sdio_cis.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. #include <linux/kernel.h>
  16. #include <linux/mmc/host.h>
  17. #include <linux/mmc/card.h>
  18. #include <linux/mmc/sdio.h>
  19. #include <linux/mmc/sdio_func.h>
  20. #include "sdio_cis.h"
  21. #include "sdio_ops.h"
  22. static int cistpl_manfid(struct mmc_card *card, struct sdio_func *func,
  23. const unsigned char *buf, unsigned size)
  24. {
  25. unsigned int vendor, device;
  26. /* TPLMID_MANF */
  27. vendor = buf[0] | (buf[1] << 8);
  28. /* TPLMID_CARD */
  29. device = buf[2] | (buf[3] << 8);
  30. if (func) {
  31. func->vendor = vendor;
  32. func->device = device;
  33. } else {
  34. card->cis.vendor = vendor;
  35. card->cis.device = device;
  36. }
  37. return 0;
  38. }
  39. static const unsigned char speed_val[16] =
  40. { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 };
  41. static const unsigned int speed_unit[8] =
  42. { 10000, 100000, 1000000, 10000000, 0, 0, 0, 0 };
  43. static int cistpl_funce_common(struct mmc_card *card,
  44. const unsigned char *buf, unsigned size)
  45. {
  46. if (size < 0x04 || buf[0] != 0)
  47. return -EINVAL;
  48. /* TPLFE_FN0_BLK_SIZE */
  49. card->cis.blksize = buf[1] | (buf[2] << 8);
  50. /* TPLFE_MAX_TRAN_SPEED */
  51. card->cis.max_dtr = speed_val[(buf[3] >> 3) & 15] *
  52. speed_unit[buf[3] & 7];
  53. return 0;
  54. }
  55. static int cistpl_funce_func(struct sdio_func *func,
  56. const unsigned char *buf, unsigned size)
  57. {
  58. unsigned vsn;
  59. unsigned min_size;
  60. vsn = func->card->cccr.sdio_vsn;
  61. min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;
  62. if (size < min_size || buf[0] != 1)
  63. return -EINVAL;
  64. /* TPLFE_MAX_BLK_SIZE */
  65. func->blksize = buf[12] | (buf[13] << 8);
  66. return 0;
  67. }
  68. static int cistpl_funce(struct mmc_card *card, struct sdio_func *func,
  69. const unsigned char *buf, unsigned size)
  70. {
  71. int ret;
  72. /*
  73. * There should be two versions of the CISTPL_FUNCE tuple,
  74. * one for the common CIS (function 0) and a version used by
  75. * the individual function's CIS (1-7). Yet, the later has a
  76. * different length depending on the SDIO spec version.
  77. */
  78. if (func)
  79. ret = cistpl_funce_func(func, buf, size);
  80. else
  81. ret = cistpl_funce_common(card, buf, size);
  82. if (ret) {
  83. printk(KERN_ERR "%s: bad CISTPL_FUNCE size %u "
  84. "type %u\n", mmc_hostname(card->host), size, buf[0]);
  85. return ret;
  86. }
  87. return 0;
  88. }
  89. typedef int (tpl_parse_t)(struct mmc_card *, struct sdio_func *,
  90. const unsigned char *, unsigned);
  91. struct cis_tpl {
  92. unsigned char code;
  93. unsigned char min_size;
  94. tpl_parse_t *parse;
  95. };
  96. static const struct cis_tpl cis_tpl_list[] = {
  97. { 0x15, 3, /* cistpl_vers_1 */ },
  98. { 0x20, 4, cistpl_manfid },
  99. { 0x21, 2, /* cistpl_funcid */ },
  100. { 0x22, 0, cistpl_funce },
  101. };
  102. static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
  103. {
  104. int ret;
  105. struct sdio_func_tuple *this, **prev;
  106. unsigned i, ptr = 0;
  107. /*
  108. * Note that this works for the common CIS (function number 0) as
  109. * well as a function's CIS * since SDIO_CCCR_CIS and SDIO_FBR_CIS
  110. * have the same offset.
  111. */
  112. for (i = 0; i < 3; i++) {
  113. unsigned char x, fn;
  114. if (func)
  115. fn = func->num;
  116. else
  117. fn = 0;
  118. ret = mmc_io_rw_direct(card, 0, 0,
  119. fn * 0x100 + SDIO_FBR_CIS + i, 0, &x);
  120. if (ret)
  121. return ret;
  122. ptr |= x << (i * 8);
  123. }
  124. if (func)
  125. prev = &func->tuples;
  126. else
  127. prev = &card->tuples;
  128. BUG_ON(*prev);
  129. do {
  130. unsigned char tpl_code, tpl_link;
  131. ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_code);
  132. if (ret)
  133. break;
  134. /* 0xff means we're done */
  135. if (tpl_code == 0xff)
  136. break;
  137. ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link);
  138. if (ret)
  139. break;
  140. this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL);
  141. if (!this)
  142. return -ENOMEM;
  143. for (i = 0; i < tpl_link; i++) {
  144. ret = mmc_io_rw_direct(card, 0, 0,
  145. ptr + i, 0, &this->data[i]);
  146. if (ret)
  147. break;
  148. }
  149. if (ret) {
  150. kfree(this);
  151. break;
  152. }
  153. for (i = 0; i < ARRAY_SIZE(cis_tpl_list); i++)
  154. if (cis_tpl_list[i].code == tpl_code)
  155. break;
  156. if (i >= ARRAY_SIZE(cis_tpl_list)) {
  157. /* this tuple is unknown to the core */
  158. this->next = NULL;
  159. this->code = tpl_code;
  160. this->size = tpl_link;
  161. *prev = this;
  162. prev = &this->next;
  163. printk(KERN_DEBUG
  164. "%s: queuing CIS tuple 0x%02x length %u\n",
  165. mmc_hostname(card->host), tpl_code, tpl_link);
  166. } else {
  167. const struct cis_tpl *tpl = cis_tpl_list + i;
  168. if (tpl_link < tpl->min_size) {
  169. printk(KERN_ERR
  170. "%s: bad CIS tuple 0x%02x (length = %u, expected >= %u)\n",
  171. mmc_hostname(card->host),
  172. tpl_code, tpl_link, tpl->min_size);
  173. ret = -EINVAL;
  174. } else if (tpl->parse) {
  175. ret = tpl->parse(card, func,
  176. this->data, tpl_link);
  177. }
  178. kfree(this);
  179. }
  180. ptr += tpl_link;
  181. } while (!ret);
  182. /*
  183. * Link in all unknown tuples found in the common CIS so that
  184. * drivers don't have to go digging in two places.
  185. */
  186. if (func)
  187. *prev = card->tuples;
  188. return ret;
  189. }
  190. int sdio_read_common_cis(struct mmc_card *card)
  191. {
  192. return sdio_read_cis(card, NULL);
  193. }
  194. void sdio_free_common_cis(struct mmc_card *card)
  195. {
  196. struct sdio_func_tuple *tuple, *victim;
  197. tuple = card->tuples;
  198. while (tuple) {
  199. victim = tuple;
  200. tuple = tuple->next;
  201. kfree(victim);
  202. }
  203. card->tuples = NULL;
  204. }
  205. int sdio_read_func_cis(struct sdio_func *func)
  206. {
  207. int ret;
  208. ret = sdio_read_cis(func->card, func);
  209. if (ret)
  210. return ret;
  211. /*
  212. * Since we've linked to tuples in the card structure,
  213. * we must make sure we have a reference to it.
  214. */
  215. get_device(&func->card->dev);
  216. /*
  217. * Vendor/device id is optional for function CIS, so
  218. * copy it from the card structure as needed.
  219. */
  220. if (func->vendor == 0) {
  221. func->vendor = func->card->cis.vendor;
  222. func->device = func->card->cis.device;
  223. }
  224. return 0;
  225. }
  226. void sdio_free_func_cis(struct sdio_func *func)
  227. {
  228. struct sdio_func_tuple *tuple, *victim;
  229. tuple = func->tuples;
  230. while (tuple && tuple != func->card->tuples) {
  231. victim = tuple;
  232. tuple = tuple->next;
  233. kfree(victim);
  234. }
  235. func->tuples = NULL;
  236. /*
  237. * We have now removed the link to the tuples in the
  238. * card structure, so remove the reference.
  239. */
  240. put_device(&func->card->dev);
  241. }