aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/vt8500.txt14
-rw-r--r--Documentation/devicetree/bindings/arm/vt8500/via,vt8500-intc.txt16
-rw-r--r--Documentation/devicetree/bindings/arm/vt8500/via,vt8500-pmc.txt13
-rw-r--r--Documentation/devicetree/bindings/arm/vt8500/via,vt8500-timer.txt15
-rw-r--r--Documentation/devicetree/bindings/clock/vt8500.txt72
-rw-r--r--Documentation/devicetree/bindings/gpio/gpio-vt8500.txt24
-rw-r--r--Documentation/devicetree/bindings/rtc/via,vt8500-rtc.txt15
-rw-r--r--Documentation/devicetree/bindings/tty/serial/via,vt8500-uart.txt17
-rw-r--r--Documentation/devicetree/bindings/usb/platform-uhci.txt15
-rw-r--r--Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt15
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt2
-rw-r--r--Documentation/devicetree/bindings/video/via,vt8500-fb.txt62
-rw-r--r--Documentation/devicetree/bindings/video/wm,prizm-ge-rops.txt13
-rw-r--r--Documentation/devicetree/bindings/video/wm,wm8505-fb.txt23
-rw-r--r--arch/arm/Kconfig7
-rw-r--r--arch/arm/boot/dts/vt8500-bv07.dts36
-rw-r--r--arch/arm/boot/dts/vt8500.dtsi116
-rw-r--r--arch/arm/boot/dts/wm8505-ref.dts36
-rw-r--r--arch/arm/boot/dts/wm8505.dtsi143
-rw-r--r--arch/arm/boot/dts/wm8650-mid.dts36
-rw-r--r--arch/arm/boot/dts/wm8650.dtsi147
-rw-r--r--arch/arm/mach-vt8500/Kconfig73
-rw-r--r--arch/arm/mach-vt8500/Makefile8
-rw-r--r--arch/arm/mach-vt8500/bv07.c80
-rw-r--r--arch/arm/mach-vt8500/common.h28
-rw-r--r--arch/arm/mach-vt8500/devices-vt8500.c91
-rw-r--r--arch/arm/mach-vt8500/devices-wm8505.c99
-rw-r--r--arch/arm/mach-vt8500/devices.c270
-rw-r--r--arch/arm/mach-vt8500/devices.h88
-rw-r--r--arch/arm/mach-vt8500/gpio.c240
-rw-r--r--arch/arm/mach-vt8500/include/mach/restart.h4
-rw-r--r--arch/arm/mach-vt8500/include/mach/vt8500_irqs.h88
-rw-r--r--arch/arm/mach-vt8500/include/mach/vt8500_regs.h79
-rw-r--r--arch/arm/mach-vt8500/include/mach/wm8505_irqs.h115
-rw-r--r--arch/arm/mach-vt8500/include/mach/wm8505_regs.h78
-rw-r--r--arch/arm/mach-vt8500/irq.c209
-rw-r--r--arch/arm/mach-vt8500/restart.c54
-rw-r--r--arch/arm/mach-vt8500/timer.c67
-rw-r--r--arch/arm/mach-vt8500/vt8500.c196
-rw-r--r--arch/arm/mach-vt8500/wm8505_7in.c79
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk-vt8500.c510
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-vt8500.c316
-rw-r--r--drivers/rtc/rtc-vt8500.c9
-rw-r--r--drivers/tty/serial/vt8500_serial.c58
-rw-r--r--drivers/video/Kconfig6
-rw-r--r--drivers/video/vt8500lcdfb.c79
-rw-r--r--drivers/video/wm8505fb.c97
-rw-r--r--drivers/video/wmt_ge_rops.c9
51 files changed, 2291 insertions, 1584 deletions
diff --git a/Documentation/devicetree/bindings/arm/vt8500.txt b/Documentation/devicetree/bindings/arm/vt8500.txt
new file mode 100644
index 000000000000..d657832c6819
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vt8500.txt
@@ -0,0 +1,14 @@
1VIA/Wondermedia VT8500 Platforms Device Tree Bindings
2---------------------------------------
3
4Boards with the VIA VT8500 SoC shall have the following properties:
5Required root node property:
6compatible = "via,vt8500";
7
8Boards with the Wondermedia WM8505 SoC shall have the following properties:
9Required root node property:
10compatible = "wm,wm8505";
11
12Boards with the Wondermedia WM8650 SoC shall have the following properties:
13Required root node property:
14compatible = "wm,wm8650";
diff --git a/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-intc.txt b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-intc.txt
new file mode 100644
index 000000000000..0a4ce1051b02
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-intc.txt
@@ -0,0 +1,16 @@
1VIA/Wondermedia VT8500 Interrupt Controller
2-----------------------------------------------------
3
4Required properties:
5- compatible : "via,vt8500-intc"
6- reg : Should contain 1 register ranges(address and length)
7- #interrupt-cells : should be <1>
8
9Example:
10
11 intc: interrupt-controller@d8140000 {
12 compatible = "via,vt8500-intc";
13 interrupt-controller;
14 reg = <0xd8140000 0x10000>;
15 #interrupt-cells = <1>;
16 };
diff --git a/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-pmc.txt b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-pmc.txt
new file mode 100644
index 000000000000..521b9c7de933
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-pmc.txt
@@ -0,0 +1,13 @@
1VIA/Wondermedia VT8500 Power Management Controller
2-----------------------------------------------------
3
4Required properties:
5- compatible : "via,vt8500-pmc"
6- reg : Should contain 1 register ranges(address and length)
7
8Example:
9
10 pmc@d8130000 {
11 compatible = "via,vt8500-pmc";
12 reg = <0xd8130000 0x1000>;
13 };
diff --git a/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-timer.txt b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-timer.txt
new file mode 100644
index 000000000000..901c73f0d8ef
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/vt8500/via,vt8500-timer.txt
@@ -0,0 +1,15 @@
1VIA/Wondermedia VT8500 Timer
2-----------------------------------------------------
3
4Required properties:
5- compatible : "via,vt8500-timer"
6- reg : Should contain 1 register ranges(address and length)
7- interrupts : interrupt for the timer
8
9Example:
10
11 timer@d8130100 {
12 compatible = "via,vt8500-timer";
13 reg = <0xd8130100 0x28>;
14 interrupts = <36>;
15 };
diff --git a/Documentation/devicetree/bindings/clock/vt8500.txt b/Documentation/devicetree/bindings/clock/vt8500.txt
new file mode 100644
index 000000000000..a880c70d0047
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/vt8500.txt
@@ -0,0 +1,72 @@
1Device Tree Clock bindings for arch-vt8500
2
3This binding uses the common clock binding[1].
4
5[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
6
7Required properties:
8- compatible : shall be one of the following:
9 "via,vt8500-pll-clock" - for a VT8500/WM8505 PLL clock
10 "wm,wm8650-pll-clock" - for a WM8650 PLL clock
11 "via,vt8500-device-clock" - for a VT/WM device clock
12
13Required properties for PLL clocks:
14- reg : shall be the control register offset from PMC base for the pll clock.
15- clocks : shall be the input parent clock phandle for the clock. This should
16 be the reference clock.
17- #clock-cells : from common clock binding; shall be set to 0.
18
19Required properties for device clocks:
20- clocks : shall be the input parent clock phandle for the clock. This should
21 be a pll output.
22- #clock-cells : from common clock binding; shall be set to 0.
23
24
25Device Clocks
26
27Device clocks are required to have one or both of the following sets of
28properties:
29
30
31Gated device clocks:
32
33Required properties:
34- enable-reg : shall be the register offset from PMC base for the enable
35 register.
36- enable-bit : shall be the bit within enable-reg to enable/disable the clock.
37
38
39Divisor device clocks:
40
41Required property:
42- divisor-reg : shall be the register offset from PMC base for the divisor
43 register.
44Optional property:
45- divisor-mask : shall be the mask for the divisor register. Defaults to 0x1f
46 if not specified.
47
48
49For example:
50
51ref25: ref25M {
52 #clock-cells = <0>;
53 compatible = "fixed-clock";
54 clock-frequency = <25000000>;
55};
56
57plla: plla {
58 #clock-cells = <0>;
59 compatible = "wm,wm8650-pll-clock";
60 clocks = <&ref25>;
61 reg = <0x200>;
62};
63
64sdhc: sdhc {
65 #clock-cells = <0>;
66 compatible = "via,vt8500-device-clock";
67 clocks = <&pllb>;
68 divisor-reg = <0x328>;
69 divisor-mask = <0x3f>;
70 enable-reg = <0x254>;
71 enable-bit = <18>;
72};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-vt8500.txt b/Documentation/devicetree/bindings/gpio/gpio-vt8500.txt
new file mode 100644
index 000000000000..f4dc5233167e
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-vt8500.txt
@@ -0,0 +1,24 @@
1VIA/Wondermedia VT8500 GPIO Controller
2-----------------------------------------------------
3
4Required properties:
5- compatible : "via,vt8500-gpio", "wm,wm8505-gpio"
6 or "wm,wm8650-gpio" depending on your SoC
7- reg : Should contain 1 register range (address and length)
8- #gpio-cells : should be <3>.
9 1) bank
10 2) pin number
11 3) flags - should be 0
12
13Example:
14
15 gpio: gpio-controller@d8110000 {
16 compatible = "via,vt8500-gpio";
17 gpio-controller;
18 reg = <0xd8110000 0x10000>;
19 #gpio-cells = <3>;
20 };
21
22 vibrate {
23 gpios = <&gpio 0 1 0>; /* Bank 0, Pin 1, No flags */
24 };
diff --git a/Documentation/devicetree/bindings/rtc/via,vt8500-rtc.txt b/Documentation/devicetree/bindings/rtc/via,vt8500-rtc.txt
new file mode 100644
index 000000000000..3c0484c49582
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/via,vt8500-rtc.txt
@@ -0,0 +1,15 @@
1VIA/Wondermedia VT8500 Realtime Clock Controller
2-----------------------------------------------------
3
4Required properties:
5- compatible : "via,vt8500-rtc"
6- reg : Should contain 1 register ranges(address and length)
7- interrupts : alarm interrupt
8
9Example:
10
11 rtc@d8100000 {
12 compatible = "via,vt8500-rtc";
13 reg = <0xd8100000 0x10000>;
14 interrupts = <48>;
15 };
diff --git a/Documentation/devicetree/bindings/tty/serial/via,vt8500-uart.txt b/Documentation/devicetree/bindings/tty/serial/via,vt8500-uart.txt
new file mode 100644
index 000000000000..5feef1ef167d
--- /dev/null
+++ b/Documentation/devicetree/bindings/tty/serial/via,vt8500-uart.txt
@@ -0,0 +1,17 @@
1VIA/Wondermedia VT8500 UART Controller
2-----------------------------------------------------
3
4Required properties:
5- compatible : "via,vt8500-uart"
6- reg : Should contain 1 register ranges(address and length)
7- interrupts : UART interrupt
8- clocks : phandle to the uart source clock (usually a 24Mhz fixed clock)
9
10Example:
11
12 uart@d8210000 {
13 compatible = "via,vt8500-uart";
14 reg = <0xd8210000 0x1040>;
15 interrupts = <47>;
16 clocks = <&ref24>;
17 };
diff --git a/Documentation/devicetree/bindings/usb/platform-uhci.txt b/Documentation/devicetree/bindings/usb/platform-uhci.txt
new file mode 100644
index 000000000000..a4fb0719d157
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/platform-uhci.txt
@@ -0,0 +1,15 @@
1Generic Platform UHCI Controller
2-----------------------------------------------------
3
4Required properties:
5- compatible : "platform-uhci"
6- reg : Should contain 1 register ranges(address and length)
7- interrupts : UHCI controller interrupt
8
9Example:
10
11 uhci@d8007b00 {
12 compatible = "platform-uhci";
13 reg = <0xd8007b00 0x200>;
14 interrupts = <43>;
15 };
diff --git a/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
new file mode 100644
index 000000000000..17b3ad1d97e7
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/via,vt8500-ehci.txt
@@ -0,0 +1,15 @@
1VIA/Wondermedia VT8500 EHCI Controller
2-----------------------------------------------------
3
4Required properties:
5- compatible : "via,vt8500-ehci"
6- reg : Should contain 1 register ranges(address and length)
7- interrupts : ehci controller interrupt
8
9Example:
10
11 ehci@d8007900 {
12 compatible = "via,vt8500-ehci";
13 reg = <0xd8007900 0x200>;
14 interrupts = <43>;
15 };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index db4d3af3643c..5c63da29aa05 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -47,5 +47,7 @@ sirf SiRF Technology, Inc.
47st STMicroelectronics 47st STMicroelectronics
48stericsson ST-Ericsson 48stericsson ST-Ericsson
49ti Texas Instruments 49ti Texas Instruments
50via VIA Technologies, Inc.
50wlf Wolfson Microelectronics 51wlf Wolfson Microelectronics
52wm Wondermedia Technologies, Inc.
51xlnx Xilinx 53xlnx Xilinx
diff --git a/Documentation/devicetree/bindings/video/via,vt8500-fb.txt b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
new file mode 100644
index 000000000000..c870b6478ec8
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/via,vt8500-fb.txt
@@ -0,0 +1,62 @@
1VIA VT8500 Framebuffer
2-----------------------------------------------------
3
4Required properties:
5- compatible : "via,vt8500-fb"
6- reg : Should contain 1 register ranges(address and length)
7- interrupts : framebuffer controller interrupt
8- display: a phandle pointing to the display node
9
10Required nodes:
11- display: a display node is required to initialize the lcd panel
12 This should be in the board dts.
13- default-mode: a videomode within the display with timing parameters
14 as specified below.
15
16Example:
17
18 fb@d800e400 {
19 compatible = "via,vt8500-fb";
20 reg = <0xd800e400 0x400>;
21 interrupts = <12>;
22 display = <&display>;
23 default-mode = <&mode0>;
24 };
25
26VIA VT8500 Display
27-----------------------------------------------------
28Required properties (as per of_videomode_helper):
29
30 - hactive, vactive: Display resolution
31 - hfront-porch, hback-porch, hsync-len: Horizontal Display timing parameters
32 in pixels
33 vfront-porch, vback-porch, vsync-len: Vertical display timing parameters in
34 lines
35 - clock: displayclock in Hz
36 - bpp: lcd panel bit-depth.
37 <16> for RGB565, <32> for RGB888
38
39Optional properties (as per of_videomode_helper):
40 - width-mm, height-mm: Display dimensions in mm
41 - hsync-active-high (bool): Hsync pulse is active high
42 - vsync-active-high (bool): Vsync pulse is active high
43 - interlaced (bool): This is an interlaced mode
44 - doublescan (bool): This is a doublescan mode
45
46Example:
47 display: display@0 {
48 modes {
49 mode0: mode@0 {
50 hactive = <800>;
51 vactive = <480>;
52 hback-porch = <88>;
53 hfront-porch = <40>;
54 hsync-len = <0>;
55 vback-porch = <32>;
56 vfront-porch = <11>;
57 vsync-len = <1>;
58 clock = <0>; /* unused but required */
59 bpp = <16>; /* non-standard but required */
60 };
61 };
62 };
diff --git a/Documentation/devicetree/bindings/video/wm,prizm-ge-rops.txt b/Documentation/devicetree/bindings/video/wm,prizm-ge-rops.txt
new file mode 100644
index 000000000000..a850fa011f02
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/wm,prizm-ge-rops.txt
@@ -0,0 +1,13 @@
1VIA/Wondermedia Graphics Engine Controller
2-----------------------------------------------------
3
4Required properties:
5- compatible : "wm,prizm-ge-rops"
6- reg : Should contain 1 register ranges(address and length)
7
8Example:
9
10 ge_rops@d8050400 {
11 compatible = "wm,prizm-ge-rops";
12 reg = <0xd8050400 0x100>;
13 };
diff --git a/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
new file mode 100644
index 000000000000..3d325e1d11ee
--- /dev/null
+++ b/Documentation/devicetree/bindings/video/wm,wm8505-fb.txt
@@ -0,0 +1,23 @@
1Wondermedia WM8505 Framebuffer
2-----------------------------------------------------
3
4Required properties:
5- compatible : "wm,wm8505-fb"
6- reg : Should contain 1 register ranges(address and length)
7- via,display: a phandle pointing to the display node
8
9Required nodes:
10- display: a display node is required to initialize the lcd panel
11 This should be in the board dts. See definition in
12 Documentation/devicetree/bindings/video/via,vt8500-fb.txt
13- default-mode: a videomode node as specified in
14 Documentation/devicetree/bindings/video/via,vt8500-fb.txt
15
16Example:
17
18 fb@d8050800 {
19 compatible = "wm,wm8505-fb";
20 reg = <0xd8050800 0x200>;
21 display = <&display>;
22 default-mode = <&mode0>;
23 };
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index de325f4615bd..1fd9bcd25b4d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1004,6 +1004,10 @@ config ARCH_VT8500
1004 select ARCH_HAS_CPUFREQ 1004 select ARCH_HAS_CPUFREQ
1005 select GENERIC_CLOCKEVENTS 1005 select GENERIC_CLOCKEVENTS
1006 select ARCH_REQUIRE_GPIOLIB 1006 select ARCH_REQUIRE_GPIOLIB
1007 select USE_OF
1008 select COMMON_CLK
1009 select HAVE_CLK
1010 select CLKDEV_LOOKUP
1007 help 1011 help
1008 Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip. 1012 Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
1009 1013
@@ -1128,8 +1132,6 @@ source "arch/arm/mach-versatile/Kconfig"
1128source "arch/arm/mach-vexpress/Kconfig" 1132source "arch/arm/mach-vexpress/Kconfig"
1129source "arch/arm/plat-versatile/Kconfig" 1133source "arch/arm/plat-versatile/Kconfig"
1130 1134
1131source "arch/arm/mach-vt8500/Kconfig"
1132
1133source "arch/arm/mach-w90x900/Kconfig" 1135source "arch/arm/mach-w90x900/Kconfig"
1134 1136
1135# Definitions to make life easier 1137# Definitions to make life easier
@@ -1622,6 +1624,7 @@ config ARCH_NR_GPIO
1622 default 355 if ARCH_U8500 1624 default 355 if ARCH_U8500
1623 default 264 if MACH_H4700 1625 default 264 if MACH_H4700
1624 default 512 if SOC_OMAP5 1626 default 512 if SOC_OMAP5
1627 default 288 if ARCH_VT8500
1625 default 0 1628 default 0
1626 help 1629 help
1627 Maximum number of GPIOs in the system. 1630 Maximum number of GPIOs in the system.
diff --git a/arch/arm/boot/dts/vt8500-bv07.dts b/arch/arm/boot/dts/vt8500-bv07.dts
new file mode 100644
index 000000000000..567cf4e8ab84
--- /dev/null
+++ b/arch/arm/boot/dts/vt8500-bv07.dts
@@ -0,0 +1,36 @@
1/*
2 * vt8500-bv07.dts - Device tree file for Benign BV07 Netbook
3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
5 *
6 * Licensed under GPLv2 or later
7 */
8
9/dts-v1/;
10/include/ "vt8500.dtsi"
11
12/ {
13 model = "Benign BV07 Netbook";
14
15 /*
16 * Display node is based on Sascha Hauer's patch on dri-devel.
17 * Added a bpp property to calculate the size of the framebuffer
18 * until the binding is formalized.
19 */
20 display: display@0 {
21 modes {
22 mode0: mode@0 {
23 hactive = <800>;
24 vactive = <480>;
25 hback-porch = <88>;
26 hfront-porch = <40>;
27 hsync-len = <0>;
28 vback-porch = <32>;
29 vfront-porch = <11>;
30 vsync-len = <1>;
31 clock = <0>; /* unused but required */
32 bpp = <16>; /* non-standard but required */
33 };
34 };
35 };
36};
diff --git a/arch/arm/boot/dts/vt8500.dtsi b/arch/arm/boot/dts/vt8500.dtsi
new file mode 100644
index 000000000000..d8645e990b21
--- /dev/null
+++ b/arch/arm/boot/dts/vt8500.dtsi
@@ -0,0 +1,116 @@
1/*
2 * vt8500.dtsi - Device tree file for VIA VT8500 SoC
3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
5 *
6 * Licensed under GPLv2 or later
7 */
8
9/include/ "skeleton.dtsi"
10
11/ {
12 compatible = "via,vt8500";
13
14 soc {
15 #address-cells = <1>;
16 #size-cells = <1>;
17 compatible = "simple-bus";
18 ranges;
19 interrupt-parent = <&intc>;
20
21 intc: interrupt-controller@d8140000 {
22 compatible = "via,vt8500-intc";
23 interrupt-controller;
24 reg = <0xd8140000 0x10000>;
25 #interrupt-cells = <1>;
26 };
27
28 gpio: gpio-controller@d8110000 {
29 compatible = "via,vt8500-gpio";
30 gpio-controller;
31 reg = <0xd8110000 0x10000>;
32 #gpio-cells = <3>;
33 };
34
35 pmc@d8130000 {
36 compatible = "via,vt8500-pmc";
37 reg = <0xd8130000 0x1000>;
38
39 clocks {
40 #address-cells = <1>;
41 #size-cells = <0>;
42
43 ref24: ref24M {
44 #clock-cells = <0>;
45 compatible = "fixed-clock";
46 clock-frequency = <24000000>;
47 };
48 };
49 };
50
51 timer@d8130100 {
52 compatible = "via,vt8500-timer";
53 reg = <0xd8130100 0x28>;
54 interrupts = <36>;
55 };
56
57 ehci@d8007900 {
58 compatible = "via,vt8500-ehci";
59 reg = <0xd8007900 0x200>;
60 interrupts = <43>;
61 };
62
63 uhci@d8007b00 {
64 compatible = "platform-uhci";
65 reg = <0xd8007b00 0x200>;
66 interrupts = <43>;
67 };
68
69 fb@d800e400 {
70 compatible = "via,vt8500-fb";
71 reg = <0xd800e400 0x400>;
72 interrupts = <12>;
73 display = <&display>;
74 default-mode = <&mode0>;
75 };
76
77 ge_rops@d8050400 {
78 compatible = "wm,prizm-ge-rops";
79 reg = <0xd8050400 0x100>;
80 };
81
82 uart@d8200000 {
83 compatible = "via,vt8500-uart";
84 reg = <0xd8200000 0x1040>;
85 interrupts = <32>;
86 clocks = <&ref24>;
87 };
88
89 uart@d82b0000 {
90 compatible = "via,vt8500-uart";
91 reg = <0xd82b0000 0x1040>;
92 interrupts = <33>;
93 clocks = <&ref24>;
94 };
95
96 uart@d8210000 {
97 compatible = "via,vt8500-uart";
98 reg = <0xd8210000 0x1040>;
99 interrupts = <47>;
100 clocks = <&ref24>;
101 };
102
103 uart@d82c0000 {
104 compatible = "via,vt8500-uart";
105 reg = <0xd82c0000 0x1040>;
106 interrupts = <50>;
107 clocks = <&ref24>;
108 };
109
110 rtc@d8100000 {
111 compatible = "via,vt8500-rtc";
112 reg = <0xd8100000 0x10000>;
113 interrupts = <48>;
114 };
115 };
116};
diff --git a/arch/arm/boot/dts/wm8505-ref.dts b/arch/arm/boot/dts/wm8505-ref.dts
new file mode 100644
index 000000000000..fd4e248074c6
--- /dev/null
+++ b/arch/arm/boot/dts/wm8505-ref.dts
@@ -0,0 +1,36 @@
1/*
2 * wm8505-ref.dts - Device tree file for Wondermedia WM8505 reference netbook
3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
5 *
6 * Licensed under GPLv2 or later
7 */
8
9/dts-v1/;
10/include/ "wm8505.dtsi"
11
12/ {
13 model = "Wondermedia WM8505 Netbook";
14
15 /*
16 * Display node is based on Sascha Hauer's patch on dri-devel.
17 * Added a bpp property to calculate the size of the framebuffer
18 * until the binding is formalized.
19 */
20 display: display@0 {
21 modes {
22 mode0: mode@0 {
23 hactive = <800>;
24 vactive = <480>;
25 hback-porch = <88>;
26 hfront-porch = <40>;
27 hsync-len = <0>;
28 vback-porch = <32>;
29 vfront-porch = <11>;
30 vsync-len = <1>;
31 clock = <0>; /* unused but required */
32 bpp = <32>; /* non-standard but required */
33 };
34 };
35 };
36};
diff --git a/arch/arm/boot/dts/wm8505.dtsi b/arch/arm/boot/dts/wm8505.dtsi
new file mode 100644
index 000000000000..b459691655ab
--- /dev/null
+++ b/arch/arm/boot/dts/wm8505.dtsi
@@ -0,0 +1,143 @@
1/*
2 * wm8505.dtsi - Device tree file for Wondermedia WM8505 SoC
3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
5 *
6 * Licensed under GPLv2 or later
7 */
8
9/include/ "skeleton.dtsi"
10
11/ {
12 compatible = "wm,wm8505";
13
14 cpus {
15 cpu@0 {
16 compatible = "arm,arm926ejs";
17 };
18 };
19
20 soc {
21 #address-cells = <1>;
22 #size-cells = <1>;
23 compatible = "simple-bus";
24 ranges;
25 interrupt-parent = <&intc0>;
26
27 intc0: interrupt-controller@d8140000 {
28 compatible = "via,vt8500-intc";
29 interrupt-controller;
30 reg = <0xd8140000 0x10000>;
31 #interrupt-cells = <1>;
32 };
33
34 /* Secondary IC cascaded to intc0 */
35 intc1: interrupt-controller@d8150000 {
36 compatible = "via,vt8500-intc";
37 interrupt-controller;
38 #interrupt-cells = <1>;
39 reg = <0xD8150000 0x10000>;
40 interrupts = <56 57 58 59 60 61 62 63>;
41 };
42
43 gpio: gpio-controller@d8110000 {
44 compatible = "wm,wm8505-gpio";
45 gpio-controller;
46 reg = <0xd8110000 0x10000>;
47 #gpio-cells = <3>;
48 };
49
50 pmc@d8130000 {
51 compatible = "via,vt8500-pmc";
52 reg = <0xd8130000 0x1000>;
53 clocks {
54 #address-cells = <1>;
55 #size-cells = <0>;
56
57 ref24: ref24M {
58 #clock-cells = <0>;
59 compatible = "fixed-clock";
60 clock-frequency = <24000000>;
61 };
62 };
63 };
64
65 timer@d8130100 {
66 compatible = "via,vt8500-timer";
67 reg = <0xd8130100 0x28>;
68 interrupts = <36>;
69 };
70
71 ehci@d8007100 {
72 compatible = "via,vt8500-ehci";
73 reg = <0xd8007100 0x200>;
74 interrupts = <43>;
75 };
76
77 uhci@d8007300 {
78 compatible = "platform-uhci";
79 reg = <0xd8007300 0x200>;
80 interrupts = <43>;
81 };
82
83 fb@d8050800 {
84 compatible = "wm,wm8505-fb";
85 reg = <0xd8050800 0x200>;
86 display = <&display>;
87 default-mode = <&mode0>;
88 };
89
90 ge_rops@d8050400 {
91 compatible = "wm,prizm-ge-rops";
92 reg = <0xd8050400 0x100>;
93 };
94
95 uart@d8200000 {
96 compatible = "via,vt8500-uart";
97 reg = <0xd8200000 0x1040>;
98 interrupts = <32>;
99 clocks = <&ref24>;
100 };
101
102 uart@d82b0000 {
103 compatible = "via,vt8500-uart";
104 reg = <0xd82b0000 0x1040>;
105 interrupts = <33>;
106 clocks = <&ref24>;
107 };
108
109 uart@d8210000 {
110 compatible = "via,vt8500-uart";
111 reg = <0xd8210000 0x1040>;
112 interrupts = <47>;
113 clocks = <&ref24>;
114 };
115
116 uart@d82c0000 {
117 compatible = "via,vt8500-uart";
118 reg = <0xd82c0000 0x1040>;
119 interrupts = <50>;
120 clocks = <&ref24>;
121 };
122
123 uart@d8370000 {
124 compatible = "via,vt8500-uart";
125 reg = <0xd8370000 0x1040>;
126 interrupts = <31>;
127 clocks = <&ref24>;
128 };
129
130 uart@d8380000 {
131 compatible = "via,vt8500-uart";
132 reg = <0xd8380000 0x1040>;
133 interrupts = <30>;
134 clocks = <&ref24>;
135 };
136
137 rtc@d8100000 {
138 compatible = "via,vt8500-rtc";
139 reg = <0xd8100000 0x10000>;
140 interrupts = <48>;
141 };
142 };
143};
diff --git a/arch/arm/boot/dts/wm8650-mid.dts b/arch/arm/boot/dts/wm8650-mid.dts
new file mode 100644
index 000000000000..cefd938f842f
--- /dev/null
+++ b/arch/arm/boot/dts/wm8650-mid.dts
@@ -0,0 +1,36 @@
1/*
2 * wm8650-mid.dts - Device tree file for Wondermedia WM8650-MID Tablet
3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
5 *
6 * Licensed under GPLv2 or later
7 */
8
9/dts-v1/;
10/include/ "wm8650.dtsi"
11
12/ {
13 model = "Wondermedia WM8650-MID Tablet";
14
15 /*
16 * Display node is based on Sascha Hauer's patch on dri-devel.
17 * Added a bpp property to calculate the size of the framebuffer
18 * until the binding is formalized.
19 */
20 display: display@0 {
21 modes {
22 mode0: mode@0 {
23 hactive = <800>;
24 vactive = <480>;
25 hback-porch = <88>;
26 hfront-porch = <40>;
27 hsync-len = <0>;
28 vback-porch = <32>;
29 vfront-porch = <11>;
30 vsync-len = <1>;
31 clock = <0>; /* unused but required */
32 bpp = <16>; /* non-standard but required */
33 };
34 };
35 };
36};
diff --git a/arch/arm/boot/dts/wm8650.dtsi b/arch/arm/boot/dts/wm8650.dtsi
new file mode 100644
index 000000000000..83b9467559bb
--- /dev/null
+++ b/arch/arm/boot/dts/wm8650.dtsi
@@ -0,0 +1,147 @@
1/*
2 * wm8650.dtsi - Device tree file for Wondermedia WM8650 SoC
3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
5 *
6 * Licensed under GPLv2 or later
7 */
8
9/include/ "skeleton.dtsi"
10
11/ {
12 compatible = "wm,wm8650";
13
14 soc {
15 #address-cells = <1>;
16 #size-cells = <1>;
17 compatible = "simple-bus";
18 ranges;
19 interrupt-parent = <&intc0>;
20
21 intc0: interrupt-controller@d8140000 {
22 compatible = "via,vt8500-intc";
23 interrupt-controller;
24 reg = <0xd8140000 0x10000>;
25 #interrupt-cells = <1>;
26 };
27
28 /* Secondary IC cascaded to intc0 */
29 intc1: interrupt-controller@d8150000 {
30 compatible = "via,vt8500-intc";
31 interrupt-controller;
32 #interrupt-cells = <1>;
33 reg = <0xD8150000 0x10000>;
34 interrupts = <56 57 58 59 60 61 62 63>;
35 };
36
37 gpio: gpio-controller@d8110000 {
38 compatible = "wm,wm8650-gpio";
39 gpio-controller;
40 reg = <0xd8110000 0x10000>;
41 #gpio-cells = <3>;
42 };
43
44 pmc@d8130000 {
45 compatible = "via,vt8500-pmc";
46 reg = <0xd8130000 0x1000>;
47
48 clocks {
49 #address-cells = <1>;
50 #size-cells = <0>;
51
52 ref25: ref25M {
53 #clock-cells = <0>;
54 compatible = "fixed-clock";
55 clock-frequency = <25000000>;
56 };
57
58 ref24: ref24M {
59 #clock-cells = <0>;
60 compatible = "fixed-clock";
61 clock-frequency = <24000000>;
62 };
63
64 plla: plla {
65 #clock-cells = <0>;
66 compatible = "wm,wm8650-pll-clock";
67 clocks = <&ref25>;
68 reg = <0x200>;
69 };
70
71 pllb: pllb {
72 #clock-cells = <0>;
73 compatible = "wm,wm8650-pll-clock";
74 clocks = <&ref25>;
75 reg = <0x204>;
76 };
77
78 arm: arm {
79 #clock-cells = <0>;
80 compatible = "via,vt8500-device-clock";
81 clocks = <&plla>;
82 divisor-reg = <0x300>;
83 };
84
85 sdhc: sdhc {
86 #clock-cells = <0>;
87 compatible = "via,vt8500-device-clock";
88 clocks = <&pllb>;
89 divisor-reg = <0x328>;
90 divisor-mask = <0x3f>;
91 enable-reg = <0x254>;
92 enable-bit = <18>;
93 };
94 };
95 };
96
97 timer@d8130100 {
98 compatible = "via,vt8500-timer";
99 reg = <0xd8130100 0x28>;
100 interrupts = <36>;
101 };
102
103 ehci@d8007900 {
104 compatible = "via,vt8500-ehci";
105 reg = <0xd8007900 0x200>;
106 interrupts = <43>;
107 };
108
109 uhci@d8007b00 {
110 compatible = "platform-uhci";
111 reg = <0xd8007b00 0x200>;
112 interrupts = <43>;
113 };
114
115 fb@d8050800 {
116 compatible = "wm,wm8505-fb";
117 reg = <0xd8050800 0x200>;
118 display = <&display>;
119 default-mode = <&mode0>;
120 };
121
122 ge_rops@d8050400 {
123 compatible = "wm,prizm-ge-rops";
124 reg = <0xd8050400 0x100>;
125 };
126
127 uart@d8200000 {
128 compatible = "via,vt8500-uart";
129 reg = <0xd8200000 0x1040>;
130 interrupts = <32>;
131 clocks = <&ref24>;
132 };
133
134 uart@d82b0000 {
135 compatible = "via,vt8500-uart";
136 reg = <0xd82b0000 0x1040>;
137 interrupts = <33>;
138 clocks = <&ref24>;
139 };
140
141 rtc@d8100000 {
142 compatible = "via,vt8500-rtc";
143 reg = <0xd8100000 0x10000>;
144 interrupts = <48>;
145 };
146 };
147};
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
deleted file mode 100644
index 2c20a341c11a..000000000000
--- a/arch/arm/mach-vt8500/Kconfig
+++ /dev/null
@@ -1,73 +0,0 @@
1if ARCH_VT8500
2
3config VTWM_VERSION_VT8500
4 bool
5
6config VTWM_VERSION_WM8505
7 bool
8
9config MACH_BV07
10 bool "Benign BV07-8500 Mini Netbook"
11 depends on ARCH_VT8500
12 select VTWM_VERSION_VT8500
13 help
14 Add support for the inexpensive 7-inch netbooks sold by many
15 Chinese distributors under various names. Note that there are
16 many hardware implementations in identical exterior, make sure
17 that yours is indeed based on a VIA VT8500 chip.
18
19config MACH_WM8505_7IN_NETBOOK
20 bool "WM8505 7-inch generic netbook"
21 depends on ARCH_VT8500
22 select VTWM_VERSION_WM8505
23 help
24 Add support for the inexpensive 7-inch netbooks sold by many
25 Chinese distributors under various names. Note that there are
26 many hardware implementations in identical exterior, make sure
27 that yours is indeed based on a WonderMedia WM8505 chip.
28
29comment "LCD panel size"
30
31config WMT_PANEL_800X480
32 bool "7-inch with 800x480 resolution"
33 depends on (FB_VT8500 || FB_WM8505)
34 default y
35 help
36 These are found in most of the netbooks in generic cases, as
37 well as in Eken M001 tablets and possibly elsewhere.
38
39 To select this panel at runtime, say y here and append
40 'panel=800x480' to your kernel command line. Otherwise, the
41 largest one available will be used.
42
43config WMT_PANEL_800X600
44 bool "8-inch with 800x600 resolution"
45 depends on (FB_VT8500 || FB_WM8505)
46 help
47 These are found in Eken M003 tablets and possibly elsewhere.
48
49 To select this panel at runtime, say y here and append
50 'panel=800x600' to your kernel command line. Otherwise, the
51 largest one available will be used.
52
53config WMT_PANEL_1024X576
54 bool "10-inch with 1024x576 resolution"
55 depends on (FB_VT8500 || FB_WM8505)
56 help
57 These are found in CherryPal netbooks and possibly elsewhere.
58
59 To select this panel at runtime, say y here and append
60 'panel=1024x576' to your kernel command line. Otherwise, the
61 largest one available will be used.
62
63config WMT_PANEL_1024X600
64 bool "10-inch with 1024x600 resolution"
65 depends on (FB_VT8500 || FB_WM8505)
66 help
67 These are found in Eken M006 tablets and possibly elsewhere.
68
69 To select this panel at runtime, say y here and append
70 'panel=1024x600' to your kernel command line. Otherwise, the
71 largest one available will be used.
72
73endif
diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile
index 7ce51767c99c..e035251cda48 100644
--- a/arch/arm/mach-vt8500/Makefile
+++ b/arch/arm/mach-vt8500/Makefile
@@ -1,7 +1 @@
1obj-y += devices.o gpio.o irq.o timer.o restart.o obj-$(CONFIG_ARCH_VT8500) += irq.o timer.o vt8500.o
2
3obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o
4obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o
5
6obj-$(CONFIG_MACH_BV07) += bv07.o
7obj-$(CONFIG_MACH_WM8505_7IN_NETBOOK) += wm8505_7in.o
diff --git a/arch/arm/mach-vt8500/bv07.c b/arch/arm/mach-vt8500/bv07.c
deleted file mode 100644
index f9fbeb2d10e9..000000000000
--- a/arch/arm/mach-vt8500/bv07.c
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 * arch/arm/mach-vt8500/bv07.c
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/io.h>
22#include <linux/pm.h>
23
24#include <asm/mach-types.h>
25#include <asm/mach/arch.h>
26#include <mach/restart.h>
27
28#include "devices.h"
29
30static void __iomem *pmc_hiber;
31
32static struct platform_device *devices[] __initdata = {
33 &vt8500_device_uart0,
34 &vt8500_device_lcdc,
35 &vt8500_device_ehci,
36 &vt8500_device_ge_rops,
37 &vt8500_device_pwm,
38 &vt8500_device_pwmbl,
39 &vt8500_device_rtc,
40};
41
42static void vt8500_power_off(void)
43{
44 local_irq_disable();
45 writew(5, pmc_hiber);
46 asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
47}
48
49void __init bv07_init(void)
50{
51#ifdef CONFIG_FB_VT8500
52 void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4);
53 if (gpio_mux_reg) {
54 writel(readl(gpio_mux_reg) | 1, gpio_mux_reg);
55 iounmap(gpio_mux_reg);
56 } else {
57 printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n");
58 }
59#endif
60 pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2);
61 if (pmc_hiber)
62 pm_power_off = &vt8500_power_off;
63 else
64 printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
65
66 wmt_setup_restart();
67 vt8500_set_resources();
68 platform_add_devices(devices, ARRAY_SIZE(devices));
69 vt8500_gpio_init();
70}
71
72MACHINE_START(BV07, "Benign BV07 Mini Netbook")
73 .atag_offset = 0x100,
74 .restart = wmt_restart,
75 .reserve = vt8500_reserve_mem,
76 .map_io = vt8500_map_io,
77 .init_irq = vt8500_init_irq,
78 .timer = &vt8500_timer,
79 .init_machine = bv07_init,
80MACHINE_END
diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h
new file mode 100644
index 000000000000..2b2419646e95
--- /dev/null
+++ b/arch/arm/mach-vt8500/common.h
@@ -0,0 +1,28 @@
1/* linux/arch/arm/mach-vt8500/dt_common.h
2 *
3 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#ifndef __ARCH_ARM_MACH_VT8500_DT_COMMON_H
17#define __ARCH_ARM_MACH_VT8500_DT_COMMON_H
18
19#include <linux/of.h>
20
21void __init vt8500_timer_init(void);
22int __init vt8500_irq_init(struct device_node *node,
23 struct device_node *parent);
24
25/* defined in drivers/clk/clk-vt8500.c */
26void __init vtwm_clk_init(void __iomem *pmc_base);
27
28#endif
diff --git a/arch/arm/mach-vt8500/devices-vt8500.c b/arch/arm/mach-vt8500/devices-vt8500.c
deleted file mode 100644
index 19519aeecf37..000000000000
--- a/arch/arm/mach-vt8500/devices-vt8500.c
+++ /dev/null
@@ -1,91 +0,0 @@
1/* linux/arch/arm/mach-vt8500/devices-vt8500.c
2 *
3 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/platform_device.h>
17
18#include <mach/vt8500_regs.h>
19#include <mach/vt8500_irqs.h>
20#include <mach/i8042.h>
21#include "devices.h"
22
23void __init vt8500_set_resources(void)
24{
25 struct resource tmp[3];
26
27 tmp[0] = wmt_mmio_res(VT8500_LCDC_BASE, SZ_1K);
28 tmp[1] = wmt_irq_res(IRQ_LCDC);
29 wmt_res_add(&vt8500_device_lcdc, tmp, 2);
30
31 tmp[0] = wmt_mmio_res(VT8500_UART0_BASE, 0x1040);
32 tmp[1] = wmt_irq_res(IRQ_UART0);
33 wmt_res_add(&vt8500_device_uart0, tmp, 2);
34
35 tmp[0] = wmt_mmio_res(VT8500_UART1_BASE, 0x1040);
36 tmp[1] = wmt_irq_res(IRQ_UART1);
37 wmt_res_add(&vt8500_device_uart1, tmp, 2);
38
39 tmp[0] = wmt_mmio_res(VT8500_UART2_BASE, 0x1040);
40 tmp[1] = wmt_irq_res(IRQ_UART2);
41 wmt_res_add(&vt8500_device_uart2, tmp, 2);
42
43 tmp[0] = wmt_mmio_res(VT8500_UART3_BASE, 0x1040);
44 tmp[1] = wmt_irq_res(IRQ_UART3);
45 wmt_res_add(&vt8500_device_uart3, tmp, 2);
46
47 tmp[0] = wmt_mmio_res(VT8500_EHCI_BASE, SZ_512);
48 tmp[1] = wmt_irq_res(IRQ_EHCI);
49 wmt_res_add(&vt8500_device_ehci, tmp, 2);
50
51 tmp[0] = wmt_mmio_res(VT8500_GEGEA_BASE, SZ_256);
52 wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
53
54 tmp[0] = wmt_mmio_res(VT8500_PWM_BASE, 0x44);
55 wmt_res_add(&vt8500_device_pwm, tmp, 1);
56
57 tmp[0] = wmt_mmio_res(VT8500_RTC_BASE, 0x2c);
58 tmp[1] = wmt_irq_res(IRQ_RTC);
59 tmp[2] = wmt_irq_res(IRQ_RTCSM);
60 wmt_res_add(&vt8500_device_rtc, tmp, 3);
61}
62
63static void __init vt8500_set_externs(void)
64{
65 /* Non-resource-aware stuff */
66 wmt_ic_base = VT8500_IC_BASE;
67 wmt_gpio_base = VT8500_GPIO_BASE;
68 wmt_pmc_base = VT8500_PMC_BASE;
69 wmt_i8042_base = VT8500_PS2_BASE;
70
71 wmt_nr_irqs = VT8500_NR_IRQS;
72 wmt_timer_irq = IRQ_PMCOS0;
73 wmt_gpio_ext_irq[0] = IRQ_EXT0;
74 wmt_gpio_ext_irq[1] = IRQ_EXT1;
75 wmt_gpio_ext_irq[2] = IRQ_EXT2;
76 wmt_gpio_ext_irq[3] = IRQ_EXT3;
77 wmt_gpio_ext_irq[4] = IRQ_EXT4;
78 wmt_gpio_ext_irq[5] = IRQ_EXT5;
79 wmt_gpio_ext_irq[6] = IRQ_EXT6;
80 wmt_gpio_ext_irq[7] = IRQ_EXT7;
81 wmt_i8042_kbd_irq = IRQ_PS2KBD;
82 wmt_i8042_aux_irq = IRQ_PS2MOUSE;
83}
84
85void __init vt8500_map_io(void)
86{
87 iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
88
89 /* Should be done before interrupts and timers are initialized */
90 vt8500_set_externs();
91}
diff --git a/arch/arm/mach-vt8500/devices-wm8505.c b/arch/arm/mach-vt8500/devices-wm8505.c
deleted file mode 100644
index db4594e029f4..000000000000
--- a/arch/arm/mach-vt8500/devices-wm8505.c
+++ /dev/null
@@ -1,99 +0,0 @@
1/* linux/arch/arm/mach-vt8500/devices-wm8505.c
2 *
3 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/platform_device.h>
17
18#include <mach/wm8505_regs.h>
19#include <mach/wm8505_irqs.h>
20#include <mach/i8042.h>
21#include "devices.h"
22
23void __init wm8505_set_resources(void)
24{
25 struct resource tmp[3];
26
27 tmp[0] = wmt_mmio_res(WM8505_GOVR_BASE, SZ_512);
28 wmt_res_add(&vt8500_device_wm8505_fb, tmp, 1);
29
30 tmp[0] = wmt_mmio_res(WM8505_UART0_BASE, 0x1040);
31 tmp[1] = wmt_irq_res(IRQ_UART0);
32 wmt_res_add(&vt8500_device_uart0, tmp, 2);
33
34 tmp[0] = wmt_mmio_res(WM8505_UART1_BASE, 0x1040);
35 tmp[1] = wmt_irq_res(IRQ_UART1);
36 wmt_res_add(&vt8500_device_uart1, tmp, 2);
37
38 tmp[0] = wmt_mmio_res(WM8505_UART2_BASE, 0x1040);
39 tmp[1] = wmt_irq_res(IRQ_UART2);
40 wmt_res_add(&vt8500_device_uart2, tmp, 2);
41
42 tmp[0] = wmt_mmio_res(WM8505_UART3_BASE, 0x1040);
43 tmp[1] = wmt_irq_res(IRQ_UART3);
44 wmt_res_add(&vt8500_device_uart3, tmp, 2);
45
46 tmp[0] = wmt_mmio_res(WM8505_UART4_BASE, 0x1040);
47 tmp[1] = wmt_irq_res(IRQ_UART4);
48 wmt_res_add(&vt8500_device_uart4, tmp, 2);
49
50 tmp[0] = wmt_mmio_res(WM8505_UART5_BASE, 0x1040);
51 tmp[1] = wmt_irq_res(IRQ_UART5);
52 wmt_res_add(&vt8500_device_uart5, tmp, 2);
53
54 tmp[0] = wmt_mmio_res(WM8505_EHCI_BASE, SZ_512);
55 tmp[1] = wmt_irq_res(IRQ_EHCI);
56 wmt_res_add(&vt8500_device_ehci, tmp, 2);
57
58 tmp[0] = wmt_mmio_res(WM8505_GEGEA_BASE, SZ_256);
59 wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
60
61 tmp[0] = wmt_mmio_res(WM8505_PWM_BASE, 0x44);
62 wmt_res_add(&vt8500_device_pwm, tmp, 1);
63
64 tmp[0] = wmt_mmio_res(WM8505_RTC_BASE, 0x2c);
65 tmp[1] = wmt_irq_res(IRQ_RTC);
66 tmp[2] = wmt_irq_res(IRQ_RTCSM);
67 wmt_res_add(&vt8500_device_rtc, tmp, 3);
68}
69
70static void __init wm8505_set_externs(void)
71{
72 /* Non-resource-aware stuff */
73 wmt_ic_base = WM8505_IC_BASE;
74 wmt_sic_base = WM8505_SIC_BASE;
75 wmt_gpio_base = WM8505_GPIO_BASE;
76 wmt_pmc_base = WM8505_PMC_BASE;
77 wmt_i8042_base = WM8505_PS2_BASE;
78
79 wmt_nr_irqs = WM8505_NR_IRQS;
80 wmt_timer_irq = IRQ_PMCOS0;
81 wmt_gpio_ext_irq[0] = IRQ_EXT0;
82 wmt_gpio_ext_irq[1] = IRQ_EXT1;
83 wmt_gpio_ext_irq[2] = IRQ_EXT2;
84 wmt_gpio_ext_irq[3] = IRQ_EXT3;
85 wmt_gpio_ext_irq[4] = IRQ_EXT4;
86 wmt_gpio_ext_irq[5] = IRQ_EXT5;
87 wmt_gpio_ext_irq[6] = IRQ_EXT6;
88 wmt_gpio_ext_irq[7] = IRQ_EXT7;
89 wmt_i8042_kbd_irq = IRQ_PS2KBD;
90 wmt_i8042_aux_irq = IRQ_PS2MOUSE;
91}
92
93void __init wm8505_map_io(void)
94{
95 iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
96
97 /* Should be done before interrupts and timers are initialized */
98 wm8505_set_externs();
99}
diff --git a/arch/arm/mach-vt8500/devices.c b/arch/arm/mach-vt8500/devices.c
deleted file mode 100644
index 1fcdc36b358d..000000000000
--- a/arch/arm/mach-vt8500/devices.c
+++ /dev/null
@@ -1,270 +0,0 @@
1/* linux/arch/arm/mach-vt8500/devices.c
2 *
3 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/io.h>
18#include <linux/device.h>
19#include <linux/dma-mapping.h>
20#include <linux/platform_device.h>
21#include <linux/pwm_backlight.h>
22#include <linux/memblock.h>
23
24#include <asm/mach/arch.h>
25
26#include <mach/vt8500fb.h>
27#include <mach/i8042.h>
28#include "devices.h"
29
30/* These can't use resources currently */
31unsigned long wmt_ic_base __initdata;
32unsigned long wmt_sic_base __initdata;
33unsigned long wmt_gpio_base __initdata;
34unsigned long wmt_pmc_base __initdata;
35unsigned long wmt_i8042_base __initdata;
36
37int wmt_nr_irqs __initdata;
38int wmt_timer_irq __initdata;
39int wmt_gpio_ext_irq[8] __initdata;
40
41/* Should remain accessible after init.
42 * i8042 driver desperately calls for attention...
43 */
44int wmt_i8042_kbd_irq;
45int wmt_i8042_aux_irq;
46
47static u64 fb_dma_mask = DMA_BIT_MASK(32);
48
49struct platform_device vt8500_device_lcdc = {
50 .name = "vt8500-lcd",
51 .id = 0,
52 .dev = {
53 .dma_mask = &fb_dma_mask,
54 .coherent_dma_mask = DMA_BIT_MASK(32),
55 },
56};
57
58struct platform_device vt8500_device_wm8505_fb = {
59 .name = "wm8505-fb",
60 .id = 0,
61};
62
63/* Smallest to largest */
64static struct vt8500fb_platform_data panels[] = {
65#ifdef CONFIG_WMT_PANEL_800X480
66{
67 .xres_virtual = 800,
68 .yres_virtual = 480 * 2,
69 .mode = {
70 .name = "800x480",
71 .xres = 800,
72 .yres = 480,
73 .left_margin = 88,
74 .right_margin = 40,
75 .upper_margin = 32,
76 .lower_margin = 11,
77 .hsync_len = 0,
78 .vsync_len = 1,
79 .vmode = FB_VMODE_NONINTERLACED,
80 },
81},
82#endif
83#ifdef CONFIG_WMT_PANEL_800X600
84{
85 .xres_virtual = 800,
86 .yres_virtual = 600 * 2,
87 .mode = {
88 .name = "800x600",
89 .xres = 800,
90 .yres = 600,
91 .left_margin = 88,
92 .right_margin = 40,
93 .upper_margin = 32,
94 .lower_margin = 11,
95 .hsync_len = 0,
96 .vsync_len = 1,
97 .vmode = FB_VMODE_NONINTERLACED,
98 },
99},
100#endif
101#ifdef CONFIG_WMT_PANEL_1024X576
102{
103 .xres_virtual = 1024,
104 .yres_virtual = 576 * 2,
105 .mode = {
106 .name = "1024x576",
107 .xres = 1024,
108 .yres = 576,
109 .left_margin = 40,
110 .right_margin = 24,
111 .upper_margin = 32,
112 .lower_margin = 11,
113 .hsync_len = 96,
114 .vsync_len = 2,
115 .vmode = FB_VMODE_NONINTERLACED,
116 },
117},
118#endif
119#ifdef CONFIG_WMT_PANEL_1024X600
120{
121 .xres_virtual = 1024,
122 .yres_virtual = 600 * 2,
123 .mode = {
124 .name = "1024x600",
125 .xres = 1024,
126 .yres = 600,
127 .left_margin = 66,
128 .right_margin = 2,
129 .upper_margin = 19,
130 .lower_margin = 1,
131 .hsync_len = 23,
132 .vsync_len = 8,
133 .vmode = FB_VMODE_NONINTERLACED,
134 },
135},
136#endif
137};
138
139static int current_panel_idx __initdata = ARRAY_SIZE(panels) - 1;
140
141static int __init panel_setup(char *str)
142{
143 int i;
144
145 for (i = 0; i < ARRAY_SIZE(panels); i++) {
146 if (strcmp(panels[i].mode.name, str) == 0) {
147 current_panel_idx = i;
148 break;
149 }
150 }
151 return 0;
152}
153
154early_param("panel", panel_setup);
155
156static inline void preallocate_fb(struct vt8500fb_platform_data *p,
157 unsigned long align) {
158 p->video_mem_len = (p->xres_virtual * p->yres_virtual * 4) >>
159 (p->bpp > 16 ? 0 : (p->bpp > 8 ? 1 :
160 (8 / p->bpp) + 1));
161 p->video_mem_phys = (unsigned long)memblock_alloc(p->video_mem_len,
162 align);
163 p->video_mem_virt = phys_to_virt(p->video_mem_phys);
164}
165
166struct platform_device vt8500_device_uart0 = {
167 .name = "vt8500_serial",
168 .id = 0,
169};
170
171struct platform_device vt8500_device_uart1 = {
172 .name = "vt8500_serial",
173 .id = 1,
174};
175
176struct platform_device vt8500_device_uart2 = {
177 .name = "vt8500_serial",
178 .id = 2,
179};
180
181struct platform_device vt8500_device_uart3 = {
182 .name = "vt8500_serial",
183 .id = 3,
184};
185
186struct platform_device vt8500_device_uart4 = {
187 .name = "vt8500_serial",
188 .id = 4,
189};
190
191struct platform_device vt8500_device_uart5 = {
192 .name = "vt8500_serial",
193 .id = 5,
194};
195
196static u64 ehci_dma_mask = DMA_BIT_MASK(32);
197
198struct platform_device vt8500_device_ehci = {
199 .name = "vt8500-ehci",
200 .id = 0,
201 .dev = {
202 .dma_mask = &ehci_dma_mask,
203 .coherent_dma_mask = DMA_BIT_MASK(32),
204 },
205};
206
207struct platform_device vt8500_device_ge_rops = {
208 .name = "wmt_ge_rops",
209 .id = -1,
210};
211
212struct platform_device vt8500_device_pwm = {
213 .name = "vt8500-pwm",
214 .id = 0,
215};
216
217static struct platform_pwm_backlight_data vt8500_pwmbl_data = {
218 .pwm_id = 0,
219 .max_brightness = 128,
220 .dft_brightness = 70,
221 .pwm_period_ns = 250000, /* revisit when clocks are implemented */
222};
223
224struct platform_device vt8500_device_pwmbl = {
225 .name = "pwm-backlight",
226 .id = 0,
227 .dev = {
228 .platform_data = &vt8500_pwmbl_data,
229 },
230};
231
232struct platform_device vt8500_device_rtc = {
233 .name = "vt8500-rtc",
234 .id = 0,
235};
236
237struct map_desc wmt_io_desc[] __initdata = {
238 /* SoC MMIO registers */
239 [0] = {
240 .virtual = 0xf8000000,
241 .pfn = __phys_to_pfn(0xd8000000),
242 .length = 0x00390000, /* max of all chip variants */
243 .type = MT_DEVICE
244 },
245 /* PCI I/O space, numbers tied to those in <mach/io.h> */
246 [1] = {
247 .virtual = 0xf0000000,
248 .pfn = __phys_to_pfn(0xc0000000),
249 .length = SZ_64K,
250 .type = MT_DEVICE
251 },
252};
253
254void __init vt8500_reserve_mem(void)
255{
256#ifdef CONFIG_FB_VT8500
257 panels[current_panel_idx].bpp = 16; /* Always use RGB565 */
258 preallocate_fb(&panels[current_panel_idx], SZ_4M);
259 vt8500_device_lcdc.dev.platform_data = &panels[current_panel_idx];
260#endif
261}
262
263void __init wm8505_reserve_mem(void)
264{
265#if defined CONFIG_FB_WM8505
266 panels[current_panel_idx].bpp = 32; /* Always use RGB888 */
267 preallocate_fb(&panels[current_panel_idx], 32);
268 vt8500_device_wm8505_fb.dev.platform_data = &panels[current_panel_idx];
269#endif
270}
diff --git a/arch/arm/mach-vt8500/devices.h b/arch/arm/mach-vt8500/devices.h
deleted file mode 100644
index 188d4e17f35c..000000000000
--- a/arch/arm/mach-vt8500/devices.h
+++ /dev/null
@@ -1,88 +0,0 @@
1/* linux/arch/arm/mach-vt8500/devices.h
2 *
3 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#ifndef __ARCH_ARM_MACH_VT8500_DEVICES_H
17#define __ARCH_ARM_MACH_VT8500_DEVICES_H
18
19#include <linux/platform_device.h>
20#include <asm/mach/map.h>
21
22void __init vt8500_init_irq(void);
23void __init wm8505_init_irq(void);
24void __init vt8500_map_io(void);
25void __init wm8505_map_io(void);
26void __init vt8500_reserve_mem(void);
27void __init wm8505_reserve_mem(void);
28void __init vt8500_gpio_init(void);
29void __init vt8500_set_resources(void);
30void __init wm8505_set_resources(void);
31
32extern unsigned long wmt_ic_base __initdata;
33extern unsigned long wmt_sic_base __initdata;
34extern unsigned long wmt_gpio_base __initdata;
35extern unsigned long wmt_pmc_base __initdata;
36
37extern int wmt_nr_irqs __initdata;
38extern int wmt_timer_irq __initdata;
39extern int wmt_gpio_ext_irq[8] __initdata;
40
41extern struct map_desc wmt_io_desc[2] __initdata;
42
43static inline struct resource wmt_mmio_res(u32 start, u32 size)
44{
45 struct resource tmp = {
46 .flags = IORESOURCE_MEM,
47 .start = start,
48 .end = start + size - 1,
49 };
50
51 return tmp;
52}
53
54static inline struct resource wmt_irq_res(int irq)
55{
56 struct resource tmp = {
57 .flags = IORESOURCE_IRQ,
58 .start = irq,
59 .end = irq,
60 };
61
62 return tmp;
63}
64
65static inline void wmt_res_add(struct platform_device *pdev,
66 const struct resource *res, unsigned int num)
67{
68 if (unlikely(platform_device_add_resources(pdev, res, num)))
69 pr_err("Failed to assign resources\n");
70}
71
72extern struct sys_timer vt8500_timer;
73
74extern struct platform_device vt8500_device_uart0;
75extern struct platform_device vt8500_device_uart1;
76extern struct platform_device vt8500_device_uart2;
77extern struct platform_device vt8500_device_uart3;
78extern struct platform_device vt8500_device_uart4;
79extern struct platform_device vt8500_device_uart5;
80
81extern struct platform_device vt8500_device_lcdc;
82extern struct platform_device vt8500_device_wm8505_fb;
83extern struct platform_device vt8500_device_ehci;
84extern struct platform_device vt8500_device_ge_rops;
85extern struct platform_device vt8500_device_pwm;
86extern struct platform_device vt8500_device_pwmbl;
87extern struct platform_device vt8500_device_rtc;
88#endif
diff --git a/arch/arm/mach-vt8500/gpio.c b/arch/arm/mach-vt8500/gpio.c
deleted file mode 100644
index 2bcc0ec783df..000000000000
--- a/arch/arm/mach-vt8500/gpio.c
+++ /dev/null
@@ -1,240 +0,0 @@
1/* linux/arch/arm/mach-vt8500/gpio.c
2 *
3 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/gpio.h>
17#include <linux/init.h>
18#include <linux/irq.h>
19#include <linux/io.h>
20
21#include "devices.h"
22
23#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
24
25#define ENABLE_REGS 0x0
26#define DIRECTION_REGS 0x20
27#define OUTVALUE_REGS 0x40
28#define INVALUE_REGS 0x60
29
30#define EXT_REGOFF 0x1c
31
32static void __iomem *regbase;
33
34struct vt8500_gpio_chip {
35 struct gpio_chip chip;
36 unsigned int shift;
37 unsigned int regoff;
38};
39
40static int gpio_to_irq_map[8];
41
42static int vt8500_muxed_gpio_request(struct gpio_chip *chip,
43 unsigned offset)
44{
45 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
46 unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
47
48 val |= (1 << vt8500_chip->shift << offset);
49 writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
50
51 return 0;
52}
53
54static void vt8500_muxed_gpio_free(struct gpio_chip *chip,
55 unsigned offset)
56{
57 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
58 unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
59
60 val &= ~(1 << vt8500_chip->shift << offset);
61 writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
62}
63
64static int vt8500_muxed_gpio_direction_input(struct gpio_chip *chip,
65 unsigned offset)
66{
67 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
68 unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
69
70 val &= ~(1 << vt8500_chip->shift << offset);
71 writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
72
73 return 0;
74}
75
76static int vt8500_muxed_gpio_direction_output(struct gpio_chip *chip,
77 unsigned offset, int value)
78{
79 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
80 unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
81
82 val |= (1 << vt8500_chip->shift << offset);
83 writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
84
85 if (value) {
86 val = readl(regbase + OUTVALUE_REGS + vt8500_chip->regoff);
87 val |= (1 << vt8500_chip->shift << offset);
88 writel(val, regbase + OUTVALUE_REGS + vt8500_chip->regoff);
89 }
90 return 0;
91}
92
93static int vt8500_muxed_gpio_get_value(struct gpio_chip *chip,
94 unsigned offset)
95{
96 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
97
98 return (readl(regbase + INVALUE_REGS + vt8500_chip->regoff)
99 >> vt8500_chip->shift >> offset) & 1;
100}
101
102static void vt8500_muxed_gpio_set_value(struct gpio_chip *chip,
103 unsigned offset, int value)
104{
105 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
106 unsigned val = readl(regbase + INVALUE_REGS + vt8500_chip->regoff);
107
108 if (value)
109 val |= (1 << vt8500_chip->shift << offset);
110 else
111 val &= ~(1 << vt8500_chip->shift << offset);
112
113 writel(val, regbase + INVALUE_REGS + vt8500_chip->regoff);
114}
115
116#define VT8500_GPIO_BANK(__name, __shift, __off, __base, __num) \
117{ \
118 .chip = { \
119 .label = __name, \
120 .request = vt8500_muxed_gpio_request, \
121 .free = vt8500_muxed_gpio_free, \
122 .direction_input = vt8500_muxed_gpio_direction_input, \
123 .direction_output = vt8500_muxed_gpio_direction_output, \
124 .get = vt8500_muxed_gpio_get_value, \
125 .set = vt8500_muxed_gpio_set_value, \
126 .can_sleep = 0, \
127 .base = __base, \
128 .ngpio = __num, \
129 }, \
130 .shift = __shift, \
131 .regoff = __off, \
132}
133
134static struct vt8500_gpio_chip vt8500_muxed_gpios[] = {
135 VT8500_GPIO_BANK("uart0", 0, 0x0, 8, 4),
136 VT8500_GPIO_BANK("uart1", 4, 0x0, 12, 4),
137 VT8500_GPIO_BANK("spi0", 8, 0x0, 16, 4),
138 VT8500_GPIO_BANK("spi1", 12, 0x0, 20, 4),
139 VT8500_GPIO_BANK("spi2", 16, 0x0, 24, 4),
140 VT8500_GPIO_BANK("pwmout", 24, 0x0, 28, 2),
141
142 VT8500_GPIO_BANK("sdmmc", 0, 0x4, 30, 11),
143 VT8500_GPIO_BANK("ms", 16, 0x4, 41, 7),
144 VT8500_GPIO_BANK("i2c0", 24, 0x4, 48, 2),
145 VT8500_GPIO_BANK("i2c1", 26, 0x4, 50, 2),
146
147 VT8500_GPIO_BANK("mii", 0, 0x8, 52, 20),
148 VT8500_GPIO_BANK("see", 20, 0x8, 72, 4),
149 VT8500_GPIO_BANK("ide", 24, 0x8, 76, 7),
150
151 VT8500_GPIO_BANK("ccir", 0, 0xc, 83, 19),
152
153 VT8500_GPIO_BANK("ts", 8, 0x10, 102, 11),
154
155 VT8500_GPIO_BANK("lcd", 0, 0x14, 113, 23),
156};
157
158static int vt8500_gpio_direction_input(struct gpio_chip *chip,
159 unsigned offset)
160{
161 unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
162
163 val &= ~(1 << offset);
164 writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
165 return 0;
166}
167
168static int vt8500_gpio_direction_output(struct gpio_chip *chip,
169 unsigned offset, int value)
170{
171 unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
172
173 val |= (1 << offset);
174 writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
175
176 if (value) {
177 val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
178 val |= (1 << offset);
179 writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
180 }
181 return 0;
182}
183
184static int vt8500_gpio_get_value(struct gpio_chip *chip,
185 unsigned offset)
186{
187 return (readl(regbase + INVALUE_REGS + EXT_REGOFF) >> offset) & 1;
188}
189
190static void vt8500_gpio_set_value(struct gpio_chip *chip,
191 unsigned offset, int value)
192{
193 unsigned val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
194
195 if (value)
196 val |= (1 << offset);
197 else
198 val &= ~(1 << offset);
199
200 writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
201}
202
203static int vt8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
204{
205 if (offset > 7)
206 return -EINVAL;
207
208 return gpio_to_irq_map[offset];
209}
210
211static struct gpio_chip vt8500_external_gpios = {
212 .label = "extgpio",
213 .direction_input = vt8500_gpio_direction_input,
214 .direction_output = vt8500_gpio_direction_output,
215 .get = vt8500_gpio_get_value,
216 .set = vt8500_gpio_set_value,
217 .to_irq = vt8500_gpio_to_irq,
218 .can_sleep = 0,
219 .base = 0,
220 .ngpio = 8,
221};
222
223void __init vt8500_gpio_init(void)
224{
225 int i;
226
227 for (i = 0; i < 8; i++)
228 gpio_to_irq_map[i] = wmt_gpio_ext_irq[i];
229
230 regbase = ioremap(wmt_gpio_base, SZ_64K);
231 if (!regbase) {
232 printk(KERN_ERR "Failed to map MMIO registers for GPIO\n");
233 return;
234 }
235
236 gpiochip_add(&vt8500_external_gpios);
237
238 for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++)
239 gpiochip_add(&vt8500_muxed_gpios[i].chip);
240}
diff --git a/arch/arm/mach-vt8500/include/mach/restart.h b/arch/arm/mach-vt8500/include/mach/restart.h
index 89f9b787d2a0..738979518acb 100644
--- a/arch/arm/mach-vt8500/include/mach/restart.h
+++ b/arch/arm/mach-vt8500/include/mach/restart.h
@@ -13,5 +13,5 @@
13 * 13 *
14 */ 14 */
15 15
16void wmt_setup_restart(void); 16void vt8500_setup_restart(void);
17void wmt_restart(char mode, const char *cmd); 17void vt8500_restart(char mode, const char *cmd);
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h b/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
deleted file mode 100644
index ecfee9124711..000000000000
--- a/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
+++ /dev/null
@@ -1,88 +0,0 @@
1/*
2 * arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/* VT8500 Interrupt Sources */
22
23#define IRQ_JPEGENC 0 /* JPEG Encoder */
24#define IRQ_JPEGDEC 1 /* JPEG Decoder */
25 /* Reserved */
26#define IRQ_PATA 3 /* PATA Controller */
27 /* Reserved */
28#define IRQ_DMA 5 /* DMA Controller */
29#define IRQ_EXT0 6 /* External Interrupt 0 */
30#define IRQ_EXT1 7 /* External Interrupt 1 */
31#define IRQ_GE 8 /* Graphic Engine */
32#define IRQ_GOV 9 /* Graphic Overlay Engine */
33#define IRQ_ETHER 10 /* Ethernet MAC */
34#define IRQ_MPEGTS 11 /* Transport Stream Interface */
35#define IRQ_LCDC 12 /* LCD Controller */
36#define IRQ_EXT2 13 /* External Interrupt 2 */
37#define IRQ_EXT3 14 /* External Interrupt 3 */
38#define IRQ_EXT4 15 /* External Interrupt 4 */
39#define IRQ_CIPHER 16 /* Cipher */
40#define IRQ_VPP 17 /* Video Post-Processor */
41#define IRQ_I2C1 18 /* I2C 1 */
42#define IRQ_I2C0 19 /* I2C 0 */
43#define IRQ_SDMMC 20 /* SD/MMC Controller */
44#define IRQ_SDMMC_DMA 21 /* SD/MMC Controller DMA */
45#define IRQ_PMC_WU 22 /* Power Management Controller Wakeup */
46 /* Reserved */
47#define IRQ_SPI0 24 /* SPI 0 */
48#define IRQ_SPI1 25 /* SPI 1 */
49#define IRQ_SPI2 26 /* SPI 2 */
50#define IRQ_LCDDF 27 /* LCD Data Formatter */
51#define IRQ_NAND 28 /* NAND Flash Controller */
52#define IRQ_NAND_DMA 29 /* NAND Flash Controller DMA */
53#define IRQ_MS 30 /* MemoryStick Controller */
54#define IRQ_MS_DMA 31 /* MemoryStick Controller DMA */
55#define IRQ_UART0 32 /* UART 0 */
56#define IRQ_UART1 33 /* UART 1 */
57#define IRQ_I2S 34 /* I2S */
58#define IRQ_PCM 35 /* PCM */
59#define IRQ_PMCOS0 36 /* PMC OS Timer 0 */
60#define IRQ_PMCOS1 37 /* PMC OS Timer 1 */
61#define IRQ_PMCOS2 38 /* PMC OS Timer 2 */
62#define IRQ_PMCOS3 39 /* PMC OS Timer 3 */
63#define IRQ_VPU 40 /* Video Processing Unit */
64#define IRQ_VID 41 /* Video Digital Input Interface */
65#define IRQ_AC97 42 /* AC97 Interface */
66#define IRQ_EHCI 43 /* USB */
67#define IRQ_NOR 44 /* NOR Flash Controller */
68#define IRQ_PS2MOUSE 45 /* PS/2 Mouse */
69#define IRQ_PS2KBD 46 /* PS/2 Keyboard */
70#define IRQ_UART2 47 /* UART 2 */
71#define IRQ_RTC 48 /* RTC Interrupt */
72#define IRQ_RTCSM 49 /* RTC Second/Minute Update Interrupt */
73#define IRQ_UART3 50 /* UART 3 */
74#define IRQ_ADC 51 /* ADC */
75#define IRQ_EXT5 52 /* External Interrupt 5 */
76#define IRQ_EXT6 53 /* External Interrupt 6 */
77#define IRQ_EXT7 54 /* External Interrupt 7 */
78#define IRQ_CIR 55 /* CIR */
79#define IRQ_DMA0 56 /* DMA Channel 0 */
80#define IRQ_DMA1 57 /* DMA Channel 1 */
81#define IRQ_DMA2 58 /* DMA Channel 2 */
82#define IRQ_DMA3 59 /* DMA Channel 3 */
83#define IRQ_DMA4 60 /* DMA Channel 4 */
84#define IRQ_DMA5 61 /* DMA Channel 5 */
85#define IRQ_DMA6 62 /* DMA Channel 6 */
86#define IRQ_DMA7 63 /* DMA Channel 7 */
87
88#define VT8500_NR_IRQS 64
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500_regs.h b/arch/arm/mach-vt8500/include/mach/vt8500_regs.h
deleted file mode 100644
index 29c63ecb2383..000000000000
--- a/arch/arm/mach-vt8500/include/mach/vt8500_regs.h
+++ /dev/null
@@ -1,79 +0,0 @@
1/*
2 * arch/arm/mach-vt8500/include/mach/vt8500_regs.h
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#ifndef __ASM_ARM_ARCH_VT8500_REGS_H
21#define __ASM_ARM_ARCH_VT8500_REGS_H
22
23/* VT8500 Registers Map */
24
25#define VT8500_REGS_START_PHYS 0xd8000000 /* Start of MMIO registers */
26#define VT8500_REGS_START_VIRT 0xf8000000 /* Virtual mapping start */
27
28#define VT8500_DDR_BASE 0xd8000000 /* 1k DDR/DDR2 Memory
29 Controller */
30#define VT8500_DMA_BASE 0xd8001000 /* 1k DMA Controller */
31#define VT8500_SFLASH_BASE 0xd8002000 /* 1k Serial Flash Memory
32 Controller */
33#define VT8500_ETHER_BASE 0xd8004000 /* 1k Ethernet MAC 0 */
34#define VT8500_CIPHER_BASE 0xd8006000 /* 4k Cipher */
35#define VT8500_USB_BASE 0xd8007800 /* 2k USB OTG */
36# define VT8500_EHCI_BASE 0xd8007900 /* EHCI */
37# define VT8500_UHCI_BASE 0xd8007b01 /* UHCI */
38#define VT8500_PATA_BASE 0xd8008000 /* 512 PATA */
39#define VT8500_PS2_BASE 0xd8008800 /* 1k PS/2 */
40#define VT8500_NAND_BASE 0xd8009000 /* 1k NAND Controller */
41#define VT8500_NOR_BASE 0xd8009400 /* 1k NOR Controller */
42#define VT8500_SDMMC_BASE 0xd800a000 /* 1k SD/MMC Controller */
43#define VT8500_MS_BASE 0xd800b000 /* 1k MS/MSPRO Controller */
44#define VT8500_LCDC_BASE 0xd800e400 /* 1k LCD Controller */
45#define VT8500_VPU_BASE 0xd8050000 /* 256 VPU */
46#define VT8500_GOV_BASE 0xd8050300 /* 256 GOV */
47#define VT8500_GEGEA_BASE 0xd8050400 /* 768 GE/GE Alpha Mixing */
48#define VT8500_LCDF_BASE 0xd8050900 /* 256 LCD Formatter */
49#define VT8500_VID_BASE 0xd8050a00 /* 256 VID */
50#define VT8500_VPP_BASE 0xd8050b00 /* 256 VPP */
51#define VT8500_TSBK_BASE 0xd80f4000 /* 4k TSBK */
52#define VT8500_JPEGDEC_BASE 0xd80fe000 /* 4k JPEG Decoder */
53#define VT8500_JPEGENC_BASE 0xd80ff000 /* 4k JPEG Encoder */
54#define VT8500_RTC_BASE 0xd8100000 /* 64k RTC */
55#define VT8500_GPIO_BASE 0xd8110000 /* 64k GPIO Configuration */
56#define VT8500_SCC_BASE 0xd8120000 /* 64k System Configuration*/
57#define VT8500_PMC_BASE 0xd8130000 /* 64k PMC Configuration */
58#define VT8500_IC_BASE 0xd8140000 /* 64k Interrupt Controller*/
59#define VT8500_UART0_BASE 0xd8200000 /* 64k UART 0 */
60#define VT8500_UART2_BASE 0xd8210000 /* 64k UART 2 */
61#define VT8500_PWM_BASE 0xd8220000 /* 64k PWM Configuration */
62#define VT8500_SPI0_BASE 0xd8240000 /* 64k SPI 0 */
63#define VT8500_SPI1_BASE 0xd8250000 /* 64k SPI 1 */
64#define VT8500_CIR_BASE 0xd8270000 /* 64k CIR */
65#define VT8500_I2C0_BASE 0xd8280000 /* 64k I2C 0 */
66#define VT8500_AC97_BASE 0xd8290000 /* 64k AC97 */
67#define VT8500_SPI2_BASE 0xd82a0000 /* 64k SPI 2 */
68#define VT8500_UART1_BASE 0xd82b0000 /* 64k UART 1 */
69#define VT8500_UART3_BASE 0xd82c0000 /* 64k UART 3 */
70#define VT8500_PCM_BASE 0xd82d0000 /* 64k PCM */
71#define VT8500_I2C1_BASE 0xd8320000 /* 64k I2C 1 */
72#define VT8500_I2S_BASE 0xd8330000 /* 64k I2S */
73#define VT8500_ADC_BASE 0xd8340000 /* 64k ADC */
74
75#define VT8500_REGS_END_PHYS 0xd834ffff /* End of MMIO registers */
76#define VT8500_REGS_LENGTH (VT8500_REGS_END_PHYS \
77 - VT8500_REGS_START_PHYS + 1)
78
79#endif
diff --git a/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h b/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
deleted file mode 100644
index 6128627ac753..000000000000
--- a/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
+++ /dev/null
@@ -1,115 +0,0 @@
1/*
2 * arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21/* WM8505 Interrupt Sources */
22
23#define IRQ_UHCI 0 /* UHC FS (UHCI?) */
24#define IRQ_EHCI 1 /* UHC HS */
25#define IRQ_UDCDMA 2 /* UDC DMA */
26 /* Reserved */
27#define IRQ_PS2MOUSE 4 /* PS/2 Mouse */
28#define IRQ_UDC 5 /* UDC */
29#define IRQ_EXT0 6 /* External Interrupt 0 */
30#define IRQ_EXT1 7 /* External Interrupt 1 */
31#define IRQ_KEYPAD 8 /* Keypad */
32#define IRQ_DMA 9 /* DMA Controller */
33#define IRQ_ETHER 10 /* Ethernet MAC */
34 /* Reserved */
35 /* Reserved */
36#define IRQ_EXT2 13 /* External Interrupt 2 */
37#define IRQ_EXT3 14 /* External Interrupt 3 */
38#define IRQ_EXT4 15 /* External Interrupt 4 */
39#define IRQ_APB 16 /* APB Bridge */
40#define IRQ_DMA0 17 /* DMA Channel 0 */
41#define IRQ_I2C1 18 /* I2C 1 */
42#define IRQ_I2C0 19 /* I2C 0 */
43#define IRQ_SDMMC 20 /* SD/MMC Controller */
44#define IRQ_SDMMC_DMA 21 /* SD/MMC Controller DMA */
45#define IRQ_PMC_WU 22 /* Power Management Controller Wakeup */
46#define IRQ_PS2KBD 23 /* PS/2 Keyboard */
47#define IRQ_SPI0 24 /* SPI 0 */
48#define IRQ_SPI1 25 /* SPI 1 */
49#define IRQ_SPI2 26 /* SPI 2 */
50#define IRQ_DMA1 27 /* DMA Channel 1 */
51#define IRQ_NAND 28 /* NAND Flash Controller */
52#define IRQ_NAND_DMA 29 /* NAND Flash Controller DMA */
53#define IRQ_UART5 30 /* UART 5 */
54#define IRQ_UART4 31 /* UART 4 */
55#define IRQ_UART0 32 /* UART 0 */
56#define IRQ_UART1 33 /* UART 1 */
57#define IRQ_DMA2 34 /* DMA Channel 2 */
58#define IRQ_I2S 35 /* I2S */
59#define IRQ_PMCOS0 36 /* PMC OS Timer 0 */
60#define IRQ_PMCOS1 37 /* PMC OS Timer 1 */
61#define IRQ_PMCOS2 38 /* PMC OS Timer 2 */
62#define IRQ_PMCOS3 39 /* PMC OS Timer 3 */
63#define IRQ_DMA3 40 /* DMA Channel 3 */
64#define IRQ_DMA4 41 /* DMA Channel 4 */
65#define IRQ_AC97 42 /* AC97 Interface */
66 /* Reserved */
67#define IRQ_NOR 44 /* NOR Flash Controller */
68#define IRQ_DMA5 45 /* DMA Channel 5 */
69#define IRQ_DMA6 46 /* DMA Channel 6 */
70#define IRQ_UART2 47 /* UART 2 */
71#define IRQ_RTC 48 /* RTC Interrupt */
72#define IRQ_RTCSM 49 /* RTC Second/Minute Update Interrupt */
73#define IRQ_UART3 50 /* UART 3 */
74#define IRQ_DMA7 51 /* DMA Channel 7 */
75#define IRQ_EXT5 52 /* External Interrupt 5 */
76#define IRQ_EXT6 53 /* External Interrupt 6 */
77#define IRQ_EXT7 54 /* External Interrupt 7 */
78#define IRQ_CIR 55 /* CIR */
79#define IRQ_SIC0 56 /* SIC IRQ0 */
80#define IRQ_SIC1 57 /* SIC IRQ1 */
81#define IRQ_SIC2 58 /* SIC IRQ2 */
82#define IRQ_SIC3 59 /* SIC IRQ3 */
83#define IRQ_SIC4 60 /* SIC IRQ4 */
84#define IRQ_SIC5 61 /* SIC IRQ5 */
85#define IRQ_SIC6 62 /* SIC IRQ6 */
86#define IRQ_SIC7 63 /* SIC IRQ7 */
87 /* Reserved */
88#define IRQ_JPEGDEC 65 /* JPEG Decoder */
89#define IRQ_SAE 66 /* SAE (?) */
90 /* Reserved */
91#define IRQ_VPU 79 /* Video Processing Unit */
92#define IRQ_VPP 80 /* Video Post-Processor */
93#define IRQ_VID 81 /* Video Digital Input Interface */
94#define IRQ_SPU 82 /* SPU (?) */
95#define IRQ_PIP 83 /* PIP Error */
96#define IRQ_GE 84 /* Graphic Engine */
97#define IRQ_GOV 85 /* Graphic Overlay Engine */
98#define IRQ_DVO 86 /* Digital Video Output */
99 /* Reserved */
100#define IRQ_DMA8 92 /* DMA Channel 8 */
101#define IRQ_DMA9 93 /* DMA Channel 9 */
102#define IRQ_DMA10 94 /* DMA Channel 10 */
103#define IRQ_DMA11 95 /* DMA Channel 11 */
104#define IRQ_DMA12 96 /* DMA Channel 12 */
105#define IRQ_DMA13 97 /* DMA Channel 13 */
106#define IRQ_DMA14 98 /* DMA Channel 14 */
107#define IRQ_DMA15 99 /* DMA Channel 15 */
108 /* Reserved */
109#define IRQ_GOVW 111 /* GOVW (?) */
110#define IRQ_GOVRSDSCD 112 /* GOVR SDSCD (?) */
111#define IRQ_GOVRSDMIF 113 /* GOVR SDMIF (?) */
112#define IRQ_GOVRHDSCD 114 /* GOVR HDSCD (?) */
113#define IRQ_GOVRHDMIF 115 /* GOVR HDMIF (?) */
114
115#define WM8505_NR_IRQS 116
diff --git a/arch/arm/mach-vt8500/include/mach/wm8505_regs.h b/arch/arm/mach-vt8500/include/mach/wm8505_regs.h
deleted file mode 100644
index df1550941efb..000000000000
--- a/arch/arm/mach-vt8500/include/mach/wm8505_regs.h
+++ /dev/null
@@ -1,78 +0,0 @@
1/*
2 * arch/arm/mach-vt8500/include/mach/wm8505_regs.h
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#ifndef __ASM_ARM_ARCH_WM8505_REGS_H
21#define __ASM_ARM_ARCH_WM8505_REGS_H
22
23/* WM8505 Registers Map */
24
25#define WM8505_REGS_START_PHYS 0xd8000000 /* Start of MMIO registers */
26#define WM8505_REGS_START_VIRT 0xf8000000 /* Virtual mapping start */
27
28#define WM8505_DDR_BASE 0xd8000400 /* 1k DDR/DDR2 Memory
29 Controller */
30#define WM8505_DMA_BASE 0xd8001800 /* 1k DMA Controller */
31#define WM8505_VDMA_BASE 0xd8001c00 /* 1k VDMA */
32#define WM8505_SFLASH_BASE 0xd8002000 /* 1k Serial Flash Memory
33 Controller */
34#define WM8505_ETHER_BASE 0xd8004000 /* 1k Ethernet MAC 0 */
35#define WM8505_CIPHER_BASE 0xd8006000 /* 4k Cipher */
36#define WM8505_USB_BASE 0xd8007000 /* 2k USB 2.0 Host */
37# define WM8505_EHCI_BASE 0xd8007100 /* EHCI */
38# define WM8505_UHCI_BASE 0xd8007301 /* UHCI */
39#define WM8505_PS2_BASE 0xd8008800 /* 1k PS/2 */
40#define WM8505_NAND_BASE 0xd8009000 /* 1k NAND Controller */
41#define WM8505_NOR_BASE 0xd8009400 /* 1k NOR Controller */
42#define WM8505_SDMMC_BASE 0xd800a000 /* 1k SD/MMC Controller */
43#define WM8505_VPU_BASE 0xd8050000 /* 256 VPU */
44#define WM8505_GOV_BASE 0xd8050300 /* 256 GOV */
45#define WM8505_GEGEA_BASE 0xd8050400 /* 768 GE/GE Alpha Mixing */
46#define WM8505_GOVR_BASE 0xd8050800 /* 512 GOVR (frambuffer) */
47#define WM8505_VID_BASE 0xd8050a00 /* 256 VID */
48#define WM8505_SCL_BASE 0xd8050d00 /* 256 SCL */
49#define WM8505_VPP_BASE 0xd8050f00 /* 256 VPP */
50#define WM8505_JPEGDEC_BASE 0xd80fe000 /* 4k JPEG Decoder */
51#define WM8505_RTC_BASE 0xd8100000 /* 64k RTC */
52#define WM8505_GPIO_BASE 0xd8110000 /* 64k GPIO Configuration */
53#define WM8505_SCC_BASE 0xd8120000 /* 64k System Configuration*/
54#define WM8505_PMC_BASE 0xd8130000 /* 64k PMC Configuration */
55#define WM8505_IC_BASE 0xd8140000 /* 64k Interrupt Controller*/
56#define WM8505_SIC_BASE 0xd8150000 /* 64k Secondary IC */
57#define WM8505_UART0_BASE 0xd8200000 /* 64k UART 0 */
58#define WM8505_UART2_BASE 0xd8210000 /* 64k UART 2 */
59#define WM8505_PWM_BASE 0xd8220000 /* 64k PWM Configuration */
60#define WM8505_SPI0_BASE 0xd8240000 /* 64k SPI 0 */
61#define WM8505_SPI1_BASE 0xd8250000 /* 64k SPI 1 */
62#define WM8505_KEYPAD_BASE 0xd8260000 /* 64k Keypad control */
63#define WM8505_CIR_BASE 0xd8270000 /* 64k CIR */
64#define WM8505_I2C0_BASE 0xd8280000 /* 64k I2C 0 */
65#define WM8505_AC97_BASE 0xd8290000 /* 64k AC97 */
66#define WM8505_SPI2_BASE 0xd82a0000 /* 64k SPI 2 */
67#define WM8505_UART1_BASE 0xd82b0000 /* 64k UART 1 */
68#define WM8505_UART3_BASE 0xd82c0000 /* 64k UART 3 */
69#define WM8505_I2C1_BASE 0xd8320000 /* 64k I2C 1 */
70#define WM8505_I2S_BASE 0xd8330000 /* 64k I2S */
71#define WM8505_UART4_BASE 0xd8370000 /* 64k UART 4 */
72#define WM8505_UART5_BASE 0xd8380000 /* 64k UART 5 */
73
74#define WM8505_REGS_END_PHYS 0xd838ffff /* End of MMIO registers */
75#define WM8505_REGS_LENGTH (WM8505_REGS_END_PHYS \
76 - WM8505_REGS_START_PHYS + 1)
77
78#endif
diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c
index 642de0408f25..f8f9ab9bc56e 100644
--- a/arch/arm/mach-vt8500/irq.c
+++ b/arch/arm/mach-vt8500/irq.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * arch/arm/mach-vt8500/irq.c 2 * arch/arm/mach-vt8500/irq.c
3 * 3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> 5 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -18,81 +19,102 @@
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 20 */
20 21
22/*
23 * This file is copied and modified from the original irq.c provided by
24 * Alexey Charkov. Minor changes have been made for Device Tree Support.
25 */
26
27#include <linux/slab.h>
21#include <linux/io.h> 28#include <linux/io.h>
22#include <linux/irq.h> 29#include <linux/irq.h>
30#include <linux/irqdomain.h>
23#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/bitops.h>
33
34#include <linux/of.h>
35#include <linux/of_irq.h>
36#include <linux/of_address.h>
24 37
25#include <asm/irq.h> 38#include <asm/irq.h>
26 39
27#include "devices.h"
28 40
29#define VT8500_IC_DCTR 0x40 /* Destination control 41#define VT8500_ICPC_IRQ 0x20
30 register, 64*u8 */ 42#define VT8500_ICPC_FIQ 0x24
31#define VT8500_INT_ENABLE (1 << 3) 43#define VT8500_ICDC 0x40 /* Destination Control 64*u32 */
32#define VT8500_TRIGGER_HIGH (0 << 4) 44#define VT8500_ICIS 0x80 /* Interrupt status, 16*u32 */
33#define VT8500_TRIGGER_RISING (1 << 4) 45
34#define VT8500_TRIGGER_FALLING (2 << 4) 46/* ICPC */
47#define ICPC_MASK 0x3F
48#define ICPC_ROTATE BIT(6)
49
50/* IC_DCTR */
51#define ICDC_IRQ 0x00
52#define ICDC_FIQ 0x01
53#define ICDC_DSS0 0x02
54#define ICDC_DSS1 0x03
55#define ICDC_DSS2 0x04
56#define ICDC_DSS3 0x05
57#define ICDC_DSS4 0x06
58#define ICDC_DSS5 0x07
59
60#define VT8500_INT_DISABLE 0
61#define VT8500_INT_ENABLE BIT(3)
62
63#define VT8500_TRIGGER_HIGH 0
64#define VT8500_TRIGGER_RISING BIT(5)
65#define VT8500_TRIGGER_FALLING BIT(6)
35#define VT8500_EDGE ( VT8500_TRIGGER_RISING \ 66#define VT8500_EDGE ( VT8500_TRIGGER_RISING \
36 | VT8500_TRIGGER_FALLING) 67 | VT8500_TRIGGER_FALLING)
37#define VT8500_IC_STATUS 0x80 /* Interrupt status, 2*u32 */
38 68
39static void __iomem *ic_regbase; 69static int irq_cnt;
40static void __iomem *sic_regbase; 70
71struct vt8500_irq_priv {
72 void __iomem *base;
73};
41 74
42static void vt8500_irq_mask(struct irq_data *d) 75static void vt8500_irq_mask(struct irq_data *d)
43{ 76{
44 void __iomem *base = ic_regbase; 77 struct vt8500_irq_priv *priv =
45 unsigned irq = d->irq; 78 (struct vt8500_irq_priv *)(d->domain->host_data);
79 void __iomem *base = priv->base;
46 u8 edge; 80 u8 edge;
47 81
48 if (irq >= 64) { 82 edge = readb(base + VT8500_ICDC + d->hwirq) & VT8500_EDGE;
49 base = sic_regbase;
50 irq -= 64;
51 }
52 edge = readb(base + VT8500_IC_DCTR + irq) & VT8500_EDGE;
53 if (edge) { 83 if (edge) {
54 void __iomem *stat_reg = base + VT8500_IC_STATUS 84 void __iomem *stat_reg = base + VT8500_ICIS
55 + (irq < 32 ? 0 : 4); 85 + (d->hwirq < 32 ? 0 : 4);
56 unsigned status = readl(stat_reg); 86 unsigned status = readl(stat_reg);
57 87
58 status |= (1 << (irq & 0x1f)); 88 status |= (1 << (d->hwirq & 0x1f));
59 writel(status, stat_reg); 89 writel(status, stat_reg);
60 } else { 90 } else {
61 u8 dctr = readb(base + VT8500_IC_DCTR + irq); 91 u8 dctr = readb(base + VT8500_ICDC + d->hwirq);
62 92
63 dctr &= ~VT8500_INT_ENABLE; 93 dctr &= ~VT8500_INT_ENABLE;
64 writeb(dctr, base + VT8500_IC_DCTR + irq); 94 writeb(dctr, base + VT8500_ICDC + d->hwirq);
65 } 95 }
66} 96}
67 97
68static void vt8500_irq_unmask(struct irq_data *d) 98static void vt8500_irq_unmask(struct irq_data *d)
69{ 99{
70 void __iomem *base = ic_regbase; 100 struct vt8500_irq_priv *priv =
71 unsigned irq = d->irq; 101 (struct vt8500_irq_priv *)(d->domain->host_data);
102 void __iomem *base = priv->base;
72 u8 dctr; 103 u8 dctr;
73 104
74 if (irq >= 64) { 105 dctr = readb(base + VT8500_ICDC + d->hwirq);
75 base = sic_regbase;
76 irq -= 64;
77 }
78 dctr = readb(base + VT8500_IC_DCTR + irq);
79 dctr |= VT8500_INT_ENABLE; 106 dctr |= VT8500_INT_ENABLE;
80 writeb(dctr, base + VT8500_IC_DCTR + irq); 107 writeb(dctr, base + VT8500_ICDC + d->hwirq);
81} 108}
82 109
83static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type) 110static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
84{ 111{
85 void __iomem *base = ic_regbase; 112 struct vt8500_irq_priv *priv =
86 unsigned irq = d->irq; 113 (struct vt8500_irq_priv *)(d->domain->host_data);
87 unsigned orig_irq = irq; 114 void __iomem *base = priv->base;
88 u8 dctr; 115 u8 dctr;
89 116
90 if (irq >= 64) { 117 dctr = readb(base + VT8500_ICDC + d->hwirq);
91 base = sic_regbase;
92 irq -= 64;
93 }
94
95 dctr = readb(base + VT8500_IC_DCTR + irq);
96 dctr &= ~VT8500_EDGE; 118 dctr &= ~VT8500_EDGE;
97 119
98 switch (flow_type) { 120 switch (flow_type) {
@@ -100,18 +122,18 @@ static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type)
100 return -EINVAL; 122 return -EINVAL;
101 case IRQF_TRIGGER_HIGH: 123 case IRQF_TRIGGER_HIGH:
102 dctr |= VT8500_TRIGGER_HIGH; 124 dctr |= VT8500_TRIGGER_HIGH;
103 __irq_set_handler_locked(orig_irq, handle_level_irq); 125 __irq_set_handler_locked(d->irq, handle_level_irq);
104 break; 126 break;
105 case IRQF_TRIGGER_FALLING: 127 case IRQF_TRIGGER_FALLING:
106 dctr |= VT8500_TRIGGER_FALLING; 128 dctr |= VT8500_TRIGGER_FALLING;
107 __irq_set_handler_locked(orig_irq, handle_edge_irq); 129 __irq_set_handler_locked(d->irq, handle_edge_irq);
108 break; 130 break;
109 case IRQF_TRIGGER_RISING: 131 case IRQF_TRIGGER_RISING:
110 dctr |= VT8500_TRIGGER_RISING; 132 dctr |= VT8500_TRIGGER_RISING;
111 __irq_set_handler_locked(orig_irq, handle_edge_irq); 133 __irq_set_handler_locked(d->irq, handle_edge_irq);
112 break; 134 break;
113 } 135 }
114 writeb(dctr, base + VT8500_IC_DCTR + irq); 136 writeb(dctr, base + VT8500_ICDC + d->hwirq);
115 137
116 return 0; 138 return 0;
117} 139}
@@ -124,57 +146,76 @@ static struct irq_chip vt8500_irq_chip = {
124 .irq_set_type = vt8500_irq_set_type, 146 .irq_set_type = vt8500_irq_set_type,
125}; 147};
126 148
127void __init vt8500_init_irq(void) 149static void __init vt8500_init_irq_hw(void __iomem *base)
128{ 150{
129 unsigned int i; 151 unsigned int i;
130 152
131 ic_regbase = ioremap(wmt_ic_base, SZ_64K); 153 /* Enable rotating priority for IRQ */
154 writel(ICPC_ROTATE, base + VT8500_ICPC_IRQ);
155 writel(0x00, base + VT8500_ICPC_FIQ);
132 156
133 if (ic_regbase) { 157 for (i = 0; i < 64; i++) {
134 /* Enable rotating priority for IRQ */ 158 /* Disable all interrupts and route them to IRQ */
135 writel((1 << 6), ic_regbase + 0x20); 159 writeb(VT8500_INT_DISABLE | ICDC_IRQ,
136 writel(0, ic_regbase + 0x24); 160 base + VT8500_ICDC + i);
161 }
162}
137 163
138 for (i = 0; i < wmt_nr_irqs; i++) { 164static int vt8500_irq_map(struct irq_domain *h, unsigned int virq,
139 /* Disable all interrupts and route them to IRQ */ 165 irq_hw_number_t hw)
140 writeb(0x00, ic_regbase + VT8500_IC_DCTR + i); 166{
167 irq_set_chip_and_handler(virq, &vt8500_irq_chip, handle_level_irq);
168 set_irq_flags(virq, IRQF_VALID);
141 169
142 irq_set_chip_and_handler(i, &vt8500_irq_chip, 170 return 0;
143 handle_level_irq);
144 set_irq_flags(i, IRQF_VALID);
145 }
146 } else {
147 printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
148 }
149} 171}
150 172
151void __init wm8505_init_irq(void) 173static struct irq_domain_ops vt8500_irq_domain_ops = {
174 .map = vt8500_irq_map,
175 .xlate = irq_domain_xlate_onecell,
176};
177
178int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
152{ 179{
153 unsigned int i; 180 struct irq_domain *vt8500_irq_domain;
181 struct vt8500_irq_priv *priv;
182 int irq, i;
183 struct device_node *np = node;
184
185 priv = kzalloc(sizeof(struct vt8500_irq_priv), GFP_KERNEL);
186 priv->base = of_iomap(np, 0);
187
188 vt8500_irq_domain = irq_domain_add_legacy(node, 64, irq_cnt, 0,
189 &vt8500_irq_domain_ops, priv);
190 if (!vt8500_irq_domain)
191 pr_err("%s: Unable to add wmt irq domain!\n", __func__);
192
193 irq_set_default_host(vt8500_irq_domain);
194
195 vt8500_init_irq_hw(priv->base);
154 196
155 ic_regbase = ioremap(wmt_ic_base, SZ_64K); 197 pr_info("Added IRQ Controller @ %x [virq_base = %d]\n",
156 sic_regbase = ioremap(wmt_sic_base, SZ_64K); 198 (u32)(priv->base), irq_cnt);
157 199
158 if (ic_regbase && sic_regbase) { 200 /* check if this is a slaved controller */
159 /* Enable rotating priority for IRQ */ 201 if (of_irq_count(np) != 0) {
160 writel((1 << 6), ic_regbase + 0x20); 202 /* check that we have the correct number of interrupts */
161 writel(0, ic_regbase + 0x24); 203 if (of_irq_count(np) != 8) {
162 writel((1 << 6), sic_regbase + 0x20); 204 pr_err("%s: Incorrect IRQ map for slave controller\n",
163 writel(0, sic_regbase + 0x24); 205 __func__);
164 206 return -EINVAL;
165 for (i = 0; i < wmt_nr_irqs; i++) {
166 /* Disable all interrupts and route them to IRQ */
167 if (i < 64)
168 writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
169 else
170 writeb(0x00, sic_regbase + VT8500_IC_DCTR
171 + i - 64);
172
173 irq_set_chip_and_handler(i, &vt8500_irq_chip,
174 handle_level_irq);
175 set_irq_flags(i, IRQF_VALID);
176 } 207 }
177 } else { 208
178 printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n"); 209 for (i = 0; i < 8; i++) {
210 irq = irq_of_parse_and_map(np, i);
211 enable_irq(irq);
212 }
213
214 pr_info("vt8500-irq: Enabled slave->parent interrupts\n");
179 } 215 }
216
217 irq_cnt += 64;
218
219 return 0;
180} 220}
221
diff --git a/arch/arm/mach-vt8500/restart.c b/arch/arm/mach-vt8500/restart.c
deleted file mode 100644
index 497e89a5e130..000000000000
--- a/arch/arm/mach-vt8500/restart.c
+++ /dev/null
@@ -1,54 +0,0 @@
1/* linux/arch/arm/mach-vt8500/restart.c
2 *
3 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15#include <asm/io.h>
16#include <linux/of.h>
17#include <linux/of_address.h>
18
19#define LEGACY_PMC_BASE 0xD8130000
20#define WMT_PRIZM_PMSR_REG 0x60
21
22static void __iomem *pmc_base;
23
24void wmt_setup_restart(void)
25{
26 struct device_node *np;
27
28 /*
29 * Check if Power Mgmt Controller node is present in device tree. If no
30 * device tree node, use the legacy PMSR value (valid for all current
31 * SoCs).
32 */
33 np = of_find_compatible_node(NULL, NULL, "wmt,prizm-pmc");
34 if (np) {
35 pmc_base = of_iomap(np, 0);
36
37 if (!pmc_base)
38 pr_err("%s:of_iomap(pmc) failed\n", __func__);
39
40 of_node_put(np);
41 } else {
42 pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
43 if (!pmc_base) {
44 pr_err("%s:ioremap(rstc) failed\n", __func__);
45 return;
46 }
47 }
48}
49
50void wmt_restart(char mode, const char *cmd)
51{
52 if (pmc_base)
53 writel(1, pmc_base + WMT_PRIZM_PMSR_REG);
54}
diff --git a/arch/arm/mach-vt8500/timer.c b/arch/arm/mach-vt8500/timer.c
index d5376c592ab6..050e1833f2d0 100644
--- a/arch/arm/mach-vt8500/timer.c
+++ b/arch/arm/mach-vt8500/timer.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * arch/arm/mach-vt8500/timer.c 2 * arch/arm/mach-vt8500/timer_dt.c
3 * 3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> 5 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 * 6 *
6 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
@@ -18,18 +19,25 @@
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */ 20 */
20 21
22/*
23 * This file is copied and modified from the original timer.c provided by
24 * Alexey Charkov. Minor changes have been made for Device Tree Support.
25 */
26
21#include <linux/io.h> 27#include <linux/io.h>
22#include <linux/irq.h> 28#include <linux/irq.h>
23#include <linux/interrupt.h> 29#include <linux/interrupt.h>
24#include <linux/clocksource.h> 30#include <linux/clocksource.h>
25#include <linux/clockchips.h> 31#include <linux/clockchips.h>
26#include <linux/delay.h> 32#include <linux/delay.h>
27
28#include <asm/mach/time.h> 33#include <asm/mach/time.h>
29 34
30#include "devices.h" 35#include <linux/of.h>
36#include <linux/of_address.h>
37#include <linux/of_irq.h>
31 38
32#define VT8500_TIMER_OFFSET 0x0100 39#define VT8500_TIMER_OFFSET 0x0100
40#define VT8500_TIMER_HZ 3000000
33#define TIMER_MATCH_VAL 0x0000 41#define TIMER_MATCH_VAL 0x0000
34#define TIMER_COUNT_VAL 0x0010 42#define TIMER_COUNT_VAL 0x0010
35#define TIMER_STATUS_VAL 0x0014 43#define TIMER_STATUS_VAL 0x0014
@@ -39,7 +47,6 @@
39#define TIMER_COUNT_R_ACTIVE (1 << 5) /* not ready for read */ 47#define TIMER_COUNT_R_ACTIVE (1 << 5) /* not ready for read */
40#define TIMER_COUNT_W_ACTIVE (1 << 4) /* not ready for write */ 48#define TIMER_COUNT_W_ACTIVE (1 << 4) /* not ready for write */
41#define TIMER_MATCH_W_ACTIVE (1 << 0) /* not ready for write */ 49#define TIMER_MATCH_W_ACTIVE (1 << 0) /* not ready for write */
42#define VT8500_TIMER_HZ 3000000
43 50
44#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t) 51#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
45 52
@@ -55,7 +62,7 @@ static cycle_t vt8500_timer_read(struct clocksource *cs)
55 return readl(regbase + TIMER_COUNT_VAL); 62 return readl(regbase + TIMER_COUNT_VAL);
56} 63}
57 64
58struct clocksource clocksource = { 65static struct clocksource clocksource = {
59 .name = "vt8500_timer", 66 .name = "vt8500_timer",
60 .rating = 200, 67 .rating = 200,
61 .read = vt8500_timer_read, 68 .read = vt8500_timer_read,
@@ -98,7 +105,7 @@ static void vt8500_timer_set_mode(enum clock_event_mode mode,
98 } 105 }
99} 106}
100 107
101struct clock_event_device clockevent = { 108static struct clock_event_device clockevent = {
102 .name = "vt8500_timer", 109 .name = "vt8500_timer",
103 .features = CLOCK_EVT_FEAT_ONESHOT, 110 .features = CLOCK_EVT_FEAT_ONESHOT,
104 .rating = 200, 111 .rating = 200,
@@ -115,26 +122,51 @@ static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
115 return IRQ_HANDLED; 122 return IRQ_HANDLED;
116} 123}
117 124
118struct irqaction irq = { 125static struct irqaction irq = {
119 .name = "vt8500_timer", 126 .name = "vt8500_timer",
120 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 127 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
121 .handler = vt8500_timer_interrupt, 128 .handler = vt8500_timer_interrupt,
122 .dev_id = &clockevent, 129 .dev_id = &clockevent,
123}; 130};
124 131
125static void __init vt8500_timer_init(void) 132static struct of_device_id vt8500_timer_ids[] = {
133 { .compatible = "via,vt8500-timer" },
134 { }
135};
136
137void __init vt8500_timer_init(void)
126{ 138{
127 regbase = ioremap(wmt_pmc_base + VT8500_TIMER_OFFSET, 0x28); 139 struct device_node *np;
128 if (!regbase) 140 int timer_irq;
129 printk(KERN_ERR "vt8500_timer_init: failed to map MMIO registers\n"); 141
142 np = of_find_matching_node(NULL, vt8500_timer_ids);
143 if (!np) {
144 pr_err("%s: Timer description missing from Device Tree\n",
145 __func__);
146 return;
147 }
148 regbase = of_iomap(np, 0);
149 if (!regbase) {
150 pr_err("%s: Missing iobase description in Device Tree\n",
151 __func__);
152 of_node_put(np);
153 return;
154 }
155 timer_irq = irq_of_parse_and_map(np, 0);
156 if (!timer_irq) {
157 pr_err("%s: Missing irq description in Device Tree\n",
158 __func__);
159 of_node_put(np);
160 return;
161 }
130 162
131 writel(1, regbase + TIMER_CTRL_VAL); 163 writel(1, regbase + TIMER_CTRL_VAL);
132 writel(0xf, regbase + TIMER_STATUS_VAL); 164 writel(0xf, regbase + TIMER_STATUS_VAL);
133 writel(~0, regbase + TIMER_MATCH_VAL); 165 writel(~0, regbase + TIMER_MATCH_VAL);
134 166
135 if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ)) 167 if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ))
136 printk(KERN_ERR "vt8500_timer_init: clocksource_register failed for %s\n", 168 pr_err("%s: vt8500_timer_init: clocksource_register failed for %s\n",
137 clocksource.name); 169 __func__, clocksource.name);
138 170
139 clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4); 171 clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4);
140 172
@@ -144,12 +176,9 @@ static void __init vt8500_timer_init(void)
144 clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent); 176 clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent);
145 clockevent.cpumask = cpumask_of(0); 177 clockevent.cpumask = cpumask_of(0);
146 178
147 if (setup_irq(wmt_timer_irq, &irq)) 179 if (setup_irq(timer_irq, &irq))
148 printk(KERN_ERR "vt8500_timer_init: setup_irq failed for %s\n", 180 pr_err("%s: setup_irq failed for %s\n", __func__,
149 clockevent.name); 181 clockevent.name);
150 clockevents_register_device(&clockevent); 182 clockevents_register_device(&clockevent);
151} 183}
152 184
153struct sys_timer vt8500_timer = {
154 .init = vt8500_timer_init
155};
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
new file mode 100644
index 000000000000..449499354449
--- /dev/null
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -0,0 +1,196 @@
1/*
2 * arch/arm/mach-vt8500/vt8500.c
3 *
4 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/io.h>
22#include <linux/pm.h>
23
24#include <asm/mach-types.h>
25#include <asm/mach/arch.h>
26#include <asm/mach/time.h>
27#include <asm/mach/map.h>
28
29#include <linux/of.h>
30#include <linux/of_address.h>
31#include <linux/of_irq.h>
32#include <linux/of_platform.h>
33
34#include <mach/restart.h>
35#include <mach/gpio.h>
36
37#include "common.h"
38
39#define LEGACY_GPIO_BASE 0xD8110000
40#define LEGACY_PMC_BASE 0xD8130000
41
42/* Registers in GPIO Controller */
43#define VT8500_GPIO_MUX_REG 0x200
44
45/* Registers in Power Management Controller */
46#define VT8500_HCR_REG 0x12
47#define VT8500_PMSR_REG 0x60
48
49static void __iomem *pmc_base;
50
51void vt8500_restart(char mode, const char *cmd)
52{
53 if (pmc_base)
54 writel(1, pmc_base + VT8500_PMSR_REG);
55}
56
57static struct map_desc vt8500_io_desc[] __initdata = {
58 /* SoC MMIO registers */
59 [0] = {
60 .virtual = 0xf8000000,
61 .pfn = __phys_to_pfn(0xd8000000),
62 .length = 0x00390000, /* max of all chip variants */
63 .type = MT_DEVICE
64 },
65};
66
67void __init vt8500_map_io(void)
68{
69 iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc));
70}
71
72static void vt8500_power_off(void)
73{
74 local_irq_disable();
75 writew(5, pmc_base + VT8500_HCR_REG);
76 asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
77}
78
79void __init vt8500_init(void)
80{
81 struct device_node *np, *fb;
82 void __iomem *gpio_base;
83
84#ifdef CONFIG_FB_VT8500
85 fb = of_find_compatible_node(NULL, NULL, "via,vt8500-fb");
86 if (fb) {
87 np = of_find_compatible_node(NULL, NULL, "via,vt8500-gpio");
88 if (np) {
89 gpio_base = of_iomap(np, 0);
90
91 if (!gpio_base)
92 pr_err("%s: of_iomap(gpio_mux) failed\n",
93 __func__);
94
95 of_node_put(np);
96 } else {
97 gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000);
98 if (!gpio_base)
99 pr_err("%s: ioremap(legacy_gpio_mux) failed\n",
100 __func__);
101 }
102 if (gpio_base) {
103 writel(readl(gpio_base + VT8500_GPIO_MUX_REG) | 1,
104 gpio_base + VT8500_GPIO_MUX_REG);
105 iounmap(gpio_base);
106 } else
107 pr_err("%s: Could not remap GPIO mux\n", __func__);
108
109 of_node_put(fb);
110 }
111#endif
112
113#ifdef CONFIG_FB_WM8505
114 fb = of_find_compatible_node(NULL, NULL, "wm,wm8505-fb");
115 if (fb) {
116 np = of_find_compatible_node(NULL, NULL, "wm,wm8505-gpio");
117 if (!np)
118 np = of_find_compatible_node(NULL, NULL,
119 "wm,wm8650-gpio");
120 if (np) {
121 gpio_base = of_iomap(np, 0);
122
123 if (!gpio_base)
124 pr_err("%s: of_iomap(gpio_mux) failed\n",
125 __func__);
126
127 of_node_put(np);
128 } else {
129 gpio_base = ioremap(LEGACY_GPIO_BASE, 0x1000);
130 if (!gpio_base)
131 pr_err("%s: ioremap(legacy_gpio_mux) failed\n",
132 __func__);
133 }
134 if (gpio_base) {
135 writel(readl(gpio_base + VT8500_GPIO_MUX_REG) |
136 0x80000000, gpio_base + VT8500_GPIO_MUX_REG);
137 iounmap(gpio_base);
138 } else
139 pr_err("%s: Could not remap GPIO mux\n", __func__);
140
141 of_node_put(fb);
142 }
143#endif
144
145 np = of_find_compatible_node(NULL, NULL, "via,vt8500-pmc");
146 if (np) {
147 pmc_base = of_iomap(np, 0);
148
149 if (!pmc_base)
150 pr_err("%s:of_iomap(pmc) failed\n", __func__);
151
152 of_node_put(np);
153 } else {
154 pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
155 if (!pmc_base)
156 pr_err("%s:ioremap(power_off) failed\n", __func__);
157 }
158 if (pmc_base)
159 pm_power_off = &vt8500_power_off;
160 else
161 pr_err("%s: PMC Hibernation register could not be remapped, not enabling power off!\n", __func__);
162
163 vtwm_clk_init(pmc_base);
164
165 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
166}
167
168static const struct of_device_id vt8500_irq_match[] __initconst = {
169 { .compatible = "via,vt8500-intc", .data = vt8500_irq_init, },
170 { /* sentinel */ },
171};
172
173static void __init vt8500_init_irq(void)
174{
175 of_irq_init(vt8500_irq_match);
176};
177
178static struct sys_timer vt8500_timer = {
179 .init = vt8500_timer_init,
180};
181
182static const char * const vt8500_dt_compat[] = {
183 "via,vt8500",
184 "wm,wm8650",
185 "wm,wm8505",
186};
187
188DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
189 .dt_compat = vt8500_dt_compat,
190 .map_io = vt8500_map_io,
191 .init_irq = vt8500_init_irq,
192 .timer = &vt8500_timer,
193 .init_machine = vt8500_init,
194 .restart = vt8500_restart,
195MACHINE_END
196
diff --git a/arch/arm/mach-vt8500/wm8505_7in.c b/arch/arm/mach-vt8500/wm8505_7in.c
deleted file mode 100644
index db19886caf7c..000000000000
--- a/arch/arm/mach-vt8500/wm8505_7in.c
+++ /dev/null
@@ -1,79 +0,0 @@
1/*
2 * arch/arm/mach-vt8500/wm8505_7in.c
3 *
4 * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include <linux/io.h>
22#include <linux/pm.h>
23
24#include <asm/mach-types.h>
25#include <asm/mach/arch.h>
26#include <mach/restart.h>
27
28#include "devices.h"
29
30static void __iomem *pmc_hiber;
31
32static struct platform_device *devices[] __initdata = {
33 &vt8500_device_uart0,
34 &vt8500_device_ehci,
35 &vt8500_device_wm8505_fb,
36 &vt8500_device_ge_rops,
37 &vt8500_device_pwm,
38 &vt8500_device_pwmbl,
39 &vt8500_device_rtc,
40};
41
42static void vt8500_power_off(void)
43{
44 local_irq_disable();
45 writew(5, pmc_hiber);
46 asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
47}
48
49void __init wm8505_7in_init(void)
50{
51#ifdef CONFIG_FB_WM8505
52 void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4);
53 if (gpio_mux_reg) {
54 writel(readl(gpio_mux_reg) | 0x80000000, gpio_mux_reg);
55 iounmap(gpio_mux_reg);
56 } else {
57 printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n");
58 }
59#endif
60 pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2);
61 if (pmc_hiber)
62 pm_power_off = &vt8500_power_off;
63 else
64 printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
65 wmt_setup_restart();
66 wm8505_set_resources();
67 platform_add_devices(devices, ARRAY_SIZE(devices));
68 vt8500_gpio_init();
69}
70
71MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
72 .atag_offset = 0x100,
73 .restart = wmt_restart,
74 .reserve = wm8505_reserve_mem,
75 .map_io = wm8505_map_io,
76 .init_irq = wm8505_init_irq,
77 .timer = &vt8500_timer,
78 .init_machine = wm8505_7in_init,
79MACHINE_END
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 6327536b4900..e48e0da5a884 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_ARCH_MMP) += mmp/
16endif 16endif
17obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o 17obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
18obj-$(CONFIG_ARCH_U8500) += ux500/ 18obj-$(CONFIG_ARCH_U8500) += ux500/
19obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
19 20
20# Chip specific 21# Chip specific
21obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o 22obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c
new file mode 100644
index 000000000000..a885600f5270
--- /dev/null
+++ b/drivers/clk/clk-vt8500.c
@@ -0,0 +1,510 @@
1/*
2 * Clock implementation for VIA/Wondermedia SoC's
3 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/io.h>
17#include <linux/of.h>
18#include <linux/slab.h>
19#include <linux/bitops.h>
20#include <linux/clkdev.h>
21#include <linux/clk-provider.h>
22
23/* All clocks share the same lock as none can be changed concurrently */
24static DEFINE_SPINLOCK(_lock);
25
26struct clk_device {
27 struct clk_hw hw;
28 void __iomem *div_reg;
29 unsigned int div_mask;
30 void __iomem *en_reg;
31 int en_bit;
32 spinlock_t *lock;
33};
34
35/*
36 * Add new PLL_TYPE_x definitions here as required. Use the first known model
37 * to support the new type as the name.
38 * Add case statements to vtwm_pll_recalc_rate(), vtwm_pll_round_round() and
39 * vtwm_pll_set_rate() to handle the new PLL_TYPE_x
40 */
41
42#define PLL_TYPE_VT8500 0
43#define PLL_TYPE_WM8650 1
44
45struct clk_pll {
46 struct clk_hw hw;
47 void __iomem *reg;
48 spinlock_t *lock;
49 int type;
50};
51
52static void __iomem *pmc_base;
53
54#define to_clk_device(_hw) container_of(_hw, struct clk_device, hw)
55
56#define VT8500_PMC_BUSY_MASK 0x18
57
58static void vt8500_pmc_wait_busy(void)
59{
60 while (readl(pmc_base) & VT8500_PMC_BUSY_MASK)
61 cpu_relax();
62}
63
64static int vt8500_dclk_enable(struct clk_hw *hw)
65{
66 struct clk_device *cdev = to_clk_device(hw);
67 u32 en_val;
68 unsigned long flags = 0;
69
70 spin_lock_irqsave(cdev->lock, flags);
71
72 en_val = readl(cdev->en_reg);
73 en_val |= BIT(cdev->en_bit);
74 writel(en_val, cdev->en_reg);
75
76 spin_unlock_irqrestore(cdev->lock, flags);
77 return 0;
78}
79
80static void vt8500_dclk_disable(struct clk_hw *hw)
81{
82 struct clk_device *cdev = to_clk_device(hw);
83 u32 en_val;
84 unsigned long flags = 0;
85
86 spin_lock_irqsave(cdev->lock, flags);
87
88 en_val = readl(cdev->en_reg);
89 en_val &= ~BIT(cdev->en_bit);
90 writel(en_val, cdev->en_reg);
91
92 spin_unlock_irqrestore(cdev->lock, flags);
93}
94
95static int vt8500_dclk_is_enabled(struct clk_hw *hw)
96{
97 struct clk_device *cdev = to_clk_device(hw);
98 u32 en_val = (readl(cdev->en_reg) & BIT(cdev->en_bit));
99
100 return en_val ? 1 : 0;
101}
102
103static unsigned long vt8500_dclk_recalc_rate(struct clk_hw *hw,
104 unsigned long parent_rate)
105{
106 struct clk_device *cdev = to_clk_device(hw);
107 u32 div = readl(cdev->div_reg) & cdev->div_mask;
108
109 /* Special case for SDMMC devices */
110 if ((cdev->div_mask == 0x3F) && (div & BIT(5)))
111 div = 64 * (div & 0x1f);
112
113 /* div == 0 is actually the highest divisor */
114 if (div == 0)
115 div = (cdev->div_mask + 1);
116
117 return parent_rate / div;
118}
119
120static long vt8500_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
121 unsigned long *prate)
122{
123 u32 divisor = *prate / rate;
124
125 return *prate / divisor;
126}
127
128static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
129 unsigned long parent_rate)
130{
131 struct clk_device *cdev = to_clk_device(hw);
132 u32 divisor = parent_rate / rate;
133 unsigned long flags = 0;
134
135 if (divisor == cdev->div_mask + 1)
136 divisor = 0;
137
138 if (divisor > cdev->div_mask) {
139 pr_err("%s: invalid divisor for clock\n", __func__);
140 return -EINVAL;
141 }
142
143 spin_lock_irqsave(cdev->lock, flags);
144
145 vt8500_pmc_wait_busy();
146 writel(divisor, cdev->div_reg);
147 vt8500_pmc_wait_busy();
148
149 spin_lock_irqsave(cdev->lock, flags);
150
151 return 0;
152}
153
154
155static const struct clk_ops vt8500_gated_clk_ops = {
156 .enable = vt8500_dclk_enable,
157 .disable = vt8500_dclk_disable,
158 .is_enabled = vt8500_dclk_is_enabled,
159};
160
161static const struct clk_ops vt8500_divisor_clk_ops = {
162 .round_rate = vt8500_dclk_round_rate,
163 .set_rate = vt8500_dclk_set_rate,
164 .recalc_rate = vt8500_dclk_recalc_rate,
165};
166
167static const struct clk_ops vt8500_gated_divisor_clk_ops = {
168 .enable = vt8500_dclk_enable,
169 .disable = vt8500_dclk_disable,
170 .is_enabled = vt8500_dclk_is_enabled,
171 .round_rate = vt8500_dclk_round_rate,
172 .set_rate = vt8500_dclk_set_rate,
173 .recalc_rate = vt8500_dclk_recalc_rate,
174};
175
176#define CLK_INIT_GATED BIT(0)
177#define CLK_INIT_DIVISOR BIT(1)
178#define CLK_INIT_GATED_DIVISOR (CLK_INIT_DIVISOR | CLK_INIT_GATED)
179
180static __init void vtwm_device_clk_init(struct device_node *node)
181{
182 u32 en_reg, div_reg;
183 struct clk *clk;
184 struct clk_device *dev_clk;
185 const char *clk_name = node->name;
186 const char *parent_name;
187 struct clk_init_data init;
188 int rc;
189 int clk_init_flags = 0;
190
191 dev_clk = kzalloc(sizeof(*dev_clk), GFP_KERNEL);
192 if (WARN_ON(!dev_clk))
193 return;
194
195 dev_clk->lock = &_lock;
196
197 rc = of_property_read_u32(node, "enable-reg", &en_reg);
198 if (!rc) {
199 dev_clk->en_reg = pmc_base + en_reg;
200 rc = of_property_read_u32(node, "enable-bit", &dev_clk->en_bit);
201 if (rc) {
202 pr_err("%s: enable-bit property required for gated clock\n",
203 __func__);
204 return;
205 }
206 clk_init_flags |= CLK_INIT_GATED;
207 }
208
209 rc = of_property_read_u32(node, "divisor-reg", &div_reg);
210 if (!rc) {
211 dev_clk->div_reg = pmc_base + div_reg;
212 /*
213 * use 0x1f as the default mask since it covers
214 * almost all the clocks and reduces dts properties
215 */
216 dev_clk->div_mask = 0x1f;
217
218 of_property_read_u32(node, "divisor-mask", &dev_clk->div_mask);
219 clk_init_flags |= CLK_INIT_DIVISOR;
220 }
221
222 of_property_read_string(node, "clock-output-names", &clk_name);
223
224 switch (clk_init_flags) {
225 case CLK_INIT_GATED:
226 init.ops = &vt8500_gated_clk_ops;
227 break;
228 case CLK_INIT_DIVISOR:
229 init.ops = &vt8500_divisor_clk_ops;
230 break;
231 case CLK_INIT_GATED_DIVISOR:
232 init.ops = &vt8500_gated_divisor_clk_ops;
233 break;
234 default:
235 pr_err("%s: Invalid clock description in device tree\n",
236 __func__);
237 kfree(dev_clk);
238 return;
239 }
240
241 init.name = clk_name;
242 init.flags = 0;
243 parent_name = of_clk_get_parent_name(node, 0);
244 init.parent_names = &parent_name;
245 init.num_parents = 1;
246
247 dev_clk->hw.init = &init;
248
249 clk = clk_register(NULL, &dev_clk->hw);
250 if (WARN_ON(IS_ERR(clk))) {
251 kfree(dev_clk);
252 return;
253 }
254 rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
255 clk_register_clkdev(clk, clk_name, NULL);
256}
257
258
259/* PLL clock related functions */
260
261#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
262
263/* Helper macros for PLL_VT8500 */
264#define VT8500_PLL_MUL(x) ((x & 0x1F) << 1)
265#define VT8500_PLL_DIV(x) ((x & 0x100) ? 1 : 2)
266
267#define VT8500_BITS_TO_FREQ(r, m, d) \
268 ((r / d) * m)
269
270#define VT8500_BITS_TO_VAL(m, d) \
271 ((d == 2 ? 0 : 0x100) | ((m >> 1) & 0x1F))
272
273/* Helper macros for PLL_WM8650 */
274#define WM8650_PLL_MUL(x) (x & 0x3FF)
275#define WM8650_PLL_DIV(x) (((x >> 10) & 7) * (1 << ((x >> 13) & 3)))
276
277#define WM8650_BITS_TO_FREQ(r, m, d1, d2) \
278 (r * m / (d1 * (1 << d2)))
279
280#define WM8650_BITS_TO_VAL(m, d1, d2) \
281 ((d2 << 13) | (d1 << 10) | (m & 0x3FF))
282
283
284static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
285 u32 *multiplier, u32 *prediv)
286{
287 unsigned long tclk;
288
289 /* sanity check */
290 if ((rate < parent_rate * 4) || (rate > parent_rate * 62)) {
291 pr_err("%s: requested rate out of range\n", __func__);
292 *multiplier = 0;
293 *prediv = 1;
294 return;
295 }
296 if (rate <= parent_rate * 31)
297 /* use the prediv to double the resolution */
298 *prediv = 2;
299 else
300 *prediv = 1;
301
302 *multiplier = rate / (parent_rate / *prediv);
303 tclk = (parent_rate / *prediv) * *multiplier;
304
305 if (tclk != rate)
306 pr_warn("%s: requested rate %lu, found rate %lu\n", __func__,
307 rate, tclk);
308}
309
310static void wm8650_find_pll_bits(unsigned long rate, unsigned long parent_rate,
311 u32 *multiplier, u32 *divisor1, u32 *divisor2)
312{
313 u32 mul, div1, div2;
314 u32 best_mul, best_div1, best_div2;
315 unsigned long tclk, rate_err, best_err;
316
317 best_err = (unsigned long)-1;
318
319 /* Find the closest match (lower or equal to requested) */
320 for (div1 = 5; div1 >= 3; div1--)
321 for (div2 = 3; div2 >= 0; div2--)
322 for (mul = 3; mul <= 1023; mul++) {
323 tclk = parent_rate * mul / (div1 * (1 << div2));
324 if (tclk > rate)
325 continue;
326 /* error will always be +ve */
327 rate_err = rate - tclk;
328 if (rate_err == 0) {
329 *multiplier = mul;
330 *divisor1 = div1;
331 *divisor2 = div2;
332 return;
333 }
334
335 if (rate_err < best_err) {
336 best_err = rate_err;
337 best_mul = mul;
338 best_div1 = div1;
339 best_div2 = div2;
340 }
341 }
342
343 /* if we got here, it wasn't an exact match */
344 pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
345 rate - best_err);
346 *multiplier = mul;
347 *divisor1 = div1;
348 *divisor2 = div2;
349}
350
351static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
352 unsigned long parent_rate)
353{
354 struct clk_pll *pll = to_clk_pll(hw);
355 u32 mul, div1, div2;
356 u32 pll_val;
357 unsigned long flags = 0;
358
359 /* sanity check */
360
361 switch (pll->type) {
362 case PLL_TYPE_VT8500:
363 vt8500_find_pll_bits(rate, parent_rate, &mul, &div1);
364 pll_val = VT8500_BITS_TO_VAL(mul, div1);
365 break;
366 case PLL_TYPE_WM8650:
367 wm8650_find_pll_bits(rate, parent_rate, &mul, &div1, &div2);
368 pll_val = WM8650_BITS_TO_VAL(mul, div1, div2);
369 break;
370 default:
371 pr_err("%s: invalid pll type\n", __func__);
372 return 0;
373 }
374
375 spin_lock_irqsave(pll->lock, flags);
376
377 vt8500_pmc_wait_busy();
378 writel(pll_val, pll->reg);
379 vt8500_pmc_wait_busy();
380
381 spin_unlock_irqrestore(pll->lock, flags);
382
383 return 0;
384}
385
386static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
387 unsigned long *prate)
388{
389 struct clk_pll *pll = to_clk_pll(hw);
390 u32 mul, div1, div2;
391 long round_rate;
392
393 switch (pll->type) {
394 case PLL_TYPE_VT8500:
395 vt8500_find_pll_bits(rate, *prate, &mul, &div1);
396 round_rate = VT8500_BITS_TO_FREQ(*prate, mul, div1);
397 break;
398 case PLL_TYPE_WM8650:
399 wm8650_find_pll_bits(rate, *prate, &mul, &div1, &div2);
400 round_rate = WM8650_BITS_TO_FREQ(*prate, mul, div1, div2);
401 break;
402 default:
403 round_rate = 0;
404 }
405
406 return round_rate;
407}
408
409static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw,
410 unsigned long parent_rate)
411{
412 struct clk_pll *pll = to_clk_pll(hw);
413 u32 pll_val = readl(pll->reg);
414 unsigned long pll_freq;
415
416 switch (pll->type) {
417 case PLL_TYPE_VT8500:
418 pll_freq = parent_rate * VT8500_PLL_MUL(pll_val);
419 pll_freq /= VT8500_PLL_DIV(pll_val);
420 break;
421 case PLL_TYPE_WM8650:
422 pll_freq = parent_rate * WM8650_PLL_MUL(pll_val);
423 pll_freq /= WM8650_PLL_DIV(pll_val);
424 break;
425 default:
426 pll_freq = 0;
427 }
428
429 return pll_freq;
430}
431
432const struct clk_ops vtwm_pll_ops = {
433 .round_rate = vtwm_pll_round_rate,
434 .set_rate = vtwm_pll_set_rate,
435 .recalc_rate = vtwm_pll_recalc_rate,
436};
437
438static __init void vtwm_pll_clk_init(struct device_node *node, int pll_type)
439{
440 u32 reg;
441 struct clk *clk;
442 struct clk_pll *pll_clk;
443 const char *clk_name = node->name;
444 const char *parent_name;
445 struct clk_init_data init;
446 int rc;
447
448 rc = of_property_read_u32(node, "reg", &reg);
449 if (WARN_ON(rc))
450 return;
451
452 pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL);
453 if (WARN_ON(!pll_clk))
454 return;
455
456 pll_clk->reg = pmc_base + reg;
457 pll_clk->lock = &_lock;
458 pll_clk->type = pll_type;
459
460 of_property_read_string(node, "clock-output-names", &clk_name);
461
462 init.name = clk_name;
463 init.ops = &vtwm_pll_ops;
464 init.flags = 0;
465 parent_name = of_clk_get_parent_name(node, 0);
466 init.parent_names = &parent_name;
467 init.num_parents = 1;
468
469 pll_clk->hw.init = &init;
470
471 clk = clk_register(NULL, &pll_clk->hw);
472 if (WARN_ON(IS_ERR(clk))) {
473 kfree(pll_clk);
474 return;
475 }
476 rc = of_clk_add_provider(node, of_clk_src_simple_get, clk);
477 clk_register_clkdev(clk, clk_name, NULL);
478}
479
480
481/* Wrappers for initialization functions */
482
483static void __init vt8500_pll_init(struct device_node *node)
484{
485 vtwm_pll_clk_init(node, PLL_TYPE_VT8500);
486}
487
488static void __init wm8650_pll_init(struct device_node *node)
489{
490 vtwm_pll_clk_init(node, PLL_TYPE_WM8650);
491}
492
493static const __initconst struct of_device_id clk_match[] = {
494 { .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
495 { .compatible = "via,vt8500-pll-clock", .data = vt8500_pll_init, },
496 { .compatible = "wm,wm8650-pll-clock", .data = wm8650_pll_init, },
497 { .compatible = "via,vt8500-device-clock",
498 .data = vtwm_device_clk_init, },
499 { /* sentinel */ }
500};
501
502void __init vtwm_clk_init(void __iomem *base)
503{
504 if (!base)
505 return;
506
507 pmc_base = base;
508
509 of_clk_init(clk_match);
510}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index ba7926f5c099..a00b828b1643 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -183,6 +183,12 @@ config GPIO_STA2X11
183 Say yes here to support the STA2x11/ConneXt GPIO device. 183 Say yes here to support the STA2x11/ConneXt GPIO device.
184 The GPIO module has 128 GPIO pins with alternate functions. 184 The GPIO module has 128 GPIO pins with alternate functions.
185 185
186config GPIO_VT8500
187 bool "VIA/Wondermedia SoC GPIO Support"
188 depends on ARCH_VT8500
189 help
190 Say yes here to support the VT8500/WM8505/WM8650 GPIO controller.
191
186config GPIO_XILINX 192config GPIO_XILINX
187 bool "Xilinx GPIO support" 193 bool "Xilinx GPIO support"
188 depends on PPC_OF || MICROBLAZE 194 depends on PPC_OF || MICROBLAZE
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 153caceeb053..a288142ad998 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_GPIO_TPS65912) += gpio-tps65912.o
69obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o 69obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o
70obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o 70obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o
71obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o 71obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o
72obj-$(CONFIG_GPIO_VT8500) += gpio-vt8500.o
72obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o 73obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o
73obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o 74obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o
74obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o 75obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c
new file mode 100644
index 000000000000..bcd8e4aa7c7d
--- /dev/null
+++ b/drivers/gpio/gpio-vt8500.c
@@ -0,0 +1,316 @@
1/* drivers/gpio/gpio-vt8500.c
2 *
3 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
4 * Based on arch/arm/mach-vt8500/gpio.c:
5 * - Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/err.h>
20#include <linux/io.h>
21#include <linux/gpio.h>
22#include <linux/platform_device.h>
23#include <linux/bitops.h>
24#include <linux/of.h>
25#include <linux/of_address.h>
26#include <linux/of_irq.h>
27#include <linux/of_device.h>
28
29/*
30 We handle GPIOs by bank, each bank containing up to 32 GPIOs covered
31 by one set of registers (although not all may be valid).
32
33 Because different SoC's have different register offsets, we pass the
34 register offsets as data in vt8500_gpio_dt_ids[].
35
36 A value of NO_REG is used to indicate that this register is not
37 supported. Only used for ->en at the moment.
38*/
39
40#define NO_REG 0xFFFF
41
42/*
43 * struct vt8500_gpio_bank_regoffsets
44 * @en: offset to enable register of the bank
45 * @dir: offset to direction register of the bank
46 * @data_out: offset to the data out register of the bank
47 * @data_in: offset to the data in register of the bank
48 * @ngpio: highest valid pin in this bank
49 */
50
51struct vt8500_gpio_bank_regoffsets {
52 unsigned int en;
53 unsigned int dir;
54 unsigned int data_out;
55 unsigned int data_in;
56 unsigned char ngpio;
57};
58
59struct vt8500_gpio_data {
60 unsigned int num_banks;
61 struct vt8500_gpio_bank_regoffsets banks[];
62};
63
64#define VT8500_BANK(__en, __dir, __out, __in, __ngpio) \
65{ \
66 .en = __en, \
67 .dir = __dir, \
68 .data_out = __out, \
69 .data_in = __in, \
70 .ngpio = __ngpio, \
71}
72
73static struct vt8500_gpio_data vt8500_data = {
74 .num_banks = 7,
75 .banks = {
76 VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26),
77 VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28),
78 VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31),
79 VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19),
80 VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19),
81 VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23),
82 VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),
83 },
84};
85
86static struct vt8500_gpio_data wm8505_data = {
87 .num_banks = 10,
88 .banks = {
89 VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8),
90 VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32),
91 VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6),
92 VT8500_BANK(0x4C, 0x74, 0x9C, 0xC4, 16),
93 VT8500_BANK(0x50, 0x78, 0xA0, 0xC8, 25),
94 VT8500_BANK(0x54, 0x7C, 0xA4, 0xCC, 5),
95 VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5),
96 VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
97 VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
98 VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
99 },
100};
101
102/*
103 * No information about which bits are valid so we just make
104 * them all available until its figured out.
105 */
106static struct vt8500_gpio_data wm8650_data = {
107 .num_banks = 9,
108 .banks = {
109 VT8500_BANK(0x40, 0x80, 0xC0, 0x00, 32),
110 VT8500_BANK(0x44, 0x84, 0xC4, 0x04, 32),
111 VT8500_BANK(0x48, 0x88, 0xC8, 0x08, 32),
112 VT8500_BANK(0x4C, 0x8C, 0xCC, 0x0C, 32),
113 VT8500_BANK(0x50, 0x90, 0xD0, 0x10, 32),
114 VT8500_BANK(0x54, 0x94, 0xD4, 0x14, 32),
115 VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
116 VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
117 VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
118 },
119};
120
121struct vt8500_gpio_chip {
122 struct gpio_chip chip;
123
124 const struct vt8500_gpio_bank_regoffsets *regs;
125 void __iomem *base;
126};
127
128
129#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
130
131static int vt8500_gpio_request(struct gpio_chip *chip, unsigned offset)
132{
133 u32 val;
134 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
135
136 if (vt8500_chip->regs->en == NO_REG)
137 return 0;
138
139 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
140 val |= BIT(offset);
141 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
142
143 return 0;
144}
145
146static void vt8500_gpio_free(struct gpio_chip *chip, unsigned offset)
147{
148 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
149 u32 val;
150
151 if (vt8500_chip->regs->en == NO_REG)
152 return;
153
154 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
155 val &= ~BIT(offset);
156 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
157}
158
159static int vt8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
160{
161 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
162
163 u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
164 val &= ~BIT(offset);
165 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
166
167 return 0;
168}
169
170static int vt8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
171 int value)
172{
173 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
174
175 u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
176 val |= BIT(offset);
177 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
178
179 if (value) {
180 val = readl_relaxed(vt8500_chip->base +
181 vt8500_chip->regs->data_out);
182 val |= BIT(offset);
183 writel_relaxed(val, vt8500_chip->base +
184 vt8500_chip->regs->data_out);
185 }
186 return 0;
187}
188
189static int vt8500_gpio_get_value(struct gpio_chip *chip, unsigned offset)
190{
191 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
192
193 return (readl_relaxed(vt8500_chip->base + vt8500_chip->regs->data_in) >>
194 offset) & 1;
195}
196
197static void vt8500_gpio_set_value(struct gpio_chip *chip, unsigned offset,
198 int value)
199{
200 struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
201
202 u32 val = readl_relaxed(vt8500_chip->base +
203 vt8500_chip->regs->data_out);
204 if (value)
205 val |= BIT(offset);
206 else
207 val &= ~BIT(offset);
208
209 writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->data_out);
210}
211
212static int vt8500_of_xlate(struct gpio_chip *gc,
213 const struct of_phandle_args *gpiospec, u32 *flags)
214{
215 /* bank if specificed in gpiospec->args[0] */
216 if (flags)
217 *flags = gpiospec->args[2];
218
219 return gpiospec->args[1];
220}
221
222static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base,
223 const struct vt8500_gpio_data *data)
224{
225 struct vt8500_gpio_chip *vtchip;
226 struct gpio_chip *chip;
227 int i;
228 int pin_cnt = 0;
229
230 vtchip = devm_kzalloc(&pdev->dev,
231 sizeof(struct vt8500_gpio_chip) * data->num_banks,
232 GFP_KERNEL);
233 if (!vtchip) {
234 pr_err("%s: failed to allocate chip memory\n", __func__);
235 return -ENOMEM;
236 }
237
238 for (i = 0; i < data->num_banks; i++) {
239 vtchip[i].base = base;
240 vtchip[i].regs = &data->banks[i];
241
242 chip = &vtchip[i].chip;
243
244 chip->of_xlate = vt8500_of_xlate;
245 chip->of_gpio_n_cells = 3;
246 chip->of_node = pdev->dev.of_node;
247
248 chip->request = vt8500_gpio_request;
249 chip->free = vt8500_gpio_free;
250 chip->direction_input = vt8500_gpio_direction_input;
251 chip->direction_output = vt8500_gpio_direction_output;
252 chip->get = vt8500_gpio_get_value;
253 chip->set = vt8500_gpio_set_value;
254 chip->can_sleep = 0;
255 chip->base = pin_cnt;
256 chip->ngpio = data->banks[i].ngpio;
257
258 pin_cnt += data->banks[i].ngpio;
259
260 gpiochip_add(chip);
261 }
262 return 0;
263}
264
265static struct of_device_id vt8500_gpio_dt_ids[] = {
266 { .compatible = "via,vt8500-gpio", .data = &vt8500_data, },
267 { .compatible = "wm,wm8505-gpio", .data = &wm8505_data, },
268 { .compatible = "wm,wm8650-gpio", .data = &wm8650_data, },
269 { /* Sentinel */ },
270};
271
272static int __devinit vt8500_gpio_probe(struct platform_device *pdev)
273{
274 void __iomem *gpio_base;
275 struct device_node *np;
276 const struct of_device_id *of_id =
277 of_match_device(vt8500_gpio_dt_ids, &pdev->dev);
278
279 if (!of_id) {
280 dev_err(&pdev->dev, "Failed to find gpio controller\n");
281 return -ENODEV;
282 }
283
284 np = pdev->dev.of_node;
285 if (!np) {
286 dev_err(&pdev->dev, "Missing GPIO description in devicetree\n");
287 return -EFAULT;
288 }
289
290 gpio_base = of_iomap(np, 0);
291 if (!gpio_base) {
292 dev_err(&pdev->dev, "Unable to map GPIO registers\n");
293 of_node_put(np);
294 return -ENOMEM;
295 }
296
297 vt8500_add_chips(pdev, gpio_base, of_id->data);
298
299 return 0;
300}
301
302static struct platform_driver vt8500_gpio_driver = {
303 .probe = vt8500_gpio_probe,
304 .driver = {
305 .name = "vt8500-gpio",
306 .owner = THIS_MODULE,
307 .of_match_table = vt8500_gpio_dt_ids,
308 },
309};
310
311module_platform_driver(vt8500_gpio_driver);
312
313MODULE_DESCRIPTION("VT8500 GPIO Driver");
314MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
315MODULE_LICENSE("GPL v2");
316MODULE_DEVICE_TABLE(of, vt8500_gpio_dt_ids);
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index 9e94fb147c26..07bf19364a74 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -23,6 +23,7 @@
23#include <linux/bcd.h> 23#include <linux/bcd.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/of.h>
26 27
27/* 28/*
28 * Register definitions 29 * Register definitions
@@ -302,12 +303,18 @@ static int __devexit vt8500_rtc_remove(struct platform_device *pdev)
302 return 0; 303 return 0;
303} 304}
304 305
306static const struct of_device_id wmt_dt_ids[] = {
307 { .compatible = "via,vt8500-rtc", },
308 {}
309};
310
305static struct platform_driver vt8500_rtc_driver = { 311static struct platform_driver vt8500_rtc_driver = {
306 .probe = vt8500_rtc_probe, 312 .probe = vt8500_rtc_probe,
307 .remove = __devexit_p(vt8500_rtc_remove), 313 .remove = __devexit_p(vt8500_rtc_remove),
308 .driver = { 314 .driver = {
309 .name = "vt8500-rtc", 315 .name = "vt8500-rtc",
310 .owner = THIS_MODULE, 316 .owner = THIS_MODULE,
317 .of_match_table = of_match_ptr(wmt_dt_ids),
311 }, 318 },
312}; 319};
313 320
@@ -315,5 +322,5 @@ module_platform_driver(vt8500_rtc_driver);
315 322
316MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); 323MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
317MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)"); 324MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)");
318MODULE_LICENSE("GPL"); 325MODULE_LICENSE("GPL v2");
319MODULE_ALIAS("platform:vt8500-rtc"); 326MODULE_ALIAS("platform:vt8500-rtc");
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 2be006fb3da0..205d4cf4a063 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -34,6 +34,7 @@
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <linux/clk.h> 35#include <linux/clk.h>
36#include <linux/platform_device.h> 36#include <linux/platform_device.h>
37#include <linux/of.h>
37 38
38/* 39/*
39 * UART Register offsets 40 * UART Register offsets
@@ -76,6 +77,8 @@
76#define RX_FIFO_INTS (RXFAF | RXFF | RXOVER | PER | FER | RXTOUT) 77#define RX_FIFO_INTS (RXFAF | RXFF | RXOVER | PER | FER | RXTOUT)
77#define TX_FIFO_INTS (TXFAE | TXFE | TXUDR) 78#define TX_FIFO_INTS (TXFAE | TXFE | TXUDR)
78 79
80#define VT8500_MAX_PORTS 6
81
79struct vt8500_port { 82struct vt8500_port {
80 struct uart_port uart; 83 struct uart_port uart;
81 char name[16]; 84 char name[16];
@@ -83,6 +86,13 @@ struct vt8500_port {
83 unsigned int ier; 86 unsigned int ier;
84}; 87};
85 88
89/*
90 * we use this variable to keep track of which ports
91 * have been allocated as we can't use pdev->id in
92 * devicetree
93 */
94static unsigned long vt8500_ports_in_use;
95
86static inline void vt8500_write(struct uart_port *port, unsigned int val, 96static inline void vt8500_write(struct uart_port *port, unsigned int val,
87 unsigned int off) 97 unsigned int off)
88{ 98{
@@ -431,7 +441,7 @@ static int vt8500_verify_port(struct uart_port *port,
431 return 0; 441 return 0;
432} 442}
433 443
434static struct vt8500_port *vt8500_uart_ports[4]; 444static struct vt8500_port *vt8500_uart_ports[VT8500_MAX_PORTS];
435static struct uart_driver vt8500_uart_driver; 445static struct uart_driver vt8500_uart_driver;
436 446
437#ifdef CONFIG_SERIAL_VT8500_CONSOLE 447#ifdef CONFIG_SERIAL_VT8500_CONSOLE
@@ -548,7 +558,9 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
548{ 558{
549 struct vt8500_port *vt8500_port; 559 struct vt8500_port *vt8500_port;
550 struct resource *mmres, *irqres; 560 struct resource *mmres, *irqres;
561 struct device_node *np = pdev->dev.of_node;
551 int ret; 562 int ret;
563 int port;
552 564
553 mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); 565 mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
554 irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 566 irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -559,16 +571,46 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
559 if (!vt8500_port) 571 if (!vt8500_port)
560 return -ENOMEM; 572 return -ENOMEM;
561 573
574 if (np)
575 port = of_alias_get_id(np, "serial");
576 if (port > VT8500_MAX_PORTS)
577 port = -1;
578 else
579 port = -1;
580
581 if (port < 0) {
582 /* calculate the port id */
583 port = find_first_zero_bit(&vt8500_ports_in_use,
584 sizeof(vt8500_ports_in_use));
585 }
586
587 if (port > VT8500_MAX_PORTS)
588 return -ENODEV;
589
590 /* reserve the port id */
591 if (test_and_set_bit(port, &vt8500_ports_in_use)) {
592 /* port already in use - shouldn't really happen */
593 return -EBUSY;
594 }
595
562 vt8500_port->uart.type = PORT_VT8500; 596 vt8500_port->uart.type = PORT_VT8500;
563 vt8500_port->uart.iotype = UPIO_MEM; 597 vt8500_port->uart.iotype = UPIO_MEM;
564 vt8500_port->uart.mapbase = mmres->start; 598 vt8500_port->uart.mapbase = mmres->start;
565 vt8500_port->uart.irq = irqres->start; 599 vt8500_port->uart.irq = irqres->start;
566 vt8500_port->uart.fifosize = 16; 600 vt8500_port->uart.fifosize = 16;
567 vt8500_port->uart.ops = &vt8500_uart_pops; 601 vt8500_port->uart.ops = &vt8500_uart_pops;
568 vt8500_port->uart.line = pdev->id; 602 vt8500_port->uart.line = port;
569 vt8500_port->uart.dev = &pdev->dev; 603 vt8500_port->uart.dev = &pdev->dev;
570 vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; 604 vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
571 vt8500_port->uart.uartclk = 24000000; 605
606 vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0);
607 if (vt8500_port->clk) {
608 vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk);
609 } else {
610 /* use the default of 24Mhz if not specified and warn */
611 pr_warn("%s: serial clock source not specified\n", __func__);
612 vt8500_port->uart.uartclk = 24000000;
613 }
572 614
573 snprintf(vt8500_port->name, sizeof(vt8500_port->name), 615 snprintf(vt8500_port->name, sizeof(vt8500_port->name),
574 "VT8500 UART%d", pdev->id); 616 "VT8500 UART%d", pdev->id);
@@ -579,7 +621,7 @@ static int __devinit vt8500_serial_probe(struct platform_device *pdev)
579 goto err; 621 goto err;
580 } 622 }
581 623
582 vt8500_uart_ports[pdev->id] = vt8500_port; 624 vt8500_uart_ports[port] = vt8500_port;
583 625
584 uart_add_one_port(&vt8500_uart_driver, &vt8500_port->uart); 626 uart_add_one_port(&vt8500_uart_driver, &vt8500_port->uart);
585 627
@@ -603,12 +645,18 @@ static int __devexit vt8500_serial_remove(struct platform_device *pdev)
603 return 0; 645 return 0;
604} 646}
605 647
648static const struct of_device_id wmt_dt_ids[] = {
649 { .compatible = "via,vt8500-uart", },
650 {}
651};
652
606static struct platform_driver vt8500_platform_driver = { 653static struct platform_driver vt8500_platform_driver = {
607 .probe = vt8500_serial_probe, 654 .probe = vt8500_serial_probe,
608 .remove = __devexit_p(vt8500_serial_remove), 655 .remove = __devexit_p(vt8500_serial_remove),
609 .driver = { 656 .driver = {
610 .name = "vt8500_serial", 657 .name = "vt8500_serial",
611 .owner = THIS_MODULE, 658 .owner = THIS_MODULE,
659 .of_match_table = of_match_ptr(wmt_dt_ids),
612 }, 660 },
613}; 661};
614 662
@@ -642,4 +690,4 @@ module_exit(vt8500_serial_exit);
642 690
643MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); 691MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
644MODULE_DESCRIPTION("Driver for vt8500 serial device"); 692MODULE_DESCRIPTION("Driver for vt8500 serial device");
645MODULE_LICENSE("GPL"); 693MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 0217f7415ef5..b66d951b8e32 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1788,7 +1788,7 @@ config FB_AU1200
1788 1788
1789config FB_VT8500 1789config FB_VT8500
1790 bool "VT8500 LCD Driver" 1790 bool "VT8500 LCD Driver"
1791 depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_VT8500 1791 depends on (FB = y) && ARM && ARCH_VT8500
1792 select FB_WMT_GE_ROPS 1792 select FB_WMT_GE_ROPS
1793 select FB_SYS_IMAGEBLIT 1793 select FB_SYS_IMAGEBLIT
1794 help 1794 help
@@ -1797,11 +1797,11 @@ config FB_VT8500
1797 1797
1798config FB_WM8505 1798config FB_WM8505
1799 bool "WM8505 frame buffer support" 1799 bool "WM8505 frame buffer support"
1800 depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_WM8505 1800 depends on (FB = y) && ARM && ARCH_VT8500
1801 select FB_WMT_GE_ROPS 1801 select FB_WMT_GE_ROPS
1802 select FB_SYS_IMAGEBLIT 1802 select FB_SYS_IMAGEBLIT
1803 help 1803 help
1804 This is the framebuffer driver for WonderMedia WM8505 1804 This is the framebuffer driver for WonderMedia WM8505/WM8650
1805 integrated LCD controller. 1805 integrated LCD controller.
1806 1806
1807source "drivers/video/geode/Kconfig" 1807source "drivers/video/geode/Kconfig"
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
index 2a5fe6ede845..d24595cd0c9b 100644
--- a/drivers/video/vt8500lcdfb.c
+++ b/drivers/video/vt8500lcdfb.c
@@ -35,6 +35,13 @@
35#include "vt8500lcdfb.h" 35#include "vt8500lcdfb.h"
36#include "wmt_ge_rops.h" 36#include "wmt_ge_rops.h"
37 37
38#ifdef CONFIG_OF
39#include <linux/of.h>
40#include <linux/of_fdt.h>
41#include <linux/memblock.h>
42#endif
43
44
38#define to_vt8500lcd_info(__info) container_of(__info, \ 45#define to_vt8500lcd_info(__info) container_of(__info, \
39 struct vt8500lcd_info, fb) 46 struct vt8500lcd_info, fb)
40 47
@@ -270,15 +277,21 @@ static int __devinit vt8500lcd_probe(struct platform_device *pdev)
270{ 277{
271 struct vt8500lcd_info *fbi; 278 struct vt8500lcd_info *fbi;
272 struct resource *res; 279 struct resource *res;
273 struct vt8500fb_platform_data *pdata = pdev->dev.platform_data;
274 void *addr; 280 void *addr;
275 int irq, ret; 281 int irq, ret;
276 282
283 struct fb_videomode of_mode;
284 struct device_node *np;
285 u32 bpp;
286 dma_addr_t fb_mem_phys;
287 unsigned long fb_mem_len;
288 void *fb_mem_virt;
289
277 ret = -ENOMEM; 290 ret = -ENOMEM;
278 fbi = NULL; 291 fbi = NULL;
279 292
280 fbi = kzalloc(sizeof(struct vt8500lcd_info) + sizeof(u32) * 16, 293 fbi = devm_kzalloc(&pdev->dev, sizeof(struct vt8500lcd_info)
281 GFP_KERNEL); 294 + sizeof(u32) * 16, GFP_KERNEL);
282 if (!fbi) { 295 if (!fbi) {
283 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); 296 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
284 ret = -ENOMEM; 297 ret = -ENOMEM;
@@ -333,9 +346,45 @@ static int __devinit vt8500lcd_probe(struct platform_device *pdev)
333 goto failed_free_res; 346 goto failed_free_res;
334 } 347 }
335 348
336 fbi->fb.fix.smem_start = pdata->video_mem_phys; 349 np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
337 fbi->fb.fix.smem_len = pdata->video_mem_len; 350 if (!np) {
338 fbi->fb.screen_base = pdata->video_mem_virt; 351 pr_err("%s: No display description in Device Tree\n", __func__);
352 ret = -EINVAL;
353 goto failed_free_res;
354 }
355
356 /*
357 * This code is copied from Sascha Hauer's of_videomode helper
358 * and can be replaced with a call to the helper once mainlined
359 */
360 ret = 0;
361 ret |= of_property_read_u32(np, "hactive", &of_mode.xres);
362 ret |= of_property_read_u32(np, "vactive", &of_mode.yres);
363 ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin);
364 ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
365 ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
366 ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
367 ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
368 ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
369 ret |= of_property_read_u32(np, "bpp", &bpp);
370 if (ret) {
371 pr_err("%s: Unable to read display properties\n", __func__);
372 goto failed_free_res;
373 }
374 of_mode.vmode = FB_VMODE_NONINTERLACED;
375
376 /* try allocating the framebuffer */
377 fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
378 fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
379 GFP_KERNEL);
380 if (!fb_mem_virt) {
381 pr_err("%s: Failed to allocate framebuffer\n", __func__);
382 return -ENOMEM;
383 };
384
385 fbi->fb.fix.smem_start = fb_mem_phys;
386 fbi->fb.fix.smem_len = fb_mem_len;
387 fbi->fb.screen_base = fb_mem_virt;
339 388
340 fbi->palette_size = PAGE_ALIGN(512); 389 fbi->palette_size = PAGE_ALIGN(512);
341 fbi->palette_cpu = dma_alloc_coherent(&pdev->dev, 390 fbi->palette_cpu = dma_alloc_coherent(&pdev->dev,
@@ -370,10 +419,11 @@ static int __devinit vt8500lcd_probe(struct platform_device *pdev)
370 goto failed_free_irq; 419 goto failed_free_irq;
371 } 420 }
372 421
373 fb_videomode_to_var(&fbi->fb.var, &pdata->mode); 422 fb_videomode_to_var(&fbi->fb.var, &of_mode);
374 fbi->fb.var.bits_per_pixel = pdata->bpp; 423
375 fbi->fb.var.xres_virtual = pdata->xres_virtual; 424 fbi->fb.var.xres_virtual = of_mode.xres;
376 fbi->fb.var.yres_virtual = pdata->yres_virtual; 425 fbi->fb.var.yres_virtual = of_mode.yres * 2;
426 fbi->fb.var.bits_per_pixel = bpp;
377 427
378 ret = vt8500lcd_set_par(&fbi->fb); 428 ret = vt8500lcd_set_par(&fbi->fb);
379 if (ret) { 429 if (ret) {
@@ -448,12 +498,18 @@ static int __devexit vt8500lcd_remove(struct platform_device *pdev)
448 return 0; 498 return 0;
449} 499}
450 500
501static const struct of_device_id via_dt_ids[] = {
502 { .compatible = "via,vt8500-fb", },
503 {}
504};
505
451static struct platform_driver vt8500lcd_driver = { 506static struct platform_driver vt8500lcd_driver = {
452 .probe = vt8500lcd_probe, 507 .probe = vt8500lcd_probe,
453 .remove = __devexit_p(vt8500lcd_remove), 508 .remove = __devexit_p(vt8500lcd_remove),
454 .driver = { 509 .driver = {
455 .owner = THIS_MODULE, 510 .owner = THIS_MODULE,
456 .name = "vt8500-lcd", 511 .name = "vt8500-lcd",
512 .of_match_table = of_match_ptr(via_dt_ids),
457 }, 513 },
458}; 514};
459 515
@@ -461,4 +517,5 @@ module_platform_driver(vt8500lcd_driver);
461 517
462MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); 518MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
463MODULE_DESCRIPTION("LCD controller driver for VIA VT8500"); 519MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
464MODULE_LICENSE("GPL"); 520MODULE_LICENSE("GPL v2");
521MODULE_DEVICE_TABLE(of, via_dt_ids);
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
index c8703bd61b74..ec4742442103 100644
--- a/drivers/video/wm8505fb.c
+++ b/drivers/video/wm8505fb.c
@@ -28,6 +28,9 @@
28#include <linux/dma-mapping.h> 28#include <linux/dma-mapping.h>
29#include <linux/platform_device.h> 29#include <linux/platform_device.h>
30#include <linux/wait.h> 30#include <linux/wait.h>
31#include <linux/of.h>
32#include <linux/of_fdt.h>
33#include <linux/memblock.h>
31 34
32#include <mach/vt8500fb.h> 35#include <mach/vt8500fb.h>
33 36
@@ -59,8 +62,12 @@ static int wm8505fb_init_hw(struct fb_info *info)
59 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR); 62 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR);
60 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1); 63 writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1);
61 64
62 /* Set in-memory picture format to RGB 32bpp */ 65 /*
63 writel(0x1c, fbi->regbase + WMT_GOVR_COLORSPACE); 66 * Set in-memory picture format to RGB
67 * 0x31C sets the correct color mode (RGB565) for WM8650
68 * Bit 8+9 (0x300) are ignored on WM8505 as reserved
69 */
70 writel(0x31c, fbi->regbase + WMT_GOVR_COLORSPACE);
64 writel(1, fbi->regbase + WMT_GOVR_COLORSPACE1); 71 writel(1, fbi->regbase + WMT_GOVR_COLORSPACE1);
65 72
66 /* Virtual buffer size */ 73 /* Virtual buffer size */
@@ -127,6 +134,18 @@ static int wm8505fb_set_par(struct fb_info *info)
127 info->var.blue.msb_right = 0; 134 info->var.blue.msb_right = 0;
128 info->fix.visual = FB_VISUAL_TRUECOLOR; 135 info->fix.visual = FB_VISUAL_TRUECOLOR;
129 info->fix.line_length = info->var.xres_virtual << 2; 136 info->fix.line_length = info->var.xres_virtual << 2;
137 } else if (info->var.bits_per_pixel == 16) {
138 info->var.red.offset = 11;
139 info->var.red.length = 5;
140 info->var.red.msb_right = 0;
141 info->var.green.offset = 5;
142 info->var.green.length = 6;
143 info->var.green.msb_right = 0;
144 info->var.blue.offset = 0;
145 info->var.blue.length = 5;
146 info->var.blue.msb_right = 0;
147 info->fix.visual = FB_VISUAL_TRUECOLOR;
148 info->fix.line_length = info->var.xres_virtual << 1;
130 } 149 }
131 150
132 wm8505fb_set_timing(info); 151 wm8505fb_set_timing(info);
@@ -246,16 +265,20 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev)
246 struct wm8505fb_info *fbi; 265 struct wm8505fb_info *fbi;
247 struct resource *res; 266 struct resource *res;
248 void *addr; 267 void *addr;
249 struct vt8500fb_platform_data *pdata;
250 int ret; 268 int ret;
251 269
252 pdata = pdev->dev.platform_data; 270 struct fb_videomode of_mode;
271 struct device_node *np;
272 u32 bpp;
273 dma_addr_t fb_mem_phys;
274 unsigned long fb_mem_len;
275 void *fb_mem_virt;
253 276
254 ret = -ENOMEM; 277 ret = -ENOMEM;
255 fbi = NULL; 278 fbi = NULL;
256 279
257 fbi = kzalloc(sizeof(struct wm8505fb_info) + sizeof(u32) * 16, 280 fbi = devm_kzalloc(&pdev->dev, sizeof(struct wm8505fb_info) +
258 GFP_KERNEL); 281 sizeof(u32) * 16, GFP_KERNEL);
259 if (!fbi) { 282 if (!fbi) {
260 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n"); 283 dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
261 ret = -ENOMEM; 284 ret = -ENOMEM;
@@ -305,21 +328,58 @@ static int __devinit wm8505fb_probe(struct platform_device *pdev)
305 goto failed_free_res; 328 goto failed_free_res;
306 } 329 }
307 330
308 fb_videomode_to_var(&fbi->fb.var, &pdata->mode); 331 np = of_parse_phandle(pdev->dev.of_node, "default-mode", 0);
332 if (!np) {
333 pr_err("%s: No display description in Device Tree\n", __func__);
334 ret = -EINVAL;
335 goto failed_free_res;
336 }
337
338 /*
339 * This code is copied from Sascha Hauer's of_videomode helper
340 * and can be replaced with a call to the helper once mainlined
341 */
342 ret = 0;
343 ret |= of_property_read_u32(np, "hactive", &of_mode.xres);
344 ret |= of_property_read_u32(np, "vactive", &of_mode.yres);
345 ret |= of_property_read_u32(np, "hback-porch", &of_mode.left_margin);
346 ret |= of_property_read_u32(np, "hfront-porch", &of_mode.right_margin);
347 ret |= of_property_read_u32(np, "hsync-len", &of_mode.hsync_len);
348 ret |= of_property_read_u32(np, "vback-porch", &of_mode.upper_margin);
349 ret |= of_property_read_u32(np, "vfront-porch", &of_mode.lower_margin);
350 ret |= of_property_read_u32(np, "vsync-len", &of_mode.vsync_len);
351 ret |= of_property_read_u32(np, "bpp", &bpp);
352 if (ret) {
353 pr_err("%s: Unable to read display properties\n", __func__);
354 goto failed_free_res;
355 }
356
357 of_mode.vmode = FB_VMODE_NONINTERLACED;
358 fb_videomode_to_var(&fbi->fb.var, &of_mode);
309 359
310 fbi->fb.var.nonstd = 0; 360 fbi->fb.var.nonstd = 0;
311 fbi->fb.var.activate = FB_ACTIVATE_NOW; 361 fbi->fb.var.activate = FB_ACTIVATE_NOW;
312 362
313 fbi->fb.var.height = -1; 363 fbi->fb.var.height = -1;
314 fbi->fb.var.width = -1; 364 fbi->fb.var.width = -1;
315 fbi->fb.var.xres_virtual = pdata->xres_virtual;
316 fbi->fb.var.yres_virtual = pdata->yres_virtual;
317 fbi->fb.var.bits_per_pixel = pdata->bpp;
318 365
319 fbi->fb.fix.smem_start = pdata->video_mem_phys; 366 /* try allocating the framebuffer */
320 fbi->fb.fix.smem_len = pdata->video_mem_len; 367 fb_mem_len = of_mode.xres * of_mode.yres * 2 * (bpp / 8);
321 fbi->fb.screen_base = pdata->video_mem_virt; 368 fb_mem_virt = dma_alloc_coherent(&pdev->dev, fb_mem_len, &fb_mem_phys,
322 fbi->fb.screen_size = pdata->video_mem_len; 369 GFP_KERNEL);
370 if (!fb_mem_virt) {
371 pr_err("%s: Failed to allocate framebuffer\n", __func__);
372 return -ENOMEM;
373 };
374
375 fbi->fb.var.xres_virtual = of_mode.xres;
376 fbi->fb.var.yres_virtual = of_mode.yres * 2;
377 fbi->fb.var.bits_per_pixel = bpp;
378
379 fbi->fb.fix.smem_start = fb_mem_phys;
380 fbi->fb.fix.smem_len = fb_mem_len;
381 fbi->fb.screen_base = fb_mem_virt;
382 fbi->fb.screen_size = fb_mem_len;
323 383
324 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) { 384 if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
325 dev_err(&pdev->dev, "Failed to allocate color map\n"); 385 dev_err(&pdev->dev, "Failed to allocate color map\n");
@@ -395,12 +455,18 @@ static int __devexit wm8505fb_remove(struct platform_device *pdev)
395 return 0; 455 return 0;
396} 456}
397 457
458static const struct of_device_id wmt_dt_ids[] = {
459 { .compatible = "wm,wm8505-fb", },
460 {}
461};
462
398static struct platform_driver wm8505fb_driver = { 463static struct platform_driver wm8505fb_driver = {
399 .probe = wm8505fb_probe, 464 .probe = wm8505fb_probe,
400 .remove = __devexit_p(wm8505fb_remove), 465 .remove = __devexit_p(wm8505fb_remove),
401 .driver = { 466 .driver = {
402 .owner = THIS_MODULE, 467 .owner = THIS_MODULE,
403 .name = DRIVER_NAME, 468 .name = DRIVER_NAME,
469 .of_match_table = of_match_ptr(wmt_dt_ids),
404 }, 470 },
405}; 471};
406 472
@@ -408,4 +474,5 @@ module_platform_driver(wm8505fb_driver);
408 474
409MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>"); 475MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>");
410MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505"); 476MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
411MODULE_LICENSE("GPL"); 477MODULE_LICENSE("GPL v2");
478MODULE_DEVICE_TABLE(of, wmt_dt_ids);
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
index 55be3865015b..ba025b4c7d09 100644
--- a/drivers/video/wmt_ge_rops.c
+++ b/drivers/video/wmt_ge_rops.c
@@ -158,12 +158,18 @@ static int __devexit wmt_ge_rops_remove(struct platform_device *pdev)
158 return 0; 158 return 0;
159} 159}
160 160
161static const struct of_device_id wmt_dt_ids[] = {
162 { .compatible = "wm,prizm-ge-rops", },
163 { /* sentinel */ }
164};
165
161static struct platform_driver wmt_ge_rops_driver = { 166static struct platform_driver wmt_ge_rops_driver = {
162 .probe = wmt_ge_rops_probe, 167 .probe = wmt_ge_rops_probe,
163 .remove = __devexit_p(wmt_ge_rops_remove), 168 .remove = __devexit_p(wmt_ge_rops_remove),
164 .driver = { 169 .driver = {
165 .owner = THIS_MODULE, 170 .owner = THIS_MODULE,
166 .name = "wmt_ge_rops", 171 .name = "wmt_ge_rops",
172 .of_match_table = of_match_ptr(wmt_dt_ids),
167 }, 173 },
168}; 174};
169 175
@@ -172,4 +178,5 @@ module_platform_driver(wmt_ge_rops_driver);
172MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com"); 178MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
173MODULE_DESCRIPTION("Accelerators for raster operations using " 179MODULE_DESCRIPTION("Accelerators for raster operations using "
174 "WonderMedia Graphics Engine"); 180 "WonderMedia Graphics Engine");
175MODULE_LICENSE("GPL"); 181MODULE_LICENSE("GPL v2");
182MODULE_DEVICE_TABLE(of, wmt_dt_ids);