From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bin Meng Date: Fri, 23 Apr 2021 17:14:02 +0800 Subject: [PATCH v4 06/22] net: phy: xilinx: Be compatible with live OF tree In-Reply-To: References: <20210314121506.18303-1-bmeng.cn@gmail.com> <20210314121506.18303-7-bmeng.cn@gmail.com> Message-ID: List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Hi Michal, On Fri, Apr 23, 2021 at 3:35 PM Michal Simek wrote: > > Hi Bin, > > ne 14. 3. 2021 v 13:17 odes?latel Bin Meng napsal: > > > > Following the same updates that were done to the fixed phy driver, > > use ofnode_ APIs instead of fdt_ APIs so that the Xilinx PHY driver > > can support live DT. > > > > Signed-off-by: Bin Meng > > > > --- > > > > (no changes since v2) > > > > Changes in v2: > > - move device tree parsing from xilinxgmiitorgmii_probe() to > > xilinxgmiitorgmii_config() and use OF APIs > > > > drivers/net/phy/phy.c | 23 +++++------ > > drivers/net/phy/xilinx_gmii2rgmii.c | 61 ++++++++++++++--------------- > > 2 files changed, 40 insertions(+), 44 deletions(-) > > > > diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c > > index eae40cc0d6..d464379121 100644 > > --- a/drivers/net/phy/phy.c > > +++ b/drivers/net/phy/phy.c > > @@ -953,23 +953,20 @@ static struct phy_device *phy_connect_gmii2rgmii(struct mii_dev *bus, > > #endif > > { > > struct phy_device *phydev = NULL; > > - int sn = dev_of_offset(dev); > > - int off; > > - > > - while (sn > 0) { > > - off = fdt_node_offset_by_compatible(gd->fdt_blob, sn, > > - "xlnx,gmii-to-rgmii-1.0"); > > - if (off > 0) { > > - phydev = phy_device_create(bus, off, > > + ofnode node = dev_ofnode(dev); > > + > > + while (ofnode_valid(node)) { > > + node = ofnode_by_compatible(node, "xlnx,gmii-to-rgmii-1.0"); > > + if (ofnode_valid(node)) { > > + phydev = phy_device_create(bus, 0, > > PHY_GMII2RGMII_ID, false, > > interface); > > + if (phydev) > > + phydev->node = node; > > break; > > } > > - if (off == -FDT_ERR_NOTFOUND) > > - sn = fdt_first_subnode(gd->fdt_blob, sn); > > - else > > - printf("%s: Error finding compat string:%d\n", > > - __func__, off); > > + > > + node = ofnode_first_subnode(node); > > } > > > > return phydev; > > diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c > > index 74105c0b7d..635c0570ef 100644 > > --- a/drivers/net/phy/xilinx_gmii2rgmii.c > > +++ b/drivers/net/phy/xilinx_gmii2rgmii.c > > @@ -18,9 +18,38 @@ DECLARE_GLOBAL_DATA_PTR; > > > > static int xilinxgmiitorgmii_config(struct phy_device *phydev) > > { > > - struct phy_device *ext_phydev = phydev->priv; > > + ofnode node = phy_get_ofnode(phydev); > > + struct phy_device *ext_phydev; > > + struct ofnode_phandle_args phandle; > > + int ext_phyaddr = -1; > > + int ret; > > > > debug("%s\n", __func__); > > + > > + if (!ofnode_valid(node)) > > + return -EINVAL; > > + > > + phydev->addr = ofnode_read_u32_default(node, "reg", -1); > > + ret = ofnode_parse_phandle_with_args(node, "phy-handle", > > + NULL, 0, 0, &phandle); > > + if (ret) > > + return ret; > > + > > + ext_phyaddr = ofnode_read_u32_default(phandle.node, "reg", -1); > > + ext_phydev = phy_find_by_mask(phydev->bus, > > + 1 << ext_phyaddr, > > + PHY_INTERFACE_MODE_RGMII); > > + if (!ext_phydev) { > > + printf("%s, No external phy device found\n", __func__); > > + return -EINVAL; > > + } > > + > > + ext_phydev->node = phandle.node; > > + phydev->priv = ext_phydev; > > + > > + debug("%s, gmii2rgmmi:0x%x, extphy:0x%x\n", __func__, phydev->addr, > > + ext_phyaddr); > > + > > if (ext_phydev->drv->config) > > ext_phydev->drv->config(ext_phydev); > > > > @@ -83,11 +112,6 @@ static int xilinxgmiitorgmii_startup(struct phy_device *phydev) > > > > static int xilinxgmiitorgmii_probe(struct phy_device *phydev) > > { > > - int ofnode = phydev->addr; > > - u32 phy_of_handle; > > - int ext_phyaddr = -1; > > - struct phy_device *ext_phydev; > > - > > debug("%s\n", __func__); > > > > if (phydev->interface != PHY_INTERFACE_MODE_GMII) { > > @@ -95,31 +119,6 @@ static int xilinxgmiitorgmii_probe(struct phy_device *phydev) > > return -EINVAL; > > } > > > > - /* > > - * Read the phy address again as the one we read in ethernet driver > > - * was overwritten for the purpose of storing the ofnode > > - */ > > - phydev->addr = fdtdec_get_int(gd->fdt_blob, ofnode, "reg", -1); > > - phy_of_handle = fdtdec_lookup_phandle(gd->fdt_blob, ofnode, > > - "phy-handle"); > > - if (phy_of_handle > 0) > > - ext_phyaddr = fdtdec_get_int(gd->fdt_blob, > > - phy_of_handle, > > - "reg", -1); > > - ext_phydev = phy_find_by_mask(phydev->bus, > > - 1 << ext_phyaddr, > > - PHY_INTERFACE_MODE_RGMII); > > - if (!ext_phydev) { > > - printf("%s, No external phy device found\n", __func__); > > - return -EINVAL; > > - } > > - > > - ext_phydev->node = offset_to_ofnode(phy_of_handle); > > - phydev->priv = ext_phydev; > > - > > - debug("%s, gmii2rgmmi:0x%x, extphy:0x%x\n", __func__, phydev->addr, > > - ext_phyaddr); > > - > > phydev->flags |= PHY_FLAG_BROKEN_RESET; > > > > return 0; > > -- > > 2.25.1 > > > > This patch is breaking u-boot on ZynqMP. In phy_connect_gmii2rgmii you > get a valid node from dev_ofnode(dev) > and you enter the while loop because ofnode_valid(node) returns true. > ofnode_by_compatible() will fail because it is not normally > gmii-to-rgmii bridge and will go to ofnode_first_subnode() which > returns 0 > which goes back to ofnode_valid() which pass again because 0 is valid > and it keeps going in this while loop. > This is with xilinx_zynqmp_virt_defconfig configuration with OF_LIVE > off but with OF_LIVE on behavior is the same. > > It means that the while loop should be replaced by something more deterministic. > What about? > ofnode_for_each_subnode(node, dev_ofnode(dev)) { This sounds good to me. I cannot find an in-tree DTS that contains the compatible string "xlnx,gmii-to-rgmii-1.0". Is this an out-of-tree DT? Regards, Bin