ihs_mdio: Encapsulate register access
[platform/kernel/u-boot.git] / board / gdsys / common / ihs_mdio.c
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 inline u16 read_control(struct ihs_mdio_info *info)
15 {
16         u16 val;
17
18         FPGA_GET_REG(info->fpga, mdio.control, &val);
19
20         return val;
21 }
22
23 static inline void write_control(struct ihs_mdio_info *info, u16 val)
24 {
25         FPGA_SET_REG(info->fpga, mdio.control, val);
26 }
27
28 static inline void write_addr_data(struct ihs_mdio_info *info, u16 val)
29 {
30         FPGA_SET_REG(info->fpga, mdio.address_data, val);
31 }
32
33 static inline u16 read_rx_data(struct ihs_mdio_info *info)
34 {
35         u16 val;
36
37         FPGA_GET_REG(info->fpga, mdio.rx_data, &val);
38
39         return val;
40 }
41
42 static int ihs_mdio_idle(struct mii_dev *bus)
43 {
44         struct ihs_mdio_info *info = bus->priv;
45         u16 val;
46         unsigned int ctr = 0;
47
48         do {
49                 val = read_control(info);
50                 udelay(100);
51                 if (ctr++ > 10)
52                         return -1;
53         } while (!(val & (1 << 12)));
54
55         return 0;
56 }
57
58 static int ihs_mdio_reset(struct mii_dev *bus)
59 {
60         ihs_mdio_idle(bus);
61
62         return 0;
63 }
64
65 static int ihs_mdio_read(struct mii_dev *bus, int addr, int dev_addr,
66                          int regnum)
67 {
68         struct ihs_mdio_info *info = bus->priv;
69         u16 val;
70
71         ihs_mdio_idle(bus);
72
73         write_control(info,
74                       ((addr & 0x1f) << 5) | (regnum & 0x1f) | (2 << 10));
75
76         /* wait for rx data available */
77         udelay(100);
78
79         val = read_rx_data(info);
80
81         return val;
82 }
83
84 static int ihs_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
85                           int regnum, u16 value)
86 {
87         struct ihs_mdio_info *info = bus->priv;
88
89         ihs_mdio_idle(bus);
90
91         write_addr_data(info, value);
92         write_control(info, ((addr & 0x1f) << 5) | (regnum & 0x1f) | (1 << 10));
93
94         return 0;
95 }
96
97 int ihs_mdio_init(struct ihs_mdio_info *info)
98 {
99         struct mii_dev *bus = mdio_alloc();
100
101         if (!bus) {
102                 printf("Failed to allocate FSL MDIO bus\n");
103                 return -1;
104         }
105
106         bus->read = ihs_mdio_read;
107         bus->write = ihs_mdio_write;
108         bus->reset = ihs_mdio_reset;
109         strcpy(bus->name, info->name);
110
111         bus->priv = info;
112
113         return mdio_register(bus);
114 }