linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's
@ 2010-10-20 20:55 Alexey Charkov
  2010-10-20 20:55 ` [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles Alexey Charkov
                   ` (5 more replies)
  0 siblings, 6 replies; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 20:55 UTC (permalink / raw)
  To: vt8500-wm8505-linux-kernel
  Cc: linux-arm-kernel, Alexey Charkov, Russell King, linux-kernel

This adds support for the family of Systems-on-Chip produced initially
by VIA and now its subsidiary WonderMedia that have recently become
widespread in lower-end Chinese ARM-based tablets and netbooks.

Support is included for both VT8500 and WM8505, selectable by a
configuration switch at kernel build time.

Included are basic machine initialization files, register and
interrupt definitions, support for the on-chip interrupt controller,
high-precision OS timer, GPIO lines, necessary macros for early debug,
pulse-width-modulated outputs control, as well as platform device
configurations for the specific drivers implemented elsewhere.

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---

Please review and state whether this could be acceptable for a merge
to mainline in the coming 2.6.37 window. If possible, I would deeply
appreciate a merge to a relevant git tree for integration prior to
asking Linus to pull the changes. I could rebase the code if needed,
currently this is against Linus' master branch.

Due credits go to the community for providing feedback, advice and
testing for all code in this patch and the follow-ups.

 arch/arm/Kconfig                                |   14 +
 arch/arm/Makefile                               |    1 +
 arch/arm/boot/compressed/Makefile               |    4 +
 arch/arm/boot/compressed/head-vt8500.S          |   46 +++
 arch/arm/mach-vt8500/Kconfig                    |   56 ++++
 arch/arm/mach-vt8500/Makefile                   |    6 +
 arch/arm/mach-vt8500/Makefile.boot              |    3 +
 arch/arm/mach-vt8500/bv07.c                     |   80 +++++
 arch/arm/mach-vt8500/devices.c                  |  393 +++++++++++++++++++++++
 arch/arm/mach-vt8500/devices.h                  |   58 ++++
 arch/arm/mach-vt8500/gpio.c                     |  226 +++++++++++++
 arch/arm/mach-vt8500/include/mach/debug-macro.S |   35 ++
 arch/arm/mach-vt8500/include/mach/entry-macro.S |   32 ++
 arch/arm/mach-vt8500/include/mach/gpio.h        |    6 +
 arch/arm/mach-vt8500/include/mach/hardware.h    |   12 +
 arch/arm/mach-vt8500/include/mach/io.h          |   28 ++
 arch/arm/mach-vt8500/include/mach/irqs.h        |  189 +++++++++++
 arch/arm/mach-vt8500/include/mach/memory.h      |   28 ++
 arch/arm/mach-vt8500/include/mach/system.h      |   20 ++
 arch/arm/mach-vt8500/include/mach/timex.h       |   26 ++
 arch/arm/mach-vt8500/include/mach/uncompress.h  |   37 +++
 arch/arm/mach-vt8500/include/mach/vmalloc.h     |   20 ++
 arch/arm/mach-vt8500/include/mach/vt8500.h      |  143 ++++++++
 arch/arm/mach-vt8500/include/mach/vt8500fb.h    |   31 ++
 arch/arm/mach-vt8500/irq.c                      |  126 ++++++++
 arch/arm/mach-vt8500/pwm.c                      |  250 ++++++++++++++
 arch/arm/mach-vt8500/timer.c                    |  192 +++++++++++
 arch/arm/mach-vt8500/wm8505_7in.c               |   81 +++++
 28 files changed, 2143 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/boot/compressed/head-vt8500.S
 create mode 100644 arch/arm/mach-vt8500/Kconfig
 create mode 100644 arch/arm/mach-vt8500/Makefile
 create mode 100644 arch/arm/mach-vt8500/Makefile.boot
 create mode 100644 arch/arm/mach-vt8500/bv07.c
 create mode 100644 arch/arm/mach-vt8500/devices.c
 create mode 100644 arch/arm/mach-vt8500/devices.h
 create mode 100644 arch/arm/mach-vt8500/gpio.c
 create mode 100644 arch/arm/mach-vt8500/include/mach/debug-macro.S
 create mode 100644 arch/arm/mach-vt8500/include/mach/entry-macro.S
 create mode 100644 arch/arm/mach-vt8500/include/mach/gpio.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/hardware.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/io.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/irqs.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/memory.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/system.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/timex.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/uncompress.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/vmalloc.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/vt8500.h
 create mode 100644 arch/arm/mach-vt8500/include/mach/vt8500fb.h
 create mode 100644 arch/arm/mach-vt8500/irq.c
 create mode 100644 arch/arm/mach-vt8500/pwm.c
 create mode 100644 arch/arm/mach-vt8500/timer.c
 create mode 100644 arch/arm/mach-vt8500/wm8505_7in.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9c26ba7..90f0142 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -824,6 +824,18 @@ config PLAT_SPEAR
 	help
 	  Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
 
+config ARCH_VT8500
+	bool "VIA/WonderMedia 85xx"
+	select CPU_ARM926T
+	select GENERIC_GPIO
+	select ARCH_HAS_CPUFREQ
+	select GENERIC_TIME
+	select GENERIC_CLOCKEVENTS
+	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_CLK
+	select HAVE_PWM
+	help
+	  Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
 endchoice
 
 #
@@ -952,6 +964,8 @@ source "arch/arm/mach-versatile/Kconfig"
 
 source "arch/arm/mach-vexpress/Kconfig"
 
+source "arch/arm/mach-vt8500/Kconfig"
+
 source "arch/arm/mach-w90x900/Kconfig"
 
 # Definitions to make life easier
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 59c1ce8..65ae7ee 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -188,6 +188,7 @@ machine-$(CONFIG_ARCH_U300)		:= u300
 machine-$(CONFIG_ARCH_U8500)		:= ux500
 machine-$(CONFIG_ARCH_VERSATILE)	:= versatile
 machine-$(CONFIG_ARCH_VEXPRESS)		:= vexpress
+machine-$(CONFIG_ARCH_VT8500)		:= vt8500
 machine-$(CONFIG_ARCH_W90X900)		:= w90x900
 machine-$(CONFIG_ARCH_NUC93X)		:= nuc93x
 machine-$(CONFIG_FOOTBRIDGE)		:= footbridge
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 65a7c1c..62cade4 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -29,6 +29,10 @@ ifeq ($(CONFIG_ARCH_SA1100),y)
 OBJS		+= head-sa1100.o
 endif
 
+ifeq ($(CONFIG_ARCH_VT8500),y)
+OBJS		+= head-vt8500.o
+endif
+
 ifeq ($(CONFIG_CPU_XSCALE),y)
 OBJS		+= head-xscale.o
 endif
diff --git a/arch/arm/boot/compressed/head-vt8500.S b/arch/arm/boot/compressed/head-vt8500.S
new file mode 100644
index 0000000..1dc1e21
--- /dev/null
+++ b/arch/arm/boot/compressed/head-vt8500.S
@@ -0,0 +1,46 @@
+/*
+ * linux/arch/arm/boot/compressed/head-vt8500.S
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * VIA VT8500 specific tweaks. This is merged into head.S by the linker.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/mach-types.h>
+
+		.section        ".start", "ax"
+
+__VT8500_start:
+	@ Compare the SCC ID register against a list of known values
+	ldr	r1, .SCCID
+	ldr	r3, [r1]
+
+	@ VT8500 override
+	ldr	r4, .VT8500SCC
+	cmp	r3, r4
+	ldreq	r7, .ID_BV07
+	beq	.Lendvt8500
+
+	@ WM8505 override
+	ldr	r4, .WM8505SCC
+	cmp	r3, r4
+	ldreq	r7, .ID_8505
+	beq	.Lendvt8500
+
+	@ Otherwise, leave the bootloader's machine id untouched
+
+.SCCID:
+	.word	0xd8120000
+.VT8500SCC:
+	.word	0x34000102
+.WM8505SCC:
+	.word	0x34260103
+
+.ID_BV07:
+	.word	MACH_TYPE_BV07
+.ID_8505:
+	.word	MACH_TYPE_WM8505_7IN_NETBOOK
+
+.Lendvt8500:
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
new file mode 100644
index 0000000..9867ba9
--- /dev/null
+++ b/arch/arm/mach-vt8500/Kconfig
@@ -0,0 +1,56 @@
+if ARCH_VT8500
+
+choice
+	prompt "VIA/WonderMedia System Type"
+	default VTWM_VERSION_VT8500
+
+config VTWM_VERSION_VT8500
+	bool "VIA VT8500"
+
+config VTWM_VERSION_WM8505
+	bool "WonderMedia WM8505"
+
+endchoice
+
+config MACH_BV07
+	bool "Benign BV07-8500 Mini Netbook"
+	depends on ARCH_VT8500 && VTWM_VERSION_VT8500
+	help
+	  Add support for the inexpensive 7-inch netbooks sold by many
+	  Chinese distributors under various names. Note that there are
+	  many hardware implementations in identical exterior, make sure
+	  that yours is indeed based on a VIA VT8500 chip.
+
+config MACH_WM8505_7IN_NETBOOK
+	bool "WM8505 7-inch generic netbook"
+	depends on ARCH_VT8500 && VTWM_VERSION_WM8505
+	help
+	  Add support for the inexpensive 7-inch netbooks sold by many
+	  Chinese distributors under various names. Note that there are
+	  many hardware implementations in identical exterior, make sure
+	  that yours is indeed based on a WonderMedia WM8505 chip.
+
+choice
+	prompt "LCD panel size"
+	depends on (FB_VT8500 || FB_WM8505)
+	default WMT_PANEL_800X480
+
+config WMT_PANEL_800X480
+	bool "7-inch with 800x480 resolution"
+	help
+	  These are found in most of the netbooks in generic cases, as
+	  well as in Eken M001 tablets and possibly elsewhere.
+
+config WMT_PANEL_800X600
+	bool "8-inch with 800x600 resolution"
+	help
+	  These are found in Eken M003 tablets and possibly elsewhere.
+
+config WMT_PANEL_1024X600
+	bool "10-inch with 1024x600 resolution"
+	help
+	  These are found in Eken M006 tablets and possibly elsewhere.
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile
new file mode 100644
index 0000000..17e0841
--- /dev/null
+++ b/arch/arm/mach-vt8500/Makefile
@@ -0,0 +1,6 @@
+obj-y += devices.o gpio.o irq.o timer.o
+
+obj-$(CONFIG_MACH_BV07) += bv07.o
+obj-$(CONFIG_MACH_WM8505_7IN_NETBOOK) += wm8505_7in.o
+
+obj-$(CONFIG_HAVE_PWM) += pwm.o
diff --git a/arch/arm/mach-vt8500/Makefile.boot b/arch/arm/mach-vt8500/Makefile.boot
new file mode 100644
index 0000000..a8acc4e
--- /dev/null
+++ b/arch/arm/mach-vt8500/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x01000000
diff --git a/arch/arm/mach-vt8500/bv07.c b/arch/arm/mach-vt8500/bv07.c
new file mode 100644
index 0000000..a9d011f
--- /dev/null
+++ b/arch/arm/mach-vt8500/bv07.c
@@ -0,0 +1,80 @@
+/*
+ *  arch/arm/mach-vt8500/bv07.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+
+#include <mach/vt8500.h>
+#include "devices.h"
+
+static struct platform_device *devices[] __initdata = {
+	&vt8500_device_uart0,
+#ifdef CONFIG_FB_VT8500
+	&vt8500_device_lcdc,
+#endif
+#ifdef CONFIG_USB_EHCI_HCD
+	&vt8500_device_ehci,
+#endif
+#ifdef CONFIG_FB_WMT_GE_ROPS
+	&vt8500_device_ge_rops,
+#endif
+#ifdef CONFIG_HAVE_PWM
+	&vt8500_device_pwm,
+#endif
+#ifdef CONFIG_BACKLIGHT_PWM
+	&vt8500_device_pwmbl,
+#endif
+#ifdef CONFIG_RTC_DRV_VT8500
+	&vt8500_device_rtc,
+#endif
+};
+
+static void vt8500_power_off(void)
+{
+	void __iomem *pmc_hiber = ioremap(VT8500_PMC_BASE + 0x12, 2);
+	local_irq_disable();
+	writew(5, pmc_hiber);
+	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
+}
+
+void __init bv07_init(void)
+{
+#ifdef CONFIG_FB_VT8500
+	void __iomem *gpio_mux_reg = ioremap(VT8500_GPIO_BASE + 0x200, 4);
+
+	writel(readl(gpio_mux_reg) | 1, gpio_mux_reg);
+	iounmap(gpio_mux_reg);
+#endif
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+	vt8500_gpio_init();
+	pm_power_off = &vt8500_power_off;
+}
+
+MACHINE_START(BV07, "Benign BV07 Mini Netbook")
+	.phys_io	= VT8500_REGS_START_PHYS,
+	.io_pg_offst	= ((VT8500_REGS_START_VIRT) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.map_io		= vt8500_map_io,
+	.init_irq	= vt8500_init_irq,
+	.timer		= &vt8500_timer,
+	.init_machine	= bv07_init,
+MACHINE_END
diff --git a/arch/arm/mach-vt8500/devices.c b/arch/arm/mach-vt8500/devices.c
new file mode 100644
index 0000000..1b559c8
--- /dev/null
+++ b/arch/arm/mach-vt8500/devices.c
@@ -0,0 +1,393 @@
+/* linux/arch/arm/mach-vt8500/devices.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/memblock.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <mach/vt8500.h>
+#include <mach/vt8500fb.h>
+#include "devices.h"
+
+#ifdef CONFIG_FB_VT8500
+static struct resource resources_lcdc[] = {
+	{
+		.start	= VT8500_LCDC_BASE,
+		.end	= VT8500_LCDC_BASE + SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_LCDC,
+		.end	= IRQ_LCDC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 fb_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device vt8500_device_lcdc = {
+	.name           = "vt8500-lcd",
+	.id             = 0,
+	.dev		= {
+		.dma_mask	= &fb_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.num_resources  = ARRAY_SIZE(resources_lcdc),
+	.resource       = resources_lcdc,
+};
+#endif
+
+#ifdef CONFIG_FB_WM8505
+static struct resource resources_wm8505_fb[] = {
+	{
+		.start	= WM8505_GOVR_BASE,
+		.end	= WM8505_GOVR_BASE + 512 - 1,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+struct platform_device vt8500_device_wm8505_fb = {
+	.name           = "wm8505-fb",
+	.id             = 0,
+	.num_resources  = ARRAY_SIZE(resources_wm8505_fb),
+	.resource       = resources_wm8505_fb,
+};
+#endif
+
+#ifdef CONFIG_WMT_PANEL_1024X600
+static struct vt8500fb_platform_data panel_data = {
+	.xres_virtual	= 1024,
+	.yres_virtual	= 600 * 2,
+	.mode		= {
+		.name		= "10-inch 1024x600 panel",
+		.xres		= 1024,
+		.yres		= 600,
+		.left_margin	= 88,
+		.right_margin	= 40,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 0,
+		.vsync_len	= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+#elif defined CONFIG_WMT_PANEL_800X600
+static struct vt8500fb_platform_data panel_data = {
+	.xres_virtual	= 800,
+	.yres_virtual	= 600 * 2,
+	.mode		= {
+		.name		= "8-inch 800x600 panel",
+		.xres		= 800,
+		.yres		= 600,
+		.left_margin	= 88,
+		.right_margin	= 40,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 0,
+		.vsync_len	= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+#elif defined CONFIG_WMT_PANEL_800X480
+static struct vt8500fb_platform_data panel_data = {
+	.xres_virtual	= 800,
+	.yres_virtual	= 480 * 2,
+	.mode		= {
+		.name		= "7-inch 800x480 panel",
+		.xres		= 800,
+		.yres		= 480,
+		.left_margin	= 88,
+		.right_margin	= 40,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 0,
+		.vsync_len	= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+};
+#endif
+
+static inline void preallocate_fb(struct vt8500fb_platform_data *p,
+				  unsigned long align) {
+	p->video_mem_len = (p->xres_virtual * p->yres_virtual * 4) >>
+			(p->bpp > 16 ? 0 : (p->bpp > 8 ? 1 :
+					(8 / p->bpp) + 1));
+	p->video_mem_phys = (unsigned long)memblock_alloc(p->video_mem_len,
+							  align);
+	p->video_mem_virt = phys_to_virt(p->video_mem_phys);
+}
+
+static struct map_desc vt8500_io_desc[] __initdata = {
+	{
+		.virtual	=  VT8500_REGS_START_VIRT,
+		.pfn		= __phys_to_pfn(VT8500_REGS_START_PHYS),
+		.length		= VT8500_REGS_LENGTH,
+		.type		= MT_DEVICE
+	},
+};
+
+void __init vt8500_map_io(void)
+{
+#ifdef CONFIG_FB_VT8500
+	panel_data.bpp = 16; /* Always use RGB565 */
+	preallocate_fb(&panel_data, SZ_4M);
+	vt8500_device_lcdc.dev.platform_data = &panel_data;
+#endif
+#ifdef CONFIG_FB_WM8505
+	panel_data.bpp = 32; /* Always use RGB888 */
+	preallocate_fb(&panel_data, 32);
+	vt8500_device_wm8505_fb.dev.platform_data = &panel_data;
+#endif
+	iotable_init(vt8500_io_desc, ARRAY_SIZE(vt8500_io_desc));
+}
+
+static struct resource resources_uart0[] = {
+	{
+		.start	= IRQ_UART0,
+		.end	= IRQ_UART0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= VT8500_UART0_BASE,
+		.end	= VT8500_UART0_BASE + VT8500_UART_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource resources_uart1[] = {
+	{
+		.start	= IRQ_UART1,
+		.end	= IRQ_UART1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= VT8500_UART1_BASE,
+		.end	= VT8500_UART1_BASE + VT8500_UART_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource resources_uart2[] = {
+	{
+		.start	= IRQ_UART2,
+		.end	= IRQ_UART2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= VT8500_UART2_BASE,
+		.end	= VT8500_UART2_BASE + VT8500_UART_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource resources_uart3[] = {
+	{
+		.start	= IRQ_UART3,
+		.end	= IRQ_UART3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= VT8500_UART3_BASE,
+		.end	= VT8500_UART3_BASE + VT8500_UART_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+#ifdef CONFIG_VTWM_VERSION_WM8505
+static struct resource resources_uart4[] = {
+	{
+		.start	= IRQ_UART4,
+		.end	= IRQ_UART4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= VT8500_UART4_BASE,
+		.end	= VT8500_UART4_BASE + VT8500_UART_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource resources_uart5[] = {
+	{
+		.start	= IRQ_UART5,
+		.end	= IRQ_UART5,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= VT8500_UART5_BASE,
+		.end	= VT8500_UART5_BASE + VT8500_UART_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+#endif
+
+struct platform_device vt8500_device_uart0 = {
+	.name		= "vt8500_serial",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(resources_uart0),
+	.resource	= resources_uart0,
+};
+
+struct platform_device vt8500_device_uart1 = {
+	.name		= "vt8500_serial",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(resources_uart1),
+	.resource	= resources_uart1,
+};
+
+struct platform_device vt8500_device_uart2 = {
+	.name		= "vt8500_serial",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(resources_uart2),
+	.resource	= resources_uart2,
+};
+
+struct platform_device vt8500_device_uart3 = {
+	.name		= "vt8500_serial",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(resources_uart3),
+	.resource	= resources_uart3,
+};
+
+#ifdef CONFIG_VTWM_VERSION_WM8505
+struct platform_device vt8500_device_uart4 = {
+	.name		= "vt8500_serial",
+	.id		= 4,
+	.num_resources	= ARRAY_SIZE(resources_uart4),
+	.resource	= resources_uart4,
+};
+
+struct platform_device vt8500_device_uart5 = {
+	.name		= "vt8500_serial",
+	.id		= 5,
+	.num_resources	= ARRAY_SIZE(resources_uart5),
+	.resource	= resources_uart5,
+};
+#endif
+
+#ifdef CONFIG_USB_EHCI_HCD
+static struct resource resources_ehci[] = {
+	{
+		.start	= VT8500_EHCI_BASE,
+		.end	= VT8500_EHCI_BASE + 512 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_EHCI,
+		.end	= IRQ_EHCI,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static u64 ehci_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device vt8500_device_ehci = {
+	.name		= "vt8500-ehci",
+	.id		= 0,
+	.dev		= {
+		.dma_mask	= &ehci_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.num_resources	= ARRAY_SIZE(resources_ehci),
+	.resource	= resources_ehci,
+};
+#endif
+
+#ifdef CONFIG_FB_WMT_GE_ROPS
+static struct resource resources_ge_rops[] = {
+	{
+		.start	= VT8500_GEGEA_BASE,
+		.end	= VT8500_GEGEA_BASE + 0xff,
+		.flags	= IORESOURCE_MEM,
+	}
+};
+
+struct platform_device vt8500_device_ge_rops = {
+	.name		= "wmt_ge_rops",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(resources_ge_rops),
+	.resource	= resources_ge_rops,
+};
+#endif
+
+#ifdef CONFIG_HAVE_PWM
+static struct resource resources_pwm[] = {
+	[0] = {
+		.start	= VT8500_PWM_BASE,
+		.end	= VT8500_PWM_BASE + 0x43,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device vt8500_device_pwm = {
+	.name		= "vt8500-pwm",
+	.id		= 0,
+	.resource	= resources_pwm,
+	.num_resources	= ARRAY_SIZE(resources_pwm),
+};
+#endif
+
+#ifdef CONFIG_BACKLIGHT_PWM
+static struct platform_pwm_backlight_data vt8500_pwmbl_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 128,
+	.dft_brightness = 70,
+	.pwm_period_ns	= 250000, /* revisit when clocks are implemented */
+};
+
+struct platform_device vt8500_device_pwmbl = {
+	.name		= "pwm-backlight",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &vt8500_pwmbl_data,
+	},
+};
+#endif
+
+#ifdef CONFIG_RTC_DRV_VT8500
+static struct resource resources_rtc[] = {
+	[0] = {
+		.start	= VT8500_RTC_BASE,
+		.end	= VT8500_RTC_BASE + 0x2c - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_RTC,
+		.end	= IRQ_RTC,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= IRQ_RTCSM,
+		.end	= IRQ_RTCSM,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device vt8500_device_rtc = {
+	.name		= "vt8500-rtc",
+	.id		= 0,
+	.resource	= resources_rtc,
+	.num_resources	= ARRAY_SIZE(resources_rtc),
+};
+#endif
diff --git a/arch/arm/mach-vt8500/devices.h b/arch/arm/mach-vt8500/devices.h
new file mode 100644
index 0000000..3da3b0c
--- /dev/null
+++ b/arch/arm/mach-vt8500/devices.h
@@ -0,0 +1,58 @@
+/* linux/arch/arm/mach-vt8500/devices.h
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_VT8500_DEVICES_H
+#define __ARCH_ARM_MACH_VT8500_DEVICES_H
+
+#include <linux/platform_device.h>
+
+void __init vt8500_init_irq(void);
+void __init vt8500_map_io(void);
+void __init vt8500_gpio_init(void);
+extern struct sys_timer vt8500_timer;
+
+extern struct platform_device vt8500_device_uart0;
+extern struct platform_device vt8500_device_uart1;
+extern struct platform_device vt8500_device_uart2;
+extern struct platform_device vt8500_device_uart3;
+#ifdef CONFIG_VTWM_VERSION_WM8505
+extern struct platform_device vt8500_device_uart4;
+extern struct platform_device vt8500_device_uart5;
+#endif
+
+#ifdef CONFIG_FB_VT8500
+extern struct platform_device vt8500_device_lcdc;
+#endif
+#ifdef CONFIG_FB_WM8505
+extern struct platform_device vt8500_device_wm8505_fb;
+#endif
+
+#ifdef CONFIG_USB_EHCI_HCD
+extern struct platform_device vt8500_device_ehci;
+#endif
+
+#ifdef CONFIG_FB_WMT_GE_ROPS
+extern struct platform_device vt8500_device_ge_rops;
+#endif
+#ifdef CONFIG_HAVE_PWM
+extern struct platform_device vt8500_device_pwm;
+#endif
+#ifdef CONFIG_BACKLIGHT_PWM
+extern struct platform_device vt8500_device_pwmbl;
+#endif
+#ifdef CONFIG_RTC_DRV_VT8500
+extern struct platform_device vt8500_device_rtc;
+#endif
+#endif
diff --git a/arch/arm/mach-vt8500/gpio.c b/arch/arm/mach-vt8500/gpio.c
new file mode 100644
index 0000000..eea5924
--- /dev/null
+++ b/arch/arm/mach-vt8500/gpio.c
@@ -0,0 +1,226 @@
+/* linux/arch/arm/mach-vt8500/gpio.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include <mach/vt8500.h>
+
+#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
+
+static void __iomem *regbase;
+
+struct vt8500_gpio_chip {
+	struct gpio_chip	chip;
+	unsigned int		shift;
+	unsigned int		regoff;
+};
+
+static unsigned int gpio_to_irq_map[] = {
+	IRQ_EXT0,
+	IRQ_EXT1,
+	IRQ_EXT2,
+	IRQ_EXT3,
+	IRQ_EXT4,
+	IRQ_EXT5,
+	IRQ_EXT6,
+	IRQ_EXT7,
+};
+
+static int vt8500_muxed_gpio_request(struct gpio_chip *chip,
+				     unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	writel(readl(regbase + vt8500_chip->regoff) |
+		(1 << vt8500_chip->shift << offset),
+		regbase + vt8500_chip->regoff);
+
+	return 0;
+}
+
+static void vt8500_muxed_gpio_free(struct gpio_chip *chip,
+				   unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	writel(readl(regbase + vt8500_chip->regoff) &
+		~(1 << vt8500_chip->shift << offset),
+		regbase + vt8500_chip->regoff);
+}
+
+static int vt8500_muxed_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	writel(readl(regbase + 0x20 + vt8500_chip->regoff) &
+		~(1 << vt8500_chip->shift << offset),
+		regbase + 0x20 + vt8500_chip->regoff);
+
+	return 0;
+}
+
+static int vt8500_muxed_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	writel(readl(regbase + 0x20 + vt8500_chip->regoff) |
+		(1 << vt8500_chip->shift << offset),
+		regbase + 0x20 + vt8500_chip->regoff);
+
+	if (value)
+		writel(readl(regbase + 0x40 + vt8500_chip->regoff) |
+			(1 << vt8500_chip->shift << offset),
+			regbase + 0x40 + vt8500_chip->regoff);
+	return 0;
+}
+
+static int vt8500_muxed_gpio_get_value(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	return (readl(regbase + 0x60 + vt8500_chip->regoff)
+		>> vt8500_chip->shift >> offset) & 1;
+}
+
+static void vt8500_muxed_gpio_set_value(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	if (value)
+		writel(readl(regbase + 0x40 + vt8500_chip->regoff) |
+			(1 << vt8500_chip->shift << offset),
+			regbase + 0x40 + vt8500_chip->regoff);
+	else
+		writel(readl(regbase + 0x40 + vt8500_chip->regoff) &
+			~(1 << vt8500_chip->shift << offset),
+			regbase + 0x40 + vt8500_chip->regoff);
+}
+
+#define VT8500_GPIO_BANK(__name, __shift, __off, __base, __num)		\
+{									\
+	.chip = {							\
+		.label			= __name,			\
+		.request		= vt8500_muxed_gpio_request,	\
+		.free			= vt8500_muxed_gpio_free,	\
+		.direction_input  = vt8500_muxed_gpio_direction_input,	\
+		.direction_output = vt8500_muxed_gpio_direction_output,	\
+		.get			= vt8500_muxed_gpio_get_value,	\
+		.set			= vt8500_muxed_gpio_set_value,	\
+		.can_sleep		= 0,				\
+		.base			= __base,			\
+		.ngpio			= __num,			\
+	},								\
+	.shift		= __shift,					\
+	.regoff		= __off,					\
+}
+
+static struct vt8500_gpio_chip vt8500_muxed_gpios[] = {
+	VT8500_GPIO_BANK("uart0", 0, 0x0, 8, 4),
+	VT8500_GPIO_BANK("uart1", 4, 0x0, 12, 4),
+	VT8500_GPIO_BANK("spi0", 8, 0x0, 16, 4),
+	VT8500_GPIO_BANK("spi1", 12, 0x0, 20, 4),
+	VT8500_GPIO_BANK("spi2", 16, 0x0, 24, 4),
+	VT8500_GPIO_BANK("pwmout", 24, 0x0, 28, 2),
+
+	VT8500_GPIO_BANK("sdmmc", 0, 0x4, 30, 11),
+	VT8500_GPIO_BANK("ms", 16, 0x4, 41, 7),
+	VT8500_GPIO_BANK("i2c0", 24, 0x4, 48, 2),
+	VT8500_GPIO_BANK("i2c1", 26, 0x4, 50, 2),
+
+	VT8500_GPIO_BANK("mii", 0, 0x8, 52, 20),
+	VT8500_GPIO_BANK("see", 20, 0x8, 72, 4),
+	VT8500_GPIO_BANK("ide", 24, 0x8, 76, 7),
+
+	VT8500_GPIO_BANK("ccir", 0, 0xc, 83, 19),
+
+	VT8500_GPIO_BANK("ts", 8, 0x10, 102, 11),
+
+	VT8500_GPIO_BANK("lcd", 0, 0x14, 113, 23),
+};
+
+static int vt8500_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	writel(readl(regbase + 0x3c) & ~(1 << offset), regbase + 0x3c);
+	return 0;
+}
+
+static int vt8500_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	writel(readl(regbase + 0x3c) | (1 << offset), regbase + 0x3c);
+
+	if (value)
+		writel(readl(regbase + 0x5c) | (1 << offset),
+		       regbase + 0x5c);
+	return 0;
+}
+
+static int vt8500_gpio_get_value(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	return (readl(regbase + 0x7c) >> offset) & 1;
+}
+
+static void vt8500_gpio_set_value(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	if (value)
+		writel(readl(regbase + 0x5c) | (1 << offset),
+		       regbase + 0x5c);
+	else
+		writel(readl(regbase + 0x5c) & ~(1 << offset),
+			regbase + 0x5c);
+}
+
+static int vt8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset > 7)
+		return -EINVAL;
+
+	return gpio_to_irq_map[offset];
+}
+
+static struct gpio_chip vt8500_external_gpios = {
+	.label			= "extgpio",
+	.direction_input	= vt8500_gpio_direction_input,
+	.direction_output	= vt8500_gpio_direction_output,
+	.get			= vt8500_gpio_get_value,
+	.set			= vt8500_gpio_set_value,
+	.to_irq			= vt8500_gpio_to_irq,
+	.can_sleep		= 0,
+	.base			= 0,
+	.ngpio			= 8,
+};
+
+void __init vt8500_gpio_init(void)
+{
+	int i;
+
+	regbase = ioremap(VT8500_GPIO_BASE, SZ_64K);
+
+	gpiochip_add(&vt8500_external_gpios);
+
+	for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++)
+		gpiochip_add(&vt8500_muxed_gpios[i].chip);
+}
diff --git a/arch/arm/mach-vt8500/include/mach/debug-macro.S b/arch/arm/mach-vt8500/include/mach/debug-macro.S
new file mode 100644
index 0000000..264e0be
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/debug-macro.S
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/mach-vt8500/include/mach/debug-macro.S
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Debugging macro include header
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <mach/vt8500.h>
+
+	.macro	addruart, rx, tmp
+	mrc	p15, 0, \rx, c1, c0
+	tst	\rx, #1			@ MMU enabled?
+	moveq	\rx,      #0xd8000000
+	movne	\rx,      #0xf8000000	@ virtual base
+	orr	\rx, \rx, #0x00200000
+	.endm
+
+	.macro	senduart,rd,rx
+	strb	\rd, [\rx, #0]
+	.endm
+
+	.macro	busyuart,rd,rx
+1001:	ldr	\rd, [\rx, #0x1c]
+	ands	\rd, \rd, #0x2
+	bne	1001b
+	.endm
+
+	.macro	waituart,rd,rx
+	.endm
diff --git a/arch/arm/mach-vt8500/include/mach/entry-macro.S b/arch/arm/mach-vt8500/include/mach/entry-macro.S
new file mode 100644
index 0000000..92684c7
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/entry-macro.S
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-vt8500/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for VIA VT8500
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+	.macro	disable_fiq
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	@ physical 0xd8140000 is virtual 0xf8140000
+	mov	\base, #0xf8000000
+	orr	\base, \base, #0x00140000
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr	\irqnr, [\base]
+	cmp	\irqnr, #63 @ may be false positive, check interrupt status
+	bne	1001f
+	ldr	\irqstat, [\base, #0x84]
+	ands	\irqstat, #0x80000000
+	moveq	\irqnr, #0
+1001:
+	.endm
+
diff --git a/arch/arm/mach-vt8500/include/mach/gpio.h b/arch/arm/mach-vt8500/include/mach/gpio.h
new file mode 100644
index 0000000..94ff276
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/gpio.h
@@ -0,0 +1,6 @@
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
diff --git a/arch/arm/mach-vt8500/include/mach/hardware.h b/arch/arm/mach-vt8500/include/mach/hardware.h
new file mode 100644
index 0000000..db4163f
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/hardware.h
@@ -0,0 +1,12 @@
+/* arch/arm/mach-vt8500/include/mach/hardware.h
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
diff --git a/arch/arm/mach-vt8500/include/mach/io.h b/arch/arm/mach-vt8500/include/mach/io.h
new file mode 100644
index 0000000..dc2181a
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/io.h
@@ -0,0 +1,28 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/io.h
+ *
+ *  Copyright (C) 2003 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#endif
diff --git a/arch/arm/mach-vt8500/include/mach/irqs.h b/arch/arm/mach-vt8500/include/mach/irqs.h
new file mode 100644
index 0000000..26f7059
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/irqs.h
@@ -0,0 +1,189 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/irqs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifdef CONFIG_VTWM_VERSION_VT8500
+/* VT8500 Interrupt Sources */
+
+#define IRQ_JPEGENC	0	/* JPEG Encoder */
+#define IRQ_JPEGDEC	1	/* JPEG Decoder */
+				/* Reserved */
+#define IRQ_PATA	3	/* PATA Controller */
+				/* Reserved */
+#define IRQ_DMA		5	/* DMA Controller */
+#define IRQ_EXT0	6	/* External Interrupt 0 */
+#define IRQ_EXT1	7	/* External Interrupt 1 */
+#define IRQ_GE		8	/* Graphic Engine */
+#define IRQ_GOV		9	/* Graphic Overlay Engine */
+#define IRQ_ETHER	10	/* Ethernet MAC */
+#define IRQ_MPEGTS	11	/* Transport Stream Interface */
+#define IRQ_LCDC	12	/* LCD Controller */
+#define IRQ_EXT2	13	/* External Interrupt 2 */
+#define IRQ_EXT3	14	/* External Interrupt 3 */
+#define IRQ_EXT4	15	/* External Interrupt 4 */
+#define IRQ_CIPHER	16	/* Cipher */
+#define IRQ_VPP		17	/* Video Post-Processor */
+#define IRQ_I2C1	18	/* I2C 1 */
+#define IRQ_I2C0	19	/* I2C 0 */
+#define IRQ_SDMMC	20	/* SD/MMC Controller */
+#define IRQ_SDMMC_DMA	21	/* SD/MMC Controller DMA */
+#define IRQ_PMC_WU	22	/* Power Management Controller Wakeup */
+				/* Reserved */
+#define IRQ_SPI0	24	/* SPI 0 */
+#define IRQ_SPI1	25	/* SPI 1 */
+#define IRQ_SPI2	26	/* SPI 2 */
+#define IRQ_LCDDF	27	/* LCD Data Formatter */
+#define IRQ_NAND	28	/* NAND Flash Controller */
+#define IRQ_NAND_DMA	29	/* NAND Flash Controller DMA */
+#define IRQ_MS		30	/* MemoryStick Controller */
+#define IRQ_MS_DMA	31	/* MemoryStick Controller DMA */
+#define IRQ_UART0	32	/* UART 0 */
+#define IRQ_UART1	33	/* UART 1 */
+#define IRQ_I2S		34	/* I2S */
+#define IRQ_PCM		35	/* PCM */
+#define IRQ_PMCOS0	36	/* PMC OS Timer 0 */
+#define IRQ_PMCOS1	37	/* PMC OS Timer 1 */
+#define IRQ_PMCOS2	38	/* PMC OS Timer 2 */
+#define IRQ_PMCOS3	39	/* PMC OS Timer 3 */
+#define IRQ_VPU		40	/* Video Processing Unit */
+#define IRQ_VID		41	/* Video Digital Input Interface */
+#define IRQ_AC97	42	/* AC97 Interface */
+#define IRQ_EHCI	43	/* USB */
+#define IRQ_NOR		44	/* NOR Flash Controller */
+#define IRQ_PS2MOUSE	45	/* PS/2 Mouse */
+#define IRQ_PS2KBD	46	/* PS/2 Keyboard */
+#define IRQ_UART2	47	/* UART 2 */
+#define IRQ_RTC		48	/* RTC Interrupt */
+#define IRQ_RTCSM	49	/* RTC Second/Minute Update Interrupt */
+#define IRQ_UART3	50	/* UART 3 */
+#define IRQ_ADC		51	/* ADC */
+#define IRQ_EXT5	52	/* External Interrupt 5 */
+#define IRQ_EXT6	53	/* External Interrupt 6 */
+#define IRQ_EXT7	54	/* External Interrupt 7 */
+#define IRQ_CIR		55	/* CIR */
+#define IRQ_DMA0	56	/* DMA Channel 0 */
+#define IRQ_DMA1	57	/* DMA Channel 1 */
+#define IRQ_DMA2	58	/* DMA Channel 2 */
+#define IRQ_DMA3	59	/* DMA Channel 3 */
+#define IRQ_DMA4	60	/* DMA Channel 4 */
+#define IRQ_DMA5	61	/* DMA Channel 5 */
+#define IRQ_DMA6	62	/* DMA Channel 6 */
+#define IRQ_DMA7	63	/* DMA Channel 7 */
+
+#define NR_IRQS		64
+
+#elif defined CONFIG_VTWM_VERSION_WM8505
+/* WM8505 Interrupt Sources */
+
+#define IRQ_UHCI	0	/* UHC FS (UHCI?) */
+#define IRQ_EHCI	1	/* UHC HS */
+#define IRQ_UDCDMA	2	/* UDC DMA */
+				/* Reserved */
+#define IRQ_PS2MOUSE	4	/* PS/2 Mouse */
+#define IRQ_UDC		5	/* UDC */
+#define IRQ_EXT0	6	/* External Interrupt 0 */
+#define IRQ_EXT1	7	/* External Interrupt 1 */
+#define IRQ_KEYPAD	8	/* Keypad */
+#define IRQ_DMA		9	/* DMA Controller */
+#define IRQ_ETHER	10	/* Ethernet MAC */
+				/* Reserved */
+				/* Reserved */
+#define IRQ_EXT2	13	/* External Interrupt 2 */
+#define IRQ_EXT3	14	/* External Interrupt 3 */
+#define IRQ_EXT4	15	/* External Interrupt 4 */
+#define IRQ_APB		16	/* APB Bridge */
+#define IRQ_DMA0	17	/* DMA Channel 0 */
+#define IRQ_I2C1	18	/* I2C 1 */
+#define IRQ_I2C0	19	/* I2C 0 */
+#define IRQ_SDMMC	20	/* SD/MMC Controller */
+#define IRQ_SDMMC_DMA	21	/* SD/MMC Controller DMA */
+#define IRQ_PMC_WU	22	/* Power Management Controller Wakeup */
+#define IRQ_PS2KBD	23	/* PS/2 Keyboard */
+#define IRQ_SPI0	24	/* SPI 0 */
+#define IRQ_SPI1	25	/* SPI 1 */
+#define IRQ_SPI2	26	/* SPI 2 */
+#define IRQ_DMA1	27	/* DMA Channel 1 */
+#define IRQ_NAND	28	/* NAND Flash Controller */
+#define IRQ_NAND_DMA	29	/* NAND Flash Controller DMA */
+#define IRQ_UART5	30	/* UART 5 */
+#define IRQ_UART4	31	/* UART 4 */
+#define IRQ_UART0	32	/* UART 0 */
+#define IRQ_UART1	33	/* UART 1 */
+#define IRQ_DMA2	34	/* DMA Channel 2 */
+#define IRQ_I2S		35	/* I2S */
+#define IRQ_PMCOS0	36	/* PMC OS Timer 0 */
+#define IRQ_PMCOS1	37	/* PMC OS Timer 1 */
+#define IRQ_PMCOS2	38	/* PMC OS Timer 2 */
+#define IRQ_PMCOS3	39	/* PMC OS Timer 3 */
+#define IRQ_DMA3	40	/* DMA Channel 3 */
+#define IRQ_DMA4	41	/* DMA Channel 4 */
+#define IRQ_AC97	42	/* AC97 Interface */
+				/* Reserved */
+#define IRQ_NOR		44	/* NOR Flash Controller */
+#define IRQ_DMA5	45	/* DMA Channel 5 */
+#define IRQ_DMA6	46	/* DMA Channel 6 */
+#define IRQ_UART2	47	/* UART 2 */
+#define IRQ_RTC		48	/* RTC Interrupt */
+#define IRQ_RTCSM	49	/* RTC Second/Minute Update Interrupt */
+#define IRQ_UART3	50	/* UART 3 */
+#define IRQ_DMA7	51	/* DMA Channel 7 */
+#define IRQ_EXT5	52	/* External Interrupt 5 */
+#define IRQ_EXT6	53	/* External Interrupt 6 */
+#define IRQ_EXT7	54	/* External Interrupt 7 */
+#define IRQ_CIR		55	/* CIR */
+#define IRQ_SIC0	56	/* SIC IRQ0 */
+#define IRQ_SIC1	57	/* SIC IRQ1 */
+#define IRQ_SIC2	58	/* SIC IRQ2 */
+#define IRQ_SIC3	59	/* SIC IRQ3 */
+#define IRQ_SIC4	60	/* SIC IRQ4 */
+#define IRQ_SIC5	61	/* SIC IRQ5 */
+#define IRQ_SIC6	62	/* SIC IRQ6 */
+#define IRQ_SIC7	63	/* SIC IRQ7 */
+				/* Reserved */
+#define IRQ_JPEGDEC	65	/* JPEG Decoder */
+#define IRQ_SAE		66	/* SAE (?) */
+				/* Reserved */
+#define IRQ_VPU		79	/* Video Processing Unit */
+#define IRQ_VPP		80	/* Video Post-Processor */
+#define IRQ_VID		81	/* Video Digital Input Interface */
+#define IRQ_SPU		82	/* SPU (?) */
+#define IRQ_PIP		83	/* PIP Error */
+#define IRQ_GE		84	/* Graphic Engine */
+#define IRQ_GOV		85	/* Graphic Overlay Engine */
+#define IRQ_DVO		86	/* Digital Video Output */
+				/* Reserved */
+#define IRQ_DMA8	92	/* DMA Channel 8 */
+#define IRQ_DMA9	93	/* DMA Channel 9 */
+#define IRQ_DMA10	94	/* DMA Channel 10 */
+#define IRQ_DMA11	95	/* DMA Channel 11 */
+#define IRQ_DMA12	96	/* DMA Channel 12 */
+#define IRQ_DMA13	97	/* DMA Channel 13 */
+#define IRQ_DMA14	98	/* DMA Channel 14 */
+#define IRQ_DMA15	99	/* DMA Channel 15 */
+				/* Reserved */
+#define IRQ_GOVW	111	/* GOVW (?) */
+#define IRQ_GOVRSDSCD	112	/* GOVR SDSCD (?) */
+#define IRQ_GOVRSDMIF	113	/* GOVR SDMIF (?) */
+#define IRQ_GOVRHDSCD	114	/* GOVR HDSCD (?) */
+#define IRQ_GOVRHDMIF	115	/* GOVR HDMIF (?) */
+				/* Reserved */
+
+#define NR_IRQS		128
+
+#endif
diff --git a/arch/arm/mach-vt8500/include/mach/memory.h b/arch/arm/mach-vt8500/include/mach/memory.h
new file mode 100644
index 0000000..175f914
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/memory.h
@@ -0,0 +1,28 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/memory.h
+ *
+ *  Copyright (C) 2003 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET	UL(0x00000000)
+
+#endif
diff --git a/arch/arm/mach-vt8500/include/mach/system.h b/arch/arm/mach-vt8500/include/mach/system.h
new file mode 100644
index 0000000..0289fcc
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/system.h
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/mach-vt8500/include/mach/system.h
+ *
+ */
+#include <mach/hardware.h>
+#include <mach/vt8500.h>
+#include <asm/io.h>
+
+/* PM Software Reset request register */
+#define VT8500_PMSR_OFFSET	0x60
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	writel(1, ioremap(VT8500_PMC_BASE + VT8500_PMSR_OFFSET, 4));
+}
diff --git a/arch/arm/mach-vt8500/include/mach/timex.h b/arch/arm/mach-vt8500/include/mach/timex.h
new file mode 100644
index 0000000..8487e4c
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/timex.h
@@ -0,0 +1,26 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/timex.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef MACH_TIMEX_H
+#define MACH_TIMEX_H
+
+#define CLOCK_TICK_RATE		(3000000)
+
+#endif /* MACH_TIMEX_H */
diff --git a/arch/arm/mach-vt8500/include/mach/uncompress.h b/arch/arm/mach-vt8500/include/mach/uncompress.h
new file mode 100644
index 0000000..e5d6436
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/uncompress.h
@@ -0,0 +1,37 @@
+/* arch/arm/mach-vt8500/include/mach/uncompress.h
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on arch/arm/mach-dove/include/mach/uncompress.h
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <mach/vt8500.h>
+#include <asm/io.h>
+
+static void putc(const char c)
+{
+	while (readb(VT8500_UART0_BASE + 0x1c) & 0x2)
+		/* Tx busy, wait and poll */;
+
+	writeb(c, VT8500_UART0_BASE);
+}
+
+static void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-vt8500/include/mach/vmalloc.h b/arch/arm/mach-vt8500/include/mach/vmalloc.h
new file mode 100644
index 0000000..75a6912
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/vmalloc.h
@@ -0,0 +1,20 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/vmalloc.h
+ *
+ *  Copyright (C) 2000 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#define VMALLOC_END		(PAGE_OFFSET + 0x10000000)
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500.h b/arch/arm/mach-vt8500/include/mach/vt8500.h
new file mode 100644
index 0000000..e64a85b
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/vt8500.h
@@ -0,0 +1,143 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/vt8500.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARM_ARCH_VT8500_H
+#define __ASM_ARM_ARCH_VT8500_H
+
+#ifdef CONFIG_VTWM_VERSION_VT8500
+/* VT8500 Registers Map */
+
+#define VT8500_REGS_START_PHYS	0xd8000000	/* Start of MMIO registers */
+#define VT8500_REGS_START_VIRT	0xf8000000	/* Virtual mapping start */
+
+#define VT8500_DDR_BASE		0xd8000000	/* 1k	DDR/DDR2 Memory
+							Controller */
+#define VT8500_DMA_BASE		0xd8001000	/* 1k	DMA Controller */
+#define VT8500_SFLASH_BASE	0xd8002000	/* 1k	Serial Flash Memory
+							Controller */
+#define VT8500_ETHER_BASE	0xd8004000	/* 1k	Ethernet MAC 0 */
+#define VT8500_CIPHER_BASE	0xd8006000	/* 4k	Cipher */
+#define VT8500_USB_BASE		0xd8007800	/* 2k	USB OTG */
+# define VT8500_EHCI_BASE	0xd8007900	/*	EHCI */
+# define VT8500_UHCI_BASE	0xd8007b01	/*	UHCI */
+#define VT8500_PATA_BASE	0xd8008000	/* 512	PATA */
+#define VT8500_PS2_BASE		0xd8008800	/* 1k	PS/2 */
+#define VT8500_NAND_BASE	0xd8009000	/* 1k	NAND Controller */
+#define VT8500_NOR_BASE		0xd8009400	/* 1k	NOR Controller */
+#define VT8500_SDMMC_BASE	0xd800a000	/* 1k	SD/MMC Controller */
+#define VT8500_MS_BASE		0xd800b000	/* 1k	MS/MSPRO Controller */
+#define VT8500_LCDC_BASE	0xd800e400	/* 1k	LCD Controller */
+#define VT8500_VPU_BASE		0xd8050000	/* 256	VPU */
+#define VT8500_GOV_BASE		0xd8050300	/* 256	GOV */
+#define VT8500_GEGEA_BASE	0xd8050400	/* 768	GE/GE Alpha Mixing */
+#define VT8500_LCDF_BASE	0xd8050900	/* 256	LCD Formatter */
+#define VT8500_VID_BASE		0xd8050a00	/* 256	VID */
+#define VT8500_VPP_BASE		0xd8050b00	/* 256	VPP */
+#define VT8500_TSBK_BASE	0xd80f4000	/* 4k	TSBK */
+#define VT8500_JPEGDEC_BASE	0xd80fe000	/* 4k	JPEG Decoder */
+#define VT8500_JPEGENC_BASE	0xd80ff000	/* 4k	JPEG Encoder */
+#define VT8500_RTC_BASE		0xd8100000	/* 64k	RTC */
+#define VT8500_GPIO_BASE	0xd8110000	/* 64k	GPIO Configuration */
+#define VT8500_SCC_BASE		0xd8120000	/* 64k	System Configuration*/
+#define VT8500_PMC_BASE		0xd8130000	/* 64k	PMC Configuration */
+#define VT8500_IC_BASE		0xd8140000	/* 64k	Interrupt Controller*/
+#define VT8500_UART0_BASE	0xd8200000	/* 64k	UART 0 */
+#define VT8500_UART2_BASE	0xd8210000	/* 64k	UART 2 */
+#define VT8500_PWM_BASE		0xd8220000	/* 64k	PWM Configuration */
+#define VT8500_SPI0_BASE	0xd8240000	/* 64k	SPI 0 */
+#define VT8500_SPI1_BASE	0xd8250000	/* 64k	SPI 1 */
+#define VT8500_CIR_BASE		0xd8270000	/* 64k	CIR */
+#define VT8500_I2C0_BASE	0xd8280000	/* 64k	I2C 0 */
+#define VT8500_AC97_BASE	0xd8290000	/* 64k	AC97 */
+#define VT8500_SPI2_BASE	0xd82a0000	/* 64k	SPI 2 */
+#define VT8500_UART1_BASE	0xd82b0000	/* 64k	UART 1 */
+#define VT8500_UART3_BASE	0xd82c0000	/* 64k	UART 3 */
+#define VT8500_PCM_BASE		0xd82d0000	/* 64k	PCM */
+#define VT8500_I2C1_BASE	0xd8320000	/* 64k	I2C 1 */
+#define VT8500_I2S_BASE		0xd8330000	/* 64k	I2S */
+#define VT8500_ADC_BASE		0xd8340000	/* 64k	ADC */
+
+#define VT8500_REGS_END_PHYS	0xd834ffff	/* End of MMIO registers */
+#define VT8500_REGS_LENGTH	(VT8500_REGS_END_PHYS \
+				- VT8500_REGS_START_PHYS + 1)
+
+#elif defined CONFIG_VTWM_VERSION_WM8505
+/* WM8505 Registers Map */
+/* To be confirmed! */
+
+#define VT8500_REGS_START_PHYS	0xd8000000	/* Start of MMIO registers */
+#define VT8500_REGS_START_VIRT	0xf8000000	/* Virtual mapping start */
+
+#define VT8500_DDR_BASE		0xd8000400	/* 1k	DDR/DDR2 Memory
+							Controller */
+#define VT8500_DMA_BASE		0xd8001800	/* 1k	DMA Controller */
+#define VT8500_VDMA_BASE	0xd8001c00	/* 1k	VDMA */
+#define VT8500_SFLASH_BASE	0xd8002000	/* 1k	Serial Flash Memory
+							Controller */
+#define VT8500_ETHER_BASE	0xd8004000	/* 1k	Ethernet MAC 0 */
+#define VT8500_CIPHER_BASE	0xd8006000	/* 4k	Cipher */
+#define VT8500_USB_BASE		0xd8007000	/* 2k	USB 2.0 Host */
+# define VT8500_EHCI_BASE	0xd8007100	/*	EHCI */
+# define VT8500_UHCI_BASE	0xd8007301	/*	UHCI */
+#define VT8500_PS2_BASE		0xd8008800	/* 1k	PS/2 */
+#define VT8500_NAND_BASE	0xd8009000	/* 1k	NAND Controller */
+#define VT8500_NOR_BASE		0xd8009400	/* 1k	NOR Controller */
+#define VT8500_SDMMC_BASE	0xd800a000	/* 1k	SD/MMC Controller */
+#define VT8500_VPU_BASE		0xd8050000	/* 256	VPU */
+#define VT8500_GOV_BASE		0xd8050300	/* 256	GOV */
+#define VT8500_GEGEA_BASE	0xd8050400	/* 768	GE/GE Alpha Mixing */
+#define WM8505_GOVR_BASE	0xd8050800	/* 512	GOVR (frambuffer) */
+#define VT8500_VID_BASE		0xd8050a00	/* 256	VID */
+#define VT8500_VPP_BASE		0xd8050b00	/* 256	VPP */
+#define VT8500_TSBK_BASE	0xd80f4000	/* 4k	TSBK */
+#define VT8500_JPEGDEC_BASE	0xd80fe000	/* 4k	JPEG Decoder */
+#define VT8500_JPEGENC_BASE	0xd80ff000	/* 4k	JPEG Encoder */
+#define VT8500_RTC_BASE		0xd8100000	/* 64k	RTC */
+#define VT8500_GPIO_BASE	0xd8110000	/* 64k	GPIO Configuration */
+#define VT8500_SCC_BASE		0xd8120000	/* 64k	System Configuration*/
+#define VT8500_PMC_BASE		0xd8130000	/* 64k	PMC Configuration */
+#define VT8500_IC_BASE		0xd8140000	/* 64k	Interrupt Controller*/
+#define VT8500_SIC_BASE		0xd8150000	/* 64k	Secondary IC */
+#define VT8500_UART0_BASE	0xd8200000	/* 64k	UART 0 */
+#define VT8500_UART2_BASE	0xd8210000	/* 64k	UART 2 */
+#define VT8500_PWM_BASE		0xd8220000	/* 64k	PWM Configuration */
+#define VT8500_SPI0_BASE	0xd8240000	/* 64k	SPI 0 */
+#define VT8500_SPI1_BASE	0xd8250000	/* 64k	SPI 1 */
+#define VT8500_CIR_BASE		0xd8270000	/* 64k	CIR */
+#define VT8500_I2C0_BASE	0xd8280000	/* 64k	I2C 0 */
+#define VT8500_AC97_BASE	0xd8290000	/* 64k	AC97 */
+#define VT8500_SPI2_BASE	0xd82a0000	/* 64k	SPI 2 */
+#define VT8500_UART1_BASE	0xd82b0000	/* 64k	UART 1 */
+#define VT8500_UART3_BASE	0xd82c0000	/* 64k	UART 3 */
+#define VT8500_PCM_BASE		0xd82d0000	/* 64k	PCM */
+#define VT8500_I2C1_BASE	0xd8320000	/* 64k	I2C 1 */
+#define VT8500_I2S_BASE		0xd8330000	/* 64k	I2S */
+#define VT8500_ADC_BASE		0xd8340000	/* 64k	ADC */
+#define VT8500_UART4_BASE	0xd8370000	/* 64k	UART 4 */
+#define VT8500_UART5_BASE	0xd8380000	/* 64k	UART 5 */
+
+#define VT8500_REGS_END_PHYS	0xd838ffff	/* End of MMIO registers */
+#define VT8500_REGS_LENGTH	(VT8500_REGS_END_PHYS \
+				- VT8500_REGS_START_PHYS + 1)
+
+#endif
+
+#define VT8500_UART_SIZE	0x1040
+
+#endif
diff --git a/arch/arm/mach-vt8500/include/mach/vt8500fb.h b/arch/arm/mach-vt8500/include/mach/vt8500fb.h
new file mode 100644
index 0000000..cc7f25e
--- /dev/null
+++ b/arch/arm/mach-vt8500/include/mach/vt8500fb.h
@@ -0,0 +1,31 @@
+/*
+ *  VT8500/WM8505 Frame Buffer platform data definitions
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VT8500FB_H
+#define _VT8500FB_H
+
+#include <linux/fb.h>
+
+struct vt8500fb_platform_data {
+	struct fb_videomode	mode;
+	__u32			xres_virtual;
+	__u32			yres_virtual;
+	__u32			bpp;
+	unsigned long		video_mem_phys;
+	void			*video_mem_virt;
+	unsigned long		video_mem_len;
+};
+
+#endif /* _VT8500FB_H */
diff --git a/arch/arm/mach-vt8500/irq.c b/arch/arm/mach-vt8500/irq.c
new file mode 100644
index 0000000..ed84ef7
--- /dev/null
+++ b/arch/arm/mach-vt8500/irq.c
@@ -0,0 +1,126 @@
+/*
+ *  arch/arm/mach-vt8500/irq.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/vt8500.h>
+
+#define VT8500_IC_DCTR		0x40		/* Destination control
+						register, 64*u8 */
+#define VT8500_INT_ENABLE	(1 << 3)
+#define VT8500_TRIGGER_HIGH	(0 << 4)
+#define VT8500_TRIGGER_RISING	(1 << 4)
+#define VT8500_TRIGGER_FALLING	(2 << 4)
+#define VT8500_IC_STATUS	0x80		/* Interrupt status, 2*u32 */
+
+static void __iomem *ic_regbase;
+
+static void vt8500_irq_mask(unsigned int irq)
+{
+	u8 edge = readb(ic_regbase
+			+ VT8500_IC_DCTR + irq) & (3 << 4);
+	if (edge)
+		writel(readl(ic_regbase
+			+ VT8500_IC_STATUS + (irq < 32 ? 0 : 4))
+			| (1 << (irq & 0x1f)), ic_regbase
+			+ VT8500_IC_STATUS + (irq & 0x20 ? 4 : 0));
+	else
+		writeb(readb(ic_regbase
+			+ VT8500_IC_DCTR + irq) & ~VT8500_INT_ENABLE,
+			ic_regbase + VT8500_IC_DCTR + irq);
+}
+
+static void vt8500_irq_unmask(unsigned int irq)
+{
+	writeb(readb(ic_regbase
+		+ VT8500_IC_DCTR + irq) | VT8500_INT_ENABLE,
+		ic_regbase + VT8500_IC_DCTR + irq);
+}
+
+static int vt8500_irq_set_wake(unsigned int irq, unsigned int on)
+{
+	return -EINVAL;
+}
+
+static int vt8500_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+	switch (flow_type) {
+	case IRQF_TRIGGER_LOW:
+		return -EINVAL;
+	case IRQF_TRIGGER_HIGH:
+		writeb((readb(ic_regbase
+			+ VT8500_IC_DCTR + irq) & ~(3 << 4))
+			| VT8500_TRIGGER_HIGH, ic_regbase
+			+ VT8500_IC_DCTR + irq);
+		set_irq_handler(irq, handle_level_irq);
+		break;
+	case IRQF_TRIGGER_FALLING:
+		writeb((readb(ic_regbase
+			+ VT8500_IC_DCTR + irq) & ~(3 << 4))
+			| VT8500_TRIGGER_FALLING, ic_regbase
+			+ VT8500_IC_DCTR + irq);
+		set_irq_handler(irq, handle_edge_irq);
+		break;
+	case IRQF_TRIGGER_RISING:
+		writeb((readb(ic_regbase
+			+ VT8500_IC_DCTR + irq) & ~(3 << 4))
+			| VT8500_TRIGGER_RISING, ic_regbase
+			+ VT8500_IC_DCTR + irq);
+		set_irq_handler(irq, handle_edge_irq);
+		break;
+	}
+
+	return 0;
+}
+
+static struct irq_chip vt8500_irq_chip = {
+	.name      = "vt8500",
+	.ack       = vt8500_irq_mask,
+	.mask      = vt8500_irq_mask,
+	.unmask    = vt8500_irq_unmask,
+	.set_wake  = vt8500_irq_set_wake,
+	.set_type  = vt8500_irq_set_type,
+};
+
+void __init vt8500_init_irq(void)
+{
+	unsigned int i;
+
+	ic_regbase = ioremap(VT8500_IC_BASE, SZ_64K);
+
+	/* Enable rotating priority for IRQ */
+	writel((1 << 6), ic_regbase + 0x20);
+	writel(0, ic_regbase + 0x24);
+
+	for (i = 0; i < NR_IRQS; i++) {
+		/* Disable all interrupts and route them to IRQ */
+		writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
+
+		set_irq_chip(i, &vt8500_irq_chip);
+		set_irq_handler(i, handle_level_irq);
+		set_irq_flags(i, IRQF_VALID);
+	}
+}
diff --git a/arch/arm/mach-vt8500/pwm.c b/arch/arm/mach-vt8500/pwm.c
new file mode 100644
index 0000000..a33cc7e
--- /dev/null
+++ b/arch/arm/mach-vt8500/pwm.c
@@ -0,0 +1,250 @@
+/*
+ * arch/arm/mach-vt8500/pwm.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+
+#include <asm/div64.h>
+
+#define VT8500_NR_PWMS 4
+
+struct pwm_device {
+	struct list_head	node;
+	struct platform_device	*pdev;
+
+	const char	*label;
+
+	void __iomem	*regbase;
+
+	unsigned int	use_count;
+	unsigned int	pwm_id;
+};
+
+/*
+ * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
+ * duty_ns   = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+ */
+int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	unsigned long long c;
+	unsigned long period_cycles, prescale, pv, dc;
+
+	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
+		return -EINVAL;
+
+	c = 25000000/2; /* wild guess --- need to implement clocks */
+	c = c * period_ns;
+	do_div(c, 1000000000);
+	period_cycles = c;
+
+	if (period_cycles < 1)
+		period_cycles = 1;
+	prescale = (period_cycles - 1) / 4096;
+	pv = period_cycles / (prescale + 1) - 1;
+	if (pv > 4095)
+		pv = 4095;
+
+	if (prescale > 1023)
+		return -EINVAL;
+
+	dc = pv * duty_ns / period_ns;
+
+	while (readb(pwm->regbase + 0x40 + pwm->pwm_id))
+		/* busy-wait */;
+	writel(prescale, pwm->regbase + 0x4 + (pwm->pwm_id << 4));
+	while (readb(pwm->regbase + 0x40 + pwm->pwm_id))
+		/* busy-wait */;
+	writel(pv, pwm->regbase + 0x8 + (pwm->pwm_id << 4));
+	while (readb(pwm->regbase + 0x40 + pwm->pwm_id))
+		/* busy-wait */;
+	writel(dc, pwm->regbase + 0xc + (pwm->pwm_id << 4));
+
+	return 0;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+	writel(5, pwm->regbase + (pwm->pwm_id << 4));
+	return 0;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+	writel(0, pwm->regbase);
+}
+EXPORT_SYMBOL(pwm_disable);
+
+static DEFINE_MUTEX(pwm_lock);
+static LIST_HEAD(pwm_list);
+
+struct pwm_device *pwm_request(int pwm_id, const char *label)
+{
+	struct pwm_device *pwm;
+	int found = 0;
+
+	mutex_lock(&pwm_lock);
+
+	list_for_each_entry(pwm, &pwm_list, node) {
+		if (pwm->pwm_id == pwm_id) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (found) {
+		if (pwm->use_count == 0) {
+			pwm->use_count++;
+			pwm->label = label;
+		} else
+			pwm = ERR_PTR(-EBUSY);
+	} else
+		pwm = ERR_PTR(-ENOENT);
+
+	mutex_unlock(&pwm_lock);
+	return pwm;
+}
+EXPORT_SYMBOL(pwm_request);
+
+void pwm_free(struct pwm_device *pwm)
+{
+	mutex_lock(&pwm_lock);
+
+	if (pwm->use_count) {
+		pwm->use_count--;
+		pwm->label = NULL;
+	} else
+		pr_warning("PWM device already freed\n");
+
+	mutex_unlock(&pwm_lock);
+}
+EXPORT_SYMBOL(pwm_free);
+
+static inline void __add_pwm(struct pwm_device *pwm)
+{
+	mutex_lock(&pwm_lock);
+	list_add_tail(&pwm->node, &pwm_list);
+	mutex_unlock(&pwm_lock);
+}
+
+static int __devinit pwm_probe(struct platform_device *pdev)
+{
+	struct pwm_device *pwms;
+	struct resource *r;
+	int ret = 0;
+	int i;
+
+	pwms = kzalloc(sizeof(struct pwm_device) * VT8500_NR_PWMS, GFP_KERNEL);
+	if (pwms == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < VT8500_NR_PWMS; i++) {
+		pwms[i].use_count = 0;
+		pwms[i].pwm_id = i;
+		pwms[i].pdev = pdev;
+	}
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "no memory resource defined\n");
+		ret = -ENODEV;
+		goto err_free;
+	}
+
+	r = request_mem_region(r->start, resource_size(r), pdev->name);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "failed to request memory resource\n");
+		ret = -EBUSY;
+		goto err_free;
+	}
+
+	pwms[0].regbase = ioremap(r->start, resource_size(r));
+	if (pwms[0].regbase == NULL) {
+		dev_err(&pdev->dev, "failed to ioremap() registers\n");
+		ret = -ENODEV;
+		goto err_free_mem;
+	}
+
+	for (i = 1; i < VT8500_NR_PWMS; i++)
+		pwms[i].regbase = pwms[1].regbase;
+
+	for (i = 0; i < VT8500_NR_PWMS; i++)
+		__add_pwm(&pwms[i]);
+
+	platform_set_drvdata(pdev, pwms);
+	return 0;
+
+err_free_mem:
+	release_mem_region(r->start, resource_size(r));
+err_free:
+	kfree(pwms);
+	return ret;
+}
+
+static int __devexit pwm_remove(struct platform_device *pdev)
+{
+	struct pwm_device *pwms;
+	struct resource *r;
+	int i;
+
+	pwms = platform_get_drvdata(pdev);
+	if (pwms == NULL)
+		return -ENODEV;
+
+	mutex_lock(&pwm_lock);
+
+	for (i = 0; i < VT8500_NR_PWMS; i++)
+		list_del(&pwms[i].node);
+	mutex_unlock(&pwm_lock);
+
+	iounmap(pwms[0].regbase);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	kfree(pwms);
+	return 0;
+}
+
+static struct platform_driver pwm_driver = {
+	.driver		= {
+		.name	= "vt8500-pwm",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pwm_probe,
+	.remove		= __devexit_p(pwm_remove),
+};
+
+static int __init pwm_init(void)
+{
+	return platform_driver_register(&pwm_driver);
+}
+arch_initcall(pwm_init);
+
+static void __exit pwm_exit(void)
+{
+	platform_driver_unregister(&pwm_driver);
+}
+module_exit(pwm_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-vt8500/timer.c b/arch/arm/mach-vt8500/timer.c
new file mode 100644
index 0000000..b69f8f2
--- /dev/null
+++ b/arch/arm/mach-vt8500/timer.c
@@ -0,0 +1,192 @@
+/*
+ *  arch/arm/mach-vt8500/timer.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/cnt32_to_63.h>
+
+#include <asm/mach/time.h>
+#include <asm/io.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/vt8500.h>
+
+#define VT8500_TIMER_OFFSET	0x0100
+#define TIMER_MATCH_VAL		0x0000
+#define TIMER_COUNT_VAL		0x0010
+#define TIMER_STATUS_VAL	0x0014
+#define TIMER_IER_VAL		0x001c		/* interrupt enable */
+#define TIMER_CTRL_VAL		0x0020
+#define TIMER_AS_VAL		0x0024		/* access status */
+#define TIMER_COUNT_R_ACTIVE	(1 << 5)	/* not ready for read */
+#define TIMER_COUNT_W_ACTIVE	(1 << 4)	/* not ready for write */
+#define TIMER_MATCH_W_ACTIVE	(1 << 0)	/* not ready for write */
+#define VT8500_TIMER_HZ		3000000
+
+static void __iomem *regbase = NULL;
+
+unsigned long long sched_clock(void)
+{
+	unsigned long long v;
+
+	if (!regbase)
+		regbase = ioremap(VT8500_PMC_BASE + VT8500_TIMER_OFFSET, 0x28);
+
+	writel(0x3, regbase + TIMER_CTRL_VAL);
+	while (readl(regbase + TIMER_AS_VAL) & TIMER_COUNT_R_ACTIVE)
+		/* wait and poll */;
+
+	v = cnt32_to_63(readl(regbase + TIMER_COUNT_VAL));
+
+	/* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn*/
+	v *= 1000 << 1;		/* 3MHz timer tick implies 333ns resolution */
+	do_div(v, 3 << 1);
+
+	return v;
+}
+
+static int vt8500_timer_set_next_event(unsigned long cycles,
+				    struct clock_event_device *evt)
+{
+	unsigned long now, alarm;
+	int late;
+
+	writel(3, regbase + TIMER_CTRL_VAL);
+	while (readl(regbase + TIMER_AS_VAL) & TIMER_COUNT_R_ACTIVE)
+		/* wait and poll */;
+	now = readl(regbase + TIMER_COUNT_VAL);
+	alarm = now + cycles;
+	while (readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE)
+		/* wait and poll */;
+	writel(alarm, regbase + TIMER_MATCH_VAL);
+
+	writel(3, regbase + TIMER_CTRL_VAL);
+	while (readl(regbase + TIMER_AS_VAL) & TIMER_COUNT_R_ACTIVE)
+		/* wait and poll */;
+	now = readl(regbase + TIMER_COUNT_VAL);
+	late = now - alarm;
+	if (late >= (-2) && late < VT8500_TIMER_HZ*5)
+		return -ETIME;
+
+	writel(1, regbase + TIMER_IER_VAL);
+
+	return 0;
+}
+
+static void vt8500_timer_set_mode(enum clock_event_mode mode,
+			      struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		writel(readl(regbase + TIMER_CTRL_VAL) | 1,
+			regbase + TIMER_CTRL_VAL);
+		writel(0, regbase + TIMER_IER_VAL);
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		writel(readl(regbase + TIMER_CTRL_VAL) & ~1,
+			regbase + TIMER_CTRL_VAL);
+		break;
+	}
+}
+
+struct clock_event_device clockevent = {
+	.name           = "vt8500_timer",
+	.features       = CLOCK_EVT_FEAT_ONESHOT,
+	.rating         = 200,
+	.set_next_event = vt8500_timer_set_next_event,
+	.set_mode       = vt8500_timer_set_mode,
+};
+
+static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+	writel(0xf, regbase + TIMER_STATUS_VAL);
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static cycle_t vt8500_timer_read(struct clocksource *cs)
+{
+	writel(3, regbase + TIMER_CTRL_VAL);
+	while (readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE)
+		/* wait and poll */;
+	return readl(regbase + TIMER_COUNT_VAL);
+}
+
+struct clocksource clocksource = {
+	.name           = "vt8500_timer",
+	.rating         = 200,
+	.read           = vt8500_timer_read,
+	.mask           = CLOCKSOURCE_MASK(32),
+	.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+struct irqaction irq = {
+	.name    = "vt8500_timer",
+	.flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler = vt8500_timer_interrupt,
+	.dev_id  = &clockevent,
+};
+
+static void __init vt8500_timer_init(void)
+{
+	int res;
+
+	struct clock_event_device *ce = &clockevent;
+	struct clocksource *cs = &clocksource;
+
+	if (!regbase)
+		regbase = ioremap(VT8500_PMC_BASE + VT8500_TIMER_OFFSET, 0x28);
+	writel(1, regbase + TIMER_CTRL_VAL);
+	writel(0xf, regbase + TIMER_STATUS_VAL);
+	writel(~0, regbase + TIMER_MATCH_VAL);
+
+	clockevents_calc_mult_shift(ce, VT8500_TIMER_HZ, 4);
+	clocksource_calc_mult_shift(cs, VT8500_TIMER_HZ, 4);
+
+	/* copy-pasted from mach-msm; no idea */
+	ce->max_delta_ns =
+		clockevent_delta2ns(0xf0000000, ce);
+	ce->min_delta_ns = clockevent_delta2ns(4, ce);
+	ce->cpumask = cpumask_of(0);
+
+	res = clocksource_register(cs);
+	if (res)
+		printk(KERN_ERR "vt8500_timer_init: clocksource_register "
+			"failed for %s\n", cs->name);
+
+	res = setup_irq(IRQ_PMCOS0, &irq);
+
+	if (res)
+		printk(KERN_ERR "vt8500_timer_init: setup_irq "
+			"failed for %s\n", cs->name);
+	clockevents_register_device(ce);
+}
+
+struct sys_timer vt8500_timer = {
+	.init = vt8500_timer_init
+};
diff --git a/arch/arm/mach-vt8500/wm8505_7in.c b/arch/arm/mach-vt8500/wm8505_7in.c
new file mode 100644
index 0000000..04e53ca
--- /dev/null
+++ b/arch/arm/mach-vt8500/wm8505_7in.c
@@ -0,0 +1,81 @@
+/*
+ *  arch/arm/mach-vt8500/wm8505_7in.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <linux/io.h>
+#include <linux/pm.h>
+
+#include <mach/vt8500.h>
+#include "devices.h"
+
+static struct platform_device *devices[] __initdata = {
+	&vt8500_device_uart0,
+#ifdef CONFIG_USB_EHCI_HCD
+	&vt8500_device_ehci,
+#endif
+#ifdef CONFIG_FB_WM8505
+	&vt8500_device_wm8505_fb,
+#endif
+#ifdef CONFIG_FB_WMT_GE_ROPS
+	&vt8500_device_ge_rops,
+#endif
+#ifdef CONFIG_HAVE_PWM
+	&vt8500_device_pwm,
+#endif
+#ifdef CONFIG_BACKLIGHT_PWM
+	&vt8500_device_pwmbl,
+#endif
+#ifdef CONFIG_RTC_DRV_VT8500
+	&vt8500_device_rtc,
+#endif
+};
+
+static void vt8500_power_off(void)
+{
+	void __iomem *pmc_hiber = ioremap(VT8500_PMC_BASE + 0x12, 2);
+	local_irq_disable();
+	writew(5, pmc_hiber);
+	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
+}
+
+void __init wm8505_7in_init(void)
+{
+#ifdef CONFIG_FB_WM8505
+	void __iomem *gpio_mux_reg = ioremap(VT8500_GPIO_BASE + 0x200, 4);
+
+	writel(readl(gpio_mux_reg) | 0x80000000, gpio_mux_reg);
+	iounmap(gpio_mux_reg);
+#endif
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+	vt8500_gpio_init();
+	pm_power_off = &vt8500_power_off;
+}
+
+MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
+	.phys_io	= VT8500_REGS_START_PHYS,
+	.io_pg_offst	= ((VT8500_REGS_START_VIRT) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.map_io		= vt8500_map_io,
+	.init_irq	= vt8500_init_irq,
+	.timer		= &vt8500_timer,
+	.init_machine	= wm8505_7in_init,
+MACHINE_END
-- 
1.7.3.1


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

* [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles
  2010-10-20 20:55 [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Alexey Charkov
@ 2010-10-20 20:55 ` Alexey Charkov
  2010-10-20 21:16   ` Greg KH
  2010-10-20 20:55 ` [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042 Alexey Charkov
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 20:55 UTC (permalink / raw)
  To: vt8500-wm8505-linux-kernel
  Cc: linux-arm-kernel, Alexey Charkov, Greg Kroah-Hartman, linux-kernel

This adds a driver for the serial ports found in VIA and WonderMedia
Systems-on-Chip. Interrupt-driven FIFO operation is implemented.
The hardware also supports pure register-based operation (which is
slower) and DMA-based FIFO operation. As the FIFOs are only 16 bytes
long, DMA operation is probably not worth the hassle.

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---

Please review and state whether this could be acceptable for a merge
to mainline in the coming 2.6.37 window. If possible, I would deeply
appreciate a merge to a relevant git tree for integration prior to
asking Linus to pull the changes. I could rebase the code if needed,
currently this is against Linus' master branch.

This patch relies on the basic architecture support for VT8500/WM8505
to be in place, as introduced by PATCH 1/6 in this series.

Due credits go to the community for providing feedback, advice and
testing.

NB: The development is being done at:
http://gitorious.org/linux-on-via-vt8500/vt8500-kernel

Relevant code may be pulled from a git tree in there.

 drivers/serial/Kconfig         |   10 +
 drivers/serial/Makefile        |    1 +
 drivers/serial/vt8500_serial.c |  637 ++++++++++++++++++++++++++++++++++++++++
 include/linux/serial_core.h    |    3 +
 4 files changed, 651 insertions(+), 0 deletions(-)
 create mode 100644 drivers/serial/vt8500_serial.c

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 12900f7..a04e6b3 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1387,6 +1387,16 @@ config SERIAL_MSM_CONSOLE
 	depends on SERIAL_MSM=y
 	select SERIAL_CORE_CONSOLE
 
+config SERIAL_VT8500
+	bool "VIA VT8500 on-chip serial port support"
+	depends on ARM && ARCH_VT8500
+	select SERIAL_CORE
+
+config SERIAL_VT8500_CONSOLE
+	bool "VIA VT8500 serial console support"
+	depends on SERIAL_VT8500=y
+	select SERIAL_CORE_CONSOLE
+
 config SERIAL_NETX
 	tristate "NetX serial port support"
 	depends on ARM && ARCH_NETX
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 1ca4fd5..d7c836c 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -86,5 +86,6 @@ obj-$(CONFIG_SERIAL_TIMBERDALE)	+= timbuart.o
 obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o
 obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
 obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
+obj-$(CONFIG_SERIAL_VT8500) += vt8500_serial.o
 obj-$(CONFIG_SERIAL_MRST_MAX3110)	+= mrst_max3110.o
 obj-$(CONFIG_SERIAL_MFD_HSU)	+= mfd.o
diff --git a/drivers/serial/vt8500_serial.c b/drivers/serial/vt8500_serial.c
new file mode 100644
index 0000000..329aff7
--- /dev/null
+++ b/drivers/serial/vt8500_serial.c
@@ -0,0 +1,637 @@
+/*
+ * drivers/serial/vt8500_serial.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on msm_serial.c, which is:
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Robert Love <rlove@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#if defined(CONFIG_SERIAL_VT8500_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+# define SUPPORT_SYSRQ
+#endif
+
+#include <linux/hrtimer.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+/*
+ * UART Register offsets
+ */
+
+#define VT8500_URTDR		0x0000	/* Transmit data */
+#define VT8500_URRDR		0x0004	/* Receive data */
+#define VT8500_URDIV		0x0008	/* Clock/Baud rate divisor */
+#define VT8500_URLCR		0x000C	/* Line control */
+#define VT8500_URICR		0x0010	/* IrDA control */
+#define VT8500_URIER		0x0014	/* Interrupt enable */
+#define VT8500_URISR		0x0018	/* Interrupt status */
+#define VT8500_URUSR		0x001c	/* UART status */
+#define VT8500_URFCR		0x0020	/* FIFO control */
+#define VT8500_URFIDX		0x0024	/* FIFO index */
+#define VT8500_URBKR		0x0028	/* Break signal count */
+#define VT8500_URTOD		0x002c	/* Time out divisor */
+#define VT8500_TXFIFO		0x1000	/* Transmit FIFO (16x8) */
+#define VT8500_RXFIFO		0x1020	/* Receive FIFO (16x10) */
+
+/*
+ * Interrupt enable and status bits
+ */
+
+#define TXDE	(1 << 0)	/* Tx Data empty */
+#define RXDF	(1 << 1)	/* Rx Data full */
+#define TXFAE	(1 << 2)	/* Tx FIFO almost empty */
+#define TXFE	(1 << 3)	/* Tx FIFO empty */
+#define RXFAF	(1 << 4)	/* Rx FIFO almost full */
+#define RXFF	(1 << 5)	/* Rx FIFO full */
+#define TXUDR	(1 << 6)	/* Tx underrun */
+#define RXOVER	(1 << 7)	/* Rx overrun */
+#define PER	(1 << 8)	/* Parity error */
+#define FER	(1 << 9)	/* Frame error */
+#define TCTS	(1 << 10)	/* Toggle of CTS */
+#define RXTOUT	(1 << 11)	/* Rx timeout */
+#define BKDONE	(1 << 12)	/* Break signal done */
+#define ERR	(1 << 13)	/* AHB error response */
+
+#define RX_FIFO_INTS	(RXFAF | RXFF | RXOVER | PER | FER | RXTOUT)
+#define TX_FIFO_INTS	(TXFAE | TXFE | TXUDR)
+
+struct vt8500_port {
+	struct uart_port	uart;
+	char			name[16];
+	struct clk		*clk;
+	unsigned int		ier;
+};
+
+static inline void vt8500_write(struct uart_port *port, unsigned int val,
+			     unsigned int off)
+{
+	writel(val, port->membase + off);
+}
+
+static inline unsigned int vt8500_read(struct uart_port *port, unsigned int off)
+{
+	return readl(port->membase + off);
+}
+
+static void vt8500_stop_tx(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port = container_of(port,
+						       struct vt8500_port,
+						       uart);
+
+	vt8500_port->ier &= ~TX_FIFO_INTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+}
+
+static void vt8500_stop_rx(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port = container_of(port,
+						       struct vt8500_port,
+						       uart);
+
+	vt8500_port->ier &= ~RX_FIFO_INTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+}
+
+static void vt8500_enable_ms(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port = container_of(port,
+						       struct vt8500_port,
+						       uart);
+
+	vt8500_port->ier |= TCTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+}
+
+static void handle_rx(struct uart_port *port)
+{
+	struct tty_struct *tty = port->state->port.tty;
+
+	/*
+	 * Handle overrun
+	 */
+	if ((vt8500_read(port, VT8500_URISR) & RXOVER)) {
+		port->icount.overrun++;
+		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+	}
+
+	/* and now the main RX loop */
+	while (vt8500_read(port, VT8500_URFIDX) & 0x1f00) {
+		unsigned int c;
+		char flag = TTY_NORMAL;
+
+		c = readw(port->membase + VT8500_RXFIFO) & 0x3ff;
+
+		/* Mask conditions we're ignorning. */
+		c &= ~port->read_status_mask;
+
+		if (c & FER) {
+			port->icount.frame++;
+			flag = TTY_FRAME;
+		} else if (c & PER) {
+			port->icount.parity++;
+			flag = TTY_PARITY;
+		}
+		port->icount.rx++;
+
+		if (!uart_handle_sysrq_char(port, c))
+			tty_insert_flip_char(tty, c, flag);
+	}
+
+	tty_flip_buffer_push(tty);
+}
+
+static void handle_tx(struct uart_port *port)
+{
+	struct circ_buf *xmit = &port->state->xmit;
+
+	if (port->x_char) {
+		writeb(port->x_char, port->membase + VT8500_TXFIFO);
+		port->icount.tx++;
+		port->x_char = 0;
+	}
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		vt8500_stop_tx(port);
+		return;
+	}
+
+	while ((vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16) {
+		if (uart_circ_empty(xmit))
+			break;
+
+		writeb(xmit->buf[xmit->tail], port->membase + VT8500_TXFIFO);
+
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+	}
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		vt8500_stop_tx(port);
+}
+
+static void vt8500_start_tx(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port = container_of(port,
+						       struct vt8500_port,
+						       uart);
+
+	vt8500_port->ier &= ~TX_FIFO_INTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+	handle_tx(port);
+	vt8500_port->ier |= TX_FIFO_INTS;
+	vt8500_write(port, vt8500_port->ier, VT8500_URIER);
+}
+
+static void handle_delta_cts(struct uart_port *port)
+{
+	port->icount.cts++;
+	wake_up_interruptible(&port->state->port.delta_msr_wait);
+}
+
+static irqreturn_t vt8500_irq(int irq, void *dev_id)
+{
+	struct uart_port *port = dev_id;
+	unsigned long isr;
+
+	spin_lock(&port->lock);
+	isr = vt8500_read(port, VT8500_URISR);
+
+	/* Acknowledge active status bits */
+	vt8500_write(port, isr, VT8500_URISR);
+
+	if (isr & RX_FIFO_INTS)
+		handle_rx(port);
+	if (isr & TX_FIFO_INTS)
+		handle_tx(port);
+	if (isr & TCTS)
+		handle_delta_cts(port);
+
+	spin_unlock(&port->lock);
+
+	return IRQ_HANDLED;
+}
+
+static unsigned int vt8500_tx_empty(struct uart_port *port)
+{
+	return (vt8500_read(port, VT8500_URFIDX) & 0x1f) < 16 ?
+						TIOCSER_TEMT : 0;
+}
+
+static unsigned int vt8500_get_mctrl(struct uart_port *port)
+{
+	unsigned int usr;
+
+	usr = vt8500_read(port, VT8500_URUSR);
+	if (usr & (1 << 4))
+		return TIOCM_CTS;
+	else
+		return 0;
+}
+
+static void vt8500_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+static void vt8500_break_ctl(struct uart_port *port, int break_ctl)
+{
+	if (break_ctl)
+		vt8500_write(port, vt8500_read(port, VT8500_URLCR) | (1 << 9),
+			     VT8500_URLCR);
+}
+
+static int vt8500_set_baud_rate(struct uart_port *port, unsigned int baud)
+{
+	unsigned long div;
+
+	div = vt8500_read(port, VT8500_URDIV) & ~(0x3ff);
+
+	if (unlikely((baud < 900) || (baud > 921600)))
+		div |= 7;
+	else
+		div |= (921600 / baud) - 1;
+
+	while (vt8500_read(port, VT8500_URUSR) & (1 << 5))
+		;
+	vt8500_write(port, div, VT8500_URDIV);
+
+	return baud;
+}
+
+static int vt8500_startup(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port =
+			container_of(port, struct vt8500_port, uart);
+	int ret;
+
+	snprintf(vt8500_port->name, sizeof(vt8500_port->name),
+		 "vt8500_serial%d", port->line);
+
+	ret = request_irq(port->irq, vt8500_irq, IRQF_TRIGGER_HIGH,
+			  vt8500_port->name, port);
+	if (unlikely(ret))
+		return ret;
+
+	vt8500_write(port, 0x03, VT8500_URLCR);	/* enable TX & RX */
+
+	return 0;
+}
+
+static void vt8500_shutdown(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port =
+			container_of(port, struct vt8500_port, uart);
+
+	vt8500_port->ier = 0;
+
+	/* disable interrupts and FIFOs */
+	vt8500_write(&vt8500_port->uart, 0, VT8500_URIER);
+	vt8500_write(&vt8500_port->uart, 0x880, VT8500_URFCR);
+	free_irq(port->irq, port);
+}
+
+static void vt8500_set_termios(struct uart_port *port,
+			       struct ktermios *termios,
+			       struct ktermios *old)
+{
+	struct vt8500_port *vt8500_port =
+			container_of(port, struct vt8500_port, uart);
+	unsigned long flags;
+	unsigned int baud, lcr;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* calculate and set baud rate */
+	baud = uart_get_baud_rate(port, termios, old, 900, 921600);
+	baud = vt8500_set_baud_rate(port, baud);
+	if (tty_termios_baud_rate(termios))
+		tty_termios_encode_baud_rate(termios, baud, baud);
+
+	/* calculate parity */
+	lcr = vt8500_read(&vt8500_port->uart, VT8500_URLCR);
+	lcr &= ~((1 << 5) | (1 << 4));
+	if (termios->c_cflag & PARENB) {
+		lcr |= (1 << 4);
+		if (termios->c_cflag & PARODD)
+			lcr |= (1 << 5);
+	}
+
+	/* calculate bits per char */
+	lcr &= ~(1 << 2);
+	switch (termios->c_cflag & CSIZE) {
+	case CS7:
+		break;
+	case CS8:
+	default:
+		lcr |= (1 << 2);
+		break;
+	}
+
+	/* calculate stop bits */
+	lcr &= ~(1 << 3);
+	if (termios->c_cflag & CSTOPB)
+		lcr |= (1 << 3);
+
+	/* set parity, bits per char, and stop bit */
+	vt8500_write(&vt8500_port->uart, lcr, VT8500_URLCR);
+
+	/* Configure status bits to ignore based on termio flags. */
+	port->read_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->read_status_mask = FER | PER;
+
+	uart_update_timeout(port, termios->c_cflag, baud);
+
+	/* Reset FIFOs */
+	vt8500_write(&vt8500_port->uart, 0x88c, VT8500_URFCR);
+	while (vt8500_read(&vt8500_port->uart, VT8500_URFCR) & 0xc)
+		/* Wait for the reset to complete */;
+
+	/* Every possible FIFO-related interrupt */
+	vt8500_port->ier = RX_FIFO_INTS | TX_FIFO_INTS;
+
+	/*
+	 * CTS flow control
+	 */
+	if (UART_ENABLE_MS(&vt8500_port->uart, termios->c_cflag))
+		vt8500_port->ier |= TCTS;
+
+	vt8500_write(&vt8500_port->uart, 0x881, VT8500_URFCR);
+	vt8500_write(&vt8500_port->uart, vt8500_port->ier, VT8500_URIER);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static const char *vt8500_type(struct uart_port *port)
+{
+	struct vt8500_port *vt8500_port =
+			container_of(port, struct vt8500_port, uart);
+	return vt8500_port->name;
+}
+
+static void vt8500_release_port(struct uart_port *port)
+{
+}
+
+static int vt8500_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+static void vt8500_config_port(struct uart_port *port, int flags)
+{
+	port->type = PORT_VT8500;
+}
+
+static int vt8500_verify_port(struct uart_port *port,
+			      struct serial_struct *ser)
+{
+	if (unlikely(ser->type != PORT_UNKNOWN && ser->type != PORT_VT8500))
+		return -EINVAL;
+	if (unlikely(port->irq != ser->irq))
+		return -EINVAL;
+	return 0;
+}
+
+static struct vt8500_port *vt8500_uart_ports[4];
+static struct uart_driver vt8500_uart_driver;
+
+#ifdef CONFIG_SERIAL_VT8500_CONSOLE
+
+static inline void wait_for_xmitr(struct uart_port *port)
+{
+	unsigned int status, tmout = 10000;
+
+	/* Wait up to 10ms for the character(s) to be sent. */
+	do {
+		status = vt8500_read(port, VT8500_URFIDX);
+
+		if (--tmout == 0)
+			break;
+		udelay(1);
+	} while (status & 0x10);
+}
+
+static void vt8500_console_putchar(struct uart_port *port, int c)
+{
+	wait_for_xmitr(port);
+	writeb(c, port->membase + VT8500_TXFIFO);
+}
+
+static void vt8500_console_write(struct console *co, const char *s,
+			      unsigned int count)
+{
+	struct vt8500_port *vt8500_port = vt8500_uart_ports[co->index];
+	unsigned long ier;
+
+	BUG_ON(co->index < 0 || co->index >= vt8500_uart_driver.nr);
+
+	ier = vt8500_read(&vt8500_port->uart, VT8500_URIER);
+	vt8500_write(&vt8500_port->uart, VT8500_URIER, 0);
+
+	uart_console_write(&vt8500_port->uart, s, count,
+			   vt8500_console_putchar);
+
+	/*
+	 *	Finally, wait for transmitter to become empty
+	 *	and switch back to FIFO
+	 */
+	wait_for_xmitr(&vt8500_port->uart);
+	vt8500_write(&vt8500_port->uart, VT8500_URIER, ier);
+}
+
+static int __init vt8500_console_setup(struct console *co, char *options)
+{
+	struct vt8500_port *vt8500_port;
+	int baud = 9600;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+
+	if (unlikely(co->index >= vt8500_uart_driver.nr || co->index < 0))
+		return -ENXIO;
+
+	vt8500_port = vt8500_uart_ports[co->index];
+
+	if (!vt8500_port)
+		return -ENODEV;
+
+	if (options)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(&vt8500_port->uart,
+				 co, baud, parity, bits, flow);
+}
+
+static struct console vt8500_console = {
+	.name = "ttyS",
+	.write = vt8500_console_write,
+	.device = uart_console_device,
+	.setup = vt8500_console_setup,
+	.flags = CON_PRINTBUFFER,
+	.index = -1,
+	.data = &vt8500_uart_driver,
+};
+
+#define VT8500_CONSOLE	(&vt8500_console)
+
+#else
+#define VT8500_CONSOLE	NULL
+#endif
+
+static struct uart_ops vt8500_uart_pops = {
+	.tx_empty	= vt8500_tx_empty,
+	.set_mctrl	= vt8500_set_mctrl,
+	.get_mctrl	= vt8500_get_mctrl,
+	.stop_tx	= vt8500_stop_tx,
+	.start_tx	= vt8500_start_tx,
+	.stop_rx	= vt8500_stop_rx,
+	.enable_ms	= vt8500_enable_ms,
+	.break_ctl	= vt8500_break_ctl,
+	.startup	= vt8500_startup,
+	.shutdown	= vt8500_shutdown,
+	.set_termios	= vt8500_set_termios,
+	.type		= vt8500_type,
+	.release_port	= vt8500_release_port,
+	.request_port	= vt8500_request_port,
+	.config_port	= vt8500_config_port,
+	.verify_port	= vt8500_verify_port,
+};
+
+static struct uart_driver vt8500_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "vt8500_serial",
+	.dev_name	= "ttyS",
+	.major		= 4,
+	.minor		= 64,
+	.nr		= 4,
+	.cons		= VT8500_CONSOLE,
+};
+
+static int __init vt8500_serial_probe(struct platform_device *pdev)
+{
+	struct vt8500_port *vt8500_port;
+	struct resource *mmres, *irqres;
+	int ret;
+
+	mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mmres || !irqres)
+		return -ENODEV;
+
+	vt8500_port = kzalloc(sizeof(struct vt8500_port), GFP_KERNEL);
+	if (!vt8500_port)
+		return -ENOMEM;
+
+	vt8500_port->uart.type = PORT_VT8500;
+	vt8500_port->uart.iotype = UPIO_MEM;
+	vt8500_port->uart.mapbase = mmres->start;
+	vt8500_port->uart.irq = irqres->start;
+	vt8500_port->uart.fifosize = 16;
+	vt8500_port->uart.ops = &vt8500_uart_pops;
+	vt8500_port->uart.line = pdev->id;
+	vt8500_port->uart.dev = &pdev->dev;
+	vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
+	vt8500_port->uart.uartclk = 24000000;
+
+	snprintf(vt8500_port->name, sizeof(vt8500_port->name),
+		 "VT8500 UART%d", pdev->id);
+
+	vt8500_port->uart.membase = ioremap(mmres->start,
+					    mmres->end - mmres->start + 1);
+	if (!vt8500_port->uart.membase) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	vt8500_uart_ports[pdev->id] = vt8500_port;
+
+	uart_add_one_port(&vt8500_uart_driver, &vt8500_port->uart);
+
+	platform_set_drvdata(pdev, vt8500_port);
+
+	return 0;
+
+err:
+	kfree(vt8500_port);
+	return ret;
+}
+
+static int __devexit vt8500_serial_remove(struct platform_device *pdev)
+{
+	struct vt8500_port *vt8500_port = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	uart_remove_one_port(&vt8500_uart_driver, &vt8500_port->uart);
+	kfree(vt8500_port);
+
+	return 0;
+}
+
+static struct platform_driver vt8500_platform_driver = {
+	.probe  = vt8500_serial_probe,
+	.remove = vt8500_serial_remove,
+	.driver = {
+		.name = "vt8500_serial",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init vt8500_serial_init(void)
+{
+	int ret;
+
+	ret = uart_register_driver(&vt8500_uart_driver);
+	if (unlikely(ret))
+		return ret;
+
+	ret = platform_driver_register(&vt8500_platform_driver);
+
+	if (unlikely(ret))
+		uart_unregister_driver(&vt8500_uart_driver);
+
+	printk(KERN_INFO "vt8500_serial: driver initialized\n");
+
+	return ret;
+}
+
+static void __exit vt8500_serial_exit(void)
+{
+#ifdef CONFIG_SERIAL_VT8500_CONSOLE
+	unregister_console(&vt8500_console);
+#endif
+	platform_driver_unregister(&vt8500_platform_driver);
+	uart_unregister_driver(&vt8500_uart_driver);
+}
+
+module_init(vt8500_serial_init);
+module_exit(vt8500_serial_exit);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
+MODULE_DESCRIPTION("Driver for vt8500 serial device");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 563e234..d641853 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -196,6 +196,9 @@
 /* High Speed UART for Medfield */
 #define PORT_MFD	95
 
+/* VIA VT8500 SoC */
+#define PORT_VT8500	96
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
-- 
1.7.3.1


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

* [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042
  2010-10-20 20:55 [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Alexey Charkov
  2010-10-20 20:55 ` [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles Alexey Charkov
@ 2010-10-20 20:55 ` Alexey Charkov
  2010-10-20 21:15   ` Dmitry Torokhov
  2010-10-30 22:23   ` [PATCH 3/6] " Ben Dooks
  2010-10-20 20:55 ` [PATCH 4/6] usb: Add support for VIA VT8500 and compatibles in EHCI HCD Alexey Charkov
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 20:55 UTC (permalink / raw)
  To: vt8500-wm8505-linux-kernel
  Cc: linux-arm-kernel, Alexey Charkov, Dmitry Torokhov, linux-input,
	linux-kernel

VIA and WonderMedia Systems-on-Chip feature a standard i8042-compatible
keyboard and mouse controller. This adds necessary glue to enable use
of the standard driver with these systems.

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---

Please review and state whether this could be acceptable for a merge
to mainline in the coming 2.6.37 window. If possible, I would deeply
appreciate a merge to a relevant git tree for integration prior to
asking Linus to pull the changes. I could rebase the code if needed,
currently this is against Linus' master branch.

This patch relies on the basic architecture support for VT8500/WM8505
to be in place, as introduced by PATCH 1/6 in this series.

Due credits go to the community for providing feedback, advice and
testing.

NB: The development is being done at:
http://gitorious.org/linux-on-via-vt8500/vt8500-kernel

Relevant code may be pulled from a git tree in there.

 drivers/input/serio/Kconfig        |    3 +-
 drivers/input/serio/i8042-vt8500.h |   71 ++++++++++++++++++++++++++++++++++++
 drivers/input/serio/i8042.h        |    2 +
 3 files changed, 75 insertions(+), 1 deletions(-)
 create mode 100644 drivers/input/serio/i8042-vt8500.h

diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 3bfe8fa..2b86774 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -21,7 +21,8 @@ if SERIO
 config SERIO_I8042
 	tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
 	default y
-	depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
+	depends on !PARISC && \
+		  (!ARM || ARCH_SHARK || ARCH_VT8500 || FOOTBRIDGE_HOST) && \
 		   (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN
 	help
 	  i8042 is the chip over which the standard AT keyboard and PS/2
diff --git a/drivers/input/serio/i8042-vt8500.h b/drivers/input/serio/i8042-vt8500.h
new file mode 100644
index 0000000..d30df82
--- /dev/null
+++ b/drivers/input/serio/i8042-vt8500.h
@@ -0,0 +1,71 @@
+#ifndef _I8042_VT8500_H
+#define _I8042_VT8500_H
+
+#include <mach/irqs.h>
+#include <mach/vt8500.h>
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+static void __iomem *regbase;
+
+/*
+ * Names.
+ */
+
+#define I8042_KBD_PHYS_DESC "vt8500ps2/serio0"
+#define I8042_AUX_PHYS_DESC "vt8500ps2/serio1"
+#define I8042_MUX_PHYS_DESC "vt8500ps2/serio%d"
+
+/*
+ * IRQs.
+ */
+
+#define I8042_KBD_IRQ	IRQ_PS2KBD
+#define I8042_AUX_IRQ	IRQ_PS2MOUSE
+
+
+/*
+ * Register numbers.
+ */
+
+#define I8042_COMMAND_REG	(regbase + 0x4)
+#define I8042_STATUS_REG	(regbase + 0x4)
+#define I8042_DATA_REG		(regbase + 0x0)
+
+static inline int i8042_read_data(void)
+{
+	return readl(I8042_DATA_REG);
+}
+
+static inline int i8042_read_status(void)
+{
+	return readl(I8042_STATUS_REG);
+}
+
+static inline void i8042_write_data(int val)
+{
+	writel(val, I8042_DATA_REG);
+}
+
+static inline void i8042_write_command(int val)
+{
+	writel(val, I8042_COMMAND_REG);
+}
+
+static inline int i8042_platform_init(void)
+{
+	i8042_reset = 1;
+	regbase = ioremap(VT8500_PS2_BASE, SZ_1K);
+	return 0;
+}
+
+static inline void i8042_platform_exit(void)
+{
+	iounmap(regbase);
+}
+
+#endif /* _I8042_VT8500_H */
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
index cbc1beb..bdb2aeb 100644
--- a/drivers/input/serio/i8042.h
+++ b/drivers/input/serio/i8042.h
@@ -16,6 +16,8 @@
 
 #if defined(CONFIG_MACH_JAZZ)
 #include "i8042-jazzio.h"
+#elif defined(CONFIG_ARCH_VT8500)
+#include "i8042-vt8500.h"
 #elif defined(CONFIG_SGI_HAS_I8042)
 #include "i8042-ip22io.h"
 #elif defined(CONFIG_SNI_RM)
-- 
1.7.3.1


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

* [PATCH 4/6] usb: Add support for VIA VT8500 and compatibles in EHCI HCD
  2010-10-20 20:55 [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Alexey Charkov
  2010-10-20 20:55 ` [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles Alexey Charkov
  2010-10-20 20:55 ` [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042 Alexey Charkov
@ 2010-10-20 20:55 ` Alexey Charkov
  2010-10-20 21:17   ` Greg KH
  2010-10-20 20:55 ` [PATCH 5/6] rtc: Add support for the RTC in VIA VT8500 and compatibles Alexey Charkov
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 20:55 UTC (permalink / raw)
  To: vt8500-wm8505-linux-kernel
  Cc: linux-arm-kernel, Alexey Charkov, Greg Kroah-Hartman,
	David Brownell, linux-usb, linux-kernel

VIA and WonderMedia Systems-on-Chip feature a standard EHCI host
controller. This adds necessary glue to use the standard driver
with these systems.

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---

Please review and state whether this could be acceptable for a merge
to mainline in the coming 2.6.37 window. If possible, I would deeply
appreciate a merge to a relevant git tree for integration prior to
asking Linus to pull the changes. I could rebase the code if needed,
currently this is against Linus' master branch.

This patch relies on the basic architecture support for VT8500/WM8505
to be in place, as introduced by PATCH 1/6 in this series.

Due credits go to the community for providing feedback, advice and
testing.

NB: The development is being done at:
http://gitorious.org/linux-on-via-vt8500/vt8500-kernel

Relevant code may be pulled from a git tree in there.

 drivers/usb/Kconfig            |    1 +
 drivers/usb/host/ehci-hcd.c    |    5 +
 drivers/usb/host/ehci-vt8500.c |  173 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 179 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/host/ehci-vt8500.c

diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 4aa00e6..6858637 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -65,6 +65,7 @@ config USB_ARCH_HAS_EHCI
 	default y if ARCH_AT91SAM9G45
 	default y if ARCH_MXC
 	default y if ARCH_OMAP3
+	default y if ARCH_VT8500
 	default PCI
 
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 34a928d..2015b02 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1197,6 +1197,11 @@ MODULE_LICENSE ("GPL");
 #define	PLATFORM_DRIVER		ehci_atmel_driver
 #endif
 
+#ifdef CONFIG_ARCH_VT8500
+#include "ehci-vt8500.c"
+#define	PLATFORM_DRIVER		vt8500_ehci_driver
+#endif
+
 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \
     !defined(XILINX_OF_PLATFORM_DRIVER)
diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c
new file mode 100644
index 0000000..7801c04
--- /dev/null
+++ b/drivers/usb/host/ehci-vt8500.c
@@ -0,0 +1,173 @@
+/*
+ * drivers/usb/host/ehci-vt8500.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on ehci-au1xxx.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <mach/vt8500.h>
+
+static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int rc = 0;
+
+	if (!udev->parent) /* udev is root hub itself, impossible */
+		rc = -1;
+	/* we only support lpm device connected to root hub yet */
+	if (ehci->has_lpm && !udev->parent->parent) {
+		rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
+		if (!rc)
+			rc = ehci_lpm_check(ehci, udev->portnum);
+	}
+	return rc;
+}
+
+static const struct hc_driver vt8500_ehci_hc_driver = {
+	.description		= hcd_name,
+	.product_desc		= "VT8500 EHCI",
+	.hcd_priv_size		= sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq			= ehci_irq,
+	.flags			= HCD_MEMORY | HCD_USB2,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset			= ehci_init,
+	.start			= ehci_run,
+	.stop			= ehci_stop,
+	.shutdown		= ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_dequeue		= ehci_urb_dequeue,
+	.endpoint_disable	= ehci_endpoint_disable,
+	.endpoint_reset		= ehci_endpoint_reset,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number	= ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data	= ehci_hub_status_data,
+	.hub_control		= ehci_hub_control,
+	.bus_suspend		= ehci_bus_suspend,
+	.bus_resume		= ehci_bus_resume,
+	.relinquish_port	= ehci_relinquish_port,
+	.port_handed_over	= ehci_port_handed_over,
+
+	/*
+	 * call back when device connected and addressed
+	 */
+	.update_device =	ehci_update_device,
+
+	.clear_tt_buffer_complete	= ehci_clear_tt_buffer_complete,
+};
+
+static int vt8500_ehci_drv_probe(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd;
+	struct ehci_hcd *ehci;
+	struct resource *res;
+	int ret;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	if (pdev->resource[1].flags != IORESOURCE_IRQ) {
+		pr_debug("resource[1] is not IORESOURCE_IRQ");
+		return -ENOMEM;
+	}
+	hcd = usb_create_hcd(&vt8500_ehci_hc_driver, &pdev->dev, "VT8500");
+	if (!hcd)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_debug("request_mem_region failed");
+		ret = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	ehci = hcd_to_ehci(hcd);
+	ehci->caps = hcd->regs;
+	ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
+
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = readl(&ehci->caps->hcs_params);
+
+	ehci_port_power(ehci, 1);
+
+	ret = usb_add_hcd(hcd, pdev->resource[1].start,
+			  IRQF_DISABLED | IRQF_SHARED);
+	if (ret == 0) {
+		platform_set_drvdata(pdev, hcd);
+		return ret;
+	}
+
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static int vt8500_ehci_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver vt8500_ehci_driver = {
+	.probe		= vt8500_ehci_drv_probe,
+	.remove		= vt8500_ehci_drv_remove,
+	.shutdown	= usb_hcd_platform_shutdown,
+	.driver = {
+		.name	= "vt8500-ehci",
+		.owner	= THIS_MODULE,
+	}
+};
+
+MODULE_ALIAS("platform:vt8500-ehci");
-- 
1.7.3.1


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

* [PATCH 5/6] rtc: Add support for the RTC in VIA VT8500 and compatibles
  2010-10-20 20:55 [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Alexey Charkov
                   ` (2 preceding siblings ...)
  2010-10-20 20:55 ` [PATCH 4/6] usb: Add support for VIA VT8500 and compatibles in EHCI HCD Alexey Charkov
@ 2010-10-20 20:55 ` Alexey Charkov
  2010-10-20 20:55 ` [PATCH 6/6] ARM: Add support for the display controllers in VT8500 and WM8505 Alexey Charkov
  2010-10-21  8:05 ` [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Arnd Bergmann
  5 siblings, 0 replies; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 20:55 UTC (permalink / raw)
  To: vt8500-wm8505-linux-kernel
  Cc: linux-arm-kernel, Alexey Charkov, Alessandro Zummo, rtc-linux,
	linux-kernel

This adds a driver for the RTC devices in VIA and WonderMedia
Systems-on-Chip. Alarm, 1Hz interrupts, reading and setting time
are supported.

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---

Please review and state whether this could be acceptable for a merge
to mainline in the coming 2.6.37 window. If possible, I would deeply
appreciate a merge to a relevant git tree for integration prior to
asking Linus to pull the changes. I could rebase the code if needed,
currently this is against Linus' master branch.

This patch relies on the basic architecture support for VT8500/WM8505
to be in place, as introduced by PATCH 1/6 in this series.

Due credits go to the community for providing feedback, advice and
testing.

NB: The development is being done at:
http://gitorious.org/linux-on-via-vt8500/vt8500-kernel

Relevant code may be pulled from a git tree in there.

 drivers/rtc/Kconfig      |    7 +
 drivers/rtc/Makefile     |    1 +
 drivers/rtc/rtc-vt8500.c |  363 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 371 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-vt8500.c

diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 48ca713..b87a2f9 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -854,6 +854,13 @@ config RTC_DRV_PXA
          This RTC driver uses PXA RTC registers available since pxa27x
          series (RDxR, RYxR) instead of legacy RCNR, RTAR.
 
+config RTC_DRV_VT8500
+	tristate "VIA/WonderMedia 85xx SoC RTC"
+	depends on ARCH_VT8500
+	help
+	  If you say Y here you will get access to the real time clock
+	  built into your VIA VT8500 SoC or its relatives.
+
 
 config RTC_DRV_SUN4V
 	bool "SUN4V Hypervisor RTC"
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 0f207b3..0c09922 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -95,6 +95,7 @@ obj-$(CONFIG_RTC_DRV_TWL4030)	+= rtc-twl.o
 obj-$(CONFIG_RTC_DRV_TX4939)	+= rtc-tx4939.o
 obj-$(CONFIG_RTC_DRV_V3020)	+= rtc-v3020.o
 obj-$(CONFIG_RTC_DRV_VR41XX)	+= rtc-vr41xx.o
+obj-$(CONFIG_RTC_DRV_VT8500)	+= rtc-vt8500.o
 obj-$(CONFIG_RTC_DRV_WM831X)	+= rtc-wm831x.o
 obj-$(CONFIG_RTC_DRV_WM8350)	+= rtc-wm8350.o
 obj-$(CONFIG_RTC_DRV_X1205)	+= rtc-x1205.o
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
new file mode 100644
index 0000000..7260c95
--- /dev/null
+++ b/drivers/rtc/rtc-vt8500.c
@@ -0,0 +1,363 @@
+/*
+ * drivers/rtc/rtc-vt8500.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on rtc-pxa.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/rtc.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/bcd.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/*
+ * Register definitions
+ */
+#define VT8500_RTC_TS		0x00	/* Time set */
+#define VT8500_RTC_DS		0x04	/* Date set */
+#define VT8500_RTC_AS		0x08	/* Alarm set */
+#define VT8500_RTC_CR		0x0c	/* Control */
+#define VT8500_RTC_TR		0x10	/* Time read */
+#define VT8500_RTC_DR		0x14	/* Date read */
+#define VT8500_RTC_WS		0x18	/* Write status */
+#define VT8500_RTC_CL		0x20	/* Calibration */
+#define VT8500_RTC_IS		0x24	/* Interrupt status */
+#define VT8500_RTC_ST		0x28	/* Status */
+
+#define INVALID_TIME_BIT	(1 << 31)
+
+#define DATE_CENTURY_S		19
+#define DATE_YEAR_S		11
+#define DATE_YEAR_MASK		(0xff << DATE_YEAR_S)
+#define DATE_MONTH_S		6
+#define DATE_MONTH_MASK		(0x1f << DATE_MONTH_S)
+#define DATE_DAY_MASK		0x3f
+
+#define TIME_DOW_S		20
+#define TIME_DOW_MASK		(0x07 << TIME_DOW_S)
+#define TIME_HOUR_S		14
+#define TIME_HOUR_MASK		(0x3f << TIME_HOUR_S)
+#define TIME_MIN_S		7
+#define TIME_MIN_MASK		(0x7f << TIME_MIN_S)
+#define TIME_SEC_MASK		0x7f
+
+#define ALARM_DAY_S		20
+#define ALARM_DAY_MASK		(0x3f << ALARM_DAY_S)
+
+#define ALARM_DAY_BIT		(1 << 29)
+#define ALARM_HOUR_BIT		(1 << 28)
+#define ALARM_MIN_BIT		(1 << 27)
+#define ALARM_SEC_BIT		(1 << 26)
+
+#define ALARM_ENABLE_MASK	(ALARM_DAY_BIT \
+				| ALARM_HOUR_BIT \
+				| ALARM_MIN_BIT \
+				| ALARM_SEC_BIT)
+
+struct vt8500_rtc {
+	void __iomem		*regbase;
+	int			irq_alarm;
+	int			irq_hz;
+	struct rtc_device	*rtc;
+	spinlock_t		lock;		/* Protects this structure */
+	struct rtc_time		rtc_alarm;
+};
+
+static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id)
+{
+	struct platform_device *pdev = to_platform_device(dev_id);
+	struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev);
+	u32 isr;
+	unsigned long events = 0;
+
+	spin_lock(&vt8500_rtc->lock);
+
+	/* clear interrupt sources */
+	isr = readl(vt8500_rtc->regbase + VT8500_RTC_IS);
+	writel(isr, vt8500_rtc->regbase + VT8500_RTC_IS);
+
+	if (isr & 1)
+		events |= RTC_AF | RTC_IRQF;
+
+	/* Only second/minute interrupts are supported */
+	if (isr & 2)
+		events |= RTC_UF | RTC_IRQF;
+
+	rtc_update_irq(vt8500_rtc->rtc, 1, events);
+
+	spin_unlock(&vt8500_rtc->lock);
+	return IRQ_HANDLED;
+}
+
+static int vt8500_rtc_open(struct device *dev)
+{
+	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
+	int ret;
+
+	ret = request_irq(vt8500_rtc->irq_hz, vt8500_rtc_irq, IRQF_DISABLED,
+			  "rtc 1Hz", dev);
+	if (ret < 0) {
+		dev_err(dev, "can't get irq %i, err %d\n", vt8500_rtc->irq_hz,
+			ret);
+		goto err_irq_hz;
+	}
+	ret = request_irq(vt8500_rtc->irq_alarm, vt8500_rtc_irq, IRQF_DISABLED,
+			  "rtc alarm", dev);
+	if (ret < 0) {
+		dev_err(dev, "can't get irq %i, err %d\n",
+			vt8500_rtc->irq_alarm, ret);
+		goto err_irq_alarm;
+	}
+	return 0;
+
+err_irq_alarm:
+	free_irq(vt8500_rtc->irq_hz, dev);
+err_irq_hz:
+	return ret;
+}
+
+static void vt8500_rtc_release(struct device *dev)
+{
+	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
+
+	spin_lock_irq(&vt8500_rtc->lock);
+	/* Disable alarm matching */
+	writel(0, vt8500_rtc->regbase + VT8500_RTC_IS);
+	spin_unlock_irq(&vt8500_rtc->lock);
+
+	free_irq(vt8500_rtc->irq_alarm, dev);
+	free_irq(vt8500_rtc->irq_hz, dev);
+}
+
+static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
+	u32 date, time;
+
+	date = readl(vt8500_rtc->regbase + VT8500_RTC_DR);
+	time = readl(vt8500_rtc->regbase + VT8500_RTC_TR);
+
+	tm->tm_sec = bcd2bin(time & TIME_SEC_MASK);
+	tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S);
+	tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S);
+	tm->tm_mday = bcd2bin(date & DATE_DAY_MASK);
+	tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S);
+	tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S);
+	tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S;
+
+	return 0;
+}
+
+static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
+
+	writel((bin2bcd(tm->tm_year) << DATE_YEAR_S)
+		| (bin2bcd(tm->tm_mon) << DATE_MONTH_S)
+		| (bin2bcd(tm->tm_mday)),
+		vt8500_rtc->regbase + VT8500_RTC_DS);
+	writel((bin2bcd(tm->tm_wday) << TIME_DOW_S)
+		| (bin2bcd(tm->tm_hour) << TIME_HOUR_S)
+		| (bin2bcd(tm->tm_min) << TIME_MIN_S)
+		| (bin2bcd(tm->tm_sec)),
+		vt8500_rtc->regbase + VT8500_RTC_TS);
+
+	return 0;
+}
+
+static int vt8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
+	u32 isr, alarm;
+
+	alarm = readl(vt8500_rtc->regbase + VT8500_RTC_AS);
+	isr = readl(vt8500_rtc->regbase + VT8500_RTC_IS);
+
+	alrm->time.tm_mday = bcd2bin((alarm & ALARM_DAY_MASK) >> ALARM_DAY_S);
+	alrm->time.tm_hour = bcd2bin((alarm & TIME_HOUR_MASK) >> TIME_HOUR_S);
+	alrm->time.tm_min = bcd2bin((alarm & TIME_MIN_MASK) >> TIME_MIN_S);
+	alrm->time.tm_sec = bcd2bin((alarm & TIME_SEC_MASK));
+
+	alrm->enabled = (alarm & ALARM_ENABLE_MASK) ? 1 : 0;
+
+	alrm->pending = (isr & 1) ? 1 : 0;
+	return 0;
+}
+
+static int vt8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
+
+	writel((alrm->enabled ? ALARM_ENABLE_MASK : 0)
+		| (bin2bcd(alrm->time.tm_mday) << ALARM_DAY_S)
+		| (bin2bcd(alrm->time.tm_hour) << TIME_HOUR_S)
+		| (bin2bcd(alrm->time.tm_min) << TIME_MIN_S)
+		| (bin2bcd(alrm->time.tm_sec)),
+		vt8500_rtc->regbase + VT8500_RTC_AS);
+
+	return 0;
+}
+
+static int vt8500_rtc_ioctl(struct device *dev, unsigned int cmd,
+		unsigned long arg)
+{
+	struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
+	int ret = 0;
+	unsigned long tmp;
+
+	spin_lock_irq(&vt8500_rtc->lock);
+	switch (cmd) {
+	case RTC_AIE_OFF:
+		tmp = readl(vt8500_rtc->regbase + VT8500_RTC_AS);
+		writel(tmp & ~ALARM_ENABLE_MASK,
+		       vt8500_rtc->regbase + VT8500_RTC_AS);
+		break;
+	case RTC_AIE_ON:
+		tmp = readl(vt8500_rtc->regbase + VT8500_RTC_AS);
+		writel(tmp | ALARM_ENABLE_MASK,
+		       vt8500_rtc->regbase + VT8500_RTC_AS);
+		break;
+	case RTC_UIE_OFF:
+		tmp = readl(vt8500_rtc->regbase + VT8500_RTC_CR);
+		writel(tmp & ~(1 << 2),
+		       vt8500_rtc->regbase + VT8500_RTC_CR);
+		break;
+	case RTC_UIE_ON:
+		tmp = readl(vt8500_rtc->regbase + VT8500_RTC_CR);
+		writel(tmp | ((1 << 3) | (1 << 2)),
+		       vt8500_rtc->regbase + VT8500_RTC_CR);
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+
+	spin_unlock_irq(&vt8500_rtc->lock);
+	return ret;
+}
+
+static const struct rtc_class_ops vt8500_rtc_ops = {
+	.open = vt8500_rtc_open,
+	.release = vt8500_rtc_release,
+	.ioctl = vt8500_rtc_ioctl,
+	.read_time = vt8500_rtc_read_time,
+	.set_time = vt8500_rtc_set_time,
+	.read_alarm = vt8500_rtc_read_alarm,
+	.set_alarm = vt8500_rtc_set_alarm,
+};
+
+static int __init vt8500_rtc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct vt8500_rtc *vt8500_rtc;
+	struct resource *res;
+	int ret;
+
+	vt8500_rtc = kzalloc(sizeof(struct vt8500_rtc), GFP_KERNEL);
+	if (!vt8500_rtc)
+		return -ENOMEM;
+
+	spin_lock_init(&vt8500_rtc->lock);
+	platform_set_drvdata(pdev, vt8500_rtc);
+
+	ret = -ENXIO;
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "No I/O memory resource defined\n");
+		goto err_map;
+	}
+
+	vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0);
+	if (vt8500_rtc->irq_alarm < 0) {
+		dev_err(dev, "No alarm IRQ resource defined\n");
+		goto err_map;
+	}
+
+	vt8500_rtc->irq_hz = platform_get_irq(pdev, 1);
+	if (vt8500_rtc->irq_hz < 0) {
+		dev_err(dev, "No 1Hz IRQ resource defined\n");
+		goto err_map;
+	}
+
+	ret = -ENOMEM;
+	vt8500_rtc->regbase = ioremap(res->start, resource_size(res));
+	if (!vt8500_rtc->regbase) {
+		dev_err(&pdev->dev, "Unable to map RTC I/O memory\n");
+		goto err_map;
+	}
+
+	/* Enable the second/minute interrupt generation and enable RTC */
+	writel((1 << 3) | (1 << 2) | 1, vt8500_rtc->regbase + VT8500_RTC_CR);
+
+	vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev,
+					      &vt8500_rtc_ops, THIS_MODULE);
+	ret = PTR_ERR(vt8500_rtc->rtc);
+	if (IS_ERR(vt8500_rtc->rtc)) {
+		dev_err(dev, "Failed to register RTC device -> %d\n", ret);
+		goto err_rtc_reg;
+	}
+
+	device_init_wakeup(dev, 1);
+
+	return 0;
+
+err_rtc_reg:
+	iounmap(vt8500_rtc->regbase);
+err_map:
+	kfree(vt8500_rtc);
+	return ret;
+}
+
+static int __exit vt8500_rtc_remove(struct platform_device *pdev)
+{
+	struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev);
+
+	rtc_device_unregister(vt8500_rtc->rtc);
+
+	spin_lock_irq(&vt8500_rtc->lock);
+	iounmap(vt8500_rtc->regbase);
+	spin_unlock_irq(&vt8500_rtc->lock);
+
+	kfree(vt8500_rtc);
+
+	return 0;
+}
+
+static struct platform_driver vt8500_rtc_driver = {
+	.probe		= vt8500_rtc_probe,
+	.remove		= __exit_p(vt8500_rtc_remove),
+	.driver		= {
+		.name	= "vt8500-rtc"
+	},
+};
+
+static int __init vt8500_rtc_init(void)
+{
+	return platform_driver_register(&vt8500_rtc_driver);
+}
+
+static void __exit vt8500_rtc_exit(void)
+{
+	platform_driver_unregister(&vt8500_rtc_driver);
+}
+
+module_init(vt8500_rtc_init);
+module_exit(vt8500_rtc_exit);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com>");
+MODULE_DESCRIPTION("VIA VT8500 SoC Realtime Clock Driver (RTC)");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vt8500-rtc");
-- 
1.7.3.1


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

* [PATCH 6/6] ARM: Add support for the display controllers in VT8500 and WM8505
  2010-10-20 20:55 [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Alexey Charkov
                   ` (3 preceding siblings ...)
  2010-10-20 20:55 ` [PATCH 5/6] rtc: Add support for the RTC in VIA VT8500 and compatibles Alexey Charkov
@ 2010-10-20 20:55 ` Alexey Charkov
  2010-10-21  8:05 ` [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Arnd Bergmann
  5 siblings, 0 replies; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 20:55 UTC (permalink / raw)
  To: vt8500-wm8505-linux-kernel; +Cc: linux-arm-kernel, Alexey Charkov, linux-kernel

This adds drivers for the LCD controller found in VIA VT8500 SoC,
GOVR display controller found in WonderMedia WM8505 SoC and for the
Graphics Engine present in both of them that provides hardware
accelerated raster operations (used for copyarea and fillrect).

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---

Please review and state whether this could be acceptable for a merge
to mainline in the coming 2.6.37 window. If possible, I would deeply
appreciate a merge to a relevant git tree for integration prior to
asking Linus to pull the changes. I could rebase the code if needed,
currently this is against Linus' master branch.

This patch relies on the basic architecture support for VT8500/WM8505
to be in place, as introduced by PATCH 1/6 in this series. Both
framebuffer drivers are independent (and never end up together in
one system), but both depend on wmt_ge_rops for raster acceleration.

Due credits go to the community for providing feedback, advice and
testing. Driver for WM8505 is by Ed Spiridonov, as stated in the
relevant copyright header, parts modified by myself.

Invaluable work wrt the Graphics Engine documentation has been done
by Giuseppe Gatta aka nextvolume. Also special thanks go to Angus
Gratton aka projectgus for convincing VIA to partly release GPL
kernel sources for the vendor-provided images, which greatly helped
in understanding some parts of WM8505's complex video handling chain.

NB: The development is being done at:
http://gitorious.org/linux-on-via-vt8500/vt8500-kernel

Relevant code may be pulled from a git tree in there.

 drivers/video/Kconfig         |   26 +++
 drivers/video/Makefile        |    3 +
 drivers/video/vt8500lcdfb.c   |  452 +++++++++++++++++++++++++++++++++++++++++
 drivers/video/vt8500lcdfb.h   |   34 +++
 drivers/video/wm8505fb.c      |  438 +++++++++++++++++++++++++++++++++++++++
 drivers/video/wm8505fb_regs.h |   76 +++++++
 drivers/video/wmt_ge_rops.c   |  186 +++++++++++++++++
 drivers/video/wmt_ge_rops.h   |    5 +
 8 files changed, 1220 insertions(+), 0 deletions(-)
 create mode 100644 drivers/video/vt8500lcdfb.c
 create mode 100644 drivers/video/vt8500lcdfb.h
 create mode 100644 drivers/video/wm8505fb.c
 create mode 100644 drivers/video/wm8505fb_regs.h
 create mode 100644 drivers/video/wmt_ge_rops.c
 create mode 100644 drivers/video/wmt_ge_rops.h

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 8b31fdf..cd3e481 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -184,6 +184,14 @@ config FB_SYS_FOPS
        depends on FB
        default n
 
+config FB_WMT_GE_ROPS
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include functions for accelerated rectangle filling and area
+	  copying using WonderMedia Graphics Engine operations.
+
 config FB_DEFERRED_IO
 	bool
 	depends on FB
@@ -1720,6 +1728,24 @@ config FB_AU1200
 	  various panels and CRTs by passing in kernel cmd line option
 	  au1200fb:panel=<name>.
 
+config FB_VT8500
+	bool "VT8500 LCD Driver"
+	depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_VT8500
+	select FB_WMT_GE_ROPS
+	select FB_SYS_IMAGEBLIT
+	help
+	  This is the framebuffer driver for VIA VT8500 integrated LCD
+	  controller.
+
+config FB_WM8505
+	bool "WM8505 frame buffer support"
+	depends on (FB = y) && ARM && ARCH_VT8500 && VTWM_VERSION_WM8505
+	select FB_WMT_GE_ROPS
+	select FB_SYS_IMAGEBLIT
+	help
+	  This is the framebuffer driver for WonderMedia WM8505
+	  integrated LCD controller.
+
 source "drivers/video/geode/Kconfig"
 
 config FB_HIT
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 485e8ed..8d916dc 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_FB_SVGALIB)       += svgalib.o
 obj-$(CONFIG_FB_MACMODES)      += macmodes.o
 obj-$(CONFIG_FB_DDC)           += fb_ddc.o
 obj-$(CONFIG_FB_DEFERRED_IO)   += fb_defio.o
+obj-$(CONFIG_FB_WMT_GE_ROPS)   += wmt_ge_rops.o
 
 # Hardware specific drivers go first
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p_planar.o
@@ -104,6 +105,8 @@ obj-$(CONFIG_FB_W100)		  += w100fb.o
 obj-$(CONFIG_FB_TMIO)		  += tmiofb.o
 obj-$(CONFIG_FB_AU1100)		  += au1100fb.o
 obj-$(CONFIG_FB_AU1200)		  += au1200fb.o
+obj-$(CONFIG_FB_VT8500)		  += vt8500lcdfb.o
+obj-$(CONFIG_FB_WM8505)		  += wm8505fb.o
 obj-$(CONFIG_FB_PMAG_AA)	  += pmag-aa-fb.o
 obj-$(CONFIG_FB_PMAG_BA)	  += pmag-ba-fb.o
 obj-$(CONFIG_FB_PMAGB_B)	  += pmagb-b-fb.o
diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/vt8500lcdfb.c
new file mode 100644
index 0000000..3dd2296
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.c
@@ -0,0 +1,452 @@
+/*
+ *  linux/drivers/video/vt8500lcdfb.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on skeletonfb.c and pxafb.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+
+#include <asm/irq.h>
+
+#include <mach/vt8500fb.h>
+
+#include "vt8500lcdfb.h"
+#include "wmt_ge_rops.h"
+
+static int vt8500lcd_set_par(struct fb_info *info)
+{
+	struct vt8500lcd_info *fbi = container_of(info,
+						  struct vt8500lcd_info,
+						  fb);
+	int reg_bpp = 5; /* 16bpp */
+	int i;
+	unsigned long control0;
+
+	if (!fbi)
+		return -EINVAL;
+
+	if (info->var.bits_per_pixel <= 8) {
+		/* palettized */
+		info->var.red.offset    = 0;
+		info->var.red.length    = info->var.bits_per_pixel;
+		info->var.red.msb_right = 0;
+
+		info->var.green.offset  = 0;
+		info->var.green.length  = info->var.bits_per_pixel;
+		info->var.green.msb_right = 0;
+
+		info->var.blue.offset   = 0;
+		info->var.blue.length   = info->var.bits_per_pixel;
+		info->var.blue.msb_right = 0;
+
+		info->var.transp.offset = 0;
+		info->var.transp.length = 0;
+		info->var.transp.msb_right = 0;
+
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		info->fix.line_length = info->var.xres_virtual /
+						(8/info->var.bits_per_pixel);
+	} else {
+		/* non-palettized */
+		info->var.transp.offset = 0;
+		info->var.transp.length = 0;
+		info->var.transp.msb_right = 0;
+
+		if (info->var.bits_per_pixel == 16) {
+			/* RGB565 */
+			info->var.red.offset = 11;
+			info->var.red.length = 5;
+			info->var.red.msb_right = 0;
+			info->var.green.offset = 5;
+			info->var.green.length = 6;
+			info->var.green.msb_right = 0;
+			info->var.blue.offset = 0;
+			info->var.blue.length = 5;
+			info->var.blue.msb_right = 0;
+		} else {
+			/* Equal depths per channel */
+			info->var.red.offset = info->var.bits_per_pixel
+							* 2 / 3;
+			info->var.red.length = info->var.bits_per_pixel / 3;
+			info->var.red.msb_right = 0;
+			info->var.green.offset = info->var.bits_per_pixel / 3;
+			info->var.green.length = info->var.bits_per_pixel / 3;
+			info->var.green.msb_right = 0;
+			info->var.blue.offset = 0;
+			info->var.blue.length = info->var.bits_per_pixel / 3;
+			info->var.blue.msb_right = 0;
+		}
+
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.line_length = info->var.bits_per_pixel > 16 ?
+					info->var.xres_virtual << 2 :
+					info->var.xres_virtual << 1;
+	}
+
+	for (i = 0; i < 8; i++) {
+		if (bpp_values[i] == info->var.bits_per_pixel) {
+			reg_bpp = i;
+			continue;
+		}
+	}
+
+	control0 = readl(fbi->regbase) & ~0xf;
+	writel(0, fbi->regbase);
+	while (readl(fbi->regbase + 0x38) & 0x10)
+		/* wait */;
+	writel((((info->var.hsync_len - 1) & 0x3f) << 26)
+		| ((info->var.left_margin & 0xff) << 18)
+		| (((info->var.xres - 1) & 0x3ff) << 8)
+		| (info->var.right_margin & 0xff), fbi->regbase + 0x4);
+	writel((((info->var.vsync_len - 1) & 0x3f) << 26)
+		| ((info->var.upper_margin & 0xff) << 18)
+		| (((info->var.yres - 1) & 0x3ff) << 8)
+		| (info->var.lower_margin & 0xff), fbi->regbase + 0x8);
+	writel((((info->var.yres - 1) & 0x400) << 2)
+		| ((info->var.xres - 1) & 0x400), fbi->regbase + 0x10);
+	writel(0x80000000, fbi->regbase + 0x20);
+	writel(control0 | (reg_bpp << 1) | 0x100, fbi->regbase);
+
+	return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int vt8500lcd_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info) {
+	struct vt8500lcd_info *fbi = container_of(info,
+						  struct vt8500lcd_info,
+						  fb);
+	int ret = 1;
+	unsigned int val;
+	if (regno >= 256)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		red = green = blue =
+			(19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+	switch (fbi->fb.fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			u32 *pal = fbi->fb.pseudo_palette;
+
+			val  = chan_to_field(red, &fbi->fb.var.red);
+			val |= chan_to_field(green, &fbi->fb.var.green);
+			val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+
+	case FB_VISUAL_STATIC_PSEUDOCOLOR:
+	case FB_VISUAL_PSEUDOCOLOR:
+		writew((red & 0xf800)
+		      | ((green >> 5) & 0x7e0)
+		      | ((blue >> 11) & 0x1f),
+		       fbi->palette_cpu + sizeof(u16) * regno);
+		break;
+	}
+
+	return ret;
+}
+
+static int vt8500lcd_ioctl(struct fb_info *info, unsigned int cmd,
+			 unsigned long arg)
+{
+	int ret = 0;
+	struct vt8500lcd_info *fbi = container_of(info,
+						  struct vt8500lcd_info,
+						  fb);
+
+	if (cmd == FBIO_WAITFORVSYNC) {
+		/* Unmask End of Frame interrupt */
+		writel(0xffffffff ^ (1 << 3), fbi->regbase + 0x3c);
+		ret = wait_event_interruptible_timeout(fbi->wait,
+			readl(fbi->regbase + 0x38) & (1 << 3), HZ / 10);
+		/* Mask back to reduce unwanted interrupt traffic */
+		writel(0xffffffff, fbi->regbase + 0x3c);
+		if (ret < 0)
+			return ret;
+		if (ret == 0)
+			return -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
+static int vt8500lcd_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	unsigned pixlen = info->fix.line_length / info->var.xres_virtual;
+	unsigned off = pixlen * var->xoffset
+		      + info->fix.line_length * var->yoffset;
+	struct vt8500lcd_info *fbi = container_of(info,
+						  struct vt8500lcd_info,
+						  fb);
+	writel((1 << 31)
+		| (((var->xres_virtual - var->xres) * pixlen / 4) << 20)
+		| (off >> 2), fbi->regbase + 0x20);
+	return 0;
+}
+
+static struct fb_ops vt8500lcd_ops = {
+	.owner		= THIS_MODULE,
+	.fb_set_par	= vt8500lcd_set_par,
+	.fb_setcolreg	= vt8500lcd_setcolreg,
+	.fb_fillrect	= wmt_ge_fillrect,
+	.fb_copyarea	= wmt_ge_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_sync	= wmt_ge_sync,
+	.fb_ioctl	= vt8500lcd_ioctl,
+	.fb_pan_display	= vt8500lcd_pan_display,
+};
+
+static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id)
+{
+	struct vt8500lcd_info *fbi = dev_id;
+
+	if (readl(fbi->regbase + 0x38) & (1 << 3))
+		wake_up_interruptible(&fbi->wait);
+
+	writel(0xffffffff, fbi->regbase + 0x38);
+	return IRQ_HANDLED;
+}
+
+static int __devinit vt8500lcd_probe(struct platform_device *pdev)
+{
+	struct vt8500lcd_info *fbi;
+	struct resource *res;
+	struct vt8500fb_platform_data *pdata = pdev->dev.platform_data;
+	void *addr;
+	int irq, ret;
+
+	ret = -ENOMEM;
+	fbi = NULL;
+
+	fbi = kzalloc(sizeof(struct vt8500lcd_info) + sizeof(u32) * 16,
+							GFP_KERNEL);
+	if (!fbi) {
+		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	strcpy(fbi->fb.fix.id, "VT8500 LCD");
+
+	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbi->fb.fix.xpanstep	= 0;
+	fbi->fb.fix.ypanstep	= 1;
+	fbi->fb.fix.ywrapstep	= 0;
+	fbi->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fbi->fb.var.nonstd	= 0;
+	fbi->fb.var.activate	= FB_ACTIVATE_NOW;
+	fbi->fb.var.height	= -1;
+	fbi->fb.var.width	= -1;
+	fbi->fb.var.vmode	= FB_VMODE_NONINTERLACED;
+
+	fbi->fb.fbops		= &vt8500lcd_ops;
+	fbi->fb.flags		= FBINFO_DEFAULT
+				| FBINFO_HWACCEL_COPYAREA
+				| FBINFO_HWACCEL_FILLRECT
+				| FBINFO_HWACCEL_YPAN
+				| FBINFO_VIRTFB
+				| FBINFO_PARTIAL_PAN_OK;
+	fbi->fb.node		= -1;
+
+	addr = fbi;
+	addr = addr + sizeof(struct vt8500lcd_info);
+	fbi->fb.pseudo_palette	= addr;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		ret = -ENODEV;
+		goto failed_fbi;
+	}
+
+	res = request_mem_region(res->start, resource_size(res), "vt8500lcd");
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to request I/O memory\n");
+		ret = -EBUSY;
+		goto failed_fbi;
+	}
+
+	fbi->regbase = ioremap(res->start, resource_size(res));
+	if (fbi->regbase == NULL) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		ret = -EBUSY;
+		goto failed_free_res;
+	}
+
+	fbi->fb.fix.smem_start	= pdata->video_mem_phys;
+	fbi->fb.fix.smem_len	= pdata->video_mem_len;
+	fbi->fb.screen_base	= pdata->video_mem_virt;
+
+	fbi->palette_size	= PAGE_ALIGN(512);
+	fbi->palette_cpu	= dma_alloc_coherent(&pdev->dev,
+						     fbi->palette_size,
+						     &fbi->palette_phys,
+						     GFP_KERNEL);
+	if (fbi->fb.pseudo_palette == NULL) {
+		dev_err(&pdev->dev, "Failed to allocate palette buffer\n");
+		ret = -ENOMEM;
+		goto failed_free_io;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no IRQ defined\n");
+		ret = -ENODEV;
+		goto failed_free_palette;
+	}
+
+	ret = request_irq(irq, vt8500lcd_handle_irq, IRQF_DISABLED, "LCD", fbi);
+	if (ret) {
+		dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
+		ret = -EBUSY;
+		goto failed_free_palette;
+	}
+
+	init_waitqueue_head(&fbi->wait);
+
+	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
+		dev_err(&pdev->dev, "Failed to allocate color map\n");
+		ret = -ENOMEM;
+		goto failed_free_irq;
+	}
+
+	fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
+	fbi->fb.var.bits_per_pixel	= pdata->bpp;
+	fbi->fb.var.xres_virtual	= pdata->xres_virtual;
+	fbi->fb.var.yres_virtual	= pdata->yres_virtual;
+
+	ret = vt8500lcd_set_par(&fbi->fb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set parameters\n");
+		goto failed_free_cmap;
+	}
+
+	writel(fbi->fb.fix.smem_start >> 22, fbi->regbase + 0x1c);
+	writel((fbi->palette_phys & 0xfffffe00) | 1, fbi->regbase + 0x18);
+
+	platform_set_drvdata(pdev, fbi);
+
+	ret = register_framebuffer(&fbi->fb);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Failed to register framebuffer device: %d\n", ret);
+		goto failed_free_cmap;
+	}
+
+	/*
+	 * Ok, now enable the LCD controller
+	 */
+	writel(readl(fbi->regbase) | 1, fbi->regbase);
+
+	return 0;
+
+failed_free_cmap:
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+failed_free_irq:
+	free_irq(irq, fbi);
+failed_free_palette:
+	dma_free_coherent(&pdev->dev, fbi->palette_size,
+			  fbi->fb.pseudo_palette, fbi->palette_phys);
+failed_free_io:
+	iounmap(fbi->regbase);
+failed_free_res:
+	release_mem_region(res->start, resource_size(res));
+failed_fbi:
+	platform_set_drvdata(pdev, NULL);
+	kfree(fbi);
+failed:
+	return ret;
+}
+
+static int __devexit vt8500lcd_remove(struct platform_device *pdev)
+{
+	struct vt8500lcd_info *fbi = platform_get_drvdata(pdev);
+	struct resource *res;
+	int irq;
+
+	if (!fbi)
+		return 0;
+
+	unregister_framebuffer(&fbi->fb);
+
+	writel(0, fbi->regbase);
+
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+
+	irq = platform_get_irq(pdev, 0);
+	free_irq(irq, fbi);
+
+	iounmap(fbi->regbase);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(fbi);
+
+	return 0;
+}
+
+static struct platform_driver vt8500lcd_driver = {
+	.probe		= vt8500lcd_probe,
+	.remove		= vt8500lcd_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "vt8500-lcd",
+	},
+};
+
+static int __init vt8500lcd_init(void)
+{
+	return platform_driver_register(&vt8500lcd_driver);
+}
+
+static void __exit vt8500lcd_exit(void)
+{
+	platform_driver_unregister(&vt8500lcd_driver);
+}
+
+module_init(vt8500lcd_init);
+module_exit(vt8500lcd_exit);
+
+MODULE_DESCRIPTION("LCD controller driver for VIA VT8500");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/vt8500lcdfb.h b/drivers/video/vt8500lcdfb.h
new file mode 100644
index 0000000..36ca3ca
--- /dev/null
+++ b/drivers/video/vt8500lcdfb.h
@@ -0,0 +1,34 @@
+/*
+ *  linux/drivers/video/vt8500lcdfb.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+struct vt8500lcd_info {
+	struct fb_info		fb;
+	void __iomem		*regbase;
+	void __iomem		*palette_cpu;
+	dma_addr_t		palette_phys;
+	size_t			palette_size;
+	wait_queue_head_t	wait;
+};
+
+static int bpp_values[] = {
+	1,
+	2,
+	4,
+	8,
+	12,
+	16,
+	18,
+	24,
+};
diff --git a/drivers/video/wm8505fb.c b/drivers/video/wm8505fb.c
new file mode 100644
index 0000000..9a1cc70
--- /dev/null
+++ b/drivers/video/wm8505fb.c
@@ -0,0 +1,438 @@
+/*
+ *  WonderMedia WM8505 Frame Buffer device driver
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *    Based on vt8500lcdfb.c
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+
+#include <asm/irq.h>
+
+#include <mach/vt8500fb.h>
+
+#include "wm8505fb_regs.h"
+#include "wmt_ge_rops.h"
+
+#define DRIVER_NAME "wm8505-fb"
+
+struct wm8505fb_info {
+	struct fb_info		fb;
+	void __iomem		*regbase;
+	unsigned int		contrast;
+};
+
+
+static int wm8505fb_init_hw(struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = container_of(info,
+						  struct wm8505fb_info,
+						  fb);
+
+	int i;
+
+	/* I know the purpose only of few registers, so clear unknown */
+	for (i = 0; i < 0x200; i += 4)
+		writel(0, fbi->regbase + i);
+
+	/* Set frame buffer address */
+	writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR);
+	writel(fbi->fb.fix.smem_start, fbi->regbase + WMT_GOVR_FBADDR1);
+
+	/* Set in-memory picture format to RGB 32bpp */
+	writel(0x1c,		       fbi->regbase + WMT_GOVR_COLORSPACE);
+	writel(1,		       fbi->regbase + WMT_GOVR_COLORSPACE1);
+
+	/* Virtual buffer size */
+	writel(info->var.xres,	       fbi->regbase + WMT_GOVR_XRES);
+	writel(info->var.xres_virtual, fbi->regbase + WMT_GOVR_XRES_VIRTUAL);
+
+	/* black magic ;) */
+	writel(0xf,		       fbi->regbase + WMT_GOVR_FHI);
+	writel(4,		       fbi->regbase + WMT_GOVR_DVO_SET);
+	writel(1,		       fbi->regbase + WMT_GOVR_MIF_ENABLE);
+	writel(1,		       fbi->regbase + WMT_GOVR_REG_UPDATE);
+
+	return 0;
+}
+
+static int wm8505fb_set_timing(struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = container_of(info,
+						  struct wm8505fb_info,
+						  fb);
+
+	int h_start = info->var.left_margin;
+	int h_end = h_start + info->var.xres;
+	int h_all = h_end + info->var.right_margin;
+	int h_sync = info->var.hsync_len;
+
+	int v_start = info->var.upper_margin;
+	int v_end = v_start + info->var.yres;
+	int v_all = v_end + info->var.lower_margin;
+	int v_sync = info->var.vsync_len + 1;
+
+	writel(0, fbi->regbase + WMT_GOVR_TG);
+
+	writel(h_start, fbi->regbase + WMT_GOVR_TIMING_H_START);
+	writel(h_end,   fbi->regbase + WMT_GOVR_TIMING_H_END);
+	writel(h_all,   fbi->regbase + WMT_GOVR_TIMING_H_ALL);
+	writel(h_sync,  fbi->regbase + WMT_GOVR_TIMING_H_SYNC);
+
+	writel(v_start, fbi->regbase + WMT_GOVR_TIMING_V_START);
+	writel(v_end,   fbi->regbase + WMT_GOVR_TIMING_V_END);
+	writel(v_all,   fbi->regbase + WMT_GOVR_TIMING_V_ALL);
+	writel(v_sync,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
+
+	writel(1, fbi->regbase + WMT_GOVR_TG);
+
+	return 0;
+}
+
+
+static int wm8505fb_set_par(struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = container_of(info,
+						  struct wm8505fb_info,
+						  fb);
+
+	if (!fbi)
+		return -EINVAL;
+
+	if (info->var.bits_per_pixel == 32) {
+		info->var.red.offset = 16;
+		info->var.red.length = 8;
+		info->var.red.msb_right = 0;
+		info->var.green.offset = 8;
+		info->var.green.length = 8;
+		info->var.green.msb_right = 0;
+		info->var.blue.offset = 0;
+		info->var.blue.length = 8;
+		info->var.blue.msb_right = 0;
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		info->fix.line_length = info->var.xres_virtual << 2;
+	}
+
+	wm8505fb_set_timing(info);
+
+	writel(fbi->contrast<<16 | fbi->contrast<<8 | fbi->contrast,
+		fbi->regbase + WMT_GOVR_CONTRAST);
+
+	return 0;
+}
+
+static ssize_t contrast_show(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct wm8505fb_info *fbi = container_of(info,
+						  struct wm8505fb_info,
+						  fb);
+
+	return sprintf(buf, "%d\n", fbi->contrast);
+}
+
+static ssize_t contrast_store(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct fb_info *info = dev_get_drvdata(dev);
+	struct wm8505fb_info *fbi = container_of(info,
+						  struct wm8505fb_info,
+						  fb);
+
+	fbi->contrast = strict_strtoul(buf, NULL, 10) & 0xff;
+	wm8505fb_set_par(info);
+
+	return count;
+}
+
+static DEVICE_ATTR(contrast, 0644, contrast_show, contrast_store);
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int wm8505fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info) {
+	struct wm8505fb_info *fbi = container_of(info,
+						  struct wm8505fb_info,
+						  fb);
+	int ret = 1;
+	unsigned int val;
+	if (regno >= 256)
+		return -EINVAL;
+
+	if (info->var.grayscale)
+		red = green = blue =
+			(19595 * red + 38470 * green + 7471 * blue) >> 16;
+
+	switch (fbi->fb.fix.visual) {
+	case FB_VISUAL_TRUECOLOR:
+		if (regno < 16) {
+			u32 *pal = info->pseudo_palette;
+
+			val  = chan_to_field(red, &fbi->fb.var.red);
+			val |= chan_to_field(green, &fbi->fb.var.green);
+			val |= chan_to_field(blue, &fbi->fb.var.blue);
+
+			pal[regno] = val;
+			ret = 0;
+		}
+		break;
+	}
+
+	return ret;
+}
+
+static int wm8505fb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = container_of(info,
+						  struct wm8505fb_info,
+						  fb);
+
+	writel(var->xoffset, fbi->regbase + WMT_GOVR_XPAN);
+	writel(var->yoffset, fbi->regbase + WMT_GOVR_YPAN);
+	return 0;
+}
+
+static int wm8505fb_blank(int blank, struct fb_info *info)
+{
+	struct wm8505fb_info *fbi = container_of(info,
+						  struct wm8505fb_info,
+						  fb);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		wm8505fb_set_timing(info);
+		break;
+	default:
+		writel(0,  fbi->regbase + WMT_GOVR_TIMING_V_SYNC);
+		break;
+	}
+
+	return 0;
+}
+
+static struct fb_ops wm8505fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_set_par	= wm8505fb_set_par,
+	.fb_setcolreg	= wm8505fb_setcolreg,
+	.fb_fillrect	= wmt_ge_fillrect,
+	.fb_copyarea	= wmt_ge_copyarea,
+	.fb_imageblit	= sys_imageblit,
+	.fb_sync	= wmt_ge_sync,
+	.fb_pan_display	= wm8505fb_pan_display,
+	.fb_blank	= wm8505fb_blank,
+};
+
+static int __devinit wm8505fb_probe(struct platform_device *pdev)
+{
+	struct wm8505fb_info	*fbi;
+	struct resource		*res;
+	void			*addr;
+	struct vt8500fb_platform_data *pdata;
+	int ret;
+
+	pdata = pdev->dev.platform_data;
+
+	ret = -ENOMEM;
+	fbi = NULL;
+
+	fbi = kzalloc(sizeof(struct wm8505fb_info) + sizeof(u32) * 16,
+							GFP_KERNEL);
+	if (!fbi) {
+		dev_err(&pdev->dev, "Failed to initialize framebuffer device\n");
+		ret = -ENOMEM;
+		goto failed;
+	}
+
+	strcpy(fbi->fb.fix.id, DRIVER_NAME);
+
+	fbi->fb.fix.type	= FB_TYPE_PACKED_PIXELS;
+	fbi->fb.fix.xpanstep	= 1;
+	fbi->fb.fix.ypanstep	= 1;
+	fbi->fb.fix.ywrapstep	= 0;
+	fbi->fb.fix.accel	= FB_ACCEL_NONE;
+
+	fbi->fb.fbops		= &wm8505fb_ops;
+	fbi->fb.flags		= FBINFO_DEFAULT
+				| FBINFO_HWACCEL_COPYAREA
+				| FBINFO_HWACCEL_FILLRECT
+				| FBINFO_HWACCEL_XPAN
+				| FBINFO_HWACCEL_YPAN
+				| FBINFO_VIRTFB
+				| FBINFO_PARTIAL_PAN_OK;
+	fbi->fb.node		= -1;
+
+	addr = fbi;
+	addr = addr + sizeof(struct wm8505fb_info);
+	fbi->fb.pseudo_palette	= addr;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		ret = -ENODEV;
+		goto failed_fbi;
+	}
+
+	res = request_mem_region(res->start, resource_size(res), "wm8505fb");
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to request I/O memory\n");
+		ret = -EBUSY;
+		goto failed_fbi;
+	}
+
+	fbi->regbase = ioremap(res->start, resource_size(res));
+	if (fbi->regbase == NULL) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		ret = -EBUSY;
+		goto failed_free_res;
+	}
+
+	fb_videomode_to_var(&fbi->fb.var, &pdata->mode);
+
+	fbi->fb.var.nonstd		= 0;
+	fbi->fb.var.activate		= FB_ACTIVATE_NOW;
+
+	fbi->fb.var.height		= -1;
+	fbi->fb.var.width		= -1;
+	fbi->fb.var.xres_virtual	= pdata->xres_virtual;
+	fbi->fb.var.yres_virtual	= pdata->yres_virtual;
+	fbi->fb.var.bits_per_pixel	= pdata->bpp;
+
+	fbi->fb.fix.smem_start	= pdata->video_mem_phys;
+	fbi->fb.fix.smem_len	= pdata->video_mem_len;
+	fbi->fb.screen_base	= pdata->video_mem_virt;
+	fbi->fb.screen_size	= pdata->video_mem_len;
+
+	if (fb_alloc_cmap(&fbi->fb.cmap, 256, 0) < 0) {
+		dev_err(&pdev->dev, "Failed to allocate color map\n");
+		ret = -ENOMEM;
+		goto failed_free_mem;
+	}
+
+	wm8505fb_init_hw(&fbi->fb);
+
+	fbi->contrast = 0x50;
+	ret = wm8505fb_set_par(&fbi->fb);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to set parameters\n");
+		goto failed_free_cmap;
+	}
+
+	platform_set_drvdata(pdev, fbi);
+
+	ret = register_framebuffer(&fbi->fb);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"Failed to register framebuffer device: %d\n", ret);
+		goto failed_free_cmap;
+	}
+
+	ret = device_create_file(&pdev->dev, &dev_attr_contrast);
+	if (ret < 0) {
+		printk(KERN_WARNING "fb%d: failed to register attributes (%d)\n",
+			fbi->fb.node, ret);
+	}
+
+	printk(KERN_INFO "fb%d: %s frame buffer at 0x%lx-0x%lx\n",
+	       fbi->fb.node, fbi->fb.fix.id, fbi->fb.fix.smem_start,
+	       fbi->fb.fix.smem_start + fbi->fb.fix.smem_len - 1);
+
+	return 0;
+
+failed_free_cmap:
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+failed_free_mem:
+	free_pages_exact(fbi->fb.screen_base, fbi->fb.screen_size);
+failed_free_io:
+	iounmap(fbi->regbase);
+failed_free_res:
+	release_mem_region(res->start, resource_size(res));
+failed_fbi:
+	platform_set_drvdata(pdev, NULL);
+	kfree(fbi);
+failed:
+	return ret;
+}
+
+static int __devexit wm8505fb_remove(struct platform_device *pdev)
+{
+	struct wm8505fb_info *fbi = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	if (!fbi)
+		return 0;
+
+	unregister_framebuffer(&fbi->fb);
+
+	writel(0, fbi->regbase);
+
+	if (fbi->fb.cmap.len)
+		fb_dealloc_cmap(&fbi->fb.cmap);
+
+	free_pages_exact(fbi->fb.screen_base, fbi->fb.screen_size);
+
+	iounmap(fbi->regbase);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(fbi);
+
+	return 0;
+}
+
+static struct platform_driver wm8505fb_driver = {
+	.probe		= wm8505fb_probe,
+	.remove		= wm8505fb_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init wm8505fb_init(void)
+{
+	return platform_driver_register(&wm8505fb_driver);
+}
+
+static void __exit wm8505fb_exit(void)
+{
+	platform_driver_unregister(&wm8505fb_driver);
+}
+
+module_init(wm8505fb_init);
+module_exit(wm8505fb_exit);
+
+MODULE_DESCRIPTION("Framebuffer driver for WMT WM8505");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/wm8505fb_regs.h b/drivers/video/wm8505fb_regs.h
new file mode 100644
index 0000000..4dd4166
--- /dev/null
+++ b/drivers/video/wm8505fb_regs.h
@@ -0,0 +1,76 @@
+/*
+ *  GOVR registers list for WM8505 chips
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *   Based on VIA/WonderMedia wm8510-govrh-reg.h
+ *   http://github.com/projectgus/kernel_wm8505/blob/wm8505_2.6.29/
+ *         drivers/video/wmt/register/wm8510/wm8510-govrh-reg.h
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _WM8505FB_REGS_H
+#define _WM8505FB_REGS_H
+
+/*
+ * Color space select register, default value 0x1c
+ *   BIT0 GOVRH_DVO_YUV2RGB_ENABLE
+ *   BIT1 GOVRH_VGA_YUV2RGB_ENABLE
+ *   BIT2 GOVRH_RGB_MODE
+ *   BIT3 GOVRH_DAC_CLKINV
+ *   BIT4 GOVRH_BLANK_ZERO
+ */
+#define WMT_GOVR_COLORSPACE	0x1e4
+/*
+ * Another colorspace select register, default value 1
+ *   BIT0 GOVRH_DVO_RGB
+ *   BIT1 GOVRH_DVO_YUV422
+ */
+#define WMT_GOVR_COLORSPACE1	 0x30
+
+#define WMT_GOVR_CONTRAST	0x1b8
+#define WMT_GOVR_BRGHTNESS	0x1bc /* incompatible with RGB? */
+
+/* Framubeffer address */
+#define WMT_GOVR_FBADDR		 0x90
+#define WMT_GOVR_FBADDR1	 0x94 /* UV offset in YUV mode */
+
+/* Offset of visible window */
+#define WMT_GOVR_XPAN		 0xa4
+#define WMT_GOVR_YPAN		 0xa0
+
+#define WMT_GOVR_XRES		 0x98
+#define WMT_GOVR_XRES_VIRTUAL	 0x9c
+
+#define WMT_GOVR_MIF_ENABLE	 0x80
+#define WMT_GOVR_FHI		 0xa8
+#define WMT_GOVR_REG_UPDATE	 0xe4
+
+/*
+ *   BIT0 GOVRH_DVO_OUTWIDTH
+ *   BIT1 GOVRH_DVO_SYNC_POLAR
+ *   BIT2 GOVRH_DVO_ENABLE
+ */
+#define WMT_GOVR_DVO_SET	0x148
+
+/* Timing generator? */
+#define WMT_GOVR_TG		0x100
+
+/* Timings */
+#define WMT_GOVR_TIMING_H_ALL	0x108
+#define WMT_GOVR_TIMING_V_ALL	0x10c
+#define WMT_GOVR_TIMING_V_START	0x110
+#define WMT_GOVR_TIMING_V_END	0x114
+#define WMT_GOVR_TIMING_H_START	0x118
+#define WMT_GOVR_TIMING_H_END	0x11c
+#define WMT_GOVR_TIMING_V_SYNC	0x128
+#define WMT_GOVR_TIMING_H_SYNC	0x12c
+
+#endif /* _WM8505FB_REGS_H */
diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/wmt_ge_rops.c
new file mode 100644
index 0000000..c71f97e
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.c
@@ -0,0 +1,186 @@
+/*
+ *  linux/drivers/video/wmt_ge_rops.c
+ *
+ *  Accelerators for raster operations using WonderMedia Graphics Engine
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/fb.h>
+#include <linux/platform_device.h>
+#include "fb_draw.h"
+
+#define GE_COMMAND_OFF		0x00
+#define GE_DEPTH_OFF		0x04
+#define GE_HIGHCOLOR_OFF	0x08
+#define GE_ROPCODE_OFF		0x14
+#define GE_FIRE_OFF		0x18
+#define GE_SRCBASE_OFF		0x20
+#define GE_SRCDISPW_OFF		0x24
+#define GE_SRCDISPH_OFF		0x28
+#define GE_SRCAREAX_OFF		0x2c
+#define GE_SRCAREAY_OFF		0x30
+#define GE_SRCAREAW_OFF		0x34
+#define GE_SRCAREAH_OFF		0x38
+#define GE_DESTBASE_OFF		0x3c
+#define GE_DESTDISPW_OFF	0x40
+#define GE_DESTDISPH_OFF	0x44
+#define GE_DESTAREAX_OFF	0x48
+#define GE_DESTAREAY_OFF	0x4c
+#define GE_DESTAREAW_OFF	0x50
+#define GE_DESTAREAH_OFF	0x54
+#define GE_PAT0C_OFF		0x88	/* Pattern 0 color */
+#define GE_ENABLE_OFF		0xec
+#define GE_INTEN_OFF		0xf0
+#define GE_STATUS_OFF		0xf8
+
+void __iomem *regbase;
+
+void wmt_ge_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
+{
+	unsigned long fg, pat;
+
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
+	    p->fix.visual == FB_VISUAL_DIRECTCOLOR)
+		fg = ((u32 *) (p->pseudo_palette))[rect->color];
+	else
+		fg = rect->color;
+
+	pat = pixel_to_pat(p->var.bits_per_pixel, fg);
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	writel(p->var.bits_per_pixel == 32 ? 3 :
+	      (p->var.bits_per_pixel == 8 ? 0 : 1), regbase + GE_DEPTH_OFF);
+	writel(p->var.bits_per_pixel == 15 ? 1 : 0, regbase + GE_HIGHCOLOR_OFF);
+	writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+	writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+	writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+	writel(rect->dx, regbase + GE_DESTAREAX_OFF);
+	writel(rect->dy, regbase + GE_DESTAREAY_OFF);
+	writel(rect->width - 1, regbase + GE_DESTAREAW_OFF);
+	writel(rect->height - 1, regbase + GE_DESTAREAH_OFF);
+
+	writel(pat, regbase + GE_PAT0C_OFF);
+	writel(1, regbase + GE_COMMAND_OFF);
+	writel(rect->rop == ROP_XOR ? 0x5a : 0xf0, regbase + GE_ROPCODE_OFF);
+	writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL(wmt_ge_fillrect);
+
+void wmt_ge_copyarea(struct fb_info *p, const struct fb_copyarea *area)
+{
+	if (p->state != FBINFO_STATE_RUNNING)
+		return;
+
+	if (p->fbops->fb_sync)
+		p->fbops->fb_sync(p);
+
+	writel(p->var.bits_per_pixel > 16 ? 3 :
+	      (p->var.bits_per_pixel > 8 ? 1 : 0), regbase + GE_DEPTH_OFF);
+
+	writel(p->fix.smem_start, regbase + GE_SRCBASE_OFF);
+	writel(p->var.xres_virtual - 1, regbase + GE_SRCDISPW_OFF);
+	writel(p->var.yres_virtual - 1, regbase + GE_SRCDISPH_OFF);
+	writel(area->sx, regbase + GE_SRCAREAX_OFF);
+	writel(area->sy, regbase + GE_SRCAREAY_OFF);
+	writel(area->width - 1, regbase + GE_SRCAREAW_OFF);
+	writel(area->height - 1, regbase + GE_SRCAREAH_OFF);
+
+	writel(p->fix.smem_start, regbase + GE_DESTBASE_OFF);
+	writel(p->var.xres_virtual - 1, regbase + GE_DESTDISPW_OFF);
+	writel(p->var.yres_virtual - 1, regbase + GE_DESTDISPH_OFF);
+	writel(area->dx, regbase + GE_DESTAREAX_OFF);
+	writel(area->dy, regbase + GE_DESTAREAY_OFF);
+	writel(area->width - 1, regbase + GE_DESTAREAW_OFF);
+	writel(area->height - 1, regbase + GE_DESTAREAH_OFF);
+
+	writel(0xcc, regbase + GE_ROPCODE_OFF);
+	writel(1, regbase + GE_COMMAND_OFF);
+	writel(1, regbase + GE_FIRE_OFF);
+}
+EXPORT_SYMBOL(wmt_ge_copyarea);
+
+int wmt_ge_sync(struct fb_info *p)
+{
+	while (readl(regbase + GE_STATUS_OFF) & 4)
+		/* busy wait */;
+
+	return 0;
+}
+EXPORT_SYMBOL(wmt_ge_sync);
+
+static int __devinit wmt_ge_rops_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "no I/O memory resource defined\n");
+		ret = -ENODEV;
+		goto error;
+	}
+
+	regbase = ioremap(res->start, resource_size(res));
+	if (regbase == NULL) {
+		dev_err(&pdev->dev, "failed to map I/O memory\n");
+		ret = -EBUSY;
+		goto error;
+	}
+
+	writel(1, regbase + GE_ENABLE_OFF);
+	printk(KERN_INFO "Enabled support for WMT GE raster acceleration\n");
+
+	return 0;
+
+error:
+	return ret;
+}
+
+static int __devexit wmt_ge_rops_remove(struct platform_device *pdev)
+{
+	iounmap(regbase);
+	return 0;
+}
+
+static struct platform_driver wmt_ge_rops_driver = {
+	.probe		= wmt_ge_rops_probe,
+	.remove		= wmt_ge_rops_remove,
+	.driver		= {
+		.owner	= THIS_MODULE,
+		.name	= "wmt_ge_rops",
+	},
+};
+
+static int __init wmt_ge_rops_init(void)
+{
+	return platform_driver_register(&wmt_ge_rops_driver);
+}
+
+static void __exit wmt_ge_rops_exit(void)
+{
+	platform_driver_unregister(&wmt_ge_rops_driver);
+}
+
+module_init(wmt_ge_rops_init);
+module_exit(wmt_ge_rops_exit);
+
+MODULE_AUTHOR("Alexey Charkov <alchark@gmail.com");
+MODULE_DESCRIPTION("Accelerators for raster operations using "
+		   "WonderMedia Graphics Engine");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/wmt_ge_rops.h
new file mode 100644
index 0000000..8738075
--- /dev/null
+++ b/drivers/video/wmt_ge_rops.h
@@ -0,0 +1,5 @@
+extern void wmt_ge_fillrect(struct fb_info *info,
+			    const struct fb_fillrect *rect);
+extern void wmt_ge_copyarea(struct fb_info *info,
+			    const struct fb_copyarea *area);
+extern int wmt_ge_sync(struct fb_info *info);
-- 
1.7.3.1


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

* Re: [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042
  2010-10-20 20:55 ` [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042 Alexey Charkov
@ 2010-10-20 21:15   ` Dmitry Torokhov
  2010-10-20 21:24     ` Alexey Charkov
  2010-10-20 22:14     ` [PATCH 3/6 v2] " Alexey Charkov
  2010-10-30 22:23   ` [PATCH 3/6] " Ben Dooks
  1 sibling, 2 replies; 27+ messages in thread
From: Dmitry Torokhov @ 2010-10-20 21:15 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, linux-input, linux-kernel

On Wednesday, October 20, 2010 01:55:35 pm Alexey Charkov wrote:
> VIA and WonderMedia Systems-on-Chip feature a standard i8042-compatible
> keyboard and mouse controller. This adds necessary glue to enable use
> of the standard driver with these systems.
> 
> Signed-off-by: Alexey Charkov <alchark@gmail.com>
> ---
> 
> Please review and state whether this could be acceptable for a merge
> to mainline in the coming 2.6.37 window. If possible, I would deeply
> appreciate a merge to a relevant git tree for integration prior to
> asking Linus to pull the changes. I could rebase the code if needed,
> currently this is against Linus' master branch.
> 
> This patch relies on the basic architecture support for VT8500/WM8505
> to be in place, as introduced by PATCH 1/6 in this series.

What tree this code will be coming through through?

> +
> +static inline int i8042_platform_init(void)
> +{
> +	i8042_reset = 1;

= true; - it's a boolean.

> +	regbase = ioremap(VT8500_PS2_BASE, SZ_1K);

Error handling?

Thanks.

-- 
Dmitry

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

* Re: [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles
  2010-10-20 20:55 ` [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles Alexey Charkov
@ 2010-10-20 21:16   ` Greg KH
  2010-10-20 21:31     ` Alexey Charkov
  0 siblings, 1 reply; 27+ messages in thread
From: Greg KH @ 2010-10-20 21:16 UTC (permalink / raw)
  To: Alexey Charkov; +Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, linux-kernel

On Thu, Oct 21, 2010 at 12:55:34AM +0400, Alexey Charkov wrote:
> This adds a driver for the serial ports found in VIA and WonderMedia
> Systems-on-Chip. Interrupt-driven FIFO operation is implemented.
> The hardware also supports pure register-based operation (which is
> slower) and DMA-based FIFO operation. As the FIFOs are only 16 bytes
> long, DMA operation is probably not worth the hassle.
> 
> Signed-off-by: Alexey Charkov <alchark@gmail.com>
> ---
> 
> Please review and state whether this could be acceptable for a merge
> to mainline in the coming 2.6.37 window.

.37?  Aren't you cutting it a bit close here?  My trees unofficially
closed a few days or so ago for new stuff to go to .37, what kept this
from being sent previously?

> If possible, I would deeply appreciate a merge to a relevant git tree
> for integration prior to asking Linus to pull the changes. I could
> rebase the code if needed, currently this is against Linus' master
> branch.
> 
> This patch relies on the basic architecture support for VT8500/WM8505
> to be in place, as introduced by PATCH 1/6 in this series.

So it will just fail to build without that patch?

thanks,

greg k-h

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

* Re: [PATCH 4/6] usb: Add support for VIA VT8500 and compatibles in EHCI HCD
  2010-10-20 20:55 ` [PATCH 4/6] usb: Add support for VIA VT8500 and compatibles in EHCI HCD Alexey Charkov
@ 2010-10-20 21:17   ` Greg KH
  2010-10-20 22:41     ` Alexey Charkov
  0 siblings, 1 reply; 27+ messages in thread
From: Greg KH @ 2010-10-20 21:17 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, David Brownell,
	linux-usb, linux-kernel

On Thu, Oct 21, 2010 at 12:55:36AM +0400, Alexey Charkov wrote:
> VIA and WonderMedia Systems-on-Chip feature a standard EHCI host
> controller. This adds necessary glue to use the standard driver
> with these systems.
> 
> Signed-off-by: Alexey Charkov <alchark@gmail.com>
> ---
> 
> Please review and state whether this could be acceptable for a merge
> to mainline in the coming 2.6.37 window. If possible, I would deeply
> appreciate a merge to a relevant git tree for integration prior to
> asking Linus to pull the changes. I could rebase the code if needed,
> currently this is against Linus' master branch.
> 
> This patch relies on the basic architecture support for VT8500/WM8505
> to be in place, as introduced by PATCH 1/6 in this series.

Will this code fail to build without that patch?

thanks,

greg k-h

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

* Re: [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042
  2010-10-20 21:15   ` Dmitry Torokhov
@ 2010-10-20 21:24     ` Alexey Charkov
  2010-10-20 22:14     ` [PATCH 3/6 v2] " Alexey Charkov
  1 sibling, 0 replies; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 21:24 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, linux-input, linux-kernel

2010/10/21 Dmitry Torokhov <dmitry.torokhov@gmail.com>
>
> On Wednesday, October 20, 2010 01:55:35 pm Alexey Charkov wrote:
> > VIA and WonderMedia Systems-on-Chip feature a standard i8042-compatible
> > keyboard and mouse controller. This adds necessary glue to enable use
> > of the standard driver with these systems.
> >
> > Signed-off-by: Alexey Charkov <alchark@gmail.com>
> > ---
> >
> > Please review and state whether this could be acceptable for a merge
> > to mainline in the coming 2.6.37 window. If possible, I would deeply
> > appreciate a merge to a relevant git tree for integration prior to
> > asking Linus to pull the changes. I could rebase the code if needed,
> > currently this is against Linus' master branch.
> >
> > This patch relies on the basic architecture support for VT8500/WM8505
> > to be in place, as introduced by PATCH 1/6 in this series.
>
> What tree this code will be coming through through?
>

Should be Russel King's ARM tree, probably. The whole series is CC'd
to linux-arm-kernel and to the relevant subsystems maintainers, as I
was instructed to do at a previous submission attempt.

> > +
> > +static inline int i8042_platform_init(void)
> > +{
> > +     i8042_reset = 1;
>
> = true; - it's a boolean.
>

Got it, thanks.

> > +     regbase = ioremap(VT8500_PS2_BASE, SZ_1K);
>
> Error handling?
>

Ok, I've missed this. Will be fixed.

> Thanks.
>
> --
> Dmitry

Thanks for your review, Dmitry! Are there any other issues with this
or is it otherwise good enough to receive your Ack?

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

* Re: [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles
  2010-10-20 21:16   ` Greg KH
@ 2010-10-20 21:31     ` Alexey Charkov
  2010-10-20 22:38       ` Greg KH
  0 siblings, 1 reply; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 21:31 UTC (permalink / raw)
  To: Greg KH; +Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, linux-kernel

2010/10/21 Greg KH <gregkh@suse.de>:
> On Thu, Oct 21, 2010 at 12:55:34AM +0400, Alexey Charkov wrote:
>> This adds a driver for the serial ports found in VIA and WonderMedia
>> Systems-on-Chip. Interrupt-driven FIFO operation is implemented.
>> The hardware also supports pure register-based operation (which is
>> slower) and DMA-based FIFO operation. As the FIFOs are only 16 bytes
>> long, DMA operation is probably not worth the hassle.
>>
>> Signed-off-by: Alexey Charkov <alchark@gmail.com>
>> ---
>>
>> Please review and state whether this could be acceptable for a merge
>> to mainline in the coming 2.6.37 window.
>
> .37?  Aren't you cutting it a bit close here?  My trees unofficially
> closed a few days or so ago for new stuff to go to .37, what kept this
> from being sent previously?
>

In fact, I'm somewhat new to kernel development, and have not yet
understood the good timings to do things properly. My view was that
the merge window is when new stuff should be submitted, while
everything in between is devoted to fixing breakage just introduced.
So, I must have been wrong :)

>> If possible, I would deeply appreciate a merge to a relevant git tree
>> for integration prior to asking Linus to pull the changes. I could
>> rebase the code if needed, currently this is against Linus' master
>> branch.
>>
>> This patch relies on the basic architecture support for VT8500/WM8505
>> to be in place, as introduced by PATCH 1/6 in this series.
>
> So it will just fail to build without that patch?
>

It won't, and it should not even be selectable, as there is a Kconfig
dependency on the relevant arch. It's just that it would be useless
without the relevant arch support.

> thanks,
>
> greg k-h
>

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

* [PATCH 3/6 v2] input: Add support for VIA VT8500 and compatibles in i8042
  2010-10-20 21:15   ` Dmitry Torokhov
  2010-10-20 21:24     ` Alexey Charkov
@ 2010-10-20 22:14     ` Alexey Charkov
  2010-10-20 23:46       ` Dmitry Torokhov
  1 sibling, 1 reply; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 22:14 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Alexey Charkov, vt8500-wm8505-linux-kernel, linux-arm-kernel,
	linux-input, linux-kernel

VIA and WonderMedia Systems-on-Chip feature a standard i8042-compatible
keyboard and mouse controller. This adds necessary glue to enable use
of the standard driver with these systems.

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---

This is to incorporate fixes to issues noted by Dmitry at the first attempt.

 drivers/input/serio/Kconfig        |    3 +-
 drivers/input/serio/i8042-vt8500.h |   74 ++++++++++++++++++++++++++++++++++++
 drivers/input/serio/i8042.h        |    2 +
 3 files changed, 78 insertions(+), 1 deletions(-)
 create mode 100644 drivers/input/serio/i8042-vt8500.h

diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index 3bfe8fa..2b86774 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -21,7 +21,8 @@ if SERIO
 config SERIO_I8042
 	tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
 	default y
-	depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
+	depends on !PARISC && \
+		  (!ARM || ARCH_SHARK || ARCH_VT8500 || FOOTBRIDGE_HOST) && \
 		   (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN
 	help
 	  i8042 is the chip over which the standard AT keyboard and PS/2
diff --git a/drivers/input/serio/i8042-vt8500.h b/drivers/input/serio/i8042-vt8500.h
new file mode 100644
index 0000000..6a709b6
--- /dev/null
+++ b/drivers/input/serio/i8042-vt8500.h
@@ -0,0 +1,74 @@
+#ifndef _I8042_VT8500_H
+#define _I8042_VT8500_H
+
+#include <mach/irqs.h>
+#include <mach/vt8500.h>
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ */
+
+static void __iomem *regbase;
+
+/*
+ * Names.
+ */
+
+#define I8042_KBD_PHYS_DESC "vt8500ps2/serio0"
+#define I8042_AUX_PHYS_DESC "vt8500ps2/serio1"
+#define I8042_MUX_PHYS_DESC "vt8500ps2/serio%d"
+
+/*
+ * IRQs.
+ */
+
+#define I8042_KBD_IRQ	IRQ_PS2KBD
+#define I8042_AUX_IRQ	IRQ_PS2MOUSE
+
+
+/*
+ * Register numbers.
+ */
+
+#define I8042_COMMAND_REG	(regbase + 0x4)
+#define I8042_STATUS_REG	(regbase + 0x4)
+#define I8042_DATA_REG		(regbase + 0x0)
+
+static inline int i8042_read_data(void)
+{
+	return readl(I8042_DATA_REG);
+}
+
+static inline int i8042_read_status(void)
+{
+	return readl(I8042_STATUS_REG);
+}
+
+static inline void i8042_write_data(int val)
+{
+	writel(val, I8042_DATA_REG);
+}
+
+static inline void i8042_write_command(int val)
+{
+	writel(val, I8042_COMMAND_REG);
+}
+
+static inline int i8042_platform_init(void)
+{
+	i8042_reset = true;
+	regbase = ioremap(VT8500_PS2_BASE, SZ_1K);
+	if (!regbase)
+		return -ENODEV;
+
+	return 0;
+}
+
+static inline void i8042_platform_exit(void)
+{
+	iounmap(regbase);
+}
+
+#endif /* _I8042_VT8500_H */
diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
index cbc1beb..bdb2aeb 100644
--- a/drivers/input/serio/i8042.h
+++ b/drivers/input/serio/i8042.h
@@ -16,6 +16,8 @@
 
 #if defined(CONFIG_MACH_JAZZ)
 #include "i8042-jazzio.h"
+#elif defined(CONFIG_ARCH_VT8500)
+#include "i8042-vt8500.h"
 #elif defined(CONFIG_SGI_HAS_I8042)
 #include "i8042-ip22io.h"
 #elif defined(CONFIG_SNI_RM)
-- 
1.7.3.1


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

* Re: [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles
  2010-10-20 21:31     ` Alexey Charkov
@ 2010-10-20 22:38       ` Greg KH
  2010-10-20 22:48         ` Alexey Charkov
  0 siblings, 1 reply; 27+ messages in thread
From: Greg KH @ 2010-10-20 22:38 UTC (permalink / raw)
  To: Alexey Charkov; +Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, linux-kernel

On Thu, Oct 21, 2010 at 01:31:41AM +0400, Alexey Charkov wrote:
> 2010/10/21 Greg KH <gregkh@suse.de>:
> > On Thu, Oct 21, 2010 at 12:55:34AM +0400, Alexey Charkov wrote:
> >> This adds a driver for the serial ports found in VIA and WonderMedia
> >> Systems-on-Chip. Interrupt-driven FIFO operation is implemented.
> >> The hardware also supports pure register-based operation (which is
> >> slower) and DMA-based FIFO operation. As the FIFOs are only 16 bytes
> >> long, DMA operation is probably not worth the hassle.
> >>
> >> Signed-off-by: Alexey Charkov <alchark@gmail.com>
> >> ---
> >>
> >> Please review and state whether this could be acceptable for a merge
> >> to mainline in the coming 2.6.37 window.
> >
> > .37? ??Aren't you cutting it a bit close here? ??My trees unofficially
> > closed a few days or so ago for new stuff to go to .37, what kept this
> > from being sent previously?
> >
> 
> In fact, I'm somewhat new to kernel development, and have not yet
> understood the good timings to do things properly.

Please read the information in Documentation/development_process, it
will help you out a lot.

> My view was that the merge window is when new stuff should be
> submitted, while everything in between is devoted to fixing breakage
> just introduced.  So, I must have been wrong :)

The merge window is for the subsystem maintainers, not the individual
developers.  You need to have the code into a subsystem tree before the
merge window in order to be able to get it accepted.

> >> If possible, I would deeply appreciate a merge to a relevant git tree
> >> for integration prior to asking Linus to pull the changes. I could
> >> rebase the code if needed, currently this is against Linus' master
> >> branch.
> >>
> >> This patch relies on the basic architecture support for VT8500/WM8505
> >> to be in place, as introduced by PATCH 1/6 in this series.
> >
> > So it will just fail to build without that patch?
> >
> 
> It won't, and it should not even be selectable, as there is a Kconfig
> dependency on the relevant arch. It's just that it would be useless
> without the relevant arch support.

That's good to know.

As the .37 merge window just opened, you are going to have to wait until
2.6.37-rc1 before anyone will be able to have the time to review and
accept these patches, sorry.  Please resend them then.

thanks,

greg k-h

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

* Re: [PATCH 4/6] usb: Add support for VIA VT8500 and compatibles in EHCI HCD
  2010-10-20 21:17   ` Greg KH
@ 2010-10-20 22:41     ` Alexey Charkov
  2010-10-20 22:47       ` Greg KH
  0 siblings, 1 reply; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 22:41 UTC (permalink / raw)
  To: Greg KH
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, David Brownell,
	linux-usb, linux-kernel

2010/10/21 Greg KH <gregkh@suse.de>:
> On Thu, Oct 21, 2010 at 12:55:36AM +0400, Alexey Charkov wrote:
>> VIA and WonderMedia Systems-on-Chip feature a standard EHCI host
>> controller. This adds necessary glue to use the standard driver
>> with these systems.
>>
>> Signed-off-by: Alexey Charkov <alchark@gmail.com>
>> ---
>>
>> Please review and state whether this could be acceptable for a merge
>> to mainline in the coming 2.6.37 window. If possible, I would deeply
>> appreciate a merge to a relevant git tree for integration prior to
>> asking Linus to pull the changes. I could rebase the code if needed,
>> currently this is against Linus' master branch.
>>
>> This patch relies on the basic architecture support for VT8500/WM8505
>> to be in place, as introduced by PATCH 1/6 in this series.
>
> Will this code fail to build without that patch?
>

As all the additions are ifdef-ed, it won't unless somebody manually
defines CONFIG_ARCH_VT8500. But in that case the person should
probably know what (s)he is doing.

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

* Re: [PATCH 4/6] usb: Add support for VIA VT8500 and compatibles in EHCI HCD
  2010-10-20 22:41     ` Alexey Charkov
@ 2010-10-20 22:47       ` Greg KH
  2010-10-20 22:54         ` Alexey Charkov
  0 siblings, 1 reply; 27+ messages in thread
From: Greg KH @ 2010-10-20 22:47 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, David Brownell,
	linux-usb, linux-kernel

On Thu, Oct 21, 2010 at 02:41:54AM +0400, Alexey Charkov wrote:
> 2010/10/21 Greg KH <gregkh@suse.de>:
> > On Thu, Oct 21, 2010 at 12:55:36AM +0400, Alexey Charkov wrote:
> >> VIA and WonderMedia Systems-on-Chip feature a standard EHCI host
> >> controller. This adds necessary glue to use the standard driver
> >> with these systems.
> >>
> >> Signed-off-by: Alexey Charkov <alchark@gmail.com>
> >> ---
> >>
> >> Please review and state whether this could be acceptable for a merge
> >> to mainline in the coming 2.6.37 window. If possible, I would deeply
> >> appreciate a merge to a relevant git tree for integration prior to
> >> asking Linus to pull the changes. I could rebase the code if needed,
> >> currently this is against Linus' master branch.
> >>
> >> This patch relies on the basic architecture support for VT8500/WM8505
> >> to be in place, as introduced by PATCH 1/6 in this series.
> >
> > Will this code fail to build without that patch?
> >
> 
> As all the additions are ifdef-ed, it won't unless somebody manually
> defines CONFIG_ARCH_VT8500. But in that case the person should
> probably know what (s)he is doing.

Ok, how about we wait for the core code to be accepted, and then have
you resend the drivers for submission?

Make sense?

thanks,

greg k-h

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

* Re: [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles
  2010-10-20 22:38       ` Greg KH
@ 2010-10-20 22:48         ` Alexey Charkov
  0 siblings, 0 replies; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 22:48 UTC (permalink / raw)
  To: Greg KH; +Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, linux-kernel

2010/10/21 Greg KH <gregkh@suse.de>:
> On Thu, Oct 21, 2010 at 01:31:41AM +0400, Alexey Charkov wrote:
>> 2010/10/21 Greg KH <gregkh@suse.de>:
>> > On Thu, Oct 21, 2010 at 12:55:34AM +0400, Alexey Charkov wrote:
>> >> This adds a driver for the serial ports found in VIA and WonderMedia
>> >> Systems-on-Chip. Interrupt-driven FIFO operation is implemented.
>> >> The hardware also supports pure register-based operation (which is
>> >> slower) and DMA-based FIFO operation. As the FIFOs are only 16 bytes
>> >> long, DMA operation is probably not worth the hassle.
>> >>
>> >> Signed-off-by: Alexey Charkov <alchark@gmail.com>
>> >> ---
>> >>
>> >> Please review and state whether this could be acceptable for a merge
>> >> to mainline in the coming 2.6.37 window.
>> >
>> > .37? ??Aren't you cutting it a bit close here? ??My trees unofficially
>> > closed a few days or so ago for new stuff to go to .37, what kept this
>> > from being sent previously?
>> >
>>
>> In fact, I'm somewhat new to kernel development, and have not yet
>> understood the good timings to do things properly.
>
> Please read the information in Documentation/development_process, it
> will help you out a lot.
>
>> My view was that the merge window is when new stuff should be
>> submitted, while everything in between is devoted to fixing breakage
>> just introduced.  So, I must have been wrong :)
>
> The merge window is for the subsystem maintainers, not the individual
> developers.  You need to have the code into a subsystem tree before the
> merge window in order to be able to get it accepted.
>
>> >> If possible, I would deeply appreciate a merge to a relevant git tree
>> >> for integration prior to asking Linus to pull the changes. I could
>> >> rebase the code if needed, currently this is against Linus' master
>> >> branch.
>> >>
>> >> This patch relies on the basic architecture support for VT8500/WM8505
>> >> to be in place, as introduced by PATCH 1/6 in this series.
>> >
>> > So it will just fail to build without that patch?
>> >
>>
>> It won't, and it should not even be selectable, as there is a Kconfig
>> dependency on the relevant arch. It's just that it would be useless
>> without the relevant arch support.
>
> That's good to know.
>
> As the .37 merge window just opened, you are going to have to wait until
> 2.6.37-rc1 before anyone will be able to have the time to review and
> accept these patches, sorry.  Please resend them then.
>
> thanks,
>
> greg k-h
>

Thanks for the directions, Greg! Probably we will have more things to
submit by then, so it does not really hurt.

Best regards,
Alexey

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

* Re: [PATCH 4/6] usb: Add support for VIA VT8500 and compatibles in EHCI HCD
  2010-10-20 22:47       ` Greg KH
@ 2010-10-20 22:54         ` Alexey Charkov
  0 siblings, 0 replies; 27+ messages in thread
From: Alexey Charkov @ 2010-10-20 22:54 UTC (permalink / raw)
  To: Greg KH
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, David Brownell,
	linux-usb, linux-kernel

2010/10/21 Greg KH <gregkh@suse.de>:
> On Thu, Oct 21, 2010 at 02:41:54AM +0400, Alexey Charkov wrote:
>> 2010/10/21 Greg KH <gregkh@suse.de>:
>> > On Thu, Oct 21, 2010 at 12:55:36AM +0400, Alexey Charkov wrote:
>> >> VIA and WonderMedia Systems-on-Chip feature a standard EHCI host
>> >> controller. This adds necessary glue to use the standard driver
>> >> with these systems.
>> >>
>> >> Signed-off-by: Alexey Charkov <alchark@gmail.com>
>> >> ---
>> >>
>> >> Please review and state whether this could be acceptable for a merge
>> >> to mainline in the coming 2.6.37 window. If possible, I would deeply
>> >> appreciate a merge to a relevant git tree for integration prior to
>> >> asking Linus to pull the changes. I could rebase the code if needed,
>> >> currently this is against Linus' master branch.
>> >>
>> >> This patch relies on the basic architecture support for VT8500/WM8505
>> >> to be in place, as introduced by PATCH 1/6 in this series.
>> >
>> > Will this code fail to build without that patch?
>> >
>>
>> As all the additions are ifdef-ed, it won't unless somebody manually
>> defines CONFIG_ARCH_VT8500. But in that case the person should
>> probably know what (s)he is doing.
>
> Ok, how about we wait for the core code to be accepted, and then have
> you resend the drivers for submission?
>
> Make sense?
>

For me, it's perfectly fine. I was just a bit uncomfortable about
submitting the core code with platform data for missing drivers, which
take quite a sizeable part of that PATCH 1/6.

> thanks,
>
> greg k-h
>

Best regards,
Alexey

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

* Re: [PATCH 3/6 v2] input: Add support for VIA VT8500 and compatibles in i8042
  2010-10-20 22:14     ` [PATCH 3/6 v2] " Alexey Charkov
@ 2010-10-20 23:46       ` Dmitry Torokhov
  0 siblings, 0 replies; 27+ messages in thread
From: Dmitry Torokhov @ 2010-10-20 23:46 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, linux-input, linux-kernel

On Thu, Oct 21, 2010 at 02:14:49AM +0400, Alexey Charkov wrote:
> VIA and WonderMedia Systems-on-Chip feature a standard i8042-compatible
> keyboard and mouse controller. This adds necessary glue to enable use
> of the standard driver with these systems.
> 
> Signed-off-by: Alexey Charkov <alchark@gmail.com>

Acked-by: Dmitry Torokhov <dtor@mail.ru>

Thanks.

-- 
Dmitry

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

* Re: [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's
  2010-10-20 20:55 [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Alexey Charkov
                   ` (4 preceding siblings ...)
  2010-10-20 20:55 ` [PATCH 6/6] ARM: Add support for the display controllers in VT8500 and WM8505 Alexey Charkov
@ 2010-10-21  8:05 ` Arnd Bergmann
  2010-10-21  9:52   ` Alexey Charkov
  5 siblings, 1 reply; 27+ messages in thread
From: Arnd Bergmann @ 2010-10-21  8:05 UTC (permalink / raw)
  To: vt8500-wm8505-linux-kernel
  Cc: Alexey Charkov, linux-arm-kernel, Russell King, linux-kernel

On Wednesday 20 October 2010 22:55:33 Alexey Charkov wrote:

> Please review and state whether this could be acceptable for a merge
> to mainline in the coming 2.6.37 window. If possible, I would deeply
> appreciate a merge to a relevant git tree for integration prior to
> asking Linus to pull the changes. I could rebase the code if needed,
> currently this is against Linus' master branch.

As Greg mentioned for his review of the serial drivers, it's too late
for 2.6.37. Fortunately that means you're really early for 2.6.38
and getting it in there should be easy.

The code does look very good though overall.

> +
> +choice
> +	prompt "LCD panel size"
> +	depends on (FB_VT8500 || FB_WM8505)
> +	default WMT_PANEL_800X480
> +
> +config WMT_PANEL_800X480
> +	bool "7-inch with 800x480 resolution"
> +	help
> +	  These are found in most of the netbooks in generic cases, as
> +	  well as in Eken M001 tablets and possibly elsewhere.
> +
> +config WMT_PANEL_800X600
> +	bool "8-inch with 800x600 resolution"
> +	help
> +	  These are found in Eken M003 tablets and possibly elsewhere.
> +
> +config WMT_PANEL_1024X600
> +	bool "10-inch with 1024x600 resolution"
> +	help
> +	  These are found in Eken M006 tablets and possibly elsewhere.
> +
> +endchoice

This should really be a run-time or at least boot-time option. If you
set the frame buffer size at compile time, I guess you can no longer
boot on a machine that uses a different size.

> +#include <mach/vt8500.h>
> +#include "devices.h"
> +
> +static struct platform_device *devices[] __initdata = {
> +	&vt8500_device_uart0,
> +#ifdef CONFIG_FB_VT8500
> +	&vt8500_device_lcdc,
> +#endif
> +#ifdef CONFIG_USB_EHCI_HCD
> +	&vt8500_device_ehci,
> +#endif
> +#ifdef CONFIG_FB_WMT_GE_ROPS
> +	&vt8500_device_ge_rops,
> +#endif
> +#ifdef CONFIG_HAVE_PWM
> +	&vt8500_device_pwm,
> +#endif
> +#ifdef CONFIG_BACKLIGHT_PWM
> +	&vt8500_device_pwmbl,
> +#endif
> +#ifdef CONFIG_RTC_DRV_VT8500
> +	&vt8500_device_rtc,
> +#endif
> +};

This doesn't work if the drivers are built as loadable modules, right?
I wouldn't even make the definitions of the devices configuration dependent.
The idea of the device model is that you describe what you have in one
place and use that information to load the drivers for it.

> +#ifdef CONFIG_VTWM_VERSION_WM8505
> +extern struct platform_device vt8500_device_uart4;
> +extern struct platform_device vt8500_device_uart5;
> +#endif
> +
> +#ifdef CONFIG_FB_VT8500
> +extern struct platform_device vt8500_device_lcdc;
> +#endif
> +#ifdef CONFIG_FB_WM8505
> +extern struct platform_device vt8500_device_wm8505_fb;
> +#endif
> +
> +#ifdef CONFIG_USB_EHCI_HCD
> +extern struct platform_device vt8500_device_ehci;
> +#endif
> +
> +#ifdef CONFIG_FB_WMT_GE_ROPS
> +extern struct platform_device vt8500_device_ge_rops;
> +#endif
> +#ifdef CONFIG_HAVE_PWM
> +extern struct platform_device vt8500_device_pwm;
> +#endif
> +#ifdef CONFIG_BACKLIGHT_PWM
> +extern struct platform_device vt8500_device_pwmbl;
> +#endif
> +#ifdef CONFIG_RTC_DRV_VT8500
> +extern struct platform_device vt8500_device_rtc;
> +#endif

The declarations never belong in an #ifdef, just make them
unconditional.

> +#ifndef __ASM_ARM_ARCH_IO_H
> +#define __ASM_ARM_ARCH_IO_H
> +
> +#define IO_SPACE_LIMIT 0xffffffff
> +
> +#define __io(a)		__typesafe_io(a)
> +#define __mem_pci(a)	(a)
> +
> +#endif


This won't work if you ever want to use the PCI on vt8505 with devices
that have I/O space mapping.

You need to define IO_SPACE_LIMIT to the size of your I/O space and
make the __io macro offset the address with the start of that window.

	Arnd

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

* Re: [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's
  2010-10-21  8:05 ` [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Arnd Bergmann
@ 2010-10-21  9:52   ` Alexey Charkov
  2010-10-21 12:01     ` Arnd Bergmann
  0 siblings, 1 reply; 27+ messages in thread
From: Alexey Charkov @ 2010-10-21  9:52 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, Russell King, linux-kernel

2010/10/21 Arnd Bergmann <arnd@arndb.de>:
> On Wednesday 20 October 2010 22:55:33 Alexey Charkov wrote:
>
>> Please review and state whether this could be acceptable for a merge
>> to mainline in the coming 2.6.37 window. If possible, I would deeply
>> appreciate a merge to a relevant git tree for integration prior to
>> asking Linus to pull the changes. I could rebase the code if needed,
>> currently this is against Linus' master branch.
>
> As Greg mentioned for his review of the serial drivers, it's too late
> for 2.6.37. Fortunately that means you're really early for 2.6.38
> and getting it in there should be easy.
>
> The code does look very good though overall.
>

Good to hear that, thanks!

>> +
>> +choice
>> +     prompt "LCD panel size"
>> +     depends on (FB_VT8500 || FB_WM8505)
>> +     default WMT_PANEL_800X480
>> +
>> +config WMT_PANEL_800X480
>> +     bool "7-inch with 800x480 resolution"
>> +     help
>> +       These are found in most of the netbooks in generic cases, as
>> +       well as in Eken M001 tablets and possibly elsewhere.
>> +
>> +config WMT_PANEL_800X600
>> +     bool "8-inch with 800x600 resolution"
>> +     help
>> +       These are found in Eken M003 tablets and possibly elsewhere.
>> +
>> +config WMT_PANEL_1024X600
>> +     bool "10-inch with 1024x600 resolution"
>> +     help
>> +       These are found in Eken M006 tablets and possibly elsewhere.
>> +
>> +endchoice
>
> This should really be a run-time or at least boot-time option. If you
> set the frame buffer size at compile time, I guess you can no longer
> boot on a machine that uses a different size.
>

It could be, but then I'd have to parse kernel command line at the
map_io stage. Is that fine? If yes, I could rework it to e.g. accept a
default value via Kconfig and allow it to be overriden via a boot
argument.

And due to the fact that the framebuffer size calculation is tied to
panel specification, it will boot in any case. The only problem that
one could encounter would be suboptimal display (for example,
offscreen pixmaps to become actually visible on screen if the panel is
taller
than expected, or some corruption in case it is wider).

>> +#include <mach/vt8500.h>
>> +#include "devices.h"
>> +
>> +static struct platform_device *devices[] __initdata = {
>> +     &vt8500_device_uart0,
>> +#ifdef CONFIG_FB_VT8500
>> +     &vt8500_device_lcdc,
>> +#endif
>> +#ifdef CONFIG_USB_EHCI_HCD
>> +     &vt8500_device_ehci,
>> +#endif
>> +#ifdef CONFIG_FB_WMT_GE_ROPS
>> +     &vt8500_device_ge_rops,
>> +#endif
>> +#ifdef CONFIG_HAVE_PWM
>> +     &vt8500_device_pwm,
>> +#endif
>> +#ifdef CONFIG_BACKLIGHT_PWM
>> +     &vt8500_device_pwmbl,
>> +#endif
>> +#ifdef CONFIG_RTC_DRV_VT8500
>> +     &vt8500_device_rtc,
>> +#endif
>> +};
>
> This doesn't work if the drivers are built as loadable modules, right?
> I wouldn't even make the definitions of the devices configuration dependent.
> The idea of the device model is that you describe what you have in one
> place and use that information to load the drivers for it.
>

But with loadable modules those symbols should still be defined as 'm'
or something, shouldn't they? Anyway, I'll drop those conditions,
thanks for pointing out.

>> +#ifdef CONFIG_VTWM_VERSION_WM8505
>> +extern struct platform_device vt8500_device_uart4;
>> +extern struct platform_device vt8500_device_uart5;
>> +#endif
>> +
>> +#ifdef CONFIG_FB_VT8500
>> +extern struct platform_device vt8500_device_lcdc;
>> +#endif
>> +#ifdef CONFIG_FB_WM8505
>> +extern struct platform_device vt8500_device_wm8505_fb;
>> +#endif
>> +
>> +#ifdef CONFIG_USB_EHCI_HCD
>> +extern struct platform_device vt8500_device_ehci;
>> +#endif
>> +
>> +#ifdef CONFIG_FB_WMT_GE_ROPS
>> +extern struct platform_device vt8500_device_ge_rops;
>> +#endif
>> +#ifdef CONFIG_HAVE_PWM
>> +extern struct platform_device vt8500_device_pwm;
>> +#endif
>> +#ifdef CONFIG_BACKLIGHT_PWM
>> +extern struct platform_device vt8500_device_pwmbl;
>> +#endif
>> +#ifdef CONFIG_RTC_DRV_VT8500
>> +extern struct platform_device vt8500_device_rtc;
>> +#endif
>
> The declarations never belong in an #ifdef, just make them
> unconditional.
>

Ok, got it.

>> +#ifndef __ASM_ARM_ARCH_IO_H
>> +#define __ASM_ARM_ARCH_IO_H
>> +
>> +#define IO_SPACE_LIMIT 0xffffffff
>> +
>> +#define __io(a)              __typesafe_io(a)
>> +#define __mem_pci(a) (a)
>> +
>> +#endif
>
>
> This won't work if you ever want to use the PCI on vt8505 with devices
> that have I/O space mapping.
>
> You need to define IO_SPACE_LIMIT to the size of your I/O space and
> make the __io macro offset the address with the start of that window.
>

The problem is that there is no documentation available for the PCI
bus in these systems (if it is even implemented there).
Vendor-provided sources do not really clarify it either, which you
have commented about at:
http://groups.google.com/group/vt8500-wm8505-linux-kernel/msg/97bf44bc5ea5d46a?

With no possibilities to test this (as I don't know any of these
devices to really use PCI with enumeration rather than just static
platform-like definitions as in the vendor's kernel), I just can't
imagine how this could be done any better.

>        Arnd
>

Thanks!
Alexey

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

* Re: [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's
  2010-10-21  9:52   ` Alexey Charkov
@ 2010-10-21 12:01     ` Arnd Bergmann
  2010-10-21 21:08       ` Alexey Charkov
  0 siblings, 1 reply; 27+ messages in thread
From: Arnd Bergmann @ 2010-10-21 12:01 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, Russell King, linux-kernel

On Thursday 21 October 2010, Alexey Charkov wrote:

> >> +
> >> +choice
> >> +     prompt "LCD panel size"
> >> +     depends on (FB_VT8500 || FB_WM8505)
> >> +     default WMT_PANEL_800X480
> >> +
> >> +config WMT_PANEL_800X480
> >> +     bool "7-inch with 800x480 resolution"
> >> +     help
> >> +       These are found in most of the netbooks in generic cases, as
> >> +       well as in Eken M001 tablets and possibly elsewhere.
> >> +
> >> +config WMT_PANEL_800X600
> >> +     bool "8-inch with 800x600 resolution"
> >> +     help
> >> +       These are found in Eken M003 tablets and possibly elsewhere.
> >> +
> >> +config WMT_PANEL_1024X600
> >> +     bool "10-inch with 1024x600 resolution"
> >> +     help
> >> +       These are found in Eken M006 tablets and possibly elsewhere.
> >> +
> >> +endchoice
> >
> > This should really be a run-time or at least boot-time option. If you
> > set the frame buffer size at compile time, I guess you can no longer
> > boot on a machine that uses a different size.
> >
> 
> It could be, but then I'd have to parse kernel command line at the
> map_io stage. Is that fine? If yes, I could rework it to e.g. accept a
> default value via Kconfig and allow it to be overriden via a boot
> argument.

Parsing complex options in general is not ok, but something simpler
probably is.

Having a Kconfig selected default is probably a good idea. The most
simple way to select this at boot time would be to have a list of
possible resolutions and pass a table index.

Would a __setup() call work for you?
 
> And due to the fact that the framebuffer size calculation is tied to
> panel specification, it will boot in any case. The only problem that
> one could encounter would be suboptimal display (for example,
> offscreen pixmaps to become actually visible on screen if the panel is
> taller
> than expected, or some corruption in case it is wider).

Another option might be to have a submenu with the possible resolutions
you want to allow and size the frame buffer for the largest of those,
but allow overriding the actual one at boot time.
 
> >> +#include <mach/vt8500.h>
> >> +#include "devices.h"
> >> +
> >> +static struct platform_device *devices[] __initdata = {
> >> +     &vt8500_device_uart0,
> >> +#ifdef CONFIG_FB_VT8500
> >> +     &vt8500_device_lcdc,
> >> +#endif
> >> +#ifdef CONFIG_USB_EHCI_HCD
> >> +     &vt8500_device_ehci,
> >> +#endif
> >> +#ifdef CONFIG_FB_WMT_GE_ROPS
> >> +     &vt8500_device_ge_rops,
> >> +#endif
> >> +#ifdef CONFIG_HAVE_PWM
> >> +     &vt8500_device_pwm,
> >> +#endif
> >> +#ifdef CONFIG_BACKLIGHT_PWM
> >> +     &vt8500_device_pwmbl,
> >> +#endif
> >> +#ifdef CONFIG_RTC_DRV_VT8500
> >> +     &vt8500_device_rtc,
> >> +#endif
> >> +};
> >
> > This doesn't work if the drivers are built as loadable modules, right?
> > I wouldn't even make the definitions of the devices configuration dependent.
> > The idea of the device model is that you describe what you have in one
> > place and use that information to load the drivers for it.
> >
> 
> But with loadable modules those symbols should still be defined as 'm'
> or something, shouldn't they? Anyway, I'll drop those conditions,
> thanks for pointing out.

If you configure an option as a module you get e.g. CONFIG_USB_EHCI_HCD_MODULE=1,
but CONFIG_USB_EHCI_HCD remains unset. It would be possible to check for
both of them, but IMHO it's cleaner to just leave the code in unconditionally.

> >> +#ifndef __ASM_ARM_ARCH_IO_H
> >> +#define __ASM_ARM_ARCH_IO_H
> >> +
> >> +#define IO_SPACE_LIMIT 0xffffffff
> >> +
> >> +#define __io(a)              __typesafe_io(a)
> >> +#define __mem_pci(a) (a)
> >> +
> >> +#endif
> >
> >
> > This won't work if you ever want to use the PCI on vt8505 with devices
> > that have I/O space mapping.
> >
> > You need to define IO_SPACE_LIMIT to the size of your I/O space and
> > make the __io macro offset the address with the start of that window.
> >
> 
> The problem is that there is no documentation available for the PCI
> bus in these systems (if it is even implemented there).
> Vendor-provided sources do not really clarify it either, which you
> have commented about at:
> http://groups.google.com/group/vt8500-wm8505-linux-kernel/msg/97bf44bc5ea5d46a?
> 
> With no possibilities to test this (as I don't know any of these
> devices to really use PCI with enumeration rather than just static
> platform-like definitions as in the vendor's kernel), I just can't
> imagine how this could be done any better.

I can have a look again. It shouldn't be hard to do an almost correct
implementation based on the source code we have, but I only own a wm8505
based device, so I also have no way of testing and it would very likely
have some subtle bugs.

	Arnd

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

* Re: [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's
  2010-10-21 12:01     ` Arnd Bergmann
@ 2010-10-21 21:08       ` Alexey Charkov
  2010-10-22  9:02         ` Arnd Bergmann
  0 siblings, 1 reply; 27+ messages in thread
From: Alexey Charkov @ 2010-10-21 21:08 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, Russell King, linux-kernel

2010/10/21 Arnd Bergmann <arnd@arndb.de>:
> On Thursday 21 October 2010, Alexey Charkov wrote:
>
>> >> +
>> >> +choice
>> >> +     prompt "LCD panel size"
>> >> +     depends on (FB_VT8500 || FB_WM8505)
>> >> +     default WMT_PANEL_800X480
>> >> +
>> >> +config WMT_PANEL_800X480
>> >> +     bool "7-inch with 800x480 resolution"
>> >> +     help
>> >> +       These are found in most of the netbooks in generic cases, as
>> >> +       well as in Eken M001 tablets and possibly elsewhere.
>> >> +
>> >> +config WMT_PANEL_800X600
>> >> +     bool "8-inch with 800x600 resolution"
>> >> +     help
>> >> +       These are found in Eken M003 tablets and possibly elsewhere.
>> >> +
>> >> +config WMT_PANEL_1024X600
>> >> +     bool "10-inch with 1024x600 resolution"
>> >> +     help
>> >> +       These are found in Eken M006 tablets and possibly elsewhere.
>> >> +
>> >> +endchoice
>> >
>> > This should really be a run-time or at least boot-time option. If you
>> > set the frame buffer size at compile time, I guess you can no longer
>> > boot on a machine that uses a different size.
>> >
>>
>> It could be, but then I'd have to parse kernel command line at the
>> map_io stage. Is that fine? If yes, I could rework it to e.g. accept a
>> default value via Kconfig and allow it to be overriden via a boot
>> argument.
>
> Parsing complex options in general is not ok, but something simpler
> probably is.
>
> Having a Kconfig selected default is probably a good idea. The most
> simple way to select this at boot time would be to have a list of
> possible resolutions and pass a table index.
>
> Would a __setup() call work for you?
>

Should probably be fine. Will it be allowable to accept something like
"panel=800x480" and strncmp it against a list of recognized values,
fall back to a Kconfig default on failure and printk the
possibilities? Just expecting an obscure table index would not be too
user-friendly, imho.

>> And due to the fact that the framebuffer size calculation is tied to
>> panel specification, it will boot in any case. The only problem that
>> one could encounter would be suboptimal display (for example,
>> offscreen pixmaps to become actually visible on screen if the panel is
>> taller
>> than expected, or some corruption in case it is wider).
>
> Another option might be to have a submenu with the possible resolutions
> you want to allow and size the frame buffer for the largest of those,
> but allow overriding the actual one at boot time.
>

In this case display parameters could be parsed in the driver itself,
but quite some memory will be over-allocated in extreme cases without
any way to claim it back after boot. Having only 128MB of RAM, is it
really better?

>> >> +#include <mach/vt8500.h>
>> >> +#include "devices.h"
>> >> +
>> >> +static struct platform_device *devices[] __initdata = {
>> >> +     &vt8500_device_uart0,
>> >> +#ifdef CONFIG_FB_VT8500
>> >> +     &vt8500_device_lcdc,
>> >> +#endif
>> >> +#ifdef CONFIG_USB_EHCI_HCD
>> >> +     &vt8500_device_ehci,
>> >> +#endif
>> >> +#ifdef CONFIG_FB_WMT_GE_ROPS
>> >> +     &vt8500_device_ge_rops,
>> >> +#endif
>> >> +#ifdef CONFIG_HAVE_PWM
>> >> +     &vt8500_device_pwm,
>> >> +#endif
>> >> +#ifdef CONFIG_BACKLIGHT_PWM
>> >> +     &vt8500_device_pwmbl,
>> >> +#endif
>> >> +#ifdef CONFIG_RTC_DRV_VT8500
>> >> +     &vt8500_device_rtc,
>> >> +#endif
>> >> +};
>> >
>> > This doesn't work if the drivers are built as loadable modules, right?
>> > I wouldn't even make the definitions of the devices configuration dependent.
>> > The idea of the device model is that you describe what you have in one
>> > place and use that information to load the drivers for it.
>> >
>>
>> But with loadable modules those symbols should still be defined as 'm'
>> or something, shouldn't they? Anyway, I'll drop those conditions,
>> thanks for pointing out.
>
> If you configure an option as a module you get e.g. CONFIG_USB_EHCI_HCD_MODULE=1,
> but CONFIG_USB_EHCI_HCD remains unset. It would be possible to check for
> both of them, but IMHO it's cleaner to just leave the code in unconditionally.
>

Cleaned this up in the development repo, thanks. Only left #ifdef's
for the sections where respective register/interrupt definitions would
be unavailable due to compiling for a different SoC version, and
adjusted the conditions accordingly.

>> >> +#ifndef __ASM_ARM_ARCH_IO_H
>> >> +#define __ASM_ARM_ARCH_IO_H
>> >> +
>> >> +#define IO_SPACE_LIMIT 0xffffffff
>> >> +
>> >> +#define __io(a)              __typesafe_io(a)
>> >> +#define __mem_pci(a) (a)
>> >> +
>> >> +#endif
>> >
>> >
>> > This won't work if you ever want to use the PCI on vt8505 with devices
>> > that have I/O space mapping.
>> >
>> > You need to define IO_SPACE_LIMIT to the size of your I/O space and
>> > make the __io macro offset the address with the start of that window.
>> >
>>
>> The problem is that there is no documentation available for the PCI
>> bus in these systems (if it is even implemented there).
>> Vendor-provided sources do not really clarify it either, which you
>> have commented about at:
>> http://groups.google.com/group/vt8500-wm8505-linux-kernel/msg/97bf44bc5ea5d46a?
>>
>> With no possibilities to test this (as I don't know any of these
>> devices to really use PCI with enumeration rather than just static
>> platform-like definitions as in the vendor's kernel), I just can't
>> imagine how this could be done any better.
>
> I can have a look again. It shouldn't be hard to do an almost correct
> implementation based on the source code we have, but I only own a wm8505
> based device, so I also have no way of testing and it would very likely
> have some subtle bugs.
>

Ok, figuring out better values for the macros would be great!

>        Arnd
>

Thanks,
Alexey

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

* Re: [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's
  2010-10-21 21:08       ` Alexey Charkov
@ 2010-10-22  9:02         ` Arnd Bergmann
  2010-10-22 13:52           ` Alexey Charkov
  0 siblings, 1 reply; 27+ messages in thread
From: Arnd Bergmann @ 2010-10-22  9:02 UTC (permalink / raw)
  To: vt8500-wm8505-linux-kernel
  Cc: Alexey Charkov, linux-arm-kernel, Russell King, linux-kernel

On Thursday 21 October 2010 23:08:39 Alexey Charkov wrote:
> 2010/10/21 Arnd Bergmann <arnd@arndb.de>:
> > On Thursday 21 October 2010, Alexey Charkov wrote:
> > Parsing complex options in general is not ok, but something simpler
> > probably is.
> >
> > Having a Kconfig selected default is probably a good idea. The most
> > simple way to select this at boot time would be to have a list of
> > possible resolutions and pass a table index.
> >
> > Would a __setup() call work for you?
> >
> 
> Should probably be fine. Will it be allowable to accept something like
> "panel=800x480" and strncmp it against a list of recognized values,
> fall back to a Kconfig default on failure and printk the
> possibilities? Just expecting an obscure table index would not be too
> user-friendly, imho.

Sounds reasonable to me.
 
> >> And due to the fact that the framebuffer size calculation is tied to
> >> panel specification, it will boot in any case. The only problem that
> >> one could encounter would be suboptimal display (for example,
> >> offscreen pixmaps to become actually visible on screen if the panel is
> >> taller
> >> than expected, or some corruption in case it is wider).
> >
> > Another option might be to have a submenu with the possible resolutions
> > you want to allow and size the frame buffer for the largest of those,
> > but allow overriding the actual one at boot time.
> >
> 
> In this case display parameters could be parsed in the driver itself,
> but quite some memory will be over-allocated in extreme cases without
> any way to claim it back after boot. Having only 128MB of RAM, is it
> really better?

Well, you could still build a specialized kernel with only support for
one resolution if you care about every byte.

> Cleaned this up in the development repo, thanks. Only left #ifdef's
> for the sections where respective register/interrupt definitions would
> be unavailable due to compiling for a different SoC version, and
> adjusted the conditions accordingly.

Ideally those should also be run-time decisions so you can build a
kernel that works on both. It's all __init code, so it won't eat
up any RAM afterwards.

> >> >> +#ifndef __ASM_ARM_ARCH_IO_H
> >> >> +#define __ASM_ARM_ARCH_IO_H
> >> >> +
> >> >> +#define IO_SPACE_LIMIT 0xffffffff
> >> >> +
> >> >> +#define __io(a)              __typesafe_io(a)
> >> >> +#define __mem_pci(a) (a)
> >> >> +
> >> >> +#endif
> 
> Ok, figuring out better values for the macros would be great!

For the IO_SPACE_LIMIT, just make it 0xffff

For __io, you need to find a place in your virtual address space
and map the real IO space.

According to the VIA source code, the physical I/O window is at
0xd8000000, they also map it to the same address in virtual space
but you can have anywhere convienient.

	Arnd

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

* Re: [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's
  2010-10-22  9:02         ` Arnd Bergmann
@ 2010-10-22 13:52           ` Alexey Charkov
  2010-10-22 14:48             ` Arnd Bergmann
  0 siblings, 1 reply; 27+ messages in thread
From: Alexey Charkov @ 2010-10-22 13:52 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, Russell King, linux-kernel

2010/10/22 Arnd Bergmann <arnd@arndb.de>:
> On Thursday 21 October 2010 23:08:39 Alexey Charkov wrote:
>> 2010/10/21 Arnd Bergmann <arnd@arndb.de>:
>> > On Thursday 21 October 2010, Alexey Charkov wrote:
>> > Parsing complex options in general is not ok, but something simpler
>> > probably is.
>> >
>> > Having a Kconfig selected default is probably a good idea. The most
>> > simple way to select this at boot time would be to have a list of
>> > possible resolutions and pass a table index.
>> >
>> > Would a __setup() call work for you?
>> >
>>
>> Should probably be fine. Will it be allowable to accept something like
>> "panel=800x480" and strncmp it against a list of recognized values,
>> fall back to a Kconfig default on failure and printk the
>> possibilities? Just expecting an obscure table index would not be too
>> user-friendly, imho.
>
> Sounds reasonable to me.
>
>> >> And due to the fact that the framebuffer size calculation is tied to
>> >> panel specification, it will boot in any case. The only problem that
>> >> one could encounter would be suboptimal display (for example,
>> >> offscreen pixmaps to become actually visible on screen if the panel is
>> >> taller
>> >> than expected, or some corruption in case it is wider).
>> >
>> > Another option might be to have a submenu with the possible resolutions
>> > you want to allow and size the frame buffer for the largest of those,
>> > but allow overriding the actual one at boot time.
>> >
>>
>> In this case display parameters could be parsed in the driver itself,
>> but quite some memory will be over-allocated in extreme cases without
>> any way to claim it back after boot. Having only 128MB of RAM, is it
>> really better?
>
> Well, you could still build a specialized kernel with only support for
> one resolution if you care about every byte.
>

If it is fine to accept an option like "panel=<value_from_a_list>" at
map_io stage, then I'd rather go that way, and calculate the minimum
required buffer size for the current configuration. Especially if we
decide to make a unified image for different SoC revisions, as WM8505
requires 32bpp framebuffer, while VT8500 requires it to be 4MB-aligned
native-bpp.

>> Cleaned this up in the development repo, thanks. Only left #ifdef's
>> for the sections where respective register/interrupt definitions would
>> be unavailable due to compiling for a different SoC version, and
>> adjusted the conditions accordingly.
>
> Ideally those should also be run-time decisions so you can build a
> kernel that works on both. It's all __init code, so it won't eat
> up any RAM afterwards.
>

I thought about that, and it should be quite useful. However, register
and interrupt definitions should then be converted into some indexed
data structures instead of macros (as they differ between VT8500 and
WM8505), and the correct index should be selectable at runtime.

Is there any way to determine which mach type we are currently running
at after early head.S initialization completes and before we could
need to use any registers and/or interrupts? It could probably be done
in machine-specific fixup functions, but I'm unsure whether this would
be a correct way to go.

>> >> >> +#ifndef __ASM_ARM_ARCH_IO_H
>> >> >> +#define __ASM_ARM_ARCH_IO_H
>> >> >> +
>> >> >> +#define IO_SPACE_LIMIT 0xffffffff
>> >> >> +
>> >> >> +#define __io(a)              __typesafe_io(a)
>> >> >> +#define __mem_pci(a) (a)
>> >> >> +
>> >> >> +#endif
>>
>> Ok, figuring out better values for the macros would be great!
>
> For the IO_SPACE_LIMIT, just make it 0xffff
>
> For __io, you need to find a place in your virtual address space
> and map the real IO space.
>
> According to the VIA source code, the physical I/O window is at
> 0xd8000000, they also map it to the same address in virtual space
> but you can have anywhere convienient.
>

Are you sure about that? 0xd8000000 is the MMIO base, as far as I can
tell (see register definitions in <mach/vt8500.h>). In earlier
discussions you presumed [1] that IO could be at 0xc0000000, but I'm
not sure how to verify that. If so, should it then look something like
this:

#define __io(a) ((void __iomem *)(((a) + 0xc0000000) +
SOME_OFFSET_TO_VIRT_SPACE))

?
By the way, other boards except for footbridge, integrator, ebsa110
and ixp4xx define IO_SPACE_LIMIT to be 0xffffffff. 0xffff seems more
plausbile, though...

>        Arnd
>

Thanks,
Alexey

[1] http://groups.google.com/group/vt8500-wm8505-linux-kernel/msg/97bf44bc5ea5d46a?

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

* Re: [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's
  2010-10-22 13:52           ` Alexey Charkov
@ 2010-10-22 14:48             ` Arnd Bergmann
  0 siblings, 0 replies; 27+ messages in thread
From: Arnd Bergmann @ 2010-10-22 14:48 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: vt8500-wm8505-linux-kernel, linux-arm-kernel, Russell King, linux-kernel

On Friday 22 October 2010 15:52:26 Alexey Charkov wrote:
> 2010/10/22 Arnd Bergmann <arnd@arndb.de>:
> > On Thursday 21 October 2010 23:08:39 Alexey Charkov wrote:

> > Well, you could still build a specialized kernel with only support for
> > one resolution if you care about every byte.
> >
> 
> If it is fine to accept an option like "panel=<value_from_a_list>" at
> map_io stage, then I'd rather go that way, and calculate the minimum
> required buffer size for the current configuration. Especially if we
> decide to make a unified image for different SoC revisions, as WM8505
> requires 32bpp framebuffer, while VT8500 requires it to be 4MB-aligned
> native-bpp.

sounds ok to me.

> >> Cleaned this up in the development repo, thanks. Only left #ifdef's
> >> for the sections where respective register/interrupt definitions would
> >> be unavailable due to compiling for a different SoC version, and
> >> adjusted the conditions accordingly.
> >
> > Ideally those should also be run-time decisions so you can build a
> > kernel that works on both. It's all __init code, so it won't eat
> > up any RAM afterwards.
> >
> 
> I thought about that, and it should be quite useful. However, register
> and interrupt definitions should then be converted into some indexed
> data structures instead of macros (as they differ between VT8500 and
> WM8505), and the correct index should be selectable at runtime.

Right.

> Is there any way to determine which mach type we are currently running
> at after early head.S initialization completes and before we could
> need to use any registers and/or interrupts? It could probably be done
> in machine-specific fixup functions, but I'm unsure whether this would
> be a correct way to go.

Normally you put the register areas into the resources for platform
devices, which are board specific. The drivers then ioremap the resource
and use offsets into those ranges.

> > For the IO_SPACE_LIMIT, just make it 0xffff
> >
> > For __io, you need to find a place in your virtual address space
> > and map the real IO space.
> >
> > According to the VIA source code, the physical I/O window is at
> > 0xd8000000, they also map it to the same address in virtual space
> > but you can have anywhere convienient.
> >
> 
> Are you sure about that? 0xd8000000 is the MMIO base, as far as I can
> tell (see register definitions in <mach/vt8500.h>). In earlier
> discussions you presumed [1] that IO could be at 0xc0000000, but I'm
> not sure how to verify that. If so, should it then look something like
> this:
> 
> #define __io(a) ((void __iomem *)(((a) + 0xc0000000) +
> SOME_OFFSET_TO_VIRT_SPACE))

You are right, 0xd8000000 is certainly not the PCI I/O space, it is
the SoC MMIO area.

The comment in the original PCI code says

        /*
         * PCI Bridge Memory Map is between 0xC0000:0000 - 0xC3FF:FFFF(64MB)
         * The first 64KB is allocated for the PCI I/O Space, except for the
         * 0xCF8 - 0xCFF(8Bytes) for the PCI Configuration
         * Others are reserved for the MemorySpace.
         */

So this should be mapped somewhere. Best map this in your map_desc
at boot time to a fixed __iomem address.
 
> ?
> By the way, other boards except for footbridge, integrator, ebsa110
> and ixp4xx define IO_SPACE_LIMIT to be 0xffffffff. 0xffff seems more
> plausbile, though...

Yes, I have noticed that before and have thought about fixing them/
If you don't have PCI or PCMCIA, it doesn't really matter. What some
platforms do is to define the I/O port range to be 32 bit addressable
and then have multiple PCI buses with long port numbers, relying on
the bus to crop them to 16 bits again, but that breaks a few assumptions
in other code.

	Arnd

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

* Re: [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042
  2010-10-20 20:55 ` [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042 Alexey Charkov
  2010-10-20 21:15   ` Dmitry Torokhov
@ 2010-10-30 22:23   ` Ben Dooks
  2010-11-01 18:31     ` Alexey Charkov
  1 sibling, 1 reply; 27+ messages in thread
From: Ben Dooks @ 2010-10-30 22:23 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: vt8500-wm8505-linux-kernel, Dmitry Torokhov, linux-kernel,
	linux-arm-kernel, linux-input

On 20/10/10 21:55, Alexey Charkov wrote:
> VIA and WonderMedia Systems-on-Chip feature a standard i8042-compatible
> keyboard and mouse controller. This adds necessary glue to enable use
> of the standard driver with these systems.
> 
> Signed-off-by: Alexey Charkov <alchark@gmail.com>
> ---
> 
> Please review and state whether this could be acceptable for a merge
> to mainline in the coming 2.6.37 window. If possible, I would deeply
> appreciate a merge to a relevant git tree for integration prior to
> asking Linus to pull the changes. I could rebase the code if needed,
> currently this is against Linus' master branch.
> 
> This patch relies on the basic architecture support for VT8500/WM8505
> to be in place, as introduced by PATCH 1/6 in this series.
> 
> Due credits go to the community for providing feedback, advice and
> testing.
> 
> NB: The development is being done at:
> http://gitorious.org/linux-on-via-vt8500/vt8500-kernel
> 
> Relevant code may be pulled from a git tree in there.
> 
>  drivers/input/serio/Kconfig        |    3 +-
>  drivers/input/serio/i8042-vt8500.h |   71 ++++++++++++++++++++++++++++++++++++
>  drivers/input/serio/i8042.h        |    2 +
>  3 files changed, 75 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/input/serio/i8042-vt8500.h
> 
> diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
> index 3bfe8fa..2b86774 100644
> --- a/drivers/input/serio/Kconfig
> +++ b/drivers/input/serio/Kconfig
> @@ -21,7 +21,8 @@ if SERIO
>  config SERIO_I8042
>  	tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
>  	default y
> -	depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
> +	depends on !PARISC && \
> +		  (!ARM || ARCH_SHARK || ARCH_VT8500 || FOOTBRIDGE_HOST) && \
>  		   (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN

this looks like someone could do with a HAS_SERIO_I8042 Kconfig entry
and have the relevant archs select it instead of having this mess.


>  	help
>  	  i8042 is the chip over which the standard AT keyboard and PS/2
> diff --git a/drivers/input/serio/i8042-vt8500.h b/drivers/input/serio/i8042-vt8500.h
> new file mode 100644
> index 0000000..d30df82
> --- /dev/null
> +++ b/drivers/input/serio/i8042-vt8500.h
> @@ -0,0 +1,71 @@
> +#ifndef _I8042_VT8500_H
> +#define _I8042_VT8500_H
> +
> +#include <mach/irqs.h>
> +#include <mach/vt8500.h>
> +
> +/*
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published by
> + * the Free Software Foundation.
> + */
> +
> +static void __iomem *regbase;
> +
> +/*
> + * Names.
> + */
> +
> +#define I8042_KBD_PHYS_DESC "vt8500ps2/serio0"
> +#define I8042_AUX_PHYS_DESC "vt8500ps2/serio1"
> +#define I8042_MUX_PHYS_DESC "vt8500ps2/serio%d"
> +
> +/*
> + * IRQs.
> + */
> +
> +#define I8042_KBD_IRQ	IRQ_PS2KBD
> +#define I8042_AUX_IRQ	IRQ_PS2MOUSE
> +
> +
> +/*
> + * Register numbers.
> + */
> +
> +#define I8042_COMMAND_REG	(regbase + 0x4)
> +#define I8042_STATUS_REG	(regbase + 0x4)
> +#define I8042_DATA_REG		(regbase + 0x0)
> +
> +static inline int i8042_read_data(void)
> +{
> +	return readl(I8042_DATA_REG);
> +}
> +
> +static inline int i8042_read_status(void)
> +{
> +	return readl(I8042_STATUS_REG);
> +}
> +
> +static inline void i8042_write_data(int val)
> +{
> +	writel(val, I8042_DATA_REG);
> +}
> +
> +static inline void i8042_write_command(int val)
> +{
> +	writel(val, I8042_COMMAND_REG);
> +}
> +
> +static inline int i8042_platform_init(void)
> +{
> +	i8042_reset = 1;
> +	regbase = ioremap(VT8500_PS2_BASE, SZ_1K);
> +	return 0;
> +}
> +
> +static inline void i8042_platform_exit(void)
> +{
> +	iounmap(regbase);
> +}
> +
> +#endif /* _I8042_VT8500_H */
> diff --git a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
> index cbc1beb..bdb2aeb 100644
> --- a/drivers/input/serio/i8042.h
> +++ b/drivers/input/serio/i8042.h
> @@ -16,6 +16,8 @@
>  
>  #if defined(CONFIG_MACH_JAZZ)
>  #include "i8042-jazzio.h"
> +#elif defined(CONFIG_ARCH_VT8500)
> +#include "i8042-vt8500.h"
>  #elif defined(CONFIG_SGI_HAS_I8042)
>  #include "i8042-ip22io.h"
>  #elif defined(CONFIG_SNI_RM)

yeurk... how about having a core i8042 implementation and having
a structure with the necessary callbacks for the code, so that
we don't end up having to select what is builtin for the system
we're compiling for?

-- 
Ben

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

* Re: [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042
  2010-10-30 22:23   ` [PATCH 3/6] " Ben Dooks
@ 2010-11-01 18:31     ` Alexey Charkov
  0 siblings, 0 replies; 27+ messages in thread
From: Alexey Charkov @ 2010-11-01 18:31 UTC (permalink / raw)
  To: Ben Dooks
  Cc: vt8500-wm8505-linux-kernel, Dmitry Torokhov, linux-kernel,
	linux-arm-kernel, linux-input

2010/10/31 Ben Dooks <ben-linux@fluff.org>:
> On 20/10/10 21:55, Alexey Charkov wrote:
>> VIA and WonderMedia Systems-on-Chip feature a standard i8042-compatible
>> keyboard and mouse controller. This adds necessary glue to enable use
>> of the standard driver with these systems.
>>
>> Signed-off-by: Alexey Charkov <alchark@gmail.com>
>> ---
>>
>> Please review and state whether this could be acceptable for a merge
>> to mainline in the coming 2.6.37 window. If possible, I would deeply
>> appreciate a merge to a relevant git tree for integration prior to
>> asking Linus to pull the changes. I could rebase the code if needed,
>> currently this is against Linus' master branch.
>>
>> This patch relies on the basic architecture support for VT8500/WM8505
>> to be in place, as introduced by PATCH 1/6 in this series.
>>
>> Due credits go to the community for providing feedback, advice and
>> testing.
>>
>> NB: The development is being done at:
>> http://gitorious.org/linux-on-via-vt8500/vt8500-kernel
>>
>> Relevant code may be pulled from a git tree in there.
>>
>>  drivers/input/serio/Kconfig        |    3 +-
>>  drivers/input/serio/i8042-vt8500.h |   71 ++++++++++++++++++++++++++++++++++++
>>  drivers/input/serio/i8042.h        |    2 +
>>  3 files changed, 75 insertions(+), 1 deletions(-)
>>  create mode 100644 drivers/input/serio/i8042-vt8500.h
>>
>> diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
>> index 3bfe8fa..2b86774 100644
>> --- a/drivers/input/serio/Kconfig
>> +++ b/drivers/input/serio/Kconfig
>> @@ -21,7 +21,8 @@ if SERIO
>>  config SERIO_I8042
>>       tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
>>       default y
>> -     depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \
>> +     depends on !PARISC && \
>> +               (!ARM || ARCH_SHARK || ARCH_VT8500 || FOOTBRIDGE_HOST) && \
>>                  (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN
>
> this looks like someone could do with a HAS_SERIO_I8042 Kconfig entry
> and have the relevant archs select it instead of having this mess.
>
>

True, it would make things much cleaner. However, that's probably out
of scope of adding VT8500 support here, thus not for me to decide :)

<snip>

>
> yeurk... how about having a core i8042 implementation and having
> a structure with the necessary callbacks for the code, so that
> we don't end up having to select what is builtin for the system
> we're compiling for?
>

I would really like to see this implemented as a standard platform
driver (accepting resources and platform_data as necessary). This
would be a way cleaner approach, with less code duplication and less
patching of the driver itself whenever a new platform is to be added.
However, I don't know how that kind of a change would affect other
arches.

> --
> Ben
>

Thanks,
Alexey

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

end of thread, other threads:[~2010-11-01 18:31 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-20 20:55 [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Alexey Charkov
2010-10-20 20:55 ` [PATCH 2/6] serial: Add support for UART on VIA VT8500 and compatibles Alexey Charkov
2010-10-20 21:16   ` Greg KH
2010-10-20 21:31     ` Alexey Charkov
2010-10-20 22:38       ` Greg KH
2010-10-20 22:48         ` Alexey Charkov
2010-10-20 20:55 ` [PATCH 3/6] input: Add support for VIA VT8500 and compatibles in i8042 Alexey Charkov
2010-10-20 21:15   ` Dmitry Torokhov
2010-10-20 21:24     ` Alexey Charkov
2010-10-20 22:14     ` [PATCH 3/6 v2] " Alexey Charkov
2010-10-20 23:46       ` Dmitry Torokhov
2010-10-30 22:23   ` [PATCH 3/6] " Ben Dooks
2010-11-01 18:31     ` Alexey Charkov
2010-10-20 20:55 ` [PATCH 4/6] usb: Add support for VIA VT8500 and compatibles in EHCI HCD Alexey Charkov
2010-10-20 21:17   ` Greg KH
2010-10-20 22:41     ` Alexey Charkov
2010-10-20 22:47       ` Greg KH
2010-10-20 22:54         ` Alexey Charkov
2010-10-20 20:55 ` [PATCH 5/6] rtc: Add support for the RTC in VIA VT8500 and compatibles Alexey Charkov
2010-10-20 20:55 ` [PATCH 6/6] ARM: Add support for the display controllers in VT8500 and WM8505 Alexey Charkov
2010-10-21  8:05 ` [PATCH 1/6] ARM: Add basic architecture support for VIA/WonderMedia 85xx SoC's Arnd Bergmann
2010-10-21  9:52   ` Alexey Charkov
2010-10-21 12:01     ` Arnd Bergmann
2010-10-21 21:08       ` Alexey Charkov
2010-10-22  9:02         ` Arnd Bergmann
2010-10-22 13:52           ` Alexey Charkov
2010-10-22 14:48             ` Arnd Bergmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).