xref: /openbmc/linux/arch/powerpc/sysdev/fsl_rcpm.c (revision 2874c5fd)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2d17799f9Schenhui zhao /*
3d17799f9Schenhui zhao  * RCPM(Run Control/Power Management) support
4d17799f9Schenhui zhao  *
5d17799f9Schenhui zhao  * Copyright 2012-2015 Freescale Semiconductor Inc.
6d17799f9Schenhui zhao  *
7d17799f9Schenhui zhao  * Author: Chenhui Zhao <chenhui.zhao@freescale.com>
8d17799f9Schenhui zhao  */
9d17799f9Schenhui zhao 
10d17799f9Schenhui zhao #define pr_fmt(fmt) "%s: " fmt, __func__
11d17799f9Schenhui zhao 
12d17799f9Schenhui zhao #include <linux/types.h>
13d17799f9Schenhui zhao #include <linux/errno.h>
14d17799f9Schenhui zhao #include <linux/of_address.h>
15d17799f9Schenhui zhao #include <linux/export.h>
16d17799f9Schenhui zhao 
17d17799f9Schenhui zhao #include <asm/io.h>
18d17799f9Schenhui zhao #include <linux/fsl/guts.h>
19d17799f9Schenhui zhao #include <asm/cputhreads.h>
20d17799f9Schenhui zhao #include <asm/fsl_pm.h>
21b081251eSMichael Ellerman #include <asm/smp.h>
22d17799f9Schenhui zhao 
23d17799f9Schenhui zhao static struct ccsr_rcpm_v1 __iomem *rcpm_v1_regs;
24d17799f9Schenhui zhao static struct ccsr_rcpm_v2 __iomem *rcpm_v2_regs;
25d17799f9Schenhui zhao static unsigned int fsl_supported_pm_modes;
26d17799f9Schenhui zhao 
rcpm_v1_irq_mask(int cpu)27d17799f9Schenhui zhao static void rcpm_v1_irq_mask(int cpu)
28d17799f9Schenhui zhao {
29d17799f9Schenhui zhao 	int hw_cpu = get_hard_smp_processor_id(cpu);
30d17799f9Schenhui zhao 	unsigned int mask = 1 << hw_cpu;
31d17799f9Schenhui zhao 
32d17799f9Schenhui zhao 	setbits32(&rcpm_v1_regs->cpmimr, mask);
33d17799f9Schenhui zhao 	setbits32(&rcpm_v1_regs->cpmcimr, mask);
34d17799f9Schenhui zhao 	setbits32(&rcpm_v1_regs->cpmmcmr, mask);
35d17799f9Schenhui zhao 	setbits32(&rcpm_v1_regs->cpmnmimr, mask);
36d17799f9Schenhui zhao }
37d17799f9Schenhui zhao 
rcpm_v2_irq_mask(int cpu)38d17799f9Schenhui zhao static void rcpm_v2_irq_mask(int cpu)
39d17799f9Schenhui zhao {
40d17799f9Schenhui zhao 	int hw_cpu = get_hard_smp_processor_id(cpu);
41d17799f9Schenhui zhao 	unsigned int mask = 1 << hw_cpu;
42d17799f9Schenhui zhao 
43d17799f9Schenhui zhao 	setbits32(&rcpm_v2_regs->tpmimr0, mask);
44d17799f9Schenhui zhao 	setbits32(&rcpm_v2_regs->tpmcimr0, mask);
45d17799f9Schenhui zhao 	setbits32(&rcpm_v2_regs->tpmmcmr0, mask);
46d17799f9Schenhui zhao 	setbits32(&rcpm_v2_regs->tpmnmimr0, mask);
47d17799f9Schenhui zhao }
48d17799f9Schenhui zhao 
rcpm_v1_irq_unmask(int cpu)49d17799f9Schenhui zhao static void rcpm_v1_irq_unmask(int cpu)
50d17799f9Schenhui zhao {
51d17799f9Schenhui zhao 	int hw_cpu = get_hard_smp_processor_id(cpu);
52d17799f9Schenhui zhao 	unsigned int mask = 1 << hw_cpu;
53d17799f9Schenhui zhao 
54d17799f9Schenhui zhao 	clrbits32(&rcpm_v1_regs->cpmimr, mask);
55d17799f9Schenhui zhao 	clrbits32(&rcpm_v1_regs->cpmcimr, mask);
56d17799f9Schenhui zhao 	clrbits32(&rcpm_v1_regs->cpmmcmr, mask);
57d17799f9Schenhui zhao 	clrbits32(&rcpm_v1_regs->cpmnmimr, mask);
58d17799f9Schenhui zhao }
59d17799f9Schenhui zhao 
rcpm_v2_irq_unmask(int cpu)60d17799f9Schenhui zhao static void rcpm_v2_irq_unmask(int cpu)
61d17799f9Schenhui zhao {
62d17799f9Schenhui zhao 	int hw_cpu = get_hard_smp_processor_id(cpu);
63d17799f9Schenhui zhao 	unsigned int mask = 1 << hw_cpu;
64d17799f9Schenhui zhao 
65d17799f9Schenhui zhao 	clrbits32(&rcpm_v2_regs->tpmimr0, mask);
66d17799f9Schenhui zhao 	clrbits32(&rcpm_v2_regs->tpmcimr0, mask);
67d17799f9Schenhui zhao 	clrbits32(&rcpm_v2_regs->tpmmcmr0, mask);
68d17799f9Schenhui zhao 	clrbits32(&rcpm_v2_regs->tpmnmimr0, mask);
69d17799f9Schenhui zhao }
70d17799f9Schenhui zhao 
rcpm_v1_set_ip_power(bool enable,u32 mask)71d17799f9Schenhui zhao static void rcpm_v1_set_ip_power(bool enable, u32 mask)
72d17799f9Schenhui zhao {
73d17799f9Schenhui zhao 	if (enable)
74d17799f9Schenhui zhao 		setbits32(&rcpm_v1_regs->ippdexpcr, mask);
75d17799f9Schenhui zhao 	else
76d17799f9Schenhui zhao 		clrbits32(&rcpm_v1_regs->ippdexpcr, mask);
77d17799f9Schenhui zhao }
78d17799f9Schenhui zhao 
rcpm_v2_set_ip_power(bool enable,u32 mask)79d17799f9Schenhui zhao static void rcpm_v2_set_ip_power(bool enable, u32 mask)
80d17799f9Schenhui zhao {
81d17799f9Schenhui zhao 	if (enable)
82d17799f9Schenhui zhao 		setbits32(&rcpm_v2_regs->ippdexpcr[0], mask);
83d17799f9Schenhui zhao 	else
84d17799f9Schenhui zhao 		clrbits32(&rcpm_v2_regs->ippdexpcr[0], mask);
85d17799f9Schenhui zhao }
86d17799f9Schenhui zhao 
rcpm_v1_cpu_enter_state(int cpu,int state)87d17799f9Schenhui zhao static void rcpm_v1_cpu_enter_state(int cpu, int state)
88d17799f9Schenhui zhao {
89d17799f9Schenhui zhao 	int hw_cpu = get_hard_smp_processor_id(cpu);
90d17799f9Schenhui zhao 	unsigned int mask = 1 << hw_cpu;
91d17799f9Schenhui zhao 
92d17799f9Schenhui zhao 	switch (state) {
93d17799f9Schenhui zhao 	case E500_PM_PH10:
94d17799f9Schenhui zhao 		setbits32(&rcpm_v1_regs->cdozcr, mask);
95d17799f9Schenhui zhao 		break;
96d17799f9Schenhui zhao 	case E500_PM_PH15:
97d17799f9Schenhui zhao 		setbits32(&rcpm_v1_regs->cnapcr, mask);
98d17799f9Schenhui zhao 		break;
99d17799f9Schenhui zhao 	default:
100d17799f9Schenhui zhao 		pr_warn("Unknown cpu PM state (%d)\n", state);
101d17799f9Schenhui zhao 		break;
102d17799f9Schenhui zhao 	}
103d17799f9Schenhui zhao }
104d17799f9Schenhui zhao 
rcpm_v2_cpu_enter_state(int cpu,int state)105d17799f9Schenhui zhao static void rcpm_v2_cpu_enter_state(int cpu, int state)
106d17799f9Schenhui zhao {
107d17799f9Schenhui zhao 	int hw_cpu = get_hard_smp_processor_id(cpu);
108d17799f9Schenhui zhao 	u32 mask = 1 << cpu_core_index_of_thread(cpu);
109d17799f9Schenhui zhao 
110d17799f9Schenhui zhao 	switch (state) {
111d17799f9Schenhui zhao 	case E500_PM_PH10:
112d17799f9Schenhui zhao 		/* one bit corresponds to one thread for PH10 of 6500 */
113d17799f9Schenhui zhao 		setbits32(&rcpm_v2_regs->tph10setr0, 1 << hw_cpu);
114d17799f9Schenhui zhao 		break;
115d17799f9Schenhui zhao 	case E500_PM_PH15:
116d17799f9Schenhui zhao 		setbits32(&rcpm_v2_regs->pcph15setr, mask);
117d17799f9Schenhui zhao 		break;
118d17799f9Schenhui zhao 	case E500_PM_PH20:
119d17799f9Schenhui zhao 		setbits32(&rcpm_v2_regs->pcph20setr, mask);
120d17799f9Schenhui zhao 		break;
121d17799f9Schenhui zhao 	case E500_PM_PH30:
122d17799f9Schenhui zhao 		setbits32(&rcpm_v2_regs->pcph30setr, mask);
123d17799f9Schenhui zhao 		break;
124d17799f9Schenhui zhao 	default:
125d17799f9Schenhui zhao 		pr_warn("Unknown cpu PM state (%d)\n", state);
126d17799f9Schenhui zhao 	}
127d17799f9Schenhui zhao }
128d17799f9Schenhui zhao 
rcpm_v1_cpu_die(int cpu)129d17799f9Schenhui zhao static void rcpm_v1_cpu_die(int cpu)
130d17799f9Schenhui zhao {
131d17799f9Schenhui zhao 	rcpm_v1_cpu_enter_state(cpu, E500_PM_PH15);
132d17799f9Schenhui zhao }
133d17799f9Schenhui zhao 
134d17799f9Schenhui zhao #ifdef CONFIG_PPC64
qoriq_disable_thread(int cpu)135d17799f9Schenhui zhao static void qoriq_disable_thread(int cpu)
136d17799f9Schenhui zhao {
137d17799f9Schenhui zhao 	int thread = cpu_thread_in_core(cpu);
138d17799f9Schenhui zhao 
139d17799f9Schenhui zhao 	book3e_stop_thread(thread);
140d17799f9Schenhui zhao }
141d17799f9Schenhui zhao #endif
142d17799f9Schenhui zhao 
rcpm_v2_cpu_die(int cpu)143d17799f9Schenhui zhao static void rcpm_v2_cpu_die(int cpu)
144d17799f9Schenhui zhao {
145d17799f9Schenhui zhao #ifdef CONFIG_PPC64
146d17799f9Schenhui zhao 	int primary;
147d17799f9Schenhui zhao 
148d17799f9Schenhui zhao 	if (threads_per_core == 2) {
149d17799f9Schenhui zhao 		primary = cpu_first_thread_sibling(cpu);
150d17799f9Schenhui zhao 		if (cpu_is_offline(primary) && cpu_is_offline(primary + 1)) {
151d17799f9Schenhui zhao 			/* if both threads are offline, put the cpu in PH20 */
152d17799f9Schenhui zhao 			rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20);
153d17799f9Schenhui zhao 		} else {
154d17799f9Schenhui zhao 			/* if only one thread is offline, disable the thread */
155d17799f9Schenhui zhao 			qoriq_disable_thread(cpu);
156d17799f9Schenhui zhao 		}
157d17799f9Schenhui zhao 	}
158d17799f9Schenhui zhao #endif
159d17799f9Schenhui zhao 
160d17799f9Schenhui zhao 	if (threads_per_core == 1)
161d17799f9Schenhui zhao 		rcpm_v2_cpu_enter_state(cpu, E500_PM_PH20);
162d17799f9Schenhui zhao }
163d17799f9Schenhui zhao 
rcpm_v1_cpu_exit_state(int cpu,int state)164d17799f9Schenhui zhao static void rcpm_v1_cpu_exit_state(int cpu, int state)
165d17799f9Schenhui zhao {
166d17799f9Schenhui zhao 	int hw_cpu = get_hard_smp_processor_id(cpu);
167d17799f9Schenhui zhao 	unsigned int mask = 1 << hw_cpu;
168d17799f9Schenhui zhao 
169d17799f9Schenhui zhao 	switch (state) {
170d17799f9Schenhui zhao 	case E500_PM_PH10:
171d17799f9Schenhui zhao 		clrbits32(&rcpm_v1_regs->cdozcr, mask);
172d17799f9Schenhui zhao 		break;
173d17799f9Schenhui zhao 	case E500_PM_PH15:
174d17799f9Schenhui zhao 		clrbits32(&rcpm_v1_regs->cnapcr, mask);
175d17799f9Schenhui zhao 		break;
176d17799f9Schenhui zhao 	default:
177d17799f9Schenhui zhao 		pr_warn("Unknown cpu PM state (%d)\n", state);
178d17799f9Schenhui zhao 		break;
179d17799f9Schenhui zhao 	}
180d17799f9Schenhui zhao }
181d17799f9Schenhui zhao 
rcpm_v1_cpu_up_prepare(int cpu)182d17799f9Schenhui zhao static void rcpm_v1_cpu_up_prepare(int cpu)
183d17799f9Schenhui zhao {
184d17799f9Schenhui zhao 	rcpm_v1_cpu_exit_state(cpu, E500_PM_PH15);
185d17799f9Schenhui zhao 	rcpm_v1_irq_unmask(cpu);
186d17799f9Schenhui zhao }
187d17799f9Schenhui zhao 
rcpm_v2_cpu_exit_state(int cpu,int state)188d17799f9Schenhui zhao static void rcpm_v2_cpu_exit_state(int cpu, int state)
189d17799f9Schenhui zhao {
190d17799f9Schenhui zhao 	int hw_cpu = get_hard_smp_processor_id(cpu);
191d17799f9Schenhui zhao 	u32 mask = 1 << cpu_core_index_of_thread(cpu);
192d17799f9Schenhui zhao 
193d17799f9Schenhui zhao 	switch (state) {
194d17799f9Schenhui zhao 	case E500_PM_PH10:
195d17799f9Schenhui zhao 		setbits32(&rcpm_v2_regs->tph10clrr0, 1 << hw_cpu);
196d17799f9Schenhui zhao 		break;
197d17799f9Schenhui zhao 	case E500_PM_PH15:
198d17799f9Schenhui zhao 		setbits32(&rcpm_v2_regs->pcph15clrr, mask);
199d17799f9Schenhui zhao 		break;
200d17799f9Schenhui zhao 	case E500_PM_PH20:
201d17799f9Schenhui zhao 		setbits32(&rcpm_v2_regs->pcph20clrr, mask);
202d17799f9Schenhui zhao 		break;
203d17799f9Schenhui zhao 	case E500_PM_PH30:
204d17799f9Schenhui zhao 		setbits32(&rcpm_v2_regs->pcph30clrr, mask);
205d17799f9Schenhui zhao 		break;
206d17799f9Schenhui zhao 	default:
207d17799f9Schenhui zhao 		pr_warn("Unknown cpu PM state (%d)\n", state);
208d17799f9Schenhui zhao 	}
209d17799f9Schenhui zhao }
210d17799f9Schenhui zhao 
rcpm_v2_cpu_up_prepare(int cpu)211d17799f9Schenhui zhao static void rcpm_v2_cpu_up_prepare(int cpu)
212d17799f9Schenhui zhao {
213d17799f9Schenhui zhao 	rcpm_v2_cpu_exit_state(cpu, E500_PM_PH20);
214d17799f9Schenhui zhao 	rcpm_v2_irq_unmask(cpu);
215d17799f9Schenhui zhao }
216d17799f9Schenhui zhao 
rcpm_v1_plat_enter_state(int state)217d17799f9Schenhui zhao static int rcpm_v1_plat_enter_state(int state)
218d17799f9Schenhui zhao {
219d17799f9Schenhui zhao 	u32 *pmcsr_reg = &rcpm_v1_regs->powmgtcsr;
220d17799f9Schenhui zhao 	int ret = 0;
221d17799f9Schenhui zhao 	int result;
222d17799f9Schenhui zhao 
223d17799f9Schenhui zhao 	switch (state) {
224d17799f9Schenhui zhao 	case PLAT_PM_SLEEP:
225d17799f9Schenhui zhao 		setbits32(pmcsr_reg, RCPM_POWMGTCSR_SLP);
226d17799f9Schenhui zhao 
227d17799f9Schenhui zhao 		/* Upon resume, wait for RCPM_POWMGTCSR_SLP bit to be clear. */
228d17799f9Schenhui zhao 		result = spin_event_timeout(
229d17799f9Schenhui zhao 		  !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_SLP), 10000, 10);
230d17799f9Schenhui zhao 		if (!result) {
231d17799f9Schenhui zhao 			pr_err("timeout waiting for SLP bit to be cleared\n");
232d17799f9Schenhui zhao 			ret = -ETIMEDOUT;
233d17799f9Schenhui zhao 		}
234d17799f9Schenhui zhao 		break;
235d17799f9Schenhui zhao 	default:
236d17799f9Schenhui zhao 		pr_warn("Unknown platform PM state (%d)", state);
237d17799f9Schenhui zhao 		ret = -EINVAL;
238d17799f9Schenhui zhao 	}
239d17799f9Schenhui zhao 
240d17799f9Schenhui zhao 	return ret;
241d17799f9Schenhui zhao }
242d17799f9Schenhui zhao 
rcpm_v2_plat_enter_state(int state)243d17799f9Schenhui zhao static int rcpm_v2_plat_enter_state(int state)
244d17799f9Schenhui zhao {
245d17799f9Schenhui zhao 	u32 *pmcsr_reg = &rcpm_v2_regs->powmgtcsr;
246d17799f9Schenhui zhao 	int ret = 0;
247d17799f9Schenhui zhao 	int result;
248d17799f9Schenhui zhao 
249d17799f9Schenhui zhao 	switch (state) {
250d17799f9Schenhui zhao 	case PLAT_PM_LPM20:
251d17799f9Schenhui zhao 		/* clear previous LPM20 status */
252d17799f9Schenhui zhao 		setbits32(pmcsr_reg, RCPM_POWMGTCSR_P_LPM20_ST);
253d17799f9Schenhui zhao 		/* enter LPM20 status */
254d17799f9Schenhui zhao 		setbits32(pmcsr_reg, RCPM_POWMGTCSR_LPM20_RQ);
255d17799f9Schenhui zhao 
256d17799f9Schenhui zhao 		/* At this point, the device is in LPM20 status. */
257d17799f9Schenhui zhao 
258d17799f9Schenhui zhao 		/* resume ... */
259d17799f9Schenhui zhao 		result = spin_event_timeout(
260d17799f9Schenhui zhao 		  !(in_be32(pmcsr_reg) & RCPM_POWMGTCSR_LPM20_ST), 10000, 10);
261d17799f9Schenhui zhao 		if (!result) {
262d17799f9Schenhui zhao 			pr_err("timeout waiting for LPM20 bit to be cleared\n");
263d17799f9Schenhui zhao 			ret = -ETIMEDOUT;
264d17799f9Schenhui zhao 		}
265d17799f9Schenhui zhao 		break;
266d17799f9Schenhui zhao 	default:
267d17799f9Schenhui zhao 		pr_warn("Unknown platform PM state (%d)\n", state);
268d17799f9Schenhui zhao 		ret = -EINVAL;
269d17799f9Schenhui zhao 	}
270d17799f9Schenhui zhao 
271d17799f9Schenhui zhao 	return ret;
272d17799f9Schenhui zhao }
273d17799f9Schenhui zhao 
rcpm_v1_plat_enter_sleep(void)274d17799f9Schenhui zhao static int rcpm_v1_plat_enter_sleep(void)
275d17799f9Schenhui zhao {
276d17799f9Schenhui zhao 	return rcpm_v1_plat_enter_state(PLAT_PM_SLEEP);
277d17799f9Schenhui zhao }
278d17799f9Schenhui zhao 
rcpm_v2_plat_enter_sleep(void)279d17799f9Schenhui zhao static int rcpm_v2_plat_enter_sleep(void)
280d17799f9Schenhui zhao {
281d17799f9Schenhui zhao 	return rcpm_v2_plat_enter_state(PLAT_PM_LPM20);
282d17799f9Schenhui zhao }
283d17799f9Schenhui zhao 
rcpm_common_freeze_time_base(u32 * tben_reg,int freeze)284d17799f9Schenhui zhao static void rcpm_common_freeze_time_base(u32 *tben_reg, int freeze)
285d17799f9Schenhui zhao {
286d17799f9Schenhui zhao 	static u32 mask;
287d17799f9Schenhui zhao 
288d17799f9Schenhui zhao 	if (freeze) {
289d17799f9Schenhui zhao 		mask = in_be32(tben_reg);
290d17799f9Schenhui zhao 		clrbits32(tben_reg, mask);
291d17799f9Schenhui zhao 	} else {
292d17799f9Schenhui zhao 		setbits32(tben_reg, mask);
293d17799f9Schenhui zhao 	}
294d17799f9Schenhui zhao 
295d17799f9Schenhui zhao 	/* read back to push the previous write */
296d17799f9Schenhui zhao 	in_be32(tben_reg);
297d17799f9Schenhui zhao }
298d17799f9Schenhui zhao 
rcpm_v1_freeze_time_base(bool freeze)299d17799f9Schenhui zhao static void rcpm_v1_freeze_time_base(bool freeze)
300d17799f9Schenhui zhao {
301d17799f9Schenhui zhao 	rcpm_common_freeze_time_base(&rcpm_v1_regs->ctbenr, freeze);
302d17799f9Schenhui zhao }
303d17799f9Schenhui zhao 
rcpm_v2_freeze_time_base(bool freeze)304d17799f9Schenhui zhao static void rcpm_v2_freeze_time_base(bool freeze)
305d17799f9Schenhui zhao {
306d17799f9Schenhui zhao 	rcpm_common_freeze_time_base(&rcpm_v2_regs->pctbenr, freeze);
307d17799f9Schenhui zhao }
308d17799f9Schenhui zhao 
rcpm_get_pm_modes(void)309d17799f9Schenhui zhao static unsigned int rcpm_get_pm_modes(void)
310d17799f9Schenhui zhao {
311d17799f9Schenhui zhao 	return fsl_supported_pm_modes;
312d17799f9Schenhui zhao }
313d17799f9Schenhui zhao 
314d17799f9Schenhui zhao static const struct fsl_pm_ops qoriq_rcpm_v1_ops = {
315d17799f9Schenhui zhao 	.irq_mask = rcpm_v1_irq_mask,
316d17799f9Schenhui zhao 	.irq_unmask = rcpm_v1_irq_unmask,
317d17799f9Schenhui zhao 	.cpu_enter_state = rcpm_v1_cpu_enter_state,
318d17799f9Schenhui zhao 	.cpu_exit_state = rcpm_v1_cpu_exit_state,
319d17799f9Schenhui zhao 	.cpu_up_prepare = rcpm_v1_cpu_up_prepare,
320d17799f9Schenhui zhao 	.cpu_die = rcpm_v1_cpu_die,
321d17799f9Schenhui zhao 	.plat_enter_sleep = rcpm_v1_plat_enter_sleep,
322d17799f9Schenhui zhao 	.set_ip_power = rcpm_v1_set_ip_power,
323d17799f9Schenhui zhao 	.freeze_time_base = rcpm_v1_freeze_time_base,
324d17799f9Schenhui zhao 	.get_pm_modes = rcpm_get_pm_modes,
325d17799f9Schenhui zhao };
326d17799f9Schenhui zhao 
327d17799f9Schenhui zhao static const struct fsl_pm_ops qoriq_rcpm_v2_ops = {
328d17799f9Schenhui zhao 	.irq_mask = rcpm_v2_irq_mask,
329d17799f9Schenhui zhao 	.irq_unmask = rcpm_v2_irq_unmask,
330d17799f9Schenhui zhao 	.cpu_enter_state = rcpm_v2_cpu_enter_state,
331d17799f9Schenhui zhao 	.cpu_exit_state = rcpm_v2_cpu_exit_state,
332d17799f9Schenhui zhao 	.cpu_up_prepare = rcpm_v2_cpu_up_prepare,
333d17799f9Schenhui zhao 	.cpu_die = rcpm_v2_cpu_die,
334d17799f9Schenhui zhao 	.plat_enter_sleep = rcpm_v2_plat_enter_sleep,
335d17799f9Schenhui zhao 	.set_ip_power = rcpm_v2_set_ip_power,
336d17799f9Schenhui zhao 	.freeze_time_base = rcpm_v2_freeze_time_base,
337d17799f9Schenhui zhao 	.get_pm_modes = rcpm_get_pm_modes,
338d17799f9Schenhui zhao };
339d17799f9Schenhui zhao 
340d17799f9Schenhui zhao static const struct of_device_id rcpm_matches[] = {
341d17799f9Schenhui zhao 	{
342d17799f9Schenhui zhao 		.compatible = "fsl,qoriq-rcpm-1.0",
343d17799f9Schenhui zhao 		.data = &qoriq_rcpm_v1_ops,
344d17799f9Schenhui zhao 	},
345d17799f9Schenhui zhao 	{
346d17799f9Schenhui zhao 		.compatible = "fsl,qoriq-rcpm-2.0",
347d17799f9Schenhui zhao 		.data = &qoriq_rcpm_v2_ops,
348d17799f9Schenhui zhao 	},
349d17799f9Schenhui zhao 	{
350d17799f9Schenhui zhao 		.compatible = "fsl,qoriq-rcpm-2.1",
351d17799f9Schenhui zhao 		.data = &qoriq_rcpm_v2_ops,
352d17799f9Schenhui zhao 	},
353d17799f9Schenhui zhao 	{},
354d17799f9Schenhui zhao };
355d17799f9Schenhui zhao 
fsl_rcpm_init(void)356d17799f9Schenhui zhao int __init fsl_rcpm_init(void)
357d17799f9Schenhui zhao {
358d17799f9Schenhui zhao 	struct device_node *np;
359d17799f9Schenhui zhao 	const struct of_device_id *match;
360d17799f9Schenhui zhao 	void __iomem *base;
361d17799f9Schenhui zhao 
362d17799f9Schenhui zhao 	np = of_find_matching_node_and_match(NULL, rcpm_matches, &match);
363d17799f9Schenhui zhao 	if (!np)
364d17799f9Schenhui zhao 		return 0;
365d17799f9Schenhui zhao 
366d17799f9Schenhui zhao 	base = of_iomap(np, 0);
367d17799f9Schenhui zhao 	of_node_put(np);
368d17799f9Schenhui zhao 	if (!base) {
369d17799f9Schenhui zhao 		pr_err("of_iomap() error.\n");
370d17799f9Schenhui zhao 		return -ENOMEM;
371d17799f9Schenhui zhao 	}
372d17799f9Schenhui zhao 
373d17799f9Schenhui zhao 	rcpm_v1_regs = base;
374d17799f9Schenhui zhao 	rcpm_v2_regs = base;
375d17799f9Schenhui zhao 
376d17799f9Schenhui zhao 	/* support sleep by default */
377d17799f9Schenhui zhao 	fsl_supported_pm_modes = FSL_PM_SLEEP;
378d17799f9Schenhui zhao 
379d17799f9Schenhui zhao 	qoriq_pm_ops = match->data;
380d17799f9Schenhui zhao 
381d17799f9Schenhui zhao 	return 0;
382d17799f9Schenhui zhao }
383