273 lines · 6.2 KB · C
RawDownload
#include <linux/config.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/mod_devicetable.h>#include <linux/slab.h> #include <asm/errno.h>#include <asm/of_device.h> /** * of_match_device - Tell if an of_device structure has a matching * of_match structure * @ids: array of of device match structures to search in * @dev: the of device structure to match against * * Used by a driver to check whether an of_device present in the * system is in its list of supported devices. */const struct of_device_id *of_match_device(const struct of_device_id *matches,					const struct of_device *dev){	if (!dev->node)		return NULL;	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {		int match = 1;		if (matches->name[0])			match &= dev->node->name				&& !strcmp(matches->name, dev->node->name);		if (matches->type[0])			match &= dev->node->type				&& !strcmp(matches->type, dev->node->type);		if (matches->compatible[0])			match &= device_is_compatible(dev->node,				matches->compatible);		if (match)			return matches;		matches++;	}	return NULL;} static int of_platform_bus_match(struct device *dev, struct device_driver *drv){	struct of_device * of_dev = to_of_device(dev);	struct of_platform_driver * of_drv = to_of_platform_driver(drv);	const struct of_device_id * matches = of_drv->match_table; 	if (!matches)		return 0; 	return of_match_device(matches, of_dev) != NULL;} struct of_device *of_dev_get(struct of_device *dev){	struct device *tmp; 	if (!dev)		return NULL;	tmp = get_device(&dev->dev);	if (tmp)		return to_of_device(tmp);	else		return NULL;} void of_dev_put(struct of_device *dev){	if (dev)		put_device(&dev->dev);}  static int of_device_probe(struct device *dev){	int error = -ENODEV;	struct of_platform_driver *drv;	struct of_device *of_dev;	const struct of_device_id *match; 	drv = to_of_platform_driver(dev->driver);	of_dev = to_of_device(dev); 	if (!drv->probe)		return error; 	of_dev_get(of_dev); 	match = of_match_device(drv->match_table, of_dev);	if (match)		error = drv->probe(of_dev, match);	if (error)		of_dev_put(of_dev); 	return error;} static int of_device_remove(struct device *dev){	struct of_device * of_dev = to_of_device(dev);	struct of_platform_driver * drv = to_of_platform_driver(dev->driver); 	if (dev->driver && drv->remove)		drv->remove(of_dev);	return 0;} static int of_device_suspend(struct device *dev, pm_message_t state){	struct of_device * of_dev = to_of_device(dev);	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);	int error = 0; 	if (dev->driver && drv->suspend)		error = drv->suspend(of_dev, state);	return error;} static int of_device_resume(struct device * dev){	struct of_device * of_dev = to_of_device(dev);	struct of_platform_driver * drv = to_of_platform_driver(dev->driver);	int error = 0; 	if (dev->driver && drv->resume)		error = drv->resume(of_dev);	return error;} struct bus_type of_platform_bus_type = {       .name	= "of_platform",       .match	= of_platform_bus_match,       .probe	= of_device_probe,       .remove	= of_device_remove,       .suspend	= of_device_suspend,       .resume	= of_device_resume,}; static int __init of_bus_driver_init(void){	return bus_register(&of_platform_bus_type);} postcore_initcall(of_bus_driver_init); int of_register_driver(struct of_platform_driver *drv){	/* initialize common driver fields */	drv->driver.name = drv->name;	drv->driver.bus = &of_platform_bus_type; 	/* register with core */	return driver_register(&drv->driver);} void of_unregister_driver(struct of_platform_driver *drv){	driver_unregister(&drv->driver);}  static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf){	struct of_device *ofdev; 	ofdev = to_of_device(dev);	return sprintf(buf, "%s", ofdev->node->full_name);} static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); /** * of_release_dev - free an of device structure when all users of it are finished. * @dev: device that's been disconnected * * Will be called only by the device core when all users of this of device are * done. */void of_release_dev(struct device *dev){	struct of_device *ofdev;         ofdev = to_of_device(dev);	of_node_put(ofdev->node);	kfree(ofdev);} int of_device_register(struct of_device *ofdev){	int rc;	struct of_device **odprop; 	BUG_ON(ofdev->node == NULL); 	odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);	if (!odprop) {		struct property *new_prop;			new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *),			GFP_KERNEL);		if (new_prop == NULL)			return -ENOMEM;		new_prop->name = "linux,device";		new_prop->length = sizeof(sizeof(struct of_device *));		new_prop->value = (unsigned char *)&new_prop[1];		odprop = (struct of_device **)new_prop->value;		*odprop = NULL;		prom_add_property(ofdev->node, new_prop);	}	*odprop = ofdev; 	rc = device_register(&ofdev->dev);	if (rc)		return rc; 	device_create_file(&ofdev->dev, &dev_attr_devspec); 	return 0;} void of_device_unregister(struct of_device *ofdev){	struct of_device **odprop; 	device_remove_file(&ofdev->dev, &dev_attr_devspec); 	odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL);	if (odprop)		*odprop = NULL; 	device_unregister(&ofdev->dev);} struct of_device* of_platform_device_create(struct device_node *np,					    const char *bus_id,					    struct device *parent){	struct of_device *dev; 	dev = kmalloc(sizeof(*dev), GFP_KERNEL);	if (!dev)		return NULL;	memset(dev, 0, sizeof(*dev)); 	dev->node = of_node_get(np);	dev->dma_mask = 0xffffffffUL;	dev->dev.dma_mask = &dev->dma_mask;	dev->dev.parent = parent;	dev->dev.bus = &of_platform_bus_type;	dev->dev.release = of_release_dev; 	strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); 	if (of_device_register(dev) != 0) {		kfree(dev);		return NULL;	} 	return dev;} EXPORT_SYMBOL(of_match_device);EXPORT_SYMBOL(of_platform_bus_type);EXPORT_SYMBOL(of_register_driver);EXPORT_SYMBOL(of_unregister_driver);EXPORT_SYMBOL(of_device_register);EXPORT_SYMBOL(of_device_unregister);EXPORT_SYMBOL(of_dev_get);EXPORT_SYMBOL(of_dev_put);EXPORT_SYMBOL(of_platform_device_create);EXPORT_SYMBOL(of_release_dev);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t