On Fri, 22 Mar 2024 at 11:43, Neil Armstrong <neil.armstrong@xxxxxxxxxx> wrote: > > The PCIe Gen4x2 PHY found in the SM8[456]50 SoCs have a second clock, > add the code to register it for PHYs configs that sets a aux_clock_rate. > > In order to get the right clock, add qmp_pcie_clk_hw_get() which uses > the newly introduced QMP_PCIE_PIPE_CLK & QMP_PCIE_PHY_AUX_CLK clock > IDs and also supports the legacy bindings by returning the PIPE clock > when #clock-cells=0. > > Signed-off-by: Neil Armstrong <neil.armstrong@xxxxxxxxxx> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx> Small question below. > --- > drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 78 ++++++++++++++++++++++++++++++-- > 1 file changed, 75 insertions(+), 3 deletions(-) > > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c > index e8da2e9146dc..6c9a95e62429 100644 > --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c > @@ -22,6 +22,8 @@ > #include <linux/reset.h> > #include <linux/slab.h> > > +#include <dt-bindings/phy/phy-qcom-qmp.h> > + > #include "phy-qcom-qmp-common.h" > > #include "phy-qcom-qmp.h" > @@ -2389,6 +2391,9 @@ struct qmp_phy_cfg { > > /* QMP PHY pipe clock interface rate */ > unsigned long pipe_clock_rate; > + > + /* QMP PHY AUX clock interface rate */ > + unsigned long aux_clock_rate; > }; > > struct qmp_pcie { > @@ -2420,6 +2425,7 @@ struct qmp_pcie { > int mode; > > struct clk_fixed_rate pipe_clk_fixed; > + struct clk_fixed_rate aux_clk_fixed; > }; > > static inline void qphy_setbits(void __iomem *base, u32 offset, u32 val) > @@ -3686,6 +3692,62 @@ static int phy_pipe_clk_register(struct qmp_pcie *qmp, struct device_node *np) > return devm_clk_hw_register(qmp->dev, &fixed->hw); > } > > +/* > + * Register a fixed rate PHY aux clock. > + * > + * The <s>_phy_aux_clksrc generated by PHY goes to the GCC that gate > + * controls it. The <s>_phy_aux_clk coming out of the GCC is requested > + * by the PHY driver for its operations. > + * We register the <s>_phy_aux_clksrc here. The gcc driver takes care > + * of assigning this <s>_phy_aux_clksrc as parent to <s>_phy_aux_clk. > + * Below picture shows this relationship. > + * > + * +---------------+ > + * | PHY block |<<---------------------------------------------+ > + * | | | > + * | +-------+ | +-----+ | > + * I/P---^-->| PLL |---^--->phy_aux_clksrc--->| GCC |--->phy_aux_clk---+ > + * clk | +-------+ | +-----+ > + * +---------------+ > + */ > +static int phy_aux_clk_register(struct qmp_pcie *qmp, struct device_node *np) > +{ > + struct clk_fixed_rate *fixed = &qmp->aux_clk_fixed; > + struct clk_init_data init = { }; > + int ret; > + > + ret = of_property_read_string_index(np, "clock-output-names", 1, &init.name); > + if (ret) { > + dev_err(qmp->dev, "%pOFn: No clock-output-names index 1\n", np); > + return ret; > + } > + > + init.ops = &clk_fixed_rate_ops; > + > + fixed->fixed_rate = qmp->cfg->aux_clock_rate; > + fixed->hw.init = &init; > + > + return devm_clk_hw_register(qmp->dev, &fixed->hw); > +} > + > +static struct clk_hw *qmp_pcie_clk_hw_get(struct of_phandle_args *clkspec, void *data) > +{ > + struct qmp_pcie *qmp = data; > + > + /* Support legacy bindings */ > + if (!clkspec->args_count) > + return &qmp->pipe_clk_fixed.hw; > + > + switch (clkspec->args[0]) { > + case QMP_PCIE_PIPE_CLK: > + return &qmp->pipe_clk_fixed.hw; > + case QMP_PCIE_PHY_AUX_CLK: > + return &qmp->aux_clk_fixed.hw; Does the absence of the default case trigger a warning if compiled with W=1? > + } > + > + return ERR_PTR(-EINVAL); > +} > + > static int qmp_pcie_register_clocks(struct qmp_pcie *qmp, struct device_node *np) > { > int ret; > @@ -3694,9 +3756,19 @@ static int qmp_pcie_register_clocks(struct qmp_pcie *qmp, struct device_node *np > if (ret) > return ret; > > - ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &qmp->pipe_clk_fixed.hw); > - if (ret) > - return ret; > + if (qmp->cfg->aux_clock_rate) { > + ret = phy_aux_clk_register(qmp, np); > + if (ret) > + return ret; > + > + ret = of_clk_add_hw_provider(np, qmp_pcie_clk_hw_get, qmp); > + if (ret) > + return ret; > + } else { > + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &qmp->pipe_clk_fixed.hw); > + if (ret) > + return ret; > + } > > /* > * Roll a devm action because the clock provider is the child node, but > > -- > 2.34.1 > > -- With best wishes Dmitry