root/drivers/usb/dwc3/drd.c

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

DEFINITIONS

This source file includes following definitions.
  1. dwc3_otg_disable_events
  2. dwc3_otg_enable_events
  3. dwc3_otg_clear_events
  4. dwc3_otg_thread_irq
  5. dwc3_otg_irq
  6. dwc3_otgregs_init
  7. dwc3_otg_get_irq
  8. dwc3_otg_init
  9. dwc3_otg_exit
  10. dwc3_otg_host_init
  11. dwc3_otg_host_exit
  12. dwc3_otg_device_init
  13. dwc3_otg_device_exit
  14. dwc3_otg_update
  15. dwc3_drd_update
  16. dwc3_drd_notifier
  17. dwc3_get_extcon
  18. dwc3_drd_init
  19. dwc3_drd_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /**
   3  * drd.c - DesignWare USB3 DRD Controller Dual-role support
   4  *
   5  * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com
   6  *
   7  * Authors: Roger Quadros <rogerq@ti.com>
   8  */
   9 
  10 #include <linux/extcon.h>
  11 #include <linux/of_graph.h>
  12 #include <linux/platform_device.h>
  13 #include <linux/property.h>
  14 
  15 #include "debug.h"
  16 #include "core.h"
  17 #include "gadget.h"
  18 
  19 static void dwc3_otg_disable_events(struct dwc3 *dwc, u32 disable_mask)
  20 {
  21         u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN);
  22 
  23         reg &= ~(disable_mask);
  24         dwc3_writel(dwc->regs, DWC3_OEVTEN, reg);
  25 }
  26 
  27 static void dwc3_otg_enable_events(struct dwc3 *dwc, u32 enable_mask)
  28 {
  29         u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN);
  30 
  31         reg |= (enable_mask);
  32         dwc3_writel(dwc->regs, DWC3_OEVTEN, reg);
  33 }
  34 
  35 static void dwc3_otg_clear_events(struct dwc3 *dwc)
  36 {
  37         u32 reg = dwc3_readl(dwc->regs, DWC3_OEVT);
  38 
  39         dwc3_writel(dwc->regs, DWC3_OEVTEN, reg);
  40 }
  41 
  42 #define DWC3_OTG_ALL_EVENTS     (DWC3_OEVTEN_XHCIRUNSTPSETEN | \
  43                 DWC3_OEVTEN_DEVRUNSTPSETEN | DWC3_OEVTEN_HIBENTRYEN | \
  44                 DWC3_OEVTEN_CONIDSTSCHNGEN | DWC3_OEVTEN_HRRCONFNOTIFEN | \
  45                 DWC3_OEVTEN_HRRINITNOTIFEN | DWC3_OEVTEN_ADEVIDLEEN | \
  46                 DWC3_OEVTEN_ADEVBHOSTENDEN | DWC3_OEVTEN_ADEVHOSTEN | \
  47                 DWC3_OEVTEN_ADEVHNPCHNGEN | DWC3_OEVTEN_ADEVSRPDETEN | \
  48                 DWC3_OEVTEN_ADEVSESSENDDETEN | DWC3_OEVTEN_BDEVBHOSTENDEN | \
  49                 DWC3_OEVTEN_BDEVHNPCHNGEN | DWC3_OEVTEN_BDEVSESSVLDDETEN | \
  50                 DWC3_OEVTEN_BDEVVBUSCHNGEN)
  51 
  52 static irqreturn_t dwc3_otg_thread_irq(int irq, void *_dwc)
  53 {
  54         struct dwc3 *dwc = _dwc;
  55 
  56         spin_lock(&dwc->lock);
  57         if (dwc->otg_restart_host) {
  58                 dwc3_otg_host_init(dwc);
  59                 dwc->otg_restart_host = 0;
  60         }
  61 
  62         spin_unlock(&dwc->lock);
  63 
  64         dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
  65 
  66         return IRQ_HANDLED;
  67 }
  68 
  69 static irqreturn_t dwc3_otg_irq(int irq, void *_dwc)
  70 {
  71         u32 reg;
  72         struct dwc3 *dwc = _dwc;
  73         irqreturn_t ret = IRQ_NONE;
  74 
  75         reg = dwc3_readl(dwc->regs, DWC3_OEVT);
  76         if (reg) {
  77                 /* ignore non OTG events, we can't disable them in OEVTEN */
  78                 if (!(reg & DWC3_OTG_ALL_EVENTS)) {
  79                         dwc3_writel(dwc->regs, DWC3_OEVT, reg);
  80                         return IRQ_NONE;
  81                 }
  82 
  83                 if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST &&
  84                     !(reg & DWC3_OEVT_DEVICEMODE))
  85                         dwc->otg_restart_host = 1;
  86                 dwc3_writel(dwc->regs, DWC3_OEVT, reg);
  87                 ret = IRQ_WAKE_THREAD;
  88         }
  89 
  90         return ret;
  91 }
  92 
  93 static void dwc3_otgregs_init(struct dwc3 *dwc)
  94 {
  95         u32 reg;
  96 
  97         /*
  98          * Prevent host/device reset from resetting OTG core.
  99          * If we don't do this then xhci_reset (USBCMD.HCRST) will reset
 100          * the signal outputs sent to the PHY, the OTG FSM logic of the
 101          * core and also the resets to the VBUS filters inside the core.
 102          */
 103         reg = dwc3_readl(dwc->regs, DWC3_OCFG);
 104         reg |= DWC3_OCFG_SFTRSTMASK;
 105         dwc3_writel(dwc->regs, DWC3_OCFG, reg);
 106 
 107         /* Disable hibernation for simplicity */
 108         reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 109         reg &= ~DWC3_GCTL_GBLHIBERNATIONEN;
 110         dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 111 
 112         /*
 113          * Initialize OTG registers as per
 114          * Figure 11-4 OTG Driver Overall Programming Flow
 115          */
 116         /* OCFG.SRPCap = 0, OCFG.HNPCap = 0 */
 117         reg = dwc3_readl(dwc->regs, DWC3_OCFG);
 118         reg &= ~(DWC3_OCFG_SRPCAP | DWC3_OCFG_HNPCAP);
 119         dwc3_writel(dwc->regs, DWC3_OCFG, reg);
 120         /* OEVT = FFFF */
 121         dwc3_otg_clear_events(dwc);
 122         /* OEVTEN = 0 */
 123         dwc3_otg_disable_events(dwc, DWC3_OTG_ALL_EVENTS);
 124         /* OEVTEN.ConIDStsChngEn = 1. Instead we enable all events */
 125         dwc3_otg_enable_events(dwc, DWC3_OTG_ALL_EVENTS);
 126         /*
 127          * OCTL.PeriMode = 1, OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0,
 128          * OCTL.HNPReq = 0
 129          */
 130         reg = dwc3_readl(dwc->regs, DWC3_OCTL);
 131         reg |= DWC3_OCTL_PERIMODE;
 132         reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN |
 133                  DWC3_OCTL_HNPREQ);
 134         dwc3_writel(dwc->regs, DWC3_OCTL, reg);
 135 }
 136 
 137 static int dwc3_otg_get_irq(struct dwc3 *dwc)
 138 {
 139         struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
 140         int irq;
 141 
 142         irq = platform_get_irq_byname_optional(dwc3_pdev, "otg");
 143         if (irq > 0)
 144                 goto out;
 145 
 146         if (irq == -EPROBE_DEFER)
 147                 goto out;
 148 
 149         irq = platform_get_irq_byname_optional(dwc3_pdev, "dwc_usb3");
 150         if (irq > 0)
 151                 goto out;
 152 
 153         if (irq == -EPROBE_DEFER)
 154                 goto out;
 155 
 156         irq = platform_get_irq(dwc3_pdev, 0);
 157         if (irq > 0)
 158                 goto out;
 159 
 160         if (!irq)
 161                 irq = -EINVAL;
 162 
 163 out:
 164         return irq;
 165 }
 166 
 167 void dwc3_otg_init(struct dwc3 *dwc)
 168 {
 169         u32 reg;
 170 
 171         /*
 172          * As per Figure 11-4 OTG Driver Overall Programming Flow,
 173          * block "Initialize GCTL for OTG operation".
 174          */
 175         /* GCTL.PrtCapDir=2'b11 */
 176         dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG);
 177         /* GUSB2PHYCFG0.SusPHY=0 */
 178         reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 179         reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
 180         dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 181 
 182         /* Initialize OTG registers */
 183         dwc3_otgregs_init(dwc);
 184 }
 185 
 186 void dwc3_otg_exit(struct dwc3 *dwc)
 187 {
 188         /* disable all OTG IRQs */
 189         dwc3_otg_disable_events(dwc, DWC3_OTG_ALL_EVENTS);
 190         /* clear all events */
 191         dwc3_otg_clear_events(dwc);
 192 }
 193 
 194 /* should be called before Host controller driver is started */
 195 void dwc3_otg_host_init(struct dwc3 *dwc)
 196 {
 197         u32 reg;
 198 
 199         /* As per Figure 11-10 A-Device Flow Diagram */
 200         /* OCFG.HNPCap = 0, OCFG.SRPCap = 0. Already 0 */
 201 
 202         /*
 203          * OCTL.PeriMode=0, OCTL.TermSelDLPulse = 0,
 204          * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0
 205          */
 206         reg = dwc3_readl(dwc->regs, DWC3_OCTL);
 207         reg &= ~(DWC3_OCTL_PERIMODE | DWC3_OCTL_TERMSELIDPULSE |
 208                         DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN);
 209         dwc3_writel(dwc->regs, DWC3_OCTL, reg);
 210 
 211         /*
 212          * OCFG.DisPrtPwrCutoff = 0/1
 213          */
 214         reg = dwc3_readl(dwc->regs, DWC3_OCFG);
 215         reg &= ~DWC3_OCFG_DISPWRCUTTOFF;
 216         dwc3_writel(dwc->regs, DWC3_OCFG, reg);
 217 
 218         /*
 219          * OCFG.SRPCap = 1, OCFG.HNPCap = GHWPARAMS6.HNP_CAP
 220          * We don't want SRP/HNP for simple dual-role so leave
 221          * these disabled.
 222          */
 223 
 224         /*
 225          * OEVTEN.OTGADevHostEvntEn = 1
 226          * OEVTEN.OTGADevSessEndDetEvntEn = 1
 227          * We don't want HNP/role-swap so leave these disabled.
 228          */
 229 
 230         /* GUSB2PHYCFG.ULPIAutoRes = 1/0, GUSB2PHYCFG.SusPHY = 1 */
 231         if (!dwc->dis_u2_susphy_quirk) {
 232                 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 233                 reg |= DWC3_GUSB2PHYCFG_SUSPHY;
 234                 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 235         }
 236 
 237         /* Set Port Power to enable VBUS: OCTL.PrtPwrCtl = 1 */
 238         reg = dwc3_readl(dwc->regs, DWC3_OCTL);
 239         reg |= DWC3_OCTL_PRTPWRCTL;
 240         dwc3_writel(dwc->regs, DWC3_OCTL, reg);
 241 }
 242 
 243 /* should be called after Host controller driver is stopped */
 244 static void dwc3_otg_host_exit(struct dwc3 *dwc)
 245 {
 246         u32 reg;
 247 
 248         /*
 249          * Exit from A-device flow as per
 250          * Figure 11-4 OTG Driver Overall Programming Flow
 251          */
 252 
 253         /*
 254          * OEVTEN.OTGADevBHostEndEvntEn=0, OEVTEN.OTGADevHNPChngEvntEn=0
 255          * OEVTEN.OTGADevSessEndDetEvntEn=0,
 256          * OEVTEN.OTGADevHostEvntEn = 0
 257          * But we don't disable any OTG events
 258          */
 259 
 260         /* OCTL.HstSetHNPEn = 0, OCTL.PrtPwrCtl=0 */
 261         reg = dwc3_readl(dwc->regs, DWC3_OCTL);
 262         reg &= ~(DWC3_OCTL_HSTSETHNPEN | DWC3_OCTL_PRTPWRCTL);
 263         dwc3_writel(dwc->regs, DWC3_OCTL, reg);
 264 }
 265 
 266 /* should be called before the gadget controller driver is started */
 267 static void dwc3_otg_device_init(struct dwc3 *dwc)
 268 {
 269         u32 reg;
 270 
 271         /* As per Figure 11-20 B-Device Flow Diagram */
 272 
 273         /*
 274          * OCFG.HNPCap = GHWPARAMS6.HNP_CAP, OCFG.SRPCap = 1
 275          * but we keep them 0 for simple dual-role operation.
 276          */
 277         reg = dwc3_readl(dwc->regs, DWC3_OCFG);
 278         /* OCFG.OTGSftRstMsk = 0/1 */
 279         reg |= DWC3_OCFG_SFTRSTMASK;
 280         dwc3_writel(dwc->regs, DWC3_OCFG, reg);
 281         /*
 282          * OCTL.PeriMode = 1
 283          * OCTL.TermSelDLPulse = 0/1, OCTL.HNPReq = 0
 284          * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0
 285          */
 286         reg = dwc3_readl(dwc->regs, DWC3_OCTL);
 287         reg |= DWC3_OCTL_PERIMODE;
 288         reg &= ~(DWC3_OCTL_TERMSELIDPULSE | DWC3_OCTL_HNPREQ |
 289                         DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN);
 290         dwc3_writel(dwc->regs, DWC3_OCTL, reg);
 291         /* OEVTEN.OTGBDevSesVldDetEvntEn = 1 */
 292         dwc3_otg_enable_events(dwc, DWC3_OEVTEN_BDEVSESSVLDDETEN);
 293         /* GUSB2PHYCFG.ULPIAutoRes = 0, GUSB2PHYCFG0.SusPHY = 1 */
 294         if (!dwc->dis_u2_susphy_quirk) {
 295                 reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
 296                 reg |= DWC3_GUSB2PHYCFG_SUSPHY;
 297                 dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
 298         }
 299         /* GCTL.GblHibernationEn = 0. Already 0. */
 300 }
 301 
 302 /* should be called after the gadget controller driver is stopped */
 303 static void dwc3_otg_device_exit(struct dwc3 *dwc)
 304 {
 305         u32 reg;
 306 
 307         /*
 308          * Exit from B-device flow as per
 309          * Figure 11-4 OTG Driver Overall Programming Flow
 310          */
 311 
 312         /*
 313          * OEVTEN.OTGBDevHNPChngEvntEn = 0
 314          * OEVTEN.OTGBDevVBusChngEvntEn = 0
 315          * OEVTEN.OTGBDevBHostEndEvntEn = 0
 316          */
 317         dwc3_otg_disable_events(dwc, DWC3_OEVTEN_BDEVHNPCHNGEN |
 318                                 DWC3_OEVTEN_BDEVVBUSCHNGEN |
 319                                 DWC3_OEVTEN_BDEVBHOSTENDEN);
 320 
 321         /* OCTL.DevSetHNPEn = 0, OCTL.HNPReq = 0, OCTL.PeriMode=1 */
 322         reg = dwc3_readl(dwc->regs, DWC3_OCTL);
 323         reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HNPREQ);
 324         reg |= DWC3_OCTL_PERIMODE;
 325         dwc3_writel(dwc->regs, DWC3_OCTL, reg);
 326 }
 327 
 328 void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus)
 329 {
 330         int ret;
 331         u32 reg;
 332         int id;
 333         unsigned long flags;
 334 
 335         if (dwc->dr_mode != USB_DR_MODE_OTG)
 336                 return;
 337 
 338         /* don't do anything if debug user changed role to not OTG */
 339         if (dwc->current_dr_role != DWC3_GCTL_PRTCAP_OTG)
 340                 return;
 341 
 342         if (!ignore_idstatus) {
 343                 reg = dwc3_readl(dwc->regs, DWC3_OSTS);
 344                 id = !!(reg & DWC3_OSTS_CONIDSTS);
 345 
 346                 dwc->desired_otg_role = id ? DWC3_OTG_ROLE_DEVICE :
 347                                         DWC3_OTG_ROLE_HOST;
 348         }
 349 
 350         if (dwc->desired_otg_role == dwc->current_otg_role)
 351                 return;
 352 
 353         switch (dwc->current_otg_role) {
 354         case DWC3_OTG_ROLE_HOST:
 355                 dwc3_host_exit(dwc);
 356                 spin_lock_irqsave(&dwc->lock, flags);
 357                 dwc3_otg_host_exit(dwc);
 358                 spin_unlock_irqrestore(&dwc->lock, flags);
 359                 break;
 360         case DWC3_OTG_ROLE_DEVICE:
 361                 dwc3_gadget_exit(dwc);
 362                 spin_lock_irqsave(&dwc->lock, flags);
 363                 dwc3_event_buffers_cleanup(dwc);
 364                 dwc3_otg_device_exit(dwc);
 365                 spin_unlock_irqrestore(&dwc->lock, flags);
 366                 break;
 367         default:
 368                 break;
 369         }
 370 
 371         spin_lock_irqsave(&dwc->lock, flags);
 372 
 373         dwc->current_otg_role = dwc->desired_otg_role;
 374 
 375         spin_unlock_irqrestore(&dwc->lock, flags);
 376 
 377         switch (dwc->desired_otg_role) {
 378         case DWC3_OTG_ROLE_HOST:
 379                 spin_lock_irqsave(&dwc->lock, flags);
 380                 dwc3_otgregs_init(dwc);
 381                 dwc3_otg_host_init(dwc);
 382                 spin_unlock_irqrestore(&dwc->lock, flags);
 383                 ret = dwc3_host_init(dwc);
 384                 if (ret) {
 385                         dev_err(dwc->dev, "failed to initialize host\n");
 386                 } else {
 387                         if (dwc->usb2_phy)
 388                                 otg_set_vbus(dwc->usb2_phy->otg, true);
 389                         if (dwc->usb2_generic_phy)
 390                                 phy_set_mode(dwc->usb2_generic_phy,
 391                                              PHY_MODE_USB_HOST);
 392                 }
 393                 break;
 394         case DWC3_OTG_ROLE_DEVICE:
 395                 spin_lock_irqsave(&dwc->lock, flags);
 396                 dwc3_otgregs_init(dwc);
 397                 dwc3_otg_device_init(dwc);
 398                 dwc3_event_buffers_setup(dwc);
 399                 spin_unlock_irqrestore(&dwc->lock, flags);
 400 
 401                 if (dwc->usb2_phy)
 402                         otg_set_vbus(dwc->usb2_phy->otg, false);
 403                 if (dwc->usb2_generic_phy)
 404                         phy_set_mode(dwc->usb2_generic_phy,
 405                                      PHY_MODE_USB_DEVICE);
 406                 ret = dwc3_gadget_init(dwc);
 407                 if (ret)
 408                         dev_err(dwc->dev, "failed to initialize peripheral\n");
 409                 break;
 410         default:
 411                 break;
 412         }
 413 }
 414 
 415 static void dwc3_drd_update(struct dwc3 *dwc)
 416 {
 417         int id;
 418 
 419         if (dwc->edev) {
 420                 id = extcon_get_state(dwc->edev, EXTCON_USB_HOST);
 421                 if (id < 0)
 422                         id = 0;
 423                 dwc3_set_mode(dwc, id ?
 424                               DWC3_GCTL_PRTCAP_HOST :
 425                               DWC3_GCTL_PRTCAP_DEVICE);
 426         }
 427 }
 428 
 429 static int dwc3_drd_notifier(struct notifier_block *nb,
 430                              unsigned long event, void *ptr)
 431 {
 432         struct dwc3 *dwc = container_of(nb, struct dwc3, edev_nb);
 433 
 434         dwc3_set_mode(dwc, event ?
 435                       DWC3_GCTL_PRTCAP_HOST :
 436                       DWC3_GCTL_PRTCAP_DEVICE);
 437 
 438         return NOTIFY_DONE;
 439 }
 440 
 441 static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
 442 {
 443         struct device *dev = dwc->dev;
 444         struct device_node *np_phy, *np_conn;
 445         struct extcon_dev *edev;
 446         const char *name;
 447 
 448         if (device_property_read_bool(dev, "extcon"))
 449                 return extcon_get_edev_by_phandle(dev, 0);
 450 
 451         /*
 452          * Device tree platforms should get extcon via phandle.
 453          * On ACPI platforms, we get the name from a device property.
 454          * This device property is for kernel internal use only and
 455          * is expected to be set by the glue code.
 456          */
 457         if (device_property_read_string(dev, "linux,extcon-name", &name) == 0) {
 458                 edev = extcon_get_extcon_dev(name);
 459                 if (!edev)
 460                         return ERR_PTR(-EPROBE_DEFER);
 461 
 462                 return edev;
 463         }
 464 
 465         np_phy = of_parse_phandle(dev->of_node, "phys", 0);
 466         np_conn = of_graph_get_remote_node(np_phy, -1, -1);
 467 
 468         if (np_conn)
 469                 edev = extcon_find_edev_by_node(np_conn);
 470         else
 471                 edev = NULL;
 472 
 473         of_node_put(np_conn);
 474         of_node_put(np_phy);
 475 
 476         return edev;
 477 }
 478 
 479 int dwc3_drd_init(struct dwc3 *dwc)
 480 {
 481         int ret, irq;
 482 
 483         dwc->edev = dwc3_get_extcon(dwc);
 484         if (IS_ERR(dwc->edev))
 485                 return PTR_ERR(dwc->edev);
 486 
 487         if (dwc->edev) {
 488                 dwc->edev_nb.notifier_call = dwc3_drd_notifier;
 489                 ret = extcon_register_notifier(dwc->edev, EXTCON_USB_HOST,
 490                                                &dwc->edev_nb);
 491                 if (ret < 0) {
 492                         dev_err(dwc->dev, "couldn't register cable notifier\n");
 493                         return ret;
 494                 }
 495 
 496                 dwc3_drd_update(dwc);
 497         } else {
 498                 dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG);
 499                 dwc->current_dr_role = DWC3_GCTL_PRTCAP_OTG;
 500 
 501                 /* use OTG block to get ID event */
 502                 irq = dwc3_otg_get_irq(dwc);
 503                 if (irq < 0)
 504                         return irq;
 505 
 506                 dwc->otg_irq = irq;
 507 
 508                 /* disable all OTG IRQs */
 509                 dwc3_otg_disable_events(dwc, DWC3_OTG_ALL_EVENTS);
 510                 /* clear all events */
 511                 dwc3_otg_clear_events(dwc);
 512 
 513                 ret = request_threaded_irq(dwc->otg_irq, dwc3_otg_irq,
 514                                            dwc3_otg_thread_irq,
 515                                            IRQF_SHARED, "dwc3-otg", dwc);
 516                 if (ret) {
 517                         dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
 518                                 dwc->otg_irq, ret);
 519                         ret = -ENODEV;
 520                         return ret;
 521                 }
 522 
 523                 dwc3_otg_init(dwc);
 524                 dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
 525         }
 526 
 527         return 0;
 528 }
 529 
 530 void dwc3_drd_exit(struct dwc3 *dwc)
 531 {
 532         unsigned long flags;
 533 
 534         if (dwc->edev)
 535                 extcon_unregister_notifier(dwc->edev, EXTCON_USB_HOST,
 536                                            &dwc->edev_nb);
 537 
 538         cancel_work_sync(&dwc->drd_work);
 539 
 540         /* debug user might have changed role, clean based on current role */
 541         switch (dwc->current_dr_role) {
 542         case DWC3_GCTL_PRTCAP_HOST:
 543                 dwc3_host_exit(dwc);
 544                 break;
 545         case DWC3_GCTL_PRTCAP_DEVICE:
 546                 dwc3_gadget_exit(dwc);
 547                 dwc3_event_buffers_cleanup(dwc);
 548                 break;
 549         case DWC3_GCTL_PRTCAP_OTG:
 550                 dwc3_otg_exit(dwc);
 551                 spin_lock_irqsave(&dwc->lock, flags);
 552                 dwc->desired_otg_role = DWC3_OTG_ROLE_IDLE;
 553                 spin_unlock_irqrestore(&dwc->lock, flags);
 554                 dwc3_otg_update(dwc, 1);
 555                 break;
 556         default:
 557                 break;
 558         }
 559 
 560         if (!dwc->edev)
 561                 free_irq(dwc->otg_irq, dwc);
 562 }

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