Message ID | 20240226100807.1095607-4-quic_varada@quicinc.com |
---|---|
State | Changes Requested |
Delegated to: | Caleb Connolly |
Headers | show |
Series | Add initial support for IPQ9574 based boards | expand |
On 26/02/2024 10:08, Varadarajan Narayanan wrote: > The BCR registers in IPQ9574 are different and have > different fields. Add function to program these > clocks accordingly. > > Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com> > --- > > drivers/clk/qcom/clock-qcom.c | 32 ++++++++++++++++++++++++++++++++ > drivers/clk/qcom/clock-qcom.h | 8 ++++++++ > 2 files changed, 40 insertions(+) > > diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c > index 7c683e5192..fe60490186 100644 > --- a/drivers/clk/qcom/clock-qcom.c > +++ b/drivers/clk/qcom/clock-qcom.c > @@ -156,6 +156,38 @@ void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, > clk_bcr_update(base + regs->cmd_rcgr); > } > > +#define CFG_MASK 0x3FFF Please define this in terms of the individual register fields. > + > +#define CFG_DIVIDER_MASK 0x1F This is just CFG_SRC_DIV_MASK, please use that instead. > + > +/* root set rate for clocks without the MND divider */ Please adjust this comment to explain what's different about v2 and where it's relevant (is it just IPQ SoCs? Or "some IPQ SoCs"?). > +void clk_rcg_set_rate_v2(phys_addr_t base, const struct bcr_regs_v2 *regs, > + int div, int cdiv, int source) As far as I can tell, this is like the RCG clocks in that the cfg register is always cmd + 4 and div_cdivr is always cfg + 4. In this case let's simplify this and save a whole lot of lines by just passing in the cmd register address and using offsets for the others. There's no need to specify all these manually. See https://lore.kernel.org/u-boot/20240131-b4-qcom-livetree-v1-4-4071c0787db0@linaro.org/ > +{ > + u32 cfg; > + > + /* setup src select and divider */ > + cfg = readl(base + regs->cfg_rcgr); > + cfg &= ~CFG_MASK; > + cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */ > + > + /* > + * Set the divider; HW permits fraction dividers (+0.5), but > + * for simplicity, we will support integers only > + */ > + if (div) > + cfg |= div & CFG_DIVIDER_MASK; > + > + writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */ > + > + /* Write the common divider clock configuration */ > + if (regs->div_cdivr) > + writel(cdiv, base + regs->div_cdivr); > + > + /* Inform h/w to start using the new config. */ > + clk_bcr_update(base + regs->cmd_rcgr); > +} > + > const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate) > { > if (!f) > diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h > index 01088c1901..95f6162ea4 100644 > --- a/drivers/clk/qcom/clock-qcom.h > +++ b/drivers/clk/qcom/clock-qcom.h > @@ -32,6 +32,12 @@ struct bcr_regs { > uintptr_t D; > }; > > +struct bcr_regs_v2 { > + uintptr_t cfg_rcgr; > + uintptr_t cmd_rcgr; > + uintptr_t div_cdivr; > +};> + > struct freq_tbl { > uint freq; > uint src; > @@ -86,6 +92,8 @@ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, > int div, int m, int n, int source, u8 mnd_width); > void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, > int source); > +void clk_rcg_set_rate_v2(phys_addr_t base, const struct bcr_regs_v2 *regs, > + int div, int cdiv, int source); > > static inline void qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id) > {
diff --git a/drivers/clk/qcom/clock-qcom.c b/drivers/clk/qcom/clock-qcom.c index 7c683e5192..fe60490186 100644 --- a/drivers/clk/qcom/clock-qcom.c +++ b/drivers/clk/qcom/clock-qcom.c @@ -156,6 +156,38 @@ void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, clk_bcr_update(base + regs->cmd_rcgr); } +#define CFG_MASK 0x3FFF + +#define CFG_DIVIDER_MASK 0x1F + +/* root set rate for clocks without the MND divider */ +void clk_rcg_set_rate_v2(phys_addr_t base, const struct bcr_regs_v2 *regs, + int div, int cdiv, int source) +{ + u32 cfg; + + /* setup src select and divider */ + cfg = readl(base + regs->cfg_rcgr); + cfg &= ~CFG_MASK; + cfg |= source & CFG_CLK_SRC_MASK; /* Select clock source */ + + /* + * Set the divider; HW permits fraction dividers (+0.5), but + * for simplicity, we will support integers only + */ + if (div) + cfg |= div & CFG_DIVIDER_MASK; + + writel(cfg, base + regs->cfg_rcgr); /* Write new clock configuration */ + + /* Write the common divider clock configuration */ + if (regs->div_cdivr) + writel(cdiv, base + regs->div_cdivr); + + /* Inform h/w to start using the new config. */ + clk_bcr_update(base + regs->cmd_rcgr); +} + const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate) { if (!f) diff --git a/drivers/clk/qcom/clock-qcom.h b/drivers/clk/qcom/clock-qcom.h index 01088c1901..95f6162ea4 100644 --- a/drivers/clk/qcom/clock-qcom.h +++ b/drivers/clk/qcom/clock-qcom.h @@ -32,6 +32,12 @@ struct bcr_regs { uintptr_t D; }; +struct bcr_regs_v2 { + uintptr_t cfg_rcgr; + uintptr_t cmd_rcgr; + uintptr_t div_cdivr; +}; + struct freq_tbl { uint freq; uint src; @@ -86,6 +92,8 @@ void clk_rcg_set_rate_mnd(phys_addr_t base, const struct bcr_regs *regs, int div, int m, int n, int source, u8 mnd_width); void clk_rcg_set_rate(phys_addr_t base, const struct bcr_regs *regs, int div, int source); +void clk_rcg_set_rate_v2(phys_addr_t base, const struct bcr_regs_v2 *regs, + int div, int cdiv, int source); static inline void qcom_gate_clk_en(const struct msm_clk_priv *priv, unsigned long id) {
The BCR registers in IPQ9574 are different and have different fields. Add function to program these clocks accordingly. Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com> --- drivers/clk/qcom/clock-qcom.c | 32 ++++++++++++++++++++++++++++++++ drivers/clk/qcom/clock-qcom.h | 8 ++++++++ 2 files changed, 40 insertions(+)