diff --git a/README b/README index b95c72bb367..20a73bab802 100644 --- a/README +++ b/README @@ -1216,9 +1216,6 @@ Note: once the monitor has been relocated, then it will complain if the default environment is used; a new CRC is computed as soon as you use the "saveenv" command to store a valid environment. -- CONFIG_SYS_FAULT_MII_ADDR: - MII address of the PHY to check for the Ethernet link state. - - CONFIG_DISPLAY_BOARDINFO Display information about the board that U-Boot is running on when U-Boot starts up. The board function checkboard() is called diff --git a/cmd/Kconfig b/cmd/Kconfig index 5fcf37e67b9..9929087a8bb 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1951,10 +1951,6 @@ config BOOTP_BOOTPATH Even though the config is called BOOTP_BOOTPATH, it stores the path in the variable 'rootpath'. -config BOOTP_VENDOREX - bool "Support vendor extensions from BOOTP/DHCP server" - depends on CMD_BOOTP - config BOOTP_BOOTFILESIZE bool "Request & store 'bootfilesize' from BOOTP/DHCP server" depends on CMD_BOOTP diff --git a/cmd/net.c b/cmd/net.c index 886735ea14f..24099764493 100644 --- a/cmd/net.c +++ b/cmd/net.c @@ -134,8 +134,8 @@ U_BOOT_CMD(dhcp6, 3, 1, do_dhcp6, #endif #if defined(CONFIG_CMD_DHCP) -static int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]) +int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]) { return netboot_common(DHCP, cmdtp, argc, argv); } @@ -145,38 +145,6 @@ U_BOOT_CMD( "boot image via network using DHCP/TFTP protocol", "[loadAddress] [[hostIPaddr:]bootfilename]" ); - -int dhcp_run(ulong addr, const char *fname, bool autoload) -{ - char *dhcp_argv[] = {"dhcp", NULL, (char *)fname, NULL}; - struct cmd_tbl cmdtp = {}; /* dummy */ - char file_addr[17]; - int old_autoload; - int ret, result; - - log_debug("addr=%lx, fname=%s, autoload=%d\n", addr, fname, autoload); - old_autoload = env_get_yesno("autoload"); - ret = env_set("autoload", autoload ? "y" : "n"); - if (ret) - return log_msg_ret("en1", -EINVAL); - - if (autoload) { - sprintf(file_addr, "%lx", addr); - dhcp_argv[1] = file_addr; - } - - result = do_dhcp(&cmdtp, 0, !autoload ? 1 : fname ? 3 : 2, dhcp_argv); - - ret = env_set("autoload", old_autoload == -1 ? NULL : - old_autoload ? "y" : "n"); - if (ret) - return log_msg_ret("en2", -EINVAL); - - if (result) - return log_msg_ret("res", -ENOENT); - - return 0; -} #endif #if defined(CONFIG_CMD_NFS) diff --git a/configs/an7581_evb_defconfig b/configs/an7581_evb_defconfig index 0ccab4f066f..baa3fc3f5de 100644 --- a/configs/an7581_evb_defconfig +++ b/configs/an7581_evb_defconfig @@ -43,6 +43,7 @@ CONFIG_ENV_IS_IN_MMC=y CONFIG_ENV_RELOC_GD_ENV_ADDR=y CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SYS_RX_ETH_BUFFER=8 CONFIG_REGMAP=y CONFIG_SYSCON=y CONFIG_CLK=y diff --git a/configs/gurnard_defconfig b/configs/gurnard_defconfig index bde531a6003..85643f249ae 100644 --- a/configs/gurnard_defconfig +++ b/configs/gurnard_defconfig @@ -42,7 +42,6 @@ CONFIG_ENV_OVERWRITE=y CONFIG_ENV_IS_IN_NAND=y CONFIG_ENV_RELOC_GD_ENV_ADDR=y CONFIG_NET_RETRY_COUNT=20 -CONFIG_TFTP_PORT=y CONFIG_TFTP_TSIZE=y CONFIG_AT91_GPIO=y CONFIG_GENERIC_ATMEL_MCI=y diff --git a/doc/device-tree-bindings/net/aquantia-phy.txt b/doc/device-tree-bindings/net/aquantia-phy.txt index 89ce61e05bb..7dd3d45df12 100644 --- a/doc/device-tree-bindings/net/aquantia-phy.txt +++ b/doc/device-tree-bindings/net/aquantia-phy.txt @@ -4,7 +4,7 @@ This text describes properties that are applicable to Aquantia PHY nodes in addition to the bindings in phy.txt. Aquantia PHYs allow some flexibility in the way they are wired in a system, -they allow MDI pins to be reversed, LEDs linked up in different weays, have an +they allow MDI pins to be reversed, LEDs linked up in different ways, have an I2C slave interface that can be used for debug. Normally the configuration corresponding to these is driven by the PHY firmware with the downside that a custom firmware is needed for each integration of a PHY. diff --git a/doc/usage/cmd/tftpput.rst b/doc/usage/cmd/tftpput.rst index 351c9faa38b..2bcb3032cb2 100644 --- a/doc/usage/cmd/tftpput.rst +++ b/doc/usage/cmd/tftpput.rst @@ -19,9 +19,8 @@ Description The tftpput command is used to transfer a file to a TFTP server. By default the destination port is 69 and the source port is pseudo-random. -If CONFIG_TFTP_PORT=y, the environment variable *tftpsrcp* can be used to set -the source port and the environment variable *tftpdstp* can be used to set -the destination port. +The environment variable *tftpsrcp* can be used to set the source port and the +environment variable *tftpdstp* can be used to set the destination port. address memory address where the data starts @@ -75,9 +74,6 @@ The command is only available if CONFIG_CMD_TFTPPUT=y. CONFIG_TFTP_BLOCKSIZE defines the size of the TFTP blocks sent. It defaults to 1468 matching an ethernet MTU of 1500. -If CONFIG_TFTP_PORT=y, the environment variables *tftpsrcp* and *tftpdstp* can -be used to set the source and the destination ports. - CONFIG_TFTP_WINDOWSIZE can be used to set the TFTP window size of transmits after which an ACK response is required. The window size defaults to 1. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 7ae28c4e0d5..c9b35b5a2ff 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -179,7 +179,7 @@ config CALXEDA_XGMAC machines. config DWC_ETH_XGMAC - bool "Synopsys DWC Ethernet XGMAC device support" + bool select PHYLIB help This driver supports the Synopsys Designware Ethernet XGMAC (10G @@ -190,7 +190,8 @@ config DWC_ETH_XGMAC_SOCFPGA bool "Synopsys DWC Ethernet XGMAC device support for SOCFPGA" select REGMAP select SYSCON - depends on DWC_ETH_XGMAC + select DWC_ETH_XGMAC + depends on ARCH_SOCFPGA default y if TARGET_SOCFPGA_AGILEX5 help The Synopsys Designware Ethernet XGMAC IP block with specific @@ -376,7 +377,7 @@ config ETH_DESIGNWARE_SOCFPGA select SYSCON select DW_ALTDESCRIPTOR bool "Altera SoCFPGA extras for Synopsys Designware Ethernet MAC" - depends on ETH_DESIGNWARE + depends on ARCH_SOCFPGA && ETH_DESIGNWARE help The Altera SoCFPGA requires additional configuration of the Altera system manager to correctly interface with the PHY. @@ -966,6 +967,9 @@ config TSEC_ENET This driver implements support for the (Enhanced) Three-Speed Ethernet Controller found on Freescale SoCs. +config MDIO_MT7531_MMIO + bool + source "drivers/net/mtk_eth/Kconfig" config HIFEMAC_ETH diff --git a/drivers/net/Makefile b/drivers/net/Makefile index f8f9a71f815..a3c3420898c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_MACB) += macb.o obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o obj-$(CONFIG_MDIO_GPIO_BITBANG) += mdio_gpio.o +obj-$(CONFIG_MDIO_MT7531_MMIO) += mdio-mt7531-mmio.o obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o obj-$(CONFIG_MDIO_MUX_MESON_G12A) += mdio_mux_meson_g12a.o obj-$(CONFIG_MDIO_MUX_MESON_GXL) += mdio_mux_meson_gxl.o diff --git a/drivers/net/airoha_eth.c b/drivers/net/airoha_eth.c index 6588eb3a806..19c3d60044c 100644 --- a/drivers/net/airoha_eth.c +++ b/drivers/net/airoha_eth.c @@ -449,14 +449,10 @@ static int airoha_qdma_init_rx_queue(struct airoha_queue *q, RX_RING_SIZE_MASK, FIELD_PREP(RX_RING_SIZE_MASK, ndesc)); - /* - * See arht_eth_free_pkt() for the reasons used to fill - * REG_RX_CPU_IDX(qid) register. - */ airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK, FIELD_PREP(RX_RING_THR_MASK, 0)); airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK, - FIELD_PREP(RX_RING_CPU_IDX_MASK, q->ndesc - 3)); + FIELD_PREP(RX_RING_CPU_IDX_MASK, q->ndesc - 1)); airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK, FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head)); @@ -920,7 +916,6 @@ static int arht_eth_free_pkt(struct udevice *dev, uchar *packet, int length) struct airoha_qdma *qdma = ð->qdma[0]; struct airoha_queue *q; int qid; - u16 prev, pprev; if (!packet) return 0; @@ -930,22 +925,29 @@ static int arht_eth_free_pkt(struct udevice *dev, uchar *packet, int length) /* * Due to cpu cache issue the airoha_qdma_reset_rx_desc() function - * will always touch 2 descriptors: - * - if current descriptor is even, then the previous and the one - * before previous descriptors will be touched (previous cacheline) - * - if current descriptor is odd, then only current and previous - * descriptors will be touched (current cacheline) + * will always touch 2 descriptors placed on the same cacheline: + * - if current descriptor is even, then current and next + * descriptors will be touched + * - if current descriptor is odd, then current and previous + * descriptors will be touched * - * Thus, to prevent possible destroying of rx queue, only (q->ndesc - 2) - * descriptors might be used for packet receiving. + * Thus, to prevent possible destroying of rx queue, we should: + * - do nothing in the even descriptor case, + * - utilize 2 descriptors (current and previous one) in the + * odd descriptor case. + * + * WARNING: Observations shows that PKTBUFSRX must be even and + * larger than 7 for reliable driver operations. */ - prev = (q->head + q->ndesc - 1) % q->ndesc; - pprev = (q->head + q->ndesc - 2) % q->ndesc; - q->head = (q->head + 1) % q->ndesc; + if (q->head & 0x01) { + airoha_qdma_reset_rx_desc(q, q->head - 1); + airoha_qdma_reset_rx_desc(q, q->head); - airoha_qdma_reset_rx_desc(q, prev); - airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK, - FIELD_PREP(RX_RING_CPU_IDX_MASK, pprev)); + airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK, + FIELD_PREP(RX_RING_CPU_IDX_MASK, q->head)); + } + + q->head = (q->head + 1) % q->ndesc; return 0; } diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 2fd92cf16bb..6ed9c6d538a 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -125,6 +125,16 @@ static int dw_mdio_reset(struct mii_dev *bus) return __dw_mdio_reset(dev); } + +#if IS_ENABLED(CONFIG_BITBANGMII) +static int dw_bb_mdio_reset(struct mii_dev *bus) +{ + struct dw_eth_dev *priv = bus->priv; + + return __dw_mdio_reset(priv->dev); +} +#endif + #endif #if IS_ENABLED(CONFIG_DM_MDIO) @@ -348,7 +358,7 @@ static int dw_bb_mdio_init(const char *name, struct udevice *dev) bus->read = dw_bb_miiphy_read; bus->write = dw_bb_miiphy_write; #if CONFIG_IS_ENABLED(DM_GPIO) - bus->reset = dw_mdio_reset; + bus->reset = dw_bb_mdio_reset; #endif bus->priv = dwpriv; diff --git a/drivers/net/mdio-mt7531-mmio.c b/drivers/net/mdio-mt7531-mmio.c new file mode 100644 index 00000000000..3e325ca58da --- /dev/null +++ b/drivers/net/mdio-mt7531-mmio.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include +#include + +#define MT7531_PHY_IAC 0x701c +#define MT7531_PHY_ACS_ST BIT(31) +#define MT7531_MDIO_REG_ADDR_CL22 GENMASK(29, 25) +#define MT7531_MDIO_DEV_ADDR MT7531_MDIO_REG_ADDR_CL22 +#define MT7531_MDIO_PHY_ADDR GENMASK(24, 20) +#define MT7531_MDIO_CMD GENMASK(19, 18) +#define MT7531_MDIO_CMD_READ_CL45 FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x3) +#define MT7531_MDIO_CMD_READ_CL22 FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x2) +#define MT7531_MDIO_CMD_WRITE FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x1) +#define MT7531_MDIO_CMD_ADDR FIELD_PREP_CONST(MT7531_MDIO_CMD, 0x0) +#define MT7531_MDIO_ST GENMASK(17, 16) +#define MT7531_MDIO_ST_CL22 FIELD_PREP_CONST(MT7531_MDIO_ST, 0x1) +#define MT7531_MDIO_ST_CL45 FIELD_PREP_CONST(MT7531_MDIO_ST, 0x0) +#define MT7531_MDIO_RW_DATA GENMASK(15, 0) +#define MT7531_MDIO_REG_ADDR_CL45 MT7531_MDIO_RW_DATA + +#define MT7531_MDIO_TIMEOUT 100000 +#define MT7531_MDIO_SLEEP 20 + +struct mt7531_mdio_priv { + phys_addr_t switch_regs; +}; + +static int mt7531_mdio_wait_busy(struct mt7531_mdio_priv *priv) +{ + unsigned int busy; + + return readl_poll_sleep_timeout(priv->switch_regs + MT7531_PHY_IAC, + busy, (busy & MT7531_PHY_ACS_ST) == 0, + MT7531_MDIO_SLEEP, MT7531_MDIO_TIMEOUT); +} + +static int mt7531_mdio_read(struct mt7531_mdio_priv *priv, int addr, int devad, int reg) +{ + u32 val; + + if (devad != MDIO_DEVAD_NONE) { + if (mt7531_mdio_wait_busy(priv)) + return -ETIMEDOUT; + + val = MT7531_PHY_ACS_ST | + MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_ADDR | + FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) | + FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad) | + FIELD_PREP(MT7531_MDIO_REG_ADDR_CL45, reg); + + writel(val, priv->switch_regs + MT7531_PHY_IAC); + } + + if (mt7531_mdio_wait_busy(priv)) + return -ETIMEDOUT; + + val = MT7531_PHY_ACS_ST | FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr); + if (devad != MDIO_DEVAD_NONE) + val |= MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_READ_CL45 | + FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad); + else + val |= MT7531_MDIO_ST_CL22 | MT7531_MDIO_CMD_READ_CL22 | + FIELD_PREP(MT7531_MDIO_REG_ADDR_CL22, reg); + + writel(val, priv->switch_regs + MT7531_PHY_IAC); + + if (mt7531_mdio_wait_busy(priv)) + return -ETIMEDOUT; + + val = readl(priv->switch_regs + MT7531_PHY_IAC); + return val & MT7531_MDIO_RW_DATA; +} + +static int mt7531_mdio_write(struct mt7531_mdio_priv *priv, int addr, int devad, + int reg, u16 value) +{ + u32 val; + + if (devad != MDIO_DEVAD_NONE) { + if (mt7531_mdio_wait_busy(priv)) + return -ETIMEDOUT; + + val = MT7531_PHY_ACS_ST | + MT7531_MDIO_ST_CL45 | MT7531_MDIO_CMD_ADDR | + FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) | + FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad) | + FIELD_PREP(MT7531_MDIO_REG_ADDR_CL45, reg); + + writel(val, priv->switch_regs + MT7531_PHY_IAC); + } + + if (mt7531_mdio_wait_busy(priv)) + return -ETIMEDOUT; + + val = MT7531_PHY_ACS_ST | FIELD_PREP(MT7531_MDIO_PHY_ADDR, addr) | + MT7531_MDIO_CMD_WRITE | FIELD_PREP(MT7531_MDIO_RW_DATA, value); + if (devad != MDIO_DEVAD_NONE) + val |= MT7531_MDIO_ST_CL45 | + FIELD_PREP(MT7531_MDIO_DEV_ADDR, devad); + else + val |= MT7531_MDIO_ST_CL22 | + FIELD_PREP(MT7531_MDIO_REG_ADDR_CL22, reg); + + writel(val, priv->switch_regs + MT7531_PHY_IAC); + + if (mt7531_mdio_wait_busy(priv)) + return -ETIMEDOUT; + + return 0; +} + +int mt7531_mdio_mmio_read(struct mii_dev *bus, int addr, int devad, int reg) +{ + struct mt7531_mdio_priv *priv = bus->priv; + + return mt7531_mdio_read(priv, addr, devad, reg); +} + +int mt7531_mdio_mmio_write(struct mii_dev *bus, int addr, int devad, + int reg, u16 value) +{ + struct mt7531_mdio_priv *priv = bus->priv; + + return mt7531_mdio_write(priv, addr, devad, reg, value); +} + +static int dm_mt7531_mdio_read(struct udevice *dev, int addr, int devad, int reg) +{ + struct mt7531_mdio_priv *priv = dev_get_priv(dev); + + return mt7531_mdio_read(priv, addr, devad, reg); +} + +static int dm_mt7531_mdio_write(struct udevice *dev, int addr, int devad, + int reg, u16 value) +{ + struct mt7531_mdio_priv *priv = dev_get_priv(dev); + + return mt7531_mdio_write(priv, addr, devad, reg, value); +} + +static const struct mdio_ops mt7531_mdio_ops = { + .read = dm_mt7531_mdio_read, + .write = dm_mt7531_mdio_write, +}; + +static int mt7531_mdio_probe(struct udevice *dev) +{ + struct mt7531_mdio_priv *priv = dev_get_priv(dev); + + priv->switch_regs = dev_read_addr(dev); + if (priv->switch_regs == FDT_ADDR_T_NONE) + return -EINVAL; + + return 0; +} + +U_BOOT_DRIVER(mt7531_mdio) = { + .name = "mt7531-mdio-mmio", + .id = UCLASS_MDIO, + .probe = mt7531_mdio_probe, + .ops = &mt7531_mdio_ops, + .priv_auto = sizeof(struct mt7531_mdio_priv), +}; diff --git a/drivers/net/mdio-mt7531-mmio.h b/drivers/net/mdio-mt7531-mmio.h new file mode 100644 index 00000000000..f98102cb939 --- /dev/null +++ b/drivers/net/mdio-mt7531-mmio.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +struct mt7531_mdio_mmio_priv { + phys_addr_t switch_regs; +}; + +int mt7531_mdio_mmio_read(struct mii_dev *bus, int addr, int devad, int reg); +int mt7531_mdio_mmio_write(struct mii_dev *bus, int addr, int devad, + int reg, u16 value); diff --git a/drivers/net/mtk_eth/Kconfig b/drivers/net/mtk_eth/Kconfig index e8cdf408237..5d4e54ab90e 100644 --- a/drivers/net/mtk_eth/Kconfig +++ b/drivers/net/mtk_eth/Kconfig @@ -1,6 +1,7 @@ config MEDIATEK_ETH bool "MediaTek Ethernet GMAC Driver" + depends on ARCH_MEDIATEK || ARCH_MTMIPS select PHYLIB select DM_GPIO select DM_RESET @@ -30,6 +31,7 @@ config MTK_ETH_SWITCH_MT7531 config MTK_ETH_SWITCH_MT7988 bool "Support for MediaTek MT7988 built-in ethernet switch" depends on TARGET_MT7988 + select MDIO_MT7531_MMIO default y config MTK_ETH_SWITCH_AN8855 diff --git a/drivers/net/mtk_eth/mt7531.c b/drivers/net/mtk_eth/mt7531.c index 32d6bebbbdb..965bc3cb7e9 100644 --- a/drivers/net/mtk_eth/mt7531.c +++ b/drivers/net/mtk_eth/mt7531.c @@ -22,17 +22,13 @@ static int mt7531_core_reg_read(struct mt753x_switch_priv *priv, u32 reg) { - u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0); - - return mt7531_mmd_read(priv, phy_addr, 0x1f, reg); + return mt7531_mmd_read(priv, 0, 0x1f, reg); } static void mt7531_core_reg_write(struct mt753x_switch_priv *priv, u32 reg, u32 val) { - u8 phy_addr = MT753X_PHY_ADDR(priv->phy_base, 0); - - mt7531_mmd_write(priv, phy_addr, 0x1f, reg, val); + mt7531_mmd_write(priv, 0, 0x1f, reg, val); } static void mt7531_core_pll_setup(struct mt753x_switch_priv *priv) @@ -171,7 +167,7 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv) { struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv; u32 i, val, pmcr, port5_sgmii; - u16 phy_addr, phy_val; + u16 phy_val; priv->smi_addr = MT753X_DFL_SMI_ADDR; priv->phy_base = (priv->smi_addr + 1) & MT753X_SMI_ADDR_MASK; @@ -180,10 +176,9 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv) /* Turn off PHYs */ for (i = 0; i < MT753X_NUM_PHYS; i++) { - phy_addr = MT753X_PHY_ADDR(priv->phy_base, i); - phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR); + phy_val = mt7531_mii_read(priv, i, MII_BMCR); phy_val |= BMCR_PDOWN; - mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val); + mt7531_mii_write(priv, i, MII_BMCR, phy_val); } /* Force MAC link down before reset */ @@ -239,10 +234,9 @@ static int mt7531_setup(struct mtk_eth_switch_priv *swpriv) /* Turn on PHYs */ for (i = 0; i < MT753X_NUM_PHYS; i++) { - phy_addr = MT753X_PHY_ADDR(priv->phy_base, i); - phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR); + phy_val = mt7531_mii_read(priv, i, MII_BMCR); phy_val &= ~BMCR_PDOWN; - mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val); + mt7531_mii_write(priv, i, MII_BMCR, phy_val); } mt7531_phy_setting(priv); diff --git a/drivers/net/mtk_eth/mt7988.c b/drivers/net/mtk_eth/mt7988.c index a416d87840c..29b6363cbd7 100644 --- a/drivers/net/mtk_eth/mt7988.c +++ b/drivers/net/mtk_eth/mt7988.c @@ -6,6 +6,7 @@ * Author: Mark Lee */ +#include #include #include #include @@ -14,6 +15,8 @@ #include "mtk_eth.h" #include "mt753x.h" +#include "../mdio-mt7531-mmio.h" + static int mt7988_reg_read(struct mt753x_switch_priv *priv, u32 reg, u32 *data) { *data = readl(priv->epriv.ethsys_base + GSW_BASE + reg); @@ -30,20 +33,34 @@ static int mt7988_reg_write(struct mt753x_switch_priv *priv, u32 reg, u32 data) static void mt7988_phy_setting(struct mt753x_switch_priv *priv) { + struct mii_dev *mdio_bus = priv->mdio_bus; u16 val; u32 i; for (i = 0; i < MT753X_NUM_PHYS; i++) { + u16 addr = MT753X_PHY_ADDR(priv->phy_base, i); + + /* Set PHY to PHY page 1 */ + mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE, + 0x1f, 0x1); + /* Enable HW auto downshift */ - mt7531_mii_write(priv, i, 0x1f, 0x1); - val = mt7531_mii_read(priv, i, PHY_EXT_REG_14); + val = mt7531_mdio_mmio_read(mdio_bus, addr, MDIO_DEVAD_NONE, + PHY_EXT_REG_14); val |= PHY_EN_DOWN_SHFIT; - mt7531_mii_write(priv, i, PHY_EXT_REG_14, val); + mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE, + PHY_EXT_REG_14, val); /* PHY link down power saving enable */ - val = mt7531_mii_read(priv, i, PHY_EXT_REG_17); + val = mt7531_mdio_mmio_read(mdio_bus, addr, MDIO_DEVAD_NONE, + PHY_EXT_REG_17); val |= PHY_LINKDOWN_POWER_SAVING_EN; - mt7531_mii_write(priv, i, PHY_EXT_REG_17, val); + mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE, + PHY_EXT_REG_17, val); + + /* Restore PHY to PHY page 0 */ + mt7531_mdio_mmio_write(mdio_bus, addr, MDIO_DEVAD_NONE, + 0x1f, 0x0); } } @@ -58,24 +75,66 @@ static void mt7988_mac_control(struct mtk_eth_switch_priv *swpriv, bool enable) mt7988_reg_write(priv, PMCR_REG(6), pmcr); } +static int mt7988_mdio_register(struct mt753x_switch_priv *priv) +{ + struct mt7531_mdio_mmio_priv *mdio_priv; + struct mii_dev *mdio_bus = mdio_alloc(); + int ret; + + if (!mdio_bus) + return -ENOMEM; + + mdio_priv = malloc(sizeof(*mdio_priv)); + if (!mdio_priv) + return -ENOMEM; + + mdio_priv->switch_regs = (phys_addr_t)priv->epriv.ethsys_base + GSW_BASE; + + mdio_bus->read = mt7531_mdio_mmio_read; + mdio_bus->write = mt7531_mdio_mmio_write; + snprintf(mdio_bus->name, sizeof(mdio_bus->name), priv->epriv.sw->name); + + mdio_bus->priv = mdio_priv; + + ret = mdio_register(mdio_bus); + if (ret) { + free(mdio_bus->priv); + mdio_free(mdio_bus); + return ret; + } + + priv->mdio_bus = mdio_bus; + + return 0; +} + static int mt7988_setup(struct mtk_eth_switch_priv *swpriv) { struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv; + struct mii_dev *mdio_bus; u16 phy_addr, phy_val; + int ret, i; u32 pmcr; - int i; priv->smi_addr = MT753X_DFL_SMI_ADDR; priv->phy_base = (priv->smi_addr + 1) & MT753X_SMI_ADDR_MASK; priv->reg_read = mt7988_reg_read; priv->reg_write = mt7988_reg_write; + ret = mt7988_mdio_register(priv); + if (ret) + return ret; + + mdio_bus = priv->mdio_bus; + /* Turn off PHYs */ for (i = 0; i < MT753X_NUM_PHYS; i++) { phy_addr = MT753X_PHY_ADDR(priv->phy_base, i); - phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR); + phy_val = mt7531_mdio_mmio_read(mdio_bus, phy_addr, + MDIO_DEVAD_NONE, MII_BMCR); phy_val |= BMCR_PDOWN; - mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val); + mt7531_mdio_mmio_write(mdio_bus, phy_addr, MDIO_DEVAD_NONE, + MII_BMCR, phy_val); } switch (priv->epriv.phy_interface) { @@ -129,21 +188,26 @@ static int mt7988_setup(struct mtk_eth_switch_priv *swpriv) /* Turn on PHYs */ for (i = 0; i < MT753X_NUM_PHYS; i++) { phy_addr = MT753X_PHY_ADDR(priv->phy_base, i); - phy_val = mt7531_mii_read(priv, phy_addr, MII_BMCR); + phy_val = mt7531_mdio_mmio_read(mdio_bus, phy_addr, + MDIO_DEVAD_NONE, MII_BMCR); phy_val &= ~BMCR_PDOWN; - mt7531_mii_write(priv, phy_addr, MII_BMCR, phy_val); + mt7531_mdio_mmio_write(mdio_bus, phy_addr, MDIO_DEVAD_NONE, + MII_BMCR, phy_val); } mt7988_phy_setting(priv); - return mt7531_mdio_register(priv); + return 0; } -static int mt7531_cleanup(struct mtk_eth_switch_priv *swpriv) +static int mt7988_cleanup(struct mtk_eth_switch_priv *swpriv) { struct mt753x_switch_priv *priv = (struct mt753x_switch_priv *)swpriv; + struct mii_dev *mdio_bus = priv->mdio_bus; - mdio_unregister(priv->mdio_bus); + mdio_unregister(mdio_bus); + free(mdio_bus->priv); + mdio_free(mdio_bus); return 0; } @@ -155,6 +219,6 @@ MTK_ETH_SWITCH(mt7988) = { .reset_wait_time = 50, .setup = mt7988_setup, - .cleanup = mt7531_cleanup, + .cleanup = mt7988_cleanup, .mac_control = mt7988_mac_control, }; diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 185c6a3156e..018be98705a 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -56,6 +56,7 @@ endif # B53_SWITCH config MV88E61XX_SWITCH bool "Marvell MV88E61xx Ethernet switch PHY support." + depends on !COMPILE_TEST if MV88E61XX_SWITCH @@ -119,6 +120,7 @@ config PHY_BROADCOM config PHY_CORTINA bool "Cortina Ethernet PHYs support" + depends on !COMPILE_TEST config SYS_CORTINA_NO_FW_UPLOAD bool "Cortina firmware loading support" diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index f63a13824ca..903fcd667f6 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -338,7 +338,7 @@ static int aquantia_set_proto(struct phy_device *phydev, static int aquantia_dts_config(struct phy_device *phydev) { - ofnode node = phydev->node; + ofnode node = phy_get_ofnode(phydev); u32 prop; u16 reg; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 9702d042296..b58283fe3d5 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -1250,3 +1250,116 @@ bool phy_interface_is_ncsi(void) return 0; #endif } + +/** + * __phy_read_page() - read the current page + * @phydev: a pointer to a &struct phy_device + * + * Returns page index or < 0 on error + */ +static int __phy_read_page(struct phy_device *phydev) +{ + struct phy_driver *drv = phydev->drv; + + if (!drv->read_page) { + debug("read_page callback not available, PHY driver not loaded?\n"); + return -EOPNOTSUPP; + } + + return drv->read_page(phydev); +} + +/** + * __phy_write_page() - Write a new page + * @phydev: a pointer to a &struct phy_device + * @page: page index to select + * + * Returns 0 or < 0 on error. + */ +static int __phy_write_page(struct phy_device *phydev, int page) +{ + struct phy_driver *drv = phydev->drv; + + if (!drv->write_page) { + debug("write_page callback not available, PHY driver not loaded?\n"); + return -EOPNOTSUPP; + } + + return drv->write_page(phydev, page); +} + +/** + * phy_save_page() - save the current page + * @phydev: a pointer to a &struct phy_device + * + * Return the current page number. On error, + * returns a negative errno. phy_restore_page() must always be called + * after this, irrespective of success or failure of this call. + */ +int phy_save_page(struct phy_device *phydev) +{ + return __phy_read_page(phydev); +} + +/** + * phy_select_page - Switch to a PHY page and return the previous page + * @phydev: a pointer to a &struct phy_device + * @page: desired page + * + * NOTE: Save the current PHY page, and set the current page. + * On error, returns a negative errno, otherwise returns the previous page number. + * phy_restore_page() must always be called after this, irrespective + * of success or failure of this call. + */ +int phy_select_page(struct phy_device *phydev, int page) +{ + int ret, oldpage; + + oldpage = ret = phy_save_page(phydev); + if (ret < 0) + return ret; + + if (oldpage != page) { + ret = __phy_write_page(phydev, page); + if (ret < 0) + return ret; + } + + return oldpage; +} + +/** + * phy_restore_page - Restore a previously saved page and propagate status + * @phydev: a pointer to a &struct phy_device + * @oldpage: the old page, return value from phy_save_page() or phy_select_page() + * @ret: operation's return code + * + * Restoring @oldpage if it is a valid page. + * This function propagates the earliest error code from the group of + * operations. + * + * Returns: + * @oldpage if it was a negative value, otherwise + * @ret if it was a negative errno value, otherwise + * phy_write_page()'s negative value if it were in error, otherwise + * @ret. + */ +int phy_restore_page(struct phy_device *phydev, int oldpage, int ret) +{ + int r; + + if (oldpage >= 0) { + r = __phy_write_page(phydev, oldpage); + + /* Propagate the operation return code if the page write + * was successful. + */ + if (ret >= 0 && r < 0) + ret = r; + } else { + /* Propagate the phy page selection error code */ + ret = oldpage; + } + + return ret; +} \ No newline at end of file diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig index ebf5d828cb0..0ad885c9e8b 100644 --- a/drivers/power/domain/Kconfig +++ b/drivers/power/domain/Kconfig @@ -20,7 +20,7 @@ config APPLE_PMGR_POWER_DOMAIN config AGILEX5_PMGR_POWER_DOMAIN bool "Enable the Agilex5 PMGR power domain driver" - depends on SPL_POWER_DOMAIN + depends on SPL_POWER_DOMAIN && TARGET_SOCFPGA_SOC64 help Enable support for power gating peripherals' SRAM specified in the handoff data values obtained from the bitstream to reduce diff --git a/include/net-common.h b/include/net-common.h index 1112af381a9..78d98e5bba0 100644 --- a/include/net-common.h +++ b/include/net-common.h @@ -479,6 +479,16 @@ int net_loop(enum proto_t protocol); */ int dhcp_run(ulong addr, const char *fname, bool autoload); +/** + * do_dhcp - Run the dhcp command + * + * @cmdtp: Unused + * @flag: Command flags (CMD_FLAG_...) + * @argc: Number of arguments + * @argv: List of arguments + * Return: result (see enum command_ret_t) + */ +int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); /** * do_ping - Run the ping command diff --git a/include/net-lwip.h b/include/net-lwip.h index e88e2186635..c910def5719 100644 --- a/include/net-lwip.h +++ b/include/net-lwip.h @@ -50,7 +50,6 @@ int net_lwip_dns_resolve(char *name_or_ip, ip_addr_t *ip); */ bool wget_validate_uri(char *uri); -int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_dns(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); int do_wget(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); diff --git a/include/phy.h b/include/phy.h index 36354aaf774..ae9fd1652cc 100644 --- a/include/phy.h +++ b/include/phy.h @@ -123,6 +123,11 @@ struct phy_driver { int (*write_mmd)(struct phy_device *phydev, int devad, int reg, u16 val); + /** @read_page: Return the current PHY register page number */ + int (*read_page)(struct phy_device *phydev); + /** @write_page: Set the current PHY register page number */ + int (*write_page)(struct phy_device *phydev, int page); + /* driver private data */ ulong data; }; @@ -314,6 +319,9 @@ int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set); int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 mask, u16 set); +int phy_save_page(struct phy_device *phydev); +int phy_select_page(struct phy_device *phydev, int page); +int phy_restore_page(struct phy_device *phydev, int oldpage, int ret); int phy_startup(struct phy_device *phydev); int phy_config(struct phy_device *phydev); diff --git a/include/uthread.h b/include/uthread.h index 11a19aa9488..78dab77f196 100644 --- a/include/uthread.h +++ b/include/uthread.h @@ -72,7 +72,7 @@ struct uthread_mutex { #define UTHREAD_MUTEX_INITIALIZER { .state = UTHREAD_MUTEX_UNLOCKED } -#ifdef CONFIG_UTHREAD +#if CONFIG_IS_ENABLED(UTHREAD) /** * uthread_create() - Create a uthread object and make it ready for execution @@ -184,5 +184,5 @@ static inline bool uthread_grp_done(unsigned int grp_id) #define uthread_mutex_trylock(_mutex) ({ 0 }) #define uthread_mutex_unlock(_mutex) ({ 0; }) -#endif /* CONFIG_UTHREAD */ +#endif /* CONFIG_IS_ENABLED(UTHREAD) */ #endif /* _UTHREAD_H_ */ diff --git a/lib/Makefile b/lib/Makefile index a2e60668864..07702cef7e7 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -161,7 +161,7 @@ obj-$(CONFIG_LIB_ELF) += elf.o obj-$(CONFIG_$(PHASE_)SEMIHOSTING) += semihosting.o -obj-$(CONFIG_UTHREAD) += uthread.o +obj-$(CONFIG_$(PHASE_)UTHREAD) += uthread.o # # Build a fast OID lookup registry from include/linux/oid_registry.h diff --git a/net/Kconfig b/net/Kconfig index 40ec6bbce76..42fcba5323f 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -60,23 +60,9 @@ config SYS_FAULT_ECHO_LINK_DOWN this option is active, then CONFIG_SYS_FAULT_MII_ADDR also needs to be configured. -config TFTP_PORT - bool "Set TFTP UDP source/destination ports via the environment" - help - If this is defined, the environment variable tftpsrcp is used to - supply the TFTP UDP source port value. If tftpsrcp isn't defined, - the normal pseudo-random port number generator is used. - - Also, the environment variable tftpdstp is used to supply the TFTP - UDP destination port value. If tftpdstp isn't defined, the normal - port 69 is used. - - The purpose for tftpsrcp is to allow a TFTP server to blindly start - the TFTP transfer using the pre-configured target IP address and UDP - port. This has the effect of "punching through" the (Windows XP) - firewall, allowing the remainder of the TFTP transfer to proceed - normally. A better solution is to properly configure the firewall, - but sometimes that is not allowed. +config SYS_FAULT_MII_ADDR + hex "MII address of the PHY to check for the Ethernet link state" + depends on SYS_FAULT_ECHO_LINK_DOWN && LED_STATUS_RED_ENABLE config TFTP_WINDOWSIZE int "TFTP window size" diff --git a/net/bootp.c b/net/bootp.c index 19e7453daed..64fca9a42d9 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -379,6 +379,14 @@ static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip, debug("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%zu)\n", src, dest, len, sizeof(struct bootp_hdr)); + /* Check the minimum size of a BOOTP packet is respected. + * A BOOTP packet is between 300 bytes and 576 bytes big + */ + if (len < offsetof(struct bootp_hdr, bp_vend) + 64) { + printf("Error: got an invalid BOOTP packet (len=%u)\n", len); + return; + } + bp = (struct bootp_hdr *)pkt; /* Filter out pkts we don't want */ @@ -396,7 +404,8 @@ static void bootp_handler(uchar *pkt, unsigned dest, struct in_addr sip, /* Retrieve extended information (we must parse the vendor area) */ if (net_read_u32((u32 *)&bp->bp_vend[0]) == htonl(BOOTP_VENDOR_MAGIC)) - bootp_process_vendor((uchar *)&bp->bp_vend[4], len); + bootp_process_vendor((uchar *)&bp->bp_vend[4], len - + (offsetof(struct bootp_hdr, bp_vend) + 4)); net_set_timeout_handler(0, (thand_f *)0); bootstage_mark_name(BOOTSTAGE_ID_BOOTP_STOP, "bootp_stop"); @@ -491,9 +500,6 @@ static int dhcp_extended(u8 *e, int message_type, struct in_addr server_ip, #endif int clientarch = -1; -#if defined(CONFIG_BOOTP_VENDOREX) - u8 *x; -#endif #if defined(CONFIG_BOOTP_SEND_HOSTNAME) char *hostname; #endif @@ -584,12 +590,6 @@ static int dhcp_extended(u8 *e, int message_type, struct in_addr server_ip, e = add_vci(e); -#if defined(CONFIG_BOOTP_VENDOREX) - x = dhcp_vendorex_prep(e); - if (x) - return x - start; -#endif - *e++ = 55; /* Parameter Request List */ cnt = e++; /* Pointer to count of requested items */ *cnt = 0; @@ -977,10 +977,6 @@ static void dhcp_process_options(uchar *popt, uchar *end) } break; default: -#if defined(CONFIG_BOOTP_VENDOREX) - if (dhcp_vendorex_proc(popt)) - break; -#endif printf("*** Unhandled DHCP Option in OFFER/ACK:" " %d\n", *popt); break; diff --git a/net/bootp.h b/net/bootp.h index 47c743479e7..14f5af68e15 100644 --- a/net/bootp.h +++ b/net/bootp.h @@ -24,10 +24,6 @@ #if defined(CONFIG_CMD_DHCP) /* Minimum DHCP Options size per RFC2131 - results in 576 byte pkt */ #define OPT_FIELD_SIZE 312 -#if defined(CONFIG_BOOTP_VENDOREX) -extern u8 *dhcp_vendorex_prep(u8 *e); /*rtn new e after add own opts. */ -extern u8 *dhcp_vendorex_proc(u8 *e); /*rtn next e if mine,else NULL */ -#endif #else #define OPT_FIELD_SIZE 64 #endif diff --git a/net/lwip/dhcp.c b/net/lwip/dhcp.c index 531bf2c6705..b798014ebcb 100644 --- a/net/lwip/dhcp.c +++ b/net/lwip/dhcp.c @@ -150,25 +150,3 @@ int do_dhcp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_SUCCESS; } - -int dhcp_run(ulong addr, const char *fname, bool autoload) -{ - char *dhcp_argv[] = {"dhcp", NULL, }; -#ifdef CONFIG_CMD_TFTPBOOT - char *tftp_argv[] = {"tftpboot", boot_file_name, NULL, }; -#endif - struct cmd_tbl cmdtp = {}; /* dummy */ - - if (autoload) { -#ifdef CONFIG_CMD_TFTPBOOT - /* Assume DHCP was already performed */ - if (boot_file_name[0]) - return do_tftpb(&cmdtp, 0, 2, tftp_argv); - return 0; -#else - return -EOPNOTSUPP; -#endif - } - - return do_dhcp(&cmdtp, 0, 1, dhcp_argv); -} diff --git a/net/net-common.c b/net/net-common.c index b064557d524..442b0597558 100644 --- a/net/net-common.c +++ b/net/net-common.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include @@ -48,3 +49,37 @@ void net_sntp_set_rtc(u32 seconds) tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); } + +#if defined(CONFIG_CMD_DHCP) +int dhcp_run(ulong addr, const char *fname, bool autoload) +{ + char *dhcp_argv[] = {"dhcp", NULL, (char *)fname, NULL}; + struct cmd_tbl cmdtp = {}; /* dummy */ + char file_addr[17]; + int old_autoload; + int ret, result; + + log_debug("addr=%lx, fname=%s, autoload=%d\n", addr, fname, autoload); + old_autoload = env_get_yesno("autoload"); + ret = env_set("autoload", autoload ? "y" : "n"); + if (ret) + return log_msg_ret("en1", -EINVAL); + + if (autoload) { + sprintf(file_addr, "%lx", addr); + dhcp_argv[1] = file_addr; + } + + result = do_dhcp(&cmdtp, 0, !autoload ? 1 : fname ? 3 : 2, dhcp_argv); + + ret = env_set("autoload", old_autoload == -1 ? NULL : + old_autoload ? "y" : "n"); + if (ret) + return log_msg_ret("en2", -EINVAL); + + if (result) + return log_msg_ret("res", -ENOENT); + + return 0; +} +#endif diff --git a/net/tftp.c b/net/tftp.c index 1ca9a5ea7cf..1760877107f 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -926,14 +926,13 @@ void tftp_start(enum proto_t protocol) /* Use a pseudo-random port unless a specific port is set */ tftp_our_port = 1024 + (get_timer(0) % 3072); -#ifdef CONFIG_TFTP_PORT ep = env_get("tftpdstp"); if (ep != NULL) tftp_remote_port = simple_strtol(ep, NULL, 10); ep = env_get("tftpsrcp"); if (ep != NULL) tftp_our_port = simple_strtol(ep, NULL, 10); -#endif + tftp_cur_block = 0; tftp_windowsize = 1; tftp_last_nack = 0;