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