From 8848f975ce42674b8bc8dedb5c7b326a42088e99 Mon Sep 17 00:00:00 2001 From: Calvin Johnson Date: Mon, 10 Dec 2018 10:22:33 +0530 Subject: [PATCH] staging: fsl_ppfe/eth: separate mdio init from mac init - separate mdio initialization from mac initialization - Define pfe_mdio_priv_s structure to hold mii_bus structure and other related data. - Modify functions to work with the separted mdio init model. Signed-off-by: Calvin Johnson --- drivers/staging/fsl_ppfe/pfe_eth.c | 232 ++++++++++-------------- drivers/staging/fsl_ppfe/pfe_eth.h | 17 +- drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c | 50 ++--- drivers/staging/fsl_ppfe/pfe_mod.h | 1 + 4 files changed, 126 insertions(+), 174 deletions(-) --- a/drivers/staging/fsl_ppfe/pfe_eth.c +++ b/drivers/staging/fsl_ppfe/pfe_eth.c @@ -790,10 +790,9 @@ const struct ethtool_ops pfe_ethtool_ops */ int pfe_eth_mdio_reset(struct mii_bus *bus) { - struct pfe_eth_priv_s *priv = (struct pfe_eth_priv_s *)bus->priv; + struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; u32 phy_speed; - netif_info(priv, hw, priv->ndev, "%s\n", __func__); mutex_lock(&bus->mdio_lock); @@ -806,25 +805,25 @@ int pfe_eth_mdio_reset(struct mii_bus *b phy_speed = (DIV_ROUND_UP((pfe->ctrl.sys_clk * 1000), 4000000) << EMAC_MII_SPEED_SHIFT); phy_speed |= EMAC_HOLDTIME(0x5); - __raw_writel(phy_speed, priv->PHY_baseaddr + EMAC_MII_CTRL_REG); + __raw_writel(phy_speed, priv->mdio_base + EMAC_MII_CTRL_REG); mutex_unlock(&bus->mdio_lock); return 0; } -/* pfe_eth_gemac_phy_timeout +/* pfe_eth_mdio_timeout * */ -static int pfe_eth_gemac_phy_timeout(struct pfe_eth_priv_s *priv, int timeout) +static int pfe_eth_mdio_timeout(struct pfe_mdio_priv_s *priv, int timeout) { - while (!(__raw_readl(priv->PHY_baseaddr + EMAC_IEVENT_REG) & + while (!(__raw_readl(priv->mdio_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) { if (timeout-- <= 0) return -1; usleep_range(10, 20); } - __raw_writel(EMAC_IEVENT_MII, priv->PHY_baseaddr + EMAC_IEVENT_REG); + __raw_writel(EMAC_IEVENT_MII, priv->mdio_base + EMAC_IEVENT_REG); return 0; } @@ -856,16 +855,15 @@ static int pfe_eth_mdio_mux(u8 muxval) static int pfe_eth_mdio_write_addr(struct mii_bus *bus, int mii_id, int dev_addr, int regnum) { - struct pfe_eth_priv_s *priv = (struct pfe_eth_priv_s *)bus->priv; + struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; __raw_writel(EMAC_MII_DATA_PA(mii_id) | EMAC_MII_DATA_RA(dev_addr) | EMAC_MII_DATA_TA | EMAC_MII_DATA(regnum), - priv->PHY_baseaddr + EMAC_MII_DATA_REG); + priv->mdio_base + EMAC_MII_DATA_REG); - if (pfe_eth_gemac_phy_timeout(priv, EMAC_MDIO_TIMEOUT)) { - netdev_err(priv->ndev, "%s: phy MDIO address write timeout\n", - __func__); + if (pfe_eth_mdio_timeout(priv, EMAC_MDIO_TIMEOUT)) { + dev_err(&bus->dev, "phy MDIO address write timeout\n"); return -1; } @@ -875,7 +873,7 @@ static int pfe_eth_mdio_write_addr(struc static int pfe_eth_mdio_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { - struct pfe_eth_priv_s *priv = (struct pfe_eth_priv_s *)bus->priv; + struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; /*To access external PHYs on QDS board mux needs to be configured*/ if ((mii_id) && (pfe->mdio_muxval[mii_id])) @@ -888,30 +886,26 @@ static int pfe_eth_mdio_write(struct mii EMAC_MII_DATA_PA(mii_id) | EMAC_MII_DATA_RA((regnum >> 16) & 0x1f) | EMAC_MII_DATA_TA | EMAC_MII_DATA(value), - priv->PHY_baseaddr + EMAC_MII_DATA_REG); + priv->mdio_base + EMAC_MII_DATA_REG); } else { /* start a write op */ __raw_writel(EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR | EMAC_MII_DATA_PA(mii_id) | EMAC_MII_DATA_RA(regnum) | EMAC_MII_DATA_TA | EMAC_MII_DATA(value), - priv->PHY_baseaddr + EMAC_MII_DATA_REG); + priv->mdio_base + EMAC_MII_DATA_REG); } - if (pfe_eth_gemac_phy_timeout(priv, EMAC_MDIO_TIMEOUT)) { - netdev_err(priv->ndev, "%s: phy MDIO write timeout\n", - __func__); + if (pfe_eth_mdio_timeout(priv, EMAC_MDIO_TIMEOUT)) { + dev_err(&bus->dev, "%s: phy MDIO write timeout\n", __func__); return -1; } - netif_info(priv, hw, priv->ndev, "%s: phy %x reg %x val %x\n", __func__, - mii_id, regnum, value); - return 0; } static int pfe_eth_mdio_read(struct mii_bus *bus, int mii_id, int regnum) { - struct pfe_eth_priv_s *priv = (struct pfe_eth_priv_s *)bus->priv; + struct pfe_mdio_priv_s *priv = (struct pfe_mdio_priv_s *)bus->priv; u16 value = 0; /*To access external PHYs on QDS board mux needs to be configured*/ @@ -925,65 +919,67 @@ static int pfe_eth_mdio_read(struct mii_ EMAC_MII_DATA_PA(mii_id) | EMAC_MII_DATA_RA((regnum >> 16) & 0x1f) | EMAC_MII_DATA_TA, - priv->PHY_baseaddr + EMAC_MII_DATA_REG); + priv->mdio_base + EMAC_MII_DATA_REG); } else { /* start a read op */ __raw_writel(EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD | EMAC_MII_DATA_PA(mii_id) | EMAC_MII_DATA_RA(regnum) | - EMAC_MII_DATA_TA, priv->PHY_baseaddr + + EMAC_MII_DATA_TA, priv->mdio_base + EMAC_MII_DATA_REG); } - if (pfe_eth_gemac_phy_timeout(priv, EMAC_MDIO_TIMEOUT)) { - netdev_err(priv->ndev, "%s: phy MDIO read timeout\n", __func__); + if (pfe_eth_mdio_timeout(priv, EMAC_MDIO_TIMEOUT)) { + dev_err(&bus->dev, "%s: phy MDIO read timeout\n", __func__); return -1; } - value = EMAC_MII_DATA(__raw_readl(priv->PHY_baseaddr + + value = EMAC_MII_DATA(__raw_readl(priv->mdio_base + EMAC_MII_DATA_REG)); - netif_info(priv, hw, priv->ndev, "%s: phy %x reg %x val %x\n", __func__, - mii_id, regnum, value); return value; } -static int pfe_eth_mdio_init(struct pfe_eth_priv_s *priv, - struct ls1012a_mdio_platform_data *minfo) +static int pfe_eth_mdio_init(struct pfe *pfe, + struct ls1012a_pfe_platform_data *pfe_info, + int ii) { + struct pfe_mdio_priv_s *priv = NULL; + struct ls1012a_mdio_platform_data *mdio_info; struct mii_bus *bus; struct device_node *mdio_node; - int rc = 0, ii; - struct phy_device *phydev; + int rc = 0; - netif_info(priv, drv, priv->ndev, "%s\n", __func__); - pr_info("%s\n", __func__); + mdio_info = (struct ls1012a_mdio_platform_data *) + pfe_info->ls1012a_mdio_pdata; + mdio_info->id = ii; - bus = mdiobus_alloc(); + bus = mdiobus_alloc_size(sizeof(struct pfe_mdio_priv_s)); if (!bus) { - netdev_err(priv->ndev, "mdiobus_alloc() failed\n"); + pr_err("mdiobus_alloc() failed\n"); rc = -ENOMEM; - goto err0; + goto err_mdioalloc; } bus->name = "ls1012a MDIO Bus"; - snprintf(bus->id, MII_BUS_ID_SIZE, "ls1012a-%x", priv->id); + snprintf(bus->id, MII_BUS_ID_SIZE, "ls1012a-%x", mdio_info->id); - bus->priv = priv; bus->read = &pfe_eth_mdio_read; bus->write = &pfe_eth_mdio_write; bus->reset = &pfe_eth_mdio_reset; - bus->parent = priv->pfe->dev; - bus->phy_mask = minfo->phy_mask; - bus->irq[0] = minfo->irq[0]; + bus->parent = pfe->dev; + bus->phy_mask = mdio_info->phy_mask; + bus->irq[0] = mdio_info->irq[0]; + priv = bus->priv; + priv->mdio_base = cbus_emac_base[ii]; - priv->mdc_div = minfo->mdc_div; + priv->mdc_div = mdio_info->mdc_div; if (!priv->mdc_div) priv->mdc_div = 64; - netif_info(priv, drv, priv->ndev, "%s: mdc_div: %d, phy_mask: %x\n", - __func__, priv->mdc_div, bus->phy_mask); + dev_info(bus->parent, "%s: mdc_div: %d, phy_mask: %x\n", + __func__, priv->mdc_div, bus->phy_mask); - mdio_node = of_get_child_by_name(priv->pfe->dev->of_node, "mdio"); - if (mdio_node) { + mdio_node = of_get_child_by_name(pfe->dev->of_node, "mdio"); + if ((mdio_info->id == 0) && mdio_node) { rc = of_mdiobus_register(bus, mdio_node); of_node_put(mdio_node); } else { @@ -991,56 +987,34 @@ static int pfe_eth_mdio_init(struct pfe_ } if (rc) { - netdev_err(priv->ndev, "mdiobus_register(%s) failed\n", - bus->name); - goto err1; + dev_err(bus->parent, "mdiobus_register(%s) failed\n", + bus->name); + goto err_mdioregister; } priv->mii_bus = bus; - - /* For clause 45 we need to call get_phy_device() with it's - * 3rd argument as true and then register the phy device - * via phy_device_register() - */ - if (priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) { - for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) { - phydev = get_phy_device(priv->mii_bus, - priv->einfo->phy_id + ii, true); - if (!phydev || IS_ERR(phydev)) { - rc = -EIO; - netdev_err(priv->ndev, "fail to get device\n"); - goto err1; - } - rc = phy_device_register(phydev); - if (rc) { - phy_device_free(phydev); - netdev_err(priv->ndev, - "phy_device_register() failed\n"); - goto err1; - } - } - } + pfe->mdio.mdio_priv[ii] = priv; pfe_eth_mdio_reset(bus); return 0; -err1: +err_mdioregister: mdiobus_free(bus); -err0: +err_mdioalloc: return rc; } /* pfe_eth_mdio_exit */ -static void pfe_eth_mdio_exit(struct mii_bus *bus) +static void pfe_eth_mdio_exit(struct pfe *pfe, + int ii) { + struct pfe_mdio_priv_s *mdio_priv = pfe->mdio.mdio_priv[ii]; + struct mii_bus *bus = mdio_priv->mii_bus; + if (!bus) return; - - netif_info((struct pfe_eth_priv_s *)bus->priv, drv, ((struct - pfe_eth_priv_s *)(bus->priv))->ndev, "%s\n", __func__); - mdiobus_unregister(bus); mdiobus_free(bus); } @@ -1221,15 +1195,16 @@ static int pfe_eth_start(struct pfe_eth_ */ static void ls1012a_configure_serdes(struct net_device *ndev) { - struct pfe_eth_priv_s *priv = pfe->eth.eth_priv[0]; + struct pfe_eth_priv_s *eth_priv = netdev_priv(ndev); + struct pfe_mdio_priv_s *mdio_priv = pfe->mdio.mdio_priv[eth_priv->id]; int sgmii_2500 = 0; - struct mii_bus *bus = priv->mii_bus; + struct mii_bus *bus = mdio_priv->mii_bus; u16 value = 0; - if (priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) + if (eth_priv->einfo->mii_config == PHY_INTERFACE_MODE_2500SGMII) sgmii_2500 = 1; - netif_info(priv, drv, ndev, "%s\n", __func__); + netif_info(eth_priv, drv, ndev, "%s\n", __func__); /* PCS configuration done with corresponding GEMAC */ pfe_eth_mdio_read(bus, 0, MDIO_SGMII_CR); @@ -2333,26 +2308,15 @@ static const struct net_device_ops pfe_n /* pfe_eth_init_one */ -static int pfe_eth_init_one(struct pfe *pfe, int id) +static int pfe_eth_init_one(struct pfe *pfe, + struct ls1012a_pfe_platform_data *pfe_info, + int id) { struct net_device *ndev = NULL; struct pfe_eth_priv_s *priv = NULL; struct ls1012a_eth_platform_data *einfo; - struct ls1012a_mdio_platform_data *minfo; - struct ls1012a_pfe_platform_data *pfe_info; int err; - /* Extract pltform data */ - pfe_info = (struct ls1012a_pfe_platform_data *) - pfe->dev->platform_data; - if (!pfe_info) { - pr_err( - "%s: pfe missing additional platform data\n" - , __func__); - err = -ENODEV; - goto err0; - } - einfo = (struct ls1012a_eth_platform_data *) pfe_info->ls1012a_eth_pdata; @@ -2365,18 +2329,6 @@ static int pfe_eth_init_one(struct pfe * goto err0; } - minfo = (struct ls1012a_mdio_platform_data *) - pfe_info->ls1012a_mdio_pdata; - - /* einfo never be NULL, but no harm in having this check */ - if (!minfo) { - pr_err( - "%s: pfe missing additional mdios platform data\n", - __func__); - err = -ENODEV; - goto err0; - } - if (us) emac_txq_cnt = EMAC_TXQ_CNT; /* Create an ethernet device instance */ @@ -2402,7 +2354,6 @@ static int pfe_eth_init_one(struct pfe * /* Set the info in the priv to the current info */ priv->einfo = &einfo[id]; priv->EMAC_baseaddr = cbus_emac_base[id]; - priv->PHY_baseaddr = cbus_emac_base[0]; priv->GPI_baseaddr = cbus_gpi_base[id]; spin_lock_init(&priv->lock); @@ -2412,13 +2363,6 @@ static int pfe_eth_init_one(struct pfe * /* Copy the station address into the dev structure, */ memcpy(ndev->dev_addr, einfo[id].mac_addr, ETH_ALEN); - /* Initialize mdio */ - err = pfe_eth_mdio_init(priv, &minfo[id]); - if (err) { - netdev_err(ndev, "%s: pfe_eth_mdio_init() failed\n", __func__); - goto err1; - } - if (us) goto phy_init; @@ -2463,7 +2407,7 @@ static int pfe_eth_init_one(struct pfe * err = register_netdev(ndev); if (err) { netdev_err(ndev, "register_netdev() failed\n"); - goto err2; + goto err1; } if ((!(pfe_use_old_dts_phy) && !(priv->phy_node)) || @@ -2480,7 +2424,7 @@ phy_init: if (err) { netdev_err(ndev, "%s: pfe_phy_init() failed\n", __func__); - goto err3; + goto err2; } if (us) { @@ -2494,21 +2438,19 @@ phy_init: skip_phy_init: /* Create all the sysfs files */ if (pfe_eth_sysfs_init(ndev)) - goto err4; + goto err3; netif_info(priv, probe, ndev, "%s: created interface, baseaddr: %p\n", __func__, priv->EMAC_baseaddr); return 0; -err4: - pfe_phy_exit(priv->ndev); err3: + pfe_phy_exit(priv->ndev); +err2: if (us) - goto err2; + goto err1; unregister_netdev(ndev); -err2: - pfe_eth_mdio_exit(priv->mii_bus); err1: free_netdev(priv->ndev); err0: @@ -2521,6 +2463,7 @@ int pfe_eth_init(struct pfe *pfe) { int ii = 0; int err; + struct ls1012a_pfe_platform_data *pfe_info; pr_info("%s\n", __func__); @@ -2530,24 +2473,43 @@ int pfe_eth_init(struct pfe *pfe) cbus_gpi_base[0] = EGPI1_BASE_ADDR; cbus_gpi_base[1] = EGPI2_BASE_ADDR; + pfe_info = (struct ls1012a_pfe_platform_data *) + pfe->dev->platform_data; + if (!pfe_info) { + pr_err("%s: pfe missing additional platform data\n", __func__); + err = -ENODEV; + goto err_pdata; + } + + for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) { + err = pfe_eth_mdio_init(pfe, pfe_info, ii); + if (err) { + pr_err("%s: pfe_eth_mdio_init() failed\n", __func__); + goto err_mdio_init; + } + } + if (fsl_guts_get_svr() == LS1012A_REV_1_0) pfe_errata_a010897 = true; else pfe_errata_a010897 = false; for (ii = 0; ii < NUM_GEMAC_SUPPORT; ii++) { - err = pfe_eth_init_one(pfe, ii); + err = pfe_eth_init_one(pfe, pfe_info, ii); if (err) - goto err0; + goto err_eth_init; } return 0; -err0: - while (ii--) +err_eth_init: + while (ii--) { pfe_eth_exit_one(pfe->eth.eth_priv[ii]); + pfe_eth_mdio_exit(pfe, ii); + } - /* Register three network devices in the kernel */ +err_mdio_init: +err_pdata: return err; } @@ -2573,9 +2535,6 @@ skip_phy_exit: if (!us) unregister_netdev(priv->ndev); - if (priv->mii_bus) - pfe_eth_mdio_exit(priv->mii_bus); - free_netdev(priv->ndev); } @@ -2589,4 +2548,7 @@ void pfe_eth_exit(struct pfe *pfe) for (ii = NUM_GEMAC_SUPPORT - 1; ii >= 0; ii--) pfe_eth_exit_one(pfe->eth.eth_priv[ii]); + + for (ii = NUM_GEMAC_SUPPORT - 1; ii >= 0; ii--) + pfe_eth_mdio_exit(pfe, ii); } --- a/drivers/staging/fsl_ppfe/pfe_eth.h +++ b/drivers/staging/fsl_ppfe/pfe_eth.h @@ -48,7 +48,7 @@ struct ls1012a_eth_platform_data { }; struct ls1012a_mdio_platform_data { - int enabled; + int id; int irq[32]; u32 phy_mask; int mdc_div; @@ -120,8 +120,6 @@ struct pfe_eth_priv_s { unsigned int event_status; int irq; void *EMAC_baseaddr; - /* This points to the EMAC base from where we access PHY */ - void *PHY_baseaddr; void *GPI_baseaddr; /* PHY stuff */ struct phy_device *phydev; @@ -129,9 +127,6 @@ struct pfe_eth_priv_s { int oldduplex; int oldlink; struct device_node *phy_node; - /* mdio info */ - int mdc_div; - struct mii_bus *mii_bus; struct clk *gemtx_clk; int wol; int pause_flag; @@ -161,6 +156,16 @@ struct pfe_eth { struct pfe_eth_priv_s *eth_priv[3]; }; +struct pfe_mdio_priv_s { + void __iomem *mdio_base; + int mdc_div; + struct mii_bus *mii_bus; +}; + +struct pfe_mdio { + struct pfe_mdio_priv_s *mdio_priv[3]; +}; + int pfe_eth_init(struct pfe *pfe); void pfe_eth_exit(struct pfe *pfe); int pfe_eth_suspend(struct net_device *dev); --- a/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c +++ b/drivers/staging/fsl_ppfe/pfe_ls1012a_platform.c @@ -21,31 +21,18 @@ extern bool pfe_use_old_dts_phy; struct ls1012a_pfe_platform_data pfe_platform_data; -static int pfe_get_gemac_if_properties(struct device_node *parent, int port, int - if_cnt, - struct ls1012a_pfe_platform_data - *pdata) +static int pfe_get_gemac_if_properties(struct device_node *gem, + int port, + struct ls1012a_pfe_platform_data *pdata) { - struct device_node *gem = NULL, *phy = NULL, *phy_node = NULL; + struct device_node *phy_node = NULL; int size; - int ii = 0, phy_id = 0; + int phy_id = 0; const u32 *addr; const void *mac_addr; - for (ii = 0; ii < if_cnt; ii++) { - gem = of_get_next_child(parent, gem); - if (!gem) - goto err; - addr = of_get_property(gem, "reg", &size); - if (addr && (be32_to_cpup(addr) == port)) - break; - } - - if (ii >= if_cnt) { - pr_err("%s:%d Failed to find interface = %d\n", - __func__, __LINE__, if_cnt); - goto err; - } + addr = of_get_property(gem, "reg", &size); + port = be32_to_cpup(addr); pdata->ls1012a_eth_pdata[port].gem_id = port; @@ -88,14 +75,6 @@ static int pfe_get_gemac_if_properties(s if (pdata->ls1012a_eth_pdata[port].phy_flags & GEMAC_NO_PHY) goto done; - phy = of_get_next_child(gem, NULL); - addr = of_get_property(phy, "reg", &size); - if (!addr) - pr_err("%s:%d Invalid phy enable flag....\n", - __func__, __LINE__); - else - pdata->ls1012a_mdio_pdata[port].enabled = - be32_to_cpup(addr); } else { pr_info("%s: No PHY or fixed-link\n", __func__); return 0; @@ -140,7 +119,7 @@ static int pfe_platform_probe(struct pla struct resource res; int ii, rc, interface_count = 0, size = 0; const u32 *prop; - struct device_node *np; + struct device_node *np, *gem = NULL; struct clk *pfe_clk; np = pdev->dev.of_node; @@ -224,8 +203,13 @@ static int pfe_platform_probe(struct pla pfe_platform_data.ls1012a_mdio_pdata[0].phy_mask = 0xffffffff; for (ii = 0; ii < interface_count; ii++) { - pfe_get_gemac_if_properties(np, ii, interface_count, - &pfe_platform_data); + gem = of_get_next_child(np, gem); + if (gem) + pfe_get_gemac_if_properties(gem, ii, + &pfe_platform_data); + else + pr_err("Unable to find interface %d\n", ii); + } pfe->dev = &pdev->dev; @@ -347,8 +331,8 @@ static int pfe_platform_resume(struct de for (i = 0; i < (NUM_GEMAC_SUPPORT); i++) { netdev = pfe->eth.eth_priv[i]->ndev; - if (pfe->eth.eth_priv[i]->mii_bus) - pfe_eth_mdio_reset(pfe->eth.eth_priv[i]->mii_bus); + if (pfe->mdio.mdio_priv[i]->mii_bus) + pfe_eth_mdio_reset(pfe->mdio.mdio_priv[i]->mii_bus); if (netif_running(netdev)) pfe_eth_resume(netdev); --- a/drivers/staging/fsl_ppfe/pfe_mod.h +++ b/drivers/staging/fsl_ppfe/pfe_mod.h @@ -52,6 +52,7 @@ struct pfe { struct pfe_ctrl ctrl; struct pfe_hif hif; struct pfe_eth eth; + struct pfe_mdio mdio; struct hif_client_s *hif_client[HIF_CLIENTS_MAX]; #if defined(CFG_DIAGS) struct pfe_diags diags;