[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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
Signed-off-by: Davide Ciminaghi <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
.../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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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
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 <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Acked-by: Giancarlo Asnaghi <[email protected]>
[Davide Ciminaghi <[email protected]>: only registers prefixed]
Signed-off-by: Davide Ciminaghi <[email protected]>
Acked-by: Jassi Brar <[email protected]>
Signed-off-by: H. Peter Anvin <[email protected]>
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
For portability, use <linux/sizes.h>.
Signed-off-by: Alessandro Rubini <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Acked-by: Giancarlo Asnaghi <[email protected]>
Acked-by: David Brown <[email protected]>
Signed-off-by: H. Peter Anvin <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
Cc: Russell King <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
.../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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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, ®s->dats);
- else
- writel(bit, ®s->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(®s->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, ®s->dirs);
- /* Data register after direction, otherwise pullup/down is selected */
- if (val)
- writel(bit, ®s->dats);
- else
- writel(bit, ®s->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, ®s->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(®s->afsela);
- if (cfg == PINMUX_TYPE_FUNCTION)
- val |= bit;
- else
- val &= ~bit;
- writel(val | bit, ®s->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, ®s->dirs);
- writel(bit, ®s->datc);
- break;
- case PINMUX_TYPE_OUTPUT_HIGH:
- writel(bit, ®s->dirs);
- writel(bit, ®s->dats);
- break;
- case PINMUX_TYPE_INPUT:
- writel(bit, ®s->dirc);
- val = readl(®s->pdis) | bit;
- writel(val, ®s->pdis);
- break;
- case PINMUX_TYPE_INPUT_PULLUP:
- writel(bit, ®s->dirc);
- val = readl(®s->pdis) & ~bit;
- writel(val, ®s->pdis);
- writel(bit, ®s->dats);
- break;
- case PINMUX_TYPE_INPUT_PULLDOWN:
- writel(bit, ®s->dirc);
- val = readl(®s->pdis) & ~bit;
- writel(val, ®s->pdis);
- writel(bit, ®s->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(®s->rimsc) & ~bit;
- writel(val, ®s->rimsc);
- }
- if (chip->irq_type[nr] & IRQ_TYPE_EDGE_FALLING) {
- val = readl(®s->fimsc) & ~bit;
- writel(val, ®s->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(®s->rimsc);
- if (type & IRQ_TYPE_EDGE_RISING)
- writel(val | bit, ®s->rimsc);
- else
- writel(val & ~bit, ®s->rimsc);
- val = readl(®s->rimsc);
- if (type & IRQ_TYPE_EDGE_FALLING)
- writel(val | bit, ®s->fimsc);
- else
- writel(val & ~bit, ®s->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(®s->is))) {
- nr = __ffs(is);
- irq = base + nr;
- generic_handle_irq(irq);
- writel(1 << nr, ®s->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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
Signed-off-by: Davide Ciminaghi <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
This patch moves the code fixing up irq numbers for amba devices
to a separate function (fixup_amba_irqs()).
Signed-off-by: Davide Ciminaghi <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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 <[email protected]>
Acked-by: Giancarlo Asnaghi <[email protected]>
---
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
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
On Wed, Aug 7, 2013 at 12:22 PM, Davide Ciminaghi <[email protected]> wrote:
> Signed-off-by: Davide Ciminaghi <[email protected]>
> Acked-by: Giancarlo Asnaghi <[email protected]>
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 <[email protected]>
Yours,
Linus Walleij
On Wed, Aug 7, 2013 at 12:19 PM, Davide Ciminaghi <[email protected]> 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 <[email protected]>
> Acked-by: Giancarlo Asnaghi <[email protected]>
Seems we should have discovered this earlier ;-)
I'd be happy to apply this too.
Acked-by: Linus Walleij <[email protected]>
If you want I can apply this and the pinctrl patch to my
pinctrl tree for a consistent switch-over.
Yours,
Linus Walleij
> 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 <[email protected]>
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
[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
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
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
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