mirror of
https://git.codelinaro.org/clo/qsdk/oss/boot/u-boot-2016.git
synced 2026-02-15 04:19:27 +01:00
Merge "ipq807x: Multiple napa port support"
This commit is contained in:
commit
41884b5338
6 changed files with 200 additions and 74 deletions
|
|
@ -28,8 +28,34 @@
|
|||
switch_mac_mode = <0x0>;
|
||||
switch_mac_mode1 = <0xFF>;
|
||||
switch_mac_mode2 = <0x6>;
|
||||
8081_port = <5>;
|
||||
napa_gpio = <44>;
|
||||
napa_gpio_cnt = <1>;
|
||||
port_phyinfo {
|
||||
port@0 {
|
||||
phy_address = <0>;
|
||||
phy_type = <1>;
|
||||
};
|
||||
port@1 {
|
||||
phy_address = <1>;
|
||||
phy_type = <1>;
|
||||
};
|
||||
port@2 {
|
||||
phy_address = <2>;
|
||||
phy_type = <1>;
|
||||
};
|
||||
port@3 {
|
||||
phy_address = <3>;
|
||||
phy_type = <1>;
|
||||
};
|
||||
port@4 {
|
||||
phy_address = <4>;
|
||||
phy_type = <1>;
|
||||
};
|
||||
port@5 {
|
||||
phy_address = <28>;
|
||||
phy_type = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -27,8 +27,36 @@
|
|||
};
|
||||
ess-switch {
|
||||
switch_mac_mode = <0x0>;
|
||||
switch_mac_mode1 = <0xFF>;
|
||||
switch_mac_mode2 = <0xFF>;
|
||||
switch_mac_mode1 = <0x6>;
|
||||
switch_mac_mode2 = <0x6>;
|
||||
napa_gpio = <25 44>;
|
||||
napa_gpio_cnt = <2>;
|
||||
port_phyinfo {
|
||||
port@0 {
|
||||
phy_address = <0>;
|
||||
phy_type = <1>;
|
||||
};
|
||||
port@1 {
|
||||
phy_address = <1>;
|
||||
phy_type = <1>;
|
||||
};
|
||||
port@2 {
|
||||
phy_address = <2>;
|
||||
phy_type = <1>;
|
||||
};
|
||||
port@3 {
|
||||
phy_address = <3>;
|
||||
phy_type = <1>;
|
||||
};
|
||||
port@4 {
|
||||
phy_address = <24>;
|
||||
phy_type = <2>;
|
||||
};
|
||||
port@5 {
|
||||
phy_address = <28>;
|
||||
phy_type = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -311,17 +311,23 @@ int get_aquantia_gpio()
|
|||
return aquantia_gpio;
|
||||
}
|
||||
|
||||
int get_napa_gpio()
|
||||
int get_napa_gpio(int napa_gpio[2])
|
||||
{
|
||||
int napa_gpio = -1, node;
|
||||
int napa_gpio_cnt = -1, node;
|
||||
int res = -1;
|
||||
|
||||
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
|
||||
if (node >= 0)
|
||||
napa_gpio = fdtdec_get_uint(gd->fdt_blob, node, "napa_gpio", -1);
|
||||
else
|
||||
return node;
|
||||
if (node >= 0) {
|
||||
napa_gpio_cnt = fdtdec_get_uint(gd->fdt_blob, node, "napa_gpio_cnt", -1);
|
||||
if (napa_gpio_cnt >= 1) {
|
||||
res = fdtdec_get_int_array(gd->fdt_blob, node, "napa_gpio",
|
||||
napa_gpio, napa_gpio_cnt);
|
||||
if (res >= 0)
|
||||
return napa_gpio_cnt;
|
||||
}
|
||||
}
|
||||
|
||||
return napa_gpio;
|
||||
return res;
|
||||
}
|
||||
|
||||
void aquantia_phy_reset_init(void)
|
||||
|
|
@ -345,24 +351,29 @@ void aquantia_phy_reset_init(void)
|
|||
|
||||
void napa_phy_reset_init(void)
|
||||
{
|
||||
int napa_gpio = -1, node;
|
||||
int napa_gpio[2] = {0}, node, napa_gpio_cnt, i;
|
||||
unsigned int *napa_gpio_base;
|
||||
|
||||
napa_gpio = get_napa_gpio();
|
||||
if (napa_gpio >=0) {
|
||||
napa_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(napa_gpio);
|
||||
writel(0x203, napa_gpio_base);
|
||||
gpio_direction_output(napa_gpio, 0x0);
|
||||
napa_gpio_cnt = get_napa_gpio(napa_gpio);
|
||||
if (napa_gpio_cnt >= 1) {
|
||||
for (i = 0; i < napa_gpio_cnt; i++) {
|
||||
if (napa_gpio[i] >=0) {
|
||||
napa_gpio_base = (unsigned int *)GPIO_CONFIG_ADDR(napa_gpio[i]);
|
||||
writel(0x203, napa_gpio_base);
|
||||
gpio_direction_output(napa_gpio[i], 0x0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void napa_phy_reset_init_done(void)
|
||||
{
|
||||
int napa_gpio;
|
||||
int napa_gpio[2] = {0}, node, napa_gpio_cnt, i;
|
||||
|
||||
napa_gpio = get_napa_gpio();
|
||||
if (napa_gpio >= 0) {
|
||||
gpio_set_value(napa_gpio, 0x1);
|
||||
napa_gpio_cnt = get_napa_gpio(napa_gpio);
|
||||
if (napa_gpio_cnt >= 1) {
|
||||
for (i = 0; i < napa_gpio_cnt; i++)
|
||||
gpio_set_value(napa_gpio[i], 0x1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ DECLARE_GLOBAL_DATA_PTR;
|
|||
static struct ipq807x_eth_dev *ipq807x_edma_dev[IPQ807X_EDMA_DEV];
|
||||
|
||||
uchar ipq807x_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xBA, 0xDB, 0xAD};
|
||||
phy_info_t *phy_info[PHY_MAX] = {0};
|
||||
int sgmii_mode[2] = {0};
|
||||
|
||||
extern void qca8075_ess_reset(void);
|
||||
extern void psgmii_self_test(void);
|
||||
|
|
@ -856,6 +858,22 @@ static void ipq807x_edma_disable_intr(struct ipq807x_edma_hw *ehw)
|
|||
IPQ807X_EDMA_MASK_INT_DISABLE);
|
||||
}
|
||||
|
||||
int set_sgmii_mode(int port_id, int sg_mode)
|
||||
{
|
||||
if (port_id == 4)
|
||||
sgmii_mode[0] = sg_mode;
|
||||
else if (port_id == 5)
|
||||
sgmii_mode[1] = sg_mode;
|
||||
}
|
||||
|
||||
int get_sgmii_mode(int port_id)
|
||||
{
|
||||
if (port_id == 4)
|
||||
return sgmii_mode[0];
|
||||
else if (port_id == 5)
|
||||
return sgmii_mode[1];
|
||||
}
|
||||
|
||||
static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
|
||||
{
|
||||
struct ipq807x_eth_dev *priv = eth_dev->priv;
|
||||
|
|
@ -871,8 +889,8 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
|
|||
char *dp[] = {"Half", "Full"};
|
||||
int linkup=0;
|
||||
int mac_speed = 0, speed_clock1 = 0, speed_clock2 = 0;
|
||||
int phy_addr, port_8033 = -1, node, aquantia_port = -1, port_8081 = -1;
|
||||
int sgmii_mode = 0;
|
||||
int phy_addr, port_8033 = -1, node, aquantia_port = -1;
|
||||
int phy_node = -1;
|
||||
|
||||
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
|
||||
if (node >= 0)
|
||||
|
|
@ -881,8 +899,7 @@ 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)
|
||||
port_8081 = fdtdec_get_uint(gd->fdt_blob, node, "8081_port", -1);
|
||||
phy_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/port_phyinfo");
|
||||
/*
|
||||
* Check PHY link, speed, Duplex on all phys.
|
||||
* we will proceed even if single link is up
|
||||
|
|
@ -902,15 +919,17 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (i == port_8033)
|
||||
phy_addr = QCA8033_PHY_ADDR;
|
||||
else if (i == port_8081)
|
||||
phy_addr = QCA8081_PHY_ADDR;
|
||||
else if (i == aquantia_port)
|
||||
phy_addr = AQU_PHY_ADDR;
|
||||
else
|
||||
phy_addr = i;
|
||||
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);
|
||||
if (status == 0)
|
||||
linkup++;
|
||||
|
|
@ -932,8 +951,8 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
|
|||
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
|
||||
priv->mac_unit, i, lstatus[status], speed,
|
||||
dp[duplex]);
|
||||
if (i == port_8081)
|
||||
sgmii_mode = 1;
|
||||
if (phy_info[i]->phy_type == QCA8081_PHY_TYPE)
|
||||
set_sgmii_mode(i, 1);
|
||||
break;
|
||||
case FAL_SPEED_100:
|
||||
mac_speed = 0x1;
|
||||
|
|
@ -950,8 +969,8 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
|
|||
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
|
||||
priv->mac_unit, i, lstatus[status], speed,
|
||||
dp[duplex]);
|
||||
if (i == port_8081)
|
||||
sgmii_mode = 1;
|
||||
if (phy_info[i]->phy_type == QCA8081_PHY_TYPE)
|
||||
set_sgmii_mode(i, 1);
|
||||
break;
|
||||
case FAL_SPEED_1000:
|
||||
mac_speed = 0x2;
|
||||
|
|
@ -959,14 +978,16 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
|
|||
speed_clock1 = 0x104;
|
||||
else if (i == port_8033)
|
||||
speed_clock1 = 0x301;
|
||||
else if (phy_info[i]->phy_type == QCA8081_PHY_TYPE)
|
||||
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,
|
||||
dp[duplex]);
|
||||
if (i == port_8081)
|
||||
sgmii_mode = 1;
|
||||
if (phy_info[i]->phy_type == QCA8081_PHY_TYPE)
|
||||
set_sgmii_mode(i, 1);
|
||||
break;
|
||||
case FAL_SPEED_10000:
|
||||
mac_speed = 0x3;
|
||||
|
|
@ -977,23 +998,22 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
|
|||
dp[duplex]);
|
||||
break;
|
||||
case FAL_SPEED_2500:
|
||||
if (i == port_8081)
|
||||
if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) {
|
||||
mac_speed = 0x2;
|
||||
else
|
||||
mac_speed = 0x4;
|
||||
|
||||
if (port_8081 == 4)
|
||||
speed_clock1 = 0x301;
|
||||
else if (port_8081 == 5)
|
||||
speed_clock1 = 0x101;
|
||||
else
|
||||
if (i == 4)
|
||||
speed_clock1 = 0x301;
|
||||
else if (i == 5)
|
||||
speed_clock1 = 0x101;
|
||||
} else {
|
||||
speed_clock1 = 0x107;
|
||||
mac_speed = 0x4;
|
||||
}
|
||||
speed_clock2 = 0x0;
|
||||
printf ("eth%d PHY%d %s Speed :%d %s duplex\n",
|
||||
priv->mac_unit, i, lstatus[status], speed,
|
||||
dp[duplex]);
|
||||
if (i == port_8081)
|
||||
sgmii_mode = 0;
|
||||
if (phy_info[i]->phy_type == QCA8081_PHY_TYPE)
|
||||
set_sgmii_mode(i, 0);
|
||||
break;
|
||||
case FAL_SPEED_5000:
|
||||
mac_speed = 0x5;
|
||||
|
|
@ -1008,19 +1028,23 @@ static int ipq807x_eth_init(struct eth_device *eth_dev, bd_t *this)
|
|||
break;
|
||||
}
|
||||
|
||||
if (i == port_8081) {
|
||||
if (sgmii_mode != uniphy_phy_mode) {
|
||||
uniphy_phy_mode = sgmii_mode;
|
||||
if (sgmii_mode) {
|
||||
ppe_port_bridge_txmac_set(i, 1);
|
||||
ppe_uniphy_mode_set(0x2, PORT_WRAPPER_SGMII0_RGMII4);
|
||||
if (phy_info[i]->phy_type == QCA8081_PHY_TYPE) {
|
||||
if (get_sgmii_mode(i)) {
|
||||
ppe_port_bridge_txmac_set(i + 1, 1);
|
||||
if (i == 4)
|
||||
ppe_uniphy_mode_set(0x1, PORT_WRAPPER_SGMII0_RGMII4);
|
||||
else if (i == 5)
|
||||
ppe_uniphy_mode_set(0x2, PORT_WRAPPER_SGMII0_RGMII4);
|
||||
|
||||
} else {
|
||||
ppe_port_bridge_txmac_set(i, 1);
|
||||
ppe_uniphy_mode_set(0x2, PORT_WRAPPER_SGMII_PLUS);
|
||||
ppe_port_bridge_txmac_set(i + 1, 1);
|
||||
if (i == 4)
|
||||
ppe_uniphy_mode_set(0x1, PORT_WRAPPER_SGMII_PLUS);
|
||||
else if (i == 5)
|
||||
ppe_uniphy_mode_set(0x2, PORT_WRAPPER_SGMII_PLUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ipq807x_speed_clock_set(i, speed_clock1, speed_clock2);
|
||||
if (i == aquantia_port)
|
||||
ipq807x_uxsgmii_speed_set(i, mac_speed, duplex, status);
|
||||
|
|
@ -1629,6 +1653,27 @@ int ipq807x_edma_hw_init(struct ipq807x_edma_hw *ehw)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void get_phy_address(int offset)
|
||||
{
|
||||
int phy_type;
|
||||
int phy_address;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < PHY_MAX; i++)
|
||||
phy_info[i] = ipq807x_alloc_mem(sizeof(phy_info_t));
|
||||
i = 0;
|
||||
for (offset = fdt_first_subnode(gd->fdt_blob, offset); offset > 0;
|
||||
offset = fdt_next_subnode(gd->fdt_blob, offset)) {
|
||||
|
||||
phy_address = fdtdec_get_uint(gd->fdt_blob,
|
||||
offset, "phy_address", 0);
|
||||
phy_type = fdtdec_get_uint(gd->fdt_blob,
|
||||
offset, "phy_type", 0);
|
||||
phy_info[i]->phy_address = phy_address;
|
||||
phy_info[i++]->phy_type = phy_type;
|
||||
}
|
||||
}
|
||||
|
||||
int ipq807x_edma_init(void *edma_board_cfg)
|
||||
{
|
||||
struct eth_device *dev[IPQ807X_EDMA_DEV];
|
||||
|
|
@ -1640,8 +1685,10 @@ int ipq807x_edma_init(void *edma_board_cfg)
|
|||
int ret = -1;
|
||||
ipq807x_edma_board_cfg_t ledma_cfg, *edma_cfg;
|
||||
static int sw_init_done = 0;
|
||||
int port_8033 = -1, port_8081 = -1, node, phy_addr, aquantia_port = -1;
|
||||
int mode;
|
||||
int port_8033 = -1, node, phy_addr, aquantia_port = -1;
|
||||
int mode, phy_node = -1;
|
||||
int napa_port_len = 0 , len;
|
||||
unsigned int phy_array[6] = {0};
|
||||
|
||||
node = fdt_path_offset(gd->fdt_blob, "/ess-switch");
|
||||
if (node >= 0)
|
||||
|
|
@ -1650,8 +1697,9 @@ int ipq807x_edma_init(void *edma_board_cfg)
|
|||
if (node >= 0)
|
||||
aquantia_port = fdtdec_get_uint(gd->fdt_blob, node, "aquantia_port", -1);
|
||||
|
||||
if (node >= 0)
|
||||
port_8081 = fdtdec_get_uint(gd->fdt_blob, node, "8081_port", -1);
|
||||
phy_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/port_phyinfo");
|
||||
if (phy_node >= 0)
|
||||
get_phy_address(phy_node);
|
||||
|
||||
mode = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode", -1);
|
||||
if (mode < 0) {
|
||||
|
|
@ -1739,14 +1787,16 @@ int ipq807x_edma_init(void *edma_board_cfg)
|
|||
goto init_failed;
|
||||
|
||||
for (phy_id = 0; phy_id < PHY_MAX; phy_id++) {
|
||||
if (phy_id == port_8033)
|
||||
phy_addr = QCA8033_PHY_ADDR;
|
||||
else if (phy_id == aquantia_port)
|
||||
phy_addr = AQU_PHY_ADDR;
|
||||
else if (phy_id == port_8081)
|
||||
phy_addr = QCA8081_PHY_ADDR;
|
||||
else
|
||||
phy_addr = phy_id;
|
||||
if (phy_node >= 0) {
|
||||
phy_addr = phy_info[phy_id]->phy_address;
|
||||
} else {
|
||||
if (phy_id == port_8033)
|
||||
phy_addr = QCA8033_PHY_ADDR;
|
||||
else if (phy_id == aquantia_port)
|
||||
phy_addr = AQU_PHY_ADDR;
|
||||
else
|
||||
phy_addr = phy_id;
|
||||
}
|
||||
|
||||
phy_chip_id1 = ipq_mdio_read(phy_addr, QCA_PHY_ID1, NULL);
|
||||
phy_chip_id2 = ipq_mdio_read(phy_addr, QCA_PHY_ID2, NULL);
|
||||
|
|
|
|||
|
|
@ -1067,7 +1067,7 @@ static void ipq807x_ppe_e_sp_cfg_tbl_drr_id_set(int id)
|
|||
ipq807x_ppe_reg_write(IPQ807X_PPE_L1_E_SP_CFG_TBL + (id * 0x80), id * 2 + 1);
|
||||
}
|
||||
|
||||
static void ppe_port_mux_set(int port_id, int port_type)
|
||||
static void ppe_port_mux_set(int port_id, int port_type, int mode)
|
||||
{
|
||||
union port_mux_ctrl_u port_mux_ctrl;
|
||||
|
||||
|
|
@ -1075,7 +1075,10 @@ static void ppe_port_mux_set(int port_id, int port_type)
|
|||
port_mux_ctrl.bf.port4_pcs_sel = PORT4_PCS_SEL_GMII_FROM_PCS0;
|
||||
if (port_id == PORT5) {
|
||||
if (port_type == PORT_GMAC_TYPE) {
|
||||
port_mux_ctrl.bf.port5_pcs_sel = PORT5_PCS_SEL_GMII_FROM_PCS0;
|
||||
if (mode == PORT_WRAPPER_SGMII_PLUS)
|
||||
port_mux_ctrl.bf.port5_pcs_sel = PORT5_PCS_SEL_GMII_FROM_PCS1;
|
||||
else
|
||||
port_mux_ctrl.bf.port5_pcs_sel = PORT5_PCS_SEL_GMII_FROM_PCS0;
|
||||
port_mux_ctrl.bf.port5_gmac_sel = PORT5_GMAC_SEL_GMAC;
|
||||
} else if (port_type == PORT_XGMAC_TYPE) {
|
||||
port_mux_ctrl.bf.port5_pcs_sel = PORT5_PCS_SEL_GMII_FROM_PCS1;
|
||||
|
|
@ -1113,7 +1116,7 @@ static void ppe_port_mux_mac_type_set(int port_id, int mode)
|
|||
default:
|
||||
return;
|
||||
}
|
||||
ppe_port_mux_set(port_id, port_type);
|
||||
ppe_port_mux_set(port_id, port_type, mode);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
#define QCA8033_PHY 0x004DD074
|
||||
#define QCA8033_PHY_ADDR 0x6
|
||||
#define QCA8081_PHY 0x004DD100
|
||||
#define QCA8081_PHY_ADDR 0x1C
|
||||
#define AQUANTIA_PHY_107 0x03a1b4e2
|
||||
#define AQUANTIA_PHY_109 0x03a1b502
|
||||
#define AQUANTIA_PHY_111 0x03a1b610
|
||||
|
|
@ -95,6 +94,15 @@ enum port_wrapper_cfg {
|
|||
PORT_WRAPPER_SGMII_PLUS,
|
||||
};
|
||||
|
||||
enum phy_mode {
|
||||
MALIBU_PHY_TYPE = 1,
|
||||
QCA8081_PHY_TYPE = 2,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u32 phy_address;
|
||||
u32 phy_type;
|
||||
}phy_info_t;
|
||||
|
||||
struct phy_ops {
|
||||
u8 (*phy_get_link_status) (u32 dev_id, u32 phy_id);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue