blob: 24850777949a8435384de97ec6b57538e40482ee [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>
Sean Andersoneba99512020-10-04 21:39:46 -04009#include <dm/device_compat.h>
10#include <fsl-mc/fsl_dpmac.h>
11#include <fsl-mc/ldpaa_wriop.h>
12#include <hwconfig.h>
Simon Glass0f2af882020-05-10 11:40:05 -060013#include <log.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070014#include <malloc.h>
Sean Andersoneba99512020-10-04 21:39:46 -040015#include <miiphy.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070016#include <net.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070017#include <phy.h>
Sean Andersoneba99512020-10-04 21:39:46 -040018#include <asm/io.h>
19#include <asm/types.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060020#include <linux/bug.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070021#include <linux/compat.h>
Simon Glassdbd79542020-05-10 11:40:11 -060022#include <linux/delay.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060023#include <asm/global_data.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070024#include "ldpaa_eth.h"
25
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053026#ifdef CONFIG_PHYLIB
Ioana Ciornei872004f2020-03-18 16:47:37 +020027static void init_phy(struct udevice *dev)
28{
29 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
30
31 priv->phy = dm_eth_phy_connect(dev);
32
33 if (!priv->phy)
34 return;
35
36 phy_config(priv->phy);
37}
Ioana Ciornei872004f2020-03-18 16:47:37 +020038#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070039
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053040#ifdef DEBUG
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053041
Yogesh Gaur318c32f2017-11-15 11:59:31 +053042#define DPNI_STATS_PER_PAGE 6
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053043
Yogesh Gaur318c32f2017-11-15 11:59:31 +053044static const char *dpni_statistics[][DPNI_STATS_PER_PAGE] = {
45 {
46 "DPNI_CNT_ING_ALL_FRAMES",
47 "DPNI_CNT_ING_ALL_BYTES",
48 "DPNI_CNT_ING_MCAST_FRAMES",
49 "DPNI_CNT_ING_MCAST_BYTES",
50 "DPNI_CNT_ING_BCAST_FRAMES",
51 "DPNI_CNT_ING_BCAST_BYTES",
52 }, {
53 "DPNI_CNT_EGR_ALL_FRAMES",
54 "DPNI_CNT_EGR_ALL_BYTES",
55 "DPNI_CNT_EGR_MCAST_FRAMES",
56 "DPNI_CNT_EGR_MCAST_BYTES",
57 "DPNI_CNT_EGR_BCAST_FRAMES",
58 "DPNI_CNT_EGR_BCAST_BYTES",
59 }, {
60 "DPNI_CNT_ING_FILTERED_FRAMES",
61 "DPNI_CNT_ING_DISCARDED_FRAMES",
62 "DPNI_CNT_ING_NOBUFFER_DISCARDS",
63 "DPNI_CNT_EGR_DISCARDED_FRAMES",
64 "DPNI_CNT_EGR_CNF_FRAMES",
65 ""
66 },
67};
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053068
Yogesh Gaur318c32f2017-11-15 11:59:31 +053069static void print_dpni_stats(const char *strings[],
70 struct dpni_statistics dpni_stats)
71{
72 uint64_t *stat;
73 int i;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053074
Yogesh Gaur318c32f2017-11-15 11:59:31 +053075 stat = (uint64_t *)&dpni_stats;
76 for (i = 0; i < DPNI_STATS_PER_PAGE; i++) {
77 if (strcmp(strings[i], "\0") == 0)
78 break;
79 printf("%s= %llu\n", strings[i], *stat);
80 stat++;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053081 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +053082}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053083
Yogesh Gaur318c32f2017-11-15 11:59:31 +053084static void ldpaa_eth_get_dpni_counter(void)
85{
86 int err = 0;
87 unsigned int page = 0;
88 struct dpni_statistics dpni_stats;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053089
Yogesh Gaur318c32f2017-11-15 11:59:31 +053090 printf("DPNI counters ..\n");
91 for (page = 0; page < 3; page++) {
92 err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS,
93 dflt_dpni->dpni_handle, page,
94 &dpni_stats);
95 if (err < 0) {
96 printf("dpni_get_statistics: failed:");
97 printf("%d for page[%d]\n", err, page);
98 return;
99 }
100 print_dpni_stats(dpni_statistics[page], dpni_stats);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530101 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530102}
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530103
Ioana Ciornei872004f2020-03-18 16:47:37 +0200104static void ldpaa_eth_get_dpmac_counter(struct udevice *dev)
105{
106 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530107 int err = 0;
108 u64 value;
109
110 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
111 priv->dpmac_handle,
112 DPMAC_CNT_ING_BYTE,
113 &value);
114 if (err < 0) {
115 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
116 return;
117 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530118 printf("\nDPMAC counters ..\n");
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530119 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
120
121 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
122 priv->dpmac_handle,
123 DPMAC_CNT_ING_FRAME_DISCARD,
124 &value);
125 if (err < 0) {
126 printf("dpmac_get_counter: DPMAC_CNT_ING_FRAME_DISCARD failed\n");
127 return;
128 }
129 printf("DPMAC_CNT_ING_FRAME_DISCARD=%lld\n", value);
130
131 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
132 priv->dpmac_handle,
133 DPMAC_CNT_ING_ALIGN_ERR,
134 &value);
135 if (err < 0) {
136 printf("dpmac_get_counter: DPMAC_CNT_ING_ALIGN_ERR failed\n");
137 return;
138 }
139 printf("DPMAC_CNT_ING_ALIGN_ERR =%lld\n", value);
140
141 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
142 priv->dpmac_handle,
143 DPMAC_CNT_ING_BYTE,
144 &value);
145 if (err < 0) {
146 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
147 return;
148 }
149 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
150
151 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
152 priv->dpmac_handle,
153 DPMAC_CNT_ING_ERR_FRAME,
154 &value);
155 if (err < 0) {
156 printf("dpmac_get_counter: DPMAC_CNT_ING_ERR_FRAME failed\n");
157 return;
158 }
159 printf("DPMAC_CNT_ING_ERR_FRAME=%lld\n", value);
160
161 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
162 priv->dpmac_handle,
163 DPMAC_CNT_EGR_BYTE ,
164 &value);
165 if (err < 0) {
166 printf("dpmac_get_counter: DPMAC_CNT_EGR_BYTE failed\n");
167 return;
168 }
169 printf("DPMAC_CNT_EGR_BYTE =%lld\n", value);
170
171 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
172 priv->dpmac_handle,
173 DPMAC_CNT_EGR_ERR_FRAME ,
174 &value);
175 if (err < 0) {
176 printf("dpmac_get_counter: DPMAC_CNT_EGR_ERR_FRAME failed\n");
177 return;
178 }
179 printf("DPMAC_CNT_EGR_ERR_FRAME =%lld\n", value);
180}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530181#endif
182
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700183static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
184 const struct dpaa_fd *fd)
185{
186 u64 fd_addr;
187 uint16_t fd_offset;
188 uint32_t fd_length;
189 struct ldpaa_fas *fas;
190 uint32_t status, err;
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530191 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
192 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700193 struct qbman_release_desc releasedesc;
194 struct qbman_swp *swp = dflt_dpio->sw_portal;
195
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700196 fd_addr = ldpaa_fd_get_addr(fd);
197 fd_offset = ldpaa_fd_get_offset(fd);
198 fd_length = ldpaa_fd_get_len(fd);
199
200 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
201
202 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
203 /* Read the frame annotation status word and check for errors */
204 fas = (struct ldpaa_fas *)
205 ((uint8_t *)(fd_addr) +
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530206 dflt_dpni->buf_layout.private_data_size);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700207 status = le32_to_cpu(fas->status);
208 if (status & LDPAA_ETH_RX_ERR_MASK) {
209 printf("Rx frame error(s): 0x%08x\n",
210 status & LDPAA_ETH_RX_ERR_MASK);
211 goto error;
212 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
213 printf("Unsupported feature in bitmask: 0x%08x\n",
214 status & LDPAA_ETH_RX_UNSUPP_MASK);
215 goto error;
216 }
217 }
218
219 debug("Rx frame: To Upper layer\n");
220 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
221 fd_length);
222
223error:
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700224 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700225 qbman_release_desc_clear(&releasedesc);
226 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530227 time_start = get_timer(0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700228 do {
229 /* Release buffer into the QBMAN */
230 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530231 } while (get_timer(time_start) < timeo && err == -EBUSY);
232
233 if (err == -EBUSY)
234 printf("Rx frame: QBMAN buffer release fails\n");
235
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700236 return;
237}
238
Ioana Ciornei872004f2020-03-18 16:47:37 +0200239static int ldpaa_eth_pull_dequeue_rx(struct udevice *dev,
240 int flags, uchar **packetp)
241{
242 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700243 const struct ldpaa_dq *dq;
244 const struct dpaa_fd *fd;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530245 int i = 5, err = 0, status;
246 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
247 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700248 static struct qbman_pull_desc pulldesc;
249 struct qbman_swp *swp = dflt_dpio->sw_portal;
250
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700251 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700252 qbman_pull_desc_clear(&pulldesc);
253 qbman_pull_desc_set_numframes(&pulldesc, 1);
254 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
255
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700256 err = qbman_swp_pull(swp, &pulldesc);
257 if (err < 0) {
258 printf("Dequeue frames error:0x%08x\n", err);
259 continue;
260 }
261
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530262 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700263
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530264 do {
265 dq = qbman_swp_dqrr_next(swp);
266 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700267
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700268 if (dq) {
269 /* Check for valid frame. If not sent a consume
270 * confirmation to QBMAN otherwise give it to NADK
271 * application and then send consume confirmation to
272 * QBMAN.
273 */
274 status = (uint8_t)ldpaa_dq_flags(dq);
275 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
276 debug("Dequeue RX frames:");
277 debug("No frame delivered\n");
278
279 qbman_swp_dqrr_consume(swp, dq);
Prabhakar Kushwaha37ed1a62015-07-02 11:29:07 +0530280 continue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700281 }
282
283 fd = ldpaa_dq_fd(dq);
284
285 /* Obtain FD and process it */
286 ldpaa_eth_rx(priv, fd);
287 qbman_swp_dqrr_consume(swp, dq);
288 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530289 } else {
290 err = -ENODATA;
291 debug("No DQRR entries\n");
292 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700293 }
294 }
295
296 return err;
297}
298
Ioana Ciornei872004f2020-03-18 16:47:37 +0200299static int ldpaa_eth_tx(struct udevice *dev, void *buf, int len)
300{
301 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700302 struct dpaa_fd fd;
303 u64 buffer_start;
304 int data_offset, err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530305 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
306 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700307 struct qbman_swp *swp = dflt_dpio->sw_portal;
308 struct qbman_eq_desc ed;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530309 struct qbman_release_desc releasedesc;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700310
311 /* Setup the FD fields */
312 memset(&fd, 0, sizeof(fd));
313
314 data_offset = priv->tx_data_offset;
315
316 do {
317 err = qbman_swp_acquire(dflt_dpio->sw_portal,
318 dflt_dpbp->dpbp_attr.bpid,
319 &buffer_start, 1);
320 } while (err == -EBUSY);
321
Ashish Kumar34f080c2017-10-26 16:03:22 +0530322 if (err <= 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700323 printf("qbman_swp_acquire() failed\n");
324 return -ENOMEM;
325 }
326
327 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
328
329 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
330
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700331 flush_dcache_range(buffer_start, buffer_start +
332 LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700333
334 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
335 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
336 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
337 ldpaa_fd_set_len(&fd, len);
338
339 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
340 LDPAA_FD_CTRL_PTV1;
341
342 qbman_eq_desc_clear(&ed);
343 qbman_eq_desc_set_no_orp(&ed, 0);
344 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530345
346 time_start = get_timer(0);
347
348 while (get_timer(time_start) < timeo) {
349 err = qbman_swp_enqueue(swp, &ed,
350 (const struct qbman_fd *)(&fd));
351 if (err != -EBUSY)
352 break;
353 }
354
355 if (err < 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700356 printf("error enqueueing Tx frame\n");
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530357 goto error;
358 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700359
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700360 return err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530361
362error:
363 qbman_release_desc_clear(&releasedesc);
364 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
365 time_start = get_timer(0);
366 do {
367 /* Release buffer into the QBMAN */
368 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
369 } while (get_timer(time_start) < timeo && err == -EBUSY);
370
371 if (err == -EBUSY)
372 printf("TX data: QBMAN buffer release fails\n");
373
374 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700375}
376
Pankaj Bansale031d262018-10-10 14:08:32 +0530377static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
378 struct dpmac_link_state *state)
379{
Pankaj Bansale031d262018-10-10 14:08:32 +0530380 phy_interface_t enet_if;
Tom Rini13da6252018-10-11 20:07:48 -0400381 struct phy_device *phydev = NULL;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200382 int err;
Pankaj Bansale031d262018-10-10 14:08:32 +0530383
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530384 /* let's start off with maximum capabilities */
Pankaj Bansale031d262018-10-10 14:08:32 +0530385 enet_if = wriop_get_enet_if(priv->dpmac_id);
386 switch (enet_if) {
387 case PHY_INTERFACE_MODE_XGMII:
388 state->rate = SPEED_10000;
389 break;
390 default:
391 state->rate = SPEED_1000;
392 break;
393 }
Pankaj Bansale031d262018-10-10 14:08:32 +0530394
Ioana Ciornei872004f2020-03-18 16:47:37 +0200395 state->up = 1;
Pankaj Bansale031d262018-10-10 14:08:32 +0530396 state->options |= DPMAC_LINK_OPT_AUTONEG;
Tom Rinie83c2012022-11-27 10:25:14 -0500397 phydev = priv->phy;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530398
Ioana Ciornei872004f2020-03-18 16:47:37 +0200399 if (phydev) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530400 err = phy_startup(phydev);
401 if (err) {
402 printf("%s: Could not initialize\n", phydev->dev->name);
403 state->up = 0;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200404 } else if (phydev->link) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530405 state->rate = min(state->rate, (uint32_t)phydev->speed);
406 if (!phydev->duplex)
407 state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
408 if (!phydev->autoneg)
409 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
410 } else {
411 state->up = 0;
412 }
413 }
Ioana Ciornei872004f2020-03-18 16:47:37 +0200414
415 if (!phydev)
Pankaj Bansale031d262018-10-10 14:08:32 +0530416 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
417
418 if (!state->up) {
419 state->rate = 0;
420 state->options = 0;
421 return -ENOLINK;
422 }
423
424 return 0;
425}
426
Ioana Ciornei872004f2020-03-18 16:47:37 +0200427static int ldpaa_eth_open(struct udevice *dev)
428{
Simon Glassfa20e932020-12-03 16:55:20 -0700429 struct eth_pdata *plat = dev_get_plat(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200430 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530431 struct dpmac_link_state dpmac_link_state = { 0 };
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530432#ifdef DEBUG
433 struct dpni_link_state link_state;
434#endif
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530435 int err = 0;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530436 struct dpni_queue d_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700437
Ioana Ciornei872004f2020-03-18 16:47:37 +0200438 if (eth_is_active(dev))
439 return 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700440
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530441 if (get_mc_boot_status() != 0) {
442 printf("ERROR (MC is not booted)\n");
443 return -ENODEV;
444 }
445
446 if (get_dpl_apply_status() == 0) {
447 printf("ERROR (DPL is deployed. No device available)\n");
448 return -ENODEV;
449 }
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530450
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530451 /* DPMAC initialization */
452 err = ldpaa_dpmac_setup(priv);
453 if (err < 0)
454 goto err_dpmac_setup;
455
Pankaj Bansale031d262018-10-10 14:08:32 +0530456 err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
457 if (err < 0)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530458 goto err_dpmac_bind;
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530459
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530460 /* DPMAC binding DPNI */
461 err = ldpaa_dpmac_bind(priv);
462 if (err)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530463 goto err_dpmac_bind;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530464
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700465 /* DPNI initialization */
466 err = ldpaa_dpni_setup(priv);
467 if (err < 0)
468 goto err_dpni_setup;
469
470 err = ldpaa_dpbp_setup();
471 if (err < 0)
472 goto err_dpbp_setup;
473
474 /* DPNI binding DPBP */
475 err = ldpaa_dpni_bind(priv);
476 if (err)
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530477 goto err_dpni_bind;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700478
Ioana Ciornei872004f2020-03-18 16:47:37 +0200479 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
480 dflt_dpni->dpni_handle, plat->enetaddr);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700481 if (err) {
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530482 printf("dpni_add_mac_addr() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700483 return err;
484 }
485
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530486 err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700487 if (err < 0) {
488 printf("dpni_enable() failed\n");
489 return err;
490 }
491
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530492 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
493 priv->dpmac_handle, &dpmac_link_state);
494 if (err < 0) {
495 printf("dpmac_set_link_state() failed\n");
496 return err;
497 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530498
499#ifdef DEBUG
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530500 printf("DPMAC link status: %d - ", dpmac_link_state.up);
501 dpmac_link_state.up == 0 ? printf("down\n") :
502 dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n");
503
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530504 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
505 dflt_dpni->dpni_handle, &link_state);
506 if (err < 0) {
507 printf("dpni_get_link_state() failed\n");
508 return err;
509 }
510
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530511 printf("DPNI link status: %d - ", link_state.up);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530512 link_state.up == 0 ? printf("down\n") :
513 link_state.up == 1 ? printf("up\n") : printf("error state\n");
514#endif
515
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530516 memset(&d_queue, 0, sizeof(struct dpni_queue));
517 err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
518 dflt_dpni->dpni_handle, DPNI_QUEUE_RX,
519 0, 0, &d_queue);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700520 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530521 printf("dpni_get_queue failed\n");
522 goto err_get_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700523 }
524
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530525 priv->rx_dflt_fqid = d_queue.fqid;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700526
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530527 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530528 &priv->tx_qdid);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700529 if (err) {
530 printf("dpni_get_qdid() failed\n");
531 goto err_qdid;
532 }
533
Pankaj Bansale031d262018-10-10 14:08:32 +0530534 return dpmac_link_state.up;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700535
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700536err_qdid:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530537err_get_queue:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530538 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
539err_dpni_bind:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700540 ldpaa_dpbp_free();
541err_dpbp_setup:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530542 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700543err_dpni_setup:
Pankaj Bansald24b1282018-10-10 14:08:29 +0530544err_dpmac_bind:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530545 dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
546 dpmac_destroy(dflt_mc_io,
547 dflt_dprc_handle,
548 MC_CMD_NO_FLAGS, priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530549err_dpmac_setup:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700550 return err;
551}
552
Ioana Ciornei872004f2020-03-18 16:47:37 +0200553static void ldpaa_eth_stop(struct udevice *dev)
554{
555 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200556 struct phy_device *phydev = NULL;
557 int err = 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700558
Ioana Ciornei872004f2020-03-18 16:47:37 +0200559 if (!eth_is_active(dev))
560 return;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530561
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530562#ifdef DEBUG
563 ldpaa_eth_get_dpni_counter();
Ioana Ciornei872004f2020-03-18 16:47:37 +0200564 ldpaa_eth_get_dpmac_counter(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200565#endif
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530566
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530567 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
568 dflt_dprc_handle, &dpmac_endpoint);
569 if (err < 0)
570 printf("dprc_disconnect() failed dpmac_endpoint\n");
571
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530572 err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
573 if (err < 0)
574 printf("dpmac_close() failed\n");
575
576 err = dpmac_destroy(dflt_mc_io,
577 dflt_dprc_handle,
578 MC_CMD_NO_FLAGS,
579 priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530580 if (err < 0)
581 printf("dpmac_destroy() failed\n");
582
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700583 /* Stop Tx and Rx traffic */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530584 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700585 if (err < 0)
586 printf("dpni_disable() failed\n");
587
Tom Rinie83c2012022-11-27 10:25:14 -0500588 phydev = priv->phy;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200589 if (phydev)
590 phy_shutdown(phydev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700591
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530592 /* Free DPBP handle and reset. */
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700593 ldpaa_dpbp_free();
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530594
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530595 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530596 if (err < 0)
597 printf("dpni_reset() failed\n");
598
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530599 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530600 if (err < 0)
601 printf("dpni_close() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700602}
603
604static void ldpaa_dpbp_drain_cnt(int count)
605{
606 uint64_t buf_array[7];
607 void *addr;
608 int ret, i;
609
610 BUG_ON(count > 7);
611
612 do {
613 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
614 dflt_dpbp->dpbp_attr.bpid,
615 buf_array, count);
616 if (ret < 0) {
617 printf("qbman_swp_acquire() failed\n");
618 return;
619 }
620 for (i = 0; i < ret; i++) {
621 addr = (void *)buf_array[i];
622 debug("Free: buffer addr =0x%p\n", addr);
623 free(addr);
624 }
625 } while (ret);
626}
627
628static void ldpaa_dpbp_drain(void)
629{
630 int i;
631 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
632 ldpaa_dpbp_drain_cnt(7);
633}
634
635static int ldpaa_bp_add_7(uint16_t bpid)
636{
637 uint64_t buf_array[7];
638 u8 *addr;
639 int i;
640 struct qbman_release_desc rd;
641
642 for (i = 0; i < 7; i++) {
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530643 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700644 if (!addr) {
645 printf("addr allocation failed\n");
646 goto err_alloc;
647 }
648 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700649 flush_dcache_range((u64)addr,
650 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700651
652 buf_array[i] = (uint64_t)addr;
653 debug("Release: buffer addr =0x%p\n", addr);
654 }
655
656release_bufs:
657 /* In case the portal is busy, retry until successful.
658 * This function is guaranteed to succeed in a reasonable amount
659 * of time.
660 */
661
662 do {
663 mdelay(1);
664 qbman_release_desc_clear(&rd);
665 qbman_release_desc_set_bpid(&rd, bpid);
666 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
667
668 return i;
669
670err_alloc:
671 if (i)
672 goto release_bufs;
673
674 return 0;
675}
676
677static int ldpaa_dpbp_seed(uint16_t bpid)
678{
679 int i;
680 int count;
681
682 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
683 count = ldpaa_bp_add_7(bpid);
684 if (count < 7)
685 printf("Buffer Seed= %d\n", count);
686 }
687
688 return 0;
689}
690
691static int ldpaa_dpbp_setup(void)
692{
693 int err;
694
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530695 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700696 &dflt_dpbp->dpbp_handle);
697 if (err) {
698 printf("dpbp_open() failed\n");
699 goto err_open;
700 }
701
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530702 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700703 if (err) {
704 printf("dpbp_enable() failed\n");
705 goto err_enable;
706 }
707
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530708 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
709 dflt_dpbp->dpbp_handle,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700710 &dflt_dpbp->dpbp_attr);
711 if (err) {
712 printf("dpbp_get_attributes() failed\n");
713 goto err_get_attr;
714 }
715
716 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530717
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700718 if (err) {
719 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
720 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
721 goto err_seed;
722 }
723
724 return 0;
725
726err_seed:
727err_get_attr:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530728 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700729err_enable:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530730 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700731err_open:
732 return err;
733}
734
735static void ldpaa_dpbp_free(void)
736{
737 ldpaa_dpbp_drain();
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530738 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
739 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
740 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700741}
742
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530743static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
744 struct ldpaa_eth_priv *priv)
745{
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530746 int error;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530747 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530748
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530749 error = dpmac_get_api_version(dflt_mc_io, 0,
750 &major_ver,
751 &minor_ver);
752 if ((major_ver < DPMAC_VER_MAJOR) ||
753 (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) {
754 printf("DPMAC version mismatch found %u.%u,",
755 major_ver, minor_ver);
756 printf("supported version is %u.%u\n",
757 DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
758 return error;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530759 }
760
761 return error;
762}
763
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530764static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
765{
766 int err = 0;
767 struct dpmac_cfg dpmac_cfg;
768
769 dpmac_cfg.mac_id = priv->dpmac_id;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530770
771 err = dpmac_create(dflt_mc_io,
772 dflt_dprc_handle,
773 MC_CMD_NO_FLAGS, &dpmac_cfg,
774 &priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530775 if (err)
776 printf("dpmac_create() failed\n");
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530777
778 err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530779 if (err < 0) {
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530780 printf("ldpaa_dpmac_version_check() failed: %d\n", err);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530781 goto err_version_check;
782 }
783
784 err = dpmac_open(dflt_mc_io,
785 MC_CMD_NO_FLAGS,
786 priv->dpmac_id,
787 &priv->dpmac_handle);
788 if (err < 0) {
789 printf("dpmac_open() failed: %d\n", err);
790 goto err_open;
791 }
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530792
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530793 return err;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530794
795err_open:
796err_version_check:
797 dpmac_destroy(dflt_mc_io,
798 dflt_dprc_handle,
799 MC_CMD_NO_FLAGS, priv->dpmac_id);
800
801 return err;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530802}
803
804static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
805{
806 int err = 0;
807 struct dprc_connection_cfg dprc_connection_cfg = {
808 /* If both rates are zero the connection */
809 /* will be configured in "best effort" mode. */
810 .committed_rate = 0,
811 .max_rate = 0
812 };
813
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530814#ifdef DEBUG
815 struct dprc_endpoint dbg_endpoint;
816 int state = 0;
817#endif
818
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530819 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000820 strcpy(dpmac_endpoint.type, "dpmac");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530821 dpmac_endpoint.id = priv->dpmac_id;
822
823 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000824 strcpy(dpni_endpoint.type, "dpni");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530825 dpni_endpoint.id = dflt_dpni->dpni_id;
826
827 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
828 dflt_dprc_handle,
829 &dpmac_endpoint,
830 &dpni_endpoint,
831 &dprc_connection_cfg);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530832 if (err)
833 printf("dprc_connect() failed\n");
834
835#ifdef DEBUG
836 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
837 dflt_dprc_handle, &dpni_endpoint,
838 &dbg_endpoint, &state);
839 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
840 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
841 printf("%s, DPMAC State= %d\n", __func__, state);
842
843 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
844 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
845 dflt_dprc_handle, &dpmac_endpoint,
846 &dbg_endpoint, &state);
847 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
848 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
849 printf("%s, DPNI State= %d\n", __func__, state);
850#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530851 return err;
852}
853
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700854static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
855{
856 int err;
857
858 /* and get a handle for the DPNI this interface is associate with */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530859 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
860 &dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700861 if (err) {
862 printf("dpni_open() failed\n");
863 goto err_open;
864 }
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530865 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530866 dflt_dpni->dpni_handle,
867 &dflt_dpni->dpni_attrs);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700868 if (err) {
869 printf("dpni_get_attributes() failed (err=%d)\n", err);
870 goto err_get_attr;
871 }
872
873 /* Configure our buffers' layout */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530874 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700875 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530876 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
877 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530878 dflt_dpni->buf_layout.pass_parser_result = true;
879 dflt_dpni->buf_layout.pass_frame_status = true;
880 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530881 /* HW erratum mandates data alignment in multiples of 256 */
882 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530883
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700884 /* ...rx, ... */
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530885 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
886 dflt_dpni->dpni_handle,
887 &dflt_dpni->buf_layout, DPNI_QUEUE_RX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700888 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530889 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700890 goto err_buf_layout;
891 }
892
893 /* ... tx, ... */
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530894 /* remove Rx-only options */
895 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
896 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530897 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
898 dflt_dpni->dpni_handle,
899 &dflt_dpni->buf_layout, DPNI_QUEUE_TX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700900 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530901 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700902 goto err_buf_layout;
903 }
904
905 /* ... tx-confirm. */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530906 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530907 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
908 dflt_dpni->dpni_handle,
909 &dflt_dpni->buf_layout,
910 DPNI_QUEUE_TX_CONFIRM);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700911 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530912 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700913 goto err_buf_layout;
914 }
915
916 /* Now that we've set our tx buffer layout, retrieve the minimum
917 * required tx data offset.
918 */
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530919 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530920 dflt_dpni->dpni_handle,
921 &priv->tx_data_offset);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700922 if (err) {
923 printf("dpni_get_tx_data_offset() failed\n");
924 goto err_data_offset;
925 }
926
927 /* Warn in case TX data offset is not multiple of 64 bytes. */
928 WARN_ON(priv->tx_data_offset % 64);
929
930 /* Accomodate SWA space. */
931 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
932 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
933
934 return 0;
935
936err_data_offset:
937err_buf_layout:
938err_get_attr:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530939 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700940err_open:
941 return err;
942}
943
944static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
945{
946 struct dpni_pools_cfg pools_params;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530947 struct dpni_queue tx_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700948 int err = 0;
949
Prabhakar Kushwahaa7992322016-03-28 14:11:05 +0530950 memset(&pools_params, 0, sizeof(pools_params));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700951 pools_params.num_dpbp = 1;
952 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
953 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530954 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
955 dflt_dpni->dpni_handle, &pools_params);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700956 if (err) {
957 printf("dpni_set_pools() failed\n");
958 return err;
959 }
960
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530961 memset(&tx_queue, 0, sizeof(struct dpni_queue));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700962
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530963 err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
964 dflt_dpni->dpni_handle,
965 DPNI_QUEUE_TX, 0, 0, &tx_queue);
966
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700967 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530968 printf("dpni_set_queue() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700969 return err;
970 }
971
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530972 err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS,
973 dflt_dpni->dpni_handle,
974 DPNI_CONF_DISABLE);
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530975 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530976 printf("dpni_set_tx_confirmation_mode() failed\n");
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530977 return err;
978 }
979
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700980 return 0;
981}
982
Ioana Ciornei872004f2020-03-18 16:47:37 +0200983static int ldpaa_eth_probe(struct udevice *dev)
984{
985 struct ofnode_phandle_args phandle;
986
987 /* Nothing to do if there is no "phy-handle" in the DTS node */
988 if (dev_read_phandle_with_args(dev, "phy-handle", NULL,
989 0, 0, &phandle)) {
990 return 0;
991 }
992
993 init_phy(dev);
994
995 return 0;
996}
997
998static uint32_t ldpaa_eth_get_dpmac_id(struct udevice *dev)
999{
1000 int port_node = dev_of_offset(dev);
1001
1002 return fdtdec_get_uint(gd->fdt_blob, port_node, "reg", -1);
1003}
1004
Ioana Ciornei872004f2020-03-18 16:47:37 +02001005static int ldpaa_eth_bind(struct udevice *dev)
1006{
Ioana Ciornei872004f2020-03-18 16:47:37 +02001007 uint32_t dpmac_id;
1008 char eth_name[16];
1009 int phy_mode = -1;
1010
Marek Behúnbc194772022-04-07 00:33:01 +02001011 phy_mode = dev_read_phy_mode(dev);
Marek Behún48631e42022-04-07 00:33:03 +02001012 if (phy_mode == PHY_INTERFACE_MODE_NA) {
Ioana Ciornei872004f2020-03-18 16:47:37 +02001013 dev_err(dev, "incorrect phy mode\n");
1014 return -EINVAL;
1015 }
1016
1017 dpmac_id = ldpaa_eth_get_dpmac_id(dev);
1018 if (dpmac_id == -1) {
1019 dev_err(dev, "missing reg field from the dpmac node\n");
1020 return -EINVAL;
1021 }
1022
Marek Behúnbc194772022-04-07 00:33:01 +02001023 sprintf(eth_name, "DPMAC%d@%s", dpmac_id,
1024 phy_string_for_interface(phy_mode));
Ioana Ciornei872004f2020-03-18 16:47:37 +02001025 device_set_name(dev, eth_name);
1026
1027 return 0;
1028}
1029
Simon Glassaad29ae2020-12-03 16:55:21 -07001030static int ldpaa_eth_of_to_plat(struct udevice *dev)
Ioana Ciornei872004f2020-03-18 16:47:37 +02001031{
1032 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +02001033
1034 priv->dpmac_id = ldpaa_eth_get_dpmac_id(dev);
Marek Behúnbc194772022-04-07 00:33:01 +02001035 priv->phy_mode = dev_read_phy_mode(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +02001036
1037 return 0;
1038}
1039
1040static const struct eth_ops ldpaa_eth_ops = {
1041 .start = ldpaa_eth_open,
1042 .send = ldpaa_eth_tx,
1043 .recv = ldpaa_eth_pull_dequeue_rx,
1044 .stop = ldpaa_eth_stop,
1045};
1046
1047static const struct udevice_id ldpaa_eth_of_ids[] = {
1048 { .compatible = "fsl,qoriq-mc-dpmac" },
1049};
1050
1051U_BOOT_DRIVER(ldpaa_eth) = {
1052 .name = "ldpaa_eth",
1053 .id = UCLASS_ETH,
1054 .of_match = ldpaa_eth_of_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001055 .of_to_plat = ldpaa_eth_of_to_plat,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001056 .bind = ldpaa_eth_bind,
1057 .probe = ldpaa_eth_probe,
1058 .ops = &ldpaa_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001059 .priv_auto = sizeof(struct ldpaa_eth_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -07001060 .plat_auto = sizeof(struct eth_pdata),
Ioana Ciornei872004f2020-03-18 16:47:37 +02001061};