diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Kconfig | 8 | ||||
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/bnxt/bnxt.c | 9 | ||||
-rw-r--r-- | drivers/net/e1000.c | 4 | ||||
-rw-r--r-- | drivers/net/fsl_enetc.c | 2 | ||||
-rw-r--r-- | drivers/net/fsl_enetc_mdio.c | 2 | ||||
-rw-r--r-- | drivers/net/mscc_eswitch/felix_switch.c | 4 | ||||
-rw-r--r-- | drivers/net/mvneta.c | 343 | ||||
-rw-r--r-- | drivers/net/octeon/Makefile | 6 | ||||
-rw-r--r-- | drivers/net/octeon/octeon_eth.c | 1060 | ||||
-rw-r--r-- | drivers/net/octeon/octeon_mdio.c | 226 | ||||
-rw-r--r-- | drivers/net/octeontx/bgx.c | 2 | ||||
-rw-r--r-- | drivers/net/octeontx/nic_main.c | 2 | ||||
-rw-r--r-- | drivers/net/octeontx/nicvf_main.c | 2 | ||||
-rw-r--r-- | drivers/net/octeontx/smi.c | 2 | ||||
-rw-r--r-- | drivers/net/octeontx2/cgx.c | 2 | ||||
-rw-r--r-- | drivers/net/octeontx2/rvu_af.c | 2 | ||||
-rw-r--r-- | drivers/net/octeontx2/rvu_pf.c | 3 | ||||
-rw-r--r-- | drivers/net/pch_gbe.c | 2 |
19 files changed, 1391 insertions, 291 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 347fe8aa425..7fe0e00649c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -445,6 +445,7 @@ config MVNETA bool "Marvell Armada XP/385/3700 network interface support" depends on ARMADA_XP || ARMADA_38X || ARMADA_3700 select PHYLIB + select DM_MDIO help This driver supports the network interface units in the Marvell ARMADA XP, ARMADA 38X and ARMADA 3700 SoCs @@ -495,6 +496,13 @@ config MT7628_ETH The MediaTek MT7628 ethernet interface is used on MT7628 and MT7688 based boards. +config NET_OCTEON + bool "MIPS Octeon ethernet support" + depends on ARCH_OCTEON + help + You must select Y to enable network device support for + MIPS Octeon SoCs. If unsure, say n + config NET_OCTEONTX bool "OcteonTX Ethernet support" depends on ARCH_OCTEONTX diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 16733d2d1f8..69fb3bbbf7c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -64,6 +64,7 @@ obj-$(CONFIG_MVMDIO) += mvmdio.o obj-$(CONFIG_MVNETA) += mvneta.o obj-$(CONFIG_MVPP2) += mvpp2.o obj-$(CONFIG_NETCONSOLE) += netconsole.o +obj-$(CONFIG_NET_OCTEON) += octeon/ obj-$(CONFIG_NET_OCTEONTX) += octeontx/ obj-$(CONFIG_NET_OCTEONTX2) += octeontx2/ obj-$(CONFIG_OCTEONTX2_CGX_INTF) += octeontx2/cgx_intf.o diff --git a/drivers/net/bnxt/bnxt.c b/drivers/net/bnxt/bnxt.c index 9844e96072e..1c9a9962408 100644 --- a/drivers/net/bnxt/bnxt.c +++ b/drivers/net/bnxt/bnxt.c @@ -28,9 +28,12 @@ static void bnxt_bring_pci(struct bnxt *bp) dm_pci_read_config16(bp->pdev, PCI_SUBSYSTEM_ID, &bp->subsystem_device); dm_pci_read_config16(bp->pdev, PCI_COMMAND, &bp->cmd_reg); dm_pci_read_config8(bp->pdev, PCI_INTERRUPT_LINE, &bp->irq); - bp->bar0 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); - bp->bar1 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_2, PCI_REGION_MEM); - bp->bar2 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_4, PCI_REGION_MEM); + bp->bar0 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); + bp->bar1 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_2, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); + bp->bar2 = dm_pci_map_bar(bp->pdev, PCI_BASE_ADDRESS_4, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); cmd_reg = bp->cmd_reg | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; cmd_reg |= PCI_COMMAND_INTX_DISABLE; /* disable intr */ dm_pci_write_config16(bp->pdev, PCI_COMMAND, cmd_reg); diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 4e34248ff6f..5fe016ebaf7 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -5549,8 +5549,8 @@ static int e1000_init_one(struct e1000_hw *hw, int cardnum, pci_dev_t devno, hw->eeprom_semaphore_present = true; #endif #ifdef CONFIG_DM_ETH - hw->hw_addr = dm_pci_map_bar(devno, PCI_BASE_ADDRESS_0, - PCI_REGION_MEM); + hw->hw_addr = dm_pci_map_bar(devno, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); #else hw->hw_addr = pci_map_bar(devno, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); diff --git a/drivers/net/fsl_enetc.c b/drivers/net/fsl_enetc.c index 1724f948bcd..9b97a03ccb3 100644 --- a/drivers/net/fsl_enetc.c +++ b/drivers/net/fsl_enetc.c @@ -339,7 +339,7 @@ static int enetc_probe(struct udevice *dev) } /* initialize register */ - priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0); + priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, 0); if (!priv->regs_base) { enetc_dbg(dev, "failed to map BAR0\n"); return -EINVAL; diff --git a/drivers/net/fsl_enetc_mdio.c b/drivers/net/fsl_enetc_mdio.c index 3eb6ac9fc8f..50ad76dfeb5 100644 --- a/drivers/net/fsl_enetc_mdio.c +++ b/drivers/net/fsl_enetc_mdio.c @@ -125,7 +125,7 @@ static int enetc_mdio_probe(struct udevice *dev) { struct enetc_mdio_priv *priv = dev_get_priv(dev); - priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0); + priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, 0); if (!priv->regs_base) { enetc_dbg(dev, "failed to map BAR0\n"); return -EINVAL; diff --git a/drivers/net/mscc_eswitch/felix_switch.c b/drivers/net/mscc_eswitch/felix_switch.c index 60b2e8f32d4..709c9e3ef51 100644 --- a/drivers/net/mscc_eswitch/felix_switch.c +++ b/drivers/net/mscc_eswitch/felix_switch.c @@ -292,13 +292,13 @@ static int felix_probe(struct udevice *dev) return -ENODEV; } - priv->imdio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0); + priv->imdio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, 0); if (!priv->imdio_base) { dev_err(dev, "failed to map BAR0\n"); return -EINVAL; } - priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, 0); + priv->regs_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, 0, 0, PCI_REGION_TYPE, 0); if (!priv->regs_base) { dev_err(dev, "failed to map BAR4\n"); return -EINVAL; diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c index 15dc7140587..d2c42c43961 100644 --- a/drivers/net/mvneta.c +++ b/drivers/net/mvneta.c @@ -40,11 +40,7 @@ DECLARE_GLOBAL_DATA_PTR; -#if !defined(CONFIG_PHYLIB) -# error Marvell mvneta requires PHYLIB -#endif - -#define CONFIG_NR_CPUS 1 +#define MVNETA_NR_CPUS 1 #define ETH_HLEN 14 /* Total octets in header */ /* 2(HW hdr) 14(MAC hdr) 4(CRC) 32(extra for cache prefetch) */ @@ -192,7 +188,6 @@ DECLARE_GLOBAL_DATA_PTR; #define MVNETA_GMAC_AUTONEG_CONFIG 0x2c0c #define MVNETA_GMAC_FORCE_LINK_DOWN BIT(0) #define MVNETA_GMAC_FORCE_LINK_PASS BIT(1) -#define MVNETA_GMAC_FORCE_LINK_UP (BIT(0) | BIT(1)) #define MVNETA_GMAC_IB_BYPASS_AN_EN BIT(3) #define MVNETA_GMAC_CONFIG_MII_SPEED BIT(5) #define MVNETA_GMAC_CONFIG_GMII_SPEED BIT(6) @@ -282,13 +277,11 @@ struct mvneta_port { unsigned int speed; int init; - int phyaddr; struct phy_device *phydev; #if CONFIG_IS_ENABLED(DM_GPIO) struct gpio_desc phy_reset_gpio; struct gpio_desc sfp_tx_disable_gpio; #endif - struct mii_dev *bus; }; /* The mvneta_tx_desc and mvneta_rx_desc structures describe the @@ -414,15 +407,6 @@ static struct buffer_location buffer_loc; */ #define BD_SPACE (1 << 20) -/* - * Dummy implementation that can be overwritten by a board - * specific function - */ -__weak int board_network_enable(struct mii_dev *bus) -{ - return 0; -} - /* Utility/helper methods */ /* Write helper method */ @@ -576,13 +560,6 @@ static void mvneta_rxq_buf_size_set(struct mvneta_port *pp, mvreg_write(pp, MVNETA_RXQ_SIZE_REG(rxq->id), val); } -static int mvneta_port_is_fixed_link(struct mvneta_port *pp) -{ - /* phy_addr is set to invalid value for fixed link */ - return pp->phyaddr > PHY_MAX_ADDR; -} - - /* Start the Ethernet port RX and TX activity */ static void mvneta_port_up(struct mvneta_port *pp) { @@ -791,7 +768,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp) /* Set CPU queue access map - all CPUs have access to all RX * queues and to all TX queues */ - for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) + for (cpu = 0; cpu < MVNETA_NR_CPUS; cpu++) mvreg_write(pp, MVNETA_CPU_MAP(cpu), (MVNETA_CPU_RXQ_ACCESS_ALL_MASK | MVNETA_CPU_TXQ_ACCESS_ALL_MASK)); @@ -834,7 +811,10 @@ static void mvneta_defaults_set(struct mvneta_port *pp) mvreg_write(pp, MVNETA_SDMA_CONFIG, val); /* Enable PHY polling in hardware if not in fixed-link mode */ - if (!mvneta_port_is_fixed_link(pp)) { + if (!CONFIG_IS_ENABLED(PHY_FIXED) || + pp->phydev->phy_id != PHY_FIXED_ID) { + mvreg_write(pp, MVNETA_PHY_ADDR, pp->phydev->addr); + val = mvreg_read(pp, MVNETA_UNIT_CONTROL); val |= MVNETA_PHY_POLLING_ENABLE; mvreg_write(pp, MVNETA_UNIT_CONTROL, val); @@ -1171,38 +1151,46 @@ static void mvneta_adjust_link(struct udevice *dev) { struct mvneta_port *pp = dev_get_priv(dev); struct phy_device *phydev = pp->phydev; - int status_change = 0; - - if (mvneta_port_is_fixed_link(pp)) { - debug("Using fixed link, skip link adjust\n"); - return; - } - - if (phydev->link) { - if ((pp->speed != phydev->speed) || - (pp->duplex != phydev->duplex)) { - u32 val; - - val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); - val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | - MVNETA_GMAC_CONFIG_GMII_SPEED | - MVNETA_GMAC_CONFIG_FULL_DUPLEX | - MVNETA_GMAC_AN_SPEED_EN | - MVNETA_GMAC_AN_DUPLEX_EN); + bool status_change = false; + + if (phydev->link && + (pp->speed != phydev->speed || pp->duplex != phydev->duplex)) { + u32 val; + + val = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG); + val &= ~(MVNETA_GMAC_CONFIG_MII_SPEED | + MVNETA_GMAC_CONFIG_GMII_SPEED | + MVNETA_GMAC_CONFIG_FULL_DUPLEX | + MVNETA_GMAC_AN_SPEED_EN | + MVNETA_GMAC_AN_DUPLEX_EN); + + /* FIXME: For fixed-link case, these were the initial settings + * used before the code was converted to use PHY_FIXED. Some of + * these may look nonsensical (for example BYPASS_AN makes sense + * for 1000base-x and 2500base-x modes, AFAIK), and in fact this + * may be changed in the future (when support for inband AN will + * be added). Also, why is ADVERT_FC enabled if we don't enable + * inband AN at all? + */ + if (CONFIG_IS_ENABLED(PHY_FIXED) && + pp->phydev->phy_id == PHY_FIXED_ID) + val = MVNETA_GMAC_IB_BYPASS_AN_EN | + MVNETA_GMAC_SET_FC_EN | + MVNETA_GMAC_ADVERT_FC_EN | + MVNETA_GMAC_SAMPLE_TX_CFG_EN; - if (phydev->duplex) - val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; + if (phydev->duplex) + val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; - if (phydev->speed == SPEED_1000) - val |= MVNETA_GMAC_CONFIG_GMII_SPEED; - else - val |= MVNETA_GMAC_CONFIG_MII_SPEED; + if (phydev->speed == SPEED_1000) + val |= MVNETA_GMAC_CONFIG_GMII_SPEED; + else if (pp->speed == SPEED_100) + val |= MVNETA_GMAC_CONFIG_MII_SPEED; - mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); + mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); - pp->duplex = phydev->duplex; - pp->speed = phydev->speed; - } + pp->duplex = phydev->duplex; + pp->speed = phydev->speed; } if (phydev->link != pp->link) { @@ -1212,7 +1200,7 @@ static void mvneta_adjust_link(struct udevice *dev) } pp->link = phydev->link; - status_change = 1; + status_change = true; } if (status_change) { @@ -1428,118 +1416,6 @@ static int mvneta_init(struct udevice *dev) /* U-Boot only functions follow here */ -/* SMI / MDIO functions */ - -static int smi_wait_ready(struct mvneta_port *pp) -{ - u32 timeout = MVNETA_SMI_TIMEOUT; - u32 smi_reg; - - /* wait till the SMI is not busy */ - do { - /* read smi register */ - smi_reg = mvreg_read(pp, MVNETA_SMI); - if (timeout-- == 0) { - printf("Error: SMI busy timeout\n"); - return -EFAULT; - } - } while (smi_reg & MVNETA_SMI_BUSY); - - return 0; -} - -/* - * mvneta_mdio_read - miiphy_read callback function. - * - * Returns 16bit phy register value, or 0xffff on error - */ -static int mvneta_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) -{ - struct mvneta_port *pp = bus->priv; - u32 smi_reg; - u32 timeout; - - /* check parameters */ - if (addr > MVNETA_PHY_ADDR_MASK) { - printf("Error: Invalid PHY address %d\n", addr); - return -EFAULT; - } - - if (reg > MVNETA_PHY_REG_MASK) { - printf("Err: Invalid register offset %d\n", reg); - return -EFAULT; - } - - /* wait till the SMI is not busy */ - if (smi_wait_ready(pp) < 0) - return -EFAULT; - - /* fill the phy address and regiser offset and read opcode */ - smi_reg = (addr << MVNETA_SMI_DEV_ADDR_OFFS) - | (reg << MVNETA_SMI_REG_ADDR_OFFS) - | MVNETA_SMI_OPCODE_READ; - - /* write the smi register */ - mvreg_write(pp, MVNETA_SMI, smi_reg); - - /* wait till read value is ready */ - timeout = MVNETA_SMI_TIMEOUT; - - do { - /* read smi register */ - smi_reg = mvreg_read(pp, MVNETA_SMI); - if (timeout-- == 0) { - printf("Err: SMI read ready timeout\n"); - return -EFAULT; - } - } while (!(smi_reg & MVNETA_SMI_READ_VALID)); - - /* Wait for the data to update in the SMI register */ - for (timeout = 0; timeout < MVNETA_SMI_TIMEOUT; timeout++) - ; - - return mvreg_read(pp, MVNETA_SMI) & MVNETA_SMI_DATA_MASK; -} - -/* - * mvneta_mdio_write - miiphy_write callback function. - * - * Returns 0 if write succeed, -EINVAL on bad parameters - * -ETIME on timeout - */ -static int mvneta_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, - u16 value) -{ - struct mvneta_port *pp = bus->priv; - u32 smi_reg; - - /* check parameters */ - if (addr > MVNETA_PHY_ADDR_MASK) { - printf("Error: Invalid PHY address %d\n", addr); - return -EFAULT; - } - - if (reg > MVNETA_PHY_REG_MASK) { - printf("Err: Invalid register offset %d\n", reg); - return -EFAULT; - } - - /* wait till the SMI is not busy */ - if (smi_wait_ready(pp) < 0) - return -EFAULT; - - /* fill the phy addr and reg offset and write opcode and data */ - smi_reg = value << MVNETA_SMI_DATA_OFFS; - smi_reg |= (addr << MVNETA_SMI_DEV_ADDR_OFFS) - | (reg << MVNETA_SMI_REG_ADDR_OFFS); - smi_reg &= ~MVNETA_SMI_OPCODE_READ; - - /* write the smi register */ - mvreg_write(pp, MVNETA_SMI, smi_reg); - - return 0; -} - static int mvneta_start(struct udevice *dev) { struct mvneta_port *pp = dev_get_priv(dev); @@ -1548,57 +1424,28 @@ static int mvneta_start(struct udevice *dev) mvneta_port_power_up(pp, pp->phy_interface); if (!pp->init || pp->link == 0) { - if (mvneta_port_is_fixed_link(pp)) { - u32 val; - - pp->init = 1; - pp->link = 1; - mvneta_init(dev); - - val = MVNETA_GMAC_FORCE_LINK_UP | - MVNETA_GMAC_IB_BYPASS_AN_EN | - MVNETA_GMAC_SET_FC_EN | - MVNETA_GMAC_ADVERT_FC_EN | - MVNETA_GMAC_SAMPLE_TX_CFG_EN; - - if (pp->duplex) - val |= MVNETA_GMAC_CONFIG_FULL_DUPLEX; - - if (pp->speed == SPEED_1000) - val |= MVNETA_GMAC_CONFIG_GMII_SPEED; - else if (pp->speed == SPEED_100) - val |= MVNETA_GMAC_CONFIG_MII_SPEED; + phydev = dm_eth_phy_connect(dev); + if (!phydev) { + printf("dm_eth_phy_connect failed\n"); + return -ENODEV; + } - mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val); - } else { - /* Set phy address of the port */ - mvreg_write(pp, MVNETA_PHY_ADDR, pp->phyaddr); - - phydev = phy_connect(pp->bus, pp->phyaddr, dev, - pp->phy_interface); - if (!phydev) { - printf("phy_connect failed\n"); - return -ENODEV; - } - - pp->phydev = phydev; - phy_config(phydev); - phy_startup(phydev); - if (!phydev->link) { - printf("%s: No link.\n", phydev->dev->name); - return -1; - } - - /* Full init on first call */ - mvneta_init(dev); - pp->init = 1; - return 0; + pp->phydev = phydev; + phy_config(phydev); + phy_startup(phydev); + if (!phydev->link) { + printf("%s: No link.\n", phydev->dev->name); + return -1; } - } - /* Upon all following calls, this is enough */ - mvneta_port_up(pp); - mvneta_port_enable(pp); + /* Full init on first call */ + mvneta_init(dev); + pp->init = 1; + } else { + /* Upon all following calls, this is enough */ + mvneta_port_up(pp); + mvneta_port_enable(pp); + } return 0; } @@ -1692,18 +1539,11 @@ static int mvneta_recv(struct udevice *dev, int flags, uchar **packetp) static int mvneta_probe(struct udevice *dev) { - struct eth_pdata *pdata = dev_get_plat(dev); struct mvneta_port *pp = dev_get_priv(dev); #if CONFIG_IS_ENABLED(DM_GPIO) struct ofnode_phandle_args sfp_args; #endif - void *blob = (void *)gd->fdt_blob; - int node = dev_of_offset(dev); - struct mii_dev *bus; - unsigned long addr; void *bd_space; - int ret; - int fl_node; /* * Allocate buffer area for descs and rx_buffers. This is only @@ -1729,7 +1569,10 @@ static int mvneta_probe(struct udevice *dev) buffer_loc.rx_buffers = (phys_addr_t)(bd_space + size); } - pp->base = (void __iomem *)pdata->iobase; + pp->base = dev_read_addr_ptr(dev); + pp->phy_interface = dev_read_phy_mode(dev); + if (pp->phy_interface == PHY_INTERFACE_MODE_NA) + return -EINVAL; /* Configure MBUS address windows */ if (device_is_compatible(dev, "marvell,armada-3700-neta")) @@ -1737,42 +1580,9 @@ static int mvneta_probe(struct udevice *dev) else mvneta_conf_mbus_windows(pp); - /* PHY interface is already decoded in mvneta_of_to_plat() */ - pp->phy_interface = pdata->phy_interface; - - /* fetch 'fixed-link' property from 'neta' node */ - fl_node = fdt_subnode_offset(blob, node, "fixed-link"); - if (fl_node != -FDT_ERR_NOTFOUND) { - /* set phy_addr to invalid value for fixed link */ - pp->phyaddr = PHY_MAX_ADDR + 1; - pp->duplex = fdtdec_get_bool(blob, fl_node, "full-duplex"); - pp->speed = fdtdec_get_int(blob, fl_node, "speed", 0); - } else { - /* Now read phyaddr from DT */ - addr = fdtdec_get_int(blob, node, "phy", 0); - addr = fdt_node_offset_by_phandle(blob, addr); - pp->phyaddr = fdtdec_get_int(blob, addr, "reg", 0); - } - - bus = mdio_alloc(); - if (!bus) { - printf("Failed to allocate MDIO bus\n"); - return -ENOMEM; - } - - bus->read = mvneta_mdio_read; - bus->write = mvneta_mdio_write; - snprintf(bus->name, sizeof(bus->name), dev->name); - bus->priv = (void *)pp; - pp->bus = bus; - - ret = mdio_register(bus); - if (ret) - return ret; - #if CONFIG_IS_ENABLED(DM_GPIO) - ret = dev_read_phandle_with_args(dev, "sfp", NULL, 0, 0, &sfp_args); - if (!ret && ofnode_is_enabled(sfp_args.node)) + if (!dev_read_phandle_with_args(dev, "sfp", NULL, 0, 0, &sfp_args) && + ofnode_is_enabled(sfp_args.node)) gpio_request_by_name_nodev(sfp_args.node, "tx-disable-gpio", 0, &pp->sfp_tx_disable_gpio, GPIOD_IS_OUT); @@ -1789,7 +1599,7 @@ static int mvneta_probe(struct udevice *dev) dm_gpio_set_value(&pp->sfp_tx_disable_gpio, 0); #endif - return board_network_enable(bus); + return 0; } static void mvneta_stop(struct udevice *dev) @@ -1808,20 +1618,6 @@ static const struct eth_ops mvneta_ops = { .write_hwaddr = mvneta_write_hwaddr, }; -static int mvneta_of_to_plat(struct udevice *dev) -{ - struct eth_pdata *pdata = dev_get_plat(dev); - - pdata->iobase = dev_read_addr(dev); - - /* Get phy-mode / phy_interface from DT */ - pdata->phy_interface = dev_read_phy_mode(dev); - if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) - return -EINVAL; - - return 0; -} - static const struct udevice_id mvneta_ids[] = { { .compatible = "marvell,armada-370-neta" }, { .compatible = "marvell,armada-xp-neta" }, @@ -1833,7 +1629,6 @@ U_BOOT_DRIVER(mvneta) = { .name = "mvneta", .id = UCLASS_ETH, .of_match = mvneta_ids, - .of_to_plat = mvneta_of_to_plat, .probe = mvneta_probe, .ops = &mvneta_ops, .priv_auto = sizeof(struct mvneta_port), diff --git a/drivers/net/octeon/Makefile b/drivers/net/octeon/Makefile new file mode 100644 index 00000000000..c573411a629 --- /dev/null +++ b/drivers/net/octeon/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2018-2022 Marvell International Ltd. +# + +obj-$(CONFIG_NET_OCTEON) += octeon_eth.o octeon_mdio.o diff --git a/drivers/net/octeon/octeon_eth.c b/drivers/net/octeon/octeon_eth.c new file mode 100644 index 00000000000..fbb1afc08ab --- /dev/null +++ b/drivers/net/octeon/octeon_eth.c @@ -0,0 +1,1060 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2022 Marvell International Ltd. + */ + +#include <dm.h> +#include <dm/device_compat.h> +#include <env.h> +#include <net.h> +#include <netdev.h> +#include <malloc.h> +#include <miiphy.h> +#include <misc.h> +#include <asm/io.h> +#include <linux/delay.h> + +#include <mach/cvmx-regs.h> +#include <mach/cvmx-csr.h> +#include <mach/cvmx-bootmem.h> +#include <mach/octeon-model.h> +#include <mach/cvmx-fuse.h> +#include <mach/octeon-feature.h> +#include <mach/octeon_fdt.h> +#include <mach/cvmx-qlm.h> +#include <mach/octeon_eth.h> +#include <mach/octeon_qlm.h> +#include <mach/cvmx-pcie.h> +#include <mach/cvmx-coremask.h> + +#include <mach/cvmx-agl-defs.h> +#include <mach/cvmx-asxx-defs.h> +#include <mach/cvmx-bgxx-defs.h> +#include <mach/cvmx-dbg-defs.h> +#include <mach/cvmx-gmxx-defs.h> +#include <mach/cvmx-gserx-defs.h> +#include <mach/cvmx-ipd-defs.h> +#include <mach/cvmx-l2c-defs.h> +#include <mach/cvmx-npi-defs.h> +#include <mach/cvmx-pcsx-defs.h> +#include <mach/cvmx-pexp-defs.h> +#include <mach/cvmx-pki-defs.h> +#include <mach/cvmx-pko-defs.h> +#include <mach/cvmx-smix-defs.h> +#include <mach/cvmx-sriox-defs.h> +#include <mach/cvmx-xcv-defs.h> +#include <mach/cvmx-pcsxx-defs.h> + +#include <mach/cvmx-helper.h> +#include <mach/cvmx-helper-board.h> +#include <mach/cvmx-helper-fdt.h> +#include <mach/cvmx-helper-bgx.h> +#include <mach/cvmx-helper-cfg.h> + +#include <mach/cvmx-hwpko.h> +#include <mach/cvmx-pko.h> +#include <mach/cvmx-pki.h> +#include <mach/cvmx-config.h> +#include <mach/cvmx-mdio.h> + +/** Maximum receive packet size (hardware default is 1536) */ +#define CONFIG_OCTEON_NETWORK_MRU 1536 + +#define OCTEON_BOOTLOADER_NAMED_BLOCK_TMP_PREFIX "__tmp" + +/** + * Enables RX packet debugging if octeon_debug_rx_packets is set in the + * environment. + */ +#define DEBUG_RX_PACKET + +/** + * Enables TX packet debugging if octeon_debug_tx_packets is set in the + * environment. + */ +#define DEBUG_TX_PACKET + +/* Global flag indicating common hw has been set up */ +static int octeon_global_hw_inited; + +#if defined(DEBUG_RX_PACKET) || defined(DEBUG_TX_PACKET) +static int packet_rx_debug; +static int packet_tx_debug; +#endif + +/* Make sure that we have enough buffers to keep prefetching blocks happy. + * Absolute minimum is probably about 200. + */ +#define NUM_PACKET_BUFFERS 1000 + +#define PKO_SHUTDOWN_TIMEOUT_VAL 100 + +/* Define the offsets from the base CSR */ +#define GMX_PRT_CFG 0x10 + +#define GMX_RX_FRM_MAX 0x30 +#define GMX_RX_JABBER 0x38 + +#define GMX_RX_ADR_CTL 0x100 +#define GMX_RX_ADR_CAM_EN 0x108 +#define GMX_RX_ADR_CAM0 0x180 +#define GMX_RX_ADR_CAM1 0x188 +#define GMX_RX_ADR_CAM2 0x190 +#define GMX_RX_ADR_CAM3 0x198 +#define GMX_RX_ADR_CAM4 0x1a0 +#define GMX_RX_ADR_CAM5 0x1a8 +#define GMX_TX_OVR_BP 0x4c8 + +/** + * Set the hardware MAC address for a device + * + * @param interface interface of port to set + * @param index index of port to set MAC address for + * @param addr Address structure to change it too. + * @return Zero on success + */ +static int cvm_oct_set_mac_address(struct udevice *dev) +{ + struct octeon_eth_info *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_plat(dev); + cvmx_gmxx_prtx_cfg_t gmx_cfg; + cvmx_helper_interface_mode_t mode; + cvmx_gmxx_rxx_adr_ctl_t control; + u8 *ptr = (uint8_t *)pdata->enetaddr; + int interface = priv->interface; + int index = priv->index; + u64 mac = 0; + u64 gmx_reg; + int xipd_port; + int i; + + for (i = 0; i < 6; i++) + mac = (mac << 8) | (u64)(ptr[i]); + + debug("%s(%s (%pM))\n", __func__, dev->name, ptr); + mode = cvmx_helper_interface_get_mode(interface); + + /* It's rather expensive to change the MAC address for BGX so we only + * do this if it has changed or not been set previously. + */ + if (octeon_has_feature(OCTEON_FEATURE_BGX)) { + xipd_port = cvmx_helper_get_ipd_port(interface, index); + if (priv->last_bgx_mac != mac || !priv->bgx_mac_set) { + cvmx_helper_bgx_set_mac(xipd_port, 1, 2, mac); + priv->last_bgx_mac = mac; + priv->bgx_mac_set = 1; + } + return 0; + } + + if (mode == CVMX_HELPER_INTERFACE_MODE_AGL) { + gmx_reg = CVMX_AGL_GMX_RXX_INT_REG(0); + } else { + gmx_reg = CVMX_GMXX_RXX_INT_REG(index, interface); + csr_wr(CVMX_GMXX_SMACX(index, interface), mac); + } + + /* Disable interface */ + gmx_cfg.u64 = csr_rd(gmx_reg + GMX_PRT_CFG); + csr_wr(gmx_reg + GMX_PRT_CFG, gmx_cfg.u64 & ~1ull); + debug("%s: gmx reg: 0x%llx\n", __func__, gmx_reg); + + csr_wr(gmx_reg + GMX_RX_ADR_CAM0, ptr[0]); + csr_wr(gmx_reg + GMX_RX_ADR_CAM1, ptr[1]); + csr_wr(gmx_reg + GMX_RX_ADR_CAM2, ptr[2]); + csr_wr(gmx_reg + GMX_RX_ADR_CAM3, ptr[3]); + csr_wr(gmx_reg + GMX_RX_ADR_CAM4, ptr[4]); + csr_wr(gmx_reg + GMX_RX_ADR_CAM5, ptr[5]); + + control.u64 = 0; + control.s.bcst = 1; /* Allow broadcast MAC addresses */ + control.s.mcst = 1; /* Force reject multicast packets */ + control.s.cam_mode = 1; /* Filter packets based on the CAM */ + + csr_wr(gmx_reg + GMX_RX_ADR_CTL, control.u64); + + csr_wr(gmx_reg + GMX_RX_ADR_CAM_EN, 1); + + /* Return interface to previous enable state */ + csr_wr(gmx_reg + GMX_PRT_CFG, gmx_cfg.u64); + + return 0; +} + +static void cvm_oct_fill_hw_memory(u64 pool, u64 size, u64 elements) +{ + static int alloc_count; + char tmp_name[64]; + int ret; + + debug("%s: pool: 0x%llx, size: 0xx%llx, count: 0x%llx\n", + __func__, pool, size, elements); + sprintf(tmp_name, "%s_fpa_alloc_%d", + OCTEON_BOOTLOADER_NAMED_BLOCK_TMP_PREFIX, alloc_count++); + ret = cvmx_fpa_setup_pool(pool, tmp_name, NULL, size, elements); +} + +/** + * Configure common hardware for all interfaces + */ +static void cvm_oct_configure_common_hw(void) +{ + int mru = env_get_ulong("octeon_mru", 0, CONFIG_OCTEON_NETWORK_MRU); + int packet_pool_size = CVMX_FPA_PACKET_POOL_SIZE; + + if (mru > packet_pool_size) + packet_pool_size = (mru + CVMX_CACHE_LINE_SIZE - 1) & + ~(CVMX_CACHE_LINE_SIZE - 1); + + /* Setup the FPA */ + cvmx_fpa_enable(); + + cvm_oct_fill_hw_memory(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, + NUM_PACKET_BUFFERS); +#if CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL + if (!octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) { + cvm_oct_fill_hw_memory(CVMX_FPA_OUTPUT_BUFFER_POOL, + CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); + } +#endif + cvm_oct_fill_hw_memory(CVMX_FPA_PACKET_POOL, packet_pool_size, + NUM_PACKET_BUFFERS); + + cvmx_helper_initialize_packet_io_global(); + cvmx_helper_initialize_packet_io_local(); + + /* The MRU defaults to 1536 bytes by the hardware. Setting + * CONFIG_OCTEON_NETWORK_MRU allows this to be overridden. + */ + if (octeon_has_feature(OCTEON_FEATURE_PKI)) { + struct cvmx_pki_global_config gbl_cfg; + int i; + + cvmx_pki_read_global_config(0, &gbl_cfg); + for (i = 0; i < CVMX_PKI_NUM_FRAME_CHECK; i++) + gbl_cfg.frm_len[i].maxlen = mru; + cvmx_pki_write_global_config(0, &gbl_cfg); + } + + /* Set POW get work timeout to maximum value */ + if (octeon_has_feature(OCTEON_FEATURE_CN68XX_WQE) || + octeon_has_feature(OCTEON_FEATURE_CN78XX_WQE)) + csr_wr(CVMX_SSO_NW_TIM, 0x3ff); + else + csr_wr(CVMX_POW_NW_TIM, 0x3ff); +} + +/** + * Enables Ethernet devices to allow packets to be transmitted and received. + * For example, this is activated when the DHCP command is issued. + * + * @param dev Ethernet device to initialize + * @param bis board data structure, not used. + * + * @return 1 for success + */ +int octeon_eth_init(struct udevice *dev) +{ + struct octeon_eth_info *priv = dev_get_priv(dev); + + debug("%s(), dev_ptr: %p, dev: %s, port: %d\n", __func__, dev, + dev->name, priv->port); + + if (priv->initted_flag) { + debug("%s already initialized\n", dev->name); + return 1; + } + + if (!octeon_global_hw_inited) { + debug("Initializing common hardware\n"); + cvm_oct_configure_common_hw(); + } + + /* Ignore backpressure on RGMII ports */ + if (!octeon_has_feature(OCTEON_FEATURE_BGX)) + csr_wr(priv->gmx_base + GMX_TX_OVR_BP, 0xf << 8 | 0xf); + + debug("%s: Setting MAC address\n", __func__); + cvm_oct_set_mac_address(dev); + + if (!octeon_global_hw_inited) { + debug("Enabling packet input\n"); + cvmx_helper_ipd_and_packet_input_enable(); + octeon_global_hw_inited = 1; + + /* Connect, configure and start the PHY, if the device is + * connected to one. If not, then it's most likely an SPF + * enabled port, which does not have such PHY setup here. + */ + if (priv->mdio_dev) { + priv->phy_dev = dm_eth_phy_connect(dev); + phy_config(priv->phy_dev); + phy_startup(priv->phy_dev); + } + } + priv->enabled = 0; + priv->initted_flag = 1; + + debug("%s exiting successfully\n", __func__); + return 1; +} + +/** + * Initializes the specified interface and port + * + * @param interface interface to initialize + * @param index port index on interface + * @param port ipd port number + * @param if_mode interface mode + * + * @return 0 for success, -1 if out of memory, 1 if port is invalid + */ +static int octeon_eth_initialize(struct udevice *dev, int interface, + int index, int port, + cvmx_helper_interface_mode_t if_mode) +{ + struct octeon_eth_info *oct_eth_info = dev_get_priv(dev); + int eth; + + eth = cvmx_helper_get_port_fdt_node_offset(interface, index); + if (eth <= 0) { + debug("ERROR: No fdt node for interface %d, index %d\n", + interface, index); + return 1; + } + + oct_eth_info->is_c45 = (if_mode == CVMX_HELPER_INTERFACE_MODE_XAUI) || + (if_mode == CVMX_HELPER_INTERFACE_MODE_RXAUI) || + (if_mode == CVMX_HELPER_INTERFACE_MODE_XFI) || + (if_mode == CVMX_HELPER_INTERFACE_MODE_XLAUI) || + (if_mode == CVMX_HELPER_INTERFACE_MODE_10G_KR) || + (if_mode == CVMX_HELPER_INTERFACE_MODE_10G_KR); + oct_eth_info->port = port; + oct_eth_info->index = index; + oct_eth_info->interface = interface; + oct_eth_info->initted_flag = 0; + /* This is guaranteed to force the link state to be printed out */ + oct_eth_info->link_state = 0xffffffffffffffffULL; + debug("Setting up port: %d, int: %d, index: %d, device: octeth%d\n", + oct_eth_info->port, oct_eth_info->interface, oct_eth_info->index, + dev_seq(dev)); + if (if_mode == CVMX_HELPER_INTERFACE_MODE_AGL) { + oct_eth_info->gmx_base = CVMX_AGL_GMX_RXX_INT_REG(0); + } else { + if (!octeon_has_feature(OCTEON_FEATURE_BGX)) + oct_eth_info->gmx_base = + CVMX_GMXX_RXX_INT_REG(index, interface); + } + + return 0; +} + +/** + * @INTERNAL + * Converts a BGX address to the node, interface and port number + * + * @param bgx_addr Address of CSR register + * + * @return node, interface and port number, will be -1 for invalid address. + */ +static struct cvmx_xiface __cvmx_bgx_reg_addr_to_xiface(u64 bgx_addr) +{ + struct cvmx_xiface xi = { -1, -1 }; + + xi.node = cvmx_csr_addr_to_node(bgx_addr); + bgx_addr = cvmx_csr_addr_strip_node(bgx_addr); + if ((bgx_addr & 0xFFFFFFFFF0000000) != 0x00011800E0000000) { + debug("%s: Invalid BGX address 0x%llx\n", __func__, + (unsigned long long)bgx_addr); + xi.node = -1; + return xi; + } + xi.interface = (bgx_addr >> 24) & 0x0F; + + return xi; +} + +static int octeon_nic_probe(struct udevice *dev) +{ + struct octeon_eth_info *info = dev_get_priv(dev); + struct ofnode_phandle_args phandle; + struct cvmx_xiface xi; + ofnode node, mdio_node; + int ipd_port; + int intf; + int ret; + + /* The empty stub is to keep cvmx_user_app_init() happy. */ + cvmx_npi_max_pknds = 1; + __cvmx_helper_init_port_valid(); + + xi = __cvmx_bgx_reg_addr_to_xiface(dev_read_addr(dev)); + intf = xi.interface; + debug("%s: Found BGX node %d, interface %d\n", __func__, xi.node, intf); + + ipd_port = cvmx_helper_get_ipd_port(intf, xi.node); + ret = octeon_eth_initialize(dev, intf, xi.node, ipd_port, + cvmx_helper_interface_get_mode(intf)); + + /* Move to subnode, as this includes the "phy-handle" */ + node = dev_read_first_subnode(dev); + + /* Check if an SPF module is conneted, then no MDIO is probed */ + ret = ofnode_parse_phandle_with_args(node, "sfp-slot", NULL, 0, 0, + &phandle); + if (!ret) { + dev_dbg(dev, "sfp-slot found, not probing for MDIO\n"); + return 0; + } + + /* Continue with MDIO probing */ + ret = ofnode_parse_phandle_with_args(node, "phy-handle", NULL, 0, 0, + &phandle); + if (ret) { + dev_err(dev, "phy-handle not found in subnode\n"); + return -ENODEV; + } + + /* Get MDIO node */ + mdio_node = ofnode_get_parent(phandle.node); + ret = uclass_get_device_by_ofnode(UCLASS_MDIO, mdio_node, + &info->mdio_dev); + if (ret) { + dev_err(dev, "mdio_dev not found\n"); + return -ENODEV; + } + + return 0; +} + +/** + * Sets the hardware MAC address of the Ethernet device + * + * @param dev - Ethernet device + * + * @return 0 for success + */ +int octeon_eth_write_hwaddr(struct udevice *dev) +{ + struct octeon_eth_info *oct_eth_info = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_plat(dev); + + /* Skip if the interface isn't yet enabled */ + if (!oct_eth_info->enabled) { + debug("%s: Interface not enabled, not setting MAC address\n", + __func__); + return 0; + } + debug("%s: Setting %s address to %02x:%02x:%02x:%02x:%02x:%02x\n", + __func__, dev->name, pdata->enetaddr[0], pdata->enetaddr[1], + pdata->enetaddr[2], pdata->enetaddr[3], pdata->enetaddr[4], + pdata->enetaddr[5]); + return cvm_oct_set_mac_address(dev); +} + +/** + * Enables and disables the XCV RGMII interface + * + * @param interface Interface number + * @param index Port index (should be 0 for RGMII) + * @param enable True to enable it, false to disable it + */ +static void octeon_bgx_xcv_rgmii_enable(int interface, int index, bool enable) +{ + union cvmx_xcv_reset xcv_reset; + + debug("%s(%d, %d, %sable)\n", __func__, interface, index, + enable ? "en" : "dis"); + xcv_reset.u64 = csr_rd(CVMX_XCV_RESET); + xcv_reset.s.rx_pkt_rst_n = enable ? 1 : 0; + csr_wr(CVMX_XCV_RESET, xcv_reset.u64); +} + +/** + * Enables a SGMII interface + * + * @param dev - Ethernet device to initialize + */ +void octeon_eth_sgmii_enable(struct udevice *dev) +{ + struct octeon_eth_info *oct_eth_info; + cvmx_gmxx_prtx_cfg_t gmx_cfg; + int index, interface; + cvmx_helper_interface_mode_t if_mode; + + oct_eth_info = dev_get_priv(dev); + interface = oct_eth_info->interface; + index = oct_eth_info->index; + + debug("%s(%s) (%d.%d)\n", __func__, dev->name, interface, index); + if (octeon_has_feature(OCTEON_FEATURE_BGX)) { + cvmx_bgxx_cmrx_config_t cmr_config; + + cmr_config.u64 = + csr_rd(CVMX_BGXX_CMRX_CONFIG(index, interface)); + cmr_config.s.enable = 1; + cmr_config.s.data_pkt_tx_en = 1; + cmr_config.s.data_pkt_rx_en = 1; + csr_wr(CVMX_BGXX_CMRX_CONFIG(index, interface), cmr_config.u64); + mdelay(100); + if (cvmx_helper_bgx_is_rgmii(interface, index)) + octeon_bgx_xcv_rgmii_enable(interface, index, true); + } else { + if_mode = cvmx_helper_interface_get_mode(interface); + /* Normal operating mode. */ + + if (if_mode == CVMX_HELPER_INTERFACE_MODE_SGMII || + if_mode == CVMX_HELPER_INTERFACE_MODE_QSGMII) { + cvmx_pcsx_miscx_ctl_reg_t pcsx_miscx_ctl_reg; + + debug(" if mode: (Q)SGMII\n"); + pcsx_miscx_ctl_reg.u64 = csr_rd(CVMX_PCSX_MISCX_CTL_REG(index, interface)); + pcsx_miscx_ctl_reg.s.gmxeno = 0; + csr_wr(CVMX_PCSX_MISCX_CTL_REG(index, interface), + pcsx_miscx_ctl_reg.u64); + } else if (if_mode != CVMX_HELPER_INTERFACE_MODE_AGL) { + cvmx_pcsxx_misc_ctl_reg_t pcsxx_misc_ctl_reg; + + debug(" if mode: AGM\n"); + pcsxx_misc_ctl_reg.u64 = + csr_rd(CVMX_PCSXX_MISC_CTL_REG(interface)); + pcsxx_misc_ctl_reg.s.gmxeno = 0; + csr_wr(CVMX_PCSXX_MISC_CTL_REG(interface), + pcsxx_misc_ctl_reg.u64); + } + + gmx_cfg.u64 = csr_rd(oct_eth_info->gmx_base + GMX_PRT_CFG); + gmx_cfg.s.en = 1; + csr_wr(oct_eth_info->gmx_base + GMX_PRT_CFG, gmx_cfg.u64); + gmx_cfg.u64 = csr_rd(oct_eth_info->gmx_base + GMX_PRT_CFG); + } +} + +/** + * Enables an Ethernet interface + * + * @param dev - Ethernet device to enable + */ +void octeon_eth_enable(struct udevice *dev) +{ + struct octeon_eth_info *oct_eth_info; + u64 tmp; + int interface; + cvmx_helper_interface_mode_t if_mode; + + oct_eth_info = dev_get_priv(dev); + interface = oct_eth_info->interface; + if_mode = cvmx_helper_interface_get_mode(interface); + + switch (if_mode) { + case CVMX_HELPER_INTERFACE_MODE_RGMII: + case CVMX_HELPER_INTERFACE_MODE_GMII: + debug(" rgmii/gmii mode\n"); + tmp = csr_rd(CVMX_ASXX_RX_PRT_EN(interface)); + tmp |= (1ull << (oct_eth_info->port & 0x3)); + csr_wr(CVMX_ASXX_RX_PRT_EN(interface), tmp); + tmp = csr_rd(CVMX_ASXX_TX_PRT_EN(interface)); + tmp |= (1ull << (oct_eth_info->port & 0x3)); + csr_wr(CVMX_ASXX_TX_PRT_EN(interface), tmp); + octeon_eth_write_hwaddr(dev); + break; + + case CVMX_HELPER_INTERFACE_MODE_SGMII: + case CVMX_HELPER_INTERFACE_MODE_XAUI: + case CVMX_HELPER_INTERFACE_MODE_RXAUI: + case CVMX_HELPER_INTERFACE_MODE_XLAUI: + case CVMX_HELPER_INTERFACE_MODE_XFI: + case CVMX_HELPER_INTERFACE_MODE_10G_KR: + case CVMX_HELPER_INTERFACE_MODE_40G_KR4: + case CVMX_HELPER_INTERFACE_MODE_MIXED: + case CVMX_HELPER_INTERFACE_MODE_AGL: + debug(" SGMII/XAUI/etc.\n"); + octeon_eth_sgmii_enable(dev); + octeon_eth_write_hwaddr(dev); + break; + + default: + break; + } +} + +void octeon_phy_port_check(struct udevice *dev) +{ + struct octeon_eth_info *oct_eth_info = dev_get_priv(dev); + struct phy_device *phydev = oct_eth_info->phydev; + + if (oct_eth_info->phy_port_check) + oct_eth_info->phy_port_check(phydev); +} + +/** + * Configure the RGMII port for the negotiated speed + * + * @param dev Linux device for the RGMII port + */ +static void cvm_oct_configure_rgmii_speed(struct udevice *dev) +{ + struct octeon_eth_info *priv = dev_get_priv(dev); + int port = priv->port; + cvmx_helper_link_info_t link_state = cvmx_helper_link_get(port); + + /* If the port is down some PHYs we need to check modules, etc. */ + if (!link_state.s.link_up) + octeon_phy_port_check(dev); + + if (link_state.u64 != priv->link_state) { + cvmx_helper_interface_mode_t mode; + + octeon_phy_port_check(dev); + + debug("%s(%s): Link state changed\n", __func__, dev->name); + printf("%s: ", dev->name); + if (!link_state.s.link_up) { + puts("Down "); + } else { + printf("Up %d Mbps ", link_state.s.speed); + if (link_state.s.full_duplex) + puts("Full duplex "); + else + puts("Half duplex "); + } + mode = cvmx_helper_interface_get_mode(priv->interface); + printf("(port %2d) (%s)\n", port, + cvmx_helper_interface_mode_to_string(mode)); + debug("%s: Setting link state\n", __func__); + cvmx_helper_link_set(priv->port, link_state); + priv->link_state = link_state.u64; + } +} + +#if defined(DEBUG_TX_PACKET) || defined(DEBUG_RX_PACKET) +static void print_mac(const char *label, const uint8_t *mac_addr) +{ + printf("%s: %02x:%02x:%02x:%02x:%02x:%02x", label, mac_addr[0], + mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); +} + +static void print_ip(const void *packet) +{ + u8 *p = (uint8_t *)packet; + u16 length; + u8 hdr_len; + + puts("IP Header:\n"); + if ((p[0] & 0xF0) != 0x40) { + printf("Invalid IP version %d\n", *p >> 4); + return; + } + hdr_len = *p & 0x0F; + if (hdr_len < 5) + printf("Invalid IP header length %d\n", hdr_len); + printf(" Version: 4, Header length: %d\n", hdr_len); + length = (p[2] << 8) | p[3]; + printf(" TOS: 0x%02x, length: %d\n", p[1], length); + printf(" ID: %d, %s%s%s fragment offset: %d\n", (p[4] << 8) | p[5], + p[6] & 0x80 ? "congested, " : "", p[6] & 0x40 ? "DF, " : "", + p[6] & 0x20 ? "MF, " : "", ((p[6] & 0x1F) << 8) | p[7]); + printf(" TTL: %d, Protocol: %d, Header Checksum: 0x%x\n", p[8], p[9], + (p[10] << 8) | p[11]); + printf(" Source IP: %d.%d.%d.%d\n Destination IP: %d.%d.%d.%d\n", + p[12], p[13], p[14], p[15], p[16], p[17], p[18], p[19]); + if (p[9] == 17 || p[9] == 6) + printf(" Source port: %u, Destination port: %u\n", + (p[20] << 8) | p[21], (p[22] << 8) | p[23]); + puts("\n"); +} + +/** + * Prints out a packet for debugging purposes + * + * @param[in] packet - pointer to packet data + * @param length - length of packet in bytes + */ +static void print_packet(const void *packet, int length) +{ + int i, j; + const unsigned char *up = packet; + u16 type = (up[12] << 8 | up[13]); + int start = 14; + + print_mac("DMAC", &up[0]); + puts(" "); + print_mac("SMAC", &up[6]); + printf(" TYPE: %04x\n", type); + + if (type == 0x0800) + print_ip(&up[start]); + + for (i = start; (i + 16) < length; i += 16) { + printf("%04x ", i); + for (j = 0; j < 16; ++j) + printf("%02x ", up[i + j]); + + printf(" "); + for (j = 0; j < 16; ++j) + printf("%c", + ((up[i + j] >= ' ') && (up[i + j] <= '~')) ? + up[i + j] : + '.'); + printf("\n"); + } + printf("%04x ", i); + for (j = 0; i + j < length; ++j) + printf("%02x ", up[i + j]); + + for (; j < 16; ++j) + printf(" "); + + printf(" "); + for (j = 0; i + j < length; ++j) + printf("%c", ((up[i + j] >= ' ') && (up[i + j] <= '~')) ? + up[i + j] : + '.'); + + printf("\n"); +} +#endif + +/** + * String representation of error codes. + */ +static const char * const rx_error_codes[] = { + "OK", + "partial", + "jabber", + "overrun", + "oversize", + "alignment", + "fragment", + "fcs", + "undersize", + "extend", + "length mismatch", + "rgmii rx", + "skip error", + "nibble error (studder)", + "(undefined)", + "(undefined)", + "SPI 4.2 FCS", + "skip", + "L2 malformed", +}; + +/** + * Called to receive a packet + * + * @param dev - device to receive on + * + * @return - length of packet + * + * This function is used to poll packets. In turn it calls NetReceive + * to process the packets. + */ +static int nic_recv(struct udevice *dev, int flags, uchar **packetp) +{ + cvmx_wqe_t *work = cvmx_pow_work_request_sync(CVMX_POW_WAIT); + struct octeon_eth_info *oct_eth_info = dev_get_priv(dev); + cvmx_buf_ptr_t buf_ptr; + void *packet_data; + int length; + int error_code; + + if (!oct_eth_info->enabled) { + oct_eth_info->enabled = 1; + debug("%s: Enabling interface %s\n", __func__, dev->name); + octeon_eth_enable(dev); + } + + if (!work) { + /* + * Somtimes the link is not up yet. Return here in this + * case, this function will be called again later. + */ + return 0; + } + + error_code = cvmx_wqe_get_rcv_err(work); + if (error_code) { + /* Work has error, so drop */ + cvmx_helper_free_packet_data(work); + cvmx_wqe_free(work); + if (error_code < ARRAY_SIZE(rx_error_codes) && + !octeon_has_feature(OCTEON_FEATURE_BGX)) + printf("Receive error (code %d: %s), dropping\n", + error_code, rx_error_codes[error_code]); + else + printf("Receive error (code %d (unknown), dropping\n", + error_code); + return 0; + } + if (cvmx_wqe_get_bufs(work) != 1) { + /* can only support single-buffer packets */ + printf("Abnormal packet received in %u bufs, dropping\n", + cvmx_wqe_get_bufs(work)); + length = cvmx_wqe_get_len(work); + buf_ptr = cvmx_wqe_get_packet_ptr(work); + packet_data = cvmx_phys_to_ptr(buf_ptr.s.addr); + print_packet(packet_data, length); + cvmx_helper_free_packet_data(work); + cvmx_wqe_free(work); + return 0; + } + + buf_ptr = cvmx_wqe_get_packet_ptr(work); + packet_data = cvmx_phys_to_ptr(buf_ptr.s.addr); + length = cvmx_wqe_get_len(work); + + oct_eth_info->packets_received++; + debug("############# got work: %p, len: %d, packet_ptr: %p\n", work, + length, packet_data); +#if defined(DEBUG_RX_PACKET) + if (packet_rx_debug) { + printf("\nRX packet: interface: %d, index: %d\n", + oct_eth_info->interface, oct_eth_info->index); + print_packet(packet_data, length); + } +#endif + *packetp = (uchar *)packet_data; + + /* Save work for free_pkt() */ + oct_eth_info->work = work; + + /* Free WQE and packet data */ + return length; +} + +static int nic_free_pkt(struct udevice *dev, uchar *pkt, int pkt_len) +{ + struct octeon_eth_info *oct_eth_info = dev_get_priv(dev); + cvmx_wqe_t *work = oct_eth_info->work; + + if (!work) + return 0; + + cvmx_helper_free_packet_data(work); + cvmx_wqe_free(work); + oct_eth_info->work = NULL; + + return 0; +} + +/** + * Packet transmit + * + * @param skb Packet to send + * @param dev Device info structure + * @return Always returns zero + */ +static int cvm_oct_xmit(struct udevice *dev, void *packet, int len) +{ + struct octeon_eth_info *priv = dev_get_priv(dev); + int queue = cvmx_pko_get_base_queue(priv->port); + cvmx_pko_command_word0_t pko_command; + cvmx_buf_ptr_t hw_buffer; + int rv; + + debug("%s: addr: %p, len: %d\n", __func__, packet, len); + + hw_buffer.u64 = 0; + hw_buffer.s.addr = cvmx_ptr_to_phys(packet); + hw_buffer.s.pool = CVMX_FPA_PACKET_POOL; + hw_buffer.s.size = len; + hw_buffer.s.back = 0; + + /* Build the PKO command */ + pko_command.u64 = 0; + pko_command.s.subone0 = 1; + pko_command.s.dontfree = 0; + pko_command.s.segs = 1; + pko_command.s.total_bytes = len; + /* Send the packet to the output queue */ + + debug("%s: port: %d, queue: %d\n", __func__, priv->port, queue); + cvmx_pko_send_packet_prepare(priv->port, queue, 0); + rv = cvmx_pko_send_packet_finish(priv->port, queue, pko_command, + hw_buffer, 0); + if (rv) + printf("Failed to send the packet rv=%d\n", rv); + + return 0; +} + +static int nic_xmit(struct udevice *dev, void *pkt, int pkt_len) +{ + struct octeon_eth_info *oct_eth_info = dev_get_priv(dev); + void *fpa_buf = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); + + if (!oct_eth_info->enabled) { + oct_eth_info->enabled = 1; + octeon_eth_enable(dev); + } + + /* We need to copy this to a FPA buffer, then give that to TX */ + + if (oct_eth_info->packets_sent == 0 && + !octeon_has_feature(OCTEON_FEATURE_BGX)) + cvm_oct_configure_rgmii_speed(dev); + + if (!fpa_buf) { + printf("ERROR allocating buffer for packet!\n"); + return -1; + } + + memcpy(fpa_buf, pkt, pkt_len); +#ifdef DEBUG_TX_PACKET + if (packet_tx_debug) { + printf("\nTX packet: interface: %d, index: %d\n", + oct_eth_info->interface, oct_eth_info->index); + print_packet(pkt, pkt_len); + } +#endif + cvm_oct_xmit(dev, fpa_buf, pkt_len); + oct_eth_info->packets_sent++; + + return 0; +} + +int nic_open(struct udevice *dev) +{ + octeon_eth_init(dev); + + return 0; +} + +static void octeon_eth_halt_bgx(struct udevice *dev, + cvmx_helper_interface_mode_t mode) +{ + union cvmx_bgxx_cmrx_config cmr_config; + union cvmx_bgxx_cmr_rx_adrx_cam cmr_cam; + struct octeon_eth_info *oct_eth_info = dev_get_priv(dev); + int index = oct_eth_info->index; + int xiface = oct_eth_info->interface; + struct cvmx_xiface xi = cvmx_helper_xiface_to_node_interface(xiface); + + debug("%s(%s(%d.%d), %d)\n", __func__, dev->name, xiface, index, mode); + + /* For RGMII we need to properly shut down the XCV interface */ + if (cvmx_helper_bgx_is_rgmii(xiface, index)) { + debug(" Shut down XCV RGMII\n"); + octeon_bgx_xcv_rgmii_enable(xi.interface, index, false); + } else { + cmr_config.u64 = csr_rd_node(xi.node, + CVMX_BGXX_CMRX_CONFIG(index, xi.interface)); + cmr_config.s.data_pkt_tx_en = 0; + cmr_config.s.data_pkt_rx_en = 0; + csr_wr_node(xi.node, CVMX_BGXX_CMRX_CONFIG(index, xi.interface), + cmr_config.u64); + + cmr_cam.u64 = csr_rd_node(xi.node, + CVMX_BGXX_CMR_RX_ADRX_CAM(index * 8, xi.interface)); + cmr_cam.s.en = 0; + csr_wr_node(xi.node, + CVMX_BGXX_CMR_RX_ADRX_CAM(index * 8, xi.interface), + cmr_cam.u64); + oct_eth_info->last_bgx_mac = 0; + oct_eth_info->bgx_mac_set = 0; + } +} + +/** + * Halts the specified Ethernet interface preventing it from receiving any more + * packets. + * + * @param dev - Ethernet device to shut down. + */ +void octeon_eth_halt(struct udevice *dev) +{ + struct octeon_eth_info *oct_eth_info = dev_get_priv(dev); + int index = oct_eth_info->index; + int interface = oct_eth_info->interface; + cvmx_helper_interface_mode_t mode; + union cvmx_gmxx_rxx_adr_ctl adr_ctl; + cvmx_gmxx_prtx_cfg_t gmx_cfg; + u64 tmp; + + debug("%s(%s): Halting\n", __func__, dev->name); + + oct_eth_info->enabled = 0; + + mode = cvmx_helper_interface_get_mode(oct_eth_info->interface); + if (octeon_has_feature(OCTEON_FEATURE_BGX)) { + octeon_eth_halt_bgx(dev, mode); + return; + } + + /* Stop SCC */ + /* Disable reception on this port at the GMX block */ + switch (mode) { + case CVMX_HELPER_INTERFACE_MODE_RGMII: + case CVMX_HELPER_INTERFACE_MODE_GMII: + debug(" RGMII/GMII\n"); + tmp = csr_rd(CVMX_ASXX_RX_PRT_EN(oct_eth_info->interface)); + tmp &= ~(1ull << index); + /* Disable the RGMII RX ports */ + csr_wr(CVMX_ASXX_RX_PRT_EN(oct_eth_info->interface), tmp); + tmp = csr_rd(CVMX_ASXX_TX_PRT_EN(oct_eth_info->interface)); + tmp &= ~(1ull << index); + /* Disable the RGMII TX ports */ + csr_wr(CVMX_ASXX_TX_PRT_EN(oct_eth_info->interface), tmp); + /* No break! */ + case CVMX_HELPER_INTERFACE_MODE_SGMII: + case CVMX_HELPER_INTERFACE_MODE_QSGMII: + case CVMX_HELPER_INTERFACE_MODE_XAUI: + case CVMX_HELPER_INTERFACE_MODE_RXAUI: + case CVMX_HELPER_INTERFACE_MODE_XLAUI: + case CVMX_HELPER_INTERFACE_MODE_XFI: + case CVMX_HELPER_INTERFACE_MODE_10G_KR: + case CVMX_HELPER_INTERFACE_MODE_40G_KR4: + case CVMX_HELPER_INTERFACE_MODE_MIXED: + case CVMX_HELPER_INTERFACE_MODE_AGL: + /* Disable MAC filtering */ + gmx_cfg.u64 = csr_rd(oct_eth_info->gmx_base + GMX_PRT_CFG); + csr_wr(oct_eth_info->gmx_base + GMX_PRT_CFG, + gmx_cfg.u64 & ~1ull); + adr_ctl.u64 = 0; + adr_ctl.s.bcst = 1; /* Reject broadcast */ + csr_wr(oct_eth_info->gmx_base + GMX_RX_ADR_CTL, adr_ctl.u64); + csr_wr(oct_eth_info->gmx_base + GMX_RX_ADR_CAM_EN, 0); + csr_wr(oct_eth_info->gmx_base + GMX_PRT_CFG, gmx_cfg.u64); + break; + default: + printf("%s: Unknown mode %d for interface 0x%x:%d\n", __func__, + mode, interface, index); + break; + } +} + +void nic_stop(struct udevice *dev) +{ + octeon_eth_halt(dev); +} + +int nic_write_hwaddr(struct udevice *dev) +{ + cvm_oct_set_mac_address(dev); + + return 0; +} + +static const struct eth_ops octeon_nic_ops = { + .start = nic_open, + .stop = nic_stop, + .send = nic_xmit, + .recv = nic_recv, + .free_pkt = nic_free_pkt, + .write_hwaddr = nic_write_hwaddr, +}; + +static const struct udevice_id octeon_nic_ids[] = { + { .compatible = "cavium,octeon-7890-bgx" }, + {} +}; + +U_BOOT_DRIVER(octeon_nic) = { + .name = "octeon_nic", + .id = UCLASS_ETH, + .probe = octeon_nic_probe, + .of_match = octeon_nic_ids, + .ops = &octeon_nic_ops, + .priv_auto = sizeof(struct octeon_eth_info), +}; diff --git a/drivers/net/octeon/octeon_mdio.c b/drivers/net/octeon/octeon_mdio.c new file mode 100644 index 00000000000..34ee80901fb --- /dev/null +++ b/drivers/net/octeon/octeon_mdio.c @@ -0,0 +1,226 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018-2022 Marvell International Ltd. + */ + +#include <dm.h> +#include <fdt_support.h> +#include <log.h> +#include <miiphy.h> +#include <net.h> +#include <linux/delay.h> + +#include <mach/cvmx-regs.h> +#include <mach/cvmx-csr.h> +#include <mach/octeon-model.h> +#include <mach/octeon-feature.h> +#include <mach/cvmx-smix-defs.h> +#include <mach/cvmx-config.h> +#include <mach/cvmx-helper.h> +#include <mach/cvmx-helper-board.h> +#include <mach/cvmx-mdio.h> + +#define CVMX_SMI_DRV_CTL 0x0001180000001828ull +#define DEFAULT_MDIO_SPEED 2500000 /** 2.5 MHz default speed */ + +/** + * cvmx_smi_drv_ctl + * + * Enables the SMI interface. + * + */ +union cvmx_smi_drv_ctl { + u64 u64; + struct cvmx_smi_drv_ctl_s { + u64 reserved_14_63 : 50; + u64 pctl : 6; + u64 reserved_6_7 : 2; + u64 nctl : 6; + } s; +}; + +struct octeon_mdiobus { + struct mii_dev *mii_dev; + /** + * The local bus is in the lower 8 bits, followed by the remote bus in + * the top 8 bits. Bit 16 will be set if the bus is non-local. + */ + u32 bus_id; + + int node; /** Node number */ + int speed; /** Bus speed, normally 2.5 MHz */ + int fdt_node; /** Node in FDT */ + bool local; /** true if local MDIO bus */ +}; + +static int octeon_mdio_read(struct udevice *mdio_dev, int phy_addr, + int dev_addr, int reg_addr) +{ + struct octeon_mdiobus *p = dev_get_priv(mdio_dev); + struct mii_dev *dev = p->mii_dev; + int value; + + debug("%s(0x%p(%s): bus_id=%d phy_addr=%d, 0x%x, 0x%x) - ", __func__, + dev, dev->name, p->bus_id, phy_addr, dev_addr, reg_addr); + if (IS_ENABLED(CONFIG_PHYLIB_10G) && dev_addr != MDIO_DEVAD_NONE) { + debug("clause 45 mode\n"); + value = cvmx_mdio_45_read(p->bus_id & 0xff, phy_addr, dev_addr, + reg_addr); + } else { + value = cvmx_mdio_read(p->bus_id & 0xff, phy_addr, reg_addr); + } + + debug("Return value: 0x%x\n", value); + return value; +} + +static int octeon_mdio_write(struct udevice *mdio_dev, int phy_addr, + int dev_addr, int reg_addr, u16 value) +{ + struct octeon_mdiobus *p = dev_get_priv(mdio_dev); + struct mii_dev *dev = p->mii_dev; + + debug("%s(0x%p(%s): bus_id=%d phy_addr=%d, 0x%x, 0x%x, 0x%x)\n", + __func__, dev, dev->name, p->bus_id, phy_addr, dev_addr, reg_addr, + value); + + if (IS_ENABLED(CONFIG_PHYLIB_10G) && dev_addr != MDIO_DEVAD_NONE) { + debug("clause 45 mode\n"); + return cvmx_mdio_45_write(p->bus_id & 0xff, phy_addr, dev_addr, + reg_addr, value); + } + + return cvmx_mdio_write(p->bus_id & 0xff, phy_addr, reg_addr, value); +} + +/** + * Converts a MDIO register address to a bus number + * + * @param reg_addr MDIO base register address + * + * @return MDIO bus number or -1 if invalid address + */ +int octeon_mdio_reg_addr_to_bus(u64 reg_addr) +{ + int bus_base; + int bus; + + /* Adjust the bus number based on the node number */ + bus_base = cvmx_csr_addr_to_node(reg_addr) * 4; + reg_addr = cvmx_csr_addr_strip_node(reg_addr); + + switch (reg_addr) { + case 0x1180000001800: + case 0x1180000003800: /* 68XX/78XX address */ + bus = 0; + break; + case 0x1180000001900: + case 0x1180000003880: + bus = 1; + break; + case 0x1180000003900: + bus = 2; + break; + case 0x1180000003980: + bus = 3; + break; + default: + printf("%s: Unknown register address 0x%llx\n", __func__, + reg_addr); + return -1; + } + bus += bus_base; + debug("%s: address 0x%llx is bus %d\n", __func__, reg_addr, bus); + return bus; +} + +static int octeon_mdio_probe(struct udevice *dev) +{ + struct octeon_mdiobus *p = dev_get_priv(dev); + union cvmx_smi_drv_ctl drv_ctl; + cvmx_smix_clk_t smi_clk; + u64 mdio_addr; + int bus; + u64 sclock; + u32 sample_dly; + u64 denom; + + mdio_addr = dev_read_addr(dev); + debug("%s: Translated address: 0x%llx\n", __func__, mdio_addr); + bus = octeon_mdio_reg_addr_to_bus(mdio_addr); + p->bus_id = bus; + debug("%s: bus: %d\n", __func__, bus); + + drv_ctl.u64 = csr_rd(CVMX_SMI_DRV_CTL); + drv_ctl.s.pctl = dev_read_u32_default(dev, "cavium,pctl-drive-strength", + drv_ctl.s.pctl); + drv_ctl.s.nctl = dev_read_u32_default(dev, "cavium,nctl-drive-strength", + drv_ctl.s.nctl); + debug("%s: Set MDIO PCTL drive strength to 0x%x and NCTL drive strength to 0x%x\n", + __func__, drv_ctl.s.pctl, drv_ctl.s.nctl); + csr_wr(CVMX_SMI_DRV_CTL, drv_ctl.u64); + + /* Set the bus speed, default is 2.5MHz */ + p->speed = dev_read_u32_default(dev, "cavium,max-speed", + DEFAULT_MDIO_SPEED); + sclock = gd->bus_clk; + smi_clk.u64 = csr_rd(CVMX_SMIX_CLK(bus & 3)); + smi_clk.s.phase = sclock / (p->speed * 2); + + /* Allow sample delay to be specified */ + sample_dly = dev_read_u32_default(dev, "cavium,sample-delay", 0); + /* Only change the sample delay if it is set, otherwise use + * the default value of 2. + */ + if (sample_dly) { + u32 sample; + + denom = (sclock * 1000ULL) / sample_dly; + debug("%s: sclock: %llu, sample_dly: %u ps, denom: %llu\n", + __func__, sclock, sample_dly, denom); + sample = (sclock + denom - 1) / denom; + debug("%s: sample: %u\n", __func__, smi_clk.s.sample); + if (sample < 2) { + printf("%s: warning: cavium,sample-delay %u ps is too small in device tree for %s\n", + __func__, sample_dly, dev->name); + sample = 2; + } + if (sample > (2 * smi_clk.s.phase - 3)) { + printf("%s: warning: cavium,sample-delay %u ps is too large in device tree for %s\n", + __func__, sample_dly, dev->name); + sample = 2 * smi_clk.s.phase - 3; + } + smi_clk.s.sample = sample & 0xf; + smi_clk.s.sample_hi = (sample >> 4) & 0xf; + debug("%s(%s): sample delay: %u ps (%d clocks)\n", __func__, + dev->name, sample_dly, smi_clk.s.sample); + } + csr_wr(CVMX_SMIX_CLK(bus & 3), smi_clk.u64); + + debug("mdio clock phase: %d clocks\n", smi_clk.s.phase); + csr_wr(CVMX_SMIX_CLK(bus & 3), smi_clk.u64); + debug("Enabling SMI interface %s\n", dev->name); + csr_wr(CVMX_SMIX_EN(bus & 3), 1); + + /* Muxed MDIO bus support removed for now! */ + return 0; +} + +static const struct mdio_ops octeon_mdio_ops = { + .read = octeon_mdio_read, + .write = octeon_mdio_write, +}; + +static const struct udevice_id octeon_mdio_ids[] = { + { .compatible = "cavium,octeon-3860-mdio" }, + {} +}; + +U_BOOT_DRIVER(octeon_mdio) = { + .name = "octeon_mdio", + .id = UCLASS_MDIO, + .of_match = octeon_mdio_ids, + .probe = octeon_mdio_probe, + .ops = &octeon_mdio_ops, + .priv_auto = sizeof(struct octeon_mdiobus), +}; diff --git a/drivers/net/octeontx/bgx.c b/drivers/net/octeontx/bgx.c index a5c0c9fe2b3..b6592ff2ce5 100644 --- a/drivers/net/octeontx/bgx.c +++ b/drivers/net/octeontx/bgx.c @@ -1458,7 +1458,7 @@ int octeontx_bgx_probe(struct udevice *dev) int bgx_idx, node; int inc = 1; - bgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + bgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); if (!bgx->reg_base) { debug("No PCI region found\n"); diff --git a/drivers/net/octeontx/nic_main.c b/drivers/net/octeontx/nic_main.c index 0f36f2586e6..99886e3afc0 100644 --- a/drivers/net/octeontx/nic_main.c +++ b/drivers/net/octeontx/nic_main.c @@ -713,7 +713,7 @@ int nic_initialize(struct udevice *dev) return -ENOMEM; /* MAP PF's configuration registers */ - nic->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + nic->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); if (!nic->reg_base) { printf("Cannot map config register space, aborting\n"); diff --git a/drivers/net/octeontx/nicvf_main.c b/drivers/net/octeontx/nicvf_main.c index c30ba49c27c..6e4d0a05121 100644 --- a/drivers/net/octeontx/nicvf_main.c +++ b/drivers/net/octeontx/nicvf_main.c @@ -509,7 +509,7 @@ int nicvf_initialize(struct udevice *dev) /* Enable TSO support */ nicvf->hw_tso = true; - nicvf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + nicvf->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); debug("nicvf->reg_base: %p\n", nicvf->reg_base); diff --git a/drivers/net/octeontx/smi.c b/drivers/net/octeontx/smi.c index d70fa820c7b..233c26f7319 100644 --- a/drivers/net/octeontx/smi.c +++ b/drivers/net/octeontx/smi.c @@ -322,7 +322,7 @@ int octeontx_smi_probe(struct udevice *dev) u64 baseaddr; debug("SMI PCI device: %x\n", bdf); - if (!dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM)) { + if (!dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM)) { printf("Failed to map PCI region for bdf %x\n", bdf); return -1; } diff --git a/drivers/net/octeontx2/cgx.c b/drivers/net/octeontx2/cgx.c index d139029f4e5..c6ec3200c01 100644 --- a/drivers/net/octeontx2/cgx.c +++ b/drivers/net/octeontx2/cgx.c @@ -253,7 +253,7 @@ int cgx_probe(struct udevice *dev) struct cgx *cgx = dev_get_priv(dev); int err; - cgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + cgx->reg_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); cgx->dev = dev; cgx->cgx_id = ((u64)(cgx->reg_base) >> 24) & 0x7; diff --git a/drivers/net/octeontx2/rvu_af.c b/drivers/net/octeontx2/rvu_af.c index d2f96548611..0d3a9ffe9ee 100644 --- a/drivers/net/octeontx2/rvu_af.c +++ b/drivers/net/octeontx2/rvu_af.c @@ -127,7 +127,7 @@ int rvu_af_probe(struct udevice *dev) { struct rvu_af *af_ptr = dev_get_priv(dev); - af_ptr->af_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, + af_ptr->af_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); debug("%s RVU AF BAR %p\n", __func__, af_ptr->af_base); af_ptr->dev = dev; diff --git a/drivers/net/octeontx2/rvu_pf.c b/drivers/net/octeontx2/rvu_pf.c index 4b00178989c..5f3ea1f8eab 100644 --- a/drivers/net/octeontx2/rvu_pf.c +++ b/drivers/net/octeontx2/rvu_pf.c @@ -58,7 +58,8 @@ int rvu_pf_probe(struct udevice *dev) debug("%s: name: %s\n", __func__, dev->name); - rvu->pf_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, PCI_REGION_MEM); + rvu->pf_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_2, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); rvu->pfid = dev_seq(dev) + 1; // RVU PF's start from 1; rvu->dev = dev; if (!rvu_af_dev) { diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index f1895246b93..ad7b5b8e99b 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -449,7 +449,7 @@ static int pch_gbe_probe(struct udevice *dev) priv->dev = dev; - iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, PCI_REGION_MEM); + iobase = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_1, 0, 0, PCI_REGION_TYPE, PCI_REGION_MEM); plat->iobase = (ulong)iobase; priv->mac_regs = (struct pch_gbe_regs *)iobase; |