linux/drivers/usb/gadget/udc/aspeed-vhub/hub.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget
   4 *
   5 * hub.c - virtual hub handling
   6 *
   7 * Copyright 2017 IBM Corporation
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  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/* usb 2.0 hub device descriptor
  40 *
  41 * A few things we may want to improve here:
  42 *
  43 *    - We may need to indicate TT support
  44 *    - We may need a device qualifier descriptor
  45 *      as devices can pretend to be usb1 or 2
  46 *    - Make vid/did overridable
  47 *    - make it look like usb1 if usb1 mode forced
  48 */
  49#define KERNEL_REL      bin2bcd(LINUX_VERSION_MAJOR)
  50#define KERNEL_VER      bin2bcd(LINUX_VERSION_PATCHLEVEL)
  51
  52enum {
  53        AST_VHUB_STR_INDEX_MAX = 4,
  54        AST_VHUB_STR_MANUF = 3,
  55        AST_VHUB_STR_PRODUCT = 2,
  56        AST_VHUB_STR_SERIAL = 1,
  57};
  58
  59static const struct usb_device_descriptor ast_vhub_dev_desc = {
  60        .bLength                = USB_DT_DEVICE_SIZE,
  61        .bDescriptorType        = USB_DT_DEVICE,
  62        .bcdUSB                 = cpu_to_le16(0x0200),
  63        .bDeviceClass           = USB_CLASS_HUB,
  64        .bDeviceSubClass        = 0,
  65        .bDeviceProtocol        = 1,
  66        .bMaxPacketSize0        = 64,
  67        .idVendor               = cpu_to_le16(0x1d6b),
  68        .idProduct              = cpu_to_le16(0x0107),
  69        .bcdDevice              = cpu_to_le16(0x0100),
  70        .iManufacturer          = AST_VHUB_STR_MANUF,
  71        .iProduct               = AST_VHUB_STR_PRODUCT,
  72        .iSerialNumber          = AST_VHUB_STR_SERIAL,
  73        .bNumConfigurations     = 1,
  74};
  75
  76/*
  77 * Configuration descriptor: same comments as above
  78 * regarding handling USB1 mode.
  79 */
  80
  81/*
  82 * We don't use sizeof() as Linux definition of
  83 * struct usb_endpoint_descriptor contains 2
  84 * extra bytes
  85 */
  86#define AST_VHUB_CONF_DESC_SIZE (USB_DT_CONFIG_SIZE + \
  87                                 USB_DT_INTERFACE_SIZE + \
  88                                 USB_DT_ENDPOINT_SIZE)
  89
  90static const struct ast_vhub_full_cdesc ast_vhub_conf_desc = {
  91        .cfg = {
  92                .bLength                = USB_DT_CONFIG_SIZE,
  93                .bDescriptorType        = USB_DT_CONFIG,
  94                .wTotalLength           = cpu_to_le16(AST_VHUB_CONF_DESC_SIZE),
  95                .bNumInterfaces         = 1,
  96                .bConfigurationValue    = 1,
  97                .iConfiguration         = 0,
  98                .bmAttributes           = USB_CONFIG_ATT_ONE |
  99                                          USB_CONFIG_ATT_SELFPOWER |
 100                                          USB_CONFIG_ATT_WAKEUP,
 101                .bMaxPower              = 0,
 102        },
 103        .intf = {
 104                .bLength                = USB_DT_INTERFACE_SIZE,
 105                .bDescriptorType        = USB_DT_INTERFACE,
 106                .bInterfaceNumber       = 0,
 107                .bAlternateSetting      = 0,
 108                .bNumEndpoints          = 1,
 109                .bInterfaceClass        = USB_CLASS_HUB,
 110                .bInterfaceSubClass     = 0,
 111                .bInterfaceProtocol     = 0,
 112                .iInterface             = 0,
 113        },
 114        .ep = {
 115                .bLength                = USB_DT_ENDPOINT_SIZE,
 116                .bDescriptorType        = USB_DT_ENDPOINT,
 117                .bEndpointAddress       = 0x81,
 118                .bmAttributes           = USB_ENDPOINT_XFER_INT,
 119                .wMaxPacketSize         = cpu_to_le16(1),
 120                .bInterval              = 0x0c,
 121        },
 122};
 123
 124#define AST_VHUB_HUB_DESC_SIZE  (USB_DT_HUB_NONVAR_SIZE + 2)
 125
 126static const struct usb_hub_descriptor ast_vhub_hub_desc = {
 127        .bDescLength                    = AST_VHUB_HUB_DESC_SIZE,
 128        .bDescriptorType                = USB_DT_HUB,
 129        .bNbrPorts                      = AST_VHUB_NUM_PORTS,
 130        .wHubCharacteristics            = cpu_to_le16(HUB_CHAR_NO_LPSM),
 131        .bPwrOn2PwrGood                 = 10,
 132        .bHubContrCurrent               = 0,
 133        .u.hs.DeviceRemovable[0]        = 0,
 134        .u.hs.DeviceRemovable[1]        = 0xff,
 135};
 136
 137/*
 138 * These strings converted to UTF-16 must be smaller than
 139 * our EP0 buffer.
 140 */
 141static const struct usb_string ast_vhub_str_array[] = {
 142        {
 143                .id = AST_VHUB_STR_SERIAL,
 144                .s = "00000000"
 145        },
 146        {
 147                .id = AST_VHUB_STR_PRODUCT,
 148                .s = "USB Virtual Hub"
 149        },
 150        {
 151                .id = AST_VHUB_STR_MANUF,
 152                .s = "Aspeed"
 153        },
 154        { }
 155};
 156
 157static const struct usb_gadget_strings ast_vhub_strings = {
 158        .language = 0x0409,
 159        .strings = (struct usb_string *)ast_vhub_str_array
 160};
 161
 162static int ast_vhub_hub_dev_status(struct ast_vhub_ep *ep,
 163                                   u16 wIndex, u16 wValue)
 164{
 165        u8 st0;
 166
 167        EPDBG(ep, "GET_STATUS(dev)\n");
 168
 169        /*
 170         * Mark it as self-powered, I doubt the BMC is powered off
 171         * the USB bus ...
 172         */
 173        st0 = 1 << USB_DEVICE_SELF_POWERED;
 174
 175        /*
 176         * Need to double check how remote wakeup actually works
 177         * on that chip and what triggers it.
 178         */
 179        if (ep->vhub->wakeup_en)
 180                st0 |= 1 << USB_DEVICE_REMOTE_WAKEUP;
 181
 182        return ast_vhub_simple_reply(ep, st0, 0);
 183}
 184
 185static int ast_vhub_hub_ep_status(struct ast_vhub_ep *ep,
 186                                  u16 wIndex, u16 wValue)
 187{
 188        int ep_num;
 189        u8 st0 = 0;
 190
 191        ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
 192        EPDBG(ep, "GET_STATUS(ep%d)\n", ep_num);
 193
 194        /* On the hub we have only EP 0 and 1 */
 195        if (ep_num == 1) {
 196                if (ep->vhub->ep1_stalled)
 197                        st0 |= 1 << USB_ENDPOINT_HALT;
 198        } else if (ep_num != 0)
 199                return std_req_stall;
 200
 201        return ast_vhub_simple_reply(ep, st0, 0);
 202}
 203
 204static int ast_vhub_hub_dev_feature(struct ast_vhub_ep *ep,
 205                                    u16 wIndex, u16 wValue,
 206                                    bool is_set)
 207{
 208        EPDBG(ep, "%s_FEATURE(dev val=%02x)\n",
 209              is_set ? "SET" : "CLEAR", wValue);
 210
 211        if (wValue != USB_DEVICE_REMOTE_WAKEUP)
 212                return std_req_stall;
 213
 214        ep->vhub->wakeup_en = is_set;
 215        EPDBG(ep, "Hub remote wakeup %s\n",
 216              is_set ? "enabled" : "disabled");
 217
 218        return std_req_complete;
 219}
 220
 221static int ast_vhub_hub_ep_feature(struct ast_vhub_ep *ep,
 222                                   u16 wIndex, u16 wValue,
 223                                   bool is_set)
 224{
 225        int ep_num;
 226        u32 reg;
 227
 228        ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
 229        EPDBG(ep, "%s_FEATURE(ep%d val=%02x)\n",
 230              is_set ? "SET" : "CLEAR", ep_num, wValue);
 231
 232        if (ep_num > 1)
 233                return std_req_stall;
 234        if (wValue != USB_ENDPOINT_HALT)
 235                return std_req_stall;
 236        if (ep_num == 0)
 237                return std_req_complete;
 238
 239        EPDBG(ep, "%s stall on EP 1\n",
 240              is_set ? "setting" : "clearing");
 241
 242        ep->vhub->ep1_stalled = is_set;
 243        reg = readl(ep->vhub->regs + AST_VHUB_EP1_CTRL);
 244        if (is_set) {
 245                reg |= VHUB_EP1_CTRL_STALL;
 246        } else {
 247                reg &= ~VHUB_EP1_CTRL_STALL;
 248                reg |= VHUB_EP1_CTRL_RESET_TOGGLE;
 249        }
 250        writel(reg, ep->vhub->regs + AST_VHUB_EP1_CTRL);
 251
 252        return std_req_complete;
 253}
 254
 255static int ast_vhub_rep_desc(struct ast_vhub_ep *ep,
 256                             u8 desc_type, u16 len)
 257{
 258        size_t dsize;
 259        struct ast_vhub *vhub = ep->vhub;
 260
 261        EPDBG(ep, "GET_DESCRIPTOR(type:%d)\n", desc_type);
 262
 263        /*
 264         * Copy first to EP buffer and send from there, so
 265         * we can do some in-place patching if needed. We know
 266         * the EP buffer is big enough but ensure that doesn't
 267         * change. We do that now rather than later after we
 268         * have checked sizes etc... to avoid a gcc bug where
 269         * it thinks len is constant and barfs about read
 270         * overflows in memcpy.
 271         */
 272        switch(desc_type) {
 273        case USB_DT_DEVICE:
 274                dsize = USB_DT_DEVICE_SIZE;
 275                memcpy(ep->buf, &vhub->vhub_dev_desc, dsize);
 276                BUILD_BUG_ON(dsize > sizeof(vhub->vhub_dev_desc));
 277                BUILD_BUG_ON(USB_DT_DEVICE_SIZE >= AST_VHUB_EP0_MAX_PACKET);
 278                break;
 279        case USB_DT_CONFIG:
 280                dsize = AST_VHUB_CONF_DESC_SIZE;
 281                memcpy(ep->buf, &vhub->vhub_conf_desc, dsize);
 282                BUILD_BUG_ON(dsize > sizeof(vhub->vhub_conf_desc));
 283                BUILD_BUG_ON(AST_VHUB_CONF_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
 284                break;
 285        case USB_DT_HUB:
 286                dsize = AST_VHUB_HUB_DESC_SIZE;
 287                memcpy(ep->buf, &vhub->vhub_hub_desc, dsize);
 288                BUILD_BUG_ON(dsize > sizeof(vhub->vhub_hub_desc));
 289                BUILD_BUG_ON(AST_VHUB_HUB_DESC_SIZE >= AST_VHUB_EP0_MAX_PACKET);
 290                break;
 291        default:
 292                return std_req_stall;
 293        }
 294
 295        /* Crop requested length */
 296        if (len > dsize)
 297                len = dsize;
 298
 299        /* Shoot it from the EP buffer */
 300        return ast_vhub_reply(ep, NULL, len);
 301}
 302
 303static struct usb_gadget_strings*
 304ast_vhub_str_of_container(struct usb_gadget_string_container *container)
 305{
 306        return (struct usb_gadget_strings *)container->stash;
 307}
 308
 309static int ast_vhub_collect_languages(struct ast_vhub *vhub, void *buf,
 310                                      size_t size)
 311{
 312        int rc, hdr_len, nlangs, max_langs;
 313        struct usb_gadget_strings *lang_str;
 314        struct usb_gadget_string_container *container;
 315        struct usb_string_descriptor *sdesc = buf;
 316
 317        nlangs = 0;
 318        hdr_len = sizeof(struct usb_descriptor_header);
 319        max_langs = (size - hdr_len) / sizeof(sdesc->wData[0]);
 320        list_for_each_entry(container, &vhub->vhub_str_desc, list) {
 321                if (nlangs >= max_langs)
 322                        break;
 323
 324                lang_str = ast_vhub_str_of_container(container);
 325                sdesc->wData[nlangs++] = cpu_to_le16(lang_str->language);
 326        }
 327
 328        rc = hdr_len + nlangs * sizeof(sdesc->wData[0]);
 329        sdesc->bLength = rc;
 330        sdesc->bDescriptorType = USB_DT_STRING;
 331
 332        return rc;
 333}
 334
 335static struct usb_gadget_strings *ast_vhub_lookup_string(struct ast_vhub *vhub,
 336                                                         u16 lang_id)
 337{
 338        struct usb_gadget_strings *lang_str;
 339        struct usb_gadget_string_container *container;
 340
 341        list_for_each_entry(container, &vhub->vhub_str_desc, list) {
 342                lang_str = ast_vhub_str_of_container(container);
 343                if (lang_str->language == lang_id)
 344                        return lang_str;
 345        }
 346
 347        return NULL;
 348}
 349
 350static int ast_vhub_rep_string(struct ast_vhub_ep *ep,
 351                               u8 string_id, u16 lang_id,
 352                               u16 len)
 353{
 354        int rc;
 355        u8 buf[256];
 356        struct ast_vhub *vhub = ep->vhub;
 357        struct usb_gadget_strings *lang_str;
 358
 359        if (string_id == 0) {
 360                rc = ast_vhub_collect_languages(vhub, buf, sizeof(buf));
 361        } else {
 362                lang_str = ast_vhub_lookup_string(vhub, lang_id);
 363                if (!lang_str)
 364                        return std_req_stall;
 365
 366                rc = usb_gadget_get_string(lang_str, string_id, buf);
 367        }
 368
 369        if (rc < 0 || rc >= AST_VHUB_EP0_MAX_PACKET)
 370                return std_req_stall;
 371
 372        /* Shoot it from the EP buffer */
 373        memcpy(ep->buf, buf, rc);
 374        return ast_vhub_reply(ep, NULL, min_t(u16, rc, len));
 375}
 376
 377enum std_req_rc ast_vhub_std_hub_request(struct ast_vhub_ep *ep,
 378                                         struct usb_ctrlrequest *crq)
 379{
 380        struct ast_vhub *vhub = ep->vhub;
 381        u16 wValue, wIndex, wLength;
 382
 383        wValue = le16_to_cpu(crq->wValue);
 384        wIndex = le16_to_cpu(crq->wIndex);
 385        wLength = le16_to_cpu(crq->wLength);
 386
 387        /* First packet, grab speed */
 388        if (vhub->speed == USB_SPEED_UNKNOWN) {
 389                u32 ustat = readl(vhub->regs + AST_VHUB_USBSTS);
 390                if (ustat & VHUB_USBSTS_HISPEED)
 391                        vhub->speed = USB_SPEED_HIGH;
 392                else
 393                        vhub->speed = USB_SPEED_FULL;
 394                UDCDBG(vhub, "USB status=%08x speed=%s\n", ustat,
 395                       vhub->speed == USB_SPEED_HIGH ? "high" : "full");
 396        }
 397
 398        switch ((crq->bRequestType << 8) | crq->bRequest) {
 399                /* SET_ADDRESS */
 400        case DeviceOutRequest | USB_REQ_SET_ADDRESS:
 401                EPDBG(ep, "SET_ADDRESS: Got address %x\n", wValue);
 402                writel(wValue, vhub->regs + AST_VHUB_CONF);
 403                return std_req_complete;
 404
 405                /* GET_STATUS */
 406        case DeviceRequest | USB_REQ_GET_STATUS:
 407                return ast_vhub_hub_dev_status(ep, wIndex, wValue);
 408        case InterfaceRequest | USB_REQ_GET_STATUS:
 409                return ast_vhub_simple_reply(ep, 0, 0);
 410        case EndpointRequest | USB_REQ_GET_STATUS:
 411                return ast_vhub_hub_ep_status(ep, wIndex, wValue);
 412
 413                /* SET/CLEAR_FEATURE */
 414        case DeviceOutRequest | USB_REQ_SET_FEATURE:
 415                return ast_vhub_hub_dev_feature(ep, wIndex, wValue, true);
 416        case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
 417                return ast_vhub_hub_dev_feature(ep, wIndex, wValue, false);
 418        case EndpointOutRequest | USB_REQ_SET_FEATURE:
 419                return ast_vhub_hub_ep_feature(ep, wIndex, wValue, true);
 420        case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
 421                return ast_vhub_hub_ep_feature(ep, wIndex, wValue, false);
 422
 423                /* GET/SET_CONFIGURATION */
 424        case DeviceRequest | USB_REQ_GET_CONFIGURATION:
 425                return ast_vhub_simple_reply(ep, 1);
 426        case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
 427                if (wValue != 1)
 428                        return std_req_stall;
 429                return std_req_complete;
 430
 431                /* GET_DESCRIPTOR */
 432        case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
 433                switch (wValue >> 8) {
 434                case USB_DT_DEVICE:
 435                case USB_DT_CONFIG:
 436                        return ast_vhub_rep_desc(ep, wValue >> 8,
 437                                                 wLength);
 438                case USB_DT_STRING:
 439                        return ast_vhub_rep_string(ep, wValue & 0xff,
 440                                                   wIndex, wLength);
 441                }
 442                return std_req_stall;
 443
 444                /* GET/SET_INTERFACE */
 445        case DeviceRequest | USB_REQ_GET_INTERFACE:
 446                return ast_vhub_simple_reply(ep, 0);
 447        case DeviceOutRequest | USB_REQ_SET_INTERFACE:
 448                if (wValue != 0 || wIndex != 0)
 449                        return std_req_stall;
 450                return std_req_complete;
 451        }
 452        return std_req_stall;
 453}
 454
 455static void ast_vhub_update_hub_ep1(struct ast_vhub *vhub,
 456                                    unsigned int port)
 457{
 458        /* Update HW EP1 response */
 459        u32 reg = readl(vhub->regs + AST_VHUB_EP1_STS_CHG);
 460        u32 pmask = (1 << (port + 1));
 461        if (vhub->ports[port].change)
 462                reg |= pmask;
 463        else
 464                reg &= ~pmask;
 465        writel(reg, vhub->regs + AST_VHUB_EP1_STS_CHG);
 466}
 467
 468static void ast_vhub_change_port_stat(struct ast_vhub *vhub,
 469                                      unsigned int port,
 470                                      u16 clr_flags,
 471                                      u16 set_flags,
 472                                      bool set_c)
 473{
 474        struct ast_vhub_port *p = &vhub->ports[port];
 475        u16 prev;
 476
 477        /* Update port status */
 478        prev = p->status;
 479        p->status = (prev & ~clr_flags) | set_flags;
 480        DDBG(&p->dev, "port %d status %04x -> %04x (C=%d)\n",
 481             port + 1, prev, p->status, set_c);
 482
 483        /* Update change bits if needed */
 484        if (set_c) {
 485                u16 chg = p->status ^ prev;
 486
 487                /* Only these are relevant for change */
 488                chg &= USB_PORT_STAT_C_CONNECTION |
 489                       USB_PORT_STAT_C_ENABLE |
 490                       USB_PORT_STAT_C_SUSPEND |
 491                       USB_PORT_STAT_C_OVERCURRENT |
 492                       USB_PORT_STAT_C_RESET |
 493                       USB_PORT_STAT_C_L1;
 494
 495                /*
 496                 * We only set USB_PORT_STAT_C_ENABLE if we are disabling
 497                 * the port as per USB spec, otherwise MacOS gets upset
 498                 */
 499                if (p->status & USB_PORT_STAT_ENABLE)
 500                        chg &= ~USB_PORT_STAT_C_ENABLE;
 501
 502                p->change = chg;
 503                ast_vhub_update_hub_ep1(vhub, port);
 504        }
 505}
 506
 507static void ast_vhub_send_host_wakeup(struct ast_vhub *vhub)
 508{
 509        u32 reg = readl(vhub->regs + AST_VHUB_CTRL);
 510        UDCDBG(vhub, "Waking up host !\n");
 511        reg |= VHUB_CTRL_MANUAL_REMOTE_WAKEUP;
 512        writel(reg, vhub->regs + AST_VHUB_CTRL);
 513}
 514
 515void ast_vhub_device_connect(struct ast_vhub *vhub,
 516                             unsigned int port, bool on)
 517{
 518        if (on)
 519                ast_vhub_change_port_stat(vhub, port, 0,
 520                                          USB_PORT_STAT_CONNECTION, true);
 521        else
 522                ast_vhub_change_port_stat(vhub, port,
 523                                          USB_PORT_STAT_CONNECTION |
 524                                          USB_PORT_STAT_ENABLE,
 525                                          0, true);
 526
 527        /*
 528         * If the hub is set to wakup the host on connection events
 529         * then send a wakeup.
 530         */
 531        if (vhub->wakeup_en)
 532                ast_vhub_send_host_wakeup(vhub);
 533}
 534
 535static void ast_vhub_wake_work(struct work_struct *work)
 536{
 537        struct ast_vhub *vhub = container_of(work,
 538                                             struct ast_vhub,
 539                                             wake_work);
 540        unsigned long flags;
 541        unsigned int i;
 542
 543        /*
 544         * Wake all sleeping ports. If a port is suspended by
 545         * the host suspend (without explicit state suspend),
 546         * we let the normal host wake path deal with it later.
 547         */
 548        spin_lock_irqsave(&vhub->lock, flags);
 549        for (i = 0; i < vhub->max_ports; i++) {
 550                struct ast_vhub_port *p = &vhub->ports[i];
 551
 552                if (!(p->status & USB_PORT_STAT_SUSPEND))
 553                        continue;
 554                ast_vhub_change_port_stat(vhub, i,
 555                                          USB_PORT_STAT_SUSPEND,
 556                                          0, true);
 557                ast_vhub_dev_resume(&p->dev);
 558        }
 559        ast_vhub_send_host_wakeup(vhub);
 560        spin_unlock_irqrestore(&vhub->lock, flags);
 561}
 562
 563void ast_vhub_hub_wake_all(struct ast_vhub *vhub)
 564{
 565        /*
 566         * A device is trying to wake the world, because this
 567         * can recurse into the device, we break the call chain
 568         * using a work queue
 569         */
 570        schedule_work(&vhub->wake_work);
 571}
 572
 573static void ast_vhub_port_reset(struct ast_vhub *vhub, u8 port)
 574{
 575        struct ast_vhub_port *p = &vhub->ports[port];
 576        u16 set, clr, speed;
 577
 578        /* First mark disabled */
 579        ast_vhub_change_port_stat(vhub, port,
 580                                  USB_PORT_STAT_ENABLE |
 581                                  USB_PORT_STAT_SUSPEND,
 582                                  USB_PORT_STAT_RESET,
 583                                  false);
 584
 585        if (!p->dev.driver)
 586                return;
 587
 588        /*
 589         * This will either "start" the port or reset the
 590         * device if already started...
 591         */
 592        ast_vhub_dev_reset(&p->dev);
 593
 594        /* Grab the right speed */
 595        speed = p->dev.driver->max_speed;
 596        if (speed == USB_SPEED_UNKNOWN || speed > vhub->speed)
 597                speed = vhub->speed;
 598
 599        switch (speed) {
 600        case USB_SPEED_LOW:
 601                set = USB_PORT_STAT_LOW_SPEED;
 602                clr = USB_PORT_STAT_HIGH_SPEED;
 603                break;
 604        case USB_SPEED_FULL:
 605                set = 0;
 606                clr = USB_PORT_STAT_LOW_SPEED |
 607                        USB_PORT_STAT_HIGH_SPEED;
 608                break;
 609        case USB_SPEED_HIGH:
 610                set = USB_PORT_STAT_HIGH_SPEED;
 611                clr = USB_PORT_STAT_LOW_SPEED;
 612                break;
 613        default:
 614                UDCDBG(vhub, "Unsupported speed %d when"
 615                       " connecting device\n",
 616                       speed);
 617                return;
 618        }
 619        clr |= USB_PORT_STAT_RESET;
 620        set |= USB_PORT_STAT_ENABLE;
 621
 622        /* This should ideally be delayed ... */
 623        ast_vhub_change_port_stat(vhub, port, clr, set, true);
 624}
 625
 626static enum std_req_rc ast_vhub_set_port_feature(struct ast_vhub_ep *ep,
 627                                                 u8 port, u16 feat)
 628{
 629        struct ast_vhub *vhub = ep->vhub;
 630        struct ast_vhub_port *p;
 631
 632        if (port == 0 || port > vhub->max_ports)
 633                return std_req_stall;
 634        port--;
 635        p = &vhub->ports[port];
 636
 637        switch(feat) {
 638        case USB_PORT_FEAT_SUSPEND:
 639                if (!(p->status & USB_PORT_STAT_ENABLE))
 640                        return std_req_complete;
 641                ast_vhub_change_port_stat(vhub, port,
 642                                          0, USB_PORT_STAT_SUSPEND,
 643                                          false);
 644                ast_vhub_dev_suspend(&p->dev);
 645                return std_req_complete;
 646        case USB_PORT_FEAT_RESET:
 647                EPDBG(ep, "Port reset !\n");
 648                ast_vhub_port_reset(vhub, port);
 649                return std_req_complete;
 650        case USB_PORT_FEAT_POWER:
 651                /*
 652                 * On Power-on, we mark the connected flag changed,
 653                 * if there's a connected device, some hosts will
 654                 * otherwise fail to detect it.
 655                 */
 656                if (p->status & USB_PORT_STAT_CONNECTION) {
 657                        p->change |= USB_PORT_STAT_C_CONNECTION;
 658                        ast_vhub_update_hub_ep1(vhub, port);
 659                }
 660                return std_req_complete;
 661        case USB_PORT_FEAT_TEST:
 662        case USB_PORT_FEAT_INDICATOR:
 663                /* We don't do anything with these */
 664                return std_req_complete;
 665        }
 666        return std_req_stall;
 667}
 668
 669static enum std_req_rc ast_vhub_clr_port_feature(struct ast_vhub_ep *ep,
 670                                                 u8 port, u16 feat)
 671{
 672        struct ast_vhub *vhub = ep->vhub;
 673        struct ast_vhub_port *p;
 674
 675        if (port == 0 || port > vhub->max_ports)
 676                return std_req_stall;
 677        port--;
 678        p = &vhub->ports[port];
 679
 680        switch(feat) {
 681        case USB_PORT_FEAT_ENABLE:
 682                ast_vhub_change_port_stat(vhub, port,
 683                                          USB_PORT_STAT_ENABLE |
 684                                          USB_PORT_STAT_SUSPEND, 0,
 685                                          false);
 686                ast_vhub_dev_suspend(&p->dev);
 687                return std_req_complete;
 688        case USB_PORT_FEAT_SUSPEND:
 689                if (!(p->status & USB_PORT_STAT_SUSPEND))
 690                        return std_req_complete;
 691                ast_vhub_change_port_stat(vhub, port,
 692                                          USB_PORT_STAT_SUSPEND, 0,
 693                                          false);
 694                ast_vhub_dev_resume(&p->dev);
 695                return std_req_complete;
 696        case USB_PORT_FEAT_POWER:
 697                /* We don't do power control */
 698                return std_req_complete;
 699        case USB_PORT_FEAT_INDICATOR:
 700                /* We don't have indicators */
 701                return std_req_complete;
 702        case USB_PORT_FEAT_C_CONNECTION:
 703        case USB_PORT_FEAT_C_ENABLE:
 704        case USB_PORT_FEAT_C_SUSPEND:
 705        case USB_PORT_FEAT_C_OVER_CURRENT:
 706        case USB_PORT_FEAT_C_RESET:
 707                /* Clear state-change feature */
 708                p->change &= ~(1u << (feat - 16));
 709                ast_vhub_update_hub_ep1(vhub, port);
 710                return std_req_complete;
 711        }
 712        return std_req_stall;
 713}
 714
 715static enum std_req_rc ast_vhub_get_port_stat(struct ast_vhub_ep *ep,
 716                                              u8 port)
 717{
 718        struct ast_vhub *vhub = ep->vhub;
 719        u16 stat, chg;
 720
 721        if (port == 0 || port > vhub->max_ports)
 722                return std_req_stall;
 723        port--;
 724
 725        stat = vhub->ports[port].status;
 726        chg = vhub->ports[port].change;
 727
 728        /* We always have power */
 729        stat |= USB_PORT_STAT_POWER;
 730
 731        EPDBG(ep, " port status=%04x change=%04x\n", stat, chg);
 732
 733        return ast_vhub_simple_reply(ep,
 734                                     stat & 0xff,
 735                                     stat >> 8,
 736                                     chg & 0xff,
 737                                     chg >> 8);
 738}
 739
 740enum std_req_rc ast_vhub_class_hub_request(struct ast_vhub_ep *ep,
 741                                           struct usb_ctrlrequest *crq)
 742{
 743        u16 wValue, wIndex, wLength;
 744
 745        wValue = le16_to_cpu(crq->wValue);
 746        wIndex = le16_to_cpu(crq->wIndex);
 747        wLength = le16_to_cpu(crq->wLength);
 748
 749        switch ((crq->bRequestType << 8) | crq->bRequest) {
 750        case GetHubStatus:
 751                EPDBG(ep, "GetHubStatus\n");
 752                return ast_vhub_simple_reply(ep, 0, 0, 0, 0);
 753        case GetPortStatus:
 754                EPDBG(ep, "GetPortStatus(%d)\n", wIndex & 0xff);
 755                return ast_vhub_get_port_stat(ep, wIndex & 0xf);
 756        case GetHubDescriptor:
 757                if (wValue != (USB_DT_HUB << 8))
 758                        return std_req_stall;
 759                EPDBG(ep, "GetHubDescriptor(%d)\n", wIndex & 0xff);
 760                return ast_vhub_rep_desc(ep, USB_DT_HUB, wLength);
 761        case SetHubFeature:
 762        case ClearHubFeature:
 763                EPDBG(ep, "Get/SetHubFeature(%d)\n", wValue);
 764                /* No feature, just complete the requests */
 765                if (wValue == C_HUB_LOCAL_POWER ||
 766                    wValue == C_HUB_OVER_CURRENT)
 767                        return std_req_complete;
 768                return std_req_stall;
 769        case SetPortFeature:
 770                EPDBG(ep, "SetPortFeature(%d,%d)\n", wIndex & 0xf, wValue);
 771                return ast_vhub_set_port_feature(ep, wIndex & 0xf, wValue);
 772        case ClearPortFeature:
 773                EPDBG(ep, "ClearPortFeature(%d,%d)\n", wIndex & 0xf, wValue);
 774                return ast_vhub_clr_port_feature(ep, wIndex & 0xf, wValue);
 775        case ClearTTBuffer:
 776        case ResetTT:
 777        case StopTT:
 778                return std_req_complete;
 779        case GetTTState:
 780                return ast_vhub_simple_reply(ep, 0, 0, 0, 0);
 781        default:
 782                EPDBG(ep, "Unknown class request\n");
 783        }
 784        return std_req_stall;
 785}
 786
 787void ast_vhub_hub_suspend(struct ast_vhub *vhub)
 788{
 789        unsigned int i;
 790
 791        UDCDBG(vhub, "USB bus suspend\n");
 792
 793        if (vhub->suspended)
 794                return;
 795
 796        vhub->suspended = true;
 797
 798        /*
 799         * Forward to unsuspended ports without changing
 800         * their connection status.
 801         */
 802        for (i = 0; i < vhub->max_ports; i++) {
 803                struct ast_vhub_port *p = &vhub->ports[i];
 804
 805                if (!(p->status & USB_PORT_STAT_SUSPEND))
 806                        ast_vhub_dev_suspend(&p->dev);
 807        }
 808}
 809
 810void ast_vhub_hub_resume(struct ast_vhub *vhub)
 811{
 812        unsigned int i;
 813
 814        UDCDBG(vhub, "USB bus resume\n");
 815
 816        if (!vhub->suspended)
 817                return;
 818
 819        vhub->suspended = false;
 820
 821        /*
 822         * Forward to unsuspended ports without changing
 823         * their connection status.
 824         */
 825        for (i = 0; i < vhub->max_ports; i++) {
 826                struct ast_vhub_port *p = &vhub->ports[i];
 827
 828                if (!(p->status & USB_PORT_STAT_SUSPEND))
 829                        ast_vhub_dev_resume(&p->dev);
 830        }
 831}
 832
 833void ast_vhub_hub_reset(struct ast_vhub *vhub)
 834{
 835        unsigned int i;
 836
 837        UDCDBG(vhub, "USB bus reset\n");
 838
 839        /*
 840         * Is the speed known ? If not we don't care, we aren't
 841         * initialized yet and ports haven't been enabled.
 842         */
 843        if (vhub->speed == USB_SPEED_UNKNOWN)
 844                return;
 845
 846        /* We aren't suspended anymore obviously */
 847        vhub->suspended = false;
 848
 849        /* No speed set */
 850        vhub->speed = USB_SPEED_UNKNOWN;
 851
 852        /* Wakeup not enabled anymore */
 853        vhub->wakeup_en = false;
 854
 855        /*
 856         * Clear all port status, disable gadgets and "suspend"
 857         * them. They will be woken up by a port reset.
 858         */
 859        for (i = 0; i < vhub->max_ports; i++) {
 860                struct ast_vhub_port *p = &vhub->ports[i];
 861
 862                /* Only keep the connected flag */
 863                p->status &= USB_PORT_STAT_CONNECTION;
 864                p->change = 0;
 865
 866                /* Suspend the gadget if any */
 867                ast_vhub_dev_suspend(&p->dev);
 868        }
 869
 870        /* Cleanup HW */
 871        writel(0, vhub->regs + AST_VHUB_CONF);
 872        writel(0, vhub->regs + AST_VHUB_EP0_CTRL);
 873        writel(VHUB_EP1_CTRL_RESET_TOGGLE |
 874               VHUB_EP1_CTRL_ENABLE,
 875               vhub->regs + AST_VHUB_EP1_CTRL);
 876        writel(0, vhub->regs + AST_VHUB_EP1_STS_CHG);
 877}
 878
 879static void ast_vhub_of_parse_dev_desc(struct ast_vhub *vhub,
 880                                       const struct device_node *vhub_np)
 881{
 882        u16 id;
 883        u32 data;
 884
 885        if (!of_property_read_u32(vhub_np, "vhub-vendor-id", &data)) {
 886                id = (u16)data;
 887                vhub->vhub_dev_desc.idVendor = cpu_to_le16(id);
 888        }
 889        if (!of_property_read_u32(vhub_np, "vhub-product-id", &data)) {
 890                id = (u16)data;
 891                vhub->vhub_dev_desc.idProduct = cpu_to_le16(id);
 892        }
 893        if (!of_property_read_u32(vhub_np, "vhub-device-revision", &data)) {
 894                id = (u16)data;
 895                vhub->vhub_dev_desc.bcdDevice = cpu_to_le16(id);
 896        }
 897}
 898
 899static void ast_vhub_fixup_usb1_dev_desc(struct ast_vhub *vhub)
 900{
 901        vhub->vhub_dev_desc.bcdUSB = cpu_to_le16(0x0100);
 902        vhub->vhub_dev_desc.bDeviceProtocol = 0;
 903}
 904
 905static struct usb_gadget_string_container*
 906ast_vhub_str_container_alloc(struct ast_vhub *vhub)
 907{
 908        unsigned int size;
 909        struct usb_string *str_array;
 910        struct usb_gadget_strings *lang_str;
 911        struct usb_gadget_string_container *container;
 912
 913        size = sizeof(*container);
 914        size += sizeof(struct usb_gadget_strings);
 915        size += sizeof(struct usb_string) * AST_VHUB_STR_INDEX_MAX;
 916        container = devm_kzalloc(&vhub->pdev->dev, size, GFP_KERNEL);
 917        if (!container)
 918                return ERR_PTR(-ENOMEM);
 919
 920        lang_str = ast_vhub_str_of_container(container);
 921        str_array = (struct usb_string *)(lang_str + 1);
 922        lang_str->strings = str_array;
 923        return container;
 924}
 925
 926static void ast_vhub_str_deep_copy(struct usb_gadget_strings *dest,
 927                                   const struct usb_gadget_strings *src)
 928{
 929        struct usb_string *src_array = src->strings;
 930        struct usb_string *dest_array = dest->strings;
 931
 932        dest->language = src->language;
 933        if (src_array && dest_array) {
 934                do {
 935                        *dest_array = *src_array;
 936                        dest_array++;
 937                        src_array++;
 938                } while (src_array->s);
 939        }
 940}
 941
 942static int ast_vhub_str_alloc_add(struct ast_vhub *vhub,
 943                                  const struct usb_gadget_strings *src_str)
 944{
 945        struct usb_gadget_strings *dest_str;
 946        struct usb_gadget_string_container *container;
 947
 948        container = ast_vhub_str_container_alloc(vhub);
 949        if (IS_ERR(container))
 950                return PTR_ERR(container);
 951
 952        dest_str = ast_vhub_str_of_container(container);
 953        ast_vhub_str_deep_copy(dest_str, src_str);
 954        list_add_tail(&container->list, &vhub->vhub_str_desc);
 955
 956        return 0;
 957}
 958
 959static const struct {
 960        const char *name;
 961        u8 id;
 962} str_id_map[] = {
 963        {"manufacturer",        AST_VHUB_STR_MANUF},
 964        {"product",             AST_VHUB_STR_PRODUCT},
 965        {"serial-number",       AST_VHUB_STR_SERIAL},
 966        {},
 967};
 968
 969static int ast_vhub_of_parse_str_desc(struct ast_vhub *vhub,
 970                                      const struct device_node *desc_np)
 971{
 972        u32 langid;
 973        int ret = 0;
 974        int i, offset;
 975        const char *str;
 976        struct device_node *child;
 977        struct usb_string str_array[AST_VHUB_STR_INDEX_MAX];
 978        struct usb_gadget_strings lang_str = {
 979                .strings = (struct usb_string *)str_array,
 980        };
 981
 982        for_each_child_of_node(desc_np, child) {
 983                if (of_property_read_u32(child, "reg", &langid))
 984                        continue; /* no language identifier specified */
 985
 986                if (!usb_validate_langid(langid))
 987                        continue; /* invalid language identifier */
 988
 989                lang_str.language = langid;
 990                for (i = offset = 0; str_id_map[i].name; i++) {
 991                        str = of_get_property(child, str_id_map[i].name, NULL);
 992                        if (str) {
 993                                str_array[offset].s = str;
 994                                str_array[offset].id = str_id_map[i].id;
 995                                offset++;
 996                        }
 997                }
 998                str_array[offset].id = 0;
 999                str_array[offset].s = NULL;
1000
1001                ret = ast_vhub_str_alloc_add(vhub, &lang_str);
1002                if (ret) {
1003                        of_node_put(child);
1004                        break;
1005                }
1006        }
1007
1008        return ret;
1009}
1010
1011static int ast_vhub_init_desc(struct ast_vhub *vhub)
1012{
1013        int ret;
1014        struct device_node *desc_np;
1015        const struct device_node *vhub_np = vhub->pdev->dev.of_node;
1016
1017        /* Initialize vhub Device Descriptor. */
1018        memcpy(&vhub->vhub_dev_desc, &ast_vhub_dev_desc,
1019                sizeof(vhub->vhub_dev_desc));
1020        ast_vhub_of_parse_dev_desc(vhub, vhub_np);
1021        if (vhub->force_usb1)
1022                ast_vhub_fixup_usb1_dev_desc(vhub);
1023
1024        /* Initialize vhub Configuration Descriptor. */
1025        memcpy(&vhub->vhub_conf_desc, &ast_vhub_conf_desc,
1026                sizeof(vhub->vhub_conf_desc));
1027
1028        /* Initialize vhub Hub Descriptor. */
1029        memcpy(&vhub->vhub_hub_desc, &ast_vhub_hub_desc,
1030                sizeof(vhub->vhub_hub_desc));
1031        vhub->vhub_hub_desc.bNbrPorts = vhub->max_ports;
1032
1033        /* Initialize vhub String Descriptors. */
1034        INIT_LIST_HEAD(&vhub->vhub_str_desc);
1035        desc_np = of_get_child_by_name(vhub_np, "vhub-strings");
1036        if (desc_np)
1037                ret = ast_vhub_of_parse_str_desc(vhub, desc_np);
1038        else
1039                ret = ast_vhub_str_alloc_add(vhub, &ast_vhub_strings);
1040
1041        return ret;
1042}
1043
1044int ast_vhub_init_hub(struct ast_vhub *vhub)
1045{
1046        vhub->speed = USB_SPEED_UNKNOWN;
1047        INIT_WORK(&vhub->wake_work, ast_vhub_wake_work);
1048
1049        return ast_vhub_init_desc(vhub);
1050}
1051