Merge "arm: dts: ipq9574: Add QCA8084 switch support in AL02-C10"

This commit is contained in:
Linux Build Service Account 2022-06-16 11:09:51 -07:00 committed by Gerrit - the friendly Code Review server
commit 32bb34e1b8
5 changed files with 164 additions and 13 deletions

View file

@ -18,4 +18,45 @@
machid = <0x8050901>;
config_name = "config@al02-c10";
ess-switch {
/* Overriding config to support QCA8084 Switch instead of
* QCA8084 PHY
*/
qca8084_switch_enable = <1>;
switch_mac_mode0 = <PORT_WRAPPER_SGMII_PLUS>;
qca8084_swt_info {
switch_mac_mode0 = <PORT_WRAPPER_SGMII_PLUS>;
switch_mac_mode1 = <PORT_WRAPPER_SGMII_PLUS>;
port@0 {
phy_address = <0xff>;
phy_type = <UNUSED_PHY_TYPE>;
forced-speed = <2500>;
forced-duplex = <1>;
};
port@1 {
phy_address = <1>;
phy_type = <QCA8084_PHY_TYPE>;
};
port@2 {
phy_address = <2>;
phy_type = <QCA8084_PHY_TYPE>;
};
port@3 {
phy_address = <3>;
phy_type = <QCA8084_PHY_TYPE>;
};
port@4 {
phy_address = <0x4>;
phy_type = <QCA8084_PHY_TYPE>;
};
port@5 {
phy_address = <0xff>;
phy_type = <UNUSED_PHY_TYPE>;
forced-speed = <2500>;
forced-duplex = <1>;
};
};
};
};

View file

@ -46,6 +46,7 @@ static struct ipq9574_eth_dev *ipq9574_edma_dev[IPQ9574_EDMA_DEV];
uchar ipq9574_def_enetaddr[6] = {0x00, 0x03, 0x7F, 0xBA, 0xDB, 0xAD};
phy_info_t *phy_info[IPQ9574_PHY_MAX] = {0};
phy_info_t *swt_info[QCA8084_MAX_PORTS] = {0};
int sgmii_mode[2] = {0};
extern void ipq_phy_addr_fixup(void);
@ -62,8 +63,12 @@ extern int ipq_board_fw_download(unsigned int phy_addr);
extern void ipq_qca8084_phy_hw_init(struct phy_ops **ops, u32 phy_addr);
extern void qca8084_phy_uqxgmii_speed_fixup(uint32_t phy_addr, uint32_t qca8084_port_id,
uint32_t status, fal_port_speed_t new_speed);
extern int ipq_qca8084_hw_init(phy_info_t * phy_info[], int node);
extern void ipq_qca8084_link_update(u32 port_id);
extern void ipq_qca8084_switch_hw_reset(int gpio);
static int tftp_acl_our_port;
static int qca8084_swt_enb = 0;
/*
* EDMA hardware instance
@ -1022,6 +1027,13 @@ static int ipq9574_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], curr_speed[i],
dp[duplex]);
if ((phy_info[i]->phy_type == QCA8084_PHY_TYPE) && qca8084_swt_enb) {
if (old_speed[i] != curr_speed[i]) {
old_speed[i] = curr_speed[i];
ipq_qca8084_link_update(phy_addr);
}
}
continue;
}
@ -1257,17 +1269,22 @@ static int ipq9574_eth_init(struct eth_device *eth_dev, bd_t *this)
}
}
ipq9574_speed_clock_set(i, clk);
if (!qca8084_swt_enb || (i != PORT0))
ipq9574_speed_clock_set(i, clk);
if (phy_info[i]->phy_type == QCA8084_PHY_TYPE)
qca8084_phy_uqxgmii_speed_fixup(phy_info[i]->phy_address, i + 1,
status, curr_speed[i]);
if (!qca8084_swt_enb && (phy_info[i]->phy_type == QCA8084_PHY_TYPE))
qca8084_phy_uqxgmii_speed_fixup(phy_info[i]->phy_address,
i + 1, status, curr_speed[i]);
ipq9574_port_mac_clock_reset(i);
if (!qca8084_swt_enb || (i != PORT0))
ipq9574_port_mac_clock_reset(i);
if (i == aquantia_port[0] || i == aquantia_port[1] ||
phy_info[i]->phy_type == QCA8084_PHY_TYPE)
((phy_info[i]->phy_type == QCA8084_PHY_TYPE) && (!qca8084_swt_enb))) {
ipq9574_uxsgmii_speed_set(i, mac_speed, duplex, status);
}
else if (qca8084_swt_enb && (phy_info[i]->phy_type == QCA8084_PHY_TYPE))
ipq_qca8084_link_update(phy_addr);
else if ((i == sfp_port[0] || i == sfp_port[1]) && sgmii_fiber == 0)
ipq9574_10g_r_speed_set(i, status);
else
@ -1831,10 +1848,11 @@ int ipq9574_edma_hw_init(struct ipq9574_edma_hw *ehw)
return 0;
}
void get_phy_address(int offset)
void get_phy_address(int offset, phy_info_t * phy_info[])
{
int phy_type;
int phy_address;
int forced_speed, forced_duplex;
int i;
for (i = 0; i < IPQ9574_PHY_MAX; i++)
@ -1846,7 +1864,13 @@ void get_phy_address(int offset)
offset, "phy_address", 0);
phy_type = fdtdec_get_uint(gd->fdt_blob,
offset, "phy_type", 0);
forced_speed = fdtdec_get_uint(gd->fdt_blob,
offset, "forced-speed", 0);
forced_duplex = fdtdec_get_uint(gd->fdt_blob,
offset, "forced-duplex", 0);
phy_info[i]->phy_address = phy_address;
phy_info[i]->forced_speed = forced_speed;
phy_info[i]->forced_duplex = forced_duplex;
phy_info[i++]->phy_type = phy_type;
}
}
@ -1870,6 +1894,7 @@ int ipq9574_edma_init(void *edma_board_cfg)
#ifdef CONFIG_QCA8084_PHY
static int qca8084_init_done = 0;
int phy_type;
int qca8084_gpio, swt_node = -1, clk[4] = {0};
#endif
int node, phy_addr, mode, phy_node = -1, res = -1;
int aquantia_port[2] = {-1, -1}, aquantia_port_cnt = -1;
@ -1892,9 +1917,22 @@ int ipq9574_edma_init(void *edma_board_cfg)
}
}
#ifdef CONFIG_QCA8084_PHY
qca8084_swt_enb = fdtdec_get_uint(gd->fdt_blob, node, "qca8084_switch_enable", 0);
qca8084_gpio = fdtdec_get_uint(gd->fdt_blob, node, "qca808x_gpio", 0);
if (qca8084_swt_enb) {
if (qca8084_gpio)
ipq_qca8084_switch_hw_reset(qca8084_gpio);
}
swt_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/qca8084_swt_info");
if (swt_node >= 0)
get_phy_address(swt_node, swt_info);
#endif
phy_node = fdt_path_offset(gd->fdt_blob, "/ess-switch/port_phyinfo");
if (phy_node >= 0)
get_phy_address(phy_node);
get_phy_address(phy_node, phy_info);
mode = fdtdec_get_uint(gd->fdt_blob, node, "switch_mac_mode0", -1);
if (mode < 0) {
@ -2084,6 +2122,37 @@ int ipq9574_edma_init(void *edma_board_cfg)
if (ret)
goto init_failed;
/** QCA8084 switch specific configurations */
if (qca8084_swt_enb) {
/** Force speed alder 1st port for QCA8084 switch mode */
switch (swt_info[0]->forced_speed) {
case FAL_SPEED_1000:
case FAL_SPEED_2500:
clk[0] = 0x201;
clk[1] = 0x0;
clk[2] = 0x301;
clk[3] = 0x0;
pr_debug("Force speed Alder 1st PORT for QCA8084 switch mode \n");
ipq9574_speed_clock_set(PORT0, clk);
/** Force Link-speed: 1000M
* Force Link-status: enable */
ipq9574_pqsgmii_speed_set(PORT0, 0x2, 0x0);
break;
default:
printf("Error: Unsupported speed configuraiton for QCA8084 switch \n");
break;
}
ret = ipq_qca8084_hw_init(swt_info, swt_node);
if (ret < 0) {
printf("Error: ipq_qca8084_hw_init failed \n");
goto init_failed;
}
}
eth_register(dev[i]);
}

View file

@ -831,6 +831,7 @@ void ppe_port_mux_mac_type_set(int port_id, int mode)
case EPORT_WRAPPER_SGMII0_RGMII4:
case EPORT_WRAPPER_SGMII_PLUS:
case EPORT_WRAPPER_SGMII_FIBER:
case EPORT_WRAPPER_SGMII_CHANNEL0:
port_type = PORT_GMAC_TYPE;
break;
case EPORT_WRAPPER_USXGMII:

View file

@ -235,10 +235,30 @@ static void ppe_uniphy_qsgmii_mode_set(uint32_t uniphy_index)
mdelay(100);
}
void ppe_uniphy_set_forceMode(void)
{
uint32_t reg_value;
reg_value = readl(PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4);
reg_value |= UNIPHY_FORCE_SPEED_25M;
writel(reg_value, PPE_UNIPHY_BASE + UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4);
}
static void ppe_uniphy_sgmii_mode_set(uint32_t uniphy_index, uint32_t mode)
{
writel(UNIPHY_MISC2_REG_SGMII_MODE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET);
if (uniphy_index == 0) {
writel(UNIPHY_MISC_SRC_PHY_MODE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC_SOURCE_SELECTION_REG_OFFSET);
ppe_uniphy_set_forceMode();
writel(UNIPHY_MISC2_REG_SGMII_PLUS_MODE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET);
} else {
writel(UNIPHY_MISC2_REG_SGMII_MODE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_MISC2_REG_OFFSET);
}
writel(UNIPHY_PLL_RESET_REG_VALUE, PPE_UNIPHY_BASE +
(uniphy_index * PPE_UNIPHY_REG_INC) + UNIPHY_PLL_RESET_REG_OFFSET);
@ -254,7 +274,12 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t uniphy_index, uint32_t mode)
ppe_uniphy_reset(UNIPHY2_XPCS_RESET, true);
mdelay(100);
if (uniphy_index == 1) {
if (uniphy_index == 0) {
writel(0x0, NSS_CC_UNIPHY_PORT1_RX_CBCR);
writel(0x0, NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4);
writel(0x0, NSS_CC_PORT1_RX_CBCR);
writel(0x0, NSS_CC_PORT1_RX_CBCR + 0x4);
} else if (uniphy_index == 1) {
writel(0x0, NSS_CC_UNIPHY_PORT1_RX_CBCR + (PORT5 - 1) * 0x8);
writel(0x0, NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4 + (PORT5 - 1) * 0x8);
writel(0x0, NSS_CC_PORT1_RX_CBCR + (PORT5 - 1) * 0x8);
@ -280,7 +305,11 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t uniphy_index, uint32_t mode)
break;
case EPORT_WRAPPER_SGMII_PLUS:
writel(0x820, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
if (uniphy_index == 0)
writel(0x20, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
else
writel(0x820, PPE_UNIPHY_BASE + (uniphy_index * PPE_UNIPHY_REG_INC)
+ PPE_UNIPHY_MODE_CONTROL);
break;
@ -304,7 +333,12 @@ static void ppe_uniphy_sgmii_mode_set(uint32_t uniphy_index, uint32_t mode)
}
mdelay(100);
if (uniphy_index == 1) {
if (uniphy_index == 0) {
writel(0x1, NSS_CC_UNIPHY_PORT1_RX_CBCR);
writel(0x1, NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4);
writel(0x1, NSS_CC_PORT1_RX_CBCR);
writel(0x1, NSS_CC_PORT1_RX_CBCR + 0x4);
} else if (uniphy_index == 1) {
writel(0x1, NSS_CC_UNIPHY_PORT1_RX_CBCR + (PORT5 - 1) * 0x8);
writel(0x1, NSS_CC_UNIPHY_PORT1_RX_CBCR + 0x4 + (PORT5 - 1) * 0x8);
writel(0x1, NSS_CC_PORT1_RX_CBCR + (PORT5 - 1) * 0x8);

View file

@ -41,6 +41,12 @@
#define UNIPHY_MISC2_REG_VALUE 0x70
#define UNIPHY_MISC_SOURCE_SELECTION_REG_OFFSET 0x21c
#define UNIPHY_MISC_SRC_PHY_MODE 0xa882
#define UNIPHY_DEC_CHANNEL_0_INPUT_OUTPUT_4 0x480
#define UNIPHY_FORCE_SPEED_25M (1 << 3)
#define UNIPHY_PLL_RESET_REG_OFFSET 0x780
#define UNIPHY_PLL_RESET_REG_VALUE 0x02bf
#define UNIPHY_PLL_RESET_REG_DEFAULT_VALUE 0x02ff