blob: 1d6eb7bd55f0b92161feab4a31aeae6d0db61b6b [file] [log] [blame]
Dirk Eibach50dcf892014-11-13 19:21:18 +01001/*
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
15static 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
31static int ihs_mdio_reset(struct mii_dev *bus)
32{
33 ihs_mdio_idle(bus);
34
35 return 0;
36}
37
38static 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
57static 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
71int 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}