xref: /rk3399_rockchip-uboot/drivers/net/ldpaa_eth/ldpaa_eth.c (revision e48df52b69069dac7f00841fc89701604c5f1bef)
1 /*
2  * Copyright (C) 2014 Freescale Semiconductor
3  *
4  * SPDX-License-Identifier:	GPL-2.0+
5  */
6 
7 #include <common.h>
8 #include <asm/io.h>
9 #include <asm/types.h>
10 #include <malloc.h>
11 #include <net.h>
12 #include <hwconfig.h>
13 #include <phy.h>
14 #include <linux/compat.h>
15 
16 #include "ldpaa_eth.h"
17 
18 #undef CONFIG_PHYLIB
19 static int init_phy(struct eth_device *dev)
20 {
21 	/*TODO for external PHY */
22 
23 	return 0;
24 }
25 
26 static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
27 			 const struct dpaa_fd *fd)
28 {
29 	u64 fd_addr;
30 	uint16_t fd_offset;
31 	uint32_t fd_length;
32 	struct ldpaa_fas *fas;
33 	uint32_t status, err;
34 	struct qbman_release_desc releasedesc;
35 	struct qbman_swp *swp = dflt_dpio->sw_portal;
36 
37 	fd_addr = ldpaa_fd_get_addr(fd);
38 	fd_offset = ldpaa_fd_get_offset(fd);
39 	fd_length = ldpaa_fd_get_len(fd);
40 
41 	debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
42 
43 	if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
44 		/* Read the frame annotation status word and check for errors */
45 		fas = (struct ldpaa_fas *)
46 				((uint8_t *)(fd_addr) +
47 				priv->buf_layout.private_data_size);
48 		status = le32_to_cpu(fas->status);
49 		if (status & LDPAA_ETH_RX_ERR_MASK) {
50 			printf("Rx frame error(s): 0x%08x\n",
51 			       status & LDPAA_ETH_RX_ERR_MASK);
52 			goto error;
53 		} else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
54 			printf("Unsupported feature in bitmask: 0x%08x\n",
55 			       status & LDPAA_ETH_RX_UNSUPP_MASK);
56 			goto error;
57 		}
58 	}
59 
60 	debug("Rx frame: To Upper layer\n");
61 	net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
62 				    fd_length);
63 
64 error:
65 	flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
66 	qbman_release_desc_clear(&releasedesc);
67 	qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
68 	do {
69 		/* Release buffer into the QBMAN */
70 		err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
71 	} while (err == -EBUSY);
72 	return;
73 }
74 
75 static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
76 {
77 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
78 	const struct ldpaa_dq *dq;
79 	const struct dpaa_fd *fd;
80 	int i = 5, err = 0, status, loop = 20;
81 	static struct qbman_pull_desc pulldesc;
82 	struct qbman_swp *swp = dflt_dpio->sw_portal;
83 
84 	while (--i) {
85 		qbman_pull_desc_clear(&pulldesc);
86 		qbman_pull_desc_set_numframes(&pulldesc, 1);
87 		qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
88 
89 		err = qbman_swp_pull(swp, &pulldesc);
90 		if (err < 0) {
91 			printf("Dequeue frames error:0x%08x\n", err);
92 			continue;
93 		}
94 
95 		do {
96 			loop--;
97 			dq = qbman_swp_dqrr_next(swp);
98 
99 			if (!loop)
100 				break;
101 		} while (!dq);
102 
103 		if (dq) {
104 			/* Check for valid frame. If not sent a consume
105 			 * confirmation to QBMAN otherwise give it to NADK
106 			 * application and then send consume confirmation to
107 			 * QBMAN.
108 			 */
109 			status = (uint8_t)ldpaa_dq_flags(dq);
110 			if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
111 				debug("Dequeue RX frames:");
112 				debug("No frame delivered\n");
113 
114 				qbman_swp_dqrr_consume(swp, dq);
115 				break;
116 			}
117 
118 			fd = ldpaa_dq_fd(dq);
119 
120 			/* Obtain FD and process it */
121 			ldpaa_eth_rx(priv, fd);
122 			qbman_swp_dqrr_consume(swp, dq);
123 			break;
124 		}
125 	}
126 
127 	return err;
128 }
129 
130 static void ldpaa_eth_tx_conf(struct ldpaa_eth_priv *priv,
131 			      const struct dpaa_fd *fd)
132 {
133 	uint64_t fd_addr;
134 	struct ldpaa_fas *fas;
135 	uint32_t status, err;
136 	struct qbman_release_desc releasedesc;
137 	struct qbman_swp *swp = dflt_dpio->sw_portal;
138 
139 	fd_addr = ldpaa_fd_get_addr(fd);
140 
141 
142 	debug("TX Conf frame:data addr=0x%p\n", (u64 *)fd_addr);
143 
144 	/* Check the status from the Frame Annotation */
145 	if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
146 		fas = (struct ldpaa_fas *)
147 				((uint8_t *)(fd_addr) +
148 				priv->buf_layout.private_data_size);
149 		status = le32_to_cpu(fas->status);
150 		if (status & LDPAA_ETH_TXCONF_ERR_MASK) {
151 			printf("TxConf frame error(s): 0x%08x\n",
152 			       status & LDPAA_ETH_TXCONF_ERR_MASK);
153 		}
154 	}
155 
156 	flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
157 	qbman_release_desc_clear(&releasedesc);
158 	qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
159 	do {
160 		/* Release buffer into the QBMAN */
161 		err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
162 	} while (err == -EBUSY);
163 }
164 
165 static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv)
166 {
167 	const struct ldpaa_dq *dq;
168 	const struct dpaa_fd *fd;
169 	int err = 0;
170 	int i = 5, status, loop = 20;
171 	static struct qbman_pull_desc pulldesc;
172 	struct qbman_swp *swp = dflt_dpio->sw_portal;
173 
174 	while (--i) {
175 		qbman_pull_desc_clear(&pulldesc);
176 		qbman_pull_desc_set_numframes(&pulldesc, 1);
177 		qbman_pull_desc_set_fq(&pulldesc, priv->tx_conf_fqid);
178 
179 		err =  qbman_swp_pull(swp, &pulldesc);
180 		if (err < 0) {
181 			printf("Dequeue TX conf frames error:0x%08x\n", err);
182 			continue;
183 		}
184 
185 		do {
186 			loop--;
187 			dq = qbman_swp_dqrr_next(swp);
188 
189 			if (!loop)
190 				break;
191 		} while (!dq);
192 
193 		if (dq) {
194 			/* Check for valid frame. If not sent a consume
195 			 * confirmation to QBMAN otherwise give it to NADK
196 			 * application and then send consume confirmation to
197 			 * QBMAN.
198 			 */
199 			status = (uint8_t)ldpaa_dq_flags(dq);
200 			if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
201 				debug("Dequeue TX conf frames:");
202 				debug("No frame is delivered\n");
203 
204 				qbman_swp_dqrr_consume(swp, dq);
205 				break;
206 			}
207 			fd = ldpaa_dq_fd(dq);
208 
209 			ldpaa_eth_tx_conf(priv, fd);
210 			qbman_swp_dqrr_consume(swp, dq);
211 			break;
212 		}
213 	}
214 
215 	return err;
216 }
217 
218 static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
219 {
220 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
221 	struct dpaa_fd fd;
222 	u64 buffer_start;
223 	int data_offset, err;
224 	u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
225 	u32 time_start;
226 	struct qbman_swp *swp = dflt_dpio->sw_portal;
227 	struct qbman_eq_desc ed;
228 	struct qbman_release_desc releasedesc;
229 
230 	/* Setup the FD fields */
231 	memset(&fd, 0, sizeof(fd));
232 
233 	data_offset = priv->tx_data_offset;
234 
235 	do {
236 		err = qbman_swp_acquire(dflt_dpio->sw_portal,
237 					dflt_dpbp->dpbp_attr.bpid,
238 					&buffer_start, 1);
239 	} while (err == -EBUSY);
240 
241 	if (err < 0) {
242 		printf("qbman_swp_acquire() failed\n");
243 		return -ENOMEM;
244 	}
245 
246 	debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
247 
248 	memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
249 
250 	flush_dcache_range(buffer_start, buffer_start +
251 					LDPAA_ETH_RX_BUFFER_SIZE);
252 
253 	ldpaa_fd_set_addr(&fd, (u64)buffer_start);
254 	ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
255 	ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
256 	ldpaa_fd_set_len(&fd, len);
257 
258 	fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
259 				LDPAA_FD_CTRL_PTV1;
260 
261 	qbman_eq_desc_clear(&ed);
262 	qbman_eq_desc_set_no_orp(&ed, 0);
263 	qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
264 
265 	time_start = get_timer(0);
266 
267 	while (get_timer(time_start) < timeo) {
268 		err = qbman_swp_enqueue(swp, &ed,
269 				(const struct qbman_fd *)(&fd));
270 		if (err != -EBUSY)
271 			break;
272 	}
273 
274 	if (err < 0) {
275 		printf("error enqueueing Tx frame\n");
276 		goto error;
277 	}
278 
279 	mdelay(1);
280 
281 	err = ldpaa_eth_pull_dequeue_tx_conf(priv);
282 	if (err < 0)
283 		printf("error Tx Conf frame\n");
284 
285 	return err;
286 
287 error:
288 	qbman_release_desc_clear(&releasedesc);
289 	qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
290 	time_start = get_timer(0);
291 	do {
292 		/* Release buffer into the QBMAN */
293 		err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
294 	} while (get_timer(time_start) < timeo && err == -EBUSY);
295 
296 	if (err == -EBUSY)
297 		printf("TX data: QBMAN buffer release fails\n");
298 
299 	return err;
300 }
301 
302 static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
303 {
304 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
305 	struct dpni_queue_attr rx_queue_attr;
306 	struct dpni_tx_flow_attr tx_flow_attr;
307 	uint8_t mac_addr[6];
308 	int err;
309 
310 	if (net_dev->state == ETH_STATE_ACTIVE)
311 		return 0;
312 
313 	/* DPNI initialization */
314 	err = ldpaa_dpni_setup(priv);
315 	if (err < 0)
316 		goto err_dpni_setup;
317 
318 	err = ldpaa_dpbp_setup();
319 	if (err < 0)
320 		goto err_dpbp_setup;
321 
322 	/* DPNI binding DPBP */
323 	err = ldpaa_dpni_bind(priv);
324 	if (err)
325 		goto err_bind;
326 
327 	err = dpni_get_primary_mac_addr(dflt_mc_io, priv->dpni_handle,
328 					mac_addr);
329 	if (err) {
330 		printf("dpni_get_primary_mac_addr() failed\n");
331 		return err;
332 	}
333 
334 	memcpy(net_dev->enetaddr, mac_addr, 0x6);
335 
336 	/* setup the MAC address */
337 	if (net_dev->enetaddr[0] & 0x01) {
338 		printf("%s: MacAddress is multcast address\n",	__func__);
339 		return 1;
340 	}
341 
342 #ifdef CONFIG_PHYLIB
343 	/* TODO Check this path */
344 	err = phy_startup(priv->phydev);
345 	if (err) {
346 		printf("%s: Could not initialize\n", priv->phydev->dev->name);
347 		return err;
348 	}
349 #else
350 	priv->phydev->speed = SPEED_1000;
351 	priv->phydev->link = 1;
352 	priv->phydev->duplex = DUPLEX_FULL;
353 #endif
354 
355 	err = dpni_enable(dflt_mc_io, priv->dpni_handle);
356 	if (err < 0) {
357 		printf("dpni_enable() failed\n");
358 		return err;
359 	}
360 
361 	/* TODO: support multiple Rx flows */
362 	err = dpni_get_rx_flow(dflt_mc_io, priv->dpni_handle, 0, 0,
363 			       &rx_queue_attr);
364 	if (err) {
365 		printf("dpni_get_rx_flow() failed\n");
366 		goto err_rx_flow;
367 	}
368 
369 	priv->rx_dflt_fqid = rx_queue_attr.fqid;
370 
371 	err = dpni_get_qdid(dflt_mc_io, priv->dpni_handle, &priv->tx_qdid);
372 	if (err) {
373 		printf("dpni_get_qdid() failed\n");
374 		goto err_qdid;
375 	}
376 
377 	err = dpni_get_tx_flow(dflt_mc_io, priv->dpni_handle, priv->tx_flow_id,
378 			       &tx_flow_attr);
379 	if (err) {
380 		printf("dpni_get_tx_flow() failed\n");
381 		goto err_tx_flow;
382 	}
383 
384 	priv->tx_conf_fqid = tx_flow_attr.conf_err_attr.queue_attr.fqid;
385 
386 	if (!priv->phydev->link)
387 		printf("%s: No link.\n", priv->phydev->dev->name);
388 
389 	return priv->phydev->link ? 0 : -1;
390 
391 err_tx_flow:
392 err_qdid:
393 err_rx_flow:
394 	dpni_disable(dflt_mc_io, priv->dpni_handle);
395 err_bind:
396 	ldpaa_dpbp_free();
397 err_dpbp_setup:
398 	dpni_close(dflt_mc_io, priv->dpni_handle);
399 err_dpni_setup:
400 	return err;
401 }
402 
403 static void ldpaa_eth_stop(struct eth_device *net_dev)
404 {
405 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
406 	int err = 0;
407 
408 	if ((net_dev->state == ETH_STATE_PASSIVE) ||
409 	    (net_dev->state == ETH_STATE_INIT))
410 		return;
411 	/* Stop Tx and Rx traffic */
412 	err = dpni_disable(dflt_mc_io, priv->dpni_handle);
413 	if (err < 0)
414 		printf("dpni_disable() failed\n");
415 
416 #ifdef CONFIG_PHYLIB
417 	phy_shutdown(priv->phydev);
418 #endif
419 
420 	ldpaa_dpbp_free();
421 	dpni_reset(dflt_mc_io, priv->dpni_handle);
422 	dpni_close(dflt_mc_io, priv->dpni_handle);
423 }
424 
425 static void ldpaa_dpbp_drain_cnt(int count)
426 {
427 	uint64_t buf_array[7];
428 	void *addr;
429 	int ret, i;
430 
431 	BUG_ON(count > 7);
432 
433 	do {
434 		ret = qbman_swp_acquire(dflt_dpio->sw_portal,
435 					dflt_dpbp->dpbp_attr.bpid,
436 					buf_array, count);
437 		if (ret < 0) {
438 			printf("qbman_swp_acquire() failed\n");
439 			return;
440 		}
441 		for (i = 0; i < ret; i++) {
442 			addr = (void *)buf_array[i];
443 			debug("Free: buffer addr =0x%p\n", addr);
444 			free(addr);
445 		}
446 	} while (ret);
447 }
448 
449 static void ldpaa_dpbp_drain(void)
450 {
451 	int i;
452 	for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
453 		ldpaa_dpbp_drain_cnt(7);
454 }
455 
456 static int ldpaa_bp_add_7(uint16_t bpid)
457 {
458 	uint64_t buf_array[7];
459 	u8 *addr;
460 	int i;
461 	struct qbman_release_desc rd;
462 
463 	for (i = 0; i < 7; i++) {
464 		addr = memalign(L1_CACHE_BYTES, LDPAA_ETH_RX_BUFFER_SIZE);
465 		if (!addr) {
466 			printf("addr allocation failed\n");
467 			goto err_alloc;
468 		}
469 		memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
470 		flush_dcache_range((u64)addr,
471 				   (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
472 
473 		buf_array[i] = (uint64_t)addr;
474 		debug("Release: buffer addr =0x%p\n", addr);
475 	}
476 
477 release_bufs:
478 	/* In case the portal is busy, retry until successful.
479 	 * This function is guaranteed to succeed in a reasonable amount
480 	 * of time.
481 	 */
482 
483 	do {
484 		mdelay(1);
485 		qbman_release_desc_clear(&rd);
486 		qbman_release_desc_set_bpid(&rd, bpid);
487 	} while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
488 
489 	return i;
490 
491 err_alloc:
492 	if (i)
493 		goto release_bufs;
494 
495 	return 0;
496 }
497 
498 static int ldpaa_dpbp_seed(uint16_t bpid)
499 {
500 	int i;
501 	int count;
502 
503 	for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
504 		count = ldpaa_bp_add_7(bpid);
505 		if (count < 7)
506 			printf("Buffer Seed= %d\n", count);
507 	}
508 
509 	return 0;
510 }
511 
512 static int ldpaa_dpbp_setup(void)
513 {
514 	int err;
515 
516 	err = dpbp_open(dflt_mc_io, dflt_dpbp->dpbp_attr.id,
517 			&dflt_dpbp->dpbp_handle);
518 	if (err) {
519 		printf("dpbp_open() failed\n");
520 		goto err_open;
521 	}
522 
523 	err = dpbp_enable(dflt_mc_io, dflt_dpbp->dpbp_handle);
524 	if (err) {
525 		printf("dpbp_enable() failed\n");
526 		goto err_enable;
527 	}
528 
529 	err = dpbp_get_attributes(dflt_mc_io, dflt_dpbp->dpbp_handle,
530 				  &dflt_dpbp->dpbp_attr);
531 	if (err) {
532 		printf("dpbp_get_attributes() failed\n");
533 		goto err_get_attr;
534 	}
535 
536 	err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
537 	if (err) {
538 		printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
539 		       dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
540 		goto err_seed;
541 	}
542 
543 	return 0;
544 
545 err_seed:
546 err_get_attr:
547 	dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle);
548 err_enable:
549 	dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle);
550 err_open:
551 	return err;
552 }
553 
554 static void ldpaa_dpbp_free(void)
555 {
556 	ldpaa_dpbp_drain();
557 	dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle);
558 	dpbp_reset(dflt_mc_io, dflt_dpbp->dpbp_handle);
559 	dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle);
560 }
561 
562 static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
563 {
564 	int err;
565 
566 	/* and get a handle for the DPNI this interface is associate with */
567 	err = dpni_open(dflt_mc_io, priv->dpni_id, &priv->dpni_handle);
568 	if (err) {
569 		printf("dpni_open() failed\n");
570 		goto err_open;
571 	}
572 
573 	err = dpni_get_attributes(dflt_mc_io, priv->dpni_handle,
574 				  &priv->dpni_attrs);
575 	if (err) {
576 		printf("dpni_get_attributes() failed (err=%d)\n", err);
577 		goto err_get_attr;
578 	}
579 
580 	/* Configure our buffers' layout */
581 	priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
582 				   DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
583 				   DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
584 	priv->buf_layout.pass_parser_result = true;
585 	priv->buf_layout.pass_frame_status = true;
586 	priv->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
587 	/* ...rx, ... */
588 	err = dpni_set_rx_buffer_layout(dflt_mc_io, priv->dpni_handle,
589 					&priv->buf_layout);
590 	if (err) {
591 		printf("dpni_set_rx_buffer_layout() failed");
592 		goto err_buf_layout;
593 	}
594 
595 	/* ... tx, ... */
596 	priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PARSER_RESULT;
597 	err = dpni_set_tx_buffer_layout(dflt_mc_io, priv->dpni_handle,
598 					&priv->buf_layout);
599 	if (err) {
600 		printf("dpni_set_tx_buffer_layout() failed");
601 		goto err_buf_layout;
602 	}
603 
604 	/* ... tx-confirm. */
605 	priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
606 	err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, priv->dpni_handle,
607 					     &priv->buf_layout);
608 	if (err) {
609 		printf("dpni_set_tx_conf_buffer_layout() failed");
610 		goto err_buf_layout;
611 	}
612 
613 	/* Now that we've set our tx buffer layout, retrieve the minimum
614 	 * required tx data offset.
615 	 */
616 	err = dpni_get_tx_data_offset(dflt_mc_io, priv->dpni_handle,
617 				      &priv->tx_data_offset);
618 	if (err) {
619 		printf("dpni_get_tx_data_offset() failed\n");
620 		goto err_data_offset;
621 	}
622 
623 	/* Warn in case TX data offset is not multiple of 64 bytes. */
624 	WARN_ON(priv->tx_data_offset % 64);
625 
626 	/* Accomodate SWA space. */
627 	priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
628 	debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
629 
630 	return 0;
631 
632 err_data_offset:
633 err_buf_layout:
634 err_get_attr:
635 	dpni_close(dflt_mc_io, priv->dpni_handle);
636 err_open:
637 	return err;
638 }
639 
640 static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
641 {
642 	struct dpni_pools_cfg pools_params;
643 	struct dpni_tx_flow_cfg dflt_tx_flow;
644 	int err = 0;
645 
646 	pools_params.num_dpbp = 1;
647 	pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
648 	pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
649 	err = dpni_set_pools(dflt_mc_io, priv->dpni_handle, &pools_params);
650 	if (err) {
651 		printf("dpni_set_pools() failed\n");
652 		return err;
653 	}
654 
655 	priv->tx_flow_id = DPNI_NEW_FLOW_ID;
656 	memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
657 
658 	err = dpni_set_tx_flow(dflt_mc_io, priv->dpni_handle,
659 			       &priv->tx_flow_id, &dflt_tx_flow);
660 	if (err) {
661 		printf("dpni_set_tx_flow() failed\n");
662 		return err;
663 	}
664 
665 	return 0;
666 }
667 
668 static int ldpaa_eth_netdev_init(struct eth_device *net_dev)
669 {
670 	int err;
671 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
672 
673 	sprintf(net_dev->name, "DPNI%d", priv->dpni_id);
674 
675 	net_dev->iobase = 0;
676 	net_dev->init = ldpaa_eth_open;
677 	net_dev->halt = ldpaa_eth_stop;
678 	net_dev->send = ldpaa_eth_tx;
679 	net_dev->recv = ldpaa_eth_pull_dequeue_rx;
680 /*
681 	TODO: PHY MDIO information
682 	priv->bus = info->bus;
683 	priv->phyaddr = info->phy_addr;
684 	priv->enet_if = info->enet_if;
685 */
686 
687 	if (init_phy(net_dev))
688 		return 0;
689 
690 	err = eth_register(net_dev);
691 	if (err < 0) {
692 		printf("eth_register() = %d\n", err);
693 		return err;
694 	}
695 
696 	return 0;
697 }
698 
699 int ldpaa_eth_init(struct dprc_obj_desc obj_desc)
700 {
701 	struct eth_device		*net_dev = NULL;
702 	struct ldpaa_eth_priv		*priv = NULL;
703 	int				err = 0;
704 
705 
706 	/* Net device */
707 	net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
708 	if (!net_dev) {
709 		printf("eth_device malloc() failed\n");
710 		return -ENOMEM;
711 	}
712 	memset(net_dev, 0, sizeof(struct eth_device));
713 
714 	/* alloc the ldpaa ethernet private struct */
715 	priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
716 	if (!priv) {
717 		printf("ldpaa_eth_priv malloc() failed\n");
718 		return -ENOMEM;
719 	}
720 	memset(priv, 0, sizeof(struct ldpaa_eth_priv));
721 
722 	net_dev->priv = (void *)priv;
723 	priv->net_dev = (struct eth_device *)net_dev;
724 	priv->dpni_id = obj_desc.id;
725 
726 	err = ldpaa_eth_netdev_init(net_dev);
727 	if (err)
728 		goto err_netdev_init;
729 
730 	debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
731 	return 0;
732 
733 err_netdev_init:
734 	free(priv);
735 	net_dev->priv = NULL;
736 	free(net_dev);
737 
738 	return err;
739 }
740