Merge "drivers: net: ipq9574: Add SKU Validation"

This commit is contained in:
Linux Build Service Account 2021-08-31 05:08:57 -07:00 committed by Gerrit - the friendly Code Review server
commit d9e69aa54b
8 changed files with 292 additions and 38 deletions

View file

@ -16,4 +16,21 @@
/ {
machid = <0x1050200>;
config_name = "config@db-al01-c3";
ess-switch {
/* Overriding port6 configuration to support AQ instead
* of QCA808x
*/
/delete-property/qca808x_gpio;
/delete-property/qca808x_gpio_cnt;
switch_mac_mode2 = <PORT_WRAPPER_USXGMII>;
aquantia_port = <4 5>;
aquantia_port_cnt = <2>;
port_phy_info {
port@5 {
phy_address = <0>;
phy_type = <AQ_PHY_TYPE>;
};
};
};
};

View file

@ -16,4 +16,52 @@
/ {
machid = <0x1050201>;
config_name = "config@db-al02-c3";
aliases {
i2c0 = "/i2c@78B9000";
};
i2c@78B9000 {
compatible = "qcom,qup-i2c";
#address-cells = <1>;
#size-cells = <0>;
reg = <0x78B9000 0x600>;
clock-frequency = <400000>;
i2c_gpio {
gpio1 {
gpio = <50>;
func = <2>;
pull = <GPIO_PULL_UP>;
drvstr = <GPIO_8MA>;
oe = <GPIO_OE_ENABLE>;
};
gpio2 {
gpio = <51>;
func = <2>;
pull = <GPIO_PULL_UP>;
drvstr = <GPIO_8MA>;
oe = <GPIO_OE_ENABLE>;
};
};
};
ess-switch {
/* Overriding port5 configuration to support SFP instead
* of QCA808x.
*/
/delete-property/qca808x_gpio;
/delete-property/qca808x_gpio_cnt;
switch_mac_mode1 = <PORT_WRAPPER_10GBASE_R>;
sfp_gpio = <61>;
sfp_gpio_cnt = <1>;
sfp_port = <4>;
sfp_port_cnt = <1>;
port_phy_info {
port@4 {
/delete-property/phy_address;
phy_type = <SFP_PHY_TYPE>;
};
};
};
};

View file

@ -425,7 +425,57 @@ void ipq_fdt_fixup_usb_device_mode(void *blob)
printf("%s: invalid param for usb_mode\n", __func__);
}
int ipq_validate_qfrom_fuse(unsigned int reg_add, int pos)
{
return (readl(reg_add) & (1 << pos));
}
int is_uniphy_enabled(int uniphy_index)
{
int bit = 0;
switch(uniphy_index) {
case 0:
bit = UNIPHY_0_DISABLE_BIT;
break;
case 1:
bit = UNIPHY_1_DISABLE_BIT;
break;
case 2:
bit = UNIPHY_2_DISABLE_BIT;
break;
default:
printf("In ipq9574: Max 3 Uniphy's can be supported\n");
break;
}
return !ipq_validate_qfrom_fuse(
QFPROM_CORR_FEATURE_CONFIG_ROW2_MSB, bit);
}
#ifdef CONFIG_PCI_IPQ
int ipq_sku_pci_validation(int pci_id)
{
int pos = 0;
switch(pci_id){
case 0:
pos = PCIE_0_CLOCK_DISABLE_BIT;
break;
case 1:
pos = PCIE_1_CLOCK_DISABLE_BIT;
break;
case 2:
pos = PCIE_2_CLOCK_DISABLE_BIT;
break;
case 3:
pos = PCIE_3_CLOCK_DISABLE_BIT;
break;
}
return ipq_validate_qfrom_fuse(
QFPROM_CORR_FEATURE_CONFIG_ROW1_MSB, pos);
}
void board_pci_init(int id)
{
int node, gpio_node, pci_no;
@ -438,11 +488,16 @@ void board_pci_init(int id)
return;
}
pci_no = fdtdec_get_int(gd->fdt_blob, node, "id", 0);
if (ipq_sku_pci_validation(pci_no)){
printf("PCIe%d disabled \n", pci_no);
}
gpio_node = fdt_subnode_offset(gd->fdt_blob, node, "pci_gpio");
if (gpio_node >= 0)
qca_gpio_init(gpio_node);
pci_no = fdtdec_get_int(gd->fdt_blob, node, "id", 0);
pcie_v2_clock_init(pci_no);
return;
@ -569,6 +624,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;
@ -626,6 +702,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;
@ -923,9 +1017,6 @@ void noc_clock_init(void)
reg_val = readl(GCC_MEM_NOC_SNOC_AXI_CBCR);
writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_MEM_NOC_SNOC_AXI_CBCR);
reg_val = readl(GCC_IMEM_AXI_CBCR);
writel(reg_val | GCC_CBCR_CLK_ENABLE, GCC_IMEM_AXI_CBCR);
}
void fixed_clock_init(void)
@ -1049,6 +1140,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();

View file

@ -62,7 +62,6 @@
#define GCC_NSSNOC_SNOC_CBCR 0x1817028
#define GCC_NSSNOC_SNOC_1_CBCR 0x181707C
#define GCC_MEM_NOC_SNOC_AXI_CBCR 0x1819018
#define GCC_IMEM_AXI_CBCR 0x180E004
#define NSS_CC_UNIPHY_PORT1_RX_ADDR 0x39B28904
#define NSS_CC_PPE_RESET_ADDR 0x39B28A08
#define NSS_CC_UNIPHY_MISC_RESET 0x39B28A24
@ -261,6 +260,23 @@ unsigned int __invoke_psci_fn_smc(unsigned int, unsigned int,
*/
#define EUD_EUD_EN2 0x7A000
/*
* QFPROM Register for SKU Validation
*/
#define QFPROM_CORR_FEATURE_CONFIG_ROW1_MSB 0xA401C
#define QFPROM_CORR_FEATURE_CONFIG_ROW2_MSB 0xA4024
#define PCIE_0_CLOCK_DISABLE_BIT 2
#define PCIE_1_CLOCK_DISABLE_BIT 3
#define PCIE_2_CLOCK_DISABLE_BIT 4
#define PCIE_3_CLOCK_DISABLE_BIT 5
#define UNIPHY_0_DISABLE_BIT 23
#define UNIPHY_1_DISABLE_BIT 24
#define UNIPHY_2_DISABLE_BIT 25
int ipq_validate_qfrom_fuse(unsigned int reg_add, int pos);
/**
* Number of RAM partition entries which are usable by APPS.
*/

View file

@ -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;
}
}

View file

@ -32,6 +32,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define pr_info(fmt, args...) printf(fmt, ##args);
extern int is_uniphy_enabled(int uniphy_index);
extern void uniphy_port5_clock_source_set(void);
/*
@ -857,10 +858,12 @@ void ipq9574_ppe_interface_mode_init(void)
if (mode1 == EPORT_WRAPPER_MAX) {
ppe_port_mux_mac_type_set(PORT5, mode0);
uniphy_port5_clock_source_set();
} else {
} else if (is_uniphy_enabled(PPE_UNIPHY_INSTANCE1)) {
ppe_port_mux_mac_type_set(PORT5, mode1);
}
ppe_port_mux_mac_type_set(PORT6, mode2);
if (is_uniphy_enabled(PPE_UNIPHY_INSTANCE2)) {
ppe_port_mux_mac_type_set(PORT6, mode2);
}
}
/*

View file

@ -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

View file

@ -27,6 +27,8 @@
#include <fdtdec.h>
#include "ipq_phy.h"
extern int is_uniphy_enabled(int uniphy_index);
DECLARE_GLOBAL_DATA_PTR;
extern int ipq_mdio_write(int mii_id,
int regnum, u16 value);
@ -436,6 +438,11 @@ static void ppe_uniphy_usxgmii_mode_set(uint32_t uniphy_index)
void ppe_uniphy_mode_set(uint32_t uniphy_index, uint32_t mode)
{
if (!is_uniphy_enabled(uniphy_index)) {
printf("Uniphy %u is disabled\n", uniphy_index);
return;
}
switch(mode) {
case EPORT_WRAPPER_PSGMII:
ppe_uniphy_psgmii_mode_set(uniphy_index);