blob: 8a1bc46c5ced0f8c284145d18e5803ba201406f6 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dirk Eibachf74a0272014-11-13 19:21:18 +01002/*
3 * (C) Copyright 2014
Mario Sixb4893582018-03-06 08:04:58 +01004 * Dirk Eibach, Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
Dirk Eibachf74a0272014-11-13 19:21:18 +01005 */
6
7#include <common.h>
8
9#include <gdsys_fpga.h>
10#include <miiphy.h>
11
12#include "ihs_mdio.h"
13
14static 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
30static int ihs_mdio_reset(struct mii_dev *bus)
31{
32 ihs_mdio_idle(bus);
33
34 return 0;
35}
36
37static 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
56static 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
70int 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;
Ben Whitten34fd6c92015-12-30 13:05:58 +000082 strcpy(bus->name, info->name);
Dirk Eibachf74a0272014-11-13 19:21:18 +010083
84 bus->priv = info;
85
86 return mdio_register(bus);
87}