| /* |
| * (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); |
| } |