Commit 9584e726 authored by Claudiu Beznea's avatar Claudiu Beznea Committed by Nicolas Ferre
Browse files

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: default avatarClaudiu Beznea <claudiu.beznea@microchip.com>
Acked-by: default avatarStephen Boyd <sboyd@kernel.org>
Signed-off-by: default avatarNicolas Ferre <nicolas.ferre@microchip.com>
Link: https://lore.kernel.org/r/20220113144900.906370-5-claudiu.beznea@microchip.com
parent 9a0775c9
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -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*/ }
};

+4 −0
Original line number Diff line number Diff line
@@ -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 */
+1 −0
Original line number Diff line number Diff line
@@ -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 */