diff --git a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso index 53d1999b6a51b9..43fb91f6424e99 100644 --- a/arch/arm64/boot/dts/ti/k3-am654-idk.dtso +++ b/arch/arm64/boot/dts/ti/k3-am654-idk.dtso @@ -179,6 +179,7 @@ AM65X_IOPAD(0x0220, PIN_OUTPUT, 2) /* (AB25) PRG0_PRU0_GPO11.PRG0_RGMII1_TX_CTL */ AM65X_IOPAD(0x020c, PIN_INPUT, 2) /* (Y25) PRG0_PRU0_GPO6.PRG0_RGMII1_RXC */ AM65X_IOPAD(0x0204, PIN_INPUT, 2) /* (Y24) PRG0_PRU0_GPO4.PRG0_RGMII1_RX_CTL */ + AM65X_IOPAD(0x026c, PIN_INPUT, 1) /* (AA28) PRG0_PRU1_GPO10.PRG0_PRU1_GPI10 */ >; }; diff --git a/drivers/net/ethernet/ti/icss_mii_rt.h b/drivers/net/ethernet/ti/icss_mii_rt.h index cecd46e52362f3..93422e12c36327 100644 --- a/drivers/net/ethernet/ti/icss_mii_rt.h +++ b/drivers/net/ethernet/ti/icss_mii_rt.h @@ -98,24 +98,34 @@ #define RGMII_CFG_GIG_EN_MII1 BIT(21) #define RGMII_CFG_FULL_DUPLEX_MII0 BIT(18) #define RGMII_CFG_FULL_DUPLEX_MII1 BIT(22) +#define RGMII_CFG_RGMII0_INBAND BIT(16) +#define RGMII_CFG_RGMII1_INBAND BIT(20) -static inline void icssg_update_rgmii_cfg(struct regmap *miig_rt, bool gig_en, +static inline void icssg_update_rgmii_cfg(struct regmap *miig_rt, int speed, bool full_duplex, int mii) { - u32 gig_en_mask, gig_val = 0, full_duplex_mask, full_duplex_val = 0; + u32 gig_en_mask, val = 0, full_duplex_mask, inband; gig_en_mask = (mii == ICSS_MII0) ? RGMII_CFG_GIG_EN_MII0 : RGMII_CFG_GIG_EN_MII1; - if (gig_en) - gig_val = gig_en_mask; - regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, gig_en_mask, gig_val); + inband = (mii == ICSS_MII0) ? RGMII_CFG_RGMII0_INBAND : + RGMII_CFG_RGMII1_INBAND; + if (speed == SPEED_1000) + val = gig_en_mask; + + regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, gig_en_mask, val); + + val = 0; + if (speed != SPEED_1000) + val = inband; + regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, inband, val); full_duplex_mask = (mii == ICSS_MII0) ? RGMII_CFG_FULL_DUPLEX_MII0 : RGMII_CFG_FULL_DUPLEX_MII1; + val = 0; if (full_duplex) - full_duplex_val = full_duplex_mask; - regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, full_duplex_mask, - full_duplex_val); + val = full_duplex_mask; + regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, full_duplex_mask, val); } static inline void icssg_update_mii_rt_cfg(struct regmap *mii_rt, int speed, @@ -132,8 +142,12 @@ static inline void icssg_update_mii_rt_cfg(struct regmap *mii_rt, int speed, case SPEED_100: val = MII_RT_TX_IPG_100M; break; + case SPEED_10: + /* IPG is not available for this speed in this version of + * ICSSG. Firmware use a hardcoded value for 10M link + */ + return; default: - /* Other links speeds not supported */ pr_err("Unsupported link speed\n"); return; } diff --git a/drivers/net/ethernet/ti/icssg_config.h b/drivers/net/ethernet/ti/icssg_config.h index 274279cf1889fd..9fdfa213e85816 100644 --- a/drivers/net/ethernet/ti/icssg_config.h +++ b/drivers/net/ethernet/ti/icssg_config.h @@ -26,6 +26,10 @@ struct icssg_config { __le32 n_burst; /* for debug */ __le32 rtu_status; /* RTU status */ __le32 info; /* reserved */ + __le32 reserve; + __le32 rand_seed; /* Used for the random number + * generation at firmware + */ } __packed; #endif /* __NET_TI_ICSSG_CONFIG_H */ diff --git a/drivers/net/ethernet/ti/icssg_prueth.c b/drivers/net/ethernet/ti/icssg_prueth.c index b9f72674b7fc0c..11b14fdc946b1f 100644 --- a/drivers/net/ethernet/ti/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg_prueth.c @@ -883,6 +883,7 @@ static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac) config->num_tx_threads = 0; config->rx_flow_id = emac->rx_flow_id_base; /* flow id for host port */ config->rx_mgr_flow_id = emac->rx_mgm_flow_id_base; /* for mgm ch */ + config->rand_seed = get_random_int(); /* set buffer sizes for the pools. 0-7 are not used for dual-emac */ for (i = PRUETH_EMAC_BUF_POOL_START; @@ -932,14 +933,24 @@ static void prueth_emac_stop(struct prueth_emac *emac) rproc_shutdown(prueth->pru[slice]); } +static void emac_set_default_mii_config(struct prueth_emac *emac) +{ + struct prueth *prueth = emac->prueth; + int slice = prueth_emac_slice(emac); + + icssg_update_rgmii_cfg(prueth->miig_rt, SPEED_10, + false, slice); + icssg_update_mii_rt_cfg(prueth->mii_rt, SPEED_10, slice); +} + /* called back by PHY layer if there is change in link state of hw port*/ static void emac_adjust_link(struct net_device *ndev) { struct prueth_emac *emac = netdev_priv(ndev); struct phy_device *phydev = emac->phydev; - bool gig_en = false, full_duplex = false; struct prueth *prueth = emac->prueth; int slice = prueth_emac_slice(emac); + bool full_duplex = false; bool new_state = false; unsigned long flags; @@ -963,12 +974,8 @@ static void emac_adjust_link(struct net_device *ndev) new_state = true; emac->link = 0; /* defaults for no link */ - - /* f/w should support 100 & 1000 */ - emac->speed = SPEED_1000; - - /* half duplex may not be supported by f/w */ - emac->duplex = DUPLEX_FULL; + emac->speed = SPEED_10; + emac->duplex = DUPLEX_HALF; } if (new_state) { @@ -978,23 +985,28 @@ static void emac_adjust_link(struct net_device *ndev) * values */ if (emac->link) { - if (phydev->speed == SPEED_1000) - gig_en = true; - if (phydev->duplex == DUPLEX_FULL) full_duplex = true; + if (!full_duplex) { + void __iomem *va = prueth->shram.va + + slice * ICSSG_CONFIG_OFFSET_SLICE1; + struct icssg_config *config = + (struct icssg_config *)va; + u32 val = get_random_int(); + + writel(val, &config->rand_seed); + } + /* Set the RGMII cfg for gig en and full duplex */ - icssg_update_rgmii_cfg(prueth->miig_rt, gig_en, + icssg_update_rgmii_cfg(prueth->miig_rt, emac->speed, full_duplex, slice); + /* update the Tx IPG based on 100M/1G speed */ icssg_update_mii_rt_cfg(prueth->mii_rt, emac->speed, slice); } else { - icssg_update_rgmii_cfg(prueth->miig_rt, true, true, - emac->port_id); - icssg_update_mii_rt_cfg(prueth->mii_rt, emac->speed, - slice); + emac_set_default_mii_config(emac); } } @@ -1133,6 +1145,8 @@ static int emac_ndo_open(struct net_device *ndev) if (ret) goto free_rx_mgm_irq; + emac_set_default_mii_config(emac); + /* start PHY */ phy_start(emac->phydev);