mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2025-12-10 07:44:53 +01:00
drivers: net: ipq9574: Add Support for SFP
Change-Id: I8cd09a85c03405de0c7e4b5d5ed3f5fc7fee8147 Signed-off-by: Selvam Sathappan Periakaruppan <speriaka@codeaurora.org>
This commit is contained in:
parent
05b77e3907
commit
56525cc2a7
3 changed files with 142 additions and 31 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue