driver: net: qca8084: add seperate configs for PHY & switch

Currently if CONFIG_QCA8084_PHY is enabled means, it will build
all qca8084 functions required for both PHY & switch mode. But,
some ipq devices might uses anyone of them. So, add configs to
seperate the PHY & switch mode and define it in corresponding
defconfig file as per the need.

Also, some of the qca8084 functions will be used only for debug
purpose, those functions are moved under the config QCA8084_DEBUG.

Thereby, we can save some space in the u-boot.

Change-Id: I7e5f53869629a0c7cbbb12daf04ed782c9693623
Signed-off-by: Ram Kumar D <quic_ramd@quicinc.com>
This commit is contained in:
Ram Kumar D 2022-07-04 16:36:07 +05:30
parent 5fa35de070
commit b8611c7623
11 changed files with 311 additions and 296 deletions

View file

@ -47,8 +47,4 @@ config QCA8033_PHY
config QCA8081_PHY
bool "Enable QCA8081 PHY support"
config QCA8084_PHY
depends on QCA8081_PHY
bool "Enable QCA8084 PHY support"
endif

View file

@ -17,7 +17,4 @@ config IPQ9574_QCA_AQUANTIA_PHY
config IPQ9574_QCA8075_PHY
bool "Enable Malibu PHY support for ipq9574"
config QCA8084_PHY
bool "Enable QCA8084 PHY support for ipq9574"
endif

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_SWT_MODE=y
CONFIG_ATHRS17C_SWITCH=y
CONFIG_CMD_NET=y

View file

@ -103,6 +103,8 @@ CONFIG_IPQ9574_QCA_AQUANTIA_PHY=y
# CONFIG_QCA8033_PHY is not set
CONFIG_QCA8081_PHY=y
CONFIG_QCA8084_PHY=y
CONFIG_QCA8084_PHY_MODE=y
CONFIG_QCA8084_SWT_MODE=y
CONFIG_IPQ9574_QCA8075_PHY=y
#

View file

@ -120,3 +120,27 @@ config ATHRS17C_SWITCH
bool "QTI S17C switch support"
help
Enable QTI S17C switch support.
config QCA8084_PHY
depends on QCA8081_PHY
bool "Enable QCA8084 Ethernet Chip support"
if QCA8084_PHY
config QCA8084_PHY_MODE
bool "Enable QCA8084 PHY Mode support"
help
Enable QCA8084 PHY Mode support.
config QCA8084_SWT_MODE
bool "Enable QCA8084 Switch Mode support"
help
Enable QCA8084 Switch Mode support.
config QCA8084_DEBUG
bool "Enable QCA8084 Debug support"
help
Enable QCA8084 Debug support.
endif # QCA8084_PHY

View file

@ -79,7 +79,7 @@ ipq_s17c_swt_cfg_t s17c_swt_cfg;
static int tftp_acl_our_port;
#ifndef CONFIG_DEVSOC_RUMI
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_SWT_MODE
static int qca8084_swt_enb = 0;
static int qca8084_chip_detect = 0;
#endif
@ -924,7 +924,7 @@ static int devsoc_eth_init(struct eth_device *eth_dev, bd_t *this)
#ifndef CONFIG_DEVSOC_RUMI
if (phy_info[i]->phy_type == UNUSED_PHY_TYPE)
continue;
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_SWT_MODE
else if ((qca8084_swt_enb && qca8084_chip_detect) &&
(phy_info[i]->phy_type == QCA8084_PHY_TYPE)) {
if (!ipq_qca8084_link_update(swt_info))
@ -1714,7 +1714,7 @@ int devsoc_edma_init(void *edma_board_cfg)
#ifdef CONFIG_DEVSOC_QCA8075_PHY
static int sw_init_done = 0;
#endif
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_SWT_MODE
static int qca8084_init_done = 0;
int qca8084_gpio, clk[4] = {0};
#endif
@ -1743,7 +1743,7 @@ int devsoc_edma_init(void *edma_board_cfg)
}
}
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_SWT_MODE
qca8084_swt_enb = fdtdec_get_uint(gd->fdt_blob, node, "qca8084_switch_enable", 0);
if (qca8084_swt_enb) {
qca8084_gpio = fdtdec_get_uint(gd->fdt_blob, node, "qca808x_gpio", 0);
@ -1882,7 +1882,7 @@ int devsoc_edma_init(void *edma_board_cfg)
printf("Error:Phy addresses not configured in DT\n");
goto init_failed;
}
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_SWT_MODE
if (phy_info[phy_id]->phy_type == QCA8084_PHY_TYPE && !qca8084_init_done) {
ipq_phy_addr_fixup();
ipq_clock_init();
@ -1930,7 +1930,7 @@ int devsoc_edma_init(void *edma_board_cfg)
ipq_qca8081_phy_init(&devsoc_edma_dev[i]->ops[phy_id], phy_addr);
break;
#endif
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_SWT_MODE
case QCA8084_PHY:
qca8084_chip_detect = 1;
break;
@ -1972,7 +1972,7 @@ int devsoc_edma_init(void *edma_board_cfg)
goto init_failed;
#ifndef CONFIG_DEVSOC_RUMI
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_SWT_MODE
/** QCA8084 switch specific configurations */
if (qca8084_swt_enb && qca8084_chip_detect) {
/** Force speed devsoc 2nd port for QCA8084 switch mode */

View file

@ -60,12 +60,18 @@ extern int ipq_qca8033_phy_init(struct phy_ops **ops, u32 phy_id);
extern int ipq_qca8081_phy_init(struct phy_ops **ops, u32 phy_id);
extern int ipq_qca_aquantia_phy_init(struct phy_ops **ops, u32 phy_id);
extern int ipq_board_fw_download(unsigned int phy_addr);
#ifdef CONFIG_QCA8084_PHY_MODE
extern void ipq_qca8084_phy_hw_init(struct phy_ops **ops, u32 phy_addr);
extern void qca8084_phy_uqxgmii_speed_fixup(uint32_t phy_addr, uint32_t qca8084_port_id,
uint32_t status, fal_port_speed_t new_speed);
#endif /* CONFIG_QCA8084_PHY_MODE */
#ifdef CONFIG_QCA8084_SWT_MODE
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);
#endif /* CONFIG_QCA8084_SWT_MODE */
static int tftp_acl_our_port;
static int qca8084_swt_enb = 0;
@ -983,11 +989,13 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
printf("Error: Wrong mode specified for SFP Port in DT\n");
return sfp_mode;
}
#ifdef CONFIG_QCA8084_SWT_MODE
} else if (qca8084_swt_enb && (phy_info[i]->phy_type == QCA8084_PHY_TYPE)) {
if (!ipq_qca8084_link_update(swt_info))
linkup++;
i = PORT3;
continue;
#endif /* CONFIG_QCA8084_SWT_MODE */
} else {
if (!priv->ops[i]) {
printf("Phy ops not mapped\n");
@ -1068,11 +1076,13 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
clk[0] = 0x409;
clk[2] = 0x509;
}
#ifdef CONFIG_QCA8084_PHY_MODE
} else if (phy_info[i]->phy_type == QCA8084_PHY_TYPE) {
clk[0] = 0x213;
clk[1] = 0x18;
clk[2] = 0x313;
clk[3] = 0x18;
#endif /* CONFIG_QCA8084_PHY_MODE */
}
}
printf("eth%d PHY%d %s Speed :%d %s duplex\n",
@ -1100,11 +1110,13 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
clk[0] = 0x409;
clk[2] = 0x509;
}
#ifdef CONFIG_QCA8084_PHY_MODE
} else if (phy_info[i]->phy_type == QCA8084_PHY_TYPE) {
clk[0] = 0x204;
clk[1] = 0x9;
clk[2] = 0x304;
clk[3] = 0x9;
#endif /* CONFIG_QCA8084_PHY_MODE */
}
}
printf("eth%d PHY%d %s Speed :%d %s duplex\n",
@ -1138,9 +1150,11 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
clk[0] = 0x401;
clk[2] = 0x501;
}
#ifdef CONFIG_QCA8084_PHY_MODE
} else if (phy_info[i]->phy_type == QCA8084_PHY_TYPE) {
clk[0] = 0x204;
clk[2] = 0x304;
#endif /* CONFIG_QCA8084_PHY_MODE */
}
}
printf("eth%d PHY%d %s Speed :%d %s duplex\n",
@ -1180,10 +1194,12 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
clk[0] = 0x201;
clk[2] = 0x301;
}
#ifdef CONFIG_QCA8084_PHY_MODE
} else if (phy_info[i]->phy_type == QCA8084_PHY_TYPE) {
mac_speed = 0x4;
clk[0] = 0x207;
clk[2] = 0x307;
#endif /* CONFIG_QCA8084_PHY_MODE */
}
}
printf("eth%d PHY%d %s Speed :%d %s duplex\n",
@ -1269,9 +1285,11 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
ipq9574_speed_clock_set(i, clk);
#ifdef CONFIG_QCA8084_PHY_MODE
if (!qca8084_swt_enb && (phy_info[i]->phy_type == QCA8084_PHY_TYPE))
qca8084_phy_uqxgmii_speed_fixup(phy_info[i]->phy_address,
i + 1, status, curr_speed[i]);
#endif /* CONFIG_QCA8084_PHY_MODE */
ipq9574_port_mac_clock_reset(i);
@ -1888,7 +1906,9 @@ int ipq9574_edma_init(void *edma_board_cfg)
#ifdef CONFIG_QCA8084_PHY
static int qca8084_init_done = 0;
int phy_type;
#ifdef CONFIG_QCA8084_SWT_MODE
int qca8084_gpio, swt_node = -1, clk[4] = {0};
#endif /* CONFIG_QCA8084_SWT_MODE */
#endif
int node, phy_addr, mode, phy_node = -1, res = -1;
int aquantia_port[2] = {-1, -1}, aquantia_port_cnt = -1;
@ -1911,7 +1931,7 @@ int ipq9574_edma_init(void *edma_board_cfg)
}
}
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_SWT_MODE
qca8084_swt_enb = fdtdec_get_uint(gd->fdt_blob, node, "qca8084_switch_enable", 0);
qca8084_gpio = fdtdec_get_uint(gd->fdt_blob, node, "qca808x_gpio", 0);
if (qca8084_swt_enb) {
@ -2082,7 +2102,7 @@ int ipq9574_edma_init(void *edma_board_cfg)
ipq_qca8081_phy_init(&ipq9574_edma_dev[i]->ops[phy_id], phy_addr);
break;
#endif
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_PHY_MODE
case QCA8084_PHY:
ipq_qca8084_phy_hw_init(&ipq9574_edma_dev[i]->ops[phy_id], phy_addr);
break;
@ -2116,6 +2136,7 @@ int ipq9574_edma_init(void *edma_board_cfg)
if (ret)
goto init_failed;
#ifdef CONFIG_QCA8084_SWT_MODE
/** QCA8084 switch specific configurations */
if (qca8084_swt_enb) {
/** Force speed alder 1st port for QCA8084 switch mode */
@ -2146,6 +2167,7 @@ int ipq9574_edma_init(void *edma_board_cfg)
goto init_failed;
}
}
#endif
eth_register(dev[i]);
}

View file

@ -551,7 +551,7 @@ static void ppe_uniphy_uqxgmii_mode_set(uint32_t uniphy_index)
/* enable uniphy eee transparent mode*/
ppe_uniphy_uqxgmii_eee_set(uniphy_index);
#ifdef CONFIG_QCA8084_PHY
#ifdef CONFIG_QCA8084_PHY_MODE
/* phy interface mode configuration for qca8084 */
qca8084_phy_interface_mode_set();
#endif

View file

@ -33,35 +33,41 @@ extern int ipq_mdio_read(int mii_id,
int regnum, ushort *data);
extern int ipq_mdio_write(int mii_id,
int regnum, u16 data);
extern void qca8084_interface_uqxgmii_mode_set(void);
extern void qca8084_gcc_clock_init(qca8084_work_mode_t clk_mode, u32 pbmp);
extern void qca8084_gcc_port_clk_parent_set(qca8084_work_mode_t clk_mode, uint32_t qca8084_port_id);
extern u8 qca8081_phy_get_link_status(u32 dev_id, u32 phy_id);
extern u32 qca8081_phy_get_duplex(u32 dev_id, u32 phy_id, fal_port_duplex_t *duplex);
extern u32 qca8081_phy_get_speed(u32 dev_id, u32 phy_id, fal_port_speed_t *speed);
extern void qca8084_uniphy_xpcs_autoneg_restart(uint32_t qca8084_port_id);
extern void qca8084_port_speed_clock_set(uint32_t qca8084_port_id,
fal_port_speed_t speed);
extern void qca8084_uniphy_xpcs_speed_set(uint32_t qca8084_port_id,
fal_port_speed_t speed);
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);
#ifdef CONFIG_QCA8084_PHY_MODE
extern void qca8084_uniphy_xpcs_autoneg_restart(uint32_t qca8084_port_id);
extern void qca8084_uniphy_xpcs_speed_set(uint32_t qca8084_port_id,
fal_port_speed_t speed);
extern u8 qca8081_phy_get_link_status(u32 dev_id, u32 phy_id);
extern u32 qca8081_phy_get_duplex(u32 dev_id, u32 phy_id, fal_port_duplex_t *duplex);
extern u32 qca8081_phy_get_speed(u32 dev_id, u32 phy_id, fal_port_speed_t *speed);
extern void qca8084_interface_uqxgmii_mode_set(void);
extern void qca8084_uniphy_uqxgmii_function_reset(uint32_t qca8084_port_id);
#endif /* CONFIG_QCA8084_PHY_MODE */
#ifdef CONFIG_QCA8084_SWT_MODE
extern void qca8084_gcc_port_clk_parent_set(qca8084_work_mode_t clk_mode,
uint32_t qca8084_port_id);
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 void qca8084_clk_reset(const char *clock_id);
bool qca8084_port_txfc_forcemode[QCA8084_MAX_PORTS] = {};
bool qca8084_port_rxfc_forcemode[QCA8084_MAX_PORTS] = {};
#endif /* CONFIG_QCA8084_SWT_MODE */
static int qca8084_reg_field_get(u32 reg_addr, u32 bit_offset,
u32 field_len, u8 value[]);
static int qca8084_reg_field_set(u32 reg_addr, u32 bit_offset,
u32 field_len, const u8 value[]);
bool qca8084_port_txfc_forcemode[QCA8084_MAX_PORTS] = {};
bool qca8084_port_rxfc_forcemode[QCA8084_MAX_PORTS] = {};
u16 qca8084_phy_reg_read(u32 phy_addr, u32 reg_id)
{
return ipq_mdio_read(phy_addr, reg_id, NULL);
@ -114,24 +120,6 @@ void qca8084_phy_modify_mmd(uint32_t phy_addr, uint32_t mmd_num,
phy_addr, mmd_reg, phy_data);
}
void qca8084_phy_ipg_config(uint32_t phy_id, fal_port_speed_t speed)
{
uint16_t phy_data = 0;
phy_data = qca8084_phy_mmd_read(phy_id, QCA8084_PHY_MMD7_NUM,
QCA8084_PHY_MMD7_IPG_10_11_ENABLE);
phy_data &= ~QCA8084_PHY_MMD7_IPG_11_EN;
/*If speed is 1G, enable 11 ipg tuning*/
pr_debug("if speed is 1G, enable 11 ipg tuning\n");
if (speed == FAL_SPEED_1000)
phy_data |= QCA8084_PHY_MMD7_IPG_11_EN;
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD7_NUM,
QCA8084_PHY_MMD7_IPG_10_11_ENABLE, phy_data);
}
void qca8084_phy_function_reset(uint32_t phy_id)
{
uint16_t phy_data = 0;
@ -147,201 +135,6 @@ void qca8084_phy_function_reset(uint32_t phy_id)
phy_data | QCA8084_PHY_FIFO_RESET);
}
void qca8084_phy_uqxgmii_speed_fixup(uint32_t phy_addr, uint32_t qca8084_port_id,
uint32_t status, fal_port_speed_t new_speed)
{
uint32_t port_clock_en = 0;
/*Restart the auto-neg of uniphy*/
pr_debug("Restart the auto-neg of uniphy\n");
qca8084_uniphy_xpcs_autoneg_restart(qca8084_port_id);
/*set gmii+ clock to uniphy1 and ethphy*/
pr_debug("set gmii,xgmii clock to uniphy and gmii to ethphy\n");
qca8084_port_speed_clock_set(qca8084_port_id, new_speed);
/*set xpcs speed*/
pr_debug("set xpcs speed\n");
qca8084_uniphy_xpcs_speed_set(qca8084_port_id, new_speed);
/*GMII/XGMII clock and ETHPHY GMII clock enable/disable*/
pr_debug("GMII/XGMII clock and ETHPHY GMII clock enable/disable\n");
if (status == 0)
port_clock_en = 1;
qca8084_port_clk_en_set(qca8084_port_id,
QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY,
port_clock_en);
pr_debug("UNIPHY GMII/XGMII interface and ETHPHY GMII interface reset and release\n");
qca8084_port_clk_reset(qca8084_port_id,
QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY);
pr_debug("ipg_tune and xgmii2gmii reset for uniphy and ETHPHY, function reset\n");
qca8084_uniphy_uqxgmii_function_reset(qca8084_port_id);
/*do ethphy function reset: PHY_FIFO_RESET*/
pr_debug("do ethphy function reset\n");
qca8084_phy_function_reset(phy_addr);
/*change IPG from 10 to 11 for 1G speed*/
qca8084_phy_ipg_config(phy_addr, new_speed);
}
void qca8084_phy_sgmii_speed_fixup (u32 phy_addr,
u32 link, fal_port_speed_t new_speed)
{
/*disable ethphy3 and uniphy0 clock*/
pr_debug("disable ethphy3 and uniphy0 clock\n");
qca8084_port_clk_en_set(PORT4,
QCA8084_CLK_TYPE_EPHY, false);
qca8084_port_clk_en_set(PORT5,
QCA8084_CLK_TYPE_UNIPHY, false);
/*set gmii clock for ethphy3 and uniphy0*/
pr_debug("set speed clock for uniphy3 and uniphy0\n");
qca8084_port_speed_clock_set(PORT4, new_speed);
/*uniphy and ethphy gmii clock enable/disable*/
pr_debug("uniphy and ethphy GMII clock enable/disable\n");
if(link)
{
pr_debug("enable ethphy3 and uniphy0 clock\n");
qca8084_port_clk_en_set(PORT4,
QCA8084_CLK_TYPE_EPHY, true);
qca8084_port_clk_en_set(PORT5,
QCA8084_CLK_TYPE_UNIPHY, true);
}
/*uniphy and ethphy gmii reset and release*/
pr_debug("uniphy and ethphy GMII interface reset and release\n");
qca8084_port_clk_reset(PORT4,
QCA8084_CLK_TYPE_EPHY);
qca8084_port_clk_reset(PORT5,
QCA8084_CLK_TYPE_UNIPHY);
/*uniphy and ethphy ipg_tune reset, function reset*/
pr_debug("uniphy and ethphy ipg_tune reset, function reset\n");
qca8084_uniphy_sgmii_function_reset(QCA8084_UNIPHY_SGMII_0);
/*do ethphy function reset*/
pr_debug("do ethphy function reset\n");
qca8084_phy_function_reset(phy_addr);
return;
}
void qca8084_phy_interface_mode_set(void)
{
pr_debug("Configure QCA8084 as PORT_UQXGMII..\n");
/*the work mode is PORT_UQXGMII in default*/
qca8084_interface_uqxgmii_mode_set();
/*init clock for PORT_UQXGMII*/
qca8084_gcc_clock_init(QCA8084_PHY_UQXGMII_MODE, 0);
/*init pinctrl for phy mode to be added later*/
}
void qca8084_cdt_thresh_init(u32 phy_id)
{
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL3,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL3_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL4,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL4_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL5,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL5_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL6,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL6_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL7,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL7_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL9,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL9_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL13,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL13_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL14,
QCA8084_PHY_MMD3_NEAR_ECHO_THRESH_VAL);
}
void qca8084_phy_modify_debug(u32 phy_addr, u32 debug_reg,
u32 mask, u32 value)
{
u16 phy_data = 0, new_phy_data = 0;
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_ADDRESS, debug_reg);
phy_data = qca8084_phy_reg_read(phy_addr, QCA8084_DEBUG_PORT_DATA);
if (phy_data == PHY_INVALID_DATA)
pr_debug("qca8084_phy_reg_read failed\n");
new_phy_data = (phy_data & ~mask) | value;
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_ADDRESS, debug_reg);
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_DATA, new_phy_data);
/* check debug register value */
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_ADDRESS, debug_reg);
phy_data = qca8084_phy_reg_read(phy_addr, QCA8084_DEBUG_PORT_DATA);
pr_debug("phy_addr:0x%x, debug_reg:0x%x, phy_data:0x%x\n",
phy_addr, debug_reg, phy_data);
}
void qca8084_phy_reset(u32 phy_addr)
{
u16 phy_data;
phy_data = qca8084_phy_reg_read(phy_addr, QCA8084_PHY_CONTROL);
qca8084_phy_reg_write(phy_addr, QCA8084_PHY_CONTROL,
phy_data | QCA8084_CTRL_SOFTWARE_RESET);
}
void qca8084_phy_adc_edge_set(u32 phy_addr, u32 adc_edge)
{
qca8084_phy_modify_debug(phy_addr,
QCA8084_PHY_DEBUG_ANA_INTERFACE_CLK_SEL, 0xf0, adc_edge);
qca8084_phy_reset(phy_addr);
}
void ipq_qca8084_phy_hw_init(struct phy_ops **ops, u32 phy_addr)
{
#ifdef DEBUG
u16 phy_data;
#endif
struct phy_ops *qca8084_ops;
qca8084_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops));
if (!qca8084_ops) {
pr_debug("Error allocating memory for phy ops\n");
return;
}
/* Note that qca8084 PHY is based on qca8081 PHY and so the following
* ops functions required would be re-used from qca8081 */
qca8084_ops->phy_get_link_status = qca8081_phy_get_link_status;
qca8084_ops->phy_get_speed = qca8081_phy_get_speed;
qca8084_ops->phy_get_duplex = qca8081_phy_get_duplex;
*ops = qca8084_ops;
#ifdef DEBUG
phy_data = qca8084_phy_reg_read(phy_addr, QCA8081_PHY_ID1);
printf("PHY ID1: 0x%x\n", phy_data);
phy_data = qca8084_phy_reg_read(phy_addr, QCA8081_PHY_ID2);
printf("PHY ID2: 0x%x\n", phy_data);
#endif
/* adjust CDT threshold */
qca8084_cdt_thresh_init(phy_addr);
/* invert ADC clock edge as falling edge to fix link issue */
qca8084_phy_adc_edge_set(phy_addr, ADC_FALLING);
}
/***************************** QCA8084 Pinctrl APIs *************************/
/****************************************************************************
*
@ -697,9 +490,177 @@ int ipq_qca8084_pinctrl_init(void)
return 0;
}
/******************************************************************************************/
/************************* New Code *******************************************************/
/******************************************************************************************/
#ifdef CONFIG_QCA8084_PHY_MODE
void qca8084_phy_ipg_config(uint32_t phy_id, fal_port_speed_t speed)
{
uint16_t phy_data = 0;
phy_data = qca8084_phy_mmd_read(phy_id, QCA8084_PHY_MMD7_NUM,
QCA8084_PHY_MMD7_IPG_10_11_ENABLE);
phy_data &= ~QCA8084_PHY_MMD7_IPG_11_EN;
/*If speed is 1G, enable 11 ipg tuning*/
pr_debug("if speed is 1G, enable 11 ipg tuning\n");
if (speed == FAL_SPEED_1000)
phy_data |= QCA8084_PHY_MMD7_IPG_11_EN;
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD7_NUM,
QCA8084_PHY_MMD7_IPG_10_11_ENABLE, phy_data);
}
void qca8084_phy_uqxgmii_speed_fixup(uint32_t phy_addr, uint32_t qca8084_port_id,
uint32_t status, fal_port_speed_t new_speed)
{
uint32_t port_clock_en = 0;
/*Restart the auto-neg of uniphy*/
pr_debug("Restart the auto-neg of uniphy\n");
qca8084_uniphy_xpcs_autoneg_restart(qca8084_port_id);
/*set gmii+ clock to uniphy1 and ethphy*/
pr_debug("set gmii,xgmii clock to uniphy and gmii to ethphy\n");
qca8084_port_speed_clock_set(qca8084_port_id, new_speed);
/*set xpcs speed*/
pr_debug("set xpcs speed\n");
qca8084_uniphy_xpcs_speed_set(qca8084_port_id, new_speed);
/*GMII/XGMII clock and ETHPHY GMII clock enable/disable*/
pr_debug("GMII/XGMII clock and ETHPHY GMII clock enable/disable\n");
if (status == 0)
port_clock_en = 1;
qca8084_port_clk_en_set(qca8084_port_id,
QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY,
port_clock_en);
pr_debug("UNIPHY GMII/XGMII interface and ETHPHY GMII interface reset and release\n");
qca8084_port_clk_reset(qca8084_port_id,
QCA8084_CLK_TYPE_UNIPHY | QCA8084_CLK_TYPE_EPHY);
pr_debug("ipg_tune and xgmii2gmii reset for uniphy and ETHPHY, function reset\n");
qca8084_uniphy_uqxgmii_function_reset(qca8084_port_id);
/*do ethphy function reset: PHY_FIFO_RESET*/
pr_debug("do ethphy function reset\n");
qca8084_phy_function_reset(phy_addr);
/*change IPG from 10 to 11 for 1G speed*/
qca8084_phy_ipg_config(phy_addr, new_speed);
}
void qca8084_phy_interface_mode_set(void)
{
pr_debug("Configure QCA8084 as PORT_UQXGMII..\n");
/*the work mode is PORT_UQXGMII in default*/
qca8084_interface_uqxgmii_mode_set();
/*init clock for PORT_UQXGMII*/
qca8084_gcc_clock_init(QCA8084_PHY_UQXGMII_MODE, 0);
/*init pinctrl for phy mode to be added later*/
}
void qca8084_cdt_thresh_init(u32 phy_id)
{
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL3,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL3_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL4,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL4_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL5,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL5_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL6,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL6_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL7,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL7_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL9,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL9_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL13,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL13_VAL);
qca8084_phy_mmd_write(phy_id, QCA8084_PHY_MMD3_NUM,
QCA8084_PHY_MMD3_CDT_THRESH_CTRL14,
QCA8084_PHY_MMD3_NEAR_ECHO_THRESH_VAL);
}
void qca8084_phy_modify_debug(u32 phy_addr, u32 debug_reg,
u32 mask, u32 value)
{
u16 phy_data = 0, new_phy_data = 0;
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_ADDRESS, debug_reg);
phy_data = qca8084_phy_reg_read(phy_addr, QCA8084_DEBUG_PORT_DATA);
if (phy_data == PHY_INVALID_DATA)
pr_debug("qca8084_phy_reg_read failed\n");
new_phy_data = (phy_data & ~mask) | value;
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_ADDRESS, debug_reg);
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_DATA, new_phy_data);
/* check debug register value */
qca8084_phy_reg_write(phy_addr, QCA8084_DEBUG_PORT_ADDRESS, debug_reg);
phy_data = qca8084_phy_reg_read(phy_addr, QCA8084_DEBUG_PORT_DATA);
pr_debug("phy_addr:0x%x, debug_reg:0x%x, phy_data:0x%x\n",
phy_addr, debug_reg, phy_data);
}
void qca8084_phy_reset(u32 phy_addr)
{
u16 phy_data;
phy_data = qca8084_phy_reg_read(phy_addr, QCA8084_PHY_CONTROL);
qca8084_phy_reg_write(phy_addr, QCA8084_PHY_CONTROL,
phy_data | QCA8084_CTRL_SOFTWARE_RESET);
}
void qca8084_phy_adc_edge_set(u32 phy_addr, u32 adc_edge)
{
qca8084_phy_modify_debug(phy_addr,
QCA8084_PHY_DEBUG_ANA_INTERFACE_CLK_SEL, 0xf0, adc_edge);
qca8084_phy_reset(phy_addr);
}
void ipq_qca8084_phy_hw_init(struct phy_ops **ops, u32 phy_addr)
{
#ifdef DEBUG
u16 phy_data;
#endif
struct phy_ops *qca8084_ops;
qca8084_ops = (struct phy_ops *)malloc(sizeof(struct phy_ops));
if (!qca8084_ops) {
pr_debug("Error allocating memory for phy ops\n");
return;
}
/* Note that qca8084 PHY is based on qca8081 PHY and so the following
* ops functions required would be re-used from qca8081 */
qca8084_ops->phy_get_link_status = qca8081_phy_get_link_status;
qca8084_ops->phy_get_speed = qca8081_phy_get_speed;
qca8084_ops->phy_get_duplex = qca8081_phy_get_duplex;
*ops = qca8084_ops;
#ifdef DEBUG
phy_data = qca8084_phy_reg_read(phy_addr, QCA8081_PHY_ID1);
printf("PHY ID1: 0x%x\n", phy_data);
phy_data = qca8084_phy_reg_read(phy_addr, QCA8081_PHY_ID2);
printf("PHY ID2: 0x%x\n", phy_data);
#endif
/* adjust CDT threshold */
qca8084_cdt_thresh_init(phy_addr);
/* invert ADC clock edge as falling edge to fix link issue */
qca8084_phy_adc_edge_set(phy_addr, ADC_FALLING);
}
#endif /* CONFIG_QCA8084_PHY_MODE */
static int qca8084_reg_field_get(u32 reg_addr, u32 bit_offset,
u32 field_len, u8 value[])
@ -722,6 +683,7 @@ static int qca8084_reg_field_set(u32 reg_addr, u32 bit_offset,
return 0;
}
#ifdef CONFIG_QCA8084_SWT_MODE
static void ipq_qca8084_switch_reset(void)
{
/* Reset switch core */
@ -1348,7 +1310,7 @@ void qca_switch_init(u32 port_bmp, u32 cpu_bmp, phy_info_t * phy_info[])
}
return;
}
/**************************************************************************/
int ipq_qca8084_link_update(phy_info_t * phy_info[])
{
struct port_phy_status phy_status = {0};
@ -1435,7 +1397,6 @@ int ipq_qca8084_hw_init(phy_info_t * phy_info[])
ipq_qca8084_work_mode_get(&work_mode);
qca8084_gcc_clock_init(work_mode, port_bmp);
ret = ipq_qca8084_pinctrl_init();
return ret;
}
@ -1449,4 +1410,4 @@ void ipq_qca8084_switch_hw_reset(int gpio)
mdelay(500);
writel(0x2, GPIO_IN_OUT_ADDR(gpio));
}
#endif /* CONFIG_QCA8084_SWT_MODE */

View file

@ -721,6 +721,7 @@ void qca8084_clk_rate_set(const char *clock_id, uint32_t rate)
qca8084_clk_update(cmd_reg);
}
#ifdef CONFIG_QCA8084_DEBUG
void qca8084_port5_uniphy0_clk_src_get(uint8_t *bypass_en)
{
uint32_t reg_val = 0;
@ -855,6 +856,7 @@ U_BOOT_CMD(
"qca8084_clk_dump - dump all the qca8084 clocks\n"
"This command can be used to check if clocks are all as expected\n"
);
#endif /* CONFIG_QCA8084_DEBUG */
void qca8084_port5_uniphy0_clk_src_set(uint8_t bypass_en)
{

View file

@ -35,13 +35,20 @@ extern void qca8084_phy_modify_mii(uint32_t phy_addr, uint32_t mii_reg,
extern uint32_t ipq_mii_read(uint32_t reg);
extern void ipq_mii_write(uint32_t reg, uint32_t val);
extern void ipq_mii_update(uint32_t reg, uint32_t mask, uint32_t val);
extern void qca8084_port_clk_rate_set(uint32_t qca8084_port_id, uint32_t rate);
extern void qca8084_port_clk_en_set(uint32_t qca8084_port_id, uint8_t mask,
uint8_t enable);
extern void qca8084_uniphy_raw_clock_set(qca8084_clk_parent_t uniphy_clk, uint64_t rate);
extern void qca8084_clk_assert(const char *clock_id);
extern void qca8084_clk_deassert(const char *clock_id);
extern void qca8084_port_clk_reset(uint32_t qca8084_port_id, uint8_t mask);
extern void qca8084_port_clk_rate_set(uint32_t qca8084_port_id, uint32_t rate);
#ifdef CONFIG_QCA8084_PHY_MODE
extern void qca8084_clk_deassert(const char *clock_id);
#endif
#ifdef CONFIG_QCA8084_SWT_MODE
extern void qca8084_uniphy_raw_clock_set(qca8084_clk_parent_t uniphy_clk,
uint64_t rate);
#endif
void qca8084_serdes_addr_get(uint32_t serdes_id, uint32_t *address)
{
@ -65,6 +72,51 @@ void qca8084_serdes_addr_get(uint32_t serdes_id, uint32_t *address)
}
}
static void qca8084_uniphy_calibration(uint32_t uniphy_addr)
{
uint16_t uniphy_data = 0;
uint32_t retries = 100, calibration_done = 0;
/* wait calibration done to uniphy*/
while (calibration_done != QCA8084_UNIPHY_MMD1_CALIBRATION_DONE) {
mdelay(1);
if (retries-- == 0)
pr_debug("uniphy callibration time out!\n");
uniphy_data = qca8084_phy_mmd_read(uniphy_addr, QCA8084_UNIPHY_MMD1,
QCA8084_UNIPHY_MMD1_CALIBRATION4);
calibration_done = (uniphy_data & QCA8084_UNIPHY_MMD1_CALIBRATION_DONE);
}
}
void qca8084_port_speed_clock_set(uint32_t qca8084_port_id,
fal_port_speed_t speed)
{
uint32_t clk_rate = 0;
switch(speed)
{
case FAL_SPEED_2500:
clk_rate = UQXGMII_SPEED_2500M_CLK;
break;
case FAL_SPEED_1000:
clk_rate = UQXGMII_SPEED_1000M_CLK;
break;
case FAL_SPEED_100:
clk_rate = UQXGMII_SPEED_100M_CLK;
break;
case FAL_SPEED_10:
clk_rate = UQXGMII_SPEED_10M_CLK;
break;
default:
pr_debug("Unknown speed\n");
return;
}
qca8084_port_clk_rate_set(qca8084_port_id, clk_rate);
}
#ifdef CONFIG_QCA8084_PHY_MODE
void qca8084_ephy_addr_get(uint32_t qca8084_port_id, uint32_t *phy_addr)
{
uint32_t data = 0;
@ -185,33 +237,6 @@ static void qca8084_uniphy_xpcs_modify_port_mmd(uint32_t qca8084_port_id,
qca8084_uniphy_xpcs_modify_mmd(mmd_id, mmd_reg, mask, value);
}
void qca8084_port_speed_clock_set(uint32_t qca8084_port_id,
fal_port_speed_t speed)
{
uint32_t clk_rate = 0;
switch(speed)
{
case FAL_SPEED_2500:
clk_rate = UQXGMII_SPEED_2500M_CLK;
break;
case FAL_SPEED_1000:
clk_rate = UQXGMII_SPEED_1000M_CLK;
break;
case FAL_SPEED_100:
clk_rate = UQXGMII_SPEED_100M_CLK;
break;
case FAL_SPEED_10:
clk_rate = UQXGMII_SPEED_10M_CLK;
break;
default:
pr_debug("Unknown speed\n");
return;
}
qca8084_port_clk_rate_set(qca8084_port_id, clk_rate);
}
static void qca8084_uniphy_xpcs_8023az_enable(void)
{
uint16_t uniphy_data = 0;
@ -250,23 +275,6 @@ static void qca8084_uniphy_xpcs_8023az_enable(void)
0x3, QCA8084_UNIPHY_MMD3_EEE_EN);
}
static void qca8084_uniphy_calibration(uint32_t uniphy_addr)
{
uint16_t uniphy_data = 0;
uint32_t retries = 100, calibration_done = 0;
/* wait calibration done to uniphy*/
while (calibration_done != QCA8084_UNIPHY_MMD1_CALIBRATION_DONE) {
mdelay(1);
if (retries-- == 0)
pr_debug("uniphy callibration time out!\n");
uniphy_data = qca8084_phy_mmd_read(uniphy_addr, QCA8084_UNIPHY_MMD1,
QCA8084_UNIPHY_MMD1_CALIBRATION4);
calibration_done = (uniphy_data & QCA8084_UNIPHY_MMD1_CALIBRATION_DONE);
}
}
static void qca8084_uniphy_xpcs_10g_r_linkup(void)
{
uint16_t uniphy_data = 0;
@ -503,8 +511,9 @@ void qca8084_interface_uqxgmii_mode_set(void)
pr_debug("enable EEE for xpcs\n");
qca8084_uniphy_xpcs_8023az_enable();
}
#endif /* CONFIG_QCA8084_PHY_MODE */
#ifdef CONFIG_QCA8084_SWT_MODE
void qca8084_uniphy_sgmii_function_reset(u32 uniphy_index)
{
u32 uniphy_addr = 0;
@ -653,3 +662,4 @@ void qca8084_interface_sgmii_mode_set(u32 uniphy_index, u32 qca8084_port_id, mac
return;
}
#endif /* CONFIG_QCA8084_SWT_MODE */