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/pci.h"
17 #include "../port/sd.h"
138 /* fake for cmdinfo */
140 Blkcnten = Mblk << 8,
141 Multiblock = Mcnt << 8,
142 Card2host = Mrd << 8,
143 Host2card = Mwr << 8,
146 static int cmdinfo[64] = {
149 [3] Resp48 | Ixchken | Crcchken,
150 [6] Resp48 | Ixchken | Crcchken,
151 [7] Resp48busy | Ixchken | Crcchken,
152 [8] Resp48 | Ixchken | Crcchken,
154 [12] Resp48busy | Ixchken | Crcchken,
155 [13] Resp48 | Ixchken | Crcchken,
157 [17] Resp48 | Isdata | Card2host | Ixchken | Crcchken,
158 [18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken,
159 [24] Resp48 | Isdata | Host2card | Ixchken | Crcchken,
160 [25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken,
162 [55] Resp48 | Ixchken | Crcchken,
165 typedef struct Ctlr Ctlr;
186 #define CR8(c, off) *((u8int*)(c->mmio + off))
187 #define CR16(c, off) *((u16int*)(c->mmio + off))
188 #define CR32(c, off) *((u32int*)(c->mmio + off))
191 mmcinterrupt(Ureg*, void *arg)
198 if((nis & Smask) == 0)
199 return; /* not for us */
201 CR16(c, Rnis) = nis; /* ack */
204 if((nis & Seint) != 0){
206 CR16(c, Reis) = eis; /* ack */
208 if((nis & Snint) != 0)
209 CR16(c, Rnie) |= Snint; /* ack */
210 if((nis & (Srem|Sins)) != 0)
212 c->waitsts |= nis | (eis << 16);
213 if((c->waitsts & c->waitmsk) != 0)
224 while((p = pcimatch(p, 0, 0)) != nil){
225 if(p->ccrb == 8 && p->ccru == 5)
227 if(p->vid == 0x1180){ /* Ricoh */
228 if(p->did == 0xe822) /* 5U822 SD/MMC */
230 if(p->did == 0xe823) /* 5U823 SD/MMC */
235 if(p == nil || p->mem[0].size < 256 || (p->mem[0].bar & 1) != 0)
238 pmmc->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
239 if(pmmc->mmio == nil)
245 if(p->did == 0x1180 && p->vid == 0xe823){ /* Ricoh */
246 /* Enable SD2.0 mode. */
247 pcicfgw8(p, 0xf9, 0xfc);
248 pcicfgw8(p, 0x150, 0x10);
249 pcicfgw8(p, 0xf9, 0x00);
252 * Some SD/MMC cards don't work with the default base
253 * clock frequency of 200MHz. Lower it to 50Hz.
255 pcicfgw8(p, 0xfc, 0x01);
256 pcicfgw8(p, 0xe1, 50);
257 pcicfgw8(p, 0xfc, 0x00);
264 pmmcinquiry(char *inquiry, int inqlen)
266 return snprint(inquiry, inqlen, "MMC Host Controller");
270 softreset(Ctlr *c, int all)
276 for(i=10; i>=0; i--){
277 if((CR8(c, Rsrst) & m) == 0)
282 if(i < 0) iprint("mmc: didnt reset\n");
286 setpower(Ctlr *c, int on)
289 Vcap18 = 1<<26, Vset18 = 0x05,
290 Vcap30 = 1<<25, Vset30 = 0x06,
291 Vcap33 = 1<<24, Vset33 = 0x07,
301 CR8(c, Rpwr) = on ? ((v<<1) | 1) : 0;
305 setclkfreq(Ctlr *c, int khz)
307 u32int caps, intfreq;
311 CR16(c, Rclc) |= ~4; /* sd clock disable */
315 caps = CR32(c, Rcap);
316 intfreq = 1000*((caps >> 8) & 0x3f);
317 for(div = 1; div <= 256; div <<= 1){
318 if((intfreq / div) <= khz){
324 CR16(c, Rclc) = div<<8;
325 CR16(c, Rclc) |= 1; /* int clock enable */
326 for(i=1000; i>=0; i--){
327 if(CR16(c, Rclc) & 2) /* int clock stable */
331 if(i < 0) iprint("mmc: clock didnt stabilize\n");
332 CR16(c, Rclc) |= 4; /* sd clock enable */
341 CR16(c, Rnise) = 0; /* interrupts off */
344 c->waitmsk = c->waitsts = 0;
350 m = Srem | Sins | Srrdy | Swrdy | Sdint | Sbge | Strac | Scmdc;
352 CR16(c, Reie) = Emask;
354 CR16(c, Reise) = Emask;
367 return (c->waitsts & c->waitmsk) != 0;
371 intrwait(Ctlr *c, u32int mask, int tmo)
376 c->waitmsk = Seint | mask;
380 tsleep(&c->r, waitcond, c, 100);
383 mmcinterrupt(nil, c);
391 c->waitsts &= ~(status & mask);
392 if((status & mask) == 0 || (status & Seint) != 0){
393 /* abort command on timeout/error interrupt */
400 return status & mask;
413 intrenable(p->intl, mmcinterrupt, c, p->tbdf, "mmc");
417 pmmccmd(u32int cmd, u32int arg, u32int *resp)
423 if(cmd >= nelem(cmdinfo) || cmdinfo[cmd] == 0)
425 mode = cmdinfo[cmd] >> 8;
426 cmd = (cmd << 8) | (cmdinfo[cmd] & 0xFF);
432 if((CR32(c, Rpres) & Pcrdin) == 0)
436 if((cmd & Isdata) != 0 || (cmd & Respmask) == Resp48busy)
438 for(i=1000; (CR32(c, Rpres) & status) != 0 && i>=0; i--)
444 if((mode & (Mcnt|Mblk)) == (Mcnt|Mblk)){
445 CR16(c, Rbsize) = c->io.bsize;
446 CR16(c, Rbcount) = c->io.bcount;
449 CR16(c, Rmode) = mode;
453 if(!intrwait(c, Scmdc, 1000))
456 switch(cmd & Respmask){
458 resp[0] = CR32(c, Rresp0);
459 if(!intrwait(c, Strac, 3000))
463 resp[0] = CR32(c, Rresp0);
466 resp[0] = CR32(c, Rresp0)<<8;
467 resp[1] = CR32(c, Rresp0)>>24 | CR32(c, Rresp1)<<8;
468 resp[2] = CR32(c, Rresp1)>>24 | CR32(c, Rresp2)<<8;
469 resp[3] = CR32(c, Rresp2)>>24 | CR32(c, Rresp3)<<8;
477 if(cmd == 0x06){ /* buswidth */
492 pmmciosetup(int write, void *buf, int bsize, int bcount)
499 if(bsize == 0 || (bsize & 3) != 0)
504 c->io.bcount = bcount;
508 readblock(Ctlr *c, uchar *buf, int len)
510 for(len >>= 2; len > 0; len--){
511 *((u32int*)buf) = CR32(c, Rdat0);
517 writeblock(Ctlr *c, uchar *buf, int len)
519 for(len >>= 2; len > 0; len--){
520 CR32(c, Rdat0) = *((u32int*)buf);
526 pmmcio(int write, uchar *buf, int len)
532 if(len != c->io.bsize*c->io.bcount)
535 if(!intrwait(c, write ? Swrdy : Srrdy, 3000))
541 writeblock(c, buf, n);
543 readblock(c, buf, n);
547 if(!intrwait(c, Strac, 1000))