ARM: at91: PM: add cpu idle support for sama7g5

Add CPU idle support for SAMA7G5. Support will make use of PMC_CPU_RATIO
register to divide the CPU clock by 16 before switching it to idle and
use automatic self-refresh option of DDR controller.

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
Acked-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Link: https://lore.kernel.org/r/20220113144900.906370-5-claudiu.beznea@microchip.com
This commit is contained in:
Claudiu Beznea 2022-01-13 16:48:54 +02:00 committed by Nicolas Ferre
parent 9a0775c9cd
commit 9584e7263e
3 changed files with 31 additions and 1 deletions

View File

@ -605,6 +605,30 @@ static void at91sam9_sdram_standby(void)
at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
}
static void sama7g5_standby(void)
{
int pwrtmg, ratio;
pwrtmg = readl(soc_pm.data.ramc[0] + UDDRC_PWRCTL);
ratio = readl(soc_pm.data.pmc + AT91_PMC_RATIO);
/*
* Place RAM into self-refresh after a maximum idle clocks. The maximum
* idle clocks is configured by bootloader in
* UDDRC_PWRMGT.SELFREF_TO_X32.
*/
writel(pwrtmg | UDDRC_PWRCTL_SELFREF_EN,
soc_pm.data.ramc[0] + UDDRC_PWRCTL);
/* Divide CPU clock by 16. */
writel(ratio & ~AT91_PMC_RATIO_RATIO, soc_pm.data.pmc + AT91_PMC_RATIO);
cpu_do_idle();
/* Restore previous configuration. */
writel(ratio, soc_pm.data.pmc + AT91_PMC_RATIO);
writel(pwrtmg, soc_pm.data.ramc[0] + UDDRC_PWRCTL);
}
struct ramc_info {
void (*idle)(void);
unsigned int memctrl;
@ -615,6 +639,7 @@ static const struct ramc_info ramc_infos[] __initconst = {
{ .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC},
{ .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
{ .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
{ .idle = sama7g5_standby, },
};
static const struct of_device_id ramc_ids[] __initconst = {
@ -622,7 +647,7 @@ static const struct of_device_id ramc_ids[] __initconst = {
{ .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] },
{ .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
{ .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] },
{ .compatible = "microchip,sama7g5-uddrc", },
{ .compatible = "microchip,sama7g5-uddrc", .data = &ramc_infos[4], },
{ /*sentinel*/ }
};

View File

@ -78,6 +78,10 @@
#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */
#define AT91_CKGR_PLLAR 0x28 /* PLL A Register */
#define AT91_PMC_RATIO 0x2c /* Processor clock ratio register [SAMA7G5 only] */
#define AT91_PMC_RATIO_RATIO (0xf) /* CPU clock ratio. */
#define AT91_CKGR_PLLBR 0x2c /* PLL B Register */
#define AT91_PMC_DIV (0xff << 0) /* Divider */
#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */

View File

@ -53,6 +53,7 @@
#define UDDRC_STAT_OPMODE_MSK (0x7 << 0) /* Operating mode mask */
#define UDDRC_PWRCTL (0x30) /* UDDRC Low Power Control Register */
#define UDDRC_PWRCTL_SELFREF_EN (1 << 0) /* Automatic self-refresh */
#define UDDRC_PWRCTL_SELFREF_SW (1 << 5) /* Software self-refresh */
#define UDDRC_DFIMISC (0x1B0) /* UDDRC DFI Miscellaneous Control Register */