diff --git a/Documentation/admin-guide/kernel-parameters.rst b/Documentation/admin-guide/kernel-parameters.rst index 38a8231700f1..73ae122159c2 100644 --- a/Documentation/admin-guide/kernel-parameters.rst +++ b/Documentation/admin-guide/kernel-parameters.rst @@ -227,3 +227,7 @@ eipv4= [KNL] Sets ipv4 address at boot up for early ethernet. eipv6= [KNL] Sets ipv6 address at boot up for early ethernet. ermac= [KNL] Sets mac address at boot up for early ethernet. + +board= [KNL] Sets Board type of device at boot up for phy detection. + +enet= [KNL] Sets the PHY type on device at boot up for phy detection. diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 144f36e13eb7..b784b10da2f2 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -7096,4 +7096,8 @@ eipv6= [KNL] Sets ipv6 address at boot up for early ethernet. - ermac= [KNL] Sets mac address at boot up for early ethernet. \ No newline at end of file + ermac= [KNL] Sets mac address at boot up for early ethernet. + + board= [KNL] Sets Board type of device at boot up for phy detection. + + enet= [KNL] Sets the PHY type on device at boot up for phy detection. diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 61da8b9bd78d..5688576fb536 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -168,6 +168,8 @@ #define DWMAC4_PCS_BASE 0x000000e0 #define RGMII_CONFIG_10M_CLK_DVD GENMASK(18, 10) +static int phytype = -1; +static int boardtype = -1; void *ipc_emac_log_ctxt; struct emac_emb_smmu_cb_ctx emac_emb_smmu_ctx = {0}; @@ -177,6 +179,14 @@ struct plat_stmmacenet_data *plat_dat; struct qcom_ethqos *pethqos; #ifdef MODULE +static char *board; +module_param(board, charp, 0660); +MODULE_PARM_DESC(board, "board type of the device"); + +static char *enet; +module_param(enet, charp, 0660); +MODULE_PARM_DESC(enet, "enet value for the phy connection"); + static char *eipv4; module_param(eipv4, charp, 0660); MODULE_PARM_DESC(eipv4, "ipv4 value from ethernet partition"); @@ -203,6 +213,28 @@ static unsigned char dev_addr[ETH_ALEN] = { 0, 0x55, 0x7b, 0xb5, 0x7d, 0xf7}; static struct ip_params pparams = {"", "", "", ""}; +static int set_board_type(char *board_params) +{ + if (!strcmp(board_params, "Air")) + boardtype = AIR_BOARD; + else if (!strcmp(board_params, "Star")) + boardtype = STAR_BOARD; + else + return -1; + return 0; +} + +static int set_phy_type(char *enet_params) +{ + if (!strcmp(enet_params, "1") || !strcmp(enet_params, "2")) + phytype = PHY_1G; + else if (!strcmp(enet_params, "3") || !strcmp(enet_params, "6")) + phytype = PHY_25G; + else + return -1; + return 0; +} + static int set_early_ethernet_ipv4(char *ipv4_addr_in) { int ret = 1; @@ -278,6 +310,11 @@ fail: } #ifndef MODULE + +__setup("board=", set_board_type); + +__setup("enet=", set_phy_type); + static int __init set_early_ethernet_ipv4_static(char *ipv4_addr_in) { int ret = 1; @@ -2233,6 +2270,12 @@ static int qcom_ethqos_probe(struct platform_device *pdev) ETHQOSINFO("M - Ethernet probe start\n"); #ifdef MODULE + if (enet) + ret = set_phy_type(enet); + + if (board) + ret = set_board_type(board); + if (eipv4) ret = set_early_ethernet_ipv4(eipv4); @@ -2374,7 +2417,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) } ETHQOSDBG("gdsc-off-on-suspend = %d\n", ethqos->gdsc_off_on_suspend); - + plat_dat->phy_type = phytype; + plat_dat->board_type = boardtype; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (ret) goto err_clk; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 502902077a34..e69ebde324a3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -55,6 +55,11 @@ struct stmmac_tx_info { #define STMMAC_TBS_AVAIL BIT(0) #define STMMAC_TBS_EN BIT(1) +#define AIR_BOARD 1 +#define STAR_BOARD 2 +#define PHY_1G 1 +#define PHY_25G 2 + /* Frequently used values are kept adjacent for cache effect */ struct stmmac_tx_queue { u32 tx_count_frames; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index d17149690050..2a6a5f73150a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -433,6 +433,76 @@ int stmmac_xpcs_setup(struct mii_bus *bus) return 0; } +/** + * stmmac_get_phy_addr + * @priv: net device structure + * @new_bus: points to the mii_bus structure + * Description: it finds the PHY address from board and phy_type + */ +int stmmac_get_phy_addr(struct stmmac_priv *priv, struct mii_bus *new_bus, + struct net_device *ndev) +{ + struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; + struct device_node *np = priv->device->of_node; + unsigned int phyaddr; + int err = 0; + + init_completion(&priv->plat->mdio_op); + new_bus->reset = &stmmac_mdio_reset; + new_bus->priv = ndev; + + if (priv->plat->phy_type != -1) { + if (priv->plat->phy_type == PHY_1G) { + err = of_property_read_u32(np, "emac-1g-phy-addr", &phyaddr); + new_bus->read = &virtio_mdio_read; + new_bus->write = &virtio_mdio_write; + } else { + new_bus->read = &virtio_mdio_read_c45_indirect; + new_bus->write = &virtio_mdio_write_c45_indirect; + new_bus->probe_capabilities = MDIOBUS_C22_C45; + if (priv->plat->phy_type == PHY_25G && + priv->plat->board_type == STAR_BOARD) { + err = of_property_read_u32(np, + "emac-star-cl45-phy-addr", &phyaddr); + } else { + err = of_property_read_u32(np, + "emac-air-cl45-phy-addr", &phyaddr); + } + } + } else { + err = of_property_read_u32(np, "emac-1g-phy-addr", &phyaddr); + if (err) { + new_bus->phy_mask = mdio_bus_data->phy_mask; + return -1; + } + new_bus->read = &virtio_mdio_read; + new_bus->write = &virtio_mdio_write; + /* Do MDIO reset before the bus->read call */ + err = new_bus->reset(new_bus); + if (err) { + new_bus->phy_mask = ~(1 << phyaddr); + return phyaddr; + } + /* 1G phy check */ + err = new_bus->read(new_bus, phyaddr, MII_BMSR); + if (err == -EBUSY || err == 0xffff) { + /* 2.5 G PHY case */ + new_bus->read = &virtio_mdio_read_c45_indirect; + new_bus->write = &virtio_mdio_write_c45_indirect; + new_bus->probe_capabilities = MDIOBUS_C22_C45; + + err = of_property_read_u32(np, + "emac-air-cl45-phy-addr", &phyaddr); + /* Board Type check */ + err = new_bus->read(new_bus, phyaddr, MII_BMSR); + if (err == -EBUSY || !err || err == 0xffff) + err = of_property_read_u32(np, + "emac-star-cl45-phy-addr", &phyaddr); + } + } + new_bus->phy_mask = ~(1 << phyaddr); + return phyaddr; +} /** * stmmac_mdio_register * @ndev: net device structure @@ -474,10 +544,9 @@ int stmmac_mdio_register(struct net_device *ndev) err = of_property_read_bool(np, "virtio-mdio"); if (err) { - new_bus->read = &virtio_mdio_read; - new_bus->write = &virtio_mdio_write; - init_completion(&priv->plat->mdio_op); + phyaddr = stmmac_get_phy_addr(priv, new_bus, ndev); max_addr = PHY_MAX_ADDR; + skip_phy_detect = 1; } else if (priv->plat->has_xgmac) { new_bus->read = &stmmac_xgmac2_mdio_read; new_bus->write = &stmmac_xgmac2_mdio_write; @@ -501,24 +570,6 @@ int stmmac_mdio_register(struct net_device *ndev) snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x", new_bus->name, priv->plat->bus_id); new_bus->priv = ndev; - err = of_property_read_u32(np, "emac-phy-addr", &phyaddr); - if (err) { - new_bus->phy_mask = mdio_bus_data->phy_mask; - } else { - err = new_bus->read(new_bus, phyaddr, MII_BMSR); - if (err == -EBUSY || !err || err == 0xffff) { - err = of_property_read_u32(np, "emac-cl45-phy-addr", &phyaddr); - new_bus->phy_mask = ~(1 << phyaddr); - skip_phy_detect = 1; - new_bus->read = &virtio_mdio_read_c45_indirect; - new_bus->write = &virtio_mdio_write_c45_indirect; - new_bus->probe_capabilities = MDIOBUS_C22_C45; - } else { - new_bus->phy_mask = ~(1 << phyaddr); - skip_phy_detect = 1; - } - } - new_bus->parent = priv->device; err = of_mdiobus_register(new_bus, mdio_node); diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h index 0726de4df0f0..ed40c565a8a3 100644 --- a/include/linux/stmmac.h +++ b/include/linux/stmmac.h @@ -308,5 +308,7 @@ struct plat_stmmacenet_data { bool mdio_op_busy; atomic_t phy_clks_suspended; struct completion mdio_op; + int board_type; + int phy_type; }; #endif