usbdwc: sync with sources (Raspberry Pi Model A support)

This commit is contained in:
cinap_lenrek 2013-06-01 16:31:58 +02:00
parent 03f364d167
commit 82f9f3df72

View file

@ -77,7 +77,7 @@ chanalloc(Ep *ep)
bitmap = ctlr->chanbusy; bitmap = ctlr->chanbusy;
for(i = 0; i < ctlr->nchan; i++) for(i = 0; i < ctlr->nchan; i++)
if((bitmap & (1<<i)) == 0){ if((bitmap & (1<<i)) == 0){
ctlr->chanbusy = bitmap | 1 << i; ctlr->chanbusy = bitmap | 1<<i;
qunlock(&ctlr->chanlock); qunlock(&ctlr->chanlock);
return &ctlr->regs->hchan[i]; return &ctlr->regs->hchan[i];
} }
@ -95,7 +95,7 @@ chanrelease(Ep *ep, Hostchan *chan)
ctlr = ep->hp->aux; ctlr = ep->hp->aux;
i = chan - ctlr->regs->hchan; i = chan - ctlr->regs->hchan;
qlock(&ctlr->chanlock); qlock(&ctlr->chanlock);
ctlr->chanbusy &= ~(1 << i); ctlr->chanbusy &= ~(1<<i);
qunlock(&ctlr->chanlock); qunlock(&ctlr->chanlock);
} }
@ -138,9 +138,12 @@ chansetup(Hostchan *hc, Ep *ep)
hcc |= Lspddev; hcc |= Lspddev;
/* fall through */ /* fall through */
case Fullspeed: case Fullspeed:
hc->hcsplt = Spltena | POS_ALL | ep->dev->hub << OHubaddr | if(ep->dev->hub > 1){
hc->hcsplt = Spltena | POS_ALL | ep->dev->hub<<OHubaddr |
ep->dev->port; ep->dev->port;
break; break;
}
/* fall through */
default: default:
hc->hcsplt = 0; hc->hcsplt = 0;
break; break;
@ -168,7 +171,7 @@ sofwait(Ctlr *ctlr, int n)
do{ do{
r->gintsts = Sofintr; r->gintsts = Sofintr;
x = splfhi(); x = splfhi();
ctlr->sofchan |= 1 << n; ctlr->sofchan |= 1<<n;
r->gintmsk |= Sofintr; r->gintmsk |= Sofintr;
sleep(&ctlr->chanintr[n], sofdone, r); sleep(&ctlr->chanintr[n], sofdone, r);
splx(x); splx(x);
@ -181,6 +184,8 @@ chandone(void *a)
Hostchan *hc; Hostchan *hc;
hc = a; hc = a;
if(hc->hcint == (Chhltd|Ack))
return 0;
return (hc->hcint & hc->hcintmsk) != 0; return (hc->hcint & hc->hcintmsk) != 0;
} }
@ -196,7 +201,7 @@ chanwait(Ep *ep, Ctlr *ctlr, Hostchan *hc, int mask)
for(;;){ for(;;){
restart: restart:
x = splfhi(); x = splfhi();
r->haintmsk |= 1 << n; r->haintmsk |= 1<<n;
hc->hcintmsk = mask; hc->hcintmsk = mask;
sleep(&ctlr->chanintr[n], chandone, hc); sleep(&ctlr->chanintr[n], chandone, hc);
hc->hcintmsk = 0; hc->hcintmsk = 0;
@ -218,7 +223,8 @@ restart:
return intr; return intr;
} }
if((intr & mask) == 0){ if((intr & mask) == 0){
dprint("ep%d.%d await %x intr %x -> %x\n", ep->dev->nb, ep->nb, mask, ointr, intr); dprint("ep%d.%d await %x intr %x -> %x\n",
ep->dev->nb, ep->nb, mask, ointr, intr);
goto restart; goto restart;
} }
now = fastticks(0); now = fastticks(0);
@ -248,7 +254,7 @@ chanintr(Ctlr *ctlr, int n)
int i; int i;
hc = &ctlr->regs->hchan[n]; hc = &ctlr->regs->hchan[n];
if(ctlr->debugchan & (1 << n)) if(ctlr->debugchan & (1<<n))
clog(nil, hc); clog(nil, hc);
if((hc->hcsplt & Spltena) == 0) if((hc->hcsplt & Spltena) == 0)
return 0; return 0;
@ -340,7 +346,7 @@ chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len)
n = ROUND(len, ep->maxpkt); n = ROUND(len, ep->maxpkt);
else else
n = len; n = len;
hc->hctsiz = n | npkt << OPktcnt | pid; hc->hctsiz = n | npkt<<OPktcnt | pid;
hc->hcdma = PADDR(a); hc->hcdma = PADDR(a);
nleft = len; nleft = len;
@ -389,7 +395,7 @@ chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len)
if((i & Xfercomp) == 0 && i != (Chhltd|Ack) && i != Chhltd){ if((i & Xfercomp) == 0 && i != (Chhltd|Ack) && i != Chhltd){
if(i & Stall) if(i & Stall)
error(Estalled); error(Estalled);
if(i & Nyet) if(i & (Nyet|Frmovrun))
continue; continue;
if(i & Nak){ if(i & Nak){
if(ep->ttype == Tintr) if(ep->ttype == Tintr)
@ -398,6 +404,7 @@ chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len)
tsleep(&up->sleep, return0, 0, 1); tsleep(&up->sleep, return0, 0, 1);
continue; continue;
} }
logdump(ep);
print("usbotg: ep%d.%d error intr %8.8ux\n", print("usbotg: ep%d.%d error intr %8.8ux\n",
ep->dev->nb, ep->nb, i); ep->dev->nb, ep->nb, i);
if(i & ~(Chhltd|Ack)) if(i & ~(Chhltd|Ack))
@ -407,31 +414,33 @@ chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len)
hcdma, hc->hcdma, i, hc->hcint); hcdma, hc->hcdma, i, hc->hcint);
} }
n = hc->hcdma - hcdma; n = hc->hcdma - hcdma;
if(n == 0) if(n == 0){
if((hc->hctsiz & Pktcnt) != (hctsiz & Pktcnt)) if((hc->hctsiz & Pktcnt) != (hctsiz & Pktcnt))
break; break;
else else
continue; continue;
}
if(dir == Epin && ep->ttype == Tbulk && n == nleft){ if(dir == Epin && ep->ttype == Tbulk && n == nleft){
nt = (hctsiz & Xfersize) - (hc->hctsiz & Xfersize); nt = (hctsiz & Xfersize) - (hc->hctsiz & Xfersize);
if(nt != n) if(nt != n){
if(n == ((nt+3) & ~3)) if(n == ROUND(nt, 4))
n = nt; n = nt;
else else
print("usbotg: intr %8.8ux dma " print("usbotg: intr %8.8ux "
"%8.8ux-%8.8ux hctsiz " "dma %8.8ux-%8.8ux "
"%8.8ux-%8.ux\n", "hctsiz %8.8ux-%8.ux\n",
i, hcdma, hc->hcdma, hctsiz, i, hcdma, hc->hcdma, hctsiz,
hc->hctsiz); hc->hctsiz);
} }
}
if(n > nleft){ if(n > nleft){
if(n != ((nleft+3) & ~3)) if(n != ROUND(nleft, 4))
dprint("too much: wanted %d got %d\n", dprint("too much: wanted %d got %d\n",
len, len - nleft + n); len, len - nleft + n);
n = nleft; n = nleft;
} }
nleft -= n; nleft -= n;
if(nleft == 0 || n % maxpkt != 0) if(nleft == 0 || (n % maxpkt) != 0)
break; break;
if((i & Xfercomp) && ep->ttype != Tctl) if((i & Xfercomp) && ep->ttype != Tctl)
break; break;
@ -443,6 +452,24 @@ chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len)
return len - nleft; return len - nleft;
} }
static long
multitrans(Ep *ep, Hostchan *hc, int rw, void *a, long n)
{
long sofar, m;
sofar = 0;
do{
m = n - sofar;
if(m > ep->maxpkt)
m = ep->maxpkt;
m = chanio(ep, hc, rw == Read? Epin : Epout, ep->toggle[rw],
(char*)a + sofar, m);
ep->toggle[rw] = hc->hctsiz & Pid;
sofar += m;
}while(sofar < n && m == ep->maxpkt);
return sofar;
}
static long static long
eptrans(Ep *ep, int rw, void *a, long n) eptrans(Ep *ep, int rw, void *a, long n)
{ {
@ -464,22 +491,10 @@ eptrans(Ep *ep, int rw, void *a, long n)
nexterror(); nexterror();
} }
chansetup(hc, ep); chansetup(hc, ep);
if(rw == Read && ep->ttype == Tbulk){ if(rw == Read && ep->ttype == Tbulk)
long sofar, m; n = multitrans(ep, hc, rw, a, n);
else{
sofar = 0; n = chanio(ep, hc, rw == Read? Epin : Epout, ep->toggle[rw],
do{
m = n - sofar;
if(m > ep->maxpkt)
m = ep->maxpkt;
m = chanio(ep, hc, Epin, ep->toggle[rw],
(char*)a + sofar, m);
ep->toggle[rw] = hc->hctsiz & Pid;
sofar += m;
}while(sofar < n && m == ep->maxpkt);
n = sofar;
}else{
n = chanio(ep, hc, rw == Read? Epin: Epout, ep->toggle[rw],
a, n); a, n);
ep->toggle[rw] = hc->hctsiz & Pid; ep->toggle[rw] = hc->hctsiz & Pid;
} }
@ -529,6 +544,10 @@ ctltrans(Ep *ep, uchar *req, long n)
chansetup(hc, ep); chansetup(hc, ep);
chanio(ep, hc, Epout, SETUP, req, Rsetuplen); chanio(ep, hc, Epout, SETUP, req, Rsetuplen);
if(req[Rtype] & Rd2h){ if(req[Rtype] & Rd2h){
if(ep->dev->hub <= 1){
ep->toggle[Read] = DATA1;
b->wp += multitrans(ep, hc, Read, data, datalen);
}else
b->wp += chanio(ep, hc, Epin, DATA1, data, datalen); b->wp += chanio(ep, hc, Epin, DATA1, data, datalen);
chanio(ep, hc, Epout, DATA1, nil, 0); chanio(ep, hc, Epout, DATA1, nil, 0);
n = Rsetuplen; n = Rsetuplen;
@ -602,7 +621,7 @@ init(Hci *hp)
tx = 0x100; tx = 0x100;
ptx = 0x200; ptx = 0x200;
r->grxfsiz = rx; r->grxfsiz = rx;
r->gnptxfsiz = rx | tx << ODepth; r->gnptxfsiz = rx | tx<<ODepth;
tsleep(&up->sleep, return0, 0, 1); tsleep(&up->sleep, return0, 0, 1);
r->hptxfsiz = (rx + tx) | ptx << ODepth; r->hptxfsiz = (rx + tx) | ptx << ODepth;
greset(r, Rxfflsh); greset(r, Rxfflsh);
@ -639,9 +658,11 @@ fiqintr(Ureg*, void *a)
if(intr & Hcintr){ if(intr & Hcintr){
haint = r->haint & r->haintmsk; haint = r->haint & r->haintmsk;
for(i = 0; haint; i++){ for(i = 0; haint; i++){
if(haint & 1 && chanintr(ctlr, i) == 0){ if(haint & 1){
r->haintmsk &= ~(1 << i); if(chanintr(ctlr, i) == 0){
wakechan |= 1 << i; r->haintmsk &= ~(1<<i);
wakechan |= 1<<i;
}
} }
haint >>= 1; haint >>= 1;
} }