1 /*
2 * bcm2835 external mass media controller (mmc / sd host interface)
3 *
4 * Copyright © 2012 Richard Miller <r.miller@acm.org>
5 */
6
7 /*
8 Not officially documented: emmc can be connected to different gpio pins
9 48-53 (SD card)
10 22-27 (P1 header)
11 34-39 (wifi - pi3 only)
12 using ALT3 function to activate the required routing
13 */
14
15 #include "u.h"
16 #include "../port/lib.h"
17 #include "../port/error.h"
18 #include "mem.h"
19 #include "dat.h"
20 #include "fns.h"
21 #include "io.h"
22 #include "../port/sd.h"
23
24 #define EMMCREGS (VIRTIO+0x300000)
25
26 enum {
27 Extfreq = 100*Mhz, /* guess external clock frequency if */
28 /* not available from vcore */
29 Initfreq = 400000, /* initialisation frequency for MMC */
30 SDfreq = 25*Mhz, /* standard SD frequency */
31 SDfreqhs = 50*Mhz, /* high speed frequency */
32 DTO = 14, /* data timeout exponent (guesswork) */
33
34 GoIdle = 0, /* mmc/sdio go idle state */
35 MMCSelect = 7, /* mmc/sd card select command */
36 Setbuswidth = 6, /* mmc/sd set bus width command */
37 Switchfunc = 6, /* mmc/sd switch function command */
38 Voltageswitch = 11, /* md/sdio switch to 1.8V */
39 IORWdirect = 52, /* sdio read/write direct command */
40 IORWextended = 53, /* sdio read/write extended command */
41 Appcmd = 55, /* mmc/sd application command prefix */
42 };
43
44 enum {
45 /* Controller registers */
46 Arg2 = 0x00>>2,
47 Blksizecnt = 0x04>>2,
48 Arg1 = 0x08>>2,
49 Cmdtm = 0x0c>>2,
50 Resp0 = 0x10>>2,
51 Resp1 = 0x14>>2,
52 Resp2 = 0x18>>2,
53 Resp3 = 0x1c>>2,
54 Data = 0x20>>2,
55 Status = 0x24>>2,
56 Control0 = 0x28>>2,
57 Control1 = 0x2c>>2,
58 Interrupt = 0x30>>2,
59 Irptmask = 0x34>>2,
60 Irpten = 0x38>>2,
61 Control2 = 0x3c>>2,
62 Forceirpt = 0x50>>2,
63 Boottimeout = 0x70>>2,
64 Dbgsel = 0x74>>2,
65 Exrdfifocfg = 0x80>>2,
66 Exrdfifoen = 0x84>>2,
67 Tunestep = 0x88>>2,
68 Tunestepsstd = 0x8c>>2,
69 Tunestepsddr = 0x90>>2,
70 Spiintspt = 0xf0>>2,
71 Slotisrver = 0xfc>>2,
72
73 /* Control0 */
74 Hispeed = 1<<2,
75 Dwidth4 = 1<<1,
76 Dwidth1 = 0<<1,
77
78 /* Control1 */
79 Srstdata = 1<<26, /* reset data circuit */
80 Srstcmd = 1<<25, /* reset command circuit */
81 Srsthc = 1<<24, /* reset complete host controller */
82 Datatoshift = 16, /* data timeout unit exponent */
83 Datatomask = 0xF0000,
84 Clkfreq8shift = 8, /* SD clock base divider LSBs */
85 Clkfreq8mask = 0xFF00,
86 Clkfreqms2shift = 6, /* SD clock base divider MSBs */
87 Clkfreqms2mask = 0xC0,
88 Clkgendiv = 0<<5, /* SD clock divided */
89 Clkgenprog = 1<<5, /* SD clock programmable */
90 Clken = 1<<2, /* SD clock enable */
91 Clkstable = 1<<1,
92 Clkintlen = 1<<0, /* enable internal EMMC clocks */
93
94 /* Cmdtm */
95 Indexshift = 24,
96 Suspend = 1<<22,
97 Resume = 2<<22,
98 Abort = 3<<22,
99 Isdata = 1<<21,
100 Ixchken = 1<<20,
101 Crcchken = 1<<19,
102 Respmask = 3<<16,
103 Respnone = 0<<16,
104 Resp136 = 1<<16,
105 Resp48 = 2<<16,
106 Resp48busy = 3<<16,
107 Multiblock = 1<<5,
108 Host2card = 0<<4,
109 Card2host = 1<<4,
110 Autocmd12 = 1<<2,
111 Autocmd23 = 2<<2,
112 Blkcnten = 1<<1,
113
114 /* Interrupt */
115 Acmderr = 1<<24,
116 Denderr = 1<<22,
117 Dcrcerr = 1<<21,
118 Dtoerr = 1<<20,
119 Cbaderr = 1<<19,
120 Cenderr = 1<<18,
121 Ccrcerr = 1<<17,
122 Ctoerr = 1<<16,
123 Err = 1<<15,
124 Cardintr = 1<<8,
125 Cardinsert = 1<<6, /* not in Broadcom datasheet */
126 Readrdy = 1<<5,
127 Writerdy = 1<<4,
128 Datadone = 1<<1,
129 Cmddone = 1<<0,
130
131 /* Status */
132 Bufread = 1<<11, /* not in Broadcom datasheet */
133 Bufwrite = 1<<10, /* not in Broadcom datasheet */
134 Readtrans = 1<<9,
135 Writetrans = 1<<8,
136 Datactive = 1<<2,
137 Datinhibit = 1<<1,
138 Cmdinhibit = 1<<0,
139 };
140
141 static int cmdinfo[64] = {
142 [0] Ixchken,
143 [2] Resp136,
144 [3] Resp48 | Ixchken | Crcchken,
145 [5] Resp48,
146 [6] Resp48 | Ixchken | Crcchken,
147 [7] Resp48busy | Ixchken | Crcchken,
148 [8] Resp48 | Ixchken | Crcchken,
149 [9] Resp136,
150 [11] Resp48 | Ixchken | Crcchken,
151 [12] Resp48busy | Ixchken | Crcchken,
152 [13] Resp48 | Ixchken | Crcchken,
153 [16] Resp48,
154 [17] Resp48 | Isdata | Card2host | Ixchken | Crcchken,
155 [18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken,
156 [24] Resp48 | Isdata | Host2card | Ixchken | Crcchken,
157 [25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken,
158 [41] Resp48,
159 [52] Resp48 | Ixchken | Crcchken,
160 [53] Resp48 | Ixchken | Crcchken | Isdata,
161 [55] Resp48 | Ixchken | Crcchken,
162 };
163
164 typedef struct Ctlr Ctlr;
165
166 struct Ctlr {
167 Rendez r;
168 Rendez cardr;
169 int fastclock;
170 ulong extclk;
171 int appcmd;
172 };
173
174 static Ctlr emmc;
175
176 static void mmcinterrupt(Ureg*, void*);
177
178 static void
WR(int reg,u32int val)179 WR(int reg, u32int val)
180 {
181 u32int *r = (u32int*)EMMCREGS;
182
183 if(0)print("WR %2.2ux %ux\n", reg<<2, val);
184 microdelay(emmc.fastclock? 2 : 20);
185 coherence();
186 r[reg] = val;
187 }
188
189 static uint
clkdiv(uint d)190 clkdiv(uint d)
191 {
192 uint v;
193
194 assert(d < 1<<10);
195 v = (d << Clkfreq8shift) & Clkfreq8mask;
196 v |= ((d >> 8) << Clkfreqms2shift) & Clkfreqms2mask;
197 return v;
198 }
199
200 static void
emmcclk(uint freq)201 emmcclk(uint freq)
202 {
203 u32int *r;
204 uint div;
205 int i;
206
207 r = (u32int*)EMMCREGS;
208 div = emmc.extclk / (freq<<1);
209 if(emmc.extclk / (div<<1) > freq)
210 div++;
211 WR(Control1, clkdiv(div) |
212 DTO<<Datatoshift | Clkgendiv | Clken | Clkintlen);
213 for(i = 0; i < 1000; i++){
214 delay(1);
215 if(r[Control1] & Clkstable)
216 break;
217 }
218 if(i == 1000)
219 print("emmc: can't set clock to %ud\n", freq);
220 }
221
222 static int
datadone(void *)223 datadone(void*)
224 {
225 int i;
226
227 u32int *r = (u32int*)EMMCREGS;
228 i = r[Interrupt];
229 return i & (Datadone|Err);
230 }
231
232 static int
cardintready(void *)233 cardintready(void*)
234 {
235 int i;
236
237 u32int *r = (u32int*)EMMCREGS;
238 i = r[Interrupt];
239 return i & Cardintr;
240 }
241
242 static int
emmcinit(void)243 emmcinit(void)
244 {
245 u32int *r;
246 ulong clk;
247
248 clk = getclkrate(ClkEmmc);
249 if(clk == 0){
250 clk = Extfreq;
251 print("emmc: assuming external clock %lud Mhz\n", clk/1000000);
252 }
253 emmc.extclk = clk;
254 r = (u32int*)EMMCREGS;
255 if(0)print("emmc control %8.8ux %8.8ux %8.8ux\n",
256 r[Control0], r[Control1], r[Control2]);
257 WR(Control1, Srsthc);
258 delay(10);
259 while(r[Control1] & Srsthc)
260 ;
261 WR(Control1, Srstdata);
262 delay(10);
263 WR(Control1, 0);
264 return 0;
265 }
266
267 static int
emmcinquiry(char * inquiry,int inqlen)268 emmcinquiry(char *inquiry, int inqlen)
269 {
270 u32int *r;
271 uint ver;
272
273 r = (u32int*)EMMCREGS;
274 ver = r[Slotisrver] >> 16;
275 return snprint(inquiry, inqlen,
276 "Arasan eMMC SD Host Controller %2.2x Version %2.2x",
277 ver&0xFF, ver>>8);
278 }
279
280 static void
emmcenable(void)281 emmcenable(void)
282 {
283 emmcclk(Initfreq);
284 WR(Irpten, 0);
285 WR(Irptmask, ~0);
286 WR(Interrupt, ~0);
287 intrenable(IRQmmc, mmcinterrupt, nil, 0, "mmc");
288 }
289
290 int
sdiocardintr(int wait)291 sdiocardintr(int wait)
292 {
293 u32int *r;
294 int i;
295
296 r = (u32int*)EMMCREGS;
297 WR(Interrupt, Cardintr);
298 while(((i = r[Interrupt]) & Cardintr) == 0){
299 if(!wait)
300 return 0;
301 WR(Irpten, r[Irpten] | Cardintr);
302 sleep(&emmc.cardr, cardintready, 0);
303 }
304 WR(Interrupt, Cardintr);
305 return i;
306 }
307
308 static int
emmccmd(u32int cmd,u32int arg,u32int * resp)309 emmccmd(u32int cmd, u32int arg, u32int *resp)
310 {
311 u32int *r;
312 u32int c;
313 int i;
314 ulong now;
315
316 r = (u32int*)EMMCREGS;
317 assert(cmd < nelem(cmdinfo) && cmdinfo[cmd] != 0);
318 c = (cmd << Indexshift) | cmdinfo[cmd];
319 /*
320 * CMD6 may be Setbuswidth or Switchfunc depending on Appcmd prefix
321 */
322 if(cmd == Switchfunc && !emmc.appcmd)
323 c |= Isdata|Card2host;
324 if(cmd == IORWextended){
325 if(arg & (1<<31))
326 c |= Host2card;
327 else
328 c |= Card2host;
329 if((r[Blksizecnt]&0xFFFF0000) != 0x10000)
330 c |= Multiblock | Blkcnten;
331 }
332 /*
333 * GoIdle indicates new card insertion: reset bus width & speed
334 */
335 if(cmd == GoIdle){
336 WR(Control0, r[Control0] & ~(Dwidth4|Hispeed));
337 emmcclk(Initfreq);
338 }
339 if(r[Status] & Cmdinhibit){
340 print("emmccmd: need to reset Cmdinhibit intr %ux stat %ux\n",
341 r[Interrupt], r[Status]);
342 WR(Control1, r[Control1] | Srstcmd);
343 while(r[Control1] & Srstcmd)
344 ;
345 while(r[Status] & Cmdinhibit)
346 ;
347 }
348 if((r[Status] & Datinhibit) &&
349 ((c & Isdata) || (c & Respmask) == Resp48busy)){
350 print("emmccmd: need to reset Datinhibit intr %ux stat %ux\n",
351 r[Interrupt], r[Status]);
352 WR(Control1, r[Control1] | Srstdata);
353 while(r[Control1] & Srstdata)
354 ;
355 while(r[Status] & Datinhibit)
356 ;
357 }
358 WR(Arg1, arg);
359 if((i = (r[Interrupt] & ~Cardintr)) != 0){
360 if(i != Cardinsert)
361 print("emmc: before command, intr was %ux\n", i);
362 WR(Interrupt, i);
363 }
364 WR(Cmdtm, c);
365 now = m->ticks;
366 while(((i=r[Interrupt])&(Cmddone|Err)) == 0)
367 if(m->ticks-now > HZ)
368 break;
369 if((i&(Cmddone|Err)) != Cmddone){
370 if((i&~(Err|Cardintr)) != Ctoerr)
371 print("emmc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, r[Status]);
372 WR(Interrupt, i);
373 if(r[Status]&Cmdinhibit){
374 WR(Control1, r[Control1]|Srstcmd);
375 while(r[Control1]&Srstcmd)
376 ;
377 }
378 error(Eio);
379 }
380 WR(Interrupt, i & ~(Datadone|Readrdy|Writerdy));
381 switch(c & Respmask){
382 case Resp136:
383 resp[0] = r[Resp0]<<8;
384 resp[1] = r[Resp0]>>24 | r[Resp1]<<8;
385 resp[2] = r[Resp1]>>24 | r[Resp2]<<8;
386 resp[3] = r[Resp2]>>24 | r[Resp3]<<8;
387 break;
388 case Resp48:
389 case Resp48busy:
390 resp[0] = r[Resp0];
391 break;
392 case Respnone:
393 resp[0] = 0;
394 break;
395 }
396 if((c & Respmask) == Resp48busy){
397 WR(Irpten, r[Irpten]|Datadone|Err);
398 tsleep(&emmc.r, datadone, 0, 3000);
399 i = r[Interrupt];
400 if((i & Datadone) == 0)
401 print("emmcio: no Datadone after CMD%d\n", cmd);
402 if(i & Err)
403 print("emmcio: CMD%d error interrupt %ux\n",
404 cmd, r[Interrupt]);
405 WR(Interrupt, i);
406 }
407 /*
408 * Once card is selected, use faster clock
409 */
410 if(cmd == MMCSelect){
411 delay(1);
412 emmcclk(SDfreq);
413 delay(1);
414 emmc.fastclock = 1;
415 }
416 if(cmd == Setbuswidth){
417 if(emmc.appcmd){
418 /*
419 * If card bus width changes, change host bus width
420 */
421 switch(arg){
422 case 0:
423 WR(Control0, r[Control0] & ~Dwidth4);
424 break;
425 case 2:
426 WR(Control0, r[Control0] | Dwidth4);
427 break;
428 }
429 }else{
430 /*
431 * If card switched into high speed mode, increase clock speed
432 */
433 if((arg&0x8000000F) == 0x80000001){
434 delay(1);
435 emmcclk(SDfreqhs);
436 delay(1);
437 }
438 }
439 }else if(cmd == IORWdirect && (arg & ~0xFF) == (1<<31|0<<28|7<<9)){
440 switch(arg & 0x3){
441 case 0:
442 WR(Control0, r[Control0] & ~Dwidth4);
443 break;
444 case 2:
445 WR(Control0, r[Control0] | Dwidth4);
446 //WR(Control0, r[Control0] | Hispeed);
447 break;
448 }
449 }
450 emmc.appcmd = (cmd == Appcmd);
451 return 0;
452 }
453
454 void
emmciosetup(int write,void * buf,int bsize,int bcount)455 emmciosetup(int write, void *buf, int bsize, int bcount)
456 {
457 USED(write);
458 USED(buf);
459 WR(Blksizecnt, bcount<<16 | bsize);
460 }
461
462 static void
emmcio(int write,uchar * buf,int len)463 emmcio(int write, uchar *buf, int len)
464 {
465 u32int *r;
466 int i;
467
468 r = (u32int*)EMMCREGS;
469 assert((len&3) == 0);
470 okay(1);
471 if(waserror()){
472 okay(0);
473 nexterror();
474 }
475 if(write)
476 dmastart(DmaChanEmmc, DmaDevEmmc, DmaM2D,
477 buf, &r[Data], len);
478 else
479 dmastart(DmaChanEmmc, DmaDevEmmc, DmaD2M,
480 &r[Data], buf, len);
481 if(dmawait(DmaChanEmmc) < 0)
482 error(Eio);
483 if(!write)
484 cachedinvse(buf, len);
485 WR(Irpten, r[Irpten]|Datadone|Err);
486 tsleep(&emmc.r, datadone, 0, 3000);
487 i = r[Interrupt]&~Cardintr;
488 if((i & Datadone) == 0){
489 print("emmcio: %d timeout intr %ux stat %ux\n",
490 write, i, r[Status]);
491 WR(Interrupt, i);
492 error(Eio);
493 }
494 if(i & Err){
495 print("emmcio: %d error intr %ux stat %ux\n",
496 write, r[Interrupt], r[Status]);
497 WR(Interrupt, i);
498 error(Eio);
499 }
500 if(i)
501 WR(Interrupt, i);
502 poperror();
503 okay(0);
504 }
505
506 static void
mmcinterrupt(Ureg *,void *)507 mmcinterrupt(Ureg*, void*)
508 {
509 u32int *r;
510 int i;
511
512 r = (u32int*)EMMCREGS;
513 i = r[Interrupt];
514 if(i&(Datadone|Err))
515 wakeup(&emmc.r);
516 if(i&Cardintr)
517 wakeup(&emmc.cardr);
518 WR(Irpten, r[Irpten] & ~i);
519 }
520
521 SDio sdio = {
522 "emmc",
523 emmcinit,
524 emmcenable,
525 emmcinquiry,
526 emmccmd,
527 emmciosetup,
528 emmcio,
529 };
530