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