diff mbox

[v4,03/10] pinctrl: mvebu: kirkwood pinctrl driver

Message ID 1347550912-18021-4-git-send-email-sebastian.hesselbarth@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sebastian Hesselbarth Sept. 13, 2012, 3:41 p.m. UTC
This patch adds a SoC specific pinctrl driver for Marvell Kirkwood SoCs
plus DT binding documentation. This driver will use the mvebu pinctrl
driver core.

Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
---
v2:
- restructured pinctrl/Kconfig to hide pinctrl driver as it will be
  always selected by arch/arm/mach-mvebu/Kconfig
- use enum for kirkwood variants instead of defines

v3:
- moved variant specific data to DT match struct

v4:
- fix bogus v3 patch set

Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Lior Amsalem <alior@marvell.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Gregory CLEMENT <gregory.clement@free-electrons.com>
Cc: Ben Dooks <ben.dooks@codethink.co.uk>
Cc: Linus Walleij <linus.walleij@linaro.org>
Cc: Stephen Warren <swarren@wwwdotorg.org>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-arm-kernel@lists.infradead.org
---
 .../bindings/pinctrl/marvell,kirkwood-pinctrl.txt  |  279 ++++++++++++
 drivers/pinctrl/Kconfig                            |    4 +
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-kirkwood.c                 |  472 ++++++++++++++++++++
 4 files changed, 756 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
 create mode 100644 drivers/pinctrl/pinctrl-kirkwood.c

Comments

Andrew Lunn Sept. 16, 2012, 7:46 a.m. UTC | #1
> +++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
> @@ -0,0 +1,279 @@
> +* Marvell Kirkwood SoC pinctrl driver for mpp
> +
> +Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
> +part and usage.
> +
> +Required properties:
> +- compatible: "marvell,88f6180-pinctrl",
> +              "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
> +              "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
> +
> +This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628

Hi Sebastian 

The current MPP code determines for itself what chip it is running on.
It can then check if a pin configuration is valid for the current
run time environment.

Here you are suggesting we have to put into the DT what chip we expect
to be on.

What is the advantage of this, over getting the information from the
device itself?

If i wanted to mass convert all existing kirkwood DT boards over to
use pinctrl, im stuck at the very first step. I've no idea what chip
they use, it was not relevant before.

Thanks
	Andrew
Sebastian Hesselbarth Sept. 16, 2012, 9:09 a.m. UTC | #2
On 09/16/2012 09:46 AM, Andrew Lunn wrote:
>> +Required properties:
>> +- compatible: "marvell,88f6180-pinctrl",
>> +              "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
>> +              "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
>> +
>> +This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628
>
> The current MPP code determines for itself what chip it is running on.
> It can then check if a pin configuration is valid for the current
> run time environment.
>
> Here you are suggesting we have to put into the DT what chip we expect
> to be on.
>
> What is the advantage of this, over getting the information from the
> device itself?

Hi Andrew,

there is no advantage over determining the variant on run time except
that it is statically and (normally) known at boot time. I understand
that mass converting kirkwood to pinctrl would require to know all
the different variants.

If there are no objections from the others, I agree to determine the
variant from the existing kirkwood_id(). I was just unsure if it is
ok to use platform-specific code with DT here.

Any ideas how to get kirkwood_id() linked into pinctrl-kirkwood with
the get-rid-of-arch-includes policy?

Sebastian
Jason Cooper Sept. 16, 2012, 12:40 p.m. UTC | #3
On Sun, Sep 16, 2012 at 09:46:52AM +0200, Andrew Lunn wrote:
> > +++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
> > @@ -0,0 +1,279 @@
> > +* Marvell Kirkwood SoC pinctrl driver for mpp
> > +
> > +Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
> > +part and usage.
> > +
> > +Required properties:
> > +- compatible: "marvell,88f6180-pinctrl",
> > +              "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
> > +              "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
> > +
> > +This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628
> 
> Hi Sebastian 
> 
> The current MPP code determines for itself what chip it is running on.
> It can then check if a pin configuration is valid for the current
> run time environment.
> 
> Here you are suggesting we have to put into the DT what chip we expect
> to be on.
> 
> What is the advantage of this, over getting the information from the
> device itself?

The DT should describe the hardware as accurately as possible.  We can't
always assume Linux will be the only thing the DT is handed off to.

> If i wanted to mass convert all existing kirkwood DT boards over to
> use pinctrl, im stuck at the very first step. I've no idea what chip
> they use, it was not relevant before.

Let's try to do the DT correctly, and create a migration path for
kirkwood to work first, then migrate to using the DT fully.

thx,

Jason.
Nicolas Pitre Sept. 17, 2012, 1:55 a.m. UTC | #4
On Sun, 16 Sep 2012, Jason Cooper wrote:

> On Sun, Sep 16, 2012 at 09:46:52AM +0200, Andrew Lunn wrote:
> > > +++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
> > > @@ -0,0 +1,279 @@
> > > +* Marvell Kirkwood SoC pinctrl driver for mpp
> > > +
> > > +Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
> > > +part and usage.
> > > +
> > > +Required properties:
> > > +- compatible: "marvell,88f6180-pinctrl",
> > > +              "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
> > > +              "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
> > > +
> > > +This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628
> > 
> > Hi Sebastian 
> > 
> > The current MPP code determines for itself what chip it is running on.
> > It can then check if a pin configuration is valid for the current
> > run time environment.
> > 
> > Here you are suggesting we have to put into the DT what chip we expect
> > to be on.
> > 
> > What is the advantage of this, over getting the information from the
> > device itself?
> 
> The DT should describe the hardware as accurately as possible.  We can't
> always assume Linux will be the only thing the DT is handed off to.
> 
> > If i wanted to mass convert all existing kirkwood DT boards over to
> > use pinctrl, im stuck at the very first step. I've no idea what chip
> > they use, it was not relevant before.
> 
> Let's try to do the DT correctly, and create a migration path for
> kirkwood to work first, then migrate to using the DT fully.

Beware beware.

The DT should of course describe the hardware as accurately as possible.  
That doesn't necessarily mean it should describe the hardware as 
_extensively_ as possible.

And that doesn't mean that all the information found in the DT has to be 
consumed by the kernel either.

Any information that can be *probed* at run time has no benefit being 
stuffed in a DT.  That's true whether it is Linux or another operating 
system.  The more that can be probed at run time the better.


Nicolas
Sebastian Hesselbarth Sept. 17, 2012, 6:36 a.m. UTC | #5
On 09/17/2012 03:55 AM, Nicolas Pitre wrote:
> On Sun, 16 Sep 2012, Jason Cooper wrote:
>> On Sun, Sep 16, 2012 at 09:46:52AM +0200, Andrew Lunn wrote:
>>>> +++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
>>>> @@ -0,0 +1,279 @@
>>>> +* Marvell Kirkwood SoC pinctrl driver for mpp
>>>> +
>>>> +Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
>>>> +part and usage.
>>>> +
>>>> +Required properties:
>>>> +- compatible: "marvell,88f6180-pinctrl",
>>>> +              "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
>>>> +              "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
>>>> +
>>>> +This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628
 >>> ...
>>> If i wanted to mass convert all existing kirkwood DT boards over to
>>> use pinctrl, im stuck at the very first step. I've no idea what chip
>>> they use, it was not relevant before.
>>
>> Let's try to do the DT correctly, and create a migration path for
>> kirkwood to work first, then migrate to using the DT fully.
>
> Beware beware.
>
> The DT should of course describe the hardware as accurately as possible.
> That doesn't necessarily mean it should describe the hardware as
> _extensively_ as possible.
>
> And that doesn't mean that all the information found in the DT has to be
> consumed by the kernel either.
>
> Any information that can be *probed* at run time has no benefit being
> stuffed in a DT.  That's true whether it is Linux or another operating
> system.  The more that can be probed at run time the better.

I had a closer look at how kirkwood probes its id. I mentionend kirkwood_id()
earlier but in fact it is kirkwood_pcie_id(). I assume pcie registers are shut
down with pcie clk gated? That would require to have pcie running at least at
boot-time on all boards.

While it is still possible to grab the id and power down pcie later, I still
think that using five different compatible strings is better here. Of course,
there is some effort to obtain the kirkwood SoC variant for all boards.

Sebastian
Andrew Lunn Sept. 17, 2012, 8:32 a.m. UTC | #6
> I had a closer look at how kirkwood probes its id. I mentionend kirkwood_id()
> earlier but in fact it is kirkwood_pcie_id(). I assume pcie registers are shut
> down with pcie clk gated? That would require to have pcie running at least at
> boot-time on all boards.
> 
> While it is still possible to grab the id and power down pcie later, I still
> think that using five different compatible strings is better here. Of course,
> there is some effort to obtain the kirkwood SoC variant for all boards.

Hi Sebastian

I did the monkey work last night for converting all existing kirkwood
DT boards over to pinctrl. I noticed that in all the DT descriptions,
they all declare themselves as 88f6281. This is probably cut/paste
from the first board we ever had. For these boards, i doubt it will be
a problem, finding out what chip is really used, as there are active
maintainers. The problem comes with old style devices which we want to
convert. But if we do the monkey work for older boards, we are going
to have to find testers anyway and they can tell us what SoC is used.

Having said that, not probing the hardware, having it configurable is
a source of errors. We already probe the hardware in order to display:

Kirkwood: MV88F6282-Rev-A0, TCLK=200000000.

so we just need to cache this and make it available to anybody who
wants it.

I'm surprised we don't have the infrastructure of this already. We
have info about the CPU, e.g.

cat /proc/cpuinfo 
Processor	  : Feroceon 88FR131 rev 1 (v5l)
BogoMIPS	  : 1587.60
Features	  : swp half thumb fastmult edsp 
CPU implementer	  : 0x56
CPU architecture: 5TE
CPU variant	  : 0x2
CPU part	  : 0x131
CPU revision	  : 1

Hardware	  : Marvell Kirkwood (Flattened Device Tree)
Revision	  : 0000
Serial		    : 0000000000000000

but don't seem to have anything about the SoC the CPU is embedded in.

AT91 has at91_get_soc_type(struct at91_socinfo *c) which is what we
would need for Kirkwood. However, interestingly, its never used
outside of arch/arm/mach-at91/setup.c!

davinci has a global structure davinci_soc_info which
gpio/gpio-davinci.c uses.

So we would not be the only architecture making such information
available. We just need to make sure we do it such that its multi-arch
kernel compatible.

       Andrew
Linus Walleij Sept. 17, 2012, 8:45 a.m. UTC | #7
On Sun, Sep 16, 2012 at 11:09 AM, Sebastian Hesselbarth
<sebastian.hesselbarth@gmail.com> wrote:
> On 09/16/2012 09:46 AM, Andrew Lunn wrote:

>> Here you are suggesting we have to put into the DT what chip we expect
>> to be on.
>>
>> What is the advantage of this, over getting the information from the
>> device itself?
>
> If there are no objections from the others, I agree to determine the
> variant from the existing kirkwood_id(). I was just unsure if it is
> ok to use platform-specific code with DT here.
>
> Any ideas how to get kirkwood_id() linked into pinctrl-kirkwood with
> the get-rid-of-arch-includes policy?

You found the weak spot between two consolidation tracks.

Getting rid of a broadcast autodetect functions from say
<mach/foo-id-probe.h> is nominally done by passing the data
to the driver as platform data instead, and only using
these functions in the mach-foo folder when populating
platform data, and thus it can be made into a local
header, say mach-foo/foo-id-probe.h

So the machine/arch code reads these registers to
populate the platform data and device drivers only
look at the platform data, which has some enum or
bool indicating what hardware it's running on, cool.

But according to the other consolidation track, platform
data should go into device tree bindings.

So the conclusion is that the DT must contain the data
about the platform, so it's not auto-probed by the kernel.
(I.e. the kernel reads no registers to figure out what hardware
this is, that stuff comes from the device tree.)

DT purists will say that the boot loader should ask the chipset
what it is with the same register writes and populate the
DT accordingly, instead of loading a precompiled blob.
Some may even ponder the crazy concept of amending the
DT in the kernel at early boot.

But in practice someone will give up, encode the stuff in
the static device tree and autoprobing of the platform
goes out the window.

Yours,
Linus Walleij
Andrew Lunn Sept. 18, 2012, 6:59 p.m. UTC | #8
On Thu, Sep 13, 2012 at 05:41:45PM +0200, Sebastian Hesselbarth wrote:
> This patch adds a SoC specific pinctrl driver for Marvell Kirkwood SoCs
> plus DT binding documentation. This driver will use the mvebu pinctrl
> driver core.
> 
> Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> ---
> v2:
> - restructured pinctrl/Kconfig to hide pinctrl driver as it will be
>   always selected by arch/arm/mach-mvebu/Kconfig
> - use enum for kirkwood variants instead of defines
> 
> v3:
> - moved variant specific data to DT match struct
> 
> v4:
> - fix bogus v3 patch set


Since Linus Walleij thinks that autoprobing is not going to happen, 

Tested-by: Andrew Lunn <andrew@lunn.ch>

However, i still think it would be nice to have auto probing.

	 Andrew

> Cc: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
> Cc: Grant Likely <grant.likely@secretlab.ca>
> Cc: Rob Herring <rob.herring@calxeda.com>
> Cc: Rob Landley <rob@landley.net>
> Cc: Russell King <linux@arm.linux.org.uk>
> Cc: Lior Amsalem <alior@marvell.com>
> Cc: Andrew Lunn <andrew@lunn.ch>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Gregory CLEMENT <gregory.clement@free-electrons.com>
> Cc: Ben Dooks <ben.dooks@codethink.co.uk>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Stephen Warren <swarren@wwwdotorg.org>
> Cc: devicetree-discuss@lists.ozlabs.org
> Cc: linux-doc@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> ---
>  .../bindings/pinctrl/marvell,kirkwood-pinctrl.txt  |  279 ++++++++++++
>  drivers/pinctrl/Kconfig                            |    4 +
>  drivers/pinctrl/Makefile                           |    1 +
>  drivers/pinctrl/pinctrl-kirkwood.c                 |  472 ++++++++++++++++++++
>  4 files changed, 756 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
>  create mode 100644 drivers/pinctrl/pinctrl-kirkwood.c
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
> new file mode 100644
> index 0000000..361bccb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
> @@ -0,0 +1,279 @@
> +* Marvell Kirkwood SoC pinctrl driver for mpp
> +
> +Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
> +part and usage.
> +
> +Required properties:
> +- compatible: "marvell,88f6180-pinctrl",
> +              "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
> +              "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
> +
> +This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x.
> +
> +Available mpp pins/groups and functions:
> +Note: brackets (x) are not part of the mpp name for marvell,function and given
> +only for more detailed description in this document.
> +
> +* Marvell Kirkwood 88f6180
> +
> +name          pins     functions
> +================================================================================
> +mpp0          0        gpio, nand(io2), spi(cs)
> +mpp1          1        gpo, nand(io3), spi(mosi)
> +mpp2          2        gpo, nand(io4), spi(sck)
> +mpp3          3        gpo, nand(io5), spi(miso)
> +mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk)
> +mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig)
> +mpp6          6        sysrst(out), spi(mosi), ptp(trig)
> +mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
> +mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
> +                       mii(col)
> +mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
> +                       mii(crs)
> +mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig)
> +mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
> +                       ptp-2(trig)
> +mpp12         12       gpo, sdio(clk)
> +mpp13         13       gpio, sdio(cmd), uart1(txd)
> +mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col)
> +mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd)
> +mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs)
> +mpp17         17       gpio, sdio(d3)
> +mpp18         18       gpo, nand(io0)
> +mpp19         19       gpo, nand(io1)
> +mpp20         20       gpio, mii(rxerr)
> +mpp21         21       gpio, audio(spdifi)
> +mpp22         22       gpio, audio(spdifo)
> +mpp23         23       gpio, audio(rmclk)
> +mpp24         24       gpio, audio(bclk)
> +mpp25         25       gpio, audio(sdo)
> +mpp26         26       gpio, audio(lrclk)
> +mpp27         27       gpio, audio(mclk)
> +mpp28         28       gpio, audio(sdi)
> +mpp29         29       gpio, audio(extclk)
> +
> +* Marvell Kirkwood 88f6190
> +
> +name          pins     functions
> +================================================================================
> +mpp0          0        gpio, nand(io2), spi(cs)
> +mpp1          1        gpo, nand(io3), spi(mosi)
> +mpp2          2        gpo, nand(io4), spi(sck)
> +mpp3          3        gpo, nand(io5), spi(miso)
> +mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk)
> +mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
> +mpp6          6        sysrst(out), spi(mosi), ptp(trig)
> +mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
> +mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
> +                       mii(col), mii-1(rxerr)
> +mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
> +                       mii(crs), sata0(prsnt)
> +mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig)
> +mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
> +                       ptp-2(trig), sata0(act)
> +mpp12         12       gpo, sdio(clk)
> +mpp13         13       gpio, sdio(cmd), uart1(txd)
> +mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col)
> +mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
> +mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs)
> +mpp17         17       gpio, sdio(d3), sata0(prsnt)
> +mpp18         18       gpo, nand(io0)
> +mpp19         19       gpo, nand(io1)
> +mpp20         20       gpio, ge1(txd0)
> +mpp21         21       gpio, ge1(txd1), sata0(act)
> +mpp22         22       gpio, ge1(txd2)
> +mpp23         23       gpio, ge1(txd3), sata0(prsnt)
> +mpp24         24       gpio, ge1(rxd0)
> +mpp25         25       gpio, ge1(rxd1)
> +mpp26         26       gpio, ge1(rxd2)
> +mpp27         27       gpio, ge1(rxd3)
> +mpp28         28       gpio, ge1(col)
> +mpp29         29       gpio, ge1(txclk)
> +mpp30         30       gpio, ge1(rxclk)
> +mpp31         31       gpio, ge1(rxclk)
> +mpp32         32       gpio, ge1(txclko)
> +mpp33         33       gpo, ge1(txclk)
> +mpp34         34       gpio, ge1(txen)
> +mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr)
> +
> +* Marvell Kirkwood 88f6192
> +
> +name          pins     functions
> +================================================================================
> +mpp0          0        gpio, nand(io2), spi(cs)
> +mpp1          1        gpo, nand(io3), spi(mosi)
> +mpp2          2        gpo, nand(io4), spi(sck)
> +mpp3          3        gpo, nand(io5), spi(miso)
> +mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act)
> +mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
> +mpp6          6        sysrst(out), spi(mosi), ptp(trig)
> +mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
> +mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
> +                       mii(col), mii-1(rxerr), sata1(prsnt)
> +mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
> +                       mii(crs), sata0(prsnt)
> +mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig), sata1(act)
> +mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
> +                       ptp-2(trig), sata0(act)
> +mpp12         12       gpo, sdio(clk)
> +mpp13         13       gpio, sdio(cmd), uart1(txd)
> +mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt)
> +mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
> +mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
> +                       sata1(act)
> +mpp17         17       gpio, sdio(d3), sata0(prsnt)
> +mpp18         18       gpo, nand(io0)
> +mpp19         19       gpo, nand(io1)
> +mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
> +                       sata1(act)
> +mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
> +                       audio(spdifo)
> +mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
> +                       sata1(prsnt)
> +mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
> +                       audio(bclk)
> +mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo)
> +mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk)
> +mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk)
> +mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi)
> +mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk)
> +mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst)
> +mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk)
> +mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs)
> +mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx)
> +mpp33         33       gpo, ge1(txclk), tdm(drx)
> +mpp34         34       gpio, ge1(txen), tdm(spi-cs1)
> +mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql)
> +
> +* Marvell Kirkwood 88f6281
> +
> +name          pins     functions
> +================================================================================
> +mpp0          0        gpio, nand(io2), spi(cs)
> +mpp1          1        gpo, nand(io3), spi(mosi)
> +mpp2          2        gpo, nand(io4), spi(sck)
> +mpp3          3        gpo, nand(io5), spi(miso)
> +mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act)
> +mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
> +mpp6          6        sysrst(out), spi(mosi), ptp(trig)
> +mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
> +mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
> +                       mii(col), mii-1(rxerr), sata1(prsnt)
> +mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
> +                       mii(crs), sata0(prsnt)
> +mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig), sata1(act)
> +mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
> +                       ptp-2(trig), sata0(act)
> +mpp12         12       gpio, sdio(clk)
> +mpp13         13       gpio, sdio(cmd), uart1(txd)
> +mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt)
> +mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
> +mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
> +                       sata1(act)
> +mpp17         17       gpio, sdio(d3), sata0(prsnt)
> +mpp18         18       gpo, nand(io0)
> +mpp19         19       gpo, nand(io1)
> +mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
> +                       sata1(act)
> +mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
> +                       audio(spdifo)
> +mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
> +                       sata1(prsnt)
> +mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
> +                       audio(bclk)
> +mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo)
> +mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk)
> +mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk)
> +mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi)
> +mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk)
> +mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst)
> +mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk)
> +mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs)
> +mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx)
> +mpp33         33       gpo, ge1(txclk), tdm(drx)
> +mpp34         34       gpio, ge1(txen), tdm(spi-cs1), sata1(act)
> +mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql)
> +mpp36         36       gpio, ts(mp0), tdm(spi-cs1), audio(spdifi)
> +mpp37         37       gpio, ts(mp1), tdm(tx2ql), audio(spdifo)
> +mpp38         38       gpio, ts(mp2), tdm(rx2ql), audio(rmclk)
> +mpp39         39       gpio, ts(mp3), tdm(spi-cs0), audio(bclk)
> +mpp40         40       gpio, ts(mp4), tdm(spi-sck), audio(sdo)
> +mpp41         41       gpio, ts(mp5), tdm(spi-miso), audio(lrclk)
> +mpp42         42       gpio, ts(mp6), tdm(spi-mosi), audio(mclk)
> +mpp43         43       gpio, ts(mp7), tdm(int), audio(sdi)
> +mpp44         44       gpio, ts(mp8), tdm(rst), audio(extclk)
> +mpp45         45       gpio, ts(mp9), tdm(pclk)
> +mpp46         46       gpio, ts(mp10), tdm(fs)
> +mpp47         47       gpio, ts(mp11), tdm(drx)
> +mpp48         48       gpio, ts(mp12), tdm(dtx)
> +mpp49         49       gpio, ts(mp9), tdm(rx0ql), ptp(clk)
> +
> +* Marvell Kirkwood 88f6282
> +
> +name          pins     functions
> +================================================================================
> +mpp0          0        gpio, nand(io2), spi(cs)
> +mpp1          1        gpo, nand(io3), spi(mosi)
> +mpp2          2        gpo, nand(io4), spi(sck)
> +mpp3          3        gpo, nand(io5), spi(miso)
> +mpp4          4        gpio, nand(io6), uart0(rxd), sata1(act), lcd(hsync)
> +mpp5          5        gpo, nand(io7), uart0(txd), sata0(act), lcd(vsync)
> +mpp6          6        sysrst(out), spi(mosi)
> +mpp7          7        gpo, spi(cs), lcd(pwm)
> +mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), mii(col),
> +                       mii-1(rxerr), sata1(prsnt)
> +mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), mii(crs),
> +                       sata0(prsnt)
> +mpp10         10       gpo, spi(sck), uart0(txd), sata1(act)
> +mpp11         11       gpio, spi(miso), uart0(rxd), sata0(act)
> +mpp12         12       gpo, sdio(clk), audio(spdifo), spi(mosi), twsi(sda)
> +mpp13         13       gpio, sdio(cmd), uart1(txd), audio(rmclk), lcd(pwm)
> +mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt),
> +                       audio(spdifi), audio-1(sdi)
> +mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act),
> +                       spi(cs)
> +mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
> +                       sata1(act), lcd(extclk)
> +mpp17         17       gpio, sdio(d3), sata0(prsnt), sata1(act), twsi1(sck)
> +mpp18         18       gpo, nand(io0), pex(clkreq)
> +mpp19         19       gpo, nand(io1)
> +mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
> +                       sata1(act), lcd(d0)
> +mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
> +                       audio(spdifo), lcd(d1)
> +mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
> +                       sata1(prsnt), lcd(d2)
> +mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
> +                       audio(bclk), lcd(d3)
> +mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo),
> +                       lcd(d4)
> +mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk),
> +                       lcd(d5)
> +mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk),
> +                       lcd(d6)
> +mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi),
> +                       lcd(d7)
> +mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk),
> +                       lcd(d8)
> +mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst), lcd(d9)
> +mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk), lcd(d10)
> +mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs), lcd(d11)
> +mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx), lcd(d12)
> +mpp33         33       gpo, ge1(txclk), tdm(drx), lcd(d13)
> +mpp34         34       gpio, ge1(txen), tdm(spi-cs1), sata1(act), lcd(d14)
> +mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql),
> +                       lcd(d15)
> +mpp36         36       gpio, ts(mp0), tdm(spi-cs1), audio(spdifi), twsi1(sda)
> +mpp37         37       gpio, ts(mp1), tdm(tx2ql), audio(spdifo), twsi1(sck)
> +mpp38         38       gpio, ts(mp2), tdm(rx2ql), audio(rmclk), lcd(d18)
> +mpp39         39       gpio, ts(mp3), tdm(spi-cs0), audio(bclk), lcd(d19)
> +mpp40         40       gpio, ts(mp4), tdm(spi-sck), audio(sdo), lcd(d20)
> +mpp41         41       gpio, ts(mp5), tdm(spi-miso), audio(lrclk), lcd(d21)
> +mpp42         42       gpio, ts(mp6), tdm(spi-mosi), audio(mclk), lcd(d22)
> +mpp43         43       gpio, ts(mp7), tdm(int), audio(sdi), lcd(d23)
> +mpp44         44       gpio, ts(mp8), tdm(rst), audio(extclk), lcd(clk)
> +mpp45         45       gpio, ts(mp9), tdm(pclk), lcd(e)
> +mpp46         46       gpio, ts(mp10), tdm(fs), lcd(hsync)
> +mpp47         47       gpio, ts(mp11), tdm(drx), lcd(vsync)
> +mpp48         48       gpio, ts(mp12), tdm(dtx), lcd(d16)
> +mpp49         49       gpo, tdm(rx0ql), pex(clkreq), lcd(d17)
> diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
> index f15eba4..31c0bba 100644
> --- a/drivers/pinctrl/Kconfig
> +++ b/drivers/pinctrl/Kconfig
> @@ -155,6 +155,10 @@ config PINCTRL_DOVE
>  	bool
>  	select PINCTRL_MVEBU
>  
> +config PINCTRL_KIRKWOOD
> +	bool
> +	select PINCTRL_MVEBU
> +
>  source "drivers/pinctrl/spear/Kconfig"
>  
>  endmenu
> diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
> index d1327df..3006294 100644
> --- a/drivers/pinctrl/Makefile
> +++ b/drivers/pinctrl/Makefile
> @@ -31,5 +31,6 @@ obj-$(CONFIG_PINCTRL_U300)	+= pinctrl-u300.o
>  obj-$(CONFIG_PINCTRL_COH901)	+= pinctrl-coh901.o
>  obj-$(CONFIG_PINCTRL_MVEBU)	+= pinctrl-mvebu.o
>  obj-$(CONFIG_PINCTRL_DOVE)	+= pinctrl-dove.o
> +obj-$(CONFIG_PINCTRL_KIRKWOOD)	+= pinctrl-kirkwood.o
>  
>  obj-$(CONFIG_PLAT_SPEAR)	+= spear/
> diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/pinctrl-kirkwood.c
> new file mode 100644
> index 0000000..9a74ef6
> --- /dev/null
> +++ b/drivers/pinctrl/pinctrl-kirkwood.c
> @@ -0,0 +1,472 @@
> +/*
> + * Marvell Kirkwood pinctrl driver based on mvebu pinctrl core
> + *
> + * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/pinctrl/pinctrl.h>
> +
> +#include "pinctrl-mvebu.h"
> +
> +#define V(f6180, f6190, f6192, f6281, f6282)		\
> +	((f6180 << 0) | (f6190 << 1) | (f6192 << 2) |	\
> +	 (f6281 << 3) | (f6282 << 4))
> +
> +enum kirkwood_variant {
> +	VARIANT_MV88F6180 = V(1, 0, 0, 0, 0),
> +	VARIANT_MV88F6190 = V(0, 1, 0, 0, 0),
> +	VARIANT_MV88F6192 = V(0, 0, 1, 0, 0),
> +	VARIANT_MV88F6281 = V(0, 0, 0, 1, 0),
> +	VARIANT_MV88F6282 = V(0, 0, 0, 0, 1),
> +};
> +
> +static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
> +	MPP_MODE(0,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "nand", "io2",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1))),
> +	MPP_MODE(1,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "nand", "io3",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "spi", "mosi",     V(1, 1, 1, 1, 1))),
> +	MPP_MODE(2,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "nand", "io4",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1))),
> +	MPP_MODE(3,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "nand", "io5",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1))),
> +	MPP_MODE(4,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "nand", "io6",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "uart0", "rxd",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0))),
> +	MPP_MODE(5,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "nand", "io7",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "uart0", "txd",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "ptp", "trig",     V(1, 1, 1, 1, 0)),
> +		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1))),
> +	MPP_MODE(6,
> +		MPP_VAR_FUNCTION(0x0, "sysrst", "out",   V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "spi", "mosi",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "ptp", "trig",     V(1, 1, 1, 1, 0))),
> +	MPP_MODE(7,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "pex", "rsto",     V(1, 1, 1, 1, 0)),
> +		MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ptp", "trig",     V(1, 1, 1, 1, 0)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(8,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "twsi0", "sda",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "uart1", "rts",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr",  V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xc, "ptp", "clk",      V(1, 1, 1, 1, 0)),
> +		MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1))),
> +	MPP_MODE(9,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "twsi0", "sck",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "uart1", "cts",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xc, "ptp", "evreq",    V(1, 1, 1, 1, 0)),
> +		MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1))),
> +	MPP_MODE(10,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0X3, "uart0", "txd",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xc, "ptp", "trig",     V(1, 1, 1, 1, 0))),
> +	MPP_MODE(11,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "uart0", "rxd",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq",  V(1, 1, 1, 1, 0)),
> +		MPP_VAR_FUNCTION(0xc, "ptp-2", "trig",   V(1, 1, 1, 1, 0)),
> +		MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0)),
> +		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1))),
> +	MPP_MODE(12,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 0, 1)),
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0)),
> +		MPP_VAR_FUNCTION(0x1, "sdio", "clk",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xb, "spi", "mosi",     V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xd, "twsi1", "sda",    V(0, 0, 0, 0, 1))),
> +	MPP_MODE(13,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "sdio", "cmd",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xa, "audio", "rmclk",  V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(14,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "sdio", "d0",      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xb, "audio-1", "sdi",  V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1))),
> +	MPP_MODE(15,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "sdio", "d1",      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "sata0", "act",    V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "spi", "cs",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(16,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "sdio", "d2",      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "sata1", "act",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "extclk",   V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1))),
> +	MPP_MODE(17,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "sdio", "d3",      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xa, "sata1", "act",    V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xd, "twsi1", "sck",    V(0, 0, 0, 0, 1))),
> +	MPP_MODE(18,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "nand", "io0",     V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "pex", "clkreq",   V(0, 0, 0, 0, 1))),
> +	MPP_MODE(19,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "nand", "io1",     V(1, 1, 1, 1, 1))),
> +	MPP_MODE(20,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "txd0",     V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d0",       V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(1, 0, 0, 0, 0))),
> +	MPP_MODE(21,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "txd1",     V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d1",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(22,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "txd2",     V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d2",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(23,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "txd3",     V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(1, 0, 0, 0, 0)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d3",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(24,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "rxd0",     V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(1, 0, 0, 0, 0)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d4",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(25,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "rxd1",     V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(1, 0, 0, 0, 0)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d5",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(26,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "rxd2",     V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(1, 0, 0, 0, 0)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d6",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(27,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "rxd3",     V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(1, 0, 0, 0, 0)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d7",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(28,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "col",      V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(1, 0, 0, 0, 0)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d8",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(29,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "txclk",    V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d9",       V(0, 0, 0, 0, 1))),
> +	MPP_MODE(30,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "rxctl",    V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d10",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(31,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "rxclk",    V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d11",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(32,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "txclko",   V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d12",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(33,
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "txctl",    V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d13",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(34,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "txen",     V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d14",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(35,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x3, "ge1", "rxerr",    V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d15",      V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(0, 1, 1, 1, 1))),
> +	MPP_MODE(36,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "twsi1", "sda",    V(0, 0, 0, 0, 1))),
> +	MPP_MODE(37,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "twsi1", "sck",    V(0, 0, 0, 0, 1))),
> +	MPP_MODE(38,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d18",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(39,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d19",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(40,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d20",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(41,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d21",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(42,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d22",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(43,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d23",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(44,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "clk",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(45,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "e",        V(0, 0, 0, 0, 1))),
> +	MPP_MODE(46,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1))),
> +	MPP_MODE(47,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1))),
> +	MPP_MODE(48,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d16",      V(0, 0, 0, 0, 1))),
> +	MPP_MODE(49,
> +		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0)),
> +		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 0)),
> +		MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 0, 1, 1)),
> +		MPP_VAR_FUNCTION(0x5, "ptp", "clk",      V(0, 0, 0, 1, 0)),
> +		MPP_VAR_FUNCTION(0xa, "pex", "clkreq",   V(0, 0, 0, 0, 1)),
> +		MPP_VAR_FUNCTION(0xb, "lcd", "d17",      V(0, 0, 0, 0, 1))),
> +};
> +
> +static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
> +	MPP_REG_CTRL(0, 29),
> +};
> +
> +static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
> +	MPP_GPIO_RANGE(0, 0, 0, 30),
> +};
> +
> +static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
> +	MPP_REG_CTRL(0, 35),
> +};
> +
> +static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
> +	MPP_GPIO_RANGE(0,  0,  0, 32),
> +	MPP_GPIO_RANGE(1, 32, 32,  4),
> +};
> +
> +static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
> +	MPP_REG_CTRL(0, 49),
> +};
> +
> +static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
> +	MPP_GPIO_RANGE(0,  0,  0, 32),
> +	MPP_GPIO_RANGE(1, 32, 32, 18),
> +};
> +
> +static struct mvebu_pinctrl_soc_info mv88f6180_info = {
> +	.variant = VARIANT_MV88F6180,
> +	.controls = mv88f6180_mpp_controls,
> +	.ncontrols = ARRAY_SIZE(mv88f6180_mpp_controls),
> +	.modes = mv88f6xxx_mpp_modes,
> +	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
> +	.gpioranges = mv88f6180_gpio_ranges,
> +	.ngpioranges = ARRAY_SIZE(mv88f6180_gpio_ranges),
> +};
> +
> +static struct mvebu_pinctrl_soc_info mv88f6190_info = {
> +	.variant = VARIANT_MV88F6190,
> +	.controls = mv88f619x_mpp_controls,
> +	.ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
> +	.modes = mv88f6xxx_mpp_modes,
> +	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
> +	.gpioranges = mv88f619x_gpio_ranges,
> +	.ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
> +};
> +
> +static struct mvebu_pinctrl_soc_info mv88f6192_info = {
> +	.variant = VARIANT_MV88F6192,
> +	.controls = mv88f619x_mpp_controls,
> +	.ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
> +	.modes = mv88f6xxx_mpp_modes,
> +	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
> +	.gpioranges = mv88f619x_gpio_ranges,
> +	.ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
> +};
> +
> +static struct mvebu_pinctrl_soc_info mv88f6281_info = {
> +	.variant = VARIANT_MV88F6281,
> +	.controls = mv88f628x_mpp_controls,
> +	.ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
> +	.modes = mv88f6xxx_mpp_modes,
> +	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
> +	.gpioranges = mv88f628x_gpio_ranges,
> +	.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
> +};
> +
> +static struct mvebu_pinctrl_soc_info mv88f6282_info = {
> +	.variant = VARIANT_MV88F6282,
> +	.controls = mv88f628x_mpp_controls,
> +	.ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
> +	.modes = mv88f6xxx_mpp_modes,
> +	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
> +	.gpioranges = mv88f628x_gpio_ranges,
> +	.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
> +};
> +
> +static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
> +	{ .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
> +	{ .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
> +	{ .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
> +	{ .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
> +	{ .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
> +	{ }
> +};
> +
> +static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match =
> +		of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
> +	pdev->dev.platform_data = match->data;
> +	return mvebu_pinctrl_probe(pdev);
> +}
> +
> +static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev)
> +{
> +	return mvebu_pinctrl_remove(pdev);
> +}
> +
> +static struct platform_driver kirkwood_pinctrl_driver = {
> +	.driver = {
> +		.name = "kirkwood-pinctrl",
> +		.owner = THIS_MODULE,
> +		.of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
> +	},
> +	.probe = kirkwood_pinctrl_probe,
> +	.remove = __devexit_p(kirkwood_pinctrl_remove),
> +};
> +
> +module_platform_driver(kirkwood_pinctrl_driver);
> +
> +MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
> +MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
> +MODULE_LICENSE("GPL v2");
> -- 
> 1.7.10.4
>
Arnd Bergmann Sept. 20, 2012, 3:30 p.m. UTC | #9
On Monday 17 September 2012, Linus Walleij wrote:
> You found the weak spot between two consolidation tracks.
> 
> Getting rid of a broadcast autodetect functions from say
> <mach/foo-id-probe.h> is nominally done by passing the data
> to the driver as platform data instead, and only using
> these functions in the mach-foo folder when populating
> platform data, and thus it can be made into a local
> header, say mach-foo/foo-id-probe.h
> 
> So the machine/arch code reads these registers to
> populate the platform data and device drivers only
> look at the platform data, which has some enum or
> bool indicating what hardware it's running on, cool.
> 
> But according to the other consolidation track, platform
> data should go into device tree bindings.
> 
> So the conclusion is that the DT must contain the data
> about the platform, so it's not auto-probed by the kernel.
> (I.e. the kernel reads no registers to figure out what hardware
> this is, that stuff comes from the device tree.)
> 
> DT purists will say that the boot loader should ask the chipset
> what it is with the same register writes and populate the
> DT accordingly, instead of loading a precompiled blob.
> Some may even ponder the crazy concept of amending the
> DT in the kernel at early boot.
> 
> But in practice someone will give up, encode the stuff in
> the static device tree and autoprobing of the platform
> goes out the window.

In general, I would prefer probing hardware by asking the hardware itself
rather than duplicating the information in the device tree. We do this
whenever we can, e.g. on PCI or USB, but we cannot normally do the same
on embedded buses like AHB, I2C or SPI, so we have to use the device
tree to provide some or all of the information.

A corner case is the one where you have different versions of the same
IP block (e.g. the pinctrl) and the kernel cannot find out which one it
is by looking at registers inside it or on the parent bus, but only
by looking at other hardware (CPU core revision, or PCI device ID of
the root complex). We have a precedent of at91 doing this, but I don't
like it too much because that still means having to change the driver
again if you get a new SoC with the same IP block but a different version
register, or if the block gets reused in something (e.g. by a different
vendor) that doesn't even have the other block that's used for
identification. To avoid that, I'd prefer using separate "compatible"
values, at least if the hardware is already described in separate .dtsi
files.

	Arnd
Andrew Lunn Sept. 20, 2012, 6:34 p.m. UTC | #10
On Thu, Sep 20, 2012 at 03:30:40PM +0000, Arnd Bergmann wrote:
> On Monday 17 September 2012, Linus Walleij wrote:
> > You found the weak spot between two consolidation tracks.
> > 
> > Getting rid of a broadcast autodetect functions from say
> > <mach/foo-id-probe.h> is nominally done by passing the data
> > to the driver as platform data instead, and only using
> > these functions in the mach-foo folder when populating
> > platform data, and thus it can be made into a local
> > header, say mach-foo/foo-id-probe.h
> > 
> > So the machine/arch code reads these registers to
> > populate the platform data and device drivers only
> > look at the platform data, which has some enum or
> > bool indicating what hardware it's running on, cool.
> > 
> > But according to the other consolidation track, platform
> > data should go into device tree bindings.
> > 
> > So the conclusion is that the DT must contain the data
> > about the platform, so it's not auto-probed by the kernel.
> > (I.e. the kernel reads no registers to figure out what hardware
> > this is, that stuff comes from the device tree.)
> > 
> > DT purists will say that the boot loader should ask the chipset
> > what it is with the same register writes and populate the
> > DT accordingly, instead of loading a precompiled blob.
> > Some may even ponder the crazy concept of amending the
> > DT in the kernel at early boot.
> > 
> > But in practice someone will give up, encode the stuff in
> > the static device tree and autoprobing of the platform
> > goes out the window.
> 
> In general, I would prefer probing hardware by asking the hardware itself
> rather than duplicating the information in the device tree. We do this
> whenever we can, e.g. on PCI or USB, but we cannot normally do the same
> on embedded buses like AHB, I2C or SPI, so we have to use the device
> tree to provide some or all of the information.
> 
> A corner case is the one where you have different versions of the same
> IP block (e.g. the pinctrl) and the kernel cannot find out which one it
> is by looking at registers inside it or on the parent bus, but only
> by looking at other hardware (CPU core revision, or PCI device ID of
> the root complex).

Hi Arnd

Even if we did look at the PCIe device IDs, we would still have one
odd-ball case to deal with. We have had an initial port to a Marvell
98DX4122 contributed. This chip is a Marvell Ethernet chip, with an
embedded Kirkwood SoC. The SoC is missing SATA, RTC, SDIO, I2S, TDM,
and TS which other kirkwoods have. So it will need a different pinctrl
table. However, looking at the PCIe device ID, it identifies itself as
a normal MV88F6281. So we would have to deal with this in DT with a
different compatibility string.

	  Andrew
Linus Walleij Sept. 20, 2012, 7:28 p.m. UTC | #11
On Thu, Sep 20, 2012 at 5:30 PM, Arnd Bergmann <arnd@arndb.de> wrote:

> A corner case is the one where you have different versions of the same
> IP block (e.g. the pinctrl) and the kernel cannot find out which one it
> is by looking at registers inside it or on the parent bus, but only
> by looking at other hardware (CPU core revision, or PCI device ID of
> the root complex).

So this is the case I'm thinking of. We have e.g. differens small flags
through platform data depending on cpu_is_ux* in the ux500.

Currently we modify platform data in the board files, just as we
switch some cache handling etc as we know this or that
ASIC has different sized cache.

> We have a precedent of at91 doing this, but I don't
> like it too much because that still means having to change the driver
> again if you get a new SoC with the same IP block but a different version
> register,

I don't like that either.

> To avoid that, I'd prefer using separate "compatible"
> values, at least if the hardware is already described in separate .dtsi
> files.

So what I'm after is whether in this case statically encoding this
onto the .dtsi files is the right thing to do, or whether the boot loader
or kernel should runtime-modify the device tree, patching in
the ASIC-specific info, just like device tree files can override
properties from include files.

Or if this is a bad idea.

Nobody is doing that right now AFAICT, but it is surely possible....

Yours,
Linus Walleij
Thomas Petazzoni Sept. 20, 2012, 7:36 p.m. UTC | #12
Dear Linus Walleij,

On Thu, 20 Sep 2012 21:28:20 +0200, Linus Walleij wrote:

> So what I'm after is whether in this case statically encoding this
> onto the .dtsi files is the right thing to do, or whether the boot loader
> or kernel should runtime-modify the device tree, patching in
> the ASIC-specific info, just like device tree files can override
> properties from include files.
> 
> Or if this is a bad idea.
> 
> Nobody is doing that right now AFAICT, but it is surely possible....

If I understand correctly, we would like drivers to be able to read
some common "system" registers to figure out which SoC variant we are
running on. Such feature should normally be provided by code in
arch/arm/mach-*/ and called by drivers, but we are trying to eliminate
all dependencies of driver code on architecture code, correct?

So, wouldn't we need a small, architecture-independent, infrastructure,
through which architecture-specific code could "register" at boot
time which SoC we are running on, and drivers could query this
information from the common infrastructure?

Of course, the major problem is to figure out what is the good
representation for this SoC identifier. Do we need a big list of SoCs
like we had machine IDs? A simple string? Or maybe there is just no
good way, and the whole idea is moot.

Best regards,

Thomas
Andrew Lunn Sept. 20, 2012, 7:51 p.m. UTC | #13
> So, wouldn't we need a small, architecture-independent, infrastructure,
> through which architecture-specific code could "register" at boot
> time which SoC we are running on, and drivers could query this
> information from the common infrastructure?
> 
> Of course, the major problem is to figure out what is the good
> representation for this SoC identifier. Do we need a big list of SoCs
> like we had machine IDs? A simple string? Or maybe there is just no
> good way, and the whole idea is moot.

I did think about stuffing it inside the cpuinfo structures:

$ cat /proc/cpuinfo 
Processor       : Feroceon 88FR131 rev 1 (v5l)
BogoMIPS        : 1196.85
Features        : swp half thumb fastmult edsp 
CPU implementer : 0x56
CPU architecture: 5TE
CPU variant     : 0x2
CPU part        : 0x131
CPU revision    : 1

Hardware        : BUBBA3 Kirkwood based miniserver
Revision        : 0000
Serial          : 0000000000000000

I could imaging a 
SoC             : MV88F6281

It would probably need a bit of string parsing by any consumer, which
is not so good.

   Andrew
Ben Dooks Sept. 21, 2012, 10:56 a.m. UTC | #14
On 20/09/12 20:36, Thomas Petazzoni wrote:
> Dear Linus Walleij,
>
> On Thu, 20 Sep 2012 21:28:20 +0200, Linus Walleij wrote:
>
>> So what I'm after is whether in this case statically encoding this
>> onto the .dtsi files is the right thing to do, or whether the boot loader
>> or kernel should runtime-modify the device tree, patching in
>> the ASIC-specific info, just like device tree files can override
>> properties from include files.
>>
>> Or if this is a bad idea.
>>
>> Nobody is doing that right now AFAICT, but it is surely possible....
>
> If I understand correctly, we would like drivers to be able to read
> some common "system" registers to figure out which SoC variant we are
> running on. Such feature should normally be provided by code in
> arch/arm/mach-*/ and called by drivers, but we are trying to eliminate
> all dependencies of driver code on architecture code, correct?
>
> So, wouldn't we need a small, architecture-independent, infrastructure,
> through which architecture-specific code could "register" at boot
> time which SoC we are running on, and drivers could query this
> information from the common infrastructure?
>
> Of course, the major problem is to figure out what is the good
> representation for this SoC identifier. Do we need a big list of SoCs
> like we had machine IDs? A simple string? Or maybe there is just no
> good way, and the whole idea is moot.

I think this is a bad idea, it means you can't try and re-use an
older kernel on an newer SoC design which may be broadly compatible
without changing the kernel source to add these flag checks.

I also don't like information hidden away that the user cannot see.
Having the device specifically named allows us to see from sysfs
exactly what we are dealing with.
Linus Walleij Sept. 21, 2012, 6:14 p.m. UTC | #15
On Thu, Sep 20, 2012 at 9:36 PM, Thomas Petazzoni
<thomas.petazzoni@free-electrons.com> wrote:

> If I understand correctly, we would like drivers to be able to read
> some common "system" registers to figure out which SoC variant we are
> running on. Such feature should normally be provided by code in
> arch/arm/mach-*/ and called by drivers, but we are trying to eliminate
> all dependencies of driver code on architecture code, correct?

So what I think is that any such mechanism would defy the idea
with device tree providing all platform configuration, including
the ASIC/SoC variant.

The only not-so-unelegant idea I have is for the machine to
go in and fiddle with the device tree, e.g. add some info into
the tree somewhere stating into the nodes which ASIC variant
it is. Maybe even modify the compatible value at runtime.

But it somehow feels like cracking an egg with a sledgehammer.

I think we need to meditate on this.

Yours,
Linus Walleij
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
new file mode 100644
index 0000000..361bccb
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt
@@ -0,0 +1,279 @@ 
+* Marvell Kirkwood SoC pinctrl driver for mpp
+
+Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding
+part and usage.
+
+Required properties:
+- compatible: "marvell,88f6180-pinctrl",
+              "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl",
+              "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl"
+
+This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x.
+
+Available mpp pins/groups and functions:
+Note: brackets (x) are not part of the mpp name for marvell,function and given
+only for more detailed description in this document.
+
+* Marvell Kirkwood 88f6180
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig)
+mpp12         12       gpo, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs)
+mpp17         17       gpio, sdio(d3)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, mii(rxerr)
+mpp21         21       gpio, audio(spdifi)
+mpp22         22       gpio, audio(spdifo)
+mpp23         23       gpio, audio(rmclk)
+mpp24         24       gpio, audio(bclk)
+mpp25         25       gpio, audio(sdo)
+mpp26         26       gpio, audio(lrclk)
+mpp27         27       gpio, audio(mclk)
+mpp28         28       gpio, audio(sdi)
+mpp29         29       gpio, audio(extclk)
+
+* Marvell Kirkwood 88f6190
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col), mii-1(rxerr)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs), sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig), sata0(act)
+mpp12         12       gpo, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs)
+mpp17         17       gpio, sdio(d3), sata0(prsnt)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0)
+mpp21         21       gpio, ge1(txd1), sata0(act)
+mpp22         22       gpio, ge1(txd2)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt)
+mpp24         24       gpio, ge1(rxd0)
+mpp25         25       gpio, ge1(rxd1)
+mpp26         26       gpio, ge1(rxd2)
+mpp27         27       gpio, ge1(rxd3)
+mpp28         28       gpio, ge1(col)
+mpp29         29       gpio, ge1(txclk)
+mpp30         30       gpio, ge1(rxclk)
+mpp31         31       gpio, ge1(rxclk)
+mpp32         32       gpio, ge1(txclko)
+mpp33         33       gpo, ge1(txclk)
+mpp34         34       gpio, ge1(txen)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr)
+
+* Marvell Kirkwood 88f6192
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col), mii-1(rxerr), sata1(prsnt)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs), sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig), sata1(act)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig), sata0(act)
+mpp12         12       gpo, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
+                       sata1(act)
+mpp17         17       gpio, sdio(d3), sata0(prsnt)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
+                       sata1(act)
+mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
+                       audio(spdifo)
+mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
+                       sata1(prsnt)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
+                       audio(bclk)
+mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo)
+mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk)
+mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk)
+mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi)
+mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk)
+mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst)
+mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk)
+mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs)
+mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx)
+mpp33         33       gpo, ge1(txclk), tdm(drx)
+mpp34         34       gpio, ge1(txen), tdm(spi-cs1)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql)
+
+* Marvell Kirkwood 88f6281
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act)
+mpp5          5        gpo, nand(io7), uart0(txd), ptp(trig), sata0(act)
+mpp6          6        sysrst(out), spi(mosi), ptp(trig)
+mpp7          7        gpo, pex(rsto), spi(cs), ptp(trig)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk),
+                       mii(col), mii-1(rxerr), sata1(prsnt)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq),
+                       mii(crs), sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), ptp(trig), sata1(act)
+mpp11         11       gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq),
+                       ptp-2(trig), sata0(act)
+mpp12         12       gpio, sdio(clk)
+mpp13         13       gpio, sdio(cmd), uart1(txd)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
+                       sata1(act)
+mpp17         17       gpio, sdio(d3), sata0(prsnt)
+mpp18         18       gpo, nand(io0)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
+                       sata1(act)
+mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
+                       audio(spdifo)
+mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
+                       sata1(prsnt)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
+                       audio(bclk)
+mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo)
+mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk)
+mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk)
+mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi)
+mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk)
+mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst)
+mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk)
+mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs)
+mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx)
+mpp33         33       gpo, ge1(txclk), tdm(drx)
+mpp34         34       gpio, ge1(txen), tdm(spi-cs1), sata1(act)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql)
+mpp36         36       gpio, ts(mp0), tdm(spi-cs1), audio(spdifi)
+mpp37         37       gpio, ts(mp1), tdm(tx2ql), audio(spdifo)
+mpp38         38       gpio, ts(mp2), tdm(rx2ql), audio(rmclk)
+mpp39         39       gpio, ts(mp3), tdm(spi-cs0), audio(bclk)
+mpp40         40       gpio, ts(mp4), tdm(spi-sck), audio(sdo)
+mpp41         41       gpio, ts(mp5), tdm(spi-miso), audio(lrclk)
+mpp42         42       gpio, ts(mp6), tdm(spi-mosi), audio(mclk)
+mpp43         43       gpio, ts(mp7), tdm(int), audio(sdi)
+mpp44         44       gpio, ts(mp8), tdm(rst), audio(extclk)
+mpp45         45       gpio, ts(mp9), tdm(pclk)
+mpp46         46       gpio, ts(mp10), tdm(fs)
+mpp47         47       gpio, ts(mp11), tdm(drx)
+mpp48         48       gpio, ts(mp12), tdm(dtx)
+mpp49         49       gpio, ts(mp9), tdm(rx0ql), ptp(clk)
+
+* Marvell Kirkwood 88f6282
+
+name          pins     functions
+================================================================================
+mpp0          0        gpio, nand(io2), spi(cs)
+mpp1          1        gpo, nand(io3), spi(mosi)
+mpp2          2        gpo, nand(io4), spi(sck)
+mpp3          3        gpo, nand(io5), spi(miso)
+mpp4          4        gpio, nand(io6), uart0(rxd), sata1(act), lcd(hsync)
+mpp5          5        gpo, nand(io7), uart0(txd), sata0(act), lcd(vsync)
+mpp6          6        sysrst(out), spi(mosi)
+mpp7          7        gpo, spi(cs), lcd(pwm)
+mpp8          8        gpio, twsi0(sda), uart0(rts), uart1(rts), mii(col),
+                       mii-1(rxerr), sata1(prsnt)
+mpp9          9        gpio, twsi(sck), uart0(cts), uart1(cts), mii(crs),
+                       sata0(prsnt)
+mpp10         10       gpo, spi(sck), uart0(txd), sata1(act)
+mpp11         11       gpio, spi(miso), uart0(rxd), sata0(act)
+mpp12         12       gpo, sdio(clk), audio(spdifo), spi(mosi), twsi(sda)
+mpp13         13       gpio, sdio(cmd), uart1(txd), audio(rmclk), lcd(pwm)
+mpp14         14       gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt),
+                       audio(spdifi), audio-1(sdi)
+mpp15         15       gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act),
+                       spi(cs)
+mpp16         16       gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs),
+                       sata1(act), lcd(extclk)
+mpp17         17       gpio, sdio(d3), sata0(prsnt), sata1(act), twsi1(sck)
+mpp18         18       gpo, nand(io0), pex(clkreq)
+mpp19         19       gpo, nand(io1)
+mpp20         20       gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi),
+                       sata1(act), lcd(d0)
+mpp21         21       gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql),
+                       audio(spdifo), lcd(d1)
+mpp22         22       gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk),
+                       sata1(prsnt), lcd(d2)
+mpp23         23       gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql),
+                       audio(bclk), lcd(d3)
+mpp24         24       gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo),
+                       lcd(d4)
+mpp25         25       gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk),
+                       lcd(d5)
+mpp26         26       gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk),
+                       lcd(d6)
+mpp27         27       gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi),
+                       lcd(d7)
+mpp28         28       gpio, ge1(col), ts(mp8), tdm(int), audio(extclk),
+                       lcd(d8)
+mpp29         29       gpio, ge1(txclk), ts(mp9), tdm(rst), lcd(d9)
+mpp30         30       gpio, ge1(rxclk), ts(mp10), tdm(pclk), lcd(d10)
+mpp31         31       gpio, ge1(rxclk), ts(mp11), tdm(fs), lcd(d11)
+mpp32         32       gpio, ge1(txclko), ts(mp12), tdm(drx), lcd(d12)
+mpp33         33       gpo, ge1(txclk), tdm(drx), lcd(d13)
+mpp34         34       gpio, ge1(txen), tdm(spi-cs1), sata1(act), lcd(d14)
+mpp35         35       gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql),
+                       lcd(d15)
+mpp36         36       gpio, ts(mp0), tdm(spi-cs1), audio(spdifi), twsi1(sda)
+mpp37         37       gpio, ts(mp1), tdm(tx2ql), audio(spdifo), twsi1(sck)
+mpp38         38       gpio, ts(mp2), tdm(rx2ql), audio(rmclk), lcd(d18)
+mpp39         39       gpio, ts(mp3), tdm(spi-cs0), audio(bclk), lcd(d19)
+mpp40         40       gpio, ts(mp4), tdm(spi-sck), audio(sdo), lcd(d20)
+mpp41         41       gpio, ts(mp5), tdm(spi-miso), audio(lrclk), lcd(d21)
+mpp42         42       gpio, ts(mp6), tdm(spi-mosi), audio(mclk), lcd(d22)
+mpp43         43       gpio, ts(mp7), tdm(int), audio(sdi), lcd(d23)
+mpp44         44       gpio, ts(mp8), tdm(rst), audio(extclk), lcd(clk)
+mpp45         45       gpio, ts(mp9), tdm(pclk), lcd(e)
+mpp46         46       gpio, ts(mp10), tdm(fs), lcd(hsync)
+mpp47         47       gpio, ts(mp11), tdm(drx), lcd(vsync)
+mpp48         48       gpio, ts(mp12), tdm(dtx), lcd(d16)
+mpp49         49       gpo, tdm(rx0ql), pex(clkreq), lcd(d17)
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index f15eba4..31c0bba 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -155,6 +155,10 @@  config PINCTRL_DOVE
 	bool
 	select PINCTRL_MVEBU
 
+config PINCTRL_KIRKWOOD
+	bool
+	select PINCTRL_MVEBU
+
 source "drivers/pinctrl/spear/Kconfig"
 
 endmenu
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index d1327df..3006294 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -31,5 +31,6 @@  obj-$(CONFIG_PINCTRL_U300)	+= pinctrl-u300.o
 obj-$(CONFIG_PINCTRL_COH901)	+= pinctrl-coh901.o
 obj-$(CONFIG_PINCTRL_MVEBU)	+= pinctrl-mvebu.o
 obj-$(CONFIG_PINCTRL_DOVE)	+= pinctrl-dove.o
+obj-$(CONFIG_PINCTRL_KIRKWOOD)	+= pinctrl-kirkwood.o
 
 obj-$(CONFIG_PLAT_SPEAR)	+= spear/
diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/pinctrl-kirkwood.c
new file mode 100644
index 0000000..9a74ef6
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-kirkwood.c
@@ -0,0 +1,472 @@ 
+/*
+ * Marvell Kirkwood pinctrl driver based on mvebu pinctrl core
+ *
+ * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-mvebu.h"
+
+#define V(f6180, f6190, f6192, f6281, f6282)		\
+	((f6180 << 0) | (f6190 << 1) | (f6192 << 2) |	\
+	 (f6281 << 3) | (f6282 << 4))
+
+enum kirkwood_variant {
+	VARIANT_MV88F6180 = V(1, 0, 0, 0, 0),
+	VARIANT_MV88F6190 = V(0, 1, 0, 0, 0),
+	VARIANT_MV88F6192 = V(0, 0, 1, 0, 0),
+	VARIANT_MV88F6281 = V(0, 0, 0, 1, 0),
+	VARIANT_MV88F6282 = V(0, 0, 0, 0, 1),
+};
+
+static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = {
+	MPP_MODE(0,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io2",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1))),
+	MPP_MODE(1,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io3",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "mosi",     V(1, 1, 1, 1, 1))),
+	MPP_MODE(2,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io4",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1))),
+	MPP_MODE(3,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io5",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1))),
+	MPP_MODE(4,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io6",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "rxd",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0))),
+	MPP_MODE(5,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io7",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "txd",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "ptp", "trig",     V(1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1))),
+	MPP_MODE(6,
+		MPP_VAR_FUNCTION(0x0, "sysrst", "out",   V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "spi", "mosi",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "ptp", "trig",     V(1, 1, 1, 1, 0))),
+	MPP_MODE(7,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "pex", "rsto",     V(1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "spi", "cs",       V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ptp", "trig",     V(1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(8,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "twsi0", "sda",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "rts",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr",  V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xc, "ptp", "clk",      V(1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1))),
+	MPP_MODE(9,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "twsi0", "sck",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "cts",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xc, "ptp", "evreq",    V(1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1))),
+	MPP_MODE(10,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "sck",      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0X3, "uart0", "txd",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xc, "ptp", "trig",     V(1, 1, 1, 1, 0))),
+	MPP_MODE(11,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "miso",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart0", "rxd",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq",  V(1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xc, "ptp-2", "trig",   V(1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0xd, "ptp", "clk",      V(1, 1, 1, 1, 0)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1))),
+	MPP_MODE(12,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 0, 1)),
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "clk",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xb, "spi", "mosi",     V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xd, "twsi1", "sda",    V(0, 0, 0, 0, 1))),
+	MPP_MODE(13,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "cmd",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xa, "audio", "rmclk",  V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "pwm",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(14,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "d0",      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xb, "audio-1", "sdi",  V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xd, "mii", "col",      V(1, 1, 1, 1, 1))),
+	MPP_MODE(15,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "d1",      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "rts",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "txd",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "sata0", "act",    V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "spi", "cs",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(16,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "d2",      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "uart0", "cts",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "uart1", "rxd",    V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "sata1", "act",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "extclk",   V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xd, "mii", "crs",      V(1, 1, 1, 1, 1))),
+	MPP_MODE(17,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "sdio", "d3",      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xa, "sata1", "act",    V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xd, "twsi1", "sck",    V(0, 0, 0, 0, 1))),
+	MPP_MODE(18,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io0",     V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "pex", "clkreq",   V(0, 0, 0, 0, 1))),
+	MPP_MODE(19,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "nand", "io1",     V(1, 1, 1, 1, 1))),
+	MPP_MODE(20,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txd0",     V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d0",       V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(1, 0, 0, 0, 0))),
+	MPP_MODE(21,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txd1",     V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d1",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(22,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txd2",     V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "prsnt",  V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d2",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(23,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txd3",     V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(1, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "prsnt",  V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d3",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(24,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxd0",     V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(1, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d4",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(25,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxd1",     V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(1, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d5",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(26,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxd2",     V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(1, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d6",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(27,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxd3",     V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(1, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d7",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(28,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "col",      V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(1, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d8",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(29,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txclk",    V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d9",       V(0, 0, 0, 0, 1))),
+	MPP_MODE(30,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxctl",    V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d10",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(31,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxclk",    V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d11",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(32,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txclko",   V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d12",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(33,
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txctl",    V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d13",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(34,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "txen",     V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata1", "act",    V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d14",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(35,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql",    V(0, 0, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ge1", "rxerr",    V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d15",      V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xc, "mii", "rxerr",    V(0, 1, 1, 1, 1))),
+	MPP_MODE(36,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp0",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1",  V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "twsi1", "sda",    V(0, 0, 0, 0, 1))),
+	MPP_MODE(37,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp1",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql",    V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "twsi1", "sck",    V(0, 0, 0, 0, 1))),
+	MPP_MODE(38,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp2",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql",    V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "rmclk",  V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d18",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(39,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp3",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0",  V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "bclk",   V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d19",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(40,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp4",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck",  V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdo",    V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d20",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(41,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp5",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "lrclk",  V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d21",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(42,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp6",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "mclk",   V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d22",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(43,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp7",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "int",      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "sdi",    V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d23",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(44,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp8",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rst",      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "clk",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(45,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "pclk",     V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "e",        V(0, 0, 0, 0, 1))),
+	MPP_MODE(46,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp10",      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "fs",       V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "hsync",    V(0, 0, 0, 0, 1))),
+	MPP_MODE(47,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp11",      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "drx",      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1))),
+	MPP_MODE(48,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp12",      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "dtx",      V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d16",      V(0, 0, 0, 0, 1))),
+	MPP_MODE(49,
+		MPP_VAR_FUNCTION(0x0, "gpio", NULL,      V(0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0x1, "ts", "mp9",       V(0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql",    V(0, 0, 0, 1, 1)),
+		MPP_VAR_FUNCTION(0x5, "ptp", "clk",      V(0, 0, 0, 1, 0)),
+		MPP_VAR_FUNCTION(0xa, "pex", "clkreq",   V(0, 0, 0, 0, 1)),
+		MPP_VAR_FUNCTION(0xb, "lcd", "d17",      V(0, 0, 0, 0, 1))),
+};
+
+static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = {
+	MPP_REG_CTRL(0, 29),
+};
+
+static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0, 0, 0, 30),
+};
+
+static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = {
+	MPP_REG_CTRL(0, 35),
+};
+
+static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,  0,  0, 32),
+	MPP_GPIO_RANGE(1, 32, 32,  4),
+};
+
+static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = {
+	MPP_REG_CTRL(0, 49),
+};
+
+static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = {
+	MPP_GPIO_RANGE(0,  0,  0, 32),
+	MPP_GPIO_RANGE(1, 32, 32, 18),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6180_info = {
+	.variant = VARIANT_MV88F6180,
+	.controls = mv88f6180_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f6180_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f6180_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f6180_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6190_info = {
+	.variant = VARIANT_MV88F6190,
+	.controls = mv88f619x_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f619x_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6192_info = {
+	.variant = VARIANT_MV88F6192,
+	.controls = mv88f619x_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f619x_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6281_info = {
+	.variant = VARIANT_MV88F6281,
+	.controls = mv88f628x_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f628x_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6282_info = {
+	.variant = VARIANT_MV88F6282,
+	.controls = mv88f628x_mpp_controls,
+	.ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls),
+	.modes = mv88f6xxx_mpp_modes,
+	.nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes),
+	.gpioranges = mv88f628x_gpio_ranges,
+	.ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges),
+};
+
+static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = {
+	{ .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info },
+	{ .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info },
+	{ .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info },
+	{ .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info },
+	{ .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info },
+	{ }
+};
+
+static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match =
+		of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
+	pdev->dev.platform_data = match->data;
+	return mvebu_pinctrl_probe(pdev);
+}
+
+static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev)
+{
+	return mvebu_pinctrl_remove(pdev);
+}
+
+static struct platform_driver kirkwood_pinctrl_driver = {
+	.driver = {
+		.name = "kirkwood-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(kirkwood_pinctrl_of_match),
+	},
+	.probe = kirkwood_pinctrl_probe,
+	.remove = __devexit_p(kirkwood_pinctrl_remove),
+};
+
+module_platform_driver(kirkwood_pinctrl_driver);
+
+MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
+MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
+MODULE_LICENSE("GPL v2");