Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] ARM: gic: add irq_domain support
From: Grant Likely @ 2011-09-30  0:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E84DCF4.4020904@gmail.com>

On Thu, Sep 29, 2011 at 04:02:44PM -0500, Rob Herring wrote:
> On 09/29/2011 12:15 PM, Grant Likely wrote:
> > On Wed, Sep 28, 2011 at 10:53:55PM -0500, Rob Herring wrote:
> >> From: Rob Herring <rob.herring@calxeda.com>
> >>
> >> Convert the gic interrupt controller to use irq domains in preparation
> >> for device-tree binding and MULTI_IRQ. This allows for translation between
> >> GIC interrupt IDs and Linux irq numbers.
> >>
> >> The meaning of irq_offset has changed. It now is just the number of skipped
> >> GIC interrupt IDs for the controller. It will be 16 for primary GIC and 32
> >> for secondary GICs.
> > 
> > [...]
> > 
> >>  /*
> >> @@ -81,7 +82,7 @@ static inline unsigned int gic_irq(struct irq_data *d)
> >>   */
> >>  static void gic_mask_irq(struct irq_data *d)
> >>  {
> >> -	u32 mask = 1 << (d->irq % 32);
> >> +	u32 mask = 1 << (gic_irq(d) % 32);
> > 
> > This can probably change simply to d->hwirq if irq_offset is
> > eliminated as I describe below.
> > 
> >>  void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
> >>  	void __iomem *dist_base, void __iomem *cpu_base)
> >>  {
> >>  	struct gic_chip_data *gic;
> >> +	struct irq_domain *domain;
> >> +	int gic_irqs;
> >>  
> >>  	BUG_ON(gic_nr >= MAX_GIC_NR);
> >>  
> >>  	gic = &gic_data[gic_nr];
> >> +	domain = &gic->domain;
> >>  	gic->dist_base = dist_base;
> >>  	gic->cpu_base = cpu_base;
> >> -	gic->irq_offset = (irq_start - 1) & ~31;
> >>  
> >> -	if (gic_nr == 0)
> >> +	/*
> >> +	 * For primary GICs, skip over SGIs.
> >> +	 * For secondary GICs, skip over PPIs, too.
> >> +	 */
> >> +	if (gic_nr == 0) {
> >>  		gic_cpu_base_addr = cpu_base;
> >> +		gic->irq_offset = 16;
> >> +		irq_start = (irq_start & ~31) + 16;
> > 
> > With the switch to irq_domain, there should no longer be any need for
> > a ~31 mask on the irq_start number.  Yes, you'll want to make sure
> > that it doesn't allocate below irq 16, but the driver should
> > completely use the irq_domain to manage the mapping from linux-irq
> > number to hwirq number.  The ~31 mask appears to have been an
> > optimization to quickly calculate hwirq number from the linux one, but
> > that value is now found in irq_data->hwirq.
> 
> I started out exactly this way removing irq_offset. The problem is the
> core irq domain code assumes that hwirq starts at 0, but for the gic it
> starts at 16 or 32.
> 
> It could be fixed in the domain core, but that would effectively mean
> moving irq_offset into the core.

Fix irq_domain.  If it cannot handle this trivial case, then it won't
be able to handle the complex powerpc use cases.

g.

^ permalink raw reply

* [PATCH] ARM: realview-eb11mp: fix map_desc alignment
From: Rob Herring @ 2011-09-30  0:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4E84E0CA.2050905@gmail.com>

From: Rob Herring <rob.herring@calxeda.com>

REALVIEW_EB11MP_GIC_CPU_BASE is not 4KB aligned which causes an
overlapping mapping. Use REALVIEW_EB11MP_SCU_BASE instead which is
aligned.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
---
Nico,

Here's another one. I visually checked the remaining Realview platforms and
think they are fine.

Rob

 arch/arm/mach-realview/realview_eb.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 026c66a..a9874e1 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -91,8 +91,8 @@ static struct map_desc realview_eb_io_desc[] __initdata = {
 
 static struct map_desc realview_eb11mp_io_desc[] __initdata = {
 	{
-		.virtual	= IO_ADDRESS(REALVIEW_EB11MP_GIC_CPU_BASE),
-		.pfn		= __phys_to_pfn(REALVIEW_EB11MP_GIC_CPU_BASE),
+		.virtual	= IO_ADDRESS(REALVIEW_EB11MP_SCU_BASE),
+		.pfn		= __phys_to_pfn(REALVIEW_EB11MP_SCU_BASE),
 		.length		= SZ_4K,
 		.type		= MT_DEVICE,
 	}, {
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH] OMAP2+: clock: use clock's recalc in DPLL handling
From: Mike Turquette @ 2011-09-30  0:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAJOA=zPq__48SbsKeFHaQ_+J0YQYLLXBP67g2JGXknhWj7PNOA@mail.gmail.com>

Not all DPLLs are identical; some require special consideration such as
OMAP4's ABE DPLL, which can have an additional 4x multiplier added to
it's clock rate based on programming the REGM4XEN bit in it's CLKMODE
register.

Unfortunately the clock framework makes a few assumptions that all DPLLs
can have their rates calculated the same way which has led to incorrect
rates for OMAP4's DPLL_ABE in some cases.  This patch fixes the same by
replacing explicit calls to omap2_dpll_get_rate with clk->recalc if
.recalc is populated for a clock.  If .recalc is NULL then fall back to
omap2_dpll_get_rate.

Reported-by: Misael Lopez Cruz <misael.lopez@ti.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
---
 arch/arm/mach-omap2/dpll3xxx.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index f77022b..193868d 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -390,7 +390,8 @@ int omap3_noncore_dpll_enable(struct clk *clk)
 	 * propagating?
 	 */
 	if (!r)
-		clk->rate = omap2_get_dpll_rate(clk);
+		clk->rate = (clk->recalc) ? clk->recalc(clk) :
+			omap2_get_dpll_rate(clk);
 
 	return r;
 }
@@ -435,7 +436,8 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 	if (!dd)
 		return -EINVAL;
 
-	if (rate == omap2_get_dpll_rate(clk))
+	if (rate == ((clk->recalc) ? clk->recalc(clk) :
+				omap2_get_dpll_rate(clk)))
 		return 0;
 
 	/*
-- 
1.7.4.1

^ permalink raw reply related

* [PATCH 2/9] regulator: helper routine to extract regulator_init_data
From: Grant Likely @ 2011-09-30  1:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110927121003.GB4289@opensource.wolfsonmicro.com>

On Tue, Sep 27, 2011 at 01:10:04PM +0100, Mark Brown wrote:
> On Tue, Sep 27, 2011 at 03:42:45PM +0530, Rajendra Nayak wrote:
> 
> > +	init_data = devm_kzalloc(dev, sizeof(struct regulator_init_data),
> > +						 GFP_KERNEL);
> > +	if (!init_data)
> > +		return NULL; /* Out of memory? */
> 
> This means that the init data will be kept around for the entire
> lifetime of the device rather than being discarded.
> 
> > +	init_data->supply_regulator = (char *)of_get_property(dev->of_node,
> > +						"regulator-supplies", NULL);
> 
> I'd expect that in the device tree world the supply regulator would
> reference the node for that regulator.

Yes, I would expect the same.

^ permalink raw reply

* [PATCH] OMAP2+: clock: use clock's recalc in DPLL handling
From: Paul Walmsley @ 2011-09-30  1:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317343888-30892-1-git-send-email-mturquette@ti.com>

Hi

On Thu, 29 Sep 2011, Mike Turquette wrote:

> Not all DPLLs are identical; some require special consideration such as
> OMAP4's ABE DPLL, which can have an additional 4x multiplier added to
> it's clock rate based on programming the REGM4XEN bit in it's CLKMODE
> register.
> 
> Unfortunately the clock framework makes a few assumptions that all DPLLs
> can have their rates calculated the same way which has led to incorrect
> rates for OMAP4's DPLL_ABE in some cases.  This patch fixes the same by
> replacing explicit calls to omap2_dpll_get_rate with clk->recalc if
> .recalc is populated for a clock.  If .recalc is NULL then fall back to
> omap2_dpll_get_rate.
> 
> Reported-by: Misael Lopez Cruz <misael.lopez@ti.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>

The conditional in the second hunk of this patch has been simplified for 
readability.  Updated patch below.  Please let me know if I screwed 
something up.  Otherwise, queued for 3.2 fixes.

thanks


- Paul

From: Mike Turquette <mturquette@ti.com>
Date: Thu, 29 Sep 2011 17:51:28 -0700
Subject: [PATCH] ARM: OMAP2+: clock: use clock's recalc in DPLL handling

Not all DPLLs are identical; some require special consideration such as
OMAP4's ABE DPLL, which can have an additional 4x multiplier added to
it's clock rate based on programming the REGM4XEN bit in it's CLKMODE
register.

Unfortunately the clock framework makes a few assumptions that all DPLLs
can have their rates calculated the same way which has led to incorrect
rates for OMAP4's DPLL_ABE in some cases.  This patch fixes the same by
replacing explicit calls to omap2_dpll_get_rate with clk->recalc if
.recalc is populated for a clock.  If .recalc is NULL then fall back to
omap2_dpll_get_rate.

Reported-by: Misael Lopez Cruz <misael.lopez@ti.com>
Signed-off-by: Mike Turquette <mturquette@ti.com>
[paul at pwsan.com: simplified conditional]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
---
 arch/arm/mach-omap2/dpll3xxx.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
index f77022b..fe4533f 100644
--- a/arch/arm/mach-omap2/dpll3xxx.c
+++ b/arch/arm/mach-omap2/dpll3xxx.c
@@ -390,7 +390,8 @@ int omap3_noncore_dpll_enable(struct clk *clk)
 	 * propagating?
 	 */
 	if (!r)
-		clk->rate = omap2_get_dpll_rate(clk);
+		clk->rate = (clk->recalc) ? clk->recalc(clk) :
+			omap2_get_dpll_rate(clk);
 
 	return r;
 }
@@ -425,6 +426,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 {
 	struct clk *new_parent = NULL;
 	u16 freqsel = 0;
+	unsigned long hw_rate;
 	struct dpll_data *dd;
 	int ret;
 
@@ -435,7 +437,8 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 	if (!dd)
 		return -EINVAL;
 
-	if (rate == omap2_get_dpll_rate(clk))
+	hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk);
+	if (rate == hw_rate)
 		return 0;
 
 	/*
-- 
1.7.6.3

^ permalink raw reply related

* [PATCH 5/9] regulator: helper routine to extract fixed_voltage_config
From: Grant Likely @ 2011-09-30  1:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-6-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:48PM +0530, Rajendra Nayak wrote:
> The helper routine of_get_fixed_voltage_config() extracts
> fixed_voltage_config structure contents from device tree.
> 
> Also add documenation for additional bindings for fixed
> regulators that can be passed through dt.
> 
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> ---
>  .../bindings/regulator/fixed-regulator.txt         |   24 +++++++++++++
>  drivers/regulator/fixed.c                          |   36 ++++++++++++++++++++
>  include/linux/regulator/fixed.h                    |    6 ++--
>  3 files changed, 63 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/regulator/fixed-regulator.txt
> 
> diff --git a/Documentation/devicetree/bindings/regulator/fixed-regulator.txt b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt
> new file mode 100644
> index 0000000..a204cbd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/regulator/fixed-regulator.txt
> @@ -0,0 +1,24 @@
> +Fixed Voltage regulators
> +
> +Required properties:
> +- compatible: Must be "regulator-fixed";
> +
> +Optional properties:
> +- regulator-fixed-supply: Name of the regulator supply
> +- regulator-fixed-microvolts: Output voltage of regulator
> +- regulator-fixed-gpio: gpio to use for enable control
> +- regulator-fixed-startup-delay: startup time in microseconds
> +- regulator-fixed-enable-high: Polarity of enable GPIO, 1 = Active High, 0 = Active low
> +- regulator-fixed-enabled-at-boot: 1 = yes, 0 = no
> +
> +Example:
> +
> +	abc: fixedregulator at 0 {
> +		compatible = "regulator-fixed";
> +		regulator-fixed-supply = "fixed-supply";
> +		regulator-fixed-microvolts = <1800000>;
> +		regulator-fixed-gpio = <43>;
> +		regulator-fixed-startup-delay = <70000>;
> +		regulator-fixed-enable-high;
> +		regulator-fixed-enabled-at-boot;
> +	};
> diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
> index 2fe9d99..c09f791 100644
> --- a/drivers/regulator/fixed.c
> +++ b/drivers/regulator/fixed.c
> @@ -26,6 +26,8 @@
>  #include <linux/gpio.h>
>  #include <linux/delay.h>
>  #include <linux/slab.h>
> +#include <linux/of.h>
> +#include <linux/regulator/of_regulator.h>
>  
>  struct fixed_voltage_data {
>  	struct regulator_desc desc;
> @@ -37,6 +39,40 @@ struct fixed_voltage_data {
>  	bool is_enabled;
>  };
>  
> +
> +/**
> + * of_get_fixed_voltage_config - extract fixed_voltage_config structure info
> + * @dev: device requesting for fixed_voltage_config
> + *
> + * Populates fixed_voltage_config structure by extracting data from device
> + * tree node, returns a pointer to the populated structure of NULL if memory
> + * alloc fails.
> + */
> +struct fixed_voltage_config *of_get_fixed_voltage_config(struct device *dev)
> +{
> +	struct fixed_voltage_config *config;
> +	struct device_node *np = dev->of_node;
> +
> +	config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config), GFP_KERNEL);

Nit: config = devm_kzalloc(dev, *config, GFP_KERNEL);

g.

^ permalink raw reply

* [PATCH] OMAP2+: clock: use clock's recalc in DPLL handling
From: Turquette, Mike @ 2011-09-30  1:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1109291925120.26728@utopia.booyaka.com>

On Thu, Sep 29, 2011 at 6:26 PM, Paul Walmsley <paul@pwsan.com> wrote:
> Hi
>
> On Thu, 29 Sep 2011, Mike Turquette wrote:
>
>> Not all DPLLs are identical; some require special consideration such as
>> OMAP4's ABE DPLL, which can have an additional 4x multiplier added to
>> it's clock rate based on programming the REGM4XEN bit in it's CLKMODE
>> register.
>>
>> Unfortunately the clock framework makes a few assumptions that all DPLLs
>> can have their rates calculated the same way which has led to incorrect
>> rates for OMAP4's DPLL_ABE in some cases. ?This patch fixes the same by
>> replacing explicit calls to omap2_dpll_get_rate with clk->recalc if
>> .recalc is populated for a clock. ?If .recalc is NULL then fall back to
>> omap2_dpll_get_rate.
>>
>> Reported-by: Misael Lopez Cruz <misael.lopez@ti.com>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>
> The conditional in the second hunk of this patch has been simplified for
> readability. ?Updated patch below. ?Please let me know if I screwed
> something up. ?Otherwise, queued for 3.2 fixes.

Looks good to me.

Regards,
Mike

> thanks
>
>
> - Paul
>
> From: Mike Turquette <mturquette@ti.com>
> Date: Thu, 29 Sep 2011 17:51:28 -0700
> Subject: [PATCH] ARM: OMAP2+: clock: use clock's recalc in DPLL handling
>
> Not all DPLLs are identical; some require special consideration such as
> OMAP4's ABE DPLL, which can have an additional 4x multiplier added to
> it's clock rate based on programming the REGM4XEN bit in it's CLKMODE
> register.
>
> Unfortunately the clock framework makes a few assumptions that all DPLLs
> can have their rates calculated the same way which has led to incorrect
> rates for OMAP4's DPLL_ABE in some cases. ?This patch fixes the same by
> replacing explicit calls to omap2_dpll_get_rate with clk->recalc if
> .recalc is populated for a clock. ?If .recalc is NULL then fall back to
> omap2_dpll_get_rate.
>
> Reported-by: Misael Lopez Cruz <misael.lopez@ti.com>
> Signed-off-by: Mike Turquette <mturquette@ti.com>
> [paul at pwsan.com: simplified conditional]
> Signed-off-by: Paul Walmsley <paul@pwsan.com>
> ---
> ?arch/arm/mach-omap2/dpll3xxx.c | ? ?7 +++++--
> ?1 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-omap2/dpll3xxx.c b/arch/arm/mach-omap2/dpll3xxx.c
> index f77022b..fe4533f 100644
> --- a/arch/arm/mach-omap2/dpll3xxx.c
> +++ b/arch/arm/mach-omap2/dpll3xxx.c
> @@ -390,7 +390,8 @@ int omap3_noncore_dpll_enable(struct clk *clk)
> ? ? ? ? * propagating?
> ? ? ? ? */
> ? ? ? ?if (!r)
> - ? ? ? ? ? ? ? clk->rate = omap2_get_dpll_rate(clk);
> + ? ? ? ? ? ? ? clk->rate = (clk->recalc) ? clk->recalc(clk) :
> + ? ? ? ? ? ? ? ? ? ? ? omap2_get_dpll_rate(clk);
>
> ? ? ? ?return r;
> ?}
> @@ -425,6 +426,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
> ?{
> ? ? ? ?struct clk *new_parent = NULL;
> ? ? ? ?u16 freqsel = 0;
> + ? ? ? unsigned long hw_rate;
> ? ? ? ?struct dpll_data *dd;
> ? ? ? ?int ret;
>
> @@ -435,7 +437,8 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
> ? ? ? ?if (!dd)
> ? ? ? ? ? ? ? ?return -EINVAL;
>
> - ? ? ? if (rate == omap2_get_dpll_rate(clk))
> + ? ? ? hw_rate = (clk->recalc) ? clk->recalc(clk) : omap2_get_dpll_rate(clk);
> + ? ? ? if (rate == hw_rate)
> ? ? ? ? ? ? ? ?return 0;
>
> ? ? ? ?/*
> --
> 1.7.6.3
>
>

^ permalink raw reply

* [PATCH 6/9] regulator: make fixed regulator driver extract data from dt
From: Grant Likely @ 2011-09-30  1:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-7-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:49PM +0530, Rajendra Nayak wrote:
> Modify the fixed regulator driver to extract fixed_voltage_config from
> device tree when passed, instead of getting it through platform_data
> structures (on non-DT builds)
> 
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> ---
>  drivers/regulator/fixed.c |   18 +++++++++++++++++-
>  1 files changed, 17 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
> index c09f791..0a9a10d 100644
> --- a/drivers/regulator/fixed.c
> +++ b/drivers/regulator/fixed.c
> @@ -140,10 +140,15 @@ static struct regulator_ops fixed_voltage_ops = {
>  
>  static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
>  {
> -	struct fixed_voltage_config *config = pdev->dev.platform_data;
> +	struct fixed_voltage_config *config;

This line doesn't actually need to change; just override it below if
the of_node is present.

>  	struct fixed_voltage_data *drvdata;
>  	int ret;
>  
> +	if (pdev->dev.of_node)
> +		config = of_get_fixed_voltage_config(&pdev->dev);
> +	else
> +		config = pdev->dev.platform_data;
> +
>  	drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL);
>  	if (drvdata == NULL) {
>  		dev_err(&pdev->dev, "Failed to allocate device data\n");
> @@ -252,12 +257,23 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
>  	return 0;
>  }
>  
> +#if defined(CONFIG_OF)
> +static const struct of_device_id fixed_of_match[] __devinitconst = {
> +	{ .compatible = "regulator-fixed", },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, fixed_of_match);
> +#else
> +#define fixed_of_match NULL
> +#endif
> +
>  static struct platform_driver regulator_fixed_voltage_driver = {
>  	.probe		= reg_fixed_voltage_probe,
>  	.remove		= __devexit_p(reg_fixed_voltage_remove),
>  	.driver		= {
>  		.name		= "reg-fixed-voltage",
>  		.owner		= THIS_MODULE,
> +		.of_match_table = fixed_of_match,


>  	},
>  };
>  
> -- 
> 1.7.1
> 

^ permalink raw reply

* [PATCH] ARM: realview-eb11mp: fix map_desc alignment
From: Nicolas Pitre @ 2011-09-30  1:34 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317343578-5307-1-git-send-email-robherring2@gmail.com>

On Thu, 29 Sep 2011, Rob Herring wrote:

> From: Rob Herring <rob.herring@calxeda.com>
> 
> REALVIEW_EB11MP_GIC_CPU_BASE is not 4KB aligned which causes an
> overlapping mapping. Use REALVIEW_EB11MP_SCU_BASE instead which is
> aligned.
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> ---
> Nico,
> 
> Here's another one. I visually checked the remaining Realview platforms and
> think they are fine.

Thanks.


Nicolas

^ permalink raw reply

* [PATCH 8/9] regulator: helper to extract regulator node based on supply name
From: Grant Likely @ 2011-09-30  1:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-9-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:51PM +0530, Rajendra Nayak wrote:
> Device nodes in DT can associate themselves with one or more
> regulators by providing a list of phandles (to regulator nodes)
> and corresponding supply names.
> 
> For Example:
> 	devicenode: node at 0x0 {
> 		...
> 		...
> 		vmmc-supply = <&regulator1>;
> 		vpll-supply = <&regulator1>;
> 	};
> 
> The driver would then do a regulator_get(dev, "vmmc"); to get
> regulator1 and do a regulator_get(dev, "vpll"); to get
> regulator2.
> 
> of_get_regulator() extracts the regulator node for a given
> device, based on the supply name.
> 
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> ---
>  drivers/regulator/of_regulator.c       |   39 ++++++++++++++++++++++++++++++++
>  include/linux/regulator/of_regulator.h |    7 +++++
>  2 files changed, 46 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
> index 7fa63ff..49dd105 100644
> --- a/drivers/regulator/of_regulator.c
> +++ b/drivers/regulator/of_regulator.c
> @@ -14,6 +14,45 @@
>  #include <linux/of.h>
>  #include <linux/regulator/machine.h>
>  
> +
> +/**
> + * of_get_regulator - get a regulator device node based on supply name
> + * @dev: Device pointer for the consumer (of regulator) device
> + * @supply: regulator supply name
> + *
> + * Extract the regulator device node corresponding to the supply name.
> + * retruns the device node corresponding to the regulator if found, else
> + * returns NULL.
> + */
> +struct device_node *of_get_regulator(struct device *dev, const char *supply)
> +{
> +	struct device_node *regnode = NULL;
> +	u32 reghandle;
> +	char prop_name[32]; /* 32 is max size of property name */
> +	const void *prop;
> +	int sz;
> +
> +	if (!dev)
> +		return NULL;
> +
> +	dev_dbg(dev, "Looking up %s-supply from device tree\n", supply);
> +
> +	snprintf(prop_name, 32, "%s-supply", supply);
> +
> +	prop = of_get_property(dev->of_node, prop_name, &sz);
> +	if (!prop || sz < 4)
> +		return NULL;
> +
> +	reghandle = be32_to_cpup(prop);
> +	regnode = of_find_node_by_phandle(reghandle);

of_parse_phandle()

> +	if (!regnode) {
> +		pr_warn("%s: %s property in node %s references invalid phandle",
> +			__func__, prop_name, dev->of_node->full_name);
> +		return NULL;
> +	}
> +	return regnode;
> +}
> +
>  static void of_get_regulation_constraints(struct device_node *np,
>  					struct regulator_init_data **init_data)
>  {
> diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h
> index 3f63be9..edaba1a 100644
> --- a/include/linux/regulator/of_regulator.h
> +++ b/include/linux/regulator/of_regulator.h
> @@ -9,12 +9,19 @@
>  #if defined(CONFIG_OF_REGULATOR)
>  extern struct regulator_init_data
>  	*of_get_regulator_init_data(struct device *dev);
> +extern struct device_node *of_get_regulator(struct device *dev,
> +	const char *supply);
>  #else
>  static inline struct regulator_init_data
>  	*of_get_regulator_init_data(struct device_node *np)
>  {
>  	return NULL;
>  }
> +static inline struct device_node *of_get_regulator(struct device *dev,
> +	const char *id)
> +{
> +	return NULL;
> +}
>  #endif /* CONFIG_OF_REGULATOR */
>  
>  #endif /* __LINUX_OF_REG_H */
> -- 
> 1.7.1
> 

^ permalink raw reply

* [PATCH 9/9] regulator: map consumer regulator based on device tree
From: Grant Likely @ 2011-09-30  1:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-10-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:52PM +0530, Rajendra Nayak wrote:
> Look up the regulator for a given consumer from device tree, during
> a regulator_get(). If not found fallback and lookup through
> the regulator_map_list instead.
> 
> Devices can associate with one or more regulators by providing a
> list of phandles and supply names.
> 
> For Example:
>         devicenode: node at 0x0 {
>                 ...
>                 ...
>                 vmmc-supply = <&regulator1>;
>                 vpll-supply = <&regulator2>;
>         };
> 
> When a device driver calls a regulator_get, specifying the
> supply name, the phandle and eventually the regulator node
> is extracted from the device node.
> 
> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
> ---
>  drivers/regulator/core.c         |   14 ++++++++++++++
>  include/linux/regulator/driver.h |    3 +++
>  2 files changed, 17 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
> index d8e6a42..47b851c 100644
> --- a/drivers/regulator/core.c
> +++ b/drivers/regulator/core.c
> @@ -25,9 +25,11 @@
>  #include <linux/mutex.h>
>  #include <linux/suspend.h>
>  #include <linux/delay.h>
> +#include <linux/of.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/regulator/driver.h>
>  #include <linux/regulator/machine.h>
> +#include <linux/regulator/of_regulator.h>
>  
>  #define CREATE_TRACE_POINTS
>  #include <trace/events/regulator.h>
> @@ -1155,6 +1157,7 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
>  	struct regulator_map *map;
>  	struct regulator *regulator = ERR_PTR(-ENODEV);
>  	const char *devname = NULL;
> +	struct device_node *node;
>  	int ret;
>  
>  	if (id == NULL) {
> @@ -1167,6 +1170,15 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
>  
>  	mutex_lock(&regulator_list_mutex);
>  
> +	if (dev->of_node) {
> +		node = of_get_regulator(dev, id);
> +		if (!node)
> +			goto retry; /* fallback and chk regulator_map_list */
> +		list_for_each_entry(rdev, &regulator_list, list)
> +			if (node == rdev->node)
> +				goto found;
> +	}
> +retry:
>  	list_for_each_entry(map, &regulator_map_list, list) {
>  		/* If the mapping has a device set up it must match */
>  		if (map->dev_name &&
> @@ -2619,6 +2631,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc,
>  	rdev->reg_data = driver_data;
>  	rdev->owner = regulator_desc->owner;
>  	rdev->desc = regulator_desc;
> +	if (dev && dev->of_node)
> +		rdev->node = dev->of_node;
>  	INIT_LIST_HEAD(&rdev->consumer_list);
>  	INIT_LIST_HEAD(&rdev->list);
>  	BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
> diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
> index 1a80bc7..4aebbf5 100644
> --- a/include/linux/regulator/driver.h
> +++ b/include/linux/regulator/driver.h
> @@ -196,6 +196,9 @@ struct regulator_dev {
>  	struct mutex mutex; /* consumer lock */
>  	struct module *owner;
>  	struct device dev;
> +#ifdef CONFIG_OF
> +	struct device_node *node;
> +#endif

There is already an of_node pointer in regulator_dev->dev.of_node.
Why does another need to be added here?

g.

^ permalink raw reply

* [PATCH 0/9] Device tree support for regulators
From: Grant Likely @ 2011-09-30  1:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317118372-17052-1-git-send-email-rnayak@ti.com>

On Tue, Sep 27, 2011 at 03:42:43PM +0530, Rajendra Nayak wrote:
> Hi Mark, Grant,
> 
> This is a respin of my RFC series I posted sometime back
> and is now based on top of the latest omap i2c-twl support
> series posted by Benoit
> git://gitorious.org/omap-pm/linux.git for_3.2/4_omap_dt_i2c_twl
> 
> some changes done since the RFC:
> 1. twl driver fixed to remove hardcoded board params
> 2. regulator helpers moved from drivers/of to drivers/regulator
> 3. Better compatible definitions for specific device type
> 4. twl regulator driver doing internal table lookup based on
> compatible rather then pdev->id
> 5. Seperate fixed voltage regulator bindings defined
> 6. Changed the way devices associate with regulators
> i.e using <name>-supply = <&regulator-phandle>;

Overall looks fairly good other than the comments made by Mark and myself.

g.

^ permalink raw reply

* [PATCH] ARM: localtimer: add header linux/errno.h explicitly
From: Shawn Guo @ 2011-09-30  2:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316798545-21128-1-git-send-email-shawn.guo@linaro.org>

Hi Russell,

Do you have any comment on this patch?  Otherwise, I will put it into
patch tracker.

Regards,
Shawn

On Sat, Sep 24, 2011 at 01:22:25AM +0800, Shawn Guo wrote:
> Per the text in  Documentation/SubmitChecklist as below, we should
> explicitly have header linux/errno.h in localtimer.h for ENXIO
> reference.
> 
> 1: If you use a facility then #include the file that defines/declares
>    that facility.  Don't depend on other header files pulling in ones
>    that you use.
> 
> Otherwise, we may run into some compiling error like the following one,
> if any file includes localtimer.h without CONFIG_LOCAL_TIMERS defined.
> 
>   arch/arm/include/asm/localtimer.h: In function ?local_timer_setup?:
>   arch/arm/include/asm/localtimer.h:53:10: error: ?ENXIO? undeclared (first use in this function)
> 
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> ---
>  arch/arm/include/asm/localtimer.h |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/include/asm/localtimer.h b/arch/arm/include/asm/localtimer.h
> index 080d74f..698ff73 100644
> --- a/arch/arm/include/asm/localtimer.h
> +++ b/arch/arm/include/asm/localtimer.h
> @@ -48,6 +48,8 @@ int local_timer_setup(struct clock_event_device *);
>  
>  #else
>  
> +#include <linux/errno.h>
> +
>  static inline int local_timer_setup(struct clock_event_device *evt)
>  {
>  	return -ENXIO;
> -- 
> 1.7.4.1

^ permalink raw reply

* [PATCH] drivers: create a pin control subsystem v8
From: Grant Likely @ 2011-09-30  2:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317211419-18472-1-git-send-email-linus.walleij@stericsson.com>

On Wed, Sep 28, 2011 at 02:03:39PM +0200, Linus Walleij wrote:
> From: Linus Walleij <linus.walleij@linaro.org>
> 
> This creates a subsystem for handling of pin control devices.
> These are devices that control different aspects of package
> pins.

Comments below, some a bit nitpicky, but overall I think it looks
good.  I haven't dug into it nearly deeply enough though.  :-(

[...]
> +/**
> + * Looks up a pin control device matching a certain device name or
> + * pure device pointer.

May as well actually do kerneldoc formatting here on the comment
blocks.

> + */
> +struct pinctrl_dev *get_pctldev_from_dev(struct device *dev,
> +					 const char *devname)
> +{
> +	struct pinctrl_dev *pctldev = NULL;
> +	bool found = false;
> +
> +	mutex_lock(&pinctrldev_list_mutex);
> +	list_for_each_entry(pctldev, &pinctrldev_list, node) {
> +		if (dev &&  &pctldev->dev == dev) {
> +			/* Matched on device pointer */
> +			found = true;
> +			break;
> +		}
> +
> +		if (devname &&
> +		    !strcmp(dev_name(&pctldev->dev), devname)) {
> +			/* Matched on device name */
> +			found = true;
> +			break;
> +		}
> +	}
> +	mutex_unlock(&pinctrldev_list_mutex);
> +
> +	if (found)
> +		return pctldev;
> +
> +	return NULL;
> +}

Nit: I'm not too fond of a single function doing both name and pointer
lookup at the same time.  Presumably the caller would have one or the
other and know what it needs to do.  I'd prefer to see one by-name
function and one by-reference.  I'm not going to make a big deal about
it though.

> +/**
> + * pinctrl_register() - register a pin controller device
> + * @pctldesc: descriptor for this pin controller
> + * @dev: parent device for this pin controller
> + * @driver_data: private pin controller data for this pin controller
> + */
> +struct pinctrl_dev *pinctrl_register(struct pinctrl_desc *pctldesc,
> +				    struct device *dev, void *driver_data)
> +{
> +	static atomic_t pinmux_no = ATOMIC_INIT(0);
> +	struct pinctrl_dev *pctldev;
> +	int ret;
> +
> +	if (pctldesc == NULL)
> +		return ERR_PTR(-EINVAL);
> +	if (pctldesc->name == NULL)
> +		return ERR_PTR(-EINVAL);
> +
> +	/* If we're implementing pinmuxing, check the ops for sanity */
> +	if (pctldesc->pmxops) {
> +		ret = pinmux_check_ops(pctldesc->pmxops);
> +		if (ret) {
> +			pr_err("%s pinmux ops lacks necessary functions\n",
> +			       pctldesc->name);
> +			return ERR_PTR(ret);
> +		}
> +	}
> +
> +	pctldev = kzalloc(sizeof(struct pinctrl_dev), GFP_KERNEL);
> +	if (pctldev == NULL)
> +		return ERR_PTR(-ENOMEM);
> +
> +	/* Initialize pin control device struct */
> +	pctldev->owner = pctldesc->owner;
> +	pctldev->desc = pctldesc;
> +	pctldev->driver_data = driver_data;
> +	INIT_RADIX_TREE(&pctldev->pin_desc_tree, GFP_KERNEL);
> +	spin_lock_init(&pctldev->pin_desc_tree_lock);
> +	INIT_LIST_HEAD(&pctldev->gpio_ranges);
> +	mutex_init(&pctldev->gpio_ranges_lock);
> +
> +	/* Register device with sysfs */
> +	pctldev->dev.parent = dev;
> +	pctldev->dev.bus = &pinctrl_bus;

I don't think there is an actual need for a pinctrl bus type.  There
aren't any drivers that are going to be bound to these things which is
the primary functionality that a bus type provides.  Am I missing
something?

> +	pctldev->dev.type = &pinctrl_type;
> +	dev_set_name(&pctldev->dev, "pinctrl.%d",
> +		     atomic_inc_return(&pinmux_no) - 1);
> +	ret = device_register(&pctldev->dev);
> +	if (ret != 0) {
> +		pr_err("error in device registration\n");
> +		put_device(&pctldev->dev);
> +		kfree(pctldev);
> +		goto out_err;
> +	}
> +	dev_set_drvdata(&pctldev->dev, pctldev);
> +
> +	/* Register all the pins */
> +	pr_debug("try to register %d pins on %s...\n",
> +		 pctldesc->npins, pctldesc->name);
> +	ret = pinctrl_register_pins(pctldev, pctldesc->pins, pctldesc->npins);
> +	if (ret) {
> +		pr_err("error during pin registration\n");
> +		pinctrl_free_pindescs(pctldev, pctldesc->pins,
> +				      pctldesc->npins);
> +		goto out_err;
> +	}
> +
> +	pinctrl_init_device_debugfs(pctldev);
> +	mutex_lock(&pinctrldev_list_mutex);
> +	list_add(&pctldev->node, &pinctrldev_list);
> +	mutex_unlock(&pinctrldev_list_mutex);
> +	pinmux_hog_maps(pctldev);
> +	return pctldev;
> +
> +out_err:
> +	put_device(&pctldev->dev);
> +	kfree(pctldev);

Once a device is initialized, it cannot be kfree()'ed directly.  The
.release method needs to do that.

> +/**
> + * pin_free() - release a single muxed in pin so something else can be muxed in
> + *	instead

Nit: the summary line in kerneldoc should fit on one line.

> +/**
> + * pinmux_register_mappings() - register a set of pinmux mappings
> + * @maps: the pinmux mappings table to register
> + * @num_maps: the number of maps in the mapping table
> + *
> + * Only call this once during initialization of your machine, the function is
> + * tagged as __init and won't be callable after init has completed. The map
> + * passed into this function will be owned by the pinmux core and cannot be
> + * free:d.
> + */
> +int __init
> +pinmux_register_mappings(struct pinmux_map const *maps, unsigned num_maps)

Nit: keep line breaks in the parameter lists.  More grep friendly.

g.

^ permalink raw reply

* [PATCH 2/2 v7] pinmux: add a driver for the U300 pinmux
From: Grant Likely @ 2011-09-30  2:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1316175249-10780-1-git-send-email-linus.walleij@stericsson.com>

On Fri, Sep 16, 2011 at 02:14:09PM +0200, Linus Walleij wrote:
> From: Linus Walleij <linus.walleij@linaro.org>
> 
> This adds a driver for the U300 pinmux portions of the system
> controller "SYSCON". It also serves as an example of how to use
> the pinmux subsystem. This driver also houses the platform data
> for the only supported platform.

Hi Linus, comments below.

> diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
> index 32a7b0f..449fd6a 100644
> --- a/arch/arm/mach-u300/Kconfig
> +++ b/arch/arm/mach-u300/Kconfig
> @@ -6,6 +6,8 @@ comment "ST-Ericsson Mobile Platform Products"
>  
>  config MACH_U300
>  	bool "U300"
> +	select PINCTRL
> +	select PINMUX_U300

Shouldn't PINMUX_U300 select PINCTRL?

> +#include "pinmux-u300.h"

There is only one file that uses this header data.  Just put it into
the .c file.

> +static int __init u300_pmx_probe(struct platform_device *pdev)
> +{
> +	int ret;
> +	struct u300_pmx *upmx;
> +	struct resource *res;
> +
> +	/* Create state holders etc for this driver */
> +	upmx = kzalloc(sizeof(struct u300_pmx), GFP_KERNEL);

devm_kzalloc()

> +	if (!upmx)
> +		return -ENOMEM;
> +
> +	upmx->dev = &pdev->dev;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!res) {
> +		ret = -ENOENT;
> +		goto out_no_resource;
> +	}
> +	upmx->phybase = res->start;
> +	upmx->physize = resource_size(res);
> +
> +	if (request_mem_region(upmx->phybase, upmx->physize,
> +			       DRIVER_NAME) == NULL) {
> +		ret = -EBUSY;
> +		goto out_no_memregion;
> +	}
> +
> +	upmx->virtbase = ioremap(upmx->phybase, upmx->physize);
> +	if (!upmx->virtbase) {
> +		ret = -ENOMEM;
> +		goto out_no_remap;
> +	}
> +
> +	upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
> +	if (IS_ERR(upmx->pctl)) {
> +		dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
> +		ret = PTR_ERR(upmx->pctl);
> +		goto out_no_pmx;
> +	}
> +
> +	/* We will handle a range of GPIO pins */
> +	pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_range);
> +
> +	platform_set_drvdata(pdev, upmx);
> +
> +	u300_pmx_dumpregs(upmx);
> +
> +	dev_info(&pdev->dev, "initialized U300 pinmux driver\n");
> +
> +	return 0;
> +
> +out_no_pmx:
> +	iounmap(upmx->virtbase);
> +out_no_remap:
> +	platform_set_drvdata(pdev, NULL);
> +out_no_memregion:
> +	release_mem_region(upmx->phybase, upmx->physize);
> +out_no_resource:
> +	kfree(upmx);
> +	return ret;
> +}
> +
> +static int __exit u300_pmx_remove(struct platform_device *pdev)

__devexit

> +{
> +	struct u300_pmx *upmx = platform_get_drvdata(pdev);
> +
> +	pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_range);
> +	pinctrl_unregister(upmx->pctl);
> +	iounmap(upmx->virtbase);
> +	release_mem_region(upmx->phybase, upmx->physize);
> +	platform_set_drvdata(pdev, NULL);
> +	kfree(upmx);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver u300_pmx_driver = {
> +	.driver = {
> +		.name = DRIVER_NAME,
> +		.owner = THIS_MODULE,
> +	},
> +	.remove = __exit_p(u300_pmx_remove),

__devexit_p

^ permalink raw reply

* [PATCH 1/5] ARM: pxa: remove redundant macro on GPIO
From: Eric Miao @ 2011-09-30  2:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAHXqBFJnS7-x-Q8aJhNhbbVHhFHWS4PTVb0369p2H42Tm4J=HQ@mail.gmail.com>

2011/9/30 Micha? Miros?aw <mirqus@gmail.com>:
> 2011/9/29 Haojian Zhuang <haojian.zhuang@marvell.com>:
> [...]
>> ? ? ? ?if (type & IRQ_TYPE_EDGE_RISING)
>> - ? ? ? ? ? ? ? GRER0 |= GPIO_bit(gpio);
>> + ? ? ? ? ? ? ? GRER(gpio) |= GPIO_bit(gpio);
> [...]
>
> This looks wrong. There are more occurrences like this. Can you
> explain if this is correct?

This is actually correct. In GRER(x) - x designates the GPIO instead
of the subindex n in GRERn.

The rest of the direct references GPxRn have been mostly removed
during the last several rounds of cleanup.

Haojian,

Please use

'git grep GP.R[0-9]'

and

'git grep GR.R[0-9]'

to rule out the rest references. I'm good with the patch, just to
make sure there is no more such reference.

>
> Best Regards,
> Micha? Miros?aw
>

^ permalink raw reply

* [PATCH 1/5] ARM: pxa: remove redundant macro on GPIO
From: Haojian Zhuang @ 2011-09-30  3:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAMPhdO_Lwi1737PTB=TFoHa8rHyyutkGc-GdUNapJOf6XkG4yg@mail.gmail.com>

2011/9/30 Eric Miao <eric.y.miao@gmail.com>:
> 2011/9/30 Micha? Miros?aw <mirqus@gmail.com>:
>> 2011/9/29 Haojian Zhuang <haojian.zhuang@marvell.com>:
>> [...]
>>> ? ? ? ?if (type & IRQ_TYPE_EDGE_RISING)
>>> - ? ? ? ? ? ? ? GRER0 |= GPIO_bit(gpio);
>>> + ? ? ? ? ? ? ? GRER(gpio) |= GPIO_bit(gpio);
>> [...]
>>
>> This looks wrong. There are more occurrences like this. Can you
>> explain if this is correct?
>
> This is actually correct. In GRER(x) - x designates the GPIO instead
> of the subindex n in GRERn.
>
> The rest of the direct references GPxRn have been mostly removed
> during the last several rounds of cleanup.
>
> Haojian,
>
> Please use
>
> 'git grep GP.R[0-9]'
>
> and
>
> 'git grep GR.R[0-9]'
>
> to rule out the rest references. I'm good with the patch, just to
> make sure there is no more such reference.
>
There's no reference to GP.R and GR.R registers except for comment.

^ permalink raw reply

* [PATCH v3] ARM: cache-l2x0: add resume entry for l2 in secure mode
From: Barry Song @ 2011-09-30  3:31 UTC (permalink / raw)
  To: linux-arm-kernel

From: Barry Song <Baohua.Song@csr.com>

we save the l2x0 registers at the first initialization, and platform codes
can get them to restore l2x0 status after wakeup.

Cc: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Signed-off-by: Barry Song <Baohua.Song@csr.com>
---
 -v3:
 save PREFETCH_CTRL and POWER_CTRL according to revision;
 save l2x0 physical address so that asm codes can use.

 arch/arm/include/asm/hardware/cache-l2x0.h |   23 +++++
 arch/arm/include/asm/outercache.h          |    7 ++
 arch/arm/kernel/asm-offsets.c              |   12 +++
 arch/arm/mm/cache-l2x0.c                   |  129 +++++++++++++++++++++++++--
 4 files changed, 161 insertions(+), 10 deletions(-)

diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h
index c48cb1e..24b5d05 100644
--- a/arch/arm/include/asm/hardware/cache-l2x0.h
+++ b/arch/arm/include/asm/hardware/cache-l2x0.h
@@ -67,6 +67,13 @@
 #define L2X0_CACHE_ID_PART_MASK		(0xf << 6)
 #define L2X0_CACHE_ID_PART_L210		(1 << 6)
 #define L2X0_CACHE_ID_PART_L310		(3 << 6)
+#define L2X0_CACHE_ID_RTL_MASK          0x3f
+#define L2X0_CACHE_ID_RTL_R0P0          0x0
+#define L2X0_CACHE_ID_RTL_R1P0          0x2
+#define L2X0_CACHE_ID_RTL_R2P0          0x4
+#define L2X0_CACHE_ID_RTL_R3P0          0x5
+#define L2X0_CACHE_ID_RTL_R3P1          0x6
+#define L2X0_CACHE_ID_RTL_R3P2          0x8
 
 #define L2X0_AUX_CTRL_MASK			0xc0000fff
 #define L2X0_AUX_CTRL_DATA_RD_LATENCY_SHIFT	0
@@ -96,6 +103,22 @@
 #ifndef __ASSEMBLY__
 extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask);
 extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask);
+
+struct l2x0_regs {
+	unsigned long phy_base;
+	unsigned long aux_ctrl;
+	/*
+	 * Whether the following registers need to be saved/restored
+	 * depends on platform
+	 */
+	unsigned long tag_latency;
+	unsigned long data_latency;
+	unsigned long filter_start;
+	unsigned long filter_end;
+	unsigned long prefetch_ctrl;
+	unsigned long pwr_ctrl;
+};
+
 #endif
 
 #endif
diff --git a/arch/arm/include/asm/outercache.h b/arch/arm/include/asm/outercache.h
index d838743..53426c6 100644
--- a/arch/arm/include/asm/outercache.h
+++ b/arch/arm/include/asm/outercache.h
@@ -34,6 +34,7 @@ struct outer_cache_fns {
 	void (*sync)(void);
 #endif
 	void (*set_debug)(unsigned long);
+	void (*resume)(void);
 };
 
 #ifdef CONFIG_OUTER_CACHE
@@ -74,6 +75,12 @@ static inline void outer_disable(void)
 		outer_cache.disable();
 }
 
+static inline void outer_resume(void)
+{
+	if (outer_cache.resume)
+		outer_cache.resume();
+}
+
 #else
 
 static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 16baba2..1429d89 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -20,6 +20,7 @@
 #include <asm/thread_info.h>
 #include <asm/memory.h>
 #include <asm/procinfo.h>
+#include <asm/hardware/cache-l2x0.h>
 #include <linux/kbuild.h>
 
 /*
@@ -92,6 +93,17 @@ int main(void)
   DEFINE(S_OLD_R0,		offsetof(struct pt_regs, ARM_ORIG_r0));
   DEFINE(S_FRAME_SIZE,		sizeof(struct pt_regs));
   BLANK();
+#ifdef CONFIG_CACHE_L2X0
+  DEFINE(L2X0_R_PHY_BASE,	offsetof(struct l2x0_regs, phy_base));
+  DEFINE(L2X0_R_AUX_CTRL,	offsetof(struct l2x0_regs, aux_ctrl));
+  DEFINE(L2X0_R_TAG_LATENCY,	offsetof(struct l2x0_regs, tag_latency));
+  DEFINE(L2X0_R_DATA_LATENCY,	offsetof(struct l2x0_regs, data_latency));
+  DEFINE(L2X0_R_FILTER_START,	offsetof(struct l2x0_regs, filter_start));
+  DEFINE(L2X0_R_FILTER_END,	offsetof(struct l2x0_regs, filter_end));
+  DEFINE(L2X0_R_PREFETCH_CTRL,	offsetof(struct l2x0_regs, prefetch_ctrl));
+  DEFINE(L2X0_R_PWR_CTRL,	offsetof(struct l2x0_regs, pwr_ctrl));
+  BLANK();
+#endif
 #ifdef CONFIG_CPU_HAS_ASID
   DEFINE(MM_CONTEXT_ID,		offsetof(struct mm_struct, context.id));
   BLANK();
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 0d85d22..3f9b998 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -33,6 +33,14 @@ static DEFINE_SPINLOCK(l2x0_lock);
 static uint32_t l2x0_way_mask;	/* Bitmask of active ways */
 static uint32_t l2x0_size;
 
+struct l2x0_regs l2x0_saved_regs;
+
+struct l2x0_of_data {
+	void (*setup)(const struct device_node *, __u32 *, __u32 *);
+	void (*save)(void);
+	void (*resume)(void);
+};
+
 static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
 {
 	/* wait for cache operation by line or way to complete */
@@ -280,7 +288,7 @@ static void l2x0_disable(void)
 	spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
-static void __init l2x0_unlock(__u32 cache_id)
+static void l2x0_unlock(__u32 cache_id)
 {
 	int lockregs;
 	int i;
@@ -356,6 +364,8 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask)
 		/* l2x0 controller is disabled */
 		writel_relaxed(aux, l2x0_base + L2X0_AUX_CTRL);
 
+		l2x0_saved_regs.aux_ctrl = aux;
+
 		l2x0_inv_all();
 
 		/* enable L2X0 */
@@ -445,33 +455,132 @@ static void __init pl310_of_setup(const struct device_node *np,
 	}
 }
 
+static void __init pl310_save(void)
+{
+	u32 l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+		L2X0_CACHE_ID_RTL_MASK;
+
+	l2x0_saved_regs.tag_latency = readl_relaxed(l2x0_base +
+		L2X0_TAG_LATENCY_CTRL);
+	l2x0_saved_regs.data_latency = readl_relaxed(l2x0_base +
+		L2X0_DATA_LATENCY_CTRL);
+	l2x0_saved_regs.filter_end = readl_relaxed(l2x0_base +
+		L2X0_ADDR_FILTER_END);
+	l2x0_saved_regs.filter_start = readl_relaxed(l2x0_base +
+		L2X0_ADDR_FILTER_START);
+
+	if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+		/*
+		 * From r2p0, there is Prefetch offset/control register
+		 */
+		l2x0_saved_regs.prefetch_ctrl = readl_relaxed(l2x0_base +
+			L2X0_PREFETCH_CTRL);
+		/*
+		 * From r3p0, there is Power control register
+		 */
+		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+			l2x0_saved_regs.pwr_ctrl = readl_relaxed(l2x0_base +
+				L2X0_POWER_CTRL);
+	}
+}
+
+static void l2x0_resume(void)
+{
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+		/* restore aux ctrl and enable l2 */
+		l2x0_unlock(readl_relaxed(l2x0_base + L2X0_CACHE_ID));
+
+		writel_relaxed(l2x0_saved_regs.aux_ctrl, l2x0_base +
+			L2X0_AUX_CTRL);
+
+		l2x0_inv_all();
+
+		writel_relaxed(1, l2x0_base + L2X0_CTRL);
+	}
+}
+
+static void pl310_resume(void)
+{
+	u32 l2x0_revision;
+
+	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
+		/* restore pl310 setup */
+		writel_relaxed(l2x0_saved_regs.tag_latency,
+			l2x0_base + L2X0_TAG_LATENCY_CTRL);
+		writel_relaxed(l2x0_saved_regs.data_latency,
+			l2x0_base + L2X0_DATA_LATENCY_CTRL);
+		writel_relaxed(l2x0_saved_regs.filter_end,
+			l2x0_base + L2X0_ADDR_FILTER_END);
+		writel_relaxed(l2x0_saved_regs.filter_start,
+			l2x0_base + L2X0_ADDR_FILTER_START);
+
+		l2x0_revision = readl_relaxed(l2x0_base + L2X0_CACHE_ID) &
+			L2X0_CACHE_ID_RTL_MASK;
+
+		if (l2x0_revision >= L2X0_CACHE_ID_RTL_R2P0) {
+			writel_relaxed(l2x0_saved_regs.prefetch_ctrl,
+				l2x0_base + L2X0_PREFETCH_CTRL);
+			if (l2x0_revision >= L2X0_CACHE_ID_RTL_R3P0)
+				writel_relaxed(l2x0_saved_regs.pwr_ctrl,
+					l2x0_base + L2X0_POWER_CTRL);
+		}
+	}
+
+	l2x0_resume();
+}
+
+static const struct l2x0_of_data pl310_data = {
+	pl310_of_setup,
+	pl310_save,
+	pl310_resume,
+};
+
+static const struct l2x0_of_data l2x0_data = {
+	l2x0_of_setup,
+	NULL,
+	l2x0_resume,
+};
+
 static const struct of_device_id l2x0_ids[] __initconst = {
-	{ .compatible = "arm,pl310-cache", .data = pl310_of_setup },
-	{ .compatible = "arm,l220-cache", .data = l2x0_of_setup },
-	{ .compatible = "arm,l210-cache", .data = l2x0_of_setup },
+	{ .compatible = "arm,pl310-cache", .data = (void *)&pl310_data },
+	{ .compatible = "arm,l220-cache", .data = (void *)&l2x0_data },
+	{ .compatible = "arm,l210-cache", .data = (void *)&l2x0_data },
 	{}
 };
 
 int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask)
 {
 	struct device_node *np;
-	void (*l2_setup)(const struct device_node *np,
-		__u32 *aux_val, __u32 *aux_mask);
+	struct l2x0_of_data *data;
+	struct resource res;
 
 	np = of_find_matching_node(NULL, l2x0_ids);
 	if (!np)
 		return -ENODEV;
-	l2x0_base = of_iomap(np, 0);
+
+	if (of_address_to_resource(np, 0, &res))
+		return -ENODEV;
+
+	l2x0_base = ioremap(res.start, resource_size(&res));
 	if (!l2x0_base)
 		return -ENOMEM;
 
+	l2x0_saved_regs.phy_base = res.start;
+
+	data = of_match_node(l2x0_ids, np)->data;
+
 	/* L2 configuration can only be changed if the cache is disabled */
 	if (!(readl_relaxed(l2x0_base + L2X0_CTRL) & 1)) {
-		l2_setup = of_match_node(l2x0_ids, np)->data;
-		if (l2_setup)
-			l2_setup(np, &aux_val, &aux_mask);
+		if (data->setup)
+			data->setup(np, &aux_val, &aux_mask);
 	}
+
+	if (data->save)
+		data->save();
+
 	l2x0_init(l2x0_base, aux_val, aux_mask);
+
+	outer_cache.resume = data->resume;
 	return 0;
 }
 #endif
-- 
1.7.1



Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Follow CSR on Twitter at http://twitter.com/CSR_PLC and read our blog at www.csr.com/blog

^ permalink raw reply related

* [PATCH 2/9] regulator: helper routine to extract regulator_init_data
From: Rajendra Nayak @ 2011-09-30  4:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110927150511.GM4289@opensource.wolfsonmicro.com>

[]...
>
>>>> +	init_data->supply_regulator = (char *)of_get_property(dev->of_node,
>>>> +						"regulator-supplies", NULL);
>
>>> I'd expect that in the device tree world the supply regulator would
>>> reference the node for that regulator.
>
>> You mean using phandles? Thats what Grant proposed too but
>> I thought you instead had an inclination towards names? Or maybe
>> I misunderstood.
>
> They need both.  We need to reference the device that provides the
> supply and use a name to say which of the potentially multiple supplies
> on the consumer device is which.

Mark, I still seem to be a little confused with this one as to why
we would need a phandle *and* a supply-name to reference a parent
regulator/supply.
The phandle would point to a regulator dt node and that node internally
would have just one name associated with it.

>
>>> Hrm, I think loosing the signs here is bad karma - negative voltages do
>>> exist after all.
>
>> Oops.. they do? didn't know about that.
>
> Yup, ground is just a reference point.

^ permalink raw reply

* [PATCH] arm: proc-v7: pc phy addresses before disable MMU
From: Per Förlin @ 2011-09-30  5:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110924130202.GF17169@n2100.arm.linux.org.uk>

On 09/24/2011 03:02 PM, Russell King - ARM Linux wrote:
> On Sat, Sep 24, 2011 at 02:55:42PM +0200, Per F?rlin wrote:
>> On 09/24/2011 01:00 PM, Will Deacon wrote:
>>> On Sat, Sep 24, 2011 at 10:32:48AM +0100, Per F?rlin wrote:
>>>> I am trying to figure out how I can get the value of PHYS_OFFSET in assembler code (proc-v7.S).
>>>> I guess I could use the value calculated in arch/arm/kernel.head.S but wouldn't that make
>>>> this patch dependent on CONFIG_ARM_PATCH_PHYS_VIRT?
>>>
>>> Wouldn't we just be better off passing a physical address to cpu_v7_reset
>>> instead?
>>>
>> Good point! I'm fine with that.
> 
> Alternatively, call it using the phys address.
I changed the code to use a label instead of the ARM specific instruction offset +4. A few more lines but the intention is that it should work with both ARM and THUMB. I'm in favour of Russell's idea of setting pc to physical before calling cpu_reset().
      /* Go to physical addresses to be ready for MMU disable */
      asm("ADR r1, pc_phy_here \n\t"
          "sub r1, %0 \n\t"
          "mov pc, r1 \n\t"
          "pc_phy_here: \n\t"
          : :"r" (PAGE_OFFSET - PHYS_OFFSET) : "r1", "cc");

Where is the best place for this code?
Should this be run for all ARM cpu_reset()?

I haven't found a nice way to add to cpu_reset() yet. This is what I have so far.
1. Redirect cpu_reset to c-function __cpu_reset_phy() that sets the pc to phy and then calls __cpu_reset() (the original one)
1.1 May add ifdefs in __cpu_reset_phy() to only do the virt to phy transition for some explicit ARM versions before calling __cpu_reset()
2. Rename cpu_v7_reset() to __cpu_v7_reset(). Only redirect cpu_v7_reset() to the c-function that goes to phy and then calls __cpu_v7_reset().
3. Add a new in parameter "phys_offset" to cpu_reset(). Modify only those CPU_reset() that needs this parameter. Redirect cpu_reset(x,y) to CPU_reset(x) or CPU_reset(x,y) based on ARM version.

Regards,
Per

^ permalink raw reply

* [PATCH v5 0/3] AM3517: Booting up
From: Abhilash K V @ 2011-09-30  6:12 UTC (permalink / raw)
  To: linux-arm-kernel

From: Abhilash K V <abhilash.kv@ti.com>

This patch-set gets the kernel booting up on a AM3517 EVM.
The board is able to boot with ramdisk after this,but the MMC and Ethernet
drivers are not up yet. Lots of warnings remain which will be addressed in
subsequent patches.

The patches are tested on master of git://github.com/tmlind/linux.git
Kernel version is 3.1.0-rc8 and last commit on top of which these patches
were added is:
	1dd8838c74476fe13e51334ad2444e6c963cf5ff: Linux-omap rebuilt:
	 Updated to -rc8, merged l3 fixes

Cc: Sanjeev Premi <premi@ti.com>
---
Changes in v5:
 -[1/3] was reworked to use the new method to select hwmods between
  different omap3 variants/revisions. 
 -minor code reformatting in [3/3]

Changes in v4:
 -Rebased and tested against the latest 3.1.0-rc6.
 -Added a patch [3/3] to check for missing PMIC info in vp init.

Changes in v3:
 Presence of SR feature is now used to decide if TWL4030 initialisation is to
 be done or not.

Changes in v2: Incorporated Kevin's comments to add SmartReflex as a FEATURE,
  and use omap3_has_sr() to fall out of omap3_twl_init() for AM35x case.
	

Abhilash K V (3):
  AM35x: Using OMAP3 generic hwmods
  omap_twl: Prevent SR to enable for am3517/am3505 devices
  OMAP2+: voltage: add check for missing PMIC info in vp init

 arch/arm/mach-omap2/id.c                   |    2 +-
 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   17 ++++++++++++-----
 arch/arm/mach-omap2/pm.c                   |    3 ++-
 arch/arm/mach-omap2/vp.c                   |    7 +++++++
 arch/arm/plat-omap/include/plat/cpu.h      |    2 ++
 5 files changed, 24 insertions(+), 7 deletions(-)

^ permalink raw reply

* [PATCH v5 1/3] AM35x: Using OMAP3 generic hwmods
From: Abhilash K V @ 2011-09-30  6:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317363153-10259-1-git-send-email-abhilash.kv@ti.com>

From: Abhilash K V <abhilash.kv@ti.com>

Removing modules iva, sr1_hwmod, sr2_hwmod, mailbox from
the base omap3xxx_hwmods list, so that they can be excluded
for am35x.

Signed-off-by: Abhilash K V <abhilash.kv@ti.com>
---
New in v5: reworked to use the new approach to select
 device-specific hwmods as suggested by PaulW here
 http://marc.info/?l=linux-kernel&m=131671863104802&w=2

 arch/arm/mach-omap2/omap_hwmod_3xxx_data.c |   17 ++++++++++++-----
 1 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 3008e16..8de6dc4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -3159,7 +3159,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_mmc2_hwmod,
 	&omap3xxx_mmc3_hwmod,
 	&omap3xxx_mpu_hwmod,
-	&omap3xxx_iva_hwmod,
 
 	&omap3xxx_timer1_hwmod,
 	&omap3xxx_timer2_hwmod,
@@ -3188,8 +3187,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_i2c1_hwmod,
 	&omap3xxx_i2c2_hwmod,
 	&omap3xxx_i2c3_hwmod,
-	&omap34xx_sr1_hwmod,
-	&omap34xx_sr2_hwmod,
 
 	/* gpio class */
 	&omap3xxx_gpio1_hwmod,
@@ -3211,8 +3208,6 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_mcbsp2_sidetone_hwmod,
 	&omap3xxx_mcbsp3_sidetone_hwmod,
 
-	/* mailbox class */
-	&omap3xxx_mailbox_hwmod,
 
 	/* mcspi class */
 	&omap34xx_mcspi1,
@@ -3225,31 +3220,43 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 
 /* 3430ES1-only hwmods */
 static __initdata struct omap_hwmod *omap3430es1_hwmods[] = {
+	&omap3xxx_iva_hwmod,
 	&omap3430es1_dss_core_hwmod,
+	/* mailbox class */
+	&omap3xxx_mailbox_hwmod,
 	NULL
 };
 
 /* 3430ES2+-only hwmods */
 static __initdata struct omap_hwmod *omap3430es2plus_hwmods[] = {
+	&omap3xxx_iva_hwmod,
 	&omap3xxx_dss_core_hwmod,
 	&omap3xxx_usbhsotg_hwmod,
+	/* mailbox class */
+	&omap3xxx_mailbox_hwmod,
 	NULL
 };
 
 /* 34xx-only hwmods (all ES revisions) */
 static __initdata struct omap_hwmod *omap34xx_hwmods[] = {
+	&omap3xxx_iva_hwmod,
 	&omap34xx_sr1_hwmod,
 	&omap34xx_sr2_hwmod,
+	/* mailbox class */
+	&omap3xxx_mailbox_hwmod,
 	NULL
 };
 
 /* 36xx-only hwmods (all ES revisions) */
 static __initdata struct omap_hwmod *omap36xx_hwmods[] = {
+	&omap3xxx_iva_hwmod,
 	&omap3xxx_uart4_hwmod,
 	&omap3xxx_dss_core_hwmod,
 	&omap36xx_sr1_hwmod,
 	&omap36xx_sr2_hwmod,
 	&omap3xxx_usbhsotg_hwmod,
+	/* mailbox class */
+	&omap3xxx_mailbox_hwmod,
 	NULL
 };
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH v5 2/3] omap_twl: Prevent SR to enable for am3517/am3505 devices
From: Abhilash K V @ 2011-09-30  6:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317363153-10259-2-git-send-email-abhilash.kv@ti.com>

From: Abhilash K V <abhilash.kv@ti.com>

In case of AM3517 & AM3505, SmartReflex is not applicable so
we must not enable it. So omap3_twl_init() is now not called
when the processor does not support SR.

Signed-off-by: Vaibhav Hiremath <hvaibhav@ti.com>
Signed-off-by: Abhilash K V <abhilash.kv@ti.com>
---
 arch/arm/mach-omap2/id.c              |    2 +-
 arch/arm/mach-omap2/pm.c              |    3 ++-
 arch/arm/plat-omap/include/plat/cpu.h |    2 ++
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
index d27daf9..b7e3082 100644
--- a/arch/arm/mach-omap2/id.c
+++ b/arch/arm/mach-omap2/id.c
@@ -188,7 +188,7 @@ static void __init omap3_check_features(void)
 	if (cpu_is_omap3630())
 		omap_features |= OMAP3_HAS_192MHZ_CLK;
 	if (!cpu_is_omap3505() && !cpu_is_omap3517())
-		omap_features |= OMAP3_HAS_IO_WAKEUP;
+		omap_features |= (OMAP3_HAS_IO_WAKEUP | OMAP3_HAS_SR);
 
 	omap_features |= OMAP3_HAS_SDRC;
 
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 0844e2e..6835198 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -250,7 +250,8 @@ postcore_initcall(omap2_common_pm_init);
 static int __init omap2_common_pm_late_init(void)
 {
 	/* Init the OMAP TWL parameters */
-	omap3_twl_init();
+	if (omap3_has_sr())
+		omap3_twl_init();
 	omap4_twl_init();
 
 	/* Init the voltage layer */
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 2f90269..cc6fcd3 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -413,6 +413,7 @@ extern u32 omap_features;
 #define OMAP4_HAS_MPU_1GHZ		BIT(8)
 #define OMAP4_HAS_MPU_1_2GHZ		BIT(9)
 #define OMAP4_HAS_MPU_1_5GHZ		BIT(10)
+#define OMAP3_HAS_SR			BIT(11)
 
 
 #define OMAP3_HAS_FEATURE(feat,flag)			\
@@ -429,6 +430,7 @@ OMAP3_HAS_FEATURE(isp, ISP)
 OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
 OMAP3_HAS_FEATURE(sdrc, SDRC)
+OMAP3_HAS_FEATURE(sr, SR)
 
 /*
  * Runtime detection of OMAP4 features
-- 
1.7.1

^ permalink raw reply related

* [PATCH v5 3/3] OMAP2+: voltage: add check for missing PMIC info in vp init
From: Abhilash K V @ 2011-09-30  6:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1317363153-10259-3-git-send-email-abhilash.kv@ti.com>

From: Abhilash K V <abhilash.kv@ti.com>

If PMIC info is not available in omap_vp_init(), abort.

Signed-off-by: Abhilash K V <abhilash.kv@ti.com>
---
 arch/arm/mach-omap2/vp.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/vp.c b/arch/arm/mach-omap2/vp.c
index 66bd700..0ed3d13 100644
--- a/arch/arm/mach-omap2/vp.c
+++ b/arch/arm/mach-omap2/vp.c
@@ -41,6 +41,13 @@ void __init omap_vp_init(struct voltagedomain *voltdm)
 	u32 val, sys_clk_rate, timeout, waittime;
 	u32 vddmin, vddmax, vstepmin, vstepmax;
 
+	if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
+		pr_err("%s: PMIC info requried to configure VP for "
+			"vdd_%s not populated.Hence cannot initialize VP\n",
+			__func__, voltdm->name);
+		return;
+	}
+
 	if (!voltdm->read || !voltdm->write) {
 		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
 			__func__, voltdm->name);
-- 
1.7.1

^ permalink raw reply related

* [PATCH] mx5: modify pm and idle
From: Hui Wang @ 2011-09-30  6:37 UTC (permalink / raw)
  To: linux-arm-kernel

Two problems exist in the current i.MX5 pm suspend/resume and idle
functions. The first is the current i.MX5 suspend routine will call
tzic_enable_wake(1) to set wake source, this will set all enabled
irq as wake source rather than those wake capable. The second
is i.MX5 idle will call mx5_cpu_lp_set() to prepare enter low power
mode, but it forgets to call wfi instruction to enter this mode.

To fix these two problems, using generic irq chip pm interface and
adding a new function mx5_arch_idle().

Signed-off-by: Hui Wang <jason77.wang@gmail.com>
---

This patch is basing on the latest imx-features branch.

This patch is validated on the i.MX51 PDK board (CPU revision 2.0).

Since both pm suspend/resume and idle has close relation with
mx5_cpu_lp_set() and tzic_enable_wake(), i choose to use one patch
instead of independent two to address existing problems.

 arch/arm/mach-mx5/system.c              |   24 +++++++++++++++--
 arch/arm/plat-mxc/include/mach/mxc.h    |    2 +-
 arch/arm/plat-mxc/include/mach/system.h |    3 +-
 arch/arm/plat-mxc/tzic.c                |   42 ++++++++++++++++++++++---------
 4 files changed, 54 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mach-mx5/system.c b/arch/arm/mach-mx5/system.c
index 76ae8dc..92bf341 100644
--- a/arch/arm/mach-mx5/system.c
+++ b/arch/arm/mach-mx5/system.c
@@ -10,11 +10,17 @@
  * http://www.opensource.org/licenses/gpl-license.html
  * http://www.gnu.org/copyleft/gpl.html
  */
+#include <linux/suspend.h>
+#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <mach/hardware.h>
+#include <mach/common.h>
+
 #include "crm_regs.h"
 
+static struct clk *gpc_dvfs_clk;
+
 /* set cpu low power mode before WFI instruction. This function is called
   * mx5 because it can be used for mx50, mx51, and mx53.*/
 void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
@@ -54,9 +60,6 @@ void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
 			stop_mode = 1;
 		}
 		arm_srpgcr |= MXC_SRPGCR_PCR;
-
-		if (tzic_enable_wake(1) != 0)
-			return;
 		break;
 	case STOP_POWER_ON:
 		ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
@@ -82,3 +85,18 @@ void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
 		__raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
 	}
 }
+
+void mx5_arch_idle(void)
+{
+		if (gpc_dvfs_clk == NULL)
+			gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+
+		/* gpc clock is needed for SRPG */
+		clk_enable(gpc_dvfs_clk);
+		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+		if (tzic_enable_wake() != 0)
+			goto exit;
+		cpu_do_idle();
+exit:
+		clk_disable(gpc_dvfs_clk);
+}
diff --git a/arch/arm/plat-mxc/include/mach/mxc.h b/arch/arm/plat-mxc/include/mach/mxc.h
index 0987923..c4d324a 100644
--- a/arch/arm/plat-mxc/include/mach/mxc.h
+++ b/arch/arm/plat-mxc/include/mach/mxc.h
@@ -182,7 +182,7 @@ struct cpu_op {
 	u32 cpu_rate;
 };
 
-int tzic_enable_wake(int is_idle);
+int tzic_enable_wake(void);
 enum mxc_cpu_pwr_mode {
 	WAIT_CLOCKED,		/* wfi only */
 	WAIT_UNCLOCKED,		/* WAIT */
diff --git a/arch/arm/plat-mxc/include/mach/system.h b/arch/arm/plat-mxc/include/mach/system.h
index 51f02a9..5b6f991 100644
--- a/arch/arm/plat-mxc/include/mach/system.h
+++ b/arch/arm/plat-mxc/include/mach/system.h
@@ -21,6 +21,7 @@
 #include <mach/common.h>
 
 extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
+extern void mx5_arch_idle(void);
 
 static inline void arch_idle(void)
 {
@@ -51,7 +52,7 @@ static inline void arch_idle(void)
 			"mcr p15, 0, %0, c1, c0, 0\n"
 			: "=r" (reg));
 	} else if (cpu_is_mx51())
-		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+		mx5_arch_idle();
 	else
 		cpu_do_idle();
 }
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index e993a18..bd73910 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -72,14 +72,35 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
 #define tzic_set_irq_fiq NULL
 #endif
 
-static unsigned int *wakeup_intr[4];
-
 static struct mxc_extra_irq tzic_extra_irq = {
 #ifdef CONFIG_FIQ
 	.set_irq_fiq = tzic_set_irq_fiq,
 #endif
 };
 
+#ifdef CONFIG_PM
+static void tzic_irq_suspend(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	int idx = gc->irq_base >> 5;
+
+	__raw_writel(gc->wake_active, tzic_base + TZIC_WAKEUP0(idx));
+}
+
+static void tzic_irq_resume(struct irq_data *d)
+{
+	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
+	int idx = gc->irq_base >> 5;
+
+	__raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(idx)),
+		     tzic_base + TZIC_WAKEUP0(idx));
+}
+
+#else
+#define tzic_irq_suspend NULL
+#define tzic_irq_resume NULL
+#endif
+
 static __init void tzic_init_gc(unsigned int irq_start)
 {
 	struct irq_chip_generic *gc;
@@ -90,12 +111,13 @@ static __init void tzic_init_gc(unsigned int irq_start)
 				    handle_level_irq);
 	gc->private = &tzic_extra_irq;
 	gc->wake_enabled = IRQ_MSK(32);
-	wakeup_intr[idx] = &gc->wake_active;
 
 	ct = gc->chip_types;
 	ct->chip.irq_mask = irq_gc_mask_disable_reg;
 	ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
 	ct->chip.irq_set_wake = irq_gc_set_wake;
+	ct->chip.irq_suspend = tzic_irq_suspend;
+	ct->chip.irq_resume = tzic_irq_resume;
 	ct->regs.disable = TZIC_ENCLEAR0(idx);
 	ct->regs.enable = TZIC_ENSET0(idx);
 
@@ -166,23 +188,19 @@ void __init tzic_init_irq(void __iomem *irqbase)
 /**
  * tzic_enable_wake() - enable wakeup interrupt
  *
- * @param is_idle		1 if called in idle loop (ENSET0 register);
- *				0 to be used when called from low power entry
  * @return			0 if successful; non-zero otherwise
  */
-int tzic_enable_wake(int is_idle)
+int tzic_enable_wake(void)
 {
-	unsigned int i, v;
+	unsigned int i;
 
 	__raw_writel(1, tzic_base + TZIC_DSMINT);
 	if (unlikely(__raw_readl(tzic_base + TZIC_DSMINT) == 0))
 		return -EAGAIN;
 
-	for (i = 0; i < 4; i++) {
-		v = is_idle ? __raw_readl(tzic_base + TZIC_ENSET0(i)) :
-			*wakeup_intr[i];
-		__raw_writel(v, tzic_base + TZIC_WAKEUP0(i));
-	}
+	for (i = 0; i < 4; i++)
+		__raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(i)),
+			     tzic_base + TZIC_WAKEUP0(i));
 
 	return 0;
 }
-- 
1.7.6

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox