1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38#include <common.h>
39#include <mpc8xx.h>
40#include <usb.h>
41#include "sl811.h"
42
43#include "../../../board/kup/common/kup.h"
44
45#ifdef __PPC__
46# define EIEIO __asm__ volatile ("eieio")
47#else
48# define EIEIO
49#endif
50
51#define SL811_ADR (0x50000000)
52#define SL811_DAT (0x50000001)
53
54#ifdef SL811_DEBUG
55static int debug = 9;
56#endif
57
58static int root_hub_devnum = 0;
59static struct usb_port_status rh_status = { 0 };
60
61static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe,
62 void *data, int buf_len, struct devrequest *cmd);
63
64static void sl811_write (__u8 index, __u8 data)
65{
66 *(volatile unsigned char *) (SL811_ADR) = index;
67 EIEIO;
68 *(volatile unsigned char *) (SL811_DAT) = data;
69 EIEIO;
70}
71
72static __u8 sl811_read (__u8 index)
73{
74 __u8 data;
75
76 *(volatile unsigned char *) (SL811_ADR) = index;
77 EIEIO;
78 data = *(volatile unsigned char *) (SL811_DAT);
79 EIEIO;
80 return (data);
81}
82
83
84
85
86static void inline sl811_read_buf(__u8 offset, __u8 *buf, __u8 size)
87{
88 *(volatile unsigned char *) (SL811_ADR) = offset;
89 EIEIO;
90 while (size--) {
91 *buf++ = *(volatile unsigned char *) (SL811_DAT);
92 EIEIO;
93 }
94}
95
96
97
98
99static void inline sl811_write_buf(__u8 offset, __u8 *buf, __u8 size)
100{
101 *(volatile unsigned char *) (SL811_ADR) = offset;
102 EIEIO;
103 while (size--) {
104 *(volatile unsigned char *) (SL811_DAT) = *buf++;
105 EIEIO;
106 }
107}
108
109int usb_init_kup4x (void)
110{
111 volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR;
112 volatile memctl8xx_t *memctl = &immap->im_memctl;
113 int i;
114 unsigned char tmp;
115
116 memctl = &immap->im_memctl;
117 memctl->memc_or7 = 0xFFFF8726;
118 memctl->memc_br7 = 0x50000401;
119
120 immap->im_cpm.cp_pbdat &= ~(BP_USB_VCC);
121
122 immap->im_cpm.cp_pbpar &= ~(BP_USB_VCC);
123
124 immap->im_cpm.cp_pbdir |= (BP_USB_VCC);
125
126 puts ("USB: ");
127
128 for (i = 0x10; i < 0xff; i++) {
129 sl811_write(i, i);
130 tmp = (sl811_read(i));
131 if (tmp != i) {
132 printf ("SL811 compare error index=0x%02x read=0x%02x\n", i, tmp);
133 return (-1);
134 }
135 }
136 printf ("SL811 ready\n");
137 return (0);
138}
139
140
141
142
143
144
145
146static int sl811_hc_reset(void)
147{
148 int status ;
149
150 sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI);
151 sl811_write(SL811_CTRL1, SL811_CTRL1_RESET);
152
153 mdelay(20);
154
155
156 sl811_write(SL811_CTRL1, 0);
157 mdelay(2);
158 sl811_write(SL811_INTRSTS, 0xff);
159 status = sl811_read(SL811_INTRSTS);
160
161 if (status & SL811_INTR_NOTPRESENT) {
162
163 PDEBUG(0, "Device not present\n");
164 rh_status.wPortStatus &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE);
165 rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION;
166 sl811_write(SL811_INTR, SL811_INTR_INSRMV);
167 return 0;
168 }
169
170
171 sl811_write(SL811_LEN_B, 0);
172 sl811_write(SL811_PIDEP_B, PIDEP(USB_PID_SOF, 0));
173 sl811_write(SL811_DEV_B, 0x00);
174 sl811_write(SL811_SOFLOW, SL811_12M_LOW);
175
176 if (status & SL811_INTR_SPEED_FULL) {
177
178 PDEBUG (0, "Full speed Device attached\n");
179
180 sl811_write(SL811_CTRL1, SL811_CTRL1_RESET);
181 mdelay(20);
182 sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_12M_HI);
183 sl811_write(SL811_CTRL1, SL811_CTRL1_SOF);
184
185
186 sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM);
187 rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION;
188 rh_status.wPortStatus &= ~USB_PORT_STAT_LOW_SPEED;
189 mdelay(2);
190 sl811_write(SL811_INTRSTS, 0xff);
191 } else {
192
193 PDEBUG(0, "Low speed Device attached\n");
194
195 sl811_write(SL811_CTRL1, SL811_CTRL1_RESET);
196 mdelay(20);
197 sl811_write(SL811_CTRL2, SL811_CTL2_HOST | SL811_CTL2_DSWAP | SL811_12M_HI);
198 sl811_write(SL811_CTRL1, SL811_CTRL1_SPEED_LOW | SL811_CTRL1_SOF);
199
200
201 sl811_write(SL811_CTRL_B, SL811_USB_CTRL_ARM);
202 rh_status.wPortStatus |= USB_PORT_STAT_CONNECTION | USB_PORT_STAT_LOW_SPEED;
203 mdelay(2);
204 sl811_write(SL811_INTRSTS, 0xff);
205 }
206
207 rh_status.wPortChange |= USB_PORT_STAT_C_CONNECTION;
208 sl811_write(SL811_INTR, SL811_INTR_DONE_A);
209
210 return 1;
211}
212
213int usb_lowlevel_init(void)
214{
215 root_hub_devnum = 0;
216 sl811_hc_reset();
217 return 0;
218}
219
220int usb_lowlevel_stop(void)
221{
222 sl811_hc_reset();
223 return 0;
224}
225
226static int calc_needed_buswidth(int bytes, int need_preamble)
227{
228 return !need_preamble ? bytes * 8 + 256 : 8 * 8 * bytes + 2048;
229}
230
231static int sl811_send_packet(struct usb_device *dev, unsigned long pipe, __u8 *buffer, int len)
232{
233 __u8 ctrl = SL811_USB_CTRL_ARM | SL811_USB_CTRL_ENABLE;
234 __u16 status = 0;
235 int err = 0, time_start = get_timer(0);
236 int need_preamble = !(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) &&
237 usb_pipeslow(pipe);
238
239 if (len > 239)
240 return -1;
241
242 if (usb_pipeout(pipe))
243 ctrl |= SL811_USB_CTRL_DIR_OUT;
244 if (usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)))
245 ctrl |= SL811_USB_CTRL_TOGGLE_1;
246 if (need_preamble)
247 ctrl |= SL811_USB_CTRL_PREAMBLE;
248
249 sl811_write(SL811_INTRSTS, 0xff);
250
251 while (err < 3) {
252 sl811_write(SL811_ADDR_A, 0x10);
253 sl811_write(SL811_LEN_A, len);
254 if (usb_pipeout(pipe) && len)
255 sl811_write_buf(0x10, buffer, len);
256
257 if (!(rh_status.wPortStatus & USB_PORT_STAT_LOW_SPEED) &&
258 sl811_read(SL811_SOFCNTDIV)*64 < calc_needed_buswidth(len, need_preamble))
259 ctrl |= SL811_USB_CTRL_SOF;
260 else
261 ctrl &= ~SL811_USB_CTRL_SOF;
262
263 sl811_write(SL811_CTRL_A, ctrl);
264 while (!(sl811_read(SL811_INTRSTS) & SL811_INTR_DONE_A)) {
265 if (5*CONFIG_SYS_HZ < get_timer(time_start)) {
266 printf("USB transmit timed out\n");
267 return -USB_ST_CRC_ERR;
268 }
269 }
270
271 sl811_write(SL811_INTRSTS, 0xff);
272 status = sl811_read(SL811_STS_A);
273
274 if (status & SL811_USB_STS_ACK) {
275 int remainder = sl811_read(SL811_CNT_A);
276 if (remainder) {
277 PDEBUG(0, "usb transfer remainder = %d\n", remainder);
278 len -= remainder;
279 }
280 if (usb_pipein(pipe) && len)
281 sl811_read_buf(0x10, buffer, len);
282 return len;
283 }
284
285 if ((status & SL811_USB_STS_NAK) == SL811_USB_STS_NAK)
286 continue;
287
288 PDEBUG(0, "usb transfer error %#x\n", (int)status);
289 err++;
290 }
291
292 err = 0;
293
294 if (status & SL811_USB_STS_ERROR)
295 err |= USB_ST_BUF_ERR;
296 if (status & SL811_USB_STS_TIMEOUT)
297 err |= USB_ST_CRC_ERR;
298 if (status & SL811_USB_STS_STALL)
299 err |= USB_ST_STALLED;
300
301 return -err;
302}
303
304int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
305 int len)
306{
307 int dir_out = usb_pipeout(pipe);
308 int ep = usb_pipeendpoint(pipe);
309 int max = usb_maxpacket(dev, pipe);
310 int done = 0;
311
312 PDEBUG(7, "dev = %ld pipe = %ld buf = %p size = %d dir_out = %d\n",
313 usb_pipedevice(pipe), usb_pipeendpoint(pipe), buffer, len, dir_out);
314
315 dev->status = 0;
316
317 sl811_write(SL811_DEV_A, usb_pipedevice(pipe));
318 sl811_write(SL811_PIDEP_A, PIDEP(!dir_out ? USB_PID_IN : USB_PID_OUT, ep));
319 while (done < len) {
320 int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done,
321 max > len - done ? len - done : max);
322 if (res < 0) {
323 dev->status = -res;
324 return res;
325 }
326
327 if (!dir_out && res < max)
328 break;
329
330 done += res;
331 usb_dotoggle(dev, ep, dir_out);
332 }
333
334 dev->act_len = done;
335
336 return 0;
337}
338
339int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
340 int len,struct devrequest *setup)
341{
342 int done = 0;
343 int devnum = usb_pipedevice(pipe);
344 int ep = usb_pipeendpoint(pipe);
345
346 dev->status = 0;
347
348 if (devnum == root_hub_devnum)
349 return sl811_rh_submit_urb(dev, pipe, buffer, len, setup);
350
351 PDEBUG(7, "dev = %d pipe = %ld buf = %p size = %d rt = %#x req = %#x bus = %i\n",
352 devnum, ep, buffer, len, (int)setup->requesttype,
353 (int)setup->request, sl811_read(SL811_SOFCNTDIV)*64);
354
355 sl811_write(SL811_DEV_A, devnum);
356 sl811_write(SL811_PIDEP_A, PIDEP(USB_PID_SETUP, ep));
357
358 usb_settoggle(dev, ep, 1, 0);
359 if (sl811_send_packet(dev, usb_sndctrlpipe(dev, ep),
360 (__u8*)setup, sizeof(*setup)) == sizeof(*setup)) {
361 int dir_in = usb_pipein(pipe);
362 int max = usb_maxpacket(dev, pipe);
363
364
365 sl811_write(SL811_PIDEP_A,
366 PIDEP(dir_in ? USB_PID_IN : USB_PID_OUT, ep));
367 usb_settoggle(dev, ep, usb_pipeout(pipe), 1);
368 while (done < len) {
369 int res = sl811_send_packet(dev, pipe, (__u8*)buffer+done,
370 max > len - done ? len - done : max);
371 if (res < 0) {
372 PDEBUG(0, "status data failed!\n");
373 dev->status = -res;
374 return 0;
375 }
376 done += res;
377 usb_dotoggle(dev, ep, usb_pipeout(pipe));
378 if (dir_in && res < max)
379 break;
380 }
381
382
383 sl811_write(SL811_PIDEP_A,
384 PIDEP(!dir_in ? USB_PID_IN : USB_PID_OUT, ep));
385 usb_settoggle(dev, ep, !usb_pipeout(pipe), 1);
386 if (sl811_send_packet(dev,
387 !dir_in ? usb_rcvctrlpipe(dev, ep) :
388 usb_sndctrlpipe(dev, ep),
389 0, 0) < 0) {
390 PDEBUG(0, "status phase failed!\n");
391 dev->status = -1;
392 }
393 } else {
394 PDEBUG(0, "setup phase failed!\n");
395 dev->status = -1;
396 }
397
398 dev->act_len = done;
399
400 return done;
401}
402
403int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
404 int len, int interval)
405{
406 PDEBUG(0, "dev = %p pipe = %#lx buf = %p size = %d int = %d\n", dev, pipe,
407 buffer, len, interval);
408 return -1;
409}
410
411
412
413
414
415
416static __u8 sl811_rh_dev_des[] =
417{
418 0x12,
419 0x01,
420 0x10,
421 0x01,
422 0x09,
423 0x00,
424 0x00,
425 0x08,
426 0x00,
427 0x00,
428 0x00,
429 0x00,
430 0x00,
431 0x00,
432 0x00,
433 0x02,
434 0x01,
435 0x01
436};
437
438
439static __u8 sl811_rh_config_des[] =
440{
441 0x09,
442 0x02,
443 0x19,
444 0x00,
445 0x01,
446 0x01,
447 0x00,
448 0x40,
449
450
451 0x00,
452
453
454 0x09,
455 0x04,
456 0x00,
457 0x00,
458 0x01,
459 0x09,
460 0x00,
461 0x00,
462 0x00,
463
464
465 0x07,
466 0x05,
467 0x81,
468 0x03,
469 0x08,
470 0x00,
471 0xff
472};
473
474
475static __u8 sl811_rh_hub_des[] =
476{
477 0x09,
478 0x29,
479 0x01,
480 0x00,
481 0x00,
482 0x50,
483 0x00,
484 0xfc,
485 0xff
486};
487
488
489
490
491
492static int ascii2utf (char *s, u8 *utf, int utfmax)
493{
494 int retval;
495
496 for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) {
497 *utf++ = *s++;
498 *utf++ = 0;
499 }
500 return retval;
501}
502
503
504
505
506
507static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len)
508{
509 char buf [30];
510
511
512
513
514
515 if (id == 0) {
516 *data++ = 4; *data++ = 3;
517 *data++ = 0; *data++ = 0;
518 return 4;
519
520
521 } else if (id == 1) {
522 sprintf (buf, "%#x", serial);
523
524
525 } else if (id == 2) {
526 sprintf (buf, "USB %s Root Hub", type);
527
528
529
530
531 } else
532 return 0;
533
534 ascii2utf (buf, data + 2, len - 2);
535 data [0] = 2 + strlen(buf) * 2;
536 data [1] = 3;
537 return data [0];
538}
539
540
541#define OK(x) len = (x); break
542
543
544
545
546static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe,
547 void *data, int buf_len, struct devrequest *cmd)
548{
549 __u8 data_buf[16];
550 __u8 *bufp = data_buf;
551 int len = 0;
552 int status = 0;
553 __u16 bmRType_bReq;
554 __u16 wValue = le16_to_cpu (cmd->value);
555 __u16 wLength = le16_to_cpu (cmd->length);
556#ifdef SL811_DEBUG
557 __u16 wIndex = le16_to_cpu (cmd->index);
558#endif
559
560 if (usb_pipeint(pipe)) {
561 PDEBUG(0, "interrupt transfer unimplemented!\n");
562 return 0;
563 }
564
565 bmRType_bReq = cmd->requesttype | (cmd->request << 8);
566
567 PDEBUG(5, "submit rh urb, req = %d(%x) val = %#x index = %#x len=%d\n",
568 bmRType_bReq, bmRType_bReq, wValue, wIndex, wLength);
569
570
571
572
573
574
575
576
577 switch (bmRType_bReq) {
578 case RH_GET_STATUS:
579 *(__u16 *)bufp = cpu_to_le16(1);
580 OK(2);
581
582 case RH_GET_STATUS | USB_RECIP_INTERFACE:
583 *(__u16 *)bufp = cpu_to_le16(0);
584 OK(2);
585
586 case RH_GET_STATUS | USB_RECIP_ENDPOINT:
587 *(__u16 *)bufp = cpu_to_le16(0);
588 OK(2);
589
590 case RH_GET_STATUS | USB_TYPE_CLASS:
591 *(__u32 *)bufp = cpu_to_le32(0);
592 OK(4);
593
594 case RH_GET_STATUS | USB_RECIP_OTHER | USB_TYPE_CLASS:
595 *(__u32 *)bufp = cpu_to_le32(rh_status.wPortChange<<16 | rh_status.wPortStatus);
596 OK(4);
597
598 case RH_CLEAR_FEATURE | USB_RECIP_ENDPOINT:
599 switch (wValue) {
600 case 1:
601 OK(0);
602 }
603 break;
604
605 case RH_CLEAR_FEATURE | USB_TYPE_CLASS:
606 switch (wValue) {
607 case C_HUB_LOCAL_POWER:
608 OK(0);
609
610 case C_HUB_OVER_CURRENT:
611 OK(0);
612 }
613 break;
614
615 case RH_CLEAR_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS:
616 switch (wValue) {
617 case USB_PORT_FEAT_ENABLE:
618 rh_status.wPortStatus &= ~USB_PORT_STAT_ENABLE;
619 OK(0);
620
621 case USB_PORT_FEAT_SUSPEND:
622 rh_status.wPortStatus &= ~USB_PORT_STAT_SUSPEND;
623 OK(0);
624
625 case USB_PORT_FEAT_POWER:
626 rh_status.wPortStatus &= ~USB_PORT_STAT_POWER;
627 OK(0);
628
629 case USB_PORT_FEAT_C_CONNECTION:
630 rh_status.wPortChange &= ~USB_PORT_STAT_C_CONNECTION;
631 OK(0);
632
633 case USB_PORT_FEAT_C_ENABLE:
634 rh_status.wPortChange &= ~USB_PORT_STAT_C_ENABLE;
635 OK(0);
636
637 case USB_PORT_FEAT_C_SUSPEND:
638 rh_status.wPortChange &= ~USB_PORT_STAT_C_SUSPEND;
639 OK(0);
640
641 case USB_PORT_FEAT_C_OVER_CURRENT:
642 rh_status.wPortChange &= ~USB_PORT_STAT_C_OVERCURRENT;
643 OK(0);
644
645 case USB_PORT_FEAT_C_RESET:
646 rh_status.wPortChange &= ~USB_PORT_STAT_C_RESET;
647 OK(0);
648 }
649 break;
650
651 case RH_SET_FEATURE | USB_RECIP_OTHER | USB_TYPE_CLASS:
652 switch (wValue) {
653 case USB_PORT_FEAT_SUSPEND:
654 rh_status.wPortStatus |= USB_PORT_STAT_SUSPEND;
655 OK(0);
656
657 case USB_PORT_FEAT_RESET:
658 rh_status.wPortStatus |= USB_PORT_STAT_RESET;
659 rh_status.wPortChange = 0;
660 rh_status.wPortChange |= USB_PORT_STAT_C_RESET;
661 rh_status.wPortStatus &= ~USB_PORT_STAT_RESET;
662 rh_status.wPortStatus |= USB_PORT_STAT_ENABLE;
663 OK(0);
664
665 case USB_PORT_FEAT_POWER:
666 rh_status.wPortStatus |= USB_PORT_STAT_POWER;
667 OK(0);
668
669 case USB_PORT_FEAT_ENABLE:
670 rh_status.wPortStatus |= USB_PORT_STAT_ENABLE;
671 OK(0);
672 }
673 break;
674
675 case RH_SET_ADDRESS:
676 root_hub_devnum = wValue;
677 OK(0);
678
679 case RH_GET_DESCRIPTOR:
680 switch ((wValue & 0xff00) >> 8) {
681 case USB_DT_DEVICE:
682 len = sizeof(sl811_rh_dev_des);
683 bufp = sl811_rh_dev_des;
684 OK(len);
685
686 case USB_DT_CONFIG:
687 len = sizeof(sl811_rh_config_des);
688 bufp = sl811_rh_config_des;
689 OK(len);
690
691 case USB_DT_STRING:
692 len = usb_root_hub_string(wValue & 0xff, (int)(long)0, "SL811HS", data, wLength);
693 if (len > 0) {
694 bufp = data;
695 OK(len);
696 }
697
698 default:
699 status = -32;
700 }
701 break;
702
703 case RH_GET_DESCRIPTOR | USB_TYPE_CLASS:
704 len = sizeof(sl811_rh_hub_des);
705 bufp = sl811_rh_hub_des;
706 OK(len);
707
708 case RH_GET_CONFIGURATION:
709 bufp[0] = 0x01;
710 OK(1);
711
712 case RH_SET_CONFIGURATION:
713 OK(0);
714
715 default:
716 PDEBUG(1, "unsupported root hub command\n");
717 status = -32;
718 }
719
720 len = min(len, buf_len);
721 if (data != bufp)
722 memcpy(data, bufp, len);
723
724 PDEBUG(5, "len = %d, status = %d\n", len, status);
725
726 usb_dev->status = status;
727 usb_dev->act_len = len;
728
729 return status == 0 ? len : status;
730}
731