xref: /linux/drivers/base/platform.c (revision 9ce7677cfd7cd871adb457c80bea3b581b839641)
1 /*
2  * platform.c - platform 'pseudo' bus for legacy devices
3  *
4  * Copyright (c) 2002-3 Patrick Mochel
5  * Copyright (c) 2002-3 Open Source Development Labs
6  *
7  * This file is released under the GPLv2
8  *
9  * Please see Documentation/driver-model/platform.txt for more
10  * information.
11  */
12 
13 #include <linux/platform_device.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/bootmem.h>
18 #include <linux/err.h>
19 #include <linux/slab.h>
20 
21 #include "base.h"
22 
23 #define to_platform_driver(drv)	(container_of((drv), struct platform_driver, driver))
24 
25 struct device platform_bus = {
26 	.bus_id		= "platform",
27 };
28 
29 /**
30  *	platform_get_resource - get a resource for a device
31  *	@dev: platform device
32  *	@type: resource type
33  *	@num: resource index
34  */
35 struct resource *
36 platform_get_resource(struct platform_device *dev, unsigned int type,
37 		      unsigned int num)
38 {
39 	int i;
40 
41 	for (i = 0; i < dev->num_resources; i++) {
42 		struct resource *r = &dev->resource[i];
43 
44 		if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
45 				 IORESOURCE_IRQ|IORESOURCE_DMA))
46 		    == type)
47 			if (num-- == 0)
48 				return r;
49 	}
50 	return NULL;
51 }
52 
53 /**
54  *	platform_get_irq - get an IRQ for a device
55  *	@dev: platform device
56  *	@num: IRQ number index
57  */
58 int platform_get_irq(struct platform_device *dev, unsigned int num)
59 {
60 	struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
61 
62 	return r ? r->start : 0;
63 }
64 
65 /**
66  *	platform_get_resource_byname - get a resource for a device by name
67  *	@dev: platform device
68  *	@type: resource type
69  *	@name: resource name
70  */
71 struct resource *
72 platform_get_resource_byname(struct platform_device *dev, unsigned int type,
73 		      char *name)
74 {
75 	int i;
76 
77 	for (i = 0; i < dev->num_resources; i++) {
78 		struct resource *r = &dev->resource[i];
79 
80 		if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM|
81 				 IORESOURCE_IRQ|IORESOURCE_DMA)) == type)
82 			if (!strcmp(r->name, name))
83 				return r;
84 	}
85 	return NULL;
86 }
87 
88 /**
89  *	platform_get_irq - get an IRQ for a device
90  *	@dev: platform device
91  *	@name: IRQ name
92  */
93 int platform_get_irq_byname(struct platform_device *dev, char *name)
94 {
95 	struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
96 
97 	return r ? r->start : 0;
98 }
99 
100 /**
101  *	platform_add_devices - add a numbers of platform devices
102  *	@devs: array of platform devices to add
103  *	@num: number of platform devices in array
104  */
105 int platform_add_devices(struct platform_device **devs, int num)
106 {
107 	int i, ret = 0;
108 
109 	for (i = 0; i < num; i++) {
110 		ret = platform_device_register(devs[i]);
111 		if (ret) {
112 			while (--i >= 0)
113 				platform_device_unregister(devs[i]);
114 			break;
115 		}
116 	}
117 
118 	return ret;
119 }
120 
121 struct platform_object {
122 	struct platform_device pdev;
123 	char name[1];
124 };
125 
126 /**
127  *	platform_device_put
128  *	@pdev:	platform device to free
129  *
130  *	Free all memory associated with a platform device.  This function
131  *	must _only_ be externally called in error cases.  All other usage
132  *	is a bug.
133  */
134 void platform_device_put(struct platform_device *pdev)
135 {
136 	if (pdev)
137 		put_device(&pdev->dev);
138 }
139 EXPORT_SYMBOL_GPL(platform_device_put);
140 
141 static void platform_device_release(struct device *dev)
142 {
143 	struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev);
144 
145 	kfree(pa->pdev.dev.platform_data);
146 	kfree(pa->pdev.resource);
147 	kfree(pa);
148 }
149 
150 /**
151  *	platform_device_alloc
152  *	@name:	base name of the device we're adding
153  *	@id:    instance id
154  *
155  *	Create a platform device object which can have other objects attached
156  *	to it, and which will have attached objects freed when it is released.
157  */
158 struct platform_device *platform_device_alloc(const char *name, unsigned int id)
159 {
160 	struct platform_object *pa;
161 
162 	pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
163 	if (pa) {
164 		strcpy(pa->name, name);
165 		pa->pdev.name = pa->name;
166 		pa->pdev.id = id;
167 		device_initialize(&pa->pdev.dev);
168 		pa->pdev.dev.release = platform_device_release;
169 	}
170 
171 	return pa ? &pa->pdev : NULL;
172 }
173 EXPORT_SYMBOL_GPL(platform_device_alloc);
174 
175 /**
176  *	platform_device_add_resources
177  *	@pdev:	platform device allocated by platform_device_alloc to add resources to
178  *	@res:   set of resources that needs to be allocated for the device
179  *	@num:	number of resources
180  *
181  *	Add a copy of the resources to the platform device.  The memory
182  *	associated with the resources will be freed when the platform
183  *	device is released.
184  */
185 int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num)
186 {
187 	struct resource *r;
188 
189 	r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL);
190 	if (r) {
191 		memcpy(r, res, sizeof(struct resource) * num);
192 		pdev->resource = r;
193 		pdev->num_resources = num;
194 	}
195 	return r ? 0 : -ENOMEM;
196 }
197 EXPORT_SYMBOL_GPL(platform_device_add_resources);
198 
199 /**
200  *	platform_device_add_data
201  *	@pdev:	platform device allocated by platform_device_alloc to add resources to
202  *	@data:	platform specific data for this platform device
203  *	@size:	size of platform specific data
204  *
205  *	Add a copy of platform specific data to the platform device's platform_data
206  *	pointer.  The memory associated with the platform data will be freed
207  *	when the platform device is released.
208  */
209 int platform_device_add_data(struct platform_device *pdev, void *data, size_t size)
210 {
211 	void *d;
212 
213 	d = kmalloc(size, GFP_KERNEL);
214 	if (d) {
215 		memcpy(d, data, size);
216 		pdev->dev.platform_data = d;
217 	}
218 	return d ? 0 : -ENOMEM;
219 }
220 EXPORT_SYMBOL_GPL(platform_device_add_data);
221 
222 /**
223  *	platform_device_add - add a platform device to device hierarchy
224  *	@pdev:	platform device we're adding
225  *
226  *	This is part 2 of platform_device_register(), though may be called
227  *	separately _iff_ pdev was allocated by platform_device_alloc().
228  */
229 int platform_device_add(struct platform_device *pdev)
230 {
231 	int i, ret = 0;
232 
233 	if (!pdev)
234 		return -EINVAL;
235 
236 	if (!pdev->dev.parent)
237 		pdev->dev.parent = &platform_bus;
238 
239 	pdev->dev.bus = &platform_bus_type;
240 
241 	if (pdev->id != -1)
242 		snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
243 	else
244 		strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
245 
246 	for (i = 0; i < pdev->num_resources; i++) {
247 		struct resource *p, *r = &pdev->resource[i];
248 
249 		if (r->name == NULL)
250 			r->name = pdev->dev.bus_id;
251 
252 		p = r->parent;
253 		if (!p) {
254 			if (r->flags & IORESOURCE_MEM)
255 				p = &iomem_resource;
256 			else if (r->flags & IORESOURCE_IO)
257 				p = &ioport_resource;
258 		}
259 
260 		if (p && request_resource(p, r)) {
261 			printk(KERN_ERR
262 			       "%s: failed to claim resource %d\n",
263 			       pdev->dev.bus_id, i);
264 			ret = -EBUSY;
265 			goto failed;
266 		}
267 	}
268 
269 	pr_debug("Registering platform device '%s'. Parent at %s\n",
270 		 pdev->dev.bus_id, pdev->dev.parent->bus_id);
271 
272 	ret = device_register(&pdev->dev);
273 	if (ret == 0)
274 		return ret;
275 
276  failed:
277 	while (--i >= 0)
278 		if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
279 			release_resource(&pdev->resource[i]);
280 	return ret;
281 }
282 EXPORT_SYMBOL_GPL(platform_device_add);
283 
284 /**
285  *	platform_device_register - add a platform-level device
286  *	@pdev:	platform device we're adding
287  *
288  */
289 int platform_device_register(struct platform_device * pdev)
290 {
291 	device_initialize(&pdev->dev);
292 	return platform_device_add(pdev);
293 }
294 
295 /**
296  *	platform_device_unregister - remove a platform-level device
297  *	@pdev:	platform device we're removing
298  *
299  *	Note that this function will also release all memory- and port-based
300  *	resources owned by the device (@dev->resource).
301  */
302 void platform_device_unregister(struct platform_device * pdev)
303 {
304 	int i;
305 
306 	if (pdev) {
307 		for (i = 0; i < pdev->num_resources; i++) {
308 			struct resource *r = &pdev->resource[i];
309 			if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
310 				release_resource(r);
311 		}
312 
313 		device_unregister(&pdev->dev);
314 	}
315 }
316 
317 /**
318  *	platform_device_register_simple
319  *	@name:  base name of the device we're adding
320  *	@id:    instance id
321  *	@res:   set of resources that needs to be allocated for the device
322  *	@num:	number of resources
323  *
324  *	This function creates a simple platform device that requires minimal
325  *	resource and memory management. Canned release function freeing
326  *	memory allocated for the device allows drivers using such devices
327  *	to be unloaded iwithout waiting for the last reference to the device
328  *	to be dropped.
329  */
330 struct platform_device *platform_device_register_simple(char *name, unsigned int id,
331 							struct resource *res, unsigned int num)
332 {
333 	struct platform_device *pdev;
334 	int retval;
335 
336 	pdev = platform_device_alloc(name, id);
337 	if (!pdev) {
338 		retval = -ENOMEM;
339 		goto error;
340 	}
341 
342 	if (num) {
343 		retval = platform_device_add_resources(pdev, res, num);
344 		if (retval)
345 			goto error;
346 	}
347 
348 	retval = platform_device_add(pdev);
349 	if (retval)
350 		goto error;
351 
352 	return pdev;
353 
354 error:
355 	platform_device_put(pdev);
356 	return ERR_PTR(retval);
357 }
358 
359 static int platform_drv_probe(struct device *_dev)
360 {
361 	struct platform_driver *drv = to_platform_driver(_dev->driver);
362 	struct platform_device *dev = to_platform_device(_dev);
363 
364 	return drv->probe(dev);
365 }
366 
367 static int platform_drv_remove(struct device *_dev)
368 {
369 	struct platform_driver *drv = to_platform_driver(_dev->driver);
370 	struct platform_device *dev = to_platform_device(_dev);
371 
372 	return drv->remove(dev);
373 }
374 
375 static void platform_drv_shutdown(struct device *_dev)
376 {
377 	struct platform_driver *drv = to_platform_driver(_dev->driver);
378 	struct platform_device *dev = to_platform_device(_dev);
379 
380 	drv->shutdown(dev);
381 }
382 
383 static int platform_drv_suspend(struct device *_dev, pm_message_t state)
384 {
385 	struct platform_driver *drv = to_platform_driver(_dev->driver);
386 	struct platform_device *dev = to_platform_device(_dev);
387 
388 	return drv->suspend(dev, state);
389 }
390 
391 static int platform_drv_resume(struct device *_dev)
392 {
393 	struct platform_driver *drv = to_platform_driver(_dev->driver);
394 	struct platform_device *dev = to_platform_device(_dev);
395 
396 	return drv->resume(dev);
397 }
398 
399 /**
400  *	platform_driver_register
401  *	@drv: platform driver structure
402  */
403 int platform_driver_register(struct platform_driver *drv)
404 {
405 	drv->driver.bus = &platform_bus_type;
406 	if (drv->probe)
407 		drv->driver.probe = platform_drv_probe;
408 	if (drv->remove)
409 		drv->driver.remove = platform_drv_remove;
410 	if (drv->shutdown)
411 		drv->driver.shutdown = platform_drv_shutdown;
412 	if (drv->suspend)
413 		drv->driver.suspend = platform_drv_suspend;
414 	if (drv->resume)
415 		drv->driver.resume = platform_drv_resume;
416 	return driver_register(&drv->driver);
417 }
418 EXPORT_SYMBOL_GPL(platform_driver_register);
419 
420 /**
421  *	platform_driver_unregister
422  *	@drv: platform driver structure
423  */
424 void platform_driver_unregister(struct platform_driver *drv)
425 {
426 	driver_unregister(&drv->driver);
427 }
428 EXPORT_SYMBOL_GPL(platform_driver_unregister);
429 
430 
431 /**
432  *	platform_match - bind platform device to platform driver.
433  *	@dev:	device.
434  *	@drv:	driver.
435  *
436  *	Platform device IDs are assumed to be encoded like this:
437  *	"<name><instance>", where <name> is a short description of the
438  *	type of device, like "pci" or "floppy", and <instance> is the
439  *	enumerated instance of the device, like '0' or '42'.
440  *	Driver IDs are simply "<name>".
441  *	So, extract the <name> from the platform_device structure,
442  *	and compare it against the name of the driver. Return whether
443  *	they match or not.
444  */
445 
446 static int platform_match(struct device * dev, struct device_driver * drv)
447 {
448 	struct platform_device *pdev = container_of(dev, struct platform_device, dev);
449 
450 	return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
451 }
452 
453 static int platform_suspend(struct device * dev, pm_message_t state)
454 {
455 	int ret = 0;
456 
457 	if (dev->driver && dev->driver->suspend)
458 		ret = dev->driver->suspend(dev, state);
459 
460 	return ret;
461 }
462 
463 static int platform_resume(struct device * dev)
464 {
465 	int ret = 0;
466 
467 	if (dev->driver && dev->driver->resume)
468 		ret = dev->driver->resume(dev);
469 
470 	return ret;
471 }
472 
473 struct bus_type platform_bus_type = {
474 	.name		= "platform",
475 	.match		= platform_match,
476 	.suspend	= platform_suspend,
477 	.resume		= platform_resume,
478 };
479 
480 int __init platform_bus_init(void)
481 {
482 	device_register(&platform_bus);
483 	return bus_register(&platform_bus_type);
484 }
485 
486 #ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK
487 u64 dma_get_required_mask(struct device *dev)
488 {
489 	u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);
490 	u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT));
491 	u64 mask;
492 
493 	if (!high_totalram) {
494 		/* convert to mask just covering totalram */
495 		low_totalram = (1 << (fls(low_totalram) - 1));
496 		low_totalram += low_totalram - 1;
497 		mask = low_totalram;
498 	} else {
499 		high_totalram = (1 << (fls(high_totalram) - 1));
500 		high_totalram += high_totalram - 1;
501 		mask = (((u64)high_totalram) << 32) + 0xffffffff;
502 	}
503 	return mask & *dev->dma_mask;
504 }
505 EXPORT_SYMBOL_GPL(dma_get_required_mask);
506 #endif
507 
508 EXPORT_SYMBOL_GPL(platform_bus);
509 EXPORT_SYMBOL_GPL(platform_bus_type);
510 EXPORT_SYMBOL_GPL(platform_add_devices);
511 EXPORT_SYMBOL_GPL(platform_device_register);
512 EXPORT_SYMBOL_GPL(platform_device_register_simple);
513 EXPORT_SYMBOL_GPL(platform_device_unregister);
514 EXPORT_SYMBOL_GPL(platform_get_irq);
515 EXPORT_SYMBOL_GPL(platform_get_resource);
516 EXPORT_SYMBOL_GPL(platform_get_irq_byname);
517 EXPORT_SYMBOL_GPL(platform_get_resource_byname);
518