Skip to content
Snippets Groups Projects
Commit 21f47fbc authored by Alexey Charkov's avatar Alexey Charkov Committed by Russell King
Browse files

ARM: 6597/1: Add basic architecture support for VIA/WonderMedia 85xx SoC's


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: default avatarAlexey Charkov <alchark@gmail.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 1bae4ce2
No related merge requests found
Showing
with 1162 additions and 0 deletions
......@@ -875,6 +875,16 @@ 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_CLOCKEVENTS
select ARCH_REQUIRE_GPIOLIB
select HAVE_PWM
help
Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
endchoice
#
......@@ -1007,6 +1017,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
......
......@@ -190,6 +190,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
......
......@@ -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
......
/*
* 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:
if ARCH_VT8500
config VTWM_VERSION_VT8500
bool
config VTWM_VERSION_WM8505
bool
config MACH_BV07
bool "Benign BV07-8500 Mini Netbook"
depends on ARCH_VT8500
select 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
select 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.
comment "LCD panel size"
config WMT_PANEL_800X480
bool "7-inch with 800x480 resolution"
depends on (FB_VT8500 || FB_WM8505)
default y
help
These are found in most of the netbooks in generic cases, as
well as in Eken M001 tablets and possibly elsewhere.
To select this panel at runtime, say y here and append
'panel=800x480' to your kernel command line. Otherwise, the
largest one available will be used.
config WMT_PANEL_800X600
bool "8-inch with 800x600 resolution"
depends on (FB_VT8500 || FB_WM8505)
help
These are found in Eken M003 tablets and possibly elsewhere.
To select this panel at runtime, say y here and append
'panel=800x600' to your kernel command line. Otherwise, the
largest one available will be used.
config WMT_PANEL_1024X576
bool "10-inch with 1024x576 resolution"
depends on (FB_VT8500 || FB_WM8505)
help
These are found in CherryPal netbooks and possibly elsewhere.
To select this panel at runtime, say y here and append
'panel=1024x576' to your kernel command line. Otherwise, the
largest one available will be used.
config WMT_PANEL_1024X600
bool "10-inch with 1024x600 resolution"
depends on (FB_VT8500 || FB_WM8505)
help
These are found in Eken M006 tablets and possibly elsewhere.
To select this panel at runtime, say y here and append
'panel=1024x600' to your kernel command line. Otherwise, the
largest one available will be used.
endif
obj-y += devices.o gpio.o irq.o timer.o
obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o
obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o
obj-$(CONFIG_MACH_BV07) += bv07.o
obj-$(CONFIG_MACH_WM8505_7IN_NETBOOK) += wm8505_7in.o
obj-$(CONFIG_HAVE_PWM) += pwm.o
zreladdr-y := 0x00008000
params_phys-y := 0x00000100
initrd_phys-y := 0x01000000
/*
* 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 <linux/io.h>
#include <linux/pm.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include "devices.h"
static void __iomem *pmc_hiber;
static struct platform_device *devices[] __initdata = {
&vt8500_device_uart0,
&vt8500_device_lcdc,
&vt8500_device_ehci,
&vt8500_device_ge_rops,
&vt8500_device_pwm,
&vt8500_device_pwmbl,
&vt8500_device_rtc,
};
static void vt8500_power_off(void)
{
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(wmt_gpio_base + 0x200, 4);
if (gpio_mux_reg) {
writel(readl(gpio_mux_reg) | 1, gpio_mux_reg);
iounmap(gpio_mux_reg);
} else {
printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n");
}
#endif
pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2);
if (pmc_hiber)
pm_power_off = &vt8500_power_off;
else
printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
vt8500_set_resources();
platform_add_devices(devices, ARRAY_SIZE(devices));
vt8500_gpio_init();
}
MACHINE_START(BV07, "Benign BV07 Mini Netbook")
.boot_params = 0x00000100,
.reserve = vt8500_reserve_mem,
.map_io = vt8500_map_io,
.init_irq = vt8500_init_irq,
.timer = &vt8500_timer,
.init_machine = bv07_init,
MACHINE_END
/* linux/arch/arm/mach-vt8500/devices-vt8500.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/platform_device.h>
#include <mach/vt8500_regs.h>
#include <mach/vt8500_irqs.h>
#include <mach/i8042.h>
#include "devices.h"
void __init vt8500_set_resources(void)
{
struct resource tmp[3];
tmp[0] = wmt_mmio_res(VT8500_LCDC_BASE, SZ_1K);
tmp[1] = wmt_irq_res(IRQ_LCDC);
wmt_res_add(&vt8500_device_lcdc, tmp, 2);
tmp[0] = wmt_mmio_res(VT8500_UART0_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART0);
wmt_res_add(&vt8500_device_uart0, tmp, 2);
tmp[0] = wmt_mmio_res(VT8500_UART1_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART1);
wmt_res_add(&vt8500_device_uart1, tmp, 2);
tmp[0] = wmt_mmio_res(VT8500_UART2_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART2);
wmt_res_add(&vt8500_device_uart2, tmp, 2);
tmp[0] = wmt_mmio_res(VT8500_UART3_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART3);
wmt_res_add(&vt8500_device_uart3, tmp, 2);
tmp[0] = wmt_mmio_res(VT8500_EHCI_BASE, SZ_512);
tmp[1] = wmt_irq_res(IRQ_EHCI);
wmt_res_add(&vt8500_device_ehci, tmp, 2);
tmp[0] = wmt_mmio_res(VT8500_GEGEA_BASE, SZ_256);
wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
tmp[0] = wmt_mmio_res(VT8500_PWM_BASE, 0x44);
wmt_res_add(&vt8500_device_pwm, tmp, 1);
tmp[0] = wmt_mmio_res(VT8500_RTC_BASE, 0x2c);
tmp[1] = wmt_irq_res(IRQ_RTC);
tmp[2] = wmt_irq_res(IRQ_RTCSM);
wmt_res_add(&vt8500_device_rtc, tmp, 3);
}
static void __init vt8500_set_externs(void)
{
/* Non-resource-aware stuff */
wmt_ic_base = VT8500_IC_BASE;
wmt_gpio_base = VT8500_GPIO_BASE;
wmt_pmc_base = VT8500_PMC_BASE;
wmt_i8042_base = VT8500_PS2_BASE;
wmt_nr_irqs = VT8500_NR_IRQS;
wmt_timer_irq = IRQ_PMCOS0;
wmt_gpio_ext_irq[0] = IRQ_EXT0;
wmt_gpio_ext_irq[1] = IRQ_EXT1;
wmt_gpio_ext_irq[2] = IRQ_EXT2;
wmt_gpio_ext_irq[3] = IRQ_EXT3;
wmt_gpio_ext_irq[4] = IRQ_EXT4;
wmt_gpio_ext_irq[5] = IRQ_EXT5;
wmt_gpio_ext_irq[6] = IRQ_EXT6;
wmt_gpio_ext_irq[7] = IRQ_EXT7;
wmt_i8042_kbd_irq = IRQ_PS2KBD;
wmt_i8042_aux_irq = IRQ_PS2MOUSE;
}
void __init vt8500_map_io(void)
{
iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
/* Should be done before interrupts and timers are initialized */
vt8500_set_externs();
}
/* linux/arch/arm/mach-vt8500/devices-wm8505.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/platform_device.h>
#include <mach/wm8505_regs.h>
#include <mach/wm8505_irqs.h>
#include <mach/i8042.h>
#include "devices.h"
void __init wm8505_set_resources(void)
{
struct resource tmp[3];
tmp[0] = wmt_mmio_res(WM8505_GOVR_BASE, SZ_512);
wmt_res_add(&vt8500_device_wm8505_fb, tmp, 1);
tmp[0] = wmt_mmio_res(WM8505_UART0_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART0);
wmt_res_add(&vt8500_device_uart0, tmp, 2);
tmp[0] = wmt_mmio_res(WM8505_UART1_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART1);
wmt_res_add(&vt8500_device_uart1, tmp, 2);
tmp[0] = wmt_mmio_res(WM8505_UART2_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART2);
wmt_res_add(&vt8500_device_uart2, tmp, 2);
tmp[0] = wmt_mmio_res(WM8505_UART3_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART3);
wmt_res_add(&vt8500_device_uart3, tmp, 2);
tmp[0] = wmt_mmio_res(WM8505_UART4_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART4);
wmt_res_add(&vt8500_device_uart4, tmp, 2);
tmp[0] = wmt_mmio_res(WM8505_UART5_BASE, 0x1040);
tmp[1] = wmt_irq_res(IRQ_UART5);
wmt_res_add(&vt8500_device_uart5, tmp, 2);
tmp[0] = wmt_mmio_res(WM8505_EHCI_BASE, SZ_512);
tmp[1] = wmt_irq_res(IRQ_EHCI);
wmt_res_add(&vt8500_device_ehci, tmp, 2);
tmp[0] = wmt_mmio_res(WM8505_GEGEA_BASE, SZ_256);
wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
tmp[0] = wmt_mmio_res(WM8505_PWM_BASE, 0x44);
wmt_res_add(&vt8500_device_pwm, tmp, 1);
tmp[0] = wmt_mmio_res(WM8505_RTC_BASE, 0x2c);
tmp[1] = wmt_irq_res(IRQ_RTC);
tmp[2] = wmt_irq_res(IRQ_RTCSM);
wmt_res_add(&vt8500_device_rtc, tmp, 3);
}
static void __init wm8505_set_externs(void)
{
/* Non-resource-aware stuff */
wmt_ic_base = WM8505_IC_BASE;
wmt_sic_base = WM8505_SIC_BASE;
wmt_gpio_base = WM8505_GPIO_BASE;
wmt_pmc_base = WM8505_PMC_BASE;
wmt_i8042_base = WM8505_PS2_BASE;
wmt_nr_irqs = WM8505_NR_IRQS;
wmt_timer_irq = IRQ_PMCOS0;
wmt_gpio_ext_irq[0] = IRQ_EXT0;
wmt_gpio_ext_irq[1] = IRQ_EXT1;
wmt_gpio_ext_irq[2] = IRQ_EXT2;
wmt_gpio_ext_irq[3] = IRQ_EXT3;
wmt_gpio_ext_irq[4] = IRQ_EXT4;
wmt_gpio_ext_irq[5] = IRQ_EXT5;
wmt_gpio_ext_irq[6] = IRQ_EXT6;
wmt_gpio_ext_irq[7] = IRQ_EXT7;
wmt_i8042_kbd_irq = IRQ_PS2KBD;
wmt_i8042_aux_irq = IRQ_PS2MOUSE;
}
void __init wm8505_map_io(void)
{
iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
/* Should be done before interrupts and timers are initialized */
wm8505_set_externs();
}
/* 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 <mach/vt8500fb.h>
#include <mach/i8042.h>
#include "devices.h"
/* These can't use resources currently */
unsigned long wmt_ic_base __initdata;
unsigned long wmt_sic_base __initdata;
unsigned long wmt_gpio_base __initdata;
unsigned long wmt_pmc_base __initdata;
unsigned long wmt_i8042_base __initdata;
int wmt_nr_irqs __initdata;
int wmt_timer_irq __initdata;
int wmt_gpio_ext_irq[8] __initdata;
/* Should remain accessible after init.
* i8042 driver desperately calls for attention...
*/
int wmt_i8042_kbd_irq;
int wmt_i8042_aux_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),
},
};
struct platform_device vt8500_device_wm8505_fb = {
.name = "wm8505-fb",
.id = 0,
};
/* Smallest to largest */
static struct vt8500fb_platform_data panels[] = {
#ifdef CONFIG_WMT_PANEL_800X480
{
.xres_virtual = 800,
.yres_virtual = 480 * 2,
.mode = {
.name = "800x480",
.xres = 800,
.yres = 480,
.left_margin = 88,
.right_margin = 40,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 0,
.vsync_len = 1,
.vmode = FB_VMODE_NONINTERLACED,
},
},
#endif
#ifdef CONFIG_WMT_PANEL_800X600
{
.xres_virtual = 800,
.yres_virtual = 600 * 2,
.mode = {
.name = "800x600",
.xres = 800,
.yres = 600,
.left_margin = 88,
.right_margin = 40,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 0,
.vsync_len = 1,
.vmode = FB_VMODE_NONINTERLACED,
},
},
#endif
#ifdef CONFIG_WMT_PANEL_1024X576
{
.xres_virtual = 1024,
.yres_virtual = 576 * 2,
.mode = {
.name = "1024x576",
.xres = 1024,
.yres = 576,
.left_margin = 40,
.right_margin = 24,
.upper_margin = 32,
.lower_margin = 11,
.hsync_len = 96,
.vsync_len = 2,
.vmode = FB_VMODE_NONINTERLACED,
},
},
#endif
#ifdef CONFIG_WMT_PANEL_1024X600
{
.xres_virtual = 1024,
.yres_virtual = 600 * 2,
.mode = {
.name = "1024x600",
.xres = 1024,
.yres = 600,
.left_margin = 66,
.right_margin = 2,
.upper_margin = 19,
.lower_margin = 1,
.hsync_len = 23,
.vsync_len = 8,
.vmode = FB_VMODE_NONINTERLACED,
},
},
#endif
};
static int current_panel_idx __initdata = ARRAY_SIZE(panels) - 1;
static int __init panel_setup(char *str)
{
int i;
for (i = 0; i < ARRAY_SIZE(panels); i++) {
if (strcmp(panels[i].mode.name, str) == 0) {
current_panel_idx = i;
break;
}
}
return 0;
}
early_param("panel", panel_setup);
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);
}
struct platform_device vt8500_device_uart0 = {
.name = "vt8500_serial",
.id = 0,
};
struct platform_device vt8500_device_uart1 = {
.name = "vt8500_serial",
.id = 1,
};
struct platform_device vt8500_device_uart2 = {
.name = "vt8500_serial",
.id = 2,
};
struct platform_device vt8500_device_uart3 = {
.name = "vt8500_serial",
.id = 3,
};
struct platform_device vt8500_device_uart4 = {
.name = "vt8500_serial",
.id = 4,
};
struct platform_device vt8500_device_uart5 = {
.name = "vt8500_serial",
.id = 5,
};
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),
},
};
struct platform_device vt8500_device_ge_rops = {
.name = "wmt_ge_rops",
.id = -1,
};
struct platform_device vt8500_device_pwm = {
.name = "vt8500-pwm",
.id = 0,
};
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,
},
};
struct platform_device vt8500_device_rtc = {
.name = "vt8500-rtc",
.id = 0,
};
struct map_desc wmt_io_desc[] __initdata = {
/* SoC MMIO registers */
[0] = {
.virtual = 0xf8000000,
.pfn = __phys_to_pfn(0xd8000000),
.length = 0x00390000, /* max of all chip variants */
.type = MT_DEVICE
},
/* PCI I/O space, numbers tied to those in <mach/io.h> */
[1] = {
.virtual = 0xf0000000,
.pfn = __phys_to_pfn(0xc0000000),
.length = SZ_64K,
.type = MT_DEVICE
},
};
void __init vt8500_reserve_mem(void)
{
#ifdef CONFIG_FB_VT8500
panels[current_panel_idx].bpp = 16; /* Always use RGB565 */
preallocate_fb(&panels[current_panel_idx], SZ_4M);
vt8500_device_lcdc.dev.platform_data = &panels[current_panel_idx];
#endif
}
void __init wm8505_reserve_mem(void)
{
#if defined CONFIG_FB_WM8505
panels[current_panel_idx].bpp = 32; /* Always use RGB888 */
preallocate_fb(&panels[current_panel_idx], 32);
vt8500_device_wm8505_fb.dev.platform_data = &panels[current_panel_idx];
#endif
}
/* 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>
#include <asm/mach/map.h>
void __init vt8500_init_irq(void);
void __init wm8505_init_irq(void);
void __init vt8500_map_io(void);
void __init wm8505_map_io(void);
void __init vt8500_reserve_mem(void);
void __init wm8505_reserve_mem(void);
void __init vt8500_gpio_init(void);
void __init vt8500_set_resources(void);
void __init wm8505_set_resources(void);
extern unsigned long wmt_ic_base __initdata;
extern unsigned long wmt_sic_base __initdata;
extern unsigned long wmt_gpio_base __initdata;
extern unsigned long wmt_pmc_base __initdata;
extern int wmt_nr_irqs __initdata;
extern int wmt_timer_irq __initdata;
extern int wmt_gpio_ext_irq[8] __initdata;
extern struct map_desc wmt_io_desc[2] __initdata;
static inline struct resource wmt_mmio_res(u32 start, u32 size)
{
struct resource tmp = {
.flags = IORESOURCE_MEM,
.start = start,
.end = start + size - 1,
};
return tmp;
}
static inline struct resource wmt_irq_res(int irq)
{
struct resource tmp = {
.flags = IORESOURCE_IRQ,
.start = irq,
.end = irq,
};
return tmp;
}
static inline void wmt_res_add(struct platform_device *pdev,
const struct resource *res, unsigned int num)
{
if (unlikely(platform_device_add_resources(pdev, res, num)))
pr_err("Failed to assign resources\n");
}
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;
extern struct platform_device vt8500_device_uart4;
extern struct platform_device vt8500_device_uart5;
extern struct platform_device vt8500_device_lcdc;
extern struct platform_device vt8500_device_wm8505_fb;
extern struct platform_device vt8500_device_ehci;
extern struct platform_device vt8500_device_ge_rops;
extern struct platform_device vt8500_device_pwm;
extern struct platform_device vt8500_device_pwmbl;
extern struct platform_device vt8500_device_rtc;
#endif
/* 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/gpio.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/io.h>
#include "devices.h"
#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
#define ENABLE_REGS 0x0
#define DIRECTION_REGS 0x20
#define OUTVALUE_REGS 0x40
#define INVALUE_REGS 0x60
#define EXT_REGOFF 0x1c
static void __iomem *regbase;
struct vt8500_gpio_chip {
struct gpio_chip chip;
unsigned int shift;
unsigned int regoff;
};
static int gpio_to_irq_map[8];
static int vt8500_muxed_gpio_request(struct gpio_chip *chip,
unsigned offset)
{
struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
val |= (1 << vt8500_chip->shift << offset);
writel(val, regbase + ENABLE_REGS + 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);
unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
val &= ~(1 << vt8500_chip->shift << offset);
writel(val, regbase + ENABLE_REGS + 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);
unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
val &= ~(1 << vt8500_chip->shift << offset);
writel(val, regbase + DIRECTION_REGS + 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);
unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
val |= (1 << vt8500_chip->shift << offset);
writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
if (value) {
val = readl(regbase + OUTVALUE_REGS + vt8500_chip->regoff);
val |= (1 << vt8500_chip->shift << offset);
writel(val, regbase + OUTVALUE_REGS + 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 + INVALUE_REGS + 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);
unsigned val = readl(regbase + INVALUE_REGS + vt8500_chip->regoff);
if (value)
val |= (1 << vt8500_chip->shift << offset);
else
val &= ~(1 << vt8500_chip->shift << offset);
writel(val, regbase + INVALUE_REGS + 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)
{
unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
val &= ~(1 << offset);
writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
return 0;
}
static int vt8500_gpio_direction_output(struct gpio_chip *chip,
unsigned offset, int value)
{
unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
val |= (1 << offset);
writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
if (value) {
val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
val |= (1 << offset);
writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
}
return 0;
}
static int vt8500_gpio_get_value(struct gpio_chip *chip,
unsigned offset)
{
return (readl(regbase + INVALUE_REGS + EXT_REGOFF) >> offset) & 1;
}
static void vt8500_gpio_set_value(struct gpio_chip *chip,
unsigned offset, int value)
{
unsigned val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
if (value)
val |= (1 << offset);
else
val &= ~(1 << offset);
writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
}
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;
for (i = 0; i < 8; i++)
gpio_to_irq_map[i] = wmt_gpio_ext_irq[i];
regbase = ioremap(wmt_gpio_base, SZ_64K);
if (!regbase) {
printk(KERN_ERR "Failed to map MMIO registers for GPIO\n");
return;
}
gpiochip_add(&vt8500_external_gpios);
for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++)
gpiochip_add(&vt8500_muxed_gpios[i].chip);
}
/*
* 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.
*
*/
.macro addruart, rp, rv
mov \rp, #0x00200000
orr \rv, \rp, #0xf8000000
orr \rp, \rp, #0xd8000000
.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
/*
* 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
#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
/* 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.
*
*/
/* arch/arm/mach-vt8500/include/mach/i8042.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.
*
*/
extern unsigned long wmt_i8042_base __initdata;
extern int wmt_i8042_kbd_irq;
extern int wmt_i8042_aux_irq;
/*
* arch/arm/mach-vt8500/include/mach/io.h
*
* Copyright (C) 2010 Alexey Charkov
*
* 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 0xffff
#define __io(a) __typesafe_io((a) + 0xf0000000)
#define __mem_pci(a) (a)
#endif
/*
* 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
*/
/* This value is just to make the core happy, never used otherwise */
#define NR_IRQS 128
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment