ref: b818f48f41895754dd9b470be407ba85cfea45bd
parent: 2d0ede468ddd363243fd31580e3e86c39b51f7be
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Dec 11 14:08:52 EST 2022
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.
--- a/sys/src/9/bcm/emmc.c
+++ b/sys/src/9/bcm/emmc.c
@@ -240,7 +240,7 @@
}
static int
-emmcinit(void)
+emmcinit(SDio*)
{
u32int *r;
ulong clk;
@@ -265,7 +265,7 @@
}
static int
-emmcinquiry(char *inquiry, int inqlen)
+emmcinquiry(SDio*, char *inquiry, int inqlen)
{
u32int *r;
uint ver;
@@ -278,7 +278,7 @@
}
static void
-emmcenable(void)
+emmcenable(SDio*)
{
emmcclk(Initfreq);
WR(Irpten, 0);
@@ -288,7 +288,7 @@
}
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 @@
}
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 @@
}
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 @@
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);
+}
--- a/sys/src/9/bcm/pi
+++ b/sys/src/9/bcm/pi
@@ -28,6 +28,7 @@
ethermedium
loopbackmedium
netdevmedium
+ emmc
ip
tcp
--- a/sys/src/9/bcm/pi2
+++ b/sys/src/9/bcm/pi2
@@ -28,6 +28,7 @@
ethermedium
loopbackmedium
netdevmedium
+ emmc
ip
tcp
--- a/sys/src/9/bcm64/pi3
+++ b/sys/src/9/bcm64/pi3
@@ -29,6 +29,7 @@
ethermedium
loopbackmedium
netdevmedium
+ emmc
ip
tcp
--- a/sys/src/9/bcm64/pi4
+++ b/sys/src/9/bcm64/pi4
@@ -34,6 +34,7 @@
ethermedium
loopbackmedium
netdevmedium
+ sdhc
ip
tcp
--- 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,7 +206,7 @@
uintptr busdram;
};
-static Ctlr emmc;
+static Ctlr sdhc;
static void mmcinterrupt(Ureg*, void*);
@@ -213,7 +213,7 @@
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 @@
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 @@
}
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 @@
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 @@
{
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 @@
}
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 @@
}
static void
-emmcenable(void)
+sdhcenable(SDio *io)
{
WR(Control0, 0);
@@ -339,15 +339,15 @@
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;
@@ -354,13 +354,13 @@
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 @@
*/
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 @@
}
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 @@
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 @@
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 @@
}
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 @@
*/
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 @@
*/
if((arg&0x8000000F) == 0x80000001){
delay(1);
- emmcclk(SDfreqhs);
+ sdhcclk(SDfreqhs);
delay(1);
}
}
@@ -490,12 +490,12 @@
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 @@
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 @@
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);
+}
--- a/sys/src/9/imx8/reform
+++ b/sys/src/9/imx8/reform
@@ -34,6 +34,7 @@
i2cimx devi2c
pciimx pci
sai
+ usdhc
ip
tcp
--- a/sys/src/9/imx8/usdhc.c
+++ b/sys/src/9/imx8/usdhc.c
@@ -190,26 +190,27 @@
};
struct Ctlr {
- Rendez r;
+ u32int *regs;
+ int irq;
+
int fastclock;
uint extclk;
int appcmd;
Adma *dma;
+
+ Rendez r;
};
-static Ctlr usdhc;
-
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 @@
}
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 @@
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 @@
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 @@
/*
* 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,7 +370,7 @@
c |= Host2card;
else
c |= Card2host;
- if((RR(Blksizecnt)&0xFFFF0000) != 0x10000)
+ if((RR(ctlr, Blksizecnt)&0xFFFF0000) != 0x10000)
c |= Multiblock | Blkcnten;
}
/*
@@ -351,65 +377,65 @@
* 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;
@@ -416,34 +442,34 @@
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,7 +478,7 @@
*/
if((arg&0x8000000F) == 0x80000001){
delay(1);
- usdhcclk(SDfreqhs);
+ usdhcclk(ctlr, SDfreqhs);
delay(1);
}
}
@@ -459,74 +485,95 @@
}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);
+}
--- a/sys/src/9/pc/pc
+++ b/sys/src/9/pc/pc
@@ -93,6 +93,8 @@
audioac97 pci audioac97mix
audiohda pci
+ pmmc pci
+
misc
pci pcipc
--- a/sys/src/9/pc/pmmc.c
+++ b/sys/src/9/pc/pmmc.c
@@ -181,8 +181,6 @@
} 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 @@
}
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 @@
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 @@
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 @@
static int
waitcond(void *arg)
{
- Ctlr *c;
-
- c = arg;
+ Ctlr *c = arg;
return (c->waitsts & c->waitmsk) != 0;
}
@@ -402,23 +405,21 @@
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);
@@ -425,8 +426,6 @@
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 @@
}
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 @@
if(bsize == 0 || (bsize & 3) != 0)
error(Egreg);
- c = pmmc;
c->io.bsize = bsize;
c->io.bcount = bcount;
}
@@ -523,12 +521,11 @@
}
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 @@
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);
+}
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -91,6 +91,8 @@
# audioac97 pci audioac97mix
audiohda pci
+ pmmc pci
+
misc
pci pcipc
archgeneric devkbd i8259 i8253
--- a/sys/src/9/port/sd.h
+++ b/sys/src/9/port/sd.h
@@ -155,17 +155,18 @@
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*);
--- 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 @@
struct Ctlr {
SDev *dev;
SDio *io;
+
/* SD card registers */
u16int rca;
u32int ocr;
@@ -84,8 +84,79 @@
};
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 @@
}
}
-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,10 +216,9 @@
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;
}
@@ -180,35 +225,35 @@
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();
@@ -215,20 +260,20 @@
}
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;
}
@@ -235,15 +280,15 @@
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);
}
@@ -250,36 +295,33 @@
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 @@
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 @@
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 @@
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 @@
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;
}
}
--- a/sys/src/9/zynq/emmc.c
+++ b/sys/src/9/zynq/emmc.c
@@ -178,7 +178,7 @@
}
static int
-emmcinit(void)
+emmcinit(SDio*)
{
u32int *r;
int i;
@@ -198,7 +198,7 @@
}
static int
-emmcinquiry(char *inquiry, int inqlen)
+emmcinquiry(SDio*, char *inquiry, int inqlen)
{
uint ver;
@@ -209,7 +209,7 @@
}
static void
-emmcenable(void)
+emmcenable(SDio *io)
{
int i;
@@ -223,11 +223,11 @@
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 @@
}
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 @@
}
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 @@
}
}
-SDio sdio = {
- "emmc",
- emmcinit,
- emmcenable,
- emmcinquiry,
- emmccmd,
- emmciosetup,
- emmcio,
-};
+void
+emmclink(void)
+{
+ static SDio io = {
+ "emmc",
+ emmcinit,
+ emmcenable,
+ emmcinquiry,
+ emmccmd,
+ emmciosetup,
+ emmcio,
+ };
+ addmmcio(&io);
+}
--- a/sys/src/9/zynq/zynq
+++ b/sys/src/9/zynq/zynq
@@ -30,6 +30,7 @@
loopbackmedium
netdevmedium
usbehci usbehcizynq
+ emmc
misc
uartzynq