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