blob: fbb1afc08abca113312c35744502e5bd9889a3c9 [file] [log] [blame]
Stefan Roesec404ac72022-04-07 09:11:52 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2018-2022 Marvell International Ltd.
4 */
5
6#include <dm.h>
7#include <dm/device_compat.h>
8#include <env.h>
9#include <net.h>
10#include <netdev.h>
11#include <malloc.h>
12#include <miiphy.h>
13#include <misc.h>
14#include <asm/io.h>
15#include <linux/delay.h>
16
17#include <mach/cvmx-regs.h>
18#include <mach/cvmx-csr.h>
19#include <mach/cvmx-bootmem.h>
20#include <mach/octeon-model.h>
21#include <mach/cvmx-fuse.h>
22#include <mach/octeon-feature.h>
23#include <mach/octeon_fdt.h>
24#include <mach/cvmx-qlm.h>
25#include <mach/octeon_eth.h>
26#include <mach/octeon_qlm.h>
27#include <mach/cvmx-pcie.h>
28#include <mach/cvmx-coremask.h>
29
30#include <mach/cvmx-agl-defs.h>
31#include <mach/cvmx-asxx-defs.h>
32#include <mach/cvmx-bgxx-defs.h>
33#include <mach/cvmx-dbg-defs.h>
34#include <mach/cvmx-gmxx-defs.h>
35#include <mach/cvmx-gserx-defs.h>
36#include <mach/cvmx-ipd-defs.h>
37#include <mach/cvmx-l2c-defs.h>
38#include <mach/cvmx-npi-defs.h>
39#include <mach/cvmx-pcsx-defs.h>
40#include <mach/cvmx-pexp-defs.h>
41#include <mach/cvmx-pki-defs.h>
42#include <mach/cvmx-pko-defs.h>
43#include <mach/cvmx-smix-defs.h>
44#include <mach/cvmx-sriox-defs.h>
45#include <mach/cvmx-xcv-defs.h>
46#include <mach/cvmx-pcsxx-defs.h>
47
48#include <mach/cvmx-helper.h>
49#include <mach/cvmx-helper-board.h>
50#include <mach/cvmx-helper-fdt.h>
51#include <mach/cvmx-helper-bgx.h>
52#include <mach/cvmx-helper-cfg.h>
53
54#include <mach/cvmx-hwpko.h>
55#include <mach/cvmx-pko.h>
56#include <mach/cvmx-pki.h>
57#include <mach/cvmx-config.h>
58#include <mach/cvmx-mdio.h>
59
60/** Maximum receive packet size (hardware default is 1536) */
61#define CONFIG_OCTEON_NETWORK_MRU 1536
62
63#define OCTEON_BOOTLOADER_NAMED_BLOCK_TMP_PREFIX "__tmp"
64
65/**
66 * Enables RX packet debugging if octeon_debug_rx_packets is set in the
67 * environment.
68 */
69#define DEBUG_RX_PACKET
70
71/**
72 * Enables TX packet debugging if octeon_debug_tx_packets is set in the
73 * environment.
74 */
75#define DEBUG_TX_PACKET
76
77/* Global flag indicating common hw has been set up */
78static int octeon_global_hw_inited;
79
80#if defined(DEBUG_RX_PACKET) || defined(DEBUG_TX_PACKET)
81static int packet_rx_debug;
82static int packet_tx_debug;
83#endif
84
85/* Make sure that we have enough buffers to keep prefetching blocks happy.
86 * Absolute minimum is probably about 200.
87 */
88#define NUM_PACKET_BUFFERS 1000
89
90#define PKO_SHUTDOWN_TIMEOUT_VAL 100
91
92/* Define the offsets from the base CSR */
93#define GMX_PRT_CFG 0x10
94
95#define GMX_RX_FRM_MAX 0x30
96#define GMX_RX_JABBER 0x38
97
98#define GMX_RX_ADR_CTL 0x100
99#define GMX_RX_ADR_CAM_EN 0x108
100#define GMX_RX_ADR_CAM0 0x180
101#define GMX_RX_ADR_CAM1 0x188
102#define GMX_RX_ADR_CAM2 0x190
103#define GMX_RX_ADR_CAM3 0x198
104#define GMX_RX_ADR_CAM4 0x1a0
105#define GMX_RX_ADR_CAM5 0x1a8
106#define GMX_TX_OVR_BP 0x4c8
107
108/**
109 * Set the hardware MAC address for a device
110 *
111 * @param interface interface of port to set
112 * @param index index of port to set MAC address for
113 * @param addr Address structure to change it too.
114 * @return Zero on success
115 */
116static int cvm_oct_set_mac_address(struct udevice *dev)
117{
118 struct octeon_eth_info *priv = dev_get_priv(dev);
119 struct eth_pdata *pdata = dev_get_plat(dev);
120 cvmx_gmxx_prtx_cfg_t gmx_cfg;
121 cvmx_helper_interface_mode_t mode;
122 cvmx_gmxx_rxx_adr_ctl_t control;
123 u8 *ptr = (uint8_t *)pdata->enetaddr;
124 int interface = priv->interface;
125 int index = priv->index;
126 u64 mac = 0;
127 u64 gmx_reg;
128 int xipd_port;
129 int i;
130
131 for (i = 0; i < 6; i++)
132 mac = (mac << 8) | (u64)(ptr[i]);
133
134 debug("%s(%s (%pM))\n", __func__, dev->name, ptr);
135 mode = cvmx_helper_interface_get_mode(interface);
136
137 /* It's rather expensive to change the MAC address for BGX so we only
138 * do this if it has changed or not been set previously.
139 */
140 if (octeon_has_feature(OCTEON_FEATURE_BGX)) {
141 xipd_port = cvmx_helper_get_ipd_port(interface, index);
142 if (priv->last_bgx_mac != mac || !priv->bgx_mac_set) {
143 cvmx_helper_bgx_set_mac(xipd_port, 1, 2, mac);
144 priv->last_bgx_mac = mac;
145 priv->bgx_mac_set = 1;
146 }
147 return 0;
148 }
149
150 if (mode == CVMX_HELPER_INTERFACE_MODE_AGL) {
151 gmx_reg = CVMX_AGL_GMX_RXX_INT_REG(0);
152 } else {
153 gmx_reg = CVMX_GMXX_RXX_INT_REG(index, interface);
154 csr_wr(CVMX_GMXX_SMACX(index, interface), mac);
155 }
156
157 /* Disable interface */
158 gmx_cfg.u64 = csr_rd(gmx_reg + GMX_PRT_CFG);
159 csr_wr(gmx_reg + GMX_PRT_CFG, gmx_cfg.u64 & ~1ull);
160 debug("%s: gmx reg: 0x%llx\n", __func__, gmx_reg);
161
162 csr_wr(gmx_reg + GMX_RX_ADR_CAM0, ptr[0]);
163 csr_wr(gmx_reg + GMX_RX_ADR_CAM1, ptr[1]);
164 csr_wr(gmx_reg + GMX_RX_ADR_CAM2, ptr[2]);
165 csr_wr(gmx_reg + GMX_RX_ADR_CAM3, ptr[3]);
166 csr_wr(gmx_reg + GMX_RX_ADR_CAM4, ptr[4]);
167 csr_wr(gmx_reg + GMX_RX_ADR_CAM5, ptr[5]);
168
169 control.u64 = 0;
170 control.s.bcst = 1; /* Allow broadcast MAC addresses */
171 control.s.mcst = 1; /* Force reject multicast packets */
172 control.s.cam_mode = 1; /* Filter packets based on the CAM */
173
174 csr_wr(gmx_reg + GMX_RX_ADR_CTL, control.u64);
175
176 csr_wr(gmx_reg + GMX_RX_ADR_CAM_EN, 1);
177
178 /* Return interface to previous enable state */
179 csr_wr(gmx_reg + GMX_PRT_CFG, gmx_cfg.u64);
180
181 return 0;
182}
183
184static void cvm_oct_fill_hw_memory(u64 pool, u64 size, u64 elements)
185{
186 static int alloc_count;
187 char tmp_name[64];
188 int ret;
189
190 debug("%s: pool: 0x%llx, size: 0xx%llx, count: 0x%llx\n",
191 __func__, pool, size, elements);
192 sprintf(tmp_name, "%s_fpa_alloc_%d",
193 OCTEON_BOOTLOADER_NAMED_BLOCK_TMP_PREFIX, alloc_count++);
194 ret = cvmx_fpa_setup_pool(pool, tmp_name, NULL, size, elements);
195}
196
197/**
198 * Configure common hardware for all interfaces
199 */
200static void cvm_oct_configure_common_hw(void)
201{
202 int mru = env_get_ulong("octeon_mru", 0, CONFIG_OCTEON_NETWORK_MRU);
203 int packet_pool_size = CVMX_FPA_PACKET_POOL_SIZE;
204
205 if (mru > packet_pool_size)
206 packet_pool_size = (mru + CVMX_CACHE_LINE_SIZE - 1) &
207 ~(CVMX_CACHE_LINE_SIZE - 1);
208
209 /* Setup the FPA */
210 cvmx_fpa_enable();
211
212 cvm_oct_fill_hw_memory(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE,
213 NUM_PACKET_BUFFERS);
214#if CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL
215 if (!octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) {
216 cvm_oct_fill_hw_memory(CVMX_FPA_OUTPUT_BUFFER_POOL,
217 CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128);
218 }
219#endif
220 cvm_oct_fill_hw_memory(CVMX_FPA_PACKET_POOL, packet_pool_size,
221 NUM_PACKET_BUFFERS);
222
223 cvmx_helper_initialize_packet_io_global();
224 cvmx_helper_initialize_packet_io_local();
225
226 /* The MRU defaults to 1536 bytes by the hardware. Setting
227 * CONFIG_OCTEON_NETWORK_MRU allows this to be overridden.
228 */
229 if (octeon_has_feature(OCTEON_FEATURE_PKI)) {
230 struct cvmx_pki_global_config gbl_cfg;
231 int i;
232
233 cvmx_pki_read_global_config(0, &gbl_cfg);
234 for (i = 0; i < CVMX_PKI_NUM_FRAME_CHECK; i++)
235 gbl_cfg.frm_len[i].maxlen = mru;
236 cvmx_pki_write_global_config(0, &gbl_cfg);
237 }
238
239 /* Set POW get work timeout to maximum value */
240 if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE) ||
241 octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE))
242 csr_wr(CVMX_SSO_NW_TIM, 0x3ff);
243 else
244 csr_wr(CVMX_POW_NW_TIM, 0x3ff);
245}
246
247/**
248 * Enables Ethernet devices to allow packets to be transmitted and received.
249 * For example, this is activated when the DHCP command is issued.
250 *
251 * @param dev Ethernet device to initialize
252 * @param bis board data structure, not used.
253 *
254 * @return 1 for success
255 */
256int octeon_eth_init(struct udevice *dev)
257{
258 struct octeon_eth_info *priv = dev_get_priv(dev);
259
260 debug("%s(), dev_ptr: %p, dev: %s, port: %d\n", __func__, dev,
261 dev->name, priv->port);
262
263 if (priv->initted_flag) {
264 debug("%s already initialized\n", dev->name);
265 return 1;
266 }
267
268 if (!octeon_global_hw_inited) {
269 debug("Initializing common hardware\n");
270 cvm_oct_configure_common_hw();
271 }
272
273 /* Ignore backpressure on RGMII ports */
274 if (!octeon_has_feature(OCTEON_FEATURE_BGX))
275 csr_wr(priv->gmx_base + GMX_TX_OVR_BP, 0xf << 8 | 0xf);
276
277 debug("%s: Setting MAC address\n", __func__);
278 cvm_oct_set_mac_address(dev);
279
280 if (!octeon_global_hw_inited) {
281 debug("Enabling packet input\n");
282 cvmx_helper_ipd_and_packet_input_enable();
283 octeon_global_hw_inited = 1;
284
285 /* Connect, configure and start the PHY, if the device is
286 * connected to one. If not, then it's most likely an SPF
287 * enabled port, which does not have such PHY setup here.
288 */
289 if (priv->mdio_dev) {
290 priv->phy_dev = dm_eth_phy_connect(dev);
291 phy_config(priv->phy_dev);
292 phy_startup(priv->phy_dev);
293 }
294 }
295 priv->enabled = 0;
296 priv->initted_flag = 1;
297
298 debug("%s exiting successfully\n", __func__);
299 return 1;
300}
301
302/**
303 * Initializes the specified interface and port
304 *
305 * @param interface interface to initialize
306 * @param index port index on interface
307 * @param port ipd port number
308 * @param if_mode interface mode
309 *
310 * @return 0 for success, -1 if out of memory, 1 if port is invalid
311 */
312static int octeon_eth_initialize(struct udevice *dev, int interface,
313 int index, int port,
314 cvmx_helper_interface_mode_t if_mode)
315{
316 struct octeon_eth_info *oct_eth_info = dev_get_priv(dev);
317 int eth;
318
319 eth = cvmx_helper_get_port_fdt_node_offset(interface, index);
320 if (eth <= 0) {
321 debug("ERROR: No fdt node for interface %d, index %d\n",
322 interface, index);
323 return 1;
324 }
325
326 oct_eth_info->is_c45 = (if_mode == CVMX_HELPER_INTERFACE_MODE_XAUI) ||
327 (if_mode == CVMX_HELPER_INTERFACE_MODE_RXAUI) ||
328 (if_mode == CVMX_HELPER_INTERFACE_MODE_XFI) ||
329 (if_mode == CVMX_HELPER_INTERFACE_MODE_XLAUI) ||
330 (if_mode == CVMX_HELPER_INTERFACE_MODE_10G_KR) ||
331 (if_mode == CVMX_HELPER_INTERFACE_MODE_10G_KR);
332 oct_eth_info->port = port;
333 oct_eth_info->index = index;
334 oct_eth_info->interface = interface;
335 oct_eth_info->initted_flag = 0;
336 /* This is guaranteed to force the link state to be printed out */
337 oct_eth_info->link_state = 0xffffffffffffffffULL;
338 debug("Setting up port: %d, int: %d, index: %d, device: octeth%d\n",
339 oct_eth_info->port, oct_eth_info->interface, oct_eth_info->index,
340 dev_seq(dev));
341 if (if_mode == CVMX_HELPER_INTERFACE_MODE_AGL) {
342 oct_eth_info->gmx_base = CVMX_AGL_GMX_RXX_INT_REG(0);
343 } else {
344 if (!octeon_has_feature(OCTEON_FEATURE_BGX))
345 oct_eth_info->gmx_base =
346 CVMX_GMXX_RXX_INT_REG(index, interface);
347 }
348
349 return 0;
350}
351
352/**
353 * @INTERNAL
354 * Converts a BGX address to the node, interface and port number
355 *
356 * @param bgx_addr Address of CSR register
357 *
358 * @return node, interface and port number, will be -1 for invalid address.
359 */
360static struct cvmx_xiface __cvmx_bgx_reg_addr_to_xiface(u64 bgx_addr)
361{
362 struct cvmx_xiface xi = { -1, -1 };
363
364 xi.node = cvmx_csr_addr_to_node(bgx_addr);
365 bgx_addr = cvmx_csr_addr_strip_node(bgx_addr);
366 if ((bgx_addr & 0xFFFFFFFFF0000000) != 0x00011800E0000000) {
367 debug("%s: Invalid BGX address 0x%llx\n", __func__,
368 (unsigned long long)bgx_addr);
369 xi.node = -1;
370 return xi;
371 }
372 xi.interface = (bgx_addr >> 24) & 0x0F;
373
374 return xi;
375}
376
377static int octeon_nic_probe(struct udevice *dev)
378{
379 struct octeon_eth_info *info = dev_get_priv(dev);
380 struct ofnode_phandle_args phandle;
381 struct cvmx_xiface xi;
382 ofnode node, mdio_node;
383 int ipd_port;
384 int intf;
385 int ret;
386
387 /* The empty stub is to keep cvmx_user_app_init() happy. */
388 cvmx_npi_max_pknds = 1;
389 __cvmx_helper_init_port_valid();
390
391 xi = __cvmx_bgx_reg_addr_to_xiface(dev_read_addr(dev));
392 intf = xi.interface;
393 debug("%s: Found BGX node %d, interface %d\n", __func__, xi.node, intf);
394
395 ipd_port = cvmx_helper_get_ipd_port(intf, xi.node);
396 ret = octeon_eth_initialize(dev, intf, xi.node, ipd_port,
397 cvmx_helper_interface_get_mode(intf));
398
399 /* Move to subnode, as this includes the "phy-handle" */
400 node = dev_read_first_subnode(dev);
401
402 /* Check if an SPF module is conneted, then no MDIO is probed */
403 ret = ofnode_parse_phandle_with_args(node, "sfp-slot", NULL, 0, 0,
404 &phandle);
405 if (!ret) {
406 dev_dbg(dev, "sfp-slot found, not probing for MDIO\n");
407 return 0;
408 }
409
410 /* Continue with MDIO probing */
411 ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0,
412 &phandle);
413 if (ret) {
414 dev_err(dev, "phy-handle not found in subnode\n");
415 return -ENODEV;
416 }
417
418 /* Get MDIO node */
419 mdio_node = ofnode_get_parent(phandle.node);
420 ret = uclass_get_device_by_ofnode(UCLASS_MDIO, mdio_node,
421 &info->mdio_dev);
422 if (ret) {
423 dev_err(dev, "mdio_dev not found\n");
424 return -ENODEV;
425 }
426
427 return 0;
428}
429
430/**
431 * Sets the hardware MAC address of the Ethernet device
432 *
433 * @param dev - Ethernet device
434 *
435 * @return 0 for success
436 */
437int octeon_eth_write_hwaddr(struct udevice *dev)
438{
439 struct octeon_eth_info *oct_eth_info = dev_get_priv(dev);
440 struct eth_pdata *pdata = dev_get_plat(dev);
441
442 /* Skip if the interface isn't yet enabled */
443 if (!oct_eth_info->enabled) {
444 debug("%s: Interface not enabled, not setting MAC address\n",
445 __func__);
446 return 0;
447 }
448 debug("%s: Setting %s address to %02x:%02x:%02x:%02x:%02x:%02x\n",
449 __func__, dev->name, pdata->enetaddr[0], pdata->enetaddr[1],
450 pdata->enetaddr[2], pdata->enetaddr[3], pdata->enetaddr[4],
451 pdata->enetaddr[5]);
452 return cvm_oct_set_mac_address(dev);
453}
454
455/**
456 * Enables and disables the XCV RGMII interface
457 *
458 * @param interface Interface number
459 * @param index Port index (should be 0 for RGMII)
460 * @param enable True to enable it, false to disable it
461 */
462static void octeon_bgx_xcv_rgmii_enable(int interface, int index, bool enable)
463{
464 union cvmx_xcv_reset xcv_reset;
465
466 debug("%s(%d, %d, %sable)\n", __func__, interface, index,
467 enable ? "en" : "dis");
468 xcv_reset.u64 = csr_rd(CVMX_XCV_RESET);
469 xcv_reset.s.rx_pkt_rst_n = enable ? 1 : 0;
470 csr_wr(CVMX_XCV_RESET, xcv_reset.u64);
471}
472
473/**
474 * Enables a SGMII interface
475 *
476 * @param dev - Ethernet device to initialize
477 */
478void octeon_eth_sgmii_enable(struct udevice *dev)
479{
480 struct octeon_eth_info *oct_eth_info;
481 cvmx_gmxx_prtx_cfg_t gmx_cfg;
482 int index, interface;
483 cvmx_helper_interface_mode_t if_mode;
484
485 oct_eth_info = dev_get_priv(dev);
486 interface = oct_eth_info->interface;
487 index = oct_eth_info->index;
488
489 debug("%s(%s) (%d.%d)\n", __func__, dev->name, interface, index);
490 if (octeon_has_feature(OCTEON_FEATURE_BGX)) {
491 cvmx_bgxx_cmrx_config_t cmr_config;
492
493 cmr_config.u64 =
494 csr_rd(CVMX_BGXX_CMRX_CONFIG(index, interface));
495 cmr_config.s.enable = 1;
496 cmr_config.s.data_pkt_tx_en = 1;
497 cmr_config.s.data_pkt_rx_en = 1;
498 csr_wr(CVMX_BGXX_CMRX_CONFIG(index, interface), cmr_config.u64);
499 mdelay(100);
500 if (cvmx_helper_bgx_is_rgmii(interface, index))
501 octeon_bgx_xcv_rgmii_enable(interface, index, true);
502 } else {
503 if_mode = cvmx_helper_interface_get_mode(interface);
504 /* Normal operating mode. */
505
506 if (if_mode == CVMX_HELPER_INTERFACE_MODE_SGMII ||
507 if_mode == CVMX_HELPER_INTERFACE_MODE_QSGMII) {
508 cvmx_pcsx_miscx_ctl_reg_t pcsx_miscx_ctl_reg;
509
510 debug(" if mode: (Q)SGMII\n");
511 pcsx_miscx_ctl_reg.u64 = csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface));
512 pcsx_miscx_ctl_reg.s.gmxeno = 0;
513 csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface),
514 pcsx_miscx_ctl_reg.u64);
515 } else if (if_mode != CVMX_HELPER_INTERFACE_MODE_AGL) {
516 cvmx_pcsxx_misc_ctl_reg_t pcsxx_misc_ctl_reg;
517
518 debug(" if mode: AGM\n");
519 pcsxx_misc_ctl_reg.u64 =
520 csr_rd(CVMX_PCSXX_MISC_CTL_REG(interface));
521 pcsxx_misc_ctl_reg.s.gmxeno = 0;
522 csr_wr(CVMX_PCSXX_MISC_CTL_REG(interface),
523 pcsxx_misc_ctl_reg.u64);
524 }
525
526 gmx_cfg.u64 = csr_rd(oct_eth_info->gmx_base + GMX_PRT_CFG);
527 gmx_cfg.s.en = 1;
528 csr_wr(oct_eth_info->gmx_base + GMX_PRT_CFG, gmx_cfg.u64);
529 gmx_cfg.u64 = csr_rd(oct_eth_info->gmx_base + GMX_PRT_CFG);
530 }
531}
532
533/**
534 * Enables an Ethernet interface
535 *
536 * @param dev - Ethernet device to enable
537 */
538void octeon_eth_enable(struct udevice *dev)
539{
540 struct octeon_eth_info *oct_eth_info;
541 u64 tmp;
542 int interface;
543 cvmx_helper_interface_mode_t if_mode;
544
545 oct_eth_info = dev_get_priv(dev);
546 interface = oct_eth_info->interface;
547 if_mode = cvmx_helper_interface_get_mode(interface);
548
549 switch (if_mode) {
550 case CVMX_HELPER_INTERFACE_MODE_RGMII:
551 case CVMX_HELPER_INTERFACE_MODE_GMII:
552 debug(" rgmii/gmii mode\n");
553 tmp = csr_rd(CVMX_ASXX_RX_PRT_EN(interface));
554 tmp |= (1ull << (oct_eth_info->port & 0x3));
555 csr_wr(CVMX_ASXX_RX_PRT_EN(interface), tmp);
556 tmp = csr_rd(CVMX_ASXX_TX_PRT_EN(interface));
557 tmp |= (1ull << (oct_eth_info->port & 0x3));
558 csr_wr(CVMX_ASXX_TX_PRT_EN(interface), tmp);
559 octeon_eth_write_hwaddr(dev);
560 break;
561
562 case CVMX_HELPER_INTERFACE_MODE_SGMII:
563 case CVMX_HELPER_INTERFACE_MODE_XAUI:
564 case CVMX_HELPER_INTERFACE_MODE_RXAUI:
565 case CVMX_HELPER_INTERFACE_MODE_XLAUI:
566 case CVMX_HELPER_INTERFACE_MODE_XFI:
567 case CVMX_HELPER_INTERFACE_MODE_10G_KR:
568 case CVMX_HELPER_INTERFACE_MODE_40G_KR4:
569 case CVMX_HELPER_INTERFACE_MODE_MIXED:
570 case CVMX_HELPER_INTERFACE_MODE_AGL:
571 debug(" SGMII/XAUI/etc.\n");
572 octeon_eth_sgmii_enable(dev);
573 octeon_eth_write_hwaddr(dev);
574 break;
575
576 default:
577 break;
578 }
579}
580
581void octeon_phy_port_check(struct udevice *dev)
582{
583 struct octeon_eth_info *oct_eth_info = dev_get_priv(dev);
584 struct phy_device *phydev = oct_eth_info->phydev;
585
586 if (oct_eth_info->phy_port_check)
587 oct_eth_info->phy_port_check(phydev);
588}
589
590/**
591 * Configure the RGMII port for the negotiated speed
592 *
593 * @param dev Linux device for the RGMII port
594 */
595static void cvm_oct_configure_rgmii_speed(struct udevice *dev)
596{
597 struct octeon_eth_info *priv = dev_get_priv(dev);
598 int port = priv->port;
599 cvmx_helper_link_info_t link_state = cvmx_helper_link_get(port);
600
601 /* If the port is down some PHYs we need to check modules, etc. */
602 if (!link_state.s.link_up)
603 octeon_phy_port_check(dev);
604
605 if (link_state.u64 != priv->link_state) {
606 cvmx_helper_interface_mode_t mode;
607
608 octeon_phy_port_check(dev);
609
610 debug("%s(%s): Link state changed\n", __func__, dev->name);
611 printf("%s: ", dev->name);
612 if (!link_state.s.link_up) {
613 puts("Down ");
614 } else {
615 printf("Up %d Mbps ", link_state.s.speed);
616 if (link_state.s.full_duplex)
617 puts("Full duplex ");
618 else
619 puts("Half duplex ");
620 }
621 mode = cvmx_helper_interface_get_mode(priv->interface);
622 printf("(port %2d) (%s)\n", port,
623 cvmx_helper_interface_mode_to_string(mode));
624 debug("%s: Setting link state\n", __func__);
625 cvmx_helper_link_set(priv->port, link_state);
626 priv->link_state = link_state.u64;
627 }
628}
629
630#if defined(DEBUG_TX_PACKET) || defined(DEBUG_RX_PACKET)
631static void print_mac(const char *label, const uint8_t *mac_addr)
632{
633 printf("%s: %02x:%02x:%02x:%02x:%02x:%02x", label, mac_addr[0],
634 mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
635}
636
637static void print_ip(const void *packet)
638{
639 u8 *p = (uint8_t *)packet;
640 u16 length;
641 u8 hdr_len;
642
643 puts("IP Header:\n");
644 if ((p[0] & 0xF0) != 0x40) {
645 printf("Invalid IP version %d\n", *p >> 4);
646 return;
647 }
648 hdr_len = *p & 0x0F;
649 if (hdr_len < 5)
650 printf("Invalid IP header length %d\n", hdr_len);
651 printf(" Version: 4, Header length: %d\n", hdr_len);
652 length = (p[2] << 8) | p[3];
653 printf(" TOS: 0x%02x, length: %d\n", p[1], length);
654 printf(" ID: %d, %s%s%s fragment offset: %d\n", (p[4] << 8) | p[5],
655 p[6] & 0x80 ? "congested, " : "", p[6] & 0x40 ? "DF, " : "",
656 p[6] & 0x20 ? "MF, " : "", ((p[6] & 0x1F) << 8) | p[7]);
657 printf(" TTL: %d, Protocol: %d, Header Checksum: 0x%x\n", p[8], p[9],
658 (p[10] << 8) | p[11]);
659 printf(" Source IP: %d.%d.%d.%d\n Destination IP: %d.%d.%d.%d\n",
660 p[12], p[13], p[14], p[15], p[16], p[17], p[18], p[19]);
661 if (p[9] == 17 || p[9] == 6)
662 printf(" Source port: %u, Destination port: %u\n",
663 (p[20] << 8) | p[21], (p[22] << 8) | p[23]);
664 puts("\n");
665}
666
667/**
668 * Prints out a packet for debugging purposes
669 *
670 * @param[in] packet - pointer to packet data
671 * @param length - length of packet in bytes
672 */
673static void print_packet(const void *packet, int length)
674{
675 int i, j;
676 const unsigned char *up = packet;
677 u16 type = (up[12] << 8 | up[13]);
678 int start = 14;
679
680 print_mac("DMAC", &up[0]);
681 puts(" ");
682 print_mac("SMAC", &up[6]);
683 printf(" TYPE: %04x\n", type);
684
685 if (type == 0x0800)
686 print_ip(&up[start]);
687
688 for (i = start; (i + 16) < length; i += 16) {
689 printf("%04x ", i);
690 for (j = 0; j < 16; ++j)
691 printf("%02x ", up[i + j]);
692
693 printf(" ");
694 for (j = 0; j < 16; ++j)
695 printf("%c",
696 ((up[i + j] >= ' ') && (up[i + j] <= '~')) ?
697 up[i + j] :
698 '.');
699 printf("\n");
700 }
701 printf("%04x ", i);
702 for (j = 0; i + j < length; ++j)
703 printf("%02x ", up[i + j]);
704
705 for (; j < 16; ++j)
706 printf(" ");
707
708 printf(" ");
709 for (j = 0; i + j < length; ++j)
710 printf("%c", ((up[i + j] >= ' ') && (up[i + j] <= '~')) ?
711 up[i + j] :
712 '.');
713
714 printf("\n");
715}
716#endif
717
718/**
719 * String representation of error codes.
720 */
721static const char * const rx_error_codes[] = {
722 "OK",
723 "partial",
724 "jabber",
725 "overrun",
726 "oversize",
727 "alignment",
728 "fragment",
729 "fcs",
730 "undersize",
731 "extend",
732 "length mismatch",
733 "rgmii rx",
734 "skip error",
735 "nibble error (studder)",
736 "(undefined)",
737 "(undefined)",
738 "SPI 4.2 FCS",
739 "skip",
740 "L2 malformed",
741};
742
743/**
744 * Called to receive a packet
745 *
746 * @param dev - device to receive on
747 *
748 * @return - length of packet
749 *
750 * This function is used to poll packets. In turn it calls NetReceive
751 * to process the packets.
752 */
753static int nic_recv(struct udevice *dev, int flags, uchar **packetp)
754{
755 cvmx_wqe_t *work = cvmx_pow_work_request_sync(CVMX_POW_WAIT);
756 struct octeon_eth_info *oct_eth_info = dev_get_priv(dev);
757 cvmx_buf_ptr_t buf_ptr;
758 void *packet_data;
759 int length;
760 int error_code;
761
762 if (!oct_eth_info->enabled) {
763 oct_eth_info->enabled = 1;
764 debug("%s: Enabling interface %s\n", __func__, dev->name);
765 octeon_eth_enable(dev);
766 }
767
768 if (!work) {
769 /*
770 * Somtimes the link is not up yet. Return here in this
771 * case, this function will be called again later.
772 */
773 return 0;
774 }
775
776 error_code = cvmx_wqe_get_rcv_err(work);
777 if (error_code) {
778 /* Work has error, so drop */
779 cvmx_helper_free_packet_data(work);
780 cvmx_wqe_free(work);
781 if (error_code < ARRAY_SIZE(rx_error_codes) &&
782 !octeon_has_feature(OCTEON_FEATURE_BGX))
783 printf("Receive error (code %d: %s), dropping\n",
784 error_code, rx_error_codes[error_code]);
785 else
786 printf("Receive error (code %d (unknown), dropping\n",
787 error_code);
788 return 0;
789 }
790 if (cvmx_wqe_get_bufs(work) != 1) {
791 /* can only support single-buffer packets */
792 printf("Abnormal packet received in %u bufs, dropping\n",
793 cvmx_wqe_get_bufs(work));
794 length = cvmx_wqe_get_len(work);
795 buf_ptr = cvmx_wqe_get_packet_ptr(work);
796 packet_data = cvmx_phys_to_ptr(buf_ptr.s.addr);
797 print_packet(packet_data, length);
798 cvmx_helper_free_packet_data(work);
799 cvmx_wqe_free(work);
800 return 0;
801 }
802
803 buf_ptr = cvmx_wqe_get_packet_ptr(work);
804 packet_data = cvmx_phys_to_ptr(buf_ptr.s.addr);
805 length = cvmx_wqe_get_len(work);
806
807 oct_eth_info->packets_received++;
808 debug("############# got work: %p, len: %d, packet_ptr: %p\n", work,
809 length, packet_data);
810#if defined(DEBUG_RX_PACKET)
811 if (packet_rx_debug) {
812 printf("\nRX packet: interface: %d, index: %d\n",
813 oct_eth_info->interface, oct_eth_info->index);
814 print_packet(packet_data, length);
815 }
816#endif
817 *packetp = (uchar *)packet_data;
818
819 /* Save work for free_pkt() */
820 oct_eth_info->work = work;
821
822 /* Free WQE and packet data */
823 return length;
824}
825
826static int nic_free_pkt(struct udevice *dev, uchar *pkt, int pkt_len)
827{
828 struct octeon_eth_info *oct_eth_info = dev_get_priv(dev);
829 cvmx_wqe_t *work = oct_eth_info->work;
830
831 if (!work)
832 return 0;
833
834 cvmx_helper_free_packet_data(work);
835 cvmx_wqe_free(work);
836 oct_eth_info->work = NULL;
837
838 return 0;
839}
840
841/**
842 * Packet transmit
843 *
844 * @param skb Packet to send
845 * @param dev Device info structure
846 * @return Always returns zero
847 */
848static int cvm_oct_xmit(struct udevice *dev, void *packet, int len)
849{
850 struct octeon_eth_info *priv = dev_get_priv(dev);
851 int queue = cvmx_pko_get_base_queue(priv->port);
852 cvmx_pko_command_word0_t pko_command;
853 cvmx_buf_ptr_t hw_buffer;
854 int rv;
855
856 debug("%s: addr: %p, len: %d\n", __func__, packet, len);
857
858 hw_buffer.u64 = 0;
859 hw_buffer.s.addr = cvmx_ptr_to_phys(packet);
860 hw_buffer.s.pool = CVMX_FPA_PACKET_POOL;
861 hw_buffer.s.size = len;
862 hw_buffer.s.back = 0;
863
864 /* Build the PKO command */
865 pko_command.u64 = 0;
866 pko_command.s.subone0 = 1;
867 pko_command.s.dontfree = 0;
868 pko_command.s.segs = 1;
869 pko_command.s.total_bytes = len;
870 /* Send the packet to the output queue */
871
872 debug("%s: port: %d, queue: %d\n", __func__, priv->port, queue);
873 cvmx_pko_send_packet_prepare(priv->port, queue, 0);
874 rv = cvmx_pko_send_packet_finish(priv->port, queue, pko_command,
875 hw_buffer, 0);
876 if (rv)
877 printf("Failed to send the packet rv=%d\n", rv);
878
879 return 0;
880}
881
882static int nic_xmit(struct udevice *dev, void *pkt, int pkt_len)
883{
884 struct octeon_eth_info *oct_eth_info = dev_get_priv(dev);
885 void *fpa_buf = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL);
886
887 if (!oct_eth_info->enabled) {
888 oct_eth_info->enabled = 1;
889 octeon_eth_enable(dev);
890 }
891
892 /* We need to copy this to a FPA buffer, then give that to TX */
893
894 if (oct_eth_info->packets_sent == 0 &&
895 !octeon_has_feature(OCTEON_FEATURE_BGX))
896 cvm_oct_configure_rgmii_speed(dev);
897
898 if (!fpa_buf) {
899 printf("ERROR allocating buffer for packet!\n");
900 return -1;
901 }
902
903 memcpy(fpa_buf, pkt, pkt_len);
904#ifdef DEBUG_TX_PACKET
905 if (packet_tx_debug) {
906 printf("\nTX packet: interface: %d, index: %d\n",
907 oct_eth_info->interface, oct_eth_info->index);
908 print_packet(pkt, pkt_len);
909 }
910#endif
911 cvm_oct_xmit(dev, fpa_buf, pkt_len);
912 oct_eth_info->packets_sent++;
913
914 return 0;
915}
916
917int nic_open(struct udevice *dev)
918{
919 octeon_eth_init(dev);
920
921 return 0;
922}
923
924static void octeon_eth_halt_bgx(struct udevice *dev,
925 cvmx_helper_interface_mode_t mode)
926{
927 union cvmx_bgxx_cmrx_config cmr_config;
928 union cvmx_bgxx_cmr_rx_adrx_cam cmr_cam;
929 struct octeon_eth_info *oct_eth_info = dev_get_priv(dev);
930 int index = oct_eth_info->index;
931 int xiface = oct_eth_info->interface;
932 struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface);
933
934 debug("%s(%s(%d.%d), %d)\n", __func__, dev->name, xiface, index, mode);
935
936 /* For RGMII we need to properly shut down the XCV interface */
937 if (cvmx_helper_bgx_is_rgmii(xiface, index)) {
938 debug(" Shut down XCV RGMII\n");
939 octeon_bgx_xcv_rgmii_enable(xi.interface, index, false);
940 } else {
941 cmr_config.u64 = csr_rd_node(xi.node,
942 CVMX_BGXX_CMRX_CONFIG(index, xi.interface));
943 cmr_config.s.data_pkt_tx_en = 0;
944 cmr_config.s.data_pkt_rx_en = 0;
945 csr_wr_node(xi.node, CVMX_BGXX_CMRX_CONFIG(index, xi.interface),
946 cmr_config.u64);
947
948 cmr_cam.u64 = csr_rd_node(xi.node,
949 CVMX_BGXX_CMR_RX_ADRX_CAM(index * 8, xi.interface));
950 cmr_cam.s.en = 0;
951 csr_wr_node(xi.node,
952 CVMX_BGXX_CMR_RX_ADRX_CAM(index * 8, xi.interface),
953 cmr_cam.u64);
954 oct_eth_info->last_bgx_mac = 0;
955 oct_eth_info->bgx_mac_set = 0;
956 }
957}
958
959/**
960 * Halts the specified Ethernet interface preventing it from receiving any more
961 * packets.
962 *
963 * @param dev - Ethernet device to shut down.
964 */
965void octeon_eth_halt(struct udevice *dev)
966{
967 struct octeon_eth_info *oct_eth_info = dev_get_priv(dev);
968 int index = oct_eth_info->index;
969 int interface = oct_eth_info->interface;
970 cvmx_helper_interface_mode_t mode;
971 union cvmx_gmxx_rxx_adr_ctl adr_ctl;
972 cvmx_gmxx_prtx_cfg_t gmx_cfg;
973 u64 tmp;
974
975 debug("%s(%s): Halting\n", __func__, dev->name);
976
977 oct_eth_info->enabled = 0;
978
979 mode = cvmx_helper_interface_get_mode(oct_eth_info->interface);
980 if (octeon_has_feature(OCTEON_FEATURE_BGX)) {
981 octeon_eth_halt_bgx(dev, mode);
982 return;
983 }
984
985 /* Stop SCC */
986 /* Disable reception on this port at the GMX block */
987 switch (mode) {
988 case CVMX_HELPER_INTERFACE_MODE_RGMII:
989 case CVMX_HELPER_INTERFACE_MODE_GMII:
990 debug(" RGMII/GMII\n");
991 tmp = csr_rd(CVMX_ASXX_RX_PRT_EN(oct_eth_info->interface));
992 tmp &= ~(1ull << index);
993 /* Disable the RGMII RX ports */
994 csr_wr(CVMX_ASXX_RX_PRT_EN(oct_eth_info->interface), tmp);
995 tmp = csr_rd(CVMX_ASXX_TX_PRT_EN(oct_eth_info->interface));
996 tmp &= ~(1ull << index);
997 /* Disable the RGMII TX ports */
998 csr_wr(CVMX_ASXX_TX_PRT_EN(oct_eth_info->interface), tmp);
999 /* No break! */
1000 case CVMX_HELPER_INTERFACE_MODE_SGMII:
1001 case CVMX_HELPER_INTERFACE_MODE_QSGMII:
1002 case CVMX_HELPER_INTERFACE_MODE_XAUI:
1003 case CVMX_HELPER_INTERFACE_MODE_RXAUI:
1004 case CVMX_HELPER_INTERFACE_MODE_XLAUI:
1005 case CVMX_HELPER_INTERFACE_MODE_XFI:
1006 case CVMX_HELPER_INTERFACE_MODE_10G_KR:
1007 case CVMX_HELPER_INTERFACE_MODE_40G_KR4:
1008 case CVMX_HELPER_INTERFACE_MODE_MIXED:
1009 case CVMX_HELPER_INTERFACE_MODE_AGL:
1010 /* Disable MAC filtering */
1011 gmx_cfg.u64 = csr_rd(oct_eth_info->gmx_base + GMX_PRT_CFG);
1012 csr_wr(oct_eth_info->gmx_base + GMX_PRT_CFG,
1013 gmx_cfg.u64 & ~1ull);
1014 adr_ctl.u64 = 0;
1015 adr_ctl.s.bcst = 1; /* Reject broadcast */
1016 csr_wr(oct_eth_info->gmx_base + GMX_RX_ADR_CTL, adr_ctl.u64);
1017 csr_wr(oct_eth_info->gmx_base + GMX_RX_ADR_CAM_EN, 0);
1018 csr_wr(oct_eth_info->gmx_base + GMX_PRT_CFG, gmx_cfg.u64);
1019 break;
1020 default:
1021 printf("%s: Unknown mode %d for interface 0x%x:%d\n", __func__,
1022 mode, interface, index);
1023 break;
1024 }
1025}
1026
1027void nic_stop(struct udevice *dev)
1028{
1029 octeon_eth_halt(dev);
1030}
1031
1032int nic_write_hwaddr(struct udevice *dev)
1033{
1034 cvm_oct_set_mac_address(dev);
1035
1036 return 0;
1037}
1038
1039static const struct eth_ops octeon_nic_ops = {
1040 .start = nic_open,
1041 .stop = nic_stop,
1042 .send = nic_xmit,
1043 .recv = nic_recv,
1044 .free_pkt = nic_free_pkt,
1045 .write_hwaddr = nic_write_hwaddr,
1046};
1047
1048static const struct udevice_id octeon_nic_ids[] = {
1049 { .compatible = "cavium,octeon-7890-bgx" },
1050 {}
1051};
1052
1053U_BOOT_DRIVER(octeon_nic) = {
1054 .name = "octeon_nic",
1055 .id = UCLASS_ETH,
1056 .probe = octeon_nic_probe,
1057 .of_match = octeon_nic_ids,
1058 .ops = &octeon_nic_ops,
1059 .priv_auto = sizeof(struct octeon_eth_info),
1060};