blob: 87fbada06ba2ca7bb80e09608b5d7b1ebb36fb0e [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
Tom Riniabb9a042024-05-18 20:20:43 -06007#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,
Ioana Ciorneibe117372023-05-31 19:04:33 +030061 j, 0, &dpni_stats);
Ioana Ciorneia121fe42023-05-23 16:47:45 +030062 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 Ciornei98fdaaa2023-05-23 16:47:46 +030082static void ldpaa_eth_collect_dpmac_stats(struct udevice *dev, u64 *data)
83{
84 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
85 int err, i;
86 u64 value;
Ioana Ciorneia121fe42023-05-23 16:47:45 +030087
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +030088 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++) {
89 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
90 priv->dpmac_handle, i,
91 &value);
92 if (err)
93 printf("dpmac_get_counter(%d) failed\n", i);
94
95 *(data + i) = value;
96 }
97}
98
99static void ldpaa_eth_add_dpmac_stats(struct udevice *dev, u64 *data)
100{
101 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
102 int i;
103
104 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++)
105 priv->dpmac_stats[i] += data[i];
106}
107
108#ifdef DEBUG
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300109static void ldpaa_eth_dump_dpni_stats(struct udevice *dev, u64 *data)
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530110{
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300111 int i;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530112
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300113 printf("DPNI counters:\n");
114 for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
115 printf(" %s: %llu\n", ldpaa_eth_dpni_stat_strings[i], data[i]);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530116}
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530117
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300118static void ldpaa_eth_dump_dpmac_stats(struct udevice *dev, u64 *data)
Ioana Ciornei872004f2020-03-18 16:47:37 +0200119{
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300120 int i;
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530121
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300122 printf("DPMAC counters:\n");
123 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++)
124 printf(" %s: %llu\n", ldpaa_eth_dpmac_stat_strings[i], data[i]);
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530125}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530126#endif
127
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700128static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
129 const struct dpaa_fd *fd)
130{
131 u64 fd_addr;
132 uint16_t fd_offset;
133 uint32_t fd_length;
134 struct ldpaa_fas *fas;
135 uint32_t status, err;
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530136 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
137 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700138 struct qbman_release_desc releasedesc;
139 struct qbman_swp *swp = dflt_dpio->sw_portal;
140
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700141 fd_addr = ldpaa_fd_get_addr(fd);
142 fd_offset = ldpaa_fd_get_offset(fd);
143 fd_length = ldpaa_fd_get_len(fd);
144
145 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
146
147 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
148 /* Read the frame annotation status word and check for errors */
149 fas = (struct ldpaa_fas *)
150 ((uint8_t *)(fd_addr) +
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530151 dflt_dpni->buf_layout.private_data_size);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700152 status = le32_to_cpu(fas->status);
153 if (status & LDPAA_ETH_RX_ERR_MASK) {
154 printf("Rx frame error(s): 0x%08x\n",
155 status & LDPAA_ETH_RX_ERR_MASK);
156 goto error;
157 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
158 printf("Unsupported feature in bitmask: 0x%08x\n",
159 status & LDPAA_ETH_RX_UNSUPP_MASK);
160 goto error;
161 }
162 }
163
164 debug("Rx frame: To Upper layer\n");
165 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
166 fd_length);
167
168error:
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700169 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700170 qbman_release_desc_clear(&releasedesc);
171 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530172 time_start = get_timer(0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700173 do {
174 /* Release buffer into the QBMAN */
175 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530176 } while (get_timer(time_start) < timeo && err == -EBUSY);
177
178 if (err == -EBUSY)
179 printf("Rx frame: QBMAN buffer release fails\n");
180
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700181 return;
182}
183
Ioana Ciornei872004f2020-03-18 16:47:37 +0200184static int ldpaa_eth_pull_dequeue_rx(struct udevice *dev,
185 int flags, uchar **packetp)
186{
187 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700188 const struct ldpaa_dq *dq;
189 const struct dpaa_fd *fd;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530190 int i = 5, err = 0, status;
191 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
192 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700193 static struct qbman_pull_desc pulldesc;
194 struct qbman_swp *swp = dflt_dpio->sw_portal;
195
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700196 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700197 qbman_pull_desc_clear(&pulldesc);
198 qbman_pull_desc_set_numframes(&pulldesc, 1);
199 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
200
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700201 err = qbman_swp_pull(swp, &pulldesc);
202 if (err < 0) {
203 printf("Dequeue frames error:0x%08x\n", err);
204 continue;
205 }
206
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530207 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700208
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530209 do {
210 dq = qbman_swp_dqrr_next(swp);
211 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700212
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700213 if (dq) {
214 /* Check for valid frame. If not sent a consume
215 * confirmation to QBMAN otherwise give it to NADK
216 * application and then send consume confirmation to
217 * QBMAN.
218 */
219 status = (uint8_t)ldpaa_dq_flags(dq);
220 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
221 debug("Dequeue RX frames:");
222 debug("No frame delivered\n");
223
224 qbman_swp_dqrr_consume(swp, dq);
Prabhakar Kushwaha37ed1a62015-07-02 11:29:07 +0530225 continue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700226 }
227
228 fd = ldpaa_dq_fd(dq);
229
230 /* Obtain FD and process it */
231 ldpaa_eth_rx(priv, fd);
232 qbman_swp_dqrr_consume(swp, dq);
233 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530234 } else {
235 err = -ENODATA;
236 debug("No DQRR entries\n");
237 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700238 }
239 }
240
241 return err;
242}
243
Ioana Ciornei872004f2020-03-18 16:47:37 +0200244static int ldpaa_eth_tx(struct udevice *dev, void *buf, int len)
245{
246 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700247 struct dpaa_fd fd;
248 u64 buffer_start;
249 int data_offset, err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530250 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
251 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700252 struct qbman_swp *swp = dflt_dpio->sw_portal;
253 struct qbman_eq_desc ed;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530254 struct qbman_release_desc releasedesc;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700255
256 /* Setup the FD fields */
257 memset(&fd, 0, sizeof(fd));
258
259 data_offset = priv->tx_data_offset;
260
261 do {
262 err = qbman_swp_acquire(dflt_dpio->sw_portal,
263 dflt_dpbp->dpbp_attr.bpid,
264 &buffer_start, 1);
265 } while (err == -EBUSY);
266
Ashish Kumar34f080c2017-10-26 16:03:22 +0530267 if (err <= 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700268 printf("qbman_swp_acquire() failed\n");
269 return -ENOMEM;
270 }
271
272 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
273
274 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
275
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700276 flush_dcache_range(buffer_start, buffer_start +
277 LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700278
279 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
280 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
281 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
282 ldpaa_fd_set_len(&fd, len);
283
284 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
285 LDPAA_FD_CTRL_PTV1;
286
287 qbman_eq_desc_clear(&ed);
288 qbman_eq_desc_set_no_orp(&ed, 0);
289 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530290
291 time_start = get_timer(0);
292
293 while (get_timer(time_start) < timeo) {
294 err = qbman_swp_enqueue(swp, &ed,
295 (const struct qbman_fd *)(&fd));
296 if (err != -EBUSY)
297 break;
298 }
299
300 if (err < 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700301 printf("error enqueueing Tx frame\n");
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530302 goto error;
303 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700304
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700305 return err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530306
307error:
308 qbman_release_desc_clear(&releasedesc);
309 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
310 time_start = get_timer(0);
311 do {
312 /* Release buffer into the QBMAN */
313 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
314 } while (get_timer(time_start) < timeo && err == -EBUSY);
315
316 if (err == -EBUSY)
317 printf("TX data: QBMAN buffer release fails\n");
318
319 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700320}
321
Pankaj Bansale031d262018-10-10 14:08:32 +0530322static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
323 struct dpmac_link_state *state)
324{
Pankaj Bansale031d262018-10-10 14:08:32 +0530325 phy_interface_t enet_if;
Tom Rini13da6252018-10-11 20:07:48 -0400326 struct phy_device *phydev = NULL;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200327 int err;
Pankaj Bansale031d262018-10-10 14:08:32 +0530328
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530329 /* let's start off with maximum capabilities */
Pankaj Bansale031d262018-10-10 14:08:32 +0530330 enet_if = wriop_get_enet_if(priv->dpmac_id);
331 switch (enet_if) {
332 case PHY_INTERFACE_MODE_XGMII:
333 state->rate = SPEED_10000;
334 break;
335 default:
336 state->rate = SPEED_1000;
337 break;
338 }
Pankaj Bansale031d262018-10-10 14:08:32 +0530339
Ioana Ciornei872004f2020-03-18 16:47:37 +0200340 state->up = 1;
Pankaj Bansale031d262018-10-10 14:08:32 +0530341 state->options |= DPMAC_LINK_OPT_AUTONEG;
Tom Rinie83c2012022-11-27 10:25:14 -0500342 phydev = priv->phy;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530343
Ioana Ciornei872004f2020-03-18 16:47:37 +0200344 if (phydev) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530345 err = phy_startup(phydev);
346 if (err) {
347 printf("%s: Could not initialize\n", phydev->dev->name);
348 state->up = 0;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200349 } else if (phydev->link) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530350 state->rate = min(state->rate, (uint32_t)phydev->speed);
351 if (!phydev->duplex)
352 state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
353 if (!phydev->autoneg)
354 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
355 } else {
356 state->up = 0;
357 }
358 }
Ioana Ciornei872004f2020-03-18 16:47:37 +0200359
360 if (!phydev)
Pankaj Bansale031d262018-10-10 14:08:32 +0530361 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
362
363 if (!state->up) {
364 state->rate = 0;
365 state->options = 0;
366 return -ENOLINK;
367 }
368
369 return 0;
370}
371
Ioana Ciornei872004f2020-03-18 16:47:37 +0200372static int ldpaa_eth_open(struct udevice *dev)
373{
Simon Glassfa20e932020-12-03 16:55:20 -0700374 struct eth_pdata *plat = dev_get_plat(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200375 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530376 struct dpmac_link_state dpmac_link_state = { 0 };
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530377#ifdef DEBUG
378 struct dpni_link_state link_state;
379#endif
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530380 int err = 0;
Ioana Ciorneibe117372023-05-31 19:04:33 +0300381 struct dpni_queue d_queue_cfg = { 0 };
382 struct dpni_queue_id d_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700383
Ioana Ciornei872004f2020-03-18 16:47:37 +0200384 if (eth_is_active(dev))
385 return 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700386
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530387 if (get_mc_boot_status() != 0) {
388 printf("ERROR (MC is not booted)\n");
389 return -ENODEV;
390 }
391
392 if (get_dpl_apply_status() == 0) {
393 printf("ERROR (DPL is deployed. No device available)\n");
394 return -ENODEV;
395 }
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530396
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530397 /* DPMAC initialization */
398 err = ldpaa_dpmac_setup(priv);
399 if (err < 0)
400 goto err_dpmac_setup;
401
Pankaj Bansale031d262018-10-10 14:08:32 +0530402 err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
403 if (err < 0)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530404 goto err_dpmac_bind;
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530405
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530406 /* DPMAC binding DPNI */
407 err = ldpaa_dpmac_bind(priv);
408 if (err)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530409 goto err_dpmac_bind;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530410
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700411 /* DPNI initialization */
412 err = ldpaa_dpni_setup(priv);
413 if (err < 0)
414 goto err_dpni_setup;
415
416 err = ldpaa_dpbp_setup();
417 if (err < 0)
418 goto err_dpbp_setup;
419
420 /* DPNI binding DPBP */
421 err = ldpaa_dpni_bind(priv);
422 if (err)
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530423 goto err_dpni_bind;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700424
Ioana Ciornei872004f2020-03-18 16:47:37 +0200425 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300426 dflt_dpni->dpni_handle, plat->enetaddr, 0, 0, 0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700427 if (err) {
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530428 printf("dpni_add_mac_addr() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700429 return err;
430 }
431
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530432 err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700433 if (err < 0) {
434 printf("dpni_enable() failed\n");
435 return err;
436 }
437
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530438 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
439 priv->dpmac_handle, &dpmac_link_state);
440 if (err < 0) {
441 printf("dpmac_set_link_state() failed\n");
442 return err;
443 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530444
445#ifdef DEBUG
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530446 printf("DPMAC link status: %d - ", dpmac_link_state.up);
447 dpmac_link_state.up == 0 ? printf("down\n") :
448 dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n");
449
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530450 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
451 dflt_dpni->dpni_handle, &link_state);
452 if (err < 0) {
453 printf("dpni_get_link_state() failed\n");
454 return err;
455 }
456
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530457 printf("DPNI link status: %d - ", link_state.up);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530458 link_state.up == 0 ? printf("down\n") :
459 link_state.up == 1 ? printf("up\n") : printf("error state\n");
460#endif
461
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530462 memset(&d_queue, 0, sizeof(struct dpni_queue));
463 err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
464 dflt_dpni->dpni_handle, DPNI_QUEUE_RX,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300465 0, 0, &d_queue_cfg, &d_queue);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700466 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530467 printf("dpni_get_queue failed\n");
468 goto err_get_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700469 }
470
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530471 priv->rx_dflt_fqid = d_queue.fqid;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700472
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530473 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300474 DPNI_QUEUE_TX, &priv->tx_qdid);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700475 if (err) {
476 printf("dpni_get_qdid() failed\n");
477 goto err_qdid;
478 }
479
Pankaj Bansale031d262018-10-10 14:08:32 +0530480 return dpmac_link_state.up;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700481
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700482err_qdid:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530483err_get_queue:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530484 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
485err_dpni_bind:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700486 ldpaa_dpbp_free();
487err_dpbp_setup:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530488 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700489err_dpni_setup:
Pankaj Bansald24b1282018-10-10 14:08:29 +0530490err_dpmac_bind:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530491 dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
492 dpmac_destroy(dflt_mc_io,
493 dflt_dprc_handle,
494 MC_CMD_NO_FLAGS, priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530495err_dpmac_setup:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700496 return err;
497}
498
Ioana Ciornei872004f2020-03-18 16:47:37 +0200499static void ldpaa_eth_stop(struct udevice *dev)
500{
501 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200502 struct phy_device *phydev = NULL;
503 int err = 0;
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300504 u64 *data;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700505
Ioana Ciornei872004f2020-03-18 16:47:37 +0200506 if (!eth_is_active(dev))
507 return;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530508
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300509 data = kzalloc(sizeof(u64) * LDPAA_ETH_DPNI_NUM_STATS, GFP_KERNEL);
510 if (data) {
511 ldpaa_eth_collect_dpni_stats(dev, data);
512 ldpaa_eth_add_dpni_stats(dev, data);
513#ifdef DEBUG
514 ldpaa_eth_dump_dpni_stats(dev, data);
515#endif
516 }
517 kfree(data);
518
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300519 data = kzalloc(sizeof(u64) * LDPAA_ETH_DPMAC_NUM_STATS, GFP_KERNEL);
520 if (data) {
521 ldpaa_eth_collect_dpmac_stats(dev, data);
522 ldpaa_eth_add_dpmac_stats(dev, data);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530523#ifdef DEBUG
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300524 ldpaa_eth_dump_dpmac_stats(dev, data);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200525#endif
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300526 }
527 kfree(data);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530528
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530529 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
530 dflt_dprc_handle, &dpmac_endpoint);
531 if (err < 0)
532 printf("dprc_disconnect() failed dpmac_endpoint\n");
533
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530534 err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
535 if (err < 0)
536 printf("dpmac_close() failed\n");
537
538 err = dpmac_destroy(dflt_mc_io,
539 dflt_dprc_handle,
540 MC_CMD_NO_FLAGS,
541 priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530542 if (err < 0)
543 printf("dpmac_destroy() failed\n");
544
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700545 /* Stop Tx and Rx traffic */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530546 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700547 if (err < 0)
548 printf("dpni_disable() failed\n");
549
Tom Rinie83c2012022-11-27 10:25:14 -0500550 phydev = priv->phy;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200551 if (phydev)
552 phy_shutdown(phydev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700553
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530554 /* Free DPBP handle and reset. */
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700555 ldpaa_dpbp_free();
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530556
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530557 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530558 if (err < 0)
559 printf("dpni_reset() failed\n");
560
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530561 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530562 if (err < 0)
563 printf("dpni_close() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700564}
565
566static void ldpaa_dpbp_drain_cnt(int count)
567{
568 uint64_t buf_array[7];
569 void *addr;
570 int ret, i;
571
572 BUG_ON(count > 7);
573
574 do {
575 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
576 dflt_dpbp->dpbp_attr.bpid,
577 buf_array, count);
578 if (ret < 0) {
579 printf("qbman_swp_acquire() failed\n");
580 return;
581 }
582 for (i = 0; i < ret; i++) {
583 addr = (void *)buf_array[i];
584 debug("Free: buffer addr =0x%p\n", addr);
585 free(addr);
586 }
587 } while (ret);
588}
589
590static void ldpaa_dpbp_drain(void)
591{
592 int i;
593 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
594 ldpaa_dpbp_drain_cnt(7);
595}
596
597static int ldpaa_bp_add_7(uint16_t bpid)
598{
599 uint64_t buf_array[7];
600 u8 *addr;
601 int i;
602 struct qbman_release_desc rd;
603
604 for (i = 0; i < 7; i++) {
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530605 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700606 if (!addr) {
607 printf("addr allocation failed\n");
608 goto err_alloc;
609 }
610 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700611 flush_dcache_range((u64)addr,
612 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700613
614 buf_array[i] = (uint64_t)addr;
615 debug("Release: buffer addr =0x%p\n", addr);
616 }
617
618release_bufs:
619 /* In case the portal is busy, retry until successful.
620 * This function is guaranteed to succeed in a reasonable amount
621 * of time.
622 */
623
624 do {
625 mdelay(1);
626 qbman_release_desc_clear(&rd);
627 qbman_release_desc_set_bpid(&rd, bpid);
628 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
629
630 return i;
631
632err_alloc:
633 if (i)
634 goto release_bufs;
635
636 return 0;
637}
638
639static int ldpaa_dpbp_seed(uint16_t bpid)
640{
641 int i;
642 int count;
643
644 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
645 count = ldpaa_bp_add_7(bpid);
646 if (count < 7)
647 printf("Buffer Seed= %d\n", count);
648 }
649
650 return 0;
651}
652
653static int ldpaa_dpbp_setup(void)
654{
655 int err;
656
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530657 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700658 &dflt_dpbp->dpbp_handle);
659 if (err) {
660 printf("dpbp_open() failed\n");
661 goto err_open;
662 }
663
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530664 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700665 if (err) {
666 printf("dpbp_enable() failed\n");
667 goto err_enable;
668 }
669
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530670 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
671 dflt_dpbp->dpbp_handle,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700672 &dflt_dpbp->dpbp_attr);
673 if (err) {
674 printf("dpbp_get_attributes() failed\n");
675 goto err_get_attr;
676 }
677
678 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530679
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700680 if (err) {
681 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
682 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
683 goto err_seed;
684 }
685
686 return 0;
687
688err_seed:
689err_get_attr:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530690 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700691err_enable:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530692 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700693err_open:
694 return err;
695}
696
697static void ldpaa_dpbp_free(void)
698{
699 ldpaa_dpbp_drain();
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530700 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
701 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
702 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700703}
704
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530705static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
706 struct ldpaa_eth_priv *priv)
707{
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530708 int error;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530709 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530710
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530711 error = dpmac_get_api_version(dflt_mc_io, 0,
712 &major_ver,
713 &minor_ver);
714 if ((major_ver < DPMAC_VER_MAJOR) ||
715 (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) {
716 printf("DPMAC version mismatch found %u.%u,",
717 major_ver, minor_ver);
718 printf("supported version is %u.%u\n",
719 DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
720 return error;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530721 }
722
723 return error;
724}
725
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530726static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
727{
728 int err = 0;
729 struct dpmac_cfg dpmac_cfg;
730
731 dpmac_cfg.mac_id = priv->dpmac_id;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530732
733 err = dpmac_create(dflt_mc_io,
734 dflt_dprc_handle,
735 MC_CMD_NO_FLAGS, &dpmac_cfg,
736 &priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530737 if (err)
738 printf("dpmac_create() failed\n");
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530739
740 err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530741 if (err < 0) {
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530742 printf("ldpaa_dpmac_version_check() failed: %d\n", err);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530743 goto err_version_check;
744 }
745
746 err = dpmac_open(dflt_mc_io,
747 MC_CMD_NO_FLAGS,
748 priv->dpmac_id,
749 &priv->dpmac_handle);
750 if (err < 0) {
751 printf("dpmac_open() failed: %d\n", err);
752 goto err_open;
753 }
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530754
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530755 return err;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530756
757err_open:
758err_version_check:
759 dpmac_destroy(dflt_mc_io,
760 dflt_dprc_handle,
761 MC_CMD_NO_FLAGS, priv->dpmac_id);
762
763 return err;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530764}
765
766static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
767{
768 int err = 0;
769 struct dprc_connection_cfg dprc_connection_cfg = {
770 /* If both rates are zero the connection */
771 /* will be configured in "best effort" mode. */
772 .committed_rate = 0,
773 .max_rate = 0
774 };
775
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530776#ifdef DEBUG
777 struct dprc_endpoint dbg_endpoint;
778 int state = 0;
779#endif
780
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530781 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000782 strcpy(dpmac_endpoint.type, "dpmac");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530783 dpmac_endpoint.id = priv->dpmac_id;
784
785 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000786 strcpy(dpni_endpoint.type, "dpni");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530787 dpni_endpoint.id = dflt_dpni->dpni_id;
788
789 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
790 dflt_dprc_handle,
791 &dpmac_endpoint,
792 &dpni_endpoint,
793 &dprc_connection_cfg);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530794 if (err)
795 printf("dprc_connect() failed\n");
796
797#ifdef DEBUG
798 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
799 dflt_dprc_handle, &dpni_endpoint,
800 &dbg_endpoint, &state);
801 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
802 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
803 printf("%s, DPMAC State= %d\n", __func__, state);
804
805 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
806 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
807 dflt_dprc_handle, &dpmac_endpoint,
808 &dbg_endpoint, &state);
809 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
810 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
811 printf("%s, DPNI State= %d\n", __func__, state);
812#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530813 return err;
814}
815
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700816static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
817{
818 int err;
819
820 /* and get a handle for the DPNI this interface is associate with */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530821 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
822 &dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700823 if (err) {
824 printf("dpni_open() failed\n");
825 goto err_open;
826 }
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530827 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530828 dflt_dpni->dpni_handle,
829 &dflt_dpni->dpni_attrs);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700830 if (err) {
831 printf("dpni_get_attributes() failed (err=%d)\n", err);
832 goto err_get_attr;
833 }
834
835 /* Configure our buffers' layout */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530836 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700837 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530838 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
839 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530840 dflt_dpni->buf_layout.pass_parser_result = true;
841 dflt_dpni->buf_layout.pass_frame_status = true;
842 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530843 /* HW erratum mandates data alignment in multiples of 256 */
844 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530845
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700846 /* ...rx, ... */
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530847 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
848 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300849 DPNI_QUEUE_RX, &dflt_dpni->buf_layout);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700850 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530851 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700852 goto err_buf_layout;
853 }
854
855 /* ... tx, ... */
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530856 /* remove Rx-only options */
857 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
858 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530859 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
860 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300861 DPNI_QUEUE_TX, &dflt_dpni->buf_layout);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700862 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530863 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700864 goto err_buf_layout;
865 }
866
867 /* ... tx-confirm. */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530868 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530869 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
870 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300871 DPNI_QUEUE_TX_CONFIRM, &dflt_dpni->buf_layout);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700872 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530873 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700874 goto err_buf_layout;
875 }
876
877 /* Now that we've set our tx buffer layout, retrieve the minimum
878 * required tx data offset.
879 */
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530880 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530881 dflt_dpni->dpni_handle,
882 &priv->tx_data_offset);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700883 if (err) {
884 printf("dpni_get_tx_data_offset() failed\n");
885 goto err_data_offset;
886 }
887
888 /* Warn in case TX data offset is not multiple of 64 bytes. */
889 WARN_ON(priv->tx_data_offset % 64);
890
891 /* Accomodate SWA space. */
892 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
893 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
894
895 return 0;
896
897err_data_offset:
898err_buf_layout:
899err_get_attr:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530900 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700901err_open:
902 return err;
903}
904
905static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
906{
907 struct dpni_pools_cfg pools_params;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530908 struct dpni_queue tx_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700909 int err = 0;
910
Prabhakar Kushwahaa7992322016-03-28 14:11:05 +0530911 memset(&pools_params, 0, sizeof(pools_params));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700912 pools_params.num_dpbp = 1;
913 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
914 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530915 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
916 dflt_dpni->dpni_handle, &pools_params);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700917 if (err) {
918 printf("dpni_set_pools() failed\n");
919 return err;
920 }
921
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530922 memset(&tx_queue, 0, sizeof(struct dpni_queue));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700923
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530924 err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
925 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300926 DPNI_QUEUE_TX, 0, 0, 0, &tx_queue);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530927
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700928 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530929 printf("dpni_set_queue() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700930 return err;
931 }
932
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530933 err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS,
934 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300935 0, DPNI_CONF_DISABLE);
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530936 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530937 printf("dpni_set_tx_confirmation_mode() failed\n");
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530938 return err;
939 }
940
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700941 return 0;
942}
943
Ioana Ciornei872004f2020-03-18 16:47:37 +0200944static int ldpaa_eth_probe(struct udevice *dev)
945{
946 struct ofnode_phandle_args phandle;
947
948 /* Nothing to do if there is no "phy-handle" in the DTS node */
949 if (dev_read_phandle_with_args(dev, "phy-handle", NULL,
950 0, 0, &phandle)) {
951 return 0;
952 }
953
954 init_phy(dev);
955
956 return 0;
957}
958
Ioana Ciornei5d1e9222023-02-09 18:07:03 +0200959uint32_t ldpaa_eth_get_dpmac_id(struct udevice *dev)
Ioana Ciornei872004f2020-03-18 16:47:37 +0200960{
961 int port_node = dev_of_offset(dev);
962
963 return fdtdec_get_uint(gd->fdt_blob, port_node, "reg", -1);
964}
965
Ioana Ciornei872004f2020-03-18 16:47:37 +0200966static int ldpaa_eth_bind(struct udevice *dev)
967{
Ioana Ciornei872004f2020-03-18 16:47:37 +0200968 uint32_t dpmac_id;
969 char eth_name[16];
970 int phy_mode = -1;
971
Marek Behúnbc194772022-04-07 00:33:01 +0200972 phy_mode = dev_read_phy_mode(dev);
Marek Behún48631e42022-04-07 00:33:03 +0200973 if (phy_mode == PHY_INTERFACE_MODE_NA) {
Ioana Ciornei872004f2020-03-18 16:47:37 +0200974 dev_err(dev, "incorrect phy mode\n");
975 return -EINVAL;
976 }
977
978 dpmac_id = ldpaa_eth_get_dpmac_id(dev);
979 if (dpmac_id == -1) {
980 dev_err(dev, "missing reg field from the dpmac node\n");
981 return -EINVAL;
982 }
983
Marek Behúnbc194772022-04-07 00:33:01 +0200984 sprintf(eth_name, "DPMAC%d@%s", dpmac_id,
985 phy_string_for_interface(phy_mode));
Ioana Ciornei872004f2020-03-18 16:47:37 +0200986 device_set_name(dev, eth_name);
987
988 return 0;
989}
990
Simon Glassaad29ae2020-12-03 16:55:21 -0700991static int ldpaa_eth_of_to_plat(struct udevice *dev)
Ioana Ciornei872004f2020-03-18 16:47:37 +0200992{
993 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200994
995 priv->dpmac_id = ldpaa_eth_get_dpmac_id(dev);
Marek Behúnbc194772022-04-07 00:33:01 +0200996 priv->phy_mode = dev_read_phy_mode(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200997
998 return 0;
999}
1000
Ioana Ciornei1fe5e9f2023-05-23 16:47:48 +03001001static int ldpaa_eth_get_sset_count(struct udevice *dev)
1002{
1003 return LDPAA_ETH_DPNI_NUM_STATS + LDPAA_ETH_DPMAC_NUM_STATS;
1004}
1005
1006static void ldpaa_eth_get_strings(struct udevice *dev, u8 *data)
1007{
1008 u8 *p = data;
1009 int i;
1010
1011 for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++) {
1012 strlcpy(p, ldpaa_eth_dpni_stat_strings[i], ETH_GSTRING_LEN);
1013 p += ETH_GSTRING_LEN;
1014 }
1015
1016 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++) {
1017 strlcpy(p, ldpaa_eth_dpmac_stat_strings[i], ETH_GSTRING_LEN);
1018 p += ETH_GSTRING_LEN;
1019 }
1020}
1021
1022static void ldpaa_eth_get_stats(struct udevice *dev, u64 *data)
1023{
1024 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
1025 int i, j = 0;
1026
1027 for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
1028 *(data + j++) = priv->dpni_stats[i];
1029
1030 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++)
1031 *(data + j++) = priv->dpmac_stats[i];
1032}
1033
Ioana Ciornei872004f2020-03-18 16:47:37 +02001034static const struct eth_ops ldpaa_eth_ops = {
Ioana Ciornei1fe5e9f2023-05-23 16:47:48 +03001035 .start = ldpaa_eth_open,
1036 .send = ldpaa_eth_tx,
1037 .recv = ldpaa_eth_pull_dequeue_rx,
1038 .stop = ldpaa_eth_stop,
1039 .get_sset_count = ldpaa_eth_get_sset_count,
1040 .get_strings = ldpaa_eth_get_strings,
1041 .get_stats = ldpaa_eth_get_stats,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001042};
1043
1044static const struct udevice_id ldpaa_eth_of_ids[] = {
1045 { .compatible = "fsl,qoriq-mc-dpmac" },
1046};
1047
1048U_BOOT_DRIVER(ldpaa_eth) = {
Ioana Ciornei5d1e9222023-02-09 18:07:03 +02001049 .name = LDPAA_ETH_DRIVER_NAME,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001050 .id = UCLASS_ETH,
1051 .of_match = ldpaa_eth_of_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001052 .of_to_plat = ldpaa_eth_of_to_plat,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001053 .bind = ldpaa_eth_bind,
1054 .probe = ldpaa_eth_probe,
1055 .ops = &ldpaa_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001056 .priv_auto = sizeof(struct ldpaa_eth_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -07001057 .plat_auto = sizeof(struct eth_pdata),
Ioana Ciornei872004f2020-03-18 16:47:37 +02001058};