1*3e620e50SAdam Ford // SPDX-License-Identifier: GPL-2.0
2*3e620e50SAdam Ford /*
3*3e620e50SAdam Ford * Texas Instruments da8xx "glue layer"
4*3e620e50SAdam Ford *
5*3e620e50SAdam Ford * Copyright (c) 2019, by Texas Instruments
6*3e620e50SAdam Ford *
7*3e620e50SAdam Ford * Based on the DA8xx "glue layer" code.
8*3e620e50SAdam Ford * Copyright (c) 2008-2019, MontaVista Software, Inc. <source@mvista.com>
9*3e620e50SAdam Ford *
10*3e620e50SAdam Ford * DT support
11*3e620e50SAdam Ford * Copyright (c) 2016 Petr Kulhavy <petr@barix.com>
12*3e620e50SAdam Ford * This file is part of the Inventra Controller Driver for Linux.
13*3e620e50SAdam Ford *
14*3e620e50SAdam Ford */
15*3e620e50SAdam Ford
16*3e620e50SAdam Ford #include <common.h>
17*3e620e50SAdam Ford #include <dm.h>
18*3e620e50SAdam Ford #include <dm/device-internal.h>
19*3e620e50SAdam Ford #include <dm/lists.h>
20*3e620e50SAdam Ford #include <asm/arch/hardware.h>
21*3e620e50SAdam Ford #include <asm/arch/da8xx-usb.h>
22*3e620e50SAdam Ford #include <linux/usb/otg.h>
23*3e620e50SAdam Ford #include <asm/omap_musb.h>
24*3e620e50SAdam Ford #include <generic-phy.h>
25*3e620e50SAdam Ford #include "linux-compat.h"
26*3e620e50SAdam Ford #include "musb_core.h"
27*3e620e50SAdam Ford #include "musb_uboot.h"
28*3e620e50SAdam Ford
29*3e620e50SAdam Ford /* USB 2.0 OTG module registers */
30*3e620e50SAdam Ford #define DA8XX_USB_REVISION_REG 0x00
31*3e620e50SAdam Ford #define DA8XX_USB_CTRL_REG 0x04
32*3e620e50SAdam Ford #define DA8XX_USB_STAT_REG 0x08
33*3e620e50SAdam Ford #define DA8XX_USB_EMULATION_REG 0x0c
34*3e620e50SAdam Ford #define DA8XX_USB_SRP_FIX_TIME_REG 0x18
35*3e620e50SAdam Ford #define DA8XX_USB_INTR_SRC_REG 0x20
36*3e620e50SAdam Ford #define DA8XX_USB_INTR_SRC_SET_REG 0x24
37*3e620e50SAdam Ford #define DA8XX_USB_INTR_SRC_CLEAR_REG 0x28
38*3e620e50SAdam Ford #define DA8XX_USB_INTR_MASK_REG 0x2c
39*3e620e50SAdam Ford #define DA8XX_USB_INTR_MASK_SET_REG 0x30
40*3e620e50SAdam Ford #define DA8XX_USB_INTR_MASK_CLEAR_REG 0x34
41*3e620e50SAdam Ford #define DA8XX_USB_INTR_SRC_MASKED_REG 0x38
42*3e620e50SAdam Ford #define DA8XX_USB_END_OF_INTR_REG 0x3c
43*3e620e50SAdam Ford #define DA8XX_USB_GENERIC_RNDIS_EP_SIZE_REG(n) (0x50 + (((n) - 1) << 2))
44*3e620e50SAdam Ford
45*3e620e50SAdam Ford /* Control register bits */
46*3e620e50SAdam Ford #define DA8XX_SOFT_RESET_MASK 1
47*3e620e50SAdam Ford
48*3e620e50SAdam Ford #define DA8XX_USB_TX_EP_MASK 0x1f /* EP0 + 4 Tx EPs */
49*3e620e50SAdam Ford #define DA8XX_USB_RX_EP_MASK 0x1e /* 4 Rx EPs */
50*3e620e50SAdam Ford
51*3e620e50SAdam Ford /* USB interrupt register bits */
52*3e620e50SAdam Ford #define DA8XX_INTR_USB_SHIFT 16
53*3e620e50SAdam Ford #define DA8XX_INTR_USB_MASK (0x1ff << DA8XX_INTR_USB_SHIFT) /* 8 Mentor */
54*3e620e50SAdam Ford /* interrupts and DRVVBUS interrupt */
55*3e620e50SAdam Ford #define DA8XX_INTR_DRVVBUS 0x100
56*3e620e50SAdam Ford #define DA8XX_INTR_RX_SHIFT 8
57*3e620e50SAdam Ford #define DA8XX_INTR_RX_MASK (DA8XX_USB_RX_EP_MASK << DA8XX_INTR_RX_SHIFT)
58*3e620e50SAdam Ford #define DA8XX_INTR_TX_SHIFT 0
59*3e620e50SAdam Ford #define DA8XX_INTR_TX_MASK (DA8XX_USB_TX_EP_MASK << DA8XX_INTR_TX_SHIFT)
60*3e620e50SAdam Ford
61*3e620e50SAdam Ford #define DA8XX_MENTOR_CORE_OFFSET 0x400
62*3e620e50SAdam Ford
da8xx_musb_interrupt(int irq,void * hci)63*3e620e50SAdam Ford static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
64*3e620e50SAdam Ford {
65*3e620e50SAdam Ford struct musb *musb = hci;
66*3e620e50SAdam Ford void __iomem *reg_base = musb->ctrl_base;
67*3e620e50SAdam Ford unsigned long flags;
68*3e620e50SAdam Ford irqreturn_t ret = IRQ_NONE;
69*3e620e50SAdam Ford u32 status;
70*3e620e50SAdam Ford
71*3e620e50SAdam Ford spin_lock_irqsave(&musb->lock, flags);
72*3e620e50SAdam Ford
73*3e620e50SAdam Ford /*
74*3e620e50SAdam Ford * NOTE: DA8XX shadows the Mentor IRQs. Don't manage them through
75*3e620e50SAdam Ford * the Mentor registers (except for setup), use the TI ones and EOI.
76*3e620e50SAdam Ford */
77*3e620e50SAdam Ford
78*3e620e50SAdam Ford /* Acknowledge and handle non-CPPI interrupts */
79*3e620e50SAdam Ford status = musb_readl(reg_base, DA8XX_USB_INTR_SRC_MASKED_REG);
80*3e620e50SAdam Ford if (!status)
81*3e620e50SAdam Ford goto eoi;
82*3e620e50SAdam Ford
83*3e620e50SAdam Ford musb_writel(reg_base, DA8XX_USB_INTR_SRC_CLEAR_REG, status);
84*3e620e50SAdam Ford dev_dbg(musb->controller, "USB IRQ %08x\n", status);
85*3e620e50SAdam Ford
86*3e620e50SAdam Ford musb->int_rx = (status & DA8XX_INTR_RX_MASK) >> DA8XX_INTR_RX_SHIFT;
87*3e620e50SAdam Ford musb->int_tx = (status & DA8XX_INTR_TX_MASK) >> DA8XX_INTR_TX_SHIFT;
88*3e620e50SAdam Ford musb->int_usb = (status & DA8XX_INTR_USB_MASK) >> DA8XX_INTR_USB_SHIFT;
89*3e620e50SAdam Ford
90*3e620e50SAdam Ford /*
91*3e620e50SAdam Ford * DRVVBUS IRQs are the only proxy we have (a very poor one!) for
92*3e620e50SAdam Ford * DA8xx's missing ID change IRQ. We need an ID change IRQ to
93*3e620e50SAdam Ford * switch appropriately between halves of the OTG state machine.
94*3e620e50SAdam Ford * Managing DEVCTL.Session per Mentor docs requires that we know its
95*3e620e50SAdam Ford * value but DEVCTL.BDevice is invalid without DEVCTL.Session set.
96*3e620e50SAdam Ford * Also, DRVVBUS pulses for SRP (but not at 5 V)...
97*3e620e50SAdam Ford */
98*3e620e50SAdam Ford if (status & (DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT)) {
99*3e620e50SAdam Ford int drvvbus = musb_readl(reg_base, DA8XX_USB_STAT_REG);
100*3e620e50SAdam Ford void __iomem *mregs = musb->mregs;
101*3e620e50SAdam Ford u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
102*3e620e50SAdam Ford int err;
103*3e620e50SAdam Ford
104*3e620e50SAdam Ford err = musb->int_usb & MUSB_INTR_VBUSERROR;
105*3e620e50SAdam Ford if (err) {
106*3e620e50SAdam Ford /*
107*3e620e50SAdam Ford * The Mentor core doesn't debounce VBUS as needed
108*3e620e50SAdam Ford * to cope with device connect current spikes. This
109*3e620e50SAdam Ford * means it's not uncommon for bus-powered devices
110*3e620e50SAdam Ford * to get VBUS errors during enumeration.
111*3e620e50SAdam Ford *
112*3e620e50SAdam Ford * This is a workaround, but newer RTL from Mentor
113*3e620e50SAdam Ford * seems to allow a better one: "re"-starting sessions
114*3e620e50SAdam Ford * without waiting for VBUS to stop registering in
115*3e620e50SAdam Ford * devctl.
116*3e620e50SAdam Ford */
117*3e620e50SAdam Ford musb->int_usb &= ~MUSB_INTR_VBUSERROR;
118*3e620e50SAdam Ford WARNING("VBUS error workaround (delay coming)\n");
119*3e620e50SAdam Ford } else if (drvvbus) {
120*3e620e50SAdam Ford MUSB_HST_MODE(musb);
121*3e620e50SAdam Ford musb->port1_status |= USB_PORT_STAT_POWER;
122*3e620e50SAdam Ford } else if (!(musb->int_usb & MUSB_INTR_BABBLE)) {
123*3e620e50SAdam Ford /*
124*3e620e50SAdam Ford * When babble condition happens, drvvbus interrupt
125*3e620e50SAdam Ford * is also generated. Ignore this drvvbus interrupt
126*3e620e50SAdam Ford * and let babble interrupt handler recovers the
127*3e620e50SAdam Ford * controller; otherwise, the host-mode flag is lost
128*3e620e50SAdam Ford * due to the MUSB_DEV_MODE() call below and babble
129*3e620e50SAdam Ford * recovery logic will not be called.
130*3e620e50SAdam Ford */
131*3e620e50SAdam Ford musb->is_active = 0;
132*3e620e50SAdam Ford MUSB_DEV_MODE(musb);
133*3e620e50SAdam Ford musb->port1_status &= ~USB_PORT_STAT_POWER;
134*3e620e50SAdam Ford }
135*3e620e50SAdam Ford ret = IRQ_HANDLED;
136*3e620e50SAdam Ford }
137*3e620e50SAdam Ford
138*3e620e50SAdam Ford if (musb->int_tx || musb->int_rx || musb->int_usb)
139*3e620e50SAdam Ford ret |= musb_interrupt(musb);
140*3e620e50SAdam Ford eoi:
141*3e620e50SAdam Ford /* EOI needs to be written for the IRQ to be re-asserted. */
142*3e620e50SAdam Ford if (ret == IRQ_HANDLED || status)
143*3e620e50SAdam Ford musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
144*3e620e50SAdam Ford
145*3e620e50SAdam Ford spin_unlock_irqrestore(&musb->lock, flags);
146*3e620e50SAdam Ford
147*3e620e50SAdam Ford return ret;
148*3e620e50SAdam Ford }
149*3e620e50SAdam Ford
da8xx_musb_init(struct musb * musb)150*3e620e50SAdam Ford static int da8xx_musb_init(struct musb *musb)
151*3e620e50SAdam Ford {
152*3e620e50SAdam Ford u32 revision;
153*3e620e50SAdam Ford void __iomem *reg_base = musb->ctrl_base;
154*3e620e50SAdam Ford
155*3e620e50SAdam Ford int ret;
156*3e620e50SAdam Ford
157*3e620e50SAdam Ford /* reset the controller */
158*3e620e50SAdam Ford writel(0x1, &da8xx_usb_regs->control);
159*3e620e50SAdam Ford udelay(50);
160*3e620e50SAdam Ford
161*3e620e50SAdam Ford /* Returns zero if e.g. not clocked */
162*3e620e50SAdam Ford revision = readl(&da8xx_usb_regs->revision);
163*3e620e50SAdam Ford if (revision == 0)
164*3e620e50SAdam Ford return -ENODEV;
165*3e620e50SAdam Ford
166*3e620e50SAdam Ford /* Disable all interrupts */
167*3e620e50SAdam Ford writel((DA8XX_USB_USBINT_MASK | DA8XX_USB_TXINT_MASK |
168*3e620e50SAdam Ford DA8XX_USB_RXINT_MASK), &da8xx_usb_regs->intmsk_set);
169*3e620e50SAdam Ford
170*3e620e50SAdam Ford musb->mregs += DA8XX_MENTOR_CORE_OFFSET;
171*3e620e50SAdam Ford
172*3e620e50SAdam Ford /* NOTE: IRQs are in mixed mode, not bypass to pure MUSB */
173*3e620e50SAdam Ford debug("DA8xx OTG revision %08x, control %02x\n", revision,
174*3e620e50SAdam Ford musb_readb(reg_base, DA8XX_USB_CTRL_REG));
175*3e620e50SAdam Ford
176*3e620e50SAdam Ford musb->isr = da8xx_musb_interrupt;
177*3e620e50SAdam Ford return 0;
178*3e620e50SAdam Ford }
179*3e620e50SAdam Ford
da8xx_musb_exit(struct musb * musb)180*3e620e50SAdam Ford static int da8xx_musb_exit(struct musb *musb)
181*3e620e50SAdam Ford {
182*3e620e50SAdam Ford /* flush any interrupts */
183*3e620e50SAdam Ford writel((DA8XX_USB_USBINT_MASK | DA8XX_USB_TXINT_MASK |
184*3e620e50SAdam Ford DA8XX_USB_RXINT_MASK), &da8xx_usb_regs->intmsk_clr);
185*3e620e50SAdam Ford writel(0, &da8xx_usb_regs->eoi);
186*3e620e50SAdam Ford
187*3e620e50SAdam Ford return 0;
188*3e620e50SAdam Ford }
189*3e620e50SAdam Ford
190*3e620e50SAdam Ford /**
191*3e620e50SAdam Ford * da8xx_musb_enable - enable interrupts
192*3e620e50SAdam Ford */
da8xx_musb_enable(struct musb * musb)193*3e620e50SAdam Ford static int da8xx_musb_enable(struct musb *musb)
194*3e620e50SAdam Ford {
195*3e620e50SAdam Ford void __iomem *reg_base = musb->ctrl_base;
196*3e620e50SAdam Ford u32 mask;
197*3e620e50SAdam Ford
198*3e620e50SAdam Ford /* Workaround: setup IRQs through both register sets. */
199*3e620e50SAdam Ford mask = ((musb->epmask & DA8XX_USB_TX_EP_MASK) << DA8XX_INTR_TX_SHIFT) |
200*3e620e50SAdam Ford ((musb->epmask & DA8XX_USB_RX_EP_MASK) << DA8XX_INTR_RX_SHIFT) |
201*3e620e50SAdam Ford DA8XX_INTR_USB_MASK;
202*3e620e50SAdam Ford musb_writel(reg_base, DA8XX_USB_INTR_MASK_SET_REG, mask);
203*3e620e50SAdam Ford
204*3e620e50SAdam Ford /* Force the DRVVBUS IRQ so we can start polling for ID change. */
205*3e620e50SAdam Ford musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG,
206*3e620e50SAdam Ford DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT);
207*3e620e50SAdam Ford
208*3e620e50SAdam Ford return 0;
209*3e620e50SAdam Ford }
210*3e620e50SAdam Ford
211*3e620e50SAdam Ford /**
212*3e620e50SAdam Ford * da8xx_musb_disable - disable HDRC and flush interrupts
213*3e620e50SAdam Ford */
da8xx_musb_disable(struct musb * musb)214*3e620e50SAdam Ford static void da8xx_musb_disable(struct musb *musb)
215*3e620e50SAdam Ford {
216*3e620e50SAdam Ford void __iomem *reg_base = musb->ctrl_base;
217*3e620e50SAdam Ford
218*3e620e50SAdam Ford musb_writel(reg_base, DA8XX_USB_INTR_MASK_CLEAR_REG,
219*3e620e50SAdam Ford DA8XX_INTR_USB_MASK |
220*3e620e50SAdam Ford DA8XX_INTR_TX_MASK | DA8XX_INTR_RX_MASK);
221*3e620e50SAdam Ford musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0);
222*3e620e50SAdam Ford }
223*3e620e50SAdam Ford
da8xx_musb_reset(struct udevice * dev)224*3e620e50SAdam Ford void da8xx_musb_reset(struct udevice *dev)
225*3e620e50SAdam Ford {
226*3e620e50SAdam Ford void *reg_base = dev_read_addr_ptr(dev);
227*3e620e50SAdam Ford
228*3e620e50SAdam Ford /* Reset the controller */
229*3e620e50SAdam Ford musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK);
230*3e620e50SAdam Ford }
231*3e620e50SAdam Ford
da8xx_musb_clear_irq(struct udevice * dev)232*3e620e50SAdam Ford void da8xx_musb_clear_irq(struct udevice *dev)
233*3e620e50SAdam Ford {
234*3e620e50SAdam Ford /* flush any interrupts */
235*3e620e50SAdam Ford writel((DA8XX_USB_USBINT_MASK | DA8XX_USB_TXINT_MASK |
236*3e620e50SAdam Ford DA8XX_USB_RXINT_MASK), &da8xx_usb_regs->intmsk_clr);
237*3e620e50SAdam Ford writel(0, &da8xx_usb_regs->eoi);
238*3e620e50SAdam Ford }
239*3e620e50SAdam Ford
240*3e620e50SAdam Ford const struct musb_platform_ops da8xx_ops = {
241*3e620e50SAdam Ford .init = da8xx_musb_init,
242*3e620e50SAdam Ford .exit = da8xx_musb_exit,
243*3e620e50SAdam Ford .enable = da8xx_musb_enable,
244*3e620e50SAdam Ford .disable = da8xx_musb_disable,
245*3e620e50SAdam Ford };
246*3e620e50SAdam Ford
247*3e620e50SAdam Ford struct da8xx_musb_platdata {
248*3e620e50SAdam Ford void *base;
249*3e620e50SAdam Ford void *ctrl_mod_base;
250*3e620e50SAdam Ford struct musb_hdrc_platform_data plat;
251*3e620e50SAdam Ford struct musb_hdrc_config musb_config;
252*3e620e50SAdam Ford struct omap_musb_board_data otg_board_data;
253*3e620e50SAdam Ford struct phy phy;
254*3e620e50SAdam Ford };
255*3e620e50SAdam Ford
da8xx_musb_ofdata_to_platdata(struct udevice * dev)256*3e620e50SAdam Ford static int da8xx_musb_ofdata_to_platdata(struct udevice *dev)
257*3e620e50SAdam Ford {
258*3e620e50SAdam Ford struct da8xx_musb_platdata *platdata = dev_get_platdata(dev);
259*3e620e50SAdam Ford const void *fdt = gd->fdt_blob;
260*3e620e50SAdam Ford int node = dev_of_offset(dev);
261*3e620e50SAdam Ford
262*3e620e50SAdam Ford platdata->base = (void *)dev_read_addr_ptr(dev);
263*3e620e50SAdam Ford platdata->musb_config.multipoint = 1;
264*3e620e50SAdam Ford platdata->musb_config.dyn_fifo = 1;
265*3e620e50SAdam Ford platdata->musb_config.num_eps = 5;
266*3e620e50SAdam Ford platdata->musb_config.ram_bits = 10;
267*3e620e50SAdam Ford platdata->plat.power = fdtdec_get_int(fdt, node, "power", 50);
268*3e620e50SAdam Ford platdata->otg_board_data.interface_type = MUSB_INTERFACE_UTMI;
269*3e620e50SAdam Ford platdata->plat.mode = MUSB_HOST;
270*3e620e50SAdam Ford platdata->otg_board_data.dev = dev;
271*3e620e50SAdam Ford platdata->plat.config = &platdata->musb_config;
272*3e620e50SAdam Ford platdata->plat.platform_ops = &da8xx_ops;
273*3e620e50SAdam Ford platdata->plat.board_data = &platdata->otg_board_data;
274*3e620e50SAdam Ford platdata->otg_board_data.clear_irq = da8xx_musb_clear_irq;
275*3e620e50SAdam Ford platdata->otg_board_data.reset = da8xx_musb_reset;
276*3e620e50SAdam Ford return 0;
277*3e620e50SAdam Ford }
278*3e620e50SAdam Ford
da8xx_musb_probe(struct udevice * dev)279*3e620e50SAdam Ford static int da8xx_musb_probe(struct udevice *dev)
280*3e620e50SAdam Ford {
281*3e620e50SAdam Ford struct musb_host_data *host = dev_get_priv(dev);
282*3e620e50SAdam Ford struct da8xx_musb_platdata *platdata = dev_get_platdata(dev);
283*3e620e50SAdam Ford struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
284*3e620e50SAdam Ford struct omap_musb_board_data *otg_board_data;
285*3e620e50SAdam Ford int ret;
286*3e620e50SAdam Ford void *base = dev_read_addr_ptr(dev);
287*3e620e50SAdam Ford
288*3e620e50SAdam Ford /* Get the phy info from the device tree */
289*3e620e50SAdam Ford ret = generic_phy_get_by_name(dev, "usb-phy", &platdata->phy);
290*3e620e50SAdam Ford if (ret)
291*3e620e50SAdam Ford return ret;
292*3e620e50SAdam Ford
293*3e620e50SAdam Ford /* Initialize the phy */
294*3e620e50SAdam Ford ret = generic_phy_init(&platdata->phy);
295*3e620e50SAdam Ford if (ret)
296*3e620e50SAdam Ford return ret;
297*3e620e50SAdam Ford
298*3e620e50SAdam Ford /* enable psc for usb2.0 */
299*3e620e50SAdam Ford lpsc_on(33);
300*3e620e50SAdam Ford
301*3e620e50SAdam Ford /* Enable phy */
302*3e620e50SAdam Ford generic_phy_power_on(&platdata->phy);
303*3e620e50SAdam Ford
304*3e620e50SAdam Ford priv->desc_before_addr = true;
305*3e620e50SAdam Ford otg_board_data = &platdata->otg_board_data;
306*3e620e50SAdam Ford
307*3e620e50SAdam Ford host->host = musb_init_controller(&platdata->plat,
308*3e620e50SAdam Ford (struct device *)otg_board_data,
309*3e620e50SAdam Ford platdata->base);
310*3e620e50SAdam Ford if (!host->host) {
311*3e620e50SAdam Ford ret = -ENODEV;
312*3e620e50SAdam Ford goto shutdown; /* Shutdown what we started */
313*3e620e50SAdam Ford }
314*3e620e50SAdam Ford
315*3e620e50SAdam Ford ret = musb_lowlevel_init(host);
316*3e620e50SAdam Ford
317*3e620e50SAdam Ford if (ret == 0)
318*3e620e50SAdam Ford return 0;
319*3e620e50SAdam Ford shutdown:
320*3e620e50SAdam Ford /* Turn off the phy if we fail */
321*3e620e50SAdam Ford generic_phy_power_off(&platdata->phy);
322*3e620e50SAdam Ford lpsc_disable(33);
323*3e620e50SAdam Ford return ret;
324*3e620e50SAdam Ford }
325*3e620e50SAdam Ford
da8xx_musb_remove(struct udevice * dev)326*3e620e50SAdam Ford static int da8xx_musb_remove(struct udevice *dev)
327*3e620e50SAdam Ford {
328*3e620e50SAdam Ford struct musb_host_data *host = dev_get_priv(dev);
329*3e620e50SAdam Ford
330*3e620e50SAdam Ford musb_stop(host->host);
331*3e620e50SAdam Ford
332*3e620e50SAdam Ford return 0;
333*3e620e50SAdam Ford }
334*3e620e50SAdam Ford
335*3e620e50SAdam Ford static const struct udevice_id da8xx_musb_ids[] = {
336*3e620e50SAdam Ford { .compatible = "ti,da830-musb" },
337*3e620e50SAdam Ford { }
338*3e620e50SAdam Ford };
339*3e620e50SAdam Ford
340*3e620e50SAdam Ford U_BOOT_DRIVER(da8xx_musb) = {
341*3e620e50SAdam Ford .name = "da8xx-musb",
342*3e620e50SAdam Ford .id = UCLASS_USB,
343*3e620e50SAdam Ford .of_match = da8xx_musb_ids,
344*3e620e50SAdam Ford .ofdata_to_platdata = da8xx_musb_ofdata_to_platdata,
345*3e620e50SAdam Ford .probe = da8xx_musb_probe,
346*3e620e50SAdam Ford .remove = da8xx_musb_remove,
347*3e620e50SAdam Ford .ops = &musb_usb_ops,
348*3e620e50SAdam Ford .platdata_auto_alloc_size = sizeof(struct da8xx_musb_platdata),
349*3e620e50SAdam Ford .priv_auto_alloc_size = sizeof(struct musb_host_data),
350*3e620e50SAdam Ford };
351