linux/drivers/usb/cdns3/core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Cadence USBSS DRD Driver.
   4 *
   5 * Copyright (C) 2018-2019 Cadence.
   6 * Copyright (C) 2017-2018 NXP
   7 * Copyright (C) 2019 Texas Instruments
   8 *
   9 * Author: Peter Chen <peter.chen@nxp.com>
  10 *         Pawel Laszczak <pawell@cadence.com>
  11 *         Roger Quadros <rogerq@ti.com>
  12 */
  13
  14#include <linux/dma-mapping.h>
  15#include <linux/module.h>
  16#include <linux/kernel.h>
  17#include <linux/platform_device.h>
  18#include <linux/interrupt.h>
  19#include <linux/io.h>
  20#include <linux/pm_runtime.h>
  21
  22#include "gadget.h"
  23#include "core.h"
  24#include "host-export.h"
  25#include "gadget-export.h"
  26#include "drd.h"
  27
  28static int cdns3_idle_init(struct cdns3 *cdns);
  29
  30static int cdns3_role_start(struct cdns3 *cdns, enum usb_role role)
  31{
  32        int ret;
  33
  34        if (WARN_ON(role > USB_ROLE_DEVICE))
  35                return 0;
  36
  37        mutex_lock(&cdns->mutex);
  38        cdns->role = role;
  39        mutex_unlock(&cdns->mutex);
  40
  41        if (!cdns->roles[role])
  42                return -ENXIO;
  43
  44        if (cdns->roles[role]->state == CDNS3_ROLE_STATE_ACTIVE)
  45                return 0;
  46
  47        mutex_lock(&cdns->mutex);
  48        ret = cdns->roles[role]->start(cdns);
  49        if (!ret)
  50                cdns->roles[role]->state = CDNS3_ROLE_STATE_ACTIVE;
  51        mutex_unlock(&cdns->mutex);
  52
  53        return ret;
  54}
  55
  56static void cdns3_role_stop(struct cdns3 *cdns)
  57{
  58        enum usb_role role = cdns->role;
  59
  60        if (WARN_ON(role > USB_ROLE_DEVICE))
  61                return;
  62
  63        if (cdns->roles[role]->state == CDNS3_ROLE_STATE_INACTIVE)
  64                return;
  65
  66        mutex_lock(&cdns->mutex);
  67        cdns->roles[role]->stop(cdns);
  68        cdns->roles[role]->state = CDNS3_ROLE_STATE_INACTIVE;
  69        mutex_unlock(&cdns->mutex);
  70}
  71
  72static void cdns3_exit_roles(struct cdns3 *cdns)
  73{
  74        cdns3_role_stop(cdns);
  75        cdns3_drd_exit(cdns);
  76}
  77
  78/**
  79 * cdns3_core_init_role - initialize role of operation
  80 * @cdns: Pointer to cdns3 structure
  81 *
  82 * Returns 0 on success otherwise negative errno
  83 */
  84static int cdns3_core_init_role(struct cdns3 *cdns)
  85{
  86        struct device *dev = cdns->dev;
  87        enum usb_dr_mode best_dr_mode;
  88        enum usb_dr_mode dr_mode;
  89        int ret;
  90
  91        dr_mode = usb_get_dr_mode(dev);
  92        cdns->role = USB_ROLE_NONE;
  93
  94        /*
  95         * If driver can't read mode by means of usb_get_dr_mode function then
  96         * chooses mode according with Kernel configuration. This setting
  97         * can be restricted later depending on strap pin configuration.
  98         */
  99        if (dr_mode == USB_DR_MODE_UNKNOWN) {
 100                if (IS_ENABLED(CONFIG_USB_CDNS3_HOST) &&
 101                    IS_ENABLED(CONFIG_USB_CDNS3_GADGET))
 102                        dr_mode = USB_DR_MODE_OTG;
 103                else if (IS_ENABLED(CONFIG_USB_CDNS3_HOST))
 104                        dr_mode = USB_DR_MODE_HOST;
 105                else if (IS_ENABLED(CONFIG_USB_CDNS3_GADGET))
 106                        dr_mode = USB_DR_MODE_PERIPHERAL;
 107        }
 108
 109        /*
 110         * At this point cdns->dr_mode contains strap configuration.
 111         * Driver try update this setting considering kernel configuration
 112         */
 113        best_dr_mode = cdns->dr_mode;
 114
 115        ret = cdns3_idle_init(cdns);
 116        if (ret)
 117                return ret;
 118
 119        if (dr_mode == USB_DR_MODE_OTG) {
 120                best_dr_mode = cdns->dr_mode;
 121        } else if (cdns->dr_mode == USB_DR_MODE_OTG) {
 122                best_dr_mode = dr_mode;
 123        } else if (cdns->dr_mode != dr_mode) {
 124                dev_err(dev, "Incorrect DRD configuration\n");
 125                return -EINVAL;
 126        }
 127
 128        dr_mode = best_dr_mode;
 129
 130        if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_HOST) {
 131                ret = cdns3_host_init(cdns);
 132                if (ret) {
 133                        dev_err(dev, "Host initialization failed with %d\n",
 134                                ret);
 135                        goto err;
 136                }
 137        }
 138
 139        if (dr_mode == USB_DR_MODE_OTG || dr_mode == USB_DR_MODE_PERIPHERAL) {
 140                ret = cdns3_gadget_init(cdns);
 141                if (ret) {
 142                        dev_err(dev, "Device initialization failed with %d\n",
 143                                ret);
 144                        goto err;
 145                }
 146        }
 147
 148        cdns->dr_mode = dr_mode;
 149
 150        ret = cdns3_drd_update_mode(cdns);
 151        if (ret)
 152                goto err;
 153
 154        /* Initialize idle role to start with */
 155        ret = cdns3_role_start(cdns, USB_ROLE_NONE);
 156        if (ret)
 157                goto err;
 158
 159        switch (cdns->dr_mode) {
 160        case USB_DR_MODE_OTG:
 161                ret = cdns3_hw_role_switch(cdns);
 162                if (ret)
 163                        goto err;
 164                break;
 165        case USB_DR_MODE_PERIPHERAL:
 166                ret = cdns3_role_start(cdns, USB_ROLE_DEVICE);
 167                if (ret)
 168                        goto err;
 169                break;
 170        case USB_DR_MODE_HOST:
 171                ret = cdns3_role_start(cdns, USB_ROLE_HOST);
 172                if (ret)
 173                        goto err;
 174                break;
 175        default:
 176                ret = -EINVAL;
 177                goto err;
 178        }
 179
 180        return 0;
 181err:
 182        cdns3_exit_roles(cdns);
 183        return ret;
 184}
 185
 186/**
 187 * cdns3_hw_role_state_machine  - role switch state machine based on hw events.
 188 * @cdns: Pointer to controller structure.
 189 *
 190 * Returns next role to be entered based on hw events.
 191 */
 192static enum usb_role cdns3_hw_role_state_machine(struct cdns3 *cdns)
 193{
 194        enum usb_role role = USB_ROLE_NONE;
 195        int id, vbus;
 196
 197        if (cdns->dr_mode != USB_DR_MODE_OTG) {
 198                if (cdns3_is_host(cdns))
 199                        role = USB_ROLE_HOST;
 200                if (cdns3_is_device(cdns))
 201                        role = USB_ROLE_DEVICE;
 202
 203                return role;
 204        }
 205
 206        id = cdns3_get_id(cdns);
 207        vbus = cdns3_get_vbus(cdns);
 208
 209        /*
 210         * Role change state machine
 211         * Inputs: ID, VBUS
 212         * Previous state: cdns->role
 213         * Next state: role
 214         */
 215        role = cdns->role;
 216
 217        switch (role) {
 218        case USB_ROLE_NONE:
 219                /*
 220                 * Driver treats USB_ROLE_NONE synonymous to IDLE state from
 221                 * controller specification.
 222                 */
 223                if (!id)
 224                        role = USB_ROLE_HOST;
 225                else if (vbus)
 226                        role = USB_ROLE_DEVICE;
 227                break;
 228        case USB_ROLE_HOST: /* from HOST, we can only change to NONE */
 229                if (id)
 230                        role = USB_ROLE_NONE;
 231                break;
 232        case USB_ROLE_DEVICE: /* from GADGET, we can only change to NONE*/
 233                if (!vbus)
 234                        role = USB_ROLE_NONE;
 235                break;
 236        }
 237
 238        dev_dbg(cdns->dev, "role %d -> %d\n", cdns->role, role);
 239
 240        return role;
 241}
 242
 243static int cdns3_idle_role_start(struct cdns3 *cdns)
 244{
 245        return 0;
 246}
 247
 248static void cdns3_idle_role_stop(struct cdns3 *cdns)
 249{
 250        /* Program Lane swap and bring PHY out of RESET */
 251        phy_reset(cdns->usb3_phy);
 252}
 253
 254static int cdns3_idle_init(struct cdns3 *cdns)
 255{
 256        struct cdns3_role_driver *rdrv;
 257
 258        rdrv = devm_kzalloc(cdns->dev, sizeof(*rdrv), GFP_KERNEL);
 259        if (!rdrv)
 260                return -ENOMEM;
 261
 262        rdrv->start = cdns3_idle_role_start;
 263        rdrv->stop = cdns3_idle_role_stop;
 264        rdrv->state = CDNS3_ROLE_STATE_INACTIVE;
 265        rdrv->suspend = NULL;
 266        rdrv->resume = NULL;
 267        rdrv->name = "idle";
 268
 269        cdns->roles[USB_ROLE_NONE] = rdrv;
 270
 271        return 0;
 272}
 273
 274/**
 275 * cdns3_hw_role_switch - switch roles based on HW state
 276 * @cdns: controller
 277 */
 278int cdns3_hw_role_switch(struct cdns3 *cdns)
 279{
 280        enum usb_role real_role, current_role;
 281        int ret = 0;
 282
 283        pm_runtime_get_sync(cdns->dev);
 284
 285        current_role = cdns->role;
 286        real_role = cdns3_hw_role_state_machine(cdns);
 287
 288        /* Do nothing if nothing changed */
 289        if (current_role == real_role)
 290                goto exit;
 291
 292        cdns3_role_stop(cdns);
 293
 294        dev_dbg(cdns->dev, "Switching role %d -> %d", current_role, real_role);
 295
 296        ret = cdns3_role_start(cdns, real_role);
 297        if (ret) {
 298                /* Back to current role */
 299                dev_err(cdns->dev, "set %d has failed, back to %d\n",
 300                        real_role, current_role);
 301                ret = cdns3_role_start(cdns, current_role);
 302                if (ret)
 303                        dev_err(cdns->dev, "back to %d failed too\n",
 304                                current_role);
 305        }
 306exit:
 307        pm_runtime_put_sync(cdns->dev);
 308        return ret;
 309}
 310
 311/**
 312 * cdsn3_role_get - get current role of controller.
 313 *
 314 * @sw: pointer to USB role switch structure
 315 *
 316 * Returns role
 317 */
 318static enum usb_role cdns3_role_get(struct usb_role_switch *sw)
 319{
 320        struct cdns3 *cdns = usb_role_switch_get_drvdata(sw);
 321
 322        return cdns->role;
 323}
 324
 325/**
 326 * cdns3_role_set - set current role of controller.
 327 *
 328 * @sw: pointer to USB role switch structure
 329 * @role: the previous role
 330 * Handles below events:
 331 * - Role switch for dual-role devices
 332 * - USB_ROLE_GADGET <--> USB_ROLE_NONE for peripheral-only devices
 333 */
 334static int cdns3_role_set(struct usb_role_switch *sw, enum usb_role role)
 335{
 336        struct cdns3 *cdns = usb_role_switch_get_drvdata(sw);
 337        int ret = 0;
 338
 339        pm_runtime_get_sync(cdns->dev);
 340
 341        if (cdns->role == role)
 342                goto pm_put;
 343
 344        if (cdns->dr_mode == USB_DR_MODE_HOST) {
 345                switch (role) {
 346                case USB_ROLE_NONE:
 347                case USB_ROLE_HOST:
 348                        break;
 349                default:
 350                        goto pm_put;
 351                }
 352        }
 353
 354        if (cdns->dr_mode == USB_DR_MODE_PERIPHERAL) {
 355                switch (role) {
 356                case USB_ROLE_NONE:
 357                case USB_ROLE_DEVICE:
 358                        break;
 359                default:
 360                        goto pm_put;
 361                }
 362        }
 363
 364        cdns3_role_stop(cdns);
 365        ret = cdns3_role_start(cdns, role);
 366        if (ret)
 367                dev_err(cdns->dev, "set role %d has failed\n", role);
 368
 369pm_put:
 370        pm_runtime_put_sync(cdns->dev);
 371        return ret;
 372}
 373
 374/**
 375 * cdns3_probe - probe for cdns3 core device
 376 * @pdev: Pointer to cdns3 core platform device
 377 *
 378 * Returns 0 on success otherwise negative errno
 379 */
 380static int cdns3_probe(struct platform_device *pdev)
 381{
 382        struct usb_role_switch_desc sw_desc = { };
 383        struct device *dev = &pdev->dev;
 384        struct resource *res;
 385        struct cdns3 *cdns;
 386        void __iomem *regs;
 387        int ret;
 388
 389        ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
 390        if (ret) {
 391                dev_err(dev, "error setting dma mask: %d\n", ret);
 392                return ret;
 393        }
 394
 395        cdns = devm_kzalloc(dev, sizeof(*cdns), GFP_KERNEL);
 396        if (!cdns)
 397                return -ENOMEM;
 398
 399        cdns->dev = dev;
 400
 401        platform_set_drvdata(pdev, cdns);
 402
 403        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "host");
 404        if (!res) {
 405                dev_err(dev, "missing host IRQ\n");
 406                return -ENODEV;
 407        }
 408
 409        cdns->xhci_res[0] = *res;
 410
 411        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "xhci");
 412        if (!res) {
 413                dev_err(dev, "couldn't get xhci resource\n");
 414                return -ENXIO;
 415        }
 416
 417        cdns->xhci_res[1] = *res;
 418
 419        cdns->dev_irq = platform_get_irq_byname(pdev, "peripheral");
 420        if (cdns->dev_irq == -EPROBE_DEFER)
 421                return cdns->dev_irq;
 422
 423        if (cdns->dev_irq < 0)
 424                dev_err(dev, "couldn't get peripheral irq\n");
 425
 426        regs = devm_platform_ioremap_resource_byname(pdev, "dev");
 427        if (IS_ERR(regs))
 428                return PTR_ERR(regs);
 429        cdns->dev_regs  = regs;
 430
 431        cdns->otg_irq = platform_get_irq_byname(pdev, "otg");
 432        if (cdns->otg_irq == -EPROBE_DEFER)
 433                return cdns->otg_irq;
 434
 435        if (cdns->otg_irq < 0) {
 436                dev_err(dev, "couldn't get otg irq\n");
 437                return cdns->otg_irq;
 438        }
 439
 440        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otg");
 441        if (!res) {
 442                dev_err(dev, "couldn't get otg resource\n");
 443                return -ENXIO;
 444        }
 445
 446        cdns->otg_res = *res;
 447
 448        mutex_init(&cdns->mutex);
 449
 450        cdns->usb2_phy = devm_phy_optional_get(dev, "cdns3,usb2-phy");
 451        if (IS_ERR(cdns->usb2_phy))
 452                return PTR_ERR(cdns->usb2_phy);
 453
 454        ret = phy_init(cdns->usb2_phy);
 455        if (ret)
 456                return ret;
 457
 458        cdns->usb3_phy = devm_phy_optional_get(dev, "cdns3,usb3-phy");
 459        if (IS_ERR(cdns->usb3_phy))
 460                return PTR_ERR(cdns->usb3_phy);
 461
 462        ret = phy_init(cdns->usb3_phy);
 463        if (ret)
 464                goto err1;
 465
 466        ret = phy_power_on(cdns->usb2_phy);
 467        if (ret)
 468                goto err2;
 469
 470        ret = phy_power_on(cdns->usb3_phy);
 471        if (ret)
 472                goto err3;
 473
 474        sw_desc.set = cdns3_role_set;
 475        sw_desc.get = cdns3_role_get;
 476        sw_desc.allow_userspace_control = true;
 477        sw_desc.driver_data = cdns;
 478        if (device_property_read_bool(dev, "usb-role-switch"))
 479                sw_desc.fwnode = dev->fwnode;
 480
 481        cdns->role_sw = usb_role_switch_register(dev, &sw_desc);
 482        if (IS_ERR(cdns->role_sw)) {
 483                ret = PTR_ERR(cdns->role_sw);
 484                dev_warn(dev, "Unable to register Role Switch\n");
 485                goto err4;
 486        }
 487
 488        ret = cdns3_drd_init(cdns);
 489        if (ret)
 490                goto err5;
 491
 492        ret = cdns3_core_init_role(cdns);
 493        if (ret)
 494                goto err5;
 495
 496        device_set_wakeup_capable(dev, true);
 497        pm_runtime_set_active(dev);
 498        pm_runtime_enable(dev);
 499
 500        /*
 501         * The controller needs less time between bus and controller suspend,
 502         * and we also needs a small delay to avoid frequently entering low
 503         * power mode.
 504         */
 505        pm_runtime_set_autosuspend_delay(dev, 20);
 506        pm_runtime_mark_last_busy(dev);
 507        pm_runtime_use_autosuspend(dev);
 508        dev_dbg(dev, "Cadence USB3 core: probe succeed\n");
 509
 510        return 0;
 511err5:
 512        cdns3_drd_exit(cdns);
 513        usb_role_switch_unregister(cdns->role_sw);
 514err4:
 515        phy_power_off(cdns->usb3_phy);
 516
 517err3:
 518        phy_power_off(cdns->usb2_phy);
 519err2:
 520        phy_exit(cdns->usb3_phy);
 521err1:
 522        phy_exit(cdns->usb2_phy);
 523
 524        return ret;
 525}
 526
 527/**
 528 * cdns3_remove - unbind drd driver and clean up
 529 * @pdev: Pointer to Linux platform device
 530 *
 531 * Returns 0 on success otherwise negative errno
 532 */
 533static int cdns3_remove(struct platform_device *pdev)
 534{
 535        struct cdns3 *cdns = platform_get_drvdata(pdev);
 536
 537        pm_runtime_get_sync(&pdev->dev);
 538        pm_runtime_disable(&pdev->dev);
 539        pm_runtime_put_noidle(&pdev->dev);
 540        cdns3_exit_roles(cdns);
 541        usb_role_switch_unregister(cdns->role_sw);
 542        phy_power_off(cdns->usb2_phy);
 543        phy_power_off(cdns->usb3_phy);
 544        phy_exit(cdns->usb2_phy);
 545        phy_exit(cdns->usb3_phy);
 546        return 0;
 547}
 548
 549#ifdef CONFIG_PM_SLEEP
 550
 551static int cdns3_suspend(struct device *dev)
 552{
 553        struct cdns3 *cdns = dev_get_drvdata(dev);
 554        unsigned long flags;
 555
 556        if (cdns->role == USB_ROLE_HOST)
 557                return 0;
 558
 559        if (pm_runtime_status_suspended(dev))
 560                pm_runtime_resume(dev);
 561
 562        if (cdns->roles[cdns->role]->suspend) {
 563                spin_lock_irqsave(&cdns->gadget_dev->lock, flags);
 564                cdns->roles[cdns->role]->suspend(cdns, false);
 565                spin_unlock_irqrestore(&cdns->gadget_dev->lock, flags);
 566        }
 567
 568        return 0;
 569}
 570
 571static int cdns3_resume(struct device *dev)
 572{
 573        struct cdns3 *cdns = dev_get_drvdata(dev);
 574        unsigned long flags;
 575
 576        if (cdns->role == USB_ROLE_HOST)
 577                return 0;
 578
 579        if (cdns->roles[cdns->role]->resume) {
 580                spin_lock_irqsave(&cdns->gadget_dev->lock, flags);
 581                cdns->roles[cdns->role]->resume(cdns, false);
 582                spin_unlock_irqrestore(&cdns->gadget_dev->lock, flags);
 583        }
 584
 585        pm_runtime_disable(dev);
 586        pm_runtime_set_active(dev);
 587        pm_runtime_enable(dev);
 588
 589        return 0;
 590}
 591#endif
 592
 593static const struct dev_pm_ops cdns3_pm_ops = {
 594        SET_SYSTEM_SLEEP_PM_OPS(cdns3_suspend, cdns3_resume)
 595};
 596
 597#ifdef CONFIG_OF
 598static const struct of_device_id of_cdns3_match[] = {
 599        { .compatible = "cdns,usb3" },
 600        { },
 601};
 602MODULE_DEVICE_TABLE(of, of_cdns3_match);
 603#endif
 604
 605static struct platform_driver cdns3_driver = {
 606        .probe          = cdns3_probe,
 607        .remove         = cdns3_remove,
 608        .driver         = {
 609                .name   = "cdns-usb3",
 610                .of_match_table = of_match_ptr(of_cdns3_match),
 611                .pm     = &cdns3_pm_ops,
 612        },
 613};
 614
 615module_platform_driver(cdns3_driver);
 616
 617MODULE_ALIAS("platform:cdns3");
 618MODULE_AUTHOR("Pawel Laszczak <pawell@cadence.com>");
 619MODULE_LICENSE("GPL v2");
 620MODULE_DESCRIPTION("Cadence USB3 DRD Controller Driver");
 621