xref: /linux/drivers/net/phy/qcom/qcom-phy-lib.c (revision 249d2b80e4db0e38503ed0ec2af6c7401bc099b9)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/phy.h>
4 #include <linux/module.h>
5 
6 #include <linux/netdevice.h>
7 #include <linux/etherdevice.h>
8 
9 #include "qcom.h"
10 
11 MODULE_DESCRIPTION("Qualcomm PHY driver Common Functions");
12 MODULE_AUTHOR("Matus Ujhelyi");
13 MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
14 MODULE_LICENSE("GPL");
15 
16 int at803x_debug_reg_read(struct phy_device *phydev, u16 reg)
17 {
18 	int ret;
19 
20 	ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg);
21 	if (ret < 0)
22 		return ret;
23 
24 	return phy_read(phydev, AT803X_DEBUG_DATA);
25 }
26 EXPORT_SYMBOL_GPL(at803x_debug_reg_read);
27 
28 int at803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
29 			  u16 clear, u16 set)
30 {
31 	u16 val;
32 	int ret;
33 
34 	ret = at803x_debug_reg_read(phydev, reg);
35 	if (ret < 0)
36 		return ret;
37 
38 	val = ret & 0xffff;
39 	val &= ~clear;
40 	val |= set;
41 
42 	return phy_write(phydev, AT803X_DEBUG_DATA, val);
43 }
44 EXPORT_SYMBOL_GPL(at803x_debug_reg_mask);
45 
46 int at803x_debug_reg_write(struct phy_device *phydev, u16 reg, u16 data)
47 {
48 	int ret;
49 
50 	ret = phy_write(phydev, AT803X_DEBUG_ADDR, reg);
51 	if (ret < 0)
52 		return ret;
53 
54 	return phy_write(phydev, AT803X_DEBUG_DATA, data);
55 }
56 EXPORT_SYMBOL_GPL(at803x_debug_reg_write);
57 
58 int at803x_set_wol(struct phy_device *phydev,
59 		   struct ethtool_wolinfo *wol)
60 {
61 	int ret, irq_enabled;
62 
63 	if (wol->wolopts & WAKE_MAGIC) {
64 		struct net_device *ndev = phydev->attached_dev;
65 		const u8 *mac;
66 		unsigned int i;
67 		static const unsigned int offsets[] = {
68 			AT803X_LOC_MAC_ADDR_32_47_OFFSET,
69 			AT803X_LOC_MAC_ADDR_16_31_OFFSET,
70 			AT803X_LOC_MAC_ADDR_0_15_OFFSET,
71 		};
72 
73 		if (!ndev)
74 			return -ENODEV;
75 
76 		mac = (const u8 *)ndev->dev_addr;
77 
78 		if (!is_valid_ether_addr(mac))
79 			return -EINVAL;
80 
81 		for (i = 0; i < 3; i++)
82 			phy_write_mmd(phydev, MDIO_MMD_PCS, offsets[i],
83 				      mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
84 
85 		/* Enable WOL interrupt */
86 		ret = phy_modify(phydev, AT803X_INTR_ENABLE, 0, AT803X_INTR_ENABLE_WOL);
87 		if (ret)
88 			return ret;
89 	} else {
90 		/* Disable WOL interrupt */
91 		ret = phy_modify(phydev, AT803X_INTR_ENABLE, AT803X_INTR_ENABLE_WOL, 0);
92 		if (ret)
93 			return ret;
94 	}
95 
96 	/* Clear WOL status */
97 	ret = phy_read(phydev, AT803X_INTR_STATUS);
98 	if (ret < 0)
99 		return ret;
100 
101 	/* Check if there are other interrupts except for WOL triggered when PHY is
102 	 * in interrupt mode, only the interrupts enabled by AT803X_INTR_ENABLE can
103 	 * be passed up to the interrupt PIN.
104 	 */
105 	irq_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
106 	if (irq_enabled < 0)
107 		return irq_enabled;
108 
109 	irq_enabled &= ~AT803X_INTR_ENABLE_WOL;
110 	if (ret & irq_enabled && !phy_polling_mode(phydev))
111 		phy_trigger_machine(phydev);
112 
113 	return 0;
114 }
115 EXPORT_SYMBOL_GPL(at803x_set_wol);
116 
117 void at803x_get_wol(struct phy_device *phydev,
118 		    struct ethtool_wolinfo *wol)
119 {
120 	int value;
121 
122 	wol->supported = WAKE_MAGIC;
123 	wol->wolopts = 0;
124 
125 	value = phy_read(phydev, AT803X_INTR_ENABLE);
126 	if (value < 0)
127 		return;
128 
129 	if (value & AT803X_INTR_ENABLE_WOL)
130 		wol->wolopts |= WAKE_MAGIC;
131 }
132 EXPORT_SYMBOL_GPL(at803x_get_wol);
133 
134 int at803x_ack_interrupt(struct phy_device *phydev)
135 {
136 	int err;
137 
138 	err = phy_read(phydev, AT803X_INTR_STATUS);
139 
140 	return (err < 0) ? err : 0;
141 }
142 EXPORT_SYMBOL_GPL(at803x_ack_interrupt);
143 
144 int at803x_config_intr(struct phy_device *phydev)
145 {
146 	int err;
147 	int value;
148 
149 	value = phy_read(phydev, AT803X_INTR_ENABLE);
150 
151 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
152 		/* Clear any pending interrupts */
153 		err = at803x_ack_interrupt(phydev);
154 		if (err)
155 			return err;
156 
157 		value |= AT803X_INTR_ENABLE_AUTONEG_ERR;
158 		value |= AT803X_INTR_ENABLE_SPEED_CHANGED;
159 		value |= AT803X_INTR_ENABLE_DUPLEX_CHANGED;
160 		value |= AT803X_INTR_ENABLE_LINK_FAIL;
161 		value |= AT803X_INTR_ENABLE_LINK_SUCCESS;
162 
163 		err = phy_write(phydev, AT803X_INTR_ENABLE, value);
164 	} else {
165 		err = phy_write(phydev, AT803X_INTR_ENABLE, 0);
166 		if (err)
167 			return err;
168 
169 		/* Clear any pending interrupts */
170 		err = at803x_ack_interrupt(phydev);
171 	}
172 
173 	return err;
174 }
175 EXPORT_SYMBOL_GPL(at803x_config_intr);
176 
177 irqreturn_t at803x_handle_interrupt(struct phy_device *phydev)
178 {
179 	int irq_status, int_enabled;
180 
181 	irq_status = phy_read(phydev, AT803X_INTR_STATUS);
182 	if (irq_status < 0) {
183 		phy_error(phydev);
184 		return IRQ_NONE;
185 	}
186 
187 	/* Read the current enabled interrupts */
188 	int_enabled = phy_read(phydev, AT803X_INTR_ENABLE);
189 	if (int_enabled < 0) {
190 		phy_error(phydev);
191 		return IRQ_NONE;
192 	}
193 
194 	/* See if this was one of our enabled interrupts */
195 	if (!(irq_status & int_enabled))
196 		return IRQ_NONE;
197 
198 	phy_trigger_machine(phydev);
199 
200 	return IRQ_HANDLED;
201 }
202 EXPORT_SYMBOL_GPL(at803x_handle_interrupt);
203 
204 int at803x_read_specific_status(struct phy_device *phydev,
205 				struct at803x_ss_mask ss_mask)
206 {
207 	int ss;
208 
209 	/* Read the AT8035 PHY-Specific Status register, which indicates the
210 	 * speed and duplex that the PHY is actually using, irrespective of
211 	 * whether we are in autoneg mode or not.
212 	 */
213 	ss = phy_read(phydev, AT803X_SPECIFIC_STATUS);
214 	if (ss < 0)
215 		return ss;
216 
217 	if (ss & AT803X_SS_SPEED_DUPLEX_RESOLVED) {
218 		int sfc, speed;
219 
220 		sfc = phy_read(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL);
221 		if (sfc < 0)
222 			return sfc;
223 
224 		speed = ss & ss_mask.speed_mask;
225 		speed >>= ss_mask.speed_shift;
226 
227 		switch (speed) {
228 		case AT803X_SS_SPEED_10:
229 			phydev->speed = SPEED_10;
230 			break;
231 		case AT803X_SS_SPEED_100:
232 			phydev->speed = SPEED_100;
233 			break;
234 		case AT803X_SS_SPEED_1000:
235 			phydev->speed = SPEED_1000;
236 			break;
237 		case QCA808X_SS_SPEED_2500:
238 			phydev->speed = SPEED_2500;
239 			break;
240 		}
241 		if (ss & AT803X_SS_DUPLEX)
242 			phydev->duplex = DUPLEX_FULL;
243 		else
244 			phydev->duplex = DUPLEX_HALF;
245 
246 		if (ss & AT803X_SS_MDIX)
247 			phydev->mdix = ETH_TP_MDI_X;
248 		else
249 			phydev->mdix = ETH_TP_MDI;
250 
251 		switch (FIELD_GET(AT803X_SFC_MDI_CROSSOVER_MODE_M, sfc)) {
252 		case AT803X_SFC_MANUAL_MDI:
253 			phydev->mdix_ctrl = ETH_TP_MDI;
254 			break;
255 		case AT803X_SFC_MANUAL_MDIX:
256 			phydev->mdix_ctrl = ETH_TP_MDI_X;
257 			break;
258 		case AT803X_SFC_AUTOMATIC_CROSSOVER:
259 			phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
260 			break;
261 		}
262 	}
263 
264 	return 0;
265 }
266 EXPORT_SYMBOL_GPL(at803x_read_specific_status);
267 
268 int at803x_config_mdix(struct phy_device *phydev, u8 ctrl)
269 {
270 	u16 val;
271 
272 	switch (ctrl) {
273 	case ETH_TP_MDI:
274 		val = AT803X_SFC_MANUAL_MDI;
275 		break;
276 	case ETH_TP_MDI_X:
277 		val = AT803X_SFC_MANUAL_MDIX;
278 		break;
279 	case ETH_TP_MDI_AUTO:
280 		val = AT803X_SFC_AUTOMATIC_CROSSOVER;
281 		break;
282 	default:
283 		return 0;
284 	}
285 
286 	return phy_modify_changed(phydev, AT803X_SPECIFIC_FUNCTION_CONTROL,
287 			  AT803X_SFC_MDI_CROSSOVER_MODE_M,
288 			  FIELD_PREP(AT803X_SFC_MDI_CROSSOVER_MODE_M, val));
289 }
290 EXPORT_SYMBOL_GPL(at803x_config_mdix);
291 
292 int at803x_prepare_config_aneg(struct phy_device *phydev)
293 {
294 	int ret;
295 
296 	ret = at803x_config_mdix(phydev, phydev->mdix_ctrl);
297 	if (ret < 0)
298 		return ret;
299 
300 	/* Changes of the midx bits are disruptive to the normal operation;
301 	 * therefore any changes to these registers must be followed by a
302 	 * software reset to take effect.
303 	 */
304 	if (ret == 1) {
305 		ret = genphy_soft_reset(phydev);
306 		if (ret < 0)
307 			return ret;
308 	}
309 
310 	return 0;
311 }
312 EXPORT_SYMBOL_GPL(at803x_prepare_config_aneg);
313 
314 static int at803x_get_downshift(struct phy_device *phydev, u8 *d)
315 {
316 	int val;
317 
318 	val = phy_read(phydev, AT803X_SMART_SPEED);
319 	if (val < 0)
320 		return val;
321 
322 	if (val & AT803X_SMART_SPEED_ENABLE)
323 		*d = FIELD_GET(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, val) + 2;
324 	else
325 		*d = DOWNSHIFT_DEV_DISABLE;
326 
327 	return 0;
328 }
329 
330 static int at803x_set_downshift(struct phy_device *phydev, u8 cnt)
331 {
332 	u16 mask, set;
333 	int ret;
334 
335 	switch (cnt) {
336 	case DOWNSHIFT_DEV_DEFAULT_COUNT:
337 		cnt = AT803X_DEFAULT_DOWNSHIFT;
338 		fallthrough;
339 	case AT803X_MIN_DOWNSHIFT ... AT803X_MAX_DOWNSHIFT:
340 		set = AT803X_SMART_SPEED_ENABLE |
341 		      AT803X_SMART_SPEED_BYPASS_TIMER |
342 		      FIELD_PREP(AT803X_SMART_SPEED_RETRY_LIMIT_MASK, cnt - 2);
343 		mask = AT803X_SMART_SPEED_RETRY_LIMIT_MASK;
344 		break;
345 	case DOWNSHIFT_DEV_DISABLE:
346 		set = 0;
347 		mask = AT803X_SMART_SPEED_ENABLE |
348 		       AT803X_SMART_SPEED_BYPASS_TIMER;
349 		break;
350 	default:
351 		return -EINVAL;
352 	}
353 
354 	ret = phy_modify_changed(phydev, AT803X_SMART_SPEED, mask, set);
355 
356 	/* After changing the smart speed settings, we need to perform a
357 	 * software reset, use phy_init_hw() to make sure we set the
358 	 * reapply any values which might got lost during software reset.
359 	 */
360 	if (ret == 1)
361 		ret = phy_init_hw(phydev);
362 
363 	return ret;
364 }
365 
366 int at803x_get_tunable(struct phy_device *phydev,
367 		       struct ethtool_tunable *tuna, void *data)
368 {
369 	switch (tuna->id) {
370 	case ETHTOOL_PHY_DOWNSHIFT:
371 		return at803x_get_downshift(phydev, data);
372 	default:
373 		return -EOPNOTSUPP;
374 	}
375 }
376 EXPORT_SYMBOL_GPL(at803x_get_tunable);
377 
378 int at803x_set_tunable(struct phy_device *phydev,
379 		       struct ethtool_tunable *tuna, const void *data)
380 {
381 	switch (tuna->id) {
382 	case ETHTOOL_PHY_DOWNSHIFT:
383 		return at803x_set_downshift(phydev, *(const u8 *)data);
384 	default:
385 		return -EOPNOTSUPP;
386 	}
387 }
388 EXPORT_SYMBOL_GPL(at803x_set_tunable);
389 
390 int at803x_cdt_fault_length(int dt)
391 {
392 	/* According to the datasheet the distance to the fault is
393 	 * DELTA_TIME * 0.824 meters.
394 	 *
395 	 * The author suspect the correct formula is:
396 	 *
397 	 *   fault_distance = DELTA_TIME * (c * VF) / 125MHz / 2
398 	 *
399 	 * where c is the speed of light, VF is the velocity factor of
400 	 * the twisted pair cable, 125MHz the counter frequency and
401 	 * we need to divide by 2 because the hardware will measure the
402 	 * round trip time to the fault and back to the PHY.
403 	 *
404 	 * With a VF of 0.69 we get the factor 0.824 mentioned in the
405 	 * datasheet.
406 	 */
407 	return (dt * 824) / 10;
408 }
409 EXPORT_SYMBOL_GPL(at803x_cdt_fault_length);
410 
411 int at803x_cdt_start(struct phy_device *phydev, u32 cdt_start)
412 {
413 	return phy_write(phydev, AT803X_CDT, cdt_start);
414 }
415 EXPORT_SYMBOL_GPL(at803x_cdt_start);
416 
417 int at803x_cdt_wait_for_completion(struct phy_device *phydev,
418 				   u32 cdt_en)
419 {
420 	int val, ret;
421 
422 	/* One test run takes about 25ms */
423 	ret = phy_read_poll_timeout(phydev, AT803X_CDT, val,
424 				    !(val & cdt_en),
425 				    30000, 100000, true);
426 
427 	return ret < 0 ? ret : 0;
428 }
429 EXPORT_SYMBOL_GPL(at803x_cdt_wait_for_completion);
430