blob: e0356e653fccdf415c41b0a5875cf82c15f03c93 [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 <asm-generic/io.h>
12#include <dm.h>
13#include <dm/device-internal.h>
14#include <dm/lists.h>
15#include <dwc3-uboot.h>
16#include <generic-phy.h>
Simon Glassdbd79542020-05-10 11:40:11 -060017#include <linux/delay.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);
364 if (ret) {
365 clk_free(&priv->clk);
366 return ret;
367 }
368#endif
369
370 return 0;
371}
372
Alexey Romanova9c58e42023-10-05 11:54:28 +0300373static int dwc3_meson_a1_clk_init(struct dwc3_meson_g12a *priv)
374{
375 int ret;
376
377 ret = clk_get_by_name(priv->dev, "usb_bus", &priv->clk);
378 if (ret)
379 return ret;
380
381 ret = clk_enable(&priv->clk);
382 if (ret)
383 return ret;
384
385 return 0;
386}
387
Neil Armstrong1f708892019-02-19 13:42:01 +0100388static int dwc3_meson_g12a_probe(struct udevice *dev)
389{
Simon Glassfa20e932020-12-03 16:55:20 -0700390 struct dwc3_meson_g12a *priv = dev_get_plat(dev);
Alexey Romanova9c58e42023-10-05 11:54:28 +0300391 struct dwc3_meson_g12a_drvdata *data =
392 (struct dwc3_meson_g12a_drvdata *)dev_get_driver_data(dev);
Neil Armstrong1f708892019-02-19 13:42:01 +0100393 int ret, i;
394
Alexey Romanova9c58e42023-10-05 11:54:28 +0300395 priv->drvdata = data;
Neil Armstrong1f708892019-02-19 13:42:01 +0100396 priv->dev = dev;
397
398 ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
399 if (ret)
400 return ret;
401
Alexey Romanova9c58e42023-10-05 11:54:28 +0300402 ret = data->clk_init(priv);
Neil Armstrong1f708892019-02-19 13:42:01 +0100403 if (ret)
404 return ret;
405
406 ret = dwc3_meson_g12a_reset_init(priv);
407 if (ret)
408 return ret;
409
410 ret = dwc3_meson_g12a_get_phys(priv);
411 if (ret)
412 return ret;
413
414#if CONFIG_IS_ENABLED(DM_REGULATOR)
415 ret = device_get_supply_regulator(dev, "vbus-supply",
416 &priv->vbus_supply);
417 if (ret && ret != -ENOENT) {
418 pr_err("Failed to get PHY regulator\n");
419 return ret;
420 }
421
422 if (priv->vbus_supply) {
423 ret = regulator_set_enable(priv->vbus_supply, true);
424 if (ret)
425 return ret;
426 }
427#endif
428
Simon Glassa7ece582020-12-19 10:40:14 -0700429 priv->otg_mode = usb_get_dr_mode(dev_ofnode(dev));
Neil Armstrong1f708892019-02-19 13:42:01 +0100430
431 ret = dwc3_meson_g12a_usb_init(priv);
432 if (ret)
433 return ret;
434
Alexey Romanova9c58e42023-10-05 11:54:28 +0300435 for (i = 0 ; i < data->phy_cnt; ++i) {
Neil Armstrong1f708892019-02-19 13:42:01 +0100436 if (!priv->phys[i].dev)
437 continue;
438
439 ret = generic_phy_init(&priv->phys[i]);
440 if (ret)
441 goto err_phy_init;
442 }
443
Alexey Romanova9c58e42023-10-05 11:54:28 +0300444 for (i = 0; i < data->phy_cnt; ++i) {
Neil Armstronga29def22020-04-21 10:17:42 +0200445 if (!priv->phys[i].dev)
446 continue;
447
448 ret = generic_phy_power_on(&priv->phys[i]);
449 if (ret)
450 goto err_phy_init;
451 }
452
Neil Armstrong1f708892019-02-19 13:42:01 +0100453 return 0;
454
455err_phy_init:
Alexey Romanova9c58e42023-10-05 11:54:28 +0300456 for (i = 0 ; i < data->phy_cnt ; ++i) {
Neil Armstrong1f708892019-02-19 13:42:01 +0100457 if (!priv->phys[i].dev)
458 continue;
459
460 generic_phy_exit(&priv->phys[i]);
461 }
462
463 return ret;
464}
465
466static int dwc3_meson_g12a_remove(struct udevice *dev)
467{
Simon Glassfa20e932020-12-03 16:55:20 -0700468 struct dwc3_meson_g12a *priv = dev_get_plat(dev);
Alexey Romanova9c58e42023-10-05 11:54:28 +0300469 struct dwc3_meson_g12a_drvdata *data = priv->drvdata;
Neil Armstrong1f708892019-02-19 13:42:01 +0100470 int i;
471
472 reset_release_all(&priv->reset, 1);
473
474 clk_release_all(&priv->clk, 1);
475
Alexey Romanova9c58e42023-10-05 11:54:28 +0300476 for (i = 0; i < data->phy_cnt; ++i) {
Neil Armstronga29def22020-04-21 10:17:42 +0200477 if (!priv->phys[i].dev)
478 continue;
479
480 generic_phy_power_off(&priv->phys[i]);
481 }
482
Alexey Romanova9c58e42023-10-05 11:54:28 +0300483 for (i = 0 ; i < data->phy_cnt; ++i) {
Neil Armstrong1f708892019-02-19 13:42:01 +0100484 if (!priv->phys[i].dev)
485 continue;
486
487 generic_phy_exit(&priv->phys[i]);
488 }
489
490 return dm_scan_fdt_dev(dev);
491}
492
Alexey Romanova9c58e42023-10-05 11:54:28 +0300493static const struct dwc3_meson_g12a_drvdata meson_g12a_drvdata = {
494 .phy_names = dwc3_meson_g12a_phy_names,
495 .phy_cnt = ARRAY_SIZE(dwc3_meson_g12a_phy_names),
496 .clk_init = dwc3_meson_g12a_clk_init,
497};
498
499static const struct dwc3_meson_g12a_drvdata meson_a1_drvdata = {
500 .phy_names = dwc3_meson_a1_phy_names,
501 .phy_cnt = ARRAY_SIZE(dwc3_meson_a1_phy_names),
502 .clk_init = dwc3_meson_a1_clk_init,
503};
504
Mattijs Korpershoek9f9828d2022-11-23 16:42:49 +0100505static int dwc3_meson_g12a_child_pre_probe(struct udevice *dev)
506{
507 if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-g12a-usb"))
508 return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_PERIPHERAL);
509
Alexey Romanova9c58e42023-10-05 11:54:28 +0300510 if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-a1-usb"))
511 return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_PERIPHERAL);
512
Mattijs Korpershoek9f9828d2022-11-23 16:42:49 +0100513 return 0;
514}
515
516static int dwc3_meson_g12a_child_post_remove(struct udevice *dev)
517{
518 if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-g12a-usb"))
519 return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_HOST);
520
Alexey Romanova9c58e42023-10-05 11:54:28 +0300521 if (ofnode_device_is_compatible(dev_ofnode(dev), "amlogic,meson-a1-usb"))
522 return dwc3_meson_g12a_force_mode(dev->parent, USB_DR_MODE_HOST);
523
Mattijs Korpershoek9f9828d2022-11-23 16:42:49 +0100524 return 0;
525}
526
Neil Armstrong1f708892019-02-19 13:42:01 +0100527static const struct udevice_id dwc3_meson_g12a_ids[] = {
Alexey Romanova9c58e42023-10-05 11:54:28 +0300528 {
529 .compatible = "amlogic,meson-g12a-usb-ctrl",
530 .data = (ulong)&meson_g12a_drvdata,
531 },
532 {
533 .compatible = "amlogic,meson-a1-usb-ctrl",
534 .data = (ulong)&meson_a1_drvdata,
535 },
Neil Armstrong1f708892019-02-19 13:42:01 +0100536 { }
537};
538
539U_BOOT_DRIVER(dwc3_generic_wrapper) = {
540 .name = "dwc3-meson-g12a",
541 .id = UCLASS_SIMPLE_BUS,
542 .of_match = dwc3_meson_g12a_ids,
543 .probe = dwc3_meson_g12a_probe,
544 .remove = dwc3_meson_g12a_remove,
Mattijs Korpershoek9f9828d2022-11-23 16:42:49 +0100545 .child_pre_probe = dwc3_meson_g12a_child_pre_probe,
546 .child_post_remove = dwc3_meson_g12a_child_post_remove,
Simon Glass71fa5b42020-12-03 16:55:18 -0700547 .plat_auto = sizeof(struct dwc3_meson_g12a),
Neil Armstrong1f708892019-02-19 13:42:01 +0100548
549};