blob: 2639f96063197c75aca996a68b70574959aa38b3 [file] [log] [blame]
MD Danish Anwardd18b892024-04-04 12:38:02 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Texas Instruments K3 AM65 PRU Ethernet Driver
4 *
5 * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/
6 *
7 */
8
9#include <asm/io.h>
10#include <asm/processor.h>
11#include <clk.h>
12#include <dm/lists.h>
13#include <dm/device.h>
14#include <dma-uclass.h>
15#include <dm/of_access.h>
16#include <dm/pinctrl.h>
17#include <fs_loader.h>
18#include <miiphy.h>
19#include <net.h>
20#include <phy.h>
21#include <power-domain.h>
22#include <linux/soc/ti/ti-udma.h>
23#include <regmap.h>
24#include <remoteproc.h>
25#include <syscon.h>
26#include <soc.h>
27#include <linux/pruss_driver.h>
28#include <dm/device_compat.h>
29
30#include "icssg_prueth.h"
31#include "icss_mii_rt.h"
32
33#define ICSS_SLICE0 0
34#define ICSS_SLICE1 1
35
36#ifdef PKTSIZE_ALIGN
37#define UDMA_RX_BUF_SIZE PKTSIZE_ALIGN
38#else
39#define UDMA_RX_BUF_SIZE ALIGN(PKTSIZE, ARCH_DMA_MINALIGN)
40#endif
41
42#ifdef PKTBUFSRX
43#define UDMA_RX_DESC_NUM PKTBUFSRX
44#else
45#define UDMA_RX_DESC_NUM 4
46#endif
47
48/* Config region lies in shared RAM */
49#define ICSS_CONFIG_OFFSET_SLICE0 0
50#define ICSS_CONFIG_OFFSET_SLICE1 0x8000
51
52/* Firmware flags */
53#define ICSS_SET_RUN_FLAG_VLAN_ENABLE BIT(0) /* switch only */
54#define ICSS_SET_RUN_FLAG_FLOOD_UNICAST BIT(1) /* switch only */
55#define ICSS_SET_RUN_FLAG_PROMISC BIT(2) /* MAC only */
56#define ICSS_SET_RUN_FLAG_MULTICAST_PROMISC BIT(3) /* MAC only */
57
58/* CTRLMMR_ICSSG_RGMII_CTRL register bits */
59#define ICSSG_CTRL_RGMII_ID_MODE BIT(24)
60
61/* Management packet type */
62#define PRUETH_PKT_TYPE_CMD 0x10
63
64/* Number of PRU Cores per Slice */
65#define ICSSG_NUM_PRU_CORES 3
66
67static int icssg_gmii_select(struct prueth_priv *priv)
68{
69 struct phy_device *phydev = priv->phydev;
70
71 if (phydev->interface != PHY_INTERFACE_MODE_MII &&
72 phydev->interface < PHY_INTERFACE_MODE_RGMII &&
73 phydev->interface > PHY_INTERFACE_MODE_RGMII_TXID) {
74 dev_err(priv->dev, "PHY mode unsupported %s\n",
75 phy_string_for_interface(phydev->interface));
76 return -EINVAL;
77 }
78
79 /* AM65 SR2.0 has TX Internal delay always enabled by hardware
80 * and it is not possible to disable TX Internal delay. The below
81 * switch case block describes how we handle different phy modes
82 * based on hardware restriction.
83 */
84 switch (phydev->interface) {
85 case PHY_INTERFACE_MODE_RGMII_ID:
86 phydev->interface = PHY_INTERFACE_MODE_RGMII_RXID;
87 break;
88 case PHY_INTERFACE_MODE_RGMII_TXID:
89 phydev->interface = PHY_INTERFACE_MODE_RGMII;
90 break;
91 case PHY_INTERFACE_MODE_RGMII:
92 case PHY_INTERFACE_MODE_RGMII_RXID:
93 dev_err(priv->dev, "RGMII mode without TX delay is not supported");
94 return -EINVAL;
95 default:
96 break;
97 }
98
99 return 0;
100}
101
102static int icssg_phy_init(struct udevice *dev)
103{
104 struct prueth_priv *priv = dev_get_priv(dev);
105 struct phy_device *phydev;
106 u32 supported = PHY_GBIT_FEATURES;
107 int ret;
108
109 phydev = dm_eth_phy_connect(dev);
110 if (!phydev) {
111 dev_err(dev, "phy_connect() failed\n");
112 return -ENODEV;
113 }
114
115 /* disable unsupported features */
116 supported &= ~(PHY_10BT_FEATURES |
117 SUPPORTED_100baseT_Half |
118 SUPPORTED_1000baseT_Half |
119 SUPPORTED_Pause |
120 SUPPORTED_Asym_Pause);
121
122 phydev->supported &= supported;
123 phydev->advertising = phydev->supported;
124 priv->phydev = phydev;
125
126 ret = icssg_gmii_select(priv);
127 if (ret)
128 goto out;
129
130 ret = phy_config(phydev);
131 if (ret < 0)
132 dev_err(dev, "phy_config() failed: %d", ret);
133out:
134 return ret;
135}
136
137static void icssg_config_set_speed(struct prueth_priv *priv, int speed)
138{
139 struct prueth *prueth = priv->prueth;
140 u8 fw_speed;
141
142 switch (speed) {
143 case SPEED_1000:
144 fw_speed = FW_LINK_SPEED_1G;
145 break;
146 case SPEED_100:
147 fw_speed = FW_LINK_SPEED_100M;
148 break;
149 case SPEED_10:
150 fw_speed = FW_LINK_SPEED_10M;
151 break;
152 default:
153 /* Other links speeds not supported */
154 dev_err(priv->dev, "Unsupported link speed\n");
155 return;
156 }
157
158 writeb(fw_speed, prueth->dram[priv->port_id].pa + PORT_LINK_SPEED_OFFSET);
159}
160
161static int icssg_update_link(struct prueth_priv *priv)
162{
163 struct phy_device *phy = priv->phydev;
164 struct prueth *prueth = priv->prueth;
165 bool gig_en = false, full_duplex = false;
166
167 if (phy->link) { /* link up */
168 if (phy->speed == SPEED_1000)
169 gig_en = true;
170 if (phy->duplex == DUPLEX_FULL)
171 full_duplex = true;
172 /* Set the RGMII cfg for gig en and full duplex */
173 icssg_update_rgmii_cfg(prueth->miig_rt, phy->speed, full_duplex,
174 priv->port_id, priv);
175 /* update the Tx IPG based on 100M/1G speed */
176 icssg_config_ipg(priv, phy->speed, priv->port_id);
177
178 /* Send command to firmware to update Speed setting */
179 icssg_config_set_speed(priv, phy->speed);
180
181 /* Enable PORT FORWARDING */
182 emac_set_port_state(priv, ICSSG_EMAC_PORT_FORWARD);
183
184 printf("link up on port %d, speed %d, %s duplex\n",
185 priv->port_id, phy->speed,
186 (phy->duplex == DUPLEX_FULL) ? "full" : "half");
187 } else {
188 emac_set_port_state(priv, ICSSG_EMAC_PORT_DISABLE);
189 printf("link down on port %d\n", priv->port_id);
190 }
191
192 return phy->link;
193}
194
195struct icssg_firmwares {
196 char *pru;
197 char *rtu;
198 char *txpru;
199};
200
201static struct icssg_firmwares icssg_emac_firmwares[] = {
202 {
203 .pru = "/lib/firmware/ti-pruss/am65x-sr2-pru0-prueth-fw.elf",
204 .rtu = "/lib/firmware/ti-pruss/am65x-sr2-rtu0-prueth-fw.elf",
205 .txpru = "/lib/firmware/ti-pruss/am65x-sr2-txpru0-prueth-fw.elf",
206 },
207 {
208 .pru = "/lib/firmware/ti-pruss/am65x-sr2-pru1-prueth-fw.elf",
209 .rtu = "/lib/firmware/ti-pruss/am65x-sr2-rtu1-prueth-fw.elf",
210 .txpru = "/lib/firmware/ti-pruss/am65x-sr2-txpru1-prueth-fw.elf",
211 }
212};
213
214static int icssg_start_pru_cores(struct udevice *dev)
215{
216 struct prueth_priv *priv = dev_get_priv(dev);
217 struct prueth *prueth = priv->prueth;
218 struct icssg_firmwares *firmwares;
219 struct udevice *rproc_dev = NULL;
220 int ret, slice;
221 u32 phandle;
222 u8 index;
223
224 slice = priv->port_id;
225 index = slice * ICSSG_NUM_PRU_CORES;
226 firmwares = icssg_emac_firmwares;
227
228 ofnode_read_u32_index(dev_ofnode(prueth->dev), "ti,prus", index, &phandle);
229 ret = uclass_get_device_by_phandle_id(UCLASS_REMOTEPROC, phandle, &rproc_dev);
230 if (ret) {
231 dev_err(dev, "Unknown remote processor with phandle '0x%x' requested(%d)\n",
232 phandle, ret);
233 return ret;
234 }
235
236 prueth->pru_core_id = dev_seq(rproc_dev);
237 ret = rproc_set_firmware(rproc_dev, firmwares[slice].pru);
238 if (ret)
239 return ret;
240
241 ret = rproc_boot(rproc_dev);
242 if (ret) {
243 dev_err(dev, "failed to boot PRU%d: %d\n", slice, ret);
244 return -EINVAL;
245 }
246
247 ofnode_read_u32_index(dev_ofnode(prueth->dev), "ti,prus", index + 1, &phandle);
248 ret = uclass_get_device_by_phandle_id(UCLASS_REMOTEPROC, phandle, &rproc_dev);
249 if (ret) {
250 dev_err(dev, "Unknown remote processor with phandle '0x%x' requested(%d)\n",
251 phandle, ret);
252 goto halt_pru;
253 }
254
255 prueth->rtu_core_id = dev_seq(rproc_dev);
256 ret = rproc_set_firmware(rproc_dev, firmwares[slice].rtu);
257 if (ret)
258 goto halt_pru;
259
260 ret = rproc_boot(rproc_dev);
261 if (ret) {
262 dev_err(dev, "failed to boot RTU%d: %d\n", slice, ret);
263 goto halt_pru;
264 }
265
266 ofnode_read_u32_index(dev_ofnode(prueth->dev), "ti,prus", index + 2, &phandle);
267 ret = uclass_get_device_by_phandle_id(UCLASS_REMOTEPROC, phandle, &rproc_dev);
268 if (ret) {
269 dev_err(dev, "Unknown remote processor with phandle '0x%x' requested(%d)\n",
270 phandle, ret);
271 goto halt_rtu;
272 }
273
274 prueth->txpru_core_id = dev_seq(rproc_dev);
275 ret = rproc_set_firmware(rproc_dev, firmwares[slice].txpru);
276 if (ret)
277 goto halt_rtu;
278
279 ret = rproc_boot(rproc_dev);
280 if (ret) {
281 dev_err(dev, "failed to boot TXPRU%d: %d\n", slice, ret);
282 goto halt_rtu;
283 }
284
285 return 0;
286
287halt_rtu:
288 rproc_stop(prueth->rtu_core_id);
289
290halt_pru:
291 rproc_stop(prueth->pru_core_id);
292 return ret;
293}
294
295static int icssg_stop_pru_cores(struct udevice *dev)
296{
297 struct prueth_priv *priv = dev_get_priv(dev);
298 struct prueth *prueth = priv->prueth;
299
300 rproc_stop(prueth->pru_core_id);
301 rproc_stop(prueth->rtu_core_id);
302 rproc_stop(prueth->txpru_core_id);
303
304 return 0;
305}
306
307static int prueth_start(struct udevice *dev)
308{
309 struct ti_udma_drv_chan_cfg_data *dma_rx_cfg_data;
310 struct eth_pdata *pdata = dev_get_plat(dev);
311 struct prueth_priv *priv = dev_get_priv(dev);
312 struct prueth *prueth = priv->prueth;
313 struct icssg_flow_cfg *flow_cfg;
314 u8 *hwaddr = pdata->enetaddr;
315 char chn_name[16];
316 void *config;
317 int ret, i;
318
319 icssg_class_set_mac_addr(prueth->miig_rt, priv->port_id, hwaddr);
320 icssg_ft1_set_mac_addr(prueth->miig_rt, priv->port_id, hwaddr);
321 icssg_class_default(prueth->miig_rt, priv->port_id, 0);
322
323 /* Set Load time configuration */
324 icssg_config(priv);
325
326 ret = icssg_start_pru_cores(dev);
327 if (ret)
328 return ret;
329
330 /* To differentiate channels for SLICE0 vs SLICE1 */
331 snprintf(chn_name, sizeof(chn_name), "tx%d-0", priv->port_id);
332
333 ret = dma_get_by_name(prueth->dev, chn_name, &prueth->dma_tx);
334 if (ret)
335 dev_err(dev, "TX dma get failed %d\n", ret);
336
337 snprintf(chn_name, sizeof(chn_name), "rx%d", priv->port_id);
338 ret = dma_get_by_name(prueth->dev, chn_name, &prueth->dma_rx);
339 if (ret)
340 dev_err(dev, "RX dma get failed %d\n", ret);
341
342 for (i = 0; i < UDMA_RX_DESC_NUM; i++) {
343 ret = dma_prepare_rcv_buf(&prueth->dma_rx,
344 net_rx_packets[i],
345 UDMA_RX_BUF_SIZE);
346 if (ret)
347 dev_err(dev, "RX dma add buf failed %d\n", ret);
348 }
349
350 ret = dma_enable(&prueth->dma_tx);
351 if (ret) {
352 dev_err(dev, "TX dma_enable failed %d\n", ret);
353 goto tx_fail;
354 }
355
356 ret = dma_enable(&prueth->dma_rx);
357 if (ret) {
358 dev_err(dev, "RX dma_enable failed %d\n", ret);
359 goto rx_fail;
360 }
361
362 /* check if the rx_flow_id of dma_rx is as expected since
363 * driver hardcode that value in config struct to firmware
364 * in probe. Just add this sanity check to catch any change
365 * to rx channel assignment in the future.
366 */
367 dma_get_cfg(&prueth->dma_rx, 0, (void **)&dma_rx_cfg_data);
368 config = (void *)(prueth->dram[priv->port_id].pa + ICSSG_CONFIG_OFFSET);
369
370 flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
371 writew(dma_rx_cfg_data->flow_id_base, &flow_cfg->rx_base_flow);
372 writew(0, &flow_cfg->mgm_base_flow);
373
374 dev_info(dev, "K3 ICSSG: rflow_id_base: %u, chn_name = %s\n",
375 dma_rx_cfg_data->flow_id_base, chn_name);
376
MD Danish Anwar6b8c29e2024-04-04 12:38:03 +0530377 ret = emac_fdb_flow_id_updated(priv);
378 if (ret) {
379 dev_err(dev, "Failed to update Rx Flow ID %d", ret);
380 goto phy_fail;
381 }
382
MD Danish Anwardd18b892024-04-04 12:38:02 +0530383 ret = phy_startup(priv->phydev);
384 if (ret) {
385 dev_err(dev, "phy_startup failed\n");
386 goto phy_fail;
387 }
388
389 ret = icssg_update_link(priv);
390 if (!ret) {
391 ret = -ENODEV;
392 goto phy_shut;
393 }
394
395 return 0;
396
397phy_shut:
398 phy_shutdown(priv->phydev);
399phy_fail:
400 dma_disable(&prueth->dma_rx);
401 dma_free(&prueth->dma_rx);
402rx_fail:
403 dma_disable(&prueth->dma_tx);
404 dma_free(&prueth->dma_tx);
405
406tx_fail:
407 icssg_class_disable(prueth->miig_rt, priv->port_id);
408
409 return ret;
410}
411
412static int prueth_send(struct udevice *dev, void *packet, int length)
413{
414 struct prueth_priv *priv = dev_get_priv(dev);
415 struct prueth *prueth = priv->prueth;
416 int ret;
417
418 ret = dma_send(&prueth->dma_tx, packet, length, NULL);
419
420 return ret;
421}
422
423static int prueth_recv(struct udevice *dev, int flags, uchar **packetp)
424{
425 struct prueth_priv *priv = dev_get_priv(dev);
426 struct prueth *prueth = priv->prueth;
427 int ret;
428
429 /* try to receive a new packet */
430 ret = dma_receive(&prueth->dma_rx, (void **)packetp, NULL);
431
432 return ret;
433}
434
435static int prueth_free_pkt(struct udevice *dev, uchar *packet, int length)
436{
437 struct prueth_priv *priv = dev_get_priv(dev);
438 struct prueth *prueth = priv->prueth;
439 int ret = 0;
440
441 if (length > 0) {
442 u32 pkt = prueth->rx_next % UDMA_RX_DESC_NUM;
443
444 dev_dbg(dev, "%s length:%d pkt:%u\n", __func__, length, pkt);
445
446 ret = dma_prepare_rcv_buf(&prueth->dma_rx,
447 net_rx_packets[pkt],
448 UDMA_RX_BUF_SIZE);
449 prueth->rx_next++;
450 }
451
452 return ret;
453}
454
455static void prueth_stop(struct udevice *dev)
456{
457 struct prueth_priv *priv = dev_get_priv(dev);
458 struct prueth *prueth = priv->prueth;
459
460 phy_shutdown(priv->phydev);
461
462 dma_disable(&prueth->dma_tx);
463 dma_disable(&prueth->dma_rx);
464
465 icssg_stop_pru_cores(dev);
466
467 dma_free(&prueth->dma_tx);
468 dma_free(&prueth->dma_rx);
469}
470
471static const struct eth_ops prueth_ops = {
472 .start = prueth_start,
473 .send = prueth_send,
474 .recv = prueth_recv,
475 .free_pkt = prueth_free_pkt,
476 .stop = prueth_stop,
477};
478
479static int icssg_ofdata_parse_phy(struct udevice *dev)
480{
481 struct prueth_priv *priv = dev_get_priv(dev);
482
483 dev_read_u32(dev, "reg", &priv->port_id);
484 priv->phy_interface = dev_read_phy_mode(dev);
485 if (priv->phy_interface == PHY_INTERFACE_MODE_NA) {
486 dev_err(dev, "Invalid PHY mode '%s', port %u\n",
487 phy_string_for_interface(priv->phy_interface),
488 priv->port_id);
489 return -EINVAL;
490 }
491
492 return 0;
493}
494
495static int prueth_port_probe(struct udevice *dev)
496{
497 struct prueth_priv *priv = dev_get_priv(dev);
498 struct prueth *prueth;
499 char portname[15];
500 int ret;
501
502 priv->dev = dev;
503 prueth = dev_get_priv(dev->parent);
504 priv->prueth = prueth;
505
506 sprintf(portname, "%s-%s", dev->parent->name, dev->name);
507
508 device_set_name(dev, portname);
509
510 ret = icssg_ofdata_parse_phy(dev);
511 if (ret)
512 goto out;
513
514 ret = icssg_phy_init(dev);
515 if (ret)
516 goto out;
517
518 ret = pruss_request_mem_region(prueth->pruss,
519 priv->port_id ? PRUSS_MEM_DRAM1 : PRUSS_MEM_DRAM0,
520 &prueth->dram[priv->port_id]);
521 if (ret) {
522 dev_err(dev, "could not request DRAM%d region\n", priv->port_id);
523 return ret;
524 }
525out:
526 return ret;
527}
528
529static int prueth_probe(struct udevice *dev)
530{
531 ofnode node, pruss_node, mdio_node, sram_node, curr_sram_node;
532 struct prueth *prueth = dev_get_priv(dev);
533 u32 phandle, err, sp, prev_end_addr;
534 struct udevice **prussdev = NULL;
535 ofnode eth_ports_node, eth_node;
536 struct udevice *port_dev;
537 int ret = 0;
538
539 prueth->dev = dev;
540
541 err = ofnode_read_u32(dev_ofnode(dev), "ti,prus", &phandle);
542 if (err)
543 return err;
544
545 node = ofnode_get_by_phandle(phandle);
546 if (!ofnode_valid(node))
547 return -EINVAL;
548
549 pruss_node = ofnode_get_parent(node);
550 ret = device_get_global_by_ofnode(pruss_node, prussdev);
551 if (ret)
552 dev_err(dev, "error getting the pruss dev\n");
553 prueth->pruss = *prussdev;
554
555 ret = pruss_request_mem_region(*prussdev, PRUSS_MEM_SHRD_RAM2,
556 &prueth->shram);
557 if (ret)
558 return ret;
559
560 ret = pruss_request_tm_region(*prussdev, &prueth->tmaddr);
561 if (ret)
562 return ret;
563
564 prueth->miig_rt = syscon_regmap_lookup_by_phandle(dev, "ti,mii-g-rt");
565 if (!prueth->miig_rt) {
566 dev_err(dev, "couldn't get mii-g-rt syscon regmap\n");
567 return -ENODEV;
568 }
569
570 prueth->mii_rt = syscon_regmap_lookup_by_phandle(dev, "ti,mii-rt");
571 if (!prueth->mii_rt) {
572 dev_err(dev, "couldn't get mii-rt syscon regmap\n");
573 return -ENODEV;
574 }
575
576 ret = ofnode_read_u32(dev_ofnode(dev), "sram", &sp);
577 if (ret) {
578 dev_err(dev, "sram node fetch failed %d\n", ret);
579 return ret;
580 }
581
582 sram_node = ofnode_get_by_phandle(sp);
583 if (!ofnode_valid(sram_node))
584 return -EINVAL;
585
586 prev_end_addr = ofnode_get_addr(sram_node);
587
588 ofnode_for_each_subnode(curr_sram_node, sram_node) {
589 u32 start_addr, size, end_addr, avail;
590 const char *name;
591
592 name = ofnode_get_name(curr_sram_node);
593 start_addr = ofnode_get_addr(curr_sram_node);
594 size = ofnode_get_size(curr_sram_node);
595 end_addr = start_addr + size;
596 avail = start_addr - prev_end_addr;
597
598 if (avail > MSMC_RAM_SIZE)
599 break;
600
601 prev_end_addr = end_addr;
602 }
603
604 prueth->sram_pa = prev_end_addr;
605 if (prueth->sram_pa % SZ_64K != 0) {
606 /* This is constraint for SR2.0 firmware */
607 dev_err(dev, "sram address needs to be 64KB aligned\n");
608 return -EINVAL;
609 }
610 dev_dbg(dev, "sram: addr %x size %x\n", prueth->sram_pa, MSMC_RAM_SIZE);
611
612 mdio_node = ofnode_find_subnode(pruss_node, "mdio");
613 prueth->mdio_base = ofnode_get_addr(mdio_node);
614 ofnode_read_u32(mdio_node, "bus_freq", &prueth->mdio_freq);
615
616 ret = clk_get_by_name_nodev(mdio_node, "fck", &prueth->mdiofck);
617 if (ret) {
618 dev_err(dev, "failed to get clock %d\n", ret);
619 return ret;
620 }
621
622 ret = clk_enable(&prueth->mdiofck);
623 if (ret) {
624 dev_err(dev, "clk_enable failed %d\n", ret);
625 return ret;
626 }
627
628 eth_ports_node = dev_read_subnode(dev, "ethernet-ports");
629 if (!ofnode_valid(eth_ports_node))
630 return -ENOENT;
631
632 ofnode_for_each_subnode(eth_node, eth_ports_node) {
633 const char *node_name;
634 u32 port_id;
635 bool disabled;
636
637 node_name = ofnode_get_name(eth_node);
638 disabled = !ofnode_is_enabled(eth_node);
639 ret = ofnode_read_u32(eth_node, "reg", &port_id);
640 if (ret)
641 dev_err(dev, "%s: error reading port_id (%d)\n", node_name, ret);
642
643 if (port_id >= PRUETH_NUM_MACS) {
644 dev_err(dev, "%s: invalid port_id (%d)\n", node_name, port_id);
645 return -EINVAL;
646 }
647
648 if (port_id < 0)
649 continue;
650 if (disabled)
651 continue;
652
653 ret = device_bind_driver_to_node(dev, "prueth_port",
654 ofnode_get_name(eth_node),
655 eth_node, &port_dev);
656 if (ret) {
657 dev_err(dev, "Failed to bind to %s node\n", ofnode_get_name(eth_node));
658 goto out;
659 }
660 }
661
662 return 0;
663out:
664 clk_disable(&prueth->mdiofck);
665
666 return ret;
667}
668
669static const struct udevice_id prueth_ids[] = {
670 { .compatible = "ti,am654-icssg-prueth" },
671 { .compatible = "ti,am642-icssg-prueth" },
672 { }
673};
674
675U_BOOT_DRIVER(prueth) = {
676 .name = "prueth",
677 .id = UCLASS_MISC,
678 .of_match = prueth_ids,
679 .probe = prueth_probe,
680 .priv_auto = sizeof(struct prueth),
681};
682
683U_BOOT_DRIVER(prueth_port) = {
684 .name = "prueth_port",
685 .id = UCLASS_ETH,
686 .probe = prueth_port_probe,
687 .ops = &prueth_ops,
688 .priv_auto = sizeof(struct prueth_priv),
689 .plat_auto = sizeof(struct eth_pdata),
690 .flags = DM_FLAG_ALLOC_PRIV_DMA,
691};