blob: 907e51da6e1ea7bd41e9d046a27e63c2d9f33f5b [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
Ioana Ciorneia121fe42023-05-23 16:47:45 +030041static void ldpaa_eth_collect_dpni_stats(struct udevice *dev, u64 *data)
42{
43 union dpni_statistics dpni_stats;
44 int dpni_stats_page_size[DPNI_STATISTICS_CNT] = {
45 sizeof(dpni_stats.page_0),
46 sizeof(dpni_stats.page_1),
47 sizeof(dpni_stats.page_2),
48 sizeof(dpni_stats.page_3),
49 sizeof(dpni_stats.page_4),
50 sizeof(dpni_stats.page_5),
51 sizeof(dpni_stats.page_6),
52 };
53 int j, k, num_cnt, err, i = 0;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053054
Ioana Ciorneia121fe42023-05-23 16:47:45 +030055 for (j = 0; j <= 6; j++) {
56 /* We're not interested in pages 4 & 5 for now */
57 if (j == 4 || j == 5)
58 continue;
59 err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS,
60 dflt_dpni->dpni_handle,
61 j, &dpni_stats);
62 if (err) {
63 memset(&dpni_stats, 0, sizeof(dpni_stats));
64 printf("dpni_get_stats(%d) failed\n", j);
65 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053066
Ioana Ciorneia121fe42023-05-23 16:47:45 +030067 num_cnt = dpni_stats_page_size[j] / sizeof(u64);
68 for (k = 0; k < num_cnt; k++)
69 *(data + i++) = dpni_stats.raw.counter[k];
70 }
71}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053072
Ioana Ciorneia121fe42023-05-23 16:47:45 +030073static void ldpaa_eth_add_dpni_stats(struct udevice *dev, u64 *data)
Yogesh Gaur318c32f2017-11-15 11:59:31 +053074{
Ioana Ciorneia121fe42023-05-23 16:47:45 +030075 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Yogesh Gaur318c32f2017-11-15 11:59:31 +053076 int i;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053077
Ioana Ciorneia121fe42023-05-23 16:47:45 +030078 for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
79 priv->dpni_stats[i] += data[i];
Yogesh Gaur318c32f2017-11-15 11:59:31 +053080}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053081
Ioana Ciorneia121fe42023-05-23 16:47:45 +030082#ifdef DEBUG
83
84static void ldpaa_eth_dump_dpni_stats(struct udevice *dev, u64 *data)
Yogesh Gaur318c32f2017-11-15 11:59:31 +053085{
Ioana Ciorneia121fe42023-05-23 16:47:45 +030086 int i;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053087
Ioana Ciorneia121fe42023-05-23 16:47:45 +030088 printf("DPNI counters:\n");
89 for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
90 printf(" %s: %llu\n", ldpaa_eth_dpni_stat_strings[i], data[i]);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053091}
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +053092
Ioana Ciornei872004f2020-03-18 16:47:37 +020093static void ldpaa_eth_get_dpmac_counter(struct udevice *dev)
94{
95 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +053096 int err = 0;
97 u64 value;
98
99 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
100 priv->dpmac_handle,
101 DPMAC_CNT_ING_BYTE,
102 &value);
103 if (err < 0) {
104 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
105 return;
106 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530107 printf("\nDPMAC counters ..\n");
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530108 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
109
110 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
111 priv->dpmac_handle,
112 DPMAC_CNT_ING_FRAME_DISCARD,
113 &value);
114 if (err < 0) {
115 printf("dpmac_get_counter: DPMAC_CNT_ING_FRAME_DISCARD failed\n");
116 return;
117 }
118 printf("DPMAC_CNT_ING_FRAME_DISCARD=%lld\n", value);
119
120 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
121 priv->dpmac_handle,
122 DPMAC_CNT_ING_ALIGN_ERR,
123 &value);
124 if (err < 0) {
125 printf("dpmac_get_counter: DPMAC_CNT_ING_ALIGN_ERR failed\n");
126 return;
127 }
128 printf("DPMAC_CNT_ING_ALIGN_ERR =%lld\n", value);
129
130 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
131 priv->dpmac_handle,
132 DPMAC_CNT_ING_BYTE,
133 &value);
134 if (err < 0) {
135 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
136 return;
137 }
138 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
139
140 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
141 priv->dpmac_handle,
142 DPMAC_CNT_ING_ERR_FRAME,
143 &value);
144 if (err < 0) {
145 printf("dpmac_get_counter: DPMAC_CNT_ING_ERR_FRAME failed\n");
146 return;
147 }
148 printf("DPMAC_CNT_ING_ERR_FRAME=%lld\n", value);
149
150 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
151 priv->dpmac_handle,
152 DPMAC_CNT_EGR_BYTE ,
153 &value);
154 if (err < 0) {
155 printf("dpmac_get_counter: DPMAC_CNT_EGR_BYTE failed\n");
156 return;
157 }
158 printf("DPMAC_CNT_EGR_BYTE =%lld\n", value);
159
160 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
161 priv->dpmac_handle,
162 DPMAC_CNT_EGR_ERR_FRAME ,
163 &value);
164 if (err < 0) {
165 printf("dpmac_get_counter: DPMAC_CNT_EGR_ERR_FRAME failed\n");
166 return;
167 }
168 printf("DPMAC_CNT_EGR_ERR_FRAME =%lld\n", value);
169}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530170#endif
171
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700172static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
173 const struct dpaa_fd *fd)
174{
175 u64 fd_addr;
176 uint16_t fd_offset;
177 uint32_t fd_length;
178 struct ldpaa_fas *fas;
179 uint32_t status, err;
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530180 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
181 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700182 struct qbman_release_desc releasedesc;
183 struct qbman_swp *swp = dflt_dpio->sw_portal;
184
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700185 fd_addr = ldpaa_fd_get_addr(fd);
186 fd_offset = ldpaa_fd_get_offset(fd);
187 fd_length = ldpaa_fd_get_len(fd);
188
189 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
190
191 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
192 /* Read the frame annotation status word and check for errors */
193 fas = (struct ldpaa_fas *)
194 ((uint8_t *)(fd_addr) +
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530195 dflt_dpni->buf_layout.private_data_size);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700196 status = le32_to_cpu(fas->status);
197 if (status & LDPAA_ETH_RX_ERR_MASK) {
198 printf("Rx frame error(s): 0x%08x\n",
199 status & LDPAA_ETH_RX_ERR_MASK);
200 goto error;
201 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
202 printf("Unsupported feature in bitmask: 0x%08x\n",
203 status & LDPAA_ETH_RX_UNSUPP_MASK);
204 goto error;
205 }
206 }
207
208 debug("Rx frame: To Upper layer\n");
209 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
210 fd_length);
211
212error:
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700213 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700214 qbman_release_desc_clear(&releasedesc);
215 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530216 time_start = get_timer(0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700217 do {
218 /* Release buffer into the QBMAN */
219 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530220 } while (get_timer(time_start) < timeo && err == -EBUSY);
221
222 if (err == -EBUSY)
223 printf("Rx frame: QBMAN buffer release fails\n");
224
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700225 return;
226}
227
Ioana Ciornei872004f2020-03-18 16:47:37 +0200228static int ldpaa_eth_pull_dequeue_rx(struct udevice *dev,
229 int flags, uchar **packetp)
230{
231 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700232 const struct ldpaa_dq *dq;
233 const struct dpaa_fd *fd;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530234 int i = 5, err = 0, status;
235 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
236 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700237 static struct qbman_pull_desc pulldesc;
238 struct qbman_swp *swp = dflt_dpio->sw_portal;
239
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700240 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700241 qbman_pull_desc_clear(&pulldesc);
242 qbman_pull_desc_set_numframes(&pulldesc, 1);
243 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
244
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700245 err = qbman_swp_pull(swp, &pulldesc);
246 if (err < 0) {
247 printf("Dequeue frames error:0x%08x\n", err);
248 continue;
249 }
250
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530251 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700252
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530253 do {
254 dq = qbman_swp_dqrr_next(swp);
255 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700256
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700257 if (dq) {
258 /* Check for valid frame. If not sent a consume
259 * confirmation to QBMAN otherwise give it to NADK
260 * application and then send consume confirmation to
261 * QBMAN.
262 */
263 status = (uint8_t)ldpaa_dq_flags(dq);
264 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
265 debug("Dequeue RX frames:");
266 debug("No frame delivered\n");
267
268 qbman_swp_dqrr_consume(swp, dq);
Prabhakar Kushwaha37ed1a62015-07-02 11:29:07 +0530269 continue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700270 }
271
272 fd = ldpaa_dq_fd(dq);
273
274 /* Obtain FD and process it */
275 ldpaa_eth_rx(priv, fd);
276 qbman_swp_dqrr_consume(swp, dq);
277 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530278 } else {
279 err = -ENODATA;
280 debug("No DQRR entries\n");
281 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700282 }
283 }
284
285 return err;
286}
287
Ioana Ciornei872004f2020-03-18 16:47:37 +0200288static int ldpaa_eth_tx(struct udevice *dev, void *buf, int len)
289{
290 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700291 struct dpaa_fd fd;
292 u64 buffer_start;
293 int data_offset, err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530294 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
295 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700296 struct qbman_swp *swp = dflt_dpio->sw_portal;
297 struct qbman_eq_desc ed;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530298 struct qbman_release_desc releasedesc;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700299
300 /* Setup the FD fields */
301 memset(&fd, 0, sizeof(fd));
302
303 data_offset = priv->tx_data_offset;
304
305 do {
306 err = qbman_swp_acquire(dflt_dpio->sw_portal,
307 dflt_dpbp->dpbp_attr.bpid,
308 &buffer_start, 1);
309 } while (err == -EBUSY);
310
Ashish Kumar34f080c2017-10-26 16:03:22 +0530311 if (err <= 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700312 printf("qbman_swp_acquire() failed\n");
313 return -ENOMEM;
314 }
315
316 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
317
318 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
319
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700320 flush_dcache_range(buffer_start, buffer_start +
321 LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700322
323 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
324 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
325 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
326 ldpaa_fd_set_len(&fd, len);
327
328 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
329 LDPAA_FD_CTRL_PTV1;
330
331 qbman_eq_desc_clear(&ed);
332 qbman_eq_desc_set_no_orp(&ed, 0);
333 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530334
335 time_start = get_timer(0);
336
337 while (get_timer(time_start) < timeo) {
338 err = qbman_swp_enqueue(swp, &ed,
339 (const struct qbman_fd *)(&fd));
340 if (err != -EBUSY)
341 break;
342 }
343
344 if (err < 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700345 printf("error enqueueing Tx frame\n");
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530346 goto error;
347 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700348
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700349 return err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530350
351error:
352 qbman_release_desc_clear(&releasedesc);
353 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
354 time_start = get_timer(0);
355 do {
356 /* Release buffer into the QBMAN */
357 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
358 } while (get_timer(time_start) < timeo && err == -EBUSY);
359
360 if (err == -EBUSY)
361 printf("TX data: QBMAN buffer release fails\n");
362
363 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700364}
365
Pankaj Bansale031d262018-10-10 14:08:32 +0530366static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
367 struct dpmac_link_state *state)
368{
Pankaj Bansale031d262018-10-10 14:08:32 +0530369 phy_interface_t enet_if;
Tom Rini13da6252018-10-11 20:07:48 -0400370 struct phy_device *phydev = NULL;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200371 int err;
Pankaj Bansale031d262018-10-10 14:08:32 +0530372
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530373 /* let's start off with maximum capabilities */
Pankaj Bansale031d262018-10-10 14:08:32 +0530374 enet_if = wriop_get_enet_if(priv->dpmac_id);
375 switch (enet_if) {
376 case PHY_INTERFACE_MODE_XGMII:
377 state->rate = SPEED_10000;
378 break;
379 default:
380 state->rate = SPEED_1000;
381 break;
382 }
Pankaj Bansale031d262018-10-10 14:08:32 +0530383
Ioana Ciornei872004f2020-03-18 16:47:37 +0200384 state->up = 1;
Pankaj Bansale031d262018-10-10 14:08:32 +0530385 state->options |= DPMAC_LINK_OPT_AUTONEG;
Tom Rinie83c2012022-11-27 10:25:14 -0500386 phydev = priv->phy;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530387
Ioana Ciornei872004f2020-03-18 16:47:37 +0200388 if (phydev) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530389 err = phy_startup(phydev);
390 if (err) {
391 printf("%s: Could not initialize\n", phydev->dev->name);
392 state->up = 0;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200393 } else if (phydev->link) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530394 state->rate = min(state->rate, (uint32_t)phydev->speed);
395 if (!phydev->duplex)
396 state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
397 if (!phydev->autoneg)
398 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
399 } else {
400 state->up = 0;
401 }
402 }
Ioana Ciornei872004f2020-03-18 16:47:37 +0200403
404 if (!phydev)
Pankaj Bansale031d262018-10-10 14:08:32 +0530405 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
406
407 if (!state->up) {
408 state->rate = 0;
409 state->options = 0;
410 return -ENOLINK;
411 }
412
413 return 0;
414}
415
Ioana Ciornei872004f2020-03-18 16:47:37 +0200416static int ldpaa_eth_open(struct udevice *dev)
417{
Simon Glassfa20e932020-12-03 16:55:20 -0700418 struct eth_pdata *plat = dev_get_plat(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200419 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530420 struct dpmac_link_state dpmac_link_state = { 0 };
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530421#ifdef DEBUG
422 struct dpni_link_state link_state;
423#endif
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530424 int err = 0;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530425 struct dpni_queue d_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700426
Ioana Ciornei872004f2020-03-18 16:47:37 +0200427 if (eth_is_active(dev))
428 return 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700429
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530430 if (get_mc_boot_status() != 0) {
431 printf("ERROR (MC is not booted)\n");
432 return -ENODEV;
433 }
434
435 if (get_dpl_apply_status() == 0) {
436 printf("ERROR (DPL is deployed. No device available)\n");
437 return -ENODEV;
438 }
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530439
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530440 /* DPMAC initialization */
441 err = ldpaa_dpmac_setup(priv);
442 if (err < 0)
443 goto err_dpmac_setup;
444
Pankaj Bansale031d262018-10-10 14:08:32 +0530445 err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
446 if (err < 0)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530447 goto err_dpmac_bind;
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530448
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530449 /* DPMAC binding DPNI */
450 err = ldpaa_dpmac_bind(priv);
451 if (err)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530452 goto err_dpmac_bind;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530453
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700454 /* DPNI initialization */
455 err = ldpaa_dpni_setup(priv);
456 if (err < 0)
457 goto err_dpni_setup;
458
459 err = ldpaa_dpbp_setup();
460 if (err < 0)
461 goto err_dpbp_setup;
462
463 /* DPNI binding DPBP */
464 err = ldpaa_dpni_bind(priv);
465 if (err)
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530466 goto err_dpni_bind;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700467
Ioana Ciornei872004f2020-03-18 16:47:37 +0200468 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
469 dflt_dpni->dpni_handle, plat->enetaddr);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700470 if (err) {
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530471 printf("dpni_add_mac_addr() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700472 return err;
473 }
474
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530475 err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700476 if (err < 0) {
477 printf("dpni_enable() failed\n");
478 return err;
479 }
480
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530481 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
482 priv->dpmac_handle, &dpmac_link_state);
483 if (err < 0) {
484 printf("dpmac_set_link_state() failed\n");
485 return err;
486 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530487
488#ifdef DEBUG
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530489 printf("DPMAC link status: %d - ", dpmac_link_state.up);
490 dpmac_link_state.up == 0 ? printf("down\n") :
491 dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n");
492
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530493 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
494 dflt_dpni->dpni_handle, &link_state);
495 if (err < 0) {
496 printf("dpni_get_link_state() failed\n");
497 return err;
498 }
499
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530500 printf("DPNI link status: %d - ", link_state.up);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530501 link_state.up == 0 ? printf("down\n") :
502 link_state.up == 1 ? printf("up\n") : printf("error state\n");
503#endif
504
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530505 memset(&d_queue, 0, sizeof(struct dpni_queue));
506 err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
507 dflt_dpni->dpni_handle, DPNI_QUEUE_RX,
508 0, 0, &d_queue);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700509 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530510 printf("dpni_get_queue failed\n");
511 goto err_get_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700512 }
513
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530514 priv->rx_dflt_fqid = d_queue.fqid;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700515
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530516 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530517 &priv->tx_qdid);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700518 if (err) {
519 printf("dpni_get_qdid() failed\n");
520 goto err_qdid;
521 }
522
Pankaj Bansale031d262018-10-10 14:08:32 +0530523 return dpmac_link_state.up;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700524
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700525err_qdid:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530526err_get_queue:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530527 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
528err_dpni_bind:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700529 ldpaa_dpbp_free();
530err_dpbp_setup:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530531 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700532err_dpni_setup:
Pankaj Bansald24b1282018-10-10 14:08:29 +0530533err_dpmac_bind:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530534 dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
535 dpmac_destroy(dflt_mc_io,
536 dflt_dprc_handle,
537 MC_CMD_NO_FLAGS, priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530538err_dpmac_setup:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700539 return err;
540}
541
Ioana Ciornei872004f2020-03-18 16:47:37 +0200542static void ldpaa_eth_stop(struct udevice *dev)
543{
544 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200545 struct phy_device *phydev = NULL;
546 int err = 0;
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300547 u64 *data;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700548
Ioana Ciornei872004f2020-03-18 16:47:37 +0200549 if (!eth_is_active(dev))
550 return;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530551
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300552 data = kzalloc(sizeof(u64) * LDPAA_ETH_DPNI_NUM_STATS, GFP_KERNEL);
553 if (data) {
554 ldpaa_eth_collect_dpni_stats(dev, data);
555 ldpaa_eth_add_dpni_stats(dev, data);
556#ifdef DEBUG
557 ldpaa_eth_dump_dpni_stats(dev, data);
558#endif
559 }
560 kfree(data);
561
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530562#ifdef DEBUG
Ioana Ciornei872004f2020-03-18 16:47:37 +0200563 ldpaa_eth_get_dpmac_counter(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200564#endif
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530565
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530566 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
567 dflt_dprc_handle, &dpmac_endpoint);
568 if (err < 0)
569 printf("dprc_disconnect() failed dpmac_endpoint\n");
570
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530571 err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
572 if (err < 0)
573 printf("dpmac_close() failed\n");
574
575 err = dpmac_destroy(dflt_mc_io,
576 dflt_dprc_handle,
577 MC_CMD_NO_FLAGS,
578 priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530579 if (err < 0)
580 printf("dpmac_destroy() failed\n");
581
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700582 /* Stop Tx and Rx traffic */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530583 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700584 if (err < 0)
585 printf("dpni_disable() failed\n");
586
Tom Rinie83c2012022-11-27 10:25:14 -0500587 phydev = priv->phy;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200588 if (phydev)
589 phy_shutdown(phydev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700590
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530591 /* Free DPBP handle and reset. */
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700592 ldpaa_dpbp_free();
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530593
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530594 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530595 if (err < 0)
596 printf("dpni_reset() failed\n");
597
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530598 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530599 if (err < 0)
600 printf("dpni_close() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700601}
602
603static void ldpaa_dpbp_drain_cnt(int count)
604{
605 uint64_t buf_array[7];
606 void *addr;
607 int ret, i;
608
609 BUG_ON(count > 7);
610
611 do {
612 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
613 dflt_dpbp->dpbp_attr.bpid,
614 buf_array, count);
615 if (ret < 0) {
616 printf("qbman_swp_acquire() failed\n");
617 return;
618 }
619 for (i = 0; i < ret; i++) {
620 addr = (void *)buf_array[i];
621 debug("Free: buffer addr =0x%p\n", addr);
622 free(addr);
623 }
624 } while (ret);
625}
626
627static void ldpaa_dpbp_drain(void)
628{
629 int i;
630 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
631 ldpaa_dpbp_drain_cnt(7);
632}
633
634static int ldpaa_bp_add_7(uint16_t bpid)
635{
636 uint64_t buf_array[7];
637 u8 *addr;
638 int i;
639 struct qbman_release_desc rd;
640
641 for (i = 0; i < 7; i++) {
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530642 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700643 if (!addr) {
644 printf("addr allocation failed\n");
645 goto err_alloc;
646 }
647 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700648 flush_dcache_range((u64)addr,
649 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700650
651 buf_array[i] = (uint64_t)addr;
652 debug("Release: buffer addr =0x%p\n", addr);
653 }
654
655release_bufs:
656 /* In case the portal is busy, retry until successful.
657 * This function is guaranteed to succeed in a reasonable amount
658 * of time.
659 */
660
661 do {
662 mdelay(1);
663 qbman_release_desc_clear(&rd);
664 qbman_release_desc_set_bpid(&rd, bpid);
665 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
666
667 return i;
668
669err_alloc:
670 if (i)
671 goto release_bufs;
672
673 return 0;
674}
675
676static int ldpaa_dpbp_seed(uint16_t bpid)
677{
678 int i;
679 int count;
680
681 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
682 count = ldpaa_bp_add_7(bpid);
683 if (count < 7)
684 printf("Buffer Seed= %d\n", count);
685 }
686
687 return 0;
688}
689
690static int ldpaa_dpbp_setup(void)
691{
692 int err;
693
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530694 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700695 &dflt_dpbp->dpbp_handle);
696 if (err) {
697 printf("dpbp_open() failed\n");
698 goto err_open;
699 }
700
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530701 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700702 if (err) {
703 printf("dpbp_enable() failed\n");
704 goto err_enable;
705 }
706
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530707 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
708 dflt_dpbp->dpbp_handle,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700709 &dflt_dpbp->dpbp_attr);
710 if (err) {
711 printf("dpbp_get_attributes() failed\n");
712 goto err_get_attr;
713 }
714
715 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530716
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700717 if (err) {
718 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
719 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
720 goto err_seed;
721 }
722
723 return 0;
724
725err_seed:
726err_get_attr:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530727 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700728err_enable:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530729 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700730err_open:
731 return err;
732}
733
734static void ldpaa_dpbp_free(void)
735{
736 ldpaa_dpbp_drain();
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530737 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
738 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
739 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700740}
741
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530742static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
743 struct ldpaa_eth_priv *priv)
744{
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530745 int error;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530746 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530747
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530748 error = dpmac_get_api_version(dflt_mc_io, 0,
749 &major_ver,
750 &minor_ver);
751 if ((major_ver < DPMAC_VER_MAJOR) ||
752 (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) {
753 printf("DPMAC version mismatch found %u.%u,",
754 major_ver, minor_ver);
755 printf("supported version is %u.%u\n",
756 DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
757 return error;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530758 }
759
760 return error;
761}
762
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530763static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
764{
765 int err = 0;
766 struct dpmac_cfg dpmac_cfg;
767
768 dpmac_cfg.mac_id = priv->dpmac_id;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530769
770 err = dpmac_create(dflt_mc_io,
771 dflt_dprc_handle,
772 MC_CMD_NO_FLAGS, &dpmac_cfg,
773 &priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530774 if (err)
775 printf("dpmac_create() failed\n");
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530776
777 err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530778 if (err < 0) {
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530779 printf("ldpaa_dpmac_version_check() failed: %d\n", err);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530780 goto err_version_check;
781 }
782
783 err = dpmac_open(dflt_mc_io,
784 MC_CMD_NO_FLAGS,
785 priv->dpmac_id,
786 &priv->dpmac_handle);
787 if (err < 0) {
788 printf("dpmac_open() failed: %d\n", err);
789 goto err_open;
790 }
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530791
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530792 return err;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530793
794err_open:
795err_version_check:
796 dpmac_destroy(dflt_mc_io,
797 dflt_dprc_handle,
798 MC_CMD_NO_FLAGS, priv->dpmac_id);
799
800 return err;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530801}
802
803static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
804{
805 int err = 0;
806 struct dprc_connection_cfg dprc_connection_cfg = {
807 /* If both rates are zero the connection */
808 /* will be configured in "best effort" mode. */
809 .committed_rate = 0,
810 .max_rate = 0
811 };
812
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530813#ifdef DEBUG
814 struct dprc_endpoint dbg_endpoint;
815 int state = 0;
816#endif
817
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530818 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000819 strcpy(dpmac_endpoint.type, "dpmac");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530820 dpmac_endpoint.id = priv->dpmac_id;
821
822 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000823 strcpy(dpni_endpoint.type, "dpni");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530824 dpni_endpoint.id = dflt_dpni->dpni_id;
825
826 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
827 dflt_dprc_handle,
828 &dpmac_endpoint,
829 &dpni_endpoint,
830 &dprc_connection_cfg);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530831 if (err)
832 printf("dprc_connect() failed\n");
833
834#ifdef DEBUG
835 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
836 dflt_dprc_handle, &dpni_endpoint,
837 &dbg_endpoint, &state);
838 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
839 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
840 printf("%s, DPMAC State= %d\n", __func__, state);
841
842 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
843 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
844 dflt_dprc_handle, &dpmac_endpoint,
845 &dbg_endpoint, &state);
846 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
847 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
848 printf("%s, DPNI State= %d\n", __func__, state);
849#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530850 return err;
851}
852
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700853static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
854{
855 int err;
856
857 /* and get a handle for the DPNI this interface is associate with */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530858 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
859 &dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700860 if (err) {
861 printf("dpni_open() failed\n");
862 goto err_open;
863 }
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530864 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530865 dflt_dpni->dpni_handle,
866 &dflt_dpni->dpni_attrs);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700867 if (err) {
868 printf("dpni_get_attributes() failed (err=%d)\n", err);
869 goto err_get_attr;
870 }
871
872 /* Configure our buffers' layout */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530873 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700874 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530875 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
876 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530877 dflt_dpni->buf_layout.pass_parser_result = true;
878 dflt_dpni->buf_layout.pass_frame_status = true;
879 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530880 /* HW erratum mandates data alignment in multiples of 256 */
881 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530882
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700883 /* ...rx, ... */
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530884 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
885 dflt_dpni->dpni_handle,
886 &dflt_dpni->buf_layout, DPNI_QUEUE_RX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700887 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530888 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700889 goto err_buf_layout;
890 }
891
892 /* ... tx, ... */
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530893 /* remove Rx-only options */
894 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
895 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530896 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
897 dflt_dpni->dpni_handle,
898 &dflt_dpni->buf_layout, DPNI_QUEUE_TX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700899 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530900 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700901 goto err_buf_layout;
902 }
903
904 /* ... tx-confirm. */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530905 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530906 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
907 dflt_dpni->dpni_handle,
908 &dflt_dpni->buf_layout,
909 DPNI_QUEUE_TX_CONFIRM);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700910 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530911 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700912 goto err_buf_layout;
913 }
914
915 /* Now that we've set our tx buffer layout, retrieve the minimum
916 * required tx data offset.
917 */
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530918 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530919 dflt_dpni->dpni_handle,
920 &priv->tx_data_offset);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700921 if (err) {
922 printf("dpni_get_tx_data_offset() failed\n");
923 goto err_data_offset;
924 }
925
926 /* Warn in case TX data offset is not multiple of 64 bytes. */
927 WARN_ON(priv->tx_data_offset % 64);
928
929 /* Accomodate SWA space. */
930 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
931 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
932
933 return 0;
934
935err_data_offset:
936err_buf_layout:
937err_get_attr:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530938 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700939err_open:
940 return err;
941}
942
943static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
944{
945 struct dpni_pools_cfg pools_params;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530946 struct dpni_queue tx_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700947 int err = 0;
948
Prabhakar Kushwahaa7992322016-03-28 14:11:05 +0530949 memset(&pools_params, 0, sizeof(pools_params));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700950 pools_params.num_dpbp = 1;
951 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
952 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530953 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
954 dflt_dpni->dpni_handle, &pools_params);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700955 if (err) {
956 printf("dpni_set_pools() failed\n");
957 return err;
958 }
959
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530960 memset(&tx_queue, 0, sizeof(struct dpni_queue));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700961
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530962 err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
963 dflt_dpni->dpni_handle,
964 DPNI_QUEUE_TX, 0, 0, &tx_queue);
965
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700966 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530967 printf("dpni_set_queue() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700968 return err;
969 }
970
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530971 err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS,
972 dflt_dpni->dpni_handle,
973 DPNI_CONF_DISABLE);
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530974 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530975 printf("dpni_set_tx_confirmation_mode() failed\n");
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530976 return err;
977 }
978
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700979 return 0;
980}
981
Ioana Ciornei872004f2020-03-18 16:47:37 +0200982static int ldpaa_eth_probe(struct udevice *dev)
983{
984 struct ofnode_phandle_args phandle;
985
986 /* Nothing to do if there is no "phy-handle" in the DTS node */
987 if (dev_read_phandle_with_args(dev, "phy-handle", NULL,
988 0, 0, &phandle)) {
989 return 0;
990 }
991
992 init_phy(dev);
993
994 return 0;
995}
996
Ioana Ciornei5d1e9222023-02-09 18:07:03 +0200997uint32_t ldpaa_eth_get_dpmac_id(struct udevice *dev)
Ioana Ciornei872004f2020-03-18 16:47:37 +0200998{
999 int port_node = dev_of_offset(dev);
1000
1001 return fdtdec_get_uint(gd->fdt_blob, port_node, "reg", -1);
1002}
1003
Ioana Ciornei872004f2020-03-18 16:47:37 +02001004static int ldpaa_eth_bind(struct udevice *dev)
1005{
Ioana Ciornei872004f2020-03-18 16:47:37 +02001006 uint32_t dpmac_id;
1007 char eth_name[16];
1008 int phy_mode = -1;
1009
Marek Behúnbc194772022-04-07 00:33:01 +02001010 phy_mode = dev_read_phy_mode(dev);
Marek Behún48631e42022-04-07 00:33:03 +02001011 if (phy_mode == PHY_INTERFACE_MODE_NA) {
Ioana Ciornei872004f2020-03-18 16:47:37 +02001012 dev_err(dev, "incorrect phy mode\n");
1013 return -EINVAL;
1014 }
1015
1016 dpmac_id = ldpaa_eth_get_dpmac_id(dev);
1017 if (dpmac_id == -1) {
1018 dev_err(dev, "missing reg field from the dpmac node\n");
1019 return -EINVAL;
1020 }
1021
Marek Behúnbc194772022-04-07 00:33:01 +02001022 sprintf(eth_name, "DPMAC%d@%s", dpmac_id,
1023 phy_string_for_interface(phy_mode));
Ioana Ciornei872004f2020-03-18 16:47:37 +02001024 device_set_name(dev, eth_name);
1025
1026 return 0;
1027}
1028
Simon Glassaad29ae2020-12-03 16:55:21 -07001029static int ldpaa_eth_of_to_plat(struct udevice *dev)
Ioana Ciornei872004f2020-03-18 16:47:37 +02001030{
1031 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +02001032
1033 priv->dpmac_id = ldpaa_eth_get_dpmac_id(dev);
Marek Behúnbc194772022-04-07 00:33:01 +02001034 priv->phy_mode = dev_read_phy_mode(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +02001035
1036 return 0;
1037}
1038
1039static const struct eth_ops ldpaa_eth_ops = {
1040 .start = ldpaa_eth_open,
1041 .send = ldpaa_eth_tx,
1042 .recv = ldpaa_eth_pull_dequeue_rx,
1043 .stop = ldpaa_eth_stop,
1044};
1045
1046static const struct udevice_id ldpaa_eth_of_ids[] = {
1047 { .compatible = "fsl,qoriq-mc-dpmac" },
1048};
1049
1050U_BOOT_DRIVER(ldpaa_eth) = {
Ioana Ciornei5d1e9222023-02-09 18:07:03 +02001051 .name = LDPAA_ETH_DRIVER_NAME,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001052 .id = UCLASS_ETH,
1053 .of_match = ldpaa_eth_of_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001054 .of_to_plat = ldpaa_eth_of_to_plat,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001055 .bind = ldpaa_eth_bind,
1056 .probe = ldpaa_eth_probe,
1057 .ops = &ldpaa_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001058 .priv_auto = sizeof(struct ldpaa_eth_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -07001059 .plat_auto = sizeof(struct eth_pdata),
Ioana Ciornei872004f2020-03-18 16:47:37 +02001060};