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