xref: /openbmc/u-boot/drivers/net/ldpaa_eth/ldpaa_eth.c (revision 5038d3e5f23ad979c05fa339284576ccb7e90c07)
1c517771aSPrabhakar Kushwaha /*
2c517771aSPrabhakar Kushwaha  * Copyright (C) 2014 Freescale Semiconductor
3c517771aSPrabhakar Kushwaha  *
4c517771aSPrabhakar Kushwaha  * SPDX-License-Identifier:	GPL-2.0+
5c517771aSPrabhakar Kushwaha  */
6c517771aSPrabhakar Kushwaha 
7c517771aSPrabhakar Kushwaha #include <common.h>
8c517771aSPrabhakar Kushwaha #include <asm/io.h>
9c517771aSPrabhakar Kushwaha #include <asm/types.h>
10c517771aSPrabhakar Kushwaha #include <malloc.h>
11c517771aSPrabhakar Kushwaha #include <net.h>
12c517771aSPrabhakar Kushwaha #include <hwconfig.h>
13c517771aSPrabhakar Kushwaha #include <phy.h>
14c517771aSPrabhakar Kushwaha #include <linux/compat.h>
15c919ab9eSPrabhakar Kushwaha #include <fsl-mc/fsl_dpmac.h>
16c517771aSPrabhakar Kushwaha 
17c517771aSPrabhakar Kushwaha #include "ldpaa_eth.h"
18c517771aSPrabhakar Kushwaha 
195753b0f1SPrabhakar Kushwaha #undef CONFIG_PHYLIB
20c517771aSPrabhakar Kushwaha static int init_phy(struct eth_device *dev)
21c517771aSPrabhakar Kushwaha {
22c517771aSPrabhakar Kushwaha 	/*TODO for external PHY */
23c517771aSPrabhakar Kushwaha 
24c517771aSPrabhakar Kushwaha 	return 0;
25c517771aSPrabhakar Kushwaha }
26c517771aSPrabhakar Kushwaha 
27*5038d3e5SPrabhakar Kushwaha #ifdef DEBUG
28*5038d3e5SPrabhakar Kushwaha static void ldpaa_eth_get_dpni_counter(void)
29*5038d3e5SPrabhakar Kushwaha {
30*5038d3e5SPrabhakar Kushwaha 	int err = 0;
31*5038d3e5SPrabhakar Kushwaha 	u64 value;
32*5038d3e5SPrabhakar Kushwaha 
33*5038d3e5SPrabhakar Kushwaha 	err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
34*5038d3e5SPrabhakar Kushwaha 		     dflt_dpni->dpni_handle,
35*5038d3e5SPrabhakar Kushwaha 		     DPNI_CNT_ING_FRAME,
36*5038d3e5SPrabhakar Kushwaha 		     &value);
37*5038d3e5SPrabhakar Kushwaha 	if (err < 0) {
38*5038d3e5SPrabhakar Kushwaha 		printf("dpni_get_counter: DPNI_CNT_ING_FRAME failed\n");
39*5038d3e5SPrabhakar Kushwaha 		return;
40*5038d3e5SPrabhakar Kushwaha 	}
41*5038d3e5SPrabhakar Kushwaha 	printf("DPNI_CNT_ING_FRAME=%lld\n", value);
42*5038d3e5SPrabhakar Kushwaha 
43*5038d3e5SPrabhakar Kushwaha 	err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
44*5038d3e5SPrabhakar Kushwaha 		     dflt_dpni->dpni_handle,
45*5038d3e5SPrabhakar Kushwaha 		     DPNI_CNT_ING_BYTE,
46*5038d3e5SPrabhakar Kushwaha 		     &value);
47*5038d3e5SPrabhakar Kushwaha 	if (err < 0) {
48*5038d3e5SPrabhakar Kushwaha 		printf("dpni_get_counter: DPNI_CNT_ING_BYTE failed\n");
49*5038d3e5SPrabhakar Kushwaha 		return;
50*5038d3e5SPrabhakar Kushwaha 	}
51*5038d3e5SPrabhakar Kushwaha 	printf("DPNI_CNT_ING_BYTE=%lld\n", value);
52*5038d3e5SPrabhakar Kushwaha 
53*5038d3e5SPrabhakar Kushwaha 	err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
54*5038d3e5SPrabhakar Kushwaha 		     dflt_dpni->dpni_handle,
55*5038d3e5SPrabhakar Kushwaha 		     DPNI_CNT_ING_FRAME_DROP ,
56*5038d3e5SPrabhakar Kushwaha 		     &value);
57*5038d3e5SPrabhakar Kushwaha 	if (err < 0) {
58*5038d3e5SPrabhakar Kushwaha 		printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DROP failed\n");
59*5038d3e5SPrabhakar Kushwaha 		return;
60*5038d3e5SPrabhakar Kushwaha 	}
61*5038d3e5SPrabhakar Kushwaha 	printf("DPNI_CNT_ING_FRAME_DROP =%lld\n", value);
62*5038d3e5SPrabhakar Kushwaha 
63*5038d3e5SPrabhakar Kushwaha 	err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
64*5038d3e5SPrabhakar Kushwaha 		     dflt_dpni->dpni_handle,
65*5038d3e5SPrabhakar Kushwaha 		     DPNI_CNT_ING_FRAME_DISCARD,
66*5038d3e5SPrabhakar Kushwaha 		     &value);
67*5038d3e5SPrabhakar Kushwaha 	if (err < 0) {
68*5038d3e5SPrabhakar Kushwaha 		printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DISCARD failed\n");
69*5038d3e5SPrabhakar Kushwaha 		return;
70*5038d3e5SPrabhakar Kushwaha 	}
71*5038d3e5SPrabhakar Kushwaha 	printf("DPNI_CNT_ING_FRAME_DISCARD=%lld\n", value);
72*5038d3e5SPrabhakar Kushwaha 
73*5038d3e5SPrabhakar Kushwaha 	err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
74*5038d3e5SPrabhakar Kushwaha 		     dflt_dpni->dpni_handle,
75*5038d3e5SPrabhakar Kushwaha 		     DPNI_CNT_EGR_FRAME,
76*5038d3e5SPrabhakar Kushwaha 		     &value);
77*5038d3e5SPrabhakar Kushwaha 	if (err < 0) {
78*5038d3e5SPrabhakar Kushwaha 		printf("dpni_get_counter: DPNI_CNT_EGR_FRAME failed\n");
79*5038d3e5SPrabhakar Kushwaha 		return;
80*5038d3e5SPrabhakar Kushwaha 	}
81*5038d3e5SPrabhakar Kushwaha 	printf("DPNI_CNT_EGR_FRAME=%lld\n", value);
82*5038d3e5SPrabhakar Kushwaha 
83*5038d3e5SPrabhakar Kushwaha 	err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
84*5038d3e5SPrabhakar Kushwaha 		     dflt_dpni->dpni_handle,
85*5038d3e5SPrabhakar Kushwaha 		     DPNI_CNT_EGR_BYTE ,
86*5038d3e5SPrabhakar Kushwaha 		     &value);
87*5038d3e5SPrabhakar Kushwaha 	if (err < 0) {
88*5038d3e5SPrabhakar Kushwaha 		printf("dpni_get_counter: DPNI_CNT_EGR_BYTE failed\n");
89*5038d3e5SPrabhakar Kushwaha 		return;
90*5038d3e5SPrabhakar Kushwaha 	}
91*5038d3e5SPrabhakar Kushwaha 	printf("DPNI_CNT_EGR_BYTE =%lld\n", value);
92*5038d3e5SPrabhakar Kushwaha 
93*5038d3e5SPrabhakar Kushwaha 	err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
94*5038d3e5SPrabhakar Kushwaha 		     dflt_dpni->dpni_handle,
95*5038d3e5SPrabhakar Kushwaha 		     DPNI_CNT_EGR_FRAME_DISCARD ,
96*5038d3e5SPrabhakar Kushwaha 		     &value);
97*5038d3e5SPrabhakar Kushwaha 	if (err < 0) {
98*5038d3e5SPrabhakar Kushwaha 		printf("dpni_get_counter: DPNI_CNT_EGR_FRAME_DISCARD failed\n");
99*5038d3e5SPrabhakar Kushwaha 		return;
100*5038d3e5SPrabhakar Kushwaha 	}
101*5038d3e5SPrabhakar Kushwaha 	printf("DPNI_CNT_EGR_FRAME_DISCARD =%lld\n", value);
102*5038d3e5SPrabhakar Kushwaha }
103*5038d3e5SPrabhakar Kushwaha #endif
104*5038d3e5SPrabhakar Kushwaha 
105c517771aSPrabhakar Kushwaha static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
106c517771aSPrabhakar Kushwaha 			 const struct dpaa_fd *fd)
107c517771aSPrabhakar Kushwaha {
108c517771aSPrabhakar Kushwaha 	u64 fd_addr;
109c517771aSPrabhakar Kushwaha 	uint16_t fd_offset;
110c517771aSPrabhakar Kushwaha 	uint32_t fd_length;
111c517771aSPrabhakar Kushwaha 	struct ldpaa_fas *fas;
112c517771aSPrabhakar Kushwaha 	uint32_t status, err;
11356c57cf7SPrabhakar Kushwaha 	u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
11456c57cf7SPrabhakar Kushwaha 	u32 time_start;
115c517771aSPrabhakar Kushwaha 	struct qbman_release_desc releasedesc;
116c517771aSPrabhakar Kushwaha 	struct qbman_swp *swp = dflt_dpio->sw_portal;
117c517771aSPrabhakar Kushwaha 
118c517771aSPrabhakar Kushwaha 	fd_addr = ldpaa_fd_get_addr(fd);
119c517771aSPrabhakar Kushwaha 	fd_offset = ldpaa_fd_get_offset(fd);
120c517771aSPrabhakar Kushwaha 	fd_length = ldpaa_fd_get_len(fd);
121c517771aSPrabhakar Kushwaha 
122c517771aSPrabhakar Kushwaha 	debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
123c517771aSPrabhakar Kushwaha 
124c517771aSPrabhakar Kushwaha 	if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
125c517771aSPrabhakar Kushwaha 		/* Read the frame annotation status word and check for errors */
126c517771aSPrabhakar Kushwaha 		fas = (struct ldpaa_fas *)
127c517771aSPrabhakar Kushwaha 				((uint8_t *)(fd_addr) +
128c919ab9eSPrabhakar Kushwaha 				dflt_dpni->buf_layout.private_data_size);
129c517771aSPrabhakar Kushwaha 		status = le32_to_cpu(fas->status);
130c517771aSPrabhakar Kushwaha 		if (status & LDPAA_ETH_RX_ERR_MASK) {
131c517771aSPrabhakar Kushwaha 			printf("Rx frame error(s): 0x%08x\n",
132c517771aSPrabhakar Kushwaha 			       status & LDPAA_ETH_RX_ERR_MASK);
133c517771aSPrabhakar Kushwaha 			goto error;
134c517771aSPrabhakar Kushwaha 		} else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
135c517771aSPrabhakar Kushwaha 			printf("Unsupported feature in bitmask: 0x%08x\n",
136c517771aSPrabhakar Kushwaha 			       status & LDPAA_ETH_RX_UNSUPP_MASK);
137c517771aSPrabhakar Kushwaha 			goto error;
138c517771aSPrabhakar Kushwaha 		}
139c517771aSPrabhakar Kushwaha 	}
140c517771aSPrabhakar Kushwaha 
141c517771aSPrabhakar Kushwaha 	debug("Rx frame: To Upper layer\n");
142c517771aSPrabhakar Kushwaha 	net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
143c517771aSPrabhakar Kushwaha 				    fd_length);
144c517771aSPrabhakar Kushwaha 
145c517771aSPrabhakar Kushwaha error:
1465753b0f1SPrabhakar Kushwaha 	flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
147c517771aSPrabhakar Kushwaha 	qbman_release_desc_clear(&releasedesc);
148c517771aSPrabhakar Kushwaha 	qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
14956c57cf7SPrabhakar Kushwaha 	time_start = get_timer(0);
150c517771aSPrabhakar Kushwaha 	do {
151c517771aSPrabhakar Kushwaha 		/* Release buffer into the QBMAN */
152c517771aSPrabhakar Kushwaha 		err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
15356c57cf7SPrabhakar Kushwaha 	} while (get_timer(time_start) < timeo && err == -EBUSY);
15456c57cf7SPrabhakar Kushwaha 
15556c57cf7SPrabhakar Kushwaha 	if (err == -EBUSY)
15656c57cf7SPrabhakar Kushwaha 		printf("Rx frame: QBMAN buffer release fails\n");
15756c57cf7SPrabhakar Kushwaha 
158c517771aSPrabhakar Kushwaha 	return;
159c517771aSPrabhakar Kushwaha }
160c517771aSPrabhakar Kushwaha 
161c517771aSPrabhakar Kushwaha static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
162c517771aSPrabhakar Kushwaha {
163c517771aSPrabhakar Kushwaha 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
164c517771aSPrabhakar Kushwaha 	const struct ldpaa_dq *dq;
165c517771aSPrabhakar Kushwaha 	const struct dpaa_fd *fd;
166b4c3a35dSPrabhakar Kushwaha 	int i = 5, err = 0, status;
167b4c3a35dSPrabhakar Kushwaha 	u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
168b4c3a35dSPrabhakar Kushwaha 	u32 time_start;
169c517771aSPrabhakar Kushwaha 	static struct qbman_pull_desc pulldesc;
170c517771aSPrabhakar Kushwaha 	struct qbman_swp *swp = dflt_dpio->sw_portal;
171c517771aSPrabhakar Kushwaha 
1725753b0f1SPrabhakar Kushwaha 	while (--i) {
173c517771aSPrabhakar Kushwaha 		qbman_pull_desc_clear(&pulldesc);
174c517771aSPrabhakar Kushwaha 		qbman_pull_desc_set_numframes(&pulldesc, 1);
175c517771aSPrabhakar Kushwaha 		qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
176c517771aSPrabhakar Kushwaha 
177c517771aSPrabhakar Kushwaha 		err = qbman_swp_pull(swp, &pulldesc);
178c517771aSPrabhakar Kushwaha 		if (err < 0) {
179c517771aSPrabhakar Kushwaha 			printf("Dequeue frames error:0x%08x\n", err);
180c517771aSPrabhakar Kushwaha 			continue;
181c517771aSPrabhakar Kushwaha 		}
182c517771aSPrabhakar Kushwaha 
183b4c3a35dSPrabhakar Kushwaha 		time_start = get_timer(0);
1845753b0f1SPrabhakar Kushwaha 
185b4c3a35dSPrabhakar Kushwaha 		 do {
186b4c3a35dSPrabhakar Kushwaha 			dq = qbman_swp_dqrr_next(swp);
187b4c3a35dSPrabhakar Kushwaha 		} while (get_timer(time_start) < timeo && !dq);
1885753b0f1SPrabhakar Kushwaha 
189c517771aSPrabhakar Kushwaha 		if (dq) {
190c517771aSPrabhakar Kushwaha 			/* Check for valid frame. If not sent a consume
191c517771aSPrabhakar Kushwaha 			 * confirmation to QBMAN otherwise give it to NADK
192c517771aSPrabhakar Kushwaha 			 * application and then send consume confirmation to
193c517771aSPrabhakar Kushwaha 			 * QBMAN.
194c517771aSPrabhakar Kushwaha 			 */
195c517771aSPrabhakar Kushwaha 			status = (uint8_t)ldpaa_dq_flags(dq);
196c517771aSPrabhakar Kushwaha 			if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
197c517771aSPrabhakar Kushwaha 				debug("Dequeue RX frames:");
198c517771aSPrabhakar Kushwaha 				debug("No frame delivered\n");
199c517771aSPrabhakar Kushwaha 
200c517771aSPrabhakar Kushwaha 				qbman_swp_dqrr_consume(swp, dq);
2010c7c87a4SPrabhakar Kushwaha 				continue;
202c517771aSPrabhakar Kushwaha 			}
203c517771aSPrabhakar Kushwaha 
204c517771aSPrabhakar Kushwaha 			fd = ldpaa_dq_fd(dq);
205c517771aSPrabhakar Kushwaha 
206c517771aSPrabhakar Kushwaha 			/* Obtain FD and process it */
207c517771aSPrabhakar Kushwaha 			ldpaa_eth_rx(priv, fd);
208c517771aSPrabhakar Kushwaha 			qbman_swp_dqrr_consume(swp, dq);
209c517771aSPrabhakar Kushwaha 			break;
210b4c3a35dSPrabhakar Kushwaha 		} else {
211b4c3a35dSPrabhakar Kushwaha 			err = -ENODATA;
212b4c3a35dSPrabhakar Kushwaha 			debug("No DQRR entries\n");
213b4c3a35dSPrabhakar Kushwaha 			break;
214c517771aSPrabhakar Kushwaha 		}
215c517771aSPrabhakar Kushwaha 	}
216c517771aSPrabhakar Kushwaha 
217c517771aSPrabhakar Kushwaha 	return err;
218c517771aSPrabhakar Kushwaha }
219c517771aSPrabhakar Kushwaha 
220c517771aSPrabhakar Kushwaha static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
221c517771aSPrabhakar Kushwaha {
222c517771aSPrabhakar Kushwaha 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
223c517771aSPrabhakar Kushwaha 	struct dpaa_fd fd;
224c517771aSPrabhakar Kushwaha 	u64 buffer_start;
225c517771aSPrabhakar Kushwaha 	int data_offset, err;
226e48df52bSPrabhakar Kushwaha 	u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
227e48df52bSPrabhakar Kushwaha 	u32 time_start;
228c517771aSPrabhakar Kushwaha 	struct qbman_swp *swp = dflt_dpio->sw_portal;
229c517771aSPrabhakar Kushwaha 	struct qbman_eq_desc ed;
230e48df52bSPrabhakar Kushwaha 	struct qbman_release_desc releasedesc;
231c517771aSPrabhakar Kushwaha 
232c517771aSPrabhakar Kushwaha 	/* Setup the FD fields */
233c517771aSPrabhakar Kushwaha 	memset(&fd, 0, sizeof(fd));
234c517771aSPrabhakar Kushwaha 
235c517771aSPrabhakar Kushwaha 	data_offset = priv->tx_data_offset;
236c517771aSPrabhakar Kushwaha 
237c517771aSPrabhakar Kushwaha 	do {
238c517771aSPrabhakar Kushwaha 		err = qbman_swp_acquire(dflt_dpio->sw_portal,
239c517771aSPrabhakar Kushwaha 					dflt_dpbp->dpbp_attr.bpid,
240c517771aSPrabhakar Kushwaha 					&buffer_start, 1);
241c517771aSPrabhakar Kushwaha 	} while (err == -EBUSY);
242c517771aSPrabhakar Kushwaha 
243c517771aSPrabhakar Kushwaha 	if (err < 0) {
244c517771aSPrabhakar Kushwaha 		printf("qbman_swp_acquire() failed\n");
245c517771aSPrabhakar Kushwaha 		return -ENOMEM;
246c517771aSPrabhakar Kushwaha 	}
247c517771aSPrabhakar Kushwaha 
248c517771aSPrabhakar Kushwaha 	debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
249c517771aSPrabhakar Kushwaha 
250c517771aSPrabhakar Kushwaha 	memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
251c517771aSPrabhakar Kushwaha 
2525753b0f1SPrabhakar Kushwaha 	flush_dcache_range(buffer_start, buffer_start +
2535753b0f1SPrabhakar Kushwaha 					LDPAA_ETH_RX_BUFFER_SIZE);
254c517771aSPrabhakar Kushwaha 
255c517771aSPrabhakar Kushwaha 	ldpaa_fd_set_addr(&fd, (u64)buffer_start);
256c517771aSPrabhakar Kushwaha 	ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
257c517771aSPrabhakar Kushwaha 	ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
258c517771aSPrabhakar Kushwaha 	ldpaa_fd_set_len(&fd, len);
259c517771aSPrabhakar Kushwaha 
260c517771aSPrabhakar Kushwaha 	fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
261c517771aSPrabhakar Kushwaha 				LDPAA_FD_CTRL_PTV1;
262c517771aSPrabhakar Kushwaha 
263c517771aSPrabhakar Kushwaha 	qbman_eq_desc_clear(&ed);
264c517771aSPrabhakar Kushwaha 	qbman_eq_desc_set_no_orp(&ed, 0);
265c517771aSPrabhakar Kushwaha 	qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
266e48df52bSPrabhakar Kushwaha 
267e48df52bSPrabhakar Kushwaha 	time_start = get_timer(0);
268e48df52bSPrabhakar Kushwaha 
269e48df52bSPrabhakar Kushwaha 	while (get_timer(time_start) < timeo) {
270e48df52bSPrabhakar Kushwaha 		err = qbman_swp_enqueue(swp, &ed,
271e48df52bSPrabhakar Kushwaha 				(const struct qbman_fd *)(&fd));
272e48df52bSPrabhakar Kushwaha 		if (err != -EBUSY)
273e48df52bSPrabhakar Kushwaha 			break;
274e48df52bSPrabhakar Kushwaha 	}
275e48df52bSPrabhakar Kushwaha 
276e48df52bSPrabhakar Kushwaha 	if (err < 0) {
277c517771aSPrabhakar Kushwaha 		printf("error enqueueing Tx frame\n");
278e48df52bSPrabhakar Kushwaha 		goto error;
279e48df52bSPrabhakar Kushwaha 	}
280c517771aSPrabhakar Kushwaha 
281c517771aSPrabhakar Kushwaha 	return err;
282e48df52bSPrabhakar Kushwaha 
283e48df52bSPrabhakar Kushwaha error:
284e48df52bSPrabhakar Kushwaha 	qbman_release_desc_clear(&releasedesc);
285e48df52bSPrabhakar Kushwaha 	qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
286e48df52bSPrabhakar Kushwaha 	time_start = get_timer(0);
287e48df52bSPrabhakar Kushwaha 	do {
288e48df52bSPrabhakar Kushwaha 		/* Release buffer into the QBMAN */
289e48df52bSPrabhakar Kushwaha 		err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
290e48df52bSPrabhakar Kushwaha 	} while (get_timer(time_start) < timeo && err == -EBUSY);
291e48df52bSPrabhakar Kushwaha 
292e48df52bSPrabhakar Kushwaha 	if (err == -EBUSY)
293e48df52bSPrabhakar Kushwaha 		printf("TX data: QBMAN buffer release fails\n");
294e48df52bSPrabhakar Kushwaha 
295e48df52bSPrabhakar Kushwaha 	return err;
296c517771aSPrabhakar Kushwaha }
297c517771aSPrabhakar Kushwaha 
298c517771aSPrabhakar Kushwaha static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
299c517771aSPrabhakar Kushwaha {
300c517771aSPrabhakar Kushwaha 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
301c517771aSPrabhakar Kushwaha 	struct dpni_queue_attr rx_queue_attr;
302c919ab9eSPrabhakar Kushwaha 	struct dpmac_link_state	dpmac_link_state = { 0 };
303*5038d3e5SPrabhakar Kushwaha #ifdef DEBUG
304*5038d3e5SPrabhakar Kushwaha 	struct dpni_link_state link_state;
305*5038d3e5SPrabhakar Kushwaha #endif
306c517771aSPrabhakar Kushwaha 	int err;
307c517771aSPrabhakar Kushwaha 
308c517771aSPrabhakar Kushwaha 	if (net_dev->state == ETH_STATE_ACTIVE)
309c517771aSPrabhakar Kushwaha 		return 0;
310c517771aSPrabhakar Kushwaha 
311c919ab9eSPrabhakar Kushwaha 	if (get_mc_boot_status() != 0) {
312c919ab9eSPrabhakar Kushwaha 		printf("ERROR (MC is not booted)\n");
313c919ab9eSPrabhakar Kushwaha 		return -ENODEV;
314c919ab9eSPrabhakar Kushwaha 	}
315c919ab9eSPrabhakar Kushwaha 
316c919ab9eSPrabhakar Kushwaha 	if (get_dpl_apply_status() == 0) {
317c919ab9eSPrabhakar Kushwaha 		printf("ERROR (DPL is deployed. No device available)\n");
318c919ab9eSPrabhakar Kushwaha 		return -ENODEV;
319c919ab9eSPrabhakar Kushwaha 	}
320c919ab9eSPrabhakar Kushwaha 	/* DPMAC initialization */
321c919ab9eSPrabhakar Kushwaha 	err = ldpaa_dpmac_setup(priv);
322c919ab9eSPrabhakar Kushwaha 	if (err < 0)
323c919ab9eSPrabhakar Kushwaha 		goto err_dpmac_setup;
324c919ab9eSPrabhakar Kushwaha 
325c919ab9eSPrabhakar Kushwaha 	/* DPMAC binding DPNI */
326c919ab9eSPrabhakar Kushwaha 	err = ldpaa_dpmac_bind(priv);
327c919ab9eSPrabhakar Kushwaha 	if (err)
328c919ab9eSPrabhakar Kushwaha 		goto err_dpamc_bind;
329c919ab9eSPrabhakar Kushwaha 
330c517771aSPrabhakar Kushwaha 	/* DPNI initialization */
331c517771aSPrabhakar Kushwaha 	err = ldpaa_dpni_setup(priv);
332c517771aSPrabhakar Kushwaha 	if (err < 0)
333c517771aSPrabhakar Kushwaha 		goto err_dpni_setup;
334c517771aSPrabhakar Kushwaha 
335c517771aSPrabhakar Kushwaha 	err = ldpaa_dpbp_setup();
336c517771aSPrabhakar Kushwaha 	if (err < 0)
337c517771aSPrabhakar Kushwaha 		goto err_dpbp_setup;
338c517771aSPrabhakar Kushwaha 
339c517771aSPrabhakar Kushwaha 	/* DPNI binding DPBP */
340c517771aSPrabhakar Kushwaha 	err = ldpaa_dpni_bind(priv);
341c517771aSPrabhakar Kushwaha 	if (err)
342c919ab9eSPrabhakar Kushwaha 		goto err_dpni_bind;
343c517771aSPrabhakar Kushwaha 
3447b2edb8bSPrabhakar Kushwaha 	err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
345c919ab9eSPrabhakar Kushwaha 				dflt_dpni->dpni_handle, net_dev->enetaddr);
346c517771aSPrabhakar Kushwaha 	if (err) {
3477b2edb8bSPrabhakar Kushwaha 		printf("dpni_add_mac_addr() failed\n");
348c517771aSPrabhakar Kushwaha 		return err;
349c517771aSPrabhakar Kushwaha 	}
350c517771aSPrabhakar Kushwaha 
351c517771aSPrabhakar Kushwaha #ifdef CONFIG_PHYLIB
352c517771aSPrabhakar Kushwaha 	/* TODO Check this path */
3535753b0f1SPrabhakar Kushwaha 	err = phy_startup(priv->phydev);
3545753b0f1SPrabhakar Kushwaha 	if (err) {
355c517771aSPrabhakar Kushwaha 		printf("%s: Could not initialize\n", priv->phydev->dev->name);
3565753b0f1SPrabhakar Kushwaha 		return err;
357c517771aSPrabhakar Kushwaha 	}
358c517771aSPrabhakar Kushwaha #else
359c517771aSPrabhakar Kushwaha 	priv->phydev->speed = SPEED_1000;
360c517771aSPrabhakar Kushwaha 	priv->phydev->link = 1;
361c517771aSPrabhakar Kushwaha 	priv->phydev->duplex = DUPLEX_FULL;
362c517771aSPrabhakar Kushwaha #endif
363c517771aSPrabhakar Kushwaha 
364c919ab9eSPrabhakar Kushwaha 	err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
365c517771aSPrabhakar Kushwaha 	if (err < 0) {
366c517771aSPrabhakar Kushwaha 		printf("dpni_enable() failed\n");
367c517771aSPrabhakar Kushwaha 		return err;
368c517771aSPrabhakar Kushwaha 	}
369c517771aSPrabhakar Kushwaha 
370c919ab9eSPrabhakar Kushwaha 	dpmac_link_state.rate = SPEED_1000;
371c919ab9eSPrabhakar Kushwaha 	dpmac_link_state.options = DPMAC_LINK_OPT_AUTONEG;
372c919ab9eSPrabhakar Kushwaha 	dpmac_link_state.up = 1;
373c919ab9eSPrabhakar Kushwaha 	err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
374c919ab9eSPrabhakar Kushwaha 				  priv->dpmac_handle, &dpmac_link_state);
375c919ab9eSPrabhakar Kushwaha 	if (err < 0) {
376c919ab9eSPrabhakar Kushwaha 		printf("dpmac_set_link_state() failed\n");
377c919ab9eSPrabhakar Kushwaha 		return err;
378c919ab9eSPrabhakar Kushwaha 	}
379*5038d3e5SPrabhakar Kushwaha 
380*5038d3e5SPrabhakar Kushwaha #ifdef DEBUG
381*5038d3e5SPrabhakar Kushwaha 	err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
382*5038d3e5SPrabhakar Kushwaha 				  dflt_dpni->dpni_handle, &link_state);
383*5038d3e5SPrabhakar Kushwaha 	if (err < 0) {
384*5038d3e5SPrabhakar Kushwaha 		printf("dpni_get_link_state() failed\n");
385*5038d3e5SPrabhakar Kushwaha 		return err;
386*5038d3e5SPrabhakar Kushwaha 	}
387*5038d3e5SPrabhakar Kushwaha 
388*5038d3e5SPrabhakar Kushwaha 	printf("link status: %d - ", link_state.up);
389*5038d3e5SPrabhakar Kushwaha 	link_state.up == 0 ? printf("down\n") :
390*5038d3e5SPrabhakar Kushwaha 	link_state.up == 1 ? printf("up\n") : printf("error state\n");
391*5038d3e5SPrabhakar Kushwaha #endif
392*5038d3e5SPrabhakar Kushwaha 
393c517771aSPrabhakar Kushwaha 	/* TODO: support multiple Rx flows */
394c919ab9eSPrabhakar Kushwaha 	err = dpni_get_rx_flow(dflt_mc_io, MC_CMD_NO_FLAGS,
395c919ab9eSPrabhakar Kushwaha 			       dflt_dpni->dpni_handle, 0, 0, &rx_queue_attr);
396c517771aSPrabhakar Kushwaha 	if (err) {
397c517771aSPrabhakar Kushwaha 		printf("dpni_get_rx_flow() failed\n");
398c517771aSPrabhakar Kushwaha 		goto err_rx_flow;
399c517771aSPrabhakar Kushwaha 	}
400c517771aSPrabhakar Kushwaha 
401c517771aSPrabhakar Kushwaha 	priv->rx_dflt_fqid = rx_queue_attr.fqid;
402c517771aSPrabhakar Kushwaha 
403c919ab9eSPrabhakar Kushwaha 	err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
40487457d11SPrabhakar Kushwaha 			    &priv->tx_qdid);
405c517771aSPrabhakar Kushwaha 	if (err) {
406c517771aSPrabhakar Kushwaha 		printf("dpni_get_qdid() failed\n");
407c517771aSPrabhakar Kushwaha 		goto err_qdid;
408c517771aSPrabhakar Kushwaha 	}
409c517771aSPrabhakar Kushwaha 
410c517771aSPrabhakar Kushwaha 	if (!priv->phydev->link)
411c517771aSPrabhakar Kushwaha 		printf("%s: No link.\n", priv->phydev->dev->name);
412c517771aSPrabhakar Kushwaha 
413c517771aSPrabhakar Kushwaha 	return priv->phydev->link ? 0 : -1;
414c517771aSPrabhakar Kushwaha 
415c517771aSPrabhakar Kushwaha err_qdid:
416c517771aSPrabhakar Kushwaha err_rx_flow:
417c919ab9eSPrabhakar Kushwaha 	dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
418c919ab9eSPrabhakar Kushwaha err_dpni_bind:
419c517771aSPrabhakar Kushwaha 	ldpaa_dpbp_free();
420c517771aSPrabhakar Kushwaha err_dpbp_setup:
421c919ab9eSPrabhakar Kushwaha err_dpamc_bind:
422c919ab9eSPrabhakar Kushwaha 	dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
423c517771aSPrabhakar Kushwaha err_dpni_setup:
424c919ab9eSPrabhakar Kushwaha err_dpmac_setup:
425c517771aSPrabhakar Kushwaha 	return err;
426c517771aSPrabhakar Kushwaha }
427c517771aSPrabhakar Kushwaha 
428c517771aSPrabhakar Kushwaha static void ldpaa_eth_stop(struct eth_device *net_dev)
429c517771aSPrabhakar Kushwaha {
430c517771aSPrabhakar Kushwaha 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
431c517771aSPrabhakar Kushwaha 	int err = 0;
432c517771aSPrabhakar Kushwaha 
4335753b0f1SPrabhakar Kushwaha 	if ((net_dev->state == ETH_STATE_PASSIVE) ||
4345753b0f1SPrabhakar Kushwaha 	    (net_dev->state == ETH_STATE_INIT))
435c517771aSPrabhakar Kushwaha 		return;
436c919ab9eSPrabhakar Kushwaha 
437*5038d3e5SPrabhakar Kushwaha #ifdef DEBUG
438*5038d3e5SPrabhakar Kushwaha 	ldpaa_eth_get_dpni_counter();
439*5038d3e5SPrabhakar Kushwaha #endif
440*5038d3e5SPrabhakar Kushwaha 
441c919ab9eSPrabhakar Kushwaha 	err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
442c919ab9eSPrabhakar Kushwaha 			      dflt_dprc_handle, &dpmac_endpoint);
443c919ab9eSPrabhakar Kushwaha 	if (err < 0)
444c919ab9eSPrabhakar Kushwaha 		printf("dprc_disconnect() failed dpmac_endpoint\n");
445c919ab9eSPrabhakar Kushwaha 
446c919ab9eSPrabhakar Kushwaha 	err = dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
447c919ab9eSPrabhakar Kushwaha 	if (err < 0)
448c919ab9eSPrabhakar Kushwaha 		printf("dpmac_destroy() failed\n");
449c919ab9eSPrabhakar Kushwaha 
450c517771aSPrabhakar Kushwaha 	/* Stop Tx and Rx traffic */
451c919ab9eSPrabhakar Kushwaha 	err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
452c517771aSPrabhakar Kushwaha 	if (err < 0)
453c517771aSPrabhakar Kushwaha 		printf("dpni_disable() failed\n");
454c517771aSPrabhakar Kushwaha 
455c517771aSPrabhakar Kushwaha #ifdef CONFIG_PHYLIB
456c517771aSPrabhakar Kushwaha 	phy_shutdown(priv->phydev);
457c517771aSPrabhakar Kushwaha #endif
458c517771aSPrabhakar Kushwaha 
459c517771aSPrabhakar Kushwaha 	ldpaa_dpbp_free();
460c919ab9eSPrabhakar Kushwaha 	dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
461c919ab9eSPrabhakar Kushwaha 	dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
462c517771aSPrabhakar Kushwaha }
463c517771aSPrabhakar Kushwaha 
464c517771aSPrabhakar Kushwaha static void ldpaa_dpbp_drain_cnt(int count)
465c517771aSPrabhakar Kushwaha {
466c517771aSPrabhakar Kushwaha 	uint64_t buf_array[7];
467c517771aSPrabhakar Kushwaha 	void *addr;
468c517771aSPrabhakar Kushwaha 	int ret, i;
469c517771aSPrabhakar Kushwaha 
470c517771aSPrabhakar Kushwaha 	BUG_ON(count > 7);
471c517771aSPrabhakar Kushwaha 
472c517771aSPrabhakar Kushwaha 	do {
473c517771aSPrabhakar Kushwaha 		ret = qbman_swp_acquire(dflt_dpio->sw_portal,
474c517771aSPrabhakar Kushwaha 					dflt_dpbp->dpbp_attr.bpid,
475c517771aSPrabhakar Kushwaha 					buf_array, count);
476c517771aSPrabhakar Kushwaha 		if (ret < 0) {
477c517771aSPrabhakar Kushwaha 			printf("qbman_swp_acquire() failed\n");
478c517771aSPrabhakar Kushwaha 			return;
479c517771aSPrabhakar Kushwaha 		}
480c517771aSPrabhakar Kushwaha 		for (i = 0; i < ret; i++) {
481c517771aSPrabhakar Kushwaha 			addr = (void *)buf_array[i];
482c517771aSPrabhakar Kushwaha 			debug("Free: buffer addr =0x%p\n", addr);
483c517771aSPrabhakar Kushwaha 			free(addr);
484c517771aSPrabhakar Kushwaha 		}
485c517771aSPrabhakar Kushwaha 	} while (ret);
486c517771aSPrabhakar Kushwaha }
487c517771aSPrabhakar Kushwaha 
488c517771aSPrabhakar Kushwaha static void ldpaa_dpbp_drain(void)
489c517771aSPrabhakar Kushwaha {
490c517771aSPrabhakar Kushwaha 	int i;
491c517771aSPrabhakar Kushwaha 	for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
492c517771aSPrabhakar Kushwaha 		ldpaa_dpbp_drain_cnt(7);
493c517771aSPrabhakar Kushwaha }
494c517771aSPrabhakar Kushwaha 
495c517771aSPrabhakar Kushwaha static int ldpaa_bp_add_7(uint16_t bpid)
496c517771aSPrabhakar Kushwaha {
497c517771aSPrabhakar Kushwaha 	uint64_t buf_array[7];
498c517771aSPrabhakar Kushwaha 	u8 *addr;
499c517771aSPrabhakar Kushwaha 	int i;
500c517771aSPrabhakar Kushwaha 	struct qbman_release_desc rd;
501c517771aSPrabhakar Kushwaha 
502c517771aSPrabhakar Kushwaha 	for (i = 0; i < 7; i++) {
503c517771aSPrabhakar Kushwaha 		addr = memalign(L1_CACHE_BYTES, LDPAA_ETH_RX_BUFFER_SIZE);
504c517771aSPrabhakar Kushwaha 		if (!addr) {
505c517771aSPrabhakar Kushwaha 			printf("addr allocation failed\n");
506c517771aSPrabhakar Kushwaha 			goto err_alloc;
507c517771aSPrabhakar Kushwaha 		}
508c517771aSPrabhakar Kushwaha 		memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
5095753b0f1SPrabhakar Kushwaha 		flush_dcache_range((u64)addr,
5105753b0f1SPrabhakar Kushwaha 				   (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
511c517771aSPrabhakar Kushwaha 
512c517771aSPrabhakar Kushwaha 		buf_array[i] = (uint64_t)addr;
513c517771aSPrabhakar Kushwaha 		debug("Release: buffer addr =0x%p\n", addr);
514c517771aSPrabhakar Kushwaha 	}
515c517771aSPrabhakar Kushwaha 
516c517771aSPrabhakar Kushwaha release_bufs:
517c517771aSPrabhakar Kushwaha 	/* In case the portal is busy, retry until successful.
518c517771aSPrabhakar Kushwaha 	 * This function is guaranteed to succeed in a reasonable amount
519c517771aSPrabhakar Kushwaha 	 * of time.
520c517771aSPrabhakar Kushwaha 	 */
521c517771aSPrabhakar Kushwaha 
522c517771aSPrabhakar Kushwaha 	do {
523c517771aSPrabhakar Kushwaha 		mdelay(1);
524c517771aSPrabhakar Kushwaha 		qbman_release_desc_clear(&rd);
525c517771aSPrabhakar Kushwaha 		qbman_release_desc_set_bpid(&rd, bpid);
526c517771aSPrabhakar Kushwaha 	} while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
527c517771aSPrabhakar Kushwaha 
528c517771aSPrabhakar Kushwaha 	return i;
529c517771aSPrabhakar Kushwaha 
530c517771aSPrabhakar Kushwaha err_alloc:
531c517771aSPrabhakar Kushwaha 	if (i)
532c517771aSPrabhakar Kushwaha 		goto release_bufs;
533c517771aSPrabhakar Kushwaha 
534c517771aSPrabhakar Kushwaha 	return 0;
535c517771aSPrabhakar Kushwaha }
536c517771aSPrabhakar Kushwaha 
537c517771aSPrabhakar Kushwaha static int ldpaa_dpbp_seed(uint16_t bpid)
538c517771aSPrabhakar Kushwaha {
539c517771aSPrabhakar Kushwaha 	int i;
540c517771aSPrabhakar Kushwaha 	int count;
541c517771aSPrabhakar Kushwaha 
542c517771aSPrabhakar Kushwaha 	for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
543c517771aSPrabhakar Kushwaha 		count = ldpaa_bp_add_7(bpid);
544c517771aSPrabhakar Kushwaha 		if (count < 7)
545c517771aSPrabhakar Kushwaha 			printf("Buffer Seed= %d\n", count);
546c517771aSPrabhakar Kushwaha 	}
547c517771aSPrabhakar Kushwaha 
548c517771aSPrabhakar Kushwaha 	return 0;
549c517771aSPrabhakar Kushwaha }
550c517771aSPrabhakar Kushwaha 
551c517771aSPrabhakar Kushwaha static int ldpaa_dpbp_setup(void)
552c517771aSPrabhakar Kushwaha {
553c517771aSPrabhakar Kushwaha 	int err;
554c517771aSPrabhakar Kushwaha 
55587457d11SPrabhakar Kushwaha 	err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
556c517771aSPrabhakar Kushwaha 			&dflt_dpbp->dpbp_handle);
557c517771aSPrabhakar Kushwaha 	if (err) {
558c517771aSPrabhakar Kushwaha 		printf("dpbp_open() failed\n");
559c517771aSPrabhakar Kushwaha 		goto err_open;
560c517771aSPrabhakar Kushwaha 	}
561c517771aSPrabhakar Kushwaha 
56287457d11SPrabhakar Kushwaha 	err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
563c517771aSPrabhakar Kushwaha 	if (err) {
564c517771aSPrabhakar Kushwaha 		printf("dpbp_enable() failed\n");
565c517771aSPrabhakar Kushwaha 		goto err_enable;
566c517771aSPrabhakar Kushwaha 	}
567c517771aSPrabhakar Kushwaha 
56887457d11SPrabhakar Kushwaha 	err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
56987457d11SPrabhakar Kushwaha 				  dflt_dpbp->dpbp_handle,
570c517771aSPrabhakar Kushwaha 				  &dflt_dpbp->dpbp_attr);
571c517771aSPrabhakar Kushwaha 	if (err) {
572c517771aSPrabhakar Kushwaha 		printf("dpbp_get_attributes() failed\n");
573c517771aSPrabhakar Kushwaha 		goto err_get_attr;
574c517771aSPrabhakar Kushwaha 	}
575c517771aSPrabhakar Kushwaha 
576c517771aSPrabhakar Kushwaha 	err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
577c517771aSPrabhakar Kushwaha 	if (err) {
578c517771aSPrabhakar Kushwaha 		printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
579c517771aSPrabhakar Kushwaha 		       dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
580c517771aSPrabhakar Kushwaha 		goto err_seed;
581c517771aSPrabhakar Kushwaha 	}
582c517771aSPrabhakar Kushwaha 
583c517771aSPrabhakar Kushwaha 	return 0;
584c517771aSPrabhakar Kushwaha 
585c517771aSPrabhakar Kushwaha err_seed:
586c517771aSPrabhakar Kushwaha err_get_attr:
58787457d11SPrabhakar Kushwaha 	dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
588c517771aSPrabhakar Kushwaha err_enable:
58987457d11SPrabhakar Kushwaha 	dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
590c517771aSPrabhakar Kushwaha err_open:
591c517771aSPrabhakar Kushwaha 	return err;
592c517771aSPrabhakar Kushwaha }
593c517771aSPrabhakar Kushwaha 
594c517771aSPrabhakar Kushwaha static void ldpaa_dpbp_free(void)
595c517771aSPrabhakar Kushwaha {
596c517771aSPrabhakar Kushwaha 	ldpaa_dpbp_drain();
59787457d11SPrabhakar Kushwaha 	dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
59887457d11SPrabhakar Kushwaha 	dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
59987457d11SPrabhakar Kushwaha 	dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
600c517771aSPrabhakar Kushwaha }
601c517771aSPrabhakar Kushwaha 
602c919ab9eSPrabhakar Kushwaha static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
603c919ab9eSPrabhakar Kushwaha {
604c919ab9eSPrabhakar Kushwaha 	int err = 0;
605c919ab9eSPrabhakar Kushwaha 	struct dpmac_cfg dpmac_cfg;
606c919ab9eSPrabhakar Kushwaha 
607c919ab9eSPrabhakar Kushwaha 	dpmac_cfg.mac_id = priv->dpmac_id;
608c919ab9eSPrabhakar Kushwaha 	err = dpmac_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpmac_cfg,
609c919ab9eSPrabhakar Kushwaha 			  &priv->dpmac_handle);
610c919ab9eSPrabhakar Kushwaha 	if (err)
611c919ab9eSPrabhakar Kushwaha 		printf("dpmac_create() failed\n");
612c919ab9eSPrabhakar Kushwaha 	return err;
613c919ab9eSPrabhakar Kushwaha }
614c919ab9eSPrabhakar Kushwaha 
615c919ab9eSPrabhakar Kushwaha static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
616c919ab9eSPrabhakar Kushwaha {
617c919ab9eSPrabhakar Kushwaha 	int err = 0;
618c919ab9eSPrabhakar Kushwaha 	struct dprc_connection_cfg dprc_connection_cfg = {
619c919ab9eSPrabhakar Kushwaha 		/* If both rates are zero the connection */
620c919ab9eSPrabhakar Kushwaha 		/* will be configured in "best effort" mode. */
621c919ab9eSPrabhakar Kushwaha 		.committed_rate = 0,
622c919ab9eSPrabhakar Kushwaha 		.max_rate = 0
623c919ab9eSPrabhakar Kushwaha 	};
624c919ab9eSPrabhakar Kushwaha 
625*5038d3e5SPrabhakar Kushwaha #ifdef DEBUG
626*5038d3e5SPrabhakar Kushwaha 	struct dprc_endpoint dbg_endpoint;
627*5038d3e5SPrabhakar Kushwaha 	int state = 0;
628*5038d3e5SPrabhakar Kushwaha #endif
629*5038d3e5SPrabhakar Kushwaha 
630c919ab9eSPrabhakar Kushwaha 	memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
631c919ab9eSPrabhakar Kushwaha 	sprintf(dpmac_endpoint.type, "dpmac");
632c919ab9eSPrabhakar Kushwaha 	dpmac_endpoint.id = priv->dpmac_id;
633c919ab9eSPrabhakar Kushwaha 
634c919ab9eSPrabhakar Kushwaha 	memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
635c919ab9eSPrabhakar Kushwaha 	sprintf(dpni_endpoint.type, "dpni");
636c919ab9eSPrabhakar Kushwaha 	dpni_endpoint.id = dflt_dpni->dpni_id;
637c919ab9eSPrabhakar Kushwaha 
638c919ab9eSPrabhakar Kushwaha 	err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
639c919ab9eSPrabhakar Kushwaha 			     dflt_dprc_handle,
640c919ab9eSPrabhakar Kushwaha 			     &dpmac_endpoint,
641c919ab9eSPrabhakar Kushwaha 			     &dpni_endpoint,
642c919ab9eSPrabhakar Kushwaha 			     &dprc_connection_cfg);
643*5038d3e5SPrabhakar Kushwaha 	if (err)
644*5038d3e5SPrabhakar Kushwaha 		printf("dprc_connect() failed\n");
645*5038d3e5SPrabhakar Kushwaha 
646*5038d3e5SPrabhakar Kushwaha #ifdef DEBUG
647*5038d3e5SPrabhakar Kushwaha 	err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
648*5038d3e5SPrabhakar Kushwaha 				    dflt_dprc_handle, &dpni_endpoint,
649*5038d3e5SPrabhakar Kushwaha 				    &dbg_endpoint, &state);
650*5038d3e5SPrabhakar Kushwaha 	printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
651*5038d3e5SPrabhakar Kushwaha 	printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
652*5038d3e5SPrabhakar Kushwaha 	printf("%s, DPMAC State= %d\n", __func__, state);
653*5038d3e5SPrabhakar Kushwaha 
654*5038d3e5SPrabhakar Kushwaha 	memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
655*5038d3e5SPrabhakar Kushwaha 	err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
656*5038d3e5SPrabhakar Kushwaha 				    dflt_dprc_handle, &dpmac_endpoint,
657*5038d3e5SPrabhakar Kushwaha 				    &dbg_endpoint, &state);
658*5038d3e5SPrabhakar Kushwaha 	printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
659*5038d3e5SPrabhakar Kushwaha 	printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
660*5038d3e5SPrabhakar Kushwaha 	printf("%s, DPNI State= %d\n", __func__, state);
661*5038d3e5SPrabhakar Kushwaha #endif
662c919ab9eSPrabhakar Kushwaha 	return err;
663c919ab9eSPrabhakar Kushwaha }
664c919ab9eSPrabhakar Kushwaha 
665c517771aSPrabhakar Kushwaha static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
666c517771aSPrabhakar Kushwaha {
667c517771aSPrabhakar Kushwaha 	int err;
668c517771aSPrabhakar Kushwaha 
669c517771aSPrabhakar Kushwaha 	/* and get a handle for the DPNI this interface is associate with */
670c919ab9eSPrabhakar Kushwaha 	err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
671c919ab9eSPrabhakar Kushwaha 			&dflt_dpni->dpni_handle);
672c517771aSPrabhakar Kushwaha 	if (err) {
673c517771aSPrabhakar Kushwaha 		printf("dpni_open() failed\n");
674c517771aSPrabhakar Kushwaha 		goto err_open;
675c517771aSPrabhakar Kushwaha 	}
676c517771aSPrabhakar Kushwaha 
67787457d11SPrabhakar Kushwaha 	err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
678c919ab9eSPrabhakar Kushwaha 				  dflt_dpni->dpni_handle,
679c919ab9eSPrabhakar Kushwaha 				  &dflt_dpni->dpni_attrs);
680c517771aSPrabhakar Kushwaha 	if (err) {
681c517771aSPrabhakar Kushwaha 		printf("dpni_get_attributes() failed (err=%d)\n", err);
682c517771aSPrabhakar Kushwaha 		goto err_get_attr;
683c517771aSPrabhakar Kushwaha 	}
684c517771aSPrabhakar Kushwaha 
685c517771aSPrabhakar Kushwaha 	/* Configure our buffers' layout */
686c919ab9eSPrabhakar Kushwaha 	dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
687c517771aSPrabhakar Kushwaha 				   DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
688c517771aSPrabhakar Kushwaha 				   DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
689c919ab9eSPrabhakar Kushwaha 	dflt_dpni->buf_layout.pass_parser_result = true;
690c919ab9eSPrabhakar Kushwaha 	dflt_dpni->buf_layout.pass_frame_status = true;
691c919ab9eSPrabhakar Kushwaha 	dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
692c517771aSPrabhakar Kushwaha 	/* ...rx, ... */
69387457d11SPrabhakar Kushwaha 	err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
694c919ab9eSPrabhakar Kushwaha 					dflt_dpni->dpni_handle,
695c919ab9eSPrabhakar Kushwaha 					&dflt_dpni->buf_layout);
696c517771aSPrabhakar Kushwaha 	if (err) {
697c517771aSPrabhakar Kushwaha 		printf("dpni_set_rx_buffer_layout() failed");
698c517771aSPrabhakar Kushwaha 		goto err_buf_layout;
699c517771aSPrabhakar Kushwaha 	}
700c517771aSPrabhakar Kushwaha 
701c517771aSPrabhakar Kushwaha 	/* ... tx, ... */
702c919ab9eSPrabhakar Kushwaha 	dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PARSER_RESULT;
70387457d11SPrabhakar Kushwaha 	err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
704c919ab9eSPrabhakar Kushwaha 					dflt_dpni->dpni_handle,
705c919ab9eSPrabhakar Kushwaha 					&dflt_dpni->buf_layout);
706c517771aSPrabhakar Kushwaha 	if (err) {
707c517771aSPrabhakar Kushwaha 		printf("dpni_set_tx_buffer_layout() failed");
708c517771aSPrabhakar Kushwaha 		goto err_buf_layout;
709c517771aSPrabhakar Kushwaha 	}
710c517771aSPrabhakar Kushwaha 
711c517771aSPrabhakar Kushwaha 	/* ... tx-confirm. */
712c919ab9eSPrabhakar Kushwaha 	dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
71387457d11SPrabhakar Kushwaha 	err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
714c919ab9eSPrabhakar Kushwaha 					     dflt_dpni->dpni_handle,
715c919ab9eSPrabhakar Kushwaha 					     &dflt_dpni->buf_layout);
716c517771aSPrabhakar Kushwaha 	if (err) {
717c517771aSPrabhakar Kushwaha 		printf("dpni_set_tx_conf_buffer_layout() failed");
718c517771aSPrabhakar Kushwaha 		goto err_buf_layout;
719c517771aSPrabhakar Kushwaha 	}
720c517771aSPrabhakar Kushwaha 
721c517771aSPrabhakar Kushwaha 	/* Now that we've set our tx buffer layout, retrieve the minimum
722c517771aSPrabhakar Kushwaha 	 * required tx data offset.
723c517771aSPrabhakar Kushwaha 	 */
72487457d11SPrabhakar Kushwaha 	err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
725c919ab9eSPrabhakar Kushwaha 				      dflt_dpni->dpni_handle,
726c919ab9eSPrabhakar Kushwaha 				      &priv->tx_data_offset);
727c517771aSPrabhakar Kushwaha 	if (err) {
728c517771aSPrabhakar Kushwaha 		printf("dpni_get_tx_data_offset() failed\n");
729c517771aSPrabhakar Kushwaha 		goto err_data_offset;
730c517771aSPrabhakar Kushwaha 	}
731c517771aSPrabhakar Kushwaha 
732c517771aSPrabhakar Kushwaha 	/* Warn in case TX data offset is not multiple of 64 bytes. */
733c517771aSPrabhakar Kushwaha 	WARN_ON(priv->tx_data_offset % 64);
734c517771aSPrabhakar Kushwaha 
735c517771aSPrabhakar Kushwaha 	/* Accomodate SWA space. */
736c517771aSPrabhakar Kushwaha 	priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
737c517771aSPrabhakar Kushwaha 	debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
738c517771aSPrabhakar Kushwaha 
739c517771aSPrabhakar Kushwaha 	return 0;
740c517771aSPrabhakar Kushwaha 
741c517771aSPrabhakar Kushwaha err_data_offset:
742c517771aSPrabhakar Kushwaha err_buf_layout:
743c517771aSPrabhakar Kushwaha err_get_attr:
744c919ab9eSPrabhakar Kushwaha 	dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
745c517771aSPrabhakar Kushwaha err_open:
746c517771aSPrabhakar Kushwaha 	return err;
747c517771aSPrabhakar Kushwaha }
748c517771aSPrabhakar Kushwaha 
749c517771aSPrabhakar Kushwaha static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
750c517771aSPrabhakar Kushwaha {
751c517771aSPrabhakar Kushwaha 	struct dpni_pools_cfg pools_params;
752c517771aSPrabhakar Kushwaha 	struct dpni_tx_flow_cfg dflt_tx_flow;
753c517771aSPrabhakar Kushwaha 	int err = 0;
754c517771aSPrabhakar Kushwaha 
755c517771aSPrabhakar Kushwaha 	pools_params.num_dpbp = 1;
756c517771aSPrabhakar Kushwaha 	pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
757c517771aSPrabhakar Kushwaha 	pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
758c919ab9eSPrabhakar Kushwaha 	err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
759c919ab9eSPrabhakar Kushwaha 			     dflt_dpni->dpni_handle, &pools_params);
760c517771aSPrabhakar Kushwaha 	if (err) {
761c517771aSPrabhakar Kushwaha 		printf("dpni_set_pools() failed\n");
762c517771aSPrabhakar Kushwaha 		return err;
763c517771aSPrabhakar Kushwaha 	}
764c517771aSPrabhakar Kushwaha 
765c517771aSPrabhakar Kushwaha 	priv->tx_flow_id = DPNI_NEW_FLOW_ID;
766c517771aSPrabhakar Kushwaha 	memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
767c517771aSPrabhakar Kushwaha 
7680c7c87a4SPrabhakar Kushwaha 	dflt_tx_flow.options = DPNI_TX_FLOW_OPT_ONLY_TX_ERROR;
7690c7c87a4SPrabhakar Kushwaha 	dflt_tx_flow.conf_err_cfg.use_default_queue = 0;
7700c7c87a4SPrabhakar Kushwaha 	dflt_tx_flow.conf_err_cfg.errors_only = 1;
771c919ab9eSPrabhakar Kushwaha 	err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS,
772c919ab9eSPrabhakar Kushwaha 			       dflt_dpni->dpni_handle, &priv->tx_flow_id,
773c919ab9eSPrabhakar Kushwaha 			       &dflt_tx_flow);
774c517771aSPrabhakar Kushwaha 	if (err) {
775c517771aSPrabhakar Kushwaha 		printf("dpni_set_tx_flow() failed\n");
776c517771aSPrabhakar Kushwaha 		return err;
777c517771aSPrabhakar Kushwaha 	}
778c517771aSPrabhakar Kushwaha 
779c517771aSPrabhakar Kushwaha 	return 0;
780c517771aSPrabhakar Kushwaha }
781c517771aSPrabhakar Kushwaha 
782c919ab9eSPrabhakar Kushwaha static int ldpaa_eth_netdev_init(struct eth_device *net_dev,
783c919ab9eSPrabhakar Kushwaha 				 phy_interface_t enet_if)
784c517771aSPrabhakar Kushwaha {
785c517771aSPrabhakar Kushwaha 	int err;
786c517771aSPrabhakar Kushwaha 	struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
787c517771aSPrabhakar Kushwaha 
788c919ab9eSPrabhakar Kushwaha 	sprintf(net_dev->name, "DPMAC%d@%s", priv->dpmac_id,
789c919ab9eSPrabhakar Kushwaha 		phy_interface_strings[enet_if]);
790c517771aSPrabhakar Kushwaha 
791c517771aSPrabhakar Kushwaha 	net_dev->iobase = 0;
792c517771aSPrabhakar Kushwaha 	net_dev->init = ldpaa_eth_open;
793c517771aSPrabhakar Kushwaha 	net_dev->halt = ldpaa_eth_stop;
794c517771aSPrabhakar Kushwaha 	net_dev->send = ldpaa_eth_tx;
795c517771aSPrabhakar Kushwaha 	net_dev->recv = ldpaa_eth_pull_dequeue_rx;
796c517771aSPrabhakar Kushwaha /*
797c517771aSPrabhakar Kushwaha 	TODO: PHY MDIO information
798c517771aSPrabhakar Kushwaha 	priv->bus = info->bus;
799c517771aSPrabhakar Kushwaha 	priv->phyaddr = info->phy_addr;
800c517771aSPrabhakar Kushwaha 	priv->enet_if = info->enet_if;
801c517771aSPrabhakar Kushwaha */
802c517771aSPrabhakar Kushwaha 
803c517771aSPrabhakar Kushwaha 	if (init_phy(net_dev))
804c517771aSPrabhakar Kushwaha 		return 0;
805c517771aSPrabhakar Kushwaha 
806c517771aSPrabhakar Kushwaha 	err = eth_register(net_dev);
807c517771aSPrabhakar Kushwaha 	if (err < 0) {
808c517771aSPrabhakar Kushwaha 		printf("eth_register() = %d\n", err);
809c517771aSPrabhakar Kushwaha 		return err;
810c517771aSPrabhakar Kushwaha 	}
811c517771aSPrabhakar Kushwaha 
812c517771aSPrabhakar Kushwaha 	return 0;
813c517771aSPrabhakar Kushwaha }
814c517771aSPrabhakar Kushwaha 
815c919ab9eSPrabhakar Kushwaha int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
816c517771aSPrabhakar Kushwaha {
817c517771aSPrabhakar Kushwaha 	struct eth_device		*net_dev = NULL;
818c517771aSPrabhakar Kushwaha 	struct ldpaa_eth_priv		*priv = NULL;
819c517771aSPrabhakar Kushwaha 	int				err = 0;
820c517771aSPrabhakar Kushwaha 
821c517771aSPrabhakar Kushwaha 
822c517771aSPrabhakar Kushwaha 	/* Net device */
823c517771aSPrabhakar Kushwaha 	net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
824c517771aSPrabhakar Kushwaha 	if (!net_dev) {
825c517771aSPrabhakar Kushwaha 		printf("eth_device malloc() failed\n");
826c517771aSPrabhakar Kushwaha 		return -ENOMEM;
827c517771aSPrabhakar Kushwaha 	}
828c517771aSPrabhakar Kushwaha 	memset(net_dev, 0, sizeof(struct eth_device));
829c517771aSPrabhakar Kushwaha 
830c517771aSPrabhakar Kushwaha 	/* alloc the ldpaa ethernet private struct */
831c517771aSPrabhakar Kushwaha 	priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
832c517771aSPrabhakar Kushwaha 	if (!priv) {
833c517771aSPrabhakar Kushwaha 		printf("ldpaa_eth_priv malloc() failed\n");
834c517771aSPrabhakar Kushwaha 		return -ENOMEM;
835c517771aSPrabhakar Kushwaha 	}
836c517771aSPrabhakar Kushwaha 	memset(priv, 0, sizeof(struct ldpaa_eth_priv));
837c517771aSPrabhakar Kushwaha 
838c517771aSPrabhakar Kushwaha 	net_dev->priv = (void *)priv;
839c517771aSPrabhakar Kushwaha 	priv->net_dev = (struct eth_device *)net_dev;
840c919ab9eSPrabhakar Kushwaha 	priv->dpmac_id = dpmac_id;
841c919ab9eSPrabhakar Kushwaha 	debug("%s dpmac_id=%d\n", __func__, dpmac_id);
842c517771aSPrabhakar Kushwaha 
843c919ab9eSPrabhakar Kushwaha 	err = ldpaa_eth_netdev_init(net_dev, enet_if);
844c517771aSPrabhakar Kushwaha 	if (err)
845c517771aSPrabhakar Kushwaha 		goto err_netdev_init;
846c517771aSPrabhakar Kushwaha 
847c517771aSPrabhakar Kushwaha 	debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
848c517771aSPrabhakar Kushwaha 	return 0;
849c517771aSPrabhakar Kushwaha 
850c517771aSPrabhakar Kushwaha err_netdev_init:
851c517771aSPrabhakar Kushwaha 	free(priv);
852c517771aSPrabhakar Kushwaha 	net_dev->priv = NULL;
853c517771aSPrabhakar Kushwaha 	free(net_dev);
854c517771aSPrabhakar Kushwaha 
855c517771aSPrabhakar Kushwaha 	return err;
856c517771aSPrabhakar Kushwaha }
857