diff options
-rw-r--r-- | arch/arm/dts/uniphier-ld20.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/dts/uniphier-pxs2.dtsi | 2 | ||||
-rw-r--r-- | arch/arm/dts/uniphier-pxs3.dtsi | 4 | ||||
-rw-r--r-- | arch/powerpc/cpu/mpc8xx/cpu.c | 12 | ||||
-rw-r--r-- | arch/powerpc/dts/mcr3000.dts | 4 | ||||
-rw-r--r-- | configs/MCR3000_defconfig | 1 | ||||
-rw-r--r-- | drivers/net/Kconfig | 6 | ||||
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/dm9000x.c | 4 | ||||
-rw-r--r-- | drivers/net/dwc_eth_qos.c | 13 | ||||
-rw-r--r-- | drivers/net/ftgmac100.c | 4 | ||||
-rw-r--r-- | drivers/net/mpc8xx_fec.c | 189 | ||||
-rw-r--r-- | drivers/net/npcm750_eth.c | 745 | ||||
-rw-r--r-- | drivers/net/phy/marvell.c | 121 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 180 | ||||
-rw-r--r-- | drivers/net/sni_ave.c | 14 | ||||
-rw-r--r-- | include/configs/imx8mp_evk.h | 2 | ||||
-rw-r--r-- | include/configs/imx8mp_rsb3720.h | 1 | ||||
-rw-r--r-- | include/configs/imx93_evk.h | 1 | ||||
-rw-r--r-- | include/net.h | 4 | ||||
-rw-r--r-- | include/netdev.h | 1 | ||||
-rw-r--r-- | include/phy.h | 189 | ||||
-rw-r--r-- | net/Kconfig | 6 | ||||
-rw-r--r-- | net/bootp.c | 2 |
24 files changed, 1199 insertions, 309 deletions
diff --git a/arch/arm/dts/uniphier-ld20.dtsi b/arch/arm/dts/uniphier-ld20.dtsi index 5e7143ed012..4549935c421 100644 --- a/arch/arm/dts/uniphier-ld20.dtsi +++ b/arch/arm/dts/uniphier-ld20.dtsi @@ -734,7 +734,7 @@ clocks = <&sys_clk 6>; reset-names = "ether"; resets = <&sys_rst 6>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; local-mac-address = [00 00 00 00 00 00]; socionext,syscon-phy-mode = <&soc_glue 0>; diff --git a/arch/arm/dts/uniphier-pxs2.dtsi b/arch/arm/dts/uniphier-pxs2.dtsi index 899ff379c9b..7a8b6c10f4d 100644 --- a/arch/arm/dts/uniphier-pxs2.dtsi +++ b/arch/arm/dts/uniphier-pxs2.dtsi @@ -583,7 +583,7 @@ clocks = <&sys_clk 6>; reset-names = "ether"; resets = <&sys_rst 6>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; local-mac-address = [00 00 00 00 00 00]; socionext,syscon-phy-mode = <&soc_glue 0>; diff --git a/arch/arm/dts/uniphier-pxs3.dtsi b/arch/arm/dts/uniphier-pxs3.dtsi index c4344926d95..004656c992b 100644 --- a/arch/arm/dts/uniphier-pxs3.dtsi +++ b/arch/arm/dts/uniphier-pxs3.dtsi @@ -564,7 +564,7 @@ clocks = <&sys_clk 6>; reset-names = "ether"; resets = <&sys_rst 6>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; local-mac-address = [00 00 00 00 00 00]; socionext,syscon-phy-mode = <&soc_glue 0>; @@ -585,7 +585,7 @@ clocks = <&sys_clk 7>; reset-names = "ether"; resets = <&sys_rst 7>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; local-mac-address = [00 00 00 00 00 00]; socionext,syscon-phy-mode = <&soc_glue 1>; diff --git a/arch/powerpc/cpu/mpc8xx/cpu.c b/arch/powerpc/cpu/mpc8xx/cpu.c index 6d16ed084e6..0ccb9f6df6f 100644 --- a/arch/powerpc/cpu/mpc8xx/cpu.c +++ b/arch/powerpc/cpu/mpc8xx/cpu.c @@ -266,15 +266,3 @@ unsigned long get_tbclk(void) return oscclk / 16; } - -/* - * Initializes on-chip ethernet controllers. - * to override, implement board_eth_init() - */ -int cpu_eth_init(struct bd_info *bis) -{ -#if defined(CONFIG_MPC8XX_FEC) - fec_initialize(bis); -#endif - return 0; -} diff --git a/arch/powerpc/dts/mcr3000.dts b/arch/powerpc/dts/mcr3000.dts index 5abf111dc5f..5f32d8a2e55 100644 --- a/arch/powerpc/dts/mcr3000.dts +++ b/arch/powerpc/dts/mcr3000.dts @@ -16,6 +16,10 @@ compatible = "fsl,pq1-smc"; }; + FEC: fec@0 { + compatible = "fsl,pq1-fec1"; + }; + chosen { stdout-path = &SERIAL; }; diff --git a/configs/MCR3000_defconfig b/configs/MCR3000_defconfig index 086507e6016..94743d69d12 100644 --- a/configs/MCR3000_defconfig +++ b/configs/MCR3000_defconfig @@ -91,3 +91,4 @@ CONFIG_DM_SERIAL=y CONFIG_WDT=y CONFIG_SHA256=y CONFIG_LZMA=y +CONFIG_DM_ETH=y diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 93e7dbe9766..52dc9e4f0f6 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -523,6 +523,11 @@ config MT7628_ETH The MediaTek MT7628 ethernet interface is used on MT7628 and MT7688 based boards. +config NET_NPCM750 + bool "Nuvoton NPCM750 Ethernet MAC" + help + support NPCM750 EMAC + config NET_OCTEON bool "MIPS Octeon ethernet support" depends on ARCH_OCTEON @@ -744,6 +749,7 @@ config RENESAS_RAVB config MPC8XX_FEC bool "Fast Ethernet Controller on MPC8XX" depends on MPC8xx + depends on DM_ETH select MII select SYS_DISCOVER_PHY help diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 9536af11946..054ec68470d 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -65,6 +65,7 @@ obj-$(CONFIG_MVMDIO) += mvmdio.o obj-$(CONFIG_MVNETA) += mvneta.o obj-$(CONFIG_MVPP2) += mvpp2.o obj-$(CONFIG_NETCONSOLE) += netconsole.o +obj-$(CONFIG_NET_NPCM750) += npcm750_eth.o obj-$(CONFIG_NET_OCTEON) += octeon/ obj-$(CONFIG_NET_OCTEONTX) += octeontx/ obj-$(CONFIG_NET_OCTEONTX2) += octeontx2/ diff --git a/drivers/net/dm9000x.c b/drivers/net/dm9000x.c index 78ce536d4a3..07733df533e 100644 --- a/drivers/net/dm9000x.c +++ b/drivers/net/dm9000x.c @@ -666,10 +666,10 @@ static int dm9000_recv(struct udevice *dev, int flags, uchar **packetp) int ret; ret = dm9000_recv_common(db, data); - if (ret) + if (ret > 0) *packetp = (void *)data; - return ret ? ret : -EAGAIN; + return ret >= 0 ? ret : -EAGAIN; } static int dm9000_write_hwaddr(struct udevice *dev) diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index c1f2391d635..001b028fa13 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -34,6 +34,7 @@ #include <cpu_func.h> #include <dm.h> #include <errno.h> +#include <eth_phy.h> #include <log.h> #include <malloc.h> #include <memalign.h> @@ -46,7 +47,6 @@ #include <asm/cache.h> #include <asm/gpio.h> #include <asm/io.h> -#include <eth_phy.h> #ifdef CONFIG_ARCH_IMX8M #include <asm/arch/clock.h> #include <asm/mach-imx/sys_proto.h> @@ -789,9 +789,6 @@ static int eqos_start(struct udevice *dev) if (!eqos->phy) { int addr = -1; addr = eqos_get_phy_addr(eqos, dev); -#ifdef DWC_NET_PHYADDR - addr = DWC_NET_PHYADDR; -#endif eqos->phy = phy_connect(eqos->mii, addr, dev, eqos->config->interface(dev)); if (!eqos->phy) { @@ -1399,8 +1396,6 @@ static int eqos_probe_resources_stm32(struct udevice *dev) if (ret) return -EINVAL; - eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0); - ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus); if (ret) { pr_err("clk_get_by_name(master_bus) failed: %d", ret); @@ -1503,6 +1498,8 @@ static int eqos_probe(struct udevice *dev) eqos->dma_regs = (void *)(eqos->regs + EQOS_DMA_REGS_BASE); eqos->tegra186_regs = (void *)(eqos->regs + EQOS_TEGRA186_REGS_BASE); + eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0); + ret = eqos_probe_resources_core(dev); if (ret < 0) { pr_err("eqos_probe_resources_core() failed: %d", ret); @@ -1574,7 +1571,7 @@ static int eqos_remove(struct udevice *dev) eqos->config->ops->eqos_stop_clks(dev); eqos->config->ops->eqos_remove_resources(dev); - eqos_probe_resources_core(dev); + eqos_remove_resources_core(dev); debug("%s: OK\n", __func__); return 0; @@ -1609,6 +1606,7 @@ static struct eqos_ops eqos_tegra186_ops = { .eqos_calibrate_pads = eqos_calibrate_pads_tegra186, .eqos_disable_calibration = eqos_disable_calibration_tegra186, .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_tegra186, + .eqos_get_enetaddr = eqos_null_ops, .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_tegra186 }; @@ -1637,6 +1635,7 @@ static struct eqos_ops eqos_stm32_ops = { .eqos_calibrate_pads = eqos_null_ops, .eqos_disable_calibration = eqos_null_ops, .eqos_set_tx_clk_speed = eqos_null_ops, + .eqos_get_enetaddr = eqos_null_ops, .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32 }; diff --git a/drivers/net/ftgmac100.c b/drivers/net/ftgmac100.c index 78779d7d60b..74261d14e54 100644 --- a/drivers/net/ftgmac100.c +++ b/drivers/net/ftgmac100.c @@ -119,7 +119,7 @@ static int ftgmac100_mdio_read(struct mii_dev *bus, int phy_addr, int dev_addr, FTGMAC100_MDIO_TIMEOUT_USEC); if (ret) { pr_err("%s: mdio read failed (phy:%d reg:%x)\n", - priv->phydev->dev->name, phy_addr, reg_addr); + bus->name, phy_addr, reg_addr); return ret; } @@ -151,7 +151,7 @@ static int ftgmac100_mdio_write(struct mii_dev *bus, int phy_addr, int dev_addr, FTGMAC100_MDIO_TIMEOUT_USEC); if (ret) { pr_err("%s: mdio write failed (phy:%d reg:%x)\n", - priv->phydev->dev->name, phy_addr, reg_addr); + bus->name, phy_addr, reg_addr); } return ret; diff --git a/drivers/net/mpc8xx_fec.c b/drivers/net/mpc8xx_fec.c index 4eb82602811..78337731e1f 100644 --- a/drivers/net/mpc8xx_fec.c +++ b/drivers/net/mpc8xx_fec.c @@ -41,7 +41,7 @@ DECLARE_GLOBAL_DATA_PTR; #endif #ifdef CONFIG_SYS_DISCOVER_PHY -static int mii_discover_phy(struct eth_device *dev); +static int mii_discover_phy(struct udevice *dev); #endif int fec8xx_miiphy_read(struct mii_dev *bus, int addr, int devad, int reg); @@ -111,50 +111,24 @@ struct common_buf_desc { static struct common_buf_desc __iomem *rtx; -static int fec_send(struct eth_device *dev, void *packet, int length); -static int fec_recv(struct eth_device *dev); -static int fec_init(struct eth_device *dev, struct bd_info *bd); -static void fec_halt(struct eth_device *dev); #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) static void __mii_init(void); #endif -int fec_initialize(struct bd_info *bis) +static int fec_probe(struct udevice *dev) { - struct eth_device *dev; - struct ether_fcc_info_s *efis; + struct ether_fcc_info_s *efis = dev_get_priv(dev); + int index = dev_get_driver_data(dev); int i; for (i = 0; i < ARRAY_SIZE(ether_fcc_info); i++) { - dev = malloc(sizeof(*dev)); - if (dev == NULL) - hang(); + if (ether_fcc_info[i].ether_index != index) + continue; - memset(dev, 0, sizeof(*dev)); + memcpy(efis, ðer_fcc_info[i], sizeof(*efis)); - /* for FEC1 make sure that the name of the interface is the same - as the old one for compatibility reasons */ - if (i == 0) - strcpy(dev->name, "FEC"); - else - sprintf(dev->name, "FEC%d", - ether_fcc_info[i].ether_index + 1); - - efis = ðer_fcc_info[i]; - - /* - * reset actual phy addr - */ efis->actual_phy_addr = -1; - dev->priv = efis; - dev->init = fec_init; - dev->halt = fec_halt; - dev->send = fec_send; - dev->recv = fec_recv; - - eth_register(dev); - #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) int retval; struct mii_dev *mdiodev = mdio_alloc(); @@ -169,13 +143,13 @@ int fec_initialize(struct bd_info *bis) return retval; #endif } - return 1; + return 0; } -static int fec_send(struct eth_device *dev, void *packet, int length) +static int fec_send(struct udevice *dev, void *packet, int length) { int j, rc; - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); @@ -217,59 +191,57 @@ static int fec_send(struct eth_device *dev, void *packet, int length) return rc; } -static int fec_recv(struct eth_device *dev) +static int fec_recv(struct udevice *dev, int flags, uchar **packetp) { - struct ether_fcc_info_s *efis = dev->priv; - fec_t __iomem *fecp = - (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); int length; - for (;;) { - /* section 16.9.23.2 */ - if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY) { - length = -1; - break; /* nothing received - leave for() loop */ - } - - length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen); + /* section 16.9.23.2 */ + if (in_be16(&rtx->rxbd[rxIdx].cbd_sc) & BD_ENET_RX_EMPTY) + return -EAGAIN; - if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) { - uchar *rx = net_rx_packets[rxIdx]; + length = in_be16(&rtx->rxbd[rxIdx].cbd_datlen); - length -= 4; + if (!(in_be16(&rtx->rxbd[rxIdx].cbd_sc) & 0x003f)) { + uchar *rx = net_rx_packets[rxIdx]; #if defined(CONFIG_CMD_CDP) - if ((rx[0] & 1) != 0 && - memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 && - !is_cdp_packet((uchar *)rx)) - rx = NULL; + if ((rx[0] & 1) != 0 && + memcmp((uchar *)rx, net_bcast_ethaddr, 6) != 0 && + !is_cdp_packet((uchar *)rx)) + return 0; #endif - /* - * Pass the packet up to the protocol layers. - */ - if (rx != NULL) - net_process_received_packet(rx, length); - } + *packetp = rx; - /* Give the buffer back to the FEC. */ - out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0); - - /* wrap around buffer index when necessary */ - if ((rxIdx + 1) >= PKTBUFSRX) { - out_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc, - BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); - rxIdx = 0; - } else { - out_be16(&rtx->rxbd[rxIdx].cbd_sc, BD_ENET_RX_EMPTY); - rxIdx++; - } + return length - 4; + } else { + return 0; + } +} - /* Try to fill Buffer Descriptors */ - /* Descriptor polling active */ - out_be32(&fecp->fec_r_des_active, 0x01000000); +static int fec_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct ether_fcc_info_s *efis = dev_get_priv(dev); + fec_t __iomem *fecp = + (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); + + /* Give the buffer back to the FEC. */ + out_be16(&rtx->rxbd[rxIdx].cbd_datlen, 0); + + /* wrap around buffer index when necessary */ + if ((rxIdx + 1) >= PKTBUFSRX) { + out_be16(&rtx->rxbd[PKTBUFSRX - 1].cbd_sc, + BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); + rxIdx = 0; + } else { + out_be16(&rtx->rxbd[rxIdx].cbd_sc, BD_ENET_RX_EMPTY); + rxIdx++; } - return length; + /* Try to fill Buffer Descriptors */ + /* Descriptor polling active */ + out_be32(&fecp->fec_r_des_active, 0x01000000); + + return 0; } /************************************************************** @@ -296,9 +268,9 @@ static int fec_recv(struct eth_device *dev) #if defined(CONFIG_RMII) -static inline void fec_10Mbps(struct eth_device *dev) +static inline void fec_10Mbps(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); int fecidx = efis->ether_index; uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008; immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; @@ -309,9 +281,9 @@ static inline void fec_10Mbps(struct eth_device *dev) setbits_be32(&immr->im_cpm.cp_cptr, mask); } -static inline void fec_100Mbps(struct eth_device *dev) +static inline void fec_100Mbps(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); int fecidx = efis->ether_index; uint mask = (fecidx == 0) ? 0x0000010 : 0x0000008; immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; @@ -324,9 +296,9 @@ static inline void fec_100Mbps(struct eth_device *dev) #endif -static inline void fec_full_duplex(struct eth_device *dev) +static inline void fec_full_duplex(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); @@ -334,9 +306,9 @@ static inline void fec_full_duplex(struct eth_device *dev) setbits_be32(&fecp->fec_x_cntrl, FEC_TCNTRL_FDEN); /* FD enable */ } -static inline void fec_half_duplex(struct eth_device *dev) +static inline void fec_half_duplex(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); @@ -497,9 +469,10 @@ static int fec_reset(fec_t __iomem *fecp) return 0; } -static int fec_init(struct eth_device *dev, struct bd_info *bd) +static int fec_start(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct eth_pdata *plat = dev_get_plat(dev); + struct ether_fcc_info_s *efis = dev_get_priv(dev); immap_t __iomem *immr = (immap_t __iomem *)CONFIG_SYS_IMMR; fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); @@ -529,7 +502,7 @@ static int fec_init(struct eth_device *dev, struct bd_info *bd) /* Set station address */ -#define ea dev->enetaddr +#define ea plat->enetaddr out_be32(&fecp->fec_addr_low, (ea[0] << 24) | (ea[1] << 16) | (ea[2] << 8) | ea[3]); out_be16(&fecp->fec_addr_high, (ea[4] << 8) | ea[5]); @@ -665,9 +638,9 @@ static int fec_init(struct eth_device *dev, struct bd_info *bd) } -static void fec_halt(struct eth_device *dev) +static void fec_stop(struct udevice *dev) { - struct ether_fcc_info_s *efis = dev->priv; + struct ether_fcc_info_s *efis = dev_get_priv(dev); fec_t __iomem *fecp = (fec_t __iomem *)(CONFIG_SYS_IMMR + efis->fecp_offset); int i; @@ -750,7 +723,7 @@ mii_send(uint mii_cmd) #endif #if defined(CONFIG_SYS_DISCOVER_PHY) -static int mii_discover_phy(struct eth_device *dev) +static int mii_discover_phy(struct udevice *dev) { #define MAX_PHY_PASSES 11 uint phyno; @@ -854,3 +827,37 @@ int fec8xx_miiphy_write(struct mii_dev *bus, int addr, int devad, int reg, return 0; } #endif + +static const struct eth_ops fec_ops = { + .start = fec_start, + .send = fec_send, + .recv = fec_recv, + .stop = fec_stop, + .free_pkt = fec_free_pkt, +}; + +static const struct udevice_id fec_ids[] = { +#ifdef CONFIG_ETHER_ON_FEC1 + { + .compatible = "fsl,pq1-fec1", + .data = 0, + }, +#endif +#ifdef CONFIG_ETHER_ON_FEC2 + { + .compatible = "fsl,pq1-fec2", + .data = 1, + }, +#endif + { } +}; + +U_BOOT_DRIVER(fec) = { + .name = "fec", + .id = UCLASS_ETH, + .of_match = fec_ids, + .probe = fec_probe, + .ops = &fec_ops, + .priv_auto = sizeof(struct ether_fcc_info_s), + .plat_auto = sizeof(struct eth_pdata), +}; diff --git a/drivers/net/npcm750_eth.c b/drivers/net/npcm750_eth.c new file mode 100644 index 00000000000..409d5cce4a7 --- /dev/null +++ b/drivers/net/npcm750_eth.c @@ -0,0 +1,745 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2021 Nuvoton Technology Corp. + */ + +#include <common.h> +#include <cpu_func.h> +#include <dm.h> +#include <errno.h> +#include <miiphy.h> +#include <malloc.h> +#include <net.h> +#include <regmap.h> +#include <serial.h> +#include <syscon.h> +#include <asm/io.h> +#include <linux/err.h> +#include <linux/iopoll.h> + +#define MAC_ADDR_SIZE 6 +#define CONFIG_TX_DESCR_NUM 32 +#define CONFIG_RX_DESCR_NUM 32 + +#define TX_TOTAL_BUFSIZE \ + ((CONFIG_TX_DESCR_NUM + 1) * PKTSIZE_ALIGN + PKTALIGN) +#define RX_TOTAL_BUFSIZE \ + ((CONFIG_RX_DESCR_NUM + 1) * PKTSIZE_ALIGN + PKTALIGN) + +#define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ) + +struct npcm750_rxbd { + unsigned int sl; + unsigned int buffer; + unsigned int reserved; + unsigned int next; +} __aligned(ARCH_DMA_MINALIGN); + +struct npcm750_txbd { + unsigned int mode; + unsigned int buffer; + unsigned int sl; + unsigned int next; +} __aligned(ARCH_DMA_MINALIGN); + +struct emc_regs { + u32 camcmr; /* 0x00 */ + u32 camen; /* 0x04 */ + u32 cam0m; /* 0x08 */ + u32 cam0l; /* 0x0c */ + u32 cam1m; /* 0x10 */ + u32 cam1l; /* 0x14 */ + u32 cam2m; /* 0x18 */ + u32 cam2l; /* 0x1c */ + u32 cam3m; /* 0x20 */ + u32 cam3l; /* 0x24 */ + u32 cam4m; /* 0x28 */ + u32 cam4l; /* 0x2c */ + u32 cam5m; /* 0x30 */ + u32 cam5l; /* 0x34 */ + u32 cam6m; /* 0x38 */ + u32 cam6l; /* 0x3c */ + u32 cam7m; /* 0x40 */ + u32 cam7l; /* 0x44 */ + u32 cam8m; /* 0x48 */ + u32 cam8l; /* 0x4c */ + u32 cam9m; /* 0x50 */ + u32 cam9l; /* 0x54 */ + u32 cam10m; /* 0x58 */ + u32 cam10l; /* 0x5c */ + u32 cam11m; /* 0x60 */ + u32 cam11l; /* 0x64 */ + u32 cam12m; /* 0x68 */ + u32 cam12l; /* 0x6c */ + u32 cam13m; /* 0x70 */ + u32 cam13l; /* 0x74 */ + u32 cam14m; /* 0x78 */ + u32 cam14l; /* 0x7c */ + u32 cam15m; /* 0x80 */ + u32 cam15l; /* 0x84 */ + u32 txdlsa; /* 0x88 */ + u32 rxdlsa; /* 0x8c */ + u32 mcmdr; /* 0x90 */ + u32 miid; /* 0x94 */ + u32 miida; /* 0x98 */ + u32 fftcr; /* 0x9c */ + u32 tsdr; /* 0xa0 */ + u32 rsdr; /* 0xa4 */ + u32 dmarfc; /* 0xa8 */ + u32 mien; /* 0xac */ + u32 mista; /* 0xb0 */ + u32 mgsta; /* 0xb4 */ + u32 mpcnt; /* 0xb8 */ + u32 mrpc; /* 0xbc */ + u32 mrpcc; /* 0xc0 */ + u32 mrepc; /* 0xc4 */ + u32 dmarfs; /* 0xc8 */ + u32 ctxdsa; /* 0xcc */ + u32 ctxbsa; /* 0xd0 */ + u32 crxdsa; /* 0xd4 */ + u32 crxbsa; /* 0xd8 */ +}; + +struct npcm750_eth_dev { + struct npcm750_txbd tdesc[CONFIG_TX_DESCR_NUM] __aligned(ARCH_DMA_MINALIGN); + struct npcm750_rxbd rdesc[CONFIG_RX_DESCR_NUM] __aligned(ARCH_DMA_MINALIGN); + u8 txbuffs[TX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN); + u8 rxbuffs[RX_TOTAL_BUFSIZE] __aligned(ARCH_DMA_MINALIGN); + struct emc_regs *emc_regs_p; + struct phy_device *phydev; + struct mii_dev *bus; + struct npcm750_txbd *curr_txd; + struct npcm750_rxbd *curr_rxd; + u32 interface; + u32 max_speed; + u32 idx; + struct regmap *gcr_regmap; +}; + +struct npcm750_eth_pdata { + struct eth_pdata eth_pdata; +}; + +/* mac controller bit */ +#define MCMDR_RXON BIT(0) +#define MCMDR_ACP BIT(3) +#define MCMDR_SPCRC BIT(5) +#define MCMDR_TXON BIT(8) +#define MCMDR_NDEF BIT(9) +#define MCMDR_FDUP BIT(18) +#define MCMDR_ENMDC BIT(19) +#define MCMDR_OPMOD BIT(20) +#define MCMDR_SWR BIT(24) + +/* cam command regiser */ +#define CAMCMR_AUP 0x01 +#define CAMCMR_AMP BIT(1) +#define CAMCMR_ABP BIT(2) +#define CAMCMR_CCAM BIT(3) +#define CAMCMR_ECMP BIT(4) +#define CAM0EN 0x01 + +/* mac mii controller bit */ +#define MDCON BIT(19) +#define PHYAD BIT(8) +#define PHYWR BIT(16) +#define PHYBUSY BIT(17) +#define PHYPRESP BIT(18) +#define CAM_ENTRY_SIZE 0x08 + +/* rx and tx status */ +#define TXDS_TXCP BIT(19) +#define RXDS_CRCE BIT(17) +#define RXDS_PTLE BIT(19) +#define RXDS_RXGD BIT(20) +#define RXDS_ALIE BIT(21) +#define RXDS_RP BIT(22) + +/* mac interrupt status*/ +#define MISTA_RXINTR BIT(0) +#define MISTA_CRCE BIT(1) +#define MISTA_RXOV BIT(2) +#define MISTA_PTLE BIT(3) +#define MISTA_RXGD BIT(4) +#define MISTA_ALIE BIT(5) +#define MISTA_RP BIT(6) +#define MISTA_MMP BIT(7) +#define MISTA_DFOI BIT(8) +#define MISTA_DENI BIT(9) +#define MISTA_RDU BIT(10) +#define MISTA_RXBERR BIT(11) +#define MISTA_CFR BIT(14) +#define MISTA_TXINTR BIT(16) +#define MISTA_TXEMP BIT(17) +#define MISTA_TXCP BIT(18) +#define MISTA_EXDEF BIT(19) +#define MISTA_NCS BIT(20) +#define MISTA_TXABT BIT(21) +#define MISTA_LC BIT(22) +#define MISTA_TDU BIT(23) +#define MISTA_TXBERR BIT(24) + +#define ENSTART 0x01 +#define ENRXINTR BIT(0) +#define ENCRCE BIT(1) +#define EMRXOV BIT(2) +#define ENPTLE BIT(3) +#define ENRXGD BIT(4) +#define ENALIE BIT(5) +#define ENRP BIT(6) +#define ENMMP BIT(7) +#define ENDFO BIT(8) +#define ENDENI BIT(9) +#define ENRDU BIT(10) +#define ENRXBERR BIT(11) +#define ENCFR BIT(14) +#define ENTXINTR BIT(16) +#define ENTXEMP BIT(17) +#define ENTXCP BIT(18) +#define ENTXDEF BIT(19) +#define ENNCS BIT(20) +#define ENTXABT BIT(21) +#define ENLC BIT(22) +#define ENTDU BIT(23) +#define ENTXBERR BIT(24) + +#define RX_STAT_RBC 0xffff +#define RX_STAT_RXINTR BIT(16) +#define RX_STAT_CRCE BIT(17) +#define RX_STAT_PTLE BIT(19) +#define RX_STAT_RXGD BIT(20) +#define RX_STAT_ALIE BIT(21) +#define RX_STAT_RP BIT(22) +#define RX_STAT_OWNER (BIT(30) | BIT(31)) + +#define TX_STAT_TBC 0xffff +#define TX_STAT_TXINTR BIT(16) +#define TX_STAT_DEF BIT(17) +#define TX_STAT_TXCP BIT(19) +#define TX_STAT_EXDEF BIT(20) +#define TX_STAT_NCS BIT(21) +#define TX_STAT_TXBT BIT(22) +#define TX_STAT_LC BIT(23) +#define TX_STAT_TXHA BIT(24) +#define TX_STAT_PAU BIT(25) +#define TX_STAT_SQE BIT(26) + +/* rx and tx owner bit */ +#define RX_OWEN_DMA BIT(31) +#define RX_OWEN_CPU 0x00 //bit 30 & bit 31 +#define TX_OWEN_DMA BIT(31) +#define TX_OWEN_CPU (~(BIT(31))) + +/* tx frame desc controller bit */ +#define MACTXINTEN 0x04 +#define CRCMODE 0x02 +#define PADDINGMODE 0x01 + +/* fftcr controller bit */ +#define RXTHD 0x03 +#define TXTHD (BIT(8) | BIT(9)) +#define BLENGTH BIT(21) + +/* global setting for driver */ +#define RX_DESC_SIZE 128 +#define TX_DESC_SIZE 64 +#define MAX_RBUFF_SZ 0x600 +#define MAX_TBUFF_SZ 0x600 +#define TX_TIMEOUT 50 +#define DELAY 1000 +#define CAM0 0x0 +#define RX_POLL_SIZE (RX_DESC_SIZE / 2) +#define MII_TIMEOUT 100 +#define GCR_INTCR 0x3c +#define INTCR_R1EN BIT(5) + +enum MIIDA_MDCCR_T { + MIIDA_MDCCR_4 = 0x00, + MIIDA_MDCCR_6 = 0x01, + MIIDA_MDCCR_8 = 0x02, + MIIDA_MDCCR_12 = 0x03, + MIIDA_MDCCR_16 = 0x04, + MIIDA_MDCCR_20 = 0x05, + MIIDA_MDCCR_24 = 0x06, + MIIDA_MDCCR_28 = 0x07, + MIIDA_MDCCR_30 = 0x08, + MIIDA_MDCCR_32 = 0x09, + MIIDA_MDCCR_36 = 0x0A, + MIIDA_MDCCR_40 = 0x0B, + MIIDA_MDCCR_44 = 0x0C, + MIIDA_MDCCR_48 = 0x0D, + MIIDA_MDCCR_54 = 0x0E, + MIIDA_MDCCR_60 = 0x0F, +}; + +DECLARE_GLOBAL_DATA_PTR; + +static int npcm750_mdio_read(struct mii_dev *bus, int addr, int devad, int regs) +{ + struct npcm750_eth_dev *priv = (struct npcm750_eth_dev *)bus->priv; + struct emc_regs *reg = priv->emc_regs_p; + u32 start, val; + int timeout = CONFIG_MDIO_TIMEOUT; + + val = (addr << 0x08) | regs | PHYBUSY | (MIIDA_MDCCR_60 << 20); + writel(val, ®->miida); + + start = get_timer(0); + while (get_timer(start) < timeout) { + if (!(readl(®->miida) & PHYBUSY)) { + val = readl(®->miid); + return val; + } + udelay(10); + }; + return -ETIMEDOUT; +} + +static int npcm750_mdio_write(struct mii_dev *bus, int addr, int devad, int regs, + u16 val) +{ + struct npcm750_eth_dev *priv = (struct npcm750_eth_dev *)bus->priv; + struct emc_regs *reg = priv->emc_regs_p; + ulong start; + int ret = -ETIMEDOUT, timeout = CONFIG_MDIO_TIMEOUT; + + writel(val, ®->miid); + writel((addr << 0x08) | regs | PHYBUSY | PHYWR | (MIIDA_MDCCR_60 << 20), ®->miida); + + start = get_timer(0); + while (get_timer(start) < timeout) { + if (!(readl(®->miida) & PHYBUSY)) { + ret = 0; + break; + } + udelay(10); + }; + return ret; +} + +static int npcm750_mdio_reset(struct mii_dev *bus) +{ + return 0; +} + +static int npcm750_mdio_init(const char *name, struct npcm750_eth_dev *priv) +{ + struct emc_regs *reg = priv->emc_regs_p; + struct mii_dev *bus = mdio_alloc(); + + if (!bus) { + printf("Failed to allocate MDIO bus\n"); + return -ENOMEM; + } + + bus->read = npcm750_mdio_read; + bus->write = npcm750_mdio_write; + snprintf(bus->name, sizeof(bus->name), "%s", name); + bus->reset = npcm750_mdio_reset; + + bus->priv = (void *)priv; + + writel(readl(®->mcmdr) | MCMDR_ENMDC, ®->mcmdr); + return mdio_register(bus); +} + +static void npcm750_tx_descs_init(struct npcm750_eth_dev *priv) +{ + struct emc_regs *reg = priv->emc_regs_p; + struct npcm750_txbd *desc_table_p = &priv->tdesc[0]; + struct npcm750_txbd *desc_p; + u8 *txbuffs = &priv->txbuffs[0]; + u32 idx; + + writel((u32)desc_table_p, ®->txdlsa); + priv->curr_txd = desc_table_p; + + for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) { + desc_p = &desc_table_p[idx]; + desc_p->buffer = (u32)&txbuffs[idx * PKTSIZE_ALIGN]; + desc_p->sl = 0; + desc_p->mode = 0; + desc_p->mode = TX_OWEN_CPU | PADDINGMODE | CRCMODE | MACTXINTEN; + if (idx < (CONFIG_TX_DESCR_NUM - 1)) + desc_p->next = (u32)&desc_table_p[idx + 1]; + else + desc_p->next = (u32)&priv->tdesc[0]; + } + flush_dcache_range((ulong)&desc_table_p[0], + (ulong)&desc_table_p[CONFIG_TX_DESCR_NUM]); +} + +static void npcm750_rx_descs_init(struct npcm750_eth_dev *priv) +{ + struct emc_regs *reg = priv->emc_regs_p; + struct npcm750_rxbd *desc_table_p = &priv->rdesc[0]; + struct npcm750_rxbd *desc_p; + u8 *rxbuffs = &priv->rxbuffs[0]; + u32 idx; + + flush_dcache_range((ulong)priv->rxbuffs[0], + (ulong)priv->rxbuffs[CONFIG_RX_DESCR_NUM]); + + writel((u32)desc_table_p, ®->rxdlsa); + priv->curr_rxd = desc_table_p; + + for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) { + desc_p = &desc_table_p[idx]; + desc_p->sl = RX_OWEN_DMA; + desc_p->buffer = (u32)&rxbuffs[idx * PKTSIZE_ALIGN]; + if (idx < (CONFIG_RX_DESCR_NUM - 1)) + desc_p->next = (u32)&desc_table_p[idx + 1]; + else + desc_p->next = (u32)&priv->rdesc[0]; + } + flush_dcache_range((ulong)&desc_table_p[0], + (ulong)&desc_table_p[CONFIG_RX_DESCR_NUM]); +} + +static void npcm750_set_fifo_threshold(struct npcm750_eth_dev *priv) +{ + struct emc_regs *reg = priv->emc_regs_p; + unsigned int val; + + val = RXTHD | TXTHD | BLENGTH; + writel(val, ®->fftcr); +} + +static void npcm750_set_global_maccmd(struct npcm750_eth_dev *priv) +{ + struct emc_regs *reg = priv->emc_regs_p; + unsigned int val; + + val = readl(®->mcmdr); + val |= MCMDR_SPCRC | MCMDR_ENMDC | MCMDR_ACP | MCMDR_NDEF; + writel(val, ®->mcmdr); +} + +static void npcm750_set_cam(struct npcm750_eth_dev *priv, + unsigned int x, unsigned char *pval) +{ + struct emc_regs *reg = priv->emc_regs_p; + unsigned int msw, lsw; + + msw = (pval[0] << 24) | (pval[1] << 16) | (pval[2] << 8) | pval[3]; + lsw = (pval[4] << 24) | (pval[5] << 16); + + writel(lsw, ®->cam0l + x * CAM_ENTRY_SIZE); + writel(msw, ®->cam0m + x * CAM_ENTRY_SIZE); + writel(readl(®->camen) | CAM0EN, ®->camen); + writel(CAMCMR_ECMP | CAMCMR_ABP | CAMCMR_AUP, ®->camcmr); +} + +static void npcm750_adjust_link(struct emc_regs *reg, + struct phy_device *phydev) +{ + u32 val = readl(®->mcmdr); + + if (!phydev->link) { + printf("%s: No link.\n", phydev->dev->name); + return; + } + + if (phydev->speed == 100) + val |= MCMDR_OPMOD; + else + val &= ~MCMDR_OPMOD; + + if (phydev->duplex) + val |= MCMDR_FDUP; + else + val &= ~MCMDR_FDUP; + + writel(val, ®->mcmdr); + + debug("Speed: %d, %s duplex%s\n", phydev->speed, + (phydev->duplex) ? "full" : "half", + (phydev->port == PORT_FIBRE) ? ", fiber mode" : ""); +} + +static int npcm750_phy_init(struct npcm750_eth_dev *priv, void *dev) +{ + struct phy_device *phydev; + int ret; + u32 address = 0x0; + + phydev = phy_connect(priv->bus, address, dev, priv->interface); + if (!phydev) + return -ENODEV; + + if (priv->max_speed) { + ret = phy_set_supported(phydev, priv->max_speed); + if (ret) + return ret; + } + phydev->advertising = phydev->supported; + + priv->phydev = phydev; + phy_config(phydev); + return 0; +} + +static int npcm750_eth_start(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct npcm750_eth_dev *priv = dev_get_priv(dev); + struct emc_regs *reg = priv->emc_regs_p; + u8 *enetaddr = pdata->enetaddr; + int ret; + + writel(readl(®->mcmdr) & ~MCMDR_TXON & ~MCMDR_RXON, ®->mcmdr); + + writel(readl(®->mcmdr) | MCMDR_SWR, ®->mcmdr); + do { + ret = readl(®->mcmdr); + } while (ret & MCMDR_SWR); + + npcm750_rx_descs_init(priv); + npcm750_tx_descs_init(priv); + + npcm750_set_cam(priv, priv->idx, enetaddr); + npcm750_set_global_maccmd(priv); + npcm750_set_fifo_threshold(priv); + + /* Start up the PHY */ + ret = phy_startup(priv->phydev); + if (ret) { + printf("Could not initialize PHY\n"); + return ret; + } + + npcm750_adjust_link(reg, priv->phydev); + writel(readl(®->mcmdr) | MCMDR_TXON | MCMDR_RXON, ®->mcmdr); + + return 0; +} + +static int npcm750_eth_send(struct udevice *dev, void *packet, int length) +{ + struct npcm750_eth_dev *priv = dev_get_priv(dev); + struct emc_regs *reg = priv->emc_regs_p; + struct npcm750_txbd *desc_p; + struct npcm750_txbd *next_desc_p; + + desc_p = priv->curr_txd; + + invalidate_dcache_range((ulong)desc_p, (ulong)(desc_p + 1)); + /* Check if the descriptor is owned by CPU */ + if (desc_p->mode & TX_OWEN_DMA) { + next_desc_p = (struct npcm750_txbd *)desc_p->next; + + while ((next_desc_p != desc_p) && (next_desc_p->mode & TX_OWEN_DMA)) + next_desc_p = (struct npcm750_txbd *)next_desc_p->next; + + if (next_desc_p == desc_p) { + struct emc_regs *reg = priv->emc_regs_p; + + writel(0, ®->tsdr); + serial_printf("TX: overflow and exit\n"); + return -EPERM; + } + + desc_p = next_desc_p; + } + + memcpy((void *)desc_p->buffer, packet, length); + flush_dcache_range((ulong)desc_p->buffer, + (ulong)desc_p->buffer + roundup(length, ARCH_DMA_MINALIGN)); + desc_p->sl = 0; + desc_p->sl = length & TX_STAT_TBC; + desc_p->mode = TX_OWEN_DMA | PADDINGMODE | CRCMODE; + flush_dcache_range((ulong)desc_p, (ulong)(desc_p + 1)); + + if (!(readl(®->mcmdr) & MCMDR_TXON)) + writel(readl(®->mcmdr) | MCMDR_TXON, ®->mcmdr); + priv->curr_txd = (struct npcm750_txbd *)priv->curr_txd->next; + + writel(0, ®->tsdr); + return 0; +} + +static int npcm750_eth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct npcm750_eth_dev *priv = dev_get_priv(dev); + struct npcm750_rxbd *desc_p; + struct npcm750_rxbd *next_desc_p; + int length = -1; + + desc_p = priv->curr_rxd; + invalidate_dcache_range((ulong)desc_p, (ulong)(desc_p + 1)); + + if ((desc_p->sl & RX_STAT_OWNER) == RX_OWEN_DMA) { + next_desc_p = (struct npcm750_rxbd *)desc_p->next; + while ((next_desc_p != desc_p) && + ((next_desc_p->sl & RX_STAT_OWNER) == RX_OWEN_CPU)) { + next_desc_p = (struct npcm750_rxbd *)next_desc_p->next; + } + + if (next_desc_p == desc_p) { + struct emc_regs *reg = priv->emc_regs_p; + + writel(0, ®->rsdr); + serial_printf("RX: overflow and exit\n"); + return -EPERM; + } + desc_p = next_desc_p; + } + + /* Check if the descriptor is owned by CPU */ + if ((desc_p->sl & RX_STAT_OWNER) == RX_OWEN_CPU) { + if (desc_p->sl & RX_STAT_RXGD) { + length = desc_p->sl & RX_STAT_RBC; + invalidate_dcache_range((ulong)desc_p->buffer, + (ulong)(desc_p->buffer + roundup(length, + ARCH_DMA_MINALIGN))); + *packetp = (u8 *)(u32)desc_p->buffer; + priv->curr_rxd = desc_p; + } + } + return length; +} + +static int npcm750_eth_free_pkt(struct udevice *dev, uchar *packet, int length) +{ + struct npcm750_eth_dev *priv = dev_get_priv(dev); + struct emc_regs *reg = priv->emc_regs_p; + struct npcm750_rxbd *desc_p = priv->curr_rxd; + + /* + * Make the current descriptor valid again and go to + * the next one + */ + desc_p->sl |= RX_OWEN_DMA; + flush_dcache_range((ulong)desc_p, (ulong)(desc_p + 1)); + priv->curr_rxd = (struct npcm750_rxbd *)priv->curr_rxd->next; + writel(0, ®->rsdr); + + return 0; +} + +static void npcm750_eth_stop(struct udevice *dev) +{ + struct npcm750_eth_dev *priv = dev_get_priv(dev); + struct emc_regs *reg = priv->emc_regs_p; + + writel(readl(®->mcmdr) & ~MCMDR_TXON, ®->mcmdr); + writel(readl(®->mcmdr) & ~MCMDR_RXON, ®->mcmdr); + priv->curr_txd = (struct npcm750_txbd *)readl(®->txdlsa); + priv->curr_rxd = (struct npcm750_rxbd *)readl(®->rxdlsa); + phy_shutdown(priv->phydev); +} + +static int npcm750_eth_write_hwaddr(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct npcm750_eth_dev *priv = dev_get_priv(dev); + + npcm750_set_cam(priv, CAM0, pdata->enetaddr); + return 0; +} + +static int npcm750_eth_bind(struct udevice *dev) +{ + return 0; +} + +static int npcm750_eth_probe(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_plat(dev); + struct npcm750_eth_dev *priv = dev_get_priv(dev); + u32 iobase = pdata->iobase; + int ret; + + memset(priv, 0, sizeof(struct npcm750_eth_dev)); + ret = dev_read_u32(dev, "id", &priv->idx); + if (ret) { + printf("failed to get id\n"); + return -EINVAL; + } + + priv->gcr_regmap = syscon_regmap_lookup_by_phandle(dev, "syscon-gcr"); + if (IS_ERR(priv->gcr_regmap)) + return -EINVAL; + + priv->emc_regs_p = (struct emc_regs *)iobase; + priv->interface = pdata->phy_interface; + priv->max_speed = pdata->max_speed; + + if (priv->idx == 0) { + /* Enable RMII for EMC1 module */ + regmap_update_bits(priv->gcr_regmap, GCR_INTCR, INTCR_R1EN, INTCR_R1EN); + } + + npcm750_mdio_init(dev->name, priv); + priv->bus = miiphy_get_dev_by_name(dev->name); + + ret = npcm750_phy_init(priv, dev); + + return ret; +} + +static int npcm750_eth_remove(struct udevice *dev) +{ + struct npcm750_eth_dev *priv = dev_get_priv(dev); + + free(priv->phydev); + mdio_unregister(priv->bus); + mdio_free(priv->bus); + + return 0; +} + +static const struct eth_ops npcm750_eth_ops = { + .start = npcm750_eth_start, + .send = npcm750_eth_send, + .recv = npcm750_eth_recv, + .free_pkt = npcm750_eth_free_pkt, + .stop = npcm750_eth_stop, + .write_hwaddr = npcm750_eth_write_hwaddr, +}; + +static int npcm750_eth_ofdata_to_platdata(struct udevice *dev) +{ + struct npcm750_eth_pdata *npcm750_pdata = dev_get_plat(dev); + struct eth_pdata *pdata = &npcm750_pdata->eth_pdata; + const char *phy_mode; + const fdt32_t *cell; + int ret = 0; + + pdata->iobase = (phys_addr_t)dev_read_addr_ptr(dev); + + pdata->phy_interface = -1; + phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode", NULL); + if (phy_mode) + pdata->phy_interface = phy_get_interface_by_name(phy_mode); + if (pdata->phy_interface == -1) { + printf("%s: Invalid PHY interface '%s'\n", __func__, phy_mode); + return -EINVAL; + } + + pdata->max_speed = 0; + cell = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "max-speed", NULL); + if (cell) + pdata->max_speed = fdt32_to_cpu(*cell); + + return ret; +} + +static const struct udevice_id npcm750_eth_ids[] = { + { .compatible = "nuvoton,npcm750-emc" }, + { } +}; + +U_BOOT_DRIVER(eth_npcm750) = { + .name = "eth_npcm750", + .id = UCLASS_ETH, + .of_match = npcm750_eth_ids, + .of_to_plat = npcm750_eth_ofdata_to_platdata, + .bind = npcm750_eth_bind, + .probe = npcm750_eth_probe, + .remove = npcm750_eth_remove, + .ops = &npcm750_eth_ops, + .priv_auto = sizeof(struct npcm750_eth_dev), + .plat_auto = sizeof(struct npcm750_eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index a62c695c5c8..212a861596f 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -104,6 +104,88 @@ #define MIIM_88E151x_MODE_SGMII 1 #define MIIM_88E151x_RESET_OFFS 15 +#if IS_ENABLED(CONFIG_DM_ETH) +static int marvell_read_page(struct phy_device *phydev) +{ + return phy_read(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE); +} + +static int marvell_write_page(struct phy_device *phydev, int page) +{ + return phy_write(phydev, MDIO_DEVAD_NONE, MII_MARVELL_PHY_PAGE, page); +} + +/* Set and/or override some configuration registers based on the + * marvell,reg-init property stored in the of_node for the phydev. + * + * marvell,reg-init = <reg-page reg mask value>,...; + * + * There may be one or more sets of <reg-page reg mask value>: + * + * reg-page: which register bank to use. + * reg: the register. + * mask: if non-zero, ANDed with existing register value. + * value: ORed with the masked value and written to the regiser. + * + */ +static int marvell_of_reg_init(struct phy_device *phydev) +{ + const __be32 *prop; + int len, i, saved_page, current_page, ret = 0; + + if (!ofnode_valid(phydev->node)) + return 0; + + prop = ofnode_get_property(phydev->node, "marvell,reg-init", &len); + if (!prop) + return 0; + + saved_page = marvell_read_page(phydev); + if (saved_page < 0) + goto err; + current_page = saved_page; + + len /= sizeof(*prop); + for (i = 0; i < len - 3; i += 4) { + u16 page = be32_to_cpup(prop + i); + u16 reg = be32_to_cpup(prop + i + 1); + u16 mask = be32_to_cpup(prop + i + 2); + u16 val_bits = be32_to_cpup(prop + i + 3); + int val; + + if (page != current_page) { + current_page = page; + ret = marvell_write_page(phydev, page); + if (ret < 0) + goto err; + } + + val = 0; + if (mask) { + val = phy_read(phydev, MDIO_DEVAD_NONE, reg); + if (val < 0) { + ret = val; + goto err; + } + val &= mask; + } + val |= val_bits; + + ret = phy_write(phydev, MDIO_DEVAD_NONE, reg, val); + if (ret < 0) + goto err; + } + +err: + return marvell_write_page(phydev, saved_page); +} +#else +static int marvell_of_reg_init(struct phy_device *phydev) +{ + return 0; +} +#endif /* CONFIG_DM_ETH */ + static int m88e1xxx_phy_extread(struct phy_device *phydev, int addr, int devaddr, int regnum) { @@ -143,6 +225,8 @@ static int m88e1011s_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR, BMCR_RESET); + marvell_of_reg_init(phydev); + genphy_config_aneg(phydev); return 0; @@ -298,6 +382,8 @@ static int m88e1111s_config(struct phy_device *phydev) /* soft reset */ phy_reset(phydev); + marvell_of_reg_init(phydev); + genphy_config_aneg(phydev); genphy_restart_aneg(phydev); @@ -397,6 +483,8 @@ static int m88e151x_config(struct phy_device *phydev) /* soft reset */ phy_reset(phydev); + marvell_of_reg_init(phydev); + genphy_config_aneg(phydev); genphy_restart_aneg(phydev); @@ -417,6 +505,8 @@ static int m88e1118_config(struct phy_device *phydev) /* Change Page Number */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); + marvell_of_reg_init(phydev); + return genphy_config_aneg(phydev); } @@ -439,6 +529,8 @@ static int m88e1121_config(struct phy_device *phydev) { int pg; + marvell_of_reg_init(phydev); + /* Configure the PHY */ genphy_config_aneg(phydev); @@ -479,6 +571,8 @@ static int m88e1145_config(struct phy_device *phydev) MIIM_M88E1145_RGMII_TX_DELAY; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1145_PHY_EXT_CR, reg); + marvell_of_reg_init(phydev); + genphy_config_aneg(phydev); /* soft reset */ @@ -511,6 +605,8 @@ static int m88e1149_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x0); phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); + marvell_of_reg_init(phydev); + genphy_config_aneg(phydev); phy_reset(phydev); @@ -518,6 +614,16 @@ static int m88e1149_config(struct phy_device *phydev) return 0; } +/* Marvell 88E1240 */ +static int m88e1240_config(struct phy_device *phydev) +{ + marvell_of_reg_init(phydev); + + genphy_config_aneg(phydev); + + return 0; +} + /* Marvell 88E1310 */ static int m88e1310_config(struct phy_device *phydev) { @@ -544,6 +650,8 @@ static int m88e1310_config(struct phy_device *phydev) /* Ensure to return to page 0 */ phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1310_PHY_PAGE, 0x0000); + marvell_of_reg_init(phydev); + return genphy_config_aneg(phydev); } @@ -578,6 +686,8 @@ static int m88e1680_config(struct phy_device *phydev) phy_write(phydev, MDIO_DEVAD_NONE, MIIM_88E1118_PHY_PAGE, 0x0000); phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x9140); + marvell_of_reg_init(phydev); + res = genphy_config_aneg(phydev); if (res < 0) return res; @@ -660,6 +770,16 @@ static struct phy_driver M88E1149S_driver = { .shutdown = &genphy_shutdown, }; +static struct phy_driver M88E1240_driver = { + .name = "Marvell 88E1240", + .uid = 0x1410e30, + .mask = 0xffffff0, + .features = PHY_GBIT_FEATURES, + .config = &m88e1240_config, + .startup = &m88e1011s_startup, + .shutdown = &genphy_shutdown, +}; + static struct phy_driver M88E151x_driver = { .name = "Marvell 88E151x", .uid = 0x1410dd0, @@ -702,6 +822,7 @@ int phy_marvell_init(void) phy_register(&M88E1118R_driver); phy_register(&M88E1111S_driver); phy_register(&M88E1011S_driver); + phy_register(&M88E1240_driver); phy_register(&M88E151x_driver); phy_register(&M88E1680_driver); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 1121b99abff..0350afdd1b6 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -984,10 +984,10 @@ struct phy_device *fixed_phy_create(ofnode node) } phydev = phy_device_create(NULL, 0, PHY_FIXED_ID, false); - if (phydev) + if (phydev) { phydev->node = subnode; - - phydev->interface = ofnode_read_phy_mode(node); + phydev->interface = ofnode_read_phy_mode(node); + } return phydev; } @@ -1101,3 +1101,177 @@ int phy_modify(struct phy_device *phydev, int devad, int regnum, u16 mask, return phy_write(phydev, devad, regnum, (ret & ~mask) | set); } + +/** + * phy_read - Convenience function for reading a given PHY register + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to read + * @return: value for success or negative errno for failure + */ +int phy_read(struct phy_device *phydev, int devad, int regnum) +{ + struct mii_dev *bus = phydev->bus; + + if (!bus || !bus->read) { + debug("%s: No bus configured\n", __func__); + return -1; + } + + return bus->read(bus, phydev->addr, devad, regnum); +} + +/** + * phy_write - Convenience function for writing a given PHY register + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to write + * @val: value to write to @regnum + * @return: 0 for success or negative errno for failure + */ +int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val) +{ + struct mii_dev *bus = phydev->bus; + + if (!bus || !bus->write) { + debug("%s: No bus configured\n", __func__); + return -1; + } + + return bus->write(bus, phydev->addr, devad, regnum, val); +} + +/** + * phy_mmd_start_indirect - Convenience function for writing MMD registers + * @phydev: the phy_device struct + * @devad: The MMD to read from + * @regnum: register number to write + * @return: None + */ +void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum) +{ + /* Write the desired MMD Devad */ + phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad); + + /* Write the desired MMD register address */ + phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum); + + /* Select the Function : DATA with no post increment */ + phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, + (devad | MII_MMD_CTRL_NOINCR)); +} + +/** + * phy_read_mmd - Convenience function for reading a register + * from an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * @return: Value for success or negative errno for failure + */ +int phy_read_mmd(struct phy_device *phydev, int devad, int regnum) +{ + struct phy_driver *drv = phydev->drv; + + if (regnum > (u16)~0 || devad > 32) + return -EINVAL; + + /* driver-specific access */ + if (drv->read_mmd) + return drv->read_mmd(phydev, devad, regnum); + + /* direct C45 / C22 access */ + if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES || + devad == MDIO_DEVAD_NONE || !devad) + return phy_read(phydev, devad, regnum); + + /* indirect C22 access */ + phy_mmd_start_indirect(phydev, devad, regnum); + + /* Read the content of the MMD's selected register */ + return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA); +} + +/** + * phy_write_mmd - Convenience function for writing a register + * on an MMD on a given PHY. + * @phydev: The phy_device struct + * @devad: The MMD to read from + * @regnum: The register on the MMD to read + * @val: value to write to @regnum + * @return: 0 for success or negative errno for failure + */ +int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val) +{ + struct phy_driver *drv = phydev->drv; + + if (regnum > (u16)~0 || devad > 32) + return -EINVAL; + + /* driver-specific access */ + if (drv->write_mmd) + return drv->write_mmd(phydev, devad, regnum, val); + + /* direct C45 / C22 access */ + if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES || + devad == MDIO_DEVAD_NONE || !devad) + return phy_write(phydev, devad, regnum, val); + + /* indirect C22 access */ + phy_mmd_start_indirect(phydev, devad, regnum); + + /* Write the data into MMD's selected register */ + return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val); +} + +/** + * phy_set_bits_mmd - Convenience function for setting bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to set + * @return: 0 for success or negative errno for failure + */ +int phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) +{ + int value, ret; + + value = phy_read_mmd(phydev, devad, regnum); + if (value < 0) + return value; + + value |= val; + + ret = phy_write_mmd(phydev, devad, regnum, value); + if (ret < 0) + return ret; + + return 0; +} + +/** + * phy_clear_bits_mmd - Convenience function for clearing bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to clear + * @return: 0 for success or negative errno for failure + */ +int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val) +{ + int value, ret; + + value = phy_read_mmd(phydev, devad, regnum); + if (value < 0) + return value; + + value &= ~val; + + ret = phy_write_mmd(phydev, devad, regnum, value); + if (ret < 0) + return ret; + + return 0; +} diff --git a/drivers/net/sni_ave.c b/drivers/net/sni_ave.c index 58276a40c77..014b070d9e5 100644 --- a/drivers/net/sni_ave.c +++ b/drivers/net/sni_ave.c @@ -483,7 +483,10 @@ static int ave_start(struct udevice *dev) priv->rx_siz = (PKTSIZE_ALIGN - priv->rx_off); val = 0; - if (priv->phy_mode != PHY_INTERFACE_MODE_RGMII) + if (priv->phy_mode != PHY_INTERFACE_MODE_RGMII && + priv->phy_mode != PHY_INTERFACE_MODE_RGMII_ID && + priv->phy_mode != PHY_INTERFACE_MODE_RGMII_RXID && + priv->phy_mode != PHY_INTERFACE_MODE_RGMII_TXID) val |= AVE_CFGR_MII; writel(val, priv->iobase + AVE_CFGR); @@ -639,6 +642,9 @@ static int ave_pro4_get_pinmode(struct ave_private *priv) break; case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: break; default: return -EINVAL; @@ -693,6 +699,9 @@ static int ave_ld20_get_pinmode(struct ave_private *priv) val = SG_ETPINMODE_RMII(0); break; case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: break; default: return -EINVAL; @@ -720,6 +729,9 @@ static int ave_pxs3_get_pinmode(struct ave_private *priv) val = SG_ETPINMODE_RMII(priv->regmap_arg); break; case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: break; default: return -EINVAL; diff --git a/include/configs/imx8mp_evk.h b/include/configs/imx8mp_evk.h index 5581c0fac02..388f3bc9ffe 100644 --- a/include/configs/imx8mp_evk.h +++ b/include/configs/imx8mp_evk.h @@ -24,8 +24,6 @@ #if defined(CONFIG_CMD_NET) #define CONFIG_FEC_MXC_PHYADDR 1 -#define DWC_NET_PHYADDR 1 - #define PHY_ANEG_TIMEOUT 20000 #endif diff --git a/include/configs/imx8mp_rsb3720.h b/include/configs/imx8mp_rsb3720.h index 17e00f958b6..ddc035ae228 100644 --- a/include/configs/imx8mp_rsb3720.h +++ b/include/configs/imx8mp_rsb3720.h @@ -42,7 +42,6 @@ #if defined(CONFIG_CMD_NET) #define CONFIG_FEC_MXC_PHYADDR 4 -#define DWC_NET_PHYADDR 4 #ifdef CONFIG_DWC_ETH_QOS #define CONFIG_SYS_NONCACHED_MEMORY (1 * SZ_1M) /* 1M */ #endif diff --git a/include/configs/imx93_evk.h b/include/configs/imx93_evk.h index 21f85f59b28..f9750da5805 100644 --- a/include/configs/imx93_evk.h +++ b/include/configs/imx93_evk.h @@ -138,7 +138,6 @@ #define WDOG_BASE_ADDR WDG3_BASE_ADDR #if defined(CONFIG_CMD_NET) -#define DWC_NET_PHYADDR 1 #define PHY_ANEG_TIMEOUT 20000 #endif diff --git a/include/net.h b/include/net.h index e3889a0bc85..c06b577808b 100644 --- a/include/net.h +++ b/include/net.h @@ -536,7 +536,9 @@ extern struct in_addr net_dns_server2; #endif extern char net_nis_domain[32]; /* Our IS domain */ extern char net_hostname[32]; /* Our hostname */ -extern char net_root_path[64]; /* Our root path */ +#ifdef CONFIG_NET +extern char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN]; /* Our root path */ +#endif /** END OF BOOTP EXTENTIONS **/ extern u8 net_ethaddr[ARP_HLEN]; /* Our ethernet address */ extern u8 net_server_ethaddr[ARP_HLEN]; /* Boot server enet address */ diff --git a/include/netdev.h b/include/netdev.h index fb18f09893c..b3f8584e900 100644 --- a/include/netdev.h +++ b/include/netdev.h @@ -42,7 +42,6 @@ int eepro100_initialize(struct bd_info *bis); int ep93xx_eth_initialize(u8 dev_num, int base_addr); int eth_3com_initialize (struct bd_info * bis); int ethoc_initialize(u8 dev_num, int base_addr); -int fec_initialize (struct bd_info *bis); int fecmxc_initialize(struct bd_info *bis); int fecmxc_initialize_multi(struct bd_info *bis, int dev_id, int phy_id, uint32_t addr); diff --git a/include/phy.h b/include/phy.h index b3295957106..ad2096ca84f 100644 --- a/include/phy.h +++ b/include/phy.h @@ -177,186 +177,6 @@ struct fixed_link { int asym_pause; }; -/** - * phy_read - Convenience function for reading a given PHY register - * @phydev: the phy_device struct - * @devad: The MMD to read from - * @regnum: register number to read - * @return: value for success or negative errno for failure - */ -static inline int phy_read(struct phy_device *phydev, int devad, int regnum) -{ - struct mii_dev *bus = phydev->bus; - - if (!bus || !bus->read) { - debug("%s: No bus configured\n", __func__); - return -1; - } - - return bus->read(bus, phydev->addr, devad, regnum); -} - -/** - * phy_write - Convenience function for writing a given PHY register - * @phydev: the phy_device struct - * @devad: The MMD to read from - * @regnum: register number to write - * @val: value to write to @regnum - * @return: 0 for success or negative errno for failure - */ -static inline int phy_write(struct phy_device *phydev, int devad, int regnum, - u16 val) -{ - struct mii_dev *bus = phydev->bus; - - if (!bus || !bus->write) { - debug("%s: No bus configured\n", __func__); - return -1; - } - - return bus->write(bus, phydev->addr, devad, regnum, val); -} - -/** - * phy_mmd_start_indirect - Convenience function for writing MMD registers - * @phydev: the phy_device struct - * @devad: The MMD to read from - * @regnum: register number to write - * @return: None - */ -static inline void phy_mmd_start_indirect(struct phy_device *phydev, int devad, - int regnum) -{ - /* Write the desired MMD Devad */ - phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, devad); - - /* Write the desired MMD register address */ - phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, regnum); - - /* Select the Function : DATA with no post increment */ - phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_CTRL, - (devad | MII_MMD_CTRL_NOINCR)); -} - -/** - * phy_read_mmd - Convenience function for reading a register - * from an MMD on a given PHY. - * @phydev: The phy_device struct - * @devad: The MMD to read from - * @regnum: The register on the MMD to read - * @return: Value for success or negative errno for failure - */ -static inline int phy_read_mmd(struct phy_device *phydev, int devad, - int regnum) -{ - struct phy_driver *drv = phydev->drv; - - if (regnum > (u16)~0 || devad > 32) - return -EINVAL; - - /* driver-specific access */ - if (drv->read_mmd) - return drv->read_mmd(phydev, devad, regnum); - - /* direct C45 / C22 access */ - if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES || - devad == MDIO_DEVAD_NONE || !devad) - return phy_read(phydev, devad, regnum); - - /* indirect C22 access */ - phy_mmd_start_indirect(phydev, devad, regnum); - - /* Read the content of the MMD's selected register */ - return phy_read(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA); -} - -/** - * phy_write_mmd - Convenience function for writing a register - * on an MMD on a given PHY. - * @phydev: The phy_device struct - * @devad: The MMD to read from - * @regnum: The register on the MMD to read - * @val: value to write to @regnum - * @return: 0 for success or negative errno for failure - */ -static inline int phy_write_mmd(struct phy_device *phydev, int devad, - int regnum, u16 val) -{ - struct phy_driver *drv = phydev->drv; - - if (regnum > (u16)~0 || devad > 32) - return -EINVAL; - - /* driver-specific access */ - if (drv->write_mmd) - return drv->write_mmd(phydev, devad, regnum, val); - - /* direct C45 / C22 access */ - if ((drv->features & PHY_10G_FEATURES) == PHY_10G_FEATURES || - devad == MDIO_DEVAD_NONE || !devad) - return phy_write(phydev, devad, regnum, val); - - /* indirect C22 access */ - phy_mmd_start_indirect(phydev, devad, regnum); - - /* Write the data into MMD's selected register */ - return phy_write(phydev, MDIO_DEVAD_NONE, MII_MMD_DATA, val); -} - -/** - * phy_set_bits_mmd - Convenience function for setting bits in a register - * on MMD - * @phydev: the phy_device struct - * @devad: the MMD containing register to modify - * @regnum: register number to modify - * @val: bits to set - * @return: 0 for success or negative errno for failure - */ -static inline int phy_set_bits_mmd(struct phy_device *phydev, int devad, - u32 regnum, u16 val) -{ - int value, ret; - - value = phy_read_mmd(phydev, devad, regnum); - if (value < 0) - return value; - - value |= val; - - ret = phy_write_mmd(phydev, devad, regnum, value); - if (ret < 0) - return ret; - - return 0; -} - -/** - * phy_clear_bits_mmd - Convenience function for clearing bits in a register - * on MMD - * @phydev: the phy_device struct - * @devad: the MMD containing register to modify - * @regnum: register number to modify - * @val: bits to clear - * @return: 0 for success or negative errno for failure - */ -static inline int phy_clear_bits_mmd(struct phy_device *phydev, int devad, - u32 regnum, u16 val) -{ - int value, ret; - - value = phy_read_mmd(phydev, devad, regnum); - if (value < 0) - return value; - - value &= ~val; - - ret = phy_write_mmd(phydev, devad, regnum, value); - if (ret < 0) - return ret; - - return 0; -} - #ifdef CONFIG_PHYLIB_10G extern struct phy_driver gen10g_driver; #endif @@ -508,6 +328,15 @@ static inline ofnode phy_get_ofnode(struct phy_device *phydev) return ofnode_null(); } #endif + +int phy_read(struct phy_device *phydev, int devad, int regnum); +int phy_write(struct phy_device *phydev, int devad, int regnum, u16 val); +void phy_mmd_start_indirect(struct phy_device *phydev, int devad, int regnum); +int phy_read_mmd(struct phy_device *phydev, int devad, int regnum); +int phy_write_mmd(struct phy_device *phydev, int devad, int regnum, u16 val); +int phy_set_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); +int phy_clear_bits_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); + int phy_startup(struct phy_device *phydev); int phy_config(struct phy_device *phydev); int phy_shutdown(struct phy_device *phydev); diff --git a/net/Kconfig b/net/Kconfig index 564ea8b2d28..52e261884d1 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -168,6 +168,12 @@ config BOOTP_SERVERIP variable, not the BOOTP server. This affects the operation of both bootp and tftp. +config BOOTP_MAX_ROOT_PATH_LEN + int "Option 17 root path length" + default 64 + help + Select maximal length of option 17 root path. + endif # if NET config SYS_RX_ETH_BUFFER diff --git a/net/bootp.c b/net/bootp.c index a544bfcc234..b260d5d09e6 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -59,7 +59,7 @@ ulong bootp_start; ulong bootp_timeout; char net_nis_domain[32] = {0,}; /* Our NIS domain */ char net_hostname[32] = {0,}; /* Our hostname */ -char net_root_path[64] = {0,}; /* Our bootpath */ +char net_root_path[CONFIG_BOOTP_MAX_ROOT_PATH_LEN] = {0,}; /* Our bootpath */ static ulong time_taken_max; |