Commit 8dde1429 authored by David S. Miller's avatar David S. Miller

Merge branch 'phy-realtek-delays'

Serge Semin says:

====================
net: phy: realtek: Fix RGMII TX/RX-delays initial config of rtl8211(e|f)

It has been discovered that RX/TX delays of rtl8211e ethernet PHY
can be configured via a MDIO register hidden in the extension pages
layout. Particularly the extension page 0xa4 provides a register 0x1c,
which bits 1 and 2 control the described delays. They are used to
implement the "rgmii-{id,rxid,txid}" phy-mode support in patch 1.

The second patch makes sure the rtl8211f TX-delay is configured only
if RGMII interface mode is specified including the rgmii-rxid one.
In other cases (most importantly for NA mode) the delays are supposed
to be preconfigured by some other software or hardware and should be
left as is without any modification. The similar thing is also done
for rtl8211e in the patch 1 of this series.

Changelog v3
- Add this cover-letter.
- Add Andrew' Reviewed-by tag to patch 1.
- Accept RGMII_RXID interface mode for rtl8211f and clear the TX_DELAY
  bit in this case.
- Initialize ret variable with 0 to prevent the "may be used uninitialized"
  warning in patch 1.

Changelog v4
- Rebase onto net-next
====================
Signed-off-by: default avatarSerge Semin <fancer.lancer@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3b2c4f4d 1da7756e
...@@ -23,11 +23,15 @@ ...@@ -23,11 +23,15 @@
#define RTL821x_INSR 0x13 #define RTL821x_INSR 0x13
#define RTL821x_EXT_PAGE_SELECT 0x1e
#define RTL821x_PAGE_SELECT 0x1f #define RTL821x_PAGE_SELECT 0x1f
#define RTL8211F_INSR 0x1d #define RTL8211F_INSR 0x1d
#define RTL8211F_TX_DELAY BIT(8) #define RTL8211F_TX_DELAY BIT(8)
#define RTL8211E_TX_DELAY BIT(1)
#define RTL8211E_RX_DELAY BIT(2)
#define RTL8211E_MODE_MII_GMII BIT(3)
#define RTL8201F_ISR 0x1e #define RTL8201F_ISR 0x1e
#define RTL8201F_IER 0x13 #define RTL8201F_IER 0x13
...@@ -157,16 +161,73 @@ static int rtl8211c_config_init(struct phy_device *phydev) ...@@ -157,16 +161,73 @@ static int rtl8211c_config_init(struct phy_device *phydev)
static int rtl8211f_config_init(struct phy_device *phydev) static int rtl8211f_config_init(struct phy_device *phydev)
{ {
u16 val = 0; u16 val;
/* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */ /* enable TX-delay for rgmii-{id,txid}, and disable it for rgmii and
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID || * rgmii-rxid. The RX-delay can be enabled by the external RXDLY pin.
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) */
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_RXID:
val = 0;
break;
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_TXID:
val = RTL8211F_TX_DELAY; val = RTL8211F_TX_DELAY;
break;
default: /* the rest of the modes imply leaving delay as is. */
return 0;
}
return phy_modify_paged(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, val); return phy_modify_paged(phydev, 0xd08, 0x11, RTL8211F_TX_DELAY, val);
} }
static int rtl8211e_config_init(struct phy_device *phydev)
{
int ret = 0, oldpage;
u16 val;
/* enable TX/RX delay for rgmii-* modes, and disable them for rgmii. */
switch (phydev->interface) {
case PHY_INTERFACE_MODE_RGMII:
val = 0;
break;
case PHY_INTERFACE_MODE_RGMII_ID:
val = RTL8211E_TX_DELAY | RTL8211E_RX_DELAY;
break;
case PHY_INTERFACE_MODE_RGMII_RXID:
val = RTL8211E_RX_DELAY;
break;
case PHY_INTERFACE_MODE_RGMII_TXID:
val = RTL8211E_TX_DELAY;
break;
default: /* the rest of the modes imply leaving delays as is. */
return 0;
}
/* According to a sample driver there is a 0x1c config register on the
* 0xa4 extension page (0x7) layout. It can be used to disable/enable
* the RX/TX delays otherwise controlled by RXDLY/TXDLY pins. It can
* also be used to customize the whole configuration register:
* 8:6 = PHY Address, 5:4 = Auto-Negotiation, 3 = Interface Mode Select,
* 2 = RX Delay, 1 = TX Delay, 0 = SELRGV (see original PHY datasheet
* for details).
*/
oldpage = phy_select_page(phydev, 0x7);
if (oldpage < 0)
goto err_restore_page;
ret = phy_write(phydev, RTL821x_EXT_PAGE_SELECT, 0xa4);
if (ret)
goto err_restore_page;
ret = phy_modify(phydev, 0x1c, RTL8211E_TX_DELAY | RTL8211E_RX_DELAY,
val);
err_restore_page:
return phy_restore_page(phydev, oldpage, ret);
}
static int rtl8211b_suspend(struct phy_device *phydev) static int rtl8211b_suspend(struct phy_device *phydev)
{ {
phy_write(phydev, MII_MMD_DATA, BIT(9)); phy_write(phydev, MII_MMD_DATA, BIT(9));
...@@ -239,6 +300,7 @@ static struct phy_driver realtek_drvs[] = { ...@@ -239,6 +300,7 @@ static struct phy_driver realtek_drvs[] = {
}, { }, {
PHY_ID_MATCH_EXACT(0x001cc915), PHY_ID_MATCH_EXACT(0x001cc915),
.name = "RTL8211E Gigabit Ethernet", .name = "RTL8211E Gigabit Ethernet",
.config_init = &rtl8211e_config_init,
.ack_interrupt = &rtl821x_ack_interrupt, .ack_interrupt = &rtl821x_ack_interrupt,
.config_intr = &rtl8211e_config_intr, .config_intr = &rtl8211e_config_intr,
.suspend = genphy_suspend, .suspend = genphy_suspend,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment