diff options
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 @@ | |||
| 1 | VIA/Wondermedia VT8500 Platforms Device Tree Bindings | ||
| 2 | --------------------------------------- | ||
| 3 | |||
| 4 | Boards with the VIA VT8500 SoC shall have the following properties: | ||
| 5 | Required root node property: | ||
| 6 | compatible = "via,vt8500"; | ||
| 7 | |||
| 8 | Boards with the Wondermedia WM8505 SoC shall have the following properties: | ||
| 9 | Required root node property: | ||
| 10 | compatible = "wm,wm8505"; | ||
| 11 | |||
| 12 | Boards with the Wondermedia WM8650 SoC shall have the following properties: | ||
| 13 | Required root node property: | ||
| 14 | compatible = "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 @@ | |||
| 1 | VIA/Wondermedia VT8500 Interrupt Controller | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : "via,vt8500-intc" | ||
| 6 | - reg : Should contain 1 register ranges(address and length) | ||
| 7 | - #interrupt-cells : should be <1> | ||
| 8 | |||
| 9 | Example: | ||
| 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 @@ | |||
| 1 | VIA/Wondermedia VT8500 Power Management Controller | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : "via,vt8500-pmc" | ||
| 6 | - reg : Should contain 1 register ranges(address and length) | ||
| 7 | |||
| 8 | Example: | ||
| 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 @@ | |||
| 1 | VIA/Wondermedia VT8500 Timer | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : "via,vt8500-timer" | ||
| 6 | - reg : Should contain 1 register ranges(address and length) | ||
| 7 | - interrupts : interrupt for the timer | ||
| 8 | |||
| 9 | Example: | ||
| 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 @@ | |||
| 1 | Device Tree Clock bindings for arch-vt8500 | ||
| 2 | |||
| 3 | This binding uses the common clock binding[1]. | ||
| 4 | |||
| 5 | [1] Documentation/devicetree/bindings/clock/clock-bindings.txt | ||
| 6 | |||
| 7 | Required 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 | |||
| 13 | Required 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 | |||
| 19 | Required 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 | |||
| 25 | Device Clocks | ||
| 26 | |||
| 27 | Device clocks are required to have one or both of the following sets of | ||
| 28 | properties: | ||
| 29 | |||
| 30 | |||
| 31 | Gated device clocks: | ||
| 32 | |||
| 33 | Required 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 | |||
| 39 | Divisor device clocks: | ||
| 40 | |||
| 41 | Required property: | ||
| 42 | - divisor-reg : shall be the register offset from PMC base for the divisor | ||
| 43 | register. | ||
| 44 | Optional property: | ||
| 45 | - divisor-mask : shall be the mask for the divisor register. Defaults to 0x1f | ||
| 46 | if not specified. | ||
| 47 | |||
| 48 | |||
| 49 | For example: | ||
| 50 | |||
| 51 | ref25: ref25M { | ||
| 52 | #clock-cells = <0>; | ||
| 53 | compatible = "fixed-clock"; | ||
| 54 | clock-frequency = <25000000>; | ||
| 55 | }; | ||
| 56 | |||
| 57 | plla: plla { | ||
| 58 | #clock-cells = <0>; | ||
| 59 | compatible = "wm,wm8650-pll-clock"; | ||
| 60 | clocks = <&ref25>; | ||
| 61 | reg = <0x200>; | ||
| 62 | }; | ||
| 63 | |||
| 64 | sdhc: 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 @@ | |||
| 1 | VIA/Wondermedia VT8500 GPIO Controller | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required 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 | |||
| 13 | Example: | ||
| 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 @@ | |||
| 1 | VIA/Wondermedia VT8500 Realtime Clock Controller | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : "via,vt8500-rtc" | ||
| 6 | - reg : Should contain 1 register ranges(address and length) | ||
| 7 | - interrupts : alarm interrupt | ||
| 8 | |||
| 9 | Example: | ||
| 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 @@ | |||
| 1 | VIA/Wondermedia VT8500 UART Controller | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required 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 | |||
| 10 | Example: | ||
| 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 @@ | |||
| 1 | Generic Platform UHCI Controller | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : "platform-uhci" | ||
| 6 | - reg : Should contain 1 register ranges(address and length) | ||
| 7 | - interrupts : UHCI controller interrupt | ||
| 8 | |||
| 9 | Example: | ||
| 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 @@ | |||
| 1 | VIA/Wondermedia VT8500 EHCI Controller | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : "via,vt8500-ehci" | ||
| 6 | - reg : Should contain 1 register ranges(address and length) | ||
| 7 | - interrupts : ehci controller interrupt | ||
| 8 | |||
| 9 | Example: | ||
| 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. | |||
| 47 | st STMicroelectronics | 47 | st STMicroelectronics |
| 48 | stericsson ST-Ericsson | 48 | stericsson ST-Ericsson |
| 49 | ti Texas Instruments | 49 | ti Texas Instruments |
| 50 | via VIA Technologies, Inc. | ||
| 50 | wlf Wolfson Microelectronics | 51 | wlf Wolfson Microelectronics |
| 52 | wm Wondermedia Technologies, Inc. | ||
| 51 | xlnx Xilinx | 53 | xlnx 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 @@ | |||
| 1 | VIA VT8500 Framebuffer | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required 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 | |||
| 10 | Required 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 | |||
| 16 | Example: | ||
| 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 | |||
| 26 | VIA VT8500 Display | ||
| 27 | ----------------------------------------------------- | ||
| 28 | Required 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 | |||
| 39 | Optional 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 | |||
| 46 | Example: | ||
| 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 @@ | |||
| 1 | VIA/Wondermedia Graphics Engine Controller | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required properties: | ||
| 5 | - compatible : "wm,prizm-ge-rops" | ||
| 6 | - reg : Should contain 1 register ranges(address and length) | ||
| 7 | |||
| 8 | Example: | ||
| 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 @@ | |||
| 1 | Wondermedia WM8505 Framebuffer | ||
| 2 | ----------------------------------------------------- | ||
| 3 | |||
| 4 | Required 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 | |||
| 9 | Required 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 | |||
| 16 | Example: | ||
| 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" | |||
| 1128 | source "arch/arm/mach-vexpress/Kconfig" | 1132 | source "arch/arm/mach-vexpress/Kconfig" |
| 1129 | source "arch/arm/plat-versatile/Kconfig" | 1133 | source "arch/arm/plat-versatile/Kconfig" |
| 1130 | 1134 | ||
| 1131 | source "arch/arm/mach-vt8500/Kconfig" | ||
| 1132 | |||
| 1133 | source "arch/arm/mach-w90x900/Kconfig" | 1135 | source "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 @@ | |||
| 1 | if ARCH_VT8500 | ||
| 2 | |||
| 3 | config VTWM_VERSION_VT8500 | ||
| 4 | bool | ||
| 5 | |||
| 6 | config VTWM_VERSION_WM8505 | ||
| 7 | bool | ||
| 8 | |||
| 9 | config 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 | |||
| 19 | config 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 | |||
| 29 | comment "LCD panel size" | ||
| 30 | |||
| 31 | config 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 | |||
| 43 | config 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 | |||
| 53 | config 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 | |||
| 63 | config 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 | |||
| 73 | endif | ||
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 @@ | |||
| 1 | obj-y += devices.o gpio.o irq.o timer.o restart.o | obj-$(CONFIG_ARCH_VT8500) += irq.o timer.o vt8500.o | |
| 2 | |||
| 3 | obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o | ||
| 4 | obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o | ||
| 5 | |||
| 6 | obj-$(CONFIG_MACH_BV07) += bv07.o | ||
| 7 | obj-$(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 | |||
| 30 | static void __iomem *pmc_hiber; | ||
| 31 | |||
| 32 | static 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 | |||
| 42 | static 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 | |||
| 49 | void __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 | |||
| 72 | MACHINE_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, | ||
| 80 | MACHINE_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 | |||
| 21 | void __init vt8500_timer_init(void); | ||
| 22 | int __init vt8500_irq_init(struct device_node *node, | ||
| 23 | struct device_node *parent); | ||
| 24 | |||
| 25 | /* defined in drivers/clk/clk-vt8500.c */ | ||
| 26 | void __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 | |||
| 23 | void __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 | |||
| 63 | static 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 | |||
| 85 | void __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 | |||
| 23 | void __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 | |||
| 70 | static 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 | |||
| 93 | void __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 */ | ||
| 31 | unsigned long wmt_ic_base __initdata; | ||
| 32 | unsigned long wmt_sic_base __initdata; | ||
| 33 | unsigned long wmt_gpio_base __initdata; | ||
| 34 | unsigned long wmt_pmc_base __initdata; | ||
| 35 | unsigned long wmt_i8042_base __initdata; | ||
| 36 | |||
| 37 | int wmt_nr_irqs __initdata; | ||
| 38 | int wmt_timer_irq __initdata; | ||
| 39 | int wmt_gpio_ext_irq[8] __initdata; | ||
| 40 | |||
| 41 | /* Should remain accessible after init. | ||
| 42 | * i8042 driver desperately calls for attention... | ||
| 43 | */ | ||
| 44 | int wmt_i8042_kbd_irq; | ||
| 45 | int wmt_i8042_aux_irq; | ||
| 46 | |||
| 47 | static u64 fb_dma_mask = DMA_BIT_MASK(32); | ||
| 48 | |||
| 49 | struct 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 | |||
| 58 | struct platform_device vt8500_device_wm8505_fb = { | ||
| 59 | .name = "wm8505-fb", | ||
| 60 | .id = 0, | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* Smallest to largest */ | ||
| 64 | static 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 | |||
| 139 | static int current_panel_idx __initdata = ARRAY_SIZE(panels) - 1; | ||
| 140 | |||
| 141 | static 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 | |||
| 154 | early_param("panel", panel_setup); | ||
| 155 | |||
| 156 | static 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 | |||
| 166 | struct platform_device vt8500_device_uart0 = { | ||
| 167 | .name = "vt8500_serial", | ||
| 168 | .id = 0, | ||
| 169 | }; | ||
| 170 | |||
| 171 | struct platform_device vt8500_device_uart1 = { | ||
| 172 | .name = "vt8500_serial", | ||
| 173 | .id = 1, | ||
| 174 | }; | ||
| 175 | |||
| 176 | struct platform_device vt8500_device_uart2 = { | ||
| 177 | .name = "vt8500_serial", | ||
| 178 | .id = 2, | ||
| 179 | }; | ||
| 180 | |||
| 181 | struct platform_device vt8500_device_uart3 = { | ||
| 182 | .name = "vt8500_serial", | ||
| 183 | .id = 3, | ||
| 184 | }; | ||
| 185 | |||
| 186 | struct platform_device vt8500_device_uart4 = { | ||
| 187 | .name = "vt8500_serial", | ||
| 188 | .id = 4, | ||
| 189 | }; | ||
| 190 | |||
| 191 | struct platform_device vt8500_device_uart5 = { | ||
| 192 | .name = "vt8500_serial", | ||
| 193 | .id = 5, | ||
| 194 | }; | ||
| 195 | |||
| 196 | static u64 ehci_dma_mask = DMA_BIT_MASK(32); | ||
| 197 | |||
| 198 | struct 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 | |||
| 207 | struct platform_device vt8500_device_ge_rops = { | ||
| 208 | .name = "wmt_ge_rops", | ||
| 209 | .id = -1, | ||
| 210 | }; | ||
| 211 | |||
| 212 | struct platform_device vt8500_device_pwm = { | ||
| 213 | .name = "vt8500-pwm", | ||
| 214 | .id = 0, | ||
| 215 | }; | ||
| 216 | |||
| 217 | static 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 | |||
| 224 | struct platform_device vt8500_device_pwmbl = { | ||
| 225 | .name = "pwm-backlight", | ||
| 226 | .id = 0, | ||
| 227 | .dev = { | ||
| 228 | .platform_data = &vt8500_pwmbl_data, | ||
| 229 | }, | ||
| 230 | }; | ||
| 231 | |||
| 232 | struct platform_device vt8500_device_rtc = { | ||
| 233 | .name = "vt8500-rtc", | ||
| 234 | .id = 0, | ||
| 235 | }; | ||
| 236 | |||
| 237 | struct 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 | |||
| 254 | void __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 | |||
| 263 | void __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 | |||
| 22 | void __init vt8500_init_irq(void); | ||
| 23 | void __init wm8505_init_irq(void); | ||
| 24 | void __init vt8500_map_io(void); | ||
| 25 | void __init wm8505_map_io(void); | ||
| 26 | void __init vt8500_reserve_mem(void); | ||
| 27 | void __init wm8505_reserve_mem(void); | ||
| 28 | void __init vt8500_gpio_init(void); | ||
| 29 | void __init vt8500_set_resources(void); | ||
| 30 | void __init wm8505_set_resources(void); | ||
| 31 | |||
| 32 | extern unsigned long wmt_ic_base __initdata; | ||
| 33 | extern unsigned long wmt_sic_base __initdata; | ||
| 34 | extern unsigned long wmt_gpio_base __initdata; | ||
| 35 | extern unsigned long wmt_pmc_base __initdata; | ||
| 36 | |||
| 37 | extern int wmt_nr_irqs __initdata; | ||
| 38 | extern int wmt_timer_irq __initdata; | ||
| 39 | extern int wmt_gpio_ext_irq[8] __initdata; | ||
| 40 | |||
| 41 | extern struct map_desc wmt_io_desc[2] __initdata; | ||
| 42 | |||
| 43 | static 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 | |||
| 54 | static 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 | |||
| 65 | static 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 | |||
| 72 | extern struct sys_timer vt8500_timer; | ||
| 73 | |||
| 74 | extern struct platform_device vt8500_device_uart0; | ||
| 75 | extern struct platform_device vt8500_device_uart1; | ||
| 76 | extern struct platform_device vt8500_device_uart2; | ||
| 77 | extern struct platform_device vt8500_device_uart3; | ||
| 78 | extern struct platform_device vt8500_device_uart4; | ||
| 79 | extern struct platform_device vt8500_device_uart5; | ||
| 80 | |||
| 81 | extern struct platform_device vt8500_device_lcdc; | ||
| 82 | extern struct platform_device vt8500_device_wm8505_fb; | ||
| 83 | extern struct platform_device vt8500_device_ehci; | ||
| 84 | extern struct platform_device vt8500_device_ge_rops; | ||
| 85 | extern struct platform_device vt8500_device_pwm; | ||
| 86 | extern struct platform_device vt8500_device_pwmbl; | ||
| 87 | extern 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 | |||
| 32 | static void __iomem *regbase; | ||
| 33 | |||
| 34 | struct vt8500_gpio_chip { | ||
| 35 | struct gpio_chip chip; | ||
| 36 | unsigned int shift; | ||
| 37 | unsigned int regoff; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int gpio_to_irq_map[8]; | ||
| 41 | |||
| 42 | static 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 | |||
| 54 | static 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 | |||
| 64 | static 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 | |||
| 76 | static 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 | |||
| 93 | static 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 | |||
| 102 | static 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 | |||
| 134 | static 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 | |||
| 158 | static 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 | |||
| 168 | static 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 | |||
| 184 | static 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 | |||
| 190 | static 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 | |||
| 203 | static 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 | |||
| 211 | static 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 | |||
| 223 | void __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 | ||
| 16 | void wmt_setup_restart(void); | 16 | void vt8500_setup_restart(void); |
| 17 | void wmt_restart(char mode, const char *cmd); | 17 | void 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 | ||
| 39 | static void __iomem *ic_regbase; | 69 | static int irq_cnt; |
| 40 | static void __iomem *sic_regbase; | 70 | |
| 71 | struct vt8500_irq_priv { | ||
| 72 | void __iomem *base; | ||
| 73 | }; | ||
| 41 | 74 | ||
| 42 | static void vt8500_irq_mask(struct irq_data *d) | 75 | static 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 | ||
| 68 | static void vt8500_irq_unmask(struct irq_data *d) | 98 | static 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 | ||
| 83 | static int vt8500_irq_set_type(struct irq_data *d, unsigned int flow_type) | 110 | static 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 | ||
| 127 | void __init vt8500_init_irq(void) | 149 | static 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++) { | 164 | static 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 | ||
| 151 | void __init wm8505_init_irq(void) | 173 | static struct irq_domain_ops vt8500_irq_domain_ops = { |
| 174 | .map = vt8500_irq_map, | ||
| 175 | .xlate = irq_domain_xlate_onecell, | ||
| 176 | }; | ||
| 177 | |||
| 178 | int __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 | |||
| 22 | static void __iomem *pmc_base; | ||
| 23 | |||
| 24 | void 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 | |||
| 50 | void 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 | ||
| 58 | struct clocksource clocksource = { | 65 | static 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 | ||
| 101 | struct clock_event_device clockevent = { | 108 | static 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 | ||
| 118 | struct irqaction irq = { | 125 | static 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 | ||
| 125 | static void __init vt8500_timer_init(void) | 132 | static struct of_device_id vt8500_timer_ids[] = { |
| 133 | { .compatible = "via,vt8500-timer" }, | ||
| 134 | { } | ||
| 135 | }; | ||
| 136 | |||
| 137 | void __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 | ||
| 153 | struct 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 | |||
| 49 | static void __iomem *pmc_base; | ||
| 50 | |||
| 51 | void vt8500_restart(char mode, const char *cmd) | ||
| 52 | { | ||
| 53 | if (pmc_base) | ||
| 54 | writel(1, pmc_base + VT8500_PMSR_REG); | ||
| 55 | } | ||
| 56 | |||
| 57 | static 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 | |||
| 67 | void __init vt8500_map_io(void) | ||
| 68 | { | ||
| 69 | iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc)); | ||
| 70 | } | ||
| 71 | |||
| 72 | static 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 | |||
| 79 | void __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 | |||
| 168 | static const struct of_device_id vt8500_irq_match[] __initconst = { | ||
| 169 | { .compatible = "via,vt8500-intc", .data = vt8500_irq_init, }, | ||
| 170 | { /* sentinel */ }, | ||
| 171 | }; | ||
| 172 | |||
| 173 | static void __init vt8500_init_irq(void) | ||
| 174 | { | ||
| 175 | of_irq_init(vt8500_irq_match); | ||
| 176 | }; | ||
| 177 | |||
| 178 | static struct sys_timer vt8500_timer = { | ||
| 179 | .init = vt8500_timer_init, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static const char * const vt8500_dt_compat[] = { | ||
| 183 | "via,vt8500", | ||
| 184 | "wm,wm8650", | ||
| 185 | "wm,wm8505", | ||
| 186 | }; | ||
| 187 | |||
| 188 | DT_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, | ||
| 195 | MACHINE_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 | |||
| 30 | static void __iomem *pmc_hiber; | ||
| 31 | |||
| 32 | static 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 | |||
| 42 | static 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 | |||
| 49 | void __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 | |||
| 71 | MACHINE_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, | ||
| 79 | MACHINE_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/ | |||
| 16 | endif | 16 | endif |
| 17 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o | 17 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o |
| 18 | obj-$(CONFIG_ARCH_U8500) += ux500/ | 18 | obj-$(CONFIG_ARCH_U8500) += ux500/ |
| 19 | obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o | ||
| 19 | 20 | ||
| 20 | # Chip specific | 21 | # Chip specific |
| 21 | obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o | 22 | obj-$(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 */ | ||
| 24 | static DEFINE_SPINLOCK(_lock); | ||
| 25 | |||
| 26 | struct 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 | |||
| 45 | struct clk_pll { | ||
| 46 | struct clk_hw hw; | ||
| 47 | void __iomem *reg; | ||
| 48 | spinlock_t *lock; | ||
| 49 | int type; | ||
| 50 | }; | ||
| 51 | |||
| 52 | static 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 | |||
| 58 | static void vt8500_pmc_wait_busy(void) | ||
| 59 | { | ||
| 60 | while (readl(pmc_base) & VT8500_PMC_BUSY_MASK) | ||
| 61 | cpu_relax(); | ||
| 62 | } | ||
| 63 | |||
| 64 | static 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 | |||
| 80 | static 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 | |||
| 95 | static 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 | |||
| 103 | static 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 | |||
| 120 | static 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 | |||
| 128 | static 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 | |||
| 155 | static 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 | |||
| 161 | static 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 | |||
| 167 | static 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 | |||
| 180 | static __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 | |||
| 284 | static 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 | |||
| 310 | static 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 | |||
| 351 | static 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 | |||
| 386 | static 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 | |||
| 409 | static 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 | |||
| 432 | const 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 | |||
| 438 | static __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", ®); | ||
| 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 | |||
| 483 | static void __init vt8500_pll_init(struct device_node *node) | ||
| 484 | { | ||
| 485 | vtwm_pll_clk_init(node, PLL_TYPE_VT8500); | ||
| 486 | } | ||
| 487 | |||
| 488 | static void __init wm8650_pll_init(struct device_node *node) | ||
| 489 | { | ||
| 490 | vtwm_pll_clk_init(node, PLL_TYPE_WM8650); | ||
| 491 | } | ||
| 492 | |||
| 493 | static 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 | |||
| 502 | void __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 | ||
| 186 | config 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 | |||
| 186 | config GPIO_XILINX | 192 | config 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 | |||
| 69 | obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o | 69 | obj-$(CONFIG_GPIO_TWL4030) += gpio-twl4030.o |
| 70 | obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o | 70 | obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o |
| 71 | obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o | 71 | obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o |
| 72 | obj-$(CONFIG_GPIO_VT8500) += gpio-vt8500.o | ||
| 72 | obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o | 73 | obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o |
| 73 | obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o | 74 | obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o |
| 74 | obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o | 75 | obj-$(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 | |||
| 51 | struct 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 | |||
| 59 | struct 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 | |||
| 73 | static 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 | |||
| 86 | static 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 | */ | ||
| 106 | static 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 | |||
| 121 | struct 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 | |||
| 131 | static 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 | |||
| 146 | static 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 | |||
| 159 | static 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 | |||
| 170 | static 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 | |||
| 189 | static 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 | |||
| 197 | static 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 | |||
| 212 | static 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 | |||
| 222 | static 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 | |||
| 265 | static 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 | |||
| 272 | static 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 | |||
| 302 | static 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 | |||
| 311 | module_platform_driver(vt8500_gpio_driver); | ||
| 312 | |||
| 313 | MODULE_DESCRIPTION("VT8500 GPIO Driver"); | ||
| 314 | MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); | ||
| 315 | MODULE_LICENSE("GPL v2"); | ||
| 316 | MODULE_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 | ||
| 306 | static const struct of_device_id wmt_dt_ids[] = { | ||
| 307 | { .compatible = "via,vt8500-rtc", }, | ||
| 308 | {} | ||
| 309 | }; | ||
| 310 | |||
| 305 | static struct platform_driver vt8500_rtc_driver = { | 311 | static 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 | ||
| 316 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); | 323 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); |
| 317 | MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)"); | 324 | MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)"); |
| 318 | MODULE_LICENSE("GPL"); | 325 | MODULE_LICENSE("GPL v2"); |
| 319 | MODULE_ALIAS("platform:vt8500-rtc"); | 326 | MODULE_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 | |||
| 79 | struct vt8500_port { | 82 | struct 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 | */ | ||
| 94 | static unsigned long vt8500_ports_in_use; | ||
| 95 | |||
| 86 | static inline void vt8500_write(struct uart_port *port, unsigned int val, | 96 | static 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 | ||
| 434 | static struct vt8500_port *vt8500_uart_ports[4]; | 444 | static struct vt8500_port *vt8500_uart_ports[VT8500_MAX_PORTS]; |
| 435 | static struct uart_driver vt8500_uart_driver; | 445 | static 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 | ||
| 648 | static const struct of_device_id wmt_dt_ids[] = { | ||
| 649 | { .compatible = "via,vt8500-uart", }, | ||
| 650 | {} | ||
| 651 | }; | ||
| 652 | |||
| 606 | static struct platform_driver vt8500_platform_driver = { | 653 | static 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 | ||
| 643 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); | 691 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); |
| 644 | MODULE_DESCRIPTION("Driver for vt8500 serial device"); | 692 | MODULE_DESCRIPTION("Driver for vt8500 serial device"); |
| 645 | MODULE_LICENSE("GPL"); | 693 | MODULE_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 | ||
| 1789 | config FB_VT8500 | 1789 | config 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 | ||
| 1798 | config FB_WM8505 | 1798 | config 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 | ||
| 1807 | source "drivers/video/geode/Kconfig" | 1807 | source "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 | ||
| 501 | static const struct of_device_id via_dt_ids[] = { | ||
| 502 | { .compatible = "via,vt8500-fb", }, | ||
| 503 | {} | ||
| 504 | }; | ||
| 505 | |||
| 451 | static struct platform_driver vt8500lcd_driver = { | 506 | static 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 | ||
| 462 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); | 518 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>"); |
| 463 | MODULE_DESCRIPTION("LCD controller driver for VIA VT8500"); | 519 | MODULE_DESCRIPTION("LCD controller driver for VIA VT8500"); |
| 464 | MODULE_LICENSE("GPL"); | 520 | MODULE_LICENSE("GPL v2"); |
| 521 | MODULE_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 | ||
| 458 | static const struct of_device_id wmt_dt_ids[] = { | ||
| 459 | { .compatible = "wm,wm8505-fb", }, | ||
| 460 | {} | ||
| 461 | }; | ||
| 462 | |||
| 398 | static struct platform_driver wm8505fb_driver = { | 463 | static 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 | ||
| 409 | MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>"); | 475 | MODULE_AUTHOR("Ed Spiridonov <edo.rus@gmail.com>"); |
| 410 | MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505"); | 476 | MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505"); |
| 411 | MODULE_LICENSE("GPL"); | 477 | MODULE_LICENSE("GPL v2"); |
| 478 | MODULE_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 | ||
| 161 | static const struct of_device_id wmt_dt_ids[] = { | ||
| 162 | { .compatible = "wm,prizm-ge-rops", }, | ||
| 163 | { /* sentinel */ } | ||
| 164 | }; | ||
| 165 | |||
| 161 | static struct platform_driver wmt_ge_rops_driver = { | 166 | static 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); | |||
| 172 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com"); | 178 | MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com"); |
| 173 | MODULE_DESCRIPTION("Accelerators for raster operations using " | 179 | MODULE_DESCRIPTION("Accelerators for raster operations using " |
| 174 | "WonderMedia Graphics Engine"); | 180 | "WonderMedia Graphics Engine"); |
| 175 | MODULE_LICENSE("GPL"); | 181 | MODULE_LICENSE("GPL v2"); |
| 182 | MODULE_DEVICE_TABLE(of, wmt_dt_ids); | ||
