PageRenderTime 32ms CodeModel.GetById 13ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/ppc64/kernel/of_device.c

https://bitbucket.org/evzijst/gittest
C | 272 lines | 203 code | 51 blank | 18 comment | 39 complexity | a823006873f157f9361774873aa0b64d MD5 | raw file
  1#include <linux/config.h>
  2#include <linux/string.h>
  3#include <linux/kernel.h>
  4#include <linux/init.h>
  5#include <linux/module.h>
  6#include <asm/errno.h>
  7#include <asm/of_device.h>
  8
  9/**
 10 * of_match_device - Tell if an of_device structure has a matching
 11 * of_match structure
 12 * @ids: array of of device match structures to search in
 13 * @dev: the of device structure to match against
 14 *
 15 * Used by a driver to check whether an of_device present in the
 16 * system is in its list of supported devices.
 17 */
 18const struct of_match * of_match_device(const struct of_match *matches,
 19					const struct of_device *dev)
 20{
 21	if (!dev->node)
 22		return NULL;
 23	while (matches->name || matches->type || matches->compatible) {
 24		int match = 1;
 25		if (matches->name && matches->name != OF_ANY_MATCH)
 26			match &= dev->node->name
 27				&& !strcmp(matches->name, dev->node->name);
 28		if (matches->type && matches->type != OF_ANY_MATCH)
 29			match &= dev->node->type
 30				&& !strcmp(matches->type, dev->node->type);
 31		if (matches->compatible && matches->compatible != OF_ANY_MATCH)
 32			match &= device_is_compatible(dev->node,
 33				matches->compatible);
 34		if (match)
 35			return matches;
 36		matches++;
 37	}
 38	return NULL;
 39}
 40
 41static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
 42{
 43	struct of_device * of_dev = to_of_device(dev);
 44	struct of_platform_driver * of_drv = to_of_platform_driver(drv);
 45	const struct of_match * matches = of_drv->match_table;
 46
 47	if (!matches)
 48		return 0;
 49
 50	return of_match_device(matches, of_dev) != NULL;
 51}
 52
 53struct of_device *of_dev_get(struct of_device *dev)
 54{
 55	struct device *tmp;
 56
 57	if (!dev)
 58		return NULL;
 59	tmp = get_device(&dev->dev);
 60	if (tmp)
 61		return to_of_device(tmp);
 62	else
 63		return NULL;
 64}
 65
 66void of_dev_put(struct of_device *dev)
 67{
 68	if (dev)
 69		put_device(&dev->dev);
 70}
 71
 72
 73static int of_device_probe(struct device *dev)
 74{
 75	int error = -ENODEV;
 76	struct of_platform_driver *drv;
 77	struct of_device *of_dev;
 78	const struct of_match *match;
 79
 80	drv = to_of_platform_driver(dev->driver);
 81	of_dev = to_of_device(dev);
 82
 83	if (!drv->probe)
 84		return error;
 85
 86	of_dev_get(of_dev);
 87
 88	match = of_match_device(drv->match_table, of_dev);
 89	if (match)
 90		error = drv->probe(of_dev, match);
 91	if (error)
 92		of_dev_put(of_dev);
 93
 94	return error;
 95}
 96
 97static int of_device_remove(struct device *dev)
 98{
 99	struct of_device * of_dev = to_of_device(dev);
100	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
101
102	if (dev->driver && drv->remove)
103		drv->remove(of_dev);
104	return 0;
105}
106
107static int of_device_suspend(struct device *dev, u32 state)
108{
109	struct of_device * of_dev = to_of_device(dev);
110	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
111	int error = 0;
112
113	if (dev->driver && drv->suspend)
114		error = drv->suspend(of_dev, state);
115	return error;
116}
117
118static int of_device_resume(struct device * dev)
119{
120	struct of_device * of_dev = to_of_device(dev);
121	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
122	int error = 0;
123
124	if (dev->driver && drv->resume)
125		error = drv->resume(of_dev);
126	return error;
127}
128
129struct bus_type of_platform_bus_type = {
130       .name	= "of_platform",
131       .match	= of_platform_bus_match,
132       .suspend	= of_device_suspend,
133       .resume	= of_device_resume,
134};
135
136static int __init of_bus_driver_init(void)
137{
138	return bus_register(&of_platform_bus_type);
139}
140
141postcore_initcall(of_bus_driver_init);
142
143int of_register_driver(struct of_platform_driver *drv)
144{
145	int count = 0;
146
147	/* initialize common driver fields */
148	drv->driver.name = drv->name;
149	drv->driver.bus = &of_platform_bus_type;
150	drv->driver.probe = of_device_probe;
151	drv->driver.remove = of_device_remove;
152
153	/* register with core */
154	count = driver_register(&drv->driver);
155	return count ? count : 1;
156}
157
158void of_unregister_driver(struct of_platform_driver *drv)
159{
160	driver_unregister(&drv->driver);
161}
162
163
164static ssize_t dev_show_devspec(struct device *dev, char *buf)
165{
166	struct of_device *ofdev;
167
168	ofdev = to_of_device(dev);
169	return sprintf(buf, "%s", ofdev->node->full_name);
170}
171
172static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL);
173
174/**
175 * of_release_dev - free an of device structure when all users of it are finished.
176 * @dev: device that's been disconnected
177 *
178 * Will be called only by the device core when all users of this of device are
179 * done.
180 */
181void of_release_dev(struct device *dev)
182{
183	struct of_device *ofdev;
184
185        ofdev = to_of_device(dev);
186	kfree(ofdev);
187}
188
189int of_device_register(struct of_device *ofdev)
190{
191	int rc;
192	struct of_device **odprop;
193
194	BUG_ON(ofdev->node == NULL);
195
196	odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
197	if (!odprop) {
198		struct property *new_prop;
199	
200		new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *),
201			GFP_KERNEL);
202		if (new_prop == NULL)
203			return -ENOMEM;
204		new_prop->name = "linux,device";
205		new_prop->length = sizeof(sizeof(struct of_device *));
206		new_prop->value = (unsigned char *)&new_prop[1];
207		odprop = (struct of_device **)new_prop->value;
208		*odprop = NULL;
209		prom_add_property(ofdev->node, new_prop);
210	}
211	*odprop = ofdev;
212
213	rc = device_register(&ofdev->dev);
214	if (rc)
215		return rc;
216
217	device_create_file(&ofdev->dev, &dev_attr_devspec);
218
219	return 0;
220}
221
222void of_device_unregister(struct of_device *ofdev)
223{
224	struct of_device **odprop;
225
226	device_remove_file(&ofdev->dev, &dev_attr_devspec);
227
228	odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);
229	if (odprop)
230		*odprop = NULL;
231
232	device_unregister(&ofdev->dev);
233}
234
235struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id)
236{
237	struct of_device *dev;
238	u32 *reg;
239
240	dev = kmalloc(sizeof(*dev), GFP_KERNEL);
241	if (!dev)
242		return NULL;
243	memset(dev, 0, sizeof(*dev));
244
245	dev->node = np;
246	dev->dma_mask = 0xffffffffUL;
247	dev->dev.dma_mask = &dev->dma_mask;
248	dev->dev.parent = NULL;
249	dev->dev.bus = &of_platform_bus_type;
250	dev->dev.release = of_release_dev;
251
252	reg = (u32 *)get_property(np, "reg", NULL);
253	strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
254
255	if (of_device_register(dev) != 0) {
256		kfree(dev);
257		return NULL;
258	}
259
260	return dev;
261}
262
263EXPORT_SYMBOL(of_match_device);
264EXPORT_SYMBOL(of_platform_bus_type);
265EXPORT_SYMBOL(of_register_driver);
266EXPORT_SYMBOL(of_unregister_driver);
267EXPORT_SYMBOL(of_device_register);
268EXPORT_SYMBOL(of_device_unregister);
269EXPORT_SYMBOL(of_dev_get);
270EXPORT_SYMBOL(of_dev_put);
271EXPORT_SYMBOL(of_platform_device_create);
272EXPORT_SYMBOL(of_release_dev);