ipq5018: Fix S17C auto-negotiation issue

This changes enable s17c link upto 1Gbps speed.

Signed-off-by: Vandhiadevan Karunamoorthy <vkarunam@codeaurora.org>
Change-Id: I78e3efbbfd1bad58ab2abcba87c06cb9d4ffcd18
This commit is contained in:
Vandhiadevan Karunamoorthy 2020-06-26 15:54:19 +05:30
parent 2cce43f909
commit 82c05e91fa
5 changed files with 86 additions and 47 deletions

View file

@ -17,6 +17,12 @@
#include <net.h>
#include <configs/ipq5018.h>
#define LINK(_data) (_data & 0x400)? "Up" : "Down"
#define DUPLEX(_data) (_data & 0x2000)? "Full duplex" : "Half duplex"
#define SPEED(_data) ((_data & 0xC000) >> 12)
#define SPEED_1000M (1 << 3)
#define SPEED_100M (1 << 2)
#define GEPHY 0x004DD0C0
#define S17C 0x1302

View file

@ -48,6 +48,9 @@ struct sdhci_host mmc_host;
extern int ipq_spi_init(u16);
#endif
extern void ppe_uniphy_set_forceMode(void);
extern void ppe_uniphy_refclk_set(void);
unsigned int qpic_frequency = 0, qpic_phase = 0;
const char *rsvd_node = "/reserved-memory";
@ -618,7 +621,7 @@ static void set_ext_mdio_gpio(int node)
{
unsigned int mdio_gpio[2] = {0};
int status = -1;
unsigned int *s17C_gpio_base;
unsigned int *mdio_gpio_base;
status = fdtdec_get_int_array(gd->fdt_blob,
node,
@ -627,13 +630,13 @@ static void set_ext_mdio_gpio(int node)
2);
if (status >= 0) {
/* mdc */
s17C_gpio_base =
mdio_gpio_base =
(unsigned int *)GPIO_CONFIG_ADDR(mdio_gpio[0]);
writel(0x7, s17C_gpio_base);
writel(0x7, mdio_gpio_base);
/* mdio */
s17C_gpio_base =
mdio_gpio_base =
(unsigned int *)GPIO_CONFIG_ADDR(mdio_gpio[1]);
writel(0x7, s17C_gpio_base);
writel(0x7, mdio_gpio_base);
}
}
@ -652,6 +655,11 @@ static void reset_s17c_switch_gpio(int gpio)
{
unsigned int *switch_gpio_base =
(unsigned int *)GPIO_CONFIG_ADDR(gpio);
/*
* Set ref clock 25MHZ and enable Force mode
*/
ppe_uniphy_refclk_set();
ppe_uniphy_set_forceMode();
writel(0x203, switch_gpio_base);
writel(0x0, GPIO_IN_OUT_ADDR(gpio));
@ -878,21 +886,6 @@ static void cmnblk_check_state(void)
}
}
static void uniphy_refclk_set(void)
{
/*
* This function drive the uniphy ref clock
* DEC_REFCLKOUTPUTCONTROLREGISTERS
* Its is configured as 25 MHZ
*/
#define UNIPHY_REF_CLK_CTRL_REG 0x98074
u32 reg_val = readl(UNIPHY_REF_CLK_CTRL_REG);
reg_val |= 0x2;
writel(reg_val, UNIPHY_REF_CLK_CTRL_REG);
mdelay(500);
}
static void gcc_clock_enable(void)
{
u32 reg_val;
@ -968,7 +961,6 @@ static void ethernet_clock_enable(void)
gephy_reset();
uniphy_reset();
gmac_reset();
uniphy_refclk_set();
gcc_clock_enable();
}

View file

@ -303,6 +303,38 @@ static void ipq5018_enable_gephy(void)
mdelay(20);
}
static int ipq5018_s17c_Link_Update(struct ipq_eth_dev *priv)
{
uint16_t phy_data;
int status = 1;
for(int i = 0;
i < priv->gmac_board_cfg->switch_port_count; ++i){
phy_data = ipq_mdio_read(
priv->gmac_board_cfg->switch_port_phy_address[i],
0x11,
NULL);
if (phy_data == 0x50)
continue;
status = 0;
printf("Port%d %s ", i + 1, LINK(phy_data));
switch(SPEED(phy_data)){
case SPEED_1000M:
printf("Speed :1000M ");
break;
case SPEED_100M:
printf("Speed :100M ");
break;
default:
printf("Speed :10M ");
}
printf ("%s \n", DUPLEX(phy_data));
}
return status;
}
static int ipq5018_phy_link_update(struct eth_device *dev)
{
struct ipq_eth_dev *priv = dev->priv;
@ -328,7 +360,7 @@ static int ipq5018_phy_link_update(struct eth_device *dev)
if (priv->ipq_swith) {
speed_clock1 = 1;
speed_clock2 = 0;
status = 0;
status = ipq5018_s17c_Link_Update(priv);
} else {
status = phy_get_ops->phy_get_link_status(priv->mac_unit,
priv->phy_address);
@ -380,23 +412,23 @@ static int ipq5018_phy_link_update(struct eth_device *dev)
}
}
if (status) {
/* No PHY link is alive */
return -1;
}
if (priv->mac_unit){
if (priv->phy_type == QCA8081_PHY_TYPE ||
priv->phy_type == QCA8081_1_1_PHY)
ppe_uniphy_mode_set(PORT_WRAPPER_SGMII_PLUS);
else
ppe_uniphy_mode_set(PORT_WRAPPER_SGMII_FIBER);
ppe_uniphy_mode_set(PORT_WRAPPER_SGMII0_RGMII4);
} else {
ipq5018_enable_gephy();
}
ipq5018_gmac0_speed_clock_set(speed_clock1, speed_clock2, priv->mac_unit);
if (status) {
/* No PHY link is alive */
return -1;
}
return 0;
}
@ -665,8 +697,6 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg)
for (int port = 0;
port < gmac_cfg->switch_port_count;
++port) {
u32 value;
ipq_mdio_write(port, MII_ADVERTISE, ADVERTISE_ALL |
ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
/*
@ -674,12 +704,8 @@ int ipq_gmac_init(ipq_gmac_board_cfg_t *gmac_cfg)
*/
ipq_mdio_write(port, MII_CTRL1000, (0x0400|ADVERTISE_1000FULL));
ipq_mdio_write(port, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
value = ipq_mdio_read(port, 0, NULL);
value &= (~(1<<12));
ipq_mdio_write(port, 0, value);
mdelay(100);
}
} else {
phy_chip_id1 = ipq_mdio_read(
ipq_gmac_macs[i]->phy_address,

View file

@ -59,8 +59,6 @@ static void ppe_gcc_uniphy_soft_reset(void)
static void ppe_uniphy_sgmii_mode_set(uint32_t mode)
{
bool force_enable =false;
writel(UNIPHY_MISC2_REG_SGMII_MODE,
PPE_UNIPHY_BASE + UNIPHY_MISC2_REG_OFFSET);
@ -83,7 +81,6 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t mode)
switch (mode) {
case PORT_WRAPPER_SGMII_FIBER:
writel(UNIPHY_SG_MODE, PPE_UNIPHY_BASE + PPE_UNIPHY_MODE_CONTROL);
force_enable = true;
break;
case PORT_WRAPPER_SGMII0_RGMII4:
@ -91,7 +88,6 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t mode)
case PORT_WRAPPER_SGMII4_RGMII4:
writel((UNIPHY_SG_MODE | UNIPHY_PSGMII_MAC_MODE),
PPE_UNIPHY_BASE + PPE_UNIPHY_MODE_CONTROL);
force_enable = true;
break;
case PORT_WRAPPER_SGMII_PLUS:
@ -116,15 +112,6 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t mode)
udelay(500);
ppe_uniphy_calibration();
/*
* Force Speed mode enable
*/
if(force_enable){
writel((readl(PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4) |
UNIPHY_FORCE_SPEED_25M),
PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4);
}
}
void ppe_uniphy_mode_set(uint32_t mode)
@ -135,3 +122,27 @@ void ppe_uniphy_mode_set(uint32_t mode)
ppe_uniphy_sgmii_mode_set(mode);
}
void ppe_uniphy_set_forceMode(void)
{
uint32_t reg_value;
reg_value = readl(PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4);
reg_value |= UNIPHY_FORCE_SPEED_25M;
writel(reg_value, PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4);
}
void ppe_uniphy_refclk_set(void)
{
/*
* This function drive the uniphy ref clock
* DEC_REFCLKOUTPUTCONTROLREGISTERS
* Its is configured as 25 MHZ
*/
u32 reg_val = readl(PPE_UNIPHY_BASE | UNIPHY_REF_CLK_CTRL_REG);
reg_val |= 0x2;
writel(reg_val, PPE_UNIPHY_BASE | UNIPHY_REF_CLK_CTRL_REG);
mdelay(200);
}

View file

@ -46,6 +46,8 @@
#define UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4 0x480
#define UNIPHY_FORCE_SPEED_25M (1 << 3)
#define UNIPHY_REF_CLK_CTRL_REG 0x74
#define UNIPHY_INSTANCE_LINK_DETECT 0x570
#define UNIPHY_MISC2_REG_OFFSET 0x218
@ -59,4 +61,6 @@
#define UNIPHY_PLL_RESET_REG_DEFAULT_VALUE 0x02ff
void ppe_uniphy_mode_set(uint32_t mode);
void ppe_uniphy_set_forceMode(void);
void ppe_uniphy_refclk_set(void);
#endif