Commit 0653cb2e authored by David S. Miller's avatar David S. Miller

Merge branch 'realtek-phy-improvements'

Martin Blumenstingl says:

====================
Realtek Ethernet PHY driver improvements

This series provides some small improvements and cleanups for the
Realtek Ethernet PHY driver.
None of the patches in this series should change any functionality.
The goal is to make the code a bit easier to read by:
- re-using the BIT and GENMASK macros (which makes it easier to compare
  the #defines in the kernel with the values from the datasheets)
- rename a #define from a generic name to a PHY-specific name since it's
  only used for one specific PHY
- logically group the register #defines and their register bit #defines
  together
- indentation cleanups
- removed some code duplicating for reading/writing registers on a
  Realtek specific "page"
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 75d0de8c 136819a6
......@@ -13,21 +13,26 @@
* option) any later version.
*
*/
#include <linux/bitops.h>
#include <linux/phy.h>
#include <linux/module.h>
#define RTL821x_PHYSR 0x11
#define RTL821x_PHYSR_DUPLEX 0x2000
#define RTL821x_PHYSR_SPEED 0xc000
#define RTL821x_PHYSR_DUPLEX BIT(13)
#define RTL821x_PHYSR_SPEED GENMASK(15, 14)
#define RTL821x_INER 0x12
#define RTL821x_INER_INIT 0x6400
#define RTL8211B_INER_INIT 0x6400
#define RTL8211E_INER_LINK_STATUS BIT(10)
#define RTL8211F_INER_LINK_STATUS BIT(4)
#define RTL821x_INSR 0x13
#define RTL821x_PAGE_SELECT 0x1f
#define RTL8211E_INER_LINK_STATUS 0x400
#define RTL8211F_INER_LINK_STATUS 0x0010
#define RTL8211F_INSR 0x1d
#define RTL8211F_TX_DELAY 0x100
#define RTL8211F_TX_DELAY BIT(8)
#define RTL8201F_ISR 0x1e
#define RTL8201F_IER 0x13
......@@ -36,6 +41,39 @@ MODULE_DESCRIPTION("Realtek PHY driver");
MODULE_AUTHOR("Johnson Leung");
MODULE_LICENSE("GPL");
static int rtl8211x_page_read(struct phy_device *phydev, u16 page, u16 address)
{
int ret;
ret = phy_write(phydev, RTL821x_PAGE_SELECT, page);
if (ret)
return ret;
ret = phy_read(phydev, address);
/* restore to default page 0 */
phy_write(phydev, RTL821x_PAGE_SELECT, 0x0);
return ret;
}
static int rtl8211x_page_write(struct phy_device *phydev, u16 page,
u16 address, u16 val)
{
int ret;
ret = phy_write(phydev, RTL821x_PAGE_SELECT, page);
if (ret)
return ret;
ret = phy_write(phydev, address, val);
/* restore to default page 0 */
phy_write(phydev, RTL821x_PAGE_SELECT, 0x0);
return ret;
}
static int rtl8201_ack_interrupt(struct phy_device *phydev)
{
int err;
......@@ -58,31 +96,21 @@ static int rtl8211f_ack_interrupt(struct phy_device *phydev)
{
int err;
phy_write(phydev, RTL821x_PAGE_SELECT, 0xa43);
err = phy_read(phydev, RTL8211F_INSR);
/* restore to default page 0 */
phy_write(phydev, RTL821x_PAGE_SELECT, 0x0);
err = rtl8211x_page_read(phydev, 0xa43, RTL8211F_INSR);
return (err < 0) ? err : 0;
}
static int rtl8201_config_intr(struct phy_device *phydev)
{
int err;
/* switch to page 7 */
phy_write(phydev, RTL821x_PAGE_SELECT, 0x7);
u16 val;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
err = phy_write(phydev, RTL8201F_IER,
BIT(13) | BIT(12) | BIT(11));
val = BIT(13) | BIT(12) | BIT(11);
else
err = phy_write(phydev, RTL8201F_IER, 0);
/* restore to default page 0 */
phy_write(phydev, RTL821x_PAGE_SELECT, 0x0);
val = 0;
return err;
return rtl8211x_page_write(phydev, 0x7, RTL8201F_IER, val);
}
static int rtl8211b_config_intr(struct phy_device *phydev)
......@@ -91,7 +119,7 @@ static int rtl8211b_config_intr(struct phy_device *phydev)
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
err = phy_write(phydev, RTL821x_INER,
RTL821x_INER_INIT);
RTL8211B_INER_INIT);
else
err = phy_write(phydev, RTL821x_INER, 0);
......@@ -113,41 +141,41 @@ static int rtl8211e_config_intr(struct phy_device *phydev)
static int rtl8211f_config_intr(struct phy_device *phydev)
{
int err;
u16 val;
phy_write(phydev, RTL821x_PAGE_SELECT, 0xa42);
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
err = phy_write(phydev, RTL821x_INER,
RTL8211F_INER_LINK_STATUS);
val = RTL8211F_INER_LINK_STATUS;
else
err = phy_write(phydev, RTL821x_INER, 0);
phy_write(phydev, RTL821x_PAGE_SELECT, 0);
val = 0;
return err;
return rtl8211x_page_write(phydev, 0xa42, RTL821x_INER, val);
}
static int rtl8211f_config_init(struct phy_device *phydev)
{
int ret;
u16 reg;
u16 val;
ret = genphy_config_init(phydev);
if (ret < 0)
return ret;
phy_write(phydev, RTL821x_PAGE_SELECT, 0xd08);
reg = phy_read(phydev, 0x11);
ret = rtl8211x_page_read(phydev, 0xd08, 0x11);
if (ret < 0)
return ret;
val = ret & 0xffff;
/* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */
if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
reg |= RTL8211F_TX_DELAY;
val |= RTL8211F_TX_DELAY;
else
reg &= ~RTL8211F_TX_DELAY;
val &= ~RTL8211F_TX_DELAY;
phy_write(phydev, 0x11, reg);
/* restore to default page 0 */
phy_write(phydev, RTL821x_PAGE_SELECT, 0x0);
ret = rtl8211x_page_write(phydev, 0xd08, 0x11, val);
if (ret)
return ret;
return 0;
}
......
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