mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2026-02-14 20:09:24 +01:00
Merge "ipq807x: Add SFP 10G ethernet support"
This commit is contained in:
commit
40e31c6f85
8 changed files with 117 additions and 25 deletions
|
|
@ -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>;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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, ®_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), ®_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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue