sdmmc.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * mmc / sd memory card
  3. *
  4. * Copyright © 2012 Richard Miller <r.miller@acm.org>
  5. *
  6. * Assumes only one card on the bus
  7. */
  8. #include "u.h"
  9. #include "../port/lib.h"
  10. #include "../port/error.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "io.h"
  15. #include "../port/sd.h"
  16. #define CSD(end, start) rbits(csd, start, (end)-(start)+1)
  17. typedef struct Ctlr Ctlr;
  18. enum {
  19. Inittimeout = 15,
  20. Multiblock = 1,
  21. /* Commands */
  22. GO_IDLE_STATE = 0,
  23. ALL_SEND_CID = 2,
  24. SEND_RELATIVE_ADDR= 3,
  25. SELECT_CARD = 7,
  26. SD_SEND_IF_COND = 8,
  27. SEND_CSD = 9,
  28. STOP_TRANSMISSION= 12,
  29. SEND_STATUS = 13,
  30. SET_BLOCKLEN = 16,
  31. READ_SINGLE_BLOCK= 17,
  32. READ_MULTIPLE_BLOCK= 18,
  33. WRITE_BLOCK = 24,
  34. WRITE_MULTIPLE_BLOCK= 25,
  35. APP_CMD = 55, /* prefix for following app-specific commands */
  36. SET_BUS_WIDTH = 6,
  37. SD_SEND_OP_COND = 41,
  38. /* Command arguments */
  39. /* SD_SEND_IF_COND */
  40. Voltage = 1<<8,
  41. Checkpattern = 0x42,
  42. /* SELECT_CARD */
  43. Rcashift = 16,
  44. /* SD_SEND_OP_COND */
  45. Hcs = 1<<30, /* host supports SDHC & SDXC */
  46. Ccs = 1<<30, /* card is SDHC or SDXC */
  47. V3_3 = 3<<20, /* 3.2-3.4 volts */
  48. /* SET_BUS_WIDTH */
  49. Width1 = 0<<0,
  50. Width4 = 2<<0,
  51. /* OCR (operating conditions register) */
  52. Powerup = 1<<31,
  53. };
  54. struct Ctlr {
  55. SDev *dev;
  56. SDio *io;
  57. /* SD card registers */
  58. u16int rca;
  59. u32int ocr;
  60. u32int cid[4];
  61. u32int csd[4];
  62. };
  63. extern SDifc sdmmcifc;
  64. extern SDio sdio;
  65. static uint
  66. rbits(u32int *p, uint start, uint len)
  67. {
  68. uint w, off, v;
  69. w = start / 32;
  70. off = start % 32;
  71. if(off == 0)
  72. v = p[w];
  73. else
  74. v = p[w] >> off | p[w+1] << (32-off);
  75. if(len < 32)
  76. return v & ((1<<len) - 1);
  77. else
  78. return v;
  79. }
  80. static void
  81. identify(SDunit *unit, u32int *csd)
  82. {
  83. uint csize, mult;
  84. unit->secsize = 1 << CSD(83, 80);
  85. switch(CSD(127, 126)){
  86. case 0: /* CSD version 1 */
  87. csize = CSD(73, 62);
  88. mult = CSD(49, 47);
  89. unit->sectors = (csize+1) * (1<<(mult+2));
  90. break;
  91. case 1: /* CSD version 2 */
  92. csize = CSD(69, 48);
  93. unit->sectors = (csize+1) * 512LL*KiB / unit->secsize;
  94. break;
  95. }
  96. if(unit->secsize == 1024){
  97. unit->sectors <<= 1;
  98. unit->secsize = 512;
  99. }
  100. }
  101. static SDev*
  102. mmcpnp(void)
  103. {
  104. SDev *sdev;
  105. Ctlr *ctl;
  106. if(sdio.init() < 0)
  107. return nil;
  108. sdev = malloc(sizeof(SDev));
  109. if(sdev == nil)
  110. return nil;
  111. ctl = malloc(sizeof(Ctlr));
  112. if(ctl == nil){
  113. free(sdev);
  114. return nil;
  115. }
  116. sdev->idno = 'M';
  117. sdev->ifc = &sdmmcifc;
  118. sdev->nunit = 1;
  119. sdev->ctlr = ctl;
  120. ctl->dev = sdev;
  121. ctl->io = &sdio;
  122. return sdev;
  123. }
  124. static int
  125. mmcverify(SDunit *unit)
  126. {
  127. int n;
  128. Ctlr *ctl;
  129. ctl = unit->dev->ctlr;
  130. n = ctl->io->inquiry((char*)&unit->inquiry[8], sizeof(unit->inquiry)-8);
  131. if(n < 0)
  132. return 0;
  133. unit->inquiry[0] = SDperdisk;
  134. unit->inquiry[1] = SDinq1removable;
  135. unit->inquiry[4] = sizeof(unit->inquiry)-4;
  136. return 1;
  137. }
  138. static int
  139. mmcenable(SDev* dev)
  140. {
  141. Ctlr *ctl;
  142. ctl = dev->ctlr;
  143. ctl->io->enable();
  144. return 1;
  145. }
  146. static int
  147. mmconline(SDunit *unit)
  148. {
  149. int hcs, i;
  150. u32int r[4];
  151. Ctlr *ctl;
  152. SDio *io;
  153. ctl = unit->dev->ctlr;
  154. io = ctl->io;
  155. assert(unit->subno == 0);
  156. if(waserror()){
  157. unit->sectors = 0;
  158. return 0;
  159. }
  160. if(unit->sectors != 0){
  161. io->cmd(SEND_STATUS, ctl->rca<<Rcashift, r);
  162. poperror();
  163. return 1;
  164. }
  165. io->cmd(GO_IDLE_STATE, 0, r);
  166. hcs = 0;
  167. if(!waserror()){
  168. io->cmd(SD_SEND_IF_COND, Voltage|Checkpattern, r);
  169. if(r[0] == (Voltage|Checkpattern)) /* SD 2.0 or above */
  170. hcs = Hcs;
  171. poperror();
  172. }
  173. for(i = 0; i < Inittimeout; i++){
  174. delay(100);
  175. io->cmd(APP_CMD, 0, r);
  176. io->cmd(SD_SEND_OP_COND, hcs|V3_3, r);
  177. if(r[0] & Powerup)
  178. break;
  179. }
  180. if(i == Inittimeout){
  181. print("sdmmc: card won't power up\n");
  182. poperror();
  183. return 2;
  184. }
  185. ctl->ocr = r[0];
  186. io->cmd(ALL_SEND_CID, 0, r);
  187. memmove(ctl->cid, r, sizeof ctl->cid);
  188. io->cmd(SEND_RELATIVE_ADDR, 0, r);
  189. ctl->rca = r[0]>>16;
  190. io->cmd(SEND_CSD, ctl->rca<<Rcashift, r);
  191. memmove(ctl->csd, r, sizeof ctl->csd);
  192. identify(unit, ctl->csd);
  193. io->cmd(SELECT_CARD, ctl->rca<<Rcashift, r);
  194. io->cmd(SET_BLOCKLEN, unit->secsize, r);
  195. io->cmd(APP_CMD, ctl->rca<<Rcashift, r);
  196. io->cmd(SET_BUS_WIDTH, Width4, r);
  197. poperror();
  198. return 1;
  199. }
  200. static int
  201. mmcrctl(SDunit *unit, char *p, int l)
  202. {
  203. Ctlr *ctl;
  204. int i, n;
  205. ctl = unit->dev->ctlr;
  206. assert(unit->subno == 0);
  207. if(unit->sectors == 0){
  208. mmconline(unit);
  209. if(unit->sectors == 0)
  210. return 0;
  211. }
  212. n = snprint(p, l, "rca %4.4ux ocr %8.8ux\ncid ", ctl->rca, ctl->ocr);
  213. for(i = nelem(ctl->cid)-1; i >= 0; i--)
  214. n += snprint(p+n, l-n, "%8.8ux", ctl->cid[i]);
  215. n += snprint(p+n, l-n, " csd ");
  216. for(i = nelem(ctl->csd)-1; i >= 0; i--)
  217. n += snprint(p+n, l-n, "%8.8ux", ctl->csd[i]);
  218. n += snprint(p+n, l-n, "\ngeometry %llud %ld\n",
  219. unit->sectors, unit->secsize);
  220. return n;
  221. }
  222. static long
  223. mmcbio(SDunit *unit, int lun, int write, void *data, long nb, uvlong bno)
  224. {
  225. int len, tries;
  226. ulong b;
  227. u32int r[4];
  228. uchar *buf;
  229. Ctlr *ctl;
  230. SDio *io;
  231. USED(lun);
  232. ctl = unit->dev->ctlr;
  233. io = ctl->io;
  234. assert(unit->subno == 0);
  235. if(unit->sectors == 0)
  236. error("media change");
  237. buf = data;
  238. len = unit->secsize;
  239. if(Multiblock){
  240. b = bno;
  241. tries = 0;
  242. while(waserror())
  243. if(++tries == 3)
  244. nexterror();
  245. io->iosetup(write, buf, len, nb);
  246. if(waserror()){
  247. io->cmd(STOP_TRANSMISSION, 0, r);
  248. nexterror();
  249. }
  250. io->cmd(write? WRITE_MULTIPLE_BLOCK: READ_MULTIPLE_BLOCK,
  251. ctl->ocr & Ccs? b: b * len, r);
  252. io->io(write, buf, nb * len);
  253. poperror();
  254. io->cmd(STOP_TRANSMISSION, 0, r);
  255. poperror();
  256. b += nb;
  257. }else{
  258. for(b = bno; b < bno + nb; b++){
  259. io->iosetup(write, buf, len, 1);
  260. io->cmd(write? WRITE_BLOCK : READ_SINGLE_BLOCK,
  261. ctl->ocr & Ccs? b: b * len, r);
  262. io->io(write, buf, len);
  263. buf += len;
  264. }
  265. }
  266. return (b - bno) * len;
  267. }
  268. static int
  269. mmcrio(SDreq*)
  270. {
  271. return -1;
  272. }
  273. SDifc sdmmcifc = {
  274. .name = "mmc",
  275. .pnp = mmcpnp,
  276. .enable = mmcenable,
  277. .verify = mmcverify,
  278. .online = mmconline,
  279. .rctl = mmcrctl,
  280. .bio = mmcbio,
  281. .rio = mmcrio,
  282. };