1 /* 2 * (C) Copyright 2014 3 * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 10 #include <gdsys_fpga.h> 11 #include <miiphy.h> 12 13 #include "ihs_mdio.h" 14 15 static int ihs_mdio_idle(struct mii_dev *bus) 16 { 17 struct ihs_mdio_info *info = bus->priv; 18 u16 val; 19 unsigned int ctr = 0; 20 21 do { 22 FPGA_GET_REG(info->fpga, mdio.control, &val); 23 udelay(100); 24 if (ctr++ > 10) 25 return -1; 26 } while (!(val & (1 << 12))); 27 28 return 0; 29 } 30 31 static int ihs_mdio_reset(struct mii_dev *bus) 32 { 33 ihs_mdio_idle(bus); 34 35 return 0; 36 } 37 38 static int ihs_mdio_read(struct mii_dev *bus, int addr, int dev_addr, 39 int regnum) 40 { 41 struct ihs_mdio_info *info = bus->priv; 42 u16 val; 43 44 ihs_mdio_idle(bus); 45 46 FPGA_SET_REG(info->fpga, mdio.control, 47 ((addr & 0x1f) << 5) | (regnum & 0x1f) | (2 << 10)); 48 49 /* wait for rx data available */ 50 udelay(100); 51 52 FPGA_GET_REG(info->fpga, mdio.rx_data, &val); 53 54 return val; 55 } 56 57 static int ihs_mdio_write(struct mii_dev *bus, int addr, int dev_addr, 58 int regnum, u16 value) 59 { 60 struct ihs_mdio_info *info = bus->priv; 61 62 ihs_mdio_idle(bus); 63 64 FPGA_SET_REG(info->fpga, mdio.address_data, value); 65 FPGA_SET_REG(info->fpga, mdio.control, 66 ((addr & 0x1f) << 5) | (regnum & 0x1f) | (1 << 10)); 67 68 return 0; 69 } 70 71 int ihs_mdio_init(struct ihs_mdio_info *info) 72 { 73 struct mii_dev *bus = mdio_alloc(); 74 75 if (!bus) { 76 printf("Failed to allocate FSL MDIO bus\n"); 77 return -1; 78 } 79 80 bus->read = ihs_mdio_read; 81 bus->write = ihs_mdio_write; 82 bus->reset = ihs_mdio_reset; 83 sprintf(bus->name, info->name); 84 85 bus->priv = info; 86 87 return mdio_register(bus); 88 } 89