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

xhci-rcar.c (6677B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * xHCI host controller driver for R-Car SoCs
      4 *
      5 * Copyright (C) 2014 Renesas Electronics Corporation
      6 */
      7
      8#include <linux/firmware.h>
      9#include <linux/iopoll.h>
     10#include <linux/module.h>
     11#include <linux/platform_device.h>
     12#include <linux/of.h>
     13#include <linux/usb/phy.h>
     14#include <linux/sys_soc.h>
     15
     16#include "xhci.h"
     17#include "xhci-plat.h"
     18#include "xhci-rcar.h"
     19
     20/*
     21* - The V3 firmware is for almost all R-Car Gen3 (except r8a7795 ES1.x)
     22* - The V2 firmware is for r8a7795 ES1.x.
     23* - The V2 firmware is possible to use on R-Car Gen2. However, the V2 causes
     24*   performance degradation. So, this driver continues to use the V1 if R-Car
     25*   Gen2.
     26* - The V1 firmware is impossible to use on R-Car Gen3.
     27*/
     28MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V1);
     29MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V2);
     30MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V3);
     31
     32/*** Register Offset ***/
     33#define RCAR_USB3_AXH_STA	0x104	/* AXI Host Control Status */
     34#define RCAR_USB3_INT_ENA	0x224	/* Interrupt Enable */
     35#define RCAR_USB3_DL_CTRL	0x250	/* FW Download Control & Status */
     36#define RCAR_USB3_FW_DATA0	0x258	/* FW Data0 */
     37
     38#define RCAR_USB3_LCLK		0xa44	/* LCLK Select */
     39#define RCAR_USB3_CONF1		0xa48	/* USB3.0 Configuration1 */
     40#define RCAR_USB3_CONF2		0xa5c	/* USB3.0 Configuration2 */
     41#define RCAR_USB3_CONF3		0xaa8	/* USB3.0 Configuration3 */
     42#define RCAR_USB3_RX_POL	0xab0	/* USB3.0 RX Polarity */
     43#define RCAR_USB3_TX_POL	0xab8	/* USB3.0 TX Polarity */
     44
     45/*** Register Settings ***/
     46/* AXI Host Control Status */
     47#define RCAR_USB3_AXH_STA_B3_PLL_ACTIVE		0x00010000
     48#define RCAR_USB3_AXH_STA_B2_PLL_ACTIVE		0x00000001
     49#define RCAR_USB3_AXH_STA_PLL_ACTIVE_MASK (RCAR_USB3_AXH_STA_B3_PLL_ACTIVE | \
     50					   RCAR_USB3_AXH_STA_B2_PLL_ACTIVE)
     51
     52/* Interrupt Enable */
     53#define RCAR_USB3_INT_XHC_ENA	0x00000001
     54#define RCAR_USB3_INT_PME_ENA	0x00000002
     55#define RCAR_USB3_INT_HSE_ENA	0x00000004
     56#define RCAR_USB3_INT_ENA_VAL	(RCAR_USB3_INT_XHC_ENA | \
     57				RCAR_USB3_INT_PME_ENA | RCAR_USB3_INT_HSE_ENA)
     58
     59/* FW Download Control & Status */
     60#define RCAR_USB3_DL_CTRL_ENABLE	0x00000001
     61#define RCAR_USB3_DL_CTRL_FW_SUCCESS	0x00000010
     62#define RCAR_USB3_DL_CTRL_FW_SET_DATA0	0x00000100
     63
     64/* LCLK Select */
     65#define RCAR_USB3_LCLK_ENA_VAL	0x01030001
     66
     67/* USB3.0 Configuration */
     68#define RCAR_USB3_CONF1_VAL	0x00030204
     69#define RCAR_USB3_CONF2_VAL	0x00030300
     70#define RCAR_USB3_CONF3_VAL	0x13802007
     71
     72/* USB3.0 Polarity */
     73#define RCAR_USB3_RX_POL_VAL	BIT(21)
     74#define RCAR_USB3_TX_POL_VAL	BIT(4)
     75
     76/* For soc_device_attribute */
     77#define RCAR_XHCI_FIRMWARE_V2   BIT(0) /* FIRMWARE V2 */
     78#define RCAR_XHCI_FIRMWARE_V3   BIT(1) /* FIRMWARE V3 */
     79
     80static const struct soc_device_attribute rcar_quirks_match[]  = {
     81	{
     82		.soc_id = "r8a7795", .revision = "ES1.*",
     83		.data = (void *)RCAR_XHCI_FIRMWARE_V2,
     84	},
     85	{ /* sentinel */ }
     86};
     87
     88static void xhci_rcar_start_gen2(struct usb_hcd *hcd)
     89{
     90	/* LCLK Select */
     91	writel(RCAR_USB3_LCLK_ENA_VAL, hcd->regs + RCAR_USB3_LCLK);
     92	/* USB3.0 Configuration */
     93	writel(RCAR_USB3_CONF1_VAL, hcd->regs + RCAR_USB3_CONF1);
     94	writel(RCAR_USB3_CONF2_VAL, hcd->regs + RCAR_USB3_CONF2);
     95	writel(RCAR_USB3_CONF3_VAL, hcd->regs + RCAR_USB3_CONF3);
     96	/* USB3.0 Polarity */
     97	writel(RCAR_USB3_RX_POL_VAL, hcd->regs + RCAR_USB3_RX_POL);
     98	writel(RCAR_USB3_TX_POL_VAL, hcd->regs + RCAR_USB3_TX_POL);
     99}
    100
    101static int xhci_rcar_is_gen2(struct device *dev)
    102{
    103	struct device_node *node = dev->of_node;
    104
    105	return of_device_is_compatible(node, "renesas,xhci-r8a7790") ||
    106		of_device_is_compatible(node, "renesas,xhci-r8a7791") ||
    107		of_device_is_compatible(node, "renesas,xhci-r8a7793") ||
    108		of_device_is_compatible(node, "renesas,rcar-gen2-xhci");
    109}
    110
    111void xhci_rcar_start(struct usb_hcd *hcd)
    112{
    113	u32 temp;
    114
    115	if (hcd->regs != NULL) {
    116		/* Interrupt Enable */
    117		temp = readl(hcd->regs + RCAR_USB3_INT_ENA);
    118		temp |= RCAR_USB3_INT_ENA_VAL;
    119		writel(temp, hcd->regs + RCAR_USB3_INT_ENA);
    120		if (xhci_rcar_is_gen2(hcd->self.controller))
    121			xhci_rcar_start_gen2(hcd);
    122	}
    123}
    124
    125static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
    126{
    127	struct device *dev = hcd->self.controller;
    128	void __iomem *regs = hcd->regs;
    129	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
    130	const struct firmware *fw;
    131	int retval, index, j;
    132	u32 data, val, temp;
    133	u32 quirks = 0;
    134	const struct soc_device_attribute *attr;
    135	const char *firmware_name;
    136
    137	/*
    138	 * According to the datasheet, "Upon the completion of FW Download,
    139	 * there is no need to write or reload FW".
    140	 */
    141	if (readl(regs + RCAR_USB3_DL_CTRL) & RCAR_USB3_DL_CTRL_FW_SUCCESS)
    142		return 0;
    143
    144	attr = soc_device_match(rcar_quirks_match);
    145	if (attr)
    146		quirks = (uintptr_t)attr->data;
    147
    148	if (quirks & RCAR_XHCI_FIRMWARE_V2)
    149		firmware_name = XHCI_RCAR_FIRMWARE_NAME_V2;
    150	else if (quirks & RCAR_XHCI_FIRMWARE_V3)
    151		firmware_name = XHCI_RCAR_FIRMWARE_NAME_V3;
    152	else
    153		firmware_name = priv->firmware_name;
    154
    155	/* request R-Car USB3.0 firmware */
    156	retval = request_firmware(&fw, firmware_name, dev);
    157	if (retval)
    158		return retval;
    159
    160	/* download R-Car USB3.0 firmware */
    161	temp = readl(regs + RCAR_USB3_DL_CTRL);
    162	temp |= RCAR_USB3_DL_CTRL_ENABLE;
    163	writel(temp, regs + RCAR_USB3_DL_CTRL);
    164
    165	for (index = 0; index < fw->size; index += 4) {
    166		/* to avoid reading beyond the end of the buffer */
    167		for (data = 0, j = 3; j >= 0; j--) {
    168			if ((j + index) < fw->size)
    169				data |= fw->data[index + j] << (8 * j);
    170		}
    171		writel(data, regs + RCAR_USB3_FW_DATA0);
    172		temp = readl(regs + RCAR_USB3_DL_CTRL);
    173		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;
    174		writel(temp, regs + RCAR_USB3_DL_CTRL);
    175
    176		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,
    177				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),
    178				1, 10000);
    179		if (retval < 0)
    180			break;
    181	}
    182
    183	temp = readl(regs + RCAR_USB3_DL_CTRL);
    184	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;
    185	writel(temp, regs + RCAR_USB3_DL_CTRL);
    186
    187	retval = readl_poll_timeout_atomic((regs + RCAR_USB3_DL_CTRL),
    188			val, val & RCAR_USB3_DL_CTRL_FW_SUCCESS, 1, 10000);
    189
    190	release_firmware(fw);
    191
    192	return retval;
    193}
    194
    195static bool xhci_rcar_wait_for_pll_active(struct usb_hcd *hcd)
    196{
    197	int retval;
    198	u32 val, mask = RCAR_USB3_AXH_STA_PLL_ACTIVE_MASK;
    199
    200	retval = readl_poll_timeout_atomic(hcd->regs + RCAR_USB3_AXH_STA,
    201			val, (val & mask) == mask, 1, 1000);
    202	return !retval;
    203}
    204
    205/* This function needs to initialize a "phy" of usb before */
    206int xhci_rcar_init_quirk(struct usb_hcd *hcd)
    207{
    208	/* If hcd->regs is NULL, we don't just call the following function */
    209	if (!hcd->regs)
    210		return 0;
    211
    212	if (!xhci_rcar_wait_for_pll_active(hcd))
    213		return -ETIMEDOUT;
    214
    215	return xhci_rcar_download_firmware(hcd);
    216}
    217
    218int xhci_rcar_resume_quirk(struct usb_hcd *hcd)
    219{
    220	int ret;
    221
    222	ret = xhci_rcar_download_firmware(hcd);
    223	if (!ret)
    224		xhci_rcar_start(hcd);
    225
    226	return ret;
    227}