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