2 * Copyright (C) 2015 Cavium Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include "opt_platform.h"
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bitset.h>
37 #include <sys/bitstring.h>
39 #include <sys/endian.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/module.h>
44 #include <sys/pciio.h>
47 #include <sys/socket.h>
48 #include <sys/sockio.h>
49 #include <sys/cpuset.h>
51 #include <sys/mutex.h>
53 #include <net/ethernet.h>
55 #include <net/if_media.h>
57 #include <machine/bus.h>
59 #include <dev/pci/pcireg.h>
60 #include <dev/pci/pcivar.h>
62 #include "thunder_bgx.h"
63 #include "thunder_bgx_var.h"
69 #define THUNDER_BGX_DEVSTR "ThunderX BGX Ethernet I/O Interface"
71 MALLOC_DEFINE(M_BGX, "thunder_bgx", "ThunderX BGX dynamic memory");
73 #define BGX_NODE_ID_MASK 0x1
74 #define BGX_NODE_ID_SHIFT 24
76 #define DRV_NAME "thunder-BGX"
77 #define DRV_VERSION "1.0"
79 static int bgx_init_phy(struct bgx *);
81 static struct bgx *bgx_vnic[MAX_BGX_THUNDER];
82 static int lmac_count __unused; /* Total no of LMACs in system */
84 static int bgx_xaui_check_link(struct lmac *lmac);
85 static void bgx_get_qlm_mode(struct bgx *);
86 static void bgx_init_hw(struct bgx *);
87 static int bgx_lmac_enable(struct bgx *, uint8_t);
88 static void bgx_lmac_disable(struct bgx *, uint8_t);
90 static int thunder_bgx_probe(device_t);
91 static int thunder_bgx_attach(device_t);
92 static int thunder_bgx_detach(device_t);
94 static device_method_t thunder_bgx_methods[] = {
95 /* Device interface */
96 DEVMETHOD(device_probe, thunder_bgx_probe),
97 DEVMETHOD(device_attach, thunder_bgx_attach),
98 DEVMETHOD(device_detach, thunder_bgx_detach),
103 static driver_t thunder_bgx_driver = {
109 static devclass_t thunder_bgx_devclass;
111 DRIVER_MODULE(thunder_bgx, pci, thunder_bgx_driver, thunder_bgx_devclass, 0, 0);
112 MODULE_DEPEND(thunder_bgx, pci, 1, 1, 1);
113 MODULE_DEPEND(thunder_bgx, ether, 1, 1, 1);
114 MODULE_DEPEND(thunder_bgx, octeon_mdio, 1, 1, 1);
117 thunder_bgx_probe(device_t dev)
122 vendor_id = pci_get_vendor(dev);
123 device_id = pci_get_device(dev);
125 if (vendor_id == PCI_VENDOR_ID_CAVIUM &&
126 device_id == PCI_DEVICE_ID_THUNDER_BGX) {
127 device_set_desc(dev, THUNDER_BGX_DEVSTR);
128 return (BUS_PROBE_DEFAULT);
135 thunder_bgx_attach(device_t dev)
142 bgx = malloc(sizeof(*bgx), M_BGX, (M_WAITOK | M_ZERO));
144 /* Enable bus mastering */
145 pci_enable_busmaster(dev);
146 /* Allocate resources - configuration registers */
147 rid = PCIR_BAR(PCI_CFG_REG_BAR_NUM);
148 bgx->reg_base = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
150 if (bgx->reg_base == NULL) {
151 device_printf(dev, "Could not allocate CSR memory space\n");
153 goto err_disable_device;
156 bgx->bgx_id = (rman_get_start(bgx->reg_base) >> BGX_NODE_ID_SHIFT) &
158 bgx->bgx_id += nic_get_node_id(bgx->reg_base) * MAX_BGX_PER_CN88XX;
160 bgx_vnic[bgx->bgx_id] = bgx;
161 bgx_get_qlm_mode(bgx);
163 err = bgx_init_phy(bgx);
169 /* Enable all LMACs */
170 for (lmac = 0; lmac < bgx->lmac_count; lmac++) {
171 err = bgx_lmac_enable(bgx, lmac);
173 device_printf(dev, "BGX%d failed to enable lmac%d\n",
182 bgx_vnic[bgx->bgx_id] = NULL;
183 bus_release_resource(dev, SYS_RES_MEMORY,
184 rman_get_rid(bgx->reg_base), bgx->reg_base);
187 pci_disable_busmaster(dev);
193 thunder_bgx_detach(device_t dev)
199 lmac = device_get_softc(dev);
201 /* Disable all LMACs */
202 for (lmacid = 0; lmacid < bgx->lmac_count; lmacid++)
203 bgx_lmac_disable(bgx, lmacid);
208 /* Register read/write APIs */
210 bgx_reg_read(struct bgx *bgx, uint8_t lmac, uint64_t offset)
212 bus_space_handle_t addr;
214 addr = ((uint32_t)lmac << 20) + offset;
216 return (bus_read_8(bgx->reg_base, addr));
220 bgx_reg_write(struct bgx *bgx, uint8_t lmac, uint64_t offset, uint64_t val)
222 bus_space_handle_t addr;
224 addr = ((uint32_t)lmac << 20) + offset;
226 bus_write_8(bgx->reg_base, addr, val);
230 bgx_reg_modify(struct bgx *bgx, uint8_t lmac, uint64_t offset, uint64_t val)
232 bus_space_handle_t addr;
234 addr = ((uint32_t)lmac << 20) + offset;
236 bus_write_8(bgx->reg_base, addr, val | bus_read_8(bgx->reg_base, addr));
240 bgx_poll_reg(struct bgx *bgx, uint8_t lmac, uint64_t reg, uint64_t mask,
247 reg_val = bgx_reg_read(bgx, lmac, reg);
248 if (zero && !(reg_val & mask))
250 if (!zero && (reg_val & mask))
259 /* Return number of BGX present in HW */
261 bgx_get_map(int node)
266 for (i = 0; i < MAX_BGX_PER_CN88XX; i++) {
267 if (bgx_vnic[(node * MAX_BGX_PER_CN88XX) + i])
274 /* Return number of LMAC configured for this BGX */
276 bgx_get_lmac_count(int node, int bgx_idx)
280 bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
282 return (bgx->lmac_count);
287 /* Returns the current link status of LMAC */
289 bgx_get_lmac_link_state(int node, int bgx_idx, int lmacid, void *status)
291 struct bgx_link_status *link = (struct bgx_link_status *)status;
295 bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
299 lmac = &bgx->lmac[lmacid];
300 link->link_up = lmac->link_up;
301 link->duplex = lmac->last_duplex;
302 link->speed = lmac->last_speed;
306 *bgx_get_lmac_mac(int node, int bgx_idx, int lmacid)
308 struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
311 return (bgx->lmac[lmacid].mac);
317 bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const uint8_t *mac)
319 struct bgx *bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
324 memcpy(bgx->lmac[lmacid].mac, mac, ETHER_ADDR_LEN);
328 bgx_sgmii_change_link_state(struct lmac *lmac)
330 struct bgx *bgx = lmac->bgx;
332 uint64_t port_cfg = 0;
333 uint64_t misc_ctl = 0;
335 cmr_cfg = bgx_reg_read(bgx, lmac->lmacid, BGX_CMRX_CFG);
337 bgx_reg_write(bgx, lmac->lmacid, BGX_CMRX_CFG, cmr_cfg);
339 port_cfg = bgx_reg_read(bgx, lmac->lmacid, BGX_GMP_GMI_PRTX_CFG);
340 misc_ctl = bgx_reg_read(bgx, lmac->lmacid, BGX_GMP_PCS_MISCX_CTL);
343 misc_ctl &= ~PCS_MISC_CTL_GMX_ENO;
344 port_cfg &= ~GMI_PORT_CFG_DUPLEX;
345 port_cfg |= (lmac->last_duplex << 2);
347 misc_ctl |= PCS_MISC_CTL_GMX_ENO;
350 switch (lmac->last_speed) {
352 port_cfg &= ~GMI_PORT_CFG_SPEED; /* speed 0 */
353 port_cfg |= GMI_PORT_CFG_SPEED_MSB; /* speed_msb 1 */
354 port_cfg &= ~GMI_PORT_CFG_SLOT_TIME; /* slottime 0 */
355 misc_ctl &= ~PCS_MISC_CTL_SAMP_PT_MASK;
356 misc_ctl |= 50; /* samp_pt */
357 bgx_reg_write(bgx, lmac->lmacid, BGX_GMP_GMI_TXX_SLOT, 64);
358 bgx_reg_write(bgx, lmac->lmacid, BGX_GMP_GMI_TXX_BURST, 0);
361 port_cfg &= ~GMI_PORT_CFG_SPEED; /* speed 0 */
362 port_cfg &= ~GMI_PORT_CFG_SPEED_MSB; /* speed_msb 0 */
363 port_cfg &= ~GMI_PORT_CFG_SLOT_TIME; /* slottime 0 */
364 misc_ctl &= ~PCS_MISC_CTL_SAMP_PT_MASK;
365 misc_ctl |= 5; /* samp_pt */
366 bgx_reg_write(bgx, lmac->lmacid, BGX_GMP_GMI_TXX_SLOT, 64);
367 bgx_reg_write(bgx, lmac->lmacid, BGX_GMP_GMI_TXX_BURST, 0);
370 port_cfg |= GMI_PORT_CFG_SPEED; /* speed 1 */
371 port_cfg &= ~GMI_PORT_CFG_SPEED_MSB; /* speed_msb 0 */
372 port_cfg |= GMI_PORT_CFG_SLOT_TIME; /* slottime 1 */
373 misc_ctl &= ~PCS_MISC_CTL_SAMP_PT_MASK;
374 misc_ctl |= 1; /* samp_pt */
375 bgx_reg_write(bgx, lmac->lmacid, BGX_GMP_GMI_TXX_SLOT, 512);
376 if (lmac->last_duplex)
377 bgx_reg_write(bgx, lmac->lmacid,
378 BGX_GMP_GMI_TXX_BURST, 0);
380 bgx_reg_write(bgx, lmac->lmacid,
381 BGX_GMP_GMI_TXX_BURST, 8192);
386 bgx_reg_write(bgx, lmac->lmacid, BGX_GMP_PCS_MISCX_CTL, misc_ctl);
387 bgx_reg_write(bgx, lmac->lmacid, BGX_GMP_GMI_PRTX_CFG, port_cfg);
389 port_cfg = bgx_reg_read(bgx, lmac->lmacid, BGX_GMP_GMI_PRTX_CFG);
393 bgx_reg_write(bgx, lmac->lmacid, BGX_CMRX_CFG, cmr_cfg);
397 bgx_lmac_handler(void *arg)
400 int link, duplex, speed;
401 int link_changed = 0;
404 lmac = (struct lmac *)arg;
406 err = LMAC_MEDIA_STATUS(lmac->phy_if_dev, lmac->lmacid,
407 &link, &duplex, &speed);
411 if (!link && lmac->last_link)
415 (lmac->last_duplex != duplex ||
416 lmac->last_link != link ||
417 lmac->last_speed != speed)) {
421 lmac->last_link = link;
422 lmac->last_speed = speed;
423 lmac->last_duplex = duplex;
428 if (link_changed > 0)
429 lmac->link_up = true;
431 lmac->link_up = false;
434 bgx_sgmii_change_link_state(lmac);
436 bgx_xaui_check_link(lmac);
439 callout_reset(&lmac->check_link, hz * 2, bgx_lmac_handler, lmac);
443 bgx_get_rx_stats(int node, int bgx_idx, int lmac, int idx)
447 bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
453 return (bgx_reg_read(bgx, lmac, BGX_CMRX_RX_STAT0 + (idx * 8)));
457 bgx_get_tx_stats(int node, int bgx_idx, int lmac, int idx)
461 bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
465 return (bgx_reg_read(bgx, lmac, BGX_CMRX_TX_STAT0 + (idx * 8)));
469 bgx_flush_dmac_addrs(struct bgx *bgx, int lmac)
473 while (bgx->lmac[lmac].dmac > 0) {
474 offset = ((bgx->lmac[lmac].dmac - 1) * sizeof(uint64_t)) +
475 (lmac * MAX_DMAC_PER_LMAC * sizeof(uint64_t));
476 bgx_reg_write(bgx, 0, BGX_CMR_RX_DMACX_CAM + offset, 0);
477 bgx->lmac[lmac].dmac--;
482 bgx_add_dmac_addr(uint64_t dmac, int node, int bgx_idx, int lmac)
487 #ifdef BGX_IN_PROMISCUOUS_MODE
491 bgx_idx += node * MAX_BGX_PER_CN88XX;
492 bgx = bgx_vnic[bgx_idx];
495 device_printf(bgx->dev,
496 "BGX%d not yet initialized, ignoring DMAC addition\n",
501 dmac = dmac | (1UL << 48) | ((uint64_t)lmac << 49); /* Enable DMAC */
502 if (bgx->lmac[lmac].dmac == MAX_DMAC_PER_LMAC) {
503 device_printf(bgx->dev,
504 "Max DMAC filters for LMAC%d reached, ignoring\n",
509 if (bgx->lmac[lmac].dmac == MAX_DMAC_PER_LMAC_TNS_BYPASS_MODE)
510 bgx->lmac[lmac].dmac = 1;
512 offset = (bgx->lmac[lmac].dmac * sizeof(uint64_t)) +
513 (lmac * MAX_DMAC_PER_LMAC * sizeof(uint64_t));
514 bgx_reg_write(bgx, 0, BGX_CMR_RX_DMACX_CAM + offset, dmac);
515 bgx->lmac[lmac].dmac++;
517 bgx_reg_write(bgx, lmac, BGX_CMRX_RX_DMAC_CTL,
518 (CAM_ACCEPT << 3) | (MCAST_MODE_CAM_FILTER << 1) |
519 (BCAST_ACCEPT << 0));
522 /* Configure BGX LMAC in internal loopback mode */
524 bgx_lmac_internal_loopback(int node, int bgx_idx,
525 int lmac_idx, boolean_t enable)
531 bgx = bgx_vnic[(node * MAX_BGX_PER_CN88XX) + bgx_idx];
535 lmac = &bgx->lmac[lmac_idx];
536 if (lmac->is_sgmii) {
537 cfg = bgx_reg_read(bgx, lmac_idx, BGX_GMP_PCS_MRX_CTL);
539 cfg |= PCS_MRX_CTL_LOOPBACK1;
541 cfg &= ~PCS_MRX_CTL_LOOPBACK1;
542 bgx_reg_write(bgx, lmac_idx, BGX_GMP_PCS_MRX_CTL, cfg);
544 cfg = bgx_reg_read(bgx, lmac_idx, BGX_SPUX_CONTROL1);
546 cfg |= SPU_CTL_LOOPBACK;
548 cfg &= ~SPU_CTL_LOOPBACK;
549 bgx_reg_write(bgx, lmac_idx, BGX_SPUX_CONTROL1, cfg);
554 bgx_lmac_sgmii_init(struct bgx *bgx, int lmacid)
558 bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_THRESH, 0x30);
559 /* max packet size */
560 bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_RXX_JABBER, MAX_FRAME_SIZE);
562 /* Disable frame alignment if using preamble */
563 cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_GMI_TXX_APPEND);
565 bgx_reg_write(bgx, lmacid, BGX_GMP_GMI_TXX_SGMII_CTL, 0);
568 bgx_reg_modify(bgx, lmacid, BGX_CMRX_CFG, CMR_EN);
571 bgx_reg_modify(bgx, lmacid, BGX_GMP_PCS_MRX_CTL, PCS_MRX_CTL_RESET);
572 if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_CTL,
573 PCS_MRX_CTL_RESET, TRUE) != 0) {
574 device_printf(bgx->dev, "BGX PCS reset not completed\n");
578 /* power down, reset autoneg, autoneg enable */
579 cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_PCS_MRX_CTL);
580 cfg &= ~PCS_MRX_CTL_PWR_DN;
581 cfg |= (PCS_MRX_CTL_RST_AN | PCS_MRX_CTL_AN_EN);
582 bgx_reg_write(bgx, lmacid, BGX_GMP_PCS_MRX_CTL, cfg);
584 if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS,
585 PCS_MRX_STATUS_AN_CPT, FALSE) != 0) {
586 device_printf(bgx->dev, "BGX AN_CPT not completed\n");
594 bgx_lmac_xaui_init(struct bgx *bgx, int lmacid, int lmac_type)
599 bgx_reg_modify(bgx, lmacid, BGX_SPUX_CONTROL1, SPU_CTL_RESET);
600 if (bgx_poll_reg(bgx, lmacid, BGX_SPUX_CONTROL1,
601 SPU_CTL_RESET, TRUE) != 0) {
602 device_printf(bgx->dev, "BGX SPU reset not completed\n");
607 cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
609 bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg);
611 bgx_reg_modify(bgx, lmacid, BGX_SPUX_CONTROL1, SPU_CTL_LOW_POWER);
612 /* Set interleaved running disparity for RXAUI */
613 if (bgx->lmac_type != BGX_MODE_RXAUI) {
614 bgx_reg_modify(bgx, lmacid,
615 BGX_SPUX_MISC_CONTROL, SPU_MISC_CTL_RX_DIS);
617 bgx_reg_modify(bgx, lmacid, BGX_SPUX_MISC_CONTROL,
618 SPU_MISC_CTL_RX_DIS | SPU_MISC_CTL_INTLV_RDISP);
621 /* clear all interrupts */
622 cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_RX_INT);
623 bgx_reg_write(bgx, lmacid, BGX_SMUX_RX_INT, cfg);
624 cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_TX_INT);
625 bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_INT, cfg);
626 cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_INT);
627 bgx_reg_write(bgx, lmacid, BGX_SPUX_INT, cfg);
629 if (bgx->use_training) {
630 bgx_reg_write(bgx, lmacid, BGX_SPUX_BR_PMD_LP_CUP, 0x00);
631 bgx_reg_write(bgx, lmacid, BGX_SPUX_BR_PMD_LD_CUP, 0x00);
632 bgx_reg_write(bgx, lmacid, BGX_SPUX_BR_PMD_LD_REP, 0x00);
633 /* training enable */
634 bgx_reg_modify(bgx, lmacid, BGX_SPUX_BR_PMD_CRTL,
635 SPU_PMD_CRTL_TRAIN_EN);
638 /* Append FCS to each packet */
639 bgx_reg_modify(bgx, lmacid, BGX_SMUX_TX_APPEND, SMU_TX_APPEND_FCS_D);
641 /* Disable forward error correction */
642 cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_FEC_CONTROL);
643 cfg &= ~SPU_FEC_CTL_FEC_EN;
644 bgx_reg_write(bgx, lmacid, BGX_SPUX_FEC_CONTROL, cfg);
646 /* Disable autoneg */
647 cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_AN_CONTROL);
648 cfg = cfg & ~(SPU_AN_CTL_AN_EN | SPU_AN_CTL_XNP_EN);
649 bgx_reg_write(bgx, lmacid, BGX_SPUX_AN_CONTROL, cfg);
651 cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_AN_ADV);
652 if (bgx->lmac_type == BGX_MODE_10G_KR)
654 else if (bgx->lmac_type == BGX_MODE_40G_KR)
657 cfg &= ~((1 << 23) | (1 << 24));
658 cfg = cfg & (~((1UL << 25) | (1UL << 22) | (1UL << 12)));
659 bgx_reg_write(bgx, lmacid, BGX_SPUX_AN_ADV, cfg);
661 cfg = bgx_reg_read(bgx, 0, BGX_SPU_DBG_CONTROL);
662 cfg &= ~SPU_DBG_CTL_AN_ARB_LINK_CHK_EN;
663 bgx_reg_write(bgx, 0, BGX_SPU_DBG_CONTROL, cfg);
666 bgx_reg_modify(bgx, lmacid, BGX_CMRX_CFG, CMR_EN);
668 cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_CONTROL1);
669 cfg &= ~SPU_CTL_LOW_POWER;
670 bgx_reg_write(bgx, lmacid, BGX_SPUX_CONTROL1, cfg);
672 cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_TX_CTL);
673 cfg &= ~SMU_TX_CTL_UNI_EN;
674 cfg |= SMU_TX_CTL_DIC_EN;
675 bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_CTL, cfg);
677 /* take lmac_count into account */
678 bgx_reg_modify(bgx, lmacid, BGX_SMUX_TX_THRESH, (0x100 - 1));
679 /* max packet size */
680 bgx_reg_modify(bgx, lmacid, BGX_SMUX_RX_JABBER, MAX_FRAME_SIZE);
686 bgx_xaui_check_link(struct lmac *lmac)
688 struct bgx *bgx = lmac->bgx;
689 int lmacid = lmac->lmacid;
690 int lmac_type = bgx->lmac_type;
693 bgx_reg_modify(bgx, lmacid, BGX_SPUX_MISC_CONTROL, SPU_MISC_CTL_RX_DIS);
694 if (bgx->use_training) {
695 cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_INT);
696 if ((cfg & (1UL << 13)) == 0) {
697 cfg = (1UL << 13) | (1UL << 14);
698 bgx_reg_write(bgx, lmacid, BGX_SPUX_INT, cfg);
699 cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_BR_PMD_CRTL);
701 bgx_reg_write(bgx, lmacid, BGX_SPUX_BR_PMD_CRTL, cfg);
706 /* wait for PCS to come out of reset */
707 if (bgx_poll_reg(bgx, lmacid, BGX_SPUX_CONTROL1,
708 SPU_CTL_RESET, TRUE) != 0) {
709 device_printf(bgx->dev, "BGX SPU reset not completed\n");
713 if ((lmac_type == BGX_MODE_10G_KR) || (lmac_type == BGX_MODE_XFI) ||
714 (lmac_type == BGX_MODE_40G_KR) || (lmac_type == BGX_MODE_XLAUI)) {
715 if (bgx_poll_reg(bgx, lmacid, BGX_SPUX_BR_STATUS1,
716 SPU_BR_STATUS_BLK_LOCK, FALSE)) {
717 device_printf(bgx->dev,
718 "SPU_BR_STATUS_BLK_LOCK not completed\n");
722 if (bgx_poll_reg(bgx, lmacid, BGX_SPUX_BX_STATUS,
723 SPU_BX_STATUS_RX_ALIGN, FALSE) != 0) {
724 device_printf(bgx->dev,
725 "SPU_BX_STATUS_RX_ALIGN not completed\n");
730 /* Clear rcvflt bit (latching high) and read it back */
731 bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS2, SPU_STATUS2_RCVFLT);
732 if (bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) & SPU_STATUS2_RCVFLT) {
733 device_printf(bgx->dev, "Receive fault, retry training\n");
734 if (bgx->use_training) {
735 cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_INT);
736 if ((cfg & (1UL << 13)) == 0) {
737 cfg = (1UL << 13) | (1UL << 14);
738 bgx_reg_write(bgx, lmacid, BGX_SPUX_INT, cfg);
739 cfg = bgx_reg_read(bgx, lmacid,
740 BGX_SPUX_BR_PMD_CRTL);
742 bgx_reg_write(bgx, lmacid,
743 BGX_SPUX_BR_PMD_CRTL, cfg);
750 /* Wait for MAC RX to be ready */
751 if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_RX_CTL,
752 SMU_RX_CTL_STATUS, TRUE) != 0) {
753 device_printf(bgx->dev, "SMU RX link not okay\n");
757 /* Wait for BGX RX to be idle */
758 if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_CTL,
759 SMU_CTL_RX_IDLE, FALSE) != 0) {
760 device_printf(bgx->dev, "SMU RX not idle\n");
764 /* Wait for BGX TX to be idle */
765 if (bgx_poll_reg(bgx, lmacid, BGX_SMUX_CTL,
766 SMU_CTL_TX_IDLE, FALSE) != 0) {
767 device_printf(bgx->dev, "SMU TX not idle\n");
771 if ((bgx_reg_read(bgx, lmacid, BGX_SPUX_STATUS2) &
772 SPU_STATUS2_RCVFLT) != 0) {
773 device_printf(bgx->dev, "Receive fault\n");
777 /* Receive link is latching low. Force it high and verify it */
778 bgx_reg_modify(bgx, lmacid, BGX_SPUX_STATUS1, SPU_STATUS1_RCV_LNK);
779 if (bgx_poll_reg(bgx, lmacid, BGX_SPUX_STATUS1,
780 SPU_STATUS1_RCV_LNK, FALSE) != 0) {
781 device_printf(bgx->dev, "SPU receive link down\n");
785 cfg = bgx_reg_read(bgx, lmacid, BGX_SPUX_MISC_CONTROL);
786 cfg &= ~SPU_MISC_CTL_RX_DIS;
787 bgx_reg_write(bgx, lmacid, BGX_SPUX_MISC_CONTROL, cfg);
792 bgx_poll_for_link(void *arg)
797 lmac = (struct lmac *)arg;
799 /* Receive link is latching low. Force it high and verify it */
800 bgx_reg_modify(lmac->bgx, lmac->lmacid,
801 BGX_SPUX_STATUS1, SPU_STATUS1_RCV_LNK);
802 bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1,
803 SPU_STATUS1_RCV_LNK, false);
805 link = bgx_reg_read(lmac->bgx, lmac->lmacid, BGX_SPUX_STATUS1);
806 if (link & SPU_STATUS1_RCV_LNK) {
808 if (lmac->bgx->lmac_type == BGX_MODE_XLAUI)
809 lmac->last_speed = 40000;
811 lmac->last_speed = 10000;
812 lmac->last_duplex = 1;
817 if (lmac->last_link != lmac->link_up) {
818 lmac->last_link = lmac->link_up;
820 bgx_xaui_check_link(lmac);
823 callout_reset(&lmac->check_link, hz * 2, bgx_poll_for_link, lmac);
827 bgx_lmac_enable(struct bgx *bgx, uint8_t lmacid)
829 uint64_t __unused dmac_bcast = (1UL << 48) - 1;
833 lmac = &bgx->lmac[lmacid];
836 if (bgx->lmac_type == BGX_MODE_SGMII) {
838 if (bgx_lmac_sgmii_init(bgx, lmacid) != 0)
842 if (bgx_lmac_xaui_init(bgx, lmacid, bgx->lmac_type))
846 if (lmac->is_sgmii) {
847 cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_GMI_TXX_APPEND);
848 cfg |= ((1UL << 2) | (1UL << 1)); /* FCS and PAD */
849 bgx_reg_modify(bgx, lmacid, BGX_GMP_GMI_TXX_APPEND, cfg);
850 bgx_reg_write(bgx, lmacid, BGX_GMP_GMI_TXX_MIN_PKT, 60 - 1);
852 cfg = bgx_reg_read(bgx, lmacid, BGX_SMUX_TX_APPEND);
853 cfg |= ((1UL << 2) | (1UL << 1)); /* FCS and PAD */
854 bgx_reg_modify(bgx, lmacid, BGX_SMUX_TX_APPEND, cfg);
855 bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_MIN_PKT, 60 + 4);
859 bgx_reg_modify(bgx, lmacid, BGX_CMRX_CFG,
860 CMR_EN | CMR_PKT_RX_EN | CMR_PKT_TX_EN);
862 /* Restore default cfg, incase low level firmware changed it */
863 bgx_reg_write(bgx, lmacid, BGX_CMRX_RX_DMAC_CTL, 0x03);
865 /* Add broadcast MAC into all LMAC's DMAC filters */
866 bgx_add_dmac_addr(dmac_bcast, 0, bgx->bgx_id, lmacid);
868 if ((bgx->lmac_type != BGX_MODE_XFI) &&
869 (bgx->lmac_type != BGX_MODE_XAUI) &&
870 (bgx->lmac_type != BGX_MODE_XLAUI) &&
871 (bgx->lmac_type != BGX_MODE_40G_KR) &&
872 (bgx->lmac_type != BGX_MODE_10G_KR)) {
873 if (lmac->phy_if_dev == NULL) {
874 device_printf(bgx->dev,
875 "LMAC%d missing interface to PHY\n", lmacid);
879 if (LMAC_PHY_CONNECT(lmac->phy_if_dev, lmac->phyaddr,
881 device_printf(bgx->dev,
882 "LMAC%d could not connect to PHY\n", lmacid);
885 mtx_init(&lmac->check_link_mtx, "BGX link poll", NULL, MTX_DEF);
886 callout_init_mtx(&lmac->check_link, &lmac->check_link_mtx, 0);
887 mtx_lock(&lmac->check_link_mtx);
888 bgx_lmac_handler(lmac);
889 mtx_unlock(&lmac->check_link_mtx);
891 mtx_init(&lmac->check_link_mtx, "BGX link poll", NULL, MTX_DEF);
892 callout_init_mtx(&lmac->check_link, &lmac->check_link_mtx, 0);
893 mtx_lock(&lmac->check_link_mtx);
894 bgx_poll_for_link(lmac);
895 mtx_unlock(&lmac->check_link_mtx);
902 bgx_lmac_disable(struct bgx *bgx, uint8_t lmacid)
907 lmac = &bgx->lmac[lmacid];
910 callout_drain(&lmac->check_link);
911 mtx_destroy(&lmac->check_link_mtx);
913 cmrx_cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_CFG);
914 cmrx_cfg &= ~(1 << 15);
915 bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cmrx_cfg);
916 bgx_flush_dmac_addrs(bgx, lmacid);
918 if ((bgx->lmac_type != BGX_MODE_XFI) &&
919 (bgx->lmac_type != BGX_MODE_XLAUI) &&
920 (bgx->lmac_type != BGX_MODE_40G_KR) &&
921 (bgx->lmac_type != BGX_MODE_10G_KR)) {
922 if (lmac->phy_if_dev == NULL) {
923 device_printf(bgx->dev,
924 "LMAC%d missing interface to PHY\n", lmacid);
927 if (LMAC_PHY_DISCONNECT(lmac->phy_if_dev, lmac->phyaddr,
929 device_printf(bgx->dev,
930 "LMAC%d could not disconnect PHY\n", lmacid);
933 lmac->phy_if_dev = NULL;
938 bgx_set_num_ports(struct bgx *bgx)
942 switch (bgx->qlm_mode) {
945 bgx->lmac_type = BGX_MODE_SGMII;
946 bgx->lane_to_sds = 0;
948 case QLM_MODE_XAUI_1X4:
950 bgx->lmac_type = BGX_MODE_XAUI;
951 bgx->lane_to_sds = 0xE4;
953 case QLM_MODE_RXAUI_2X2:
955 bgx->lmac_type = BGX_MODE_RXAUI;
956 bgx->lane_to_sds = 0xE4;
958 case QLM_MODE_XFI_4X1:
960 bgx->lmac_type = BGX_MODE_XFI;
961 bgx->lane_to_sds = 0;
963 case QLM_MODE_XLAUI_1X4:
965 bgx->lmac_type = BGX_MODE_XLAUI;
966 bgx->lane_to_sds = 0xE4;
968 case QLM_MODE_10G_KR_4X1:
970 bgx->lmac_type = BGX_MODE_10G_KR;
971 bgx->lane_to_sds = 0;
972 bgx->use_training = 1;
974 case QLM_MODE_40G_KR4_1X4:
976 bgx->lmac_type = BGX_MODE_40G_KR;
977 bgx->lane_to_sds = 0xE4;
978 bgx->use_training = 1;
986 * Check if low level firmware has programmed LMAC count
987 * based on board type, if yes consider that otherwise
988 * the default static values
990 lmac_count = bgx_reg_read(bgx, 0, BGX_CMR_RX_LMACS) & 0x7;
992 bgx->lmac_count = lmac_count;
996 bgx_init_hw(struct bgx *bgx)
1000 bgx_set_num_ports(bgx);
1002 bgx_reg_modify(bgx, 0, BGX_CMR_GLOBAL_CFG, CMR_GLOBAL_CFG_FCS_STRIP);
1003 if (bgx_reg_read(bgx, 0, BGX_CMR_BIST_STATUS))
1004 device_printf(bgx->dev, "BGX%d BIST failed\n", bgx->bgx_id);
1006 /* Set lmac type and lane2serdes mapping */
1007 for (i = 0; i < bgx->lmac_count; i++) {
1008 if (bgx->lmac_type == BGX_MODE_RXAUI) {
1010 bgx->lane_to_sds = 0x0e;
1012 bgx->lane_to_sds = 0x04;
1013 bgx_reg_write(bgx, i, BGX_CMRX_CFG,
1014 (bgx->lmac_type << 8) | bgx->lane_to_sds);
1017 bgx_reg_write(bgx, i, BGX_CMRX_CFG,
1018 (bgx->lmac_type << 8) | (bgx->lane_to_sds + i));
1019 bgx->lmac[i].lmacid_bd = lmac_count;
1023 bgx_reg_write(bgx, 0, BGX_CMR_TX_LMACS, bgx->lmac_count);
1024 bgx_reg_write(bgx, 0, BGX_CMR_RX_LMACS, bgx->lmac_count);
1026 /* Set the backpressure AND mask */
1027 for (i = 0; i < bgx->lmac_count; i++) {
1028 bgx_reg_modify(bgx, 0, BGX_CMR_CHAN_MSK_AND,
1029 ((1UL << MAX_BGX_CHANS_PER_LMAC) - 1) <<
1030 (i * MAX_BGX_CHANS_PER_LMAC));
1033 /* Disable all MAC filtering */
1034 for (i = 0; i < RX_DMAC_COUNT; i++)
1035 bgx_reg_write(bgx, 0, BGX_CMR_RX_DMACX_CAM + (i * 8), 0x00);
1037 /* Disable MAC steering (NCSI traffic) */
1038 for (i = 0; i < RX_TRAFFIC_STEER_RULE_COUNT; i++)
1039 bgx_reg_write(bgx, 0, BGX_CMR_RX_STREERING + (i * 8), 0x00);
1043 bgx_get_qlm_mode(struct bgx *bgx)
1045 device_t dev = bgx->dev;;
1049 /* Read LMAC0 type to figure out QLM mode
1050 * This is configured by low level firmware
1052 lmac_type = bgx_reg_read(bgx, 0, BGX_CMRX_CFG);
1053 lmac_type = (lmac_type >> 8) & 0x07;
1055 train_en = bgx_reg_read(bgx, 0, BGX_SPUX_BR_PMD_CRTL) &
1056 SPU_PMD_CRTL_TRAIN_EN;
1058 switch (lmac_type) {
1059 case BGX_MODE_SGMII:
1060 bgx->qlm_mode = QLM_MODE_SGMII;
1062 device_printf(dev, "BGX%d QLM mode: SGMII\n",
1067 bgx->qlm_mode = QLM_MODE_XAUI_1X4;
1069 device_printf(dev, "BGX%d QLM mode: XAUI\n",
1073 case BGX_MODE_RXAUI:
1074 bgx->qlm_mode = QLM_MODE_RXAUI_2X2;
1076 device_printf(dev, "BGX%d QLM mode: RXAUI\n",
1082 bgx->qlm_mode = QLM_MODE_XFI_4X1;
1084 device_printf(dev, "BGX%d QLM mode: XFI\n",
1088 bgx->qlm_mode = QLM_MODE_10G_KR_4X1;
1090 device_printf(dev, "BGX%d QLM mode: 10G_KR\n",
1095 case BGX_MODE_XLAUI:
1097 bgx->qlm_mode = QLM_MODE_XLAUI_1X4;
1099 device_printf(dev, "BGX%d QLM mode: XLAUI\n",
1103 bgx->qlm_mode = QLM_MODE_40G_KR4_1X4;
1105 device_printf(dev, "BGX%d QLM mode: 40G_KR4\n",
1111 bgx->qlm_mode = QLM_MODE_SGMII;
1113 device_printf(dev, "BGX%d QLM default mode: SGMII\n",
1120 bgx_init_phy(struct bgx *bgx)
1124 /* By default we fail */
1127 err = bgx_fdt_init_phy(bgx);
1131 /* ARM64TODO: Add ACPI function here */