Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 3/6] ARM: ux500: Add support for ST-Ericsson's u9540 SoC
From: Lee Jones @ 2012-10-11  9:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121011085223.GW12801@game.jcrosoft.org>

On Thu, 11 Oct 2012, Jean-Christophe PLAGNIOL-VILLARD wrote:

> On 08:38 Thu 11 Oct     , Lee Jones wrote:
> > On Wed, 10 Oct 2012, Jean-Christophe PLAGNIOL-VILLARD wrote:
> > 
> > > On 16:18 Wed 10 Oct     , Lee Jones wrote:
> > > > First level board support for the u9540.
> > > > 
> > > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > > ---
> > > >  arch/arm/mach-ux500/cpu-db8500.c |   14 ++++++++++++++
> > > >  1 file changed, 14 insertions(+)
> > > > 
> > > > diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
> > > > index 3d8e321..6b7f970 100644
> > > > --- a/arch/arm/mach-ux500/cpu-db8500.c
> > > > +++ b/arch/arm/mach-ux500/cpu-db8500.c
> > > > @@ -17,6 +17,7 @@
> > > >  #include <linux/platform_device.h>
> > > >  #include <linux/io.h>
> > > >  #include <linux/mfd/abx500/ab8500.h>
> > > > +#include <linux/mfd/dbx500-prcmu.h>
> > > >  #include <linux/of.h>
> > > >  #include <linux/of_platform.h>
> > > >  #include <linux/regulator/machine.h>
> > > > @@ -319,6 +320,8 @@ static void __init u8500_init_machine(void)
> > > >  		snowball_pinmaps_init();
> > > >  	else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
> > > >  		hrefv60_pinmaps_init();
> > > > +	else if (of_machine_is_compatible("st-ericsson,u9540")) {}
> > > > +		/* TODO: Add u9540 pinmaps. */
> > > do you via DT no here
> > 
> > We don't support pinctrl yet. It will come, it's just not available yet.
> so stop to add more and update the drviers

We'll get round to it. 

We have a set priority list. Neither you nor I have control over that.

> and u9540 is a SoC name not a baord name

It's both. The u9540 board is affectionately called the u9540 board.

> > > >  	/* TODO: Export SoC, USB, cpu-freq and DMA40 */
> > > >  	parent = u8500_of_init_devices();
> > > > @@ -331,6 +334,7 @@ static const char * u8500_dt_board_compat[] = {
> > > >  	"calaosystems,snowball-a9500",
> > > >  	"st-ericsson,hrefv60+",
> > > >  	"st-ericsson,mop500",
> > > > +	"st-ericsson,u9540",
> > > stop to add more compatible sue a more generic one
> > 
> > Not entirely sure what you mean here.
> > 
> > These are the only four boards we officially support.
> > 
> > There are other uXXXX boards that we do not.
> you do not need it just mach a global compatbile

Why? What difference does it make? I could understand if we
had a long list of supported boards, but I think this is move
verbose and descriptive.

> > > >  	NULL,
> > > >  };
> > > >  
> > > > @@ -345,4 +349,14 @@ DT_MACHINE_START(U8500_DT, "ST-Ericsson U8500 platform (Device Tree Support)")
> > > >  	.dt_compat      = u8500_dt_board_compat,
> > > >  MACHINE_END
> > > >  
> > > > +DT_MACHINE_START(U9540_DT, "ST-Ericsson 9540 platform (Device Tree Support)")
> > > > +	.map_io		= u8500_map_io,
> > > > +	.init_irq	= ux500_init_irq,
> > > > +	.timer		= &ux500_timer,
> > > > +	.handle_irq	= gic_handle_irq,
> > > > +	.init_machine	= u8500_init_machine,
> > > > +	.init_late	= NULL,
> > > > +	.dt_compat      = u8500_dt_board_compat,
> > > > +MACHINE_END
> > > really?
> > > no need drop it for a more generic on
> > 
> > This may look the same as the previous MACHINE_START now, but
> > it will have differences in the future as more u9540 support is
> > upstreamed. I think it should stick around as a separate entity
> > for the time being. If we can consolidate the init functions at
> > a later date, believe me I will make sure it happens.

-- 
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH 6/6] mfd: Differentiate between u8500 and u9540 TCDM address mapping
From: Arnd Bergmann @ 2012-10-11  9:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121011085951.GU9707@gmail.com>

On Thursday 11 October 2012, Lee Jones wrote:
> From what I understand, this code has to be called before Device
> Tree kicks in. Actually, this code is mearly a stand-in until Loic
> has finished with the PRCMU re-vamp. Once that's complete, this
> stuff will be passed from init_IRQ(), which is invoked directly in
> start_kernel().

Ok, fair enough.

	Arnd

^ permalink raw reply

* [PATCH 3/7] ARM: tegra30: cpuidle: add LP2 driver for secondary CPUs
From: Joseph Lo @ 2012-10-11  9:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5074A74A.8010803@wwwdotorg.org>

On Wed, 2012-10-10 at 06:38 +0800, Stephen Warren wrote:
> On 10/08/2012 04:26 AM, Joseph Lo wrote:
> > This supports power-gated (LP2) idle on secondary CPUs for Tegra30.
> > The secondary CPUs can go into LP2 state independently. When CPU goes
> > into LP2 state, it saves it's state and puts itself to flow controlled
> > WFI state. After that, it will been power gated.
> 
> > diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
> 
> >  static struct cpuidle_driver tegra_idle_driver = {
> >  	.name = "tegra_idle",
> >  	.owner = THIS_MODULE,
> >  	.en_core_tk_irqen = 1,
> > -	.state_count = 1,
> > +	.state_count = 2,
> 
> Doesn't that assignment need to be ifdef'd just like the array entry
> setup below:
> 
> >  	.states = {
> >  		[0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
> > +#ifdef CONFIG_PM_SLEEP
> > +		[1] = {
> > +			.enter			= tegra30_idle_lp2,
> > +			.exit_latency		= 2000,
> > +			.target_residency	= 2200,
> > +			.power_usage		= 0,
> > +			.flags			= CPUIDLE_FLAG_TIME_VALID,
> > +			.name			= "LP2",
> > +			.desc			= "CPU power-gate",
> > +		},
> > +#endif
> >  	},
> >  };
> 
> > @@ -41,6 +114,10 @@ int __init tegra30_cpuidle_init(void)
> >  	struct cpuidle_device *dev;
> >  	struct cpuidle_driver *drv = &tegra_idle_driver;
> >  
> > +#ifndef CONFIG_PM_SLEEP
> > +	drv->state_count = 1;	/* support clockgating only */
> > +#endif
> 
> Oh, I see it's done here. Just fixing the static initialization seems a
> lot simpler?
> 
OK. Will do.

> > diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
> 
> > +void __cpuinit tegra_clear_cpu_in_lp2(int cpu)
> > +{
> > +	spin_lock(&tegra_lp2_lock);
> > +	BUG_ON(!cpumask_test_cpu(cpu, &tegra_in_lp2));
> > +	cpumask_clear_cpu(cpu, &tegra_in_lp2);
> > +
> > +	/*
> > +	 * Update the IRAM copy used by the reset handler. The IRAM copy
> > +	 * can't use used directly by cpumask_clear_cpu() because it uses
> > +	 * LDREX/STREX which requires the addressed location to be inner
> > +	 * cacheable and sharable which IRAM isn't.
> > +	 */
> > +	writel(tegra_in_lp2.bits[0], tegra_cpu_lp2_mask);
> > +	dsb();
> 
> Why not /just/ store the data in IRAM, and read/write directly to it,
> rather than maintaining an SDRAM-based copy of it?
> 
> Then, wouldn't the body of this function be simply:
> 
> spin_lock();
> BUG_ON(!(tegra_cpu_lp2_mask & BIT(cpu)));
> tegra_cpu_lp2_mask |= BIT(cpu);
> spin_unlock();
> 

It may not simple like this. To maintain it identical to a cpumask. It
may look likes below. Because I need to compare it with cpu_online_mask.

void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id)
{
	cpumask_t *iram_cpu_lp2_mask = tegra_cpu_lp2_mask;
	unsigned long *addr;

	spin_lock(&tegra_lp2_lock);

	addr = cpumask_bits(iram_cpu_lp2_mask);
	BUG_ON(!(1UL &
		(addr[BIT_WORD(phy_cpu_id)]
		 >> (phy_cpu_id & (BITS_PER_LONG-1)))));

	*(addr + BIT_WORD(phy_cpu_id)) &= ~BIT_MASK(phy_cpu_id);

	spin_unlock(&tegra_lp2_lock);
}

> > +bool __cpuinit tegra_set_cpu_in_lp2(int cpu)
> 
> Similar comment here.

bool __cpuinit tegra_set_cpu_in_lp2(int phy_cpu_id)
{ 
	bool last_cpu = false;
	cpumask_t *iram_cpu_lp2_mask = tegra_cpu_lp2_mask;
	unsigned long *addr;

	spin_lock(&tegra_lp2_lock);

	addr = cpumask_bits(iram_cpu_lp2_mask);
	BUG_ON((1UL &
		(addr[BIT_WORD(phy_cpu_id)]
		 >> (phy_cpu_id & (BITS_PER_LONG-1)))));

	*(addr + BIT_WORD(phy_cpu_id)) |= BIT_MASK(phy_cpu_id);

	if ((phy_cpu_id == 0) && 
	     cpumask_equal(iram_cpu_lp2_mask, cpu_online_mask))
		last_cpu = true;

	spin_unlock(&tegra_lp2_lock);
	return last_cpu;
}

So I think the original version should more easy to understand. How do
you think?

Thanks,
Joseph

^ permalink raw reply

* [PATCH 4/4] mtd: nand: omap2: Add data correction support
From: Philip, Avinash @ 2012-10-11  9:05 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121011082149.GA15609@parrot.com>

On Thu, Oct 11, 2012 at 13:51:49, Ivan Djelic wrote:
> On Thu, Oct 11, 2012 at 06:27:13AM +0100, Philip, Avinash wrote:
> (...)
> > > Another simple strategy could use the fact that you add a 14th zero byte to
> > > the 13 BCH bytes for RBL compatibility:
> > 
> > RBL compatibility (14th byte) is applicable only for BCH8 ecc scheme.
> > 
> > So I am planning adding an extra byte (0) for BCH4 ecc scheme. So with this
> > we can go for same approaches in BCH4 & BCH8 ecc scheme.
> > 
> > If I understood correctly, software BCH ecc scheme is modifying calculated
> > ecc data to handle bit flips in erased pages.
> > 
> > If that is the only reason, whether same logic can go for same ECC calculation
> > (remove modification of calculated ecc in case of software ecc correction)
> > by adding an extra byte (0) in spare area to handle erased pages.
> > 
> > So can you share if I am missing something?
> 
> Yes, the only reason why a constant polynomial is added to hw-generated ECC
> bytes is to transparently handle bitflips in erased pages.
> Handling erased pages this way has several benefits over the zero byte hack:
> - cleaner code, no checking of the zero byte
> - no expensive scan of data+spare area when reading an erased block: this
>   step can significantly slow down the initial UBI scan (lots of erased
>    pages to read)

Thanks for raising this point.
In order to reduce scan time of data+spare area when reading an erased block,
we can follow below steps

1. Create a standard ecc vector for erased page & check against it with calculated
   ecc of erased page.
2. If the vectors won't match, go for counting bit flips in erased page.
3. Again filtering of erased page can done by checking zero at fixed locations
   in spare area.
Note:
Reading of bits in erased page should done only for pages having bitflips.

> - no need to worry about the (very unlikely) possibility of having more
>   than 4 bitflips in the zero byte
> 
> OTOH, having the same ECC codes for both ELM and non-ELM chips with RBL
> compatibility sounds nice and would also simplify things.
> Note: on platforms where we use SW BCH correction, we also use the
> MLC OMAP boot mode, which is more robust and not compatible
> with 8-bit/4-bit BCH layouts.
> 
> I don't know which way is better for the OMAP community:
> 1. Unifying ECC modes = loosing the constant polynomial benefits,
>    but gaining RBL compat and simplifying code
> 2. Keeping separate ECC modes = code bloat
> 
> Tony, do you have an opinion on this ?
> 
> BTW, Afzal is submitting a series of patches [1] which are not
> compatible with your series; is there any plan to merge your patches ?

My next series will be on top Afzal's changes.

Thanks
Avinash

> 
> BR,
> --
> Ivan
> 
> [1] http://lists.infradead.org/pipermail/linux-mtd/2012-October/044374.html
> 

^ permalink raw reply

* [PATCH v2 00/15] pinctrl: samsung: Usability and extensibiltiy improvements
From: Kyungmin Park @ 2012-10-11  9:01 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349943081-27939-1-git-send-email-t.figa@samsung.com>

Hi,

On Thu, Oct 11, 2012 at 5:11 PM, Tomasz Figa <t.figa@samsung.com> wrote:
> This patch series is a work on improving usability and extensibiltiy of
> the pinctrl-samsung driver. It consists of three main parts:
>  - improving flexibility of SoC-specific data specification
>  - converting the driver to one GPIO chip and IRQ domain per pin bank
>  - improving wake-up IRQ setup and handling

Really good job! and it solved mess GPIOs H/W configurations of Samsung SoC.
Basically Samsung SoC GPIOs don't have generic rules. Even worse, pin
name is mixed but offset is still increased.

With DT support. we can solve this issue and use generic pinctrl drivers.

For all series.
Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com>

>
> 1) What the first part does, in addition to various related fixes, is
> removing any unnecessary static data from pinctrl-exynos driver.
>
> This is achieved mostly thanks to assigning pin numbers dynamically,
> with help of only pin counts of particular banks. It also simplifies
> adding next SoC variants, since much less static data needs to be
> specified.
>
> 2) The second part attempts to simplify usage of the driver and fix several
> problems of current implementation, in particular:
>
>   - Simplifies GPIO pin specification in device tree by using pin
>     namespace local to pin bank instead of local to pin controller, e.g.
>
>         gpios = <&gpj0 3 0>;
>
>     instead of
>
>         gpios = <&pinctrl0 115 0>;
>
>   - Simplifies GPIO interrupt specification in device tree by using
>     namespace local to pin bank (and equal to GPIO namespace), e.g.
>
>         interrupt-parent = <&gpj0>;
>         interrupts = <3 0>;
>
>     instead of
>
>         interrupt-parent = <&pinctrl0>;
>         interrupts = <115 0>;
>
>   - Simplifies internal GPIO pin to bank translation thanks to
>     correspondence of particular GPIO chips to pin banks. This allows
>     to remove the (costly in case of GPIO bit-banging drivers) lookup
>     over all banks to find the one that the pin is from.
>
> 3) Third part is focused on removing the hard-coded description of wake-up
> interrupt layout.
>
> It moves wake-up interrupt description to bank struct and device tree,
> which allows to specify which pin banks support wake-up interrupts and
> how they are handled (direct or multiplexed/chained).
>
> See particular patches for more detailed descriptions and the last patch for
> updated device tree bindings.
>
> Changes since v1:
>  - dropped moving SoC-specific data to device tree
>    (might be added in further patches)
>  - dropped per-bank specification of configuration register offsets
>    (thus limiting scope of the driver to Exynos SoCs; will be added in
>     further patches)
>
> Tomasz Figa (15):
>   pinctrl: samsung: Detect and handle unsupported configuration types
>   pinctrl: samsung: Do not pass gpio_chip to pin_to_reg_bank
>   pinctrl: samsung: Assing pin numbers dynamically
>   pinctrl: samsung: Remove static pin enumerations
>   pinctrl: samsung: Distinguish between pin group and bank nodes
>   ARM: dts: exynos4210-pinctrl: Add nodes for pin banks
>   pinctrl: samsung: Match pin banks with their device nodes
>   pinctrl: samsung: Hold pointer to driver data in bank struct
>   pinctrl: samsung: Include bank-specific eint offset in bank struct
>   pinctrl: exynos: Use one IRQ domain per pin bank
>   pinctrl: samsung: Use one GPIO chip per pin bank
>   pinctrl: samsung: Use per-bank IRQ domain for wake-up interrupts
>   pinctrl: exynos: Set pin function to EINT in irq_set_type of wake-up
>     EINT
>   pinctrl: samsung: Add GPIO to IRQ translation
>   Documentation: Update samsung-pinctrl device tree bindings
>     documentation
>
>  .../bindings/pinctrl/samsung-pinctrl.txt           | 118 +++++--
>  arch/arm/boot/dts/exynos4210-pinctrl.dtsi          | 278 ++++++++++++++++
>  arch/arm/boot/dts/exynos4210.dtsi                  | 241 +-------------
>  drivers/pinctrl/pinctrl-exynos.c                   | 367 ++++++++++-----------
>  drivers/pinctrl/pinctrl-exynos.h                   | 170 ++--------
>  drivers/pinctrl/pinctrl-samsung.c                  | 203 ++++++++----
>  drivers/pinctrl/pinctrl-samsung.h                  |  29 +-
>  7 files changed, 741 insertions(+), 665 deletions(-)
>
> --
> 1.7.12
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 6/6] mfd: Differentiate between u8500 and u9540 TCDM address mapping
From: Lee Jones @ 2012-10-11  8:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201210101834.40749.arnd@arndb.de>

On Wed, 10 Oct 2012, Arnd Bergmann wrote:

> On Wednesday 10 October 2012, Lee Jones wrote:
> > @@ -2688,7 +2688,11 @@ void __init db8500_prcmu_early_init(void)
> >                         iounmap(tcpm_base);
> >                 }
> >  
> > -               tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
> > +               if (cpu_is_u9540())
> > +                       tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE,
> > +                                               SZ_4K + SZ_8K) + SZ_8K;
> > +               else
> > +                       tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
> >         } else {
> >                 pr_err("prcmu: Unsupported chip version\n");
> >                 BUG();
> 
> Would it be possible to get the base out of the device tree and always
> map it from there? Adding another dependency on a fixed constant is
> just going to make the conversion to multiplatform harder, since it
> was decided that device drivers should not have access to platform
> header files in the multiplatform case.

>From what I understand, this code has to be called before Device
Tree kicks in. Actually, this code is mearly a stand-in until Loic
has finished with the PRCMU re-vamp. Once that's complete, this
stuff will be passed from init_IRQ(), which is invoked directly in
start_kernel().

-- 
Lee Jones
Linaro ST-Ericsson Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH v4 RESEND 1/3] Input: egalax_ts: get gpio from devicetree
From: Shawn Guo @ 2012-10-11  8:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121010163036.GC19335@core.coreip.homeip.net>

Add LAKML ...

On Wed, Oct 10, 2012 at 09:30:36AM -0700, Dmitry Torokhov wrote:
> Hi Hui,
> 
> On Wed, Oct 10, 2012 at 05:12:01PM +0800, Hui Wang wrote:
> > The irq_to_gpio() is old, most platforms use GENERIC_GPIO framework
> > and don't support this API anymore.
> > 
> > The i.MX6q sabrelite platform equips an egalax touchscreen controller,
> > and this platform already transfered to GENERIC_GPIO framework, to
> > support this driver, we use a more generic way to get gpio.
> 
> Unfortunately this does break the driver for platforms that do still
> support irq_to_gpio and have not transitioned to device tree (yet?).
> It looks like the API suffered from premature deletion...
> 
> I really do not want to add a new platform data structure with only gpio
> in it, is there a better way to detect if irq_to_gpio() (even if only a
> stub) is available?
> 
If CONFIG_ARCH_HAVE_CUSTOM_GPIO_H is not enabled for an architecture,
the irq_to_gpio() in include/linux/gpio.h will tell unavailability by
returning -EINVAL.  But ARM architecture still selects ARCH_HAVE_CUSTOM_GPIO_H
because there are still some platforms having mach/gpio.h.

We may also need a stub irq_to_gpio simply returning -EINVAL into
arch/arm/include/asm/gpio.h when platform does not provide irq_to_gpio,
so that driver can detect if irq_to_gpio() is available.  And that
stub can be removed later when we deselect ARCH_HAVE_CUSTOM_GPIO_H
for ARM architecture.

Shawn

^ permalink raw reply

* alignment faults in 3.6
From: Russell King - ARM Linux @ 2012-10-11  8:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AE90C24D6B3A694183C094C60CF0A2F6026B7038@saturn3.aculab.com>

On Thu, Oct 11, 2012 at 09:21:35AM +0100, David Laight wrote:
> It might be enough to use __attribute__((aligned(2))) on some structure
> members (actually does 'ldm' need 8 byte alignment?? - in which case
> aligned(4) is enough).

No, ldm just needs 4 byte alignment, the same as normal word loads/stores
not to fault.  The only instructions which needs 8 byte alignment not to
fault are the double-word load/stores.

> One on my bugbears is hardware that will once receive ethernet frames
> onto a 4n boundary - it needs to be 4n+2. two bytes of 'junk' will do.

Indeed, but remember that is just a mere optimisation for IPv4.  What
may be true of IPv4 is not necessarily true of other protocols, though
IPv4 is currently the dominant protocol today.  IPv6 follows the same
alignment rules as IPv4, so it's unlikely to change.

^ permalink raw reply

* [PATCH 3/6] ARM: ux500: Add support for ST-Ericsson's u9540 SoC
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-11  8:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121011073820.GS9707@gmail.com>

On 08:38 Thu 11 Oct     , Lee Jones wrote:
> On Wed, 10 Oct 2012, Jean-Christophe PLAGNIOL-VILLARD wrote:
> 
> > On 16:18 Wed 10 Oct     , Lee Jones wrote:
> > > First level board support for the u9540.
> > > 
> > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  arch/arm/mach-ux500/cpu-db8500.c |   14 ++++++++++++++
> > >  1 file changed, 14 insertions(+)
> > > 
> > > diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
> > > index 3d8e321..6b7f970 100644
> > > --- a/arch/arm/mach-ux500/cpu-db8500.c
> > > +++ b/arch/arm/mach-ux500/cpu-db8500.c
> > > @@ -17,6 +17,7 @@
> > >  #include <linux/platform_device.h>
> > >  #include <linux/io.h>
> > >  #include <linux/mfd/abx500/ab8500.h>
> > > +#include <linux/mfd/dbx500-prcmu.h>
> > >  #include <linux/of.h>
> > >  #include <linux/of_platform.h>
> > >  #include <linux/regulator/machine.h>
> > > @@ -319,6 +320,8 @@ static void __init u8500_init_machine(void)
> > >  		snowball_pinmaps_init();
> > >  	else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
> > >  		hrefv60_pinmaps_init();
> > > +	else if (of_machine_is_compatible("st-ericsson,u9540")) {}
> > > +		/* TODO: Add u9540 pinmaps. */
> > do you via DT no here
> 
> We don't support pinctrl yet. It will come, it's just not available yet.
so stop to add more and update the drviers

and u9540 is a SoC name not a baord name
> 
> > >  	/* TODO: Export SoC, USB, cpu-freq and DMA40 */
> > >  	parent = u8500_of_init_devices();
> > > @@ -331,6 +334,7 @@ static const char * u8500_dt_board_compat[] = {
> > >  	"calaosystems,snowball-a9500",
> > >  	"st-ericsson,hrefv60+",
> > >  	"st-ericsson,mop500",
> > > +	"st-ericsson,u9540",
> > stop to add more compatible sue a more generic one
> 
> Not entirely sure what you mean here.
> 
> These are the only four boards we officially support.
> 
> There are other uXXXX boards that we do not.
you do not need it just mach a global compatbile
> 
> > >  	NULL,
> > >  };
> > >  
> > > @@ -345,4 +349,14 @@ DT_MACHINE_START(U8500_DT, "ST-Ericsson U8500 platform (Device Tree Support)")
> > >  	.dt_compat      = u8500_dt_board_compat,
> > >  MACHINE_END
> > >  
> > > +DT_MACHINE_START(U9540_DT, "ST-Ericsson 9540 platform (Device Tree Support)")
> > > +	.map_io		= u8500_map_io,
> > > +	.init_irq	= ux500_init_irq,
> > > +	.timer		= &ux500_timer,
> > > +	.handle_irq	= gic_handle_irq,
> > > +	.init_machine	= u8500_init_machine,
> > > +	.init_late	= NULL,
> > > +	.dt_compat      = u8500_dt_board_compat,
> > > +MACHINE_END
> > really?
> > no need drop it for a more generic on
> 
> This may look the same as the previous MACHINE_START now, but
> it will have differences in the future as more u9540 support is
> upstreamed. I think it should stick around as a separate entity
> for the time being. If we can consolidate the init functions at
> a later date, believe me I will make sure it happens.
> 
> -- 
> Lee Jones
> Linaro ST-Ericsson Landing Team Lead
> Linaro.org ? Open source software for ARM SoCs
> Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply

* [PATCH] usb: remove CONFIG_USB_MUSB_HOST etc
From: Sekhar Nori @ 2012-10-11  8:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <507668C3.6080908@denx.de>

On 10/11/2012 12:05 PM, Heiko Schocher wrote:
> Hello Manjunathappa
> 
> On 11.10.2012 07:42, Manjunathappa, Prakash wrote:
>> Hi,
>> On Mon, Oct 08, 2012 at 18:47:07, Constantine Shulyupin wrote:
>>> From: Constantine Shulyupin<const@MakeLinux.com>
>>>
>>> Remove USB configuration in arch/arm/mach-davinci/usb.c accordingly
>>> CONFIG_USB_MUSB_OTG CONFIG_USB_MUSB_PERIPHERAL CONFIG_USB_MUSB_HOST
>>> and set MUSB_OTG configuration by default
>>> because this configuration options are removed from Kconfig.
>>>
>>> Signed-off-by: Constantine Shulyupin<const@MakeLinux.com>
>>>
>>> ---
>>>   arch/arm/mach-davinci/usb.c |    6 ------
>>>   1 file changed, 6 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-davinci/usb.c b/arch/arm/mach-davinci/usb.c
>>> index f77b953..34509ff 100644
>>> --- a/arch/arm/mach-davinci/usb.c
>>> +++ b/arch/arm/mach-davinci/usb.c
>>> @@ -42,14 +42,8 @@ static struct musb_hdrc_config musb_config = {
>>>   };
>>>
>>>   static struct musb_hdrc_platform_data usb_data = {
>>> -#if defined(CONFIG_USB_MUSB_OTG)
>>>       /* OTG requires a Mini-AB connector */
>>>       .mode           = MUSB_OTG,
>>> -#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
>>> -    .mode           = MUSB_PERIPHERAL,
>>> -#elif defined(CONFIG_USB_MUSB_HOST)
>>> -    .mode           = MUSB_HOST,
>>> -#endif
>>>       .clock        = "usb",
>>>       .config        =&musb_config,
>>>   };
>>
>> Tested it on DM6446-EVM for host mode with MSC thumb drive and gadget
>> mode with g-ether. It works.
>>
>> Acked-by: Manjunathappa, Prakash<prakash.pm@ti.com>
> 
> I sent a similiar patch here:
> 
> http://comments.gmane.org/gmane.linux.usb.general/54512
> 
> If the issues, mentioned from Sergei for my patch, nullified I add my:

The last outstanding issue from Sergei seems to be additional comments
describing why MUSB_OTG is OK to use.

Prakash/Constantine,

Did you have to make any hardware changes when testing host/gadget on
DM6446 EVM? Or change in kernel configuration?

It appears that there is no way to choose any of the config option
affecting the mode setting. Right now it seems to be just defaulting to
MUSB_UNDEFINED. Setting it to MUSB_OTG would be better than that.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH 4/6] ARM: ux500: Add UART support to the u9540 Device Tree
From: Jean-Christophe PLAGNIOL-VILLARD @ 2012-10-11  8:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121011072927.GR9707@gmail.com>

On 08:29 Thu 11 Oct     , Lee Jones wrote:
> On Wed, 10 Oct 2012, Jean-Christophe PLAGNIOL-VILLARD wrote:
> 
> > On 16:18 Wed 10 Oct     , Lee Jones wrote:
> > > Add the 3 UART nodes required to enable serial ports on the u9540.
> > > 
> > > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> > > Signed-off-by: Lee Jones <lee.jones@linaro.org>
> > > ---
> > >  arch/arm/boot/dts/u9540.dts |   13 ++++++++++++-
> > dts? it's dtsi
> 
> No it's not.
so the name of the file is wrong s u9540 is a SoC name

Best Regards,
J.

^ permalink raw reply

* [PATCH 1/3] ARM: dts: Renaming elpida_ecb240abacn.dtsi as lpddr2_data.dtsi
From: Lokesh Vutla @ 2012-10-11  8:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5076831A.4020701@ti.com>

On Thursday 11 October 2012 01:58 PM, Benoit Cousson wrote:
> On 10/11/2012 08:16 AM, Lokesh Vutla wrote:
>> + devicetree-discuss
>>
>> Hi Benoit,
>>
>> On Wednesday 10 October 2012 08:18 PM, Benoit Cousson wrote:
>>> Hi Lokesh,
>>>
>>> On 10/10/2012 02:05 PM, Lokesh Vutla wrote:
>>>> Renaming elpida_ecb240abacn.dtsi file generic, so that the
>>>> same file can be reused for other parts from different vendors.
>>>
>>> Could you elaborate a little bit?
>>> Are these settings purely reflecting lpddr2 spec timings?
>>
>> The basic idea is to group data for all the lpddr2 devices in a single
>> file instead of creating separate file for each lpddr2 device.
>>
>> Right now the file elpida_ecb240abacn.dtsi contains only data for
>> lpddr2-s4 2G parts from Elpida.
>> I wanted to add data for lpddr2-s4 4G parts from Samsung.
>> So I renamed the file elpida_ecb240abacn.dtsi as lpddr2_data.dtsi.
>>
>> Please let me know if more clarification is needed.
>
> Well, not anymore... as explained in the previous email, you should not
> do that.
> Keep the Elpida file and create another one for the Samsung part.
> Then each board will be able to select the proper one and include only
> the relevant data.
OK, Ill agree with you.
I ll do the changes and post the V2.

Thanks,
Lokesh
>
> Regards,
> Benoit
>

^ permalink raw reply

* [PATCH 1/3] ARM: dts: Renaming elpida_ecb240abacn.dtsi as lpddr2_data.dtsi
From: Benoit Cousson @ 2012-10-11  8:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5076644D.5050703@ti.com>

On 10/11/2012 08:16 AM, Lokesh Vutla wrote:
> + devicetree-discuss
> 
> Hi Benoit,
> 
> On Wednesday 10 October 2012 08:18 PM, Benoit Cousson wrote:
>> Hi Lokesh,
>>
>> On 10/10/2012 02:05 PM, Lokesh Vutla wrote:
>>> Renaming elpida_ecb240abacn.dtsi file generic, so that the
>>> same file can be reused for other parts from different vendors.
>>
>> Could you elaborate a little bit?
>> Are these settings purely reflecting lpddr2 spec timings?
> 
> The basic idea is to group data for all the lpddr2 devices in a single
> file instead of creating separate file for each lpddr2 device.
> 
> Right now the file elpida_ecb240abacn.dtsi contains only data for
> lpddr2-s4 2G parts from Elpida.
> I wanted to add data for lpddr2-s4 4G parts from Samsung.
> So I renamed the file elpida_ecb240abacn.dtsi as lpddr2_data.dtsi.
> 
> Please let me know if more clarification is needed.

Well, not anymore... as explained in the previous email, you should not
do that.
Keep the Elpida file and create another one for the Samsung part.
Then each board will be able to select the proper one and include only
the relevant data.

Regards,
Benoit

^ permalink raw reply

* [PATCH 4/4] mtd: nand: omap2: Add data correction support
From: Ivan Djelic @ 2012-10-11  8:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <518397C60809E147AF5323E0420B992E3E9CB751@DBDE01.ent.ti.com>

On Thu, Oct 11, 2012 at 06:27:13AM +0100, Philip, Avinash wrote:
(...)
> > Another simple strategy could use the fact that you add a 14th zero byte to
> > the 13 BCH bytes for RBL compatibility:
> 
> RBL compatibility (14th byte) is applicable only for BCH8 ecc scheme.
> 
> So I am planning adding an extra byte (0) for BCH4 ecc scheme. So with this
> we can go for same approaches in BCH4 & BCH8 ecc scheme.
> 
> If I understood correctly, software BCH ecc scheme is modifying calculated
> ecc data to handle bit flips in erased pages.
> 
> If that is the only reason, whether same logic can go for same ECC calculation
> (remove modification of calculated ecc in case of software ecc correction)
> by adding an extra byte (0) in spare area to handle erased pages.
> 
> So can you share if I am missing something?

Yes, the only reason why a constant polynomial is added to hw-generated ECC bytes is to transparently handle bitflips in erased pages.
Handling erased pages this way has several benefits over the zero byte hack:
- cleaner code, no checking of the zero byte
- no expensive scan of data+spare area when reading an erased block: this step can significantly slow down the initial UBI scan (lots of erased pages to read)
- no need to worry about the (very unlikely) possibility of having more than 4 bitflips in the zero byte

OTOH, having the same ECC codes for both ELM and non-ELM chips with RBL compatibility sounds nice and would also simplify things.
Note: on platforms where we use SW BCH correction, we also use the MLC OMAP boot mode, which is more robust and not compatible with 8-bit/4-bit BCH layouts.

I don't know which way is better for the OMAP community:
1. Unifying ECC modes = loosing the constant polynomial benefits, but gaining RBL compat and simplifying code
2. Keeping separate ECC modes = code bloat

Tony, do you have an opinion on this ?

BTW, Afzal is submitting a series of patches [1] which are not compatible with your series; is there any plan to merge your patches ?

BR,
--
Ivan

[1] http://lists.infradead.org/pipermail/linux-mtd/2012-October/044374.html

^ permalink raw reply

* alignment faults in 3.6
From: David Laight @ 2012-10-11  8:21 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <yw1xtxu1pwtv.fsf@unicorn.mansr.com>



> -----Original Message-----
> From: netdev-owner at vger.kernel.org [mailto:netdev-owner at vger.kernel.org] On Behalf Of M?ns Rullg?rd
> Sent: 11 October 2012 03:27
> To: Jon Masters
> Cc: linux-arm-kernel at lists.infradead.org; netdev at vger.kernel.org
> Subject: Re: alignment faults in 3.6
> 
> Jon Masters <jonathan@jonmasters.org> writes:
> 
> > Hi everyone,
> >
> > On 10/05/2012 10:33 AM, Rob Herring wrote:
> >> On 10/05/2012 09:05 AM, Russell King - ARM Linux wrote:
> >>> On Fri, Oct 05, 2012 at 07:24:44AM -0500, Rob Herring wrote:
> >>>> On 10/05/2012 03:24 AM, Russell King - ARM Linux wrote:
> >>>>> Does it matter?  I'm just relaying the argument against adding __packed
> >>>>> which was used before we were forced (by the networking folk) to implement
> >>>>> the alignment fault handler.
> >>>>
> >>>> It doesn't really matter what will be accepted or not as adding __packed
> >>>> to struct iphdr doesn't fix the problem anyway. 
...
> There are exactly two possible solutions:
> 
> 1. Change the networking code so those structs are always aligned.  This
>    might not be (easily) possible.
> 2. Mark the structs __packed and fix any typecasts like the ones seen in
>    this thread.  This will have an adverse effect in cases where the
>    structs are in fact aligned.
> 
> Both solutions lie squarely in the networking code.  It's time to
> involve that list, or we'll never get anywhere.

It might be enough to use __attribute__((aligned(2))) on some structure
members (actually does 'ldm' need 8 byte alignment?? - in which case
aligned(4) is enough).

One on my bugbears is hardware that will once receive ethernet frames
onto a 4n boundary - it needs to be 4n+2. two bytes of 'junk' will do.

	David

^ permalink raw reply

* [PATCH 3/3] ARM: dts: EMIF and LPDDR2 device tree data for OMAP5 boards
From: Santosh Shilimkar @ 2012-10-11  8:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <50767F42.9000807@ti.com>

On Thursday 11 October 2012 01:41 PM, Benoit Cousson wrote:
> Hi Lokesh,
>
> On 10/11/2012 08:16 AM, Lokesh Vutla wrote:
>> + devicetree-discuss
>>
>> Hi Benoit,
>>
>> On Wednesday 10 October 2012 08:31 PM, Benoit Cousson wrote:
>>> On 10/10/2012 02:05 PM, Lokesh Vutla wrote:
>>>> Device tree data for the EMIF sdram controllers in OMAP5
>>>> and LPDDR2 memory devices attached to OMAP5 boards.
>>>
>>> Nit: Could you make a sentence with a verb to explain what you are doing
>>> in this patch.
>> I am really sorry about this.
>> I ll make sure that all patch descriptions will be clear in V2 of this
>> patch series.
>>
>> In this patch I am adding device tree data for LPDDR2 memory devices
>> attached to omap5-sevm and also adding device tree data for EMIF sdram
>> controllers in OMAP5.
>>>
>>>> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
>>>> ---
>>>>    arch/arm/boot/dts/lpddr2_data.dtsi |   64
>>>> +++++++++++++++++++++++++++++++++++-
>>>>    arch/arm/boot/dts/omap5-evm.dts    |   11 +++++++
>>>>    arch/arm/boot/dts/omap5.dtsi       |   18 ++++++++++
>>>>    3 files changed, 92 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/arm/boot/dts/lpddr2_data.dtsi
>>>> b/arch/arm/boot/dts/lpddr2_data.dtsi
>>>> index f97f70f..8e8c1bc 100644
>>>> --- a/arch/arm/boot/dts/lpddr2_data.dtsi
>>>> +++ b/arch/arm/boot/dts/lpddr2_data.dtsi
>>>> @@ -3,7 +3,7 @@
>>>>     */
>>>>
>>>>    / {
>>>> -    elpida_ECB240ABACN: lpddr2 {
>>>> +    elpida_ECB240ABACN: lpddr2 at 0 {
>>>>            compatible    = "Elpida,ECB240ABACN","jedec,lpddr2-s4";
>>>>            density        = <2048>;
>>>>            io-width    = <32>;
>>>> @@ -64,4 +64,66 @@
>>>>                tDQSCK-max-derated = <6000>;
>>>>            };
>>>>        };
>>>> +
>>>> +    samsung_K3PE0E000B: lpddr2 at 1 {
>>>
>>> I'm confused now, why are you reusing the same lpddr2_data.dtsi file?
>>> You should create a file per memory. That will make the reuse much
>>> easier.
>>>
>>> If the goal of your first patch was to do that, it is then the wrong
>>> approach.
>> Yes, I wanted to group data for all lppdr2 devices in a single file than
>> creating separate file for each device.
>> May be a dumb question, Why can't we group data for all the lpddr2
>> devices in a single file?
>
> Well, why should we do that? What will be the advantage?
>
> That will increase the size of the DTS/DTB with data nobody will care if
> only one type of memory is used on a given platform.
>
> Going in the same direction you can consider adding every OMAP
> description into a single DTS... Does that really make sense?
>
> So clearly there is no point doing that, it will cluttered the OMAP4 DTB
> with useless Samsung memory data. And the same issue for OMAP5 board
> that will contain Elpida memory information. And it will get worst each
> time someone will want to add a new memory in this file.
>
> You should just include the data you need for a given board.
>
I agree with Benoit. Keeping the memory data files separate will be
better and also if some non-omap boards is using the memory parts,
the separate files can be re-used.

Regards
Santosh

^ permalink raw reply

* [PATCH 3/3] ARM: dts: EMIF and LPDDR2 device tree data for OMAP5 boards
From: Benoit Cousson @ 2012-10-11  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5076644A.10504@ti.com>

Hi Lokesh,

On 10/11/2012 08:16 AM, Lokesh Vutla wrote:
> + devicetree-discuss
> 
> Hi Benoit,
> 
> On Wednesday 10 October 2012 08:31 PM, Benoit Cousson wrote:
>> On 10/10/2012 02:05 PM, Lokesh Vutla wrote:
>>> Device tree data for the EMIF sdram controllers in OMAP5
>>> and LPDDR2 memory devices attached to OMAP5 boards.
>>
>> Nit: Could you make a sentence with a verb to explain what you are doing
>> in this patch.
> I am really sorry about this.
> I ll make sure that all patch descriptions will be clear in V2 of this
> patch series.
> 
> In this patch I am adding device tree data for LPDDR2 memory devices
> attached to omap5-sevm and also adding device tree data for EMIF sdram
> controllers in OMAP5.
>>
>>> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
>>> ---
>>>   arch/arm/boot/dts/lpddr2_data.dtsi |   64
>>> +++++++++++++++++++++++++++++++++++-
>>>   arch/arm/boot/dts/omap5-evm.dts    |   11 +++++++
>>>   arch/arm/boot/dts/omap5.dtsi       |   18 ++++++++++
>>>   3 files changed, 92 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/arch/arm/boot/dts/lpddr2_data.dtsi
>>> b/arch/arm/boot/dts/lpddr2_data.dtsi
>>> index f97f70f..8e8c1bc 100644
>>> --- a/arch/arm/boot/dts/lpddr2_data.dtsi
>>> +++ b/arch/arm/boot/dts/lpddr2_data.dtsi
>>> @@ -3,7 +3,7 @@
>>>    */
>>>
>>>   / {
>>> -    elpida_ECB240ABACN: lpddr2 {
>>> +    elpida_ECB240ABACN: lpddr2 at 0 {
>>>           compatible    = "Elpida,ECB240ABACN","jedec,lpddr2-s4";
>>>           density        = <2048>;
>>>           io-width    = <32>;
>>> @@ -64,4 +64,66 @@
>>>               tDQSCK-max-derated = <6000>;
>>>           };
>>>       };
>>> +
>>> +    samsung_K3PE0E000B: lpddr2 at 1 {
>>
>> I'm confused now, why are you reusing the same lpddr2_data.dtsi file?
>> You should create a file per memory. That will make the reuse much
>> easier.
>>
>> If the goal of your first patch was to do that, it is then the wrong
>> approach.
> Yes, I wanted to group data for all lppdr2 devices in a single file than
> creating separate file for each device.
> May be a dumb question, Why can't we group data for all the lpddr2
> devices in a single file?

Well, why should we do that? What will be the advantage?

That will increase the size of the DTS/DTB with data nobody will care if
only one type of memory is used on a given platform.

Going in the same direction you can consider adding every OMAP
description into a single DTS... Does that really make sense?

So clearly there is no point doing that, it will cluttered the OMAP4 DTB
with useless Samsung memory data. And the same issue for OMAP5 board
that will contain Elpida memory information. And it will get worst each
time someone will want to add a new memory in this file.

You should just include the data you need for a given board.


Regards,
Benoit

^ permalink raw reply

* [PATCH 15/15] Documentation: Update samsung-pinctrl device tree bindings documentation
From: Tomasz Figa @ 2012-10-11  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349943081-27939-1-git-send-email-t.figa@samsung.com>

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
 .../bindings/pinctrl/samsung-pinctrl.txt           | 118 ++++++++++++++++-----
 1 file changed, 93 insertions(+), 25 deletions(-)

diff --git a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
index 03dee50..63806e2 100644
--- a/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt
@@ -13,8 +13,14 @@ Required Properties:
 - reg: Base address of the pin controller hardware module and length of
   the address space it occupies.
 
-- interrupts: interrupt specifier for the controller. The format and value of
-  the interrupt specifier depends on the interrupt parent for the controller.
+- Pin banks as child nodes: Pin banks of the controller are represented by child
+  nodes of the controller node. Bank name is taken from name of the node. Each
+  bank node must contain following properties:
+
+  - gpio-controller: identifies the node as a gpio controller and pin bank.
+  - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
+    binding is used, the amount of cells must be specified as 2. See generic
+    GPIO binding documentation for description of particular cells.
 
 - Pin mux/config groups as child nodes: The pin mux (selecting pin function
   mode) and pin config (pull up/down, driver strength) settings are represented
@@ -72,16 +78,24 @@ used as system wakeup events.
 A. External GPIO Interrupts: For supporting external gpio interrupts, the
    following properties should be specified in the pin-controller device node.
 
-- interrupt-controller: identifies the controller node as interrupt-parent.
-- #interrupt-cells: the value of this property should be 2.
-  - First Cell: represents the external gpio interrupt number local to the
-    external gpio interrupt space of the controller.
-  - Second Cell: flags to identify the type of the interrupt
-    - 1 = rising edge triggered
-    - 2 = falling edge triggered
-    - 3 = rising and falling edge triggered
-    - 4 = high level triggered
-    - 8 = low level triggered
+   - interrupt-parent: phandle of the interrupt parent to which the external
+     GPIO interrupts are forwarded to.
+   - interrupts: interrupt specifier for the controller. The format and value of
+     the interrupt specifier depends on the interrupt parent for the controller.
+
+   In addition, following properties must be present in node of every bank
+   of pins supporting GPIO interrupts:
+
+   - interrupt-controller: identifies the controller node as interrupt-parent.
+   - #interrupt-cells: the value of this property should be 2.
+     - First Cell: represents the external gpio interrupt number local to the
+       external gpio interrupt space of the controller.
+     - Second Cell: flags to identify the type of the interrupt
+       - 1 = rising edge triggered
+       - 2 = falling edge triggered
+       - 3 = rising and falling edge triggered
+       - 4 = high level triggered
+       - 8 = low level triggered
 
 B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
    child node representing the external wakeup interrupt controller should be
@@ -94,6 +108,11 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
        found on Samsung Exynos4210 SoC.
    - interrupt-parent: phandle of the interrupt parent to which the external
      wakeup interrupts are forwarded to.
+   - interrupts: interrupt used by multiplexed wakeup interrupts.
+
+   In addition, following properties must be present in node of every bank
+   of pins supporting wake-up interrupts:
+
    - interrupt-controller: identifies the node as interrupt-parent.
    - #interrupt-cells: the value of this property should be 2
      - First Cell: represents the external wakeup interrupt number local to
@@ -105,11 +124,63 @@ B. External Wakeup Interrupts: For supporting external wakeup interrupts, a
        - 4 = high level triggered
        - 8 = low level triggered
 
+   Node of every bank of pins supporting direct wake-up interrupts (without
+   multiplexing) must contain following properties:
+
+   - interrupt-parent: phandle of the interrupt parent to which the external
+     wakeup interrupts are forwarded to.
+   - interrupts: interrupts of the interrupt parent which are used for external
+     wakeup interrupts from pins of the bank, must contain interrupts for all
+     pins of the bank.
+
 Aliases:
 
 All the pin controller nodes should be represented in the aliases node using
 the following format 'pinctrl{n}' where n is a unique number for the alias.
 
+Example: A pin-controller node with pin banks:
+
+	pinctrl_0: pinctrl at 11400000 {
+		compatible = "samsung,pinctrl-exynos4210";
+		reg = <0x11400000 0x1000>;
+		interrupts = <0 47 0>;
+
+		/* ... */
+
+		/* Pin bank without external interrupts */
+		gpy0: gpy0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		/* ... */
+
+		/* Pin bank with external GPIO or muxed wake-up interrupts */
+		gpj0: gpj0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		/* ... */
+
+		/* Pin bank with external direct wake-up interrupts */
+		gpx0: gpx0 {
+			gpio-controller;
+			#gpio-cells = <2>;
+
+			interrupt-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
+			#interrupt-cells = <2>;
+		};
+
+		/* ... */
+	};
+
 Example 1: A pin-controller node with pin groups.
 
 	pinctrl_0: pinctrl at 11400000 {
@@ -117,6 +188,8 @@ Example 1: A pin-controller node with pin groups.
 		reg = <0x11400000 0x1000>;
 		interrupts = <0 47 0>;
 
+		/* ... */
+
 		uart0_data: uart0-data {
 			samsung,pins = "gpa0-0", "gpa0-1";
 			samsung,pin-function = <2>;
@@ -158,20 +231,14 @@ Example 2: A pin-controller node with external wakeup interrupt controller node.
 	pinctrl_1: pinctrl at 11000000 {
 		compatible = "samsung,pinctrl-exynos4210";
 		reg = <0x11000000 0x1000>;
-		interrupts = <0 46 0>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
+		interrupts = <0 46 0>
 
-		wakup_eint: wakeup-interrupt-controller {
+		/* ... */
+
+		wakeup-interrupt-controller {
 			compatible = "samsung,exynos4210-wakeup-eint";
 			interrupt-parent = <&gic>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-					<0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-					<0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-					<0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
-					<0 32 0>;
+			interrupts = <0 32 0>;
 		};
 	};
 
@@ -190,7 +257,8 @@ Example 4: Set up the default pin state for uart controller.
 
 	static int s3c24xx_serial_probe(struct platform_device *pdev) {
 		struct pinctrl *pinctrl;
-		...
-		...
+
+		/* ... */
+
 		pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
 	}
-- 
1.7.12

^ permalink raw reply related

* [PATCH 14/15] pinctrl: samsung: Add GPIO to IRQ translation
From: Tomasz Figa @ 2012-10-11  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349943081-27939-1-git-send-email-t.figa@samsung.com>

Some drivers require a way to translate GPIO pins to their IRQ numbers.

This patch adds the .to_irq() gpiolib callback to pinctrl-samsung
driver, which creates (if not present yet) and returns an IRQ mapping
for given GPIO pin.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
 drivers/pinctrl/pinctrl-samsung.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 0a38368..0db88bb 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/irqdomain.h>
 
 #include "core.h"
 #include "pinctrl-samsung.h"
@@ -528,6 +529,23 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
 }
 
 /*
+ * gpiolib gpio_to_irq callback function. Creates a mapping between a GPIO pin
+ * and a virtual IRQ, if not already present.
+ */
+static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
+	unsigned int virq;
+
+	if (!bank->irq_domain)
+		return -ENXIO;
+
+	virq = irq_create_mapping(bank->irq_domain, offset);
+
+	return (virq) ? : -ENXIO;
+}
+
+/*
  * Parse the pin names listed in the 'samsung,pins' property and convert it
  * into a list of gpio numbers are create a pin group from it.
  */
@@ -755,6 +773,7 @@ static const struct gpio_chip samsung_gpiolib_chip = {
 	.get = samsung_gpio_get,
 	.direction_input = samsung_gpio_direction_input,
 	.direction_output = samsung_gpio_direction_output,
+	.to_irq = samsung_gpio_to_irq,
 	.owner = THIS_MODULE,
 };
 
-- 
1.7.12

^ permalink raw reply related

* [PATCH 13/15] pinctrl: exynos: Set pin function to EINT in irq_set_type of wake-up EINT
From: Tomasz Figa @ 2012-10-11  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349943081-27939-1-git-send-email-t.figa@samsung.com>

Pins used as wake-up interrupts need to be configured as EINTs. This
patch adds the required configuration code to exynos_wkup_irq_set_type,
to set the pin as EINT when its interrupt trigger type is configured.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
 drivers/pinctrl/pinctrl-exynos.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 4bf2fc4..73a0aa2 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -257,6 +257,7 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
 	unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
 	unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
 	unsigned long con, trig_type;
+	unsigned int mask;
 
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
@@ -288,6 +289,16 @@ static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
 	con &= ~(EXYNOS_EINT_CON_MASK << shift);
 	con |= trig_type << shift;
 	writel(con, d->virt_base + reg_con);
+
+	reg_con = bank->pctl_offset;
+	shift = pin * bank->func_width;
+	mask = (1 << bank->func_width) - 1;
+
+	con = readl(d->virt_base + reg_con);
+	con &= ~(mask << shift);
+	con |= EXYNOS_EINT_FUNC << shift;
+	writel(con, d->virt_base + reg_con);
+
 	return 0;
 }
 
-- 
1.7.12

^ permalink raw reply related

* [PATCH 12/15] pinctrl: samsung: Use per-bank IRQ domain for wake-up interrupts
From: Tomasz Figa @ 2012-10-11  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349943081-27939-1-git-send-email-t.figa@samsung.com>

This patch reworks wake-up interrupt handling in pinctrl-exynos driver,
so each pin bank, which provides wake-up interrupts, has its own IRQ
domain.

Information about whether given pin bank provides wake-up interrupts,
how many and whether they are separate or muxed are parsed from device
tree.

It gives following advantages:
  - interrupts can be specified in device tree in a more readable way,
    e.g. :
    	device {
		/* ... */
		interrupt-parent = <&gpx2>;
		interrupts = <4 0>;
		/* ... */
	};
  - the amount and layout of interrupts is not hardcoded in the code
    anymore, but defined in SoC-specific structure
  - bank and pin of each wake-up interrupt can be easily identified, to
    allow operations, such as setting the pin to EINT function, from
    irq_set_type() callback

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
 arch/arm/boot/dts/exynos4210-pinctrl.dtsi |   6 ++
 arch/arm/boot/dts/exynos4210.dtsi         |   8 +-
 drivers/pinctrl/pinctrl-exynos.c          | 163 ++++++++++++++++++------------
 drivers/pinctrl/pinctrl-exynos.h          |  29 +++++-
 drivers/pinctrl/pinctrl-samsung.h         |   6 +-
 5 files changed, 136 insertions(+), 76 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
index f207d8d..6a4a1a0 100644
--- a/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
+++ b/arch/arm/boot/dts/exynos4210-pinctrl.dtsi
@@ -445,6 +445,9 @@
 			#gpio-cells = <2>;
 
 			interrupt-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
+				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>;
 			#interrupt-cells = <2>;
 		};
 
@@ -453,6 +456,9 @@
 			#gpio-cells = <2>;
 
 			interrupt-controller;
+			interrupt-parent = <&gic>;
+			interrupts = <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
+				     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
 			#interrupt-cells = <2>;
 		};
 
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index c27aea7..d877dbe 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -56,13 +56,7 @@
 		wakup_eint: wakeup-interrupt-controller {
 			compatible = "samsung,exynos4210-wakeup-eint";
 			interrupt-parent = <&gic>;
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			interrupts = <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>,
-				     <0 20 0>, <0 21 0>, <0 22 0>, <0 23 0>,
-				     <0 24 0>, <0 25 0>, <0 26 0>, <0 27 0>,
-				     <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>,
-				     <0 32 0>;
+			interrupts = <0 32 0>;
 		};
 	};
 
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index be757b1..4bf2fc4 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -218,46 +218,43 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 
 static void exynos_wkup_irq_unmask(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-	unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-	unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-	unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+	struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = b->drvdata;
+	unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
 	unsigned long mask;
 
 	mask = readl(d->virt_base + reg_mask);
-	mask &= ~(1 << pin);
+	mask &= ~(1 << irqd->hwirq);
 	writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_wkup_irq_mask(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-	unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-	unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-	unsigned long reg_mask = d->ctrl->weint_mask + (bank << 2);
+	struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = b->drvdata;
+	unsigned long reg_mask = d->ctrl->weint_mask + b->eint_offset;
 	unsigned long mask;
 
 	mask = readl(d->virt_base + reg_mask);
-	mask |= 1 << pin;
+	mask |= 1 << irqd->hwirq;
 	writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_wkup_irq_ack(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-	unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-	unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-	unsigned long pend = d->ctrl->weint_pend + (bank << 2);
+	struct samsung_pin_bank *b = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = b->drvdata;
+	unsigned long pend = d->ctrl->weint_pend + b->eint_offset;
 
-	writel(1 << pin, d->virt_base + pend);
+	writel(1 << irqd->hwirq, d->virt_base + pend);
 }
 
 static int exynos_wkup_irq_set_type(struct irq_data *irqd, unsigned int type)
 {
-	struct samsung_pinctrl_drv_data *d = irq_data_get_irq_chip_data(irqd);
-	unsigned int bank = irqd->hwirq / EXYNOS_EINT_MAX_PER_BANK;
-	unsigned int pin = irqd->hwirq & (EXYNOS_EINT_MAX_PER_BANK - 1);
-	unsigned long reg_con = d->ctrl->weint_con + (bank << 2);
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned int pin = irqd->hwirq;
+	unsigned long reg_con = d->ctrl->weint_con + bank->eint_offset;
 	unsigned long shift = EXYNOS_EINT_CON_LEN * pin;
 	unsigned long con, trig_type;
 
@@ -309,6 +306,7 @@ static struct irq_chip exynos_wkup_irq_chip = {
 static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
 {
 	struct exynos_weint_data *eintd = irq_get_handler_data(irq);
+	struct samsung_pin_bank *bank = eintd->bank;
 	struct irq_chip *chip = irq_get_chip(irq);
 	int eint_irq;
 
@@ -318,20 +316,20 @@ static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
 	if (chip->irq_ack)
 		chip->irq_ack(&desc->irq_data);
 
-	eint_irq = irq_linear_revmap(eintd->domain, eintd->irq);
+	eint_irq = irq_linear_revmap(bank->irq_domain, eintd->irq);
 	generic_handle_irq(eint_irq);
 	chip->irq_unmask(&desc->irq_data);
 	chained_irq_exit(chip, desc);
 }
 
-static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend,
-					struct irq_domain *domain)
+static inline void exynos_irq_demux_eint(unsigned long pend,
+						struct irq_domain *domain)
 {
 	unsigned int irq;
 
 	while (pend) {
 		irq = fls(pend) - 1;
-		generic_handle_irq(irq_find_mapping(domain, irq_base + irq));
+		generic_handle_irq(irq_find_mapping(domain, irq));
 		pend &= ~(1 << irq);
 	}
 }
@@ -340,18 +338,22 @@ static inline void exynos_irq_demux_eint(int irq_base, unsigned long pend,
 static void exynos_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
 {
 	struct irq_chip *chip = irq_get_chip(irq);
-	struct exynos_weint_data *eintd = irq_get_handler_data(irq);
-	struct samsung_pinctrl_drv_data *d = eintd->domain->host_data;
+	struct exynos_muxed_weint_data *eintd = irq_get_handler_data(irq);
+	struct samsung_pinctrl_drv_data *d = eintd->banks[0]->drvdata;
+	struct samsung_pin_ctrl *ctrl = d->ctrl;
 	unsigned long pend;
 	unsigned long mask;
+	int i;
 
 	chained_irq_enter(chip, desc);
-	pend = readl(d->virt_base + d->ctrl->weint_pend + 0x8);
-	mask = readl(d->virt_base + d->ctrl->weint_mask + 0x8);
-	exynos_irq_demux_eint(16, pend & ~mask, eintd->domain);
-	pend = readl(d->virt_base + d->ctrl->weint_pend + 0xC);
-	mask = readl(d->virt_base + d->ctrl->weint_mask + 0xC);
-	exynos_irq_demux_eint(24, pend & ~mask, eintd->domain);
+
+	for (i = 0; i < eintd->nr_banks; ++i) {
+		struct samsung_pin_bank *b = eintd->banks[i];
+		pend = readl(d->virt_base + ctrl->weint_pend + b->eint_offset);
+		mask = readl(d->virt_base + ctrl->weint_mask + b->eint_offset);
+		exynos_irq_demux_eint(pend & ~mask, b->irq_domain);
+	}
+
 	chained_irq_exit(chip, desc);
 }
 
@@ -381,7 +383,11 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 	struct device *dev = d->dev;
 	struct device_node *wkup_np = NULL;
 	struct device_node *np;
+	struct samsung_pin_bank *bank;
 	struct exynos_weint_data *weint_data;
+	struct exynos_muxed_weint_data *muxed_data;
+	unsigned int muxed_banks = 0;
+	unsigned int i;
 	int idx, irq;
 
 	for_each_child_of_node(dev->of_node, np) {
@@ -393,40 +399,74 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 	if (!wkup_np)
 		return -ENODEV;
 
-	d->wkup_irqd = irq_domain_add_linear(wkup_np, d->ctrl->nr_wint,
-				&exynos_wkup_irqd_ops, d);
-	if (!d->wkup_irqd) {
-		dev_err(dev, "wakeup irq domain allocation failed\n");
-		return -ENXIO;
-	}
+	bank = d->ctrl->pin_banks;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_WKUP)
+			continue;
 
-	weint_data = devm_kzalloc(dev, sizeof(*weint_data) * 17, GFP_KERNEL);
-	if (!weint_data) {
-		dev_err(dev, "could not allocate memory for weint_data\n");
-		return -ENOMEM;
-	}
+		bank->irq_domain = irq_domain_add_linear(bank->of_node,
+				bank->nr_pins, &exynos_wkup_irqd_ops, bank);
+		if (!bank->irq_domain) {
+			dev_err(dev, "wkup irq domain add failed\n");
+			return -ENXIO;
+		}
 
-	irq = irq_of_parse_and_map(wkup_np, 16);
-	if (irq) {
-		weint_data[16].domain = d->wkup_irqd;
-		irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
-		irq_set_handler_data(irq, &weint_data[16]);
-	} else {
-		dev_err(dev, "irq number for EINT16-32 not found\n");
-	}
+		if (!of_find_property(bank->of_node, "interrupts", NULL)) {
+			bank->eint_type = EINT_TYPE_WKUP_MUX;
+			++muxed_banks;
+			continue;
+		}
 
-	for (idx = 0; idx < 16; idx++) {
-		weint_data[idx].domain = d->wkup_irqd;
-		weint_data[idx].irq = idx;
+		weint_data = devm_kzalloc(dev, bank->nr_pins
+					* sizeof(*weint_data), GFP_KERNEL);
+		if (!weint_data) {
+			dev_err(dev, "could not allocate memory for weint_data\n");
+			return -ENOMEM;
+		}
 
-		irq = irq_of_parse_and_map(wkup_np, idx);
-		if (irq) {
+		for (idx = 0; idx < bank->nr_pins; ++idx) {
+			irq = irq_of_parse_and_map(bank->of_node, idx);
+			if (!irq) {
+				dev_err(dev, "irq number for eint-%s-%d not found\n",
+							bank->name, idx);
+				continue;
+			}
+			weint_data[idx].irq = idx;
+			weint_data[idx].bank = bank;
 			irq_set_handler_data(irq, &weint_data[idx]);
 			irq_set_chained_handler(irq, exynos_irq_eint0_15);
-		} else {
-			dev_err(dev, "irq number for eint-%x not found\n", idx);
 		}
 	}
+
+	if (!muxed_banks)
+		return 0;
+
+	irq = irq_of_parse_and_map(wkup_np, 0);
+	if (!irq) {
+		dev_err(dev, "irq number for muxed EINTs not found\n");
+		return 0;
+	}
+
+	muxed_data = devm_kzalloc(dev, sizeof(*muxed_data)
+		+ muxed_banks*sizeof(struct samsung_pin_bank *), GFP_KERNEL);
+	if (!muxed_data) {
+		dev_err(dev, "could not allocate memory for muxed_data\n");
+		return -ENOMEM;
+	}
+
+	irq_set_chained_handler(irq, exynos_irq_demux_eint16_31);
+	irq_set_handler_data(irq, muxed_data);
+
+	bank = d->ctrl->pin_banks;
+	idx = 0;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_WKUP_MUX)
+			continue;
+
+		muxed_data->banks[idx++] = bank;
+	}
+	muxed_data->nr_banks = muxed_banks;
+
 	return 0;
 }
 
@@ -468,10 +508,10 @@ static struct samsung_pin_bank exynos4210_pin_banks1[] = {
 	EXYNOS_PIN_BANK_EINTN(8, 0x1A0, "gpy4"),
 	EXYNOS_PIN_BANK_EINTN(8, 0x1C0, "gpy5"),
 	EXYNOS_PIN_BANK_EINTN(8, 0x1E0, "gpy6"),
-	EXYNOS_PIN_BANK_EINTN(8, 0xC00, "gpx0"),
-	EXYNOS_PIN_BANK_EINTN(8, 0xC20, "gpx1"),
-	EXYNOS_PIN_BANK_EINTN(8, 0xC40, "gpx2"),
-	EXYNOS_PIN_BANK_EINTN(8, 0xC60, "gpx3"),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+	EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
 };
 
 /* pin banks of exynos4210 pin-controller 2 */
@@ -498,7 +538,6 @@ struct samsung_pin_ctrl exynos4210_pin_ctrl[] = {
 		/* pin-controller instance 1 data */
 		.pin_banks	= exynos4210_pin_banks1,
 		.nr_banks	= ARRAY_SIZE(exynos4210_pin_banks1),
-		.nr_wint	= 32,
 		.geint_con	= EXYNOS_GPIO_ECON_OFFSET,
 		.geint_mask	= EXYNOS_GPIO_EMASK_OFFSET,
 		.geint_pend	= EXYNOS_GPIO_EPEND_OFFSET,
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
index f05efa0..0a70889 100644
--- a/drivers/pinctrl/pinctrl-exynos.h
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -73,13 +73,36 @@
 		.name		= id			\
 	}
 
+#define EXYNOS_PIN_BANK_EINTW(pins, reg, id, offs)	\
+	{						\
+		.pctl_offset	= reg,			\
+		.nr_pins	= pins,			\
+		.func_width	= 4,			\
+		.pud_width	= 2,			\
+		.drv_width	= 2,			\
+		.eint_type	= EINT_TYPE_WKUP,	\
+		.eint_offset	= offs,			\
+		.name		= id			\
+	}
+
 /**
  * struct exynos_weint_data: irq specific data for all the wakeup interrupts
  * generated by the external wakeup interrupt controller.
- * @domain: irq domain representing the external wakeup interrupts
  * @irq: interrupt number within the domain.
+ * @bank: bank responsible for this interrupt
  */
 struct exynos_weint_data {
-	struct irq_domain	*domain;
-	u32			irq;
+	unsigned int irq;
+	struct samsung_pin_bank *bank;
+};
+
+/**
+ * struct exynos_muxed_weint_data: irq specific data for muxed wakeup interrupts
+ * generated by the external wakeup interrupt controller.
+ * @nr_banks: count of banks being part of the mux
+ * @banks: array of banks being part of the mux
+ */
+struct exynos_muxed_weint_data {
+	unsigned int nr_banks;
+	struct samsung_pin_bank *banks[];
 };
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index dac40ff..0670d9e 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -66,6 +66,7 @@ enum pincfg_type {
  * @EINT_TYPE_NONE: bank does not support external interrupts
  * @EINT_TYPE_GPIO: bank supportes external gpio interrupts
  * @EINT_TYPE_WKUP: bank supportes external wakeup interrupts
+ * @EINT_TYPE_WKUP_MUX: bank supports multiplexed external wakeup interrupts
  *
  * Samsung GPIO controller groups all the available pins into banks. The pins
  * in a pin bank can support external gpio interrupts or external wakeup
@@ -78,6 +79,7 @@ enum eint_type {
 	EINT_TYPE_NONE,
 	EINT_TYPE_GPIO,
 	EINT_TYPE_WKUP,
+	EINT_TYPE_WKUP_MUX,
 };
 
 /* maximum length of a pin in pin descriptor (example: "gpa0-0") */
@@ -143,7 +145,6 @@ struct samsung_pin_bank {
  * @nr_banks: number of pin banks.
  * @base: starting system wide pin number.
  * @nr_pins: number of pins supported by the controller.
- * @nr_wint: number of external wakeup interrupts supported.
  * @geint_con: offset of the ext-gpio controller registers.
  * @geint_mask: offset of the ext-gpio interrupt mask registers.
  * @geint_pend: offset of the ext-gpio interrupt pending registers.
@@ -163,7 +164,6 @@ struct samsung_pin_ctrl {
 
 	u32		base;
 	u32		nr_pins;
-	u32		nr_wint;
 
 	u32		geint_con;
 	u32		geint_mask;
@@ -206,8 +206,6 @@ struct samsung_pinctrl_drv_data {
 	unsigned int			nr_groups;
 	const struct samsung_pmx_func	*pmx_functions;
 	unsigned int			nr_functions;
-
-	struct irq_domain		*wkup_irqd;
 };
 
 /**
-- 
1.7.12

^ permalink raw reply related

* [PATCH 11/15] pinctrl: samsung: Use one GPIO chip per pin bank
From: Tomasz Figa @ 2012-10-11  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349943081-27939-1-git-send-email-t.figa@samsung.com>

This patch modifies the pinctrl-samsung driver to register one GPIO chip
per pin bank, instead of a single chip for all pin banks of the
controller.

It simplifies GPIO accesses a lot (constant time instead of looping
through the list of banks to find the right one) and should have a good
effect on performance of any bit-banging driver.

In addition it allows to reference GPIO pins by a phandle to the bank
node and a local pin offset inside of the bank (similar to previous
gpiolib driver), which is more clear and readable than using indices
relative to the whole pin controller.

Example:
	device {
		/* ... */
		gpios = <&gpk0 4 0>;
		/* ... */
	};

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
 drivers/pinctrl/pinctrl-samsung.c | 117 ++++++++++++++++++++++++--------------
 drivers/pinctrl/pinctrl-samsung.h |  11 ++--
 2 files changed, 79 insertions(+), 49 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index e1ef5d2..0a38368 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -48,6 +48,11 @@ struct pin_config {
 
 static unsigned int pin_base = 0;
 
+static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
+{
+	return container_of(gc, struct samsung_pin_bank, gpio_chip);
+}
+
 /* check if the selector is a valid pin group selector */
 static int samsung_get_group_count(struct pinctrl_dev *pctldev)
 {
@@ -333,9 +338,12 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
 	void __iomem *reg;
 	u32 data, pin_offset, mask, shift;
 
+	bank = gc_to_pin_bank(range->gc);
 	drvdata = pinctrl_dev_get_drvdata(pctldev);
 
-	pin_to_reg_bank(drvdata, offset, &reg, &pin_offset, &bank);
+	pin_offset = offset - bank->pin_base;
+	reg = drvdata->virt_base + bank->pctl_offset;
+
 	mask = (1 << bank->func_width) - 1;
 	shift = pin_offset * bank->func_width;
 
@@ -469,17 +477,16 @@ static struct pinconf_ops samsung_pinconf_ops = {
 /* gpiolib gpio_set callback function */
 static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 {
+	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
 	void __iomem *reg;
-	u32 pin_offset, data;
-	struct samsung_pinctrl_drv_data *drvdata;
+	u32 data;
 
-	drvdata = dev_get_drvdata(gc->dev);
+	reg = bank->drvdata->virt_base + bank->pctl_offset;
 
-	pin_to_reg_bank(drvdata, offset, &reg, &pin_offset, NULL);
 	data = readl(reg + DAT_REG);
-	data &= ~(1 << pin_offset);
+	data &= ~(1 << offset);
 	if (value)
-		data |= 1 << pin_offset;
+		data |= 1 << offset;
 	writel(data, reg + DAT_REG);
 }
 
@@ -487,14 +494,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
 static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
 {
 	void __iomem *reg;
-	u32 pin_offset, data;
-	struct samsung_pinctrl_drv_data *drvdata;
+	u32 data;
+	struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
 
-	drvdata = dev_get_drvdata(gc->dev);
+	reg = bank->drvdata->virt_base + bank->pctl_offset;
 
-	pin_to_reg_bank(drvdata, offset, &reg, &pin_offset, NULL);
 	data = readl(reg + DAT_REG);
-	data >>= pin_offset;
+	data >>= offset;
 	data &= 1;
 	return data;
 }
@@ -724,12 +730,16 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
-	drvdata->grange.name = "samsung-pctrl-gpio-range";
-	drvdata->grange.id = 0;
-	drvdata->grange.base = drvdata->ctrl->base;
-	drvdata->grange.npins = drvdata->ctrl->nr_pins;
-	drvdata->grange.gc = drvdata->gc;
-	pinctrl_add_gpio_range(drvdata->pctl_dev, &drvdata->grange);
+	for (bank = 0; bank < drvdata->ctrl->nr_banks; ++bank) {
+		pin_bank = &drvdata->ctrl->pin_banks[bank];
+		pin_bank->grange.name = pin_bank->name;
+		pin_bank->grange.id = bank;
+		pin_bank->grange.pin_base = pin_bank->pin_base;
+		pin_bank->grange.base = pin_bank->gpio_chip.base;
+		pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
+		pin_bank->grange.gc = &pin_bank->gpio_chip;
+		pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
+	}
 
 	ret = samsung_pinctrl_parse_dt(pdev, drvdata);
 	if (ret) {
@@ -740,49 +750,68 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev,
 	return 0;
 }
 
+static const struct gpio_chip samsung_gpiolib_chip = {
+	.set = samsung_gpio_set,
+	.get = samsung_gpio_get,
+	.direction_input = samsung_gpio_direction_input,
+	.direction_output = samsung_gpio_direction_output,
+	.owner = THIS_MODULE,
+};
+
 /* register the gpiolib interface with the gpiolib subsystem */
 static int __init samsung_gpiolib_register(struct platform_device *pdev,
 				struct samsung_pinctrl_drv_data *drvdata)
 {
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	struct samsung_pin_bank *bank = ctrl->pin_banks;
 	struct gpio_chip *gc;
 	int ret;
+	int i;
 
-	gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL);
-	if (!gc) {
-		dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n");
-		return -ENOMEM;
-	}
-
-	drvdata->gc = gc;
-	gc->base = drvdata->ctrl->base;
-	gc->ngpio = drvdata->ctrl->nr_pins;
-	gc->dev = &pdev->dev;
-	gc->set = samsung_gpio_set;
-	gc->get = samsung_gpio_get;
-	gc->direction_input = samsung_gpio_direction_input;
-	gc->direction_output = samsung_gpio_direction_output;
-	gc->label = drvdata->ctrl->label;
-	gc->owner = THIS_MODULE;
-	ret = gpiochip_add(gc);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
-					"code: %d\n", gc->label, ret);
-		return ret;
+	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+		bank->gpio_chip = samsung_gpiolib_chip;
+
+		gc = &bank->gpio_chip;
+		gc->base = ctrl->base + bank->pin_base;
+		gc->ngpio = bank->nr_pins;
+		gc->dev = &pdev->dev;
+		gc->of_node = bank->of_node;
+		gc->label = bank->name;
+
+		ret = gpiochip_add(gc);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
+							gc->label, ret);
+			goto fail;
+		}
 	}
 
 	return 0;
+
+fail:
+	for (--i, --bank; i >= 0; --i, --bank)
+		if (gpiochip_remove(&bank->gpio_chip))
+			dev_err(&pdev->dev, "gpio chip %s remove failed\n",
+							bank->gpio_chip.label);
+	return ret;
 }
 
 /* unregister the gpiolib interface with the gpiolib subsystem */
 static int __init samsung_gpiolib_unregister(struct platform_device *pdev,
 				struct samsung_pinctrl_drv_data *drvdata)
 {
-	int ret = gpiochip_remove(drvdata->gc);
-	if (ret) {
+	struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
+	struct samsung_pin_bank *bank = ctrl->pin_banks;
+	int ret = 0;
+	int i;
+
+	for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank)
+		ret = gpiochip_remove(&bank->gpio_chip);
+
+	if (ret)
 		dev_err(&pdev->dev, "gpio chip remove failed\n");
-		return ret;
-	}
-	return 0;
+
+	return ret;
 }
 
 static const struct of_device_id samsung_pinctrl_dt_match[];
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index e56be22..dac40ff 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -23,6 +23,8 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/pinctrl/machine.h>
 
+#include <linux/gpio.h>
+
 /* register offsets within a pin bank */
 #define DAT_REG		0x4
 #define PUD_REG		0x8
@@ -113,6 +115,8 @@ struct samsung_pinctrl_drv_data;
  * @of_node: OF node of the bank.
  * @drvdata: link to controller driver data
  * @irq_domain: IRQ domain of the bank.
+ * @gpio_chip: GPIO chip of the bank.
+ * @grange: linux gpio pin range supported by this bank.
  */
 struct samsung_pin_bank {
 	u32		pctl_offset;
@@ -129,6 +133,8 @@ struct samsung_pin_bank {
 	struct device_node *of_node;
 	struct samsung_pinctrl_drv_data *drvdata;
 	struct irq_domain *irq_domain;
+	struct gpio_chip gpio_chip;
+	struct pinctrl_gpio_range grange;
 };
 
 /**
@@ -186,8 +192,6 @@ struct samsung_pin_ctrl {
  * @nr_groups: number of such pin groups.
  * @pmx_functions: list of pin functions available to the driver.
  * @nr_function: number of such pin functions.
- * @gc: gpio_chip instance registered with gpiolib.
- * @grange: linux gpio pin range supported by this controller.
  */
 struct samsung_pinctrl_drv_data {
 	void __iomem			*virt_base;
@@ -204,9 +208,6 @@ struct samsung_pinctrl_drv_data {
 	unsigned int			nr_functions;
 
 	struct irq_domain		*wkup_irqd;
-
-	struct gpio_chip		*gc;
-	struct pinctrl_gpio_range	grange;
 };
 
 /**
-- 
1.7.12

^ permalink raw reply related

* [PATCH 10/15] pinctrl: exynos: Use one IRQ domain per pin bank
From: Tomasz Figa @ 2012-10-11  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349943081-27939-1-git-send-email-t.figa@samsung.com>

Instead of registering one IRQ domain for all pin banks of a pin
controller, this patch implements registration of per-bank domains.

At a cost of a little memory overhead (~2.5KiB for all GPIO interrupts
of Exynos4x12) it simplifies driver code and device tree sources,
because GPIO interrupts can be now specified per banks.

Example:
	device {
		/* ... */
		interrupt-parent = <&gpa1>;
		interrupts = <3 0>;
		/* ... */
	};

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
 arch/arm/boot/dts/exynos4210.dtsi |   4 --
 drivers/pinctrl/pinctrl-exynos.c  | 117 +++++++++++---------------------------
 drivers/pinctrl/pinctrl-exynos.h  |  12 ----
 drivers/pinctrl/pinctrl-samsung.c |   4 --
 drivers/pinctrl/pinctrl-samsung.h |   7 +--
 5 files changed, 35 insertions(+), 109 deletions(-)

diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index b768e9f..c27aea7 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -46,16 +46,12 @@
 		compatible = "samsung,pinctrl-exynos4210";
 		reg = <0x11400000 0x1000>;
 		interrupts = <0 47 0>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
 	};
 
 	pinctrl_1: pinctrl at 11000000 {
 		compatible = "samsung,pinctrl-exynos4210";
 		reg = <0x11000000 0x1000>;
 		interrupts = <0 46 0>;
-		interrupt-controller;
-		#interrupt-cells = <2>;
 
 		wakup_eint: wakeup-interrupt-controller {
 			compatible = "samsung,exynos4210-wakeup-eint";
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index bd9f130..be757b1 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -40,46 +40,46 @@ static const struct of_device_id exynos_wkup_irq_ids[] = {
 
 static void exynos_gpio_irq_unmask(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
-	struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-	unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
 	unsigned long mask;
 
 	mask = readl(d->virt_base + reg_mask);
-	mask &= ~(1 << edata->pin);
+	mask &= ~(1 << irqd->hwirq);
 	writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_gpio_irq_mask(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
-	struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-	unsigned long reg_mask = d->ctrl->geint_mask + edata->eint_offset;
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long reg_mask = d->ctrl->geint_mask + bank->eint_offset;
 	unsigned long mask;
 
 	mask = readl(d->virt_base + reg_mask);
-	mask |= 1 << edata->pin;
+	mask |= 1 << irqd->hwirq;
 	writel(mask, d->virt_base + reg_mask);
 }
 
 static void exynos_gpio_irq_ack(struct irq_data *irqd)
 {
-	struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
-	struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-	unsigned long reg_pend = d->ctrl->geint_pend + edata->eint_offset;
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
+	unsigned long reg_pend = d->ctrl->geint_pend + bank->eint_offset;
 
-	writel(1 << edata->pin, d->virt_base + reg_pend);
+	writel(1 << irqd->hwirq, d->virt_base + reg_pend);
 }
 
 static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
 {
-	struct samsung_pinctrl_drv_data *d = irqd->domain->host_data;
+	struct samsung_pin_bank *bank = irq_data_get_irq_chip_data(irqd);
+	struct samsung_pinctrl_drv_data *d = bank->drvdata;
 	struct samsung_pin_ctrl *ctrl = d->ctrl;
-	struct exynos_geint_data *edata = irq_data_get_irq_handler_data(irqd);
-	struct samsung_pin_bank *bank = edata->bank;
-	unsigned int shift = EXYNOS_EINT_CON_LEN * edata->pin;
+	unsigned int pin = irqd->hwirq;
+	unsigned int shift = EXYNOS_EINT_CON_LEN * pin;
 	unsigned int con, trig_type;
-	unsigned long reg_con = ctrl->geint_con + edata->eint_offset;
+	unsigned long reg_con = ctrl->geint_con + bank->eint_offset;
 	unsigned int mask;
 
 	switch (type) {
@@ -114,7 +114,7 @@ static int exynos_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
 	writel(con, d->virt_base + reg_con);
 
 	reg_con = bank->pctl_offset;
-	shift = edata->pin * bank->func_width;
+	shift = pin * bank->func_width;
 	mask = (1 << bank->func_width) - 1;
 
 	con = readl(d->virt_base + reg_con);
@@ -136,81 +136,23 @@ static struct irq_chip exynos_gpio_irq_chip = {
 	.irq_set_type	= exynos_gpio_irq_set_type,
 };
 
-/*
- * given a controller-local external gpio interrupt number, prepare the handler
- * data for it.
- */
-static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
-				struct samsung_pinctrl_drv_data *d)
-{
-	struct samsung_pin_bank *bank = d->ctrl->pin_banks;
-	struct exynos_geint_data *eint_data;
-	unsigned int nr_banks = d->ctrl->nr_banks, idx;
-	unsigned int irq_base = 0;
-
-	if (hw >= d->ctrl->nr_gint) {
-		dev_err(d->dev, "unsupported ext-gpio interrupt\n");
-		return NULL;
-	}
-
-	for (idx = 0; idx < nr_banks; idx++, bank++) {
-		if (bank->eint_type != EINT_TYPE_GPIO)
-			continue;
-		if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))
-			break;
-		irq_base += bank->nr_pins;
-	}
-
-	if (idx == nr_banks) {
-		dev_err(d->dev, "pin bank not found for ext-gpio interrupt\n");
-		return NULL;
-	}
-
-	eint_data = devm_kzalloc(d->dev, sizeof(*eint_data), GFP_KERNEL);
-	if (!eint_data) {
-		dev_err(d->dev, "no memory for eint-gpio data\n");
-		return NULL;
-	}
-
-	eint_data->bank	= bank;
-	eint_data->pin = hw - irq_base;
-	eint_data->eint_offset = bank->eint_offset;
-	return eint_data;
-}
-
 static int exynos_gpio_irq_map(struct irq_domain *h, unsigned int virq,
 					irq_hw_number_t hw)
 {
-	struct samsung_pinctrl_drv_data *d = h->host_data;
-	struct exynos_geint_data *eint_data;
-
-	eint_data = exynos_get_eint_data(hw, d);
-	if (!eint_data)
-		return -EINVAL;
+	struct samsung_pin_bank *b = h->host_data;
 
-	irq_set_handler_data(virq, eint_data);
-	irq_set_chip_data(virq, h->host_data);
+	irq_set_chip_data(virq, b);
 	irq_set_chip_and_handler(virq, &exynos_gpio_irq_chip,
 					handle_level_irq);
 	set_irq_flags(virq, IRQF_VALID);
 	return 0;
 }
 
-static void exynos_gpio_irq_unmap(struct irq_domain *h, unsigned int virq)
-{
-	struct samsung_pinctrl_drv_data *d = h->host_data;
-	struct exynos_geint_data *eint_data;
-
-	eint_data = irq_get_handler_data(virq);
-	devm_kfree(d->dev, eint_data);
-}
-
 /*
  * irq domain callbacks for external gpio interrupt controller.
  */
 static const struct irq_domain_ops exynos_gpio_irqd_ops = {
 	.map	= exynos_gpio_irq_map,
-	.unmap	= exynos_gpio_irq_unmap,
 	.xlate	= irq_domain_xlate_twocell,
 };
 
@@ -229,7 +171,7 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
 		return IRQ_HANDLED;
 	bank += (group - 1);
 
-	virq = irq_linear_revmap(d->gpio_irqd, bank->irq_base + pin);
+	virq = irq_linear_revmap(bank->irq_domain, pin);
 	if (!virq)
 		return IRQ_NONE;
 	generic_handle_irq(virq);
@@ -242,8 +184,10 @@ static irqreturn_t exynos_eint_gpio_irq(int irq, void *data)
  */
 static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 {
+	struct samsung_pin_bank *bank;
 	struct device *dev = d->dev;
 	unsigned int ret;
+	unsigned int i;
 
 	if (!d->irq) {
 		dev_err(dev, "irq number not available\n");
@@ -257,11 +201,16 @@ static int exynos_eint_gpio_init(struct samsung_pinctrl_drv_data *d)
 		return -ENXIO;
 	}
 
-	d->gpio_irqd = irq_domain_add_linear(dev->of_node, d->ctrl->nr_gint,
-				&exynos_gpio_irqd_ops, d);
-	if (!d->gpio_irqd) {
-		dev_err(dev, "gpio irq domain allocation failed\n");
-		return -ENXIO;
+	bank = d->ctrl->pin_banks;
+	for (i = 0; i < d->ctrl->nr_banks; ++i, ++bank) {
+		if (bank->eint_type != EINT_TYPE_GPIO)
+			continue;
+		bank->irq_domain = irq_domain_add_linear(bank->of_node,
+				bank->nr_pins, &exynos_gpio_irqd_ops, bank);
+		if (!bank->irq_domain) {
+			dev_err(dev, "gpio irq domain add failed\n");
+			return -ENXIO;
+		}
 	}
 
 	return 0;
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
index 5d8e380..f05efa0 100644
--- a/drivers/pinctrl/pinctrl-exynos.h
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -74,18 +74,6 @@
 	}
 
 /**
- * struct exynos_geint_data: gpio eint specific data for irq_chip callbacks.
- * @bank: pin bank from which this gpio interrupt originates.
- * @pin: pin number within the bank.
- * @eint_offset: offset to be added to the con/pend/mask register bank base.
- */
-struct exynos_geint_data {
-	struct samsung_pin_bank	*bank;
-	u32			pin;
-	u32			eint_offset;
-};
-
-/**
  * struct exynos_weint_data: irq specific data for all the wakeup interrupts
  * generated by the external wakeup interrupt controller.
  * @domain: irq domain representing the external wakeup interrupts
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index 53493c3..e1ef5d2 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -813,10 +813,6 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
 		bank->drvdata = d;
 		bank->pin_base = ctrl->nr_pins;
 		ctrl->nr_pins += bank->nr_pins;
-		if (bank->eint_type == EINT_TYPE_GPIO) {
-			bank->irq_base = ctrl->nr_gint;
-			ctrl->nr_gint += bank->nr_pins;
-		}
 	}
 
 	for_each_child_of_node(node, np) {
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index d77d9bc..e56be22 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -109,10 +109,10 @@ struct samsung_pinctrl_drv_data;
  * @conpdn_width: width of the sleep mode function selector bin field.
  * @pudpdn_width: width of the sleep mode pull up/down selector bit field.
  * @eint_type: type of the external interrupt supported by the bank.
- * @irq_base: starting controller local irq number of the bank.
  * @name: name to be prefixed for each pin in this pin bank.
  * @of_node: OF node of the bank.
  * @drvdata: link to controller driver data
+ * @irq_domain: IRQ domain of the bank.
  */
 struct samsung_pin_bank {
 	u32		pctl_offset;
@@ -125,10 +125,10 @@ struct samsung_pin_bank {
 	u8		pudpdn_width;
 	enum eint_type	eint_type;
 	u32		eint_offset;
-	u32		irq_base;
 	char		*name;
 	struct device_node *of_node;
 	struct samsung_pinctrl_drv_data *drvdata;
+	struct irq_domain *irq_domain;
 };
 
 /**
@@ -137,7 +137,6 @@ struct samsung_pin_bank {
  * @nr_banks: number of pin banks.
  * @base: starting system wide pin number.
  * @nr_pins: number of pins supported by the controller.
- * @nr_gint: number of external gpio interrupts supported.
  * @nr_wint: number of external wakeup interrupts supported.
  * @geint_con: offset of the ext-gpio controller registers.
  * @geint_mask: offset of the ext-gpio interrupt mask registers.
@@ -158,7 +157,6 @@ struct samsung_pin_ctrl {
 
 	u32		base;
 	u32		nr_pins;
-	u32		nr_gint;
 	u32		nr_wint;
 
 	u32		geint_con;
@@ -205,7 +203,6 @@ struct samsung_pinctrl_drv_data {
 	const struct samsung_pmx_func	*pmx_functions;
 	unsigned int			nr_functions;
 
-	struct irq_domain		*gpio_irqd;
 	struct irq_domain		*wkup_irqd;
 
 	struct gpio_chip		*gc;
-- 
1.7.12

^ permalink raw reply related

* [PATCH 09/15] pinctrl: samsung: Include bank-specific eint offset in bank struct
From: Tomasz Figa @ 2012-10-11  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349943081-27939-1-git-send-email-t.figa@samsung.com>

Some SoCs, like Exynos4x12, have non-sequential layout of EINT control
registers and so current way of calculating register addresses does not
work correctly for them.

This patch adds eint_offset field to samsung_pin_bank struct and
modifies the driver to use it instead of calculating the offsets from
bank index.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
 drivers/pinctrl/pinctrl-exynos.c  | 55 +++++++++++++++++++--------------------
 drivers/pinctrl/pinctrl-exynos.h  |  3 ++-
 drivers/pinctrl/pinctrl-samsung.h |  1 +
 3 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c
index 0ea2164..bd9f130 100644
--- a/drivers/pinctrl/pinctrl-exynos.c
+++ b/drivers/pinctrl/pinctrl-exynos.c
@@ -146,7 +146,7 @@ static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
 	struct samsung_pin_bank *bank = d->ctrl->pin_banks;
 	struct exynos_geint_data *eint_data;
 	unsigned int nr_banks = d->ctrl->nr_banks, idx;
-	unsigned int irq_base = 0, eint_offset = 0;
+	unsigned int irq_base = 0;
 
 	if (hw >= d->ctrl->nr_gint) {
 		dev_err(d->dev, "unsupported ext-gpio interrupt\n");
@@ -159,7 +159,6 @@ static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
 		if ((hw >= irq_base) && (hw < (irq_base + bank->nr_pins)))
 			break;
 		irq_base += bank->nr_pins;
-		eint_offset += 4;
 	}
 
 	if (idx == nr_banks) {
@@ -175,7 +174,7 @@ static struct exynos_geint_data *exynos_get_eint_data(irq_hw_number_t hw,
 
 	eint_data->bank	= bank;
 	eint_data->pin = hw - irq_base;
-	eint_data->eint_offset = eint_offset;
+	eint_data->eint_offset = bank->eint_offset;
 	return eint_data;
 }
 
@@ -484,35 +483,35 @@ static int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
 
 /* pin banks of exynos4210 pin-controller 0 */
 static struct samsung_pin_bank exynos4210_pin_banks0[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0"),
-	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb"),
-	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0"),
-	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1"),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0"),
-	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1"),
-	EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1"),
-	EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2"),
-	EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3"),
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpb", 0x08),
+	EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpc0", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpc1", 0x10),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpd0", 0x14),
+	EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpd1", 0x18),
+	EXYNOS_PIN_BANK_EINTG(5, 0x0E0, "gpe0", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpe1", 0x20),
+	EXYNOS_PIN_BANK_EINTG(6, 0x120, "gpe2", 0x24),
+	EXYNOS_PIN_BANK_EINTG(8, 0x140, "gpe3", 0x28),
+	EXYNOS_PIN_BANK_EINTG(8, 0x160, "gpe4", 0x2c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpf0", 0x30),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpf1", 0x34),
+	EXYNOS_PIN_BANK_EINTG(8, 0x1C0, "gpf2", 0x38),
+	EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf3", 0x3c),
 };
 
 /* pin banks of exynos4210 pin-controller 1 */
 static struct samsung_pin_bank exynos4210_pin_banks1[] = {
-	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0"),
-	EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1"),
-	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0"),
-	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1"),
-	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2"),
-	EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0"),
-	EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1"),
-	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2"),
+	EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpj0", 0x00),
+	EXYNOS_PIN_BANK_EINTG(5, 0x020, "gpj1", 0x04),
+	EXYNOS_PIN_BANK_EINTG(7, 0x040, "gpk0", 0x08),
+	EXYNOS_PIN_BANK_EINTG(7, 0x060, "gpk1", 0x0c),
+	EXYNOS_PIN_BANK_EINTG(7, 0x080, "gpk2", 0x10),
+	EXYNOS_PIN_BANK_EINTG(7, 0x0A0, "gpk3", 0x14),
+	EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpl0", 0x18),
+	EXYNOS_PIN_BANK_EINTG(3, 0x0E0, "gpl1", 0x1c),
+	EXYNOS_PIN_BANK_EINTG(8, 0x100, "gpl2", 0x20),
 	EXYNOS_PIN_BANK_EINTN(6, 0x120, "gpy0"),
 	EXYNOS_PIN_BANK_EINTN(4, 0x140, "gpy1"),
 	EXYNOS_PIN_BANK_EINTN(6, 0x160, "gpy2"),
diff --git a/drivers/pinctrl/pinctrl-exynos.h b/drivers/pinctrl/pinctrl-exynos.h
index 2de4a29..5d8e380 100644
--- a/drivers/pinctrl/pinctrl-exynos.h
+++ b/drivers/pinctrl/pinctrl-exynos.h
@@ -59,7 +59,7 @@
 		.name		= id			\
 	}
 
-#define EXYNOS_PIN_BANK_EINTG(pins, reg, id)		\
+#define EXYNOS_PIN_BANK_EINTG(pins, reg, id, offs)	\
 	{						\
 		.pctl_offset	= reg,			\
 		.nr_pins	= pins,			\
@@ -69,6 +69,7 @@
 		.conpdn_width	= 2,			\
 		.pudpdn_width	= 2,			\
 		.eint_type	= EINT_TYPE_GPIO,	\
+		.eint_offset	= offs,			\
 		.name		= id			\
 	}
 
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index ea5dadd..d77d9bc 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -124,6 +124,7 @@ struct samsung_pin_bank {
 	u8		conpdn_width;
 	u8		pudpdn_width;
 	enum eint_type	eint_type;
+	u32		eint_offset;
 	u32		irq_base;
 	char		*name;
 	struct device_node *of_node;
-- 
1.7.12

^ permalink raw reply related

* [PATCH 08/15] pinctrl: samsung: Hold pointer to driver data in bank struct
From: Tomasz Figa @ 2012-10-11  8:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1349943081-27939-1-git-send-email-t.figa@samsung.com>

This patch is a preparation for converting the pinctrl-samsung driver to
one GPIO chip and IRQ domain per bank. It allows one having only
a pointer to particular bank struct to access driver data struct.

Signed-off-by: Tomasz Figa <t.figa@samsung.com>
---
 drivers/pinctrl/pinctrl-samsung.c | 18 ++++++++++--------
 drivers/pinctrl/pinctrl-samsung.h |  2 ++
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index f266710..53493c3 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -789,17 +789,18 @@ static const struct of_device_id samsung_pinctrl_dt_match[];
 
 /* retrieve the soc specific data */
 static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
+				struct samsung_pinctrl_drv_data *d,
 				struct platform_device *pdev)
 {
 	int id;
 	const struct of_device_id *match;
-	const struct device_node *node = pdev->dev.of_node;
+	struct device_node *node = pdev->dev.of_node;
 	struct device_node *np;
 	struct samsung_pin_ctrl *ctrl;
 	struct samsung_pin_bank *bank;
 	int i;
 
-	id = of_alias_get_id(pdev->dev.of_node, "pinctrl");
+	id = of_alias_get_id(node, "pinctrl");
 	if (id < 0) {
 		dev_err(&pdev->dev, "failed to get alias id\n");
 		return NULL;
@@ -809,6 +810,7 @@ static struct samsung_pin_ctrl *samsung_pinctrl_get_soc_data(
 
 	bank = ctrl->pin_banks;
 	for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
+		bank->drvdata = d;
 		bank->pin_base = ctrl->nr_pins;
 		ctrl->nr_pins += bank->nr_pins;
 		if (bank->eint_type == EINT_TYPE_GPIO) {
@@ -848,18 +850,18 @@ static int __devinit samsung_pinctrl_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	ctrl = samsung_pinctrl_get_soc_data(pdev);
-	if (!ctrl) {
-		dev_err(&pdev->dev, "driver data not available\n");
-		return -EINVAL;
-	}
-
 	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
 	if (!drvdata) {
 		dev_err(dev, "failed to allocate memory for driver's "
 				"private data\n");
 		return -ENOMEM;
 	}
+
+	ctrl = samsung_pinctrl_get_soc_data(drvdata, pdev);
+	if (!ctrl) {
+		dev_err(&pdev->dev, "driver data not available\n");
+		return -EINVAL;
+	}
 	drvdata->ctrl = ctrl;
 	drvdata->dev = dev;
 
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index 5c53f32..ea5dadd 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -112,6 +112,7 @@ struct samsung_pinctrl_drv_data;
  * @irq_base: starting controller local irq number of the bank.
  * @name: name to be prefixed for each pin in this pin bank.
  * @of_node: OF node of the bank.
+ * @drvdata: link to controller driver data
  */
 struct samsung_pin_bank {
 	u32		pctl_offset;
@@ -126,6 +127,7 @@ struct samsung_pin_bank {
 	u32		irq_base;
 	char		*name;
 	struct device_node *of_node;
+	struct samsung_pinctrl_drv_data *drvdata;
 };
 
 /**
-- 
1.7.12

^ 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