This source file includes following definitions.
- ast_vhub_patch_dev_desc_usb1
- ast_vhub_hub_dev_status
- ast_vhub_hub_ep_status
- ast_vhub_hub_dev_feature
- ast_vhub_hub_ep_feature
- ast_vhub_rep_desc
- ast_vhub_rep_string
- ast_vhub_std_hub_request
- ast_vhub_update_hub_ep1
- ast_vhub_change_port_stat
- ast_vhub_send_host_wakeup
- ast_vhub_device_connect
- ast_vhub_wake_work
- ast_vhub_hub_wake_all
- ast_vhub_port_reset
- ast_vhub_set_port_feature
- ast_vhub_clr_port_feature
- ast_vhub_get_port_stat
- ast_vhub_class_hub_request
- ast_vhub_hub_suspend
- ast_vhub_hub_resume
- ast_vhub_hub_reset
- ast_vhub_init_hub
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 #include <linux/kernel.h>
  16 #include <linux/module.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/delay.h>
  19 #include <linux/ioport.h>
  20 #include <linux/slab.h>
  21 #include <linux/errno.h>
  22 #include <linux/list.h>
  23 #include <linux/interrupt.h>
  24 #include <linux/proc_fs.h>
  25 #include <linux/prefetch.h>
  26 #include <linux/clk.h>
  27 #include <linux/usb/gadget.h>
  28 #include <linux/of.h>
  29 #include <linux/of_gpio.h>
  30 #include <linux/regmap.h>
  31 #include <linux/dma-mapping.h>
  32 #include <linux/bcd.h>
  33 #include <linux/version.h>
  34 #include <linux/usb.h>
  35 #include <linux/usb/hcd.h>
  36 
  37 #include "vhub.h"
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 #define KERNEL_REL      bin2bcd(((LINUX_VERSION_CODE >> 16) & 0x0ff))
  50 #define KERNEL_VER      bin2bcd(((LINUX_VERSION_CODE >> 8) & 0x0ff))
  51 
  52 enum {
  53         AST_VHUB_STR_MANUF = 3,
  54         AST_VHUB_STR_PRODUCT = 2,
  55         AST_VHUB_STR_SERIAL = 1,
  56 };
  57 
  58 static const struct usb_device_descriptor ast_vhub_dev_desc = {
  59         .bLength                = USB_DT_DEVICE_SIZE,
  60         .bDescriptorType        = USB_DT_DEVICE,
  61         .bcdUSB                 = cpu_to_le16(0x0200),
  62         .bDeviceClass           = USB_CLASS_HUB,
  63         .bDeviceSubClass        = 0,
  64         .bDeviceProtocol        = 1,
  65         .bMaxPacketSize0        = 64,
  66         .idVendor               = cpu_to_le16(0x1d6b),
  67         .idProduct              = cpu_to_le16(0x0107),
  68         .bcdDevice              = cpu_to_le16(0x0100),
  69         .iManufacturer          = AST_VHUB_STR_MANUF,
  70         .iProduct               = AST_VHUB_STR_PRODUCT,
  71         .iSerialNumber          = AST_VHUB_STR_SERIAL,
  72         .bNumConfigurations     = 1,
  73 };
  74 
  75 
  76 static void ast_vhub_patch_dev_desc_usb1(struct usb_device_descriptor *desc)
  77 {
  78         desc->bcdUSB = cpu_to_le16(0x0100);
  79         desc->bDeviceProtocol = 0;
  80 }
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89 
  90 
  91 
  92 #define AST_VHUB_CONF_DESC_SIZE (USB_DT_CONFIG_SIZE + \
  93                                  USB_DT_INTERFACE_SIZE + \
  94                                  USB_DT_ENDPOINT_SIZE)
  95 
  96 static const struct ast_vhub_full_cdesc {
  97         struct usb_config_descriptor    cfg;
  98         struct usb_interface_descriptor intf;
  99         struct usb_endpoint_descriptor  ep;
 100 } __attribute__ ((packed)) ast_vhub_conf_desc = {
 101         .cfg = {
 102                 .bLength                = USB_DT_CONFIG_SIZE,
 103                 .bDescriptorType        = USB_DT_CONFIG,
 104                 .wTotalLength           = cpu_to_le16(AST_VHUB_CONF_DESC_SIZE),
 105                 .bNumInterfaces         = 1,
 106                 .bConfigurationValue    = 1,
 107                 .iConfiguration         = 0,
 108                 .bmAttributes           = USB_CONFIG_ATT_ONE |
 109                                           USB_CONFIG_ATT_SELFPOWER |
 110                                           USB_CONFIG_ATT_WAKEUP,
 111                 .bMaxPower              = 0,
 112         },
 113         .intf = {
 114                 .bLength                = USB_DT_INTERFACE_SIZE,
 115                 .bDescriptorType        = USB_DT_INTERFACE,
 116                 .bInterfaceNumber       = 0,
 117                 .bAlternateSetting      = 0,
 118                 .bNumEndpoints          = 1,
 119                 .bInterfaceClass        = USB_CLASS_HUB,
 120                 .bInterfaceSubClass     = 0,
 121                 .bInterfaceProtocol     = 0,
 122                 .iInterface             = 0,
 123         },
 124         .ep = {
 125                 .bLength                = USB_DT_ENDPOINT_SIZE,
 126                 .bDescriptorType        = USB_DT_ENDPOINT,
 127                 .bEndpointAddress       = 0x81,
 128                 .bmAttributes           = USB_ENDPOINT_XFER_INT,
 129                 .wMaxPacketSize         = cpu_to_le16(1),
 130                 .bInterval              = 0x0c,
 131         },
 132 };
 133 
 134 #define AST_VHUB_HUB_DESC_SIZE  (USB_DT_HUB_NONVAR_SIZE + 2)
 135 
 136 static const struct usb_hub_descriptor ast_vhub_hub_desc = {
 137         .bDescLength                    = AST_VHUB_HUB_DESC_SIZE,
 138         .bDescriptorType                = USB_DT_HUB,
 139         .bNbrPorts                      = AST_VHUB_NUM_PORTS,
 140         .wHubCharacteristics            = cpu_to_le16(HUB_CHAR_NO_LPSM),
 141         .bPwrOn2PwrGood                 = 10,
 142         .bHubContrCurrent               = 0,
 143         .u.hs.DeviceRemovable[0]        = 0,
 144         .u.hs.DeviceRemovable[1]        = 0xff,
 145 };
 146 
 147 
 148 
 149 
 150 
 151 static const struct usb_string ast_vhub_str_array[] = {
 152         {
 153                 .id = AST_VHUB_STR_SERIAL,
 154                 .s = "00000000"
 155         },
 156         {
 157                 .id = AST_VHUB_STR_PRODUCT,
 158                 .s = "USB Virtual Hub"
 159         },
 160         {
 161                 .id = AST_VHUB_STR_MANUF,
 162                 .s = "Aspeed"
 163         },
 164         { }
 165 };
 166 
 167 static const struct usb_gadget_strings ast_vhub_strings = {
 168         .language = 0x0409,
 169         .strings = (struct usb_string *)ast_vhub_str_array
 170 };
 171 
 172 static int ast_vhub_hub_dev_status(struct ast_vhub_ep *ep,
 173                                    u16 wIndex, u16 wValue)
 174 {
 175         u8 st0;
 176 
 177         EPDBG(ep, "GET_STATUS(dev)\n");
 178 
 179         
 180 
 181 
 182 
 183         st0 = 1 << USB_DEVICE_SELF_POWERED;
 184 
 185         
 186 
 187 
 188 
 189         if (ep->vhub->wakeup_en)
 190                 st0 |= 1 << USB_DEVICE_REMOTE_WAKEUP;
 191 
 192         return ast_vhub_simple_reply(ep, st0, 0);
 193 }
 194 
 195 static int ast_vhub_hub_ep_status(struct ast_vhub_ep *ep,
 196                                   u16 wIndex, u16 wValue)
 197 {
 198         int ep_num;
 199         u8 st0 = 0;
 200 
 201         ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
 202         EPDBG(ep, "GET_STATUS(ep%d)\n", ep_num);
 203 
 204         
 205         if (ep_num == 1) {
 206                 if (ep->vhub->ep1_stalled)
 207                         st0 |= 1 << USB_ENDPOINT_HALT;
 208         } else if (ep_num != 0)
 209                 return std_req_stall;
 210 
 211         return ast_vhub_simple_reply(ep, st0, 0);
 212 }
 213 
 214 static int ast_vhub_hub_dev_feature(struct ast_vhub_ep *ep,
 215                                     u16 wIndex, u16 wValue,
 216                                     bool is_set)
 217 {
 218         EPDBG(ep, "%s_FEATURE(dev val=%02x)\n",
 219               is_set ? "SET" : "CLEAR", wValue);
 220 
 221         if (wValue != USB_DEVICE_REMOTE_WAKEUP)
 222                 return std_req_stall;
 223 
 224         ep->vhub->wakeup_en = is_set;
 225         EPDBG(ep, "Hub remote wakeup %s\n",
 226               is_set ? "enabled" : "disabled");
 227 
 228         return std_req_complete;
 229 }
 230 
 231 static int ast_vhub_hub_ep_feature(struct ast_vhub_ep *ep,
 232                                    u16 wIndex, u16 wValue,
 233                                    bool is_set)
 234 {
 235         int ep_num;
 236         u32 reg;
 237 
 238         ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
 239         EPDBG(ep, "%s_FEATURE(ep%d val=%02x)\n",
 240               is_set ? "SET" : "CLEAR", ep_num, wValue);
 241 
 242         if (ep_num > 1)
 243                 return std_req_stall;
 244         if (wValue != USB_ENDPOINT_HALT)
 245                 return std_req_stall;
 246         if (ep_num == 0)
 247                 return std_req_complete;
 248 
 249         EPDBG(ep, "%s stall on EP 1\n",
 250               is_set ? "setting" : "clearing");
 251 
 252         ep->vhub->ep1_stalled = is_set;
 253         reg = readl(ep->vhub->regs + AST_VHUB_EP1_CTRL);
 254         if (is_set) {
 255                 reg |= VHUB_EP1_CTRL_STALL;
 256         } else {
 257                 reg &= ~VHUB_EP1_CTRL_STALL;
 258                 reg |= VHUB_EP1_CTRL_RESET_TOGGLE;
 259         }
 260         writel(reg, ep->vhub->regs + AST_VHUB_EP1_CTRL);
 261 
 262         return std_req_complete;
 263 }
 264 
 265 static int ast_vhub_rep_desc(struct ast_vhub_ep *ep,
 266                              u8 desc_type, u16 len)
 267 {
 268         size_t dsize;
 269 
 270         EPDBG(ep, "GET_DESCRIPTOR(type:%d)\n", desc_type);
 271 
 272         
 273 
 274 
 275 
 276 
 277 
 278 
 279 
 280 
 281         switch(desc_type) {
 282         case USB_DT_DEVICE:
 283                 dsize = USB_DT_DEVICE_SIZE;
 284                 memcpy(ep->buf, &ast_vhub_dev_desc, dsize);
 285                 BUILD_BUG_ON(dsize > sizeof(ast_vhub_dev_desc));
 286                 BUILD_BUG_ON(USB_DT_DEVICE_SIZE >= AST_VHUB_EP0_MAX_PACKET);
 287                 break;
 288         case USB_DT_CONFIG:
 289                 dsize = AST_VHUB_CONF_DESC_SIZE;
 290                 memcpy(ep->buf, &ast_vhub_conf_desc, dsize);
 291                 BUILD_BUG_ON(dsize > sizeof(ast_vhub_conf_desc));
 292                 BUILD_BUG_ON(AST_VHUB_CONF_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
 293                 break;
 294         case USB_DT_HUB:
 295                 dsize = AST_VHUB_HUB_DESC_SIZE;
 296                 memcpy(ep->buf, &ast_vhub_hub_desc, dsize);
 297                 BUILD_BUG_ON(dsize > sizeof(ast_vhub_hub_desc));
 298                 BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
 299                 break;
 300         default:
 301                 return std_req_stall;
 302         }
 303 
 304         
 305         if (len > dsize)
 306                 len = dsize;
 307 
 308         
 309         if (desc_type == USB_DT_DEVICE && ep->vhub->force_usb1)
 310                 ast_vhub_patch_dev_desc_usb1(ep->buf);
 311 
 312         
 313         return ast_vhub_reply(ep, NULL, len);
 314 }
 315 
 316 static int ast_vhub_rep_string(struct ast_vhub_ep *ep,
 317                                u8 string_id, u16 lang_id,
 318                                u16 len)
 319 {
 320         int rc = usb_gadget_get_string (&ast_vhub_strings, string_id, ep->buf);
 321 
 322         
 323 
 324 
 325 
 326         BUG_ON(rc >= AST_VHUB_EP0_MAX_PACKET);
 327 
 328         if (rc < 0)
 329                 return std_req_stall;
 330 
 331         
 332         return ast_vhub_reply(ep, NULL, min_t(u16, rc, len));
 333 }
 334 
 335 enum std_req_rc ast_vhub_std_hub_request(struct ast_vhub_ep *ep,
 336                                          struct usb_ctrlrequest *crq)
 337 {
 338         struct ast_vhub *vhub = ep->vhub;
 339         u16 wValue, wIndex, wLength;
 340 
 341         wValue = le16_to_cpu(crq->wValue);
 342         wIndex = le16_to_cpu(crq->wIndex);
 343         wLength = le16_to_cpu(crq->wLength);
 344 
 345         
 346         if (vhub->speed == USB_SPEED_UNKNOWN) {
 347                 u32 ustat = readl(vhub->regs + AST_VHUB_USBSTS);
 348                 if (ustat & VHUB_USBSTS_HISPEED)
 349                         vhub->speed = USB_SPEED_HIGH;
 350                 else
 351                         vhub->speed = USB_SPEED_FULL;
 352                 UDCDBG(vhub, "USB status=%08x speed=%s\n", ustat,
 353                        vhub->speed == USB_SPEED_HIGH ? "high" : "full");
 354         }
 355 
 356         switch ((crq->bRequestType << 8) | crq->bRequest) {
 357                 
 358         case DeviceOutRequest | USB_REQ_SET_ADDRESS:
 359                 EPDBG(ep, "SET_ADDRESS: Got address %x\n", wValue);
 360                 writel(wValue, vhub->regs + AST_VHUB_CONF);
 361                 return std_req_complete;
 362 
 363                 
 364         case DeviceRequest | USB_REQ_GET_STATUS:
 365                 return ast_vhub_hub_dev_status(ep, wIndex, wValue);
 366         case InterfaceRequest | USB_REQ_GET_STATUS:
 367                 return ast_vhub_simple_reply(ep, 0, 0);
 368         case EndpointRequest | USB_REQ_GET_STATUS:
 369                 return ast_vhub_hub_ep_status(ep, wIndex, wValue);
 370 
 371                 
 372         case DeviceOutRequest | USB_REQ_SET_FEATURE:
 373                 return ast_vhub_hub_dev_feature(ep, wIndex, wValue, true);
 374         case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
 375                 return ast_vhub_hub_dev_feature(ep, wIndex, wValue, false);
 376         case EndpointOutRequest | USB_REQ_SET_FEATURE:
 377                 return ast_vhub_hub_ep_feature(ep, wIndex, wValue, true);
 378         case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
 379                 return ast_vhub_hub_ep_feature(ep, wIndex, wValue, false);
 380 
 381                 
 382         case DeviceRequest | USB_REQ_GET_CONFIGURATION:
 383                 return ast_vhub_simple_reply(ep, 1);
 384         case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
 385                 if (wValue != 1)
 386                         return std_req_stall;
 387                 return std_req_complete;
 388 
 389                 
 390         case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
 391                 switch (wValue >> 8) {
 392                 case USB_DT_DEVICE:
 393                 case USB_DT_CONFIG:
 394                         return ast_vhub_rep_desc(ep, wValue >> 8,
 395                                                  wLength);
 396                 case USB_DT_STRING:
 397                         return ast_vhub_rep_string(ep, wValue & 0xff,
 398                                                    wIndex, wLength);
 399                 }
 400                 return std_req_stall;
 401 
 402                 
 403         case DeviceRequest | USB_REQ_GET_INTERFACE:
 404                 return ast_vhub_simple_reply(ep, 0);
 405         case DeviceOutRequest | USB_REQ_SET_INTERFACE:
 406                 if (wValue != 0 || wIndex != 0)
 407                         return std_req_stall;
 408                 return std_req_complete;
 409         }
 410         return std_req_stall;
 411 }
 412 
 413 static void ast_vhub_update_hub_ep1(struct ast_vhub *vhub,
 414                                     unsigned int port)
 415 {
 416         
 417         u32 reg = readl(vhub->regs + AST_VHUB_EP1_STS_CHG);
 418         u32 pmask = (1 << (port + 1));
 419         if (vhub->ports[port].change)
 420                 reg |= pmask;
 421         else
 422                 reg &= ~pmask;
 423         writel(reg, vhub->regs + AST_VHUB_EP1_STS_CHG);
 424 }
 425 
 426 static void ast_vhub_change_port_stat(struct ast_vhub *vhub,
 427                                       unsigned int port,
 428                                       u16 clr_flags,
 429                                       u16 set_flags,
 430                                       bool set_c)
 431 {
 432         struct ast_vhub_port *p = &vhub->ports[port];
 433         u16 prev;
 434 
 435         
 436         prev = p->status;
 437         p->status = (prev & ~clr_flags) | set_flags;
 438         DDBG(&p->dev, "port %d status %04x -> %04x (C=%d)\n",
 439              port + 1, prev, p->status, set_c);
 440 
 441         
 442         if (set_c) {
 443                 u16 chg = p->status ^ prev;
 444 
 445                 
 446                 chg &= USB_PORT_STAT_C_CONNECTION |
 447                        USB_PORT_STAT_C_ENABLE |
 448                        USB_PORT_STAT_C_SUSPEND |
 449                        USB_PORT_STAT_C_OVERCURRENT |
 450                        USB_PORT_STAT_C_RESET |
 451                        USB_PORT_STAT_C_L1;
 452 
 453                 
 454 
 455 
 456 
 457                 if (p->status & USB_PORT_STAT_ENABLE)
 458                         chg &= ~USB_PORT_STAT_C_ENABLE;
 459 
 460                 p->change = chg;
 461                 ast_vhub_update_hub_ep1(vhub, port);
 462         }
 463 }
 464 
 465 static void ast_vhub_send_host_wakeup(struct ast_vhub *vhub)
 466 {
 467         u32 reg = readl(vhub->regs + AST_VHUB_CTRL);
 468         UDCDBG(vhub, "Waking up host !\n");
 469         reg |= VHUB_CTRL_MANUAL_REMOTE_WAKEUP;
 470         writel(reg, vhub->regs + AST_VHUB_CTRL);
 471 }
 472 
 473 void ast_vhub_device_connect(struct ast_vhub *vhub,
 474                              unsigned int port, bool on)
 475 {
 476         if (on)
 477                 ast_vhub_change_port_stat(vhub, port, 0,
 478                                           USB_PORT_STAT_CONNECTION, true);
 479         else
 480                 ast_vhub_change_port_stat(vhub, port,
 481                                           USB_PORT_STAT_CONNECTION |
 482                                           USB_PORT_STAT_ENABLE,
 483                                           0, true);
 484 
 485         
 486 
 487 
 488 
 489         if (vhub->wakeup_en)
 490                 ast_vhub_send_host_wakeup(vhub);
 491 }
 492 
 493 static void ast_vhub_wake_work(struct work_struct *work)
 494 {
 495         struct ast_vhub *vhub = container_of(work,
 496                                              struct ast_vhub,
 497                                              wake_work);
 498         unsigned long flags;
 499         unsigned int i;
 500 
 501         
 502 
 503 
 504 
 505 
 506         spin_lock_irqsave(&vhub->lock, flags);
 507         for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
 508                 struct ast_vhub_port *p = &vhub->ports[i];
 509 
 510                 if (!(p->status & USB_PORT_STAT_SUSPEND))
 511                         continue;
 512                 ast_vhub_change_port_stat(vhub, i,
 513                                           USB_PORT_STAT_SUSPEND,
 514                                           0, true);
 515                 ast_vhub_dev_resume(&p->dev);
 516         }
 517         ast_vhub_send_host_wakeup(vhub);
 518         spin_unlock_irqrestore(&vhub->lock, flags);
 519 }
 520 
 521 void ast_vhub_hub_wake_all(struct ast_vhub *vhub)
 522 {
 523         
 524 
 525 
 526 
 527 
 528         schedule_work(&vhub->wake_work);
 529 }
 530 
 531 static void ast_vhub_port_reset(struct ast_vhub *vhub, u8 port)
 532 {
 533         struct ast_vhub_port *p = &vhub->ports[port];
 534         u16 set, clr, speed;
 535 
 536         
 537         ast_vhub_change_port_stat(vhub, port,
 538                                   USB_PORT_STAT_ENABLE |
 539                                   USB_PORT_STAT_SUSPEND,
 540                                   USB_PORT_STAT_RESET,
 541                                   false);
 542 
 543         if (!p->dev.driver)
 544                 return;
 545 
 546         
 547 
 548 
 549 
 550         ast_vhub_dev_reset(&p->dev);
 551 
 552         
 553         speed = p->dev.driver->max_speed;
 554         if (speed == USB_SPEED_UNKNOWN || speed > vhub->speed)
 555                 speed = vhub->speed;
 556 
 557         switch (speed) {
 558         case USB_SPEED_LOW:
 559                 set = USB_PORT_STAT_LOW_SPEED;
 560                 clr = USB_PORT_STAT_HIGH_SPEED;
 561                 break;
 562         case USB_SPEED_FULL:
 563                 set = 0;
 564                 clr = USB_PORT_STAT_LOW_SPEED |
 565                         USB_PORT_STAT_HIGH_SPEED;
 566                 break;
 567         case USB_SPEED_HIGH:
 568                 set = USB_PORT_STAT_HIGH_SPEED;
 569                 clr = USB_PORT_STAT_LOW_SPEED;
 570                 break;
 571         default:
 572                 UDCDBG(vhub, "Unsupported speed %d when"
 573                        " connecting device\n",
 574                        speed);
 575                 return;
 576         }
 577         clr |= USB_PORT_STAT_RESET;
 578         set |= USB_PORT_STAT_ENABLE;
 579 
 580         
 581         ast_vhub_change_port_stat(vhub, port, clr, set, true);
 582 }
 583 
 584 static enum std_req_rc ast_vhub_set_port_feature(struct ast_vhub_ep *ep,
 585                                                  u8 port, u16 feat)
 586 {
 587         struct ast_vhub *vhub = ep->vhub;
 588         struct ast_vhub_port *p;
 589 
 590         if (port == 0 || port > AST_VHUB_NUM_PORTS)
 591                 return std_req_stall;
 592         port--;
 593         p = &vhub->ports[port];
 594 
 595         switch(feat) {
 596         case USB_PORT_FEAT_SUSPEND:
 597                 if (!(p->status & USB_PORT_STAT_ENABLE))
 598                         return std_req_complete;
 599                 ast_vhub_change_port_stat(vhub, port,
 600                                           0, USB_PORT_STAT_SUSPEND,
 601                                           false);
 602                 ast_vhub_dev_suspend(&p->dev);
 603                 return std_req_complete;
 604         case USB_PORT_FEAT_RESET:
 605                 EPDBG(ep, "Port reset !\n");
 606                 ast_vhub_port_reset(vhub, port);
 607                 return std_req_complete;
 608         case USB_PORT_FEAT_POWER:
 609                 
 610 
 611 
 612 
 613 
 614                 if (p->status & USB_PORT_STAT_CONNECTION) {
 615                         p->change |= USB_PORT_STAT_C_CONNECTION;
 616                         ast_vhub_update_hub_ep1(vhub, port);
 617                 }
 618                 return std_req_complete;
 619         case USB_PORT_FEAT_TEST:
 620         case USB_PORT_FEAT_INDICATOR:
 621                 
 622                 return std_req_complete;
 623         }
 624         return std_req_stall;
 625 }
 626 
 627 static enum std_req_rc ast_vhub_clr_port_feature(struct ast_vhub_ep *ep,
 628                                                  u8 port, u16 feat)
 629 {
 630         struct ast_vhub *vhub = ep->vhub;
 631         struct ast_vhub_port *p;
 632 
 633         if (port == 0 || port > AST_VHUB_NUM_PORTS)
 634                 return std_req_stall;
 635         port--;
 636         p = &vhub->ports[port];
 637 
 638         switch(feat) {
 639         case USB_PORT_FEAT_ENABLE:
 640                 ast_vhub_change_port_stat(vhub, port,
 641                                           USB_PORT_STAT_ENABLE |
 642                                           USB_PORT_STAT_SUSPEND, 0,
 643                                           false);
 644                 ast_vhub_dev_suspend(&p->dev);
 645                 return std_req_complete;
 646         case USB_PORT_FEAT_SUSPEND:
 647                 if (!(p->status & USB_PORT_STAT_SUSPEND))
 648                         return std_req_complete;
 649                 ast_vhub_change_port_stat(vhub, port,
 650                                           USB_PORT_STAT_SUSPEND, 0,
 651                                           false);
 652                 ast_vhub_dev_resume(&p->dev);
 653                 return std_req_complete;
 654         case USB_PORT_FEAT_POWER:
 655                 
 656                 return std_req_complete;
 657         case USB_PORT_FEAT_INDICATOR:
 658                 
 659                 return std_req_complete;
 660         case USB_PORT_FEAT_C_CONNECTION:
 661         case USB_PORT_FEAT_C_ENABLE:
 662         case USB_PORT_FEAT_C_SUSPEND:
 663         case USB_PORT_FEAT_C_OVER_CURRENT:
 664         case USB_PORT_FEAT_C_RESET:
 665                 
 666                 p->change &= ~(1u << (feat - 16));
 667                 ast_vhub_update_hub_ep1(vhub, port);
 668                 return std_req_complete;
 669         }
 670         return std_req_stall;
 671 }
 672 
 673 static enum std_req_rc ast_vhub_get_port_stat(struct ast_vhub_ep *ep,
 674                                               u8 port)
 675 {
 676         struct ast_vhub *vhub = ep->vhub;
 677         u16 stat, chg;
 678 
 679         if (port == 0 || port > AST_VHUB_NUM_PORTS)
 680                 return std_req_stall;
 681         port--;
 682 
 683         stat = vhub->ports[port].status;
 684         chg = vhub->ports[port].change;
 685 
 686         
 687         stat |= USB_PORT_STAT_POWER;
 688 
 689         EPDBG(ep, " port status=%04x change=%04x\n", stat, chg);
 690 
 691         return ast_vhub_simple_reply(ep,
 692                                      stat & 0xff,
 693                                      stat >> 8,
 694                                      chg & 0xff,
 695                                      chg >> 8);
 696 }
 697 
 698 enum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep,
 699                                            struct usb_ctrlrequest *crq)
 700 {
 701         u16 wValue, wIndex, wLength;
 702 
 703         wValue = le16_to_cpu(crq->wValue);
 704         wIndex = le16_to_cpu(crq->wIndex);
 705         wLength = le16_to_cpu(crq->wLength);
 706 
 707         switch ((crq->bRequestType << 8) | crq->bRequest) {
 708         case GetHubStatus:
 709                 EPDBG(ep, "GetHubStatus\n");
 710                 return ast_vhub_simple_reply(ep, 0, 0, 0, 0);
 711         case GetPortStatus:
 712                 EPDBG(ep, "GetPortStatus(%d)\n", wIndex & 0xff);
 713                 return ast_vhub_get_port_stat(ep, wIndex & 0xf);
 714         case GetHubDescriptor:
 715                 if (wValue != (USB_DT_HUB << 8))
 716                         return std_req_stall;
 717                 EPDBG(ep, "GetHubDescriptor(%d)\n", wIndex & 0xff);
 718                 return ast_vhub_rep_desc(ep, USB_DT_HUB, wLength);
 719         case SetHubFeature:
 720         case ClearHubFeature:
 721                 EPDBG(ep, "Get/SetHubFeature(%d)\n", wValue);
 722                 
 723                 if (wValue == C_HUB_LOCAL_POWER ||
 724                     wValue == C_HUB_OVER_CURRENT)
 725                         return std_req_complete;
 726                 return std_req_stall;
 727         case SetPortFeature:
 728                 EPDBG(ep, "SetPortFeature(%d,%d)\n", wIndex & 0xf, wValue);
 729                 return ast_vhub_set_port_feature(ep, wIndex & 0xf, wValue);
 730         case ClearPortFeature:
 731                 EPDBG(ep, "ClearPortFeature(%d,%d)\n", wIndex & 0xf, wValue);
 732                 return ast_vhub_clr_port_feature(ep, wIndex & 0xf, wValue);
 733         case ClearTTBuffer:
 734         case ResetTT:
 735         case StopTT:
 736                 return std_req_complete;
 737         case GetTTState:
 738                 return ast_vhub_simple_reply(ep, 0, 0, 0, 0);
 739         default:
 740                 EPDBG(ep, "Unknown class request\n");
 741         }
 742         return std_req_stall;
 743 }
 744 
 745 void ast_vhub_hub_suspend(struct ast_vhub *vhub)
 746 {
 747         unsigned int i;
 748 
 749         UDCDBG(vhub, "USB bus suspend\n");
 750 
 751         if (vhub->suspended)
 752                 return;
 753 
 754         vhub->suspended = true;
 755 
 756         
 757 
 758 
 759 
 760         for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
 761                 struct ast_vhub_port *p = &vhub->ports[i];
 762 
 763                 if (!(p->status & USB_PORT_STAT_SUSPEND))
 764                         ast_vhub_dev_suspend(&p->dev);
 765         }
 766 }
 767 
 768 void ast_vhub_hub_resume(struct ast_vhub *vhub)
 769 {
 770         unsigned int i;
 771 
 772         UDCDBG(vhub, "USB bus resume\n");
 773 
 774         if (!vhub->suspended)
 775                 return;
 776 
 777         vhub->suspended = false;
 778 
 779         
 780 
 781 
 782 
 783         for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
 784                 struct ast_vhub_port *p = &vhub->ports[i];
 785 
 786                 if (!(p->status & USB_PORT_STAT_SUSPEND))
 787                         ast_vhub_dev_resume(&p->dev);
 788         }
 789 }
 790 
 791 void ast_vhub_hub_reset(struct ast_vhub *vhub)
 792 {
 793         unsigned int i;
 794 
 795         UDCDBG(vhub, "USB bus reset\n");
 796 
 797         
 798 
 799 
 800 
 801         if (vhub->speed == USB_SPEED_UNKNOWN)
 802                 return;
 803 
 804         
 805         vhub->suspended = false;
 806 
 807         
 808         vhub->speed = USB_SPEED_UNKNOWN;
 809 
 810         
 811         vhub->wakeup_en = false;
 812 
 813         
 814 
 815 
 816 
 817         for (i = 0; i < AST_VHUB_NUM_PORTS; i++) {
 818                 struct ast_vhub_port *p = &vhub->ports[i];
 819 
 820                 
 821                 p->status &= USB_PORT_STAT_CONNECTION;
 822                 p->change = 0;
 823 
 824                 
 825                 ast_vhub_dev_suspend(&p->dev);
 826         }
 827 
 828         
 829         writel(0, vhub->regs + AST_VHUB_CONF);
 830         writel(0, vhub->regs + AST_VHUB_EP0_CTRL);
 831         writel(VHUB_EP1_CTRL_RESET_TOGGLE |
 832                VHUB_EP1_CTRL_ENABLE,
 833                vhub->regs + AST_VHUB_EP1_CTRL);
 834         writel(0, vhub->regs + AST_VHUB_EP1_STS_CHG);
 835 }
 836 
 837 void ast_vhub_init_hub(struct ast_vhub *vhub)
 838 {
 839         vhub->speed = USB_SPEED_UNKNOWN;
 840         INIT_WORK(&vhub->wake_work, ast_vhub_wake_work);
 841 }
 842