]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/mmc/core/sdio_cis.c
Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
[mv-sheeva.git] / drivers / mmc / core / sdio_cis.c
1 /*
2  * linux/drivers/mmc/core/sdio_cis.c
3  *
4  * Author:      Nicolas Pitre
5  * Created:     June 11, 2007
6  * Copyright:   MontaVista Software Inc.
7  *
8  * Copyright 2007 Pierre Ossman
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or (at
13  * your option) any later version.
14  */
15
16 #include <linux/kernel.h>
17
18 #include <linux/mmc/host.h>
19 #include <linux/mmc/card.h>
20 #include <linux/mmc/sdio.h>
21 #include <linux/mmc/sdio_func.h>
22
23 #include "sdio_cis.h"
24 #include "sdio_ops.h"
25
26 static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func,
27                          const unsigned char *buf, unsigned size)
28 {
29         unsigned i, nr_strings;
30         char **buffer, *string;
31
32         buf += 2;
33         size -= 2;
34
35         nr_strings = 0;
36         for (i = 0; i < size; i++) {
37                 if (buf[i] == 0xff)
38                         break;
39                 if (buf[i] == 0)
40                         nr_strings++;
41         }
42
43         if (nr_strings < 4) {
44                 printk(KERN_WARNING "SDIO: ignoring broken CISTPL_VERS_1\n");
45                 return 0;
46         }
47
48         size = i;
49
50         buffer = kzalloc(sizeof(char*) * nr_strings + size, GFP_KERNEL);
51         if (!buffer)
52                 return -ENOMEM;
53
54         string = (char*)(buffer + nr_strings);
55
56         for (i = 0; i < nr_strings; i++) {
57                 buffer[i] = string;
58                 strcpy(string, buf);
59                 string += strlen(string) + 1;
60                 buf += strlen(buf) + 1;
61         }
62
63         if (func) {
64                 func->num_info = nr_strings;
65                 func->info = (const char**)buffer;
66         } else {
67                 card->num_info = nr_strings;
68                 card->info = (const char**)buffer;
69         }
70
71         return 0;
72 }
73
74 static int cistpl_manfid(struct mmc_card *card, struct sdio_func *func,
75                          const unsigned char *buf, unsigned size)
76 {
77         unsigned int vendor, device;
78
79         /* TPLMID_MANF */
80         vendor = buf[0] | (buf[1] << 8);
81
82         /* TPLMID_CARD */
83         device = buf[2] | (buf[3] << 8);
84
85         if (func) {
86                 func->vendor = vendor;
87                 func->device = device;
88         } else {
89                 card->cis.vendor = vendor;
90                 card->cis.device = device;
91         }
92
93         return 0;
94 }
95
96 static const unsigned char speed_val[16] =
97         { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 };
98 static const unsigned int speed_unit[8] =
99         { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 };
100
101 /* FUNCE tuples with these types get passed to SDIO drivers */
102 static const unsigned char funce_type_whitelist[] = {
103         4 /* CISTPL_FUNCE_LAN_NODE_ID used in Broadcom cards */
104 };
105
106 static int cistpl_funce_whitelisted(unsigned char type)
107 {
108         int i;
109
110         for (i = 0; i < ARRAY_SIZE(funce_type_whitelist); i++) {
111                 if (funce_type_whitelist[i] == type)
112                         return 1;
113         }
114         return 0;
115 }
116
117 static int cistpl_funce_common(struct mmc_card *card,
118                                const unsigned char *buf, unsigned size)
119 {
120         if (size < 0x04 || buf[0] != 0)
121                 return -EINVAL;
122
123         /* TPLFE_FN0_BLK_SIZE */
124         card->cis.blksize = buf[1] | (buf[2] << 8);
125
126         /* TPLFE_MAX_TRAN_SPEED */
127         card->cis.max_dtr = speed_val[(buf[3] >> 3) & 15] *
128                             speed_unit[buf[3] & 7];
129
130         return 0;
131 }
132
133 static int cistpl_funce_func(struct sdio_func *func,
134                              const unsigned char *buf, unsigned size)
135 {
136         unsigned vsn;
137         unsigned min_size;
138
139         /* let SDIO drivers take care of whitelisted FUNCE tuples */
140         if (cistpl_funce_whitelisted(buf[0]))
141                 return -EILSEQ;
142
143         vsn = func->card->cccr.sdio_vsn;
144         min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;
145
146         if (size < min_size || buf[0] != 1)
147                 return -EINVAL;
148
149         /* TPLFE_MAX_BLK_SIZE */
150         func->max_blksize = buf[12] | (buf[13] << 8);
151
152         /* TPLFE_ENABLE_TIMEOUT_VAL, present in ver 1.1 and above */
153         if (vsn > SDIO_SDIO_REV_1_00)
154                 func->enable_timeout = (buf[28] | (buf[29] << 8)) * 10;
155         else
156                 func->enable_timeout = jiffies_to_msecs(HZ);
157
158         return 0;
159 }
160
161 static int cistpl_funce(struct mmc_card *card, struct sdio_func *func,
162                         const unsigned char *buf, unsigned size)
163 {
164         int ret;
165
166         /*
167          * There should be two versions of the CISTPL_FUNCE tuple,
168          * one for the common CIS (function 0) and a version used by
169          * the individual function's CIS (1-7). Yet, the later has a
170          * different length depending on the SDIO spec version.
171          */
172         if (func)
173                 ret = cistpl_funce_func(func, buf, size);
174         else
175                 ret = cistpl_funce_common(card, buf, size);
176
177         if (ret && ret != -EILSEQ) {
178                 printk(KERN_ERR "%s: bad CISTPL_FUNCE size %u "
179                        "type %u\n", mmc_hostname(card->host), size, buf[0]);
180         }
181
182         return ret;
183 }
184
185 typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *,
186                            const unsigned char *, unsigned);
187
188 struct cis_tpl {
189         unsigned char code;
190         unsigned char min_size;
191         tpl_parse_t *parse;
192 };
193
194 static const struct cis_tpl cis_tpl_list[] = {
195         {       0x15,   3,      cistpl_vers_1           },
196         {       0x20,   4,      cistpl_manfid           },
197         {       0x21,   2,      /* cistpl_funcid */     },
198         {       0x22,   0,      cistpl_funce            },
199 };
200
201 static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
202 {
203         int ret;
204         struct sdio_func_tuple *this, **prev;
205         unsigned i, ptr = 0;
206
207         /*
208          * Note that this works for the common CIS (function number 0) as
209          * well as a function's CIS * since SDIO_CCCR_CIS and SDIO_FBR_CIS
210          * have the same offset.
211          */
212         for (i = 0; i < 3; i++) {
213                 unsigned char x, fn;
214
215                 if (func)
216                         fn = func->num;
217                 else
218                         fn = 0;
219
220                 ret = mmc_io_rw_direct(card, 0, 0,
221                         SDIO_FBR_BASE(fn) + SDIO_FBR_CIS + i, 0, &x);
222                 if (ret)
223                         return ret;
224                 ptr |= x << (i * 8);
225         }
226
227         if (func)
228                 prev = &func->tuples;
229         else
230                 prev = &card->tuples;
231
232         BUG_ON(*prev);
233
234         do {
235                 unsigned char tpl_code, tpl_link;
236
237                 ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_code);
238                 if (ret)
239                         break;
240
241                 /* 0xff means we're done */
242                 if (tpl_code == 0xff)
243                         break;
244
245                 /* null entries have no link field or data */
246                 if (tpl_code == 0x00)
247                         continue;
248
249                 ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link);
250                 if (ret)
251                         break;
252
253                 /* a size of 0xff also means we're done */
254                 if (tpl_link == 0xff)
255                         break;
256
257                 this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL);
258                 if (!this)
259                         return -ENOMEM;
260
261                 for (i = 0; i < tpl_link; i++) {
262                         ret = mmc_io_rw_direct(card, 0, 0,
263                                                ptr + i, 0, &this->data[i]);
264                         if (ret)
265                                 break;
266                 }
267                 if (ret) {
268                         kfree(this);
269                         break;
270                 }
271
272                 for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++)
273                         if (cis_tpl_list[i].code == tpl_code)
274                                 break;
275                 if (i < ARRAY_SIZE(cis_tpl_list)) {
276                         const struct cis_tpl *tpl = cis_tpl_list + i;
277                         if (tpl_link < tpl->min_size) {
278                                 printk(KERN_ERR
279                                        "%s: bad CIS tuple 0x%02x"
280                                        " (length = %u, expected >= %u)\n",
281                                        mmc_hostname(card->host),
282                                        tpl_code, tpl_link, tpl->min_size);
283                                 ret = -EINVAL;
284                         } else if (tpl->parse) {
285                                 ret = tpl->parse(card, func,
286                                                  this->data, tpl_link);
287                         }
288                         /*
289                          * We don't need the tuple anymore if it was
290                          * successfully parsed by the SDIO core or if it is
291                          * not going to be parsed by SDIO drivers.
292                          */
293                         if (!ret || ret != -EILSEQ)
294                                 kfree(this);
295                 } else {
296                         /* unknown tuple */
297                         ret = -EILSEQ;
298                 }
299
300                 if (ret == -EILSEQ) {
301                         /* this tuple is unknown to the core or whitelisted */
302                         this->next = NULL;
303                         this->code = tpl_code;
304                         this->size = tpl_link;
305                         *prev = this;
306                         prev = &this->next;
307                         printk(KERN_DEBUG
308                                "%s: queuing CIS tuple 0x%02x length %u\n",
309                                mmc_hostname(card->host), tpl_code, tpl_link);
310                         /* keep on analyzing tuples */
311                         ret = 0;
312                 }
313
314                 ptr += tpl_link;
315         } while (!ret);
316
317         /*
318          * Link in all unknown tuples found in the common CIS so that
319          * drivers don't have to go digging in two places.
320          */
321         if (func)
322                 *prev = card->tuples;
323
324         return ret;
325 }
326
327 int sdio_read_common_cis(struct mmc_card *card)
328 {
329         return sdio_read_cis(card, NULL);
330 }
331
332 void sdio_free_common_cis(struct mmc_card *card)
333 {
334         struct sdio_func_tuple *tuple, *victim;
335
336         tuple = card->tuples;
337
338         while (tuple) {
339                 victim = tuple;
340                 tuple = tuple->next;
341                 kfree(victim);
342         }
343
344         card->tuples = NULL;
345 }
346
347 int sdio_read_func_cis(struct sdio_func *func)
348 {
349         int ret;
350
351         ret = sdio_read_cis(func->card, func);
352         if (ret)
353                 return ret;
354
355         /*
356          * Since we've linked to tuples in the card structure,
357          * we must make sure we have a reference to it.
358          */
359         get_device(&func->card->dev);
360
361         /*
362          * Vendor/device id is optional for function CIS, so
363          * copy it from the card structure as needed.
364          */
365         if (func->vendor == 0) {
366                 func->vendor = func->card->cis.vendor;
367                 func->device = func->card->cis.device;
368         }
369
370         return 0;
371 }
372
373 void sdio_free_func_cis(struct sdio_func *func)
374 {
375         struct sdio_func_tuple *tuple, *victim;
376
377         tuple = func->tuples;
378
379         while (tuple && tuple != func->card->tuples) {
380                 victim = tuple;
381                 tuple = tuple->next;
382                 kfree(victim);
383         }
384
385         func->tuples = NULL;
386
387         /*
388          * We have now removed the link to the tuples in the
389          * card structure, so remove the reference.
390          */
391         put_device(&func->card->dev);
392 }
393