11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * platform.c - platform 'pseudo' bus for legacy devices 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2002-3 Patrick Mochel 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2002-3 Open Source Development Labs 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is released under the GPLv2 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Please see Documentation/driver-model/platform.txt for more 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * information. 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13daa4122673f002911122cac2b996bd36b6c01b32Andrew Morton#include <linux/string.h> 14d052d1beff706920e82c5d55006b08e256b5df09Russell King#include <linux/platform_device.h> 1505212157e94ccf4cf458413bbba509cfa95ff92bGrant Likely#include <linux/of_device.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/dma-mapping.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bootmem.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h> 214e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/slab.h> 229d7302299ee96ca954fe4ab8ca640333b6e19ad0Magnus Damm#include <linux/pm_runtime.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 24a1bdc7aad8b557176ccecff1da137ebe3090871eBen Dooks#include "base.h" 25a1bdc7aad8b557176ccecff1da137ebe3090871eBen Dooks 264a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman#define to_platform_driver(drv) (container_of((drv), struct platform_driver, \ 274a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman driver)) 2800d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct device platform_bus = { 301e0b2cf933ebf32494eba3f668859ba57f06a951Kay Sievers .init_name = "platform", 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 32a96b204208443ab7e23c681f7ddabe807a741d0cDmitry TorokhovEXPORT_SYMBOL_GPL(platform_bus); 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 35a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * arch_setup_pdev_archdata - Allow manipulation of archdata before its used 367de636fa25c19fc4187f85f8325c50b1b21a6d8bRandy Dunlap * @pdev: platform device 37a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * 38a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * This is called before platform_device_add() such that any pdev_archdata may 39a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * be setup before the platform_notifier is called. So if a user needs to 40a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * manipulate any relevant information in the pdev_archdata they can do: 41a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * 42a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * platform_devic_alloc() 43a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * ... manipulate ... 44a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * platform_device_add() 45a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * 46a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * And if they don't care they can just call platform_device_register() and 47a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala * everything will just work out. 48a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala */ 49a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Galavoid __weak arch_setup_pdev_archdata(struct platform_device *pdev) 50a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala{ 51a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala} 52a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala 53a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala/** 544a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_get_resource - get a resource for a device 554a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @dev: platform device 564a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @type: resource type 574a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @num: resource index 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 594a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartmanstruct resource *platform_get_resource(struct platform_device *dev, 604a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman unsigned int type, unsigned int num) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < dev->num_resources; i++) { 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *r = &dev->resource[i]; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm if (type == resource_type(r) && num-- == 0) 68c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm return r; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 72a96b204208443ab7e23c681f7ddabe807a741d0cDmitry TorokhovEXPORT_SYMBOL_GPL(platform_get_resource); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 754a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_get_irq - get an IRQ for a device 764a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @dev: platform device 774a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @num: IRQ number index 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint platform_get_irq(struct platform_device *dev, unsigned int num) 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 83305b3228f9ff4d59f49e6d34a7034d44ee8ce2f0David Vrabel return r ? r->start : -ENXIO; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 85a96b204208443ab7e23c681f7ddabe807a741d0cDmitry TorokhovEXPORT_SYMBOL_GPL(platform_get_irq); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 884a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_get_resource_byname - get a resource for a device by name 894a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @dev: platform device 904a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @type: resource type 914a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @name: resource name 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 934a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartmanstruct resource *platform_get_resource_byname(struct platform_device *dev, 94c0afe7ba5e71d8ab66bc42f90b3e237581d3c509Linus Walleij unsigned int type, 95c0afe7ba5e71d8ab66bc42f90b3e237581d3c509Linus Walleij const char *name) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < dev->num_resources; i++) { 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *r = &dev->resource[i]; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 102c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm if (type == resource_type(r) && !strcmp(r->name, name)) 103c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm return r; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 107a96b204208443ab7e23c681f7ddabe807a741d0cDmitry TorokhovEXPORT_SYMBOL_GPL(platform_get_resource_byname); 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1104a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_get_irq - get an IRQ for a device 1114a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @dev: platform device 1124a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @name: IRQ name 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 114c0afe7ba5e71d8ab66bc42f90b3e237581d3c509Linus Walleijint platform_get_irq_byname(struct platform_device *dev, const char *name) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1164a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, 1174a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman name); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 119305b3228f9ff4d59f49e6d34a7034d44ee8ce2f0David Vrabel return r ? r->start : -ENXIO; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 121a96b204208443ab7e23c681f7ddabe807a741d0cDmitry TorokhovEXPORT_SYMBOL_GPL(platform_get_irq_byname); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1244a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_add_devices - add a numbers of platform devices 1254a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @devs: array of platform devices to add 1264a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @num: number of platform devices in array 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint platform_add_devices(struct platform_device **devs, int num) 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ret = 0; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < num; i++) { 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = platform_device_register(devs[i]); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (--i >= 0) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds platform_device_unregister(devs[i]); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 143a96b204208443ab7e23c681f7ddabe807a741d0cDmitry TorokhovEXPORT_SYMBOL_GPL(platform_add_devices); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 14537c12e7497b6fe2b6a890814f0ff4edce696d862Russell Kingstruct platform_object { 14637c12e7497b6fe2b6a890814f0ff4edce696d862Russell King struct platform_device pdev; 14737c12e7497b6fe2b6a890814f0ff4edce696d862Russell King char name[1]; 14837c12e7497b6fe2b6a890814f0ff4edce696d862Russell King}; 14937c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 1513c31f07ad0dab02fe17195d32a965d57fd947707Ben Hutchings * platform_device_put - destroy a platform device 1524a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @pdev: platform device to free 15337c12e7497b6fe2b6a890814f0ff4edce696d862Russell King * 1544a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * Free all memory associated with a platform device. This function must 1554a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * _only_ be externally called in error cases. All other usage is a bug. 15637c12e7497b6fe2b6a890814f0ff4edce696d862Russell King */ 15737c12e7497b6fe2b6a890814f0ff4edce696d862Russell Kingvoid platform_device_put(struct platform_device *pdev) 15837c12e7497b6fe2b6a890814f0ff4edce696d862Russell King{ 15937c12e7497b6fe2b6a890814f0ff4edce696d862Russell King if (pdev) 16037c12e7497b6fe2b6a890814f0ff4edce696d862Russell King put_device(&pdev->dev); 16137c12e7497b6fe2b6a890814f0ff4edce696d862Russell King} 16237c12e7497b6fe2b6a890814f0ff4edce696d862Russell KingEXPORT_SYMBOL_GPL(platform_device_put); 16337c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 16437c12e7497b6fe2b6a890814f0ff4edce696d862Russell Kingstatic void platform_device_release(struct device *dev) 16537c12e7497b6fe2b6a890814f0ff4edce696d862Russell King{ 1664a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman struct platform_object *pa = container_of(dev, struct platform_object, 1674a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman pdev.dev); 16837c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 1697096d0422153ffcc2264eef652fc3a7bca3e6d3cGrant Likely of_device_node_put(&pa->pdev.dev); 17037c12e7497b6fe2b6a890814f0ff4edce696d862Russell King kfree(pa->pdev.dev.platform_data); 171e710d7d5a9cab1041b7a3cf9e655b75d92786857Samuel Ortiz kfree(pa->pdev.mfd_cell); 17237c12e7497b6fe2b6a890814f0ff4edce696d862Russell King kfree(pa->pdev.resource); 17337c12e7497b6fe2b6a890814f0ff4edce696d862Russell King kfree(pa); 17437c12e7497b6fe2b6a890814f0ff4edce696d862Russell King} 17537c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 17637c12e7497b6fe2b6a890814f0ff4edce696d862Russell King/** 1773c31f07ad0dab02fe17195d32a965d57fd947707Ben Hutchings * platform_device_alloc - create a platform device 1784a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @name: base name of the device we're adding 1794a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @id: instance id 18037c12e7497b6fe2b6a890814f0ff4edce696d862Russell King * 1814a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * Create a platform device object which can have other objects attached 1824a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * to it, and which will have attached objects freed when it is released. 18337c12e7497b6fe2b6a890814f0ff4edce696d862Russell King */ 1841359555eb77d240b7c1d7ee75bb07e89e89770e4Jean Delvarestruct platform_device *platform_device_alloc(const char *name, int id) 18537c12e7497b6fe2b6a890814f0ff4edce696d862Russell King{ 18637c12e7497b6fe2b6a890814f0ff4edce696d862Russell King struct platform_object *pa; 18737c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 18837c12e7497b6fe2b6a890814f0ff4edce696d862Russell King pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL); 18937c12e7497b6fe2b6a890814f0ff4edce696d862Russell King if (pa) { 19037c12e7497b6fe2b6a890814f0ff4edce696d862Russell King strcpy(pa->name, name); 19137c12e7497b6fe2b6a890814f0ff4edce696d862Russell King pa->pdev.name = pa->name; 19237c12e7497b6fe2b6a890814f0ff4edce696d862Russell King pa->pdev.id = id; 19337c12e7497b6fe2b6a890814f0ff4edce696d862Russell King device_initialize(&pa->pdev.dev); 19437c12e7497b6fe2b6a890814f0ff4edce696d862Russell King pa->pdev.dev.release = platform_device_release; 195a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala arch_setup_pdev_archdata(&pa->pdev); 19637c12e7497b6fe2b6a890814f0ff4edce696d862Russell King } 19737c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 19893ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov return pa ? &pa->pdev : NULL; 19937c12e7497b6fe2b6a890814f0ff4edce696d862Russell King} 20037c12e7497b6fe2b6a890814f0ff4edce696d862Russell KingEXPORT_SYMBOL_GPL(platform_device_alloc); 20137c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 20237c12e7497b6fe2b6a890814f0ff4edce696d862Russell King/** 2033c31f07ad0dab02fe17195d32a965d57fd947707Ben Hutchings * platform_device_add_resources - add resources to a platform device 2044a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @pdev: platform device allocated by platform_device_alloc to add resources to 2054a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @res: set of resources that needs to be allocated for the device 2064a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @num: number of resources 20737c12e7497b6fe2b6a890814f0ff4edce696d862Russell King * 2084a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * Add a copy of the resources to the platform device. The memory 2094a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * associated with the resources will be freed when the platform device is 2104a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * released. 21137c12e7497b6fe2b6a890814f0ff4edce696d862Russell King */ 2124a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartmanint platform_device_add_resources(struct platform_device *pdev, 2130b7f1a7efb38b551f5948a13d0b36e876ba536dbGeert Uytterhoeven const struct resource *res, unsigned int num) 21437c12e7497b6fe2b6a890814f0ff4edce696d862Russell King{ 215cea896238fbfdbce254f51fc8fd78c59df50081fUwe Kleine-König struct resource *r = NULL; 21637c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 217cea896238fbfdbce254f51fc8fd78c59df50081fUwe Kleine-König if (res) { 218cea896238fbfdbce254f51fc8fd78c59df50081fUwe Kleine-König r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL); 219cea896238fbfdbce254f51fc8fd78c59df50081fUwe Kleine-König if (!r) 220cea896238fbfdbce254f51fc8fd78c59df50081fUwe Kleine-König return -ENOMEM; 22137c12e7497b6fe2b6a890814f0ff4edce696d862Russell King } 222cea896238fbfdbce254f51fc8fd78c59df50081fUwe Kleine-König 2234a03d6f7c863a039b937649a93341615f531358eUwe Kleine-König kfree(pdev->resource); 224cea896238fbfdbce254f51fc8fd78c59df50081fUwe Kleine-König pdev->resource = r; 225cea896238fbfdbce254f51fc8fd78c59df50081fUwe Kleine-König pdev->num_resources = num; 226cea896238fbfdbce254f51fc8fd78c59df50081fUwe Kleine-König return 0; 22737c12e7497b6fe2b6a890814f0ff4edce696d862Russell King} 22837c12e7497b6fe2b6a890814f0ff4edce696d862Russell KingEXPORT_SYMBOL_GPL(platform_device_add_resources); 22937c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 23037c12e7497b6fe2b6a890814f0ff4edce696d862Russell King/** 2313c31f07ad0dab02fe17195d32a965d57fd947707Ben Hutchings * platform_device_add_data - add platform-specific data to a platform device 2324a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @pdev: platform device allocated by platform_device_alloc to add resources to 2334a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @data: platform specific data for this platform device 2344a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @size: size of platform specific data 23537c12e7497b6fe2b6a890814f0ff4edce696d862Russell King * 2364a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * Add a copy of platform specific data to the platform device's 2374a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_data pointer. The memory associated with the platform data 2384a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * will be freed when the platform device is released. 23937c12e7497b6fe2b6a890814f0ff4edce696d862Russell King */ 2404a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartmanint platform_device_add_data(struct platform_device *pdev, const void *data, 2414a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman size_t size) 24237c12e7497b6fe2b6a890814f0ff4edce696d862Russell King{ 24327a33f9e8fb203e71925257cf039fe6ec623c5d1Uwe Kleine-König void *d = NULL; 2445cfc64ceb6222aabec640ba76e89529a8fc2c1f0Anton Vorontsov 24527a33f9e8fb203e71925257cf039fe6ec623c5d1Uwe Kleine-König if (data) { 24627a33f9e8fb203e71925257cf039fe6ec623c5d1Uwe Kleine-König d = kmemdup(data, size, GFP_KERNEL); 24727a33f9e8fb203e71925257cf039fe6ec623c5d1Uwe Kleine-König if (!d) 24827a33f9e8fb203e71925257cf039fe6ec623c5d1Uwe Kleine-König return -ENOMEM; 24937c12e7497b6fe2b6a890814f0ff4edce696d862Russell King } 25027a33f9e8fb203e71925257cf039fe6ec623c5d1Uwe Kleine-König 251251e031d132ea3d03e0a32f2240c67f449979c5dUwe Kleine-König kfree(pdev->dev.platform_data); 25227a33f9e8fb203e71925257cf039fe6ec623c5d1Uwe Kleine-König pdev->dev.platform_data = d; 25327a33f9e8fb203e71925257cf039fe6ec623c5d1Uwe Kleine-König return 0; 25437c12e7497b6fe2b6a890814f0ff4edce696d862Russell King} 25537c12e7497b6fe2b6a890814f0ff4edce696d862Russell KingEXPORT_SYMBOL_GPL(platform_device_add_data); 25637c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 25737c12e7497b6fe2b6a890814f0ff4edce696d862Russell King/** 2584a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_device_add - add a platform device to device hierarchy 2594a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @pdev: platform device we're adding 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2614a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * This is part 2 of platform_device_register(), though may be called 2624a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * separately _iff_ pdev was allocated by platform_device_alloc(). 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 26437c12e7497b6fe2b6a890814f0ff4edce696d862Russell Kingint platform_device_add(struct platform_device *pdev) 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, ret = 0; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pdev) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pdev->dev.parent) 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->dev.parent = &platform_bus; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pdev->dev.bus = &platform_bus_type; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev->id != -1) 2771e0b2cf933ebf32494eba3f668859ba57f06a951Kay Sievers dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 279acc0e90fbccbc6e4d48184cba0983ea044e131afGreg Kroah-Hartman dev_set_name(&pdev->dev, "%s", pdev->name); 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < pdev->num_resources; i++) { 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *p, *r = &pdev->resource[i]; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (r->name == NULL) 2851e0b2cf933ebf32494eba3f668859ba57f06a951Kay Sievers r->name = dev_name(&pdev->dev); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = r->parent; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!p) { 289c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm if (resource_type(r) == IORESOURCE_MEM) 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = &iomem_resource; 291c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm else if (resource_type(r) == IORESOURCE_IO) 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds p = &ioport_resource; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 295d960bb4db9f422b5c3c82e0dfd6c8213a4fc430dKumar Gala if (p && insert_resource(p, r)) { 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "%s: failed to claim resource %d\n", 2981e0b2cf933ebf32494eba3f668859ba57f06a951Kay Sievers dev_name(&pdev->dev), i); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EBUSY; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto failed; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pr_debug("Registering platform device '%s'. Parent at %s\n", 3051e0b2cf933ebf32494eba3f668859ba57f06a951Kay Sievers dev_name(&pdev->dev), dev_name(pdev->dev.parent)); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 307e391553222211e07dfbe2f01c413b4e6d0ae32aaRussell King ret = device_add(&pdev->dev); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret == 0) 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds failed: 312c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm while (--i >= 0) { 313c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm struct resource *r = &pdev->resource[i]; 314c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm unsigned long type = resource_type(r); 315c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm 316c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm if (type == IORESOURCE_MEM || type == IORESOURCE_IO) 317c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm release_resource(r); 318c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm } 319c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 32237c12e7497b6fe2b6a890814f0ff4edce696d862Russell KingEXPORT_SYMBOL_GPL(platform_device_add); 32337c12e7497b6fe2b6a890814f0ff4edce696d862Russell King 32437c12e7497b6fe2b6a890814f0ff4edce696d862Russell King/** 3254a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_device_del - remove a platform-level device 3264a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @pdev: platform device we're removing 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3284a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * Note that this function will also release all memory- and port-based 3294a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * resources owned by the device (@dev->resource). This function must 3304a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * _only_ be externally called in error cases. All other usage is a bug. 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 33293ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhovvoid platform_device_del(struct platform_device *pdev) 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pdev) { 337dc4c15d44b2b43279b2667baa7645c65c2ff960eJean Delvare device_del(&pdev->dev); 338dc4c15d44b2b43279b2667baa7645c65c2ff960eJean Delvare 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < pdev->num_resources; i++) { 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *r = &pdev->resource[i]; 341c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm unsigned long type = resource_type(r); 342c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm 343c9f66169f1c696f9489503d7de92daff135c1efdMagnus Damm if (type == IORESOURCE_MEM || type == IORESOURCE_IO) 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_resource(r); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 34893ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry TorokhovEXPORT_SYMBOL_GPL(platform_device_del); 34993ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov 35093ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov/** 3514a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_device_register - add a platform-level device 3524a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @pdev: platform device we're adding 35393ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov */ 3544a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartmanint platform_device_register(struct platform_device *pdev) 35593ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov{ 35693ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov device_initialize(&pdev->dev); 357a77ce8167cc1d0370fcb1d79b367d62e050cb2b0Kumar Gala arch_setup_pdev_archdata(pdev); 35893ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov return platform_device_add(pdev); 35993ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov} 360a96b204208443ab7e23c681f7ddabe807a741d0cDmitry TorokhovEXPORT_SYMBOL_GPL(platform_device_register); 36193ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov 36293ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov/** 3634a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_device_unregister - unregister a platform-level device 3644a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @pdev: platform device we're unregistering 36593ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov * 3664a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * Unregistration is done in 2 steps. First we release all resources 3674a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * and remove it from the subsystem, then we drop reference count by 3684a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * calling platform_device_put(). 36993ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov */ 3704a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartmanvoid platform_device_unregister(struct platform_device *pdev) 37193ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov{ 37293ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov platform_device_del(pdev); 37393ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov platform_device_put(pdev); 37493ce3061be212f6280e7ccafa9a7f698a95c6d75Dmitry Torokhov} 375a96b204208443ab7e23c681f7ddabe807a741d0cDmitry TorokhovEXPORT_SYMBOL_GPL(platform_device_unregister); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 37801dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König * platform_device_register_full - add a platform-level device with 37944f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-König * resources and platform-specific data 38049a4ec188f9a96c9a5567956718213d38a456a19David Brownell * 38101dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König * @pdevinfo: data used to create device 382d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov * 383f0eae0ed3b7d4182a6b4dd03540a738518ea3163Jani Nikula * Returns &struct platform_device pointer on success, or ERR_PTR() on error. 384d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov */ 38501dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-Königstruct platform_device *platform_device_register_full( 3865a3072be6ce00b10565c78da05ad78df41310045Uwe Kleine-König const struct platform_device_info *pdevinfo) 387d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov{ 38844f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-König int ret = -ENOMEM; 389d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov struct platform_device *pdev; 390d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov 39101dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id); 39244f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-König if (!pdev) 39301dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König goto err_alloc; 39401dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König 39501dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König pdev->dev.parent = pdevinfo->parent; 39601dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König 39701dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König if (pdevinfo->dma_mask) { 39801dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König /* 39901dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König * This memory isn't freed when the device is put, 40001dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König * I don't have a nice idea for that though. Conceptually 40101dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König * dma_mask in struct device should not be a pointer. 40201dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König * See http://thread.gmane.org/gmane.linux.kernel.pci/9081 40301dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König */ 40401dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König pdev->dev.dma_mask = 40501dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL); 40601dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König if (!pdev->dev.dma_mask) 40701dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König goto err; 40801dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König 40901dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König *pdev->dev.dma_mask = pdevinfo->dma_mask; 41001dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König pdev->dev.coherent_dma_mask = pdevinfo->dma_mask; 41101dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König } 412d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov 41301dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König ret = platform_device_add_resources(pdev, 41401dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König pdevinfo->res, pdevinfo->num_res); 415807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov if (ret) 416807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov goto err; 41744f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-König 41801dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König ret = platform_device_add_data(pdev, 41901dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König pdevinfo->data, pdevinfo->size_data); 420807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov if (ret) 421807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov goto err; 422d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov 42344f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-König ret = platform_device_add(pdev); 42444f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-König if (ret) { 42544f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-Königerr: 42601dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König kfree(pdev->dev.dma_mask); 42701dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-König 42801dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-Königerr_alloc: 42944f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-König platform_device_put(pdev); 43044f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-König return ERR_PTR(ret); 43144f28bdea09415d40b4d73a7668db5961362ec53Uwe Kleine-König } 432d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov 433d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov return pdev; 434d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov} 43501dcc60a7cb8cd5193676554b94a90d349bdfd15Uwe Kleine-KönigEXPORT_SYMBOL_GPL(platform_device_register_full); 436d8bf254089a6c31d7d01a4d1d2f1861662900855Dmitry Eremin-Solenikov 43700d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell Kingstatic int platform_drv_probe(struct device *_dev) 43800d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King{ 43900d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King struct platform_driver *drv = to_platform_driver(_dev->driver); 44000d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King struct platform_device *dev = to_platform_device(_dev); 44100d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King 44200d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King return drv->probe(dev); 44300d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King} 44400d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King 445c67334fbdfbba533af767610cf3fde8a49710e62David Brownellstatic int platform_drv_probe_fail(struct device *_dev) 446c67334fbdfbba533af767610cf3fde8a49710e62David Brownell{ 447c67334fbdfbba533af767610cf3fde8a49710e62David Brownell return -ENXIO; 448c67334fbdfbba533af767610cf3fde8a49710e62David Brownell} 449c67334fbdfbba533af767610cf3fde8a49710e62David Brownell 45000d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell Kingstatic int platform_drv_remove(struct device *_dev) 45100d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King{ 45200d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King struct platform_driver *drv = to_platform_driver(_dev->driver); 45300d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King struct platform_device *dev = to_platform_device(_dev); 45400d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King 45500d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King return drv->remove(dev); 45600d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King} 45700d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King 45800d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell Kingstatic void platform_drv_shutdown(struct device *_dev) 45900d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King{ 46000d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King struct platform_driver *drv = to_platform_driver(_dev->driver); 46100d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King struct platform_device *dev = to_platform_device(_dev); 46200d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King 46300d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King drv->shutdown(dev); 46400d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King} 46500d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King 46600d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King/** 4673c31f07ad0dab02fe17195d32a965d57fd947707Ben Hutchings * platform_driver_register - register a driver for platform-level devices 4684a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @drv: platform driver structure 46900d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King */ 47000d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell Kingint platform_driver_register(struct platform_driver *drv) 47100d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King{ 47200d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King drv->driver.bus = &platform_bus_type; 47300d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King if (drv->probe) 47400d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King drv->driver.probe = platform_drv_probe; 47500d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King if (drv->remove) 47600d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King drv->driver.remove = platform_drv_remove; 47700d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King if (drv->shutdown) 47800d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King drv->driver.shutdown = platform_drv_shutdown; 479783ea7d4eeefe895f2731fe73ac951e94418927bMagnus Damm 48000d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King return driver_register(&drv->driver); 48100d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King} 48200d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell KingEXPORT_SYMBOL_GPL(platform_driver_register); 48300d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King 48400d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King/** 4853c31f07ad0dab02fe17195d32a965d57fd947707Ben Hutchings * platform_driver_unregister - unregister a driver for platform-level devices 4864a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @drv: platform driver structure 48700d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King */ 48800d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell Kingvoid platform_driver_unregister(struct platform_driver *drv) 48900d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King{ 49000d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King driver_unregister(&drv->driver); 49100d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King} 49200d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell KingEXPORT_SYMBOL_GPL(platform_driver_unregister); 49300d3dcdd96646be6059cc21f2efa94c4edc1eda5Russell King 494c67334fbdfbba533af767610cf3fde8a49710e62David Brownell/** 495c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * platform_driver_probe - register driver for non-hotpluggable device 496c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * @drv: platform driver structure 497c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * @probe: the driver probe routine, probably from an __init section 498c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * 499c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * Use this instead of platform_driver_register() when you know the device 500c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * is not hotpluggable and has already been registered, and you want to 501c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * remove its run-once probe() infrastructure from memory after the driver 502c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * has bound to the device. 503c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * 504c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * One typical use for this would be with drivers for controllers integrated 505c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * into system-on-chip processors, where the controller devices have been 506c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * configured as part of board setup. 507c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * 508c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * Returns zero if the driver registered and bound to a device, else returns 509c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * a negative error code and with the driver not registered. 510c67334fbdfbba533af767610cf3fde8a49710e62David Brownell */ 511c63e07834bb12910bea41da15b8902150f5217c2Andrew Mortonint __init_or_module platform_driver_probe(struct platform_driver *drv, 512c67334fbdfbba533af767610cf3fde8a49710e62David Brownell int (*probe)(struct platform_device *)) 513c67334fbdfbba533af767610cf3fde8a49710e62David Brownell{ 514c67334fbdfbba533af767610cf3fde8a49710e62David Brownell int retval, code; 515c67334fbdfbba533af767610cf3fde8a49710e62David Brownell 5161a6f2a7512021ceae3c4201c7aab07f032e9ce91Dmitry Torokhov /* make sure driver won't have bind/unbind attributes */ 5171a6f2a7512021ceae3c4201c7aab07f032e9ce91Dmitry Torokhov drv->driver.suppress_bind_attrs = true; 5181a6f2a7512021ceae3c4201c7aab07f032e9ce91Dmitry Torokhov 519c67334fbdfbba533af767610cf3fde8a49710e62David Brownell /* temporary section violation during probe() */ 520c67334fbdfbba533af767610cf3fde8a49710e62David Brownell drv->probe = probe; 521c67334fbdfbba533af767610cf3fde8a49710e62David Brownell retval = code = platform_driver_register(drv); 522c67334fbdfbba533af767610cf3fde8a49710e62David Brownell 5231a6f2a7512021ceae3c4201c7aab07f032e9ce91Dmitry Torokhov /* 5241a6f2a7512021ceae3c4201c7aab07f032e9ce91Dmitry Torokhov * Fixup that section violation, being paranoid about code scanning 525c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * the list of drivers in order to probe new devices. Check to see 526c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * if the probe was successful, and make sure any forced probes of 527c67334fbdfbba533af767610cf3fde8a49710e62David Brownell * new devices fail. 528c67334fbdfbba533af767610cf3fde8a49710e62David Brownell */ 529d79d32440c33cf60f1e0efbeb8144b1647be0b50Patrick Pannuto spin_lock(&drv->driver.bus->p->klist_drivers.k_lock); 530c67334fbdfbba533af767610cf3fde8a49710e62David Brownell drv->probe = NULL; 531e5dd12784617f0f1fae5f96a7fac1ec4c49fadbeGreg Kroah-Hartman if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list)) 532c67334fbdfbba533af767610cf3fde8a49710e62David Brownell retval = -ENODEV; 533c67334fbdfbba533af767610cf3fde8a49710e62David Brownell drv->driver.probe = platform_drv_probe_fail; 534d79d32440c33cf60f1e0efbeb8144b1647be0b50Patrick Pannuto spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock); 535c67334fbdfbba533af767610cf3fde8a49710e62David Brownell 536c67334fbdfbba533af767610cf3fde8a49710e62David Brownell if (code != retval) 537c67334fbdfbba533af767610cf3fde8a49710e62David Brownell platform_driver_unregister(drv); 538c67334fbdfbba533af767610cf3fde8a49710e62David Brownell return retval; 539c67334fbdfbba533af767610cf3fde8a49710e62David Brownell} 540c67334fbdfbba533af767610cf3fde8a49710e62David BrownellEXPORT_SYMBOL_GPL(platform_driver_probe); 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 542ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov/** 543ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * platform_create_bundle - register driver and create corresponding device 544ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * @driver: platform driver structure 545ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * @probe: the driver probe routine, probably from an __init section 546ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * @res: set of resources that needs to be allocated for the device 547ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * @n_res: number of resources 548ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * @data: platform specific data for this platform device 549ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * @size: size of platform specific data 550ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * 551ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * Use this in legacy-style modules that probe hardware directly and 552ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov * register a single platform device and corresponding platform driver. 553f0eae0ed3b7d4182a6b4dd03540a738518ea3163Jani Nikula * 554f0eae0ed3b7d4182a6b4dd03540a738518ea3163Jani Nikula * Returns &struct platform_device pointer on success, or ERR_PTR() on error. 555ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov */ 556ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhovstruct platform_device * __init_or_module platform_create_bundle( 557ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov struct platform_driver *driver, 558ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov int (*probe)(struct platform_device *), 559ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov struct resource *res, unsigned int n_res, 560ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov const void *data, size_t size) 561ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov{ 562ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov struct platform_device *pdev; 563ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov int error; 564ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov 565ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov pdev = platform_device_alloc(driver->driver.name, -1); 566ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov if (!pdev) { 567ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov error = -ENOMEM; 568ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov goto err_out; 569ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov } 570ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov 571807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov error = platform_device_add_resources(pdev, res, n_res); 572807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov if (error) 573807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov goto err_pdev_put; 574ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov 575807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov error = platform_device_add_data(pdev, data, size); 576807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov if (error) 577807508c8ff9af6ce8f25c5ca5f3eb06a8e7d3286Anton Vorontsov goto err_pdev_put; 578ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov 579ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov error = platform_device_add(pdev); 580ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov if (error) 581ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov goto err_pdev_put; 582ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov 583ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov error = platform_driver_probe(driver, probe); 584ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov if (error) 585ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov goto err_pdev_del; 586ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov 587ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov return pdev; 588ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov 589ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhoverr_pdev_del: 590ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov platform_device_del(pdev); 591ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhoverr_pdev_put: 592ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov platform_device_put(pdev); 593ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhoverr_out: 594ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov return ERR_PTR(error); 595ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov} 596ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry TorokhovEXPORT_SYMBOL_GPL(platform_create_bundle); 597ecdf6ceb8cf4756bd4214bf9755755752b6015f5Dmitry Torokhov 598a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell/* modalias support enables more hands-off userspace setup: 599a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell * (a) environment variable lets new-style hotplug events work once system is 600a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell * fully running: "modprobe $MODALIAS" 601a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell * (b) sysfs attribute lets new-style coldplug recover from hotplug events 602a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell * mishandled before system is fully running: "modprobe $(cat modalias)" 603a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell */ 6044a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartmanstatic ssize_t modalias_show(struct device *dev, struct device_attribute *a, 6054a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman char *buf) 606a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell{ 607a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell struct platform_device *pdev = to_platform_device(dev); 60843cc71eed1250755986da4c0f9898f9a635cb3bfKay Sievers int len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name); 609a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell 610a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; 611a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell} 612a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell 613a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownellstatic struct device_attribute platform_dev_attrs[] = { 614a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell __ATTR_RO(modalias), 615a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell __ATTR_NULL, 616a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell}; 617a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell 6187eff2e7a8b65c25920207324e56611150eb1cd9aKay Sieversstatic int platform_uevent(struct device *dev, struct kobj_uevent_env *env) 619a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell{ 620a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell struct platform_device *pdev = to_platform_device(dev); 621eca3930163ba8884060ce9d9ff5ef0d9b7c7b00fGrant Likely int rc; 622eca3930163ba8884060ce9d9ff5ef0d9b7c7b00fGrant Likely 623eca3930163ba8884060ce9d9ff5ef0d9b7c7b00fGrant Likely /* Some devices have extra OF data and an OF-style MODALIAS */ 624eca3930163ba8884060ce9d9ff5ef0d9b7c7b00fGrant Likely rc = of_device_uevent(dev,env); 625eca3930163ba8884060ce9d9ff5ef0d9b7c7b00fGrant Likely if (rc != -ENODEV) 626eca3930163ba8884060ce9d9ff5ef0d9b7c7b00fGrant Likely return rc; 627a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell 62857fee4a58fe802272742caae248872c392a60670Eric Miao add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, 6290a26813c9f528f17901b2f2394fba8557d2c9485Sebastian Andrzej Siewior pdev->name); 630a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell return 0; 631a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell} 632a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell 63357fee4a58fe802272742caae248872c392a60670Eric Miaostatic const struct platform_device_id *platform_match_id( 634831fad2f75f0d7bfc339de81173e7068a3c72276Uwe Kleine-König const struct platform_device_id *id, 63557fee4a58fe802272742caae248872c392a60670Eric Miao struct platform_device *pdev) 63657fee4a58fe802272742caae248872c392a60670Eric Miao{ 63757fee4a58fe802272742caae248872c392a60670Eric Miao while (id->name[0]) { 63857fee4a58fe802272742caae248872c392a60670Eric Miao if (strcmp(pdev->name, id->name) == 0) { 63957fee4a58fe802272742caae248872c392a60670Eric Miao pdev->id_entry = id; 64057fee4a58fe802272742caae248872c392a60670Eric Miao return id; 64157fee4a58fe802272742caae248872c392a60670Eric Miao } 64257fee4a58fe802272742caae248872c392a60670Eric Miao id++; 64357fee4a58fe802272742caae248872c392a60670Eric Miao } 64457fee4a58fe802272742caae248872c392a60670Eric Miao return NULL; 64557fee4a58fe802272742caae248872c392a60670Eric Miao} 64657fee4a58fe802272742caae248872c392a60670Eric Miao 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/** 6484a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * platform_match - bind platform device to platform driver. 6494a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @dev: device. 6504a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * @drv: driver. 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 6524a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * Platform device IDs are assumed to be encoded like this: 6534a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * "<name><instance>", where <name> is a short description of the type of 6544a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * device, like "pci" or "floppy", and <instance> is the enumerated 6554a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * instance of the device, like '0' or '42'. Driver IDs are simply 6564a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * "<name>". So, extract the <name> from the platform_device structure, 6574a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * and compare it against the name of the driver. Return whether they match 6584a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartman * or not. 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 6604a3ad20ccd8f4d2a0535cf98fa83f7b561ba59a9Greg Kroah-Hartmanstatic int platform_match(struct device *dev, struct device_driver *drv) 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 66271b3e0c1ad90f28e34c105069175cbd4edb43dfaEric Miao struct platform_device *pdev = to_platform_device(dev); 66357fee4a58fe802272742caae248872c392a60670Eric Miao struct platform_driver *pdrv = to_platform_driver(drv); 66457fee4a58fe802272742caae248872c392a60670Eric Miao 66505212157e94ccf4cf458413bbba509cfa95ff92bGrant Likely /* Attempt an OF style match first */ 66605212157e94ccf4cf458413bbba509cfa95ff92bGrant Likely if (of_driver_match_device(dev, drv)) 66705212157e94ccf4cf458413bbba509cfa95ff92bGrant Likely return 1; 66805212157e94ccf4cf458413bbba509cfa95ff92bGrant Likely 66905212157e94ccf4cf458413bbba509cfa95ff92bGrant Likely /* Then try to match against the id table */ 67057fee4a58fe802272742caae248872c392a60670Eric Miao if (pdrv->id_table) 67157fee4a58fe802272742caae248872c392a60670Eric Miao return platform_match_id(pdrv->id_table, pdev) != NULL; 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67357fee4a58fe802272742caae248872c392a60670Eric Miao /* fall-back to driver name match */ 6741e0b2cf933ebf32494eba3f668859ba57f06a951Kay Sievers return (strcmp(pdev->name, drv->name) == 0); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 67725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki#ifdef CONFIG_PM_SLEEP 67825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 67925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysockistatic int platform_legacy_suspend(struct device *dev, pm_message_t mesg) 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 681783ea7d4eeefe895f2731fe73ac951e94418927bMagnus Damm struct platform_driver *pdrv = to_platform_driver(dev->driver); 682783ea7d4eeefe895f2731fe73ac951e94418927bMagnus Damm struct platform_device *pdev = to_platform_device(dev); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 685783ea7d4eeefe895f2731fe73ac951e94418927bMagnus Damm if (dev->driver && pdrv->suspend) 686783ea7d4eeefe895f2731fe73ac951e94418927bMagnus Damm ret = pdrv->suspend(pdev, mesg); 687386415d88b1ae50304f9c61aa3e0db082fa90428David Brownell 688386415d88b1ae50304f9c61aa3e0db082fa90428David Brownell return ret; 689386415d88b1ae50304f9c61aa3e0db082fa90428David Brownell} 690386415d88b1ae50304f9c61aa3e0db082fa90428David Brownell 69125e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysockistatic int platform_legacy_resume(struct device *dev) 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 693783ea7d4eeefe895f2731fe73ac951e94418927bMagnus Damm struct platform_driver *pdrv = to_platform_driver(dev->driver); 694783ea7d4eeefe895f2731fe73ac951e94418927bMagnus Damm struct platform_device *pdev = to_platform_device(dev); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret = 0; 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 697783ea7d4eeefe895f2731fe73ac951e94418927bMagnus Damm if (dev->driver && pdrv->resume) 698783ea7d4eeefe895f2731fe73ac951e94418927bMagnus Damm ret = pdrv->resume(pdev); 6999480e307cd88ef09ec9294c7d97ebec18e6d2221Russell King 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 70369c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysocki#endif /* CONFIG_PM_SLEEP */ 7049d7302299ee96ca954fe4ab8ca640333b6e19ad0Magnus Damm 70525e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki#ifdef CONFIG_SUSPEND 70625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 70769c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysockiint platform_pm_suspend(struct device *dev) 70825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki{ 70925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki struct device_driver *drv = dev->driver; 71025e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki int ret = 0; 71125e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 712adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (!drv) 713adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki return 0; 714adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki 715adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (drv->pm) { 71625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki if (drv->pm->suspend) 71725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = drv->pm->suspend(dev); 71825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } else { 71925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = platform_legacy_suspend(dev, PMSG_SUSPEND); 72025e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } 72125e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 72225e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki return ret; 72325e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki} 72425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 72569c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysockiint platform_pm_resume(struct device *dev) 72625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki{ 72725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki struct device_driver *drv = dev->driver; 72825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki int ret = 0; 72925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 730adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (!drv) 731adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki return 0; 732adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki 733adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (drv->pm) { 73425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki if (drv->pm->resume) 73525e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = drv->pm->resume(dev); 73625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } else { 73725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = platform_legacy_resume(dev); 73825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } 73925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 74025e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki return ret; 74125e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki} 74225e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 74369c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysocki#endif /* CONFIG_SUSPEND */ 74425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 7451f112cee07b314e244ee9e71d9c1e6950dc13327Rafael J. Wysocki#ifdef CONFIG_HIBERNATE_CALLBACKS 74625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 74769c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysockiint platform_pm_freeze(struct device *dev) 74825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki{ 74925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki struct device_driver *drv = dev->driver; 75025e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki int ret = 0; 75125e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 75225e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki if (!drv) 75325e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki return 0; 75425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 75525e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki if (drv->pm) { 75625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki if (drv->pm->freeze) 75725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = drv->pm->freeze(dev); 75825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } else { 75925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = platform_legacy_suspend(dev, PMSG_FREEZE); 76025e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } 76125e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 76225e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki return ret; 76325e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki} 76425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 76569c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysockiint platform_pm_thaw(struct device *dev) 76625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki{ 76725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki struct device_driver *drv = dev->driver; 76825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki int ret = 0; 76925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 770adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (!drv) 771adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki return 0; 772adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki 773adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (drv->pm) { 77425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki if (drv->pm->thaw) 77525e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = drv->pm->thaw(dev); 77625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } else { 77725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = platform_legacy_resume(dev); 77825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } 77925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 78025e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki return ret; 78125e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki} 78225e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 78369c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysockiint platform_pm_poweroff(struct device *dev) 78425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki{ 78525e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki struct device_driver *drv = dev->driver; 78625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki int ret = 0; 78725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 788adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (!drv) 789adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki return 0; 790adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki 791adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (drv->pm) { 79225e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki if (drv->pm->poweroff) 79325e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = drv->pm->poweroff(dev); 79425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } else { 79525e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = platform_legacy_suspend(dev, PMSG_HIBERNATE); 79625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } 79725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 79825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki return ret; 79925e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki} 80025e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 80169c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysockiint platform_pm_restore(struct device *dev) 80225e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki{ 80325e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki struct device_driver *drv = dev->driver; 80425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki int ret = 0; 80525e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 806adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (!drv) 807adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki return 0; 808adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki 809adf094931ffb25ef4b381559918f1a34181a5273Rafael J. Wysocki if (drv->pm) { 81025e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki if (drv->pm->restore) 81125e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = drv->pm->restore(dev); 81225e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } else { 81325e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki ret = platform_legacy_resume(dev); 81425e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki } 81525e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 81625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki return ret; 81725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki} 81825e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 81969c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysocki#endif /* CONFIG_HIBERNATE_CALLBACKS */ 82025e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 821d9ab77161d811ffb0bccf396f7155cc905c1b9e1Dmitry Torokhovstatic const struct dev_pm_ops platform_dev_pm_ops = { 8228b313a38ecffc0ff0b4c5115f0a461f73b7dfdb6Rafael J. Wysocki .runtime_suspend = pm_generic_runtime_suspend, 8238b313a38ecffc0ff0b4c5115f0a461f73b7dfdb6Rafael J. Wysocki .runtime_resume = pm_generic_runtime_resume, 8248b313a38ecffc0ff0b4c5115f0a461f73b7dfdb6Rafael J. Wysocki .runtime_idle = pm_generic_runtime_idle, 82569c9dd1ecf446ad8a830e4afc539a2a1adc85b78Rafael J. Wysocki USE_PLATFORM_PM_SLEEP_OPS 82625e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki}; 82725e18499e08cb097cbbfeab5de25d094d5312ee5Rafael J. Wysocki 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct bus_type platform_bus_type = { 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "platform", 830a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell .dev_attrs = platform_dev_attrs, 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .match = platform_match, 832a0245f7ad5214cb00131d7cd176446e067c913dcDavid Brownell .uevent = platform_uevent, 8339d7302299ee96ca954fe4ab8ca640333b6e19ad0Magnus Damm .pm = &platform_dev_pm_ops, 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 835a96b204208443ab7e23c681f7ddabe807a741d0cDmitry TorokhovEXPORT_SYMBOL_GPL(platform_bus_type); 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint __init platform_bus_init(void) 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 839fbfb14455391b89edcf37327526988dea7849532Cornelia Huck int error; 840fbfb14455391b89edcf37327526988dea7849532Cornelia Huck 84113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm early_platform_cleanup(); 84213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 843fbfb14455391b89edcf37327526988dea7849532Cornelia Huck error = device_register(&platform_bus); 844fbfb14455391b89edcf37327526988dea7849532Cornelia Huck if (error) 845fbfb14455391b89edcf37327526988dea7849532Cornelia Huck return error; 846fbfb14455391b89edcf37327526988dea7849532Cornelia Huck error = bus_register(&platform_bus_type); 847fbfb14455391b89edcf37327526988dea7849532Cornelia Huck if (error) 848fbfb14455391b89edcf37327526988dea7849532Cornelia Huck device_unregister(&platform_bus); 849fbfb14455391b89edcf37327526988dea7849532Cornelia Huck return error; 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsu64 dma_get_required_mask(struct device *dev) 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT); 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT)); 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u64 mask; 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!high_totalram) { 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* convert to mask just covering totalram */ 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds low_totalram = (1 << (fls(low_totalram) - 1)); 8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds low_totalram += low_totalram - 1; 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = low_totalram; 8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds high_totalram = (1 << (fls(high_totalram) - 1)); 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds high_totalram += high_totalram - 1; 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mask = (((u64)high_totalram) << 32) + 0xffffffff; 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 869e88a0c2ca81207a75afe5bbb8020541dabf606acJames Bottomley return mask; 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEXPORT_SYMBOL_GPL(dma_get_required_mask); 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 87313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 87413977091a988fb0d21821c2221ddc920eba36b79Magnus Dammstatic __initdata LIST_HEAD(early_platform_driver_list); 87513977091a988fb0d21821c2221ddc920eba36b79Magnus Dammstatic __initdata LIST_HEAD(early_platform_device_list); 87613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 87713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm/** 8784d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * early_platform_driver_register - register early platform driver 879d86c1302c58e4d4ebd99d459c2daff13613ac7f4Randy Dunlap * @epdrv: early_platform driver structure 88013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @buf: string passed from early_param() 8814d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * 8824d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * Helper function for early_platform_init() / early_platform_init_buffer() 88313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 88413977091a988fb0d21821c2221ddc920eba36b79Magnus Dammint __init early_platform_driver_register(struct early_platform_driver *epdrv, 88513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm char *buf) 88613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm{ 887c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm char *tmp; 88813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int n; 88913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 89013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm /* Simply add the driver to the end of the global list. 89113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * Drivers will by default be put on the list in compiled-in order. 89213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 89313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (!epdrv->list.next) { 89413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm INIT_LIST_HEAD(&epdrv->list); 89513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm list_add_tail(&epdrv->list, &early_platform_driver_list); 89613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 89713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 89813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm /* If the user has specified device then make sure the driver 89913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * gets prioritized. The driver of the last device specified on 90013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * command line will be put first on the list. 90113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 90213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm n = strlen(epdrv->pdrv->driver.name); 90313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) { 90413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm list_move(&epdrv->list, &early_platform_driver_list); 90513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 906c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm /* Allow passing parameters after device name */ 907c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm if (buf[n] == '\0' || buf[n] == ',') 90813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm epdrv->requested_id = -1; 909c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm else { 910c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm epdrv->requested_id = simple_strtoul(&buf[n + 1], 911c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm &tmp, 10); 912c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm 913c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm if (buf[n] != '.' || (tmp == &buf[n + 1])) { 914c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm epdrv->requested_id = EARLY_PLATFORM_ID_ERROR; 915c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm n = 0; 916c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm } else 917c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm n += strcspn(&buf[n + 1], ",") + 1; 918c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm } 919c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm 920c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm if (buf[n] == ',') 921c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm n++; 922c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm 923c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm if (epdrv->bufsize) { 924c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm memcpy(epdrv->buffer, &buf[n], 925c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1)); 926c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm epdrv->buffer[epdrv->bufsize - 1] = '\0'; 927c60e0504c8e4fa14179d0687d80ef25148dd6dd4Magnus Damm } 92813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 92913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 93013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm return 0; 93113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm} 93213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 93313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm/** 9344d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * early_platform_add_devices - adds a number of early platform devices 93513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @devs: array of early platform devices to add 93613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @num: number of early platform devices in array 9374d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * 9384d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * Used by early architecture code to register early platform devices and 9394d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * their platform data. 94013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 94113977091a988fb0d21821c2221ddc920eba36b79Magnus Dammvoid __init early_platform_add_devices(struct platform_device **devs, int num) 94213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm{ 94313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm struct device *dev; 94413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int i; 94513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 94613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm /* simply add the devices to list */ 94713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm for (i = 0; i < num; i++) { 94813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm dev = &devs[i]->dev; 94913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 95013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (!dev->devres_head.next) { 95113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm INIT_LIST_HEAD(&dev->devres_head); 95213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm list_add_tail(&dev->devres_head, 95313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm &early_platform_device_list); 95413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 95513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 95613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm} 95713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 95813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm/** 9594d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * early_platform_driver_register_all - register early platform drivers 96013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @class_str: string to identify early platform driver class 9614d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * 9624d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * Used by architecture code to register all early platform drivers 9634d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * for a certain class. If omitted then only early platform drivers 9644d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * with matching kernel command line class parameters will be registered. 96513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 96613977091a988fb0d21821c2221ddc920eba36b79Magnus Dammvoid __init early_platform_driver_register_all(char *class_str) 96713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm{ 96813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm /* The "class_str" parameter may or may not be present on the kernel 96913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * command line. If it is present then there may be more than one 97013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * matching parameter. 97113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * 97213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * Since we register our early platform drivers using early_param() 97313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * we need to make sure that they also get registered in the case 97413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * when the parameter is missing from the kernel command line. 97513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * 97613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * We use parse_early_options() to make sure the early_param() gets 97713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * called at least once. The early_param() may be called more than 97813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * once since the name of the preferred device may be specified on 97913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * the kernel command line. early_platform_driver_register() handles 98013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * this case for us. 98113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 98213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm parse_early_options(class_str); 98313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm} 98413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 98513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm/** 9864d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * early_platform_match - find early platform device matching driver 987d86c1302c58e4d4ebd99d459c2daff13613ac7f4Randy Dunlap * @epdrv: early platform driver structure 98813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @id: id to match against 98913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 99013977091a988fb0d21821c2221ddc920eba36b79Magnus Dammstatic __init struct platform_device * 99113977091a988fb0d21821c2221ddc920eba36b79Magnus Dammearly_platform_match(struct early_platform_driver *epdrv, int id) 99213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm{ 99313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm struct platform_device *pd; 99413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 99513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) 99613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (platform_match(&pd->dev, &epdrv->pdrv->driver)) 99713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (pd->id == id) 99813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm return pd; 99913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 100013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm return NULL; 100113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm} 100213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 100313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm/** 10044d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * early_platform_left - check if early platform driver has matching devices 1005d86c1302c58e4d4ebd99d459c2daff13613ac7f4Randy Dunlap * @epdrv: early platform driver structure 100613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @id: return true if id or above exists 100713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 100813977091a988fb0d21821c2221ddc920eba36b79Magnus Dammstatic __init int early_platform_left(struct early_platform_driver *epdrv, 100913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int id) 101013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm{ 101113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm struct platform_device *pd; 101213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 101313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm list_for_each_entry(pd, &early_platform_device_list, dev.devres_head) 101413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (platform_match(&pd->dev, &epdrv->pdrv->driver)) 101513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (pd->id >= id) 101613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm return 1; 101713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 101813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm return 0; 101913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm} 102013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 102113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm/** 10224d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * early_platform_driver_probe_id - probe drivers matching class_str and id 102313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @class_str: string to identify early platform driver class 102413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @id: id to match against 102513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @nr_probe: number of platform devices to successfully probe before exiting 102613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 102713977091a988fb0d21821c2221ddc920eba36b79Magnus Dammstatic int __init early_platform_driver_probe_id(char *class_str, 102813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int id, 102913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int nr_probe) 103013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm{ 103113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm struct early_platform_driver *epdrv; 103213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm struct platform_device *match; 103313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int match_id; 103413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int n = 0; 103513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int left = 0; 103613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 103713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm list_for_each_entry(epdrv, &early_platform_driver_list, list) { 103813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm /* only use drivers matching our class_str */ 103913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (strcmp(class_str, epdrv->class_str)) 104013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm continue; 104113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 104213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (id == -2) { 104313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm match_id = epdrv->requested_id; 104413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm left = 1; 104513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 104613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } else { 104713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm match_id = id; 104813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm left += early_platform_left(epdrv, id); 104913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 105013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm /* skip requested id */ 105113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm switch (epdrv->requested_id) { 105213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm case EARLY_PLATFORM_ID_ERROR: 105313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm case EARLY_PLATFORM_ID_UNSET: 105413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm break; 105513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm default: 105613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (epdrv->requested_id == id) 105713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm match_id = EARLY_PLATFORM_ID_UNSET; 105813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 105913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 106013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 106113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm switch (match_id) { 106213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm case EARLY_PLATFORM_ID_ERROR: 106313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm pr_warning("%s: unable to parse %s parameter\n", 106413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm class_str, epdrv->pdrv->driver.name); 106513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm /* fall-through */ 106613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm case EARLY_PLATFORM_ID_UNSET: 106713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm match = NULL; 106813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm break; 106913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm default: 107013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm match = early_platform_match(epdrv, match_id); 107113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 107213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 107313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (match) { 1074a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt /* 1075a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt * Set up a sensible init_name to enable 1076a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt * dev_name() and others to be used before the 1077a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt * rest of the driver core is initialized. 1078a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt */ 107906fe53beb636294587d8e94ef83c06cef07c21fdPaul Mundt if (!match->dev.init_name && slab_is_available()) { 1080a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt if (match->id != -1) 1081bd05086bbe3f241cd552068f9ceba9e19c6ce427Paul Mundt match->dev.init_name = 1082bd05086bbe3f241cd552068f9ceba9e19c6ce427Paul Mundt kasprintf(GFP_KERNEL, "%s.%d", 1083bd05086bbe3f241cd552068f9ceba9e19c6ce427Paul Mundt match->name, 1084bd05086bbe3f241cd552068f9ceba9e19c6ce427Paul Mundt match->id); 1085a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt else 1086bd05086bbe3f241cd552068f9ceba9e19c6ce427Paul Mundt match->dev.init_name = 1087bd05086bbe3f241cd552068f9ceba9e19c6ce427Paul Mundt kasprintf(GFP_KERNEL, "%s", 1088bd05086bbe3f241cd552068f9ceba9e19c6ce427Paul Mundt match->name); 1089a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt 1090a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt if (!match->dev.init_name) 1091a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt return -ENOMEM; 1092a636ee7fb35b731ba2b331f6294e809bb6be09c8Paul Mundt } 1093bd05086bbe3f241cd552068f9ceba9e19c6ce427Paul Mundt 109413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (epdrv->pdrv->probe(match)) 109513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm pr_warning("%s: unable to probe %s early.\n", 109613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm class_str, match->name); 109713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm else 109813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm n++; 109913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 110013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 110113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (n >= nr_probe) 110213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm break; 110313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 110413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 110513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (left) 110613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm return n; 110713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm else 110813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm return -ENODEV; 110913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm} 111013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 111113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm/** 11124d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * early_platform_driver_probe - probe a class of registered drivers 111313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @class_str: string to identify early platform driver class 111413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @nr_probe: number of platform devices to successfully probe before exiting 111513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * @user_only: only probe user specified early platform devices 11164d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * 11174d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * Used by architecture code to probe registered early platform drivers 11184d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * within a certain class. For probe to happen a registered early platform 11194d26e139f0b7d4c0700d6993506f1f60e2f2caa5Magnus Damm * device matching a registered early platform driver is needed. 112013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 112113977091a988fb0d21821c2221ddc920eba36b79Magnus Dammint __init early_platform_driver_probe(char *class_str, 112213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int nr_probe, 112313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int user_only) 112413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm{ 112513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm int k, n, i; 112613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 112713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm n = 0; 112813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm for (i = -2; n < nr_probe; i++) { 112913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm k = early_platform_driver_probe_id(class_str, i, nr_probe - n); 113013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 113113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (k < 0) 113213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm break; 113313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 113413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm n += k; 113513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 113613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm if (user_only) 113713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm break; 113813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 113913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 114013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm return n; 114113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm} 114213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 114313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm/** 114413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm * early_platform_cleanup - clean up early platform code 114513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm */ 114613977091a988fb0d21821c2221ddc920eba36b79Magnus Dammvoid __init early_platform_cleanup(void) 114713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm{ 114813977091a988fb0d21821c2221ddc920eba36b79Magnus Damm struct platform_device *pd, *pd2; 114913977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 115013977091a988fb0d21821c2221ddc920eba36b79Magnus Damm /* clean up the devres list used to chain devices */ 115113977091a988fb0d21821c2221ddc920eba36b79Magnus Damm list_for_each_entry_safe(pd, pd2, &early_platform_device_list, 115213977091a988fb0d21821c2221ddc920eba36b79Magnus Damm dev.devres_head) { 115313977091a988fb0d21821c2221ddc920eba36b79Magnus Damm list_del(&pd->dev.devres_head); 115413977091a988fb0d21821c2221ddc920eba36b79Magnus Damm memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head)); 115513977091a988fb0d21821c2221ddc920eba36b79Magnus Damm } 115613977091a988fb0d21821c2221ddc920eba36b79Magnus Damm} 115713977091a988fb0d21821c2221ddc920eba36b79Magnus Damm 1158