xref: /openbmc/linux/drivers/base/platform.c (revision bf563b01)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * platform.c - platform 'pseudo' bus for legacy devices
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  * Copyright (c) 2002-3 Patrick Mochel
51da177e4SLinus Torvalds  * Copyright (c) 2002-3 Open Source Development Labs
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * This file is released under the GPLv2
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * Please see Documentation/driver-model/platform.txt for more
101da177e4SLinus Torvalds  * information.
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
13daa41226SAndrew Morton #include <linux/string.h>
14d052d1beSRussell King #include <linux/platform_device.h>
1505212157SGrant Likely #include <linux/of_device.h>
169ec36cafSRob Herring #include <linux/of_irq.h>
171da177e4SLinus Torvalds #include <linux/module.h>
181da177e4SLinus Torvalds #include <linux/init.h>
191da177e4SLinus Torvalds #include <linux/dma-mapping.h>
201da177e4SLinus Torvalds #include <linux/bootmem.h>
211da177e4SLinus Torvalds #include <linux/err.h>
224e57b681STim Schmielau #include <linux/slab.h>
239d730229SMagnus Damm #include <linux/pm_runtime.h>
24f48c767cSUlf Hansson #include <linux/pm_domain.h>
25689ae231SJean Delvare #include <linux/idr.h>
2691e56878SMika Westerberg #include <linux/acpi.h>
2786be408bSSylwester Nawrocki #include <linux/clk/clk-conf.h>
283d713e0eSKim Phillips #include <linux/limits.h>
2900bbc1d8SMika Westerberg #include <linux/property.h>
301da177e4SLinus Torvalds 
31a1bdc7aaSBen Dooks #include "base.h"
32bed2b42dSRafael J. Wysocki #include "power/power.h"
33a1bdc7aaSBen Dooks 
34689ae231SJean Delvare /* For automatically allocated device IDs */
35689ae231SJean Delvare static DEFINE_IDA(platform_devid_ida);
36689ae231SJean Delvare 
371da177e4SLinus Torvalds struct device platform_bus = {
381e0b2cf9SKay Sievers 	.init_name	= "platform",
391da177e4SLinus Torvalds };
40a96b2042SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_bus);
411da177e4SLinus Torvalds 
421da177e4SLinus Torvalds /**
43a77ce816SKumar Gala  * arch_setup_pdev_archdata - Allow manipulation of archdata before its used
447de636faSRandy Dunlap  * @pdev: platform device
45a77ce816SKumar Gala  *
46a77ce816SKumar Gala  * This is called before platform_device_add() such that any pdev_archdata may
47a77ce816SKumar Gala  * be setup before the platform_notifier is called.  So if a user needs to
48a77ce816SKumar Gala  * manipulate any relevant information in the pdev_archdata they can do:
49a77ce816SKumar Gala  *
50b1d6d822SSebastian Andrzej Siewior  *	platform_device_alloc()
51a77ce816SKumar Gala  *	... manipulate ...
52a77ce816SKumar Gala  *	platform_device_add()
53a77ce816SKumar Gala  *
54a77ce816SKumar Gala  * And if they don't care they can just call platform_device_register() and
55a77ce816SKumar Gala  * everything will just work out.
56a77ce816SKumar Gala  */
57a77ce816SKumar Gala void __weak arch_setup_pdev_archdata(struct platform_device *pdev)
58a77ce816SKumar Gala {
59a77ce816SKumar Gala }
60a77ce816SKumar Gala 
61a77ce816SKumar Gala /**
621da177e4SLinus Torvalds  * platform_get_resource - get a resource for a device
631da177e4SLinus Torvalds  * @dev: platform device
641da177e4SLinus Torvalds  * @type: resource type
651da177e4SLinus Torvalds  * @num: resource index
661da177e4SLinus Torvalds  */
674a3ad20cSGreg Kroah-Hartman struct resource *platform_get_resource(struct platform_device *dev,
684a3ad20cSGreg Kroah-Hartman 				       unsigned int type, unsigned int num)
691da177e4SLinus Torvalds {
701da177e4SLinus Torvalds 	int i;
711da177e4SLinus Torvalds 
721da177e4SLinus Torvalds 	for (i = 0; i < dev->num_resources; i++) {
731da177e4SLinus Torvalds 		struct resource *r = &dev->resource[i];
741da177e4SLinus Torvalds 
75c9f66169SMagnus Damm 		if (type == resource_type(r) && num-- == 0)
761da177e4SLinus Torvalds 			return r;
771da177e4SLinus Torvalds 	}
781da177e4SLinus Torvalds 	return NULL;
791da177e4SLinus Torvalds }
80a96b2042SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_get_resource);
811da177e4SLinus Torvalds 
821da177e4SLinus Torvalds /**
831da177e4SLinus Torvalds  * platform_get_irq - get an IRQ for a device
841da177e4SLinus Torvalds  * @dev: platform device
851da177e4SLinus Torvalds  * @num: IRQ number index
861da177e4SLinus Torvalds  */
871da177e4SLinus Torvalds int platform_get_irq(struct platform_device *dev, unsigned int num)
881da177e4SLinus Torvalds {
895cf8f7dbSAndreas Larsson #ifdef CONFIG_SPARC
905cf8f7dbSAndreas Larsson 	/* sparc does not have irqs represented as IORESOURCE_IRQ resources */
915cf8f7dbSAndreas Larsson 	if (!dev || num >= dev->archdata.num_irqs)
925cf8f7dbSAndreas Larsson 		return -ENXIO;
935cf8f7dbSAndreas Larsson 	return dev->archdata.irqs[num];
945cf8f7dbSAndreas Larsson #else
959ec36cafSRob Herring 	struct resource *r;
96aff008adSGuenter Roeck 	if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) {
97aff008adSGuenter Roeck 		int ret;
98aff008adSGuenter Roeck 
99aff008adSGuenter Roeck 		ret = of_irq_get(dev->dev.of_node, num);
100e330b9a6SSergei Shtylyov 		if (ret > 0 || ret == -EPROBE_DEFER)
101aff008adSGuenter Roeck 			return ret;
102aff008adSGuenter Roeck 	}
1039ec36cafSRob Herring 
1049ec36cafSRob Herring 	r = platform_get_resource(dev, IORESOURCE_IRQ, num);
105d44fa3d4SAgustin Vega-Frias 	if (has_acpi_companion(&dev->dev)) {
106d44fa3d4SAgustin Vega-Frias 		if (r && r->flags & IORESOURCE_DISABLED) {
107d44fa3d4SAgustin Vega-Frias 			int ret;
108d44fa3d4SAgustin Vega-Frias 
109d44fa3d4SAgustin Vega-Frias 			ret = acpi_irq_get(ACPI_HANDLE(&dev->dev), num, r);
110d44fa3d4SAgustin Vega-Frias 			if (ret)
111d44fa3d4SAgustin Vega-Frias 				return ret;
112d44fa3d4SAgustin Vega-Frias 		}
113d44fa3d4SAgustin Vega-Frias 	}
114d44fa3d4SAgustin Vega-Frias 
1157085a740SLinus Walleij 	/*
1167085a740SLinus Walleij 	 * The resources may pass trigger flags to the irqs that need
1177085a740SLinus Walleij 	 * to be set up. It so happens that the trigger flags for
1187085a740SLinus Walleij 	 * IORESOURCE_BITS correspond 1-to-1 to the IRQF_TRIGGER*
1197085a740SLinus Walleij 	 * settings.
1207085a740SLinus Walleij 	 */
12160ca5e0dSGuenter Roeck 	if (r && r->flags & IORESOURCE_BITS) {
12260ca5e0dSGuenter Roeck 		struct irq_data *irqd;
12360ca5e0dSGuenter Roeck 
12460ca5e0dSGuenter Roeck 		irqd = irq_get_irq_data(r->start);
12560ca5e0dSGuenter Roeck 		if (!irqd)
12660ca5e0dSGuenter Roeck 			return -ENXIO;
12760ca5e0dSGuenter Roeck 		irqd_set_trigger_type(irqd, r->flags & IORESOURCE_BITS);
12860ca5e0dSGuenter Roeck 	}
1291da177e4SLinus Torvalds 
130305b3228SDavid Vrabel 	return r ? r->start : -ENXIO;
1315cf8f7dbSAndreas Larsson #endif
1321da177e4SLinus Torvalds }
133a96b2042SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_get_irq);
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds /**
1364b83555dSStephen Boyd  * platform_irq_count - Count the number of IRQs a platform device uses
1374b83555dSStephen Boyd  * @dev: platform device
1384b83555dSStephen Boyd  *
1394b83555dSStephen Boyd  * Return: Number of IRQs a platform device uses or EPROBE_DEFER
1404b83555dSStephen Boyd  */
1414b83555dSStephen Boyd int platform_irq_count(struct platform_device *dev)
1424b83555dSStephen Boyd {
1434b83555dSStephen Boyd 	int ret, nr = 0;
1444b83555dSStephen Boyd 
1454b83555dSStephen Boyd 	while ((ret = platform_get_irq(dev, nr)) >= 0)
1464b83555dSStephen Boyd 		nr++;
1474b83555dSStephen Boyd 
1484b83555dSStephen Boyd 	if (ret == -EPROBE_DEFER)
1494b83555dSStephen Boyd 		return ret;
1504b83555dSStephen Boyd 
1514b83555dSStephen Boyd 	return nr;
1524b83555dSStephen Boyd }
1534b83555dSStephen Boyd EXPORT_SYMBOL_GPL(platform_irq_count);
1544b83555dSStephen Boyd 
1554b83555dSStephen Boyd /**
1561da177e4SLinus Torvalds  * platform_get_resource_byname - get a resource for a device by name
1571da177e4SLinus Torvalds  * @dev: platform device
1581da177e4SLinus Torvalds  * @type: resource type
1591da177e4SLinus Torvalds  * @name: resource name
1601da177e4SLinus Torvalds  */
1614a3ad20cSGreg Kroah-Hartman struct resource *platform_get_resource_byname(struct platform_device *dev,
162c0afe7baSLinus Walleij 					      unsigned int type,
163c0afe7baSLinus Walleij 					      const char *name)
1641da177e4SLinus Torvalds {
1651da177e4SLinus Torvalds 	int i;
1661da177e4SLinus Torvalds 
1671da177e4SLinus Torvalds 	for (i = 0; i < dev->num_resources; i++) {
1681da177e4SLinus Torvalds 		struct resource *r = &dev->resource[i];
1691da177e4SLinus Torvalds 
1701b8cb929SPeter Ujfalusi 		if (unlikely(!r->name))
1711b8cb929SPeter Ujfalusi 			continue;
1721b8cb929SPeter Ujfalusi 
173c9f66169SMagnus Damm 		if (type == resource_type(r) && !strcmp(r->name, name))
1741da177e4SLinus Torvalds 			return r;
1751da177e4SLinus Torvalds 	}
1761da177e4SLinus Torvalds 	return NULL;
1771da177e4SLinus Torvalds }
178a96b2042SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_get_resource_byname);
1791da177e4SLinus Torvalds 
1801da177e4SLinus Torvalds /**
181d6ff8551SWolfram Sang  * platform_get_irq_byname - get an IRQ for a device by name
1821da177e4SLinus Torvalds  * @dev: platform device
1831da177e4SLinus Torvalds  * @name: IRQ name
1841da177e4SLinus Torvalds  */
185c0afe7baSLinus Walleij int platform_get_irq_byname(struct platform_device *dev, const char *name)
1861da177e4SLinus Torvalds {
187ad69674eSGrygorii Strashko 	struct resource *r;
1881da177e4SLinus Torvalds 
189aff008adSGuenter Roeck 	if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) {
190aff008adSGuenter Roeck 		int ret;
191aff008adSGuenter Roeck 
192aff008adSGuenter Roeck 		ret = of_irq_get_byname(dev->dev.of_node, name);
193e330b9a6SSergei Shtylyov 		if (ret > 0 || ret == -EPROBE_DEFER)
194aff008adSGuenter Roeck 			return ret;
195aff008adSGuenter Roeck 	}
196ad69674eSGrygorii Strashko 
197ad69674eSGrygorii Strashko 	r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
198305b3228SDavid Vrabel 	return r ? r->start : -ENXIO;
1991da177e4SLinus Torvalds }
200a96b2042SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_get_irq_byname);
2011da177e4SLinus Torvalds 
2021da177e4SLinus Torvalds /**
2031da177e4SLinus Torvalds  * platform_add_devices - add a numbers of platform devices
2041da177e4SLinus Torvalds  * @devs: array of platform devices to add
2051da177e4SLinus Torvalds  * @num: number of platform devices in array
2061da177e4SLinus Torvalds  */
2071da177e4SLinus Torvalds int platform_add_devices(struct platform_device **devs, int num)
2081da177e4SLinus Torvalds {
2091da177e4SLinus Torvalds 	int i, ret = 0;
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds 	for (i = 0; i < num; i++) {
2121da177e4SLinus Torvalds 		ret = platform_device_register(devs[i]);
2131da177e4SLinus Torvalds 		if (ret) {
2141da177e4SLinus Torvalds 			while (--i >= 0)
2151da177e4SLinus Torvalds 				platform_device_unregister(devs[i]);
2161da177e4SLinus Torvalds 			break;
2171da177e4SLinus Torvalds 		}
2181da177e4SLinus Torvalds 	}
2191da177e4SLinus Torvalds 
2201da177e4SLinus Torvalds 	return ret;
2211da177e4SLinus Torvalds }
222a96b2042SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_add_devices);
2231da177e4SLinus Torvalds 
22437c12e74SRussell King struct platform_object {
22537c12e74SRussell King 	struct platform_device pdev;
2261cec24c5SYann Droneaud 	char name[];
22737c12e74SRussell King };
22837c12e74SRussell King 
2291da177e4SLinus Torvalds /**
2303c31f07aSBen Hutchings  * platform_device_put - destroy a platform device
23137c12e74SRussell King  * @pdev: platform device to free
23237c12e74SRussell King  *
2334a3ad20cSGreg Kroah-Hartman  * Free all memory associated with a platform device.  This function must
2344a3ad20cSGreg Kroah-Hartman  * _only_ be externally called in error cases.  All other usage is a bug.
23537c12e74SRussell King  */
23637c12e74SRussell King void platform_device_put(struct platform_device *pdev)
23737c12e74SRussell King {
23837c12e74SRussell King 	if (pdev)
23937c12e74SRussell King 		put_device(&pdev->dev);
24037c12e74SRussell King }
24137c12e74SRussell King EXPORT_SYMBOL_GPL(platform_device_put);
24237c12e74SRussell King 
24337c12e74SRussell King static void platform_device_release(struct device *dev)
24437c12e74SRussell King {
2454a3ad20cSGreg Kroah-Hartman 	struct platform_object *pa = container_of(dev, struct platform_object,
2464a3ad20cSGreg Kroah-Hartman 						  pdev.dev);
24737c12e74SRussell King 
2487096d042SGrant Likely 	of_device_node_put(&pa->pdev.dev);
24937c12e74SRussell King 	kfree(pa->pdev.dev.platform_data);
250e710d7d5SSamuel Ortiz 	kfree(pa->pdev.mfd_cell);
25137c12e74SRussell King 	kfree(pa->pdev.resource);
2523d713e0eSKim Phillips 	kfree(pa->pdev.driver_override);
25337c12e74SRussell King 	kfree(pa);
25437c12e74SRussell King }
25537c12e74SRussell King 
25637c12e74SRussell King /**
2573c31f07aSBen Hutchings  * platform_device_alloc - create a platform device
25837c12e74SRussell King  * @name: base name of the device we're adding
25937c12e74SRussell King  * @id: instance id
26037c12e74SRussell King  *
26137c12e74SRussell King  * Create a platform device object which can have other objects attached
26237c12e74SRussell King  * to it, and which will have attached objects freed when it is released.
26337c12e74SRussell King  */
2641359555eSJean Delvare struct platform_device *platform_device_alloc(const char *name, int id)
26537c12e74SRussell King {
26637c12e74SRussell King 	struct platform_object *pa;
26737c12e74SRussell King 
2681cec24c5SYann Droneaud 	pa = kzalloc(sizeof(*pa) + strlen(name) + 1, GFP_KERNEL);
26937c12e74SRussell King 	if (pa) {
27037c12e74SRussell King 		strcpy(pa->name, name);
27137c12e74SRussell King 		pa->pdev.name = pa->name;
27237c12e74SRussell King 		pa->pdev.id = id;
27337c12e74SRussell King 		device_initialize(&pa->pdev.dev);
27437c12e74SRussell King 		pa->pdev.dev.release = platform_device_release;
275a77ce816SKumar Gala 		arch_setup_pdev_archdata(&pa->pdev);
27637c12e74SRussell King 	}
27737c12e74SRussell King 
27837c12e74SRussell King 	return pa ? &pa->pdev : NULL;
27937c12e74SRussell King }
28037c12e74SRussell King EXPORT_SYMBOL_GPL(platform_device_alloc);
28137c12e74SRussell King 
28237c12e74SRussell King /**
2833c31f07aSBen Hutchings  * platform_device_add_resources - add resources to a platform device
28437c12e74SRussell King  * @pdev: platform device allocated by platform_device_alloc to add resources to
28537c12e74SRussell King  * @res: set of resources that needs to be allocated for the device
28637c12e74SRussell King  * @num: number of resources
28737c12e74SRussell King  *
28837c12e74SRussell King  * Add a copy of the resources to the platform device.  The memory
2894a3ad20cSGreg Kroah-Hartman  * associated with the resources will be freed when the platform device is
2904a3ad20cSGreg Kroah-Hartman  * released.
29137c12e74SRussell King  */
2924a3ad20cSGreg Kroah-Hartman int platform_device_add_resources(struct platform_device *pdev,
2930b7f1a7eSGeert Uytterhoeven 				  const struct resource *res, unsigned int num)
29437c12e74SRussell King {
295cea89623SUwe Kleine-König 	struct resource *r = NULL;
29637c12e74SRussell King 
297cea89623SUwe Kleine-König 	if (res) {
2983e61dfd8SUwe Kleine-König 		r = kmemdup(res, sizeof(struct resource) * num, GFP_KERNEL);
299cea89623SUwe Kleine-König 		if (!r)
300cea89623SUwe Kleine-König 			return -ENOMEM;
301cea89623SUwe Kleine-König 	}
302cea89623SUwe Kleine-König 
3034a03d6f7SUwe Kleine-König 	kfree(pdev->resource);
30437c12e74SRussell King 	pdev->resource = r;
30537c12e74SRussell King 	pdev->num_resources = num;
3063e61dfd8SUwe Kleine-König 	return 0;
30737c12e74SRussell King }
30837c12e74SRussell King EXPORT_SYMBOL_GPL(platform_device_add_resources);
30937c12e74SRussell King 
31037c12e74SRussell King /**
3113c31f07aSBen Hutchings  * platform_device_add_data - add platform-specific data to a platform device
31237c12e74SRussell King  * @pdev: platform device allocated by platform_device_alloc to add resources to
31337c12e74SRussell King  * @data: platform specific data for this platform device
31437c12e74SRussell King  * @size: size of platform specific data
31537c12e74SRussell King  *
3164a3ad20cSGreg Kroah-Hartman  * Add a copy of platform specific data to the platform device's
3174a3ad20cSGreg Kroah-Hartman  * platform_data pointer.  The memory associated with the platform data
3184a3ad20cSGreg Kroah-Hartman  * will be freed when the platform device is released.
31937c12e74SRussell King  */
3204a3ad20cSGreg Kroah-Hartman int platform_device_add_data(struct platform_device *pdev, const void *data,
3214a3ad20cSGreg Kroah-Hartman 			     size_t size)
32237c12e74SRussell King {
32327a33f9eSUwe Kleine-König 	void *d = NULL;
32437c12e74SRussell King 
32527a33f9eSUwe Kleine-König 	if (data) {
3265cfc64ceSAnton Vorontsov 		d = kmemdup(data, size, GFP_KERNEL);
32727a33f9eSUwe Kleine-König 		if (!d)
32827a33f9eSUwe Kleine-König 			return -ENOMEM;
32927a33f9eSUwe Kleine-König 	}
33027a33f9eSUwe Kleine-König 
331251e031dSUwe Kleine-König 	kfree(pdev->dev.platform_data);
33237c12e74SRussell King 	pdev->dev.platform_data = d;
333daa41226SAndrew Morton 	return 0;
33437c12e74SRussell King }
33537c12e74SRussell King EXPORT_SYMBOL_GPL(platform_device_add_data);
33637c12e74SRussell King 
33737c12e74SRussell King /**
33800bbc1d8SMika Westerberg  * platform_device_add_properties - add built-in properties to a platform device
33900bbc1d8SMika Westerberg  * @pdev: platform device to add properties to
340f4d05266SHeikki Krogerus  * @properties: null terminated array of properties to add
34100bbc1d8SMika Westerberg  *
342f4d05266SHeikki Krogerus  * The function will take deep copy of @properties and attach the copy to the
343f4d05266SHeikki Krogerus  * platform device. The memory associated with properties will be freed when the
344f4d05266SHeikki Krogerus  * platform device is released.
34500bbc1d8SMika Westerberg  */
34600bbc1d8SMika Westerberg int platform_device_add_properties(struct platform_device *pdev,
347277036f0SJan Kiszka 				   const struct property_entry *properties)
34800bbc1d8SMika Westerberg {
349f4d05266SHeikki Krogerus 	return device_add_properties(&pdev->dev, properties);
35000bbc1d8SMika Westerberg }
35100bbc1d8SMika Westerberg EXPORT_SYMBOL_GPL(platform_device_add_properties);
35200bbc1d8SMika Westerberg 
35300bbc1d8SMika Westerberg /**
35437c12e74SRussell King  * platform_device_add - add a platform device to device hierarchy
35567be2dd1SMartin Waitz  * @pdev: platform device we're adding
3561da177e4SLinus Torvalds  *
35737c12e74SRussell King  * This is part 2 of platform_device_register(), though may be called
35837c12e74SRussell King  * separately _iff_ pdev was allocated by platform_device_alloc().
3591da177e4SLinus Torvalds  */
36037c12e74SRussell King int platform_device_add(struct platform_device *pdev)
3611da177e4SLinus Torvalds {
362689ae231SJean Delvare 	int i, ret;
3631da177e4SLinus Torvalds 
3641da177e4SLinus Torvalds 	if (!pdev)
3651da177e4SLinus Torvalds 		return -EINVAL;
3661da177e4SLinus Torvalds 
3671da177e4SLinus Torvalds 	if (!pdev->dev.parent)
3681da177e4SLinus Torvalds 		pdev->dev.parent = &platform_bus;
3691da177e4SLinus Torvalds 
3701da177e4SLinus Torvalds 	pdev->dev.bus = &platform_bus_type;
3711da177e4SLinus Torvalds 
372689ae231SJean Delvare 	switch (pdev->id) {
373689ae231SJean Delvare 	default:
3741e0b2cf9SKay Sievers 		dev_set_name(&pdev->dev, "%s.%d", pdev->name,  pdev->id);
375689ae231SJean Delvare 		break;
376689ae231SJean Delvare 	case PLATFORM_DEVID_NONE:
377acc0e90fSGreg Kroah-Hartman 		dev_set_name(&pdev->dev, "%s", pdev->name);
378689ae231SJean Delvare 		break;
379689ae231SJean Delvare 	case PLATFORM_DEVID_AUTO:
380689ae231SJean Delvare 		/*
381689ae231SJean Delvare 		 * Automatically allocated device ID. We mark it as such so
382689ae231SJean Delvare 		 * that we remember it must be freed, and we append a suffix
383689ae231SJean Delvare 		 * to avoid namespace collision with explicit IDs.
384689ae231SJean Delvare 		 */
385689ae231SJean Delvare 		ret = ida_simple_get(&platform_devid_ida, 0, 0, GFP_KERNEL);
386689ae231SJean Delvare 		if (ret < 0)
3875da7f709SGreg Kroah-Hartman 			goto err_out;
388689ae231SJean Delvare 		pdev->id = ret;
389689ae231SJean Delvare 		pdev->id_auto = true;
390689ae231SJean Delvare 		dev_set_name(&pdev->dev, "%s.%d.auto", pdev->name, pdev->id);
391689ae231SJean Delvare 		break;
392689ae231SJean Delvare 	}
3931da177e4SLinus Torvalds 
3941da177e4SLinus Torvalds 	for (i = 0; i < pdev->num_resources; i++) {
3955da7f709SGreg Kroah-Hartman 		struct resource *p, *r = &pdev->resource[i];
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds 		if (r->name == NULL)
3981e0b2cf9SKay Sievers 			r->name = dev_name(&pdev->dev);
3991da177e4SLinus Torvalds 
4001da177e4SLinus Torvalds 		p = r->parent;
4011da177e4SLinus Torvalds 		if (!p) {
4020e6c861fSGreg Kroah-Hartman 			if (resource_type(r) == IORESOURCE_MEM)
4031da177e4SLinus Torvalds 				p = &iomem_resource;
4040e6c861fSGreg Kroah-Hartman 			else if (resource_type(r) == IORESOURCE_IO)
4051da177e4SLinus Torvalds 				p = &ioport_resource;
4061da177e4SLinus Torvalds 		}
4071da177e4SLinus Torvalds 
4080e6c861fSGreg Kroah-Hartman 		if (p && insert_resource(p, r)) {
4098a18f428SChen Yu 			dev_err(&pdev->dev, "failed to claim resource %d: %pR\n", i, r);
4105da7f709SGreg Kroah-Hartman 			ret = -EBUSY;
4115da7f709SGreg Kroah-Hartman 			goto failed;
4125da7f709SGreg Kroah-Hartman 		}
4131da177e4SLinus Torvalds 	}
4141da177e4SLinus Torvalds 
4151da177e4SLinus Torvalds 	pr_debug("Registering platform device '%s'. Parent at %s\n",
4161e0b2cf9SKay Sievers 		 dev_name(&pdev->dev), dev_name(pdev->dev.parent));
4171da177e4SLinus Torvalds 
418e3915532SRussell King 	ret = device_add(&pdev->dev);
4198b2dcebaSGreg Kroah-Hartman 	if (ret == 0)
4208b2dcebaSGreg Kroah-Hartman 		return ret;
4218b2dcebaSGreg Kroah-Hartman 
4225da7f709SGreg Kroah-Hartman  failed:
4238b2dcebaSGreg Kroah-Hartman 	if (pdev->id_auto) {
4248b2dcebaSGreg Kroah-Hartman 		ida_simple_remove(&platform_devid_ida, pdev->id);
4258b2dcebaSGreg Kroah-Hartman 		pdev->id = PLATFORM_DEVID_AUTO;
4268b2dcebaSGreg Kroah-Hartman 	}
4278b2dcebaSGreg Kroah-Hartman 
4288b2dcebaSGreg Kroah-Hartman 	while (--i >= 0) {
4298b2dcebaSGreg Kroah-Hartman 		struct resource *r = &pdev->resource[i];
4307f5dcaf1SGrant Likely 		if (r->parent)
4318b2dcebaSGreg Kroah-Hartman 			release_resource(r);
4328b2dcebaSGreg Kroah-Hartman 	}
433c9f66169SMagnus Damm 
4345da7f709SGreg Kroah-Hartman  err_out:
4351da177e4SLinus Torvalds 	return ret;
4361da177e4SLinus Torvalds }
43737c12e74SRussell King EXPORT_SYMBOL_GPL(platform_device_add);
43837c12e74SRussell King 
43937c12e74SRussell King /**
44093ce3061SDmitry Torokhov  * platform_device_del - remove a platform-level device
44193ce3061SDmitry Torokhov  * @pdev: platform device we're removing
44293ce3061SDmitry Torokhov  *
44393ce3061SDmitry Torokhov  * Note that this function will also release all memory- and port-based
4444a3ad20cSGreg Kroah-Hartman  * resources owned by the device (@dev->resource).  This function must
4454a3ad20cSGreg Kroah-Hartman  * _only_ be externally called in error cases.  All other usage is a bug.
44693ce3061SDmitry Torokhov  */
44793ce3061SDmitry Torokhov void platform_device_del(struct platform_device *pdev)
44893ce3061SDmitry Torokhov {
4498b2dcebaSGreg Kroah-Hartman 	int i;
45093ce3061SDmitry Torokhov 
4518b2dcebaSGreg Kroah-Hartman 	if (pdev) {
452c90aab9cSJerome Marchand 		device_remove_properties(&pdev->dev);
453dc4c15d4SJean Delvare 		device_del(&pdev->dev);
4548b2dcebaSGreg Kroah-Hartman 
4558b2dcebaSGreg Kroah-Hartman 		if (pdev->id_auto) {
4568b2dcebaSGreg Kroah-Hartman 			ida_simple_remove(&platform_devid_ida, pdev->id);
4578b2dcebaSGreg Kroah-Hartman 			pdev->id = PLATFORM_DEVID_AUTO;
4588b2dcebaSGreg Kroah-Hartman 		}
4598b2dcebaSGreg Kroah-Hartman 
4608b2dcebaSGreg Kroah-Hartman 		for (i = 0; i < pdev->num_resources; i++) {
4618b2dcebaSGreg Kroah-Hartman 			struct resource *r = &pdev->resource[i];
4627f5dcaf1SGrant Likely 			if (r->parent)
4638b2dcebaSGreg Kroah-Hartman 				release_resource(r);
4648b2dcebaSGreg Kroah-Hartman 		}
4658b2dcebaSGreg Kroah-Hartman 	}
46693ce3061SDmitry Torokhov }
46793ce3061SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_device_del);
46893ce3061SDmitry Torokhov 
46993ce3061SDmitry Torokhov /**
47037c12e74SRussell King  * platform_device_register - add a platform-level device
47137c12e74SRussell King  * @pdev: platform device we're adding
47237c12e74SRussell King  */
47337c12e74SRussell King int platform_device_register(struct platform_device *pdev)
47437c12e74SRussell King {
47537c12e74SRussell King 	device_initialize(&pdev->dev);
476a77ce816SKumar Gala 	arch_setup_pdev_archdata(pdev);
47737c12e74SRussell King 	return platform_device_add(pdev);
47837c12e74SRussell King }
479a96b2042SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_device_register);
4801da177e4SLinus Torvalds 
4811da177e4SLinus Torvalds /**
48293ce3061SDmitry Torokhov  * platform_device_unregister - unregister a platform-level device
48393ce3061SDmitry Torokhov  * @pdev: platform device we're unregistering
4841da177e4SLinus Torvalds  *
48580682fa9SUwe Zeisberger  * Unregistration is done in 2 steps. First we release all resources
4862d7b5a70SJean Delvare  * and remove it from the subsystem, then we drop reference count by
48793ce3061SDmitry Torokhov  * calling platform_device_put().
4881da177e4SLinus Torvalds  */
4891da177e4SLinus Torvalds void platform_device_unregister(struct platform_device *pdev)
4901da177e4SLinus Torvalds {
49193ce3061SDmitry Torokhov 	platform_device_del(pdev);
49293ce3061SDmitry Torokhov 	platform_device_put(pdev);
4931da177e4SLinus Torvalds }
494a96b2042SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_device_unregister);
4951da177e4SLinus Torvalds 
4961da177e4SLinus Torvalds /**
49701dcc60aSUwe Kleine-König  * platform_device_register_full - add a platform-level device with
49844f28bdeSUwe Kleine-König  * resources and platform-specific data
49944f28bdeSUwe Kleine-König  *
50001dcc60aSUwe Kleine-König  * @pdevinfo: data used to create device
501d8bf2540SDmitry Baryshkov  *
502f0eae0edSJani Nikula  * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
503d8bf2540SDmitry Baryshkov  */
50401dcc60aSUwe Kleine-König struct platform_device *platform_device_register_full(
5055a3072beSUwe Kleine-König 		const struct platform_device_info *pdevinfo)
506d8bf2540SDmitry Baryshkov {
50744f28bdeSUwe Kleine-König 	int ret = -ENOMEM;
508d8bf2540SDmitry Baryshkov 	struct platform_device *pdev;
509d8bf2540SDmitry Baryshkov 
51001dcc60aSUwe Kleine-König 	pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
51144f28bdeSUwe Kleine-König 	if (!pdev)
51201dcc60aSUwe Kleine-König 		goto err_alloc;
51301dcc60aSUwe Kleine-König 
51401dcc60aSUwe Kleine-König 	pdev->dev.parent = pdevinfo->parent;
515ce793486SRafael J. Wysocki 	pdev->dev.fwnode = pdevinfo->fwnode;
51601dcc60aSUwe Kleine-König 
51701dcc60aSUwe Kleine-König 	if (pdevinfo->dma_mask) {
51801dcc60aSUwe Kleine-König 		/*
51901dcc60aSUwe Kleine-König 		 * This memory isn't freed when the device is put,
52001dcc60aSUwe Kleine-König 		 * I don't have a nice idea for that though.  Conceptually
52101dcc60aSUwe Kleine-König 		 * dma_mask in struct device should not be a pointer.
52201dcc60aSUwe Kleine-König 		 * See http://thread.gmane.org/gmane.linux.kernel.pci/9081
52301dcc60aSUwe Kleine-König 		 */
52401dcc60aSUwe Kleine-König 		pdev->dev.dma_mask =
52501dcc60aSUwe Kleine-König 			kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
52601dcc60aSUwe Kleine-König 		if (!pdev->dev.dma_mask)
52744f28bdeSUwe Kleine-König 			goto err;
528d8bf2540SDmitry Baryshkov 
52901dcc60aSUwe Kleine-König 		*pdev->dev.dma_mask = pdevinfo->dma_mask;
53001dcc60aSUwe Kleine-König 		pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
53101dcc60aSUwe Kleine-König 	}
532d8bf2540SDmitry Baryshkov 
53301dcc60aSUwe Kleine-König 	ret = platform_device_add_resources(pdev,
53401dcc60aSUwe Kleine-König 			pdevinfo->res, pdevinfo->num_res);
53544f28bdeSUwe Kleine-König 	if (ret)
53644f28bdeSUwe Kleine-König 		goto err;
537d8bf2540SDmitry Baryshkov 
53801dcc60aSUwe Kleine-König 	ret = platform_device_add_data(pdev,
53901dcc60aSUwe Kleine-König 			pdevinfo->data, pdevinfo->size_data);
54044f28bdeSUwe Kleine-König 	if (ret)
54144f28bdeSUwe Kleine-König 		goto err;
54244f28bdeSUwe Kleine-König 
543f4d05266SHeikki Krogerus 	if (pdevinfo->properties) {
544f4d05266SHeikki Krogerus 		ret = platform_device_add_properties(pdev,
545f4d05266SHeikki Krogerus 						     pdevinfo->properties);
54600bbc1d8SMika Westerberg 		if (ret)
54700bbc1d8SMika Westerberg 			goto err;
54800bbc1d8SMika Westerberg 	}
54900bbc1d8SMika Westerberg 
55044f28bdeSUwe Kleine-König 	ret = platform_device_add(pdev);
55144f28bdeSUwe Kleine-König 	if (ret) {
55244f28bdeSUwe Kleine-König err:
5537b199811SRafael J. Wysocki 		ACPI_COMPANION_SET(&pdev->dev, NULL);
55401dcc60aSUwe Kleine-König 		kfree(pdev->dev.dma_mask);
55501dcc60aSUwe Kleine-König 
55601dcc60aSUwe Kleine-König err_alloc:
55744f28bdeSUwe Kleine-König 		platform_device_put(pdev);
55844f28bdeSUwe Kleine-König 		return ERR_PTR(ret);
55944f28bdeSUwe Kleine-König 	}
560d8bf2540SDmitry Baryshkov 
561d8bf2540SDmitry Baryshkov 	return pdev;
562d8bf2540SDmitry Baryshkov }
56301dcc60aSUwe Kleine-König EXPORT_SYMBOL_GPL(platform_device_register_full);
564d8bf2540SDmitry Baryshkov 
56500d3dcddSRussell King static int platform_drv_probe(struct device *_dev)
56600d3dcddSRussell King {
56700d3dcddSRussell King 	struct platform_driver *drv = to_platform_driver(_dev->driver);
56800d3dcddSRussell King 	struct platform_device *dev = to_platform_device(_dev);
56994d76d5dSRafael J. Wysocki 	int ret;
57000d3dcddSRussell King 
57186be408bSSylwester Nawrocki 	ret = of_clk_set_defaults(_dev->of_node, false);
57286be408bSSylwester Nawrocki 	if (ret < 0)
57386be408bSSylwester Nawrocki 		return ret;
57486be408bSSylwester Nawrocki 
575cb518413SUlf Hansson 	ret = dev_pm_domain_attach(_dev, true);
57625cad69fSMartin Wilck 	if (ret != -EPROBE_DEFER) {
57725cad69fSMartin Wilck 		if (drv->probe) {
57894d76d5dSRafael J. Wysocki 			ret = drv->probe(dev);
5799383f4c6SJosh Cartwright 			if (ret)
580cb518413SUlf Hansson 				dev_pm_domain_detach(_dev, true);
58125cad69fSMartin Wilck 		} else {
58225cad69fSMartin Wilck 			/* don't fail if just dev_pm_domain_attach failed */
58325cad69fSMartin Wilck 			ret = 0;
58425cad69fSMartin Wilck 		}
585cb518413SUlf Hansson 	}
58694d76d5dSRafael J. Wysocki 
5873f9120b0SJohan Hovold 	if (drv->prevent_deferred_probe && ret == -EPROBE_DEFER) {
5883f9120b0SJohan Hovold 		dev_warn(_dev, "probe deferral not supported\n");
5893f9120b0SJohan Hovold 		ret = -ENXIO;
5903f9120b0SJohan Hovold 	}
5913f9120b0SJohan Hovold 
59294d76d5dSRafael J. Wysocki 	return ret;
59300d3dcddSRussell King }
59400d3dcddSRussell King 
595c67334fbSDavid Brownell static int platform_drv_probe_fail(struct device *_dev)
596c67334fbSDavid Brownell {
597c67334fbSDavid Brownell 	return -ENXIO;
598c67334fbSDavid Brownell }
599c67334fbSDavid Brownell 
60000d3dcddSRussell King static int platform_drv_remove(struct device *_dev)
60100d3dcddSRussell King {
60200d3dcddSRussell King 	struct platform_driver *drv = to_platform_driver(_dev->driver);
60300d3dcddSRussell King 	struct platform_device *dev = to_platform_device(_dev);
604b8b2c7d8SUwe Kleine-König 	int ret = 0;
60500d3dcddSRussell King 
606b8b2c7d8SUwe Kleine-König 	if (drv->remove)
60794d76d5dSRafael J. Wysocki 		ret = drv->remove(dev);
608cb518413SUlf Hansson 	dev_pm_domain_detach(_dev, true);
60994d76d5dSRafael J. Wysocki 
61094d76d5dSRafael J. Wysocki 	return ret;
61100d3dcddSRussell King }
61200d3dcddSRussell King 
61300d3dcddSRussell King static void platform_drv_shutdown(struct device *_dev)
61400d3dcddSRussell King {
61500d3dcddSRussell King 	struct platform_driver *drv = to_platform_driver(_dev->driver);
61600d3dcddSRussell King 	struct platform_device *dev = to_platform_device(_dev);
61700d3dcddSRussell King 
618b8b2c7d8SUwe Kleine-König 	if (drv->shutdown)
61900d3dcddSRussell King 		drv->shutdown(dev);
62000d3dcddSRussell King }
62100d3dcddSRussell King 
62200d3dcddSRussell King /**
6239447057eSLibo Chen  * __platform_driver_register - register a driver for platform-level devices
62400d3dcddSRussell King  * @drv: platform driver structure
62508801f96SRandy Dunlap  * @owner: owning module/driver
62600d3dcddSRussell King  */
6279447057eSLibo Chen int __platform_driver_register(struct platform_driver *drv,
6289447057eSLibo Chen 				struct module *owner)
62900d3dcddSRussell King {
6309447057eSLibo Chen 	drv->driver.owner = owner;
63100d3dcddSRussell King 	drv->driver.bus = &platform_bus_type;
63200d3dcddSRussell King 	drv->driver.probe = platform_drv_probe;
63300d3dcddSRussell King 	drv->driver.remove = platform_drv_remove;
63400d3dcddSRussell King 	drv->driver.shutdown = platform_drv_shutdown;
635783ea7d4SMagnus Damm 
63600d3dcddSRussell King 	return driver_register(&drv->driver);
63700d3dcddSRussell King }
6389447057eSLibo Chen EXPORT_SYMBOL_GPL(__platform_driver_register);
63900d3dcddSRussell King 
64000d3dcddSRussell King /**
6413c31f07aSBen Hutchings  * platform_driver_unregister - unregister a driver for platform-level devices
64200d3dcddSRussell King  * @drv: platform driver structure
64300d3dcddSRussell King  */
64400d3dcddSRussell King void platform_driver_unregister(struct platform_driver *drv)
64500d3dcddSRussell King {
64600d3dcddSRussell King 	driver_unregister(&drv->driver);
64700d3dcddSRussell King }
64800d3dcddSRussell King EXPORT_SYMBOL_GPL(platform_driver_unregister);
64900d3dcddSRussell King 
650c67334fbSDavid Brownell /**
651c3b50dc2SWolfram Sang  * __platform_driver_probe - register driver for non-hotpluggable device
652c67334fbSDavid Brownell  * @drv: platform driver structure
6533f9120b0SJohan Hovold  * @probe: the driver probe routine, probably from an __init section
654c3b50dc2SWolfram Sang  * @module: module which will be the owner of the driver
655c67334fbSDavid Brownell  *
656c67334fbSDavid Brownell  * Use this instead of platform_driver_register() when you know the device
657c67334fbSDavid Brownell  * is not hotpluggable and has already been registered, and you want to
658c67334fbSDavid Brownell  * remove its run-once probe() infrastructure from memory after the driver
659c67334fbSDavid Brownell  * has bound to the device.
660c67334fbSDavid Brownell  *
661c67334fbSDavid Brownell  * One typical use for this would be with drivers for controllers integrated
662c67334fbSDavid Brownell  * into system-on-chip processors, where the controller devices have been
663c67334fbSDavid Brownell  * configured as part of board setup.
664c67334fbSDavid Brownell  *
6653f9120b0SJohan Hovold  * Note that this is incompatible with deferred probing.
666647c86d0SFabio Porcedda  *
667c67334fbSDavid Brownell  * Returns zero if the driver registered and bound to a device, else returns
668c67334fbSDavid Brownell  * a negative error code and with the driver not registered.
669c67334fbSDavid Brownell  */
670c3b50dc2SWolfram Sang int __init_or_module __platform_driver_probe(struct platform_driver *drv,
671c3b50dc2SWolfram Sang 		int (*probe)(struct platform_device *), struct module *module)
672c67334fbSDavid Brownell {
673c67334fbSDavid Brownell 	int retval, code;
674c67334fbSDavid Brownell 
6755c36eb2aSDmitry Torokhov 	if (drv->driver.probe_type == PROBE_PREFER_ASYNCHRONOUS) {
6765c36eb2aSDmitry Torokhov 		pr_err("%s: drivers registered with %s can not be probed asynchronously\n",
6775c36eb2aSDmitry Torokhov 			 drv->driver.name, __func__);
6785c36eb2aSDmitry Torokhov 		return -EINVAL;
6795c36eb2aSDmitry Torokhov 	}
6805c36eb2aSDmitry Torokhov 
6815c36eb2aSDmitry Torokhov 	/*
6825c36eb2aSDmitry Torokhov 	 * We have to run our probes synchronously because we check if
6835c36eb2aSDmitry Torokhov 	 * we find any devices to bind to and exit with error if there
6845c36eb2aSDmitry Torokhov 	 * are any.
6855c36eb2aSDmitry Torokhov 	 */
6865c36eb2aSDmitry Torokhov 	drv->driver.probe_type = PROBE_FORCE_SYNCHRONOUS;
6875c36eb2aSDmitry Torokhov 
6883f9120b0SJohan Hovold 	/*
6893f9120b0SJohan Hovold 	 * Prevent driver from requesting probe deferral to avoid further
6903f9120b0SJohan Hovold 	 * futile probe attempts.
6913f9120b0SJohan Hovold 	 */
6923f9120b0SJohan Hovold 	drv->prevent_deferred_probe = true;
6933f9120b0SJohan Hovold 
6941a6f2a75SDmitry Torokhov 	/* make sure driver won't have bind/unbind attributes */
6951a6f2a75SDmitry Torokhov 	drv->driver.suppress_bind_attrs = true;
6961a6f2a75SDmitry Torokhov 
697c67334fbSDavid Brownell 	/* temporary section violation during probe() */
698c67334fbSDavid Brownell 	drv->probe = probe;
699c3b50dc2SWolfram Sang 	retval = code = __platform_driver_register(drv, module);
700c67334fbSDavid Brownell 
7011a6f2a75SDmitry Torokhov 	/*
7021a6f2a75SDmitry Torokhov 	 * Fixup that section violation, being paranoid about code scanning
703c67334fbSDavid Brownell 	 * the list of drivers in order to probe new devices.  Check to see
704c67334fbSDavid Brownell 	 * if the probe was successful, and make sure any forced probes of
705c67334fbSDavid Brownell 	 * new devices fail.
706c67334fbSDavid Brownell 	 */
707d79d3244SPatrick Pannuto 	spin_lock(&drv->driver.bus->p->klist_drivers.k_lock);
708c67334fbSDavid Brownell 	drv->probe = NULL;
709e5dd1278SGreg Kroah-Hartman 	if (code == 0 && list_empty(&drv->driver.p->klist_devices.k_list))
710c67334fbSDavid Brownell 		retval = -ENODEV;
711c67334fbSDavid Brownell 	drv->driver.probe = platform_drv_probe_fail;
712d79d3244SPatrick Pannuto 	spin_unlock(&drv->driver.bus->p->klist_drivers.k_lock);
713c67334fbSDavid Brownell 
714c67334fbSDavid Brownell 	if (code != retval)
715c67334fbSDavid Brownell 		platform_driver_unregister(drv);
716c67334fbSDavid Brownell 	return retval;
717c67334fbSDavid Brownell }
718c3b50dc2SWolfram Sang EXPORT_SYMBOL_GPL(__platform_driver_probe);
7191da177e4SLinus Torvalds 
720ecdf6cebSDmitry Torokhov /**
721291f653aSWolfram Sang  * __platform_create_bundle - register driver and create corresponding device
722ecdf6cebSDmitry Torokhov  * @driver: platform driver structure
723ecdf6cebSDmitry Torokhov  * @probe: the driver probe routine, probably from an __init section
724ecdf6cebSDmitry Torokhov  * @res: set of resources that needs to be allocated for the device
725ecdf6cebSDmitry Torokhov  * @n_res: number of resources
726ecdf6cebSDmitry Torokhov  * @data: platform specific data for this platform device
727ecdf6cebSDmitry Torokhov  * @size: size of platform specific data
728291f653aSWolfram Sang  * @module: module which will be the owner of the driver
729ecdf6cebSDmitry Torokhov  *
730ecdf6cebSDmitry Torokhov  * Use this in legacy-style modules that probe hardware directly and
731ecdf6cebSDmitry Torokhov  * register a single platform device and corresponding platform driver.
732f0eae0edSJani Nikula  *
733f0eae0edSJani Nikula  * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
734ecdf6cebSDmitry Torokhov  */
735291f653aSWolfram Sang struct platform_device * __init_or_module __platform_create_bundle(
736ecdf6cebSDmitry Torokhov 			struct platform_driver *driver,
737ecdf6cebSDmitry Torokhov 			int (*probe)(struct platform_device *),
738ecdf6cebSDmitry Torokhov 			struct resource *res, unsigned int n_res,
739291f653aSWolfram Sang 			const void *data, size_t size, struct module *module)
740ecdf6cebSDmitry Torokhov {
741ecdf6cebSDmitry Torokhov 	struct platform_device *pdev;
742ecdf6cebSDmitry Torokhov 	int error;
743ecdf6cebSDmitry Torokhov 
744ecdf6cebSDmitry Torokhov 	pdev = platform_device_alloc(driver->driver.name, -1);
745ecdf6cebSDmitry Torokhov 	if (!pdev) {
746ecdf6cebSDmitry Torokhov 		error = -ENOMEM;
747ecdf6cebSDmitry Torokhov 		goto err_out;
748ecdf6cebSDmitry Torokhov 	}
749ecdf6cebSDmitry Torokhov 
750ecdf6cebSDmitry Torokhov 	error = platform_device_add_resources(pdev, res, n_res);
751ecdf6cebSDmitry Torokhov 	if (error)
752ecdf6cebSDmitry Torokhov 		goto err_pdev_put;
753ecdf6cebSDmitry Torokhov 
754ecdf6cebSDmitry Torokhov 	error = platform_device_add_data(pdev, data, size);
755ecdf6cebSDmitry Torokhov 	if (error)
756ecdf6cebSDmitry Torokhov 		goto err_pdev_put;
757ecdf6cebSDmitry Torokhov 
758ecdf6cebSDmitry Torokhov 	error = platform_device_add(pdev);
759ecdf6cebSDmitry Torokhov 	if (error)
760ecdf6cebSDmitry Torokhov 		goto err_pdev_put;
761ecdf6cebSDmitry Torokhov 
762291f653aSWolfram Sang 	error = __platform_driver_probe(driver, probe, module);
763ecdf6cebSDmitry Torokhov 	if (error)
764ecdf6cebSDmitry Torokhov 		goto err_pdev_del;
765ecdf6cebSDmitry Torokhov 
766ecdf6cebSDmitry Torokhov 	return pdev;
767ecdf6cebSDmitry Torokhov 
768ecdf6cebSDmitry Torokhov err_pdev_del:
769ecdf6cebSDmitry Torokhov 	platform_device_del(pdev);
770ecdf6cebSDmitry Torokhov err_pdev_put:
771ecdf6cebSDmitry Torokhov 	platform_device_put(pdev);
772ecdf6cebSDmitry Torokhov err_out:
773ecdf6cebSDmitry Torokhov 	return ERR_PTR(error);
774ecdf6cebSDmitry Torokhov }
775291f653aSWolfram Sang EXPORT_SYMBOL_GPL(__platform_create_bundle);
776ecdf6cebSDmitry Torokhov 
777dbe2256dSThierry Reding /**
778dbe2256dSThierry Reding  * __platform_register_drivers - register an array of platform drivers
779dbe2256dSThierry Reding  * @drivers: an array of drivers to register
780dbe2256dSThierry Reding  * @count: the number of drivers to register
781dbe2256dSThierry Reding  * @owner: module owning the drivers
782dbe2256dSThierry Reding  *
783dbe2256dSThierry Reding  * Registers platform drivers specified by an array. On failure to register a
784dbe2256dSThierry Reding  * driver, all previously registered drivers will be unregistered. Callers of
785dbe2256dSThierry Reding  * this API should use platform_unregister_drivers() to unregister drivers in
786dbe2256dSThierry Reding  * the reverse order.
787dbe2256dSThierry Reding  *
788dbe2256dSThierry Reding  * Returns: 0 on success or a negative error code on failure.
789dbe2256dSThierry Reding  */
790dbe2256dSThierry Reding int __platform_register_drivers(struct platform_driver * const *drivers,
791dbe2256dSThierry Reding 				unsigned int count, struct module *owner)
792dbe2256dSThierry Reding {
793dbe2256dSThierry Reding 	unsigned int i;
794dbe2256dSThierry Reding 	int err;
795dbe2256dSThierry Reding 
796dbe2256dSThierry Reding 	for (i = 0; i < count; i++) {
797dbe2256dSThierry Reding 		pr_debug("registering platform driver %ps\n", drivers[i]);
798dbe2256dSThierry Reding 
799dbe2256dSThierry Reding 		err = __platform_driver_register(drivers[i], owner);
800dbe2256dSThierry Reding 		if (err < 0) {
801dbe2256dSThierry Reding 			pr_err("failed to register platform driver %ps: %d\n",
802dbe2256dSThierry Reding 			       drivers[i], err);
803dbe2256dSThierry Reding 			goto error;
804dbe2256dSThierry Reding 		}
805dbe2256dSThierry Reding 	}
806dbe2256dSThierry Reding 
807dbe2256dSThierry Reding 	return 0;
808dbe2256dSThierry Reding 
809dbe2256dSThierry Reding error:
810dbe2256dSThierry Reding 	while (i--) {
811dbe2256dSThierry Reding 		pr_debug("unregistering platform driver %ps\n", drivers[i]);
812dbe2256dSThierry Reding 		platform_driver_unregister(drivers[i]);
813dbe2256dSThierry Reding 	}
814dbe2256dSThierry Reding 
815dbe2256dSThierry Reding 	return err;
816dbe2256dSThierry Reding }
817dbe2256dSThierry Reding EXPORT_SYMBOL_GPL(__platform_register_drivers);
818dbe2256dSThierry Reding 
819dbe2256dSThierry Reding /**
820dbe2256dSThierry Reding  * platform_unregister_drivers - unregister an array of platform drivers
821dbe2256dSThierry Reding  * @drivers: an array of drivers to unregister
822dbe2256dSThierry Reding  * @count: the number of drivers to unregister
823dbe2256dSThierry Reding  *
824dbe2256dSThierry Reding  * Unegisters platform drivers specified by an array. This is typically used
825dbe2256dSThierry Reding  * to complement an earlier call to platform_register_drivers(). Drivers are
826dbe2256dSThierry Reding  * unregistered in the reverse order in which they were registered.
827dbe2256dSThierry Reding  */
828dbe2256dSThierry Reding void platform_unregister_drivers(struct platform_driver * const *drivers,
829dbe2256dSThierry Reding 				 unsigned int count)
830dbe2256dSThierry Reding {
831dbe2256dSThierry Reding 	while (count--) {
832dbe2256dSThierry Reding 		pr_debug("unregistering platform driver %ps\n", drivers[count]);
833dbe2256dSThierry Reding 		platform_driver_unregister(drivers[count]);
834dbe2256dSThierry Reding 	}
835dbe2256dSThierry Reding }
836dbe2256dSThierry Reding EXPORT_SYMBOL_GPL(platform_unregister_drivers);
837dbe2256dSThierry Reding 
838a0245f7aSDavid Brownell /* modalias support enables more hands-off userspace setup:
839a0245f7aSDavid Brownell  * (a) environment variable lets new-style hotplug events work once system is
840a0245f7aSDavid Brownell  *     fully running:  "modprobe $MODALIAS"
841a0245f7aSDavid Brownell  * (b) sysfs attribute lets new-style coldplug recover from hotplug events
842a0245f7aSDavid Brownell  *     mishandled before system is fully running:  "modprobe $(cat modalias)"
843a0245f7aSDavid Brownell  */
8444a3ad20cSGreg Kroah-Hartman static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
8454a3ad20cSGreg Kroah-Hartman 			     char *buf)
846a0245f7aSDavid Brownell {
847a0245f7aSDavid Brownell 	struct platform_device	*pdev = to_platform_device(dev);
8488c4ff6d0SZhang Rui 	int len;
8498c4ff6d0SZhang Rui 
8500634c295SRob Herring 	len = of_device_modalias(dev, buf, PAGE_SIZE);
851b9f73067SZhang Rui 	if (len != -ENODEV)
852b9f73067SZhang Rui 		return len;
853b9f73067SZhang Rui 
8548c4ff6d0SZhang Rui 	len = acpi_device_modalias(dev, buf, PAGE_SIZE -1);
8558c4ff6d0SZhang Rui 	if (len != -ENODEV)
8568c4ff6d0SZhang Rui 		return len;
8578c4ff6d0SZhang Rui 
8588c4ff6d0SZhang Rui 	len = snprintf(buf, PAGE_SIZE, "platform:%s\n", pdev->name);
859a0245f7aSDavid Brownell 
860a0245f7aSDavid Brownell 	return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
861a0245f7aSDavid Brownell }
862d06262e5SGreg Kroah-Hartman static DEVICE_ATTR_RO(modalias);
863a0245f7aSDavid Brownell 
8643d713e0eSKim Phillips static ssize_t driver_override_store(struct device *dev,
8653d713e0eSKim Phillips 				     struct device_attribute *attr,
8663d713e0eSKim Phillips 				     const char *buf, size_t count)
8673d713e0eSKim Phillips {
8683d713e0eSKim Phillips 	struct platform_device *pdev = to_platform_device(dev);
86962655397SAdrian Salido 	char *driver_override, *old, *cp;
8703d713e0eSKim Phillips 
871bf563b01SNicolai Stange 	/* We need to keep extra room for a newline */
872bf563b01SNicolai Stange 	if (count >= (PAGE_SIZE - 1))
8733d713e0eSKim Phillips 		return -EINVAL;
8743d713e0eSKim Phillips 
8753d713e0eSKim Phillips 	driver_override = kstrndup(buf, count, GFP_KERNEL);
8763d713e0eSKim Phillips 	if (!driver_override)
8773d713e0eSKim Phillips 		return -ENOMEM;
8783d713e0eSKim Phillips 
8793d713e0eSKim Phillips 	cp = strchr(driver_override, '\n');
8803d713e0eSKim Phillips 	if (cp)
8813d713e0eSKim Phillips 		*cp = '\0';
8823d713e0eSKim Phillips 
88362655397SAdrian Salido 	device_lock(dev);
88462655397SAdrian Salido 	old = pdev->driver_override;
8853d713e0eSKim Phillips 	if (strlen(driver_override)) {
8863d713e0eSKim Phillips 		pdev->driver_override = driver_override;
8873d713e0eSKim Phillips 	} else {
8883d713e0eSKim Phillips 		kfree(driver_override);
8893d713e0eSKim Phillips 		pdev->driver_override = NULL;
8903d713e0eSKim Phillips 	}
89162655397SAdrian Salido 	device_unlock(dev);
8923d713e0eSKim Phillips 
8933d713e0eSKim Phillips 	kfree(old);
8943d713e0eSKim Phillips 
8953d713e0eSKim Phillips 	return count;
8963d713e0eSKim Phillips }
8973d713e0eSKim Phillips 
8983d713e0eSKim Phillips static ssize_t driver_override_show(struct device *dev,
8993d713e0eSKim Phillips 				    struct device_attribute *attr, char *buf)
9003d713e0eSKim Phillips {
9013d713e0eSKim Phillips 	struct platform_device *pdev = to_platform_device(dev);
90262655397SAdrian Salido 	ssize_t len;
9033d713e0eSKim Phillips 
90462655397SAdrian Salido 	device_lock(dev);
90562655397SAdrian Salido 	len = sprintf(buf, "%s\n", pdev->driver_override);
90662655397SAdrian Salido 	device_unlock(dev);
90762655397SAdrian Salido 	return len;
9083d713e0eSKim Phillips }
9093d713e0eSKim Phillips static DEVICE_ATTR_RW(driver_override);
9103d713e0eSKim Phillips 
9113d713e0eSKim Phillips 
912d06262e5SGreg Kroah-Hartman static struct attribute *platform_dev_attrs[] = {
913d06262e5SGreg Kroah-Hartman 	&dev_attr_modalias.attr,
9143d713e0eSKim Phillips 	&dev_attr_driver_override.attr,
915d06262e5SGreg Kroah-Hartman 	NULL,
916a0245f7aSDavid Brownell };
917d06262e5SGreg Kroah-Hartman ATTRIBUTE_GROUPS(platform_dev);
918a0245f7aSDavid Brownell 
9197eff2e7aSKay Sievers static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
920a0245f7aSDavid Brownell {
921a0245f7aSDavid Brownell 	struct platform_device	*pdev = to_platform_device(dev);
922eca39301SGrant Likely 	int rc;
923eca39301SGrant Likely 
924eca39301SGrant Likely 	/* Some devices have extra OF data and an OF-style MODALIAS */
92507d57a32SGrant Likely 	rc = of_device_uevent_modalias(dev, env);
926eca39301SGrant Likely 	if (rc != -ENODEV)
927eca39301SGrant Likely 		return rc;
928a0245f7aSDavid Brownell 
9298c4ff6d0SZhang Rui 	rc = acpi_device_uevent_modalias(dev, env);
9308c4ff6d0SZhang Rui 	if (rc != -ENODEV)
9318c4ff6d0SZhang Rui 		return rc;
9328c4ff6d0SZhang Rui 
93357fee4a5SEric Miao 	add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
9340a26813cSSebastian Andrzej Siewior 			pdev->name);
935a0245f7aSDavid Brownell 	return 0;
936a0245f7aSDavid Brownell }
937a0245f7aSDavid Brownell 
93857fee4a5SEric Miao static const struct platform_device_id *platform_match_id(
939831fad2fSUwe Kleine-König 			const struct platform_device_id *id,
94057fee4a5SEric Miao 			struct platform_device *pdev)
94157fee4a5SEric Miao {
94257fee4a5SEric Miao 	while (id->name[0]) {
94357fee4a5SEric Miao 		if (strcmp(pdev->name, id->name) == 0) {
94457fee4a5SEric Miao 			pdev->id_entry = id;
94557fee4a5SEric Miao 			return id;
94657fee4a5SEric Miao 		}
94757fee4a5SEric Miao 		id++;
94857fee4a5SEric Miao 	}
94957fee4a5SEric Miao 	return NULL;
95057fee4a5SEric Miao }
95157fee4a5SEric Miao 
9521da177e4SLinus Torvalds /**
9531da177e4SLinus Torvalds  * platform_match - bind platform device to platform driver.
9541da177e4SLinus Torvalds  * @dev: device.
9551da177e4SLinus Torvalds  * @drv: driver.
9561da177e4SLinus Torvalds  *
9571da177e4SLinus Torvalds  * Platform device IDs are assumed to be encoded like this:
9584a3ad20cSGreg Kroah-Hartman  * "<name><instance>", where <name> is a short description of the type of
9594a3ad20cSGreg Kroah-Hartman  * device, like "pci" or "floppy", and <instance> is the enumerated
9604a3ad20cSGreg Kroah-Hartman  * instance of the device, like '0' or '42'.  Driver IDs are simply
9614a3ad20cSGreg Kroah-Hartman  * "<name>".  So, extract the <name> from the platform_device structure,
9624a3ad20cSGreg Kroah-Hartman  * and compare it against the name of the driver. Return whether they match
9634a3ad20cSGreg Kroah-Hartman  * or not.
9641da177e4SLinus Torvalds  */
9651da177e4SLinus Torvalds static int platform_match(struct device *dev, struct device_driver *drv)
9661da177e4SLinus Torvalds {
96771b3e0c1SEric Miao 	struct platform_device *pdev = to_platform_device(dev);
96857fee4a5SEric Miao 	struct platform_driver *pdrv = to_platform_driver(drv);
9691da177e4SLinus Torvalds 
9703d713e0eSKim Phillips 	/* When driver_override is set, only bind to the matching driver */
9713d713e0eSKim Phillips 	if (pdev->driver_override)
9723d713e0eSKim Phillips 		return !strcmp(pdev->driver_override, drv->name);
9733d713e0eSKim Phillips 
97405212157SGrant Likely 	/* Attempt an OF style match first */
97505212157SGrant Likely 	if (of_driver_match_device(dev, drv))
97605212157SGrant Likely 		return 1;
97705212157SGrant Likely 
97891e56878SMika Westerberg 	/* Then try ACPI style match */
97991e56878SMika Westerberg 	if (acpi_driver_match_device(dev, drv))
98091e56878SMika Westerberg 		return 1;
98191e56878SMika Westerberg 
98205212157SGrant Likely 	/* Then try to match against the id table */
98357fee4a5SEric Miao 	if (pdrv->id_table)
98457fee4a5SEric Miao 		return platform_match_id(pdrv->id_table, pdev) != NULL;
98557fee4a5SEric Miao 
98657fee4a5SEric Miao 	/* fall-back to driver name match */
9871e0b2cf9SKay Sievers 	return (strcmp(pdev->name, drv->name) == 0);
9881da177e4SLinus Torvalds }
9891da177e4SLinus Torvalds 
99025e18499SRafael J. Wysocki #ifdef CONFIG_PM_SLEEP
99125e18499SRafael J. Wysocki 
99225e18499SRafael J. Wysocki static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
9931da177e4SLinus Torvalds {
994783ea7d4SMagnus Damm 	struct platform_driver *pdrv = to_platform_driver(dev->driver);
995783ea7d4SMagnus Damm 	struct platform_device *pdev = to_platform_device(dev);
9961da177e4SLinus Torvalds 	int ret = 0;
9971da177e4SLinus Torvalds 
998783ea7d4SMagnus Damm 	if (dev->driver && pdrv->suspend)
999783ea7d4SMagnus Damm 		ret = pdrv->suspend(pdev, mesg);
1000386415d8SDavid Brownell 
1001386415d8SDavid Brownell 	return ret;
1002386415d8SDavid Brownell }
1003386415d8SDavid Brownell 
100425e18499SRafael J. Wysocki static int platform_legacy_resume(struct device *dev)
10051da177e4SLinus Torvalds {
1006783ea7d4SMagnus Damm 	struct platform_driver *pdrv = to_platform_driver(dev->driver);
1007783ea7d4SMagnus Damm 	struct platform_device *pdev = to_platform_device(dev);
10081da177e4SLinus Torvalds 	int ret = 0;
10091da177e4SLinus Torvalds 
1010783ea7d4SMagnus Damm 	if (dev->driver && pdrv->resume)
1011783ea7d4SMagnus Damm 		ret = pdrv->resume(pdev);
10129480e307SRussell King 
10131da177e4SLinus Torvalds 	return ret;
10141da177e4SLinus Torvalds }
10151da177e4SLinus Torvalds 
101669c9dd1eSRafael J. Wysocki #endif /* CONFIG_PM_SLEEP */
10179d730229SMagnus Damm 
101825e18499SRafael J. Wysocki #ifdef CONFIG_SUSPEND
101925e18499SRafael J. Wysocki 
102069c9dd1eSRafael J. Wysocki int platform_pm_suspend(struct device *dev)
102125e18499SRafael J. Wysocki {
102225e18499SRafael J. Wysocki 	struct device_driver *drv = dev->driver;
102325e18499SRafael J. Wysocki 	int ret = 0;
102425e18499SRafael J. Wysocki 
1025adf09493SRafael J. Wysocki 	if (!drv)
1026adf09493SRafael J. Wysocki 		return 0;
1027adf09493SRafael J. Wysocki 
1028adf09493SRafael J. Wysocki 	if (drv->pm) {
102925e18499SRafael J. Wysocki 		if (drv->pm->suspend)
103025e18499SRafael J. Wysocki 			ret = drv->pm->suspend(dev);
103125e18499SRafael J. Wysocki 	} else {
103225e18499SRafael J. Wysocki 		ret = platform_legacy_suspend(dev, PMSG_SUSPEND);
103325e18499SRafael J. Wysocki 	}
103425e18499SRafael J. Wysocki 
103525e18499SRafael J. Wysocki 	return ret;
103625e18499SRafael J. Wysocki }
103725e18499SRafael J. Wysocki 
103869c9dd1eSRafael J. Wysocki int platform_pm_resume(struct device *dev)
103925e18499SRafael J. Wysocki {
104025e18499SRafael J. Wysocki 	struct device_driver *drv = dev->driver;
104125e18499SRafael J. Wysocki 	int ret = 0;
104225e18499SRafael J. Wysocki 
1043adf09493SRafael J. Wysocki 	if (!drv)
1044adf09493SRafael J. Wysocki 		return 0;
1045adf09493SRafael J. Wysocki 
1046adf09493SRafael J. Wysocki 	if (drv->pm) {
104725e18499SRafael J. Wysocki 		if (drv->pm->resume)
104825e18499SRafael J. Wysocki 			ret = drv->pm->resume(dev);
104925e18499SRafael J. Wysocki 	} else {
105025e18499SRafael J. Wysocki 		ret = platform_legacy_resume(dev);
105125e18499SRafael J. Wysocki 	}
105225e18499SRafael J. Wysocki 
105325e18499SRafael J. Wysocki 	return ret;
105425e18499SRafael J. Wysocki }
105525e18499SRafael J. Wysocki 
105669c9dd1eSRafael J. Wysocki #endif /* CONFIG_SUSPEND */
105725e18499SRafael J. Wysocki 
10581f112ceeSRafael J. Wysocki #ifdef CONFIG_HIBERNATE_CALLBACKS
105925e18499SRafael J. Wysocki 
106069c9dd1eSRafael J. Wysocki int platform_pm_freeze(struct device *dev)
106125e18499SRafael J. Wysocki {
106225e18499SRafael J. Wysocki 	struct device_driver *drv = dev->driver;
106325e18499SRafael J. Wysocki 	int ret = 0;
106425e18499SRafael J. Wysocki 
106525e18499SRafael J. Wysocki 	if (!drv)
106625e18499SRafael J. Wysocki 		return 0;
106725e18499SRafael J. Wysocki 
106825e18499SRafael J. Wysocki 	if (drv->pm) {
106925e18499SRafael J. Wysocki 		if (drv->pm->freeze)
107025e18499SRafael J. Wysocki 			ret = drv->pm->freeze(dev);
107125e18499SRafael J. Wysocki 	} else {
107225e18499SRafael J. Wysocki 		ret = platform_legacy_suspend(dev, PMSG_FREEZE);
107325e18499SRafael J. Wysocki 	}
107425e18499SRafael J. Wysocki 
107525e18499SRafael J. Wysocki 	return ret;
107625e18499SRafael J. Wysocki }
107725e18499SRafael J. Wysocki 
107869c9dd1eSRafael J. Wysocki int platform_pm_thaw(struct device *dev)
107925e18499SRafael J. Wysocki {
108025e18499SRafael J. Wysocki 	struct device_driver *drv = dev->driver;
108125e18499SRafael J. Wysocki 	int ret = 0;
108225e18499SRafael J. Wysocki 
1083adf09493SRafael J. Wysocki 	if (!drv)
1084adf09493SRafael J. Wysocki 		return 0;
1085adf09493SRafael J. Wysocki 
1086adf09493SRafael J. Wysocki 	if (drv->pm) {
108725e18499SRafael J. Wysocki 		if (drv->pm->thaw)
108825e18499SRafael J. Wysocki 			ret = drv->pm->thaw(dev);
108925e18499SRafael J. Wysocki 	} else {
109025e18499SRafael J. Wysocki 		ret = platform_legacy_resume(dev);
109125e18499SRafael J. Wysocki 	}
109225e18499SRafael J. Wysocki 
109325e18499SRafael J. Wysocki 	return ret;
109425e18499SRafael J. Wysocki }
109525e18499SRafael J. Wysocki 
109669c9dd1eSRafael J. Wysocki int platform_pm_poweroff(struct device *dev)
109725e18499SRafael J. Wysocki {
109825e18499SRafael J. Wysocki 	struct device_driver *drv = dev->driver;
109925e18499SRafael J. Wysocki 	int ret = 0;
110025e18499SRafael J. Wysocki 
1101adf09493SRafael J. Wysocki 	if (!drv)
1102adf09493SRafael J. Wysocki 		return 0;
1103adf09493SRafael J. Wysocki 
1104adf09493SRafael J. Wysocki 	if (drv->pm) {
110525e18499SRafael J. Wysocki 		if (drv->pm->poweroff)
110625e18499SRafael J. Wysocki 			ret = drv->pm->poweroff(dev);
110725e18499SRafael J. Wysocki 	} else {
110825e18499SRafael J. Wysocki 		ret = platform_legacy_suspend(dev, PMSG_HIBERNATE);
110925e18499SRafael J. Wysocki 	}
111025e18499SRafael J. Wysocki 
111125e18499SRafael J. Wysocki 	return ret;
111225e18499SRafael J. Wysocki }
111325e18499SRafael J. Wysocki 
111469c9dd1eSRafael J. Wysocki int platform_pm_restore(struct device *dev)
111525e18499SRafael J. Wysocki {
111625e18499SRafael J. Wysocki 	struct device_driver *drv = dev->driver;
111725e18499SRafael J. Wysocki 	int ret = 0;
111825e18499SRafael J. Wysocki 
1119adf09493SRafael J. Wysocki 	if (!drv)
1120adf09493SRafael J. Wysocki 		return 0;
1121adf09493SRafael J. Wysocki 
1122adf09493SRafael J. Wysocki 	if (drv->pm) {
112325e18499SRafael J. Wysocki 		if (drv->pm->restore)
112425e18499SRafael J. Wysocki 			ret = drv->pm->restore(dev);
112525e18499SRafael J. Wysocki 	} else {
112625e18499SRafael J. Wysocki 		ret = platform_legacy_resume(dev);
112725e18499SRafael J. Wysocki 	}
112825e18499SRafael J. Wysocki 
112925e18499SRafael J. Wysocki 	return ret;
113025e18499SRafael J. Wysocki }
113125e18499SRafael J. Wysocki 
113269c9dd1eSRafael J. Wysocki #endif /* CONFIG_HIBERNATE_CALLBACKS */
113325e18499SRafael J. Wysocki 
1134d9ab7716SDmitry Torokhov static const struct dev_pm_ops platform_dev_pm_ops = {
11358b313a38SRafael J. Wysocki 	.runtime_suspend = pm_generic_runtime_suspend,
11368b313a38SRafael J. Wysocki 	.runtime_resume = pm_generic_runtime_resume,
113769c9dd1eSRafael J. Wysocki 	USE_PLATFORM_PM_SLEEP_OPS
113825e18499SRafael J. Wysocki };
113925e18499SRafael J. Wysocki 
11401da177e4SLinus Torvalds struct bus_type platform_bus_type = {
11411da177e4SLinus Torvalds 	.name		= "platform",
1142d06262e5SGreg Kroah-Hartman 	.dev_groups	= platform_dev_groups,
11431da177e4SLinus Torvalds 	.match		= platform_match,
1144a0245f7aSDavid Brownell 	.uevent		= platform_uevent,
11459d730229SMagnus Damm 	.pm		= &platform_dev_pm_ops,
11461da177e4SLinus Torvalds };
1147a96b2042SDmitry Torokhov EXPORT_SYMBOL_GPL(platform_bus_type);
11481da177e4SLinus Torvalds 
11491da177e4SLinus Torvalds int __init platform_bus_init(void)
11501da177e4SLinus Torvalds {
1151fbfb1445SCornelia Huck 	int error;
1152fbfb1445SCornelia Huck 
115313977091SMagnus Damm 	early_platform_cleanup();
115413977091SMagnus Damm 
1155fbfb1445SCornelia Huck 	error = device_register(&platform_bus);
1156fbfb1445SCornelia Huck 	if (error)
1157fbfb1445SCornelia Huck 		return error;
1158fbfb1445SCornelia Huck 	error =  bus_register(&platform_bus_type);
1159fbfb1445SCornelia Huck 	if (error)
1160fbfb1445SCornelia Huck 		device_unregister(&platform_bus);
1161801d728cSPantelis Antoniou 	of_platform_register_reconfig_notifier();
1162fbfb1445SCornelia Huck 	return error;
11631da177e4SLinus Torvalds }
11641da177e4SLinus Torvalds 
11651da177e4SLinus Torvalds #ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK
11661da177e4SLinus Torvalds u64 dma_get_required_mask(struct device *dev)
11671da177e4SLinus Torvalds {
11681da177e4SLinus Torvalds 	u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT);
11691da177e4SLinus Torvalds 	u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT));
11701da177e4SLinus Torvalds 	u64 mask;
11711da177e4SLinus Torvalds 
11721da177e4SLinus Torvalds 	if (!high_totalram) {
11731da177e4SLinus Torvalds 		/* convert to mask just covering totalram */
11741da177e4SLinus Torvalds 		low_totalram = (1 << (fls(low_totalram) - 1));
11751da177e4SLinus Torvalds 		low_totalram += low_totalram - 1;
11761da177e4SLinus Torvalds 		mask = low_totalram;
11771da177e4SLinus Torvalds 	} else {
11781da177e4SLinus Torvalds 		high_totalram = (1 << (fls(high_totalram) - 1));
11791da177e4SLinus Torvalds 		high_totalram += high_totalram - 1;
11801da177e4SLinus Torvalds 		mask = (((u64)high_totalram) << 32) + 0xffffffff;
11811da177e4SLinus Torvalds 	}
1182e88a0c2cSJames Bottomley 	return mask;
11831da177e4SLinus Torvalds }
11841da177e4SLinus Torvalds EXPORT_SYMBOL_GPL(dma_get_required_mask);
11851da177e4SLinus Torvalds #endif
118613977091SMagnus Damm 
118713977091SMagnus Damm static __initdata LIST_HEAD(early_platform_driver_list);
118813977091SMagnus Damm static __initdata LIST_HEAD(early_platform_device_list);
118913977091SMagnus Damm 
119013977091SMagnus Damm /**
11914d26e139SMagnus Damm  * early_platform_driver_register - register early platform driver
1192d86c1302SRandy Dunlap  * @epdrv: early_platform driver structure
119313977091SMagnus Damm  * @buf: string passed from early_param()
11944d26e139SMagnus Damm  *
11954d26e139SMagnus Damm  * Helper function for early_platform_init() / early_platform_init_buffer()
119613977091SMagnus Damm  */
119713977091SMagnus Damm int __init early_platform_driver_register(struct early_platform_driver *epdrv,
119813977091SMagnus Damm 					  char *buf)
119913977091SMagnus Damm {
1200c60e0504SMagnus Damm 	char *tmp;
120113977091SMagnus Damm 	int n;
120213977091SMagnus Damm 
120313977091SMagnus Damm 	/* Simply add the driver to the end of the global list.
120413977091SMagnus Damm 	 * Drivers will by default be put on the list in compiled-in order.
120513977091SMagnus Damm 	 */
120613977091SMagnus Damm 	if (!epdrv->list.next) {
120713977091SMagnus Damm 		INIT_LIST_HEAD(&epdrv->list);
120813977091SMagnus Damm 		list_add_tail(&epdrv->list, &early_platform_driver_list);
120913977091SMagnus Damm 	}
121013977091SMagnus Damm 
121113977091SMagnus Damm 	/* If the user has specified device then make sure the driver
121213977091SMagnus Damm 	 * gets prioritized. The driver of the last device specified on
121313977091SMagnus Damm 	 * command line will be put first on the list.
121413977091SMagnus Damm 	 */
121513977091SMagnus Damm 	n = strlen(epdrv->pdrv->driver.name);
121613977091SMagnus Damm 	if (buf && !strncmp(buf, epdrv->pdrv->driver.name, n)) {
121713977091SMagnus Damm 		list_move(&epdrv->list, &early_platform_driver_list);
121813977091SMagnus Damm 
1219c60e0504SMagnus Damm 		/* Allow passing parameters after device name */
1220c60e0504SMagnus Damm 		if (buf[n] == '\0' || buf[n] == ',')
122113977091SMagnus Damm 			epdrv->requested_id = -1;
1222c60e0504SMagnus Damm 		else {
1223c60e0504SMagnus Damm 			epdrv->requested_id = simple_strtoul(&buf[n + 1],
1224c60e0504SMagnus Damm 							     &tmp, 10);
1225c60e0504SMagnus Damm 
1226c60e0504SMagnus Damm 			if (buf[n] != '.' || (tmp == &buf[n + 1])) {
122713977091SMagnus Damm 				epdrv->requested_id = EARLY_PLATFORM_ID_ERROR;
1228c60e0504SMagnus Damm 				n = 0;
1229c60e0504SMagnus Damm 			} else
1230c60e0504SMagnus Damm 				n += strcspn(&buf[n + 1], ",") + 1;
1231c60e0504SMagnus Damm 		}
1232c60e0504SMagnus Damm 
1233c60e0504SMagnus Damm 		if (buf[n] == ',')
1234c60e0504SMagnus Damm 			n++;
1235c60e0504SMagnus Damm 
1236c60e0504SMagnus Damm 		if (epdrv->bufsize) {
1237c60e0504SMagnus Damm 			memcpy(epdrv->buffer, &buf[n],
1238c60e0504SMagnus Damm 			       min_t(int, epdrv->bufsize, strlen(&buf[n]) + 1));
1239c60e0504SMagnus Damm 			epdrv->buffer[epdrv->bufsize - 1] = '\0';
1240c60e0504SMagnus Damm 		}
124113977091SMagnus Damm 	}
124213977091SMagnus Damm 
124313977091SMagnus Damm 	return 0;
124413977091SMagnus Damm }
124513977091SMagnus Damm 
124613977091SMagnus Damm /**
12474d26e139SMagnus Damm  * early_platform_add_devices - adds a number of early platform devices
124813977091SMagnus Damm  * @devs: array of early platform devices to add
124913977091SMagnus Damm  * @num: number of early platform devices in array
12504d26e139SMagnus Damm  *
12514d26e139SMagnus Damm  * Used by early architecture code to register early platform devices and
12524d26e139SMagnus Damm  * their platform data.
125313977091SMagnus Damm  */
125413977091SMagnus Damm void __init early_platform_add_devices(struct platform_device **devs, int num)
125513977091SMagnus Damm {
125613977091SMagnus Damm 	struct device *dev;
125713977091SMagnus Damm 	int i;
125813977091SMagnus Damm 
125913977091SMagnus Damm 	/* simply add the devices to list */
126013977091SMagnus Damm 	for (i = 0; i < num; i++) {
126113977091SMagnus Damm 		dev = &devs[i]->dev;
126213977091SMagnus Damm 
126313977091SMagnus Damm 		if (!dev->devres_head.next) {
1264bed2b42dSRafael J. Wysocki 			pm_runtime_early_init(dev);
126513977091SMagnus Damm 			INIT_LIST_HEAD(&dev->devres_head);
126613977091SMagnus Damm 			list_add_tail(&dev->devres_head,
126713977091SMagnus Damm 				      &early_platform_device_list);
126813977091SMagnus Damm 		}
126913977091SMagnus Damm 	}
127013977091SMagnus Damm }
127113977091SMagnus Damm 
127213977091SMagnus Damm /**
12734d26e139SMagnus Damm  * early_platform_driver_register_all - register early platform drivers
127413977091SMagnus Damm  * @class_str: string to identify early platform driver class
12754d26e139SMagnus Damm  *
12764d26e139SMagnus Damm  * Used by architecture code to register all early platform drivers
12774d26e139SMagnus Damm  * for a certain class. If omitted then only early platform drivers
12784d26e139SMagnus Damm  * with matching kernel command line class parameters will be registered.
127913977091SMagnus Damm  */
128013977091SMagnus Damm void __init early_platform_driver_register_all(char *class_str)
128113977091SMagnus Damm {
128213977091SMagnus Damm 	/* The "class_str" parameter may or may not be present on the kernel
128313977091SMagnus Damm 	 * command line. If it is present then there may be more than one
128413977091SMagnus Damm 	 * matching parameter.
128513977091SMagnus Damm 	 *
128613977091SMagnus Damm 	 * Since we register our early platform drivers using early_param()
128713977091SMagnus Damm 	 * we need to make sure that they also get registered in the case
128813977091SMagnus Damm 	 * when the parameter is missing from the kernel command line.
128913977091SMagnus Damm 	 *
129013977091SMagnus Damm 	 * We use parse_early_options() to make sure the early_param() gets
129113977091SMagnus Damm 	 * called at least once. The early_param() may be called more than
129213977091SMagnus Damm 	 * once since the name of the preferred device may be specified on
129313977091SMagnus Damm 	 * the kernel command line. early_platform_driver_register() handles
129413977091SMagnus Damm 	 * this case for us.
129513977091SMagnus Damm 	 */
129613977091SMagnus Damm 	parse_early_options(class_str);
129713977091SMagnus Damm }
129813977091SMagnus Damm 
129913977091SMagnus Damm /**
13004d26e139SMagnus Damm  * early_platform_match - find early platform device matching driver
1301d86c1302SRandy Dunlap  * @epdrv: early platform driver structure
130213977091SMagnus Damm  * @id: id to match against
130313977091SMagnus Damm  */
1304a8257910SHanjun Guo static struct platform_device * __init
130513977091SMagnus Damm early_platform_match(struct early_platform_driver *epdrv, int id)
130613977091SMagnus Damm {
130713977091SMagnus Damm 	struct platform_device *pd;
130813977091SMagnus Damm 
130913977091SMagnus Damm 	list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
131013977091SMagnus Damm 		if (platform_match(&pd->dev, &epdrv->pdrv->driver))
131113977091SMagnus Damm 			if (pd->id == id)
131213977091SMagnus Damm 				return pd;
131313977091SMagnus Damm 
131413977091SMagnus Damm 	return NULL;
131513977091SMagnus Damm }
131613977091SMagnus Damm 
131713977091SMagnus Damm /**
13184d26e139SMagnus Damm  * early_platform_left - check if early platform driver has matching devices
1319d86c1302SRandy Dunlap  * @epdrv: early platform driver structure
132013977091SMagnus Damm  * @id: return true if id or above exists
132113977091SMagnus Damm  */
1322a8257910SHanjun Guo static int __init early_platform_left(struct early_platform_driver *epdrv,
132313977091SMagnus Damm 				       int id)
132413977091SMagnus Damm {
132513977091SMagnus Damm 	struct platform_device *pd;
132613977091SMagnus Damm 
132713977091SMagnus Damm 	list_for_each_entry(pd, &early_platform_device_list, dev.devres_head)
132813977091SMagnus Damm 		if (platform_match(&pd->dev, &epdrv->pdrv->driver))
132913977091SMagnus Damm 			if (pd->id >= id)
133013977091SMagnus Damm 				return 1;
133113977091SMagnus Damm 
133213977091SMagnus Damm 	return 0;
133313977091SMagnus Damm }
133413977091SMagnus Damm 
133513977091SMagnus Damm /**
13364d26e139SMagnus Damm  * early_platform_driver_probe_id - probe drivers matching class_str and id
133713977091SMagnus Damm  * @class_str: string to identify early platform driver class
133813977091SMagnus Damm  * @id: id to match against
133913977091SMagnus Damm  * @nr_probe: number of platform devices to successfully probe before exiting
134013977091SMagnus Damm  */
134113977091SMagnus Damm static int __init early_platform_driver_probe_id(char *class_str,
134213977091SMagnus Damm 						 int id,
134313977091SMagnus Damm 						 int nr_probe)
134413977091SMagnus Damm {
134513977091SMagnus Damm 	struct early_platform_driver *epdrv;
134613977091SMagnus Damm 	struct platform_device *match;
134713977091SMagnus Damm 	int match_id;
134813977091SMagnus Damm 	int n = 0;
134913977091SMagnus Damm 	int left = 0;
135013977091SMagnus Damm 
135113977091SMagnus Damm 	list_for_each_entry(epdrv, &early_platform_driver_list, list) {
135213977091SMagnus Damm 		/* only use drivers matching our class_str */
135313977091SMagnus Damm 		if (strcmp(class_str, epdrv->class_str))
135413977091SMagnus Damm 			continue;
135513977091SMagnus Damm 
135613977091SMagnus Damm 		if (id == -2) {
135713977091SMagnus Damm 			match_id = epdrv->requested_id;
135813977091SMagnus Damm 			left = 1;
135913977091SMagnus Damm 
136013977091SMagnus Damm 		} else {
136113977091SMagnus Damm 			match_id = id;
136213977091SMagnus Damm 			left += early_platform_left(epdrv, id);
136313977091SMagnus Damm 
136413977091SMagnus Damm 			/* skip requested id */
136513977091SMagnus Damm 			switch (epdrv->requested_id) {
136613977091SMagnus Damm 			case EARLY_PLATFORM_ID_ERROR:
136713977091SMagnus Damm 			case EARLY_PLATFORM_ID_UNSET:
136813977091SMagnus Damm 				break;
136913977091SMagnus Damm 			default:
137013977091SMagnus Damm 				if (epdrv->requested_id == id)
137113977091SMagnus Damm 					match_id = EARLY_PLATFORM_ID_UNSET;
137213977091SMagnus Damm 			}
137313977091SMagnus Damm 		}
137413977091SMagnus Damm 
137513977091SMagnus Damm 		switch (match_id) {
137613977091SMagnus Damm 		case EARLY_PLATFORM_ID_ERROR:
13770258e182SFabio Porcedda 			pr_warn("%s: unable to parse %s parameter\n",
137813977091SMagnus Damm 				class_str, epdrv->pdrv->driver.name);
137913977091SMagnus Damm 			/* fall-through */
138013977091SMagnus Damm 		case EARLY_PLATFORM_ID_UNSET:
138113977091SMagnus Damm 			match = NULL;
138213977091SMagnus Damm 			break;
138313977091SMagnus Damm 		default:
138413977091SMagnus Damm 			match = early_platform_match(epdrv, match_id);
138513977091SMagnus Damm 		}
138613977091SMagnus Damm 
138713977091SMagnus Damm 		if (match) {
1388a636ee7fSPaul Mundt 			/*
1389a636ee7fSPaul Mundt 			 * Set up a sensible init_name to enable
1390a636ee7fSPaul Mundt 			 * dev_name() and others to be used before the
1391a636ee7fSPaul Mundt 			 * rest of the driver core is initialized.
1392a636ee7fSPaul Mundt 			 */
139306fe53beSPaul Mundt 			if (!match->dev.init_name && slab_is_available()) {
1394a636ee7fSPaul Mundt 				if (match->id != -1)
1395bd05086bSPaul Mundt 					match->dev.init_name =
1396bd05086bSPaul Mundt 						kasprintf(GFP_KERNEL, "%s.%d",
1397bd05086bSPaul Mundt 							  match->name,
1398bd05086bSPaul Mundt 							  match->id);
1399a636ee7fSPaul Mundt 				else
1400bd05086bSPaul Mundt 					match->dev.init_name =
1401bd05086bSPaul Mundt 						kasprintf(GFP_KERNEL, "%s",
1402a636ee7fSPaul Mundt 							  match->name);
1403a636ee7fSPaul Mundt 
1404a636ee7fSPaul Mundt 				if (!match->dev.init_name)
1405a636ee7fSPaul Mundt 					return -ENOMEM;
1406a636ee7fSPaul Mundt 			}
1407bd05086bSPaul Mundt 
140813977091SMagnus Damm 			if (epdrv->pdrv->probe(match))
14090258e182SFabio Porcedda 				pr_warn("%s: unable to probe %s early.\n",
141013977091SMagnus Damm 					class_str, match->name);
141113977091SMagnus Damm 			else
141213977091SMagnus Damm 				n++;
141313977091SMagnus Damm 		}
141413977091SMagnus Damm 
141513977091SMagnus Damm 		if (n >= nr_probe)
141613977091SMagnus Damm 			break;
141713977091SMagnus Damm 	}
141813977091SMagnus Damm 
141913977091SMagnus Damm 	if (left)
142013977091SMagnus Damm 		return n;
142113977091SMagnus Damm 	else
142213977091SMagnus Damm 		return -ENODEV;
142313977091SMagnus Damm }
142413977091SMagnus Damm 
142513977091SMagnus Damm /**
14264d26e139SMagnus Damm  * early_platform_driver_probe - probe a class of registered drivers
142713977091SMagnus Damm  * @class_str: string to identify early platform driver class
142813977091SMagnus Damm  * @nr_probe: number of platform devices to successfully probe before exiting
142913977091SMagnus Damm  * @user_only: only probe user specified early platform devices
14304d26e139SMagnus Damm  *
14314d26e139SMagnus Damm  * Used by architecture code to probe registered early platform drivers
14324d26e139SMagnus Damm  * within a certain class. For probe to happen a registered early platform
14334d26e139SMagnus Damm  * device matching a registered early platform driver is needed.
143413977091SMagnus Damm  */
143513977091SMagnus Damm int __init early_platform_driver_probe(char *class_str,
143613977091SMagnus Damm 				       int nr_probe,
143713977091SMagnus Damm 				       int user_only)
143813977091SMagnus Damm {
143913977091SMagnus Damm 	int k, n, i;
144013977091SMagnus Damm 
144113977091SMagnus Damm 	n = 0;
144213977091SMagnus Damm 	for (i = -2; n < nr_probe; i++) {
144313977091SMagnus Damm 		k = early_platform_driver_probe_id(class_str, i, nr_probe - n);
144413977091SMagnus Damm 
144513977091SMagnus Damm 		if (k < 0)
144613977091SMagnus Damm 			break;
144713977091SMagnus Damm 
144813977091SMagnus Damm 		n += k;
144913977091SMagnus Damm 
145013977091SMagnus Damm 		if (user_only)
145113977091SMagnus Damm 			break;
145213977091SMagnus Damm 	}
145313977091SMagnus Damm 
145413977091SMagnus Damm 	return n;
145513977091SMagnus Damm }
145613977091SMagnus Damm 
145713977091SMagnus Damm /**
145813977091SMagnus Damm  * early_platform_cleanup - clean up early platform code
145913977091SMagnus Damm  */
146013977091SMagnus Damm void __init early_platform_cleanup(void)
146113977091SMagnus Damm {
146213977091SMagnus Damm 	struct platform_device *pd, *pd2;
146313977091SMagnus Damm 
146413977091SMagnus Damm 	/* clean up the devres list used to chain devices */
146513977091SMagnus Damm 	list_for_each_entry_safe(pd, pd2, &early_platform_device_list,
146613977091SMagnus Damm 				 dev.devres_head) {
146713977091SMagnus Damm 		list_del(&pd->dev.devres_head);
146813977091SMagnus Damm 		memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
146913977091SMagnus Damm 	}
147013977091SMagnus Damm }
147113977091SMagnus Damm 
1472