• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2014-2016 Freescale Semiconductor, Inc.
4  * Copyright 2017 NXP
5  */
6 
7 #include <common.h>
8 #include <cpu_func.h>
9 #include <asm/io.h>
10 #include <asm/types.h>
11 #include <malloc.h>
12 #include <net.h>
13 #include <hwconfig.h>
14 #include <phy.h>
15 #include <linux/compat.h>
16 #include <fsl-mc/fsl_dpmac.h>
17 
18 #include <fsl-mc/ldpaa_wriop.h>
19 #include "ldpaa_eth.h"
20 
21 #ifdef CONFIG_PHYLIB
init_phy(struct eth_device * dev)22 static int init_phy(struct eth_device *dev)
23 {
24 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
25 	struct phy_device *phydev = NULL;
26 	struct mii_dev *bus;
27 	int phy_addr, phy_num;
28 	int ret = 0;
29 
30 	bus = wriop_get_mdio(priv->dpmac_id);
31 	if (bus == NULL)
32 		return 0;
33 
34 	for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
35 		phy_addr = wriop_get_phy_address(priv->dpmac_id, phy_num);
36 		if (phy_addr < 0)
37 			continue;
38 
39 		phydev = phy_connect(bus, phy_addr, dev,
40 				     wriop_get_enet_if(priv->dpmac_id));
41 		if (!phydev) {
42 			printf("Failed to connect\n");
43 			ret = -ENODEV;
44 			break;
45 		}
46 		wriop_set_phy_dev(priv->dpmac_id, phy_num, phydev);
47 		ret = phy_config(phydev);
48 		if (ret)
49 			break;
50 	}
51 
52 	if (ret) {
53 		for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
54 			phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
55 			if (!phydev)
56 				continue;
57 
58 			free(phydev);
59 			wriop_set_phy_dev(priv->dpmac_id, phy_num, NULL);
60 		}
61 	}
62 
63 	return ret;
64 }
65 #endif
66 
67 #ifdef DEBUG
68 
69 #define DPNI_STATS_PER_PAGE 6
70 
71 static const char *dpni_statistics[][DPNI_STATS_PER_PAGE] = {
72 	{
73 	"DPNI_CNT_ING_ALL_FRAMES",
74 	"DPNI_CNT_ING_ALL_BYTES",
75 	"DPNI_CNT_ING_MCAST_FRAMES",
76 	"DPNI_CNT_ING_MCAST_BYTES",
77 	"DPNI_CNT_ING_BCAST_FRAMES",
78 	"DPNI_CNT_ING_BCAST_BYTES",
79 	}, {
80 	"DPNI_CNT_EGR_ALL_FRAMES",
81 	"DPNI_CNT_EGR_ALL_BYTES",
82 	"DPNI_CNT_EGR_MCAST_FRAMES",
83 	"DPNI_CNT_EGR_MCAST_BYTES",
84 	"DPNI_CNT_EGR_BCAST_FRAMES",
85 	"DPNI_CNT_EGR_BCAST_BYTES",
86 	}, {
87 	"DPNI_CNT_ING_FILTERED_FRAMES",
88 	"DPNI_CNT_ING_DISCARDED_FRAMES",
89 	"DPNI_CNT_ING_NOBUFFER_DISCARDS",
90 	"DPNI_CNT_EGR_DISCARDED_FRAMES",
91 	"DPNI_CNT_EGR_CNF_FRAMES",
92 	""
93 	},
94 };
95 
print_dpni_stats(const char * strings[],struct dpni_statistics dpni_stats)96 static void print_dpni_stats(const char *strings[],
97 			     struct dpni_statistics dpni_stats)
98 {
99 	uint64_t *stat;
100 	int i;
101 
102 	stat = (uint64_t *)&dpni_stats;
103 	for (i = 0; i < DPNI_STATS_PER_PAGE; i++) {
104 		if (strcmp(strings[i], "\0") == 0)
105 			break;
106 		printf("%s= %llu\n", strings[i], *stat);
107 		stat++;
108 	}
109 }
110 
ldpaa_eth_get_dpni_counter(void)111 static void ldpaa_eth_get_dpni_counter(void)
112 {
113 	int err = 0;
114 	unsigned int page = 0;
115 	struct dpni_statistics dpni_stats;
116 
117 	printf("DPNI counters ..\n");
118 	for (page = 0; page < 3; page++) {
119 		err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS,
120 					  dflt_dpni->dpni_handle, page,
121 					  &dpni_stats);
122 		if (err < 0) {
123 			printf("dpni_get_statistics: failed:");
124 			printf("%d for page[%d]\n", err, page);
125 			return;
126 		}
127 		print_dpni_stats(dpni_statistics[page], dpni_stats);
128 	}
129 }
130 
ldpaa_eth_get_dpmac_counter(struct eth_device * net_dev)131 static void ldpaa_eth_get_dpmac_counter(struct eth_device *net_dev)
132 {
133 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
134 	int err = 0;
135 	u64 value;
136 
137 	err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
138 		     priv->dpmac_handle,
139 		     DPMAC_CNT_ING_BYTE,
140 		     &value);
141 	if (err < 0) {
142 		printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
143 		return;
144 	}
145 	printf("\nDPMAC counters ..\n");
146 	printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
147 
148 	err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
149 		     priv->dpmac_handle,
150 		     DPMAC_CNT_ING_FRAME_DISCARD,
151 		     &value);
152 	if (err < 0) {
153 		printf("dpmac_get_counter: DPMAC_CNT_ING_FRAME_DISCARD failed\n");
154 		return;
155 	}
156 	printf("DPMAC_CNT_ING_FRAME_DISCARD=%lld\n", value);
157 
158 	err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
159 		     priv->dpmac_handle,
160 		     DPMAC_CNT_ING_ALIGN_ERR,
161 		     &value);
162 	if (err < 0) {
163 		printf("dpmac_get_counter: DPMAC_CNT_ING_ALIGN_ERR failed\n");
164 		return;
165 	}
166 	printf("DPMAC_CNT_ING_ALIGN_ERR =%lld\n", value);
167 
168 	err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
169 		     priv->dpmac_handle,
170 		     DPMAC_CNT_ING_BYTE,
171 		     &value);
172 	if (err < 0) {
173 		printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
174 		return;
175 	}
176 	printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
177 
178 	err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
179 		     priv->dpmac_handle,
180 		     DPMAC_CNT_ING_ERR_FRAME,
181 		     &value);
182 	if (err < 0) {
183 		printf("dpmac_get_counter: DPMAC_CNT_ING_ERR_FRAME failed\n");
184 		return;
185 	}
186 	printf("DPMAC_CNT_ING_ERR_FRAME=%lld\n", value);
187 
188 	err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
189 		     priv->dpmac_handle,
190 		     DPMAC_CNT_EGR_BYTE ,
191 		     &value);
192 	if (err < 0) {
193 		printf("dpmac_get_counter: DPMAC_CNT_EGR_BYTE failed\n");
194 		return;
195 	}
196 	printf("DPMAC_CNT_EGR_BYTE =%lld\n", value);
197 
198 	err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
199 		     priv->dpmac_handle,
200 		     DPMAC_CNT_EGR_ERR_FRAME ,
201 		     &value);
202 	if (err < 0) {
203 		printf("dpmac_get_counter: DPMAC_CNT_EGR_ERR_FRAME failed\n");
204 		return;
205 	}
206 	printf("DPMAC_CNT_EGR_ERR_FRAME =%lld\n", value);
207 }
208 #endif
209 
ldpaa_eth_rx(struct ldpaa_eth_priv * priv,const struct dpaa_fd * fd)210 static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
211 			 const struct dpaa_fd *fd)
212 {
213 	u64 fd_addr;
214 	uint16_t fd_offset;
215 	uint32_t fd_length;
216 	struct ldpaa_fas *fas;
217 	uint32_t status, err;
218 	u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
219 	u32 time_start;
220 	struct qbman_release_desc releasedesc;
221 	struct qbman_swp *swp = dflt_dpio->sw_portal;
222 
223 	fd_addr = ldpaa_fd_get_addr(fd);
224 	fd_offset = ldpaa_fd_get_offset(fd);
225 	fd_length = ldpaa_fd_get_len(fd);
226 
227 	debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
228 
229 	if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
230 		/* Read the frame annotation status word and check for errors */
231 		fas = (struct ldpaa_fas *)
232 				((uint8_t *)(fd_addr) +
233 				dflt_dpni->buf_layout.private_data_size);
234 		status = le32_to_cpu(fas->status);
235 		if (status & LDPAA_ETH_RX_ERR_MASK) {
236 			printf("Rx frame error(s): 0x%08x\n",
237 			       status & LDPAA_ETH_RX_ERR_MASK);
238 			goto error;
239 		} else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
240 			printf("Unsupported feature in bitmask: 0x%08x\n",
241 			       status & LDPAA_ETH_RX_UNSUPP_MASK);
242 			goto error;
243 		}
244 	}
245 
246 	debug("Rx frame: To Upper layer\n");
247 	net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
248 				    fd_length);
249 
250 error:
251 	flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
252 	qbman_release_desc_clear(&releasedesc);
253 	qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
254 	time_start = get_timer(0);
255 	do {
256 		/* Release buffer into the QBMAN */
257 		err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
258 	} while (get_timer(time_start) < timeo && err == -EBUSY);
259 
260 	if (err == -EBUSY)
261 		printf("Rx frame: QBMAN buffer release fails\n");
262 
263 	return;
264 }
265 
ldpaa_eth_pull_dequeue_rx(struct eth_device * dev)266 static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
267 {
268 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
269 	const struct ldpaa_dq *dq;
270 	const struct dpaa_fd *fd;
271 	int i = 5, err = 0, status;
272 	u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
273 	u32 time_start;
274 	static struct qbman_pull_desc pulldesc;
275 	struct qbman_swp *swp = dflt_dpio->sw_portal;
276 
277 	while (--i) {
278 		qbman_pull_desc_clear(&pulldesc);
279 		qbman_pull_desc_set_numframes(&pulldesc, 1);
280 		qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
281 
282 		err = qbman_swp_pull(swp, &pulldesc);
283 		if (err < 0) {
284 			printf("Dequeue frames error:0x%08x\n", err);
285 			continue;
286 		}
287 
288 		time_start = get_timer(0);
289 
290 		 do {
291 			dq = qbman_swp_dqrr_next(swp);
292 		} while (get_timer(time_start) < timeo && !dq);
293 
294 		if (dq) {
295 			/* Check for valid frame. If not sent a consume
296 			 * confirmation to QBMAN otherwise give it to NADK
297 			 * application and then send consume confirmation to
298 			 * QBMAN.
299 			 */
300 			status = (uint8_t)ldpaa_dq_flags(dq);
301 			if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
302 				debug("Dequeue RX frames:");
303 				debug("No frame delivered\n");
304 
305 				qbman_swp_dqrr_consume(swp, dq);
306 				continue;
307 			}
308 
309 			fd = ldpaa_dq_fd(dq);
310 
311 			/* Obtain FD and process it */
312 			ldpaa_eth_rx(priv, fd);
313 			qbman_swp_dqrr_consume(swp, dq);
314 			break;
315 		} else {
316 			err = -ENODATA;
317 			debug("No DQRR entries\n");
318 			break;
319 		}
320 	}
321 
322 	return err;
323 }
324 
ldpaa_eth_tx(struct eth_device * net_dev,void * buf,int len)325 static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
326 {
327 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
328 	struct dpaa_fd fd;
329 	u64 buffer_start;
330 	int data_offset, err;
331 	u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
332 	u32 time_start;
333 	struct qbman_swp *swp = dflt_dpio->sw_portal;
334 	struct qbman_eq_desc ed;
335 	struct qbman_release_desc releasedesc;
336 
337 	/* Setup the FD fields */
338 	memset(&fd, 0, sizeof(fd));
339 
340 	data_offset = priv->tx_data_offset;
341 
342 	do {
343 		err = qbman_swp_acquire(dflt_dpio->sw_portal,
344 					dflt_dpbp->dpbp_attr.bpid,
345 					&buffer_start, 1);
346 	} while (err == -EBUSY);
347 
348 	if (err <= 0) {
349 		printf("qbman_swp_acquire() failed\n");
350 		return -ENOMEM;
351 	}
352 
353 	debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
354 
355 	memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
356 
357 	flush_dcache_range(buffer_start, buffer_start +
358 					LDPAA_ETH_RX_BUFFER_SIZE);
359 
360 	ldpaa_fd_set_addr(&fd, (u64)buffer_start);
361 	ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
362 	ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
363 	ldpaa_fd_set_len(&fd, len);
364 
365 	fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
366 				LDPAA_FD_CTRL_PTV1;
367 
368 	qbman_eq_desc_clear(&ed);
369 	qbman_eq_desc_set_no_orp(&ed, 0);
370 	qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
371 
372 	time_start = get_timer(0);
373 
374 	while (get_timer(time_start) < timeo) {
375 		err = qbman_swp_enqueue(swp, &ed,
376 				(const struct qbman_fd *)(&fd));
377 		if (err != -EBUSY)
378 			break;
379 	}
380 
381 	if (err < 0) {
382 		printf("error enqueueing Tx frame\n");
383 		goto error;
384 	}
385 
386 	return err;
387 
388 error:
389 	qbman_release_desc_clear(&releasedesc);
390 	qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
391 	time_start = get_timer(0);
392 	do {
393 		/* Release buffer into the QBMAN */
394 		err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
395 	} while (get_timer(time_start) < timeo && err == -EBUSY);
396 
397 	if (err == -EBUSY)
398 		printf("TX data: QBMAN buffer release fails\n");
399 
400 	return err;
401 }
402 
ldpaa_get_dpmac_state(struct ldpaa_eth_priv * priv,struct dpmac_link_state * state)403 static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
404 				 struct dpmac_link_state *state)
405 {
406 	phy_interface_t enet_if;
407 	int phys_detected;
408 #ifdef CONFIG_PHYLIB
409 	struct phy_device *phydev = NULL;
410 	int err, phy_num;
411 #endif
412 
413 	/* let's start off with maximum capabilities */
414 	enet_if = wriop_get_enet_if(priv->dpmac_id);
415 	switch (enet_if) {
416 	case PHY_INTERFACE_MODE_XGMII:
417 		state->rate = SPEED_10000;
418 		break;
419 	default:
420 		state->rate = SPEED_1000;
421 		break;
422 	}
423 	state->up = 1;
424 
425 	phys_detected = 0;
426 #ifdef CONFIG_PHYLIB
427 	state->options |= DPMAC_LINK_OPT_AUTONEG;
428 
429 	/* start the phy devices one by one and update the dpmac state */
430 	for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
431 		phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
432 		if (!phydev)
433 			continue;
434 
435 		phys_detected++;
436 		err = phy_startup(phydev);
437 		if (err) {
438 			printf("%s: Could not initialize\n", phydev->dev->name);
439 			state->up = 0;
440 			break;
441 		}
442 		if (phydev->link) {
443 			state->rate = min(state->rate, (uint32_t)phydev->speed);
444 			if (!phydev->duplex)
445 				state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
446 			if (!phydev->autoneg)
447 				state->options &= ~DPMAC_LINK_OPT_AUTONEG;
448 		} else {
449 			/* break out of loop even if one phy is down */
450 			state->up = 0;
451 			break;
452 		}
453 	}
454 #endif
455 	if (!phys_detected)
456 		state->options &= ~DPMAC_LINK_OPT_AUTONEG;
457 
458 	if (!state->up) {
459 		state->rate = 0;
460 		state->options = 0;
461 		return -ENOLINK;
462 	}
463 
464 	return 0;
465 }
466 
ldpaa_eth_open(struct eth_device * net_dev,bd_t * bd)467 static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
468 {
469 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
470 	struct dpmac_link_state	dpmac_link_state = { 0 };
471 #ifdef DEBUG
472 	struct dpni_link_state link_state;
473 #endif
474 	int err = 0;
475 	struct dpni_queue d_queue;
476 
477 	if (net_dev->state == ETH_STATE_ACTIVE)
478 		return 0;
479 
480 	if (get_mc_boot_status() != 0) {
481 		printf("ERROR (MC is not booted)\n");
482 		return -ENODEV;
483 	}
484 
485 	if (get_dpl_apply_status() == 0) {
486 		printf("ERROR (DPL is deployed. No device available)\n");
487 		return -ENODEV;
488 	}
489 
490 	/* DPMAC initialization */
491 	err = ldpaa_dpmac_setup(priv);
492 	if (err < 0)
493 		goto err_dpmac_setup;
494 
495 	err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
496 	if (err < 0)
497 		goto err_dpmac_bind;
498 
499 	/* DPMAC binding DPNI */
500 	err = ldpaa_dpmac_bind(priv);
501 	if (err)
502 		goto err_dpmac_bind;
503 
504 	/* DPNI initialization */
505 	err = ldpaa_dpni_setup(priv);
506 	if (err < 0)
507 		goto err_dpni_setup;
508 
509 	err = ldpaa_dpbp_setup();
510 	if (err < 0)
511 		goto err_dpbp_setup;
512 
513 	/* DPNI binding DPBP */
514 	err = ldpaa_dpni_bind(priv);
515 	if (err)
516 		goto err_dpni_bind;
517 
518 	err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
519 				dflt_dpni->dpni_handle, net_dev->enetaddr);
520 	if (err) {
521 		printf("dpni_add_mac_addr() failed\n");
522 		return err;
523 	}
524 
525 	err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
526 	if (err < 0) {
527 		printf("dpni_enable() failed\n");
528 		return err;
529 	}
530 
531 	err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
532 				  priv->dpmac_handle, &dpmac_link_state);
533 	if (err < 0) {
534 		printf("dpmac_set_link_state() failed\n");
535 		return err;
536 	}
537 
538 #ifdef DEBUG
539 	printf("DPMAC link status: %d - ", dpmac_link_state.up);
540 	dpmac_link_state.up == 0 ? printf("down\n") :
541 	dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n");
542 
543 	err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
544 				  dflt_dpni->dpni_handle, &link_state);
545 	if (err < 0) {
546 		printf("dpni_get_link_state() failed\n");
547 		return err;
548 	}
549 
550 	printf("DPNI link status: %d - ", link_state.up);
551 	link_state.up == 0 ? printf("down\n") :
552 	link_state.up == 1 ? printf("up\n") : printf("error state\n");
553 #endif
554 
555 	memset(&d_queue, 0, sizeof(struct dpni_queue));
556 	err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
557 			     dflt_dpni->dpni_handle, DPNI_QUEUE_RX,
558 			     0, 0, &d_queue);
559 	if (err) {
560 		printf("dpni_get_queue failed\n");
561 		goto err_get_queue;
562 	}
563 
564 	priv->rx_dflt_fqid = d_queue.fqid;
565 
566 	err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
567 			    &priv->tx_qdid);
568 	if (err) {
569 		printf("dpni_get_qdid() failed\n");
570 		goto err_qdid;
571 	}
572 
573 	return dpmac_link_state.up;
574 
575 err_qdid:
576 err_get_queue:
577 	dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
578 err_dpni_bind:
579 	ldpaa_dpbp_free();
580 err_dpbp_setup:
581 	dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
582 err_dpni_setup:
583 err_dpmac_bind:
584 	dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
585 	dpmac_destroy(dflt_mc_io,
586 		      dflt_dprc_handle,
587 		      MC_CMD_NO_FLAGS, priv->dpmac_id);
588 err_dpmac_setup:
589 	return err;
590 }
591 
ldpaa_eth_stop(struct eth_device * net_dev)592 static void ldpaa_eth_stop(struct eth_device *net_dev)
593 {
594 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
595 	int err = 0;
596 #ifdef CONFIG_PHYLIB
597 	struct phy_device *phydev = NULL;
598 	int phy_num;
599 #endif
600 
601 	if ((net_dev->state == ETH_STATE_PASSIVE) ||
602 	    (net_dev->state == ETH_STATE_INIT))
603 		return;
604 
605 #ifdef DEBUG
606 	ldpaa_eth_get_dpni_counter();
607 	ldpaa_eth_get_dpmac_counter(net_dev);
608 #endif
609 
610 	err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
611 			      dflt_dprc_handle, &dpmac_endpoint);
612 	if (err < 0)
613 		printf("dprc_disconnect() failed dpmac_endpoint\n");
614 
615 	err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
616 	if (err < 0)
617 		printf("dpmac_close() failed\n");
618 
619 	err = dpmac_destroy(dflt_mc_io,
620 			    dflt_dprc_handle,
621 			    MC_CMD_NO_FLAGS,
622 			    priv->dpmac_id);
623 	if (err < 0)
624 		printf("dpmac_destroy() failed\n");
625 
626 	/* Stop Tx and Rx traffic */
627 	err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
628 	if (err < 0)
629 		printf("dpni_disable() failed\n");
630 
631 #ifdef CONFIG_PHYLIB
632 	for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
633 		phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
634 		if (phydev)
635 			phy_shutdown(phydev);
636 	}
637 #endif
638 
639 	/* Free DPBP handle and reset. */
640 	ldpaa_dpbp_free();
641 
642 	dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
643 	if (err < 0)
644 		printf("dpni_reset() failed\n");
645 
646 	dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
647 	if (err < 0)
648 		printf("dpni_close() failed\n");
649 }
650 
ldpaa_dpbp_drain_cnt(int count)651 static void ldpaa_dpbp_drain_cnt(int count)
652 {
653 	uint64_t buf_array[7];
654 	void *addr;
655 	int ret, i;
656 
657 	BUG_ON(count > 7);
658 
659 	do {
660 		ret = qbman_swp_acquire(dflt_dpio->sw_portal,
661 					dflt_dpbp->dpbp_attr.bpid,
662 					buf_array, count);
663 		if (ret < 0) {
664 			printf("qbman_swp_acquire() failed\n");
665 			return;
666 		}
667 		for (i = 0; i < ret; i++) {
668 			addr = (void *)buf_array[i];
669 			debug("Free: buffer addr =0x%p\n", addr);
670 			free(addr);
671 		}
672 	} while (ret);
673 }
674 
ldpaa_dpbp_drain(void)675 static void ldpaa_dpbp_drain(void)
676 {
677 	int i;
678 	for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
679 		ldpaa_dpbp_drain_cnt(7);
680 }
681 
ldpaa_bp_add_7(uint16_t bpid)682 static int ldpaa_bp_add_7(uint16_t bpid)
683 {
684 	uint64_t buf_array[7];
685 	u8 *addr;
686 	int i;
687 	struct qbman_release_desc rd;
688 
689 	for (i = 0; i < 7; i++) {
690 		addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
691 		if (!addr) {
692 			printf("addr allocation failed\n");
693 			goto err_alloc;
694 		}
695 		memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
696 		flush_dcache_range((u64)addr,
697 				   (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
698 
699 		buf_array[i] = (uint64_t)addr;
700 		debug("Release: buffer addr =0x%p\n", addr);
701 	}
702 
703 release_bufs:
704 	/* In case the portal is busy, retry until successful.
705 	 * This function is guaranteed to succeed in a reasonable amount
706 	 * of time.
707 	 */
708 
709 	do {
710 		mdelay(1);
711 		qbman_release_desc_clear(&rd);
712 		qbman_release_desc_set_bpid(&rd, bpid);
713 	} while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
714 
715 	return i;
716 
717 err_alloc:
718 	if (i)
719 		goto release_bufs;
720 
721 	return 0;
722 }
723 
ldpaa_dpbp_seed(uint16_t bpid)724 static int ldpaa_dpbp_seed(uint16_t bpid)
725 {
726 	int i;
727 	int count;
728 
729 	for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
730 		count = ldpaa_bp_add_7(bpid);
731 		if (count < 7)
732 			printf("Buffer Seed= %d\n", count);
733 	}
734 
735 	return 0;
736 }
737 
ldpaa_dpbp_setup(void)738 static int ldpaa_dpbp_setup(void)
739 {
740 	int err;
741 
742 	err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
743 			&dflt_dpbp->dpbp_handle);
744 	if (err) {
745 		printf("dpbp_open() failed\n");
746 		goto err_open;
747 	}
748 
749 	err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
750 	if (err) {
751 		printf("dpbp_enable() failed\n");
752 		goto err_enable;
753 	}
754 
755 	err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
756 				  dflt_dpbp->dpbp_handle,
757 				  &dflt_dpbp->dpbp_attr);
758 	if (err) {
759 		printf("dpbp_get_attributes() failed\n");
760 		goto err_get_attr;
761 	}
762 
763 	err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
764 
765 	if (err) {
766 		printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
767 		       dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
768 		goto err_seed;
769 	}
770 
771 	return 0;
772 
773 err_seed:
774 err_get_attr:
775 	dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
776 err_enable:
777 	dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
778 err_open:
779 	return err;
780 }
781 
ldpaa_dpbp_free(void)782 static void ldpaa_dpbp_free(void)
783 {
784 	ldpaa_dpbp_drain();
785 	dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
786 	dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
787 	dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
788 }
789 
ldpaa_dpmac_version_check(struct fsl_mc_io * mc_io,struct ldpaa_eth_priv * priv)790 static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
791 				     struct ldpaa_eth_priv *priv)
792 {
793 	int error;
794 	uint16_t major_ver, minor_ver;
795 
796 	error = dpmac_get_api_version(dflt_mc_io, 0,
797 					&major_ver,
798 					&minor_ver);
799 	if ((major_ver < DPMAC_VER_MAJOR) ||
800 	    (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) {
801 		printf("DPMAC version mismatch found %u.%u,",
802 		       major_ver, minor_ver);
803 		printf("supported version is %u.%u\n",
804 		       DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
805 		return error;
806 	}
807 
808 	return error;
809 }
810 
ldpaa_dpmac_setup(struct ldpaa_eth_priv * priv)811 static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
812 {
813 	int err = 0;
814 	struct dpmac_cfg dpmac_cfg;
815 
816 	dpmac_cfg.mac_id = priv->dpmac_id;
817 
818 	err = dpmac_create(dflt_mc_io,
819 			   dflt_dprc_handle,
820 			   MC_CMD_NO_FLAGS, &dpmac_cfg,
821 			   &priv->dpmac_id);
822 	if (err)
823 		printf("dpmac_create() failed\n");
824 
825 	err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
826 	if (err < 0) {
827 		printf("ldpaa_dpmac_version_check() failed: %d\n", err);
828 		goto err_version_check;
829 	}
830 
831 	err = dpmac_open(dflt_mc_io,
832 			 MC_CMD_NO_FLAGS,
833 			 priv->dpmac_id,
834 			 &priv->dpmac_handle);
835 	if (err < 0) {
836 		printf("dpmac_open() failed: %d\n", err);
837 		goto err_open;
838 	}
839 
840 	return err;
841 
842 err_open:
843 err_version_check:
844 	dpmac_destroy(dflt_mc_io,
845 		      dflt_dprc_handle,
846 		      MC_CMD_NO_FLAGS, priv->dpmac_id);
847 
848 	return err;
849 }
850 
ldpaa_dpmac_bind(struct ldpaa_eth_priv * priv)851 static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
852 {
853 	int err = 0;
854 	struct dprc_connection_cfg dprc_connection_cfg = {
855 		/* If both rates are zero the connection */
856 		/* will be configured in "best effort" mode. */
857 		.committed_rate = 0,
858 		.max_rate = 0
859 	};
860 
861 #ifdef DEBUG
862 	struct dprc_endpoint dbg_endpoint;
863 	int state = 0;
864 #endif
865 
866 	memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
867 	strcpy(dpmac_endpoint.type, "dpmac");
868 	dpmac_endpoint.id = priv->dpmac_id;
869 
870 	memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
871 	strcpy(dpni_endpoint.type, "dpni");
872 	dpni_endpoint.id = dflt_dpni->dpni_id;
873 
874 	err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
875 			     dflt_dprc_handle,
876 			     &dpmac_endpoint,
877 			     &dpni_endpoint,
878 			     &dprc_connection_cfg);
879 	if (err)
880 		printf("dprc_connect() failed\n");
881 
882 #ifdef DEBUG
883 	err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
884 				    dflt_dprc_handle, &dpni_endpoint,
885 				    &dbg_endpoint, &state);
886 	printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
887 	printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
888 	printf("%s, DPMAC State= %d\n", __func__, state);
889 
890 	memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
891 	err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
892 				    dflt_dprc_handle, &dpmac_endpoint,
893 				    &dbg_endpoint, &state);
894 	printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
895 	printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
896 	printf("%s, DPNI State= %d\n", __func__, state);
897 #endif
898 	return err;
899 }
900 
ldpaa_dpni_setup(struct ldpaa_eth_priv * priv)901 static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
902 {
903 	int err;
904 
905 	/* and get a handle for the DPNI this interface is associate with */
906 	err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
907 			&dflt_dpni->dpni_handle);
908 	if (err) {
909 		printf("dpni_open() failed\n");
910 		goto err_open;
911 	}
912 	err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
913 				  dflt_dpni->dpni_handle,
914 				  &dflt_dpni->dpni_attrs);
915 	if (err) {
916 		printf("dpni_get_attributes() failed (err=%d)\n", err);
917 		goto err_get_attr;
918 	}
919 
920 	/* Configure our buffers' layout */
921 	dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
922 				   DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
923 				   DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
924 				   DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
925 	dflt_dpni->buf_layout.pass_parser_result = true;
926 	dflt_dpni->buf_layout.pass_frame_status = true;
927 	dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
928 	/* HW erratum mandates data alignment in multiples of 256 */
929 	dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
930 
931 	/* ...rx, ... */
932 	err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
933 				     dflt_dpni->dpni_handle,
934 				     &dflt_dpni->buf_layout, DPNI_QUEUE_RX);
935 	if (err) {
936 		printf("dpni_set_buffer_layout() failed");
937 		goto err_buf_layout;
938 	}
939 
940 	/* ... tx, ... */
941 	/* remove Rx-only options */
942 	dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
943 				      DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
944 	err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
945 				     dflt_dpni->dpni_handle,
946 				     &dflt_dpni->buf_layout, DPNI_QUEUE_TX);
947 	if (err) {
948 		printf("dpni_set_buffer_layout() failed");
949 		goto err_buf_layout;
950 	}
951 
952 	/* ... tx-confirm. */
953 	dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
954 	err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
955 				     dflt_dpni->dpni_handle,
956 				     &dflt_dpni->buf_layout,
957 				     DPNI_QUEUE_TX_CONFIRM);
958 	if (err) {
959 		printf("dpni_set_buffer_layout() failed");
960 		goto err_buf_layout;
961 	}
962 
963 	/* Now that we've set our tx buffer layout, retrieve the minimum
964 	 * required tx data offset.
965 	 */
966 	err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
967 				      dflt_dpni->dpni_handle,
968 				      &priv->tx_data_offset);
969 	if (err) {
970 		printf("dpni_get_tx_data_offset() failed\n");
971 		goto err_data_offset;
972 	}
973 
974 	/* Warn in case TX data offset is not multiple of 64 bytes. */
975 	WARN_ON(priv->tx_data_offset % 64);
976 
977 	/* Accomodate SWA space. */
978 	priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
979 	debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
980 
981 	return 0;
982 
983 err_data_offset:
984 err_buf_layout:
985 err_get_attr:
986 	dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
987 err_open:
988 	return err;
989 }
990 
ldpaa_dpni_bind(struct ldpaa_eth_priv * priv)991 static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
992 {
993 	struct dpni_pools_cfg pools_params;
994 	struct dpni_queue tx_queue;
995 	int err = 0;
996 
997 	memset(&pools_params, 0, sizeof(pools_params));
998 	pools_params.num_dpbp = 1;
999 	pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
1000 	pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
1001 	err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
1002 			     dflt_dpni->dpni_handle, &pools_params);
1003 	if (err) {
1004 		printf("dpni_set_pools() failed\n");
1005 		return err;
1006 	}
1007 
1008 	memset(&tx_queue, 0, sizeof(struct dpni_queue));
1009 
1010 	err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
1011 			     dflt_dpni->dpni_handle,
1012 			     DPNI_QUEUE_TX, 0, 0, &tx_queue);
1013 
1014 	if (err) {
1015 		printf("dpni_set_queue() failed\n");
1016 		return err;
1017 	}
1018 
1019 	err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS,
1020 					    dflt_dpni->dpni_handle,
1021 					    DPNI_CONF_DISABLE);
1022 	if (err) {
1023 		printf("dpni_set_tx_confirmation_mode() failed\n");
1024 		return err;
1025 	}
1026 
1027 	return 0;
1028 }
1029 
ldpaa_eth_netdev_init(struct eth_device * net_dev,phy_interface_t enet_if)1030 static int ldpaa_eth_netdev_init(struct eth_device *net_dev,
1031 				 phy_interface_t enet_if)
1032 {
1033 	int err;
1034 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
1035 
1036 	snprintf(net_dev->name, ETH_NAME_LEN, "DPMAC%d@%s", priv->dpmac_id,
1037 		 phy_interface_strings[enet_if]);
1038 
1039 	net_dev->iobase = 0;
1040 	net_dev->init = ldpaa_eth_open;
1041 	net_dev->halt = ldpaa_eth_stop;
1042 	net_dev->send = ldpaa_eth_tx;
1043 	net_dev->recv = ldpaa_eth_pull_dequeue_rx;
1044 
1045 #ifdef CONFIG_PHYLIB
1046 	err = init_phy(net_dev);
1047 	if (err < 0)
1048 		return err;
1049 #endif
1050 
1051 	err = eth_register(net_dev);
1052 	if (err < 0) {
1053 		printf("eth_register() = %d\n", err);
1054 		return err;
1055 	}
1056 
1057 	return 0;
1058 }
1059 
ldpaa_eth_init(int dpmac_id,phy_interface_t enet_if)1060 int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
1061 {
1062 	struct eth_device		*net_dev = NULL;
1063 	struct ldpaa_eth_priv		*priv = NULL;
1064 	int				err = 0;
1065 
1066 	/* Net device */
1067 	net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
1068 	if (!net_dev) {
1069 		printf("eth_device malloc() failed\n");
1070 		return -ENOMEM;
1071 	}
1072 	memset(net_dev, 0, sizeof(struct eth_device));
1073 
1074 	/* alloc the ldpaa ethernet private struct */
1075 	priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
1076 	if (!priv) {
1077 		printf("ldpaa_eth_priv malloc() failed\n");
1078 		free(net_dev);
1079 		return -ENOMEM;
1080 	}
1081 	memset(priv, 0, sizeof(struct ldpaa_eth_priv));
1082 
1083 	net_dev->priv = (void *)priv;
1084 	priv->net_dev = (struct eth_device *)net_dev;
1085 	priv->dpmac_id = dpmac_id;
1086 	debug("%s dpmac_id=%d\n", __func__, dpmac_id);
1087 
1088 	err = ldpaa_eth_netdev_init(net_dev, enet_if);
1089 	if (err)
1090 		goto err_netdev_init;
1091 
1092 	debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
1093 	return 0;
1094 
1095 err_netdev_init:
1096 	free(priv);
1097 	net_dev->priv = NULL;
1098 	free(net_dev);
1099 
1100 	return err;
1101 }
1102