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