xref: /openbmc/linux/drivers/of/platform.c (revision 7dd65feb)
1 /*
2  *    Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
3  *			 <benh@kernel.crashing.org>
4  *    and		 Arnd Bergmann, IBM Corp.
5  *    Merged from powerpc/kernel/of_platform.c and
6  *    sparc{,64}/kernel/of_device.c by Stephen Rothwell
7  *
8  *  This program is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU General Public License
10  *  as published by the Free Software Foundation; either version
11  *  2 of the License, or (at your option) any later version.
12  *
13  */
14 #include <linux/errno.h>
15 #include <linux/module.h>
16 #include <linux/device.h>
17 #include <linux/of_device.h>
18 #include <linux/of_platform.h>
19 
20 extern struct device_attribute of_platform_device_attrs[];
21 
22 static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
23 {
24 	struct of_device *of_dev = to_of_device(dev);
25 	struct of_platform_driver *of_drv = to_of_platform_driver(drv);
26 	const struct of_device_id *matches = of_drv->match_table;
27 
28 	if (!matches)
29 		return 0;
30 
31 	return of_match_device(matches, of_dev) != NULL;
32 }
33 
34 static int of_platform_device_probe(struct device *dev)
35 {
36 	int error = -ENODEV;
37 	struct of_platform_driver *drv;
38 	struct of_device *of_dev;
39 	const struct of_device_id *match;
40 
41 	drv = to_of_platform_driver(dev->driver);
42 	of_dev = to_of_device(dev);
43 
44 	if (!drv->probe)
45 		return error;
46 
47 	of_dev_get(of_dev);
48 
49 	match = of_match_device(drv->match_table, of_dev);
50 	if (match)
51 		error = drv->probe(of_dev, match);
52 	if (error)
53 		of_dev_put(of_dev);
54 
55 	return error;
56 }
57 
58 static int of_platform_device_remove(struct device *dev)
59 {
60 	struct of_device *of_dev = to_of_device(dev);
61 	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
62 
63 	if (dev->driver && drv->remove)
64 		drv->remove(of_dev);
65 	return 0;
66 }
67 
68 static void of_platform_device_shutdown(struct device *dev)
69 {
70 	struct of_device *of_dev = to_of_device(dev);
71 	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
72 
73 	if (dev->driver && drv->shutdown)
74 		drv->shutdown(of_dev);
75 }
76 
77 #ifdef CONFIG_PM_SLEEP
78 
79 static int of_platform_legacy_suspend(struct device *dev, pm_message_t mesg)
80 {
81 	struct of_device *of_dev = to_of_device(dev);
82 	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
83 	int ret = 0;
84 
85 	if (dev->driver && drv->suspend)
86 		ret = drv->suspend(of_dev, mesg);
87 	return ret;
88 }
89 
90 static int of_platform_legacy_resume(struct device *dev)
91 {
92 	struct of_device *of_dev = to_of_device(dev);
93 	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
94 	int ret = 0;
95 
96 	if (dev->driver && drv->resume)
97 		ret = drv->resume(of_dev);
98 	return ret;
99 }
100 
101 static int of_platform_pm_prepare(struct device *dev)
102 {
103 	struct device_driver *drv = dev->driver;
104 	int ret = 0;
105 
106 	if (drv && drv->pm && drv->pm->prepare)
107 		ret = drv->pm->prepare(dev);
108 
109 	return ret;
110 }
111 
112 static void of_platform_pm_complete(struct device *dev)
113 {
114 	struct device_driver *drv = dev->driver;
115 
116 	if (drv && drv->pm && drv->pm->complete)
117 		drv->pm->complete(dev);
118 }
119 
120 #ifdef CONFIG_SUSPEND
121 
122 static int of_platform_pm_suspend(struct device *dev)
123 {
124 	struct device_driver *drv = dev->driver;
125 	int ret = 0;
126 
127 	if (!drv)
128 		return 0;
129 
130 	if (drv->pm) {
131 		if (drv->pm->suspend)
132 			ret = drv->pm->suspend(dev);
133 	} else {
134 		ret = of_platform_legacy_suspend(dev, PMSG_SUSPEND);
135 	}
136 
137 	return ret;
138 }
139 
140 static int of_platform_pm_suspend_noirq(struct device *dev)
141 {
142 	struct device_driver *drv = dev->driver;
143 	int ret = 0;
144 
145 	if (!drv)
146 		return 0;
147 
148 	if (drv->pm) {
149 		if (drv->pm->suspend_noirq)
150 			ret = drv->pm->suspend_noirq(dev);
151 	}
152 
153 	return ret;
154 }
155 
156 static int of_platform_pm_resume(struct device *dev)
157 {
158 	struct device_driver *drv = dev->driver;
159 	int ret = 0;
160 
161 	if (!drv)
162 		return 0;
163 
164 	if (drv->pm) {
165 		if (drv->pm->resume)
166 			ret = drv->pm->resume(dev);
167 	} else {
168 		ret = of_platform_legacy_resume(dev);
169 	}
170 
171 	return ret;
172 }
173 
174 static int of_platform_pm_resume_noirq(struct device *dev)
175 {
176 	struct device_driver *drv = dev->driver;
177 	int ret = 0;
178 
179 	if (!drv)
180 		return 0;
181 
182 	if (drv->pm) {
183 		if (drv->pm->resume_noirq)
184 			ret = drv->pm->resume_noirq(dev);
185 	}
186 
187 	return ret;
188 }
189 
190 #else /* !CONFIG_SUSPEND */
191 
192 #define of_platform_pm_suspend		NULL
193 #define of_platform_pm_resume		NULL
194 #define of_platform_pm_suspend_noirq	NULL
195 #define of_platform_pm_resume_noirq	NULL
196 
197 #endif /* !CONFIG_SUSPEND */
198 
199 #ifdef CONFIG_HIBERNATION
200 
201 static int of_platform_pm_freeze(struct device *dev)
202 {
203 	struct device_driver *drv = dev->driver;
204 	int ret = 0;
205 
206 	if (!drv)
207 		return 0;
208 
209 	if (drv->pm) {
210 		if (drv->pm->freeze)
211 			ret = drv->pm->freeze(dev);
212 	} else {
213 		ret = of_platform_legacy_suspend(dev, PMSG_FREEZE);
214 	}
215 
216 	return ret;
217 }
218 
219 static int of_platform_pm_freeze_noirq(struct device *dev)
220 {
221 	struct device_driver *drv = dev->driver;
222 	int ret = 0;
223 
224 	if (!drv)
225 		return 0;
226 
227 	if (drv->pm) {
228 		if (drv->pm->freeze_noirq)
229 			ret = drv->pm->freeze_noirq(dev);
230 	}
231 
232 	return ret;
233 }
234 
235 static int of_platform_pm_thaw(struct device *dev)
236 {
237 	struct device_driver *drv = dev->driver;
238 	int ret = 0;
239 
240 	if (!drv)
241 		return 0;
242 
243 	if (drv->pm) {
244 		if (drv->pm->thaw)
245 			ret = drv->pm->thaw(dev);
246 	} else {
247 		ret = of_platform_legacy_resume(dev);
248 	}
249 
250 	return ret;
251 }
252 
253 static int of_platform_pm_thaw_noirq(struct device *dev)
254 {
255 	struct device_driver *drv = dev->driver;
256 	int ret = 0;
257 
258 	if (!drv)
259 		return 0;
260 
261 	if (drv->pm) {
262 		if (drv->pm->thaw_noirq)
263 			ret = drv->pm->thaw_noirq(dev);
264 	}
265 
266 	return ret;
267 }
268 
269 static int of_platform_pm_poweroff(struct device *dev)
270 {
271 	struct device_driver *drv = dev->driver;
272 	int ret = 0;
273 
274 	if (!drv)
275 		return 0;
276 
277 	if (drv->pm) {
278 		if (drv->pm->poweroff)
279 			ret = drv->pm->poweroff(dev);
280 	} else {
281 		ret = of_platform_legacy_suspend(dev, PMSG_HIBERNATE);
282 	}
283 
284 	return ret;
285 }
286 
287 static int of_platform_pm_poweroff_noirq(struct device *dev)
288 {
289 	struct device_driver *drv = dev->driver;
290 	int ret = 0;
291 
292 	if (!drv)
293 		return 0;
294 
295 	if (drv->pm) {
296 		if (drv->pm->poweroff_noirq)
297 			ret = drv->pm->poweroff_noirq(dev);
298 	}
299 
300 	return ret;
301 }
302 
303 static int of_platform_pm_restore(struct device *dev)
304 {
305 	struct device_driver *drv = dev->driver;
306 	int ret = 0;
307 
308 	if (!drv)
309 		return 0;
310 
311 	if (drv->pm) {
312 		if (drv->pm->restore)
313 			ret = drv->pm->restore(dev);
314 	} else {
315 		ret = of_platform_legacy_resume(dev);
316 	}
317 
318 	return ret;
319 }
320 
321 static int of_platform_pm_restore_noirq(struct device *dev)
322 {
323 	struct device_driver *drv = dev->driver;
324 	int ret = 0;
325 
326 	if (!drv)
327 		return 0;
328 
329 	if (drv->pm) {
330 		if (drv->pm->restore_noirq)
331 			ret = drv->pm->restore_noirq(dev);
332 	}
333 
334 	return ret;
335 }
336 
337 #else /* !CONFIG_HIBERNATION */
338 
339 #define of_platform_pm_freeze		NULL
340 #define of_platform_pm_thaw		NULL
341 #define of_platform_pm_poweroff		NULL
342 #define of_platform_pm_restore		NULL
343 #define of_platform_pm_freeze_noirq	NULL
344 #define of_platform_pm_thaw_noirq		NULL
345 #define of_platform_pm_poweroff_noirq	NULL
346 #define of_platform_pm_restore_noirq	NULL
347 
348 #endif /* !CONFIG_HIBERNATION */
349 
350 static struct dev_pm_ops of_platform_dev_pm_ops = {
351 	.prepare = of_platform_pm_prepare,
352 	.complete = of_platform_pm_complete,
353 	.suspend = of_platform_pm_suspend,
354 	.resume = of_platform_pm_resume,
355 	.freeze = of_platform_pm_freeze,
356 	.thaw = of_platform_pm_thaw,
357 	.poweroff = of_platform_pm_poweroff,
358 	.restore = of_platform_pm_restore,
359 	.suspend_noirq = of_platform_pm_suspend_noirq,
360 	.resume_noirq = of_platform_pm_resume_noirq,
361 	.freeze_noirq = of_platform_pm_freeze_noirq,
362 	.thaw_noirq = of_platform_pm_thaw_noirq,
363 	.poweroff_noirq = of_platform_pm_poweroff_noirq,
364 	.restore_noirq = of_platform_pm_restore_noirq,
365 };
366 
367 #define OF_PLATFORM_PM_OPS_PTR	(&of_platform_dev_pm_ops)
368 
369 #else /* !CONFIG_PM_SLEEP */
370 
371 #define OF_PLATFORM_PM_OPS_PTR	NULL
372 
373 #endif /* !CONFIG_PM_SLEEP */
374 
375 int of_bus_type_init(struct bus_type *bus, const char *name)
376 {
377 	bus->name = name;
378 	bus->match = of_platform_bus_match;
379 	bus->probe = of_platform_device_probe;
380 	bus->remove = of_platform_device_remove;
381 	bus->shutdown = of_platform_device_shutdown;
382 	bus->dev_attrs = of_platform_device_attrs;
383 	bus->pm = OF_PLATFORM_PM_OPS_PTR;
384 	return bus_register(bus);
385 }
386 
387 int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
388 {
389 	/* initialize common driver fields */
390 	if (!drv->driver.name)
391 		drv->driver.name = drv->name;
392 	if (!drv->driver.owner)
393 		drv->driver.owner = drv->owner;
394 	drv->driver.bus = bus;
395 
396 	/* register with core */
397 	return driver_register(&drv->driver);
398 }
399 EXPORT_SYMBOL(of_register_driver);
400 
401 void of_unregister_driver(struct of_platform_driver *drv)
402 {
403 	driver_unregister(&drv->driver);
404 }
405 EXPORT_SYMBOL(of_unregister_driver);
406