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