common: Drop linux/delay.h from common header
[oweals/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 #include <linux/delay.h>
9
10 #include <miiphy.h>
11 #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
12 #include <gdsys_fpga.h>
13 #else
14 #include <fdtdec.h>
15 #include <dm.h>
16 #include <regmap.h>
17 #endif
18
19 #include "ihs_mdio.h"
20
21 #ifndef CONFIG_GDSYS_LEGACY_DRIVERS
22 enum {
23         REG_MDIO_CONTROL = 0x0,
24         REG_MDIO_ADDR_DATA = 0x2,
25         REG_MDIO_RX_DATA = 0x4,
26 };
27
28 static inline u16 read_reg(struct udevice *fpga, uint base, uint addr)
29 {
30         struct regmap *map;
31         u8 *ptr;
32
33         regmap_init_mem(dev_ofnode(fpga), &map);
34         ptr = regmap_get_range(map, 0);
35
36         return in_le16((u16 *)(ptr + base + addr));
37 }
38
39 static inline void write_reg(struct udevice *fpga, uint base, uint addr,
40                              u16 val)
41 {
42         struct regmap *map;
43         u8 *ptr;
44
45         regmap_init_mem(dev_ofnode(fpga), &map);
46         ptr = regmap_get_range(map, 0);
47
48         out_le16((u16 *)(ptr + base + addr), val);
49 }
50 #endif
51
52 static inline u16 read_control(struct ihs_mdio_info *info)
53 {
54         u16 val;
55 #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
56         FPGA_GET_REG(info->fpga, mdio.control, &val);
57 #else
58         val = read_reg(info->fpga, info->base, REG_MDIO_CONTROL);
59 #endif
60         return val;
61 }
62
63 static inline void write_control(struct ihs_mdio_info *info, u16 val)
64 {
65 #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
66         FPGA_SET_REG(info->fpga, mdio.control, val);
67 #else
68         write_reg(info->fpga, info->base, REG_MDIO_CONTROL, val);
69 #endif
70 }
71
72 static inline void write_addr_data(struct ihs_mdio_info *info, u16 val)
73 {
74 #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
75         FPGA_SET_REG(info->fpga, mdio.address_data, val);
76 #else
77         write_reg(info->fpga, info->base, REG_MDIO_ADDR_DATA, val);
78 #endif
79 }
80
81 static inline u16 read_rx_data(struct ihs_mdio_info *info)
82 {
83         u16 val;
84 #ifdef CONFIG_GDSYS_LEGACY_DRIVERS
85         FPGA_GET_REG(info->fpga, mdio.rx_data, &val);
86 #else
87         val = read_reg(info->fpga, info->base, REG_MDIO_RX_DATA);
88 #endif
89         return val;
90 }
91
92 static int ihs_mdio_idle(struct mii_dev *bus)
93 {
94         struct ihs_mdio_info *info = bus->priv;
95         u16 val;
96         unsigned int ctr = 0;
97
98         do {
99                 val = read_control(info);
100                 udelay(100);
101                 if (ctr++ > 10)
102                         return -1;
103         } while (!(val & (1 << 12)));
104
105         return 0;
106 }
107
108 static int ihs_mdio_reset(struct mii_dev *bus)
109 {
110         ihs_mdio_idle(bus);
111
112         return 0;
113 }
114
115 static int ihs_mdio_read(struct mii_dev *bus, int addr, int dev_addr,
116                          int regnum)
117 {
118         struct ihs_mdio_info *info = bus->priv;
119         u16 val;
120
121         ihs_mdio_idle(bus);
122
123         write_control(info,
124                       ((addr & 0x1f) << 5) | (regnum & 0x1f) | (2 << 10));
125
126         /* wait for rx data available */
127         udelay(100);
128
129         val = read_rx_data(info);
130
131         return val;
132 }
133
134 static int ihs_mdio_write(struct mii_dev *bus, int addr, int dev_addr,
135                           int regnum, u16 value)
136 {
137         struct ihs_mdio_info *info = bus->priv;
138
139         ihs_mdio_idle(bus);
140
141         write_addr_data(info, value);
142         write_control(info, ((addr & 0x1f) << 5) | (regnum & 0x1f) | (1 << 10));
143
144         return 0;
145 }
146
147 int ihs_mdio_init(struct ihs_mdio_info *info)
148 {
149         struct mii_dev *bus = mdio_alloc();
150
151         if (!bus) {
152                 printf("Failed to allocate FSL MDIO bus\n");
153                 return -1;
154         }
155
156         bus->read = ihs_mdio_read;
157         bus->write = ihs_mdio_write;
158         bus->reset = ihs_mdio_reset;
159         strcpy(bus->name, info->name);
160
161         bus->priv = info;
162
163         return mdio_register(bus);
164 }