From 457bfcfd2ff3b5390786cab550e2de90eca7bdbe Mon Sep 17 00:00:00 2001 From: Ram Kumar D Date: Tue, 29 Nov 2022 15:21:05 +0530 Subject: [PATCH] driver: net: add qca8084 by-pass mode support on MI01.1 RDP Added QCA8084 by-pass mode support on MI01.1 RDP Change-Id: I1a14729cac5463675f9cb0d15df3da76746aa81e Signed-off-by: Ram Kumar D --- arch/arm/dts/ipq5332-mi01.1.dts | 13 +++-- configs/ipq5332_defconfig | 1 + drivers/net/ipq5332/ipq5332_edma.c | 48 ++++++++++++++-- drivers/net/ipq_common/ipq_qca8084.c | 56 ++++++++++++++++--- drivers/net/ipq_common/ipq_qca8084.h | 5 ++ drivers/net/ipq_common/ipq_qca8084_clk.c | 6 +- .../ipq_common/ipq_qca8084_interface_ctrl.c | 31 ++++++++++ .../ipq_common/ipq_qca8084_interface_ctrl.h | 3 +- 8 files changed, 140 insertions(+), 23 deletions(-) diff --git a/arch/arm/dts/ipq5332-mi01.1.dts b/arch/arm/dts/ipq5332-mi01.1.dts index 7471d32e49..d4c3c9865d 100644 --- a/arch/arm/dts/ipq5332-mi01.1.dts +++ b/arch/arm/dts/ipq5332-mi01.1.dts @@ -200,10 +200,11 @@ ess-switch { switch_mac_mode0 = ; - switch_mac_mode1 = ; + switch_mac_mode1 = ; qca808x_gpio = <51>; qca808x_gpio_cnt = <1>; qca8084_switch_enable = <1>; + qca8084_bypass_enable = <1>; port_phyinfo { port@0 { @@ -214,9 +215,9 @@ }; port@1 { phy_address = <4>; - phy_type = ; - uniphy_id = <0>; - uniphy_mode = ; + phy_type = ; + uniphy_id = <1>; + uniphy_mode = ; }; }; @@ -243,6 +244,10 @@ phy_address = <3>; phy_type = ; }; + port@4 { + phy_address = <0xff>; + phy_type = ; + }; port@5 { phy_address = <0xff>; phy_type = ; diff --git a/configs/ipq5332_defconfig b/configs/ipq5332_defconfig index 6a65a24f3e..0c865787e6 100644 --- a/configs/ipq5332_defconfig +++ b/configs/ipq5332_defconfig @@ -104,6 +104,7 @@ CONFIG_IPQ_QCA_AQUANTIA_PHY=y CONFIG_QCA8033_PHY=y CONFIG_QCA8081_PHY=y CONFIG_QCA8084_PHY=y +CONFIG_QCA8084_PHY_MODE=y CONFIG_QCA8084_SWT_MODE=y CONFIG_ATHRS17C_SWITCH=y diff --git a/drivers/net/ipq5332/ipq5332_edma.c b/drivers/net/ipq5332/ipq5332_edma.c index 95cc882aea..1a38acc704 100644 --- a/drivers/net/ipq5332/ipq5332_edma.c +++ b/drivers/net/ipq5332/ipq5332_edma.c @@ -29,6 +29,7 @@ #include #include "ipq5332_edma.h" #include "ipq_phy.h" +#include "ipq_qca8084.h" DECLARE_GLOBAL_DATA_PTR; #ifdef DEBUG @@ -88,6 +89,14 @@ static int qca8084_swt_enb = 0; static int qca8084_chip_detect = 0; #endif +#ifdef CONFIG_QCA8084_PHY_MODE +extern void ipq_qca8084_phy_hw_init(struct phy_ops **ops, u32 phy_addr); +extern void qca8084_phy_sgmii_mode_set(uint32_t phy_addr, u32 interface_mode); +#endif /* CONFIG_QCA8084_PHY_MODE */ + +static int qca8084_bypass_enb = 0; +extern void qca8084_bypass_interface_mode_set(u32 interface_mode); + /* * EDMA hardware instance */ @@ -917,6 +926,7 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) continue; #ifdef CONFIG_QCA8084_SWT_MODE else if ((qca8084_swt_enb && qca8084_chip_detect) && + (!(qca8084_bypass_enb & i)) && (phy_info->phy_type == QCA8084_PHY_TYPE)) { if (!ipq_qca8084_link_update(swt_info)) linkup++; @@ -1016,7 +1026,8 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) clk[1] = 1; clk[2] = 0x418; clk[3] = 1; - if (phy_info->phy_type == QCA8081_PHY_TYPE) { + if ((phy_info->phy_type == QCA8081_PHY_TYPE) || + (phy_info->phy_type == QCA8084_PHY_TYPE)) { clk[0] = 0x309; clk[1] = 0; clk[2] = 0x409; @@ -1029,7 +1040,8 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) clk[1] = 0x0; clk[2] = 0x404; clk[3] = 0x0; - if (phy_info->phy_type == QCA8081_PHY_TYPE) { + if ((phy_info->phy_type == QCA8081_PHY_TYPE) || + (phy_info->phy_type == QCA8084_PHY_TYPE)) { clk[0] = 0x301; clk[2] = 0x401; } @@ -1040,8 +1052,9 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) clk[1] = 0x0; clk[2] = 0x407; clk[3] = 0x0; - if (phy_info->phy_type == SFP_PHY_TYPE || - phy_info->phy_type == QCA8081_PHY_TYPE) { + if ((phy_info->phy_type == SFP_PHY_TYPE) || + (phy_info->phy_type == QCA8081_PHY_TYPE) || + (phy_info->phy_type == QCA8084_PHY_TYPE)) { clk[0] = 0x301; clk[2] = 0x401; } @@ -1077,7 +1090,8 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) curr_speed[i], dp[duplex]); } - if (phy_info->phy_type == QCA8081_PHY_TYPE) { + if ((phy_info->phy_type == QCA8081_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, sgmii_mode); @@ -1105,6 +1119,17 @@ static int ipq5332_eth_init(struct eth_device *eth_dev, bd_t *this) } } + if (phy_info->phy_type == QCA8084_PHY_TYPE) { + if (curr_speed[i] == FAL_SPEED_2500) { + qca8084_phy_sgmii_mode_set(PORT4, + PORT_SGMII_PLUS); + } + else { + qca8084_phy_sgmii_mode_set(PORT4, + PHY_SGMII_BASET); + } + } + ipq5332_port_mac_clock_reset(i); if (phy_info->phy_type == AQ_PHY_TYPE){ @@ -1710,6 +1735,8 @@ int ipq5332_edma_init(void *edma_board_cfg) node = fdt_path_offset(gd->fdt_blob, "/ess-switch"); #ifdef CONFIG_QCA8084_SWT_MODE + qca8084_bypass_enb = fdtdec_get_uint(gd->fdt_blob, node, + "qca8084_bypass_enable", 0); qca8084_swt_enb = fdtdec_get_uint(gd->fdt_blob, node, "qca8084_switch_enable", 0); if (qca8084_swt_enb) { @@ -1913,9 +1940,15 @@ int ipq5332_edma_init(void *edma_board_cfg) phy_addr); break; #endif -#ifdef CONFIG_QCA8084_SWT_MODE +#ifdef CONFIG_QCA8084_PHY case QCA8084_PHY: qca8084_chip_detect = 1; + if (qca8084_bypass_enb && + (phy_addr == PORT4)) { + ipq_qca8084_phy_hw_init( + &ipq5332_edma_dev[i]->ops[phy_id], + phy_addr); + } break; #endif #ifdef CONFIG_ATHRS17C_SWITCH @@ -1961,6 +1994,9 @@ int ipq5332_edma_init(void *edma_board_cfg) #ifdef CONFIG_QCA8084_SWT_MODE /** QCA8084 switch specific configurations */ if (qca8084_swt_enb && qca8084_chip_detect) { + + if (qca8084_bypass_enb) + qca8084_bypass_interface_mode_set(PHY_SGMII_BASET); /* * Force speed ipq5332 1st port * for QCA8084 switch mode diff --git a/drivers/net/ipq_common/ipq_qca8084.c b/drivers/net/ipq_common/ipq_qca8084.c index e67c3a909a..0ed8a51518 100644 --- a/drivers/net/ipq_common/ipq_qca8084.c +++ b/drivers/net/ipq_common/ipq_qca8084.c @@ -39,6 +39,7 @@ extern void qca8084_port_speed_clock_set(uint32_t qca8084_port_id, extern void qca8084_port_clk_en_set(uint32_t qca8084_port_id, uint8_t mask, uint8_t enable); extern void qca8084_port_clk_reset(uint32_t qca8084_port_id, uint8_t mask); +extern void qca8084_phy_sgmii_mode_set(uint32_t phy_addr, u32 interface_mode); #ifdef CONFIG_QCA8084_PHY_MODE extern void qca8084_uniphy_xpcs_autoneg_restart(uint32_t qca8084_port_id); @@ -57,7 +58,10 @@ extern void qca8084_gcc_port_clk_parent_set(qca8084_work_mode_t clk_mode, extern void qca8084_uniphy_sgmii_function_reset(u32 uniphy_index); extern void qca8084_interface_sgmii_mode_set(u32 uniphy_index, u32 qca8084_port_id, mac_config_t *config); +extern uint8_t qca8084_uniphy_mode_check(uint32_t uniphy_index, + qca8084_uniphy_mode_t uniphy_mode); extern void qca8084_clk_reset(const char *clock_id); +extern void qca8084_clk_disable(const char *clock_id); bool qca8084_port_txfc_forcemode[QCA8084_MAX_PORTS] = {}; bool qca8084_port_rxfc_forcemode[QCA8084_MAX_PORTS] = {}; @@ -742,13 +746,18 @@ static int ipq_qca8084_work_mode_init(int mac_mode0, int mac_mode1) return -1; } + if (qca8084_uniphy_mode_check(QCA8084_UNIPHY_SGMII_0, QCA8084_UNIPHY_PHY)){ + pr_debug("%s %d QCA8084 Uniphy 0 is in SGMII Mode \n", + __func__, __LINE__); + ipq_qca8084_work_mode_set(QCA8084_SWITCH_BYPASS_PORT5_MODE); + return ret; + } + switch (mac_mode1) { case EPORT_WRAPPER_SGMII_PLUS: - case EPORT_WRAPPER_SGMII_CHANNEL0: + case EPORT_WRAPPER_MAX: ipq_qca8084_work_mode_set(QCA8084_SWITCH_MODE); break; - case EPORT_WRAPPER_MAX: - ipq_qca8084_work_mode_set(QCA8084_SWITCH_BYPASS_PORT5_MODE); default: printf("%s %d Error: Unsupported mac_mode1 \n", __func__, __LINE__); return -1; @@ -779,11 +788,21 @@ static int chip_ver_get(void) return ret; } +void qca8084_bypass_interface_mode_set(u32 interface_mode) +{ + ipq_qca8084_work_mode_set(QCA8084_PHY_SGMII_UQXGMII_MODE); + qca8084_phy_sgmii_mode_set(PORT4, interface_mode); + + pr_debug("ethphy3 software reset\n"); + qca8084_phy_reset(PORT4); + + /*init pinctrl for phy mode to be added later*/ +} bool qca8084_port_phy_connected(u32 port_id) { u32 cpu_bmp = 0x1; - if ((cpu_bmp & BIT(port_id)) || (port_id == PORT1) || + if ((cpu_bmp & BIT(port_id)) || (port_id == PORT0) || (port_id == PORT5)) return false; @@ -1186,8 +1205,10 @@ static int _qca8084_interface_mode_init(u32 port_id, u32 mac_mode, if(mac_mode == EPORT_WRAPPER_SGMII_PLUS) config.mac_mode = QCA8084_MAC_MODE_SGMII_PLUS; - else if(mac_mode == EPORT_WRAPPER_SGMII_CHANNEL0) + else if (mac_mode == EPORT_WRAPPER_SGMII_CHANNEL0) config.mac_mode = QCA8084_MAC_MODE_SGMII; + else if (mac_mode == EPORT_WRAPPER_MAX) + config.mac_mode = QCA8084_MAC_MODE_MAX; else { printf("%s %d Unsupported mac mode \n", __func__, __LINE__); return -1; @@ -1207,11 +1228,25 @@ static int _qca8084_interface_mode_init(u32 port_id, u32 mac_mode, config.auto_neg = !(phy_info->forced_speed); config.force_speed = force_speed; - qca8084_interface_sgmii_mode_set(uniphy_index, port_id, &config); - /*do sgmii function reset*/ - pr_debug("ipg_tune reset and function reset\n"); - qca8084_uniphy_sgmii_function_reset(uniphy_index); + if (port_id == PORT5) { + if (qca8084_uniphy_mode_check(QCA8084_UNIPHY_SGMII_0, QCA8084_UNIPHY_PHY)) + pr_debug("%s %d QCA8084 Uniphy 0 is in SGMII Mode \n", + __func__, __LINE__); + else { + if (config.mac_mode == QCA8084_MAC_MODE_MAX) { + pr_debug("%s %d QCA8084 Port 5 clk disable \n", + __func__, __LINE__); + qca8084_clk_disable(QCA8084_SRDS0_SYS_CLK); + } + } + } else { + qca8084_interface_sgmii_mode_set(uniphy_index, port_id, &config); + + /*do sgmii function reset*/ + pr_debug("ipg_tune reset and function reset\n"); + qca8084_uniphy_sgmii_function_reset(uniphy_index); + } return 0; } @@ -1318,6 +1353,9 @@ int ipq_qca8084_link_update(phy_info_t * phy_info[]) for (int i=PORT1; iphy_address; + if (phy_info[i]->phy_type == UNUSED_PHY_TYPE) + continue; + rv = qca8084_phy_get_status(port_id, &phy_status); if (rv < 0) { printf("%s %d failed get phy status of idx %d \n", diff --git a/drivers/net/ipq_common/ipq_qca8084.h b/drivers/net/ipq_common/ipq_qca8084.h index 7e844654fd..afbe3a4898 100644 --- a/drivers/net/ipq_common/ipq_qca8084.h +++ b/drivers/net/ipq_common/ipq_qca8084.h @@ -20,6 +20,11 @@ extern "C" { #endif +/*QCA8084 PHY Fixup definitions */ +#define PORT_UQXGMII 0x1 +#define PHY_SGMII_BASET 0x2 +#define PORT_SGMII_PLUS 0x3 + /*MII register*/ #define QCA8084_PHY_FIFO_CONTROL 0x19 diff --git a/drivers/net/ipq_common/ipq_qca8084_clk.c b/drivers/net/ipq_common/ipq_qca8084_clk.c index 1ee0497a5b..36ef2a44f2 100644 --- a/drivers/net/ipq_common/ipq_qca8084_clk.c +++ b/drivers/net/ipq_common/ipq_qca8084_clk.c @@ -828,7 +828,7 @@ void qca8084_clk_dump(void) struct qca8084_clk_data clk_data; int ret; - pr_debug("%-31s Frequency RCG_VAL CDIV_VAL CBC_VAL\n", "Clock Name"); + printf("%-31s Frequency RCG_VAL CDIV_VAL CBC_VAL\n", "Clock Name"); for (i = 0; i < ARRAY_SIZE(qca8084_clk_lookup_table); i++) { clk = &qca8084_clk_lookup_table[i]; @@ -836,8 +836,8 @@ void qca8084_clk_dump(void) ret = qca8084_clk_rate_get(clk->clk_name, &clk_data); if (ret != 0) continue; - pr_debug("%-31s %-9ld 0x%-5x 0x%-6x 0x%-5x\n", - clk->clk_name + 8, clk_data.rate, + printf("%-31s %-9ld 0x%-5x 0x%-6x 0x%-5x\n", + clk->clk_name, clk_data.rate, clk_data.rcg_val, clk_data.cdiv_val, clk_data.cbc_val); } } diff --git a/drivers/net/ipq_common/ipq_qca8084_interface_ctrl.c b/drivers/net/ipq_common/ipq_qca8084_interface_ctrl.c index a9a9980bf0..0098e4636d 100644 --- a/drivers/net/ipq_common/ipq_qca8084_interface_ctrl.c +++ b/drivers/net/ipq_common/ipq_qca8084_interface_ctrl.c @@ -663,3 +663,34 @@ void qca8084_interface_sgmii_mode_set(u32 uniphy_index, u32 qca8084_port_id, mac return; } #endif /* CONFIG_QCA8084_SWT_MODE */ + +void qca8084_phy_sgmii_mode_set(uint32_t phy_addr, u32 interface_mode) +{ + uint32_t phy_addr_tmp = 0; + mac_config_t config = {0}; + + if(interface_mode == PHY_SGMII_BASET) + config.mac_mode = QCA8084_MAC_MODE_SGMII; + else if(interface_mode == PORT_SGMII_PLUS) + config.mac_mode = QCA8084_MAC_MODE_SGMII_PLUS; + else { + printf("Unsupported interface mode \n"); + return; + } + + config.clock_mode = QCA8084_INTERFACE_CLOCK_PHY_MODE; + config.auto_neg = 1; + + qca8084_ephy_addr_get(PORT4, &phy_addr_tmp); + if(phy_addr_tmp != phy_addr) + { + printf("phy_addr:0x%x is not matched with port4 phy addr:0x%x\n", + phy_addr, phy_addr_tmp); + return; + } + + qca8084_interface_sgmii_mode_set(QCA8084_UNIPHY_SGMII_0, + PORT4, &config); + return; +} + diff --git a/drivers/net/ipq_common/ipq_qca8084_interface_ctrl.h b/drivers/net/ipq_common/ipq_qca8084_interface_ctrl.h index 43dfeb7958..491d715ce1 100644 --- a/drivers/net/ipq_common/ipq_qca8084_interface_ctrl.h +++ b/drivers/net/ipq_common/ipq_qca8084_interface_ctrl.h @@ -156,7 +156,8 @@ typedef enum { QCA8084_MAC_MODE_FIBER, QCA8084_MAC_MODE_RMII, QCA8084_MAC_MODE_SGMII_PLUS, - QCA8084_MAC_MODE_DEFAULT + QCA8084_MAC_MODE_DEFAULT, + QCA8084_MAC_MODE_MAX = 0xFF, } qca8084_mac_mode_t; typedef struct {