Re: [PATCH 2/6] crypto: jz4780-rng: Make ingenic CGU driver use syscon

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux