summaryrefslogtreecommitdiff
path: root/arch/arm/mach-at91
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-at91')
-rw-r--r--arch/arm/mach-at91/pm.c47
-rw-r--r--arch/arm/mach-at91/pm.h1
-rw-r--r--arch/arm/mach-at91/pm_data-offsets.c2
-rw-r--r--arch/arm/mach-at91/pm_suspend.S101
4 files changed, 128 insertions, 23 deletions
diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 05a1547642b6..3aa20038ad93 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -222,13 +222,16 @@ static const struct of_device_id sam9x60_ws_ids[] = {
{ /* sentinel */ }
};
-static const struct of_device_id sama7g5_ws_ids[] = {
+static const struct of_device_id sama7_ws_ids[] = {
+ { .compatible = "microchip,sama7d65-rtc", .data = &ws_info[1] },
{ .compatible = "microchip,sama7g5-rtc", .data = &ws_info[1] },
{ .compatible = "microchip,sama7g5-ohci", .data = &ws_info[2] },
{ .compatible = "usb-ohci", .data = &ws_info[2] },
{ .compatible = "atmel,at91sam9g45-ehci", .data = &ws_info[2] },
{ .compatible = "usb-ehci", .data = &ws_info[2] },
+ { .compatible = "microchip,sama7d65-sdhci", .data = &ws_info[3] },
{ .compatible = "microchip,sama7g5-sdhci", .data = &ws_info[3] },
+ { .compatible = "microchip,sama7d65-rtt", .data = &ws_info[4] },
{ .compatible = "microchip,sama7g5-rtt", .data = &ws_info[4] },
{ /* sentinel */ }
};
@@ -545,11 +548,12 @@ extern u32 at91_pm_suspend_in_sram_sz;
static int at91_suspend_finish(unsigned long val)
{
- unsigned char modified_gray_code[] = {
- 0x00, 0x01, 0x02, 0x03, 0x06, 0x07, 0x04, 0x05, 0x0c, 0x0d,
- 0x0e, 0x0f, 0x0a, 0x0b, 0x08, 0x09, 0x18, 0x19, 0x1a, 0x1b,
- 0x1e, 0x1f, 0x1c, 0x1d, 0x14, 0x15, 0x16, 0x17, 0x12, 0x13,
- 0x10, 0x11,
+ /* SYNOPSYS workaround to fix a bug in the calibration logic */
+ unsigned char modified_fix_code[] = {
+ 0x00, 0x01, 0x01, 0x06, 0x07, 0x0c, 0x06, 0x07, 0x0b, 0x18,
+ 0x0a, 0x0b, 0x0c, 0x0d, 0x0d, 0x0a, 0x13, 0x13, 0x12, 0x13,
+ 0x14, 0x15, 0x15, 0x12, 0x18, 0x19, 0x19, 0x1e, 0x1f, 0x14,
+ 0x1e, 0x1f,
};
unsigned int tmp, index;
int i;
@@ -560,25 +564,25 @@ static int at91_suspend_finish(unsigned long val)
* restore the ZQ0SR0 with the value saved here. But the
* calibration is buggy and restoring some values from ZQ0SR0
* is forbidden and risky thus we need to provide processed
- * values for these (modified gray code values).
+ * values for these.
*/
tmp = readl(soc_pm.data.ramc_phy + DDR3PHY_ZQ0SR0);
/* Store pull-down output impedance select. */
index = (tmp >> DDR3PHY_ZQ0SR0_PDO_OFF) & 0x1f;
- soc_pm.bu->ddr_phy_calibration[0] = modified_gray_code[index];
+ soc_pm.bu->ddr_phy_calibration[0] = modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDO_OFF;
/* Store pull-up output impedance select. */
index = (tmp >> DDR3PHY_ZQ0SR0_PUO_OFF) & 0x1f;
- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
+ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PUO_OFF;
/* Store pull-down on-die termination impedance select. */
index = (tmp >> DDR3PHY_ZQ0SR0_PDODT_OFF) & 0x1f;
- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
+ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SR0_PDODT_OFF;
/* Store pull-up on-die termination impedance select. */
index = (tmp >> DDR3PHY_ZQ0SRO_PUODT_OFF) & 0x1f;
- soc_pm.bu->ddr_phy_calibration[0] |= modified_gray_code[index];
+ soc_pm.bu->ddr_phy_calibration[0] |= modified_fix_code[index] << DDR3PHY_ZQ0SRO_PUODT_OFF;
/*
* The 1st 8 words of memory might get corrupted in the process
@@ -643,6 +647,11 @@ static void at91_pm_suspend(suspend_state_t state)
at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
&at91_pm_suspend_in_sram,
at91_pm_suspend_in_sram_sz);
+
+ if (IS_ENABLED(CONFIG_SOC_SAMA7D65)) {
+ /* SHDWC.SR */
+ readl(soc_pm.data.shdwc + 0x08);
+ }
} else {
at91_suspend_finish(0);
}
@@ -1061,7 +1070,8 @@ static int __init at91_pm_backup_init(void)
int ret = -ENODEV, located = 0;
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2) &&
- !IS_ENABLED(CONFIG_SOC_SAMA7G5))
+ !IS_ENABLED(CONFIG_SOC_SAMA7G5) &&
+ !IS_ENABLED(CONFIG_SOC_SAMA7D65))
return -EPERM;
if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
@@ -1329,6 +1339,7 @@ struct pmc_info {
unsigned long uhp_udp_mask;
unsigned long mckr;
unsigned long version;
+ unsigned long mcks;
};
static const struct pmc_info pmc_infos[] __initconst = {
@@ -1360,8 +1371,14 @@ static const struct pmc_info pmc_infos[] __initconst = {
{
.mckr = 0x28,
.version = AT91_PMC_V2,
+ .mcks = 4,
+ },
+ {
+ .uhp_udp_mask = AT91SAM926x_PMC_UHP,
+ .mckr = 0x28,
+ .version = AT91_PMC_V2,
+ .mcks = 9,
},
-
};
static const struct of_device_id atmel_pmc_ids[] __initconst = {
@@ -1378,6 +1395,7 @@ static const struct of_device_id atmel_pmc_ids[] __initconst = {
{ .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
{ .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] },
{ .compatible = "microchip,sam9x7-pmc", .data = &pmc_infos[4] },
+ { .compatible = "microchip,sama7d65-pmc", .data = &pmc_infos[6] },
{ .compatible = "microchip,sama7g5-pmc", .data = &pmc_infos[5] },
{ /* sentinel */ },
};
@@ -1448,6 +1466,7 @@ static void __init at91_pm_init(void (*pm_idle)(void))
soc_pm.data.uhp_udp_mask = pmc->uhp_udp_mask;
soc_pm.data.pmc_mckr_offset = pmc->mckr;
soc_pm.data.pmc_version = pmc->version;
+ soc_pm.data.pmc_mcks = pmc->mcks;
if (pm_idle)
arm_pm_idle = pm_idle;
@@ -1671,7 +1690,7 @@ void __init sama7_pm_init(void)
at91_pm_modes_init(iomaps, ARRAY_SIZE(iomaps));
at91_pm_init(NULL);
- soc_pm.ws_ids = sama7g5_ws_ids;
+ soc_pm.ws_ids = sama7_ws_ids;
soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
soc_pm.sfrbu_regs.pswbu.key = (0x4BD20C << 8);
diff --git a/arch/arm/mach-at91/pm.h b/arch/arm/mach-at91/pm.h
index 53bdc9000e44..50c3a425d140 100644
--- a/arch/arm/mach-at91/pm.h
+++ b/arch/arm/mach-at91/pm.h
@@ -39,6 +39,7 @@ struct at91_pm_data {
unsigned int suspend_mode;
unsigned int pmc_mckr_offset;
unsigned int pmc_version;
+ unsigned int pmc_mcks;
};
#endif
diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c
index 40bd4e8fe40a..0ca5da66dc26 100644
--- a/arch/arm/mach-at91/pm_data-offsets.c
+++ b/arch/arm/mach-at91/pm_data-offsets.c
@@ -18,6 +18,8 @@ int main(void)
pmc_mckr_offset));
DEFINE(PM_DATA_PMC_VERSION, offsetof(struct at91_pm_data,
pmc_version));
+ DEFINE(PM_DATA_PMC_MCKS, offsetof(struct at91_pm_data,
+ pmc_mcks));
return 0;
}
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index e5869cca5e79..e23b86834096 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -814,18 +814,20 @@ sr_dis_exit:
.endm
/**
- * at91_mckx_ps_enable: save MCK1..4 settings and switch it to main clock
+ * at91_mckx_ps_enable: save MCK settings and switch it to main clock
*
- * Side effects: overwrites tmp1, tmp2
+ * Side effects: overwrites tmp1, tmp2, tmp3
*/
.macro at91_mckx_ps_enable
#ifdef CONFIG_SOC_SAMA7
ldr pmc, .pmc_base
+ ldr tmp3, .mcks
- /* There are 4 MCKs we need to handle: MCK1..4 */
+ /* Start at MCK1 and go until MCKs */
mov tmp1, #1
-e_loop: cmp tmp1, #5
- beq e_done
+e_loop:
+ cmp tmp1, tmp3
+ bgt e_done
/* Write MCK ID to retrieve the settings. */
str tmp1, [pmc, #AT91_PMC_MCR_V2]
@@ -850,7 +852,37 @@ e_save_mck3:
b e_ps
e_save_mck4:
+ cmp tmp1, #4
+ bne e_save_mck5
str tmp2, .saved_mck4
+ b e_ps
+
+e_save_mck5:
+ cmp tmp1, #5
+ bne e_save_mck6
+ str tmp2, .saved_mck5
+ b e_ps
+
+e_save_mck6:
+ cmp tmp1, #6
+ bne e_save_mck7
+ str tmp2, .saved_mck6
+ b e_ps
+
+e_save_mck7:
+ cmp tmp1, #7
+ bne e_save_mck8
+ str tmp2, .saved_mck7
+ b e_ps
+
+e_save_mck8:
+ cmp tmp1, #8
+ bne e_save_mck9
+ str tmp2, .saved_mck8
+ b e_ps
+
+e_save_mck9:
+ str tmp2, .saved_mck9
e_ps:
/* Use CSS=MAINCK and DIV=1. */
@@ -870,18 +902,20 @@ e_done:
.endm
/**
- * at91_mckx_ps_restore: restore MCK1..4 settings
+ * at91_mckx_ps_restore: restore MCKx settings
*
* Side effects: overwrites tmp1, tmp2
*/
.macro at91_mckx_ps_restore
#ifdef CONFIG_SOC_SAMA7
ldr pmc, .pmc_base
+ ldr tmp2, .mcks
- /* There are 4 MCKs we need to handle: MCK1..4 */
+ /* Start from MCK1 and go up to MCKs */
mov tmp1, #1
-r_loop: cmp tmp1, #5
- beq r_done
+r_loop:
+ cmp tmp1, tmp2
+ bgt r_done
r_save_mck1:
cmp tmp1, #1
@@ -902,7 +936,37 @@ r_save_mck3:
b r_ps
r_save_mck4:
+ cmp tmp1, #4
+ bne r_save_mck5
ldr tmp2, .saved_mck4
+ b r_ps
+
+r_save_mck5:
+ cmp tmp1, #5
+ bne r_save_mck6
+ ldr tmp2, .saved_mck5
+ b r_ps
+
+r_save_mck6:
+ cmp tmp1, #6
+ bne r_save_mck7
+ ldr tmp2, .saved_mck6
+ b r_ps
+
+r_save_mck7:
+ cmp tmp1, #7
+ bne r_save_mck8
+ ldr tmp2, .saved_mck7
+ b r_ps
+
+r_save_mck8:
+ cmp tmp1, #8
+ bne r_save_mck9
+ ldr tmp2, .saved_mck8
+ b r_ps
+
+r_save_mck9:
+ ldr tmp2, .saved_mck9
r_ps:
/* Write MCK ID to retrieve the settings. */
@@ -921,6 +985,7 @@ r_ps:
wait_mckrdy tmp1
add tmp1, tmp1, #1
+ ldr tmp2, .mcks
b r_loop
r_done:
#endif
@@ -1045,6 +1110,10 @@ ENTRY(at91_pm_suspend_in_sram)
str tmp1, .memtype
ldr tmp1, [r0, #PM_DATA_MODE]
str tmp1, .pm_mode
+#ifdef CONFIG_SOC_SAMA7
+ ldr tmp1, [r0, #PM_DATA_PMC_MCKS]
+ str tmp1, .mcks
+#endif
/*
* ldrne below are here to preload their address in the TLB as access
@@ -1132,6 +1201,10 @@ ENDPROC(at91_pm_suspend_in_sram)
.word 0
.pmc_version:
.word 0
+#ifdef CONFIG_SOC_SAMA7
+.mcks:
+ .word 0
+#endif
.saved_mckr:
.word 0
.saved_pllar:
@@ -1155,6 +1228,16 @@ ENDPROC(at91_pm_suspend_in_sram)
.word 0
.saved_mck4:
.word 0
+.saved_mck5:
+ .word 0
+.saved_mck6:
+ .word 0
+.saved_mck7:
+ .word 0
+.saved_mck8:
+ .word 0
+.saved_mck9:
+ .word 0
#endif
ENTRY(at91_pm_suspend_in_sram_sz)