diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-12-11 19:08:52 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-12-11 19:08:52 +0000 |
commit | b818f48f41895754dd9b470be407ba85cfea45bd (patch) | |
tree | 0cebbe57cc9dce2e617cc9b1f75660b9ddf48880 | |
parent | 2d0ede468ddd363243fd31580e3e86c39b51f7be (diff) |
sdmmc: multiple controller support
remove the global sdio struct and add a addmmcio() function
for drivers to register their controllers.
there is a SDio.aux pointer now where controller drivers
can stash a pointer to their private data.
SDio.init() also can signal that it wants to be called
again for more controllers by returning > 0 (see pc/pmmc.c).
this is in preparation for supporting the internal mmc
device in the mnt-reform which is hooked up to usdhc1.
-rw-r--r-- | sys/src/9/bcm/emmc.c | 37 | ||||
-rw-r--r-- | sys/src/9/bcm/pi | 1 | ||||
-rw-r--r-- | sys/src/9/bcm/pi2 | 1 | ||||
-rw-r--r-- | sys/src/9/bcm64/pi3 | 1 | ||||
-rw-r--r-- | sys/src/9/bcm64/pi4 | 1 | ||||
-rw-r--r-- | sys/src/9/bcm64/sdhc.c | 121 | ||||
-rw-r--r-- | sys/src/9/imx8/reform | 1 | ||||
-rw-r--r-- | sys/src/9/imx8/usdhc.c | 285 | ||||
-rw-r--r-- | sys/src/9/pc/pc | 2 | ||||
-rw-r--r-- | sys/src/9/pc/pmmc.c | 84 | ||||
-rw-r--r-- | sys/src/9/pc64/pc64 | 2 | ||||
-rw-r--r-- | sys/src/9/port/sd.h | 15 | ||||
-rw-r--r-- | sys/src/9/port/sdmmc.c | 225 | ||||
-rw-r--r-- | sys/src/9/zynq/emmc.c | 37 | ||||
-rw-r--r-- | sys/src/9/zynq/zynq | 1 |
15 files changed, 464 insertions, 350 deletions
diff --git a/sys/src/9/bcm/emmc.c b/sys/src/9/bcm/emmc.c index 84cad4cc6..a505b155b 100644 --- a/sys/src/9/bcm/emmc.c +++ b/sys/src/9/bcm/emmc.c @@ -240,7 +240,7 @@ cardintready(void*) } static int -emmcinit(void) +emmcinit(SDio*) { u32int *r; ulong clk; @@ -265,7 +265,7 @@ emmcinit(void) } static int -emmcinquiry(char *inquiry, int inqlen) +emmcinquiry(SDio*, char *inquiry, int inqlen) { u32int *r; uint ver; @@ -278,7 +278,7 @@ emmcinquiry(char *inquiry, int inqlen) } static void -emmcenable(void) +emmcenable(SDio*) { emmcclk(Initfreq); WR(Irpten, 0); @@ -288,7 +288,7 @@ emmcenable(void) } static int -emmccmd(u32int cmd, u32int arg, u32int *resp) +emmccmd(SDio*, u32int cmd, u32int arg, u32int *resp) { u32int *r; u32int c; @@ -435,7 +435,7 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) } static void -emmciosetup(int write, void *buf, int bsize, int bcount) +emmciosetup(SDio*, int write, void *buf, int bsize, int bcount) { USED(write); USED(buf); @@ -443,7 +443,7 @@ emmciosetup(int write, void *buf, int bsize, int bcount) } static void -emmcio(int write, uchar *buf, int len) +emmcio(SDio*, int write, uchar *buf, int len) { u32int *r; int i; @@ -497,13 +497,18 @@ mmcinterrupt(Ureg*, void*) WR(Irpten, r[Irpten] & ~i); } -SDio sdio = { - "emmc", - emmcinit, - emmcenable, - emmcinquiry, - emmccmd, - emmciosetup, - emmcio, - .highspeed = 1, -}; +void +emmclink(void) +{ + static SDio io = { + "emmc", + emmcinit, + emmcenable, + emmcinquiry, + emmccmd, + emmciosetup, + emmcio, + .highspeed = 1, + }; + addmmcio(&io); +} diff --git a/sys/src/9/bcm/pi b/sys/src/9/bcm/pi index 105c8e4ae..44ef83aba 100644 --- a/sys/src/9/bcm/pi +++ b/sys/src/9/bcm/pi @@ -28,6 +28,7 @@ link ethermedium loopbackmedium netdevmedium + emmc ip tcp diff --git a/sys/src/9/bcm/pi2 b/sys/src/9/bcm/pi2 index 73d1d5f30..acdd10f13 100644 --- a/sys/src/9/bcm/pi2 +++ b/sys/src/9/bcm/pi2 @@ -28,6 +28,7 @@ link ethermedium loopbackmedium netdevmedium + emmc ip tcp diff --git a/sys/src/9/bcm64/pi3 b/sys/src/9/bcm64/pi3 index e1cbaa6aa..285131eb6 100644 --- a/sys/src/9/bcm64/pi3 +++ b/sys/src/9/bcm64/pi3 @@ -29,6 +29,7 @@ link ethermedium loopbackmedium netdevmedium + emmc ip tcp diff --git a/sys/src/9/bcm64/pi4 b/sys/src/9/bcm64/pi4 index ace3a182f..84baa57fc 100644 --- a/sys/src/9/bcm64/pi4 +++ b/sys/src/9/bcm64/pi4 @@ -34,6 +34,7 @@ link ethermedium loopbackmedium netdevmedium + sdhc ip tcp diff --git a/sys/src/9/bcm64/sdhc.c b/sys/src/9/bcm64/sdhc.c index 48426ff7b..214de6083 100644 --- a/sys/src/9/bcm64/sdhc.c +++ b/sys/src/9/bcm64/sdhc.c @@ -15,7 +15,7 @@ #include "io.h" #include "../port/sd.h" -#define EMMCREGS (VIRTIO+0x340000) +#define SDHCREGS (VIRTIO+0x340000) enum { Extfreq = 100*Mhz, /* guess external clock frequency if */ @@ -206,14 +206,14 @@ struct Ctlr { uintptr busdram; }; -static Ctlr emmc; +static Ctlr sdhc; static void mmcinterrupt(Ureg*, void*); static void WR(int reg, u32int val) { - u32int *r = (u32int*)EMMCREGS; + u32int *r = (u32int*)SDHCREGS; if(0)print("WR %2.2ux %ux\n", reg<<2, val); coherence(); @@ -247,7 +247,7 @@ dmaalloc(void *addr, int len) p->desc |= len<<OLength | End | Int; else p->desc |= Maxdma<<OLength; - p->addr = emmc.busdram + (PADDR(a) - PHYSDRAM); + p->addr = sdhc.busdram + (PADDR(a) - PHYSDRAM); a += Maxdma; len -= Maxdma; n--; @@ -257,15 +257,15 @@ dmaalloc(void *addr, int len) } static void -emmcclk(uint freq) +sdhcclk(uint freq) { u32int *r; uint div; int i; - r = (u32int*)EMMCREGS; - div = emmc.extclk / (freq<<1); - if(emmc.extclk / (div<<1) > freq) + r = (u32int*)SDHCREGS; + div = sdhc.extclk / (freq<<1); + if(sdhc.extclk / (div<<1) > freq) div++; WR(Control1, clkdiv(div) | DTO<<Datatoshift | Clkgendiv | Clken | Clkintlen); @@ -275,7 +275,7 @@ emmcclk(uint freq) break; } if(i == 1000) - print("emmc: can't set clock to %ud\n", freq); + print("sdhc: can't set clock to %ud\n", freq); } static int @@ -283,29 +283,29 @@ datadone(void*) { int i; - u32int *r = (u32int*)EMMCREGS; + u32int *r = (u32int*)SDHCREGS; i = r[Interrupt]; return i & (Datadone|Err); } static int -emmcinit(void) +sdhcinit(SDio *io) { u32int *r; ulong clk; char *s; - emmc.busdram = soc.busdram; + sdhc.busdram = soc.busdram; if((s = getconf("*emmc2bus")) != nil) - emmc.busdram = strtoull(s, nil, 16); + sdhc.busdram = strtoull(s, nil, 16); clk = getclkrate(ClkEmmc2); if(clk == 0){ clk = Extfreq; - print("emmc: assuming external clock %lud Mhz\n", clk/1000000); + print("%s: assuming external clock %lud Mhz\n", io->name, clk/1000000); } - emmc.extclk = clk; - r = (u32int*)EMMCREGS; - if(0)print("emmc control %8.8ux %8.8ux %8.8ux\n", + sdhc.extclk = clk; + r = (u32int*)SDHCREGS; + if(0)print("sdhc control %8.8ux %8.8ux %8.8ux\n", r[Control0], r[Control1], r[Control2]); WR(Control1, Srsthc); delay(10); @@ -318,12 +318,12 @@ emmcinit(void) } static int -emmcinquiry(char *inquiry, int inqlen) +sdhcinquiry(SDio *, char *inquiry, int inqlen) { u32int *r; uint ver; - r = (u32int*)EMMCREGS; + r = (u32int*)SDHCREGS; ver = r[Slotisrver] >> 16; return snprint(inquiry, inqlen, "BCM SD Host Controller %2.2x Version %2.2x", @@ -331,7 +331,7 @@ emmcinquiry(char *inquiry, int inqlen) } static void -emmcenable(void) +sdhcenable(SDio *io) { WR(Control0, 0); @@ -339,28 +339,28 @@ emmcenable(void) WR(Control0, V3_3 | Buspower | Dwidth1 | DmaADMA2); WR(Control1, 0); delay(1); - emmcclk(Initfreq); + sdhcclk(Initfreq); WR(Irpten, 0); WR(Irptmask, ~(Cardintr|Dmaintr)); WR(Interrupt, ~0); - intrenable(IRQmmc, mmcinterrupt, nil, BUSUNKNOWN, "sdhc"); + intrenable(IRQmmc, mmcinterrupt, nil, BUSUNKNOWN, io->name); } static int -emmccmd(u32int cmd, u32int arg, u32int *resp) +sdhccmd(SDio*, u32int cmd, u32int arg, u32int *resp) { u32int *r; u32int c; int i; ulong now; - r = (u32int*)EMMCREGS; + r = (u32int*)SDHCREGS; assert(cmd < nelem(cmdinfo) && cmdinfo[cmd] != 0); c = (cmd << Indexshift) | cmdinfo[cmd]; /* * CMD6 may be Setbuswidth or Switchfunc depending on Appcmd prefix */ - if(cmd == Switchfunc && !emmc.appcmd) + if(cmd == Switchfunc && !sdhc.appcmd) c |= Isdata|Card2host; if(c & Isdata) c |= Dmaen; @@ -377,10 +377,10 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) */ if(cmd == GoIdle){ WR(Control0, r[Control0] & ~(Dwidth4|Hispeed)); - emmcclk(Initfreq); + sdhcclk(Initfreq); } if(r[Status] & Cmdinhibit){ - print("emmccmd: need to reset Cmdinhibit intr %ux stat %ux\n", + print("sdhccmd: need to reset Cmdinhibit intr %ux stat %ux\n", r[Interrupt], r[Status]); WR(Control1, r[Control1] | Srstcmd); while(r[Control1] & Srstcmd) @@ -390,7 +390,7 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) } if((r[Status] & Datinhibit) && ((c & Isdata) || (c & Respmask) == Resp48busy)){ - print("emmccmd: need to reset Datinhibit intr %ux stat %ux\n", + print("sdhccmd: need to reset Datinhibit intr %ux stat %ux\n", r[Interrupt], r[Status]); WR(Control1, r[Control1] | Srstdata); while(r[Control1] & Srstdata) @@ -401,7 +401,7 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) WR(Arg1, arg); if((i = (r[Interrupt] & ~Cardintr)) != 0){ if(i != Cardinsert) - print("emmc: before command, intr was %ux\n", i); + print("sdhc: before command, intr was %ux\n", i); WR(Interrupt, i); } WR(Cmdtm, c); @@ -411,7 +411,7 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) break; if((i&(Cmddone|Err)) != Cmddone){ if((i&~(Err|Cardintr)) != Ctoerr) - print("emmc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, r[Status]); + print("sdhc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, r[Status]); WR(Interrupt, i); if(r[Status]&Cmdinhibit){ WR(Control1, r[Control1]|Srstcmd); @@ -438,12 +438,12 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) } if((c & Respmask) == Resp48busy){ WR(Irpten, r[Irpten]|Datadone|Err); - tsleep(&emmc.r, datadone, 0, 3000); + tsleep(&sdhc.r, datadone, 0, 3000); i = r[Interrupt]; if((i & Datadone) == 0) - print("emmcio: no Datadone after CMD%d\n", cmd); + print("sdhcio: no Datadone after CMD%d\n", cmd); if(i & Err) - print("emmcio: CMD%d error interrupt %ux\n", + print("sdhcio: CMD%d error interrupt %ux\n", cmd, r[Interrupt]); WR(Interrupt, i); } @@ -452,12 +452,12 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) */ if(cmd == MMCSelect){ delay(1); - emmcclk(SDfreq); + sdhcclk(SDfreq); delay(1); - emmc.fastclock = 1; + sdhc.fastclock = 1; } if(cmd == Setbuswidth){ - if(emmc.appcmd){ + if(sdhc.appcmd){ /* * If card bus width changes, change host bus width */ @@ -475,7 +475,7 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) */ if((arg&0x8000000F) == 0x80000001){ delay(1); - emmcclk(SDfreqhs); + sdhcclk(SDfreqhs); delay(1); } } @@ -490,12 +490,12 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) break; } } - emmc.appcmd = (cmd == Appcmd); + sdhc.appcmd = (cmd == Appcmd); return 0; } static void -emmciosetup(int write, void *buf, int bsize, int bcount) +sdhciosetup(SDio*, int write, void *buf, int bsize, int bcount) { int len; @@ -504,30 +504,30 @@ emmciosetup(int write, void *buf, int bsize, int bcount) assert((len&3) == 0); assert(bsize <= 2048); WR(Blksizecnt, bcount<<16 | bsize); - if(emmc.dma) - sdfree(emmc.dma); - emmc.dma = dmaalloc(buf, len); + if(sdhc.dma) + sdfree(sdhc.dma); + sdhc.dma = dmaalloc(buf, len); if(write) cachedwbse(buf, len); else cachedwbinvse(buf, len); - WR(Dmadesc, emmc.busdram + (PADDR(emmc.dma) - PHYSDRAM)); + WR(Dmadesc, sdhc.busdram + (PADDR(sdhc.dma) - PHYSDRAM)); okay(1); } static void -emmcio(int write, uchar *buf, int len) +sdhcio(SDio*, int write, uchar *buf, int len) { u32int *r; int i; - r = (u32int*)EMMCREGS; + r = (u32int*)SDHCREGS; if(waserror()){ okay(0); nexterror(); } WR(Irpten, r[Irpten] | Datadone|Err); - tsleep(&emmc.r, datadone, 0, 3000); + tsleep(&sdhc.r, datadone, 0, 3000); WR(Irpten, r[Irpten] & ~(Datadone|Err)); i = r[Interrupt]; if((i & (Datadone|Err)) != Datadone){ @@ -549,20 +549,25 @@ mmcinterrupt(Ureg*, void*) u32int *r; int i; - r = (u32int*)EMMCREGS; + r = (u32int*)SDHCREGS; i = r[Interrupt]; if(i&(Datadone|Err)) - wakeup(&emmc.r); + wakeup(&sdhc.r); WR(Irpten, r[Irpten] & ~i); } -SDio sdio = { - "sdhc", - emmcinit, - emmcenable, - emmcinquiry, - emmccmd, - emmciosetup, - emmcio, - .highspeed = 1, -}; +void +sdhclink(void) +{ + static SDio io = { + "sdhc", + sdhcinit, + sdhcenable, + sdhcinquiry, + sdhccmd, + sdhciosetup, + sdhcio, + .highspeed = 1, + }; + addmmcio(&io); +} diff --git a/sys/src/9/imx8/reform b/sys/src/9/imx8/reform index c5899f890..11d591534 100644 --- a/sys/src/9/imx8/reform +++ b/sys/src/9/imx8/reform @@ -34,6 +34,7 @@ link i2cimx devi2c pciimx pci sai + usdhc ip tcp diff --git a/sys/src/9/imx8/usdhc.c b/sys/src/9/imx8/usdhc.c index 8954ba8b9..c8c482bdb 100644 --- a/sys/src/9/imx8/usdhc.c +++ b/sys/src/9/imx8/usdhc.c @@ -190,26 +190,27 @@ enum { }; struct Ctlr { - Rendez r; + u32int *regs; + int irq; + int fastclock; uint extclk; int appcmd; Adma *dma; -}; -static Ctlr usdhc; + Rendez r; +}; static void usdhcinterrupt(Ureg*, void*); -static u32int *regs = (u32int*)(VIRTIO+0xB50000); /* USDHC2 */ -#define RR(reg) (regs[reg]) +#define RR(ctlr, reg) ((ctlr)->regs[reg]) static void -WR(int reg, u32int val) +WR(Ctlr *ctlr, int reg, u32int val) { if(0)print("WR %2.2ux %ux\n", reg<<2, val); coherence(); - regs[reg] = val; + ctlr->regs[reg] = val; } static Adma* @@ -237,9 +238,9 @@ dmaalloc(void *addr, int len) } static void -usdhcclk(uint freq) +usdhcclk(Ctlr *ctlr, uint freq) { - uint pre_div = 1, post_div = 1, clk = usdhc.extclk; + uint pre_div = 1, post_div = 1, clk = ctlr->extclk; while(clk / (pre_div * 16) > freq && pre_div < 256) pre_div <<= 1; @@ -247,23 +248,53 @@ usdhcclk(uint freq) while(clk / (pre_div * post_div) > freq && post_div < 16) post_div++; - WR(Vendorspec, RR(Vendorspec) & ~ClkEn); - WR(Control1, (pre_div>>1)<<SDCLKFSshift | (post_div-1)<<DVSshift | DTO<<Datatoshift); + WR(ctlr, Vendorspec, RR(ctlr, Vendorspec) & ~ClkEn); + WR(ctlr, Control1, (pre_div>>1)<<SDCLKFSshift | (post_div-1)<<DVSshift | DTO<<Datatoshift); delay(10); - WR(Vendorspec, RR(Vendorspec) | ClkEn | PerEn); - while((RR(Status) & Clkstable) == 0) + WR(ctlr, Vendorspec, RR(ctlr, Vendorspec) | ClkEn | PerEn); + while((RR(ctlr, Status) & Clkstable) == 0) ; } static int -datadone(void*) +datadone(void *arg) { - return RR(Interrupt) & (Datadone|Err); + Ctlr *ctlr = arg; + return RR(ctlr, Interrupt) & (Datadone|Err); +} + +static void +usdhcreset(Ctlr *ctlr) +{ + if(0)print("usdhc control %8.8ux %8.8ux %8.8ux\n", + RR(ctlr, Control0), RR(ctlr, Control1), RR(ctlr, Control2)); + + WR(ctlr, Control1, Srsthc); + delay(10); + while(RR(ctlr, Control1) & Srsthc) + ; + WR(ctlr, Control1, Srstdata); + delay(10); + WR(ctlr, Control1, 0); } static int -usdhcinit(void) +usdhc1init(SDio *) { + /* TODO */ + return -1; +} + +static int +usdhc2init(SDio *io) +{ + static Ctlr ctlr[1] = { + .regs = (u32int*)(VIRTIO+0xB50000), /* USDHC2 */ + .irq = IRQusdhc2, + }; + + io->aux = ctlr; + iomuxpad("pad_sd2_clk", "usdhc2_clk", "~LVTTL ~HYS ~PUE ~ODE SLOW 75_OHM"); iomuxpad("pad_sd2_cmd", "usdhc2_cmd", "~LVTTL HYS PUE ~ODE SLOW 75_OHM"); iomuxpad("pad_sd2_data0", "usdhc2_data0", "~LVTTL HYS PUE ~ODE SLOW 75_OHM"); @@ -277,51 +308,46 @@ usdhcinit(void) setclkgate("usdhc2.ipg_clk_perclk", 1); setclkgate("usdhc2.ipg_clk", 1); - usdhc.extclk = getclkrate("usdhc2.ipg_clk_perclk"); - if(usdhc.extclk <= 0){ - print("usdhc: usdhc2.ipg_clk_perclk not enabled\n"); + ctlr->extclk = getclkrate("usdhc2.ipg_clk_perclk"); + if(ctlr->extclk <= 0){ + print("%s: usdhc2.ipg_clk_perclk not enabled\n", io->name); return -1; } - if(0)print("usdhc control %8.8ux %8.8ux %8.8ux\n", - RR(Control0), RR(Control1), RR(Control2)); + usdhcreset(ctlr); - WR(Control1, Srsthc); - delay(10); - while(RR(Control1) & Srsthc) - ; - WR(Control1, Srstdata); - delay(10); - WR(Control1, 0); return 0; } static int -usdhcinquiry(char *inquiry, int inqlen) +usdhcinquiry(SDio*, char *inquiry, int inqlen) { return snprint(inquiry, inqlen, "USDHC Host Controller"); } static void -usdhcenable(void) +usdhcenable(SDio *io) { - WR(Control0, 0); + Ctlr *ctlr = io->aux; + + WR(ctlr, Control0, 0); delay(1); - WR(Vendorspec, RR(Vendorspec) & ~Vsel); - WR(Control0, LE | Dwidth1 | DmaADMA2); - WR(Control1, 0); + WR(ctlr, Vendorspec, RR(ctlr, Vendorspec) & ~Vsel); + WR(ctlr, Control0, LE | Dwidth1 | DmaADMA2); + WR(ctlr, Control1, 0); delay(1); - WR(Vendorspec, RR(Vendorspec) | HclkEn | IpgEn); - usdhcclk(Initfreq); - WR(Irpten, 0); - WR(Irptmask, ~(Cardintr|Dmaintr)); - WR(Interrupt, ~0); - intrenable(IRQusdhc2, usdhcinterrupt, nil, BUSUNKNOWN, "usdhc2"); + WR(ctlr, Vendorspec, RR(ctlr, Vendorspec) | HclkEn | IpgEn); + usdhcclk(ctlr, Initfreq); + WR(ctlr, Irpten, 0); + WR(ctlr, Irptmask, ~(Cardintr|Dmaintr)); + WR(ctlr, Interrupt, ~0); + intrenable(ctlr->irq, usdhcinterrupt, ctlr, BUSUNKNOWN, io->name); } static int -usdhccmd(u32int cmd, u32int arg, u32int *resp) +usdhccmd(SDio *io, u32int cmd, u32int arg, u32int *resp) { + Ctlr *ctlr = io->aux; u32int c; int i; ulong now; @@ -335,7 +361,7 @@ usdhccmd(u32int cmd, u32int arg, u32int *resp) /* * CMD6 may be Setbuswidth or Switchfunc depending on Appcmd prefix */ - if(cmd == Switchfunc && !usdhc.appcmd) + if(cmd == Switchfunc && !ctlr->appcmd) c |= Isdata|Card2host; if(c & Isdata) c |= Dmaen; @@ -344,106 +370,106 @@ usdhccmd(u32int cmd, u32int arg, u32int *resp) c |= Host2card; else c |= Card2host; - if((RR(Blksizecnt)&0xFFFF0000) != 0x10000) + if((RR(ctlr, Blksizecnt)&0xFFFF0000) != 0x10000) c |= Multiblock | Blkcnten; } /* * GoIdle indicates new card insertion: reset bus width & speed */ if(cmd == GoIdle){ - WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth1); - usdhcclk(Initfreq); + WR(ctlr, Control0, (RR(ctlr, Control0) & ~DwidthMask) | Dwidth1); + usdhcclk(ctlr, Initfreq); } - if(RR(Status) & Cmdinhibit){ + if(RR(ctlr, Status) & Cmdinhibit){ print("usdhccmd: need to reset Cmdinhibit intr %ux stat %ux\n", - RR(Interrupt), RR(Status)); - WR(Control1, RR(Control1) | Srstcmd); - while(RR(Control1) & Srstcmd) + RR(ctlr, Interrupt), RR(ctlr, Status)); + WR(ctlr, Control1, RR(ctlr, Control1) | Srstcmd); + while(RR(ctlr, Control1) & Srstcmd) ; - while(RR(Status) & Cmdinhibit) + while(RR(ctlr, Status) & Cmdinhibit) ; } - if((RR(Status) & Datinhibit) && + if((RR(ctlr, Status) & Datinhibit) && ((c & Isdata) || (c & Respmask) == Resp48busy)){ print("usdhccmd: need to reset Datinhibit intr %ux stat %ux\n", - RR(Interrupt), RR(Status)); - WR(Control1, RR(Control1) | Srstdata); - while(RR(Control1) & Srstdata) + RR(ctlr, Interrupt), RR(ctlr, Status)); + WR(ctlr, Control1, RR(ctlr, Control1) | Srstdata); + while(RR(ctlr, Control1) & Srstdata) ; - while(RR(Status) & Datinhibit) + while(RR(ctlr, Status) & Datinhibit) ; } - while(RR(Status) & Datactive) + while(RR(ctlr, Status) & Datactive) ; - WR(Arg1, arg); - if((i = (RR(Interrupt) & ~Cardintr)) != 0){ + WR(ctlr, Arg1, arg); + if((i = (RR(ctlr, Interrupt) & ~Cardintr)) != 0){ if(i != Cardinsert) - print("usdhc: before command, intr was %ux\n", i); - WR(Interrupt, i); + print("usdhccmd: before command, intr was %ux\n", i); + WR(ctlr, Interrupt, i); } - WR(Mixctrl, (RR(Mixctrl) & ~MixCmdMask) | (c & MixCmdMask)); - WR(Cmdtm, c & ~0xFFFF); + WR(ctlr, Mixctrl, (RR(ctlr, Mixctrl) & ~MixCmdMask) | (c & MixCmdMask)); + WR(ctlr, Cmdtm, c & ~0xFFFF); now = MACHP(0)->ticks; - while(((i=RR(Interrupt))&(Cmddone|Err)) == 0) + while(((i=RR(ctlr, Interrupt))&(Cmddone|Err)) == 0) if(MACHP(0)->ticks - now > HZ) break; if((i&(Cmddone|Err)) != Cmddone){ if((i&~(Err|Cardintr)) != Ctoerr) - print("usdhc: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, RR(Status)); - WR(Interrupt, i); - if(RR(Status)&Cmdinhibit){ - WR(Control1, RR(Control1)|Srstcmd); - while(RR(Control1)&Srstcmd) + print("usdhccmd: cmd %ux arg %ux error intr %ux stat %ux\n", c, arg, i, RR(ctlr, Status)); + WR(ctlr, Interrupt, i); + if(RR(ctlr, Status)&Cmdinhibit){ + WR(ctlr, Control1, RR(ctlr, Control1)|Srstcmd); + while(RR(ctlr, Control1)&Srstcmd) ; } error(Eio); } - WR(Interrupt, i & ~(Datadone|Readrdy|Writerdy)); + WR(ctlr, Interrupt, i & ~(Datadone|Readrdy|Writerdy)); switch(c & Respmask){ case Resp136: - resp[0] = RR(Resp0)<<8; - resp[1] = RR(Resp0)>>24 | RR(Resp1)<<8; - resp[2] = RR(Resp1)>>24 | RR(Resp2)<<8; - resp[3] = RR(Resp2)>>24 | RR(Resp3)<<8; + resp[0] = RR(ctlr, Resp0)<<8; + resp[1] = RR(ctlr, Resp0)>>24 | RR(ctlr, Resp1)<<8; + resp[2] = RR(ctlr, Resp1)>>24 | RR(ctlr, Resp2)<<8; + resp[3] = RR(ctlr, Resp2)>>24 | RR(ctlr, Resp3)<<8; break; case Resp48: case Resp48busy: - resp[0] = RR(Resp0); + resp[0] = RR(ctlr, Resp0); break; case Respnone: resp[0] = 0; break; } if((c & Respmask) == Resp48busy){ - WR(Irpten, RR(Irpten)|Datadone|Err); - tsleep(&usdhc.r, datadone, 0, 1000); - i = RR(Interrupt); + WR(ctlr, Irpten, RR(ctlr, Irpten)|Datadone|Err); + tsleep(&ctlr->r, datadone, ctlr, 1000); + i = RR(ctlr, Interrupt); if((i & Datadone) == 0) print("usdhcio: no Datadone in %x after CMD%d\n", i, cmd); if(i & Err) print("usdhcio: CMD%d error interrupt %ux\n", - cmd, RR(Interrupt)); - if(i != 0) WR(Interrupt, i); + cmd, RR(ctlr, Interrupt)); + if(i != 0) WR(ctlr, Interrupt, i); } /* * Once card is selected, use faster clock */ if(cmd == MMCSelect){ - usdhcclk(SDfreq); - usdhc.fastclock = 1; + usdhcclk(ctlr, SDfreq); + ctlr->fastclock = 1; } if(cmd == Setbuswidth){ - if(usdhc.appcmd){ + if(ctlr->appcmd){ /* * If card bus width changes, change host bus width */ switch(arg){ case 0: - WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth1); + WR(ctlr, Control0, (RR(ctlr, Control0) & ~DwidthMask) | Dwidth1); break; case 2: - WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth4); + WR(ctlr, Control0, (RR(ctlr, Control0) & ~DwidthMask) | Dwidth4); break; } } else { @@ -452,81 +478,102 @@ usdhccmd(u32int cmd, u32int arg, u32int *resp) */ if((arg&0x8000000F) == 0x80000001){ delay(1); - usdhcclk(SDfreqhs); + usdhcclk(ctlr, SDfreqhs); delay(1); } } }else if(cmd == IORWdirect && (arg & ~0xFF) == (1<<31|0<<28|7<<9)){ switch(arg & 0x3){ case 0: - WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth1); + WR(ctlr, Control0, (RR(ctlr, Control0) & ~DwidthMask) | Dwidth1); break; case 2: - WR(Control0, (RR(Control0) & ~DwidthMask) | Dwidth4); + WR(ctlr, Control0, (RR(ctlr, Control0) & ~DwidthMask) | Dwidth4); break; } } - usdhc.appcmd = (cmd == Appcmd); + ctlr->appcmd = (cmd == Appcmd); return 0; } static void -usdhciosetup(int write, void *buf, int bsize, int bcount) +usdhciosetup(SDio *io, int write, void *buf, int bsize, int bcount) { + Ctlr *ctlr = io->aux; int len = bsize * bcount; assert(((uintptr)buf&3) == 0); assert((len&3) == 0); assert(bsize <= 2048); - WR(Blksizecnt, bcount<<16 | bsize); - if(usdhc.dma) - sdfree(usdhc.dma); - usdhc.dma = dmaalloc(buf, len); + WR(ctlr, Blksizecnt, bcount<<16 | bsize); + if(ctlr->dma) + sdfree(ctlr->dma); + ctlr->dma = dmaalloc(buf, len); if(write) cachedwbse(buf, len); else cachedwbinvse(buf, len); - WR(Dmadesc, PADDR(usdhc.dma)); + WR(ctlr, Dmadesc, PADDR(ctlr->dma)); } static void -usdhcio(int write, uchar *buf, int len) +usdhcio(SDio *io, int write, uchar *buf, int len) { + Ctlr *ctlr = io->aux; u32int i; - WR(Irpten, RR(Irpten) | Datadone|Err); - tsleep(&usdhc.r, datadone, 0, 3000); - WR(Irpten, RR(Irpten) & ~(Datadone|Err)); - i = RR(Interrupt); + WR(ctlr, Irpten, RR(ctlr, Irpten) | Datadone|Err); + tsleep(&ctlr->r, datadone, ctlr, 3000); + WR(ctlr, Irpten, RR(ctlr, Irpten) & ~(Datadone|Err)); + i = RR(ctlr, Interrupt); if((i & (Datadone|Err)) != Datadone){ - print("sdhc: %s error intr %ux stat %ux\n", - write? "write" : "read", i, RR(Status)); - WR(Interrupt, i); + print("%s: %s error intr %ux stat %ux\n", io->name, + write? "write" : "read", i, RR(ctlr, Status)); + WR(ctlr, Interrupt, i); error(Eio); } - WR(Interrupt, i); + WR(ctlr, Interrupt, i); if(!write) cachedinvse(buf, len); } static void -usdhcinterrupt(Ureg*, void*) -{ +usdhcinterrupt(Ureg*, void *arg) +{ + Ctlr *ctlr = arg; u32int i; - i = RR(Interrupt); + i = RR(ctlr, Interrupt); if(i&(Datadone|Err)) - wakeup(&usdhc.r); - WR(Irpten, RR(Irpten) & ~i); + wakeup(&ctlr->r); + WR(ctlr, Irpten, RR(ctlr, Irpten) & ~i); } -SDio sdio = { - "usdhc", - usdhcinit, - usdhcenable, - usdhcinquiry, - usdhccmd, - usdhciosetup, - usdhcio, - .highspeed = 1, - .nomultiwrite = 1, -}; +void +usdhclink(void) +{ + static SDio usdhc1 = { + "usdhc1", + usdhc1init, + usdhcenable, + usdhcinquiry, + usdhccmd, + usdhciosetup, + usdhcio, + .highspeed = 1, + .nomultiwrite = 1, + }; + static SDio usdhc2 = { + "usdhc2", + usdhc2init, + usdhcenable, + usdhcinquiry, + usdhccmd, + usdhciosetup, + usdhcio, + .highspeed = 1, + .nomultiwrite = 1, + }; + + addmmcio(&usdhc1); + addmmcio(&usdhc2); +} diff --git a/sys/src/9/pc/pc b/sys/src/9/pc/pc index ab909ee9f..63c03d779 100644 --- a/sys/src/9/pc/pc +++ b/sys/src/9/pc/pc @@ -93,6 +93,8 @@ link audioac97 pci audioac97mix audiohda pci + pmmc pci + misc pci pcipc diff --git a/sys/src/9/pc/pmmc.c b/sys/src/9/pc/pmmc.c index 710ce52bc..2db89e0b5 100644 --- a/sys/src/9/pc/pmmc.c +++ b/sys/src/9/pc/pmmc.c @@ -181,8 +181,6 @@ struct Ctlr { } io; }; -static Ctlr pmmc[1]; - #define CR8(c, off) *((u8int*)(c->mmio + off)) #define CR16(c, off) *((u16int*)(c->mmio + off)) #define CR32(c, off) *((u32int*)(c->mmio + off)) @@ -216,12 +214,14 @@ mmcinterrupt(Ureg*, void *arg) } static int -pmmcinit(void) +pmmcinit(SDio *io) { - Pcidev *p; + static Pcidev *p; + Ctlr *c; - p = nil; while((p = pcimatch(p, 0, 0)) != nil){ + if(p->mem[0].size < 256 || (p->mem[0].bar & 1) != 0) + continue; if(p->ccrb == 8 && p->ccru == 5) break; if(p->vid == 0x1180){ /* Ricoh */ @@ -231,15 +231,19 @@ pmmcinit(void) break; } } - - if(p == nil || p->mem[0].size < 256 || (p->mem[0].bar & 1) != 0) + if(p == nil) return -1; - - pmmc->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size); - if(pmmc->mmio == nil) + c = malloc(sizeof(Ctlr)); + if(c == nil) + return -1; + c->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size); + if(c->mmio == nil){ + free(c); return -1; + } + c->pdev = p; + io->aux = c; - pmmc->pdev = p; pcienable(p); if(p->did == 0x1180 && p->vid == 0xe823){ /* Ricoh */ @@ -257,11 +261,12 @@ pmmcinit(void) pcicfgw8(p, 0xfc, 0x00); } - return 0; + /* probe again for next device */ + return 1; } static int -pmmcinquiry(char *inquiry, int inqlen) +pmmcinquiry(SDio*, char *inquiry, int inqlen) { return snprint(inquiry, inqlen, "MMC Host Controller"); } @@ -361,9 +366,7 @@ resetctlr(Ctlr *c) static int waitcond(void *arg) { - Ctlr *c; - - c = arg; + Ctlr *c = arg; return (c->waitsts & c->waitmsk) != 0; } @@ -402,31 +405,27 @@ intrwait(Ctlr *c, u32int mask, int tmo) static void -pmmcenable(void) +pmmcenable(SDio *io) { - Pcidev *p; - Ctlr *c; + Ctlr *c = io->aux; + Pcidev *p = c->pdev; - c = pmmc; - p = c->pdev; resetctlr(c); - intrenable(p->intl, mmcinterrupt, c, p->tbdf, "mmc"); + intrenable(p->intl, mmcinterrupt, c, p->tbdf, io->name); } static int -pmmccmd(u32int cmd, u32int arg, u32int *resp) +pmmccmd(SDio *io, u32int cmd, u32int arg, u32int *resp) { + Ctlr *c = io->aux; u32int status; int i, mode; - Ctlr *c; if(cmd >= nelem(cmdinfo) || cmdinfo[cmd] == 0) error(Egreg); mode = cmdinfo[cmd] >> 8; cmd = (cmd << 8) | (cmdinfo[cmd] & 0xFF); - c = pmmc; - if(c->change) resetctlr(c); if((CR32(c, Rpres) & Pcrdin) == 0) @@ -489,9 +488,9 @@ pmmccmd(u32int cmd, u32int arg, u32int *resp) } static void -pmmciosetup(int write, void *buf, int bsize, int bcount) +pmmciosetup(SDio *io, int write, void *buf, int bsize, int bcount) { - Ctlr *c; + Ctlr *c = io->aux; USED(write); USED(buf); @@ -499,7 +498,6 @@ pmmciosetup(int write, void *buf, int bsize, int bcount) if(bsize == 0 || (bsize & 3) != 0) error(Egreg); - c = pmmc; c->io.bsize = bsize; c->io.bcount = bcount; } @@ -523,12 +521,11 @@ writeblock(Ctlr *c, uchar *buf, int len) } static void -pmmcio(int write, uchar *buf, int len) +pmmcio(SDio *io, int write, uchar *buf, int len) { - Ctlr *c; + Ctlr *c = io->aux; int n; - c = pmmc; if(len != c->io.bsize*c->io.bcount) error(Egreg); while(len > 0){ @@ -548,12 +545,17 @@ pmmcio(int write, uchar *buf, int len) error(Eio); } -SDio sdio = { - "pmmc", - pmmcinit, - pmmcenable, - pmmcinquiry, - pmmccmd, - pmmciosetup, - pmmcio, -}; +void +pmmclink(void) +{ + static SDio io = { + "pmmc", + pmmcinit, + pmmcenable, + pmmcinquiry, + pmmccmd, + pmmciosetup, + pmmcio, + }; + addmmcio(&io); +} diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64 index 30b7d7ed7..f69b3516f 100644 --- a/sys/src/9/pc64/pc64 +++ b/sys/src/9/pc64/pc64 @@ -91,6 +91,8 @@ link # audioac97 pci audioac97mix audiohda pci + pmmc pci + misc pci pcipc archgeneric devkbd i8259 i8253 diff --git a/sys/src/9/port/sd.h b/sys/src/9/port/sd.h index 0ef5dab33..10996b006 100644 --- a/sys/src/9/port/sd.h +++ b/sys/src/9/port/sd.h @@ -155,17 +155,18 @@ enum { struct SDio { char *name; - int (*init)(void); - void (*enable)(void); - int (*inquiry)(char*, int); - int (*cmd)(u32int, u32int, u32int*); - void (*iosetup)(int, void*, int, int); - void (*io)(int, uchar*, int); + int (*init)(SDio*); + void (*enable)(SDio*); + int (*inquiry)(SDio*, char*, int); + int (*cmd)(SDio*, u32int, u32int, u32int*); + void (*iosetup)(SDio*, int, void*, int, int); + void (*io)(SDio*, int, uchar*, int); char highspeed; char nomultiwrite; /* quirk for usdhc */ + void *aux; }; -extern SDio sdio; +extern void addmmcio(SDio *io); /* devsd.c */ extern void sdadddevs(SDev*); diff --git a/sys/src/9/port/sdmmc.c b/sys/src/9/port/sdmmc.c index d7bd02d97..d8a9258fe 100644 --- a/sys/src/9/port/sdmmc.c +++ b/sys/src/9/port/sdmmc.c @@ -3,7 +3,6 @@ * * Copyright © 2012 Richard Miller <r.miller@acm.org> * - * Assumes only one card on the bus */ #include "u.h" @@ -74,6 +73,7 @@ enum { struct Ctlr { SDev *dev; SDio *io; + /* SD card registers */ u16int rca; u32int ocr; @@ -84,7 +84,78 @@ struct Ctlr { }; extern SDifc sdmmcifc; -extern SDio sdio; + +static SDio *sdio[8]; +static int nsdio, isdio; + +void +addmmcio(SDio *io) +{ + assert(io != nil); + assert(isdio == 0); + if(nsdio >= nelem(sdio)){ + print("addmmcio: out of slots for %s\n", io->name); + return; + } + sdio[nsdio++] = io; +} + +static SDev* +init1(void) +{ + SDev *sdev; + Ctlr *ctlr; + SDio *io; + int more; + + if(isdio >= nsdio) + return nil; + if((sdev = malloc(sizeof(SDev))) == nil) + return nil; + if((ctlr = malloc(sizeof(Ctlr))) == nil){ + free(sdev); + return nil; + } + if((io = malloc(sizeof(SDio))) == nil){ + free(ctlr); + free(sdev); + return nil; + } +Next: + memmove(io, sdio[isdio++], sizeof(SDio)); + if(io->init != nil){ + more = (*io->init)(io); + if(more < 0){ + if(isdio < nsdio) + goto Next; + + free(io); + free(ctlr); + free(sdev); + return nil; + } + if(more > 0) + isdio--; /* try again */ + } + sdev->idno = 'M'; + sdev->ifc = &sdmmcifc; + sdev->nunit = 1; + sdev->ctlr = ctlr; + ctlr->dev = sdev; + ctlr->io = io; + return sdev; +} + +static SDev* +mmcpnp(void) +{ + SDev *list = nil, **link = &list; + + while((*link = init1()) != nil) + link = &(*link)->next; + + return list; +} static uint rbits(u32int *p, uint start, uint len) @@ -126,39 +197,14 @@ identify(SDunit *unit, u32int *csd) } } -static SDev* -mmcpnp(void) -{ - SDev *sdev; - Ctlr *ctl; - - if(sdio.init() < 0) - return nil; - sdev = malloc(sizeof(SDev)); - if(sdev == nil) - return nil; - ctl = malloc(sizeof(Ctlr)); - if(ctl == nil){ - free(sdev); - return nil; - } - sdev->idno = 'M'; - sdev->ifc = &sdmmcifc; - sdev->nunit = 1; - sdev->ctlr = ctl; - ctl->dev = sdev; - ctl->io = &sdio; - return sdev; -} - static int mmcverify(SDunit *unit) { + Ctlr *ctlr = unit->dev->ctlr; + SDio *io = ctlr->io; int n; - Ctlr *ctl; - ctl = unit->dev->ctlr; - n = ctl->io->inquiry((char*)&unit->inquiry[8], sizeof(unit->inquiry)-8); + n = (*io->inquiry)(io, (char*)&unit->inquiry[8], sizeof(unit->inquiry)-8); if(n < 0) return 0; unit->inquiry[0] = 0x00; /* direct access (disk) */ @@ -170,116 +216,112 @@ mmcverify(SDunit *unit) static int mmcenable(SDev* dev) { - Ctlr *ctl; - - ctl = dev->ctlr; - ctl->io->enable(); + Ctlr *ctlr = dev->ctlr; + SDio *io = ctlr->io; + (*io->enable)(io); return 1; } static void mmcswitchfunc(SDio *io, int arg) { + u32int r[4]; uchar *buf; int n; - u32int r[4]; n = Funcbytes; buf = sdmalloc(n); if(waserror()){ - print("mmcswitchfunc error\n"); + print("%s: mmcswitchfunc error\n", io->name); sdfree(buf); nexterror(); } - io->iosetup(0, buf, n, 1); - io->cmd(SWITCH_FUNC, arg, r); - io->io(0, buf, n); + (*io->iosetup)(io, 0, buf, n, 1); + (*io->cmd)(io, SWITCH_FUNC, arg, r); + (*io->io)(io, 0, buf, n); sdfree(buf); poperror(); } static int -cardinit(Ctlr *ctl) +cardinit(Ctlr *ctlr) { + SDio *io = ctlr->io; u32int r[4]; int hcs, i; - SDio *io = ctl->io; - io->cmd(GO_IDLE_STATE, 0, r); + (*io->cmd)(io, GO_IDLE_STATE, 0, r); hcs = 0; if(!waserror()){ - io->cmd(SD_SEND_IF_COND, Voltage|Checkpattern, r); + (*io->cmd)(io, SD_SEND_IF_COND, Voltage|Checkpattern, r); if(r[0] == (Voltage|Checkpattern)) /* SD 2.0 or above */ hcs = Hcs; poperror(); } for(i = 0; i < Inittimeout; i++){ tsleep(&up->sleep, return0, nil, 100); - io->cmd(APP_CMD, 0, r); - io->cmd(SD_SEND_OP_COND, hcs|V3_3, r); + (*io->cmd)(io, APP_CMD, 0, r); + (*io->cmd)(io, SD_SEND_OP_COND, hcs|V3_3, r); if(r[0] & Powerup) break; } if(i == Inittimeout) return 2; - ctl->ocr = r[0]; - io->cmd(ALL_SEND_CID, 0, r); - memmove(ctl->cid, r, sizeof ctl->cid); - io->cmd(SEND_RELATIVE_ADDR, 0, r); - ctl->rca = r[0]>>16; - io->cmd(SEND_CSD, ctl->rca<<Rcashift, r); - memmove(ctl->csd, r, sizeof ctl->csd); + ctlr->ocr = r[0]; + (*io->cmd)(io, ALL_SEND_CID, 0, r); + memmove(ctlr->cid, r, sizeof ctlr->cid); + (*io->cmd)(io, SEND_RELATIVE_ADDR, 0, r); + ctlr->rca = r[0]>>16; + (*io->cmd)(io, SEND_CSD, ctlr->rca<<Rcashift, r); + memmove(ctlr->csd, r, sizeof ctlr->csd); return 1; } static void retryproc(void *arg) { - Ctlr *ctl = arg; + Ctlr *ctlr = arg; int i = 0; while(waserror()) ; - if(i++ < ctl->retry) - cardinit(ctl); + if(i++ < ctlr->retry) + cardinit(ctlr); USED(i); - ctl->retry = 0; + ctlr->retry = 0; pexit("", 1); } static int mmconline(SDunit *unit) { + Ctlr *ctlr = unit->dev->ctlr; + SDio *io = ctlr->io; u32int r[4]; - Ctlr *ctl; - SDio *io; assert(unit->subno == 0); - ctl = unit->dev->ctlr; - io = ctl->io; - - if(ctl->retry) + if(ctlr->retry) return 0; if(waserror()){ unit->sectors = 0; - if(ctl->retry++ == 0) - kproc(unit->name, retryproc, ctl); + if(ctlr->retry++ == 0) + kproc(unit->name, retryproc, ctlr); return 0; } if(unit->sectors != 0){ - io->cmd(SEND_STATUS, ctl->rca<<Rcashift, r); + (*io->cmd)(io, SEND_STATUS, ctlr->rca<<Rcashift, r); poperror(); return 1; } - if(cardinit(ctl) != 1){ + if(cardinit(ctlr) != 1){ poperror(); return 2; } - identify(unit, ctl->csd); - io->cmd(SELECT_CARD, ctl->rca<<Rcashift, r); - io->cmd(SET_BLOCKLEN, unit->secsize, r); - io->cmd(APP_CMD, ctl->rca<<Rcashift, r); - io->cmd(SET_BUS_WIDTH, Width4, r); + identify(unit, ctlr->csd); + (*io->cmd)(io, SELECT_CARD, ctlr->rca<<Rcashift, r); + (*io->cmd)(io, SET_BLOCKLEN, unit->secsize, r); + (*io->cmd)(io, APP_CMD, ctlr->rca<<Rcashift, r); + (*io->cmd)(io, SET_BUS_WIDTH, Width4, r); if(io->highspeed){ if(!waserror()){ mmcswitchfunc(io, Hispeed|Setfunc); @@ -293,7 +335,7 @@ mmconline(SDunit *unit) static int mmcrctl(SDunit *unit, char *p, int l) { - Ctlr *ctl; + Ctlr *ctlr = unit->dev->ctlr; int i, n; assert(unit->subno == 0); @@ -302,13 +344,12 @@ mmcrctl(SDunit *unit, char *p, int l) if(unit->sectors == 0) return 0; } - ctl = unit->dev->ctlr; - n = snprint(p, l, "rca %4.4ux ocr %8.8ux\ncid ", ctl->rca, ctl->ocr); - for(i = nelem(ctl->cid)-1; i >= 0; i--) - n += snprint(p+n, l-n, "%8.8ux", ctl->cid[i]); + n = snprint(p, l, "rca %4.4ux ocr %8.8ux\ncid ", ctlr->rca, ctlr->ocr); + for(i = nelem(ctlr->cid)-1; i >= 0; i--) + n += snprint(p+n, l-n, "%8.8ux", ctlr->cid[i]); n += snprint(p+n, l-n, " csd "); - for(i = nelem(ctl->csd)-1; i >= 0; i--) - n += snprint(p+n, l-n, "%8.8ux", ctl->csd[i]); + for(i = nelem(ctlr->csd)-1; i >= 0; i--) + n += snprint(p+n, l-n, "%8.8ux", ctlr->csd[i]); n += snprint(p+n, l-n, "\ngeometry %llud %ld\n", unit->sectors, unit->secsize); return n; @@ -317,16 +358,14 @@ mmcrctl(SDunit *unit, char *p, int l) static long mmcbio(SDunit *unit, int lun, int write, void *data, long nb, uvlong bno) { + Ctlr *ctlr = unit->dev->ctlr; + SDio *io = ctlr->io; int len, tries; - ulong b; u32int r[4]; uchar *buf; - Ctlr *ctl; - SDio *io; + ulong b; USED(lun); - ctl = unit->dev->ctlr; - io = ctl->io; assert(unit->subno == 0); if(unit->sectors == 0) error(Echange); @@ -338,24 +377,24 @@ mmcbio(SDunit *unit, int lun, int write, void *data, long nb, uvlong bno) while(waserror()) if(++tries == 3) nexterror(); - io->iosetup(write, buf, len, nb); + (*io->iosetup)(io, write, buf, len, nb); if(waserror()){ - io->cmd(STOP_TRANSMISSION, 0, r); + (*io->cmd)(io, STOP_TRANSMISSION, 0, r); nexterror(); } - io->cmd(write? WRITE_MULTIPLE_BLOCK: READ_MULTIPLE_BLOCK, - ctl->ocr & Ccs? b: b * len, r); - io->io(write, buf, nb * len); + (*io->cmd)(io, write? WRITE_MULTIPLE_BLOCK: READ_MULTIPLE_BLOCK, + ctlr->ocr & Ccs? b: b * len, r); + (*io->io)(io, write, buf, nb * len); poperror(); - io->cmd(STOP_TRANSMISSION, 0, r); + (*io->cmd)(io, STOP_TRANSMISSION, 0, r); poperror(); b += nb; }else{ for(b = bno; b < bno + nb; b++){ - io->iosetup(write, buf, len, 1); - io->cmd(write? WRITE_BLOCK : READ_SINGLE_BLOCK, - ctl->ocr & Ccs? b: b * len, r); - io->io(write, buf, len); + (*io->iosetup)(io, write, buf, len, 1); + (*io->cmd)(io, write? WRITE_BLOCK : READ_SINGLE_BLOCK, + ctlr->ocr & Ccs? b: b * len, r); + (*io->io)(io, write, buf, len); buf += len; } } diff --git a/sys/src/9/zynq/emmc.c b/sys/src/9/zynq/emmc.c index cdd1e5e8a..71824b44a 100644 --- a/sys/src/9/zynq/emmc.c +++ b/sys/src/9/zynq/emmc.c @@ -178,7 +178,7 @@ datadone(void*) } static int -emmcinit(void) +emmcinit(SDio*) { u32int *r; int i; @@ -198,7 +198,7 @@ emmcinit(void) } static int -emmcinquiry(char *inquiry, int inqlen) +emmcinquiry(SDio*, char *inquiry, int inqlen) { uint ver; @@ -209,7 +209,7 @@ emmcinquiry(char *inquiry, int inqlen) } static void -emmcenable(void) +emmcenable(SDio *io) { int i; @@ -223,11 +223,11 @@ emmcenable(void) if(i == 1000) print("SD clock won't initialise!\n"); emmc.regs[Irptmask] = ~(Dtoerr|Cardintr|Dmaintr); - intrenable(emmc.irq, interrupt, nil, LEVEL, sdio.name); + intrenable(emmc.irq, interrupt, nil, LEVEL, io->name); } static int -emmccmd(u32int cmd, u32int arg, u32int *resp) +emmccmd(SDio*, u32int cmd, u32int arg, u32int *resp) { ulong now; u32int *r; @@ -339,7 +339,7 @@ emmccmd(u32int cmd, u32int arg, u32int *resp) } static void -emmciosetup(int, void *buf, int bsize, int bcount) +emmciosetup(SDio*, int, void *buf, int bsize, int bcount) { u32int *r; uintptr pa; @@ -360,7 +360,7 @@ emmciosetup(int, void *buf, int bsize, int bcount) } static void -emmcio(int write, uchar *buf, int len) +emmcio(SDio*, int write, uchar *buf, int len) { u32int *r; int i; @@ -393,12 +393,17 @@ emmcio(int write, uchar *buf, int len) } } -SDio sdio = { - "emmc", - emmcinit, - emmcenable, - emmcinquiry, - emmccmd, - emmciosetup, - emmcio, -}; +void +emmclink(void) +{ + static SDio io = { + "emmc", + emmcinit, + emmcenable, + emmcinquiry, + emmccmd, + emmciosetup, + emmcio, + }; + addmmcio(&io); +} diff --git a/sys/src/9/zynq/zynq b/sys/src/9/zynq/zynq index 4c702d4aa..626a58531 100644 --- a/sys/src/9/zynq/zynq +++ b/sys/src/9/zynq/zynq @@ -30,6 +30,7 @@ link loopbackmedium netdevmedium usbehci usbehcizynq + emmc misc uartzynq |