mscc.c: Add support for additional VSC PHYs
Add support for the following VSC PHYs VSC8504, VSC8552, VSC8572 VSC8562, VSC8564, VSC8575, VSC8582 Updates for v2: Checked for NULL on input to container_of Changed a large if else series to a switch statement. Added a WARN_ON to make sure lowest nibble of mask is 0 Signed-off-by: Bryan Whitehead <Bryan.Whitehead@microchip.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									945fe45759
								
							
						
					
					
						commit
						75a1ccfe6c
					
				| @ -252,13 +252,21 @@ enum rgmii_rx_clock_delay { | ||||
| #define MSCC_PHY_TR_LSB			  17 | ||||
| #define MSCC_PHY_TR_MSB			  18 | ||||
| 
 | ||||
| /* Microsemi PHY ID's */ | ||||
| /* Microsemi PHY ID's
 | ||||
|  *   Code assumes lowest nibble is 0 | ||||
|  */ | ||||
| #define PHY_ID_VSC8504			  0x000704c0 | ||||
| #define PHY_ID_VSC8514			  0x00070670 | ||||
| #define PHY_ID_VSC8530			  0x00070560 | ||||
| #define PHY_ID_VSC8531			  0x00070570 | ||||
| #define PHY_ID_VSC8540			  0x00070760 | ||||
| #define PHY_ID_VSC8541			  0x00070770 | ||||
| #define PHY_ID_VSC8552			  0x000704e0 | ||||
| #define PHY_ID_VSC856X			  0x000707e0 | ||||
| #define PHY_ID_VSC8572			  0x000704d0 | ||||
| #define PHY_ID_VSC8574			  0x000704a0 | ||||
| #define PHY_ID_VSC8575			  0x000707d0 | ||||
| #define PHY_ID_VSC8582			  0x000707b0 | ||||
| #define PHY_ID_VSC8584			  0x000707c0 | ||||
| 
 | ||||
| #define MSCC_VDDMAC_1500		  1500 | ||||
| @ -1595,6 +1603,9 @@ static bool vsc8584_is_pkg_init(struct phy_device *phydev, bool reversed) | ||||
| 		else | ||||
| 			addr = vsc8531->base_addr + i; | ||||
| 
 | ||||
| 		if (!map[addr]) | ||||
| 			continue; | ||||
| 
 | ||||
| 		phy = container_of(map[addr], struct phy_device, mdio); | ||||
| 
 | ||||
| 		if ((phy->phy_id & phydev->drv->phy_id_mask) != | ||||
| @ -1647,14 +1658,29 @@ static int vsc8584_config_init(struct phy_device *phydev) | ||||
| 	 * in this pre-init function. | ||||
| 	 */ | ||||
| 	if (!vsc8584_is_pkg_init(phydev, val & PHY_ADDR_REVERSED ? 1 : 0)) { | ||||
| 		if ((phydev->phy_id & phydev->drv->phy_id_mask) == | ||||
| 		    (PHY_ID_VSC8574 & phydev->drv->phy_id_mask)) | ||||
| 		/* The following switch statement assumes that the lowest
 | ||||
| 		 * nibble of the phy_id_mask is always 0. This works because | ||||
| 		 * the lowest nibble of the PHY_ID's below are also 0. | ||||
| 		 */ | ||||
| 		WARN_ON(phydev->drv->phy_id_mask & 0xf); | ||||
| 
 | ||||
| 		switch (phydev->phy_id & phydev->drv->phy_id_mask) { | ||||
| 		case PHY_ID_VSC8504: | ||||
| 		case PHY_ID_VSC8552: | ||||
| 		case PHY_ID_VSC8572: | ||||
| 		case PHY_ID_VSC8574: | ||||
| 			ret = vsc8574_config_pre_init(phydev); | ||||
| 		else if ((phydev->phy_id & phydev->drv->phy_id_mask) == | ||||
| 			 (PHY_ID_VSC8584 & phydev->drv->phy_id_mask)) | ||||
| 			break; | ||||
| 		case PHY_ID_VSC856X: | ||||
| 		case PHY_ID_VSC8575: | ||||
| 		case PHY_ID_VSC8582: | ||||
| 		case PHY_ID_VSC8584: | ||||
| 			ret = vsc8584_config_pre_init(phydev); | ||||
| 		else | ||||
| 			break; | ||||
| 		default: | ||||
| 			ret = -EINVAL; | ||||
| 			break; | ||||
| 		}; | ||||
| 
 | ||||
| 		if (ret) | ||||
| 			goto err; | ||||
| @ -2321,6 +2347,32 @@ static int vsc85xx_probe(struct phy_device *phydev) | ||||
| 
 | ||||
| /* Microsemi VSC85xx PHYs */ | ||||
| static struct phy_driver vsc85xx_driver[] = { | ||||
| { | ||||
| 	.phy_id		= PHY_ID_VSC8504, | ||||
| 	.name		= "Microsemi GE VSC8504 SyncE", | ||||
| 	.phy_id_mask	= 0xfffffff0, | ||||
| 	/* PHY_GBIT_FEATURES */ | ||||
| 	.soft_reset	= &genphy_soft_reset, | ||||
| 	.config_init    = &vsc8584_config_init, | ||||
| 	.config_aneg    = &vsc85xx_config_aneg, | ||||
| 	.aneg_done	= &genphy_aneg_done, | ||||
| 	.read_status	= &vsc85xx_read_status, | ||||
| 	.ack_interrupt  = &vsc85xx_ack_interrupt, | ||||
| 	.config_intr    = &vsc85xx_config_intr, | ||||
| 	.did_interrupt  = &vsc8584_did_interrupt, | ||||
| 	.suspend	= &genphy_suspend, | ||||
| 	.resume		= &genphy_resume, | ||||
| 	.probe		= &vsc8574_probe, | ||||
| 	.set_wol	= &vsc85xx_wol_set, | ||||
| 	.get_wol	= &vsc85xx_wol_get, | ||||
| 	.get_tunable	= &vsc85xx_get_tunable, | ||||
| 	.set_tunable	= &vsc85xx_set_tunable, | ||||
| 	.read_page	= &vsc85xx_phy_read_page, | ||||
| 	.write_page	= &vsc85xx_phy_write_page, | ||||
| 	.get_sset_count = &vsc85xx_get_sset_count, | ||||
| 	.get_strings    = &vsc85xx_get_strings, | ||||
| 	.get_stats      = &vsc85xx_get_stats, | ||||
| }, | ||||
| { | ||||
| 	.phy_id		= PHY_ID_VSC8514, | ||||
| 	.name		= "Microsemi GE VSC8514 SyncE", | ||||
| @ -2444,6 +2496,82 @@ static struct phy_driver vsc85xx_driver[] = { | ||||
| 	.get_strings    = &vsc85xx_get_strings, | ||||
| 	.get_stats      = &vsc85xx_get_stats, | ||||
| }, | ||||
| { | ||||
| 	.phy_id		= PHY_ID_VSC8552, | ||||
| 	.name		= "Microsemi GE VSC8552 SyncE", | ||||
| 	.phy_id_mask	= 0xfffffff0, | ||||
| 	/* PHY_GBIT_FEATURES */ | ||||
| 	.soft_reset	= &genphy_soft_reset, | ||||
| 	.config_init    = &vsc8584_config_init, | ||||
| 	.config_aneg    = &vsc85xx_config_aneg, | ||||
| 	.aneg_done	= &genphy_aneg_done, | ||||
| 	.read_status	= &vsc85xx_read_status, | ||||
| 	.ack_interrupt  = &vsc85xx_ack_interrupt, | ||||
| 	.config_intr    = &vsc85xx_config_intr, | ||||
| 	.did_interrupt  = &vsc8584_did_interrupt, | ||||
| 	.suspend	= &genphy_suspend, | ||||
| 	.resume		= &genphy_resume, | ||||
| 	.probe		= &vsc8574_probe, | ||||
| 	.set_wol	= &vsc85xx_wol_set, | ||||
| 	.get_wol	= &vsc85xx_wol_get, | ||||
| 	.get_tunable	= &vsc85xx_get_tunable, | ||||
| 	.set_tunable	= &vsc85xx_set_tunable, | ||||
| 	.read_page	= &vsc85xx_phy_read_page, | ||||
| 	.write_page	= &vsc85xx_phy_write_page, | ||||
| 	.get_sset_count = &vsc85xx_get_sset_count, | ||||
| 	.get_strings    = &vsc85xx_get_strings, | ||||
| 	.get_stats      = &vsc85xx_get_stats, | ||||
| }, | ||||
| { | ||||
| 	.phy_id		= PHY_ID_VSC856X, | ||||
| 	.name		= "Microsemi GE VSC856X SyncE", | ||||
| 	.phy_id_mask	= 0xfffffff0, | ||||
| 	/* PHY_GBIT_FEATURES */ | ||||
| 	.soft_reset	= &genphy_soft_reset, | ||||
| 	.config_init    = &vsc8584_config_init, | ||||
| 	.config_aneg    = &vsc85xx_config_aneg, | ||||
| 	.aneg_done	= &genphy_aneg_done, | ||||
| 	.read_status	= &vsc85xx_read_status, | ||||
| 	.ack_interrupt  = &vsc85xx_ack_interrupt, | ||||
| 	.config_intr    = &vsc85xx_config_intr, | ||||
| 	.did_interrupt  = &vsc8584_did_interrupt, | ||||
| 	.suspend	= &genphy_suspend, | ||||
| 	.resume		= &genphy_resume, | ||||
| 	.probe		= &vsc8584_probe, | ||||
| 	.get_tunable	= &vsc85xx_get_tunable, | ||||
| 	.set_tunable	= &vsc85xx_set_tunable, | ||||
| 	.read_page	= &vsc85xx_phy_read_page, | ||||
| 	.write_page	= &vsc85xx_phy_write_page, | ||||
| 	.get_sset_count = &vsc85xx_get_sset_count, | ||||
| 	.get_strings    = &vsc85xx_get_strings, | ||||
| 	.get_stats      = &vsc85xx_get_stats, | ||||
| }, | ||||
| { | ||||
| 	.phy_id		= PHY_ID_VSC8572, | ||||
| 	.name		= "Microsemi GE VSC8572 SyncE", | ||||
| 	.phy_id_mask	= 0xfffffff0, | ||||
| 	/* PHY_GBIT_FEATURES */ | ||||
| 	.soft_reset	= &genphy_soft_reset, | ||||
| 	.config_init    = &vsc8584_config_init, | ||||
| 	.config_aneg    = &vsc85xx_config_aneg, | ||||
| 	.aneg_done	= &genphy_aneg_done, | ||||
| 	.read_status	= &vsc85xx_read_status, | ||||
| 	.ack_interrupt  = &vsc85xx_ack_interrupt, | ||||
| 	.config_intr    = &vsc85xx_config_intr, | ||||
| 	.did_interrupt  = &vsc8584_did_interrupt, | ||||
| 	.suspend	= &genphy_suspend, | ||||
| 	.resume		= &genphy_resume, | ||||
| 	.probe		= &vsc8574_probe, | ||||
| 	.set_wol	= &vsc85xx_wol_set, | ||||
| 	.get_wol	= &vsc85xx_wol_get, | ||||
| 	.get_tunable	= &vsc85xx_get_tunable, | ||||
| 	.set_tunable	= &vsc85xx_set_tunable, | ||||
| 	.read_page	= &vsc85xx_phy_read_page, | ||||
| 	.write_page	= &vsc85xx_phy_write_page, | ||||
| 	.get_sset_count = &vsc85xx_get_sset_count, | ||||
| 	.get_strings    = &vsc85xx_get_strings, | ||||
| 	.get_stats      = &vsc85xx_get_stats, | ||||
| }, | ||||
| { | ||||
| 	.phy_id		= PHY_ID_VSC8574, | ||||
| 	.name		= "Microsemi GE VSC8574 SyncE", | ||||
| @ -2470,6 +2598,54 @@ static struct phy_driver vsc85xx_driver[] = { | ||||
| 	.get_strings    = &vsc85xx_get_strings, | ||||
| 	.get_stats      = &vsc85xx_get_stats, | ||||
| }, | ||||
| { | ||||
| 	.phy_id		= PHY_ID_VSC8575, | ||||
| 	.name		= "Microsemi GE VSC8575 SyncE", | ||||
| 	.phy_id_mask	= 0xfffffff0, | ||||
| 	/* PHY_GBIT_FEATURES */ | ||||
| 	.soft_reset	= &genphy_soft_reset, | ||||
| 	.config_init    = &vsc8584_config_init, | ||||
| 	.config_aneg    = &vsc85xx_config_aneg, | ||||
| 	.aneg_done	= &genphy_aneg_done, | ||||
| 	.read_status	= &vsc85xx_read_status, | ||||
| 	.ack_interrupt  = &vsc85xx_ack_interrupt, | ||||
| 	.config_intr    = &vsc85xx_config_intr, | ||||
| 	.did_interrupt  = &vsc8584_did_interrupt, | ||||
| 	.suspend	= &genphy_suspend, | ||||
| 	.resume		= &genphy_resume, | ||||
| 	.probe		= &vsc8584_probe, | ||||
| 	.get_tunable	= &vsc85xx_get_tunable, | ||||
| 	.set_tunable	= &vsc85xx_set_tunable, | ||||
| 	.read_page	= &vsc85xx_phy_read_page, | ||||
| 	.write_page	= &vsc85xx_phy_write_page, | ||||
| 	.get_sset_count = &vsc85xx_get_sset_count, | ||||
| 	.get_strings    = &vsc85xx_get_strings, | ||||
| 	.get_stats      = &vsc85xx_get_stats, | ||||
| }, | ||||
| { | ||||
| 	.phy_id		= PHY_ID_VSC8582, | ||||
| 	.name		= "Microsemi GE VSC8582 SyncE", | ||||
| 	.phy_id_mask	= 0xfffffff0, | ||||
| 	/* PHY_GBIT_FEATURES */ | ||||
| 	.soft_reset	= &genphy_soft_reset, | ||||
| 	.config_init    = &vsc8584_config_init, | ||||
| 	.config_aneg    = &vsc85xx_config_aneg, | ||||
| 	.aneg_done	= &genphy_aneg_done, | ||||
| 	.read_status	= &vsc85xx_read_status, | ||||
| 	.ack_interrupt  = &vsc85xx_ack_interrupt, | ||||
| 	.config_intr    = &vsc85xx_config_intr, | ||||
| 	.did_interrupt  = &vsc8584_did_interrupt, | ||||
| 	.suspend	= &genphy_suspend, | ||||
| 	.resume		= &genphy_resume, | ||||
| 	.probe		= &vsc8584_probe, | ||||
| 	.get_tunable	= &vsc85xx_get_tunable, | ||||
| 	.set_tunable	= &vsc85xx_set_tunable, | ||||
| 	.read_page	= &vsc85xx_phy_read_page, | ||||
| 	.write_page	= &vsc85xx_phy_write_page, | ||||
| 	.get_sset_count = &vsc85xx_get_sset_count, | ||||
| 	.get_strings    = &vsc85xx_get_strings, | ||||
| 	.get_stats      = &vsc85xx_get_stats, | ||||
| }, | ||||
| { | ||||
| 	.phy_id		= PHY_ID_VSC8584, | ||||
| 	.name		= "Microsemi GE VSC8584 SyncE", | ||||
| @ -2500,12 +2676,18 @@ static struct phy_driver vsc85xx_driver[] = { | ||||
| module_phy_driver(vsc85xx_driver); | ||||
| 
 | ||||
| static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = { | ||||
| 	{ PHY_ID_VSC8504, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8514, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8530, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8531, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8540, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8541, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8552, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC856X, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8572, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8574, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8575, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8582, 0xfffffff0, }, | ||||
| 	{ PHY_ID_VSC8584, 0xfffffff0, }, | ||||
| 	{ } | ||||
| }; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user