Message ID | 20220603084454.1861142-2-dmitry.baryshkov@linaro.org (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | PCI: qcom: Rework pipe_clk/pipe_clk_src handling | expand |
Hi Dmitry, Thank you for the patch! Yet something to improve: [auto build test ERROR on v5.18] [also build test ERROR on next-20220603] [cannot apply to clk/clk-next helgaas-pci/next agross-msm/qcom/for-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/intel-lab-lkp/linux/commits/Dmitry-Baryshkov/PCI-qcom-Rework-pipe_clk-pipe_clk_src-handling/20220605-164136 base: 4b0986a3613c92f4ec1bdc7f60ec66fea135991f config: mips-randconfig-r005-20220605 (https://download.01.org/0day-ci/archive/20220605/202206052344.Lkv2vI5x-lkp@intel.com/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 416a5080d89066029f9889dc23f94de47c2fa895) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install mips cross compiling tool for clang build # apt-get install binutils-mips-linux-gnu # https://github.com/intel-lab-lkp/linux/commit/4fbc2ca1313223feb409121fa1028557f72a310b git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Dmitry-Baryshkov/PCI-qcom-Rework-pipe_clk-pipe_clk_src-handling/20220605-164136 git checkout 4fbc2ca1313223feb409121fa1028557f72a310b # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=mips SHELL=/bin/bash drivers/clk/qcom/ If you fix the issue, kindly add following tag where applicable Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): >> drivers/clk/qcom/clk-regmap-phy-mux.c:30:8: error: call to undeclared function 'FIELD_GET'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] val = FIELD_GET(PHY_MUX_MASK, val); ^ >> drivers/clk/qcom/clk-regmap-phy-mux.c:44:7: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] FIELD_PREP(PHY_MUX_MASK, PHY_MUX_PHY_SRC)); ^ drivers/clk/qcom/clk-regmap-phy-mux.c:54:7: error: call to undeclared function 'FIELD_PREP'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration] FIELD_PREP(PHY_MUX_MASK, PHY_MUX_REF_SRC)); ^ 3 errors generated. vim +/FIELD_GET +30 drivers/clk/qcom/clk-regmap-phy-mux.c 22 23 static int phy_mux_is_enabled(struct clk_hw *hw) 24 { 25 struct clk_regmap *clkr = to_clk_regmap(hw); 26 struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr); 27 unsigned int val; 28 29 regmap_read(clkr->regmap, phy_mux->reg, &val); > 30 val = FIELD_GET(PHY_MUX_MASK, val); 31 32 WARN_ON(val != PHY_MUX_PHY_SRC && val != PHY_MUX_REF_SRC); 33 34 return val == PHY_MUX_PHY_SRC; 35 } 36 37 static int phy_mux_enable(struct clk_hw *hw) 38 { 39 struct clk_regmap *clkr = to_clk_regmap(hw); 40 struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr); 41 42 return regmap_update_bits(clkr->regmap, phy_mux->reg, 43 PHY_MUX_MASK, > 44 FIELD_PREP(PHY_MUX_MASK, PHY_MUX_PHY_SRC)); 45 } 46
On Fri, Jun 03, 2022 at 11:44:50AM +0300, Dmitry Baryshkov wrote: > On recent Qualcomm platforms the QMP PIPE clocks feed into a set of > muxes which must be parked to the "safe" source (bi_tcxo) when > corresponding GDSC is turned off and on again. Currently this is > handcoded in the PCIe driver by reparenting the gcc_pipe_N_clk_src > clock. However the same code sequence should be applied in the > pcie-qcom endpoint, USB3 and UFS drivers. > > Rather than copying this sequence over and over again, follow the > example of clk_rcg2_shared_ops and implement this parking in the > enable() and disable() clock operations. Supplement the regmap-mux with > the new clk_regmap_phy_mux type, which implements such multiplexers > as a simple gate clocks. > > This is possible since each of these multiplexers has just two clock > sources: one coming from the PHY and a reference (XO) one. If the clock > is running off the from-PHY source, report it as enabled. Report it as > disabled otherwise (if it uses reference source). > > This way the PHY will disable the pipe clock before turning off the > GDSC, which in turn would lead to disabling corresponding pipe_clk_src > (and thus it being parked to a safe, reference clock source). And vice > versa, after enabling the GDSC the PHY will enable the pipe clock, which > would cause pipe_clk_src to be switched from a safe source to the > working one. > > Reviewed-by: Johan Hovold <johan+linaro@kernel.org> > Tested-by: Johan Hovold <johan+linaro@kernel.org> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> > --- > drivers/clk/qcom/Makefile | 1 + > drivers/clk/qcom/clk-regmap-phy-mux.c | 62 +++++++++++++++++++++++++++ > drivers/clk/qcom/clk-regmap-phy-mux.h | 33 ++++++++++++++ > 3 files changed, 96 insertions(+) > create mode 100644 drivers/clk/qcom/clk-regmap-phy-mux.c > create mode 100644 drivers/clk/qcom/clk-regmap-phy-mux.h > > diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile > index 36789f5233ef..08594230c1c1 100644 > --- a/drivers/clk/qcom/Makefile > +++ b/drivers/clk/qcom/Makefile > @@ -11,6 +11,7 @@ clk-qcom-y += clk-branch.o > clk-qcom-y += clk-regmap-divider.o > clk-qcom-y += clk-regmap-mux.o > clk-qcom-y += clk-regmap-mux-div.o > +clk-qcom-y += clk-regmap-phy-mux.o > clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o > clk-qcom-y += clk-hfpll.o > clk-qcom-y += reset.o > diff --git a/drivers/clk/qcom/clk-regmap-phy-mux.c b/drivers/clk/qcom/clk-regmap-phy-mux.c > new file mode 100644 > index 000000000000..a1adc075b471 > --- /dev/null > +++ b/drivers/clk/qcom/clk-regmap-phy-mux.c > @@ -0,0 +1,62 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (c) 2022, Linaro Ltd. > + */ > + > +#include <linux/clk-provider.h> > +#include <linux/bitops.h> > +#include <linux/regmap.h> > +#include <linux/export.h> > + > +#include "clk-regmap.h" > +#include "clk-regmap-phy-mux.h" > + > +#define PHY_MUX_MASK GENMASK(1, 0) > +#define PHY_MUX_PHY_SRC 0 > +#define PHY_MUX_REF_SRC 2 > + > +static inline struct clk_regmap_phy_mux *to_clk_regmap_phy_mux(struct clk_regmap *clkr) > +{ > + return container_of(clkr, struct clk_regmap_phy_mux, clkr); > +} > + > +static int phy_mux_is_enabled(struct clk_hw *hw) > +{ > + struct clk_regmap *clkr = to_clk_regmap(hw); > + struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr); > + unsigned int val; > + > + regmap_read(clkr->regmap, phy_mux->reg, &val); > + val = FIELD_GET(PHY_MUX_MASK, val); As reported by the build bot, you need to include linux/bitfield.h explicitly for the FIELD macros. Johan
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 36789f5233ef..08594230c1c1 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -11,6 +11,7 @@ clk-qcom-y += clk-branch.o clk-qcom-y += clk-regmap-divider.o clk-qcom-y += clk-regmap-mux.o clk-qcom-y += clk-regmap-mux-div.o +clk-qcom-y += clk-regmap-phy-mux.o clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o clk-qcom-y += clk-hfpll.o clk-qcom-y += reset.o diff --git a/drivers/clk/qcom/clk-regmap-phy-mux.c b/drivers/clk/qcom/clk-regmap-phy-mux.c new file mode 100644 index 000000000000..a1adc075b471 --- /dev/null +++ b/drivers/clk/qcom/clk-regmap-phy-mux.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022, Linaro Ltd. + */ + +#include <linux/clk-provider.h> +#include <linux/bitops.h> +#include <linux/regmap.h> +#include <linux/export.h> + +#include "clk-regmap.h" +#include "clk-regmap-phy-mux.h" + +#define PHY_MUX_MASK GENMASK(1, 0) +#define PHY_MUX_PHY_SRC 0 +#define PHY_MUX_REF_SRC 2 + +static inline struct clk_regmap_phy_mux *to_clk_regmap_phy_mux(struct clk_regmap *clkr) +{ + return container_of(clkr, struct clk_regmap_phy_mux, clkr); +} + +static int phy_mux_is_enabled(struct clk_hw *hw) +{ + struct clk_regmap *clkr = to_clk_regmap(hw); + struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr); + unsigned int val; + + regmap_read(clkr->regmap, phy_mux->reg, &val); + val = FIELD_GET(PHY_MUX_MASK, val); + + WARN_ON(val != PHY_MUX_PHY_SRC && val != PHY_MUX_REF_SRC); + + return val == PHY_MUX_PHY_SRC; +} + +static int phy_mux_enable(struct clk_hw *hw) +{ + struct clk_regmap *clkr = to_clk_regmap(hw); + struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr); + + return regmap_update_bits(clkr->regmap, phy_mux->reg, + PHY_MUX_MASK, + FIELD_PREP(PHY_MUX_MASK, PHY_MUX_PHY_SRC)); +} + +static void phy_mux_disable(struct clk_hw *hw) +{ + struct clk_regmap *clkr = to_clk_regmap(hw); + struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr); + + regmap_update_bits(clkr->regmap, phy_mux->reg, + PHY_MUX_MASK, + FIELD_PREP(PHY_MUX_MASK, PHY_MUX_REF_SRC)); +} + +const struct clk_ops clk_regmap_phy_mux_ops = { + .enable = phy_mux_enable, + .disable = phy_mux_disable, + .is_enabled = phy_mux_is_enabled, +}; +EXPORT_SYMBOL_GPL(clk_regmap_phy_mux_ops); diff --git a/drivers/clk/qcom/clk-regmap-phy-mux.h b/drivers/clk/qcom/clk-regmap-phy-mux.h new file mode 100644 index 000000000000..614dd384695c --- /dev/null +++ b/drivers/clk/qcom/clk-regmap-phy-mux.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022, Linaro Ltd. + */ + +#ifndef __QCOM_CLK_REGMAP_PHY_MUX_H__ +#define __QCOM_CLK_REGMAP_PHY_MUX_H__ + +#include "clk-regmap.h" + +/* + * A clock implementation for PHY pipe and symbols clock muxes. + * + * If the clock is running off the from-PHY source, report it as enabled. + * Report it as disabled otherwise (if it uses reference source). + * + * This way the PHY will disable the pipe clock before turning off the GDSC, + * which in turn would lead to disabling corresponding pipe_clk_src (and thus + * it being parked to a safe, reference clock source). And vice versa, after + * enabling the GDSC the PHY will enable the pipe clock, which would cause + * pipe_clk_src to be switched from a safe source to the working one. + * + * For some platforms this should be used for the UFS symbol_clk_src clocks + * too. + */ +struct clk_regmap_phy_mux { + u32 reg; + struct clk_regmap clkr; +}; + +extern const struct clk_ops clk_regmap_phy_mux_ops; + +#endif