Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] GPIO: mvebu-gpio: Don't initialize the mask_cache
From: Andrew Lunn @ 2012-10-27 13:28 UTC (permalink / raw)
  To: linux-arm-kernel

Due to the SMP nature of some of the chips, which have per CPU
registers, the driver does not use the generic irq_gc_mask_set_bit() &
irq_gc_mask_clr_bit() functions, which only support a single register.
The driver has its own implementation of these functions, which can
pick the correct register depending on the CPU being used. The
functions do however use the gc->mask_cache value.

The call to irq_setup_generic_chip() was passing
IRQ_GC_INIT_MASK_CACHE, which caused the gc->mask_cache to be
initialized to the contents of some random register. This resulted in
unexpected interrupts been delivered from random GPIO lines.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
---
 drivers/gpio/gpio-mvebu.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index eb42ab1..cf7afb9 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -646,7 +646,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
 	ct->handler = handle_edge_irq;
 	ct->chip.name = mvchip->chip.label;
 
-	irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
+	irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
 			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 
 	/* Setup irq domain on top of the generic chip. */
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH] ARM: OMAP4: Basic default configuration for Pandaboard
From: Santosh Shilimkar @ 2012-10-27 13:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1351339406-10082-1-git-send-email-const@MakeLinux.com>

On Saturday 27 October 2012 05:33 PM, Constantine Shulyupin wrote:
> From: Constantine Shulyupin <const@MakeLinux.com>
>
> Tested SD (MMC) and Ethernet smsc95xx on linux-3.7-rc2
>
> Signed-off-by: Constantine Shulyupin <const@MakeLinux.com>
> --
> kernel size is 2.3 MiB
> ---
>   arch/arm/configs/omap4_panda_defconfig |  115 ++++++++++++++++++++++++++++++++

We got rid of all omap board defconfigs and now just using
omap2plus_defconfig for all OMAP2/3/4/5 machines. If something
is missing from omap2plus_defconfig, which you need to on your
panda custom config, do send patch for that. Otherwise, we are
no longer adding board defconfigs.

Regards
Santosh

^ permalink raw reply

* [PATCH v2 3/3] ARM: OMAP: ocp2scp: create omap device for ocp2scp
From: kishon @ 2012-10-27 12:29 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121026201631.GR11908@atomide.com>

On Saturday 27 October 2012 01:46 AM, Tony Lindgren wrote:
> * Felipe Balbi <balbi@ti.com> [121026 13:07]:
>> On Fri, Oct 26, 2012 at 10:21:41AM -0700, Tony Lindgren wrote:
>>> * Arnd Bergmann <arnd@arndb.de> [121026 00:48]:
>>>> On Friday 26 October 2012, Felipe Balbi wrote:
>>>>>> +static void omap_init_ocp2scp(void)
>>>>>> +{
>>>>>> +     struct omap_hwmod       *oh;
>>>>>> +     struct platform_device  *pdev;
>>>>>> +     int                     bus_id = -1, dev_cnt = 0, i;
>>>>>> +     struct omap_ocp2scp_dev *ocp2scp_dev;
>>>>>> +     const char              *oh_name, *name;
>>>>>> +     struct omap_ocp2scp_platform_data *pdata;
>>>>>> +
>>>>>> +     oh_name = "ocp2scp_usb_phy";
>>>>>> +     name    = "omap-ocp2scp";
>>>>>
>>>>> how about adding checks here to return early case we're not running on
>>>>> OMAP4 or OMAP5 ??
>>>>>
>>>>
>>>> I suppose even OMAP4-only, since OMAP5 always has DT enabled.
>>>
>>> Hmm yes, currently omap_hwmod_lookup(oh_name) produces
>>> bogus errors for other omaps as the hwmod data is only
>>> there for omap4.
>>
>> shouldn't that be fixed too ? I mean, if data isn't just return -ENODEV
>> or something similar.
>
> Yes some kind of checking is needed here.

Ok. I'll fix and send.

Thanks
Kishon

^ permalink raw reply

* [PATCH v2 1/3] drivers: bus: ocp2scp: add pdata support
From: kishon @ 2012-10-27 12:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121026195915.GA29548@arwen.pp.htv.fi>

Hi,

On Saturday 27 October 2012 01:29 AM, Felipe Balbi wrote:
> Hi,
>
> On Fri, Oct 26, 2012 at 10:16:55AM -0700, Tony Lindgren wrote:
>> * Felipe Balbi <balbi@ti.com> [121025 23:55]:
>>> On Thu, Oct 25, 2012 at 10:44:47AM -0700, Tony Lindgren wrote:
>>>> * Felipe Balbi <balbi@ti.com> [121024 23:24]:
>>>>> Hi,
>>>>>
>>>>> On Wed, Oct 24, 2012 at 05:48:07PM -0700, Tony Lindgren wrote:
>>>>>> * Tony Lindgren <tony@atomide.com> [121016 09:53]:
>>>>>>> * Kishon Vijay Abraham I <kishon@ti.com> [121007 23:01]:
>>>>>>>> ocp2scp was not having pdata support which makes *musb* fail for non-dt
>>>>>>>> boot in OMAP platform. The pdata will have information about the devices
>>>>>>>> that is connected to ocp2scp. ocp2scp driver will now make use of this
>>>>>>>> information to create the devices that is attached to ocp2scp.
>>>>>>>>
>>>>>>>> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
>>>>>>>
>>>>>>> This fixes the regression on my panda es for musb port:
>>>>>>>
>>>>>>> Acked-by: Tony Lindgren <tony@atomide.com>
>>>>>>
>>>>>> Looks like nobody has picked this one up and we need it to
>>>>>> fix the musb regression on omap, so I'll queue these up.
>>>>>
>>>>> I don't seem to have the patches around in any mailbox :-(
>>>>
>>>> Bounced them to you. Do you have any better ideas for the
>>>> -rc cycle to fix the MUSB regression on omap4?
>>>
>>> Well, there are two regressions that I know of. One is caused by the
>>> mode1 DMA changes, which I'll just revert, and the other is the
>>> missing platform_data support on the new PHY driver which these patches
>>> are supposed to solve, right ?
>>
>> Yes that's it AFAIK.
>
> Kishon, any other patches I need to take to get MUSB working on v3.7 ?

These should be good enough to get MUSB working..

Thanks
Kishon

^ permalink raw reply

* [PATCH] ARM: OMAP4: Basic default configuration for Pandaboard
From: Constantine Shulyupin @ 2012-10-27 12:03 UTC (permalink / raw)
  To: linux-arm-kernel

From: Constantine Shulyupin <const@MakeLinux.com>

Tested SD (MMC) and Ethernet smsc95xx on linux-3.7-rc2

Signed-off-by: Constantine Shulyupin <const@MakeLinux.com>
--
kernel size is 2.3 MiB
---
 arch/arm/configs/omap4_panda_defconfig |  115 ++++++++++++++++++++++++++++++++
 1 file changed, 115 insertions(+)
 create mode 100644 arch/arm/configs/omap4_panda_defconfig

diff --git a/arch/arm/configs/omap4_panda_defconfig b/arch/arm/configs/omap4_panda_defconfig
new file mode 100644
index 0000000..82c773d
--- /dev/null
+++ b/arch/arm/configs/omap4_panda_defconfig
@@ -0,0 +1,115 @@
+CONFIG_MACH_OMAP4_PANDA=y
+CONFIG_ARCH_OMAP=y
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
+CONFIG_ARCH_OMAP2PLUS=y
+CONFIG_ARCH_OMAP4=y
+CONFIG_SOC_HAS_OMAP2_SDRC=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+
+CONFIG_MACH_OMAP_GENERIC=n
+CONFIG_ARCH_OMAP2=n
+CONFIG_ARCH_OMAP3=n
+CONFIG_SOC_AM33XX=n
+
+CONFIG_MACH_OMAP2_TUSB6010=n
+CONFIG_MACH_OMAP_H4=n
+CONFIG_MACH_OMAP_APOLLON=n
+CONFIG_MACH_OMAP_2430SDP=n
+CONFIG_MACH_OMAP3_BEAGLE=n
+CONFIG_MACH_DEVKIT8000=n
+CONFIG_MACH_OMAP_LDP=n
+CONFIG_MACH_OMAP3530_LV_SOM=n
+CONFIG_MACH_OMAP3_TORPEDO=n
+CONFIG_MACH_OVERO=n
+CONFIG_MACH_OMAP3EVM=n
+CONFIG_MACH_OMAP3517EVM=n
+CONFIG_MACH_OMAP3_PANDORA=n
+CONFIG_MACH_TOUCHBOOK=n
+CONFIG_MACH_OMAP_3430SDP=n
+CONFIG_MACH_NOKIA_N800=n
+CONFIG_MACH_NOKIA_N810=n
+CONFIG_MACH_NOKIA_N810_WIMAX=n
+CONFIG_MACH_NOKIA_N8X0=n
+CONFIG_MACH_NOKIA_RM680=n
+CONFIG_MACH_NOKIA_RX51=n
+CONFIG_MACH_OMAP_ZOOM2=n
+CONFIG_MACH_OMAP_ZOOM3=n
+CONFIG_MACH_CM_T35=n
+CONFIG_MACH_CM_T3517=n
+CONFIG_MACH_CM_T3730=n
+CONFIG_MACH_IGEP0020=n
+CONFIG_MACH_IGEP0030=n
+CONFIG_MACH_SBC3530=n
+CONFIG_MACH_OMAP_3630SDP=n
+CONFIG_MACH_TI8168EVM=n
+CONFIG_MACH_TI8148EVM=n
+CONFIG_MACH_OMAP_4430SDP=n
+
+CONFIG_MODULES=y
+CONFIG_SYSVIPC=y
+CONFIG_EXPERIMENTAL=y # required for CONFIG_USB_NET_SMSC95XX
+
+CONFIG_MMC=y
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+
+CONFIG_DMA_OMAP=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_ENGINE=y
+
+CONFIG_USB=y
+
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_USB_EHCI_HCD=y
+
+CONFIG_USB_NET_AX8817X=n
+CONFIG_USB_NET_CDCETHER=n
+CONFIG_USB_NET_CDC_NCM=n
+CONFIG_USB_NET_NET1080=n
+CONFIG_USB_NET_CDC_SUBSET=n
+CONFIG_USB_BELKIN=n
+CONFIG_USB_ARMLINUX=n
+CONFIG_USB_NET_ZAURUS=n
+
+
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_EVENTS=y
+CONFIG_I2C_CHARDEV=y
+
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_DRV_TWL4030=y
+
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_CRAMFS=y
+
+CONFIG_FPE_NWFPE=y
+
+CONFIG_REGULATOR_TWL4030=y
+
+CONFIG_SPI=y
+CONFIG_SPI_OMAP24XX=y
+
+CONFIG_FB_OMAP_LCD_VGA=y
+CONFIG_OMAP2_DSS=y
+CONFIG_FB_OMAP2=y
-- 
1.7.9.5

^ permalink raw reply related

* [GIT PULL] i.MX fixes for -rc
From: Sascha Hauer @ 2012-10-27 11:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201210262101.44700.arnd@arndb.de>

On Fri, Oct 26, 2012 at 09:01:44PM +0000, Arnd Bergmann wrote:
> On Wednesday 24 October 2012, Sascha Hauer wrote:
> >       ARM i.MX25: Fix PWM per clock lookups
> 
> This patch is now causing build errors in imx_v4_v5_defconfig:
> 
> arch/arm/mach-imx/clk-imx25.c: In function 'mx25_clocks_init':
> arch/arm/mach-imx/clk-imx25.c:206:26: error: 'pwm_ipg_per' undeclared (first use in this function)
> arch/arm/mach-imx/clk-imx25.c:206:26: note: each undeclared identifier is reported only once for each function it appears in
> 
> Any idea what went wrong? The symbol doesn't seem to exist anywhere in
> v3.7-rc2. Should I revert this patch for now?

Yes, please revert it for now.

There are several gates missing in clk-imx25.c. I have a patch which
adds support for them and I seem to have missed that the above depends
on it.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply

* [PATCH] Fix socfpga compilation with early_printk() enabled
From: Pavel Machek @ 2012-10-27 11:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201210251458.48528.arnd@arndb.de>

Hi!

> > This fixes early_printk() compilation for
> > socfpga. (senduart/busyuart/waituart were missing). It does that by
> > making Picochip code generic.
> > 
> > Signed-off-by: Pavel Machek <pavel@denx.de>
> > Acked-by: Dinh Nguyen <dinguyen@altera.com>
> > Acked-by: Jamie Iles <jamie@jamieiles.com 
> 
> Applied to fixes branch of arm-soc, but please be more explicit about
> what you want to happen with patches in the future. Ideally we would
> get pull requests for patches on each platform from only one person,
> so please coordinate with Dinh Nguyen who that should be.

Dinh is the maintainer, so if we can only send patches from one
person, it needs to be him. If you'd be willing to take patches from
second person, that would help us... if not, of course I can send all
the patches through Dinh.

> Some minor things:
> 
> * If you include something in the email that should not be part of
> the git changelog (e.g. "Hi!"), then please put it below the "---"
> line under the Signed-off list.

Ok.

> * you are missing a '>' after Jamies email address

Sorry.

> * When you submit a patch for inclusion, please always take both
> Olof and me on Cc on the email, since we are doing this work together
> and take turns, so you might not always know which one will take
> the patch. We have an alias "arm at kernel.org" that you can also
> use.

Olof Johansson <olof@lixom.net>? Can do.

But... perhaps you should add an entry into MAINTAINERS file
explaining all this? arm at kernel.org is not mentioned there, Olof is
not mentioned as maintaining arm. (And yes, I did check it before
original patch submission).

Thanks,
								Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* ERRATA_751472 was Re: [PATCHv2] arm:socfpga: Enable SMP for socfpga
From: Pavel Machek @ 2012-10-27 11:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1351187384.15182.18.camel@dinh-ubuntu>

Hi!

> > > multi_v7 works fine for me. But I need
> > > +#CONFIG_ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA is not set 
> > 
> > Why? I don't think those should break other versions of A9. If they do,
> > we need to fix that. In general, we should turn on all errata for
> > multi-platform builds, so we need to make sure they are done in a
> > compatible way and can be bypassed if they have performance impacts.
> > That may ultimately require some runtime patching though.
> 
> Our virtual platform is having a problem with CONFIG_ARM_ERRATA_751472.
> It could be that our virtual platform is not simulating this
> correctly.

proc-v7.S:

#if defined(CONFIG_ARM_ERRATA_751472) && defined(CONFIG_SMP)
        ALT_SMP(cmp r6, #0x30)                  @ present prior to r3p0
        ALT_UP_B(1f)
	mrclt   p15, 0, r10, c15, c0, 1         @ read diagnostic register
        orrlt   r10, r10, #1 << 11              @ set bit #11
        mcrlt   p15, 0, r10, c15, c0, 1         @ write diagnostic register
1:
#endif

Is ALT_SMP()/ALT_UP available this early during boot?

If it is, do we need the && defined(CONFIG_SMP)? ALT_UP_... should do
the right thing. (Okk, I guess the ifdef saves cca 16 bytes in the
image...)

									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* [PATCH] arm: socfpga: fix build break for allyesconfig
From: Pavel Machek @ 2012-10-27 11:24 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201210271043.40569.arnd@arndb.de>

On Sat 2012-10-27 10:43:40, Arnd Bergmann wrote:
> On Friday 26 October 2012, Pavel Machek wrote:
> > arch/arm/mach-socfpga/headsmp.S:21: Error: attempt to use an ARM
> > instruction on a Thumb-only processor -- `movw
> > r0,#:lower16:(0xffd08000+0x10)'
> > ...
> > 
> > Using .arch armv7-a indeed works and is a very nice solution.
> > 
> > Signed-off-by: Pavel Machek <pavel@denx.de>
> > 
> > --- a/arch/arm/mach-socfpga/headsmp.S
> > +++ b/arch/arm/mach-socfpga/headsmp.S
> > @@ -11,6 +11,7 @@
> >  #include <linux/init.h>
> >  
> >         __INIT
> > +       .arch   armv7-a
> >  
> >  #define HPS_SYSMGR_ADDRESS     0xffd08000
> >  #define CONFIG_SYSTEM_MANAGER  HPS_SYSMGR_ADDRESS
> > 
> 
> Thanks, applied with new commit message.

Thanks!
									Pavel

-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

^ permalink raw reply

* [PATCH] i2c: omap: ensure writes to dev->buf_len are ordered
From: Santosh Shilimkar @ 2012-10-27 10:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <alpine.DEB.2.00.1210262251020.11258@utopia.booyaka.com>

On Saturday 27 October 2012 04:31 AM, Paul Walmsley wrote:
> Hi Felipe
>
> just two quick comments
>
> On Thu, 25 Oct 2012, Felipe Balbi wrote:
>
>> if we allow compiler reorder our writes, we could
>> fall into a situation where dev->buf_len is reset
>> for no apparent reason.
>>
>> This bug was found with a simple script which would
>> transfer data to an i2c client from 1 to 1024 bytes
>> (a simple for loop), when we got to transfer sizes
>> bigger than the fifo size, dev->buf_len was reset
>> to zero before we had an oportunity to handle XDR
>> Interrupt. Because dev->buf_len was zero, we entered
>> omap_i2c_transmit_data() to transfer zero bytes,
>> which would mean we would just silently exit
>> omap_i2c_transmit_data() without actually writing
>> anything to DATA register. That would cause XDR
>> IRQ to trigger forever and we would never transfer
>> the remaining bytes.
>>
>> After adding the memory barrier, we also drop resetting
>> dev->buf_len to zero in omap_i2c_xfer_msg() because
>> both omap_i2c_transmit_data() and omap_i2c_receive_data()
>> will act until dev->buf_len reaches zero, rendering the
>> other write in omap_i2c_xfer_msg() redundant.
>>
>> This patch has been tested with pandaboard for a few
>> iterations of the script mentioned above.
>>
>> Signed-off-by: Felipe Balbi <balbi@ti.com>
>> ---
>>
>> This bug has been there forever, but it's quite annoying.
>> I think it deserves being pushed upstream during this -rc
>> cycle, but if Wolfram decides to wait until v3.8, I don't
>> mind.
>>
>>   drivers/i2c/busses/i2c-omap.c | 2 +-
>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
>> index db31eae..1ec4e6e 100644
>> --- a/drivers/i2c/busses/i2c-omap.c
>> +++ b/drivers/i2c/busses/i2c-omap.c
>> @@ -521,6 +521,7 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
>>   	/* REVISIT: Could the STB bit of I2C_CON be used with probing? */
>>   	dev->buf = msg->buf;
>>   	dev->buf_len = msg->len;
>> +	wmb();
>>
>>   	omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
>>
>
> Would suggest moving the wmb() immediately before the point at which the
> interrupt can occur.  Looks to me that's when the OMAP_I2C_CON_REG write
> occurs.
>
> Also would suggest adding a comment to clarify what the wmb() is intended
> to do.  Maybe something like 'Prevent the compiler from moving earlier
> changes to dev->buf and dev->buf_len after the write to CON_REG.  This
> write enables interrupts and those variables are used in the interrupt
> handler'.
>
Another alternative, which I will recommend to just make use of the
read*/wrire* instead __raw versions. The barriers are taken care
already and driver point of view, it is transparent.

-->
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index db31eae..0cd6365 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -265,13 +265,13 @@ static const u8 reg_map_ip_v2[] = {
  static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
  				      int reg, u16 val)
  {
-	__raw_writew(val, i2c_dev->base +
+	writew(val, i2c_dev->base +
  			(i2c_dev->regs[reg] << i2c_dev->reg_shift));
  }

  static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
  {
-	return __raw_readw(i2c_dev->base +
+	return readw(i2c_dev->base +
  				(i2c_dev->regs[reg] << i2c_dev->reg_shift));
  }

Patch might be damaged because of copy paste.

Regards
Santosh

^ permalink raw reply related

* [PATCH] arm: socfpga: fix build break for allyesconfig
From: Arnd Bergmann @ 2012-10-27 10:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20121026230052.GA24573@elf.ucw.cz>

On Friday 26 October 2012, Pavel Machek wrote:
> arch/arm/mach-socfpga/headsmp.S:21: Error: attempt to use an ARM
> instruction on a Thumb-only processor -- `movw
> r0,#:lower16:(0xffd08000+0x10)'
> ...
> 
> Using .arch armv7-a indeed works and is a very nice solution.
> 
> Signed-off-by: Pavel Machek <pavel@denx.de>
> 
> --- a/arch/arm/mach-socfpga/headsmp.S
> +++ b/arch/arm/mach-socfpga/headsmp.S
> @@ -11,6 +11,7 @@
>  #include <linux/init.h>
>  
>         __INIT
> +       .arch   armv7-a
>  
>  #define HPS_SYSMGR_ADDRESS     0xffd08000
>  #define CONFIG_SYSTEM_MANAGER  HPS_SYSMGR_ADDRESS
> 

Thanks, applied with new commit message.

	Arnd

^ permalink raw reply

* [PATCH] ARM: dts: mxs: Add PWM3 muxing options for i.MX28
From: julien.boibessot at free.fr @ 2012-10-27 10:15 UTC (permalink / raw)
  To: linux-arm-kernel

From: Julien Boibessot <julien.boibessot@armadeus.com>

Signed-off-by: Gwenhael Goavec-Merou <gwenhael.goavec-merou@armadeus.com>
Signed-off-by: Julien Boibessot <julien.boibessot@armadeus.com>
---
 arch/arm/boot/dts/imx28.dtsi |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index e16d631..2b607aa 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -491,6 +491,16 @@
 					fsl,pull-up = <0>;
 				};
 
+				pwm3_pins_a: pwm3 at 0 {
+					reg = <0>;
+					fsl,pinmux-ids = <
+						0x31c0 /* MX28_PAD_PWM3__PWM_3 */
+					>;
+					fsl,drive-strength = <0>;
+					fsl,voltage = <1>;
+					fsl,pull-up = <0>;
+				};
+
 				pwm4_pins_a: pwm4 at 0 {
 					reg = <0>;
 					fsl,pinmux-ids = <
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH V2 5/5] ARM: SPEAr: Add plgpio node in device tree dtsi files
From: Viresh Kumar @ 2012-10-27  9:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351330569.git.viresh.kumar@linaro.org>

This patch adds plgpio nodes in SPEAr DT files.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 arch/arm/boot/dts/spear1310-evb.dts |  4 ++++
 arch/arm/boot/dts/spear1310.dtsi    | 27 +++++++++++++++++++++++++++
 arch/arm/boot/dts/spear1340-evb.dts |  4 ++++
 arch/arm/boot/dts/spear1340.dtsi    | 26 ++++++++++++++++++++++++++
 arch/arm/boot/dts/spear310.dtsi     | 22 +++++++++++++++++++++-
 arch/arm/boot/dts/spear320-evb.dts  |  4 ++++
 arch/arm/boot/dts/spear320.dtsi     | 23 ++++++++++++++++++++++-
 7 files changed, 108 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts
index dd4358b..2e4c572 100644
--- a/arch/arm/boot/dts/spear1310-evb.dts
+++ b/arch/arm/boot/dts/spear1310-evb.dts
@@ -181,6 +181,10 @@
 			       status = "okay";
 			};
 
+			gpio at d8400000 {
+			       status = "okay";
+			};
+
 			i2c0: i2c at e0280000 {
 			       status = "okay";
 			};
diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi
index 419ea74..7cd25eb 100644
--- a/arch/arm/boot/dts/spear1310.dtsi
+++ b/arch/arm/boot/dts/spear1310.dtsi
@@ -70,6 +70,12 @@
 			status = "disabled";
 		};
 
+		pinmux: pinmux at e0700000 {
+			compatible = "st,spear1310-pinmux";
+			reg = <0xe0700000 0x1000>;
+			#gpio-range-cells = <2>;
+		};
+
 		spi1: spi at 5d400000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x5d400000 0x1000>;
@@ -179,6 +185,27 @@
 			thermal at e07008c4 {
 				st,thermal-flags = <0x7000>;
 			};
+
+			gpiopinctrl: gpio at d8400000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xd8400000 0x1000>;
+				interrupts = <0 100 0x4>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-ranges = <&pinmux 0 246>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <246>;
+				st-plgpio,enb-reg = <0xd0>;
+				st-plgpio,wdata-reg = <0x90>;
+				st-plgpio,dir-reg = <0xb0>;
+				st-plgpio,ie-reg = <0x30>;
+				st-plgpio,rdata-reg = <0x70>;
+				st-plgpio,mis-reg = <0x10>;
+				st-plgpio,eit-reg = <0x50>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts
index c9a54e0..045f712 100644
--- a/arch/arm/boot/dts/spear1340-evb.dts
+++ b/arch/arm/boot/dts/spear1340-evb.dts
@@ -193,6 +193,10 @@
 			       status = "okay";
 			};
 
+			gpio at e2800000 {
+			       status = "okay";
+			};
+
 			i2c0: i2c at e0280000 {
 			       status = "okay";
 			};
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index d71fe2a..6c09eb0 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -24,6 +24,12 @@
 			status = "disabled";
 		};
 
+		pinmux: pinmux at e0700000 {
+			compatible = "st,spear1340-pinmux";
+			reg = <0xe0700000 0x1000>;
+			#gpio-range-cells = <2>;
+		};
+
 		spi1: spi at 5d400000 {
 			compatible = "arm,pl022", "arm,primecell";
 			reg = <0x5d400000 0x1000>;
@@ -51,6 +57,26 @@
 			thermal at e07008c4 {
 				st,thermal-flags = <0x2a00>;
 			};
+
+			gpiopinctrl: gpio at e2800000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xe2800000 0x1000>;
+				interrupts = <0 107 0x4>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-ranges = <&pinmux 0 252>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <250>;
+				st-plgpio,wdata-reg = <0x40>;
+				st-plgpio,dir-reg = <0x00>;
+				st-plgpio,ie-reg = <0x80>;
+				st-plgpio,rdata-reg = <0x20>;
+				st-plgpio,mis-reg = <0xa0>;
+				st-plgpio,eit-reg = <0x60>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
index 62fc4fb..930303e 100644
--- a/arch/arm/boot/dts/spear310.dtsi
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -22,9 +22,10 @@
 			  0xb0000000 0xb0000000 0x10000000
 			  0xd0000000 0xd0000000 0x30000000>;
 
-		pinmux at b4000000 {
+		pinmux: pinmux at b4000000 {
 			compatible = "st,spear310-pinmux";
 			reg = <0xb4000000 0x1000>;
+			#gpio-range-cells = <2>;
 		};
 
 		fsmc: flash at 44000000 {
@@ -75,6 +76,25 @@
 				reg = <0xb2200000 0x1000>;
 				status = "disabled";
 			};
+
+			gpiopinctrl: gpio at b4000000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xb4000000 0x1000>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-ranges = <&pinmux 0 102>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <102>;
+				st-plgpio,enb-reg = <0x10>;
+				st-plgpio,wdata-reg = <0x20>;
+				st-plgpio,dir-reg = <0x30>;
+				st-plgpio,ie-reg = <0x50>;
+				st-plgpio,rdata-reg = <0x40>;
+				st-plgpio,mis-reg = <0x60>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/spear320-evb.dts b/arch/arm/boot/dts/spear320-evb.dts
index 082328b..ad4bfc6 100644
--- a/arch/arm/boot/dts/spear320-evb.dts
+++ b/arch/arm/boot/dts/spear320-evb.dts
@@ -164,6 +164,10 @@
 			       status = "okay";
 			};
 
+			gpio at b3000000 {
+			       status = "okay";
+			};
+
 			i2c0: i2c at d0180000 {
 			       status = "okay";
 			};
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
index 1f49d69..67d7ada 100644
--- a/arch/arm/boot/dts/spear320.dtsi
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -21,9 +21,10 @@
 		ranges = <0x40000000 0x40000000 0x80000000
 			  0xd0000000 0xd0000000 0x30000000>;
 
-		pinmux at b3000000 {
+		pinmux: pinmux at b3000000 {
 			compatible = "st,spear320-pinmux";
 			reg = <0xb3000000 0x1000>;
+			#gpio-range-cells = <2>;
 		};
 
 		clcd at 90000000 {
@@ -90,6 +91,26 @@
 				reg = <0xa4000000 0x1000>;
 				status = "disabled";
 			};
+
+			gpiopinctrl: gpio at b3000000 {
+				compatible = "st,spear-plgpio";
+				reg = <0xb3000000 0x1000>;
+				#interrupt-cells = <1>;
+				interrupt-controller;
+				gpio-controller;
+				#gpio-cells = <2>;
+				gpio-ranges = <&pinmux 0 102>;
+				status = "disabled";
+
+				st-plgpio,ngpio = <102>;
+				st-plgpio,enb-reg = <0x24>;
+				st-plgpio,wdata-reg = <0x34>;
+				st-plgpio,dir-reg = <0x44>;
+				st-plgpio,ie-reg = <0x64>;
+				st-plgpio,rdata-reg = <0x54>;
+				st-plgpio,mis-reg = <0x84>;
+				st-plgpio,eit-reg = <0x94>;
+			};
 		};
 	};
 };
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH V2 4/5] pinctrl: SPEAr: Add gpio ranges support
From: Viresh Kumar @ 2012-10-27  9:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351330569.git.viresh.kumar@linaro.org>

Most of SPEAr SoCs, which support pinctrl, can configure & use pads as gpio.
This patch gpio enable support for SPEAr pinctrl drivers.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---

It has few differences since the time it was last posted. I kept your Acked-by
as the changes aren't that big (I believe). :)

 drivers/pinctrl/spear/Kconfig             |   4 +
 drivers/pinctrl/spear/pinctrl-spear.c     | 107 ++++++++++--
 drivers/pinctrl/spear/pinctrl-spear.h     |  46 ++++++
 drivers/pinctrl/spear/pinctrl-spear1310.c | 264 ++++++++++++++++++++++++++++++
 drivers/pinctrl/spear/pinctrl-spear300.c  |   2 +
 drivers/pinctrl/spear/pinctrl-spear310.c  |   2 +
 drivers/pinctrl/spear/pinctrl-spear320.c  |   2 +
 drivers/pinctrl/spear/pinctrl-spear3xx.c  |  37 +++++
 8 files changed, 447 insertions(+), 17 deletions(-)

diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig
index 6f9a1e8..04d93e6 100644
--- a/drivers/pinctrl/spear/Kconfig
+++ b/drivers/pinctrl/spear/Kconfig
@@ -25,21 +25,25 @@ config PINCTRL_SPEAR310
 	bool "ST Microelectronics SPEAr310 SoC pin controller driver"
 	depends on MACH_SPEAR310
 	select PINCTRL_SPEAR3XX
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR320
 	bool "ST Microelectronics SPEAr320 SoC pin controller driver"
 	depends on MACH_SPEAR320
 	select PINCTRL_SPEAR3XX
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR1310
 	bool "ST Microelectronics SPEAr1310 SoC pin controller driver"
 	depends on MACH_SPEAR1310
 	select PINCTRL_SPEAR
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR1340
 	bool "ST Microelectronics SPEAr1340 SoC pin controller driver"
 	depends on MACH_SPEAR1340
 	select PINCTRL_SPEAR
+	select PINCTRL_SPEAR_PLGPIO
 
 config PINCTRL_SPEAR_PLGPIO
 	bool "SPEAr SoC PLGPIO Controller"
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index b1fd6ee..cbca6dc 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_gpio.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
@@ -38,6 +39,28 @@ static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
 	writel_relaxed(val, pmx->vbase + reg);
 }
 
+static void muxregs_endisable(struct spear_pmx *pmx,
+		struct spear_muxreg *muxregs, u8 count, bool enable)
+{
+	struct spear_muxreg *muxreg;
+	u32 val, temp, j;
+
+	for (j = 0; j < count; j++) {
+		muxreg = &muxregs[j];
+
+		val = pmx_readl(pmx, muxreg->reg);
+		val &= ~muxreg->mask;
+
+		if (enable)
+			temp = muxreg->val;
+		else
+			temp = ~muxreg->val;
+
+		val |= muxreg->mask & temp;
+		pmx_writel(pmx, val, muxreg->reg);
+	}
+}
+
 static int set_mode(struct spear_pmx *pmx, int mode)
 {
 	struct spear_pmx_mode *pmx_mode = NULL;
@@ -70,6 +93,17 @@ static int set_mode(struct spear_pmx *pmx, int mode)
 	return 0;
 }
 
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+		unsigned count, u16 reg)
+{
+	int i = 0, j = 0;
+
+	for (; i < count; i++)
+		for (; j < gpio_pingroup[i].nmuxregs; j++)
+			gpio_pingroup[i].muxregs[j].reg = reg;
+}
+
 void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
 {
 	struct spear_pingroup *pgroup;
@@ -216,9 +250,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
 	struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
 	const struct spear_pingroup *pgroup;
 	const struct spear_modemux *modemux;
-	struct spear_muxreg *muxreg;
-	u32 val, temp;
-	int i, j;
+	int i;
 	bool found = false;
 
 	pgroup = pmx->machdata->groups[group];
@@ -233,20 +265,8 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
 		}
 
 		found = true;
-		for (j = 0; j < modemux->nmuxregs; j++) {
-			muxreg = &modemux->muxregs[j];
-
-			val = pmx_readl(pmx, muxreg->reg);
-			val &= ~muxreg->mask;
-
-			if (enable)
-				temp = muxreg->val;
-			else
-				temp = ~muxreg->val;
-
-			val |= muxreg->mask & temp;
-			pmx_writel(pmx, val, muxreg->reg);
-		}
+		muxregs_endisable(pmx, modemux->muxregs, modemux->nmuxregs,
+				enable);
 	}
 
 	if (!found) {
@@ -270,12 +290,65 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
 	spear_pinctrl_endisable(pctldev, function, group, false);
 }
 
+/* gpio with pinmux */
+static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx,
+		unsigned pin)
+{
+	struct spear_gpio_pingroup *gpio_pingroup;
+	int i = 0, j;
+
+	if (!pmx->machdata->gpio_pingroups)
+		return NULL;
+
+	for (; i < pmx->machdata->ngpio_pingroups; i++) {
+		gpio_pingroup = &pmx->machdata->gpio_pingroups[i];
+
+		for (j = 0; j < gpio_pingroup->npins; j++) {
+			if (gpio_pingroup->pins[j] == pin)
+				return gpio_pingroup;
+		}
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+static int gpio_request_endisable(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset, bool enable)
+{
+	struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
+	struct spear_gpio_pingroup *gpio_pingroup;
+
+	gpio_pingroup = get_gpio_pingroup(pmx, offset);
+	if (IS_ERR(gpio_pingroup))
+		return PTR_ERR(gpio_pingroup);
+
+	if (gpio_pingroup)
+		muxregs_endisable(pmx, gpio_pingroup->muxregs,
+				gpio_pingroup->nmuxregs, enable);
+
+	return 0;
+}
+
+static int gpio_request_enable(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset)
+{
+	return gpio_request_endisable(pctldev, range, offset, true);
+}
+
+static void gpio_disable_free(struct pinctrl_dev *pctldev,
+		struct pinctrl_gpio_range *range, unsigned offset)
+{
+	gpio_request_endisable(pctldev, range, offset, false);
+}
+
 static struct pinmux_ops spear_pinmux_ops = {
 	.get_functions_count = spear_pinctrl_get_funcs_count,
 	.get_function_name = spear_pinctrl_get_func_name,
 	.get_function_groups = spear_pinctrl_get_func_groups,
 	.enable = spear_pinctrl_enable,
 	.disable = spear_pinctrl_disable,
+	.gpio_request_enable = gpio_request_enable,
+	.gpio_disable_free = gpio_disable_free,
 };
 
 static struct pinctrl_desc spear_pinctrl_desc = {
diff --git a/drivers/pinctrl/spear/pinctrl-spear.h b/drivers/pinctrl/spear/pinctrl-spear.h
index d950eb7..94f142c 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.h
+++ b/drivers/pinctrl/spear/pinctrl-spear.h
@@ -12,6 +12,7 @@
 #ifndef __PINMUX_SPEAR_H__
 #define __PINMUX_SPEAR_H__
 
+#include <linux/gpio.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/types.h>
 
@@ -46,6 +47,44 @@ struct spear_muxreg {
 	u32 val;
 };
 
+struct spear_gpio_pingroup {
+	const unsigned *pins;
+	unsigned npins;
+	struct spear_muxreg *muxregs;
+	u8 nmuxregs;
+};
+
+/* ste: set to enable */
+#define DEFINE_MUXREG(__pins, __muxreg, __mask, __ste)		\
+static struct spear_muxreg __pins##_muxregs[] = {		\
+	{							\
+		.reg = __muxreg,				\
+		.mask = __mask,					\
+		.val = __ste ? __mask : 0,			\
+	},							\
+}
+
+#define DEFINE_2_MUXREG(__pins, __muxreg1, __muxreg2, __mask, __ste1, __ste2) \
+static struct spear_muxreg __pins##_muxregs[] = {		\
+	{							\
+		.reg = __muxreg1,				\
+		.mask = __mask,					\
+		.val = __ste1 ? __mask : 0,			\
+	}, {							\
+		.reg = __muxreg2,				\
+		.mask = __mask,					\
+		.val = __ste2 ? __mask : 0,			\
+	},							\
+}
+
+#define GPIO_PINGROUP(__pins)					\
+	{							\
+		.pins = __pins,					\
+		.npins = ARRAY_SIZE(__pins),			\
+		.muxregs = __pins##_muxregs,			\
+		.nmuxregs = ARRAY_SIZE(__pins##_muxregs),	\
+	}
+
 /**
  * struct spear_modemux - SPEAr mode mux configuration
  * @modes: mode ids supported by this group of muxregs
@@ -100,6 +139,8 @@ struct spear_function {
  * @nfunctions: The numbmer of entries in @functions.
  * @groups: An array describing all pin groups the pin SoC supports.
  * @ngroups: The numbmer of entries in @groups.
+ * @gpio_pingroups: gpio pingroups
+ * @ngpio_pingroups: gpio pingroups count
  *
  * @modes_supported: Does SoC support modes
  * @mode: mode configured from probe
@@ -113,6 +154,8 @@ struct spear_pinctrl_machdata {
 	unsigned nfunctions;
 	struct spear_pingroup **groups;
 	unsigned ngroups;
+	struct spear_gpio_pingroup *gpio_pingroups;
+	unsigned ngpio_pingroups;
 
 	bool modes_supported;
 	u16 mode;
@@ -136,6 +179,9 @@ struct spear_pmx {
 
 /* exported routines */
 void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
+void __devinit
+pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
+		unsigned count, u16 reg);
 int __devinit spear_pinctrl_probe(struct platform_device *pdev,
 		struct spear_pinctrl_machdata *machdata);
 int __devexit spear_pinctrl_remove(struct platform_device *pdev);
diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index 0436fc7..30134f7 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -2418,6 +2418,268 @@ static struct spear_function *spear1310_functions[] = {
 	&gpt64_function,
 };
 
+static const unsigned pin18[] = { 18, };
+static const unsigned pin19[] = { 19, };
+static const unsigned pin20[] = { 20, };
+static const unsigned pin21[] = { 21, };
+static const unsigned pin22[] = { 22, };
+static const unsigned pin23[] = { 23, };
+static const unsigned pin54[] = { 54, };
+static const unsigned pin55[] = { 55, };
+static const unsigned pin56[] = { 56, };
+static const unsigned pin57[] = { 57, };
+static const unsigned pin58[] = { 58, };
+static const unsigned pin59[] = { 59, };
+static const unsigned pin60[] = { 60, };
+static const unsigned pin61[] = { 61, };
+static const unsigned pin62[] = { 62, };
+static const unsigned pin63[] = { 63, };
+static const unsigned pin143[] = { 143, };
+static const unsigned pin144[] = { 144, };
+static const unsigned pin145[] = { 145, };
+static const unsigned pin146[] = { 146, };
+static const unsigned pin147[] = { 147, };
+static const unsigned pin148[] = { 148, };
+static const unsigned pin149[] = { 149, };
+static const unsigned pin150[] = { 150, };
+static const unsigned pin151[] = { 151, };
+static const unsigned pin152[] = { 152, };
+static const unsigned pin205[] = { 205, };
+static const unsigned pin206[] = { 206, };
+static const unsigned pin211[] = { 211, };
+static const unsigned pin212[] = { 212, };
+static const unsigned pin213[] = { 213, };
+static const unsigned pin214[] = { 214, };
+static const unsigned pin215[] = { 215, };
+static const unsigned pin216[] = { 216, };
+static const unsigned pin217[] = { 217, };
+static const unsigned pin218[] = { 218, };
+static const unsigned pin219[] = { 219, };
+static const unsigned pin220[] = { 220, };
+static const unsigned pin221[] = { 221, };
+static const unsigned pin222[] = { 222, };
+static const unsigned pin223[] = { 223, };
+static const unsigned pin224[] = { 224, };
+static const unsigned pin225[] = { 225, };
+static const unsigned pin226[] = { 226, };
+static const unsigned pin227[] = { 227, };
+static const unsigned pin228[] = { 228, };
+static const unsigned pin229[] = { 229, };
+static const unsigned pin230[] = { 230, };
+static const unsigned pin231[] = { 231, };
+static const unsigned pin232[] = { 232, };
+static const unsigned pin233[] = { 233, };
+static const unsigned pin234[] = { 234, };
+static const unsigned pin235[] = { 235, };
+static const unsigned pin236[] = { 236, };
+static const unsigned pin237[] = { 237, };
+static const unsigned pin238[] = { 238, };
+static const unsigned pin239[] = { 239, };
+static const unsigned pin240[] = { 240, };
+static const unsigned pin241[] = { 241, };
+static const unsigned pin242[] = { 242, };
+static const unsigned pin243[] = { 243, };
+static const unsigned pin244[] = { 244, };
+static const unsigned pin245[] = { 245, };
+
+static const unsigned pin_grp0[] = { 173, 174, };
+static const unsigned pin_grp1[] = { 175, 185, 188, 197, 198, };
+static const unsigned pin_grp2[] = { 176, 177, 178, 179, 184, 186, 187, 189,
+	190, 191, 192, };
+static const unsigned pin_grp3[] = { 180, 181, 182, 183, 193, 194, 195, 196, };
+static const unsigned pin_grp4[] = { 199, 200, };
+static const unsigned pin_grp5[] = { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+	75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, };
+static const unsigned pin_grp6[] = { 86, 87, 88, 89, 90, 91, 92, 93, };
+static const unsigned pin_grp7[] = { 98, 99, };
+static const unsigned pin_grp8[] = { 158, 159, 160, 161, 162, 163, 164, 165,
+	166, 167, 168, 169, 170, 171, 172, };
+
+/* Define muxreg arrays */
+DEFINE_2_MUXREG(i2c0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2C0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SSP0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_cs0_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS0_MASK, 0, 1);
+DEFINE_2_MUXREG(ssp0_cs1_2_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS1_2_MASK, 0, 1);
+DEFINE_2_MUXREG(i2s0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2S0_MASK, 0, 1);
+DEFINE_2_MUXREG(i2s1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_I2S1_MASK, 0, 1);
+DEFINE_2_MUXREG(clcd_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_CLCD1_MASK, 0, 1);
+DEFINE_2_MUXREG(clcd_high_res_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_CLCD2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin18, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO15_MASK, 0, 1);
+DEFINE_2_MUXREG(pin19, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO14_MASK, 0, 1);
+DEFINE_2_MUXREG(pin20, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO13_MASK, 0, 1);
+DEFINE_2_MUXREG(pin21, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO12_MASK, 0, 1);
+DEFINE_2_MUXREG(pin22, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO11_MASK, 0, 1);
+DEFINE_2_MUXREG(pin23, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO10_MASK, 0, 1);
+DEFINE_2_MUXREG(pin143, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO00_MASK, 0, 1);
+DEFINE_2_MUXREG(pin144, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO01_MASK, 0, 1);
+DEFINE_2_MUXREG(pin145, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO02_MASK, 0, 1);
+DEFINE_2_MUXREG(pin146, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO03_MASK, 0, 1);
+DEFINE_2_MUXREG(pin147, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO04_MASK, 0, 1);
+DEFINE_2_MUXREG(pin148, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO05_MASK, 0, 1);
+DEFINE_2_MUXREG(pin149, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO06_MASK, 0, 1);
+DEFINE_2_MUXREG(pin150, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO07_MASK, 0, 1);
+DEFINE_2_MUXREG(pin151, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO08_MASK, 0, 1);
+DEFINE_2_MUXREG(pin152, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO09_MASK, 0, 1);
+DEFINE_2_MUXREG(smi_2_chips_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SMI_MASK, 0, 1);
+DEFINE_2_MUXREG(pin54, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin55, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin56, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFRSTPWDWN3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin57, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin58, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin59, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN0_MASK, 0, 1);
+DEFINE_2_MUXREG(pin60, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFWPRT3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin61, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFCE3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin62, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD25_MASK, 0, 1);
+DEFINE_2_MUXREG(pin63, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD24_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp0, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp1, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp2, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_RXCLK_RDV_TXEN_D03_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp3, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIID47_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp4, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MDC_MDIO_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp5, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD23_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp6, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MCI_DATA8_15_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp7, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFCE2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin_grp8, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND8_MASK, 0, 1);
+DEFINE_2_MUXREG(nand_16bit_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND16BIT_1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin205, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL1_MASK | PMX_NFCE1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin206, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL0_MASK | PMX_NFCE2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin211, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW1_MASK | PMX_NFWPRT1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin212, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW0_MASK | PMX_NFWPRT2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin213, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA0_MASK, 0, 1);
+DEFINE_2_MUXREG(pin214, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin215, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin216, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA3_MASK, 0, 1);
+DEFINE_2_MUXREG(pin217, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA4_MASK, 0, 1);
+DEFINE_2_MUXREG(pin218, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA5_MASK, 0, 1);
+DEFINE_2_MUXREG(pin219, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA6_MASK, 0, 1);
+DEFINE_2_MUXREG(pin220, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA7_MASK, 0, 1);
+DEFINE_2_MUXREG(pin221, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA1SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin222, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA2SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin223, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA3SD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin224, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR0ALE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin225, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR1CLECLK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin226, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin227, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICECF_MASK, 0, 1);
+DEFINE_2_MUXREG(pin228, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICEXD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin229, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICESDMMC_MASK, 0, 1);
+DEFINE_2_MUXREG(pin230, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin231, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF2_MASK, 0, 1);
+DEFINE_2_MUXREG(pin232, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDXD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin233, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDSDMMC_MASK, 0, 1);
+DEFINE_2_MUXREG(pin234, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATADIR_MASK, 0, 1);
+DEFINE_2_MUXREG(pin235, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMARQWP_MASK, 0, 1);
+DEFINE_2_MUXREG(pin236, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDRE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin237, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIOWRWE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin238, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIRESETCF_MASK, 0, 1);
+DEFINE_2_MUXREG(pin239, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS0CE_MASK, 0, 1);
+DEFINE_2_MUXREG(pin240, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICFINTR_MASK, 0, 1);
+DEFINE_2_MUXREG(pin241, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDY_MASK, 0, 1);
+DEFINE_2_MUXREG(pin242, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS1_MASK, 0, 1);
+DEFINE_2_MUXREG(pin243, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMAACK_MASK, 0, 1);
+DEFINE_2_MUXREG(pin244, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCISDCMD_MASK, 0, 1);
+DEFINE_2_MUXREG(pin245, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCILEDS_MASK, 0, 1);
+DEFINE_2_MUXREG(keyboard_rowcol6_8_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROWCOL68_MASK, 0, 1);
+DEFINE_2_MUXREG(uart0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_UART0_MASK, 0, 1);
+DEFINE_2_MUXREG(uart0_modem_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_UART0_MODEM_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt0_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR0_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt0_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR1_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt1_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR0_MASK, 0, 1);
+DEFINE_2_MUXREG(gpt1_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR1_MASK, 0, 1);
+DEFINE_2_MUXREG(touch_xy_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_TOUCH_XY_MASK, 0, 1);
+
+static struct spear_gpio_pingroup spear1310_gpio_pingroup[] = {
+	GPIO_PINGROUP(i2c0_pins),
+	GPIO_PINGROUP(ssp0_pins),
+	GPIO_PINGROUP(ssp0_cs0_pins),
+	GPIO_PINGROUP(ssp0_cs1_2_pins),
+	GPIO_PINGROUP(i2s0_pins),
+	GPIO_PINGROUP(i2s1_pins),
+	GPIO_PINGROUP(clcd_pins),
+	GPIO_PINGROUP(clcd_high_res_pins),
+	GPIO_PINGROUP(pin18),
+	GPIO_PINGROUP(pin19),
+	GPIO_PINGROUP(pin20),
+	GPIO_PINGROUP(pin21),
+	GPIO_PINGROUP(pin22),
+	GPIO_PINGROUP(pin23),
+	GPIO_PINGROUP(pin143),
+	GPIO_PINGROUP(pin144),
+	GPIO_PINGROUP(pin145),
+	GPIO_PINGROUP(pin146),
+	GPIO_PINGROUP(pin147),
+	GPIO_PINGROUP(pin148),
+	GPIO_PINGROUP(pin149),
+	GPIO_PINGROUP(pin150),
+	GPIO_PINGROUP(pin151),
+	GPIO_PINGROUP(pin152),
+	GPIO_PINGROUP(smi_2_chips_pins),
+	GPIO_PINGROUP(pin54),
+	GPIO_PINGROUP(pin55),
+	GPIO_PINGROUP(pin56),
+	GPIO_PINGROUP(pin57),
+	GPIO_PINGROUP(pin58),
+	GPIO_PINGROUP(pin59),
+	GPIO_PINGROUP(pin60),
+	GPIO_PINGROUP(pin61),
+	GPIO_PINGROUP(pin62),
+	GPIO_PINGROUP(pin63),
+	GPIO_PINGROUP(pin_grp0),
+	GPIO_PINGROUP(pin_grp1),
+	GPIO_PINGROUP(pin_grp2),
+	GPIO_PINGROUP(pin_grp3),
+	GPIO_PINGROUP(pin_grp4),
+	GPIO_PINGROUP(pin_grp5),
+	GPIO_PINGROUP(pin_grp6),
+	GPIO_PINGROUP(pin_grp7),
+	GPIO_PINGROUP(pin_grp8),
+	GPIO_PINGROUP(nand_16bit_pins),
+	GPIO_PINGROUP(pin205),
+	GPIO_PINGROUP(pin206),
+	GPIO_PINGROUP(pin211),
+	GPIO_PINGROUP(pin212),
+	GPIO_PINGROUP(pin213),
+	GPIO_PINGROUP(pin214),
+	GPIO_PINGROUP(pin215),
+	GPIO_PINGROUP(pin216),
+	GPIO_PINGROUP(pin217),
+	GPIO_PINGROUP(pin218),
+	GPIO_PINGROUP(pin219),
+	GPIO_PINGROUP(pin220),
+	GPIO_PINGROUP(pin221),
+	GPIO_PINGROUP(pin222),
+	GPIO_PINGROUP(pin223),
+	GPIO_PINGROUP(pin224),
+	GPIO_PINGROUP(pin225),
+	GPIO_PINGROUP(pin226),
+	GPIO_PINGROUP(pin227),
+	GPIO_PINGROUP(pin228),
+	GPIO_PINGROUP(pin229),
+	GPIO_PINGROUP(pin230),
+	GPIO_PINGROUP(pin231),
+	GPIO_PINGROUP(pin232),
+	GPIO_PINGROUP(pin233),
+	GPIO_PINGROUP(pin234),
+	GPIO_PINGROUP(pin235),
+	GPIO_PINGROUP(pin236),
+	GPIO_PINGROUP(pin237),
+	GPIO_PINGROUP(pin238),
+	GPIO_PINGROUP(pin239),
+	GPIO_PINGROUP(pin240),
+	GPIO_PINGROUP(pin241),
+	GPIO_PINGROUP(pin242),
+	GPIO_PINGROUP(pin243),
+	GPIO_PINGROUP(pin244),
+	GPIO_PINGROUP(pin245),
+	GPIO_PINGROUP(keyboard_rowcol6_8_pins),
+	GPIO_PINGROUP(uart0_pins),
+	GPIO_PINGROUP(uart0_modem_pins),
+	GPIO_PINGROUP(gpt0_tmr0_pins),
+	GPIO_PINGROUP(gpt0_tmr1_pins),
+	GPIO_PINGROUP(gpt1_tmr0_pins),
+	GPIO_PINGROUP(gpt1_tmr1_pins),
+	GPIO_PINGROUP(touch_xy_pins),
+};
+
 static struct spear_pinctrl_machdata spear1310_machdata = {
 	.pins = spear1310_pins,
 	.npins = ARRAY_SIZE(spear1310_pins),
@@ -2425,6 +2687,8 @@ static struct spear_pinctrl_machdata spear1310_machdata = {
 	.ngroups = ARRAY_SIZE(spear1310_pingroups),
 	.functions = spear1310_functions,
 	.nfunctions = ARRAY_SIZE(spear1310_functions),
+	.gpio_pingroups = spear1310_gpio_pingroup,
+	.ngpio_pingroups = ARRAY_SIZE(spear1310_gpio_pingroup),
 	.modes_supported = false,
 };
 
diff --git a/drivers/pinctrl/spear/pinctrl-spear300.c b/drivers/pinctrl/spear/pinctrl-spear300.c
index 4dfc284..9a49100 100644
--- a/drivers/pinctrl/spear/pinctrl-spear300.c
+++ b/drivers/pinctrl/spear/pinctrl-spear300.c
@@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
 	spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
 	spear3xx_machdata.functions = spear300_functions;
 	spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions);
+	spear3xx_machdata.gpio_pingroups = NULL;
+	spear3xx_machdata.ngpio_pingroups = 0;
 
 	spear3xx_machdata.modes_supported = true;
 	spear3xx_machdata.pmx_modes = spear300_pmx_modes;
diff --git a/drivers/pinctrl/spear/pinctrl-spear310.c b/drivers/pinctrl/spear/pinctrl-spear310.c
index 9688369..4d5dfe9 100644
--- a/drivers/pinctrl/spear/pinctrl-spear310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear310.c
@@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
 	spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
 
 	pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+	pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+			spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
 
 	spear3xx_machdata.modes_supported = false;
 
diff --git a/drivers/pinctrl/spear/pinctrl-spear320.c b/drivers/pinctrl/spear/pinctrl-spear320.c
index ca47b0e..c996e26 100644
--- a/drivers/pinctrl/spear/pinctrl-spear320.c
+++ b/drivers/pinctrl/spear/pinctrl-spear320.c
@@ -3431,6 +3431,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
 	spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes);
 
 	pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
+	pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
+			spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
 
 	ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
 	if (ret)
diff --git a/drivers/pinctrl/spear/pinctrl-spear3xx.c b/drivers/pinctrl/spear/pinctrl-spear3xx.c
index 0242378..12ee21a 100644
--- a/drivers/pinctrl/spear/pinctrl-spear3xx.c
+++ b/drivers/pinctrl/spear/pinctrl-spear3xx.c
@@ -481,7 +481,44 @@ struct spear_function spear3xx_timer_2_3_function = {
 	.ngroups = ARRAY_SIZE(timer_2_3_grps),
 };
 
+/* Define muxreg arrays */
+DEFINE_MUXREG(firda_pins, 0, PMX_FIRDA_MASK, 0);
+DEFINE_MUXREG(i2c_pins, 0, PMX_I2C_MASK, 0);
+DEFINE_MUXREG(ssp_cs_pins, 0, PMX_SSP_CS_MASK, 0);
+DEFINE_MUXREG(ssp_pins, 0, PMX_SSP_MASK, 0);
+DEFINE_MUXREG(mii_pins, 0, PMX_MII_MASK, 0);
+DEFINE_MUXREG(gpio0_pin0_pins, 0, PMX_GPIO_PIN0_MASK, 0);
+DEFINE_MUXREG(gpio0_pin1_pins, 0, PMX_GPIO_PIN1_MASK, 0);
+DEFINE_MUXREG(gpio0_pin2_pins, 0, PMX_GPIO_PIN2_MASK, 0);
+DEFINE_MUXREG(gpio0_pin3_pins, 0, PMX_GPIO_PIN3_MASK, 0);
+DEFINE_MUXREG(gpio0_pin4_pins, 0, PMX_GPIO_PIN4_MASK, 0);
+DEFINE_MUXREG(gpio0_pin5_pins, 0, PMX_GPIO_PIN5_MASK, 0);
+DEFINE_MUXREG(uart0_ext_pins, 0, PMX_UART0_MODEM_MASK, 0);
+DEFINE_MUXREG(uart0_pins, 0, PMX_UART0_MASK, 0);
+DEFINE_MUXREG(timer_0_1_pins, 0, PMX_TIMER_0_1_MASK, 0);
+DEFINE_MUXREG(timer_2_3_pins, 0, PMX_TIMER_2_3_MASK, 0);
+
+static struct spear_gpio_pingroup spear3xx_gpio_pingroup[] = {
+	GPIO_PINGROUP(firda_pins),
+	GPIO_PINGROUP(i2c_pins),
+	GPIO_PINGROUP(ssp_cs_pins),
+	GPIO_PINGROUP(ssp_pins),
+	GPIO_PINGROUP(mii_pins),
+	GPIO_PINGROUP(gpio0_pin0_pins),
+	GPIO_PINGROUP(gpio0_pin1_pins),
+	GPIO_PINGROUP(gpio0_pin2_pins),
+	GPIO_PINGROUP(gpio0_pin3_pins),
+	GPIO_PINGROUP(gpio0_pin4_pins),
+	GPIO_PINGROUP(gpio0_pin5_pins),
+	GPIO_PINGROUP(uart0_ext_pins),
+	GPIO_PINGROUP(uart0_pins),
+	GPIO_PINGROUP(timer_0_1_pins),
+	GPIO_PINGROUP(timer_2_3_pins),
+};
+
 struct spear_pinctrl_machdata spear3xx_machdata = {
 	.pins = spear3xx_pins,
 	.npins = ARRAY_SIZE(spear3xx_pins),
+	.gpio_pingroups = spear3xx_gpio_pingroup,
+	.ngpio_pingroups = ARRAY_SIZE(spear3xx_gpio_pingroup),
 };
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH V2 3/5] pinctrl: SPEAr: Add plgpio driver
From: Viresh Kumar @ 2012-10-27  9:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351330569.git.viresh.kumar@linaro.org>

Most of SPEAr SoCs, which support pinctrl, can configure & use pads as gpio.
This patch adds plgpio driver for configuring these pads as gpio.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
Linus,

It was Acked-by you last time it was sent:
	http://www.spinics.net/lists/arm-kernel/msg173443.html

 drivers/pinctrl/spear/Kconfig          |   7 +
 drivers/pinctrl/spear/Makefile         |   1 +
 drivers/pinctrl/spear/pinctrl-plgpio.c | 746 +++++++++++++++++++++++++++++++++
 3 files changed, 754 insertions(+)
 create mode 100644 drivers/pinctrl/spear/pinctrl-plgpio.c

diff --git a/drivers/pinctrl/spear/Kconfig b/drivers/pinctrl/spear/Kconfig
index 91558791..6f9a1e8 100644
--- a/drivers/pinctrl/spear/Kconfig
+++ b/drivers/pinctrl/spear/Kconfig
@@ -41,4 +41,11 @@ config PINCTRL_SPEAR1340
 	depends on MACH_SPEAR1340
 	select PINCTRL_SPEAR
 
+config PINCTRL_SPEAR_PLGPIO
+	bool "SPEAr SoC PLGPIO Controller"
+	depends on GPIOLIB && PINCTRL_SPEAR
+	help
+	  Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
+	  SoCs.
+
 endif
diff --git a/drivers/pinctrl/spear/Makefile b/drivers/pinctrl/spear/Makefile
index b28a7ba..0e400eb 100644
--- a/drivers/pinctrl/spear/Makefile
+++ b/drivers/pinctrl/spear/Makefile
@@ -1,5 +1,6 @@
 # SPEAr pinmux support
 
+obj-$(CONFIG_PINCTRL_SPEAR_PLGPIO)	+= pinctrl-plgpio.o
 obj-$(CONFIG_PINCTRL_SPEAR)	+= pinctrl-spear.o
 obj-$(CONFIG_PINCTRL_SPEAR3XX)	+= pinctrl-spear3xx.o
 obj-$(CONFIG_PINCTRL_SPEAR300)	+= pinctrl-spear300.o
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
new file mode 100644
index 0000000..1044ad3
--- /dev/null
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -0,0 +1,746 @@
+/*
+ * SPEAr platform PLGPIO driver
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/spinlock.h>
+#include <asm/mach/irq.h>
+
+#define MAX_GPIO_PER_REG		32
+#define PIN_OFFSET(pin)			(pin % MAX_GPIO_PER_REG)
+#define REG_OFFSET(base, reg, pin)	(base + reg + (pin / MAX_GPIO_PER_REG) \
+							* sizeof(int *))
+
+/*
+ * plgpio pins in all machines are not one to one mapped, bitwise with registers
+ * bits. These set of macros define register masks for which below functions
+ * (pin_to_offset and offset_to_pin) are required to be called.
+ */
+#define PTO_ENB_REG		0x001
+#define PTO_WDATA_REG		0x002
+#define PTO_DIR_REG		0x004
+#define PTO_IE_REG		0x008
+#define PTO_RDATA_REG		0x010
+#define PTO_MIS_REG		0x020
+
+struct plgpio_regs {
+	u32 enb;		/* enable register */
+	u32 wdata;		/* write data register */
+	u32 dir;		/* direction set register */
+	u32 rdata;		/* read data register */
+	u32 ie;			/* interrupt enable register */
+	u32 mis;		/* mask interrupt status register */
+	u32 eit;		/* edge interrupt type */
+};
+
+/*
+ * struct plgpio: plgpio driver specific structure
+ *
+ * lock: lock for guarding gpio registers
+ * base: base address of plgpio block
+ * irq_base: irq number of plgpio0
+ * chip: gpio framework specific chip information structure
+ * p2o: function ptr for pin to offset conversion. This is required only for
+ *	machines where mapping b/w pin and offset is not 1-to-1.
+ * o2p: function ptr for offset to pin conversion. This is required only for
+ *	machines where mapping b/w pin and offset is not 1-to-1.
+ * p2o_regs: mask of registers for which p2o and o2p are applicable
+ * regs: register offsets
+ * csave_regs: context save registers for standby/sleep/hibernate cases
+ */
+struct plgpio {
+	spinlock_t		lock;
+	void __iomem		*base;
+	struct clk		*clk;
+	unsigned		irq_base;
+	struct irq_domain	*irq_domain;
+	struct gpio_chip	chip;
+	int			(*p2o)(int pin);	/* pin_to_offset */
+	int			(*o2p)(int offset);	/* offset_to_pin */
+	u32			p2o_regs;
+	struct plgpio_regs	regs;
+#ifdef CONFIG_PM
+	struct plgpio_regs	*csave_regs;
+#endif
+};
+
+/* register manipulation inline functions */
+static inline u32 is_plgpio_set(void __iomem *base, u32 pin, u32 reg)
+{
+	u32 offset = PIN_OFFSET(pin);
+	void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+	u32 val = readl_relaxed(reg_off);
+
+	return !!(val & (1 << offset));
+}
+
+static inline void plgpio_reg_set(void __iomem *base, u32 pin, u32 reg)
+{
+	u32 offset = PIN_OFFSET(pin);
+	void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+	u32 val = readl_relaxed(reg_off);
+
+	writel_relaxed(val | (1 << offset), reg_off);
+}
+
+static inline void plgpio_reg_reset(void __iomem *base, u32 pin, u32 reg)
+{
+	u32 offset = PIN_OFFSET(pin);
+	void __iomem *reg_off = REG_OFFSET(base, reg, pin);
+	u32 val = readl_relaxed(reg_off);
+
+	writel_relaxed(val & ~(1 << offset), reg_off);
+}
+
+/* gpio framework specific routines */
+static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	unsigned long flags;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return -EINVAL;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_set(plgpio->base, offset, plgpio->regs.dir);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+
+	return 0;
+}
+
+static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	unsigned long flags;
+	unsigned dir_offset = offset, wdata_offset = offset, tmp;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) {
+		tmp = plgpio->p2o(offset);
+		if (tmp == -1)
+			return -EINVAL;
+
+		if (plgpio->p2o_regs & PTO_DIR_REG)
+			dir_offset = tmp;
+		if (plgpio->p2o_regs & PTO_WDATA_REG)
+			wdata_offset = tmp;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	if (value)
+		plgpio_reg_set(plgpio->base, wdata_offset,
+				plgpio->regs.wdata);
+	else
+		plgpio_reg_reset(plgpio->base, wdata_offset,
+				plgpio->regs.wdata);
+
+	plgpio_reg_reset(plgpio->base, dir_offset, plgpio->regs.dir);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+
+	return 0;
+}
+
+static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+	if (offset >= chip->ngpio)
+		return -EINVAL;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return -EINVAL;
+	}
+
+	return is_plgpio_set(plgpio->base, offset, plgpio->regs.rdata);
+}
+
+static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+	if (offset >= chip->ngpio)
+		return;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	if (value)
+		plgpio_reg_set(plgpio->base, offset, plgpio->regs.wdata);
+	else
+		plgpio_reg_reset(plgpio->base, offset, plgpio->regs.wdata);
+}
+
+static int plgpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	int gpio = chip->base + offset;
+	unsigned long flags;
+	int ret = 0;
+
+	if (offset >= chip->ngpio)
+		return -EINVAL;
+
+	ret = pinctrl_request_gpio(gpio);
+	if (ret)
+		return ret;
+
+	if (!IS_ERR(plgpio->clk)) {
+		ret = clk_prepare_enable(plgpio->clk);
+		if (ret)
+			goto err0;
+	}
+
+	if (plgpio->regs.enb == -1)
+		return 0;
+
+	/*
+	 * put gpio in IN mode before enabling it. This make enabling gpio safe
+	 */
+	ret = plgpio_direction_input(chip, offset);
+	if (ret)
+		goto err1;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1) {
+			ret = -EINVAL;
+			goto err1;
+		}
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_set(plgpio->base, offset, plgpio->regs.enb);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+	return 0;
+
+err1:
+	clk_disable_unprepare(plgpio->clk);
+err0:
+	pinctrl_free_gpio(gpio);
+	return ret;
+}
+
+static void plgpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+	int gpio = chip->base + offset;
+	unsigned long flags;
+
+	if (offset >= chip->ngpio)
+		return;
+
+	if (plgpio->regs.enb == -1)
+		goto disable_clk;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_reset(plgpio->base, offset, plgpio->regs.enb);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+
+disable_clk:
+	if (!IS_ERR(plgpio->clk))
+		clk_disable_unprepare(plgpio->clk);
+
+	pinctrl_free_gpio(gpio);
+}
+
+static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
+
+	if (plgpio->irq_base < 0)
+		return -EINVAL;
+
+	return irq_find_mapping(plgpio->irq_domain, offset);
+}
+
+/* PLGPIO IRQ */
+static void plgpio_irq_disable(struct irq_data *d)
+{
+	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - plgpio->irq_base;
+	unsigned long flags;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_set(plgpio->base, offset, plgpio->regs.ie);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static void plgpio_irq_enable(struct irq_data *d)
+{
+	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - plgpio->irq_base;
+	unsigned long flags;
+
+	/* get correct offset for "offset" pin */
+	if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
+		offset = plgpio->p2o(offset);
+		if (offset == -1)
+			return;
+	}
+
+	spin_lock_irqsave(&plgpio->lock, flags);
+	plgpio_reg_reset(plgpio->base, offset, plgpio->regs.ie);
+	spin_unlock_irqrestore(&plgpio->lock, flags);
+}
+
+static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
+{
+	struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
+	int offset = d->irq - plgpio->irq_base;
+	void __iomem *reg_off;
+	unsigned int supported_type = 0, val;
+
+	if (offset >= plgpio->chip.ngpio)
+		return -EINVAL;
+
+	if (plgpio->regs.eit == -1)
+		supported_type = IRQ_TYPE_LEVEL_HIGH;
+	else
+		supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+
+	if (!(trigger & supported_type))
+		return -EINVAL;
+
+	if (plgpio->regs.eit == -1)
+		return 0;
+
+	reg_off = REG_OFFSET(plgpio->base, plgpio->regs.eit, offset);
+	val = readl_relaxed(reg_off);
+
+	offset = PIN_OFFSET(offset);
+	if (trigger & IRQ_TYPE_EDGE_RISING)
+		writel_relaxed(val | (1 << offset), reg_off);
+	else
+		writel_relaxed(val & ~(1 << offset), reg_off);
+
+	return 0;
+}
+
+static struct irq_chip plgpio_irqchip = {
+	.name		= "PLGPIO",
+	.irq_enable	= plgpio_irq_enable,
+	.irq_disable	= plgpio_irq_disable,
+	.irq_set_type	= plgpio_irq_set_type,
+};
+
+static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
+{
+	struct plgpio *plgpio = irq_get_handler_data(irq);
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+	int regs_count, count, pin, offset, i = 0;
+	unsigned long pending;
+
+	count = plgpio->chip.ngpio;
+	regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG);
+
+	chained_irq_enter(irqchip, desc);
+	/* check all plgpio MIS registers for a possible interrupt */
+	for (; i < regs_count; i++) {
+		pending = readl_relaxed(plgpio->base + plgpio->regs.mis +
+				i * sizeof(int *));
+		if (!pending)
+			continue;
+
+		/* clear interrupts */
+		writel_relaxed(~pending, plgpio->base + plgpio->regs.mis +
+				i * sizeof(int *));
+		/*
+		 * clear extra bits in last register having gpios < MAX/REG
+		 * ex: Suppose there are max 102 plgpios. then last register
+		 * must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits
+		 * so, we must not take other 28 bits into consideration for
+		 * checking interrupt. so clear those bits.
+		 */
+		count = count - i * MAX_GPIO_PER_REG;
+		if (count < MAX_GPIO_PER_REG)
+			pending &= (1 << count) - 1;
+
+		for_each_set_bit(offset, &pending, MAX_GPIO_PER_REG) {
+			/* get correct pin for "offset" */
+			if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) {
+				pin = plgpio->o2p(offset);
+				if (pin == -1)
+					continue;
+			} else
+				pin = offset;
+
+			/* get correct irq line number */
+			pin = i * MAX_GPIO_PER_REG + pin;
+			generic_handle_irq(plgpio_to_irq(&plgpio->chip, pin));
+		}
+	}
+	chained_irq_exit(irqchip, desc);
+}
+
+/*
+ * pin to offset and offset to pin converter functions
+ *
+ * In spear310 there is inconsistency among bit positions in plgpio regiseters,
+ * for different plgpio pins. For example: for pin 27, bit offset is 23, pin
+ * 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1
+ */
+static int spear310_p2o(int pin)
+{
+	int offset = pin;
+
+	if (pin <= 27)
+		offset += 4;
+	else if (pin <= 33)
+		offset = -1;
+	else if (pin <= 97)
+		offset -= 2;
+	else if (pin <= 101)
+		offset = 101 - pin;
+	else
+		offset = -1;
+
+	return offset;
+}
+
+int spear310_o2p(int offset)
+{
+	if (offset <= 3)
+		return 101 - offset;
+	else if (offset <= 31)
+		return offset - 4;
+	else
+		return offset + 2;
+}
+
+static int __devinit plgpio_probe_dt(struct platform_device *pdev,
+		struct plgpio *plgpio)
+{
+	struct device_node *np = pdev->dev.of_node;
+	int ret = -EINVAL;
+	u32 val;
+
+	if (of_machine_is_compatible("st,spear310")) {
+		plgpio->p2o = spear310_p2o;
+		plgpio->o2p = spear310_o2p;
+		plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG |
+			PTO_RDATA_REG | PTO_MIS_REG;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) {
+		plgpio->chip.ngpio = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid ngpio field\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val))
+		plgpio->regs.enb = val;
+	else
+		plgpio->regs.enb = -1;
+
+	if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) {
+		plgpio->regs.wdata = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid wdata reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) {
+		plgpio->regs.dir = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid dir reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) {
+		plgpio->regs.ie = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid ie reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) {
+		plgpio->regs.rdata = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid rdata reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) {
+		plgpio->regs.mis = val;
+	} else {
+		dev_err(&pdev->dev, "DT: Invalid mis reg\n");
+		goto end;
+	}
+
+	if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val))
+		plgpio->regs.eit = val;
+	else
+		plgpio->regs.eit = -1;
+
+	return 0;
+
+end:
+	return ret;
+}
+static int __devinit plgpio_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct plgpio *plgpio;
+	struct resource *res;
+	int ret, irq, i;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
+		return -EBUSY;
+	}
+
+	plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
+	if (!plgpio) {
+		dev_err(&pdev->dev, "memory allocation fail\n");
+		return -ENOMEM;
+	}
+
+	plgpio->base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!plgpio->base) {
+		dev_err(&pdev->dev, "request and ioremap fail\n");
+		return -ENOMEM;
+	}
+
+	ret = plgpio_probe_dt(pdev, plgpio);
+	if (ret) {
+		dev_err(&pdev->dev, "DT probe failed\n");
+		return ret;
+	}
+
+	plgpio->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(plgpio->clk))
+		dev_warn(&pdev->dev, "clk_get() failed, work without it\n");
+
+#ifdef CONFIG_PM
+	plgpio->csave_regs = devm_kzalloc(&pdev->dev,
+			sizeof(*plgpio->csave_regs) *
+			DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
+			GFP_KERNEL);
+	if (!plgpio->csave_regs) {
+		dev_err(&pdev->dev, "csave registers memory allocation fail\n");
+		return -ENOMEM;
+	}
+#endif
+
+	platform_set_drvdata(pdev, plgpio);
+	spin_lock_init(&plgpio->lock);
+
+	plgpio->irq_base = -1;
+	plgpio->chip.base = -1;
+	plgpio->chip.request = plgpio_request;
+	plgpio->chip.free = plgpio_free;
+	plgpio->chip.direction_input = plgpio_direction_input;
+	plgpio->chip.direction_output = plgpio_direction_output;
+	plgpio->chip.get = plgpio_get_value;
+	plgpio->chip.set = plgpio_set_value;
+	plgpio->chip.to_irq = plgpio_to_irq;
+	plgpio->chip.label = dev_name(&pdev->dev);
+	plgpio->chip.dev = &pdev->dev;
+	plgpio->chip.owner = THIS_MODULE;
+
+	ret = gpiochip_add(&plgpio->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpio chip\n");
+		return ret;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_info(&pdev->dev, "irqs not supported\n");
+		return 0;
+	}
+
+	plgpio->irq_base = irq_alloc_descs(-1, 0, plgpio->chip.ngpio, 0);
+	if (IS_ERR_VALUE(plgpio->irq_base)) {
+		/* we would not support irq for gpio */
+		dev_warn(&pdev->dev, "couldn't allocate irq base\n");
+		return 0;
+	}
+
+	plgpio->irq_domain = irq_domain_add_legacy(np, plgpio->chip.ngpio,
+			plgpio->irq_base, 0, &irq_domain_simple_ops, NULL);
+	if (WARN_ON(!plgpio->irq_domain)) {
+		dev_err(&pdev->dev, "irq domain init failed\n");
+		irq_free_descs(plgpio->irq_base, plgpio->chip.ngpio);
+		ret = -ENXIO;
+		goto remove_gpiochip;
+	}
+
+	irq_set_chained_handler(irq, plgpio_irq_handler);
+	for (i = 0; i < plgpio->chip.ngpio; i++) {
+		irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip,
+				handle_simple_irq);
+		set_irq_flags(i + plgpio->irq_base, IRQF_VALID);
+		irq_set_chip_data(i + plgpio->irq_base, plgpio);
+	}
+
+	irq_set_handler_data(irq, plgpio);
+	dev_info(&pdev->dev, "PLGPIO registered with IRQs\n");
+
+	return 0;
+
+remove_gpiochip:
+	dev_info(&pdev->dev, "Remove gpiochip\n");
+	if (gpiochip_remove(&plgpio->chip))
+		dev_err(&pdev->dev, "unable to remove gpiochip\n");
+
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static int plgpio_suspend(struct device *dev)
+{
+	struct plgpio *plgpio = dev_get_drvdata(dev);
+	int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+	void __iomem *off;
+
+	for (i = 0; i < reg_count; i++) {
+		off = plgpio->base + i * sizeof(int *);
+
+		if (plgpio->regs.enb != -1)
+			plgpio->csave_regs[i].enb =
+				readl_relaxed(plgpio->regs.enb + off);
+		if (plgpio->regs.eit != -1)
+			plgpio->csave_regs[i].eit =
+				readl_relaxed(plgpio->regs.eit + off);
+		plgpio->csave_regs[i].wdata = readl_relaxed(plgpio->regs.wdata +
+				off);
+		plgpio->csave_regs[i].dir = readl_relaxed(plgpio->regs.dir +
+				off);
+		plgpio->csave_regs[i].ie = readl_relaxed(plgpio->regs.ie + off);
+	}
+
+	return 0;
+}
+
+/*
+ * This is used to correct the values in end registers. End registers contain
+ * extra bits that might be used for other purpose in platform. So, we shouldn't
+ * overwrite these bits. This macro, reads given register again, preserves other
+ * bit values (non-plgpio bits), and retain captured value (plgpio bits).
+ */
+#define plgpio_prepare_reg(__reg, _off, _mask, _tmp)		\
+{								\
+	_tmp = readl_relaxed(plgpio->regs.__reg + _off);		\
+	_tmp &= ~_mask;						\
+	plgpio->csave_regs[i].__reg =				\
+		_tmp | (plgpio->csave_regs[i].__reg & _mask);	\
+}
+
+static int plgpio_resume(struct device *dev)
+{
+	struct plgpio *plgpio = dev_get_drvdata(dev);
+	int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
+	void __iomem *off;
+	u32 mask, tmp;
+
+	for (i = 0; i < reg_count; i++) {
+		off = plgpio->base + i * sizeof(int *);
+
+		if (i == reg_count - 1) {
+			mask = (1 << (plgpio->chip.ngpio - i *
+						MAX_GPIO_PER_REG)) - 1;
+
+			if (plgpio->regs.enb != -1)
+				plgpio_prepare_reg(enb, off, mask, tmp);
+
+			if (plgpio->regs.eit != -1)
+				plgpio_prepare_reg(eit, off, mask, tmp);
+
+			plgpio_prepare_reg(wdata, off, mask, tmp);
+			plgpio_prepare_reg(dir, off, mask, tmp);
+			plgpio_prepare_reg(ie, off, mask, tmp);
+		}
+
+		writel_relaxed(plgpio->csave_regs[i].wdata, plgpio->regs.wdata +
+				off);
+		writel_relaxed(plgpio->csave_regs[i].dir, plgpio->regs.dir +
+				off);
+
+		if (plgpio->regs.eit != -1)
+			writel_relaxed(plgpio->csave_regs[i].eit,
+					plgpio->regs.eit + off);
+
+		writel_relaxed(plgpio->csave_regs[i].ie, plgpio->regs.ie + off);
+
+		if (plgpio->regs.enb != -1)
+			writel_relaxed(plgpio->csave_regs[i].enb,
+					plgpio->regs.enb + off);
+	}
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume);
+
+static const struct of_device_id plgpio_of_match[] = {
+	{ .compatible = "st,spear-plgpio" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, plgpio_of_match);
+
+static struct platform_driver plgpio_driver = {
+	.probe = plgpio_probe,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "spear-plgpio",
+		.pm = &plgpio_dev_pm_ops,
+		.of_match_table = of_match_ptr(plgpio_of_match),
+	},
+};
+
+static int __init plgpio_init(void)
+{
+	return platform_driver_register(&plgpio_driver);
+}
+subsys_initcall(plgpio_init);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
+MODULE_DESCRIPTION("ST Microlectronics SPEAr PLGPIO driver");
+MODULE_LICENSE("GPL");
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH V2 RESEND 2/5] gpiolib: provide provision for gpiolib to register pin range
From: Viresh Kumar @ 2012-10-27  9:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351330569.git.viresh.kumar@linaro.org>

From: Shiraz Hashim <shiraz.hashim@st.com>

pinctrl subsystem needs gpio chip base to prepare set of gpio pin ranges, which
a given pinctrl driver can handle. This is important to handle pinctrl gpio
request calls in order to program a given pin properly for gpio operation.

As gpio base is allocated dynamically during gpiochip registration, presently
there exists no clean way to pass this information to the pinctrl subsystem.

After few discussions from [1], it was concluded that may be gpio controller
reporting the pin range it supports, is a better way than pinctrl subsystem
directly registering it.

[1] http://comments.gmane.org/gmane.linux.ports.arm.kernel/184816

Cc: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
---
V1->V2:
------
- Add non-DT routines to register gpio ranges
- Update Documentation/gpio.txt
- Update Documentation/pinctrl.txt to mark older way as DEPRECATED
- of_gpiochip_add_pin_range() rearranged a bit
- use devm_kzalloc() instead of kzalloc()
- few other minor fixes

 Documentation/devicetree/bindings/gpio/gpio.txt | 36 ++++++++++++++++
 Documentation/gpio.txt                          | 26 ++++++++++++
 Documentation/pinctrl.txt                       |  3 ++
 drivers/gpio/gpiolib-of.c                       | 56 +++++++++++++++++++++++++
 drivers/gpio/gpiolib.c                          | 43 +++++++++++++++++++
 drivers/pinctrl/core.c                          | 13 ++++++
 drivers/pinctrl/devicetree.c                    | 13 ++++++
 include/asm-generic/gpio.h                      | 25 +++++++++++
 include/linux/gpio.h                            |  3 ++
 include/linux/pinctrl/pinctrl.h                 | 17 ++++++++
 10 files changed, 235 insertions(+)

diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index 4e16ba4..a336287 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
 		gpio-controller;
 	};
 
+2.1) gpio-controller and pinctrl subsystem
+------------------------------------------
 
+gpio-controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with optional gpio feature.
+
+While the pin allocation is totally managed by the pin ctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to
+request the corresponding pin before any gpio usage.
+
+For this, the gpio controller can use a pinctrl phandle and pins to
+announce the pinrange to the pin ctrl subsystem. For example,
+
+	qe_pio_e: gpio-controller at 1460 {
+		#gpio-cells = <2>;
+		compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
+		reg = <0x1460 0x18>;
+		gpio-controller;
+		gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
+
+    }
+
+where,
+   &pinctrl1 and &pinctrl2 is the phandle to the pinctrl DT node.
+
+   Next values specify the base pin and number of pins for the range
+   handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
+   pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
+   by this gpio controller.
+
+The pinctrl node must have "#gpio-range-cells" property to show number of
+arguments to pass with phandle from gpio controllers node.
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index e08a883..77f233c 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -439,6 +439,32 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its
 signaling rate accordingly.
 
 
+gpio-controller and pinctrl subsystem
+------------------------------------------
+
+gpio-controller on a SOC might be tightly coupled with the pinctrl
+subsystem, in the sense that the pins can be used by other functions
+together with optional gpio feature.
+
+While the pin allocation is totally managed by the pin ctrl subsystem,
+gpio (under gpiolib) is still maintained by gpio drivers. It may happen
+that different pin ranges in a SoC is managed by different gpio drivers.
+
+This makes it logical to let gpio drivers announce their pin ranges to
+the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to
+request the corresponding pin before any gpio usage.
+
+For this, the gpio controller can register its pin range with pinctrl subsystem.
+There are two ways of doing it currently with or without DT.
+
+For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
+
+For non-DT support, user can call gpiochip_add_pin_range() with appropriate
+parameters to register a range of gpio pins with a pinctrl driver. For this
+exact name string of pinctrl device has to be passed as one of the argument to
+this routine.
+
+
 What do these conventions omit?
 ===============================
 One of the biggest things these conventions omit is pin multiplexing, since
diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index a1cd2f9..da40efb 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -364,6 +364,9 @@ will get an pin number into its handled number range. Further it is also passed
 the range ID value, so that the pin controller knows which range it should
 deal with.
 
+Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see
+section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind
+pinctrl and gpio drivers.
 
 PINMUX interfaces
 =================
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index f1a4599..a5b90c8 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
 #include <linux/slab.h>
 
 /* Private data structure for of_gpiochip_find_and_xlate */
@@ -216,6 +217,58 @@ err0:
 }
 EXPORT_SYMBOL(of_mm_gpiochip_add);
 
+#ifdef CONFIG_PINCTRL
+void of_gpiochip_add_pin_range(struct gpio_chip *chip)
+{
+	struct device_node *np = chip->of_node;
+	struct gpio_pin_range *pin_range;
+	struct of_phandle_args pinspec;
+	int index = 0, ret;
+
+	if (!np)
+		return;
+
+	do {
+		ret = of_parse_phandle_with_args(np, "gpio-ranges",
+				"#gpio-range-cells", index, &pinspec);
+		if (ret)
+			break;
+
+		pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range),
+				GFP_KERNEL);
+		if (!pin_range) {
+			pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
+					chip->label);
+			break;
+		}
+
+		pin_range->range.name = chip->label;
+		pin_range->range.base = chip->base;
+		pin_range->range.pin_base = pinspec.args[0];
+		pin_range->range.npins = pinspec.args[1];
+		pin_range->pctldev = of_pinctrl_add_gpio_range(pinspec.np,
+				&pin_range->range);
+
+		list_add_tail(&pin_range->node, &chip->pin_ranges);
+
+	} while (index++);
+}
+
+void of_gpiochip_remove_pin_range(struct gpio_chip *chip)
+{
+	struct gpio_pin_range *pin_range, *tmp;
+
+	list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
+		list_del(&pin_range->node);
+		pinctrl_remove_gpio_range(pin_range->pctldev,
+				&pin_range->range);
+	}
+}
+#else
+void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
+void of_gpiochip_remove_pin_range(struct gpio_chip *chip) {}
+#endif
+
 void of_gpiochip_add(struct gpio_chip *chip)
 {
 	if ((!chip->of_node) && (chip->dev))
@@ -229,11 +282,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
 		chip->of_xlate = of_gpio_simple_xlate;
 	}
 
+	of_gpiochip_add_pin_range(chip);
 	of_node_get(chip->of_node);
 }
 
 void of_gpiochip_remove(struct gpio_chip *chip)
 {
+	of_gpiochip_remove_pin_range(chip);
+
 	if (chip->of_node)
 		of_node_put(chip->of_node);
 }
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 5d6c71e..3e84796 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1081,6 +1081,10 @@ int gpiochip_add(struct gpio_chip *chip)
 		}
 	}
 
+#ifdef CONFIG_PINCTRL
+	INIT_LIST_HEAD(&chip->pin_ranges);
+#endif
+
 	of_gpiochip_add(chip);
 
 unlock:
@@ -1178,6 +1182,45 @@ struct gpio_chip *gpiochip_find(void *data,
 }
 EXPORT_SYMBOL_GPL(gpiochip_find);
 
+#ifdef CONFIG_PINCTRL
+void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+		unsigned int pin_base, unsigned int npins)
+{
+	struct gpio_pin_range *pin_range;
+
+	pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range), GFP_KERNEL);
+	if (!pin_range) {
+		pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
+				chip->label);
+		return;
+	}
+
+	pin_range->range.name = chip->label;
+	pin_range->range.base = chip->base;
+	pin_range->range.pin_base = pin_base;
+	pin_range->range.npins = npins;
+	pin_range->pctldev = find_pinctrl_and_add_gpio_range(pinctl_name,
+			&pin_range->range);
+
+	list_add_tail(&pin_range->node, &chip->pin_ranges);
+}
+
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
+{
+	struct gpio_pin_range *pin_range, *tmp;
+
+	list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
+		list_del(&pin_range->node);
+		pinctrl_remove_gpio_range(pin_range->pctldev,
+				&pin_range->range);
+	}
+}
+#else
+void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+		unsigned int pin_base, unsigned int npins) {}
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip) {}
+#endif
+
 /* These "optional" allocation calls help prevent drivers from stomping
  * on each other, and help provide better diagnostics in debugfs.
  * They're called even less than the "set direction" calls.
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index b1086dc..71db586 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -345,6 +345,19 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
 }
 EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
 
+struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
+		struct pinctrl_gpio_range *range)
+{
+	struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname);
+
+	if (!pctldev)
+		return NULL;
+
+	pinctrl_add_gpio_range(pctldev, range);
+	return pctldev;
+}
+EXPORT_SYMBOL_GPL(find_pinctrl_and_add_gpio_range);
+
 /**
  * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
  * @pctldev: pin controller device to remove the range from
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index fcb1de4..6728ec7 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -106,6 +106,19 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
 	return NULL;
 }
 
+struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
+		struct pinctrl_gpio_range *range)
+{
+	struct pinctrl_dev *pctldev;
+
+	pctldev = find_pinctrl_by_of_node(np);
+	if (!pctldev)
+		return NULL;
+
+	pinctrl_add_gpio_range(pctldev, range);
+	return pctldev;
+}
+
 static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
 				struct device_node *np_config)
 {
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index a9432fc..92e5c43 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -5,6 +5,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/of.h>
+#include <linux/pinctrl/pinctrl.h>
 
 #ifdef CONFIG_GPIOLIB
 
@@ -47,6 +48,21 @@ struct seq_file;
 struct module;
 struct device_node;
 
+#ifdef CONFIG_PINCTRL
+/**
+ * struct gpio_pin_range - pin range controlled by a gpio chip
+ * @head: list for maintaining set of pin ranges, used internally
+ * @pctldev: pinctrl device which handles corresponding pins
+ * @range: actual range of pins controlled by a gpio controller
+ */
+
+struct gpio_pin_range {
+	struct list_head node;
+	struct pinctrl_dev *pctldev;
+	struct pinctrl_gpio_range range;
+};
+#endif
+
 /**
  * struct gpio_chip - abstract a GPIO controller
  * @label: for diagnostics
@@ -134,6 +150,15 @@ struct gpio_chip {
 	int (*of_xlate)(struct gpio_chip *gc,
 		        const struct of_phandle_args *gpiospec, u32 *flags);
 #endif
+#ifdef CONFIG_PINCTRL
+	/*
+	 * If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
+	 * describe the actual pin range which they serve in an SoC. This
+	 * information would be used by pinctrl subsystem to configure
+	 * corresponding pins for gpio usage.
+	 */
+	struct list_head pin_ranges;
+#endif
 };
 
 extern const char *gpiochip_is_requested(struct gpio_chip *chip,
diff --git a/include/linux/gpio.h b/include/linux/gpio.h
index 2e31e8b..a284459 100644
--- a/include/linux/gpio.h
+++ b/include/linux/gpio.h
@@ -231,6 +231,9 @@ static inline int irq_to_gpio(unsigned irq)
 	return -EINVAL;
 }
 
+void gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
+		unsigned int pin_base, unsigned int npins);
+void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
 #endif
 
 #endif /* __LINUX_GPIO_H */
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index eda0467..434e5a9 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -136,6 +136,23 @@ extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
 				unsigned nranges);
 extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
 				struct pinctrl_gpio_range *range);
+
+extern struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
+		struct pinctrl_gpio_range *range);
+
+#ifdef CONFIG_OF
+extern struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
+		struct pinctrl_gpio_range *range);
+#else
+static inline
+struct pinctrl_dev *of_pinctrl_add_gpio_range(struct device_node *np,
+		struct pinctrl_gpio_range *range)
+{
+	return NULL;
+}
+
+#endif /* CONFIG_OF */
+
 extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
 extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
 #else
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH V2 1/5] Revert "pinctrl: remove pinctrl_remove_gpio_range"
From: Viresh Kumar @ 2012-10-27  9:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351330569.git.viresh.kumar@linaro.org>

This reverts earlier commit which removed pinctrl_remove_gpio_range(), because
at that time there aren't any more users of that routine. It was removed as the
removal of ranges was done in unregister of pinctrl.

But because we are registering stuff from gpiolib now, we may remove and insert
a gpio module multiple times. So, we need that again.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---

This is V1 actually. Because it is part of this series, it is marked V2.

 drivers/pinctrl/core.c          | 14 ++++++++++++++
 include/linux/pinctrl/pinctrl.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index cec6072..b1086dc 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -346,6 +346,20 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
 EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
 
 /**
+ * pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
+ * @pctldev: pin controller device to remove the range from
+ * @range: the GPIO range to remove
+ */
+void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
+			       struct pinctrl_gpio_range *range)
+{
+	mutex_lock(&pinctrl_mutex);
+	list_del(&range->node);
+	mutex_unlock(&pinctrl_mutex);
+}
+EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
+
+/**
  * pinctrl_get_group_selector() - returns the group selector for a group
  * @pctldev: the pin controller handling the group
  * @pin_group: the pin group to look up
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 7d087f0..eda0467 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -134,6 +134,8 @@ extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
 extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
 				struct pinctrl_gpio_range *ranges,
 				unsigned nranges);
+extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
+				struct pinctrl_gpio_range *range);
 extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
 extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
 #else
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH V2 0/5] Pinctrl: SPEAr: Add support for plgpio driver
From: Viresh Kumar @ 2012-10-27  9:51 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Linus,

This patchset has an interesting history. It was first started by me. After i
left ST Shiraz took over and now i am back again :)

The idea of this series is to add plgpio support for SPEAr. PLGPIO's are pads
which can be configured as GPIO and so it is closely bound to pinctrl framework.

Some of these are sent earlier and Acked-by you. So, they will retain that. The
main bottleneck is still: 
  gpiolib: provide provision for gpiolib to register pin range

I have tried to fix most of your comments. Please see if they are fixed.

This is rebased over:

http://www.spinics.net/lists/arm-kernel/msg203465.html

--
viresh

Shiraz Hashim (1):
  gpiolib: provide provision for gpiolib to register pin range

Viresh Kumar (4):
  Revert "pinctrl: remove pinctrl_remove_gpio_range"
  pinctrl: SPEAr: Add plgpio driver
  pinctrl: SPEAr: Add gpio ranges support
  ARM: SPEAr: Add plgpio node in device tree dtsi files

 Documentation/devicetree/bindings/gpio/gpio.txt |  36 ++
 Documentation/gpio.txt                          |  26 +
 Documentation/pinctrl.txt                       |   3 +
 arch/arm/boot/dts/spear1310-evb.dts             |   4 +
 arch/arm/boot/dts/spear1310.dtsi                |  27 +
 arch/arm/boot/dts/spear1340-evb.dts             |   4 +
 arch/arm/boot/dts/spear1340.dtsi                |  26 +
 arch/arm/boot/dts/spear310.dtsi                 |  22 +-
 arch/arm/boot/dts/spear320-evb.dts              |   4 +
 arch/arm/boot/dts/spear320.dtsi                 |  23 +-
 drivers/gpio/gpiolib-of.c                       |  56 ++
 drivers/gpio/gpiolib.c                          |  43 ++
 drivers/pinctrl/core.c                          |  27 +
 drivers/pinctrl/devicetree.c                    |  13 +
 drivers/pinctrl/spear/Kconfig                   |  11 +
 drivers/pinctrl/spear/Makefile                  |   1 +
 drivers/pinctrl/spear/pinctrl-plgpio.c          | 746 ++++++++++++++++++++++++
 drivers/pinctrl/spear/pinctrl-spear.c           | 107 +++-
 drivers/pinctrl/spear/pinctrl-spear.h           |  46 ++
 drivers/pinctrl/spear/pinctrl-spear1310.c       | 264 +++++++++
 drivers/pinctrl/spear/pinctrl-spear300.c        |   2 +
 drivers/pinctrl/spear/pinctrl-spear310.c        |   2 +
 drivers/pinctrl/spear/pinctrl-spear320.c        |   2 +
 drivers/pinctrl/spear/pinctrl-spear3xx.c        |  37 ++
 include/asm-generic/gpio.h                      |  25 +
 include/linux/gpio.h                            |   3 +
 include/linux/pinctrl/pinctrl.h                 |  19 +
 27 files changed, 1560 insertions(+), 19 deletions(-)
 create mode 100644 drivers/pinctrl/spear/pinctrl-plgpio.c

-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply

* [GIT PULL] SPEAr pinctrl updates for v-3.5
From: viresh kumar @ 2012-10-27  9:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdZok471mc_XqogZo2orS7aCeMDSz0oxXfncm5HgMv37aw@mail.gmail.com>

Hi Linus,

Sorry for replying on very old thread. Actually i wanted to give
answer to some of
your review comments you already gave.

On Mon, Sep 3, 2012 at 5:18 PM, Linus Walleij <linus.walleij@linaro.org> wrote:
> On Sat, Sep 1, 2012 at 1:22 PM, shiraz hashim
> <shiraz.linux.kernel@gmail.com> wrote:

>> +2.1) gpio-controller and pinctrl subsystem
>> +------------------------------------------
>>

<...>

>> +   &pinctrl1 and &pinctrl2 is the phandle to the pinctrl DT node.
>> +
>> +   Next values specify the base pin and number of pins for the range
>> +   handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
>> +   pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
>> +   by this gpio controller.

> Also, you should put a big "DEPRECATED" mark on the old gpio
> range concept, and refer to the new way of doing things.

I have added following on reply to this request:

diff --git a/Documentation/pinctrl.txt b/Documentation/pinctrl.txt
index a1cd2f9..da40efb 100644
--- a/Documentation/pinctrl.txt
+++ b/Documentation/pinctrl.txt
@@ -364,6 +364,9 @@ will get an pin number into its handled number
range. Further it is also passed
 the range ID value, so that the pin controller knows which range it should
 deal with.

+Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see
+section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind
+pinctrl and gpio drivers.


>> diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h

>> +#ifdef CONFIG_PINCTRL
>
> There's no need to #ifdef this I think.

Actually there is, as definition of struct pinctrl_gpio_range is enclosed
in this config option.

>> +/**
>> + * struct gpio_pin_range - pin range controlled by a gpio chip
>> + * @head: list for maintaining set of pin ranges, used internally
>> + * @pctldev: pinctrl device which handles corresponding pins
>> + * @range: actual range of pins controlled by a gpio controller
>> + */
>> +
>> +struct gpio_pin_range {
>> +       struct list_head node;
>> +       struct pinctrl_dev *pctldev;
>> +       struct pinctrl_gpio_range range;
>> +};
>> +#endif

--
viresh

^ permalink raw reply related

* [PATCH 9/9] pinctrl: SPEAr1340: Add clcd sleep mode pin configuration
From: Viresh Kumar @ 2012-10-27  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351329224.git.viresh.kumar@linaro.org>

From: Vipul Kumar Samar <vipulkumar.samar@st.com>

CLCD pads must be configured differently for sleep mode. This patch adds support
for clcd_sleep_pingroup.

Signed-off-by: Vipul Kumar Samar <vipulkumar.samar@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/pinctrl/spear/pinctrl-spear1340.c | 39 ++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c
index 3963675..0606b8c 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1340.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1340.c
@@ -1692,7 +1692,43 @@ static struct spear_pingroup clcd_pingroup = {
 	.nmodemuxs = ARRAY_SIZE(clcd_modemux),
 };
 
-static const char *const clcd_grps[] = { "clcd_grp" };
+/* Disable cld runtime to save panel damage */
+static struct spear_muxreg clcd_sleep_muxreg[] = {
+	{
+		.reg = PAD_SHARED_IP_EN_1,
+		.mask = ARM_TRACE_MASK | MIPHY_DBG_MASK,
+		.val = 0,
+	}, {
+		.reg = PAD_FUNCTION_EN_5,
+		.mask = CLCD_REG4_MASK | CLCD_AND_ARM_TRACE_REG4_MASK,
+		.val = 0x0,
+	}, {
+		.reg = PAD_FUNCTION_EN_6,
+		.mask = CLCD_AND_ARM_TRACE_REG5_MASK,
+		.val = 0x0,
+	}, {
+		.reg = PAD_FUNCTION_EN_7,
+		.mask = CLCD_AND_ARM_TRACE_REG6_MASK,
+		.val = 0x0,
+	},
+};
+
+static struct spear_modemux clcd_sleep_modemux[] = {
+	{
+		.muxregs = clcd_sleep_muxreg,
+		.nmuxregs = ARRAY_SIZE(clcd_sleep_muxreg),
+	},
+};
+
+static struct spear_pingroup clcd_sleep_pingroup = {
+	.name = "clcd_sleep_grp",
+	.pins = clcd_pins,
+	.npins = ARRAY_SIZE(clcd_pins),
+	.modemuxs = clcd_sleep_modemux,
+	.nmodemuxs = ARRAY_SIZE(clcd_sleep_modemux),
+};
+
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_sleep_grp" };
 static struct spear_function clcd_function = {
 	.name = "clcd",
 	.groups = clcd_grps,
@@ -1893,6 +1929,7 @@ static struct spear_pingroup *spear1340_pingroups[] = {
 	&sdhci_pingroup,
 	&cf_pingroup,
 	&xd_pingroup,
+	&clcd_sleep_pingroup,
 	&clcd_pingroup,
 	&arm_trace_pingroup,
 	&miphy_dbg_pingroup,
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH 8/9] pinctrl: SPEAr1340: Make DDR reset & clock pads as gpio
From: Viresh Kumar @ 2012-10-27  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351329224.git.viresh.kumar@linaro.org>

From: Deepak Sikri <deepak.sikri@st.com>

Some gpio pins are used to control DDR reset and clock enable while the system
is moved into Low power. This patch adds in the corresponding GPIO entries in
the pads_as_gpio_pins to ensure the pads are available as gpio's.

Signed-off-by: Deepak Sikri <deepak.sikri@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/pinctrl/spear/pinctrl-spear1340.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/spear/pinctrl-spear1340.c b/drivers/pinctrl/spear/pinctrl-spear1340.c
index a0eb057..3963675 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1340.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1340.c
@@ -213,7 +213,7 @@ static const struct pinctrl_pin_desc spear1340_pins[] = {
  * Pad multiplexing for making all pads as gpio's. This is done to override the
  * values passed from bootloader and start from scratch.
  */
-static const unsigned pads_as_gpio_pins[] = { 251 };
+static const unsigned pads_as_gpio_pins[] = { 12, 88, 89, 251 };
 static struct spear_muxreg pads_as_gpio_muxreg[] = {
 	{
 		.reg = PAD_FUNCTION_EN_1,
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH 7/9] pinctrl: SPEAr1310: add register entries for enabling pad direction
From: Viresh Kumar @ 2012-10-27  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351329224.git.viresh.kumar@linaro.org>

From: Shiraz Hashim <shiraz.hashim@st.com>

Pad direction must also be updated for SPEAr1310, while setting pads values.
This patch adds support for that.

Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/pinctrl/spear/pinctrl-spear1310.c | 266 ++++++++++++++++++++++++++++++
 1 file changed, 266 insertions(+)

diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index a25ab73..0436fc7 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -164,6 +164,10 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
 	#define PMX_SSP0_CS0_MASK			(1 << 29)
 	#define PMX_SSP0_CS1_2_MASK			(1 << 30)
 
+#define PAD_DIRECTION_SEL_0				0x65C
+#define PAD_DIRECTION_SEL_1				0x660
+#define PAD_DIRECTION_SEL_2				0x664
+
 /* combined macros */
 #define PMX_GMII_MASK		(PMX_GMIICLK_MASK |			\
 				PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK |	\
@@ -237,6 +241,10 @@ static struct spear_muxreg i2c0_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_I2C0_MASK,
 		.val = PMX_I2C0_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_I2C0_MASK,
+		.val = PMX_I2C0_MASK,
 	},
 };
 
@@ -269,6 +277,10 @@ static struct spear_muxreg ssp0_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_SSP0_MASK,
 		.val = PMX_SSP0_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_SSP0_MASK,
+		.val = PMX_SSP0_MASK,
 	},
 };
 
@@ -294,6 +306,10 @@ static struct spear_muxreg ssp0_cs0_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_2,
 		.mask = PMX_SSP0_CS0_MASK,
 		.val = PMX_SSP0_CS0_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_SSP0_CS0_MASK,
+		.val = PMX_SSP0_CS0_MASK,
 	},
 };
 
@@ -319,6 +335,10 @@ static struct spear_muxreg ssp0_cs1_2_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_2,
 		.mask = PMX_SSP0_CS1_2_MASK,
 		.val = PMX_SSP0_CS1_2_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_SSP0_CS1_2_MASK,
+		.val = PMX_SSP0_CS1_2_MASK,
 	},
 };
 
@@ -352,6 +372,10 @@ static struct spear_muxreg i2s0_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_I2S0_MASK,
 		.val = PMX_I2S0_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_I2S0_MASK,
+		.val = PMX_I2S0_MASK,
 	},
 };
 
@@ -384,6 +408,10 @@ static struct spear_muxreg i2s1_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_I2S1_MASK,
 		.val = PMX_I2S1_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_I2S1_MASK,
+		.val = PMX_I2S1_MASK,
 	},
 };
 
@@ -418,6 +446,10 @@ static struct spear_muxreg clcd_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_CLCD1_MASK,
 		.val = PMX_CLCD1_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_CLCD1_MASK,
+		.val = PMX_CLCD1_MASK,
 	},
 };
 
@@ -443,6 +475,10 @@ static struct spear_muxreg clcd_high_res_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_CLCD2_MASK,
 		.val = PMX_CLCD2_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_CLCD2_MASK,
+		.val = PMX_CLCD2_MASK,
 	},
 };
 
@@ -479,6 +515,14 @@ static struct spear_muxreg arm_gpio_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_EGPIO_1_GRP_MASK,
 		.val = PMX_EGPIO_1_GRP_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_EGPIO_0_GRP_MASK,
+		.val = PMX_EGPIO_0_GRP_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_EGPIO_1_GRP_MASK,
+		.val = PMX_EGPIO_1_GRP_MASK,
 	},
 };
 
@@ -511,6 +555,10 @@ static struct spear_muxreg smi_2_chips_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_SMI_MASK,
 		.val = PMX_SMI_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_SMI_MASK,
+		.val = PMX_SMI_MASK,
 	},
 };
 
@@ -539,6 +587,14 @@ static struct spear_muxreg smi_4_chips_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
 		.val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_SMI_MASK,
+		.val = PMX_SMI_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+		.val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
 	},
 };
 
@@ -573,6 +629,10 @@ static struct spear_muxreg gmii_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_GMII_MASK,
 		.val = PMX_GMII_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_GMII_MASK,
+		.val = PMX_GMII_MASK,
 	},
 };
 
@@ -615,6 +675,18 @@ static struct spear_muxreg rgmii_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_2,
 		.mask = PMX_RGMII_REG2_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_RGMII_REG0_MASK,
+		.val = PMX_RGMII_REG0_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_RGMII_REG1_MASK,
+		.val = PMX_RGMII_REG1_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_RGMII_REG2_MASK,
+		.val = PMX_RGMII_REG2_MASK,
 	},
 };
 
@@ -649,6 +721,10 @@ static struct spear_muxreg smii_0_1_2_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_SMII_0_1_2_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_SMII_0_1_2_MASK,
+		.val = PMX_SMII_0_1_2_MASK,
 	},
 };
 
@@ -681,6 +757,10 @@ static struct spear_muxreg ras_mii_txclk_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_NFCE2_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_NFCE2_MASK,
+		.val = PMX_NFCE2_MASK,
 	},
 };
 
@@ -721,6 +801,14 @@ static struct spear_muxreg nand_8bit_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_NAND8BIT_1_MASK,
 		.val = PMX_NAND8BIT_1_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_NAND8BIT_0_MASK,
+		.val = PMX_NAND8BIT_0_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_NAND8BIT_1_MASK,
+		.val = PMX_NAND8BIT_1_MASK,
 	},
 };
 
@@ -747,6 +835,10 @@ static struct spear_muxreg nand_16bit_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_NAND16BIT_1_MASK,
 		.val = PMX_NAND16BIT_1_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_NAND16BIT_1_MASK,
+		.val = PMX_NAND16BIT_1_MASK,
 	},
 };
 
@@ -772,6 +864,10 @@ static struct spear_muxreg nand_4_chips_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_NAND_4CHIPS_MASK,
 		.val = PMX_NAND_4CHIPS_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_NAND_4CHIPS_MASK,
+		.val = PMX_NAND_4CHIPS_MASK,
 	},
 };
 
@@ -833,6 +929,10 @@ static struct spear_muxreg keyboard_rowcol6_8_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_KBD_ROWCOL68_MASK,
 		.val = PMX_KBD_ROWCOL68_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_KBD_ROWCOL68_MASK,
+		.val = PMX_KBD_ROWCOL68_MASK,
 	},
 };
 
@@ -866,6 +966,10 @@ static struct spear_muxreg uart0_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_UART0_MASK,
 		.val = PMX_UART0_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_UART0_MASK,
+		.val = PMX_UART0_MASK,
 	},
 };
 
@@ -891,6 +995,10 @@ static struct spear_muxreg uart0_modem_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_UART0_MODEM_MASK,
 		.val = PMX_UART0_MODEM_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_UART0_MODEM_MASK,
+		.val = PMX_UART0_MODEM_MASK,
 	},
 };
 
@@ -923,6 +1031,10 @@ static struct spear_muxreg gpt0_tmr0_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_GPT0_TMR0_MASK,
 		.val = PMX_GPT0_TMR0_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_GPT0_TMR0_MASK,
+		.val = PMX_GPT0_TMR0_MASK,
 	},
 };
 
@@ -948,6 +1060,10 @@ static struct spear_muxreg gpt0_tmr1_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_GPT0_TMR1_MASK,
 		.val = PMX_GPT0_TMR1_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_GPT0_TMR1_MASK,
+		.val = PMX_GPT0_TMR1_MASK,
 	},
 };
 
@@ -980,6 +1096,10 @@ static struct spear_muxreg gpt1_tmr0_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_GPT1_TMR0_MASK,
 		.val = PMX_GPT1_TMR0_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_GPT1_TMR0_MASK,
+		.val = PMX_GPT1_TMR0_MASK,
 	},
 };
 
@@ -1005,6 +1125,10 @@ static struct spear_muxreg gpt1_tmr1_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_GPT1_TMR1_MASK,
 		.val = PMX_GPT1_TMR1_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_GPT1_TMR1_MASK,
+		.val = PMX_GPT1_TMR1_MASK,
 	},
 };
 
@@ -1049,6 +1173,20 @@ static const unsigned mcif_pins[] = { 86, 87, 88, 89, 90, 91, 92, 93, 213, 214,
 		.reg = PAD_FUNCTION_EN_2,			\
 		.mask = PMX_MCIFALL_2_MASK,			\
 		.val = PMX_MCIFALL_2_MASK,			\
+	}, {							\
+		.reg = PAD_DIRECTION_SEL_0,			\
+		.mask = PMX_MCI_DATA8_15_MASK,			\
+		.val = PMX_MCI_DATA8_15_MASK,			\
+	}, {							\
+		.reg = PAD_DIRECTION_SEL_1,			\
+		.mask = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK |	\
+			PMX_NFWPRT2_MASK,			\
+		.val = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK |  \
+			PMX_NFWPRT2_MASK,			\
+	}, {							\
+		.reg = PAD_DIRECTION_SEL_2,			\
+		.mask = PMX_MCIFALL_2_MASK,			\
+		.val = PMX_MCIFALL_2_MASK,			\
 	}
 
 /* sdhci device */
@@ -1154,6 +1292,10 @@ static struct spear_muxreg touch_xy_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_2,
 		.mask = PMX_TOUCH_XY_MASK,
 		.val = PMX_TOUCH_XY_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_TOUCH_XY_MASK,
+		.val = PMX_TOUCH_XY_MASK,
 	},
 };
 
@@ -1187,6 +1329,10 @@ static struct spear_muxreg uart1_dis_i2c_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_I2C0_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_I2C0_MASK,
+		.val = PMX_I2C0_MASK,
 	},
 };
 
@@ -1213,6 +1359,12 @@ static struct spear_muxreg uart1_dis_sd_muxreg[] = {
 		.mask = PMX_MCIDATA1_MASK |
 			PMX_MCIDATA2_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_MCIDATA1_MASK |
+			PMX_MCIDATA2_MASK,
+		.val = PMX_MCIDATA1_MASK |
+			PMX_MCIDATA2_MASK,
 	},
 };
 
@@ -1246,6 +1398,10 @@ static struct spear_muxreg uart2_3_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_I2S0_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_I2S0_MASK,
+		.val = PMX_I2S0_MASK,
 	},
 };
 
@@ -1278,6 +1434,10 @@ static struct spear_muxreg uart4_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
+		.val = PMX_I2S0_MASK | PMX_CLCD1_MASK,
 	},
 };
 
@@ -1310,6 +1470,10 @@ static struct spear_muxreg uart5_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_CLCD1_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_CLCD1_MASK,
+		.val = PMX_CLCD1_MASK,
 	},
 };
 
@@ -1344,6 +1508,10 @@ static struct spear_muxreg rs485_0_1_tdm_0_1_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_CLCD1_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_CLCD1_MASK,
+		.val = PMX_CLCD1_MASK,
 	},
 };
 
@@ -1376,6 +1544,10 @@ static struct spear_muxreg i2c_1_2_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_CLCD1_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_CLCD1_MASK,
+		.val = PMX_CLCD1_MASK,
 	},
 };
 
@@ -1409,6 +1581,10 @@ static struct spear_muxreg i2c3_dis_smi_clcd_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
+		.val = PMX_CLCD1_MASK | PMX_SMI_MASK,
 	},
 };
 
@@ -1435,6 +1611,10 @@ static struct spear_muxreg i2c3_dis_sd_i2s0_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
+		.val = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
 	},
 };
 
@@ -1469,6 +1649,10 @@ static struct spear_muxreg i2c_4_5_dis_smi_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_0,
 		.mask = PMX_SMI_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_SMI_MASK,
+		.val = PMX_SMI_MASK,
 	},
 };
 
@@ -1499,6 +1683,14 @@ static struct spear_muxreg i2c4_dis_sd_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_2,
 		.mask = PMX_MCIDATA5_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_MCIDATA4_MASK,
+		.val = PMX_MCIDATA4_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_MCIDATA5_MASK,
+		.val = PMX_MCIDATA5_MASK,
 	},
 };
 
@@ -1526,6 +1718,12 @@ static struct spear_muxreg i2c5_dis_sd_muxreg[] = {
 		.mask = PMX_MCIDATA6_MASK |
 			PMX_MCIDATA7_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_MCIDATA6_MASK |
+			PMX_MCIDATA7_MASK,
+		.val = PMX_MCIDATA6_MASK |
+			PMX_MCIDATA7_MASK,
 	},
 };
 
@@ -1560,6 +1758,10 @@ static struct spear_muxreg i2c_6_7_dis_kbd_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_KBD_ROWCOL25_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_KBD_ROWCOL25_MASK,
+		.val = PMX_KBD_ROWCOL25_MASK,
 	},
 };
 
@@ -1587,6 +1789,12 @@ static struct spear_muxreg i2c6_dis_sd_muxreg[] = {
 		.mask = PMX_MCIIORDRE_MASK |
 			PMX_MCIIOWRWE_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_MCIIORDRE_MASK |
+			PMX_MCIIOWRWE_MASK,
+		.val = PMX_MCIIORDRE_MASK |
+			PMX_MCIIOWRWE_MASK,
 	},
 };
 
@@ -1613,6 +1821,12 @@ static struct spear_muxreg i2c7_dis_sd_muxreg[] = {
 		.mask = PMX_MCIRESETCF_MASK |
 			PMX_MCICS0CE_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_MCIRESETCF_MASK |
+			PMX_MCICS0CE_MASK,
+		.val = PMX_MCIRESETCF_MASK |
+			PMX_MCICS0CE_MASK,
 	},
 };
 
@@ -1651,6 +1865,14 @@ static struct spear_muxreg can0_dis_nor_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_NFRSTPWDWN3_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_NFRSTPWDWN2_MASK,
+		.val = PMX_NFRSTPWDWN2_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_NFRSTPWDWN3_MASK,
+		.val = PMX_NFRSTPWDWN3_MASK,
 	},
 };
 
@@ -1677,6 +1899,10 @@ static struct spear_muxreg can0_dis_sd_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_2,
 		.mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
+		.val = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
 	},
 };
 
@@ -1711,6 +1937,10 @@ static struct spear_muxreg can1_dis_sd_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_2,
 		.mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
+		.val = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
 	},
 };
 
@@ -1737,6 +1967,10 @@ static struct spear_muxreg can1_dis_kbd_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_1,
 		.mask = PMX_KBD_ROWCOL25_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_KBD_ROWCOL25_MASK,
+		.val = PMX_KBD_ROWCOL25_MASK,
 	},
 };
 
@@ -1782,6 +2016,18 @@ static struct spear_muxreg pci_muxreg[] = {
 		.reg = PAD_FUNCTION_EN_2,
 		.mask = PMX_PCI_REG2_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_0,
+		.mask = PMX_MCI_DATA8_15_MASK,
+		.val = PMX_MCI_DATA8_15_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_PCI_REG1_MASK,
+		.val = PMX_PCI_REG1_MASK,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_PCI_REG2_MASK,
+		.val = PMX_PCI_REG2_MASK,
 	},
 };
 
@@ -1964,6 +2210,14 @@ static struct spear_muxreg ssp1_dis_kbd_muxreg[] = {
 			PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
 			PMX_NFCE2_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_1,
+		.mask = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+			PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+			PMX_NFCE2_MASK,
+		.val = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+			PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+			PMX_NFCE2_MASK,
 	},
 };
 
@@ -1990,6 +2244,12 @@ static struct spear_muxreg ssp1_dis_sd_muxreg[] = {
 		.mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
 			PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+			PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
+		.val = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+			PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
 	},
 };
 
@@ -2024,6 +2284,12 @@ static struct spear_muxreg gpt64_muxreg[] = {
 		.mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
 			| PMX_MCILEDS_MASK,
 		.val = 0,
+	}, {
+		.reg = PAD_DIRECTION_SEL_2,
+		.mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+			| PMX_MCILEDS_MASK,
+		.val = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+			| PMX_MCILEDS_MASK,
 	},
 };
 
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH 6/9] pinctrl: SPEAr1310: Separate out pci pins from pcie_sata pin group
From: Viresh Kumar @ 2012-10-27  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351329224.git.viresh.kumar@linaro.org>

From: Vipul Kumar Samar <vipulkumar.samar@st.com>

SPEAr1310 has separate PCI and PCIe implementations which are not muxed with
each other. Presently they have been implemented as muxed together with SATA and
are represented wrongly in the software.

In reality only PCIe and SATA implementations are muxed with each other. This
patch separates out pci pins creating a new pingroup and function for pci.

Signed-off-by: Vipul Kumar Samar <vipulkumar.samar@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Shiraz Hashim <shiraz.hashim@st.com>
---
 drivers/pinctrl/spear/pinctrl-spear1310.c | 93 +++++++++++++++++--------------
 1 file changed, 51 insertions(+), 42 deletions(-)

diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index baf98ae..a25ab73 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -1763,29 +1763,52 @@ static struct spear_function can1_function = {
 	.ngroups = ARRAY_SIZE(can1_grps),
 };
 
-/* Pad multiplexing for pci device */
-static const unsigned pci_sata_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
+/* Pad multiplexing for (ras-ip) pci device */
+static const unsigned pci_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
 	19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
 	37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
 	55, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 };
-#define PCI_SATA_MUXREG				\
-	{					\
-		.reg = PAD_FUNCTION_EN_0,	\
-		.mask = PMX_MCI_DATA8_15_MASK,	\
-		.val = 0,			\
-	}, {					\
-		.reg = PAD_FUNCTION_EN_1,	\
-		.mask = PMX_PCI_REG1_MASK,	\
-		.val = 0,			\
-	}, {					\
-		.reg = PAD_FUNCTION_EN_2,	\
-		.mask = PMX_PCI_REG2_MASK,	\
-		.val = 0,			\
-	}
 
-/* pad multiplexing for pcie0 device */
+static struct spear_muxreg pci_muxreg[] = {
+	{
+		.reg = PAD_FUNCTION_EN_0,
+		.mask = PMX_MCI_DATA8_15_MASK,
+		.val = 0,
+	}, {
+		.reg = PAD_FUNCTION_EN_1,
+		.mask = PMX_PCI_REG1_MASK,
+		.val = 0,
+	}, {
+		.reg = PAD_FUNCTION_EN_2,
+		.mask = PMX_PCI_REG2_MASK,
+		.val = 0,
+	},
+};
+
+static struct spear_modemux pci_modemux[] = {
+	{
+		.muxregs = pci_muxreg,
+		.nmuxregs = ARRAY_SIZE(pci_muxreg),
+	},
+};
+
+static struct spear_pingroup pci_pingroup = {
+	.name = "pci_grp",
+	.pins = pci_pins,
+	.npins = ARRAY_SIZE(pci_pins),
+	.modemuxs = pci_modemux,
+	.nmodemuxs = ARRAY_SIZE(pci_modemux),
+};
+
+static const char *const pci_grps[] = { "pci_grp" };
+static struct spear_function pci_function = {
+	.name = "pci",
+	.groups = pci_grps,
+	.ngroups = ARRAY_SIZE(pci_grps),
+};
+
+/* pad multiplexing for (fix-part) pcie0 device */
 static struct spear_muxreg pcie0_muxreg[] = {
-	PCI_SATA_MUXREG,
 	{
 		.reg = PCIE_SATA_CFG,
 		.mask = PCIE_CFG_VAL(0),
@@ -1802,15 +1825,12 @@ static struct spear_modemux pcie0_modemux[] = {
 
 static struct spear_pingroup pcie0_pingroup = {
 	.name = "pcie0_grp",
-	.pins = pci_sata_pins,
-	.npins = ARRAY_SIZE(pci_sata_pins),
 	.modemuxs = pcie0_modemux,
 	.nmodemuxs = ARRAY_SIZE(pcie0_modemux),
 };
 
-/* pad multiplexing for pcie1 device */
+/* pad multiplexing for (fix-part) pcie1 device */
 static struct spear_muxreg pcie1_muxreg[] = {
-	PCI_SATA_MUXREG,
 	{
 		.reg = PCIE_SATA_CFG,
 		.mask = PCIE_CFG_VAL(1),
@@ -1827,15 +1847,12 @@ static struct spear_modemux pcie1_modemux[] = {
 
 static struct spear_pingroup pcie1_pingroup = {
 	.name = "pcie1_grp",
-	.pins = pci_sata_pins,
-	.npins = ARRAY_SIZE(pci_sata_pins),
 	.modemuxs = pcie1_modemux,
 	.nmodemuxs = ARRAY_SIZE(pcie1_modemux),
 };
 
-/* pad multiplexing for pcie2 device */
+/* pad multiplexing for (fix-part) pcie2 device */
 static struct spear_muxreg pcie2_muxreg[] = {
-	PCI_SATA_MUXREG,
 	{
 		.reg = PCIE_SATA_CFG,
 		.mask = PCIE_CFG_VAL(2),
@@ -1852,22 +1869,20 @@ static struct spear_modemux pcie2_modemux[] = {
 
 static struct spear_pingroup pcie2_pingroup = {
 	.name = "pcie2_grp",
-	.pins = pci_sata_pins,
-	.npins = ARRAY_SIZE(pci_sata_pins),
 	.modemuxs = pcie2_modemux,
 	.nmodemuxs = ARRAY_SIZE(pcie2_modemux),
 };
 
-static const char *const pci_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" };
-static struct spear_function pci_function = {
-	.name = "pci",
-	.groups = pci_grps,
-	.ngroups = ARRAY_SIZE(pci_grps),
+static const char *const pcie_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp"
+};
+static struct spear_function pcie_function = {
+	.name = "pci_express",
+	.groups = pcie_grps,
+	.ngroups = ARRAY_SIZE(pcie_grps),
 };
 
 /* pad multiplexing for sata0 device */
 static struct spear_muxreg sata0_muxreg[] = {
-	PCI_SATA_MUXREG,
 	{
 		.reg = PCIE_SATA_CFG,
 		.mask = SATA_CFG_VAL(0),
@@ -1884,15 +1899,12 @@ static struct spear_modemux sata0_modemux[] = {
 
 static struct spear_pingroup sata0_pingroup = {
 	.name = "sata0_grp",
-	.pins = pci_sata_pins,
-	.npins = ARRAY_SIZE(pci_sata_pins),
 	.modemuxs = sata0_modemux,
 	.nmodemuxs = ARRAY_SIZE(sata0_modemux),
 };
 
 /* pad multiplexing for sata1 device */
 static struct spear_muxreg sata1_muxreg[] = {
-	PCI_SATA_MUXREG,
 	{
 		.reg = PCIE_SATA_CFG,
 		.mask = SATA_CFG_VAL(1),
@@ -1909,15 +1921,12 @@ static struct spear_modemux sata1_modemux[] = {
 
 static struct spear_pingroup sata1_pingroup = {
 	.name = "sata1_grp",
-	.pins = pci_sata_pins,
-	.npins = ARRAY_SIZE(pci_sata_pins),
 	.modemuxs = sata1_modemux,
 	.nmodemuxs = ARRAY_SIZE(sata1_modemux),
 };
 
 /* pad multiplexing for sata2 device */
 static struct spear_muxreg sata2_muxreg[] = {
-	PCI_SATA_MUXREG,
 	{
 		.reg = PCIE_SATA_CFG,
 		.mask = SATA_CFG_VAL(2),
@@ -1934,8 +1943,6 @@ static struct spear_modemux sata2_modemux[] = {
 
 static struct spear_pingroup sata2_pingroup = {
 	.name = "sata2_grp",
-	.pins = pci_sata_pins,
-	.npins = ARRAY_SIZE(pci_sata_pins),
 	.modemuxs = sata2_modemux,
 	.nmodemuxs = ARRAY_SIZE(sata2_modemux),
 };
@@ -2093,6 +2100,7 @@ static struct spear_pingroup *spear1310_pingroups[] = {
 	&can0_dis_sd_pingroup,
 	&can1_dis_sd_pingroup,
 	&can1_dis_kbd_pingroup,
+	&pci_pingroup,
 	&pcie0_pingroup,
 	&pcie1_pingroup,
 	&pcie2_pingroup,
@@ -2138,6 +2146,7 @@ static struct spear_function *spear1310_functions[] = {
 	&can0_function,
 	&can1_function,
 	&pci_function,
+	&pcie_function,
 	&sata_function,
 	&ssp1_function,
 	&gpt64_function,
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH 5/9] pinctrl: SPEAr1310: Fix value of PERIP_CFG reigster and MCIF_SEL_SHIFT
From: Viresh Kumar @ 2012-10-27  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351329224.git.viresh.kumar@linaro.org>

From: Vipul Kumar Samar <vipulkumar.samar@st.com>

This patch fixes two macros: PERIP_CFG registers offset and MCIF selection
shift.

Signed-off-by: Vipul Kumar Samar <vipulkumar.samar@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/pinctrl/spear/pinctrl-spear1310.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index c720d09..baf98ae 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -25,8 +25,8 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
 };
 
 /* registers */
-#define PERIP_CFG					0x32C
-	#define MCIF_SEL_SHIFT				3
+#define PERIP_CFG					0x3B0
+	#define MCIF_SEL_SHIFT				5
 	#define MCIF_SEL_SD				(0x1 << MCIF_SEL_SHIFT)
 	#define MCIF_SEL_CF				(0x2 << MCIF_SEL_SHIFT)
 	#define MCIF_SEL_XD				(0x3 << MCIF_SEL_SHIFT)
-- 
1.7.12.rc2.18.g61b472e

^ permalink raw reply related

* [PATCH 4/9] pinctrl: SPEAr1310: fix clcd high resolution pin group name
From: Viresh Kumar @ 2012-10-27  9:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1351329224.git.viresh.kumar@linaro.org>

From: Shiraz Hashim <shiraz.hashim@st.com>

All group names in SPEAr pinctrl have "_grp" at the end of their name. Do the
same for clcd_high_res_grp.

Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
 drivers/pinctrl/spear/pinctrl-spear1310.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pinctrl/spear/pinctrl-spear1310.c b/drivers/pinctrl/spear/pinctrl-spear1310.c
index d6cca8c..c720d09 100644
--- a/drivers/pinctrl/spear/pinctrl-spear1310.c
+++ b/drivers/pinctrl/spear/pinctrl-spear1310.c
@@ -461,7 +461,7 @@ static struct spear_pingroup clcd_high_res_pingroup = {
 	.nmodemuxs = ARRAY_SIZE(clcd_high_res_modemux),
 };
 
-static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res" };
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res_grp" };
 static struct spear_function clcd_function = {
 	.name = "clcd",
 	.groups = clcd_grps,
-- 
1.7.12.rc2.18.g61b472e

^ 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