Merge "ipq807x: Add SFP 10G ethernet support"

This commit is contained in:
Linux Build Service Account 2018-11-13 12:13:00 -08:00 committed by Gerrit - the friendly Code Review server
commit 40e31c6f85
8 changed files with 117 additions and 25 deletions

View file

@ -30,8 +30,9 @@
};
ess-switch {
switch_mac_mode = <0x5>;
switch_mac_mode1 = <0xFF>;
switch_mac_mode1 = <0x7>;
switch_mac_mode2 = <0x2>;
sfp_port = <4>;
aquantia_port = <5>;
aquantia_gpio = <44>;
};

View file

@ -892,6 +892,7 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
int linkup=0;
int mac_speed = 0, speed_clock1 = 0, speed_clock2 = 0;
int phy_addr, port_8033 = -1, node, aquantia_port = -1;
int sfp_port = -1;
int phy_node = -1;
int ret_sgmii_mode;
@ -902,6 +903,9 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
if (node >= 0)
aquantia_port = fdtdec_get_uint(gd->fdt_blob, node, "aquantia_port", -1);
if (node >= 0)
sfp_port = fdtdec_get_uint(gd->fdt_blob, node, "sfp_port", -1);
phy_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/port_phyinfo");
/*
* Check PHY link, speed, Duplex on all phys.
@ -909,35 +913,44 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
* else we will return with -1;
*/
for (i = 0; i < 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 ("Link status/Get speed/Get duplex not mapped\n");
return -1;
}
if (phy_node >= 0) {
phy_addr = phy_info[i]->phy_address;
if (i == sfp_port) {
status = phy_status_get_from_ppe(i);
speed = FAL_SPEED_10000;
duplex = FAL_FULL_DUPLEX;
} else {
if (!priv->ops[i]) {
printf ("Phy ops not mapped\n");
continue;
}
phy_get_ops = priv->ops[i];
if (i == port_8033)
phy_addr = QCA8033_PHY_ADDR;
else if (i == aquantia_port)
phy_addr = AQU_PHY_ADDR;
else
phy_addr = i;
if (!phy_get_ops->phy_get_link_status ||
!phy_get_ops->phy_get_speed ||
!phy_get_ops->phy_get_duplex) {
printf ("Link status/Get speed/Get duplex not mapped\n");
return -1;
}
if (phy_node >= 0) {
phy_addr = phy_info[i]->phy_address;
} else {
if (i == port_8033)
phy_addr = QCA8033_PHY_ADDR;
else if (i == aquantia_port)
phy_addr = AQU_PHY_ADDR;
else
phy_addr = 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, &speed);
phy_get_ops->phy_get_duplex(priv->mac_unit, phy_addr, &duplex);
}
status = phy_get_ops->phy_get_link_status(priv->mac_unit, phy_addr);
if (status == 0)
linkup++;
phy_get_ops->phy_get_speed(priv->mac_unit, phy_addr, &speed);
phy_get_ops->phy_get_duplex(priv->mac_unit, phy_addr, &duplex);
switch (speed) {
case FAL_SPEED_10:
if (i == aquantia_port) {
@ -1001,7 +1014,10 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
break;
case FAL_SPEED_10000:
mac_speed = 0x3;
speed_clock1 = 0x101;
if (i == 4)
speed_clock1 = 0x301;
else
speed_clock1 = 0x101;
speed_clock2 = 0x0;
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
priv->mac_unit, i, lstatus[status], speed,
@ -1077,6 +1093,8 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
ipq807x_speed_clock_set(i, speed_clock1, speed_clock2);
if (i == aquantia_port)
ipq807x_uxsgmii_speed_set(i, mac_speed, duplex, status);
else if (i == sfp_port)
ipq807x_10g_r_speed_set(i, status);
else
ipq807x_pqsgmii_speed_set(i, mac_speed, status);
}

View file

@ -319,5 +319,7 @@ extern void ipq807x_speed_clock_set(int port, int speed_clock1, int speed_clock2
extern void ipq807x_pqsgmii_speed_set(int port, int speed, int status);
extern void ipq807x_uxsgmii_speed_set(int port, int speed, int duplex, int status);
extern void ppe_port_bridge_txmac_sett(int port, int status);
extern void ipq807x_10g_r_speed_set(int port, int status);
extern int phy_status_get_from_ppe(int port_id);
#endif /* ___IPQ807X_EDMA__ */

View file

@ -191,6 +191,19 @@ void ipq807x_speed_clock_set(int port, int speed_clock1, int speed_clock2)
}
}
int phy_status_get_from_ppe(int port_id)
{
uint32_t reg_field = 0;
ipq807x_ppe_reg_read(PORT_PHY_STATUS_ADDRESS, &reg_field);
if (port_id == (PORT5 - PPE_UNIPHY_INSTANCE1))
reg_field >>= PORT_PHY_STATUS_PORT5_1_OFFSET;
else
reg_field >>= PORT_PHY_STATUS_PORT6_OFFSET;
return ((reg_field >> 7) & 0x1) ? 0 : 1;
}
void ppe_port_bridge_txmac_set(int port_id, int status)
{
uint32_t reg_value = 0;
@ -249,7 +262,18 @@ void ppe_xgmac_speed_set(uint32_t uniphy_index, int speed)
}
void ppe_xgmac_10g_r_speed_set(uint32_t uniphy_index)
{
uint32_t reg_value = 0;
ipq807x_ppe_reg_read(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), &reg_value);
reg_value |=JD;
ipq807x_ppe_reg_write(PPE_SWITCH_NSS_SWITCH_XGMAC0 +
(uniphy_index * NSS_SWITCH_XGMAC_MAC_TX_CONFIGURATION), reg_value);
}
void ppe_port_txmac_status_set(uint32_t uniphy_index)
{
@ -289,6 +313,25 @@ void ppe_mac_packet_filter_set(uint32_t uniphy_index)
(uniphy_index * MAC_PACKET_FILTER_INC), 0x81);
}
void ipq807x_10g_r_speed_set(int port, int status)
{
uint32_t uniphy_index;
/* Setting the speed only for PORT5 and PORT6 */
if (port == (PORT5 - PPE_UNIPHY_INSTANCE1))
uniphy_index = PPE_UNIPHY_INSTANCE1;
else if (port == (PORT6 - PPE_UNIPHY_INSTANCE1))
uniphy_index = PPE_UNIPHY_INSTANCE2;
else
return;
ppe_xgmac_10g_r_speed_set(uniphy_index - 1);
ppe_port_bridge_txmac_set(port + 1, status);
ppe_port_txmac_status_set(uniphy_index - 1);
ppe_port_rxmac_status_set(uniphy_index - 1);
ppe_mac_packet_filter_set(uniphy_index - 1);
}
void ipq807x_uxsgmii_speed_set(int port, int speed, int duplex,
int status)
{
@ -1113,6 +1156,9 @@ static void ppe_port_mux_mac_type_set(int port_id, int mode)
case PORT_WRAPPER_USXGMII:
port_type = PORT_XGMAC_TYPE;
break;
case PORT_WRAPPER_10GBASE_R:
port_type = PORT_XGMAC_TYPE;
break;
default:
return;
}

View file

@ -117,6 +117,10 @@ union ipo_action_u {
#define PORT6_GMAC_SEL_GMAC 1
#define PORT6_GMAC_SEL_XGMAC 0
#define PORT_PHY_STATUS_ADDRESS 0x44
#define PORT_PHY_STATUS_PORT5_1_OFFSET 8
#define PORT_PHY_STATUS_PORT6_OFFSET 16
#define IPQ807X_PPE_IPE_L3_BASE_ADDR 0x200000
#define IPQ807X_PPE_L3_VP_PORT_TBL_ADDR (IPQ807X_PPE_IPE_L3_BASE_ADDR + 0x1000)
#define IPQ807X_PPE_L3_VP_PORT_TBL_INC 0x10

View file

@ -194,6 +194,21 @@ static int ppe_uniphy_10g_r_linkup(uint32_t uniphy_index)
return 0;
}
static void ppe_uniphy_10g_r_mode_set(uint32_t uniphy_index)
{
uint32_t reg_value = 0;
ppe_gcc_uniphy_xpcs_reset(uniphy_index, true);
writel(0x1021, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
writel(0x1C0, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ UNIPHY_INSTANCE_LINK_DETECT);
ppe_gcc_uniphy_soft_reset(uniphy_index);
ppe_uniphy_calibration(uniphy_index);
ppe_gcc_uniphy_xpcs_reset(uniphy_index, false);
}
static void ppe_uniphy_usxgmii_mode_set(uint32_t uniphy_index)
{
uint32_t reg_value = 0;
@ -253,6 +268,9 @@ void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode)
case PORT_WRAPPER_USXGMII:
ppe_uniphy_usxgmii_mode_set(uniphy_index);
break;
case PORT_WRAPPER_10GBASE_R:
ppe_uniphy_10g_r_mode_set(uniphy_index);
break;
default:
break;
}

View file

@ -38,6 +38,8 @@
#define UNIPHY_CH1_CH0_SGMII (1 << 1)
#define UNIPHY_CH0_ATHR_CSCO_MODE_25M (1 << 0)
#define UNIPHY_INSTANCE_LINK_DETECT 0x570
#define UNIPHY_MISC2_REG_OFFSET 0x218
#define UNIPHY_MISC2_REG_SGMII_MODE 0x30
#define UNIPHY_MISC2_REG_SGMII_PLUS_MODE 0x50

View file

@ -93,6 +93,7 @@ enum port_wrapper_cfg {
PORT_WRAPPER_SGMII4_RGMII4,
PORT_WRAPPER_QSGMII,
PORT_WRAPPER_SGMII_PLUS,
PORT_WRAPPER_10GBASE_R,
};
enum phy_mode {