emmc.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. /*
  2. * bcm2835 external mass media controller (mmc / sd host interface)
  3. *
  4. * Copyright © 2012 Richard Miller <r.miller@acm.org>
  5. */
  6. #include "u.h"
  7. #include "../port/lib.h"
  8. #include "../port/error.h"
  9. #include "mem.h"
  10. #include "dat.h"
  11. #include "fns.h"
  12. #include "io.h"
  13. #include "../port/sd.h"
  14. #define EMMCREGS (VIRTIO+0x300000)
  15. enum {
  16. Extfreq = 100*Mhz, /* guess external clock frequency if */
  17. /* not available from vcore */
  18. Initfreq = 400000, /* initialisation frequency for MMC */
  19. SDfreq = 25*Mhz, /* standard SD frequency */
  20. DTO = 14, /* data timeout exponent (guesswork) */
  21. MMCSelect = 7, /* mmc/sd card select command */
  22. Setbuswidth = 6, /* mmc/sd set bus width command */
  23. };
  24. enum {
  25. /* Controller registers */
  26. Arg2 = 0x00>>2,
  27. Blksizecnt = 0x04>>2,
  28. Arg1 = 0x08>>2,
  29. Cmdtm = 0x0c>>2,
  30. Resp0 = 0x10>>2,
  31. Resp1 = 0x14>>2,
  32. Resp2 = 0x18>>2,
  33. Resp3 = 0x1c>>2,
  34. Data = 0x20>>2,
  35. Status = 0x24>>2,
  36. Control0 = 0x28>>2,
  37. Control1 = 0x2c>>2,
  38. Interrupt = 0x30>>2,
  39. Irptmask = 0x34>>2,
  40. Irpten = 0x38>>2,
  41. Control2 = 0x3c>>2,
  42. Forceirpt = 0x50>>2,
  43. Boottimeout = 0x70>>2,
  44. Dbgsel = 0x74>>2,
  45. Exrdfifocfg = 0x80>>2,
  46. Exrdfifoen = 0x84>>2,
  47. Tunestep = 0x88>>2,
  48. Tunestepsstd = 0x8c>>2,
  49. Tunestepsddr = 0x90>>2,
  50. Spiintspt = 0xf0>>2,
  51. Slotisrver = 0xfc>>2,
  52. /* Control0 */
  53. Dwidth4 = 1<<1,
  54. Dwidth1 = 0<<1,
  55. /* Control1 */
  56. Srstdata = 1<<26, /* reset data circuit */
  57. Srstcmd = 1<<25, /* reset command circuit */
  58. Srsthc = 1<<24, /* reset complete host controller */
  59. Datatoshift = 16, /* data timeout unit exponent */
  60. Datatomask = 0xF0000,
  61. Clkfreq8shift = 8, /* SD clock base divider LSBs */
  62. Clkfreq8mask = 0xFF00,
  63. Clkfreqms2shift = 6, /* SD clock base divider MSBs */
  64. Clkfreqms2mask = 0xC0,
  65. Clkgendiv = 0<<5, /* SD clock divided */
  66. Clkgenprog = 1<<5, /* SD clock programmable */
  67. Clken = 1<<2, /* SD clock enable */
  68. Clkstable = 1<<1,
  69. Clkintlen = 1<<0, /* enable internal EMMC clocks */
  70. /* Cmdtm */
  71. Indexshift = 24,
  72. Suspend = 1<<22,
  73. Resume = 2<<22,
  74. Abort = 3<<22,
  75. Isdata = 1<<21,
  76. Ixchken = 1<<20,
  77. Crcchken = 1<<19,
  78. Respmask = 3<<16,
  79. Respnone = 0<<16,
  80. Resp136 = 1<<16,
  81. Resp48 = 2<<16,
  82. Resp48busy = 3<<16,
  83. Multiblock = 1<<5,
  84. Host2card = 0<<4,
  85. Card2host = 1<<4,
  86. Autocmd12 = 1<<2,
  87. Autocmd23 = 2<<2,
  88. Blkcnten = 1<<1,
  89. /* Interrupt */
  90. Acmderr = 1<<24,
  91. Denderr = 1<<22,
  92. Dcrcerr = 1<<21,
  93. Dtoerr = 1<<20,
  94. Cbaderr = 1<<19,
  95. Cenderr = 1<<18,
  96. Ccrcerr = 1<<17,
  97. Ctoerr = 1<<16,
  98. Err = 1<<15,
  99. Cardintr = 1<<8, /* not in Broadcom datasheet */
  100. Cardinsert = 1<<6, /* not in Broadcom datasheet */
  101. Readrdy = 1<<5,
  102. Writerdy = 1<<4,
  103. Datadone = 1<<1,
  104. Cmddone = 1<<0,
  105. /* Status */
  106. Bufread = 1<<11, /* not in Broadcom datasheet */
  107. Bufwrite = 1<<10, /* not in Broadcom datasheet */
  108. Readtrans = 1<<9,
  109. Writetrans = 1<<8,
  110. Datactive = 1<<2,
  111. Datinhibit = 1<<1,
  112. Cmdinhibit = 1<<0,
  113. };
  114. int cmdinfo[64] = {
  115. [0] Ixchken,
  116. [2] Resp136,
  117. [3] Resp48 | Ixchken | Crcchken,
  118. [6] Resp48 | Ixchken | Crcchken,
  119. [7] Resp48busy | Ixchken | Crcchken,
  120. [8] Resp48 | Ixchken | Crcchken,
  121. [9] Resp136,
  122. [12] Resp48busy | Ixchken | Crcchken,
  123. [13] Resp48 | Ixchken | Crcchken,
  124. [16] Resp48,
  125. [17] Resp48 | Isdata | Card2host | Ixchken | Crcchken,
  126. [18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken,
  127. [24] Resp48 | Isdata | Host2card | Ixchken | Crcchken,
  128. [25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken,
  129. [41] Resp48,
  130. [55] Resp48 | Ixchken | Crcchken,
  131. };
  132. typedef struct Ctlr Ctlr;
  133. struct Ctlr {
  134. Rendez r;
  135. int datadone;
  136. int fastclock;
  137. ulong extclk;
  138. };
  139. static Ctlr emmc;
  140. static void mmcinterrupt(Ureg*, void*);
  141. static void
  142. WR(int reg, u32int val)
  143. {
  144. u32int *r = (u32int*)EMMCREGS;
  145. if(0)print("WR %2.2ux %ux\n", reg<<2, val);
  146. microdelay(emmc.fastclock? 2 : 20);
  147. r[reg] = val;
  148. }
  149. static uint
  150. clkdiv(uint d)
  151. {
  152. uint v;
  153. assert(d < 1<<10);
  154. v = (d << Clkfreq8shift) & Clkfreq8mask;
  155. v |= ((d >> 8) << Clkfreqms2shift) & Clkfreqms2mask;
  156. return v;
  157. }
  158. static int
  159. datadone(void*)
  160. {
  161. return emmc.datadone;
  162. }
  163. static int
  164. emmcinit(void)
  165. {
  166. u32int *r;
  167. ulong clk;
  168. char *s;
  169. clk = getclkrate(ClkEmmc);
  170. s = "";
  171. if(clk == 0){
  172. s = "Assuming ";
  173. clk = Extfreq;
  174. }
  175. emmc.extclk = clk;
  176. print("%seMMC external clock %lud Mhz\n", s, clk/1000000);
  177. r = (u32int*)EMMCREGS;
  178. if(0)print("emmc control %8.8ux %8.8ux %8.8ux\n",
  179. r[Control0], r[Control1], r[Control2]);
  180. WR(Control1, Srsthc);
  181. delay(10);
  182. while(r[Control1] & Srsthc)
  183. ;
  184. return 0;
  185. }
  186. static int
  187. emmcinquiry(char *inquiry, int inqlen)
  188. {
  189. u32int *r;
  190. uint ver;
  191. r = (u32int*)EMMCREGS;
  192. ver = r[Slotisrver] >> 16;
  193. return snprint(inquiry, inqlen,
  194. "Arasan eMMC SD Host Controller %2.2x Version %2.2x",
  195. ver&0xFF, ver>>8);
  196. }
  197. static void
  198. emmcenable(void)
  199. {
  200. u32int *r;
  201. int i;
  202. r = (u32int*)EMMCREGS;
  203. WR(Control1, clkdiv(emmc.extclk/Initfreq - 1) |
  204. DTO<<Datatoshift | Clkgendiv | Clken | Clkintlen);
  205. for(i = 0; i < 1000; i++){
  206. delay(1);
  207. if(r[Control1] & Clkstable)
  208. break;
  209. }
  210. if(i == 1000)
  211. print("SD clock won't initialise!\n");
  212. WR(Irptmask, ~(Dtoerr|Cardintr));
  213. intrenable(IRQmmc, mmcinterrupt, nil, 0, "mmc");
  214. }
  215. static int
  216. emmccmd(u32int cmd, u32int arg, u32int *resp)
  217. {
  218. u32int *r;
  219. u32int c;
  220. int i;
  221. ulong now;
  222. r = (u32int*)EMMCREGS;
  223. assert(cmd < nelem(cmdinfo) && cmdinfo[cmd] != 0);
  224. c = (cmd << Indexshift) | cmdinfo[cmd];
  225. if(r[Status] & Cmdinhibit){
  226. print("emmccmd: need to reset Cmdinhibit intr %ux stat %ux\n",
  227. r[Interrupt], r[Status]);
  228. WR(Control1, r[Control1] | Srstcmd);
  229. while(r[Control1] & Srstcmd)
  230. ;
  231. while(r[Status] & Cmdinhibit)
  232. ;
  233. }
  234. if((r[Status] & Datinhibit) &&
  235. ((c & Isdata) || (c & Respmask) == Resp48busy)){
  236. print("emmccmd: need to reset Datinhibit intr %ux stat %ux\n",
  237. r[Interrupt], r[Status]);
  238. WR(Control1, r[Control1] | Srstdata);
  239. while(r[Control1] & Srstdata)
  240. ;
  241. while(r[Status] & Datinhibit)
  242. ;
  243. }
  244. WR(Arg1, arg);
  245. if((i = r[Interrupt]) != 0){
  246. if(i != Cardinsert)
  247. print("emmc: before command, intr was %ux\n", i);
  248. WR(Interrupt, i);
  249. }
  250. WR(Cmdtm, c);
  251. now = m->ticks;
  252. while(((i=r[Interrupt])&(Cmddone|Err)) == 0)
  253. if(m->ticks-now > HZ)
  254. break;
  255. if((i&(Cmddone|Err)) != Cmddone){
  256. if((i&~Err) != Ctoerr)
  257. print("emmc: cmd %ux error intr %ux stat %ux\n", c, i, r[Status]);
  258. WR(Interrupt, i);
  259. if(r[Status]&Cmdinhibit){
  260. WR(Control1, r[Control1]|Srstcmd);
  261. while(r[Control1]&Srstcmd)
  262. ;
  263. }
  264. error(Eio);
  265. }
  266. WR(Interrupt, i & ~(Datadone|Readrdy|Writerdy));
  267. switch(c & Respmask){
  268. case Resp136:
  269. resp[0] = r[Resp0]<<8;
  270. resp[1] = r[Resp0]>>24 | r[Resp1]<<8;
  271. resp[2] = r[Resp1]>>24 | r[Resp2]<<8;
  272. resp[3] = r[Resp2]>>24 | r[Resp3]<<8;
  273. break;
  274. case Resp48:
  275. case Resp48busy:
  276. resp[0] = r[Resp0];
  277. break;
  278. case Respnone:
  279. resp[0] = 0;
  280. break;
  281. }
  282. if((c & Respmask) == Resp48busy){
  283. WR(Irpten, Datadone|Err);
  284. tsleep(&emmc.r, datadone, 0, 3000);
  285. i = emmc.datadone;
  286. emmc.datadone = 0;
  287. WR(Irpten, 0);
  288. if((i & Datadone) == 0)
  289. print("emmcio: no Datadone after CMD%d\n", cmd);
  290. if(i & Err)
  291. print("emmcio: CMD%d error interrupt %ux\n",
  292. cmd, r[Interrupt]);
  293. WR(Interrupt, i);
  294. }
  295. /*
  296. * Once card is selected, use faster clock
  297. */
  298. if(cmd == MMCSelect){
  299. delay(10);
  300. WR(Control1, clkdiv(emmc.extclk/SDfreq - 1) |
  301. DTO<<Datatoshift | Clkgendiv | Clken | Clkintlen);
  302. for(i = 0; i < 1000; i++){
  303. delay(1);
  304. if(r[Control1] & Clkstable)
  305. break;
  306. }
  307. delay(10);
  308. emmc.fastclock = 1;
  309. }
  310. /*
  311. * If card bus width changes, change host bus width
  312. */
  313. if(cmd == Setbuswidth){
  314. switch(arg){
  315. case 0:
  316. WR(Control0, r[Control0] & ~Dwidth4);
  317. break;
  318. case 2:
  319. WR(Control0, r[Control0] | Dwidth4);
  320. break;
  321. }
  322. }
  323. return 0;
  324. }
  325. void
  326. emmciosetup(int write, void *buf, int bsize, int bcount)
  327. {
  328. USED(write);
  329. USED(buf);
  330. WR(Blksizecnt, bcount<<16 | bsize);
  331. }
  332. static void
  333. emmcio(int write, uchar *buf, int len)
  334. {
  335. u32int *r;
  336. int i;
  337. r = (u32int*)EMMCREGS;
  338. assert((len&3) == 0);
  339. okay(1);
  340. if(waserror()){
  341. okay(0);
  342. nexterror();
  343. }
  344. if(write)
  345. dmastart(DmaChanEmmc, DmaDevEmmc, DmaM2D,
  346. buf, &r[Data], len);
  347. else
  348. dmastart(DmaChanEmmc, DmaDevEmmc, DmaD2M,
  349. &r[Data], buf, len);
  350. if(dmawait(DmaChanEmmc) < 0)
  351. error(Eio);
  352. WR(Irpten, Datadone|Err);
  353. tsleep(&emmc.r, datadone, 0, 3000);
  354. i = emmc.datadone;
  355. emmc.datadone = 0;
  356. WR(Irpten, 0);
  357. if((i & Datadone) == 0){
  358. print("emmcio: %d timeout intr %ux stat %ux\n",
  359. write, i, r[Status]);
  360. WR(Interrupt, i);
  361. error(Eio);
  362. }
  363. if(i & Err){
  364. print("emmcio: %d error intr %ux stat %ux\n",
  365. write, r[Interrupt], r[Status]);
  366. WR(Interrupt, i);
  367. error(Eio);
  368. }
  369. if(i)
  370. WR(Interrupt, i);
  371. poperror();
  372. okay(0);
  373. }
  374. static void
  375. mmcinterrupt(Ureg*, void*)
  376. {
  377. u32int *r;
  378. int i;
  379. r = (u32int*)EMMCREGS;
  380. i = r[Interrupt];
  381. r[Interrupt] = i & (Datadone|Err);
  382. emmc.datadone = i;
  383. wakeup(&emmc.r);
  384. }
  385. SDio sdio = {
  386. "emmc",
  387. emmcinit,
  388. emmcenable,
  389. emmcinquiry,
  390. emmccmd,
  391. emmciosetup,
  392. emmcio,
  393. };