blob: 1a3e9350c46dfe3c3e86cccd747ce6f4e98c7c06 [file] [log] [blame]
Neil Armstrong1f708892019-02-19 13:42:01 +01001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Amlogic G12A DWC3 Glue layer
4 *
5 * Copyright (C) 2019 BayLibre, SAS
6 * Author: Neil Armstrong <narmstrong@baylibre.com>
7 */
8
9#include <common.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Neil Armstrong1f708892019-02-19 13:42:01 +010011#include <dm.h>
12#include <dm/device-internal.h>
13#include <dm/lists.h>
14#include <dwc3-uboot.h>
15#include <generic-phy.h>
Simon Glassdbd79542020-05-10 11:40:11 -060016#include <linux/delay.h>
Igor Prusov89606c02023-11-14 14:02:56 +030017#include <linux/io.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060018#include <linux/printk.h>
Neil Armstrong1f708892019-02-19 13:42:01 +010019#include <linux/usb/ch9.h>
20#include <linux/usb/gadget.h>
21#include <malloc.h>
22#include <regmap.h>
23#include <usb.h>
24#include "core.h"
25#include "gadget.h"
26#include <reset.h>
27#include <clk.h>
28#include <power/regulator.h>
29#include <linux/bitfield.h>
30#include <linux/bitops.h>
31#include <linux/compat.h>
Alexey Romanova9c58e42023-10-05 11:54:28 +030032#include <dt-bindings/clock/amlogic,a1-peripherals-clkc.h>
Neil Armstrong1f708892019-02-19 13:42:01 +010033
34/* USB2 Ports Control Registers */
35
36#define U2P_REG_SIZE 0x20
37
38#define U2P_R0 0x0
39 #define U2P_R0_HOST_DEVICE BIT(0)
40 #define U2P_R0_POWER_OK BIT(1)
41 #define U2P_R0_HAST_MODE BIT(2)
42 #define U2P_R0_POWER_ON_RESET BIT(3)
43 #define U2P_R0_ID_PULLUP BIT(4)
44 #define U2P_R0_DRV_VBUS BIT(5)
45
46#define U2P_R1 0x4
47 #define U2P_R1_PHY_READY BIT(0)
48 #define U2P_R1_ID_DIG BIT(1)
49 #define U2P_R1_OTG_SESSION_VALID BIT(2)
50 #define U2P_R1_VBUS_VALID BIT(3)
51
52/* USB Glue Control Registers */
53
54#define USB_R0 0x80
55 #define USB_R0_P30_LANE0_TX2RX_LOOPBACK BIT(17)
56 #define USB_R0_P30_LANE0_EXT_PCLK_REQ BIT(18)
57 #define USB_R0_P30_PCS_RX_LOS_MASK_VAL_MASK GENMASK(28, 19)
58 #define USB_R0_U2D_SS_SCALEDOWN_MODE_MASK GENMASK(30, 29)
59 #define USB_R0_U2D_ACT BIT(31)
60
61#define USB_R1 0x84
62 #define USB_R1_U3H_BIGENDIAN_GS BIT(0)
63 #define USB_R1_U3H_PME_ENABLE BIT(1)
64 #define USB_R1_U3H_HUB_PORT_OVERCURRENT_MASK GENMASK(4, 2)
65 #define USB_R1_U3H_HUB_PORT_PERM_ATTACH_MASK GENMASK(9, 7)
66 #define USB_R1_U3H_HOST_U2_PORT_DISABLE_MASK GENMASK(13, 12)
67 #define USB_R1_U3H_HOST_U3_PORT_DISABLE BIT(16)
68 #define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT BIT(17)
69 #define USB_R1_U3H_HOST_MSI_ENABLE BIT(18)
70 #define USB_R1_U3H_FLADJ_30MHZ_REG_MASK GENMASK(24, 19)
71 #define USB_R1_P30_PCS_TX_SWING_FULL_MASK GENMASK(31, 25)
72
73#define USB_R2 0x88
74 #define USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK GENMASK(25, 20)
75 #define USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK GENMASK(31, 26)
76
77#define USB_R3 0x8c
78 #define USB_R3_P30_SSC_ENABLE BIT(0)
79 #define USB_R3_P30_SSC_RANGE_MASK GENMASK(3, 1)
80 #define USB_R3_P30_SSC_REF_CLK_SEL_MASK GENMASK(12, 4)
81 #define USB_R3_P30_REF_SSP_EN BIT(13)
82
83#define USB_R4 0x90
84 #define USB_R4_P21_PORT_RESET_0 BIT(0)
85 #define USB_R4_P21_SLEEP_M0 BIT(1)
86 #define USB_R4_MEM_PD_MASK GENMASK(3, 2)
87 #define USB_R4_P21_ONLY BIT(4)
88
89#define USB_R5 0x94
90 #define USB_R5_ID_DIG_SYNC BIT(0)
91 #define USB_R5_ID_DIG_REG BIT(1)
92 #define USB_R5_ID_DIG_CFG_MASK GENMASK(3, 2)
93 #define USB_R5_ID_DIG_EN_0 BIT(4)
94 #define USB_R5_ID_DIG_EN_1 BIT(5)
95 #define USB_R5_ID_DIG_CURR BIT(6)
96 #define USB_R5_ID_DIG_IRQ BIT(7)
97 #define USB_R5_ID_DIG_TH_MASK GENMASK(15, 8)
98 #define USB_R5_ID_DIG_CNT_MASK GENMASK(23, 16)
99
100enum {
101 USB2_HOST_PHY = 0,
102 USB2_OTG_PHY,
103 USB3_HOST_PHY,
104 PHY_COUNT,
105};
106
Alexey Romanova9c58e42023-10-05 11:54:28 +0300107static const char *const dwc3_meson_g12a_phy_names[] = {
Neil Armstrong1f708892019-02-19 13:42:01 +0100108 "usb2-phy0", "usb2-phy1", "usb3-phy0",
109};
110
Alexey Romanova9c58e42023-10-05 11:54:28 +0300111static const char *const dwc3_meson_a1_phy_names[] = {
112 "usb2-phy0", "usb2-phy1"
113};
114
115struct dwc3_meson_g12a;
116
117struct dwc3_meson_g12a_drvdata {
118 const char *const *phy_names;
119 unsigned int phy_cnt;
120 int (*clk_init)(struct dwc3_meson_g12a *priv);
121};
122
Neil Armstrong1f708892019-02-19 13:42:01 +0100123struct dwc3_meson_g12a {
124 struct udevice *dev;
125 struct regmap *regmap;
126 struct clk clk;
127 struct reset_ctl reset;
128 struct phy phys[PHY_COUNT];
129 enum usb_dr_mode otg_mode;
130 enum usb_dr_mode otg_phy_mode;
131 unsigned int usb2_ports;
132 unsigned int usb3_ports;
133#if CONFIG_IS_ENABLED(DM_REGULATOR)
134 struct udevice *vbus_supply;
135#endif
Alexey Romanova9c58e42023-10-05 11:54:28 +0300136 struct dwc3_meson_g12a_drvdata *drvdata;
Neil Armstrong1f708892019-02-19 13:42:01 +0100137};
138
139#define U2P_REG_SIZE 0x20
140#define USB_REG_OFFSET 0x80
141
142static void dwc3_meson_g12a_usb2_set_mode(struct dwc3_meson_g12a *priv,
143 int i, enum usb_dr_mode mode)
144{
145 switch (mode) {
146 case USB_DR_MODE_HOST:
147 case USB_DR_MODE_OTG:
148 case USB_DR_MODE_UNKNOWN:
149 regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
150 U2P_R0_HOST_DEVICE,
151 U2P_R0_HOST_DEVICE);
152 break;
153
154 case USB_DR_MODE_PERIPHERAL:
155 regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
156 U2P_R0_HOST_DEVICE, 0);
157 break;
158 }
159}
160
161static int dwc3_meson_g12a_usb2_init(struct dwc3_meson_g12a *priv)
162{
163 int i;
164
165 if (priv->otg_mode == USB_DR_MODE_PERIPHERAL)
166 priv->otg_phy_mode = USB_DR_MODE_PERIPHERAL;
167 else
168 priv->otg_phy_mode = USB_DR_MODE_HOST;
169
170 for (i = 0 ; i < USB3_HOST_PHY ; ++i) {
171 if (!priv->phys[i].dev)
172 continue;
173
174 regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
175 U2P_R0_POWER_ON_RESET,
176 U2P_R0_POWER_ON_RESET);
177
178 if (i == USB2_OTG_PHY) {
179 regmap_update_bits(priv->regmap,
180 U2P_R0 + (U2P_REG_SIZE * i),
181 U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS,
182 U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS);
183
184 dwc3_meson_g12a_usb2_set_mode(priv, i,
185 priv->otg_phy_mode);
186 } else
187 dwc3_meson_g12a_usb2_set_mode(priv, i,
188 USB_DR_MODE_HOST);
189
190 regmap_update_bits(priv->regmap, U2P_R0 + (U2P_REG_SIZE * i),
191 U2P_R0_POWER_ON_RESET, 0);
192 }
193
194 return 0;
195}
196
197static void dwc3_meson_g12a_usb3_init(struct dwc3_meson_g12a *priv)
198{
199 regmap_update_bits(priv->regmap, USB_R3,
200 USB_R3_P30_SSC_RANGE_MASK |
201 USB_R3_P30_REF_SSP_EN,
202 USB_R3_P30_SSC_ENABLE |
203 FIELD_PREP(USB_R3_P30_SSC_RANGE_MASK, 2) |
204 USB_R3_P30_REF_SSP_EN);
205 udelay(2);
206
207 regmap_update_bits(priv->regmap, USB_R2,
208 USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK,
209 FIELD_PREP(USB_R2_P30_PCS_TX_DEEMPH_3P5DB_MASK, 0x15));
210
211 regmap_update_bits(priv->regmap, USB_R2,
212 USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK,
213 FIELD_PREP(USB_R2_P30_PCS_TX_DEEMPH_6DB_MASK, 0x20));
214
215 udelay(2);
216
217 regmap_update_bits(priv->regmap, USB_R1,
218 USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT,
219 USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT);
220
221 regmap_update_bits(priv->regmap, USB_R1,
222 USB_R1_P30_PCS_TX_SWING_FULL_MASK,
223 FIELD_PREP(USB_R1_P30_PCS_TX_SWING_FULL_MASK, 127));
224}
225
226static void dwc3_meson_g12a_usb_init_mode(struct dwc3_meson_g12a *priv)
227{
228 if (priv->otg_phy_mode == USB_DR_MODE_PERIPHERAL) {
229 regmap_update_bits(priv->regmap, USB_R0,
230 USB_R0_U2D_ACT, USB_R0_U2D_ACT);
231 regmap_update_bits(priv->regmap, USB_R0,
232 USB_R0_U2D_SS_SCALEDOWN_MODE_MASK, 0);
233 regmap_update_bits(priv->regmap, USB_R4,
234 USB_R4_P21_SLEEP_M0, USB_R4_P21_SLEEP_M0);
235 } else {
236 regmap_update_bits(priv->regmap, USB_R0,
237 USB_R0_U2D_ACT, 0);
238 regmap_update_bits(priv->regmap, USB_R4,
239 USB_R4_P21_SLEEP_M0, 0);
240 }
241}
242
243static int dwc3_meson_g12a_usb_init(struct dwc3_meson_g12a *priv)
244{
245 int ret;
246
247 ret = dwc3_meson_g12a_usb2_init(priv);
248 if (ret)
249 return ret;
250
251 regmap_update_bits(priv->regmap, USB_R1,
252 USB_R1_U3H_FLADJ_30MHZ_REG_MASK,
253 FIELD_PREP(USB_R1_U3H_FLADJ_30MHZ_REG_MASK, 0x20));
254
255 regmap_update_bits(priv->regmap, USB_R5,
256 USB_R5_ID_DIG_EN_0,
257 USB_R5_ID_DIG_EN_0);
258 regmap_update_bits(priv->regmap, USB_R5,
259 USB_R5_ID_DIG_EN_1,
260 USB_R5_ID_DIG_EN_1);
261 regmap_update_bits(priv->regmap, USB_R5,
262 USB_R5_ID_DIG_TH_MASK,
263 FIELD_PREP(USB_R5_ID_DIG_TH_MASK, 0xff));
264
265 /* If we have an actual SuperSpeed port, initialize it */
266 if (priv->usb3_ports)
267 dwc3_meson_g12a_usb3_init(priv);
268
269 dwc3_meson_g12a_usb_init_mode(priv);
270
271 return 0;
272}
273
274int dwc3_meson_g12a_force_mode(struct udevice *dev, enum usb_dr_mode mode)
275{
Simon Glassfa20e932020-12-03 16:55:20 -0700276 struct dwc3_meson_g12a *priv = dev_get_plat(dev);
Neil Armstrong1f708892019-02-19 13:42:01 +0100277
278 if (!priv)
279 return -EINVAL;
280
281 if (mode != USB_DR_MODE_HOST && mode != USB_DR_MODE_PERIPHERAL)
282 return -EINVAL;
283
284 if (!priv->phys[USB2_OTG_PHY].dev)
285 return -EINVAL;
286
Neil Armstrong1f708892019-02-19 13:42:01 +0100287 if (mode == USB_DR_MODE_HOST)
288 debug("%s: switching to Host Mode\n", __func__);
289 else
290 debug("%s: switching to Device Mode\n", __func__);
291
292#if CONFIG_IS_ENABLED(DM_REGULATOR)
293 if (priv->vbus_supply) {
294 int ret = regulator_set_enable(priv->vbus_supply,
295 (mode == USB_DR_MODE_PERIPHERAL));
296 if (ret)
297 return ret;
298 }
299#endif
300 priv->otg_phy_mode = mode;
301
302 dwc3_meson_g12a_usb2_set_mode(priv, USB2_OTG_PHY, mode);
303
304 dwc3_meson_g12a_usb_init_mode(priv);
305
306 return 0;
307}
308
309static int dwc3_meson_g12a_get_phys(struct dwc3_meson_g12a *priv)
310{
Alexey Romanova9c58e42023-10-05 11:54:28 +0300311 struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
Neil Armstrong1f708892019-02-19 13:42:01 +0100312 int i, ret;
313
Alexey Romanova9c58e42023-10-05 11:54:28 +0300314 for (i = 0 ; i < data->phy_cnt; ++i) {
315 ret = generic_phy_get_by_name(priv->dev, data->phy_names[i],
Neil Armstrong1f708892019-02-19 13:42:01 +0100316 &priv->phys[i]);
Neil Armstrongf2a1bed2021-05-05 10:38:57 +0200317 if (ret == -ENOENT || ret == -ENODATA)
Neil Armstrong1f708892019-02-19 13:42:01 +0100318 continue;
319
320 if (ret)
321 return ret;
322
323 if (i == USB3_HOST_PHY)
324 priv->usb3_ports++;
325 else
326 priv->usb2_ports++;
327 }
328
329 debug("%s: usb2 ports: %d\n", __func__, priv->usb2_ports);
330 debug("%s: usb3 ports: %d\n", __func__, priv->usb3_ports);
331
332 return 0;
333}
334
335static int dwc3_meson_g12a_reset_init(struct dwc3_meson_g12a *priv)
336{
337 int ret;
338
339 ret = reset_get_by_index(priv->dev, 0, &priv->reset);
340 if (ret)
341 return ret;
342
343 ret = reset_assert(&priv->reset);
344 udelay(1);
345 ret |= reset_deassert(&priv->reset);
346 if (ret) {
347 reset_free(&priv->reset);
348 return ret;
349 }
350
351 return 0;
352}
353
354static int dwc3_meson_g12a_clk_init(struct dwc3_meson_g12a *priv)
355{
356 int ret;
357
358 ret = clk_get_by_index(priv->dev, 0, &priv->clk);
359 if (ret)
360 return ret;
361
362#if CONFIG_IS_ENABLED(CLK)
363 ret = clk_enable(&priv->clk);
Sean Andersond318eb32023-12-16 14:38:42 -0500364 if (ret)
Neil Armstrong1f708892019-02-19 13:42:01 +0100365 return ret;
Neil Armstrong1f708892019-02-19 13:42:01 +0100366#endif
367
368 return 0;
369}
370
Alexey Romanova9c58e42023-10-05 11:54:28 +0300371static int dwc3_meson_a1_clk_init(struct dwc3_meson_g12a *priv)
372{
373 int ret;
374
375 ret = clk_get_by_name(priv->dev, "usb_bus", &priv->clk);
376 if (ret)
377 return ret;
378
379 ret = clk_enable(&priv->clk);
380 if (ret)
381 return ret;
382
383 return 0;
384}
385
Neil Armstrong1f708892019-02-19 13:42:01 +0100386static int dwc3_meson_g12a_probe(struct udevice *dev)
387{
Simon Glassfa20e932020-12-03 16:55:20 -0700388 struct dwc3_meson_g12a *priv = dev_get_plat(dev);
Alexey Romanova9c58e42023-10-05 11:54:28 +0300389 struct dwc3_meson_g12a_drvdata *data =
390 (struct dwc3_meson_g12a_drvdata *)dev_get_driver_data(dev);
Neil Armstrong1f708892019-02-19 13:42:01 +0100391 int ret, i;
392
Alexey Romanova9c58e42023-10-05 11:54:28 +0300393 priv->drvdata = data;
Neil Armstrong1f708892019-02-19 13:42:01 +0100394 priv->dev = dev;
395
396 ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
397 if (ret)
398 return ret;
399
Alexey Romanova9c58e42023-10-05 11:54:28 +0300400 ret = data->clk_init(priv);
Neil Armstrong1f708892019-02-19 13:42:01 +0100401 if (ret)
402 return ret;
403
404 ret = dwc3_meson_g12a_reset_init(priv);
405 if (ret)
406 return ret;
407
408 ret = dwc3_meson_g12a_get_phys(priv);
409 if (ret)
410 return ret;
411
412#if CONFIG_IS_ENABLED(DM_REGULATOR)
413 ret = device_get_supply_regulator(dev, "vbus-supply",
414 &priv->vbus_supply);
415 if (ret && ret != -ENOENT) {
416 pr_err("Failed to get PHY regulator\n");
417 return ret;
418 }
419
420 if (priv->vbus_supply) {
421 ret = regulator_set_enable(priv->vbus_supply, true);
422 if (ret)
423 return ret;
424 }
425#endif
426
Simon Glassa7ece582020-12-19 10:40:14 -0700427 priv->otg_mode = usb_get_dr_mode(dev_ofnode(dev));
Neil Armstrong1f708892019-02-19 13:42:01 +0100428
429 ret = dwc3_meson_g12a_usb_init(priv);
430 if (ret)
431 return ret;
432
Alexey Romanova9c58e42023-10-05 11:54:28 +0300433 for (i = 0 ; i < data->phy_cnt; ++i) {
Neil Armstrong1f708892019-02-19 13:42:01 +0100434 if (!priv->phys[i].dev)
435 continue;
436
437 ret = generic_phy_init(&priv->phys[i]);
438 if (ret)
439 goto err_phy_init;
440 }
441
Alexey Romanova9c58e42023-10-05 11:54:28 +0300442 for (i = 0; i < data->phy_cnt; ++i) {
Neil Armstronga29def22020-04-21 10:17:42 +0200443 if (!priv->phys[i].dev)
444 continue;
445
446 ret = generic_phy_power_on(&priv->phys[i]);
447 if (ret)
448 goto err_phy_init;
449 }
450
Neil Armstrong1f708892019-02-19 13:42:01 +0100451 return 0;
452
453err_phy_init:
Alexey Romanova9c58e42023-10-05 11:54:28 +0300454 for (i = 0 ; i < data->phy_cnt ; ++i) {
Neil Armstrong1f708892019-02-19 13:42:01 +0100455 if (!priv->phys[i].dev)
456 continue;
457
458 generic_phy_exit(&priv->phys[i]);
459 }
460
461 return ret;
462}
463
464static int dwc3_meson_g12a_remove(struct udevice *dev)
465{
Simon Glassfa20e932020-12-03 16:55:20 -0700466 struct dwc3_meson_g12a *priv = dev_get_plat(dev);
Alexey Romanova9c58e42023-10-05 11:54:28 +0300467 struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
Neil Armstrong1f708892019-02-19 13:42:01 +0100468 int i;
469
470 reset_release_all(&priv->reset, 1);
471
472 clk_release_all(&priv->clk, 1);
473
Alexey Romanova9c58e42023-10-05 11:54:28 +0300474 for (i = 0; i < data->phy_cnt; ++i) {
Neil Armstronga29def22020-04-21 10:17:42 +0200475 if (!priv->phys[i].dev)
476 continue;
477
478 generic_phy_power_off(&priv->phys[i]);
479 }
480
Alexey Romanova9c58e42023-10-05 11:54:28 +0300481 for (i = 0 ; i < data->phy_cnt; ++i) {
Neil Armstrong1f708892019-02-19 13:42:01 +0100482 if (!priv->phys[i].dev)
483 continue;
484
485 generic_phy_exit(&priv->phys[i]);
486 }
487
488 return dm_scan_fdt_dev(dev);
489}
490
Alexey Romanova9c58e42023-10-05 11:54:28 +0300491static const struct dwc3_meson_g12a_drvdata meson_g12a_drvdata = {
492 .phy_names = dwc3_meson_g12a_phy_names,
493 .phy_cnt = ARRAY_SIZE(dwc3_meson_g12a_phy_names),
494 .clk_init = dwc3_meson_g12a_clk_init,
495};
496
497static const struct dwc3_meson_g12a_drvdata meson_a1_drvdata = {
498 .phy_names = dwc3_meson_a1_phy_names,
499 .phy_cnt = ARRAY_SIZE(dwc3_meson_a1_phy_names),
500 .clk_init = dwc3_meson_a1_clk_init,
501};
502
Mattijs Korpershoek9f9828d2022-11-23 16:42:49 +0100503static int dwc3_meson_g12a_child_pre_probe(struct udevice *dev)
504{
505 if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-g12a-usb"))
506 return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_PERIPHERAL);
507
Alexey Romanova9c58e42023-10-05 11:54:28 +0300508 if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-a1-usb"))
509 return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_PERIPHERAL);
510
Mattijs Korpershoek9f9828d2022-11-23 16:42:49 +0100511 return 0;
512}
513
514static int dwc3_meson_g12a_child_post_remove(struct udevice *dev)
515{
516 if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-g12a-usb"))
517 return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_HOST);
518
Alexey Romanova9c58e42023-10-05 11:54:28 +0300519 if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-a1-usb"))
520 return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_HOST);
521
Mattijs Korpershoek9f9828d2022-11-23 16:42:49 +0100522 return 0;
523}
524
Neil Armstrong1f708892019-02-19 13:42:01 +0100525static const struct udevice_id dwc3_meson_g12a_ids[] = {
Alexey Romanova9c58e42023-10-05 11:54:28 +0300526 {
527 .compatible = "amlogic,meson-g12a-usb-ctrl",
528 .data = (ulong)&meson_g12a_drvdata,
529 },
530 {
531 .compatible = "amlogic,meson-a1-usb-ctrl",
532 .data = (ulong)&meson_a1_drvdata,
533 },
Neil Armstrong1f708892019-02-19 13:42:01 +0100534 { }
535};
536
537U_BOOT_DRIVER(dwc3_generic_wrapper) = {
538 .name = "dwc3-meson-g12a",
539 .id = UCLASS_SIMPLE_BUS,
540 .of_match = dwc3_meson_g12a_ids,
541 .probe = dwc3_meson_g12a_probe,
542 .remove = dwc3_meson_g12a_remove,
Mattijs Korpershoek9f9828d2022-11-23 16:42:49 +0100543 .child_pre_probe = dwc3_meson_g12a_child_pre_probe,
544 .child_post_remove = dwc3_meson_g12a_child_post_remove,
Simon Glass71fa5b42020-12-03 16:55:18 -0700545 .plat_auto = sizeof(struct dwc3_meson_g12a),
Neil Armstrong1f708892019-02-19 13:42:01 +0100546
547};