xref: /linux/drivers/net/ethernet/freescale/enetc/enetc_mdio.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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