diff options
author | Tom Rini <trini@konsulko.com> | 2019-10-09 16:22:03 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2019-10-09 16:22:03 -0400 |
commit | 44fb0d6c9f5147a41c710032869e5e01b3c9e310 (patch) | |
tree | f0c7932d0a8a688095e95f7d1de17be4f7d3af0b /drivers/net | |
parent | 548aefa5b9e5c31681e0a8bd78e96b66eedd1137 (diff) | |
parent | bcaa0e3302e384ad65c352b385678acdf3f20c0a (diff) | |
download | u-boot-44fb0d6c9f5147a41c710032869e5e01b3c9e310.tar.gz u-boot-44fb0d6c9f5147a41c710032869e5e01b3c9e310.tar.xz u-boot-44fb0d6c9f5147a41c710032869e5e01b3c9e310.zip |
Merge tag 'xilinx-for-v2020.01' of https://gitlab.denx.de/u-boot/custodians/u-boot-microblaze
Xilinx/FPGA changes for v2020.01
FPGA:
- Enable fpga loading on Versal
- Minor fix
Microblaze:
- Fix LMB configurations to support initrds
- Some other cleanups
Zynq:
- Minor config/dt changes
- Add distro boot support for usb1 and mmc1
- Remove Xilinx private boot commands and use only distro boot
ZynqMP:
- Kconfig cleanups, defconfig updates
- Update some dt files
- Add firmware driver for talking to PMUFW
- Extend distro boot support for jtag
- Add new IDs
- Add system controller configurations
- Convert code to talk firmware via mailbox or SMCs
Versal:
- Add board_late_init()
- Add run time DT memory setup
- Add DFU support
- Extend distro boot support for jtag and dfu
- Add clock driver
- Tune mini configurations
Xilinx:
- Improve documentation (boot scripts, dt binding)
- Enable run time initrd_high calculation
- Define default SYS_PROMPT
- Add zynq/zynqmp virtual defconfig
Drivers:
- Add Xilinx mailbox driver for talking to firmware
- Clean zynq_gem for Versal
- Move ZYNQ_HISPD_BROKEN to Kconfig
- Wire genphy_init() in phy.c
- Add Xilinx gii2rgmii bridge
- Cleanup zynq_sdhci
- dwc3 fix
- zynq_gpio fix
- axi_emac fix
Others:
- apalis-tk1 - clean config file
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/phy/Kconfig | 7 | ||||
-rw-r--r-- | drivers/net/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/phy/phy.c | 49 | ||||
-rw-r--r-- | drivers/net/phy/xilinx_gmii2rgmii.c | 144 | ||||
-rw-r--r-- | drivers/net/xilinx_axi_emac.c | 7 | ||||
-rw-r--r-- | drivers/net/zynq_gem.c | 7 |
6 files changed, 208 insertions, 7 deletions
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 2a3da068c9..30bd8e7653 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -228,6 +228,13 @@ config PHY_VITESSE config PHY_XILINX bool "Xilinx Ethernet PHYs support" +config PHY_XILINX_GMII2RGMII + bool "Xilinx GMII to RGMII Ethernet PHYs support" + help + This adds support for Xilinx GMII to RGMII IP core. This IP acts + as bridge between MAC connected over GMII and external phy that + is connected over RGMII interface. + config PHY_FIXED bool "Fixed-Link PHY" depends on DM_ETH diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 555da83630..76b6197009 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_PHY_SMSC) += smsc.o obj-$(CONFIG_PHY_TERANETICS) += teranetics.o obj-$(CONFIG_PHY_TI) += ti.o obj-$(CONFIG_PHY_XILINX) += xilinx_phy.o +obj-$(CONFIG_PHY_XILINX_GMII2RGMII) += xilinx_gmii2rgmii.o obj-$(CONFIG_PHY_VITESSE) += vitesse.o obj-$(CONFIG_PHY_MSCC) += mscc.o obj-$(CONFIG_PHY_FIXED) += fixed.o diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index ae37dd6c1e..f2d17aa91a 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -458,6 +458,11 @@ static struct phy_driver genphy_driver = { .shutdown = genphy_shutdown, }; +int genphy_init(void) +{ + return phy_register(&genphy_driver); +} + static LIST_HEAD(phy_drivers); int phy_init(void) @@ -540,6 +545,11 @@ int phy_init(void) #ifdef CONFIG_PHY_FIXED phy_fixed_init(); #endif +#ifdef CONFIG_PHY_XILINX_GMII2RGMII + phy_xilinx_gmii2rgmii_init(); +#endif + genphy_init(); + return 0; } @@ -911,6 +921,41 @@ void phy_connect_dev(struct phy_device *phydev, struct eth_device *dev) debug("%s connected to %s\n", dev->name, phydev->drv->name); } +#ifdef CONFIG_PHY_XILINX_GMII2RGMII +#ifdef CONFIG_DM_ETH +static struct phy_device *phy_connect_gmii2rgmii(struct mii_dev *bus, + struct udevice *dev, + phy_interface_t interface) +#else +static struct phy_device *phy_connect_gmii2rgmii(struct mii_dev *bus, + struct eth_device *dev, + phy_interface_t interface) +#endif +{ + struct phy_device *phydev = NULL; + int sn = dev_of_offset(dev); + int off; + + while (sn > 0) { + off = fdt_node_offset_by_compatible(gd->fdt_blob, sn, + "xlnx,gmii-to-rgmii-1.0"); + if (off > 0) { + phydev = phy_device_create(bus, off, + PHY_GMII2RGMII_ID, false, + interface); + break; + } + if (off == -FDT_ERR_NOTFOUND) + sn = fdt_first_subnode(gd->fdt_blob, sn); + else + printf("%s: Error finding compat string:%d\n", + __func__, off); + } + + return phydev; +} +#endif + #ifdef CONFIG_PHY_FIXED #ifdef CONFIG_DM_ETH static struct phy_device *phy_connect_fixed(struct mii_dev *bus, @@ -957,6 +1002,10 @@ struct phy_device *phy_connect(struct mii_dev *bus, int addr, #ifdef CONFIG_PHY_FIXED phydev = phy_connect_fixed(bus, dev, interface); #endif +#ifdef CONFIG_PHY_XILINX_GMII2RGMII + if (!phydev) + phydev = phy_connect_gmii2rgmii(bus, dev, interface); +#endif if (!phydev) phydev = phy_find_by_mask(bus, mask, interface); diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c new file mode 100644 index 0000000000..8c20da2682 --- /dev/null +++ b/drivers/net/phy/xilinx_gmii2rgmii.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx GMII2RGMII phy driver + * + * Copyright (C) 2018 Xilinx, Inc. + */ + +#include <dm.h> +#include <phy.h> +#include <config.h> +#include <common.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define ZYNQ_GMII2RGMII_REG 0x10 +#define ZYNQ_GMII2RGMII_SPEED_MASK (BMCR_SPEED1000 | BMCR_SPEED100) + +static int xilinxgmiitorgmii_config(struct phy_device *phydev) +{ + struct phy_device *ext_phydev = phydev->priv; + + debug("%s\n", __func__); + if (ext_phydev->drv->config) + ext_phydev->drv->config(ext_phydev); + + return 0; +} + +static int xilinxgmiitorgmii_extread(struct phy_device *phydev, int addr, + int devaddr, int regnum) +{ + struct phy_device *ext_phydev = phydev->priv; + + debug("%s\n", __func__); + if (ext_phydev->drv->readext) + ext_phydev->drv->readext(ext_phydev, addr, devaddr, regnum); + + return 0; +} + +static int xilinxgmiitorgmii_extwrite(struct phy_device *phydev, int addr, + int devaddr, int regnum, u16 val) + +{ + struct phy_device *ext_phydev = phydev->priv; + + debug("%s\n", __func__); + if (ext_phydev->drv->writeext) + ext_phydev->drv->writeext(ext_phydev, addr, devaddr, regnum, + val); + + return 0; +} + +static int xilinxgmiitorgmii_startup(struct phy_device *phydev) +{ + u16 val = 0; + struct phy_device *ext_phydev = phydev->priv; + + debug("%s\n", __func__); + ext_phydev->dev = phydev->dev; + if (ext_phydev->drv->startup) + ext_phydev->drv->startup(ext_phydev); + + val = phy_read(phydev, phydev->addr, ZYNQ_GMII2RGMII_REG); + val &= ~ZYNQ_GMII2RGMII_SPEED_MASK; + + if (ext_phydev->speed == SPEED_1000) + val |= BMCR_SPEED1000; + else if (ext_phydev->speed == SPEED_100) + val |= BMCR_SPEED100; + + phy_write(phydev, phydev->addr, ZYNQ_GMII2RGMII_REG, val | + BMCR_FULLDPLX); + + phydev->duplex = ext_phydev->duplex; + phydev->speed = ext_phydev->speed; + phydev->link = ext_phydev->link; + + return 0; +} + +static int xilinxgmiitorgmii_probe(struct phy_device *phydev) +{ + int ofnode = phydev->addr; + u32 phy_of_handle; + int ext_phyaddr = -1; + struct phy_device *ext_phydev; + + debug("%s\n", __func__); + + if (phydev->interface != PHY_INTERFACE_MODE_GMII) { + printf("Incorrect interface type\n"); + return -EINVAL; + } + + /* + * Read the phy address again as the one we read in ethernet driver + * was overwritten for the purpose of storing the ofnode + */ + phydev->addr = fdtdec_get_int(gd->fdt_blob, ofnode, "reg", -1); + phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob, ofnode, + "phy-handle"); + if (phy_of_handle > 0) + ext_phyaddr = fdtdec_get_int(gd->fdt_blob, + phy_of_handle, + "reg", -1); + ext_phydev = phy_find_by_mask(phydev->bus, + 1 << ext_phyaddr, + PHY_INTERFACE_MODE_RGMII); + if (!ext_phydev) { + printf("%s, No external phy device found\n", __func__); + return -EINVAL; + } + + ext_phydev->node = offset_to_ofnode(phy_of_handle); + phydev->priv = ext_phydev; + + debug("%s, gmii2rgmmi:0x%x, extphy:0x%x\n", __func__, phydev->addr, + ext_phyaddr); + + phydev->flags |= PHY_FLAG_BROKEN_RESET; + + return 0; +} + +static struct phy_driver gmii2rgmii_driver = { + .name = "XILINX GMII2RGMII", + .uid = PHY_GMII2RGMII_ID, + .mask = 0xffffffff, + .features = PHY_GBIT_FEATURES, + .probe = xilinxgmiitorgmii_probe, + .config = xilinxgmiitorgmii_config, + .startup = xilinxgmiitorgmii_startup, + .writeext = xilinxgmiitorgmii_extwrite, + .readext = xilinxgmiitorgmii_extread, +}; + +int phy_xilinx_gmii2rgmii_init(void) +{ + phy_register(&gmii2rgmii_driver); + + return 0; +} diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index 26c21c6d70..36d651109c 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -93,6 +93,7 @@ struct axidma_priv { struct phy_device *phydev; struct mii_dev *bus; u8 eth_hasnobuf; + int phy_of_handle; }; /* BD descriptors */ @@ -276,6 +277,8 @@ static int axiemac_phy_init(struct udevice *dev) phydev->supported &= supported; phydev->advertising = phydev->supported; priv->phydev = phydev; + if (priv->phy_of_handle) + priv->phydev->node = offset_to_ofnode(priv->phy_of_handle); phy_config(phydev); return 0; @@ -736,8 +739,10 @@ static int axi_emac_ofdata_to_platdata(struct udevice *dev) priv->phyaddr = -1; offset = fdtdec_lookup_phandle(gd->fdt_blob, node, "phy-handle"); - if (offset > 0) + if (offset > 0) { priv->phyaddr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1); + priv->phy_of_handle = offset; + } phy_mode = fdt_getprop(gd->fdt_blob, node, "phy-mode", NULL); if (phy_mode) diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 033efb8195..a7a6ce987f 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -26,8 +26,6 @@ #include <asm/arch/sys_proto.h> #include <linux/errno.h> -DECLARE_GLOBAL_DATA_PTR; - /* Bit/mask specification */ #define ZYNQ_GEM_PHYMNTNC_OP_MASK 0x40020000 /* operation mask bits */ #define ZYNQ_GEM_PHYMNTNC_OP_R_MASK 0x20000000 /* read operation */ @@ -465,7 +463,6 @@ static int zynq_gem_init(struct udevice *dev) break; } -#if !defined(CONFIG_ARCH_VERSAL) ret = clk_set_rate(&priv->clk, clk_rate); if (IS_ERR_VALUE(ret) && ret != (unsigned long)-ENOSYS) { dev_err(dev, "failed to set tx clock rate\n"); @@ -477,9 +474,6 @@ static int zynq_gem_init(struct udevice *dev) dev_err(dev, "failed to enable tx clock\n"); return ret; } -#else - debug("requested clk_rate %ld\n", clk_rate); -#endif setbits_le32(®s->nwctrl, ZYNQ_GEM_NWCTRL_RXEN_MASK | ZYNQ_GEM_NWCTRL_TXEN_MASK); @@ -753,6 +747,7 @@ static int zynq_gem_ofdata_to_platdata(struct udevice *dev) } static const struct udevice_id zynq_gem_ids[] = { + { .compatible = "cdns,versal-gem" }, { .compatible = "cdns,zynqmp-gem" }, { .compatible = "cdns,zynq-gem" }, { .compatible = "cdns,gem" }, |