cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drd.c (11868B)


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