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