blob: cc949f593ae4a4f8984f18379a9f2c863d9f22d9 [file] [log] [blame]
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -07001/*
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
16#include "ldpaa_eth.h"
17
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -070018#undef CONFIG_PHYLIB
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070019static int init_phy(struct eth_device *dev)
20{
21 /*TODO for external PHY */
22
23 return 0;
24}
25
26static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
27 const struct dpaa_fd *fd)
28{
29 u64 fd_addr;
30 uint16_t fd_offset;
31 uint32_t fd_length;
32 struct ldpaa_fas *fas;
33 uint32_t status, err;
34 struct qbman_release_desc releasedesc;
35 struct qbman_swp *swp = dflt_dpio->sw_portal;
36
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070037 fd_addr = ldpaa_fd_get_addr(fd);
38 fd_offset = ldpaa_fd_get_offset(fd);
39 fd_length = ldpaa_fd_get_len(fd);
40
41 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
42
43 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
44 /* Read the frame annotation status word and check for errors */
45 fas = (struct ldpaa_fas *)
46 ((uint8_t *)(fd_addr) +
47 priv->buf_layout.private_data_size);
48 status = le32_to_cpu(fas->status);
49 if (status & LDPAA_ETH_RX_ERR_MASK) {
50 printf("Rx frame error(s): 0x%08x\n",
51 status & LDPAA_ETH_RX_ERR_MASK);
52 goto error;
53 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
54 printf("Unsupported feature in bitmask: 0x%08x\n",
55 status & LDPAA_ETH_RX_UNSUPP_MASK);
56 goto error;
57 }
58 }
59
60 debug("Rx frame: To Upper layer\n");
61 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
62 fd_length);
63
64error:
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -070065 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070066 qbman_release_desc_clear(&releasedesc);
67 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
68 do {
69 /* Release buffer into the QBMAN */
70 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
71 } while (err == -EBUSY);
72 return;
73}
74
75static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
76{
77 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
78 const struct ldpaa_dq *dq;
79 const struct dpaa_fd *fd;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +053080 int i = 5, err = 0, status;
81 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
82 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070083 static struct qbman_pull_desc pulldesc;
84 struct qbman_swp *swp = dflt_dpio->sw_portal;
85
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070086 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -070087 qbman_pull_desc_clear(&pulldesc);
88 qbman_pull_desc_set_numframes(&pulldesc, 1);
89 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
90
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070091 err = qbman_swp_pull(swp, &pulldesc);
92 if (err < 0) {
93 printf("Dequeue frames error:0x%08x\n", err);
94 continue;
95 }
96
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +053097 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -070098
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +053099 do {
100 dq = qbman_swp_dqrr_next(swp);
101 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700102
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700103 if (dq) {
104 /* Check for valid frame. If not sent a consume
105 * confirmation to QBMAN otherwise give it to NADK
106 * application and then send consume confirmation to
107 * QBMAN.
108 */
109 status = (uint8_t)ldpaa_dq_flags(dq);
110 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
111 debug("Dequeue RX frames:");
112 debug("No frame delivered\n");
113
114 qbman_swp_dqrr_consume(swp, dq);
115 break;
116 }
117
118 fd = ldpaa_dq_fd(dq);
119
120 /* Obtain FD and process it */
121 ldpaa_eth_rx(priv, fd);
122 qbman_swp_dqrr_consume(swp, dq);
123 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530124 } else {
125 err = -ENODATA;
126 debug("No DQRR entries\n");
127 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700128 }
129 }
130
131 return err;
132}
133
134static void ldpaa_eth_tx_conf(struct ldpaa_eth_priv *priv,
135 const struct dpaa_fd *fd)
136{
137 uint64_t fd_addr;
138 struct ldpaa_fas *fas;
139 uint32_t status, err;
140 struct qbman_release_desc releasedesc;
141 struct qbman_swp *swp = dflt_dpio->sw_portal;
142
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700143 fd_addr = ldpaa_fd_get_addr(fd);
144
145
146 debug("TX Conf frame:data addr=0x%p\n", (u64 *)fd_addr);
147
148 /* Check the status from the Frame Annotation */
149 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
150 fas = (struct ldpaa_fas *)
151 ((uint8_t *)(fd_addr) +
152 priv->buf_layout.private_data_size);
153 status = le32_to_cpu(fas->status);
154 if (status & LDPAA_ETH_TXCONF_ERR_MASK) {
155 printf("TxConf frame error(s): 0x%08x\n",
156 status & LDPAA_ETH_TXCONF_ERR_MASK);
157 }
158 }
159
Prabhakar Kushwahaf386a9d2015-07-02 11:28:57 +0530160 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700161 qbman_release_desc_clear(&releasedesc);
162 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
163 do {
164 /* Release buffer into the QBMAN */
165 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
166 } while (err == -EBUSY);
167}
168
169static int ldpaa_eth_pull_dequeue_tx_conf(struct ldpaa_eth_priv *priv)
170{
171 const struct ldpaa_dq *dq;
172 const struct dpaa_fd *fd;
173 int err = 0;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530174 int i = 5, status;
175 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
176 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700177 static struct qbman_pull_desc pulldesc;
178 struct qbman_swp *swp = dflt_dpio->sw_portal;
179
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700180 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700181 qbman_pull_desc_clear(&pulldesc);
182 qbman_pull_desc_set_numframes(&pulldesc, 1);
183 qbman_pull_desc_set_fq(&pulldesc, priv->tx_conf_fqid);
184
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700185 err = qbman_swp_pull(swp, &pulldesc);
186 if (err < 0) {
187 printf("Dequeue TX conf frames error:0x%08x\n", err);
188 continue;
189 }
190
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530191 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700192
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530193 do {
194 dq = qbman_swp_dqrr_next(swp);
195 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700196
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700197 if (dq) {
198 /* Check for valid frame. If not sent a consume
199 * confirmation to QBMAN otherwise give it to NADK
200 * application and then send consume confirmation to
201 * QBMAN.
202 */
203 status = (uint8_t)ldpaa_dq_flags(dq);
204 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
205 debug("Dequeue TX conf frames:");
206 debug("No frame is delivered\n");
207
208 qbman_swp_dqrr_consume(swp, dq);
209 break;
210 }
211 fd = ldpaa_dq_fd(dq);
212
213 ldpaa_eth_tx_conf(priv, fd);
214 qbman_swp_dqrr_consume(swp, dq);
215 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530216 } else {
217 err = -ENODATA;
218 debug("No DQRR entries\n");
219 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700220 }
221 }
222
223 return err;
224}
225
226static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
227{
228 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
229 struct dpaa_fd fd;
230 u64 buffer_start;
231 int data_offset, err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530232 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
233 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700234 struct qbman_swp *swp = dflt_dpio->sw_portal;
235 struct qbman_eq_desc ed;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530236 struct qbman_release_desc releasedesc;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700237
238 /* Setup the FD fields */
239 memset(&fd, 0, sizeof(fd));
240
241 data_offset = priv->tx_data_offset;
242
243 do {
244 err = qbman_swp_acquire(dflt_dpio->sw_portal,
245 dflt_dpbp->dpbp_attr.bpid,
246 &buffer_start, 1);
247 } while (err == -EBUSY);
248
249 if (err < 0) {
250 printf("qbman_swp_acquire() failed\n");
251 return -ENOMEM;
252 }
253
254 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
255
256 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
257
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700258 flush_dcache_range(buffer_start, buffer_start +
259 LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700260
261 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
262 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
263 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
264 ldpaa_fd_set_len(&fd, len);
265
266 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
267 LDPAA_FD_CTRL_PTV1;
268
269 qbman_eq_desc_clear(&ed);
270 qbman_eq_desc_set_no_orp(&ed, 0);
271 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530272
273 time_start = get_timer(0);
274
275 while (get_timer(time_start) < timeo) {
276 err = qbman_swp_enqueue(swp, &ed,
277 (const struct qbman_fd *)(&fd));
278 if (err != -EBUSY)
279 break;
280 }
281
282 if (err < 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700283 printf("error enqueueing Tx frame\n");
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530284 goto error;
285 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700286
287 mdelay(1);
288
289 err = ldpaa_eth_pull_dequeue_tx_conf(priv);
290 if (err < 0)
291 printf("error Tx Conf frame\n");
292
293 return err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530294
295error:
296 qbman_release_desc_clear(&releasedesc);
297 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
298 time_start = get_timer(0);
299 do {
300 /* Release buffer into the QBMAN */
301 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
302 } while (get_timer(time_start) < timeo && err == -EBUSY);
303
304 if (err == -EBUSY)
305 printf("TX data: QBMAN buffer release fails\n");
306
307 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700308}
309
310static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
311{
312 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
313 struct dpni_queue_attr rx_queue_attr;
314 struct dpni_tx_flow_attr tx_flow_attr;
315 uint8_t mac_addr[6];
316 int err;
317
318 if (net_dev->state == ETH_STATE_ACTIVE)
319 return 0;
320
321 /* DPNI initialization */
322 err = ldpaa_dpni_setup(priv);
323 if (err < 0)
324 goto err_dpni_setup;
325
326 err = ldpaa_dpbp_setup();
327 if (err < 0)
328 goto err_dpbp_setup;
329
330 /* DPNI binding DPBP */
331 err = ldpaa_dpni_bind(priv);
332 if (err)
333 goto err_bind;
334
335 err = dpni_get_primary_mac_addr(dflt_mc_io, priv->dpni_handle,
336 mac_addr);
337 if (err) {
338 printf("dpni_get_primary_mac_addr() failed\n");
339 return err;
340 }
341
342 memcpy(net_dev->enetaddr, mac_addr, 0x6);
343
344 /* setup the MAC address */
345 if (net_dev->enetaddr[0] & 0x01) {
346 printf("%s: MacAddress is multcast address\n", __func__);
347 return 1;
348 }
349
350#ifdef CONFIG_PHYLIB
351 /* TODO Check this path */
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700352 err = phy_startup(priv->phydev);
353 if (err) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700354 printf("%s: Could not initialize\n", priv->phydev->dev->name);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700355 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700356 }
357#else
358 priv->phydev->speed = SPEED_1000;
359 priv->phydev->link = 1;
360 priv->phydev->duplex = DUPLEX_FULL;
361#endif
362
363 err = dpni_enable(dflt_mc_io, priv->dpni_handle);
364 if (err < 0) {
365 printf("dpni_enable() failed\n");
366 return err;
367 }
368
369 /* TODO: support multiple Rx flows */
370 err = dpni_get_rx_flow(dflt_mc_io, priv->dpni_handle, 0, 0,
371 &rx_queue_attr);
372 if (err) {
373 printf("dpni_get_rx_flow() failed\n");
374 goto err_rx_flow;
375 }
376
377 priv->rx_dflt_fqid = rx_queue_attr.fqid;
378
379 err = dpni_get_qdid(dflt_mc_io, priv->dpni_handle, &priv->tx_qdid);
380 if (err) {
381 printf("dpni_get_qdid() failed\n");
382 goto err_qdid;
383 }
384
385 err = dpni_get_tx_flow(dflt_mc_io, priv->dpni_handle, priv->tx_flow_id,
386 &tx_flow_attr);
387 if (err) {
388 printf("dpni_get_tx_flow() failed\n");
389 goto err_tx_flow;
390 }
391
392 priv->tx_conf_fqid = tx_flow_attr.conf_err_attr.queue_attr.fqid;
393
394 if (!priv->phydev->link)
395 printf("%s: No link.\n", priv->phydev->dev->name);
396
397 return priv->phydev->link ? 0 : -1;
398
399err_tx_flow:
400err_qdid:
401err_rx_flow:
402 dpni_disable(dflt_mc_io, priv->dpni_handle);
403err_bind:
404 ldpaa_dpbp_free();
405err_dpbp_setup:
406 dpni_close(dflt_mc_io, priv->dpni_handle);
407err_dpni_setup:
408 return err;
409}
410
411static void ldpaa_eth_stop(struct eth_device *net_dev)
412{
413 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
414 int err = 0;
415
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700416 if ((net_dev->state == ETH_STATE_PASSIVE) ||
417 (net_dev->state == ETH_STATE_INIT))
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700418 return;
419 /* Stop Tx and Rx traffic */
420 err = dpni_disable(dflt_mc_io, priv->dpni_handle);
421 if (err < 0)
422 printf("dpni_disable() failed\n");
423
424#ifdef CONFIG_PHYLIB
425 phy_shutdown(priv->phydev);
426#endif
427
428 ldpaa_dpbp_free();
429 dpni_reset(dflt_mc_io, priv->dpni_handle);
430 dpni_close(dflt_mc_io, priv->dpni_handle);
431}
432
433static void ldpaa_dpbp_drain_cnt(int count)
434{
435 uint64_t buf_array[7];
436 void *addr;
437 int ret, i;
438
439 BUG_ON(count > 7);
440
441 do {
442 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
443 dflt_dpbp->dpbp_attr.bpid,
444 buf_array, count);
445 if (ret < 0) {
446 printf("qbman_swp_acquire() failed\n");
447 return;
448 }
449 for (i = 0; i < ret; i++) {
450 addr = (void *)buf_array[i];
451 debug("Free: buffer addr =0x%p\n", addr);
452 free(addr);
453 }
454 } while (ret);
455}
456
457static void ldpaa_dpbp_drain(void)
458{
459 int i;
460 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
461 ldpaa_dpbp_drain_cnt(7);
462}
463
464static int ldpaa_bp_add_7(uint16_t bpid)
465{
466 uint64_t buf_array[7];
467 u8 *addr;
468 int i;
469 struct qbman_release_desc rd;
470
471 for (i = 0; i < 7; i++) {
472 addr = memalign(L1_CACHE_BYTES, LDPAA_ETH_RX_BUFFER_SIZE);
473 if (!addr) {
474 printf("addr allocation failed\n");
475 goto err_alloc;
476 }
477 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700478 flush_dcache_range((u64)addr,
479 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700480
481 buf_array[i] = (uint64_t)addr;
482 debug("Release: buffer addr =0x%p\n", addr);
483 }
484
485release_bufs:
486 /* In case the portal is busy, retry until successful.
487 * This function is guaranteed to succeed in a reasonable amount
488 * of time.
489 */
490
491 do {
492 mdelay(1);
493 qbman_release_desc_clear(&rd);
494 qbman_release_desc_set_bpid(&rd, bpid);
495 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
496
497 return i;
498
499err_alloc:
500 if (i)
501 goto release_bufs;
502
503 return 0;
504}
505
506static int ldpaa_dpbp_seed(uint16_t bpid)
507{
508 int i;
509 int count;
510
511 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
512 count = ldpaa_bp_add_7(bpid);
513 if (count < 7)
514 printf("Buffer Seed= %d\n", count);
515 }
516
517 return 0;
518}
519
520static int ldpaa_dpbp_setup(void)
521{
522 int err;
523
524 err = dpbp_open(dflt_mc_io, dflt_dpbp->dpbp_attr.id,
525 &dflt_dpbp->dpbp_handle);
526 if (err) {
527 printf("dpbp_open() failed\n");
528 goto err_open;
529 }
530
531 err = dpbp_enable(dflt_mc_io, dflt_dpbp->dpbp_handle);
532 if (err) {
533 printf("dpbp_enable() failed\n");
534 goto err_enable;
535 }
536
537 err = dpbp_get_attributes(dflt_mc_io, dflt_dpbp->dpbp_handle,
538 &dflt_dpbp->dpbp_attr);
539 if (err) {
540 printf("dpbp_get_attributes() failed\n");
541 goto err_get_attr;
542 }
543
544 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
545 if (err) {
546 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
547 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
548 goto err_seed;
549 }
550
551 return 0;
552
553err_seed:
554err_get_attr:
555 dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle);
556err_enable:
557 dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle);
558err_open:
559 return err;
560}
561
562static void ldpaa_dpbp_free(void)
563{
564 ldpaa_dpbp_drain();
565 dpbp_disable(dflt_mc_io, dflt_dpbp->dpbp_handle);
566 dpbp_reset(dflt_mc_io, dflt_dpbp->dpbp_handle);
567 dpbp_close(dflt_mc_io, dflt_dpbp->dpbp_handle);
568}
569
570static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
571{
572 int err;
573
574 /* and get a handle for the DPNI this interface is associate with */
575 err = dpni_open(dflt_mc_io, priv->dpni_id, &priv->dpni_handle);
576 if (err) {
577 printf("dpni_open() failed\n");
578 goto err_open;
579 }
580
581 err = dpni_get_attributes(dflt_mc_io, priv->dpni_handle,
582 &priv->dpni_attrs);
583 if (err) {
584 printf("dpni_get_attributes() failed (err=%d)\n", err);
585 goto err_get_attr;
586 }
587
588 /* Configure our buffers' layout */
589 priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
590 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
591 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
592 priv->buf_layout.pass_parser_result = true;
593 priv->buf_layout.pass_frame_status = true;
594 priv->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
595 /* ...rx, ... */
596 err = dpni_set_rx_buffer_layout(dflt_mc_io, priv->dpni_handle,
597 &priv->buf_layout);
598 if (err) {
599 printf("dpni_set_rx_buffer_layout() failed");
600 goto err_buf_layout;
601 }
602
603 /* ... tx, ... */
604 priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PARSER_RESULT;
605 err = dpni_set_tx_buffer_layout(dflt_mc_io, priv->dpni_handle,
606 &priv->buf_layout);
607 if (err) {
608 printf("dpni_set_tx_buffer_layout() failed");
609 goto err_buf_layout;
610 }
611
612 /* ... tx-confirm. */
613 priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
614 err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, priv->dpni_handle,
615 &priv->buf_layout);
616 if (err) {
617 printf("dpni_set_tx_conf_buffer_layout() failed");
618 goto err_buf_layout;
619 }
620
621 /* Now that we've set our tx buffer layout, retrieve the minimum
622 * required tx data offset.
623 */
624 err = dpni_get_tx_data_offset(dflt_mc_io, priv->dpni_handle,
625 &priv->tx_data_offset);
626 if (err) {
627 printf("dpni_get_tx_data_offset() failed\n");
628 goto err_data_offset;
629 }
630
631 /* Warn in case TX data offset is not multiple of 64 bytes. */
632 WARN_ON(priv->tx_data_offset % 64);
633
634 /* Accomodate SWA space. */
635 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
636 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
637
638 return 0;
639
640err_data_offset:
641err_buf_layout:
642err_get_attr:
643 dpni_close(dflt_mc_io, priv->dpni_handle);
644err_open:
645 return err;
646}
647
648static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
649{
650 struct dpni_pools_cfg pools_params;
651 struct dpni_tx_flow_cfg dflt_tx_flow;
652 int err = 0;
653
654 pools_params.num_dpbp = 1;
655 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
656 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
657 err = dpni_set_pools(dflt_mc_io, priv->dpni_handle, &pools_params);
658 if (err) {
659 printf("dpni_set_pools() failed\n");
660 return err;
661 }
662
663 priv->tx_flow_id = DPNI_NEW_FLOW_ID;
664 memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
665
666 err = dpni_set_tx_flow(dflt_mc_io, priv->dpni_handle,
667 &priv->tx_flow_id, &dflt_tx_flow);
668 if (err) {
669 printf("dpni_set_tx_flow() failed\n");
670 return err;
671 }
672
673 return 0;
674}
675
676static int ldpaa_eth_netdev_init(struct eth_device *net_dev)
677{
678 int err;
679 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
680
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700681 sprintf(net_dev->name, "DPNI%d", priv->dpni_id);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700682
683 net_dev->iobase = 0;
684 net_dev->init = ldpaa_eth_open;
685 net_dev->halt = ldpaa_eth_stop;
686 net_dev->send = ldpaa_eth_tx;
687 net_dev->recv = ldpaa_eth_pull_dequeue_rx;
688/*
689 TODO: PHY MDIO information
690 priv->bus = info->bus;
691 priv->phyaddr = info->phy_addr;
692 priv->enet_if = info->enet_if;
693*/
694
695 if (init_phy(net_dev))
696 return 0;
697
698 err = eth_register(net_dev);
699 if (err < 0) {
700 printf("eth_register() = %d\n", err);
701 return err;
702 }
703
704 return 0;
705}
706
707int ldpaa_eth_init(struct dprc_obj_desc obj_desc)
708{
709 struct eth_device *net_dev = NULL;
710 struct ldpaa_eth_priv *priv = NULL;
711 int err = 0;
712
713
714 /* Net device */
715 net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
716 if (!net_dev) {
717 printf("eth_device malloc() failed\n");
718 return -ENOMEM;
719 }
720 memset(net_dev, 0, sizeof(struct eth_device));
721
722 /* alloc the ldpaa ethernet private struct */
723 priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
724 if (!priv) {
725 printf("ldpaa_eth_priv malloc() failed\n");
726 return -ENOMEM;
727 }
728 memset(priv, 0, sizeof(struct ldpaa_eth_priv));
729
730 net_dev->priv = (void *)priv;
731 priv->net_dev = (struct eth_device *)net_dev;
732 priv->dpni_id = obj_desc.id;
733
734 err = ldpaa_eth_netdev_init(net_dev);
735 if (err)
736 goto err_netdev_init;
737
738 debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
739 return 0;
740
741err_netdev_init:
742 free(priv);
743 net_dev->priv = NULL;
744 free(net_dev);
745
746 return err;
747}