2 * OMAP3-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"
17 static Ctlr* ctlrs[Nhcis];
26 dprint("ehci %#p reset\n", ctlr->capio);
30 * Turn off legacy mode. Some controllers won't
31 * interrupt us as expected otherwise.
35 /* clear high 32 bits of address signals if it's 64 bits capable.
36 * This is probably not needed but it does not hurt and others do it.
38 if((ctlr->capio->capparms & C64) != 0){
39 dprint("ehci: 64 bits\n");
43 if(ehcidebugcapio != ctlr->capio){
44 opio->cmd |= Chcreset; /* controller reset */
46 for(i = 0; i < 100; i++){
47 if((opio->cmd & Chcreset) == 0)
52 print("ehci %#p controller reset timed out\n", ctlr->capio);
55 /* requesting more interrupts per µframe may miss interrupts */
56 opio->cmd |= Citc8; /* 1 intr. per ms */
58 switch(opio->cmd & Cflsmask){
69 panic("ehci: unknown fls %ld", opio->cmd & Cflsmask);
72 dprint("ehci: %d frames\n", ctlr->nframes);
92 opio->cmd |= Chcreset; /* controller reset */
94 for(i = 0; i < 100; i++){
95 if((opio->cmd & Chcreset) == 0)
100 print("ehci %#p controller reset timed out\n", ctlr->capio);
109 * omap3-specific ehci code
113 /* opio->insn[5] bits */
114 Control = 1<<31, /* set to start access, cleared when done */
118 Regaddrsh = 16, /* 0x2f means use extended reg addr */
121 /* phy reg addresses */
125 Phystppullupoff = 0x90, /* on is 0x10 */
127 Phyrstport2 = 147, /* gpio # */
132 wrulpi(Eopio *opio, int port, int reg, uchar data)
134 opio->insn[5] = Control | port << Portsh | Write | reg << Regaddrsh |
138 * this seems contrary to the skimpy documentation in the manual
139 * but inverting the test hangs forever.
141 while (!(opio->insn[5] & Control))
158 if(getconf("*nousbehci") != nil || probeaddr(PHYSEHCI) < 0)
161 ctlr = smalloc(sizeof(Ctlr));
163 * don't bother with vmap; i/o space is all mapped anyway,
164 * and a size less than 1MB will blow an assertion in mmukmap.
166 ctlr->capio = capio = (Ecapio *)PHYSEHCI;
167 ctlr->opio = opio = (Eopio*)((uintptr)capio + (capio->cap & 0xff));
170 hp->port = (uintptr)ctlr->capio;
172 hp->nports = capio->parms & Cnports;
174 ddprint("echi: %s, ncc %lud npcc %lud\n",
175 capio->parms & 0x10000 ? "leds" : "no leds",
176 (capio->parms >> 12) & 0xf, (capio->parms >> 8) & 0xf);
177 ddprint("ehci: routing %s, %sport power ctl, %d ports\n",
178 capio->parms & 0x40 ? "explicit" : "automatic",
179 capio->parms & 0x10 ? "" : "no ", hp->nports);
181 ctlr->tdalloc = ucallocalign;
182 ctlr->dmaalloc = ucalloc;
183 cltr->dmafree = ucfree;
188 /* omap35-specific set up */
189 /* bit 5 `must be set to 1 for proper behavior', spruf98d §23.2.6.7.17 */
190 opio->insn[4] |= 1<<5;
193 /* insn[5] is for both utmi and ulpi, depending on hostconfig mode */
194 uhh = (Uhh *)PHYSUHH;
195 if (uhh->hostconfig & P1ulpi_bypass) { /* utmi port 1 active */
197 iprint("usbehci: bypassing ulpi on port 1!\n");
198 opio->insn[5] &= ~(MASK(4) << 13);
199 opio->insn[5] |= 1 << 13; /* select port 1 */
201 } else { /* ulpi port 1 active */
202 /* TODO may need to reset gpio port2 here */
204 /* disable integrated stp pull-up resistor */
205 wrulpi(opio, 1, Ifcctlreg, Phystppullupoff);
207 /* force phy to `high-speed' */
208 wrulpi(opio, 1, Funcctlreg, 0x40);
212 * Linkage to the generic HCI driver.
215 hp->shutdown = shutdown;
216 hp->debug = setdebug;
218 intrenable(78, hp->interrupt, hp, UNKNOWN, "usbtll");
219 intrenable(92, hp->interrupt, hp, UNKNOWN, "usb otg");
220 intrenable(93, hp->interrupt, hp, UNKNOWN, "usb otg dma");
222 intrenable(hp->irq, hp->interrupt, hp, UNKNOWN, hp->type);
230 addhcitype("ehci", reset);