xref: /linux/drivers/of/platform.c (revision 94a0cb1fc61ab7a0d47d268a7764374efeb2160b)
13f23de10SStephen Rothwell /*
23f23de10SStephen Rothwell  *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
33f23de10SStephen Rothwell  *			 <benh@kernel.crashing.org>
43f23de10SStephen Rothwell  *    and		 Arnd Bergmann, IBM Corp.
53f23de10SStephen Rothwell  *    Merged from powerpc/kernel/of_platform.c and
63f23de10SStephen Rothwell  *    sparc{,64}/kernel/of_device.c by Stephen Rothwell
73f23de10SStephen Rothwell  *
83f23de10SStephen Rothwell  *  This program is free software; you can redistribute it and/or
93f23de10SStephen Rothwell  *  modify it under the terms of the GNU General Public License
103f23de10SStephen Rothwell  *  as published by the Free Software Foundation; either version
113f23de10SStephen Rothwell  *  2 of the License, or (at your option) any later version.
123f23de10SStephen Rothwell  *
133f23de10SStephen Rothwell  */
143f23de10SStephen Rothwell #include <linux/errno.h>
155c457083SStephen Rothwell #include <linux/module.h>
163f23de10SStephen Rothwell #include <linux/device.h>
175fd200f3SGrant Likely #include <linux/dma-mapping.h>
1850ef5284SGrant Likely #include <linux/slab.h>
199e3288dcSGrant Likely #include <linux/of_address.h>
203f23de10SStephen Rothwell #include <linux/of_device.h>
219e3288dcSGrant Likely #include <linux/of_irq.h>
223f23de10SStephen Rothwell #include <linux/of_platform.h>
23eca39301SGrant Likely #include <linux/platform_device.h>
24eca39301SGrant Likely 
25eca39301SGrant Likely static int platform_driver_probe_shim(struct platform_device *pdev)
26eca39301SGrant Likely {
27eca39301SGrant Likely 	struct platform_driver *pdrv;
28eca39301SGrant Likely 	struct of_platform_driver *ofpdrv;
29eca39301SGrant Likely 	const struct of_device_id *match;
30eca39301SGrant Likely 
31eca39301SGrant Likely 	pdrv = container_of(pdev->dev.driver, struct platform_driver, driver);
32eca39301SGrant Likely 	ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver);
33c1b6d380SGrant Likely 
34c1b6d380SGrant Likely 	/* There is an unlikely chance that an of_platform driver might match
35c1b6d380SGrant Likely 	 * on a non-OF platform device.  If so, then of_match_device() will
36c1b6d380SGrant Likely 	 * come up empty.  Return -EINVAL in this case so other drivers get
37c1b6d380SGrant Likely 	 * the chance to bind. */
38eca39301SGrant Likely 	match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
39c1b6d380SGrant Likely 	return match ? ofpdrv->probe(pdev, match) : -EINVAL;
40eca39301SGrant Likely }
41eca39301SGrant Likely 
42eca39301SGrant Likely static void platform_driver_shutdown_shim(struct platform_device *pdev)
43eca39301SGrant Likely {
44eca39301SGrant Likely 	struct platform_driver *pdrv;
45eca39301SGrant Likely 	struct of_platform_driver *ofpdrv;
46eca39301SGrant Likely 
47eca39301SGrant Likely 	pdrv = container_of(pdev->dev.driver, struct platform_driver, driver);
48eca39301SGrant Likely 	ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver);
49eca39301SGrant Likely 	ofpdrv->shutdown(pdev);
50eca39301SGrant Likely }
51eca39301SGrant Likely 
52eca39301SGrant Likely /**
53eca39301SGrant Likely  * of_register_platform_driver
54eca39301SGrant Likely  */
55eca39301SGrant Likely int of_register_platform_driver(struct of_platform_driver *drv)
56eca39301SGrant Likely {
57eca39301SGrant Likely 	/* setup of_platform_driver to platform_driver adaptors */
58eca39301SGrant Likely 	drv->platform_driver.driver = drv->driver;
59eca39301SGrant Likely 	if (drv->probe)
60eca39301SGrant Likely 		drv->platform_driver.probe = platform_driver_probe_shim;
61eca39301SGrant Likely 	drv->platform_driver.remove = drv->remove;
62eca39301SGrant Likely 	if (drv->shutdown)
63eca39301SGrant Likely 		drv->platform_driver.shutdown = platform_driver_shutdown_shim;
64eca39301SGrant Likely 	drv->platform_driver.suspend = drv->suspend;
65eca39301SGrant Likely 	drv->platform_driver.resume = drv->resume;
66eca39301SGrant Likely 
67eca39301SGrant Likely 	return platform_driver_register(&drv->platform_driver);
68eca39301SGrant Likely }
69eca39301SGrant Likely EXPORT_SYMBOL(of_register_platform_driver);
70eca39301SGrant Likely 
71eca39301SGrant Likely void of_unregister_platform_driver(struct of_platform_driver *drv)
72eca39301SGrant Likely {
73eca39301SGrant Likely 	platform_driver_unregister(&drv->platform_driver);
74eca39301SGrant Likely }
75eca39301SGrant Likely EXPORT_SYMBOL(of_unregister_platform_driver);
763f23de10SStephen Rothwell 
77596c955cSGrant Likely #if defined(CONFIG_PPC_DCR)
78596c955cSGrant Likely #include <asm/dcr.h>
79596c955cSGrant Likely #endif
80596c955cSGrant Likely 
81140b932fSOlaf Hering extern struct device_attribute of_platform_device_attrs[];
82140b932fSOlaf Hering 
833f23de10SStephen Rothwell static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
843f23de10SStephen Rothwell {
85597b9d1eSGrant Likely 	const struct of_device_id *matches = drv->of_match_table;
863f23de10SStephen Rothwell 
873f23de10SStephen Rothwell 	if (!matches)
883f23de10SStephen Rothwell 		return 0;
893f23de10SStephen Rothwell 
9044504b2bSGrant Likely 	return of_match_device(matches, dev) != NULL;
913f23de10SStephen Rothwell }
923f23de10SStephen Rothwell 
933f23de10SStephen Rothwell static int of_platform_device_probe(struct device *dev)
943f23de10SStephen Rothwell {
953f23de10SStephen Rothwell 	int error = -ENODEV;
963f23de10SStephen Rothwell 	struct of_platform_driver *drv;
97*94a0cb1fSGrant Likely 	struct platform_device *of_dev;
983f23de10SStephen Rothwell 	const struct of_device_id *match;
993f23de10SStephen Rothwell 
1003f23de10SStephen Rothwell 	drv = to_of_platform_driver(dev->driver);
101*94a0cb1fSGrant Likely 	of_dev = to_platform_device(dev);
1023f23de10SStephen Rothwell 
1033f23de10SStephen Rothwell 	if (!drv->probe)
1043f23de10SStephen Rothwell 		return error;
1053f23de10SStephen Rothwell 
1063f23de10SStephen Rothwell 	of_dev_get(of_dev);
1073f23de10SStephen Rothwell 
10844504b2bSGrant Likely 	match = of_match_device(drv->driver.of_match_table, dev);
1093f23de10SStephen Rothwell 	if (match)
1103f23de10SStephen Rothwell 		error = drv->probe(of_dev, match);
1113f23de10SStephen Rothwell 	if (error)
1123f23de10SStephen Rothwell 		of_dev_put(of_dev);
1133f23de10SStephen Rothwell 
1143f23de10SStephen Rothwell 	return error;
1153f23de10SStephen Rothwell }
1163f23de10SStephen Rothwell 
1173f23de10SStephen Rothwell static int of_platform_device_remove(struct device *dev)
1183f23de10SStephen Rothwell {
119*94a0cb1fSGrant Likely 	struct platform_device *of_dev = to_platform_device(dev);
1203f23de10SStephen Rothwell 	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
1213f23de10SStephen Rothwell 
1223f23de10SStephen Rothwell 	if (dev->driver && drv->remove)
1233f23de10SStephen Rothwell 		drv->remove(of_dev);
1243f23de10SStephen Rothwell 	return 0;
1253f23de10SStephen Rothwell }
1263f23de10SStephen Rothwell 
127a09ad3c4SMichael Ellerman static void of_platform_device_shutdown(struct device *dev)
128a09ad3c4SMichael Ellerman {
129*94a0cb1fSGrant Likely 	struct platform_device *of_dev = to_platform_device(dev);
130a09ad3c4SMichael Ellerman 	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
131a09ad3c4SMichael Ellerman 
132a09ad3c4SMichael Ellerman 	if (dev->driver && drv->shutdown)
133a09ad3c4SMichael Ellerman 		drv->shutdown(of_dev);
134a09ad3c4SMichael Ellerman }
135a09ad3c4SMichael Ellerman 
136d35ef90bSAnton Vorontsov #ifdef CONFIG_PM_SLEEP
137d35ef90bSAnton Vorontsov 
138d35ef90bSAnton Vorontsov static int of_platform_legacy_suspend(struct device *dev, pm_message_t mesg)
139d35ef90bSAnton Vorontsov {
140*94a0cb1fSGrant Likely 	struct platform_device *of_dev = to_platform_device(dev);
141d35ef90bSAnton Vorontsov 	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
142d35ef90bSAnton Vorontsov 	int ret = 0;
143d35ef90bSAnton Vorontsov 
144d35ef90bSAnton Vorontsov 	if (dev->driver && drv->suspend)
145d35ef90bSAnton Vorontsov 		ret = drv->suspend(of_dev, mesg);
146d35ef90bSAnton Vorontsov 	return ret;
147d35ef90bSAnton Vorontsov }
148d35ef90bSAnton Vorontsov 
149d35ef90bSAnton Vorontsov static int of_platform_legacy_resume(struct device *dev)
150d35ef90bSAnton Vorontsov {
151*94a0cb1fSGrant Likely 	struct platform_device *of_dev = to_platform_device(dev);
152d35ef90bSAnton Vorontsov 	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
153d35ef90bSAnton Vorontsov 	int ret = 0;
154d35ef90bSAnton Vorontsov 
155d35ef90bSAnton Vorontsov 	if (dev->driver && drv->resume)
156d35ef90bSAnton Vorontsov 		ret = drv->resume(of_dev);
157d35ef90bSAnton Vorontsov 	return ret;
158d35ef90bSAnton Vorontsov }
159d35ef90bSAnton Vorontsov 
160d35ef90bSAnton Vorontsov static int of_platform_pm_prepare(struct device *dev)
161d35ef90bSAnton Vorontsov {
162d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
163d35ef90bSAnton Vorontsov 	int ret = 0;
164d35ef90bSAnton Vorontsov 
165d35ef90bSAnton Vorontsov 	if (drv && drv->pm && drv->pm->prepare)
166d35ef90bSAnton Vorontsov 		ret = drv->pm->prepare(dev);
167d35ef90bSAnton Vorontsov 
168d35ef90bSAnton Vorontsov 	return ret;
169d35ef90bSAnton Vorontsov }
170d35ef90bSAnton Vorontsov 
171d35ef90bSAnton Vorontsov static void of_platform_pm_complete(struct device *dev)
172d35ef90bSAnton Vorontsov {
173d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
174d35ef90bSAnton Vorontsov 
175d35ef90bSAnton Vorontsov 	if (drv && drv->pm && drv->pm->complete)
176d35ef90bSAnton Vorontsov 		drv->pm->complete(dev);
177d35ef90bSAnton Vorontsov }
178d35ef90bSAnton Vorontsov 
179d35ef90bSAnton Vorontsov #ifdef CONFIG_SUSPEND
180d35ef90bSAnton Vorontsov 
181d35ef90bSAnton Vorontsov static int of_platform_pm_suspend(struct device *dev)
182d35ef90bSAnton Vorontsov {
183d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
184d35ef90bSAnton Vorontsov 	int ret = 0;
185d35ef90bSAnton Vorontsov 
186d35ef90bSAnton Vorontsov 	if (!drv)
187d35ef90bSAnton Vorontsov 		return 0;
188d35ef90bSAnton Vorontsov 
189d35ef90bSAnton Vorontsov 	if (drv->pm) {
190d35ef90bSAnton Vorontsov 		if (drv->pm->suspend)
191d35ef90bSAnton Vorontsov 			ret = drv->pm->suspend(dev);
192d35ef90bSAnton Vorontsov 	} else {
193d35ef90bSAnton Vorontsov 		ret = of_platform_legacy_suspend(dev, PMSG_SUSPEND);
194d35ef90bSAnton Vorontsov 	}
195d35ef90bSAnton Vorontsov 
196d35ef90bSAnton Vorontsov 	return ret;
197d35ef90bSAnton Vorontsov }
198d35ef90bSAnton Vorontsov 
199d35ef90bSAnton Vorontsov static int of_platform_pm_suspend_noirq(struct device *dev)
200d35ef90bSAnton Vorontsov {
201d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
202d35ef90bSAnton Vorontsov 	int ret = 0;
203d35ef90bSAnton Vorontsov 
204d35ef90bSAnton Vorontsov 	if (!drv)
205d35ef90bSAnton Vorontsov 		return 0;
206d35ef90bSAnton Vorontsov 
207d35ef90bSAnton Vorontsov 	if (drv->pm) {
208d35ef90bSAnton Vorontsov 		if (drv->pm->suspend_noirq)
209d35ef90bSAnton Vorontsov 			ret = drv->pm->suspend_noirq(dev);
210d35ef90bSAnton Vorontsov 	}
211d35ef90bSAnton Vorontsov 
212d35ef90bSAnton Vorontsov 	return ret;
213d35ef90bSAnton Vorontsov }
214d35ef90bSAnton Vorontsov 
215d35ef90bSAnton Vorontsov static int of_platform_pm_resume(struct device *dev)
216d35ef90bSAnton Vorontsov {
217d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
218d35ef90bSAnton Vorontsov 	int ret = 0;
219d35ef90bSAnton Vorontsov 
220d35ef90bSAnton Vorontsov 	if (!drv)
221d35ef90bSAnton Vorontsov 		return 0;
222d35ef90bSAnton Vorontsov 
223d35ef90bSAnton Vorontsov 	if (drv->pm) {
224d35ef90bSAnton Vorontsov 		if (drv->pm->resume)
225d35ef90bSAnton Vorontsov 			ret = drv->pm->resume(dev);
226d35ef90bSAnton Vorontsov 	} else {
227d35ef90bSAnton Vorontsov 		ret = of_platform_legacy_resume(dev);
228d35ef90bSAnton Vorontsov 	}
229d35ef90bSAnton Vorontsov 
230d35ef90bSAnton Vorontsov 	return ret;
231d35ef90bSAnton Vorontsov }
232d35ef90bSAnton Vorontsov 
233d35ef90bSAnton Vorontsov static int of_platform_pm_resume_noirq(struct device *dev)
234d35ef90bSAnton Vorontsov {
235d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
236d35ef90bSAnton Vorontsov 	int ret = 0;
237d35ef90bSAnton Vorontsov 
238d35ef90bSAnton Vorontsov 	if (!drv)
239d35ef90bSAnton Vorontsov 		return 0;
240d35ef90bSAnton Vorontsov 
241d35ef90bSAnton Vorontsov 	if (drv->pm) {
242d35ef90bSAnton Vorontsov 		if (drv->pm->resume_noirq)
243d35ef90bSAnton Vorontsov 			ret = drv->pm->resume_noirq(dev);
244d35ef90bSAnton Vorontsov 	}
245d35ef90bSAnton Vorontsov 
246d35ef90bSAnton Vorontsov 	return ret;
247d35ef90bSAnton Vorontsov }
248d35ef90bSAnton Vorontsov 
249d35ef90bSAnton Vorontsov #else /* !CONFIG_SUSPEND */
250d35ef90bSAnton Vorontsov 
251d35ef90bSAnton Vorontsov #define of_platform_pm_suspend		NULL
252d35ef90bSAnton Vorontsov #define of_platform_pm_resume		NULL
253d35ef90bSAnton Vorontsov #define of_platform_pm_suspend_noirq	NULL
254d35ef90bSAnton Vorontsov #define of_platform_pm_resume_noirq	NULL
255d35ef90bSAnton Vorontsov 
256d35ef90bSAnton Vorontsov #endif /* !CONFIG_SUSPEND */
257d35ef90bSAnton Vorontsov 
258d35ef90bSAnton Vorontsov #ifdef CONFIG_HIBERNATION
259d35ef90bSAnton Vorontsov 
260d35ef90bSAnton Vorontsov static int of_platform_pm_freeze(struct device *dev)
261d35ef90bSAnton Vorontsov {
262d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
263d35ef90bSAnton Vorontsov 	int ret = 0;
264d35ef90bSAnton Vorontsov 
265d35ef90bSAnton Vorontsov 	if (!drv)
266d35ef90bSAnton Vorontsov 		return 0;
267d35ef90bSAnton Vorontsov 
268d35ef90bSAnton Vorontsov 	if (drv->pm) {
269d35ef90bSAnton Vorontsov 		if (drv->pm->freeze)
270d35ef90bSAnton Vorontsov 			ret = drv->pm->freeze(dev);
271d35ef90bSAnton Vorontsov 	} else {
272d35ef90bSAnton Vorontsov 		ret = of_platform_legacy_suspend(dev, PMSG_FREEZE);
273d35ef90bSAnton Vorontsov 	}
274d35ef90bSAnton Vorontsov 
275d35ef90bSAnton Vorontsov 	return ret;
276d35ef90bSAnton Vorontsov }
277d35ef90bSAnton Vorontsov 
278d35ef90bSAnton Vorontsov static int of_platform_pm_freeze_noirq(struct device *dev)
279d35ef90bSAnton Vorontsov {
280d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
281d35ef90bSAnton Vorontsov 	int ret = 0;
282d35ef90bSAnton Vorontsov 
283d35ef90bSAnton Vorontsov 	if (!drv)
284d35ef90bSAnton Vorontsov 		return 0;
285d35ef90bSAnton Vorontsov 
286d35ef90bSAnton Vorontsov 	if (drv->pm) {
287d35ef90bSAnton Vorontsov 		if (drv->pm->freeze_noirq)
288d35ef90bSAnton Vorontsov 			ret = drv->pm->freeze_noirq(dev);
289d35ef90bSAnton Vorontsov 	}
290d35ef90bSAnton Vorontsov 
291d35ef90bSAnton Vorontsov 	return ret;
292d35ef90bSAnton Vorontsov }
293d35ef90bSAnton Vorontsov 
294d35ef90bSAnton Vorontsov static int of_platform_pm_thaw(struct device *dev)
295d35ef90bSAnton Vorontsov {
296d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
297d35ef90bSAnton Vorontsov 	int ret = 0;
298d35ef90bSAnton Vorontsov 
299d35ef90bSAnton Vorontsov 	if (!drv)
300d35ef90bSAnton Vorontsov 		return 0;
301d35ef90bSAnton Vorontsov 
302d35ef90bSAnton Vorontsov 	if (drv->pm) {
303d35ef90bSAnton Vorontsov 		if (drv->pm->thaw)
304d35ef90bSAnton Vorontsov 			ret = drv->pm->thaw(dev);
305d35ef90bSAnton Vorontsov 	} else {
306d35ef90bSAnton Vorontsov 		ret = of_platform_legacy_resume(dev);
307d35ef90bSAnton Vorontsov 	}
308d35ef90bSAnton Vorontsov 
309d35ef90bSAnton Vorontsov 	return ret;
310d35ef90bSAnton Vorontsov }
311d35ef90bSAnton Vorontsov 
312d35ef90bSAnton Vorontsov static int of_platform_pm_thaw_noirq(struct device *dev)
313d35ef90bSAnton Vorontsov {
314d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
315d35ef90bSAnton Vorontsov 	int ret = 0;
316d35ef90bSAnton Vorontsov 
317d35ef90bSAnton Vorontsov 	if (!drv)
318d35ef90bSAnton Vorontsov 		return 0;
319d35ef90bSAnton Vorontsov 
320d35ef90bSAnton Vorontsov 	if (drv->pm) {
321d35ef90bSAnton Vorontsov 		if (drv->pm->thaw_noirq)
322d35ef90bSAnton Vorontsov 			ret = drv->pm->thaw_noirq(dev);
323d35ef90bSAnton Vorontsov 	}
324d35ef90bSAnton Vorontsov 
325d35ef90bSAnton Vorontsov 	return ret;
326d35ef90bSAnton Vorontsov }
327d35ef90bSAnton Vorontsov 
328d35ef90bSAnton Vorontsov static int of_platform_pm_poweroff(struct device *dev)
329d35ef90bSAnton Vorontsov {
330d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
331d35ef90bSAnton Vorontsov 	int ret = 0;
332d35ef90bSAnton Vorontsov 
333d35ef90bSAnton Vorontsov 	if (!drv)
334d35ef90bSAnton Vorontsov 		return 0;
335d35ef90bSAnton Vorontsov 
336d35ef90bSAnton Vorontsov 	if (drv->pm) {
337d35ef90bSAnton Vorontsov 		if (drv->pm->poweroff)
338d35ef90bSAnton Vorontsov 			ret = drv->pm->poweroff(dev);
339d35ef90bSAnton Vorontsov 	} else {
340d35ef90bSAnton Vorontsov 		ret = of_platform_legacy_suspend(dev, PMSG_HIBERNATE);
341d35ef90bSAnton Vorontsov 	}
342d35ef90bSAnton Vorontsov 
343d35ef90bSAnton Vorontsov 	return ret;
344d35ef90bSAnton Vorontsov }
345d35ef90bSAnton Vorontsov 
346d35ef90bSAnton Vorontsov static int of_platform_pm_poweroff_noirq(struct device *dev)
347d35ef90bSAnton Vorontsov {
348d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
349d35ef90bSAnton Vorontsov 	int ret = 0;
350d35ef90bSAnton Vorontsov 
351d35ef90bSAnton Vorontsov 	if (!drv)
352d35ef90bSAnton Vorontsov 		return 0;
353d35ef90bSAnton Vorontsov 
354d35ef90bSAnton Vorontsov 	if (drv->pm) {
355d35ef90bSAnton Vorontsov 		if (drv->pm->poweroff_noirq)
356d35ef90bSAnton Vorontsov 			ret = drv->pm->poweroff_noirq(dev);
357d35ef90bSAnton Vorontsov 	}
358d35ef90bSAnton Vorontsov 
359d35ef90bSAnton Vorontsov 	return ret;
360d35ef90bSAnton Vorontsov }
361d35ef90bSAnton Vorontsov 
362d35ef90bSAnton Vorontsov static int of_platform_pm_restore(struct device *dev)
363d35ef90bSAnton Vorontsov {
364d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
365d35ef90bSAnton Vorontsov 	int ret = 0;
366d35ef90bSAnton Vorontsov 
367d35ef90bSAnton Vorontsov 	if (!drv)
368d35ef90bSAnton Vorontsov 		return 0;
369d35ef90bSAnton Vorontsov 
370d35ef90bSAnton Vorontsov 	if (drv->pm) {
371d35ef90bSAnton Vorontsov 		if (drv->pm->restore)
372d35ef90bSAnton Vorontsov 			ret = drv->pm->restore(dev);
373d35ef90bSAnton Vorontsov 	} else {
374d35ef90bSAnton Vorontsov 		ret = of_platform_legacy_resume(dev);
375d35ef90bSAnton Vorontsov 	}
376d35ef90bSAnton Vorontsov 
377d35ef90bSAnton Vorontsov 	return ret;
378d35ef90bSAnton Vorontsov }
379d35ef90bSAnton Vorontsov 
380d35ef90bSAnton Vorontsov static int of_platform_pm_restore_noirq(struct device *dev)
381d35ef90bSAnton Vorontsov {
382d35ef90bSAnton Vorontsov 	struct device_driver *drv = dev->driver;
383d35ef90bSAnton Vorontsov 	int ret = 0;
384d35ef90bSAnton Vorontsov 
385d35ef90bSAnton Vorontsov 	if (!drv)
386d35ef90bSAnton Vorontsov 		return 0;
387d35ef90bSAnton Vorontsov 
388d35ef90bSAnton Vorontsov 	if (drv->pm) {
389d35ef90bSAnton Vorontsov 		if (drv->pm->restore_noirq)
390d35ef90bSAnton Vorontsov 			ret = drv->pm->restore_noirq(dev);
391d35ef90bSAnton Vorontsov 	}
392d35ef90bSAnton Vorontsov 
393d35ef90bSAnton Vorontsov 	return ret;
394d35ef90bSAnton Vorontsov }
395d35ef90bSAnton Vorontsov 
396d35ef90bSAnton Vorontsov #else /* !CONFIG_HIBERNATION */
397d35ef90bSAnton Vorontsov 
398d35ef90bSAnton Vorontsov #define of_platform_pm_freeze		NULL
399d35ef90bSAnton Vorontsov #define of_platform_pm_thaw		NULL
400d35ef90bSAnton Vorontsov #define of_platform_pm_poweroff		NULL
401d35ef90bSAnton Vorontsov #define of_platform_pm_restore		NULL
402d35ef90bSAnton Vorontsov #define of_platform_pm_freeze_noirq	NULL
403d35ef90bSAnton Vorontsov #define of_platform_pm_thaw_noirq		NULL
404d35ef90bSAnton Vorontsov #define of_platform_pm_poweroff_noirq	NULL
405d35ef90bSAnton Vorontsov #define of_platform_pm_restore_noirq	NULL
406d35ef90bSAnton Vorontsov 
407d35ef90bSAnton Vorontsov #endif /* !CONFIG_HIBERNATION */
408d35ef90bSAnton Vorontsov 
409d35ef90bSAnton Vorontsov static struct dev_pm_ops of_platform_dev_pm_ops = {
410d35ef90bSAnton Vorontsov 	.prepare = of_platform_pm_prepare,
411d35ef90bSAnton Vorontsov 	.complete = of_platform_pm_complete,
412d35ef90bSAnton Vorontsov 	.suspend = of_platform_pm_suspend,
413d35ef90bSAnton Vorontsov 	.resume = of_platform_pm_resume,
414d35ef90bSAnton Vorontsov 	.freeze = of_platform_pm_freeze,
415d35ef90bSAnton Vorontsov 	.thaw = of_platform_pm_thaw,
416d35ef90bSAnton Vorontsov 	.poweroff = of_platform_pm_poweroff,
417d35ef90bSAnton Vorontsov 	.restore = of_platform_pm_restore,
418d35ef90bSAnton Vorontsov 	.suspend_noirq = of_platform_pm_suspend_noirq,
419d35ef90bSAnton Vorontsov 	.resume_noirq = of_platform_pm_resume_noirq,
420d35ef90bSAnton Vorontsov 	.freeze_noirq = of_platform_pm_freeze_noirq,
421d35ef90bSAnton Vorontsov 	.thaw_noirq = of_platform_pm_thaw_noirq,
422d35ef90bSAnton Vorontsov 	.poweroff_noirq = of_platform_pm_poweroff_noirq,
423d35ef90bSAnton Vorontsov 	.restore_noirq = of_platform_pm_restore_noirq,
424d35ef90bSAnton Vorontsov };
425d35ef90bSAnton Vorontsov 
426d35ef90bSAnton Vorontsov #define OF_PLATFORM_PM_OPS_PTR	(&of_platform_dev_pm_ops)
427d35ef90bSAnton Vorontsov 
428d35ef90bSAnton Vorontsov #else /* !CONFIG_PM_SLEEP */
429d35ef90bSAnton Vorontsov 
430d35ef90bSAnton Vorontsov #define OF_PLATFORM_PM_OPS_PTR	NULL
431d35ef90bSAnton Vorontsov 
432d35ef90bSAnton Vorontsov #endif /* !CONFIG_PM_SLEEP */
433d35ef90bSAnton Vorontsov 
4343f23de10SStephen Rothwell int of_bus_type_init(struct bus_type *bus, const char *name)
4353f23de10SStephen Rothwell {
4363f23de10SStephen Rothwell 	bus->name = name;
4373f23de10SStephen Rothwell 	bus->match = of_platform_bus_match;
4383f23de10SStephen Rothwell 	bus->probe = of_platform_device_probe;
4393f23de10SStephen Rothwell 	bus->remove = of_platform_device_remove;
440a09ad3c4SMichael Ellerman 	bus->shutdown = of_platform_device_shutdown;
441140b932fSOlaf Hering 	bus->dev_attrs = of_platform_device_attrs;
442d35ef90bSAnton Vorontsov 	bus->pm = OF_PLATFORM_PM_OPS_PTR;
4433f23de10SStephen Rothwell 	return bus_register(bus);
4443f23de10SStephen Rothwell }
4455c457083SStephen Rothwell 
4465c457083SStephen Rothwell int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
4475c457083SStephen Rothwell {
448eca39301SGrant Likely 	/*
449eca39301SGrant Likely 	 * Temporary: of_platform_bus used to be distinct from the platform
450eca39301SGrant Likely 	 * bus.  It isn't anymore, and so drivers on the platform bus need
451eca39301SGrant Likely 	 * to be registered in a special way.
452eca39301SGrant Likely 	 *
453eca39301SGrant Likely 	 * After all of_platform_bus_type drivers are converted to
454eca39301SGrant Likely 	 * platform_drivers, this exception can be removed.
455eca39301SGrant Likely 	 */
456eca39301SGrant Likely 	if (bus == &platform_bus_type)
457eca39301SGrant Likely 		return of_register_platform_driver(drv);
4585c457083SStephen Rothwell 
4595c457083SStephen Rothwell 	/* register with core */
460eca39301SGrant Likely 	drv->driver.bus = bus;
4615c457083SStephen Rothwell 	return driver_register(&drv->driver);
4625c457083SStephen Rothwell }
4635c457083SStephen Rothwell EXPORT_SYMBOL(of_register_driver);
4645c457083SStephen Rothwell 
4655c457083SStephen Rothwell void of_unregister_driver(struct of_platform_driver *drv)
4665c457083SStephen Rothwell {
467eca39301SGrant Likely 	if (drv->driver.bus == &platform_bus_type)
468eca39301SGrant Likely 		of_unregister_platform_driver(drv);
469eca39301SGrant Likely 	else
4705c457083SStephen Rothwell 		driver_unregister(&drv->driver);
4715c457083SStephen Rothwell }
4725c457083SStephen Rothwell EXPORT_SYMBOL(of_unregister_driver);
4735fd200f3SGrant Likely 
4745fd200f3SGrant Likely #if !defined(CONFIG_SPARC)
4755fd200f3SGrant Likely /*
4765fd200f3SGrant Likely  * The following routines scan a subtree and registers a device for
4775fd200f3SGrant Likely  * each applicable node.
4785fd200f3SGrant Likely  *
4795fd200f3SGrant Likely  * Note: sparc doesn't use these routines because it has a different
4805fd200f3SGrant Likely  * mechanism for creating devices from device tree nodes.
4815fd200f3SGrant Likely  */
4825fd200f3SGrant Likely 
4835fd200f3SGrant Likely /**
48494c09319SGrant Likely  * of_device_make_bus_id - Use the device node data to assign a unique name
48594c09319SGrant Likely  * @dev: pointer to device structure that is linked to a device tree node
48694c09319SGrant Likely  *
48794c09319SGrant Likely  * This routine will first try using either the dcr-reg or the reg property
48894c09319SGrant Likely  * value to derive a unique name.  As a last resort it will use the node
48994c09319SGrant Likely  * name followed by a unique number.
49094c09319SGrant Likely  */
49194c09319SGrant Likely static void of_device_make_bus_id(struct device *dev)
49294c09319SGrant Likely {
49394c09319SGrant Likely 	static atomic_t bus_no_reg_magic;
49494c09319SGrant Likely 	struct device_node *node = dev->of_node;
49594c09319SGrant Likely 	const u32 *reg;
49694c09319SGrant Likely 	u64 addr;
49794c09319SGrant Likely 	int magic;
49894c09319SGrant Likely 
49994c09319SGrant Likely #ifdef CONFIG_PPC_DCR
50094c09319SGrant Likely 	/*
50194c09319SGrant Likely 	 * If it's a DCR based device, use 'd' for native DCRs
50294c09319SGrant Likely 	 * and 'D' for MMIO DCRs.
50394c09319SGrant Likely 	 */
50494c09319SGrant Likely 	reg = of_get_property(node, "dcr-reg", NULL);
50594c09319SGrant Likely 	if (reg) {
50694c09319SGrant Likely #ifdef CONFIG_PPC_DCR_NATIVE
50794c09319SGrant Likely 		dev_set_name(dev, "d%x.%s", *reg, node->name);
50894c09319SGrant Likely #else /* CONFIG_PPC_DCR_NATIVE */
50994c09319SGrant Likely 		u64 addr = of_translate_dcr_address(node, *reg, NULL);
51094c09319SGrant Likely 		if (addr != OF_BAD_ADDR) {
51194c09319SGrant Likely 			dev_set_name(dev, "D%llx.%s",
51294c09319SGrant Likely 				     (unsigned long long)addr, node->name);
51394c09319SGrant Likely 			return;
51494c09319SGrant Likely 		}
51594c09319SGrant Likely #endif /* !CONFIG_PPC_DCR_NATIVE */
51694c09319SGrant Likely 	}
51794c09319SGrant Likely #endif /* CONFIG_PPC_DCR */
51894c09319SGrant Likely 
51994c09319SGrant Likely 	/*
52094c09319SGrant Likely 	 * For MMIO, get the physical address
52194c09319SGrant Likely 	 */
52294c09319SGrant Likely 	reg = of_get_property(node, "reg", NULL);
52394c09319SGrant Likely 	if (reg) {
52494c09319SGrant Likely 		addr = of_translate_address(node, reg);
52594c09319SGrant Likely 		if (addr != OF_BAD_ADDR) {
52694c09319SGrant Likely 			dev_set_name(dev, "%llx.%s",
52794c09319SGrant Likely 				     (unsigned long long)addr, node->name);
52894c09319SGrant Likely 			return;
52994c09319SGrant Likely 		}
53094c09319SGrant Likely 	}
53194c09319SGrant Likely 
53294c09319SGrant Likely 	/*
53394c09319SGrant Likely 	 * No BusID, use the node name and add a globally incremented
53494c09319SGrant Likely 	 * counter (and pray...)
53594c09319SGrant Likely 	 */
53694c09319SGrant Likely 	magic = atomic_add_return(1, &bus_no_reg_magic);
53794c09319SGrant Likely 	dev_set_name(dev, "%s.%d", node->name, magic - 1);
53894c09319SGrant Likely }
53994c09319SGrant Likely 
54094c09319SGrant Likely /**
54194c09319SGrant Likely  * of_device_alloc - Allocate and initialize an of_device
54294c09319SGrant Likely  * @np: device node to assign to device
54394c09319SGrant Likely  * @bus_id: Name to assign to the device.  May be null to use default name.
54494c09319SGrant Likely  * @parent: Parent device.
54594c09319SGrant Likely  */
546*94a0cb1fSGrant Likely struct platform_device *of_device_alloc(struct device_node *np,
54794c09319SGrant Likely 				  const char *bus_id,
54894c09319SGrant Likely 				  struct device *parent)
54994c09319SGrant Likely {
550*94a0cb1fSGrant Likely 	struct platform_device *dev;
551ac80a51eSGrant Likely 	int rc, i, num_reg = 0, num_irq = 0;
552ac80a51eSGrant Likely 	struct resource *res, temp_res;
55394c09319SGrant Likely 
554ac80a51eSGrant Likely 	/* First count how many resources are needed */
555ac80a51eSGrant Likely 	while (of_address_to_resource(np, num_reg, &temp_res) == 0)
556ac80a51eSGrant Likely 		num_reg++;
557ac80a51eSGrant Likely 	while (of_irq_to_resource(np, num_irq, &temp_res) != NO_IRQ)
558ac80a51eSGrant Likely 		num_irq++;
559ac80a51eSGrant Likely 
560ac80a51eSGrant Likely 	/* Allocate memory for both the struct device and the resource table */
561ac80a51eSGrant Likely 	dev = kzalloc(sizeof(*dev) + (sizeof(*res) * (num_reg + num_irq)),
562ac80a51eSGrant Likely 		      GFP_KERNEL);
56394c09319SGrant Likely 	if (!dev)
56494c09319SGrant Likely 		return NULL;
565ac80a51eSGrant Likely 	res = (struct resource *) &dev[1];
566ac80a51eSGrant Likely 
567ac80a51eSGrant Likely 	/* Populate the resource table */
568ac80a51eSGrant Likely 	if (num_irq || num_reg) {
569ac80a51eSGrant Likely 		dev->num_resources = num_reg + num_irq;
570ac80a51eSGrant Likely 		dev->resource = res;
571ac80a51eSGrant Likely 		for (i = 0; i < num_reg; i++, res++) {
572ac80a51eSGrant Likely 			rc = of_address_to_resource(np, i, res);
573ac80a51eSGrant Likely 			WARN_ON(rc);
574ac80a51eSGrant Likely 		}
575ac80a51eSGrant Likely 		for (i = 0; i < num_irq; i++, res++) {
576ac80a51eSGrant Likely 			rc = of_irq_to_resource(np, i, res);
577ac80a51eSGrant Likely 			WARN_ON(rc == NO_IRQ);
578ac80a51eSGrant Likely 		}
579ac80a51eSGrant Likely 	}
58094c09319SGrant Likely 
58194c09319SGrant Likely 	dev->dev.of_node = of_node_get(np);
5829e3288dcSGrant Likely #if defined(CONFIG_PPC) || defined(CONFIG_MICROBLAZE)
58394c09319SGrant Likely 	dev->dev.dma_mask = &dev->archdata.dma_mask;
5849e3288dcSGrant Likely #endif
58594c09319SGrant Likely 	dev->dev.parent = parent;
58694c09319SGrant Likely 	dev->dev.release = of_release_dev;
58794c09319SGrant Likely 
58894c09319SGrant Likely 	if (bus_id)
58994c09319SGrant Likely 		dev_set_name(&dev->dev, "%s", bus_id);
59094c09319SGrant Likely 	else
59194c09319SGrant Likely 		of_device_make_bus_id(&dev->dev);
59294c09319SGrant Likely 
59394c09319SGrant Likely 	return dev;
59494c09319SGrant Likely }
59594c09319SGrant Likely EXPORT_SYMBOL(of_device_alloc);
59694c09319SGrant Likely 
59794c09319SGrant Likely /**
5985fd200f3SGrant Likely  * of_platform_device_create - Alloc, initialize and register an of_device
5995fd200f3SGrant Likely  * @np: pointer to node to create device for
6005fd200f3SGrant Likely  * @bus_id: name to assign device
6015fd200f3SGrant Likely  * @parent: Linux device model parent device.
6025fd200f3SGrant Likely  */
603*94a0cb1fSGrant Likely struct platform_device *of_platform_device_create(struct device_node *np,
6045fd200f3SGrant Likely 					    const char *bus_id,
6055fd200f3SGrant Likely 					    struct device *parent)
6065fd200f3SGrant Likely {
607*94a0cb1fSGrant Likely 	struct platform_device *dev;
6085fd200f3SGrant Likely 
6095fd200f3SGrant Likely 	dev = of_device_alloc(np, bus_id, parent);
6105fd200f3SGrant Likely 	if (!dev)
6115fd200f3SGrant Likely 		return NULL;
6125fd200f3SGrant Likely 
6139e3288dcSGrant Likely #if defined(CONFIG_PPC) || defined(CONFIG_MICROBLAZE)
6145fd200f3SGrant Likely 	dev->archdata.dma_mask = 0xffffffffUL;
6159e3288dcSGrant Likely #endif
6165fd200f3SGrant Likely 	dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
617eca39301SGrant Likely 	dev->dev.bus = &platform_bus_type;
6185fd200f3SGrant Likely 
6195fd200f3SGrant Likely 	/* We do not fill the DMA ops for platform devices by default.
6205fd200f3SGrant Likely 	 * This is currently the responsibility of the platform code
6215fd200f3SGrant Likely 	 * to do such, possibly using a device notifier
6225fd200f3SGrant Likely 	 */
6235fd200f3SGrant Likely 
6245fd200f3SGrant Likely 	if (of_device_register(dev) != 0) {
6255fd200f3SGrant Likely 		of_device_free(dev);
6265fd200f3SGrant Likely 		return NULL;
6275fd200f3SGrant Likely 	}
6285fd200f3SGrant Likely 
6295fd200f3SGrant Likely 	return dev;
6305fd200f3SGrant Likely }
6315fd200f3SGrant Likely EXPORT_SYMBOL(of_platform_device_create);
6325fd200f3SGrant Likely 
6335fd200f3SGrant Likely /**
6345fd200f3SGrant Likely  * of_platform_bus_create - Create an OF device for a bus node and all its
6355fd200f3SGrant Likely  * children. Optionally recursively instantiate matching busses.
6365fd200f3SGrant Likely  * @bus: device node of the bus to instantiate
6375fd200f3SGrant Likely  * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to
6385fd200f3SGrant Likely  * disallow recursive creation of child busses
6395fd200f3SGrant Likely  */
6405fd200f3SGrant Likely static int of_platform_bus_create(const struct device_node *bus,
6415fd200f3SGrant Likely 				  const struct of_device_id *matches,
6425fd200f3SGrant Likely 				  struct device *parent)
6435fd200f3SGrant Likely {
6445fd200f3SGrant Likely 	struct device_node *child;
645*94a0cb1fSGrant Likely 	struct platform_device *dev;
6465fd200f3SGrant Likely 	int rc = 0;
6475fd200f3SGrant Likely 
6485fd200f3SGrant Likely 	for_each_child_of_node(bus, child) {
6495fd200f3SGrant Likely 		pr_debug("   create child: %s\n", child->full_name);
6505fd200f3SGrant Likely 		dev = of_platform_device_create(child, NULL, parent);
6515fd200f3SGrant Likely 		if (dev == NULL)
6525fd200f3SGrant Likely 			rc = -ENOMEM;
6535fd200f3SGrant Likely 		else if (!of_match_node(matches, child))
6545fd200f3SGrant Likely 			continue;
6555fd200f3SGrant Likely 		if (rc == 0) {
6565fd200f3SGrant Likely 			pr_debug("   and sub busses\n");
6575fd200f3SGrant Likely 			rc = of_platform_bus_create(child, matches, &dev->dev);
6585fd200f3SGrant Likely 		}
6595fd200f3SGrant Likely 		if (rc) {
6605fd200f3SGrant Likely 			of_node_put(child);
6615fd200f3SGrant Likely 			break;
6625fd200f3SGrant Likely 		}
6635fd200f3SGrant Likely 	}
6645fd200f3SGrant Likely 	return rc;
6655fd200f3SGrant Likely }
6665fd200f3SGrant Likely 
6675fd200f3SGrant Likely /**
6685fd200f3SGrant Likely  * of_platform_bus_probe - Probe the device-tree for platform busses
6695fd200f3SGrant Likely  * @root: parent of the first level to probe or NULL for the root of the tree
6705fd200f3SGrant Likely  * @matches: match table, NULL to use the default
6715fd200f3SGrant Likely  * @parent: parent to hook devices from, NULL for toplevel
6725fd200f3SGrant Likely  *
6735fd200f3SGrant Likely  * Note that children of the provided root are not instantiated as devices
6745fd200f3SGrant Likely  * unless the specified root itself matches the bus list and is not NULL.
6755fd200f3SGrant Likely  */
6765fd200f3SGrant Likely int of_platform_bus_probe(struct device_node *root,
6775fd200f3SGrant Likely 			  const struct of_device_id *matches,
6785fd200f3SGrant Likely 			  struct device *parent)
6795fd200f3SGrant Likely {
6805fd200f3SGrant Likely 	struct device_node *child;
681*94a0cb1fSGrant Likely 	struct platform_device *dev;
6825fd200f3SGrant Likely 	int rc = 0;
6835fd200f3SGrant Likely 
6845fd200f3SGrant Likely 	if (matches == NULL)
6855fd200f3SGrant Likely 		matches = of_default_bus_ids;
6865fd200f3SGrant Likely 	if (matches == OF_NO_DEEP_PROBE)
6875fd200f3SGrant Likely 		return -EINVAL;
6885fd200f3SGrant Likely 	if (root == NULL)
6895fd200f3SGrant Likely 		root = of_find_node_by_path("/");
6905fd200f3SGrant Likely 	else
6915fd200f3SGrant Likely 		of_node_get(root);
69260d59913SGrant Likely 	if (root == NULL)
69360d59913SGrant Likely 		return -EINVAL;
6945fd200f3SGrant Likely 
6955fd200f3SGrant Likely 	pr_debug("of_platform_bus_probe()\n");
6965fd200f3SGrant Likely 	pr_debug(" starting at: %s\n", root->full_name);
6975fd200f3SGrant Likely 
6985fd200f3SGrant Likely 	/* Do a self check of bus type, if there's a match, create
6995fd200f3SGrant Likely 	 * children
7005fd200f3SGrant Likely 	 */
7015fd200f3SGrant Likely 	if (of_match_node(matches, root)) {
7025fd200f3SGrant Likely 		pr_debug(" root match, create all sub devices\n");
7035fd200f3SGrant Likely 		dev = of_platform_device_create(root, NULL, parent);
7045fd200f3SGrant Likely 		if (dev == NULL) {
7055fd200f3SGrant Likely 			rc = -ENOMEM;
7065fd200f3SGrant Likely 			goto bail;
7075fd200f3SGrant Likely 		}
7085fd200f3SGrant Likely 		pr_debug(" create all sub busses\n");
7095fd200f3SGrant Likely 		rc = of_platform_bus_create(root, matches, &dev->dev);
7105fd200f3SGrant Likely 		goto bail;
7115fd200f3SGrant Likely 	}
7125fd200f3SGrant Likely 	for_each_child_of_node(root, child) {
7135fd200f3SGrant Likely 		if (!of_match_node(matches, child))
7145fd200f3SGrant Likely 			continue;
7155fd200f3SGrant Likely 
7165fd200f3SGrant Likely 		pr_debug("  match: %s\n", child->full_name);
7175fd200f3SGrant Likely 		dev = of_platform_device_create(child, NULL, parent);
7185fd200f3SGrant Likely 		if (dev == NULL)
7195fd200f3SGrant Likely 			rc = -ENOMEM;
7205fd200f3SGrant Likely 		else
7215fd200f3SGrant Likely 			rc = of_platform_bus_create(child, matches, &dev->dev);
7225fd200f3SGrant Likely 		if (rc) {
7235fd200f3SGrant Likely 			of_node_put(child);
7245fd200f3SGrant Likely 			break;
7255fd200f3SGrant Likely 		}
7265fd200f3SGrant Likely 	}
7275fd200f3SGrant Likely  bail:
7285fd200f3SGrant Likely 	of_node_put(root);
7295fd200f3SGrant Likely 	return rc;
7305fd200f3SGrant Likely }
7315fd200f3SGrant Likely EXPORT_SYMBOL(of_platform_bus_probe);
7325fd200f3SGrant Likely #endif /* !CONFIG_SPARC */
733