xref: /openbmc/u-boot/drivers/usb/host/ehci-exynos.c (revision ed09a554)
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 <asm-generic/errno.h>
22 #include <linux/compat.h>
23 #include "ehci.h"
24 
25 /* Declare global data pointer */
26 DECLARE_GLOBAL_DATA_PTR;
27 
28 #ifdef CONFIG_DM_USB
29 struct exynos_ehci_platdata {
30 	struct usb_platdata usb_plat;
31 	fdt_addr_t hcd_base;
32 	fdt_addr_t phy_base;
33 	struct gpio_desc vbus_gpio;
34 };
35 #endif
36 
37 /**
38  * Contains pointers to register base addresses
39  * for the usb controller.
40  */
41 struct exynos_ehci {
42 	struct ehci_ctrl ctrl;
43 	struct exynos_usb_phy *usb;
44 	struct ehci_hccr *hcd;
45 #ifndef CONFIG_DM_USB
46 	struct gpio_desc vbus_gpio;
47 #endif
48 };
49 
50 #ifndef CONFIG_DM_USB
51 static struct exynos_ehci exynos;
52 #endif
53 
54 #ifdef CONFIG_DM_USB
55 static int ehci_usb_ofdata_to_platdata(struct udevice *dev)
56 {
57 	struct exynos_ehci_platdata *plat = dev_get_platdata(dev);
58 	const void *blob = gd->fdt_blob;
59 	unsigned int node;
60 	int depth;
61 
62 	/*
63 	 * Get the base address for XHCI controller from the device node
64 	 */
65 	plat->hcd_base = dev_get_addr(dev);
66 	if (plat->hcd_base == FDT_ADDR_T_NONE) {
67 		debug("Can't get the XHCI register base address\n");
68 		return -ENXIO;
69 	}
70 
71 	depth = 0;
72 	node = fdtdec_next_compatible_subnode(blob, dev->of_offset,
73 				COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth);
74 	if (node <= 0) {
75 		debug("XHCI: Can't get device node for usb3-phy controller\n");
76 		return -ENODEV;
77 	}
78 
79 	/*
80 	 * Get the base address for usbphy from the device node
81 	 */
82 	plat->phy_base = fdtdec_get_addr(blob, node, "reg");
83 	if (plat->phy_base == FDT_ADDR_T_NONE) {
84 		debug("Can't get the usbphy register address\n");
85 		return -ENXIO;
86 	}
87 
88 	/* Vbus gpio */
89 	gpio_request_by_name(dev, "samsung,vbus-gpio", 0,
90 			     &plat->vbus_gpio, GPIOD_IS_OUT);
91 
92 	return 0;
93 }
94 #else
95 static int exynos_usb_parse_dt(const void *blob, struct exynos_ehci *exynos)
96 {
97 	fdt_addr_t addr;
98 	unsigned int node;
99 	int depth;
100 
101 	node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS_EHCI);
102 	if (node <= 0) {
103 		debug("EHCI: Can't get device node for ehci\n");
104 		return -ENODEV;
105 	}
106 
107 	/*
108 	 * Get the base address for EHCI controller from the device node
109 	 */
110 	addr = fdtdec_get_addr(blob, node, "reg");
111 	if (addr == FDT_ADDR_T_NONE) {
112 		debug("Can't get the EHCI register address\n");
113 		return -ENXIO;
114 	}
115 
116 	exynos->hcd = (struct ehci_hccr *)addr;
117 
118 	/* Vbus gpio */
119 	gpio_request_by_name_nodev(blob, node, "samsung,vbus-gpio", 0,
120 				   &exynos->vbus_gpio, GPIOD_IS_OUT);
121 
122 	depth = 0;
123 	node = fdtdec_next_compatible_subnode(blob, node,
124 					COMPAT_SAMSUNG_EXYNOS_USB_PHY, &depth);
125 	if (node <= 0) {
126 		debug("EHCI: Can't get device node for usb-phy controller\n");
127 		return -ENODEV;
128 	}
129 
130 	/*
131 	 * Get the base address for usbphy from the device node
132 	 */
133 	exynos->usb = (struct exynos_usb_phy *)fdtdec_get_addr(blob, node,
134 								"reg");
135 	if (exynos->usb == NULL) {
136 		debug("Can't get the usbphy register address\n");
137 		return -ENXIO;
138 	}
139 
140 	return 0;
141 }
142 #endif
143 
144 static void exynos5_setup_usb_phy(struct exynos_usb_phy *usb)
145 {
146 	u32 hsic_ctrl;
147 
148 	clrbits_le32(&usb->usbphyctrl0,
149 			HOST_CTRL0_FSEL_MASK |
150 			HOST_CTRL0_COMMONON_N |
151 			/* HOST Phy setting */
152 			HOST_CTRL0_PHYSWRST |
153 			HOST_CTRL0_PHYSWRSTALL |
154 			HOST_CTRL0_SIDDQ |
155 			HOST_CTRL0_FORCESUSPEND |
156 			HOST_CTRL0_FORCESLEEP);
157 
158 	setbits_le32(&usb->usbphyctrl0,
159 			/* Setting up the ref freq */
160 			(CLK_24MHZ << 16) |
161 			/* HOST Phy setting */
162 			HOST_CTRL0_LINKSWRST |
163 			HOST_CTRL0_UTMISWRST);
164 	udelay(10);
165 	clrbits_le32(&usb->usbphyctrl0,
166 			HOST_CTRL0_LINKSWRST |
167 			HOST_CTRL0_UTMISWRST);
168 
169 	/* HSIC Phy Setting */
170 	hsic_ctrl = (HSIC_CTRL_FORCESUSPEND |
171 			HSIC_CTRL_FORCESLEEP |
172 			HSIC_CTRL_SIDDQ);
173 
174 	clrbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
175 	clrbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
176 
177 	hsic_ctrl = (((HSIC_CTRL_REFCLKDIV_12 & HSIC_CTRL_REFCLKDIV_MASK)
178 				<< HSIC_CTRL_REFCLKDIV_SHIFT)
179 			| ((HSIC_CTRL_REFCLKSEL & HSIC_CTRL_REFCLKSEL_MASK)
180 				<< HSIC_CTRL_REFCLKSEL_SHIFT)
181 			| HSIC_CTRL_UTMISWRST);
182 
183 	setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
184 	setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
185 
186 	udelay(10);
187 
188 	clrbits_le32(&usb->hsicphyctrl1, HSIC_CTRL_PHYSWRST |
189 					HSIC_CTRL_UTMISWRST);
190 
191 	clrbits_le32(&usb->hsicphyctrl2, HSIC_CTRL_PHYSWRST |
192 					HSIC_CTRL_UTMISWRST);
193 
194 	udelay(20);
195 
196 	/* EHCI Ctrl setting */
197 	setbits_le32(&usb->ehcictrl,
198 			EHCICTRL_ENAINCRXALIGN |
199 			EHCICTRL_ENAINCR4 |
200 			EHCICTRL_ENAINCR8 |
201 			EHCICTRL_ENAINCR16);
202 }
203 
204 static void exynos4412_setup_usb_phy(struct exynos4412_usb_phy *usb)
205 {
206 	writel(CLK_24MHZ, &usb->usbphyclk);
207 
208 	clrbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
209 		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
210 		PHYPWR_NORMAL_MASK_PHY0));
211 
212 	setbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
213 	udelay(10);
214 	clrbits_le32(&usb->usbphyrstcon, (RSTCON_HOSTPHY_SWRST | RSTCON_SWRST));
215 }
216 
217 static void setup_usb_phy(struct exynos_usb_phy *usb)
218 {
219 	set_usbhost_mode(USB20_PHY_CFG_HOST_LINK_EN);
220 
221 	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_EN);
222 
223 	if (cpu_is_exynos5())
224 		exynos5_setup_usb_phy(usb);
225 	else if (cpu_is_exynos4())
226 		if (proid_is_exynos4412())
227 			exynos4412_setup_usb_phy((struct exynos4412_usb_phy *)
228 						 usb);
229 }
230 
231 static void exynos5_reset_usb_phy(struct exynos_usb_phy *usb)
232 {
233 	u32 hsic_ctrl;
234 
235 	/* HOST_PHY reset */
236 	setbits_le32(&usb->usbphyctrl0,
237 			HOST_CTRL0_PHYSWRST |
238 			HOST_CTRL0_PHYSWRSTALL |
239 			HOST_CTRL0_SIDDQ |
240 			HOST_CTRL0_FORCESUSPEND |
241 			HOST_CTRL0_FORCESLEEP);
242 
243 	/* HSIC Phy reset */
244 	hsic_ctrl = (HSIC_CTRL_FORCESUSPEND |
245 			HSIC_CTRL_FORCESLEEP |
246 			HSIC_CTRL_SIDDQ |
247 			HSIC_CTRL_PHYSWRST);
248 
249 	setbits_le32(&usb->hsicphyctrl1, hsic_ctrl);
250 	setbits_le32(&usb->hsicphyctrl2, hsic_ctrl);
251 }
252 
253 static void exynos4412_reset_usb_phy(struct exynos4412_usb_phy *usb)
254 {
255 	setbits_le32(&usb->usbphyctrl, (PHYPWR_NORMAL_MASK_HSIC0 |
256 		PHYPWR_NORMAL_MASK_HSIC1 | PHYPWR_NORMAL_MASK_PHY1 |
257 		PHYPWR_NORMAL_MASK_PHY0));
258 }
259 
260 /* Reset the EHCI host controller. */
261 static void reset_usb_phy(struct exynos_usb_phy *usb)
262 {
263 	if (cpu_is_exynos5())
264 		exynos5_reset_usb_phy(usb);
265 	else if (cpu_is_exynos4())
266 		if (proid_is_exynos4412())
267 			exynos4412_reset_usb_phy((struct exynos4412_usb_phy *)
268 						 usb);
269 
270 	set_usbhost_phy_ctrl(POWER_USB_HOST_PHY_CTRL_DISABLE);
271 }
272 
273 #ifndef CONFIG_DM_USB
274 /*
275  * EHCI-initialization
276  * Create the appropriate control structures to manage
277  * a new EHCI host controller.
278  */
279 int ehci_hcd_init(int index, enum usb_init_type init,
280 		struct ehci_hccr **hccr, struct ehci_hcor **hcor)
281 {
282 	struct exynos_ehci *ctx = &exynos;
283 
284 #ifdef CONFIG_OF_CONTROL
285 	if (exynos_usb_parse_dt(gd->fdt_blob, ctx)) {
286 		debug("Unable to parse device tree for ehci-exynos\n");
287 		return -ENODEV;
288 	}
289 #else
290 	ctx->usb = (struct exynos_usb_phy *)samsung_get_base_usb_phy();
291 	ctx->hcd = (struct ehci_hccr *)samsung_get_base_usb_ehci();
292 #endif
293 
294 #ifdef CONFIG_OF_CONTROL
295 	/* setup the Vbus gpio here */
296 	if (dm_gpio_is_valid(&ctx->vbus_gpio))
297 		dm_gpio_set_value(&ctx->vbus_gpio, 1);
298 #endif
299 
300 	setup_usb_phy(ctx->usb);
301 
302 	board_usb_init(index, init);
303 
304 	*hccr = ctx->hcd;
305 	*hcor = (struct ehci_hcor *)((uint32_t) *hccr
306 				+ HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
307 
308 	debug("Exynos5-ehci: init hccr %x and hcor %x hc_length %d\n",
309 		(uint32_t)*hccr, (uint32_t)*hcor,
310 		(uint32_t)HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
311 
312 	return 0;
313 }
314 
315 /*
316  * Destroy the appropriate control structures corresponding
317  * the EHCI host controller.
318  */
319 int ehci_hcd_stop(int index)
320 {
321 	struct exynos_ehci *ctx = &exynos;
322 
323 	reset_usb_phy(ctx->usb);
324 
325 	return 0;
326 }
327 #endif
328 
329 #ifdef CONFIG_DM_USB
330 static int ehci_usb_probe(struct udevice *dev)
331 {
332 	struct exynos_ehci_platdata *plat = dev_get_platdata(dev);
333 	struct exynos_ehci *ctx = dev_get_priv(dev);
334 	struct ehci_hcor *hcor;
335 
336 	ctx->hcd = (struct ehci_hccr *)plat->hcd_base;
337 	ctx->usb = (struct exynos_usb_phy *)plat->phy_base;
338 	hcor = (struct ehci_hcor *)((uint32_t)ctx->hcd +
339 			HC_LENGTH(ehci_readl(&ctx->hcd->cr_capbase)));
340 
341 	/* setup the Vbus gpio here */
342 	if (dm_gpio_is_valid(&plat->vbus_gpio))
343 		dm_gpio_set_value(&plat->vbus_gpio, 1);
344 
345 	setup_usb_phy(ctx->usb);
346 
347 	return ehci_register(dev, ctx->hcd, hcor, NULL, 0, USB_INIT_HOST);
348 }
349 
350 static int ehci_usb_remove(struct udevice *dev)
351 {
352 	struct exynos_ehci *ctx = dev_get_priv(dev);
353 	int ret;
354 
355 	ret = ehci_deregister(dev);
356 	if (ret)
357 		return ret;
358 	reset_usb_phy(ctx->usb);
359 
360 	return 0;
361 }
362 
363 static const struct udevice_id ehci_usb_ids[] = {
364 	{ .compatible = "samsung,exynos-ehci" },
365 	{ }
366 };
367 
368 U_BOOT_DRIVER(usb_ehci) = {
369 	.name	= "ehci_exynos",
370 	.id	= UCLASS_USB,
371 	.of_match = ehci_usb_ids,
372 	.ofdata_to_platdata = ehci_usb_ofdata_to_platdata,
373 	.probe = ehci_usb_probe,
374 	.remove = ehci_usb_remove,
375 	.ops	= &ehci_usb_ops,
376 	.priv_auto_alloc_size = sizeof(struct exynos_ehci),
377 	.platdata_auto_alloc_size = sizeof(struct exynos_ehci_platdata),
378 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
379 };
380 #endif
381