1 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2 /* Copyright 2019 NXP */
3
4 #include <linux/fsl/enetc_mdio.h>
5 #include <linux/mdio.h>
6 #include <linux/of_mdio.h>
7 #include <linux/iopoll.h>
8 #include <linux/of.h>
9
10 #include "enetc_pf.h"
11
12 #define ENETC_MDIO_CFG 0x0 /* MDIO configuration and status */
13 #define ENETC_MDIO_CTL 0x4 /* MDIO control */
14 #define ENETC_MDIO_DATA 0x8 /* MDIO data */
15 #define ENETC_MDIO_ADDR 0xc /* MDIO address */
16
17 #define MDIO_CFG_CLKDIV(x) ((((x) >> 1) & 0xff) << 8)
18 #define MDIO_CFG_BSY BIT(0)
19 #define MDIO_CFG_RD_ER BIT(1)
20 #define MDIO_CFG_HOLD(x) (((x) << 2) & GENMASK(4, 2))
21 #define MDIO_CFG_ENC45 BIT(6)
22 /* external MDIO only - driven on neg MDC edge */
23 #define MDIO_CFG_NEG BIT(23)
24
25 #define ENETC_EMDIO_CFG \
26 (MDIO_CFG_HOLD(2) | \
27 MDIO_CFG_CLKDIV(258) | \
28 MDIO_CFG_NEG)
29
30 #define MDIO_CTL_DEV_ADDR(x) ((x) & 0x1f)
31 #define MDIO_CTL_PORT_ADDR(x) (((x) & 0x1f) << 5)
32 #define MDIO_CTL_READ BIT(15)
33
enetc_mdio_rd(struct enetc_mdio_priv * mdio_priv,int off)34 static inline u32 enetc_mdio_rd(struct enetc_mdio_priv *mdio_priv, int off)
35 {
36 return enetc_port_rd_mdio(mdio_priv->hw, mdio_priv->mdio_base + off);
37 }
38
enetc_mdio_wr(struct enetc_mdio_priv * mdio_priv,int off,u32 val)39 static inline void enetc_mdio_wr(struct enetc_mdio_priv *mdio_priv, int off,
40 u32 val)
41 {
42 enetc_port_wr_mdio(mdio_priv->hw, mdio_priv->mdio_base + off, val);
43 }
44
enetc_mdio_is_busy(struct enetc_mdio_priv * mdio_priv)45 static bool enetc_mdio_is_busy(struct enetc_mdio_priv *mdio_priv)
46 {
47 return enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_BSY;
48 }
49
enetc_mdio_wait_complete(struct enetc_mdio_priv * mdio_priv)50 static int enetc_mdio_wait_complete(struct enetc_mdio_priv *mdio_priv)
51 {
52 bool is_busy;
53
54 return readx_poll_timeout(enetc_mdio_is_busy, mdio_priv,
55 is_busy, !is_busy, 10, 10 * 1000);
56 }
57
enetc_mdio_write_c22(struct mii_bus * bus,int phy_id,int regnum,u16 value)58 int enetc_mdio_write_c22(struct mii_bus *bus, int phy_id, int regnum,
59 u16 value)
60 {
61 struct enetc_mdio_priv *mdio_priv = bus->priv;
62 u32 mdio_ctl, mdio_cfg;
63 u16 dev_addr;
64 int ret;
65
66 mdio_cfg = ENETC_EMDIO_CFG;
67 dev_addr = regnum & 0x1f;
68 mdio_cfg &= ~MDIO_CFG_ENC45;
69
70 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
71
72 ret = enetc_mdio_wait_complete(mdio_priv);
73 if (ret)
74 return ret;
75
76 /* set port and dev addr */
77 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
78 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
79
80 /* write the value */
81 enetc_mdio_wr(mdio_priv, ENETC_MDIO_DATA, value);
82
83 ret = enetc_mdio_wait_complete(mdio_priv);
84 if (ret)
85 return ret;
86
87 return 0;
88 }
89 EXPORT_SYMBOL_GPL(enetc_mdio_write_c22);
90
enetc_mdio_write_c45(struct mii_bus * bus,int phy_id,int dev_addr,int regnum,u16 value)91 int enetc_mdio_write_c45(struct mii_bus *bus, int phy_id, int dev_addr,
92 int regnum, u16 value)
93 {
94 struct enetc_mdio_priv *mdio_priv = bus->priv;
95 u32 mdio_ctl, mdio_cfg;
96 int ret;
97
98 mdio_cfg = ENETC_EMDIO_CFG;
99 mdio_cfg |= MDIO_CFG_ENC45;
100
101 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
102
103 ret = enetc_mdio_wait_complete(mdio_priv);
104 if (ret)
105 return ret;
106
107 /* set port and dev addr */
108 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
109 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
110
111 /* set the register address */
112 enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
113
114 ret = enetc_mdio_wait_complete(mdio_priv);
115 if (ret)
116 return ret;
117
118 /* write the value */
119 enetc_mdio_wr(mdio_priv, ENETC_MDIO_DATA, value);
120
121 ret = enetc_mdio_wait_complete(mdio_priv);
122 if (ret)
123 return ret;
124
125 return 0;
126 }
127 EXPORT_SYMBOL_GPL(enetc_mdio_write_c45);
128
enetc_mdio_read_c22(struct mii_bus * bus,int phy_id,int regnum)129 int enetc_mdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)
130 {
131 struct enetc_mdio_priv *mdio_priv = bus->priv;
132 u32 mdio_ctl, mdio_cfg;
133 u16 dev_addr, value;
134 int ret;
135
136 mdio_cfg = ENETC_EMDIO_CFG;
137 dev_addr = regnum & 0x1f;
138 mdio_cfg &= ~MDIO_CFG_ENC45;
139
140 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
141
142 ret = enetc_mdio_wait_complete(mdio_priv);
143 if (ret)
144 return ret;
145
146 /* set port and device addr */
147 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
148 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
149
150 /* initiate the read */
151 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
152
153 ret = enetc_mdio_wait_complete(mdio_priv);
154 if (ret)
155 return ret;
156
157 /* return all Fs if nothing was there */
158 if (enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_RD_ER) {
159 dev_dbg(&bus->dev,
160 "Error while reading PHY%d reg at %d.%d\n",
161 phy_id, dev_addr, regnum);
162 return 0xffff;
163 }
164
165 value = enetc_mdio_rd(mdio_priv, ENETC_MDIO_DATA) & 0xffff;
166
167 return value;
168 }
169 EXPORT_SYMBOL_GPL(enetc_mdio_read_c22);
170
enetc_mdio_read_c45(struct mii_bus * bus,int phy_id,int dev_addr,int regnum)171 int enetc_mdio_read_c45(struct mii_bus *bus, int phy_id, int dev_addr,
172 int regnum)
173 {
174 struct enetc_mdio_priv *mdio_priv = bus->priv;
175 u32 mdio_ctl, mdio_cfg;
176 u16 value;
177 int ret;
178
179 mdio_cfg = ENETC_EMDIO_CFG;
180 mdio_cfg |= MDIO_CFG_ENC45;
181
182 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CFG, mdio_cfg);
183
184 ret = enetc_mdio_wait_complete(mdio_priv);
185 if (ret)
186 return ret;
187
188 /* set port and device addr */
189 mdio_ctl = MDIO_CTL_PORT_ADDR(phy_id) | MDIO_CTL_DEV_ADDR(dev_addr);
190 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl);
191
192 /* set the register address */
193 enetc_mdio_wr(mdio_priv, ENETC_MDIO_ADDR, regnum & 0xffff);
194
195 ret = enetc_mdio_wait_complete(mdio_priv);
196 if (ret)
197 return ret;
198
199 /* initiate the read */
200 enetc_mdio_wr(mdio_priv, ENETC_MDIO_CTL, mdio_ctl | MDIO_CTL_READ);
201
202 ret = enetc_mdio_wait_complete(mdio_priv);
203 if (ret)
204 return ret;
205
206 /* return all Fs if nothing was there */
207 if (enetc_mdio_rd(mdio_priv, ENETC_MDIO_CFG) & MDIO_CFG_RD_ER) {
208 dev_dbg(&bus->dev,
209 "Error while reading PHY%d reg at %d.%d\n",
210 phy_id, dev_addr, regnum);
211 return 0xffff;
212 }
213
214 value = enetc_mdio_rd(mdio_priv, ENETC_MDIO_DATA) & 0xffff;
215
216 return value;
217 }
218 EXPORT_SYMBOL_GPL(enetc_mdio_read_c45);
219
enetc_hw_alloc(struct device * dev,void __iomem * port_regs)220 struct enetc_hw *enetc_hw_alloc(struct device *dev, void __iomem *port_regs)
221 {
222 struct enetc_hw *hw;
223
224 hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
225 if (!hw)
226 return ERR_PTR(-ENOMEM);
227
228 hw->port = port_regs;
229
230 return hw;
231 }
232 EXPORT_SYMBOL_GPL(enetc_hw_alloc);
233
234 /* Lock for MDIO access errata on LS1028A */
235 DEFINE_RWLOCK(enetc_mdio_lock);
236 EXPORT_SYMBOL_GPL(enetc_mdio_lock);
237