mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2025-12-10 07:44:53 +01:00
This patch adds initial support for qca8084 PHY which is based on qca8081 PHY. qca8084 PHY has support for 4x2.5G. Change-Id: Ic767c19fad050e5ee9a97ad7fa50c1b6b27893dd Signed-off-by: Selvam Sathappan Periakaruppan <quic_speriaka@quicinc.com>
504 lines
15 KiB
C
504 lines
15 KiB
C
/*
|
|
* Copyright (c) 2022, The Linux Foundation. All rights reserved.
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
#include "ipq_phy.h"
|
|
#include "ipq_qca8084.h"
|
|
#include "ipq_qca8084_clk.h"
|
|
#include "ipq_qca8084_interface_ctrl.h"
|
|
#include <malloc.h>
|
|
|
|
#ifdef DEBUG
|
|
#define pr_debug(fmt, args...) printf(fmt, ##args);
|
|
#else
|
|
#define pr_debug(fmt, args...)
|
|
#endif
|
|
|
|
extern void qca8084_phy_reset(u32 phy_id);
|
|
extern u16 qca8084_phy_reg_read(u32 phy_id, u32 reg_id);
|
|
extern u16 qca8084_phy_reg_write(u32 phy_id, u32 reg_id, u16 value);
|
|
extern u16 qca8084_phy_mmd_read(u32 phy_id, u16 mmd_num, u16 reg_id);
|
|
extern u16 qca8084_phy_mmd_write(u32 phy_id, u16 mmd_num, u16 reg_id,
|
|
u16 value);
|
|
extern void qca8084_phy_modify_mmd(uint32_t phy_addr, uint32_t mmd_num,
|
|
uint32_t mmd_reg, uint32_t mask, uint32_t value);
|
|
extern void qca8084_phy_modify_mii(uint32_t phy_addr, uint32_t mii_reg,
|
|
uint32_t mask, uint32_t value);
|
|
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_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);
|
|
|
|
void qca8084_serdes_addr_get(uint32_t serdes_id, uint32_t *address)
|
|
{
|
|
uint32_t data = 0;
|
|
|
|
data = ipq_mii_read(SERDES_CFG_OFFSET);
|
|
switch(serdes_id)
|
|
{
|
|
case QCA8084_UNIPHY_SGMII_0:
|
|
*address = (data >> SERDES_CFG_S0_ADDR_BOFFSET) & 0x1f;
|
|
break;
|
|
case QCA8084_UNIPHY_SGMII_1:
|
|
*address = (data >> SERDES_CFG_S1_ADDR_BOFFSET) & 0x1f;
|
|
break;
|
|
case QCA8084_UNIPHY_XPCS:
|
|
*address = (data >> SERDES_CFG_S1_XPCS_ADDR_BOFFSET) & 0x1f;
|
|
break;
|
|
default:
|
|
pr_debug("Serdes id not matching\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void qca8084_ephy_addr_get(uint32_t qca8084_port_id, uint32_t *phy_addr)
|
|
{
|
|
uint32_t data = 0;
|
|
|
|
data = ipq_mii_read(EPHY_CFG_OFFSET);
|
|
switch(qca8084_port_id)
|
|
{
|
|
case PORT1:
|
|
*phy_addr = (data >> EPHY_CFG_EPHY0_ADDR_BOFFSET) & 0x1f;
|
|
break;
|
|
case PORT2:
|
|
*phy_addr = (data >> EPHY_CFG_EPHY1_ADDR_BOFFSET) & 0x1f;
|
|
break;
|
|
case PORT3:
|
|
*phy_addr = (data >> EPHY_CFG_EPHY2_ADDR_BOFFSET) & 0x1f;
|
|
break;
|
|
case PORT4:
|
|
*phy_addr = (data >> EPHY_CFG_EPHY3_ADDR_BOFFSET) & 0x1f;
|
|
break;
|
|
default:
|
|
pr_debug("qca8084_port_id not matching\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static uint16_t qca8084_uniphy_xpcs_mmd_read(uint16_t mmd_num, uint16_t mmd_reg)
|
|
{
|
|
uint32_t uniphy_xpcs_addr = 0;
|
|
|
|
qca8084_serdes_addr_get(QCA8084_UNIPHY_XPCS, &uniphy_xpcs_addr);
|
|
|
|
return qca8084_phy_mmd_read(uniphy_xpcs_addr, mmd_num, mmd_reg);
|
|
}
|
|
|
|
static void qca8084_uniphy_xpcs_mmd_write(uint16_t mmd_num, uint16_t mmd_reg,
|
|
uint16_t reg_val)
|
|
{
|
|
uint32_t uniphy_xpcs_addr = 0;
|
|
#ifdef DEBUG
|
|
uint16_t phy_data = 0;
|
|
#endif
|
|
|
|
qca8084_serdes_addr_get(QCA8084_UNIPHY_XPCS, &uniphy_xpcs_addr);
|
|
|
|
qca8084_phy_mmd_write(uniphy_xpcs_addr, mmd_num, mmd_reg, reg_val);
|
|
/*check the mmd register value*/
|
|
#ifdef DEBUG
|
|
phy_data =
|
|
#endif
|
|
qca8084_uniphy_xpcs_mmd_read(mmd_num, mmd_reg);
|
|
|
|
pr_debug("phy_addr:0x%x, mmd_num:0x%x, mmd_reg:0x%x, phy_data:0x%x\n",
|
|
uniphy_xpcs_addr, mmd_num, mmd_reg, phy_data);
|
|
}
|
|
|
|
static void qca8084_uniphy_xpcs_modify_mmd(uint32_t mmd_num, uint32_t mmd_reg,
|
|
uint32_t mask, uint32_t value)
|
|
{
|
|
uint16_t phy_data = 0, new_phy_data = 0;
|
|
|
|
phy_data = qca8084_uniphy_xpcs_mmd_read(mmd_num, mmd_reg);
|
|
new_phy_data = (phy_data & ~mask) | value;
|
|
qca8084_uniphy_xpcs_mmd_write(mmd_num, mmd_reg, new_phy_data);
|
|
}
|
|
|
|
uint8_t qca8084_uniphy_mode_check(uint32_t uniphy_index,
|
|
qca8084_uniphy_mode_t uniphy_mode)
|
|
{
|
|
uint32_t uniphy_addr = 0;
|
|
uint16_t uniphy_mode_ctrl_data = 0;
|
|
|
|
qca8084_serdes_addr_get(uniphy_index, &uniphy_addr);
|
|
|
|
uniphy_mode_ctrl_data = qca8084_phy_mmd_read(uniphy_addr,
|
|
QCA8084_UNIPHY_MMD1, QCA8084_UNIPHY_MMD1_MODE_CTRL);
|
|
if(uniphy_mode_ctrl_data == PHY_INVALID_DATA)
|
|
return 0;
|
|
|
|
if(!(uniphy_mode & uniphy_mode_ctrl_data))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static uint32_t qca8084_uniphy_xpcs_port_to_mmd(uint32_t qca8084_port_id)
|
|
{
|
|
uint32_t mmd_id = 0;
|
|
|
|
switch(qca8084_port_id)
|
|
{
|
|
case PORT1:
|
|
mmd_id = QCA8084_UNIPHY_MMD31;
|
|
break;
|
|
case PORT2:
|
|
mmd_id = QCA8084_UNIPHY_MMD26;
|
|
break;
|
|
case PORT3:
|
|
mmd_id = QCA8084_UNIPHY_MMD27;
|
|
break;
|
|
case PORT4:
|
|
mmd_id = QCA8084_UNIPHY_MMD28;
|
|
break;
|
|
default:
|
|
pr_debug("Port not matching qca8084 ports\n");
|
|
}
|
|
|
|
return mmd_id;
|
|
}
|
|
|
|
static void qca8084_uniphy_xpcs_modify_port_mmd(uint32_t qca8084_port_id,
|
|
uint32_t mmd_reg, uint32_t mask,
|
|
uint32_t value)
|
|
{
|
|
uint32_t mmd_id = 0;
|
|
|
|
mmd_id = qca8084_uniphy_xpcs_port_to_mmd(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;
|
|
|
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_AN_LP_BASE_ABL2);
|
|
if(!(uniphy_data & QCA8084_UNIPHY_MMD3_XPCS_EEE_CAP))
|
|
return;
|
|
|
|
/*Configure the EEE related timer*/
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_EEE_MODE_CTRL,
|
|
0x0f40, QCA8084_UNIPHY_MMD3_EEE_RES_REGS |
|
|
QCA8084_UNIPHY_MMD3_EEE_SIGN_BIT_REGS);
|
|
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_EEE_TX_TIMER,
|
|
0x1fff, QCA8084_UNIPHY_MMD3_EEE_TSL_REGS|
|
|
QCA8084_UNIPHY_MMD3_EEE_TLU_REGS |
|
|
QCA8084_UNIPHY_MMD3_EEE_TWL_REGS);
|
|
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_EEE_RX_TIMER,
|
|
0x1fff, QCA8084_UNIPHY_MMD3_EEE_100US_REG_REGS|
|
|
QCA8084_UNIPHY_MMD3_EEE_RWR_REG_REGS);
|
|
|
|
/*enable TRN_LPI*/
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_EEE_MODE_CTRL1,
|
|
0x101, QCA8084_UNIPHY_MMD3_EEE_TRANS_LPI_MODE|
|
|
QCA8084_UNIPHY_MMD3_EEE_TRANS_RX_LPI_MODE);
|
|
|
|
/*enable TX/RX LPI pattern*/
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_EEE_MODE_CTRL,
|
|
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;
|
|
uint32_t retries = 100, linkup = 0;
|
|
|
|
/* wait 10G_R link up */
|
|
while (linkup != QCA8084_UNIPHY_MMD3_10GBASE_R_UP) {
|
|
mdelay(1);
|
|
if (retries-- == 0)
|
|
pr_debug("10g_r link up timeout\n");
|
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_10GBASE_R_PCS_STATUS1);
|
|
|
|
linkup = (uniphy_data & QCA8084_UNIPHY_MMD3_10GBASE_R_UP);
|
|
}
|
|
}
|
|
|
|
static void qca8084_uniphy_xpcs_soft_reset(void)
|
|
{
|
|
uint16_t uniphy_data = 0;
|
|
uint32_t retries = 100, reset_done = QCA8084_UNIPHY_MMD3_XPCS_SOFT_RESET;
|
|
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_DIG_CTRL1, 0x8000,
|
|
QCA8084_UNIPHY_MMD3_XPCS_SOFT_RESET);
|
|
|
|
while (reset_done) {
|
|
mdelay(1);
|
|
if (retries-- == 0)
|
|
pr_debug("xpcs soft reset timeout\n");
|
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_DIG_CTRL1);
|
|
|
|
reset_done = (uniphy_data & QCA8084_UNIPHY_MMD3_XPCS_SOFT_RESET);
|
|
}
|
|
}
|
|
|
|
void qca8084_uniphy_xpcs_speed_set(uint32_t qca8084_port_id,
|
|
fal_port_speed_t speed)
|
|
{
|
|
uint32_t xpcs_speed = 0;
|
|
|
|
switch(speed)
|
|
{
|
|
case FAL_SPEED_2500:
|
|
xpcs_speed = QCA8084_UNIPHY_MMD_XPC_SPEED_2500;
|
|
break;
|
|
case FAL_SPEED_1000:
|
|
xpcs_speed = QCA8084_UNIPHY_MMD_XPC_SPEED_1000;
|
|
break;
|
|
case FAL_SPEED_100:
|
|
xpcs_speed = QCA8084_UNIPHY_MMD_XPC_SPEED_100;
|
|
break;
|
|
case FAL_SPEED_10:
|
|
xpcs_speed = QCA8084_UNIPHY_MMD_XPC_SPEED_10;
|
|
break;
|
|
default:
|
|
pr_debug("Unknown speed\n");
|
|
return;
|
|
}
|
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
|
QCA8084_UNIPHY_MMD_MII_CTRL,
|
|
QCA8084_UNIPHY_MMD_XPC_SPEED_MASK,
|
|
xpcs_speed);
|
|
}
|
|
|
|
void qca8084_uniphy_uqxgmii_function_reset(uint32_t qca8084_port_id)
|
|
{
|
|
uint32_t uniphy_addr = 0;
|
|
|
|
qca8084_serdes_addr_get(QCA8084_UNIPHY_SGMII_1, &uniphy_addr);
|
|
|
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
|
QCA8084_UNIPHY_MMD1_USXGMII_RESET, BIT(qca8084_port_id-1), 0);
|
|
mdelay(1);
|
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
|
QCA8084_UNIPHY_MMD1_USXGMII_RESET, BIT(qca8084_port_id-1),
|
|
BIT(qca8084_port_id-1));
|
|
if(qca8084_port_id == PORT1)
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD_MII_DIG_CTRL,
|
|
0x400, QCA8084_UNIPHY_MMD3_USXG_FIFO_RESET);
|
|
else
|
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
|
QCA8084_UNIPHY_MMD_MII_DIG_CTRL,
|
|
0x20, QCA8084_UNIPHY_MMD_USXG_FIFO_RESET);
|
|
}
|
|
|
|
void qca8084_uniphy_xpcs_autoneg_restart(uint32_t qca8084_port_id)
|
|
{
|
|
uint32_t retries = 500, uniphy_data = 0, mmd_id = 0;
|
|
|
|
mmd_id = qca8084_uniphy_xpcs_port_to_mmd(qca8084_port_id);
|
|
qca8084_uniphy_xpcs_modify_mmd(mmd_id, QCA8084_UNIPHY_MMD_MII_CTRL,
|
|
QCA8084_UNIPHY_MMD_MII_AN_RESTART, QCA8084_UNIPHY_MMD_MII_AN_RESTART);
|
|
mdelay(1);
|
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(mmd_id,
|
|
QCA8084_UNIPHY_MMD_MII_ERR_SEL);
|
|
while(!(uniphy_data & QCA8084_UNIPHY_MMD_MII_AN_COMPLETE_INT))
|
|
{
|
|
mdelay(1);
|
|
if (retries-- == 0)
|
|
{
|
|
pr_debug("xpcs uniphy autoneg restart timeout\n");
|
|
}
|
|
uniphy_data = qca8084_uniphy_xpcs_mmd_read(mmd_id,
|
|
QCA8084_UNIPHY_MMD_MII_ERR_SEL);
|
|
}
|
|
}
|
|
|
|
static void _qca8084_interface_uqxgmii_mode_set(uint32_t uniphy_addr)
|
|
{
|
|
uint32_t qca8084_port_id = 0, phy_addr = 0;
|
|
|
|
/*reset xpcs*/
|
|
pr_debug("reset xpcs\n");
|
|
qca8084_clk_assert(QCA8084_UNIPHY_XPCS_RST);
|
|
/*select xpcs mode*/
|
|
pr_debug("select xpcs mode\n");
|
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
|
QCA8084_UNIPHY_MMD1_MODE_CTRL, 0x1f00, QCA8084_UNIPHY_MMD1_XPCS_MODE);
|
|
/*config dapa pass as usxgmii*/
|
|
pr_debug("config dapa pass as usxgmii\n");
|
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
|
QCA8084_UNIPHY_MMD1_GMII_DATAPASS_SEL, QCA8084_UNIPHY_MMD1_DATAPASS_MASK,
|
|
QCA8084_UNIPHY_MMD1_DATAPASS_USXGMII);
|
|
/*reset and release uniphy GMII/XGMII and ethphy GMII*/
|
|
pr_debug("reset and release uniphy GMII/XGMII and ethphy GMII\n");
|
|
for(qca8084_port_id = PORT1; qca8084_port_id <= PORT4;
|
|
qca8084_port_id++)
|
|
{
|
|
qca8084_port_clk_reset(qca8084_port_id,
|
|
QCA8084_CLK_TYPE_UNIPHY|QCA8084_CLK_TYPE_EPHY);
|
|
}
|
|
|
|
/*ana sw reset and release*/
|
|
pr_debug("ana sw reset and release\n");
|
|
qca8084_phy_modify_mii(uniphy_addr,
|
|
QCA8084_UNIPHY_PLL_POWER_ON_AND_RESET, 0x40, QCA8084_UNIPHY_ANA_SOFT_RESET);
|
|
mdelay(10);
|
|
qca8084_phy_modify_mii(uniphy_addr,
|
|
QCA8084_UNIPHY_PLL_POWER_ON_AND_RESET, 0x40, QCA8084_UNIPHY_ANA_SOFT_RELEASE);
|
|
|
|
/*Wait calibration done*/
|
|
pr_debug("Wait calibration done\n");
|
|
qca8084_uniphy_calibration(uniphy_addr);
|
|
/*Enable SSCG(Spread Spectrum Clock Generator)*/
|
|
pr_debug("enable uniphy sscg\n");
|
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
|
QCA8084_UNIPHY_MMD1_CDA_CONTROL1, 0x8, QCA8084_UNIPHY_MMD1_SSCG_ENABLE);
|
|
/*release XPCS*/
|
|
pr_debug("release XPCS\n");
|
|
qca8084_clk_deassert(QCA8084_UNIPHY_XPCS_RST);
|
|
/*ethphy software reset*/
|
|
pr_debug("ethphy software reset\n");
|
|
for(qca8084_port_id = PORT1; qca8084_port_id <= PORT4;
|
|
qca8084_port_id++)
|
|
{
|
|
qca8084_ephy_addr_get(qca8084_port_id, &phy_addr);
|
|
qca8084_phy_reset(phy_addr);
|
|
}
|
|
/*Set BaseR mode*/
|
|
pr_debug("Set BaseR mode\n");
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_PCS_CTRL2, 0xf, QCA8084_UNIPHY_MMD3_PCS_TYPE_10GBASE_R);
|
|
/*wait 10G base_r link up*/
|
|
pr_debug("wait 10G base_r link up\n");
|
|
qca8084_uniphy_xpcs_10g_r_linkup();
|
|
/*enable UQXGMII mode*/
|
|
pr_debug("enable UQSXGMII mode\n");
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_DIG_CTRL1, 0x200, QCA8084_UNIPHY_MMD3_USXGMII_EN);
|
|
/*set UQXGMII mode*/
|
|
pr_debug("set QXGMII mode\n");
|
|
qca8084_uniphy_xpcs_modify_mmd(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_VR_RPCS_TPC, 0x1c00, QCA8084_UNIPHY_MMD3_QXGMII_EN);
|
|
/*set AM interval*/
|
|
pr_debug("set AM interval\n");
|
|
qca8084_uniphy_xpcs_mmd_write(QCA8084_UNIPHY_MMD3,
|
|
QCA8084_UNIPHY_MMD3_MII_AM_INTERVAL, QCA8084_UNIPHY_MMD3_MII_AM_INTERVAL_VAL);
|
|
/*xpcs software reset*/
|
|
pr_debug("xpcs software reset\n");
|
|
qca8084_uniphy_xpcs_soft_reset();
|
|
}
|
|
|
|
void qca8084_interface_uqxgmii_mode_set(void)
|
|
{
|
|
uint32_t uniphy_addr = 0, qca8084_port_id = 0;
|
|
|
|
qca8084_serdes_addr_get(QCA8084_UNIPHY_SGMII_1, &uniphy_addr);
|
|
|
|
/*disable IPG_tuning bypass*/
|
|
pr_debug("disable IPG_tuning bypass\n");
|
|
qca8084_phy_modify_mmd(uniphy_addr, QCA8084_UNIPHY_MMD1,
|
|
QCA8084_UNIPHY_MMD1_BYPASS_TUNING_IPG,
|
|
QCA8084_UNIPHY_MMD1_BYPASS_TUNING_IPG_EN, 0);
|
|
/*disable uniphy GMII/XGMII clock and disable ethphy GMII clock*/
|
|
pr_debug("disable uniphy GMII/XGMII clock and ethphy GMII clock\n");
|
|
for(qca8084_port_id = PORT1; qca8084_port_id <= PORT4;
|
|
qca8084_port_id++)
|
|
{
|
|
qca8084_port_clk_en_set(qca8084_port_id,
|
|
QCA8084_CLK_TYPE_UNIPHY|QCA8084_CLK_TYPE_EPHY, 0);
|
|
}
|
|
/*configure uqxgmii mode*/
|
|
pr_debug("configure uqxgmii mode\n");
|
|
_qca8084_interface_uqxgmii_mode_set(uniphy_addr);
|
|
/*enable auto-neg complete interrupt,Mii using mii-4bits,
|
|
configure as PHY mode, enable autoneg ability*/
|
|
pr_debug("enable auto-neg complete interrupt, Mii using mii-4bits,"
|
|
" configure as PHY mode, enable autoneg ability, disable TICD\n");
|
|
for (qca8084_port_id = PORT1; qca8084_port_id <= PORT4;
|
|
qca8084_port_id++)
|
|
{
|
|
/*enable auto-neg complete interrupt,Mii using mii-4bits,configure as PHY mode*/
|
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
|
QCA8084_UNIPHY_MMD_MII_AN_INT_MSK, 0x109,
|
|
QCA8084_UNIPHY_MMD_AN_COMPLETE_INT |
|
|
QCA8084_UNIPHY_MMD_MII_4BITS_CTRL |
|
|
QCA8084_UNIPHY_MMD_TX_CONFIG_CTRL);
|
|
|
|
/*enable autoneg ability*/
|
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
|
QCA8084_UNIPHY_MMD_MII_CTRL, 0x3060, QCA8084_UNIPHY_MMD_MII_AN_ENABLE |
|
|
QCA8084_UNIPHY_MMD_XPC_SPEED_1000);
|
|
|
|
/*disable TICD*/
|
|
qca8084_uniphy_xpcs_modify_port_mmd(qca8084_port_id,
|
|
QCA8084_UNIPHY_MMD_MII_XAUI_MODE_CTRL, 0x1,
|
|
QCA8084_UNIPHY_MMD_TX_IPG_CHECK_DISABLE);
|
|
}
|
|
|
|
/*enable EEE for xpcs*/
|
|
pr_debug("enable EEE for xpcs\n");
|
|
qca8084_uniphy_xpcs_8023az_enable();
|
|
}
|