Commit 2a5ab39b authored by David S. Miller's avatar David S. Miller

Merge branch 'mtk_eth_soc-refactoring-and-clause45'

Daniel Golle says:

====================
net: ethernet: mtk_eth_soc: refactoring and Clause 45

Rework value and type of mdio read and write functions in mtk_eth_soc
and generally clean up and unify both functions.
Then add support to access Clause 45 phy registers, using newly
introduced helper inline functions added by a patch Russell King has
suggested in a reply to an earlier version of this series [1].

All three commits are tested on the Bananapi BPi-R64 board having
MediaTek MT7531BE DSA gigE switch using clause 22 MDIO and
Ubiquiti UniFi 6 LR access point having Aquantia AQR112C PHY using
clause 45 MDIO.

[1]: https://lore.kernel.org/netdev/Ycr5Cna76eg2B0An@shell.armlinux.org.uk/

v11: also address return value of mtk_mdio_busy_wait
v10: correct order of SoB lines in 2/3, change patch order in series
v9: improved formatting and Cc missing maintainer
v8: add patch from Russel King, switch to bitfield helper macros
v7: remove unneeded variables and order OR-ed call parameters
v6: further clean up functions and more cleanly separate patches
v5: fix wrong variable name in first patch covered by follow-up patch
v4: clean-up return values and types, split into two commits
v3: return -1 instead of 0xffff on error in _mtk_mdio_write
v2: use MII_DEVADDR_C45_SHIFT and MII_REGADDR_C45_MASK to extract
    device id and register address. Unify read and write functions to
    have identical types and parameter names where possible as we are
    anyway already replacing both function bodies.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ffd32ea6 e2e7f6e2
...@@ -91,46 +91,96 @@ static int mtk_mdio_busy_wait(struct mtk_eth *eth) ...@@ -91,46 +91,96 @@ static int mtk_mdio_busy_wait(struct mtk_eth *eth)
} }
dev_err(eth->dev, "mdio: MDIO timeout\n"); dev_err(eth->dev, "mdio: MDIO timeout\n");
return -1; return -ETIMEDOUT;
} }
static u32 _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, static int _mtk_mdio_write(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg,
u32 phy_register, u32 write_data) u32 write_data)
{ {
if (mtk_mdio_busy_wait(eth)) int ret;
return -1;
ret = mtk_mdio_busy_wait(eth);
if (ret < 0)
return ret;
if (phy_reg & MII_ADDR_C45) {
mtk_w32(eth, PHY_IAC_ACCESS |
PHY_IAC_START_C45 |
PHY_IAC_CMD_C45_ADDR |
PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
PHY_IAC_ADDR(phy_addr) |
PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)),
MTK_PHY_IAC);
write_data &= 0xffff; ret = mtk_mdio_busy_wait(eth);
if (ret < 0)
return ret;
mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_WRITE | mtk_w32(eth, PHY_IAC_ACCESS |
(phy_register << PHY_IAC_REG_SHIFT) | PHY_IAC_START_C45 |
(phy_addr << PHY_IAC_ADDR_SHIFT) | write_data, PHY_IAC_CMD_WRITE |
PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
PHY_IAC_ADDR(phy_addr) |
PHY_IAC_DATA(write_data),
MTK_PHY_IAC);
} else {
mtk_w32(eth, PHY_IAC_ACCESS |
PHY_IAC_START_C22 |
PHY_IAC_CMD_WRITE |
PHY_IAC_REG(phy_reg) |
PHY_IAC_ADDR(phy_addr) |
PHY_IAC_DATA(write_data),
MTK_PHY_IAC); MTK_PHY_IAC);
}
if (mtk_mdio_busy_wait(eth)) ret = mtk_mdio_busy_wait(eth);
return -1; if (ret < 0)
return ret;
return 0; return 0;
} }
static u32 _mtk_mdio_read(struct mtk_eth *eth, int phy_addr, int phy_reg) static int _mtk_mdio_read(struct mtk_eth *eth, u32 phy_addr, u32 phy_reg)
{ {
u32 d; int ret;
if (mtk_mdio_busy_wait(eth)) ret = mtk_mdio_busy_wait(eth);
return 0xffff; if (ret < 0)
return ret;
mtk_w32(eth, PHY_IAC_ACCESS | PHY_IAC_START | PHY_IAC_READ | if (phy_reg & MII_ADDR_C45) {
(phy_reg << PHY_IAC_REG_SHIFT) | mtk_w32(eth, PHY_IAC_ACCESS |
(phy_addr << PHY_IAC_ADDR_SHIFT), PHY_IAC_START_C45 |
PHY_IAC_CMD_C45_ADDR |
PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
PHY_IAC_ADDR(phy_addr) |
PHY_IAC_DATA(mdiobus_c45_regad(phy_reg)),
MTK_PHY_IAC); MTK_PHY_IAC);
if (mtk_mdio_busy_wait(eth)) ret = mtk_mdio_busy_wait(eth);
return 0xffff; if (ret < 0)
return ret;
d = mtk_r32(eth, MTK_PHY_IAC) & 0xffff; mtk_w32(eth, PHY_IAC_ACCESS |
PHY_IAC_START_C45 |
PHY_IAC_CMD_C45_READ |
PHY_IAC_REG(mdiobus_c45_devad(phy_reg)) |
PHY_IAC_ADDR(phy_addr),
MTK_PHY_IAC);
} else {
mtk_w32(eth, PHY_IAC_ACCESS |
PHY_IAC_START_C22 |
PHY_IAC_CMD_C22_READ |
PHY_IAC_REG(phy_reg) |
PHY_IAC_ADDR(phy_addr),
MTK_PHY_IAC);
}
ret = mtk_mdio_busy_wait(eth);
if (ret < 0)
return ret;
return d; return mtk_r32(eth, MTK_PHY_IAC) & PHY_IAC_DATA_MASK;
} }
static int mtk_mdio_write(struct mii_bus *bus, int phy_addr, static int mtk_mdio_write(struct mii_bus *bus, int phy_addr,
...@@ -497,6 +547,7 @@ static int mtk_mdio_init(struct mtk_eth *eth) ...@@ -497,6 +547,7 @@ static int mtk_mdio_init(struct mtk_eth *eth)
eth->mii_bus->name = "mdio"; eth->mii_bus->name = "mdio";
eth->mii_bus->read = mtk_mdio_read; eth->mii_bus->read = mtk_mdio_read;
eth->mii_bus->write = mtk_mdio_write; eth->mii_bus->write = mtk_mdio_write;
eth->mii_bus->probe_capabilities = MDIOBUS_C22_C45;
eth->mii_bus->priv = eth; eth->mii_bus->priv = eth;
eth->mii_bus->parent = eth->dev; eth->mii_bus->parent = eth->dev;
......
...@@ -341,11 +341,20 @@ ...@@ -341,11 +341,20 @@
/* PHY Indirect Access Control registers */ /* PHY Indirect Access Control registers */
#define MTK_PHY_IAC 0x10004 #define MTK_PHY_IAC 0x10004
#define PHY_IAC_ACCESS BIT(31) #define PHY_IAC_ACCESS BIT(31)
#define PHY_IAC_READ BIT(19) #define PHY_IAC_REG_MASK GENMASK(29, 25)
#define PHY_IAC_WRITE BIT(18) #define PHY_IAC_REG(x) FIELD_PREP(PHY_IAC_REG_MASK, (x))
#define PHY_IAC_START BIT(16) #define PHY_IAC_ADDR_MASK GENMASK(24, 20)
#define PHY_IAC_ADDR_SHIFT 20 #define PHY_IAC_ADDR(x) FIELD_PREP(PHY_IAC_ADDR_MASK, (x))
#define PHY_IAC_REG_SHIFT 25 #define PHY_IAC_CMD_MASK GENMASK(19, 18)
#define PHY_IAC_CMD_C45_ADDR FIELD_PREP(PHY_IAC_CMD_MASK, 0)
#define PHY_IAC_CMD_WRITE FIELD_PREP(PHY_IAC_CMD_MASK, 1)
#define PHY_IAC_CMD_C22_READ FIELD_PREP(PHY_IAC_CMD_MASK, 2)
#define PHY_IAC_CMD_C45_READ FIELD_PREP(PHY_IAC_CMD_MASK, 3)
#define PHY_IAC_START_MASK GENMASK(17, 16)
#define PHY_IAC_START_C45 FIELD_PREP(PHY_IAC_START_MASK, 0)
#define PHY_IAC_START_C22 FIELD_PREP(PHY_IAC_START_MASK, 1)
#define PHY_IAC_DATA_MASK GENMASK(15, 0)
#define PHY_IAC_DATA(x) FIELD_PREP(PHY_IAC_DATA_MASK, (x))
#define PHY_IAC_TIMEOUT HZ #define PHY_IAC_TIMEOUT HZ
#define MTK_MAC_MISC 0x1000c #define MTK_MAC_MISC 0x1000c
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#define __LINUX_MDIO_H__ #define __LINUX_MDIO_H__
#include <uapi/linux/mdio.h> #include <uapi/linux/mdio.h>
#include <linux/bitfield.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
/* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit /* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit
...@@ -14,6 +15,7 @@ ...@@ -14,6 +15,7 @@
*/ */
#define MII_ADDR_C45 (1<<30) #define MII_ADDR_C45 (1<<30)
#define MII_DEVADDR_C45_SHIFT 16 #define MII_DEVADDR_C45_SHIFT 16
#define MII_DEVADDR_C45_MASK GENMASK(20, 16)
#define MII_REGADDR_C45_MASK GENMASK(15, 0) #define MII_REGADDR_C45_MASK GENMASK(15, 0)
struct gpio_desc; struct gpio_desc;
...@@ -381,6 +383,16 @@ static inline u32 mdiobus_c45_addr(int devad, u16 regnum) ...@@ -381,6 +383,16 @@ static inline u32 mdiobus_c45_addr(int devad, u16 regnum)
return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum; return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum;
} }
static inline u16 mdiobus_c45_regad(u32 regnum)
{
return FIELD_GET(MII_REGADDR_C45_MASK, regnum);
}
static inline u16 mdiobus_c45_devad(u32 regnum)
{
return FIELD_GET(MII_DEVADDR_C45_MASK, regnum);
}
static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad, static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
u16 regnum) u16 regnum)
{ {
......
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