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