From 82c05e91fa27672e250580abd01cebc84a3b18b4 Mon Sep 17 00:00:00 2001 From: Vandhiadevan Karunamoorthy Date: Fri, 26 Jun 2020 15:54:19 +0530 Subject: [PATCH] ipq5018: Fix S17C auto-negotiation issue This changes enable s17c link upto 1Gbps speed. Signed-off-by: Vandhiadevan Karunamoorthy Change-Id: I78e3efbbfd1bad58ab2abcba87c06cb9d4ffcd18 --- .../include/asm/arch-ipq5018/ipq5018_gmac.h | 6 +++ board/qca/arm/ipq5018/ipq5018.c | 34 +++++------- drivers/net/ipq5018/ipq5018_gmac.c | 52 ++++++++++++++----- drivers/net/ipq5018/ipq5018_uniphy.c | 37 ++++++++----- drivers/net/ipq5018/ipq5018_uniphy.h | 4 ++ 5 files changed, 86 insertions(+), 47 deletions(-) diff --git a/arch/arm/include/asm/arch-ipq5018/ipq5018_gmac.h b/arch/arm/include/asm/arch-ipq5018/ipq5018_gmac.h index bb2aedb07e..630c041b41 100644 --- a/arch/arm/include/asm/arch-ipq5018/ipq5018_gmac.h +++ b/arch/arm/include/asm/arch-ipq5018/ipq5018_gmac.h @@ -17,6 +17,12 @@ #include #include +#define LINK(_data) (_data & 0x400)? "Up" : "Down" +#define DUPLEX(_data) (_data & 0x2000)? "Full duplex" : "Half duplex" +#define SPEED(_data) ((_data & 0xC000) >> 12) +#define SPEED_1000M (1 << 3) +#define SPEED_100M (1 << 2) + #define GEPHY 0x004DD0C0 #define S17C 0x1302 diff --git a/board/qca/arm/ipq5018/ipq5018.c b/board/qca/arm/ipq5018/ipq5018.c index e7fe245e0c..3f91989520 100644 --- a/board/qca/arm/ipq5018/ipq5018.c +++ b/board/qca/arm/ipq5018/ipq5018.c @@ -48,6 +48,9 @@ struct sdhci_host mmc_host; extern int ipq_spi_init(u16); #endif +extern void ppe_uniphy_set_forceMode(void); +extern void ppe_uniphy_refclk_set(void); + unsigned int qpic_frequency = 0, qpic_phase = 0; const char *rsvd_node = "/reserved-memory"; @@ -618,7 +621,7 @@ static void set_ext_mdio_gpio(int node) { unsigned int mdio_gpio[2] = {0}; int status = -1; - unsigned int *s17C_gpio_base; + unsigned int *mdio_gpio_base; status = fdtdec_get_int_array(gd->fdt_blob, node, @@ -627,13 +630,13 @@ static void set_ext_mdio_gpio(int node) 2); if (status >= 0) { /* mdc */ - s17C_gpio_base = + mdio_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(mdio_gpio[0]); - writel(0x7, s17C_gpio_base); + writel(0x7, mdio_gpio_base); /* mdio */ - s17C_gpio_base = + mdio_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(mdio_gpio[1]); - writel(0x7, s17C_gpio_base); + writel(0x7, mdio_gpio_base); } } @@ -652,6 +655,11 @@ static void reset_s17c_switch_gpio(int gpio) { unsigned int *switch_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(gpio); +/* + * Set ref clock 25MHZ and enable Force mode + */ + ppe_uniphy_refclk_set(); + ppe_uniphy_set_forceMode(); writel(0x203, switch_gpio_base); writel(0x0, GPIO_IN_OUT_ADDR(gpio)); @@ -878,21 +886,6 @@ static void cmnblk_check_state(void) } } -static void uniphy_refclk_set(void) -{ -/* - * This function drive the uniphy ref clock - * DEC_REFCLKOUTPUTCONTROLREGISTERS - * Its is configured as 25 MHZ - */ -#define UNIPHY_REF_CLK_CTRL_REG 0x98074 - - u32 reg_val = readl(UNIPHY_REF_CLK_CTRL_REG); - reg_val |= 0x2; - writel(reg_val, UNIPHY_REF_CLK_CTRL_REG); - mdelay(500); -} - static void gcc_clock_enable(void) { u32 reg_val; @@ -968,7 +961,6 @@ static void ethernet_clock_enable(void) gephy_reset(); uniphy_reset(); gmac_reset(); - uniphy_refclk_set(); gcc_clock_enable(); } diff --git a/drivers/net/ipq5018/ipq5018_gmac.c b/drivers/net/ipq5018/ipq5018_gmac.c index f436b9d7a1..2fc0c524f5 100644 --- a/drivers/net/ipq5018/ipq5018_gmac.c +++ b/drivers/net/ipq5018/ipq5018_gmac.c @@ -303,6 +303,38 @@ static void ipq5018_enable_gephy(void) mdelay(20); } +static int ipq5018_s17c_Link_Update(struct ipq_eth_dev *priv) +{ + uint16_t phy_data; + int status = 1; + + for(int i = 0; + i < priv->gmac_board_cfg->switch_port_count; ++i){ + phy_data = ipq_mdio_read( + priv->gmac_board_cfg->switch_port_phy_address[i], + 0x11, + NULL); + if (phy_data == 0x50) + continue; + status = 0; + printf("Port%d %s ", i + 1, LINK(phy_data)); + + switch(SPEED(phy_data)){ + case SPEED_1000M: + printf("Speed :1000M "); + break; + case SPEED_100M: + printf("Speed :100M "); + break; + default: + printf("Speed :10M "); + } + + printf ("%s \n", DUPLEX(phy_data)); + } + return status; +} + static int ipq5018_phy_link_update(struct eth_device *dev) { struct ipq_eth_dev *priv = dev->priv; @@ -328,7 +360,7 @@ static int ipq5018_phy_link_update(struct eth_device *dev) if (priv->ipq_swith) { speed_clock1 = 1; speed_clock2 = 0; - status = 0; + status = ipq5018_s17c_Link_Update(priv); } else { status = phy_get_ops->phy_get_link_status(priv->mac_unit, priv->phy_address); @@ -380,23 +412,23 @@ static int ipq5018_phy_link_update(struct eth_device *dev) } } + if (status) { + /* No PHY link is alive */ + return -1; + } + if (priv->mac_unit){ if (priv->phy_type == QCA8081_PHY_TYPE || priv->phy_type == QCA8081_1_1_PHY) ppe_uniphy_mode_set(PORT_WRAPPER_SGMII_PLUS); else - ppe_uniphy_mode_set(PORT_WRAPPER_SGMII_FIBER); + ppe_uniphy_mode_set(PORT_WRAPPER_SGMII0_RGMII4); } else { ipq5018_enable_gephy(); } ipq5018_gmac0_speed_clock_set(speed_clock1, speed_clock2, priv->mac_unit); - if (status) { - /* No PHY link is alive */ - return -1; - } - return 0; } @@ -665,8 +697,6 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg) for (int port = 0; port < gmac_cfg->switch_port_count; ++port) { - u32 value; - ipq_mdio_write(port, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); /* @@ -674,12 +704,8 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg) */ ipq_mdio_write(port, MII_CTRL1000, (0x0400|ADVERTISE_1000FULL)); ipq_mdio_write(port, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); - value = ipq_mdio_read(port, 0, NULL); - value &= (~(1<<12)); - ipq_mdio_write(port, 0, value); mdelay(100); } - } else { phy_chip_id1 = ipq_mdio_read( ipq_gmac_macs[i]->phy_address, diff --git a/drivers/net/ipq5018/ipq5018_uniphy.c b/drivers/net/ipq5018/ipq5018_uniphy.c index b0b0228529..d3edde505d 100644 --- a/drivers/net/ipq5018/ipq5018_uniphy.c +++ b/drivers/net/ipq5018/ipq5018_uniphy.c @@ -59,8 +59,6 @@ static void ppe_gcc_uniphy_soft_reset(void) static void ppe_uniphy_sgmii_mode_set(uint32_t mode) { - bool force_enable =false; - writel(UNIPHY_MISC2_REG_SGMII_MODE, PPE_UNIPHY_BASE + UNIPHY_MISC2_REG_OFFSET); @@ -83,7 +81,6 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t mode) switch (mode) { case PORT_WRAPPER_SGMII_FIBER: writel(UNIPHY_SG_MODE, PPE_UNIPHY_BASE + PPE_UNIPHY_MODE_CONTROL); - force_enable = true; break; case PORT_WRAPPER_SGMII0_RGMII4: @@ -91,7 +88,6 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t mode) case PORT_WRAPPER_SGMII4_RGMII4: writel((UNIPHY_SG_MODE | UNIPHY_PSGMII_MAC_MODE), PPE_UNIPHY_BASE + PPE_UNIPHY_MODE_CONTROL); - force_enable = true; break; case PORT_WRAPPER_SGMII_PLUS: @@ -116,15 +112,6 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t mode) udelay(500); ppe_uniphy_calibration(); - -/* - * Force Speed mode enable - */ - if(force_enable){ - writel((readl(PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4) | - UNIPHY_FORCE_SPEED_25M), - PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4); - } } void ppe_uniphy_mode_set(uint32_t mode) @@ -135,3 +122,27 @@ void ppe_uniphy_mode_set(uint32_t mode) ppe_uniphy_sgmii_mode_set(mode); } +void ppe_uniphy_set_forceMode(void) +{ + uint32_t reg_value; + + reg_value = readl(PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4); + reg_value |= UNIPHY_FORCE_SPEED_25M; + + writel(reg_value, PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4); + +} + +void ppe_uniphy_refclk_set(void) +{ +/* + * This function drive the uniphy ref clock + * DEC_REFCLKOUTPUTCONTROLREGISTERS + * Its is configured as 25 MHZ + */ + + u32 reg_val = readl(PPE_UNIPHY_BASE | UNIPHY_REF_CLK_CTRL_REG); + reg_val |= 0x2; + writel(reg_val, PPE_UNIPHY_BASE | UNIPHY_REF_CLK_CTRL_REG); + mdelay(200); +} diff --git a/drivers/net/ipq5018/ipq5018_uniphy.h b/drivers/net/ipq5018/ipq5018_uniphy.h index ad4645d614..3b606636b0 100644 --- a/drivers/net/ipq5018/ipq5018_uniphy.h +++ b/drivers/net/ipq5018/ipq5018_uniphy.h @@ -46,6 +46,8 @@ #define UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4 0x480 #define UNIPHY_FORCE_SPEED_25M (1 << 3) +#define UNIPHY_REF_CLK_CTRL_REG 0x74 + #define UNIPHY_INSTANCE_LINK_DETECT 0x570 #define UNIPHY_MISC2_REG_OFFSET 0x218 @@ -59,4 +61,6 @@ #define UNIPHY_PLL_RESET_REG_DEFAULT_VALUE 0x02ff void ppe_uniphy_mode_set(uint32_t mode); +void ppe_uniphy_set_forceMode(void); +void ppe_uniphy_refclk_set(void); #endif