aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8216.c48
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8216.h9
2 files changed, 57 insertions, 0 deletions
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c
index e1c3dc95c3..c6e3a05299 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.c
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.c
@@ -816,6 +816,52 @@ static void ar8216_get_arl_entry(struct ar8xxx_priv *priv,
}
static int
+ar8216_phy_read(struct ar8xxx_priv *priv, int addr, int regnum)
+{
+ u32 t, val = 0xffff;
+ int err;
+
+ if (addr >= AR8216_NUM_PORTS)
+ return 0xffff;
+ t = (regnum << AR8216_MDIO_CTRL_REG_ADDR_S) |
+ (addr << AR8216_MDIO_CTRL_PHY_ADDR_S) |
+ AR8216_MDIO_CTRL_MASTER_EN |
+ AR8216_MDIO_CTRL_BUSY |
+ AR8216_MDIO_CTRL_CMD_READ;
+
+ ar8xxx_write(priv, AR8216_REG_MDIO_CTRL, t);
+ err = ar8xxx_reg_wait(priv, AR8216_REG_MDIO_CTRL,
+ AR8216_MDIO_CTRL_BUSY, 0, 5);
+ if (!err)
+ val = ar8xxx_read(priv, AR8216_REG_MDIO_CTRL);
+
+ return val & AR8216_MDIO_CTRL_DATA_M;
+}
+
+static int
+ar8216_phy_write(struct ar8xxx_priv *priv, int addr, int regnum, u16 val)
+{
+ u32 t;
+ int ret;
+
+ if (addr >= AR8216_NUM_PORTS)
+ return -EINVAL;
+
+ t = (addr << AR8216_MDIO_CTRL_PHY_ADDR_S) |
+ (regnum << AR8216_MDIO_CTRL_REG_ADDR_S) |
+ AR8216_MDIO_CTRL_MASTER_EN |
+ AR8216_MDIO_CTRL_BUSY |
+ AR8216_MDIO_CTRL_CMD_WRITE |
+ val;
+
+ ar8xxx_write(priv, AR8216_REG_MDIO_CTRL, t);
+ ret = ar8xxx_reg_wait(priv, AR8216_REG_MDIO_CTRL,
+ AR8216_MDIO_CTRL_BUSY, 0, 5);
+
+ return ret;
+}
+
+static int
ar8229_hw_init(struct ar8xxx_priv *priv)
{
int phy_if_mode;
@@ -1870,6 +1916,8 @@ static const struct ar8xxx_chip ar8229_chip = {
.hw_init = ar8229_hw_init,
.init_globals = ar8229_init_globals,
.init_port = ar8229_init_port,
+ .phy_read = ar8216_phy_read,
+ .phy_write = ar8216_phy_write,
.setup_port = ar8236_setup_port,
.read_port_status = ar8216_read_port_status,
.atu_flush = ar8216_atu_flush,
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.h b/target/linux/generic/files/drivers/net/phy/ar8216.h
index 0444bf7f22..975ba23517 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.h
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.h
@@ -152,6 +152,15 @@
#define AR8216_GLOBAL_CPUPORT_MIRROR_PORT_S 4
#define AR8216_GLOBAL_CPUPORT_EN BIT(8)
+#define AR8216_REG_MDIO_CTRL 0x98
+#define AR8216_MDIO_CTRL_DATA_M BITS(0, 16)
+#define AR8216_MDIO_CTRL_REG_ADDR_S 16
+#define AR8216_MDIO_CTRL_PHY_ADDR_S 21
+#define AR8216_MDIO_CTRL_CMD_WRITE 0
+#define AR8216_MDIO_CTRL_CMD_READ BIT(27)
+#define AR8216_MDIO_CTRL_MASTER_EN BIT(30)
+#define AR8216_MDIO_CTRL_BUSY BIT(31)
+
#define AR8216_PORT_OFFSET(_i) (0x0100 * (_i + 1))
#define AR8216_REG_PORT_STATUS(_i) (AR8216_PORT_OFFSET(_i) + 0x0000)
#define AR8216_PORT_STATUS_SPEED BITS(0,2)