xref: /OK3568_Linux_fs/kernel/arch/arm/mach-at91/pm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * arch/arm/mach-at91/pm.c
4*4882a593Smuzhiyun  * AT91 Power Management
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 2005 David Brownell
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/genalloc.h>
10*4882a593Smuzhiyun #include <linux/io.h>
11*4882a593Smuzhiyun #include <linux/of_address.h>
12*4882a593Smuzhiyun #include <linux/of.h>
13*4882a593Smuzhiyun #include <linux/of_platform.h>
14*4882a593Smuzhiyun #include <linux/parser.h>
15*4882a593Smuzhiyun #include <linux/suspend.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <linux/clk/at91_pmc.h>
18*4882a593Smuzhiyun #include <linux/platform_data/atmel.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include <asm/cacheflush.h>
21*4882a593Smuzhiyun #include <asm/fncpy.h>
22*4882a593Smuzhiyun #include <asm/system_misc.h>
23*4882a593Smuzhiyun #include <asm/suspend.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #include "generic.h"
26*4882a593Smuzhiyun #include "pm.h"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun /*
29*4882a593Smuzhiyun  * FIXME: this is needed to communicate between the pinctrl driver and
30*4882a593Smuzhiyun  * the PM implementation in the machine. Possibly part of the PM
31*4882a593Smuzhiyun  * implementation should be moved down into the pinctrl driver and get
32*4882a593Smuzhiyun  * called as part of the generic suspend/resume path.
33*4882a593Smuzhiyun  */
34*4882a593Smuzhiyun #ifdef CONFIG_PINCTRL_AT91
35*4882a593Smuzhiyun extern void at91_pinctrl_gpio_suspend(void);
36*4882a593Smuzhiyun extern void at91_pinctrl_gpio_resume(void);
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun struct at91_soc_pm {
40*4882a593Smuzhiyun 	int (*config_shdwc_ws)(void __iomem *shdwc, u32 *mode, u32 *polarity);
41*4882a593Smuzhiyun 	int (*config_pmc_ws)(void __iomem *pmc, u32 mode, u32 polarity);
42*4882a593Smuzhiyun 	const struct of_device_id *ws_ids;
43*4882a593Smuzhiyun 	struct at91_pm_data data;
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun static struct at91_soc_pm soc_pm = {
47*4882a593Smuzhiyun 	.data = {
48*4882a593Smuzhiyun 		.standby_mode = AT91_PM_STANDBY,
49*4882a593Smuzhiyun 		.suspend_mode = AT91_PM_ULP0,
50*4882a593Smuzhiyun 	},
51*4882a593Smuzhiyun };
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun static const match_table_t pm_modes __initconst = {
54*4882a593Smuzhiyun 	{ AT91_PM_STANDBY,	"standby" },
55*4882a593Smuzhiyun 	{ AT91_PM_ULP0,		"ulp0" },
56*4882a593Smuzhiyun 	{ AT91_PM_ULP0_FAST,    "ulp0-fast" },
57*4882a593Smuzhiyun 	{ AT91_PM_ULP1,		"ulp1" },
58*4882a593Smuzhiyun 	{ AT91_PM_BACKUP,	"backup" },
59*4882a593Smuzhiyun 	{ -1, NULL },
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #define at91_ramc_read(id, field) \
63*4882a593Smuzhiyun 	__raw_readl(soc_pm.data.ramc[id] + field)
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun #define at91_ramc_write(id, field, value) \
66*4882a593Smuzhiyun 	__raw_writel(value, soc_pm.data.ramc[id] + field)
67*4882a593Smuzhiyun 
at91_pm_valid_state(suspend_state_t state)68*4882a593Smuzhiyun static int at91_pm_valid_state(suspend_state_t state)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	switch (state) {
71*4882a593Smuzhiyun 		case PM_SUSPEND_ON:
72*4882a593Smuzhiyun 		case PM_SUSPEND_STANDBY:
73*4882a593Smuzhiyun 		case PM_SUSPEND_MEM:
74*4882a593Smuzhiyun 			return 1;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 		default:
77*4882a593Smuzhiyun 			return 0;
78*4882a593Smuzhiyun 	}
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun static int canary = 0xA5A5A5A5;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun static struct at91_pm_bu {
84*4882a593Smuzhiyun 	int suspended;
85*4882a593Smuzhiyun 	unsigned long reserved;
86*4882a593Smuzhiyun 	phys_addr_t canary;
87*4882a593Smuzhiyun 	phys_addr_t resume;
88*4882a593Smuzhiyun } *pm_bu;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun struct wakeup_source_info {
91*4882a593Smuzhiyun 	unsigned int pmc_fsmr_bit;
92*4882a593Smuzhiyun 	unsigned int shdwc_mr_bit;
93*4882a593Smuzhiyun 	bool set_polarity;
94*4882a593Smuzhiyun };
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun static const struct wakeup_source_info ws_info[] = {
97*4882a593Smuzhiyun 	{ .pmc_fsmr_bit = AT91_PMC_FSTT(10),	.set_polarity = true },
98*4882a593Smuzhiyun 	{ .pmc_fsmr_bit = AT91_PMC_RTCAL,	.shdwc_mr_bit = BIT(17) },
99*4882a593Smuzhiyun 	{ .pmc_fsmr_bit = AT91_PMC_USBAL },
100*4882a593Smuzhiyun 	{ .pmc_fsmr_bit = AT91_PMC_SDMMC_CD },
101*4882a593Smuzhiyun 	{ .pmc_fsmr_bit = AT91_PMC_RTTAL },
102*4882a593Smuzhiyun 	{ .pmc_fsmr_bit = AT91_PMC_RXLP_MCE },
103*4882a593Smuzhiyun };
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun static const struct of_device_id sama5d2_ws_ids[] = {
106*4882a593Smuzhiyun 	{ .compatible = "atmel,sama5d2-gem",		.data = &ws_info[0] },
107*4882a593Smuzhiyun 	{ .compatible = "atmel,sama5d2-rtc",		.data = &ws_info[1] },
108*4882a593Smuzhiyun 	{ .compatible = "atmel,sama5d3-udc",		.data = &ws_info[2] },
109*4882a593Smuzhiyun 	{ .compatible = "atmel,at91rm9200-ohci",	.data = &ws_info[2] },
110*4882a593Smuzhiyun 	{ .compatible = "usb-ohci",			.data = &ws_info[2] },
111*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9g45-ehci",	.data = &ws_info[2] },
112*4882a593Smuzhiyun 	{ .compatible = "usb-ehci",			.data = &ws_info[2] },
113*4882a593Smuzhiyun 	{ .compatible = "atmel,sama5d2-sdhci",		.data = &ws_info[3] },
114*4882a593Smuzhiyun 	{ /* sentinel */ }
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun static const struct of_device_id sam9x60_ws_ids[] = {
118*4882a593Smuzhiyun 	{ .compatible = "microchip,sam9x60-rtc",	.data = &ws_info[1] },
119*4882a593Smuzhiyun 	{ .compatible = "atmel,at91rm9200-ohci",	.data = &ws_info[2] },
120*4882a593Smuzhiyun 	{ .compatible = "usb-ohci",			.data = &ws_info[2] },
121*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9g45-ehci",	.data = &ws_info[2] },
122*4882a593Smuzhiyun 	{ .compatible = "usb-ehci",			.data = &ws_info[2] },
123*4882a593Smuzhiyun 	{ .compatible = "microchip,sam9x60-rtt",	.data = &ws_info[4] },
124*4882a593Smuzhiyun 	{ .compatible = "cdns,sam9x60-macb",		.data = &ws_info[5] },
125*4882a593Smuzhiyun 	{ /* sentinel */ }
126*4882a593Smuzhiyun };
127*4882a593Smuzhiyun 
at91_pm_config_ws(unsigned int pm_mode,bool set)128*4882a593Smuzhiyun static int at91_pm_config_ws(unsigned int pm_mode, bool set)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	const struct wakeup_source_info *wsi;
131*4882a593Smuzhiyun 	const struct of_device_id *match;
132*4882a593Smuzhiyun 	struct platform_device *pdev;
133*4882a593Smuzhiyun 	struct device_node *np;
134*4882a593Smuzhiyun 	unsigned int mode = 0, polarity = 0, val = 0;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	if (pm_mode != AT91_PM_ULP1)
137*4882a593Smuzhiyun 		return 0;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	if (!soc_pm.data.pmc || !soc_pm.data.shdwc || !soc_pm.ws_ids)
140*4882a593Smuzhiyun 		return -EPERM;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	if (!set) {
143*4882a593Smuzhiyun 		writel(mode, soc_pm.data.pmc + AT91_PMC_FSMR);
144*4882a593Smuzhiyun 		return 0;
145*4882a593Smuzhiyun 	}
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	if (soc_pm.config_shdwc_ws)
148*4882a593Smuzhiyun 		soc_pm.config_shdwc_ws(soc_pm.data.shdwc, &mode, &polarity);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	/* SHDWC.MR */
151*4882a593Smuzhiyun 	val = readl(soc_pm.data.shdwc + 0x04);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	/* Loop through defined wakeup sources. */
154*4882a593Smuzhiyun 	for_each_matching_node_and_match(np, soc_pm.ws_ids, &match) {
155*4882a593Smuzhiyun 		pdev = of_find_device_by_node(np);
156*4882a593Smuzhiyun 		if (!pdev)
157*4882a593Smuzhiyun 			continue;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun 		if (device_may_wakeup(&pdev->dev)) {
160*4882a593Smuzhiyun 			wsi = match->data;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 			/* Check if enabled on SHDWC. */
163*4882a593Smuzhiyun 			if (wsi->shdwc_mr_bit && !(val & wsi->shdwc_mr_bit))
164*4882a593Smuzhiyun 				goto put_device;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 			mode |= wsi->pmc_fsmr_bit;
167*4882a593Smuzhiyun 			if (wsi->set_polarity)
168*4882a593Smuzhiyun 				polarity |= wsi->pmc_fsmr_bit;
169*4882a593Smuzhiyun 		}
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun put_device:
172*4882a593Smuzhiyun 		put_device(&pdev->dev);
173*4882a593Smuzhiyun 	}
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	if (mode) {
176*4882a593Smuzhiyun 		if (soc_pm.config_pmc_ws)
177*4882a593Smuzhiyun 			soc_pm.config_pmc_ws(soc_pm.data.pmc, mode, polarity);
178*4882a593Smuzhiyun 	} else {
179*4882a593Smuzhiyun 		pr_err("AT91: PM: no ULP1 wakeup sources found!");
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	return mode ? 0 : -EPERM;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
at91_sama5d2_config_shdwc_ws(void __iomem * shdwc,u32 * mode,u32 * polarity)185*4882a593Smuzhiyun static int at91_sama5d2_config_shdwc_ws(void __iomem *shdwc, u32 *mode,
186*4882a593Smuzhiyun 					u32 *polarity)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun 	u32 val;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	/* SHDWC.WUIR */
191*4882a593Smuzhiyun 	val = readl(shdwc + 0x0c);
192*4882a593Smuzhiyun 	*mode |= (val & 0x3ff);
193*4882a593Smuzhiyun 	*polarity |= ((val >> 16) & 0x3ff);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	return 0;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun 
at91_sama5d2_config_pmc_ws(void __iomem * pmc,u32 mode,u32 polarity)198*4882a593Smuzhiyun static int at91_sama5d2_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun 	writel(mode, pmc + AT91_PMC_FSMR);
201*4882a593Smuzhiyun 	writel(polarity, pmc + AT91_PMC_FSPR);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	return 0;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun 
at91_sam9x60_config_pmc_ws(void __iomem * pmc,u32 mode,u32 polarity)206*4882a593Smuzhiyun static int at91_sam9x60_config_pmc_ws(void __iomem *pmc, u32 mode, u32 polarity)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	writel(mode, pmc + AT91_PMC_FSMR);
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	return 0;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun /*
214*4882a593Smuzhiyun  * Called after processes are frozen, but before we shutdown devices.
215*4882a593Smuzhiyun  */
at91_pm_begin(suspend_state_t state)216*4882a593Smuzhiyun static int at91_pm_begin(suspend_state_t state)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	switch (state) {
219*4882a593Smuzhiyun 	case PM_SUSPEND_MEM:
220*4882a593Smuzhiyun 		soc_pm.data.mode = soc_pm.data.suspend_mode;
221*4882a593Smuzhiyun 		break;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	case PM_SUSPEND_STANDBY:
224*4882a593Smuzhiyun 		soc_pm.data.mode = soc_pm.data.standby_mode;
225*4882a593Smuzhiyun 		break;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	default:
228*4882a593Smuzhiyun 		soc_pm.data.mode = -1;
229*4882a593Smuzhiyun 	}
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	return at91_pm_config_ws(soc_pm.data.mode, true);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun /*
235*4882a593Smuzhiyun  * Verify that all the clocks are correct before entering
236*4882a593Smuzhiyun  * slow-clock mode.
237*4882a593Smuzhiyun  */
at91_pm_verify_clocks(void)238*4882a593Smuzhiyun static int at91_pm_verify_clocks(void)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	unsigned long scsr;
241*4882a593Smuzhiyun 	int i;
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	scsr = readl(soc_pm.data.pmc + AT91_PMC_SCSR);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	/* USB must not be using PLLB */
246*4882a593Smuzhiyun 	if ((scsr & soc_pm.data.uhp_udp_mask) != 0) {
247*4882a593Smuzhiyun 		pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
248*4882a593Smuzhiyun 		return 0;
249*4882a593Smuzhiyun 	}
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	/* PCK0..PCK3 must be disabled, or configured to use clk32k */
252*4882a593Smuzhiyun 	for (i = 0; i < 4; i++) {
253*4882a593Smuzhiyun 		u32 css;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
256*4882a593Smuzhiyun 			continue;
257*4882a593Smuzhiyun 		css = readl(soc_pm.data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
258*4882a593Smuzhiyun 		if (css != AT91_PMC_CSS_SLOW) {
259*4882a593Smuzhiyun 			pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
260*4882a593Smuzhiyun 			return 0;
261*4882a593Smuzhiyun 		}
262*4882a593Smuzhiyun 	}
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	return 1;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun /*
268*4882a593Smuzhiyun  * Call this from platform driver suspend() to see how deeply to suspend.
269*4882a593Smuzhiyun  * For example, some controllers (like OHCI) need one of the PLL clocks
270*4882a593Smuzhiyun  * in order to act as a wakeup source, and those are not available when
271*4882a593Smuzhiyun  * going into slow clock mode.
272*4882a593Smuzhiyun  *
273*4882a593Smuzhiyun  * REVISIT: generalize as clk_will_be_available(clk)?  Other platforms have
274*4882a593Smuzhiyun  * the very same problem (but not using at91 main_clk), and it'd be better
275*4882a593Smuzhiyun  * to add one generic API rather than lots of platform-specific ones.
276*4882a593Smuzhiyun  */
at91_suspend_entering_slow_clock(void)277*4882a593Smuzhiyun int at91_suspend_entering_slow_clock(void)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	return (soc_pm.data.mode >= AT91_PM_ULP0);
280*4882a593Smuzhiyun }
281*4882a593Smuzhiyun EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun static void (*at91_suspend_sram_fn)(struct at91_pm_data *);
284*4882a593Smuzhiyun extern void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data);
285*4882a593Smuzhiyun extern u32 at91_pm_suspend_in_sram_sz;
286*4882a593Smuzhiyun 
at91_suspend_finish(unsigned long val)287*4882a593Smuzhiyun static int at91_suspend_finish(unsigned long val)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun 	flush_cache_all();
290*4882a593Smuzhiyun 	outer_disable();
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	at91_suspend_sram_fn(&soc_pm.data);
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	return 0;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
at91_pm_suspend(suspend_state_t state)297*4882a593Smuzhiyun static void at91_pm_suspend(suspend_state_t state)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	if (soc_pm.data.mode == AT91_PM_BACKUP) {
300*4882a593Smuzhiyun 		pm_bu->suspended = 1;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 		cpu_suspend(0, at91_suspend_finish);
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 		/* The SRAM is lost between suspend cycles */
305*4882a593Smuzhiyun 		at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
306*4882a593Smuzhiyun 					     &at91_pm_suspend_in_sram,
307*4882a593Smuzhiyun 					     at91_pm_suspend_in_sram_sz);
308*4882a593Smuzhiyun 	} else {
309*4882a593Smuzhiyun 		at91_suspend_finish(0);
310*4882a593Smuzhiyun 	}
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	outer_resume();
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun /*
316*4882a593Smuzhiyun  * STANDBY mode has *all* drivers suspended; ignores irqs not marked as 'wakeup'
317*4882a593Smuzhiyun  * event sources; and reduces DRAM power.  But otherwise it's identical to
318*4882a593Smuzhiyun  * PM_SUSPEND_ON: cpu idle, and nothing fancy done with main or cpu clocks.
319*4882a593Smuzhiyun  *
320*4882a593Smuzhiyun  * AT91_PM_ULP0 is like STANDBY plus slow clock mode, so drivers must
321*4882a593Smuzhiyun  * suspend more deeply, the master clock switches to the clk32k and turns off
322*4882a593Smuzhiyun  * the main oscillator
323*4882a593Smuzhiyun  *
324*4882a593Smuzhiyun  * AT91_PM_BACKUP turns off the whole SoC after placing the DDR in self refresh
325*4882a593Smuzhiyun  */
at91_pm_enter(suspend_state_t state)326*4882a593Smuzhiyun static int at91_pm_enter(suspend_state_t state)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun #ifdef CONFIG_PINCTRL_AT91
329*4882a593Smuzhiyun 	at91_pinctrl_gpio_suspend();
330*4882a593Smuzhiyun #endif
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	switch (state) {
333*4882a593Smuzhiyun 	case PM_SUSPEND_MEM:
334*4882a593Smuzhiyun 	case PM_SUSPEND_STANDBY:
335*4882a593Smuzhiyun 		/*
336*4882a593Smuzhiyun 		 * Ensure that clocks are in a valid state.
337*4882a593Smuzhiyun 		 */
338*4882a593Smuzhiyun 		if (soc_pm.data.mode >= AT91_PM_ULP0 &&
339*4882a593Smuzhiyun 		    !at91_pm_verify_clocks())
340*4882a593Smuzhiyun 			goto error;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 		at91_pm_suspend(state);
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 		break;
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	case PM_SUSPEND_ON:
347*4882a593Smuzhiyun 		cpu_do_idle();
348*4882a593Smuzhiyun 		break;
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun 	default:
351*4882a593Smuzhiyun 		pr_debug("AT91: PM - bogus suspend state %d\n", state);
352*4882a593Smuzhiyun 		goto error;
353*4882a593Smuzhiyun 	}
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun error:
356*4882a593Smuzhiyun #ifdef CONFIG_PINCTRL_AT91
357*4882a593Smuzhiyun 	at91_pinctrl_gpio_resume();
358*4882a593Smuzhiyun #endif
359*4882a593Smuzhiyun 	return 0;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun /*
363*4882a593Smuzhiyun  * Called right prior to thawing processes.
364*4882a593Smuzhiyun  */
at91_pm_end(void)365*4882a593Smuzhiyun static void at91_pm_end(void)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun 	at91_pm_config_ws(soc_pm.data.mode, false);
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun static const struct platform_suspend_ops at91_pm_ops = {
372*4882a593Smuzhiyun 	.valid	= at91_pm_valid_state,
373*4882a593Smuzhiyun 	.begin	= at91_pm_begin,
374*4882a593Smuzhiyun 	.enter	= at91_pm_enter,
375*4882a593Smuzhiyun 	.end	= at91_pm_end,
376*4882a593Smuzhiyun };
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun static struct platform_device at91_cpuidle_device = {
379*4882a593Smuzhiyun 	.name = "cpuidle-at91",
380*4882a593Smuzhiyun };
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun /*
383*4882a593Smuzhiyun  * The AT91RM9200 goes into self-refresh mode with this command, and will
384*4882a593Smuzhiyun  * terminate self-refresh automatically on the next SDRAM access.
385*4882a593Smuzhiyun  *
386*4882a593Smuzhiyun  * Self-refresh mode is exited as soon as a memory access is made, but we don't
387*4882a593Smuzhiyun  * know for sure when that happens. However, we need to restore the low-power
388*4882a593Smuzhiyun  * mode if it was enabled before going idle. Restoring low-power mode while
389*4882a593Smuzhiyun  * still in self-refresh is "not recommended", but seems to work.
390*4882a593Smuzhiyun  */
at91rm9200_standby(void)391*4882a593Smuzhiyun static void at91rm9200_standby(void)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun 	asm volatile(
394*4882a593Smuzhiyun 		"b    1f\n\t"
395*4882a593Smuzhiyun 		".align    5\n\t"
396*4882a593Smuzhiyun 		"1:  mcr    p15, 0, %0, c7, c10, 4\n\t"
397*4882a593Smuzhiyun 		"    str    %2, [%1, %3]\n\t"
398*4882a593Smuzhiyun 		"    mcr    p15, 0, %0, c7, c0, 4\n\t"
399*4882a593Smuzhiyun 		:
400*4882a593Smuzhiyun 		: "r" (0), "r" (soc_pm.data.ramc[0]),
401*4882a593Smuzhiyun 		  "r" (1), "r" (AT91_MC_SDRAMC_SRR));
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun /* We manage both DDRAM/SDRAM controllers, we need more than one value to
405*4882a593Smuzhiyun  * remember.
406*4882a593Smuzhiyun  */
at91_ddr_standby(void)407*4882a593Smuzhiyun static void at91_ddr_standby(void)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	/* Those two values allow us to delay self-refresh activation
410*4882a593Smuzhiyun 	 * to the maximum. */
411*4882a593Smuzhiyun 	u32 lpr0, lpr1 = 0;
412*4882a593Smuzhiyun 	u32 mdr, saved_mdr0, saved_mdr1 = 0;
413*4882a593Smuzhiyun 	u32 saved_lpr0, saved_lpr1 = 0;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	/* LPDDR1 --> force DDR2 mode during self-refresh */
416*4882a593Smuzhiyun 	saved_mdr0 = at91_ramc_read(0, AT91_DDRSDRC_MDR);
417*4882a593Smuzhiyun 	if ((saved_mdr0 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
418*4882a593Smuzhiyun 		mdr = saved_mdr0 & ~AT91_DDRSDRC_MD;
419*4882a593Smuzhiyun 		mdr |= AT91_DDRSDRC_MD_DDR2;
420*4882a593Smuzhiyun 		at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr);
421*4882a593Smuzhiyun 	}
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	if (soc_pm.data.ramc[1]) {
424*4882a593Smuzhiyun 		saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
425*4882a593Smuzhiyun 		lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
426*4882a593Smuzhiyun 		lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
427*4882a593Smuzhiyun 		saved_mdr1 = at91_ramc_read(1, AT91_DDRSDRC_MDR);
428*4882a593Smuzhiyun 		if ((saved_mdr1 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
429*4882a593Smuzhiyun 			mdr = saved_mdr1 & ~AT91_DDRSDRC_MD;
430*4882a593Smuzhiyun 			mdr |= AT91_DDRSDRC_MD_DDR2;
431*4882a593Smuzhiyun 			at91_ramc_write(1, AT91_DDRSDRC_MDR, mdr);
432*4882a593Smuzhiyun 		}
433*4882a593Smuzhiyun 	}
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
436*4882a593Smuzhiyun 	lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
437*4882a593Smuzhiyun 	lpr0 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	/* self-refresh mode now */
440*4882a593Smuzhiyun 	at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
441*4882a593Smuzhiyun 	if (soc_pm.data.ramc[1])
442*4882a593Smuzhiyun 		at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	cpu_do_idle();
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0);
447*4882a593Smuzhiyun 	at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
448*4882a593Smuzhiyun 	if (soc_pm.data.ramc[1]) {
449*4882a593Smuzhiyun 		at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1);
450*4882a593Smuzhiyun 		at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
451*4882a593Smuzhiyun 	}
452*4882a593Smuzhiyun }
453*4882a593Smuzhiyun 
sama5d3_ddr_standby(void)454*4882a593Smuzhiyun static void sama5d3_ddr_standby(void)
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	u32 lpr0;
457*4882a593Smuzhiyun 	u32 saved_lpr0;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
460*4882a593Smuzhiyun 	lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
461*4882a593Smuzhiyun 	lpr0 |= AT91_DDRSDRC_LPCB_POWER_DOWN;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	cpu_do_idle();
466*4882a593Smuzhiyun 
467*4882a593Smuzhiyun 	at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun /* We manage both DDRAM/SDRAM controllers, we need more than one value to
471*4882a593Smuzhiyun  * remember.
472*4882a593Smuzhiyun  */
at91sam9_sdram_standby(void)473*4882a593Smuzhiyun static void at91sam9_sdram_standby(void)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun 	u32 lpr0, lpr1 = 0;
476*4882a593Smuzhiyun 	u32 saved_lpr0, saved_lpr1 = 0;
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	if (soc_pm.data.ramc[1]) {
479*4882a593Smuzhiyun 		saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
480*4882a593Smuzhiyun 		lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
481*4882a593Smuzhiyun 		lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
482*4882a593Smuzhiyun 	}
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	saved_lpr0 = at91_ramc_read(0, AT91_SDRAMC_LPR);
485*4882a593Smuzhiyun 	lpr0 = saved_lpr0 & ~AT91_SDRAMC_LPCB;
486*4882a593Smuzhiyun 	lpr0 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	/* self-refresh mode now */
489*4882a593Smuzhiyun 	at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
490*4882a593Smuzhiyun 	if (soc_pm.data.ramc[1])
491*4882a593Smuzhiyun 		at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	cpu_do_idle();
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
496*4882a593Smuzhiyun 	if (soc_pm.data.ramc[1])
497*4882a593Smuzhiyun 		at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun struct ramc_info {
501*4882a593Smuzhiyun 	void (*idle)(void);
502*4882a593Smuzhiyun 	unsigned int memctrl;
503*4882a593Smuzhiyun };
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun static const struct ramc_info ramc_infos[] __initconst = {
506*4882a593Smuzhiyun 	{ .idle = at91rm9200_standby, .memctrl = AT91_MEMCTRL_MC},
507*4882a593Smuzhiyun 	{ .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC},
508*4882a593Smuzhiyun 	{ .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
509*4882a593Smuzhiyun 	{ .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
510*4882a593Smuzhiyun };
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun static const struct of_device_id ramc_ids[] __initconst = {
513*4882a593Smuzhiyun 	{ .compatible = "atmel,at91rm9200-sdramc", .data = &ramc_infos[0] },
514*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] },
515*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
516*4882a593Smuzhiyun 	{ .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] },
517*4882a593Smuzhiyun 	{ /*sentinel*/ }
518*4882a593Smuzhiyun };
519*4882a593Smuzhiyun 
at91_dt_ramc(void)520*4882a593Smuzhiyun static __init int at91_dt_ramc(void)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun 	struct device_node *np;
523*4882a593Smuzhiyun 	const struct of_device_id *of_id;
524*4882a593Smuzhiyun 	int idx = 0;
525*4882a593Smuzhiyun 	void *standby = NULL;
526*4882a593Smuzhiyun 	const struct ramc_info *ramc;
527*4882a593Smuzhiyun 	int ret;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	for_each_matching_node_and_match(np, ramc_ids, &of_id) {
530*4882a593Smuzhiyun 		soc_pm.data.ramc[idx] = of_iomap(np, 0);
531*4882a593Smuzhiyun 		if (!soc_pm.data.ramc[idx]) {
532*4882a593Smuzhiyun 			pr_err("unable to map ramc[%d] cpu registers\n", idx);
533*4882a593Smuzhiyun 			ret = -ENOMEM;
534*4882a593Smuzhiyun 			goto unmap_ramc;
535*4882a593Smuzhiyun 		}
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 		ramc = of_id->data;
538*4882a593Smuzhiyun 		if (!standby)
539*4882a593Smuzhiyun 			standby = ramc->idle;
540*4882a593Smuzhiyun 		soc_pm.data.memctrl = ramc->memctrl;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 		idx++;
543*4882a593Smuzhiyun 	}
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	if (!idx) {
546*4882a593Smuzhiyun 		pr_err("unable to find compatible ram controller node in dtb\n");
547*4882a593Smuzhiyun 		ret = -ENODEV;
548*4882a593Smuzhiyun 		goto unmap_ramc;
549*4882a593Smuzhiyun 	}
550*4882a593Smuzhiyun 
551*4882a593Smuzhiyun 	if (!standby) {
552*4882a593Smuzhiyun 		pr_warn("ramc no standby function available\n");
553*4882a593Smuzhiyun 		return 0;
554*4882a593Smuzhiyun 	}
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	at91_cpuidle_device.dev.platform_data = standby;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	return 0;
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun unmap_ramc:
561*4882a593Smuzhiyun 	while (idx)
562*4882a593Smuzhiyun 		iounmap(soc_pm.data.ramc[--idx]);
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	return ret;
565*4882a593Smuzhiyun }
566*4882a593Smuzhiyun 
at91rm9200_idle(void)567*4882a593Smuzhiyun static void at91rm9200_idle(void)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun 	/*
570*4882a593Smuzhiyun 	 * Disable the processor clock.  The processor will be automatically
571*4882a593Smuzhiyun 	 * re-enabled by an interrupt or by a reset.
572*4882a593Smuzhiyun 	 */
573*4882a593Smuzhiyun 	writel(AT91_PMC_PCK, soc_pm.data.pmc + AT91_PMC_SCDR);
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun 
at91sam9_idle(void)576*4882a593Smuzhiyun static void at91sam9_idle(void)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun 	writel(AT91_PMC_PCK, soc_pm.data.pmc + AT91_PMC_SCDR);
579*4882a593Smuzhiyun 	cpu_do_idle();
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun 
at91_pm_sram_init(void)582*4882a593Smuzhiyun static void __init at91_pm_sram_init(void)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	struct gen_pool *sram_pool;
585*4882a593Smuzhiyun 	phys_addr_t sram_pbase;
586*4882a593Smuzhiyun 	unsigned long sram_base;
587*4882a593Smuzhiyun 	struct device_node *node;
588*4882a593Smuzhiyun 	struct platform_device *pdev = NULL;
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 	for_each_compatible_node(node, NULL, "mmio-sram") {
591*4882a593Smuzhiyun 		pdev = of_find_device_by_node(node);
592*4882a593Smuzhiyun 		if (pdev) {
593*4882a593Smuzhiyun 			of_node_put(node);
594*4882a593Smuzhiyun 			break;
595*4882a593Smuzhiyun 		}
596*4882a593Smuzhiyun 	}
597*4882a593Smuzhiyun 
598*4882a593Smuzhiyun 	if (!pdev) {
599*4882a593Smuzhiyun 		pr_warn("%s: failed to find sram device!\n", __func__);
600*4882a593Smuzhiyun 		return;
601*4882a593Smuzhiyun 	}
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	sram_pool = gen_pool_get(&pdev->dev, NULL);
604*4882a593Smuzhiyun 	if (!sram_pool) {
605*4882a593Smuzhiyun 		pr_warn("%s: sram pool unavailable!\n", __func__);
606*4882a593Smuzhiyun 		goto out_put_device;
607*4882a593Smuzhiyun 	}
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	sram_base = gen_pool_alloc(sram_pool, at91_pm_suspend_in_sram_sz);
610*4882a593Smuzhiyun 	if (!sram_base) {
611*4882a593Smuzhiyun 		pr_warn("%s: unable to alloc sram!\n", __func__);
612*4882a593Smuzhiyun 		goto out_put_device;
613*4882a593Smuzhiyun 	}
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun 	sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base);
616*4882a593Smuzhiyun 	at91_suspend_sram_fn = __arm_ioremap_exec(sram_pbase,
617*4882a593Smuzhiyun 					at91_pm_suspend_in_sram_sz, false);
618*4882a593Smuzhiyun 	if (!at91_suspend_sram_fn) {
619*4882a593Smuzhiyun 		pr_warn("SRAM: Could not map\n");
620*4882a593Smuzhiyun 		goto out_put_device;
621*4882a593Smuzhiyun 	}
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	/* Copy the pm suspend handler to SRAM */
624*4882a593Smuzhiyun 	at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn,
625*4882a593Smuzhiyun 			&at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
626*4882a593Smuzhiyun 	return;
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun out_put_device:
629*4882a593Smuzhiyun 	put_device(&pdev->dev);
630*4882a593Smuzhiyun 	return;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun 
at91_is_pm_mode_active(int pm_mode)633*4882a593Smuzhiyun static bool __init at91_is_pm_mode_active(int pm_mode)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun 	return (soc_pm.data.standby_mode == pm_mode ||
636*4882a593Smuzhiyun 		soc_pm.data.suspend_mode == pm_mode);
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun 
at91_pm_backup_init(void)639*4882a593Smuzhiyun static int __init at91_pm_backup_init(void)
640*4882a593Smuzhiyun {
641*4882a593Smuzhiyun 	struct gen_pool *sram_pool;
642*4882a593Smuzhiyun 	struct device_node *np;
643*4882a593Smuzhiyun 	struct platform_device *pdev = NULL;
644*4882a593Smuzhiyun 	int ret = -ENODEV;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 	if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
647*4882a593Smuzhiyun 		return -EPERM;
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun 	if (!at91_is_pm_mode_active(AT91_PM_BACKUP))
650*4882a593Smuzhiyun 		return 0;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-sfrbu");
653*4882a593Smuzhiyun 	if (!np) {
654*4882a593Smuzhiyun 		pr_warn("%s: failed to find sfrbu!\n", __func__);
655*4882a593Smuzhiyun 		return ret;
656*4882a593Smuzhiyun 	}
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun 	soc_pm.data.sfrbu = of_iomap(np, 0);
659*4882a593Smuzhiyun 	of_node_put(np);
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun 	np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-securam");
662*4882a593Smuzhiyun 	if (!np)
663*4882a593Smuzhiyun 		goto securam_fail_no_ref_dev;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	pdev = of_find_device_by_node(np);
666*4882a593Smuzhiyun 	of_node_put(np);
667*4882a593Smuzhiyun 	if (!pdev) {
668*4882a593Smuzhiyun 		pr_warn("%s: failed to find securam device!\n", __func__);
669*4882a593Smuzhiyun 		goto securam_fail_no_ref_dev;
670*4882a593Smuzhiyun 	}
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	sram_pool = gen_pool_get(&pdev->dev, NULL);
673*4882a593Smuzhiyun 	if (!sram_pool) {
674*4882a593Smuzhiyun 		pr_warn("%s: securam pool unavailable!\n", __func__);
675*4882a593Smuzhiyun 		goto securam_fail;
676*4882a593Smuzhiyun 	}
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	pm_bu = (void *)gen_pool_alloc(sram_pool, sizeof(struct at91_pm_bu));
679*4882a593Smuzhiyun 	if (!pm_bu) {
680*4882a593Smuzhiyun 		pr_warn("%s: unable to alloc securam!\n", __func__);
681*4882a593Smuzhiyun 		ret = -ENOMEM;
682*4882a593Smuzhiyun 		goto securam_fail;
683*4882a593Smuzhiyun 	}
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	pm_bu->suspended = 0;
686*4882a593Smuzhiyun 	pm_bu->canary = __pa_symbol(&canary);
687*4882a593Smuzhiyun 	pm_bu->resume = __pa_symbol(cpu_resume);
688*4882a593Smuzhiyun 
689*4882a593Smuzhiyun 	return 0;
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun securam_fail:
692*4882a593Smuzhiyun 	put_device(&pdev->dev);
693*4882a593Smuzhiyun securam_fail_no_ref_dev:
694*4882a593Smuzhiyun 	iounmap(soc_pm.data.sfrbu);
695*4882a593Smuzhiyun 	soc_pm.data.sfrbu = NULL;
696*4882a593Smuzhiyun 	return ret;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun 
at91_pm_use_default_mode(int pm_mode)699*4882a593Smuzhiyun static void __init at91_pm_use_default_mode(int pm_mode)
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun 	if (pm_mode != AT91_PM_ULP1 && pm_mode != AT91_PM_BACKUP)
702*4882a593Smuzhiyun 		return;
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	if (soc_pm.data.standby_mode == pm_mode)
705*4882a593Smuzhiyun 		soc_pm.data.standby_mode = AT91_PM_ULP0;
706*4882a593Smuzhiyun 	if (soc_pm.data.suspend_mode == pm_mode)
707*4882a593Smuzhiyun 		soc_pm.data.suspend_mode = AT91_PM_ULP0;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun static const struct of_device_id atmel_shdwc_ids[] = {
711*4882a593Smuzhiyun 	{ .compatible = "atmel,sama5d2-shdwc" },
712*4882a593Smuzhiyun 	{ .compatible = "microchip,sam9x60-shdwc" },
713*4882a593Smuzhiyun 	{ /* sentinel. */ }
714*4882a593Smuzhiyun };
715*4882a593Smuzhiyun 
at91_pm_modes_init(void)716*4882a593Smuzhiyun static void __init at91_pm_modes_init(void)
717*4882a593Smuzhiyun {
718*4882a593Smuzhiyun 	struct device_node *np;
719*4882a593Smuzhiyun 	int ret;
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	if (!at91_is_pm_mode_active(AT91_PM_BACKUP) &&
722*4882a593Smuzhiyun 	    !at91_is_pm_mode_active(AT91_PM_ULP1))
723*4882a593Smuzhiyun 		return;
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	np = of_find_matching_node(NULL, atmel_shdwc_ids);
726*4882a593Smuzhiyun 	if (!np) {
727*4882a593Smuzhiyun 		pr_warn("%s: failed to find shdwc!\n", __func__);
728*4882a593Smuzhiyun 		goto ulp1_default;
729*4882a593Smuzhiyun 	}
730*4882a593Smuzhiyun 
731*4882a593Smuzhiyun 	soc_pm.data.shdwc = of_iomap(np, 0);
732*4882a593Smuzhiyun 	of_node_put(np);
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 	ret = at91_pm_backup_init();
735*4882a593Smuzhiyun 	if (ret) {
736*4882a593Smuzhiyun 		if (!at91_is_pm_mode_active(AT91_PM_ULP1))
737*4882a593Smuzhiyun 			goto unmap;
738*4882a593Smuzhiyun 		else
739*4882a593Smuzhiyun 			goto backup_default;
740*4882a593Smuzhiyun 	}
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun 	return;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun unmap:
745*4882a593Smuzhiyun 	iounmap(soc_pm.data.shdwc);
746*4882a593Smuzhiyun 	soc_pm.data.shdwc = NULL;
747*4882a593Smuzhiyun ulp1_default:
748*4882a593Smuzhiyun 	at91_pm_use_default_mode(AT91_PM_ULP1);
749*4882a593Smuzhiyun backup_default:
750*4882a593Smuzhiyun 	at91_pm_use_default_mode(AT91_PM_BACKUP);
751*4882a593Smuzhiyun }
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun struct pmc_info {
754*4882a593Smuzhiyun 	unsigned long uhp_udp_mask;
755*4882a593Smuzhiyun 	unsigned long mckr;
756*4882a593Smuzhiyun 	unsigned long version;
757*4882a593Smuzhiyun };
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun static const struct pmc_info pmc_infos[] __initconst = {
760*4882a593Smuzhiyun 	{
761*4882a593Smuzhiyun 		.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP,
762*4882a593Smuzhiyun 		.mckr = 0x30,
763*4882a593Smuzhiyun 		.version = AT91_PMC_V1,
764*4882a593Smuzhiyun 	},
765*4882a593Smuzhiyun 
766*4882a593Smuzhiyun 	{
767*4882a593Smuzhiyun 		.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP,
768*4882a593Smuzhiyun 		.mckr = 0x30,
769*4882a593Smuzhiyun 		.version = AT91_PMC_V1,
770*4882a593Smuzhiyun 	},
771*4882a593Smuzhiyun 	{
772*4882a593Smuzhiyun 		.uhp_udp_mask = AT91SAM926x_PMC_UHP,
773*4882a593Smuzhiyun 		.mckr = 0x30,
774*4882a593Smuzhiyun 		.version = AT91_PMC_V1,
775*4882a593Smuzhiyun 	},
776*4882a593Smuzhiyun 	{	.uhp_udp_mask = 0,
777*4882a593Smuzhiyun 		.mckr = 0x30,
778*4882a593Smuzhiyun 		.version = AT91_PMC_V1,
779*4882a593Smuzhiyun 	},
780*4882a593Smuzhiyun 	{
781*4882a593Smuzhiyun 		.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP,
782*4882a593Smuzhiyun 		.mckr = 0x28,
783*4882a593Smuzhiyun 		.version = AT91_PMC_V2,
784*4882a593Smuzhiyun 	},
785*4882a593Smuzhiyun };
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun static const struct of_device_id atmel_pmc_ids[] __initconst = {
788*4882a593Smuzhiyun 	{ .compatible = "atmel,at91rm9200-pmc", .data = &pmc_infos[0] },
789*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9260-pmc", .data = &pmc_infos[1] },
790*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9261-pmc", .data = &pmc_infos[1] },
791*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9263-pmc", .data = &pmc_infos[1] },
792*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9g45-pmc", .data = &pmc_infos[2] },
793*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9n12-pmc", .data = &pmc_infos[1] },
794*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9rl-pmc", .data = &pmc_infos[3] },
795*4882a593Smuzhiyun 	{ .compatible = "atmel,at91sam9x5-pmc", .data = &pmc_infos[1] },
796*4882a593Smuzhiyun 	{ .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] },
797*4882a593Smuzhiyun 	{ .compatible = "atmel,sama5d4-pmc", .data = &pmc_infos[1] },
798*4882a593Smuzhiyun 	{ .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
799*4882a593Smuzhiyun 	{ .compatible = "microchip,sam9x60-pmc", .data = &pmc_infos[4] },
800*4882a593Smuzhiyun 	{ /* sentinel */ },
801*4882a593Smuzhiyun };
802*4882a593Smuzhiyun 
at91_pm_modes_validate(const int * modes,int len)803*4882a593Smuzhiyun static void __init at91_pm_modes_validate(const int *modes, int len)
804*4882a593Smuzhiyun {
805*4882a593Smuzhiyun 	u8 i, standby = 0, suspend = 0;
806*4882a593Smuzhiyun 	int mode;
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	for (i = 0; i < len; i++) {
809*4882a593Smuzhiyun 		if (standby && suspend)
810*4882a593Smuzhiyun 			break;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun 		if (modes[i] == soc_pm.data.standby_mode && !standby) {
813*4882a593Smuzhiyun 			standby = 1;
814*4882a593Smuzhiyun 			continue;
815*4882a593Smuzhiyun 		}
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 		if (modes[i] == soc_pm.data.suspend_mode && !suspend) {
818*4882a593Smuzhiyun 			suspend = 1;
819*4882a593Smuzhiyun 			continue;
820*4882a593Smuzhiyun 		}
821*4882a593Smuzhiyun 	}
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 	if (!standby) {
824*4882a593Smuzhiyun 		if (soc_pm.data.suspend_mode == AT91_PM_STANDBY)
825*4882a593Smuzhiyun 			mode = AT91_PM_ULP0;
826*4882a593Smuzhiyun 		else
827*4882a593Smuzhiyun 			mode = AT91_PM_STANDBY;
828*4882a593Smuzhiyun 
829*4882a593Smuzhiyun 		pr_warn("AT91: PM: %s mode not supported! Using %s.\n",
830*4882a593Smuzhiyun 			pm_modes[soc_pm.data.standby_mode].pattern,
831*4882a593Smuzhiyun 			pm_modes[mode].pattern);
832*4882a593Smuzhiyun 		soc_pm.data.standby_mode = mode;
833*4882a593Smuzhiyun 	}
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 	if (!suspend) {
836*4882a593Smuzhiyun 		if (soc_pm.data.standby_mode == AT91_PM_ULP0)
837*4882a593Smuzhiyun 			mode = AT91_PM_STANDBY;
838*4882a593Smuzhiyun 		else
839*4882a593Smuzhiyun 			mode = AT91_PM_ULP0;
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 		pr_warn("AT91: PM: %s mode not supported! Using %s.\n",
842*4882a593Smuzhiyun 			pm_modes[soc_pm.data.suspend_mode].pattern,
843*4882a593Smuzhiyun 			pm_modes[mode].pattern);
844*4882a593Smuzhiyun 		soc_pm.data.suspend_mode = mode;
845*4882a593Smuzhiyun 	}
846*4882a593Smuzhiyun }
847*4882a593Smuzhiyun 
at91_pm_init(void (* pm_idle)(void))848*4882a593Smuzhiyun static void __init at91_pm_init(void (*pm_idle)(void))
849*4882a593Smuzhiyun {
850*4882a593Smuzhiyun 	struct device_node *pmc_np;
851*4882a593Smuzhiyun 	const struct of_device_id *of_id;
852*4882a593Smuzhiyun 	const struct pmc_info *pmc;
853*4882a593Smuzhiyun 
854*4882a593Smuzhiyun 	if (at91_cpuidle_device.dev.platform_data)
855*4882a593Smuzhiyun 		platform_device_register(&at91_cpuidle_device);
856*4882a593Smuzhiyun 
857*4882a593Smuzhiyun 	pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id);
858*4882a593Smuzhiyun 	soc_pm.data.pmc = of_iomap(pmc_np, 0);
859*4882a593Smuzhiyun 	of_node_put(pmc_np);
860*4882a593Smuzhiyun 	if (!soc_pm.data.pmc) {
861*4882a593Smuzhiyun 		pr_err("AT91: PM not supported, PMC not found\n");
862*4882a593Smuzhiyun 		return;
863*4882a593Smuzhiyun 	}
864*4882a593Smuzhiyun 
865*4882a593Smuzhiyun 	pmc = of_id->data;
866*4882a593Smuzhiyun 	soc_pm.data.uhp_udp_mask = pmc->uhp_udp_mask;
867*4882a593Smuzhiyun 	soc_pm.data.pmc_mckr_offset = pmc->mckr;
868*4882a593Smuzhiyun 	soc_pm.data.pmc_version = pmc->version;
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 	if (pm_idle)
871*4882a593Smuzhiyun 		arm_pm_idle = pm_idle;
872*4882a593Smuzhiyun 
873*4882a593Smuzhiyun 	at91_pm_sram_init();
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun 	if (at91_suspend_sram_fn) {
876*4882a593Smuzhiyun 		suspend_set_ops(&at91_pm_ops);
877*4882a593Smuzhiyun 		pr_info("AT91: PM: standby: %s, suspend: %s\n",
878*4882a593Smuzhiyun 			pm_modes[soc_pm.data.standby_mode].pattern,
879*4882a593Smuzhiyun 			pm_modes[soc_pm.data.suspend_mode].pattern);
880*4882a593Smuzhiyun 	} else {
881*4882a593Smuzhiyun 		pr_info("AT91: PM not supported, due to no SRAM allocated\n");
882*4882a593Smuzhiyun 	}
883*4882a593Smuzhiyun }
884*4882a593Smuzhiyun 
at91rm9200_pm_init(void)885*4882a593Smuzhiyun void __init at91rm9200_pm_init(void)
886*4882a593Smuzhiyun {
887*4882a593Smuzhiyun 	int ret;
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun 	if (!IS_ENABLED(CONFIG_SOC_AT91RM9200))
890*4882a593Smuzhiyun 		return;
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 	/*
893*4882a593Smuzhiyun 	 * Force STANDBY and ULP0 mode to avoid calling
894*4882a593Smuzhiyun 	 * at91_pm_modes_validate() which may increase booting time.
895*4882a593Smuzhiyun 	 * Platform supports anyway only STANDBY and ULP0 modes.
896*4882a593Smuzhiyun 	 */
897*4882a593Smuzhiyun 	soc_pm.data.standby_mode = AT91_PM_STANDBY;
898*4882a593Smuzhiyun 	soc_pm.data.suspend_mode = AT91_PM_ULP0;
899*4882a593Smuzhiyun 
900*4882a593Smuzhiyun 	ret = at91_dt_ramc();
901*4882a593Smuzhiyun 	if (ret)
902*4882a593Smuzhiyun 		return;
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	/*
905*4882a593Smuzhiyun 	 * AT91RM9200 SDRAM low-power mode cannot be used with self-refresh.
906*4882a593Smuzhiyun 	 */
907*4882a593Smuzhiyun 	at91_ramc_write(0, AT91_MC_SDRAMC_LPR, 0);
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	at91_pm_init(at91rm9200_idle);
910*4882a593Smuzhiyun }
911*4882a593Smuzhiyun 
sam9x60_pm_init(void)912*4882a593Smuzhiyun void __init sam9x60_pm_init(void)
913*4882a593Smuzhiyun {
914*4882a593Smuzhiyun 	static const int modes[] __initconst = {
915*4882a593Smuzhiyun 		AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
916*4882a593Smuzhiyun 	};
917*4882a593Smuzhiyun 	int ret;
918*4882a593Smuzhiyun 
919*4882a593Smuzhiyun 	if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
920*4882a593Smuzhiyun 		return;
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 	at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
923*4882a593Smuzhiyun 	at91_pm_modes_init();
924*4882a593Smuzhiyun 	ret = at91_dt_ramc();
925*4882a593Smuzhiyun 	if (ret)
926*4882a593Smuzhiyun 		return;
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun 	at91_pm_init(NULL);
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 	soc_pm.ws_ids = sam9x60_ws_ids;
931*4882a593Smuzhiyun 	soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun 
at91sam9_pm_init(void)934*4882a593Smuzhiyun void __init at91sam9_pm_init(void)
935*4882a593Smuzhiyun {
936*4882a593Smuzhiyun 	int ret;
937*4882a593Smuzhiyun 
938*4882a593Smuzhiyun 	if (!IS_ENABLED(CONFIG_SOC_AT91SAM9))
939*4882a593Smuzhiyun 		return;
940*4882a593Smuzhiyun 
941*4882a593Smuzhiyun 	/*
942*4882a593Smuzhiyun 	 * Force STANDBY and ULP0 mode to avoid calling
943*4882a593Smuzhiyun 	 * at91_pm_modes_validate() which may increase booting time.
944*4882a593Smuzhiyun 	 * Platform supports anyway only STANDBY and ULP0 modes.
945*4882a593Smuzhiyun 	 */
946*4882a593Smuzhiyun 	soc_pm.data.standby_mode = AT91_PM_STANDBY;
947*4882a593Smuzhiyun 	soc_pm.data.suspend_mode = AT91_PM_ULP0;
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun 	ret = at91_dt_ramc();
950*4882a593Smuzhiyun 	if (ret)
951*4882a593Smuzhiyun 		return;
952*4882a593Smuzhiyun 
953*4882a593Smuzhiyun 	at91_pm_init(at91sam9_idle);
954*4882a593Smuzhiyun }
955*4882a593Smuzhiyun 
sama5_pm_init(void)956*4882a593Smuzhiyun void __init sama5_pm_init(void)
957*4882a593Smuzhiyun {
958*4882a593Smuzhiyun 	static const int modes[] __initconst = {
959*4882a593Smuzhiyun 		AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST,
960*4882a593Smuzhiyun 	};
961*4882a593Smuzhiyun 	int ret;
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun 	if (!IS_ENABLED(CONFIG_SOC_SAMA5))
964*4882a593Smuzhiyun 		return;
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun 	at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
967*4882a593Smuzhiyun 	ret = at91_dt_ramc();
968*4882a593Smuzhiyun 	if (ret)
969*4882a593Smuzhiyun 		return;
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun 	at91_pm_init(NULL);
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun 
sama5d2_pm_init(void)974*4882a593Smuzhiyun void __init sama5d2_pm_init(void)
975*4882a593Smuzhiyun {
976*4882a593Smuzhiyun 	static const int modes[] __initconst = {
977*4882a593Smuzhiyun 		AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
978*4882a593Smuzhiyun 		AT91_PM_BACKUP,
979*4882a593Smuzhiyun 	};
980*4882a593Smuzhiyun 	int ret;
981*4882a593Smuzhiyun 
982*4882a593Smuzhiyun 	if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
983*4882a593Smuzhiyun 		return;
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
986*4882a593Smuzhiyun 	at91_pm_modes_init();
987*4882a593Smuzhiyun 	ret = at91_dt_ramc();
988*4882a593Smuzhiyun 	if (ret)
989*4882a593Smuzhiyun 		return;
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun 	at91_pm_init(NULL);
992*4882a593Smuzhiyun 
993*4882a593Smuzhiyun 	soc_pm.ws_ids = sama5d2_ws_ids;
994*4882a593Smuzhiyun 	soc_pm.config_shdwc_ws = at91_sama5d2_config_shdwc_ws;
995*4882a593Smuzhiyun 	soc_pm.config_pmc_ws = at91_sama5d2_config_pmc_ws;
996*4882a593Smuzhiyun }
997*4882a593Smuzhiyun 
at91_pm_modes_select(char * str)998*4882a593Smuzhiyun static int __init at91_pm_modes_select(char *str)
999*4882a593Smuzhiyun {
1000*4882a593Smuzhiyun 	char *s;
1001*4882a593Smuzhiyun 	substring_t args[MAX_OPT_ARGS];
1002*4882a593Smuzhiyun 	int standby, suspend;
1003*4882a593Smuzhiyun 
1004*4882a593Smuzhiyun 	if (!str)
1005*4882a593Smuzhiyun 		return 0;
1006*4882a593Smuzhiyun 
1007*4882a593Smuzhiyun 	s = strsep(&str, ",");
1008*4882a593Smuzhiyun 	standby = match_token(s, pm_modes, args);
1009*4882a593Smuzhiyun 	if (standby < 0)
1010*4882a593Smuzhiyun 		return 0;
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun 	suspend = match_token(str, pm_modes, args);
1013*4882a593Smuzhiyun 	if (suspend < 0)
1014*4882a593Smuzhiyun 		return 0;
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun 	soc_pm.data.standby_mode = standby;
1017*4882a593Smuzhiyun 	soc_pm.data.suspend_mode = suspend;
1018*4882a593Smuzhiyun 
1019*4882a593Smuzhiyun 	return 0;
1020*4882a593Smuzhiyun }
1021*4882a593Smuzhiyun early_param("atmel.pm_modes", at91_pm_modes_select);
1022