Merge branch 'next' of git://git.infradead.org/users/vkoul/slave-dma
[pandora-kernel.git] / drivers / bcma / main.c
1 /*
2  * Broadcom specific AMBA
3  * Bus subsystem
4  *
5  * Licensed under the GNU/GPL. See COPYING for details.
6  */
7
8 #include "bcma_private.h"
9 #include <linux/bcma/bcma.h>
10 #include <linux/slab.h>
11
12 MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
13 MODULE_LICENSE("GPL");
14
15 static int bcma_bus_match(struct device *dev, struct device_driver *drv);
16 static int bcma_device_probe(struct device *dev);
17 static int bcma_device_remove(struct device *dev);
18 static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env);
19
20 static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
21 {
22         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
23         return sprintf(buf, "0x%03X\n", core->id.manuf);
24 }
25 static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
26 {
27         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
28         return sprintf(buf, "0x%03X\n", core->id.id);
29 }
30 static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
31 {
32         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
33         return sprintf(buf, "0x%02X\n", core->id.rev);
34 }
35 static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
36 {
37         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
38         return sprintf(buf, "0x%X\n", core->id.class);
39 }
40 static struct device_attribute bcma_device_attrs[] = {
41         __ATTR_RO(manuf),
42         __ATTR_RO(id),
43         __ATTR_RO(rev),
44         __ATTR_RO(class),
45         __ATTR_NULL,
46 };
47
48 static struct bus_type bcma_bus_type = {
49         .name           = "bcma",
50         .match          = bcma_bus_match,
51         .probe          = bcma_device_probe,
52         .remove         = bcma_device_remove,
53         .uevent         = bcma_device_uevent,
54         .dev_attrs      = bcma_device_attrs,
55 };
56
57 static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
58 {
59         struct bcma_device *core;
60
61         list_for_each_entry(core, &bus->cores, list) {
62                 if (core->id.id == coreid)
63                         return core;
64         }
65         return NULL;
66 }
67
68 static void bcma_release_core_dev(struct device *dev)
69 {
70         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
71         if (core->io_addr)
72                 iounmap(core->io_addr);
73         if (core->io_wrap)
74                 iounmap(core->io_wrap);
75         kfree(core);
76 }
77
78 static int bcma_register_cores(struct bcma_bus *bus)
79 {
80         struct bcma_device *core;
81         int err, dev_id = 0;
82
83         list_for_each_entry(core, &bus->cores, list) {
84                 /* We support that cores ourself */
85                 switch (core->id.id) {
86                 case BCMA_CORE_CHIPCOMMON:
87                 case BCMA_CORE_PCI:
88                 case BCMA_CORE_PCIE:
89                 case BCMA_CORE_MIPS_74K:
90                         continue;
91                 }
92
93                 core->dev.release = bcma_release_core_dev;
94                 core->dev.bus = &bcma_bus_type;
95                 dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
96
97                 switch (bus->hosttype) {
98                 case BCMA_HOSTTYPE_PCI:
99                         core->dev.parent = &bus->host_pci->dev;
100                         core->dma_dev = &bus->host_pci->dev;
101                         core->irq = bus->host_pci->irq;
102                         break;
103                 case BCMA_HOSTTYPE_SOC:
104                         core->dev.dma_mask = &core->dev.coherent_dma_mask;
105                         core->dma_dev = &core->dev;
106                         break;
107                 case BCMA_HOSTTYPE_SDIO:
108                         break;
109                 }
110
111                 err = device_register(&core->dev);
112                 if (err) {
113                         pr_err("Could not register dev for core 0x%03X\n",
114                                core->id.id);
115                         continue;
116                 }
117                 core->dev_registered = true;
118                 dev_id++;
119         }
120
121         return 0;
122 }
123
124 static void bcma_unregister_cores(struct bcma_bus *bus)
125 {
126         struct bcma_device *core;
127
128         list_for_each_entry(core, &bus->cores, list) {
129                 if (core->dev_registered)
130                         device_unregister(&core->dev);
131         }
132 }
133
134 int bcma_bus_register(struct bcma_bus *bus)
135 {
136         int err;
137         struct bcma_device *core;
138
139         /* Scan for devices (cores) */
140         err = bcma_bus_scan(bus);
141         if (err) {
142                 pr_err("Failed to scan: %d\n", err);
143                 return -1;
144         }
145
146         /* Init CC core */
147         core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
148         if (core) {
149                 bus->drv_cc.core = core;
150                 bcma_core_chipcommon_init(&bus->drv_cc);
151         }
152
153         /* Init MIPS core */
154         core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
155         if (core) {
156                 bus->drv_mips.core = core;
157                 bcma_core_mips_init(&bus->drv_mips);
158         }
159
160         /* Init PCIE core */
161         core = bcma_find_core(bus, BCMA_CORE_PCIE);
162         if (core) {
163                 bus->drv_pci.core = core;
164                 bcma_core_pci_init(&bus->drv_pci);
165         }
166
167         /* Try to get SPROM */
168         err = bcma_sprom_get(bus);
169         if (err == -ENOENT) {
170                 pr_err("No SPROM available\n");
171         } else if (err) {
172                 pr_err("Failed to get SPROM: %d\n", err);
173                 return -ENOENT;
174         }
175
176         /* Register found cores */
177         bcma_register_cores(bus);
178
179         pr_info("Bus registered\n");
180
181         return 0;
182 }
183
184 void bcma_bus_unregister(struct bcma_bus *bus)
185 {
186         bcma_unregister_cores(bus);
187 }
188
189 int __init bcma_bus_early_register(struct bcma_bus *bus,
190                                    struct bcma_device *core_cc,
191                                    struct bcma_device *core_mips)
192 {
193         int err;
194         struct bcma_device *core;
195         struct bcma_device_id match;
196
197         bcma_init_bus(bus);
198
199         match.manuf = BCMA_MANUF_BCM;
200         match.id = BCMA_CORE_CHIPCOMMON;
201         match.class = BCMA_CL_SIM;
202         match.rev = BCMA_ANY_REV;
203
204         /* Scan for chip common core */
205         err = bcma_bus_scan_early(bus, &match, core_cc);
206         if (err) {
207                 pr_err("Failed to scan for common core: %d\n", err);
208                 return -1;
209         }
210
211         match.manuf = BCMA_MANUF_MIPS;
212         match.id = BCMA_CORE_MIPS_74K;
213         match.class = BCMA_CL_SIM;
214         match.rev = BCMA_ANY_REV;
215
216         /* Scan for mips core */
217         err = bcma_bus_scan_early(bus, &match, core_mips);
218         if (err) {
219                 pr_err("Failed to scan for mips core: %d\n", err);
220                 return -1;
221         }
222
223         /* Init CC core */
224         core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
225         if (core) {
226                 bus->drv_cc.core = core;
227                 bcma_core_chipcommon_init(&bus->drv_cc);
228         }
229
230         /* Init MIPS core */
231         core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
232         if (core) {
233                 bus->drv_mips.core = core;
234                 bcma_core_mips_init(&bus->drv_mips);
235         }
236
237         pr_info("Early bus registered\n");
238
239         return 0;
240 }
241
242 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
243 {
244         drv->drv.name = drv->name;
245         drv->drv.bus = &bcma_bus_type;
246         drv->drv.owner = owner;
247
248         return driver_register(&drv->drv);
249 }
250 EXPORT_SYMBOL_GPL(__bcma_driver_register);
251
252 void bcma_driver_unregister(struct bcma_driver *drv)
253 {
254         driver_unregister(&drv->drv);
255 }
256 EXPORT_SYMBOL_GPL(bcma_driver_unregister);
257
258 static int bcma_bus_match(struct device *dev, struct device_driver *drv)
259 {
260         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
261         struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
262         const struct bcma_device_id *cid = &core->id;
263         const struct bcma_device_id *did;
264
265         for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
266             if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
267                 (did->id == cid->id || did->id == BCMA_ANY_ID) &&
268                 (did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
269                 (did->class == cid->class || did->class == BCMA_ANY_CLASS))
270                         return 1;
271         }
272         return 0;
273 }
274
275 static int bcma_device_probe(struct device *dev)
276 {
277         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
278         struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
279                                                drv);
280         int err = 0;
281
282         if (adrv->probe)
283                 err = adrv->probe(core);
284
285         return err;
286 }
287
288 static int bcma_device_remove(struct device *dev)
289 {
290         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
291         struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
292                                                drv);
293
294         if (adrv->remove)
295                 adrv->remove(core);
296
297         return 0;
298 }
299
300 static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
301 {
302         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
303
304         return add_uevent_var(env,
305                               "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
306                               core->id.manuf, core->id.id,
307                               core->id.rev, core->id.class);
308 }
309
310 static int __init bcma_modinit(void)
311 {
312         int err;
313
314         err = bus_register(&bcma_bus_type);
315         if (err)
316                 return err;
317
318 #ifdef CONFIG_BCMA_HOST_PCI
319         err = bcma_host_pci_init();
320         if (err) {
321                 pr_err("PCI host initialization failed\n");
322                 err = 0;
323         }
324 #endif
325
326         return err;
327 }
328 fs_initcall(bcma_modinit);
329
330 static void __exit bcma_modexit(void)
331 {
332 #ifdef CONFIG_BCMA_HOST_PCI
333         bcma_host_pci_exit();
334 #endif
335         bus_unregister(&bcma_bus_type);
336 }
337 module_exit(bcma_modexit)