Linux Audio

Check our new training course

Loading...
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * MPC83xx suspend support
  4 *
  5 * Author: Scott Wood <scottwood@freescale.com>
  6 *
  7 * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
  8 */
  9
 10#include <linux/pm.h>
 11#include <linux/types.h>
 12#include <linux/ioport.h>
 13#include <linux/interrupt.h>
 14#include <linux/wait.h>
 15#include <linux/sched/signal.h>
 16#include <linux/kthread.h>
 17#include <linux/freezer.h>
 18#include <linux/suspend.h>
 19#include <linux/fsl_devices.h>
 20#include <linux/of_address.h>
 21#include <linux/of_irq.h>
 22#include <linux/platform_device.h>
 23#include <linux/export.h>
 24
 25#include <asm/reg.h>
 26#include <asm/io.h>
 27#include <asm/time.h>
 28#include <asm/mpc6xx.h>
 29#include <asm/switch_to.h>
 30
 31#include <sysdev/fsl_soc.h>
 32
 33#define PMCCR1_NEXT_STATE       0x0C /* Next state for power management */
 34#define PMCCR1_NEXT_STATE_SHIFT 2
 35#define PMCCR1_CURR_STATE       0x03 /* Current state for power management*/
 36#define IMMR_SYSCR_OFFSET       0x100
 37#define IMMR_RCW_OFFSET         0x900
 38#define RCW_PCI_HOST            0x80000000
 39
 40void mpc83xx_enter_deep_sleep(phys_addr_t immrbase);
 41
 42struct mpc83xx_pmc {
 43	u32 config;
 44#define PMCCR_DLPEN 2 /* DDR SDRAM low power enable */
 45#define PMCCR_SLPEN 1 /* System low power enable */
 46
 47	u32 event;
 48	u32 mask;
 49/* All but PMCI are deep-sleep only */
 50#define PMCER_GPIO   0x100
 51#define PMCER_PCI    0x080
 52#define PMCER_USB    0x040
 53#define PMCER_ETSEC1 0x020
 54#define PMCER_ETSEC2 0x010
 55#define PMCER_TIMER  0x008
 56#define PMCER_INT1   0x004
 57#define PMCER_INT2   0x002
 58#define PMCER_PMCI   0x001
 59#define PMCER_ALL    0x1FF
 60
 61	/* deep-sleep only */
 62	u32 config1;
 63#define PMCCR1_USE_STATE  0x80000000
 64#define PMCCR1_PME_EN     0x00000080
 65#define PMCCR1_ASSERT_PME 0x00000040
 66#define PMCCR1_POWER_OFF  0x00000020
 67
 68	/* deep-sleep only */
 69	u32 config2;
 70};
 71
 72struct mpc83xx_rcw {
 73	u32 rcwlr;
 74	u32 rcwhr;
 75};
 76
 77struct mpc83xx_clock {
 78	u32 spmr;
 79	u32 occr;
 80	u32 sccr;
 81};
 82
 83struct mpc83xx_syscr {
 84	__be32 sgprl;
 85	__be32 sgprh;
 86	__be32 spridr;
 87	__be32 :32;
 88	__be32 spcr;
 89	__be32 sicrl;
 90	__be32 sicrh;
 91};
 92
 93struct mpc83xx_saved {
 94	u32 sicrl;
 95	u32 sicrh;
 96	u32 sccr;
 97};
 98
 99struct pmc_type {
100	int has_deep_sleep;
101};
102
103static int has_deep_sleep, deep_sleeping;
104static int pmc_irq;
105static struct mpc83xx_pmc __iomem *pmc_regs;
106static struct mpc83xx_clock __iomem *clock_regs;
107static struct mpc83xx_syscr __iomem *syscr_regs;
108static struct mpc83xx_saved saved_regs;
109static int is_pci_agent, wake_from_pci;
110static phys_addr_t immrbase;
111static int pci_pm_state;
112static DECLARE_WAIT_QUEUE_HEAD(agent_wq);
113
114int fsl_deep_sleep(void)
115{
116	return deep_sleeping;
117}
118EXPORT_SYMBOL(fsl_deep_sleep);
119
120static int mpc83xx_change_state(void)
121{
122	u32 curr_state;
123	u32 reg_cfg1 = in_be32(&pmc_regs->config1);
124
125	if (is_pci_agent) {
126		pci_pm_state = (reg_cfg1 & PMCCR1_NEXT_STATE) >>
127		               PMCCR1_NEXT_STATE_SHIFT;
128		curr_state = reg_cfg1 & PMCCR1_CURR_STATE;
129
130		if (curr_state != pci_pm_state) {
131			reg_cfg1 &= ~PMCCR1_CURR_STATE;
132			reg_cfg1 |= pci_pm_state;
133			out_be32(&pmc_regs->config1, reg_cfg1);
134
135			wake_up(&agent_wq);
136			return 1;
137		}
138	}
139
140	return 0;
141}
142
143static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
144{
145	u32 event = in_be32(&pmc_regs->event);
146	int ret = IRQ_NONE;
147
148	if (mpc83xx_change_state())
149		ret = IRQ_HANDLED;
150
151	if (event) {
152		out_be32(&pmc_regs->event, event);
153		ret = IRQ_HANDLED;
154	}
155
156	return ret;
157}
158
159static void mpc83xx_suspend_restore_regs(void)
160{
161	out_be32(&syscr_regs->sicrl, saved_regs.sicrl);
162	out_be32(&syscr_regs->sicrh, saved_regs.sicrh);
163	out_be32(&clock_regs->sccr, saved_regs.sccr);
164}
165
166static void mpc83xx_suspend_save_regs(void)
167{
168	saved_regs.sicrl = in_be32(&syscr_regs->sicrl);
169	saved_regs.sicrh = in_be32(&syscr_regs->sicrh);
170	saved_regs.sccr = in_be32(&clock_regs->sccr);
171}
172
173static int mpc83xx_suspend_enter(suspend_state_t state)
174{
175	int ret = -EAGAIN;
176
177	/* Don't go to sleep if there's a race where pci_pm_state changes
178	 * between the agent thread checking it and the PM code disabling
179	 * interrupts.
180	 */
181	if (wake_from_pci) {
182		if (pci_pm_state != (deep_sleeping ? 3 : 2))
183			goto out;
184
185		out_be32(&pmc_regs->config1,
186		         in_be32(&pmc_regs->config1) | PMCCR1_PME_EN);
187	}
188
189	/* Put the system into low-power mode and the RAM
190	 * into self-refresh mode once the core goes to
191	 * sleep.
192	 */
193
194	out_be32(&pmc_regs->config, PMCCR_SLPEN | PMCCR_DLPEN);
195
196	/* If it has deep sleep (i.e. it's an 831x or compatible),
197	 * disable power to the core upon entering sleep mode.  This will
198	 * require going through the boot firmware upon a wakeup event.
199	 */
200
201	if (deep_sleeping) {
202		mpc83xx_suspend_save_regs();
203
204		out_be32(&pmc_regs->mask, PMCER_ALL);
205
206		out_be32(&pmc_regs->config1,
207		         in_be32(&pmc_regs->config1) | PMCCR1_POWER_OFF);
208
209		if (IS_ENABLED(CONFIG_PPC_FPU))
210			enable_kernel_fp();
211
212		mpc83xx_enter_deep_sleep(immrbase);
213
214		out_be32(&pmc_regs->config1,
215		         in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
216
217		out_be32(&pmc_regs->mask, PMCER_PMCI);
218
219		mpc83xx_suspend_restore_regs();
220	} else {
221		out_be32(&pmc_regs->mask, PMCER_PMCI);
222
223		mpc6xx_enter_standby();
224	}
225
226	ret = 0;
227
228out:
229	out_be32(&pmc_regs->config1,
230	         in_be32(&pmc_regs->config1) & ~PMCCR1_PME_EN);
231
232	return ret;
233}
234
235static void mpc83xx_suspend_end(void)
236{
237	deep_sleeping = 0;
238}
239
240static int mpc83xx_suspend_valid(suspend_state_t state)
241{
242	return state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM;
243}
244
245static int mpc83xx_suspend_begin(suspend_state_t state)
246{
247	switch (state) {
248		case PM_SUSPEND_STANDBY:
249			deep_sleeping = 0;
250			return 0;
251
252		case PM_SUSPEND_MEM:
253			if (has_deep_sleep)
254				deep_sleeping = 1;
255
256			return 0;
257
258		default:
259			return -EINVAL;
260	}
261}
262
263static int agent_thread_fn(void *data)
264{
265	set_freezable();
266
267	while (1) {
268		wait_event_freezable(agent_wq, pci_pm_state >= 2);
269
270		if (signal_pending(current) || pci_pm_state < 2)
271			continue;
272
273		/* With a preemptible kernel (or SMP), this could race with
274		 * a userspace-driven suspend request.  It's probably best
275		 * to avoid mixing the two with such a configuration (or
276		 * else fix it by adding a mutex to state_store that we can
277		 * synchronize with).
278		 */
279
280		wake_from_pci = 1;
281
282		pm_suspend(pci_pm_state == 3 ? PM_SUSPEND_MEM :
283		                               PM_SUSPEND_STANDBY);
284
285		wake_from_pci = 0;
286	}
287
288	return 0;
289}
290
291static void mpc83xx_set_agent(void)
292{
293	out_be32(&pmc_regs->config1, PMCCR1_USE_STATE);
294	out_be32(&pmc_regs->mask, PMCER_PMCI);
295
296	kthread_run(agent_thread_fn, NULL, "PCI power mgt");
297}
298
299static int mpc83xx_is_pci_agent(void)
300{
301	struct mpc83xx_rcw __iomem *rcw_regs;
302	int ret;
303
304	rcw_regs = ioremap(get_immrbase() + IMMR_RCW_OFFSET,
305	                   sizeof(struct mpc83xx_rcw));
306
307	if (!rcw_regs)
308		return -ENOMEM;
309
310	ret = !(in_be32(&rcw_regs->rcwhr) & RCW_PCI_HOST);
311
312	iounmap(rcw_regs);
313	return ret;
314}
315
316static const struct platform_suspend_ops mpc83xx_suspend_ops = {
317	.valid = mpc83xx_suspend_valid,
318	.begin = mpc83xx_suspend_begin,
319	.enter = mpc83xx_suspend_enter,
320	.end = mpc83xx_suspend_end,
321};
322
323static struct pmc_type pmc_types[] = {
324	{
325		.has_deep_sleep = 1,
326	},
327	{
328		.has_deep_sleep = 0,
329	}
330};
331
332static const struct of_device_id pmc_match[] = {
333	{
334		.compatible = "fsl,mpc8313-pmc",
335		.data = &pmc_types[0],
336	},
337	{
338		.compatible = "fsl,mpc8349-pmc",
339		.data = &pmc_types[1],
340	},
341	{}
342};
343
344static int pmc_probe(struct platform_device *ofdev)
345{
346	struct device_node *np = ofdev->dev.of_node;
347	struct resource res;
348	const struct pmc_type *type;
349	int ret = 0;
350
351	type = of_device_get_match_data(&ofdev->dev);
352	if (!type)
353		return -EINVAL;
354
355	if (!of_device_is_available(np))
356		return -ENODEV;
357
358	has_deep_sleep = type->has_deep_sleep;
359	immrbase = get_immrbase();
360
361	is_pci_agent = mpc83xx_is_pci_agent();
362	if (is_pci_agent < 0)
363		return is_pci_agent;
364
365	ret = of_address_to_resource(np, 0, &res);
366	if (ret)
367		return -ENODEV;
368
369	pmc_irq = irq_of_parse_and_map(np, 0);
370	if (pmc_irq) {
371		ret = request_irq(pmc_irq, pmc_irq_handler, IRQF_SHARED,
372		                  "pmc", ofdev);
373
374		if (ret)
375			return -EBUSY;
376	}
377
378	pmc_regs = ioremap(res.start, sizeof(*pmc_regs));
379
380	if (!pmc_regs) {
381		ret = -ENOMEM;
382		goto out;
383	}
384
385	ret = of_address_to_resource(np, 1, &res);
386	if (ret) {
387		ret = -ENODEV;
388		goto out_pmc;
389	}
390
391	clock_regs = ioremap(res.start, sizeof(*clock_regs));
392
393	if (!clock_regs) {
394		ret = -ENOMEM;
395		goto out_pmc;
396	}
397
398	if (has_deep_sleep) {
399		syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET,
400				     sizeof(*syscr_regs));
401		if (!syscr_regs) {
402			ret = -ENOMEM;
403			goto out_syscr;
404		}
405	}
406
407	if (is_pci_agent)
408		mpc83xx_set_agent();
409
410	suspend_set_ops(&mpc83xx_suspend_ops);
411	return 0;
412
413out_syscr:
414	iounmap(clock_regs);
415out_pmc:
416	iounmap(pmc_regs);
417out:
418	if (pmc_irq)
419		free_irq(pmc_irq, ofdev);
420
421	return ret;
422}
423
424static struct platform_driver pmc_driver = {
425	.driver = {
426		.name = "mpc83xx-pmc",
427		.of_match_table = pmc_match,
428		.suppress_bind_attrs = true,
429	},
430	.probe = pmc_probe,
431};
432
433builtin_platform_driver(pmc_driver);
  1/*
  2 * MPC83xx suspend support
  3 *
  4 * Author: Scott Wood <scottwood@freescale.com>
  5 *
  6 * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
  7 *
  8 * This program is free software; you can redistribute it and/or modify it
  9 * under the terms of the GNU General Public License version 2 as published
 10 * by the Free Software Foundation.
 11 */
 12
 13#include <linux/pm.h>
 14#include <linux/types.h>
 15#include <linux/ioport.h>
 16#include <linux/interrupt.h>
 17#include <linux/wait.h>
 18#include <linux/sched/signal.h>
 19#include <linux/kthread.h>
 20#include <linux/freezer.h>
 21#include <linux/suspend.h>
 22#include <linux/fsl_devices.h>
 23#include <linux/of_address.h>
 24#include <linux/of_irq.h>
 25#include <linux/of_platform.h>
 26#include <linux/export.h>
 27
 28#include <asm/reg.h>
 29#include <asm/io.h>
 30#include <asm/time.h>
 31#include <asm/mpc6xx.h>
 32#include <asm/switch_to.h>
 33
 34#include <sysdev/fsl_soc.h>
 35
 36#define PMCCR1_NEXT_STATE       0x0C /* Next state for power management */
 37#define PMCCR1_NEXT_STATE_SHIFT 2
 38#define PMCCR1_CURR_STATE       0x03 /* Current state for power management*/
 39#define IMMR_SYSCR_OFFSET       0x100
 40#define IMMR_RCW_OFFSET         0x900
 41#define RCW_PCI_HOST            0x80000000
 42
 43void mpc83xx_enter_deep_sleep(phys_addr_t immrbase);
 44
 45struct mpc83xx_pmc {
 46	u32 config;
 47#define PMCCR_DLPEN 2 /* DDR SDRAM low power enable */
 48#define PMCCR_SLPEN 1 /* System low power enable */
 49
 50	u32 event;
 51	u32 mask;
 52/* All but PMCI are deep-sleep only */
 53#define PMCER_GPIO   0x100
 54#define PMCER_PCI    0x080
 55#define PMCER_USB    0x040
 56#define PMCER_ETSEC1 0x020
 57#define PMCER_ETSEC2 0x010
 58#define PMCER_TIMER  0x008
 59#define PMCER_INT1   0x004
 60#define PMCER_INT2   0x002
 61#define PMCER_PMCI   0x001
 62#define PMCER_ALL    0x1FF
 63
 64	/* deep-sleep only */
 65	u32 config1;
 66#define PMCCR1_USE_STATE  0x80000000
 67#define PMCCR1_PME_EN     0x00000080
 68#define PMCCR1_ASSERT_PME 0x00000040
 69#define PMCCR1_POWER_OFF  0x00000020
 70
 71	/* deep-sleep only */
 72	u32 config2;
 73};
 74
 75struct mpc83xx_rcw {
 76	u32 rcwlr;
 77	u32 rcwhr;
 78};
 79
 80struct mpc83xx_clock {
 81	u32 spmr;
 82	u32 occr;
 83	u32 sccr;
 84};
 85
 86struct mpc83xx_syscr {
 87	__be32 sgprl;
 88	__be32 sgprh;
 89	__be32 spridr;
 90	__be32 :32;
 91	__be32 spcr;
 92	__be32 sicrl;
 93	__be32 sicrh;
 94};
 95
 96struct mpc83xx_saved {
 97	u32 sicrl;
 98	u32 sicrh;
 99	u32 sccr;
100};
101
102struct pmc_type {
103	int has_deep_sleep;
104};
105
106static struct platform_device *pmc_dev;
107static int has_deep_sleep, deep_sleeping;
108static int pmc_irq;
109static struct mpc83xx_pmc __iomem *pmc_regs;
110static struct mpc83xx_clock __iomem *clock_regs;
111static struct mpc83xx_syscr __iomem *syscr_regs;
112static struct mpc83xx_saved saved_regs;
113static int is_pci_agent, wake_from_pci;
114static phys_addr_t immrbase;
115static int pci_pm_state;
116static DECLARE_WAIT_QUEUE_HEAD(agent_wq);
117
118int fsl_deep_sleep(void)
119{
120	return deep_sleeping;
121}
122EXPORT_SYMBOL(fsl_deep_sleep);
123
124static int mpc83xx_change_state(void)
125{
126	u32 curr_state;
127	u32 reg_cfg1 = in_be32(&pmc_regs->config1);
128
129	if (is_pci_agent) {
130		pci_pm_state = (reg_cfg1 & PMCCR1_NEXT_STATE) >>
131		               PMCCR1_NEXT_STATE_SHIFT;
132		curr_state = reg_cfg1 & PMCCR1_CURR_STATE;
133
134		if (curr_state != pci_pm_state) {
135			reg_cfg1 &= ~PMCCR1_CURR_STATE;
136			reg_cfg1 |= pci_pm_state;
137			out_be32(&pmc_regs->config1, reg_cfg1);
138
139			wake_up(&agent_wq);
140			return 1;
141		}
142	}
143
144	return 0;
145}
146
147static irqreturn_t pmc_irq_handler(int irq, void *dev_id)
148{
149	u32 event = in_be32(&pmc_regs->event);
150	int ret = IRQ_NONE;
151
152	if (mpc83xx_change_state())
153		ret = IRQ_HANDLED;
154
155	if (event) {
156		out_be32(&pmc_regs->event, event);
157		ret = IRQ_HANDLED;
158	}
159
160	return ret;
161}
162
163static void mpc83xx_suspend_restore_regs(void)
164{
165	out_be32(&syscr_regs->sicrl, saved_regs.sicrl);
166	out_be32(&syscr_regs->sicrh, saved_regs.sicrh);
167	out_be32(&clock_regs->sccr, saved_regs.sccr);
168}
169
170static void mpc83xx_suspend_save_regs(void)
171{
172	saved_regs.sicrl = in_be32(&syscr_regs->sicrl);
173	saved_regs.sicrh = in_be32(&syscr_regs->sicrh);
174	saved_regs.sccr = in_be32(&clock_regs->sccr);
175}
176
177static int mpc83xx_suspend_enter(suspend_state_t state)
178{
179	int ret = -EAGAIN;
180
181	/* Don't go to sleep if there's a race where pci_pm_state changes
182	 * between the agent thread checking it and the PM code disabling
183	 * interrupts.
184	 */
185	if (wake_from_pci) {
186		if (pci_pm_state != (deep_sleeping ? 3 : 2))
187			goto out;
188
189		out_be32(&pmc_regs->config1,
190		         in_be32(&pmc_regs->config1) | PMCCR1_PME_EN);
191	}
192
193	/* Put the system into low-power mode and the RAM
194	 * into self-refresh mode once the core goes to
195	 * sleep.
196	 */
197
198	out_be32(&pmc_regs->config, PMCCR_SLPEN | PMCCR_DLPEN);
199
200	/* If it has deep sleep (i.e. it's an 831x or compatible),
201	 * disable power to the core upon entering sleep mode.  This will
202	 * require going through the boot firmware upon a wakeup event.
203	 */
204
205	if (deep_sleeping) {
206		mpc83xx_suspend_save_regs();
207
208		out_be32(&pmc_regs->mask, PMCER_ALL);
209
210		out_be32(&pmc_regs->config1,
211		         in_be32(&pmc_regs->config1) | PMCCR1_POWER_OFF);
212
213		enable_kernel_fp();
214
215		mpc83xx_enter_deep_sleep(immrbase);
216
217		out_be32(&pmc_regs->config1,
218		         in_be32(&pmc_regs->config1) & ~PMCCR1_POWER_OFF);
219
220		out_be32(&pmc_regs->mask, PMCER_PMCI);
221
222		mpc83xx_suspend_restore_regs();
223	} else {
224		out_be32(&pmc_regs->mask, PMCER_PMCI);
225
226		mpc6xx_enter_standby();
227	}
228
229	ret = 0;
230
231out:
232	out_be32(&pmc_regs->config1,
233	         in_be32(&pmc_regs->config1) & ~PMCCR1_PME_EN);
234
235	return ret;
236}
237
238static void mpc83xx_suspend_end(void)
239{
240	deep_sleeping = 0;
241}
242
243static int mpc83xx_suspend_valid(suspend_state_t state)
244{
245	return state == PM_SUSPEND_STANDBY || state == PM_SUSPEND_MEM;
246}
247
248static int mpc83xx_suspend_begin(suspend_state_t state)
249{
250	switch (state) {
251		case PM_SUSPEND_STANDBY:
252			deep_sleeping = 0;
253			return 0;
254
255		case PM_SUSPEND_MEM:
256			if (has_deep_sleep)
257				deep_sleeping = 1;
258
259			return 0;
260
261		default:
262			return -EINVAL;
263	}
264}
265
266static int agent_thread_fn(void *data)
267{
268	while (1) {
269		wait_event_interruptible(agent_wq, pci_pm_state >= 2);
270		try_to_freeze();
271
272		if (signal_pending(current) || pci_pm_state < 2)
273			continue;
274
275		/* With a preemptible kernel (or SMP), this could race with
276		 * a userspace-driven suspend request.  It's probably best
277		 * to avoid mixing the two with such a configuration (or
278		 * else fix it by adding a mutex to state_store that we can
279		 * synchronize with).
280		 */
281
282		wake_from_pci = 1;
283
284		pm_suspend(pci_pm_state == 3 ? PM_SUSPEND_MEM :
285		                               PM_SUSPEND_STANDBY);
286
287		wake_from_pci = 0;
288	}
289
290	return 0;
291}
292
293static void mpc83xx_set_agent(void)
294{
295	out_be32(&pmc_regs->config1, PMCCR1_USE_STATE);
296	out_be32(&pmc_regs->mask, PMCER_PMCI);
297
298	kthread_run(agent_thread_fn, NULL, "PCI power mgt");
299}
300
301static int mpc83xx_is_pci_agent(void)
302{
303	struct mpc83xx_rcw __iomem *rcw_regs;
304	int ret;
305
306	rcw_regs = ioremap(get_immrbase() + IMMR_RCW_OFFSET,
307	                   sizeof(struct mpc83xx_rcw));
308
309	if (!rcw_regs)
310		return -ENOMEM;
311
312	ret = !(in_be32(&rcw_regs->rcwhr) & RCW_PCI_HOST);
313
314	iounmap(rcw_regs);
315	return ret;
316}
317
318static const struct platform_suspend_ops mpc83xx_suspend_ops = {
319	.valid = mpc83xx_suspend_valid,
320	.begin = mpc83xx_suspend_begin,
321	.enter = mpc83xx_suspend_enter,
322	.end = mpc83xx_suspend_end,
323};
324
325static const struct of_device_id pmc_match[];
326static int pmc_probe(struct platform_device *ofdev)
327{
328	const struct of_device_id *match;
329	struct device_node *np = ofdev->dev.of_node;
330	struct resource res;
331	const struct pmc_type *type;
332	int ret = 0;
333
334	match = of_match_device(pmc_match, &ofdev->dev);
335	if (!match)
336		return -EINVAL;
337
338	type = match->data;
339
340	if (!of_device_is_available(np))
341		return -ENODEV;
342
343	has_deep_sleep = type->has_deep_sleep;
344	immrbase = get_immrbase();
345	pmc_dev = ofdev;
346
347	is_pci_agent = mpc83xx_is_pci_agent();
348	if (is_pci_agent < 0)
349		return is_pci_agent;
350
351	ret = of_address_to_resource(np, 0, &res);
352	if (ret)
353		return -ENODEV;
354
355	pmc_irq = irq_of_parse_and_map(np, 0);
356	if (pmc_irq) {
357		ret = request_irq(pmc_irq, pmc_irq_handler, IRQF_SHARED,
358		                  "pmc", ofdev);
359
360		if (ret)
361			return -EBUSY;
362	}
363
364	pmc_regs = ioremap(res.start, sizeof(*pmc_regs));
365
366	if (!pmc_regs) {
367		ret = -ENOMEM;
368		goto out;
369	}
370
371	ret = of_address_to_resource(np, 1, &res);
372	if (ret) {
373		ret = -ENODEV;
374		goto out_pmc;
375	}
376
377	clock_regs = ioremap(res.start, sizeof(*clock_regs));
378
379	if (!clock_regs) {
380		ret = -ENOMEM;
381		goto out_pmc;
382	}
383
384	if (has_deep_sleep) {
385		syscr_regs = ioremap(immrbase + IMMR_SYSCR_OFFSET,
386				     sizeof(*syscr_regs));
387		if (!syscr_regs) {
388			ret = -ENOMEM;
389			goto out_syscr;
390		}
391	}
392
393	if (is_pci_agent)
394		mpc83xx_set_agent();
395
396	suspend_set_ops(&mpc83xx_suspend_ops);
397	return 0;
398
399out_syscr:
400	iounmap(clock_regs);
401out_pmc:
402	iounmap(pmc_regs);
403out:
404	if (pmc_irq)
405		free_irq(pmc_irq, ofdev);
406
407	return ret;
408}
409
410static int pmc_remove(struct platform_device *ofdev)
411{
412	return -EPERM;
413};
414
415static struct pmc_type pmc_types[] = {
416	{
417		.has_deep_sleep = 1,
418	},
419	{
420		.has_deep_sleep = 0,
421	}
422};
423
424static const struct of_device_id pmc_match[] = {
425	{
426		.compatible = "fsl,mpc8313-pmc",
427		.data = &pmc_types[0],
428	},
429	{
430		.compatible = "fsl,mpc8349-pmc",
431		.data = &pmc_types[1],
432	},
433	{}
434};
435
436static struct platform_driver pmc_driver = {
437	.driver = {
438		.name = "mpc83xx-pmc",
439		.of_match_table = pmc_match,
440	},
441	.probe = pmc_probe,
442	.remove = pmc_remove
443};
444
445builtin_platform_driver(pmc_driver);