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