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
ihs_mdio_idle(struct mii_dev * bus)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
ihs_mdio_reset(struct mii_dev * bus)31 static int ihs_mdio_reset(struct mii_dev *bus)
32 {
33 ihs_mdio_idle(bus);
34
35 return 0;
36 }
37
ihs_mdio_read(struct mii_dev * bus,int addr,int dev_addr,int regnum)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
ihs_mdio_write(struct mii_dev * bus,int addr,int dev_addr,int regnum,u16 value)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
ihs_mdio_init(struct ihs_mdio_info * info)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 strcpy(bus->name, info->name);
84
85 bus->priv = info;
86
87 return mdio_register(bus);
88 }
89