File Index
Files and directories
Sign in
FILE

xhci-rcar.c

File preview with syntax highlighting.

linux-6.19.14/drivers/usb/host/xhci-rcar.c C
  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/reset.h>
 15
 16#include "xhci.h"
 17#include "xhci-plat.h"
 18#include "xhci-rcar-regs.h"
 19#include "xhci-rzg3e-regs.h"
 20#include "xhci-rzv2m.h"
 21
 22#define XHCI_RCAR_FIRMWARE_NAME_V1	"r8a779x_usb3_v1.dlmem"
 23#define XHCI_RCAR_FIRMWARE_NAME_V3	"r8a779x_usb3_v3.dlmem"
 24
 25/*
 26* - The V3 firmware is for all R-Car Gen3
 27* - The V2 firmware is possible to use on R-Car Gen2. However, the V2 causes
 28*   performance degradation. So, this driver continues to use the V1 if R-Car
 29*   Gen2.
 30* - The V1 firmware is impossible to use on R-Car Gen3.
 31*/
 32MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V1);
 33MODULE_FIRMWARE(XHCI_RCAR_FIRMWARE_NAME_V3);
 34
 35static void xhci_rcar_start_gen2(struct usb_hcd *hcd)
 36{
 37	/* LCLK Select */
 38	writel(RCAR_USB3_LCLK_ENA_VAL, hcd->regs + RCAR_USB3_LCLK);
 39	/* USB3.0 Configuration */
 40	writel(RCAR_USB3_CONF1_VAL, hcd->regs + RCAR_USB3_CONF1);
 41	writel(RCAR_USB3_CONF2_VAL, hcd->regs + RCAR_USB3_CONF2);
 42	writel(RCAR_USB3_CONF3_VAL, hcd->regs + RCAR_USB3_CONF3);
 43	/* USB3.0 Polarity */
 44	writel(RCAR_USB3_RX_POL_VAL, hcd->regs + RCAR_USB3_RX_POL);
 45	writel(RCAR_USB3_TX_POL_VAL, hcd->regs + RCAR_USB3_TX_POL);
 46}
 47
 48static int xhci_rcar_is_gen2(struct device *dev)
 49{
 50	struct device_node *node = dev->of_node;
 51
 52	return of_device_is_compatible(node, "renesas,xhci-r8a7790") ||
 53		of_device_is_compatible(node, "renesas,xhci-r8a7791") ||
 54		of_device_is_compatible(node, "renesas,xhci-r8a7793") ||
 55		of_device_is_compatible(node, "renesas,rcar-gen2-xhci");
 56}
 57
 58static void xhci_rcar_start(struct usb_hcd *hcd)
 59{
 60	u32 temp;
 61
 62	if (hcd->regs != NULL) {
 63		/* Interrupt Enable */
 64		temp = readl(hcd->regs + RCAR_USB3_INT_ENA);
 65		temp |= RCAR_USB3_INT_ENA_VAL;
 66		writel(temp, hcd->regs + RCAR_USB3_INT_ENA);
 67		if (xhci_rcar_is_gen2(hcd->self.controller))
 68			xhci_rcar_start_gen2(hcd);
 69	}
 70}
 71
 72static void xhci_rzg3e_start(struct usb_hcd *hcd)
 73{
 74	u32 int_en;
 75
 76	if (hcd->regs) {
 77		/* Update the controller initial setting */
 78		writel(0x03130200, hcd->regs + RZG3E_USB3_HOST_U3P0PIPESC(0));
 79		writel(0x00160200, hcd->regs + RZG3E_USB3_HOST_U3P0PIPESC(1));
 80		writel(0x03150000, hcd->regs + RZG3E_USB3_HOST_U3P0PIPESC(2));
 81		writel(0x03130200, hcd->regs + RZG3E_USB3_HOST_U3P0PIPESC(3));
 82		writel(0x00180000, hcd->regs + RZG3E_USB3_HOST_U3P0PIPESC(4));
 83
 84		/* Interrupt Enable */
 85		int_en = readl(hcd->regs + RZG3E_USB3_HOST_INTEN);
 86		int_en |= RZG3E_USB3_HOST_INTEN_ENA;
 87		writel(int_en, hcd->regs + RZG3E_USB3_HOST_INTEN);
 88	}
 89}
 90
 91static int xhci_rzg3e_resume(struct usb_hcd *hcd)
 92{
 93	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 94
 95	return reset_control_deassert(xhci->reset);
 96}
 97
 98static int xhci_rzg3e_post_resume(struct usb_hcd *hcd)
 99{
100	xhci_rzg3e_start(hcd);
101
102	return 0;
103}
104
105static int xhci_rzg3e_suspend(struct usb_hcd *hcd)
106{
107	struct xhci_hcd *xhci = hcd_to_xhci(hcd);
108
109	reset_control_assert(xhci->reset);
110
111	return 0;
112}
113
114static int xhci_rcar_download_firmware(struct usb_hcd *hcd)
115{
116	struct device *dev = hcd->self.controller;
117	void __iomem *regs = hcd->regs;
118	struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
119	const struct firmware *fw;
120	int retval, index, j;
121	u32 data, val, temp;
122
123	/*
124	 * According to the datasheet, "Upon the completion of FW Download,
125	 * there is no need to write or reload FW".
126	 */
127	if (readl(regs + RCAR_USB3_DL_CTRL) & RCAR_USB3_DL_CTRL_FW_SUCCESS)
128		return 0;
129
130	/* request R-Car USB3.0 firmware */
131	retval = request_firmware(&fw, priv->firmware_name, dev);
132	if (retval)
133		return retval;
134
135	/* download R-Car USB3.0 firmware */
136	temp = readl(regs + RCAR_USB3_DL_CTRL);
137	temp |= RCAR_USB3_DL_CTRL_ENABLE;
138	writel(temp, regs + RCAR_USB3_DL_CTRL);
139
140	for (index = 0; index < fw->size; index += 4) {
141		/* to avoid reading beyond the end of the buffer */
142		for (data = 0, j = 3; j >= 0; j--) {
143			if ((j + index) < fw->size)
144				data |= fw->data[index + j] << (8 * j);
145		}
146		writel(data, regs + RCAR_USB3_FW_DATA0);
147		temp = readl(regs + RCAR_USB3_DL_CTRL);
148		temp |= RCAR_USB3_DL_CTRL_FW_SET_DATA0;
149		writel(temp, regs + RCAR_USB3_DL_CTRL);
150
151		retval = readl_poll_timeout_atomic(regs + RCAR_USB3_DL_CTRL,
152				val, !(val & RCAR_USB3_DL_CTRL_FW_SET_DATA0),
153				1, 10000);
154		if (retval < 0)
155			break;
156	}
157
158	temp = readl(regs + RCAR_USB3_DL_CTRL);
159	temp &= ~RCAR_USB3_DL_CTRL_ENABLE;
160	writel(temp, regs + RCAR_USB3_DL_CTRL);
161
162	retval = readl_poll_timeout_atomic((regs + RCAR_USB3_DL_CTRL),
163			val, val & RCAR_USB3_DL_CTRL_FW_SUCCESS, 1, 10000);
164
165	release_firmware(fw);
166
167	return retval;
168}
169
170static bool xhci_rcar_wait_for_pll_active(struct usb_hcd *hcd)
171{
172	int retval;
173	u32 val, mask = RCAR_USB3_AXH_STA_PLL_ACTIVE_MASK;
174
175	retval = readl_poll_timeout_atomic(hcd->regs + RCAR_USB3_AXH_STA,
176			val, (val & mask) == mask, 1, 1000);
177	return !retval;
178}
179
180/* This function needs to initialize a "phy" of usb before */
181static int xhci_rcar_init_quirk(struct usb_hcd *hcd)
182{
183	/* If hcd->regs is NULL, we don't just call the following function */
184	if (!hcd->regs)
185		return 0;
186
187	if (!xhci_rcar_wait_for_pll_active(hcd))
188		return -ETIMEDOUT;
189
190	return xhci_rcar_download_firmware(hcd);
191}
192
193static int xhci_rcar_resume_quirk(struct usb_hcd *hcd)
194{
195	int ret;
196
197	ret = xhci_rcar_download_firmware(hcd);
198	if (!ret)
199		xhci_rcar_start(hcd);
200
201	return ret;
202}
203
204/*
205 * On R-Car Gen2 and Gen3, the AC64 bit (bit 0) of HCCPARAMS1 is set
206 * to 1. However, these SoCs don't support 64-bit address memory
207 * pointers. So, this driver clears the AC64 bit of xhci->hcc_params
208 * to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32)) in
209 * xhci_gen_setup() by using the XHCI_NO_64BIT_SUPPORT quirk.
210 *
211 * And, since the firmware/internal CPU control the USBSTS.STS_HALT
212 * and the process speed is down when the roothub port enters U3,
213 * long delay for the handshake of STS_HALT is neeed in xhci_suspend()
214 * by using the XHCI_SLOW_SUSPEND quirk.
215 */
216#define SET_XHCI_PLAT_PRIV_FOR_RCAR(firmware)				\
217	.firmware_name = firmware,					\
218	.quirks = XHCI_NO_64BIT_SUPPORT |  XHCI_SLOW_SUSPEND,		\
219	.init_quirk = xhci_rcar_init_quirk,				\
220	.plat_start = xhci_rcar_start,					\
221	.resume_quirk = xhci_rcar_resume_quirk,
222
223static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen2 = {
224	SET_XHCI_PLAT_PRIV_FOR_RCAR(XHCI_RCAR_FIRMWARE_NAME_V1)
225};
226
227static const struct xhci_plat_priv xhci_plat_renesas_rcar_gen3 = {
228	SET_XHCI_PLAT_PRIV_FOR_RCAR(XHCI_RCAR_FIRMWARE_NAME_V3)
229};
230
231static const struct xhci_plat_priv xhci_plat_renesas_rzv2m = {
232	.quirks = XHCI_NO_64BIT_SUPPORT | XHCI_SLOW_SUSPEND,
233	.init_quirk = xhci_rzv2m_init_quirk,
234	.plat_start = xhci_rzv2m_start,
235};
236
237static const struct xhci_plat_priv xhci_plat_renesas_rzg3e = {
238	.quirks = XHCI_NO_64BIT_SUPPORT | XHCI_RESET_ON_RESUME | XHCI_SUSPEND_RESUME_CLKS,
239	.plat_start = xhci_rzg3e_start,
240	.suspend_quirk = xhci_rzg3e_suspend,
241	.resume_quirk = xhci_rzg3e_resume,
242	.post_resume_quirk = xhci_rzg3e_post_resume,
243};
244
245static const struct of_device_id usb_xhci_of_match[] = {
246	{
247		.compatible = "renesas,xhci-r8a7790",
248		.data = &xhci_plat_renesas_rcar_gen2,
249	}, {
250		.compatible = "renesas,xhci-r8a7791",
251		.data = &xhci_plat_renesas_rcar_gen2,
252	}, {
253		.compatible = "renesas,xhci-r8a7793",
254		.data = &xhci_plat_renesas_rcar_gen2,
255	}, {
256		.compatible = "renesas,xhci-r8a7795",
257		.data = &xhci_plat_renesas_rcar_gen3,
258	}, {
259		.compatible = "renesas,xhci-r8a7796",
260		.data = &xhci_plat_renesas_rcar_gen3,
261	}, {
262		.compatible = "renesas,r9a09g047-xhci",
263		.data = &xhci_plat_renesas_rzg3e,
264	}, {
265		.compatible = "renesas,rcar-gen2-xhci",
266		.data = &xhci_plat_renesas_rcar_gen2,
267	}, {
268		.compatible = "renesas,rcar-gen3-xhci",
269		.data = &xhci_plat_renesas_rcar_gen3,
270	}, {
271		.compatible = "renesas,rzv2m-xhci",
272		.data = &xhci_plat_renesas_rzv2m,
273	},
274	{ },
275};
276MODULE_DEVICE_TABLE(of, usb_xhci_of_match);
277
278static int xhci_renesas_probe(struct platform_device *pdev)
279{
280	const struct xhci_plat_priv *priv_match;
281
282	priv_match = of_device_get_match_data(&pdev->dev);
283
284	return xhci_plat_probe(pdev, NULL, priv_match);
285}
286
287static struct platform_driver usb_xhci_renesas_driver = {
288	.probe = xhci_renesas_probe,
289	.remove = xhci_plat_remove,
290	.shutdown = usb_hcd_platform_shutdown,
291	.driver = {
292		.name = "xhci-renesas-hcd",
293		.pm = &xhci_plat_pm_ops,
294		.of_match_table = usb_xhci_of_match,
295	},
296};
297module_platform_driver(usb_xhci_renesas_driver);
298
299MODULE_DESCRIPTION("xHCI Platform Host Controller Driver for Renesas R-Car and RZ");
300MODULE_LICENSE("GPL");
~/ Read-only file preview.