aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8216.c15
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8216.h4
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8327.c44
-rw-r--r--target/linux/generic/files/drivers/net/phy/ar8327.h7
4 files changed, 69 insertions, 1 deletions
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.c b/target/linux/generic/files/drivers/net/phy/ar8216.c
index 68754e6096..2f0be1b8da 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.c
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.c
@@ -295,6 +295,17 @@ ar8xxx_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val)
return ret;
}
+void
+ar8xxx_phy_dbg_read(struct ar8xxx_priv *priv, int phy_addr,
+ u16 dbg_addr, u16 *dbg_data)
+{
+ struct mii_bus *bus = priv->mii_bus;
+
+ mutex_lock(&bus->mdio_lock);
+ bus->write(bus, phy_addr, MII_ATH_DBG_ADDR, dbg_addr);
+ *dbg_data = bus->read(bus, phy_addr, MII_ATH_DBG_DATA);
+ mutex_unlock(&bus->mdio_lock);
+}
void
ar8xxx_phy_dbg_write(struct ar8xxx_priv *priv, int phy_addr,
@@ -2166,7 +2177,7 @@ ar8xxx_phy_probe(struct phy_device *phydev)
int ret;
/* skip PHYs at unused adresses */
- if (phydev->mdio.addr != 0 && phydev->mdio.addr != 4)
+ if (phydev->mdio.addr != 0 && phydev->mdio.addr != 3 && phydev->mdio.addr != 4)
return -ENODEV;
if (!ar8xxx_is_possible(phydev->mdio.bus))
@@ -2225,6 +2236,8 @@ found:
phydev->supported |= SUPPORTED_1000baseT_Full;
phydev->advertising |= ADVERTISED_1000baseT_Full;
}
+ if (priv->chip->phy_rgmii_set)
+ priv->chip->phy_rgmii_set(priv, phydev);
}
phydev->priv = priv;
diff --git a/target/linux/generic/files/drivers/net/phy/ar8216.h b/target/linux/generic/files/drivers/net/phy/ar8216.h
index 509818c50d..33f505cbe2 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8216.h
+++ b/target/linux/generic/files/drivers/net/phy/ar8216.h
@@ -413,6 +413,7 @@ struct ar8xxx_chip {
void (*get_arl_entry)(struct ar8xxx_priv *priv, struct arl_entry *a,
u32 *status, enum arl_op op);
int (*sw_hw_apply)(struct switch_dev *dev);
+ void (*phy_rgmii_set)(struct ar8xxx_priv *priv, struct phy_device *phydev);
const struct ar8xxx_mib_desc *mib_decs;
unsigned num_mibs;
@@ -478,6 +479,9 @@ u32
ar8xxx_rmw(struct ar8xxx_priv *priv, int reg, u32 mask, u32 val);
void
+ar8xxx_phy_dbg_read(struct ar8xxx_priv *priv, int phy_addr,
+ u16 dbg_addr, u16 *dbg_data);
+void
ar8xxx_phy_dbg_write(struct ar8xxx_priv *priv, int phy_addr,
u16 dbg_addr, u16 dbg_data);
void
diff --git a/target/linux/generic/files/drivers/net/phy/ar8327.c b/target/linux/generic/files/drivers/net/phy/ar8327.c
index 803fb3d49f..170c3e43a3 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8327.c
+++ b/target/linux/generic/files/drivers/net/phy/ar8327.c
@@ -128,6 +128,49 @@ ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg)
}
static void
+ar8327_phy_rgmii_set(struct ar8xxx_priv *priv, struct phy_device *phydev)
+{
+ u16 phy_val = 0;
+ int phyaddr = phydev->mdio.addr;
+ struct device_node *np = phydev->mdio.dev.of_node;
+
+ if (!np)
+ return;
+
+ if (!of_property_read_bool(np, "qca,phy-rgmii-en")) {
+ pr_err("ar8327: qca,phy-rgmii-en is not specified\n");
+ return -EINVAL;
+ }
+ ar8xxx_phy_dbg_read(priv, phyaddr,
+ AR8327_PHY_MODE_SEL, &phy_val);
+ phy_val |= AR8327_PHY_MODE_SEL_RGMII;
+ ar8xxx_phy_dbg_write(priv, phyaddr,
+ AR8327_PHY_MODE_SEL, phy_val);
+
+ /* set rgmii tx clock delay if needed */
+ if (!of_property_read_bool(np, "qca,txclk-delay-en")) {
+ pr_err("ar8327: qca,txclk-delay-en is not specified\n");
+ return -EINVAL;
+ }
+ ar8xxx_phy_dbg_read(priv, phyaddr,
+ AR8327_PHY_SYS_CTRL, &phy_val);
+ phy_val |= AR8327_PHY_SYS_CTRL_RGMII_TX_DELAY;
+ ar8xxx_phy_dbg_write(priv, phyaddr,
+ AR8327_PHY_SYS_CTRL, phy_val);
+
+ /* set rgmii rx clock delay if needed */
+ if (!of_property_read_bool(np, "qca,rxclk-delay-en")) {
+ pr_err("ar8327: qca,rxclk-delay-en is not specified\n");
+ return -EINVAL;
+ }
+ ar8xxx_phy_dbg_read(priv, phyaddr,
+ AR8327_PHY_TEST_CTRL, &phy_val);
+ phy_val |= AR8327_PHY_TEST_CTRL_RGMII_RX_DELAY;
+ ar8xxx_phy_dbg_write(priv, phyaddr,
+ AR8327_PHY_TEST_CTRL, phy_val);
+}
+
+static void
ar8327_phy_fixup(struct ar8xxx_priv *priv, int phy)
{
switch (priv->chip_rev) {
@@ -1490,6 +1533,7 @@ const struct ar8xxx_chip ar8337_chip = {
.set_mirror_regs = ar8327_set_mirror_regs,
.get_arl_entry = ar8327_get_arl_entry,
.sw_hw_apply = ar8327_sw_hw_apply,
+ .phy_rgmii_set = ar8327_phy_rgmii_set,
.num_mibs = ARRAY_SIZE(ar8236_mibs),
.mib_decs = ar8236_mibs,
diff --git a/target/linux/generic/files/drivers/net/phy/ar8327.h b/target/linux/generic/files/drivers/net/phy/ar8327.h
index 38e33ea57e..a59d306d6f 100644
--- a/target/linux/generic/files/drivers/net/phy/ar8327.h
+++ b/target/linux/generic/files/drivers/net/phy/ar8327.h
@@ -284,6 +284,13 @@
#define AR8337_PAD_MAC06_EXCHANGE_EN BIT(31)
+#define AR8327_PHY_MODE_SEL 0x12
+#define AR8327_PHY_MODE_SEL_RGMII BIT(3)
+#define AR8327_PHY_TEST_CTRL 0x0
+#define AR8327_PHY_TEST_CTRL_RGMII_RX_DELAY BIT(15)
+#define AR8327_PHY_SYS_CTRL 0x5
+#define AR8327_PHY_SYS_CTRL_RGMII_TX_DELAY BIT(8)
+
enum ar8327_led_pattern {
AR8327_LED_PATTERN_OFF = 0,
AR8327_LED_PATTERN_BLINK,