xref: /openbmc/u-boot/drivers/usb/host/ehci-vf.c (revision 0885cdb9d154ac0f63bb681d4f280a39de354f8c)
1a94bb7a4SSanchayan Maity /*
2a94bb7a4SSanchayan Maity  * Copyright (c) 2015 Sanchayan Maity <sanchayan.maity@toradex.com>
3a94bb7a4SSanchayan Maity  * Copyright (C) 2015 Toradex AG
4a94bb7a4SSanchayan Maity  *
5a94bb7a4SSanchayan Maity  * Based on ehci-mx6 driver
6a94bb7a4SSanchayan Maity  *
7a94bb7a4SSanchayan Maity  * SPDX-License-Identifier:	GPL-2.0+
8a94bb7a4SSanchayan Maity  */
9a94bb7a4SSanchayan Maity 
10a94bb7a4SSanchayan Maity #include <common.h>
11*0885cdb9SSanchayan Maity #include <dm.h>
12a94bb7a4SSanchayan Maity #include <usb.h>
13a94bb7a4SSanchayan Maity #include <errno.h>
14a94bb7a4SSanchayan Maity #include <linux/compiler.h>
15a94bb7a4SSanchayan Maity #include <asm/io.h>
16*0885cdb9SSanchayan Maity #include <asm-generic/gpio.h>
17a94bb7a4SSanchayan Maity #include <asm/arch/clock.h>
18a94bb7a4SSanchayan Maity #include <asm/arch/imx-regs.h>
19a94bb7a4SSanchayan Maity #include <asm/arch/crm_regs.h>
20a94bb7a4SSanchayan Maity #include <asm/imx-common/iomux-v3.h>
21a94bb7a4SSanchayan Maity #include <asm/imx-common/regs-usbphy.h>
22e162c6b1SMateusz Kulikowski #include <usb/ehci-ci.h>
23*0885cdb9SSanchayan Maity #include <libfdt.h>
24*0885cdb9SSanchayan Maity #include <fdtdec.h>
25a94bb7a4SSanchayan Maity 
26a94bb7a4SSanchayan Maity #include "ehci.h"
27a94bb7a4SSanchayan Maity 
28a94bb7a4SSanchayan Maity #define USB_NC_REG_OFFSET				0x00000800
29a94bb7a4SSanchayan Maity 
30a94bb7a4SSanchayan Maity #define ANADIG_PLL_CTRL_EN_USB_CLKS		(1 << 6)
31a94bb7a4SSanchayan Maity 
32a94bb7a4SSanchayan Maity #define UCTRL_OVER_CUR_POL	(1 << 8) /* OTG Polarity of Overcurrent */
33a94bb7a4SSanchayan Maity #define UCTRL_OVER_CUR_DIS	(1 << 7) /* Disable OTG Overcurrent Detection */
34a94bb7a4SSanchayan Maity 
35a94bb7a4SSanchayan Maity /* USBCMD */
36a94bb7a4SSanchayan Maity #define UCMD_RUN_STOP		(1 << 0) /* controller run/stop */
37a94bb7a4SSanchayan Maity #define UCMD_RESET			(1 << 1) /* controller reset */
38a94bb7a4SSanchayan Maity 
39*0885cdb9SSanchayan Maity DECLARE_GLOBAL_DATA_PTR;
40*0885cdb9SSanchayan Maity 
41a94bb7a4SSanchayan Maity static const unsigned phy_bases[] = {
42a94bb7a4SSanchayan Maity 	USB_PHY0_BASE_ADDR,
43a94bb7a4SSanchayan Maity 	USB_PHY1_BASE_ADDR,
44a94bb7a4SSanchayan Maity };
45a94bb7a4SSanchayan Maity 
46a94bb7a4SSanchayan Maity static const unsigned nc_reg_bases[] = {
47a94bb7a4SSanchayan Maity 	USBC0_BASE_ADDR,
48a94bb7a4SSanchayan Maity 	USBC1_BASE_ADDR,
49a94bb7a4SSanchayan Maity };
50a94bb7a4SSanchayan Maity 
51a94bb7a4SSanchayan Maity static void usb_internal_phy_clock_gate(int index)
52a94bb7a4SSanchayan Maity {
53a94bb7a4SSanchayan Maity 	void __iomem *phy_reg;
54a94bb7a4SSanchayan Maity 
55a94bb7a4SSanchayan Maity 	phy_reg = (void __iomem *)phy_bases[index];
56a94bb7a4SSanchayan Maity 	clrbits_le32(phy_reg + USBPHY_CTRL, USBPHY_CTRL_CLKGATE);
57a94bb7a4SSanchayan Maity }
58a94bb7a4SSanchayan Maity 
59a94bb7a4SSanchayan Maity static void usb_power_config(int index)
60a94bb7a4SSanchayan Maity {
61a94bb7a4SSanchayan Maity 	struct anadig_reg __iomem *anadig =
62a94bb7a4SSanchayan Maity 		(struct anadig_reg __iomem *)ANADIG_BASE_ADDR;
63a94bb7a4SSanchayan Maity 	void __iomem *pll_ctrl;
64a94bb7a4SSanchayan Maity 
65a94bb7a4SSanchayan Maity 	switch (index) {
66a94bb7a4SSanchayan Maity 	case 0:
67a94bb7a4SSanchayan Maity 		pll_ctrl = &anadig->pll3_ctrl;
68a94bb7a4SSanchayan Maity 		clrbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_BYPASS);
69a94bb7a4SSanchayan Maity 		setbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_ENABLE
70a94bb7a4SSanchayan Maity 			 | ANADIG_PLL3_CTRL_POWERDOWN
71a94bb7a4SSanchayan Maity 			 | ANADIG_PLL_CTRL_EN_USB_CLKS);
72a94bb7a4SSanchayan Maity 		break;
73a94bb7a4SSanchayan Maity 	case 1:
74a94bb7a4SSanchayan Maity 		pll_ctrl = &anadig->pll7_ctrl;
75a94bb7a4SSanchayan Maity 		clrbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_BYPASS);
76a94bb7a4SSanchayan Maity 		setbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_ENABLE
77a94bb7a4SSanchayan Maity 			 | ANADIG_PLL7_CTRL_POWERDOWN
78a94bb7a4SSanchayan Maity 			 | ANADIG_PLL_CTRL_EN_USB_CLKS);
79a94bb7a4SSanchayan Maity 		break;
80a94bb7a4SSanchayan Maity 	default:
81a94bb7a4SSanchayan Maity 		return;
82a94bb7a4SSanchayan Maity 	}
83a94bb7a4SSanchayan Maity }
84a94bb7a4SSanchayan Maity 
85a94bb7a4SSanchayan Maity static void usb_phy_enable(int index, struct usb_ehci *ehci)
86a94bb7a4SSanchayan Maity {
87a94bb7a4SSanchayan Maity 	void __iomem *phy_reg;
88a94bb7a4SSanchayan Maity 	void __iomem *phy_ctrl;
89a94bb7a4SSanchayan Maity 	void __iomem *usb_cmd;
90a94bb7a4SSanchayan Maity 
91a94bb7a4SSanchayan Maity 	phy_reg = (void __iomem *)phy_bases[index];
92a94bb7a4SSanchayan Maity 	phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
93a94bb7a4SSanchayan Maity 	usb_cmd = (void __iomem *)&ehci->usbcmd;
94a94bb7a4SSanchayan Maity 
95a94bb7a4SSanchayan Maity 	/* Stop then Reset */
96a94bb7a4SSanchayan Maity 	clrbits_le32(usb_cmd, UCMD_RUN_STOP);
97a94bb7a4SSanchayan Maity 	while (readl(usb_cmd) & UCMD_RUN_STOP)
98a94bb7a4SSanchayan Maity 		;
99a94bb7a4SSanchayan Maity 
100a94bb7a4SSanchayan Maity 	setbits_le32(usb_cmd, UCMD_RESET);
101a94bb7a4SSanchayan Maity 	while (readl(usb_cmd) & UCMD_RESET)
102a94bb7a4SSanchayan Maity 		;
103a94bb7a4SSanchayan Maity 
104a94bb7a4SSanchayan Maity 	/* Reset USBPHY module */
105a94bb7a4SSanchayan Maity 	setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST);
106a94bb7a4SSanchayan Maity 	udelay(10);
107a94bb7a4SSanchayan Maity 
108a94bb7a4SSanchayan Maity 	/* Remove CLKGATE and SFTRST */
109a94bb7a4SSanchayan Maity 	clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
110a94bb7a4SSanchayan Maity 	udelay(10);
111a94bb7a4SSanchayan Maity 
112a94bb7a4SSanchayan Maity 	/* Power up the PHY */
113a94bb7a4SSanchayan Maity 	writel(0, phy_reg + USBPHY_PWD);
114a94bb7a4SSanchayan Maity 
115a94bb7a4SSanchayan Maity 	/* Enable FS/LS device */
116a94bb7a4SSanchayan Maity 	setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 |
117a94bb7a4SSanchayan Maity 		 USBPHY_CTRL_ENUTMILEVEL3);
118a94bb7a4SSanchayan Maity }
119a94bb7a4SSanchayan Maity 
120a94bb7a4SSanchayan Maity static void usb_oc_config(int index)
121a94bb7a4SSanchayan Maity {
122a94bb7a4SSanchayan Maity 	void __iomem *ctrl;
123a94bb7a4SSanchayan Maity 
124a94bb7a4SSanchayan Maity 	ctrl = (void __iomem *)(nc_reg_bases[index] + USB_NC_REG_OFFSET);
125a94bb7a4SSanchayan Maity 
126a94bb7a4SSanchayan Maity 	setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
127a94bb7a4SSanchayan Maity 	setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
128a94bb7a4SSanchayan Maity }
129a94bb7a4SSanchayan Maity 
13008c11cb5SSanchayan Maity int __weak board_usb_phy_mode(int port)
13108c11cb5SSanchayan Maity {
13208c11cb5SSanchayan Maity 	return 0;
13308c11cb5SSanchayan Maity }
13408c11cb5SSanchayan Maity 
13560ed2864SSanchayan Maity int __weak board_ehci_hcd_init(int port)
13660ed2864SSanchayan Maity {
13760ed2864SSanchayan Maity 	return 0;
13860ed2864SSanchayan Maity }
13960ed2864SSanchayan Maity 
140*0885cdb9SSanchayan Maity int ehci_vf_common_init(struct usb_ehci *ehci, int index)
141*0885cdb9SSanchayan Maity {
142*0885cdb9SSanchayan Maity 	int ret;
143*0885cdb9SSanchayan Maity 
144*0885cdb9SSanchayan Maity 	/* Do board specific initialisation */
145*0885cdb9SSanchayan Maity 	ret = board_ehci_hcd_init(index);
146*0885cdb9SSanchayan Maity 	if (ret)
147*0885cdb9SSanchayan Maity 		return ret;
148*0885cdb9SSanchayan Maity 
149*0885cdb9SSanchayan Maity 	usb_power_config(index);
150*0885cdb9SSanchayan Maity 	usb_oc_config(index);
151*0885cdb9SSanchayan Maity 	usb_internal_phy_clock_gate(index);
152*0885cdb9SSanchayan Maity 	usb_phy_enable(index, ehci);
153*0885cdb9SSanchayan Maity 
154*0885cdb9SSanchayan Maity 	return 0;
155*0885cdb9SSanchayan Maity }
156*0885cdb9SSanchayan Maity 
157*0885cdb9SSanchayan Maity #ifndef CONFIG_DM_USB
158a94bb7a4SSanchayan Maity int ehci_hcd_init(int index, enum usb_init_type init,
159a94bb7a4SSanchayan Maity 		struct ehci_hccr **hccr, struct ehci_hcor **hcor)
160a94bb7a4SSanchayan Maity {
161a94bb7a4SSanchayan Maity 	struct usb_ehci *ehci;
16208c11cb5SSanchayan Maity 	enum usb_init_type type;
163*0885cdb9SSanchayan Maity 	int ret;
164a94bb7a4SSanchayan Maity 
165a94bb7a4SSanchayan Maity 	if (index >= ARRAY_SIZE(nc_reg_bases))
166a94bb7a4SSanchayan Maity 		return -EINVAL;
167a94bb7a4SSanchayan Maity 
168a94bb7a4SSanchayan Maity 	ehci = (struct usb_ehci *)nc_reg_bases[index];
169a94bb7a4SSanchayan Maity 
170*0885cdb9SSanchayan Maity 	ret = ehci_vf_common_init(index);
171*0885cdb9SSanchayan Maity 	if (ret)
172*0885cdb9SSanchayan Maity 		return ret;
173a94bb7a4SSanchayan Maity 
174a94bb7a4SSanchayan Maity 	*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
175a94bb7a4SSanchayan Maity 	*hcor = (struct ehci_hcor *)((uint32_t)*hccr +
176a94bb7a4SSanchayan Maity 			HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
177a94bb7a4SSanchayan Maity 
17808c11cb5SSanchayan Maity 	type = board_usb_phy_mode(index);
17908c11cb5SSanchayan Maity 	if (type != init)
18008c11cb5SSanchayan Maity 		return -ENODEV;
18108c11cb5SSanchayan Maity 
182a94bb7a4SSanchayan Maity 	if (init == USB_INIT_DEVICE) {
183a94bb7a4SSanchayan Maity 		setbits_le32(&ehci->usbmode, CM_DEVICE);
184a94bb7a4SSanchayan Maity 		writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
185a94bb7a4SSanchayan Maity 		setbits_le32(&ehci->portsc, USB_EN);
186a94bb7a4SSanchayan Maity 	} else if (init == USB_INIT_HOST) {
187a94bb7a4SSanchayan Maity 		setbits_le32(&ehci->usbmode, CM_HOST);
188a94bb7a4SSanchayan Maity 		writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
189a94bb7a4SSanchayan Maity 		setbits_le32(&ehci->portsc, USB_EN);
190a94bb7a4SSanchayan Maity 	}
191a94bb7a4SSanchayan Maity 
192a94bb7a4SSanchayan Maity 	return 0;
193a94bb7a4SSanchayan Maity }
194a94bb7a4SSanchayan Maity 
195a94bb7a4SSanchayan Maity int ehci_hcd_stop(int index)
196a94bb7a4SSanchayan Maity {
197a94bb7a4SSanchayan Maity 	return 0;
198a94bb7a4SSanchayan Maity }
199*0885cdb9SSanchayan Maity #else
200*0885cdb9SSanchayan Maity /* Possible port types (dual role mode) */
201*0885cdb9SSanchayan Maity enum dr_mode {
202*0885cdb9SSanchayan Maity 	DR_MODE_NONE = 0,
203*0885cdb9SSanchayan Maity 	DR_MODE_HOST,		/* supports host operation */
204*0885cdb9SSanchayan Maity 	DR_MODE_DEVICE,		/* supports device operation */
205*0885cdb9SSanchayan Maity 	DR_MODE_OTG,		/* supports both */
206*0885cdb9SSanchayan Maity };
207*0885cdb9SSanchayan Maity 
208*0885cdb9SSanchayan Maity struct ehci_vf_priv_data {
209*0885cdb9SSanchayan Maity 	struct ehci_ctrl ctrl;
210*0885cdb9SSanchayan Maity 	struct usb_ehci *ehci;
211*0885cdb9SSanchayan Maity 	struct gpio_desc cdet_gpio;
212*0885cdb9SSanchayan Maity 	enum usb_init_type init_type;
213*0885cdb9SSanchayan Maity 	enum dr_mode dr_mode;
214*0885cdb9SSanchayan Maity 	u32 portnr;
215*0885cdb9SSanchayan Maity };
216*0885cdb9SSanchayan Maity 
217*0885cdb9SSanchayan Maity static int vf_usb_ofdata_to_platdata(struct udevice *dev)
218*0885cdb9SSanchayan Maity {
219*0885cdb9SSanchayan Maity 	struct ehci_vf_priv_data *priv = dev_get_priv(dev);
220*0885cdb9SSanchayan Maity 	const void *dt_blob = gd->fdt_blob;
221*0885cdb9SSanchayan Maity 	int node = dev->of_offset;
222*0885cdb9SSanchayan Maity 	const char *mode;
223*0885cdb9SSanchayan Maity 
224*0885cdb9SSanchayan Maity 	priv->portnr = dev->seq;
225*0885cdb9SSanchayan Maity 
226*0885cdb9SSanchayan Maity 	priv->ehci = (struct usb_ehci *)dev_get_addr(dev);
227*0885cdb9SSanchayan Maity 	mode = fdt_getprop(dt_blob, node, "dr_mode", NULL);
228*0885cdb9SSanchayan Maity 	if (mode) {
229*0885cdb9SSanchayan Maity 		if (0 == strcmp(mode, "host")) {
230*0885cdb9SSanchayan Maity 			priv->dr_mode = DR_MODE_HOST;
231*0885cdb9SSanchayan Maity 			priv->init_type = USB_INIT_HOST;
232*0885cdb9SSanchayan Maity 		} else if (0 == strcmp(mode, "peripheral")) {
233*0885cdb9SSanchayan Maity 			priv->dr_mode = DR_MODE_DEVICE;
234*0885cdb9SSanchayan Maity 			priv->init_type = USB_INIT_DEVICE;
235*0885cdb9SSanchayan Maity 		} else if (0 == strcmp(mode, "otg")) {
236*0885cdb9SSanchayan Maity 			priv->dr_mode = DR_MODE_OTG;
237*0885cdb9SSanchayan Maity 			/*
238*0885cdb9SSanchayan Maity 			 * We set init_type to device by default when OTG
239*0885cdb9SSanchayan Maity 			 * mode is requested. If a valid gpio is provided
240*0885cdb9SSanchayan Maity 			 * we will switch the init_type based on the state
241*0885cdb9SSanchayan Maity 			 * of the gpio pin.
242*0885cdb9SSanchayan Maity 			 */
243*0885cdb9SSanchayan Maity 			priv->init_type = USB_INIT_DEVICE;
244*0885cdb9SSanchayan Maity 		} else {
245*0885cdb9SSanchayan Maity 			debug("%s: Cannot decode dr_mode '%s'\n",
246*0885cdb9SSanchayan Maity 			      __func__, mode);
247*0885cdb9SSanchayan Maity 			return -EINVAL;
248*0885cdb9SSanchayan Maity 		}
249*0885cdb9SSanchayan Maity 	} else {
250*0885cdb9SSanchayan Maity 		priv->dr_mode = DR_MODE_HOST;
251*0885cdb9SSanchayan Maity 		priv->init_type = USB_INIT_HOST;
252*0885cdb9SSanchayan Maity 	}
253*0885cdb9SSanchayan Maity 
254*0885cdb9SSanchayan Maity 	if (priv->dr_mode == DR_MODE_OTG) {
255*0885cdb9SSanchayan Maity 		gpio_request_by_name_nodev(dt_blob, node, "fsl,cdet-gpio", 0,
256*0885cdb9SSanchayan Maity 					   &priv->cdet_gpio, GPIOD_IS_IN);
257*0885cdb9SSanchayan Maity 		if (dm_gpio_is_valid(&priv->cdet_gpio)) {
258*0885cdb9SSanchayan Maity 			if (dm_gpio_get_value(&priv->cdet_gpio))
259*0885cdb9SSanchayan Maity 				priv->init_type = USB_INIT_DEVICE;
260*0885cdb9SSanchayan Maity 			else
261*0885cdb9SSanchayan Maity 				priv->init_type = USB_INIT_HOST;
262*0885cdb9SSanchayan Maity 		}
263*0885cdb9SSanchayan Maity 	}
264*0885cdb9SSanchayan Maity 
265*0885cdb9SSanchayan Maity 	return 0;
266*0885cdb9SSanchayan Maity }
267*0885cdb9SSanchayan Maity 
268*0885cdb9SSanchayan Maity static int vf_init_after_reset(struct ehci_ctrl *dev)
269*0885cdb9SSanchayan Maity {
270*0885cdb9SSanchayan Maity 	struct ehci_vf_priv_data *priv = dev->priv;
271*0885cdb9SSanchayan Maity 	enum usb_init_type type = priv->init_type;
272*0885cdb9SSanchayan Maity 	struct usb_ehci *ehci = priv->ehci;
273*0885cdb9SSanchayan Maity 	int ret;
274*0885cdb9SSanchayan Maity 
275*0885cdb9SSanchayan Maity 	ret = ehci_vf_common_init(priv->ehci, priv->portnr);
276*0885cdb9SSanchayan Maity 	if (ret)
277*0885cdb9SSanchayan Maity 		return ret;
278*0885cdb9SSanchayan Maity 
279*0885cdb9SSanchayan Maity 	if (type == USB_INIT_DEVICE)
280*0885cdb9SSanchayan Maity 		return 0;
281*0885cdb9SSanchayan Maity 
282*0885cdb9SSanchayan Maity 	setbits_le32(&ehci->usbmode, CM_HOST);
283*0885cdb9SSanchayan Maity 	writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
284*0885cdb9SSanchayan Maity 	setbits_le32(&ehci->portsc, USB_EN);
285*0885cdb9SSanchayan Maity 
286*0885cdb9SSanchayan Maity 	mdelay(10);
287*0885cdb9SSanchayan Maity 
288*0885cdb9SSanchayan Maity 	return 0;
289*0885cdb9SSanchayan Maity }
290*0885cdb9SSanchayan Maity 
291*0885cdb9SSanchayan Maity static const struct ehci_ops vf_ehci_ops = {
292*0885cdb9SSanchayan Maity 	.init_after_reset = vf_init_after_reset
293*0885cdb9SSanchayan Maity };
294*0885cdb9SSanchayan Maity 
295*0885cdb9SSanchayan Maity static int vf_usb_bind(struct udevice *dev)
296*0885cdb9SSanchayan Maity {
297*0885cdb9SSanchayan Maity 	static int num_controllers;
298*0885cdb9SSanchayan Maity 
299*0885cdb9SSanchayan Maity 	/*
300*0885cdb9SSanchayan Maity 	 * Without this hack, if we return ENODEV for USB Controller 0, on
301*0885cdb9SSanchayan Maity 	 * probe for the next controller, USB Controller 1 will be given a
302*0885cdb9SSanchayan Maity 	 * sequence number of 0. This conflicts with our requirement of
303*0885cdb9SSanchayan Maity 	 * sequence numbers while initialising the peripherals.
304*0885cdb9SSanchayan Maity 	 */
305*0885cdb9SSanchayan Maity 	dev->req_seq = num_controllers;
306*0885cdb9SSanchayan Maity 	num_controllers++;
307*0885cdb9SSanchayan Maity 
308*0885cdb9SSanchayan Maity 	return 0;
309*0885cdb9SSanchayan Maity }
310*0885cdb9SSanchayan Maity 
311*0885cdb9SSanchayan Maity static int ehci_usb_probe(struct udevice *dev)
312*0885cdb9SSanchayan Maity {
313*0885cdb9SSanchayan Maity 	struct usb_platdata *plat = dev_get_platdata(dev);
314*0885cdb9SSanchayan Maity 	struct ehci_vf_priv_data *priv = dev_get_priv(dev);
315*0885cdb9SSanchayan Maity 	struct usb_ehci *ehci = priv->ehci;
316*0885cdb9SSanchayan Maity 	struct ehci_hccr *hccr;
317*0885cdb9SSanchayan Maity 	struct ehci_hcor *hcor;
318*0885cdb9SSanchayan Maity 	int ret;
319*0885cdb9SSanchayan Maity 
320*0885cdb9SSanchayan Maity 	ret = ehci_vf_common_init(ehci, priv->portnr);
321*0885cdb9SSanchayan Maity 	if (ret)
322*0885cdb9SSanchayan Maity 		return ret;
323*0885cdb9SSanchayan Maity 
324*0885cdb9SSanchayan Maity 	if (priv->init_type != plat->init_type)
325*0885cdb9SSanchayan Maity 		return -ENODEV;
326*0885cdb9SSanchayan Maity 
327*0885cdb9SSanchayan Maity 	if (priv->init_type == USB_INIT_HOST) {
328*0885cdb9SSanchayan Maity 		setbits_le32(&ehci->usbmode, CM_HOST);
329*0885cdb9SSanchayan Maity 		writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
330*0885cdb9SSanchayan Maity 		setbits_le32(&ehci->portsc, USB_EN);
331*0885cdb9SSanchayan Maity 	}
332*0885cdb9SSanchayan Maity 
333*0885cdb9SSanchayan Maity 	mdelay(10);
334*0885cdb9SSanchayan Maity 
335*0885cdb9SSanchayan Maity 	hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
336*0885cdb9SSanchayan Maity 	hcor = (struct ehci_hcor *)((uint32_t)hccr +
337*0885cdb9SSanchayan Maity 				HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
338*0885cdb9SSanchayan Maity 
339*0885cdb9SSanchayan Maity 	return ehci_register(dev, hccr, hcor, &vf_ehci_ops, 0, priv->init_type);
340*0885cdb9SSanchayan Maity }
341*0885cdb9SSanchayan Maity 
342*0885cdb9SSanchayan Maity static int ehci_usb_remove(struct udevice *dev)
343*0885cdb9SSanchayan Maity {
344*0885cdb9SSanchayan Maity 	int ret;
345*0885cdb9SSanchayan Maity 
346*0885cdb9SSanchayan Maity 	ret = ehci_deregister(dev);
347*0885cdb9SSanchayan Maity 	if (ret)
348*0885cdb9SSanchayan Maity 		return ret;
349*0885cdb9SSanchayan Maity 
350*0885cdb9SSanchayan Maity 	return 0;
351*0885cdb9SSanchayan Maity }
352*0885cdb9SSanchayan Maity 
353*0885cdb9SSanchayan Maity static const struct udevice_id vf_usb_ids[] = {
354*0885cdb9SSanchayan Maity 	{ .compatible = "fsl,vf610-usb" },
355*0885cdb9SSanchayan Maity 	{ }
356*0885cdb9SSanchayan Maity };
357*0885cdb9SSanchayan Maity 
358*0885cdb9SSanchayan Maity U_BOOT_DRIVER(usb_ehci) = {
359*0885cdb9SSanchayan Maity 	.name = "ehci_vf",
360*0885cdb9SSanchayan Maity 	.id = UCLASS_USB,
361*0885cdb9SSanchayan Maity 	.of_match = vf_usb_ids,
362*0885cdb9SSanchayan Maity 	.bind = vf_usb_bind,
363*0885cdb9SSanchayan Maity 	.probe = ehci_usb_probe,
364*0885cdb9SSanchayan Maity 	.remove = ehci_usb_remove,
365*0885cdb9SSanchayan Maity 	.ops = &ehci_usb_ops,
366*0885cdb9SSanchayan Maity 	.ofdata_to_platdata = vf_usb_ofdata_to_platdata,
367*0885cdb9SSanchayan Maity 	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
368*0885cdb9SSanchayan Maity 	.priv_auto_alloc_size = sizeof(struct ehci_vf_priv_data),
369*0885cdb9SSanchayan Maity 	.flags = DM_FLAG_ALLOC_PRIV_DMA,
370*0885cdb9SSanchayan Maity };
371*0885cdb9SSanchayan Maity #endif
372