root/drivers/usb/chipidea/host.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ehci_ci_portpower
  2. ehci_ci_reset
  3. host_irq
  4. host_start
  5. host_stop
  6. ci_hdrc_host_destroy
  7. ci_ehci_hub_control
  8. ci_ehci_bus_suspend
  9. ci_hdrc_host_init
  10. ci_hdrc_host_driver_init

   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 
  24 static struct hc_driver __read_mostly ci_ehci_hc_driver;
  25 static int (*orig_bus_suspend)(struct usb_hcd *hcd);
  26 
  27 struct ehci_ci_priv {
  28         struct regulator *reg_vbus;
  29         bool enabled;
  30 };
  31 
  32 static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
  33 {
  34         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
  35         struct ehci_ci_priv *priv = (struct ehci_ci_priv *)ehci->priv;
  36         struct device *dev = hcd->self.controller;
  37         struct ci_hdrc *ci = dev_get_drvdata(dev);
  38         int ret = 0;
  39         int port = HCS_N_PORTS(ehci->hcs_params);
  40 
  41         if (priv->reg_vbus && enable != priv->enabled) {
  42                 if (port > 1) {
  43                         dev_warn(dev,
  44                                 "Not support multi-port regulator control\n");
  45                         return 0;
  46                 }
  47                 if (enable)
  48                         ret = regulator_enable(priv->reg_vbus);
  49                 else
  50                         ret = regulator_disable(priv->reg_vbus);
  51                 if (ret) {
  52                         dev_err(dev,
  53                                 "Failed to %s vbus regulator, ret=%d\n",
  54                                 enable ? "enable" : "disable", ret);
  55                         return ret;
  56                 }
  57                 priv->enabled = enable;
  58         }
  59 
  60         if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
  61                 /*
  62                  * Marvell 28nm HSIC PHY requires forcing the port to HS mode.
  63                  * As HSIC is always HS, this should be safe for others.
  64                  */
  65                 hw_port_test_set(ci, 5);
  66                 hw_port_test_set(ci, 0);
  67         }
  68         return 0;
  69 };
  70 
  71 static int ehci_ci_reset(struct usb_hcd *hcd)
  72 {
  73         struct device *dev = hcd->self.controller;
  74         struct ci_hdrc *ci = dev_get_drvdata(dev);
  75         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
  76         int ret;
  77 
  78         ret = ehci_setup(hcd);
  79         if (ret)
  80                 return ret;
  81 
  82         ehci->need_io_watchdog = 0;
  83 
  84         if (ci->platdata->notify_event) {
  85                 ret = ci->platdata->notify_event(ci,
  86                                 CI_HDRC_CONTROLLER_RESET_EVENT);
  87                 if (ret)
  88                         return ret;
  89         }
  90 
  91         ci_platform_configure(ci);
  92 
  93         return ret;
  94 }
  95 
  96 static const struct ehci_driver_overrides ehci_ci_overrides = {
  97         .extra_priv_size = sizeof(struct ehci_ci_priv),
  98         .port_power      = ehci_ci_portpower,
  99         .reset           = ehci_ci_reset,
 100 };
 101 
 102 static irqreturn_t host_irq(struct ci_hdrc *ci)
 103 {
 104         return usb_hcd_irq(ci->irq, ci->hcd);
 105 }
 106 
 107 static int host_start(struct ci_hdrc *ci)
 108 {
 109         struct usb_hcd *hcd;
 110         struct ehci_hcd *ehci;
 111         struct ehci_ci_priv *priv;
 112         int ret;
 113 
 114         if (usb_disabled())
 115                 return -ENODEV;
 116 
 117         hcd = __usb_create_hcd(&ci_ehci_hc_driver, ci->dev->parent,
 118                                ci->dev, dev_name(ci->dev), NULL);
 119         if (!hcd)
 120                 return -ENOMEM;
 121 
 122         dev_set_drvdata(ci->dev, ci);
 123         hcd->rsrc_start = ci->hw_bank.phys;
 124         hcd->rsrc_len = ci->hw_bank.size;
 125         hcd->regs = ci->hw_bank.abs;
 126         hcd->has_tt = 1;
 127 
 128         hcd->power_budget = ci->platdata->power_budget;
 129         hcd->tpl_support = ci->platdata->tpl_support;
 130         if (ci->phy || ci->usb_phy) {
 131                 hcd->skip_phy_initialization = 1;
 132                 if (ci->usb_phy)
 133                         hcd->usb_phy = ci->usb_phy;
 134         }
 135 
 136         ehci = hcd_to_ehci(hcd);
 137         ehci->caps = ci->hw_bank.cap;
 138         ehci->has_hostpc = ci->hw_bank.lpm;
 139         ehci->has_tdi_phy_lpm = ci->hw_bank.lpm;
 140         ehci->imx28_write_fix = ci->imx28_write_fix;
 141 
 142         priv = (struct ehci_ci_priv *)ehci->priv;
 143         priv->reg_vbus = NULL;
 144 
 145         if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
 146                 if (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON) {
 147                         ret = regulator_enable(ci->platdata->reg_vbus);
 148                         if (ret) {
 149                                 dev_err(ci->dev,
 150                                 "Failed to enable vbus regulator, ret=%d\n",
 151                                                                         ret);
 152                                 goto put_hcd;
 153                         }
 154                 } else {
 155                         priv->reg_vbus = ci->platdata->reg_vbus;
 156                 }
 157         }
 158 
 159         if (ci->platdata->pins_host)
 160                 pinctrl_select_state(ci->platdata->pctl,
 161                                      ci->platdata->pins_host);
 162 
 163         ret = usb_add_hcd(hcd, 0, 0);
 164         if (ret) {
 165                 goto disable_reg;
 166         } else {
 167                 struct usb_otg *otg = &ci->otg;
 168 
 169                 ci->hcd = hcd;
 170 
 171                 if (ci_otg_is_fsm_mode(ci)) {
 172                         otg->host = &hcd->self;
 173                         hcd->self.otg_port = 1;
 174                 }
 175 
 176                 if (ci->platdata->notify_event &&
 177                         (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC))
 178                         ci->platdata->notify_event
 179                                 (ci, CI_HDRC_IMX_HSIC_ACTIVE_EVENT);
 180         }
 181 
 182         return ret;
 183 
 184 disable_reg:
 185         if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
 186                         (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
 187                 regulator_disable(ci->platdata->reg_vbus);
 188 put_hcd:
 189         usb_put_hcd(hcd);
 190 
 191         return ret;
 192 }
 193 
 194 static void host_stop(struct ci_hdrc *ci)
 195 {
 196         struct usb_hcd *hcd = ci->hcd;
 197 
 198         if (hcd) {
 199                 if (ci->platdata->notify_event)
 200                         ci->platdata->notify_event(ci,
 201                                 CI_HDRC_CONTROLLER_STOPPED_EVENT);
 202                 usb_remove_hcd(hcd);
 203                 ci->role = CI_ROLE_END;
 204                 synchronize_irq(ci->irq);
 205                 usb_put_hcd(hcd);
 206                 if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
 207                         (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
 208                                 regulator_disable(ci->platdata->reg_vbus);
 209         }
 210         ci->hcd = NULL;
 211         ci->otg.host = NULL;
 212 
 213         if (ci->platdata->pins_host && ci->platdata->pins_default)
 214                 pinctrl_select_state(ci->platdata->pctl,
 215                                      ci->platdata->pins_default);
 216 }
 217 
 218 
 219 void ci_hdrc_host_destroy(struct ci_hdrc *ci)
 220 {
 221         if (ci->role == CI_ROLE_HOST && ci->hcd)
 222                 host_stop(ci);
 223 }
 224 
 225 /* The below code is based on tegra ehci driver */
 226 static int ci_ehci_hub_control(
 227         struct usb_hcd  *hcd,
 228         u16             typeReq,
 229         u16             wValue,
 230         u16             wIndex,
 231         char            *buf,
 232         u16             wLength
 233 )
 234 {
 235         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 236         u32 __iomem     *status_reg;
 237         u32             temp;
 238         unsigned long   flags;
 239         int             retval = 0;
 240         struct device *dev = hcd->self.controller;
 241         struct ci_hdrc *ci = dev_get_drvdata(dev);
 242 
 243         status_reg = &ehci->regs->port_status[(wIndex & 0xff) - 1];
 244 
 245         spin_lock_irqsave(&ehci->lock, flags);
 246 
 247         if (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_SUSPEND) {
 248                 temp = ehci_readl(ehci, status_reg);
 249                 if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) != 0) {
 250                         retval = -EPIPE;
 251                         goto done;
 252                 }
 253 
 254                 temp &= ~(PORT_RWC_BITS | PORT_WKCONN_E);
 255                 temp |= PORT_WKDISC_E | PORT_WKOC_E;
 256                 ehci_writel(ehci, temp | PORT_SUSPEND, status_reg);
 257 
 258                 /*
 259                  * If a transaction is in progress, there may be a delay in
 260                  * suspending the port. Poll until the port is suspended.
 261                  */
 262                 if (ehci_handshake(ehci, status_reg, PORT_SUSPEND,
 263                         PORT_SUSPEND, 5000))
 264                         ehci_err(ehci, "timeout waiting for SUSPEND\n");
 265 
 266                 if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
 267                         if (ci->platdata->notify_event)
 268                                 ci->platdata->notify_event(ci,
 269                                         CI_HDRC_IMX_HSIC_SUSPEND_EVENT);
 270 
 271                         temp = ehci_readl(ehci, status_reg);
 272                         temp &= ~(PORT_WKDISC_E | PORT_WKCONN_E);
 273                         ehci_writel(ehci, temp, status_reg);
 274                 }
 275 
 276                 set_bit((wIndex & 0xff) - 1, &ehci->suspended_ports);
 277                 goto done;
 278         }
 279 
 280         /*
 281          * After resume has finished, it needs do some post resume
 282          * operation for some SoCs.
 283          */
 284         else if (typeReq == ClearPortFeature &&
 285                 wValue == USB_PORT_FEAT_C_SUSPEND) {
 286                 /* Make sure the resume has finished, it should be finished */
 287                 if (ehci_handshake(ehci, status_reg, PORT_RESUME, 0, 25000))
 288                         ehci_err(ehci, "timeout waiting for resume\n");
 289         }
 290 
 291         spin_unlock_irqrestore(&ehci->lock, flags);
 292 
 293         /* Handle the hub control events here */
 294         return ehci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength);
 295 done:
 296         spin_unlock_irqrestore(&ehci->lock, flags);
 297         return retval;
 298 }
 299 static int ci_ehci_bus_suspend(struct usb_hcd *hcd)
 300 {
 301         struct ehci_hcd *ehci = hcd_to_ehci(hcd);
 302         struct device *dev = hcd->self.controller;
 303         struct ci_hdrc *ci = dev_get_drvdata(dev);
 304         int port;
 305         u32 tmp;
 306 
 307         int ret = orig_bus_suspend(hcd);
 308 
 309         if (ret)
 310                 return ret;
 311 
 312         port = HCS_N_PORTS(ehci->hcs_params);
 313         while (port--) {
 314                 u32 __iomem *reg = &ehci->regs->port_status[port];
 315                 u32 portsc = ehci_readl(ehci, reg);
 316 
 317                 if (portsc & PORT_CONNECT) {
 318                         /*
 319                          * For chipidea, the resume signal will be ended
 320                          * automatically, so for remote wakeup case, the
 321                          * usbcmd.rs may not be set before the resume has
 322                          * ended if other resume paths consumes too much
 323                          * time (~24ms), in that case, the SOF will not
 324                          * send out within 3ms after resume ends, then the
 325                          * high speed device will enter full speed mode.
 326                          */
 327 
 328                         tmp = ehci_readl(ehci, &ehci->regs->command);
 329                         tmp |= CMD_RUN;
 330                         ehci_writel(ehci, tmp, &ehci->regs->command);
 331                         /*
 332                          * It needs a short delay between set RS bit and PHCD.
 333                          */
 334                         usleep_range(150, 200);
 335                         /*
 336                          * Need to clear WKCN and WKOC for imx HSIC,
 337                          * otherwise, there will be wakeup event.
 338                          */
 339                         if (ci->platdata->flags & CI_HDRC_IMX_IS_HSIC) {
 340                                 tmp = ehci_readl(ehci, reg);
 341                                 tmp &= ~(PORT_WKDISC_E | PORT_WKCONN_E);
 342                                 ehci_writel(ehci, tmp, reg);
 343                         }
 344 
 345                         break;
 346                 }
 347         }
 348 
 349         return 0;
 350 }
 351 
 352 int ci_hdrc_host_init(struct ci_hdrc *ci)
 353 {
 354         struct ci_role_driver *rdrv;
 355 
 356         if (!hw_read(ci, CAP_DCCPARAMS, DCCPARAMS_HC))
 357                 return -ENXIO;
 358 
 359         rdrv = devm_kzalloc(ci->dev, sizeof(struct ci_role_driver), GFP_KERNEL);
 360         if (!rdrv)
 361                 return -ENOMEM;
 362 
 363         rdrv->start     = host_start;
 364         rdrv->stop      = host_stop;
 365         rdrv->irq       = host_irq;
 366         rdrv->name      = "host";
 367         ci->roles[CI_ROLE_HOST] = rdrv;
 368 
 369         return 0;
 370 }
 371 
 372 void ci_hdrc_host_driver_init(void)
 373 {
 374         ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
 375         orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
 376         ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
 377         ci_ehci_hc_driver.hub_control = ci_ehci_hub_control;
 378 }

/* [<][>][^][v][top][bottom][index][help] */