On Fri, 22 Mar 2024 at 12:45, Neil Armstrong <neil.armstrong@xxxxxxxxxx> wrote: > > On 22/03/2024 11:41, Dmitry Baryshkov wrote: > > 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? > > Nop it doesn't with GCC arm-gnu-toolchain-13.2.Rel1-x86_64-aarch64-none-linux-gnu + W=1 and with smatch and C=1 Ok, great! > > Neil > > > > >> + } > >> + > >> + 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