X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Froms%2Fu-boot%2Fdrivers%2Fnet%2Fxilinx_ll_temac_mdio.c;fp=qemu%2Froms%2Fu-boot%2Fdrivers%2Fnet%2Fxilinx_ll_temac_mdio.c;h=b7bab794e5707f8bd897e874ff9cabfd09f45a64;hb=e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb;hp=0000000000000000000000000000000000000000;hpb=9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00;p=kvmfornfv.git diff --git a/qemu/roms/u-boot/drivers/net/xilinx_ll_temac_mdio.c b/qemu/roms/u-boot/drivers/net/xilinx_ll_temac_mdio.c new file mode 100644 index 000000000..b7bab794e --- /dev/null +++ b/qemu/roms/u-boot/drivers/net/xilinx_ll_temac_mdio.c @@ -0,0 +1,177 @@ +/* + * Xilinx xps_ll_temac ethernet driver for u-boot + * + * MDIO bus access + * + * Copyright (C) 2011 - 2012 Stephan Linz + * Copyright (C) 2008 - 2011 Michal Simek + * Copyright (C) 2008 - 2011 PetaLogix + * + * Based on Yoshio Kashiwagi kashiwagi@co-nss.co.jp driver + * Copyright (C) 2008 Nissin Systems Co.,Ltd. + * March 2008 created + * + * CREDITS: tsec driver + * + * SPDX-License-Identifier: GPL-2.0+ + * + * [0]: http://www.xilinx.com/support/documentation + * + * [S]: [0]/ip_documentation/xps_ll_temac.pdf + * [A]: [0]/application_notes/xapp1041.pdf + */ + +#include +#include +#include +#include +#include +#include + +#include "xilinx_ll_temac.h" +#include "xilinx_ll_temac_mdio.h" + +#if !defined(CONFIG_MII) +# error "LL_TEMAC requires MII -- missing CONFIG_MII" +#endif + +#if !defined(CONFIG_PHYLIB) +# error "LL_TEMAC requires PHYLIB -- missing CONFIG_PHYLIB" +#endif + +/* + * Prior to PHY access, the MDIO clock must be setup. This driver will set a + * safe default that should work with PLB bus speeds of up to 150 MHz and keep + * the MDIO clock below 2.5 MHz. If the user wishes faster access to the PHY + * then the clock divisor can be set to a different value by setting the + * correct bus speed value with CONFIG_XILINX_LL_TEMAC_CLK. + */ +#if !defined(CONFIG_XILINX_LL_TEMAC_CLK) +#define MDIO_CLOCK_DIV MC_CLKDIV_10(150000000) +#else +#define MDIO_CLOCK_DIV MC_CLKDIV_25(CONFIG_XILINX_LL_TEMAC_CLK) +#endif + +static int ll_temac_mdio_setup(struct mii_dev *bus) +{ + struct temac_reg *regs = (struct temac_reg *)bus->priv; + + /* setup MDIO clock */ + ll_temac_indirect_set(regs, TEMAC_MC, + MC_MDIOEN | (MDIO_CLOCK_DIV & MC_CLKDIV_MASK)); + + return 0; +} + +/* + * Indirect MII PHY read via ll_temac. + * + * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf + * page 67, Using the MII Management to Access PHY Registers + */ +int ll_temac_local_mdio_read(struct temac_reg *regs, int addr, int devad, + int regnum) +{ + out_be32(®s->lsw, + ((addr << LSW_PHYAD_POS) & LSW_PHYAD_MASK) | + (regnum & LSW_REGAD_MASK)); + out_be32(®s->ctl, TEMAC_MIIMAI); + + ll_temac_check_status(regs, RSE_MIIM_RR); + + return in_be32(®s->lsw) & LSW_REGDAT_MASK; +} + +/* + * Indirect MII PHY write via ll_temac. + * + * http://www.xilinx.com/support/documentation/ip_documentation/xps_ll_temac.pdf + * page 67, Using the MII Management to Access PHY Registers + */ +void ll_temac_local_mdio_write(struct temac_reg *regs, int addr, int devad, + int regnum, u16 value) +{ + out_be32(®s->lsw, (value & LSW_REGDAT_MASK)); + out_be32(®s->ctl, CTL_WEN | TEMAC_MIIMWD); + + out_be32(®s->lsw, + ((addr << LSW_PHYAD_POS) & LSW_PHYAD_MASK) | + (regnum & LSW_REGAD_MASK)); + out_be32(®s->ctl, CTL_WEN | TEMAC_MIIMAI); + + ll_temac_check_status(regs, RSE_MIIM_WR); +} + +int ll_temac_phy_read(struct mii_dev *bus, int addr, int devad, int regnum) +{ + struct temac_reg *regs = (struct temac_reg *)bus->priv; + + return ll_temac_local_mdio_read(regs, addr, devad, regnum); +} + +int ll_temac_phy_write(struct mii_dev *bus, int addr, int devad, int regnum, + u16 value) +{ + struct temac_reg *regs = (struct temac_reg *)bus->priv; + + ll_temac_local_mdio_write(regs, addr, devad, regnum, value); + + return 0; +} + +/* + * Use MII register 1 (MII status register) to detect PHY + * + * A Mask used to verify certain PHY features (register content) + * in the PHY detection register: + * Auto-negotiation support, 10Mbps half/full duplex support + */ +#define PHY_DETECT_REG MII_BMSR +#define PHY_DETECT_MASK (BMSR_10FULL | BMSR_10HALF | BMSR_ANEGCAPABLE) + +/* Looking for a valid PHY address */ +int ll_temac_phy_addr(struct mii_dev *bus) +{ + struct temac_reg *regs = (struct temac_reg *)bus->priv; + unsigned short val; + unsigned int phy; + + for (phy = PHY_MAX_ADDR; phy >= 0; phy--) { + val = ll_temac_local_mdio_read(regs, phy, 0, PHY_DETECT_REG); + if ((val != 0xFFFF) && + ((val & PHY_DETECT_MASK) == PHY_DETECT_MASK)) { + /* Found a valid PHY address */ + return phy; + } + } + + return -1; +} + +int xilinx_ll_temac_mdio_initialize(bd_t *bis, struct ll_temac_mdio_info *info) +{ + struct mii_dev *bus = mdio_alloc(); + + if (!bus) { + printf("Failed to allocate LL_TEMAC MDIO bus: %s\n", + info->name); + return -1; + } + + bus->read = ll_temac_phy_read; + bus->write = ll_temac_phy_write; + bus->reset = NULL; + + /* use given name or generate its own unique name */ + if (info->name) { + strncpy(bus->name, info->name, MDIO_NAME_LEN); + } else { + snprintf(bus->name, MDIO_NAME_LEN, "lltemii.%p", info->regs); + info->name = bus->name; + } + + bus->priv = info->regs; + + ll_temac_mdio_setup(bus); + return mdio_register(bus); +}