On Wed, Nov 06, 2024 at 11:16:37AM +0800, Lei Wei wrote: > > > On 11/1/2024 9:21 PM, Andrew Lunn wrote: > > > +static int ipq_pcs_config_mode(struct ipq_pcs *qpcs, > > > + phy_interface_t interface) > > > +{ > > > + unsigned int val; > > > + int ret; > > > + > > > + /* Configure PCS interface mode */ > > > + switch (interface) { > > > + case PHY_INTERFACE_MODE_SGMII: > > > + /* Select Qualcomm SGMII AN mode */ > > > + ret = regmap_update_bits(qpcs->regmap, PCS_MODE_CTRL, > > > + PCS_MODE_SEL_MASK | PCS_MODE_AN_MODE, > > > + PCS_MODE_SGMII); > > > > How does Qualcomm SGMII AN mode differ from Cisco SGMII AN mode? > > > > Qualcomm SGMII AN mode extends Cisco SGMII spec Revision 1.8 by adding pause > bit support in the SGMII word format. It re-uses two of the reserved bits > 1..9 for this purpose. The PCS supports both Qualcomm SGMII AN and Cisco > SGMII AN modes. Is Qualcomm SGMII AN actually needed? I assume it only works against a Qualcomm PHY? What interoperability testing have you do against non-Qualcomm PHYs? > > > +struct phylink_pcs *ipq_pcs_create(struct device_node *np) > > > +{ > > > + struct platform_device *pdev; > > > + struct ipq_pcs_mii *qpcs_mii; > > > + struct device_node *pcs_np; > > > + struct ipq_pcs *qpcs; > > > + int i, ret; > > > + u32 index; > > > + > > > + if (!of_device_is_available(np)) > > > + return ERR_PTR(-ENODEV); > > > + > > > + if (of_property_read_u32(np, "reg", &index)) > > > + return ERR_PTR(-EINVAL); > > > + > > > + if (index >= PCS_MAX_MII_NRS) > > > + return ERR_PTR(-EINVAL); > > > + > > > + pcs_np = of_get_parent(np); > > > + if (!pcs_np) > > > + return ERR_PTR(-ENODEV); > > > + > > > + if (!of_device_is_available(pcs_np)) { > > > + of_node_put(pcs_np); > > > + return ERR_PTR(-ENODEV); > > > + } > > > > How have you got this far if the parent is not available? > > > > This check can fail only if the parent node is disabled in the board DTS. I > think this error situation may not be caught earlier than this point. > However I agree, the above check is redundant, since this check is > immediately followed by a validity check on the 'pdev' of the parent node, > which should be able cover any such errors as well. This was also because the driver does not work as i expected. I was expecting the PCS driver to walk its own DT and instantiate the PCS devices listed. If the parent is disabled, it is clearly not going to start its own children. But it is in fact some other device which walks the PCS DT blob, and as a result the child/parent relationship is broken, a child could exist without its parent. > > > + for (i = 0; i < PCS_MII_CLK_MAX; i++) { > > > + qpcs_mii->clk[i] = of_clk_get_by_name(np, pcs_mii_clk_name[i]); > > > + if (IS_ERR(qpcs_mii->clk[i])) { > > > + dev_err(qpcs->dev, > > > + "Failed to get MII %d interface clock %s\n", > > > + index, pcs_mii_clk_name[i]); > > > + goto err_clk_get; > > > + } > > > + > > > + ret = clk_prepare_enable(qpcs_mii->clk[i]); > > > + if (ret) { > > > + dev_err(qpcs->dev, > > > + "Failed to enable MII %d interface clock %s\n", > > > + index, pcs_mii_clk_name[i]); > > > + goto err_clk_en; > > > + } > > > + } > > > > Maybe devm_clk_bulk_get() etc will help you here? I've never actually > > used them, so i don't know for sure. > > > > We don't have a 'device' associated with the 'np', so we could not consider > using the "devm_clk_bulk_get()" API. Another artefact of not have a child-parent relationship. I wounder if it makes sense to change the architecture. Have the PCS driver instantiate the PCS devices as its children. They then have a device structure for calls like clk_bulk_get(), and a more normal consumer/provider setup. Andrew