Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
^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) }