Hi PrasannaKumar, On Thursday, 17 August 2017 11:25:16 PDT PrasannaKumar Muralidharan wrote: > Ingenic PRNG registers are a part of the same hardware block as clock > and power stuff. It is handled by CGU driver. Ingenic M200 SoC has power > related registers that are after the PRNG registers. So instead of > shortening the register range use syscon interface to expose regmap. > This regmap is used by the PRNG driver. > > Signed-off-by: PrasannaKumar Muralidharan <prasannatsmkumar@xxxxxxxxx> > --- > arch/mips/boot/dts/ingenic/jz4740.dtsi | 14 +++++++---- > arch/mips/boot/dts/ingenic/jz4780.dtsi | 14 +++++++---- > drivers/clk/ingenic/cgu.c | 46 > +++++++++++++++++++++------------- drivers/clk/ingenic/cgu.h | > 9 +++++-- > drivers/clk/ingenic/jz4740-cgu.c | 30 +++++++++++----------- > drivers/clk/ingenic/jz4780-cgu.c | 10 ++++---- > 6 files changed, 73 insertions(+), 50 deletions(-) > > diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi > b/arch/mips/boot/dts/ingenic/jz4740.dtsi index 2ca7ce7..ada5e67 100644 > --- a/arch/mips/boot/dts/ingenic/jz4740.dtsi > +++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi > @@ -34,14 +34,18 @@ > clock-frequency = <32768>; > }; > > - cgu: jz4740-cgu@10000000 { > - compatible = "ingenic,jz4740-cgu"; > + cgu_registers { > + compatible = "simple-mfd", "syscon"; > reg = <0x10000000 0x100>; > > - clocks = <&ext>, <&rtc>; > - clock-names = "ext", "rtc"; > + cgu: jz4780-cgu@10000000 { > + compatible = "ingenic,jz4740-cgu"; > > - #clock-cells = <1>; > + clocks = <&ext>, <&rtc>; > + clock-names = "ext", "rtc"; > + > + #clock-cells = <1>; > + }; > }; > > rtc_dev: rtc@10003000 { > diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi > b/arch/mips/boot/dts/ingenic/jz4780.dtsi index 4853ef6..1301694 100644 > --- a/arch/mips/boot/dts/ingenic/jz4780.dtsi > +++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi > @@ -34,14 +34,18 @@ > clock-frequency = <32768>; > }; > > - cgu: jz4780-cgu@10000000 { > - compatible = "ingenic,jz4780-cgu"; > + cgu_registers { > + compatible = "simple-mfd", "syscon"; > reg = <0x10000000 0x100>; > > - clocks = <&ext>, <&rtc>; > - clock-names = "ext", "rtc"; > + cgu: jz4780-cgu@10000000 { > + compatible = "ingenic,jz4780-cgu"; > > - #clock-cells = <1>; > + clocks = <&ext>, <&rtc>; > + clock-names = "ext", "rtc"; > + > + #clock-cells = <1>; > + }; > }; > > pinctrl: pin-controller@10010000 { > diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c > index e8248f9..2f12c7c 100644 > --- a/drivers/clk/ingenic/cgu.c > +++ b/drivers/clk/ingenic/cgu.c > @@ -29,6 +29,18 @@ > > #define MHZ (1000 * 1000) > > +unsigned int cgu_readl(struct ingenic_cgu *cgu, unsigned int reg) > +{ > + unsigned int val = 0; > + regmap_read(cgu->regmap, reg, &val); > + return val; > +} > + > +int cgu_writel(struct ingenic_cgu *cgu, unsigned int val, unsigned int reg) > +{ > + return regmap_write(cgu->regmap, reg, val); > +} This is going to introduce a lot of overhead to the CGU driver - each regmap_read() or regmap_write() call will not only add overhead from the indirection but also acquire a lock which we really don't need. Could you instead perhaps: - Just add "syscon" as a second compatible string to the CGU node in the device tree, but otherwise leave it as-is without the extra cgu_registers node. - Have your RNG device node as a child of the CGU node, which should let it pick up the regmap via syscon_node_to_regmap() as it already does. - Leave the CGU driver as-is, so it can continue accessing memory directly rather than via regmap. Thanks, Paul > + > /** > * ingenic_cgu_gate_get() - get the value of clock gate register bit > * @cgu: reference to the CGU whose registers should be read > @@ -43,7 +55,7 @@ static inline bool > ingenic_cgu_gate_get(struct ingenic_cgu *cgu, > const struct ingenic_cgu_gate_info *info) > { > - return readl(cgu->base + info->reg) & BIT(info->bit); > + return cgu_readl(cgu, info->reg) & BIT(info->bit); > } > > /** > @@ -60,14 +72,14 @@ static inline void > ingenic_cgu_gate_set(struct ingenic_cgu *cgu, > const struct ingenic_cgu_gate_info *info, bool val) > { > - u32 clkgr = readl(cgu->base + info->reg); > + u32 clkgr = cgu_readl(cgu, info->reg); > > if (val) > clkgr |= BIT(info->bit); > else > clkgr &= ~BIT(info->bit); > > - writel(clkgr, cgu->base + info->reg); > + cgu_writel(cgu, clkgr, info->reg); > } > > /* > @@ -91,7 +103,7 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long > parent_rate) pll_info = &clk_info->pll; > > spin_lock_irqsave(&cgu->lock, flags); > - ctl = readl(cgu->base + pll_info->reg); > + ctl = cgu_readl(cgu, pll_info->reg); > spin_unlock_irqrestore(&cgu->lock, flags); > > m = (ctl >> pll_info->m_shift) & GENMASK(pll_info->m_bits - 1, 0); > @@ -190,7 +202,7 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long > req_rate, clk_info->name, req_rate, rate); > > spin_lock_irqsave(&cgu->lock, flags); > - ctl = readl(cgu->base + pll_info->reg); > + ctl = cgu_readl(cgu, pll_info->reg); > > ctl &= ~(GENMASK(pll_info->m_bits - 1, 0) << pll_info->m_shift); > ctl |= (m - pll_info->m_offset) << pll_info->m_shift; > @@ -204,11 +216,11 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long > req_rate, ctl &= ~BIT(pll_info->bypass_bit); > ctl |= BIT(pll_info->enable_bit); > > - writel(ctl, cgu->base + pll_info->reg); > + cgu_writel(cgu, ctl, pll_info->reg); > > /* wait for the PLL to stabilise */ > for (i = 0; i < timeout; i++) { > - ctl = readl(cgu->base + pll_info->reg); > + ctl = cgu_readl(cgu, pll_info->reg); > if (ctl & BIT(pll_info->stable_bit)) > break; > mdelay(1); > @@ -243,7 +255,7 @@ static u8 ingenic_clk_get_parent(struct clk_hw *hw) > clk_info = &cgu->clock_info[ingenic_clk->idx]; > > if (clk_info->type & CGU_CLK_MUX) { > - reg = readl(cgu->base + clk_info->mux.reg); > + reg = cgu_readl(cgu, clk_info->mux.reg); > hw_idx = (reg >> clk_info->mux.shift) & > GENMASK(clk_info->mux.bits - 1, 0); > > @@ -297,10 +309,10 @@ static int ingenic_clk_set_parent(struct clk_hw *hw, > u8 idx) spin_lock_irqsave(&cgu->lock, flags); > > /* write the register */ > - reg = readl(cgu->base + clk_info->mux.reg); > + reg = cgu_readl(cgu, clk_info->mux.reg); > reg &= ~mask; > reg |= hw_idx << clk_info->mux.shift; > - writel(reg, cgu->base + clk_info->mux.reg); > + cgu_writel(cgu, reg, clk_info->mux.reg); > > spin_unlock_irqrestore(&cgu->lock, flags); > return 0; > @@ -321,7 +333,7 @@ ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long > parent_rate) clk_info = &cgu->clock_info[ingenic_clk->idx]; > > if (clk_info->type & CGU_CLK_DIV) { > - div_reg = readl(cgu->base + clk_info->div.reg); > + div_reg = cgu_readl(cgu, clk_info->div.reg); > div = (div_reg >> clk_info->div.shift) & > GENMASK(clk_info->div.bits - 1, 0); > div += 1; > @@ -399,7 +411,7 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long > req_rate, return -EINVAL; > > spin_lock_irqsave(&cgu->lock, flags); > - reg = readl(cgu->base + clk_info->div.reg); > + reg = cgu_readl(cgu, clk_info->div.reg); > > /* update the divide */ > mask = GENMASK(clk_info->div.bits - 1, 0); > @@ -415,12 +427,12 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long > req_rate, reg |= BIT(clk_info->div.ce_bit); > > /* update the hardware */ > - writel(reg, cgu->base + clk_info->div.reg); > + cgu_writel(cgu, reg, clk_info->div.reg); > > /* wait for the change to take effect */ > if (clk_info->div.busy_bit != -1) { > for (i = 0; i < timeout; i++) { > - reg = readl(cgu->base + clk_info->div.reg); > + reg = cgu_readl(cgu, clk_info->div.reg); > if (!(reg & BIT(clk_info->div.busy_bit))) > break; > mdelay(1); > @@ -661,11 +673,9 @@ ingenic_cgu_new(const struct ingenic_cgu_clk_info > *clock_info, if (!cgu) > goto err_out; > > - cgu->base = of_iomap(np, 0); > - if (!cgu->base) { > - pr_err("%s: failed to map CGU registers\n", __func__); > + cgu->regmap = syscon_node_to_regmap(np->parent); > + if (cgu->regmap == NULL) > goto err_out_free; > - } > > cgu->np = np; > cgu->clock_info = clock_info; > diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h > index 09700b2..86fd5b0 100644 > --- a/drivers/clk/ingenic/cgu.h > +++ b/drivers/clk/ingenic/cgu.h > @@ -19,7 +19,9 @@ > #define __DRIVERS_CLK_INGENIC_CGU_H__ > > #include <linux/bitops.h> > +#include <linux/mfd/syscon.h> > #include <linux/of.h> > +#include <linux/regmap.h> > #include <linux/spinlock.h> > > /** > @@ -171,14 +173,14 @@ struct ingenic_cgu_clk_info { > /** > * struct ingenic_cgu - data about the CGU > * @np: the device tree node that caused the CGU to be probed > - * @base: the ioremap'ed base address of the CGU registers > + * @regmap: the regmap object used to access the CGU registers > * @clock_info: an array containing information about implemented clocks > * @clocks: used to provide clocks to DT, allows lookup of struct clk* > * @lock: lock to be held whilst manipulating CGU registers > */ > struct ingenic_cgu { > struct device_node *np; > - void __iomem *base; > + struct regmap *regmap; > > const struct ingenic_cgu_clk_info *clock_info; > struct clk_onecell_data clocks; > @@ -186,6 +188,9 @@ struct ingenic_cgu { > spinlock_t lock; > }; > > +unsigned int cgu_readl(struct ingenic_cgu *cgu, unsigned int reg); > +int cgu_writel(struct ingenic_cgu *cgu, unsigned int val, unsigned int > reg); + > /** > * struct ingenic_clk - private data for a clock > * @hw: see Documentation/clk.txt > diff --git a/drivers/clk/ingenic/jz4740-cgu.c > b/drivers/clk/ingenic/jz4740-cgu.c index 510fe7e..3003afb 100644 > --- a/drivers/clk/ingenic/jz4740-cgu.c > +++ b/drivers/clk/ingenic/jz4740-cgu.c > @@ -232,7 +232,7 @@ CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", > jz4740_cgu_init); > > void jz4740_clock_set_wait_mode(enum jz4740_wait_mode mode) > { > - uint32_t lcr = readl(cgu->base + CGU_REG_LCR); > + uint32_t lcr = cgu_readl(cgu, CGU_REG_LCR); > > switch (mode) { > case JZ4740_WAIT_MODE_IDLE: > @@ -244,24 +244,24 @@ void jz4740_clock_set_wait_mode(enum jz4740_wait_mode > mode) break; > } > > - writel(lcr, cgu->base + CGU_REG_LCR); > + cgu_writel(cgu, lcr, CGU_REG_LCR); > } > > void jz4740_clock_udc_disable_auto_suspend(void) > { > - uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR); > + uint32_t clkgr = cgu_readl(cgu, CGU_REG_CLKGR); > > clkgr &= ~CLKGR_UDC; > - writel(clkgr, cgu->base + CGU_REG_CLKGR); > + cgu_writel(cgu, clkgr, CGU_REG_CLKGR); > } > EXPORT_SYMBOL_GPL(jz4740_clock_udc_disable_auto_suspend); > > void jz4740_clock_udc_enable_auto_suspend(void) > { > - uint32_t clkgr = readl(cgu->base + CGU_REG_CLKGR); > + uint32_t clkgr = cgu_readl(cgu, CGU_REG_CLKGR); > > clkgr |= CLKGR_UDC; > - writel(clkgr, cgu->base + CGU_REG_CLKGR); > + cgu_writel(cgu, clkgr, CGU_REG_CLKGR); > } > EXPORT_SYMBOL_GPL(jz4740_clock_udc_enable_auto_suspend); > > @@ -273,31 +273,31 @@ void jz4740_clock_suspend(void) > { > uint32_t clkgr, cppcr; > > - clkgr = readl(cgu->base + CGU_REG_CLKGR); > + clkgr = cgu_readl(cgu, CGU_REG_CLKGR); > clkgr |= JZ_CLOCK_GATE_TCU | JZ_CLOCK_GATE_DMAC | JZ_CLOCK_GATE_UART0; > - writel(clkgr, cgu->base + CGU_REG_CLKGR); > + cgu_writel(cgu, clkgr, CGU_REG_CLKGR); > > - cppcr = readl(cgu->base + CGU_REG_CPPCR); > + cppcr = cgu_readl(cgu, CGU_REG_CPPCR); > cppcr &= ~BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit); > - writel(cppcr, cgu->base + CGU_REG_CPPCR); > + cgu_writel(cgu, cppcr, CGU_REG_CPPCR); > } > > void jz4740_clock_resume(void) > { > uint32_t clkgr, cppcr, stable; > > - cppcr = readl(cgu->base + CGU_REG_CPPCR); > + cppcr = cgu_readl(cgu, CGU_REG_CPPCR); > cppcr |= BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.enable_bit); > - writel(cppcr, cgu->base + CGU_REG_CPPCR); > + cgu_writel(cgu, cppcr, CGU_REG_CPPCR); > > stable = BIT(jz4740_cgu_clocks[JZ4740_CLK_PLL].pll.stable_bit); > do { > - cppcr = readl(cgu->base + CGU_REG_CPPCR); > + cppcr = cgu_readl(cgu, CGU_REG_CPPCR); > } while (!(cppcr & stable)); > > - clkgr = readl(cgu->base + CGU_REG_CLKGR); > + clkgr = cgu_readl(cgu, CGU_REG_CLKGR); > clkgr &= ~JZ_CLOCK_GATE_TCU; > clkgr &= ~JZ_CLOCK_GATE_DMAC; > clkgr &= ~JZ_CLOCK_GATE_UART0; > - writel(clkgr, cgu->base + CGU_REG_CLKGR); > + cgu_writel(cgu, clkgr, CGU_REG_CLKGR); > } > diff --git a/drivers/clk/ingenic/jz4780-cgu.c > b/drivers/clk/ingenic/jz4780-cgu.c index b35d6d9..8f83433 100644 > --- a/drivers/clk/ingenic/jz4780-cgu.c > +++ b/drivers/clk/ingenic/jz4780-cgu.c > @@ -113,11 +113,11 @@ static int jz4780_otg_phy_set_parent(struct clk_hw > *hw, u8 idx) > > spin_lock_irqsave(&cgu->lock, flags); > > - usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); > + usbpcr1 = cgu_readl(cgu, CGU_REG_USBPCR1); > usbpcr1 &= ~USBPCR1_REFCLKSEL_MASK; > /* we only use CLKCORE */ > usbpcr1 |= USBPCR1_REFCLKSEL_CORE; > - writel(usbpcr1, cgu->base + CGU_REG_USBPCR1); > + cgu_writel(cgu, usbpcr1, CGU_REG_USBPCR1); > > spin_unlock_irqrestore(&cgu->lock, flags); > return 0; > @@ -129,7 +129,7 @@ static unsigned long jz4780_otg_phy_recalc_rate(struct > clk_hw *hw, u32 usbpcr1; > unsigned refclk_div; > > - usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); > + usbpcr1 = cgu_readl(cgu, CGU_REG_USBPCR1); > refclk_div = usbpcr1 & USBPCR1_REFCLKDIV_MASK; > > switch (refclk_div) { > @@ -194,10 +194,10 @@ static int jz4780_otg_phy_set_rate(struct clk_hw *hw, > unsigned long req_rate, > > spin_lock_irqsave(&cgu->lock, flags); > > - usbpcr1 = readl(cgu->base + CGU_REG_USBPCR1); > + usbpcr1 = cgu_readl(cgu, CGU_REG_USBPCR1); > usbpcr1 &= ~USBPCR1_REFCLKDIV_MASK; > usbpcr1 |= div_bits; > - writel(usbpcr1, cgu->base + CGU_REG_USBPCR1); > + cgu_writel(cgu, usbpcr1, CGU_REG_USBPCR1); > > spin_unlock_irqrestore(&cgu->lock, flags); > return 0;
Attachment:
signature.asc
Description: This is a digitally signed message part.