Line data Source code
1 : /*
2 : * linux/drivers/mmc/core/sdio_bus.c
3 : *
4 : * Copyright 2007 Pierre Ossman
5 : *
6 : * This program is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU General Public License as published by
8 : * the Free Software Foundation; either version 2 of the License, or (at
9 : * your option) any later version.
10 : *
11 : * SDIO function driver model
12 : */
13 :
14 : #include <linux/device.h>
15 : #include <linux/err.h>
16 :
17 : #include <linux/mmc/card.h>
18 : #include <linux/mmc/sdio_func.h>
19 :
20 : #include "sdio_cis.h"
21 : #include "sdio_bus.h"
22 :
23 : /* show configuration fields */
24 : #define sdio_config_attr(field, format_string) \
25 : static ssize_t \
26 : field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
27 : { \
28 : struct sdio_func *func; \
29 : \
30 : func = dev_to_sdio_func (dev); \
31 : return sprintf (buf, format_string, func->field); \
32 : }
33 :
34 5 : sdio_config_attr(class, "0x%02x\n");
35 20 : sdio_config_attr(vendor, "0x%04x\n");
36 6 : sdio_config_attr(device, "0x%04x\n");
37 5 :
38 6 : static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
39 5 : {
40 3 : struct sdio_func *func = dev_to_sdio_func (dev);
41 1 :
42 6 : return sprintf(buf, "sdio:c%02Xv%04Xd%04X\n",
43 1 : func->class, func->vendor, func->device);
44 : }
45 :
46 1 : static struct device_attribute sdio_dev_attrs[] = {
47 : __ATTR_RO(class),
48 : __ATTR_RO(vendor),
49 : __ATTR_RO(device),
50 : __ATTR_RO(modalias),
51 : __ATTR_NULL,
52 : };
53 :
54 : static const struct sdio_device_id *sdio_match_one(struct sdio_func *func,
55 : const struct sdio_device_id *id)
56 : {
57 168 : if (id->class != (__u8)SDIO_ANY_ID && id->class != func->class)
58 24 : return NULL;
59 168 : if (id->vendor != (__u16)SDIO_ANY_ID && id->vendor != func->vendor)
60 24 : return NULL;
61 168 : if (id->device != (__u16)SDIO_ANY_ID && id->device != func->device)
62 24 : return NULL;
63 24 : return id;
64 : }
65 :
66 : static const struct sdio_device_id *sdio_match_device(struct sdio_func *func,
67 : struct sdio_driver *sdrv)
68 24 : {
69 24 : const struct sdio_device_id *ids;
70 :
71 24 : ids = sdrv->id_table;
72 :
73 48 : if (ids) {
74 72 : while (ids->class || ids->vendor || ids->device) {
75 120 : if (sdio_match_one(func, ids))
76 48 : return ids;
77 24 : ids++;
78 24 : }
79 : }
80 :
81 48 : return NULL;
82 : }
83 :
84 : static int sdio_bus_match(struct device *dev, struct device_driver *drv)
85 : {
86 36 : struct sdio_func *func = dev_to_sdio_func(dev);
87 36 : struct sdio_driver *sdrv = to_sdio_driver(drv);
88 12 :
89 84 : if (sdio_match_device(func, sdrv))
90 24 : return 1;
91 :
92 12 : return 0;
93 : }
94 :
95 : static int
96 : sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
97 : {
98 51 : struct sdio_func *func = dev_to_sdio_func(dev);
99 17 :
100 102 : if (add_uevent_var(env,
101 17 : "SDIO_CLASS=%02X", func->class))
102 34 : return -ENOMEM;
103 :
104 102 : if (add_uevent_var(env,
105 : "SDIO_ID=%04X:%04X", func->vendor, func->device))
106 17 : return -ENOMEM;
107 :
108 119 : if (add_uevent_var(env,
109 : "MODALIAS=sdio:c%02Xv%04Xd%04X",
110 : func->class, func->vendor, func->device))
111 17 : return -ENOMEM;
112 :
113 17 : return 0;
114 : }
115 :
116 : static int sdio_bus_probe(struct device *dev)
117 : {
118 48 : struct sdio_driver *drv = to_sdio_driver(dev->driver);
119 36 : struct sdio_func *func = dev_to_sdio_func(dev);
120 12 : const struct sdio_device_id *id;
121 12 : int ret;
122 12 :
123 60 : id = sdio_match_device(func, drv);
124 36 : if (!id)
125 12 : return -ENODEV;
126 :
127 : /* Set the default block size so the driver is sure it's something
128 : * sensible. */
129 24 : sdio_claim_host(func);
130 48 : ret = sdio_set_block_size(func, 0);
131 24 : sdio_release_host(func);
132 24 : if (ret)
133 12 : return ret;
134 :
135 24 : return drv->probe(func, id);
136 : }
137 :
138 : static int sdio_bus_remove(struct device *dev)
139 : {
140 48 : struct sdio_driver *drv = to_sdio_driver(dev->driver);
141 36 : struct sdio_func *func = dev_to_sdio_func(dev);
142 12 :
143 24 : drv->remove(func);
144 :
145 36 : if (func->irq_handler) {
146 12 : printk(KERN_WARNING "WARNING: driver %s did not remove "
147 : "its interrupt handler!\n", drv->name);
148 24 : sdio_claim_host(func);
149 36 : sdio_release_irq(func);
150 24 : sdio_release_host(func);
151 : }
152 :
153 24 : return 0;
154 : }
155 :
156 1 : static struct bus_type sdio_bus_type = {
157 : .name = "sdio",
158 : .dev_attrs = sdio_dev_attrs,
159 : .match = sdio_bus_match,
160 : .uevent = sdio_bus_uevent,
161 : .probe = sdio_bus_probe,
162 : .remove = sdio_bus_remove,
163 : };
164 :
165 : int sdio_register_bus(void)
166 : {
167 3 : return bus_register(&sdio_bus_type);
168 : }
169 :
170 : void sdio_unregister_bus(void)
171 : {
172 2 : bus_unregister(&sdio_bus_type);
173 2 : }
174 :
175 : /**
176 : * sdio_register_driver - register a function driver
177 : * @drv: SDIO function driver
178 : */
179 : int sdio_register_driver(struct sdio_driver *drv)
180 : {
181 0 : drv->drv.name = drv->name;
182 0 : drv->drv.bus = &sdio_bus_type;
183 0 : return driver_register(&drv->drv);
184 : }
185 : EXPORT_SYMBOL_GPL(sdio_register_driver);
186 :
187 : /**
188 : * sdio_unregister_driver - unregister a function driver
189 : * @drv: SDIO function driver
190 : */
191 : void sdio_unregister_driver(struct sdio_driver *drv)
192 : {
193 0 : drv->drv.bus = &sdio_bus_type;
194 0 : driver_unregister(&drv->drv);
195 0 : }
196 : EXPORT_SYMBOL_GPL(sdio_unregister_driver);
197 :
198 : static void sdio_release_func(struct device *dev)
199 : {
200 0 : struct sdio_func *func = dev_to_sdio_func(dev);
201 0 :
202 0 : sdio_free_func_cis(func);
203 :
204 0 : if (func->info)
205 0 : kfree(func->info);
206 :
207 0 : kfree(func);
208 0 : }
209 :
210 : /*
211 : * Allocate and initialise a new SDIO function structure.
212 : */
213 : struct sdio_func *sdio_alloc_func(struct mmc_card *card)
214 : {
215 0 : struct sdio_func *func;
216 0 :
217 0 : func = kzalloc(sizeof(struct sdio_func), GFP_KERNEL);
218 0 : if (!func)
219 0 : return ERR_PTR(-ENOMEM);
220 :
221 0 : func->card = card;
222 :
223 0 : device_initialize(&func->dev);
224 :
225 0 : func->dev.parent = &card->dev;
226 0 : func->dev.bus = &sdio_bus_type;
227 0 : func->dev.release = sdio_release_func;
228 :
229 0 : return func;
230 : }
231 :
232 : /*
233 : * Register a new SDIO function with the driver model.
234 : */
235 : int sdio_add_func(struct sdio_func *func)
236 : {
237 0 : int ret;
238 0 :
239 0 : dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
240 :
241 0 : ret = device_add(&func->dev);
242 0 : if (ret == 0)
243 0 : sdio_func_set_present(func);
244 :
245 0 : return ret;
246 : }
247 :
248 : /*
249 : * Unregister a SDIO function with the driver model, and
250 : * (eventually) free it.
251 : * This function can be called through error paths where sdio_add_func() was
252 : * never executed (because a failure occurred at an earlier point).
253 : */
254 : void sdio_remove_func(struct sdio_func *func)
255 : {
256 4 : if (!sdio_func_present(func))
257 2 : return;
258 :
259 2 : device_del(&func->dev);
260 2 : put_device(&func->dev);
261 2 : }
262 :
|