1 /*
2 * Kirkwood-specific code for
3 * USB Enhanced Host Controller Interface (EHCI) driver
4 * High speed USB 2.0.
5 */
6
7 #include "u.h"
8 #include "../port/lib.h"
9 #include "mem.h"
10 #include "dat.h"
11 #include "fns.h"
12 #include "io.h"
13 #include "../port/error.h"
14 #include "../port/usb.h"
15 #include "../port/portusbehci.h"
16 #include "usbehci.h"
17 //#include "uncached.h"
18
19 #define WINTARG(ctl) (((ctl) >> 4) & 017)
20 #define WINATTR(ctl) (((ctl) >> 8) & 0377)
21 #define WIN64KSIZE(ctl) (((ctl) >> 16) + 1)
22
23 #define SIZETO64KSIZE(size) ((size) / (64*1024) - 1)
24
25 enum {
26 Debug = 0,
27 };
28
29 typedef struct Kwusb Kwusb;
30 typedef struct Kwusbtt Kwusbtt;
31 typedef struct Usbwin Usbwin;
32
33 /* kirkwood usb transaction translator registers? (undocumented) */
34 struct Kwusbtt { /* at soc.ehci */
35 ulong id;
36 ulong hwgeneral;
37 ulong hwhost;
38 ulong hwdevice;
39 ulong hwtxbuf;
40 ulong hwrxbuf;
41 ulong hwtttxbuf;
42 ulong hwttrxbuf;
43 };
44
45 /* kirkwood usb bridge & phy registers */
46 struct Kwusb { /* at offset 0x300 from soc.ehci */
47 ulong bcs; /* bridge ctl & sts */
48 uchar _pad0[0x310-0x304];
49
50 ulong bic; /* bridge intr. cause */
51 ulong bim; /* bridge intr. mask */
52 ulong _pad1;
53 ulong bea; /* bridge error addr. */
54 struct Usbwin {
55 ulong ctl; /* see Winenable in io.h */
56 ulong base;
57 ulong _pad2[2];
58 } win[4];
59 ulong phycfg; /* phy config. */
60 uchar _pad3[0x400-0x364];
61
62 ulong pwrctl; /* power control */
63 uchar _pad4[0x410-0x404];
64 ulong phypll; /* phy pll control */
65 uchar _pad5[0x420-0x414];
66 ulong phytxctl; /* phy transmit control */
67 uchar _pad6[0x430-0x424];
68 ulong phyrxctl; /* phy receive control */
69 uchar _pad7[0x440-0x434];
70 ulong phyivref; /* phy ivref control */
71 };
72
73 static Ctlr* ctlrs[Nhcis];
74
75 static void
addrmapdump(void)76 addrmapdump(void)
77 {
78 int i;
79 ulong ctl, targ, attr, size64k;
80 Kwusb *map;
81 Usbwin *win;
82
83 if (!Debug)
84 return;
85 map = (Kwusb *)(soc.ehci + 0x300);
86 for (i = 0; i < nelem(map->win); i++) {
87 win = &map->win[i];
88 ctl = win->ctl;
89 if (ctl & Winenable) {
90 targ = WINTARG(ctl);
91 attr = WINATTR(ctl);
92 size64k = WIN64KSIZE(ctl);
93 print("usbehci: address map window %d: "
94 "targ %ld attr %#lux size %,ld addr %#lux\n",
95 i, targ, attr, size64k * 64*1024, win->base);
96 }
97 }
98 }
99
100 /* assumes ctlr is ilocked */
101 static void
ctlrreset(Ctlr * ctlr)102 ctlrreset(Ctlr *ctlr)
103 {
104 int i;
105 Eopio *opio;
106
107 opio = ctlr->opio;
108 opio->cmd |= Chcreset;
109 coherence();
110 /* wait for it to come out of reset */
111 for(i = 0; i < 100 && opio->cmd & Chcreset; i++)
112 delay(1);
113 if(i >= 100)
114 print("ehci %#p controller reset timed out\n", ctlr->capio);
115 /*
116 * Marvell errata FE-USB-340 workaround: 1 << 4 magic:
117 * disable streaming. Magic 3 (usb host mode) from the linux driver
118 * makes it work. Ick.
119 */
120 opio->usbmode |= 1 << 4 | 3;
121 coherence();
122 }
123
124 /*
125 * configure window `win' as 256MB dram with attribute `attr' and
126 * base address
127 */
128 static void
setaddrwin(Kwusb * kw,int win,int attr,ulong base)129 setaddrwin(Kwusb *kw, int win, int attr, ulong base)
130 {
131 kw->win[win].ctl = Winenable | Targdram << 4 | attr << 8 |
132 SIZETO64KSIZE(256*MB) << 16;
133 kw->win[win].base = base;
134 }
135
136 static void
ehcireset(Ctlr * ctlr)137 ehcireset(Ctlr *ctlr)
138 {
139 int i, amp, txvdd;
140 ulong v;
141 Eopio *opio;
142 Kwusb *kw;
143
144 ilock(ctlr);
145 dprint("ehci %#p reset\n", ctlr->capio);
146 opio = ctlr->opio;
147
148 kw = (Kwusb *)(soc.ehci + 0x300);
149 kw->bic = 0;
150 kw->bim = (1<<4) - 1; /* enable all defined intrs */
151 ctlrreset(ctlr);
152
153 /*
154 * clear high 32 bits of address signals if it's 64 bits capable.
155 * This is probably not needed but it does not hurt and others do it.
156 */
157 if((ctlr->capio->capparms & C64) != 0){
158 dprint("ehci: 64 bits\n");
159 opio->seg = 0;
160 }
161
162 /* requesting more interrupts per µframe may miss interrupts */
163 opio->cmd &= ~Citcmask;
164 opio->cmd |= 1 << Citcshift; /* max of 1 intr. per 125 µs */
165 switch(opio->cmd & Cflsmask){
166 case Cfls1024:
167 ctlr->nframes = 1024;
168 break;
169 case Cfls512:
170 ctlr->nframes = 512;
171 break;
172 case Cfls256:
173 ctlr->nframes = 256;
174 break;
175 default:
176 panic("ehci: unknown fls %ld", opio->cmd & Cflsmask);
177 }
178 dprint("ehci: %d frames\n", ctlr->nframes);
179
180 /*
181 * set up the USB address map (bridge address decoding)
182 */
183 for (i = 0; i < nelem(kw->win); i++)
184 kw->win[i].ctl = kw->win[i].base = 0;
185 coherence();
186
187 setaddrwin(kw, 0, Attrcs0, 0);
188 setaddrwin(kw, 1, Attrcs1, 256*MB);
189 coherence();
190
191 if (Debug)
192 if (kw->bcs & (1 << 4))
193 print("usbehci: not swapping bytes\n");
194 else
195 print("usbehci: swapping bytes\n");
196 addrmapdump(); /* verify sanity */
197
198 kw->pwrctl |= 1 << 0 | 1 << 1; /* Pu | PuPll */
199 coherence();
200
201 /*
202 * Marvell guideline GL-USB-160.
203 */
204 kw->phypll |= 1 << 21; /* VCOCAL_START: PLL calibration */
205 coherence();
206 microdelay(100);
207 kw->phypll &= ~(1 << 21);
208
209 v = kw->phytxctl & ~(017 << 27 | 7); /* REG_EXT_FS_RCALL & AMP_2_0 */
210 switch (m->socrev) {
211 default:
212 print("usbehci: bad 6281 soc rev %d\n", m->socrev);
213 /* fall through */
214 case Socreva0:
215 amp = 4;
216 txvdd = 1;
217 break;
218 case Socreva1:
219 amp = 3;
220 txvdd = 3;
221 break;
222 }
223 /* REG_EXT_FS_RCALL_EN | REG_RCAL_START | AMP_2_0 */
224 kw->phytxctl = v | 1 << 26 | 1 << 12 | amp;
225 coherence();
226 microdelay(100);
227 kw->phytxctl &= ~(1 << 12);
228
229 v = kw->phyrxctl & ~(3 << 2 | 017 << 4); /* LPF_COEF_1_0 & SQ_THRESH_3_0 */
230 kw->phyrxctl = v | 1 << 2 | 8 << 4;
231
232 v = kw->phyivref & ~(3 << 8); /* TXVDD12 */
233 kw->phyivref = v | txvdd << 8;
234 coherence();
235
236 ehcirun(ctlr, 0);
237 ctlrreset(ctlr);
238
239 iunlock(ctlr);
240 }
241
242 static void
setdebug(Hci *,int d)243 setdebug(Hci*, int d)
244 {
245 ehcidebug = d;
246 }
247
248 static void
shutdown(Hci * hp)249 shutdown(Hci *hp)
250 {
251 Ctlr *ctlr;
252 Eopio *opio;
253
254 ctlr = hp->aux;
255 ilock(ctlr);
256 ctlrreset(ctlr);
257
258 delay(100);
259 ehcirun(ctlr, 0);
260
261 opio = ctlr->opio;
262 opio->frbase = 0;
263 coherence();
264 iunlock(ctlr);
265 }
266
267 static void
findehcis(void)268 findehcis(void) /* actually just use fixed addresses on sheeva */
269 {
270 int i;
271 Ctlr *ctlr;
272 static int already = 0;
273
274 if(already)
275 return;
276 already = 1;
277
278 ctlr = malloc(sizeof(Ctlr));
279 if (ctlr == nil)
280 panic("ehci: out of memory");
281 /* the sheeva's usb 2.0 otg uses a superset of the ehci registers */
282 ctlr->capio = (Ecapio *)(soc.ehci + 0x100);
283 ctlr->opio = (Eopio *) (soc.ehci + 0x140);
284 dprint("usbehci: port %#p\n", ctlr->capio);
285
286 for(i = 0; i < Nhcis; i++)
287 if(ctlrs[i] == nil){
288 ctlrs[i] = ctlr;
289 break;
290 }
291 if(i == Nhcis)
292 print("ehci: bug: more than %d controllers\n", Nhcis);
293 }
294
295 static int
reset(Hci * hp)296 reset(Hci *hp)
297 {
298 static Lock resetlck;
299 int i;
300 Ctlr *ctlr;
301 Ecapio *capio;
302
303 ilock(&resetlck);
304 findehcis();
305
306 /*
307 * Any adapter matches if no hp->port is supplied,
308 * otherwise the ports must match.
309 */
310 ctlr = nil;
311 for(i = 0; i < Nhcis && ctlrs[i] != nil; i++){
312 ctlr = ctlrs[i];
313 if(ctlr->active == 0)
314 if(hp->port == 0 || hp->port == (uintptr)ctlr->capio){
315 ctlr->active = 1;
316 break;
317 }
318 }
319 iunlock(&resetlck);
320 if(ctlrs[i] == nil || i == Nhcis)
321 return -1;
322
323 hp->aux = ctlr;
324 hp->port = (uintptr)ctlr->capio;
325 hp->irq = IRQ0usb0;
326 hp->tbdf = 0;
327
328 capio = ctlr->capio;
329 hp->nports = capio->parms & Cnports;
330
331 ddprint("echi: %s, ncc %lud npcc %lud\n",
332 capio->parms & 0x10000 ? "leds" : "no leds",
333 (capio->parms >> 12) & 0xf, (capio->parms >> 8) & 0xf);
334 ddprint("ehci: routing %s, %sport power ctl, %d ports\n",
335 capio->parms & 0x40 ? "explicit" : "automatic",
336 capio->parms & 0x10 ? "" : "no ", hp->nports);
337
338 ehcireset(ctlr);
339 ehcimeminit(ctlr);
340
341 /*
342 * Linkage to the generic HCI driver.
343 */
344 ehcilinkage(hp);
345 hp->shutdown = shutdown;
346 hp->debug = setdebug;
347 return 0;
348 }
349
350 void
usbehcilink(void)351 usbehcilink(void)
352 {
353 addhcitype("ehci", reset);
354 }
355