net: phy: adin: configure RGMII/RMII/MII modes on config

The ADIN1300 chip supports RGMII, RMII & MII modes. Default (if
unconfigured) is RGMII.
This change adds support for configuring these modes via the device
registers.

For RGMII with internal delays (modes RGMII_ID,RGMII_TXID, RGMII_RXID),
the default delay is 2 ns. This can be configurable and will be done in
a subsequent change.

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Alexandru Ardelean <alexandru.ardelean@analog.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Alexandru Ardelean 2019-08-16 16:10:03 +03:00 коммит произвёл David S. Miller
Родитель 3e32d020d8
Коммит d6200c8fd5
1 изменённых файлов: 78 добавлений и 1 удалений

Просмотреть файл

@ -31,9 +31,86 @@
(ADIN1300_INT_LINK_STAT_CHNG_EN | ADIN1300_INT_HW_IRQ_EN)
#define ADIN1300_INT_STATUS_REG 0x0019
#define ADIN1300_GE_RGMII_CFG_REG 0xff23
#define ADIN1300_GE_RGMII_RXID_EN BIT(2)
#define ADIN1300_GE_RGMII_TXID_EN BIT(1)
#define ADIN1300_GE_RGMII_EN BIT(0)
#define ADIN1300_GE_RMII_CFG_REG 0xff24
#define ADIN1300_GE_RMII_EN BIT(0)
static int adin_config_rgmii_mode(struct phy_device *phydev)
{
int reg;
if (!phy_interface_is_rgmii(phydev))
return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
ADIN1300_GE_RGMII_CFG_REG,
ADIN1300_GE_RGMII_EN);
reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_GE_RGMII_CFG_REG);
if (reg < 0)
return reg;
reg |= ADIN1300_GE_RGMII_EN;
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) {
reg |= ADIN1300_GE_RGMII_RXID_EN;
} else {
reg &= ~ADIN1300_GE_RGMII_RXID_EN;
}
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) {
reg |= ADIN1300_GE_RGMII_TXID_EN;
} else {
reg &= ~ADIN1300_GE_RGMII_TXID_EN;
}
return phy_write_mmd(phydev, MDIO_MMD_VEND1,
ADIN1300_GE_RGMII_CFG_REG, reg);
}
static int adin_config_rmii_mode(struct phy_device *phydev)
{
int reg;
if (phydev->interface != PHY_INTERFACE_MODE_RMII)
return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
ADIN1300_GE_RMII_CFG_REG,
ADIN1300_GE_RMII_EN);
reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_GE_RMII_CFG_REG);
if (reg < 0)
return reg;
reg |= ADIN1300_GE_RMII_EN;
return phy_write_mmd(phydev, MDIO_MMD_VEND1,
ADIN1300_GE_RMII_CFG_REG, reg);
}
static int adin_config_init(struct phy_device *phydev)
{
return genphy_config_init(phydev);
int rc;
rc = genphy_config_init(phydev);
if (rc < 0)
return rc;
rc = adin_config_rgmii_mode(phydev);
if (rc < 0)
return rc;
rc = adin_config_rmii_mode(phydev);
if (rc < 0)
return rc;
phydev_dbg(phydev, "PHY is using mode '%s'\n",
phy_modes(phydev->interface));
return 0;
}
static int adin_phy_ack_intr(struct phy_device *phydev)