]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Revert "Revert vexpress/soc"
authorArnd Bergmann <arnd@arndb.de>
Mon, 5 Nov 2012 17:24:18 +0000 (18:24 +0100)
committerArnd Bergmann <arnd@arndb.de>
Mon, 5 Nov 2012 17:24:18 +0000 (18:24 +0100)
This reverts commit a6ec79157d51c2e9898ae4892cc3d438beff8290.

20 files changed:
Documentation/devicetree/bindings/arm/vexpress-sysreg.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/vexpress.txt
arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
arch/arm/boot/dts/vexpress-v2m.dtsi
arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
arch/arm/boot/dts/vexpress-v2p-ca5s.dts
arch/arm/boot/dts/vexpress-v2p-ca9.dts
arch/arm/include/asm/hardware/sp810.h
arch/arm/mach-vexpress/Kconfig
arch/arm/mach-vexpress/Makefile
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/include/mach/motherboard.h
arch/arm/mach-vexpress/platsmp.c
arch/arm/mach-vexpress/v2m.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/vexpress-config.c [new file with mode: 0644]
drivers/mfd/vexpress-sysreg.c [new file with mode: 0644]
include/linux/vexpress.h [new file with mode: 0644]

diff --git a/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt b/Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
new file mode 100644 (file)
index 0000000..9cf3f25
--- /dev/null
@@ -0,0 +1,50 @@
+ARM Versatile Express system registers
+--------------------------------------
+
+This is a system control registers block, providing multiple low level
+platform functions like board detection and identification, software
+interrupt generation, MMC and NOR Flash control etc.
+
+Required node properties:
+- compatible value : = "arm,vexpress,sysreg";
+- reg : physical base address and the size of the registers window
+- gpio-controller : specifies that the node is a GPIO controller
+- #gpio-cells : size of the GPIO specifier, should be 2:
+  - first cell is the pseudo-GPIO line number:
+    0 - MMC CARDIN
+    1 - MMC WPROT
+    2 - NOR FLASH WPn
+  - second cell can take standard GPIO flags (currently ignored).
+
+Example:
+       v2m_sysreg: sysreg@10000000 {
+               compatible = "arm,vexpress-sysreg";
+               reg = <0x10000000 0x1000>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+This block also can also act a bridge to the platform's configuration
+bus via "system control" interface, addressing devices with site number,
+position in the board stack, config controller, function and device
+numbers - see motherboard's TRM for more details.
+
+The node describing a config device must refer to the sysreg node via
+"arm,vexpress,config-bridge" phandle (can be also defined in the node's
+parent) and relies on the board topology properties - see main vexpress
+node documentation for more details. It must must also define the
+following property:
+- arm,vexpress-sysreg,func : must contain two cells:
+  - first cell defines function number (eg. 1 for clock generator,
+    2 for voltage regulators etc.)
+  - device number (eg. osc 0, osc 1 etc.)
+
+Example:
+       mcc {
+               arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+               osc@0 {
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 0>;
+               };
+       };
index ec8b50cbb2e8ed5c6a14e0068be7b85f4ffcc789..ae49161e478ae556a31cb9eed4bc66e50daf9c70 100644 (file)
@@ -11,6 +11,10 @@ the motherboard file using a /include/ directive. As the motherboard
 can be initialized in one of two different configurations ("memory
 maps"), care must be taken to include the correct one.
 
+
+Root node
+---------
+
 Required properties in the root node:
 - compatible value:
        compatible = "arm,vexpress,<model>", "arm,vexpress";
@@ -45,6 +49,10 @@ Optional properties in the root node:
   - Coretile Express A9x4 (V2P-CA9) HBI-0225:
        arm,hbi = <0x225>;
 
+
+CPU nodes
+---------
+
 Top-level standard "cpus" node is required. It must contain a node
 with device_type = "cpu" property for every available core, eg.:
 
@@ -59,6 +67,52 @@ with device_type = "cpu" property for every available core, eg.:
                };
        };
 
+
+Configuration infrastructure
+----------------------------
+
+The platform has an elaborated configuration system, consisting of
+microcontrollers residing on the mother- and daughterboards known
+as Motherboard/Daughterboard Configuration Controller (MCC and DCC).
+The controllers are responsible for the platform initialization
+(reset generation, flash programming, FPGA bitfiles loading etc.)
+but also control clock generators, voltage regulators, gather
+environmental data like temperature, power consumption etc. Even
+the video output switch (FPGA) is controlled that way.
+
+Nodes describing devices controlled by this infrastructure should
+point at the bridge device node:
+- bridge phandle:
+       arm,vexpress,config-bridge = <phandle>;
+This property can be also defined in a parent node (eg. for a DCC)
+and is effective for all children.
+
+
+Platform topology
+-----------------
+
+As Versatile Express can be configured in number of physically
+different setups, the device tree should describe platform topology.
+Root node and main motherboard node must define the following
+property, describing physical location of the children nodes:
+- site number:
+       arm,vexpress,site = <number>;
+  where 0 means motherboard, 1 or 2 are daugtherboard sites,
+  0xf means "master" site (site containing main CPU tile)
+- when daughterboards are stacked on one site, their position
+  in the stack be be described with:
+       arm,vexpress,position = <number>;
+- when describing tiles consisting more than one DCC, its number
+  can be described with:
+       arm,vexpress,dcc = <number>;
+
+Any of the numbers above defaults to zero if not defined in
+the node or any of its parent.
+
+
+Motherboard
+-----------
+
 The motherboard description file provides a single "motherboard" node
 using 2 address cells corresponding to the Static Memory Bus used
 between the motherboard and the tile. The first cell defines the Chip
@@ -87,22 +141,30 @@ can be used to obtain required phandle in the tile's "aliases" node:
 - SP804 timers:
        v2m_timer01 and v2m_timer23
 
-Current Linux implementation requires a "arm,v2m_timer" alias
-pointing at one of the motherboard's SP804 timers, if it is to be
-used as the system timer. This alias should be defined in the
-motherboard files.
+The tile description should define a "smb" node, describing the
+Static Memory Bus between the tile and motherboard. It must define
+the following properties:
+- "simple-bus" compatible value (to ensure creation of the children)
+       compatible = "simple-bus";
+- mapping of the SMB CS/offset addresses into main address space:
+       #address-cells = <2>;
+       #size-cells = <1>;
+       ranges = <...>;
+- interrupts mapping:
+       #interrupt-cells = <1>;
+       interrupt-map-mask = <0 0 63>;
+       interrupt-map = <...>;
 
-The tile description must define "ranges", "interrupt-map-mask" and
-"interrupt-map" properties to translate the motherboard's address
-and interrupt space into one used by the tile's processor.
 
-Abbreviated example:
+Example of a VE tile description (simplified)
+---------------------------------------------
 
 /dts-v1/;
 
 / {
        model = "V2P-CA5s";
        arm,hbi = <0x225>;
+       arm,vexpress,site = <0xf>;
        compatible = "arm,vexpress-v2p-ca5s", "arm,vexpress";
        interrupt-parent = <&gic>;
        #address-cells = <1>;
@@ -134,13 +196,29 @@ Abbreviated example:
                      <0x2c000100 0x100>;
        };
 
-       motherboard {
+       dcc {
+               compatible = "simple-bus";
+               arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+               osc@0 {
+                       compatible = "arm,vexpress-osc";
+               };
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
                /* CS0 is visible at 0x08000000 */
                ranges = <0 0 0x08000000 0x04000000>;
+
+               #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 63>;
                /* Active high IRQ 0 is connected to GIC's SPI0 */
                interrupt-map = <0 0 0 &gic 0 0 4>;
+
+               /include/ "vexpress-v2m-rs1.dtsi"
        };
 };
 
-/include/ "vexpress-v2m-rs1.dtsi"
index d8a827bd2bf3728984621d1c45d90b640e8373db..ac870fb3fa0d459b6639e5965f9cc2daecae14e2 100644 (file)
  * CHANGES TO vexpress-v2m.dtsi!
  */
 
-/ {
-       aliases {
-               arm,v2m_timer = &v2m_timer01;
-       };
-
        motherboard {
-               compatible = "simple-bus";
+               model = "V2M-P1";
+               arm,hbi = <0x190>;
+               arm,vexpress,site = <0>;
                arm,v2m-memory-map = "rs1";
+               compatible = "arm,vexpress,v2m-p1", "simple-bus";
                #address-cells = <2>; /* SMB chipselect number and offset */
                #size-cells = <1>;
                #interrupt-cells = <1>;
+               ranges;
 
                flash@0,00000000 {
                        compatible = "arm,vexpress-flash", "cfi-flash";
                        #size-cells = <1>;
                        ranges = <0 3 0 0x200000>;
 
-                       sysreg@010000 {
+                       v2m_sysreg: sysreg@010000 {
                                compatible = "arm,vexpress-sysreg";
                                reg = <0x010000 0x1000>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
                        };
 
-                       sysctl@020000 {
+                       v2m_sysctl: sysctl@020000 {
                                compatible = "arm,sp810", "arm,primecell";
                                reg = <0x020000 0x1000>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
+                               clock-names = "refclk", "timclk", "apb_pclk";
+                               #clock-cells = <1>;
+                               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
                        };
 
                        /* PCI-E I2C bus */
                                compatible = "arm,pl041", "arm,primecell";
                                reg = <0x040000 0x1000>;
                                interrupts = <11>;
+                               clocks = <&smbclk>;
+                               clock-names = "apb_pclk";
                        };
 
                        mmci@050000 {
                                compatible = "arm,pl180", "arm,primecell";
                                reg = <0x050000 0x1000>;
                                interrupts = <9 10>;
+                               cd-gpios = <&v2m_sysreg 0 0>;
+                               wp-gpios = <&v2m_sysreg 1 0>;
+                               max-frequency = <12000000>;
+                               vmmc-supply = <&v2m_fixed_3v3>;
+                               clocks = <&v2m_clk24mhz>, <&smbclk>;
+                               clock-names = "mclk", "apb_pclk";
                        };
 
                        kmi@060000 {
                                compatible = "arm,pl050", "arm,primecell";
                                reg = <0x060000 0x1000>;
                                interrupts = <12>;
+                               clocks = <&v2m_clk24mhz>, <&smbclk>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
                        };
 
                        kmi@070000 {
                                compatible = "arm,pl050", "arm,primecell";
                                reg = <0x070000 0x1000>;
                                interrupts = <13>;
+                               clocks = <&v2m_clk24mhz>, <&smbclk>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
                        };
 
                        v2m_serial0: uart@090000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x090000 0x1000>;
                                interrupts = <5>;
+                               clocks = <&v2m_oscclk2>, <&smbclk>;
+                               clock-names = "uartclk", "apb_pclk";
                        };
 
                        v2m_serial1: uart@0a0000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0a0000 0x1000>;
                                interrupts = <6>;
+                               clocks = <&v2m_oscclk2>, <&smbclk>;
+                               clock-names = "uartclk", "apb_pclk";
                        };
 
                        v2m_serial2: uart@0b0000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0b0000 0x1000>;
                                interrupts = <7>;
+                               clocks = <&v2m_oscclk2>, <&smbclk>;
+                               clock-names = "uartclk", "apb_pclk";
                        };
 
                        v2m_serial3: uart@0c0000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0c0000 0x1000>;
                                interrupts = <8>;
+                               clocks = <&v2m_oscclk2>, <&smbclk>;
+                               clock-names = "uartclk", "apb_pclk";
                        };
 
                        wdt@0f0000 {
                                compatible = "arm,sp805", "arm,primecell";
                                reg = <0x0f0000 0x1000>;
                                interrupts = <0>;
+                               clocks = <&v2m_refclk32khz>, <&smbclk>;
+                               clock-names = "wdogclk", "apb_pclk";
                        };
 
                        v2m_timer01: timer@110000 {
                                compatible = "arm,sp804", "arm,primecell";
                                reg = <0x110000 0x1000>;
                                interrupts = <2>;
+                               clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
                        };
 
                        v2m_timer23: timer@120000 {
                                compatible = "arm,sp804", "arm,primecell";
                                reg = <0x120000 0x1000>;
                                interrupts = <3>;
+                               clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
                        };
 
                        /* DVI I2C bus */
                                compatible = "arm,pl031", "arm,primecell";
                                reg = <0x170000 0x1000>;
                                interrupts = <4>;
+                               clocks = <&smbclk>;
+                               clock-names = "apb_pclk";
                        };
 
                        compact-flash@1a0000 {
                                compatible = "arm,pl111", "arm,primecell";
                                reg = <0x1f0000 0x1000>;
                                interrupts = <14>;
+                               clocks = <&v2m_oscclk1>, <&smbclk>;
+                               clock-names = "clcdclk", "apb_pclk";
                        };
                };
 
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
+
+               v2m_clk24mhz: clk24mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "v2m:clk24mhz";
+               };
+
+               v2m_refclk1mhz: refclk1mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <1000000>;
+                       clock-output-names = "v2m:refclk1mhz";
+               };
+
+               v2m_refclk32khz: refclk32khz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+                       clock-output-names = "v2m:refclk32khz";
+               };
+
+               mcc {
+                       compatible = "arm,vexpress,config-bus";
+                       arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+                       osc@0 {
+                               /* MCC static memory clock */
+                               compatible = "arm,vexpress-osc";
+                               arm,vexpress-sysreg,func = <1 0>;
+                               freq-range = <25000000 60000000>;
+                               #clock-cells = <0>;
+                               clock-output-names = "v2m:oscclk0";
+                       };
+
+                       v2m_oscclk1: osc@1 {
+                               /* CLCD clock */
+                               compatible = "arm,vexpress-osc";
+                               arm,vexpress-sysreg,func = <1 1>;
+                               freq-range = <23750000 63500000>;
+                               #clock-cells = <0>;
+                               clock-output-names = "v2m:oscclk1";
+                       };
+
+                       v2m_oscclk2: osc@2 {
+                               /* IO FPGA peripheral clock */
+                               compatible = "arm,vexpress-osc";
+                               arm,vexpress-sysreg,func = <1 2>;
+                               freq-range = <24000000 24000000>;
+                               #clock-cells = <0>;
+                               clock-output-names = "v2m:oscclk2";
+                       };
+
+                       volt@0 {
+                               /* Logic level voltage */
+                               compatible = "arm,vexpress-volt";
+                               arm,vexpress-sysreg,func = <2 0>;
+                               regulator-name = "VIO";
+                               regulator-always-on;
+                               label = "VIO";
+                       };
+
+                       temp@0 {
+                               /* MCC internal operating temperature */
+                               compatible = "arm,vexpress-temp";
+                               arm,vexpress-sysreg,func = <4 0>;
+                               label = "MCC";
+                       };
+
+                       reset@0 {
+                               compatible = "arm,vexpress-reset";
+                               arm,vexpress-sysreg,func = <5 0>;
+                       };
+
+                       muxfpga@0 {
+                               compatible = "arm,vexpress-muxfpga";
+                               arm,vexpress-sysreg,func = <7 0>;
+                       };
+
+                       shutdown@0 {
+                               compatible = "arm,vexpress-shutdown";
+                               arm,vexpress-sysreg,func = <8 0>;
+                       };
+
+                       reboot@0 {
+                               compatible = "arm,vexpress-reboot";
+                               arm,vexpress-sysreg,func = <9 0>;
+                       };
+
+                       dvimode@0 {
+                               compatible = "arm,vexpress-dvimode";
+                               arm,vexpress-sysreg,func = <11 0>;
+                       };
+               };
        };
-};
index dba53fd026bb3692ecf33d69d237a2f9356c4bd1..f1420368355bb2f91715526d4a057660f5480b71 100644 (file)
  * CHANGES TO vexpress-v2m-rs1.dtsi!
  */
 
-/ {
-       aliases {
-               arm,v2m_timer = &v2m_timer01;
-       };
-
        motherboard {
-               compatible = "simple-bus";
+               model = "V2M-P1";
+               arm,hbi = <0x190>;
+               arm,vexpress,site = <0>;
+               compatible = "arm,vexpress,v2m-p1", "simple-bus";
                #address-cells = <2>; /* SMB chipselect number and offset */
                #size-cells = <1>;
                #interrupt-cells = <1>;
+               ranges;
 
                flash@0,00000000 {
                        compatible = "arm,vexpress-flash", "cfi-flash";
                        #size-cells = <1>;
                        ranges = <0 7 0 0x20000>;
 
-                       sysreg@00000 {
+                       v2m_sysreg: sysreg@00000 {
                                compatible = "arm,vexpress-sysreg";
                                reg = <0x00000 0x1000>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
                        };
 
-                       sysctl@01000 {
+                       v2m_sysctl: sysctl@01000 {
                                compatible = "arm,sp810", "arm,primecell";
                                reg = <0x01000 0x1000>;
+                               clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
+                               clock-names = "refclk", "timclk", "apb_pclk";
+                               #clock-cells = <1>;
+                               clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
                        };
 
                        /* PCI-E I2C bus */
                                compatible = "arm,pl041", "arm,primecell";
                                reg = <0x04000 0x1000>;
                                interrupts = <11>;
+                               clocks = <&smbclk>;
+                               clock-names = "apb_pclk";
                        };
 
                        mmci@05000 {
                                compatible = "arm,pl180", "arm,primecell";
                                reg = <0x05000 0x1000>;
                                interrupts = <9 10>;
+                               cd-gpios = <&v2m_sysreg 0 0>;
+                               wp-gpios = <&v2m_sysreg 1 0>;
+                               max-frequency = <12000000>;
+                               vmmc-supply = <&v2m_fixed_3v3>;
+                               clocks = <&v2m_clk24mhz>, <&smbclk>;
+                               clock-names = "mclk", "apb_pclk";
                        };
 
                        kmi@06000 {
                                compatible = "arm,pl050", "arm,primecell";
                                reg = <0x06000 0x1000>;
                                interrupts = <12>;
+                               clocks = <&v2m_clk24mhz>, <&smbclk>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
                        };
 
                        kmi@07000 {
                                compatible = "arm,pl050", "arm,primecell";
                                reg = <0x07000 0x1000>;
                                interrupts = <13>;
+                               clocks = <&v2m_clk24mhz>, <&smbclk>;
+                               clock-names = "KMIREFCLK", "apb_pclk";
                        };
 
                        v2m_serial0: uart@09000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x09000 0x1000>;
                                interrupts = <5>;
+                               clocks = <&v2m_oscclk2>, <&smbclk>;
+                               clock-names = "uartclk", "apb_pclk";
                        };
 
                        v2m_serial1: uart@0a000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0a000 0x1000>;
                                interrupts = <6>;
+                               clocks = <&v2m_oscclk2>, <&smbclk>;
+                               clock-names = "uartclk", "apb_pclk";
                        };
 
                        v2m_serial2: uart@0b000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0b000 0x1000>;
                                interrupts = <7>;
+                               clocks = <&v2m_oscclk2>, <&smbclk>;
+                               clock-names = "uartclk", "apb_pclk";
                        };
 
                        v2m_serial3: uart@0c000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0c000 0x1000>;
                                interrupts = <8>;
+                               clocks = <&v2m_oscclk2>, <&smbclk>;
+                               clock-names = "uartclk", "apb_pclk";
                        };
 
                        wdt@0f000 {
                                compatible = "arm,sp805", "arm,primecell";
                                reg = <0x0f000 0x1000>;
                                interrupts = <0>;
+                               clocks = <&v2m_refclk32khz>, <&smbclk>;
+                               clock-names = "wdogclk", "apb_pclk";
                        };
 
                        v2m_timer01: timer@11000 {
                                compatible = "arm,sp804", "arm,primecell";
                                reg = <0x11000 0x1000>;
                                interrupts = <2>;
+                               clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
                        };
 
                        v2m_timer23: timer@12000 {
                                compatible = "arm,sp804", "arm,primecell";
                                reg = <0x12000 0x1000>;
                                interrupts = <3>;
+                               clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>;
+                               clock-names = "timclken1", "timclken2", "apb_pclk";
                        };
 
                        /* DVI I2C bus */
                                compatible = "arm,pl031", "arm,primecell";
                                reg = <0x17000 0x1000>;
                                interrupts = <4>;
+                               clocks = <&smbclk>;
+                               clock-names = "apb_pclk";
                        };
 
                        compact-flash@1a000 {
                                compatible = "arm,pl111", "arm,primecell";
                                reg = <0x1f000 0x1000>;
                                interrupts = <14>;
+                               clocks = <&v2m_oscclk1>, <&smbclk>;
+                               clock-names = "clcdclk", "apb_pclk";
                        };
                };
 
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
+
+               v2m_clk24mhz: clk24mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <24000000>;
+                       clock-output-names = "v2m:clk24mhz";
+               };
+
+               v2m_refclk1mhz: refclk1mhz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <1000000>;
+                       clock-output-names = "v2m:refclk1mhz";
+               };
+
+               v2m_refclk32khz: refclk32khz {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+                       clock-output-names = "v2m:refclk32khz";
+               };
+
+               mcc {
+                       compatible = "arm,vexpress,config-bus";
+                       arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+                       osc@0 {
+                               /* MCC static memory clock */
+                               compatible = "arm,vexpress-osc";
+                               arm,vexpress-sysreg,func = <1 0>;
+                               freq-range = <25000000 60000000>;
+                               #clock-cells = <0>;
+                               clock-output-names = "v2m:oscclk0";
+                       };
+
+                       v2m_oscclk1: osc@1 {
+                               /* CLCD clock */
+                               compatible = "arm,vexpress-osc";
+                               arm,vexpress-sysreg,func = <1 1>;
+                               freq-range = <23750000 63500000>;
+                               #clock-cells = <0>;
+                               clock-output-names = "v2m:oscclk1";
+                       };
+
+                       v2m_oscclk2: osc@2 {
+                               /* IO FPGA peripheral clock */
+                               compatible = "arm,vexpress-osc";
+                               arm,vexpress-sysreg,func = <1 2>;
+                               freq-range = <24000000 24000000>;
+                               #clock-cells = <0>;
+                               clock-output-names = "v2m:oscclk2";
+                       };
+
+                       volt@0 {
+                               /* Logic level voltage */
+                               compatible = "arm,vexpress-volt";
+                               arm,vexpress-sysreg,func = <2 0>;
+                               regulator-name = "VIO";
+                               regulator-always-on;
+                               label = "VIO";
+                       };
+
+                       temp@0 {
+                               /* MCC internal operating temperature */
+                               compatible = "arm,vexpress-temp";
+                               arm,vexpress-sysreg,func = <4 0>;
+                               label = "MCC";
+                       };
+
+                       reset@0 {
+                               compatible = "arm,vexpress-reset";
+                               arm,vexpress-sysreg,func = <5 0>;
+                       };
+
+                       muxfpga@0 {
+                               compatible = "arm,vexpress-muxfpga";
+                               arm,vexpress-sysreg,func = <7 0>;
+                       };
+
+                       shutdown@0 {
+                               compatible = "arm,vexpress-shutdown";
+                               arm,vexpress-sysreg,func = <8 0>;
+                       };
+
+                       reboot@0 {
+                               compatible = "arm,vexpress-reboot";
+                               arm,vexpress-sysreg,func = <9 0>;
+                       };
+
+                       dvimode@0 {
+                               compatible = "arm,vexpress-dvimode";
+                               arm,vexpress-sysreg,func = <11 0>;
+                       };
+               };
        };
-};
index d12b34ca05685fd04b0c500088c74740bcacfc84..a3d37ec2655d80efccae49ee9f85ca9c9b1213b1 100644 (file)
@@ -12,6 +12,7 @@
 / {
        model = "V2P-CA15";
        arm,hbi = <0x237>;
+       arm,vexpress,site = <0xf>;
        compatible = "arm,vexpress,v2p-ca15,tc1", "arm,vexpress,v2p-ca15", "arm,vexpress";
        interrupt-parent = <&gic>;
        #address-cells = <2>;
                compatible = "arm,hdlcd";
                reg = <0 0x2b000000 0 0x1000>;
                interrupts = <0 85 4>;
+               clocks = <&oscclk5>;
+               clock-names = "pxlclk";
        };
 
        memory-controller@2b0a0000 {
                compatible = "arm,pl341", "arm,primecell";
                reg = <0 0x2b0a0000 0 0x1000>;
+               clocks = <&oscclk7>;
+               clock-names = "apb_pclk";
        };
 
        wdt@2b060000 {
                compatible = "arm,sp805", "arm,primecell";
+               status = "disabled";
                reg = <0 0x2b060000 0 0x1000>;
                interrupts = <98>;
+               clocks = <&oscclk7>;
+               clock-names = "apb_pclk";
        };
 
        gic: interrupt-controller@2c001000 {
@@ -84,6 +92,8 @@
                reg = <0 0x7ffd0000 0 0x1000>;
                interrupts = <0 86 4>,
                             <0 87 4>;
+               clocks = <&oscclk7>;
+               clock-names = "apb_pclk";
        };
 
        dma@7ffb0000 {
                             <0 89 4>,
                             <0 90 4>,
                             <0 91 4>;
+               clocks = <&oscclk7>;
+               clock-names = "apb_pclk";
        };
 
        timer {
                             <0 69 4>;
        };
 
-       motherboard {
+       dcc {
+               compatible = "arm,vexpress,config-bus";
+               arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+               osc@0 {
+                       /* CPU PLL reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 0>;
+                       freq-range = <50000000 60000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk0";
+               };
+
+               osc@4 {
+                       /* Multiplexed AXI master clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 4>;
+                       freq-range = <20000000 40000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk4";
+               };
+
+               oscclk5: osc@5 {
+                       /* HDLCD PLL reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 5>;
+                       freq-range = <23750000 165000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk5";
+               };
+
+               smbclk: osc@6 {
+                       /* SMB clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 6>;
+                       freq-range = <20000000 50000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk6";
+               };
+
+               oscclk7: osc@7 {
+                       /* SYS PLL reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 7>;
+                       freq-range = <20000000 60000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk7";
+               };
+
+               osc@8 {
+                       /* DDR2 PLL reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 8>;
+                       freq-range = <40000000 40000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk8";
+               };
+
+               volt@0 {
+                       /* CPU core voltage */
+                       compatible = "arm,vexpress-volt";
+                       arm,vexpress-sysreg,func = <2 0>;
+                       regulator-name = "Cores";
+                       regulator-min-microvolt = <800000>;
+                       regulator-max-microvolt = <1050000>;
+                       regulator-always-on;
+                       label = "Cores";
+               };
+
+               amp@0 {
+                       /* Total current for the two cores */
+                       compatible = "arm,vexpress-amp";
+                       arm,vexpress-sysreg,func = <3 0>;
+                       label = "Cores";
+               };
+
+               temp@0 {
+                       /* DCC internal temperature */
+                       compatible = "arm,vexpress-temp";
+                       arm,vexpress-sysreg,func = <4 0>;
+                       label = "DCC";
+               };
+
+               power@0 {
+                       /* Total power */
+                       compatible = "arm,vexpress-power";
+                       arm,vexpress-sysreg,func = <12 0>;
+                       label = "Cores";
+               };
+
+               energy@0 {
+                       /* Total energy */
+                       compatible = "arm,vexpress-energy";
+                       arm,vexpress-sysreg,func = <13 0>;
+                       label = "Cores";
+               };
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
                ranges = <0 0 0 0x08000000 0x04000000>,
                         <1 0 0 0x14000000 0x04000000>,
                         <2 0 0 0x18000000 0x04000000>,
                         <4 0 0 0x0c000000 0x04000000>,
                         <5 0 0 0x10000000 0x04000000>;
 
+               #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 63>;
                interrupt-map = <0 0  0 &gic 0  0 4>,
                                <0 0  1 &gic 0  1 4>,
                                <0 0 40 &gic 0 40 4>,
                                <0 0 41 &gic 0 41 4>,
                                <0 0 42 &gic 0 42 4>;
+
+               /include/ "vexpress-v2m-rs1.dtsi"
        };
 };
-
-/include/ "vexpress-v2m-rs1.dtsi"
index 4890a81c5467e0862a9b86ad15f88e5dc0d11d47..1fc405a9ecfb0a4e6cacd94ba9442d6ce75575fa 100644 (file)
@@ -12,6 +12,7 @@
 / {
        model = "V2P-CA15_CA7";
        arm,hbi = <0x249>;
+       arm,vexpress,site = <0xf>;
        compatible = "arm,vexpress,v2p-ca15_a7", "arm,vexpress";
        interrupt-parent = <&gic>;
        #address-cells = <2>;
                compatible = "arm,sp805", "arm,primecell";
                reg = <0 0x2a490000 0 0x1000>;
                interrupts = <98>;
+               clocks = <&oscclk6a>, <&oscclk6a>;
+               clock-names = "wdogclk", "apb_pclk";
        };
 
        hdlcd@2b000000 {
                compatible = "arm,hdlcd";
                reg = <0 0x2b000000 0 0x1000>;
                interrupts = <0 85 4>;
+               clocks = <&oscclk5>;
+               clock-names = "pxlclk";
        };
 
        memory-controller@2b0a0000 {
                compatible = "arm,pl341", "arm,primecell";
                reg = <0 0x2b0a0000 0 0x1000>;
+               clocks = <&oscclk6a>;
+               clock-names = "apb_pclk";
        };
 
        gic: interrupt-controller@2c001000 {
                reg = <0 0x7ffd0000 0 0x1000>;
                interrupts = <0 86 4>,
                             <0 87 4>;
+               clocks = <&oscclk6a>;
+               clock-names = "apb_pclk";
        };
 
        dma@7ff00000 {
                             <0 89 4>,
                             <0 90 4>,
                             <0 91 4>;
+               clocks = <&oscclk6a>;
+               clock-names = "apb_pclk";
        };
 
        timer {
                             <0 69 4>;
        };
 
-       motherboard {
+       oscclk6a: oscclk6a {
+               /* Reference 24MHz clock */
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <24000000>;
+               clock-output-names = "oscclk6a";
+       };
+
+       dcc {
+               compatible = "arm,vexpress,config-bus";
+               arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+               osc@0 {
+                       /* A15 PLL 0 reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 0>;
+                       freq-range = <17000000 50000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk0";
+               };
+
+               osc@1 {
+                       /* A15 PLL 1 reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 1>;
+                       freq-range = <17000000 50000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk1";
+               };
+
+               osc@2 {
+                       /* A7 PLL 0 reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 2>;
+                       freq-range = <17000000 50000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk2";
+               };
+
+               osc@3 {
+                       /* A7 PLL 1 reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 3>;
+                       freq-range = <17000000 50000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk3";
+               };
+
+               osc@4 {
+                       /* External AXI master clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 4>;
+                       freq-range = <20000000 40000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk4";
+               };
+
+               oscclk5: osc@5 {
+                       /* HDLCD PLL reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 5>;
+                       freq-range = <23750000 165000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk5";
+               };
+
+               smbclk: osc@6 {
+                       /* Static memory controller clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 6>;
+                       freq-range = <20000000 40000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk6";
+               };
+
+               osc@7 {
+                       /* SYS PLL reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 7>;
+                       freq-range = <17000000 50000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk7";
+               };
+
+               osc@8 {
+                       /* DDR2 PLL reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 8>;
+                       freq-range = <20000000 50000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk8";
+               };
+
+               volt@0 {
+                       /* A15 CPU core voltage */
+                       compatible = "arm,vexpress-volt";
+                       arm,vexpress-sysreg,func = <2 0>;
+                       regulator-name = "A15 Vcore";
+                       regulator-min-microvolt = <800000>;
+                       regulator-max-microvolt = <1050000>;
+                       regulator-always-on;
+                       label = "A15 Vcore";
+               };
+
+               volt@1 {
+                       /* A7 CPU core voltage */
+                       compatible = "arm,vexpress-volt";
+                       arm,vexpress-sysreg,func = <2 1>;
+                       regulator-name = "A7 Vcore";
+                       regulator-min-microvolt = <800000>;
+                       regulator-max-microvolt = <1050000>;
+                       regulator-always-on;
+                       label = "A7 Vcore";
+               };
+
+               amp@0 {
+                       /* Total current for the two A15 cores */
+                       compatible = "arm,vexpress-amp";
+                       arm,vexpress-sysreg,func = <3 0>;
+                       label = "A15 Icore";
+               };
+
+               amp@1 {
+                       /* Total current for the three A7 cores */
+                       compatible = "arm,vexpress-amp";
+                       arm,vexpress-sysreg,func = <3 1>;
+                       label = "A7 Icore";
+               };
+
+               temp@0 {
+                       /* DCC internal temperature */
+                       compatible = "arm,vexpress-temp";
+                       arm,vexpress-sysreg,func = <4 0>;
+                       label = "DCC";
+               };
+
+               power@0 {
+                       /* Total power for the two A15 cores */
+                       compatible = "arm,vexpress-power";
+                       arm,vexpress-sysreg,func = <12 0>;
+                       label = "A15 Pcore";
+               };
+               power@1 {
+                       /* Total power for the three A7 cores */
+                       compatible = "arm,vexpress-power";
+                       arm,vexpress-sysreg,func = <12 1>;
+                       label = "A7 Pcore";
+               };
+
+               energy@0 {
+                       /* Total energy for the two A15 cores */
+                       compatible = "arm,vexpress-energy";
+                       arm,vexpress-sysreg,func = <13 0>;
+                       label = "A15 Jcore";
+               };
+
+               energy@2 {
+                       /* Total energy for the three A7 cores */
+                       compatible = "arm,vexpress-energy";
+                       arm,vexpress-sysreg,func = <13 2>;
+                       label = "A7 Jcore";
+               };
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
                ranges = <0 0 0 0x08000000 0x04000000>,
                         <1 0 0 0x14000000 0x04000000>,
                         <2 0 0 0x18000000 0x04000000>,
                         <4 0 0 0x0c000000 0x04000000>,
                         <5 0 0 0x10000000 0x04000000>;
 
+               #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 63>;
                interrupt-map = <0 0  0 &gic 0  0 4>,
                                <0 0  1 &gic 0  1 4>,
                                <0 0 40 &gic 0 40 4>,
                                <0 0 41 &gic 0 41 4>,
                                <0 0 42 &gic 0 42 4>;
+
+               /include/ "vexpress-v2m-rs1.dtsi"
        };
 };
-
-/include/ "vexpress-v2m-rs1.dtsi"
index 18917a0f86047a3a444919badb09fb47da244bc4..6328cbc71d3005931fecb40a796bcedd8c61ce1f 100644 (file)
@@ -12,6 +12,7 @@
 / {
        model = "V2P-CA5s";
        arm,hbi = <0x225>;
+       arm,vexpress,site = <0xf>;
        compatible = "arm,vexpress,v2p-ca5s", "arm,vexpress";
        interrupt-parent = <&gic>;
        #address-cells = <1>;
                compatible = "arm,hdlcd";
                reg = <0x2a110000 0x1000>;
                interrupts = <0 85 4>;
+               clocks = <&oscclk3>;
+               clock-names = "pxlclk";
        };
 
        memory-controller@2a150000 {
                compatible = "arm,pl341", "arm,primecell";
                reg = <0x2a150000 0x1000>;
+               clocks = <&oscclk1>;
+               clock-names = "apb_pclk";
        };
 
        memory-controller@2a190000 {
@@ -68,6 +73,8 @@
                reg = <0x2a190000 0x1000>;
                interrupts = <0 86 4>,
                             <0 87 4>;
+               clocks = <&oscclk1>;
+               clock-names = "apb_pclk";
        };
 
        scu@2c000000 {
                             <0 69 4>;
        };
 
-       motherboard {
+       dcc {
+               compatible = "arm,vexpress,config-bus";
+               arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+               osc@0 {
+                       /* CPU and internal AXI reference clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 0>;
+                       freq-range = <50000000 100000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk0";
+               };
+
+               oscclk1: osc@1 {
+                       /* Multiplexed AXI master clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 1>;
+                       freq-range = <5000000 50000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk1";
+               };
+
+               osc@2 {
+                       /* DDR2 */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 2>;
+                       freq-range = <80000000 120000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk2";
+               };
+
+               oscclk3: osc@3 {
+                       /* HDLCD */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 3>;
+                       freq-range = <23750000 165000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk3";
+               };
+
+               osc@4 {
+                       /* Test chip gate configuration */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 4>;
+                       freq-range = <80000000 80000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk4";
+               };
+
+               smbclk: osc@5 {
+                       /* SMB clock */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 5>;
+                       freq-range = <25000000 60000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "oscclk5";
+               };
+
+               temp@0 {
+                       /* DCC internal operating temperature */
+                       compatible = "arm,vexpress-temp";
+                       arm,vexpress-sysreg,func = <4 0>;
+                       label = "DCC";
+               };
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
                ranges = <0 0 0x08000000 0x04000000>,
                         <1 0 0x14000000 0x04000000>,
                         <2 0 0x18000000 0x04000000>,
                         <4 0 0x0c000000 0x04000000>,
                         <5 0 0x10000000 0x04000000>;
 
+               #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 63>;
                interrupt-map = <0 0  0 &gic 0  0 4>,
                                <0 0  1 &gic 0  1 4>,
                                <0 0 40 &gic 0 40 4>,
                                <0 0 41 &gic 0 41 4>,
                                <0 0 42 &gic 0 42 4>;
+
+               /include/ "vexpress-v2m-rs1.dtsi"
        };
 };
-
-/include/ "vexpress-v2m-rs1.dtsi"
index 3f0c736d31d6bca211d1c76550ed28ca841a3c56..1420bb14d95c9bdeecea3aff5598612df359b924 100644 (file)
@@ -12,6 +12,7 @@
 / {
        model = "V2P-CA9";
        arm,hbi = <0x191>;
+       arm,vexpress,site = <0xf>;
        compatible = "arm,vexpress,v2p-ca9", "arm,vexpress";
        interrupt-parent = <&gic>;
        #address-cells = <1>;
                compatible = "arm,pl111", "arm,primecell";
                reg = <0x10020000 0x1000>;
                interrupts = <0 44 4>;
+               clocks = <&oscclk1>, <&oscclk2>;
+               clock-names = "clcdclk", "apb_pclk";
        };
 
        memory-controller@100e0000 {
                compatible = "arm,pl341", "arm,primecell";
                reg = <0x100e0000 0x1000>;
+               clocks = <&oscclk2>;
+               clock-names = "apb_pclk";
        };
 
        memory-controller@100e1000 {
@@ -82,6 +87,8 @@
                reg = <0x100e1000 0x1000>;
                interrupts = <0 45 4>,
                             <0 46 4>;
+               clocks = <&oscclk2>;
+               clock-names = "apb_pclk";
        };
 
        timer@100e4000 {
                reg = <0x100e4000 0x1000>;
                interrupts = <0 48 4>,
                             <0 49 4>;
+               clocks = <&oscclk2>, <&oscclk2>;
+               clock-names = "timclk", "apb_pclk";
        };
 
        watchdog@100e5000 {
                compatible = "arm,sp805", "arm,primecell";
                reg = <0x100e5000 0x1000>;
                interrupts = <0 51 4>;
+               clocks = <&oscclk2>, <&oscclk2>;
+               clock-names = "wdogclk", "apb_pclk";
        };
 
        scu@1e000000 {
                             <0 63 4>;
        };
 
-       motherboard {
+       dcc {
+               compatible = "arm,vexpress,config-bus";
+               arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+               osc@0 {
+                       /* ACLK clock to the AXI master port on the test chip */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 0>;
+                       freq-range = <30000000 50000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "extsaxiclk";
+               };
+
+               oscclk1: osc@1 {
+                       /* Reference clock for the CLCD */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 1>;
+                       freq-range = <10000000 80000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "clcdclk";
+               };
+
+               smbclk: oscclk2: osc@2 {
+                       /* Reference clock for the test chip internal PLLs */
+                       compatible = "arm,vexpress-osc";
+                       arm,vexpress-sysreg,func = <1 2>;
+                       freq-range = <33000000 100000000>;
+                       #clock-cells = <0>;
+                       clock-output-names = "tcrefclk";
+               };
+
+               volt@0 {
+                       /* Test Chip internal logic voltage */
+                       compatible = "arm,vexpress-volt";
+                       arm,vexpress-sysreg,func = <2 0>;
+                       regulator-name = "VD10";
+                       regulator-always-on;
+                       label = "VD10";
+               };
+
+               volt@1 {
+                       /* PL310, L2 cache, RAM cell supply (not PL310 logic) */
+                       compatible = "arm,vexpress-volt";
+                       arm,vexpress-sysreg,func = <2 1>;
+                       regulator-name = "VD10_S2";
+                       regulator-always-on;
+                       label = "VD10_S2";
+               };
+
+               volt@2 {
+                       /* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
+                       compatible = "arm,vexpress-volt";
+                       arm,vexpress-sysreg,func = <2 2>;
+                       regulator-name = "VD10_S3";
+                       regulator-always-on;
+                       label = "VD10_S3";
+               };
+
+               volt@3 {
+                       /* DDR2 SDRAM and Test Chip DDR2 I/O supply */
+                       compatible = "arm,vexpress-volt";
+                       arm,vexpress-sysreg,func = <2 3>;
+                       regulator-name = "VCC1V8";
+                       regulator-always-on;
+                       label = "VCC1V8";
+               };
+
+               volt@4 {
+                       /* DDR2 SDRAM VTT termination voltage */
+                       compatible = "arm,vexpress-volt";
+                       arm,vexpress-sysreg,func = <2 4>;
+                       regulator-name = "DDR2VTT";
+                       regulator-always-on;
+                       label = "DDR2VTT";
+               };
+
+               volt@5 {
+                       /* Local board supply for miscellaneous logic external to the Test Chip */
+                       arm,vexpress-sysreg,func = <2 5>;
+                       compatible = "arm,vexpress-volt";
+                       regulator-name = "VCC3V3";
+                       regulator-always-on;
+                       label = "VCC3V3";
+               };
+
+               amp@0 {
+                       /* PL310, L2 cache, RAM cell supply (not PL310 logic) */
+                       compatible = "arm,vexpress-amp";
+                       arm,vexpress-sysreg,func = <3 0>;
+                       label = "VD10_S2";
+               };
+
+               amp@1 {
+                       /* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
+                       compatible = "arm,vexpress-amp";
+                       arm,vexpress-sysreg,func = <3 1>;
+                       label = "VD10_S3";
+               };
+
+               power@0 {
+                       /* PL310, L2 cache, RAM cell supply (not PL310 logic) */
+                       compatible = "arm,vexpress-power";
+                       arm,vexpress-sysreg,func = <12 0>;
+                       label = "PVD10_S2";
+               };
+
+               power@1 {
+                       /* Cortex-A9 system supply, Cores, MPEs, SCU and PL310 logic */
+                       compatible = "arm,vexpress-power";
+                       arm,vexpress-sysreg,func = <12 1>;
+                       label = "PVD10_S3";
+               };
+       };
+
+       smb {
+               compatible = "simple-bus";
+
+               #address-cells = <2>;
+               #size-cells = <1>;
                ranges = <0 0 0x40000000 0x04000000>,
                         <1 0 0x44000000 0x04000000>,
                         <2 0 0x48000000 0x04000000>,
                         <3 0 0x4c000000 0x04000000>,
                         <7 0 0x10000000 0x00020000>;
 
+               #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 63>;
                interrupt-map = <0 0  0 &gic 0  0 4>,
                                <0 0  1 &gic 0  1 4>,
                                <0 0 40 &gic 0 40 4>,
                                <0 0 41 &gic 0 41 4>,
                                <0 0 42 &gic 0 42 4>;
+
+               /include/ "vexpress-v2m.dtsi"
        };
 };
-
-/include/ "vexpress-v2m.dtsi"
index 6b9b077d86b3788fabb129c0b18bfb722724a697..2cdcf4476769d3e3aae22c07a4a670b780d8576e 100644 (file)
 #define SCPCELLID2             0xFF8
 #define SCPCELLID3             0xFFC
 
-#define SCCTRL_TIMEREN0SEL_REFCLK      (0 << 15)
-#define SCCTRL_TIMEREN0SEL_TIMCLK      (1 << 15)
-
-#define SCCTRL_TIMEREN1SEL_REFCLK      (0 << 17)
-#define SCCTRL_TIMEREN1SEL_TIMCLK      (1 << 17)
-
 static inline void sysctl_soft_reset(void __iomem *base)
 {
        /* switch to slow mode */
index c9529606620368d474a12917c8105012a50e560d..99e63f5f99d179eeeafbae428bd82444adbee747 100644 (file)
@@ -1,11 +1,12 @@
 config ARCH_VEXPRESS
        bool "ARM Ltd. Versatile Express family" if ARCH_MULTI_V7
-       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARCH_REQUIRE_GPIOLIB
        select ARM_AMBA
        select ARM_GIC
        select ARM_TIMER_SP804
        select CLKDEV_LOOKUP
        select COMMON_CLK
+       select COMMON_CLK_VERSATILE
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
@@ -17,6 +18,7 @@ config ARCH_VEXPRESS
        select PLAT_VERSATILE
        select PLAT_VERSATILE_CLCD
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
+       select VEXPRESS_CONFIG
        help
          This option enables support for systems using Cortex processor based
          ARM core and logic (FPGA) tiles on the Versatile Express motherboard,
index 42703e8b4d3bcdb674b99f4c01425e0dbcb44a21..80b64971fbddbbf07b8c03eb626c773529db1b5e 100644 (file)
@@ -4,7 +4,7 @@
 ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
        -I$(srctree)/arch/arm/plat-versatile/include
 
-obj-y                                  := v2m.o
+obj-y                                  := v2m.o reset.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)      += ct-ca9x4.o
 obj-$(CONFIG_SMP)                      += platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)              += hotplug.o
index 4f471fa3e3c577b2c3a0b24ee461096caf4e8e4f..60838ddb8564376efba0f6b5c1c1160154e0c343 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/clkdev.h>
+#include <linux/vexpress.h>
 
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
@@ -64,19 +65,6 @@ static void __init ct_ca9x4_init_irq(void)
        ca9x4_twd_init();
 }
 
-static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
-{
-       u32 site = v2m_get_master_site();
-
-       /*
-        * Old firmware was using the "site" component of the command
-        * to control the DVI muxer (while it should be always 0 ie. MB).
-        * Newer firmware uses the data register. Keep both for compatibility.
-        */
-       v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE(site), site);
-       v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE(SYS_CFG_SITE_MB), 2);
-}
-
 static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
 {
        unsigned long framesize = 1024 * 768 * 2;
@@ -93,7 +81,6 @@ static struct clcd_board ct_ca9x4_clcd_data = {
        .caps           = CLCD_CAP_5551 | CLCD_CAP_565,
        .check          = clcdfb_check,
        .decode         = clcdfb_decode,
-       .enable         = ct_ca9x4_clcd_enable,
        .setup          = ct_ca9x4_clcd_setup,
        .mmap           = versatile_clcd_mmap_dma,
        .remove         = versatile_clcd_remove_dma,
@@ -111,14 +98,6 @@ static struct amba_device *ct_ca9x4_amba_devs[] __initdata = {
        &gpio_device,
 };
 
-
-static struct v2m_osc ct_osc1 = {
-       .osc = 1,
-       .rate_min = 10000000,
-       .rate_max = 80000000,
-       .rate_default = 23750000,
-};
-
 static struct resource pmu_resources[] = {
        [0] = {
                .start  = IRQ_CT_CA9X4_PMU_CPU0,
@@ -149,10 +128,18 @@ static struct platform_device pmu_device = {
        .resource       = pmu_resources,
 };
 
+static struct platform_device osc1_device = {
+       .name           = "vexpress-osc",
+       .id             = 1,
+       .num_resources  = 1,
+       .resource       = (struct resource []) {
+               VEXPRESS_RES_FUNC(0xf, 1),
+       },
+};
+
 static void __init ct_ca9x4_init(void)
 {
        int i;
-       struct clk *clk;
 
 #ifdef CONFIG_CACHE_L2X0
        void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
@@ -164,14 +151,14 @@ static void __init ct_ca9x4_init(void)
        l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
 #endif
 
-       ct_osc1.site = v2m_get_master_site();
-       clk = v2m_osc_register("ct:osc1", &ct_osc1);
-       clk_register_clkdev(clk, NULL, "ct:clcd");
-
        for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
                amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
 
        platform_device_register(&pmu_device);
+       platform_device_register(&osc1_device);
+
+       WARN_ON(clk_register_clkdev(vexpress_osc_setup(&osc1_device.dev),
+                       NULL, "ct:clcd"));
 }
 
 #ifdef CONFIG_SMP
index 1e388c7bf4d72496dc4d586062d3f8c82753cd5a..68abc8b7278158d1d7041f81e886c9d0a478c389 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef __MACH_MOTHERBOARD_H
 #define __MACH_MOTHERBOARD_H
 
-#include <linux/clk-provider.h>
-
 /*
  * Physical addresses, offset from V2M_PA_CS0-3
  */
 #define V2M_CF                 (V2M_PA_CS7 + 0x0001a000)
 #define V2M_CLCD               (V2M_PA_CS7 + 0x0001f000)
 
-/*
- * Offsets from SYSREGS base
- */
-#define V2M_SYS_ID             0x000
-#define V2M_SYS_SW             0x004
-#define V2M_SYS_LED            0x008
-#define V2M_SYS_100HZ          0x024
-#define V2M_SYS_FLAGS          0x030
-#define V2M_SYS_FLAGSSET       0x030
-#define V2M_SYS_FLAGSCLR       0x034
-#define V2M_SYS_NVFLAGS                0x038
-#define V2M_SYS_NVFLAGSSET     0x038
-#define V2M_SYS_NVFLAGSCLR     0x03c
-#define V2M_SYS_MCI            0x048
-#define V2M_SYS_FLASH          0x03c
-#define V2M_SYS_CFGSW          0x058
-#define V2M_SYS_24MHZ          0x05c
-#define V2M_SYS_MISC           0x060
-#define V2M_SYS_DMA            0x064
-#define V2M_SYS_PROCID0                0x084
-#define V2M_SYS_PROCID1                0x088
-#define V2M_SYS_CFGDATA                0x0a0
-#define V2M_SYS_CFGCTRL                0x0a4
-#define V2M_SYS_CFGSTAT                0x0a8
-
 
 /*
  * Interrupts.  Those in {} are for AMBA devices
 #define IRQ_V2M_PCIE           (32 + 17)
 
 
-/*
- * Configuration
- */
-#define SYS_CFG_START          (1 << 31)
-#define SYS_CFG_WRITE          (1 << 30)
-#define SYS_CFG_OSC            (1 << 20)
-#define SYS_CFG_VOLT           (2 << 20)
-#define SYS_CFG_AMP            (3 << 20)
-#define SYS_CFG_TEMP           (4 << 20)
-#define SYS_CFG_RESET          (5 << 20)
-#define SYS_CFG_SCC            (6 << 20)
-#define SYS_CFG_MUXFPGA                (7 << 20)
-#define SYS_CFG_SHUTDOWN       (8 << 20)
-#define SYS_CFG_REBOOT         (9 << 20)
-#define SYS_CFG_DVIMODE                (11 << 20)
-#define SYS_CFG_POWER          (12 << 20)
-#define SYS_CFG_SITE(n)                ((n) << 16)
-#define SYS_CFG_SITE_MB                0
-#define SYS_CFG_SITE_DB1       1
-#define SYS_CFG_SITE_DB2       2
-#define SYS_CFG_STACK(n)       ((n) << 12)
-
-#define SYS_CFG_ERR            (1 << 1)
-#define SYS_CFG_COMPLETE       (1 << 0)
-
-int v2m_cfg_write(u32 devfn, u32 data);
-int v2m_cfg_read(u32 devfn, u32 *data);
-void v2m_flags_set(u32 data);
-
-/*
- * Miscellaneous
- */
-#define SYS_MISC_MASTERSITE    (1 << 14)
-#define SYS_PROCIDx_HBI_MASK   0xfff
-
-int v2m_get_master_site(void);
-
 /*
  * Core tile IDs
  */
@@ -149,21 +85,4 @@ struct ct_desc {
 
 extern struct ct_desc *ct_desc;
 
-/*
- * OSC clock provider
- */
-struct v2m_osc {
-       struct clk_hw hw;
-       u8 site; /* 0 = motherboard, 1 = site 1, 2 = site 2 */
-       u8 stack; /* board stack position */
-       u16 osc;
-       unsigned long rate_min;
-       unsigned long rate_max;
-       unsigned long rate_default;
-};
-
-#define to_v2m_osc(osc) container_of(osc, struct v2m_osc, hw)
-
-struct clk *v2m_osc_register(const char *name, struct v2m_osc *osc);
-
 #endif
index 7db27c8c05cc39572651ed76058c3a45b3914f71..c5d70de9bb4e20165fb9e6181e26f8cfafe3a0cb 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/smp.h>
 #include <linux/io.h>
 #include <linux/of_fdt.h>
+#include <linux/vexpress.h>
 
 #include <asm/smp_scu.h>
 #include <asm/hardware/gic.h>
@@ -193,7 +194,7 @@ static void __init vexpress_smp_prepare_cpus(unsigned int max_cpus)
         * until it receives a soft interrupt, and then the
         * secondary CPU branches to this address.
         */
-       v2m_flags_set(virt_to_phys(versatile_secondary_startup));
+       vexpress_flags_set(virt_to_phys(versatile_secondary_startup));
 }
 
 struct smp_operations __initdata vexpress_smp_ops = {
index 560e0df728f89931826f080cfe87dda6abcec128..4e168e81fb424827b2cf0fe2546df030ea41d31f 100644 (file)
 #include <linux/smsc911x.h>
 #include <linux/spinlock.h>
 #include <linux/usb/isp1760.h>
-#include <linux/clkdev.h>
-#include <linux/clk-provider.h>
 #include <linux/mtd/physmap.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
+#include <linux/vexpress.h>
 
 #include <asm/arch_timer.h>
 #include <asm/mach-types.h>
@@ -33,7 +32,6 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/hardware/timer-sp.h>
-#include <asm/hardware/sp810.h>
 
 #include <mach/ct-ca9x4.h>
 #include <mach/motherboard.h>
@@ -58,22 +56,6 @@ static struct map_desc v2m_io_desc[] __initdata = {
        },
 };
 
-static void __iomem *v2m_sysreg_base;
-
-static void __init v2m_sysctl_init(void __iomem *base)
-{
-       u32 scctrl;
-
-       if (WARN_ON(!base))
-               return;
-
-       /* Select 1MHz TIMCLK as the reference clock for SP804 timers */
-       scctrl = readl(base + SCCTRL);
-       scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK;
-       scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK;
-       writel(scctrl, base + SCCTRL);
-}
-
 static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
 {
        if (WARN_ON(!base || irq == NO_IRQ))
@@ -87,69 +69,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
 }
 
 
-static DEFINE_SPINLOCK(v2m_cfg_lock);
-
-int v2m_cfg_write(u32 devfn, u32 data)
-{
-       /* Configuration interface broken? */
-       u32 val;
-
-       printk("%s: writing %08x to %08x\n", __func__, data, devfn);
-
-       devfn |= SYS_CFG_START | SYS_CFG_WRITE;
-
-       spin_lock(&v2m_cfg_lock);
-       val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
-       writel(val & ~SYS_CFG_COMPLETE, v2m_sysreg_base + V2M_SYS_CFGSTAT);
-
-       writel(data, v2m_sysreg_base +  V2M_SYS_CFGDATA);
-       writel(devfn, v2m_sysreg_base + V2M_SYS_CFGCTRL);
-
-       do {
-               val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
-       } while (val == 0);
-       spin_unlock(&v2m_cfg_lock);
-
-       return !!(val & SYS_CFG_ERR);
-}
-
-int v2m_cfg_read(u32 devfn, u32 *data)
-{
-       u32 val;
-
-       devfn |= SYS_CFG_START;
-
-       spin_lock(&v2m_cfg_lock);
-       writel(0, v2m_sysreg_base + V2M_SYS_CFGSTAT);
-       writel(devfn, v2m_sysreg_base + V2M_SYS_CFGCTRL);
-
-       mb();
-
-       do {
-               cpu_relax();
-               val = readl(v2m_sysreg_base + V2M_SYS_CFGSTAT);
-       } while (val == 0);
-
-       *data = readl(v2m_sysreg_base + V2M_SYS_CFGDATA);
-       spin_unlock(&v2m_cfg_lock);
-
-       return !!(val & SYS_CFG_ERR);
-}
-
-void __init v2m_flags_set(u32 data)
-{
-       writel(~0, v2m_sysreg_base + V2M_SYS_FLAGSCLR);
-       writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET);
-}
-
-int v2m_get_master_site(void)
-{
-       u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
-
-       return misc & SYS_MISC_MASTERSITE ? SYS_CFG_SITE_DB2 : SYS_CFG_SITE_DB1;
-}
-
-
 static struct resource v2m_pcie_i2c_resource = {
        .start  = V2M_SERIAL_BUS_PCI,
        .end    = V2M_SERIAL_BUS_PCI + SZ_4K - 1,
@@ -237,14 +156,8 @@ static struct platform_device v2m_usb_device = {
        .dev.platform_data = &v2m_usb_config,
 };
 
-static void v2m_flash_set_vpp(struct platform_device *pdev, int on)
-{
-       writel(on != 0, v2m_sysreg_base + V2M_SYS_FLASH);
-}
-
 static struct physmap_flash_data v2m_flash_data = {
        .width          = 4,
-       .set_vpp        = v2m_flash_set_vpp,
 };
 
 static struct resource v2m_flash_resources[] = {
@@ -291,14 +204,61 @@ static struct platform_device v2m_cf_device = {
        .dev.platform_data = &v2m_pata_data,
 };
 
-static unsigned int v2m_mmci_status(struct device *dev)
-{
-       return readl(v2m_sysreg_base + V2M_SYS_MCI) & (1 << 0);
-}
-
 static struct mmci_platform_data v2m_mmci_data = {
        .ocr_mask       = MMC_VDD_32_33|MMC_VDD_33_34,
-       .status         = v2m_mmci_status,
+       .gpio_wp        = VEXPRESS_GPIO_MMC_WPROT,
+       .gpio_cd        = VEXPRESS_GPIO_MMC_CARDIN,
+};
+
+static struct resource v2m_sysreg_resources[] = {
+       {
+               .start  = V2M_SYSREGS,
+               .end    = V2M_SYSREGS + 0xfff,
+               .flags  = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device v2m_sysreg_device = {
+       .name           = "vexpress-sysreg",
+       .id             = -1,
+       .resource       = v2m_sysreg_resources,
+       .num_resources  = ARRAY_SIZE(v2m_sysreg_resources),
+};
+
+static struct platform_device v2m_muxfpga_device = {
+       .name           = "vexpress-muxfpga",
+       .id             = 0,
+       .num_resources  = 1,
+       .resource       = (struct resource []) {
+               VEXPRESS_RES_FUNC(0, 7),
+       }
+};
+
+static struct platform_device v2m_shutdown_device = {
+       .name           = "vexpress-shutdown",
+       .id             = 0,
+       .num_resources  = 1,
+       .resource       = (struct resource []) {
+               VEXPRESS_RES_FUNC(0, 8),
+       }
+};
+
+static struct platform_device v2m_reboot_device = {
+       .name           = "vexpress-reboot",
+       .id             = 0,
+       .num_resources  = 1,
+       .resource       = (struct resource []) {
+               VEXPRESS_RES_FUNC(0, 9),
+       }
+};
+
+static struct platform_device v2m_dvimode_device = {
+       .name           = "vexpress-dvimode",
+       .id             = 0,
+       .num_resources  = 1,
+       .resource       = (struct resource []) {
+               VEXPRESS_RES_FUNC(0, 11),
+       }
 };
 
 static AMBA_APB_DEVICE(aaci,  "mb:aaci",  0, V2M_AACI, IRQ_V2M_AACI, NULL);
@@ -325,123 +285,9 @@ static struct amba_device *v2m_amba_devs[] __initdata = {
        &rtc_device,
 };
 
-
-static unsigned long v2m_osc_recalc_rate(struct clk_hw *hw,
-               unsigned long parent_rate)
-{
-       struct v2m_osc *osc = to_v2m_osc(hw);
-
-       return !parent_rate ? osc->rate_default : parent_rate;
-}
-
-static long v2m_osc_round_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long *parent_rate)
-{
-       struct v2m_osc *osc = to_v2m_osc(hw);
-
-       if (WARN_ON(rate < osc->rate_min))
-               rate = osc->rate_min;
-
-       if (WARN_ON(rate > osc->rate_max))
-               rate = osc->rate_max;
-
-       return rate;
-}
-
-static int v2m_osc_set_rate(struct clk_hw *hw, unsigned long rate,
-               unsigned long parent_rate)
-{
-       struct v2m_osc *osc = to_v2m_osc(hw);
-
-       v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(osc->site) |
-                       SYS_CFG_STACK(osc->stack) | osc->osc, rate);
-
-       return 0;
-}
-
-static struct clk_ops v2m_osc_ops = {
-       .recalc_rate = v2m_osc_recalc_rate,
-       .round_rate = v2m_osc_round_rate,
-       .set_rate = v2m_osc_set_rate,
-};
-
-struct clk * __init v2m_osc_register(const char *name, struct v2m_osc *osc)
-{
-       struct clk_init_data init;
-
-       WARN_ON(osc->site > 2);
-       WARN_ON(osc->stack > 15);
-       WARN_ON(osc->osc > 4095);
-
-       init.name = name;
-       init.ops = &v2m_osc_ops;
-       init.flags = CLK_IS_ROOT;
-       init.num_parents = 0;
-
-       osc->hw.init = &init;
-
-       return clk_register(NULL, &osc->hw);
-}
-
-static struct v2m_osc v2m_mb_osc1 = {
-       .site = SYS_CFG_SITE_MB,
-       .osc = 1,
-       .rate_min = 23750000,
-       .rate_max = 63500000,
-       .rate_default = 23750000,
-};
-
-static const char *v2m_ref_clk_periphs[] __initconst = {
-       "mb:wdt",   "1000f000.wdt",  "1c0f0000.wdt",    /* SP805 WDT */
-};
-
-static const char *v2m_osc1_periphs[] __initconst = {
-       "mb:clcd",  "1001f000.clcd", "1c1f0000.clcd",   /* PL111 CLCD */
-};
-
-static const char *v2m_osc2_periphs[] __initconst = {
-       "mb:mmci",  "10005000.mmci", "1c050000.mmci",   /* PL180 MMCI */
-       "mb:kmi0",  "10006000.kmi",  "1c060000.kmi",    /* PL050 KMI0 */
-       "mb:kmi1",  "10007000.kmi",  "1c070000.kmi",    /* PL050 KMI1 */
-       "mb:uart0", "10009000.uart", "1c090000.uart",   /* PL011 UART0 */
-       "mb:uart1", "1000a000.uart", "1c0a0000.uart",   /* PL011 UART1 */
-       "mb:uart2", "1000b000.uart", "1c0b0000.uart",   /* PL011 UART2 */
-       "mb:uart3", "1000c000.uart", "1c0c0000.uart",   /* PL011 UART3 */
-};
-
-static void __init v2m_clk_init(void)
-{
-       struct clk *clk;
-       int i;
-
-       clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
-                       CLK_IS_ROOT, 0);
-       WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
-
-       clk = clk_register_fixed_rate(NULL, "mb:ref_clk", NULL,
-                       CLK_IS_ROOT, 32768);
-       for (i = 0; i < ARRAY_SIZE(v2m_ref_clk_periphs); i++)
-               WARN_ON(clk_register_clkdev(clk, NULL, v2m_ref_clk_periphs[i]));
-
-       clk = clk_register_fixed_rate(NULL, "mb:sp804_clk", NULL,
-                       CLK_IS_ROOT, 1000000);
-       WARN_ON(clk_register_clkdev(clk, "v2m-timer0", "sp804"));
-       WARN_ON(clk_register_clkdev(clk, "v2m-timer1", "sp804"));
-
-       clk = v2m_osc_register("mb:osc1", &v2m_mb_osc1);
-       for (i = 0; i < ARRAY_SIZE(v2m_osc1_periphs); i++)
-               WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc1_periphs[i]));
-
-       clk = clk_register_fixed_rate(NULL, "mb:osc2", NULL,
-                       CLK_IS_ROOT, 24000000);
-       for (i = 0; i < ARRAY_SIZE(v2m_osc2_periphs); i++)
-               WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc2_periphs[i]));
-}
-
 static void __init v2m_timer_init(void)
 {
-       v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
-       v2m_clk_init();
+       vexpress_clk_init(ioremap(V2M_SYSCTL, SZ_4K));
        v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
 }
 
@@ -453,19 +299,7 @@ static void __init v2m_init_early(void)
 {
        if (ct_desc->init_early)
                ct_desc->init_early();
-       versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
-}
-
-static void v2m_power_off(void)
-{
-       if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))
-               printk(KERN_EMERG "Unable to shutdown\n");
-}
-
-static void v2m_restart(char str, const char *cmd)
-{
-       if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))
-               printk(KERN_EMERG "Unable to reboot\n");
+       versatile_sched_clock_init(vexpress_get_24mhz_clock_base(), 24000000);
 }
 
 struct ct_desc *ct_desc;
@@ -482,7 +316,7 @@ static void __init v2m_populate_ct_desc(void)
        u32 current_tile_id;
 
        ct_desc = NULL;
-       current_tile_id = readl(v2m_sysreg_base + V2M_SYS_PROCID0)
+       current_tile_id = vexpress_get_procid(VEXPRESS_SITE_MASTER)
                                & V2M_CT_ID_MASK;
 
        for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
@@ -498,7 +332,7 @@ static void __init v2m_populate_ct_desc(void)
 static void __init v2m_map_io(void)
 {
        iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
-       v2m_sysreg_base = ioremap(V2M_SYSREGS, SZ_4K);
+       vexpress_sysreg_early_init(ioremap(V2M_SYSREGS, SZ_4K));
        v2m_populate_ct_desc();
        ct_desc->map_io();
 }
@@ -515,6 +349,12 @@ static void __init v2m_init(void)
        regulator_register_fixed(0, v2m_eth_supplies,
                        ARRAY_SIZE(v2m_eth_supplies));
 
+       platform_device_register(&v2m_muxfpga_device);
+       platform_device_register(&v2m_shutdown_device);
+       platform_device_register(&v2m_reboot_device);
+       platform_device_register(&v2m_dvimode_device);
+
+       platform_device_register(&v2m_sysreg_device);
        platform_device_register(&v2m_pcie_i2c_device);
        platform_device_register(&v2m_ddc_i2c_device);
        platform_device_register(&v2m_flash_device);
@@ -525,7 +365,7 @@ static void __init v2m_init(void)
        for (i = 0; i < ARRAY_SIZE(v2m_amba_devs); i++)
                amba_device_register(v2m_amba_devs[i], &iomem_resource);
 
-       pm_power_off = v2m_power_off;
+       pm_power_off = vexpress_power_off;
 
        ct_desc->init_tile();
 }
@@ -539,7 +379,7 @@ MACHINE_START(VEXPRESS, "ARM-Versatile Express")
        .timer          = &v2m_timer,
        .handle_irq     = gic_handle_irq,
        .init_machine   = v2m_init,
-       .restart        = v2m_restart,
+       .restart        = vexpress_restart,
 MACHINE_END
 
 static struct map_desc v2m_rs1_io_desc __initdata = {
@@ -580,20 +420,13 @@ void __init v2m_dt_map_io(void)
 
 void __init v2m_dt_init_early(void)
 {
-       struct device_node *node;
        u32 dt_hbi;
 
-       node = of_find_compatible_node(NULL, NULL, "arm,vexpress-sysreg");
-       v2m_sysreg_base = of_iomap(node, 0);
-       if (WARN_ON(!v2m_sysreg_base))
-               return;
+       vexpress_sysreg_of_early_init();
 
        /* Confirm board type against DT property, if available */
        if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
-               int site = v2m_get_master_site();
-               u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ?
-                               V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
-               u32 hbi = id & SYS_PROCIDx_HBI_MASK;
+               u32 hbi = vexpress_get_hbi(VEXPRESS_SITE_MASTER);
 
                if (WARN_ON(dt_hbi != hbi))
                        pr_warning("vexpress: DT HBI (%x) is not matching "
@@ -613,51 +446,47 @@ static void __init v2m_dt_init_irq(void)
 
 static void __init v2m_dt_timer_init(void)
 {
-       struct device_node *node;
-       const char *path;
-       int err;
+       struct device_node *node = NULL;
 
-       node = of_find_compatible_node(NULL, NULL, "arm,sp810");
-       v2m_sysctl_init(of_iomap(node, 0));
+       vexpress_clk_of_init();
 
-       v2m_clk_init();
+       do {
+               node = of_find_compatible_node(node, NULL, "arm,sp804");
+       } while (node && vexpress_get_site_by_node(node) != VEXPRESS_SITE_MB);
+       if (node) {
+               pr_info("Using SP804 '%s' as a clock & events source\n",
+                               node->full_name);
+               v2m_sp804_init(of_iomap(node, 0),
+                               irq_of_parse_and_map(node, 0));
+       }
 
-       err = of_property_read_string(of_aliases, "arm,v2m_timer", &path);
-       if (WARN_ON(err))
-               return;
-       node = of_find_node_by_path(path);
-       v2m_sp804_init(of_iomap(node, 0), irq_of_parse_and_map(node, 0));
        if (arch_timer_of_register() != 0)
                twd_local_timer_of_register();
 
        if (arch_timer_sched_clock_init() != 0)
-               versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
+               versatile_sched_clock_init(vexpress_get_24mhz_clock_base(),
+                               24000000);
 }
 
 static struct sys_timer v2m_dt_timer = {
        .init = v2m_dt_timer_init,
 };
 
-static struct of_dev_auxdata v2m_dt_auxdata_lookup[] __initdata = {
-       OF_DEV_AUXDATA("arm,vexpress-flash", V2M_NOR0, "physmap-flash",
-                       &v2m_flash_data),
-       OF_DEV_AUXDATA("arm,primecell", V2M_MMCI, "mb:mmci", &v2m_mmci_data),
-       /* RS1 memory map */
-       OF_DEV_AUXDATA("arm,vexpress-flash", 0x08000000, "physmap-flash",
-                       &v2m_flash_data),
-       OF_DEV_AUXDATA("arm,primecell", 0x1c050000, "mb:mmci", &v2m_mmci_data),
+static const struct of_device_id v2m_dt_bus_match[] __initconst = {
+       { .compatible = "simple-bus", },
+       { .compatible = "arm,amba-bus", },
+       { .compatible = "arm,vexpress,config-bus", },
        {}
 };
 
 static void __init v2m_dt_init(void)
 {
        l2x0_of_init(0x00400000, 0xfe0fffff);
-       of_platform_populate(NULL, of_default_bus_match_table,
-                       v2m_dt_auxdata_lookup, NULL);
-       pm_power_off = v2m_power_off;
+       of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL);
+       pm_power_off = vexpress_power_off;
 }
 
-const static char *v2m_dt_match[] __initconst = {
+static const char * const v2m_dt_match[] __initconst = {
        "arm,vexpress",
        "xen,xenvm",
        NULL,
@@ -672,5 +501,5 @@ DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")
        .timer          = &v2m_dt_timer,
        .init_machine   = v2m_dt_init,
        .handle_irq     = gic_handle_irq,
-       .restart        = v2m_restart,
+       .restart        = vexpress_restart,
 MACHINE_END
index acab3ef8a310efb611ccb30868c7f85474807d86..637bcdf8ce7776a696c9a456c39505fb2c131fe5 100644 (file)
@@ -1070,3 +1070,9 @@ config MCP_UCB1200_TS
        depends on MCP_UCB1200 && INPUT
 
 endmenu
+
+config VEXPRESS_CONFIG
+       bool
+       help
+         Platform configuration infrastructure for the ARM Ltd.
+         Versatile Express.
index d8ccb630ddb07f6fbdf821661181f2c5fe67bbce..296817c6c06f215703a66a25a55eafdb1539e3ee 100644 (file)
@@ -138,3 +138,4 @@ obj-$(CONFIG_MFD_RC5T583)   += rc5t583.o rc5t583-irq.o
 obj-$(CONFIG_MFD_SEC_CORE)     += sec-core.o sec-irq.o
 obj-$(CONFIG_MFD_SYSCON)       += syscon.o
 obj-$(CONFIG_MFD_LM3533)       += lm3533-core.o lm3533-ctrlbank.o
+obj-$(CONFIG_VEXPRESS_CONFIG)  += vexpress-config.o vexpress-sysreg.o
diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c
new file mode 100644 (file)
index 0000000..fae15d8
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define pr_fmt(fmt) "vexpress-config: " fmt
+
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/vexpress.h>
+
+
+#define VEXPRESS_CONFIG_MAX_BRIDGES 2
+
+struct vexpress_config_bridge {
+       struct device_node *node;
+       struct vexpress_config_bridge_info *info;
+       struct list_head transactions;
+       spinlock_t transactions_lock;
+} vexpress_config_bridges[VEXPRESS_CONFIG_MAX_BRIDGES];
+
+static DECLARE_BITMAP(vexpress_config_bridges_map,
+               ARRAY_SIZE(vexpress_config_bridges));
+static DEFINE_MUTEX(vexpress_config_bridges_mutex);
+
+struct vexpress_config_bridge *vexpress_config_bridge_register(
+               struct device_node *node,
+               struct vexpress_config_bridge_info *info)
+{
+       struct vexpress_config_bridge *bridge;
+       int i;
+
+       pr_debug("Registering bridge '%s'\n", info->name);
+
+       mutex_lock(&vexpress_config_bridges_mutex);
+       i = find_first_zero_bit(vexpress_config_bridges_map,
+                       ARRAY_SIZE(vexpress_config_bridges));
+       if (i >= ARRAY_SIZE(vexpress_config_bridges)) {
+               pr_err("Can't register more bridges!\n");
+               mutex_unlock(&vexpress_config_bridges_mutex);
+               return NULL;
+       }
+       __set_bit(i, vexpress_config_bridges_map);
+       bridge = &vexpress_config_bridges[i];
+
+       bridge->node = node;
+       bridge->info = info;
+       INIT_LIST_HEAD(&bridge->transactions);
+       spin_lock_init(&bridge->transactions_lock);
+
+       mutex_unlock(&vexpress_config_bridges_mutex);
+
+       return bridge;
+}
+
+void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
+{
+       struct vexpress_config_bridge __bridge = *bridge;
+       int i;
+
+       mutex_lock(&vexpress_config_bridges_mutex);
+       for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++)
+               if (&vexpress_config_bridges[i] == bridge)
+                       __clear_bit(i, vexpress_config_bridges_map);
+       mutex_unlock(&vexpress_config_bridges_mutex);
+
+       WARN_ON(!list_empty(&__bridge.transactions));
+       while (!list_empty(&__bridge.transactions))
+               cpu_relax();
+}
+
+
+struct vexpress_config_func {
+       struct vexpress_config_bridge *bridge;
+       void *func;
+};
+
+struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
+               struct device_node *node)
+{
+       struct device_node *bridge_node;
+       struct vexpress_config_func *func;
+       int i;
+
+       if (WARN_ON(dev && node && dev->of_node != node))
+               return NULL;
+       if (dev && !node)
+               node = dev->of_node;
+
+       func = kzalloc(sizeof(*func), GFP_KERNEL);
+       if (!func)
+               return NULL;
+
+       bridge_node = of_node_get(node);
+       while (bridge_node) {
+               const __be32 *prop = of_get_property(bridge_node,
+                               "arm,vexpress,config-bridge", NULL);
+
+               if (prop) {
+                       bridge_node = of_find_node_by_phandle(
+                                       be32_to_cpup(prop));
+                       break;
+               }
+
+               bridge_node = of_get_next_parent(bridge_node);
+       }
+
+       mutex_lock(&vexpress_config_bridges_mutex);
+       for (i = 0; i < ARRAY_SIZE(vexpress_config_bridges); i++) {
+               struct vexpress_config_bridge *bridge =
+                               &vexpress_config_bridges[i];
+
+               if (test_bit(i, vexpress_config_bridges_map) &&
+                               bridge->node == bridge_node) {
+                       func->bridge = bridge;
+                       func->func = bridge->info->func_get(dev, node);
+                       break;
+               }
+       }
+       mutex_unlock(&vexpress_config_bridges_mutex);
+
+       if (!func->func) {
+               of_node_put(node);
+               kfree(func);
+               return NULL;
+       }
+
+       return func;
+}
+
+void vexpress_config_func_put(struct vexpress_config_func *func)
+{
+       func->bridge->info->func_put(func->func);
+       of_node_put(func->bridge->node);
+       kfree(func);
+}
+
+
+struct vexpress_config_trans {
+       struct vexpress_config_func *func;
+       int offset;
+       bool write;
+       u32 *data;
+       int status;
+       struct completion completion;
+       struct list_head list;
+};
+
+static void vexpress_config_dump_trans(const char *what,
+               struct vexpress_config_trans *trans)
+{
+       pr_debug("%s %s trans %p func 0x%p offset %d data 0x%x status %d\n",
+                       what, trans->write ? "write" : "read", trans,
+                       trans->func->func, trans->offset,
+                       trans->data ? *trans->data : 0, trans->status);
+}
+
+static int vexpress_config_schedule(struct vexpress_config_trans *trans)
+{
+       int status;
+       struct vexpress_config_bridge *bridge = trans->func->bridge;
+       unsigned long flags;
+
+       init_completion(&trans->completion);
+       trans->status = -EFAULT;
+
+       spin_lock_irqsave(&bridge->transactions_lock, flags);
+
+       vexpress_config_dump_trans("Executing", trans);
+
+       if (list_empty(&bridge->transactions))
+               status = bridge->info->func_exec(trans->func->func,
+                               trans->offset, trans->write, trans->data);
+       else
+               status = VEXPRESS_CONFIG_STATUS_WAIT;
+
+       switch (status) {
+       case VEXPRESS_CONFIG_STATUS_DONE:
+               vexpress_config_dump_trans("Finished", trans);
+               trans->status = status;
+               break;
+       case VEXPRESS_CONFIG_STATUS_WAIT:
+               list_add_tail(&trans->list, &bridge->transactions);
+               break;
+       }
+
+       spin_unlock_irqrestore(&bridge->transactions_lock, flags);
+
+       return status;
+}
+
+void vexpress_config_complete(struct vexpress_config_bridge *bridge,
+               int status)
+{
+       struct vexpress_config_trans *trans;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bridge->transactions_lock, flags);
+
+       trans = list_first_entry(&bridge->transactions,
+                       struct vexpress_config_trans, list);
+       vexpress_config_dump_trans("Completed", trans);
+
+       trans->status = status;
+       list_del(&trans->list);
+
+       if (!list_empty(&bridge->transactions)) {
+               vexpress_config_dump_trans("Pending", trans);
+
+               bridge->info->func_exec(trans->func->func, trans->offset,
+                               trans->write, trans->data);
+       }
+       spin_unlock_irqrestore(&bridge->transactions_lock, flags);
+
+       complete(&trans->completion);
+}
+
+int vexpress_config_wait(struct vexpress_config_trans *trans)
+{
+       wait_for_completion(&trans->completion);
+
+       return trans->status;
+}
+
+
+int vexpress_config_read(struct vexpress_config_func *func, int offset,
+               u32 *data)
+{
+       struct vexpress_config_trans trans = {
+               .func = func,
+               .offset = offset,
+               .write = false,
+               .data = data,
+               .status = 0,
+       };
+       int status = vexpress_config_schedule(&trans);
+
+       if (status == VEXPRESS_CONFIG_STATUS_WAIT)
+               status = vexpress_config_wait(&trans);
+
+       return status;
+}
+EXPORT_SYMBOL(vexpress_config_read);
+
+int vexpress_config_write(struct vexpress_config_func *func, int offset,
+               u32 data)
+{
+       struct vexpress_config_trans trans = {
+               .func = func,
+               .offset = offset,
+               .write = true,
+               .data = &data,
+               .status = 0,
+       };
+       int status = vexpress_config_schedule(&trans);
+
+       if (status == VEXPRESS_CONFIG_STATUS_WAIT)
+               status = vexpress_config_wait(&trans);
+
+       return status;
+}
+EXPORT_SYMBOL(vexpress_config_write);
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
new file mode 100644 (file)
index 0000000..059d6b1
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/leds.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/slab.h>
+#include <linux/stat.h>
+#include <linux/timer.h>
+#include <linux/vexpress.h>
+
+#define SYS_ID                 0x000
+#define SYS_SW                 0x004
+#define SYS_LED                        0x008
+#define SYS_100HZ              0x024
+#define SYS_FLAGS              0x030
+#define SYS_FLAGSSET           0x030
+#define SYS_FLAGSCLR           0x034
+#define SYS_NVFLAGS            0x038
+#define SYS_NVFLAGSSET         0x038
+#define SYS_NVFLAGSCLR         0x03c
+#define SYS_MCI                        0x048
+#define SYS_FLASH              0x04c
+#define SYS_CFGSW              0x058
+#define SYS_24MHZ              0x05c
+#define SYS_MISC               0x060
+#define SYS_DMA                        0x064
+#define SYS_PROCID0            0x084
+#define SYS_PROCID1            0x088
+#define SYS_CFGDATA            0x0a0
+#define SYS_CFGCTRL            0x0a4
+#define SYS_CFGSTAT            0x0a8
+
+#define SYS_HBI_MASK           0xfff
+#define SYS_ID_HBI_SHIFT       16
+#define SYS_PROCIDx_HBI_SHIFT  0
+
+#define SYS_MCI_CARDIN         (1 << 0)
+#define SYS_MCI_WPROT          (1 << 1)
+
+#define SYS_FLASH_WPn          (1 << 0)
+
+#define SYS_MISC_MASTERSITE    (1 << 14)
+
+#define SYS_CFGCTRL_START      (1 << 31)
+#define SYS_CFGCTRL_WRITE      (1 << 30)
+#define SYS_CFGCTRL_DCC(n)     (((n) & 0xf) << 26)
+#define SYS_CFGCTRL_FUNC(n)    (((n) & 0x3f) << 20)
+#define SYS_CFGCTRL_SITE(n)    (((n) & 0x3) << 16)
+#define SYS_CFGCTRL_POSITION(n)        (((n) & 0xf) << 12)
+#define SYS_CFGCTRL_DEVICE(n)  (((n) & 0xfff) << 0)
+
+#define SYS_CFGSTAT_ERR                (1 << 1)
+#define SYS_CFGSTAT_COMPLETE   (1 << 0)
+
+
+static void __iomem *vexpress_sysreg_base;
+static struct device *vexpress_sysreg_dev;
+static int vexpress_master_site;
+
+
+void vexpress_flags_set(u32 data)
+{
+       writel(~0, vexpress_sysreg_base + SYS_FLAGSCLR);
+       writel(data, vexpress_sysreg_base + SYS_FLAGSSET);
+}
+
+u32 vexpress_get_procid(int site)
+{
+       if (site == VEXPRESS_SITE_MASTER)
+               site = vexpress_master_site;
+
+       return readl(vexpress_sysreg_base + (site == VEXPRESS_SITE_DB1 ?
+                       SYS_PROCID0 : SYS_PROCID1));
+}
+
+u32 vexpress_get_hbi(int site)
+{
+       u32 id;
+
+       switch (site) {
+       case VEXPRESS_SITE_MB:
+               id = readl(vexpress_sysreg_base + SYS_ID);
+               return (id >> SYS_ID_HBI_SHIFT) & SYS_HBI_MASK;
+       case VEXPRESS_SITE_MASTER:
+       case VEXPRESS_SITE_DB1:
+       case VEXPRESS_SITE_DB2:
+               id = vexpress_get_procid(site);
+               return (id >> SYS_PROCIDx_HBI_SHIFT) & SYS_HBI_MASK;
+       }
+
+       return ~0;
+}
+
+void __iomem *vexpress_get_24mhz_clock_base(void)
+{
+       return vexpress_sysreg_base + SYS_24MHZ;
+}
+
+
+static void vexpress_sysreg_find_prop(struct device_node *node,
+               const char *name, u32 *val)
+{
+       of_node_get(node);
+       while (node) {
+               if (of_property_read_u32(node, name, val) == 0) {
+                       of_node_put(node);
+                       return;
+               }
+               node = of_get_next_parent(node);
+       }
+}
+
+unsigned __vexpress_get_site(struct device *dev, struct device_node *node)
+{
+       u32 site = 0;
+
+       WARN_ON(dev && node && dev->of_node != node);
+       if (dev && !node)
+               node = dev->of_node;
+
+       if (node) {
+               vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
+       } else if (dev && dev->bus == &platform_bus_type) {
+               struct platform_device *pdev = to_platform_device(dev);
+
+               if (pdev->num_resources == 1 &&
+                               pdev->resource[0].flags == IORESOURCE_BUS)
+                       site = pdev->resource[0].start;
+       } else if (dev && strncmp(dev_name(dev), "ct:", 3) == 0) {
+               site = VEXPRESS_SITE_MASTER;
+       }
+
+       if (site == VEXPRESS_SITE_MASTER)
+               site = vexpress_master_site;
+
+       return site;
+}
+
+
+struct vexpress_sysreg_config_func {
+       u32 template;
+       u32 device;
+};
+
+static struct vexpress_config_bridge *vexpress_sysreg_config_bridge;
+static struct timer_list vexpress_sysreg_config_timer;
+static u32 *vexpress_sysreg_config_data;
+static int vexpress_sysreg_config_tries;
+
+static void *vexpress_sysreg_config_func_get(struct device *dev,
+               struct device_node *node)
+{
+       struct vexpress_sysreg_config_func *config_func;
+       u32 site;
+       u32 position = 0;
+       u32 dcc = 0;
+       u32 func_device[2];
+       int err = -EFAULT;
+
+       if (node) {
+               of_node_get(node);
+               vexpress_sysreg_find_prop(node, "arm,vexpress,site", &site);
+               vexpress_sysreg_find_prop(node, "arm,vexpress,position",
+                               &position);
+               vexpress_sysreg_find_prop(node, "arm,vexpress,dcc", &dcc);
+               err = of_property_read_u32_array(node,
+                               "arm,vexpress-sysreg,func", func_device,
+                               ARRAY_SIZE(func_device));
+               of_node_put(node);
+       } else if (dev && dev->bus == &platform_bus_type) {
+               struct platform_device *pdev = to_platform_device(dev);
+
+               if (pdev->num_resources == 1 &&
+                               pdev->resource[0].flags == IORESOURCE_BUS) {
+                       site = pdev->resource[0].start;
+                       func_device[0] = pdev->resource[0].end;
+                       func_device[1] = pdev->id;
+                       err = 0;
+               }
+       }
+       if (err)
+               return NULL;
+
+       config_func = kzalloc(sizeof(*config_func), GFP_KERNEL);
+       if (!config_func)
+               return NULL;
+
+       config_func->template = SYS_CFGCTRL_DCC(dcc);
+       config_func->template |= SYS_CFGCTRL_FUNC(func_device[0]);
+       config_func->template |= SYS_CFGCTRL_SITE(site == VEXPRESS_SITE_MASTER ?
+                       vexpress_master_site : site);
+       config_func->template |= SYS_CFGCTRL_POSITION(position);
+       config_func->device |= func_device[1];
+
+       dev_dbg(vexpress_sysreg_dev, "func 0x%p = 0x%x, %d\n", config_func,
+                       config_func->template, config_func->device);
+
+       return config_func;
+}
+
+static void vexpress_sysreg_config_func_put(void *func)
+{
+       kfree(func);
+}
+
+static int vexpress_sysreg_config_func_exec(void *func, int offset,
+               bool write, u32 *data)
+{
+       int status;
+       struct vexpress_sysreg_config_func *config_func = func;
+       u32 command;
+
+       if (WARN_ON(!vexpress_sysreg_base))
+               return -ENOENT;
+
+       command = readl(vexpress_sysreg_base + SYS_CFGCTRL);
+       if (WARN_ON(command & SYS_CFGCTRL_START))
+               return -EBUSY;
+
+       command = SYS_CFGCTRL_START;
+       command |= write ? SYS_CFGCTRL_WRITE : 0;
+       command |= config_func->template;
+       command |= SYS_CFGCTRL_DEVICE(config_func->device + offset);
+
+       /* Use a canary for reads */
+       if (!write)
+               *data = 0xdeadbeef;
+
+       dev_dbg(vexpress_sysreg_dev, "command %x, data %x\n",
+                       command, *data);
+       writel(*data, vexpress_sysreg_base + SYS_CFGDATA);
+       writel(0, vexpress_sysreg_base + SYS_CFGSTAT);
+       writel(command, vexpress_sysreg_base + SYS_CFGCTRL);
+       mb();
+
+       if (vexpress_sysreg_dev) {
+               /* Schedule completion check */
+               if (!write)
+                       vexpress_sysreg_config_data = data;
+               vexpress_sysreg_config_tries = 100;
+               mod_timer(&vexpress_sysreg_config_timer,
+                               jiffies + usecs_to_jiffies(100));
+               status = VEXPRESS_CONFIG_STATUS_WAIT;
+       } else {
+               /* Early execution, no timer available, have to spin */
+               u32 cfgstat;
+
+               do {
+                       cpu_relax();
+                       cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
+               } while (!cfgstat);
+
+               if (!write && (cfgstat & SYS_CFGSTAT_COMPLETE))
+                       *data = readl(vexpress_sysreg_base + SYS_CFGDATA);
+               status = VEXPRESS_CONFIG_STATUS_DONE;
+
+               if (cfgstat & SYS_CFGSTAT_ERR)
+                       status = -EINVAL;
+       }
+
+       return status;
+}
+
+struct vexpress_config_bridge_info vexpress_sysreg_config_bridge_info = {
+       .name = "vexpress-sysreg",
+       .func_get = vexpress_sysreg_config_func_get,
+       .func_put = vexpress_sysreg_config_func_put,
+       .func_exec = vexpress_sysreg_config_func_exec,
+};
+
+static void vexpress_sysreg_config_complete(unsigned long data)
+{
+       int status = VEXPRESS_CONFIG_STATUS_DONE;
+       u32 cfgstat = readl(vexpress_sysreg_base + SYS_CFGSTAT);
+
+       if (cfgstat & SYS_CFGSTAT_ERR)
+               status = -EINVAL;
+       if (!vexpress_sysreg_config_tries--)
+               status = -ETIMEDOUT;
+
+       if (status < 0) {
+               dev_err(vexpress_sysreg_dev, "error %d\n", status);
+       } else if (!(cfgstat & SYS_CFGSTAT_COMPLETE)) {
+               mod_timer(&vexpress_sysreg_config_timer,
+                               jiffies + usecs_to_jiffies(50));
+               return;
+       }
+
+       if (vexpress_sysreg_config_data) {
+               *vexpress_sysreg_config_data = readl(vexpress_sysreg_base +
+                               SYS_CFGDATA);
+               dev_dbg(vexpress_sysreg_dev, "read data %x\n",
+                               *vexpress_sysreg_config_data);
+               vexpress_sysreg_config_data = NULL;
+       }
+
+       vexpress_config_complete(vexpress_sysreg_config_bridge, status);
+}
+
+
+void __init vexpress_sysreg_early_init(void __iomem *base)
+{
+       struct device_node *node = of_find_compatible_node(NULL, NULL,
+                       "arm,vexpress-sysreg");
+
+       if (node)
+               base = of_iomap(node, 0);
+
+       if (WARN_ON(!base))
+               return;
+
+       vexpress_sysreg_base = base;
+
+       if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
+               vexpress_master_site = VEXPRESS_SITE_DB2;
+       else
+               vexpress_master_site = VEXPRESS_SITE_DB1;
+
+       vexpress_sysreg_config_bridge = vexpress_config_bridge_register(
+                       node, &vexpress_sysreg_config_bridge_info);
+       WARN_ON(!vexpress_sysreg_config_bridge);
+}
+
+void __init vexpress_sysreg_of_early_init(void)
+{
+       vexpress_sysreg_early_init(NULL);
+}
+
+
+static struct vexpress_sysreg_gpio {
+       unsigned long reg;
+       u32 value;
+} vexpress_sysreg_gpios[] = {
+       [VEXPRESS_GPIO_MMC_CARDIN] = {
+               .reg = SYS_MCI,
+               .value = SYS_MCI_CARDIN,
+       },
+       [VEXPRESS_GPIO_MMC_WPROT] = {
+               .reg = SYS_MCI,
+               .value = SYS_MCI_WPROT,
+       },
+       [VEXPRESS_GPIO_FLASH_WPn] = {
+               .reg = SYS_FLASH,
+               .value = SYS_FLASH_WPn,
+       },
+};
+
+static int vexpress_sysreg_gpio_direction_input(struct gpio_chip *chip,
+                                      unsigned offset)
+{
+       return 0;
+}
+
+static int vexpress_sysreg_gpio_direction_output(struct gpio_chip *chip,
+                                               unsigned offset, int value)
+{
+       return 0;
+}
+
+static int vexpress_sysreg_gpio_get(struct gpio_chip *chip,
+                                      unsigned offset)
+{
+       struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
+       u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
+
+       return !!(reg_value & gpio->value);
+}
+
+static void vexpress_sysreg_gpio_set(struct gpio_chip *chip,
+                                      unsigned offset, int value)
+{
+       struct vexpress_sysreg_gpio *gpio = &vexpress_sysreg_gpios[offset];
+       u32 reg_value = readl(vexpress_sysreg_base + gpio->reg);
+
+       if (value)
+               reg_value |= gpio->value;
+       else
+               reg_value &= ~gpio->value;
+
+       writel(reg_value, vexpress_sysreg_base + gpio->reg);
+}
+
+static struct gpio_chip vexpress_sysreg_gpio_chip = {
+       .label = "vexpress-sysreg",
+       .direction_input = vexpress_sysreg_gpio_direction_input,
+       .direction_output = vexpress_sysreg_gpio_direction_output,
+       .get = vexpress_sysreg_gpio_get,
+       .set = vexpress_sysreg_gpio_set,
+       .ngpio = ARRAY_SIZE(vexpress_sysreg_gpios),
+       .base = 0,
+};
+
+
+static ssize_t vexpress_sysreg_sys_id_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "0x%08x\n", readl(vexpress_sysreg_base + SYS_ID));
+}
+
+DEVICE_ATTR(sys_id, S_IRUGO, vexpress_sysreg_sys_id_show, NULL);
+
+static int __devinit vexpress_sysreg_probe(struct platform_device *pdev)
+{
+       int err;
+       struct resource *res = platform_get_resource(pdev,
+                       IORESOURCE_MEM, 0);
+
+       if (!devm_request_mem_region(&pdev->dev, res->start,
+                       resource_size(res), pdev->name)) {
+               dev_err(&pdev->dev, "Failed to request memory region!\n");
+               return -EBUSY;
+       }
+
+       if (!vexpress_sysreg_base)
+               vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
+                               resource_size(res));
+
+       if (!vexpress_sysreg_base) {
+               dev_err(&pdev->dev, "Failed to obtain base address!\n");
+               return -EFAULT;
+       }
+
+       setup_timer(&vexpress_sysreg_config_timer,
+                       vexpress_sysreg_config_complete, 0);
+
+       vexpress_sysreg_gpio_chip.dev = &pdev->dev;
+       err = gpiochip_add(&vexpress_sysreg_gpio_chip);
+       if (err) {
+               vexpress_config_bridge_unregister(
+                               vexpress_sysreg_config_bridge);
+               dev_err(&pdev->dev, "Failed to register GPIO chip! (%d)\n",
+                               err);
+               return err;
+       }
+
+       vexpress_sysreg_dev = &pdev->dev;
+
+       device_create_file(vexpress_sysreg_dev, &dev_attr_sys_id);
+
+       return 0;
+}
+
+static const struct of_device_id vexpress_sysreg_match[] = {
+       { .compatible = "arm,vexpress-sysreg", },
+       {},
+};
+
+static struct platform_driver vexpress_sysreg_driver = {
+       .driver = {
+               .name = "vexpress-sysreg",
+               .of_match_table = vexpress_sysreg_match,
+       },
+       .probe = vexpress_sysreg_probe,
+};
+
+static int __init vexpress_sysreg_init(void)
+{
+       return platform_driver_register(&vexpress_sysreg_driver);
+}
+core_initcall(vexpress_sysreg_init);
+
+
+#if defined(CONFIG_LEDS_CLASS)
+
+struct vexpress_sysreg_led {
+       u32 mask;
+       struct led_classdev cdev;
+} vexpress_sysreg_leds[] = {
+       { .mask = 1 << 0, .cdev.name = "v2m:green:user1",
+                       .cdev.default_trigger = "heartbeat", },
+       { .mask = 1 << 1, .cdev.name = "v2m:green:user2",
+                       .cdev.default_trigger = "mmc0", },
+       { .mask = 1 << 2, .cdev.name = "v2m:green:user3",
+                       .cdev.default_trigger = "cpu0", },
+       { .mask = 1 << 3, .cdev.name = "v2m:green:user4",
+                       .cdev.default_trigger = "cpu1", },
+       { .mask = 1 << 4, .cdev.name = "v2m:green:user5",
+                       .cdev.default_trigger = "cpu2", },
+       { .mask = 1 << 5, .cdev.name = "v2m:green:user6",
+                       .cdev.default_trigger = "cpu3", },
+       { .mask = 1 << 6, .cdev.name = "v2m:green:user7",
+                       .cdev.default_trigger = "cpu4", },
+       { .mask = 1 << 7, .cdev.name = "v2m:green:user8",
+                       .cdev.default_trigger = "cpu5", },
+};
+
+static DEFINE_SPINLOCK(vexpress_sysreg_leds_lock);
+
+static void vexpress_sysreg_led_brightness_set(struct led_classdev *cdev,
+               enum led_brightness brightness)
+{
+       struct vexpress_sysreg_led *led = container_of(cdev,
+                       struct vexpress_sysreg_led, cdev);
+       unsigned long flags;
+       u32 val;
+
+       spin_lock_irqsave(&vexpress_sysreg_leds_lock, flags);
+
+       val = readl(vexpress_sysreg_base + SYS_LED);
+       if (brightness == LED_OFF)
+               val &= ~led->mask;
+       else
+               val |= led->mask;
+       writel(val, vexpress_sysreg_base + SYS_LED);
+
+       spin_unlock_irqrestore(&vexpress_sysreg_leds_lock, flags);
+}
+
+static int __init vexpress_sysreg_init_leds(void)
+{
+       struct vexpress_sysreg_led *led;
+       int i;
+
+       /* Clear all user LEDs */
+       writel(0, vexpress_sysreg_base + SYS_LED);
+
+       for (i = 0, led = vexpress_sysreg_leds;
+                       i < ARRAY_SIZE(vexpress_sysreg_leds); i++, led++) {
+               int err;
+
+               led->cdev.brightness_set = vexpress_sysreg_led_brightness_set;
+               err = led_classdev_register(vexpress_sysreg_dev, &led->cdev);
+               if (err) {
+                       dev_err(vexpress_sysreg_dev,
+                                       "Failed to register LED %d! (%d)\n",
+                                       i, err);
+                       while (led--, i--)
+                               led_classdev_unregister(&led->cdev);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+device_initcall(vexpress_sysreg_init_leds);
+
+#endif
diff --git a/include/linux/vexpress.h b/include/linux/vexpress.h
new file mode 100644 (file)
index 0000000..c52215f
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#ifndef _LINUX_VEXPRESS_H
+#define _LINUX_VEXPRESS_H
+
+#include <linux/device.h>
+
+#define VEXPRESS_SITE_MB               0
+#define VEXPRESS_SITE_DB1              1
+#define VEXPRESS_SITE_DB2              2
+#define VEXPRESS_SITE_MASTER           0xf
+
+#define VEXPRESS_CONFIG_STATUS_DONE    0
+#define VEXPRESS_CONFIG_STATUS_WAIT    1
+
+#define VEXPRESS_GPIO_MMC_CARDIN       0
+#define VEXPRESS_GPIO_MMC_WPROT                1
+#define VEXPRESS_GPIO_FLASH_WPn                2
+
+#define VEXPRESS_RES_FUNC(_site, _func)        \
+{                                      \
+       .start = (_site),               \
+       .end = (_func),                 \
+       .flags = IORESOURCE_BUS,        \
+}
+
+/* Config bridge API */
+
+/**
+ * struct vexpress_config_bridge_info - description of the platform
+ * configuration infrastructure bridge.
+ *
+ * @name:      Bridge name
+ *
+ * @func_get:  Obtains pointer to a configuration function for a given
+ *             device or a Device Tree node, to be used with @func_put
+ *             and @func_exec. The node pointer should take precedence
+ *             over device pointer when both are passed.
+ *
+ * @func_put:  Tells the bridge that the function will not be used any
+ *             more, so all allocated resources can be released.
+ *
+ * @func_exec: Executes a configuration function read or write operation.
+ *             The offset selects a 32 bit word of the value accessed.
+ *             Must return VEXPRESS_CONFIG_STATUS_DONE when operation
+ *             is finished immediately, VEXPRESS_CONFIG_STATUS_WAIT when
+ *             will be completed in some time or negative value in case
+ *             of error.
+ */
+struct vexpress_config_bridge_info {
+       const char *name;
+       void *(*func_get)(struct device *dev, struct device_node *node);
+       void (*func_put)(void *func);
+       int (*func_exec)(void *func, int offset, bool write, u32 *data);
+};
+
+struct vexpress_config_bridge;
+
+struct vexpress_config_bridge *vexpress_config_bridge_register(
+               struct device_node *node,
+               struct vexpress_config_bridge_info *info);
+void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge);
+
+void vexpress_config_complete(struct vexpress_config_bridge *bridge,
+               int status);
+
+/* Config function API */
+
+struct vexpress_config_func;
+
+struct vexpress_config_func *__vexpress_config_func_get(struct device *dev,
+               struct device_node *node);
+#define vexpress_config_func_get_by_dev(dev) \
+               __vexpress_config_func_get(dev, NULL)
+#define vexpress_config_func_get_by_node(node) \
+               __vexpress_config_func_get(NULL, node)
+void vexpress_config_func_put(struct vexpress_config_func *func);
+
+/* Both may sleep! */
+int vexpress_config_read(struct vexpress_config_func *func, int offset,
+               u32 *data);
+int vexpress_config_write(struct vexpress_config_func *func, int offset,
+               u32 data);
+
+/* Platform control */
+
+u32 vexpress_get_procid(int site);
+u32 vexpress_get_hbi(int site);
+void *vexpress_get_24mhz_clock_base(void);
+void vexpress_flags_set(u32 data);
+
+#define vexpress_get_site_by_node(node) __vexpress_get_site(NULL, node)
+#define vexpress_get_site_by_dev(dev) __vexpress_get_site(dev, NULL)
+unsigned __vexpress_get_site(struct device *dev, struct device_node *node);
+
+void vexpress_sysreg_early_init(void __iomem *base);
+void vexpress_sysreg_of_early_init(void);
+
+void vexpress_power_off(void);
+void vexpress_restart(char str, const char *cmd);
+
+/* Clocks */
+
+struct clk *vexpress_osc_setup(struct device *dev);
+void vexpress_osc_of_setup(struct device_node *node);
+
+void vexpress_clk_init(void __iomem *sp810_base);
+void vexpress_clk_of_init(void);
+
+#endif