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; @@ -477,6 +478,9 @@ ar8xxx_write(struct ar8xxx_priv *priv, int reg, u32 val); 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); 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 @@ -127,6 +127,49 @@ ar8327_get_pad_cfg(struct ar8327_pad_cfg *cfg) return t; } +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) { @@ -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,