1 /* 2 * (C) Copyright 2004 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 4 * 5 * This code is based on linux driver for sl811hs chip, source at 6 * drivers/usb/host/sl811.c: 7 * 8 * SL811 Host Controller Interface driver for USB. 9 * 10 * Copyright (c) 2003/06, Courage Co., Ltd. 11 * 12 * Based on: 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> 18 * 19 * See file CREDITS for list of people who contributed to this 20 * project. 21 * 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. 26 * 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. 31 * 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, 35 * MA 02111-1307 USA 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 /* nothing */ 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 57 static int debug = 9; 58 #endif 59 60 static int root_hub_devnum = 0; 61 static struct usb_port_status rh_status = { 0 };/* root hub port status */ 62 63 static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe, 64 void *data, int buf_len, struct devrequest *cmd); 65 66 static 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 74 static __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 * Read consecutive bytes of data from the SL811H/SL11H buffer 87 */ 88 static 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 * Write consecutive bytes of data to the SL811H/SL11H buffer 100 */ 101 static 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 111 int 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; /* start at 0x50000000 */ 121 /* BP 14 low = USB ON */ 122 immap->im_cpm.cp_pbdat &= ~(BP_USB_VCC); 123 /* PB 14 nomal port */ 124 immap->im_cpm.cp_pbpar &= ~(BP_USB_VCC); 125 /* output */ 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 * This function resets SL811HS controller and detects the speed of 144 * the connecting device 145 * 146 * Return: 0 = no device attached; 1 = USB device attached 147 */ 148 static 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 /* Disable hardware SOF generation, clear all irq status. */ 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 /* Device is not present */ 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 /* Send SOF to address 0, endpoint 0. */ 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 /* full speed device connect directly to root hub */ 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 /* start the SOF or EOP */ 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 /* slow speed device connect directly to root-hub */ 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 /* start the SOF or EOP */ 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_INSRMV*/SL811_INTR_DONE_A); 211 212 return 1; 213 } 214 215 int usb_lowlevel_init(void) 216 { 217 root_hub_devnum = 0; 218 sl811_hc_reset(); 219 return 0; 220 } 221 222 int usb_lowlevel_stop(void) 223 { 224 sl811_hc_reset(); 225 return 0; 226 } 227 228 static int calc_needed_buswidth(int bytes, int need_preamble) 229 { 230 return !need_preamble ? bytes * 8 + 256 : 8 * 8 * bytes + 2048; 231 } 232 233 static 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 306 int 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) /* short packet */ 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 341 int 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 /* setup phase */ 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 /* data phase */ 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) /* short packet */ 381 break; 382 } 383 384 /* status phase */ 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 405 int 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 * SL811 Virtual Root Hub 415 */ 416 417 /* Device descriptor */ 418 static __u8 sl811_rh_dev_des[] = 419 { 420 0x12, /* __u8 bLength; */ 421 0x01, /* __u8 bDescriptorType; Device */ 422 0x10, /* __u16 bcdUSB; v1.1 */ 423 0x01, 424 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ 425 0x00, /* __u8 bDeviceSubClass; */ 426 0x00, /* __u8 bDeviceProtocol; */ 427 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ 428 0x00, /* __u16 idVendor; */ 429 0x00, 430 0x00, /* __u16 idProduct; */ 431 0x00, 432 0x00, /* __u16 bcdDevice; */ 433 0x00, 434 0x00, /* __u8 iManufacturer; */ 435 0x02, /* __u8 iProduct; */ 436 0x01, /* __u8 iSerialNumber; */ 437 0x01 /* __u8 bNumConfigurations; */ 438 }; 439 440 /* Configuration descriptor */ 441 static __u8 sl811_rh_config_des[] = 442 { 443 0x09, /* __u8 bLength; */ 444 0x02, /* __u8 bDescriptorType; Configuration */ 445 0x19, /* __u16 wTotalLength; */ 446 0x00, 447 0x01, /* __u8 bNumInterfaces; */ 448 0x01, /* __u8 bConfigurationValue; */ 449 0x00, /* __u8 iConfiguration; */ 450 0x40, /* __u8 bmAttributes; 451 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 452 4..0: resvd */ 453 0x00, /* __u8 MaxPower; */ 454 455 /* interface */ 456 0x09, /* __u8 if_bLength; */ 457 0x04, /* __u8 if_bDescriptorType; Interface */ 458 0x00, /* __u8 if_bInterfaceNumber; */ 459 0x00, /* __u8 if_bAlternateSetting; */ 460 0x01, /* __u8 if_bNumEndpoints; */ 461 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ 462 0x00, /* __u8 if_bInterfaceSubClass; */ 463 0x00, /* __u8 if_bInterfaceProtocol; */ 464 0x00, /* __u8 if_iInterface; */ 465 466 /* endpoint */ 467 0x07, /* __u8 ep_bLength; */ 468 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 469 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ 470 0x03, /* __u8 ep_bmAttributes; Interrupt */ 471 0x08, /* __u16 ep_wMaxPacketSize; */ 472 0x00, 473 0xff /* __u8 ep_bInterval; 255 ms */ 474 }; 475 476 /* root hub class descriptor*/ 477 static __u8 sl811_rh_hub_des[] = 478 { 479 0x09, /* __u8 bLength; */ 480 0x29, /* __u8 bDescriptorType; Hub-descriptor */ 481 0x01, /* __u8 bNbrPorts; */ 482 0x00, /* __u16 wHubCharacteristics; */ 483 0x00, 484 0x50, /* __u8 bPwrOn2pwrGood; 2ms */ 485 0x00, /* __u8 bHubContrCurrent; 0 mA */ 486 0xfc, /* __u8 DeviceRemovable; *** 7 Ports max *** */ 487 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ 488 }; 489 490 /* 491 * helper routine for returning string descriptors in UTF-16LE 492 * input can actually be ISO-8859-1; ASCII is its 7-bit subset 493 */ 494 static 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 * root_hub_string is used by each host controller's root hub code, 507 * so that they're identified consistently throughout the system. 508 */ 509 static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len) 510 { 511 char buf [30]; 512 513 /* assert (len > (2 * (sizeof (buf) + 1))); 514 assert (strlen (type) <= 8);*/ 515 516 /* language ids */ 517 if (id == 0) { 518 *data++ = 4; *data++ = 3; /* 4 bytes data */ 519 *data++ = 0; *data++ = 0; /* some language id */ 520 return 4; 521 522 /* serial number */ 523 } else if (id == 1) { 524 sprintf (buf, "%#x", serial); 525 526 /* product description */ 527 } else if (id == 2) { 528 sprintf (buf, "USB %s Root Hub", type); 529 530 /* id 3 == vendor description */ 531 532 /* unsupported IDs --> "stall" */ 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 /* helper macro */ 543 #define OK(x) len = (x); break 544 545 /* 546 * This function handles all USB request to the the virtual root hub 547 */ 548 static 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 /* Request Destination: 575 without flags: Device, 576 USB_RECIP_INTERFACE: interface, 577 USB_RECIP_ENDPOINT: endpoint, 578 USB_TYPE_CLASS means HUB here, 579 USB_RECIP_OTHER | USB_TYPE_CLASS almost ever means HUB_PORT here 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