xref: /linux/drivers/net/phy/bcm84881.c (revision aec2f682d47c54ef434b2d440992626d80b1ebdc)
1 // SPDX-License-Identifier: GPL-2.0
2 // Broadcom BCM84881 NBASE-T PHY driver, as found on a SFP+ module.
3 // Copyright (C) 2019 Russell King, Deep Blue Solutions Ltd.
4 //
5 // Like the Marvell 88x3310, the Broadcom 84881 changes its host-side
6 // interface according to the operating speed between 10GBASE-R,
7 // 2500BASE-X and SGMII (but unlike the 88x3310, without the control
8 // word).
9 //
10 // This driver only supports those aspects of the PHY that I'm able to
11 // observe and test with the SFP+ module, which is an incomplete subset
12 // of what this PHY is able to support. For example, I only assume it
13 // supports a single lane Serdes connection, but it may be that the PHY
14 // is able to support more than that.
15 #include <linux/delay.h>
16 #include <linux/module.h>
17 #include <linux/phy.h>
18 
19 enum {
20 	MDIO_AN_C22 = 0xffe0,
21 };
22 
23 /* BCM8489x LED controller (BCM84891L datasheet 2.4.1.58). Each pin has
24  * CTL bits in 0xA83B (stride 3: 2-bit CTL + 1-bit OE_N) plus MASK_LOW/
25  * MASK_EXT source selects. LED4 is firmware-controlled; always RMW.
26  */
27 #define BCM8489X_LED_CTL		0xa83b
28 #define BCM8489X_LED_CTL_ON(i)		(0x2 << ((i) * 3))
29 #define BCM8489X_LED_CTL_MASK(i)	(0x3 << ((i) * 3))
30 
31 #define BCM8489X_LED_SRC_RX		BIT(1)
32 #define BCM8489X_LED_SRC_TX		BIT(2)
33 #define BCM8489X_LED_SRC_1000		BIT(3)	/* high only at 1000 */
34 #define BCM8489X_LED_SRC_100_1000	BIT(4)	/* high at 100 and 1000 */
35 #define BCM8489X_LED_SRC_FORCE		BIT(5)	/* always-1 source */
36 #define BCM8489X_LED_SRC_10G		BIT(7)
37 #define BCM8489X_LED_SRCX_2500		BIT(2)
38 #define BCM8489X_LED_SRCX_5000		BIT(3)
39 
40 #define BCM8489X_MAX_LEDS		2
41 
42 static const struct {
43 	u16 mask_low;
44 	u16 mask_ext;
45 } bcm8489x_led_regs[BCM8489X_MAX_LEDS] = {
46 	{ 0xa82c, 0xa8ef },	/* LED1 */
47 	{ 0xa82f, 0xa8f0 },	/* LED2 */
48 };
49 
50 static int bcm84881_wait_init(struct phy_device *phydev)
51 {
52 	int val;
53 
54 	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1,
55 					 val, !(val & MDIO_CTRL1_RESET),
56 					 100000, 2000000, false);
57 }
58 
59 static void bcm84881_fill_possible_interfaces(struct phy_device *phydev)
60 {
61 	unsigned long *possible = phydev->possible_interfaces;
62 
63 	__set_bit(PHY_INTERFACE_MODE_SGMII, possible);
64 	__set_bit(PHY_INTERFACE_MODE_2500BASEX, possible);
65 	__set_bit(PHY_INTERFACE_MODE_10GBASER, possible);
66 }
67 
68 static int bcm84881_config_init(struct phy_device *phydev)
69 {
70 	bcm84881_fill_possible_interfaces(phydev);
71 
72 	switch (phydev->interface) {
73 	case PHY_INTERFACE_MODE_SGMII:
74 	case PHY_INTERFACE_MODE_2500BASEX:
75 	case PHY_INTERFACE_MODE_10GBASER:
76 		break;
77 	default:
78 		return -ENODEV;
79 	}
80 
81 	return 0;
82 }
83 
84 static int bcm8489x_config_init(struct phy_device *phydev)
85 {
86 	__set_bit(PHY_INTERFACE_MODE_USXGMII, phydev->possible_interfaces);
87 
88 	if (phydev->interface != PHY_INTERFACE_MODE_USXGMII)
89 		return -ENODEV;
90 
91 	/* MDIO_CTRL1_LPOWER is set at boot on the tested platform. Does not
92 	 * recur on ifdown/ifup, cable events, or link-partner advertisement
93 	 * changes; clear it once.
94 	 */
95 	return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_CTRL1,
96 				  MDIO_CTRL1_LPOWER);
97 }
98 
99 static int bcm8489x_led_write(struct phy_device *phydev, u8 index,
100 			      u16 low, u16 ext)
101 {
102 	int ret;
103 
104 	ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD,
105 			    bcm8489x_led_regs[index].mask_low, low);
106 	if (ret)
107 		return ret;
108 	ret = phy_write_mmd(phydev, MDIO_MMD_PMAPMD,
109 			    bcm8489x_led_regs[index].mask_ext, ext);
110 	if (ret)
111 		return ret;
112 	return phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, BCM8489X_LED_CTL,
113 			      BCM8489X_LED_CTL_MASK(index),
114 			      (low | ext) ? BCM8489X_LED_CTL_ON(index) : 0);
115 }
116 
117 static int bcm8489x_led_brightness_set(struct phy_device *phydev,
118 				       u8 index, enum led_brightness value)
119 {
120 	if (index >= BCM8489X_MAX_LEDS)
121 		return -EINVAL;
122 
123 	return bcm8489x_led_write(phydev, index,
124 				  value ? BCM8489X_LED_SRC_FORCE : 0, 0);
125 }
126 
127 static const unsigned long bcm8489x_supported_triggers =
128 	BIT(TRIGGER_NETDEV_LINK) |
129 	BIT(TRIGGER_NETDEV_LINK_100) |
130 	BIT(TRIGGER_NETDEV_LINK_1000) |
131 	BIT(TRIGGER_NETDEV_LINK_2500) |
132 	BIT(TRIGGER_NETDEV_LINK_5000) |
133 	BIT(TRIGGER_NETDEV_LINK_10000) |
134 	BIT(TRIGGER_NETDEV_RX) |
135 	BIT(TRIGGER_NETDEV_TX);
136 
137 static int bcm8489x_led_hw_is_supported(struct phy_device *phydev, u8 index,
138 					unsigned long rules)
139 {
140 	if (index >= BCM8489X_MAX_LEDS)
141 		return -EINVAL;
142 
143 	if (rules & ~bcm8489x_supported_triggers)
144 		return -EOPNOTSUPP;
145 
146 	/* Source bit 4 lights at both 100 and 1000; "100 only" isn't
147 	 * representable in hardware. Accept LINK_100 only alongside
148 	 * LINK_1000 or LINK so the offload is precise.
149 	 */
150 	if ((rules & BIT(TRIGGER_NETDEV_LINK_100)) &&
151 	    !(rules & (BIT(TRIGGER_NETDEV_LINK_1000) |
152 		       BIT(TRIGGER_NETDEV_LINK))))
153 		return -EOPNOTSUPP;
154 
155 	return 0;
156 }
157 
158 static int bcm8489x_led_hw_control_set(struct phy_device *phydev, u8 index,
159 				       unsigned long rules)
160 {
161 	u16 low = 0, ext = 0;
162 
163 	if (index >= BCM8489X_MAX_LEDS)
164 		return -EINVAL;
165 
166 	if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
167 		low |= BCM8489X_LED_SRC_100_1000;
168 	if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
169 		low |= BCM8489X_LED_SRC_1000;
170 	if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))
171 		ext |= BCM8489X_LED_SRCX_2500;
172 	if (rules & (BIT(TRIGGER_NETDEV_LINK_5000) | BIT(TRIGGER_NETDEV_LINK)))
173 		ext |= BCM8489X_LED_SRCX_5000;
174 	if (rules & (BIT(TRIGGER_NETDEV_LINK_10000) | BIT(TRIGGER_NETDEV_LINK)))
175 		low |= BCM8489X_LED_SRC_10G;
176 	if (rules & BIT(TRIGGER_NETDEV_RX))
177 		low |= BCM8489X_LED_SRC_RX;
178 	if (rules & BIT(TRIGGER_NETDEV_TX))
179 		low |= BCM8489X_LED_SRC_TX;
180 
181 	return bcm8489x_led_write(phydev, index, low, ext);
182 }
183 
184 static int bcm8489x_led_hw_control_get(struct phy_device *phydev, u8 index,
185 				       unsigned long *rules)
186 {
187 	int low, ext;
188 
189 	if (index >= BCM8489X_MAX_LEDS)
190 		return -EINVAL;
191 
192 	low = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
193 			   bcm8489x_led_regs[index].mask_low);
194 	if (low < 0)
195 		return low;
196 	ext = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
197 			   bcm8489x_led_regs[index].mask_ext);
198 	if (ext < 0)
199 		return ext;
200 
201 	*rules = 0;
202 	if (low & BCM8489X_LED_SRC_100_1000)
203 		*rules |= BIT(TRIGGER_NETDEV_LINK_100);
204 	if (low & BCM8489X_LED_SRC_1000)
205 		*rules |= BIT(TRIGGER_NETDEV_LINK_1000);
206 	if (ext & BCM8489X_LED_SRCX_2500)
207 		*rules |= BIT(TRIGGER_NETDEV_LINK_2500);
208 	if (ext & BCM8489X_LED_SRCX_5000)
209 		*rules |= BIT(TRIGGER_NETDEV_LINK_5000);
210 	if (low & BCM8489X_LED_SRC_10G)
211 		*rules |= BIT(TRIGGER_NETDEV_LINK_10000);
212 	if (low & BCM8489X_LED_SRC_RX)
213 		*rules |= BIT(TRIGGER_NETDEV_RX);
214 	if (low & BCM8489X_LED_SRC_TX)
215 		*rules |= BIT(TRIGGER_NETDEV_TX);
216 
217 	return 0;
218 }
219 
220 static int bcm84881_probe(struct phy_device *phydev)
221 {
222 	/* This driver requires PMAPMD and AN blocks */
223 	const u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
224 
225 	if (!phydev->is_c45 ||
226 	    (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
227 		return -ENODEV;
228 
229 	return 0;
230 }
231 
232 static int bcm84881_get_features(struct phy_device *phydev)
233 {
234 	int ret;
235 
236 	ret = genphy_c45_pma_read_abilities(phydev);
237 	if (ret)
238 		return ret;
239 
240 	/* Although the PHY sets bit 1.11.8, it does not support 10M modes */
241 	linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
242 			   phydev->supported);
243 	linkmode_clear_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
244 			   phydev->supported);
245 
246 	return 0;
247 }
248 
249 static int bcm84881_config_aneg(struct phy_device *phydev)
250 {
251 	bool changed = false;
252 	u32 adv;
253 	int ret;
254 
255 	/* Wait for the PHY to finish initialising, otherwise our
256 	 * advertisement may be overwritten.
257 	 */
258 	ret = bcm84881_wait_init(phydev);
259 	if (ret)
260 		return ret;
261 
262 	/* We don't support manual MDI control */
263 	phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
264 
265 	/* disabled autoneg doesn't seem to work with this PHY */
266 	if (phydev->autoneg == AUTONEG_DISABLE)
267 		return -EINVAL;
268 
269 	ret = genphy_c45_an_config_aneg(phydev);
270 	if (ret < 0)
271 		return ret;
272 	if (ret > 0)
273 		changed = true;
274 
275 	adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
276 	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN,
277 				     MDIO_AN_C22 + MII_CTRL1000,
278 				     ADVERTISE_1000FULL | ADVERTISE_1000HALF,
279 				     adv);
280 	if (ret < 0)
281 		return ret;
282 	if (ret > 0)
283 		changed = true;
284 
285 	return genphy_c45_check_and_restart_aneg(phydev, changed);
286 }
287 
288 static int bcm84881_aneg_done(struct phy_device *phydev)
289 {
290 	int bmsr, val;
291 
292 	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
293 	if (val < 0)
294 		return val;
295 
296 	bmsr = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_C22 + MII_BMSR);
297 	if (bmsr < 0)
298 		return bmsr;
299 
300 	return !!(val & MDIO_AN_STAT1_COMPLETE) &&
301 	       !!(bmsr & BMSR_ANEGCOMPLETE);
302 }
303 
304 static int bcm84881_read_status(struct phy_device *phydev)
305 {
306 	unsigned int mode;
307 	int bmsr, val;
308 
309 	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
310 	if (val < 0)
311 		return val;
312 
313 	if (val & MDIO_AN_CTRL1_RESTART) {
314 		phydev->link = 0;
315 		return 0;
316 	}
317 
318 	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
319 	if (val < 0)
320 		return val;
321 
322 	bmsr = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_C22 + MII_BMSR);
323 	if (bmsr < 0)
324 		return bmsr;
325 
326 	phydev->autoneg_complete = !!(val & MDIO_AN_STAT1_COMPLETE) &&
327 				   !!(bmsr & BMSR_ANEGCOMPLETE);
328 	phydev->link = !!(val & MDIO_STAT1_LSTATUS) &&
329 		       !!(bmsr & BMSR_LSTATUS);
330 	if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete)
331 		phydev->link = false;
332 
333 	linkmode_zero(phydev->lp_advertising);
334 	phydev->speed = SPEED_UNKNOWN;
335 	phydev->duplex = DUPLEX_UNKNOWN;
336 	phydev->pause = 0;
337 	phydev->asym_pause = 0;
338 	phydev->mdix = 0;
339 
340 	if (!phydev->link)
341 		return 0;
342 
343 	if (phydev->autoneg_complete) {
344 		val = genphy_c45_read_lpa(phydev);
345 		if (val < 0)
346 			return val;
347 
348 		val = phy_read_mmd(phydev, MDIO_MMD_AN,
349 				   MDIO_AN_C22 + MII_STAT1000);
350 		if (val < 0)
351 			return val;
352 
353 		mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
354 
355 		if (phydev->autoneg == AUTONEG_ENABLE)
356 			phy_resolve_aneg_linkmode(phydev);
357 	}
358 
359 	if (phydev->autoneg == AUTONEG_DISABLE) {
360 		/* disabled autoneg doesn't seem to work, so force the link
361 		 * down.
362 		 */
363 		phydev->link = 0;
364 		return 0;
365 	}
366 
367 	/* BCM84891/92 on USXGMII: the host interface mode doesn't change
368 	 * with copper speed (USXGMII symbol replication; the MAC receives
369 	 * the negotiated copper speed, not 10G, so no rate adaptation).
370 	 * Skip 0x4011; phy_resolve_aneg_linkmode() above already set the
371 	 * speed. Only bcm8489x_config_init() allows USXGMII.
372 	 */
373 	if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
374 		return genphy_c45_read_mdix(phydev);
375 
376 	/* Set the host link mode - we set the phy interface mode and
377 	 * the speed according to this register so that downshift works.
378 	 * We leave the duplex setting as per the resolution from the
379 	 * above.
380 	 */
381 	val = phy_read_mmd(phydev, MDIO_MMD_VEND1, 0x4011);
382 	mode = (val & 0x1e) >> 1;
383 	if (mode == 1 || mode == 2)
384 		phydev->interface = PHY_INTERFACE_MODE_SGMII;
385 	else if (mode == 3)
386 		phydev->interface = PHY_INTERFACE_MODE_10GBASER;
387 	else if (mode == 4)
388 		phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
389 	switch (mode & 7) {
390 	case 1:
391 		phydev->speed = SPEED_100;
392 		break;
393 	case 2:
394 		phydev->speed = SPEED_1000;
395 		break;
396 	case 3:
397 		phydev->speed = SPEED_10000;
398 		break;
399 	case 4:
400 		phydev->speed = SPEED_2500;
401 		break;
402 	case 5:
403 		phydev->speed = SPEED_5000;
404 		break;
405 	}
406 
407 	return genphy_c45_read_mdix(phydev);
408 }
409 
410 /* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
411  * or 802.3z control word, so inband will not work.
412  */
413 static unsigned int bcm84881_inband_caps(struct phy_device *phydev,
414 					 phy_interface_t interface)
415 {
416 	return LINK_INBAND_DISABLE;
417 }
418 
419 static struct phy_driver bcm84881_drivers[] = {
420 	{
421 		.phy_id		= 0xae025150,
422 		.phy_id_mask	= 0xfffffff0,
423 		.name		= "Broadcom BCM84881",
424 		.inband_caps	= bcm84881_inband_caps,
425 		.config_init	= bcm84881_config_init,
426 		.probe		= bcm84881_probe,
427 		.get_features	= bcm84881_get_features,
428 		.config_aneg	= bcm84881_config_aneg,
429 		.aneg_done	= bcm84881_aneg_done,
430 		.read_status	= bcm84881_read_status,
431 	}, {
432 		PHY_ID_MATCH_MODEL(0x35905080),
433 		.name		= "Broadcom BCM84891",
434 		.inband_caps	= bcm84881_inband_caps,
435 		.config_init	= bcm8489x_config_init,
436 		.probe		= bcm84881_probe,
437 		.get_features	= bcm84881_get_features,
438 		.config_aneg	= bcm84881_config_aneg,
439 		.aneg_done	= bcm84881_aneg_done,
440 		.read_status	= bcm84881_read_status,
441 		.led_brightness_set = bcm8489x_led_brightness_set,
442 		.led_hw_is_supported = bcm8489x_led_hw_is_supported,
443 		.led_hw_control_set = bcm8489x_led_hw_control_set,
444 		.led_hw_control_get = bcm8489x_led_hw_control_get,
445 	}, {
446 		PHY_ID_MATCH_MODEL(0x359050a0),
447 		.name		= "Broadcom BCM84892",
448 		.inband_caps	= bcm84881_inband_caps,
449 		.config_init	= bcm8489x_config_init,
450 		.probe		= bcm84881_probe,
451 		.get_features	= bcm84881_get_features,
452 		.config_aneg	= bcm84881_config_aneg,
453 		.aneg_done	= bcm84881_aneg_done,
454 		.read_status	= bcm84881_read_status,
455 		.led_brightness_set = bcm8489x_led_brightness_set,
456 		.led_hw_is_supported = bcm8489x_led_hw_is_supported,
457 		.led_hw_control_set = bcm8489x_led_hw_control_set,
458 		.led_hw_control_get = bcm8489x_led_hw_control_get,
459 	},
460 };
461 
462 module_phy_driver(bcm84881_drivers);
463 
464 /* FIXME: module auto-loading for Clause 45 PHYs seems non-functional */
465 static const struct mdio_device_id __maybe_unused bcm84881_tbl[] = {
466 	{ 0xae025150, 0xfffffff0 },
467 	{ PHY_ID_MATCH_MODEL(0x35905080) },
468 	{ PHY_ID_MATCH_MODEL(0x359050a0) },
469 	{ },
470 };
471 MODULE_AUTHOR("Russell King");
472 MODULE_DESCRIPTION("Broadcom BCM84881/BCM84891/BCM84892 PHY driver");
473 MODULE_DEVICE_TABLE(mdio, bcm84881_tbl);
474 MODULE_LICENSE("GPL");
475