xref: /OK3568_Linux_fs/u-boot/drivers/usb/host/xhci-rcar.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Renesas RCar USB HOST xHCI Controller
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <common.h>
10*4882a593Smuzhiyun #include <clk.h>
11*4882a593Smuzhiyun #include <dm.h>
12*4882a593Smuzhiyun #include <fdtdec.h>
13*4882a593Smuzhiyun #include <usb.h>
14*4882a593Smuzhiyun #include <wait_bit.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <usb/xhci.h>
17*4882a593Smuzhiyun #include "xhci-rcar-r8a779x_usb3_v3.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /* Register Offset */
20*4882a593Smuzhiyun #define RCAR_USB3_DL_CTRL	0x250	/* FW Download Control & Status */
21*4882a593Smuzhiyun #define RCAR_USB3_FW_DATA0	0x258	/* FW Data0 */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun /* Register Settings */
24*4882a593Smuzhiyun /* FW Download Control & Status */
25*4882a593Smuzhiyun #define RCAR_USB3_DL_CTRL_ENABLE	BIT(0)
26*4882a593Smuzhiyun #define RCAR_USB3_DL_CTRL_FW_SUCCESS	BIT(4)
27*4882a593Smuzhiyun #define RCAR_USB3_DL_CTRL_FW_SET_DATA0	BIT(8)
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun struct rcar_xhci_platdata {
30*4882a593Smuzhiyun 	fdt_addr_t	hcd_base;
31*4882a593Smuzhiyun 	struct clk	clk;
32*4882a593Smuzhiyun };
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun /**
35*4882a593Smuzhiyun  * Contains pointers to register base addresses
36*4882a593Smuzhiyun  * for the usb controller.
37*4882a593Smuzhiyun  */
38*4882a593Smuzhiyun struct rcar_xhci {
39*4882a593Smuzhiyun 	struct xhci_ctrl ctrl;	/* Needs to come first in this struct! */
40*4882a593Smuzhiyun 	struct usb_platdata usb_plat;
41*4882a593Smuzhiyun 	struct xhci_hccr *hcd;
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
xhci_rcar_download_fw(struct rcar_xhci * ctx,const u32 * fw_data,const size_t fw_array_size)44*4882a593Smuzhiyun static int xhci_rcar_download_fw(struct rcar_xhci *ctx, const u32 *fw_data,
45*4882a593Smuzhiyun 				 const size_t fw_array_size)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	void __iomem *regs = (void __iomem *)ctx->hcd;
48*4882a593Smuzhiyun 	int i, ret;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	/* Download R-Car USB3.0 firmware */
51*4882a593Smuzhiyun 	setbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_ENABLE);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	for (i = 0; i < fw_array_size; i++) {
54*4882a593Smuzhiyun 		writel(fw_data[i], regs + RCAR_USB3_FW_DATA0);
55*4882a593Smuzhiyun 		setbits_le32(regs + RCAR_USB3_DL_CTRL,
56*4882a593Smuzhiyun 			     RCAR_USB3_DL_CTRL_FW_SET_DATA0);
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun <<<<<<< HEAD
59*4882a593Smuzhiyun 		ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
60*4882a593Smuzhiyun 					RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
61*4882a593Smuzhiyun 					10, false);
62*4882a593Smuzhiyun =======
63*4882a593Smuzhiyun 		ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
64*4882a593Smuzhiyun 				   RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
65*4882a593Smuzhiyun 				   10, false);
66*4882a593Smuzhiyun >>>>>>> e1cc60c... usb: xhci: Add Renesas R-Car xHCI driver
67*4882a593Smuzhiyun 		if (ret)
68*4882a593Smuzhiyun 			break;
69*4882a593Smuzhiyun 	}
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	clrbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_ENABLE);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun <<<<<<< HEAD
74*4882a593Smuzhiyun 	ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL,
75*4882a593Smuzhiyun 				RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
76*4882a593Smuzhiyun 				10, false);
77*4882a593Smuzhiyun =======
78*4882a593Smuzhiyun 	ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
79*4882a593Smuzhiyun 			   RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
80*4882a593Smuzhiyun 			   10, false);
81*4882a593Smuzhiyun >>>>>>> e1cc60c... usb: xhci: Add Renesas R-Car xHCI driver
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	return ret;
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
xhci_rcar_probe(struct udevice * dev)86*4882a593Smuzhiyun static int xhci_rcar_probe(struct udevice *dev)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun 	struct rcar_xhci_platdata *plat = dev_get_platdata(dev);
89*4882a593Smuzhiyun 	struct rcar_xhci *ctx = dev_get_priv(dev);
90*4882a593Smuzhiyun 	struct xhci_hcor *hcor;
91*4882a593Smuzhiyun 	int len, ret;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	ret = clk_get_by_index(dev, 0, &plat->clk);
94*4882a593Smuzhiyun 	if (ret < 0) {
95*4882a593Smuzhiyun 		dev_err(dev, "Failed to get USB3 clock\n");
96*4882a593Smuzhiyun 		return ret;
97*4882a593Smuzhiyun 	}
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	ret = clk_enable(&plat->clk);
100*4882a593Smuzhiyun 	if (ret) {
101*4882a593Smuzhiyun 		dev_err(dev, "Failed to enable USB3 clock\n");
102*4882a593Smuzhiyun 		goto err_clk;
103*4882a593Smuzhiyun 	}
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	ctx->hcd = (struct xhci_hccr *)plat->hcd_base;
106*4882a593Smuzhiyun 	len = HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase));
107*4882a593Smuzhiyun 	hcor = (struct xhci_hcor *)((uintptr_t)ctx->hcd + len);
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	ret = xhci_rcar_download_fw(ctx, firmware_r8a779x_usb3_v3,
110*4882a593Smuzhiyun 				    ARRAY_SIZE(firmware_r8a779x_usb3_v3));
111*4882a593Smuzhiyun 	if (ret) {
112*4882a593Smuzhiyun 		dev_err(dev, "Failed to download firmware\n");
113*4882a593Smuzhiyun 		goto err_fw;
114*4882a593Smuzhiyun 	}
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	ret = xhci_register(dev, ctx->hcd, hcor);
117*4882a593Smuzhiyun 	if (ret) {
118*4882a593Smuzhiyun 		dev_err(dev, "Failed to register xHCI\n");
119*4882a593Smuzhiyun 		goto err_fw;
120*4882a593Smuzhiyun 	}
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	return 0;
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun err_fw:
125*4882a593Smuzhiyun 	clk_disable(&plat->clk);
126*4882a593Smuzhiyun err_clk:
127*4882a593Smuzhiyun 	clk_free(&plat->clk);
128*4882a593Smuzhiyun 	return ret;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
xhci_rcar_deregister(struct udevice * dev)131*4882a593Smuzhiyun static int xhci_rcar_deregister(struct udevice *dev)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun 	int ret;
134*4882a593Smuzhiyun 	struct rcar_xhci_platdata *plat = dev_get_platdata(dev);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	ret = xhci_deregister(dev);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	clk_disable(&plat->clk);
139*4882a593Smuzhiyun 	clk_free(&plat->clk);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	return ret;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
xhci_rcar_ofdata_to_platdata(struct udevice * dev)144*4882a593Smuzhiyun static int xhci_rcar_ofdata_to_platdata(struct udevice *dev)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	struct rcar_xhci_platdata *plat = dev_get_platdata(dev);
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	plat->hcd_base = devfdt_get_addr(dev);
149*4882a593Smuzhiyun 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
150*4882a593Smuzhiyun 		debug("Can't get the XHCI register base address\n");
151*4882a593Smuzhiyun 		return -ENXIO;
152*4882a593Smuzhiyun 	}
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	return 0;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun static const struct udevice_id xhci_rcar_ids[] = {
158*4882a593Smuzhiyun 	{ .compatible = "renesas,xhci-r8a7795" },
159*4882a593Smuzhiyun 	{ .compatible = "renesas,xhci-r8a7796" },
160*4882a593Smuzhiyun 	{ .compatible = "renesas,xhci-r8a77965" },
161*4882a593Smuzhiyun 	{ }
162*4882a593Smuzhiyun };
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun U_BOOT_DRIVER(usb_xhci) = {
165*4882a593Smuzhiyun 	.name		= "xhci_rcar",
166*4882a593Smuzhiyun 	.id		= UCLASS_USB,
167*4882a593Smuzhiyun 	.probe		= xhci_rcar_probe,
168*4882a593Smuzhiyun 	.remove		= xhci_rcar_deregister,
169*4882a593Smuzhiyun 	.ops		= &xhci_usb_ops,
170*4882a593Smuzhiyun 	.of_match	= xhci_rcar_ids,
171*4882a593Smuzhiyun 	.ofdata_to_platdata = xhci_rcar_ofdata_to_platdata,
172*4882a593Smuzhiyun 	.platdata_auto_alloc_size = sizeof(struct rcar_xhci_platdata),
173*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rcar_xhci),
174*4882a593Smuzhiyun 	.flags		= DM_FLAG_ALLOC_PRIV_DMA,
175*4882a593Smuzhiyun };
176