blob: b72198ca53077be81b6beb53e7ee321e70c91493 [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
Simon Glass63334482019-11-14 12:57:39 -07007#include <cpu_func.h>
Sean Andersoneba99512020-10-04 21:39:46 -04008#include <dm/device_compat.h>
9#include <fsl-mc/fsl_dpmac.h>
10#include <fsl-mc/ldpaa_wriop.h>
11#include <hwconfig.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070013#include <malloc.h>
Sean Andersoneba99512020-10-04 21:39:46 -040014#include <miiphy.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070015#include <net.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070016#include <phy.h>
Sean Andersoneba99512020-10-04 21:39:46 -040017#include <asm/io.h>
18#include <asm/types.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060019#include <linux/bug.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070020#include <linux/compat.h>
Simon Glassdbd79542020-05-10 11:40:11 -060021#include <linux/delay.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060022#include <asm/global_data.h>
Ioana Ciornei5d1e9222023-02-09 18:07:03 +020023#include <net/ldpaa_eth.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070024#include "ldpaa_eth.h"
25
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053026#ifdef CONFIG_PHYLIB
Ioana Ciornei872004f2020-03-18 16:47:37 +020027static void init_phy(struct udevice *dev)
28{
29 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
30
31 priv->phy = dm_eth_phy_connect(dev);
32
33 if (!priv->phy)
34 return;
35
36 phy_config(priv->phy);
37}
Ioana Ciornei872004f2020-03-18 16:47:37 +020038#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070039
Ioana Ciorneia121fe42023-05-23 16:47:45 +030040static void ldpaa_eth_collect_dpni_stats(struct udevice *dev, u64 *data)
41{
42 union dpni_statistics dpni_stats;
43 int dpni_stats_page_size[DPNI_STATISTICS_CNT] = {
44 sizeof(dpni_stats.page_0),
45 sizeof(dpni_stats.page_1),
46 sizeof(dpni_stats.page_2),
47 sizeof(dpni_stats.page_3),
48 sizeof(dpni_stats.page_4),
49 sizeof(dpni_stats.page_5),
50 sizeof(dpni_stats.page_6),
51 };
52 int j, k, num_cnt, err, i = 0;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053053
Ioana Ciorneia121fe42023-05-23 16:47:45 +030054 for (j = 0; j <= 6; j++) {
55 /* We're not interested in pages 4 & 5 for now */
56 if (j == 4 || j == 5)
57 continue;
58 err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS,
59 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +030060 j, 0, &dpni_stats);
Ioana Ciorneia121fe42023-05-23 16:47:45 +030061 if (err) {
62 memset(&dpni_stats, 0, sizeof(dpni_stats));
63 printf("dpni_get_stats(%d) failed\n", j);
64 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053065
Ioana Ciorneia121fe42023-05-23 16:47:45 +030066 num_cnt = dpni_stats_page_size[j] / sizeof(u64);
67 for (k = 0; k < num_cnt; k++)
68 *(data + i++) = dpni_stats.raw.counter[k];
69 }
70}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053071
Ioana Ciorneia121fe42023-05-23 16:47:45 +030072static void ldpaa_eth_add_dpni_stats(struct udevice *dev, u64 *data)
Yogesh Gaur318c32f2017-11-15 11:59:31 +053073{
Ioana Ciorneia121fe42023-05-23 16:47:45 +030074 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Yogesh Gaur318c32f2017-11-15 11:59:31 +053075 int i;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053076
Ioana Ciorneia121fe42023-05-23 16:47:45 +030077 for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
78 priv->dpni_stats[i] += data[i];
Yogesh Gaur318c32f2017-11-15 11:59:31 +053079}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053080
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +030081static void ldpaa_eth_collect_dpmac_stats(struct udevice *dev, u64 *data)
82{
83 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
84 int err, i;
85 u64 value;
Ioana Ciorneia121fe42023-05-23 16:47:45 +030086
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +030087 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++) {
88 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
89 priv->dpmac_handle, i,
90 &value);
91 if (err)
92 printf("dpmac_get_counter(%d) failed\n", i);
93
94 *(data + i) = value;
95 }
96}
97
98static void ldpaa_eth_add_dpmac_stats(struct udevice *dev, u64 *data)
99{
100 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
101 int i;
102
103 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++)
104 priv->dpmac_stats[i] += data[i];
105}
106
107#ifdef DEBUG
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300108static void ldpaa_eth_dump_dpni_stats(struct udevice *dev, u64 *data)
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530109{
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300110 int i;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530111
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300112 printf("DPNI counters:\n");
113 for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
114 printf(" %s: %llu\n", ldpaa_eth_dpni_stat_strings[i], data[i]);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530115}
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530116
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300117static void ldpaa_eth_dump_dpmac_stats(struct udevice *dev, u64 *data)
Ioana Ciornei872004f2020-03-18 16:47:37 +0200118{
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300119 int i;
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530120
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300121 printf("DPMAC counters:\n");
122 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++)
123 printf(" %s: %llu\n", ldpaa_eth_dpmac_stat_strings[i], data[i]);
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530124}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530125#endif
126
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700127static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
128 const struct dpaa_fd *fd)
129{
130 u64 fd_addr;
131 uint16_t fd_offset;
132 uint32_t fd_length;
133 struct ldpaa_fas *fas;
134 uint32_t status, err;
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530135 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
136 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700137 struct qbman_release_desc releasedesc;
138 struct qbman_swp *swp = dflt_dpio->sw_portal;
139
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700140 fd_addr = ldpaa_fd_get_addr(fd);
141 fd_offset = ldpaa_fd_get_offset(fd);
142 fd_length = ldpaa_fd_get_len(fd);
143
144 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
145
146 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
147 /* Read the frame annotation status word and check for errors */
148 fas = (struct ldpaa_fas *)
149 ((uint8_t *)(fd_addr) +
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530150 dflt_dpni->buf_layout.private_data_size);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700151 status = le32_to_cpu(fas->status);
152 if (status & LDPAA_ETH_RX_ERR_MASK) {
153 printf("Rx frame error(s): 0x%08x\n",
154 status & LDPAA_ETH_RX_ERR_MASK);
155 goto error;
156 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
157 printf("Unsupported feature in bitmask: 0x%08x\n",
158 status & LDPAA_ETH_RX_UNSUPP_MASK);
159 goto error;
160 }
161 }
162
163 debug("Rx frame: To Upper layer\n");
164 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
165 fd_length);
166
167error:
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700168 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700169 qbman_release_desc_clear(&releasedesc);
170 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530171 time_start = get_timer(0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700172 do {
173 /* Release buffer into the QBMAN */
174 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530175 } while (get_timer(time_start) < timeo && err == -EBUSY);
176
177 if (err == -EBUSY)
178 printf("Rx frame: QBMAN buffer release fails\n");
179
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700180 return;
181}
182
Ioana Ciornei872004f2020-03-18 16:47:37 +0200183static int ldpaa_eth_pull_dequeue_rx(struct udevice *dev,
184 int flags, uchar **packetp)
185{
186 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700187 const struct ldpaa_dq *dq;
188 const struct dpaa_fd *fd;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530189 int i = 5, err = 0, status;
190 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
191 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700192 static struct qbman_pull_desc pulldesc;
193 struct qbman_swp *swp = dflt_dpio->sw_portal;
194
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700195 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700196 qbman_pull_desc_clear(&pulldesc);
197 qbman_pull_desc_set_numframes(&pulldesc, 1);
198 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
199
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700200 err = qbman_swp_pull(swp, &pulldesc);
201 if (err < 0) {
202 printf("Dequeue frames error:0x%08x\n", err);
203 continue;
204 }
205
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530206 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700207
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530208 do {
209 dq = qbman_swp_dqrr_next(swp);
210 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700211
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700212 if (dq) {
213 /* Check for valid frame. If not sent a consume
214 * confirmation to QBMAN otherwise give it to NADK
215 * application and then send consume confirmation to
216 * QBMAN.
217 */
218 status = (uint8_t)ldpaa_dq_flags(dq);
219 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
220 debug("Dequeue RX frames:");
221 debug("No frame delivered\n");
222
223 qbman_swp_dqrr_consume(swp, dq);
Prabhakar Kushwaha37ed1a62015-07-02 11:29:07 +0530224 continue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700225 }
226
227 fd = ldpaa_dq_fd(dq);
228
229 /* Obtain FD and process it */
230 ldpaa_eth_rx(priv, fd);
231 qbman_swp_dqrr_consume(swp, dq);
232 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530233 } else {
234 err = -ENODATA;
235 debug("No DQRR entries\n");
236 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700237 }
238 }
239
240 return err;
241}
242
Ioana Ciornei872004f2020-03-18 16:47:37 +0200243static int ldpaa_eth_tx(struct udevice *dev, void *buf, int len)
244{
245 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700246 struct dpaa_fd fd;
247 u64 buffer_start;
248 int data_offset, err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530249 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
250 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700251 struct qbman_swp *swp = dflt_dpio->sw_portal;
252 struct qbman_eq_desc ed;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530253 struct qbman_release_desc releasedesc;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700254
255 /* Setup the FD fields */
256 memset(&fd, 0, sizeof(fd));
257
258 data_offset = priv->tx_data_offset;
259
260 do {
261 err = qbman_swp_acquire(dflt_dpio->sw_portal,
262 dflt_dpbp->dpbp_attr.bpid,
263 &buffer_start, 1);
264 } while (err == -EBUSY);
265
Ashish Kumar34f080c2017-10-26 16:03:22 +0530266 if (err <= 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700267 printf("qbman_swp_acquire() failed\n");
268 return -ENOMEM;
269 }
270
271 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
272
273 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
274
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700275 flush_dcache_range(buffer_start, buffer_start +
276 LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700277
278 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
279 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
280 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
281 ldpaa_fd_set_len(&fd, len);
282
283 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
284 LDPAA_FD_CTRL_PTV1;
285
286 qbman_eq_desc_clear(&ed);
287 qbman_eq_desc_set_no_orp(&ed, 0);
288 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530289
290 time_start = get_timer(0);
291
292 while (get_timer(time_start) < timeo) {
293 err = qbman_swp_enqueue(swp, &ed,
294 (const struct qbman_fd *)(&fd));
295 if (err != -EBUSY)
296 break;
297 }
298
299 if (err < 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700300 printf("error enqueueing Tx frame\n");
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530301 goto error;
302 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700303
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700304 return err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530305
306error:
307 qbman_release_desc_clear(&releasedesc);
308 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
309 time_start = get_timer(0);
310 do {
311 /* Release buffer into the QBMAN */
312 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
313 } while (get_timer(time_start) < timeo && err == -EBUSY);
314
315 if (err == -EBUSY)
316 printf("TX data: QBMAN buffer release fails\n");
317
318 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700319}
320
Pankaj Bansale031d262018-10-10 14:08:32 +0530321static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
322 struct dpmac_link_state *state)
323{
Pankaj Bansale031d262018-10-10 14:08:32 +0530324 phy_interface_t enet_if;
Tom Rini13da6252018-10-11 20:07:48 -0400325 struct phy_device *phydev = NULL;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200326 int err;
Pankaj Bansale031d262018-10-10 14:08:32 +0530327
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530328 /* let's start off with maximum capabilities */
Pankaj Bansale031d262018-10-10 14:08:32 +0530329 enet_if = wriop_get_enet_if(priv->dpmac_id);
330 switch (enet_if) {
331 case PHY_INTERFACE_MODE_XGMII:
332 state->rate = SPEED_10000;
333 break;
334 default:
335 state->rate = SPEED_1000;
336 break;
337 }
Pankaj Bansale031d262018-10-10 14:08:32 +0530338
Ioana Ciornei872004f2020-03-18 16:47:37 +0200339 state->up = 1;
Pankaj Bansale031d262018-10-10 14:08:32 +0530340 state->options |= DPMAC_LINK_OPT_AUTONEG;
Tom Rinie83c2012022-11-27 10:25:14 -0500341 phydev = priv->phy;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530342
Ioana Ciornei872004f2020-03-18 16:47:37 +0200343 if (phydev) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530344 err = phy_startup(phydev);
345 if (err) {
346 printf("%s: Could not initialize\n", phydev->dev->name);
347 state->up = 0;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200348 } else if (phydev->link) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530349 state->rate = min(state->rate, (uint32_t)phydev->speed);
350 if (!phydev->duplex)
351 state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
352 if (!phydev->autoneg)
353 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
354 } else {
355 state->up = 0;
356 }
357 }
Ioana Ciornei872004f2020-03-18 16:47:37 +0200358
359 if (!phydev)
Pankaj Bansale031d262018-10-10 14:08:32 +0530360 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
361
362 if (!state->up) {
363 state->rate = 0;
364 state->options = 0;
365 return -ENOLINK;
366 }
367
368 return 0;
369}
370
Ioana Ciornei872004f2020-03-18 16:47:37 +0200371static int ldpaa_eth_open(struct udevice *dev)
372{
Simon Glassfa20e932020-12-03 16:55:20 -0700373 struct eth_pdata *plat = dev_get_plat(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200374 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530375 struct dpmac_link_state dpmac_link_state = { 0 };
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530376#ifdef DEBUG
377 struct dpni_link_state link_state;
378#endif
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530379 int err = 0;
Ioana Ciorneibe117372023-05-31 19:04:33 +0300380 struct dpni_queue d_queue_cfg = { 0 };
381 struct dpni_queue_id d_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700382
Ioana Ciornei872004f2020-03-18 16:47:37 +0200383 if (eth_is_active(dev))
384 return 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700385
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530386 if (get_mc_boot_status() != 0) {
387 printf("ERROR (MC is not booted)\n");
388 return -ENODEV;
389 }
390
391 if (get_dpl_apply_status() == 0) {
392 printf("ERROR (DPL is deployed. No device available)\n");
393 return -ENODEV;
394 }
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530395
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530396 /* DPMAC initialization */
397 err = ldpaa_dpmac_setup(priv);
398 if (err < 0)
399 goto err_dpmac_setup;
400
Pankaj Bansale031d262018-10-10 14:08:32 +0530401 err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
402 if (err < 0)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530403 goto err_dpmac_bind;
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530404
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530405 /* DPMAC binding DPNI */
406 err = ldpaa_dpmac_bind(priv);
407 if (err)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530408 goto err_dpmac_bind;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530409
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700410 /* DPNI initialization */
411 err = ldpaa_dpni_setup(priv);
412 if (err < 0)
413 goto err_dpni_setup;
414
415 err = ldpaa_dpbp_setup();
416 if (err < 0)
417 goto err_dpbp_setup;
418
419 /* DPNI binding DPBP */
420 err = ldpaa_dpni_bind(priv);
421 if (err)
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530422 goto err_dpni_bind;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700423
Ioana Ciornei872004f2020-03-18 16:47:37 +0200424 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300425 dflt_dpni->dpni_handle, plat->enetaddr, 0, 0, 0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700426 if (err) {
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530427 printf("dpni_add_mac_addr() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700428 return err;
429 }
430
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530431 err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700432 if (err < 0) {
433 printf("dpni_enable() failed\n");
434 return err;
435 }
436
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530437 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
438 priv->dpmac_handle, &dpmac_link_state);
439 if (err < 0) {
440 printf("dpmac_set_link_state() failed\n");
441 return err;
442 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530443
444#ifdef DEBUG
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530445 printf("DPMAC link status: %d - ", dpmac_link_state.up);
446 dpmac_link_state.up == 0 ? printf("down\n") :
447 dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n");
448
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530449 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
450 dflt_dpni->dpni_handle, &link_state);
451 if (err < 0) {
452 printf("dpni_get_link_state() failed\n");
453 return err;
454 }
455
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530456 printf("DPNI link status: %d - ", link_state.up);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530457 link_state.up == 0 ? printf("down\n") :
458 link_state.up == 1 ? printf("up\n") : printf("error state\n");
459#endif
460
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530461 memset(&d_queue, 0, sizeof(struct dpni_queue));
462 err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
463 dflt_dpni->dpni_handle, DPNI_QUEUE_RX,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300464 0, 0, &d_queue_cfg, &d_queue);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700465 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530466 printf("dpni_get_queue failed\n");
467 goto err_get_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700468 }
469
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530470 priv->rx_dflt_fqid = d_queue.fqid;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700471
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530472 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300473 DPNI_QUEUE_TX, &priv->tx_qdid);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700474 if (err) {
475 printf("dpni_get_qdid() failed\n");
476 goto err_qdid;
477 }
478
Pankaj Bansale031d262018-10-10 14:08:32 +0530479 return dpmac_link_state.up;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700480
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700481err_qdid:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530482err_get_queue:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530483 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
484err_dpni_bind:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700485 ldpaa_dpbp_free();
486err_dpbp_setup:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530487 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700488err_dpni_setup:
Pankaj Bansald24b1282018-10-10 14:08:29 +0530489err_dpmac_bind:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530490 dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
491 dpmac_destroy(dflt_mc_io,
492 dflt_dprc_handle,
493 MC_CMD_NO_FLAGS, priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530494err_dpmac_setup:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700495 return err;
496}
497
Ioana Ciornei872004f2020-03-18 16:47:37 +0200498static void ldpaa_eth_stop(struct udevice *dev)
499{
500 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200501 struct phy_device *phydev = NULL;
502 int err = 0;
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300503 u64 *data;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700504
Ioana Ciornei872004f2020-03-18 16:47:37 +0200505 if (!eth_is_active(dev))
506 return;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530507
Ioana Ciorneia121fe42023-05-23 16:47:45 +0300508 data = kzalloc(sizeof(u64) * LDPAA_ETH_DPNI_NUM_STATS, GFP_KERNEL);
509 if (data) {
510 ldpaa_eth_collect_dpni_stats(dev, data);
511 ldpaa_eth_add_dpni_stats(dev, data);
512#ifdef DEBUG
513 ldpaa_eth_dump_dpni_stats(dev, data);
514#endif
515 }
516 kfree(data);
517
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300518 data = kzalloc(sizeof(u64) * LDPAA_ETH_DPMAC_NUM_STATS, GFP_KERNEL);
519 if (data) {
520 ldpaa_eth_collect_dpmac_stats(dev, data);
521 ldpaa_eth_add_dpmac_stats(dev, data);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530522#ifdef DEBUG
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300523 ldpaa_eth_dump_dpmac_stats(dev, data);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200524#endif
Ioana Ciornei98fdaaa2023-05-23 16:47:46 +0300525 }
526 kfree(data);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530527
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530528 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
529 dflt_dprc_handle, &dpmac_endpoint);
530 if (err < 0)
531 printf("dprc_disconnect() failed dpmac_endpoint\n");
532
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530533 err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
534 if (err < 0)
535 printf("dpmac_close() failed\n");
536
537 err = dpmac_destroy(dflt_mc_io,
538 dflt_dprc_handle,
539 MC_CMD_NO_FLAGS,
540 priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530541 if (err < 0)
542 printf("dpmac_destroy() failed\n");
543
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700544 /* Stop Tx and Rx traffic */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530545 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700546 if (err < 0)
547 printf("dpni_disable() failed\n");
548
Tom Rinie83c2012022-11-27 10:25:14 -0500549 phydev = priv->phy;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200550 if (phydev)
551 phy_shutdown(phydev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700552
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530553 /* Free DPBP handle and reset. */
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700554 ldpaa_dpbp_free();
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530555
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530556 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530557 if (err < 0)
558 printf("dpni_reset() failed\n");
559
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530560 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530561 if (err < 0)
562 printf("dpni_close() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700563}
564
565static void ldpaa_dpbp_drain_cnt(int count)
566{
567 uint64_t buf_array[7];
568 void *addr;
569 int ret, i;
570
571 BUG_ON(count > 7);
572
573 do {
574 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
575 dflt_dpbp->dpbp_attr.bpid,
576 buf_array, count);
577 if (ret < 0) {
578 printf("qbman_swp_acquire() failed\n");
579 return;
580 }
581 for (i = 0; i < ret; i++) {
582 addr = (void *)buf_array[i];
583 debug("Free: buffer addr =0x%p\n", addr);
584 free(addr);
585 }
586 } while (ret);
587}
588
589static void ldpaa_dpbp_drain(void)
590{
591 int i;
592 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
593 ldpaa_dpbp_drain_cnt(7);
594}
595
596static int ldpaa_bp_add_7(uint16_t bpid)
597{
598 uint64_t buf_array[7];
599 u8 *addr;
600 int i;
601 struct qbman_release_desc rd;
602
603 for (i = 0; i < 7; i++) {
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530604 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700605 if (!addr) {
606 printf("addr allocation failed\n");
607 goto err_alloc;
608 }
609 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700610 flush_dcache_range((u64)addr,
611 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700612
613 buf_array[i] = (uint64_t)addr;
614 debug("Release: buffer addr =0x%p\n", addr);
615 }
616
617release_bufs:
618 /* In case the portal is busy, retry until successful.
619 * This function is guaranteed to succeed in a reasonable amount
620 * of time.
621 */
622
623 do {
624 mdelay(1);
625 qbman_release_desc_clear(&rd);
626 qbman_release_desc_set_bpid(&rd, bpid);
627 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
628
629 return i;
630
631err_alloc:
632 if (i)
633 goto release_bufs;
634
635 return 0;
636}
637
638static int ldpaa_dpbp_seed(uint16_t bpid)
639{
640 int i;
641 int count;
642
643 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
644 count = ldpaa_bp_add_7(bpid);
645 if (count < 7)
646 printf("Buffer Seed= %d\n", count);
647 }
648
649 return 0;
650}
651
652static int ldpaa_dpbp_setup(void)
653{
654 int err;
655
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530656 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700657 &dflt_dpbp->dpbp_handle);
658 if (err) {
659 printf("dpbp_open() failed\n");
660 goto err_open;
661 }
662
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530663 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700664 if (err) {
665 printf("dpbp_enable() failed\n");
666 goto err_enable;
667 }
668
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530669 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
670 dflt_dpbp->dpbp_handle,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700671 &dflt_dpbp->dpbp_attr);
672 if (err) {
673 printf("dpbp_get_attributes() failed\n");
674 goto err_get_attr;
675 }
676
677 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530678
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700679 if (err) {
680 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
681 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
682 goto err_seed;
683 }
684
685 return 0;
686
687err_seed:
688err_get_attr:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530689 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700690err_enable:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530691 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700692err_open:
693 return err;
694}
695
696static void ldpaa_dpbp_free(void)
697{
698 ldpaa_dpbp_drain();
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530699 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
700 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
701 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700702}
703
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530704static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
705 struct ldpaa_eth_priv *priv)
706{
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530707 int error;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530708 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530709
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530710 error = dpmac_get_api_version(dflt_mc_io, 0,
711 &major_ver,
712 &minor_ver);
713 if ((major_ver < DPMAC_VER_MAJOR) ||
714 (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) {
715 printf("DPMAC version mismatch found %u.%u,",
716 major_ver, minor_ver);
717 printf("supported version is %u.%u\n",
718 DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
719 return error;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530720 }
721
722 return error;
723}
724
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530725static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
726{
727 int err = 0;
728 struct dpmac_cfg dpmac_cfg;
729
730 dpmac_cfg.mac_id = priv->dpmac_id;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530731
732 err = dpmac_create(dflt_mc_io,
733 dflt_dprc_handle,
734 MC_CMD_NO_FLAGS, &dpmac_cfg,
735 &priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530736 if (err)
737 printf("dpmac_create() failed\n");
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530738
739 err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530740 if (err < 0) {
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530741 printf("ldpaa_dpmac_version_check() failed: %d\n", err);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530742 goto err_version_check;
743 }
744
745 err = dpmac_open(dflt_mc_io,
746 MC_CMD_NO_FLAGS,
747 priv->dpmac_id,
748 &priv->dpmac_handle);
749 if (err < 0) {
750 printf("dpmac_open() failed: %d\n", err);
751 goto err_open;
752 }
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530753
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530754 return err;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530755
756err_open:
757err_version_check:
758 dpmac_destroy(dflt_mc_io,
759 dflt_dprc_handle,
760 MC_CMD_NO_FLAGS, priv->dpmac_id);
761
762 return err;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530763}
764
765static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
766{
767 int err = 0;
768 struct dprc_connection_cfg dprc_connection_cfg = {
769 /* If both rates are zero the connection */
770 /* will be configured in "best effort" mode. */
771 .committed_rate = 0,
772 .max_rate = 0
773 };
774
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530775#ifdef DEBUG
776 struct dprc_endpoint dbg_endpoint;
777 int state = 0;
778#endif
779
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530780 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000781 strcpy(dpmac_endpoint.type, "dpmac");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530782 dpmac_endpoint.id = priv->dpmac_id;
783
784 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000785 strcpy(dpni_endpoint.type, "dpni");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530786 dpni_endpoint.id = dflt_dpni->dpni_id;
787
788 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
789 dflt_dprc_handle,
790 &dpmac_endpoint,
791 &dpni_endpoint,
792 &dprc_connection_cfg);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530793 if (err)
794 printf("dprc_connect() failed\n");
795
796#ifdef DEBUG
797 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
798 dflt_dprc_handle, &dpni_endpoint,
799 &dbg_endpoint, &state);
800 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
801 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
802 printf("%s, DPMAC State= %d\n", __func__, state);
803
804 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
805 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
806 dflt_dprc_handle, &dpmac_endpoint,
807 &dbg_endpoint, &state);
808 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
809 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
810 printf("%s, DPNI State= %d\n", __func__, state);
811#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530812 return err;
813}
814
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700815static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
816{
817 int err;
818
819 /* and get a handle for the DPNI this interface is associate with */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530820 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
821 &dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700822 if (err) {
823 printf("dpni_open() failed\n");
824 goto err_open;
825 }
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530826 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530827 dflt_dpni->dpni_handle,
828 &dflt_dpni->dpni_attrs);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700829 if (err) {
830 printf("dpni_get_attributes() failed (err=%d)\n", err);
831 goto err_get_attr;
832 }
833
834 /* Configure our buffers' layout */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530835 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700836 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530837 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
838 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530839 dflt_dpni->buf_layout.pass_parser_result = true;
840 dflt_dpni->buf_layout.pass_frame_status = true;
841 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530842 /* HW erratum mandates data alignment in multiples of 256 */
843 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530844
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700845 /* ...rx, ... */
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530846 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
847 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300848 DPNI_QUEUE_RX, &dflt_dpni->buf_layout);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700849 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530850 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700851 goto err_buf_layout;
852 }
853
854 /* ... tx, ... */
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530855 /* remove Rx-only options */
856 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
857 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530858 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
859 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300860 DPNI_QUEUE_TX, &dflt_dpni->buf_layout);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700861 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530862 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700863 goto err_buf_layout;
864 }
865
866 /* ... tx-confirm. */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530867 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530868 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
869 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300870 DPNI_QUEUE_TX_CONFIRM, &dflt_dpni->buf_layout);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700871 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530872 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700873 goto err_buf_layout;
874 }
875
876 /* Now that we've set our tx buffer layout, retrieve the minimum
877 * required tx data offset.
878 */
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530879 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530880 dflt_dpni->dpni_handle,
881 &priv->tx_data_offset);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700882 if (err) {
883 printf("dpni_get_tx_data_offset() failed\n");
884 goto err_data_offset;
885 }
886
887 /* Warn in case TX data offset is not multiple of 64 bytes. */
888 WARN_ON(priv->tx_data_offset % 64);
889
890 /* Accomodate SWA space. */
891 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
892 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
893
894 return 0;
895
896err_data_offset:
897err_buf_layout:
898err_get_attr:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530899 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700900err_open:
901 return err;
902}
903
904static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
905{
906 struct dpni_pools_cfg pools_params;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530907 struct dpni_queue tx_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700908 int err = 0;
909
Prabhakar Kushwahaa7992322016-03-28 14:11:05 +0530910 memset(&pools_params, 0, sizeof(pools_params));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700911 pools_params.num_dpbp = 1;
912 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
913 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530914 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
915 dflt_dpni->dpni_handle, &pools_params);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700916 if (err) {
917 printf("dpni_set_pools() failed\n");
918 return err;
919 }
920
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530921 memset(&tx_queue, 0, sizeof(struct dpni_queue));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700922
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530923 err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
924 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300925 DPNI_QUEUE_TX, 0, 0, 0, &tx_queue);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530926
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700927 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530928 printf("dpni_set_queue() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700929 return err;
930 }
931
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530932 err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS,
933 dflt_dpni->dpni_handle,
Ioana Ciorneibe117372023-05-31 19:04:33 +0300934 0, DPNI_CONF_DISABLE);
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530935 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530936 printf("dpni_set_tx_confirmation_mode() failed\n");
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +0530937 return err;
938 }
939
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700940 return 0;
941}
942
Ioana Ciornei872004f2020-03-18 16:47:37 +0200943static int ldpaa_eth_probe(struct udevice *dev)
944{
945 struct ofnode_phandle_args phandle;
946
947 /* Nothing to do if there is no "phy-handle" in the DTS node */
948 if (dev_read_phandle_with_args(dev, "phy-handle", NULL,
949 0, 0, &phandle)) {
950 return 0;
951 }
952
953 init_phy(dev);
954
955 return 0;
956}
957
Ioana Ciornei5d1e9222023-02-09 18:07:03 +0200958uint32_t ldpaa_eth_get_dpmac_id(struct udevice *dev)
Ioana Ciornei872004f2020-03-18 16:47:37 +0200959{
960 int port_node = dev_of_offset(dev);
961
962 return fdtdec_get_uint(gd->fdt_blob, port_node, "reg", -1);
963}
964
Ioana Ciornei872004f2020-03-18 16:47:37 +0200965static int ldpaa_eth_bind(struct udevice *dev)
966{
Ioana Ciornei872004f2020-03-18 16:47:37 +0200967 uint32_t dpmac_id;
968 char eth_name[16];
969 int phy_mode = -1;
970
Marek Behúnbc194772022-04-07 00:33:01 +0200971 phy_mode = dev_read_phy_mode(dev);
Marek Behún48631e42022-04-07 00:33:03 +0200972 if (phy_mode == PHY_INTERFACE_MODE_NA) {
Ioana Ciornei872004f2020-03-18 16:47:37 +0200973 dev_err(dev, "incorrect phy mode\n");
974 return -EINVAL;
975 }
976
977 dpmac_id = ldpaa_eth_get_dpmac_id(dev);
978 if (dpmac_id == -1) {
979 dev_err(dev, "missing reg field from the dpmac node\n");
980 return -EINVAL;
981 }
982
Marek Behúnbc194772022-04-07 00:33:01 +0200983 sprintf(eth_name, "DPMAC%d@%s", dpmac_id,
984 phy_string_for_interface(phy_mode));
Ioana Ciornei872004f2020-03-18 16:47:37 +0200985 device_set_name(dev, eth_name);
986
987 return 0;
988}
989
Simon Glassaad29ae2020-12-03 16:55:21 -0700990static int ldpaa_eth_of_to_plat(struct udevice *dev)
Ioana Ciornei872004f2020-03-18 16:47:37 +0200991{
992 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200993
994 priv->dpmac_id = ldpaa_eth_get_dpmac_id(dev);
Marek Behúnbc194772022-04-07 00:33:01 +0200995 priv->phy_mode = dev_read_phy_mode(dev);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200996
997 return 0;
998}
999
Ioana Ciornei1fe5e9f2023-05-23 16:47:48 +03001000static int ldpaa_eth_get_sset_count(struct udevice *dev)
1001{
1002 return LDPAA_ETH_DPNI_NUM_STATS + LDPAA_ETH_DPMAC_NUM_STATS;
1003}
1004
1005static void ldpaa_eth_get_strings(struct udevice *dev, u8 *data)
1006{
1007 u8 *p = data;
1008 int i;
1009
1010 for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++) {
1011 strlcpy(p, ldpaa_eth_dpni_stat_strings[i], ETH_GSTRING_LEN);
1012 p += ETH_GSTRING_LEN;
1013 }
1014
1015 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++) {
1016 strlcpy(p, ldpaa_eth_dpmac_stat_strings[i], ETH_GSTRING_LEN);
1017 p += ETH_GSTRING_LEN;
1018 }
1019}
1020
1021static void ldpaa_eth_get_stats(struct udevice *dev, u64 *data)
1022{
1023 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
1024 int i, j = 0;
1025
1026 for (i = 0; i < LDPAA_ETH_DPNI_NUM_STATS; i++)
1027 *(data + j++) = priv->dpni_stats[i];
1028
1029 for (i = 0; i < LDPAA_ETH_DPMAC_NUM_STATS; i++)
1030 *(data + j++) = priv->dpmac_stats[i];
1031}
1032
Ioana Ciornei872004f2020-03-18 16:47:37 +02001033static const struct eth_ops ldpaa_eth_ops = {
Ioana Ciornei1fe5e9f2023-05-23 16:47:48 +03001034 .start = ldpaa_eth_open,
1035 .send = ldpaa_eth_tx,
1036 .recv = ldpaa_eth_pull_dequeue_rx,
1037 .stop = ldpaa_eth_stop,
1038 .get_sset_count = ldpaa_eth_get_sset_count,
1039 .get_strings = ldpaa_eth_get_strings,
1040 .get_stats = ldpaa_eth_get_stats,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001041};
1042
1043static const struct udevice_id ldpaa_eth_of_ids[] = {
1044 { .compatible = "fsl,qoriq-mc-dpmac" },
1045};
1046
1047U_BOOT_DRIVER(ldpaa_eth) = {
Ioana Ciornei5d1e9222023-02-09 18:07:03 +02001048 .name = LDPAA_ETH_DRIVER_NAME,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001049 .id = UCLASS_ETH,
1050 .of_match = ldpaa_eth_of_ids,
Simon Glassaad29ae2020-12-03 16:55:21 -07001051 .of_to_plat = ldpaa_eth_of_to_plat,
Ioana Ciornei872004f2020-03-18 16:47:37 +02001052 .bind = ldpaa_eth_bind,
1053 .probe = ldpaa_eth_probe,
1054 .ops = &ldpaa_eth_ops,
Simon Glass8a2b47f2020-12-03 16:55:17 -07001055 .priv_auto = sizeof(struct ldpaa_eth_priv),
Simon Glass71fa5b42020-12-03 16:55:18 -07001056 .plat_auto = sizeof(struct eth_pdata),
Ioana Ciornei872004f2020-03-18 16:47:37 +02001057};