blob: 09163a65aa0146a8a95536cd1e35caed4fa4ee22 [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>
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +053015#include <fsl-mc/fsl_dpmac.h>
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070016
17#include "ldpaa_eth.h"
18
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -070019#undef CONFIG_PHYLIB
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -070020static int init_phy(struct eth_device *dev)
21{
22 /*TODO for external PHY */
23
24 return 0;
25}
26
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +053027#ifdef DEBUG
28static void ldpaa_eth_get_dpni_counter(void)
29{
30 int err = 0;
31 u64 value;
32
33 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
34 dflt_dpni->dpni_handle,
35 DPNI_CNT_ING_FRAME,
36 &value);
37 if (err < 0) {
38 printf("dpni_get_counter: DPNI_CNT_ING_FRAME failed\n");
39 return;
40 }
41 printf("DPNI_CNT_ING_FRAME=%lld\n", value);
42
43 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
44 dflt_dpni->dpni_handle,
45 DPNI_CNT_ING_BYTE,
46 &value);
47 if (err < 0) {
48 printf("dpni_get_counter: DPNI_CNT_ING_BYTE failed\n");
49 return;
50 }
51 printf("DPNI_CNT_ING_BYTE=%lld\n", value);
52
53 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
54 dflt_dpni->dpni_handle,
55 DPNI_CNT_ING_FRAME_DROP ,
56 &value);
57 if (err < 0) {
58 printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DROP failed\n");
59 return;
60 }
61 printf("DPNI_CNT_ING_FRAME_DROP =%lld\n", value);
62
63 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
64 dflt_dpni->dpni_handle,
65 DPNI_CNT_ING_FRAME_DISCARD,
66 &value);
67 if (err < 0) {
68 printf("dpni_get_counter: DPNI_CNT_ING_FRAME_DISCARD failed\n");
69 return;
70 }
71 printf("DPNI_CNT_ING_FRAME_DISCARD=%lld\n", value);
72
73 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
74 dflt_dpni->dpni_handle,
75 DPNI_CNT_EGR_FRAME,
76 &value);
77 if (err < 0) {
78 printf("dpni_get_counter: DPNI_CNT_EGR_FRAME failed\n");
79 return;
80 }
81 printf("DPNI_CNT_EGR_FRAME=%lld\n", value);
82
83 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
84 dflt_dpni->dpni_handle,
85 DPNI_CNT_EGR_BYTE ,
86 &value);
87 if (err < 0) {
88 printf("dpni_get_counter: DPNI_CNT_EGR_BYTE failed\n");
89 return;
90 }
91 printf("DPNI_CNT_EGR_BYTE =%lld\n", value);
92
93 err = dpni_get_counter(dflt_mc_io, MC_CMD_NO_FLAGS,
94 dflt_dpni->dpni_handle,
95 DPNI_CNT_EGR_FRAME_DISCARD ,
96 &value);
97 if (err < 0) {
98 printf("dpni_get_counter: DPNI_CNT_EGR_FRAME_DISCARD failed\n");
99 return;
100 }
101 printf("DPNI_CNT_EGR_FRAME_DISCARD =%lld\n", value);
102}
103#endif
104
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700105static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv,
106 const struct dpaa_fd *fd)
107{
108 u64 fd_addr;
109 uint16_t fd_offset;
110 uint32_t fd_length;
111 struct ldpaa_fas *fas;
112 uint32_t status, err;
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530113 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
114 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700115 struct qbman_release_desc releasedesc;
116 struct qbman_swp *swp = dflt_dpio->sw_portal;
117
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700118 fd_addr = ldpaa_fd_get_addr(fd);
119 fd_offset = ldpaa_fd_get_offset(fd);
120 fd_length = ldpaa_fd_get_len(fd);
121
122 debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length);
123
124 if (fd->simple.frc & LDPAA_FD_FRC_FASV) {
125 /* Read the frame annotation status word and check for errors */
126 fas = (struct ldpaa_fas *)
127 ((uint8_t *)(fd_addr) +
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530128 dflt_dpni->buf_layout.private_data_size);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700129 status = le32_to_cpu(fas->status);
130 if (status & LDPAA_ETH_RX_ERR_MASK) {
131 printf("Rx frame error(s): 0x%08x\n",
132 status & LDPAA_ETH_RX_ERR_MASK);
133 goto error;
134 } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) {
135 printf("Unsupported feature in bitmask: 0x%08x\n",
136 status & LDPAA_ETH_RX_UNSUPP_MASK);
137 goto error;
138 }
139 }
140
141 debug("Rx frame: To Upper layer\n");
142 net_process_received_packet((uint8_t *)(fd_addr) + fd_offset,
143 fd_length);
144
145error:
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700146 flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700147 qbman_release_desc_clear(&releasedesc);
148 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530149 time_start = get_timer(0);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700150 do {
151 /* Release buffer into the QBMAN */
152 err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1);
Prabhakar Kushwahac7d10d82015-07-02 11:29:08 +0530153 } while (get_timer(time_start) < timeo && err == -EBUSY);
154
155 if (err == -EBUSY)
156 printf("Rx frame: QBMAN buffer release fails\n");
157
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700158 return;
159}
160
161static int ldpaa_eth_pull_dequeue_rx(struct eth_device *dev)
162{
163 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
164 const struct ldpaa_dq *dq;
165 const struct dpaa_fd *fd;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530166 int i = 5, err = 0, status;
167 u32 timeo = (CONFIG_SYS_HZ * 2) / 1000;
168 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700169 static struct qbman_pull_desc pulldesc;
170 struct qbman_swp *swp = dflt_dpio->sw_portal;
171
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700172 while (--i) {
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700173 qbman_pull_desc_clear(&pulldesc);
174 qbman_pull_desc_set_numframes(&pulldesc, 1);
175 qbman_pull_desc_set_fq(&pulldesc, priv->rx_dflt_fqid);
176
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700177 err = qbman_swp_pull(swp, &pulldesc);
178 if (err < 0) {
179 printf("Dequeue frames error:0x%08x\n", err);
180 continue;
181 }
182
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530183 time_start = get_timer(0);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700184
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530185 do {
186 dq = qbman_swp_dqrr_next(swp);
187 } while (get_timer(time_start) < timeo && !dq);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700188
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700189 if (dq) {
190 /* Check for valid frame. If not sent a consume
191 * confirmation to QBMAN otherwise give it to NADK
192 * application and then send consume confirmation to
193 * QBMAN.
194 */
195 status = (uint8_t)ldpaa_dq_flags(dq);
196 if ((status & LDPAA_DQ_STAT_VALIDFRAME) == 0) {
197 debug("Dequeue RX frames:");
198 debug("No frame delivered\n");
199
200 qbman_swp_dqrr_consume(swp, dq);
Prabhakar Kushwaha37ed1a62015-07-02 11:29:07 +0530201 continue;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700202 }
203
204 fd = ldpaa_dq_fd(dq);
205
206 /* Obtain FD and process it */
207 ldpaa_eth_rx(priv, fd);
208 qbman_swp_dqrr_consume(swp, dq);
209 break;
Prabhakar Kushwahabe0c9552015-07-02 11:29:06 +0530210 } else {
211 err = -ENODATA;
212 debug("No DQRR entries\n");
213 break;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700214 }
215 }
216
217 return err;
218}
219
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700220static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len)
221{
222 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
223 struct dpaa_fd fd;
224 u64 buffer_start;
225 int data_offset, err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530226 u32 timeo = (CONFIG_SYS_HZ * 10) / 1000;
227 u32 time_start;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700228 struct qbman_swp *swp = dflt_dpio->sw_portal;
229 struct qbman_eq_desc ed;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530230 struct qbman_release_desc releasedesc;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700231
232 /* Setup the FD fields */
233 memset(&fd, 0, sizeof(fd));
234
235 data_offset = priv->tx_data_offset;
236
237 do {
238 err = qbman_swp_acquire(dflt_dpio->sw_portal,
239 dflt_dpbp->dpbp_attr.bpid,
240 &buffer_start, 1);
241 } while (err == -EBUSY);
242
243 if (err < 0) {
244 printf("qbman_swp_acquire() failed\n");
245 return -ENOMEM;
246 }
247
248 debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start);
249
250 memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len);
251
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700252 flush_dcache_range(buffer_start, buffer_start +
253 LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700254
255 ldpaa_fd_set_addr(&fd, (u64)buffer_start);
256 ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset));
257 ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid);
258 ldpaa_fd_set_len(&fd, len);
259
260 fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA |
261 LDPAA_FD_CTRL_PTV1;
262
263 qbman_eq_desc_clear(&ed);
264 qbman_eq_desc_set_no_orp(&ed, 0);
265 qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0);
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530266
267 time_start = get_timer(0);
268
269 while (get_timer(time_start) < timeo) {
270 err = qbman_swp_enqueue(swp, &ed,
271 (const struct qbman_fd *)(&fd));
272 if (err != -EBUSY)
273 break;
274 }
275
276 if (err < 0) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700277 printf("error enqueueing Tx frame\n");
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530278 goto error;
279 }
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700280
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700281 return err;
Prabhakar Kushwaha20c30102015-07-02 11:29:05 +0530282
283error:
284 qbman_release_desc_clear(&releasedesc);
285 qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid);
286 time_start = get_timer(0);
287 do {
288 /* Release buffer into the QBMAN */
289 err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1);
290 } while (get_timer(time_start) < timeo && err == -EBUSY);
291
292 if (err == -EBUSY)
293 printf("TX data: QBMAN buffer release fails\n");
294
295 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700296}
297
298static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
299{
300 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
301 struct dpni_queue_attr rx_queue_attr;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530302 struct dpmac_link_state dpmac_link_state = { 0 };
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530303#ifdef DEBUG
304 struct dpni_link_state link_state;
305#endif
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700306 int err;
307
308 if (net_dev->state == ETH_STATE_ACTIVE)
309 return 0;
310
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530311 if (get_mc_boot_status() != 0) {
312 printf("ERROR (MC is not booted)\n");
313 return -ENODEV;
314 }
315
316 if (get_dpl_apply_status() == 0) {
317 printf("ERROR (DPL is deployed. No device available)\n");
318 return -ENODEV;
319 }
320 /* DPMAC initialization */
321 err = ldpaa_dpmac_setup(priv);
322 if (err < 0)
323 goto err_dpmac_setup;
324
325 /* DPMAC binding DPNI */
326 err = ldpaa_dpmac_bind(priv);
327 if (err)
328 goto err_dpamc_bind;
329
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700330 /* DPNI initialization */
331 err = ldpaa_dpni_setup(priv);
332 if (err < 0)
333 goto err_dpni_setup;
334
335 err = ldpaa_dpbp_setup();
336 if (err < 0)
337 goto err_dpbp_setup;
338
339 /* DPNI binding DPBP */
340 err = ldpaa_dpni_bind(priv);
341 if (err)
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530342 goto err_dpni_bind;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700343
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530344 err = dpni_add_mac_addr(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530345 dflt_dpni->dpni_handle, net_dev->enetaddr);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700346 if (err) {
Prabhakar Kushwahad2c20a32015-10-07 16:29:58 +0530347 printf("dpni_add_mac_addr() failed\n");
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700348 return err;
349 }
350
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700351#ifdef CONFIG_PHYLIB
352 /* TODO Check this path */
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700353 err = phy_startup(priv->phydev);
354 if (err) {
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700355 printf("%s: Could not initialize\n", priv->phydev->dev->name);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700356 return err;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700357 }
358#else
359 priv->phydev->speed = SPEED_1000;
360 priv->phydev->link = 1;
361 priv->phydev->duplex = DUPLEX_FULL;
362#endif
363
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530364 err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700365 if (err < 0) {
366 printf("dpni_enable() failed\n");
367 return err;
368 }
369
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530370 dpmac_link_state.rate = SPEED_1000;
371 dpmac_link_state.options = DPMAC_LINK_OPT_AUTONEG;
372 dpmac_link_state.up = 1;
373 err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
374 priv->dpmac_handle, &dpmac_link_state);
375 if (err < 0) {
376 printf("dpmac_set_link_state() failed\n");
377 return err;
378 }
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530379
380#ifdef DEBUG
381 err = dpni_get_link_state(dflt_mc_io, MC_CMD_NO_FLAGS,
382 dflt_dpni->dpni_handle, &link_state);
383 if (err < 0) {
384 printf("dpni_get_link_state() failed\n");
385 return err;
386 }
387
388 printf("link status: %d - ", link_state.up);
389 link_state.up == 0 ? printf("down\n") :
390 link_state.up == 1 ? printf("up\n") : printf("error state\n");
391#endif
392
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700393 /* TODO: support multiple Rx flows */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530394 err = dpni_get_rx_flow(dflt_mc_io, MC_CMD_NO_FLAGS,
395 dflt_dpni->dpni_handle, 0, 0, &rx_queue_attr);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700396 if (err) {
397 printf("dpni_get_rx_flow() failed\n");
398 goto err_rx_flow;
399 }
400
401 priv->rx_dflt_fqid = rx_queue_attr.fqid;
402
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530403 err = dpni_get_qdid(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle,
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530404 &priv->tx_qdid);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700405 if (err) {
406 printf("dpni_get_qdid() failed\n");
407 goto err_qdid;
408 }
409
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700410 if (!priv->phydev->link)
411 printf("%s: No link.\n", priv->phydev->dev->name);
412
413 return priv->phydev->link ? 0 : -1;
414
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700415err_qdid:
416err_rx_flow:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530417 dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
418err_dpni_bind:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700419 ldpaa_dpbp_free();
420err_dpbp_setup:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530421err_dpamc_bind:
422 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700423err_dpni_setup:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530424err_dpmac_setup:
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700425 return err;
426}
427
428static void ldpaa_eth_stop(struct eth_device *net_dev)
429{
430 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
431 int err = 0;
432
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700433 if ((net_dev->state == ETH_STATE_PASSIVE) ||
434 (net_dev->state == ETH_STATE_INIT))
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700435 return;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530436
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530437#ifdef DEBUG
438 ldpaa_eth_get_dpni_counter();
439#endif
440
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530441 err = dprc_disconnect(dflt_mc_io, MC_CMD_NO_FLAGS,
442 dflt_dprc_handle, &dpmac_endpoint);
443 if (err < 0)
444 printf("dprc_disconnect() failed dpmac_endpoint\n");
445
446 err = dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
447 if (err < 0)
448 printf("dpmac_destroy() failed\n");
449
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700450 /* Stop Tx and Rx traffic */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530451 err = dpni_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700452 if (err < 0)
453 printf("dpni_disable() failed\n");
454
455#ifdef CONFIG_PHYLIB
456 phy_shutdown(priv->phydev);
457#endif
458
459 ldpaa_dpbp_free();
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530460 dpni_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
461 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700462}
463
464static void ldpaa_dpbp_drain_cnt(int count)
465{
466 uint64_t buf_array[7];
467 void *addr;
468 int ret, i;
469
470 BUG_ON(count > 7);
471
472 do {
473 ret = qbman_swp_acquire(dflt_dpio->sw_portal,
474 dflt_dpbp->dpbp_attr.bpid,
475 buf_array, count);
476 if (ret < 0) {
477 printf("qbman_swp_acquire() failed\n");
478 return;
479 }
480 for (i = 0; i < ret; i++) {
481 addr = (void *)buf_array[i];
482 debug("Free: buffer addr =0x%p\n", addr);
483 free(addr);
484 }
485 } while (ret);
486}
487
488static void ldpaa_dpbp_drain(void)
489{
490 int i;
491 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7)
492 ldpaa_dpbp_drain_cnt(7);
493}
494
495static int ldpaa_bp_add_7(uint16_t bpid)
496{
497 uint64_t buf_array[7];
498 u8 *addr;
499 int i;
500 struct qbman_release_desc rd;
501
502 for (i = 0; i < 7; i++) {
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530503 addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700504 if (!addr) {
505 printf("addr allocation failed\n");
506 goto err_alloc;
507 }
508 memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE);
Prabhakar Kushwahadbe0f2a2015-03-20 19:28:15 -0700509 flush_dcache_range((u64)addr,
510 (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE));
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700511
512 buf_array[i] = (uint64_t)addr;
513 debug("Release: buffer addr =0x%p\n", addr);
514 }
515
516release_bufs:
517 /* In case the portal is busy, retry until successful.
518 * This function is guaranteed to succeed in a reasonable amount
519 * of time.
520 */
521
522 do {
523 mdelay(1);
524 qbman_release_desc_clear(&rd);
525 qbman_release_desc_set_bpid(&rd, bpid);
526 } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i));
527
528 return i;
529
530err_alloc:
531 if (i)
532 goto release_bufs;
533
534 return 0;
535}
536
537static int ldpaa_dpbp_seed(uint16_t bpid)
538{
539 int i;
540 int count;
541
542 for (i = 0; i < LDPAA_ETH_NUM_BUFS; i += 7) {
543 count = ldpaa_bp_add_7(bpid);
544 if (count < 7)
545 printf("Buffer Seed= %d\n", count);
546 }
547
548 return 0;
549}
550
551static int ldpaa_dpbp_setup(void)
552{
553 int err;
554
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530555 err = dpbp_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_attr.id,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700556 &dflt_dpbp->dpbp_handle);
557 if (err) {
558 printf("dpbp_open() failed\n");
559 goto err_open;
560 }
561
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530562 err = dpbp_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700563 if (err) {
564 printf("dpbp_enable() failed\n");
565 goto err_enable;
566 }
567
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530568 err = dpbp_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
569 dflt_dpbp->dpbp_handle,
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700570 &dflt_dpbp->dpbp_attr);
571 if (err) {
572 printf("dpbp_get_attributes() failed\n");
573 goto err_get_attr;
574 }
575
576 err = ldpaa_dpbp_seed(dflt_dpbp->dpbp_attr.bpid);
577 if (err) {
578 printf("Buffer seeding failed for DPBP %d (bpid=%d)\n",
579 dflt_dpbp->dpbp_attr.id, dflt_dpbp->dpbp_attr.bpid);
580 goto err_seed;
581 }
582
583 return 0;
584
585err_seed:
586err_get_attr:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530587 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700588err_enable:
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530589 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700590err_open:
591 return err;
592}
593
594static void ldpaa_dpbp_free(void)
595{
596 ldpaa_dpbp_drain();
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530597 dpbp_disable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
598 dpbp_reset(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
599 dpbp_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpbp->dpbp_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700600}
601
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530602static int ldpaa_dpmac_version_check(struct fsl_mc_io *mc_io,
603 struct ldpaa_eth_priv *priv)
604{
605 struct dpmac_attr attr;
606 int error;
607
608 memset(&attr, 0, sizeof(struct dpmac_attr));
609 error = dpmac_get_attributes(mc_io, MC_CMD_NO_FLAGS,
610 priv->dpmac_handle,
611 &attr);
612 if (error == 0) {
613 if ((attr.version.major != DPMAC_VER_MAJOR) ||
614 (attr.version.minor != DPMAC_VER_MINOR)) {
615 printf("DPMAC version mismatch found %u.%u,",
616 attr.version.major, attr.version.minor);
617 printf("supported version is %u.%u\n",
618 DPMAC_VER_MAJOR, DPMAC_VER_MINOR);
619 }
620 }
621
622 return error;
623}
624
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530625static int ldpaa_dpmac_setup(struct ldpaa_eth_priv *priv)
626{
627 int err = 0;
628 struct dpmac_cfg dpmac_cfg;
629
630 dpmac_cfg.mac_id = priv->dpmac_id;
631 err = dpmac_create(dflt_mc_io, MC_CMD_NO_FLAGS, &dpmac_cfg,
632 &priv->dpmac_handle);
633 if (err)
634 printf("dpmac_create() failed\n");
Prabhakar Kushwaha0a4156c2015-12-24 15:32:37 +0530635
636 err = ldpaa_dpmac_version_check(dflt_mc_io, priv);
637 if (err < 0)
638 printf("ldpaa_dpmac_version_check() failed: %d\n", err);
639
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530640 return err;
641}
642
643static int ldpaa_dpmac_bind(struct ldpaa_eth_priv *priv)
644{
645 int err = 0;
646 struct dprc_connection_cfg dprc_connection_cfg = {
647 /* If both rates are zero the connection */
648 /* will be configured in "best effort" mode. */
649 .committed_rate = 0,
650 .max_rate = 0
651 };
652
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530653#ifdef DEBUG
654 struct dprc_endpoint dbg_endpoint;
655 int state = 0;
656#endif
657
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530658 memset(&dpmac_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000659 strcpy(dpmac_endpoint.type, "dpmac");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530660 dpmac_endpoint.id = priv->dpmac_id;
661
662 memset(&dpni_endpoint, 0, sizeof(struct dprc_endpoint));
Ben Whitten34fd6c92015-12-30 13:05:58 +0000663 strcpy(dpni_endpoint.type, "dpni");
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530664 dpni_endpoint.id = dflt_dpni->dpni_id;
665
666 err = dprc_connect(dflt_mc_io, MC_CMD_NO_FLAGS,
667 dflt_dprc_handle,
668 &dpmac_endpoint,
669 &dpni_endpoint,
670 &dprc_connection_cfg);
Prabhakar Kushwahab4af96f2015-11-04 12:26:01 +0530671 if (err)
672 printf("dprc_connect() failed\n");
673
674#ifdef DEBUG
675 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
676 dflt_dprc_handle, &dpni_endpoint,
677 &dbg_endpoint, &state);
678 printf("%s, DPMAC Type= %s\n", __func__, dbg_endpoint.type);
679 printf("%s, DPMAC ID= %d\n", __func__, dbg_endpoint.id);
680 printf("%s, DPMAC State= %d\n", __func__, state);
681
682 memset(&dbg_endpoint, 0, sizeof(struct dprc_endpoint));
683 err = dprc_get_connection(dflt_mc_io, MC_CMD_NO_FLAGS,
684 dflt_dprc_handle, &dpmac_endpoint,
685 &dbg_endpoint, &state);
686 printf("%s, DPNI Type= %s\n", __func__, dbg_endpoint.type);
687 printf("%s, DPNI ID= %d\n", __func__, dbg_endpoint.id);
688 printf("%s, DPNI State= %d\n", __func__, state);
689#endif
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530690 return err;
691}
692
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700693static int ldpaa_dpni_setup(struct ldpaa_eth_priv *priv)
694{
695 int err;
696
697 /* and get a handle for the DPNI this interface is associate with */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530698 err = dpni_open(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_id,
699 &dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700700 if (err) {
701 printf("dpni_open() failed\n");
702 goto err_open;
703 }
704
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530705 err = dpni_get_attributes(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530706 dflt_dpni->dpni_handle,
707 &dflt_dpni->dpni_attrs);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700708 if (err) {
709 printf("dpni_get_attributes() failed (err=%d)\n", err);
710 goto err_get_attr;
711 }
712
713 /* Configure our buffers' layout */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530714 dflt_dpni->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700715 DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530716 DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
717 DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530718 dflt_dpni->buf_layout.pass_parser_result = true;
719 dflt_dpni->buf_layout.pass_frame_status = true;
720 dflt_dpni->buf_layout.private_data_size = LDPAA_ETH_SWA_SIZE;
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530721 /* HW erratum mandates data alignment in multiples of 256 */
722 dflt_dpni->buf_layout.data_align = LDPAA_ETH_BUF_ALIGN;
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700723 /* ...rx, ... */
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530724 err = dpni_set_rx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530725 dflt_dpni->dpni_handle,
726 &dflt_dpni->buf_layout);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700727 if (err) {
728 printf("dpni_set_rx_buffer_layout() failed");
729 goto err_buf_layout;
730 }
731
732 /* ... tx, ... */
Prabhakar Kushwaha9a934802015-11-04 12:26:02 +0530733 /* remove Rx-only options */
734 dflt_dpni->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
735 DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530736 err = dpni_set_tx_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530737 dflt_dpni->dpni_handle,
738 &dflt_dpni->buf_layout);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700739 if (err) {
740 printf("dpni_set_tx_buffer_layout() failed");
741 goto err_buf_layout;
742 }
743
744 /* ... tx-confirm. */
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530745 dflt_dpni->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530746 err = dpni_set_tx_conf_buffer_layout(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530747 dflt_dpni->dpni_handle,
748 &dflt_dpni->buf_layout);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700749 if (err) {
750 printf("dpni_set_tx_conf_buffer_layout() failed");
751 goto err_buf_layout;
752 }
753
754 /* Now that we've set our tx buffer layout, retrieve the minimum
755 * required tx data offset.
756 */
Prabhakar Kushwaha9564df62015-07-07 15:40:06 +0530757 err = dpni_get_tx_data_offset(dflt_mc_io, MC_CMD_NO_FLAGS,
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530758 dflt_dpni->dpni_handle,
759 &priv->tx_data_offset);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700760 if (err) {
761 printf("dpni_get_tx_data_offset() failed\n");
762 goto err_data_offset;
763 }
764
765 /* Warn in case TX data offset is not multiple of 64 bytes. */
766 WARN_ON(priv->tx_data_offset % 64);
767
768 /* Accomodate SWA space. */
769 priv->tx_data_offset += LDPAA_ETH_SWA_SIZE;
770 debug("priv->tx_data_offset=%d\n", priv->tx_data_offset);
771
772 return 0;
773
774err_data_offset:
775err_buf_layout:
776err_get_attr:
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530777 dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700778err_open:
779 return err;
780}
781
782static int ldpaa_dpni_bind(struct ldpaa_eth_priv *priv)
783{
784 struct dpni_pools_cfg pools_params;
785 struct dpni_tx_flow_cfg dflt_tx_flow;
786 int err = 0;
787
788 pools_params.num_dpbp = 1;
789 pools_params.pools[0].dpbp_id = (uint16_t)dflt_dpbp->dpbp_attr.id;
790 pools_params.pools[0].buffer_size = LDPAA_ETH_RX_BUFFER_SIZE;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530791 err = dpni_set_pools(dflt_mc_io, MC_CMD_NO_FLAGS,
792 dflt_dpni->dpni_handle, &pools_params);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700793 if (err) {
794 printf("dpni_set_pools() failed\n");
795 return err;
796 }
797
798 priv->tx_flow_id = DPNI_NEW_FLOW_ID;
799 memset(&dflt_tx_flow, 0, sizeof(dflt_tx_flow));
800
Prabhakar Kushwahac3d06e32015-12-24 15:32:49 +0530801 dflt_tx_flow.use_common_tx_conf_queue = 0;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530802 err = dpni_set_tx_flow(dflt_mc_io, MC_CMD_NO_FLAGS,
803 dflt_dpni->dpni_handle, &priv->tx_flow_id,
804 &dflt_tx_flow);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700805 if (err) {
806 printf("dpni_set_tx_flow() failed\n");
807 return err;
808 }
809
810 return 0;
811}
812
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530813static int ldpaa_eth_netdev_init(struct eth_device *net_dev,
814 phy_interface_t enet_if)
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700815{
816 int err;
817 struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
818
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530819 sprintf(net_dev->name, "DPMAC%d@%s", priv->dpmac_id,
820 phy_interface_strings[enet_if]);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700821
822 net_dev->iobase = 0;
823 net_dev->init = ldpaa_eth_open;
824 net_dev->halt = ldpaa_eth_stop;
825 net_dev->send = ldpaa_eth_tx;
826 net_dev->recv = ldpaa_eth_pull_dequeue_rx;
827/*
828 TODO: PHY MDIO information
829 priv->bus = info->bus;
830 priv->phyaddr = info->phy_addr;
831 priv->enet_if = info->enet_if;
832*/
833
834 if (init_phy(net_dev))
835 return 0;
836
837 err = eth_register(net_dev);
838 if (err < 0) {
839 printf("eth_register() = %d\n", err);
840 return err;
841 }
842
843 return 0;
844}
845
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530846int ldpaa_eth_init(int dpmac_id, phy_interface_t enet_if)
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700847{
848 struct eth_device *net_dev = NULL;
849 struct ldpaa_eth_priv *priv = NULL;
850 int err = 0;
851
852
853 /* Net device */
854 net_dev = (struct eth_device *)malloc(sizeof(struct eth_device));
855 if (!net_dev) {
856 printf("eth_device malloc() failed\n");
857 return -ENOMEM;
858 }
859 memset(net_dev, 0, sizeof(struct eth_device));
860
861 /* alloc the ldpaa ethernet private struct */
862 priv = (struct ldpaa_eth_priv *)malloc(sizeof(struct ldpaa_eth_priv));
863 if (!priv) {
864 printf("ldpaa_eth_priv malloc() failed\n");
865 return -ENOMEM;
866 }
867 memset(priv, 0, sizeof(struct ldpaa_eth_priv));
868
869 net_dev->priv = (void *)priv;
870 priv->net_dev = (struct eth_device *)net_dev;
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530871 priv->dpmac_id = dpmac_id;
872 debug("%s dpmac_id=%d\n", __func__, dpmac_id);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700873
Prabhakar Kushwaha52d2e2c2015-11-04 12:26:00 +0530874 err = ldpaa_eth_netdev_init(net_dev, enet_if);
Prabhakar Kushwaha5350b992015-03-19 09:20:46 -0700875 if (err)
876 goto err_netdev_init;
877
878 debug("ldpaa ethernet: Probed interface %s\n", net_dev->name);
879 return 0;
880
881err_netdev_init:
882 free(priv);
883 net_dev->priv = NULL;
884 free(net_dev);
885
886 return err;
887}