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