xref: /openbmc/u-boot/drivers/usb/host/ehci-exynos.c (revision 76b00aca)
1 /*
2  * SAMSUNG EXYNOS USB HOST EHCI Controller
3  *
4  * Copyright (C) 2012 Samsung Electronics Co.Ltd
5  *	Vivek Gautam <gautam.vivek@samsung.com>
6  *
7  * SPDX-License-Identifier:	GPL-2.0+
8  */
9 
10 #include <common.h>
11 #include <dm.h>
12 #include <fdtdec.h>
13 #include <libfdt.h>
14 #include <malloc.h>
15 #include <usb.h>
16 #include <asm/arch/cpu.h>
17 #include <asm/arch/ehci.h>
18 #include <asm/arch/system.h>
19 #include <asm/arch/power.h>
20 #include <asm/gpio.h>
21 #include <linux/errno.h>
22 #include <linux/compat.h>
23 #include "ehci.h"
24 
25 /* Declare global data pointer */
26 DECLARE_GLOBAL_DATA_PTR;
27 
28 struct exynos_ehci_platdata {
29 	struct usb_platdata usb_plat;
30 	fdt_addr_t hcd_base;
31 	fdt_addr_t phy_base;
32 	struct gpio_desc vbus_gpio;
33 };
34 
35 /**
36  * Contains pointers to register base addresses
37  * for the usb controller.
38  */
39 struct exynos_ehci {
40 	struct ehci_ctrl ctrl;
41 	struct exynos_usb_phy *usb;
42 	struct ehci_hccr *hcd;
43 };
44 
45 static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
46 {
47 	struct exynos_ehci_platdata *plat = dev_get_platdata(dev);
48 	const void *blob = gd->fdt_blob;
49 	unsigned int node;
50 	int depth;
51 
52 	/*
53 	 * Get the base address for XHCI controller from the device node
54 	 */
55 	plat->hcd_base = dev_get_addr(dev);
56 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
57 		debug("Can't get the XHCI register base address\n");
58 		return -ENXIO;
59 	}
60 
61 	depth = 0;
62 	node = fdtdec_next_compatible_subnode(blob, dev_of_offset(dev),
63 				COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth);
64 	if (node <= 0) {
65 		debug("XHCI: Can't get device node for usb3-phy controller\n");
66 		return -ENODEV;
67 	}
68 
69 	/*
70 	 * Get the base address for usbphy from the device node
71 	 */
72 	plat->phy_base = fdtdec_get_addr(blob, node, "reg");
73 	if (plat->phy_base == FDT_ADDR_T_NONE) {
74 		debug("Can't get the usbphy register address\n");
75 		return -ENXIO;
76 	}
77 
78 	/* Vbus gpio */
79 	gpio_request_by_name(dev, "samsung,vbus-gpio", 0,
80 			     &plat->vbus_gpio, GPIOD_IS_OUT);
81 
82 	return 0;
83 }
84 
85 static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
86 {
87 	u32 hsic_ctrl;
88 
89 	clrbits_le32(&usb->usbphyctrl0,
90 			HOST_CTRL0_FSEL_MASK |
91 			HOST_CTRL0_COMMONON_N |
92 			/* HOST Phy setting */
93 			HOST_CTRL0_PHYSWRST |
94 			HOST_CTRL0_PHYSWRSTALL |
95 			HOST_CTRL0_SIDDQ |
96 			HOST_CTRL0_FORCESUSPEND |
97 			HOST_CTRL0_FORCESLEEP);
98 
99 	setbits_le32(&usb->usbphyctrl0,
100 			/* Setting up the ref freq */
101 			(CLK_24MHZ << 16) |
102 			/* HOST Phy setting */
103 			HOST_CTRL0_LINKSWRST |
104 			HOST_CTRL0_UTMISWRST);
105 	udelay(10);
106 	clrbits_le32(&usb->usbphyctrl0,
107 			HOST_CTRL0_LINKSWRST |
108 			HOST_CTRL0_UTMISWRST);
109 
110 	/* HSIC Phy Setting */
111 	hsic_ctrl = (HSIC_CTRL_FORCESUSPEND |
112 			HSIC_CTRL_FORCESLEEP |
113 			HSIC_CTRL_SIDDQ);
114 
115 	clrbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
116 	clrbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
117 
118 	hsic_ctrl = (((HSIC_CTRL_REFCLKDIV_12 & HSIC_CTRL_REFCLKDIV_MASK)
119 				<< HSIC_CTRL_REFCLKDIV_SHIFT)
120 			| ((HSIC_CTRL_REFCLKSEL & HSIC_CTRL_REFCLKSEL_MASK)
121 				<< HSIC_CTRL_REFCLKSEL_SHIFT)
122 			| HSIC_CTRL_UTMISWRST);
123 
124 	setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
125 	setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
126 
127 	udelay(10);
128 
129 	clrbits_le32(&usb->hsicphyctrl1, HSIC_CTRL_PHYSWRST |
130 					HSIC_CTRL_UTMISWRST);
131 
132 	clrbits_le32(&usb->hsicphyctrl2, HSIC_CTRL_PHYSWRST |
133 					HSIC_CTRL_UTMISWRST);
134 
135 	udelay(20);
136 
137 	/* EHCI Ctrl setting */
138 	setbits_le32(&usb->ehcictrl,
139 			EHCICTRL_ENAINCRXALIGN |
140 			EHCICTRL_ENAINCR4 |
141 			EHCICTRL_ENAINCR8 |
142 			EHCICTRL_ENAINCR16);
143 }
144 
145 static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
146 {
147 	writel(CLK_24MHZ, &usb->usbphyclk);
148 
149 	clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
150 		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
151 		PHYPWR_NORMAL_MASK_PHY0));
152 
153 	setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
154 	udelay(10);
155 	clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
156 }
157 
158 static void setup_usb_phy(struct exynos_usb_phy *usb)
159 {
160 	set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
161 
162 	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
163 
164 	if (cpu_is_exynos5())
165 		exynos5_setup_usb_phy(usb);
166 	else if (cpu_is_exynos4())
167 		if (proid_is_exynos4412())
168 			exynos4412_setup_usb_phy((struct exynos4412_usb_phy *)
169 						 usb);
170 }
171 
172 static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
173 {
174 	u32 hsic_ctrl;
175 
176 	/* HOST_PHY reset */
177 	setbits_le32(&usb->usbphyctrl0,
178 			HOST_CTRL0_PHYSWRST |
179 			HOST_CTRL0_PHYSWRSTALL |
180 			HOST_CTRL0_SIDDQ |
181 			HOST_CTRL0_FORCESUSPEND |
182 			HOST_CTRL0_FORCESLEEP);
183 
184 	/* HSIC Phy reset */
185 	hsic_ctrl = (HSIC_CTRL_FORCESUSPEND |
186 			HSIC_CTRL_FORCESLEEP |
187 			HSIC_CTRL_SIDDQ |
188 			HSIC_CTRL_PHYSWRST);
189 
190 	setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
191 	setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
192 }
193 
194 static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
195 {
196 	setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
197 		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
198 		PHYPWR_NORMAL_MASK_PHY0));
199 }
200 
201 /* Reset the EHCI host controller. */
202 static void reset_usb_phy(struct exynos_usb_phy *usb)
203 {
204 	if (cpu_is_exynos5())
205 		exynos5_reset_usb_phy(usb);
206 	else if (cpu_is_exynos4())
207 		if (proid_is_exynos4412())
208 			exynos4412_reset_usb_phy((struct exynos4412_usb_phy *)
209 						 usb);
210 
211 	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
212 }
213 
214 static int ehci_usb_probe(struct udevice *dev)
215 {
216 	struct exynos_ehci_platdata *plat = dev_get_platdata(dev);
217 	struct exynos_ehci *ctx = dev_get_priv(dev);
218 	struct ehci_hcor *hcor;
219 
220 	ctx->hcd = (struct ehci_hccr *)plat->hcd_base;
221 	ctx->usb = (struct exynos_usb_phy *)plat->phy_base;
222 
223 	/* setup the Vbus gpio here */
224 	if (dm_gpio_is_valid(&plat->vbus_gpio))
225 		dm_gpio_set_value(&plat->vbus_gpio, 1);
226 
227 	setup_usb_phy(ctx->usb);
228 	hcor = (struct ehci_hcor *)((uint32_t)ctx->hcd +
229 			HC_LENGTH(ehci_readl(&ctx->hcd->cr_capbase)));
230 
231 	return ehci_register(dev, ctx->hcd, hcor, NULL, 0, USB_INIT_HOST);
232 }
233 
234 static int ehci_usb_remove(struct udevice *dev)
235 {
236 	struct exynos_ehci *ctx = dev_get_priv(dev);
237 	int ret;
238 
239 	ret = ehci_deregister(dev);
240 	if (ret)
241 		return ret;
242 	reset_usb_phy(ctx->usb);
243 
244 	return 0;
245 }
246 
247 static const struct udevice_id ehci_usb_ids[] = {
248 	{ .compatible = "samsung,exynos-ehci" },
249 	{ }
250 };
251 
252 U_BOOT_DRIVER(usb_ehci) = {
253 	.name	= "ehci_exynos",
254 	.id	= UCLASS_USB,
255 	.of_match = ehci_usb_ids,
256 	.ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
257 	.probe = ehci_usb_probe,
258 	.remove = ehci_usb_remove,
259 	.ops	= &ehci_usb_ops,
260 	.priv_auto_alloc_size = sizeof(struct exynos_ehci),
261 	.platdata_auto_alloc_size = sizeof(struct exynos_ehci_platdata),
262 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
263 };
264