blob: 48343dce1c4ff6e186d2177d0cfbf59c45162f93 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07002/*
Yogesh Gaur1a0c4ae2018-05-09 10:52:17 +05303 * Copyright 2014-2016 Freescale Semiconductor, Inc.
Yogesh Gaur318c32f2017-11-15 11:59:31 +05304 * Copyright 2017 NXP
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07005 */
6
7#include <common.h>
Simon Glass63334482019-11-14 12:57:39 -07008#include <cpu_func.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07009#include <asm/io.h>
10#include <asm/types.h>
11#include <malloc.h>
12#include <net.h>
13#include <hwconfig.h>
14#include <phy.h>
Ioana Ciornei872004f2020-03-18 16:47:37 +020015#include <miiphy.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070016#include <linux/compat.h>
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +053017#include <fsl-mc/fsl_dpmac.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070018
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053019#include <fsl-mc/ldpaa_wriop.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070020#include "ldpaa_eth.h"
21
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053022#ifdef CONFIG_PHYLIB
Ioana Ciornei872004f2020-03-18 16:47:37 +020023#ifdef CONFIG_DM_ETH
24static void init_phy(struct udevice *dev)
25{
26 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
27
28 priv->phy = dm_eth_phy_connect(dev);
29
30 if (!priv->phy)
31 return;
32
33 phy_config(priv->phy);
34}
35#else
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070036static int init_phy(struct eth_device *dev)
37{
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053038 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
39 struct phy_device *phydev = NULL;
40 struct mii_dev *bus;
Pankaj Bansal50adb5e2018-10-10 14:08:34 +053041 int phy_addr, phy_num;
42 int ret = 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070043
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053044 bus = wriop_get_mdio(priv->dpmac_id);
45 if (bus == NULL)
46 return 0;
47
Pankaj Bansal50adb5e2018-10-10 14:08:34 +053048 for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
49 phy_addr = wriop_get_phy_address(priv->dpmac_id, phy_num);
50 if (phy_addr < 0)
51 continue;
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053052
Pankaj Bansal50adb5e2018-10-10 14:08:34 +053053 phydev = phy_connect(bus, phy_addr, dev,
54 wriop_get_enet_if(priv->dpmac_id));
55 if (!phydev) {
56 printf("Failed to connect\n");
57 ret = -ENODEV;
58 break;
59 }
60 wriop_set_phy_dev(priv->dpmac_id, phy_num, phydev);
61 ret = phy_config(phydev);
62 if (ret)
63 break;
64 }
Pankaj Bansalff076d72018-10-10 14:08:31 +053065
66 if (ret) {
Pankaj Bansal50adb5e2018-10-10 14:08:34 +053067 for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
68 phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
69 if (!phydev)
70 continue;
71
72 free(phydev);
73 wriop_set_phy_dev(priv->dpmac_id, phy_num, NULL);
74 }
Pankaj Bansalff076d72018-10-10 14:08:31 +053075 }
76
77 return ret;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070078}
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +053079#endif
Ioana Ciornei872004f2020-03-18 16:47:37 +020080#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070081
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053082#ifdef DEBUG
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053083
Yogesh Gaur318c32f2017-11-15 11:59:31 +053084#define DPNI_STATS_PER_PAGE 6
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053085
Yogesh Gaur318c32f2017-11-15 11:59:31 +053086static const char *dpni_statistics[][DPNI_STATS_PER_PAGE] = {
87 {
88 "DPNI_CNT_ING_ALL_FRAMES",
89 "DPNI_CNT_ING_ALL_BYTES",
90 "DPNI_CNT_ING_MCAST_FRAMES",
91 "DPNI_CNT_ING_MCAST_BYTES",
92 "DPNI_CNT_ING_BCAST_FRAMES",
93 "DPNI_CNT_ING_BCAST_BYTES",
94 }, {
95 "DPNI_CNT_EGR_ALL_FRAMES",
96 "DPNI_CNT_EGR_ALL_BYTES",
97 "DPNI_CNT_EGR_MCAST_FRAMES",
98 "DPNI_CNT_EGR_MCAST_BYTES",
99 "DPNI_CNT_EGR_BCAST_FRAMES",
100 "DPNI_CNT_EGR_BCAST_BYTES",
101 }, {
102 "DPNI_CNT_ING_FILTERED_FRAMES",
103 "DPNI_CNT_ING_DISCARDED_FRAMES",
104 "DPNI_CNT_ING_NOBUFFER_DISCARDS",
105 "DPNI_CNT_EGR_DISCARDED_FRAMES",
106 "DPNI_CNT_EGR_CNF_FRAMES",
107 ""
108 },
109};
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530110
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530111static void print_dpni_stats(const char *strings[],
112 struct dpni_statistics dpni_stats)
113{
114 uint64_t *stat;
115 int i;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530116
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530117 stat = (uint64_t *)&dpni_stats;
118 for (i = 0; i < DPNI_STATS_PER_PAGE; i++) {
119 if (strcmp(strings[i], "\0") == 0)
120 break;
121 printf("%s= %llu\n", strings[i], *stat);
122 stat++;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530123 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530124}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530125
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530126static void ldpaa_eth_get_dpni_counter(void)
127{
128 int err = 0;
129 unsigned int page = 0;
130 struct dpni_statistics dpni_stats;
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530131
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530132 printf("DPNI counters ..\n");
133 for (page = 0; page < 3; page++) {
134 err = dpni_get_statistics(dflt_mc_io, MC_CMD_NO_FLAGS,
135 dflt_dpni->dpni_handle, page,
136 &dpni_stats);
137 if (err < 0) {
138 printf("dpni_get_statistics: failed:");
139 printf("%d for page[%d]\n", err, page);
140 return;
141 }
142 print_dpni_stats(dpni_statistics[page], dpni_stats);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530143 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530144}
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530145
Ioana Ciornei872004f2020-03-18 16:47:37 +0200146#ifdef CONFIG_DM_ETH
147static void ldpaa_eth_get_dpmac_counter(struct udevice *dev)
148{
149 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
150#else
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530151static void ldpaa_eth_get_dpmac_counter(struct eth_device *net_dev)
152{
153 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200154#endif
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530155 int err = 0;
156 u64 value;
157
158 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
159 priv->dpmac_handle,
160 DPMAC_CNT_ING_BYTE,
161 &value);
162 if (err < 0) {
163 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
164 return;
165 }
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530166 printf("\nDPMAC counters ..\n");
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530167 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
168
169 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
170 priv->dpmac_handle,
171 DPMAC_CNT_ING_FRAME_DISCARD,
172 &value);
173 if (err < 0) {
174 printf("dpmac_get_counter: DPMAC_CNT_ING_FRAME_DISCARD failed\n");
175 return;
176 }
177 printf("DPMAC_CNT_ING_FRAME_DISCARD=%lld\n", value);
178
179 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
180 priv->dpmac_handle,
181 DPMAC_CNT_ING_ALIGN_ERR,
182 &value);
183 if (err < 0) {
184 printf("dpmac_get_counter: DPMAC_CNT_ING_ALIGN_ERR failed\n");
185 return;
186 }
187 printf("DPMAC_CNT_ING_ALIGN_ERR =%lld\n", value);
188
189 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
190 priv->dpmac_handle,
191 DPMAC_CNT_ING_BYTE,
192 &value);
193 if (err < 0) {
194 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
195 return;
196 }
197 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
198
199 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
200 priv->dpmac_handle,
201 DPMAC_CNT_ING_ERR_FRAME,
202 &value);
203 if (err < 0) {
204 printf("dpmac_get_counter: DPMAC_CNT_ING_ERR_FRAME failed\n");
205 return;
206 }
207 printf("DPMAC_CNT_ING_ERR_FRAME=%lld\n", value);
208
209 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
210 priv->dpmac_handle,
211 DPMAC_CNT_EGR_BYTE ,
212 &value);
213 if (err < 0) {
214 printf("dpmac_get_counter: DPMAC_CNT_EGR_BYTE failed\n");
215 return;
216 }
217 printf("DPMAC_CNT_EGR_BYTE =%lld\n", value);
218
219 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
220 priv->dpmac_handle,
221 DPMAC_CNT_EGR_ERR_FRAME ,
222 &value);
223 if (err < 0) {
224 printf("dpmac_get_counter: DPMAC_CNT_EGR_ERR_FRAME failed\n");
225 return;
226 }
227 printf("DPMAC_CNT_EGR_ERR_FRAME =%lld\n", value);
228}
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530229#endif
230
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700231static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
232 const struct dpaa_fd *fd)
233{
234 u64 fd_addr;
235 uint16_t fd_offset;
236 uint32_t fd_length;
237 struct ldpaa_fas *fas;
238 uint32_t status, err;
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530239 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
240 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700241 struct qbman_release_desc releasedesc;
242 struct qbman_swp *swp = dflt_dpio->sw_portal;
243
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700244 fd_addr = ldpaa_fd_get_addr(fd);
245 fd_offset = ldpaa_fd_get_offset(fd);
246 fd_length = ldpaa_fd_get_len(fd);
247
248 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
249
250 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
251 /* Read the frame annotation status word and check for errors */
252 fas = (struct ldpaa_fas *)
253 ((uint8_t *)(fd_addr) +
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530254 dflt_dpni->buf_layout.private_data_size);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700255 status = le32_to_cpu(fas->status);
256 if (status & LDPAA_ETH_RX_ERR_MASK) {
257 printf("Rx frame error(s): 0x%08x\n",
258 status & LDPAA_ETH_RX_ERR_MASK);
259 goto error;
260 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
261 printf("Unsupported feature in bitmask: 0x%08x\n",
262 status & LDPAA_ETH_RX_UNSUPP_MASK);
263 goto error;
264 }
265 }
266
267 debug("Rx frame: To Upper layer\n");
268 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
269 fd_length);
270
271error:
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700272 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700273 qbman_release_desc_clear(&releasedesc);
274 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530275 time_start = get_timer(0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700276 do {
277 /* Release buffer into the QBMAN */
278 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530279 } while (get_timer(time_start) < timeo && err == -EBUSY);
280
281 if (err == -EBUSY)
282 printf("Rx frame: QBMAN buffer release fails\n");
283
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700284 return;
285}
286
Ioana Ciornei872004f2020-03-18 16:47:37 +0200287#ifdef CONFIG_DM_ETH
288static int ldpaa_eth_pull_dequeue_rx(struct udevice *dev,
289 int flags, uchar **packetp)
290{
291 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
292#else
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700293static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
294{
295 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200296#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700297 const struct ldpaa_dq *dq;
298 const struct dpaa_fd *fd;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530299 int i = 5, err = 0, status;
300 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
301 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700302 static struct qbman_pull_desc pulldesc;
303 struct qbman_swp *swp = dflt_dpio->sw_portal;
304
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700305 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700306 qbman_pull_desc_clear(&pulldesc);
307 qbman_pull_desc_set_numframes(&pulldesc, 1);
308 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
309
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700310 err = qbman_swp_pull(swp, &pulldesc);
311 if (err < 0) {
312 printf("Dequeue frames error:0x%08x\n", err);
313 continue;
314 }
315
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530316 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700317
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530318 do {
319 dq = qbman_swp_dqrr_next(swp);
320 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700321
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700322 if (dq) {
323 /* Check for valid frame. If not sent a consume
324 * confirmation to QBMAN otherwise give it to NADK
325 * application and then send consume confirmation to
326 * QBMAN.
327 */
328 status = (uint8_t)ldpaa_dq_flags(dq);
329 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
330 debug("Dequeue RX frames:");
331 debug("No frame delivered\n");
332
333 qbman_swp_dqrr_consume(swp, dq);
Prabhakar Kushwaha37ed1a62015-07-02 11:29:07 +0530334 continue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700335 }
336
337 fd = ldpaa_dq_fd(dq);
338
339 /* Obtain FD and process it */
340 ldpaa_eth_rx(priv, fd);
341 qbman_swp_dqrr_consume(swp, dq);
342 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530343 } else {
344 err = -ENODATA;
345 debug("No DQRR entries\n");
346 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700347 }
348 }
349
350 return err;
351}
352
Ioana Ciornei872004f2020-03-18 16:47:37 +0200353#ifdef CONFIG_DM_ETH
354static int ldpaa_eth_tx(struct udevice *dev, void *buf, int len)
355{
356 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
357#else
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700358static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
359{
360 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200361#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700362 struct dpaa_fd fd;
363 u64 buffer_start;
364 int data_offset, err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530365 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
366 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700367 struct qbman_swp *swp = dflt_dpio->sw_portal;
368 struct qbman_eq_desc ed;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530369 struct qbman_release_desc releasedesc;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700370
371 /* Setup the FD fields */
372 memset(&fd, 0, sizeof(fd));
373
374 data_offset = priv->tx_data_offset;
375
376 do {
377 err = qbman_swp_acquire(dflt_dpio->sw_portal,
378 dflt_dpbp->dpbp_attr.bpid,
379 &buffer_start, 1);
380 } while (err == -EBUSY);
381
Ashish Kumar34f080c2017-10-26 16:03:22 +0530382 if (err <= 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700383 printf("qbman_swp_acquire() failed\n");
384 return -ENOMEM;
385 }
386
387 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
388
389 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
390
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700391 flush_dcache_range(buffer_start, buffer_start +
392 LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700393
394 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
395 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
396 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
397 ldpaa_fd_set_len(&fd, len);
398
399 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
400 LDPAA_FD_CTRL_PTV1;
401
402 qbman_eq_desc_clear(&ed);
403 qbman_eq_desc_set_no_orp(&ed, 0);
404 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530405
406 time_start = get_timer(0);
407
408 while (get_timer(time_start) < timeo) {
409 err = qbman_swp_enqueue(swp, &ed,
410 (const struct qbman_fd *)(&fd));
411 if (err != -EBUSY)
412 break;
413 }
414
415 if (err < 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700416 printf("error enqueueing Tx frame\n");
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530417 goto error;
418 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700419
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700420 return err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530421
422error:
423 qbman_release_desc_clear(&releasedesc);
424 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
425 time_start = get_timer(0);
426 do {
427 /* Release buffer into the QBMAN */
428 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
429 } while (get_timer(time_start) < timeo && err == -EBUSY);
430
431 if (err == -EBUSY)
432 printf("TX data: QBMAN buffer release fails\n");
433
434 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700435}
436
Ioana Ciornei872004f2020-03-18 16:47:37 +0200437static struct phy_device *ldpaa_get_phydev(struct ldpaa_eth_priv *priv)
438{
439#ifdef CONFIG_DM_ETH
440 return priv->phy;
441#else
442#ifdef CONFIG_PHYLIB
443 struct phy_device *phydev = NULL;
444 int phy_num;
445
446 /* start the phy devices one by one and update the dpmac state */
447 for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
448 phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
449 if (phydev)
450 return phydev;
451 }
452 return NULL;
453#endif
454 return NULL;
455#endif
456}
457
Pankaj Bansale031d262018-10-10 14:08:32 +0530458static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
459 struct dpmac_link_state *state)
460{
Pankaj Bansale031d262018-10-10 14:08:32 +0530461 phy_interface_t enet_if;
Tom Rini13da6252018-10-11 20:07:48 -0400462 struct phy_device *phydev = NULL;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200463 int err;
Pankaj Bansale031d262018-10-10 14:08:32 +0530464
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530465 /* let's start off with maximum capabilities */
Pankaj Bansale031d262018-10-10 14:08:32 +0530466 enet_if = wriop_get_enet_if(priv->dpmac_id);
467 switch (enet_if) {
468 case PHY_INTERFACE_MODE_XGMII:
469 state->rate = SPEED_10000;
470 break;
471 default:
472 state->rate = SPEED_1000;
473 break;
474 }
Pankaj Bansale031d262018-10-10 14:08:32 +0530475
Ioana Ciornei872004f2020-03-18 16:47:37 +0200476 state->up = 1;
Pankaj Bansale031d262018-10-10 14:08:32 +0530477 state->options |= DPMAC_LINK_OPT_AUTONEG;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200478 phydev = ldpaa_get_phydev(priv);
Pankaj Bansal50adb5e2018-10-10 14:08:34 +0530479
Ioana Ciornei872004f2020-03-18 16:47:37 +0200480 if (phydev) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530481 err = phy_startup(phydev);
482 if (err) {
483 printf("%s: Could not initialize\n", phydev->dev->name);
484 state->up = 0;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200485 } else if (phydev->link) {
Pankaj Bansale031d262018-10-10 14:08:32 +0530486 state->rate = min(state->rate, (uint32_t)phydev->speed);
487 if (!phydev->duplex)
488 state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
489 if (!phydev->autoneg)
490 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
491 } else {
492 state->up = 0;
493 }
494 }
Ioana Ciornei872004f2020-03-18 16:47:37 +0200495
496 if (!phydev)
Pankaj Bansale031d262018-10-10 14:08:32 +0530497 state->options &= ~DPMAC_LINK_OPT_AUTONEG;
498
499 if (!state->up) {
500 state->rate = 0;
501 state->options = 0;
502 return -ENOLINK;
503 }
504
505 return 0;
506}
507
Ioana Ciornei872004f2020-03-18 16:47:37 +0200508#ifdef CONFIG_DM_ETH
509static int ldpaa_eth_open(struct udevice *dev)
510{
511 struct eth_pdata *plat = dev_get_platdata(dev);
512 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
513#else
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700514static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
515{
516 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200517#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530518 struct dpmac_link_state dpmac_link_state = { 0 };
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530519#ifdef DEBUG
520 struct dpni_link_state link_state;
521#endif
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530522 int err = 0;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530523 struct dpni_queue d_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700524
Ioana Ciornei872004f2020-03-18 16:47:37 +0200525#ifdef CONFIG_DM_ETH
526 if (eth_is_active(dev))
527 return 0;
528#else
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700529 if (net_dev->state == ETH_STATE_ACTIVE)
530 return 0;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200531#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700532
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530533 if (get_mc_boot_status() != 0) {
534 printf("ERROR (MC is not booted)\n");
535 return -ENODEV;
536 }
537
538 if (get_dpl_apply_status() == 0) {
539 printf("ERROR (DPL is deployed. No device available)\n");
540 return -ENODEV;
541 }
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530542
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530543 /* DPMAC initialization */
544 err = ldpaa_dpmac_setup(priv);
545 if (err < 0)
546 goto err_dpmac_setup;
547
Pankaj Bansale031d262018-10-10 14:08:32 +0530548 err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
549 if (err < 0)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530550 goto err_dpmac_bind;
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +0530551
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530552 /* DPMAC binding DPNI */
553 err = ldpaa_dpmac_bind(priv);
554 if (err)
Pankaj Bansald24b1282018-10-10 14:08:29 +0530555 goto err_dpmac_bind;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530556
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700557 /* DPNI initialization */
558 err = ldpaa_dpni_setup(priv);
559 if (err < 0)
560 goto err_dpni_setup;
561
562 err = ldpaa_dpbp_setup();
563 if (err < 0)
564 goto err_dpbp_setup;
565
566 /* DPNI binding DPBP */
567 err = ldpaa_dpni_bind(priv);
568 if (err)
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530569 goto err_dpni_bind;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700570
Ioana Ciornei872004f2020-03-18 16:47:37 +0200571#ifdef CONFIG_DM_ETH
572 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
573 dflt_dpni->dpni_handle, plat->enetaddr);
574#else
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530575 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530576 dflt_dpni->dpni_handle, net_dev->enetaddr);
Ioana Ciornei872004f2020-03-18 16:47:37 +0200577#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700578 if (err) {
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530579 printf("dpni_add_mac_addr() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700580 return err;
581 }
582
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530583 err = dpni_enable(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_enable() failed\n");
586 return err;
587 }
588
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530589 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
590 priv->dpmac_handle, &dpmac_link_state);
591 if (err < 0) {
592 printf("dpmac_set_link_state() failed\n");
593 return err;
594 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530595
596#ifdef DEBUG
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530597 printf("DPMAC link status: %d - ", dpmac_link_state.up);
598 dpmac_link_state.up == 0 ? printf("down\n") :
599 dpmac_link_state.up == 1 ? printf("up\n") : printf("error state\n");
600
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530601 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
602 dflt_dpni->dpni_handle, &link_state);
603 if (err < 0) {
604 printf("dpni_get_link_state() failed\n");
605 return err;
606 }
607
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530608 printf("DPNI link status: %d - ", link_state.up);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530609 link_state.up == 0 ? printf("down\n") :
610 link_state.up == 1 ? printf("up\n") : printf("error state\n");
611#endif
612
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530613 memset(&d_queue, 0, sizeof(struct dpni_queue));
614 err = dpni_get_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
615 dflt_dpni->dpni_handle, DPNI_QUEUE_RX,
616 0, 0, &d_queue);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700617 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530618 printf("dpni_get_queue failed\n");
619 goto err_get_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700620 }
621
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530622 priv->rx_dflt_fqid = d_queue.fqid;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700623
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530624 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530625 &priv->tx_qdid);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700626 if (err) {
627 printf("dpni_get_qdid() failed\n");
628 goto err_qdid;
629 }
630
Pankaj Bansale031d262018-10-10 14:08:32 +0530631 return dpmac_link_state.up;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700632
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700633err_qdid:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530634err_get_queue:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530635 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
636err_dpni_bind:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700637 ldpaa_dpbp_free();
638err_dpbp_setup:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530639 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700640err_dpni_setup:
Pankaj Bansald24b1282018-10-10 14:08:29 +0530641err_dpmac_bind:
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530642 dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
643 dpmac_destroy(dflt_mc_io,
644 dflt_dprc_handle,
645 MC_CMD_NO_FLAGS, priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530646err_dpmac_setup:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700647 return err;
648}
649
Ioana Ciornei872004f2020-03-18 16:47:37 +0200650#ifdef CONFIG_DM_ETH
651static void ldpaa_eth_stop(struct udevice *dev)
652{
653 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
654#else
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700655static void ldpaa_eth_stop(struct eth_device *net_dev)
656{
657 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
Tom Rini13da6252018-10-11 20:07:48 -0400658#endif
Ioana Ciornei872004f2020-03-18 16:47:37 +0200659 struct phy_device *phydev = NULL;
660 int err = 0;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700661
Ioana Ciornei872004f2020-03-18 16:47:37 +0200662#ifdef CONFIG_DM_ETH
663 if (!eth_is_active(dev))
664 return;
665#else
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700666 if ((net_dev->state == ETH_STATE_PASSIVE) ||
667 (net_dev->state == ETH_STATE_INIT))
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700668 return;
Ioana Ciornei872004f2020-03-18 16:47:37 +0200669#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530670
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530671#ifdef DEBUG
672 ldpaa_eth_get_dpni_counter();
Ioana Ciornei872004f2020-03-18 16:47:37 +0200673#ifdef CONFIG_DM_ETH
674 ldpaa_eth_get_dpmac_counter(dev);
675#else
Prabhakar Kushwaha314aa552015-12-24 15:33:37 +0530676 ldpaa_eth_get_dpmac_counter(net_dev);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530677#endif
Ioana Ciornei872004f2020-03-18 16:47:37 +0200678#endif
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530679
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530680 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
681 dflt_dprc_handle, &dpmac_endpoint);
682 if (err < 0)
683 printf("dprc_disconnect() failed dpmac_endpoint\n");
684
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530685 err = dpmac_close(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
686 if (err < 0)
687 printf("dpmac_close() failed\n");
688
689 err = dpmac_destroy(dflt_mc_io,
690 dflt_dprc_handle,
691 MC_CMD_NO_FLAGS,
692 priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530693 if (err < 0)
694 printf("dpmac_destroy() failed\n");
695
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700696 /* Stop Tx and Rx traffic */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530697 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700698 if (err < 0)
699 printf("dpni_disable() failed\n");
700
Ioana Ciornei872004f2020-03-18 16:47:37 +0200701 phydev = ldpaa_get_phydev(priv);
702 if (phydev)
703 phy_shutdown(phydev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700704
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530705 /* Free DPBP handle and reset. */
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700706 ldpaa_dpbp_free();
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530707
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530708 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530709 if (err < 0)
710 printf("dpni_reset() failed\n");
711
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530712 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530713 if (err < 0)
714 printf("dpni_close() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700715}
716
717static void ldpaa_dpbp_drain_cnt(int count)
718{
719 uint64_t buf_array[7];
720 void *addr;
721 int ret, i;
722
723 BUG_ON(count > 7);
724
725 do {
726 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
727 dflt_dpbp->dpbp_attr.bpid,
728 buf_array, count);
729 if (ret < 0) {
730 printf("qbman_swp_acquire() failed\n");
731 return;
732 }
733 for (i = 0; i < ret; i++) {
734 addr = (void *)buf_array[i];
735 debug("Free: buffer addr =0x%p\n", addr);
736 free(addr);
737 }
738 } while (ret);
739}
740
741static void ldpaa_dpbp_drain(void)
742{
743 int i;
744 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
745 ldpaa_dpbp_drain_cnt(7);
746}
747
748static int ldpaa_bp_add_7(uint16_t bpid)
749{
750 uint64_t buf_array[7];
751 u8 *addr;
752 int i;
753 struct qbman_release_desc rd;
754
755 for (i = 0; i < 7; i++) {
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530756 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700757 if (!addr) {
758 printf("addr allocation failed\n");
759 goto err_alloc;
760 }
761 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700762 flush_dcache_range((u64)addr,
763 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700764
765 buf_array[i] = (uint64_t)addr;
766 debug("Release: buffer addr =0x%p\n", addr);
767 }
768
769release_bufs:
770 /* In case the portal is busy, retry until successful.
771 * This function is guaranteed to succeed in a reasonable amount
772 * of time.
773 */
774
775 do {
776 mdelay(1);
777 qbman_release_desc_clear(&rd);
778 qbman_release_desc_set_bpid(&rd, bpid);
779 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
780
781 return i;
782
783err_alloc:
784 if (i)
785 goto release_bufs;
786
787 return 0;
788}
789
790static int ldpaa_dpbp_seed(uint16_t bpid)
791{
792 int i;
793 int count;
794
795 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
796 count = ldpaa_bp_add_7(bpid);
797 if (count < 7)
798 printf("Buffer Seed= %d\n", count);
799 }
800
801 return 0;
802}
803
804static int ldpaa_dpbp_setup(void)
805{
806 int err;
807
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530808 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700809 &dflt_dpbp->dpbp_handle);
810 if (err) {
811 printf("dpbp_open() failed\n");
812 goto err_open;
813 }
814
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530815 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700816 if (err) {
817 printf("dpbp_enable() failed\n");
818 goto err_enable;
819 }
820
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530821 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
822 dflt_dpbp->dpbp_handle,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700823 &dflt_dpbp->dpbp_attr);
824 if (err) {
825 printf("dpbp_get_attributes() failed\n");
826 goto err_get_attr;
827 }
828
829 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530830
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700831 if (err) {
832 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
833 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
834 goto err_seed;
835 }
836
837 return 0;
838
839err_seed:
840err_get_attr:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530841 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700842err_enable:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530843 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700844err_open:
845 return err;
846}
847
848static void ldpaa_dpbp_free(void)
849{
850 ldpaa_dpbp_drain();
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530851 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
852 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
853 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700854}
855
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530856static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
857 struct ldpaa_eth_priv *priv)
858{
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530859 int error;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530860 uint16_t major_ver, minor_ver;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530861
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530862 error = dpmac_get_api_version(dflt_mc_io, 0,
863 &major_ver,
864 &minor_ver);
865 if ((major_ver < DPMAC_VER_MAJOR) ||
866 (major_ver == DPMAC_VER_MAJOR && minor_ver < DPMAC_VER_MINOR)) {
867 printf("DPMAC version mismatch found %u.%u,",
868 major_ver, minor_ver);
869 printf("supported version is %u.%u\n",
870 DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
871 return error;
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530872 }
873
874 return error;
875}
876
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530877static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
878{
879 int err = 0;
880 struct dpmac_cfg dpmac_cfg;
881
882 dpmac_cfg.mac_id = priv->dpmac_id;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530883
884 err = dpmac_create(dflt_mc_io,
885 dflt_dprc_handle,
886 MC_CMD_NO_FLAGS, &dpmac_cfg,
887 &priv->dpmac_id);
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530888 if (err)
889 printf("dpmac_create() failed\n");
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530890
891 err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530892 if (err < 0) {
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530893 printf("ldpaa_dpmac_version_check() failed: %d\n", err);
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530894 goto err_version_check;
895 }
896
897 err = dpmac_open(dflt_mc_io,
898 MC_CMD_NO_FLAGS,
899 priv->dpmac_id,
900 &priv->dpmac_handle);
901 if (err < 0) {
902 printf("dpmac_open() failed: %d\n", err);
903 goto err_open;
904 }
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530905
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530906 return err;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530907
908err_open:
909err_version_check:
910 dpmac_destroy(dflt_mc_io,
911 dflt_dprc_handle,
912 MC_CMD_NO_FLAGS, priv->dpmac_id);
913
914 return err;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530915}
916
917static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
918{
919 int err = 0;
920 struct dprc_connection_cfg dprc_connection_cfg = {
921 /* If both rates are zero the connection */
922 /* will be configured in "best effort" mode. */
923 .committed_rate = 0,
924 .max_rate = 0
925 };
926
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530927#ifdef DEBUG
928 struct dprc_endpoint dbg_endpoint;
929 int state = 0;
930#endif
931
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530932 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000933 strcpy(dpmac_endpoint.type, "dpmac");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530934 dpmac_endpoint.id = priv->dpmac_id;
935
936 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000937 strcpy(dpni_endpoint.type, "dpni");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530938 dpni_endpoint.id = dflt_dpni->dpni_id;
939
940 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
941 dflt_dprc_handle,
942 &dpmac_endpoint,
943 &dpni_endpoint,
944 &dprc_connection_cfg);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530945 if (err)
946 printf("dprc_connect() failed\n");
947
948#ifdef DEBUG
949 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
950 dflt_dprc_handle, &dpni_endpoint,
951 &dbg_endpoint, &state);
952 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
953 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
954 printf("%s, DPMAC State= %d\n", __func__, state);
955
956 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
957 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
958 dflt_dprc_handle, &dpmac_endpoint,
959 &dbg_endpoint, &state);
960 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
961 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
962 printf("%s, DPNI State= %d\n", __func__, state);
963#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530964 return err;
965}
966
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700967static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
968{
969 int err;
970
971 /* and get a handle for the DPNI this interface is associate with */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530972 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
973 &dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700974 if (err) {
975 printf("dpni_open() failed\n");
976 goto err_open;
977 }
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530978 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530979 dflt_dpni->dpni_handle,
980 &dflt_dpni->dpni_attrs);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700981 if (err) {
982 printf("dpni_get_attributes() failed (err=%d)\n", err);
983 goto err_get_attr;
984 }
985
986 /* Configure our buffers' layout */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530987 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700988 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530989 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
990 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530991 dflt_dpni->buf_layout.pass_parser_result = true;
992 dflt_dpni->buf_layout.pass_frame_status = true;
993 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530994 /* HW erratum mandates data alignment in multiples of 256 */
995 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530996
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700997 /* ...rx, ... */
Yogesh Gaur318c32f2017-11-15 11:59:31 +0530998 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
999 dflt_dpni->dpni_handle,
1000 &dflt_dpni->buf_layout, DPNI_QUEUE_RX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001001 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301002 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001003 goto err_buf_layout;
1004 }
1005
1006 /* ... tx, ... */
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +05301007 /* remove Rx-only options */
1008 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
1009 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301010 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
1011 dflt_dpni->dpni_handle,
1012 &dflt_dpni->buf_layout, DPNI_QUEUE_TX);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001013 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301014 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001015 goto err_buf_layout;
1016 }
1017
1018 /* ... tx-confirm. */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301019 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301020 err = dpni_set_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
1021 dflt_dpni->dpni_handle,
1022 &dflt_dpni->buf_layout,
1023 DPNI_QUEUE_TX_CONFIRM);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001024 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301025 printf("dpni_set_buffer_layout() failed");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001026 goto err_buf_layout;
1027 }
1028
1029 /* Now that we've set our tx buffer layout, retrieve the minimum
1030 * required tx data offset.
1031 */
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +05301032 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301033 dflt_dpni->dpni_handle,
1034 &priv->tx_data_offset);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001035 if (err) {
1036 printf("dpni_get_tx_data_offset() failed\n");
1037 goto err_data_offset;
1038 }
1039
1040 /* Warn in case TX data offset is not multiple of 64 bytes. */
1041 WARN_ON(priv->tx_data_offset % 64);
1042
1043 /* Accomodate SWA space. */
1044 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
1045 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
1046
1047 return 0;
1048
1049err_data_offset:
1050err_buf_layout:
1051err_get_attr:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301052 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001053err_open:
1054 return err;
1055}
1056
1057static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
1058{
1059 struct dpni_pools_cfg pools_params;
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301060 struct dpni_queue tx_queue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001061 int err = 0;
1062
Prabhakar Kushwahaa7992322016-03-28 14:11:05 +05301063 memset(&pools_params, 0, sizeof(pools_params));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001064 pools_params.num_dpbp = 1;
1065 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
1066 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301067 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
1068 dflt_dpni->dpni_handle, &pools_params);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001069 if (err) {
1070 printf("dpni_set_pools() failed\n");
1071 return err;
1072 }
1073
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301074 memset(&tx_queue, 0, sizeof(struct dpni_queue));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001075
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301076 err = dpni_set_queue(dflt_mc_io, MC_CMD_NO_FLAGS,
1077 dflt_dpni->dpni_handle,
1078 DPNI_QUEUE_TX, 0, 0, &tx_queue);
1079
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001080 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301081 printf("dpni_set_queue() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001082 return err;
1083 }
1084
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301085 err = dpni_set_tx_confirmation_mode(dflt_mc_io, MC_CMD_NO_FLAGS,
1086 dflt_dpni->dpni_handle,
1087 DPNI_CONF_DISABLE);
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +05301088 if (err) {
Yogesh Gaur318c32f2017-11-15 11:59:31 +05301089 printf("dpni_set_tx_confirmation_mode() failed\n");
Prabhakar Kushwahab0efba72015-12-24 15:33:13 +05301090 return err;
1091 }
1092
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001093 return 0;
1094}
1095
Ioana Ciornei872004f2020-03-18 16:47:37 +02001096#ifdef CONFIG_DM_ETH
1097static int ldpaa_eth_probe(struct udevice *dev)
1098{
1099 struct ofnode_phandle_args phandle;
1100
1101 /* Nothing to do if there is no "phy-handle" in the DTS node */
1102 if (dev_read_phandle_with_args(dev, "phy-handle", NULL,
1103 0, 0, &phandle)) {
1104 return 0;
1105 }
1106
1107 init_phy(dev);
1108
1109 return 0;
1110}
1111
1112static uint32_t ldpaa_eth_get_dpmac_id(struct udevice *dev)
1113{
1114 int port_node = dev_of_offset(dev);
1115
1116 return fdtdec_get_uint(gd->fdt_blob, port_node, "reg", -1);
1117}
1118
1119static const char *ldpaa_eth_get_phy_mode_str(struct udevice *dev)
1120{
1121 int port_node = dev_of_offset(dev);
1122 const char *phy_mode_str;
1123
1124 phy_mode_str = fdt_getprop(gd->fdt_blob, port_node,
1125 "phy-connection-type", NULL);
1126 if (phy_mode_str)
1127 return phy_mode_str;
1128
1129 phy_mode_str = fdt_getprop(gd->fdt_blob, port_node, "phy-mode", NULL);
1130 return phy_mode_str;
1131}
1132
1133static int ldpaa_eth_bind(struct udevice *dev)
1134{
1135 const char *phy_mode_str = NULL;
1136 uint32_t dpmac_id;
1137 char eth_name[16];
1138 int phy_mode = -1;
1139
1140 phy_mode_str = ldpaa_eth_get_phy_mode_str(dev);
1141 if (phy_mode_str)
1142 phy_mode = phy_get_interface_by_name(phy_mode_str);
1143 if (phy_mode == -1) {
1144 dev_err(dev, "incorrect phy mode\n");
1145 return -EINVAL;
1146 }
1147
1148 dpmac_id = ldpaa_eth_get_dpmac_id(dev);
1149 if (dpmac_id == -1) {
1150 dev_err(dev, "missing reg field from the dpmac node\n");
1151 return -EINVAL;
1152 }
1153
1154 sprintf(eth_name, "DPMAC%d@%s", dpmac_id, phy_mode_str);
1155 device_set_name(dev, eth_name);
1156
1157 return 0;
1158}
1159
1160static int ldpaa_eth_ofdata_to_platdata(struct udevice *dev)
1161{
1162 struct ldpaa_eth_priv *priv = dev_get_priv(dev);
1163 const char *phy_mode_str;
1164
1165 priv->dpmac_id = ldpaa_eth_get_dpmac_id(dev);
1166 phy_mode_str = ldpaa_eth_get_phy_mode_str(dev);
1167 priv->phy_mode = phy_get_interface_by_name(phy_mode_str);
1168
1169 return 0;
1170}
1171
1172static const struct eth_ops ldpaa_eth_ops = {
1173 .start = ldpaa_eth_open,
1174 .send = ldpaa_eth_tx,
1175 .recv = ldpaa_eth_pull_dequeue_rx,
1176 .stop = ldpaa_eth_stop,
1177};
1178
1179static const struct udevice_id ldpaa_eth_of_ids[] = {
1180 { .compatible = "fsl,qoriq-mc-dpmac" },
1181};
1182
1183U_BOOT_DRIVER(ldpaa_eth) = {
1184 .name = "ldpaa_eth",
1185 .id = UCLASS_ETH,
1186 .of_match = ldpaa_eth_of_ids,
1187 .ofdata_to_platdata = ldpaa_eth_ofdata_to_platdata,
1188 .bind = ldpaa_eth_bind,
1189 .probe = ldpaa_eth_probe,
1190 .ops = &ldpaa_eth_ops,
1191 .priv_auto_alloc_size = sizeof(struct ldpaa_eth_priv),
1192 .platdata_auto_alloc_size = sizeof(struct eth_pdata),
1193};
1194
1195#else
1196
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301197static int ldpaa_eth_netdev_init(struct eth_device *net_dev,
1198 phy_interface_t enet_if)
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001199{
1200 int err;
1201 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
1202
Pankaj Bansal8a921702018-08-02 16:31:28 +05301203 snprintf(net_dev->name, ETH_NAME_LEN, "DPMAC%d@%s", priv->dpmac_id,
1204 phy_interface_strings[enet_if]);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001205
1206 net_dev->iobase = 0;
1207 net_dev->init = ldpaa_eth_open;
1208 net_dev->halt = ldpaa_eth_stop;
1209 net_dev->send = ldpaa_eth_tx;
1210 net_dev->recv = ldpaa_eth_pull_dequeue_rx;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001211
Prabhakar Kushwahaef9329a2016-02-24 17:02:11 +05301212#ifdef CONFIG_PHYLIB
1213 err = init_phy(net_dev);
1214 if (err < 0)
1215 return err;
1216#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001217
1218 err = eth_register(net_dev);
1219 if (err < 0) {
1220 printf("eth_register() = %d\n", err);
1221 return err;
1222 }
1223
1224 return 0;
1225}
1226
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301227int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001228{
1229 struct eth_device *net_dev = NULL;
1230 struct ldpaa_eth_priv *priv = NULL;
1231 int err = 0;
1232
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001233 /* Net device */
1234 net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
1235 if (!net_dev) {
1236 printf("eth_device malloc() failed\n");
1237 return -ENOMEM;
1238 }
1239 memset(net_dev, 0, sizeof(struct eth_device));
1240
1241 /* alloc the ldpaa ethernet private struct */
1242 priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
1243 if (!priv) {
1244 printf("ldpaa_eth_priv malloc() failed\n");
Pankaj Bansala78f0452019-02-08 08:46:11 +00001245 free(net_dev);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001246 return -ENOMEM;
1247 }
1248 memset(priv, 0, sizeof(struct ldpaa_eth_priv));
1249
1250 net_dev->priv = (void *)priv;
1251 priv->net_dev = (struct eth_device *)net_dev;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301252 priv->dpmac_id = dpmac_id;
1253 debug("%s dpmac_id=%d\n", __func__, dpmac_id);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001254
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +05301255 err = ldpaa_eth_netdev_init(net_dev, enet_if);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001256 if (err)
1257 goto err_netdev_init;
1258
1259 debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
1260 return 0;
1261
1262err_netdev_init:
1263 free(priv);
1264 net_dev->priv = NULL;
1265 free(net_dev);
1266
1267 return err;
1268}
Ioana Ciornei872004f2020-03-18 16:47:37 +02001269#endif