blob: a3b9c152b256825b97bddc3d1a247de93c605495 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07002/*
Yogesh Gaur1a0c4ae2018-05-09 10:52:17 +05303 * Copyright 2014-2016 Freescale Semiconductor, Inc.
Yogesh Gaur318c32f2017-11-15 11:59:31 +05304 * Copyright 2017 NXP
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07005 */
6
7#include <common.h>
Simon Glass63334482019-11-14 12:57:39 -07008#include <cpu_func.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07009#include <asm/io.h>
10#include <asm/types.h>
11#include <malloc.h>
12#include <net.h>
13#include <hwconfig.h>
14#include <phy.h>
15#include <linux/compat.h>
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +053016#include <fsl-mc/fsl_dpmac.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070017
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053018#include <fsl-mc/ldpaa_wriop.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070019#include "ldpaa_eth.h"
20
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053021#ifdef CONFIG_PHYLIB
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070022static int init_phy(struct eth_device *dev)
23{
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053024 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
25 struct phy_device *phydev = NULL;
26 struct mii_dev *bus;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +053027 int phy_addr, phy_num;
28 int ret = 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070029
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053030 bus = wriop_get_mdio(priv->dpmac_id);
31 if (bus == NULL)
32 return 0;
33
Pankaj Bansal50adb5e2018-10-10 14:08:34 +053034 for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
35 phy_addr = wriop_get_phy_address(priv->dpmac_id, phy_num);
36 if (phy_addr < 0)
37 continue;
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053038
Pankaj Bansal50adb5e2018-10-10 14:08:34 +053039 phydev = phy_connect(bus, phy_addr, dev,
40 wriop_get_enet_if(priv->dpmac_id));
41 if (!phydev) {
42 printf("Failed to connect\n");
43 ret = -ENODEV;
44 break;
45 }
46 wriop_set_phy_dev(priv->dpmac_id, phy_num, phydev);
47 ret = phy_config(phydev);
48 if (ret)
49 break;
50 }
Pankaj Bansalff076d72018-10-10 14:08:31 +053051
52 if (ret) {
Pankaj Bansal50adb5e2018-10-10 14:08:34 +053053 for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
54 phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
55 if (!phydev)
56 continue;
57
58 free(phydev);
59 wriop_set_phy_dev(priv->dpmac_id, phy_num, NULL);
60 }
Pankaj Bansalff076d72018-10-10 14:08:31 +053061 }
62
63 return ret;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070064}
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053065#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070066
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053067#ifdef DEBUG
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053068
Yogesh Gaur318c32f2017-11-15 11:59:31 +053069#define DPNI_STATS_PER_PAGE 6
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053070
Yogesh Gaur318c32f2017-11-15 11:59:31 +053071static const char *dpni_statistics[][DPNI_STATS_PER_PAGE] = {
72 {
73 "DPNI_CNT_ING_ALL_FRAMES",
74 "DPNI_CNT_ING_ALL_BYTES",
75 "DPNI_CNT_ING_MCAST_FRAMES",
76 "DPNI_CNT_ING_MCAST_BYTES",
77 "DPNI_CNT_ING_BCAST_FRAMES",
78 "DPNI_CNT_ING_BCAST_BYTES",
79 }, {
80 "DPNI_CNT_EGR_ALL_FRAMES",
81 "DPNI_CNT_EGR_ALL_BYTES",
82 "DPNI_CNT_EGR_MCAST_FRAMES",
83 "DPNI_CNT_EGR_MCAST_BYTES",
84 "DPNI_CNT_EGR_BCAST_FRAMES",
85 "DPNI_CNT_EGR_BCAST_BYTES",
86 }, {
87 "DPNI_CNT_ING_FILTERED_FRAMES",
88 "DPNI_CNT_ING_DISCARDED_FRAMES",
89 "DPNI_CNT_ING_NOBUFFER_DISCARDS",
90 "DPNI_CNT_EGR_DISCARDED_FRAMES",
91 "DPNI_CNT_EGR_CNF_FRAMES",
92 ""
93 },
94};
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053095
Yogesh Gaur318c32f2017-11-15 11:59:31 +053096static void print_dpni_stats(const char *strings[],
97 struct dpni_statistics dpni_stats)
98{
99 uint64_t *stat;
100 int i;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530101
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530102 stat = (uint64_t *)&dpni_stats;
103 for (i = 0; i < DPNI_STATS_PER_PAGE; i++) {
104 if (strcmp(strings[i], "\0") == 0)
105 break;
106 printf("%s= %llu\n", strings[i], *stat);
107 stat++;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530108 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530109}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530110
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530111static void ldpaa_eth_get_dpni_counter(void)
112{
113 int err = 0;
114 unsigned int page = 0;
115 struct dpni_statistics dpni_stats;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530116
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530117 printf("DPNI counters ..\n");
118 for (page = 0; page < 3; page++) {
119 err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS,
120 dflt_dpni->dpni_handle, page,
121 &dpni_stats);
122 if (err < 0) {
123 printf("dpni_get_statistics: failed:");
124 printf("%d for page[%d]\n", err, page);
125 return;
126 }
127 print_dpni_stats(dpni_statistics[page], dpni_stats);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530128 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530129}
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530130
131static void ldpaa_eth_get_dpmac_counter(struct eth_device *net_dev)
132{
133 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
134 int err = 0;
135 u64 value;
136
137 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
138 priv->dpmac_handle,
139 DPMAC_CNT_ING_BYTE,
140 &value);
141 if (err < 0) {
142 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
143 return;
144 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530145 printf("\nDPMAC counters ..\n");
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530146 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
147
148 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
149 priv->dpmac_handle,
150 DPMAC_CNT_ING_FRAME_DISCARD,
151 &value);
152 if (err < 0) {
153 printf("dpmac_get_counter: DPMAC_CNT_ING_FRAME_DISCARD failed\n");
154 return;
155 }
156 printf("DPMAC_CNT_ING_FRAME_DISCARD=%lld\n", value);
157
158 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
159 priv->dpmac_handle,
160 DPMAC_CNT_ING_ALIGN_ERR,
161 &value);
162 if (err < 0) {
163 printf("dpmac_get_counter: DPMAC_CNT_ING_ALIGN_ERR failed\n");
164 return;
165 }
166 printf("DPMAC_CNT_ING_ALIGN_ERR =%lld\n", value);
167
168 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
169 priv->dpmac_handle,
170 DPMAC_CNT_ING_BYTE,
171 &value);
172 if (err < 0) {
173 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
174 return;
175 }
176 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
177
178 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
179 priv->dpmac_handle,
180 DPMAC_CNT_ING_ERR_FRAME,
181 &value);
182 if (err < 0) {
183 printf("dpmac_get_counter: DPMAC_CNT_ING_ERR_FRAME failed\n");
184 return;
185 }
186 printf("DPMAC_CNT_ING_ERR_FRAME=%lld\n", value);
187
188 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
189 priv->dpmac_handle,
190 DPMAC_CNT_EGR_BYTE ,
191 &value);
192 if (err < 0) {
193 printf("dpmac_get_counter: DPMAC_CNT_EGR_BYTE failed\n");
194 return;
195 }
196 printf("DPMAC_CNT_EGR_BYTE =%lld\n", value);
197
198 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
199 priv->dpmac_handle,
200 DPMAC_CNT_EGR_ERR_FRAME ,
201 &value);
202 if (err < 0) {
203 printf("dpmac_get_counter: DPMAC_CNT_EGR_ERR_FRAME failed\n");
204 return;
205 }
206 printf("DPMAC_CNT_EGR_ERR_FRAME =%lld\n", value);
207}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530208#endif
209
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700210static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
211 const struct dpaa_fd *fd)
212{
213 u64 fd_addr;
214 uint16_t fd_offset;
215 uint32_t fd_length;
216 struct ldpaa_fas *fas;
217 uint32_t status, err;
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530218 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
219 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700220 struct qbman_release_desc releasedesc;
221 struct qbman_swp *swp = dflt_dpio->sw_portal;
222
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700223 fd_addr = ldpaa_fd_get_addr(fd);
224 fd_offset = ldpaa_fd_get_offset(fd);
225 fd_length = ldpaa_fd_get_len(fd);
226
227 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
228
229 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
230 /* Read the frame annotation status word and check for errors */
231 fas = (struct ldpaa_fas *)
232 ((uint8_t *)(fd_addr) +
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530233 dflt_dpni->buf_layout.private_data_size);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700234 status = le32_to_cpu(fas->status);
235 if (status & LDPAA_ETH_RX_ERR_MASK) {
236 printf("Rx frame error(s): 0x%08x\n",
237 status & LDPAA_ETH_RX_ERR_MASK);
238 goto error;
239 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
240 printf("Unsupported feature in bitmask: 0x%08x\n",
241 status & LDPAA_ETH_RX_UNSUPP_MASK);
242 goto error;
243 }
244 }
245
246 debug("Rx frame: To Upper layer\n");
247 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
248 fd_length);
249
250error:
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700251 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700252 qbman_release_desc_clear(&releasedesc);
253 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530254 time_start = get_timer(0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700255 do {
256 /* Release buffer into the QBMAN */
257 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530258 } while (get_timer(time_start) < timeo && err == -EBUSY);
259
260 if (err == -EBUSY)
261 printf("Rx frame: QBMAN buffer release fails\n");
262
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700263 return;
264}
265
266static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
267{
268 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
269 const struct ldpaa_dq *dq;
270 const struct dpaa_fd *fd;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530271 int i = 5, err = 0, status;
272 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
273 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700274 static struct qbman_pull_desc pulldesc;
275 struct qbman_swp *swp = dflt_dpio->sw_portal;
276
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700277 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700278 qbman_pull_desc_clear(&pulldesc);
279 qbman_pull_desc_set_numframes(&pulldesc, 1);
280 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
281
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700282 err = qbman_swp_pull(swp, &pulldesc);
283 if (err < 0) {
284 printf("Dequeue frames error:0x%08x\n", err);
285 continue;
286 }
287
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530288 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700289
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530290 do {
291 dq = qbman_swp_dqrr_next(swp);
292 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700293
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700294 if (dq) {
295 /* Check for valid frame. If not sent a consume
296 * confirmation to QBMAN otherwise give it to NADK
297 * application and then send consume confirmation to
298 * QBMAN.
299 */
300 status = (uint8_t)ldpaa_dq_flags(dq);
301 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
302 debug("Dequeue RX frames:");
303 debug("No frame delivered\n");
304
305 qbman_swp_dqrr_consume(swp, dq);
Prabhakar Kushwaha37ed1a62015-07-02 11:29:07 +0530306 continue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700307 }
308
309 fd = ldpaa_dq_fd(dq);
310
311 /* Obtain FD and process it */
312 ldpaa_eth_rx(priv, fd);
313 qbman_swp_dqrr_consume(swp, dq);
314 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530315 } else {
316 err = -ENODATA;
317 debug("No DQRR entries\n");
318 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700319 }
320 }
321
322 return err;
323}
324
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700325static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
326{
327 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
328 struct dpaa_fd fd;
329 u64 buffer_start;
330 int data_offset, err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530331 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
332 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700333 struct qbman_swp *swp = dflt_dpio->sw_portal;
334 struct qbman_eq_desc ed;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530335 struct qbman_release_desc releasedesc;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700336
337 /* Setup the FD fields */
338 memset(&fd, 0, sizeof(fd));
339
340 data_offset = priv->tx_data_offset;
341
342 do {
343 err = qbman_swp_acquire(dflt_dpio->sw_portal,
344 dflt_dpbp->dpbp_attr.bpid,
345 &buffer_start, 1);
346 } while (err == -EBUSY);
347
Ashish Kumar34f080c2017-10-26 16:03:22 +0530348 if (err <= 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700349 printf("qbman_swp_acquire() failed\n");
350 return -ENOMEM;
351 }
352
353 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
354
355 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
356
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700357 flush_dcache_range(buffer_start, buffer_start +
358 LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700359
360 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
361 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
362 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
363 ldpaa_fd_set_len(&fd, len);
364
365 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
366 LDPAA_FD_CTRL_PTV1;
367
368 qbman_eq_desc_clear(&ed);
369 qbman_eq_desc_set_no_orp(&ed, 0);
370 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530371
372 time_start = get_timer(0);
373
374 while (get_timer(time_start) < timeo) {
375 err = qbman_swp_enqueue(swp, &ed,
376 (const struct qbman_fd *)(&fd));
377 if (err != -EBUSY)
378 break;
379 }
380
381 if (err < 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700382 printf("error enqueueing Tx frame\n");
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530383 goto error;
384 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700385
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700386 return err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530387
388error:
389 qbman_release_desc_clear(&releasedesc);
390 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
391 time_start = get_timer(0);
392 do {
393 /* Release buffer into the QBMAN */
394 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
395 } while (get_timer(time_start) < timeo && err == -EBUSY);
396
397 if (err == -EBUSY)
398 printf("TX data: QBMAN buffer release fails\n");
399
400 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700401}
402
Pankaj Bansale031d262018-10-10 14:08:32 +0530403static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
404 struct dpmac_link_state *state)
405{
Pankaj Bansale031d262018-10-10 14:08:32 +0530406 phy_interface_t enet_if;
Tom Rini13da6252018-10-11 20:07:48 -0400407 int phys_detected;
408#ifdef CONFIG_PHYLIB
409 struct phy_device *phydev = NULL;
410 int err, phy_num;
411#endif
Pankaj Bansale031d262018-10-10 14:08:32 +0530412
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530413 /* let's start off with maximum capabilities */
Pankaj Bansale031d262018-10-10 14:08:32 +0530414 enet_if = wriop_get_enet_if(priv->dpmac_id);
415 switch (enet_if) {
416 case PHY_INTERFACE_MODE_XGMII:
417 state->rate = SPEED_10000;
418 break;
419 default:
420 state->rate = SPEED_1000;
421 break;
422 }
423 state->up = 1;
424
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530425 phys_detected = 0;
Pankaj Bansale031d262018-10-10 14:08:32 +0530426#ifdef CONFIG_PHYLIB
427 state->options |= DPMAC_LINK_OPT_AUTONEG;
428
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530429 /* start the phy devices one by one and update the dpmac state */
430 for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
431 phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
432 if (!phydev)
433 continue;
434
435 phys_detected++;
Pankaj Bansale031d262018-10-10 14:08:32 +0530436 err = phy_startup(phydev);
437 if (err) {
438 printf("%s: Could not initialize\n", phydev->dev->name);
439 state->up = 0;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530440 break;
Pankaj Bansale031d262018-10-10 14:08:32 +0530441 }
442 if (phydev->link) {
443 state->rate = min(state->rate, (uint32_t)phydev->speed);
444 if (!phydev->duplex)
445 state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
446 if (!phydev->autoneg)
447 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
448 } else {
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530449 /* break out of loop even if one phy is down */
Pankaj Bansale031d262018-10-10 14:08:32 +0530450 state->up = 0;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530451 break;
Pankaj Bansale031d262018-10-10 14:08:32 +0530452 }
453 }
454#endif
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530455 if (!phys_detected)
Pankaj Bansale031d262018-10-10 14:08:32 +0530456 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
457
458 if (!state->up) {
459 state->rate = 0;
460 state->options = 0;
461 return -ENOLINK;
462 }
463
464 return 0;
465}
466
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700467static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
468{
469 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530470 struct dpmac_link_state dpmac_link_state = { 0 };
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530471#ifdef DEBUG
472 struct dpni_link_state link_state;
473#endif
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530474 int err = 0;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530475 struct dpni_queue d_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700476
477 if (net_dev->state == ETH_STATE_ACTIVE)
478 return 0;
479
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530480 if (get_mc_boot_status() != 0) {
481 printf("ERROR (MC is not booted)\n");
482 return -ENODEV;
483 }
484
485 if (get_dpl_apply_status() == 0) {
486 printf("ERROR (DPL is deployed. No device available)\n");
487 return -ENODEV;
488 }
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530489
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530490 /* DPMAC initialization */
491 err = ldpaa_dpmac_setup(priv);
492 if (err < 0)
493 goto err_dpmac_setup;
494
Pankaj Bansale031d262018-10-10 14:08:32 +0530495 err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
496 if (err < 0)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530497 goto err_dpmac_bind;
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530498
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530499 /* DPMAC binding DPNI */
500 err = ldpaa_dpmac_bind(priv);
501 if (err)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530502 goto err_dpmac_bind;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530503
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700504 /* DPNI initialization */
505 err = ldpaa_dpni_setup(priv);
506 if (err < 0)
507 goto err_dpni_setup;
508
509 err = ldpaa_dpbp_setup();
510 if (err < 0)
511 goto err_dpbp_setup;
512
513 /* DPNI binding DPBP */
514 err = ldpaa_dpni_bind(priv);
515 if (err)
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530516 goto err_dpni_bind;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700517
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530518 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530519 dflt_dpni->dpni_handle, net_dev->enetaddr);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700520 if (err) {
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530521 printf("dpni_add_mac_addr() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700522 return err;
523 }
524
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530525 err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700526 if (err < 0) {
527 printf("dpni_enable() failed\n");
528 return err;
529 }
530
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530531 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
532 priv->dpmac_handle, &dpmac_link_state);
533 if (err < 0) {
534 printf("dpmac_set_link_state() failed\n");
535 return err;
536 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530537
538#ifdef DEBUG
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530539 printf("DPMAC link status: %d - ", dpmac_link_state.up);
540 dpmac_link_state.up == 0 ? printf("down\n") :
541 dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n");
542
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530543 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
544 dflt_dpni->dpni_handle, &link_state);
545 if (err < 0) {
546 printf("dpni_get_link_state() failed\n");
547 return err;
548 }
549
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530550 printf("DPNI link status: %d - ", link_state.up);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530551 link_state.up == 0 ? printf("down\n") :
552 link_state.up == 1 ? printf("up\n") : printf("error state\n");
553#endif
554
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530555 memset(&d_queue, 0, sizeof(struct dpni_queue));
556 err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
557 dflt_dpni->dpni_handle, DPNI_QUEUE_RX,
558 0, 0, &d_queue);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700559 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530560 printf("dpni_get_queue failed\n");
561 goto err_get_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700562 }
563
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530564 priv->rx_dflt_fqid = d_queue.fqid;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700565
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530566 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530567 &priv->tx_qdid);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700568 if (err) {
569 printf("dpni_get_qdid() failed\n");
570 goto err_qdid;
571 }
572
Pankaj Bansale031d262018-10-10 14:08:32 +0530573 return dpmac_link_state.up;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700574
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700575err_qdid:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530576err_get_queue:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530577 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
578err_dpni_bind:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700579 ldpaa_dpbp_free();
580err_dpbp_setup:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530581 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700582err_dpni_setup:
Pankaj Bansald24b1282018-10-10 14:08:29 +0530583err_dpmac_bind:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530584 dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
585 dpmac_destroy(dflt_mc_io,
586 dflt_dprc_handle,
587 MC_CMD_NO_FLAGS, priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530588err_dpmac_setup:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700589 return err;
590}
591
592static void ldpaa_eth_stop(struct eth_device *net_dev)
593{
594 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
595 int err = 0;
Tom Rini13da6252018-10-11 20:07:48 -0400596#ifdef CONFIG_PHYLIB
Pankaj Bansal1c2289d2018-10-10 14:08:30 +0530597 struct phy_device *phydev = NULL;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530598 int phy_num;
Tom Rini13da6252018-10-11 20:07:48 -0400599#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700600
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700601 if ((net_dev->state == ETH_STATE_PASSIVE) ||
602 (net_dev->state == ETH_STATE_INIT))
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700603 return;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530604
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530605#ifdef DEBUG
606 ldpaa_eth_get_dpni_counter();
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530607 ldpaa_eth_get_dpmac_counter(net_dev);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530608#endif
609
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530610 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
611 dflt_dprc_handle, &dpmac_endpoint);
612 if (err < 0)
613 printf("dprc_disconnect() failed dpmac_endpoint\n");
614
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530615 err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
616 if (err < 0)
617 printf("dpmac_close() failed\n");
618
619 err = dpmac_destroy(dflt_mc_io,
620 dflt_dprc_handle,
621 MC_CMD_NO_FLAGS,
622 priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530623 if (err < 0)
624 printf("dpmac_destroy() failed\n");
625
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700626 /* Stop Tx and Rx traffic */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530627 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700628 if (err < 0)
629 printf("dpni_disable() failed\n");
630
631#ifdef CONFIG_PHYLIB
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530632 for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
633 phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
634 if (phydev)
635 phy_shutdown(phydev);
636 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700637#endif
638
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530639 /* Free DPBP handle and reset. */
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700640 ldpaa_dpbp_free();
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530641
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530642 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530643 if (err < 0)
644 printf("dpni_reset() failed\n");
645
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530646 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530647 if (err < 0)
648 printf("dpni_close() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700649}
650
651static void ldpaa_dpbp_drain_cnt(int count)
652{
653 uint64_t buf_array[7];
654 void *addr;
655 int ret, i;
656
657 BUG_ON(count > 7);
658
659 do {
660 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
661 dflt_dpbp->dpbp_attr.bpid,
662 buf_array, count);
663 if (ret < 0) {
664 printf("qbman_swp_acquire() failed\n");
665 return;
666 }
667 for (i = 0; i < ret; i++) {
668 addr = (void *)buf_array[i];
669 debug("Free: buffer addr =0x%p\n", addr);
670 free(addr);
671 }
672 } while (ret);
673}
674
675static void ldpaa_dpbp_drain(void)
676{
677 int i;
678 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
679 ldpaa_dpbp_drain_cnt(7);
680}
681
682static int ldpaa_bp_add_7(uint16_t bpid)
683{
684 uint64_t buf_array[7];
685 u8 *addr;
686 int i;
687 struct qbman_release_desc rd;
688
689 for (i = 0; i < 7; i++) {
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530690 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700691 if (!addr) {
692 printf("addr allocation failed\n");
693 goto err_alloc;
694 }
695 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700696 flush_dcache_range((u64)addr,
697 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700698
699 buf_array[i] = (uint64_t)addr;
700 debug("Release: buffer addr =0x%p\n", addr);
701 }
702
703release_bufs:
704 /* In case the portal is busy, retry until successful.
705 * This function is guaranteed to succeed in a reasonable amount
706 * of time.
707 */
708
709 do {
710 mdelay(1);
711 qbman_release_desc_clear(&rd);
712 qbman_release_desc_set_bpid(&rd, bpid);
713 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
714
715 return i;
716
717err_alloc:
718 if (i)
719 goto release_bufs;
720
721 return 0;
722}
723
724static int ldpaa_dpbp_seed(uint16_t bpid)
725{
726 int i;
727 int count;
728
729 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
730 count = ldpaa_bp_add_7(bpid);
731 if (count < 7)
732 printf("Buffer Seed= %d\n", count);
733 }
734
735 return 0;
736}
737
738static int ldpaa_dpbp_setup(void)
739{
740 int err;
741
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530742 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700743 &dflt_dpbp->dpbp_handle);
744 if (err) {
745 printf("dpbp_open() failed\n");
746 goto err_open;
747 }
748
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530749 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700750 if (err) {
751 printf("dpbp_enable() failed\n");
752 goto err_enable;
753 }
754
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530755 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
756 dflt_dpbp->dpbp_handle,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700757 &dflt_dpbp->dpbp_attr);
758 if (err) {
759 printf("dpbp_get_attributes() failed\n");
760 goto err_get_attr;
761 }
762
763 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530764
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700765 if (err) {
766 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
767 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
768 goto err_seed;
769 }
770
771 return 0;
772
773err_seed:
774err_get_attr:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530775 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700776err_enable:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530777 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700778err_open:
779 return err;
780}
781
782static void ldpaa_dpbp_free(void)
783{
784 ldpaa_dpbp_drain();
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530785 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
786 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
787 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700788}
789
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530790static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
791 struct ldpaa_eth_priv *priv)
792{
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530793 int error;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530794 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530795
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530796 error = dpmac_get_api_version(dflt_mc_io, 0,
797 &major_ver,
798 &minor_ver);
799 if ((major_ver < DPMAC_VER_MAJOR) ||
800 (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) {
801 printf("DPMAC version mismatch found %u.%u,",
802 major_ver, minor_ver);
803 printf("supported version is %u.%u\n",
804 DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
805 return error;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530806 }
807
808 return error;
809}
810
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530811static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
812{
813 int err = 0;
814 struct dpmac_cfg dpmac_cfg;
815
816 dpmac_cfg.mac_id = priv->dpmac_id;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530817
818 err = dpmac_create(dflt_mc_io,
819 dflt_dprc_handle,
820 MC_CMD_NO_FLAGS, &dpmac_cfg,
821 &priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530822 if (err)
823 printf("dpmac_create() failed\n");
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530824
825 err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530826 if (err < 0) {
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530827 printf("ldpaa_dpmac_version_check() failed: %d\n", err);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530828 goto err_version_check;
829 }
830
831 err = dpmac_open(dflt_mc_io,
832 MC_CMD_NO_FLAGS,
833 priv->dpmac_id,
834 &priv->dpmac_handle);
835 if (err < 0) {
836 printf("dpmac_open() failed: %d\n", err);
837 goto err_open;
838 }
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530839
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530840 return err;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530841
842err_open:
843err_version_check:
844 dpmac_destroy(dflt_mc_io,
845 dflt_dprc_handle,
846 MC_CMD_NO_FLAGS, priv->dpmac_id);
847
848 return err;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530849}
850
851static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
852{
853 int err = 0;
854 struct dprc_connection_cfg dprc_connection_cfg = {
855 /* If both rates are zero the connection */
856 /* will be configured in "best effort" mode. */
857 .committed_rate = 0,
858 .max_rate = 0
859 };
860
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530861#ifdef DEBUG
862 struct dprc_endpoint dbg_endpoint;
863 int state = 0;
864#endif
865
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530866 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000867 strcpy(dpmac_endpoint.type, "dpmac");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530868 dpmac_endpoint.id = priv->dpmac_id;
869
870 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000871 strcpy(dpni_endpoint.type, "dpni");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530872 dpni_endpoint.id = dflt_dpni->dpni_id;
873
874 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
875 dflt_dprc_handle,
876 &dpmac_endpoint,
877 &dpni_endpoint,
878 &dprc_connection_cfg);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530879 if (err)
880 printf("dprc_connect() failed\n");
881
882#ifdef DEBUG
883 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
884 dflt_dprc_handle, &dpni_endpoint,
885 &dbg_endpoint, &state);
886 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
887 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
888 printf("%s, DPMAC State= %d\n", __func__, state);
889
890 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
891 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
892 dflt_dprc_handle, &dpmac_endpoint,
893 &dbg_endpoint, &state);
894 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
895 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
896 printf("%s, DPNI State= %d\n", __func__, state);
897#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530898 return err;
899}
900
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700901static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
902{
903 int err;
904
905 /* and get a handle for the DPNI this interface is associate with */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530906 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
907 &dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700908 if (err) {
909 printf("dpni_open() failed\n");
910 goto err_open;
911 }
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530912 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530913 dflt_dpni->dpni_handle,
914 &dflt_dpni->dpni_attrs);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700915 if (err) {
916 printf("dpni_get_attributes() failed (err=%d)\n", err);
917 goto err_get_attr;
918 }
919
920 /* Configure our buffers' layout */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530921 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700922 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530923 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
924 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530925 dflt_dpni->buf_layout.pass_parser_result = true;
926 dflt_dpni->buf_layout.pass_frame_status = true;
927 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530928 /* HW erratum mandates data alignment in multiples of 256 */
929 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530930
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700931 /* ...rx, ... */
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530932 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
933 dflt_dpni->dpni_handle,
934 &dflt_dpni->buf_layout, DPNI_QUEUE_RX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700935 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530936 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700937 goto err_buf_layout;
938 }
939
940 /* ... tx, ... */
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530941 /* remove Rx-only options */
942 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
943 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530944 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
945 dflt_dpni->dpni_handle,
946 &dflt_dpni->buf_layout, DPNI_QUEUE_TX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700947 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530948 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700949 goto err_buf_layout;
950 }
951
952 /* ... tx-confirm. */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530953 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530954 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
955 dflt_dpni->dpni_handle,
956 &dflt_dpni->buf_layout,
957 DPNI_QUEUE_TX_CONFIRM);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700958 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530959 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700960 goto err_buf_layout;
961 }
962
963 /* Now that we've set our tx buffer layout, retrieve the minimum
964 * required tx data offset.
965 */
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530966 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530967 dflt_dpni->dpni_handle,
968 &priv->tx_data_offset);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700969 if (err) {
970 printf("dpni_get_tx_data_offset() failed\n");
971 goto err_data_offset;
972 }
973
974 /* Warn in case TX data offset is not multiple of 64 bytes. */
975 WARN_ON(priv->tx_data_offset % 64);
976
977 /* Accomodate SWA space. */
978 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
979 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
980
981 return 0;
982
983err_data_offset:
984err_buf_layout:
985err_get_attr:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530986 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700987err_open:
988 return err;
989}
990
991static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
992{
993 struct dpni_pools_cfg pools_params;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530994 struct dpni_queue tx_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700995 int err = 0;
996
Prabhakar Kushwahaa7992322016-03-28 14:11:05 +0530997 memset(&pools_params, 0, sizeof(pools_params));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700998 pools_params.num_dpbp = 1;
999 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
1000 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301001 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
1002 dflt_dpni->dpni_handle, &pools_params);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001003 if (err) {
1004 printf("dpni_set_pools() failed\n");
1005 return err;
1006 }
1007
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301008 memset(&tx_queue, 0, sizeof(struct dpni_queue));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001009
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301010 err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
1011 dflt_dpni->dpni_handle,
1012 DPNI_QUEUE_TX, 0, 0, &tx_queue);
1013
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001014 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301015 printf("dpni_set_queue() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001016 return err;
1017 }
1018
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301019 err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS,
1020 dflt_dpni->dpni_handle,
1021 DPNI_CONF_DISABLE);
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +05301022 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301023 printf("dpni_set_tx_confirmation_mode() failed\n");
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +05301024 return err;
1025 }
1026
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001027 return 0;
1028}
1029
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301030static int ldpaa_eth_netdev_init(struct eth_device *net_dev,
1031 phy_interface_t enet_if)
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001032{
1033 int err;
1034 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
1035
Pankaj Bansal8a921702018-08-02 16:31:28 +05301036 snprintf(net_dev->name, ETH_NAME_LEN, "DPMAC%d@%s", priv->dpmac_id,
1037 phy_interface_strings[enet_if]);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001038
1039 net_dev->iobase = 0;
1040 net_dev->init = ldpaa_eth_open;
1041 net_dev->halt = ldpaa_eth_stop;
1042 net_dev->send = ldpaa_eth_tx;
1043 net_dev->recv = ldpaa_eth_pull_dequeue_rx;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001044
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +05301045#ifdef CONFIG_PHYLIB
1046 err = init_phy(net_dev);
1047 if (err < 0)
1048 return err;
1049#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001050
1051 err = eth_register(net_dev);
1052 if (err < 0) {
1053 printf("eth_register() = %d\n", err);
1054 return err;
1055 }
1056
1057 return 0;
1058}
1059
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301060int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001061{
1062 struct eth_device *net_dev = NULL;
1063 struct ldpaa_eth_priv *priv = NULL;
1064 int err = 0;
1065
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001066 /* Net device */
1067 net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
1068 if (!net_dev) {
1069 printf("eth_device malloc() failed\n");
1070 return -ENOMEM;
1071 }
1072 memset(net_dev, 0, sizeof(struct eth_device));
1073
1074 /* alloc the ldpaa ethernet private struct */
1075 priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
1076 if (!priv) {
1077 printf("ldpaa_eth_priv malloc() failed\n");
Pankaj Bansala78f0452019-02-08 08:46:11 +00001078 free(net_dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001079 return -ENOMEM;
1080 }
1081 memset(priv, 0, sizeof(struct ldpaa_eth_priv));
1082
1083 net_dev->priv = (void *)priv;
1084 priv->net_dev = (struct eth_device *)net_dev;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301085 priv->dpmac_id = dpmac_id;
1086 debug("%s dpmac_id=%d\n", __func__, dpmac_id);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001087
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301088 err = ldpaa_eth_netdev_init(net_dev, enet_if);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001089 if (err)
1090 goto err_netdev_init;
1091
1092 debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
1093 return 0;
1094
1095err_netdev_init:
1096 free(priv);
1097 net_dev->priv = NULL;
1098 free(net_dev);
1099
1100 return err;
1101}