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