All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/26] STA2X11 devicetree support for amba/pci
@ 2013-08-07 10:16 Alessandro Rubini
  2013-08-07 10:16 ` [PATCH 01/26] x86: fix warning for sta2x11 Alessandro Rubini
                   ` (27 more replies)
  0 siblings, 28 replies; 35+ messages in thread
From: Alessandro Rubini @ 2013-08-07 10:16 UTC (permalink / raw)
  To: linux-kernel
  Cc: Davide Ciminaghi, Giancarlo Asnaghi, x86, H. Peter Anvin,
	Ingo Molnar, Russell King, Thomas Gleixner, devicetree

[DISCLAIMER : both of us (Alessandro and Davide) are not devicetree
experts, so please understand how our issues and our dislike of the
approach may result from some lack of knowledge. (any pointer is
welcome).]


As some of you may remember, we're submitting patches adding support
for the STA2X11 (aka Connext) ST chip. The device is a pci-express I/O
HUB containing a number of AMBA peripherals (gpios, uarts, mmc/sd,
dma, ST msps, spi, i2c).  Being a PCI device, it's fully autoprobed:
we can even plug two evaluation boards in the same PC, and all devices
in there are expected to work (and they do, with some of our
patch-sets).

A first set of drivers for this chip was written by Wind River, by
simply copying AMBA drivers and turning them into pci drivers. This of
course worked, but implied tons of duplicated code. Our attempt was to
recycle existing AMBA drivers by instantiating AMBA devices at
runtime. This was done by a rather simple pci to amba "bridge" module,
submitted several times, up to https://lkml.org/lkml/2013/2/20/698

The problem was that AMBA devices need platform data with some
instance information.  Platform code (under arch/x86/sta2x11/) was
submitted for some Connext based boards, but it was rejected as "ARM
shit" by Peter Anvin (https://lkml.org/lkml/2012/5/28/266). We agree
the tables are not beautiful, so we didn't submit such stuff any more.
Peter suggested that "the firmware should provide ACPI tables", but
this is not possible for plug-in pci boards, or we should use
devicetree (Peter's message: https://lkml.org/lkml/2012/5/29/38).

So we turned to devicetree, mostly because AMBA drivers usually
already have devicetree support.  Davide took over the effort, which
turned out to be really big.

Some of the problems he found are:

     * Passing a dtb to the kernel: we use a modified kexec at present
       because x86 boot loaders can't pass the DT blob, to our knowledge.

     * Passing correct irq numbers to the AMBA drivers, because PCI MSI
       irq numbers are dynamically allocated (we solved this by using
       of_update_property() at runtime). We also had to register a new
       irq domain for msi irqs, otherwise of_irq_map_one() would complain
       about irqs lacking a corresponding domain.

     * Switching to a new gpio driver with devicetree support (we took the
       Nomadik gpio/pinctrl because our device apparently has more or less
       the same gpio cell as the Nomadik chip). This requires implementation
       of writel_relaxed() and IRQF_VALID on x86: we hacked them internally
       but the patches are not part of this set. We're willing to solve
       these incompatibilities first, if there's interest.

     * Writing a suitable dts: at present, a dts only exists for one
       of the STA2X11 based boards (Intel Northville). This includes a
       copy of all the physical addresses for the devices, as dts requires
       that, even if such addresses are automatically assigned by PCI.
       Clearly, with this approach we kill PCI autodetect: if you plug
       to a different slot you need a different dts.

This got us a more or less working kernel on the Northville board
(where the device is soldered on the motherboard and acts as main chipset).
The plug-in PCIe board cannot be supported by device tree, as far as
we know, which in our opinion is a strong downside of device tree in favor
of the platform data "shit".

Here's the list of amba devices after boot (we used a kernel
with a common clock framework implementation for the Connext, patches
to be (re)submitted shortly):

[root@localhost ~]# for d in `ls /sys/bus/amba/devices/` ; \
do cat /sys/bus/amba/devices/$d/id ; done
00280080 # -> amba pl080
00380802 # -> amba pl011
00380802 # -> amba pl011
00380802 # -> amba pl011
00380802 # -> amba pl011
10480180 # -> amba mmci
10480180 # -> amba mmci
10480180 # -> amba mmci
10480180 # -> amba mmci
00080023 # -> amba pl023
00080023 # -> amba pl023
00080023 # -> amba pl023
00280080 # -> amba pl080

And the platform devices:

[root@localhost ~]# for d in `ls /sys/bus/platform/devices/` ; \
do cat /sys/bus/platform/devices/$d/modalias ; done
platform:alarmtimer
platform:apb-regs.3		# Connext apb-regs
platform:apb-soc-regs.3		# Connext apb-soc-regs
platform:gpio-0000:03:00.0-0	# Connext gpios 0..3
platform:gpio-0000:03:00.0-1
platform:gpio-0000:03:00.0-2
platform:gpio-0000:03:00.0-3
platform:microcode
platform:mmio-0000:05:00.5-0	# Connext esram memory
platform:pcspkr
platform:regulatory
platform:scr.3			# Connext scr (OTP)
platform:sctl.3			# Connext sysctl
platform:serial8250
platform:sta2x11-clock-regs	# Connext virtual clock regs platform dev


But this awful pile of dts data will not work for he pluggable PCIe card.
We need to regenerate the dts file at each and every boot, because PCI
assignment may change according to what other cards are present.

So this devicetree stuff is killing all the autodetection of PCI,
and is very difficult to pass over in the x86 world. On the other
hand platform data is denied by x86 maintainers.

So the question is: what is the right way (and the right dts
structure) to deal with a hotplug bus that instantiates AMBA
devices, without killing del self-detection features?

Thanks
/alessandro


Alessandro Rubini (5):
  x86: fix warning for sta2x11
  DMA: PL330: use prefix in reg names to build under x86
  mmc: Use the new <linux/sizes.h>
  x86: add CONFIG_ARM_AMBA, selected by STA2X11
  drivers/amba: add support for a PCI bridge

Davide Ciminaghi (21):
  x86 STA2X11: select devicetree related config items.
  OF platform: export of_amba_device_create()
  OF platform, of_amba_device_create(): add parent resource to parameters.
  kernel irqdomain: export irq_domain_disassociate()
  x86 devicetree: add irq domain for msi irqs
  x86 devicetree: add functions for handling setup/teardown of MSI irqs
  x86 kernel apic: notify MSI irqdomain(s) on setup/teardown of MSI IRQs
  drivers/amba/pci-amba.c: use devicetree for amba device creation.
  gpio: remove sta2x11-gpio
  x86 STA2X11: remove the sta2x11-mfd driver.
  x86 STA2X11 platform: add sta2x11_platform_init()
  x86 STA2X11 platform: add sta2x11_instance_data helpers
  x86 STA2X11 platform: add a common probe function for platform devices
  x86 STA2X11 platform: create sta2x11-clock-regs device
  x86 STA2X11 platform: remove useless pr_info()'s
  AMBA: pci-amba bridge: improve code readability
  AMBA: pci-amba bridge: extend number of amba devs per pci device
  AMBA: pci-amba bridge: export function creating pci-amba device names
  x86 STA2X11: add dts for Intel's Northville board
  drivers/clk: sta2x11 common clock framework implementation
  pinctrl: add support for sta2x11 (via pinctrl-nomadik)

 .../devicetree/bindings/pinctrl/ste,nomadik.txt    |    2 +-
 .../devicetree/bindings/x86/interrupt.txt          |   14 +
 arch/x86/Kconfig                                   |   10 +
 arch/x86/include/asm/prom.h                        |    9 +
 arch/x86/include/asm/sta2x11.h                     |  358 ++++++++-
 arch/x86/kernel/apic/io_apic.c                     |    5 +
 arch/x86/kernel/devicetree.c                       |   60 ++
 arch/x86/pci/sta2x11-fixup.c                       |    9 +-
 arch/x86/platform/Makefile                         |    1 +
 arch/x86/platform/sta2x11/Makefile                 |    1 +
 arch/x86/platform/sta2x11/northville.dts           |  941 ++++++++++++++++++++
 arch/x86/platform/sta2x11/sta2x11.c                |  522 +++++++++++
 drivers/Kconfig                                    |    2 +
 drivers/amba/Kconfig                               |   10 +
 drivers/amba/Makefile                              |    1 +
 drivers/amba/pci-amba.c                            |  298 +++++++
 drivers/clk/Makefile                               |    1 +
 drivers/clk/sta2x11/Makefile                       |    1 +
 drivers/clk/sta2x11/clk-audio-pll.c                |  149 +++
 drivers/clk/sta2x11/clk-soc-pll.c                  |   95 ++
 drivers/clk/sta2x11/clk.c                          |  865 ++++++++++++++++++
 drivers/clk/sta2x11/clk.h                          |   88 ++
 drivers/dma/pl330.c                                |  107 ++--
 drivers/gpio/Kconfig                               |    8 -
 drivers/gpio/Makefile                              |    1 -
 drivers/gpio/gpio-sta2x11.c                        |  440 ---------
 drivers/mfd/Kconfig                                |    6 -
 drivers/mfd/Makefile                               |    1 -
 drivers/mfd/sta2x11-mfd.c                          |  680 --------------
 drivers/mmc/host/mmci.c                            |    2 +-
 drivers/mmc/host/msm_sdcc.c                        |    2 +-
 drivers/mmc/host/mvsdio.c                          |    2 +-
 drivers/mmc/host/pxamci.c                          |    3 +-
 drivers/of/platform.c                              |   24 +-
 drivers/pinctrl/Kconfig                            |    6 +-
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-nomadik-sta2x11.c          |  578 ++++++++++++
 drivers/pinctrl/pinctrl-nomadik.c                  |    7 +
 drivers/pinctrl/pinctrl-nomadik.h                  |   14 +
 include/linux/irqdomain.h                          |    3 +
 include/linux/mfd/sta2x11-mfd.h                    |  518 -----------
 include/linux/of_platform.h                        |    7 +-
 include/linux/pci-amba.h                           |   42 +
 kernel/irq/irqdomain.c                             |    3 +-
 44 files changed, 4167 insertions(+), 1730 deletions(-)
 create mode 100644 arch/x86/platform/sta2x11/Makefile
 create mode 100644 arch/x86/platform/sta2x11/northville.dts
 create mode 100644 arch/x86/platform/sta2x11/sta2x11.c
 create mode 100644 drivers/amba/Kconfig
 create mode 100644 drivers/amba/pci-amba.c
 create mode 100644 drivers/clk/sta2x11/Makefile
 create mode 100644 drivers/clk/sta2x11/clk-audio-pll.c
 create mode 100644 drivers/clk/sta2x11/clk-soc-pll.c
 create mode 100644 drivers/clk/sta2x11/clk.c
 create mode 100644 drivers/clk/sta2x11/clk.h
 delete mode 100644 drivers/gpio/gpio-sta2x11.c
 delete mode 100644 drivers/mfd/sta2x11-mfd.c
 create mode 100644 drivers/pinctrl/pinctrl-nomadik-sta2x11.c
 delete mode 100644 include/linux/mfd/sta2x11-mfd.h
 create mode 100644 include/linux/pci-amba.h

-- 
1.7.7.2

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH 01/26] x86: fix warning for sta2x11
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
@ 2013-08-07 10:16 ` Alessandro Rubini
  2013-08-07 10:16 ` [PATCH 02/26] DMA: PL330: use prefix in reg names to build under x86 Alessandro Rubini
                   ` (26 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Alessandro Rubini @ 2013-08-07 10:16 UTC (permalink / raw)
  To: linux-kernel
  Cc: Davide Ciminaghi, Giancarlo Asnaghi, x86, H. Peter Anvin,
	Ingo Molnar, Russell King, Thomas Gleixner, devicetree

The .free fied of struct dma_map_ops features a prototype that is
different from what lib/swiotlb.c offers. The new "attrs" argument in
dma_ops.free is missing from the generic implementation.

This removes the build warning by providing a function that just calls
swiotlb_free_coherent() without passing "attrs".

The real solution, in my opinion, would be adding "attrs" as argument
to swiotlb_free_coherent() and remove this new empty function as well
as the identical ones found in other 6 files within arch.

Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/pci/sta2x11-fixup.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/arch/x86/pci/sta2x11-fixup.c b/arch/x86/pci/sta2x11-fixup.c
index 9d8a509..5c24ccb 100644
--- a/arch/x86/pci/sta2x11-fixup.c
+++ b/arch/x86/pci/sta2x11-fixup.c
@@ -180,10 +180,17 @@ static void *sta2x11_swiotlb_alloc_coherent(struct device *dev,
 	return vaddr;
 }
 
+static void sta2x11_swiotlb_free_coherent(struct device *dev, size_t size,
+					  void *vaddr, dma_addr_t dma_addr,
+					  struct dma_attrs *attrs)
+{
+	swiotlb_free_coherent(dev, size, vaddr, dma_addr);
+}
+
 /* We have our own dma_ops: the same as swiotlb but from alloc (above) */
 static struct dma_map_ops sta2x11_dma_ops = {
 	.alloc = sta2x11_swiotlb_alloc_coherent,
-	.free = swiotlb_free_coherent,
+	.free = sta2x11_swiotlb_free_coherent,
 	.map_page = swiotlb_map_page,
 	.unmap_page = swiotlb_unmap_page,
 	.map_sg = swiotlb_map_sg_attrs,
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 02/26] DMA: PL330: use prefix in reg names to build under x86
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
  2013-08-07 10:16 ` [PATCH 01/26] x86: fix warning for sta2x11 Alessandro Rubini
@ 2013-08-07 10:16 ` Alessandro Rubini
  2013-08-07 10:16 ` [PATCH 03/26] mmc: Use the new <linux/sizes.h> Alessandro Rubini
                   ` (25 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Alessandro Rubini @ 2013-08-07 10:16 UTC (permalink / raw)
  To: linux-kernel
  Cc: Davide Ciminaghi, Giancarlo Asnaghi, x86, H. Peter Anvin,
	Ingo Molnar, Russell King, Thomas Gleixner, devicetree

This driver would not compile if ARM_AMBA is selected under x86,
because "CS" and "DS" are already defined there.  But AMBA
is used in the x86 world by a PCI-to-AMBA bridge, to be submitted.

The patch just adds the "PL330_" prefix to all registers,
so it can be built by randomconfig after ARM_AMBA appears within x86.
No other technical changes have been performed.
The patch was build-tested only.

Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
Link: http://lkml.kernel.org/r/1355146956-6009-2-git-send-email-ciminaghi@gnudd.com
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
[Davide Ciminaghi <ciminaghi@gnudd.com>: only registers prefixed]
Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Jassi Brar <jassisinghbrar@gmail.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>

Conflicts:

	drivers/dma/pl330.c
---
 drivers/dma/pl330.c |  107 ++++++++++++++++++++++++++-------------------------
 1 files changed, 54 insertions(+), 53 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 4ad13eb..da67bee 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -71,7 +71,7 @@ enum pl330_reqtype {
 };
 
 /* Register and Bit field Definitions */
-#define DS			0x0
+#define PL330_DS		0x0
 #define DS_ST_STOP		0x0
 #define DS_ST_EXEC		0x1
 #define DS_ST_CMISS		0x2
@@ -85,33 +85,33 @@ enum pl330_reqtype {
 #define DS_ST_FLTCMP		0xe
 #define DS_ST_FAULT		0xf
 
-#define DPC			0x4
-#define INTEN			0x20
-#define ES			0x24
-#define INTSTATUS		0x28
-#define INTCLR			0x2c
-#define FSM			0x30
-#define FSC			0x34
-#define FTM			0x38
+#define PL330_DPC		0x4
+#define PL330_INTEN		0x20
+#define PL330_ES		0x24
+#define PL330_INTSTATUS		0x28
+#define PL330_INTCLR		0x2c
+#define PL330_FSM		0x30
+#define PL330_FSC		0x34
+#define PL330_FTM		0x38
 
 #define _FTC			0x40
-#define FTC(n)			(_FTC + (n)*0x4)
+#define PL330_FTC(n)		(_FTC + (n)*0x4)
 
 #define _CS			0x100
-#define CS(n)			(_CS + (n)*0x8)
+#define PL330_CS(n)		(_CS + (n)*0x8)
 #define CS_CNS			(1 << 21)
 
 #define _CPC			0x104
-#define CPC(n)			(_CPC + (n)*0x8)
+#define PL330_CPC(n)		(_CPC + (n)*0x8)
 
 #define _SA			0x400
-#define SA(n)			(_SA + (n)*0x20)
+#define PL330_SA(n)		(_SA + (n)*0x20)
 
 #define _DA			0x404
-#define DA(n)			(_DA + (n)*0x20)
+#define PL330_DA(n)		(_DA + (n)*0x20)
 
 #define _CC			0x408
-#define CC(n)			(_CC + (n)*0x20)
+#define PL330_CC(n)		(_CC + (n)*0x20)
 
 #define CC_SRCINC		(1 << 0)
 #define CC_DSTINC		(1 << 14)
@@ -132,24 +132,24 @@ enum pl330_reqtype {
 #define CC_SWAP_SHFT		28
 
 #define _LC0			0x40c
-#define LC0(n)			(_LC0 + (n)*0x20)
+#define PL330_LC0(n)		(_LC0 + (n)*0x20)
 
 #define _LC1			0x410
-#define LC1(n)			(_LC1 + (n)*0x20)
+#define PL330_LC1(n)		(_LC1 + (n)*0x20)
 
-#define DBGSTATUS		0xd00
+#define PL330_DBGSTATUS		0xd00
 #define DBG_BUSY		(1 << 0)
 
-#define DBGCMD			0xd04
-#define DBGINST0		0xd08
-#define DBGINST1		0xd0c
+#define PL330_DBGCMD		0xd04
+#define PL330_DBGINST0		0xd08
+#define PL330_DBGINST1		0xd0c
 
-#define CR0			0xe00
-#define CR1			0xe04
-#define CR2			0xe08
-#define CR3			0xe0c
-#define CR4			0xe10
-#define CRD			0xe14
+#define PL330_CR0		0xe00
+#define PL330_CR1		0xe04
+#define PL330_CR2		0xe08
+#define PL330_CR3		0xe0c
+#define PL330_CR4		0xe10
+#define PL330_CRD		0xe14
 
 #define PERIPH_ID		0xfe0
 #define PERIPH_REV_SHIFT	20
@@ -1006,7 +1006,7 @@ static bool _until_dmac_idle(struct pl330_thread *thrd)
 
 	do {
 		/* Until Manager is Idle */
-		if (!(readl(regs + DBGSTATUS) & DBG_BUSY))
+		if (!(readl(regs + PL330_DBGSTATUS) & DBG_BUSY))
 			break;
 
 		cpu_relax();
@@ -1029,10 +1029,10 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd,
 		val |= (1 << 0);
 		val |= (thrd->id << 8); /* Channel Number */
 	}
-	writel(val, regs + DBGINST0);
+	writel(val, regs + PL330_DBGINST0);
 
 	val = *((u32 *)&insn[2]);
-	writel(val, regs + DBGINST1);
+	writel(val, regs + PL330_DBGINST1);
 
 	/* If timed out due to halted state-machine */
 	if (_until_dmac_idle(thrd)) {
@@ -1041,7 +1041,7 @@ static inline void _execute_DBGINSN(struct pl330_thread *thrd,
 	}
 
 	/* Get going */
-	writel(0, regs + DBGCMD);
+	writel(0, regs + PL330_DBGCMD);
 }
 
 /*
@@ -1066,9 +1066,9 @@ static inline u32 _state(struct pl330_thread *thrd)
 	u32 val;
 
 	if (is_manager(thrd))
-		val = readl(regs + DS) & 0xf;
+		val = readl(regs + PL330_DS) & 0xf;
 	else
-		val = readl(regs + CS(thrd->id)) & 0xf;
+		val = readl(regs + PL330_CS(thrd->id)) & 0xf;
 
 	switch (val) {
 	case DS_ST_STOP:
@@ -1135,7 +1135,8 @@ static void _stop(struct pl330_thread *thrd)
 	_emit_KILL(0, insn);
 
 	/* Stop generating interrupts for SEV */
-	writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN);
+	writel(readl(regs + PL330_INTEN) & ~(1 << thrd->ev),
+	       regs + PL330_INTEN);
 
 	_execute_DBGINSN(thrd, insn, is_manager(thrd));
 }
@@ -1174,7 +1175,7 @@ static bool _trigger(struct pl330_thread *thrd)
 
 	if (r->cfg)
 		ns = r->cfg->nonsecure ? 1 : 0;
-	else if (readl(regs + CS(thrd->id)) & CS_CNS)
+	else if (readl(regs + PL330_CS(thrd->id)) & CS_CNS)
 		ns = 1;
 	else
 		ns = 0;
@@ -1190,7 +1191,7 @@ static bool _trigger(struct pl330_thread *thrd)
 	_emit_GO(0, insn, &go);
 
 	/* Set to generate interrupts for SEV */
-	writel(readl(regs + INTEN) | (1 << thrd->ev), regs + INTEN);
+	writel(readl(regs + PL330_INTEN) | (1 << thrd->ev), regs + PL330_INTEN);
 
 	/* Only manager can execute GO */
 	_execute_DBGINSN(thrd, insn, true);
@@ -1565,7 +1566,7 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r)
 
 		ccr = _prepare_ccr(r->cfg);
 	} else {
-		ccr = readl(regs + CC(thrd->id));
+		ccr = readl(regs + PL330_CC(thrd->id));
 	}
 
 	/* If this req doesn't have valid xfer settings */
@@ -1642,7 +1643,7 @@ static void pl330_dotask(unsigned long data)
 
 			_stop(thrd);
 
-			if (readl(regs + FSC) & (1 << thrd->id))
+			if (readl(regs + PL330_FSC) & (1 << thrd->id))
 				err = PL330_ERR_FAIL;
 			else
 				err = PL330_ERR_ABORT;
@@ -1687,13 +1688,13 @@ static int pl330_update(const struct pl330_info *pi)
 
 	spin_lock_irqsave(&pl330->lock, flags);
 
-	val = readl(regs + FSM) & 0x1;
+	val = readl(regs + PL330_FSM) & 0x1;
 	if (val)
 		pl330->dmac_tbd.reset_mngr = true;
 	else
 		pl330->dmac_tbd.reset_mngr = false;
 
-	val = readl(regs + FSC) & ((1 << pi->pcfg.num_chan) - 1);
+	val = readl(regs + PL330_FSC) & ((1 << pi->pcfg.num_chan) - 1);
 	pl330->dmac_tbd.reset_chan |= val;
 	if (val) {
 		int i = 0;
@@ -1701,8 +1702,8 @@ static int pl330_update(const struct pl330_info *pi)
 			if (val & (1 << i)) {
 				dev_info(pi->dev,
 					"Reset Channel-%d\t CS-%x FTC-%x\n",
-						i, readl(regs + CS(i)),
-						readl(regs + FTC(i)));
+						i, readl(regs + PL330_CS(i)),
+						readl(regs + PL330_FTC(i)));
 				_stop(&pl330->channels[i]);
 			}
 			i++;
@@ -1710,7 +1711,7 @@ static int pl330_update(const struct pl330_info *pi)
 	}
 
 	/* Check which event happened i.e, thread notified */
-	val = readl(regs + ES);
+	val = readl(regs + PL330_ES);
 	if (pi->pcfg.num_events < 32
 			&& val & ~((1 << pi->pcfg.num_events) - 1)) {
 		pl330->dmac_tbd.reset_dmac = true;
@@ -1722,12 +1723,12 @@ static int pl330_update(const struct pl330_info *pi)
 	for (ev = 0; ev < pi->pcfg.num_events; ev++) {
 		if (val & (1 << ev)) { /* Event occurred */
 			struct pl330_thread *thrd;
-			u32 inten = readl(regs + INTEN);
+			u32 inten = readl(regs + PL330_INTEN);
 			int active;
 
 			/* Clear the event */
 			if (inten & (1 << ev))
-				writel(1 << ev, regs + INTCLR);
+				writel(1 << ev, regs + PL330_INTCLR);
 
 			ret = 1;
 
@@ -1934,41 +1935,41 @@ static void read_dmac_config(struct pl330_info *pi)
 	void __iomem *regs = pi->base;
 	u32 val;
 
-	val = readl(regs + CRD) >> CRD_DATA_WIDTH_SHIFT;
+	val = readl(regs + PL330_CRD) >> CRD_DATA_WIDTH_SHIFT;
 	val &= CRD_DATA_WIDTH_MASK;
 	pi->pcfg.data_bus_width = 8 * (1 << val);
 
-	val = readl(regs + CRD) >> CRD_DATA_BUFF_SHIFT;
+	val = readl(regs + PL330_CRD) >> CRD_DATA_BUFF_SHIFT;
 	val &= CRD_DATA_BUFF_MASK;
 	pi->pcfg.data_buf_dep = val + 1;
 
-	val = readl(regs + CR0) >> CR0_NUM_CHANS_SHIFT;
+	val = readl(regs + PL330_CR0) >> CR0_NUM_CHANS_SHIFT;
 	val &= CR0_NUM_CHANS_MASK;
 	val += 1;
 	pi->pcfg.num_chan = val;
 
-	val = readl(regs + CR0);
+	val = readl(regs + PL330_CR0);
 	if (val & CR0_PERIPH_REQ_SET) {
 		val = (val >> CR0_NUM_PERIPH_SHIFT) & CR0_NUM_PERIPH_MASK;
 		val += 1;
 		pi->pcfg.num_peri = val;
-		pi->pcfg.peri_ns = readl(regs + CR4);
+		pi->pcfg.peri_ns = readl(regs + PL330_CR4);
 	} else {
 		pi->pcfg.num_peri = 0;
 	}
 
-	val = readl(regs + CR0);
+	val = readl(regs + PL330_CR0);
 	if (val & CR0_BOOT_MAN_NS)
 		pi->pcfg.mode |= DMAC_MODE_NS;
 	else
 		pi->pcfg.mode &= ~DMAC_MODE_NS;
 
-	val = readl(regs + CR0) >> CR0_NUM_EVENTS_SHIFT;
+	val = readl(regs + PL330_CR0) >> CR0_NUM_EVENTS_SHIFT;
 	val &= CR0_NUM_EVENTS_MASK;
 	val += 1;
 	pi->pcfg.num_events = val;
 
-	pi->pcfg.irq_ns = readl(regs + CR3);
+	pi->pcfg.irq_ns = readl(regs + PL330_CR3);
 }
 
 static inline void _reset_thread(struct pl330_thread *thrd)
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 03/26] mmc: Use the new <linux/sizes.h>
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
  2013-08-07 10:16 ` [PATCH 01/26] x86: fix warning for sta2x11 Alessandro Rubini
  2013-08-07 10:16 ` [PATCH 02/26] DMA: PL330: use prefix in reg names to build under x86 Alessandro Rubini
@ 2013-08-07 10:16 ` Alessandro Rubini
  2013-08-07 10:17 ` [PATCH 04/26] x86: add CONFIG_ARM_AMBA, selected by STA2X11 Alessandro Rubini
                   ` (24 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Alessandro Rubini @ 2013-08-07 10:16 UTC (permalink / raw)
  To: linux-kernel
  Cc: Davide Ciminaghi, Giancarlo Asnaghi, x86, H. Peter Anvin,
	Ingo Molnar, Russell King, Thomas Gleixner, devicetree,
	Chris Ball, linux-mmc

For portability, use <linux/sizes.h>.

Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
Link: http://lkml.kernel.org/r/1355146956-6009-6-git-send-email-ciminaghi@gnudd.com
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
Acked-by: David Brown <davidb@codeaurora.org>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
---
 drivers/mmc/host/mmci.c     |    2 +-
 drivers/mmc/host/msm_sdcc.c |    2 +-
 drivers/mmc/host/mvsdio.c   |    2 +-
 drivers/mmc/host/pxamci.c   |    3 +--
 4 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index c3785ed..edd987e 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -34,11 +34,11 @@
 #include <linux/amba/mmci.h>
 #include <linux/pm_runtime.h>
 #include <linux/types.h>
+#include <linux/sizes.h>
 #include <linux/pinctrl/consumer.h>
 
 #include <asm/div64.h>
 #include <asm/io.h>
-#include <asm/sizes.h>
 
 #include "mmci.h"
 
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index b900de4..405f0d8 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -37,10 +37,10 @@
 #include <linux/memory.h>
 #include <linux/gfp.h>
 #include <linux/gpio.h>
+#include <linux/sizes.h>
 
 #include <asm/cacheflush.h>
 #include <asm/div64.h>
-#include <asm/sizes.h>
 
 #include <linux/platform_data/mmc-msm_sdcc.h>
 #include <mach/dma.h>
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index 4ddd83f..4dec50f 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -23,11 +23,11 @@
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
 #include <linux/of_irq.h>
+#include <linux/sizes.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/slot-gpio.h>
 #include <linux/pinctrl/consumer.h>
 
-#include <asm/sizes.h>
 #include <asm/unaligned.h>
 #include <linux/platform_data/mmc-mvsdio.h>
 
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c
index 1956a3d..3924f36 100644
--- a/drivers/mmc/host/pxamci.c
+++ b/drivers/mmc/host/pxamci.c
@@ -33,8 +33,7 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
-
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <mach/hardware.h>
 #include <mach/dma.h>
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 04/26] x86: add CONFIG_ARM_AMBA, selected by STA2X11
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (2 preceding siblings ...)
  2013-08-07 10:16 ` [PATCH 03/26] mmc: Use the new <linux/sizes.h> Alessandro Rubini
@ 2013-08-07 10:17 ` Alessandro Rubini
  2013-08-07 10:17 ` [PATCH 05/26] drivers/amba: add support for a PCI bridge Alessandro Rubini
                   ` (23 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Alessandro Rubini @ 2013-08-07 10:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: Davide Ciminaghi, Giancarlo Asnaghi, x86, H. Peter Anvin,
	Ingo Molnar, Russell King, Thomas Gleixner, devicetree

The sta2x11 I/O Hub is a bridge from PCIe to AMBA. It reuses a number
of amba drivers and needs to activate core bus support.

Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/Kconfig |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 52432ab..490b001 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -554,6 +554,7 @@ config STA2X11
 	select SWIOTLB
 	select MFD_STA2X11
 	select ARCH_REQUIRE_GPIOLIB
+	select ARM_AMBA
 	default n
 	---help---
 	  This adds support for boards based on the STA2X11 IO-Hub,
@@ -2255,6 +2256,9 @@ config TS5500
 
 endif # X86_32
 
+config ARM_AMBA
+        bool
+
 config AMD_NB
 	def_bool y
 	depends on CPU_SUP_AMD && PCI
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 05/26] drivers/amba: add support for a PCI bridge
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (3 preceding siblings ...)
  2013-08-07 10:17 ` [PATCH 04/26] x86: add CONFIG_ARM_AMBA, selected by STA2X11 Alessandro Rubini
@ 2013-08-07 10:17 ` Alessandro Rubini
  2013-08-07 10:17 ` [PATCH 06/26] x86 STA2X11: select devicetree related config items Davide Ciminaghi
                   ` (22 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Alessandro Rubini @ 2013-08-07 10:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: Davide Ciminaghi, Giancarlo Asnaghi, x86, H. Peter Anvin,
	Ingo Molnar, Russell King, Thomas Gleixner, devicetree

This is a PCI driver that registers AMBA devices for the range of
supported devices.  It is currently used by STA2X11, which exports
AMBA peripherals under PCIe.  The original AMBA drivers work with no
changes or minimal ones.

Signed-off-by: Alessandro Rubini <rubini@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
Cc: Russell King <linux@arm.linux.org.uk>
---
 drivers/Kconfig         |    2 +
 drivers/amba/Kconfig    |   10 +++++
 drivers/amba/Makefile   |    1 +
 drivers/amba/pci-amba.c |   93 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 106 insertions(+), 0 deletions(-)
 create mode 100644 drivers/amba/Kconfig
 create mode 100644 drivers/amba/pci-amba.c

diff --git a/drivers/Kconfig b/drivers/Kconfig
index aa43b91..5603bc3 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -166,4 +166,6 @@ source "drivers/reset/Kconfig"
 
 source "drivers/fmc/Kconfig"
 
+source "drivers/amba/Kconfig"
+
 endmenu
diff --git a/drivers/amba/Kconfig b/drivers/amba/Kconfig
new file mode 100644
index 0000000..b5b5aca
--- /dev/null
+++ b/drivers/amba/Kconfig
@@ -0,0 +1,10 @@
+
+config PCI_AMBA
+	tristate "PCI-to-AMBA bridge"
+	depends on ARM_AMBA && PCI
+	---help---
+	  This compiles a PCI driver that registers AMBA devices, so
+	  the respective AMBA driver can be used unchanged if you have
+	  a PCI to amba bridge. This is required for STA2X11 support.
+
+	  If uncertain, choose N.
diff --git a/drivers/amba/Makefile b/drivers/amba/Makefile
index 66e81c2..d30e947 100644
--- a/drivers/amba/Makefile
+++ b/drivers/amba/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ARM_AMBA)		+= bus.o
+obj-$(CONFIG_PCI_AMBA)		+= pci-amba.o
 obj-$(CONFIG_TEGRA_AHB)		+= tegra-ahb.o
diff --git a/drivers/amba/pci-amba.c b/drivers/amba/pci-amba.c
new file mode 100644
index 0000000..8ce526a
--- /dev/null
+++ b/drivers/amba/pci-amba.c
@@ -0,0 +1,93 @@
+/*
+ * Support for AMBA devices (both APB and AHB) behind a PCI bridge
+ * Copyright 2012 ST Microelectronics (Alessandro Rubini)
+ * GNU GPL version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/amba/bus.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/sizes.h>
+
+static int pci_amba_probe(struct pci_dev *pdev,
+			  const struct pci_device_id *id)
+{
+	struct amba_device *adev;
+	char *name;
+	int ret;
+
+	pci_enable_msi(pdev);
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+
+	/* Create a name: each of them must be different */
+	name = devm_kzalloc(&pdev->dev, strlen(dev_name(&pdev->dev)) + 6,
+		GFP_KERNEL);
+	sprintf(name, "amba-%s", dev_name(&pdev->dev));
+
+	/* Simply build an amba device and register it */
+	adev = amba_device_alloc(name,  pdev->resource[0].start, SZ_4K);
+	if (!adev)
+		return -ENOMEM;
+	adev->irq[0] = pdev->irq;
+
+	/* This bridge can host both APB and AHB devices, so set master */
+	pci_set_master(pdev);
+	if (pdev->vendor == PCI_VENDOR_ID_STMICRO) {
+		/* Under sta2x11, DMA is there but limited to 512M */
+		adev->dma_mask = SZ_512M - 1;
+		adev->dev.coherent_dma_mask = SZ_512M - 1;
+	}
+
+	adev->dev.platform_data = pdev->dev.platform_data;
+	pci_set_drvdata(pdev, adev);
+
+	return amba_device_add(adev, &pdev->resource[0]);
+};
+
+static void pci_amba_remove(struct pci_dev *pdev)
+{
+	struct amba_device *adev = pci_get_drvdata(pdev);
+	amba_device_unregister(adev);
+	pci_disable_msi(pdev);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(pci_amba_table) = {
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_UART_HWFC)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_UART_NO_HWFC)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_SOC_DMA)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_I2C)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_SPI_HS)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_SDIO_EMMC)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_SDIO)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_DMA)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_MSPS)},
+	{0,}
+};
+
+static struct pci_driver pci_amba_driver = {
+	.name		= "pci-amba",
+	.id_table	= pci_amba_table,
+	.probe		= pci_amba_probe,
+	.remove		= pci_amba_remove,
+};
+
+static int __init pci_amba_init(void)
+{
+	return pci_register_driver(&pci_amba_driver);
+}
+
+static void __exit pci_amba_exit(void)
+{
+	pci_unregister_driver(&pci_amba_driver);
+}
+
+module_init(pci_amba_init);
+module_exit(pci_amba_exit);
+
+MODULE_LICENSE("GPL");
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 06/26] x86 STA2X11: select devicetree related config items.
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (4 preceding siblings ...)
  2013-08-07 10:17 ` [PATCH 05/26] drivers/amba: add support for a PCI bridge Alessandro Rubini
@ 2013-08-07 10:17 ` Davide Ciminaghi
  2013-08-07 10:17 ` [PATCH 07/26] OF platform: export of_amba_device_create() Davide Ciminaghi
                   ` (21 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch selects some config items needed for adding device tree support
to STA2X11 based machines. In particular:

* OF_DYNAMIC is needed to use of_detach_node() and avoid instantiating
  the same node twice.

* IRQ_DOMAIN is needed because irq_of_parse_and_map() needs
  irq_create_of_mapping(), which is part of the irqdomain stuff.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/Kconfig |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 490b001..0a779eb 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -555,6 +555,10 @@ config STA2X11
 	select MFD_STA2X11
 	select ARCH_REQUIRE_GPIOLIB
 	select ARM_AMBA
+	select OF
+	select OF_EARLY_FLATTREE
+	select OF_DYNAMIC
+	select IRQ_DOMAIN
 	default n
 	---help---
 	  This adds support for boards based on the STA2X11 IO-Hub,
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 07/26] OF platform: export of_amba_device_create()
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (5 preceding siblings ...)
  2013-08-07 10:17 ` [PATCH 06/26] x86 STA2X11: select devicetree related config items Davide Ciminaghi
@ 2013-08-07 10:17 ` Davide Ciminaghi
  2013-08-07 10:17 ` [PATCH 08/26] OF platform, of_amba_device_create(): add parent resource to parameters Davide Ciminaghi
                   ` (20 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This is needed because the pci-amba bus will create one or more amba devices
for each probed pci device. We cannot create all the devices belonging to
the same amba bus with just one call to of_platform_populate()

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 drivers/of/platform.c       |   17 +++++++++--------
 include/linux/of_platform.h |    6 +++++-
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index b0d1ff8..57c6bbe 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -249,10 +249,10 @@ struct platform_device *of_platform_device_create(struct device_node *np,
 EXPORT_SYMBOL(of_platform_device_create);
 
 #ifdef CONFIG_ARM_AMBA
-static struct amba_device *of_amba_device_create(struct device_node *node,
-						 const char *bus_id,
-						 void *platform_data,
-						 struct device *parent)
+struct amba_device *of_amba_device_create(struct device_node *node,
+					  const char *bus_id,
+					  void *platform_data,
+					  struct device *parent)
 {
 	struct amba_device *dev;
 	const void *prop;
@@ -304,14 +304,15 @@ err_free:
 	return NULL;
 }
 #else /* CONFIG_ARM_AMBA */
-static struct amba_device *of_amba_device_create(struct device_node *node,
-						 const char *bus_id,
-						 void *platform_data,
-						 struct device *parent)
+struct amba_device *of_amba_device_create(struct device_node *node,
+					  const char *bus_id,
+					  void *platform_data,
+					  struct device *parent)
 {
 	return NULL;
 }
 #endif /* CONFIG_ARM_AMBA */
+EXPORT_SYMBOL(of_amba_device_create);
 
 /**
  * of_devname_lookup() - Given a device node, lookup the preferred Linux name
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 05cb4a9..6cd5ac2 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -59,10 +59,14 @@ extern struct platform_device *of_device_alloc(struct device_node *np,
 					 struct device *parent);
 extern struct platform_device *of_find_device_by_node(struct device_node *np);
 
-/* Platform devices and busses creation */
+/* Platform and amba devices and busses creation */
 extern struct platform_device *of_platform_device_create(struct device_node *np,
 						   const char *bus_id,
 						   struct device *parent);
+extern struct amba_device *of_amba_device_create(struct device_node *node,
+						 const char *bus_id,
+						 void *platform_data,
+						 struct device *parent);
 
 extern int of_platform_bus_probe(struct device_node *root,
 				 const struct of_device_id *matches,
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 08/26] OF platform, of_amba_device_create(): add parent resource to parameters.
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (6 preceding siblings ...)
  2013-08-07 10:17 ` [PATCH 07/26] OF platform: export of_amba_device_create() Davide Ciminaghi
@ 2013-08-07 10:17 ` Davide Ciminaghi
  2013-08-07 10:17 ` [PATCH 09/26] kernel irqdomain: export irq_domain_disassociate() Davide Ciminaghi
                   ` (19 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This is needed when creating pci-amba devices: an amba device's
resource shall be child of the corresponding pci device's resource.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 drivers/of/platform.c       |   11 +++++++----
 include/linux/of_platform.h |    3 ++-
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 57c6bbe..bf75aaa 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -252,7 +252,8 @@ EXPORT_SYMBOL(of_platform_device_create);
 struct amba_device *of_amba_device_create(struct device_node *node,
 					  const char *bus_id,
 					  void *platform_data,
-					  struct device *parent)
+					  struct device *parent,
+					  struct resource *parent_resource)
 {
 	struct amba_device *dev;
 	const void *prop;
@@ -293,7 +294,7 @@ struct amba_device *of_amba_device_create(struct device_node *node,
 	if (ret)
 		goto err_free;
 
-	ret = amba_device_add(dev, &iomem_resource);
+	ret = amba_device_add(dev, parent_resource);
 	if (ret)
 		goto err_free;
 
@@ -307,7 +308,8 @@ err_free:
 struct amba_device *of_amba_device_create(struct device_node *node,
 					  const char *bus_id,
 					  void *platform_data,
-					  struct device *parent)
+					  struct device *parent,
+					  struct resource *parent_resource)
 {
 	return NULL;
 }
@@ -375,7 +377,8 @@ static int of_platform_bus_create(struct device_node *bus,
 	}
 
 	if (of_device_is_compatible(bus, "arm,primecell")) {
-		of_amba_device_create(bus, bus_id, platform_data, parent);
+		of_amba_device_create(bus, bus_id, platform_data, parent,
+				      &iomem_resource);
 		return 0;
 	}
 
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index 6cd5ac2..be13538 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -66,7 +66,8 @@ extern struct platform_device *of_platform_device_create(struct device_node *np,
 extern struct amba_device *of_amba_device_create(struct device_node *node,
 						 const char *bus_id,
 						 void *platform_data,
-						 struct device *parent);
+						 struct device *parent,
+						 struct resource *parent_res);
 
 extern int of_platform_bus_probe(struct device_node *root,
 				 const struct of_device_id *matches,
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 09/26] kernel irqdomain: export irq_domain_disassociate()
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (7 preceding siblings ...)
  2013-08-07 10:17 ` [PATCH 08/26] OF platform, of_amba_device_create(): add parent resource to parameters Davide Ciminaghi
@ 2013-08-07 10:17 ` Davide Ciminaghi
  2013-08-07 10:19 ` [PATCH 10/26] x86 devicetree: add irq domain for msi irqs Davide Ciminaghi
                   ` (18 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:17 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree,
	Benjamin Herrenschmidt

irq_create_of_mapping() requires an irqdomain to be registered for each
interrupt controller node.
While extending devicetree usage on x86 to devices with MSI irqs, [at
least] an msi interrupt controller node had to be added together with the
relevant irqdomain.
Registering a nomap irqdomain for each msi controller and adding irqs to
such domain in native_setup_msi_irqs() via irq_domain_associate() looked
like the simplest and safest solution to the problem, but then of course
irq_domain_disassociate() must be called by native_teardown_msi_irq().

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 include/linux/irqdomain.h |    3 +++
 kernel/irq/irqdomain.c    |    3 ++-
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index c983ed1..b7f0df4 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -172,6 +172,9 @@ extern int irq_domain_associate(struct irq_domain *domain, unsigned int irq,
 extern void irq_domain_associate_many(struct irq_domain *domain,
 				      unsigned int irq_base,
 				      irq_hw_number_t hwirq_base, int count);
+extern void irq_domain_disassociate(struct irq_domain *domain,
+				    unsigned int irq);
+
 
 extern unsigned int irq_create_mapping(struct irq_domain *host,
 				       irq_hw_number_t hwirq);
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 706724e..a33e29c 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -230,7 +230,7 @@ void irq_set_default_host(struct irq_domain *domain)
 }
 EXPORT_SYMBOL_GPL(irq_set_default_host);
 
-static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
+void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
 {
 	struct irq_data *irq_data = irq_get_irq_data(irq);
 	irq_hw_number_t hwirq;
@@ -265,6 +265,7 @@ static void irq_domain_disassociate(struct irq_domain *domain, unsigned int irq)
 		mutex_unlock(&revmap_trees_mutex);
 	}
 }
+EXPORT_SYMBOL(irq_domain_disassociate);
 
 int irq_domain_associate(struct irq_domain *domain, unsigned int virq,
 			 irq_hw_number_t hwirq)
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 10/26] x86 devicetree: add irq domain for msi irqs
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (8 preceding siblings ...)
  2013-08-07 10:17 ` [PATCH 09/26] kernel irqdomain: export irq_domain_disassociate() Davide Ciminaghi
@ 2013-08-07 10:19 ` Davide Ciminaghi
  2013-08-07 10:19 ` [PATCH 11/26] x86 devicetree: add functions for handling setup/teardown of MSI irqs Davide Ciminaghi
                   ` (17 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:19 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

An irqdomain is created for each MSI interrupt controller found in
the tree. This is to make irq_create_of_mapping() happy later on.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 .../devicetree/bindings/x86/interrupt.txt          |   14 ++++++++++++++
 arch/x86/kernel/devicetree.c                       |   12 ++++++++++++
 2 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/Documentation/devicetree/bindings/x86/interrupt.txt b/Documentation/devicetree/bindings/x86/interrupt.txt
index 7d19f49..fa6e2f0 100644
--- a/Documentation/devicetree/bindings/x86/interrupt.txt
+++ b/Documentation/devicetree/bindings/x86/interrupt.txt
@@ -24,3 +24,17 @@ Interrupt chips
   Required property:
 
      compatible = "intel,ce4100-lapic";
+
+* MSI interrupts (STA2X11)
+
+  Required properties:
+  -------------------
+     compatible = "intel,msi-irqs";
+     #interrupt-cells = <1>;
+
+  Device's interrupt property:
+
+     interrupts = <I>;
+
+  I is the MSI irq number. Should be left equal to zero in the devicetree
+  and updated at runtime, after the irq number has been allocated.
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 376dc78..d1dcfd0 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -401,6 +401,16 @@ static void __init ioapic_add_ofnode(struct device_node *np)
 	printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
 }
 
+static const struct irq_domain_ops msi_irq_domain_ops = {
+	.xlate = irq_domain_xlate_onecell,
+};
+
+static void __init add_msi_irq_domain(struct device_node *np)
+{
+	if (!irq_domain_add_nomap(np, nr_irqs, &msi_irq_domain_ops, NULL))
+		pr_err("%s: error creating msi domain\n", __func__);
+}
+
 void __init x86_add_irq_domains(void)
 {
 	struct device_node *dp;
@@ -411,6 +421,8 @@ void __init x86_add_irq_domains(void)
 	for_each_node_with_property(dp, "interrupt-controller") {
 		if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
 			ioapic_add_ofnode(dp);
+		if (of_device_is_compatible(dp, "intel,msi-irqs"))
+			add_msi_irq_domain(dp);
 	}
 }
 #else
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 11/26] x86 devicetree: add functions for handling setup/teardown of MSI irqs
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (9 preceding siblings ...)
  2013-08-07 10:19 ` [PATCH 10/26] x86 devicetree: add irq domain for msi irqs Davide Ciminaghi
@ 2013-08-07 10:19 ` Davide Ciminaghi
  2013-08-07 10:19 ` [PATCH 12/26] x86 kernel apic: notify MSI irqdomain(s) on etup/teardown of MSI IRQs Davide Ciminaghi
                   ` (16 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:19 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch introduces x86_of_new_msi_irq() and x86_of_del_msi_irq(), which
shall be invoked by native_setup_msi_irqs() and native_teardown_msi_irq()
respectively to add/delete irq numbers to/from the "dummy" msi irqdomain.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/include/asm/prom.h  |    9 +++++++
 arch/x86/kernel/devicetree.c |   48 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h
index bade6ac..902b361 100644
--- a/arch/x86/include/asm/prom.h
+++ b/arch/x86/include/asm/prom.h
@@ -27,11 +27,20 @@ extern int of_ioapic;
 extern u64 initial_dtb;
 extern void add_dtb(u64 data);
 extern void x86_add_irq_domains(void);
+extern int x86_of_new_msi_irq(struct pci_dev *pdev, unsigned int irq);
+extern void x86_of_del_msi_irq(unsigned int irq);
 void x86_of_pci_init(void);
 void x86_dtb_init(void);
 #else
 static inline void add_dtb(u64 data) { }
 static inline void x86_add_irq_domains(void) { }
+
+static inline int x86_of_new_msi_irq(struct pci_dev *pdev, unsigned int irq)
+{
+	return 0;
+}
+
+static inline void x86_of_del_msi_irq(unsigned int irq) { }
 static inline void x86_of_pci_init(void) { }
 static inline void x86_dtb_init(void) { }
 #define of_ioapic 0
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index d1dcfd0..805931b 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -401,6 +401,54 @@ static void __init ioapic_add_ofnode(struct device_node *np)
 	printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
 }
 
+int x86_of_new_msi_irq(struct pci_dev *pdev, unsigned int irq)
+{
+	struct device_node *n = of_node_get(pci_device_to_OF_node(pdev));
+	struct device_node *iparent;
+	struct irq_domain *d;
+	int ret = 0;
+	/* Dummy interrupt specifier */
+	__be32 intspec = 0;
+	const __be32 *addr;
+	struct of_irq oirq;
+
+	/* Walk up the tree looking for the device's interrupt controller */
+	if (!n)
+		return ret;
+	iparent = of_irq_find_parent(n);
+	of_node_put(n);
+	if (!iparent)
+		return ret;
+
+	addr = of_get_property(n, "reg", NULL);
+	if (!addr)
+		return ret;
+
+	ret = of_irq_map_raw(iparent, &intspec, 1, addr, &oirq);
+	if (ret < 0)
+		return ret;
+
+	/* Controller found, now look for the relevant irq domain */
+	d = irq_find_host(oirq.controller);
+	if (!d) {
+		WARN_ON(1);
+		return -ENODEV;
+	}
+	/* And finally simply associate this irq number with itself */
+	ret = irq_domain_associate(d, irq, irq);
+	return ret;
+}
+
+void x86_of_del_msi_irq(unsigned int irq)
+{
+	struct irq_data *irq_data = irq_get_irq_data(irq);
+	if (!irq_data->domain) {
+		WARN_ON(1);
+		return;
+	}
+	irq_domain_disassociate(irq_data->domain, irq);
+}
+
 static const struct irq_domain_ops msi_irq_domain_ops = {
 	.xlate = irq_domain_xlate_onecell,
 };
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 12/26] x86 kernel apic: notify MSI irqdomain(s) on etup/teardown of MSI IRQs
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (10 preceding siblings ...)
  2013-08-07 10:19 ` [PATCH 11/26] x86 devicetree: add functions for handling setup/teardown of MSI irqs Davide Ciminaghi
@ 2013-08-07 10:19 ` Davide Ciminaghi
  2013-08-07 10:19 ` [PATCH 13/26] drivers/amba/pci-amba.c: use devicetree for amba device creation Davide Ciminaghi
                   ` (15 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:19 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch should have no effect on non-OF x86 machines.

When CONFIG_OF is enabled, an irqdomain exists for each MSI controller
in the devicetree. This patch invokes the functions taking care of
adding/removing IRQs numbers to/from the MSI irqdomain they belong to.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/kernel/apic/io_apic.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 9ed796c..65db413 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -60,6 +60,7 @@
 #include <asm/irq_remapping.h>
 #include <asm/hpet.h>
 #include <asm/hw_irq.h>
+#include <asm/prom.h>
 
 #include <asm/apic.h>
 
@@ -3154,6 +3155,9 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 		ret = setup_msi_irq(dev, msidesc, irq, 0);
 		if (ret < 0)
 			goto error;
+		ret = x86_of_new_msi_irq(dev, irq);
+		if (ret < 0)
+			goto error;
 	}
 	return 0;
 
@@ -3164,6 +3168,7 @@ error:
 
 void native_teardown_msi_irq(unsigned int irq)
 {
+	x86_of_del_msi_irq(irq);
 	destroy_irq(irq);
 }
 
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 13/26] drivers/amba/pci-amba.c: use devicetree for amba device creation.
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (11 preceding siblings ...)
  2013-08-07 10:19 ` [PATCH 12/26] x86 kernel apic: notify MSI irqdomain(s) on etup/teardown of MSI IRQs Davide Ciminaghi
@ 2013-08-07 10:19 ` Davide Ciminaghi
  2013-08-07 10:19 ` [PATCH 14/26] gpio: remove sta2x11-gpio Davide Ciminaghi
                   ` (14 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:19 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

The following scheme applies for each pci-amba device within the
devicetree:

	* sta2x11 pci express port (pci id = 0xcc17)
	  |
	  |
	  * pci-amba bridge node (pci id = 0xcc18)
	    |
	    +-------+
	    |	    |
	    |	    * amba-bus node (ranges, interrupt-map)
	    |	      |
	    |	      ...
	    ...	      |
	    |	      * amba side of pci-amba device
	    |
	    |
	    * pci side of pci-amba device

As far as the sta2x11 is concerned, there are 4 pci-amba bridge nodes (one
for each pci express endpoint).
A pci-amba bridge node contains an amba bus and all the pci side parts of
the pci-amba devices attached to the same pci express endpoint.
Finally, each child node of the amba bus represents the amba side of a
pci-amba device.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 drivers/amba/pci-amba.c |  126 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 109 insertions(+), 17 deletions(-)

diff --git a/drivers/amba/pci-amba.c b/drivers/amba/pci-amba.c
index 8ce526a..e56717b 100644
--- a/drivers/amba/pci-amba.c
+++ b/drivers/amba/pci-amba.c
@@ -12,42 +12,134 @@
 #include <linux/slab.h>
 #include <linux/irq.h>
 #include <linux/sizes.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+
+/*
+  Length of an interrupt map row:
+  Child unit address (amba node, length is 1) +
+  Child interrupt specifier (amba node, length is 1) +
+  Interrupt parent (phandle, length is 1) +
+  Parent unit address (parent is msi controller, length is 1)
+  Parent interrupt specifier (parent is msi controller, length is 1)
+*/
+#define IMAP_ROW_LEN (1 + 1 + 1 + 1 + 1)
 
 static int pci_amba_probe(struct pci_dev *pdev,
 			  const struct pci_device_id *id)
 {
 	struct amba_device *adev;
+	int i, ret, len;
+	struct device_node *n, *node, *pci_amba_bridge, *amba_bus = NULL,
+		*amba_node = NULL;
+	const void *p;
 	char *name;
-	int ret;
+	struct property *newimap;
+	u32 *newv, *ptr;
+	const u32 *reg;
+	int found;
 
 	pci_enable_msi(pdev);
 	ret = pci_enable_device(pdev);
 	if (ret)
 		return ret;
 
-	/* Create a name: each of them must be different */
+	/* This bridge can host both APB and AHB devices, so set master */
+	pci_set_master(pdev);
+
+	node = pdev->dev.of_node;
+	if (!node)
+		return -EINVAL;
+
+	/* Get a reference to the pci amba bridge (our pci parent) */
+	pci_amba_bridge = of_get_parent(node);
+	if (!pci_amba_bridge)
+		return -EINVAL;
+	if (of_node_cmp(pci_amba_bridge->type, "pci"))
+		return -EINVAL;
+
+	/* Look for the relevant amba bus node */
+	for_each_child_of_node(pci_amba_bridge, n) {
+		if (of_device_is_compatible(n, "arm,amba-bus")) {
+			amba_bus = n;
+			break;
+		}
+	}
+	of_node_put(pci_amba_bridge);
+	if (!amba_bus)
+		return -ENODEV;
+
+	/*
+	   Now find out what the relevant amba device is by looking for
+	   a resource with the same initial address of this pci device's BAR0
+	*/
+	for_each_child_of_node(amba_bus, n) {
+		struct resource r;
+		if (of_address_to_resource(n, 0, &r))
+			continue;
+		if (r.start == pdev->resource[0].start) {
+			amba_node = n;
+			break;
+		}
+	}
+	if (!amba_node)
+		return -ENODEV;
+
+	/* Create a unique name for the device */
 	name = devm_kzalloc(&pdev->dev, strlen(dev_name(&pdev->dev)) + 6,
-		GFP_KERNEL);
+			    GFP_KERNEL);
 	sprintf(name, "amba-%s", dev_name(&pdev->dev));
 
-	/* Simply build an amba device and register it */
-	adev = amba_device_alloc(name,  pdev->resource[0].start, SZ_4K);
-	if (!adev)
-		return -ENOMEM;
-	adev->irq[0] = pdev->irq;
+	/*
+	  Since we're dealing with MSI IRQs, the value of a device's IRQ
+	  number is known at runtime only. Update the amba bus interrupt
+	  map to fix things up.
+	*/
+	if (of_get_property(amba_node, "interrupts", NULL)) {
+		p = of_get_property(amba_bus, "interrupt-map", &len);
+		if (!p)
+			/* No amba bus interrupt-map property */
+			return -EINVAL;
 
-	/* This bridge can host both APB and AHB devices, so set master */
-	pci_set_master(pdev);
-	if (pdev->vendor == PCI_VENDOR_ID_STMICRO) {
-		/* Under sta2x11, DMA is there but limited to 512M */
-		adev->dma_mask = SZ_512M - 1;
-		adev->dev.coherent_dma_mask = SZ_512M - 1;
+		newimap = devm_kzalloc(&pdev->dev, sizeof(*newimap),
+				       GFP_KERNEL);
+		if (!newimap)
+			return -ENOMEM;
+
+		newimap->name = kstrdup("interrupt-map", GFP_KERNEL);
+		if (!newimap->name)
+			return -ENOMEM;
+
+		newv = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
+		if (!newv) {
+			kfree(newimap->name);
+			return -ENOMEM;
+		}
+
+		newimap->value = newv;
+		newimap->length = len;
+		memcpy(newv, p, len);
+		for (ptr = newv, i = 0, found = 0;
+		     i < len/sizeof(u32);
+		     ptr += IMAP_ROW_LEN, i += IMAP_ROW_LEN) {
+			reg = of_get_property(amba_node, "reg", NULL);
+			if (ptr[0] == reg[0]) {
+				ptr[IMAP_ROW_LEN - 1] = cpu_to_be32(pdev->irq);
+				found = 1;
+				break;
+			}
+		}
+		if (!found) {
+			pr_err("Could not update amba irq\n");
+			return -EINVAL;
+		}
+		of_update_property(amba_bus, newimap);
 	}
 
-	adev->dev.platform_data = pdev->dev.platform_data;
+	/* And finally create the amba device */
+	adev = of_amba_device_create(n, name, NULL, NULL, &pdev->resource[0]);
 	pci_set_drvdata(pdev, adev);
-
-	return amba_device_add(adev, &pdev->resource[0]);
+	return 0;
 };
 
 static void pci_amba_remove(struct pci_dev *pdev)
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 14/26] gpio: remove sta2x11-gpio
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (12 preceding siblings ...)
  2013-08-07 10:19 ` [PATCH 13/26] drivers/amba/pci-amba.c: use devicetree for amba device creation Davide Ciminaghi
@ 2013-08-07 10:19 ` Davide Ciminaghi
  2013-08-07 19:49   ` Linus Walleij
  2013-08-07 10:20 ` [PATCH 15/26] x86 STA2X11: remove the sta2x11-mfd driver Davide Ciminaghi
                   ` (13 subsequent siblings)
  27 siblings, 1 reply; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:19 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree, Linus Walleij

The Connext chip has 4 gpio cells looking very similar to those of the
Nomadik, whose gpio/pinctrl driver (already featuring devicetree support)
will be used instead of the sta2x11 specific one.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 drivers/gpio/Kconfig        |    8 -
 drivers/gpio/Makefile       |    1 -
 drivers/gpio/gpio-sta2x11.c |  440 -------------------------------------------
 3 files changed, 0 insertions(+), 449 deletions(-)
 delete mode 100644 drivers/gpio/gpio-sta2x11.c

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 4b7ba53..c93b13a 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -226,14 +226,6 @@ config GPIO_SPEAR_SPICS
 	help
 	  Say yes here to support ST SPEAr SPI Chip Select as GPIO device
 
-config GPIO_STA2X11
-	bool "STA2x11/ConneXt GPIO support"
-	depends on MFD_STA2X11
-	select GENERIC_IRQ_CHIP
-	help
-	  Say yes here to support the STA2x11/ConneXt GPIO device.
-	  The GPIO module has 128 GPIO pins with alternate functions.
-
 config GPIO_TS5500
 	tristate "TS-5500 DIO blocks and compatibles"
 	help
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 156fd28..62a8b41 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -65,7 +65,6 @@ obj-$(CONFIG_ARCH_SA1100)	+= gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)		+= gpio-sch.o
 obj-$(CONFIG_GPIO_SODAVILLE)	+= gpio-sodaville.o
 obj-$(CONFIG_GPIO_SPEAR_SPICS)	+= gpio-spear-spics.o
-obj-$(CONFIG_GPIO_STA2X11)	+= gpio-sta2x11.o
 obj-$(CONFIG_GPIO_STMPE)	+= gpio-stmpe.o
 obj-$(CONFIG_GPIO_STP_XWAY)	+= gpio-stp-xway.o
 obj-$(CONFIG_GPIO_SX150X)	+= gpio-sx150x.o
diff --git a/drivers/gpio/gpio-sta2x11.c b/drivers/gpio/gpio-sta2x11.c
deleted file mode 100644
index f43ab6a..0000000
--- a/drivers/gpio/gpio-sta2x11.c
+++ /dev/null
@@ -1,440 +0,0 @@
-/*
- * STMicroelectronics ConneXt (STA2X11) GPIO driver
- *
- * Copyright 2012 ST Microelectronics (Alessandro Rubini)
- * Based on gpio-ml-ioh.c, Copyright 2010 OKI Semiconductors Ltd.
- * Also based on previous sta2x11 work, Copyright 2011 Wind River Systems, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/sta2x11-mfd.h>
-
-struct gsta_regs {
-	u32 dat;		/* 0x00 */
-	u32 dats;
-	u32 datc;
-	u32 pdis;
-	u32 dir;		/* 0x10 */
-	u32 dirs;
-	u32 dirc;
-	u32 unused_1c;
-	u32 afsela;		/* 0x20 */
-	u32 unused_24[7];
-	u32 rimsc;		/* 0x40 */
-	u32 fimsc;
-	u32 is;
-	u32 ic;
-};
-
-struct gsta_gpio {
-	spinlock_t			lock;
-	struct device			*dev;
-	void __iomem			*reg_base;
-	struct gsta_regs __iomem	*regs[GSTA_NR_BLOCKS];
-	struct gpio_chip		gpio;
-	int				irq_base;
-	/* FIXME: save the whole config here (AF, ...) */
-	unsigned			irq_type[GSTA_NR_GPIO];
-};
-
-static inline struct gsta_regs __iomem *__regs(struct gsta_gpio *chip, int nr)
-{
-	return chip->regs[nr / GSTA_GPIO_PER_BLOCK];
-}
-
-static inline u32 __bit(int nr)
-{
-	return 1U << (nr % GSTA_GPIO_PER_BLOCK);
-}
-
-/*
- * gpio methods
- */
-
-static void gsta_gpio_set(struct gpio_chip *gpio, unsigned nr, int val)
-{
-	struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
-	struct gsta_regs __iomem *regs = __regs(chip, nr);
-	u32 bit = __bit(nr);
-
-	if (val)
-		writel(bit, &regs->dats);
-	else
-		writel(bit, &regs->datc);
-}
-
-static int gsta_gpio_get(struct gpio_chip *gpio, unsigned nr)
-{
-	struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
-	struct gsta_regs __iomem *regs = __regs(chip, nr);
-	u32 bit = __bit(nr);
-
-	return readl(&regs->dat) & bit;
-}
-
-static int gsta_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
-				      int val)
-{
-	struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
-	struct gsta_regs __iomem *regs = __regs(chip, nr);
-	u32 bit = __bit(nr);
-
-	writel(bit, &regs->dirs);
-	/* Data register after direction, otherwise pullup/down is selected */
-	if (val)
-		writel(bit, &regs->dats);
-	else
-		writel(bit, &regs->datc);
-	return 0;
-}
-
-static int gsta_gpio_direction_input(struct gpio_chip *gpio, unsigned nr)
-{
-	struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
-	struct gsta_regs __iomem *regs = __regs(chip, nr);
-	u32 bit = __bit(nr);
-
-	writel(bit, &regs->dirc);
-	return 0;
-}
-
-static int gsta_gpio_to_irq(struct gpio_chip *gpio, unsigned offset)
-{
-	struct gsta_gpio *chip = container_of(gpio, struct gsta_gpio, gpio);
-	return chip->irq_base + offset;
-}
-
-static void gsta_gpio_setup(struct gsta_gpio *chip) /* called from probe */
-{
-	struct gpio_chip *gpio = &chip->gpio;
-
-	/*
-	 * ARCH_NR_GPIOS is currently 256 and dynamic allocation starts
-	 * from the end. However, for compatibility, we need the first
-	 * ConneXt device to start from gpio 0: it's the main chipset
-	 * on most boards so documents and drivers assume gpio0..gpio127
-	 */
-	static int gpio_base;
-
-	gpio->label = dev_name(chip->dev);
-	gpio->owner = THIS_MODULE;
-	gpio->direction_input = gsta_gpio_direction_input;
-	gpio->get = gsta_gpio_get;
-	gpio->direction_output = gsta_gpio_direction_output;
-	gpio->set = gsta_gpio_set;
-	gpio->dbg_show = NULL;
-	gpio->base = gpio_base;
-	gpio->ngpio = GSTA_NR_GPIO;
-	gpio->can_sleep = 0;
-	gpio->to_irq = gsta_gpio_to_irq;
-
-	/*
-	 * After the first device, turn to dynamic gpio numbers.
-	 * For example, with ARCH_NR_GPIOS = 256 we can fit two cards
-	 */
-	if (!gpio_base)
-		gpio_base = -1;
-}
-
-/*
- * Special method: alternate functions and pullup/pulldown. This is only
- * invoked on startup to configure gpio's according to platform data.
- * FIXME : this functionality shall be managed (and exported to other drivers)
- * via the pin control subsystem.
- */
-static void gsta_set_config(struct gsta_gpio *chip, int nr, unsigned cfg)
-{
-	struct gsta_regs __iomem *regs = __regs(chip, nr);
-	unsigned long flags;
-	u32 bit = __bit(nr);
-	u32 val;
-	int err = 0;
-
-	pr_info("%s: %p %i %i\n", __func__, chip, nr, cfg);
-
-	if (cfg == PINMUX_TYPE_NONE)
-		return;
-
-	/* Alternate function or not? */
-	spin_lock_irqsave(&chip->lock, flags);
-	val = readl(&regs->afsela);
-	if (cfg == PINMUX_TYPE_FUNCTION)
-		val |= bit;
-	else
-		val &= ~bit;
-	writel(val | bit, &regs->afsela);
-	if (cfg == PINMUX_TYPE_FUNCTION) {
-		spin_unlock_irqrestore(&chip->lock, flags);
-		return;
-	}
-
-	/* not alternate function: set details */
-	switch (cfg) {
-	case PINMUX_TYPE_OUTPUT_LOW:
-		writel(bit, &regs->dirs);
-		writel(bit, &regs->datc);
-		break;
-	case PINMUX_TYPE_OUTPUT_HIGH:
-		writel(bit, &regs->dirs);
-		writel(bit, &regs->dats);
-		break;
-	case PINMUX_TYPE_INPUT:
-		writel(bit, &regs->dirc);
-		val = readl(&regs->pdis) | bit;
-		writel(val, &regs->pdis);
-		break;
-	case PINMUX_TYPE_INPUT_PULLUP:
-		writel(bit, &regs->dirc);
-		val = readl(&regs->pdis) & ~bit;
-		writel(val, &regs->pdis);
-		writel(bit, &regs->dats);
-		break;
-	case PINMUX_TYPE_INPUT_PULLDOWN:
-		writel(bit, &regs->dirc);
-		val = readl(&regs->pdis) & ~bit;
-		writel(val, &regs->pdis);
-		writel(bit, &regs->datc);
-		break;
-	default:
-		err = 1;
-	}
-	spin_unlock_irqrestore(&chip->lock, flags);
-	if (err)
-		pr_err("%s: chip %p, pin %i, cfg %i is invalid\n",
-		       __func__, chip, nr, cfg);
-}
-
-/*
- * Irq methods
- */
-
-static void gsta_irq_disable(struct irq_data *data)
-{
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-	struct gsta_gpio *chip = gc->private;
-	int nr = data->irq - chip->irq_base;
-	struct gsta_regs __iomem *regs = __regs(chip, nr);
-	u32 bit = __bit(nr);
-	u32 val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lock, flags);
-	if (chip->irq_type[nr] & IRQ_TYPE_EDGE_RISING) {
-		val = readl(&regs->rimsc) & ~bit;
-		writel(val, &regs->rimsc);
-	}
-	if (chip->irq_type[nr] & IRQ_TYPE_EDGE_FALLING) {
-		val = readl(&regs->fimsc) & ~bit;
-		writel(val, &regs->fimsc);
-	}
-	spin_unlock_irqrestore(&chip->lock, flags);
-	return;
-}
-
-static void gsta_irq_enable(struct irq_data *data)
-{
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-	struct gsta_gpio *chip = gc->private;
-	int nr = data->irq - chip->irq_base;
-	struct gsta_regs __iomem *regs = __regs(chip, nr);
-	u32 bit = __bit(nr);
-	u32 val;
-	int type;
-	unsigned long flags;
-
-	type = chip->irq_type[nr];
-
-	spin_lock_irqsave(&chip->lock, flags);
-	val = readl(&regs->rimsc);
-	if (type & IRQ_TYPE_EDGE_RISING)
-		writel(val | bit, &regs->rimsc);
-	else
-		writel(val & ~bit, &regs->rimsc);
-	val = readl(&regs->rimsc);
-	if (type & IRQ_TYPE_EDGE_FALLING)
-		writel(val | bit, &regs->fimsc);
-	else
-		writel(val & ~bit, &regs->fimsc);
-	spin_unlock_irqrestore(&chip->lock, flags);
-	return;
-}
-
-static int gsta_irq_type(struct irq_data *d, unsigned int type)
-{
-	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-	struct gsta_gpio *chip = gc->private;
-	int nr = d->irq - chip->irq_base;
-
-	/* We only support edge interrupts */
-	if (!(type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))) {
-		pr_debug("%s: unsupported type 0x%x\n", __func__, type);
-		return -EINVAL;
-	}
-
-	chip->irq_type[nr] = type; /* used for enable/disable */
-
-	gsta_irq_enable(d);
-	return 0;
-}
-
-static irqreturn_t gsta_gpio_handler(int irq, void *dev_id)
-{
-	struct gsta_gpio *chip = dev_id;
-	struct gsta_regs __iomem *regs;
-	u32 is;
-	int i, nr, base;
-	irqreturn_t ret = IRQ_NONE;
-
-	for (i = 0; i < GSTA_NR_BLOCKS; i++) {
-		regs = chip->regs[i];
-		base = chip->irq_base + i * GSTA_GPIO_PER_BLOCK;
-		while ((is = readl(&regs->is))) {
-			nr = __ffs(is);
-			irq = base + nr;
-			generic_handle_irq(irq);
-			writel(1 << nr, &regs->ic);
-			ret = IRQ_HANDLED;
-		}
-	}
-	return ret;
-}
-
-static void gsta_alloc_irq_chip(struct gsta_gpio *chip)
-{
-	struct irq_chip_generic *gc;
-	struct irq_chip_type *ct;
-
-	gc = irq_alloc_generic_chip(KBUILD_MODNAME, 1, chip->irq_base,
-				     chip->reg_base, handle_simple_irq);
-	gc->private = chip;
-	ct = gc->chip_types;
-
-	ct->chip.irq_set_type = gsta_irq_type;
-	ct->chip.irq_disable = gsta_irq_disable;
-	ct->chip.irq_enable = gsta_irq_enable;
-
-	/* FIXME: this makes at most 32 interrupts. Request 0 by now */
-	irq_setup_generic_chip(gc, 0 /* IRQ_MSK(GSTA_GPIO_PER_BLOCK) */, 0,
-			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-
-	/* Set up all all 128 interrupts: code from setup_generic_chip */
-	{
-		struct irq_chip_type *ct = gc->chip_types;
-		int i, j;
-		for (j = 0; j < GSTA_NR_GPIO; j++) {
-			i = chip->irq_base + j;
-			irq_set_chip_and_handler(i, &ct->chip, ct->handler);
-			irq_set_chip_data(i, gc);
-			irq_modify_status(i, IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-		}
-		gc->irq_cnt = i - gc->irq_base;
-	}
-}
-
-/* The platform device used here is instantiated by the MFD device */
-static int gsta_probe(struct platform_device *dev)
-{
-	int i, err;
-	struct pci_dev *pdev;
-	struct sta2x11_gpio_pdata *gpio_pdata;
-	struct gsta_gpio *chip;
-	struct resource *res;
-
-	pdev = *(struct pci_dev **)(dev->dev.platform_data);
-	gpio_pdata = dev_get_platdata(&pdev->dev);
-
-	if (gpio_pdata == NULL)
-		dev_err(&dev->dev, "no gpio config\n");
-	pr_debug("gpio config: %p\n", gpio_pdata);
-
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-
-	chip = devm_kzalloc(&dev->dev, sizeof(*chip), GFP_KERNEL);
-	if (!chip)
-		return -ENOMEM;
-	chip->dev = &dev->dev;
-	chip->reg_base = devm_ioremap_resource(&dev->dev, res);
-	if (IS_ERR(chip->reg_base))
-		return PTR_ERR(chip->reg_base);
-
-	for (i = 0; i < GSTA_NR_BLOCKS; i++) {
-		chip->regs[i] = chip->reg_base + i * 4096;
-		/* disable all irqs */
-		writel(0, &chip->regs[i]->rimsc);
-		writel(0, &chip->regs[i]->fimsc);
-		writel(~0, &chip->regs[i]->ic);
-	}
-	spin_lock_init(&chip->lock);
-	gsta_gpio_setup(chip);
-	if (gpio_pdata)
-		for (i = 0; i < GSTA_NR_GPIO; i++)
-			gsta_set_config(chip, i, gpio_pdata->pinconfig[i]);
-
-	/* 384 was used in previous code: be compatible for other drivers */
-	err = irq_alloc_descs(-1, 384, GSTA_NR_GPIO, NUMA_NO_NODE);
-	if (err < 0) {
-		dev_warn(&dev->dev, "sta2x11 gpio: Can't get irq base (%i)\n",
-			 -err);
-		return err;
-	}
-	chip->irq_base = err;
-	gsta_alloc_irq_chip(chip);
-
-	err = request_irq(pdev->irq, gsta_gpio_handler,
-			     IRQF_SHARED, KBUILD_MODNAME, chip);
-	if (err < 0) {
-		dev_err(&dev->dev, "sta2x11 gpio: Can't request irq (%i)\n",
-			-err);
-		goto err_free_descs;
-	}
-
-	err = gpiochip_add(&chip->gpio);
-	if (err < 0) {
-		dev_err(&dev->dev, "sta2x11 gpio: Can't register (%i)\n",
-			-err);
-		goto err_free_irq;
-	}
-
-	platform_set_drvdata(dev, chip);
-	return 0;
-
-err_free_irq:
-	free_irq(pdev->irq, chip);
-err_free_descs:
-	irq_free_descs(chip->irq_base, GSTA_NR_GPIO);
-	return err;
-}
-
-static struct platform_driver sta2x11_gpio_platform_driver = {
-	.driver = {
-		.name	= "sta2x11-gpio",
-		.owner	= THIS_MODULE,
-	},
-	.probe = gsta_probe,
-};
-
-module_platform_driver(sta2x11_gpio_platform_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("sta2x11_gpio GPIO driver");
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 15/26] x86 STA2X11: remove the sta2x11-mfd driver.
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (13 preceding siblings ...)
  2013-08-07 10:19 ` [PATCH 14/26] gpio: remove sta2x11-gpio Davide Ciminaghi
@ 2013-08-07 10:20 ` Davide Ciminaghi
  2013-08-07 10:20 ` [PATCH 16/26] x86 STA2X11 platform: add sta2x11_platform_init() Davide Ciminaghi
                   ` (12 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree, Samuel Ortiz

This patch removes the mfd driver for the Connext chip, the final goal
being to create platform devices through the new OF enabled version of
the pci to amba bridge.
Most of the sta2x11-mfd.h header file is moved to asm/sta2x11.h.
Platform drivers for sctl, scr, apbreg and apb_soc_regs are moved under
arch/x86/platform/sta2x11.c (but the common probe function is empty at
the moment, since we have no struct sta2x11_mfd anymore).
Makefiles and Kconfigs are updated accordingly (note that REGMAP_MMIO is
now selected by CONFIG_STA2X11, not CONFIG_STA2X11_MFD, which does not
exist anymore).

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/Kconfig                    |    1 +
 arch/x86/include/asm/sta2x11.h      |  318 ++++++++++++++++-
 arch/x86/platform/Makefile          |    1 +
 arch/x86/platform/sta2x11/Makefile  |    1 +
 arch/x86/platform/sta2x11/sta2x11.c |  279 ++++++++++++++
 drivers/mfd/Kconfig                 |    6 -
 drivers/mfd/Makefile                |    1 -
 drivers/mfd/sta2x11-mfd.c           |  680 -----------------------------------
 include/linux/mfd/sta2x11-mfd.h     |  518 --------------------------
 9 files changed, 598 insertions(+), 1207 deletions(-)
 create mode 100644 arch/x86/platform/sta2x11/Makefile
 create mode 100644 arch/x86/platform/sta2x11/sta2x11.c
 delete mode 100644 drivers/mfd/sta2x11-mfd.c
 delete mode 100644 include/linux/mfd/sta2x11-mfd.h

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 0a779eb..ae05df92 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -559,6 +559,7 @@ config STA2X11
 	select OF_EARLY_FLATTREE
 	select OF_DYNAMIC
 	select IRQ_DOMAIN
+	select REGMAP_MMIO
 	default n
 	---help---
 	  This adds support for boards based on the STA2X11 IO-Hub,
diff --git a/arch/x86/include/asm/sta2x11.h b/arch/x86/include/asm/sta2x11.h
index e9d32df..cd76923 100644
--- a/arch/x86/include/asm/sta2x11.h
+++ b/arch/x86/include/asm/sta2x11.h
@@ -1,12 +1,326 @@
 /*
  * Header file for STMicroelectronics ConneXt (STA2X11) IOHub
+ * Copyright (c) 2009-2011 Wind River Systems, Inc.
+ * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
  */
 #ifndef __ASM_STA2X11_H
 #define __ASM_STA2X11_H
 
+#include <linux/types.h>
 #include <linux/pci.h>
 
-/* This needs to be called from the MFD to configure its sub-devices */
-struct sta2x11_instance *sta2x11_get_instance(struct pci_dev *pdev);
+enum sta2x11_plat_dev {
+	sta2x11_sctl = 0,
+	sta2x11_gpio,
+	sta2x11_scr,
+	sta2x11_time,
+	sta2x11_apbreg,
+	sta2x11_apb_soc_regs,
+	sta2x11_vic,
+	sta2x11_n_plat_devs,
+};
+
+#define STA2X11_SCTL_NAME		"sta2x11-sctl"
+#define STA2X11_GPIO_NAME		"sta2x11-gpio"
+#define STA2X11_SCR_NAME		"sta2x11-scr"
+#define STA2X11_TIME_NAME		"sta2x11-time"
+#define STA2X11_APBREG_NAME		"sta2x11-apbreg"
+#define STA2X11_APB_SOC_REGS_NAME	"sta2x11-apb-soc-regs"
+#define STA2X11_VIC_NAME		"sta2x11-vic"
+
+/* CAN and MLB */
+#define APBREG_BSR	0x00	/* Bridge Status Reg */
+#define APBREG_PAER	0x08	/* Peripherals Address Error Reg */
+#define APBREG_PWAC	0x20	/* Peripheral Write Access Control reg */
+#define APBREG_PRAC	0x40	/* Peripheral Read Access Control reg */
+#define APBREG_PCG	0x60	/* Peripheral Clock Gating Reg */
+#define APBREG_PUR	0x80	/* Peripheral Under Reset Reg */
+#define APBREG_EMU_PCG	0xA0	/* Emulator Peripheral Clock Gating Reg */
+
+#define APBREG_CAN	(1 << 1)
+#define APBREG_MLB	(1 << 3)
+
+/* SARAC */
+#define APBREG_BSR_SARAC     0x100 /* Bridge Status Reg */
+#define APBREG_PAER_SARAC    0x108 /* Peripherals Address Error Reg */
+#define APBREG_PWAC_SARAC    0x120 /* Peripheral Write Access Control reg */
+#define APBREG_PRAC_SARAC    0x140 /* Peripheral Read Access Control reg */
+#define APBREG_PCG_SARAC     0x160 /* Peripheral Clock Gating Reg */
+#define APBREG_PUR_SARAC     0x180 /* Peripheral Under Reset Reg */
+#define APBREG_EMU_PCG_SARAC 0x1A0 /* Emulator Peripheral Clock Gating Reg */
+
+#define APBREG_SARAC	(1 << 2)
+
+#define SCTL_SCCTL		0x00	/* System controller control register */
+#define SCTL_ARMCFG		0x04	/* ARM configuration register */
+#define SCTL_SCPLLCTL		0x08	/* PLL control status register */
+
+#define SCTL_SCPLLCTL_AUDIO_PLL_PD	     BIT(1)
+#define SCTL_SCPLLCTL_FRAC_CONTROL	     BIT(3)
+#define SCTL_SCPLLCTL_STRB_BYPASS	     BIT(6)
+#define SCTL_SCPLLCTL_STRB_INPUT	     BIT(8)
+
+#define SCTL_SCPLLFCTRL		0x0c	/* PLL frequency control register */
+
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_MASK	0xff
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_SHIFT	  10
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_MASK	   7
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_SHIFT	  21
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_MASK	   7
+#define SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_SHIFT	  18
+#define SCTL_SCPLLFCTRL_DITHER_DISABLE_MASK     0x03
+#define SCTL_SCPLLFCTRL_DITHER_DISABLE_SHIFT       4
+
+
+#define SCTL_SCRESFRACT		0x10	/* PLL fractional input register */
+
+#define SCTL_SCRESFRACT_MASK	0x0000ffff
+
+
+#define SCTL_SCRESCTRL1		0x14	/* Peripheral reset control 1 */
+#define SCTL_SCRESXTRL2		0x18	/* Peripheral reset control 2 */
+#define SCTL_SCPEREN0		0x1c	/* Peripheral clock enable register 0 */
+#define SCTL_SCPEREN1		0x20	/* Peripheral clock enable register 1 */
+#define SCTL_SCPEREN2		0x24	/* Peripheral clock enable register 2 */
+#define SCTL_SCGRST		0x28	/* Peripheral global reset */
+#define SCTL_SCPCIECSBRST	0x2c	/* PCIe PAB CSB reset status register */
+#define SCTL_SCPCIPMCR1		0x30	/* PCI power management control 1 */
+#define SCTL_SCPCIPMCR2		0x34	/* PCI power management control 2 */
+#define SCTL_SCPCIPMSR1		0x38	/* PCI power management status 1 */
+#define SCTL_SCPCIPMSR2		0x3c	/* PCI power management status 2 */
+#define SCTL_SCPCIPMSR3		0x40	/* PCI power management status 3 */
+#define SCTL_SCINTREN		0x44	/* Interrupt enable */
+#define SCTL_SCRISR		0x48	/* RAW interrupt status */
+#define SCTL_SCCLKSTAT0		0x4c	/* Peripheral clocks status 0 */
+#define SCTL_SCCLKSTAT1		0x50	/* Peripheral clocks status 1 */
+#define SCTL_SCCLKSTAT2		0x54	/* Peripheral clocks status 2 */
+#define SCTL_SCRSTSTA		0x58	/* Reset status register */
+
+#define SCTL_SCRESCTRL1_USB_PHY_POR	(1 << 0)
+#define SCTL_SCRESCTRL1_USB_OTG		(1 << 1)
+#define SCTL_SCRESCTRL1_USB_HRST	(1 << 2)
+#define SCTL_SCRESCTRL1_USB_PHY_HOST	(1 << 3)
+#define SCTL_SCRESCTRL1_SATAII		(1 << 4)
+#define SCTL_SCRESCTRL1_VIP		(1 << 5)
+#define SCTL_SCRESCTRL1_PER_MMC0	(1 << 6)
+#define SCTL_SCRESCTRL1_PER_MMC1	(1 << 7)
+#define SCTL_SCRESCTRL1_PER_GPIO0	(1 << 8)
+#define SCTL_SCRESCTRL1_PER_GPIO1	(1 << 9)
+#define SCTL_SCRESCTRL1_PER_GPIO2	(1 << 10)
+#define SCTL_SCRESCTRL1_PER_GPIO3	(1 << 11)
+#define SCTL_SCRESCTRL1_PER_MTU0	(1 << 12)
+#define SCTL_SCRESCTRL1_KER_SPI0	(1 << 13)
+#define SCTL_SCRESCTRL1_KER_SPI1	(1 << 14)
+#define SCTL_SCRESCTRL1_KER_SPI2	(1 << 15)
+#define SCTL_SCRESCTRL1_KER_MCI0	(1 << 16)
+#define SCTL_SCRESCTRL1_KER_MCI1	(1 << 17)
+#define SCTL_SCRESCTRL1_PRE_HSI2C0	(1 << 18)
+#define SCTL_SCRESCTRL1_PER_HSI2C1	(1 << 19)
+#define SCTL_SCRESCTRL1_PER_HSI2C2	(1 << 20)
+#define SCTL_SCRESCTRL1_PER_HSI2C3	(1 << 21)
+#define SCTL_SCRESCTRL1_PER_MSP0	(1 << 22)
+#define SCTL_SCRESCTRL1_PER_MSP1	(1 << 23)
+#define SCTL_SCRESCTRL1_PER_MSP2	(1 << 24)
+#define SCTL_SCRESCTRL1_PER_MSP3	(1 << 25)
+#define SCTL_SCRESCTRL1_PER_MSP4	(1 << 26)
+#define SCTL_SCRESCTRL1_PER_MSP5	(1 << 27)
+#define SCTL_SCRESCTRL1_PER_MMC		(1 << 28)
+#define SCTL_SCRESCTRL1_KER_MSP0	(1 << 29)
+#define SCTL_SCRESCTRL1_KER_MSP1	(1 << 30)
+#define SCTL_SCRESCTRL1_KER_MSP2	(1 << 31)
+
+#define SCTL_SCPEREN0_UART0		(1 << 0)
+#define SCTL_SCPEREN0_UART1		(1 << 1)
+#define SCTL_SCPEREN0_UART2		(1 << 2)
+#define SCTL_SCPEREN0_UART3		(1 << 3)
+#define SCTL_SCPEREN0_MSP0		(1 << 4)
+#define SCTL_SCPEREN0_MSP1		(1 << 5)
+#define SCTL_SCPEREN0_MSP2		(1 << 6)
+#define SCTL_SCPEREN0_MSP3		(1 << 7)
+#define SCTL_SCPEREN0_MSP4		(1 << 8)
+#define SCTL_SCPEREN0_MSP5		(1 << 9)
+#define SCTL_SCPEREN0_SPI0		(1 << 10)
+#define SCTL_SCPEREN0_SPI1		(1 << 11)
+#define SCTL_SCPEREN0_SPI2		(1 << 12)
+#define SCTL_SCPEREN0_I2C0		(1 << 13)
+#define SCTL_SCPEREN0_I2C1		(1 << 14)
+#define SCTL_SCPEREN0_I2C2		(1 << 15)
+#define SCTL_SCPEREN0_I2C3		(1 << 16)
+#define SCTL_SCPEREN0_SVDO_LVDS		(1 << 17)
+#define SCTL_SCPEREN0_USB_HOST		(1 << 18)
+#define SCTL_SCPEREN0_USB_OTG		(1 << 19)
+#define SCTL_SCPEREN0_MCI0		(1 << 20)
+#define SCTL_SCPEREN0_MCI1		(1 << 21)
+#define SCTL_SCPEREN0_MCI2		(1 << 22)
+#define SCTL_SCPEREN0_MCI3		(1 << 23)
+#define SCTL_SCPEREN0_SATA		(1 << 24)
+#define SCTL_SCPEREN0_ETHERNET		(1 << 25)
+#define SCTL_SCPEREN0_VIC		(1 << 26)
+#define SCTL_SCPEREN0_DMA_AUDIO		(1 << 27)
+#define SCTL_SCPEREN0_DMA_SOC		(1 << 28)
+#define SCTL_SCPEREN0_RAM		(1 << 29)
+#define SCTL_SCPEREN0_VIP		(1 << 30)
+#define SCTL_SCPEREN0_ARM		(1 << 31)
+
+#define SCTL_SCPEREN1_UART0		(1 << 0)
+#define SCTL_SCPEREN1_UART1		(1 << 1)
+#define SCTL_SCPEREN1_UART2		(1 << 2)
+#define SCTL_SCPEREN1_UART3		(1 << 3)
+#define SCTL_SCPEREN1_MSP0		(1 << 4)
+#define SCTL_SCPEREN1_MSP1		(1 << 5)
+#define SCTL_SCPEREN1_MSP2		(1 << 6)
+#define SCTL_SCPEREN1_MSP3		(1 << 7)
+#define SCTL_SCPEREN1_MSP4		(1 << 8)
+#define SCTL_SCPEREN1_MSP5		(1 << 9)
+#define SCTL_SCPEREN1_SPI0		(1 << 10)
+#define SCTL_SCPEREN1_SPI1		(1 << 11)
+#define SCTL_SCPEREN1_SPI2		(1 << 12)
+#define SCTL_SCPEREN1_I2C0		(1 << 13)
+#define SCTL_SCPEREN1_I2C1		(1 << 14)
+#define SCTL_SCPEREN1_I2C2		(1 << 15)
+#define SCTL_SCPEREN1_I2C3		(1 << 16)
+#define SCTL_SCPEREN1_USB_PHY		(1 << 17)
+
+#define PCIE_EP1_FUNC3_0_INTR_REG	0x000
+#define PCIE_EP1_FUNC7_4_INTR_REG	0x004
+#define PCIE_EP2_FUNC3_0_INTR_REG	0x008
+#define PCIE_EP2_FUNC7_4_INTR_REG	0x00c
+#define PCIE_EP3_FUNC3_0_INTR_REG	0x010
+#define PCIE_EP3_FUNC7_4_INTR_REG	0x014
+#define PCIE_EP4_FUNC3_0_INTR_REG	0x018
+#define PCIE_EP4_FUNC7_4_INTR_REG	0x01c
+#define PCIE_INTR_ENABLE0_REG		0x020
+#define PCIE_INTR_ENABLE1_REG		0x024
+#define PCIE_EP1_FUNC_TC_REG		0x028
+#define PCIE_EP2_FUNC_TC_REG		0x02c
+#define PCIE_EP3_FUNC_TC_REG		0x030
+#define PCIE_EP4_FUNC_TC_REG		0x034
+#define PCIE_EP1_FUNC_F_REG		0x038
+#define PCIE_EP2_FUNC_F_REG		0x03c
+#define PCIE_EP3_FUNC_F_REG		0x040
+#define PCIE_EP4_FUNC_F_REG		0x044
+#define PCIE_PAB_AMBA_SW_RST_REG	0x048
+#define PCIE_PM_STATUS_0_PORT_0_4	0x04c
+#define PCIE_PM_STATUS_7_0_EP1		0x050
+#define PCIE_PM_STATUS_7_0_EP2		0x054
+#define PCIE_PM_STATUS_7_0_EP3		0x058
+#define PCIE_PM_STATUS_7_0_EP4		0x05c
+#define PCIE_DEV_ID_0_EP1_REG		0x060
+#define PCIE_CC_REV_ID_0_EP1_REG	0x064
+#define PCIE_DEV_ID_1_EP1_REG		0x068
+#define PCIE_CC_REV_ID_1_EP1_REG	0x06c
+#define PCIE_DEV_ID_2_EP1_REG		0x070
+#define PCIE_CC_REV_ID_2_EP1_REG	0x074
+#define PCIE_DEV_ID_3_EP1_REG		0x078
+#define PCIE_CC_REV_ID_3_EP1_REG	0x07c
+#define PCIE_DEV_ID_4_EP1_REG		0x080
+#define PCIE_CC_REV_ID_4_EP1_REG	0x084
+#define PCIE_DEV_ID_5_EP1_REG		0x088
+#define PCIE_CC_REV_ID_5_EP1_REG	0x08c
+#define PCIE_DEV_ID_6_EP1_REG		0x090
+#define PCIE_CC_REV_ID_6_EP1_REG	0x094
+#define PCIE_DEV_ID_7_EP1_REG		0x098
+#define PCIE_CC_REV_ID_7_EP1_REG	0x09c
+#define PCIE_DEV_ID_0_EP2_REG		0x0a0
+#define PCIE_CC_REV_ID_0_EP2_REG	0x0a4
+#define PCIE_DEV_ID_1_EP2_REG		0x0a8
+#define PCIE_CC_REV_ID_1_EP2_REG	0x0ac
+#define PCIE_DEV_ID_2_EP2_REG		0x0b0
+#define PCIE_CC_REV_ID_2_EP2_REG	0x0b4
+#define PCIE_DEV_ID_3_EP2_REG		0x0b8
+#define PCIE_CC_REV_ID_3_EP2_REG	0x0bc
+#define PCIE_DEV_ID_4_EP2_REG		0x0c0
+#define PCIE_CC_REV_ID_4_EP2_REG	0x0c4
+#define PCIE_DEV_ID_5_EP2_REG		0x0c8
+#define PCIE_CC_REV_ID_5_EP2_REG	0x0cc
+#define PCIE_DEV_ID_6_EP2_REG		0x0d0
+#define PCIE_CC_REV_ID_6_EP2_REG	0x0d4
+#define PCIE_DEV_ID_7_EP2_REG		0x0d8
+#define PCIE_CC_REV_ID_7_EP2_REG	0x0dC
+#define PCIE_DEV_ID_0_EP3_REG		0x0e0
+#define PCIE_CC_REV_ID_0_EP3_REG	0x0e4
+#define PCIE_DEV_ID_1_EP3_REG		0x0e8
+#define PCIE_CC_REV_ID_1_EP3_REG	0x0ec
+#define PCIE_DEV_ID_2_EP3_REG		0x0f0
+#define PCIE_CC_REV_ID_2_EP3_REG	0x0f4
+#define PCIE_DEV_ID_3_EP3_REG		0x0f8
+#define PCIE_CC_REV_ID_3_EP3_REG	0x0fc
+#define PCIE_DEV_ID_4_EP3_REG		0x100
+#define PCIE_CC_REV_ID_4_EP3_REG	0x104
+#define PCIE_DEV_ID_5_EP3_REG		0x108
+#define PCIE_CC_REV_ID_5_EP3_REG	0x10c
+#define PCIE_DEV_ID_6_EP3_REG		0x110
+#define PCIE_CC_REV_ID_6_EP3_REG	0x114
+#define PCIE_DEV_ID_7_EP3_REG		0x118
+#define PCIE_CC_REV_ID_7_EP3_REG	0x11c
+#define PCIE_DEV_ID_0_EP4_REG		0x120
+#define PCIE_CC_REV_ID_0_EP4_REG	0x124
+#define PCIE_DEV_ID_1_EP4_REG		0x128
+#define PCIE_CC_REV_ID_1_EP4_REG	0x12c
+#define PCIE_DEV_ID_2_EP4_REG		0x130
+#define PCIE_CC_REV_ID_2_EP4_REG	0x134
+#define PCIE_DEV_ID_3_EP4_REG		0x138
+#define PCIE_CC_REV_ID_3_EP4_REG	0x13c
+#define PCIE_DEV_ID_4_EP4_REG		0x140
+#define PCIE_CC_REV_ID_4_EP4_REG	0x144
+#define PCIE_DEV_ID_5_EP4_REG		0x148
+#define PCIE_CC_REV_ID_5_EP4_REG	0x14c
+#define PCIE_DEV_ID_6_EP4_REG		0x150
+#define PCIE_CC_REV_ID_6_EP4_REG	0x154
+#define PCIE_DEV_ID_7_EP4_REG		0x158
+#define PCIE_CC_REV_ID_7_EP4_REG	0x15c
+#define PCIE_SUBSYS_VEN_ID_REG		0x160
+#define PCIE_COMMON_CLOCK_CONFIG_0_4_0	0x164
+#define PCIE_MIPHYP_SSC_EN_REG		0x168
+#define PCIE_MIPHYP_ADDR_REG		0x16c
+#define PCIE_L1_ASPM_READY_REG		0x170
+#define PCIE_EXT_CFG_RDY_REG		0x174
+#define PCIE_SoC_INT_ROUTER_STATUS0_REG 0x178
+#define PCIE_SoC_INT_ROUTER_STATUS1_REG 0x17c
+#define PCIE_SoC_INT_ROUTER_STATUS2_REG 0x180
+#define PCIE_SoC_INT_ROUTER_STATUS3_REG 0x184
+#define DMA_IP_CTRL_REG			0x324
+#define DISP_BRIDGE_PU_PD_CTRL_REG	0x328
+#define VIP_PU_PD_CTRL_REG		0x32c
+#define USB_MLB_PU_PD_CTRL_REG		0x330
+#define SDIO_PU_PD_MISCFUNC_CTRL_REG1	0x334
+#define SDIO_PU_PD_MISCFUNC_CTRL_REG2	0x338
+#define UART_PU_PD_CTRL_REG		0x33c
+#define ARM_Lock			0x340
+#define SYS_IO_CHAR_REG1		0x344
+#define SYS_IO_CHAR_REG2		0x348
+#define SATA_CORE_ID_REG		0x34c
+#define SATA_CTRL_REG			0x350
+#define I2C_HSFIX_MISC_REG		0x354
+#define SPARE2_RESERVED			0x358
+#define SPARE3_RESERVED			0x35c
+#define MASTER_LOCK_REG			0x368
+#define SYSTEM_CONFIG_STATUS_REG	0x36c
+#define MSP_CLK_CTRL_REG		0x39c
+#define COMPENSATION_REG1		0x3c4
+#define COMPENSATION_REG2		0x3c8
+#define COMPENSATION_REG3		0x3cc
+#define TEST_CTL_REG			0x3d0
+
+/*
+ * SECR (OTP) registers
+ */
+#define STA2X11_SECR_CR			0x00
+#define STA2X11_SECR_FVR0		0x10
+#define STA2X11_SECR_FVR1		0x14
 
 #endif /* __ASM_STA2X11_H */
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile
index 01e0231..28fc10c 100644
--- a/arch/x86/platform/Makefile
+++ b/arch/x86/platform/Makefile
@@ -11,3 +11,4 @@ obj-y	+= sfi/
 obj-y	+= ts5500/
 obj-y	+= visws/
 obj-y	+= uv/
+obj-y	+= sta2x11/
diff --git a/arch/x86/platform/sta2x11/Makefile b/arch/x86/platform/sta2x11/Makefile
new file mode 100644
index 0000000..798c497
--- /dev/null
+++ b/arch/x86/platform/sta2x11/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_STA2X11) = sta2x11.o
diff --git a/arch/x86/platform/sta2x11/sta2x11.c b/arch/x86/platform/sta2x11/sta2x11.c
new file mode 100644
index 0000000..ab3bc62
--- /dev/null
+++ b/arch/x86/platform/sta2x11/sta2x11.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2009-2011 Wind River Systems, Inc.
+ * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <asm/sta2x11.h>
+
+static inline int __reg_within_range(unsigned int r,
+				     unsigned int start,
+				     unsigned int end)
+{
+	return ((r >= start) && (r <= end));
+}
+
+/*
+ * Special sta2x11 regmap lock/unlock functions
+ */
+
+static void sta2x11_regmap_lock(void *__lock)
+{
+	spinlock_t *lock = __lock;
+	spin_lock(lock);
+}
+
+static void sta2x11_regmap_unlock(void *__lock)
+{
+	spinlock_t *lock = __lock;
+	spin_unlock(lock);
+}
+
+/* OTP (one time programmable registers do not require locking */
+static void sta2x11_regmap_nolock(void *__lock)
+{
+}
+
+static bool sta2x11_sctl_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return !__reg_within_range(reg, SCTL_SCPCIECSBRST, SCTL_SCRSTSTA);
+}
+
+static struct regmap_config sta2x11_sctl_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.lock = sta2x11_regmap_lock,
+	.unlock = sta2x11_regmap_unlock,
+	.max_register = SCTL_SCRSTSTA,
+	.writeable_reg = sta2x11_sctl_writeable_reg,
+};
+
+static bool sta2x11_scr_readable_reg(struct device *dev, unsigned int reg)
+{
+	return (reg == STA2X11_SECR_CR) ||
+		__reg_within_range(reg, STA2X11_SECR_FVR0, STA2X11_SECR_FVR1);
+}
+
+static bool sta2x11_scr_writeable_reg(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+static struct regmap_config sta2x11_scr_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.lock = sta2x11_regmap_nolock,
+	.unlock = sta2x11_regmap_nolock,
+	.max_register = STA2X11_SECR_FVR1,
+	.readable_reg = sta2x11_scr_readable_reg,
+	.writeable_reg = sta2x11_scr_writeable_reg,
+};
+
+static bool sta2x11_apbreg_readable_reg(struct device *dev, unsigned int reg)
+{
+	/* Two blocks (CAN and MLB, SARAC) 0x100 bytes apart */
+	if (reg >= APBREG_BSR_SARAC)
+		reg -= APBREG_BSR_SARAC;
+	switch (reg) {
+	case APBREG_BSR:
+	case APBREG_PAER:
+	case APBREG_PWAC:
+	case APBREG_PRAC:
+	case APBREG_PCG:
+	case APBREG_PUR:
+	case APBREG_EMU_PCG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool sta2x11_apbreg_writeable_reg(struct device *dev, unsigned int reg)
+{
+	if (reg >= APBREG_BSR_SARAC)
+		reg -= APBREG_BSR_SARAC;
+	if (!sta2x11_apbreg_readable_reg(dev, reg))
+		return false;
+	return reg != APBREG_PAER;
+}
+
+static struct regmap_config sta2x11_apbreg_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.lock = sta2x11_regmap_lock,
+	.unlock = sta2x11_regmap_unlock,
+	.max_register = APBREG_EMU_PCG_SARAC,
+	.readable_reg = sta2x11_apbreg_readable_reg,
+	.writeable_reg = sta2x11_apbreg_writeable_reg,
+};
+
+static bool sta2x11_apb_soc_regs_readable_reg(struct device *dev,
+					      unsigned int reg)
+{
+	return reg <= PCIE_SoC_INT_ROUTER_STATUS3_REG ||
+		__reg_within_range(reg, DMA_IP_CTRL_REG, SPARE3_RESERVED) ||
+		__reg_within_range(reg, MASTER_LOCK_REG,
+				   SYSTEM_CONFIG_STATUS_REG) ||
+		reg == MSP_CLK_CTRL_REG ||
+		__reg_within_range(reg, COMPENSATION_REG1, TEST_CTL_REG);
+}
+
+static bool sta2x11_apb_soc_regs_writeable_reg(struct device *dev,
+					       unsigned int reg)
+{
+	if (!sta2x11_apb_soc_regs_readable_reg(dev, reg))
+		return false;
+	switch (reg) {
+	case PCIE_COMMON_CLOCK_CONFIG_0_4_0:
+	case SYSTEM_CONFIG_STATUS_REG:
+	case COMPENSATION_REG1:
+	case PCIE_SoC_INT_ROUTER_STATUS0_REG...PCIE_SoC_INT_ROUTER_STATUS3_REG:
+	case PCIE_PM_STATUS_0_PORT_0_4...PCIE_PM_STATUS_7_0_EP4:
+		return false;
+	default:
+		return true;
+	}
+}
+
+static struct regmap_config sta2x11_apb_soc_regs_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.lock = sta2x11_regmap_lock,
+	.unlock = sta2x11_regmap_unlock,
+	.max_register = TEST_CTL_REG,
+	.readable_reg = sta2x11_apb_soc_regs_readable_reg,
+	.writeable_reg = sta2x11_apb_soc_regs_writeable_reg,
+};
+
+static struct regmap_config *
+sta2x11_platform_regmap_configs[sta2x11_n_plat_devs] = {
+	[sta2x11_sctl] = &sta2x11_sctl_regmap_config,
+	[sta2x11_apbreg] = &sta2x11_apbreg_regmap_config,
+	[sta2x11_apb_soc_regs] = &sta2x11_apb_soc_regs_regmap_config,
+	[sta2x11_scr] = &sta2x11_scr_regmap_config,
+};
+
+/* Probe for the four platform devices */
+
+static int sta2x11_platform_probe(struct platform_device *dev,
+				  enum sta2x11_plat_dev index)
+{
+	return -EINVAL;
+}
+
+static int sta2x11_sctl_probe(struct platform_device *dev)
+{
+	return sta2x11_platform_probe(dev, sta2x11_sctl);
+}
+
+static int sta2x11_apbreg_probe(struct platform_device *dev)
+{
+	return sta2x11_platform_probe(dev, sta2x11_apbreg);
+}
+
+static int sta2x11_apb_soc_regs_probe(struct platform_device *dev)
+{
+	return sta2x11_platform_probe(dev, sta2x11_apb_soc_regs);
+}
+
+static int sta2x11_scr_probe(struct platform_device *dev)
+{
+	return sta2x11_platform_probe(dev, sta2x11_scr);
+}
+
+/* The three platform drivers */
+static struct platform_driver sta2x11_sctl_platform_driver = {
+	.driver = {
+		.name	= STA2X11_SCTL_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sta2x11_sctl_probe,
+};
+
+static int __init sta2x11_sctl_init(void)
+{
+	pr_info("%s\n", __func__);
+	return platform_driver_register(&sta2x11_sctl_platform_driver);
+}
+
+static struct platform_driver sta2x11_platform_driver = {
+	.driver = {
+		.name	= STA2X11_APBREG_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sta2x11_apbreg_probe,
+};
+
+static int __init sta2x11_apbreg_init(void)
+{
+	pr_info("%s\n", __func__);
+	return platform_driver_register(&sta2x11_platform_driver);
+}
+
+static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
+	.driver = {
+		.name	= STA2X11_APB_SOC_REGS_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sta2x11_apb_soc_regs_probe,
+};
+
+static int __init sta2x11_apb_soc_regs_init(void)
+{
+	pr_info("%s\n", __func__);
+	return platform_driver_register(&sta2x11_apb_soc_regs_platform_driver);
+}
+
+static struct platform_driver sta2x11_scr_platform_driver = {
+	.driver = {
+		.name = STA2X11_SCR_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = sta2x11_scr_probe,
+};
+
+static int __init sta2x11_scr_init(void)
+{
+	pr_info("%s\n", __func__);
+	return platform_driver_register(&sta2x11_scr_platform_driver);
+}
+
+subsys_initcall(sta2x11_apbreg_init);
+subsys_initcall(sta2x11_sctl_init);
+subsys_initcall(sta2x11_apb_soc_regs_init);
+subsys_initcall(sta2x11_scr_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Wind River");
+MODULE_DESCRIPTION("STA2x11 platform drivers");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 633ee43..372d221 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -666,12 +666,6 @@ config STMPE_SPI
 	  This is used to enable SPI interface of STMPE
 endmenu
 
-config MFD_STA2X11
-	bool "STMicroelectronics STA2X11"
-	depends on STA2X11 && GENERIC_HARDIRQS
-	select MFD_CORE
-	select REGMAP_MMIO
-
 config MFD_SYSCON
 	bool "System Controller Register R/W Based on Regmap"
 	select REGMAP_MMIO
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 3c90051..4819411 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -24,7 +24,6 @@ obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
 obj-$(CONFIG_MFD_TI_SSP)	+= ti-ssp.o
 obj-$(CONFIG_MFD_TI_AM335X_TSCADC)	+= ti_am335x_tscadc.o
 
-obj-$(CONFIG_MFD_STA2X11)	+= sta2x11-mfd.o
 obj-$(CONFIG_MFD_STMPE)		+= stmpe.o
 obj-$(CONFIG_STMPE_I2C)		+= stmpe-i2c.o
 obj-$(CONFIG_STMPE_SPI)		+= stmpe-spi.o
diff --git a/drivers/mfd/sta2x11-mfd.c b/drivers/mfd/sta2x11-mfd.c
deleted file mode 100644
index 65c6fa6..0000000
--- a/drivers/mfd/sta2x11-mfd.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/*
- * Copyright (c) 2009-2011 Wind River Systems, Inc.
- * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/seq_file.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/sta2x11-mfd.h>
-#include <linux/regmap.h>
-
-#include <asm/sta2x11.h>
-
-static inline int __reg_within_range(unsigned int r,
-				     unsigned int start,
-				     unsigned int end)
-{
-	return ((r >= start) && (r <= end));
-}
-
-/* This describes STA2X11 MFD chip for us, we may have several */
-struct sta2x11_mfd {
-	struct sta2x11_instance *instance;
-	struct regmap *regmap[sta2x11_n_mfd_plat_devs];
-	spinlock_t lock[sta2x11_n_mfd_plat_devs];
-	struct list_head list;
-	void __iomem *regs[sta2x11_n_mfd_plat_devs];
-};
-
-static LIST_HEAD(sta2x11_mfd_list);
-
-/* Three functions to act on the list */
-static struct sta2x11_mfd *sta2x11_mfd_find(struct pci_dev *pdev)
-{
-	struct sta2x11_instance *instance;
-	struct sta2x11_mfd *mfd;
-
-	if (!pdev && !list_empty(&sta2x11_mfd_list)) {
-		pr_warning("%s: Unspecified device, "
-			    "using first instance\n", __func__);
-		return list_entry(sta2x11_mfd_list.next,
-				  struct sta2x11_mfd, list);
-	}
-
-	instance = sta2x11_get_instance(pdev);
-	if (!instance)
-		return NULL;
-	list_for_each_entry(mfd, &sta2x11_mfd_list, list) {
-		if (mfd->instance == instance)
-			return mfd;
-	}
-	return NULL;
-}
-
-static int sta2x11_mfd_add(struct pci_dev *pdev, gfp_t flags)
-{
-	int i;
-	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
-	struct sta2x11_instance *instance;
-
-	if (mfd)
-		return -EBUSY;
-	instance = sta2x11_get_instance(pdev);
-	if (!instance)
-		return -EINVAL;
-	mfd = kzalloc(sizeof(*mfd), flags);
-	if (!mfd)
-		return -ENOMEM;
-	INIT_LIST_HEAD(&mfd->list);
-	for (i = 0; i < ARRAY_SIZE(mfd->lock); i++)
-		spin_lock_init(&mfd->lock[i]);
-	mfd->instance = instance;
-	list_add(&mfd->list, &sta2x11_mfd_list);
-	return 0;
-}
-
-/* This function is exported and is not expected to fail */
-u32 __sta2x11_mfd_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val,
-		       enum sta2x11_mfd_plat_dev index)
-{
-	struct sta2x11_mfd *mfd = sta2x11_mfd_find(pdev);
-	u32 r;
-	unsigned long flags;
-	void __iomem *regs;
-
-	if (!mfd) {
-		dev_warn(&pdev->dev, ": can't access sctl regs\n");
-		return 0;
-	}
-
-	regs = mfd->regs[index];
-	if (!regs) {
-		dev_warn(&pdev->dev, ": system ctl not initialized\n");
-		return 0;
-	}
-	spin_lock_irqsave(&mfd->lock[index], flags);
-	r = readl(regs + reg);
-	r &= ~mask;
-	r |= val;
-	if (mask)
-		writel(r, regs + reg);
-	spin_unlock_irqrestore(&mfd->lock[index], flags);
-	return r;
-}
-EXPORT_SYMBOL(__sta2x11_mfd_mask);
-
-int sta2x11_mfd_get_regs_data(struct platform_device *dev,
-			      enum sta2x11_mfd_plat_dev index,
-			      void __iomem **regs,
-			      spinlock_t **lock)
-{
-	struct pci_dev *pdev = *(struct pci_dev **)dev_get_platdata(&dev->dev);
-	struct sta2x11_mfd *mfd;
-
-	if (!pdev)
-		return -ENODEV;
-	mfd = sta2x11_mfd_find(pdev);
-	if (!mfd)
-		return -ENODEV;
-	if (index >= sta2x11_n_mfd_plat_devs)
-		return -ENODEV;
-	*regs = mfd->regs[index];
-	*lock = &mfd->lock[index];
-	pr_debug("%s %d *regs = %p\n", __func__, __LINE__, *regs);
-	return *regs ? 0 : -ENODEV;
-}
-EXPORT_SYMBOL(sta2x11_mfd_get_regs_data);
-
-/*
- * Special sta2x11-mfd regmap lock/unlock functions
- */
-
-static void sta2x11_regmap_lock(void *__lock)
-{
-	spinlock_t *lock = __lock;
-	spin_lock(lock);
-}
-
-static void sta2x11_regmap_unlock(void *__lock)
-{
-	spinlock_t *lock = __lock;
-	spin_unlock(lock);
-}
-
-/* OTP (one time programmable registers do not require locking */
-static void sta2x11_regmap_nolock(void *__lock)
-{
-}
-
-static const char *sta2x11_mfd_names[sta2x11_n_mfd_plat_devs] = {
-	[sta2x11_sctl] = STA2X11_MFD_SCTL_NAME,
-	[sta2x11_apbreg] = STA2X11_MFD_APBREG_NAME,
-	[sta2x11_apb_soc_regs] = STA2X11_MFD_APB_SOC_REGS_NAME,
-	[sta2x11_scr] = STA2X11_MFD_SCR_NAME,
-};
-
-static bool sta2x11_sctl_writeable_reg(struct device *dev, unsigned int reg)
-{
-	return !__reg_within_range(reg, SCTL_SCPCIECSBRST, SCTL_SCRSTSTA);
-}
-
-static struct regmap_config sta2x11_sctl_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-	.lock = sta2x11_regmap_lock,
-	.unlock = sta2x11_regmap_unlock,
-	.max_register = SCTL_SCRSTSTA,
-	.writeable_reg = sta2x11_sctl_writeable_reg,
-};
-
-static bool sta2x11_scr_readable_reg(struct device *dev, unsigned int reg)
-{
-	return (reg == STA2X11_SECR_CR) ||
-		__reg_within_range(reg, STA2X11_SECR_FVR0, STA2X11_SECR_FVR1);
-}
-
-static bool sta2x11_scr_writeable_reg(struct device *dev, unsigned int reg)
-{
-	return false;
-}
-
-static struct regmap_config sta2x11_scr_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-	.lock = sta2x11_regmap_nolock,
-	.unlock = sta2x11_regmap_nolock,
-	.max_register = STA2X11_SECR_FVR1,
-	.readable_reg = sta2x11_scr_readable_reg,
-	.writeable_reg = sta2x11_scr_writeable_reg,
-};
-
-static bool sta2x11_apbreg_readable_reg(struct device *dev, unsigned int reg)
-{
-	/* Two blocks (CAN and MLB, SARAC) 0x100 bytes apart */
-	if (reg >= APBREG_BSR_SARAC)
-		reg -= APBREG_BSR_SARAC;
-	switch (reg) {
-	case APBREG_BSR:
-	case APBREG_PAER:
-	case APBREG_PWAC:
-	case APBREG_PRAC:
-	case APBREG_PCG:
-	case APBREG_PUR:
-	case APBREG_EMU_PCG:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static bool sta2x11_apbreg_writeable_reg(struct device *dev, unsigned int reg)
-{
-	if (reg >= APBREG_BSR_SARAC)
-		reg -= APBREG_BSR_SARAC;
-	if (!sta2x11_apbreg_readable_reg(dev, reg))
-		return false;
-	return reg != APBREG_PAER;
-}
-
-static struct regmap_config sta2x11_apbreg_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-	.lock = sta2x11_regmap_lock,
-	.unlock = sta2x11_regmap_unlock,
-	.max_register = APBREG_EMU_PCG_SARAC,
-	.readable_reg = sta2x11_apbreg_readable_reg,
-	.writeable_reg = sta2x11_apbreg_writeable_reg,
-};
-
-static bool sta2x11_apb_soc_regs_readable_reg(struct device *dev,
-					      unsigned int reg)
-{
-	return reg <= PCIE_SoC_INT_ROUTER_STATUS3_REG ||
-		__reg_within_range(reg, DMA_IP_CTRL_REG, SPARE3_RESERVED) ||
-		__reg_within_range(reg, MASTER_LOCK_REG,
-				   SYSTEM_CONFIG_STATUS_REG) ||
-		reg == MSP_CLK_CTRL_REG ||
-		__reg_within_range(reg, COMPENSATION_REG1, TEST_CTL_REG);
-}
-
-static bool sta2x11_apb_soc_regs_writeable_reg(struct device *dev,
-					       unsigned int reg)
-{
-	if (!sta2x11_apb_soc_regs_readable_reg(dev, reg))
-		return false;
-	switch (reg) {
-	case PCIE_COMMON_CLOCK_CONFIG_0_4_0:
-	case SYSTEM_CONFIG_STATUS_REG:
-	case COMPENSATION_REG1:
-	case PCIE_SoC_INT_ROUTER_STATUS0_REG...PCIE_SoC_INT_ROUTER_STATUS3_REG:
-	case PCIE_PM_STATUS_0_PORT_0_4...PCIE_PM_STATUS_7_0_EP4:
-		return false;
-	default:
-		return true;
-	}
-}
-
-static struct regmap_config sta2x11_apb_soc_regs_regmap_config = {
-	.reg_bits = 32,
-	.reg_stride = 4,
-	.val_bits = 32,
-	.lock = sta2x11_regmap_lock,
-	.unlock = sta2x11_regmap_unlock,
-	.max_register = TEST_CTL_REG,
-	.readable_reg = sta2x11_apb_soc_regs_readable_reg,
-	.writeable_reg = sta2x11_apb_soc_regs_writeable_reg,
-};
-
-static struct regmap_config *
-sta2x11_mfd_regmap_configs[sta2x11_n_mfd_plat_devs] = {
-	[sta2x11_sctl] = &sta2x11_sctl_regmap_config,
-	[sta2x11_apbreg] = &sta2x11_apbreg_regmap_config,
-	[sta2x11_apb_soc_regs] = &sta2x11_apb_soc_regs_regmap_config,
-	[sta2x11_scr] = &sta2x11_scr_regmap_config,
-};
-
-/* Probe for the four platform devices */
-
-static int sta2x11_mfd_platform_probe(struct platform_device *dev,
-				      enum sta2x11_mfd_plat_dev index)
-{
-	struct pci_dev **pdev;
-	struct sta2x11_mfd *mfd;
-	struct resource *res;
-	const char *name = sta2x11_mfd_names[index];
-	struct regmap_config *regmap_config = sta2x11_mfd_regmap_configs[index];
-
-	pdev = dev_get_platdata(&dev->dev);
-	mfd = sta2x11_mfd_find(*pdev);
-	if (!mfd)
-		return -ENODEV;
-	if (!regmap_config)
-		return -ENODEV;
-
-	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENOMEM;
-
-	if (!request_mem_region(res->start, resource_size(res), name))
-		return -EBUSY;
-
-	mfd->regs[index] = ioremap(res->start, resource_size(res));
-	if (!mfd->regs[index]) {
-		release_mem_region(res->start, resource_size(res));
-		return -ENOMEM;
-	}
-	regmap_config->lock_arg = &mfd->lock;
-	/*
-	   No caching, registers could be reached both via regmap and via
-	   void __iomem *
-	*/
-	regmap_config->cache_type = REGCACHE_NONE;
-	mfd->regmap[index] = devm_regmap_init_mmio(&dev->dev, mfd->regs[index],
-						   regmap_config);
-	WARN_ON(!mfd->regmap[index]);
-
-	return 0;
-}
-
-static int sta2x11_sctl_probe(struct platform_device *dev)
-{
-	return sta2x11_mfd_platform_probe(dev, sta2x11_sctl);
-}
-
-static int sta2x11_apbreg_probe(struct platform_device *dev)
-{
-	return sta2x11_mfd_platform_probe(dev, sta2x11_apbreg);
-}
-
-static int sta2x11_apb_soc_regs_probe(struct platform_device *dev)
-{
-	return sta2x11_mfd_platform_probe(dev, sta2x11_apb_soc_regs);
-}
-
-static int sta2x11_scr_probe(struct platform_device *dev)
-{
-	return sta2x11_mfd_platform_probe(dev, sta2x11_scr);
-}
-
-/* The three platform drivers */
-static struct platform_driver sta2x11_sctl_platform_driver = {
-	.driver = {
-		.name	= STA2X11_MFD_SCTL_NAME,
-		.owner	= THIS_MODULE,
-	},
-	.probe		= sta2x11_sctl_probe,
-};
-
-static int __init sta2x11_sctl_init(void)
-{
-	pr_info("%s\n", __func__);
-	return platform_driver_register(&sta2x11_sctl_platform_driver);
-}
-
-static struct platform_driver sta2x11_platform_driver = {
-	.driver = {
-		.name	= STA2X11_MFD_APBREG_NAME,
-		.owner	= THIS_MODULE,
-	},
-	.probe		= sta2x11_apbreg_probe,
-};
-
-static int __init sta2x11_apbreg_init(void)
-{
-	pr_info("%s\n", __func__);
-	return platform_driver_register(&sta2x11_platform_driver);
-}
-
-static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
-	.driver = {
-		.name	= STA2X11_MFD_APB_SOC_REGS_NAME,
-		.owner	= THIS_MODULE,
-	},
-	.probe		= sta2x11_apb_soc_regs_probe,
-};
-
-static int __init sta2x11_apb_soc_regs_init(void)
-{
-	pr_info("%s\n", __func__);
-	return platform_driver_register(&sta2x11_apb_soc_regs_platform_driver);
-}
-
-static struct platform_driver sta2x11_scr_platform_driver = {
-	.driver = {
-		.name = STA2X11_MFD_SCR_NAME,
-		.owner = THIS_MODULE,
-	},
-	.probe = sta2x11_scr_probe,
-};
-
-static int __init sta2x11_scr_init(void)
-{
-	pr_info("%s\n", __func__);
-	return platform_driver_register(&sta2x11_scr_platform_driver);
-}
-
-
-/*
- * What follows are the PCI devices that host the above pdevs.
- * Each logic block is 4kB and they are all consecutive: we use this info.
- */
-
-/* Mfd 0 device */
-
-/* Mfd 0, Bar 0 */
-enum mfd0_bar0_cells {
-	STA2X11_GPIO_0 = 0,
-	STA2X11_GPIO_1,
-	STA2X11_GPIO_2,
-	STA2X11_GPIO_3,
-	STA2X11_SCTL,
-	STA2X11_SCR,
-	STA2X11_TIME,
-};
-/* Mfd 0 , Bar 1 */
-enum mfd0_bar1_cells {
-	STA2X11_APBREG = 0,
-};
-#define CELL_4K(_name, _cell) { \
-		.name = _name, \
-		.start = _cell * 4096, .end = _cell * 4096 + 4095, \
-		.flags = IORESOURCE_MEM, \
-		}
-
-static const struct resource gpio_resources[] = {
-	{
-		/* 4 consecutive cells, 1 driver */
-		.name = STA2X11_MFD_GPIO_NAME,
-		.start = 0,
-		.end = (4 * 4096) - 1,
-		.flags = IORESOURCE_MEM,
-	}
-};
-static const struct resource sctl_resources[] = {
-	CELL_4K(STA2X11_MFD_SCTL_NAME, STA2X11_SCTL),
-};
-static const struct resource scr_resources[] = {
-	CELL_4K(STA2X11_MFD_SCR_NAME, STA2X11_SCR),
-};
-static const struct resource time_resources[] = {
-	CELL_4K(STA2X11_MFD_TIME_NAME, STA2X11_TIME),
-};
-
-static const struct resource apbreg_resources[] = {
-	CELL_4K(STA2X11_MFD_APBREG_NAME, STA2X11_APBREG),
-};
-
-#define DEV(_name, _r) \
-	{ .name = _name, .num_resources = ARRAY_SIZE(_r), .resources = _r, }
-
-static struct mfd_cell sta2x11_mfd0_bar0[] = {
-	/* offset 0: we add pdata later */
-	DEV(STA2X11_MFD_GPIO_NAME, gpio_resources),
-	DEV(STA2X11_MFD_SCTL_NAME, sctl_resources),
-	DEV(STA2X11_MFD_SCR_NAME,  scr_resources),
-	DEV(STA2X11_MFD_TIME_NAME, time_resources),
-};
-
-static struct mfd_cell sta2x11_mfd0_bar1[] = {
-	DEV(STA2X11_MFD_APBREG_NAME, apbreg_resources),
-};
-
-/* Mfd 1 devices */
-
-/* Mfd 1, Bar 0 */
-enum mfd1_bar0_cells {
-	STA2X11_VIC = 0,
-};
-
-/* Mfd 1, Bar 1 */
-enum mfd1_bar1_cells {
-	STA2X11_APB_SOC_REGS = 0,
-};
-
-static const struct resource vic_resources[] = {
-	CELL_4K(STA2X11_MFD_VIC_NAME, STA2X11_VIC),
-};
-
-static const struct resource apb_soc_regs_resources[] = {
-	CELL_4K(STA2X11_MFD_APB_SOC_REGS_NAME, STA2X11_APB_SOC_REGS),
-};
-
-static struct mfd_cell sta2x11_mfd1_bar0[] = {
-	DEV(STA2X11_MFD_VIC_NAME, vic_resources),
-};
-
-static struct mfd_cell sta2x11_mfd1_bar1[] = {
-	DEV(STA2X11_MFD_APB_SOC_REGS_NAME, apb_soc_regs_resources),
-};
-
-
-static int sta2x11_mfd_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
-	return 0;
-}
-
-static int sta2x11_mfd_resume(struct pci_dev *pdev)
-{
-	int err;
-
-	pci_set_power_state(pdev, 0);
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
-	pci_restore_state(pdev);
-
-	return 0;
-}
-
-struct sta2x11_mfd_bar_setup_data {
-	struct mfd_cell *cells;
-	int ncells;
-};
-
-struct sta2x11_mfd_setup_data {
-	struct sta2x11_mfd_bar_setup_data bars[2];
-};
-
-#define STA2X11_MFD0 0
-#define STA2X11_MFD1 1
-
-static struct sta2x11_mfd_setup_data mfd_setup_data[] = {
-	/* Mfd 0: gpio, sctl, scr, timers / apbregs */
-	[STA2X11_MFD0] = {
-		.bars = {
-			[0] = {
-				.cells = sta2x11_mfd0_bar0,
-				.ncells = ARRAY_SIZE(sta2x11_mfd0_bar0),
-			},
-			[1] = {
-				.cells = sta2x11_mfd0_bar1,
-				.ncells = ARRAY_SIZE(sta2x11_mfd0_bar1),
-			},
-		},
-	},
-	/* Mfd 1: vic / apb-soc-regs */
-	[STA2X11_MFD1] = {
-		.bars = {
-			[0] = {
-				.cells = sta2x11_mfd1_bar0,
-				.ncells = ARRAY_SIZE(sta2x11_mfd1_bar0),
-			},
-			[1] = {
-				.cells = sta2x11_mfd1_bar1,
-				.ncells = ARRAY_SIZE(sta2x11_mfd1_bar1),
-			},
-		},
-	},
-};
-
-static void sta2x11_mfd_setup(struct pci_dev *pdev,
-			      struct sta2x11_mfd_setup_data *sd)
-{
-	int i, j;
-	for (i = 0; i < ARRAY_SIZE(sd->bars); i++)
-		for (j = 0; j < sd->bars[i].ncells; j++) {
-			sd->bars[i].cells[j].pdata_size = sizeof(pdev);
-			sd->bars[i].cells[j].platform_data = &pdev;
-		}
-}
-
-static int sta2x11_mfd_probe(struct pci_dev *pdev,
-			     const struct pci_device_id *pci_id)
-{
-	int err, i;
-	struct sta2x11_mfd_setup_data *setup_data;
-
-	dev_info(&pdev->dev, "%s\n", __func__);
-
-	err = pci_enable_device(pdev);
-	if (err) {
-		dev_err(&pdev->dev, "Can't enable device.\n");
-		return err;
-	}
-
-	err = pci_enable_msi(pdev);
-	if (err)
-		dev_info(&pdev->dev, "Enable msi failed\n");
-
-	setup_data = pci_id->device == PCI_DEVICE_ID_STMICRO_GPIO ?
-		&mfd_setup_data[STA2X11_MFD0] :
-		&mfd_setup_data[STA2X11_MFD1];
-
-	/* platform data is the pci device for all of them */
-	sta2x11_mfd_setup(pdev, setup_data);
-
-	/* Record this pdev before mfd_add_devices: their probe looks for it */
-	if (!sta2x11_mfd_find(pdev))
-		sta2x11_mfd_add(pdev, GFP_ATOMIC);
-
-	/* Just 2 bars for all mfd's at present */
-	for (i = 0; i < 2; i++) {
-		err = mfd_add_devices(&pdev->dev, -1,
-				      setup_data->bars[i].cells,
-				      setup_data->bars[i].ncells,
-				      &pdev->resource[i],
-				      0, NULL);
-		if (err) {
-			dev_err(&pdev->dev,
-				"mfd_add_devices[%d] failed: %d\n", i, err);
-			goto err_disable;
-		}
-	}
-
-	return 0;
-
-err_disable:
-	mfd_remove_devices(&pdev->dev);
-	pci_disable_device(pdev);
-	pci_disable_msi(pdev);
-	return err;
-}
-
-static DEFINE_PCI_DEVICE_TABLE(sta2x11_mfd_tbl) = {
-	{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)},
-	{PCI_DEVICE(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_VIC)},
-	{0,},
-};
-
-static struct pci_driver sta2x11_mfd_driver = {
-	.name =		"sta2x11-mfd",
-	.id_table =	sta2x11_mfd_tbl,
-	.probe =	sta2x11_mfd_probe,
-	.suspend =	sta2x11_mfd_suspend,
-	.resume =	sta2x11_mfd_resume,
-};
-
-static int __init sta2x11_mfd_init(void)
-{
-	pr_info("%s\n", __func__);
-	return pci_register_driver(&sta2x11_mfd_driver);
-}
-
-/*
- * All of this must be ready before "normal" devices like MMCI appear.
- * But MFD (the pci device) can't be too early. The following choice
- * prepares platform drivers very early and probe the PCI device later,
- * but before other PCI devices.
- */
-subsys_initcall(sta2x11_apbreg_init);
-subsys_initcall(sta2x11_sctl_init);
-subsys_initcall(sta2x11_apb_soc_regs_init);
-subsys_initcall(sta2x11_scr_init);
-rootfs_initcall(sta2x11_mfd_init);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Wind River");
-MODULE_DESCRIPTION("STA2x11 mfd for GPIO, SCTL and APBREG");
-MODULE_DEVICE_TABLE(pci, sta2x11_mfd_tbl);
diff --git a/include/linux/mfd/sta2x11-mfd.h b/include/linux/mfd/sta2x11-mfd.h
deleted file mode 100644
index 9a855ac..0000000
--- a/include/linux/mfd/sta2x11-mfd.h
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * Copyright (c) 2009-2011 Wind River Systems, Inc.
- * Copyright (c) 2011 ST Microelectronics (Alessandro Rubini)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * The STMicroelectronics ConneXt (STA2X11) chip has several unrelated
- * functions in one PCI endpoint functions. This driver simply
- * registers the platform devices in this iomemregion and exports a few
- * functions to access common registers
- */
-
-#ifndef __STA2X11_MFD_H
-#define __STA2X11_MFD_H
-#include <linux/types.h>
-#include <linux/pci.h>
-
-enum sta2x11_mfd_plat_dev {
-	sta2x11_sctl = 0,
-	sta2x11_gpio,
-	sta2x11_scr,
-	sta2x11_time,
-	sta2x11_apbreg,
-	sta2x11_apb_soc_regs,
-	sta2x11_vic,
-	sta2x11_n_mfd_plat_devs,
-};
-
-#define STA2X11_MFD_SCTL_NAME	       "sta2x11-sctl"
-#define STA2X11_MFD_GPIO_NAME	       "sta2x11-gpio"
-#define STA2X11_MFD_SCR_NAME	       "sta2x11-scr"
-#define STA2X11_MFD_TIME_NAME	       "sta2x11-time"
-#define STA2X11_MFD_APBREG_NAME	       "sta2x11-apbreg"
-#define STA2X11_MFD_APB_SOC_REGS_NAME  "sta2x11-apb-soc-regs"
-#define STA2X11_MFD_VIC_NAME	       "sta2x11-vic"
-
-extern u32
-__sta2x11_mfd_mask(struct pci_dev *, u32, u32, u32, enum sta2x11_mfd_plat_dev);
-
-/*
- * The MFD PCI block includes the GPIO peripherals and other register blocks.
- * For GPIO, we have 32*4 bits (I use "gsta" for "gpio sta2x11".)
- */
-#define GSTA_GPIO_PER_BLOCK	32
-#define GSTA_NR_BLOCKS		4
-#define GSTA_NR_GPIO		(GSTA_GPIO_PER_BLOCK * GSTA_NR_BLOCKS)
-
-/* Pinconfig is set by the board definition: altfunc, pull-up, pull-down */
-struct sta2x11_gpio_pdata {
-	unsigned pinconfig[GSTA_NR_GPIO];
-};
-
-/* Macros below lifted from sh_pfc.h, with minor differences */
-#define PINMUX_TYPE_NONE		0
-#define PINMUX_TYPE_FUNCTION		1
-#define PINMUX_TYPE_OUTPUT_LOW		2
-#define PINMUX_TYPE_OUTPUT_HIGH		3
-#define PINMUX_TYPE_INPUT		4
-#define PINMUX_TYPE_INPUT_PULLUP	5
-#define PINMUX_TYPE_INPUT_PULLDOWN	6
-
-/* Give names to GPIO pins, like PXA does, taken from the manual */
-#define STA2X11_GPIO0			0
-#define STA2X11_GPIO1			1
-#define STA2X11_GPIO2			2
-#define STA2X11_GPIO3			3
-#define STA2X11_GPIO4			4
-#define STA2X11_GPIO5			5
-#define STA2X11_GPIO6			6
-#define STA2X11_GPIO7			7
-#define STA2X11_GPIO8_RGBOUT_RED7	8
-#define STA2X11_GPIO9_RGBOUT_RED6	9
-#define STA2X11_GPIO10_RGBOUT_RED5	10
-#define STA2X11_GPIO11_RGBOUT_RED4	11
-#define STA2X11_GPIO12_RGBOUT_RED3	12
-#define STA2X11_GPIO13_RGBOUT_RED2	13
-#define STA2X11_GPIO14_RGBOUT_RED1	14
-#define STA2X11_GPIO15_RGBOUT_RED0	15
-#define STA2X11_GPIO16_RGBOUT_GREEN7	16
-#define STA2X11_GPIO17_RGBOUT_GREEN6	17
-#define STA2X11_GPIO18_RGBOUT_GREEN5	18
-#define STA2X11_GPIO19_RGBOUT_GREEN4	19
-#define STA2X11_GPIO20_RGBOUT_GREEN3	20
-#define STA2X11_GPIO21_RGBOUT_GREEN2	21
-#define STA2X11_GPIO22_RGBOUT_GREEN1	22
-#define STA2X11_GPIO23_RGBOUT_GREEN0	23
-#define STA2X11_GPIO24_RGBOUT_BLUE7	24
-#define STA2X11_GPIO25_RGBOUT_BLUE6	25
-#define STA2X11_GPIO26_RGBOUT_BLUE5	26
-#define STA2X11_GPIO27_RGBOUT_BLUE4	27
-#define STA2X11_GPIO28_RGBOUT_BLUE3	28
-#define STA2X11_GPIO29_RGBOUT_BLUE2	29
-#define STA2X11_GPIO30_RGBOUT_BLUE1	30
-#define STA2X11_GPIO31_RGBOUT_BLUE0	31
-#define STA2X11_GPIO32_RGBOUT_VSYNCH	32
-#define STA2X11_GPIO33_RGBOUT_HSYNCH	33
-#define STA2X11_GPIO34_RGBOUT_DEN	34
-#define STA2X11_GPIO35_ETH_CRS_DV	35
-#define STA2X11_GPIO36_ETH_TXD1		36
-#define STA2X11_GPIO37_ETH_TXD0		37
-#define STA2X11_GPIO38_ETH_TX_EN	38
-#define STA2X11_GPIO39_MDIO		39
-#define STA2X11_GPIO40_ETH_REF_CLK	40
-#define STA2X11_GPIO41_ETH_RXD1		41
-#define STA2X11_GPIO42_ETH_RXD0		42
-#define STA2X11_GPIO43_MDC		43
-#define STA2X11_GPIO44_CAN_TX		44
-#define STA2X11_GPIO45_CAN_RX		45
-#define STA2X11_GPIO46_MLB_DAT		46
-#define STA2X11_GPIO47_MLB_SIG		47
-#define STA2X11_GPIO48_SPI0_CLK		48
-#define STA2X11_GPIO49_SPI0_TXD		49
-#define STA2X11_GPIO50_SPI0_RXD		50
-#define STA2X11_GPIO51_SPI0_FRM		51
-#define STA2X11_GPIO52_SPI1_CLK		52
-#define STA2X11_GPIO53_SPI1_TXD		53
-#define STA2X11_GPIO54_SPI1_RXD		54
-#define STA2X11_GPIO55_SPI1_FRM		55
-#define STA2X11_GPIO56_SPI2_CLK		56
-#define STA2X11_GPIO57_SPI2_TXD		57
-#define STA2X11_GPIO58_SPI2_RXD		58
-#define STA2X11_GPIO59_SPI2_FRM		59
-#define STA2X11_GPIO60_I2C0_SCL		60
-#define STA2X11_GPIO61_I2C0_SDA		61
-#define STA2X11_GPIO62_I2C1_SCL		62
-#define STA2X11_GPIO63_I2C1_SDA		63
-#define STA2X11_GPIO64_I2C2_SCL		64
-#define STA2X11_GPIO65_I2C2_SDA		65
-#define STA2X11_GPIO66_I2C3_SCL		66
-#define STA2X11_GPIO67_I2C3_SDA		67
-#define STA2X11_GPIO68_MSP0_RCK		68
-#define STA2X11_GPIO69_MSP0_RXD		69
-#define STA2X11_GPIO70_MSP0_RFS		70
-#define STA2X11_GPIO71_MSP0_TCK		71
-#define STA2X11_GPIO72_MSP0_TXD		72
-#define STA2X11_GPIO73_MSP0_TFS		73
-#define STA2X11_GPIO74_MSP0_SCK		74
-#define STA2X11_GPIO75_MSP1_CK		75
-#define STA2X11_GPIO76_MSP1_RXD		76
-#define STA2X11_GPIO77_MSP1_FS		77
-#define STA2X11_GPIO78_MSP1_TXD		78
-#define STA2X11_GPIO79_MSP2_CK		79
-#define STA2X11_GPIO80_MSP2_RXD		80
-#define STA2X11_GPIO81_MSP2_FS		81
-#define STA2X11_GPIO82_MSP2_TXD		82
-#define STA2X11_GPIO83_MSP3_CK		83
-#define STA2X11_GPIO84_MSP3_RXD		84
-#define STA2X11_GPIO85_MSP3_FS		85
-#define STA2X11_GPIO86_MSP3_TXD		86
-#define STA2X11_GPIO87_MSP4_CK		87
-#define STA2X11_GPIO88_MSP4_RXD		88
-#define STA2X11_GPIO89_MSP4_FS		89
-#define STA2X11_GPIO90_MSP4_TXD		90
-#define STA2X11_GPIO91_MSP5_CK		91
-#define STA2X11_GPIO92_MSP5_RXD		92
-#define STA2X11_GPIO93_MSP5_FS		93
-#define STA2X11_GPIO94_MSP5_TXD		94
-#define STA2X11_GPIO95_SDIO3_DAT3	95
-#define STA2X11_GPIO96_SDIO3_DAT2	96
-#define STA2X11_GPIO97_SDIO3_DAT1	97
-#define STA2X11_GPIO98_SDIO3_DAT0	98
-#define STA2X11_GPIO99_SDIO3_CLK	99
-#define STA2X11_GPIO100_SDIO3_CMD	100
-#define STA2X11_GPIO101			101
-#define STA2X11_GPIO102			102
-#define STA2X11_GPIO103			103
-#define STA2X11_GPIO104			104
-#define STA2X11_GPIO105_SDIO2_DAT3	105
-#define STA2X11_GPIO106_SDIO2_DAT2	106
-#define STA2X11_GPIO107_SDIO2_DAT1	107
-#define STA2X11_GPIO108_SDIO2_DAT0	108
-#define STA2X11_GPIO109_SDIO2_CLK	109
-#define STA2X11_GPIO110_SDIO2_CMD	110
-#define STA2X11_GPIO111			111
-#define STA2X11_GPIO112			112
-#define STA2X11_GPIO113			113
-#define STA2X11_GPIO114			114
-#define STA2X11_GPIO115_SDIO1_DAT3	115
-#define STA2X11_GPIO116_SDIO1_DAT2	116
-#define STA2X11_GPIO117_SDIO1_DAT1	117
-#define STA2X11_GPIO118_SDIO1_DAT0	118
-#define STA2X11_GPIO119_SDIO1_CLK	119
-#define STA2X11_GPIO120_SDIO1_CMD	120
-#define STA2X11_GPIO121			121
-#define STA2X11_GPIO122			122
-#define STA2X11_GPIO123			123
-#define STA2X11_GPIO124			124
-#define STA2X11_GPIO125_UART2_TXD	125
-#define STA2X11_GPIO126_UART2_RXD	126
-#define STA2X11_GPIO127_UART3_TXD	127
-
-/*
- * The APB bridge has its own registers, needed by our users as well.
- * They are accessed with the following read/mask/write function.
- */
-static inline u32
-sta2x11_apbreg_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
-{
-	return __sta2x11_mfd_mask(pdev, reg, mask, val, sta2x11_apbreg);
-}
-
-/* CAN and MLB */
-#define APBREG_BSR	0x00	/* Bridge Status Reg */
-#define APBREG_PAER	0x08	/* Peripherals Address Error Reg */
-#define APBREG_PWAC	0x20	/* Peripheral Write Access Control reg */
-#define APBREG_PRAC	0x40	/* Peripheral Read Access Control reg */
-#define APBREG_PCG	0x60	/* Peripheral Clock Gating Reg */
-#define APBREG_PUR	0x80	/* Peripheral Under Reset Reg */
-#define APBREG_EMU_PCG	0xA0	/* Emulator Peripheral Clock Gating Reg */
-
-#define APBREG_CAN	(1 << 1)
-#define APBREG_MLB	(1 << 3)
-
-/* SARAC */
-#define APBREG_BSR_SARAC     0x100 /* Bridge Status Reg */
-#define APBREG_PAER_SARAC    0x108 /* Peripherals Address Error Reg */
-#define APBREG_PWAC_SARAC    0x120 /* Peripheral Write Access Control reg */
-#define APBREG_PRAC_SARAC    0x140 /* Peripheral Read Access Control reg */
-#define APBREG_PCG_SARAC     0x160 /* Peripheral Clock Gating Reg */
-#define APBREG_PUR_SARAC     0x180 /* Peripheral Under Reset Reg */
-#define APBREG_EMU_PCG_SARAC 0x1A0 /* Emulator Peripheral Clock Gating Reg */
-
-#define APBREG_SARAC	(1 << 2)
-
-/*
- * The system controller has its own registers. Some of these are accessed
- * by out users as well, using the following read/mask/write/function
- */
-static inline
-u32 sta2x11_sctl_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
-{
-	return __sta2x11_mfd_mask(pdev, reg, mask, val, sta2x11_sctl);
-}
-
-#define SCTL_SCCTL		0x00	/* System controller control register */
-#define SCTL_ARMCFG		0x04	/* ARM configuration register */
-#define SCTL_SCPLLCTL		0x08	/* PLL control status register */
-
-#define SCTL_SCPLLCTL_AUDIO_PLL_PD	     BIT(1)
-#define SCTL_SCPLLCTL_FRAC_CONTROL	     BIT(3)
-#define SCTL_SCPLLCTL_STRB_BYPASS	     BIT(6)
-#define SCTL_SCPLLCTL_STRB_INPUT	     BIT(8)
-
-#define SCTL_SCPLLFCTRL		0x0c	/* PLL frequency control register */
-
-#define SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_MASK	0xff
-#define SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_SHIFT	  10
-#define SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_MASK	   7
-#define SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_SHIFT	  21
-#define SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_MASK	   7
-#define SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_SHIFT	  18
-#define SCTL_SCPLLFCTRL_DITHER_DISABLE_MASK     0x03
-#define SCTL_SCPLLFCTRL_DITHER_DISABLE_SHIFT       4
-
-
-#define SCTL_SCRESFRACT		0x10	/* PLL fractional input register */
-
-#define SCTL_SCRESFRACT_MASK	0x0000ffff
-
-
-#define SCTL_SCRESCTRL1		0x14	/* Peripheral reset control 1 */
-#define SCTL_SCRESXTRL2		0x18	/* Peripheral reset control 2 */
-#define SCTL_SCPEREN0		0x1c	/* Peripheral clock enable register 0 */
-#define SCTL_SCPEREN1		0x20	/* Peripheral clock enable register 1 */
-#define SCTL_SCPEREN2		0x24	/* Peripheral clock enable register 2 */
-#define SCTL_SCGRST		0x28	/* Peripheral global reset */
-#define SCTL_SCPCIECSBRST       0x2c    /* PCIe PAB CSB reset status register */
-#define SCTL_SCPCIPMCR1		0x30	/* PCI power management control 1 */
-#define SCTL_SCPCIPMCR2		0x34	/* PCI power management control 2 */
-#define SCTL_SCPCIPMSR1		0x38	/* PCI power management status 1 */
-#define SCTL_SCPCIPMSR2		0x3c	/* PCI power management status 2 */
-#define SCTL_SCPCIPMSR3		0x40	/* PCI power management status 3 */
-#define SCTL_SCINTREN		0x44	/* Interrupt enable */
-#define SCTL_SCRISR		0x48	/* RAW interrupt status */
-#define SCTL_SCCLKSTAT0		0x4c	/* Peripheral clocks status 0 */
-#define SCTL_SCCLKSTAT1		0x50	/* Peripheral clocks status 1 */
-#define SCTL_SCCLKSTAT2		0x54	/* Peripheral clocks status 2 */
-#define SCTL_SCRSTSTA		0x58	/* Reset status register */
-
-#define SCTL_SCRESCTRL1_USB_PHY_POR	(1 << 0)
-#define SCTL_SCRESCTRL1_USB_OTG	(1 << 1)
-#define SCTL_SCRESCTRL1_USB_HRST	(1 << 2)
-#define SCTL_SCRESCTRL1_USB_PHY_HOST	(1 << 3)
-#define SCTL_SCRESCTRL1_SATAII	(1 << 4)
-#define SCTL_SCRESCTRL1_VIP		(1 << 5)
-#define SCTL_SCRESCTRL1_PER_MMC0	(1 << 6)
-#define SCTL_SCRESCTRL1_PER_MMC1	(1 << 7)
-#define SCTL_SCRESCTRL1_PER_GPIO0	(1 << 8)
-#define SCTL_SCRESCTRL1_PER_GPIO1	(1 << 9)
-#define SCTL_SCRESCTRL1_PER_GPIO2	(1 << 10)
-#define SCTL_SCRESCTRL1_PER_GPIO3	(1 << 11)
-#define SCTL_SCRESCTRL1_PER_MTU0	(1 << 12)
-#define SCTL_SCRESCTRL1_KER_SPI0	(1 << 13)
-#define SCTL_SCRESCTRL1_KER_SPI1	(1 << 14)
-#define SCTL_SCRESCTRL1_KER_SPI2	(1 << 15)
-#define SCTL_SCRESCTRL1_KER_MCI0	(1 << 16)
-#define SCTL_SCRESCTRL1_KER_MCI1	(1 << 17)
-#define SCTL_SCRESCTRL1_PRE_HSI2C0	(1 << 18)
-#define SCTL_SCRESCTRL1_PER_HSI2C1	(1 << 19)
-#define SCTL_SCRESCTRL1_PER_HSI2C2	(1 << 20)
-#define SCTL_SCRESCTRL1_PER_HSI2C3	(1 << 21)
-#define SCTL_SCRESCTRL1_PER_MSP0	(1 << 22)
-#define SCTL_SCRESCTRL1_PER_MSP1	(1 << 23)
-#define SCTL_SCRESCTRL1_PER_MSP2	(1 << 24)
-#define SCTL_SCRESCTRL1_PER_MSP3	(1 << 25)
-#define SCTL_SCRESCTRL1_PER_MSP4	(1 << 26)
-#define SCTL_SCRESCTRL1_PER_MSP5	(1 << 27)
-#define SCTL_SCRESCTRL1_PER_MMC	(1 << 28)
-#define SCTL_SCRESCTRL1_KER_MSP0	(1 << 29)
-#define SCTL_SCRESCTRL1_KER_MSP1	(1 << 30)
-#define SCTL_SCRESCTRL1_KER_MSP2	(1 << 31)
-
-#define SCTL_SCPEREN0_UART0		(1 << 0)
-#define SCTL_SCPEREN0_UART1		(1 << 1)
-#define SCTL_SCPEREN0_UART2		(1 << 2)
-#define SCTL_SCPEREN0_UART3		(1 << 3)
-#define SCTL_SCPEREN0_MSP0		(1 << 4)
-#define SCTL_SCPEREN0_MSP1		(1 << 5)
-#define SCTL_SCPEREN0_MSP2		(1 << 6)
-#define SCTL_SCPEREN0_MSP3		(1 << 7)
-#define SCTL_SCPEREN0_MSP4		(1 << 8)
-#define SCTL_SCPEREN0_MSP5		(1 << 9)
-#define SCTL_SCPEREN0_SPI0		(1 << 10)
-#define SCTL_SCPEREN0_SPI1		(1 << 11)
-#define SCTL_SCPEREN0_SPI2		(1 << 12)
-#define SCTL_SCPEREN0_I2C0		(1 << 13)
-#define SCTL_SCPEREN0_I2C1		(1 << 14)
-#define SCTL_SCPEREN0_I2C2		(1 << 15)
-#define SCTL_SCPEREN0_I2C3		(1 << 16)
-#define SCTL_SCPEREN0_SVDO_LVDS		(1 << 17)
-#define SCTL_SCPEREN0_USB_HOST		(1 << 18)
-#define SCTL_SCPEREN0_USB_OTG		(1 << 19)
-#define SCTL_SCPEREN0_MCI0		(1 << 20)
-#define SCTL_SCPEREN0_MCI1		(1 << 21)
-#define SCTL_SCPEREN0_MCI2		(1 << 22)
-#define SCTL_SCPEREN0_MCI3		(1 << 23)
-#define SCTL_SCPEREN0_SATA		(1 << 24)
-#define SCTL_SCPEREN0_ETHERNET		(1 << 25)
-#define SCTL_SCPEREN0_VIC		(1 << 26)
-#define SCTL_SCPEREN0_DMA_AUDIO		(1 << 27)
-#define SCTL_SCPEREN0_DMA_SOC		(1 << 28)
-#define SCTL_SCPEREN0_RAM		(1 << 29)
-#define SCTL_SCPEREN0_VIP		(1 << 30)
-#define SCTL_SCPEREN0_ARM		(1 << 31)
-
-#define SCTL_SCPEREN1_UART0		(1 << 0)
-#define SCTL_SCPEREN1_UART1		(1 << 1)
-#define SCTL_SCPEREN1_UART2		(1 << 2)
-#define SCTL_SCPEREN1_UART3		(1 << 3)
-#define SCTL_SCPEREN1_MSP0		(1 << 4)
-#define SCTL_SCPEREN1_MSP1		(1 << 5)
-#define SCTL_SCPEREN1_MSP2		(1 << 6)
-#define SCTL_SCPEREN1_MSP3		(1 << 7)
-#define SCTL_SCPEREN1_MSP4		(1 << 8)
-#define SCTL_SCPEREN1_MSP5		(1 << 9)
-#define SCTL_SCPEREN1_SPI0		(1 << 10)
-#define SCTL_SCPEREN1_SPI1		(1 << 11)
-#define SCTL_SCPEREN1_SPI2		(1 << 12)
-#define SCTL_SCPEREN1_I2C0		(1 << 13)
-#define SCTL_SCPEREN1_I2C1		(1 << 14)
-#define SCTL_SCPEREN1_I2C2		(1 << 15)
-#define SCTL_SCPEREN1_I2C3		(1 << 16)
-#define SCTL_SCPEREN1_USB_PHY		(1 << 17)
-
-/*
- * APB-SOC registers
- */
-static inline
-u32 sta2x11_apb_soc_regs_mask(struct pci_dev *pdev, u32 reg, u32 mask, u32 val)
-{
-	return __sta2x11_mfd_mask(pdev, reg, mask, val, sta2x11_apb_soc_regs);
-}
-
-#define PCIE_EP1_FUNC3_0_INTR_REG	0x000
-#define PCIE_EP1_FUNC7_4_INTR_REG	0x004
-#define PCIE_EP2_FUNC3_0_INTR_REG	0x008
-#define PCIE_EP2_FUNC7_4_INTR_REG	0x00c
-#define PCIE_EP3_FUNC3_0_INTR_REG	0x010
-#define PCIE_EP3_FUNC7_4_INTR_REG	0x014
-#define PCIE_EP4_FUNC3_0_INTR_REG	0x018
-#define PCIE_EP4_FUNC7_4_INTR_REG	0x01c
-#define PCIE_INTR_ENABLE0_REG		0x020
-#define PCIE_INTR_ENABLE1_REG		0x024
-#define PCIE_EP1_FUNC_TC_REG		0x028
-#define PCIE_EP2_FUNC_TC_REG		0x02c
-#define PCIE_EP3_FUNC_TC_REG		0x030
-#define PCIE_EP4_FUNC_TC_REG		0x034
-#define PCIE_EP1_FUNC_F_REG		0x038
-#define PCIE_EP2_FUNC_F_REG		0x03c
-#define PCIE_EP3_FUNC_F_REG		0x040
-#define PCIE_EP4_FUNC_F_REG		0x044
-#define PCIE_PAB_AMBA_SW_RST_REG	0x048
-#define PCIE_PM_STATUS_0_PORT_0_4	0x04c
-#define PCIE_PM_STATUS_7_0_EP1		0x050
-#define PCIE_PM_STATUS_7_0_EP2		0x054
-#define PCIE_PM_STATUS_7_0_EP3		0x058
-#define PCIE_PM_STATUS_7_0_EP4		0x05c
-#define PCIE_DEV_ID_0_EP1_REG		0x060
-#define PCIE_CC_REV_ID_0_EP1_REG	0x064
-#define PCIE_DEV_ID_1_EP1_REG		0x068
-#define PCIE_CC_REV_ID_1_EP1_REG	0x06c
-#define PCIE_DEV_ID_2_EP1_REG		0x070
-#define PCIE_CC_REV_ID_2_EP1_REG	0x074
-#define PCIE_DEV_ID_3_EP1_REG		0x078
-#define PCIE_CC_REV_ID_3_EP1_REG	0x07c
-#define PCIE_DEV_ID_4_EP1_REG		0x080
-#define PCIE_CC_REV_ID_4_EP1_REG	0x084
-#define PCIE_DEV_ID_5_EP1_REG		0x088
-#define PCIE_CC_REV_ID_5_EP1_REG	0x08c
-#define PCIE_DEV_ID_6_EP1_REG		0x090
-#define PCIE_CC_REV_ID_6_EP1_REG	0x094
-#define PCIE_DEV_ID_7_EP1_REG		0x098
-#define PCIE_CC_REV_ID_7_EP1_REG	0x09c
-#define PCIE_DEV_ID_0_EP2_REG		0x0a0
-#define PCIE_CC_REV_ID_0_EP2_REG	0x0a4
-#define PCIE_DEV_ID_1_EP2_REG		0x0a8
-#define PCIE_CC_REV_ID_1_EP2_REG	0x0ac
-#define PCIE_DEV_ID_2_EP2_REG		0x0b0
-#define PCIE_CC_REV_ID_2_EP2_REG	0x0b4
-#define PCIE_DEV_ID_3_EP2_REG		0x0b8
-#define PCIE_CC_REV_ID_3_EP2_REG	0x0bc
-#define PCIE_DEV_ID_4_EP2_REG		0x0c0
-#define PCIE_CC_REV_ID_4_EP2_REG	0x0c4
-#define PCIE_DEV_ID_5_EP2_REG		0x0c8
-#define PCIE_CC_REV_ID_5_EP2_REG	0x0cc
-#define PCIE_DEV_ID_6_EP2_REG		0x0d0
-#define PCIE_CC_REV_ID_6_EP2_REG	0x0d4
-#define PCIE_DEV_ID_7_EP2_REG		0x0d8
-#define PCIE_CC_REV_ID_7_EP2_REG	0x0dC
-#define PCIE_DEV_ID_0_EP3_REG		0x0e0
-#define PCIE_CC_REV_ID_0_EP3_REG	0x0e4
-#define PCIE_DEV_ID_1_EP3_REG		0x0e8
-#define PCIE_CC_REV_ID_1_EP3_REG	0x0ec
-#define PCIE_DEV_ID_2_EP3_REG		0x0f0
-#define PCIE_CC_REV_ID_2_EP3_REG	0x0f4
-#define PCIE_DEV_ID_3_EP3_REG		0x0f8
-#define PCIE_CC_REV_ID_3_EP3_REG	0x0fc
-#define PCIE_DEV_ID_4_EP3_REG		0x100
-#define PCIE_CC_REV_ID_4_EP3_REG	0x104
-#define PCIE_DEV_ID_5_EP3_REG		0x108
-#define PCIE_CC_REV_ID_5_EP3_REG	0x10c
-#define PCIE_DEV_ID_6_EP3_REG		0x110
-#define PCIE_CC_REV_ID_6_EP3_REG	0x114
-#define PCIE_DEV_ID_7_EP3_REG		0x118
-#define PCIE_CC_REV_ID_7_EP3_REG	0x11c
-#define PCIE_DEV_ID_0_EP4_REG		0x120
-#define PCIE_CC_REV_ID_0_EP4_REG	0x124
-#define PCIE_DEV_ID_1_EP4_REG		0x128
-#define PCIE_CC_REV_ID_1_EP4_REG	0x12c
-#define PCIE_DEV_ID_2_EP4_REG		0x130
-#define PCIE_CC_REV_ID_2_EP4_REG	0x134
-#define PCIE_DEV_ID_3_EP4_REG		0x138
-#define PCIE_CC_REV_ID_3_EP4_REG	0x13c
-#define PCIE_DEV_ID_4_EP4_REG		0x140
-#define PCIE_CC_REV_ID_4_EP4_REG	0x144
-#define PCIE_DEV_ID_5_EP4_REG		0x148
-#define PCIE_CC_REV_ID_5_EP4_REG	0x14c
-#define PCIE_DEV_ID_6_EP4_REG		0x150
-#define PCIE_CC_REV_ID_6_EP4_REG	0x154
-#define PCIE_DEV_ID_7_EP4_REG		0x158
-#define PCIE_CC_REV_ID_7_EP4_REG	0x15c
-#define PCIE_SUBSYS_VEN_ID_REG		0x160
-#define PCIE_COMMON_CLOCK_CONFIG_0_4_0	0x164
-#define PCIE_MIPHYP_SSC_EN_REG		0x168
-#define PCIE_MIPHYP_ADDR_REG		0x16c
-#define PCIE_L1_ASPM_READY_REG		0x170
-#define PCIE_EXT_CFG_RDY_REG		0x174
-#define PCIE_SoC_INT_ROUTER_STATUS0_REG 0x178
-#define PCIE_SoC_INT_ROUTER_STATUS1_REG 0x17c
-#define PCIE_SoC_INT_ROUTER_STATUS2_REG 0x180
-#define PCIE_SoC_INT_ROUTER_STATUS3_REG 0x184
-#define DMA_IP_CTRL_REG			0x324
-#define DISP_BRIDGE_PU_PD_CTRL_REG	0x328
-#define VIP_PU_PD_CTRL_REG		0x32c
-#define USB_MLB_PU_PD_CTRL_REG		0x330
-#define SDIO_PU_PD_MISCFUNC_CTRL_REG1	0x334
-#define SDIO_PU_PD_MISCFUNC_CTRL_REG2	0x338
-#define UART_PU_PD_CTRL_REG		0x33c
-#define ARM_Lock			0x340
-#define SYS_IO_CHAR_REG1		0x344
-#define SYS_IO_CHAR_REG2		0x348
-#define SATA_CORE_ID_REG		0x34c
-#define SATA_CTRL_REG			0x350
-#define I2C_HSFIX_MISC_REG		0x354
-#define SPARE2_RESERVED			0x358
-#define SPARE3_RESERVED			0x35c
-#define MASTER_LOCK_REG			0x368
-#define SYSTEM_CONFIG_STATUS_REG	0x36c
-#define MSP_CLK_CTRL_REG		0x39c
-#define COMPENSATION_REG1		0x3c4
-#define COMPENSATION_REG2		0x3c8
-#define COMPENSATION_REG3		0x3cc
-#define TEST_CTL_REG			0x3d0
-
-/*
- * SECR (OTP) registers
- */
-#define STA2X11_SECR_CR			0x00
-#define STA2X11_SECR_FVR0		0x10
-#define STA2X11_SECR_FVR1		0x14
-
-extern int sta2x11_mfd_get_regs_data(struct platform_device *pdev,
-				     enum sta2x11_mfd_plat_dev index,
-				     void __iomem **regs,
-				     spinlock_t **lock);
-
-#endif /* __STA2X11_MFD_H */
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 16/26] x86 STA2X11 platform: add sta2x11_platform_init()
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (14 preceding siblings ...)
  2013-08-07 10:20 ` [PATCH 15/26] x86 STA2X11: remove the sta2x11-mfd driver Davide Ciminaghi
@ 2013-08-07 10:20 ` Davide Ciminaghi
  2013-08-07 10:20 ` [PATCH 17/26] x86 STA2X11 platform: add sta2x11_instance_data helpers Davide Ciminaghi
                   ` (11 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch adds an init function which looks for connext nodes in the
device tree (compatible "pci104a,cc17") and creates a list of sta2x11
related data structures (struct sta2x11_instance_data). For each sta2x11,
the relevant four platform devices are also created (scr, apbreg,
apb-soc-regs, sctl).
Finally, of_match_tables are added to the four struct platform_driver.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/include/asm/sta2x11.h      |   17 +++++-
 arch/x86/platform/sta2x11/sta2x11.c |  111 ++++++++++++++++++++++++++++++++++-
 2 files changed, 125 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/sta2x11.h b/arch/x86/include/asm/sta2x11.h
index cd76923..30dd761 100644
--- a/arch/x86/include/asm/sta2x11.h
+++ b/arch/x86/include/asm/sta2x11.h
@@ -21,7 +21,7 @@
 #define __ASM_STA2X11_H
 
 #include <linux/types.h>
-#include <linux/pci.h>
+#include <linux/of.h>
 
 enum sta2x11_plat_dev {
 	sta2x11_sctl = 0,
@@ -34,6 +34,21 @@ enum sta2x11_plat_dev {
 	sta2x11_n_plat_devs,
 };
 
+/*
+ * Data structure representing a connext instance.
+ */
+struct sta2x11_instance_data {
+	/* Instance id */
+	int id;
+	/* Registers data */
+	struct sta2x11_platform_drv_data *sctl;
+	struct sta2x11_platform_drv_data *scr;
+	struct sta2x11_platform_drv_data *apbreg;
+	struct sta2x11_platform_drv_data *apb_soc_regs;
+	/* Do not touch this from outside arch/x86/platform/sta2x11/sta2x11.c */
+	struct list_head list;
+};
+
 #define STA2X11_SCTL_NAME		"sta2x11-sctl"
 #define STA2X11_GPIO_NAME		"sta2x11-gpio"
 #define STA2X11_SCR_NAME		"sta2x11-scr"
diff --git a/arch/x86/platform/sta2x11/sta2x11.c b/arch/x86/platform/sta2x11/sta2x11.c
index ab3bc62..936a7ab 100644
--- a/arch/x86/platform/sta2x11/sta2x11.c
+++ b/arch/x86/platform/sta2x11/sta2x11.c
@@ -30,9 +30,14 @@
 #include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
+#include <linux/list.h>
+#include <linux/of_pci.h>
+#include <linux/of_platform.h>
 
 #include <asm/sta2x11.h>
 
+static LIST_HEAD(connext_instances);
+
 static inline int __reg_within_range(unsigned int r,
 				     unsigned int start,
 				     unsigned int end)
@@ -213,10 +218,16 @@ static int sta2x11_scr_probe(struct platform_device *dev)
 }
 
 /* The three platform drivers */
+static const struct of_device_id sctl_ids[] = {
+	{ .compatible = "st,sta2x11-sctl" },
+	{}
+};
+
 static struct platform_driver sta2x11_sctl_platform_driver = {
 	.driver = {
 		.name	= STA2X11_SCTL_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = sctl_ids,
 	},
 	.probe		= sta2x11_sctl_probe,
 };
@@ -227,10 +238,16 @@ static int __init sta2x11_sctl_init(void)
 	return platform_driver_register(&sta2x11_sctl_platform_driver);
 }
 
-static struct platform_driver sta2x11_platform_driver = {
+static const struct of_device_id apbreg_ids[] = {
+	{ .compatible = "st,sta2x11-apb-regs" },
+	{}
+};
+
+static struct platform_driver sta2x11_apbreg_platform_driver = {
 	.driver = {
 		.name	= STA2X11_APBREG_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = apbreg_ids
 	},
 	.probe		= sta2x11_apbreg_probe,
 };
@@ -238,13 +255,19 @@ static struct platform_driver sta2x11_platform_driver = {
 static int __init sta2x11_apbreg_init(void)
 {
 	pr_info("%s\n", __func__);
-	return platform_driver_register(&sta2x11_platform_driver);
+	return platform_driver_register(&sta2x11_apbreg_platform_driver);
 }
 
+static const struct of_device_id apb_soc_regs_ids[] = {
+	{ .compatible = "st,sta2x11-apb-soc-regs" },
+	{}
+};
+
 static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
 	.driver = {
 		.name	= STA2X11_APB_SOC_REGS_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = apb_soc_regs_ids,
 	},
 	.probe		= sta2x11_apb_soc_regs_probe,
 };
@@ -255,10 +278,16 @@ static int __init sta2x11_apb_soc_regs_init(void)
 	return platform_driver_register(&sta2x11_apb_soc_regs_platform_driver);
 }
 
+static const struct of_device_id scr_ids[] = {
+	{ .compatible = "st,sta2x11-scr" },
+	{}
+};
+
 static struct platform_driver sta2x11_scr_platform_driver = {
 	.driver = {
 		.name = STA2X11_SCR_NAME,
 		.owner = THIS_MODULE,
+		.of_match_table = scr_ids,
 	},
 	.probe = sta2x11_scr_probe,
 };
@@ -269,10 +298,88 @@ static int __init sta2x11_scr_init(void)
 	return platform_driver_register(&sta2x11_scr_platform_driver);
 }
 
+
+static struct platform_device *
+do_create(const char *c, struct device_node *from,
+	  struct sta2x11_instance_data *idata)
+{
+	struct device_node *n;
+	struct platform_device *out = NULL;
+	int name_size;
+	char *name;
+
+	n = of_find_compatible_node(of_node_get(from), NULL, c);
+	if (!n)
+		return out;
+	/* %s.%1d */
+	name_size = strlen(n->name) + 3;
+	name = kzalloc(name_size, GFP_KERNEL);
+	if (!name)
+		return out;
+	snprintf(name, name_size, "%s.%1d", n->name, idata->id);
+
+	out = of_platform_device_create(n, name, NULL);
+	of_node_put(n);
+
+	if (!out) {
+		kfree(name);
+		return out;
+	}
+	/*
+	  Avoid the node to be re-instantiated later on
+	  by the pci-amba bridge
+	*/
+	of_detach_node(n);
+	return out;
+}
+
+static int new_connext(struct device_node *from,
+		       struct sta2x11_instance_data *idata)
+{
+	int i;
+	/* Create platform devices belonging to this connext instance */
+	const char *devs[] = {
+		"st,sta2x11-scr",
+		"st,sta2x11-apb-soc-regs",
+		"st,sta2x11-apb-regs",
+		"st,sta2x11-sctl",
+	};
+	for (i = 0; i < ARRAY_SIZE(devs); i++)
+		WARN_ON(!do_create(devs[i], from, idata));
+	return 0;
+}
+
+static int __init sta2x11_platform_init(void)
+{
+	struct device_node *n;
+	int ret = 0, stat;
+	struct sta2x11_instance_data *idata;
+	struct resource r;
+
+	for_each_compatible_node(n, NULL, "pci104a,cc17") {
+		if (of_pci_parse_bus_range(of_node_get(n), &r) < 0) {
+			ret = -EINVAL;
+			continue;
+		}
+		idata = kzalloc(sizeof(*idata), GFP_KERNEL);
+		if (!idata) {
+			ret = -ENOMEM;
+			continue;
+		}
+		idata->id = r.start + 1;
+		list_add(&idata->list, &connext_instances);
+		stat = new_connext(n, idata);
+		if (stat < 0)
+			ret = stat;
+	}
+	return ret;
+}
+
 subsys_initcall(sta2x11_apbreg_init);
 subsys_initcall(sta2x11_sctl_init);
 subsys_initcall(sta2x11_apb_soc_regs_init);
 subsys_initcall(sta2x11_scr_init);
+rootfs_initcall(sta2x11_platform_init);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Wind River");
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 17/26] x86 STA2X11 platform: add sta2x11_instance_data helpers
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (15 preceding siblings ...)
  2013-08-07 10:20 ` [PATCH 16/26] x86 STA2X11 platform: add sta2x11_platform_init() Davide Ciminaghi
@ 2013-08-07 10:20 ` Davide Ciminaghi
  2013-08-07 10:20 ` [PATCH 18/26] x86 STA2X11 platform: add a common probe function for platform devices Davide Ciminaghi
                   ` (10 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch adds functions to get a pointer to a sta2x11 instance data
structure given a pointer to a connext device or device node.
Such helpers will be used by the (now empty) common probe function,
and maybe by the common clock framework.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/include/asm/sta2x11.h      |   13 ++++++++
 arch/x86/platform/sta2x11/sta2x11.c |   55 ++++++++++++++++++++++++++++++++++-
 2 files changed, 67 insertions(+), 1 deletions(-)

diff --git a/arch/x86/include/asm/sta2x11.h b/arch/x86/include/asm/sta2x11.h
index 30dd761..6df0c87 100644
--- a/arch/x86/include/asm/sta2x11.h
+++ b/arch/x86/include/asm/sta2x11.h
@@ -49,6 +49,19 @@ struct sta2x11_instance_data {
 	struct list_head list;
 };
 
+/*
+ * Helper functions: get the pointer to a sta2x11 instance given the pointer
+ * to a device/device node belonging to a connext chip
+ */
+extern struct sta2x11_instance_data *
+sta2x11_node_to_instance(struct device_node *);
+
+static inline
+struct sta2x11_instance_data *sta2x11_dev_to_instance(struct device *dev)
+{
+	return sta2x11_node_to_instance(dev->of_node);
+}
+
 #define STA2X11_SCTL_NAME		"sta2x11-sctl"
 #define STA2X11_GPIO_NAME		"sta2x11-gpio"
 #define STA2X11_SCR_NAME		"sta2x11-scr"
diff --git a/arch/x86/platform/sta2x11/sta2x11.c b/arch/x86/platform/sta2x11/sta2x11.c
index 936a7ab..861d447 100644
--- a/arch/x86/platform/sta2x11/sta2x11.c
+++ b/arch/x86/platform/sta2x11/sta2x11.c
@@ -189,7 +189,60 @@ sta2x11_platform_regmap_configs[sta2x11_n_plat_devs] = {
 	[sta2x11_scr] = &sta2x11_scr_regmap_config,
 };
 
-/* Probe for the four platform devices */
+static struct sta2x11_instance_data *find_instance(int id)
+{
+	struct sta2x11_instance_data *ptr;
+	list_for_each_entry(ptr, &connext_instances, list)
+		if (ptr->id == id)
+			return ptr;
+	return NULL;
+}
+
+static struct sta2x11_instance_data
+*connext_node_to_instance(struct device_node *n)
+{
+	struct resource r;
+	if (of_pci_parse_bus_range(n, &r) < 0)
+		return NULL;
+	return find_instance(r.start + 1);
+}
+
+struct sta2x11_instance_data *sta2x11_node_to_instance(struct device_node *n)
+{
+	struct device_node *amba_bus, *pci_amba_bridge, *connext_node = NULL,
+		*parent;
+
+	if (!of_node_cmp(n->type, "pci")) {
+		/* A pci node */
+		for (parent = n->parent; parent; parent = parent->parent) {
+			if (of_device_is_compatible(parent, "pci104a,cc17")) {
+				connext_node = parent;
+				break;
+			}
+		}
+		if (!connext_node)
+			return NULL;
+		return connext_node_to_instance(connext_node);
+	}
+
+	/* An amba or platform device (or even an amba bus node) */
+	amba_bus = n;
+	if (!of_device_is_compatible(n, "arm,amba-bus"))
+		amba_bus = n->parent;
+	if (!amba_bus || !of_device_is_compatible(amba_bus, "arm,amba-bus"))
+		return NULL;
+	pci_amba_bridge = amba_bus->parent;
+	if (!pci_amba_bridge || !of_device_is_compatible(pci_amba_bridge,
+							 "pci104a,cc18"))
+		return NULL;
+	connext_node = pci_amba_bridge->parent;
+	if (!connext_node ||
+	    !of_device_is_compatible(connext_node, "pci104a,cc17.0"))
+		return NULL;
+	return connext_node_to_instance(connext_node);
+}
+EXPORT_SYMBOL(sta2x11_node_to_instance);
+
 
 static int sta2x11_platform_probe(struct platform_device *dev,
 				  enum sta2x11_plat_dev index)
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 18/26] x86 STA2X11 platform: add a common probe function for platform devices
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (16 preceding siblings ...)
  2013-08-07 10:20 ` [PATCH 17/26] x86 STA2X11 platform: add sta2x11_instance_data helpers Davide Ciminaghi
@ 2013-08-07 10:20 ` Davide Ciminaghi
  2013-08-07 10:20 ` [PATCH 19/26] x86 STA2X11 platform: create sta2x11-clock-regs device Davide Ciminaghi
                   ` (9 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch introduces a common probe method for the STA2X11 base platform
drivers. The following steps are performed:

* Registers belonging to the probed device are ioremapped.
* devm_regmap_init_mmio() is invoked on such registers.
* A struct sta2x11_platform_drv_data containing device data is allocated,
  filled in, and "linked" to the struct sta2x11_instance_data representing
  the instance to which the probed device belongs.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/include/asm/sta2x11.h      |    9 +++++
 arch/x86/platform/sta2x11/sta2x11.c |   68 ++++++++++++++++++++++++++++++++++-
 2 files changed, 76 insertions(+), 1 deletions(-)

diff --git a/arch/x86/include/asm/sta2x11.h b/arch/x86/include/asm/sta2x11.h
index 6df0c87..31fc648 100644
--- a/arch/x86/include/asm/sta2x11.h
+++ b/arch/x86/include/asm/sta2x11.h
@@ -35,6 +35,15 @@ enum sta2x11_plat_dev {
 };
 
 /*
+ * Platform driver data for sta2x11 platform devices
+ */
+struct sta2x11_platform_drv_data {
+	void * __iomem regs;
+	spinlock_t lock;
+	struct regmap *regmap;
+};
+
+/*
  * Data structure representing a connext instance.
  */
 struct sta2x11_instance_data {
diff --git a/arch/x86/platform/sta2x11/sta2x11.c b/arch/x86/platform/sta2x11/sta2x11.c
index 861d447..1f1d1af 100644
--- a/arch/x86/platform/sta2x11/sta2x11.c
+++ b/arch/x86/platform/sta2x11/sta2x11.c
@@ -244,10 +244,76 @@ struct sta2x11_instance_data *sta2x11_node_to_instance(struct device_node *n)
 EXPORT_SYMBOL(sta2x11_node_to_instance);
 
 
+/* Common probe for the four platform devices */
 static int sta2x11_platform_probe(struct platform_device *dev,
 				  enum sta2x11_plat_dev index)
 {
-	return -EINVAL;
+	struct resource *res;
+	struct regmap_config *regmap_config =
+		sta2x11_platform_regmap_configs[index];
+	struct sta2x11_platform_drv_data *platform_drv_data, **dst;
+	struct sta2x11_instance_data *instance;
+
+	if (!regmap_config)
+		return -ENODEV;
+
+	platform_drv_data = devm_kzalloc(&dev->dev, sizeof(*platform_drv_data),
+					 GFP_KERNEL);
+	if (!platform_drv_data)
+		return -ENOMEM;
+
+	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENOMEM;
+
+	platform_drv_data->regs = devm_request_and_ioremap(&dev->dev, res);
+	if (!platform_drv_data->regs)
+		return -ENOMEM;
+
+	regmap_config->lock_arg = &platform_drv_data->lock;
+	/*
+	   No caching, registers could be reached both via regmap and via
+	   void __iomem *
+	*/
+	regmap_config->cache_type = REGCACHE_NONE;
+	platform_drv_data->regmap =
+		devm_regmap_init_mmio(&dev->dev, platform_drv_data->regs,
+				      regmap_config);
+	WARN_ON(!platform_drv_data->regmap);
+
+	if (!dev->dev.of_node)
+		return -ENODEV;
+
+	/* Find out the connext's instance id */
+	instance = sta2x11_dev_to_instance(&dev->dev);
+	if (!instance)
+		return -ENODEV;
+
+	/*
+	  In case the device represents the sysctl or apb soc registers,
+	  add clocks related data and maybe create the "virtual"
+	  sta2x11-clock-regs platform devices
+	 */
+	switch (index) {
+	case sta2x11_sctl:
+		dst = &instance->sctl;
+		break;
+	case sta2x11_apb_soc_regs:
+		dst = &instance->apb_soc_regs;
+		break;
+	case sta2x11_apbreg:
+		dst = &instance->apbreg;
+		break;
+	case sta2x11_scr:
+		dst = &instance->scr;
+		break;
+	default:
+		return -ENODEV;
+	}
+	*dst = platform_drv_data;
+
+	platform_set_drvdata(dev, platform_drv_data);
+	return 0;
 }
 
 static int sta2x11_sctl_probe(struct platform_device *dev)
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 19/26] x86 STA2X11 platform: create sta2x11-clock-regs device
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (17 preceding siblings ...)
  2013-08-07 10:20 ` [PATCH 18/26] x86 STA2X11 platform: add a common probe function for platform devices Davide Ciminaghi
@ 2013-08-07 10:20 ` Davide Ciminaghi
  2013-08-07 10:20 ` [PATCH 20/26] x86 STA2X11 platform: remove useless pr_info()'s Davide Ciminaghi
                   ` (8 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch creates a virtual platform device each time the apb-soc-regs
and sctl devices have been probed for a given sta2x11 instance.
This will trigger clock registration for such instance.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/include/asm/sta2x11.h      |    1 +
 arch/x86/platform/sta2x11/sta2x11.c |   21 +++++++++++++++++++++
 2 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/sta2x11.h b/arch/x86/include/asm/sta2x11.h
index 31fc648..3c5dee4 100644
--- a/arch/x86/include/asm/sta2x11.h
+++ b/arch/x86/include/asm/sta2x11.h
@@ -78,6 +78,7 @@ struct sta2x11_instance_data *sta2x11_dev_to_instance(struct device *dev)
 #define STA2X11_APBREG_NAME		"sta2x11-apbreg"
 #define STA2X11_APB_SOC_REGS_NAME	"sta2x11-apb-soc-regs"
 #define STA2X11_VIC_NAME		"sta2x11-vic"
+#define STA2X11_CLOCK_REGS_NAME		"sta2x11-clock-regs"
 
 /* CAN and MLB */
 #define APBREG_BSR	0x00	/* Bridge Status Reg */
diff --git a/arch/x86/platform/sta2x11/sta2x11.c b/arch/x86/platform/sta2x11/sta2x11.c
index 1f1d1af..57ed10d 100644
--- a/arch/x86/platform/sta2x11/sta2x11.c
+++ b/arch/x86/platform/sta2x11/sta2x11.c
@@ -243,6 +243,20 @@ struct sta2x11_instance_data *sta2x11_node_to_instance(struct device_node *n)
 }
 EXPORT_SYMBOL(sta2x11_node_to_instance);
 
+static int create_clk_dev(struct sta2x11_instance_data *instance)
+{
+	int stat;
+	struct platform_device *cpd =
+		platform_device_alloc(STA2X11_CLOCK_REGS_NAME, instance->id);
+	if (!cpd)
+		return -ENOMEM;
+
+	cpd->dev.platform_data = instance;
+	stat = platform_device_add(cpd);
+	if (stat < 0)
+		platform_device_put(cpd);
+	return stat;
+}
 
 /* Common probe for the four platform devices */
 static int sta2x11_platform_probe(struct platform_device *dev,
@@ -312,6 +326,13 @@ static int sta2x11_platform_probe(struct platform_device *dev,
 	}
 	*dst = platform_drv_data;
 
+	/*
+	 * When both sctl and apb_soc_regs have been probed, we're ready for
+	 * creating the "sta2x11-clock-regs" platform device
+	 */
+	if (instance->sctl && instance->apb_soc_regs)
+		create_clk_dev(instance);
+
 	platform_set_drvdata(dev, platform_drv_data);
 	return 0;
 }
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 20/26] x86 STA2X11 platform: remove useless pr_info()'s
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (18 preceding siblings ...)
  2013-08-07 10:20 ` [PATCH 19/26] x86 STA2X11 platform: create sta2x11-clock-regs device Davide Ciminaghi
@ 2013-08-07 10:20 ` Davide Ciminaghi
  2013-08-07 10:21 ` [PATCH 21/26] AMBA: pci-amba bridge: improve code readability Davide Ciminaghi
                   ` (7 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:20 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/platform/sta2x11/sta2x11.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/x86/platform/sta2x11/sta2x11.c b/arch/x86/platform/sta2x11/sta2x11.c
index 57ed10d..b3e9cec 100644
--- a/arch/x86/platform/sta2x11/sta2x11.c
+++ b/arch/x86/platform/sta2x11/sta2x11.c
@@ -374,7 +374,6 @@ static struct platform_driver sta2x11_sctl_platform_driver = {
 
 static int __init sta2x11_sctl_init(void)
 {
-	pr_info("%s\n", __func__);
 	return platform_driver_register(&sta2x11_sctl_platform_driver);
 }
 
@@ -394,7 +393,6 @@ static struct platform_driver sta2x11_apbreg_platform_driver = {
 
 static int __init sta2x11_apbreg_init(void)
 {
-	pr_info("%s\n", __func__);
 	return platform_driver_register(&sta2x11_apbreg_platform_driver);
 }
 
@@ -414,7 +412,6 @@ static struct platform_driver sta2x11_apb_soc_regs_platform_driver = {
 
 static int __init sta2x11_apb_soc_regs_init(void)
 {
-	pr_info("%s\n", __func__);
 	return platform_driver_register(&sta2x11_apb_soc_regs_platform_driver);
 }
 
@@ -434,7 +431,6 @@ static struct platform_driver sta2x11_scr_platform_driver = {
 
 static int __init sta2x11_scr_init(void)
 {
-	pr_info("%s\n", __func__);
 	return platform_driver_register(&sta2x11_scr_platform_driver);
 }
 
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 21/26] AMBA: pci-amba bridge: improve code readability
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (19 preceding siblings ...)
  2013-08-07 10:20 ` [PATCH 20/26] x86 STA2X11 platform: remove useless pr_info()'s Davide Ciminaghi
@ 2013-08-07 10:21 ` Davide Ciminaghi
  2013-08-07 10:21 ` [PATCH 22/26] AMBA: pci-amba bridge: extend number of amba devs per pci device Davide Ciminaghi
                   ` (6 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:21 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch moves the code fixing up irq numbers for amba devices
to a separate function (fixup_amba_irqs()).

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 drivers/amba/pci-amba.c |   97 +++++++++++++++++++++++++---------------------
 1 files changed, 53 insertions(+), 44 deletions(-)

diff --git a/drivers/amba/pci-amba.c b/drivers/amba/pci-amba.c
index e56717b..c825c7a 100644
--- a/drivers/amba/pci-amba.c
+++ b/drivers/amba/pci-amba.c
@@ -25,19 +25,63 @@
 */
 #define IMAP_ROW_LEN (1 + 1 + 1 + 1 + 1)
 
+static int fixup_amba_irq(struct device_node *amba_node,
+			  struct device_node *amba_bus,
+			  struct pci_dev *pdev)
+{
+	const void *p;
+	struct property *newimap;
+	u32 *ptr, *newv;
+	const u32 *reg;
+	int i, len, found;
+
+	p = of_get_property(amba_bus, "interrupt-map", &len);
+	if (!p)
+		/* No amba bus interrupt-map property */
+		return -EINVAL;
+
+	newimap = devm_kzalloc(&pdev->dev, sizeof(*newimap), GFP_KERNEL);
+	if (!newimap)
+		return -ENOMEM;
+
+	newimap->name = kstrdup("interrupt-map", GFP_KERNEL);
+	if (!newimap->name)
+		return -ENOMEM;
+
+	newv = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
+	if (!newv) {
+		kfree(newimap->name);
+		return -ENOMEM;
+	}
+
+	newimap->value = newv;
+	newimap->length = len;
+	memcpy(newv, p, len);
+	for (ptr = newv, i = 0, found = 0;
+	     i < len/sizeof(u32); ptr += IMAP_ROW_LEN, i += IMAP_ROW_LEN) {
+		reg = of_get_property(amba_node, "reg", NULL);
+		if (ptr[0] == reg[0]) {
+			ptr[IMAP_ROW_LEN - 1] = cpu_to_be32(pdev->irq);
+			found = 1;
+			break;
+		}
+	}
+	if (!found) {
+		pr_err("Could not update amba irq\n");
+		return -EINVAL;
+	}
+	of_update_property(amba_bus, newimap);
+	return 0;
+}
+
 static int pci_amba_probe(struct pci_dev *pdev,
 			  const struct pci_device_id *id)
 {
 	struct amba_device *adev;
-	int i, ret, len;
+	int ret;
 	struct device_node *n, *node, *pci_amba_bridge, *amba_bus = NULL,
 		*amba_node = NULL;
-	const void *p;
 	char *name;
-	struct property *newimap;
-	u32 *newv, *ptr;
-	const u32 *reg;
-	int found;
 
 	pci_enable_msi(pdev);
 	ret = pci_enable_device(pdev);
@@ -96,44 +140,9 @@ static int pci_amba_probe(struct pci_dev *pdev,
 	  map to fix things up.
 	*/
 	if (of_get_property(amba_node, "interrupts", NULL)) {
-		p = of_get_property(amba_bus, "interrupt-map", &len);
-		if (!p)
-			/* No amba bus interrupt-map property */
-			return -EINVAL;
-
-		newimap = devm_kzalloc(&pdev->dev, sizeof(*newimap),
-				       GFP_KERNEL);
-		if (!newimap)
-			return -ENOMEM;
-
-		newimap->name = kstrdup("interrupt-map", GFP_KERNEL);
-		if (!newimap->name)
-			return -ENOMEM;
-
-		newv = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
-		if (!newv) {
-			kfree(newimap->name);
-			return -ENOMEM;
-		}
-
-		newimap->value = newv;
-		newimap->length = len;
-		memcpy(newv, p, len);
-		for (ptr = newv, i = 0, found = 0;
-		     i < len/sizeof(u32);
-		     ptr += IMAP_ROW_LEN, i += IMAP_ROW_LEN) {
-			reg = of_get_property(amba_node, "reg", NULL);
-			if (ptr[0] == reg[0]) {
-				ptr[IMAP_ROW_LEN - 1] = cpu_to_be32(pdev->irq);
-				found = 1;
-				break;
-			}
-		}
-		if (!found) {
-			pr_err("Could not update amba irq\n");
-			return -EINVAL;
-		}
-		of_update_property(amba_bus, newimap);
+		ret = fixup_amba_irq(amba_node, amba_bus, pdev);
+		if (ret < 0)
+			return ret;
 	}
 
 	/* And finally create the amba device */
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 22/26] AMBA: pci-amba bridge: extend number of amba devs per pci device
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (20 preceding siblings ...)
  2013-08-07 10:21 ` [PATCH 21/26] AMBA: pci-amba bridge: improve code readability Davide Ciminaghi
@ 2013-08-07 10:21 ` Davide Ciminaghi
  2013-08-07 10:21 ` [PATCH 23/26] AMBA: pci-amba bridge: export function creating pci-amba device names Davide Ciminaghi
                   ` (5 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:21 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch makes it possible to create multiple AMBA devices
per PCI device (multiple AMBA devices on the same PCI bar, or
one/more AMBA devices referring to more than one PCI BAR).
This feature is needed to completely support the Connext chip,
which has, for instance, multiple devices on the same BAR
(former mfd device) and multiple devices on multiple PCI BARs
(6 msp ports, 2 ports per PCI BAR).

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 drivers/amba/pci-amba.c |  152 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 121 insertions(+), 31 deletions(-)

diff --git a/drivers/amba/pci-amba.c b/drivers/amba/pci-amba.c
index c825c7a..f272d38 100644
--- a/drivers/amba/pci-amba.c
+++ b/drivers/amba/pci-amba.c
@@ -25,9 +25,47 @@
 */
 #define IMAP_ROW_LEN (1 + 1 + 1 + 1 + 1)
 
-static int fixup_amba_irq(struct device_node *amba_node,
-			  struct device_node *amba_bus,
-			  struct pci_dev *pdev)
+static inline int resource_fits(struct resource *r1, struct resource *r2)
+{
+	return (r1->start >= r2->start) && (r1->end <= r2->end);
+}
+
+static const char *get_platform_prefix(struct pci_dev *pdev)
+{
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_STMICRO_ESRAM:
+		return "mmio";
+	case PCI_DEVICE_ID_STMICRO_GPIO:
+		return "gpio";
+	default:
+		return "pci-amba-platform";
+	}
+	return NULL;
+}
+
+static inline int is_platform_device(struct pci_dev *pdev)
+{
+	return pdev->device == PCI_DEVICE_ID_STMICRO_ESRAM ||
+		pdev->device == PCI_DEVICE_ID_STMICRO_GPIO ||
+		pdev->device == PCI_DEVICE_ID_STMICRO_VIC;
+}
+
+static int get_dev_name(char **name, struct pci_dev *pdev, int index)
+{
+	const char *prefix = is_platform_device(pdev) ?
+		get_platform_prefix(pdev) : "amba";
+	const char *core = dev_name(&pdev->dev);
+	*name = devm_kzalloc(&pdev->dev, strlen(core) + strlen(prefix) + 3,
+			     GFP_KERNEL);
+	if (!*name)
+		return -ENOMEM;
+	sprintf(*name, "%s-%s-%1d", prefix, core, index);
+	return 0;
+}
+
+static int fixup_irq(struct device_node *node,
+		     struct device_node *amba_bus,
+		     struct pci_dev *pdev)
 {
 	const void *p;
 	struct property *newimap;
@@ -59,7 +97,7 @@ static int fixup_amba_irq(struct device_node *amba_node,
 	memcpy(newv, p, len);
 	for (ptr = newv, i = 0, found = 0;
 	     i < len/sizeof(u32); ptr += IMAP_ROW_LEN, i += IMAP_ROW_LEN) {
-		reg = of_get_property(amba_node, "reg", NULL);
+		reg = of_get_property(node, "reg", NULL);
 		if (ptr[0] == reg[0]) {
 			ptr[IMAP_ROW_LEN - 1] = cpu_to_be32(pdev->irq);
 			found = 1;
@@ -77,10 +115,12 @@ static int fixup_amba_irq(struct device_node *amba_node,
 static int pci_amba_probe(struct pci_dev *pdev,
 			  const struct pci_device_id *id)
 {
-	struct amba_device *adev;
-	int ret;
+	struct amba_device **adev = NULL;
+	struct platform_device **platdev = NULL;
+	int ret, i, dncnt = 0;
+	void *drvdata;
 	struct device_node *n, *node, *pci_amba_bridge, *amba_bus = NULL,
-		*amba_node = NULL;
+		*dev_nodes[8];
 	char *name;
 
 	pci_enable_msi(pdev);
@@ -95,6 +135,8 @@ static int pci_amba_probe(struct pci_dev *pdev,
 	if (!node)
 		return -EINVAL;
 
+	memset(dev_nodes, 0, sizeof(dev_nodes));
+
 	/* Get a reference to the pci amba bridge (our pci parent) */
 	pci_amba_bridge = of_get_parent(node);
 	if (!pci_amba_bridge)
@@ -114,47 +156,93 @@ static int pci_amba_probe(struct pci_dev *pdev,
 		return -ENODEV;
 
 	/*
+	  Allocate an array of amba or platform devices pointers
+	*/
+	if (is_platform_device(pdev))
+		platdev = devm_kzalloc(&pdev->dev, sizeof(*platdev) * 8,
+				       GFP_KERNEL);
+	else
+		adev = devm_kzalloc(&pdev->dev, sizeof(*adev) * 8, GFP_KERNEL);
+	if (!adev && !platdev)
+		return -ENOMEM;
+
+	/*
 	   Now find out what the relevant amba device is by looking for
 	   a resource with the same initial address of this pci device's BAR0
 	*/
 	for_each_child_of_node(amba_bus, n) {
-		struct resource r;
-		if (of_address_to_resource(n, 0, &r))
+		struct resource r[8];
+		if (of_address_to_resource(n, 0, &r[dncnt]))
 			continue;
-		if (r.start == pdev->resource[0].start) {
-			amba_node = n;
-			break;
+		for (i = PCI_STD_RESOURCES; (i < PCI_STD_RESOURCE_END) &&
+			     (dncnt < ARRAY_SIZE(dev_nodes)); i++) {
+			if (resource_fits(&r[dncnt], &pdev->resource[i])) {
+				dev_nodes[dncnt++] = n;
+				break;
+			}
 		}
 	}
-	if (!amba_node)
+	if (!dncnt)
 		return -ENODEV;
 
-	/* Create a unique name for the device */
-	name = devm_kzalloc(&pdev->dev, strlen(dev_name(&pdev->dev)) + 6,
-			    GFP_KERNEL);
-	sprintf(name, "amba-%s", dev_name(&pdev->dev));
-
-	/*
-	  Since we're dealing with MSI IRQs, the value of a device's IRQ
-	  number is known at runtime only. Update the amba bus interrupt
-	  map to fix things up.
-	*/
-	if (of_get_property(amba_node, "interrupts", NULL)) {
-		ret = fixup_amba_irq(amba_node, amba_bus, pdev);
+	for (i = 0; i < dncnt && dev_nodes[i]; i++) {
+		/* Create a unique name for the device */
+		ret = get_dev_name(&name, pdev, i);
 		if (ret < 0)
 			return ret;
+		/*
+		  Since we're dealing with MSI IRQs, the value of a device's
+		  IRQ number is known at runtime only. Update the amba bus
+		  interrupt map property to fix things up.
+		*/
+		if (of_get_property(dev_nodes[i], "interrupts", NULL)) {
+			ret = fixup_irq(dev_nodes[i], amba_bus, pdev);
+			if (ret < 0)
+				return ret;
+		}
+		/* And finally create the amba or platform device */
+		if (is_platform_device(pdev)) {
+			platdev[i] = of_platform_device_create(dev_nodes[i],
+							       name, NULL);
+			continue;
+		}
+		adev[i] = of_amba_device_create(dev_nodes[i], name, NULL, NULL,
+						&pdev->resource[0]);
 	}
-
-	/* And finally create the amba device */
-	adev = of_amba_device_create(n, name, NULL, NULL, &pdev->resource[0]);
-	pci_set_drvdata(pdev, adev);
+	drvdata = is_platform_device(pdev) ? (void *)platdev : (void *)adev;
+	pci_set_drvdata(pdev, drvdata);
 	return 0;
 };
 
+static void platform_remove(void *__platdev)
+{
+	int i;
+	struct platform_device **platdev = __platdev;
+	for (i = 0; i < 8; i++) {
+		if (!platdev[i])
+			break;
+		platform_device_unregister(platdev[i]);
+	}
+}
+
+static void amba_remove(void *__ambadev)
+{
+	int i;
+	struct amba_device **ambadev = __ambadev;
+	for (i = 0; i < 8; i++) {
+		if (!ambadev[i])
+			break;
+		amba_device_unregister(ambadev[i]);
+	}
+}
+
 static void pci_amba_remove(struct pci_dev *pdev)
 {
-	struct amba_device *adev = pci_get_drvdata(pdev);
-	amba_device_unregister(adev);
+	void *drvdata = pci_get_drvdata(pdev);
+	if (is_platform_device(pdev))
+		platform_remove(drvdata);
+	else
+		amba_remove(drvdata);
 	pci_disable_msi(pdev);
 }
 
@@ -168,6 +256,8 @@ static DEFINE_PCI_DEVICE_TABLE(pci_amba_table) = {
 	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_SDIO)},
 	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_DMA)},
 	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_MSPS)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_ESRAM)},
+	{PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_GPIO)},
 	{0,}
 };
 
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 23/26] AMBA: pci-amba bridge: export function creating pci-amba device names
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (21 preceding siblings ...)
  2013-08-07 10:21 ` [PATCH 22/26] AMBA: pci-amba bridge: extend number of amba devs per pci device Davide Ciminaghi
@ 2013-08-07 10:21 ` Davide Ciminaghi
  2013-08-07 10:21 ` [PATCH 24/26] x86 STA2X11: add dts for Intel's Northville board Davide Ciminaghi
                   ` (4 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:21 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

pci_amba_get_dev_name() will be used by the sta2x11 common clock framework
to register clkdevs with the same name as the corresponding amba or
platform device.

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 drivers/amba/pci-amba.c  |   14 ++++++++++++++
 include/linux/pci-amba.h |   42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/pci-amba.h

diff --git a/drivers/amba/pci-amba.c b/drivers/amba/pci-amba.c
index f272d38..1beeefd 100644
--- a/drivers/amba/pci-amba.c
+++ b/drivers/amba/pci-amba.c
@@ -9,6 +9,7 @@
 #include <linux/amba/bus.h>
 #include <linux/pci.h>
 #include <linux/pci_ids.h>
+#include <linux/pci-amba.h>
 #include <linux/slab.h>
 #include <linux/irq.h>
 #include <linux/sizes.h>
@@ -25,6 +26,8 @@
 */
 #define IMAP_ROW_LEN (1 + 1 + 1 + 1 + 1)
 
+static const struct pci_device_id pci_amba_table[];
+
 static inline int resource_fits(struct resource *r1, struct resource *r2)
 {
 	return (r1->start >= r2->start) && (r1->end <= r2->end);
@@ -63,6 +66,17 @@ static int get_dev_name(char **name, struct pci_dev *pdev, int index)
 	return 0;
 }
 
+int pci_amba_get_dev_name(char **name, struct pci_dev *pdev, int index)
+{
+	/* Check whether the device is a pci-amba one */
+	if (!pci_match_id(pci_amba_table, pdev))
+		return -ENODEV;
+	if (!name)
+		return -EINVAL;
+	return get_dev_name(name, pdev, index);
+}
+EXPORT_SYMBOL(pci_amba_get_dev_name);
+
 static int fixup_irq(struct device_node *node,
 		     struct device_node *amba_bus,
 		     struct pci_dev *pdev)
diff --git a/include/linux/pci-amba.h b/include/linux/pci-amba.h
new file mode 100644
index 0000000..913624e
--- /dev/null
+++ b/include/linux/pci-amba.h
@@ -0,0 +1,42 @@
+/*
+ * PCI-AMBA Helpers
+ *
+ * Copyright 2012 ST Microelectronics (Alessandro Rubini, Davide Ciminaghi)
+ *
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#ifndef _PCI_AMBA_H
+#define _PCI_AMBA_H
+
+#include <linux/of.h>
+
+/*
+ * pci_amba_get_dev_name: allocate and fill in a buffer with a suitable
+ * name for a pci-amba device.
+ *
+ * @name: pointer to a location where the address of the allocated buffer
+ * shall be stored.
+ * @pdev: pointer to the corresponding pci device.
+ * @index: index of device (in case of more than one amba/platform device
+ * per pci device).
+ *
+ */
+extern int pci_amba_get_dev_name(char **name, struct pci_dev *pdev, int index);
+
+#endif /* _PCI_AMBA_H */
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 24/26] x86 STA2X11: add dts for Intel's Northville board
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (22 preceding siblings ...)
  2013-08-07 10:21 ` [PATCH 23/26] AMBA: pci-amba bridge: export function creating pci-amba device names Davide Ciminaghi
@ 2013-08-07 10:21 ` Davide Ciminaghi
  2013-08-07 10:21 ` [PATCH 25/26] drivers/clk: sta2x11 common clock framework implementation Davide Ciminaghi
                   ` (3 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:21 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

The base for this dts was automatically generated to avoid typos, most
of all in ranges and interrupt-map properties.
It was then hand-edited to add some details (for instance mmci1 gpio's).
This dts is still incomplete. Yet, it contains most of the
pci-amba devices and allows a northville board to boot with a serial
console on /dev/ttyAMA1. A shell is also working on the same UART
(interrupts are OK for UART's and apparently for most of the other

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/platform/sta2x11/northville.dts |  941 ++++++++++++++++++++++++++++++
 1 files changed, 941 insertions(+), 0 deletions(-)
 create mode 100644 arch/x86/platform/sta2x11/northville.dts

diff --git a/arch/x86/platform/sta2x11/northville.dts b/arch/x86/platform/sta2x11/northville.dts
new file mode 100644
index 0000000..b41c499
--- /dev/null
+++ b/arch/x86/platform/sta2x11/northville.dts
@@ -0,0 +1,941 @@
+/dts-v1/;
+/ {
+	compatible =  "intel,northville" ;
+	#address-cells = < 1 >;
+	#size-cells = < 1 >;
+	cpus@0 {
+		#address-cells = < 1 >;
+		#size-cells = < 0 >;
+		cpu@0 {
+			compatible =  "intel,e6600-cpu" ;
+			reg = < 0x00000000  >;
+
+		};
+
+	};
+	soc@2 {
+		compatible =  "intel,e6600-soc" ;
+		#address-cells = < 1 >;
+		#size-cells = < 1 >;
+		ranges;
+		pci@cf8 {
+			compatible =  "pci" ;
+			device_type =  "pci" ;
+			#address-cells = < 3 >;
+			#size-cells = < 2 >;
+			reg = < 0x00000cf8    0x00000008  >;
+			ranges = < 0x02000000    0x00000000    0x000a0000    0x000a0000    0x00000000    0x00020000
+				 0x02000000    0x00000000    0x40000000    0x40000000    0x00000000    0xc0000000  >;
+			bus-range = < 0x00000000    0x00000000  >;
+			/* pci host bridge, bus = 0, dev = 0, function = 0 ; */
+			/* name = Atom Processor E6xx PCI Host Bridge #1 */
+			pci@00000000 {
+				compatible =  "pci8086,4114.5",
+					"pci8086,4114",
+					"pciclass060000",
+					"pciclass0600" ;
+				reg = < 0x00000000    0x00000000    0x00000000    0x00000000    0x00000100  >;
+				device_type =  "pci" ;
+
+			};
+			/* pci host bridge, bus = 0, dev = 1, function = 0 ; */
+			/* name = Atom Processor E6xx Configuration Unit */
+			pci@00000800 {
+				compatible =  "pci8086,8183.2",
+					"pci8086,8183",
+					"pciclass060000",
+					"pciclass0600" ;
+				reg = < 0x00000800    0x00000000    0x00000000    0x00000000    0x00000100  >;
+				device_type =  "pci" ;
+
+			};
+			/* pci device, bus = 0, dev = 2, function = 0 ; */
+			/* name = Atom Processor E6xx Integrated Graphics Controller */
+			pci@02001000 {
+				compatible =  "pci8086,4108.5",
+					"pci8086,4108",
+					"pciclass030000",
+					"pciclass0300" ;
+				reg = < 0x02001000    0x00000000    0xd2a00000    0x00000000    0x00100000
+					 0x01001000    0x00000000    0x0000f010    0x00000000    0x00000008
+					 0x02001000    0x00000000    0xb0000000    0x00000000    0x10000000
+					 0x02001000    0x00000000    0xd2bc0000    0x00000000    0x00040000  >;
+				device_type =  "pci" ;
+
+			};
+			/* pci device, bus = 0, dev = 3, function = 0 ; */
+			/* name = Atom Processor E6xx Integrated Graphics Controller */
+			pci@02001800 {
+				compatible =  "pci8086,8182.2",
+					"pci8086,8182",
+					"pciclass040000",
+					"pciclass0400" ;
+				reg = < 0x02001800    0x00000000    0xd2b00000    0x00000000    0x00080000
+					 0x01001800    0x00000000    0x0000f000    0x00000000    0x00000008
+					 0x02001800    0x00000000    0xa0000000    0x00000000    0x10000000
+					 0x02001800    0x00000000    0xd2b80000    0x00000000    0x00040000  >;
+				device_type =  "pci" ;
+
+			};
+			/* pci-pci bridge, bus = 0, dev = 23, function = 0 ; */
+			/* name = Atom Processor E6xx PCI Express Port 1 */
+			pci@0000b800 {
+				compatible =  "pci8086,8184.2",
+					"pci8086,8184",
+					"pciclass060400",
+					"pciclass0604" ;
+				reg = < 0x0000b800    0x00000000    0x00000000    0x00000000    0x00000100  >;
+				device_type =  "pci" ;
+				#address-cells = < 3 >;
+				#size-cells = < 2 >;
+				bus-range = < 0x00000001    0x00000006  >;
+				ranges = < 0x0200b800    0x00000000    0xc0000000    0x02000000    0x00000000    0xc0000000    0x00000000    0x12900000  >;
+				/* pci-pci bridge, bus = 1, dev = 0, function = 0 ; */
+				/* name = Device cc17 */
+				pci@00010000 {
+					compatible =  "pci104a,cc17.0",
+						"pci104a,cc17",
+						"pciclass060400",
+						"pciclass0604" ;
+					reg = < 0x00010000    0x00000000    0x00000000    0x00000000    0x00000100  >;
+					device_type =  "pci" ;
+					interrupt-parent = <&msi>;
+					#interrupt-cells = <1>;
+
+					#address-cells = < 3 >;
+					#size-cells = < 2 >;
+					bus-range = < 0x00000002    0x00000006  >;
+					ranges = < 0x02010000    0x00000000    0xc0000000    0x0200b800    0x00000000    0xc0000000    0x00000000    0x12900000  >;
+					/* pci-pci bridge, bus = 2, dev = 0, function = 0 ; */
+					/* name = Device cc18 */
+					pci@00020000 {
+						compatible =  "pci104a,cc18.0",
+							"pci104a,cc18",
+							"pciclass060400",
+							"pciclass0604" ;
+						reg = < 0x00020000    0x00000000    0x00000000    0x00000000    0x00000100  >;
+						device_type =  "pci" ;
+						#address-cells = < 3 >;
+						#size-cells = < 2 >;
+						bus-range = < 0x00000003    0x00000003  >;
+						ranges = < 0x02020000    0x00000000    0xca800000    0x02010000    0x00000000    0xca800000    0x00000000    0x04000000  >;
+						/* pci device, bus = 3, dev = 0, function = 0 ; */
+						/* name = Device cc0c */
+						pci@02030000 {
+							compatible =  "pci104a,cc0c.0",
+								"pci104a,cc0c",
+								"pciclass088000",
+								"pciclass0880" ;
+							reg = < 0x02030000    0x00000000    0xce400000    0x00000000    0x00400000
+								 0x02030000    0x00000000    0xce000000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 3, dev = 0, function = 1 ; */
+						/* name = Device cc01 */
+						pci@02030100 {
+							compatible =  "pci104a,cc01.0",
+								"pci104a,cc01",
+								"pciclass0c0380",
+								"pciclass0c03" ;
+							reg = < 0x02030100    0x00000000    0xcdc00000    0x00000000    0x00400000
+								 0x02030100    0x00000000    0xcd800000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 3, dev = 0, function = 2 ; */
+						/* name = Connext usb host controller */
+						pci@02030200 {
+							compatible =  "pci104a,cc00.0",
+								"pci104a,cc00",
+								"pciclass0c0380",
+								"pciclass0c03" ;
+							reg = < 0x02030200    0x00000000    0xcd400000    0x00000000    0x00400000
+								 0x02030200    0x00000000    0xcd000000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 3, dev = 0, function = 3 ; */
+						/* name = Device cc02 */
+						pci@02030300 {
+							compatible =  "pci104a,cc02.0",
+								"pci104a,cc02",
+								"pciclass0c0380",
+								"pciclass0c03" ;
+							reg = < 0x02030300    0x00000000    0xccc00000    0x00000000    0x00400000
+								 0x02030300    0x00000000    0xcc800000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 3, dev = 0, function = 4 ; */
+						/* name = Device cc05 */
+						pci@02030400 {
+							compatible =  "pci104a,cc05.0",
+								"pci104a,cc05",
+								"pciclass080100",
+								"pciclass0801" ;
+							reg = < 0x02030400    0x00000000    0xcc400000    0x00000000    0x00400000
+								 0x02030400    0x00000000    0xcc000000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 3, dev = 0, function = 5 ; */
+						/* name = Device cc03 */
+						pci@02030500 {
+							compatible =  "pci104a,cc03.0",
+								"pci104a,cc03",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02030500    0x00000000    0xcbc00000    0x00000000    0x00400000
+								 0x02030500    0x00000000    0xcb800000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 3, dev = 0, function = 6 ; */
+						/* name = Device cc03 */
+						pci@02030600 {
+							compatible =  "pci104a,cc03.0",
+								"pci104a,cc03",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02030600    0x00000000    0xcb400000    0x00000000    0x00400000
+								 0x02030600    0x00000000    0xcb000000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 3, dev = 0, function = 7 ; */
+						/* name = Device cc04 */
+						pci@02030700 {
+							compatible =  "pci104a,cc04.0",
+								"pci104a,cc04",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02030700    0x00000000    0xcac00000    0x00000000    0x00400000
+								 0x02030700    0x00000000    0xca800000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						amba@00020000 {
+							compatible =  "arm,amba-bus" ;
+							#address-cells = < 1 >;
+							#size-cells = < 1 >;
+							#interrupt-cells = < 1 >;
+							interrupt-map = < 0x50000000    0xffffffff    &msi    0xfee03000    0x00000000
+								 0x54005000    0x0000001f    &msi    0xfee03000    0x00000000
+								 0x54006000    0x00000020    &msi    0xfee03000    0x00000000
+								 0x54007000    0x00000021    &msi    0xfee03000    0x00000000
+								 0x54008000    0x00000022    &msi    0xfee03000    0x00000000
+								 0x54009000    0xffffffff    &msi    0xfee03000    0x00000000
+								 0x5400a000    0xffffffff    &msi    0xfee03000    0x00000000
+								 0x13000000    0x00000001    &msi    0xfee03000    0x00000000
+								 0x5c000000    0x0000001b    &msi    0xfee03000    0x00000000
+								 0x5c001000    0x0000001c    &msi    0xfee03000    0x00000000
+								 0x5c002000    0x0000001d    &msi    0xfee03000    0x00000000  >;
+							ranges = < 0x50000000    0x02030000    0x00000000    0xce000000    0x00001000
+								 0x54005000    0x02030000    0x00000000    0xce400000    0x00001000
+								 0x54006000    0x02030000    0x00000000    0xce401000    0x00001000
+								 0x54007000    0x02030000    0x00000000    0xce402000    0x00001000
+								 0x54008000    0x02030000    0x00000000    0xce403000    0x00001000
+								 0x54009000    0x02030000    0x00000000    0xce404000    0x00001000
+								 0x5400a000    0x02030000    0x00000000    0xce405000    0x00001000
+								 0x13000000    0x02030400    0x00000000    0xcc400000    0x00001000
+								 0x5c000000    0x02030500    0x00000000    0xcbc00000    0x00001000
+								 0x5c001000    0x02030600    0x00000000    0xcb400000    0x00001000
+								 0x5c002000    0x02030700    0x00000000    0xcac00000    0x00001000  >;
+							soc_dma_0: dma-controller@13000000 {
+								compatible =  "stericsson,pl080-nomadik",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x00280080  >;
+								reg = < 0x13000000    0x00001000  >;
+								interrupts = < 0x00000001  >;
+
+							};
+							apb_regs_0: apb-regs@50000000 {
+								compatible =  "st,sta2x11-apb-regs" ;
+								reg = < 0x50000000    0x00010000  >;
+
+							};
+							gpio0_0: gpio@54005000 {
+								compatible =  "st,nomadik-gpio" ;
+								reg = < 0x54005000    0x00001000  >;
+								interrupts = < 0x0000001f  >;
+								interrupt-controller;
+								#interrupt-cells = < 2 >;
+								gpio-controller;
+								#gpio-cells = < 2 >;
+								gpio-bank = < 0 >;
+
+							};
+							gpio1_0: gpio@54006000 {
+								compatible =  "st,nomadik-gpio" ;
+								reg = < 0x54006000    0x00001000  >;
+								interrupts = < 0x00000020  >;
+								interrupt-controller;
+								#interrupt-cells = < 2 >;
+								gpio-controller;
+								#gpio-cells = < 2 >;
+								gpio-bank = < 1 >;
+
+							};
+							gpio2_0: gpio@54007000 {
+								compatible =  "st,nomadik-gpio" ;
+								reg = < 0x54007000    0x00001000  >;
+								interrupts = < 0x00000021  >;
+								interrupt-controller;
+								#interrupt-cells = < 2 >;
+								gpio-controller;
+								#gpio-cells = < 2 >;
+								gpio-bank = < 2 >;
+
+							};
+							gpio3_0: gpio@54008000 {
+								compatible =  "st,nomadik-gpio" ;
+								reg = < 0x54008000    0x00001000  >;
+								interrupts = < 0x00000022  >;
+								interrupt-controller;
+								#interrupt-cells = < 2 >;
+								gpio-controller;
+								#gpio-cells = < 2 >;
+								gpio-bank = < 3 >;
+
+							};
+							pinctrl {
+								compatible = "stericsson,nmk-pinctrl-sta2x11";
+								/* Pin configurations */
+								sdio1_default_mux: sdio1_mux {
+								       ste,function = "sdio1";
+								       ste,pins = "sdio1_a_1";
+								};
+								sdio1_default_mode: sdio1_mode {
+										    mmcsd_default_cfg1 {
+												       /* CD, WP */
+												       ste,pins = "GPIO124_J5",
+												       "GPIO123_J4";
+												       /* inputs with no pull up ? */
+												       ste,input = <0>;
+										     };
+										     mmcsd_default_cfg2 {
+												       /* PWR */
+												       ste,pins = "GPIO121_J3";
+												       /* output ? */
+												       ste,output = <2>;
+										     };
+									};
+							};
+							sctl_0: sctl@54009000 {
+								compatible =  "st,sta2x11-sctl" ;
+								reg = < 0x54009000    0x00001000  >;
+
+							};
+							scr_0: scr@5400a000 {
+								compatible =  "st,sta2x11-scr" ;
+								reg = < 0x5400a000    0x00001000  >;
+
+							};
+							uart0_0: serial@5c000000 {
+								compatible =  "stericsson,pl011",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x00380802  >;
+								reg = < 0x5c000000    0x00001000  >;
+								interrupts = < 0x0000001b  >;
+
+							};
+							uart1_0: serial@5c001000 {
+								compatible =  "stericsson,pl011",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x00380802  >;
+								reg = < 0x5c001000    0x00001000  >;
+								interrupts = < 0x0000001c  >;
+
+							};
+							uart2_0: serial@5c002000 {
+								compatible =  "stericsson,pl011",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x00380802  >;
+								reg = < 0x5c002000    0x00001000  >;
+								interrupts = < 0x0000001d  >;
+
+							};
+
+						};
+
+					};
+					/* pci-pci bridge, bus = 2, dev = 1, function = 0 ; */
+					/* name = Device cc18 */
+					pci@00020800 {
+						compatible =  "pci104a,cc18.0",
+							"pci104a,cc18",
+							"pciclass060400",
+							"pciclass0604" ;
+						reg = < 0x00020800    0x00000000    0x00000000    0x00000000    0x00000100  >;
+						device_type =  "pci" ;
+						#address-cells = < 3 >;
+						#size-cells = < 2 >;
+						bus-range = < 0x00000004    0x00000004  >;
+						ranges = < 0x02020800    0x00000000    0xcec00000    0x02010000    0x00000000    0xcec00000    0x00000000    0x03d00000  >;
+						/* pci device, bus = 4, dev = 0, function = 0 ; */
+						/* name = Device cc06 */
+						pci@02040000 {
+							compatible =  "pci104a,cc06.0",
+								"pci104a,cc06",
+								"pciclass010600",
+								"pciclass0106" ;
+							reg = < 0x02040000    0x00000000    0xd2400000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 4, dev = 0, function = 1 ; */
+						/* name = Device cc07 */
+						pci@02040100 {
+							compatible =  "pci104a,cc07.0",
+								"pci104a,cc07",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02040100    0x00000000    0xd2000000    0x00000000    0x00400000
+								 0x02040100    0x00000000    0xd1c00000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 4, dev = 0, function = 2 ; */
+						/* name = Device cc07 */
+						pci@02040200 {
+							compatible =  "pci104a,cc07.0",
+								"pci104a,cc07",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02040200    0x00000000    0xd1800000    0x00000000    0x00400000
+								 0x02040200    0x00000000    0xd1400000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 4, dev = 0, function = 3 ; */
+						/* name = Device cc07 */
+						pci@02040300 {
+							compatible =  "pci104a,cc07.0",
+								"pci104a,cc07",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02040300    0x00000000    0xd1000000    0x00000000    0x00400000
+								 0x02040300    0x00000000    0xd0c00000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 4, dev = 0, function = 4 ; */
+						/* name = Device cc07 */
+						pci@02040400 {
+							compatible =  "pci104a,cc07.0",
+								"pci104a,cc07",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02040400    0x00000000    0xd0800000    0x00000000    0x00400000
+								 0x02040400    0x00000000    0xd0400000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 4, dev = 0, function = 5 ; */
+						/* name = Device cc04 */
+						pci@02040500 {
+							compatible =  "pci104a,cc04.0",
+								"pci104a,cc04",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02040500    0x00000000    0xd0000000    0x00000000    0x00400000
+								 0x02040500    0x00000000    0xcfc00000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 4, dev = 0, function = 6 ; */
+						/* name = Device cc14 */
+						pci@02040600 {
+							compatible =  "pci104a,cc14.0",
+								"pci104a,cc14",
+								"pciclass088000",
+								"pciclass0880" ;
+							reg = < 0x02040600    0x00000000    0xcf800000    0x00000000    0x00400000
+								 0x02040600    0x00000000    0xcf400000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 4, dev = 0, function = 7 ; */
+						/* name = Device cc12 */
+						pci@02040700 {
+							compatible =  "pci104a,cc12.0",
+								"pci104a,cc12",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02040700    0x00000000    0xcf000000    0x00000000    0x00400000
+								 0x02040700    0x00000000    0xcec00000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						amba@00020800 {
+							compatible =  "arm,amba-bus" ;
+							#address-cells = < 1 >;
+							#size-cells = < 1 >;
+							#interrupt-cells = < 1 >;
+							interrupt-map = < 0x5c003000    0x0000001e    &msi    0xfee03000    0x00000000  >;
+							ranges = < 0x5c003000    0x02040500    0x00000000    0xd0000000    0x00001000  >;
+							uart3_0: serial@5c003000 {
+								compatible =  "stericsson,pl011",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x00380802  >;
+								reg = < 0x5c003000    0x00001000  >;
+								interrupts = < 0x0000001e  >;
+
+							};
+
+						};
+
+					};
+					/* pci-pci bridge, bus = 2, dev = 2, function = 0 ; */
+					/* name = Device cc18 */
+					pci@00021000 {
+						compatible =  "pci104a,cc18.0",
+							"pci104a,cc18",
+							"pciclass060400",
+							"pciclass0604" ;
+						reg = < 0x00021000    0x00000000    0x00000000    0x00000000    0x00000100  >;
+						device_type =  "pci" ;
+						#address-cells = < 3 >;
+						#size-cells = < 2 >;
+						bus-range = < 0x00000005    0x00000005  >;
+						ranges = < 0x02021000    0x00000000    0xc6400000    0x02010000    0x00000000    0xc6400000    0x00000000    0x04000000  >;
+						/* pci device, bus = 5, dev = 0, function = 0 ; */
+						/* name = Device cc16 */
+						pci@02050000 {
+							compatible =  "pci104a,cc16.0",
+								"pci104a,cc16",
+								"pciclass088000",
+								"pciclass0880" ;
+							reg = < 0x02050000    0x00000000    0xca000000    0x00000000    0x00400000
+								 0x02050000    0x00000000    0xc9c00000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 5, dev = 0, function = 1 ; */
+						/* name = Device cc0a */
+						pci@02050100 {
+							compatible =  "pci104a,cc0a.0",
+								"pci104a,cc0a",
+								"pciclass088000",
+								"pciclass0880" ;
+							reg = < 0x02050100    0x00000000    0xc9800000    0x00000000    0x00400000
+								 0x02050100    0x00000000    0xc9400000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 5, dev = 0, function = 2 ; */
+						/* name = Device cc0b */
+						pci@02050200 {
+							compatible =  "pci104a,cc0b.0",
+								"pci104a,cc0b",
+								"pciclass088000",
+								"pciclass0880" ;
+							reg = < 0x02050200    0x00000000    0xc9000000    0x00000000    0x00400000
+								 0x02050200    0x00000000    0xc8c00000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 5, dev = 0, function = 3 ; */
+						/* name = Device cc0b */
+						pci@02050300 {
+							compatible =  "pci104a,cc0b.0",
+								"pci104a,cc0b",
+								"pciclass088000",
+								"pciclass0880" ;
+							reg = < 0x02050300    0x00000000    0xc8800000    0x00000000    0x00400000
+								 0x02050300    0x00000000    0xc8400000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 5, dev = 0, function = 4 ; */
+						/* name = Device cc0b */
+						pci@02050400 {
+							compatible =  "pci104a,cc0b.0",
+								"pci104a,cc0b",
+								"pciclass088000",
+								"pciclass0880" ;
+							reg = < 0x02050400    0x00000000    0xc8000000    0x00000000    0x00400000
+								 0x02050400    0x00000000    0xc7c00000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 5, dev = 0, function = 5 ; */
+						/* name = Device cc15 */
+						pci@02050500 {
+							compatible =  "pci104a,cc15.0",
+								"pci104a,cc15",
+								"pciclass088000",
+								"pciclass0880" ;
+							reg = < 0x02050500    0x00000000    0xc7800000    0x00000000    0x00400000
+								 0x02050500    0x00000000    0xc7400000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 5, dev = 0, function = 6 ; */
+						/* name = Device cc09 */
+						pci@02050600 {
+							compatible =  "pci104a,cc09.0",
+								"pci104a,cc09",
+								"pciclass020000",
+								"pciclass0200" ;
+							reg = < 0x02050600    0x00000000    0xc7000000    0x00000000    0x00400000
+								 0x02050600    0x00000000    0xc6c00000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 5, dev = 0, function = 7 ; */
+						/* name = Device cc11 */
+						pci@02050700 {
+							compatible =  "pci104a,cc11.0",
+								"pci104a,cc11",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02050700    0x00000000    0xc6800000    0x00000000    0x00400000
+								 0x02050700    0x00000000    0xc6400000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						amba@00021000 {
+							compatible =  "arm,amba-bus" ;
+							#address-cells = < 1 >;
+							#size-cells = < 1 >;
+							#interrupt-cells = < 1 >;
+							interrupt-map = < 0x5800b000    0xffffffff    &msi    0xfee03000    0x00000000
+								 0x54001000    0x00000010    &msi    0xfee03000    0x00000000
+								 0x54000000    0x00000011    &msi    0xfee03000    0x00000000
+								 0x58004000    0x00000012    &msi    0xfee03000    0x00000000
+								 0x5c004000    0x00000013    &msi    0xfee03000    0x00000000
+								 0x80000000    0xffffffff    &msi    0xfee03000    0x00000000  >;
+							ranges = < 0x5800b000    0x02050000    0x00000000    0xc9c00000    0x00001000
+								 0x54001000    0x02050100    0x00000000    0xc9800000    0x00001000
+								 0x54000000    0x02050200    0x00000000    0xc9000000    0x00001000
+								 0x58004000    0x02050300    0x00000000    0xc8800000    0x00001000
+								 0x5c004000    0x02050400    0x00000000    0xc8000000    0x00001000
+								 0x80000000    0x02050500    0x00000000	   0xc7800000    0x00010000 >;
+							sdio1_0: mmc@54000000 {
+								compatible =  "stericsson, pl180-ux500v2",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x10480180  >;
+								reg = < 0x54000000    0x00001000  >;
+								interrupts = < 0x00000011  >;
+								bus-width=<4>;
+								/* Test at 2MHz */
+								max-frequency=<2000000>;
+								/* CD -> GPIO 124 -> GPIO3 PIN 28 */
+								cd-gpios = <&gpio3_0 28 0x1>;
+								cd-inverted;
+								/* WP -> GPIO 123 -> GPIO3 PIN 27 */
+								wp-gpios = <&gpio3_0 27 0>;
+								wp-inverted;
+								pinctrl-names = "default";
+								pinctrl-0 = <&sdio1_default_mux>, <&sdio1_default_mode>;
+							};
+							sdio0_0: mmc@54001000 {
+								compatible =  "stericsson, pl180-ux500v2",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x10480180  >;
+								reg = < 0x54001000    0x00001000  >;
+								interrupts = < 0x00000010  >;
+
+							};
+							sdio2_0: mmc@58004000 {
+								compatible =  "stericsson, pl180-ux500v2",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x10480180  >;
+								reg = < 0x58004000    0x00001000  >;
+								interrupts = < 0x00000012  >;
+
+							};
+							apb_soc_regs_0: apb-soc-regs@5800b000 {
+								compatible =  "st,sta2x11-apb-soc-regs" ;
+								reg = < 0x5800b000    0x00001000  >;
+
+							};
+							sdio3_0: mmc@5c004000 {
+								compatible =  "stericsson, pl180-ux500v2",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x10480180  >;
+								reg = < 0x5c004000    0x00001000  >;
+								interrupts = < 0x00000013  >;
+
+							};
+							esram_0: esram@80000000 {
+								compatible =  "mmio-sram" ;
+								reg = < 0x80000000    0x00010000  >;
+
+							};
+
+						};
+
+					};
+					/* pci-pci bridge, bus = 2, dev = 3, function = 0 ; */
+					/* name = Device cc18 */
+					pci@00021800 {
+						compatible =  "pci104a,cc18.0",
+							"pci104a,cc18",
+							"pciclass060400",
+							"pciclass0604" ;
+						reg = < 0x00021800    0x00000000    0x00000000    0x00000000    0x00000100  >;
+						device_type =  "pci" ;
+						#address-cells = < 3 >;
+						#size-cells = < 2 >;
+						bus-range = < 0x00000006    0x00000006  >;
+						ranges = < 0x02021800    0x00000000    0xc0000000    0x02010000    0x00000000    0xc0000000    0x00000000    0x06000000  >;
+						/* pci device, bus = 6, dev = 0, function = 0 ; */
+						/* name = Device cc0d */
+						pci@02060000 {
+							compatible =  "pci104a,cc0d.0",
+								"pci104a,cc0d",
+								"pciclass040000",
+								"pciclass0400" ;
+							reg = < 0x02060000    0x00000000    0xc5c00000    0x00000000    0x00400000
+								 0x02060000    0x00000000    0xc5800000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 6, dev = 0, function = 1 ; */
+						/* name = Device cc13 */
+						pci@02060100 {
+							compatible =  "pci104a,cc13.0",
+								"pci104a,cc13",
+								"pciclass038000",
+								"pciclass0380" ;
+							reg = < 0x02060100    0x00000000    0xc5400000    0x00000000    0x00400000
+								 0x02060100    0x00000000    0xc5000000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 6, dev = 0, function = 2 ; */
+						/* name = Device cc08 */
+						pci@02060200 {
+							compatible =  "pci104a,cc08.0",
+								"pci104a,cc08",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02060200    0x00000000    0xc4c00000    0x00000000    0x00400000
+								 0x02060200    0x00000000    0xc4800000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 6, dev = 0, function = 3 ; */
+						/* name = Device cc08 */
+						pci@02060300 {
+							compatible =  "pci104a,cc08.0",
+								"pci104a,cc08",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02060300    0x00000000    0xc4400000    0x00000000    0x00400000
+								 0x02060300    0x00000000    0xc4000000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 6, dev = 0, function = 4 ; */
+						/* name = Device cc08 */
+						pci@02060400 {
+							compatible =  "pci104a,cc08.0",
+								"pci104a,cc08",
+								"pciclass070000",
+								"pciclass0700" ;
+							reg = < 0x02060400    0x00000000    0xc3c00000    0x00000000    0x00400000
+								 0x02060400    0x00000000    0xc3800000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 6, dev = 0, function = 5 ; */
+						/* name = Device cc0e */
+						pci@02060500 {
+							compatible =  "pci104a,cc0e.0",
+								"pci104a,cc0e",
+								"pciclass080100",
+								"pciclass0801" ;
+							reg = < 0x02060500    0x00000000    0xc3400000    0x00000000    0x00400000
+								 0x02060500    0x00000000    0xc3000000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 6, dev = 0, function = 6 ; */
+						/* name = Device cc0f */
+						pci@02060600 {
+							compatible =  "pci104a,cc0f.0",
+								"pci104a,cc0f",
+								"pciclass040100",
+								"pciclass0401" ;
+							reg = < 0x02060600    0x00000000    0xc2c00000    0x00000000    0x00400000
+								 0x02060600    0x00000000    0xc2800000    0x00000000    0x00400000
+								 0x02060600    0x00000000    0xc2400000    0x00000000    0x00400000
+								 0x02060600    0x00000000    0xc2000000    0x00000000    0x00400000
+								 0x02060600    0x00000000    0xc1c00000    0x00000000    0x00400000
+								 0x02060600    0x00000000    0xc1800000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						/* pci device, bus = 6, dev = 0, function = 7 ; */
+						/* name = Device cc10 */
+						pci@02060700 {
+							compatible =  "pci104a,cc10.0",
+								"pci104a,cc10",
+								"pciclass040100",
+								"pciclass0401" ;
+							reg = < 0x02060700    0x00000000    0xc1400000    0x00000000    0x00400000
+								 0x02060700    0x00000000    0xc1000000    0x00000000    0x00400000
+								 0x02060700    0x00000000    0xc0c00000    0x00000000    0x00400000
+								 0x02060700    0x00000000    0xc0800000    0x00000000    0x00400000
+								 0x02060700    0x00000000    0xc0400000    0x00000000    0x00400000
+								 0x02060700    0x00000000    0xc0000000    0x00000000    0x00400000  >;
+							device_type =  "pci" ;
+
+						};
+						amba@00021800 {
+							compatible =  "arm,amba-bus" ;
+							#address-cells = < 1 >;
+							#size-cells = < 1 >;
+							#interrupt-cells = < 1 >;
+							interrupt-map = < 0x54002000    0x0000000e    &msi    0xfee03000    0x00000000
+								 0x54003000    0x0000000f    &msi    0xfee03000    0x00000000
+								 0x54004000    0x00000010    &msi    0xfee03000    0x00000000
+								 0x30000000    0x00000011    &msi    0xfee03000    0x00000000  >;
+							ranges = < 0x54002000    0x02060200    0x00000000    0xc4c00000    0x00001000
+								 0x54003000    0x02060300    0x00000000    0xc4400000    0x00001000
+								 0x54004000    0x02060400    0x00000000    0xc3c00000    0x00001000
+								 0x30000000    0x02060500    0x00000000    0xc3400000    0x00001000  >;
+							audio_dma_0: dma-controller@30000000 {
+								compatible =  "stericsson,pl080-nomadik",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x00280080  >;
+								reg = < 0x30000000    0x00001000  >;
+								interrupts = < 0x00000007  >;
+
+							};
+							spi0_0: ssp@54002000 {
+								compatible =  "stericsson,pl023",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x00080023  >;
+								reg = < 0x54002000    0x00001000  >;
+								interrupts = < 0x0000000e  >;
+
+							};
+							spi1_0: ssp@54003000 {
+								compatible =  "stericsson,pl023",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x00080023  >;
+								reg = < 0x54003000    0x00001000  >;
+								interrupts = < 0x0000000f  >;
+
+							};
+							spi2_0: ssp@54004000 {
+								compatible =  "stericsson,pl023",
+									"arm,primecell" ;
+								arm,primecell-periphid = < 0x00080023  >;
+								reg = < 0x54004000    0x00001000  >;
+								interrupts = < 0x00000010  >;
+
+							};
+
+						};
+
+					};
+
+				};
+
+			};
+			/* pci-pci bridge, bus = 0, dev = 24, function = 0 ; */
+			/* name = Atom Processor E6xx PCI Express Port 2 */
+			pci@0000c000 {
+				compatible =  "pci8086,8185.2",
+					"pci8086,8185",
+					"pciclass060400",
+					"pciclass0604" ;
+				reg = < 0x0000c000    0x00000000    0x00000000    0x00000000    0x00000100  >;
+				device_type =  "pci" ;
+				#address-cells = < 3 >;
+				#size-cells = < 2 >;
+				bus-range = < 0x00000007    0x00000007  >;
+				ranges = < 0x0200c000    0x00000000    0x40800000    0x02000000    0x00000000    0x40800000    0x00000000    0x00200000  >;
+
+			};
+			/* pci-pci bridge, bus = 0, dev = 25, function = 0 ; */
+			/* name = Atom Processor E6xx PCI Express Port 3 */
+			pci@0000c800 {
+				compatible =  "pci8086,8180.2",
+					"pci8086,8180",
+					"pciclass060400",
+					"pciclass0604" ;
+				reg = < 0x0000c800    0x00000000    0x00000000    0x00000000    0x00000100  >;
+				device_type =  "pci" ;
+				#address-cells = < 3 >;
+				#size-cells = < 2 >;
+				bus-range = < 0x00000008    0x00000008  >;
+				ranges = < 0x0200c800    0x00000000    0x40400000    0x02000000    0x00000000    0x40400000    0x00000000    0x00200000  >;
+
+			};
+			/* pci-pci bridge, bus = 0, dev = 26, function = 0 ; */
+			/* name = Atom Processor E6xx PCI Express Port 4 */
+			pci@0000d000 {
+				compatible =  "pci8086,8181.2",
+					"pci8086,8181",
+					"pciclass060400",
+					"pciclass0604" ;
+				reg = < 0x0000d000    0x00000000    0x00000000    0x00000000    0x00000100  >;
+				device_type =  "pci" ;
+				#address-cells = < 3 >;
+				#size-cells = < 2 >;
+				bus-range = < 0x00000009    0x00000009  >;
+				ranges = < 0x0200d000    0x00000000    0x40000000    0x02000000    0x00000000    0x40000000    0x00000000    0x00200000  >;
+
+			};
+			/* pci device, bus = 0, dev = 27, function = 0 ; */
+			/* name = System Controller Hub (SCH Poulsbo) HD Audio Controller */
+			pci@0200d800 {
+				compatible =  "pci8086,811b.2",
+					"pci8086,811b",
+					"pciclass040300",
+					"pciclass0403" ;
+				reg = < 0x0200d800    0x00000000    0xd2c00000    0x00000000    0x00004000  >;
+				device_type =  "pci" ;
+
+			};
+			/* pci device, bus = 0, dev = 31, function = 0 ; */
+			/* name = Atom Processor E6xx LPC Bridge */
+			pci@0000f800 {
+				compatible =  "pci8086,8186.2",
+					"pci8086,8186",
+					"pciclass060100",
+					"pciclass0601" ;
+				reg = < 0x0000f800    0x00000000    0x00000000    0x00000000    0x00000100  >;
+				device_type =  "pci" ;
+
+			};
+
+		};
+		interrupt-controller@0xfec00000 {
+			compatible =  "intel,e6600-ioapic",
+				"intel,ioapic" ;
+			reg = < 0xfec00000    0x00000040  >;
+			interrupt-controller;
+
+		};
+		timer@0xfed00000 {
+			compatible =  "intel,e6600-hpet",
+				"intel,hpet" ;
+			reg = < 0xfed00000    0x00000400  >;
+
+		};
+		interrupt-controller@0xfee00000 {
+			compatible =  "intel,e6600-lapic",
+				"intel,lapic" ;
+			reg = < 0xfee00000    0x00001000  >;
+
+		};
+		msi: interrupt-controller@0xfee03000 {
+			compatible =  "intel,msi-irqs" ;
+			interrupt-controller;
+			#interrupt-cells = < 1 >;
+			#address-cells = < 1 >;
+			reg = < 0xfee03000    0x00001000  >;
+
+		};
+
+	};
+
+};
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 25/26] drivers/clk: sta2x11 common clock framework implementation
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (23 preceding siblings ...)
  2013-08-07 10:21 ` [PATCH 24/26] x86 STA2X11: add dts for Intel's Northville board Davide Ciminaghi
@ 2013-08-07 10:21 ` Davide Ciminaghi
  2013-08-07 10:22 ` [PATCH 26/26] pinctrl: add support for sta2x11 (via pinctrl-nomadik) Davide Ciminaghi
                   ` (2 subsequent siblings)
  27 siblings, 0 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:21 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree

This patch was submitted as RFC on June 20th 2012 (see
https://lkml.org/lkml/2012/6/20/779 for more details) and
resubmitted on March 8th 2013 (see
https://lkml.org/lkml/2013/3/8/245 for more details).

This is a new version which:

* Gets rid of the platform bus notifier replacing it with a platform
driver for the "virtual" sta2x11-clock-regs" device, which is created
when three of the sta2x11 basic platform devices (sta2x11-sctl,
sta2x11-apbreg and sta2x11-apb-soc-regs) have been probed.

* Adds some more clocks (gpios, sdio/mmc, spi, i2c, dma). Clocks still
have to be improved because not all the details have been modeled (for
instance mmc clocks are actually muxed clocks, not fixed factor).

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 arch/x86/Kconfig                    |    1 +
 drivers/clk/Makefile                |    1 +
 drivers/clk/sta2x11/Makefile        |    1 +
 drivers/clk/sta2x11/clk-audio-pll.c |  149 ++++++
 drivers/clk/sta2x11/clk-soc-pll.c   |   95 ++++
 drivers/clk/sta2x11/clk.c           |  865 +++++++++++++++++++++++++++++++++++
 drivers/clk/sta2x11/clk.h           |   88 ++++
 7 files changed, 1200 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/sta2x11/Makefile
 create mode 100644 drivers/clk/sta2x11/clk-audio-pll.c
 create mode 100644 drivers/clk/sta2x11/clk-soc-pll.c
 create mode 100644 drivers/clk/sta2x11/clk.c
 create mode 100644 drivers/clk/sta2x11/clk.h

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ae05df92..fed3507 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -551,6 +551,7 @@ config STA2X11
 	depends on X86_32_NON_STANDARD && PCI
 	select X86_DEV_DMA_OPS
 	select X86_DMA_REMAP
+	select COMMON_CLK
 	select SWIOTLB
 	select MFD_STA2X11
 	select ARCH_REQUIRE_GPIOLIB
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 4038c2b..d2b7693 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 obj-$(CONFIG_PLAT_SAMSUNG)	+= samsung/
 
 obj-$(CONFIG_X86)		+= x86/
+obj-$(CONFIG_STA2X11)		+= sta2x11/
 
 # Chip specific
 obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
diff --git a/drivers/clk/sta2x11/Makefile b/drivers/clk/sta2x11/Makefile
new file mode 100644
index 0000000..60c319a
--- /dev/null
+++ b/drivers/clk/sta2x11/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_STA2X11) += clk.o clk-soc-pll.o clk-audio-pll.o
diff --git a/drivers/clk/sta2x11/clk-audio-pll.c b/drivers/clk/sta2x11/clk-audio-pll.c
new file mode 100644
index 0000000..8ed28a2
--- /dev/null
+++ b/drivers/clk/sta2x11/clk-audio-pll.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright ST Microelectronics 2012
+ * Author: Davide Ciminaghi <ciminaghi@gnudd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Common clock api implementation for sta2x11
+ * audio-pll clock type implementation
+ */
+/* #define DEBUG */
+
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/clk-provider.h>
+#include <asm/div64.h>
+#include <asm/sta2x11.h>
+
+#include "clk.h"
+
+/**
+ * struct clk_audio_pll - sta2x11 audio pll clock
+ * @hw: clk_hw for the pll
+ *
+ * Soc pll
+ */
+struct clk_audio_pll {
+	struct clk_hw hw;
+	void __iomem *base;
+	spinlock_t *lock;
+};
+
+#define to_clk_audio_pll(_hw) container_of(_hw, struct clk_audio_pll, hw)
+
+static unsigned long clk_audio_pll_recalc_rate(struct clk_hw *hw,
+					       unsigned long parent_rate)
+{
+	struct clk_audio_pll *audio_pll = to_clk_audio_pll(hw);
+	u32 scpllctl = readl(audio_pll->base + SCTL_SCPLLCTL);
+	u32 scpllfctrl = readl(audio_pll->base + SCTL_SCPLLFCTRL);
+	u16 scresfract = readl(audio_pll->base + SCTL_SCRESFRACT);
+	u64 fvco, inff, ndiv, fract, idf, phi, odf;
+	int frac_control, dither_disable;
+
+	inff = parent_rate;
+	frac_control = scpllctl & SCTL_SCPLLCTL_FRAC_CONTROL;
+	ndiv = (scpllfctrl >> SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_SHIFT) &
+		SCTL_SCPLLFCTRL_AUDIO_PLL_NDIV_MASK;
+	fract = scresfract & SCTL_SCRESFRACT_MASK ;
+	idf = (scpllfctrl >> SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_SHIFT) &
+		SCTL_SCPLLFCTRL_AUDIO_PLL_IDF_MASK;
+	idf = idf ? idf : 1;
+	odf = (scpllfctrl >> SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_SHIFT) &
+		SCTL_SCPLLFCTRL_AUDIO_PLL_ODF_MASK;
+	odf = odf > 5 ? 32 : (1<<odf);
+	dither_disable = ((scpllfctrl >> SCTL_SCPLLFCTRL_DITHER_DISABLE_SHIFT) &
+			  SCTL_SCPLLFCTRL_DITHER_DISABLE_MASK) ? 0 : 1;
+
+	pr_debug("%s : refclk = %llu, scpllctl = 0x%08x\n", __func__,
+		 inff, scpllctl);
+	pr_debug("%s : scpllfctrl = 0x%08x, scresfract = 0x%08x\n",
+		 __func__, scpllfctrl, scresfract);
+	pr_debug("%s : ndiv = %llu, frac_control = %d, dither_disable = %d\n",
+		 __func__, ndiv, frac_control, dither_disable);
+	pr_debug("%s: fract = %llu, idf = %llu, odf = %llu\n",
+		 __func__, fract, idf, odf);
+
+	fvco = frac_control ?
+		div_u64((inff*2*((ndiv<<17)+(fract<<1)+dither_disable ? 0 : 1)),
+			(idf<<17)) :
+		div_u64((inff * 2 * ndiv), idf);
+	phi = div_u64(fvco, (odf * 2));
+
+	pr_debug("%s: fvco = %llu Hz, phi = %llu Hz\n", __func__, fvco, phi);
+
+	return phi;
+}
+
+static int clk_audio_pll_enable(struct clk_hw *hw)
+{
+	struct clk_audio_pll *audio_pll = to_clk_audio_pll(hw);
+	u32 scpllctl;
+	unsigned long flags;
+	spin_lock_irqsave(audio_pll->lock, flags);
+	scpllctl = readl(audio_pll->base + SCTL_SCPLLCTL);
+	scpllctl &= ~SCTL_SCPLLCTL_AUDIO_PLL_PD;
+	writel(scpllctl, audio_pll->base + SCTL_SCPLLCTL);
+	spin_unlock_irqrestore(audio_pll->lock, flags);
+	return 0;
+}
+
+static void clk_audio_pll_disable(struct clk_hw *hw)
+{
+	struct clk_audio_pll *audio_pll = to_clk_audio_pll(hw);
+	u32 scpllctl;
+	unsigned long flags;
+	spin_lock_irqsave(audio_pll->lock, flags);
+	scpllctl = readl(audio_pll->base + SCTL_SCPLLCTL);
+	scpllctl |= SCTL_SCPLLCTL_AUDIO_PLL_PD;
+	writel(scpllctl, audio_pll->base + SCTL_SCPLLCTL);
+	spin_unlock_irqrestore(audio_pll->lock, flags);
+}
+
+static const struct clk_ops clk_soc_pll_ops = {
+	.enable = clk_audio_pll_enable,
+	.disable = clk_audio_pll_disable,
+	.recalc_rate = clk_audio_pll_recalc_rate,
+};
+
+
+struct clk *register_sta2x11_clk_audio_pll(const char *name,
+					   const char *parent_name,
+					   void __iomem *base, spinlock_t *lock)
+{
+	struct clk_audio_pll *audio_pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	audio_pll = kzalloc(sizeof(*audio_pll), GFP_KERNEL);
+	if (!audio_pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_soc_pll_ops;
+	init.flags = 0;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	audio_pll->base = base;
+	audio_pll->lock = lock;
+	audio_pll->hw.init = &init;
+
+	clk = clk_register(NULL, &audio_pll->hw);
+	if (IS_ERR(clk))
+		kfree(audio_pll);
+
+	return clk;
+}
diff --git a/drivers/clk/sta2x11/clk-soc-pll.c b/drivers/clk/sta2x11/clk-soc-pll.c
new file mode 100644
index 0000000..8383bf9
--- /dev/null
+++ b/drivers/clk/sta2x11/clk-soc-pll.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright ST Microelectronics 2012
+ * Author: Davide Ciminaghi <ciminaghi@gnudd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Common clock api implementation for sta2x11
+ * soc-pll clock type implementation
+ */
+/* #define DEBUG */
+
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <asm/sta2x11.h>
+
+#include "clk.h"
+
+/**
+ * struct clk_soc_pll - sta2x11 soc pll clock
+ * @hw: clk_hw for the pll
+ *
+ * Soc pll
+ */
+struct clk_soc_pll {
+	struct clk_hw hw;
+	void __iomem *base;
+	spinlock_t *lock;
+};
+
+#define to_clk_soc_pll(_hw) container_of(_hw, struct clk_soc_pll, hw)
+
+#define PLL1NMUL_MASK	0x7f
+#define PLL1NMUL_SHIFT	3
+
+static unsigned long clk_soc_pll_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct clk_soc_pll *soc_pll = to_clk_soc_pll(hw);
+	unsigned long out;
+	u32 scpllfctrl = readl(soc_pll->base + SCTL_SCPLLFCTRL);
+	u32 nmul = (scpllfctrl >> PLL1NMUL_SHIFT) & PLL1NMUL_MASK;
+	out = parent_rate * nmul;
+	pr_debug("%s : soc_pll->base = %p\n", __func__, soc_pll->base);
+	pr_debug("%s : scpllfctrl = 0x%08x\n", __func__, scpllfctrl);
+	pr_debug("%s : nmul = %d\n", __func__, nmul);
+	pr_debug("%s : calculated rate = %lu\n", __func__, out);
+	pr_debug("%s : parent_rate = %lu\n", __func__, parent_rate);
+	return out;
+}
+
+static const struct clk_ops clk_soc_pll_ops = {
+	.recalc_rate = clk_soc_pll_recalc_rate,
+};
+
+
+struct clk *register_sta2x11_clk_soc_pll(const char *name,
+					 const char *parent_name,
+					 void __iomem *base, spinlock_t *lock)
+{
+	struct clk_soc_pll *soc_pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	soc_pll = kzalloc(sizeof(*soc_pll), GFP_KERNEL);
+	if (!soc_pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &clk_soc_pll_ops;
+	init.flags = 0;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	soc_pll->base = base;
+	soc_pll->lock = lock;
+	soc_pll->hw.init = &init;
+
+	clk = clk_register(NULL, &soc_pll->hw);
+	if (IS_ERR(clk))
+		kfree(soc_pll);
+
+	return clk;
+}
diff --git a/drivers/clk/sta2x11/clk.c b/drivers/clk/sta2x11/clk.c
new file mode 100644
index 0000000..24087a6
--- /dev/null
+++ b/drivers/clk/sta2x11/clk.c
@@ -0,0 +1,865 @@
+/*
+ * Copyright ST Microelectronics 2012
+ * Author: Davide Ciminaghi <ciminaghi@gnudd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Common clock api implementation for sta2x11
+ */
+/* #define DEBUG */
+
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/clkdev.h>
+#include <linux/pci-amba.h>
+#include <asm/sta2x11.h>
+
+#include "clk.h"
+
+#define STA2X11_MAX_CLK_NAME_LEN 60
+#define STA2X11_MAX_CLK_NPARENTS 8
+
+/*
+ * struct sta2x11_clk_data
+ * This structure is used to build the table listing all the
+ * clocks for a connext chip.
+ *
+ * @basename : basename of the clock (a .%d suffix will be added to
+ * deal with multiple connext instances).
+ * @type : sta2x11 clock type (see clk.h, enum sta2x11_clk_type)
+ * @reg_offset : the controlling register's offset for this clock
+ * @init : pointer to init function. When this pointer is not NULL, the
+ * pointed function is invoked before clock registration. This is used to
+ * fill the clock struct fields which are unknown at compile time (typically
+ * virtual addresses of controlling registers).
+ * @args : arguments needed for registration
+ */
+struct sta2x11_clk_data {
+	const char *basename;
+	int type;
+	unsigned int reg_offset;
+	void (*init)(struct sta2x11_clk_data *, struct sta2x11_instance_data *);
+	unsigned long flags;
+	union {
+		struct	{
+			const char *parent_name;
+			unsigned long rate;
+		} fixed_rate_root;
+		struct {
+			const char *parent_name;
+			unsigned int mult;
+			unsigned int div;
+		} fixed_factor;
+		struct {
+			const char **parent_names;
+			u8 num_parents;
+			void __iomem *reg;
+			u8 shift;
+			u8 width;
+			u8 clk_mux_flags;
+			spinlock_t *lock;
+		} mux;
+		struct {
+			const char *parent_name;
+			void __iomem *base;
+			spinlock_t *lock;
+		} soc_pll;
+		struct {
+			const char *parent_name;
+			void __iomem *base;
+			spinlock_t *lock;
+		} audio_pll;
+		struct {
+			const char *parent_name;
+			void __iomem *reg;
+			u8 shift;
+			u8 width;
+			spinlock_t *lock;
+			struct clk_div_table *div_tab;
+			u8 tab_divider_flags;
+		} tab_divider;
+	} args;
+};
+
+/* Various helper macros used to setup the clock table */
+
+/*
+ * Use this macro to declare a fixed clock with no parents
+ *
+ * @name : clock name
+ * @f : clock frequency
+ */
+#define DECLARE_FIXED_RATE_ROOT_CLK(n, f)				\
+	[n] = {								\
+		.basename = #n,						\
+		.type = fixed_rate_root,				\
+		.flags = CLK_IS_ROOT,					\
+		.args = {						\
+			.fixed_rate_root = {				\
+				.parent_name = NULL,			\
+				.rate = f,				\
+			}						\
+		}							\
+	}
+
+/*
+ * Use this macro to declare a fixed factor clock
+ *
+ * @n : clock name
+ * @parent_name = name of parent clock
+ * @flags = clock flags
+ * @mult = const mult factor
+ * @div = const div factor
+ */
+#define DECLARE_FIXED_FACTOR_CLK(n, pn, f, m, d)			\
+	[n] = {								\
+		.basename = #n,						\
+		.type = fixed_factor,					\
+		.reg_offset = 0,					\
+		.flags = f,						\
+		.args = {						\
+			.fixed_factor = {				\
+				.parent_name = #pn,			\
+				.mult = m,				\
+				.div = d,				\
+			}						\
+		}							\
+	}
+
+/*
+ * Use this macro to declare a mux clock
+ *
+ * @name : clock name
+ * @reg_offset : offset of controlling register
+ * @parent_names : names of parents
+ * @init : pointer to init function
+ * @flags : clock flags
+ * @shift : bitmask shift
+ * @width : bitmask width
+ * @clk_mux_flags : flags of clock mux
+ */
+#define DECLARE_MUX_CLK(n, ro, pn, in, f, s, w, cmf)			\
+	[n] = {								\
+		.basename = #n,						\
+		.type = mux,						\
+		.flags = f,						\
+		.reg_offset = ro,					\
+		.init = in,						\
+		.args = {						\
+			.mux = {					\
+				.parent_names = pn,			\
+				.num_parents = ARRAY_SIZE(pn),		\
+				.shift = s,				\
+				.width = w,				\
+				.clk_mux_flags = cmf,			\
+			},						\
+		}							\
+	}
+
+/*
+ * Use this macro to declare a pll clock
+ *
+ * @n : clock name
+ * @parent_name : name of parent
+ * @type : clock type
+ */
+#ifndef xcat
+#define xcat(a, b) a##b
+#endif
+
+#define DECLARE_PLL_CLK(n, pn, t)			\
+	[n] = {						\
+		.basename = #n,				\
+		.type = t,				\
+		.init = xcat(t, _init),			\
+		.args = {				\
+			.t = {				\
+				.parent_name = #pn,	\
+			},				\
+		}					\
+	}
+
+/*
+ * Use this macro to declare a soc-pll clock
+ *
+ * @n : clock name
+ * @parent_name : name of parent
+ */
+#define DECLARE_SOC_PLL_CLK(n, pn)   DECLARE_PLL_CLK(n, pn, soc_pll)
+
+/*
+ * Use this macro to declare an audio-pll clock
+ *
+ * @n : clock name
+ * @parent_name : name of parent
+ */
+#define DECLARE_AUDIO_PLL_CLK(n, pn)  DECLARE_PLL_CLK(n, pn, audio_pll)
+
+/*
+ * Use this macro to declare a tab-divider clock
+ *
+ * @n : clock name
+ * @ro : register offset
+ * @pn : parent name
+ * @in : init function
+ * @f : clock flags
+ * @s : controlling bitmask shift
+ * @w : controlling bitmask width
+ * @tdf : tab divider clock specific flags
+ */
+#define DECLARE_TAB_DIVIDER_CLK(n, ro, pn, in, f, s, w, tab, tdf)	\
+	[n] = {								\
+		.basename = #n,						\
+		.type = tab_divider,					\
+		.flags = f,						\
+		.reg_offset = ro,					\
+		.init = in,						\
+		.args = {						\
+			.tab_divider = {				\
+				.parent_name = #pn,			\
+				.shift = s,				\
+				.width = w,				\
+				.div_tab = tab,				\
+				.tab_divider_flags = tdf,		\
+			},						\
+		}							\
+	}
+
+/* Arrays with parents */
+
+static const char *soc_phi_parents[] = {
+	"soc_phia.%d",
+	"soc_phib.%d",
+};
+
+static const char *audio_pll_sdmmc_parents[] = {
+	"audio_pll_phi.%d",
+	"eaudio_pll_phi_div2.%d",
+};
+
+static const char *audio_pll_msp_parents[] = {
+	"audio_pll_phi_div4.%d",
+	"audio_pll_phi_div10.%d",
+};
+
+static const char *audio_pll_sarac_parents[] = {
+	"audio_pll_phi_div4.%d",
+	"audio_pll_phi.%d",
+};
+
+static const char *hclk_pre_parents[] = {
+	"soc_phi_byp_div3.%d",
+	"soc_phi_byp_div4.%d",
+	"soc_phi_byp_div6.%d",
+	"soc_phi_byp_div3.%d",
+};
+
+static const char *hclk_parents[] = {
+	"soc_phi_byp.%d",
+	"hclk_pre.%d",
+};
+
+/*
+ * Dividers' tables
+ */
+
+/* phia odf */
+static struct clk_div_table phia_odf_tab[] = {
+	{
+		.val = 0,
+		.div = 1,
+	},
+	{
+		.val = 1,
+		.div = 2,
+	},
+	{
+		.val = 2,
+		.div = 4,
+	},
+	{
+		.val = 3,
+		.div = 6,
+	},
+	{
+		.val = 4,
+		.div = 8,
+	},
+	{
+		.val = 5,
+		.div = 10,
+	},
+	{
+		.val = 6,
+		.div = 12,
+	},
+	{
+		.val = 7,
+		.div = 14,
+	},
+	/* Terminator */
+	{
+		.div = 0,
+	},
+};
+
+/* phib dividers */
+static struct clk_div_table phib_div_tab[] = {
+	{
+		.val = 0,
+		.div = 3,
+	},
+	{
+		.val = 1,
+		.div = 5,
+	},
+	/* Terminator */
+	{
+		.div = 0,
+	},
+};
+
+/*
+ * Init functions
+ */
+/*
+ * Init function for soc-pll clock
+ */
+static void soc_pll_init(struct sta2x11_clk_data *cptr,
+				struct sta2x11_instance_data *id)
+{
+	cptr->args.soc_pll.base = id->sctl->regs;
+	cptr->args.soc_pll.lock = &id->sctl->lock;
+}
+
+/*
+ * Init function for audio-pll clock
+ */
+static void audio_pll_init(struct sta2x11_clk_data *cptr,
+				  struct sta2x11_instance_data *id)
+{
+	cptr->args.audio_pll.base = id->sctl->regs;
+	cptr->args.audio_pll.lock = &id->sctl->lock;
+}
+
+/*
+ * Init functions for mux clocks
+ */
+static void
+sctl_mux_clock_init(struct sta2x11_clk_data *cptr,
+		    struct sta2x11_instance_data *id)
+{
+	cptr->args.mux.reg = id->sctl->regs + cptr->reg_offset;
+	cptr->args.mux.lock = &id->sctl->lock;
+}
+
+/*
+ * Init function for tab divider clock
+ */
+static void
+tab_divider_clock_init(struct sta2x11_clk_data *cptr,
+		       struct sta2x11_instance_data *id)
+{
+	cptr->args.tab_divider.reg = id->sctl->regs + cptr->reg_offset;
+	cptr->args.tab_divider.lock = &id->sctl->lock;
+}
+
+/*
+ * This table contains everything is needed to register all the clocks
+ * on a single connext instance
+ *
+ * TODO: this table shall be patched at startup to deal with the (very few
+ * at present) differences between STA2X11 based boards.
+ *
+ * TODO: complete this table with all the remaining clocks (mmc, msp, spi, ...)
+ */
+static struct sta2x11_clk_data clk_data[] = {
+	/* 24MHz refclk */
+	DECLARE_FIXED_RATE_ROOT_CLK(xtal, 24000000),
+	/* Sata clk */
+	DECLARE_FIXED_RATE_ROOT_CLK(sata, 100000000),
+	/* Eth clk */
+	DECLARE_FIXED_RATE_ROOT_CLK(eth, 50000000),
+	/* Soc pll vco */
+	DECLARE_SOC_PLL_CLK(soc_vco, xtal),
+	/* Soc pll vco dividers */
+	DECLARE_TAB_DIVIDER_CLK(soc_phia, SCTL_SCPLLFCTRL,
+				soc_vco, tab_divider_clock_init,
+				0, 0, 3, phia_odf_tab, 0),
+	DECLARE_TAB_DIVIDER_CLK(soc_phib, SCTL_SCCTL, soc_vco,
+				tab_divider_clock_init,
+				0, 10, 1, phib_div_tab, 0),
+	DECLARE_MUX_CLK(soc_phi, SCTL_SCCTL, soc_phi_parents,
+			sctl_mux_clock_init, 0, 2, 1, 0),
+	/*
+	 * TODO : IMPLEMENT THIS ONE AS A DIFFERENT TYPE OF CLOCK
+	 *
+	 * We need a mux clock controlled by a custom function:
+	 *
+	 * soc_phi_byp = soc_phi if pll is locked && !powered down && !bypassed
+	 * soc_phi_byp = xtal otherwise
+	 *
+	 * For now we assume that the soc pll is never bypassed, so we just
+	 * use a fixed factor clock to keep the correct names
+	 */
+	DECLARE_FIXED_FACTOR_CLK(soc_phi_byp, soc_phi, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(clk_48M, soc_phi_byp, 0, 1, 13),
+	DECLARE_FIXED_FACTOR_CLK(soc_phi_byp_div3, soc_phi_byp, 0, 1, 3),
+	DECLARE_FIXED_FACTOR_CLK(soc_phi_byp_div4, soc_phi_byp, 0, 1, 4),
+	DECLARE_FIXED_FACTOR_CLK(soc_phi_byp_div6, soc_phi_byp, 0, 1, 6),
+	DECLARE_FIXED_FACTOR_CLK(clk_52M, soc_phi_byp_div6, 0, 1, 2),
+	DECLARE_MUX_CLK(hclk_pre, SCTL_SCCTL, hclk_pre_parents,
+			sctl_mux_clock_init, 0, 0, 2, 0),
+	DECLARE_MUX_CLK(hclk, SCTL_SCCTL, hclk_parents,
+			sctl_mux_clock_init, 0, 9, 1, 0),
+	/* Audio pll derived clocks */
+	DECLARE_AUDIO_PLL_CLK(audio_pll_phi, xtal),
+	DECLARE_FIXED_FACTOR_CLK(audio_pll_phi_div2, audio_pll_phi, 0, 1, 2),
+	DECLARE_FIXED_FACTOR_CLK(audio_pll_phi_div10, audio_pll_phi, 0, 1, 10),
+	DECLARE_FIXED_FACTOR_CLK(audio_pll_phi_div4, audio_pll_phi_div2,
+				 0, 1, 2),
+	DECLARE_MUX_CLK(audio_pll_sdmmc, SCTL_SCCTL, audio_pll_sdmmc_parents,
+			sctl_mux_clock_init, 0, 8, 1, 0),
+	DECLARE_MUX_CLK(audio_pll_msp, SCTL_SCCTL, audio_pll_msp_parents,
+			sctl_mux_clock_init, 0, 8, 1, 0),
+	DECLARE_MUX_CLK(audio_pll_sarac, SCTL_SCCTL, audio_pll_sarac_parents,
+			sctl_mux_clock_init, 0, 8, 1, 0),
+	/* Peripheral clocks for uarts. TODO: implement these as gated clocks */
+	DECLARE_FIXED_FACTOR_CLK(hclk_uart0, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_uart1, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_uart2, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_uart3, hclk, 0, 1, 1),
+	/* Baud rate clocks for uarts. TODO: implement these as gated clocks */
+	DECLARE_FIXED_FACTOR_CLK(bclk_uart0, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(bclk_uart1, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(bclk_uart2, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(bclk_uart3, clk_48M, 0, 1, 1),
+	/* Peripheral clocks for gpios. TODO: implement these as gated clocks */
+	DECLARE_FIXED_FACTOR_CLK(hclk_gpio0, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_gpio1, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_gpio2, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_gpio3, hclk, 0, 1, 1),
+	/* Stmmac clock. TODO: implement this as a mux with sata */
+	DECLARE_FIXED_FACTOR_CLK(stmmac_rmii, eth, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(stmmac_csr, stmmac_rmii, 0, 1, 2),
+	/* sdmmc CLOCKS: FIXME: MUXED CLOCKS */
+	DECLARE_FIXED_FACTOR_CLK(sdmmc0, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(sdmmc1, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(sdmmc2, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(sdmmc3, clk_48M, 0, 1, 1),
+	/* Peripheral clocks for sdios */
+	DECLARE_FIXED_FACTOR_CLK(hclk_sdio0, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_sdio1, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_sdio2, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_sdio3, hclk, 0, 1, 1),
+	/* Peripheral clocks for dma's */
+	DECLARE_FIXED_FACTOR_CLK(hclk_soc_dma, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_audio_dma, hclk, 0, 1, 1),
+	/* Peripheral clocks for i2cs */
+	DECLARE_FIXED_FACTOR_CLK(hclk_i2c0, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_i2c1, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_i2c2, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_i2c3, hclk, 0, 1, 1),
+	/* i2c clocks */
+	DECLARE_FIXED_FACTOR_CLK(bclk_i2c0, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(bclk_i2c1, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(bclk_i2c2, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(bclk_i2c3, clk_48M, 0, 1, 1),
+	/* Peripheral clocks for spis */
+	DECLARE_FIXED_FACTOR_CLK(hclk_spi0, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_spi1, hclk, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(hclk_spi2, hclk, 0, 1, 1),
+	/* spi clocks */
+	DECLARE_FIXED_FACTOR_CLK(bclk_spi0, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(bclk_spi1, clk_48M, 0, 1, 1),
+	DECLARE_FIXED_FACTOR_CLK(bclk_spi2, clk_48M, 0, 1, 1),
+};
+
+/*
+ * Inline helpers
+ */
+static inline int get_sdio_clk_index(unsigned int fn)
+{
+	switch(fn) {
+	case 2:
+		return sdmmc1;
+	case 3:
+		return sdmmc2;
+	case 4:
+		return sdmmc3;
+	default:
+		return sta2x11_n_clks;
+	}
+}
+
+static inline int get_i2c_bclk_index(unsigned int fn)
+{
+	return bclk_i2c0 + fn - 1;
+}
+
+static inline int get_spi_bclk_index(unsigned int fn)
+{
+	return bclk_spi0 + fn - 2;
+}
+
+/*
+ * The following code registers various clock types for the connext
+ */
+
+typedef struct clk *(regfunc)(struct sta2x11_clk_data *, const char *, int);
+
+static __init struct clk *
+do_register_fixed_rate_root(struct sta2x11_clk_data *cptr,
+			    const char *name,
+			    int instance_id)
+{
+	pr_debug("Registering fixed rate root clock %s, rate = %lu\n",
+		 name, cptr->args.fixed_rate_root.rate);
+	return clk_register_fixed_rate(NULL,
+				       name,
+				       NULL,
+				       cptr->flags,
+				       cptr->args.fixed_rate_root.rate);
+}
+
+static __init struct clk *
+do_register_fixed_factor(struct sta2x11_clk_data *cptr,
+			 const char *name, int instance_id)
+{
+	char parent_name[STA2X11_MAX_CLK_NAME_LEN];
+	snprintf(parent_name, sizeof(parent_name), "%s.%d",
+		 cptr->args.fixed_factor.parent_name, instance_id);
+	return clk_register_fixed_factor(NULL, name,
+					 parent_name,
+					 cptr->flags,
+					 cptr->args.fixed_factor.mult,
+					 cptr->args.fixed_factor.div);
+}
+
+static __init struct clk *
+do_register_mux(struct sta2x11_clk_data *cptr,
+		const char *name, int instance_id)
+{
+	int i, nparents = cptr->args.mux.num_parents;
+	char *parents[STA2X11_MAX_CLK_NPARENTS], *ptr;
+	char parent_names[STA2X11_MAX_CLK_NPARENTS*STA2X11_MAX_CLK_NAME_LEN];
+	if (nparents > STA2X11_MAX_CLK_NPARENTS)
+		return ERR_PTR(-ENOMEM);
+	for (i = 0, ptr = parent_names; i < nparents; i++,
+		     ptr += STA2X11_MAX_CLK_NAME_LEN) {
+		snprintf(ptr, STA2X11_MAX_CLK_NAME_LEN,
+			 cptr->args.mux.parent_names[i], instance_id);
+		parents[i] = ptr;
+	}
+	return clk_register_mux(NULL, name, (const char **)parents,
+				cptr->args.mux.num_parents, cptr->flags,
+				cptr->args.mux.reg, cptr->args.mux.shift,
+				cptr->args.mux.width,
+				cptr->args.mux.clk_mux_flags,
+				cptr->args.mux.lock);
+}
+
+static __init struct clk *
+do_register_tab_divider(struct sta2x11_clk_data *cptr,
+			const char *name, int instance_id)
+{
+	char parent_name[STA2X11_MAX_CLK_NAME_LEN];
+	snprintf(parent_name, sizeof(parent_name), "%s.%d",
+		 cptr->args.tab_divider.parent_name, instance_id);
+	pr_debug("%s: registering tab_divider clock %s\n", __func__, name);
+	pr_debug("%s: parent = %s\n", __func__, parent_name);
+	return clk_register_divider_table(NULL, name, parent_name,
+					  0, cptr->args.tab_divider.reg,
+					  cptr->args.tab_divider.shift,
+					  cptr->args.tab_divider.width,
+					  0, cptr->args.tab_divider.div_tab,
+					  cptr->args.tab_divider.lock);
+}
+
+static __init struct clk *
+do_register_soc_pll(struct sta2x11_clk_data *cptr,
+		    const char *name, int instance_id)
+{
+	char parent_name[STA2X11_MAX_CLK_NAME_LEN];
+	snprintf(parent_name, sizeof(parent_name), "%s.%d",
+		 cptr->args.soc_pll.parent_name, instance_id);
+	pr_debug("%s: registering soc_pll clock %s\n", __func__, name);
+	pr_debug("%s: parent = %s\n", __func__, parent_name);
+	return register_sta2x11_clk_soc_pll(name, parent_name,
+					    cptr->args.soc_pll.base,
+					    cptr->args.soc_pll.lock);
+}
+
+static __init struct clk *
+do_register_audio_pll(struct sta2x11_clk_data *cptr,
+		      const char *name, int instance_id)
+{
+	char parent_name[STA2X11_MAX_CLK_NAME_LEN];
+	snprintf(parent_name, sizeof(parent_name), "%s.%d",
+		 cptr->args.audio_pll.parent_name, instance_id);
+	pr_debug("%s: registering audio_pll clock %s\n", __func__, name);
+	pr_debug("%s: parent = %s\n", __func__, parent_name);
+	return register_sta2x11_clk_audio_pll(name, parent_name,
+					      cptr->args.audio_pll.base,
+					      cptr->args.audio_pll.lock);
+}
+
+/*
+ * This function registers all the clocks listed in the clk_data table
+ * Such table is static and can be modified on a per-board basis at startup.
+ */
+static regfunc * regfuncs[] = {
+	[fixed_rate_root] = do_register_fixed_rate_root,
+	[fixed_factor] = do_register_fixed_factor,
+	[mux] = do_register_mux,
+	[tab_divider] = do_register_tab_divider,
+	[soc_pll] = do_register_soc_pll,
+	[audio_pll] = do_register_audio_pll,
+};
+
+static int register_clocks(struct sta2x11_instance_data *id,
+				  struct platform_device *dev)
+{
+	int i;
+	struct sta2x11_clk_data *cptr;
+	struct clk *clk, **clks;
+
+	/*
+	 * When this function is called, kmalloc already works, so we should
+	 * have no problem using it
+	 */
+	clks = kzalloc(sta2x11_n_clks * sizeof(struct clk *), GFP_KERNEL);
+	if (!clks)
+		return -ENOMEM;
+
+	for (i = 0, cptr = clk_data; i < ARRAY_SIZE(clk_data); i++, cptr++) {
+		/*
+		 * name can be on stack, since the clock framework does
+		 * kstrdup on register
+		 */
+		char name[STA2X11_MAX_CLK_NAME_LEN];
+		if (cptr->type < 0 || cptr->type > sta2x11_clk_ntypes) {
+			pr_err("%s: invalid type %d for clk %s, skipping\n",
+			       __func__, cptr->type,
+			       cptr->basename ? cptr->basename : "UNKNOWN");
+			continue;
+		}
+		if (cptr->type == none)
+			/* Clock not implemented on this board */
+			continue;
+		if (!regfuncs[cptr->type]) {
+			pr_err("%s : no regfunc for clk %s, skipping\n",
+			       __func__, cptr->basename ? cptr->basename :
+			       "UNKNOWN");
+			continue;
+		}
+		/*
+		 * Set up a clock name by adding an instance id to its
+		 * basename
+		 */
+		snprintf(name, sizeof(name), "%s.%d", cptr->basename,
+			 id->id);
+		/*
+		 * This should add runtime data to the clock. In particular,
+		 * it should add the controlling register's virtual address
+		 * (which is unknown at compile time)
+		 */
+		if (cptr->init)
+			cptr->init(cptr, id);
+		/* Ok, now just register the clock */
+		clk = regfuncs[cptr->type](cptr, name, id->id);
+		if (IS_ERR(clk)) {
+			pr_err("%s error registering clock %s\n",
+			       __func__, name);
+		} else {
+			pr_info("%s: registered clock %s\n", __func__, name);
+			clks[i] = clk;
+			/*
+			  A lookup is also added for each of the registered
+			  clocks
+			*/
+			clk_register_clkdev(clks[i], name, NULL);
+		}
+	}
+	/* Finally assign registered clocks to the instance they belong to */
+	platform_set_drvdata(dev, clks);
+	return 0;
+}
+
+/*
+ * Driver for the sta2x11-clock-regs platform device
+ */
+static int sta2x11_clock_regs_probe(struct platform_device *dev)
+{
+	struct sta2x11_instance_data *id = dev_get_platdata(&dev->dev);
+
+	dev_dbg(&dev->dev, "%s entered, id = %p", __func__, id);
+	if (!id)
+		return -EINVAL;
+	return register_clocks(id, dev);
+}
+
+static struct platform_driver sta2x11_clock_regs_driver = {
+	.driver = {
+		.name	= STA2X11_CLOCK_REGS_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sta2x11_clock_regs_probe,
+};
+
+/*
+ * This function just registers a notifier for the platform bus to know
+ * when the sta2x11-sctl and sta2x11-apb-soc-regs devices have been bound
+ * to the relevant drivers
+ */
+static int __init sta2x11_init_clocks(void)
+{
+	return platform_driver_register(&sta2x11_clock_regs_driver);
+}
+subsys_initcall(sta2x11_init_clocks);
+
+static struct clk **get_instance_clocks(struct sta2x11_instance_data *idata)
+{
+	struct device *d, *start;
+	char name[strlen(STA2X11_CLOCK_REGS_NAME) + 3];
+	snprintf(name, sizeof(name), "%s.%d",
+		 STA2X11_CLOCK_REGS_NAME, idata->id);
+	for (start = NULL; ; start = d) {
+		d = bus_find_device_by_name(&platform_bus_type, start, name);
+		if (!d)
+			break;
+		WARN_ON(dev_get_platdata(d) != idata);
+		return platform_get_drvdata(to_platform_device(d));
+	}
+	return NULL;
+}
+
+/*
+ * This is invoked on pci_enable() for every connext pci device
+ *
+ * It registers a lookup for the device's clock (if needed), so that
+ * the driver can find it.
+ */
+static void clk_new_pdev(struct pci_dev *pdev)
+{
+	struct sta2x11_instance_data *instance =
+		sta2x11_dev_to_instance(&pdev->dev);
+	/* Initialize with an invalid index */
+	enum sta2x11_clk clk_index = sta2x11_n_clks;
+	int sdio_index = -1;
+	struct clk **clks;
+	char *name;
+	if (!instance)
+		/*
+		 * Just ignore devices not belonging to the connext chip
+		 */
+		return;
+	clks = get_instance_clocks(instance);
+	if (!clks) {
+		/*
+		  If this is a connext device, it should have a corresponding
+		  clocks device
+		*/
+		WARN_ON(1);
+		return;
+	}
+
+	switch (pdev->device) {
+	case PCI_DEVICE_ID_STMICRO_UART_HWFC:
+		clk_index = pdev->devfn == 5 ? bclk_uart2 : bclk_uart3;
+		/* FALL THROUGH */
+	case PCI_DEVICE_ID_STMICRO_UART_NO_HWFC:
+		if (clk_index == sta2x11_n_clks)
+			clk_index =
+				(pdev->devfn == 5 ? bclk_uart0 : bclk_uart1);
+		if (pci_amba_get_dev_name(&name, pdev, 0) < 0) {
+			/* Could get no name for the pci-amba device */
+			WARN_ON(1);
+			return;
+		}
+		clk_register_clkdev(clks[clk_index], NULL, name);
+		break;
+	case PCI_DEVICE_ID_STMICRO_MAC:
+		clk_register_clkdev(clks[stmmac_csr], NULL,
+				    dev_name(&pdev->dev));
+		break;
+	case PCI_DEVICE_ID_STMICRO_GPIO:
+	{
+		int i;
+		for (i = 0; i < 4; i++) {
+			if (pci_amba_get_dev_name(&name, pdev, i) < 0) {
+				/* Could get no name for the pci-amba device */
+				WARN_ON(1);
+				continue;
+			}
+			clk_register_clkdev(clks[hclk_gpio0 + i], NULL, name);
+		}
+		break;
+	}
+	case PCI_DEVICE_ID_STMICRO_SDIO_EMMC:
+		sdio_index = sdmmc0;
+		/* FALL THROUGH */
+	case PCI_DEVICE_ID_STMICRO_SDIO:
+		if (pci_amba_get_dev_name(&name, pdev, 0) < 0) {
+			/* Could get no name for the pci-amba device */
+			WARN_ON(1);
+			return;
+		}
+		if (sdio_index < 0)
+			sdio_index = get_sdio_clk_index(pdev->devfn);
+		if (sdio_index >= sta2x11_n_clks) {
+			pr_err("Unknown sdio device, not registering clock\n");
+			break;
+		}
+		clk_register_clkdev(clks[sdio_index], NULL, name,
+				    pdev->bus->number, pdev->devfn);
+		break;
+	case PCI_DEVICE_ID_STMICRO_AUDIO_ROUTER_DMA:
+		clk_index = hclk_audio_dma;
+		/* FALL THROUGH */
+	case PCI_DEVICE_ID_STMICRO_SOC_DMA:
+		if (clk_index == sta2x11_n_clks)
+			clk_index = hclk_soc_dma;
+		if (pci_amba_get_dev_name(&name, pdev, 0) < 0) {
+			/* Could get no name for the pci-amba device */
+			WARN_ON(1);
+			return;
+		}
+		clk_register_clkdev(clks[clk_index], NULL, name);
+		break;
+	case PCI_DEVICE_ID_STMICRO_I2C:
+		if (pci_amba_get_dev_name(&name, pdev, 0) < 0) {
+			/* Could get no name for the pci-amba device */
+			WARN_ON(1);
+			return;
+		}
+		clk_index = get_i2c_bclk_index(pdev->devfn);
+		clk_register_clkdev(clks[clk_index], NULL, name);
+		break;
+	case PCI_DEVICE_ID_STMICRO_SPI_HS:
+		if (pci_amba_get_dev_name(&name, pdev, 0) < 0) {
+			/* Could get no name for the pci-amba device */
+			WARN_ON(1);
+			return;
+		}
+		clk_index = get_spi_bclk_index(pdev->devfn);
+		clk_register_clkdev(clks[clk_index], NULL, name);
+		break;
+		/* TODO : ADD MORE ID's HERE */
+	default:
+		dev_dbg(&pdev->dev, "clk: ignoring device\n");
+		break;
+	}
+}
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_STMICRO, PCI_ANY_ID, clk_new_pdev);
diff --git a/drivers/clk/sta2x11/clk.h b/drivers/clk/sta2x11/clk.h
new file mode 100644
index 0000000..7a2e0ef
--- /dev/null
+++ b/drivers/clk/sta2x11/clk.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright ST Microelectronics 2012
+ * Author: Davide Ciminaghi <ciminaghi@gnudd.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Common clock api implementation for sta2x11, main header file
+ */
+#ifndef __STA2X11_CLK_H__
+#define __STA2X11_CLK_H__
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+
+/*
+ * Indices for connext clocks
+ */
+enum sta2x11_clk {
+	xtal, sata, pcie, sdvo, eth, usb,
+	soc_vco, soc_phia, soc_phib, audio_pll_phi,
+	soc_phi, soc_phi_byp,
+	soc_phi_byp_div3, soc_phi_byp_div4, soc_phi_byp_div6,
+	audio_pll_phi_div2, audio_pll_phi_div4, audio_pll_phi_div10,
+	audio_pll_msp, audio_pll_sarac, audio_pll_sdmmc,
+	hclk_pre, hclk, clk_48M, clk_52M,
+	/* Uarts' peripheral clocks */
+	hclk_uart0, hclk_uart1, hclk_uart2, hclk_uart3,
+	/* Uarts' baud rate clocks */
+	bclk_uart0, bclk_uart1, bclk_uart2, bclk_uart3,
+	/* gpios clock */
+	hclk_gpio0, hclk_gpio1, hclk_gpio2, hclk_gpio3,
+	/* sdios clocks */
+	hclk_sdio0, hclk_sdio1, hclk_sdio2, hclk_sdio3,
+	/* soc dma clock */
+	hclk_soc_dma,
+	/* audio dma clock */
+	hclk_audio_dma,
+	/* i2c clocks */
+	hclk_i2c0, hclk_i2c1, hclk_i2c2, hclk_i2c3,
+	bclk_i2c0, bclk_i2c1, bclk_i2c2, bclk_i2c3,
+	/* spi clocks */
+	hclk_spi0, hclk_spi1, hclk_spi2,
+	bclk_spi0, bclk_spi1, bclk_spi2,
+	sdmmc0, sdmmc1, sdmmc2, sdmmc3,
+	stmmac_csr, stmmac_rmii,
+	sta2x11_n_clks,
+};
+
+/*
+ * Clock types used on the connext
+ *
+ * By convention, a clock listed in clk_data[] with type == none, is not
+ * registered (usually because the clock itself is not active on the
+ * board the kernel is being run on).
+ */
+enum sta2x11_clk_type {
+	/* Not present on this board */
+	none = 0,
+	fixed_rate_root = 1,
+	fixed_factor = 2,
+	mux = 3,
+	tab_divider = 4,
+	soc_pll = 5,
+	audio_pll = 6,
+	sta2x11_clk_ntypes,
+};
+
+struct clk *register_sta2x11_clk_soc_pll(const char *name,
+					 const char *parent_name,
+					 void __iomem *reg,
+					 spinlock_t *lock);
+struct clk *register_sta2x11_clk_audio_pll(const char *name,
+					   const char *parent_name,
+					   void __iomem *base,
+					   spinlock_t *lock);
+#endif /* __STA2X11_CLK_H__ */
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH 26/26] pinctrl: add support for sta2x11 (via pinctrl-nomadik)
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (24 preceding siblings ...)
  2013-08-07 10:21 ` [PATCH 25/26] drivers/clk: sta2x11 common clock framework implementation Davide Ciminaghi
@ 2013-08-07 10:22 ` Davide Ciminaghi
  2013-08-07 19:47   ` Linus Walleij
  2013-08-07 20:43   ` Alessandro Rubini
  2013-08-07 15:41 ` [PATCH 00/26] STA2X11 devicetree support for amba/pci H. Peter Anvin
  2013-08-07 21:12 ` Alessandro Rubini
  27 siblings, 2 replies; 35+ messages in thread
From: Davide Ciminaghi @ 2013-08-07 10:22 UTC (permalink / raw)
  To: linux-kernel
  Cc: rubini, Giancarlo Asnaghi, x86, H. Peter Anvin, Ingo Molnar,
	Russell King, Thomas Gleixner, devicetree, Linus Walleij

Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>
---
 .../devicetree/bindings/pinctrl/ste,nomadik.txt    |    2 +-
 drivers/pinctrl/Kconfig                            |    6 +-
 drivers/pinctrl/Makefile                           |    1 +
 drivers/pinctrl/pinctrl-nomadik-sta2x11.c          |  578 ++++++++++++++++++++
 drivers/pinctrl/pinctrl-nomadik.c                  |    7 +
 drivers/pinctrl/pinctrl-nomadik.h                  |   14 +
 6 files changed, 606 insertions(+), 2 deletions(-)
 create mode 100644 drivers/pinctrl/pinctrl-nomadik-sta2x11.c

diff --git a/Documentation/devicetree/bindings/pinctrl/ste,nomadik.txt b/Documentation/devicetree/bindings/pinctrl/ste,nomadik.txt
index 9a2f3f4..3361894 100644
--- a/Documentation/devicetree/bindings/pinctrl/ste,nomadik.txt
+++ b/Documentation/devicetree/bindings/pinctrl/ste,nomadik.txt
@@ -2,7 +2,7 @@ ST Ericsson Nomadik pinmux controller
 
 Required properties:
 - compatible: "stericsson,nmk-pinctrl", "stericsson,nmk-pinctrl-db8540",
-              "stericsson,nmk-pinctrl-stn8815"
+              "stericsson,nmk-pinctrl-stn8815", "stericsson,nmk-pinctrl-sta2x11"
 - reg: Should contain the register physical address and length of the PRCMU.
 
 Please refer to pinctrl-bindings.txt in this directory for details of the
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index bc830af..be2977f 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -154,7 +154,7 @@ config PINCTRL_IMX28
 
 config PINCTRL_NOMADIK
 	bool "Nomadik pin controller driver"
-	depends on ARCH_U8500 || ARCH_NOMADIK
+	depends on ARCH_U8500 || ARCH_NOMADIK || STA2X11
 	select PINMUX
 	select PINCONF
 
@@ -176,6 +176,10 @@ config PINCTRL_ROCKCHIP
 	select GENERIC_PINCONF
 	select GENERIC_IRQ_CHIP
 
+config PINCTRL_STA2X11
+       bool "STA2X11 pin controller driver"
+       depends on PINCTRL_NOMADIK && STA2X11
+
 config PINCTRL_SINGLE
 	tristate "One-register-per-pin type device tree based pinctrl driver"
 	depends on OF
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index d64563bf..24efd71 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_PINCTRL_NOMADIK)	+= pinctrl-nomadik.o
 obj-$(CONFIG_PINCTRL_STN8815)	+= pinctrl-nomadik-stn8815.o
 obj-$(CONFIG_PINCTRL_DB8500)	+= pinctrl-nomadik-db8500.o
 obj-$(CONFIG_PINCTRL_DB8540)	+= pinctrl-nomadik-db8540.o
+obj-$(CONFIG_PINCTRL_STA2X11)	+= pinctrl-nomadik-sta2x11.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
 obj-$(CONFIG_PINCTRL_SIRF)	+= sirf/
diff --git a/drivers/pinctrl/pinctrl-nomadik-sta2x11.c b/drivers/pinctrl/pinctrl-nomadik-sta2x11.c
new file mode 100644
index 0000000..0a4e3c7
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-nomadik-sta2x11.c
@@ -0,0 +1,578 @@
+#include <linux/kernel.h>
+#include <linux/pinctrl/pinctrl.h>
+#include "pinctrl-nomadik.h"
+
+/* All the pins that can be used for GPIO and some other functions */
+#define _GPIO(offset)		(offset)
+
+#define STA2X11_PIN_F6		_GPIO(0)
+#define STA2X11_PIN_D5		_GPIO(1)
+#define STA2X11_PIN_E6		_GPIO(2)
+#define STA2X11_PIN_E7		_GPIO(3)
+#define STA2X11_PIN_E9		_GPIO(4)
+#define STA2X11_PIN_F7		_GPIO(5)
+#define STA2X11_PIN_E8		_GPIO(6)
+#define STA2X11_PIN_F8		_GPIO(7)
+#define STA2X11_PIN_D14		_GPIO(8)
+#define STA2X11_PIN_E13		_GPIO(9)
+#define STA2X11_PIN_D13		_GPIO(10)
+#define STA2X11_PIN_E12		_GPIO(11)
+#define STA2X11_PIN_C15		_GPIO(12)
+#define STA2X11_PIN_E14		_GPIO(13)
+#define STA2X11_PIN_D15		_GPIO(14)
+#define STA2X11_PIN_E15		_GPIO(15)
+#define STA2X11_PIN_A17		_GPIO(16)
+#define STA2X11_PIN_C16		_GPIO(17)
+#define STA2X11_PIN_C18		_GPIO(18)
+#define STA2X11_PIN_B19		_GPIO(19)
+#define STA2X11_PIN_C17		_GPIO(20)
+#define STA2X11_PIN_D16		_GPIO(21)
+#define STA2X11_PIN_B18		_GPIO(22)
+#define STA2X11_PIN_A18		_GPIO(23)
+#define STA2X11_PIN_G13		_GPIO(24)
+#define STA2X11_PIN_F14		_GPIO(25)
+#define STA2X11_PIN_F13		_GPIO(26)
+#define STA2X11_PIN_D18		_GPIO(27)
+#define STA2X11_PIN_D19		_GPIO(28)
+#define STA2X11_PIN_G14		_GPIO(29)
+#define STA2X11_PIN_E17		_GPIO(30)
+#define STA2X11_PIN_C19		_GPIO(31)
+#define STA2X11_PIN_E19		_GPIO(32)
+#define STA2X11_PIN_E16		_GPIO(33)
+#define STA2X11_PIN_H14		_GPIO(34)
+#define STA2X11_PIN_L13		_GPIO(35)
+#define STA2X11_PIN_N16		_GPIO(36)
+#define STA2X11_PIN_M16		_GPIO(37)
+#define STA2X11_PIN_N13		_GPIO(38)
+#define STA2X11_PIN_M14		_GPIO(39)
+#define STA2X11_PIN_N14		_GPIO(40)
+#define STA2X11_PIN_M15		_GPIO(41)
+#define STA2X11_PIN_P17		_GPIO(42)
+#define STA2X11_PIN_P15		_GPIO(43)
+#define STA2X11_PIN_R18		_GPIO(44)
+#define STA2X11_PIN_R17		_GPIO(45)
+#define STA2X11_PIN_T19		_GPIO(46)
+#define STA2X11_PIN_R16		_GPIO(47)
+#define STA2X11_PIN_T18		_GPIO(48)
+#define STA2X11_PIN_U17		_GPIO(49)
+#define STA2X11_PIN_T17		_GPIO(50)
+#define STA2X11_PIN_U16		_GPIO(51)
+#define STA2X11_PIN_T15		_GPIO(52)
+#define STA2X11_PIN_T16		_GPIO(53)
+#define STA2X11_PIN_R15		_GPIO(54)
+#define STA2X11_PIN_T14		_GPIO(55)
+#define STA2X11_PIN_U18		_GPIO(56)
+#define STA2X11_PIN_U19		_GPIO(57)
+#define STA2X11_PIN_V19		_GPIO(58)
+#define STA2X11_PIN_V18		_GPIO(59)
+#define STA2X11_PIN_P18		_GPIO(60)
+#define STA2X11_PIN_R19		_GPIO(61)
+#define STA2X11_PIN_V17		_GPIO(62)
+#define STA2X11_PIN_V16		_GPIO(63)
+#define STA2X11_PIN_W17		_GPIO(64)
+#define STA2X11_PIN_W16		_GPIO(65)
+#define STA2X11_PIN_P13		_GPIO(66)
+#define STA2X11_PIN_P14		_GPIO(67)
+#define STA2X11_PIN_R9		_GPIO(68)
+#define STA2X11_PIN_R8		_GPIO(69)
+#define STA2X11_PIN_P11		_GPIO(70)
+#define STA2X11_PIN_R7		_GPIO(71)
+#define STA2X11_PIN_P10		_GPIO(72)
+#define STA2X11_PIN_P9		_GPIO(73)
+#define STA2X11_PIN_P8		_GPIO(74)
+#define STA2X11_PIN_N6		_GPIO(75)
+#define STA2X11_PIN_P5		_GPIO(76)
+#define STA2X11_PIN_N5		_GPIO(77)
+#define STA2X11_PIN_P6		_GPIO(78)
+#define STA2X11_PIN_R5		_GPIO(79)
+#define STA2X11_PIN_R6		_GPIO(80)
+#define STA2X11_PIN_T6		_GPIO(81)
+#define STA2X11_PIN_T5		_GPIO(82)
+#define STA2X11_PIN_W6		_GPIO(83)
+#define STA2X11_PIN_V6		_GPIO(84)
+#define STA2X11_PIN_W5		_GPIO(85)
+#define STA2X11_PIN_V5		_GPIO(86)
+#define STA2X11_PIN_V4		_GPIO(87)
+#define STA2X11_PIN_U4		_GPIO(88)
+#define STA2X11_PIN_U3		_GPIO(89)
+#define STA2X11_PIN_T4		_GPIO(90)
+#define STA2X11_PIN_W4		_GPIO(91)
+#define STA2X11_PIN_W3		_GPIO(92)
+#define STA2X11_PIN_W2		_GPIO(93)
+#define STA2X11_PIN_V3		_GPIO(94)
+#define STA2X11_PIN_V2		_GPIO(95)
+#define STA2X11_PIN_R4		_GPIO(96)
+#define STA2X11_PIN_V1		_GPIO(97)
+#define STA2X11_PIN_M5		_GPIO(98)
+#define STA2X11_PIN_U2		_GPIO(99)
+#define STA2X11_PIN_T2		_GPIO(100)
+#define STA2X11_PIN_U1		_GPIO(101)
+#define STA2X11_PIN_T3		_GPIO(102)
+#define STA2X11_PIN_R3		_GPIO(103)
+#define STA2X11_PIN_M7		_GPIO(104)
+#define STA2X11_PIN_P4		_GPIO(105)
+#define STA2X11_PIN_R2		_GPIO(106)
+#define STA2X11_PIN_P2		_GPIO(107)
+#define STA2X11_PIN_M6		_GPIO(108)
+#define STA2X11_PIN_T1		_GPIO(109)
+#define STA2X11_PIN_L5		_GPIO(110)
+#define STA2X11_PIN_N3		_GPIO(111)
+#define STA2X11_PIN_P1		_GPIO(112)
+#define STA2X11_PIN_N2		_GPIO(113)
+#define STA2X11_PIN_R1		_GPIO(114)
+#define STA2X11_PIN_N4		_GPIO(115)
+#define STA2X11_PIN_P3		_GPIO(116)
+#define STA2X11_PIN_M4		_GPIO(117)
+#define STA2X11_PIN_K5		_GPIO(118)
+#define STA2X11_PIN_H2		_GPIO(119)
+#define STA2X11_PIN_H1		_GPIO(120)
+#define STA2X11_PIN_J3		_GPIO(121)
+#define STA2X11_PIN_H3		_GPIO(122)
+#define STA2X11_PIN_J4		_GPIO(123)
+#define STA2X11_PIN_J5		_GPIO(124)
+#define STA2X11_PIN_D3		_GPIO(125)
+#define STA2X11_PIN_F4		_GPIO(126)
+#define STA2X11_PIN_D4		_GPIO(127)
+
+/*
+ * The names of the pins are denoted by GPIO number and ball name, even
+ * though they can be used for other things than GPIO, this is the first
+ * column in the table of the data sheet and often used on schematics and
+ * such.
+ */
+static const struct pinctrl_pin_desc nmk_sta2x11_pins[] = {
+	PINCTRL_PIN(STA2X11_PIN_F6, "GPIO0_F6"),
+	PINCTRL_PIN(STA2X11_PIN_D5, "GPIO1_D5"),
+	PINCTRL_PIN(STA2X11_PIN_E6, "GPIO2_E6"),
+	PINCTRL_PIN(STA2X11_PIN_E7, "GPIO3_E7"),
+	PINCTRL_PIN(STA2X11_PIN_E9, "GPIO4_E9"),
+	PINCTRL_PIN(STA2X11_PIN_F7, "GPIO5_F7"),
+	PINCTRL_PIN(STA2X11_PIN_E8, "GPIO6_E8"),
+	PINCTRL_PIN(STA2X11_PIN_F8, "GPIO7_F8"),
+	PINCTRL_PIN(STA2X11_PIN_D14, "GPIO8_D14"),
+	PINCTRL_PIN(STA2X11_PIN_E13, "GPIO9_E13"),
+	PINCTRL_PIN(STA2X11_PIN_D13, "GPIO10_D13"),
+	PINCTRL_PIN(STA2X11_PIN_E12, "GPIO11_E12"),
+	PINCTRL_PIN(STA2X11_PIN_C15, "GPIO12_C15"),
+	PINCTRL_PIN(STA2X11_PIN_E14, "GPIO13_E14"),
+	PINCTRL_PIN(STA2X11_PIN_D15, "GPIO14_D15"),
+	PINCTRL_PIN(STA2X11_PIN_E15, "GPIO15_E15"),
+	PINCTRL_PIN(STA2X11_PIN_A17, "GPIO16_A17"),
+	PINCTRL_PIN(STA2X11_PIN_C16, "GPIO17_C16"),
+	PINCTRL_PIN(STA2X11_PIN_C18, "GPIO18_C18"),
+	PINCTRL_PIN(STA2X11_PIN_B19, "GPIO19_B19"),
+	PINCTRL_PIN(STA2X11_PIN_C17, "GPIO20_C17"),
+	PINCTRL_PIN(STA2X11_PIN_D16, "GPIO21_D16"),
+	PINCTRL_PIN(STA2X11_PIN_B18, "GPIO22_B18"),
+	PINCTRL_PIN(STA2X11_PIN_A18, "GPIO23_A18"),
+	PINCTRL_PIN(STA2X11_PIN_G13, "GPIO24_G13"),
+	PINCTRL_PIN(STA2X11_PIN_F14, "GPIO25_F14"),
+	PINCTRL_PIN(STA2X11_PIN_F13, "GPIO26_F13"),
+	PINCTRL_PIN(STA2X11_PIN_D18, "GPIO27_D18"),
+	PINCTRL_PIN(STA2X11_PIN_D19, "GPIO28_D19"),
+	PINCTRL_PIN(STA2X11_PIN_G14, "GPIO29_G14"),
+	PINCTRL_PIN(STA2X11_PIN_E17, "GPIO30_E17"),
+	PINCTRL_PIN(STA2X11_PIN_C19, "GPIO31_C19"),
+	PINCTRL_PIN(STA2X11_PIN_E19, "GPIO32_E19"),
+	PINCTRL_PIN(STA2X11_PIN_E16, "GPIO33_E16"),
+	PINCTRL_PIN(STA2X11_PIN_H14, "GPIO34_H14"),
+	PINCTRL_PIN(STA2X11_PIN_L13, "GPIO35_L13"),
+	PINCTRL_PIN(STA2X11_PIN_N16, "GPIO36_N16"),
+	PINCTRL_PIN(STA2X11_PIN_M16, "GPIO37_M16"),
+	PINCTRL_PIN(STA2X11_PIN_N13, "GPIO38_N13"),
+	PINCTRL_PIN(STA2X11_PIN_M14, "GPIO39_M14"),
+	PINCTRL_PIN(STA2X11_PIN_N14, "GPIO40_N14"),
+	PINCTRL_PIN(STA2X11_PIN_M15, "GPIO41_M15"),
+	PINCTRL_PIN(STA2X11_PIN_P17, "GPIO42_P17"),
+	PINCTRL_PIN(STA2X11_PIN_P15, "GPIO43_P15"),
+	PINCTRL_PIN(STA2X11_PIN_R18, "GPIO44_R18"),
+	PINCTRL_PIN(STA2X11_PIN_R17, "GPIO45_R17"),
+	PINCTRL_PIN(STA2X11_PIN_T19, "GPIO46_T19"),
+	PINCTRL_PIN(STA2X11_PIN_R16, "GPIO47_R16"),
+	PINCTRL_PIN(STA2X11_PIN_T18, "GPIO48_T18"),
+	PINCTRL_PIN(STA2X11_PIN_U17, "GPIO49_U17"),
+	PINCTRL_PIN(STA2X11_PIN_T17, "GPIO50_T17"),
+	PINCTRL_PIN(STA2X11_PIN_U16, "GPIO51_U16"),
+	PINCTRL_PIN(STA2X11_PIN_T15, "GPIO52_T15"),
+	PINCTRL_PIN(STA2X11_PIN_T16, "GPIO53_T16"),
+	PINCTRL_PIN(STA2X11_PIN_R15, "GPIO54_R15"),
+	PINCTRL_PIN(STA2X11_PIN_T14, "GPIO55_T14"),
+	PINCTRL_PIN(STA2X11_PIN_U18, "GPIO56_U18"),
+	PINCTRL_PIN(STA2X11_PIN_U19, "GPIO57_U19"),
+	PINCTRL_PIN(STA2X11_PIN_V19, "GPIO58_V19"),
+	PINCTRL_PIN(STA2X11_PIN_V18, "GPIO59_V18"),
+	PINCTRL_PIN(STA2X11_PIN_P18, "GPIO60_P18"),
+	PINCTRL_PIN(STA2X11_PIN_R19, "GPIO61_R19"),
+	PINCTRL_PIN(STA2X11_PIN_V17, "GPIO62_V17"),
+	PINCTRL_PIN(STA2X11_PIN_V16, "GPIO63_V16"),
+	PINCTRL_PIN(STA2X11_PIN_W17, "GPIO64_W17"),
+	PINCTRL_PIN(STA2X11_PIN_W16, "GPIO65_W16"),
+	PINCTRL_PIN(STA2X11_PIN_P13, "GPIO66_P13"),
+	PINCTRL_PIN(STA2X11_PIN_P14, "GPIO67_P14"),
+	PINCTRL_PIN(STA2X11_PIN_R9, "GPIO68_R9"),
+	PINCTRL_PIN(STA2X11_PIN_R8, "GPIO69_R8"),
+	PINCTRL_PIN(STA2X11_PIN_P11, "GPIO70_P11"),
+	PINCTRL_PIN(STA2X11_PIN_R7, "GPIO71_R7"),
+	PINCTRL_PIN(STA2X11_PIN_P10, "GPIO72_P10"),
+	PINCTRL_PIN(STA2X11_PIN_P9, "GPIO73_P9"),
+	PINCTRL_PIN(STA2X11_PIN_P8, "GPIO74_P8"),
+	PINCTRL_PIN(STA2X11_PIN_N6, "GPIO75_N6"),
+	PINCTRL_PIN(STA2X11_PIN_P5, "GPIO76_P5"),
+	PINCTRL_PIN(STA2X11_PIN_N5, "GPIO77_N5"),
+	PINCTRL_PIN(STA2X11_PIN_P6, "GPIO78_P6"),
+	PINCTRL_PIN(STA2X11_PIN_R5, "GPIO79_R5"),
+	PINCTRL_PIN(STA2X11_PIN_R6, "GPIO80_R6"),
+	PINCTRL_PIN(STA2X11_PIN_T6, "GPIO81_T6"),
+	PINCTRL_PIN(STA2X11_PIN_T5, "GPIO82_T5"),
+	PINCTRL_PIN(STA2X11_PIN_W6, "GPIO83_W6"),
+	PINCTRL_PIN(STA2X11_PIN_V6, "GPIO84_V6"),
+	PINCTRL_PIN(STA2X11_PIN_W5, "GPIO85_W5"),
+	PINCTRL_PIN(STA2X11_PIN_V5, "GPIO86_V5"),
+	PINCTRL_PIN(STA2X11_PIN_V4, "GPIO87_V4"),
+	PINCTRL_PIN(STA2X11_PIN_U4, "GPIO88_U4"),
+	PINCTRL_PIN(STA2X11_PIN_U3, "GPIO89_U3"),
+	PINCTRL_PIN(STA2X11_PIN_T4, "GPIO90_T4"),
+	PINCTRL_PIN(STA2X11_PIN_W4, "GPIO91_W4"),
+	PINCTRL_PIN(STA2X11_PIN_W3, "GPIO92_W3"),
+	PINCTRL_PIN(STA2X11_PIN_W2, "GPIO93_W2"),
+	PINCTRL_PIN(STA2X11_PIN_V3, "GPIO94_V3"),
+	PINCTRL_PIN(STA2X11_PIN_V2, "GPIO95_V2"),
+	PINCTRL_PIN(STA2X11_PIN_R4, "GPIO96_R4"),
+	PINCTRL_PIN(STA2X11_PIN_V1, "GPIO97_V1"),
+	PINCTRL_PIN(STA2X11_PIN_M5, "GPIO98_M5"),
+	PINCTRL_PIN(STA2X11_PIN_U2, "GPIO99_U2"),
+	PINCTRL_PIN(STA2X11_PIN_T2, "GPIO100_T2"),
+	PINCTRL_PIN(STA2X11_PIN_U1, "GPIO101_U1"),
+	PINCTRL_PIN(STA2X11_PIN_T3, "GPIO102_T3"),
+	PINCTRL_PIN(STA2X11_PIN_R3, "GPIO103_R3"),
+	PINCTRL_PIN(STA2X11_PIN_M7, "GPIO104_M7"),
+	PINCTRL_PIN(STA2X11_PIN_P4, "GPIO105_P4"),
+	PINCTRL_PIN(STA2X11_PIN_R2, "GPIO106_R2"),
+	PINCTRL_PIN(STA2X11_PIN_P2, "GPIO107_P2"),
+	PINCTRL_PIN(STA2X11_PIN_M6, "GPIO108_M6"),
+	PINCTRL_PIN(STA2X11_PIN_T1, "GPIO109_T1"),
+	PINCTRL_PIN(STA2X11_PIN_L5, "GPIO110_L5"),
+	PINCTRL_PIN(STA2X11_PIN_N3, "GPIO111_N3"),
+	PINCTRL_PIN(STA2X11_PIN_P1, "GPIO112_P1"),
+	PINCTRL_PIN(STA2X11_PIN_N2, "GPIO113_N2"),
+	PINCTRL_PIN(STA2X11_PIN_R1, "GPIO114_R1"),
+	PINCTRL_PIN(STA2X11_PIN_N4, "GPIO115_N4"),
+	PINCTRL_PIN(STA2X11_PIN_P3, "GPIO116_P3"),
+	PINCTRL_PIN(STA2X11_PIN_M4, "GPIO117_M4"),
+	PINCTRL_PIN(STA2X11_PIN_K5, "GPIO118_K5"),
+	PINCTRL_PIN(STA2X11_PIN_H2, "GPIO119_H2"),
+	PINCTRL_PIN(STA2X11_PIN_H1, "GPIO120_H1"),
+	PINCTRL_PIN(STA2X11_PIN_J3, "GPIO121_J3"),
+	PINCTRL_PIN(STA2X11_PIN_H3, "GPIO122_H3"),
+	PINCTRL_PIN(STA2X11_PIN_J4, "GPIO123_J4"),
+	PINCTRL_PIN(STA2X11_PIN_J5, "GPIO124_J5"),
+	PINCTRL_PIN(STA2X11_PIN_D3, "GPIO125_D3"),
+	PINCTRL_PIN(STA2X11_PIN_F4, "GPIO126_F4"),
+	PINCTRL_PIN(STA2X11_PIN_D4, "GPIO127_D4"),
+};
+
+#define STA2X11_GPIO_RANGE(a, b, c) { .name = "STA2X11", .id = a, .base = b, \
+			.pin_base = b, .npins = c }
+
+/*
+ * This matches the 32-pin gpio chips registered by the GPIO portion. This
+ * cannot be const since we assign the struct gpio_chip * pointer at runtime.
+ */
+static struct pinctrl_gpio_range nmk_sta2x11_ranges[] = {
+	STA2X11_GPIO_RANGE(0, 0, 32),
+	STA2X11_GPIO_RANGE(1, 32, 32),
+	STA2X11_GPIO_RANGE(2, 64, 32),
+	STA2X11_GPIO_RANGE(3, 96, 32),
+};
+
+/*
+ * Read the pin group names like this:
+ * u0_a_1    = first groups of pins for uart0 on alt function a
+ * i2c2_b_2  = second group of pins for i2c2 on alt function b
+ */
+
+/* Altfunction A */
+static const unsigned gpio07_a_1_pins[] = { STA2X11_PIN_F6, STA2X11_PIN_D5,
+	STA2X11_PIN_E6, STA2X11_PIN_E7, STA2X11_PIN_E9, STA2X11_PIN_F7,
+	STA2X11_PIN_E8, STA2X11_PIN_F8 };
+
+static const unsigned rgbout_a_1_pins[] = {
+	STA2X11_PIN_D14,
+	STA2X11_PIN_E13,
+	STA2X11_PIN_D13,
+	STA2X11_PIN_E12,
+	STA2X11_PIN_C15,
+	STA2X11_PIN_E14,
+	STA2X11_PIN_D15,
+	STA2X11_PIN_E15,
+	STA2X11_PIN_A17,
+	STA2X11_PIN_C16,
+	STA2X11_PIN_C18,
+	STA2X11_PIN_B19,
+	STA2X11_PIN_C17,
+	STA2X11_PIN_D16,
+	STA2X11_PIN_B18,
+	STA2X11_PIN_A18,
+	STA2X11_PIN_G13,
+	STA2X11_PIN_F14,
+	STA2X11_PIN_F13,
+	STA2X11_PIN_D18,
+	STA2X11_PIN_D19,
+	STA2X11_PIN_G14,
+	STA2X11_PIN_E17,
+	STA2X11_PIN_C19,
+	STA2X11_PIN_E19,
+	STA2X11_PIN_E16,
+	STA2X11_PIN_H14,
+};
+
+static const unsigned eth_a_1_pins[] = {
+	STA2X11_PIN_L13,
+	STA2X11_PIN_N16,
+	STA2X11_PIN_M16,
+	STA2X11_PIN_N13,
+	STA2X11_PIN_M14,
+	STA2X11_PIN_N14,
+	STA2X11_PIN_M15,
+	STA2X11_PIN_P17,
+	STA2X11_PIN_P15,
+};
+
+static const unsigned can_a_1_pins[] = {
+	STA2X11_PIN_R18,
+	STA2X11_PIN_R17,
+};
+
+static const unsigned mlb_a_1_pins[] = {
+	STA2X11_PIN_T19,
+	STA2X11_PIN_R16,
+};
+
+static const unsigned spi0_a_1_pins[] = {
+	STA2X11_PIN_T18,
+	STA2X11_PIN_U17,
+	STA2X11_PIN_T17,
+	STA2X11_PIN_U16,
+};
+
+static const unsigned spi1_a_1_pins[] = {
+	STA2X11_PIN_T15,
+	STA2X11_PIN_T16,
+	STA2X11_PIN_R15,
+	STA2X11_PIN_T14,
+};
+
+static const unsigned spi2_a_1_pins[] = {
+	STA2X11_PIN_U18,
+	STA2X11_PIN_U19,
+	STA2X11_PIN_V19,
+	STA2X11_PIN_V18,
+};
+
+static const unsigned i2c0_a_1_pins[] = {
+	STA2X11_PIN_P18,
+	STA2X11_PIN_R19,
+};
+
+static const unsigned i2c1_a_1_pins[] = {
+	STA2X11_PIN_V17,
+	STA2X11_PIN_V16,
+};
+
+static const unsigned i2c2_a_1_pins[] = {
+	STA2X11_PIN_W17,
+	STA2X11_PIN_W16,
+};
+
+static const unsigned i2c3_a_1_pins[] = {
+	STA2X11_PIN_P13,
+	STA2X11_PIN_P14,
+};
+
+static const unsigned msp0_a_1_pins[] = {
+	STA2X11_PIN_R9,
+	STA2X11_PIN_R8,
+	STA2X11_PIN_P11,
+	STA2X11_PIN_R7,
+	STA2X11_PIN_P10,
+	STA2X11_PIN_P9,
+	STA2X11_PIN_P8,
+};
+
+static const unsigned msp1_a_1_pins[] = {
+	STA2X11_PIN_N6,
+	STA2X11_PIN_P5,
+	STA2X11_PIN_N5,
+	STA2X11_PIN_P6,
+};
+
+static const unsigned msp2_a_1_pins[] = {
+	STA2X11_PIN_R5,
+	STA2X11_PIN_R6,
+	STA2X11_PIN_T6,
+	STA2X11_PIN_T5,
+};
+
+static const unsigned msp3_a_1_pins[] = {
+	STA2X11_PIN_W6,
+	STA2X11_PIN_V6,
+	STA2X11_PIN_W5,
+	STA2X11_PIN_V5,
+};
+
+static const unsigned msp4_a_1_pins[] = {
+	STA2X11_PIN_V4,
+	STA2X11_PIN_U4,
+	STA2X11_PIN_U3,
+	STA2X11_PIN_T4,
+};
+
+static const unsigned msp5_a_1_pins[] = {
+	STA2X11_PIN_W4,
+	STA2X11_PIN_W3,
+	STA2X11_PIN_W2,
+	STA2X11_PIN_V3,
+};
+
+static const unsigned sdio3_a_1_pins[] = {
+	STA2X11_PIN_V2,
+	STA2X11_PIN_R4,
+	STA2X11_PIN_V1,
+	STA2X11_PIN_M5,
+	STA2X11_PIN_U2,
+	STA2X11_PIN_T2,
+};
+
+static const unsigned sdio2_a_1_pins[] = {
+	STA2X11_PIN_P4,
+	STA2X11_PIN_R2,
+	STA2X11_PIN_P2,
+	STA2X11_PIN_M6,
+	STA2X11_PIN_T1,
+	STA2X11_PIN_L5,
+};
+
+static const unsigned sdio1_a_1_pins[] = {
+	STA2X11_PIN_N4,
+	STA2X11_PIN_P3,
+	STA2X11_PIN_M4,
+	STA2X11_PIN_K5,
+	STA2X11_PIN_H2,
+	STA2X11_PIN_H1,
+};
+
+static const unsigned u2_a_1_pins[] = {
+	STA2X11_PIN_D3,
+	STA2X11_PIN_F4,
+};
+
+static const unsigned u3_a_1_pins[] = {
+	STA2X11_PIN_D4,
+};
+
+#define STA2X11_PIN_GROUP(a, b) { .name = #a, .pins = a##_pins,		\
+			.npins = ARRAY_SIZE(a##_pins), .altsetting = b }
+
+static const struct nmk_pingroup nmk_sta2x11_groups[] = {
+	STA2X11_PIN_GROUP(gpio07_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(rgbout_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(eth_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(can_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(mlb_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(spi0_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(spi1_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(spi2_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(i2c0_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(i2c1_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(i2c2_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(i2c3_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(msp0_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(msp1_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(msp2_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(msp3_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(msp4_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(msp5_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(sdio3_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(sdio2_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(sdio1_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(u2_a_1, NMK_GPIO_ALT_A),
+	STA2X11_PIN_GROUP(u3_a_1, NMK_GPIO_ALT_A),
+};
+
+/* We use this macro to define the groups applicable to a function */
+#define STA2X11_FUNC_GROUPS(a, b...)	   \
+static const char * const a##_groups[] = { b };
+
+STA2X11_FUNC_GROUPS(gpio07, "gpio07_a_1");
+STA2X11_FUNC_GROUPS(rgbout, "rgbout_a_1");
+STA2X11_FUNC_GROUPS(eth, "eth_a_1");
+STA2X11_FUNC_GROUPS(can, "can_a_1");
+STA2X11_FUNC_GROUPS(mlb, "mlb_a_1");
+STA2X11_FUNC_GROUPS(spi0, "spi0_a_1");
+STA2X11_FUNC_GROUPS(spi1, "spi1_a_1");
+STA2X11_FUNC_GROUPS(spi2, "spi2_a_1");
+STA2X11_FUNC_GROUPS(i2c0, "i2c0_a_1");
+STA2X11_FUNC_GROUPS(i2c1, "i2c1_a_1");
+STA2X11_FUNC_GROUPS(i2c2, "i2c2_a_1");
+STA2X11_FUNC_GROUPS(i2c3, "i2c3_a_1");
+STA2X11_FUNC_GROUPS(msp0, "msp0_a_1");
+STA2X11_FUNC_GROUPS(msp1, "msp1_a_1");
+STA2X11_FUNC_GROUPS(msp2, "msp2_a_1");
+STA2X11_FUNC_GROUPS(msp3, "msp3_a_1");
+STA2X11_FUNC_GROUPS(msp4, "msp4_a_1");
+STA2X11_FUNC_GROUPS(msp5, "msp5_a_1");
+STA2X11_FUNC_GROUPS(sdio3, "sdio3_a_1");
+STA2X11_FUNC_GROUPS(sdio2, "sdio2_a_1");
+STA2X11_FUNC_GROUPS(sdio1, "sdio1_a_1");
+STA2X11_FUNC_GROUPS(u2, "u2_a_1");
+STA2X11_FUNC_GROUPS(u3, "u3_a_1");
+
+
+#define FUNCTION(fname)					\
+	{						\
+		.name = #fname,				\
+		.groups = fname##_groups,		\
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+static const struct nmk_function nmk_sta2x11_functions[] = {
+	FUNCTION(gpio07),
+	FUNCTION(rgbout),
+	FUNCTION(eth),
+	FUNCTION(can),
+	FUNCTION(mlb),
+	FUNCTION(spi0),
+	FUNCTION(spi1),
+	FUNCTION(spi2),
+	FUNCTION(i2c0),
+	FUNCTION(i2c1),
+	FUNCTION(i2c2),
+	FUNCTION(i2c3),
+	FUNCTION(msp0),
+	FUNCTION(msp1),
+	FUNCTION(msp2),
+	FUNCTION(msp3),
+	FUNCTION(msp4),
+	FUNCTION(msp5),
+	FUNCTION(sdio3),
+	FUNCTION(sdio2),
+	FUNCTION(sdio1),
+	FUNCTION(u2),
+	FUNCTION(u3),
+};
+
+static const struct nmk_pinctrl_soc_data nmk_sta2x11_soc = {
+	.gpio_ranges = nmk_sta2x11_ranges,
+	.gpio_num_ranges = ARRAY_SIZE(nmk_sta2x11_ranges),
+	.pins = nmk_sta2x11_pins,
+	.npins = ARRAY_SIZE(nmk_sta2x11_pins),
+	.functions = nmk_sta2x11_functions,
+	.nfunctions = ARRAY_SIZE(nmk_sta2x11_functions),
+	.groups = nmk_sta2x11_groups,
+	.ngroups = ARRAY_SIZE(nmk_sta2x11_groups),
+};
+
+void nmk_pinctrl_sta2x11_init(const struct nmk_pinctrl_soc_data **soc)
+{
+	*soc = &nmk_sta2x11_soc;
+}
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 97fb020..d7d4b592 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -2131,6 +2131,10 @@ static const struct of_device_id nmk_pinctrl_match[] = {
 		.compatible = "stericsson,db8540-pinctrl",
 		.data = (void *)PINCTRL_NMK_DB8540,
 	},
+	{
+		.compatible = "stericsson,nmk-pinctrl-sta2x11",
+		.data = (void *)PINCTRL_NMK_STA2X11,
+	},
 	{},
 };
 
@@ -2188,6 +2192,8 @@ static int nmk_pinctrl_probe(struct platform_device *pdev)
 		nmk_pinctrl_db8500_init(&npct->soc);
 	if (version == PINCTRL_NMK_DB8540)
 		nmk_pinctrl_db8540_init(&npct->soc);
+	if (version == PINCTRL_NMK_STA2X11)
+		nmk_pinctrl_sta2x11_init(&npct->soc);
 
 	if (np) {
 		prcm_np = of_parse_phandle(np, "prcm", 0);
@@ -2262,6 +2268,7 @@ static const struct platform_device_id nmk_pinctrl_id[] = {
 	{ "pinctrl-stn8815", PINCTRL_NMK_STN8815 },
 	{ "pinctrl-db8500", PINCTRL_NMK_DB8500 },
 	{ "pinctrl-db8540", PINCTRL_NMK_DB8540 },
+	{ "pinctrl-sta2x11", PINCTRL_NMK_STA2X11 },
 	{ }
 };
 
diff --git a/drivers/pinctrl/pinctrl-nomadik.h b/drivers/pinctrl/pinctrl-nomadik.h
index bcd4191..8b072f8 100644
--- a/drivers/pinctrl/pinctrl-nomadik.h
+++ b/drivers/pinctrl/pinctrl-nomadik.h
@@ -7,6 +7,7 @@
 #define PINCTRL_NMK_STN8815	0
 #define PINCTRL_NMK_DB8500	1
 #define PINCTRL_NMK_DB8540	2
+#define PINCTRL_NMK_STA2X11	3
 
 #define PRCM_GPIOCR_ALTCX(pin_num,\
 	altc1_used, altc1_ri, altc1_cb,\
@@ -179,4 +180,17 @@ nmk_pinctrl_db8540_init(const struct nmk_pinctrl_soc_data **soc)
 
 #endif
 
+#ifdef CONFIG_PINCTRL_STA2X11
+
+void nmk_pinctrl_sta2x11_init(const struct nmk_pinctrl_soc_data **soc);
+
+#else
+
+static inline void
+nmk_pinctrl_sta2x11_init(const struct nmk_pinctrl_soc_data **soc)
+{
+}
+
+#endif
+
 #endif /* PINCTRL_PINCTRL_NOMADIK_H */
-- 
1.7.7.2

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH 00/26] STA2X11 devicetree support for amba/pci
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (25 preceding siblings ...)
  2013-08-07 10:22 ` [PATCH 26/26] pinctrl: add support for sta2x11 (via pinctrl-nomadik) Davide Ciminaghi
@ 2013-08-07 15:41 ` H. Peter Anvin
  2013-08-07 21:12 ` Alessandro Rubini
  27 siblings, 0 replies; 35+ messages in thread
From: H. Peter Anvin @ 2013-08-07 15:41 UTC (permalink / raw)
  To: Alessandro Rubini
  Cc: linux-kernel, Davide Ciminaghi, Giancarlo Asnaghi, x86,
	Ingo Molnar, Russell King, Thomas Gleixner, devicetree

On 08/07/2013 03:16 AM, Alessandro Rubini wrote:
> 
> Some of the problems he found are:
> 
>      * Passing a dtb to the kernel: we use a modified kexec at present
>        because x86 boot loaders can't pass the DT blob, to our knowledge.
> 
>      * Passing correct irq numbers to the AMBA drivers, because PCI MSI
>        irq numbers are dynamically allocated (we solved this by using
>        of_update_property() at runtime). We also had to register a new
>        irq domain for msi irqs, otherwise of_irq_map_one() would complain
>        about irqs lacking a corresponding domain.
> 
>      * Switching to a new gpio driver with devicetree support (we took the
>        Nomadik gpio/pinctrl because our device apparently has more or less
>        the same gpio cell as the Nomadik chip). This requires implementation
>        of writel_relaxed() and IRQF_VALID on x86: we hacked them internally
>        but the patches are not part of this set. We're willing to solve
>        these incompatibilities first, if there's interest.
> 
>      * Writing a suitable dts: at present, a dts only exists for one
>        of the STA2X11 based boards (Intel Northville). This includes a
>        copy of all the physical addresses for the devices, as dts requires
>        that, even if such addresses are automatically assigned by PCI.
>        Clearly, with this approach we kill PCI autodetect: if you plug
>        to a different slot you need a different dts.
> 
> This got us a more or less working kernel on the Northville board
> (where the device is soldered on the motherboard and acts as main chipset).
> The plug-in PCIe board cannot be supported by device tree, as far as
> we know, which in our opinion is a strong downside of device tree in favor
> of the platform data "shit".
> 

OK, so we have a real corner case here... which is a plugin board beyond
which sits a bus normally used by fixed devices.  You are definitely
correct that this is something that stresses current means of
description to the breaking point.

*Note there are some questions below that I would perfectly understand
if you can't talk about publicly, if so, please contact me privately at
my corporate address.*

However, the plugin board is very different from it being the main
chipset, in no small part because you can boot without it.  I think this
is the first time I have ever heard of a chip which can act both as a
system chipset and a plugin card.

The mainboard case is relatively straightforward -- we should use ACPI 5
(preferred for x86) or device tree to describe it.  My understanding
from what you describe so far is that the only existing case is the
Northville which is a mainboard.

For the plugin case, my thinking is that we probably do need a driver of
some kind which at least contains the description of the board, as I
assume one is not present in any kind of firmware on the board itself
(*do any such boards or plans for them actually exist at this point?*)
Ideally that driver should be (primarily?) a data object (an ACPI 5 SSDT
or a DTB file) rather than open coded C.

I believe ACPI 5 unlike device tree should be able to specify the
dynamic properties that you are rightfully concerned with.

Sorry if this feels like a wild goose chase to you.  Some of this
problem domain is not very well handled by the current code, but we
really have to draw a hard line to make sure it doesn't descend into
unmaintainable chaos.

We have similar issues with MinnowBoard and are trying to use that as a
platform to figure out how a lot of these things need to be handled.

	-hpa


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 26/26] pinctrl: add support for sta2x11 (via pinctrl-nomadik)
  2013-08-07 10:22 ` [PATCH 26/26] pinctrl: add support for sta2x11 (via pinctrl-nomadik) Davide Ciminaghi
@ 2013-08-07 19:47   ` Linus Walleij
  2013-08-07 20:43   ` Alessandro Rubini
  1 sibling, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2013-08-07 19:47 UTC (permalink / raw)
  To: Davide Ciminaghi
  Cc: linux-kernel, Alessandro Rubini, Giancarlo Asnaghi, x86,
	H. Peter Anvin, Ingo Molnar, Russell King, Thomas Gleixner,
	devicetree

On Wed, Aug 7, 2013 at 12:22 PM, Davide Ciminaghi <ciminaghi@gnudd.com> wrote:

> Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
> Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>

Maybe you could add a commit message?

Apart from that it looks like a straight-forward plug-in to the
Nomadik pin controller, so I'd happily apply it, but I guess it
will go in through the x86 tree?

Acked-by: Linus Walleij <linus.walleij@linaro.org>

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 14/26] gpio: remove sta2x11-gpio
  2013-08-07 10:19 ` [PATCH 14/26] gpio: remove sta2x11-gpio Davide Ciminaghi
@ 2013-08-07 19:49   ` Linus Walleij
  0 siblings, 0 replies; 35+ messages in thread
From: Linus Walleij @ 2013-08-07 19:49 UTC (permalink / raw)
  To: Davide Ciminaghi
  Cc: linux-kernel, Alessandro Rubini, Giancarlo Asnaghi, x86,
	H. Peter Anvin, Ingo Molnar, Russell King, Thomas Gleixner,
	devicetree

On Wed, Aug 7, 2013 at 12:19 PM, Davide Ciminaghi <ciminaghi@gnudd.com> wrote:

> The Connext chip has 4 gpio cells looking very similar to those of the
> Nomadik, whose gpio/pinctrl driver (already featuring devicetree support)
> will be used instead of the sta2x11 specific one.
>
> Signed-off-by: Davide Ciminaghi <ciminaghi@gnudd.com>
> Acked-by: Giancarlo Asnaghi <giancarlo.asnaghi@st.com>

Seems we should have discovered this earlier ;-)

I'd be happy to apply this too.
Acked-by: Linus Walleij <linus.walleij@linaro.org>

If you want I can apply this and the pinctrl patch to my
pinctrl tree for a consistent switch-over.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 26/26] pinctrl: add support for sta2x11 (via pinctrl-nomadik)
  2013-08-07 10:22 ` [PATCH 26/26] pinctrl: add support for sta2x11 (via pinctrl-nomadik) Davide Ciminaghi
  2013-08-07 19:47   ` Linus Walleij
@ 2013-08-07 20:43   ` Alessandro Rubini
  1 sibling, 0 replies; 35+ messages in thread
From: Alessandro Rubini @ 2013-08-07 20:43 UTC (permalink / raw)
  To: linus.walleij
  Cc: ciminaghi, linux-kernel, giancarlo.asnaghi, x86, hpa, mingo,
	linux, tglx, devicetree

> Maybe you could add a commit message?

Ack (Davide is holidays, I grant that for him).

> Apart from that it looks like a straight-forward plug-in to the
> Nomadik pin controller, so I'd happily apply it, but I guess it
> will go in through the x86 tree?

It's part of a bigger series, that adds devicetree support first.
Yes, it's expected to go through a different path, if the whole
series is ok.
 
> Acked-by: Linus Walleij <linus.walleij@linaro.org>

Thanks for this and the gpio acked-by -- yes, I didn't notice it's a
nomadik logic block; it's Davide who tried to match the registers.

/alessandro

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 00/26] STA2X11 devicetree support for amba/pci
  2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
                   ` (26 preceding siblings ...)
  2013-08-07 15:41 ` [PATCH 00/26] STA2X11 devicetree support for amba/pci H. Peter Anvin
@ 2013-08-07 21:12 ` Alessandro Rubini
  2013-08-07 21:15   ` H. Peter Anvin
                     ` (2 more replies)
  27 siblings, 3 replies; 35+ messages in thread
From: Alessandro Rubini @ 2013-08-07 21:12 UTC (permalink / raw)
  To: hpa
  Cc: linux-kernel, ciminaghi, giancarlo.asnaghi, x86, mingo, linux,
	tglx, devicetree

[stripped list of issues from my original message follows]
>> Some of the problems he found are:
>> 
>>      * Passing a dtb to the kernel: we use a modified kexec at present
>>      * Passing correct irq numbers to the AMBA drivers
>>      * Switching to a new gpio driver with devicetree support
>>      * Writing a suitable dts: at present, a dts only exists for one
>>        of the STA2X11 based boards (Intel Northville).

> OK, so we have a real corner case here... which is a plugin board beyond
> which sits a bus normally used by fixed devices.  You are definitely
> correct that this is something that stresses current means of
> description to the breaking point.

Basically, it's an ARM chip with a PCI interface. So it offers USB, SATA,
Eth, i2c, spi, gpio, can etc to the x86 CPU.

> *Note there are some questions below that I would perfectly understand
> if you can't talk about publicly, if so, please contact me privately at
> my corporate address.*

Thanks. I'm not aware of any such issues at this point, though.
 
> However, the plugin board is very different from it being the main
> chipset, in no small part because you can boot without it.  I think this
> is the first time I have ever heard of a chip which can act both as a
> system chipset and a plugin card.

The main CPU in the Northville is an Atom, which IIUC has its own
memory controller -- and definitely a PCIe controller.  The Sta2x11
chip is connected to the PCIe bus, as both a slave and a master. It's
a busmaster for SATA, USB and something else, and equipped with a
PrimeCell PL080 as DMA engine for UART, I2C, SPI, MMC.

I'm aware it might be the first time this happens, but I also suspect
it will be common pretty soon: the industrial world wants I2C, UART,
SPI and GPIO, and bridging overt PCI to an external SoC is the right
approach, in my opinion.

> The mainboard case is relatively straightforward -- we should use ACPI 5
> (preferred for x86) or device tree to describe it.  My understanding
> from what you describe so far is that the only existing case is the
> Northville which is a mainboard.

There are a pair of such mainboards around, but what we developers
only have the Northville at this time.

And the evaluation board, which is a PCIe card. With the previous
platform_data-based approach I could plug two of them and access all
devices (2 * 4 UART, 2 * 3 I2C etc).

> For the plugin case, my thinking is that we probably do need a driver of
> some kind which at least contains the description of the board, as I
> assume one is not present in any kind of firmware on the board itself
> (*do any such boards or plans for them actually exist at this point?*)

The board exists as an evaluation board. But I see nothing against an
industrial-grade commercial offering, to give SPI, CAN and all the
rest to PC users that need them, as a single do-it-all cheap board.

> Ideally that driver should be (primarily?) a data object (an ACPI 5 SSDT
> or a DTB file) rather than open coded C.

Mostly so. It used to be platform data, to register devices for
drivers that already exist. Like we did for Ether and CAN: just
add the vendor/device pair and PCI support where missing.
 
> I believe ACPI 5 unlike device tree should be able to specify the
> dynamic properties that you are rightfully concerned with.

We'll try to get acquainted with that, but my wild guess is that
platform data is still simpler. I'm aware of the issues, and I'm not
insisting, though.
 
> Sorry if this feels like a wild goose chase to you.  Some of this
> problem domain is not very well handled by the current code, but we
> really have to draw a hard line to make sure it doesn't descend into
> unmaintainable chaos.

I understand. My impression of devicetree is exactly like that, I must
say.  What we have here is a very clean PCI enumeration of it all: we
only need to specify the mapping of GPIO pins (i.e. card-detect for
mmc) and DMA channels, as all the rest works by itself.

> We have similar issues with MinnowBoard and are trying to use that as a
> platform to figure out how a lot of these things need to be handled.

Interesting. I'll take a look. We were looking for a simple PC today
and found that very thing as a viable option.

Thank you for your feedback.  May I ask three more questions (this is
the 1st)?

Is the patch-set a viable approach for mainline, modulo serious evaluation
of the hairy IRQ details and the other bits?

Would it make sense to work on devicetree support in x86 bootloaders
(especially yours, let's ignore grub)?

thank you again
/alessandro

^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 00/26] STA2X11 devicetree support for amba/pci
  2013-08-07 21:12 ` Alessandro Rubini
@ 2013-08-07 21:15   ` H. Peter Anvin
  2013-08-07 22:05   ` H. Peter Anvin
  2013-08-07 22:12   ` H. Peter Anvin
  2 siblings, 0 replies; 35+ messages in thread
From: H. Peter Anvin @ 2013-08-07 21:15 UTC (permalink / raw)
  To: Alessandro Rubini
  Cc: linux-kernel, ciminaghi, giancarlo.asnaghi, x86, mingo, linux,
	tglx, devicetree

On 08/07/2013 02:12 PM, Alessandro Rubini wrote:
> 
> Would it make sense to work on devicetree support in x86 bootloaders
> (especially yours, let's ignore grub)?
> 

No, it's already there.  ;)

	-hpa



^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 00/26] STA2X11 devicetree support for amba/pci
  2013-08-07 21:12 ` Alessandro Rubini
  2013-08-07 21:15   ` H. Peter Anvin
@ 2013-08-07 22:05   ` H. Peter Anvin
  2013-08-07 22:12   ` H. Peter Anvin
  2 siblings, 0 replies; 35+ messages in thread
From: H. Peter Anvin @ 2013-08-07 22:05 UTC (permalink / raw)
  To: Alessandro Rubini
  Cc: linux-kernel, ciminaghi, giancarlo.asnaghi, x86, mingo, linux,
	tglx, devicetree

On 08/07/2013 02:12 PM, Alessandro Rubini wrote:
> 
> I understand. My impression of devicetree is exactly like that, I must
> say.  What we have here is a very clean PCI enumeration of it all: we
> only need to specify the mapping of GPIO pins (i.e. card-detect for
> mmc) and DMA channels, as all the rest works by itself.
> 

Could you elucidate this a bit more?  Specifically, from the PCI host's
perspective, how do you know what you are dealing with (presumably PCI
VID:DID:SVID:SID?)  How exactly does the mapping of PCI BARs and
INT/MSI/MSI-X channels to the slave device play in?

I think it is safe to say that the device models we have today simply
don't account for this kind of usage, which, as you say, is a genuine
problem, and I think we need to understand the problem space better in
order to properly architect the solution, as I don't think we have one
right now.

	-hpa


^ permalink raw reply	[flat|nested] 35+ messages in thread

* Re: [PATCH 00/26] STA2X11 devicetree support for amba/pci
  2013-08-07 21:12 ` Alessandro Rubini
  2013-08-07 21:15   ` H. Peter Anvin
  2013-08-07 22:05   ` H. Peter Anvin
@ 2013-08-07 22:12   ` H. Peter Anvin
  2 siblings, 0 replies; 35+ messages in thread
From: H. Peter Anvin @ 2013-08-07 22:12 UTC (permalink / raw)
  To: Alessandro Rubini
  Cc: linux-kernel, ciminaghi, giancarlo.asnaghi, x86, mingo, linux,
	tglx, devicetree

On 08/07/2013 02:12 PM, Alessandro Rubini wrote:
> 
> Thank you for your feedback.  May I ask three more questions (this is
> the 1st)?
> 
> Is the patch-set a viable approach for mainline, modulo serious evaluation
> of the hairy IRQ details and the other bits?
> 

Serious evaluation is definitely called for.  I think that is all I can
say at this point.

When you say that on Northville this acts as "the main chipset".  The
typical definition of that is the firmware resides there.  Is that the
case in this platform as well (I am guessing no)?  It may sound like
splitting hairs but I'm trying to wrap my brain around this platform; it
sounds like I might have received a very wrong understanding.

	-hpa


^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2013-08-07 22:13 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-07 10:16 [PATCH 00/26] STA2X11 devicetree support for amba/pci Alessandro Rubini
2013-08-07 10:16 ` [PATCH 01/26] x86: fix warning for sta2x11 Alessandro Rubini
2013-08-07 10:16 ` [PATCH 02/26] DMA: PL330: use prefix in reg names to build under x86 Alessandro Rubini
2013-08-07 10:16 ` [PATCH 03/26] mmc: Use the new <linux/sizes.h> Alessandro Rubini
2013-08-07 10:17 ` [PATCH 04/26] x86: add CONFIG_ARM_AMBA, selected by STA2X11 Alessandro Rubini
2013-08-07 10:17 ` [PATCH 05/26] drivers/amba: add support for a PCI bridge Alessandro Rubini
2013-08-07 10:17 ` [PATCH 06/26] x86 STA2X11: select devicetree related config items Davide Ciminaghi
2013-08-07 10:17 ` [PATCH 07/26] OF platform: export of_amba_device_create() Davide Ciminaghi
2013-08-07 10:17 ` [PATCH 08/26] OF platform, of_amba_device_create(): add parent resource to parameters Davide Ciminaghi
2013-08-07 10:17 ` [PATCH 09/26] kernel irqdomain: export irq_domain_disassociate() Davide Ciminaghi
2013-08-07 10:19 ` [PATCH 10/26] x86 devicetree: add irq domain for msi irqs Davide Ciminaghi
2013-08-07 10:19 ` [PATCH 11/26] x86 devicetree: add functions for handling setup/teardown of MSI irqs Davide Ciminaghi
2013-08-07 10:19 ` [PATCH 12/26] x86 kernel apic: notify MSI irqdomain(s) on etup/teardown of MSI IRQs Davide Ciminaghi
2013-08-07 10:19 ` [PATCH 13/26] drivers/amba/pci-amba.c: use devicetree for amba device creation Davide Ciminaghi
2013-08-07 10:19 ` [PATCH 14/26] gpio: remove sta2x11-gpio Davide Ciminaghi
2013-08-07 19:49   ` Linus Walleij
2013-08-07 10:20 ` [PATCH 15/26] x86 STA2X11: remove the sta2x11-mfd driver Davide Ciminaghi
2013-08-07 10:20 ` [PATCH 16/26] x86 STA2X11 platform: add sta2x11_platform_init() Davide Ciminaghi
2013-08-07 10:20 ` [PATCH 17/26] x86 STA2X11 platform: add sta2x11_instance_data helpers Davide Ciminaghi
2013-08-07 10:20 ` [PATCH 18/26] x86 STA2X11 platform: add a common probe function for platform devices Davide Ciminaghi
2013-08-07 10:20 ` [PATCH 19/26] x86 STA2X11 platform: create sta2x11-clock-regs device Davide Ciminaghi
2013-08-07 10:20 ` [PATCH 20/26] x86 STA2X11 platform: remove useless pr_info()'s Davide Ciminaghi
2013-08-07 10:21 ` [PATCH 21/26] AMBA: pci-amba bridge: improve code readability Davide Ciminaghi
2013-08-07 10:21 ` [PATCH 22/26] AMBA: pci-amba bridge: extend number of amba devs per pci device Davide Ciminaghi
2013-08-07 10:21 ` [PATCH 23/26] AMBA: pci-amba bridge: export function creating pci-amba device names Davide Ciminaghi
2013-08-07 10:21 ` [PATCH 24/26] x86 STA2X11: add dts for Intel's Northville board Davide Ciminaghi
2013-08-07 10:21 ` [PATCH 25/26] drivers/clk: sta2x11 common clock framework implementation Davide Ciminaghi
2013-08-07 10:22 ` [PATCH 26/26] pinctrl: add support for sta2x11 (via pinctrl-nomadik) Davide Ciminaghi
2013-08-07 19:47   ` Linus Walleij
2013-08-07 20:43   ` Alessandro Rubini
2013-08-07 15:41 ` [PATCH 00/26] STA2X11 devicetree support for amba/pci H. Peter Anvin
2013-08-07 21:12 ` Alessandro Rubini
2013-08-07 21:15   ` H. Peter Anvin
2013-08-07 22:05   ` H. Peter Anvin
2013-08-07 22:12   ` H. Peter Anvin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.