4 * initially written for X230 Ricoh MMC controller.
5 * cmdinfo[] table stolen from bcm/emmc.c, thanks richard.
7 * for sdhc documentation see: https://www.sdcard.org/
10 #include "../port/lib.h"
11 #include "../port/error.h"
16 #include "../port/sd.h"
137 /* fake for cmdinfo */
139 Blkcnten = Mblk << 8,
140 Multiblock = Mcnt << 8,
141 Card2host = Mrd << 8,
142 Host2card = Mwr << 8,
148 [3] Resp48 | Ixchken | Crcchken,
149 [6] Resp48 | Ixchken | Crcchken,
150 [7] Resp48busy | Ixchken | Crcchken,
151 [8] Resp48 | Ixchken | Crcchken,
153 [12] Resp48busy | Ixchken | Crcchken,
154 [13] Resp48 | Ixchken | Crcchken,
156 [17] Resp48 | Isdata | Card2host | Ixchken | Crcchken,
157 [18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken,
158 [24] Resp48 | Isdata | Host2card | Ixchken | Crcchken,
159 [25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken,
161 [55] Resp48 | Ixchken | Crcchken,
164 typedef struct Ctlr Ctlr;
185 #define CR8(c, off) *((u8int*)(c->mmio + off))
186 #define CR16(c, off) *((u16int*)(c->mmio + off))
187 #define CR32(c, off) *((u32int*)(c->mmio + off))
190 mmcinterrupt(Ureg*, void *arg)
197 if((nis & Smask) == 0)
198 return; /* not for us */
200 CR16(c, Rnis) = nis; /* ack */
203 if((nis & Seint) != 0){
205 CR16(c, Reis) = eis; /* ack */
207 if((nis & Snint) != 0)
208 CR16(c, Rnie) |= Snint; /* ack */
209 if((nis & (Srem|Sins)) != 0)
211 c->waitsts |= nis | (eis << 16);
212 if((c->waitsts & c->waitmsk) != 0)
223 while((p = pcimatch(p, 0, 0)) != nil){
224 if(p->ccrb == 8 && p->ccru == 5)
226 if(p->vid == 0x1180){ /* Ricoh */
227 if(p->did == 0xe822) /* 5U822 SD/MMC */
229 if(p->did == 0xe823) /* 5U823 SD/MMC */
234 if(p == nil || p->mem[0].size < 256)
237 if(p->did == 0x1180 && p->vid == 0xe823){ /* Ricoh */
238 /* Enable SD2.0 mode. */
239 pcicfgw8(p, 0xf9, 0xfc);
240 pcicfgw8(p, 0x150, 0x10);
241 pcicfgw8(p, 0xf9, 0x00);
244 * Some SD/MMC cards don't work with the default base
245 * clock frequency of 200MHz. Lower it to 50Hz.
247 pcicfgw8(p, 0xfc, 0x01);
248 pcicfgw8(p, 0xe1, 50);
249 pcicfgw8(p, 0xfc, 0x00);
252 pmmc->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
253 if(pmmc->mmio == nil)
260 pmmcinquiry(char *inquiry, int inqlen)
262 return snprint(inquiry, inqlen, "MMC Host Controller");
266 softreset(Ctlr *c, int all)
272 for(i=10; i>=0; i--){
273 if((CR8(c, Rsrst) & m) == 0)
278 if(i < 0) iprint("mmc: didnt reset\n");
282 setpower(Ctlr *c, int on)
285 Vcap18 = 1<<26, Vset18 = 0x05,
286 Vcap30 = 1<<25, Vset30 = 0x06,
287 Vcap33 = 1<<24, Vset33 = 0x07,
297 CR8(c, Rpwr) = on ? ((v<<1) | 1) : 0;
301 setclkfreq(Ctlr *c, int khz)
303 u32int caps, intfreq;
307 CR16(c, Rclc) |= ~4; /* sd clock disable */
311 caps = CR32(c, Rcap);
312 intfreq = 1000*((caps >> 8) & 0x3f);
313 for(div = 1; div <= 256; div <<= 1){
314 if((intfreq / div) <= khz){
320 CR16(c, Rclc) = div<<8;
321 CR16(c, Rclc) |= 1; /* int clock enable */
322 for(i=1000; i>=0; i--){
323 if(CR16(c, Rclc) & 2) /* int clock stable */
327 if(i < 0) iprint("mmc: clock didnt stabilize\n");
328 CR16(c, Rclc) |= 4; /* sd clock enable */
337 CR16(c, Rnise) = 0; /* interrupts off */
340 c->waitmsk = c->waitsts = 0;
346 m = Srem | Sins | Srrdy | Swrdy | Sdint | Sbge | Strac | Scmdc;
348 CR16(c, Reie) = Emask;
350 CR16(c, Reise) = Emask;
363 return (c->waitsts & c->waitmsk) != 0;
367 intrwait(Ctlr *c, u32int mask, int tmo)
372 c->waitmsk = Seint | mask;
376 tsleep(&c->r, waitcond, c, 100);
379 mmcinterrupt(nil, c);
387 c->waitsts &= ~(status & mask);
388 if((status & mask) == 0 || (status & Seint) != 0){
389 /* abort command on timeout/error interrupt */
396 return status & mask;
409 intrenable(p->intl, mmcinterrupt, c, p->tbdf, "mmc");
413 pmmccmd(u32int cmd, u32int arg, u32int *resp)
419 if(cmd >= nelem(cmdinfo) || cmdinfo[cmd] == 0)
421 mode = cmdinfo[cmd] >> 8;
422 cmd = (cmd << 8) | (cmdinfo[cmd] & 0xFF);
428 if((CR32(c, Rpres) & Pcrdin) == 0)
432 if((cmd & Isdata) != 0 || (cmd & Respmask) == Resp48busy)
434 for(i=1000; (CR32(c, Rpres) & status) != 0 && i>=0; i--)
440 if((mode & (Mcnt|Mblk)) == (Mcnt|Mblk)){
441 CR16(c, Rbsize) = c->io.bsize;
442 CR16(c, Rbcount) = c->io.bcount;
445 CR16(c, Rmode) = mode;
449 if(!intrwait(c, Scmdc, 1000))
452 switch(cmd & Respmask){
454 resp[0] = CR32(c, Rresp0);
455 if(!intrwait(c, Strac, 3000))
459 resp[0] = CR32(c, Rresp0);
462 resp[0] = CR32(c, Rresp0)<<8;
463 resp[1] = CR32(c, Rresp0)>>24 | CR32(c, Rresp1)<<8;
464 resp[2] = CR32(c, Rresp1)>>24 | CR32(c, Rresp2)<<8;
465 resp[3] = CR32(c, Rresp2)>>24 | CR32(c, Rresp3)<<8;
473 if(cmd == 0x06){ /* buswidth */
488 pmmciosetup(int write, void *buf, int bsize, int bcount)
495 if(bsize == 0 || (bsize & 3) != 0)
500 c->io.bcount = bcount;
504 readblock(Ctlr *c, uchar *buf, int len)
506 for(len >>= 2; len > 0; len--){
507 *((u32int*)buf) = CR32(c, Rdat0);
513 writeblock(Ctlr *c, uchar *buf, int len)
515 for(len >>= 2; len > 0; len--){
516 CR32(c, Rdat0) = *((u32int*)buf);
522 pmmcio(int write, uchar *buf, int len)
528 if(len != c->io.bsize*c->io.bcount)
531 if(!intrwait(c, write ? Swrdy : Srrdy, 3000))
537 writeblock(c, buf, n);
539 readblock(c, buf, n);
543 if(!intrwait(c, Strac, 1000))