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/phy/xilinx_gmii2rgmii.c | |
parent | 548aefa5b9e5c31681e0a8bd78e96b66eedd1137 (diff) | |
parent | bcaa0e3302e384ad65c352b385678acdf3f20c0a (diff) |
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/phy/xilinx_gmii2rgmii.c')
-rw-r--r-- | drivers/net/phy/xilinx_gmii2rgmii.c | 144 |
1 files changed, 144 insertions, 0 deletions
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; +} |