Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Claudiu Beznea and committed by
Nicolas Ferre
9584e726 9a0775c9

+31 -1
+26 -1
arch/arm/mach-at91/pm.c
··· 605 605 at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1); 606 606 } 607 607 608 + static void sama7g5_standby(void) 609 + { 610 + int pwrtmg, ratio; 611 + 612 + pwrtmg = readl(soc_pm.data.ramc[0] + UDDRC_PWRCTL); 613 + ratio = readl(soc_pm.data.pmc + AT91_PMC_RATIO); 614 + 615 + /* 616 + * Place RAM into self-refresh after a maximum idle clocks. The maximum 617 + * idle clocks is configured by bootloader in 618 + * UDDRC_PWRMGT.SELFREF_TO_X32. 619 + */ 620 + writel(pwrtmg | UDDRC_PWRCTL_SELFREF_EN, 621 + soc_pm.data.ramc[0] + UDDRC_PWRCTL); 622 + /* Divide CPU clock by 16. */ 623 + writel(ratio & ~AT91_PMC_RATIO_RATIO, soc_pm.data.pmc + AT91_PMC_RATIO); 624 + 625 + cpu_do_idle(); 626 + 627 + /* Restore previous configuration. */ 628 + writel(ratio, soc_pm.data.pmc + AT91_PMC_RATIO); 629 + writel(pwrtmg, soc_pm.data.ramc[0] + UDDRC_PWRCTL); 630 + } 631 + 608 632 struct ramc_info { 609 633 void (*idle)(void); 610 634 unsigned int memctrl; ··· 639 615 { .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC}, 640 616 { .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, 641 617 { .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR}, 618 + { .idle = sama7g5_standby, }, 642 619 }; 643 620 644 621 static const struct of_device_id ramc_ids[] __initconst = { ··· 647 622 { .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] }, 648 623 { .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] }, 649 624 { .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] }, 650 - { .compatible = "microchip,sama7g5-uddrc", }, 625 + { .compatible = "microchip,sama7g5-uddrc", .data = &ramc_infos[4], }, 651 626 { /*sentinel*/ } 652 627 }; 653 628
+4
include/linux/clk/at91_pmc.h
··· 78 78 #define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ 79 79 80 80 #define AT91_CKGR_PLLAR 0x28 /* PLL A Register */ 81 + 82 + #define AT91_PMC_RATIO 0x2c /* Processor clock ratio register [SAMA7G5 only] */ 83 + #define AT91_PMC_RATIO_RATIO (0xf) /* CPU clock ratio. */ 84 + 81 85 #define AT91_CKGR_PLLBR 0x2c /* PLL B Register */ 82 86 #define AT91_PMC_DIV (0xff << 0) /* Divider */ 83 87 #define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */
+1
include/soc/at91/sama7-ddr.h
··· 53 53 #define UDDRC_STAT_OPMODE_MSK (0x7 << 0) /* Operating mode mask */ 54 54 55 55 #define UDDRC_PWRCTL (0x30) /* UDDRC Low Power Control Register */ 56 + #define UDDRC_PWRCTL_SELFREF_EN (1 << 0) /* Automatic self-refresh */ 56 57 #define UDDRC_PWRCTL_SELFREF_SW (1 << 5) /* Software self-refresh */ 57 58 58 59 #define UDDRC_DFIMISC (0x1B0) /* UDDRC DFI Miscellaneous Control Register */