diff options
Diffstat (limited to 'board/gdsys/common/ihs_mdio.c')
-rw-r--r-- | board/gdsys/common/ihs_mdio.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/board/gdsys/common/ihs_mdio.c b/board/gdsys/common/ihs_mdio.c new file mode 100644 index 0000000..1d6eb7b --- /dev/null +++ b/board/gdsys/common/ihs_mdio.c @@ -0,0 +1,88 @@ +/* + * (C) Copyright 2014 + * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +#include <gdsys_fpga.h> +#include <miiphy.h> + +#include "ihs_mdio.h" + +static int ihs_mdio_idle(struct mii_dev *bus) +{ + struct ihs_mdio_info *info = bus->priv; + u16 val; + unsigned int ctr = 0; + + do { + FPGA_GET_REG(info->fpga, mdio.control, &val); + udelay(100); + if (ctr++ > 10) + return -1; + } while (!(val & (1 << 12))); + + return 0; +} + +static int ihs_mdio_reset(struct mii_dev *bus) +{ + ihs_mdio_idle(bus); + + return 0; +} + +static int ihs_mdio_read(struct mii_dev *bus, int addr, int dev_addr, + int regnum) +{ + struct ihs_mdio_info *info = bus->priv; + u16 val; + + ihs_mdio_idle(bus); + + FPGA_SET_REG(info->fpga, mdio.control, + ((addr & 0x1f) << 5) | (regnum & 0x1f) | (2 << 10)); + + /* wait for rx data available */ + udelay(100); + + FPGA_GET_REG(info->fpga, mdio.rx_data, &val); + + return val; +} + +static int ihs_mdio_write(struct mii_dev *bus, int addr, int dev_addr, + int regnum, u16 value) +{ + struct ihs_mdio_info *info = bus->priv; + + ihs_mdio_idle(bus); + + FPGA_SET_REG(info->fpga, mdio.address_data, value); + FPGA_SET_REG(info->fpga, mdio.control, + ((addr & 0x1f) << 5) | (regnum & 0x1f) | (1 << 10)); + + return 0; +} + +int ihs_mdio_init(struct ihs_mdio_info *info) +{ + struct mii_dev *bus = mdio_alloc(); + + if (!bus) { + printf("Failed to allocate FSL MDIO bus\n"); + return -1; + } + + bus->read = ihs_mdio_read; + bus->write = ihs_mdio_write; + bus->reset = ihs_mdio_reset; + sprintf(bus->name, info->name); + + bus->priv = info; + + return mdio_register(bus); +} |