linux/drivers/usb/chipidea/host.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * host.c - ChipIdea USB host controller driver
   4 *
   5 * Copyright (c) 2012 Intel Corporation
   6 *
   7 * Author: Alexander Shishkin
   8 */
   9
  10#include <linux/kernel.h>
  11#include <linux/io.h>
  12#include <linux/usb.h>
  13#include <linux/usb/hcd.h>
  14#include <linux/usb/chipidea.h>
  15#include <linux/regulator/consumer.h>
  16#include <linux/pinctrl/consumer.h>
  17
  18#include "../host/ehci.h"
  19
  20#include "ci.h"
  21#include "bits.h"
  22#include "host.h"
  23
  24static struct hc_driver __read_mostly ci_ehci_hc_driver;
  25static int (*orig_bus_suspend)(struct usb_hcd *hcd);
  26
  27struct ehci_ci_priv {
  28        struct regulator *reg_vbus;
  29        bool enabled;
  30};
  31
  32struct ci_hdrc_dma_aligned_buffer {
  33        void *kmalloc_ptr;
  34        void *old_xfer_buffer;
  35        u8 data[];
  36};
  37
  38static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
  39{
  40        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
  41        struct ehci_ci_priv *priv = (struct ehci_ci_priv *)ehci->priv;
  42        struct device *dev = hcd->self.controller;
  43        struct ci_hdrc *ci = dev_get_drvdata(dev);
  44        int ret = 0;
  45        int port = HCS_N_PORTS(ehci->hcs_params);
  46
  47        if (priv->reg_vbus && enable != priv->enabled) {
  48                if (port > 1) {
  49                        dev_warn(dev,
  50                                "Not support multi-port regulator control\n");
  51                        return 0;
  52                }
  53                if (enable)
  54                        ret = regulator_enable(priv->reg_vbus);
  55                else
  56                        ret = regulator_disable(priv->reg_vbus);
  57                if (ret) {
  58                        dev_err(dev,
  59                                "Failed to %s vbus regulator, ret=%d\n",
  60                                enable ? "enable" : "disable", ret);
  61                        return ret;
  62                }
  63                priv->enabled = enable;
  64        }
  65
  66        if (ci->platdata->flags & CI_HDRC_PHY_VBUS_CONTROL &&
  67                        ci->usb_phy && ci->usb_phy->set_vbus) {
  68                if (enable)
  69                        ci->usb_phy->set_vbus(ci->usb_phy, 1);
  70                else
  71                        ci->usb_phy->set_vbus(ci->usb_phy, 0);
  72        }
  73
  74        if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
  75                /*
  76                 * Marvell 28nm HSIC PHY requires forcing the port to HS mode.
  77                 * As HSIC is always HS, this should be safe for others.
  78                 */
  79                hw_port_test_set(ci, 5);
  80                hw_port_test_set(ci, 0);
  81        }
  82
  83        return 0;
  84};
  85
  86static int ehci_ci_reset(struct usb_hcd *hcd)
  87{
  88        struct device *dev = hcd->self.controller;
  89        struct ci_hdrc *ci = dev_get_drvdata(dev);
  90        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
  91        int ret;
  92
  93        ret = ehci_setup(hcd);
  94        if (ret)
  95                return ret;
  96
  97        ehci->need_io_watchdog = 0;
  98
  99        if (ci->platdata->notify_event) {
 100                ret = ci->platdata->notify_event(ci,
 101                                CI_HDRC_CONTROLLER_RESET_EVENT);
 102                if (ret)
 103                        return ret;
 104        }
 105
 106        ci_platform_configure(ci);
 107
 108        return ret;
 109}
 110
 111static const struct ehci_driver_overrides ehci_ci_overrides = {
 112        .extra_priv_size = sizeof(struct ehci_ci_priv),
 113        .port_power      = ehci_ci_portpower,
 114        .reset           = ehci_ci_reset,
 115};
 116
 117static irqreturn_t host_irq(struct ci_hdrc *ci)
 118{
 119        return usb_hcd_irq(ci->irq, ci->hcd);
 120}
 121
 122static int host_start(struct ci_hdrc *ci)
 123{
 124        struct usb_hcd *hcd;
 125        struct ehci_hcd *ehci;
 126        struct ehci_ci_priv *priv;
 127        int ret;
 128
 129        if (usb_disabled())
 130                return -ENODEV;
 131
 132        hcd = __usb_create_hcd(&ci_ehci_hc_driver, ci->dev->parent,
 133                               ci->dev, dev_name(ci->dev), NULL);
 134        if (!hcd)
 135                return -ENOMEM;
 136
 137        dev_set_drvdata(ci->dev, ci);
 138        hcd->rsrc_start = ci->hw_bank.phys;
 139        hcd->rsrc_len = ci->hw_bank.size;
 140        hcd->regs = ci->hw_bank.abs;
 141        hcd->has_tt = 1;
 142
 143        hcd->power_budget = ci->platdata->power_budget;
 144        hcd->tpl_support = ci->platdata->tpl_support;
 145        if (ci->phy || ci->usb_phy) {
 146                hcd->skip_phy_initialization = 1;
 147                if (ci->usb_phy)
 148                        hcd->usb_phy = ci->usb_phy;
 149        }
 150
 151        ehci = hcd_to_ehci(hcd);
 152        ehci->caps = ci->hw_bank.cap;
 153        ehci->has_hostpc = ci->hw_bank.lpm;
 154        ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
 155        ehci->imx28_write_fix = ci->imx28_write_fix;
 156
 157        priv = (struct ehci_ci_priv *)ehci->priv;
 158        priv->reg_vbus = NULL;
 159
 160        if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
 161                if (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON) {
 162                        ret = regulator_enable(ci->platdata->reg_vbus);
 163                        if (ret) {
 164                                dev_err(ci->dev,
 165                                "Failed to enable vbus regulator, ret=%d\n",
 166                                                                        ret);
 167                                goto put_hcd;
 168                        }
 169                } else {
 170                        priv->reg_vbus = ci->platdata->reg_vbus;
 171                }
 172        }
 173
 174        if (ci->platdata->pins_host)
 175                pinctrl_select_state(ci->platdata->pctl,
 176                                     ci->platdata->pins_host);
 177
 178        ci->hcd = hcd;
 179
 180        ret = usb_add_hcd(hcd, 0, 0);
 181        if (ret) {
 182                ci->hcd = NULL;
 183                goto disable_reg;
 184        } else {
 185                struct usb_otg *otg = &ci->otg;
 186
 187                if (ci_otg_is_fsm_mode(ci)) {
 188                        otg->host = &hcd->self;
 189                        hcd->self.otg_port = 1;
 190                }
 191
 192                if (ci->platdata->notify_event &&
 193                        (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC))
 194                        ci->platdata->notify_event
 195                                (ci, CI_HDRC_IMX_HSIC_ACTIVE_EVENT);
 196        }
 197
 198        return ret;
 199
 200disable_reg:
 201        if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
 202                        (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
 203                regulator_disable(ci->platdata->reg_vbus);
 204put_hcd:
 205        usb_put_hcd(hcd);
 206
 207        return ret;
 208}
 209
 210static void host_stop(struct ci_hdrc *ci)
 211{
 212        struct usb_hcd *hcd = ci->hcd;
 213
 214        if (hcd) {
 215                if (ci->platdata->notify_event)
 216                        ci->platdata->notify_event(ci,
 217                                CI_HDRC_CONTROLLER_STOPPED_EVENT);
 218                usb_remove_hcd(hcd);
 219                ci->role = CI_ROLE_END;
 220                synchronize_irq(ci->irq);
 221                usb_put_hcd(hcd);
 222                if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
 223                        (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
 224                                regulator_disable(ci->platdata->reg_vbus);
 225        }
 226        ci->hcd = NULL;
 227        ci->otg.host = NULL;
 228
 229        if (ci->platdata->pins_host && ci->platdata->pins_default)
 230                pinctrl_select_state(ci->platdata->pctl,
 231                                     ci->platdata->pins_default);
 232}
 233
 234
 235void ci_hdrc_host_destroy(struct ci_hdrc *ci)
 236{
 237        if (ci->role == CI_ROLE_HOST && ci->hcd)
 238                host_stop(ci);
 239}
 240
 241/* The below code is based on tegra ehci driver */
 242static int ci_ehci_hub_control(
 243        struct usb_hcd  *hcd,
 244        u16             typeReq,
 245        u16             wValue,
 246        u16             wIndex,
 247        char            *buf,
 248        u16             wLength
 249)
 250{
 251        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 252        unsigned int    ports = HCS_N_PORTS(ehci->hcs_params);
 253        u32 __iomem     *status_reg;
 254        u32             temp, port_index;
 255        unsigned long   flags;
 256        int             retval = 0;
 257        bool            done = false;
 258        struct device *dev = hcd->self.controller;
 259        struct ci_hdrc *ci = dev_get_drvdata(dev);
 260
 261        port_index = wIndex & 0xff;
 262        port_index -= (port_index > 0);
 263        status_reg = &ehci->regs->port_status[port_index];
 264
 265        spin_lock_irqsave(&ehci->lock, flags);
 266
 267        if (ci->platdata->hub_control) {
 268                retval = ci->platdata->hub_control(ci, typeReq, wValue, wIndex,
 269                                                   buf, wLength, &done, &flags);
 270                if (done)
 271                        goto done;
 272        }
 273
 274        if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
 275                if (!wIndex || wIndex > ports) {
 276                        retval = -EPIPE;
 277                        goto done;
 278                }
 279
 280                temp = ehci_readl(ehci, status_reg);
 281                if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
 282                        retval = -EPIPE;
 283                        goto done;
 284                }
 285
 286                temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E);
 287                temp |= PORT_WKDISC_E | PORT_WKOC_E;
 288                ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
 289
 290                /*
 291                 * If a transaction is in progress, there may be a delay in
 292                 * suspending the port. Poll until the port is suspended.
 293                 */
 294                if (ehci_handshake(ehci, status_reg, PORT_SUSPEND,
 295                        PORT_SUSPEND, 5000))
 296                        ehci_err(ehci, "timeout waiting for SUSPEND\n");
 297
 298                if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
 299                        if (ci->platdata->notify_event)
 300                                ci->platdata->notify_event(ci,
 301                                        CI_HDRC_IMX_HSIC_SUSPEND_EVENT);
 302
 303                        temp = ehci_readl(ehci, status_reg);
 304                        temp &= ~(PORT_WKDISC_E | PORT_WKCONN_E);
 305                        ehci_writel(ehci, temp, status_reg);
 306                }
 307
 308                set_bit(port_index, &ehci->suspended_ports);
 309                goto done;
 310        }
 311
 312        /*
 313         * After resume has finished, it needs do some post resume
 314         * operation for some SoCs.
 315         */
 316        else if (typeReq == ClearPortFeature &&
 317                wValue == USB_PORT_FEAT_C_SUSPEND) {
 318                /* Make sure the resume has finished, it should be finished */
 319                if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 25000))
 320                        ehci_err(ehci, "timeout waiting for resume\n");
 321        }
 322
 323        spin_unlock_irqrestore(&ehci->lock, flags);
 324
 325        /* Handle the hub control events here */
 326        return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
 327done:
 328        spin_unlock_irqrestore(&ehci->lock, flags);
 329        return retval;
 330}
 331static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
 332{
 333        struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 334        struct device *dev = hcd->self.controller;
 335        struct ci_hdrc *ci = dev_get_drvdata(dev);
 336        int port;
 337        u32 tmp;
 338
 339        int ret = orig_bus_suspend(hcd);
 340
 341        if (ret)
 342                return ret;
 343
 344        port = HCS_N_PORTS(ehci->hcs_params);
 345        while (port--) {
 346                u32 __iomem *reg = &ehci->regs->port_status[port];
 347                u32 portsc = ehci_readl(ehci, reg);
 348
 349                if (portsc & PORT_CONNECT) {
 350                        /*
 351                         * For chipidea, the resume signal will be ended
 352                         * automatically, so for remote wakeup case, the
 353                         * usbcmd.rs may not be set before the resume has
 354                         * ended if other resume paths consumes too much
 355                         * time (~24ms), in that case, the SOF will not
 356                         * send out within 3ms after resume ends, then the
 357                         * high speed device will enter full speed mode.
 358                         */
 359
 360                        tmp = ehci_readl(ehci, &ehci->regs->command);
 361                        tmp |= CMD_RUN;
 362                        ehci_writel(ehci, tmp, &ehci->regs->command);
 363                        /*
 364                         * It needs a short delay between set RS bit and PHCD.
 365                         */
 366                        usleep_range(150, 200);
 367                        /*
 368                         * Need to clear WKCN and WKOC for imx HSIC,
 369                         * otherwise, there will be wakeup event.
 370                         */
 371                        if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
 372                                tmp = ehci_readl(ehci, reg);
 373                                tmp &= ~(PORT_WKDISC_E | PORT_WKCONN_E);
 374                                ehci_writel(ehci, tmp, reg);
 375                        }
 376
 377                        break;
 378                }
 379        }
 380
 381        return 0;
 382}
 383
 384static void ci_hdrc_free_dma_aligned_buffer(struct urb *urb)
 385{
 386        struct ci_hdrc_dma_aligned_buffer *temp;
 387        size_t length;
 388
 389        if (!(urb->transfer_flags & URB_ALIGNED_TEMP_BUFFER))
 390                return;
 391
 392        temp = container_of(urb->transfer_buffer,
 393                            struct ci_hdrc_dma_aligned_buffer, data);
 394
 395        if (usb_urb_dir_in(urb)) {
 396                if (usb_pipeisoc(urb->pipe))
 397                        length = urb->transfer_buffer_length;
 398                else
 399                        length = urb->actual_length;
 400
 401                memcpy(temp->old_xfer_buffer, temp->data, length);
 402        }
 403        urb->transfer_buffer = temp->old_xfer_buffer;
 404        kfree(temp->kmalloc_ptr);
 405
 406        urb->transfer_flags &= ~URB_ALIGNED_TEMP_BUFFER;
 407}
 408
 409static int ci_hdrc_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags)
 410{
 411        struct ci_hdrc_dma_aligned_buffer *temp, *kmalloc_ptr;
 412        const unsigned int ci_hdrc_usb_dma_align = 32;
 413        size_t kmalloc_size;
 414
 415        if (urb->num_sgs || urb->sg || urb->transfer_buffer_length == 0 ||
 416            !((uintptr_t)urb->transfer_buffer & (ci_hdrc_usb_dma_align - 1)))
 417                return 0;
 418
 419        /* Allocate a buffer with enough padding for alignment */
 420        kmalloc_size = urb->transfer_buffer_length +
 421                       sizeof(struct ci_hdrc_dma_aligned_buffer) +
 422                       ci_hdrc_usb_dma_align - 1;
 423
 424        kmalloc_ptr = kmalloc(kmalloc_size, mem_flags);
 425        if (!kmalloc_ptr)
 426                return -ENOMEM;
 427
 428        /* Position our struct dma_aligned_buffer such that data is aligned */
 429        temp = PTR_ALIGN(kmalloc_ptr + 1, ci_hdrc_usb_dma_align) - 1;
 430        temp->kmalloc_ptr = kmalloc_ptr;
 431        temp->old_xfer_buffer = urb->transfer_buffer;
 432        if (usb_urb_dir_out(urb))
 433                memcpy(temp->data, urb->transfer_buffer,
 434                       urb->transfer_buffer_length);
 435        urb->transfer_buffer = temp->data;
 436
 437        urb->transfer_flags |= URB_ALIGNED_TEMP_BUFFER;
 438
 439        return 0;
 440}
 441
 442static int ci_hdrc_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
 443                                   gfp_t mem_flags)
 444{
 445        int ret;
 446
 447        ret = ci_hdrc_alloc_dma_aligned_buffer(urb, mem_flags);
 448        if (ret)
 449                return ret;
 450
 451        ret = usb_hcd_map_urb_for_dma(hcd, urb, mem_flags);
 452        if (ret)
 453                ci_hdrc_free_dma_aligned_buffer(urb);
 454
 455        return ret;
 456}
 457
 458static void ci_hdrc_unmap_urb_for_dma(struct usb_hcd *hcd, struct urb *urb)
 459{
 460        usb_hcd_unmap_urb_for_dma(hcd, urb);
 461        ci_hdrc_free_dma_aligned_buffer(urb);
 462}
 463
 464int ci_hdrc_host_init(struct ci_hdrc *ci)
 465{
 466        struct ci_role_driver *rdrv;
 467
 468        if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_HC))
 469                return -ENXIO;
 470
 471        rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL);
 472        if (!rdrv)
 473                return -ENOMEM;
 474
 475        rdrv->start     = host_start;
 476        rdrv->stop      = host_stop;
 477        rdrv->irq       = host_irq;
 478        rdrv->name      = "host";
 479        ci->roles[CI_ROLE_HOST] = rdrv;
 480
 481        if (ci->platdata->flags & CI_HDRC_REQUIRES_ALIGNED_DMA) {
 482                ci_ehci_hc_driver.map_urb_for_dma = ci_hdrc_map_urb_for_dma;
 483                ci_ehci_hc_driver.unmap_urb_for_dma = ci_hdrc_unmap_urb_for_dma;
 484        }
 485
 486        return 0;
 487}
 488
 489void ci_hdrc_host_driver_init(void)
 490{
 491        ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
 492        orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
 493        ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
 494        ci_ehci_hc_driver.hub_control = ci_ehci_hub_control;
 495}
 496