3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * This code is based on linux driver for sl811hs chip, source at
6 * drivers/usb/host/sl811.c:
8 * SL811 Host Controller Interface driver for USB.
10 * Copyright (c) 2003/06, Courage Co., Ltd.
13 * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap,
14 * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber,
15 * Adam Richter, Gregory P. Smith;
16 * 2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com>
17 * 3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn>
19 * See file CREDITS for list of people who contributed to this
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License as
24 * published by the Free Software Foundation; either version 2 of
25 * the License, or (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
39 #ifdef CONFIG_USB_SL811HS
44 #include "../board/kup/common/kup.h"
47 # define EIEIO __asm__ volatile ("eieio")
49 # define EIEIO /* nothing */
52 #define SL811_ADR (0x50000000)
53 #define SL811_DAT (0x50000001)
55 #define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);})
61 static int root_hub_devnum
= 0;
62 static struct usb_port_status rh_status
= { 0 };/* root hub port status */
64 static int sl811_rh_submit_urb(struct usb_device
*usb_dev
, unsigned long pipe
,
65 void *data
, int buf_len
, struct devrequest
*cmd
);
67 static void sl811_write (__u8 index
, __u8 data
)
69 *(volatile unsigned char *) (SL811_ADR
) = index
;
71 *(volatile unsigned char *) (SL811_DAT
) = data
;
75 static __u8
sl811_read (__u8 index
)
79 *(volatile unsigned char *) (SL811_ADR
) = index
;
81 data
= *(volatile unsigned char *) (SL811_DAT
);
87 * Read consecutive bytes of data from the SL811H/SL11H buffer
89 static void inline sl811_read_buf(__u8 offset
, __u8
*buf
, __u8 size
)
91 *(volatile unsigned char *) (SL811_ADR
) = offset
;
94 *buf
++ = *(volatile unsigned char *) (SL811_DAT
);
100 * Write consecutive bytes of data to the SL811H/SL11H buffer
102 static void inline sl811_write_buf(__u8 offset
, __u8
*buf
, __u8 size
)
104 *(volatile unsigned char *) (SL811_ADR
) = offset
;
107 *(volatile unsigned char *) (SL811_DAT
) = *buf
++;
112 int usb_init_kup4x (void)
114 volatile immap_t
*immap
= (immap_t
*) CFG_IMMR
;
115 volatile memctl8xx_t
*memctl
= &immap
->im_memctl
;
119 memctl
= &immap
->im_memctl
;
120 memctl
->memc_or7
= 0xFFFF8726;
121 memctl
->memc_br7
= 0x50000401; /* start at 0x50000000 */
122 /* BP 14 low = USB ON */
123 immap
->im_cpm
.cp_pbdat
&= ~(BP_USB_VCC
);
124 /* PB 14 nomal port */
125 immap
->im_cpm
.cp_pbpar
&= ~(BP_USB_VCC
);
127 immap
->im_cpm
.cp_pbdir
|= (BP_USB_VCC
);
131 for (i
= 0x10; i
< 0xff; i
++) {
133 tmp
= (sl811_read(i
));
135 printf ("SL811 compare error index=0x%02x read=0x%02x\n", i
, tmp
);
139 printf ("SL811 ready\n");
144 * This function resets SL811HS controller and detects the speed of
145 * the connecting device
147 * Return: 0 = no device attached; 1 = USB device attached
149 static int sl811_hc_reset(void)
153 sl811_write(SL811_CTRL2
, SL811_CTL2_HOST
| SL811_12M_HI
);
154 sl811_write(SL811_CTRL1
, SL811_CTRL1_RESET
);
158 /* Disable hardware SOF generation, clear all irq status. */
159 sl811_write(SL811_CTRL1
, 0);
161 sl811_write(SL811_INTRSTS
, 0xff);
162 status
= sl811_read(SL811_INTRSTS
);
164 if (status
& SL811_INTR_NOTPRESENT
) {
165 /* Device is not present */
166 PDEBUG(0, "Device not present\n");
167 rh_status
.wPortStatus
&= ~(USB_PORT_STAT_CONNECTION
| USB_PORT_STAT_ENABLE
);
168 rh_status
.wPortChange
|= USB_PORT_STAT_C_CONNECTION
;
169 sl811_write(SL811_INTR
, SL811_INTR_INSRMV
);
173 /* Send SOF to address 0, endpoint 0. */
174 sl811_write(SL811_LEN_B
, 0);
175 sl811_write(SL811_PIDEP_B
, PIDEP(USB_PID_SOF
, 0));
176 sl811_write(SL811_DEV_B
, 0x00);
177 sl811_write(SL811_SOFLOW
, SL811_12M_LOW
);
179 if (status
& SL811_INTR_SPEED_FULL
) {
180 /* full speed device connect directly to root hub */
181 PDEBUG (0, "Full speed Device attached\n");
183 sl811_write(SL811_CTRL1
, SL811_CTRL1_RESET
);
185 sl811_write(SL811_CTRL2
, SL811_CTL2_HOST
| SL811_12M_HI
);
186 sl811_write(SL811_CTRL1
, SL811_CTRL1_SOF
);
188 /* start the SOF or EOP */
189 sl811_write(SL811_CTRL_B
, SL811_USB_CTRL_ARM
);
190 rh_status
.wPortStatus
|= USB_PORT_STAT_CONNECTION
;
191 rh_status
.wPortStatus
&= ~USB_PORT_STAT_LOW_SPEED
;
193 sl811_write(SL811_INTRSTS
, 0xff);
195 /* slow speed device connect directly to root-hub */
196 PDEBUG(0, "Low speed Device attached\n");
198 sl811_write(SL811_CTRL1
, SL811_CTRL1_RESET
);
200 sl811_write(SL811_CTRL2
, SL811_CTL2_HOST
| SL811_CTL2_DSWAP
| SL811_12M_HI
);
201 sl811_write(SL811_CTRL1
, SL811_CTRL1_SPEED_LOW
| SL811_CTRL1_SOF
);
203 /* start the SOF or EOP */
204 sl811_write(SL811_CTRL_B
, SL811_USB_CTRL_ARM
);
205 rh_status
.wPortStatus
|= USB_PORT_STAT_CONNECTION
| USB_PORT_STAT_LOW_SPEED
;
207 sl811_write(SL811_INTRSTS
, 0xff);
210 rh_status
.wPortChange
|= USB_PORT_STAT_C_CONNECTION
;
211 sl811_write(SL811_INTR
, /*SL811_INTR_INSRMV*/SL811_INTR_DONE_A
);
216 int usb_lowlevel_init(void)
223 int usb_lowlevel_stop(void)
229 static int calc_needed_buswidth(int bytes
, int need_preamble
)
231 return !need_preamble
? bytes
* 8 + 256 : 8 * 8 * bytes
+ 2048;
234 static int sl811_send_packet(struct usb_device
*dev
, unsigned long pipe
, __u8
*buffer
, int len
)
236 __u8 ctrl
= SL811_USB_CTRL_ARM
| SL811_USB_CTRL_ENABLE
;
238 int err
= 0, time_start
= get_timer(0);
239 int need_preamble
= !(rh_status
.wPortStatus
& USB_PORT_STAT_LOW_SPEED
) &&
245 if (usb_pipeout(pipe
))
246 ctrl
|= SL811_USB_CTRL_DIR_OUT
;
247 if (usb_gettoggle(dev
, usb_pipeendpoint(pipe
), usb_pipeout(pipe
)))
248 ctrl
|= SL811_USB_CTRL_TOGGLE_1
;
250 ctrl
|= SL811_USB_CTRL_PREAMBLE
;
252 sl811_write(SL811_INTRSTS
, 0xff);
255 sl811_write(SL811_ADDR_A
, 0x10);
256 sl811_write(SL811_LEN_A
, len
);
257 if (usb_pipeout(pipe
) && len
)
258 sl811_write_buf(0x10, buffer
, len
);
260 if (!(rh_status
.wPortStatus
& USB_PORT_STAT_LOW_SPEED
) &&
261 sl811_read(SL811_SOFCNTDIV
)*64 < calc_needed_buswidth(len
, need_preamble
))
262 ctrl
|= SL811_USB_CTRL_SOF
;
264 ctrl
&= ~SL811_USB_CTRL_SOF
;
266 sl811_write(SL811_CTRL_A
, ctrl
);
267 while (!(sl811_read(SL811_INTRSTS
) & SL811_INTR_DONE_A
)) {
268 if (5*CFG_HZ
< get_timer(time_start
)) {
269 printf("USB transmit timed out\n");
270 return -USB_ST_CRC_ERR
;
274 sl811_write(SL811_INTRSTS
, 0xff);
275 status
= sl811_read(SL811_STS_A
);
277 if (status
& SL811_USB_STS_ACK
) {
278 int remainder
= sl811_read(SL811_CNT_A
);
280 PDEBUG(0, "usb transfer remainder = %d\n", remainder
);
283 if (usb_pipein(pipe
) && len
)
284 sl811_read_buf(0x10, buffer
, len
);
288 if ((status
& SL811_USB_STS_NAK
) == SL811_USB_STS_NAK
)
291 PDEBUG(0, "usb transfer error %#x\n", (int)status
);
297 if (status
& SL811_USB_STS_ERROR
)
298 err
|= USB_ST_BUF_ERR
;
299 if (status
& SL811_USB_STS_TIMEOUT
)
300 err
|= USB_ST_CRC_ERR
;
301 if (status
& SL811_USB_STS_STALL
)
302 err
|= USB_ST_STALLED
;
307 int submit_bulk_msg(struct usb_device
*dev
, unsigned long pipe
, void *buffer
,
310 int dir_out
= usb_pipeout(pipe
);
311 int ep
= usb_pipeendpoint(pipe
);
312 int max
= usb_maxpacket(dev
, pipe
);
315 PDEBUG(7, "dev = %ld pipe = %ld buf = %p size = %d dir_out = %d\n",
316 usb_pipedevice(pipe
), usb_pipeendpoint(pipe
), buffer
, len
, dir_out
);
320 sl811_write(SL811_DEV_A
, usb_pipedevice(pipe
));
321 sl811_write(SL811_PIDEP_A
, PIDEP(!dir_out
? USB_PID_IN
: USB_PID_OUT
, ep
));
323 int res
= sl811_send_packet(dev
, pipe
, (__u8
*)buffer
+done
,
324 max
> len
- done
? len
- done
: max
);
330 if (!dir_out
&& res
< max
) /* short packet */
334 usb_dotoggle(dev
, ep
, dir_out
);
342 int submit_control_msg(struct usb_device
*dev
, unsigned long pipe
, void *buffer
,
343 int len
,struct devrequest
*setup
)
346 int devnum
= usb_pipedevice(pipe
);
347 int ep
= usb_pipeendpoint(pipe
);
351 if (devnum
== root_hub_devnum
)
352 return sl811_rh_submit_urb(dev
, pipe
, buffer
, len
, setup
);
354 PDEBUG(7, "dev = %d pipe = %ld buf = %p size = %d rt = %#x req = %#x bus = %i\n",
355 devnum
, ep
, buffer
, len
, (int)setup
->requesttype
,
356 (int)setup
->request
, sl811_read(SL811_SOFCNTDIV
)*64);
358 sl811_write(SL811_DEV_A
, devnum
);
359 sl811_write(SL811_PIDEP_A
, PIDEP(USB_PID_SETUP
, ep
));
361 usb_settoggle(dev
, ep
, 1, 0);
362 if (sl811_send_packet(dev
, usb_sndctrlpipe(dev
, ep
),
363 (__u8
*)setup
, sizeof(*setup
)) == sizeof(*setup
)) {
364 int dir_in
= usb_pipein(pipe
);
365 int max
= usb_maxpacket(dev
, pipe
);
368 sl811_write(SL811_PIDEP_A
,
369 PIDEP(dir_in
? USB_PID_IN
: USB_PID_OUT
, ep
));
370 usb_settoggle(dev
, ep
, usb_pipeout(pipe
), 1);
372 int res
= sl811_send_packet(dev
, pipe
, (__u8
*)buffer
+done
,
373 max
> len
- done
? len
- done
: max
);
375 PDEBUG(0, "status data failed!\n");
380 usb_dotoggle(dev
, ep
, usb_pipeout(pipe
));
381 if (dir_in
&& res
< max
) /* short packet */
386 sl811_write(SL811_PIDEP_A
,
387 PIDEP(!dir_in
? USB_PID_IN
: USB_PID_OUT
, ep
));
388 usb_settoggle(dev
, ep
, !usb_pipeout(pipe
), 1);
389 if (sl811_send_packet(dev
,
390 !dir_in
? usb_rcvctrlpipe(dev
, ep
) :
391 usb_sndctrlpipe(dev
, ep
),
393 PDEBUG(0, "status phase failed!\n");
397 PDEBUG(0, "setup phase failed!\n");
406 int submit_int_msg(struct usb_device
*dev
, unsigned long pipe
, void *buffer
,
407 int len
, int interval
)
409 PDEBUG(0, "dev = %p pipe = %#lx buf = %p size = %d int = %d\n", dev
, pipe
,
410 buffer
, len
, interval
);
415 * SL811 Virtual Root Hub
418 /* Device descriptor */
419 static __u8 sl811_rh_dev_des
[] =
421 0x12, /* __u8 bLength; */
422 0x01, /* __u8 bDescriptorType; Device */
423 0x10, /* __u16 bcdUSB; v1.1 */
425 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
426 0x00, /* __u8 bDeviceSubClass; */
427 0x00, /* __u8 bDeviceProtocol; */
428 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
429 0x00, /* __u16 idVendor; */
431 0x00, /* __u16 idProduct; */
433 0x00, /* __u16 bcdDevice; */
435 0x00, /* __u8 iManufacturer; */
436 0x02, /* __u8 iProduct; */
437 0x01, /* __u8 iSerialNumber; */
438 0x01 /* __u8 bNumConfigurations; */
441 /* Configuration descriptor */
442 static __u8 sl811_rh_config_des
[] =
444 0x09, /* __u8 bLength; */
445 0x02, /* __u8 bDescriptorType; Configuration */
446 0x19, /* __u16 wTotalLength; */
448 0x01, /* __u8 bNumInterfaces; */
449 0x01, /* __u8 bConfigurationValue; */
450 0x00, /* __u8 iConfiguration; */
451 0x40, /* __u8 bmAttributes;
452 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup,
454 0x00, /* __u8 MaxPower; */
457 0x09, /* __u8 if_bLength; */
458 0x04, /* __u8 if_bDescriptorType; Interface */
459 0x00, /* __u8 if_bInterfaceNumber; */
460 0x00, /* __u8 if_bAlternateSetting; */
461 0x01, /* __u8 if_bNumEndpoints; */
462 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
463 0x00, /* __u8 if_bInterfaceSubClass; */
464 0x00, /* __u8 if_bInterfaceProtocol; */
465 0x00, /* __u8 if_iInterface; */
468 0x07, /* __u8 ep_bLength; */
469 0x05, /* __u8 ep_bDescriptorType; Endpoint */
470 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
471 0x03, /* __u8 ep_bmAttributes; Interrupt */
472 0x08, /* __u16 ep_wMaxPacketSize; */
474 0xff /* __u8 ep_bInterval; 255 ms */
477 /* root hub class descriptor*/
478 static __u8 sl811_rh_hub_des
[] =
480 0x09, /* __u8 bLength; */
481 0x29, /* __u8 bDescriptorType; Hub-descriptor */
482 0x01, /* __u8 bNbrPorts; */
483 0x00, /* __u16 wHubCharacteristics; */
485 0x50, /* __u8 bPwrOn2pwrGood; 2ms */
486 0x00, /* __u8 bHubContrCurrent; 0 mA */
487 0xfc, /* __u8 DeviceRemovable; *** 7 Ports max *** */
488 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
492 * helper routine for returning string descriptors in UTF-16LE
493 * input can actually be ISO-8859-1; ASCII is its 7-bit subset
495 static int ascii2utf (char *s
, u8
*utf
, int utfmax
)
499 for (retval
= 0; *s
&& utfmax
> 1; utfmax
-= 2, retval
+= 2) {
507 * root_hub_string is used by each host controller's root hub code,
508 * so that they're identified consistently throughout the system.
510 static int usb_root_hub_string (int id
, int serial
, char *type
, __u8
*data
, int len
)
514 /* assert (len > (2 * (sizeof (buf) + 1)));
515 assert (strlen (type) <= 8);*/
519 *data
++ = 4; *data
++ = 3; /* 4 bytes data */
520 *data
++ = 0; *data
++ = 0; /* some language id */
524 } else if (id
== 1) {
525 sprintf (buf
, "%#x", serial
);
527 /* product description */
528 } else if (id
== 2) {
529 sprintf (buf
, "USB %s Root Hub", type
);
531 /* id 3 == vendor description */
533 /* unsupported IDs --> "stall" */
537 ascii2utf (buf
, data
+ 2, len
- 2);
538 data
[0] = 2 + strlen(buf
) * 2;
544 #define OK(x) len = (x); break
547 * This function handles all USB request to the the virtual root hub
549 static int sl811_rh_submit_urb(struct usb_device
*usb_dev
, unsigned long pipe
,
550 void *data
, int buf_len
, struct devrequest
*cmd
)
553 __u8
*bufp
= data_buf
;
562 if (usb_pipeint(pipe
)) {
563 PDEBUG(0, "interrupt transfer unimplemented!\n");
567 bmRType_bReq
= cmd
->requesttype
| (cmd
->request
<< 8);
568 wValue
= le16_to_cpu (cmd
->value
);
569 wIndex
= le16_to_cpu (cmd
->index
);
570 wLength
= le16_to_cpu (cmd
->length
);
572 PDEBUG(5, "submit rh urb, req = %d(%x) val = %#x index = %#x len=%d\n",
573 bmRType_bReq
, bmRType_bReq
, wValue
, wIndex
, wLength
);
575 /* Request Destination:
576 without flags: Device,
577 USB_RECIP_INTERFACE: interface,
578 USB_RECIP_ENDPOINT: endpoint,
579 USB_TYPE_CLASS means HUB here,
580 USB_RECIP_OTHER | USB_TYPE_CLASS almost ever means HUB_PORT here
582 switch (bmRType_bReq
) {
584 *(__u16
*)bufp
= cpu_to_le16(1);
587 case RH_GET_STATUS
| USB_RECIP_INTERFACE
:
588 *(__u16
*)bufp
= cpu_to_le16(0);
591 case RH_GET_STATUS
| USB_RECIP_ENDPOINT
:
592 *(__u16
*)bufp
= cpu_to_le16(0);
595 case RH_GET_STATUS
| USB_TYPE_CLASS
:
596 *(__u32
*)bufp
= cpu_to_le32(0);
599 case RH_GET_STATUS
| USB_RECIP_OTHER
| USB_TYPE_CLASS
:
600 *(__u32
*)bufp
= cpu_to_le32(rh_status
.wPortChange
<<16 | rh_status
.wPortStatus
);
603 case RH_CLEAR_FEATURE
| USB_RECIP_ENDPOINT
:
610 case RH_CLEAR_FEATURE
| USB_TYPE_CLASS
:
612 case C_HUB_LOCAL_POWER
:
615 case C_HUB_OVER_CURRENT
:
620 case RH_CLEAR_FEATURE
| USB_RECIP_OTHER
| USB_TYPE_CLASS
:
622 case USB_PORT_FEAT_ENABLE
:
623 rh_status
.wPortStatus
&= ~USB_PORT_STAT_ENABLE
;
626 case USB_PORT_FEAT_SUSPEND
:
627 rh_status
.wPortStatus
&= ~USB_PORT_STAT_SUSPEND
;
630 case USB_PORT_FEAT_POWER
:
631 rh_status
.wPortStatus
&= ~USB_PORT_STAT_POWER
;
634 case USB_PORT_FEAT_C_CONNECTION
:
635 rh_status
.wPortChange
&= ~USB_PORT_STAT_C_CONNECTION
;
638 case USB_PORT_FEAT_C_ENABLE
:
639 rh_status
.wPortChange
&= ~USB_PORT_STAT_C_ENABLE
;
642 case USB_PORT_FEAT_C_SUSPEND
:
643 rh_status
.wPortChange
&= ~USB_PORT_STAT_C_SUSPEND
;
646 case USB_PORT_FEAT_C_OVER_CURRENT
:
647 rh_status
.wPortChange
&= ~USB_PORT_STAT_C_OVERCURRENT
;
650 case USB_PORT_FEAT_C_RESET
:
651 rh_status
.wPortChange
&= ~USB_PORT_STAT_C_RESET
;
656 case RH_SET_FEATURE
| USB_RECIP_OTHER
| USB_TYPE_CLASS
:
658 case USB_PORT_FEAT_SUSPEND
:
659 rh_status
.wPortStatus
|= USB_PORT_STAT_SUSPEND
;
662 case USB_PORT_FEAT_RESET
:
663 rh_status
.wPortStatus
|= USB_PORT_STAT_RESET
;
664 rh_status
.wPortChange
= 0;
665 rh_status
.wPortChange
|= USB_PORT_STAT_C_RESET
;
666 rh_status
.wPortStatus
&= ~USB_PORT_STAT_RESET
;
667 rh_status
.wPortStatus
|= USB_PORT_STAT_ENABLE
;
670 case USB_PORT_FEAT_POWER
:
671 rh_status
.wPortStatus
|= USB_PORT_STAT_POWER
;
674 case USB_PORT_FEAT_ENABLE
:
675 rh_status
.wPortStatus
|= USB_PORT_STAT_ENABLE
;
681 root_hub_devnum
= wValue
;
684 case RH_GET_DESCRIPTOR
:
685 switch ((wValue
& 0xff00) >> 8) {
687 len
= sizeof(sl811_rh_dev_des
);
688 bufp
= sl811_rh_dev_des
;
692 len
= sizeof(sl811_rh_config_des
);
693 bufp
= sl811_rh_config_des
;
697 len
= usb_root_hub_string(wValue
& 0xff, (int)(long)0, "SL811HS", data
, wLength
);
708 case RH_GET_DESCRIPTOR
| USB_TYPE_CLASS
:
709 len
= sizeof(sl811_rh_hub_des
);
710 bufp
= sl811_rh_hub_des
;
713 case RH_GET_CONFIGURATION
:
717 case RH_SET_CONFIGURATION
:
721 PDEBUG(1, "unsupported root hub command\n");
725 len
= min(len
, buf_len
);
727 memcpy(data
, bufp
, len
);
729 PDEBUG(5, "len = %d, status = %d\n", len
, status
);
731 usb_dev
->status
= status
;
732 usb_dev
->act_len
= len
;
734 return status
== 0 ? len
: status
;
737 #endif /* CONFIG_USB_SL811HS */