Commit b883e47b authored by Oleksij Rempel's avatar Oleksij Rempel Committed by David S. Miller
Browse files

net: phy: tja11xx: add support for master-slave configuration



The TJA11xx PHYs have a vendor specific Master/Slave configuration bit,
which is not compatible with IEEE 803.2-2018 spec for 100Base-T1
devices. So, provide a custom config_ange call back to solve this
problem.

Signed-off-by: default avatarOleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bdbdac76
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#define MII_ECTRL_WAKE_REQUEST		BIT(0)

#define MII_CFG1			18
#define MII_CFG1_MASTER_SLAVE		BIT(15)
#define MII_CFG1_AUTO_OP		BIT(14)
#define MII_CFG1_SLEEP_CONFIRM		BIT(6)
#define MII_CFG1_LED_MODE_MASK		GENMASK(5, 4)
@@ -167,6 +168,32 @@ static int tja11xx_soft_reset(struct phy_device *phydev)
	return genphy_soft_reset(phydev);
}

static int tja11xx_config_aneg(struct phy_device *phydev)
{
	u16 ctl = 0;
	int ret;

	switch (phydev->master_slave_set) {
	case MASTER_SLAVE_CFG_MASTER_FORCE:
		ctl |= MII_CFG1_MASTER_SLAVE;
		break;
	case MASTER_SLAVE_CFG_SLAVE_FORCE:
		break;
	case MASTER_SLAVE_CFG_UNKNOWN:
	case MASTER_SLAVE_CFG_UNSUPPORTED:
		return 0;
	default:
		phydev_warn(phydev, "Unsupported Master/Slave mode\n");
		return -ENOTSUPP;
	}

	ret = phy_modify_changed(phydev, MII_CFG1, MII_CFG1_MASTER_SLAVE, ctl);
	if (ret < 0)
		return ret;

	return __genphy_config_aneg(phydev, ret);
}

static int tja11xx_config_init(struct phy_device *phydev)
{
	int ret;
@@ -224,10 +251,22 @@ static int tja11xx_read_status(struct phy_device *phydev)
{
	int ret;

	phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN;
	phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED;

	ret = genphy_update_link(phydev);
	if (ret)
		return ret;

	ret = phy_read(phydev, MII_CFG1);
	if (ret < 0)
		return ret;

	if (ret & MII_CFG1_MASTER_SLAVE)
		phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE;
	else
		phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE;

	if (phydev->link) {
		ret = phy_read(phydev, MII_COMMSTAT);
		if (ret < 0)
@@ -504,6 +543,7 @@ static struct phy_driver tja11xx_driver[] = {
		.features       = PHY_BASIC_T1_FEATURES,
		.probe		= tja11xx_probe,
		.soft_reset	= tja11xx_soft_reset,
		.config_aneg	= tja11xx_config_aneg,
		.config_init	= tja11xx_config_init,
		.read_status	= tja11xx_read_status,
		.suspend	= genphy_suspend,
@@ -519,6 +559,7 @@ static struct phy_driver tja11xx_driver[] = {
		.features       = PHY_BASIC_T1_FEATURES,
		.probe		= tja11xx_probe,
		.soft_reset	= tja11xx_soft_reset,
		.config_aneg	= tja11xx_config_aneg,
		.config_init	= tja11xx_config_init,
		.read_status	= tja11xx_read_status,
		.suspend	= genphy_suspend,
@@ -533,6 +574,7 @@ static struct phy_driver tja11xx_driver[] = {
		.features       = PHY_BASIC_T1_FEATURES,
		.probe		= tja1102_p0_probe,
		.soft_reset	= tja11xx_soft_reset,
		.config_aneg	= tja11xx_config_aneg,
		.config_init	= tja11xx_config_init,
		.read_status	= tja11xx_read_status,
		.match_phy_device = tja1102_p0_match_phy_device,
@@ -551,6 +593,7 @@ static struct phy_driver tja11xx_driver[] = {
		.features       = PHY_BASIC_T1_FEATURES,
		/* currently no probe for Port 1 is need */
		.soft_reset	= tja11xx_soft_reset,
		.config_aneg	= tja11xx_config_aneg,
		.config_init	= tja11xx_config_init,
		.read_status	= tja11xx_read_status,
		.match_phy_device = tja1102_p1_match_phy_device,