Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/bcma/main.c
15109 views
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
break;
93
case BCMA_HOSTTYPE_NONE:
94
case BCMA_HOSTTYPE_SDIO:
95
break;
96
}
97
98
err = device_register(&core->dev);
99
if (err) {
100
pr_err("Could not register dev for core 0x%03X\n",
101
core->id.id);
102
continue;
103
}
104
core->dev_registered = true;
105
dev_id++;
106
}
107
108
return 0;
109
}
110
111
static void bcma_unregister_cores(struct bcma_bus *bus)
112
{
113
struct bcma_device *core;
114
115
list_for_each_entry(core, &bus->cores, list) {
116
if (core->dev_registered)
117
device_unregister(&core->dev);
118
}
119
}
120
121
int bcma_bus_register(struct bcma_bus *bus)
122
{
123
int err;
124
struct bcma_device *core;
125
126
/* Scan for devices (cores) */
127
err = bcma_bus_scan(bus);
128
if (err) {
129
pr_err("Failed to scan: %d\n", err);
130
return -1;
131
}
132
133
/* Init CC core */
134
core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
135
if (core) {
136
bus->drv_cc.core = core;
137
bcma_core_chipcommon_init(&bus->drv_cc);
138
}
139
140
/* Init PCIE core */
141
core = bcma_find_core(bus, BCMA_CORE_PCIE);
142
if (core) {
143
bus->drv_pci.core = core;
144
bcma_core_pci_init(&bus->drv_pci);
145
}
146
147
/* Register found cores */
148
bcma_register_cores(bus);
149
150
pr_info("Bus registered\n");
151
152
return 0;
153
}
154
EXPORT_SYMBOL_GPL(bcma_bus_register);
155
156
void bcma_bus_unregister(struct bcma_bus *bus)
157
{
158
bcma_unregister_cores(bus);
159
}
160
EXPORT_SYMBOL_GPL(bcma_bus_unregister);
161
162
int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
163
{
164
drv->drv.name = drv->name;
165
drv->drv.bus = &bcma_bus_type;
166
drv->drv.owner = owner;
167
168
return driver_register(&drv->drv);
169
}
170
EXPORT_SYMBOL_GPL(__bcma_driver_register);
171
172
void bcma_driver_unregister(struct bcma_driver *drv)
173
{
174
driver_unregister(&drv->drv);
175
}
176
EXPORT_SYMBOL_GPL(bcma_driver_unregister);
177
178
static int bcma_bus_match(struct device *dev, struct device_driver *drv)
179
{
180
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
181
struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
182
const struct bcma_device_id *cid = &core->id;
183
const struct bcma_device_id *did;
184
185
for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
186
if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
187
(did->id == cid->id || did->id == BCMA_ANY_ID) &&
188
(did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
189
(did->class == cid->class || did->class == BCMA_ANY_CLASS))
190
return 1;
191
}
192
return 0;
193
}
194
195
static int bcma_device_probe(struct device *dev)
196
{
197
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
198
struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
199
drv);
200
int err = 0;
201
202
if (adrv->probe)
203
err = adrv->probe(core);
204
205
return err;
206
}
207
208
static int bcma_device_remove(struct device *dev)
209
{
210
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
211
struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
212
drv);
213
214
if (adrv->remove)
215
adrv->remove(core);
216
217
return 0;
218
}
219
220
static int __init bcma_modinit(void)
221
{
222
int err;
223
224
err = bus_register(&bcma_bus_type);
225
if (err)
226
return err;
227
228
#ifdef CONFIG_BCMA_HOST_PCI
229
err = bcma_host_pci_init();
230
if (err) {
231
pr_err("PCI host initialization failed\n");
232
err = 0;
233
}
234
#endif
235
236
return err;
237
}
238
fs_initcall(bcma_modinit);
239
240
static void __exit bcma_modexit(void)
241
{
242
#ifdef CONFIG_BCMA_HOST_PCI
243
bcma_host_pci_exit();
244
#endif
245
bus_unregister(&bcma_bus_type);
246
}
247
module_exit(bcma_modexit)
248
249