Merge branch 'batman-adv/next' of git://git.open-mesh.org/ecsv/linux-merge
[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
11 MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
12 MODULE_LICENSE("GPL");
13
14 static int bcma_bus_match(struct device *dev, struct device_driver *drv);
15 static int bcma_device_probe(struct device *dev);
16 static int bcma_device_remove(struct device *dev);
17
18 static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
19 {
20         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
21         return sprintf(buf, "0x%03X\n", core->id.manuf);
22 }
23 static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
24 {
25         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
26         return sprintf(buf, "0x%03X\n", core->id.id);
27 }
28 static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
29 {
30         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
31         return sprintf(buf, "0x%02X\n", core->id.rev);
32 }
33 static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
34 {
35         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
36         return sprintf(buf, "0x%X\n", core->id.class);
37 }
38 static struct device_attribute bcma_device_attrs[] = {
39         __ATTR_RO(manuf),
40         __ATTR_RO(id),
41         __ATTR_RO(rev),
42         __ATTR_RO(class),
43         __ATTR_NULL,
44 };
45
46 static struct bus_type bcma_bus_type = {
47         .name           = "bcma",
48         .match          = bcma_bus_match,
49         .probe          = bcma_device_probe,
50         .remove         = bcma_device_remove,
51         .dev_attrs      = bcma_device_attrs,
52 };
53
54 static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
55 {
56         struct bcma_device *core;
57
58         list_for_each_entry(core, &bus->cores, list) {
59                 if (core->id.id == coreid)
60                         return core;
61         }
62         return NULL;
63 }
64
65 static void bcma_release_core_dev(struct device *dev)
66 {
67         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
68         kfree(core);
69 }
70
71 static int bcma_register_cores(struct bcma_bus *bus)
72 {
73         struct bcma_device *core;
74         int err, dev_id = 0;
75
76         list_for_each_entry(core, &bus->cores, list) {
77                 /* We support that cores ourself */
78                 switch (core->id.id) {
79                 case BCMA_CORE_CHIPCOMMON:
80                 case BCMA_CORE_PCI:
81                 case BCMA_CORE_PCIE:
82                         continue;
83                 }
84
85                 core->dev.release = bcma_release_core_dev;
86                 core->dev.bus = &bcma_bus_type;
87                 dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id);
88
89                 switch (bus->hosttype) {
90                 case BCMA_HOSTTYPE_PCI:
91                         core->dev.parent = &bus->host_pci->dev;
92                         core->dma_dev = &bus->host_pci->dev;
93                         core->irq = bus->host_pci->irq;
94                         break;
95                 case BCMA_HOSTTYPE_NONE:
96                 case BCMA_HOSTTYPE_SDIO:
97                         break;
98                 }
99
100                 err = device_register(&core->dev);
101                 if (err) {
102                         pr_err("Could not register dev for core 0x%03X\n",
103                                core->id.id);
104                         continue;
105                 }
106                 core->dev_registered = true;
107                 dev_id++;
108         }
109
110         return 0;
111 }
112
113 static void bcma_unregister_cores(struct bcma_bus *bus)
114 {
115         struct bcma_device *core;
116
117         list_for_each_entry(core, &bus->cores, list) {
118                 if (core->dev_registered)
119                         device_unregister(&core->dev);
120         }
121 }
122
123 int bcma_bus_register(struct bcma_bus *bus)
124 {
125         int err;
126         struct bcma_device *core;
127
128         /* Scan for devices (cores) */
129         err = bcma_bus_scan(bus);
130         if (err) {
131                 pr_err("Failed to scan: %d\n", err);
132                 return -1;
133         }
134
135         /* Init CC core */
136         core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
137         if (core) {
138                 bus->drv_cc.core = core;
139                 bcma_core_chipcommon_init(&bus->drv_cc);
140         }
141
142         /* Init PCIE core */
143         core = bcma_find_core(bus, BCMA_CORE_PCIE);
144         if (core) {
145                 bus->drv_pci.core = core;
146                 bcma_core_pci_init(&bus->drv_pci);
147         }
148
149         /* Try to get SPROM */
150         err = bcma_sprom_get(bus);
151         if (err) {
152                 pr_err("Failed to get SPROM: %d\n", err);
153                 return -ENOENT;
154         }
155
156         /* Register found cores */
157         bcma_register_cores(bus);
158
159         pr_info("Bus registered\n");
160
161         return 0;
162 }
163 EXPORT_SYMBOL_GPL(bcma_bus_register);
164
165 void bcma_bus_unregister(struct bcma_bus *bus)
166 {
167         bcma_unregister_cores(bus);
168 }
169 EXPORT_SYMBOL_GPL(bcma_bus_unregister);
170
171 int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
172 {
173         drv->drv.name = drv->name;
174         drv->drv.bus = &bcma_bus_type;
175         drv->drv.owner = owner;
176
177         return driver_register(&drv->drv);
178 }
179 EXPORT_SYMBOL_GPL(__bcma_driver_register);
180
181 void bcma_driver_unregister(struct bcma_driver *drv)
182 {
183         driver_unregister(&drv->drv);
184 }
185 EXPORT_SYMBOL_GPL(bcma_driver_unregister);
186
187 static int bcma_bus_match(struct device *dev, struct device_driver *drv)
188 {
189         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
190         struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
191         const struct bcma_device_id *cid = &core->id;
192         const struct bcma_device_id *did;
193
194         for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
195             if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
196                 (did->id == cid->id || did->id == BCMA_ANY_ID) &&
197                 (did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
198                 (did->class == cid->class || did->class == BCMA_ANY_CLASS))
199                         return 1;
200         }
201         return 0;
202 }
203
204 static int bcma_device_probe(struct device *dev)
205 {
206         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
207         struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
208                                                drv);
209         int err = 0;
210
211         if (adrv->probe)
212                 err = adrv->probe(core);
213
214         return err;
215 }
216
217 static int bcma_device_remove(struct device *dev)
218 {
219         struct bcma_device *core = container_of(dev, struct bcma_device, dev);
220         struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
221                                                drv);
222
223         if (adrv->remove)
224                 adrv->remove(core);
225
226         return 0;
227 }
228
229 static int __init bcma_modinit(void)
230 {
231         int err;
232
233         err = bus_register(&bcma_bus_type);
234         if (err)
235                 return err;
236
237 #ifdef CONFIG_BCMA_HOST_PCI
238         err = bcma_host_pci_init();
239         if (err) {
240                 pr_err("PCI host initialization failed\n");
241                 err = 0;
242         }
243 #endif
244
245         return err;
246 }
247 fs_initcall(bcma_modinit);
248
249 static void __exit bcma_modexit(void)
250 {
251 #ifdef CONFIG_BCMA_HOST_PCI
252         bcma_host_pci_exit();
253 #endif
254         bus_unregister(&bcma_bus_type);
255 }
256 module_exit(bcma_modexit)