drivers: net: ipq9574: Add Support for SFP

Change-Id: I8cd09a85c03405de0c7e4b5d5ed3f5fc7fee8147
Signed-off-by: Selvam Sathappan Periakaruppan <speriaka@codeaurora.org>
This commit is contained in:
Selvam Sathappan Periakaruppan 2021-08-21 02:02:54 +05:30 committed by Gerrit - the friendly Code Review server
parent 05b77e3907
commit 56525cc2a7
3 changed files with 142 additions and 31 deletions

View file

@ -602,6 +602,27 @@ int set_uuid_bootargs(char *boot_args, char *part_name, int buflen, bool gpt_fla
#endif
#ifdef CONFIG_IPQ9574_EDMA
int get_sfp_gpio(int sfp_gpio[2])
{
int sfp_gpio_cnt = -1, node;
int res = -1;
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
if (node >= 0) {
sfp_gpio_cnt = fdtdec_get_uint(gd->fdt_blob, node, "sfp_gpio_cnt", -1);
if (sfp_gpio_cnt >= 1) {
res = fdtdec_get_int_array(gd->fdt_blob, node, "sfp_gpio",
(u32 *)sfp_gpio, sfp_gpio_cnt);
if (res >= 0)
return sfp_gpio_cnt;
}
}
return res;
}
int get_aquantia_gpio(int aquantia_gpio[2])
{
int aquantia_gpio_cnt = -1, node;
@ -659,6 +680,24 @@ int get_qca807x_gpio(int qca807x_gpio[2])
return res;
}
void sfp_reset_init(void)
{
int sfp_gpio[2] = {-1, -1}, sfp_gpio_cnt, i;
unsigned int *sfp_gpio_base;
uint32_t cfg;
sfp_gpio_cnt = get_sfp_gpio(sfp_gpio);
if (sfp_gpio_cnt >= 1) {
for (i = 0; i < sfp_gpio_cnt; i++) {
if (sfp_gpio[i] >= 0) {
sfp_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(sfp_gpio[i]);
cfg = GPIO_OE | GPIO_DRV_8_MA | GPIO_PULL_UP;
writel(cfg, sfp_gpio_base);
}
}
}
}
void aquantia_phy_reset_init(void)
{
int aquantia_gpio[2] = {-1, -1}, aquantia_gpio_cnt, i;
@ -1079,6 +1118,7 @@ void bring_phy_out_of_reset(void)
qca807x_phy_reset_init();
aquantia_phy_reset_init();
qca808x_phy_reset_init();
sfp_reset_init();
mdelay(500);
qca807x_phy_reset_init_done();
aquantia_phy_reset_init_done();

View file

@ -941,11 +941,13 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
fal_port_duplex_t duplex;
char *lstatus[] = {"up", "Down"};
char *dp[] = {"Half", "Full"};
int linkup=0;
int linkup = 0;
int clk[4] = {0};
int phy_addr, node, aquantia_port[2] = {-1, -1}, aquantia_port_cnt = -1;
int phy_addr = -1, node = -1;
int aquantia_port[2] = {-1, -1}, aquantia_port_cnt = -1;
int sfp_port[2] = {-1, -1}, sfp_port_cnt = -1;
int sgmii_mode = -1, sfp_mode = -1, sgmii_fiber = -1;
int phy_node = -1, res = -1;
int sgmii_mode;
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
@ -956,7 +958,16 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
res = fdtdec_get_int_array(gd->fdt_blob, node, "aquantia_port",
(u32 *)aquantia_port, aquantia_port_cnt);
if (res < 0)
printf("Error: Aquantia port details not provided in DT");
printf("Error: Aquantia port details not provided in DT\n");
}
sfp_port_cnt = fdtdec_get_uint(gd->fdt_blob, node, "sfp_port_cnt", -1);
if (sfp_port_cnt >= 1) {
res = fdtdec_get_int_array(gd->fdt_blob, node, "sfp_port",
(u32 *)sfp_port, sfp_port_cnt);
if (res < 0)
printf("Error: SFP port details not provided in DT\n");
}
}
@ -967,33 +978,68 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
* else we will return with -1;
*/
for (i = 0; i < IPQ9574_PHY_MAX; i++) {
if (!priv->ops[i]) {
printf("Phy ops not mapped\n");
continue;
}
phy_get_ops = priv->ops[i];
if (!phy_get_ops->phy_get_link_status ||
!phy_get_ops->phy_get_speed ||
!phy_get_ops->phy_get_duplex) {
printf("Error:Link status/Get speed/Get duplex not mapped\n");
return -1;
}
if (phy_node >= 0) {
/*
* For each ethernet port, one node should be added
* inside port_phyinfo with appropriate phy address
if (i == sfp_port[0] || i == sfp_port[1]) {
status = phy_status_get_from_ppe(i);
duplex = FAL_FULL_DUPLEX;
/* SFP Port can be enabled in USXGMII0 or USXGMII1 i.e
* SFP Port can be port5 or port6 (with port id - 4 or 5).
* Port5 (port id - 4) -> Serdes1
* Port6 (port id - 5) -> Serdes2
*/
phy_addr = phy_info[i]->phy_address;
if (i == 4) {
sfp_mode = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode1", -1);
if (sfp_mode < 0) {
printf("Error: switch_mac_mode1 not specified in dts\n");
return sfp_mode;
}
} else if (i == 5) {
sfp_mode = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode2", -1);
if (sfp_mode < 0) {
printf("Error: switch_mac_mode2 not specified in dts\n");
return sfp_mode;
}
} else {
printf("Error: SFP Port can be enabled in USXGMII0 or USXGMII1 (Port5 or Port6) only in ipq9574 platform\n");
}
if (sfp_mode == EPORT_WRAPPER_SGMII_FIBER) {
sgmii_fiber = 1;
curr_speed[i] = FAL_SPEED_1000;
} else if (sfp_mode == EPORT_WRAPPER_10GBASE_R) {
sgmii_fiber = 0;
curr_speed[i] = FAL_SPEED_10000;
} else {
printf("Error: Wrong mode specified for SFP Port in DT\n");
return sfp_mode;
}
} else {
printf("Error:Phy addresses not configured in DT\n");
return -1;
}
if (!priv->ops[i]) {
printf("Phy ops not mapped\n");
continue;
}
phy_get_ops = priv->ops[i];
status = phy_get_ops->phy_get_link_status(priv->mac_unit, phy_addr);
phy_get_ops->phy_get_speed(priv->mac_unit, phy_addr, &curr_speed[i]);
phy_get_ops->phy_get_duplex(priv->mac_unit, phy_addr, &duplex);
if (!phy_get_ops->phy_get_link_status ||
!phy_get_ops->phy_get_speed ||
!phy_get_ops->phy_get_duplex) {
printf("Error:Link status/Get speed/Get duplex not mapped\n");
return -1;
}
if (phy_node >= 0) {
/*
* For each ethernet port, one node should be added
* inside port_phyinfo with appropriate phy address
*/
phy_addr = phy_info[i]->phy_address;
} else {
printf("Error:Phy addresses not configured in DT\n");
return -1;
}
status = phy_get_ops->phy_get_link_status(priv->mac_unit, phy_addr);
phy_get_ops->phy_get_speed(priv->mac_unit, phy_addr, &curr_speed[i]);
phy_get_ops->phy_get_duplex(priv->mac_unit, phy_addr, &duplex);
}
if (status == 0) {
linkup++;
@ -1092,6 +1138,11 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
clk[0] = 0x204;
clk[2] = 0x304;
}
} else if (i == sfp_port[0] || i == sfp_port[1]) {
if (i == 4) {
clk[0] = 0x401;
clk[2] = 0x501;
}
}
if (phy_node >= 0) {
if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) {
@ -1190,12 +1241,31 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
}
}
if (i == sfp_port[0] || i == sfp_port[1]) {
if (sgmii_fiber) {
ppe_port_bridge_txmac_set(i + 1, 1);
if (i == 4)
ppe_uniphy_mode_set(0x1, EPORT_WRAPPER_SGMII_FIBER);
else
ppe_uniphy_mode_set(0x2, EPORT_WRAPPER_SGMII_FIBER);
ppe_port_mux_mac_type_set(i + 1, EPORT_WRAPPER_SGMII_FIBER);
} else {
if (i == 4)
ppe_uniphy_mode_set(0x1, EPORT_WRAPPER_10GBASE_R);
else
ppe_uniphy_mode_set(0x2, EPORT_WRAPPER_10GBASE_R);
ppe_port_mux_mac_type_set(i + 1, EPORT_WRAPPER_10GBASE_R);
}
}
ipq9574_speed_clock_set(i, clk);
ipq9574_port_mac_clock_reset(i);
if (i == aquantia_port[0] || i == aquantia_port[1])
ipq9574_uxsgmii_speed_set(i, mac_speed, duplex, status);
else if (i == sfp_port[0] || i == sfp_port[1])
ipq9574_10g_r_speed_set(i, status);
else
ipq9574_pqsgmii_speed_set(i, mac_speed, status);
}
@ -1962,8 +2032,9 @@ int ipq9574_edma_init(void *edma_board_cfg)
break;
#endif
default:
printf("\nphy chip id: 0x%x id not matching for phy id: 0x%x",
phy_chip_id, phy_id);
if (phy_info[phy_id]->phy_type != SFP_PHY_TYPE)
printf("\nphy chip id: 0x%x id not matching for phy id: 0x%x",
phy_chip_id, phy_id);
break;
}
}

View file

@ -124,7 +124,7 @@ union ipo_action_u {
#define IPQ9574_PORT_MUX_CTRL_DEFAULT 0x0
#define PORT_PHY_STATUS_ADDRESS 0x44
#define PORT_PHY_STATUS_PORT5_1_OFFSET 16
#define PORT_PHY_STATUS_PORT5_1_OFFSET 8
#define PORT_PHY_STATUS_PORT6_OFFSET 16
#define IPQ9574_PPE_IPE_L3_BASE_ADDR 0x200000