1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2004 4 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 5 * 6 * This code is based on linux driver for sl811hs chip, source at 7 * drivers/usb/host/sl811.c: 8 * 9 * SL811 Host Controller Interface driver for USB. 10 * 11 * Copyright (c) 2003/06, Courage Co., Ltd. 12 * 13 * Based on: 14 * 1.uhci.c by Linus Torvalds, Johannes Erdfelt, Randy Dunlap, 15 * Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber, 16 * Adam Richter, Gregory P. Smith; 17 * 2.Original SL811 driver (hc_sl811.o) by Pei Liu <pbl@cypress.com> 18 * 3.Rewrited as sl811.o by Yin Aihua <yinah:couragetech.com.cn> 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 /* nothing */ 32 #endif 33 34 #define SL811_ADR (0x50000000) 35 #define SL811_DAT (0x50000001) 36 37 #ifdef SL811_DEBUG 38 static int debug = 9; 39 #endif 40 41 static int root_hub_devnum = 0; 42 static struct usb_port_status rh_status = { 0 };/* root hub port status */ 43 44 static int sl811_rh_submit_urb(struct usb_device *usb_dev, unsigned long pipe, 45 void *data, int buf_len, struct devrequest *cmd); 46 47 static 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 55 static __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 * Read consecutive bytes of data from the SL811H/SL11H buffer 68 */ 69 static 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 * Write consecutive bytes of data to the SL811H/SL11H buffer 81 */ 82 static 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 92 int 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; /* start at 0x50000000 */ 102 /* BP 14 low = USB ON */ 103 immap->im_cpm.cp_pbdat &= ~(BP_USB_VCC); 104 /* PB 14 nomal port */ 105 immap->im_cpm.cp_pbpar &= ~(BP_USB_VCC); 106 /* output */ 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 * This function resets SL811HS controller and detects the speed of 125 * the connecting device 126 * 127 * Return: 0 = no device attached; 1 = USB device attached 128 */ 129 static 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 /* Disable hardware SOF generation, clear all irq status. */ 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 /* Device is not present */ 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 /* Send SOF to address 0, endpoint 0. */ 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 /* full speed device connect directly to root hub */ 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 /* start the SOF or EOP */ 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 /* slow speed device connect directly to root-hub */ 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 /* start the SOF or EOP */ 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_INSRMV*/SL811_INTR_DONE_A); 192 193 return 1; 194 } 195 196 int 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 203 int usb_lowlevel_stop(int index) 204 { 205 sl811_hc_reset(); 206 return 0; 207 } 208 209 static int calc_needed_buswidth(int bytes, int need_preamble) 210 { 211 return !need_preamble ? bytes * 8 + 256 : 8 * 8 * bytes + 2048; 212 } 213 214 static 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 287 int 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) /* short packet */ 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 322 int 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 /* setup phase */ 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 /* data phase */ 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) /* short packet */ 362 break; 363 } 364 365 /* status phase */ 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 386 int 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 * SL811 Virtual Root Hub 396 */ 397 398 /* Device descriptor */ 399 static __u8 sl811_rh_dev_des[] = 400 { 401 0x12, /* __u8 bLength; */ 402 0x01, /* __u8 bDescriptorType; Device */ 403 0x10, /* __u16 bcdUSB; v1.1 */ 404 0x01, 405 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ 406 0x00, /* __u8 bDeviceSubClass; */ 407 0x00, /* __u8 bDeviceProtocol; */ 408 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ 409 0x00, /* __u16 idVendor; */ 410 0x00, 411 0x00, /* __u16 idProduct; */ 412 0x00, 413 0x00, /* __u16 bcdDevice; */ 414 0x00, 415 0x00, /* __u8 iManufacturer; */ 416 0x02, /* __u8 iProduct; */ 417 0x01, /* __u8 iSerialNumber; */ 418 0x01 /* __u8 bNumConfigurations; */ 419 }; 420 421 /* Configuration descriptor */ 422 static __u8 sl811_rh_config_des[] = 423 { 424 0x09, /* __u8 bLength; */ 425 0x02, /* __u8 bDescriptorType; Configuration */ 426 0x19, /* __u16 wTotalLength; */ 427 0x00, 428 0x01, /* __u8 bNumInterfaces; */ 429 0x01, /* __u8 bConfigurationValue; */ 430 0x00, /* __u8 iConfiguration; */ 431 0x40, /* __u8 bmAttributes; 432 Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 433 4..0: resvd */ 434 0x00, /* __u8 MaxPower; */ 435 436 /* interface */ 437 0x09, /* __u8 if_bLength; */ 438 0x04, /* __u8 if_bDescriptorType; Interface */ 439 0x00, /* __u8 if_bInterfaceNumber; */ 440 0x00, /* __u8 if_bAlternateSetting; */ 441 0x01, /* __u8 if_bNumEndpoints; */ 442 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ 443 0x00, /* __u8 if_bInterfaceSubClass; */ 444 0x00, /* __u8 if_bInterfaceProtocol; */ 445 0x00, /* __u8 if_iInterface; */ 446 447 /* endpoint */ 448 0x07, /* __u8 ep_bLength; */ 449 0x05, /* __u8 ep_bDescriptorType; Endpoint */ 450 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ 451 0x03, /* __u8 ep_bmAttributes; Interrupt */ 452 0x08, /* __u16 ep_wMaxPacketSize; */ 453 0x00, 454 0xff /* __u8 ep_bInterval; 255 ms */ 455 }; 456 457 /* root hub class descriptor*/ 458 static __u8 sl811_rh_hub_des[] = 459 { 460 0x09, /* __u8 bLength; */ 461 0x29, /* __u8 bDescriptorType; Hub-descriptor */ 462 0x01, /* __u8 bNbrPorts; */ 463 0x00, /* __u16 wHubCharacteristics; */ 464 0x00, 465 0x50, /* __u8 bPwrOn2pwrGood; 2ms */ 466 0x00, /* __u8 bHubContrCurrent; 0 mA */ 467 0xfc, /* __u8 DeviceRemovable; *** 7 Ports max *** */ 468 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ 469 }; 470 471 /* 472 * helper routine for returning string descriptors in UTF-16LE 473 * input can actually be ISO-8859-1; ASCII is its 7-bit subset 474 */ 475 static 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 * root_hub_string is used by each host controller's root hub code, 488 * so that they're identified consistently throughout the system. 489 */ 490 static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len) 491 { 492 char buf [30]; 493 494 /* assert (len > (2 * (sizeof (buf) + 1))); 495 assert (strlen (type) <= 8);*/ 496 497 /* language ids */ 498 if (id == 0) { 499 *data++ = 4; *data++ = 3; /* 4 bytes data */ 500 *data++ = 0; *data++ = 0; /* some language id */ 501 return 4; 502 503 /* serial number */ 504 } else if (id == 1) { 505 sprintf (buf, "%#x", serial); 506 507 /* product description */ 508 } else if (id == 2) { 509 sprintf (buf, "USB %s Root Hub", type); 510 511 /* id 3 == vendor description */ 512 513 /* unsupported IDs --> "stall" */ 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 /* helper macro */ 524 #define OK(x) len = (x); break 525 526 /* 527 * This function handles all USB request to the the virtual root hub 528 */ 529 static 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 /* Request Destination: 554 without flags: Device, 555 USB_RECIP_INTERFACE: interface, 556 USB_RECIP_ENDPOINT: endpoint, 557 USB_TYPE_CLASS means HUB here, 558 USB_RECIP_OTHER | USB_TYPE_CLASS almost ever means HUB_PORT here 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