linux/drivers/usb/gadget/udc/aspeed-vhub/dev.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * aspeed-vhub -- Driver for Aspeed SoC "vHub" USB gadget
   4 *
   5 * dev.c - Individual device/gadget management (ie, a port = a gadget)
   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/usb.h>
  33#include <linux/usb/hcd.h>
  34
  35#include "vhub.h"
  36
  37void ast_vhub_dev_irq(struct ast_vhub_dev *d)
  38{
  39        u32 istat = readl(d->regs + AST_VHUB_DEV_ISR);
  40
  41        writel(istat, d->regs + AST_VHUB_DEV_ISR);
  42
  43        if (istat & VHUV_DEV_IRQ_EP0_IN_ACK_STALL)
  44                ast_vhub_ep0_handle_ack(&d->ep0, true);
  45        if (istat & VHUV_DEV_IRQ_EP0_OUT_ACK_STALL)
  46                ast_vhub_ep0_handle_ack(&d->ep0, false);
  47        if (istat & VHUV_DEV_IRQ_EP0_SETUP)
  48                ast_vhub_ep0_handle_setup(&d->ep0);
  49}
  50
  51static void ast_vhub_dev_enable(struct ast_vhub_dev *d)
  52{
  53        u32 reg, hmsk;
  54
  55        if (d->enabled)
  56                return;
  57
  58        /* Enable device and its EP0 interrupts */
  59        reg = VHUB_DEV_EN_ENABLE_PORT |
  60                VHUB_DEV_EN_EP0_IN_ACK_IRQEN |
  61                VHUB_DEV_EN_EP0_OUT_ACK_IRQEN |
  62                VHUB_DEV_EN_EP0_SETUP_IRQEN;
  63        if (d->gadget.speed == USB_SPEED_HIGH)
  64                reg |= VHUB_DEV_EN_SPEED_SEL_HIGH;
  65        writel(reg, d->regs + AST_VHUB_DEV_EN_CTRL);
  66
  67        /* Enable device interrupt in the hub as well */
  68        hmsk = VHUB_IRQ_DEVICE1 << d->index;
  69        reg = readl(d->vhub->regs + AST_VHUB_IER);
  70        reg |= hmsk;
  71        writel(reg, d->vhub->regs + AST_VHUB_IER);
  72
  73        /* Set EP0 DMA buffer address */
  74        writel(d->ep0.buf_dma, d->regs + AST_VHUB_DEV_EP0_DATA);
  75
  76        d->enabled = true;
  77}
  78
  79static void ast_vhub_dev_disable(struct ast_vhub_dev *d)
  80{
  81        u32 reg, hmsk;
  82
  83        if (!d->enabled)
  84                return;
  85
  86        /* Disable device interrupt in the hub */
  87        hmsk = VHUB_IRQ_DEVICE1 << d->index;
  88        reg = readl(d->vhub->regs + AST_VHUB_IER);
  89        reg &= ~hmsk;
  90        writel(reg, d->vhub->regs + AST_VHUB_IER);
  91
  92        /* Then disable device */
  93        writel(0, d->regs + AST_VHUB_DEV_EN_CTRL);
  94        d->gadget.speed = USB_SPEED_UNKNOWN;
  95        d->enabled = false;
  96        d->suspended = false;
  97}
  98
  99static int ast_vhub_dev_feature(struct ast_vhub_dev *d,
 100                                u16 wIndex, u16 wValue,
 101                                bool is_set)
 102{
 103        DDBG(d, "%s_FEATURE(dev val=%02x)\n",
 104             is_set ? "SET" : "CLEAR", wValue);
 105
 106        if (wValue != USB_DEVICE_REMOTE_WAKEUP)
 107                return std_req_driver;
 108
 109        d->wakeup_en = is_set;
 110
 111        return std_req_complete;
 112}
 113
 114static int ast_vhub_ep_feature(struct ast_vhub_dev *d,
 115                               u16 wIndex, u16 wValue, bool is_set)
 116{
 117        struct ast_vhub_ep *ep;
 118        int ep_num;
 119
 120        ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
 121        DDBG(d, "%s_FEATURE(ep%d val=%02x)\n",
 122             is_set ? "SET" : "CLEAR", ep_num, wValue);
 123        if (ep_num == 0)
 124                return std_req_complete;
 125        if (ep_num >= AST_VHUB_NUM_GEN_EPs || !d->epns[ep_num - 1])
 126                return std_req_stall;
 127        if (wValue != USB_ENDPOINT_HALT)
 128                return std_req_driver;
 129
 130        ep = d->epns[ep_num - 1];
 131        if (WARN_ON(!ep))
 132                return std_req_stall;
 133
 134        if (!ep->epn.enabled || !ep->ep.desc || ep->epn.is_iso ||
 135            ep->epn.is_in != !!(wIndex & USB_DIR_IN))
 136                return std_req_stall;
 137
 138        DDBG(d, "%s stall on EP %d\n",
 139             is_set ? "setting" : "clearing", ep_num);
 140        ep->epn.stalled = is_set;
 141        ast_vhub_update_epn_stall(ep);
 142
 143        return std_req_complete;
 144}
 145
 146static int ast_vhub_dev_status(struct ast_vhub_dev *d,
 147                               u16 wIndex, u16 wValue)
 148{
 149        u8 st0;
 150
 151        DDBG(d, "GET_STATUS(dev)\n");
 152
 153        st0 = d->gadget.is_selfpowered << USB_DEVICE_SELF_POWERED;
 154        if (d->wakeup_en)
 155                st0 |= 1 << USB_DEVICE_REMOTE_WAKEUP;
 156
 157        return ast_vhub_simple_reply(&d->ep0, st0, 0);
 158}
 159
 160static int ast_vhub_ep_status(struct ast_vhub_dev *d,
 161                              u16 wIndex, u16 wValue)
 162{
 163        int ep_num = wIndex & USB_ENDPOINT_NUMBER_MASK;
 164        struct ast_vhub_ep *ep;
 165        u8 st0 = 0;
 166
 167        DDBG(d, "GET_STATUS(ep%d)\n", ep_num);
 168
 169        if (ep_num >= AST_VHUB_NUM_GEN_EPs)
 170                return std_req_stall;
 171        if (ep_num != 0) {
 172                ep = d->epns[ep_num - 1];
 173                if (!ep)
 174                        return std_req_stall;
 175                if (!ep->epn.enabled || !ep->ep.desc || ep->epn.is_iso ||
 176                    ep->epn.is_in != !!(wIndex & USB_DIR_IN))
 177                        return std_req_stall;
 178                if (ep->epn.stalled)
 179                        st0 |= 1 << USB_ENDPOINT_HALT;
 180        }
 181
 182        return ast_vhub_simple_reply(&d->ep0, st0, 0);
 183}
 184
 185static void ast_vhub_dev_set_address(struct ast_vhub_dev *d, u8 addr)
 186{
 187        u32 reg;
 188
 189        DDBG(d, "SET_ADDRESS: Got address %x\n", addr);
 190
 191        reg = readl(d->regs + AST_VHUB_DEV_EN_CTRL);
 192        reg &= ~VHUB_DEV_EN_ADDR_MASK;
 193        reg |= VHUB_DEV_EN_SET_ADDR(addr);
 194        writel(reg, d->regs + AST_VHUB_DEV_EN_CTRL);
 195}
 196
 197int ast_vhub_std_dev_request(struct ast_vhub_ep *ep,
 198                             struct usb_ctrlrequest *crq)
 199{
 200        struct ast_vhub_dev *d = ep->dev;
 201        u16 wValue, wIndex;
 202
 203        /* No driver, we shouldn't be enabled ... */
 204        if (!d->driver || !d->enabled || d->suspended) {
 205                EPDBG(ep,
 206                      "Device is wrong state driver=%p enabled=%d"
 207                      " suspended=%d\n",
 208                      d->driver, d->enabled, d->suspended);
 209                return std_req_stall;
 210        }
 211
 212        /* First packet, grab speed */
 213        if (d->gadget.speed == USB_SPEED_UNKNOWN) {
 214                d->gadget.speed = ep->vhub->speed;
 215                if (d->gadget.speed > d->driver->max_speed)
 216                        d->gadget.speed = d->driver->max_speed;
 217                DDBG(d, "fist packet, captured speed %d\n",
 218                     d->gadget.speed);
 219        }
 220
 221        wValue = le16_to_cpu(crq->wValue);
 222        wIndex = le16_to_cpu(crq->wIndex);
 223
 224        switch ((crq->bRequestType << 8) | crq->bRequest) {
 225                /* SET_ADDRESS */
 226        case DeviceOutRequest | USB_REQ_SET_ADDRESS:
 227                ast_vhub_dev_set_address(d, wValue);
 228                return std_req_complete;
 229
 230                /* GET_STATUS */
 231        case DeviceRequest | USB_REQ_GET_STATUS:
 232                return ast_vhub_dev_status(d, wIndex, wValue);
 233        case InterfaceRequest | USB_REQ_GET_STATUS:
 234                return ast_vhub_simple_reply(ep, 0, 0);
 235        case EndpointRequest | USB_REQ_GET_STATUS:
 236                return ast_vhub_ep_status(d, wIndex, wValue);
 237
 238                /* SET/CLEAR_FEATURE */
 239        case DeviceOutRequest | USB_REQ_SET_FEATURE:
 240                return ast_vhub_dev_feature(d, wIndex, wValue, true);
 241        case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
 242                return ast_vhub_dev_feature(d, wIndex, wValue, false);
 243        case EndpointOutRequest | USB_REQ_SET_FEATURE:
 244                return ast_vhub_ep_feature(d, wIndex, wValue, true);
 245        case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
 246                return ast_vhub_ep_feature(d, wIndex, wValue, false);
 247        }
 248        return std_req_driver;
 249}
 250
 251static int ast_vhub_udc_wakeup(struct usb_gadget* gadget)
 252{
 253        struct ast_vhub_dev *d = to_ast_dev(gadget);
 254        unsigned long flags;
 255        int rc = -EINVAL;
 256
 257        spin_lock_irqsave(&d->vhub->lock, flags);
 258        if (!d->wakeup_en)
 259                goto err;
 260
 261        DDBG(d, "Device initiated wakeup\n");
 262
 263        /* Wakeup the host */
 264        ast_vhub_hub_wake_all(d->vhub);
 265        rc = 0;
 266 err:
 267        spin_unlock_irqrestore(&d->vhub->lock, flags);
 268        return rc;
 269}
 270
 271static int ast_vhub_udc_get_frame(struct usb_gadget* gadget)
 272{
 273        struct ast_vhub_dev *d = to_ast_dev(gadget);
 274
 275        return (readl(d->vhub->regs + AST_VHUB_USBSTS) >> 16) & 0x7ff;
 276}
 277
 278static void ast_vhub_dev_nuke(struct ast_vhub_dev *d)
 279{
 280        unsigned int i;
 281
 282        for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) {
 283                if (!d->epns[i])
 284                        continue;
 285                ast_vhub_nuke(d->epns[i], -ESHUTDOWN);
 286        }
 287}
 288
 289static int ast_vhub_udc_pullup(struct usb_gadget* gadget, int on)
 290{
 291        struct ast_vhub_dev *d = to_ast_dev(gadget);
 292        unsigned long flags;
 293
 294        spin_lock_irqsave(&d->vhub->lock, flags);
 295
 296        DDBG(d, "pullup(%d)\n", on);
 297
 298        /* Mark disconnected in the hub */
 299        ast_vhub_device_connect(d->vhub, d->index, on);
 300
 301        /*
 302         * If enabled, nuke all requests if any (there shouldn't be)
 303         * and disable the port. This will clear the address too.
 304         */
 305        if (d->enabled) {
 306                ast_vhub_dev_nuke(d);
 307                ast_vhub_dev_disable(d);
 308        }
 309
 310        spin_unlock_irqrestore(&d->vhub->lock, flags);
 311
 312        return 0;
 313}
 314
 315static int ast_vhub_udc_start(struct usb_gadget *gadget,
 316                              struct usb_gadget_driver *driver)
 317{
 318        struct ast_vhub_dev *d = to_ast_dev(gadget);
 319        unsigned long flags;
 320
 321        spin_lock_irqsave(&d->vhub->lock, flags);
 322
 323        DDBG(d, "start\n");
 324
 325        /* We don't do much more until the hub enables us */
 326        d->driver = driver;
 327        d->gadget.is_selfpowered = 1;
 328
 329        spin_unlock_irqrestore(&d->vhub->lock, flags);
 330
 331        return 0;
 332}
 333
 334static struct usb_ep *ast_vhub_udc_match_ep(struct usb_gadget *gadget,
 335                                            struct usb_endpoint_descriptor *desc,
 336                                            struct usb_ss_ep_comp_descriptor *ss)
 337{
 338        struct ast_vhub_dev *d = to_ast_dev(gadget);
 339        struct ast_vhub_ep *ep;
 340        struct usb_ep *u_ep;
 341        unsigned int max, addr, i;
 342
 343        DDBG(d, "Match EP type %d\n", usb_endpoint_type(desc));
 344
 345        /*
 346         * First we need to look for an existing unclaimed EP as another
 347         * configuration may have already associated a bunch of EPs with
 348         * this gadget. This duplicates the code in usb_ep_autoconfig_ss()
 349         * unfortunately.
 350         */
 351        list_for_each_entry(u_ep, &gadget->ep_list, ep_list) {
 352                if (usb_gadget_ep_match_desc(gadget, u_ep, desc, ss)) {
 353                        DDBG(d, " -> using existing EP%d\n",
 354                             to_ast_ep(u_ep)->d_idx);
 355                        return u_ep;
 356                }
 357        }
 358
 359        /*
 360         * We didn't find one, we need to grab one from the pool.
 361         *
 362         * First let's do some sanity checking
 363         */
 364        switch(usb_endpoint_type(desc)) {
 365        case USB_ENDPOINT_XFER_CONTROL:
 366                /* Only EP0 can be a control endpoint */
 367                return NULL;
 368        case USB_ENDPOINT_XFER_ISOC:
 369                /* ISO:  limit 1023 bytes full speed, 1024 high/super speed */
 370                if (gadget_is_dualspeed(gadget))
 371                        max = 1024;
 372                else
 373                        max = 1023;
 374                break;
 375        case USB_ENDPOINT_XFER_BULK:
 376                if (gadget_is_dualspeed(gadget))
 377                        max = 512;
 378                else
 379                        max = 64;
 380                break;
 381        case USB_ENDPOINT_XFER_INT:
 382                if (gadget_is_dualspeed(gadget))
 383                        max = 1024;
 384                else
 385                        max = 64;
 386                break;
 387        }
 388        if (usb_endpoint_maxp(desc) > max)
 389                return NULL;
 390
 391        /*
 392         * Find a free EP address for that device. We can't
 393         * let the generic code assign these as it would
 394         * create overlapping numbers for IN and OUT which
 395         * we don't support, so also create a suitable name
 396         * that will allow the generic code to use our
 397         * assigned address.
 398         */
 399        for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++)
 400                if (d->epns[i] == NULL)
 401                        break;
 402        if (i >= AST_VHUB_NUM_GEN_EPs)
 403                return NULL;
 404        addr = i + 1;
 405
 406        /*
 407         * Now grab an EP from the shared pool and associate
 408         * it with our device
 409         */
 410        ep = ast_vhub_alloc_epn(d, addr);
 411        if (!ep)
 412                return NULL;
 413        DDBG(d, "Allocated epn#%d for port EP%d\n",
 414             ep->epn.g_idx, addr);
 415
 416        return &ep->ep;
 417}
 418
 419static int ast_vhub_udc_stop(struct usb_gadget *gadget)
 420{
 421        struct ast_vhub_dev *d = to_ast_dev(gadget);
 422        unsigned long flags;
 423
 424        spin_lock_irqsave(&d->vhub->lock, flags);
 425
 426        DDBG(d, "stop\n");
 427
 428        d->driver = NULL;
 429        d->gadget.speed = USB_SPEED_UNKNOWN;
 430
 431        ast_vhub_dev_nuke(d);
 432
 433        if (d->enabled)
 434                ast_vhub_dev_disable(d);
 435
 436        spin_unlock_irqrestore(&d->vhub->lock, flags);
 437
 438        return 0;
 439}
 440
 441static const struct usb_gadget_ops ast_vhub_udc_ops = {
 442        .get_frame      = ast_vhub_udc_get_frame,
 443        .wakeup         = ast_vhub_udc_wakeup,
 444        .pullup         = ast_vhub_udc_pullup,
 445        .udc_start      = ast_vhub_udc_start,
 446        .udc_stop       = ast_vhub_udc_stop,
 447        .match_ep       = ast_vhub_udc_match_ep,
 448};
 449
 450void ast_vhub_dev_suspend(struct ast_vhub_dev *d)
 451{
 452        d->suspended = true;
 453        if (d->driver) {
 454                spin_unlock(&d->vhub->lock);
 455                d->driver->suspend(&d->gadget);
 456                spin_lock(&d->vhub->lock);
 457        }
 458}
 459
 460void ast_vhub_dev_resume(struct ast_vhub_dev *d)
 461{
 462        d->suspended = false;
 463        if (d->driver) {
 464                spin_unlock(&d->vhub->lock);
 465                d->driver->resume(&d->gadget);
 466                spin_lock(&d->vhub->lock);
 467        }
 468}
 469
 470void ast_vhub_dev_reset(struct ast_vhub_dev *d)
 471{
 472        /*
 473         * If speed is not set, we enable the port. If it is,
 474         * send reset to the gadget and reset "speed".
 475         *
 476         * Speed is an indication that we have got the first
 477         * setup packet to the device.
 478         */
 479        if (d->gadget.speed == USB_SPEED_UNKNOWN && !d->enabled) {
 480                DDBG(d, "Reset at unknown speed of disabled device, enabling...\n");
 481                ast_vhub_dev_enable(d);
 482                d->suspended = false;
 483        }
 484        if (d->gadget.speed != USB_SPEED_UNKNOWN && d->driver) {
 485                unsigned int i;
 486
 487                DDBG(d, "Reset at known speed of bound device, resetting...\n");
 488                spin_unlock(&d->vhub->lock);
 489                d->driver->reset(&d->gadget);
 490                spin_lock(&d->vhub->lock);
 491
 492                /*
 493                 * Disable/re-enable HW, this will clear the address
 494                 * and speed setting.
 495                 */
 496                ast_vhub_dev_disable(d);
 497                ast_vhub_dev_enable(d);
 498
 499                /* Clear stall on all EPs */
 500                for (i = 0; i < AST_VHUB_NUM_GEN_EPs; i++) {
 501                        struct ast_vhub_ep *ep = d->epns[i];
 502
 503                        if (ep && ep->epn.stalled) {
 504                                ep->epn.stalled = false;
 505                                ast_vhub_update_epn_stall(ep);
 506                        }
 507                }
 508
 509                /* Additional cleanups */
 510                d->wakeup_en = false;
 511                d->suspended = false;
 512        }
 513}
 514
 515void ast_vhub_del_dev(struct ast_vhub_dev *d)
 516{
 517        unsigned long flags;
 518
 519        spin_lock_irqsave(&d->vhub->lock, flags);
 520        if (!d->registered) {
 521                spin_unlock_irqrestore(&d->vhub->lock, flags);
 522                return;
 523        }
 524        d->registered = false;
 525        spin_unlock_irqrestore(&d->vhub->lock, flags);
 526
 527        usb_del_gadget_udc(&d->gadget);
 528        device_unregister(d->port_dev);
 529}
 530
 531static void ast_vhub_dev_release(struct device *dev)
 532{
 533        kfree(dev);
 534}
 535
 536int ast_vhub_init_dev(struct ast_vhub *vhub, unsigned int idx)
 537{
 538        struct ast_vhub_dev *d = &vhub->ports[idx].dev;
 539        struct device *parent = &vhub->pdev->dev;
 540        int rc;
 541
 542        d->vhub = vhub;
 543        d->index = idx;
 544        d->name = devm_kasprintf(parent, GFP_KERNEL, "port%d", idx+1);
 545        d->regs = vhub->regs + 0x100 + 0x10 * idx;
 546
 547        ast_vhub_init_ep0(vhub, &d->ep0, d);
 548
 549        /*
 550         * The UDC core really needs us to have separate and uniquely
 551         * named "parent" devices for each port so we create a sub device
 552         * here for that purpose
 553         */
 554        d->port_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
 555        if (!d->port_dev)
 556                return -ENOMEM;
 557        device_initialize(d->port_dev);
 558        d->port_dev->release = ast_vhub_dev_release;
 559        d->port_dev->parent = parent;
 560        dev_set_name(d->port_dev, "%s:p%d", dev_name(parent), idx + 1);
 561        rc = device_add(d->port_dev);
 562        if (rc)
 563                goto fail_add;
 564
 565        /* Populate gadget */
 566        INIT_LIST_HEAD(&d->gadget.ep_list);
 567        d->gadget.ops = &ast_vhub_udc_ops;
 568        d->gadget.ep0 = &d->ep0.ep;
 569        d->gadget.name = KBUILD_MODNAME;
 570        if (vhub->force_usb1)
 571                d->gadget.max_speed = USB_SPEED_FULL;
 572        else
 573                d->gadget.max_speed = USB_SPEED_HIGH;
 574        d->gadget.speed = USB_SPEED_UNKNOWN;
 575        d->gadget.dev.of_node = vhub->pdev->dev.of_node;
 576
 577        rc = usb_add_gadget_udc(d->port_dev, &d->gadget);
 578        if (rc != 0)
 579                goto fail_udc;
 580        d->registered = true;
 581
 582        return 0;
 583 fail_udc:
 584        device_del(d->port_dev);
 585 fail_add:
 586        put_device(d->port_dev);
 587
 588        return rc;
 589}
 590