aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-5.4/701-net-0317-staging-fsl_ppfe-eth-separate-mdio-init-from-mac-ini.patch
diff options
context:
space:
mode:
authorYangbo Lu <yangbo.lu@nxp.com>2020-04-10 10:47:05 +0800
committerPetr Štetiar <ynezz@true.cz>2020-05-07 12:53:06 +0200
commitcddd4591404fb4c53dc0b3c0b15b942cdbed4356 (patch)
tree392c1179de46b0f804e3789edca19069b64e6b44 /target/linux/layerscape/patches-5.4/701-net-0317-staging-fsl_ppfe-eth-separate-mdio-init-from-mac-ini.patch
parentd1d2c0b5579ea4f69a42246c9318539d61ba1999 (diff)
downloadupstream-cddd4591404fb4c53dc0b3c0b15b942cdbed4356.tar.gz
upstream-cddd4591404fb4c53dc0b3c0b15b942cdbed4356.tar.bz2
upstream-cddd4591404fb4c53dc0b3c0b15b942cdbed4356.zip
layerscape: add patches-5.4
Add patches for linux-5.4. The patches are from NXP LSDK-20.04 release which was tagged LSDK-20.04-V5.4. https://source.codeaurora.org/external/qoriq/qoriq-components/linux/ For boards LS1021A-IOT, and Traverse-LS1043 which are not involved in LSDK, port the dts patches from 4.14. The patches are sorted into the following categories: 301-arch-xxxx 302-dts-xxxx 303-core-xxxx 701-net-xxxx 801-audio-xxxx 802-can-xxxx 803-clock-xxxx 804-crypto-xxxx 805-display-xxxx 806-dma-xxxx 807-gpio-xxxx 808-i2c-xxxx 809-jailhouse-xxxx 810-keys-xxxx 811-kvm-xxxx 812-pcie-xxxx 813-pm-xxxx 814-qe-xxxx 815-sata-xxxx 816-sdhc-xxxx 817-spi-xxxx 818-thermal-xxxx 819-uart-xxxx 820-usb-xxxx 821-vfio-xxxx Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Diffstat (limited to 'target/linux/layerscape/patches-5.4/701-net-0317-staging-fsl_ppfe-eth-separate-mdio-init-from-mac-ini.patch')
-rw-r--r--target/linux/layerscape/patches-5.4/701-net-0317-staging-fsl_ppfe-eth-separate-mdio-init-from-mac-ini.patch651
1 files changed, 651 insertions, 0 deletions
diff --git a/target/linux/layerscape/patches-5.4/701-net-0317-staging-fsl_ppfe-eth-separate-mdio-init-from-mac-ini.patch b/target/linux/layerscape/patches-5.4/701-net-0317-staging-fsl_ppfe-eth-separate-mdio-init-from-mac-ini.patch
new file mode 100644
index 0000000000..fbf13c8ffc
--- /dev/null
+++ b/target/linux/layerscape/patches-5.4/701-net-0317-staging-fsl_ppfe-eth-separate-mdio-init-from-mac-ini.patch
@@ -0,0 +1,651 @@
+From 8848f975ce42674b8bc8dedb5c7b326a42088e99 Mon Sep 17 00:00:00 2001
+From: Calvin Johnson <calvin.johnson@nxp.com>
+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 <calvin.johnson@nxp.com>
+---
+ 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;