xref: /openbmc/u-boot/drivers/usb/host/ehci-vf.c (revision 67cf22cbdef8c62ffa28b4caf935825fe410c68d)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2a94bb7a4SSanchayan Maity /*
3a94bb7a4SSanchayan Maity  * Copyright (c) 2015 Sanchayan Maity <sanchayan.maity@toradex.com>
4a94bb7a4SSanchayan Maity  * Copyright (C) 2015 Toradex AG
5a94bb7a4SSanchayan Maity  *
6a94bb7a4SSanchayan Maity  * Based on ehci-mx6 driver
7a94bb7a4SSanchayan Maity  */
8a94bb7a4SSanchayan Maity 
9a94bb7a4SSanchayan Maity #include <common.h>
100885cdb9SSanchayan Maity #include <dm.h>
11a94bb7a4SSanchayan Maity #include <usb.h>
12a94bb7a4SSanchayan Maity #include <errno.h>
13a94bb7a4SSanchayan Maity #include <linux/compiler.h>
14a94bb7a4SSanchayan Maity #include <asm/io.h>
150885cdb9SSanchayan Maity #include <asm-generic/gpio.h>
16a94bb7a4SSanchayan Maity #include <asm/arch/clock.h>
17a94bb7a4SSanchayan Maity #include <asm/arch/imx-regs.h>
18a94bb7a4SSanchayan Maity #include <asm/arch/crm_regs.h>
19552a848eSStefano Babic #include <asm/mach-imx/iomux-v3.h>
20552a848eSStefano Babic #include <asm/mach-imx/regs-usbphy.h>
21e162c6b1SMateusz Kulikowski #include <usb/ehci-ci.h>
22b08c8c48SMasahiro Yamada #include <linux/libfdt.h>
230885cdb9SSanchayan Maity #include <fdtdec.h>
24a94bb7a4SSanchayan Maity 
25a94bb7a4SSanchayan Maity #include "ehci.h"
26a94bb7a4SSanchayan Maity 
27a94bb7a4SSanchayan Maity #define USB_NC_REG_OFFSET				0x00000800
28a94bb7a4SSanchayan Maity 
29a94bb7a4SSanchayan Maity #define ANADIG_PLL_CTRL_EN_USB_CLKS		(1 << 6)
30a94bb7a4SSanchayan Maity 
31a94bb7a4SSanchayan Maity #define UCTRL_OVER_CUR_POL	(1 << 8) /* OTG Polarity of Overcurrent */
32a94bb7a4SSanchayan Maity #define UCTRL_OVER_CUR_DIS	(1 << 7) /* Disable OTG Overcurrent Detection */
33a94bb7a4SSanchayan Maity 
34a94bb7a4SSanchayan Maity /* USBCMD */
35a94bb7a4SSanchayan Maity #define UCMD_RUN_STOP		(1 << 0) /* controller run/stop */
36a94bb7a4SSanchayan Maity #define UCMD_RESET			(1 << 1) /* controller reset */
37a94bb7a4SSanchayan Maity 
380885cdb9SSanchayan Maity DECLARE_GLOBAL_DATA_PTR;
390885cdb9SSanchayan Maity 
40a94bb7a4SSanchayan Maity static const unsigned phy_bases[] = {
41a94bb7a4SSanchayan Maity 	USB_PHY0_BASE_ADDR,
42a94bb7a4SSanchayan Maity 	USB_PHY1_BASE_ADDR,
43a94bb7a4SSanchayan Maity };
44a94bb7a4SSanchayan Maity 
45a94bb7a4SSanchayan Maity static const unsigned nc_reg_bases[] = {
46a94bb7a4SSanchayan Maity 	USBC0_BASE_ADDR,
47a94bb7a4SSanchayan Maity 	USBC1_BASE_ADDR,
48a94bb7a4SSanchayan Maity };
49a94bb7a4SSanchayan Maity 
usb_internal_phy_clock_gate(int index)50a94bb7a4SSanchayan Maity static void usb_internal_phy_clock_gate(int index)
51a94bb7a4SSanchayan Maity {
52a94bb7a4SSanchayan Maity 	void __iomem *phy_reg;
53a94bb7a4SSanchayan Maity 
54a94bb7a4SSanchayan Maity 	phy_reg = (void __iomem *)phy_bases[index];
55a94bb7a4SSanchayan Maity 	clrbits_le32(phy_reg + USBPHY_CTRL, USBPHY_CTRL_CLKGATE);
56a94bb7a4SSanchayan Maity }
57a94bb7a4SSanchayan Maity 
usb_power_config(int index)58a94bb7a4SSanchayan Maity static void usb_power_config(int index)
59a94bb7a4SSanchayan Maity {
60a94bb7a4SSanchayan Maity 	struct anadig_reg __iomem *anadig =
61a94bb7a4SSanchayan Maity 		(struct anadig_reg __iomem *)ANADIG_BASE_ADDR;
62a94bb7a4SSanchayan Maity 	void __iomem *pll_ctrl;
63a94bb7a4SSanchayan Maity 
64a94bb7a4SSanchayan Maity 	switch (index) {
65a94bb7a4SSanchayan Maity 	case 0:
66a94bb7a4SSanchayan Maity 		pll_ctrl = &anadig->pll3_ctrl;
67a94bb7a4SSanchayan Maity 		clrbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_BYPASS);
68a94bb7a4SSanchayan Maity 		setbits_le32(pll_ctrl, ANADIG_PLL3_CTRL_ENABLE
69a94bb7a4SSanchayan Maity 			 | ANADIG_PLL3_CTRL_POWERDOWN
70a94bb7a4SSanchayan Maity 			 | ANADIG_PLL_CTRL_EN_USB_CLKS);
71a94bb7a4SSanchayan Maity 		break;
72a94bb7a4SSanchayan Maity 	case 1:
73a94bb7a4SSanchayan Maity 		pll_ctrl = &anadig->pll7_ctrl;
74a94bb7a4SSanchayan Maity 		clrbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_BYPASS);
75a94bb7a4SSanchayan Maity 		setbits_le32(pll_ctrl, ANADIG_PLL7_CTRL_ENABLE
76a94bb7a4SSanchayan Maity 			 | ANADIG_PLL7_CTRL_POWERDOWN
77a94bb7a4SSanchayan Maity 			 | ANADIG_PLL_CTRL_EN_USB_CLKS);
78a94bb7a4SSanchayan Maity 		break;
79a94bb7a4SSanchayan Maity 	default:
80a94bb7a4SSanchayan Maity 		return;
81a94bb7a4SSanchayan Maity 	}
82a94bb7a4SSanchayan Maity }
83a94bb7a4SSanchayan Maity 
usb_phy_enable(int index,struct usb_ehci * ehci)84a94bb7a4SSanchayan Maity static void usb_phy_enable(int index, struct usb_ehci *ehci)
85a94bb7a4SSanchayan Maity {
86a94bb7a4SSanchayan Maity 	void __iomem *phy_reg;
87a94bb7a4SSanchayan Maity 	void __iomem *phy_ctrl;
88a94bb7a4SSanchayan Maity 	void __iomem *usb_cmd;
89a94bb7a4SSanchayan Maity 
90a94bb7a4SSanchayan Maity 	phy_reg = (void __iomem *)phy_bases[index];
91a94bb7a4SSanchayan Maity 	phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL);
92a94bb7a4SSanchayan Maity 	usb_cmd = (void __iomem *)&ehci->usbcmd;
93a94bb7a4SSanchayan Maity 
94a94bb7a4SSanchayan Maity 	/* Stop then Reset */
95a94bb7a4SSanchayan Maity 	clrbits_le32(usb_cmd, UCMD_RUN_STOP);
96a94bb7a4SSanchayan Maity 	while (readl(usb_cmd) & UCMD_RUN_STOP)
97a94bb7a4SSanchayan Maity 		;
98a94bb7a4SSanchayan Maity 
99a94bb7a4SSanchayan Maity 	setbits_le32(usb_cmd, UCMD_RESET);
100a94bb7a4SSanchayan Maity 	while (readl(usb_cmd) & UCMD_RESET)
101a94bb7a4SSanchayan Maity 		;
102a94bb7a4SSanchayan Maity 
103a94bb7a4SSanchayan Maity 	/* Reset USBPHY module */
104a94bb7a4SSanchayan Maity 	setbits_le32(phy_ctrl, USBPHY_CTRL_SFTRST);
105a94bb7a4SSanchayan Maity 	udelay(10);
106a94bb7a4SSanchayan Maity 
107a94bb7a4SSanchayan Maity 	/* Remove CLKGATE and SFTRST */
108a94bb7a4SSanchayan Maity 	clrbits_le32(phy_ctrl, USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST);
109a94bb7a4SSanchayan Maity 	udelay(10);
110a94bb7a4SSanchayan Maity 
111a94bb7a4SSanchayan Maity 	/* Power up the PHY */
112a94bb7a4SSanchayan Maity 	writel(0, phy_reg + USBPHY_PWD);
113a94bb7a4SSanchayan Maity 
114a94bb7a4SSanchayan Maity 	/* Enable FS/LS device */
115a94bb7a4SSanchayan Maity 	setbits_le32(phy_ctrl, USBPHY_CTRL_ENUTMILEVEL2 |
116a94bb7a4SSanchayan Maity 		 USBPHY_CTRL_ENUTMILEVEL3);
117a94bb7a4SSanchayan Maity }
118a94bb7a4SSanchayan Maity 
usb_oc_config(int index)119a94bb7a4SSanchayan Maity static void usb_oc_config(int index)
120a94bb7a4SSanchayan Maity {
121a94bb7a4SSanchayan Maity 	void __iomem *ctrl;
122a94bb7a4SSanchayan Maity 
123a94bb7a4SSanchayan Maity 	ctrl = (void __iomem *)(nc_reg_bases[index] + USB_NC_REG_OFFSET);
124a94bb7a4SSanchayan Maity 
125a94bb7a4SSanchayan Maity 	setbits_le32(ctrl, UCTRL_OVER_CUR_POL);
126a94bb7a4SSanchayan Maity 	setbits_le32(ctrl, UCTRL_OVER_CUR_DIS);
127a94bb7a4SSanchayan Maity }
128a94bb7a4SSanchayan Maity 
board_usb_phy_mode(int port)12908c11cb5SSanchayan Maity int __weak board_usb_phy_mode(int port)
13008c11cb5SSanchayan Maity {
13108c11cb5SSanchayan Maity 	return 0;
13208c11cb5SSanchayan Maity }
13308c11cb5SSanchayan Maity 
board_ehci_hcd_init(int port)13460ed2864SSanchayan Maity int __weak board_ehci_hcd_init(int port)
13560ed2864SSanchayan Maity {
13660ed2864SSanchayan Maity 	return 0;
13760ed2864SSanchayan Maity }
13860ed2864SSanchayan Maity 
ehci_vf_common_init(struct usb_ehci * ehci,int index)1390885cdb9SSanchayan Maity int ehci_vf_common_init(struct usb_ehci *ehci, int index)
1400885cdb9SSanchayan Maity {
1410885cdb9SSanchayan Maity 	int ret;
1420885cdb9SSanchayan Maity 
1430885cdb9SSanchayan Maity 	/* Do board specific initialisation */
1440885cdb9SSanchayan Maity 	ret = board_ehci_hcd_init(index);
1450885cdb9SSanchayan Maity 	if (ret)
1460885cdb9SSanchayan Maity 		return ret;
1470885cdb9SSanchayan Maity 
1480885cdb9SSanchayan Maity 	usb_power_config(index);
1490885cdb9SSanchayan Maity 	usb_oc_config(index);
1500885cdb9SSanchayan Maity 	usb_internal_phy_clock_gate(index);
1510885cdb9SSanchayan Maity 	usb_phy_enable(index, ehci);
1520885cdb9SSanchayan Maity 
1530885cdb9SSanchayan Maity 	return 0;
1540885cdb9SSanchayan Maity }
1550885cdb9SSanchayan Maity 
156*fd09c205SSven Schwermer #if !CONFIG_IS_ENABLED(DM_USB)
ehci_hcd_init(int index,enum usb_init_type init,struct ehci_hccr ** hccr,struct ehci_hcor ** hcor)157a94bb7a4SSanchayan Maity int ehci_hcd_init(int index, enum usb_init_type init,
158a94bb7a4SSanchayan Maity 		struct ehci_hccr **hccr, struct ehci_hcor **hcor)
159a94bb7a4SSanchayan Maity {
160a94bb7a4SSanchayan Maity 	struct usb_ehci *ehci;
16108c11cb5SSanchayan Maity 	enum usb_init_type type;
1620885cdb9SSanchayan Maity 	int ret;
163a94bb7a4SSanchayan Maity 
164a94bb7a4SSanchayan Maity 	if (index >= ARRAY_SIZE(nc_reg_bases))
165a94bb7a4SSanchayan Maity 		return -EINVAL;
166a94bb7a4SSanchayan Maity 
167a94bb7a4SSanchayan Maity 	ehci = (struct usb_ehci *)nc_reg_bases[index];
168a94bb7a4SSanchayan Maity 
1690885cdb9SSanchayan Maity 	ret = ehci_vf_common_init(index);
1700885cdb9SSanchayan Maity 	if (ret)
1710885cdb9SSanchayan Maity 		return ret;
172a94bb7a4SSanchayan Maity 
173a94bb7a4SSanchayan Maity 	*hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
174a94bb7a4SSanchayan Maity 	*hcor = (struct ehci_hcor *)((uint32_t)*hccr +
175a94bb7a4SSanchayan Maity 			HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
176a94bb7a4SSanchayan Maity 
17708c11cb5SSanchayan Maity 	type = board_usb_phy_mode(index);
17808c11cb5SSanchayan Maity 	if (type != init)
17908c11cb5SSanchayan Maity 		return -ENODEV;
18008c11cb5SSanchayan Maity 
181a94bb7a4SSanchayan Maity 	if (init == USB_INIT_DEVICE) {
182a94bb7a4SSanchayan Maity 		setbits_le32(&ehci->usbmode, CM_DEVICE);
183a94bb7a4SSanchayan Maity 		writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
184a94bb7a4SSanchayan Maity 		setbits_le32(&ehci->portsc, USB_EN);
185a94bb7a4SSanchayan Maity 	} else if (init == USB_INIT_HOST) {
186a94bb7a4SSanchayan Maity 		setbits_le32(&ehci->usbmode, CM_HOST);
187a94bb7a4SSanchayan Maity 		writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
188a94bb7a4SSanchayan Maity 		setbits_le32(&ehci->portsc, USB_EN);
189a94bb7a4SSanchayan Maity 	}
190a94bb7a4SSanchayan Maity 
191a94bb7a4SSanchayan Maity 	return 0;
192a94bb7a4SSanchayan Maity }
193a94bb7a4SSanchayan Maity 
ehci_hcd_stop(int index)194a94bb7a4SSanchayan Maity int ehci_hcd_stop(int index)
195a94bb7a4SSanchayan Maity {
196a94bb7a4SSanchayan Maity 	return 0;
197a94bb7a4SSanchayan Maity }
1980885cdb9SSanchayan Maity #else
1990885cdb9SSanchayan Maity /* Possible port types (dual role mode) */
2000885cdb9SSanchayan Maity enum dr_mode {
2010885cdb9SSanchayan Maity 	DR_MODE_NONE = 0,
2020885cdb9SSanchayan Maity 	DR_MODE_HOST,		/* supports host operation */
2030885cdb9SSanchayan Maity 	DR_MODE_DEVICE,		/* supports device operation */
2040885cdb9SSanchayan Maity 	DR_MODE_OTG,		/* supports both */
2050885cdb9SSanchayan Maity };
2060885cdb9SSanchayan Maity 
2070885cdb9SSanchayan Maity struct ehci_vf_priv_data {
2080885cdb9SSanchayan Maity 	struct ehci_ctrl ctrl;
2090885cdb9SSanchayan Maity 	struct usb_ehci *ehci;
2100885cdb9SSanchayan Maity 	struct gpio_desc cdet_gpio;
2110885cdb9SSanchayan Maity 	enum usb_init_type init_type;
2120885cdb9SSanchayan Maity 	enum dr_mode dr_mode;
2130885cdb9SSanchayan Maity 	u32 portnr;
2140885cdb9SSanchayan Maity };
2150885cdb9SSanchayan Maity 
vf_usb_ofdata_to_platdata(struct udevice * dev)2160885cdb9SSanchayan Maity static int vf_usb_ofdata_to_platdata(struct udevice *dev)
2170885cdb9SSanchayan Maity {
2180885cdb9SSanchayan Maity 	struct ehci_vf_priv_data *priv = dev_get_priv(dev);
2190885cdb9SSanchayan Maity 	const void *dt_blob = gd->fdt_blob;
220e160f7d4SSimon Glass 	int node = dev_of_offset(dev);
2210885cdb9SSanchayan Maity 	const char *mode;
2220885cdb9SSanchayan Maity 
2230885cdb9SSanchayan Maity 	priv->portnr = dev->seq;
2240885cdb9SSanchayan Maity 
225a821c4afSSimon Glass 	priv->ehci = (struct usb_ehci *)devfdt_get_addr(dev);
2260885cdb9SSanchayan Maity 	mode = fdt_getprop(dt_blob, node, "dr_mode", NULL);
2270885cdb9SSanchayan Maity 	if (mode) {
2280885cdb9SSanchayan Maity 		if (0 == strcmp(mode, "host")) {
2290885cdb9SSanchayan Maity 			priv->dr_mode = DR_MODE_HOST;
2300885cdb9SSanchayan Maity 			priv->init_type = USB_INIT_HOST;
2310885cdb9SSanchayan Maity 		} else if (0 == strcmp(mode, "peripheral")) {
2320885cdb9SSanchayan Maity 			priv->dr_mode = DR_MODE_DEVICE;
2330885cdb9SSanchayan Maity 			priv->init_type = USB_INIT_DEVICE;
2340885cdb9SSanchayan Maity 		} else if (0 == strcmp(mode, "otg")) {
2350885cdb9SSanchayan Maity 			priv->dr_mode = DR_MODE_OTG;
2360885cdb9SSanchayan Maity 			/*
2370885cdb9SSanchayan Maity 			 * We set init_type to device by default when OTG
2380885cdb9SSanchayan Maity 			 * mode is requested. If a valid gpio is provided
2390885cdb9SSanchayan Maity 			 * we will switch the init_type based on the state
2400885cdb9SSanchayan Maity 			 * of the gpio pin.
2410885cdb9SSanchayan Maity 			 */
2420885cdb9SSanchayan Maity 			priv->init_type = USB_INIT_DEVICE;
2430885cdb9SSanchayan Maity 		} else {
2440885cdb9SSanchayan Maity 			debug("%s: Cannot decode dr_mode '%s'\n",
2450885cdb9SSanchayan Maity 			      __func__, mode);
2460885cdb9SSanchayan Maity 			return -EINVAL;
2470885cdb9SSanchayan Maity 		}
2480885cdb9SSanchayan Maity 	} else {
2490885cdb9SSanchayan Maity 		priv->dr_mode = DR_MODE_HOST;
2500885cdb9SSanchayan Maity 		priv->init_type = USB_INIT_HOST;
2510885cdb9SSanchayan Maity 	}
2520885cdb9SSanchayan Maity 
2530885cdb9SSanchayan Maity 	if (priv->dr_mode == DR_MODE_OTG) {
254150c5afeSSimon Glass 		gpio_request_by_name_nodev(offset_to_ofnode(node),
255150c5afeSSimon Glass 					   "fsl,cdet-gpio", 0, &priv->cdet_gpio,
256150c5afeSSimon Glass 					   GPIOD_IS_IN);
2570885cdb9SSanchayan Maity 		if (dm_gpio_is_valid(&priv->cdet_gpio)) {
2580885cdb9SSanchayan Maity 			if (dm_gpio_get_value(&priv->cdet_gpio))
2590885cdb9SSanchayan Maity 				priv->init_type = USB_INIT_DEVICE;
2600885cdb9SSanchayan Maity 			else
2610885cdb9SSanchayan Maity 				priv->init_type = USB_INIT_HOST;
2620885cdb9SSanchayan Maity 		}
2630885cdb9SSanchayan Maity 	}
2640885cdb9SSanchayan Maity 
2650885cdb9SSanchayan Maity 	return 0;
2660885cdb9SSanchayan Maity }
2670885cdb9SSanchayan Maity 
vf_init_after_reset(struct ehci_ctrl * dev)2680885cdb9SSanchayan Maity static int vf_init_after_reset(struct ehci_ctrl *dev)
2690885cdb9SSanchayan Maity {
2700885cdb9SSanchayan Maity 	struct ehci_vf_priv_data *priv = dev->priv;
2710885cdb9SSanchayan Maity 	enum usb_init_type type = priv->init_type;
2720885cdb9SSanchayan Maity 	struct usb_ehci *ehci = priv->ehci;
2730885cdb9SSanchayan Maity 	int ret;
2740885cdb9SSanchayan Maity 
2750885cdb9SSanchayan Maity 	ret = ehci_vf_common_init(priv->ehci, priv->portnr);
2760885cdb9SSanchayan Maity 	if (ret)
2770885cdb9SSanchayan Maity 		return ret;
2780885cdb9SSanchayan Maity 
2790885cdb9SSanchayan Maity 	if (type == USB_INIT_DEVICE)
2800885cdb9SSanchayan Maity 		return 0;
2810885cdb9SSanchayan Maity 
2820885cdb9SSanchayan Maity 	setbits_le32(&ehci->usbmode, CM_HOST);
2830885cdb9SSanchayan Maity 	writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
2840885cdb9SSanchayan Maity 	setbits_le32(&ehci->portsc, USB_EN);
2850885cdb9SSanchayan Maity 
2860885cdb9SSanchayan Maity 	mdelay(10);
2870885cdb9SSanchayan Maity 
2880885cdb9SSanchayan Maity 	return 0;
2890885cdb9SSanchayan Maity }
2900885cdb9SSanchayan Maity 
2910885cdb9SSanchayan Maity static const struct ehci_ops vf_ehci_ops = {
2920885cdb9SSanchayan Maity 	.init_after_reset = vf_init_after_reset
2930885cdb9SSanchayan Maity };
2940885cdb9SSanchayan Maity 
vf_usb_bind(struct udevice * dev)2950885cdb9SSanchayan Maity static int vf_usb_bind(struct udevice *dev)
2960885cdb9SSanchayan Maity {
2970885cdb9SSanchayan Maity 	static int num_controllers;
2980885cdb9SSanchayan Maity 
2990885cdb9SSanchayan Maity 	/*
3000885cdb9SSanchayan Maity 	 * Without this hack, if we return ENODEV for USB Controller 0, on
3010885cdb9SSanchayan Maity 	 * probe for the next controller, USB Controller 1 will be given a
3020885cdb9SSanchayan Maity 	 * sequence number of 0. This conflicts with our requirement of
3030885cdb9SSanchayan Maity 	 * sequence numbers while initialising the peripherals.
3040885cdb9SSanchayan Maity 	 */
3050885cdb9SSanchayan Maity 	dev->req_seq = num_controllers;
3060885cdb9SSanchayan Maity 	num_controllers++;
3070885cdb9SSanchayan Maity 
3080885cdb9SSanchayan Maity 	return 0;
3090885cdb9SSanchayan Maity }
3100885cdb9SSanchayan Maity 
ehci_usb_probe(struct udevice * dev)3110885cdb9SSanchayan Maity static int ehci_usb_probe(struct udevice *dev)
3120885cdb9SSanchayan Maity {
3130885cdb9SSanchayan Maity 	struct usb_platdata *plat = dev_get_platdata(dev);
3140885cdb9SSanchayan Maity 	struct ehci_vf_priv_data *priv = dev_get_priv(dev);
3150885cdb9SSanchayan Maity 	struct usb_ehci *ehci = priv->ehci;
3160885cdb9SSanchayan Maity 	struct ehci_hccr *hccr;
3170885cdb9SSanchayan Maity 	struct ehci_hcor *hcor;
3180885cdb9SSanchayan Maity 	int ret;
3190885cdb9SSanchayan Maity 
3200885cdb9SSanchayan Maity 	ret = ehci_vf_common_init(ehci, priv->portnr);
3210885cdb9SSanchayan Maity 	if (ret)
3220885cdb9SSanchayan Maity 		return ret;
3230885cdb9SSanchayan Maity 
3240885cdb9SSanchayan Maity 	if (priv->init_type != plat->init_type)
3250885cdb9SSanchayan Maity 		return -ENODEV;
3260885cdb9SSanchayan Maity 
3270885cdb9SSanchayan Maity 	if (priv->init_type == USB_INIT_HOST) {
3280885cdb9SSanchayan Maity 		setbits_le32(&ehci->usbmode, CM_HOST);
3290885cdb9SSanchayan Maity 		writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc);
3300885cdb9SSanchayan Maity 		setbits_le32(&ehci->portsc, USB_EN);
3310885cdb9SSanchayan Maity 	}
3320885cdb9SSanchayan Maity 
3330885cdb9SSanchayan Maity 	mdelay(10);
3340885cdb9SSanchayan Maity 
3350885cdb9SSanchayan Maity 	hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
3360885cdb9SSanchayan Maity 	hcor = (struct ehci_hcor *)((uint32_t)hccr +
3370885cdb9SSanchayan Maity 				HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
3380885cdb9SSanchayan Maity 
3390885cdb9SSanchayan Maity 	return ehci_register(dev, hccr, hcor, &vf_ehci_ops, 0, priv->init_type);
3400885cdb9SSanchayan Maity }
3410885cdb9SSanchayan Maity 
3420885cdb9SSanchayan Maity static const struct udevice_id vf_usb_ids[] = {
3430885cdb9SSanchayan Maity 	{ .compatible = "fsl,vf610-usb" },
3440885cdb9SSanchayan Maity 	{ }
3450885cdb9SSanchayan Maity };
3460885cdb9SSanchayan Maity 
3470885cdb9SSanchayan Maity U_BOOT_DRIVER(usb_ehci) = {
3480885cdb9SSanchayan Maity 	.name = "ehci_vf",
3490885cdb9SSanchayan Maity 	.id = UCLASS_USB,
3500885cdb9SSanchayan Maity 	.of_match = vf_usb_ids,
3510885cdb9SSanchayan Maity 	.bind = vf_usb_bind,
3520885cdb9SSanchayan Maity 	.probe = ehci_usb_probe,
35399e2df47SMasahiro Yamada 	.remove = ehci_deregister,
3540885cdb9SSanchayan Maity 	.ops = &ehci_usb_ops,
3550885cdb9SSanchayan Maity 	.ofdata_to_platdata = vf_usb_ofdata_to_platdata,
3560885cdb9SSanchayan Maity 	.platdata_auto_alloc_size = sizeof(struct usb_platdata),
3570885cdb9SSanchayan Maity 	.priv_auto_alloc_size = sizeof(struct ehci_vf_priv_data),
3580885cdb9SSanchayan Maity 	.flags = DM_FLAG_ALLOC_PRIV_DMA,
3590885cdb9SSanchayan Maity };
3600885cdb9SSanchayan Maity #endif
361