xref: /linux/drivers/net/phy/bcm54140.c (revision 1a9239bb4253f9076b5b4b2a1a4e8d7defd77a95)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Broadcom BCM54140 Quad SGMII/QSGMII Copper/Fiber Gigabit PHY
3  *
4  * Copyright (c) 2020 Michael Walle <michael@walle.cc>
5  */
6 
7 #include <linux/bitfield.h>
8 #include <linux/brcmphy.h>
9 #include <linux/hwmon.h>
10 #include <linux/module.h>
11 #include <linux/phy.h>
12 
13 #include "phylib.h"
14 #include "bcm-phy-lib.h"
15 
16 /* RDB per-port registers
17  */
18 #define BCM54140_RDB_ISR		0x00a	/* interrupt status */
19 #define BCM54140_RDB_IMR		0x00b	/* interrupt mask */
20 #define  BCM54140_RDB_INT_LINK		BIT(1)	/* link status changed */
21 #define  BCM54140_RDB_INT_SPEED		BIT(2)	/* link speed change */
22 #define  BCM54140_RDB_INT_DUPLEX	BIT(3)	/* duplex mode changed */
23 #define BCM54140_RDB_SPARE1		0x012	/* spare control 1 */
24 #define  BCM54140_RDB_SPARE1_LSLM	BIT(2)	/* link speed LED mode */
25 #define BCM54140_RDB_SPARE2		0x014	/* spare control 2 */
26 #define  BCM54140_RDB_SPARE2_WS_RTRY_DIS BIT(8) /* wirespeed retry disable */
27 #define  BCM54140_RDB_SPARE2_WS_RTRY_LIMIT GENMASK(4, 2) /* retry limit */
28 #define BCM54140_RDB_SPARE3		0x015	/* spare control 3 */
29 #define  BCM54140_RDB_SPARE3_BIT0	BIT(0)
30 #define BCM54140_RDB_LED_CTRL		0x019	/* LED control */
31 #define  BCM54140_RDB_LED_CTRL_ACTLINK0	BIT(4)
32 #define  BCM54140_RDB_LED_CTRL_ACTLINK1	BIT(8)
33 #define BCM54140_RDB_C_APWR		0x01a	/* auto power down control */
34 #define  BCM54140_RDB_C_APWR_SINGLE_PULSE	BIT(8)	/* single pulse */
35 #define  BCM54140_RDB_C_APWR_APD_MODE_DIS	0 /* ADP disable */
36 #define  BCM54140_RDB_C_APWR_APD_MODE_EN	1 /* ADP enable */
37 #define  BCM54140_RDB_C_APWR_APD_MODE_DIS2	2 /* ADP disable */
38 #define  BCM54140_RDB_C_APWR_APD_MODE_EN_ANEG	3 /* ADP enable w/ aneg */
39 #define  BCM54140_RDB_C_APWR_APD_MODE_MASK	GENMASK(6, 5)
40 #define  BCM54140_RDB_C_APWR_SLP_TIM_MASK BIT(4)/* sleep timer */
41 #define  BCM54140_RDB_C_APWR_SLP_TIM_2_7 0	/* 2.7s */
42 #define  BCM54140_RDB_C_APWR_SLP_TIM_5_4 1	/* 5.4s */
43 #define BCM54140_RDB_C_PWR		0x02a	/* copper power control */
44 #define  BCM54140_RDB_C_PWR_ISOLATE	BIT(5)	/* super isolate mode */
45 #define BCM54140_RDB_C_MISC_CTRL	0x02f	/* misc copper control */
46 #define  BCM54140_RDB_C_MISC_CTRL_WS_EN BIT(4)	/* wirespeed enable */
47 
48 /* RDB global registers
49  */
50 #define BCM54140_RDB_TOP_IMR		0x82d	/* interrupt mask */
51 #define  BCM54140_RDB_TOP_IMR_PORT0	BIT(4)
52 #define  BCM54140_RDB_TOP_IMR_PORT1	BIT(5)
53 #define  BCM54140_RDB_TOP_IMR_PORT2	BIT(6)
54 #define  BCM54140_RDB_TOP_IMR_PORT3	BIT(7)
55 #define BCM54140_RDB_MON_CTRL		0x831	/* monitor control */
56 #define  BCM54140_RDB_MON_CTRL_V_MODE	BIT(3)	/* voltage mode */
57 #define  BCM54140_RDB_MON_CTRL_SEL_MASK	GENMASK(2, 1)
58 #define  BCM54140_RDB_MON_CTRL_SEL_TEMP	0	/* meassure temperature */
59 #define  BCM54140_RDB_MON_CTRL_SEL_1V0	1	/* meassure AVDDL 1.0V */
60 #define  BCM54140_RDB_MON_CTRL_SEL_3V3	2	/* meassure AVDDH 3.3V */
61 #define  BCM54140_RDB_MON_CTRL_SEL_RR	3	/* meassure all round-robin */
62 #define  BCM54140_RDB_MON_CTRL_PWR_DOWN	BIT(0)	/* power-down monitor */
63 #define BCM54140_RDB_MON_TEMP_VAL	0x832	/* temperature value */
64 #define BCM54140_RDB_MON_TEMP_MAX	0x833	/* temperature high thresh */
65 #define BCM54140_RDB_MON_TEMP_MIN	0x834	/* temperature low thresh */
66 #define  BCM54140_RDB_MON_TEMP_DATA_MASK GENMASK(9, 0)
67 #define BCM54140_RDB_MON_1V0_VAL	0x835	/* AVDDL 1.0V value */
68 #define BCM54140_RDB_MON_1V0_MAX	0x836	/* AVDDL 1.0V high thresh */
69 #define BCM54140_RDB_MON_1V0_MIN	0x837	/* AVDDL 1.0V low thresh */
70 #define  BCM54140_RDB_MON_1V0_DATA_MASK	GENMASK(10, 0)
71 #define BCM54140_RDB_MON_3V3_VAL	0x838	/* AVDDH 3.3V value */
72 #define BCM54140_RDB_MON_3V3_MAX	0x839	/* AVDDH 3.3V high thresh */
73 #define BCM54140_RDB_MON_3V3_MIN	0x83a	/* AVDDH 3.3V low thresh */
74 #define  BCM54140_RDB_MON_3V3_DATA_MASK	GENMASK(11, 0)
75 #define BCM54140_RDB_MON_ISR		0x83b	/* interrupt status */
76 #define  BCM54140_RDB_MON_ISR_3V3	BIT(2)	/* AVDDH 3.3V alarm */
77 #define  BCM54140_RDB_MON_ISR_1V0	BIT(1)	/* AVDDL 1.0V alarm */
78 #define  BCM54140_RDB_MON_ISR_TEMP	BIT(0)	/* temperature alarm */
79 
80 /* According to the datasheet the formula is:
81  *   T = 413.35 - (0.49055 * bits[9:0])
82  */
83 #define BCM54140_HWMON_TO_TEMP(v) (413350L - (v) * 491)
84 #define BCM54140_HWMON_FROM_TEMP(v) DIV_ROUND_CLOSEST_ULL(413350L - (v), 491)
85 
86 /* According to the datasheet the formula is:
87  *   U = bits[11:0] / 1024 * 220 / 0.2
88  *
89  * Normalized:
90  *   U = bits[11:0] / 4096 * 2514
91  */
92 #define BCM54140_HWMON_TO_IN_1V0(v) ((v) * 2514 >> 11)
93 #define BCM54140_HWMON_FROM_IN_1V0(v) DIV_ROUND_CLOSEST_ULL(((v) << 11), 2514)
94 
95 /* According to the datasheet the formula is:
96  *   U = bits[10:0] / 1024 * 880 / 0.7
97  *
98  * Normalized:
99  *   U = bits[10:0] / 2048 * 4400
100  */
101 #define BCM54140_HWMON_TO_IN_3V3(v) ((v) * 4400 >> 12)
102 #define BCM54140_HWMON_FROM_IN_3V3(v) DIV_ROUND_CLOSEST_ULL(((v) << 12), 4400)
103 
104 #define BCM54140_HWMON_TO_IN(ch, v) ((ch) ? BCM54140_HWMON_TO_IN_3V3(v) \
105 					  : BCM54140_HWMON_TO_IN_1V0(v))
106 #define BCM54140_HWMON_FROM_IN(ch, v) ((ch) ? BCM54140_HWMON_FROM_IN_3V3(v) \
107 					    : BCM54140_HWMON_FROM_IN_1V0(v))
108 #define BCM54140_HWMON_IN_MASK(ch) ((ch) ? BCM54140_RDB_MON_3V3_DATA_MASK \
109 					 : BCM54140_RDB_MON_1V0_DATA_MASK)
110 #define BCM54140_HWMON_IN_VAL_REG(ch) ((ch) ? BCM54140_RDB_MON_3V3_VAL \
111 					    : BCM54140_RDB_MON_1V0_VAL)
112 #define BCM54140_HWMON_IN_MIN_REG(ch) ((ch) ? BCM54140_RDB_MON_3V3_MIN \
113 					    : BCM54140_RDB_MON_1V0_MIN)
114 #define BCM54140_HWMON_IN_MAX_REG(ch) ((ch) ? BCM54140_RDB_MON_3V3_MAX \
115 					    : BCM54140_RDB_MON_1V0_MAX)
116 #define BCM54140_HWMON_IN_ALARM_BIT(ch) ((ch) ? BCM54140_RDB_MON_ISR_3V3 \
117 					      : BCM54140_RDB_MON_ISR_1V0)
118 
119 /* This PHY has two different PHY IDs depening on its MODE_SEL pin. This
120  * pin choses between 4x SGMII and QSGMII mode:
121  *   AE02_5009 4x SGMII
122  *   AE02_5019 QSGMII
123  */
124 #define BCM54140_PHY_ID_MASK	0xffffffe8
125 
126 #define BCM54140_PHY_ID_REV(phy_id)	((phy_id) & 0x7)
127 #define BCM54140_REV_B0			1
128 
129 #define BCM54140_DEFAULT_DOWNSHIFT 5
130 #define BCM54140_MAX_DOWNSHIFT 9
131 
132 enum bcm54140_global_phy {
133 	BCM54140_BASE_ADDR = 0,
134 };
135 
136 struct bcm54140_priv {
137 	int port;
138 	int base_addr;
139 #if IS_ENABLED(CONFIG_HWMON)
140 	/* protect the alarm bits */
141 	struct mutex alarm_lock;
142 	u16 alarm;
143 #endif
144 };
145 
146 #if IS_ENABLED(CONFIG_HWMON)
bcm54140_hwmon_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)147 static umode_t bcm54140_hwmon_is_visible(const void *data,
148 					 enum hwmon_sensor_types type,
149 					 u32 attr, int channel)
150 {
151 	switch (type) {
152 	case hwmon_in:
153 		switch (attr) {
154 		case hwmon_in_min:
155 		case hwmon_in_max:
156 			return 0644;
157 		case hwmon_in_label:
158 		case hwmon_in_input:
159 		case hwmon_in_alarm:
160 			return 0444;
161 		default:
162 			return 0;
163 		}
164 	case hwmon_temp:
165 		switch (attr) {
166 		case hwmon_temp_min:
167 		case hwmon_temp_max:
168 			return 0644;
169 		case hwmon_temp_input:
170 		case hwmon_temp_alarm:
171 			return 0444;
172 		default:
173 			return 0;
174 		}
175 	default:
176 		return 0;
177 	}
178 }
179 
bcm54140_hwmon_read_alarm(struct device * dev,unsigned int bit,long * val)180 static int bcm54140_hwmon_read_alarm(struct device *dev, unsigned int bit,
181 				     long *val)
182 {
183 	struct phy_device *phydev = dev_get_drvdata(dev);
184 	struct bcm54140_priv *priv = phydev->priv;
185 	int tmp, ret = 0;
186 
187 	mutex_lock(&priv->alarm_lock);
188 
189 	/* latch any alarm bits */
190 	tmp = bcm_phy_read_rdb(phydev, BCM54140_RDB_MON_ISR);
191 	if (tmp < 0) {
192 		ret = tmp;
193 		goto out;
194 	}
195 	priv->alarm |= tmp;
196 
197 	*val = !!(priv->alarm & bit);
198 	priv->alarm &= ~bit;
199 
200 out:
201 	mutex_unlock(&priv->alarm_lock);
202 	return ret;
203 }
204 
bcm54140_hwmon_read_temp(struct device * dev,u32 attr,long * val)205 static int bcm54140_hwmon_read_temp(struct device *dev, u32 attr, long *val)
206 {
207 	struct phy_device *phydev = dev_get_drvdata(dev);
208 	u16 reg;
209 	int tmp;
210 
211 	switch (attr) {
212 	case hwmon_temp_input:
213 		reg = BCM54140_RDB_MON_TEMP_VAL;
214 		break;
215 	case hwmon_temp_min:
216 		reg = BCM54140_RDB_MON_TEMP_MIN;
217 		break;
218 	case hwmon_temp_max:
219 		reg = BCM54140_RDB_MON_TEMP_MAX;
220 		break;
221 	case hwmon_temp_alarm:
222 		return bcm54140_hwmon_read_alarm(dev,
223 						 BCM54140_RDB_MON_ISR_TEMP,
224 						 val);
225 	default:
226 		return -EOPNOTSUPP;
227 	}
228 
229 	tmp = bcm_phy_read_rdb(phydev, reg);
230 	if (tmp < 0)
231 		return tmp;
232 
233 	*val = BCM54140_HWMON_TO_TEMP(tmp & BCM54140_RDB_MON_TEMP_DATA_MASK);
234 
235 	return 0;
236 }
237 
bcm54140_hwmon_read_in(struct device * dev,u32 attr,int channel,long * val)238 static int bcm54140_hwmon_read_in(struct device *dev, u32 attr,
239 				  int channel, long *val)
240 {
241 	struct phy_device *phydev = dev_get_drvdata(dev);
242 	u16 bit, reg;
243 	int tmp;
244 
245 	switch (attr) {
246 	case hwmon_in_input:
247 		reg = BCM54140_HWMON_IN_VAL_REG(channel);
248 		break;
249 	case hwmon_in_min:
250 		reg = BCM54140_HWMON_IN_MIN_REG(channel);
251 		break;
252 	case hwmon_in_max:
253 		reg = BCM54140_HWMON_IN_MAX_REG(channel);
254 		break;
255 	case hwmon_in_alarm:
256 		bit = BCM54140_HWMON_IN_ALARM_BIT(channel);
257 		return bcm54140_hwmon_read_alarm(dev, bit, val);
258 	default:
259 		return -EOPNOTSUPP;
260 	}
261 
262 	tmp = bcm_phy_read_rdb(phydev, reg);
263 	if (tmp < 0)
264 		return tmp;
265 
266 	tmp &= BCM54140_HWMON_IN_MASK(channel);
267 	*val = BCM54140_HWMON_TO_IN(channel, tmp);
268 
269 	return 0;
270 }
271 
bcm54140_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)272 static int bcm54140_hwmon_read(struct device *dev,
273 			       enum hwmon_sensor_types type, u32 attr,
274 			       int channel, long *val)
275 {
276 	switch (type) {
277 	case hwmon_temp:
278 		return bcm54140_hwmon_read_temp(dev, attr, val);
279 	case hwmon_in:
280 		return bcm54140_hwmon_read_in(dev, attr, channel, val);
281 	default:
282 		return -EOPNOTSUPP;
283 	}
284 }
285 
286 static const char *const bcm54140_hwmon_in_labels[] = {
287 	"AVDDL",
288 	"AVDDH",
289 };
290 
bcm54140_hwmon_read_string(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,const char ** str)291 static int bcm54140_hwmon_read_string(struct device *dev,
292 				      enum hwmon_sensor_types type, u32 attr,
293 				      int channel, const char **str)
294 {
295 	switch (type) {
296 	case hwmon_in:
297 		switch (attr) {
298 		case hwmon_in_label:
299 			*str = bcm54140_hwmon_in_labels[channel];
300 			return 0;
301 		default:
302 			return -EOPNOTSUPP;
303 		}
304 	default:
305 		return -EOPNOTSUPP;
306 	}
307 }
308 
bcm54140_hwmon_write_temp(struct device * dev,u32 attr,int channel,long val)309 static int bcm54140_hwmon_write_temp(struct device *dev, u32 attr,
310 				     int channel, long val)
311 {
312 	struct phy_device *phydev = dev_get_drvdata(dev);
313 	u16 mask = BCM54140_RDB_MON_TEMP_DATA_MASK;
314 	u16 reg;
315 
316 	val = clamp_val(val, BCM54140_HWMON_TO_TEMP(mask),
317 			BCM54140_HWMON_TO_TEMP(0));
318 
319 	switch (attr) {
320 	case hwmon_temp_min:
321 		reg = BCM54140_RDB_MON_TEMP_MIN;
322 		break;
323 	case hwmon_temp_max:
324 		reg = BCM54140_RDB_MON_TEMP_MAX;
325 		break;
326 	default:
327 		return -EOPNOTSUPP;
328 	}
329 
330 	return bcm_phy_modify_rdb(phydev, reg, mask,
331 				  BCM54140_HWMON_FROM_TEMP(val));
332 }
333 
bcm54140_hwmon_write_in(struct device * dev,u32 attr,int channel,long val)334 static int bcm54140_hwmon_write_in(struct device *dev, u32 attr,
335 				   int channel, long val)
336 {
337 	struct phy_device *phydev = dev_get_drvdata(dev);
338 	u16 mask = BCM54140_HWMON_IN_MASK(channel);
339 	u16 reg;
340 
341 	val = clamp_val(val, 0, BCM54140_HWMON_TO_IN(channel, mask));
342 
343 	switch (attr) {
344 	case hwmon_in_min:
345 		reg = BCM54140_HWMON_IN_MIN_REG(channel);
346 		break;
347 	case hwmon_in_max:
348 		reg = BCM54140_HWMON_IN_MAX_REG(channel);
349 		break;
350 	default:
351 		return -EOPNOTSUPP;
352 	}
353 
354 	return bcm_phy_modify_rdb(phydev, reg, mask,
355 				  BCM54140_HWMON_FROM_IN(channel, val));
356 }
357 
bcm54140_hwmon_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)358 static int bcm54140_hwmon_write(struct device *dev,
359 				enum hwmon_sensor_types type, u32 attr,
360 				int channel, long val)
361 {
362 	switch (type) {
363 	case hwmon_temp:
364 		return bcm54140_hwmon_write_temp(dev, attr, channel, val);
365 	case hwmon_in:
366 		return bcm54140_hwmon_write_in(dev, attr, channel, val);
367 	default:
368 		return -EOPNOTSUPP;
369 	}
370 }
371 
372 static const struct hwmon_channel_info * const bcm54140_hwmon_info[] = {
373 	HWMON_CHANNEL_INFO(temp,
374 			   HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
375 			   HWMON_T_ALARM),
376 	HWMON_CHANNEL_INFO(in,
377 			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
378 			   HWMON_I_ALARM | HWMON_I_LABEL,
379 			   HWMON_I_INPUT | HWMON_I_MIN | HWMON_I_MAX |
380 			   HWMON_I_ALARM | HWMON_I_LABEL),
381 	NULL
382 };
383 
384 static const struct hwmon_ops bcm54140_hwmon_ops = {
385 	.is_visible = bcm54140_hwmon_is_visible,
386 	.read = bcm54140_hwmon_read,
387 	.read_string = bcm54140_hwmon_read_string,
388 	.write = bcm54140_hwmon_write,
389 };
390 
391 static const struct hwmon_chip_info bcm54140_chip_info = {
392 	.ops = &bcm54140_hwmon_ops,
393 	.info = bcm54140_hwmon_info,
394 };
395 
bcm54140_enable_monitoring(struct phy_device * phydev)396 static int bcm54140_enable_monitoring(struct phy_device *phydev)
397 {
398 	u16 mask, set;
399 
400 	/* 3.3V voltage mode */
401 	set = BCM54140_RDB_MON_CTRL_V_MODE;
402 
403 	/* select round-robin */
404 	mask = BCM54140_RDB_MON_CTRL_SEL_MASK;
405 	set |= FIELD_PREP(BCM54140_RDB_MON_CTRL_SEL_MASK,
406 			  BCM54140_RDB_MON_CTRL_SEL_RR);
407 
408 	/* remove power-down bit */
409 	mask |= BCM54140_RDB_MON_CTRL_PWR_DOWN;
410 
411 	return bcm_phy_modify_rdb(phydev, BCM54140_RDB_MON_CTRL, mask, set);
412 }
413 
bcm54140_probe_once(struct phy_device * phydev)414 static int bcm54140_probe_once(struct phy_device *phydev)
415 {
416 	struct device *hwmon;
417 	int ret;
418 
419 	/* enable hardware monitoring */
420 	ret = bcm54140_enable_monitoring(phydev);
421 	if (ret)
422 		return ret;
423 
424 	hwmon = devm_hwmon_device_register_with_info(&phydev->mdio.dev,
425 						     "BCM54140", phydev,
426 						     &bcm54140_chip_info,
427 						     NULL);
428 	return PTR_ERR_OR_ZERO(hwmon);
429 }
430 #endif
431 
bcm54140_base_read_rdb(struct phy_device * phydev,u16 rdb)432 static int bcm54140_base_read_rdb(struct phy_device *phydev, u16 rdb)
433 {
434 	int ret;
435 
436 	phy_lock_mdio_bus(phydev);
437 	ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
438 				  MII_BCM54XX_RDB_ADDR, rdb);
439 	if (ret < 0)
440 		goto out;
441 
442 	ret = __phy_package_read(phydev, BCM54140_BASE_ADDR,
443 				 MII_BCM54XX_RDB_DATA);
444 
445 out:
446 	phy_unlock_mdio_bus(phydev);
447 	return ret;
448 }
449 
bcm54140_base_write_rdb(struct phy_device * phydev,u16 rdb,u16 val)450 static int bcm54140_base_write_rdb(struct phy_device *phydev,
451 				   u16 rdb, u16 val)
452 {
453 	int ret;
454 
455 	phy_lock_mdio_bus(phydev);
456 	ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
457 				  MII_BCM54XX_RDB_ADDR, rdb);
458 	if (ret < 0)
459 		goto out;
460 
461 	ret = __phy_package_write(phydev, BCM54140_BASE_ADDR,
462 				  MII_BCM54XX_RDB_DATA, val);
463 
464 out:
465 	phy_unlock_mdio_bus(phydev);
466 	return ret;
467 }
468 
469 /* Under some circumstances a core PLL may not lock, this will then prevent
470  * a successful link establishment. Restart the PLL after the voltages are
471  * stable to workaround this issue.
472  */
bcm54140_b0_workaround(struct phy_device * phydev)473 static int bcm54140_b0_workaround(struct phy_device *phydev)
474 {
475 	int spare3;
476 	int ret;
477 
478 	spare3 = bcm_phy_read_rdb(phydev, BCM54140_RDB_SPARE3);
479 	if (spare3 < 0)
480 		return spare3;
481 
482 	spare3 &= ~BCM54140_RDB_SPARE3_BIT0;
483 
484 	ret = bcm_phy_write_rdb(phydev, BCM54140_RDB_SPARE3, spare3);
485 	if (ret)
486 		return ret;
487 
488 	ret = phy_modify(phydev, MII_BMCR, 0, BMCR_PDOWN);
489 	if (ret)
490 		return ret;
491 
492 	ret = phy_modify(phydev, MII_BMCR, BMCR_PDOWN, 0);
493 	if (ret)
494 		return ret;
495 
496 	spare3 |= BCM54140_RDB_SPARE3_BIT0;
497 
498 	return bcm_phy_write_rdb(phydev, BCM54140_RDB_SPARE3, spare3);
499 }
500 
501 /* The BCM54140 is a quad PHY where only the first port has access to the
502  * global register. Thus we need to find out its PHY address.
503  *
504  */
bcm54140_get_base_addr_and_port(struct phy_device * phydev)505 static int bcm54140_get_base_addr_and_port(struct phy_device *phydev)
506 {
507 	struct bcm54140_priv *priv = phydev->priv;
508 	struct mii_bus *bus = phydev->mdio.bus;
509 	int addr, min_addr, max_addr;
510 	int step = 1;
511 	u32 phy_id;
512 	int tmp;
513 
514 	min_addr = phydev->mdio.addr;
515 	max_addr = phydev->mdio.addr;
516 	addr = phydev->mdio.addr;
517 
518 	/* We scan forward and backwards and look for PHYs which have the
519 	 * same phy_id like we do. Step 1 will scan forward, step 2
520 	 * backwards. Once we are finished, we have a min_addr and
521 	 * max_addr which resembles the range of PHY addresses of the same
522 	 * type of PHY. There is one caveat; there may be many PHYs of
523 	 * the same type, but we know that each PHY takes exactly 4
524 	 * consecutive addresses. Therefore we can deduce our offset
525 	 * to the base address of this quad PHY.
526 	 */
527 
528 	while (1) {
529 		if (step == 3) {
530 			break;
531 		} else if (step == 1) {
532 			max_addr = addr;
533 			addr++;
534 		} else {
535 			min_addr = addr;
536 			addr--;
537 		}
538 
539 		if (addr < 0 || addr >= PHY_MAX_ADDR) {
540 			addr = phydev->mdio.addr;
541 			step++;
542 			continue;
543 		}
544 
545 		/* read the PHY id */
546 		tmp = mdiobus_read(bus, addr, MII_PHYSID1);
547 		if (tmp < 0)
548 			return tmp;
549 		phy_id = tmp << 16;
550 		tmp = mdiobus_read(bus, addr, MII_PHYSID2);
551 		if (tmp < 0)
552 			return tmp;
553 		phy_id |= tmp;
554 
555 		/* see if it is still the same PHY */
556 		if ((phy_id & phydev->drv->phy_id_mask) !=
557 		    (phydev->drv->phy_id & phydev->drv->phy_id_mask)) {
558 			addr = phydev->mdio.addr;
559 			step++;
560 		}
561 	}
562 
563 	/* The range we get should be a multiple of four. Please note that both
564 	 * the min_addr and max_addr are inclusive. So we have to add one if we
565 	 * subtract them.
566 	 */
567 	if ((max_addr - min_addr + 1) % 4) {
568 		dev_err(&phydev->mdio.dev,
569 			"Detected Quad PHY IDs %d..%d doesn't make sense.\n",
570 			min_addr, max_addr);
571 		return -EINVAL;
572 	}
573 
574 	priv->port = (phydev->mdio.addr - min_addr) % 4;
575 	priv->base_addr = phydev->mdio.addr - priv->port;
576 
577 	return 0;
578 }
579 
bcm54140_probe(struct phy_device * phydev)580 static int bcm54140_probe(struct phy_device *phydev)
581 {
582 	struct bcm54140_priv *priv;
583 	int ret;
584 
585 	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
586 	if (!priv)
587 		return -ENOMEM;
588 
589 	phydev->priv = priv;
590 
591 	ret = bcm54140_get_base_addr_and_port(phydev);
592 	if (ret)
593 		return ret;
594 
595 	devm_phy_package_join(&phydev->mdio.dev, phydev, priv->base_addr, 0);
596 
597 #if IS_ENABLED(CONFIG_HWMON)
598 	mutex_init(&priv->alarm_lock);
599 
600 	if (phy_package_init_once(phydev)) {
601 		ret = bcm54140_probe_once(phydev);
602 		if (ret)
603 			return ret;
604 	}
605 #endif
606 
607 	phydev_dbg(phydev, "probed (port %d, base PHY address %d)\n",
608 		   priv->port, priv->base_addr);
609 
610 	return 0;
611 }
612 
bcm54140_config_init(struct phy_device * phydev)613 static int bcm54140_config_init(struct phy_device *phydev)
614 {
615 	u16 reg = 0xffff;
616 	int ret;
617 
618 	/* Apply hardware errata */
619 	if (BCM54140_PHY_ID_REV(phydev->phy_id) == BCM54140_REV_B0) {
620 		ret = bcm54140_b0_workaround(phydev);
621 		if (ret)
622 			return ret;
623 	}
624 
625 	/* Unmask events we are interested in. */
626 	reg &= ~(BCM54140_RDB_INT_DUPLEX |
627 		 BCM54140_RDB_INT_SPEED |
628 		 BCM54140_RDB_INT_LINK);
629 	ret = bcm_phy_write_rdb(phydev, BCM54140_RDB_IMR, reg);
630 	if (ret)
631 		return ret;
632 
633 	/* LED1=LINKSPD[1], LED2=LINKSPD[2], LED3=LINK/ACTIVITY */
634 	ret = bcm_phy_modify_rdb(phydev, BCM54140_RDB_SPARE1,
635 				 0, BCM54140_RDB_SPARE1_LSLM);
636 	if (ret)
637 		return ret;
638 
639 	ret = bcm_phy_modify_rdb(phydev, BCM54140_RDB_LED_CTRL,
640 				 0, BCM54140_RDB_LED_CTRL_ACTLINK0);
641 	if (ret)
642 		return ret;
643 
644 	/* disable super isolate mode */
645 	return bcm_phy_modify_rdb(phydev, BCM54140_RDB_C_PWR,
646 				  BCM54140_RDB_C_PWR_ISOLATE, 0);
647 }
648 
bcm54140_handle_interrupt(struct phy_device * phydev)649 static irqreturn_t bcm54140_handle_interrupt(struct phy_device *phydev)
650 {
651 	int irq_status, irq_mask;
652 
653 	irq_status = bcm_phy_read_rdb(phydev, BCM54140_RDB_ISR);
654 	if (irq_status < 0) {
655 		phy_error(phydev);
656 		return IRQ_NONE;
657 	}
658 
659 	irq_mask = bcm_phy_read_rdb(phydev, BCM54140_RDB_IMR);
660 	if (irq_mask < 0) {
661 		phy_error(phydev);
662 		return IRQ_NONE;
663 	}
664 	irq_mask = ~irq_mask;
665 
666 	if (!(irq_status & irq_mask))
667 		return IRQ_NONE;
668 
669 	phy_trigger_machine(phydev);
670 
671 	return IRQ_HANDLED;
672 }
673 
bcm54140_ack_intr(struct phy_device * phydev)674 static int bcm54140_ack_intr(struct phy_device *phydev)
675 {
676 	int reg;
677 
678 	/* clear pending interrupts */
679 	reg = bcm_phy_read_rdb(phydev, BCM54140_RDB_ISR);
680 	if (reg < 0)
681 		return reg;
682 
683 	return 0;
684 }
685 
bcm54140_config_intr(struct phy_device * phydev)686 static int bcm54140_config_intr(struct phy_device *phydev)
687 {
688 	struct bcm54140_priv *priv = phydev->priv;
689 	static const u16 port_to_imr_bit[] = {
690 		BCM54140_RDB_TOP_IMR_PORT0, BCM54140_RDB_TOP_IMR_PORT1,
691 		BCM54140_RDB_TOP_IMR_PORT2, BCM54140_RDB_TOP_IMR_PORT3,
692 	};
693 	int reg, err;
694 
695 	if (priv->port >= ARRAY_SIZE(port_to_imr_bit))
696 		return -EINVAL;
697 
698 	reg = bcm54140_base_read_rdb(phydev, BCM54140_RDB_TOP_IMR);
699 	if (reg < 0)
700 		return reg;
701 
702 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
703 		err = bcm54140_ack_intr(phydev);
704 		if (err)
705 			return err;
706 
707 		reg &= ~port_to_imr_bit[priv->port];
708 		err = bcm54140_base_write_rdb(phydev, BCM54140_RDB_TOP_IMR, reg);
709 	} else {
710 		reg |= port_to_imr_bit[priv->port];
711 		err = bcm54140_base_write_rdb(phydev, BCM54140_RDB_TOP_IMR, reg);
712 		if (err)
713 			return err;
714 
715 		err = bcm54140_ack_intr(phydev);
716 	}
717 
718 	return err;
719 }
720 
bcm54140_get_downshift(struct phy_device * phydev,u8 * data)721 static int bcm54140_get_downshift(struct phy_device *phydev, u8 *data)
722 {
723 	int val;
724 
725 	val = bcm_phy_read_rdb(phydev, BCM54140_RDB_C_MISC_CTRL);
726 	if (val < 0)
727 		return val;
728 
729 	if (!(val & BCM54140_RDB_C_MISC_CTRL_WS_EN)) {
730 		*data = DOWNSHIFT_DEV_DISABLE;
731 		return 0;
732 	}
733 
734 	val = bcm_phy_read_rdb(phydev, BCM54140_RDB_SPARE2);
735 	if (val < 0)
736 		return val;
737 
738 	if (val & BCM54140_RDB_SPARE2_WS_RTRY_DIS)
739 		*data = 1;
740 	else
741 		*data = FIELD_GET(BCM54140_RDB_SPARE2_WS_RTRY_LIMIT, val) + 2;
742 
743 	return 0;
744 }
745 
bcm54140_set_downshift(struct phy_device * phydev,u8 cnt)746 static int bcm54140_set_downshift(struct phy_device *phydev, u8 cnt)
747 {
748 	u16 mask, set;
749 	int ret;
750 
751 	if (cnt > BCM54140_MAX_DOWNSHIFT && cnt != DOWNSHIFT_DEV_DEFAULT_COUNT)
752 		return -EINVAL;
753 
754 	if (!cnt)
755 		return bcm_phy_modify_rdb(phydev, BCM54140_RDB_C_MISC_CTRL,
756 					  BCM54140_RDB_C_MISC_CTRL_WS_EN, 0);
757 
758 	if (cnt == DOWNSHIFT_DEV_DEFAULT_COUNT)
759 		cnt = BCM54140_DEFAULT_DOWNSHIFT;
760 
761 	if (cnt == 1) {
762 		mask = 0;
763 		set = BCM54140_RDB_SPARE2_WS_RTRY_DIS;
764 	} else {
765 		mask = BCM54140_RDB_SPARE2_WS_RTRY_DIS;
766 		mask |= BCM54140_RDB_SPARE2_WS_RTRY_LIMIT;
767 		set = FIELD_PREP(BCM54140_RDB_SPARE2_WS_RTRY_LIMIT, cnt - 2);
768 	}
769 	ret = bcm_phy_modify_rdb(phydev, BCM54140_RDB_SPARE2,
770 				 mask, set);
771 	if (ret)
772 		return ret;
773 
774 	return bcm_phy_modify_rdb(phydev, BCM54140_RDB_C_MISC_CTRL,
775 				  0, BCM54140_RDB_C_MISC_CTRL_WS_EN);
776 }
777 
bcm54140_get_edpd(struct phy_device * phydev,u16 * tx_interval)778 static int bcm54140_get_edpd(struct phy_device *phydev, u16 *tx_interval)
779 {
780 	int val;
781 
782 	val = bcm_phy_read_rdb(phydev, BCM54140_RDB_C_APWR);
783 	if (val < 0)
784 		return val;
785 
786 	switch (FIELD_GET(BCM54140_RDB_C_APWR_APD_MODE_MASK, val)) {
787 	case BCM54140_RDB_C_APWR_APD_MODE_DIS:
788 	case BCM54140_RDB_C_APWR_APD_MODE_DIS2:
789 		*tx_interval = ETHTOOL_PHY_EDPD_DISABLE;
790 		break;
791 	case BCM54140_RDB_C_APWR_APD_MODE_EN:
792 	case BCM54140_RDB_C_APWR_APD_MODE_EN_ANEG:
793 		switch (FIELD_GET(BCM54140_RDB_C_APWR_SLP_TIM_MASK, val)) {
794 		case BCM54140_RDB_C_APWR_SLP_TIM_2_7:
795 			*tx_interval = 2700;
796 			break;
797 		case BCM54140_RDB_C_APWR_SLP_TIM_5_4:
798 			*tx_interval = 5400;
799 			break;
800 		}
801 	}
802 
803 	return 0;
804 }
805 
bcm54140_set_edpd(struct phy_device * phydev,u16 tx_interval)806 static int bcm54140_set_edpd(struct phy_device *phydev, u16 tx_interval)
807 {
808 	u16 mask, set;
809 
810 	mask = BCM54140_RDB_C_APWR_APD_MODE_MASK;
811 	if (tx_interval == ETHTOOL_PHY_EDPD_DISABLE)
812 		set = FIELD_PREP(BCM54140_RDB_C_APWR_APD_MODE_MASK,
813 				 BCM54140_RDB_C_APWR_APD_MODE_DIS);
814 	else
815 		set = FIELD_PREP(BCM54140_RDB_C_APWR_APD_MODE_MASK,
816 				 BCM54140_RDB_C_APWR_APD_MODE_EN_ANEG);
817 
818 	/* enable single pulse mode */
819 	set |= BCM54140_RDB_C_APWR_SINGLE_PULSE;
820 
821 	/* set sleep timer */
822 	mask |= BCM54140_RDB_C_APWR_SLP_TIM_MASK;
823 	switch (tx_interval) {
824 	case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
825 	case ETHTOOL_PHY_EDPD_DISABLE:
826 	case 2700:
827 		set |= BCM54140_RDB_C_APWR_SLP_TIM_2_7;
828 		break;
829 	case 5400:
830 		set |= BCM54140_RDB_C_APWR_SLP_TIM_5_4;
831 		break;
832 	default:
833 		return -EINVAL;
834 	}
835 
836 	return bcm_phy_modify_rdb(phydev, BCM54140_RDB_C_APWR, mask, set);
837 }
838 
bcm54140_get_tunable(struct phy_device * phydev,struct ethtool_tunable * tuna,void * data)839 static int bcm54140_get_tunable(struct phy_device *phydev,
840 				struct ethtool_tunable *tuna, void *data)
841 {
842 	switch (tuna->id) {
843 	case ETHTOOL_PHY_DOWNSHIFT:
844 		return bcm54140_get_downshift(phydev, data);
845 	case ETHTOOL_PHY_EDPD:
846 		return bcm54140_get_edpd(phydev, data);
847 	default:
848 		return -EOPNOTSUPP;
849 	}
850 }
851 
bcm54140_set_tunable(struct phy_device * phydev,struct ethtool_tunable * tuna,const void * data)852 static int bcm54140_set_tunable(struct phy_device *phydev,
853 				struct ethtool_tunable *tuna, const void *data)
854 {
855 	switch (tuna->id) {
856 	case ETHTOOL_PHY_DOWNSHIFT:
857 		return bcm54140_set_downshift(phydev, *(const u8 *)data);
858 	case ETHTOOL_PHY_EDPD:
859 		return bcm54140_set_edpd(phydev, *(const u16 *)data);
860 	default:
861 		return -EOPNOTSUPP;
862 	}
863 }
864 
865 static struct phy_driver bcm54140_drivers[] = {
866 	{
867 		.phy_id         = PHY_ID_BCM54140,
868 		.phy_id_mask    = BCM54140_PHY_ID_MASK,
869 		.name           = "Broadcom BCM54140",
870 		.flags		= PHY_POLL_CABLE_TEST,
871 		.features       = PHY_GBIT_FEATURES,
872 		.config_init    = bcm54140_config_init,
873 		.handle_interrupt = bcm54140_handle_interrupt,
874 		.config_intr    = bcm54140_config_intr,
875 		.probe		= bcm54140_probe,
876 		.suspend	= genphy_suspend,
877 		.resume		= genphy_resume,
878 		.soft_reset	= genphy_soft_reset,
879 		.get_tunable	= bcm54140_get_tunable,
880 		.set_tunable	= bcm54140_set_tunable,
881 		.cable_test_start = bcm_phy_cable_test_start_rdb,
882 		.cable_test_get_status = bcm_phy_cable_test_get_status_rdb,
883 	},
884 };
885 module_phy_driver(bcm54140_drivers);
886 
887 static const struct mdio_device_id __maybe_unused bcm54140_tbl[] = {
888 	{ PHY_ID_BCM54140, BCM54140_PHY_ID_MASK },
889 	{ }
890 };
891 
892 MODULE_AUTHOR("Michael Walle");
893 MODULE_DESCRIPTION("Broadcom BCM54140 PHY driver");
894 MODULE_DEVICE_TABLE(mdio, bcm54140_tbl);
895 MODULE_LICENSE("GPL");
896