Skip to content

Commit bc4722c

Browse files
LiBinSHAclaudiubeznea
authored andcommitted
ARM: at91: pm: fix at91_suspend_finish for ZQ calibration
For sama7g5 and sama7d65 backup mode, we encountered a "ZQ calibrate error" during recalibrating the impedance in BootStrap. We found that the impedance value saved in at91_suspend_finish() before the DDR entered self-refresh mode did not match the resistor values. The ZDATA field in the DDR3PHY_ZQ0CR0 register uses a modified gray code to select the different impedance setting. But these gray code are incorrect, a workaournd from design team fixed the bug in the calibration logic. The ZDATA contains four independent impedance elements, but the algorithm combined the four elements into one. The elements were fixed using properly shifted offsets. Signed-off-by: Li Bin <bin.li@microchip.com> [nicolas.ferre@microchip.com: fix indentation and combine 2 patches] Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com> Tested-by: Ryan Wanner <Ryan.Wanner@microchip.com> Tested-by: Durai Manickam KR <durai.manickamkr@microchip.com> Tested-by: Andrei Simion <andrei.simion@microchip.com> Signed-off-by: Ryan Wanner <Ryan.Wanner@microchip.com> Link: https://lore.kernel.org/r/28b33f9bcd0ca60ceba032969fe054d38f2b9577.1740671156.git.Ryan.Wanner@microchip.com Signed-off-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
1 parent ebbb396 commit bc4722c

1 file changed

Lines changed: 11 additions & 10 deletions

File tree

  • arch/arm/mach-at91

arch/arm/mach-at91/pm.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -545,11 +545,12 @@ extern u32 at91_pm_suspend_in_sram_sz;
545545

546546
static int at91_suspend_finish(unsigned long val)
547547
{
548-
unsigned char modified_gray_code[] = {
549-
0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, 0x0c, 0x0d,
550-
0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09, 0x18, 0x19, 0x1a, 0x1b,
551-
0x1e, 0x1f, 0x1c, 0x1d, 0x14, 0x15, 0x16, 0x17, 0x12, 0x13,
552-
0x10, 0x11,
548+
/* SYNOPSYS workaround to fix a bug in the calibration logic */
549+
unsigned char modified_fix_code[] = {
550+
0x00, 0x01, 0x01, 0x06, 0x07, 0x0c, 0x06, 0x07, 0x0b, 0x18,
551+
0x0a, 0x0b, 0x0c, 0x0d, 0x0d, 0x0a, 0x13, 0x13, 0x12, 0x13,
552+
0x14, 0x15, 0x15, 0x12, 0x18, 0x19, 0x19, 0x1e, 0x1f, 0x14,
553+
0x1e, 0x1f,
553554
};
554555
unsigned int tmp, index;
555556
int i;
@@ -560,25 +561,25 @@ static int at91_suspend_finish(unsigned long val)
560561
* restore the ZQ0SR0 with the value saved here. But the
561562
* calibration is buggy and restoring some values from ZQ0SR0
562563
* is forbidden and risky thus we need to provide processed
563-
* values for these (modified gray code values).
564+
* values for these.
564565
*/
565566
tmp = readl(soc_pm.data.ramc_phy + DDR3PHY_ZQ0SR0);
566567

567568
/* Store pull-down output impedance select. */
568569
index = (tmp >> DDR3PHY_ZQ0SR0_PDO_OFF) & 0x1f;
569-
soc_pm.bu->ddr_phy_calibration[0] = modified_gray_code[index];
570+
soc_pm.bu->ddr_phy_calibration[0] = modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDO_OFF;
570571

571572
/* Store pull-up output impedance select. */
572573
index = (tmp >> DDR3PHY_ZQ0SR0_PUO_OFF) & 0x1f;
573-
soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
574+
soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PUO_OFF;
574575

575576
/* Store pull-down on-die termination impedance select. */
576577
index = (tmp >> DDR3PHY_ZQ0SR0_PDODT_OFF) & 0x1f;
577-
soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
578+
soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDODT_OFF;
578579

579580
/* Store pull-up on-die termination impedance select. */
580581
index = (tmp >> DDR3PHY_ZQ0SRO_PUODT_OFF) & 0x1f;
581-
soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
582+
soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SRO_PUODT_OFF;
582583

583584
/*
584585
* The 1st 8 words of memory might get corrupted in the process

0 commit comments

Comments
 (0)