mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	[POWERPC] Move of_device allocation into of_device.[ch]
Extract generic of_device allocation code from of_platform_device_create() and move it into of_device.[ch], called of_device_alloc(). Also, there's now of_device_free() which puts the device node. This way, bus drivers that build on of_platform (like ibmebus will) can build upon this code instead of reinventing the wheel. Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
		
							parent
							
								
									ebb3e820b8
								
							
						
					
					
						commit
						fec738dd48
					
				
					 4 changed files with 91 additions and 68 deletions
				
			
		|  | @ -7,8 +7,88 @@ | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| 
 | 
 | ||||||
| #include <asm/errno.h> | #include <asm/errno.h> | ||||||
|  | #include <asm/dcr.h> | ||||||
| #include <asm/of_device.h> | #include <asm/of_device.h> | ||||||
| 
 | 
 | ||||||
|  | static void of_device_make_bus_id(struct of_device *dev) | ||||||
|  | { | ||||||
|  | 	static atomic_t bus_no_reg_magic; | ||||||
|  | 	struct device_node *node = dev->node; | ||||||
|  | 	char *name = dev->dev.bus_id; | ||||||
|  | 	const u32 *reg; | ||||||
|  | 	u64 addr; | ||||||
|  | 	int magic; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * If it's a DCR based device, use 'd' for native DCRs | ||||||
|  | 	 * and 'D' for MMIO DCRs. | ||||||
|  | 	 */ | ||||||
|  | #ifdef CONFIG_PPC_DCR | ||||||
|  | 	reg = of_get_property(node, "dcr-reg", NULL); | ||||||
|  | 	if (reg) { | ||||||
|  | #ifdef CONFIG_PPC_DCR_NATIVE | ||||||
|  | 		snprintf(name, BUS_ID_SIZE, "d%x.%s", | ||||||
|  | 			 *reg, node->name); | ||||||
|  | #else /* CONFIG_PPC_DCR_NATIVE */ | ||||||
|  | 		addr = of_translate_dcr_address(node, *reg, NULL); | ||||||
|  | 		if (addr != OF_BAD_ADDR) { | ||||||
|  | 			snprintf(name, BUS_ID_SIZE, | ||||||
|  | 				 "D%llx.%s", (unsigned long long)addr, | ||||||
|  | 				 node->name); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | #endif /* !CONFIG_PPC_DCR_NATIVE */ | ||||||
|  | 	} | ||||||
|  | #endif /* CONFIG_PPC_DCR */ | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * For MMIO, get the physical address | ||||||
|  | 	 */ | ||||||
|  | 	reg = of_get_property(node, "reg", NULL); | ||||||
|  | 	if (reg) { | ||||||
|  | 		addr = of_translate_address(node, reg); | ||||||
|  | 		if (addr != OF_BAD_ADDR) { | ||||||
|  | 			snprintf(name, BUS_ID_SIZE, | ||||||
|  | 				 "%llx.%s", (unsigned long long)addr, | ||||||
|  | 				 node->name); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * No BusID, use the node name and add a globally incremented | ||||||
|  | 	 * counter (and pray...) | ||||||
|  | 	 */ | ||||||
|  | 	magic = atomic_add_return(1, &bus_no_reg_magic); | ||||||
|  | 	snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct of_device *of_device_alloc(struct device_node *np, | ||||||
|  | 				  const char *bus_id, | ||||||
|  | 				  struct device *parent) | ||||||
|  | { | ||||||
|  | 	struct of_device *dev; | ||||||
|  | 
 | ||||||
|  | 	dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||||||
|  | 	if (!dev) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	dev->node = of_node_get(np); | ||||||
|  | 	dev->dev.dma_mask = &dev->dma_mask; | ||||||
|  | 	dev->dev.parent = parent; | ||||||
|  | 	dev->dev.release = of_release_dev; | ||||||
|  | 	dev->dev.archdata.of_node = np; | ||||||
|  | 	dev->dev.archdata.numa_node = of_node_to_nid(np); | ||||||
|  | 
 | ||||||
|  | 	if (bus_id) | ||||||
|  | 		strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); | ||||||
|  | 	else | ||||||
|  | 		of_device_make_bus_id(dev); | ||||||
|  | 
 | ||||||
|  | 	return dev; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL(of_device_alloc); | ||||||
|  | 
 | ||||||
| ssize_t of_device_get_modalias(struct of_device *ofdev, | ssize_t of_device_get_modalias(struct of_device *ofdev, | ||||||
| 				char *str, ssize_t len) | 				char *str, ssize_t len) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -23,7 +23,6 @@ | ||||||
| #include <linux/of_platform.h> | #include <linux/of_platform.h> | ||||||
| 
 | 
 | ||||||
| #include <asm/errno.h> | #include <asm/errno.h> | ||||||
| #include <asm/dcr.h> |  | ||||||
| #include <asm/topology.h> | #include <asm/topology.h> | ||||||
| #include <asm/pci-bridge.h> | #include <asm/pci-bridge.h> | ||||||
| #include <asm/ppc-pci.h> | #include <asm/ppc-pci.h> | ||||||
|  | @ -53,8 +52,6 @@ static struct of_device_id of_default_bus_ids[] = { | ||||||
| 	{}, | 	{}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static atomic_t bus_no_reg_magic; |  | ||||||
| 
 |  | ||||||
| struct bus_type of_platform_bus_type = { | struct bus_type of_platform_bus_type = { | ||||||
|        .uevent	= of_device_uevent, |        .uevent	= of_device_uevent, | ||||||
| }; | }; | ||||||
|  | @ -87,89 +84,26 @@ void of_unregister_platform_driver(struct of_platform_driver *drv) | ||||||
| } | } | ||||||
| EXPORT_SYMBOL(of_unregister_platform_driver); | EXPORT_SYMBOL(of_unregister_platform_driver); | ||||||
| 
 | 
 | ||||||
| static void of_platform_make_bus_id(struct of_device *dev) |  | ||||||
| { |  | ||||||
| 	struct device_node *node = dev->node; |  | ||||||
| 	char *name = dev->dev.bus_id; |  | ||||||
| 	const u32 *reg; |  | ||||||
| 	u64 addr; |  | ||||||
| 	int magic; |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * If it's a DCR based device, use 'd' for native DCRs |  | ||||||
| 	 * and 'D' for MMIO DCRs. |  | ||||||
| 	 */ |  | ||||||
| #ifdef CONFIG_PPC_DCR |  | ||||||
| 	reg = of_get_property(node, "dcr-reg", NULL); |  | ||||||
| 	if (reg) { |  | ||||||
| #ifdef CONFIG_PPC_DCR_NATIVE |  | ||||||
| 		snprintf(name, BUS_ID_SIZE, "d%x.%s", |  | ||||||
| 			 *reg, node->name); |  | ||||||
| #else /* CONFIG_PPC_DCR_NATIVE */ |  | ||||||
| 		addr = of_translate_dcr_address(node, *reg, NULL); |  | ||||||
| 		if (addr != OF_BAD_ADDR) { |  | ||||||
| 			snprintf(name, BUS_ID_SIZE, |  | ||||||
| 				 "D%llx.%s", (unsigned long long)addr, |  | ||||||
| 				 node->name); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| #endif /* !CONFIG_PPC_DCR_NATIVE */ |  | ||||||
| 	} |  | ||||||
| #endif /* CONFIG_PPC_DCR */ |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * For MMIO, get the physical address |  | ||||||
| 	 */ |  | ||||||
| 	reg = of_get_property(node, "reg", NULL); |  | ||||||
| 	if (reg) { |  | ||||||
| 		addr = of_translate_address(node, reg); |  | ||||||
| 		if (addr != OF_BAD_ADDR) { |  | ||||||
| 			snprintf(name, BUS_ID_SIZE, |  | ||||||
| 				 "%llx.%s", (unsigned long long)addr, |  | ||||||
| 				 node->name); |  | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * No BusID, use the node name and add a globally incremented |  | ||||||
| 	 * counter (and pray...) |  | ||||||
| 	 */ |  | ||||||
| 	magic = atomic_add_return(1, &bus_no_reg_magic); |  | ||||||
| 	snprintf(name, BUS_ID_SIZE, "%s.%d", node->name, magic - 1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct of_device* of_platform_device_create(struct device_node *np, | struct of_device* of_platform_device_create(struct device_node *np, | ||||||
| 					    const char *bus_id, | 					    const char *bus_id, | ||||||
| 					    struct device *parent) | 					    struct device *parent) | ||||||
| { | { | ||||||
| 	struct of_device *dev; | 	struct of_device *dev; | ||||||
| 
 | 
 | ||||||
| 	dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 	dev = of_device_alloc(np, bus_id, parent); | ||||||
| 	if (!dev) | 	if (!dev) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	dev->node = of_node_get(np); |  | ||||||
| 	dev->dma_mask = 0xffffffffUL; | 	dev->dma_mask = 0xffffffffUL; | ||||||
| 	dev->dev.dma_mask = &dev->dma_mask; |  | ||||||
| 	dev->dev.parent = parent; |  | ||||||
| 	dev->dev.bus = &of_platform_bus_type; | 	dev->dev.bus = &of_platform_bus_type; | ||||||
| 	dev->dev.release = of_release_dev; |  | ||||||
| 	dev->dev.archdata.of_node = np; |  | ||||||
| 	dev->dev.archdata.numa_node = of_node_to_nid(np); |  | ||||||
| 
 | 
 | ||||||
| 	/* We do not fill the DMA ops for platform devices by default.
 | 	/* We do not fill the DMA ops for platform devices by default.
 | ||||||
| 	 * This is currently the responsibility of the platform code | 	 * This is currently the responsibility of the platform code | ||||||
| 	 * to do such, possibly using a device notifier | 	 * to do such, possibly using a device notifier | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
| 	if (bus_id) |  | ||||||
| 		strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); |  | ||||||
| 	else |  | ||||||
| 		of_platform_make_bus_id(dev); |  | ||||||
| 
 |  | ||||||
| 	if (of_device_register(dev) != 0) { | 	if (of_device_register(dev) != 0) { | ||||||
| 		kfree(dev); | 		of_device_free(dev); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -17,6 +17,10 @@ struct of_device | ||||||
| 	struct device		dev;		/* Generic device interface */ | 	struct device		dev;		/* Generic device interface */ | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | extern struct of_device *of_device_alloc(struct device_node *np, | ||||||
|  | 					 const char *bus_id, | ||||||
|  | 					 struct device *parent); | ||||||
|  | 
 | ||||||
| extern ssize_t of_device_get_modalias(struct of_device *ofdev, | extern ssize_t of_device_get_modalias(struct of_device *ofdev, | ||||||
| 					char *str, ssize_t len); | 					char *str, ssize_t len); | ||||||
| extern int of_device_uevent(struct device *dev, | extern int of_device_uevent(struct device *dev, | ||||||
|  |  | ||||||
|  | @ -22,5 +22,10 @@ extern int of_device_register(struct of_device *ofdev); | ||||||
| extern void of_device_unregister(struct of_device *ofdev); | extern void of_device_unregister(struct of_device *ofdev); | ||||||
| extern void of_release_dev(struct device *dev); | extern void of_release_dev(struct device *dev); | ||||||
| 
 | 
 | ||||||
|  | static inline void of_device_free(struct of_device *dev) | ||||||
|  | { | ||||||
|  | 	of_release_dev(&dev->dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #endif /* __KERNEL__ */ | #endif /* __KERNEL__ */ | ||||||
| #endif /* _LINUX_OF_DEVICE_H */ | #endif /* _LINUX_OF_DEVICE_H */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Joachim Fenkes
						Joachim Fenkes