mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-16 01:04:08 +08:00
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: Alexey Charkov <alchark@gmail.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
1bae4ce27c
commit
21f47fbc5b
@ -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
|
||||
|
46
arch/arm/boot/compressed/head-vt8500.S
Normal file
46
arch/arm/boot/compressed/head-vt8500.S
Normal file
@ -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:
|
73
arch/arm/mach-vt8500/Kconfig
Normal file
73
arch/arm/mach-vt8500/Kconfig
Normal file
@ -0,0 +1,73 @@
|
||||
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
|
9
arch/arm/mach-vt8500/Makefile
Normal file
9
arch/arm/mach-vt8500/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
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
|
3
arch/arm/mach-vt8500/Makefile.boot
Normal file
3
arch/arm/mach-vt8500/Makefile.boot
Normal file
@ -0,0 +1,3 @@
|
||||
zreladdr-y := 0x00008000
|
||||
params_phys-y := 0x00000100
|
||||
initrd_phys-y := 0x01000000
|
77
arch/arm/mach-vt8500/bv07.c
Normal file
77
arch/arm/mach-vt8500/bv07.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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
|
91
arch/arm/mach-vt8500/devices-vt8500.c
Normal file
91
arch/arm/mach-vt8500/devices-vt8500.c
Normal file
@ -0,0 +1,91 @@
|
||||
/* 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();
|
||||
}
|
99
arch/arm/mach-vt8500/devices-wm8505.c
Normal file
99
arch/arm/mach-vt8500/devices-wm8505.c
Normal file
@ -0,0 +1,99 @@
|
||||
/* 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();
|
||||
}
|
270
arch/arm/mach-vt8500/devices.c
Normal file
270
arch/arm/mach-vt8500/devices.c
Normal file
@ -0,0 +1,270 @@
|
||||
/* 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
|
||||
}
|
88
arch/arm/mach-vt8500/devices.h
Normal file
88
arch/arm/mach-vt8500/devices.h
Normal file
@ -0,0 +1,88 @@
|
||||
/* 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
|
240
arch/arm/mach-vt8500/gpio.c
Normal file
240
arch/arm/mach-vt8500/gpio.c
Normal file
@ -0,0 +1,240 @@
|
||||
/* 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);
|
||||
}
|
31
arch/arm/mach-vt8500/include/mach/debug-macro.S
Normal file
31
arch/arm/mach-vt8500/include/mach/debug-macro.S
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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
|
32
arch/arm/mach-vt8500/include/mach/entry-macro.S
Normal file
32
arch/arm/mach-vt8500/include/mach/entry-macro.S
Normal file
@ -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
|
||||
|
6
arch/arm/mach-vt8500/include/mach/gpio.h
Normal file
6
arch/arm/mach-vt8500/include/mach/gpio.h
Normal file
@ -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
|
12
arch/arm/mach-vt8500/include/mach/hardware.h
Normal file
12
arch/arm/mach-vt8500/include/mach/hardware.h
Normal file
@ -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.
|
||||
*
|
||||
*/
|
18
arch/arm/mach-vt8500/include/mach/i8042.h
Normal file
18
arch/arm/mach-vt8500/include/mach/i8042.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* 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;
|
28
arch/arm/mach-vt8500/include/mach/io.h
Normal file
28
arch/arm/mach-vt8500/include/mach/io.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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
|
22
arch/arm/mach-vt8500/include/mach/irqs.h
Normal file
22
arch/arm/mach-vt8500/include/mach/irqs.h
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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
|
28
arch/arm/mach-vt8500/include/mach/memory.h
Normal file
28
arch/arm/mach-vt8500/include/mach/memory.h
Normal file
@ -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
|
18
arch/arm/mach-vt8500/include/mach/system.h
Normal file
18
arch/arm/mach-vt8500/include/mach/system.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* arch/arm/mach-vt8500/include/mach/system.h
|
||||
*
|
||||
*/
|
||||
#include <asm/io.h>
|
||||
|
||||
/* PM Software Reset request register */
|
||||
#define VT8500_PMSR_VIRT 0xf8130060
|
||||
|
||||
static inline void arch_idle(void)
|
||||
{
|
||||
cpu_do_idle();
|
||||
}
|
||||
|
||||
static inline void arch_reset(char mode, const char *cmd)
|
||||
{
|
||||
writel(1, VT8500_PMSR_VIRT);
|
||||
}
|
26
arch/arm/mach-vt8500/include/mach/timex.h
Normal file
26
arch/arm/mach-vt8500/include/mach/timex.h
Normal file
@ -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 */
|
37
arch/arm/mach-vt8500/include/mach/uncompress.h
Normal file
37
arch/arm/mach-vt8500/include/mach/uncompress.h
Normal file
@ -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.
|
||||
*
|
||||
*/
|
||||
|
||||
#define UART0_PHYS 0xd8200000
|
||||
#include <asm/io.h>
|
||||
|
||||
static void putc(const char c)
|
||||
{
|
||||
while (readb(UART0_PHYS + 0x1c) & 0x2)
|
||||
/* Tx busy, wait and poll */;
|
||||
|
||||
writeb(c, UART0_PHYS);
|
||||
}
|
||||
|
||||
static void flush(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* nothing to do
|
||||
*/
|
||||
#define arch_decomp_setup()
|
||||
#define arch_decomp_wdog()
|
20
arch/arm/mach-vt8500/include/mach/vmalloc.h
Normal file
20
arch/arm/mach-vt8500/include/mach/vmalloc.h
Normal file
@ -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 0xd0000000UL
|
88
arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
Normal file
88
arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* arch/arm/mach-vt8500/include/mach/vt8500_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
|
||||
*/
|
||||
|
||||
/* 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 VT8500_NR_IRQS 64
|
79
arch/arm/mach-vt8500/include/mach/vt8500_regs.h
Normal file
79
arch/arm/mach-vt8500/include/mach/vt8500_regs.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* arch/arm/mach-vt8500/include/mach/vt8500_regs.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_REGS_H
|
||||
#define __ASM_ARM_ARCH_VT8500_REGS_H
|
||||
|
||||
/* 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)
|
||||
|
||||
#endif
|
31
arch/arm/mach-vt8500/include/mach/vt8500fb.h
Normal file
31
arch/arm/mach-vt8500/include/mach/vt8500fb.h
Normal file
@ -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 */
|
115
arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
Normal file
115
arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
* arch/arm/mach-vt8500/include/mach/wm8505_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
|
||||
*/
|
||||
|
||||
/* 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 (?) */
|
||||
|
||||
#define WM8505_NR_IRQS 116
|
78
arch/arm/mach-vt8500/include/mach/wm8505_regs.h
Normal file
78
arch/arm/mach-vt8500/include/mach/wm8505_regs.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* arch/arm/mach-vt8500/include/mach/wm8505_regs.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_WM8505_REGS_H
|
||||
#define __ASM_ARM_ARCH_WM8505_REGS_H
|
||||
|
||||
/* WM8505 Registers Map */
|
||||
|
||||
#define WM8505_REGS_START_PHYS 0xd8000000 /* Start of MMIO registers */
|
||||
#define WM8505_REGS_START_VIRT 0xf8000000 /* Virtual mapping start */
|
||||
|
||||
#define WM8505_DDR_BASE 0xd8000400 /* 1k DDR/DDR2 Memory
|
||||
Controller */
|
||||
#define WM8505_DMA_BASE 0xd8001800 /* 1k DMA Controller */
|
||||
#define WM8505_VDMA_BASE 0xd8001c00 /* 1k VDMA */
|
||||
#define WM8505_SFLASH_BASE 0xd8002000 /* 1k Serial Flash Memory
|
||||
Controller */
|
||||
#define WM8505_ETHER_BASE 0xd8004000 /* 1k Ethernet MAC 0 */
|
||||
#define WM8505_CIPHER_BASE 0xd8006000 /* 4k Cipher */
|
||||
#define WM8505_USB_BASE 0xd8007000 /* 2k USB 2.0 Host */
|
||||
# define WM8505_EHCI_BASE 0xd8007100 /* EHCI */
|
||||
# define WM8505_UHCI_BASE 0xd8007301 /* UHCI */
|
||||
#define WM8505_PS2_BASE 0xd8008800 /* 1k PS/2 */
|
||||
#define WM8505_NAND_BASE 0xd8009000 /* 1k NAND Controller */
|
||||
#define WM8505_NOR_BASE 0xd8009400 /* 1k NOR Controller */
|
||||
#define WM8505_SDMMC_BASE 0xd800a000 /* 1k SD/MMC Controller */
|
||||
#define WM8505_VPU_BASE 0xd8050000 /* 256 VPU */
|
||||
#define WM8505_GOV_BASE 0xd8050300 /* 256 GOV */
|
||||
#define WM8505_GEGEA_BASE 0xd8050400 /* 768 GE/GE Alpha Mixing */
|
||||
#define WM8505_GOVR_BASE 0xd8050800 /* 512 GOVR (frambuffer) */
|
||||
#define WM8505_VID_BASE 0xd8050a00 /* 256 VID */
|
||||
#define WM8505_SCL_BASE 0xd8050d00 /* 256 SCL */
|
||||
#define WM8505_VPP_BASE 0xd8050f00 /* 256 VPP */
|
||||
#define WM8505_JPEGDEC_BASE 0xd80fe000 /* 4k JPEG Decoder */
|
||||
#define WM8505_RTC_BASE 0xd8100000 /* 64k RTC */
|
||||
#define WM8505_GPIO_BASE 0xd8110000 /* 64k GPIO Configuration */
|
||||
#define WM8505_SCC_BASE 0xd8120000 /* 64k System Configuration*/
|
||||
#define WM8505_PMC_BASE 0xd8130000 /* 64k PMC Configuration */
|
||||
#define WM8505_IC_BASE 0xd8140000 /* 64k Interrupt Controller*/
|
||||
#define WM8505_SIC_BASE 0xd8150000 /* 64k Secondary IC */
|
||||
#define WM8505_UART0_BASE 0xd8200000 /* 64k UART 0 */
|
||||
#define WM8505_UART2_BASE 0xd8210000 /* 64k UART 2 */
|
||||
#define WM8505_PWM_BASE 0xd8220000 /* 64k PWM Configuration */
|
||||
#define WM8505_SPI0_BASE 0xd8240000 /* 64k SPI 0 */
|
||||
#define WM8505_SPI1_BASE 0xd8250000 /* 64k SPI 1 */
|
||||
#define WM8505_KEYPAD_BASE 0xd8260000 /* 64k Keypad control */
|
||||
#define WM8505_CIR_BASE 0xd8270000 /* 64k CIR */
|
||||
#define WM8505_I2C0_BASE 0xd8280000 /* 64k I2C 0 */
|
||||
#define WM8505_AC97_BASE 0xd8290000 /* 64k AC97 */
|
||||
#define WM8505_SPI2_BASE 0xd82a0000 /* 64k SPI 2 */
|
||||
#define WM8505_UART1_BASE 0xd82b0000 /* 64k UART 1 */
|
||||
#define WM8505_UART3_BASE 0xd82c0000 /* 64k UART 3 */
|
||||
#define WM8505_I2C1_BASE 0xd8320000 /* 64k I2C 1 */
|
||||
#define WM8505_I2S_BASE 0xd8330000 /* 64k I2S */
|
||||
#define WM8505_UART4_BASE 0xd8370000 /* 64k UART 4 */
|
||||
#define WM8505_UART5_BASE 0xd8380000 /* 64k UART 5 */
|
||||
|
||||
#define WM8505_REGS_END_PHYS 0xd838ffff /* End of MMIO registers */
|
||||
#define WM8505_REGS_LENGTH (WM8505_REGS_END_PHYS \
|
||||
- WM8505_REGS_START_PHYS + 1)
|
||||
|
||||
#endif
|
177
arch/arm/mach-vt8500/irq.c
Normal file
177
arch/arm/mach-vt8500/irq.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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 "devices.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_EDGE ( VT8500_TRIGGER_RISING \
|
||||
| VT8500_TRIGGER_FALLING)
|
||||
#define VT8500_IC_STATUS 0x80 /* Interrupt status, 2*u32 */
|
||||
|
||||
static void __iomem *ic_regbase;
|
||||
static void __iomem *sic_regbase;
|
||||
|
||||
static void vt8500_irq_mask(unsigned int irq)
|
||||
{
|
||||
void __iomem *base = ic_regbase;
|
||||
u8 edge;
|
||||
|
||||
if (irq >= 64) {
|
||||
base = sic_regbase;
|
||||
irq -= 64;
|
||||
}
|
||||
edge = readb(base + VT8500_IC_DCTR + irq) & VT8500_EDGE;
|
||||
if (edge) {
|
||||
void __iomem *stat_reg = base + VT8500_IC_STATUS
|
||||
+ (irq < 32 ? 0 : 4);
|
||||
unsigned status = readl(stat_reg);
|
||||
|
||||
status |= (1 << (irq & 0x1f));
|
||||
writel(status, stat_reg);
|
||||
} else {
|
||||
u8 dctr = readb(base + VT8500_IC_DCTR + irq);
|
||||
|
||||
dctr &= ~VT8500_INT_ENABLE;
|
||||
writeb(dctr, base + VT8500_IC_DCTR + irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void vt8500_irq_unmask(unsigned int irq)
|
||||
{
|
||||
void __iomem *base = ic_regbase;
|
||||
u8 dctr;
|
||||
|
||||
if (irq >= 64) {
|
||||
base = sic_regbase;
|
||||
irq -= 64;
|
||||
}
|
||||
dctr = readb(base + VT8500_IC_DCTR + irq);
|
||||
dctr |= VT8500_INT_ENABLE;
|
||||
writeb(dctr, base + VT8500_IC_DCTR + irq);
|
||||
}
|
||||
|
||||
static int vt8500_irq_set_type(unsigned int irq, unsigned int flow_type)
|
||||
{
|
||||
void __iomem *base = ic_regbase;
|
||||
unsigned int orig_irq = irq;
|
||||
u8 dctr;
|
||||
|
||||
if (irq >= 64) {
|
||||
base = sic_regbase;
|
||||
irq -= 64;
|
||||
}
|
||||
|
||||
dctr = readb(base + VT8500_IC_DCTR + irq);
|
||||
dctr &= ~VT8500_EDGE;
|
||||
|
||||
switch (flow_type) {
|
||||
case IRQF_TRIGGER_LOW:
|
||||
return -EINVAL;
|
||||
case IRQF_TRIGGER_HIGH:
|
||||
dctr |= VT8500_TRIGGER_HIGH;
|
||||
irq_desc[orig_irq].handle_irq = handle_level_irq;
|
||||
break;
|
||||
case IRQF_TRIGGER_FALLING:
|
||||
dctr |= VT8500_TRIGGER_FALLING;
|
||||
irq_desc[orig_irq].handle_irq = handle_edge_irq;
|
||||
break;
|
||||
case IRQF_TRIGGER_RISING:
|
||||
dctr |= VT8500_TRIGGER_RISING;
|
||||
irq_desc[orig_irq].handle_irq = handle_edge_irq;
|
||||
break;
|
||||
}
|
||||
writeb(dctr, base + VT8500_IC_DCTR + irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip vt8500_irq_chip = {
|
||||
.name = "vt8500",
|
||||
.ack = vt8500_irq_mask,
|
||||
.mask = vt8500_irq_mask,
|
||||
.unmask = vt8500_irq_unmask,
|
||||
.set_type = vt8500_irq_set_type,
|
||||
};
|
||||
|
||||
void __init vt8500_init_irq(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
ic_regbase = ioremap(wmt_ic_base, SZ_64K);
|
||||
|
||||
if (ic_regbase) {
|
||||
/* Enable rotating priority for IRQ */
|
||||
writel((1 << 6), ic_regbase + 0x20);
|
||||
writel(0, ic_regbase + 0x24);
|
||||
|
||||
for (i = 0; i < wmt_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);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void __init wm8505_init_irq(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
ic_regbase = ioremap(wmt_ic_base, SZ_64K);
|
||||
sic_regbase = ioremap(wmt_sic_base, SZ_64K);
|
||||
|
||||
if (ic_regbase && sic_regbase) {
|
||||
/* Enable rotating priority for IRQ */
|
||||
writel((1 << 6), ic_regbase + 0x20);
|
||||
writel(0, ic_regbase + 0x24);
|
||||
writel((1 << 6), sic_regbase + 0x20);
|
||||
writel(0, sic_regbase + 0x24);
|
||||
|
||||
for (i = 0; i < wmt_nr_irqs; i++) {
|
||||
/* Disable all interrupts and route them to IRQ */
|
||||
if (i < 64)
|
||||
writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
|
||||
else
|
||||
writeb(0x00, sic_regbase + VT8500_IC_DCTR
|
||||
+ i - 64);
|
||||
|
||||
set_irq_chip(i, &vt8500_irq_chip);
|
||||
set_irq_handler(i, handle_level_irq);
|
||||
set_irq_flags(i, IRQF_VALID);
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
|
||||
}
|
||||
}
|
265
arch/arm/mach-vt8500/pwm.c
Normal file
265
arch/arm/mach-vt8500/pwm.c
Normal file
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* 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 <linux/delay.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
|
||||
#define VT8500_NR_PWMS 4
|
||||
|
||||
static DEFINE_MUTEX(pwm_lock);
|
||||
static LIST_HEAD(pwm_list);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
|
||||
static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask)
|
||||
{
|
||||
int loops = msecs_to_loops(10);
|
||||
while ((readb(reg) & bitmask) && --loops)
|
||||
cpu_relax();
|
||||
|
||||
if (unlikely(!loops))
|
||||
pr_warning("Waiting for status bits 0x%x to clear timed out\n",
|
||||
bitmask);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
c = (unsigned long long)pv * duty_ns;
|
||||
do_div(c, period_ns);
|
||||
dc = c;
|
||||
|
||||
pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 1));
|
||||
writel(prescale, pwm->regbase + 0x4 + (pwm->pwm_id << 4));
|
||||
|
||||
pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 2));
|
||||
writel(pv, pwm->regbase + 0x8 + (pwm->pwm_id << 4));
|
||||
|
||||
pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 3));
|
||||
writel(dc, pwm->regbase + 0xc + (pwm->pwm_id << 4));
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pwm_config);
|
||||
|
||||
int pwm_enable(struct pwm_device *pwm)
|
||||
{
|
||||
pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0));
|
||||
writel(5, pwm->regbase + (pwm->pwm_id << 4));
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(pwm_enable);
|
||||
|
||||
void pwm_disable(struct pwm_device *pwm)
|
||||
{
|
||||
pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0));
|
||||
writel(0, pwm->regbase + (pwm->pwm_id << 4));
|
||||
}
|
||||
EXPORT_SYMBOL(pwm_disable);
|
||||
|
||||
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[0].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");
|
155
arch/arm/mach-vt8500/timer.c
Normal file
155
arch/arm/mach-vt8500/timer.c
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include "devices.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
|
||||
|
||||
#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
|
||||
|
||||
static void __iomem *regbase;
|
||||
|
||||
static cycle_t vt8500_timer_read(struct clocksource *cs)
|
||||
{
|
||||
int loops = msecs_to_loops(10);
|
||||
writel(3, regbase + TIMER_CTRL_VAL);
|
||||
while ((readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE)
|
||||
&& --loops)
|
||||
cpu_relax();
|
||||
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,
|
||||
};
|
||||
|
||||
static int vt8500_timer_set_next_event(unsigned long cycles,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
int loops = msecs_to_loops(10);
|
||||
cycle_t alarm = clocksource.read(&clocksource) + cycles;
|
||||
while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE)
|
||||
&& --loops)
|
||||
cpu_relax();
|
||||
writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL);
|
||||
|
||||
if ((signed)(alarm - clocksource.read(&clocksource)) <= 16)
|
||||
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:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
writel(readl(regbase + TIMER_CTRL_VAL) | 1,
|
||||
regbase + TIMER_CTRL_VAL);
|
||||
writel(0, regbase + TIMER_IER_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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
regbase = ioremap(wmt_pmc_base + VT8500_TIMER_OFFSET, 0x28);
|
||||
if (!regbase)
|
||||
printk(KERN_ERR "vt8500_timer_init: failed to map MMIO registers\n");
|
||||
|
||||
writel(1, regbase + TIMER_CTRL_VAL);
|
||||
writel(0xf, regbase + TIMER_STATUS_VAL);
|
||||
writel(~0, regbase + TIMER_MATCH_VAL);
|
||||
|
||||
if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ))
|
||||
printk(KERN_ERR "vt8500_timer_init: clocksource_register failed for %s\n",
|
||||
clocksource.name);
|
||||
|
||||
clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4);
|
||||
|
||||
/* copy-pasted from mach-msm; no idea */
|
||||
clockevent.max_delta_ns =
|
||||
clockevent_delta2ns(0xf0000000, &clockevent);
|
||||
clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent);
|
||||
clockevent.cpumask = cpumask_of(0);
|
||||
|
||||
if (setup_irq(wmt_timer_irq, &irq))
|
||||
printk(KERN_ERR "vt8500_timer_init: setup_irq failed for %s\n",
|
||||
clockevent.name);
|
||||
clockevents_register_device(&clockevent);
|
||||
}
|
||||
|
||||
struct sys_timer vt8500_timer = {
|
||||
.init = vt8500_timer_init
|
||||
};
|
77
arch/arm/mach-vt8500/wm8505_7in.c
Normal file
77
arch/arm/mach-vt8500/wm8505_7in.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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 <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_ehci,
|
||||
&vt8500_device_wm8505_fb,
|
||||
&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 wm8505_7in_init(void)
|
||||
{
|
||||
#ifdef CONFIG_FB_WM8505
|
||||
void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4);
|
||||
if (gpio_mux_reg) {
|
||||
writel(readl(gpio_mux_reg) | 0x80000000, 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");
|
||||
|
||||
wm8505_set_resources();
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
vt8500_gpio_init();
|
||||
}
|
||||
|
||||
MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
|
||||
.boot_params = 0x00000100,
|
||||
.reserve = wm8505_reserve_mem,
|
||||
.map_io = wm8505_map_io,
|
||||
.init_irq = wm8505_init_irq,
|
||||
.timer = &vt8500_timer,
|
||||
.init_machine = wm8505_7in_init,
|
||||
MACHINE_END
|
Loading…
Reference in New Issue
Block a user