File Index
Files and directories
Sign in
FILE

microchip_t1s.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/phy/microchip_t1s.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Driver for Microchip 10BASE-T1S PHYs
  4 *
  5 * Support: Microchip Phys:
  6 *  lan8670/1/2 Rev.B1/C1/C2/D0
  7 *  lan8650/1 Rev.B0/B1 Internal PHYs
  8 */
  9
 10#include <linux/kernel.h>
 11#include <linux/module.h>
 12#include <linux/phy.h>
 13
 14#define PHY_ID_LAN867X_REVB1 0x0007C162
 15#define PHY_ID_LAN867X_REVC1 0x0007C164
 16#define PHY_ID_LAN867X_REVC2 0x0007C165
 17#define PHY_ID_LAN867X_REVD0 0x0007C166
 18/* Both Rev.B0 and B1 clause 22 PHYID's are same due to B1 chip limitation */
 19#define PHY_ID_LAN865X_REVB 0x0007C1B3
 20
 21#define LAN867X_REG_STS2 0x0019
 22
 23#define LAN867x_RESET_COMPLETE_STS BIT(11)
 24
 25#define LAN865X_REG_CFGPARAM_ADDR 0x00D8
 26#define LAN865X_REG_CFGPARAM_DATA 0x00D9
 27#define LAN865X_REG_CFGPARAM_CTRL 0x00DA
 28#define LAN865X_REG_STS2 0x0019
 29
 30/* Collision Detector Control 0 Register */
 31#define LAN86XX_REG_COL_DET_CTRL0	0x0087
 32#define COL_DET_CTRL0_ENABLE_BIT_MASK	BIT(15)
 33#define COL_DET_ENABLE			BIT(15)
 34#define COL_DET_DISABLE			0x0000
 35
 36/* LAN8670/1/2 Rev.D0 Link Status Selection Register */
 37#define LAN867X_REG_LINK_STATUS_CTRL	0x0012
 38#define LINK_STATUS_CONFIGURATION	GENMASK(12, 11)
 39#define LINK_STATUS_SEMAPHORE		BIT(0)
 40
 41/* Link Status Configuration */
 42#define LINK_STATUS_CONFIG_PLCA_STATUS	0x1
 43#define LINK_STATUS_CONFIG_SEMAPHORE	0x2
 44
 45#define LINK_STATUS_SEMAPHORE_SET	0x1
 46
 47#define LAN865X_CFGPARAM_READ_ENABLE BIT(1)
 48
 49/* The arrays below are pulled from the following table from AN1699
 50 * Access MMD Address Value Mask
 51 * RMW 0x1F 0x00D0 0x0002 0x0E03
 52 * RMW 0x1F 0x00D1 0x0000 0x0300
 53 * RMW 0x1F 0x0084 0x3380 0xFFC0
 54 * RMW 0x1F 0x0085 0x0006 0x000F
 55 * RMW 0x1F 0x008A 0xC000 0xF800
 56 * RMW 0x1F 0x0087 0x801C 0x801C
 57 * RMW 0x1F 0x0088 0x033F 0x1FFF
 58 * W   0x1F 0x008B 0x0404 ------
 59 * RMW 0x1F 0x0080 0x0600 0x0600
 60 * RMW 0x1F 0x00F1 0x2400 0x7F00
 61 * RMW 0x1F 0x0096 0x2000 0x2000
 62 * W   0x1F 0x0099 0x7F80 ------
 63 */
 64
 65static const u32 lan867x_revb1_fixup_registers[12] = {
 66	0x00D0, 0x00D1, 0x0084, 0x0085,
 67	0x008A, 0x0087, 0x0088, 0x008B,
 68	0x0080, 0x00F1, 0x0096, 0x0099,
 69};
 70
 71static const u16 lan867x_revb1_fixup_values[12] = {
 72	0x0002, 0x0000, 0x3380, 0x0006,
 73	0xC000, 0x801C, 0x033F, 0x0404,
 74	0x0600, 0x2400, 0x2000, 0x7F80,
 75};
 76
 77static const u16 lan867x_revb1_fixup_masks[12] = {
 78	0x0E03, 0x0300, 0xFFC0, 0x000F,
 79	0xF800, 0x801C, 0x1FFF, 0xFFFF,
 80	0x0600, 0x7F00, 0x2000, 0xFFFF,
 81};
 82
 83/* LAN865x Rev.B0/B1 configuration parameters from AN1760
 84 * As per the Configuration Application Note AN1760 published in the below link,
 85 * https://www.microchip.com/en-us/application-notes/an1760
 86 * Revision F (DS60001760G - June 2024)
 87 */
 88static const u32 lan865x_revb_fixup_registers[17] = {
 89	0x00D0, 0x00E0, 0x00E9, 0x00F5,
 90	0x00F4, 0x00F8, 0x00F9, 0x0081,
 91	0x0091, 0x0043, 0x0044, 0x0045,
 92	0x0053, 0x0054, 0x0055, 0x0040,
 93	0x0050,
 94};
 95
 96static const u16 lan865x_revb_fixup_values[17] = {
 97	0x3F31, 0xC000, 0x9E50, 0x1CF8,
 98	0xC020, 0xB900, 0x4E53, 0x0080,
 99	0x9660, 0x00FF, 0xFFFF, 0x0000,
100	0x00FF, 0xFFFF, 0x0000, 0x0002,
101	0x0002,
102};
103
104static const u16 lan865x_revb_fixup_cfg_regs[2] = {
105	0x0084, 0x008A,
106};
107
108static const u32 lan865x_revb_sqi_fixup_regs[12] = {
109	0x00B0, 0x00B1, 0x00B2, 0x00B3,
110	0x00B4, 0x00B5, 0x00B6, 0x00B7,
111	0x00B8, 0x00B9, 0x00BA, 0x00BB,
112};
113
114static const u16 lan865x_revb_sqi_fixup_values[12] = {
115	0x0103, 0x0910, 0x1D26, 0x002A,
116	0x0103, 0x070D, 0x1720, 0x0027,
117	0x0509, 0x0E13, 0x1C25, 0x002B,
118};
119
120static const u16 lan865x_revb_sqi_fixup_cfg_regs[3] = {
121	0x00AD, 0x00AE, 0x00AF,
122};
123
124/* LAN867x Rev.D0 configuration parameters from AN1699
125 * As per the Configuration Application Note AN1699 published in the below link,
126 * https://www.microchip.com/en-us/application-notes/an1699
127 * Revision G (DS60001699G - October 2025)
128 */
129static const u16 lan867x_revd0_fixup_regs[8] = {
130	0x0037, 0x008A, 0x0118, 0x00D6,
131	0x0082, 0x00FD, 0x00FD, 0x0091,
132};
133
134static const u16 lan867x_revd0_fixup_values[8] = {
135	0x0800, 0xBFC0, 0x029C, 0x1001,
136	0x001C, 0x0C0B, 0x8C07, 0x9660,
137};
138
139/* Pulled from AN1760 describing 'indirect read'
140 *
141 * write_register(0x4, 0x00D8, addr)
142 * write_register(0x4, 0x00DA, 0x2)
143 * return (int8)(read_register(0x4, 0x00D9))
144 *
145 * 0x4 refers to memory map selector 4, which maps to MDIO_MMD_VEND2
146 */
147static int lan865x_revb_indirect_read(struct phy_device *phydev, u16 addr)
148{
149	int ret;
150
151	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_ADDR,
152			    addr);
153	if (ret)
154		return ret;
155
156	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_CTRL,
157			    LAN865X_CFGPARAM_READ_ENABLE);
158	if (ret)
159		return ret;
160
161	return phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_DATA);
162}
163
164/* This is pulled straight from AN1760 from 'calculation of offset 1' &
165 * 'calculation of offset 2'
166 */
167static int lan865x_generate_cfg_offsets(struct phy_device *phydev, s8 offsets[])
168{
169	const u16 fixup_regs[2] = {0x0004, 0x0008};
170	int ret;
171
172	for (int i = 0; i < ARRAY_SIZE(fixup_regs); i++) {
173		ret = lan865x_revb_indirect_read(phydev, fixup_regs[i]);
174		if (ret < 0)
175			return ret;
176
177		/* 5-bit signed value, sign extend */
178		ret &= GENMASK(4, 0);
179		if (ret & BIT(4))
180			offsets[i] = ret | 0xE0;
181		else
182			offsets[i] = ret;
183	}
184
185	return 0;
186}
187
188static int lan865x_read_cfg_params(struct phy_device *phydev,
189				   const u16 cfg_regs[], u16 cfg_params[],
190				   u8 count)
191{
192	int ret;
193
194	for (int i = 0; i < count; i++) {
195		ret = phy_read_mmd(phydev, MDIO_MMD_VEND2,
196				   cfg_regs[i]);
197		if (ret < 0)
198			return ret;
199		cfg_params[i] = (u16)ret;
200	}
201
202	return 0;
203}
204
205static int lan865x_write_cfg_params(struct phy_device *phydev,
206				    const u16 cfg_regs[], u16 cfg_params[],
207				    u8 count)
208{
209	int ret;
210
211	for (int i = 0; i < count; i++) {
212		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, cfg_regs[i],
213				    cfg_params[i]);
214		if (ret)
215			return ret;
216	}
217
218	return 0;
219}
220
221static int lan865x_setup_cfgparam(struct phy_device *phydev, s8 offsets[])
222{
223	u16 cfg_results[ARRAY_SIZE(lan865x_revb_fixup_cfg_regs)];
224	u16 cfg_params[ARRAY_SIZE(lan865x_revb_fixup_cfg_regs)];
225	int ret;
226
227	ret = lan865x_read_cfg_params(phydev, lan865x_revb_fixup_cfg_regs,
228				      cfg_params, ARRAY_SIZE(cfg_params));
229	if (ret)
230		return ret;
231
232	cfg_results[0] = FIELD_PREP(GENMASK(15, 10), 9 + offsets[0]) |
233			 FIELD_PREP(GENMASK(9, 4), 14 + offsets[0]) |
234			 0x03;
235	cfg_results[1] = FIELD_PREP(GENMASK(15, 10), 40 + offsets[1]);
236
237	return lan865x_write_cfg_params(phydev, lan865x_revb_fixup_cfg_regs,
238					cfg_results, ARRAY_SIZE(cfg_results));
239}
240
241static int lan865x_setup_sqi_cfgparam(struct phy_device *phydev, s8 offsets[])
242{
243	u16 cfg_results[ARRAY_SIZE(lan865x_revb_sqi_fixup_cfg_regs)];
244	u16 cfg_params[ARRAY_SIZE(lan865x_revb_sqi_fixup_cfg_regs)];
245	int ret;
246
247	ret = lan865x_read_cfg_params(phydev, lan865x_revb_sqi_fixup_cfg_regs,
248				      cfg_params, ARRAY_SIZE(cfg_params));
249	if (ret)
250		return ret;
251
252	cfg_results[0] = FIELD_PREP(GENMASK(13, 8), 5 + offsets[0]) |
253			 (9 + offsets[0]);
254	cfg_results[1] = FIELD_PREP(GENMASK(13, 8), 9 + offsets[0]) |
255			 (14 + offsets[0]);
256	cfg_results[2] = FIELD_PREP(GENMASK(13, 8), 17 + offsets[0]) |
257			 (22 + offsets[0]);
258
259	return lan865x_write_cfg_params(phydev, lan865x_revb_sqi_fixup_cfg_regs,
260					cfg_results, ARRAY_SIZE(cfg_results));
261}
262
263static int lan865x_revb_config_init(struct phy_device *phydev)
264{
265	s8 offsets[2];
266	int ret;
267
268	/* Reference to AN1760
269	 * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8650-1-Configuration-60001760.pdf
270	 */
271	ret = lan865x_generate_cfg_offsets(phydev, offsets);
272	if (ret)
273		return ret;
274
275	for (int i = 0; i < ARRAY_SIZE(lan865x_revb_fixup_registers); i++) {
276		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
277				    lan865x_revb_fixup_registers[i],
278				    lan865x_revb_fixup_values[i]);
279		if (ret)
280			return ret;
281
282		if (i == 1) {
283			ret = lan865x_setup_cfgparam(phydev, offsets);
284			if (ret)
285				return ret;
286		}
287	}
288
289	ret = lan865x_setup_sqi_cfgparam(phydev, offsets);
290	if (ret)
291		return ret;
292
293	for (int i = 0; i < ARRAY_SIZE(lan865x_revb_sqi_fixup_regs); i++) {
294		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
295				    lan865x_revb_sqi_fixup_regs[i],
296				    lan865x_revb_sqi_fixup_values[i]);
297		if (ret)
298			return ret;
299	}
300
301	return 0;
302}
303
304static int lan867x_check_reset_complete(struct phy_device *phydev)
305{
306	int err;
307
308	/* The chip completes a reset in 3us, we might get here earlier than
309	 * that, as an added margin we'll conditionally sleep 5us.
310	 */
311	err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2);
312	if (err < 0)
313		return err;
314
315	if (!(err & LAN867x_RESET_COMPLETE_STS)) {
316		udelay(5);
317		err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2);
318		if (err < 0)
319			return err;
320		if (!(err & LAN867x_RESET_COMPLETE_STS)) {
321			phydev_err(phydev, "PHY reset failed\n");
322			return -ENODEV;
323		}
324	}
325
326	return 0;
327}
328
329static int lan867x_revc_config_init(struct phy_device *phydev)
330{
331	s8 offsets[2];
332	int ret;
333
334	ret = lan867x_check_reset_complete(phydev);
335	if (ret)
336		return ret;
337
338	ret = lan865x_generate_cfg_offsets(phydev, offsets);
339	if (ret)
340		return ret;
341
342	/* LAN867x Rev.C1/C2 configuration settings are equal to the first 9
343	 * configuration settings and all the sqi fixup settings from LAN865x
344	 * Rev.B0/B1. So the same fixup registers and values from LAN865x
345	 * Rev.B0/B1 are used for LAN867x Rev.C1/C2 to avoid duplication.
346	 * Refer the below links for the comparison.
347	 * https://www.microchip.com/en-us/application-notes/an1760
348	 * Revision F (DS60001760G - June 2024)
349	 * https://www.microchip.com/en-us/application-notes/an1699
350	 * Revision E (DS60001699F - June 2024)
351	 */
352	for (int i = 0; i < 9; i++) {
353		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
354				    lan865x_revb_fixup_registers[i],
355				    lan865x_revb_fixup_values[i]);
356		if (ret)
357			return ret;
358
359		if (i == 1) {
360			ret = lan865x_setup_cfgparam(phydev, offsets);
361			if (ret)
362				return ret;
363		}
364	}
365
366	ret = lan865x_setup_sqi_cfgparam(phydev, offsets);
367	if (ret)
368		return ret;
369
370	for (int i = 0; i < ARRAY_SIZE(lan865x_revb_sqi_fixup_regs); i++) {
371		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
372				    lan865x_revb_sqi_fixup_regs[i],
373				    lan865x_revb_sqi_fixup_values[i]);
374		if (ret)
375			return ret;
376	}
377
378	return 0;
379}
380
381static int lan867x_revb1_config_init(struct phy_device *phydev)
382{
383	int err;
384
385	err = lan867x_check_reset_complete(phydev);
386	if (err)
387		return err;
388
389	/* Reference to AN1699
390	 * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8670-1-2-config-60001699.pdf
391	 * AN1699 says Read, Modify, Write, but the Write is not required if the
392	 * register already has the required value. So it is safe to use
393	 * phy_modify_mmd here.
394	 */
395	for (int i = 0; i < ARRAY_SIZE(lan867x_revb1_fixup_registers); i++) {
396		err = phy_modify_mmd(phydev, MDIO_MMD_VEND2,
397				     lan867x_revb1_fixup_registers[i],
398				     lan867x_revb1_fixup_masks[i],
399				     lan867x_revb1_fixup_values[i]);
400		if (err)
401			return err;
402	}
403
404	return 0;
405}
406
407static int lan867x_revd0_link_active_selection(struct phy_device *phydev,
408					       bool plca_enabled)
409{
410	u16 value;
411
412	if (plca_enabled) {
413		/* 0x1 - When PLCA is enabled: link status reflects plca_status.
414		 */
415		value = FIELD_PREP(LINK_STATUS_CONFIGURATION,
416				   LINK_STATUS_CONFIG_PLCA_STATUS);
417	} else {
418		/* 0x2 - Link status is controlled by the value written into the
419		 * LINK_STATUS_SEMAPHORE bit written. Here the link semaphore
420		 * bit is written with 0x1 to set the link always active in
421		 * CSMA/CD mode as it doesn't support autoneg.
422		 */
423		value = FIELD_PREP(LINK_STATUS_CONFIGURATION,
424				   LINK_STATUS_CONFIG_SEMAPHORE) |
425			FIELD_PREP(LINK_STATUS_SEMAPHORE,
426				   LINK_STATUS_SEMAPHORE_SET);
427	}
428
429	return phy_write_mmd(phydev, MDIO_MMD_VEND2,
430			     LAN867X_REG_LINK_STATUS_CTRL, value);
431}
432
433/* As per LAN8650/1 Rev.B0/B1 AN1760 (Revision F (DS60001760G - June 2024)) and
434 * LAN8670/1/2 Rev.C1/C2 AN1699 (Revision E (DS60001699F - June 2024)), under
435 * normal operation, the device should be operated in PLCA mode. Disabling
436 * collision detection is recommended to allow the device to operate in noisy
437 * environments or when reflections and other inherent transmission line
438 * distortion cause poor signal quality. Collision detection must be re-enabled
439 * if the device is configured to operate in CSMA/CD mode.
440 *
441 * AN1760: https://www.microchip.com/en-us/application-notes/an1760
442 * AN1699: https://www.microchip.com/en-us/application-notes/an1699
443 */
444static int lan86xx_plca_set_cfg(struct phy_device *phydev,
445				const struct phy_plca_cfg *plca_cfg)
446{
447	int ret;
448
449	/* Link status selection must be configured for LAN8670/1/2 Rev.D0 */
450	if (phydev->phy_id == PHY_ID_LAN867X_REVD0) {
451		ret = lan867x_revd0_link_active_selection(phydev,
452							  plca_cfg->enabled);
453		if (ret)
454			return ret;
455	}
456
457	ret = genphy_c45_plca_set_cfg(phydev, plca_cfg);
458	if (ret)
459		return ret;
460
461	if (plca_cfg->enabled)
462		return phy_modify_mmd(phydev, MDIO_MMD_VEND2,
463				      LAN86XX_REG_COL_DET_CTRL0,
464				      COL_DET_CTRL0_ENABLE_BIT_MASK,
465				      COL_DET_DISABLE);
466
467	return phy_modify_mmd(phydev, MDIO_MMD_VEND2, LAN86XX_REG_COL_DET_CTRL0,
468			      COL_DET_CTRL0_ENABLE_BIT_MASK, COL_DET_ENABLE);
469}
470
471static int lan867x_revd0_config_init(struct phy_device *phydev)
472{
473	int ret;
474
475	ret = lan867x_check_reset_complete(phydev);
476	if (ret)
477		return ret;
478
479	for (int i = 0; i < ARRAY_SIZE(lan867x_revd0_fixup_regs); i++) {
480		ret = phy_write_mmd(phydev, MDIO_MMD_VEND2,
481				    lan867x_revd0_fixup_regs[i],
482				    lan867x_revd0_fixup_values[i]);
483		if (ret)
484			return ret;
485	}
486
487	/* Initially the PHY will be in CSMA/CD mode by default. So it is
488	 * required to set the link always active as it doesn't support
489	 * autoneg.
490	 */
491	return lan867x_revd0_link_active_selection(phydev, false);
492}
493
494static int lan86xx_read_status(struct phy_device *phydev)
495{
496	/* The phy has some limitations, namely:
497	 *  - always reports link up
498	 *  - only supports 10MBit half duplex
499	 *  - does not support auto negotiate
500	 */
501	phydev->link = 1;
502	phydev->duplex = DUPLEX_HALF;
503	phydev->speed = SPEED_10;
504	phydev->autoneg = AUTONEG_DISABLE;
505
506	return 0;
507}
508
509/* OPEN Alliance 10BASE-T1x compliance MAC-PHYs will have both C22 and
510 * C45 registers space. If the PHY is discovered via C22 bus protocol it assumes
511 * it uses C22 protocol and always uses C22 registers indirect access to access
512 * C45 registers. This is because, we don't have a clean separation between
513 * C22/C45 register space and C22/C45 MDIO bus protocols. Resulting, PHY C45
514 * registers direct access can't be used which can save multiple SPI bus access.
515 * To support this feature, set .read_mmd/.write_mmd in the PHY driver to call
516 * .read_c45/.write_c45 in the OPEN Alliance framework
517 * drivers/net/ethernet/oa_tc6.c
518 */
519static int lan865x_phy_read_mmd(struct phy_device *phydev, int devnum,
520				u16 regnum)
521{
522	struct mii_bus *bus = phydev->mdio.bus;
523	int addr = phydev->mdio.addr;
524
525	return __mdiobus_c45_read(bus, addr, devnum, regnum);
526}
527
528static int lan865x_phy_write_mmd(struct phy_device *phydev, int devnum,
529				 u16 regnum, u16 val)
530{
531	struct mii_bus *bus = phydev->mdio.bus;
532	int addr = phydev->mdio.addr;
533
534	return __mdiobus_c45_write(bus, addr, devnum, regnum, val);
535}
536
537static struct phy_driver microchip_t1s_driver[] = {
538	{
539		PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1),
540		.name               = "LAN867X Rev.B1",
541		.features           = PHY_BASIC_T1S_P2MP_FEATURES,
542		.config_init        = lan867x_revb1_config_init,
543		.read_status        = lan86xx_read_status,
544		.get_plca_cfg	    = genphy_c45_plca_get_cfg,
545		.set_plca_cfg	    = genphy_c45_plca_set_cfg,
546		.get_plca_status    = genphy_c45_plca_get_status,
547	},
548	{
549		PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVC1),
550		.name               = "LAN867X Rev.C1",
551		.features           = PHY_BASIC_T1S_P2MP_FEATURES,
552		.config_init        = lan867x_revc_config_init,
553		.read_status        = lan86xx_read_status,
554		.get_plca_cfg	    = genphy_c45_plca_get_cfg,
555		.set_plca_cfg	    = lan86xx_plca_set_cfg,
556		.get_plca_status    = genphy_c45_plca_get_status,
557	},
558	{
559		PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVC2),
560		.name               = "LAN867X Rev.C2",
561		.features           = PHY_BASIC_T1S_P2MP_FEATURES,
562		.config_init        = lan867x_revc_config_init,
563		.read_status        = lan86xx_read_status,
564		.get_plca_cfg	    = genphy_c45_plca_get_cfg,
565		.set_plca_cfg	    = lan86xx_plca_set_cfg,
566		.get_plca_status    = genphy_c45_plca_get_status,
567	},
568	{
569		PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVD0),
570		.name               = "LAN867X Rev.D0",
571		.features           = PHY_BASIC_T1S_P2MP_FEATURES,
572		.config_init        = lan867x_revd0_config_init,
573		.get_plca_cfg	    = genphy_c45_plca_get_cfg,
574		.set_plca_cfg	    = lan86xx_plca_set_cfg,
575		.get_plca_status    = genphy_c45_plca_get_status,
576		.cable_test_start   = genphy_c45_oatc14_cable_test_start,
577		.cable_test_get_status = genphy_c45_oatc14_cable_test_get_status,
578		.get_sqi            = genphy_c45_oatc14_get_sqi,
579		.get_sqi_max        = genphy_c45_oatc14_get_sqi_max,
580	},
581	{
582		PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB),
583		.name               = "LAN865X Rev.B0/B1 Internal Phy",
584		.features           = PHY_BASIC_T1S_P2MP_FEATURES,
585		.config_init        = lan865x_revb_config_init,
586		.read_status        = lan86xx_read_status,
587		.read_mmd           = lan865x_phy_read_mmd,
588		.write_mmd          = lan865x_phy_write_mmd,
589		.get_plca_cfg	    = genphy_c45_plca_get_cfg,
590		.set_plca_cfg	    = lan86xx_plca_set_cfg,
591		.get_plca_status    = genphy_c45_plca_get_status,
592	},
593};
594
595module_phy_driver(microchip_t1s_driver);
596
597static const struct mdio_device_id __maybe_unused tbl[] = {
598	{ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1) },
599	{ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVC1) },
600	{ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVC2) },
601	{ PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVD0) },
602	{ PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB) },
603	{ }
604};
605
606MODULE_DEVICE_TABLE(mdio, tbl);
607
608MODULE_DESCRIPTION("Microchip 10BASE-T1S PHYs driver");
609MODULE_AUTHOR("Ramón Nordin Rodriguez");
610MODULE_LICENSE("GPL");
~/ Read-only file preview.