xref: /OK3568_Linux_fs/kernel/arch/powerpc/platforms/pseries/ibmebus.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * IBM PowerPC IBM eBus Infrastructure Support.
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (c) 2005 IBM Corporation
5*4882a593Smuzhiyun  *  Joachim Fenkes <fenkes@de.ibm.com>
6*4882a593Smuzhiyun  *  Heiko J Schick <schickhj@de.ibm.com>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * All rights reserved.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * This source code is distributed under a dual license of GPL v2.0 and OpenIB
11*4882a593Smuzhiyun  * BSD.
12*4882a593Smuzhiyun  *
13*4882a593Smuzhiyun  * OpenIB BSD License
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
16*4882a593Smuzhiyun  * modification, are permitted provided that the following conditions are met:
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * Redistributions of source code must retain the above copyright notice, this
19*4882a593Smuzhiyun  * list of conditions and the following disclaimer.
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  * Redistributions in binary form must reproduce the above copyright notice,
22*4882a593Smuzhiyun  * this list of conditions and the following disclaimer in the documentation
23*4882a593Smuzhiyun  * and/or other materials
24*4882a593Smuzhiyun  * provided with the distribution.
25*4882a593Smuzhiyun  *
26*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27*4882a593Smuzhiyun  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28*4882a593Smuzhiyun  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29*4882a593Smuzhiyun  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30*4882a593Smuzhiyun  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32*4882a593Smuzhiyun  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
33*4882a593Smuzhiyun  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
34*4882a593Smuzhiyun  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35*4882a593Smuzhiyun  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36*4882a593Smuzhiyun  * POSSIBILITY OF SUCH DAMAGE.
37*4882a593Smuzhiyun  */
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #include <linux/init.h>
40*4882a593Smuzhiyun #include <linux/export.h>
41*4882a593Smuzhiyun #include <linux/console.h>
42*4882a593Smuzhiyun #include <linux/kobject.h>
43*4882a593Smuzhiyun #include <linux/dma-map-ops.h>
44*4882a593Smuzhiyun #include <linux/interrupt.h>
45*4882a593Smuzhiyun #include <linux/of.h>
46*4882a593Smuzhiyun #include <linux/slab.h>
47*4882a593Smuzhiyun #include <linux/stat.h>
48*4882a593Smuzhiyun #include <linux/of_platform.h>
49*4882a593Smuzhiyun #include <asm/ibmebus.h>
50*4882a593Smuzhiyun #include <asm/machdep.h>
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun static struct device ibmebus_bus_device = { /* fake "parent" device */
53*4882a593Smuzhiyun 	.init_name = "ibmebus",
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun struct bus_type ibmebus_bus_type;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun /* These devices will automatically be added to the bus during init */
59*4882a593Smuzhiyun static const struct of_device_id ibmebus_matches[] __initconst = {
60*4882a593Smuzhiyun 	{ .compatible = "IBM,lhca" },
61*4882a593Smuzhiyun 	{ .compatible = "IBM,lhea" },
62*4882a593Smuzhiyun 	{},
63*4882a593Smuzhiyun };
64*4882a593Smuzhiyun 
ibmebus_alloc_coherent(struct device * dev,size_t size,dma_addr_t * dma_handle,gfp_t flag,unsigned long attrs)65*4882a593Smuzhiyun static void *ibmebus_alloc_coherent(struct device *dev,
66*4882a593Smuzhiyun 				    size_t size,
67*4882a593Smuzhiyun 				    dma_addr_t *dma_handle,
68*4882a593Smuzhiyun 				    gfp_t flag,
69*4882a593Smuzhiyun 				    unsigned long attrs)
70*4882a593Smuzhiyun {
71*4882a593Smuzhiyun 	void *mem;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 	mem = kmalloc(size, flag);
74*4882a593Smuzhiyun 	*dma_handle = (dma_addr_t)mem;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	return mem;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
ibmebus_free_coherent(struct device * dev,size_t size,void * vaddr,dma_addr_t dma_handle,unsigned long attrs)79*4882a593Smuzhiyun static void ibmebus_free_coherent(struct device *dev,
80*4882a593Smuzhiyun 				  size_t size, void *vaddr,
81*4882a593Smuzhiyun 				  dma_addr_t dma_handle,
82*4882a593Smuzhiyun 				  unsigned long attrs)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	kfree(vaddr);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
ibmebus_map_page(struct device * dev,struct page * page,unsigned long offset,size_t size,enum dma_data_direction direction,unsigned long attrs)87*4882a593Smuzhiyun static dma_addr_t ibmebus_map_page(struct device *dev,
88*4882a593Smuzhiyun 				   struct page *page,
89*4882a593Smuzhiyun 				   unsigned long offset,
90*4882a593Smuzhiyun 				   size_t size,
91*4882a593Smuzhiyun 				   enum dma_data_direction direction,
92*4882a593Smuzhiyun 				   unsigned long attrs)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun 	return (dma_addr_t)(page_address(page) + offset);
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
ibmebus_unmap_page(struct device * dev,dma_addr_t dma_addr,size_t size,enum dma_data_direction direction,unsigned long attrs)97*4882a593Smuzhiyun static void ibmebus_unmap_page(struct device *dev,
98*4882a593Smuzhiyun 			       dma_addr_t dma_addr,
99*4882a593Smuzhiyun 			       size_t size,
100*4882a593Smuzhiyun 			       enum dma_data_direction direction,
101*4882a593Smuzhiyun 			       unsigned long attrs)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	return;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
ibmebus_map_sg(struct device * dev,struct scatterlist * sgl,int nents,enum dma_data_direction direction,unsigned long attrs)106*4882a593Smuzhiyun static int ibmebus_map_sg(struct device *dev,
107*4882a593Smuzhiyun 			  struct scatterlist *sgl,
108*4882a593Smuzhiyun 			  int nents, enum dma_data_direction direction,
109*4882a593Smuzhiyun 			  unsigned long attrs)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	struct scatterlist *sg;
112*4882a593Smuzhiyun 	int i;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	for_each_sg(sgl, sg, nents, i) {
115*4882a593Smuzhiyun 		sg->dma_address = (dma_addr_t) sg_virt(sg);
116*4882a593Smuzhiyun 		sg->dma_length = sg->length;
117*4882a593Smuzhiyun 	}
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	return nents;
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun 
ibmebus_unmap_sg(struct device * dev,struct scatterlist * sg,int nents,enum dma_data_direction direction,unsigned long attrs)122*4882a593Smuzhiyun static void ibmebus_unmap_sg(struct device *dev,
123*4882a593Smuzhiyun 			     struct scatterlist *sg,
124*4882a593Smuzhiyun 			     int nents, enum dma_data_direction direction,
125*4882a593Smuzhiyun 			     unsigned long attrs)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	return;
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun 
ibmebus_dma_supported(struct device * dev,u64 mask)130*4882a593Smuzhiyun static int ibmebus_dma_supported(struct device *dev, u64 mask)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun 	return mask == DMA_BIT_MASK(64);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
ibmebus_dma_get_required_mask(struct device * dev)135*4882a593Smuzhiyun static u64 ibmebus_dma_get_required_mask(struct device *dev)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	return DMA_BIT_MASK(64);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun static const struct dma_map_ops ibmebus_dma_ops = {
141*4882a593Smuzhiyun 	.alloc              = ibmebus_alloc_coherent,
142*4882a593Smuzhiyun 	.free               = ibmebus_free_coherent,
143*4882a593Smuzhiyun 	.map_sg             = ibmebus_map_sg,
144*4882a593Smuzhiyun 	.unmap_sg           = ibmebus_unmap_sg,
145*4882a593Smuzhiyun 	.dma_supported      = ibmebus_dma_supported,
146*4882a593Smuzhiyun 	.get_required_mask  = ibmebus_dma_get_required_mask,
147*4882a593Smuzhiyun 	.map_page           = ibmebus_map_page,
148*4882a593Smuzhiyun 	.unmap_page         = ibmebus_unmap_page,
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun 
ibmebus_match_path(struct device * dev,const void * data)151*4882a593Smuzhiyun static int ibmebus_match_path(struct device *dev, const void *data)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun 	struct device_node *dn = to_platform_device(dev)->dev.of_node;
154*4882a593Smuzhiyun 	return (of_find_node_by_path(data) == dn);
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
ibmebus_match_node(struct device * dev,const void * data)157*4882a593Smuzhiyun static int ibmebus_match_node(struct device *dev, const void *data)
158*4882a593Smuzhiyun {
159*4882a593Smuzhiyun 	return to_platform_device(dev)->dev.of_node == data;
160*4882a593Smuzhiyun }
161*4882a593Smuzhiyun 
ibmebus_create_device(struct device_node * dn)162*4882a593Smuzhiyun static int ibmebus_create_device(struct device_node *dn)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun 	struct platform_device *dev;
165*4882a593Smuzhiyun 	int ret;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
168*4882a593Smuzhiyun 	if (!dev)
169*4882a593Smuzhiyun 		return -ENOMEM;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	dev->dev.bus = &ibmebus_bus_type;
172*4882a593Smuzhiyun 	dev->dev.dma_ops = &ibmebus_dma_ops;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	ret = of_device_add(dev);
175*4882a593Smuzhiyun 	if (ret)
176*4882a593Smuzhiyun 		platform_device_put(dev);
177*4882a593Smuzhiyun 	return ret;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun 
ibmebus_create_devices(const struct of_device_id * matches)180*4882a593Smuzhiyun static int ibmebus_create_devices(const struct of_device_id *matches)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	struct device_node *root, *child;
183*4882a593Smuzhiyun 	struct device *dev;
184*4882a593Smuzhiyun 	int ret = 0;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	root = of_find_node_by_path("/");
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	for_each_child_of_node(root, child) {
189*4882a593Smuzhiyun 		if (!of_match_node(matches, child))
190*4882a593Smuzhiyun 			continue;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 		dev = bus_find_device(&ibmebus_bus_type, NULL, child,
193*4882a593Smuzhiyun 				      ibmebus_match_node);
194*4882a593Smuzhiyun 		if (dev) {
195*4882a593Smuzhiyun 			put_device(dev);
196*4882a593Smuzhiyun 			continue;
197*4882a593Smuzhiyun 		}
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 		ret = ibmebus_create_device(child);
200*4882a593Smuzhiyun 		if (ret) {
201*4882a593Smuzhiyun 			printk(KERN_ERR "%s: failed to create device (%i)",
202*4882a593Smuzhiyun 			       __func__, ret);
203*4882a593Smuzhiyun 			of_node_put(child);
204*4882a593Smuzhiyun 			break;
205*4882a593Smuzhiyun 		}
206*4882a593Smuzhiyun 	}
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	of_node_put(root);
209*4882a593Smuzhiyun 	return ret;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
ibmebus_register_driver(struct platform_driver * drv)212*4882a593Smuzhiyun int ibmebus_register_driver(struct platform_driver *drv)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	/* If the driver uses devices that ibmebus doesn't know, add them */
215*4882a593Smuzhiyun 	ibmebus_create_devices(drv->driver.of_match_table);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 	drv->driver.bus = &ibmebus_bus_type;
218*4882a593Smuzhiyun 	return driver_register(&drv->driver);
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun EXPORT_SYMBOL(ibmebus_register_driver);
221*4882a593Smuzhiyun 
ibmebus_unregister_driver(struct platform_driver * drv)222*4882a593Smuzhiyun void ibmebus_unregister_driver(struct platform_driver *drv)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	driver_unregister(&drv->driver);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun EXPORT_SYMBOL(ibmebus_unregister_driver);
227*4882a593Smuzhiyun 
ibmebus_request_irq(u32 ist,irq_handler_t handler,unsigned long irq_flags,const char * devname,void * dev_id)228*4882a593Smuzhiyun int ibmebus_request_irq(u32 ist, irq_handler_t handler,
229*4882a593Smuzhiyun 			unsigned long irq_flags, const char *devname,
230*4882a593Smuzhiyun 			void *dev_id)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun 	unsigned int irq = irq_create_mapping(NULL, ist);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	if (!irq)
235*4882a593Smuzhiyun 		return -EINVAL;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	return request_irq(irq, handler, irq_flags, devname, dev_id);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun EXPORT_SYMBOL(ibmebus_request_irq);
240*4882a593Smuzhiyun 
ibmebus_free_irq(u32 ist,void * dev_id)241*4882a593Smuzhiyun void ibmebus_free_irq(u32 ist, void *dev_id)
242*4882a593Smuzhiyun {
243*4882a593Smuzhiyun 	unsigned int irq = irq_find_mapping(NULL, ist);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	free_irq(irq, dev_id);
246*4882a593Smuzhiyun 	irq_dispose_mapping(irq);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun EXPORT_SYMBOL(ibmebus_free_irq);
249*4882a593Smuzhiyun 
ibmebus_chomp(const char * in,size_t count)250*4882a593Smuzhiyun static char *ibmebus_chomp(const char *in, size_t count)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	char *out = kmalloc(count + 1, GFP_KERNEL);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	if (!out)
255*4882a593Smuzhiyun 		return NULL;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	memcpy(out, in, count);
258*4882a593Smuzhiyun 	out[count] = '\0';
259*4882a593Smuzhiyun 	if (out[count - 1] == '\n')
260*4882a593Smuzhiyun 		out[count - 1] = '\0';
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	return out;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun 
probe_store(struct bus_type * bus,const char * buf,size_t count)265*4882a593Smuzhiyun static ssize_t probe_store(struct bus_type *bus, const char *buf, size_t count)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun 	struct device_node *dn = NULL;
268*4882a593Smuzhiyun 	struct device *dev;
269*4882a593Smuzhiyun 	char *path;
270*4882a593Smuzhiyun 	ssize_t rc = 0;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	path = ibmebus_chomp(buf, count);
273*4882a593Smuzhiyun 	if (!path)
274*4882a593Smuzhiyun 		return -ENOMEM;
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	dev = bus_find_device(&ibmebus_bus_type, NULL, path,
277*4882a593Smuzhiyun 			      ibmebus_match_path);
278*4882a593Smuzhiyun 	if (dev) {
279*4882a593Smuzhiyun 		put_device(dev);
280*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: %s has already been probed\n",
281*4882a593Smuzhiyun 		       __func__, path);
282*4882a593Smuzhiyun 		rc = -EEXIST;
283*4882a593Smuzhiyun 		goto out;
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	if ((dn = of_find_node_by_path(path))) {
287*4882a593Smuzhiyun 		rc = ibmebus_create_device(dn);
288*4882a593Smuzhiyun 		of_node_put(dn);
289*4882a593Smuzhiyun 	} else {
290*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: no such device node: %s\n",
291*4882a593Smuzhiyun 		       __func__, path);
292*4882a593Smuzhiyun 		rc = -ENODEV;
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun out:
296*4882a593Smuzhiyun 	kfree(path);
297*4882a593Smuzhiyun 	if (rc)
298*4882a593Smuzhiyun 		return rc;
299*4882a593Smuzhiyun 	return count;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun static BUS_ATTR_WO(probe);
302*4882a593Smuzhiyun 
remove_store(struct bus_type * bus,const char * buf,size_t count)303*4882a593Smuzhiyun static ssize_t remove_store(struct bus_type *bus, const char *buf, size_t count)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun 	struct device *dev;
306*4882a593Smuzhiyun 	char *path;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	path = ibmebus_chomp(buf, count);
309*4882a593Smuzhiyun 	if (!path)
310*4882a593Smuzhiyun 		return -ENOMEM;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
313*4882a593Smuzhiyun 				   ibmebus_match_path))) {
314*4882a593Smuzhiyun 		of_device_unregister(to_platform_device(dev));
315*4882a593Smuzhiyun 		put_device(dev);
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 		kfree(path);
318*4882a593Smuzhiyun 		return count;
319*4882a593Smuzhiyun 	} else {
320*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: %s not on the bus\n",
321*4882a593Smuzhiyun 		       __func__, path);
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun 		kfree(path);
324*4882a593Smuzhiyun 		return -ENODEV;
325*4882a593Smuzhiyun 	}
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun static BUS_ATTR_WO(remove);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun static struct attribute *ibmbus_bus_attrs[] = {
330*4882a593Smuzhiyun 	&bus_attr_probe.attr,
331*4882a593Smuzhiyun 	&bus_attr_remove.attr,
332*4882a593Smuzhiyun 	NULL,
333*4882a593Smuzhiyun };
334*4882a593Smuzhiyun ATTRIBUTE_GROUPS(ibmbus_bus);
335*4882a593Smuzhiyun 
ibmebus_bus_bus_match(struct device * dev,struct device_driver * drv)336*4882a593Smuzhiyun static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun 	const struct of_device_id *matches = drv->of_match_table;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	if (!matches)
341*4882a593Smuzhiyun 		return 0;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	return of_match_device(matches, dev) != NULL;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
ibmebus_bus_device_probe(struct device * dev)346*4882a593Smuzhiyun static int ibmebus_bus_device_probe(struct device *dev)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun 	int error = -ENODEV;
349*4882a593Smuzhiyun 	struct platform_driver *drv;
350*4882a593Smuzhiyun 	struct platform_device *of_dev;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	drv = to_platform_driver(dev->driver);
353*4882a593Smuzhiyun 	of_dev = to_platform_device(dev);
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	if (!drv->probe)
356*4882a593Smuzhiyun 		return error;
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	of_dev_get(of_dev);
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	if (of_driver_match_device(dev, dev->driver))
361*4882a593Smuzhiyun 		error = drv->probe(of_dev);
362*4882a593Smuzhiyun 	if (error)
363*4882a593Smuzhiyun 		of_dev_put(of_dev);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun 	return error;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
ibmebus_bus_device_remove(struct device * dev)368*4882a593Smuzhiyun static int ibmebus_bus_device_remove(struct device *dev)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun 	struct platform_device *of_dev = to_platform_device(dev);
371*4882a593Smuzhiyun 	struct platform_driver *drv = to_platform_driver(dev->driver);
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	if (dev->driver && drv->remove)
374*4882a593Smuzhiyun 		drv->remove(of_dev);
375*4882a593Smuzhiyun 	return 0;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
ibmebus_bus_device_shutdown(struct device * dev)378*4882a593Smuzhiyun static void ibmebus_bus_device_shutdown(struct device *dev)
379*4882a593Smuzhiyun {
380*4882a593Smuzhiyun 	struct platform_device *of_dev = to_platform_device(dev);
381*4882a593Smuzhiyun 	struct platform_driver *drv = to_platform_driver(dev->driver);
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	if (dev->driver && drv->shutdown)
384*4882a593Smuzhiyun 		drv->shutdown(of_dev);
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun /*
388*4882a593Smuzhiyun  * ibmebus_bus_device_attrs
389*4882a593Smuzhiyun  */
devspec_show(struct device * dev,struct device_attribute * attr,char * buf)390*4882a593Smuzhiyun static ssize_t devspec_show(struct device *dev,
391*4882a593Smuzhiyun 				struct device_attribute *attr, char *buf)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun 	struct platform_device *ofdev;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	ofdev = to_platform_device(dev);
396*4882a593Smuzhiyun 	return sprintf(buf, "%pOF\n", ofdev->dev.of_node);
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun static DEVICE_ATTR_RO(devspec);
399*4882a593Smuzhiyun 
name_show(struct device * dev,struct device_attribute * attr,char * buf)400*4882a593Smuzhiyun static ssize_t name_show(struct device *dev,
401*4882a593Smuzhiyun 				struct device_attribute *attr, char *buf)
402*4882a593Smuzhiyun {
403*4882a593Smuzhiyun 	struct platform_device *ofdev;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	ofdev = to_platform_device(dev);
406*4882a593Smuzhiyun 	return sprintf(buf, "%pOFn\n", ofdev->dev.of_node);
407*4882a593Smuzhiyun }
408*4882a593Smuzhiyun static DEVICE_ATTR_RO(name);
409*4882a593Smuzhiyun 
modalias_show(struct device * dev,struct device_attribute * attr,char * buf)410*4882a593Smuzhiyun static ssize_t modalias_show(struct device *dev,
411*4882a593Smuzhiyun 				struct device_attribute *attr, char *buf)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	return of_device_modalias(dev, buf, PAGE_SIZE);
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun static DEVICE_ATTR_RO(modalias);
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun static struct attribute *ibmebus_bus_device_attrs[] = {
418*4882a593Smuzhiyun 	&dev_attr_devspec.attr,
419*4882a593Smuzhiyun 	&dev_attr_name.attr,
420*4882a593Smuzhiyun 	&dev_attr_modalias.attr,
421*4882a593Smuzhiyun 	NULL,
422*4882a593Smuzhiyun };
423*4882a593Smuzhiyun ATTRIBUTE_GROUPS(ibmebus_bus_device);
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun struct bus_type ibmebus_bus_type = {
426*4882a593Smuzhiyun 	.name      = "ibmebus",
427*4882a593Smuzhiyun 	.uevent    = of_device_uevent_modalias,
428*4882a593Smuzhiyun 	.bus_groups = ibmbus_bus_groups,
429*4882a593Smuzhiyun 	.match     = ibmebus_bus_bus_match,
430*4882a593Smuzhiyun 	.probe     = ibmebus_bus_device_probe,
431*4882a593Smuzhiyun 	.remove    = ibmebus_bus_device_remove,
432*4882a593Smuzhiyun 	.shutdown  = ibmebus_bus_device_shutdown,
433*4882a593Smuzhiyun 	.dev_groups = ibmebus_bus_device_groups,
434*4882a593Smuzhiyun };
435*4882a593Smuzhiyun EXPORT_SYMBOL(ibmebus_bus_type);
436*4882a593Smuzhiyun 
ibmebus_bus_init(void)437*4882a593Smuzhiyun static int __init ibmebus_bus_init(void)
438*4882a593Smuzhiyun {
439*4882a593Smuzhiyun 	int err;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	printk(KERN_INFO "IBM eBus Device Driver\n");
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	err = bus_register(&ibmebus_bus_type);
444*4882a593Smuzhiyun 	if (err) {
445*4882a593Smuzhiyun 		printk(KERN_ERR "%s: failed to register IBM eBus.\n",
446*4882a593Smuzhiyun 		       __func__);
447*4882a593Smuzhiyun 		return err;
448*4882a593Smuzhiyun 	}
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	err = device_register(&ibmebus_bus_device);
451*4882a593Smuzhiyun 	if (err) {
452*4882a593Smuzhiyun 		printk(KERN_WARNING "%s: device_register returned %i\n",
453*4882a593Smuzhiyun 		       __func__, err);
454*4882a593Smuzhiyun 		bus_unregister(&ibmebus_bus_type);
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 		return err;
457*4882a593Smuzhiyun 	}
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 	err = ibmebus_create_devices(ibmebus_matches);
460*4882a593Smuzhiyun 	if (err) {
461*4882a593Smuzhiyun 		device_unregister(&ibmebus_bus_device);
462*4882a593Smuzhiyun 		bus_unregister(&ibmebus_bus_type);
463*4882a593Smuzhiyun 		return err;
464*4882a593Smuzhiyun 	}
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	return 0;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun machine_postcore_initcall(pseries, ibmebus_bus_init);
469