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 <[email protected]> > --- > 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;
signature.asc
Description: This is a digitally signed message part.
