On Tue, 19 Mar 2024 at 16:35, Neil Armstrong <neil.armstrong@xxxxxxxxxx> wrote: > > On 19/03/2024 11:59, Neil Armstrong wrote: > > On 19/03/2024 11:55, Dmitry Baryshkov wrote: > >> On Tue, 19 Mar 2024 at 12:45, 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. > >>> > >>> Signed-off-by: Neil Armstrong <neil.armstrong@xxxxxxxxxx> > >>> --- > >>> drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 70 ++++++++++++++++++++++++++++++++ > >>> 1 file changed, 70 insertions(+) > >>> > >>> diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c > >>> index 079b3e306489..2d05226ae200 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) > >>> @@ -3681,6 +3687,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; > >>> + } > >>> + > >>> + return ERR_PTR(-EINVAL); > >>> +} > >> > >> Can we use of_clk_hw_onecell_get() instead? I think it even should be > >> possible to use onecell for both cases, it will look at the first arg, > >> which will be 0 in case of #clock-cells equal to 0. > > > > Let me investigate if it's possible > > Ok, it would work but it would require building a clk_hw_onecell_data a runtime, > while we could simply provide this qmp_pcie_clk_hw_get() and avoid runtime 2 allocations. > > I'm not sure it's worth it. Single allocation (or even 0 allocations if you embed it into struct qmp_pcie) for the sake of using standard helpers. -- With best wishes Dmitry