Re: [PATCH 1/8] net: phy: Introduce Qualcomm IPQ5018 internal PHY driver

From: Ziyang Huang
Date: Mon Jan 22 2024 - 12:00:58 EST


在 2024/1/22 0:19, Andrew Lunn 写道:
On Sun, Jan 21, 2024 at 08:42:30PM +0800, Ziyang Huang wrote:
Signed-off-by: Ziyang Huang <hzyitc@xxxxxxxxxxx>

You need to say something in the commit message. One obvious thing is
to justify not using the at803x driver, since

I want add more descriptions here. But I have no idea what to write. This is a mininal driver for a special phy.

Here is the thing, at first, I was tring to add these into at803x driver, then I found that the IPQ5018 internel phy is a special device. The initialization sequence is initing GCC clock and reset control, then registering clocks providers, which is very different from other devices.

What's more, I remembered it *wrongly* and thought it need to be accessed through MMIO. After checking the vendor code again, this doesn't exist.

So it seem like that it's a good idea to move it back to at803x driver.



+#define IPQ5018_PHY_ID 0x004dd0c0

is in the Atheros OUI range.

+static int ipq5018_probe(struct phy_device *phydev)
+{
+ struct ipq5018_phy *priv;
+ struct device *dev = &phydev->mdio.dev;
+ char name[64];
+ int ret;

I guess you are new to mainline network. Please read:

https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html

Section 1.6.4.

Sorry for missing it, will read it later.


+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to allocate priv\n");

Please read the documentation of dev_err_probe() and this fix the
obvious problem with this.

I had read it and I had known this helper function is to resolve the duplicate code for EPROBE_DEFER.

But it also say "Note that it is deemed acceptable to use this function for error prints during probe even if the @err is known to never be -EPROBE_DEFER. The benefit compared to a normal dev_err() is the standardized format of the error code and the fact that the error code is returned."

And I can find the same code in other driver, so I thought it is a standard. Or should I just return -ENOMEM? Please let me known.


+ snprintf(name, sizeof(name), "%s#rx", dev_name(dev));
+ priv->clk_rx = clk_hw_register_fixed_rate(dev, name, NULL, 0,
+ TX_RX_CLK_RATE);
+ if (IS_ERR_OR_NULL(priv->clk_rx))
+ return dev_err_probe(dev, PTR_ERR(priv->clk_rx),
+ "failed to register rx clock\n");
+
+ snprintf(name, sizeof(name), "%s#tx", dev_name(dev));
+ priv->clk_tx = clk_hw_register_fixed_rate(dev, name, NULL, 0,
+ TX_RX_CLK_RATE);
+ if (IS_ERR_OR_NULL(priv->clk_tx))
+ return dev_err_probe(dev, PTR_ERR(priv->clk_tx),
+ "failed to register tx clock\n");
+
+ priv->clk_data = devm_kzalloc(dev,
+ struct_size(priv->clk_data, hws, 2),
+ GFP_KERNEL);
+ if (!priv->clk_data)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to allocate clk_data\n");
+
+ priv->clk_data->num = 2;
+ priv->clk_data->hws[0] = priv->clk_rx;
+ priv->clk_data->hws[1] = priv->clk_tx;
+ ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+ priv->clk_data);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "fail to register clock provider\n");

This needs an explanation. Why register two fixed clocks, which you
never use? Why not put these two clocks in DT?

Without documentions, here is my guess:

This is required by GCC controller. GCC driver require TX and RX clocks from GEPHY/UNIPHY. Then throught some sel or div cells, output clocks to GEPHY/UNIPHY and MAC. So I need to register them to make them can be refered in GCC controller. Will add a figure describing the clock tree in UNIPHY driver.

The frequency of these clocks is depends on the mode. For GEPHY, it only supports SGMII ( Or something similar, this is a internal bus ) and the clock is fixed at 1.25G. But for UNIPHY, is supports more mode like SGMII+ which used 3.125G.


+
+ return 0;
+}
+
+static int ipq5018_soft_reset(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = phy_modify(phydev, IPQ5018_PHY_FIFO_CONTROL,
+ IPQ5018_PHY_FIFO_RESET, 0);
+ if (ret < 0)
+ return ret;
+
+ msleep(50);
+
+ ret = phy_modify(phydev, IPQ5018_PHY_FIFO_CONTROL,
+ IPQ5018_PHY_FIFO_RESET, IPQ5018_PHY_FIFO_RESET);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}

This needs an explanation. It is also somewhat like
qca808x_link_change_notify(). Is it really sufficient to only do this
reset FIFO during a soft reset, or is it needed when ever the link
changes?

I'm not sure here, this is what u-boot does. But I guess, we can reset GCC_GEPHY_* serial reset_controls.


You also appear to be missing device tree bindings.

Sorry for forgeting to add a WiP tag. Will add dt-bindings documentions in next patches.


Andrew

---
pw-bot: cr