be623856f288cbb92e6cad85441639afc7ef4f8d
[safe/jmp/linux-2.6] / drivers / mmc / core / sdio.c
1 /*
2  *  linux/drivers/mmc/sdio.c
3  *
4  *  Copyright 2006-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
12 #include <linux/err.h>
13
14 #include <linux/mmc/host.h>
15 #include <linux/mmc/card.h>
16 #include <linux/mmc/sdio.h>
17 #include <linux/mmc/sdio_func.h>
18
19 #include "core.h"
20 #include "bus.h"
21 #include "sdio_bus.h"
22 #include "mmc_ops.h"
23 #include "sd_ops.h"
24 #include "sdio_ops.h"
25
26 static int sdio_read_fbr(struct sdio_func *func)
27 {
28         int ret;
29         unsigned char data;
30
31         ret = mmc_io_rw_direct(func->card, 0, 0,
32                 func->num * 0x100 + SDIO_FBR_STD_IF, 0, &data);
33         if (ret)
34                 goto out;
35
36         data &= 0x0f;
37
38         if (data == 0x0f) {
39                 ret = mmc_io_rw_direct(func->card, 0, 0,
40                         func->num * 0x100 + SDIO_FBR_STD_IF_EXT, 0, &data);
41                 if (ret)
42                         goto out;
43         }
44
45         func->class = data;
46
47 out:
48         return ret;
49 }
50
51 static int sdio_init_func(struct mmc_card *card, unsigned int fn)
52 {
53         int ret;
54         struct sdio_func *func;
55
56         BUG_ON(fn > SDIO_MAX_FUNCS);
57
58         func = sdio_alloc_func(card);
59         if (IS_ERR(func))
60                 return PTR_ERR(func);
61
62         func->num = fn;
63
64         ret = sdio_read_fbr(func);
65         if (ret)
66                 goto fail;
67
68         card->sdio_func[fn - 1] = func;
69
70         return 0;
71
72 fail:
73         /*
74          * It is okay to remove the function here even though we hold
75          * the host lock as we haven't registered the device yet.
76          */
77         sdio_remove_func(func);
78         return ret;
79 }
80
81 static int sdio_read_cccr(struct mmc_card *card)
82 {
83         int ret;
84         int cccr_vsn;
85         unsigned char data;
86
87         memset(&card->cccr, 0, sizeof(struct sdio_cccr));
88
89         ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CCCR, 0, &data);
90         if (ret)
91                 goto out;
92
93         cccr_vsn = data & 0x0f;
94
95         if (cccr_vsn > SDIO_CCCR_REV_1_20) {
96                 printk(KERN_ERR "%s: unrecognised CCCR structure version %d\n",
97                         mmc_hostname(card->host), cccr_vsn);
98                 return -EINVAL;
99         }
100
101         card->cccr.sdio_vsn = (data & 0xf0) >> 4;
102
103         ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CAPS, 0, &data);
104         if (ret)
105                 goto out;
106
107         if (data & SDIO_CCCR_CAP_SMB)
108                 card->cccr.multi_block = 1;
109         if (data & SDIO_CCCR_CAP_LSC)
110                 card->cccr.low_speed = 1;
111         if (data & SDIO_CCCR_CAP_4BLS)
112                 card->cccr.wide_bus = 1;
113
114         if (cccr_vsn >= SDIO_CCCR_REV_1_10) {
115                 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_POWER, 0, &data);
116                 if (ret)
117                         goto out;
118
119                 if (data & SDIO_POWER_SMPC)
120                         card->cccr.high_power = 1;
121         }
122
123         if (cccr_vsn >= SDIO_CCCR_REV_1_20) {
124                 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &data);
125                 if (ret)
126                         goto out;
127
128                 if (data & SDIO_SPEED_SHS)
129                         card->cccr.high_speed = 1;
130         }
131
132 out:
133         return ret;
134 }
135
136 /*
137  * Host is being removed. Free up the current card.
138  */
139 static void mmc_sdio_remove(struct mmc_host *host)
140 {
141         int i;
142
143         BUG_ON(!host);
144         BUG_ON(!host->card);
145
146         for (i = 0;i < host->card->sdio_funcs;i++) {
147                 if (host->card->sdio_func[i]) {
148                         sdio_remove_func(host->card->sdio_func[i]);
149                         host->card->sdio_func[i] = NULL;
150                 }
151         }
152
153         mmc_remove_card(host->card);
154         host->card = NULL;
155 }
156
157 /*
158  * Card detection callback from host.
159  */
160 static void mmc_sdio_detect(struct mmc_host *host)
161 {
162         int err;
163
164         BUG_ON(!host);
165         BUG_ON(!host->card);
166
167         mmc_claim_host(host);
168
169         /*
170          * Just check if our card has been removed.
171          */
172         err = mmc_select_card(host->card);
173
174         mmc_release_host(host);
175
176         if (err) {
177                 mmc_sdio_remove(host);
178
179                 mmc_claim_host(host);
180                 mmc_detach_bus(host);
181                 mmc_release_host(host);
182         }
183 }
184
185
186 static const struct mmc_bus_ops mmc_sdio_ops = {
187         .remove = mmc_sdio_remove,
188         .detect = mmc_sdio_detect,
189 };
190
191
192 /*
193  * Starting point for SDIO card init.
194  */
195 int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
196 {
197         int err;
198         int i, funcs;
199         struct mmc_card *card;
200
201         BUG_ON(!host);
202         BUG_ON(!host->claimed);
203
204         mmc_attach_bus(host, &mmc_sdio_ops);
205
206         /*
207          * Sanity check the voltages that the card claims to
208          * support.
209          */
210         if (ocr & 0x7F) {
211                 printk(KERN_WARNING "%s: card claims to support voltages "
212                        "below the defined range. These will be ignored.\n",
213                        mmc_hostname(host));
214                 ocr &= ~0x7F;
215         }
216
217         if (ocr & MMC_VDD_165_195) {
218                 printk(KERN_WARNING "%s: SDIO card claims to support the "
219                        "incompletely defined 'low voltage range'. This "
220                        "will be ignored.\n", mmc_hostname(host));
221                 ocr &= ~MMC_VDD_165_195;
222         }
223
224         host->ocr = mmc_select_voltage(host, ocr);
225
226         /*
227          * Can we support the voltage(s) of the card(s)?
228          */
229         if (!host->ocr) {
230                 err = -EINVAL;
231                 goto err;
232         }
233
234         /*
235          * Inform the card of the voltage
236          */
237         err = mmc_send_io_op_cond(host, host->ocr, &ocr);
238         if (err)
239                 goto err;
240
241         /*
242          * The number of functions on the card is encoded inside
243          * the ocr.
244          */
245         funcs = (ocr & 0x70000000) >> 28;
246
247         /*
248          * Allocate card structure.
249          */
250         card = mmc_alloc_card(host);
251         if (IS_ERR(card)) {
252                 err = PTR_ERR(card);
253                 goto err;
254         }
255
256         card->type = MMC_TYPE_SDIO;
257         card->sdio_funcs = funcs;
258
259         host->card = card;
260
261         /*
262          * Set card RCA.
263          */
264         err = mmc_send_relative_addr(host, &card->rca);
265         if (err)
266                 goto remove;
267
268         mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
269
270         /*
271          * Select card, as all following commands rely on that.
272          */
273         err = mmc_select_card(card);
274         if (err)
275                 goto remove;
276
277         /*
278          * Read the common registers.
279          */
280         err = sdio_read_cccr(card);
281         if (err)
282                 goto remove;
283
284         /*
285          * Initialize (but don't add) all present functions.
286          */
287         for (i = 0;i < funcs;i++) {
288                 err = sdio_init_func(host->card, i + 1);
289                 if (err)
290                         goto remove;
291         }
292
293         mmc_release_host(host);
294
295         /*
296          * First add the card to the driver model...
297          */
298         err = mmc_add_card(host->card);
299         if (err)
300                 goto remove_added;
301
302         /*
303          * ...then the SDIO functions.
304          */
305         for (i = 0;i < funcs;i++) {
306                 err = sdio_add_func(host->card->sdio_func[i]);
307                 if (err)
308                         goto remove_added;
309         }
310
311         return 0;
312
313
314 remove_added:
315         /* Remove without lock if the device has been added. */
316         mmc_sdio_remove(host);
317         mmc_claim_host(host);
318 remove:
319         /* And with lock if it hasn't been added. */
320         if (host->card)
321                 mmc_sdio_remove(host);
322 err:
323         mmc_detach_bus(host);
324         mmc_release_host(host);
325
326         printk(KERN_ERR "%s: error %d whilst initialising SDIO card\n",
327                 mmc_hostname(host), err);
328
329         return err;
330 }
331