diff --git a/arch/arm/dts/ipq5332-mi03.1.dts b/arch/arm/dts/ipq5332-mi03.1.dts index 6004997c1e..54d2a635d0 100644 --- a/arch/arm/dts/ipq5332-mi03.1.dts +++ b/arch/arm/dts/ipq5332-mi03.1.dts @@ -72,4 +72,57 @@ }; }; }; + + ess-switch { + switch_mac_mode0 = ; + switch_mac_mode1 = ; + qca8337_rst_gpio = <22>; + qca8033_gpio_cnt = <1>; + qca8033_gpio = <31>; + qca8337_switch_enable = <1>; + + mdio_gpio { + mdc1 { + gpio = <27>; + func = <1>; + pull = ; + drvstr = ; + }; + mdio { + gpio = <28>; + func = <1>; + pull = ; + drvstr = ; + }; + }; + + port_phyinfo { + port@0 { + phy_address = <0>; + uniphy_id = <0>; + phy_type = ; + uniphy_mode = ; + }; + port@1 { + phy_address = <5>; + phy_type = ; + uniphy_id = <1>; + uniphy_mode = ; + }; + }; + + qca8337_swt_info { + mac_pwr = <0xaa545>; + port_count = <3>; + update = <1>; + pad0_mode = <0x80>; + pad5_mode = <0>; + pad6_mode = <0>; + port0 = <0x2613a0>; + sgmii_ctrl = <0xc74164de>; + port0_status = <0x4e>; + port6_status = <0>; + port_phy_address = <2 3 4>; + }; + }; }; diff --git a/board/qca/arm/ipq5332/ipq5332.c b/board/qca/arm/ipq5332/ipq5332.c index 8105983d7b..745fb5ec51 100644 --- a/board/qca/arm/ipq5332/ipq5332.c +++ b/board/qca/arm/ipq5332/ipq5332.c @@ -792,6 +792,27 @@ int get_qca808x_gpio(int qca808x_gpio[2]) return res; } +int get_qca8033_gpio(int qca8033_gpio[2]) +{ + int qca8033_gpio_cnt = -1, node; + int res = -1; + + node = fdt_path_offset(gd->fdt_blob, "/ess-switch"); + if (node >= 0) { + qca8033_gpio_cnt = + fdtdec_get_uint(gd->fdt_blob, node, + "qca8033_gpio_cnt", -1); + if (qca8033_gpio_cnt >= 1) { + res = fdtdec_get_int_array(gd->fdt_blob, node, + "qca8033_gpio", (u32 *)qca8033_gpio, + qca8033_gpio_cnt); + if (res >= 0) + return qca8033_gpio_cnt; + } + } + + return res; +} void aquantia_phy_reset_init(void) { int aquantia_gpio[2] = {-1, -1}, aquantia_gpio_cnt, i; @@ -918,6 +939,29 @@ void qca8081_napa_reset(void) } } +void qca8033_phy_reset(void) +{ + int qca8033_gpio[2] = {-1, -1}, qca8033_gpio_cnt, i; + unsigned int *qca8033_gpio_base; + uint32_t cfg; + + qca8033_gpio_cnt = get_qca8033_gpio(qca8033_gpio); + if (qca8033_gpio_cnt >= 1) { + for (i = 0; i < qca8033_gpio_cnt; i++) { + if (qca8033_gpio[i] >= 0) { + qca8033_gpio_base = + (unsigned int *)GPIO_CONFIG_ADDR( + qca8033_gpio[i]); + cfg = GPIO_OE | GPIO_DRV_2_MA | GPIO_PULL_UP; + writel(cfg, qca8033_gpio_base); + writel(0x0, GPIO_IN_OUT_ADDR(qca8033_gpio[i])); + mdelay(100); + writel(0x3, GPIO_IN_OUT_ADDR(qca8033_gpio[i])); + } + } + } +} + void bring_phy_out_of_reset(void) { qca8081_napa_reset(); diff --git a/drivers/net/ipq5332/ipq5332_edma.c b/drivers/net/ipq5332/ipq5332_edma.c index 592baaa329..e824cdf43b 100644 --- a/drivers/net/ipq5332/ipq5332_edma.c +++ b/drivers/net/ipq5332/ipq5332_edma.c @@ -74,9 +74,10 @@ extern int ipq_qca8084_hw_init(phy_info_t * phy_info[]); extern int ipq_qca8084_link_update(phy_info_t * phy_info[]); extern void ipq_qca8084_switch_hw_reset(int gpio); extern void ipq5332_xgmac_sgmiiplus_speed_set(int port, int speed, int status); +extern void ppe_uniphy_refclk_set_25M(uint32_t uniphy_index); +extern void qca8033_phy_reset(void); #ifdef CONFIG_ATHRS17C_SWITCH extern void ppe_uniphy_set_forceMode(uint32_t uniphy_index); - extern int ipq_qca8337_switch_init(ipq_s17c_swt_cfg_t *s17c_swt_cfg); extern int ipq_qca8337_link_update(ipq_s17c_swt_cfg_t *s17c_swt_cfg); extern void ipq_s17c_switch_reset(int gpio); @@ -1018,7 +1019,8 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) clk[1] = 9; clk[2] = 0x418; clk[3] = 9; - if (phy_info->phy_type == QCA8081_PHY_TYPE) { + if ((phy_info->phy_type == QCA8081_PHY_TYPE) || + (phy_info->phy_type == QCA8033_PHY_TYPE)) { clk[1] = 3; clk[3] = 3; } @@ -1030,7 +1032,8 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) clk[2] = 0x418; clk[3] = 1; if ((phy_info->phy_type == QCA8081_PHY_TYPE) || - (phy_info->phy_type == QCA8084_PHY_TYPE)) { + (phy_info->phy_type == QCA8084_PHY_TYPE) || + (phy_info->phy_type == QCA8033_PHY_TYPE)) { clk[0] = 0x309; clk[1] = 0; clk[2] = 0x409; @@ -1044,7 +1047,8 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) clk[2] = 0x404; clk[3] = 0x0; if ((phy_info->phy_type == QCA8081_PHY_TYPE) || - (phy_info->phy_type == QCA8084_PHY_TYPE)) { + (phy_info->phy_type == QCA8084_PHY_TYPE) || + (phy_info->phy_type == QCA8033_PHY_TYPE)) { clk[0] = 0x301; clk[2] = 0x401; } @@ -1094,6 +1098,7 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) } if ((phy_info->phy_type == QCA8081_PHY_TYPE) || + (phy_info->phy_type == QCA8033_PHY_TYPE) || (phy_info->phy_type == QCA8084_PHY_TYPE)) { ppe_port_bridge_txmac_set(i, 1); ppe_uniphy_mode_set(port_info[i]->uniphy_id, @@ -1762,25 +1767,37 @@ int ipq5332_edma_init(void *edma_board_cfg) #ifdef CONFIG_ATHRS17C_SWITCH s17c_swt_enb = fdtdec_get_uint(gd->fdt_blob, node, - "s17c_switch_enable", 0); + "qca8337_switch_enable", 0); if (s17c_swt_enb) { s17c_swt_cfg.chip_detect = 0; s17c_rst_gpio = fdtdec_get_uint(gd->fdt_blob, node, - "s17c_rst_gpio", 0); + "qca8337_rst_gpio", 0); ipq_s17c_switch_reset(s17c_rst_gpio); - /* - * Set ref clock 25MHZ and enable Force mode - */ - ppe_uniphy_set_forceMode(PORT0); phy_node = fdt_path_offset(gd->fdt_blob, - "/ess-switch/s17c_swt_info"); + "/ess-switch/qca8337_swt_info"); + s17c_swt_cfg.update = fdtdec_get_uint(gd->fdt_blob, + phy_node, "update", 0); + s17c_swt_cfg.pad0_mode = fdtdec_get_uint(gd->fdt_blob, + phy_node, "pad0_mode", 0); + s17c_swt_cfg.pad5_mode = fdtdec_get_uint(gd->fdt_blob, + phy_node, "pad5_mode", 0); + s17c_swt_cfg.pad6_mode = fdtdec_get_uint(gd->fdt_blob, + phy_node, "pad6_mode", 0); + s17c_swt_cfg.port0 = fdtdec_get_uint(gd->fdt_blob, + phy_node, "port0", 0); + s17c_swt_cfg.sgmii_ctrl = fdtdec_get_uint(gd->fdt_blob, + phy_node, "sgmii_ctrl", 0); + s17c_swt_cfg.port0_status = fdtdec_get_uint(gd->fdt_blob, + phy_node, "port0_status", 0); + s17c_swt_cfg.port6_status = fdtdec_get_uint(gd->fdt_blob, + phy_node, "port6_status", 0); s17c_swt_cfg.port_count = fdtdec_get_uint(gd->fdt_blob, - phy_node, "s17c_mac_pwr", 0); - s17c_swt_cfg.port_count = fdtdec_get_uint(gd->fdt_blob, - phy_node, "s17c_port_count", 0); + phy_node, "port_count", 0); + s17c_swt_cfg.mac_pwr = fdtdec_get_uint(gd->fdt_blob, + phy_node, "mac_pwr", 0); fdtdec_get_int_array(gd->fdt_blob, phy_node, - "s17c_port_address", + "port_phy_address", s17c_swt_cfg.port_phy_address, s17c_swt_cfg.port_count); } @@ -1884,6 +1901,15 @@ int ipq5332_edma_init(void *edma_board_cfg) ipq_clock_init(); qca8084_init_done = 1; } +#endif +#ifdef CONFIG_QCA8033_PHY + if (phy_info->phy_type == QCA8033_PHY_TYPE) { + ppe_uniphy_refclk_set_25M( + port_info[phy_id]->uniphy_id); + mdelay(10); + qca8033_phy_reset(); + mdelay(100); + } #endif if (phy_info->phy_type == AQ_PHY_TYPE) { phy_chip_id1 = ipq_mdio_read(phy_addr, @@ -1962,8 +1988,13 @@ int ipq5332_edma_init(void *edma_board_cfg) #endif #ifdef CONFIG_ATHRS17C_SWITCH case QCA8337_PHY: - if (s17c_swt_enb) + if (s17c_swt_enb) { + ppe_uniphy_set_forceMode( + port_info[phy_id]->uniphy_id); + ppe_uniphy_refclk_set_25M( + port_info[phy_id]->uniphy_id); s17c_swt_cfg.chip_detect = 1; + } break; #endif #ifdef CONFIG_IPQ_QCA_AQUANTIA_PHY @@ -2000,9 +2031,10 @@ int ipq5332_edma_init(void *edma_board_cfg) if (ret) goto init_failed; -#ifdef CONFIG_QCA8084_SWT_MODE - /** QCA8084 switch specific configurations */ - if (qca8084_swt_enb && qca8084_chip_detect) { +#if defined(CONFIG_QCA8084_SWT_MODE) || defined(CONFIG_ATHRS17C_SWITCH) + /** QCA8084 & QCA8337 switch specific configurations */ + if ((qca8084_swt_enb && qca8084_chip_detect) || + (s17c_swt_cfg.chip_detect == 1)) { #ifdef CONFIG_QCA8084_BYPASS_MODE if (qca8084_bypass_enb) @@ -2018,27 +2050,41 @@ int ipq5332_edma_init(void *edma_board_cfg) clk[2] = 0x401; clk[3] = 0x0; - pr_debug("Force speed ipq5332 1st PORT " - "for QCA8084 switch mode \n"); + pr_debug("Force speed for QCA8084 & QCA8337 " + "switch mode \n"); ipq5332_port_mac_clock_reset(PORT0); - - /** Force Link-speed: 1000M - * Force Link-status: enable */ - ipq5332_xgmac_sgmiiplus_speed_set(PORT0, 0x4, 0); +#if defined(CONFIG_QCA8084_SWT_MODE) + if (qca8084_chip_detect) { + /** Force Link-speed: 2500M + * Force Link-status: enable */ + ipq5332_xgmac_sgmiiplus_speed_set(PORT0, + 0x4, 0); + } else +#endif + { + /*Force Link-speed: 1000M */ + ipq5332_pqsgmii_speed_set(PORT0, 0x2, 0); + } ipq5332_speed_clock_set(PORT0, clk); - ret = ipq_qca8084_hw_init(swt_info); - if (ret < 0) { - printf("Error: qca8084 switch mode" - "hw_init failed \n"); - goto init_failed; +#if defined(CONFIG_QCA8084_SWT_MODE) + if (qca8084_chip_detect) { + ret = ipq_qca8084_hw_init(swt_info); + if (ret < 0) { + printf("Error: qca8084 switch mode" + "hw_init failed \n"); + goto init_failed; + } + } + else +#endif + { + ret = ipq_qca8337_switch_init(&s17c_swt_cfg); + if (ret < 0) + goto init_failed; } } -#endif -#ifdef CONFIG_ATHRS17C_SWITCH - if (s17c_swt_cfg.chip_detect) - ipq_qca8337_switch_init(&s17c_swt_cfg); #endif eth_register(dev[i]); } diff --git a/drivers/net/ipq5332/ipq5332_uniphy.c b/drivers/net/ipq5332/ipq5332_uniphy.c index f3415e341f..89a4b0c5b9 100644 --- a/drivers/net/ipq5332/ipq5332_uniphy.c +++ b/drivers/net/ipq5332/ipq5332_uniphy.c @@ -186,6 +186,19 @@ void ppe_uniphy_set_forceMode(uint32_t uniphy_index) + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4); } +void ppe_uniphy_refclk_set_25M(uint32_t uniphy_index) +{ + uint32_t reg_value; + + reg_value = readl(PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + UNIPHY1_CLKOUT_50M_CTRL_OPTION); + reg_value |= (UNIPHY1_CLKOUT_50M_CTRL_CLK50M_DIV2_SEL | + UNIPHY1_CLKOUT_50M_CTRL_50M_25M_EN); + + writel(reg_value, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC) + + UNIPHY1_CLKOUT_50M_CTRL_OPTION); +} + static void ppe_uniphy_sgmii_mode_set(uint32_t uniphy_index, uint32_t mode) { uint32_t reg_value; diff --git a/drivers/net/ipq5332/ipq5332_uniphy.h b/drivers/net/ipq5332/ipq5332_uniphy.h index 7f564f90d6..0c256884d8 100644 --- a/drivers/net/ipq5332/ipq5332_uniphy.h +++ b/drivers/net/ipq5332/ipq5332_uniphy.h @@ -47,6 +47,10 @@ #define UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4 0x480 #define UNIPHY_FORCE_SPEED_25M (1 << 3) +#define UNIPHY1_CLKOUT_50M_CTRL_OPTION 0x610 +#define UNIPHY1_CLKOUT_50M_CTRL_CLK50M_DIV2_SEL (1 << 5) +#define UNIPHY1_CLKOUT_50M_CTRL_50M_25M_EN 0x1 + #define UNIPHY_PLL_RESET_REG_OFFSET 0x780 #define UNIPHY_PLL_RESET_REG_VALUE 0x02bf #define UNIPHY_PLL_RESET_REG_DEFAULT_VALUE 0x02ff diff --git a/drivers/net/ipq_common/athrs17_phy.c b/drivers/net/ipq_common/athrs17_phy.c index 78e1c5f64e..72ee0784e8 100644 --- a/drivers/net/ipq_common/athrs17_phy.c +++ b/drivers/net/ipq_common/athrs17_phy.c @@ -198,23 +198,29 @@ void athrs17_reg_init(ipq_s17c_swt_cfg_t *swt_cfg) { athrs17_reg_write(S17_MAC_PWR_REG, swt_cfg->mac_pwr); - athrs17_reg_write(S17_P0STATUS_REG, (S17_SPEED_1000M | - S17_TXMAC_EN | - S17_RXMAC_EN | - S17_DUPLEX_FULL)); - athrs17_reg_write(S17_GLOFW_CTRL1_REG, (S17_IGMP_JOIN_LEAVE_DPALL | S17_BROAD_DPALL | S17_MULTI_FLOOD_DPALL | S17_UNI_FLOOD_DPALL)); - athrs17_reg_write(S17_P5PAD_MODE_REG, S17_MAC0_RGMII_RXCLK_DELAY); + if (swt_cfg->update) { + athrs17_reg_write(S17_P0STATUS_REG, swt_cfg->port0_status); + athrs17_reg_write(S17_P5PAD_MODE_REG, swt_cfg->pad5_mode); + athrs17_reg_write(S17_P0PAD_MODE_REG, swt_cfg->pad0_mode); + } else { + athrs17_reg_write(S17_P0STATUS_REG, (S17_SPEED_1000M | + S17_TXMAC_EN | + S17_RXMAC_EN | + S17_DUPLEX_FULL)); - athrs17_reg_write(S17_P0PAD_MODE_REG, (S17_MAC0_RGMII_EN | + athrs17_reg_write(S17_P5PAD_MODE_REG, S17_MAC0_RGMII_RXCLK_DELAY); + + athrs17_reg_write(S17_P0PAD_MODE_REG, (S17_MAC0_RGMII_EN | S17_MAC0_RGMII_TXCLK_DELAY | S17_MAC0_RGMII_RXCLK_DELAY | (0x1 << S17_MAC0_RGMII_TXCLK_SHIFT) | (0x2 << S17_MAC0_RGMII_RXCLK_SHIFT))); + } printf("%s: complete\n", __func__); } @@ -228,33 +234,41 @@ void athrs17_reg_init_lan(ipq_s17c_swt_cfg_t *swt_cfg) { uint32_t reg_val; - athrs17_reg_write(S17_P6STATUS_REG, (S17_SPEED_1000M | - S17_TXMAC_EN | - S17_RXMAC_EN | - S17_DUPLEX_FULL)); + if (swt_cfg->update) { + athrs17_reg_write(S17_P6STATUS_REG, swt_cfg->port6_status); + athrs17_reg_write(S17_MAC_PWR_REG, swt_cfg->mac_pwr); + athrs17_reg_write(S17_P6PAD_MODE_REG, swt_cfg->pad6_mode); + athrs17_reg_write(S17_PWS_REG, swt_cfg->port0); + athrs17_reg_write(S17_SGMII_CTRL_REG, swt_cfg->sgmii_ctrl); + } else { - athrs17_reg_write(S17_MAC_PWR_REG, swt_cfg->mac_pwr); - reg_val = athrs17_reg_read(S17_P6PAD_MODE_REG); - athrs17_reg_write(S17_P6PAD_MODE_REG, (reg_val | S17_MAC6_SGMII_EN)); + athrs17_reg_write(S17_P6STATUS_REG, (S17_SPEED_1000M | + S17_TXMAC_EN | + S17_RXMAC_EN | + S17_DUPLEX_FULL)); - athrs17_reg_write(S17_PWS_REG, 0x2613a0); + athrs17_reg_write(S17_MAC_PWR_REG, swt_cfg->mac_pwr); + reg_val = athrs17_reg_read(S17_P6PAD_MODE_REG); + athrs17_reg_write(S17_P6PAD_MODE_REG, (reg_val | S17_MAC6_SGMII_EN)); - athrs17_reg_write(S17_SGMII_CTRL_REG,(S17c_SGMII_EN_PLL | - S17c_SGMII_EN_RX | - S17c_SGMII_EN_TX | - S17c_SGMII_EN_SD | - S17c_SGMII_BW_HIGH | - S17c_SGMII_SEL_CLK125M | - S17c_SGMII_TXDR_CTRL_600mV | - S17c_SGMII_CDR_BW_8 | - S17c_SGMII_DIS_AUTO_LPI_25M | - S17c_SGMII_MODE_CTRL_SGMII_PHY | - S17c_SGMII_PAUSE_SG_TX_EN_25M | - S17c_SGMII_ASYM_PAUSE_25M | - S17c_SGMII_PAUSE_25M | - S17c_SGMII_HALF_DUPLEX_25M | - S17c_SGMII_FULL_DUPLEX_25M)); + athrs17_reg_write(S17_PWS_REG, 0x2613a0); + athrs17_reg_write(S17_SGMII_CTRL_REG,(S17c_SGMII_EN_PLL | + S17c_SGMII_EN_RX | + S17c_SGMII_EN_TX | + S17c_SGMII_EN_SD | + S17c_SGMII_BW_HIGH | + S17c_SGMII_SEL_CLK125M | + S17c_SGMII_TXDR_CTRL_600mV | + S17c_SGMII_CDR_BW_8 | + S17c_SGMII_DIS_AUTO_LPI_25M | + S17c_SGMII_MODE_CTRL_SGMII_PHY | + S17c_SGMII_PAUSE_SG_TX_EN_25M | + S17c_SGMII_ASYM_PAUSE_25M | + S17c_SGMII_PAUSE_25M | + S17c_SGMII_HALF_DUPLEX_25M | + S17c_SGMII_FULL_DUPLEX_25M)); + } athrs17_reg_write(S17_MODULE_EN_REG, S17_MIB_COUNTER_ENABLE); } @@ -355,7 +369,7 @@ int ipq_qca8337_switch_init(ipq_s17c_swt_cfg_t *s17c_swt_cfg) if (ipq_athrs17_init(s17c_swt_cfg) != 0) { printf("QCA_8337 switch init failed \n"); - return 0; + return -1; } for (port = 0; port < s17c_swt_cfg->port_count; ++port) { @@ -370,7 +384,7 @@ int ipq_qca8337_switch_init(ipq_s17c_swt_cfg_t *s17c_swt_cfg) mdelay(100); } - return 1; + return 0; } int ipq_qca8337_link_update(ipq_s17c_swt_cfg_t *s17c_swt_cfg) @@ -389,7 +403,7 @@ int ipq_qca8337_link_update(ipq_s17c_swt_cfg_t *s17c_swt_cfg) if (phy_data & LINK_UP) status = 0; - printf("Port%d %s ", i + 1, LINK(phy_data)); + printf("QCA8337: Port%d %s ", i + 1, LINK(phy_data)); switch(SPEED(phy_data)){ case SPEED_1000M: diff --git a/drivers/net/ipq_common/athrs17_phy.h b/drivers/net/ipq_common/athrs17_phy.h index 2975c83bf7..47904ca649 100644 --- a/drivers/net/ipq_common/athrs17_phy.h +++ b/drivers/net/ipq_common/athrs17_phy.h @@ -615,6 +615,14 @@ typedef struct { int port_count; int chip_detect; u32 port_phy_address[S17C_MAX_PORT]; + bool update; + u32 pad0_mode; + u32 pad5_mode; + u32 pad6_mode; + u32 port0; + u32 sgmii_ctrl; + u32 port0_status; + u32 port6_status; } ipq_s17c_swt_cfg_t; #endif