]> git.ipfire.org Git - people/ms/u-boot.git/blob - drivers/net/ldpaa_eth/ldpaa_eth.c
f235b622b6f39489ddbdce0cc13d3d428b470705
[people/ms/u-boot.git] / drivers / net / ldpaa_eth / ldpaa_eth.c
1 /*
2 * Copyright (C) 2014 Freescale Semiconductor
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7 #include <common.h>
8 #include <asm/io.h>
9 #include <asm/types.h>
10 #include <malloc.h>
11 #include <net.h>
12 #include <hwconfig.h>
13 #include <phy.h>
14 #include <linux/compat.h>
15 #include <fsl-mc/fsl_dpmac.h>
16
17 #include <fsl-mc/ldpaa_wriop.h>
18 #include "ldpaa_eth.h"
19
20 #ifdef CONFIG_PHYLIB
21 static int init_phy(struct eth_device *dev)
22 {
23 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
24 struct phy_device *phydev = NULL;
25 struct mii_dev *bus;
26
27 bus = wriop_get_mdio(priv->dpmac_id);
28 if (bus == NULL)
29 return 0;
30
31 phydev = phy_connect(bus, wriop_get_phy_address(priv->dpmac_id),
32 dev, wriop_get_enet_if(priv->dpmac_id));
33 if (!phydev) {
34 printf("Failed to connect\n");
35 return -1;
36 }
37
38 priv->phydev = phydev;
39
40 return phy_config(phydev);
41 }
42 #endif
43
44 #ifdef DEBUG
45 static void ldpaa_eth_get_dpni_counter(void)
46 {
47 int err = 0;
48 u64 value;
49
50 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
51 dflt_dpni->dpni_handle,
52 DPNI_CNT_ING_FRAME,
53 &value);
54 if (err < 0) {
55 printf("dpni_get_counter: DPNI_CNT_ING_FRAME failed\n");
56 return;
57 }
58 printf("DPNI_CNT_ING_FRAME=%lld\n", value);
59
60 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
61 dflt_dpni->dpni_handle,
62 DPNI_CNT_ING_BYTE,
63 &value);
64 if (err < 0) {
65 printf("dpni_get_counter: DPNI_CNT_ING_BYTE failed\n");
66 return;
67 }
68 printf("DPNI_CNT_ING_BYTE=%lld\n", value);
69
70 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
71 dflt_dpni->dpni_handle,
72 DPNI_CNT_ING_FRAME_DROP ,
73 &value);
74 if (err < 0) {
75 printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DROP failed\n");
76 return;
77 }
78 printf("DPNI_CNT_ING_FRAME_DROP =%lld\n", value);
79
80 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
81 dflt_dpni->dpni_handle,
82 DPNI_CNT_ING_FRAME_DISCARD,
83 &value);
84 if (err < 0) {
85 printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DISCARD failed\n");
86 return;
87 }
88 printf("DPNI_CNT_ING_FRAME_DISCARD=%lld\n", value);
89
90 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
91 dflt_dpni->dpni_handle,
92 DPNI_CNT_EGR_FRAME,
93 &value);
94 if (err < 0) {
95 printf("dpni_get_counter: DPNI_CNT_EGR_FRAME failed\n");
96 return;
97 }
98 printf("DPNI_CNT_EGR_FRAME=%lld\n", value);
99
100 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
101 dflt_dpni->dpni_handle,
102 DPNI_CNT_EGR_BYTE ,
103 &value);
104 if (err < 0) {
105 printf("dpni_get_counter: DPNI_CNT_EGR_BYTE failed\n");
106 return;
107 }
108 printf("DPNI_CNT_EGR_BYTE =%lld\n", value);
109
110 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
111 dflt_dpni->dpni_handle,
112 DPNI_CNT_EGR_FRAME_DISCARD ,
113 &value);
114 if (err < 0) {
115 printf("dpni_get_counter: DPNI_CNT_EGR_FRAME_DISCARD failed\n");
116 return;
117 }
118 printf("DPNI_CNT_EGR_FRAME_DISCARD =%lld\n", value);
119 }
120
121 static void ldpaa_eth_get_dpmac_counter(struct eth_device *net_dev)
122 {
123 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
124 int err = 0;
125 u64 value;
126
127 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
128 priv->dpmac_handle,
129 DPMAC_CNT_ING_BYTE,
130 &value);
131 if (err < 0) {
132 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
133 return;
134 }
135 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
136
137 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
138 priv->dpmac_handle,
139 DPMAC_CNT_ING_FRAME_DISCARD,
140 &value);
141 if (err < 0) {
142 printf("dpmac_get_counter: DPMAC_CNT_ING_FRAME_DISCARD failed\n");
143 return;
144 }
145 printf("DPMAC_CNT_ING_FRAME_DISCARD=%lld\n", value);
146
147 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
148 priv->dpmac_handle,
149 DPMAC_CNT_ING_ALIGN_ERR,
150 &value);
151 if (err < 0) {
152 printf("dpmac_get_counter: DPMAC_CNT_ING_ALIGN_ERR failed\n");
153 return;
154 }
155 printf("DPMAC_CNT_ING_ALIGN_ERR =%lld\n", value);
156
157 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
158 priv->dpmac_handle,
159 DPMAC_CNT_ING_BYTE,
160 &value);
161 if (err < 0) {
162 printf("dpmac_get_counter: DPMAC_CNT_ING_BYTE failed\n");
163 return;
164 }
165 printf("DPMAC_CNT_ING_BYTE=%lld\n", value);
166
167 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
168 priv->dpmac_handle,
169 DPMAC_CNT_ING_ERR_FRAME,
170 &value);
171 if (err < 0) {
172 printf("dpmac_get_counter: DPMAC_CNT_ING_ERR_FRAME failed\n");
173 return;
174 }
175 printf("DPMAC_CNT_ING_ERR_FRAME=%lld\n", value);
176
177 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
178 priv->dpmac_handle,
179 DPMAC_CNT_EGR_BYTE ,
180 &value);
181 if (err < 0) {
182 printf("dpmac_get_counter: DPMAC_CNT_EGR_BYTE failed\n");
183 return;
184 }
185 printf("DPMAC_CNT_EGR_BYTE =%lld\n", value);
186
187 err = dpmac_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
188 priv->dpmac_handle,
189 DPMAC_CNT_EGR_ERR_FRAME ,
190 &value);
191 if (err < 0) {
192 printf("dpmac_get_counter: DPMAC_CNT_EGR_ERR_FRAME failed\n");
193 return;
194 }
195 printf("DPMAC_CNT_EGR_ERR_FRAME =%lld\n", value);
196 }
197 #endif
198
199 static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
200 const struct dpaa_fd *fd)
201 {
202 u64 fd_addr;
203 uint16_t fd_offset;
204 uint32_t fd_length;
205 struct ldpaa_fas *fas;
206 uint32_t status, err;
207 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
208 u32 time_start;
209 struct qbman_release_desc releasedesc;
210 struct qbman_swp *swp = dflt_dpio->sw_portal;
211
212 fd_addr = ldpaa_fd_get_addr(fd);
213 fd_offset = ldpaa_fd_get_offset(fd);
214 fd_length = ldpaa_fd_get_len(fd);
215
216 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
217
218 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
219 /* Read the frame annotation status word and check for errors */
220 fas = (struct ldpaa_fas *)
221 ((uint8_t *)(fd_addr) +
222 dflt_dpni->buf_layout.private_data_size);
223 status = le32_to_cpu(fas->status);
224 if (status & LDPAA_ETH_RX_ERR_MASK) {
225 printf("Rx frame error(s): 0x%08x\n",
226 status & LDPAA_ETH_RX_ERR_MASK);
227 goto error;
228 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
229 printf("Unsupported feature in bitmask: 0x%08x\n",
230 status & LDPAA_ETH_RX_UNSUPP_MASK);
231 goto error;
232 }
233 }
234
235 debug("Rx frame: To Upper layer\n");
236 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
237 fd_length);
238
239 error:
240 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
241 qbman_release_desc_clear(&releasedesc);
242 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
243 time_start = get_timer(0);
244 do {
245 /* Release buffer into the QBMAN */
246 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
247 } while (get_timer(time_start) < timeo && err == -EBUSY);
248
249 if (err == -EBUSY)
250 printf("Rx frame: QBMAN buffer release fails\n");
251
252 return;
253 }
254
255 static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
256 {
257 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
258 const struct ldpaa_dq *dq;
259 const struct dpaa_fd *fd;
260 int i = 5, err = 0, status;
261 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
262 u32 time_start;
263 static struct qbman_pull_desc pulldesc;
264 struct qbman_swp *swp = dflt_dpio->sw_portal;
265
266 while (--i) {
267 qbman_pull_desc_clear(&pulldesc);
268 qbman_pull_desc_set_numframes(&pulldesc, 1);
269 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
270
271 err = qbman_swp_pull(swp, &pulldesc);
272 if (err < 0) {
273 printf("Dequeue frames error:0x%08x\n", err);
274 continue;
275 }
276
277 time_start = get_timer(0);
278
279 do {
280 dq = qbman_swp_dqrr_next(swp);
281 } while (get_timer(time_start) < timeo && !dq);
282
283 if (dq) {
284 /* Check for valid frame. If not sent a consume
285 * confirmation to QBMAN otherwise give it to NADK
286 * application and then send consume confirmation to
287 * QBMAN.
288 */
289 status = (uint8_t)ldpaa_dq_flags(dq);
290 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
291 debug("Dequeue RX frames:");
292 debug("No frame delivered\n");
293
294 qbman_swp_dqrr_consume(swp, dq);
295 continue;
296 }
297
298 fd = ldpaa_dq_fd(dq);
299
300 /* Obtain FD and process it */
301 ldpaa_eth_rx(priv, fd);
302 qbman_swp_dqrr_consume(swp, dq);
303 break;
304 } else {
305 err = -ENODATA;
306 debug("No DQRR entries\n");
307 break;
308 }
309 }
310
311 return err;
312 }
313
314 static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
315 {
316 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
317 struct dpaa_fd fd;
318 u64 buffer_start;
319 int data_offset, err;
320 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
321 u32 time_start;
322 struct qbman_swp *swp = dflt_dpio->sw_portal;
323 struct qbman_eq_desc ed;
324 struct qbman_release_desc releasedesc;
325
326 /* Setup the FD fields */
327 memset(&fd, 0, sizeof(fd));
328
329 data_offset = priv->tx_data_offset;
330
331 do {
332 err = qbman_swp_acquire(dflt_dpio->sw_portal,
333 dflt_dpbp->dpbp_attr.bpid,
334 &buffer_start, 1);
335 } while (err == -EBUSY);
336
337 if (err < 0) {
338 printf("qbman_swp_acquire() failed\n");
339 return -ENOMEM;
340 }
341
342 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
343
344 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
345
346 flush_dcache_range(buffer_start, buffer_start +
347 LDPAA_ETH_RX_BUFFER_SIZE);
348
349 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
350 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
351 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
352 ldpaa_fd_set_len(&fd, len);
353
354 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
355 LDPAA_FD_CTRL_PTV1;
356
357 qbman_eq_desc_clear(&ed);
358 qbman_eq_desc_set_no_orp(&ed, 0);
359 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
360
361 time_start = get_timer(0);
362
363 while (get_timer(time_start) < timeo) {
364 err = qbman_swp_enqueue(swp, &ed,
365 (const struct qbman_fd *)(&fd));
366 if (err != -EBUSY)
367 break;
368 }
369
370 if (err < 0) {
371 printf("error enqueueing Tx frame\n");
372 goto error;
373 }
374
375 return err;
376
377 error:
378 qbman_release_desc_clear(&releasedesc);
379 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
380 time_start = get_timer(0);
381 do {
382 /* Release buffer into the QBMAN */
383 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
384 } while (get_timer(time_start) < timeo && err == -EBUSY);
385
386 if (err == -EBUSY)
387 printf("TX data: QBMAN buffer release fails\n");
388
389 return err;
390 }
391
392 static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
393 {
394 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
395 struct dpni_queue_attr rx_queue_attr;
396 struct dpmac_link_state dpmac_link_state = { 0 };
397 #ifdef DEBUG
398 struct dpni_link_state link_state;
399 #endif
400 int err = 0;
401 struct mii_dev *bus;
402 phy_interface_t enet_if;
403
404 if (net_dev->state == ETH_STATE_ACTIVE)
405 return 0;
406
407 if (get_mc_boot_status() != 0) {
408 printf("ERROR (MC is not booted)\n");
409 return -ENODEV;
410 }
411
412 if (get_dpl_apply_status() == 0) {
413 printf("ERROR (DPL is deployed. No device available)\n");
414 return -ENODEV;
415 }
416
417 /* DPMAC initialization */
418 err = ldpaa_dpmac_setup(priv);
419 if (err < 0)
420 goto err_dpmac_setup;
421
422 #ifdef CONFIG_PHYLIB
423 if (priv->phydev) {
424 err = phy_startup(priv->phydev);
425 if (err) {
426 printf("%s: Could not initialize\n",
427 priv->phydev->dev->name);
428 goto err_dpamc_bind;
429 }
430 }
431 #else
432 priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device));
433 memset(priv->phydev, 0, sizeof(struct phy_device));
434
435 priv->phydev->speed = SPEED_1000;
436 priv->phydev->link = 1;
437 priv->phydev->duplex = DUPLEX_FULL;
438 #endif
439
440 bus = wriop_get_mdio(priv->dpmac_id);
441 enet_if = wriop_get_enet_if(priv->dpmac_id);
442 if ((bus == NULL) &&
443 (enet_if == PHY_INTERFACE_MODE_XGMII)) {
444 priv->phydev = (struct phy_device *)
445 malloc(sizeof(struct phy_device));
446 memset(priv->phydev, 0, sizeof(struct phy_device));
447
448 priv->phydev->speed = SPEED_10000;
449 priv->phydev->link = 1;
450 priv->phydev->duplex = DUPLEX_FULL;
451 }
452
453 if (!priv->phydev->link) {
454 printf("%s: No link.\n", priv->phydev->dev->name);
455 err = -1;
456 goto err_dpamc_bind;
457 }
458
459 /* DPMAC binding DPNI */
460 err = ldpaa_dpmac_bind(priv);
461 if (err)
462 goto err_dpamc_bind;
463
464 /* DPNI initialization */
465 err = ldpaa_dpni_setup(priv);
466 if (err < 0)
467 goto err_dpni_setup;
468
469 err = ldpaa_dpbp_setup();
470 if (err < 0)
471 goto err_dpbp_setup;
472
473 /* DPNI binding DPBP */
474 err = ldpaa_dpni_bind(priv);
475 if (err)
476 goto err_dpni_bind;
477
478 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
479 dflt_dpni->dpni_handle, net_dev->enetaddr);
480 if (err) {
481 printf("dpni_add_mac_addr() failed\n");
482 return err;
483 }
484
485 err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
486 if (err < 0) {
487 printf("dpni_enable() failed\n");
488 return err;
489 }
490
491 dpmac_link_state.rate = priv->phydev->speed;
492
493 if (priv->phydev->autoneg == AUTONEG_DISABLE)
494 dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG;
495 else
496 dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG;
497
498 if (priv->phydev->duplex == DUPLEX_HALF)
499 dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
500
501 dpmac_link_state.up = priv->phydev->link;
502
503 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
504 priv->dpmac_handle, &dpmac_link_state);
505 if (err < 0) {
506 printf("dpmac_set_link_state() failed\n");
507 return err;
508 }
509
510 #ifdef DEBUG
511 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
512 dflt_dpni->dpni_handle, &link_state);
513 if (err < 0) {
514 printf("dpni_get_link_state() failed\n");
515 return err;
516 }
517
518 printf("link status: %d - ", link_state.up);
519 link_state.up == 0 ? printf("down\n") :
520 link_state.up == 1 ? printf("up\n") : printf("error state\n");
521 #endif
522
523 /* TODO: support multiple Rx flows */
524 err = dpni_get_rx_flow(dflt_mc_io, MC_CMD_NO_FLAGS,
525 dflt_dpni->dpni_handle, 0, 0, &rx_queue_attr);
526 if (err) {
527 printf("dpni_get_rx_flow() failed\n");
528 goto err_rx_flow;
529 }
530
531 priv->rx_dflt_fqid = rx_queue_attr.fqid;
532
533 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
534 &priv->tx_qdid);
535 if (err) {
536 printf("dpni_get_qdid() failed\n");
537 goto err_qdid;
538 }
539
540 return priv->phydev->link;
541
542 err_qdid:
543 err_rx_flow:
544 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
545 err_dpni_bind:
546 ldpaa_dpbp_free();
547 err_dpbp_setup:
548 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
549 err_dpni_setup:
550 err_dpamc_bind:
551 dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
552 err_dpmac_setup:
553 return err;
554 }
555
556 static void ldpaa_eth_stop(struct eth_device *net_dev)
557 {
558 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
559 int err = 0;
560 #ifdef CONFIG_PHYLIB
561 struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id);
562 #endif
563
564 if ((net_dev->state == ETH_STATE_PASSIVE) ||
565 (net_dev->state == ETH_STATE_INIT))
566 return;
567
568 #ifdef DEBUG
569 ldpaa_eth_get_dpni_counter();
570 ldpaa_eth_get_dpmac_counter(net_dev);
571 #endif
572
573 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
574 dflt_dprc_handle, &dpmac_endpoint);
575 if (err < 0)
576 printf("dprc_disconnect() failed dpmac_endpoint\n");
577
578 err = dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
579 if (err < 0)
580 printf("dpmac_destroy() failed\n");
581
582 /* Stop Tx and Rx traffic */
583 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
584 if (err < 0)
585 printf("dpni_disable() failed\n");
586
587 #ifdef CONFIG_PHYLIB
588 if (priv->phydev && bus != NULL)
589 phy_shutdown(priv->phydev);
590 else {
591 free(priv->phydev);
592 priv->phydev = NULL;
593 }
594 #endif
595
596 ldpaa_dpbp_free();
597 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
598 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
599 }
600
601 static void ldpaa_dpbp_drain_cnt(int count)
602 {
603 uint64_t buf_array[7];
604 void *addr;
605 int ret, i;
606
607 BUG_ON(count > 7);
608
609 do {
610 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
611 dflt_dpbp->dpbp_attr.bpid,
612 buf_array, count);
613 if (ret < 0) {
614 printf("qbman_swp_acquire() failed\n");
615 return;
616 }
617 for (i = 0; i < ret; i++) {
618 addr = (void *)buf_array[i];
619 debug("Free: buffer addr =0x%p\n", addr);
620 free(addr);
621 }
622 } while (ret);
623 }
624
625 static void ldpaa_dpbp_drain(void)
626 {
627 int i;
628 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
629 ldpaa_dpbp_drain_cnt(7);
630 }
631
632 static int ldpaa_bp_add_7(uint16_t bpid)
633 {
634 uint64_t buf_array[7];
635 u8 *addr;
636 int i;
637 struct qbman_release_desc rd;
638
639 for (i = 0; i < 7; i++) {
640 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
641 if (!addr) {
642 printf("addr allocation failed\n");
643 goto err_alloc;
644 }
645 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
646 flush_dcache_range((u64)addr,
647 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
648
649 buf_array[i] = (uint64_t)addr;
650 debug("Release: buffer addr =0x%p\n", addr);
651 }
652
653 release_bufs:
654 /* In case the portal is busy, retry until successful.
655 * This function is guaranteed to succeed in a reasonable amount
656 * of time.
657 */
658
659 do {
660 mdelay(1);
661 qbman_release_desc_clear(&rd);
662 qbman_release_desc_set_bpid(&rd, bpid);
663 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
664
665 return i;
666
667 err_alloc:
668 if (i)
669 goto release_bufs;
670
671 return 0;
672 }
673
674 static int ldpaa_dpbp_seed(uint16_t bpid)
675 {
676 int i;
677 int count;
678
679 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
680 count = ldpaa_bp_add_7(bpid);
681 if (count < 7)
682 printf("Buffer Seed= %d\n", count);
683 }
684
685 return 0;
686 }
687
688 static int ldpaa_dpbp_setup(void)
689 {
690 int err;
691
692 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
693 &dflt_dpbp->dpbp_handle);
694 if (err) {
695 printf("dpbp_open() failed\n");
696 goto err_open;
697 }
698
699 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
700 if (err) {
701 printf("dpbp_enable() failed\n");
702 goto err_enable;
703 }
704
705 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
706 dflt_dpbp->dpbp_handle,
707 &dflt_dpbp->dpbp_attr);
708 if (err) {
709 printf("dpbp_get_attributes() failed\n");
710 goto err_get_attr;
711 }
712
713 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
714 if (err) {
715 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
716 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
717 goto err_seed;
718 }
719
720 return 0;
721
722 err_seed:
723 err_get_attr:
724 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
725 err_enable:
726 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
727 err_open:
728 return err;
729 }
730
731 static void ldpaa_dpbp_free(void)
732 {
733 ldpaa_dpbp_drain();
734 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
735 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
736 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
737 }
738
739 static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
740 struct ldpaa_eth_priv *priv)
741 {
742 struct dpmac_attr attr;
743 int error;
744
745 memset(&attr, 0, sizeof(struct dpmac_attr));
746 error = dpmac_get_attributes(mc_io, MC_CMD_NO_FLAGS,
747 priv->dpmac_handle,
748 &attr);
749 if (error == 0) {
750 if ((attr.version.major != DPMAC_VER_MAJOR) ||
751 (attr.version.minor != DPMAC_VER_MINOR)) {
752 printf("DPMAC version mismatch found %u.%u,",
753 attr.version.major, attr.version.minor);
754 printf("supported version is %u.%u\n",
755 DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
756 }
757 }
758
759 return error;
760 }
761
762 static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
763 {
764 int err = 0;
765 struct dpmac_cfg dpmac_cfg;
766
767 dpmac_cfg.mac_id = priv->dpmac_id;
768 err = dpmac_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpmac_cfg,
769 &priv->dpmac_handle);
770 if (err)
771 printf("dpmac_create() failed\n");
772
773 err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
774 if (err < 0)
775 printf("ldpaa_dpmac_version_check() failed: %d\n", err);
776
777 return err;
778 }
779
780 static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
781 {
782 int err = 0;
783 struct dprc_connection_cfg dprc_connection_cfg = {
784 /* If both rates are zero the connection */
785 /* will be configured in "best effort" mode. */
786 .committed_rate = 0,
787 .max_rate = 0
788 };
789
790 #ifdef DEBUG
791 struct dprc_endpoint dbg_endpoint;
792 int state = 0;
793 #endif
794
795 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
796 strcpy(dpmac_endpoint.type, "dpmac");
797 dpmac_endpoint.id = priv->dpmac_id;
798
799 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
800 strcpy(dpni_endpoint.type, "dpni");
801 dpni_endpoint.id = dflt_dpni->dpni_id;
802
803 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
804 dflt_dprc_handle,
805 &dpmac_endpoint,
806 &dpni_endpoint,
807 &dprc_connection_cfg);
808 if (err)
809 printf("dprc_connect() failed\n");
810
811 #ifdef DEBUG
812 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
813 dflt_dprc_handle, &dpni_endpoint,
814 &dbg_endpoint, &state);
815 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
816 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
817 printf("%s, DPMAC State= %d\n", __func__, state);
818
819 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
820 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
821 dflt_dprc_handle, &dpmac_endpoint,
822 &dbg_endpoint, &state);
823 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
824 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
825 printf("%s, DPNI State= %d\n", __func__, state);
826 #endif
827 return err;
828 }
829
830 static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
831 {
832 int err;
833
834 /* and get a handle for the DPNI this interface is associate with */
835 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
836 &dflt_dpni->dpni_handle);
837 if (err) {
838 printf("dpni_open() failed\n");
839 goto err_open;
840 }
841
842 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
843 dflt_dpni->dpni_handle,
844 &dflt_dpni->dpni_attrs);
845 if (err) {
846 printf("dpni_get_attributes() failed (err=%d)\n", err);
847 goto err_get_attr;
848 }
849
850 /* Configure our buffers' layout */
851 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
852 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
853 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
854 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
855 dflt_dpni->buf_layout.pass_parser_result = true;
856 dflt_dpni->buf_layout.pass_frame_status = true;
857 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
858 /* HW erratum mandates data alignment in multiples of 256 */
859 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
860 /* ...rx, ... */
861 err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
862 dflt_dpni->dpni_handle,
863 &dflt_dpni->buf_layout);
864 if (err) {
865 printf("dpni_set_rx_buffer_layout() failed");
866 goto err_buf_layout;
867 }
868
869 /* ... tx, ... */
870 /* remove Rx-only options */
871 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
872 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
873 err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
874 dflt_dpni->dpni_handle,
875 &dflt_dpni->buf_layout);
876 if (err) {
877 printf("dpni_set_tx_buffer_layout() failed");
878 goto err_buf_layout;
879 }
880
881 /* ... tx-confirm. */
882 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
883 err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
884 dflt_dpni->dpni_handle,
885 &dflt_dpni->buf_layout);
886 if (err) {
887 printf("dpni_set_tx_conf_buffer_layout() failed");
888 goto err_buf_layout;
889 }
890
891 /* Now that we've set our tx buffer layout, retrieve the minimum
892 * required tx data offset.
893 */
894 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
895 dflt_dpni->dpni_handle,
896 &priv->tx_data_offset);
897 if (err) {
898 printf("dpni_get_tx_data_offset() failed\n");
899 goto err_data_offset;
900 }
901
902 /* Warn in case TX data offset is not multiple of 64 bytes. */
903 WARN_ON(priv->tx_data_offset % 64);
904
905 /* Accomodate SWA space. */
906 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
907 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
908
909 return 0;
910
911 err_data_offset:
912 err_buf_layout:
913 err_get_attr:
914 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
915 err_open:
916 return err;
917 }
918
919 static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
920 {
921 struct dpni_pools_cfg pools_params;
922 struct dpni_tx_flow_cfg dflt_tx_flow;
923 struct dpni_tx_conf_cfg tx_conf_cfg;
924 int err = 0;
925
926 memset(&pools_params, 0, sizeof(pools_params));
927 pools_params.num_dpbp = 1;
928 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
929 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
930 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
931 dflt_dpni->dpni_handle, &pools_params);
932 if (err) {
933 printf("dpni_set_pools() failed\n");
934 return err;
935 }
936
937 priv->tx_flow_id = DPNI_NEW_FLOW_ID;
938 memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
939
940 dflt_tx_flow.use_common_tx_conf_queue = 0;
941 err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS,
942 dflt_dpni->dpni_handle, &priv->tx_flow_id,
943 &dflt_tx_flow);
944 if (err) {
945 printf("dpni_set_tx_flow() failed\n");
946 return err;
947 }
948
949 memset(&tx_conf_cfg, 0, sizeof(struct dpni_tx_conf_cfg));
950 tx_conf_cfg.errors_only = true;
951 /*Set tx-conf and error configuration*/
952 err = dpni_set_tx_conf(dflt_mc_io, MC_CMD_NO_FLAGS,
953 dflt_dpni->dpni_handle,
954 priv->tx_flow_id, &tx_conf_cfg);
955 if (err) {
956 printf("dpni_set_tx_conf() failed\n");
957 return err;
958 }
959
960 return 0;
961 }
962
963 static int ldpaa_eth_netdev_init(struct eth_device *net_dev,
964 phy_interface_t enet_if)
965 {
966 int err;
967 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
968
969 sprintf(net_dev->name, "DPMAC%d@%s", priv->dpmac_id,
970 phy_interface_strings[enet_if]);
971
972 net_dev->iobase = 0;
973 net_dev->init = ldpaa_eth_open;
974 net_dev->halt = ldpaa_eth_stop;
975 net_dev->send = ldpaa_eth_tx;
976 net_dev->recv = ldpaa_eth_pull_dequeue_rx;
977
978 #ifdef CONFIG_PHYLIB
979 err = init_phy(net_dev);
980 if (err < 0)
981 return err;
982 #endif
983
984 err = eth_register(net_dev);
985 if (err < 0) {
986 printf("eth_register() = %d\n", err);
987 return err;
988 }
989
990 return 0;
991 }
992
993 int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
994 {
995 struct eth_device *net_dev = NULL;
996 struct ldpaa_eth_priv *priv = NULL;
997 int err = 0;
998
999
1000 /* Net device */
1001 net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
1002 if (!net_dev) {
1003 printf("eth_device malloc() failed\n");
1004 return -ENOMEM;
1005 }
1006 memset(net_dev, 0, sizeof(struct eth_device));
1007
1008 /* alloc the ldpaa ethernet private struct */
1009 priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
1010 if (!priv) {
1011 printf("ldpaa_eth_priv malloc() failed\n");
1012 return -ENOMEM;
1013 }
1014 memset(priv, 0, sizeof(struct ldpaa_eth_priv));
1015
1016 net_dev->priv = (void *)priv;
1017 priv->net_dev = (struct eth_device *)net_dev;
1018 priv->dpmac_id = dpmac_id;
1019 debug("%s dpmac_id=%d\n", __func__, dpmac_id);
1020
1021 err = ldpaa_eth_netdev_init(net_dev, enet_if);
1022 if (err)
1023 goto err_netdev_init;
1024
1025 debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
1026 return 0;
1027
1028 err_netdev_init:
1029 free(priv);
1030 net_dev->priv = NULL;
1031 free(net_dev);
1032
1033 return err;
1034 }