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