| .. | .. |
|---|
| 5 | 5 | * Copyright (c) 2002-3 Patrick Mochel |
|---|
| 6 | 6 | * Copyright (c) 2002-3 Open Source Development Labs |
|---|
| 7 | 7 | * |
|---|
| 8 | | - * Please see Documentation/driver-model/platform.txt for more |
|---|
| 8 | + * Please see Documentation/driver-api/driver-model/platform.rst for more |
|---|
| 9 | 9 | * information. |
|---|
| 10 | 10 | */ |
|---|
| 11 | 11 | |
|---|
| .. | .. |
|---|
| 16 | 16 | #include <linux/module.h> |
|---|
| 17 | 17 | #include <linux/init.h> |
|---|
| 18 | 18 | #include <linux/dma-mapping.h> |
|---|
| 19 | | -#include <linux/bootmem.h> |
|---|
| 19 | +#include <linux/memblock.h> |
|---|
| 20 | 20 | #include <linux/err.h> |
|---|
| 21 | 21 | #include <linux/slab.h> |
|---|
| 22 | 22 | #include <linux/pm_runtime.h> |
|---|
| .. | .. |
|---|
| 41 | 41 | EXPORT_SYMBOL_GPL(platform_bus); |
|---|
| 42 | 42 | |
|---|
| 43 | 43 | /** |
|---|
| 44 | | - * arch_setup_pdev_archdata - Allow manipulation of archdata before its used |
|---|
| 45 | | - * @pdev: platform device |
|---|
| 46 | | - * |
|---|
| 47 | | - * This is called before platform_device_add() such that any pdev_archdata may |
|---|
| 48 | | - * be setup before the platform_notifier is called. So if a user needs to |
|---|
| 49 | | - * manipulate any relevant information in the pdev_archdata they can do: |
|---|
| 50 | | - * |
|---|
| 51 | | - * platform_device_alloc() |
|---|
| 52 | | - * ... manipulate ... |
|---|
| 53 | | - * platform_device_add() |
|---|
| 54 | | - * |
|---|
| 55 | | - * And if they don't care they can just call platform_device_register() and |
|---|
| 56 | | - * everything will just work out. |
|---|
| 57 | | - */ |
|---|
| 58 | | -void __weak arch_setup_pdev_archdata(struct platform_device *pdev) |
|---|
| 59 | | -{ |
|---|
| 60 | | -} |
|---|
| 61 | | - |
|---|
| 62 | | -/** |
|---|
| 63 | 44 | * platform_get_resource - get a resource for a device |
|---|
| 64 | 45 | * @dev: platform device |
|---|
| 65 | 46 | * @type: resource type |
|---|
| 66 | 47 | * @num: resource index |
|---|
| 48 | + * |
|---|
| 49 | + * Return: a pointer to the resource or NULL on failure. |
|---|
| 67 | 50 | */ |
|---|
| 68 | 51 | struct resource *platform_get_resource(struct platform_device *dev, |
|---|
| 69 | 52 | unsigned int type, unsigned int num) |
|---|
| .. | .. |
|---|
| 80 | 63 | } |
|---|
| 81 | 64 | EXPORT_SYMBOL_GPL(platform_get_resource); |
|---|
| 82 | 65 | |
|---|
| 66 | +#ifdef CONFIG_HAS_IOMEM |
|---|
| 83 | 67 | /** |
|---|
| 84 | 68 | * devm_platform_get_and_ioremap_resource - call devm_ioremap_resource() for a |
|---|
| 85 | 69 | * platform device and get resource |
|---|
| .. | .. |
|---|
| 88 | 72 | * resource management |
|---|
| 89 | 73 | * @index: resource index |
|---|
| 90 | 74 | * @res: optional output parameter to store a pointer to the obtained resource. |
|---|
| 75 | + * |
|---|
| 76 | + * Return: a pointer to the remapped memory or an ERR_PTR() encoded error code |
|---|
| 77 | + * on failure. |
|---|
| 91 | 78 | */ |
|---|
| 92 | 79 | void __iomem * |
|---|
| 93 | 80 | devm_platform_get_and_ioremap_resource(struct platform_device *pdev, |
|---|
| .. | .. |
|---|
| 107 | 94 | * device |
|---|
| 108 | 95 | * |
|---|
| 109 | 96 | * @pdev: platform device to use both for memory resource lookup as well as |
|---|
| 110 | | - * resource managemend |
|---|
| 97 | + * resource management |
|---|
| 111 | 98 | * @index: resource index |
|---|
| 99 | + * |
|---|
| 100 | + * Return: a pointer to the remapped memory or an ERR_PTR() encoded error code |
|---|
| 101 | + * on failure. |
|---|
| 112 | 102 | */ |
|---|
| 113 | 103 | void __iomem *devm_platform_ioremap_resource(struct platform_device *pdev, |
|---|
| 114 | 104 | unsigned int index) |
|---|
| 115 | 105 | { |
|---|
| 116 | | - struct resource *res; |
|---|
| 117 | | - |
|---|
| 118 | | - res = platform_get_resource(pdev, IORESOURCE_MEM, index); |
|---|
| 119 | | - return devm_ioremap_resource(&pdev->dev, res); |
|---|
| 106 | + return devm_platform_get_and_ioremap_resource(pdev, index, NULL); |
|---|
| 120 | 107 | } |
|---|
| 121 | 108 | EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource); |
|---|
| 122 | 109 | |
|---|
| 123 | 110 | /** |
|---|
| 124 | | - * platform_get_irq - get an IRQ for a device |
|---|
| 111 | + * devm_platform_ioremap_resource_wc - write-combined variant of |
|---|
| 112 | + * devm_platform_ioremap_resource() |
|---|
| 113 | + * |
|---|
| 114 | + * @pdev: platform device to use both for memory resource lookup as well as |
|---|
| 115 | + * resource management |
|---|
| 116 | + * @index: resource index |
|---|
| 117 | + * |
|---|
| 118 | + * Return: a pointer to the remapped memory or an ERR_PTR() encoded error code |
|---|
| 119 | + * on failure. |
|---|
| 120 | + */ |
|---|
| 121 | +void __iomem *devm_platform_ioremap_resource_wc(struct platform_device *pdev, |
|---|
| 122 | + unsigned int index) |
|---|
| 123 | +{ |
|---|
| 124 | + struct resource *res; |
|---|
| 125 | + |
|---|
| 126 | + res = platform_get_resource(pdev, IORESOURCE_MEM, index); |
|---|
| 127 | + return devm_ioremap_resource_wc(&pdev->dev, res); |
|---|
| 128 | +} |
|---|
| 129 | + |
|---|
| 130 | +/** |
|---|
| 131 | + * devm_platform_ioremap_resource_byname - call devm_ioremap_resource for |
|---|
| 132 | + * a platform device, retrieve the |
|---|
| 133 | + * resource by name |
|---|
| 134 | + * |
|---|
| 135 | + * @pdev: platform device to use both for memory resource lookup as well as |
|---|
| 136 | + * resource management |
|---|
| 137 | + * @name: name of the resource |
|---|
| 138 | + * |
|---|
| 139 | + * Return: a pointer to the remapped memory or an ERR_PTR() encoded error code |
|---|
| 140 | + * on failure. |
|---|
| 141 | + */ |
|---|
| 142 | +void __iomem * |
|---|
| 143 | +devm_platform_ioremap_resource_byname(struct platform_device *pdev, |
|---|
| 144 | + const char *name) |
|---|
| 145 | +{ |
|---|
| 146 | + struct resource *res; |
|---|
| 147 | + |
|---|
| 148 | + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); |
|---|
| 149 | + return devm_ioremap_resource(&pdev->dev, res); |
|---|
| 150 | +} |
|---|
| 151 | +EXPORT_SYMBOL_GPL(devm_platform_ioremap_resource_byname); |
|---|
| 152 | +#endif /* CONFIG_HAS_IOMEM */ |
|---|
| 153 | + |
|---|
| 154 | +/** |
|---|
| 155 | + * platform_get_irq_optional - get an optional IRQ for a device |
|---|
| 125 | 156 | * @dev: platform device |
|---|
| 126 | 157 | * @num: IRQ number index |
|---|
| 158 | + * |
|---|
| 159 | + * Gets an IRQ for a platform device. Device drivers should check the return |
|---|
| 160 | + * value for errors so as to not pass a negative integer value to the |
|---|
| 161 | + * request_irq() APIs. This is the same as platform_get_irq(), except that it |
|---|
| 162 | + * does not print an error message if an IRQ can not be obtained. |
|---|
| 163 | + * |
|---|
| 164 | + * For example:: |
|---|
| 165 | + * |
|---|
| 166 | + * int irq = platform_get_irq_optional(pdev, 0); |
|---|
| 167 | + * if (irq < 0) |
|---|
| 168 | + * return irq; |
|---|
| 169 | + * |
|---|
| 170 | + * Return: non-zero IRQ number on success, negative error number on failure. |
|---|
| 127 | 171 | */ |
|---|
| 128 | | -int platform_get_irq(struct platform_device *dev, unsigned int num) |
|---|
| 172 | +int platform_get_irq_optional(struct platform_device *dev, unsigned int num) |
|---|
| 129 | 173 | { |
|---|
| 174 | + int ret; |
|---|
| 130 | 175 | #ifdef CONFIG_SPARC |
|---|
| 131 | 176 | /* sparc does not have irqs represented as IORESOURCE_IRQ resources */ |
|---|
| 132 | 177 | if (!dev || num >= dev->archdata.num_irqs) |
|---|
| 133 | 178 | return -ENXIO; |
|---|
| 134 | | - return dev->archdata.irqs[num]; |
|---|
| 179 | + ret = dev->archdata.irqs[num]; |
|---|
| 180 | + goto out; |
|---|
| 135 | 181 | #else |
|---|
| 136 | 182 | struct resource *r; |
|---|
| 137 | | - if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { |
|---|
| 138 | | - int ret; |
|---|
| 139 | 183 | |
|---|
| 184 | + if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { |
|---|
| 140 | 185 | ret = of_irq_get(dev->dev.of_node, num); |
|---|
| 141 | 186 | if (ret > 0 || ret == -EPROBE_DEFER) |
|---|
| 142 | | - return ret; |
|---|
| 187 | + goto out; |
|---|
| 143 | 188 | } |
|---|
| 144 | 189 | |
|---|
| 145 | 190 | r = platform_get_resource(dev, IORESOURCE_IRQ, num); |
|---|
| 146 | 191 | if (has_acpi_companion(&dev->dev)) { |
|---|
| 147 | 192 | if (r && r->flags & IORESOURCE_DISABLED) { |
|---|
| 148 | | - int ret; |
|---|
| 149 | | - |
|---|
| 150 | 193 | ret = acpi_irq_get(ACPI_HANDLE(&dev->dev), num, r); |
|---|
| 151 | 194 | if (ret) |
|---|
| 152 | | - return ret; |
|---|
| 195 | + goto out; |
|---|
| 153 | 196 | } |
|---|
| 154 | 197 | } |
|---|
| 155 | 198 | |
|---|
| .. | .. |
|---|
| 163 | 206 | struct irq_data *irqd; |
|---|
| 164 | 207 | |
|---|
| 165 | 208 | irqd = irq_get_irq_data(r->start); |
|---|
| 166 | | - if (!irqd) |
|---|
| 167 | | - return -ENXIO; |
|---|
| 209 | + if (!irqd) { |
|---|
| 210 | + ret = -ENXIO; |
|---|
| 211 | + goto out; |
|---|
| 212 | + } |
|---|
| 168 | 213 | irqd_set_trigger_type(irqd, r->flags & IORESOURCE_BITS); |
|---|
| 169 | 214 | } |
|---|
| 170 | 215 | |
|---|
| 171 | | - return r ? r->start : -ENXIO; |
|---|
| 216 | + if (r) { |
|---|
| 217 | + ret = r->start; |
|---|
| 218 | + goto out; |
|---|
| 219 | + } |
|---|
| 220 | + |
|---|
| 221 | + /* |
|---|
| 222 | + * For the index 0 interrupt, allow falling back to GpioInt |
|---|
| 223 | + * resources. While a device could have both Interrupt and GpioInt |
|---|
| 224 | + * resources, making this fallback ambiguous, in many common cases |
|---|
| 225 | + * the device will only expose one IRQ, and this fallback |
|---|
| 226 | + * allows a common code path across either kind of resource. |
|---|
| 227 | + */ |
|---|
| 228 | + if (num == 0 && has_acpi_companion(&dev->dev)) { |
|---|
| 229 | + ret = acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num); |
|---|
| 230 | + /* Our callers expect -ENXIO for missing IRQs. */ |
|---|
| 231 | + if (ret >= 0 || ret == -EPROBE_DEFER) |
|---|
| 232 | + goto out; |
|---|
| 233 | + } |
|---|
| 234 | + |
|---|
| 235 | + ret = -ENXIO; |
|---|
| 172 | 236 | #endif |
|---|
| 237 | +out: |
|---|
| 238 | + WARN(ret == 0, "0 is an invalid IRQ number\n"); |
|---|
| 239 | + return ret; |
|---|
| 240 | +} |
|---|
| 241 | +EXPORT_SYMBOL_GPL(platform_get_irq_optional); |
|---|
| 242 | + |
|---|
| 243 | +/** |
|---|
| 244 | + * platform_get_irq - get an IRQ for a device |
|---|
| 245 | + * @dev: platform device |
|---|
| 246 | + * @num: IRQ number index |
|---|
| 247 | + * |
|---|
| 248 | + * Gets an IRQ for a platform device and prints an error message if finding the |
|---|
| 249 | + * IRQ fails. Device drivers should check the return value for errors so as to |
|---|
| 250 | + * not pass a negative integer value to the request_irq() APIs. |
|---|
| 251 | + * |
|---|
| 252 | + * For example:: |
|---|
| 253 | + * |
|---|
| 254 | + * int irq = platform_get_irq(pdev, 0); |
|---|
| 255 | + * if (irq < 0) |
|---|
| 256 | + * return irq; |
|---|
| 257 | + * |
|---|
| 258 | + * Return: non-zero IRQ number on success, negative error number on failure. |
|---|
| 259 | + */ |
|---|
| 260 | +int platform_get_irq(struct platform_device *dev, unsigned int num) |
|---|
| 261 | +{ |
|---|
| 262 | + int ret; |
|---|
| 263 | + |
|---|
| 264 | + ret = platform_get_irq_optional(dev, num); |
|---|
| 265 | + if (ret < 0 && ret != -EPROBE_DEFER) |
|---|
| 266 | + dev_err(&dev->dev, "IRQ index %u not found\n", num); |
|---|
| 267 | + |
|---|
| 268 | + return ret; |
|---|
| 173 | 269 | } |
|---|
| 174 | 270 | EXPORT_SYMBOL_GPL(platform_get_irq); |
|---|
| 175 | 271 | |
|---|
| .. | .. |
|---|
| 183 | 279 | { |
|---|
| 184 | 280 | int ret, nr = 0; |
|---|
| 185 | 281 | |
|---|
| 186 | | - while ((ret = platform_get_irq(dev, nr)) >= 0) |
|---|
| 282 | + while ((ret = platform_get_irq_optional(dev, nr)) >= 0) |
|---|
| 187 | 283 | nr++; |
|---|
| 188 | 284 | |
|---|
| 189 | 285 | if (ret == -EPROBE_DEFER) |
|---|
| .. | .. |
|---|
| 218 | 314 | } |
|---|
| 219 | 315 | EXPORT_SYMBOL_GPL(platform_get_resource_byname); |
|---|
| 220 | 316 | |
|---|
| 221 | | -/** |
|---|
| 222 | | - * platform_get_irq_byname - get an IRQ for a device by name |
|---|
| 223 | | - * @dev: platform device |
|---|
| 224 | | - * @name: IRQ name |
|---|
| 225 | | - */ |
|---|
| 226 | | -int platform_get_irq_byname(struct platform_device *dev, const char *name) |
|---|
| 317 | +static int __platform_get_irq_byname(struct platform_device *dev, |
|---|
| 318 | + const char *name) |
|---|
| 227 | 319 | { |
|---|
| 228 | 320 | struct resource *r; |
|---|
| 321 | + int ret; |
|---|
| 229 | 322 | |
|---|
| 230 | 323 | if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { |
|---|
| 231 | | - int ret; |
|---|
| 232 | | - |
|---|
| 233 | 324 | ret = of_irq_get_byname(dev->dev.of_node, name); |
|---|
| 234 | 325 | if (ret > 0 || ret == -EPROBE_DEFER) |
|---|
| 235 | 326 | return ret; |
|---|
| 236 | 327 | } |
|---|
| 237 | 328 | |
|---|
| 238 | 329 | r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name); |
|---|
| 239 | | - return r ? r->start : -ENXIO; |
|---|
| 330 | + if (r) { |
|---|
| 331 | + WARN(r->start == 0, "0 is an invalid IRQ number\n"); |
|---|
| 332 | + return r->start; |
|---|
| 333 | + } |
|---|
| 334 | + |
|---|
| 335 | + return -ENXIO; |
|---|
| 336 | +} |
|---|
| 337 | + |
|---|
| 338 | +/** |
|---|
| 339 | + * platform_get_irq_byname - get an IRQ for a device by name |
|---|
| 340 | + * @dev: platform device |
|---|
| 341 | + * @name: IRQ name |
|---|
| 342 | + * |
|---|
| 343 | + * Get an IRQ like platform_get_irq(), but then by name rather then by index. |
|---|
| 344 | + * |
|---|
| 345 | + * Return: non-zero IRQ number on success, negative error number on failure. |
|---|
| 346 | + */ |
|---|
| 347 | +int platform_get_irq_byname(struct platform_device *dev, const char *name) |
|---|
| 348 | +{ |
|---|
| 349 | + int ret; |
|---|
| 350 | + |
|---|
| 351 | + ret = __platform_get_irq_byname(dev, name); |
|---|
| 352 | + if (ret < 0 && ret != -EPROBE_DEFER) |
|---|
| 353 | + dev_err(&dev->dev, "IRQ %s not found\n", name); |
|---|
| 354 | + |
|---|
| 355 | + return ret; |
|---|
| 240 | 356 | } |
|---|
| 241 | 357 | EXPORT_SYMBOL_GPL(platform_get_irq_byname); |
|---|
| 358 | + |
|---|
| 359 | +/** |
|---|
| 360 | + * platform_get_irq_byname_optional - get an optional IRQ for a device by name |
|---|
| 361 | + * @dev: platform device |
|---|
| 362 | + * @name: IRQ name |
|---|
| 363 | + * |
|---|
| 364 | + * Get an optional IRQ by name like platform_get_irq_byname(). Except that it |
|---|
| 365 | + * does not print an error message if an IRQ can not be obtained. |
|---|
| 366 | + * |
|---|
| 367 | + * Return: non-zero IRQ number on success, negative error number on failure. |
|---|
| 368 | + */ |
|---|
| 369 | +int platform_get_irq_byname_optional(struct platform_device *dev, |
|---|
| 370 | + const char *name) |
|---|
| 371 | +{ |
|---|
| 372 | + return __platform_get_irq_byname(dev, name); |
|---|
| 373 | +} |
|---|
| 374 | +EXPORT_SYMBOL_GPL(platform_get_irq_byname_optional); |
|---|
| 242 | 375 | |
|---|
| 243 | 376 | /** |
|---|
| 244 | 377 | * platform_add_devices - add a numbers of platform devices |
|---|
| .. | .. |
|---|
| 267 | 400 | char name[]; |
|---|
| 268 | 401 | }; |
|---|
| 269 | 402 | |
|---|
| 403 | +/* |
|---|
| 404 | + * Set up default DMA mask for platform devices if the they weren't |
|---|
| 405 | + * previously set by the architecture / DT. |
|---|
| 406 | + */ |
|---|
| 407 | +static void setup_pdev_dma_masks(struct platform_device *pdev) |
|---|
| 408 | +{ |
|---|
| 409 | + pdev->dev.dma_parms = &pdev->dma_parms; |
|---|
| 410 | + |
|---|
| 411 | + if (!pdev->dev.coherent_dma_mask) |
|---|
| 412 | + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); |
|---|
| 413 | + if (!pdev->dev.dma_mask) { |
|---|
| 414 | + pdev->platform_dma_mask = DMA_BIT_MASK(32); |
|---|
| 415 | + pdev->dev.dma_mask = &pdev->platform_dma_mask; |
|---|
| 416 | + } |
|---|
| 417 | +}; |
|---|
| 418 | + |
|---|
| 270 | 419 | /** |
|---|
| 271 | 420 | * platform_device_put - destroy a platform device |
|---|
| 272 | 421 | * @pdev: platform device to free |
|---|
| .. | .. |
|---|
| 276 | 425 | */ |
|---|
| 277 | 426 | void platform_device_put(struct platform_device *pdev) |
|---|
| 278 | 427 | { |
|---|
| 279 | | - if (pdev) |
|---|
| 428 | + if (!IS_ERR_OR_NULL(pdev)) |
|---|
| 280 | 429 | put_device(&pdev->dev); |
|---|
| 281 | 430 | } |
|---|
| 282 | 431 | EXPORT_SYMBOL_GPL(platform_device_put); |
|---|
| .. | .. |
|---|
| 313 | 462 | pa->pdev.id = id; |
|---|
| 314 | 463 | device_initialize(&pa->pdev.dev); |
|---|
| 315 | 464 | pa->pdev.dev.release = platform_device_release; |
|---|
| 316 | | - arch_setup_pdev_archdata(&pa->pdev); |
|---|
| 465 | + setup_pdev_dma_masks(&pa->pdev); |
|---|
| 317 | 466 | } |
|---|
| 318 | 467 | |
|---|
| 319 | 468 | return pa ? &pa->pdev : NULL; |
|---|
| .. | .. |
|---|
| 424 | 573 | * that we remember it must be freed, and we append a suffix |
|---|
| 425 | 574 | * to avoid namespace collision with explicit IDs. |
|---|
| 426 | 575 | */ |
|---|
| 427 | | - ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL); |
|---|
| 576 | + ret = ida_alloc(&platform_devid_ida, GFP_KERNEL); |
|---|
| 428 | 577 | if (ret < 0) |
|---|
| 429 | 578 | goto err_out; |
|---|
| 430 | 579 | pdev->id = ret; |
|---|
| .. | .. |
|---|
| 447 | 596 | p = &ioport_resource; |
|---|
| 448 | 597 | } |
|---|
| 449 | 598 | |
|---|
| 450 | | - if (p && insert_resource(p, r)) { |
|---|
| 451 | | - dev_err(&pdev->dev, "failed to claim resource %d: %pR\n", i, r); |
|---|
| 452 | | - ret = -EBUSY; |
|---|
| 453 | | - goto failed; |
|---|
| 599 | + if (p) { |
|---|
| 600 | + ret = insert_resource(p, r); |
|---|
| 601 | + if (ret) { |
|---|
| 602 | + dev_err(&pdev->dev, "failed to claim resource %d: %pR\n", i, r); |
|---|
| 603 | + goto failed; |
|---|
| 604 | + } |
|---|
| 454 | 605 | } |
|---|
| 455 | 606 | } |
|---|
| 456 | 607 | |
|---|
| .. | .. |
|---|
| 463 | 614 | |
|---|
| 464 | 615 | failed: |
|---|
| 465 | 616 | if (pdev->id_auto) { |
|---|
| 466 | | - ida_simple_remove(&platform_devid_ida, pdev->id); |
|---|
| 617 | + ida_free(&platform_devid_ida, pdev->id); |
|---|
| 467 | 618 | pdev->id = PLATFORM_DEVID_AUTO; |
|---|
| 468 | 619 | } |
|---|
| 469 | 620 | |
|---|
| .. | .. |
|---|
| 490 | 641 | { |
|---|
| 491 | 642 | u32 i; |
|---|
| 492 | 643 | |
|---|
| 493 | | - if (pdev) { |
|---|
| 494 | | - device_remove_properties(&pdev->dev); |
|---|
| 644 | + if (!IS_ERR_OR_NULL(pdev)) { |
|---|
| 495 | 645 | device_del(&pdev->dev); |
|---|
| 496 | 646 | |
|---|
| 497 | 647 | if (pdev->id_auto) { |
|---|
| 498 | | - ida_simple_remove(&platform_devid_ida, pdev->id); |
|---|
| 648 | + ida_free(&platform_devid_ida, pdev->id); |
|---|
| 499 | 649 | pdev->id = PLATFORM_DEVID_AUTO; |
|---|
| 500 | 650 | } |
|---|
| 501 | 651 | |
|---|
| .. | .. |
|---|
| 515 | 665 | int platform_device_register(struct platform_device *pdev) |
|---|
| 516 | 666 | { |
|---|
| 517 | 667 | device_initialize(&pdev->dev); |
|---|
| 518 | | - arch_setup_pdev_archdata(pdev); |
|---|
| 668 | + setup_pdev_dma_masks(pdev); |
|---|
| 519 | 669 | return platform_device_add(pdev); |
|---|
| 520 | 670 | } |
|---|
| 521 | 671 | EXPORT_SYMBOL_GPL(platform_device_register); |
|---|
| .. | .. |
|---|
| 546 | 696 | struct platform_device *platform_device_register_full( |
|---|
| 547 | 697 | const struct platform_device_info *pdevinfo) |
|---|
| 548 | 698 | { |
|---|
| 549 | | - int ret = -ENOMEM; |
|---|
| 699 | + int ret; |
|---|
| 550 | 700 | struct platform_device *pdev; |
|---|
| 551 | 701 | |
|---|
| 552 | 702 | pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id); |
|---|
| 553 | 703 | if (!pdev) |
|---|
| 554 | | - goto err_alloc; |
|---|
| 704 | + return ERR_PTR(-ENOMEM); |
|---|
| 555 | 705 | |
|---|
| 556 | 706 | pdev->dev.parent = pdevinfo->parent; |
|---|
| 557 | 707 | pdev->dev.fwnode = pdevinfo->fwnode; |
|---|
| 708 | + pdev->dev.of_node = of_node_get(to_of_node(pdev->dev.fwnode)); |
|---|
| 709 | + pdev->dev.of_node_reused = pdevinfo->of_node_reused; |
|---|
| 558 | 710 | |
|---|
| 559 | 711 | if (pdevinfo->dma_mask) { |
|---|
| 560 | | - /* |
|---|
| 561 | | - * This memory isn't freed when the device is put, |
|---|
| 562 | | - * I don't have a nice idea for that though. Conceptually |
|---|
| 563 | | - * dma_mask in struct device should not be a pointer. |
|---|
| 564 | | - * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 |
|---|
| 565 | | - */ |
|---|
| 566 | | - pdev->dev.dma_mask = |
|---|
| 567 | | - kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); |
|---|
| 568 | | - if (!pdev->dev.dma_mask) |
|---|
| 569 | | - goto err; |
|---|
| 570 | | - |
|---|
| 571 | | - kmemleak_ignore(pdev->dev.dma_mask); |
|---|
| 572 | | - |
|---|
| 573 | | - *pdev->dev.dma_mask = pdevinfo->dma_mask; |
|---|
| 712 | + pdev->platform_dma_mask = pdevinfo->dma_mask; |
|---|
| 713 | + pdev->dev.dma_mask = &pdev->platform_dma_mask; |
|---|
| 574 | 714 | pdev->dev.coherent_dma_mask = pdevinfo->dma_mask; |
|---|
| 575 | 715 | } |
|---|
| 576 | 716 | |
|---|
| .. | .. |
|---|
| 595 | 735 | if (ret) { |
|---|
| 596 | 736 | err: |
|---|
| 597 | 737 | ACPI_COMPANION_SET(&pdev->dev, NULL); |
|---|
| 598 | | - kfree(pdev->dev.dma_mask); |
|---|
| 599 | | - |
|---|
| 600 | | -err_alloc: |
|---|
| 601 | 738 | platform_device_put(pdev); |
|---|
| 602 | 739 | return ERR_PTR(ret); |
|---|
| 603 | 740 | } |
|---|
| .. | .. |
|---|
| 866 | 1003 | * @drivers: an array of drivers to unregister |
|---|
| 867 | 1004 | * @count: the number of drivers to unregister |
|---|
| 868 | 1005 | * |
|---|
| 869 | | - * Unegisters platform drivers specified by an array. This is typically used |
|---|
| 1006 | + * Unregisters platform drivers specified by an array. This is typically used |
|---|
| 870 | 1007 | * to complement an earlier call to platform_register_drivers(). Drivers are |
|---|
| 871 | 1008 | * unregistered in the reverse order in which they were registered. |
|---|
| 872 | 1009 | */ |
|---|
| .. | .. |
|---|
| 886 | 1023 | * (b) sysfs attribute lets new-style coldplug recover from hotplug events |
|---|
| 887 | 1024 | * mishandled before system is fully running: "modprobe $(cat modalias)" |
|---|
| 888 | 1025 | */ |
|---|
| 889 | | -static ssize_t modalias_show(struct device *dev, struct device_attribute *a, |
|---|
| 890 | | - char *buf) |
|---|
| 1026 | +static ssize_t modalias_show(struct device *dev, |
|---|
| 1027 | + struct device_attribute *attr, char *buf) |
|---|
| 891 | 1028 | { |
|---|
| 892 | | - struct platform_device *pdev = to_platform_device(dev); |
|---|
| 1029 | + struct platform_device *pdev = to_platform_device(dev); |
|---|
| 893 | 1030 | int len; |
|---|
| 894 | 1031 | |
|---|
| 895 | 1032 | len = of_device_modalias(dev, buf, PAGE_SIZE); |
|---|
| 896 | 1033 | if (len != -ENODEV) |
|---|
| 897 | 1034 | return len; |
|---|
| 898 | 1035 | |
|---|
| 899 | | - len = acpi_device_modalias(dev, buf, PAGE_SIZE -1); |
|---|
| 1036 | + len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1); |
|---|
| 900 | 1037 | if (len != -ENODEV) |
|---|
| 901 | 1038 | return len; |
|---|
| 902 | 1039 | |
|---|
| 903 | | - len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name); |
|---|
| 904 | | - |
|---|
| 905 | | - return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; |
|---|
| 1040 | + return sysfs_emit(buf, "platform:%s\n", pdev->name); |
|---|
| 906 | 1041 | } |
|---|
| 907 | 1042 | static DEVICE_ATTR_RO(modalias); |
|---|
| 908 | 1043 | |
|---|
| .. | .. |
|---|
| 947 | 1082 | ssize_t len; |
|---|
| 948 | 1083 | |
|---|
| 949 | 1084 | device_lock(dev); |
|---|
| 950 | | - len = sprintf(buf, "%s\n", pdev->driver_override); |
|---|
| 1085 | + len = sysfs_emit(buf, "%s\n", pdev->driver_override); |
|---|
| 951 | 1086 | device_unlock(dev); |
|---|
| 1087 | + |
|---|
| 952 | 1088 | return len; |
|---|
| 953 | 1089 | } |
|---|
| 954 | 1090 | static DEVICE_ATTR_RW(driver_override); |
|---|
| 955 | 1091 | |
|---|
| 1092 | +static ssize_t numa_node_show(struct device *dev, |
|---|
| 1093 | + struct device_attribute *attr, char *buf) |
|---|
| 1094 | +{ |
|---|
| 1095 | + return sysfs_emit(buf, "%d\n", dev_to_node(dev)); |
|---|
| 1096 | +} |
|---|
| 1097 | +static DEVICE_ATTR_RO(numa_node); |
|---|
| 1098 | + |
|---|
| 1099 | +static umode_t platform_dev_attrs_visible(struct kobject *kobj, struct attribute *a, |
|---|
| 1100 | + int n) |
|---|
| 1101 | +{ |
|---|
| 1102 | + struct device *dev = container_of(kobj, typeof(*dev), kobj); |
|---|
| 1103 | + |
|---|
| 1104 | + if (a == &dev_attr_numa_node.attr && |
|---|
| 1105 | + dev_to_node(dev) == NUMA_NO_NODE) |
|---|
| 1106 | + return 0; |
|---|
| 1107 | + |
|---|
| 1108 | + return a->mode; |
|---|
| 1109 | +} |
|---|
| 956 | 1110 | |
|---|
| 957 | 1111 | static struct attribute *platform_dev_attrs[] = { |
|---|
| 958 | 1112 | &dev_attr_modalias.attr, |
|---|
| 1113 | + &dev_attr_numa_node.attr, |
|---|
| 959 | 1114 | &dev_attr_driver_override.attr, |
|---|
| 960 | 1115 | NULL, |
|---|
| 961 | 1116 | }; |
|---|
| 962 | | -ATTRIBUTE_GROUPS(platform_dev); |
|---|
| 1117 | + |
|---|
| 1118 | +static struct attribute_group platform_dev_group = { |
|---|
| 1119 | + .attrs = platform_dev_attrs, |
|---|
| 1120 | + .is_visible = platform_dev_attrs_visible, |
|---|
| 1121 | +}; |
|---|
| 1122 | +__ATTRIBUTE_GROUPS(platform_dev); |
|---|
| 963 | 1123 | |
|---|
| 964 | 1124 | static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) |
|---|
| 965 | 1125 | { |
|---|
| .. | .. |
|---|
| 1185 | 1345 | ret = of_dma_configure(dev, dev->of_node, true); |
|---|
| 1186 | 1346 | } else if (has_acpi_companion(dev)) { |
|---|
| 1187 | 1347 | attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode)); |
|---|
| 1188 | | - if (attr != DEV_DMA_NOT_SUPPORTED) |
|---|
| 1189 | | - ret = acpi_dma_configure(dev, attr); |
|---|
| 1348 | + ret = acpi_dma_configure(dev, attr); |
|---|
| 1190 | 1349 | } |
|---|
| 1191 | 1350 | |
|---|
| 1192 | 1351 | return ret; |
|---|
| .. | .. |
|---|
| 1208 | 1367 | }; |
|---|
| 1209 | 1368 | EXPORT_SYMBOL_GPL(platform_bus_type); |
|---|
| 1210 | 1369 | |
|---|
| 1370 | +static inline int __platform_match(struct device *dev, const void *drv) |
|---|
| 1371 | +{ |
|---|
| 1372 | + return platform_match(dev, (struct device_driver *)drv); |
|---|
| 1373 | +} |
|---|
| 1374 | + |
|---|
| 1375 | +/** |
|---|
| 1376 | + * platform_find_device_by_driver - Find a platform device with a given |
|---|
| 1377 | + * driver. |
|---|
| 1378 | + * @start: The device to start the search from. |
|---|
| 1379 | + * @drv: The device driver to look for. |
|---|
| 1380 | + */ |
|---|
| 1381 | +struct device *platform_find_device_by_driver(struct device *start, |
|---|
| 1382 | + const struct device_driver *drv) |
|---|
| 1383 | +{ |
|---|
| 1384 | + return bus_find_device(&platform_bus_type, start, drv, |
|---|
| 1385 | + __platform_match); |
|---|
| 1386 | +} |
|---|
| 1387 | +EXPORT_SYMBOL_GPL(platform_find_device_by_driver); |
|---|
| 1388 | + |
|---|
| 1389 | +void __weak __init early_platform_cleanup(void) { } |
|---|
| 1390 | + |
|---|
| 1211 | 1391 | int __init platform_bus_init(void) |
|---|
| 1212 | 1392 | { |
|---|
| 1213 | 1393 | int error; |
|---|
| .. | .. |
|---|
| 1225 | 1405 | of_platform_register_reconfig_notifier(); |
|---|
| 1226 | 1406 | return error; |
|---|
| 1227 | 1407 | } |
|---|
| 1228 | | - |
|---|
| 1229 | | -#ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK |
|---|
| 1230 | | -u64 dma_get_required_mask(struct device *dev) |
|---|
| 1231 | | -{ |
|---|
| 1232 | | - u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT); |
|---|
| 1233 | | - u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT)); |
|---|
| 1234 | | - u64 mask; |
|---|
| 1235 | | - |
|---|
| 1236 | | - if (!high_totalram) { |
|---|
| 1237 | | - /* convert to mask just covering totalram */ |
|---|
| 1238 | | - low_totalram = (1 << (fls(low_totalram) - 1)); |
|---|
| 1239 | | - low_totalram += low_totalram - 1; |
|---|
| 1240 | | - mask = low_totalram; |
|---|
| 1241 | | - } else { |
|---|
| 1242 | | - high_totalram = (1 << (fls(high_totalram) - 1)); |
|---|
| 1243 | | - high_totalram += high_totalram - 1; |
|---|
| 1244 | | - mask = (((u64)high_totalram) << 32) + 0xffffffff; |
|---|
| 1245 | | - } |
|---|
| 1246 | | - return mask; |
|---|
| 1247 | | -} |
|---|
| 1248 | | -EXPORT_SYMBOL_GPL(dma_get_required_mask); |
|---|
| 1249 | | -#endif |
|---|
| 1250 | | - |
|---|
| 1251 | | -static __initdata LIST_HEAD(early_platform_driver_list); |
|---|
| 1252 | | -static __initdata LIST_HEAD(early_platform_device_list); |
|---|
| 1253 | | - |
|---|
| 1254 | | -/** |
|---|
| 1255 | | - * early_platform_driver_register - register early platform driver |
|---|
| 1256 | | - * @epdrv: early_platform driver structure |
|---|
| 1257 | | - * @buf: string passed from early_param() |
|---|
| 1258 | | - * |
|---|
| 1259 | | - * Helper function for early_platform_init() / early_platform_init_buffer() |
|---|
| 1260 | | - */ |
|---|
| 1261 | | -int __init early_platform_driver_register(struct early_platform_driver *epdrv, |
|---|
| 1262 | | - char *buf) |
|---|
| 1263 | | -{ |
|---|
| 1264 | | - char *tmp; |
|---|
| 1265 | | - int n; |
|---|
| 1266 | | - |
|---|
| 1267 | | - /* Simply add the driver to the end of the global list. |
|---|
| 1268 | | - * Drivers will by default be put on the list in compiled-in order. |
|---|
| 1269 | | - */ |
|---|
| 1270 | | - if (!epdrv->list.next) { |
|---|
| 1271 | | - INIT_LIST_HEAD(&epdrv->list); |
|---|
| 1272 | | - list_add_tail(&epdrv->list, &early_platform_driver_list); |
|---|
| 1273 | | - } |
|---|
| 1274 | | - |
|---|
| 1275 | | - /* If the user has specified device then make sure the driver |
|---|
| 1276 | | - * gets prioritized. The driver of the last device specified on |
|---|
| 1277 | | - * command line will be put first on the list. |
|---|
| 1278 | | - */ |
|---|
| 1279 | | - n = strlen(epdrv->pdrv->driver.name); |
|---|
| 1280 | | - if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) { |
|---|
| 1281 | | - list_move(&epdrv->list, &early_platform_driver_list); |
|---|
| 1282 | | - |
|---|
| 1283 | | - /* Allow passing parameters after device name */ |
|---|
| 1284 | | - if (buf[n] == '\0' || buf[n] == ',') |
|---|
| 1285 | | - epdrv->requested_id = -1; |
|---|
| 1286 | | - else { |
|---|
| 1287 | | - epdrv->requested_id = simple_strtoul(&buf[n + 1], |
|---|
| 1288 | | - &tmp, 10); |
|---|
| 1289 | | - |
|---|
| 1290 | | - if (buf[n] != '.' || (tmp == &buf[n + 1])) { |
|---|
| 1291 | | - epdrv->requested_id = EARLY_PLATFORM_ID_ERROR; |
|---|
| 1292 | | - n = 0; |
|---|
| 1293 | | - } else |
|---|
| 1294 | | - n += strcspn(&buf[n + 1], ",") + 1; |
|---|
| 1295 | | - } |
|---|
| 1296 | | - |
|---|
| 1297 | | - if (buf[n] == ',') |
|---|
| 1298 | | - n++; |
|---|
| 1299 | | - |
|---|
| 1300 | | - if (epdrv->bufsize) { |
|---|
| 1301 | | - memcpy(epdrv->buffer, &buf[n], |
|---|
| 1302 | | - min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1)); |
|---|
| 1303 | | - epdrv->buffer[epdrv->bufsize - 1] = '\0'; |
|---|
| 1304 | | - } |
|---|
| 1305 | | - } |
|---|
| 1306 | | - |
|---|
| 1307 | | - return 0; |
|---|
| 1308 | | -} |
|---|
| 1309 | | - |
|---|
| 1310 | | -/** |
|---|
| 1311 | | - * early_platform_add_devices - adds a number of early platform devices |
|---|
| 1312 | | - * @devs: array of early platform devices to add |
|---|
| 1313 | | - * @num: number of early platform devices in array |
|---|
| 1314 | | - * |
|---|
| 1315 | | - * Used by early architecture code to register early platform devices and |
|---|
| 1316 | | - * their platform data. |
|---|
| 1317 | | - */ |
|---|
| 1318 | | -void __init early_platform_add_devices(struct platform_device **devs, int num) |
|---|
| 1319 | | -{ |
|---|
| 1320 | | - struct device *dev; |
|---|
| 1321 | | - int i; |
|---|
| 1322 | | - |
|---|
| 1323 | | - /* simply add the devices to list */ |
|---|
| 1324 | | - for (i = 0; i < num; i++) { |
|---|
| 1325 | | - dev = &devs[i]->dev; |
|---|
| 1326 | | - |
|---|
| 1327 | | - if (!dev->devres_head.next) { |
|---|
| 1328 | | - pm_runtime_early_init(dev); |
|---|
| 1329 | | - INIT_LIST_HEAD(&dev->devres_head); |
|---|
| 1330 | | - list_add_tail(&dev->devres_head, |
|---|
| 1331 | | - &early_platform_device_list); |
|---|
| 1332 | | - } |
|---|
| 1333 | | - } |
|---|
| 1334 | | -} |
|---|
| 1335 | | - |
|---|
| 1336 | | -/** |
|---|
| 1337 | | - * early_platform_driver_register_all - register early platform drivers |
|---|
| 1338 | | - * @class_str: string to identify early platform driver class |
|---|
| 1339 | | - * |
|---|
| 1340 | | - * Used by architecture code to register all early platform drivers |
|---|
| 1341 | | - * for a certain class. If omitted then only early platform drivers |
|---|
| 1342 | | - * with matching kernel command line class parameters will be registered. |
|---|
| 1343 | | - */ |
|---|
| 1344 | | -void __init early_platform_driver_register_all(char *class_str) |
|---|
| 1345 | | -{ |
|---|
| 1346 | | - /* The "class_str" parameter may or may not be present on the kernel |
|---|
| 1347 | | - * command line. If it is present then there may be more than one |
|---|
| 1348 | | - * matching parameter. |
|---|
| 1349 | | - * |
|---|
| 1350 | | - * Since we register our early platform drivers using early_param() |
|---|
| 1351 | | - * we need to make sure that they also get registered in the case |
|---|
| 1352 | | - * when the parameter is missing from the kernel command line. |
|---|
| 1353 | | - * |
|---|
| 1354 | | - * We use parse_early_options() to make sure the early_param() gets |
|---|
| 1355 | | - * called at least once. The early_param() may be called more than |
|---|
| 1356 | | - * once since the name of the preferred device may be specified on |
|---|
| 1357 | | - * the kernel command line. early_platform_driver_register() handles |
|---|
| 1358 | | - * this case for us. |
|---|
| 1359 | | - */ |
|---|
| 1360 | | - parse_early_options(class_str); |
|---|
| 1361 | | -} |
|---|
| 1362 | | - |
|---|
| 1363 | | -/** |
|---|
| 1364 | | - * early_platform_match - find early platform device matching driver |
|---|
| 1365 | | - * @epdrv: early platform driver structure |
|---|
| 1366 | | - * @id: id to match against |
|---|
| 1367 | | - */ |
|---|
| 1368 | | -static struct platform_device * __init |
|---|
| 1369 | | -early_platform_match(struct early_platform_driver *epdrv, int id) |
|---|
| 1370 | | -{ |
|---|
| 1371 | | - struct platform_device *pd; |
|---|
| 1372 | | - |
|---|
| 1373 | | - list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) |
|---|
| 1374 | | - if (platform_match(&pd->dev, &epdrv->pdrv->driver)) |
|---|
| 1375 | | - if (pd->id == id) |
|---|
| 1376 | | - return pd; |
|---|
| 1377 | | - |
|---|
| 1378 | | - return NULL; |
|---|
| 1379 | | -} |
|---|
| 1380 | | - |
|---|
| 1381 | | -/** |
|---|
| 1382 | | - * early_platform_left - check if early platform driver has matching devices |
|---|
| 1383 | | - * @epdrv: early platform driver structure |
|---|
| 1384 | | - * @id: return true if id or above exists |
|---|
| 1385 | | - */ |
|---|
| 1386 | | -static int __init early_platform_left(struct early_platform_driver *epdrv, |
|---|
| 1387 | | - int id) |
|---|
| 1388 | | -{ |
|---|
| 1389 | | - struct platform_device *pd; |
|---|
| 1390 | | - |
|---|
| 1391 | | - list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) |
|---|
| 1392 | | - if (platform_match(&pd->dev, &epdrv->pdrv->driver)) |
|---|
| 1393 | | - if (pd->id >= id) |
|---|
| 1394 | | - return 1; |
|---|
| 1395 | | - |
|---|
| 1396 | | - return 0; |
|---|
| 1397 | | -} |
|---|
| 1398 | | - |
|---|
| 1399 | | -/** |
|---|
| 1400 | | - * early_platform_driver_probe_id - probe drivers matching class_str and id |
|---|
| 1401 | | - * @class_str: string to identify early platform driver class |
|---|
| 1402 | | - * @id: id to match against |
|---|
| 1403 | | - * @nr_probe: number of platform devices to successfully probe before exiting |
|---|
| 1404 | | - */ |
|---|
| 1405 | | -static int __init early_platform_driver_probe_id(char *class_str, |
|---|
| 1406 | | - int id, |
|---|
| 1407 | | - int nr_probe) |
|---|
| 1408 | | -{ |
|---|
| 1409 | | - struct early_platform_driver *epdrv; |
|---|
| 1410 | | - struct platform_device *match; |
|---|
| 1411 | | - int match_id; |
|---|
| 1412 | | - int n = 0; |
|---|
| 1413 | | - int left = 0; |
|---|
| 1414 | | - |
|---|
| 1415 | | - list_for_each_entry(epdrv, &early_platform_driver_list, list) { |
|---|
| 1416 | | - /* only use drivers matching our class_str */ |
|---|
| 1417 | | - if (strcmp(class_str, epdrv->class_str)) |
|---|
| 1418 | | - continue; |
|---|
| 1419 | | - |
|---|
| 1420 | | - if (id == -2) { |
|---|
| 1421 | | - match_id = epdrv->requested_id; |
|---|
| 1422 | | - left = 1; |
|---|
| 1423 | | - |
|---|
| 1424 | | - } else { |
|---|
| 1425 | | - match_id = id; |
|---|
| 1426 | | - left += early_platform_left(epdrv, id); |
|---|
| 1427 | | - |
|---|
| 1428 | | - /* skip requested id */ |
|---|
| 1429 | | - switch (epdrv->requested_id) { |
|---|
| 1430 | | - case EARLY_PLATFORM_ID_ERROR: |
|---|
| 1431 | | - case EARLY_PLATFORM_ID_UNSET: |
|---|
| 1432 | | - break; |
|---|
| 1433 | | - default: |
|---|
| 1434 | | - if (epdrv->requested_id == id) |
|---|
| 1435 | | - match_id = EARLY_PLATFORM_ID_UNSET; |
|---|
| 1436 | | - } |
|---|
| 1437 | | - } |
|---|
| 1438 | | - |
|---|
| 1439 | | - switch (match_id) { |
|---|
| 1440 | | - case EARLY_PLATFORM_ID_ERROR: |
|---|
| 1441 | | - pr_warn("%s: unable to parse %s parameter\n", |
|---|
| 1442 | | - class_str, epdrv->pdrv->driver.name); |
|---|
| 1443 | | - /* fall-through */ |
|---|
| 1444 | | - case EARLY_PLATFORM_ID_UNSET: |
|---|
| 1445 | | - match = NULL; |
|---|
| 1446 | | - break; |
|---|
| 1447 | | - default: |
|---|
| 1448 | | - match = early_platform_match(epdrv, match_id); |
|---|
| 1449 | | - } |
|---|
| 1450 | | - |
|---|
| 1451 | | - if (match) { |
|---|
| 1452 | | - /* |
|---|
| 1453 | | - * Set up a sensible init_name to enable |
|---|
| 1454 | | - * dev_name() and others to be used before the |
|---|
| 1455 | | - * rest of the driver core is initialized. |
|---|
| 1456 | | - */ |
|---|
| 1457 | | - if (!match->dev.init_name && slab_is_available()) { |
|---|
| 1458 | | - if (match->id != -1) |
|---|
| 1459 | | - match->dev.init_name = |
|---|
| 1460 | | - kasprintf(GFP_KERNEL, "%s.%d", |
|---|
| 1461 | | - match->name, |
|---|
| 1462 | | - match->id); |
|---|
| 1463 | | - else |
|---|
| 1464 | | - match->dev.init_name = |
|---|
| 1465 | | - kasprintf(GFP_KERNEL, "%s", |
|---|
| 1466 | | - match->name); |
|---|
| 1467 | | - |
|---|
| 1468 | | - if (!match->dev.init_name) |
|---|
| 1469 | | - return -ENOMEM; |
|---|
| 1470 | | - } |
|---|
| 1471 | | - |
|---|
| 1472 | | - if (epdrv->pdrv->probe(match)) |
|---|
| 1473 | | - pr_warn("%s: unable to probe %s early.\n", |
|---|
| 1474 | | - class_str, match->name); |
|---|
| 1475 | | - else |
|---|
| 1476 | | - n++; |
|---|
| 1477 | | - } |
|---|
| 1478 | | - |
|---|
| 1479 | | - if (n >= nr_probe) |
|---|
| 1480 | | - break; |
|---|
| 1481 | | - } |
|---|
| 1482 | | - |
|---|
| 1483 | | - if (left) |
|---|
| 1484 | | - return n; |
|---|
| 1485 | | - else |
|---|
| 1486 | | - return -ENODEV; |
|---|
| 1487 | | -} |
|---|
| 1488 | | - |
|---|
| 1489 | | -/** |
|---|
| 1490 | | - * early_platform_driver_probe - probe a class of registered drivers |
|---|
| 1491 | | - * @class_str: string to identify early platform driver class |
|---|
| 1492 | | - * @nr_probe: number of platform devices to successfully probe before exiting |
|---|
| 1493 | | - * @user_only: only probe user specified early platform devices |
|---|
| 1494 | | - * |
|---|
| 1495 | | - * Used by architecture code to probe registered early platform drivers |
|---|
| 1496 | | - * within a certain class. For probe to happen a registered early platform |
|---|
| 1497 | | - * device matching a registered early platform driver is needed. |
|---|
| 1498 | | - */ |
|---|
| 1499 | | -int __init early_platform_driver_probe(char *class_str, |
|---|
| 1500 | | - int nr_probe, |
|---|
| 1501 | | - int user_only) |
|---|
| 1502 | | -{ |
|---|
| 1503 | | - int k, n, i; |
|---|
| 1504 | | - |
|---|
| 1505 | | - n = 0; |
|---|
| 1506 | | - for (i = -2; n < nr_probe; i++) { |
|---|
| 1507 | | - k = early_platform_driver_probe_id(class_str, i, nr_probe - n); |
|---|
| 1508 | | - |
|---|
| 1509 | | - if (k < 0) |
|---|
| 1510 | | - break; |
|---|
| 1511 | | - |
|---|
| 1512 | | - n += k; |
|---|
| 1513 | | - |
|---|
| 1514 | | - if (user_only) |
|---|
| 1515 | | - break; |
|---|
| 1516 | | - } |
|---|
| 1517 | | - |
|---|
| 1518 | | - return n; |
|---|
| 1519 | | -} |
|---|
| 1520 | | - |
|---|
| 1521 | | -/** |
|---|
| 1522 | | - * early_platform_cleanup - clean up early platform code |
|---|
| 1523 | | - */ |
|---|
| 1524 | | -void __init early_platform_cleanup(void) |
|---|
| 1525 | | -{ |
|---|
| 1526 | | - struct platform_device *pd, *pd2; |
|---|
| 1527 | | - |
|---|
| 1528 | | - /* clean up the devres list used to chain devices */ |
|---|
| 1529 | | - list_for_each_entry_safe(pd, pd2, &early_platform_device_list, |
|---|
| 1530 | | - dev.devres_head) { |
|---|
| 1531 | | - list_del(&pd->dev.devres_head); |
|---|
| 1532 | | - memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head)); |
|---|
| 1533 | | - } |
|---|
| 1534 | | -} |
|---|
| 1535 | | - |
|---|