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 <quic_ramd@quicinc.com>
This commit is contained in:
Ram Kumar D 2022-11-29 15:21:05 +05:30
parent 24f263d138
commit 457bfcfd2f
8 changed files with 140 additions and 23 deletions

View file

@ -200,10 +200,11 @@
ess-switch {
switch_mac_mode0 = <PORT_WRAPPER_SGMII_PLUS>;
switch_mac_mode1 = <PORT_WRAPPER_SGMII_PLUS>;
switch_mac_mode1 = <PORT_WRAPPER_SGMII0_RGMII4>;
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 = <UNUSED_PHY_TYPE>;
uniphy_id = <0>;
uniphy_mode = <PORT_WRAPPER_SGMII_PLUS>;
phy_type = <QCA8084_PHY_TYPE>;
uniphy_id = <1>;
uniphy_mode = <PORT_WRAPPER_SGMII0_RGMII4>;
};
};
@ -243,6 +244,10 @@
phy_address = <3>;
phy_type = <QCA8084_PHY_TYPE>;
};
port@4 {
phy_address = <0xff>;
phy_type = <UNUSED_PHY_TYPE>;
};
port@5 {
phy_address = <0xff>;
phy_type = <UNUSED_PHY_TYPE>;

View file

@ -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

View file

@ -29,6 +29,7 @@
#include <fdtdec.h>
#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

View file

@ -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; i<PORT5; i++) {
port_id = phy_info[i]->phy_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",

View file

@ -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

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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 {