blob: 2cb6e9b7d7056db23ff57537e3fe3b63f8287ba1 [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.
Ioana Ciornei5d1e9222023-02-09 18:07:03 +02004 * Copyright 2017, 2023 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>
Ioana Ciornei5d1e9222023-02-09 18:07:03 +020024#include <net/ldpaa_eth.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070025#include "ldpaa_eth.h"
26
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053027#ifdef CONFIG_PHYLIB
Ioana Ciornei872004f2020-03-18 16:47:37 +020028static void init_phy(struct udevice *dev)
29{
30 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
31
32 priv->phy = dm_eth_phy_connect(dev);
33
34 if (!priv->phy)
35 return;
36
37 phy_config(priv->phy);
38}
Ioana Ciornei872004f2020-03-18 16:47:37 +020039#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070040
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053041#ifdef DEBUG
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053042
Yogesh Gaur318c32f2017-11-15 11:59:31 +053043#define DPNI_STATS_PER_PAGE 6
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053044
Yogesh Gaur318c32f2017-11-15 11:59:31 +053045static const char *dpni_statistics[][DPNI_STATS_PER_PAGE] = {
46 {
47 "DPNI_CNT_ING_ALL_FRAMES",
48 "DPNI_CNT_ING_ALL_BYTES",
49 "DPNI_CNT_ING_MCAST_FRAMES",
50 "DPNI_CNT_ING_MCAST_BYTES",
51 "DPNI_CNT_ING_BCAST_FRAMES",
52 "DPNI_CNT_ING_BCAST_BYTES",
53 }, {
54 "DPNI_CNT_EGR_ALL_FRAMES",
55 "DPNI_CNT_EGR_ALL_BYTES",
56 "DPNI_CNT_EGR_MCAST_FRAMES",
57 "DPNI_CNT_EGR_MCAST_BYTES",
58 "DPNI_CNT_EGR_BCAST_FRAMES",
59 "DPNI_CNT_EGR_BCAST_BYTES",
60 }, {
61 "DPNI_CNT_ING_FILTERED_FRAMES",
62 "DPNI_CNT_ING_DISCARDED_FRAMES",
63 "DPNI_CNT_ING_NOBUFFER_DISCARDS",
64 "DPNI_CNT_EGR_DISCARDED_FRAMES",
65 "DPNI_CNT_EGR_CNF_FRAMES",
66 ""
67 },
68};
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053069
Yogesh Gaur318c32f2017-11-15 11:59:31 +053070static void print_dpni_stats(const char *strings[],
71 struct dpni_statistics dpni_stats)
72{
73 uint64_t *stat;
74 int i;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053075
Yogesh Gaur318c32f2017-11-15 11:59:31 +053076 stat = (uint64_t *)&dpni_stats;
77 for (i = 0; i < DPNI_STATS_PER_PAGE; i++) {
78 if (strcmp(strings[i], "\0") == 0)
79 break;
80 printf("%s= %llu\n", strings[i], *stat);
81 stat++;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053082 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +053083}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053084
Yogesh Gaur318c32f2017-11-15 11:59:31 +053085static void ldpaa_eth_get_dpni_counter(void)
86{
87 int err = 0;
88 unsigned int page = 0;
89 struct dpni_statistics dpni_stats;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053090
Yogesh Gaur318c32f2017-11-15 11:59:31 +053091 printf("DPNI counters ..\n");
92 for (page = 0; page < 3; page++) {
93 err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS,
94 dflt_dpni->dpni_handle, page,
95 &dpni_stats);
96 if (err < 0) {
97 printf("dpni_get_statistics: failed:");
98 printf("%d for page[%d]\n", err, page);
99 return;
100 }
101 print_dpni_stats(dpni_statistics[page], dpni_stats);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530102 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530103}
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530104
Ioana Ciornei872004f2020-03-18 16:47:37 +0200105static void ldpaa_eth_get_dpmac_counter(struct udevice *dev)
106{
107 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530108 int err = 0;
109 u64 value;
110
111 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
112 priv->dpmac_handle,
113 DPMAC_CNT_ING_BYTE,
114 &value);
115 if (err < 0) {
116 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
117 return;
118 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530119 printf("\nDPMAC counters ..\n");
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530120 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
121
122 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
123 priv->dpmac_handle,
124 DPMAC_CNT_ING_FRAME_DISCARD,
125 &value);
126 if (err < 0) {
127 printf("dpmac_get_counter: DPMAC_CNT_ING_FRAME_DISCARD failed\n");
128 return;
129 }
130 printf("DPMAC_CNT_ING_FRAME_DISCARD=%lld\n", value);
131
132 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
133 priv->dpmac_handle,
134 DPMAC_CNT_ING_ALIGN_ERR,
135 &value);
136 if (err < 0) {
137 printf("dpmac_get_counter: DPMAC_CNT_ING_ALIGN_ERR failed\n");
138 return;
139 }
140 printf("DPMAC_CNT_ING_ALIGN_ERR =%lld\n", value);
141
142 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
143 priv->dpmac_handle,
144 DPMAC_CNT_ING_BYTE,
145 &value);
146 if (err < 0) {
147 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
148 return;
149 }
150 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
151
152 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
153 priv->dpmac_handle,
154 DPMAC_CNT_ING_ERR_FRAME,
155 &value);
156 if (err < 0) {
157 printf("dpmac_get_counter: DPMAC_CNT_ING_ERR_FRAME failed\n");
158 return;
159 }
160 printf("DPMAC_CNT_ING_ERR_FRAME=%lld\n", value);
161
162 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
163 priv->dpmac_handle,
164 DPMAC_CNT_EGR_BYTE ,
165 &value);
166 if (err < 0) {
167 printf("dpmac_get_counter: DPMAC_CNT_EGR_BYTE failed\n");
168 return;
169 }
170 printf("DPMAC_CNT_EGR_BYTE =%lld\n", value);
171
172 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
173 priv->dpmac_handle,
174 DPMAC_CNT_EGR_ERR_FRAME ,
175 &value);
176 if (err < 0) {
177 printf("dpmac_get_counter: DPMAC_CNT_EGR_ERR_FRAME failed\n");
178 return;
179 }
180 printf("DPMAC_CNT_EGR_ERR_FRAME =%lld\n", value);
181}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530182#endif
183
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700184static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
185 const struct dpaa_fd *fd)
186{
187 u64 fd_addr;
188 uint16_t fd_offset;
189 uint32_t fd_length;
190 struct ldpaa_fas *fas;
191 uint32_t status, err;
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530192 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
193 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700194 struct qbman_release_desc releasedesc;
195 struct qbman_swp *swp = dflt_dpio->sw_portal;
196
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700197 fd_addr = ldpaa_fd_get_addr(fd);
198 fd_offset = ldpaa_fd_get_offset(fd);
199 fd_length = ldpaa_fd_get_len(fd);
200
201 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
202
203 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
204 /* Read the frame annotation status word and check for errors */
205 fas = (struct ldpaa_fas *)
206 ((uint8_t *)(fd_addr) +
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530207 dflt_dpni->buf_layout.private_data_size);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700208 status = le32_to_cpu(fas->status);
209 if (status & LDPAA_ETH_RX_ERR_MASK) {
210 printf("Rx frame error(s): 0x%08x\n",
211 status & LDPAA_ETH_RX_ERR_MASK);
212 goto error;
213 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
214 printf("Unsupported feature in bitmask: 0x%08x\n",
215 status & LDPAA_ETH_RX_UNSUPP_MASK);
216 goto error;
217 }
218 }
219
220 debug("Rx frame: To Upper layer\n");
221 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
222 fd_length);
223
224error:
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700225 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700226 qbman_release_desc_clear(&releasedesc);
227 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530228 time_start = get_timer(0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700229 do {
230 /* Release buffer into the QBMAN */
231 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530232 } while (get_timer(time_start) < timeo && err == -EBUSY);
233
234 if (err == -EBUSY)
235 printf("Rx frame: QBMAN buffer release fails\n");
236
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700237 return;
238}
239
Ioana Ciornei872004f2020-03-18 16:47:37 +0200240static int ldpaa_eth_pull_dequeue_rx(struct udevice *dev,
241 int flags, uchar **packetp)
242{
243 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700244 const struct ldpaa_dq *dq;
245 const struct dpaa_fd *fd;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530246 int i = 5, err = 0, status;
247 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
248 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700249 static struct qbman_pull_desc pulldesc;
250 struct qbman_swp *swp = dflt_dpio->sw_portal;
251
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700252 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700253 qbman_pull_desc_clear(&pulldesc);
254 qbman_pull_desc_set_numframes(&pulldesc, 1);
255 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
256
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700257 err = qbman_swp_pull(swp, &pulldesc);
258 if (err < 0) {
259 printf("Dequeue frames error:0x%08x\n", err);
260 continue;
261 }
262
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530263 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700264
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530265 do {
266 dq = qbman_swp_dqrr_next(swp);
267 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700268
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700269 if (dq) {
270 /* Check for valid frame. If not sent a consume
271 * confirmation to QBMAN otherwise give it to NADK
272 * application and then send consume confirmation to
273 * QBMAN.
274 */
275 status = (uint8_t)ldpaa_dq_flags(dq);
276 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
277 debug("Dequeue RX frames:");
278 debug("No frame delivered\n");
279
280 qbman_swp_dqrr_consume(swp, dq);
Prabhakar Kushwaha37ed1a62015-07-02 11:29:07 +0530281 continue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700282 }
283
284 fd = ldpaa_dq_fd(dq);
285
286 /* Obtain FD and process it */
287 ldpaa_eth_rx(priv, fd);
288 qbman_swp_dqrr_consume(swp, dq);
289 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530290 } else {
291 err = -ENODATA;
292 debug("No DQRR entries\n");
293 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700294 }
295 }
296
297 return err;
298}
299
Ioana Ciornei872004f2020-03-18 16:47:37 +0200300static int ldpaa_eth_tx(struct udevice *dev, void *buf, int len)
301{
302 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700303 struct dpaa_fd fd;
304 u64 buffer_start;
305 int data_offset, err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530306 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
307 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700308 struct qbman_swp *swp = dflt_dpio->sw_portal;
309 struct qbman_eq_desc ed;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530310 struct qbman_release_desc releasedesc;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700311
312 /* Setup the FD fields */
313 memset(&fd, 0, sizeof(fd));
314
315 data_offset = priv->tx_data_offset;
316
317 do {
318 err = qbman_swp_acquire(dflt_dpio->sw_portal,
319 dflt_dpbp->dpbp_attr.bpid,
320 &buffer_start, 1);
321 } while (err == -EBUSY);
322
Ashish Kumar34f080c2017-10-26 16:03:22 +0530323 if (err <= 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700324 printf("qbman_swp_acquire() failed\n");
325 return -ENOMEM;
326 }
327
328 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
329
330 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
331
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700332 flush_dcache_range(buffer_start, buffer_start +
333 LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700334
335 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
336 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
337 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
338 ldpaa_fd_set_len(&fd, len);
339
340 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
341 LDPAA_FD_CTRL_PTV1;
342
343 qbman_eq_desc_clear(&ed);
344 qbman_eq_desc_set_no_orp(&ed, 0);
345 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530346
347 time_start = get_timer(0);
348
349 while (get_timer(time_start) < timeo) {
350 err = qbman_swp_enqueue(swp, &ed,
351 (const struct qbman_fd *)(&fd));
352 if (err != -EBUSY)
353 break;
354 }
355
356 if (err < 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700357 printf("error enqueueing Tx frame\n");
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530358 goto error;
359 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700360
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700361 return err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530362
363error:
364 qbman_release_desc_clear(&releasedesc);
365 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
366 time_start = get_timer(0);
367 do {
368 /* Release buffer into the QBMAN */
369 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
370 } while (get_timer(time_start) < timeo && err == -EBUSY);
371
372 if (err == -EBUSY)
373 printf("TX data: QBMAN buffer release fails\n");
374
375 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700376}
377
Pankaj Bansale031d262018-10-10 14:08:32 +0530378static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
379 struct dpmac_link_state *state)
380{
Pankaj Bansale031d262018-10-10 14:08:32 +0530381 phy_interface_t enet_if;
Tom Rini13da6252018-10-11 20:07:48 -0400382 struct phy_device *phydev = NULL;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200383 int err;
Pankaj Bansale031d262018-10-10 14:08:32 +0530384
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530385 /* let's start off with maximum capabilities */
Pankaj Bansale031d262018-10-10 14:08:32 +0530386 enet_if = wriop_get_enet_if(priv->dpmac_id);
387 switch (enet_if) {
388 case PHY_INTERFACE_MODE_XGMII:
389 state->rate = SPEED_10000;
390 break;
391 default:
392 state->rate = SPEED_1000;
393 break;
394 }
Pankaj Bansale031d262018-10-10 14:08:32 +0530395
Ioana Ciornei872004f2020-03-18 16:47:37 +0200396 state->up = 1;
Pankaj Bansale031d262018-10-10 14:08:32 +0530397 state->options |= DPMAC_LINK_OPT_AUTONEG;
Tom Rinie83c2012022-11-27 10:25:14 -0500398 phydev = priv->phy;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530399
Ioana Ciornei872004f2020-03-18 16:47:37 +0200400 if (phydev) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530401 err = phy_startup(phydev);
402 if (err) {
403 printf("%s: Could not initialize\n", phydev->dev->name);
404 state->up = 0;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200405 } else if (phydev->link) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530406 state->rate = min(state->rate, (uint32_t)phydev->speed);
407 if (!phydev->duplex)
408 state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
409 if (!phydev->autoneg)
410 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
411 } else {
412 state->up = 0;
413 }
414 }
Ioana Ciornei872004f2020-03-18 16:47:37 +0200415
416 if (!phydev)
Pankaj Bansale031d262018-10-10 14:08:32 +0530417 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
418
419 if (!state->up) {
420 state->rate = 0;
421 state->options = 0;
422 return -ENOLINK;
423 }
424
425 return 0;
426}
427
Ioana Ciornei872004f2020-03-18 16:47:37 +0200428static int ldpaa_eth_open(struct udevice *dev)
429{
Simon Glassfa20e932020-12-03 16:55:20 -0700430 struct eth_pdata *plat = dev_get_plat(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200431 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530432 struct dpmac_link_state dpmac_link_state = { 0 };
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530433#ifdef DEBUG
434 struct dpni_link_state link_state;
435#endif
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530436 int err = 0;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530437 struct dpni_queue d_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700438
Ioana Ciornei872004f2020-03-18 16:47:37 +0200439 if (eth_is_active(dev))
440 return 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700441
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530442 if (get_mc_boot_status() != 0) {
443 printf("ERROR (MC is not booted)\n");
444 return -ENODEV;
445 }
446
447 if (get_dpl_apply_status() == 0) {
448 printf("ERROR (DPL is deployed. No device available)\n");
449 return -ENODEV;
450 }
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530451
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530452 /* DPMAC initialization */
453 err = ldpaa_dpmac_setup(priv);
454 if (err < 0)
455 goto err_dpmac_setup;
456
Pankaj Bansale031d262018-10-10 14:08:32 +0530457 err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
458 if (err < 0)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530459 goto err_dpmac_bind;
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530460
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530461 /* DPMAC binding DPNI */
462 err = ldpaa_dpmac_bind(priv);
463 if (err)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530464 goto err_dpmac_bind;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530465
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700466 /* DPNI initialization */
467 err = ldpaa_dpni_setup(priv);
468 if (err < 0)
469 goto err_dpni_setup;
470
471 err = ldpaa_dpbp_setup();
472 if (err < 0)
473 goto err_dpbp_setup;
474
475 /* DPNI binding DPBP */
476 err = ldpaa_dpni_bind(priv);
477 if (err)
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530478 goto err_dpni_bind;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700479
Ioana Ciornei872004f2020-03-18 16:47:37 +0200480 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
481 dflt_dpni->dpni_handle, plat->enetaddr);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700482 if (err) {
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530483 printf("dpni_add_mac_addr() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700484 return err;
485 }
486
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530487 err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700488 if (err < 0) {
489 printf("dpni_enable() failed\n");
490 return err;
491 }
492
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530493 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
494 priv->dpmac_handle, &dpmac_link_state);
495 if (err < 0) {
496 printf("dpmac_set_link_state() failed\n");
497 return err;
498 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530499
500#ifdef DEBUG
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530501 printf("DPMAC link status: %d - ", dpmac_link_state.up);
502 dpmac_link_state.up == 0 ? printf("down\n") :
503 dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n");
504
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530505 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
506 dflt_dpni->dpni_handle, &link_state);
507 if (err < 0) {
508 printf("dpni_get_link_state() failed\n");
509 return err;
510 }
511
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530512 printf("DPNI link status: %d - ", link_state.up);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530513 link_state.up == 0 ? printf("down\n") :
514 link_state.up == 1 ? printf("up\n") : printf("error state\n");
515#endif
516
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530517 memset(&d_queue, 0, sizeof(struct dpni_queue));
518 err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
519 dflt_dpni->dpni_handle, DPNI_QUEUE_RX,
520 0, 0, &d_queue);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700521 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530522 printf("dpni_get_queue failed\n");
523 goto err_get_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700524 }
525
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530526 priv->rx_dflt_fqid = d_queue.fqid;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700527
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530528 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530529 &priv->tx_qdid);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700530 if (err) {
531 printf("dpni_get_qdid() failed\n");
532 goto err_qdid;
533 }
534
Pankaj Bansale031d262018-10-10 14:08:32 +0530535 return dpmac_link_state.up;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700536
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700537err_qdid:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530538err_get_queue:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530539 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
540err_dpni_bind:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700541 ldpaa_dpbp_free();
542err_dpbp_setup:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530543 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700544err_dpni_setup:
Pankaj Bansald24b1282018-10-10 14:08:29 +0530545err_dpmac_bind:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530546 dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
547 dpmac_destroy(dflt_mc_io,
548 dflt_dprc_handle,
549 MC_CMD_NO_FLAGS, priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530550err_dpmac_setup:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700551 return err;
552}
553
Ioana Ciornei872004f2020-03-18 16:47:37 +0200554static void ldpaa_eth_stop(struct udevice *dev)
555{
556 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200557 struct phy_device *phydev = NULL;
558 int err = 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700559
Ioana Ciornei872004f2020-03-18 16:47:37 +0200560 if (!eth_is_active(dev))
561 return;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530562
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530563#ifdef DEBUG
564 ldpaa_eth_get_dpni_counter();
Ioana Ciornei872004f2020-03-18 16:47:37 +0200565 ldpaa_eth_get_dpmac_counter(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200566#endif
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530567
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530568 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
569 dflt_dprc_handle, &dpmac_endpoint);
570 if (err < 0)
571 printf("dprc_disconnect() failed dpmac_endpoint\n");
572
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530573 err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
574 if (err < 0)
575 printf("dpmac_close() failed\n");
576
577 err = dpmac_destroy(dflt_mc_io,
578 dflt_dprc_handle,
579 MC_CMD_NO_FLAGS,
580 priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530581 if (err < 0)
582 printf("dpmac_destroy() failed\n");
583
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700584 /* Stop Tx and Rx traffic */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530585 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700586 if (err < 0)
587 printf("dpni_disable() failed\n");
588
Tom Rinie83c2012022-11-27 10:25:14 -0500589 phydev = priv->phy;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200590 if (phydev)
591 phy_shutdown(phydev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700592
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530593 /* Free DPBP handle and reset. */
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700594 ldpaa_dpbp_free();
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530595
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530596 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530597 if (err < 0)
598 printf("dpni_reset() failed\n");
599
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530600 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530601 if (err < 0)
602 printf("dpni_close() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700603}
604
605static void ldpaa_dpbp_drain_cnt(int count)
606{
607 uint64_t buf_array[7];
608 void *addr;
609 int ret, i;
610
611 BUG_ON(count > 7);
612
613 do {
614 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
615 dflt_dpbp->dpbp_attr.bpid,
616 buf_array, count);
617 if (ret < 0) {
618 printf("qbman_swp_acquire() failed\n");
619 return;
620 }
621 for (i = 0; i < ret; i++) {
622 addr = (void *)buf_array[i];
623 debug("Free: buffer addr =0x%p\n", addr);
624 free(addr);
625 }
626 } while (ret);
627}
628
629static void ldpaa_dpbp_drain(void)
630{
631 int i;
632 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
633 ldpaa_dpbp_drain_cnt(7);
634}
635
636static int ldpaa_bp_add_7(uint16_t bpid)
637{
638 uint64_t buf_array[7];
639 u8 *addr;
640 int i;
641 struct qbman_release_desc rd;
642
643 for (i = 0; i < 7; i++) {
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530644 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700645 if (!addr) {
646 printf("addr allocation failed\n");
647 goto err_alloc;
648 }
649 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700650 flush_dcache_range((u64)addr,
651 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700652
653 buf_array[i] = (uint64_t)addr;
654 debug("Release: buffer addr =0x%p\n", addr);
655 }
656
657release_bufs:
658 /* In case the portal is busy, retry until successful.
659 * This function is guaranteed to succeed in a reasonable amount
660 * of time.
661 */
662
663 do {
664 mdelay(1);
665 qbman_release_desc_clear(&rd);
666 qbman_release_desc_set_bpid(&rd, bpid);
667 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
668
669 return i;
670
671err_alloc:
672 if (i)
673 goto release_bufs;
674
675 return 0;
676}
677
678static int ldpaa_dpbp_seed(uint16_t bpid)
679{
680 int i;
681 int count;
682
683 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
684 count = ldpaa_bp_add_7(bpid);
685 if (count < 7)
686 printf("Buffer Seed= %d\n", count);
687 }
688
689 return 0;
690}
691
692static int ldpaa_dpbp_setup(void)
693{
694 int err;
695
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530696 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700697 &dflt_dpbp->dpbp_handle);
698 if (err) {
699 printf("dpbp_open() failed\n");
700 goto err_open;
701 }
702
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530703 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700704 if (err) {
705 printf("dpbp_enable() failed\n");
706 goto err_enable;
707 }
708
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530709 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
710 dflt_dpbp->dpbp_handle,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700711 &dflt_dpbp->dpbp_attr);
712 if (err) {
713 printf("dpbp_get_attributes() failed\n");
714 goto err_get_attr;
715 }
716
717 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530718
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700719 if (err) {
720 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
721 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
722 goto err_seed;
723 }
724
725 return 0;
726
727err_seed:
728err_get_attr:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530729 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700730err_enable:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530731 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700732err_open:
733 return err;
734}
735
736static void ldpaa_dpbp_free(void)
737{
738 ldpaa_dpbp_drain();
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530739 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
740 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
741 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700742}
743
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530744static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
745 struct ldpaa_eth_priv *priv)
746{
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530747 int error;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530748 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530749
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530750 error = dpmac_get_api_version(dflt_mc_io, 0,
751 &major_ver,
752 &minor_ver);
753 if ((major_ver < DPMAC_VER_MAJOR) ||
754 (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) {
755 printf("DPMAC version mismatch found %u.%u,",
756 major_ver, minor_ver);
757 printf("supported version is %u.%u\n",
758 DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
759 return error;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530760 }
761
762 return error;
763}
764
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530765static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
766{
767 int err = 0;
768 struct dpmac_cfg dpmac_cfg;
769
770 dpmac_cfg.mac_id = priv->dpmac_id;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530771
772 err = dpmac_create(dflt_mc_io,
773 dflt_dprc_handle,
774 MC_CMD_NO_FLAGS, &dpmac_cfg,
775 &priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530776 if (err)
777 printf("dpmac_create() failed\n");
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530778
779 err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530780 if (err < 0) {
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530781 printf("ldpaa_dpmac_version_check() failed: %d\n", err);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530782 goto err_version_check;
783 }
784
785 err = dpmac_open(dflt_mc_io,
786 MC_CMD_NO_FLAGS,
787 priv->dpmac_id,
788 &priv->dpmac_handle);
789 if (err < 0) {
790 printf("dpmac_open() failed: %d\n", err);
791 goto err_open;
792 }
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530793
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530794 return err;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530795
796err_open:
797err_version_check:
798 dpmac_destroy(dflt_mc_io,
799 dflt_dprc_handle,
800 MC_CMD_NO_FLAGS, priv->dpmac_id);
801
802 return err;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530803}
804
805static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
806{
807 int err = 0;
808 struct dprc_connection_cfg dprc_connection_cfg = {
809 /* If both rates are zero the connection */
810 /* will be configured in "best effort" mode. */
811 .committed_rate = 0,
812 .max_rate = 0
813 };
814
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530815#ifdef DEBUG
816 struct dprc_endpoint dbg_endpoint;
817 int state = 0;
818#endif
819
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530820 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000821 strcpy(dpmac_endpoint.type, "dpmac");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530822 dpmac_endpoint.id = priv->dpmac_id;
823
824 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000825 strcpy(dpni_endpoint.type, "dpni");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530826 dpni_endpoint.id = dflt_dpni->dpni_id;
827
828 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
829 dflt_dprc_handle,
830 &dpmac_endpoint,
831 &dpni_endpoint,
832 &dprc_connection_cfg);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530833 if (err)
834 printf("dprc_connect() failed\n");
835
836#ifdef DEBUG
837 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
838 dflt_dprc_handle, &dpni_endpoint,
839 &dbg_endpoint, &state);
840 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
841 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
842 printf("%s, DPMAC State= %d\n", __func__, state);
843
844 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
845 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
846 dflt_dprc_handle, &dpmac_endpoint,
847 &dbg_endpoint, &state);
848 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
849 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
850 printf("%s, DPNI State= %d\n", __func__, state);
851#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530852 return err;
853}
854
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700855static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
856{
857 int err;
858
859 /* and get a handle for the DPNI this interface is associate with */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530860 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
861 &dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700862 if (err) {
863 printf("dpni_open() failed\n");
864 goto err_open;
865 }
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530866 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530867 dflt_dpni->dpni_handle,
868 &dflt_dpni->dpni_attrs);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700869 if (err) {
870 printf("dpni_get_attributes() failed (err=%d)\n", err);
871 goto err_get_attr;
872 }
873
874 /* Configure our buffers' layout */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530875 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700876 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530877 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
878 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530879 dflt_dpni->buf_layout.pass_parser_result = true;
880 dflt_dpni->buf_layout.pass_frame_status = true;
881 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530882 /* HW erratum mandates data alignment in multiples of 256 */
883 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530884
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700885 /* ...rx, ... */
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530886 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
887 dflt_dpni->dpni_handle,
888 &dflt_dpni->buf_layout, DPNI_QUEUE_RX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700889 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530890 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700891 goto err_buf_layout;
892 }
893
894 /* ... tx, ... */
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530895 /* remove Rx-only options */
896 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
897 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530898 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
899 dflt_dpni->dpni_handle,
900 &dflt_dpni->buf_layout, DPNI_QUEUE_TX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700901 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530902 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700903 goto err_buf_layout;
904 }
905
906 /* ... tx-confirm. */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530907 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530908 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
909 dflt_dpni->dpni_handle,
910 &dflt_dpni->buf_layout,
911 DPNI_QUEUE_TX_CONFIRM);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700912 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530913 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700914 goto err_buf_layout;
915 }
916
917 /* Now that we've set our tx buffer layout, retrieve the minimum
918 * required tx data offset.
919 */
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530920 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530921 dflt_dpni->dpni_handle,
922 &priv->tx_data_offset);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700923 if (err) {
924 printf("dpni_get_tx_data_offset() failed\n");
925 goto err_data_offset;
926 }
927
928 /* Warn in case TX data offset is not multiple of 64 bytes. */
929 WARN_ON(priv->tx_data_offset % 64);
930
931 /* Accomodate SWA space. */
932 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
933 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
934
935 return 0;
936
937err_data_offset:
938err_buf_layout:
939err_get_attr:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530940 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700941err_open:
942 return err;
943}
944
945static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
946{
947 struct dpni_pools_cfg pools_params;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530948 struct dpni_queue tx_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700949 int err = 0;
950
Prabhakar Kushwahaa7992322016-03-28 14:11:05 +0530951 memset(&pools_params, 0, sizeof(pools_params));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700952 pools_params.num_dpbp = 1;
953 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
954 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530955 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
956 dflt_dpni->dpni_handle, &pools_params);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700957 if (err) {
958 printf("dpni_set_pools() failed\n");
959 return err;
960 }
961
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530962 memset(&tx_queue, 0, sizeof(struct dpni_queue));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700963
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530964 err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
965 dflt_dpni->dpni_handle,
966 DPNI_QUEUE_TX, 0, 0, &tx_queue);
967
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700968 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530969 printf("dpni_set_queue() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700970 return err;
971 }
972
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530973 err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS,
974 dflt_dpni->dpni_handle,
975 DPNI_CONF_DISABLE);
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530976 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530977 printf("dpni_set_tx_confirmation_mode() failed\n");
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530978 return err;
979 }
980
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700981 return 0;
982}
983
Ioana Ciornei872004f2020-03-18 16:47:37 +0200984static int ldpaa_eth_probe(struct udevice *dev)
985{
986 struct ofnode_phandle_args phandle;
987
988 /* Nothing to do if there is no "phy-handle" in the DTS node */
989 if (dev_read_phandle_with_args(dev, "phy-handle", NULL,
990 0, 0, &phandle)) {
991 return 0;
992 }
993
994 init_phy(dev);
995
996 return 0;
997}
998
Ioana Ciornei5d1e9222023-02-09 18:07:03 +0200999uint32_t ldpaa_eth_get_dpmac_id(struct udevice *dev)
Ioana Ciornei872004f2020-03-18 16:47:37 +02001000{
1001 int port_node = dev_of_offset(dev);
1002
1003 return fdtdec_get_uint(gd->fdt_blob, port_node, "reg", -1);
1004}
1005
Ioana Ciornei872004f2020-03-18 16:47:37 +02001006static int ldpaa_eth_bind(struct udevice *dev)
1007{
Ioana Ciornei872004f2020-03-18 16:47:37 +02001008 uint32_t dpmac_id;
1009 char eth_name[16];
1010 int phy_mode = -1;
1011
Marek Behúnbc194772022-04-07 00:33:01 +02001012 phy_mode = dev_read_phy_mode(dev);
Marek Behún48631e42022-04-07 00:33:03 +02001013 if (phy_mode == PHY_INTERFACE_MODE_NA) {
Ioana Ciornei872004f2020-03-18 16:47:37 +02001014 dev_err(dev, "incorrect phy mode\n");
1015 return -EINVAL;
1016 }
1017
1018 dpmac_id = ldpaa_eth_get_dpmac_id(dev);
1019 if (dpmac_id == -1) {
1020 dev_err(dev, "missing reg field from the dpmac node\n");
1021 return -EINVAL;
1022 }
1023
Marek Behúnbc194772022-04-07 00:33:01 +02001024 sprintf(eth_name, "DPMAC%d@%s", dpmac_id,
1025 phy_string_for_interface(phy_mode));
Ioana Ciornei872004f2020-03-18 16:47:37 +02001026 device_set_name(dev, eth_name);
1027
1028 return 0;
1029}
1030
Simon Glassaad29ae2020-12-03 16:55:21 -07001031static int ldpaa_eth_of_to_plat(struct udevice *dev)
Ioana Ciornei872004f2020-03-18 16:47:37 +02001032{
1033 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +02001034
1035 priv->dpmac_id = ldpaa_eth_get_dpmac_id(dev);
Marek Behúnbc194772022-04-07 00:33:01 +02001036 priv->phy_mode = dev_read_phy_mode(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +02001037
1038 return 0;
1039}
1040
1041static const struct eth_ops ldpaa_eth_ops = {
1042 .start = ldpaa_eth_open,
1043 .send = ldpaa_eth_tx,
1044 .recv = ldpaa_eth_pull_dequeue_rx,
1045 .stop = ldpaa_eth_stop,
1046};
1047
1048static const struct udevice_id ldpaa_eth_of_ids[] = {
1049 { .compatible = "fsl,qoriq-mc-dpmac" },
1050};
1051
1052U_BOOT_DRIVER(ldpaa_eth) = {
Ioana Ciornei5d1e9222023-02-09 18:07:03 +02001053 .name = LDPAA_ETH_DRIVER_NAME,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001054 .id = UCLASS_ETH,
1055 .of_match = ldpaa_eth_of_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001056 .of_to_plat = ldpaa_eth_of_to_plat,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001057 .bind = ldpaa_eth_bind,
1058 .probe = ldpaa_eth_probe,
1059 .ops = &ldpaa_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001060 .priv_auto = sizeof(struct ldpaa_eth_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -07001061 .plat_auto = sizeof(struct eth_pdata),
Ioana Ciornei872004f2020-03-18 16:47:37 +02001062};