2 * Kirkwood-specific code for
3 * USB Enhanced Host Controller Interface (EHCI) driver
8 #include "../port/lib.h"
13 #include "../port/error.h"
14 #include "../port/usb.h"
16 //#include "uncached.h"
18 #define WINTARG(ctl) (((ctl) >> 4) & 017)
19 #define WINATTR(ctl) (((ctl) >> 8) & 0377)
20 #define WIN64KSIZE(ctl) (((ctl) >> 16) + 1)
22 #define SIZETO64KSIZE(size) ((size) / (64*1024) - 1)
28 typedef struct Kwusb Kwusb;
29 typedef struct Kwusbtt Kwusbtt;
30 typedef struct Usbwin Usbwin;
32 /* kirkwood usb transaction translator registers? (undocumented) */
33 struct Kwusbtt { /* at soc.ehci */
44 /* kirkwood usb bridge & phy registers */
45 struct Kwusb { /* at offset 0x300 from soc.ehci */
46 ulong bcs; /* bridge ctl & sts */
47 uchar _pad0[0x310-0x304];
49 ulong bic; /* bridge intr. cause */
50 ulong bim; /* bridge intr. mask */
52 ulong bea; /* bridge error addr. */
54 ulong ctl; /* see Winenable in io.h */
58 ulong phycfg; /* phy config. */
59 uchar _pad3[0x400-0x364];
61 ulong pwrctl; /* power control */
62 uchar _pad4[0x410-0x404];
63 ulong phypll; /* phy pll control */
64 uchar _pad5[0x420-0x414];
65 ulong phytxctl; /* phy transmit control */
66 uchar _pad6[0x430-0x424];
67 ulong phyrxctl; /* phy receive control */
68 uchar _pad7[0x440-0x434];
69 ulong phyivref; /* phy ivref control */
72 static Ctlr* ctlrs[Nhcis];
78 ulong ctl, targ, attr, size64k;
84 map = (Kwusb *)(soc.ehci + 0x300);
85 for (i = 0; i < nelem(map->win); i++) {
88 if (ctl & Winenable) {
91 size64k = WIN64KSIZE(ctl);
92 print("usbehci: address map window %d: "
93 "targ %ld attr %#lux size %,ld addr %#lux\n",
94 i, targ, attr, size64k * 64*1024, win->base);
99 /* assumes ctlr is ilocked */
101 ctlrreset(Ctlr *ctlr)
107 opio->cmd |= Chcreset;
109 /* wait for it to come out of reset */
110 for(i = 0; i < 100 && opio->cmd & Chcreset; i++)
113 print("ehci %#p controller reset timed out\n", ctlr->capio);
115 * Marvell errata FE-USB-340 workaround: 1 << 4 magic:
116 * disable streaming. Magic 3 (usb host mode) from the linux driver
117 * makes it work. Ick.
119 opio->usbmode |= 1 << 4 | 3;
124 * configure window `win' as 256MB dram with attribute `attr' and
128 setaddrwin(Kwusb *kw, int win, int attr, ulong base)
130 kw->win[win].ctl = Winenable | Targdram << 4 | attr << 8 |
131 SIZETO64KSIZE(256*MB) << 16;
132 kw->win[win].base = base;
136 ehcireset(Ctlr *ctlr)
144 dprint("ehci %#p reset\n", ctlr->capio);
147 kw = (Kwusb *)(soc.ehci + 0x300);
149 kw->bim = (1<<4) - 1; /* enable all defined intrs */
153 * clear high 32 bits of address signals if it's 64 bits capable.
154 * This is probably not needed but it does not hurt and others do it.
156 if((ctlr->capio->capparms & C64) != 0){
157 dprint("ehci: 64 bits\n");
161 /* requesting more interrupts per µframe may miss interrupts */
162 opio->cmd |= Citc8; /* 1 intr. per ms */
163 switch(opio->cmd & Cflsmask){
165 ctlr->nframes = 1024;
174 panic("ehci: unknown fls %ld", opio->cmd & Cflsmask);
176 dprint("ehci: %d frames\n", ctlr->nframes);
179 * set up the USB address map (bridge address decoding)
181 for (i = 0; i < nelem(kw->win); i++)
182 kw->win[i].ctl = kw->win[i].base = 0;
185 setaddrwin(kw, 0, Attrcs0, 0);
186 setaddrwin(kw, 1, Attrcs1, 256*MB);
190 if (kw->bcs & (1 << 4))
191 print("usbehci: not swapping bytes\n");
193 print("usbehci: swapping bytes\n");
194 addrmapdump(); /* verify sanity */
196 kw->pwrctl |= 1 << 0 | 1 << 1; /* Pu | PuPll */
200 * Marvell guideline GL-USB-160.
202 kw->phypll |= 1 << 21; /* VCOCAL_START: PLL calibration */
205 kw->phypll &= ~(1 << 21);
207 v = kw->phytxctl & ~(017 << 27 | 7); /* REG_EXT_FS_RCALL & AMP_2_0 */
210 print("usbehci: bad 6281 soc rev %d\n", m->socrev);
221 /* REG_EXT_FS_RCALL_EN | REG_RCAL_START | AMP_2_0 */
222 kw->phytxctl = v | 1 << 26 | 1 << 12 | amp;
225 kw->phytxctl &= ~(1 << 12);
227 v = kw->phyrxctl & ~(3 << 2 | 017 << 4); /* LPF_COEF_1_0 & SQ_THRESH_3_0 */
228 kw->phyrxctl = v | 1 << 2 | 8 << 4;
230 v = kw->phyivref & ~(3 << 8); /* TXVDD12 */
231 kw->phyivref = v | txvdd << 8;
241 setdebug(Hci*, int d)
266 findehcis(void) /* actually just use fixed addresses on sheeva */
270 static int already = 0;
276 ctlr = smalloc(sizeof(Ctlr));
277 /* the sheeva's usb 2.0 otg uses a superset of the ehci registers */
278 ctlr->capio = (Ecapio *)(soc.ehci + 0x100);
279 ctlr->opio = (Eopio *) (soc.ehci + 0x140);
280 dprint("usbehci: port %#p\n", ctlr->capio);
282 for(i = 0; i < Nhcis; i++)
288 print("ehci: bug: more than %d controllers\n", Nhcis);
294 static Lock resetlck;
303 * Any adapter matches if no hp->port is supplied,
304 * otherwise the ports must match.
307 for(i = 0; i < Nhcis && ctlrs[i] != nil; i++){
309 if(ctlr->active == 0)
310 if(hp->port == 0 || hp->port == (uintptr)ctlr->capio){
316 if(ctlrs[i] == nil || i == Nhcis)
320 hp->port = (uintptr)ctlr->capio;
325 hp->nports = capio->parms & Cnports;
327 ddprint("echi: %s, ncc %lud npcc %lud\n",
328 capio->parms & 0x10000 ? "leds" : "no leds",
329 (capio->parms >> 12) & 0xf, (capio->parms >> 8) & 0xf);
330 ddprint("ehci: routing %s, %sport power ctl, %d ports\n",
331 capio->parms & 0x40 ? "explicit" : "automatic",
332 capio->parms & 0x10 ? "" : "no ", hp->nports);
338 * Linkage to the generic HCI driver.
341 hp->shutdown = shutdown;
342 hp->debug = setdebug;
344 intrenable(Irqlo, hp->irq, hp->interrupt, hp, hp->type);
352 addhcitype("ehci", reset);