root/drivers/usb/cdns3/drd.c

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

DEFINITIONS

This source file includes following definitions.
  1. cdns3_set_mode
  2. cdns3_get_id
  3. cdns3_get_vbus
  4. cdns3_is_host
  5. cdns3_is_device
  6. cdns3_otg_disable_irq
  7. cdns3_otg_enable_irq
  8. cdns3_drd_switch_host
  9. cdns3_drd_switch_gadget
  10. cdns3_init_otg_mode
  11. cdns3_drd_update_mode
  12. cdns3_drd_thread_irq
  13. cdns3_drd_irq
  14. cdns3_drd_init
  15. cdns3_drd_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Cadence USBSS DRD Driver.
   4  *
   5  * Copyright (C) 2018-2019 Cadence.
   6  * Copyright (C) 2019 Texas Instruments
   7  *
   8  * Author: Pawel Laszczak <pawell@cadence.com>
   9  *         Roger Quadros <rogerq@ti.com>
  10  *
  11  *
  12  */
  13 #include <linux/kernel.h>
  14 #include <linux/interrupt.h>
  15 #include <linux/delay.h>
  16 #include <linux/iopoll.h>
  17 #include <linux/usb/otg.h>
  18 
  19 #include "gadget.h"
  20 #include "drd.h"
  21 #include "core.h"
  22 
  23 /**
  24  * cdns3_set_mode - change mode of OTG Core
  25  * @cdns: pointer to context structure
  26  * @mode: selected mode from cdns_role
  27  *
  28  * Returns 0 on success otherwise negative errno
  29  */
  30 int cdns3_set_mode(struct cdns3 *cdns, enum usb_dr_mode mode)
  31 {
  32         int ret = 0;
  33         u32 reg;
  34 
  35         switch (mode) {
  36         case USB_DR_MODE_PERIPHERAL:
  37                 break;
  38         case USB_DR_MODE_HOST:
  39                 break;
  40         case USB_DR_MODE_OTG:
  41                 dev_dbg(cdns->dev, "Set controller to OTG mode\n");
  42                 if (cdns->version == CDNS3_CONTROLLER_V1) {
  43                         reg = readl(&cdns->otg_v1_regs->override);
  44                         reg |= OVERRIDE_IDPULLUP;
  45                         writel(reg, &cdns->otg_v1_regs->override);
  46                 } else {
  47                         reg = readl(&cdns->otg_v0_regs->ctrl1);
  48                         reg |= OVERRIDE_IDPULLUP_V0;
  49                         writel(reg, &cdns->otg_v0_regs->ctrl1);
  50                 }
  51 
  52                 /*
  53                  * Hardware specification says: "ID_VALUE must be valid within
  54                  * 50ms after idpullup is set to '1" so driver must wait
  55                  * 50ms before reading this pin.
  56                  */
  57                 usleep_range(50000, 60000);
  58                 break;
  59         default:
  60                 dev_err(cdns->dev, "Unsupported mode of operation %d\n", mode);
  61                 return -EINVAL;
  62         }
  63 
  64         return ret;
  65 }
  66 
  67 int cdns3_get_id(struct cdns3 *cdns)
  68 {
  69         int id;
  70 
  71         id = readl(&cdns->otg_regs->sts) & OTGSTS_ID_VALUE;
  72         dev_dbg(cdns->dev, "OTG ID: %d", id);
  73 
  74         return id;
  75 }
  76 
  77 int cdns3_get_vbus(struct cdns3 *cdns)
  78 {
  79         int vbus;
  80 
  81         vbus = !!(readl(&cdns->otg_regs->sts) & OTGSTS_VBUS_VALID);
  82         dev_dbg(cdns->dev, "OTG VBUS: %d", vbus);
  83 
  84         return vbus;
  85 }
  86 
  87 int cdns3_is_host(struct cdns3 *cdns)
  88 {
  89         if (cdns->dr_mode == USB_DR_MODE_HOST)
  90                 return 1;
  91         else if (!cdns3_get_id(cdns))
  92                 return 1;
  93 
  94         return 0;
  95 }
  96 
  97 int cdns3_is_device(struct cdns3 *cdns)
  98 {
  99         if (cdns->dr_mode == USB_DR_MODE_PERIPHERAL)
 100                 return 1;
 101         else if (cdns->dr_mode == USB_DR_MODE_OTG)
 102                 if (cdns3_get_id(cdns))
 103                         return 1;
 104 
 105         return 0;
 106 }
 107 
 108 /**
 109  * cdns3_otg_disable_irq - Disable all OTG interrupts
 110  * @cdns: Pointer to controller context structure
 111  */
 112 static void cdns3_otg_disable_irq(struct cdns3 *cdns)
 113 {
 114         writel(0, &cdns->otg_regs->ien);
 115 }
 116 
 117 /**
 118  * cdns3_otg_enable_irq - enable id and sess_valid interrupts
 119  * @cdns: Pointer to controller context structure
 120  */
 121 static void cdns3_otg_enable_irq(struct cdns3 *cdns)
 122 {
 123         writel(OTGIEN_ID_CHANGE_INT | OTGIEN_VBUSVALID_RISE_INT |
 124                OTGIEN_VBUSVALID_FALL_INT, &cdns->otg_regs->ien);
 125 }
 126 
 127 /**
 128  * cdns3_drd_switch_host - start/stop host
 129  * @cdns: Pointer to controller context structure
 130  * @on: 1 for start, 0 for stop
 131  *
 132  * Returns 0 on success otherwise negative errno
 133  */
 134 int cdns3_drd_switch_host(struct cdns3 *cdns, int on)
 135 {
 136         int ret, val;
 137         u32 reg = OTGCMD_OTG_DIS;
 138 
 139         /* switch OTG core */
 140         if (on) {
 141                 writel(OTGCMD_HOST_BUS_REQ | reg, &cdns->otg_regs->cmd);
 142 
 143                 dev_dbg(cdns->dev, "Waiting till Host mode is turned on\n");
 144                 ret = readl_poll_timeout_atomic(&cdns->otg_regs->sts, val,
 145                                                 val & OTGSTS_XHCI_READY,
 146                                                 1, 100000);
 147                 if (ret) {
 148                         dev_err(cdns->dev, "timeout waiting for xhci_ready\n");
 149                         return ret;
 150                 }
 151         } else {
 152                 writel(OTGCMD_HOST_BUS_DROP | OTGCMD_DEV_BUS_DROP |
 153                        OTGCMD_DEV_POWER_OFF | OTGCMD_HOST_POWER_OFF,
 154                        &cdns->otg_regs->cmd);
 155                 /* Waiting till H_IDLE state.*/
 156                 readl_poll_timeout_atomic(&cdns->otg_regs->state, val,
 157                                           !(val & OTGSTATE_HOST_STATE_MASK),
 158                                           1, 2000000);
 159         }
 160 
 161         return 0;
 162 }
 163 
 164 /**
 165  * cdns3_drd_switch_gadget - start/stop gadget
 166  * @cdns: Pointer to controller context structure
 167  * @on: 1 for start, 0 for stop
 168  *
 169  * Returns 0 on success otherwise negative errno
 170  */
 171 int cdns3_drd_switch_gadget(struct cdns3 *cdns, int on)
 172 {
 173         int ret, val;
 174         u32 reg = OTGCMD_OTG_DIS;
 175 
 176         /* switch OTG core */
 177         if (on) {
 178                 writel(OTGCMD_DEV_BUS_REQ | reg, &cdns->otg_regs->cmd);
 179 
 180                 dev_dbg(cdns->dev, "Waiting till Device mode is turned on\n");
 181 
 182                 ret = readl_poll_timeout_atomic(&cdns->otg_regs->sts, val,
 183                                                 val & OTGSTS_DEV_READY,
 184                                                 1, 100000);
 185                 if (ret) {
 186                         dev_err(cdns->dev, "timeout waiting for dev_ready\n");
 187                         return ret;
 188                 }
 189         } else {
 190                 /*
 191                  * driver should wait at least 10us after disabling Device
 192                  * before turning-off Device (DEV_BUS_DROP)
 193                  */
 194                 usleep_range(20, 30);
 195                 writel(OTGCMD_HOST_BUS_DROP | OTGCMD_DEV_BUS_DROP |
 196                        OTGCMD_DEV_POWER_OFF | OTGCMD_HOST_POWER_OFF,
 197                        &cdns->otg_regs->cmd);
 198                 /* Waiting till DEV_IDLE state.*/
 199                 readl_poll_timeout_atomic(&cdns->otg_regs->state, val,
 200                                           !(val & OTGSTATE_DEV_STATE_MASK),
 201                                           1, 2000000);
 202         }
 203 
 204         return 0;
 205 }
 206 
 207 /**
 208  * cdns3_init_otg_mode - initialize drd controller
 209  * @cdns: Pointer to controller context structure
 210  *
 211  * Returns 0 on success otherwise negative errno
 212  */
 213 static int cdns3_init_otg_mode(struct cdns3 *cdns)
 214 {
 215         int ret = 0;
 216 
 217         cdns3_otg_disable_irq(cdns);
 218         /* clear all interrupts */
 219         writel(~0, &cdns->otg_regs->ivect);
 220 
 221         ret = cdns3_set_mode(cdns, USB_DR_MODE_OTG);
 222         if (ret)
 223                 return ret;
 224 
 225         cdns3_otg_enable_irq(cdns);
 226         return ret;
 227 }
 228 
 229 /**
 230  * cdns3_drd_update_mode - initialize mode of operation
 231  * @cdns: Pointer to controller context structure
 232  *
 233  * Returns 0 on success otherwise negative errno
 234  */
 235 int cdns3_drd_update_mode(struct cdns3 *cdns)
 236 {
 237         int ret = 0;
 238 
 239         switch (cdns->dr_mode) {
 240         case USB_DR_MODE_PERIPHERAL:
 241                 ret = cdns3_set_mode(cdns, USB_DR_MODE_PERIPHERAL);
 242                 break;
 243         case USB_DR_MODE_HOST:
 244                 ret = cdns3_set_mode(cdns, USB_DR_MODE_HOST);
 245                 break;
 246         case USB_DR_MODE_OTG:
 247                 ret = cdns3_init_otg_mode(cdns);
 248                 break;
 249         default:
 250                 dev_err(cdns->dev, "Unsupported mode of operation %d\n",
 251                         cdns->dr_mode);
 252                 return -EINVAL;
 253         }
 254 
 255         return ret;
 256 }
 257 
 258 static irqreturn_t cdns3_drd_thread_irq(int irq, void *data)
 259 {
 260         struct cdns3 *cdns = data;
 261 
 262         cdns3_hw_role_switch(cdns);
 263 
 264         return IRQ_HANDLED;
 265 }
 266 
 267 /**
 268  * cdns3_drd_irq - interrupt handler for OTG events
 269  *
 270  * @irq: irq number for cdns3 core device
 271  * @data: structure of cdns3
 272  *
 273  * Returns IRQ_HANDLED or IRQ_NONE
 274  */
 275 static irqreturn_t cdns3_drd_irq(int irq, void *data)
 276 {
 277         irqreturn_t ret = IRQ_NONE;
 278         struct cdns3 *cdns = data;
 279         u32 reg;
 280 
 281         if (cdns->dr_mode != USB_DR_MODE_OTG)
 282                 return ret;
 283 
 284         reg = readl(&cdns->otg_regs->ivect);
 285 
 286         if (!reg)
 287                 return ret;
 288 
 289         if (reg & OTGIEN_ID_CHANGE_INT) {
 290                 dev_dbg(cdns->dev, "OTG IRQ: new ID: %d\n",
 291                         cdns3_get_id(cdns));
 292 
 293                 ret = IRQ_WAKE_THREAD;
 294         }
 295 
 296         if (reg & (OTGIEN_VBUSVALID_RISE_INT | OTGIEN_VBUSVALID_FALL_INT)) {
 297                 dev_dbg(cdns->dev, "OTG IRQ: new VBUS: %d\n",
 298                         cdns3_get_vbus(cdns));
 299 
 300                 ret = IRQ_WAKE_THREAD;
 301         }
 302 
 303         writel(~0, &cdns->otg_regs->ivect);
 304         return ret;
 305 }
 306 
 307 int cdns3_drd_init(struct cdns3 *cdns)
 308 {
 309         void __iomem *regs;
 310         int ret = 0;
 311         u32 state;
 312 
 313         regs = devm_ioremap_resource(cdns->dev, &cdns->otg_res);
 314         if (IS_ERR(regs))
 315                 return PTR_ERR(regs);
 316 
 317         /* Detection of DRD version. Controller has been released
 318          * in two versions. Both are similar, but they have same changes
 319          * in register maps.
 320          * The first register in old version is command register and it's read
 321          * only, so driver should read 0 from it. On the other hand, in v1
 322          * the first register contains device ID number which is not set to 0.
 323          * Driver uses this fact to detect the proper version of
 324          * controller.
 325          */
 326         cdns->otg_v0_regs = regs;
 327         if (!readl(&cdns->otg_v0_regs->cmd)) {
 328                 cdns->version  = CDNS3_CONTROLLER_V0;
 329                 cdns->otg_v1_regs = NULL;
 330                 cdns->otg_regs = regs;
 331                 writel(1, &cdns->otg_v0_regs->simulate);
 332                 dev_info(cdns->dev, "DRD version v0 (%08x)\n",
 333                          readl(&cdns->otg_v0_regs->version));
 334         } else {
 335                 cdns->otg_v0_regs = NULL;
 336                 cdns->otg_v1_regs = regs;
 337                 cdns->otg_regs = (void *)&cdns->otg_v1_regs->cmd;
 338                 cdns->version  = CDNS3_CONTROLLER_V1;
 339                 writel(1, &cdns->otg_v1_regs->simulate);
 340                 dev_info(cdns->dev, "DRD version v1 (ID: %08x, rev: %08x)\n",
 341                          readl(&cdns->otg_v1_regs->did),
 342                          readl(&cdns->otg_v1_regs->rid));
 343         }
 344 
 345         state = OTGSTS_STRAP(readl(&cdns->otg_regs->sts));
 346 
 347         /* Update dr_mode according to STRAP configuration. */
 348         cdns->dr_mode = USB_DR_MODE_OTG;
 349         if (state == OTGSTS_STRAP_HOST) {
 350                 dev_dbg(cdns->dev, "Controller strapped to HOST\n");
 351                 cdns->dr_mode = USB_DR_MODE_HOST;
 352         } else if (state == OTGSTS_STRAP_GADGET) {
 353                 dev_dbg(cdns->dev, "Controller strapped to PERIPHERAL\n");
 354                 cdns->dr_mode = USB_DR_MODE_PERIPHERAL;
 355         }
 356 
 357         ret = devm_request_threaded_irq(cdns->dev, cdns->otg_irq,
 358                                         cdns3_drd_irq,
 359                                         cdns3_drd_thread_irq,
 360                                         IRQF_SHARED,
 361                                         dev_name(cdns->dev), cdns);
 362 
 363         if (ret) {
 364                 dev_err(cdns->dev, "couldn't get otg_irq\n");
 365                 return ret;
 366         }
 367 
 368         state = readl(&cdns->otg_regs->sts);
 369         if (OTGSTS_OTG_NRDY(state) != 0) {
 370                 dev_err(cdns->dev, "Cadence USB3 OTG device not ready\n");
 371                 return -ENODEV;
 372         }
 373 
 374         return ret;
 375 }
 376 
 377 int cdns3_drd_exit(struct cdns3 *cdns)
 378 {
 379         cdns3_otg_disable_irq(cdns);
 380         return 0;
 381 }

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