xref: /OK3568_Linux_fs/kernel/drivers/soc/ti/pm33xx.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * AM33XX Power Management Routines
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2012-2018 Texas Instruments Incorporated - http://www.ti.com/
6*4882a593Smuzhiyun  *	Vaibhav Bedia, Dave Gerlach
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/clk.h>
10*4882a593Smuzhiyun #include <linux/cpu.h>
11*4882a593Smuzhiyun #include <linux/err.h>
12*4882a593Smuzhiyun #include <linux/genalloc.h>
13*4882a593Smuzhiyun #include <linux/kernel.h>
14*4882a593Smuzhiyun #include <linux/init.h>
15*4882a593Smuzhiyun #include <linux/io.h>
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/nvmem-consumer.h>
18*4882a593Smuzhiyun #include <linux/of.h>
19*4882a593Smuzhiyun #include <linux/of_address.h>
20*4882a593Smuzhiyun #include <linux/platform_data/pm33xx.h>
21*4882a593Smuzhiyun #include <linux/platform_device.h>
22*4882a593Smuzhiyun #include <linux/rtc.h>
23*4882a593Smuzhiyun #include <linux/rtc/rtc-omap.h>
24*4882a593Smuzhiyun #include <linux/sizes.h>
25*4882a593Smuzhiyun #include <linux/sram.h>
26*4882a593Smuzhiyun #include <linux/suspend.h>
27*4882a593Smuzhiyun #include <linux/ti-emif-sram.h>
28*4882a593Smuzhiyun #include <linux/wkup_m3_ipc.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include <asm/proc-fns.h>
31*4882a593Smuzhiyun #include <asm/suspend.h>
32*4882a593Smuzhiyun #include <asm/system_misc.h>
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define AMX3_PM_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \
35*4882a593Smuzhiyun 					 (unsigned long)pm_sram->do_wfi)
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define RTC_SCRATCH_RESUME_REG	0
38*4882a593Smuzhiyun #define RTC_SCRATCH_MAGIC_REG	1
39*4882a593Smuzhiyun #define RTC_REG_BOOT_MAGIC	0x8cd0 /* RTC */
40*4882a593Smuzhiyun #define GIC_INT_SET_PENDING_BASE 0x200
41*4882a593Smuzhiyun #define AM43XX_GIC_DIST_BASE	0x48241000
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun static void __iomem *rtc_base_virt;
44*4882a593Smuzhiyun static struct clk *rtc_fck;
45*4882a593Smuzhiyun static u32 rtc_magic_val;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun static int (*am33xx_do_wfi_sram)(unsigned long unused);
48*4882a593Smuzhiyun static phys_addr_t am33xx_do_wfi_sram_phys;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun static struct gen_pool *sram_pool, *sram_pool_data;
51*4882a593Smuzhiyun static unsigned long ocmcram_location, ocmcram_location_data;
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun static struct rtc_device *omap_rtc;
54*4882a593Smuzhiyun static void __iomem *gic_dist_base;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun static struct am33xx_pm_platform_data *pm_ops;
57*4882a593Smuzhiyun static struct am33xx_pm_sram_addr *pm_sram;
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun static struct device *pm33xx_dev;
60*4882a593Smuzhiyun static struct wkup_m3_ipc *m3_ipc;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun #ifdef CONFIG_SUSPEND
63*4882a593Smuzhiyun static int rtc_only_idle;
64*4882a593Smuzhiyun static int retrigger_irq;
65*4882a593Smuzhiyun static unsigned long suspend_wfi_flags;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun static struct wkup_m3_wakeup_src wakeup_src = {.irq_nr = 0,
68*4882a593Smuzhiyun 	.src = "Unknown",
69*4882a593Smuzhiyun };
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun static struct wkup_m3_wakeup_src rtc_alarm_wakeup = {
72*4882a593Smuzhiyun 	.irq_nr = 108, .src = "RTC Alarm",
73*4882a593Smuzhiyun };
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun static struct wkup_m3_wakeup_src rtc_ext_wakeup = {
76*4882a593Smuzhiyun 	.irq_nr = 0, .src = "Ext wakeup",
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun #endif
79*4882a593Smuzhiyun 
sram_suspend_address(unsigned long addr)80*4882a593Smuzhiyun static u32 sram_suspend_address(unsigned long addr)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	return ((unsigned long)am33xx_do_wfi_sram +
83*4882a593Smuzhiyun 		AMX3_PM_SRAM_SYMBOL_OFFSET(addr));
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
am33xx_push_sram_idle(void)86*4882a593Smuzhiyun static int am33xx_push_sram_idle(void)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	struct am33xx_pm_ro_sram_data ro_sram_data;
89*4882a593Smuzhiyun 	int ret;
90*4882a593Smuzhiyun 	u32 table_addr, ro_data_addr;
91*4882a593Smuzhiyun 	void *copy_addr;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	ro_sram_data.amx3_pm_sram_data_virt = ocmcram_location_data;
94*4882a593Smuzhiyun 	ro_sram_data.amx3_pm_sram_data_phys =
95*4882a593Smuzhiyun 		gen_pool_virt_to_phys(sram_pool_data, ocmcram_location_data);
96*4882a593Smuzhiyun 	ro_sram_data.rtc_base_virt = rtc_base_virt;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	/* Save physical address to calculate resume offset during pm init */
99*4882a593Smuzhiyun 	am33xx_do_wfi_sram_phys = gen_pool_virt_to_phys(sram_pool,
100*4882a593Smuzhiyun 							ocmcram_location);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	am33xx_do_wfi_sram = sram_exec_copy(sram_pool, (void *)ocmcram_location,
103*4882a593Smuzhiyun 					    pm_sram->do_wfi,
104*4882a593Smuzhiyun 					    *pm_sram->do_wfi_sz);
105*4882a593Smuzhiyun 	if (!am33xx_do_wfi_sram) {
106*4882a593Smuzhiyun 		dev_err(pm33xx_dev,
107*4882a593Smuzhiyun 			"PM: %s: am33xx_do_wfi copy to sram failed\n",
108*4882a593Smuzhiyun 			__func__);
109*4882a593Smuzhiyun 		return -ENODEV;
110*4882a593Smuzhiyun 	}
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	table_addr =
113*4882a593Smuzhiyun 		sram_suspend_address((unsigned long)pm_sram->emif_sram_table);
114*4882a593Smuzhiyun 	ret = ti_emif_copy_pm_function_table(sram_pool, (void *)table_addr);
115*4882a593Smuzhiyun 	if (ret) {
116*4882a593Smuzhiyun 		dev_dbg(pm33xx_dev,
117*4882a593Smuzhiyun 			"PM: %s: EMIF function copy failed\n", __func__);
118*4882a593Smuzhiyun 		return -EPROBE_DEFER;
119*4882a593Smuzhiyun 	}
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	ro_data_addr =
122*4882a593Smuzhiyun 		sram_suspend_address((unsigned long)pm_sram->ro_sram_data);
123*4882a593Smuzhiyun 	copy_addr = sram_exec_copy(sram_pool, (void *)ro_data_addr,
124*4882a593Smuzhiyun 				   &ro_sram_data,
125*4882a593Smuzhiyun 				   sizeof(ro_sram_data));
126*4882a593Smuzhiyun 	if (!copy_addr) {
127*4882a593Smuzhiyun 		dev_err(pm33xx_dev,
128*4882a593Smuzhiyun 			"PM: %s: ro_sram_data copy to sram failed\n",
129*4882a593Smuzhiyun 			__func__);
130*4882a593Smuzhiyun 		return -ENODEV;
131*4882a593Smuzhiyun 	}
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun 	return 0;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
am33xx_do_sram_idle(u32 wfi_flags)136*4882a593Smuzhiyun static int am33xx_do_sram_idle(u32 wfi_flags)
137*4882a593Smuzhiyun {
138*4882a593Smuzhiyun 	int ret = 0;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	if (!m3_ipc || !pm_ops)
141*4882a593Smuzhiyun 		return 0;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	if (wfi_flags & WFI_FLAG_WAKE_M3)
144*4882a593Smuzhiyun 		ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_IDLE);
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun 	return pm_ops->cpu_suspend(am33xx_do_wfi_sram, wfi_flags);
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun 
am43xx_map_gic(void)149*4882a593Smuzhiyun static int __init am43xx_map_gic(void)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun 	gic_dist_base = ioremap(AM43XX_GIC_DIST_BASE, SZ_4K);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	if (!gic_dist_base)
154*4882a593Smuzhiyun 		return -ENOMEM;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	return 0;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun #ifdef CONFIG_SUSPEND
rtc_wake_src(void)160*4882a593Smuzhiyun static struct wkup_m3_wakeup_src rtc_wake_src(void)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun 	u32 i;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	i = __raw_readl(rtc_base_virt + 0x44) & 0x40;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	if (i) {
167*4882a593Smuzhiyun 		retrigger_irq = rtc_alarm_wakeup.irq_nr;
168*4882a593Smuzhiyun 		return rtc_alarm_wakeup;
169*4882a593Smuzhiyun 	}
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	retrigger_irq = rtc_ext_wakeup.irq_nr;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	return rtc_ext_wakeup;
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
am33xx_rtc_only_idle(unsigned long wfi_flags)176*4882a593Smuzhiyun static int am33xx_rtc_only_idle(unsigned long wfi_flags)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	omap_rtc_power_off_program(&omap_rtc->dev);
179*4882a593Smuzhiyun 	am33xx_do_wfi_sram(wfi_flags);
180*4882a593Smuzhiyun 	return 0;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun /*
184*4882a593Smuzhiyun  * Note that the RTC module clock must be re-enabled only for rtc+ddr suspend.
185*4882a593Smuzhiyun  * And looks like the module can stay in SYSC_IDLE_SMART_WKUP mode configured
186*4882a593Smuzhiyun  * by the interconnect code just fine for both rtc+ddr suspend and retention
187*4882a593Smuzhiyun  * suspend.
188*4882a593Smuzhiyun  */
am33xx_pm_suspend(suspend_state_t suspend_state)189*4882a593Smuzhiyun static int am33xx_pm_suspend(suspend_state_t suspend_state)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun 	int i, ret = 0;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	if (suspend_state == PM_SUSPEND_MEM &&
194*4882a593Smuzhiyun 	    pm_ops->check_off_mode_enable()) {
195*4882a593Smuzhiyun 		ret = clk_prepare_enable(rtc_fck);
196*4882a593Smuzhiyun 		if (ret) {
197*4882a593Smuzhiyun 			dev_err(pm33xx_dev, "Failed to enable clock: %i\n", ret);
198*4882a593Smuzhiyun 			return ret;
199*4882a593Smuzhiyun 		}
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 		pm_ops->save_context();
202*4882a593Smuzhiyun 		suspend_wfi_flags |= WFI_FLAG_RTC_ONLY;
203*4882a593Smuzhiyun 		clk_save_context();
204*4882a593Smuzhiyun 		ret = pm_ops->soc_suspend(suspend_state, am33xx_rtc_only_idle,
205*4882a593Smuzhiyun 					  suspend_wfi_flags);
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 		suspend_wfi_flags &= ~WFI_FLAG_RTC_ONLY;
208*4882a593Smuzhiyun 		dev_info(pm33xx_dev, "Entering RTC Only mode with DDR in self-refresh\n");
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 		if (!ret) {
211*4882a593Smuzhiyun 			clk_restore_context();
212*4882a593Smuzhiyun 			pm_ops->restore_context();
213*4882a593Smuzhiyun 			m3_ipc->ops->set_rtc_only(m3_ipc);
214*4882a593Smuzhiyun 			am33xx_push_sram_idle();
215*4882a593Smuzhiyun 		}
216*4882a593Smuzhiyun 	} else {
217*4882a593Smuzhiyun 		ret = pm_ops->soc_suspend(suspend_state, am33xx_do_wfi_sram,
218*4882a593Smuzhiyun 					  suspend_wfi_flags);
219*4882a593Smuzhiyun 	}
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	if (ret) {
222*4882a593Smuzhiyun 		dev_err(pm33xx_dev, "PM: Kernel suspend failure\n");
223*4882a593Smuzhiyun 	} else {
224*4882a593Smuzhiyun 		i = m3_ipc->ops->request_pm_status(m3_ipc);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 		switch (i) {
227*4882a593Smuzhiyun 		case 0:
228*4882a593Smuzhiyun 			dev_info(pm33xx_dev,
229*4882a593Smuzhiyun 				 "PM: Successfully put all powerdomains to target state\n");
230*4882a593Smuzhiyun 			break;
231*4882a593Smuzhiyun 		case 1:
232*4882a593Smuzhiyun 			dev_err(pm33xx_dev,
233*4882a593Smuzhiyun 				"PM: Could not transition all powerdomains to target state\n");
234*4882a593Smuzhiyun 			ret = -1;
235*4882a593Smuzhiyun 			break;
236*4882a593Smuzhiyun 		default:
237*4882a593Smuzhiyun 			dev_err(pm33xx_dev,
238*4882a593Smuzhiyun 				"PM: CM3 returned unknown result = %d\n", i);
239*4882a593Smuzhiyun 			ret = -1;
240*4882a593Smuzhiyun 		}
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 		/* print the wakeup reason */
243*4882a593Smuzhiyun 		if (rtc_only_idle) {
244*4882a593Smuzhiyun 			wakeup_src = rtc_wake_src();
245*4882a593Smuzhiyun 			pr_info("PM: Wakeup source %s\n", wakeup_src.src);
246*4882a593Smuzhiyun 		} else {
247*4882a593Smuzhiyun 			pr_info("PM: Wakeup source %s\n",
248*4882a593Smuzhiyun 				m3_ipc->ops->request_wake_src(m3_ipc));
249*4882a593Smuzhiyun 		}
250*4882a593Smuzhiyun 	}
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	if (suspend_state == PM_SUSPEND_MEM && pm_ops->check_off_mode_enable())
253*4882a593Smuzhiyun 		clk_disable_unprepare(rtc_fck);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	return ret;
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
am33xx_pm_enter(suspend_state_t suspend_state)258*4882a593Smuzhiyun static int am33xx_pm_enter(suspend_state_t suspend_state)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun 	int ret = 0;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	switch (suspend_state) {
263*4882a593Smuzhiyun 	case PM_SUSPEND_MEM:
264*4882a593Smuzhiyun 	case PM_SUSPEND_STANDBY:
265*4882a593Smuzhiyun 		ret = am33xx_pm_suspend(suspend_state);
266*4882a593Smuzhiyun 		break;
267*4882a593Smuzhiyun 	default:
268*4882a593Smuzhiyun 		ret = -EINVAL;
269*4882a593Smuzhiyun 	}
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	return ret;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
am33xx_pm_begin(suspend_state_t state)274*4882a593Smuzhiyun static int am33xx_pm_begin(suspend_state_t state)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun 	int ret = -EINVAL;
277*4882a593Smuzhiyun 	struct nvmem_device *nvmem;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 	if (state == PM_SUSPEND_MEM && pm_ops->check_off_mode_enable()) {
280*4882a593Smuzhiyun 		nvmem = devm_nvmem_device_get(&omap_rtc->dev,
281*4882a593Smuzhiyun 					      "omap_rtc_scratch0");
282*4882a593Smuzhiyun 		if (!IS_ERR(nvmem))
283*4882a593Smuzhiyun 			nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
284*4882a593Smuzhiyun 					   (void *)&rtc_magic_val);
285*4882a593Smuzhiyun 		rtc_only_idle = 1;
286*4882a593Smuzhiyun 	} else {
287*4882a593Smuzhiyun 		rtc_only_idle = 0;
288*4882a593Smuzhiyun 	}
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	pm_ops->begin_suspend();
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	switch (state) {
293*4882a593Smuzhiyun 	case PM_SUSPEND_MEM:
294*4882a593Smuzhiyun 		ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_DEEPSLEEP);
295*4882a593Smuzhiyun 		break;
296*4882a593Smuzhiyun 	case PM_SUSPEND_STANDBY:
297*4882a593Smuzhiyun 		ret = m3_ipc->ops->prepare_low_power(m3_ipc, WKUP_M3_STANDBY);
298*4882a593Smuzhiyun 		break;
299*4882a593Smuzhiyun 	}
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	return ret;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun 
am33xx_pm_end(void)304*4882a593Smuzhiyun static void am33xx_pm_end(void)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun 	u32 val = 0;
307*4882a593Smuzhiyun 	struct nvmem_device *nvmem;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	nvmem = devm_nvmem_device_get(&omap_rtc->dev, "omap_rtc_scratch0");
310*4882a593Smuzhiyun 	if (IS_ERR(nvmem))
311*4882a593Smuzhiyun 		return;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun 	m3_ipc->ops->finish_low_power(m3_ipc);
314*4882a593Smuzhiyun 	if (rtc_only_idle) {
315*4882a593Smuzhiyun 		if (retrigger_irq) {
316*4882a593Smuzhiyun 			/*
317*4882a593Smuzhiyun 			 * 32 bits of Interrupt Set-Pending correspond to 32
318*4882a593Smuzhiyun 			 * 32 interrupts. Compute the bit offset of the
319*4882a593Smuzhiyun 			 * Interrupt and set that particular bit
320*4882a593Smuzhiyun 			 * Compute the register offset by dividing interrupt
321*4882a593Smuzhiyun 			 * number by 32 and mutiplying by 4
322*4882a593Smuzhiyun 			 */
323*4882a593Smuzhiyun 			writel_relaxed(1 << (retrigger_irq & 31),
324*4882a593Smuzhiyun 				       gic_dist_base + GIC_INT_SET_PENDING_BASE
325*4882a593Smuzhiyun 				       + retrigger_irq / 32 * 4);
326*4882a593Smuzhiyun 		}
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 		nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
329*4882a593Smuzhiyun 				   (void *)&val);
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	rtc_only_idle = 0;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	pm_ops->finish_suspend();
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun 
am33xx_pm_valid(suspend_state_t state)337*4882a593Smuzhiyun static int am33xx_pm_valid(suspend_state_t state)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun 	switch (state) {
340*4882a593Smuzhiyun 	case PM_SUSPEND_STANDBY:
341*4882a593Smuzhiyun 	case PM_SUSPEND_MEM:
342*4882a593Smuzhiyun 		return 1;
343*4882a593Smuzhiyun 	default:
344*4882a593Smuzhiyun 		return 0;
345*4882a593Smuzhiyun 	}
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun static const struct platform_suspend_ops am33xx_pm_ops = {
349*4882a593Smuzhiyun 	.begin		= am33xx_pm_begin,
350*4882a593Smuzhiyun 	.end		= am33xx_pm_end,
351*4882a593Smuzhiyun 	.enter		= am33xx_pm_enter,
352*4882a593Smuzhiyun 	.valid		= am33xx_pm_valid,
353*4882a593Smuzhiyun };
354*4882a593Smuzhiyun #endif /* CONFIG_SUSPEND */
355*4882a593Smuzhiyun 
am33xx_pm_set_ipc_ops(void)356*4882a593Smuzhiyun static void am33xx_pm_set_ipc_ops(void)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	u32 resume_address;
359*4882a593Smuzhiyun 	int temp;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	temp = ti_emif_get_mem_type();
362*4882a593Smuzhiyun 	if (temp < 0) {
363*4882a593Smuzhiyun 		dev_err(pm33xx_dev, "PM: Cannot determine memory type, no PM available\n");
364*4882a593Smuzhiyun 		return;
365*4882a593Smuzhiyun 	}
366*4882a593Smuzhiyun 	m3_ipc->ops->set_mem_type(m3_ipc, temp);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	/* Physical resume address to be used by ROM code */
369*4882a593Smuzhiyun 	resume_address = am33xx_do_wfi_sram_phys +
370*4882a593Smuzhiyun 			 *pm_sram->resume_offset + 0x4;
371*4882a593Smuzhiyun 
372*4882a593Smuzhiyun 	m3_ipc->ops->set_resume_address(m3_ipc, (void *)resume_address);
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun 
am33xx_pm_free_sram(void)375*4882a593Smuzhiyun static void am33xx_pm_free_sram(void)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun 	gen_pool_free(sram_pool, ocmcram_location, *pm_sram->do_wfi_sz);
378*4882a593Smuzhiyun 	gen_pool_free(sram_pool_data, ocmcram_location_data,
379*4882a593Smuzhiyun 		      sizeof(struct am33xx_pm_ro_sram_data));
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun /*
383*4882a593Smuzhiyun  * Push the minimal suspend-resume code to SRAM
384*4882a593Smuzhiyun  */
am33xx_pm_alloc_sram(void)385*4882a593Smuzhiyun static int am33xx_pm_alloc_sram(void)
386*4882a593Smuzhiyun {
387*4882a593Smuzhiyun 	struct device_node *np;
388*4882a593Smuzhiyun 	int ret = 0;
389*4882a593Smuzhiyun 
390*4882a593Smuzhiyun 	np = of_find_compatible_node(NULL, NULL, "ti,omap3-mpu");
391*4882a593Smuzhiyun 	if (!np) {
392*4882a593Smuzhiyun 		np = of_find_compatible_node(NULL, NULL, "ti,omap4-mpu");
393*4882a593Smuzhiyun 		if (!np) {
394*4882a593Smuzhiyun 			dev_err(pm33xx_dev, "PM: %s: Unable to find device node for mpu\n",
395*4882a593Smuzhiyun 				__func__);
396*4882a593Smuzhiyun 			return -ENODEV;
397*4882a593Smuzhiyun 		}
398*4882a593Smuzhiyun 	}
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	sram_pool = of_gen_pool_get(np, "pm-sram", 0);
401*4882a593Smuzhiyun 	if (!sram_pool) {
402*4882a593Smuzhiyun 		dev_err(pm33xx_dev, "PM: %s: Unable to get sram pool for ocmcram\n",
403*4882a593Smuzhiyun 			__func__);
404*4882a593Smuzhiyun 		ret = -ENODEV;
405*4882a593Smuzhiyun 		goto mpu_put_node;
406*4882a593Smuzhiyun 	}
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun 	sram_pool_data = of_gen_pool_get(np, "pm-sram", 1);
409*4882a593Smuzhiyun 	if (!sram_pool_data) {
410*4882a593Smuzhiyun 		dev_err(pm33xx_dev, "PM: %s: Unable to get sram data pool for ocmcram\n",
411*4882a593Smuzhiyun 			__func__);
412*4882a593Smuzhiyun 		ret = -ENODEV;
413*4882a593Smuzhiyun 		goto mpu_put_node;
414*4882a593Smuzhiyun 	}
415*4882a593Smuzhiyun 
416*4882a593Smuzhiyun 	ocmcram_location = gen_pool_alloc(sram_pool, *pm_sram->do_wfi_sz);
417*4882a593Smuzhiyun 	if (!ocmcram_location) {
418*4882a593Smuzhiyun 		dev_err(pm33xx_dev, "PM: %s: Unable to allocate memory from ocmcram\n",
419*4882a593Smuzhiyun 			__func__);
420*4882a593Smuzhiyun 		ret = -ENOMEM;
421*4882a593Smuzhiyun 		goto mpu_put_node;
422*4882a593Smuzhiyun 	}
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	ocmcram_location_data = gen_pool_alloc(sram_pool_data,
425*4882a593Smuzhiyun 					       sizeof(struct emif_regs_amx3));
426*4882a593Smuzhiyun 	if (!ocmcram_location_data) {
427*4882a593Smuzhiyun 		dev_err(pm33xx_dev, "PM: Unable to allocate memory from ocmcram\n");
428*4882a593Smuzhiyun 		gen_pool_free(sram_pool, ocmcram_location, *pm_sram->do_wfi_sz);
429*4882a593Smuzhiyun 		ret = -ENOMEM;
430*4882a593Smuzhiyun 	}
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun mpu_put_node:
433*4882a593Smuzhiyun 	of_node_put(np);
434*4882a593Smuzhiyun 	return ret;
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun 
am33xx_pm_rtc_setup(void)437*4882a593Smuzhiyun static int am33xx_pm_rtc_setup(void)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun 	struct device_node *np;
440*4882a593Smuzhiyun 	unsigned long val = 0;
441*4882a593Smuzhiyun 	struct nvmem_device *nvmem;
442*4882a593Smuzhiyun 	int error;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	np = of_find_node_by_name(NULL, "rtc");
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 	if (of_device_is_available(np)) {
447*4882a593Smuzhiyun 		/* RTC interconnect target module clock */
448*4882a593Smuzhiyun 		rtc_fck = of_clk_get_by_name(np->parent, "fck");
449*4882a593Smuzhiyun 		if (IS_ERR(rtc_fck))
450*4882a593Smuzhiyun 			return PTR_ERR(rtc_fck);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 		rtc_base_virt = of_iomap(np, 0);
453*4882a593Smuzhiyun 		if (!rtc_base_virt) {
454*4882a593Smuzhiyun 			pr_warn("PM: could not iomap rtc");
455*4882a593Smuzhiyun 			error = -ENODEV;
456*4882a593Smuzhiyun 			goto err_clk_put;
457*4882a593Smuzhiyun 		}
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 		omap_rtc = rtc_class_open("rtc0");
460*4882a593Smuzhiyun 		if (!omap_rtc) {
461*4882a593Smuzhiyun 			pr_warn("PM: rtc0 not available");
462*4882a593Smuzhiyun 			error = -EPROBE_DEFER;
463*4882a593Smuzhiyun 			goto err_iounmap;
464*4882a593Smuzhiyun 		}
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 		nvmem = devm_nvmem_device_get(&omap_rtc->dev,
467*4882a593Smuzhiyun 					      "omap_rtc_scratch0");
468*4882a593Smuzhiyun 		if (!IS_ERR(nvmem)) {
469*4882a593Smuzhiyun 			nvmem_device_read(nvmem, RTC_SCRATCH_MAGIC_REG * 4,
470*4882a593Smuzhiyun 					  4, (void *)&rtc_magic_val);
471*4882a593Smuzhiyun 			if ((rtc_magic_val & 0xffff) != RTC_REG_BOOT_MAGIC)
472*4882a593Smuzhiyun 				pr_warn("PM: bootloader does not support rtc-only!\n");
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 			nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4,
475*4882a593Smuzhiyun 					   4, (void *)&val);
476*4882a593Smuzhiyun 			val = pm_sram->resume_address;
477*4882a593Smuzhiyun 			nvmem_device_write(nvmem, RTC_SCRATCH_RESUME_REG * 4,
478*4882a593Smuzhiyun 					   4, (void *)&val);
479*4882a593Smuzhiyun 		}
480*4882a593Smuzhiyun 	} else {
481*4882a593Smuzhiyun 		pr_warn("PM: no-rtc available, rtc-only mode disabled.\n");
482*4882a593Smuzhiyun 	}
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun 	return 0;
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun err_iounmap:
487*4882a593Smuzhiyun 	iounmap(rtc_base_virt);
488*4882a593Smuzhiyun err_clk_put:
489*4882a593Smuzhiyun 	clk_put(rtc_fck);
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	return error;
492*4882a593Smuzhiyun }
493*4882a593Smuzhiyun 
am33xx_pm_probe(struct platform_device * pdev)494*4882a593Smuzhiyun static int am33xx_pm_probe(struct platform_device *pdev)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
497*4882a593Smuzhiyun 	int ret;
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	if (!of_machine_is_compatible("ti,am33xx") &&
500*4882a593Smuzhiyun 	    !of_machine_is_compatible("ti,am43"))
501*4882a593Smuzhiyun 		return -ENODEV;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	pm_ops = dev->platform_data;
504*4882a593Smuzhiyun 	if (!pm_ops) {
505*4882a593Smuzhiyun 		dev_err(dev, "PM: Cannot get core PM ops!\n");
506*4882a593Smuzhiyun 		return -ENODEV;
507*4882a593Smuzhiyun 	}
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	ret = am43xx_map_gic();
510*4882a593Smuzhiyun 	if (ret) {
511*4882a593Smuzhiyun 		pr_err("PM: Could not ioremap GIC base\n");
512*4882a593Smuzhiyun 		return ret;
513*4882a593Smuzhiyun 	}
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	pm_sram = pm_ops->get_sram_addrs();
516*4882a593Smuzhiyun 	if (!pm_sram) {
517*4882a593Smuzhiyun 		dev_err(dev, "PM: Cannot get PM asm function addresses!!\n");
518*4882a593Smuzhiyun 		return -ENODEV;
519*4882a593Smuzhiyun 	}
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	m3_ipc = wkup_m3_ipc_get();
522*4882a593Smuzhiyun 	if (!m3_ipc) {
523*4882a593Smuzhiyun 		pr_err("PM: Cannot get wkup_m3_ipc handle\n");
524*4882a593Smuzhiyun 		return -EPROBE_DEFER;
525*4882a593Smuzhiyun 	}
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	pm33xx_dev = dev;
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	ret = am33xx_pm_alloc_sram();
530*4882a593Smuzhiyun 	if (ret)
531*4882a593Smuzhiyun 		return ret;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	ret = am33xx_pm_rtc_setup();
534*4882a593Smuzhiyun 	if (ret)
535*4882a593Smuzhiyun 		goto err_free_sram;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	ret = am33xx_push_sram_idle();
538*4882a593Smuzhiyun 	if (ret)
539*4882a593Smuzhiyun 		goto err_unsetup_rtc;
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	am33xx_pm_set_ipc_ops();
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun #ifdef CONFIG_SUSPEND
544*4882a593Smuzhiyun 	suspend_set_ops(&am33xx_pm_ops);
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	/*
547*4882a593Smuzhiyun 	 * For a system suspend we must flush the caches, we want
548*4882a593Smuzhiyun 	 * the DDR in self-refresh, we want to save the context
549*4882a593Smuzhiyun 	 * of the EMIF, and we want the wkup_m3 to handle low-power
550*4882a593Smuzhiyun 	 * transition.
551*4882a593Smuzhiyun 	 */
552*4882a593Smuzhiyun 	suspend_wfi_flags |= WFI_FLAG_FLUSH_CACHE;
553*4882a593Smuzhiyun 	suspend_wfi_flags |= WFI_FLAG_SELF_REFRESH;
554*4882a593Smuzhiyun 	suspend_wfi_flags |= WFI_FLAG_SAVE_EMIF;
555*4882a593Smuzhiyun 	suspend_wfi_flags |= WFI_FLAG_WAKE_M3;
556*4882a593Smuzhiyun #endif /* CONFIG_SUSPEND */
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	ret = pm_ops->init(am33xx_do_sram_idle);
559*4882a593Smuzhiyun 	if (ret) {
560*4882a593Smuzhiyun 		dev_err(dev, "Unable to call core pm init!\n");
561*4882a593Smuzhiyun 		ret = -ENODEV;
562*4882a593Smuzhiyun 		goto err_put_wkup_m3_ipc;
563*4882a593Smuzhiyun 	}
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	return 0;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun err_put_wkup_m3_ipc:
568*4882a593Smuzhiyun 	wkup_m3_ipc_put(m3_ipc);
569*4882a593Smuzhiyun err_unsetup_rtc:
570*4882a593Smuzhiyun 	iounmap(rtc_base_virt);
571*4882a593Smuzhiyun 	clk_put(rtc_fck);
572*4882a593Smuzhiyun err_free_sram:
573*4882a593Smuzhiyun 	am33xx_pm_free_sram();
574*4882a593Smuzhiyun 	pm33xx_dev = NULL;
575*4882a593Smuzhiyun 	return ret;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun 
am33xx_pm_remove(struct platform_device * pdev)578*4882a593Smuzhiyun static int am33xx_pm_remove(struct platform_device *pdev)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun 	if (pm_ops->deinit)
581*4882a593Smuzhiyun 		pm_ops->deinit();
582*4882a593Smuzhiyun 	suspend_set_ops(NULL);
583*4882a593Smuzhiyun 	wkup_m3_ipc_put(m3_ipc);
584*4882a593Smuzhiyun 	am33xx_pm_free_sram();
585*4882a593Smuzhiyun 	iounmap(rtc_base_virt);
586*4882a593Smuzhiyun 	clk_put(rtc_fck);
587*4882a593Smuzhiyun 	return 0;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun static struct platform_driver am33xx_pm_driver = {
591*4882a593Smuzhiyun 	.driver = {
592*4882a593Smuzhiyun 		.name   = "pm33xx",
593*4882a593Smuzhiyun 	},
594*4882a593Smuzhiyun 	.probe = am33xx_pm_probe,
595*4882a593Smuzhiyun 	.remove = am33xx_pm_remove,
596*4882a593Smuzhiyun };
597*4882a593Smuzhiyun module_platform_driver(am33xx_pm_driver);
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun MODULE_ALIAS("platform:pm33xx");
600*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
601*4882a593Smuzhiyun MODULE_DESCRIPTION("am33xx power management driver");
602