[PATCH 1/6] U6/U6715 ARM architecture files
Philippe Langlais
philippe.langlais at stericsson.com
Thu May 27 04:27:27 EDT 2010
V2 after first internal review
Signed-off-by: Philippe Langlais <philippe.langlais at stericsson.com>
---
arch/arm/Kconfig | 10 +
arch/arm/Makefile | 2 +
arch/arm/mach-u67xx/Kconfig | 11 +
arch/arm/mach-u67xx/Makefile | 11 +
arch/arm/mach-u67xx/Makefile.boot | 4 +
arch/arm/mach-u67xx/board_u67xx_wavex.c | 48 ++
arch/arm/mach-u67xx/devices.c | 95 ++++
arch/arm/plat-u6xxx/Kconfig | 20 +
arch/arm/plat-u6xxx/Makefile | 8 +
arch/arm/plat-u6xxx/include/mach/cpu.h | 36 ++
arch/arm/plat-u6xxx/include/mach/debug-macro.S | 38 ++
arch/arm/plat-u6xxx/include/mach/entry-macro.S | 32 ++
arch/arm/plat-u6xxx/include/mach/hardware.h | 41 ++
arch/arm/plat-u6xxx/include/mach/io.h | 20 +
arch/arm/plat-u6xxx/include/mach/irqs.h | 130 +++++
arch/arm/plat-u6xxx/include/mach/memory.h | 24 +
arch/arm/plat-u6xxx/include/mach/platform.h | 15 +
arch/arm/plat-u6xxx/include/mach/regs-u6.h | 121 +++++
arch/arm/plat-u6xxx/include/mach/scon.h | 121 +++++
arch/arm/plat-u6xxx/include/mach/system.h | 42 ++
arch/arm/plat-u6xxx/include/mach/timer.h | 24 +
arch/arm/plat-u6xxx/include/mach/timex.h | 23 +
arch/arm/plat-u6xxx/include/mach/uncompress.h | 50 ++
arch/arm/plat-u6xxx/include/mach/vmalloc.h | 10 +
arch/arm/plat-u6xxx/io.c | 34 ++
arch/arm/plat-u6xxx/irq.c | 231 ++++++++
arch/arm/plat-u6xxx/timer.c | 679 ++++++++++++++++++++++++
27 files changed, 1880 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-u67xx/Kconfig
create mode 100644 arch/arm/mach-u67xx/Makefile
create mode 100644 arch/arm/mach-u67xx/Makefile.boot
create mode 100644 arch/arm/mach-u67xx/board_u67xx_wavex.c
create mode 100644 arch/arm/mach-u67xx/devices.c
create mode 100644 arch/arm/plat-u6xxx/Kconfig
create mode 100644 arch/arm/plat-u6xxx/Makefile
create mode 100644 arch/arm/plat-u6xxx/include/mach/cpu.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/debug-macro.S
create mode 100644 arch/arm/plat-u6xxx/include/mach/entry-macro.S
create mode 100644 arch/arm/plat-u6xxx/include/mach/hardware.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/io.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/irqs.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/memory.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/platform.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/regs-u6.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/scon.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/system.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/timer.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/timex.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/uncompress.h
create mode 100644 arch/arm/plat-u6xxx/include/mach/vmalloc.h
create mode 100644 arch/arm/plat-u6xxx/io.c
create mode 100644 arch/arm/plat-u6xxx/irq.c
create mode 100644 arch/arm/plat-u6xxx/timer.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1f254bd..8248c0a 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -741,6 +741,13 @@ config ARCH_U300
help
Support for ST-Ericsson U300 series mobile platforms.
+config PLAT_U6XXX
+ bool "ST-Ericsson U6XXX Series"
+ select GENERIC_GPIO
+ select ARCH_REQUIRE_GPIOLIB
+ help
+ Support for ST-Ericsson's U6XXX architecture
+
config ARCH_U8500
bool "ST-Ericsson U8500 Series"
select CPU_V7
@@ -910,6 +917,9 @@ source "arch/arm/plat-stmp3xxx/Kconfig"
source "arch/arm/mach-u300/Kconfig"
+source "arch/arm/plat-u6xxx/Kconfig"
+source "arch/arm/mach-u67xx/Kconfig"
+
source "arch/arm/mach-ux500/Kconfig"
source "arch/arm/mach-versatile/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 64ba313..9a7cab3 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -176,6 +176,7 @@ machine-$(CONFIG_ARCH_SHMOBILE) := shmobile
machine-$(CONFIG_ARCH_STMP378X) := stmp378x
machine-$(CONFIG_ARCH_STMP37XX) := stmp37xx
machine-$(CONFIG_ARCH_U300) := u300
+machine-$(CONFIG_ARCH_U67XX) := u67xx
machine-$(CONFIG_ARCH_U8500) := ux500
machine-$(CONFIG_ARCH_VERSATILE) := versatile
machine-$(CONFIG_ARCH_VEXPRESS) := vexpress
@@ -201,6 +202,7 @@ plat-$(CONFIG_PLAT_S3C24XX) := s3c24xx samsung
plat-$(CONFIG_PLAT_S5P) := s5p samsung
plat-$(CONFIG_PLAT_SPEAR) := spear
plat-$(CONFIG_PLAT_VERSATILE) := versatile
+plat-$(CONFIG_PLAT_U6XXX) := u6xxx
ifeq ($(CONFIG_ARCH_EBSA110),y)
# This is what happens if you forget the IOCS16 line.
diff --git a/arch/arm/mach-u67xx/Kconfig b/arch/arm/mach-u67xx/Kconfig
new file mode 100644
index 0000000..48f53fb
--- /dev/null
+++ b/arch/arm/mach-u67xx/Kconfig
@@ -0,0 +1,11 @@
+comment "U67XX Board Type"
+ depends on ARCH_U67XX
+
+choice
+ prompt "Choose the U67XX Board type"
+ default MACH_U67XX_WAVEC_2GB
+ help
+ "Choose the ST-Ericsson Reference Design Board"
+ config MACH_U67XX_WAVEC_2GB
+ bool "U67XX WaveC Board with 2Gb Micron combo"
+endchoice
diff --git a/arch/arm/mach-u67xx/Makefile b/arch/arm/mach-u67xx/Makefile
new file mode 100644
index 0000000..38cf624
--- /dev/null
+++ b/arch/arm/mach-u67xx/Makefile
@@ -0,0 +1,11 @@
+#
+## Makefile for the linux kernel, hardware dependent part of ST-Ericsson U67xx
+#
+#
+## Object file lists.
+
+# Common support
+obj-y := devices.o
+
+# Specific board support
+obj-$(CONFIG_MACH_U67XX_WAVEC_2GB) += board_u67xx_wavex.o
diff --git a/arch/arm/mach-u67xx/Makefile.boot b/arch/arm/mach-u67xx/Makefile.boot
new file mode 100644
index 0000000..c4e8c02
--- /dev/null
+++ b/arch/arm/mach-u67xx/Makefile.boot
@@ -0,0 +1,4 @@
+ zreladdr-y := 0x20008000
+params_phys-y := 0x20000100
+initrd_phys-y := 0x26000000
+
diff --git a/arch/arm/mach-u67xx/board_u67xx_wavex.c b/arch/arm/mach-u67xx/board_u67xx_wavex.c
new file mode 100644
index 0000000..2a806e7
--- /dev/null
+++ b/arch/arm/mach-u67xx/board_u67xx_wavex.c
@@ -0,0 +1,48 @@
+/*
+ * linux/arch/arm/mach-u67xx/board_u67xx_wavex.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Platform machine definition for U6XXX WAVEx Board.
+ */
+
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <asm/setup.h>
+
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <mach/irqs.h>
+#include <mach/timer.h>
+
+/* List of board specific devices */
+static struct platform_device *devices[] __initdata = {
+};
+
+void __init u67xx_init(void)
+{
+ /* Add specific board devices */
+ platform_add_devices(devices, ARRAY_SIZE(devices));
+}
+
+MACHINE_START(U6715, "STE_U67xx_refd")
+ /* Maintainer: Philippe Langlais <philippe.langlais at stericsson.com> */
+ .phys_io = UART1_BASE,
+ .io_pg_offst = (IO_ADDRESS(UART1_BASE) >> 18) & 0xfffc,
+ .boot_params = BOOT_PARAMS_OFFSET,
+ .map_io = u67xx_map_io,
+ .init_irq = u6_init_irq,
+ .init_machine = u67xx_init,
+ .timer = &u6_timer,
+MACHINE_END
+
diff --git a/arch/arm/mach-u67xx/devices.c b/arch/arm/mach-u67xx/devices.c
new file mode 100644
index 0000000..0ead380
--- /dev/null
+++ b/arch/arm/mach-u67xx/devices.c
@@ -0,0 +1,95 @@
+/*
+ * linux/arch/arm/mach-u67xx/devices.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Device specification for the U67XX
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/fs.h>
+#include <mach/hardware.h>
+#include <mach/scon.h>
+#include <mach/gpio.h>
+
+/* EXTINT to GPIO mapping */
+unsigned char extint_to_gpio[NR_EXTINT] = {
+ GPIO_A0, /*extint 0 */
+ GPIO_A1, /*extint 1 */
+ GPIO_A2, /*extint 2 */
+ GPIO_A3, /*extint 3 */
+ GPIO_A4, /*extint 4 */
+ GPIO_A5, /*extint 5 */
+ GPIO_A12, /*extint 6 */
+ GPIO_A13, /*extint 7 */
+ GPIO_A14, /*extint 8 */
+ GPIO_A15, /*extint 9 */
+ GPIO_A16, /*extint 10 */
+ GPIO_A17, /*extint 11 */
+ GPIO_D19, /*extint 12 */
+ GPIO_A19, /*extint 13 */
+ GPIO_A20, /*extint 14 */
+ GPIO_B11, /*extint 15 */
+ GPIO_E30, /*extint 16 */
+ GPIO_D15, /*extint 17 */
+ GPIO_D20, /*extint 18 */
+ GPIO_B9, /*extint 19 */
+ GPIO_B7, /*extint 20 */
+ GPIO_A25, /*extint 21 */
+ GPIO_D18, /*extint 22 */
+ GPIO_A6 /*extint 23 */
+};
+EXPORT_SYMBOL(extint_to_gpio);
+
+struct gpio_bank u6_gpio_bank[6] = {
+ {(void __iomem *)GPIOA_PINS_REG, (void __iomem *)SCON_SYSMUX0_REG},
+ {(void __iomem *)GPIOB_PINS_REG, (void __iomem *)SCON_SYSMUX2_REG},
+ {(void __iomem *)GPIOC_PINS_REG, (void __iomem *)SCON_SYSMUX4_REG},
+ {(void __iomem *)GPIOD_PINS_REG, (void __iomem *)SCON_SYSMUX6_REG},
+ {(void __iomem *)GPIOE_PINS_REG, (void __iomem *)SCON_SYSMUX8_REG},
+ {(void __iomem *)GPIOF_PINS_REG, (void __iomem *)SCON_SYSMUX10_REG},
+};
+
+static struct gpio_data u6_gpio_data = {
+ ARRAY_SIZE(u6_gpio_bank), /* nb bank */
+ u6_gpio_bank
+};
+
+static struct resource u6_wavex_gpio_resources[] = {
+ [0] = {
+ .start = GPIOA_BASE, /* Physical address */
+ .end = GPIOA_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device u6_wavex_gpio_device = {
+ .name = "u6-gpio",
+ .id = -1,
+ .dev = {
+ .platform_data = &u6_gpio_data,
+ },
+ .num_resources = ARRAY_SIZE(u6_wavex_gpio_resources),
+ .resource = u6_wavex_gpio_resources,
+};
+
+/* list of devices */
+static struct platform_device *platform_devs[] __initdata = {
+ &u6_wavex_gpio_device,
+};
+
+/* register generic devices */
+
+static int __init u67xx_devices_init(void)
+{
+ platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
+ return 0;
+}
+
+arch_initcall(u67xx_devices_init);
diff --git a/arch/arm/plat-u6xxx/Kconfig b/arch/arm/plat-u6xxx/Kconfig
new file mode 100644
index 0000000..b01f77c
--- /dev/null
+++ b/arch/arm/plat-u6xxx/Kconfig
@@ -0,0 +1,20 @@
+menu "STE U6XXX Implementations"
+
+choice
+ prompt "U67XX System Type"
+ default ARCH_U67XX
+
+config ARCH_U67XX
+ bool "U67XX"
+ select PLAT_U6XXX
+ select CPU_ARM926T
+ select GENERIC_TIME
+ select GENERIC_CLOCKEVENTS
+ select U6_MTU_TIMER
+endchoice
+
+endmenu
+
+config U6_MTU_TIMER
+ bool
+ default y
diff --git a/arch/arm/plat-u6xxx/Makefile b/arch/arm/plat-u6xxx/Makefile
new file mode 100644
index 0000000..12c832c
--- /dev/null
+++ b/arch/arm/plat-u6xxx/Makefile
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux kernel hardware independant part of STE U6XXX.
+#
+
+# Common support
+obj-y := io.o irq.o
+
+obj-$(CONFIG_U6_MTU_TIMER) += timer.o
diff --git a/arch/arm/plat-u6xxx/include/mach/cpu.h b/arch/arm/plat-u6xxx/include/mach/cpu.h
new file mode 100644
index 0000000..7512ce6
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/cpu.h
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/cpu.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ * U6 cpu type detection
+ */
+
+#ifndef __ASM_PLAT_CPU_H
+#define __ASM_PLAT_CPU_H
+
+/*
+ * Macros to group U6xxx into cpu classes.
+ * These can be used in most places.
+ * cpu_is_u67xx(): True for U67XX
+ */
+
+#define GET_U6XXX_CLASS ((inl(SCON_SYSVER_REG)&0x0F00)>>8)
+#define GET_U6XXX_SUBCLASS ((inl(SCON_SYSVER_REG)&0x0FF0)>>4)
+
+#define cpu_is_u67xx() 0
+#define cpu_is_u67xx_v2() 0
+#define cpu_is_u67xx_v3() 0
+
+#if defined(CONFIG_ARCH_U67XX)
+# undef cpu_is_u67xx
+# undef cpu_is_u67xx_v2
+# undef cpu_is_u67xx_v3
+# define cpu_is_u67xx() (GET_U6XXX_CLASS == 0x6)
+# define cpu_is_u67xx_v2() (GET_U6XXX_SUBCLASS == 0x62)
+# define cpu_is_u67xx_v3() (GET_U6XXX_SUBCLASS == 0x63)
+#endif
+
+#endif /* __ASM_PLAT_CPU_H */
+
diff --git a/arch/arm/plat-u6xxx/include/mach/debug-macro.S b/arch/arm/plat-u6xxx/include/mach/debug-macro.S
new file mode 100644
index 0000000..039c810
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/debug-macro.S
@@ -0,0 +1,38 @@
+/* linux/arch/arm/plat-u6xxx/include/mach/debug-macro.S
+ *
+ * Debugging macro include header
+ *
+ * Copyright (C) 2010 ST-Ericsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+*/
+
+#include <mach/hardware.h>
+
+ .macro addruart,rx
+ mrc p15, 0, \rx, c1, c0
+ tst \rx, #1 @ MMU enabled?
+ ldreq \rx, = UART1_BASE @ physical base address
+ ldrne \rx, = IO_ADDRESS(UART1_BASE) @ virtual base
+ .endm
+
+ .macro senduart,rd,rx
+ strb \rd, [\rx]
+ .endm
+
+ .macro waituart,rd,rx
+1001:
+ ldr \rd, [\rx, #20]
+ tst \rd, #1 << 5 @ LSR_THRE - 0 when full
+ beq 1001b
+ .endm
+
+ .macro busyuart,rd,rx
+1001:
+ ldr \rd, [\rx, #20]
+ tst \rd, #1 << 6 @ LSR_TEMT - 0 when busy
+ beq 1001b
+ .endm
diff --git a/arch/arm/plat-u6xxx/include/mach/entry-macro.S b/arch/arm/plat-u6xxx/include/mach/entry-macro.S
new file mode 100644
index 0000000..59bb2d2
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/entry-macro.S
@@ -0,0 +1,32 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for U6-based platforms
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * 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.
+ */
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+
+ .macro arch_ret_to_user, tmp1, tmp2
+ .endm
+
+ .macro disable_fiq
+ .endm
+
+ .macro get_irqnr_preamble, base, tmp
+ .endm
+
+ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
+ ldr \base, =IO_ADDRESS(INTC_BASE)
+ ldr \irqnr, [\base, #INTC_VECTOR_IRQ_OFFSET] @ load intc vector reg
+ mov \irqnr, \irqnr, lsr #3 @ Bits[0..2] are reserved
+ ands \irqnr, \irqnr, #0x00FF @ mask Bits[11..31]
+ .endm
+
+ .macro irq_prio_table
+ .endm
+
diff --git a/arch/arm/plat-u6xxx/include/mach/hardware.h b/arch/arm/plat-u6xxx/include/mach/hardware.h
new file mode 100644
index 0000000..79199ec
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/hardware.h
@@ -0,0 +1,41 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/hardware.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/sizes.h>
+#ifndef __ASSEMBLER__
+#include <mach/cpu.h>
+#endif
+
+/*
+ * Processor specific registers defines
+ */
+#include "regs-u6.h"
+
+/*
+ * Where in virtual memory the IO devices (timers, system controllers
+ * and so on)
+ */
+
+#define IO_BASE_VIRT 0xE8000000 /* VA of IO */
+
+/* macro to get at IO space when running virtually */
+/* this version gives more IO address range to map*/
+#define IO_ADDRESS(x) ((x) - IO_BASE_PHYS + IO_BASE_VIRT)
+
+/* typesafe io address */
+#define __io_address(n) __io(IO_ADDRESS(n))
+
+/*
+ * Board specific defines
+ */
+
+#endif
+
diff --git a/arch/arm/plat-u6xxx/include/mach/io.h b/arch/arm/plat-u6xxx/include/mach/io.h
new file mode 100644
index 0000000..058b5e4
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/io.h
@@ -0,0 +1,20 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/io.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Dummy IO map & IO definitions
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io(a) __typesafe_io(a)
+#define __mem_pci(a) (a)
+
+void u67xx_map_io(void);
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff --git a/arch/arm/plat-u6xxx/include/mach/irqs.h b/arch/arm/plat-u6xxx/include/mach/irqs.h
new file mode 100644
index 0000000..abd5ab7
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/irqs.h
@@ -0,0 +1,130 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/irqs.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_PLAT_U6_IRQS_H
+#define __ASM_PLAT_U6_IRQS_H
+
+#define IRQ_COUNT 65
+
+/* external IRQ definition EXTINT */
+#define IRQ_EXTINT(num) (IRQ_COUNT+(num))
+#define EXTINT_NUM(irq) ((irq)-IRQ_COUNT)
+
+#define NR_EXTINT 24
+#define NR_IRQS (IRQ_COUNT+NR_EXTINT)
+
+#ifndef __ASSEMBLY__
+extern unsigned char extint_to_gpio[NR_EXTINT];
+
+#define EXTINT_TO_GPIO(gpio_irq) extint_to_gpio[gpio_irq-IRQ_COUNT]
+
+#define hw_raw_local_irq_save raw_local_irq_save
+#define hw_raw_local_irq_restore raw_local_irq_restore
+
+void /*__init */ u6_init_irq(void);
+void u6_monitor_irq_enter(unsigned int irq);
+void u6_monitor_irq_exit(unsigned int irq);
+#endif /* __ASSEMBLY__ */
+
+/*
+ * Interrupt numbers
+ */
+#define IRQ_GHOST 0
+#define IRQ_EXTINT1 1
+#define IRQ_EXTINT2 2
+#define IRQ_EXTINT3 3
+#define IRQ_RFRD 4
+#define IRQ_MMTU 5
+#define IRQ_IIS 6
+#define IRQ_USB 7
+#define IRQ_I2C2 8
+#define IRQ_TVO 9
+#define IRQ_3G_WUP 10
+#define IRQ_3G_CALINT 11
+#define IRQ_3G_FRAME_IT 12
+#define IRQ_GPADCINT 13
+#define IRQ_ARM9_COMMTX 14
+#define IRQ_ARM9_COMMRX 15
+#define IRQ_KBS 16
+#define IRQ_SCTU2 17
+#define IRQ_SCTU1 18
+#define IRQ_PIO1 19
+#define IRQ_PIO2 20
+#define IRQ_FINT0 21
+#define IRQ_FINT1 22
+#define IRQ_UART2 23
+#define IRQ_UART1 24
+#define IRQ_SPI2 25
+#define IRQ_SPI1 26
+#define IRQ_FCI 27
+#define IRQ_I2C1 28
+#define IRQ_DMAU 29
+#define IRQ_USIM 30
+#define IRQ_HSDPA 31 /* reserved */
+#define IRQ_MSI 32
+#define IRQ_JDI 33
+#define IRQ_JDU 34
+#define IRQ_NFI 35
+#define IRQ_IPP 36
+#define IRQ_VDC 37
+#define IRQ_VEC 38
+#define IRQ_VDE 39
+#define IRQ_CAM 40
+#define IRQ_ETB_ACQ 41
+#define IRQ_ETB_FULL 42
+#define IRQ_RESERVED43 43
+#define IRQ_RESERVED44 44
+#define IRQ_RESERVED45 45 /* reserved */
+#define IRQ_RESERVED46 46
+#define IRQ_RESERVED47 47
+#define IRQ_PDCU 48
+#define IRQ_MC2SC0 49
+#define IRQ_MC2SC1 50
+#define IRQ_MC2SC2 51
+#define IRQ_MC2SC3 52
+#define IRQ_MC2SC4 53
+#define IRQ_MC2SC5 54
+#define IRQ_MC2SC6 55
+#define IRQ_MC2SC7 56
+
+/* INTC PRIOMASK_IRQ Register (32 bits) */
+#define INTC_PRIOMASK_IRQ_OFFSET 0x0
+#define INTC_PRIOMASK_IRQ_REG IO_ADDRESS(INTC_BASE + INTC_PRIOMASK_IRQ_OFFSET)
+
+/* INTC PRIOMASK_FIQ Register (32 bits) */
+#define INTC_PRIOMASK_FIQ_OFFSET 0x4
+#define INTC_PRIOMASK_FIQ_REG IO_ADDRESS(INTC_BASE + INTC_PRIOMASK_FIQ_OFFSET)
+
+/* INTC VECTOR_IRQ Register (32 bits) */
+#define INTC_VECTOR_IRQ_OFFSET 0x100
+#define INTC_VECTOR_IRQ_REG IO_ADDRESS(INTC_BASE + INTC_VECTOR_IRQ_OFFSET)
+
+/* INTC VECTOR_FIQ Register (32 bits) */
+#define INTC_VECTOR_FIQ_OFFSET 0x104
+#define INTC_VECTOR_FIQ_REG IO_ADDRESS(INTC_BASE + INTC_VECTOR_FIQ_OFFSET)
+
+/* INTC PENDING_* Registers (32 bits) */
+#define INTC_PENDING_1_OFFSET 0x200
+#define INTC_PENDING_2_OFFSET 0x204
+#define INTC_PENDING_3_OFFSET 0x208
+#define INTC_FEATURES_OFFSET 0x300
+
+/* INTC REQUEST 64 Registers (32 bits) */
+#define INTC_REQUEST1_OFFSET 0x404
+#define INTC_REQUEST64_OFFSET 0x500
+
+/* INTC MOD_ID Register (32 bits) */
+#define INTC_MOD_ID_OFFSET 0xFFC
+
+/* interrupt x [1..64] request configuration */
+#define INTC_REQUESTx(x) IO_ADDRESS(INTC_BASE+INTC_REQUEST1_OFFSET+(x-1)*4)
+
+/* EXTINTx [0..23] configuration register */
+#define EXTINT_CFGx(x) IO_ADDRESS(EXTINT_BASE+(x)*4)
+
+#endif /* __ASM_PLAT_U6_IRQS_H */
diff --git a/arch/arm/plat-u6xxx/include/mach/memory.h b/arch/arm/plat-u6xxx/include/mach/memory.h
new file mode 100644
index 0000000..0fa6cea
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/memory.h
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/memory.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET UL(0x20000000)
+#define BOOT_PARAMS_OFFSET (PHYS_OFFSET + 0x100)
+
+/**
+ * CONSISTENT_DMA_SIZE: Size of DMA-consistent memory region.
+ * Must be multiple of 2M,between 2MB and 14MB inclusive
+ */
+#define CONSISTENT_DMA_SIZE (SZ_2M)
+
+#endif
diff --git a/arch/arm/plat-u6xxx/include/mach/platform.h b/arch/arm/plat-u6xxx/include/mach/platform.h
new file mode 100644
index 0000000..5265ccd
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/platform.h
@@ -0,0 +1,15 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/platform.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_ARCH_PLATFORM_H
+#define __ASM_ARCH_PLATFORM_H 1
+
+#include <linux/types.h>
+#include <mach/hardware.h>
+
+#endif /* __ASM_ARCH_PLATFORM_H */
diff --git a/arch/arm/plat-u6xxx/include/mach/regs-u6.h b/arch/arm/plat-u6xxx/include/mach/regs-u6.h
new file mode 100644
index 0000000..aa2fbb0
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/regs-u6.h
@@ -0,0 +1,121 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/regs-u6.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ * Basic register address definitions in physical memory
+ */
+
+#if !defined(__REGS_U6_H__)
+#define __REGS_U6_H__
+
+#define IO_BASE_PHYS 0xC1000000 /* phys base address of reg */
+#define IO_SIZE 0x03400000 /* How much */
+
+/*
+ * System Controller Core devices base address table
+ */
+
+/* DMA Controller */
+#define DMAU_BASE (IO_BASE_PHYS + 0x0000000)
+
+/* Interrupt Controller */
+#define INTC_BASE (IO_BASE_PHYS + 0x0100000)
+
+/* SDRam controller */
+#define SDI_BASE (IO_BASE_PHYS + 0x0200000)
+
+/* Nand Flash Inteface controller */
+#define NFI_BASE (IO_BASE_PHYS + 0x0300000)
+
+/* USB controller */
+#define USB_BASE (IO_BASE_PHYS + 0x0400000)
+
+/* Video Display Engine */
+#define VDE_BASE (IO_BASE_PHYS + 0x0500000)
+
+/* Video Decoder */
+#define VDC_BASE (IO_BASE_PHYS + 0x1000000)
+
+/* Viedo Encoder */
+#define VEC_BASE (IO_BASE_PHYS + 0x1100000)
+
+/* Texture Codec, MPEG4 encoder sub module */
+#define TC_BASE (IO_BASE_PHYS + 0x1102000)
+
+/* Image Post-Processor */
+#define IPP2_BASE (IO_BASE_PHYS + 0x1200000)
+
+/* JPEG Decoder Unit */
+#define JDU_BASE (IO_BASE_PHYS + 0x1300000)
+
+/* TV output controller */
+#define TVO_BASE (IO_BASE_PHYS + 0x1400000)
+
+/* Camera controller */
+#define CAM_BASE (IO_BASE_PHYS + 0x1800000)
+
+/* External Bus Interfaces */
+#define EBI_BASE (IO_BASE_PHYS + 0x2001000)
+
+/* SPI controllers */
+#define SPI1_BASE (IO_BASE_PHYS + 0x2002000)
+#define SPI2_BASE (IO_BASE_PHYS + 0x2003000)
+
+/* SD/MMC controller */
+#define FCI_BASE (IO_BASE_PHYS + 0x2008000)
+
+/* Crypto Acceleration Engine */
+#define CAE_BASE (IO_BASE_PHYS + 0x2009000)
+
+/* Multimedia Timer Unit, aka MTU in Datasheet */
+#define MMTU_BASE (IO_BASE_PHYS + 0x2101000)
+
+/* System controller timer units */
+#define SCTU1_BASE (IO_BASE_PHYS + 0x2102000)
+#define SCTU2_BASE (IO_BASE_PHYS + 0x2103000)
+
+/* General Purpose I/O units */
+#define GPIOA_BASE (IO_BASE_PHYS + 0x2104000)
+#define GPIOB_BASE (IO_BASE_PHYS + 0x2104200)
+#define GPIOC_BASE (IO_BASE_PHYS + 0x2104400)
+#define GPIOD_BASE (IO_BASE_PHYS + 0x2104600)
+#define GPIOE_BASE (IO_BASE_PHYS + 0x2104800)
+#define GPIOF_BASE (IO_BASE_PHYS + 0x2104A00)
+
+/* External Interrupt controller */
+#define EXTINT_BASE (IO_BASE_PHYS + 0x2105000)
+
+/* Keyboard Scanner */
+#define KBS_BASE (IO_BASE_PHYS + 0x2106000)
+
+/* Pulse Width Modulators */
+#define PWM1_BASE (IO_BASE_PHYS + 0x2108000)
+#define PWM2_BASE (IO_BASE_PHYS + 0x2109000)
+#define PWM3_BASE (IO_BASE_PHYS + 0x210A000)
+
+/* I2C controllers */
+#define I2C1_BASE (IO_BASE_PHYS + 0x210C000)
+#define I2C2_BASE (IO_BASE_PHYS + 0x210D000)
+
+/* UARTs */
+#define UART1_BASE (IO_BASE_PHYS + 0x210E000)
+#define UART2_BASE (IO_BASE_PHYS + 0x210F000)
+
+/* Clock Generation Unit */
+#define CGU_BASE (IO_BASE_PHYS + 0x2200000)
+
+/* Time base Unit */
+#define TBU_BASE (IO_BASE_PHYS + 0x2201000)
+
+/* Power Down Control Unit */
+#define PDCU_BASE (IO_BASE_PHYS + 0x2202000)
+
+/* Watchdog & Reset Unit */
+#define WDRU_BASE (IO_BASE_PHYS + 0x2203000)
+
+/* System Configuration */
+#define SCON_BASE (IO_BASE_PHYS + 0x2204000)
+
+#endif /* __REGS_U6_H__ */
diff --git a/arch/arm/plat-u6xxx/include/mach/scon.h b/arch/arm/plat-u6xxx/include/mach/scon.h
new file mode 100644
index 0000000..67b7c89
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/scon.h
@@ -0,0 +1,121 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/scon.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * System Configuration Block registers
+ */
+
+#ifndef __ARCH_SCON_H
+#define __ARCH_SCON_H
+
+/*
+ * this structure allows to store SCON register values to set
+ * during initialization step
+ */
+
+struct u6_scon_config {
+ void __iomem *scon_reg_addr;
+ u32 scon_reg_value;
+};
+
+#define SCON_REGISTER_NB 15
+
+/* SCON SYSVER Register (32 bits) */
+#define SCON_SYSVER_OFFSET 0x0
+#define SCON_SYSVER_REG IO_ADDRESS(SCON_BASE + SCON_SYSVER_OFFSET)
+
+/* SCON SYSCON0 Register (32 bits) */
+#define SCON_SYSCON0_OFFSET 0x4
+#define SCON_SYSCON0_REG IO_ADDRESS(SCON_BASE + SCON_SYSCON0_OFFSET)
+
+/* SCON SYSPROT Register (32 bits) */
+#define SCON_SYSPROT_OFFSET 0x8
+#define SCON_SYSPROT_REG IO_ADDRESS(SCON_BASE + SCON_SYSPROT_OFFSET)
+
+/* SCON SYSMUX0 Register (32 bits) */
+#define SCON_SYSMUX0_OFFSET 0xC
+#define SCON_SYSMUX0_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX0_OFFSET)
+
+/* SCON SYSMUX1 Register (32 bits) */
+#define SCON_SYSMUX1_OFFSET 0x10
+#define SCON_SYSMUX1_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX1_OFFSET)
+
+/* SCON SYSMUX2 Register (32 bits) */
+#define SCON_SYSMUX2_OFFSET 0x14
+#define SCON_SYSMUX2_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX2_OFFSET)
+
+/* SCON SYSMUX3 Register (32 bits) */
+#define SCON_SYSMUX3_OFFSET 0x18
+#define SCON_SYSMUX3_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX3_OFFSET)
+
+/* SCON SYSMUX4 Register (32 bits) */
+#define SCON_SYSMUX4_OFFSET 0x1C
+#define SCON_SYSMUX4_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX4_OFFSET)
+
+/* SCON SYSMUX5 Register (32 bits) */
+#define SCON_SYSMUX5_OFFSET 0x20
+#define SCON_SYSMUX5_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX5_OFFSET)
+
+/* SCON SYSMUX6 Register (32 bits) */
+#define SCON_SYSMUX6_OFFSET 0x24
+#define SCON_SYSMUX6_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX6_OFFSET)
+
+/* SCON SYSMUX7 Register (32 bits) */
+#define SCON_SYSMUX7_OFFSET 0x28
+#define SCON_SYSMUX7_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX7_OFFSET)
+
+/* SCON SYSMUX8 Register (32 bits) */
+#define SCON_SYSMUX8_OFFSET 0x2C
+#define SCON_SYSMUX8_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX8_OFFSET)
+
+/* SCON SYSMUX9 Register (32 bits) */
+#define SCON_SYSMUX9_OFFSET 0x30
+#define SCON_SYSMUX9_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX9_OFFSET)
+
+/* SCON SYSMUX10 Register (32 bits) */
+#define SCON_SYSMUX10_OFFSET 0x34
+#define SCON_SYSMUX10_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX10_OFFSET)
+
+/* SCON SYSMUX11 Register (32 bits) */
+#define SCON_SYSMUX11_OFFSET 0x38
+#define SCON_SYSMUX11_REG IO_ADDRESS(SCON_BASE + SCON_SYSMUX11_OFFSET)
+
+/* SCON SYSPAD0 Register (32 bits) */
+#define SCON_SYSPAD0_OFFSET 0x50
+#define SCON_SYSPAD0_REG IO_ADDRESS(SCON_BASE + SCON_SYSPAD0_OFFSET)
+
+/* SCON SYSPAD1 Register (32 bits) */
+#define SCON_SYSPAD1_OFFSET 0x54
+#define SCON_SYSPAD1_REG IO_ADDRESS(SCON_BASE + SCON_SYSPAD1_OFFSET)
+
+/* SCON SYSPAD2 Register (32 bits) */
+#define SCON_SYSPAD2_OFFSET 0x58
+#define SCON_SYSPAD2_REG IO_ADDRESS(SCON_BASE + SCON_SYSPAD2_OFFSET)
+
+/* SCON SYSCON1 Register (32 bits) */
+#define SCON_SYSCON1_OFFSET 0x70
+#define SCON_SYSCON1_REG IO_ADDRESS(SCON_BASE + SCON_SYSCON1_OFFSET)
+
+/* SCON SYSIISMUX Register (32 bits) */
+#define SCON_SYSIISMUX_OFFSET 0x74
+#define SCON_SYSIISMUX_REG IO_ADDRESS(SCON_BASE + SCON_SYSIISMUX_OFFSET)
+
+/* SCON SYSAHBPROT Register (32 bits) */
+#define SCON_SYSAHBPROT_OFFSET 0x78
+#define SCON_SYSAHBPROT_REG IO_ADDRESS(SCON_BASE + SCON_SYSAHBPROT_OFFSET)
+
+/* SCON SYSIVSBRIDGE Register (32 bits) */
+#define SCON_SYSIVSBRIDGE_OFFSET 0x7C
+#define SCON_SYSIVSBRIDGE_REG IO_ADDRESS(SCON_BASE + SCON_SYSIVSBRIDGE_OFFSET)
+
+/* Register description for SYSPADx */
+/* SYSPAD configuration defines */
+#define SCON_PAD_PULL_UP 0
+#define SCON_PAD_REPEATER 1
+#define SCON_PAD_PLAIN_INPUT 2
+#define SCON_PAD_PULL_DOWN 3
+
+#endif
diff --git a/arch/arm/plat-u6xxx/include/mach/system.h b/arch/arm/plat-u6xxx/include/mach/system.h
new file mode 100644
index 0000000..cbe3380
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/system.h
@@ -0,0 +1,42 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/system.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+#include <mach/hardware.h>
+
+/* Watchdog & Reset Unit TIMER Register (16 bits) */
+#define WDRU_TIM_OFFSET 0x4
+
+static inline void arch_idle(void)
+{
+ /*
+ * This should do all the clock switching
+ * and wait for interrupt tricks
+ */
+ cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+ unsigned long flags;
+ /*
+ * To reset, we hit the on-board reset register
+ * in the system FPGA
+ */
+ /* diasble HW interruption */
+ hw_raw_local_irq_save(flags);
+ /* load watchdog with reset value */
+ outl(0x5, IO_ADDRESS(WDRU_BASE + WDRU_TIM_OFFSET));
+ /* wait for wachdog expiration */
+ while (1)
+ ;
+}
+
+#endif
diff --git a/arch/arm/plat-u6xxx/include/mach/timer.h b/arch/arm/plat-u6xxx/include/mach/timer.h
new file mode 100644
index 0000000..049e72d
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/timer.h
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/timer.h
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#ifndef __PLAT_TIMER_H
+#define __PLAT_TIMER_H
+#ifdef U6_TIMER_C
+#define PUBLIC
+#else
+#define PUBLIC extern
+#endif
+
+struct sys_timer;
+
+PUBLIC struct sys_timer u6_timer;
+
+PUBLIC void __init u6_timer_init(void);
+
+#undef PUBLIC
+#endif
diff --git a/arch/arm/plat-u6xxx/include/mach/timex.h b/arch/arm/plat-u6xxx/include/mach/timex.h
new file mode 100644
index 0000000..1e71241
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/timex.h
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/timex.h
+ *
+ * Integrator architecture timex specifications
+ *
+ * Copyright (C) 1999 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
+ */
+
+#define CLOCK_TICK_RATE (50000000 / 16)
diff --git a/arch/arm/plat-u6xxx/include/mach/uncompress.h b/arch/arm/plat-u6xxx/include/mach/uncompress.h
new file mode 100644
index 0000000..7dae14d
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/uncompress.h
@@ -0,0 +1,50 @@
+/*
+ * linux/arch/arm/plat-u6xxx/include/mach/uncompress.h
+ *
+ * Copyright (C) 2010 ST-Ericsson SA
+ * 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
+ */
+
+#include <linux/io.h>
+#include "mach/hardware.h"
+
+/* UART THR Register (8 bits) */
+#define UART1_THR_OFFSET 0x0
+#define UART1_THR_REG IO_ADDRESS(UART1_BASE + UART1_THR_OFFSET)
+
+/* UART LSR Register (8 bits) */
+#define UART1_LSR_OFFSET 0x14
+#define UART1_LSR_REG IO_ADDRESS(UART1_BASE + UART1_LSR_OFFSET)
+
+static void putc(int c)
+{
+ if (c == '\n')
+ putc('\r');
+
+ while (!(readb(UART1_LSR_REG) & (1<<5)))
+ barrier();
+ writeb(c, UART1_THR_REG);
+}
+
+static inline void flush(void)
+{
+}
+
+/* nothing to do */
+#define arch_decomp_setup()
+
+#define arch_decomp_wdog()
diff --git a/arch/arm/plat-u6xxx/include/mach/vmalloc.h b/arch/arm/plat-u6xxx/include/mach/vmalloc.h
new file mode 100644
index 0000000..583033f
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/vmalloc.h
@@ -0,0 +1,10 @@
+/*
+ * linux/arch/arm/plat-u6/include/mach/vmalloc.h
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ *
+ * Virtual memory allocations
+ * End must be above the I/O registers and on an even 2MiB boundary.
+ */
+#define VMALLOC_END (PAGE_OFFSET + 0x28000000)
diff --git a/arch/arm/plat-u6xxx/io.c b/arch/arm/plat-u6xxx/io.c
new file mode 100644
index 0000000..d4ae93b
--- /dev/null
+++ b/arch/arm/plat-u6xxx/io.c
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/arm/plat-u6xxx/io.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Philippe Langlais <philippe.langlais at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+
+#include <asm/mach/map.h>
+
+
+static struct map_desc u67xx_io_desc[] __initdata = {
+ {
+ .virtual = IO_BASE_VIRT, /* only peripherals */
+ .pfn = __phys_to_pfn(IO_BASE_PHYS),
+ .length = IO_SIZE,
+ .type = MT_DEVICE,
+ }
+};
+
+void __init u67xx_map_io(void)
+{
+ iotable_init(u67xx_io_desc, ARRAY_SIZE(u67xx_io_desc));
+}
+
diff --git a/arch/arm/plat-u6xxx/irq.c b/arch/arm/plat-u6xxx/irq.c
new file mode 100644
index 0000000..1c11a2e
--- /dev/null
+++ b/arch/arm/plat-u6xxx/irq.c
@@ -0,0 +1,231 @@
+/*
+ * linux/arch/arm/plat-u6xxx/irq.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Loic Pallardy <loic.pallardy at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/irq.h>
+#include <mach/irqs.h> /* U6 specific constants, types */
+
+#define INTC_REQUESTx_PENDING_MASK (1 << 31)
+#define INTC_REQUESTx_SET_SWINT_MASK (1 << 30)
+#define INTC_REQUESTx_CLR_SWINT_MASK (1 << 29)
+#define INTC_REQUESTx_WE_PRIORITY_MASK (1 << 28)
+#define INTC_REQUESTx_WE_TARGET_MASK (1 << 27)
+#define INTC_REQUESTx_WE_ENABLE_MASK (1 << 26)
+#define INTC_REQUESTx_WE_ACTIVE_LOW_MASK (1 << 25)
+#define INTC_REQUESTx_ACTIVE_LOW_MASK (1 << 17)
+#define INTC_REQUESTx_ENABLE_MASK (1 << 16)
+#define INTC_REQUESTx_TARGET_MASK (1 << 8)
+
+#define INTC_IID_USB_LP_INT 13
+
+static void u6_irq_mask(uint32_t irqno)
+{
+ if (irqno > 0 || irqno < IRQ_COUNT) {
+ unsigned long flags;
+ uint32_t a, v;
+
+ hw_raw_local_irq_save(flags);
+
+ a = INTC_REQUESTx(irqno);
+ v = readl(a);
+ v &= ~INTC_REQUESTx_ENABLE_MASK;
+ v |= INTC_REQUESTx_WE_ENABLE_MASK;
+ v |= INTC_REQUESTx_CLR_SWINT_MASK;
+ writel(v, a);
+
+ hw_raw_local_irq_restore(flags);
+ }
+}
+
+static void u6_irq_unmask(uint32_t irqno)
+{
+ if (irqno > 0 || irqno < IRQ_COUNT) {
+ unsigned long flags;
+ uint32_t a, v;
+
+ hw_raw_local_irq_save(flags);
+
+ a = INTC_REQUESTx(irqno);
+ v = readl(a);
+ v |= INTC_REQUESTx_ENABLE_MASK;
+ v |= INTC_REQUESTx_WE_ENABLE_MASK;
+ v |= INTC_REQUESTx_CLR_SWINT_MASK;
+ writel(v, a);
+
+ hw_raw_local_irq_restore(flags);
+ }
+}
+
+static int u6_irq_type(unsigned irqno, unsigned type)
+{
+ int l;
+ uint32_t reg = INTC_REQUESTx(irqno);
+
+ if (irqno > 0 || irqno < IRQ_COUNT) {
+ if (type == IRQF_TRIGGER_LOW) {
+ l = (INTC_REQUESTx_ACTIVE_LOW_MASK
+ | INTC_REQUESTx_WE_ACTIVE_LOW_MASK);
+ } else if (type == IRQF_TRIGGER_HIGH) {
+ l = (INTC_REQUESTx_WE_ACTIVE_LOW_MASK);
+ } else {
+ goto bad;
+ }
+
+ writel(l, reg);
+ return 0;
+
+ }
+
+bad:
+ return -EINVAL;
+}
+
+int u6_irq_enabled(uint32_t irqno)
+{
+ if (irqno > 0 || irqno < IRQ_COUNT) {
+ uint32_t a = INTC_REQUESTx(irqno);
+ uint32_t v = readl(a);
+
+ return v & INTC_REQUESTx_ENABLE_MASK;
+ } else
+ return 0;
+}
+
+static struct irq_chip u6_irq_chip = {
+ .ack = u6_irq_mask,
+ .mask = u6_irq_mask, /* disable irqs */
+ .unmask = u6_irq_unmask, /* enable irqs */
+ .set_type = u6_irq_type,
+};
+
+
+#if defined(CONFIG_ARCH_U67XX)
+
+static const uint32_t u6_irq_config[] = {
+ 0, /* GHOST 0 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* EXTINT1 1 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* EXTINT2 2 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* EXTINT3 3 */
+ 0, /* RFRD 4 */
+ 0, /* MTU 5 */
+ 0, /* IIS 6 */
+ 0, /* USB 7 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* I2C2 8 */
+ 0, /* TVO 9 */
+ 0, /* 3G_WUP 10 */
+ 0, /* 3G_CALINT 11 */
+ 0, /* 3G_FRAME_IT 12 */
+ 0, /* GPADCINT 13 */
+ 0, /* ARM9_COMMTX 14 */
+ 0, /* ARM9_COMMRX 15 */
+ 0, /* KBS 16 */
+ 0, /* SCTU2 17 */
+ 0, /* SCTU1 18 */
+ 0, /* PIO1 19 */
+ 0, /* PIO2 20 */
+ 0, /* FINT0 21 */
+ 0, /* FINT1 22 */
+ 0, /* UART2 23 */
+ 0, /* UART1 24 */
+ 0, /* SPI2 25 */
+ 0, /* SPI1 26 */
+ 0, /* FCI 27 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* I2C1 28 */
+ 0, /* DMAU 29 */
+ 0, /* USIM 30 */
+ 0, /* RESERVED31 31 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* MSI 32 */
+ 0, /* JDI 33 */
+ 0, /* JDU 34 */
+ 0, /* NFI 35 */
+ 0, /* IPP 36 */
+ 0, /* VDC 37 */
+ 0, /* VEC 38 */
+ 0, /* VDE 39 */
+ INTC_REQUESTx_ACTIVE_LOW_MASK, /* CAM 40 */
+ 0, /* ETB_ACQ 41 */
+ 0, /* ETB_FULL 42 */
+ 0, /* DIGRF_TX 43 */
+ 0, /* DIGRF_RX 44 */
+ 0, /* RESERVED45 45 */
+ 0, /* FIR_FI 46 */
+ 0, /* FIR 47 */
+ 0, /* PDCU 48 */
+ 0, /* MC2SC0 49 */
+ 0, /* MC2SC1 50 */
+ 0, /* MC2SC2 51 */
+ 0, /* MC2SC3 52 */
+ 0, /* MC2SC4 53 */
+ 0, /* MC2SC5 54 */
+ 0, /* MC2SC6 55 */
+ 0, /* MC2SC7 56 */
+ 0, /* Reserved 57 */
+ 0, /* Reserved 58 */
+ 0, /* Reserved 59 */
+ 0, /* Reserved 60 */
+ 0, /* Reserved 61 */
+ 0, /* Reserved 62 */
+ 0, /* Reserved 63 */
+ 0, /* Reserved 64 */
+};
+
+#endif
+
+static const uint32_t u6_irq_irq_priority;
+static const uint32_t u6_irq_fiq_priority;
+
+void __init u6_init_irq(void)
+{
+ unsigned int irqno;
+
+ /* Clock interrupt controller.
+ */
+ struct clk *clk = clk_get(NULL, "INTC");
+ clk_enable(clk);
+ clk_put(clk);
+
+ /* The address of the vector table INTCdata.asm is assumed to be aligned
+ * to a 2KB boundary. Thus the register access value will be padded with
+ * zeroes, which is conforming to the 'READ_ONLY' attributes of the LS
+ * 11 bits. We are using the same table for both IRQ and FIQ.
+ */
+ writel(0, INTC_VECTOR_FIQ_REG); /* no vector IRQ */
+ writel(0, INTC_VECTOR_IRQ_REG); /* no vector FIQ */
+
+ writel(u6_irq_irq_priority, INTC_PRIOMASK_IRQ_REG);
+ writel(u6_irq_fiq_priority, INTC_PRIOMASK_FIQ_REG);
+
+ /* Initialize the individual interrupt sources.
+ */
+ for (irqno = 1; irqno < IRQ_COUNT; irqno += 1) {
+ uint32_t a = INTC_REQUESTx(irqno);
+ uint32_t v = u6_irq_config[irqno];
+
+ v |= 4;
+ v |= INTC_REQUESTx_WE_ACTIVE_LOW_MASK;
+ v |= INTC_REQUESTx_WE_TARGET_MASK;
+ v |= INTC_REQUESTx_WE_PRIORITY_MASK;
+ v |= INTC_REQUESTx_WE_ENABLE_MASK;
+ v |= INTC_REQUESTx_CLR_SWINT_MASK;
+
+ writel(v, a);
+
+ set_irq_chip(irqno, &u6_irq_chip);
+ set_irq_handler(irqno, handle_level_irq);
+ set_irq_flags(irqno, IRQF_VALID | IRQF_PROBE);
+ }
+}
diff --git a/arch/arm/plat-u6xxx/timer.c b/arch/arm/plat-u6xxx/timer.c
new file mode 100644
index 0000000..62f13f5
--- /dev/null
+++ b/arch/arm/plat-u6xxx/timer.c
@@ -0,0 +1,679 @@
+/*
+ * linux/arch/arm/plat-u6xxx/timer.c
+ *
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Vincent Guittot <vincent.guittot at stericsson.com> for ST-Ericsson.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/mach/time.h>
+
+#include <mach/hardware.h>
+
+#include <asm/mach/irq.h>
+#include <linux/interrupt.h>
+#include <mach/irqs.h>
+
+#include <linux/clk.h>
+
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+
+#ifdef CONFIG_U6_POWER_SYSFS
+#include "power_sysfs.h"
+#endif
+
+/*** System timer variable ***/
+struct sys_timer u6_timer;
+
+/*** Module definition ***/
+/*************************/
+
+#define MODULE_NAME "U6_TIMER"
+#define PKMOD MODULE_NAME ": "
+
+#undef U6_TIMER_DEBUG
+#if defined(U6_TIMER_DEBUG)
+#define debug(fmt, args...) \
+ printk(PKMOD fmt, ## args)
+#else
+#define debug(fmt, args...)
+#endif
+
+#define U6_MMTU_CLOCK_SOURCE
+
+/*** MMTU clock devices ***/
+/*************************/
+
+/*** MMTU HW ip register index definition ***/
+#define MMTU_CON_IDX 0
+#define MMTU_TCVAL_IDX 1
+#define MMTU_PRESCALER_IDX 2
+#define MMTU_MATCH_CON_IDX 3
+#define MMTU_MATCH0_IDX 5
+#define MMTU_MATCH1_IDX 6
+#define MMTU_INT_OFFSET 0x3F4
+#define MMTU_MOD_CONF_IDX 1
+#define MMTU_INT_CLR_ENA_IDX 2
+#define MMTU_INT_SET_ENA_IDX 3
+#define MMTU_INT_STATUS_IDX 4
+#define MMTU_INT_ENABLE_IDX 5
+#define MMTU_INT_CLR_STAT_IDX 6
+#define MMTU_INT_SET_STAT_IDX 7
+
+#define MMTU_IRQ_MASK 0x1
+#define MMTU_USED_MATCH_IDX MMTU_MATCH0_IDX
+
+/* MMTU sys clock definition */
+#define MMTU_SYS_FRQ 13000000
+
+/*** MMTU Clock event device ***/
+#define MMTU_ROOT_FRQ 8000
+static int u6_mmtu_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt);
+static void u6_mmtu_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt);
+
+static struct clock_event_device clockevent_mmtu = {
+ .name = "mmtu_timer",
+ .rating = 360,
+ .shift = 30,
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_next_event = u6_mmtu_set_next_event,
+ .set_mode = u6_mmtu_set_mode,
+};
+
+/*** MMTU Clock source device ***/
+#ifdef U6_MMTU_CLOCK_SOURCE
+static cycle_t u6_mmtu_read(struct clocksource *);
+
+static struct clocksource clocksource_mmtu = {
+ .name = "mmtu_timer",
+ .rating = 360,
+ .read = u6_mmtu_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .shift = 8,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+#endif
+
+/*** MMTU driver ***/
+#define RELOAD_COUNTER_POWER_MMTU 32
+#define RELOAD_COUNTER_MMTU (1 << RELOAD_COUNTER_POWER_MMTU)
+
+struct mmtu_ctxt {
+ unsigned long *base;
+ int autoreload;
+ uint32_t compvalue;
+ uint32_t endvalue;
+ struct clk *clk;
+ int mode;
+};
+
+struct mmtu_ctxt mmtu_table[1] = {
+ {
+ .base = (unsigned long *)IO_ADDRESS(MMTU_BASE),
+ .autoreload = 0,
+ .compvalue = 0,
+ .endvalue = 0,
+ .clk = NULL,
+ .mode = 0,
+ },
+};
+
+static inline struct mmtu_ctxt *u6_mmtu_get_context(int id)
+{
+ return &(mmtu_table[id]);
+}
+
+static inline int u6_mmtu_timer_start(unsigned long cycles, int id);
+static inline void u6_mmtu_clk_enable(int id);
+static inline void u6_mmtu_clk_disable(int id);
+
+static irqreturn_t
+u6_mmtu_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ uint8_t status, enable;
+ struct mmtu_ctxt *mmtu;
+
+ mmtu = u6_mmtu_get_context(0);
+
+ status = readl((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_STATUS_IDX));
+ enable = readl((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_ENABLE_IDX));
+
+ debug("mmtu_timer_interrupt %d\n", status);
+
+ if (status & enable & MMTU_IRQ_MASK) {
+ struct clock_event_device *evt = &clockevent_mmtu;
+
+ writel(MMTU_IRQ_MASK, (mmtu->base + MMTU_INT_OFFSET
+ + MMTU_INT_CLR_STAT_IDX));
+
+ if (mmtu->autoreload)
+ u6_mmtu_timer_start(mmtu->compvalue, 0);
+ else
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET +
+ MMTU_INT_CLR_ENA_IDX));
+
+ if (evt->event_handler)
+ evt->event_handler(evt);
+ }
+ return IRQ_HANDLED;
+}
+
+static struct irqaction u6_mmtu_timer_irq = {
+ .name = "U6 MMTU timer Tick",
+ .flags = IRQF_DISABLED,
+ .handler = (irq_handler_t) u6_mmtu_timer_interrupt,
+};
+
+static inline void u6_mmtu_clk_enable(int id)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
+
+ /* Clock Multimedia Timer Unit.
+ */
+ if ((mmtu->clk != NULL) && (mmtu->mode == 0)) {
+ debug("mmtu_clk_enable\n");
+ mmtu->mode = 1;
+ clk_enable(mmtu->clk);
+ }
+}
+
+static inline void u6_mmtu_clk_disable(int id)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
+
+ /* Clock Multimedia Timer Unit.
+ */
+ if ((mmtu->clk != NULL) && (mmtu->mode == 1)) {
+ debug("mmtu_clk_disable\n");
+ clk_disable(mmtu->clk);
+ mmtu->mode = 0;
+ }
+}
+
+static inline int u6_mmtu_timer_start(unsigned long cycles, int id)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
+
+ debug("mmtu_timer_start %d\n", cycles);
+ u6_mmtu_clk_enable(id);
+
+ /* MMTU limitation : can't set a value smaller or equal to tcval + 1 */
+ cycles = cycles < 2 ? 2 : cycles;
+
+ mmtu->compvalue = cycles;
+
+ mmtu->endvalue = mmtu->compvalue
+ + readl((mmtu->base + MMTU_TCVAL_IDX));
+
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+
+ writel(mmtu->endvalue, (mmtu->base + MMTU_USED_MATCH_IDX));
+
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
+
+ /* the value has already expired */
+ if ((mmtu->endvalue <= readl((mmtu->base + MMTU_TCVAL_IDX)))
+ && (mmtu->endvalue > mmtu->compvalue)
+ && !(readl((mmtu->base + MMTU_INT_OFFSET
+ + MMTU_INT_STATUS_IDX)) & MMTU_IRQ_MASK))
+ writel(MMTU_IRQ_MASK, (mmtu->base + MMTU_INT_OFFSET
+ + MMTU_INT_SET_STAT_IDX));
+
+ return 0;
+}
+
+static int u6_mmtu_timer_init(int id, unsigned long reload,
+ unsigned long prescale, int over_it)
+{
+
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(id);
+
+ debug("mmtu_timer_init %d\n", id);
+
+ /* Enable clock */
+/*
+ u6_mmtu_clk_enable(id);
+ clk mngt not available yet
+ directly enable it
+*/
+ {
+ unsigned long flags;
+ unsigned long reg;
+ hw_raw_local_irq_save(flags);
+ reg = readl(CGU_GATESC2_REG);
+ reg |= 0x1 << 2;
+ writel(reg, CGU_GATESC2_REG);
+ hw_raw_local_irq_restore(flags);
+ }
+
+ /* Reset timer */
+ /* reset control register */
+ writel(0x0000, (mmtu->base + MMTU_CON_IDX));
+ writel(0x0002, (mmtu->base + MMTU_CON_IDX));
+ /* reset control register */
+ writel(0x0000, (mmtu->base + MMTU_CON_IDX));
+
+ /* clear whole enable irq register */
+ writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_ENA_IDX));
+ /* clear whole status register */
+ writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+
+ /* reset pre-scaler reload register */
+ writel(0x00000000, (mmtu->base + MMTU_PRESCALER_IDX));
+
+ /* reset match control register */
+ writel(0x0000, (mmtu->base + MMTU_MATCH_CON_IDX));
+ /* reset match 0 register */
+ writel(0x00000000, (mmtu->base + MMTU_MATCH0_IDX));
+ /* reset match 1 register */
+ writel(0x00000000, (mmtu->base + MMTU_MATCH1_IDX));
+
+ /* Initialize timer */
+ writel(prescale - 1, (mmtu->base + MMTU_PRESCALER_IDX));
+ /* power of 2 system clock */
+ writel(reload, (mmtu->base + MMTU_MATCH0_IDX));
+
+ /* enable counter register */
+ writel(0x0001, (mmtu->base + MMTU_CON_IDX));
+
+ /* clear whole status register */
+ writel(0xFF, (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+
+ if (id == 0)
+ setup_irq(IRQ_MMTU, &u6_mmtu_timer_irq);
+
+ /* Disable clock */
+#ifndef U6_MMTU_CLOCK_SOURCE
+ u6_mmtu_clk_disable(id);
+#endif
+ return 0;
+}
+
+/*** MMTU Clock event device ***/
+
+static int u6_mmtu_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ debug("mmtu_set_next_event %d\n", cycles);
+ u6_mmtu_timer_start(cycles, 0);
+
+ return 0;
+}
+
+static void u6_mmtu_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+ unsigned long reg;
+
+ debug("mmtu_set_mode %d\n", mode);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_UNUSED:
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_ENA_IDX));
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+
+ reg = readl((mmtu->base + MMTU_TCVAL_IDX));
+ writel(reg - 1, (mmtu->base + MMTU_USED_MATCH_IDX));
+
+#ifndef U6_MMTU_CLOCK_SOURCE
+ u6_mmtu_clk_disable(0);
+
+ if (mmtu->clk != NULL)
+ clk_put(mmtu->clk);
+#endif
+ mmtu->autoreload = 0;
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ mmtu->autoreload = 0;
+
+ if (mmtu->clk == NULL) {
+ mmtu->clk = clk_get(0, "MMTU");
+ if (IS_ERR(mmtu->clk))
+ mmtu->clk = NULL;
+ }
+
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_CLR_STAT_IDX));
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_RESUME:
+ mmtu->autoreload = 0;
+ break;
+ case CLOCK_EVT_MODE_PERIODIC:
+ writel(MMTU_IRQ_MASK,
+ (mmtu->base + MMTU_INT_OFFSET + MMTU_INT_SET_ENA_IDX));
+ mmtu->autoreload = 1;
+ break;
+ }
+}
+
+static void u6_clockevent_init_mmtu(void)
+{
+ printk(PKMOD "clockevent_init_mmtu\n");
+
+ /* prescale 13Mhz -> 1Mhz */
+#ifndef U6_MMTU_CLOCK_SOURCE
+ u6_mmtu_timer_init(0, 0, (MMTU_SYS_FRQ / MMTU_ROOT_FRQ), 0);
+#endif
+
+/* issue it is shorter than reality and generates spurious irq */
+/* clockevent_mmtu.mult = div_sc(MMTU_ROOT_FRQ, NSEC_PER_SEC,
+ * clockevent_mmtu.shift) + 1;*/
+ clockevent_mmtu.mult =
+ div_sc(MMTU_ROOT_FRQ, NSEC_PER_SEC, clockevent_mmtu.shift);
+
+/* clockevent_mmtu.max_delta_ns = div_sc(RELOAD_COUNTER_MMTU,
+ * clockevent_mmtu.mult, clockevent_mmtu.shift);*/
+/* In fact it is wider than the 32bits variable !!! */
+ clockevent_mmtu.max_delta_ns = 0xFFFFFFFF;
+
+/* MMTU HW limitation: match register can't be set w/ tcval+1 */
+/* clockevent_mmtu.min_delta_ns = div_sc(1, clockevent_mmtu.mult,
+ * clockevent_mmtu.shift)+1;*/
+ clockevent_mmtu.min_delta_ns =
+ div_sc(2, clockevent_mmtu.mult, clockevent_mmtu.shift) + 1;
+ /* avoid to much timer interrupt with 10us min between 2 irq */
+ if (clockevent_mmtu.min_delta_ns < 10000)
+ clockevent_mmtu.min_delta_ns = 10000;
+ else if (clockevent_mmtu.max_delta_ns < 10000)
+ clockevent_mmtu.min_delta_ns = clockevent_mmtu.max_delta_ns>>1;
+
+ clockevent_mmtu.cpumask = get_cpu_mask(0);
+ clockevents_register_device(&clockevent_mmtu);
+
+ u6_mmtu_set_next_event(MMTU_ROOT_FRQ / HZ, &clockevent_mmtu);
+}
+
+/*** MMTU Clock source device ***/
+#ifdef U6_MMTU_CLOCK_SOURCE
+
+static cycle_t u6_mmtu_read(struct clocksource *source)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+
+ return readl((mmtu->base + MMTU_TCVAL_IDX)) & source->mask;
+}
+
+static void u6_clocksource_init_mmtu(void)
+{
+ printk(PKMOD "clocksource_init_mmtu\n");
+
+ if (MMTU_ROOT_FRQ >= 1000000)
+ clocksource_mmtu.mult =
+ clocksource_khz2mult((MMTU_ROOT_FRQ / 1000),
+ clocksource_mmtu.shift);
+ else
+ clocksource_mmtu.mult = clocksource_hz2mult((MMTU_ROOT_FRQ),
+ clocksource_mmtu.shift);
+
+ u6_mmtu_timer_init(0, 0, (MMTU_SYS_FRQ / MMTU_ROOT_FRQ), 0);
+
+ clocksource_register(&clocksource_mmtu);
+}
+
+unsigned long long u6_mmtu_time(void)
+{
+ unsigned long long ticks64 = u6_mmtu_read(&clocksource_mmtu);
+
+ return (ticks64 * clocksource_mmtu.mult) >> clocksource_mmtu.shift;
+}
+#endif
+
+/*** SysFs interface ***/
+/***********************/
+#ifdef CONFIG_U6_POWER_SYSFS
+
+/*** Clock event sysfs interface **/
+
+#define shows_one_evt(file_name, object) \
+static ssize_t show_##file_name##_evt \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%s\n", clockevent_mmtu.object); \
+}
+
+#define showu_one_evt(file_name, object) \
+static ssize_t show_##file_name##_evt \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%u\n", clockevent_mmtu.object); \
+}
+
+#define showlu_one_evt(file_name, object) \
+static ssize_t show_##file_name##_evt \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%lu\n", clockevent_mmtu.object); \
+}
+
+#define storelu_one_evt(file_name, object) \
+static ssize_t store_##file_name##_evt \
+(struct kobject *kobj, const char *buf, size_t size) \
+{ \
+ unsigned long object; \
+ strict_strtoul(buf, 10, &object); \
+ clockevent_mmtu.object = object; \
+ return size; \
+}
+
+#define showx_one_evt(file_name, object) \
+static ssize_t show_##file_name##_evt \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "0x%x\n", clockevent_mmtu.object); \
+}
+
+shows_one_evt(name, name);
+showu_one_evt(rating, rating);
+showlu_one_evt(mult, mult);
+#ifdef CONFIG_U6_TIMER_TUNE
+storelu_one_evt(mult, mult);
+#endif
+showu_one_evt(shift, shift);
+showx_one_evt(features, features);
+showlu_one_evt(min_delta_ns, min_delta_ns);
+showlu_one_evt(max_delta_ns, max_delta_ns);
+
+static ssize_t show_clock_mode_evt(struct kobject *kobj, char *buf)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+
+ return sprintf(buf, "%u\n", mmtu->mode);
+}
+
+static ssize_t show_periodic_evt(struct kobject *kobj, char *buf)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+
+ return sprintf(buf, "%u\n", mmtu->autoreload);
+}
+
+static ssize_t show_next_event_evt(struct kobject *kobj, char *buf)
+{
+ struct mmtu_ctxt *mmtu = u6_mmtu_get_context(0);
+ uint8_t enable;
+
+ enable = readb((mmtu->base + MMTU_INT_OFFSET + MMTU_INT_ENABLE_IDX));
+
+ if (enable & 0x1)
+ return sprintf(buf, "%lu\n", (unsigned long)mmtu->endvalue);
+ else
+ return sprintf(buf, "No Event Set\n");
+}
+
+define_one_ro_ext(name, _evt);
+define_one_ro_ext(rating, _evt);
+#ifdef CONFIG_U6_TIMER_TUNE
+define_one_rw_ext(mult, _evt);
+#else
+define_one_ro_ext(mult, _evt);
+#endif
+define_one_ro_ext(shift, _evt);
+define_one_ro_ext(features, _evt);
+define_one_ro_ext(min_delta_ns, _evt);
+define_one_ro_ext(max_delta_ns, _evt);
+define_one_ro_ext(clock_mode, _evt);
+define_one_ro_ext(periodic, _evt);
+define_one_ro_ext(next_event, _evt);
+
+static struct attribute *dbs_attributes_event[] = {
+ &name_evt.attr,
+ &rating_evt.attr,
+ &mult_evt.attr,
+ &shift_evt.attr,
+ &features_evt.attr,
+ &min_delta_ns_evt.attr,
+ &max_delta_ns_evt.attr,
+ &clock_mode_evt.attr,
+ &periodic_evt.attr,
+ &next_event_evt.attr,
+ NULL
+};
+
+static struct attribute_group dbs_attr_event_group = {
+ .attrs = dbs_attributes_event,
+ .name = "mmtu_event",
+};
+
+/*** Clock source sysfs interface ***/
+#ifdef U6_MMTU_CLOCK_SOURCE
+
+#define shows_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%s\n", clocksource_mmtu.object); \
+}
+
+#define showu_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%u\n", clocksource_mmtu.object); \
+}
+
+#define showlu_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "%lu\n", clocksource_mmtu.object); \
+}
+
+#define showlx_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "0x%lx\n", clocksource_mmtu.object); \
+}
+
+#define showllx_one_src(file_name, object) \
+static ssize_t show_##file_name##_src \
+(struct kobject *kobj, char *buf) \
+{ \
+ return sprintf(buf, "0x%llx\n", clocksource_mmtu.object); \
+}
+
+shows_one_src(name, name);
+showu_one_src(rating, rating);
+showu_one_src(mult, mult);
+showu_one_src(shift, shift);
+showllx_one_src(mask, mask);
+showlx_one_src(flags, flags);
+
+static ssize_t show_stamp_src(struct kobject *kobj, char *buf)
+{
+ return sprintf(buf, "%lu\n",
+ (unsigned long)(u6_mmtu_read(&clocksource_mmtu)));
+}
+
+static ssize_t show_time_src(struct kobject *kobj, char *buf)
+{
+ return sprintf(buf, "%llu\n", u6_mmtu_time());
+}
+
+define_one_ro_ext(name, _src);
+define_one_ro_ext(rating, _src);
+define_one_ro_ext(mult, _src);
+define_one_ro_ext(shift, _src);
+define_one_ro_ext(mask, _src);
+define_one_ro_ext(flags, _src);
+define_one_ro_ext(stamp, _src);
+define_one_ro_ext(time, _src);
+
+static struct attribute *dbs_attributes_srce[] = {
+ &name_src.attr,
+ &rating_src.attr,
+ &mult_src.attr,
+ &shift_src.attr,
+ &mask_src.attr,
+ &flags_src.attr,
+ &stamp_src.attr,
+ &time_src.attr,
+ NULL
+};
+
+static struct attribute_group dbs_attr_srce_group = {
+ .attrs = dbs_attributes_srce,
+ .name = "mmtu_source",
+};
+#endif
+#endif
+
+/*** System timer init ***/
+/*************************/
+
+void __init u6_timer_init(void)
+{
+ printk(PKMOD "mmtu_timer_init\n");
+
+#ifdef U6_MMTU_CLOCK_SOURCE
+ u6_clocksource_init_mmtu();
+#endif
+
+ u6_clockevent_init_mmtu();
+
+}
+
+struct sys_timer u6_timer = {
+ .init = u6_timer_init,
+#ifndef CONFIG_GENERIC_TIME
+ .offset = NULL,
+#endif
+};
+
+#ifdef CONFIG_U6_POWER_SYSFS
+static int __init u6_mmtu_init_sysfs(void)
+{
+ printk(PKMOD "mmtu_init_sysfs\n");
+
+#ifdef U6_MMTU_CLOCK_SOURCE
+ if (sysfs_create_group(&u6_power_kobj, &dbs_attr_srce_group))
+ printk(PKMOD "Unable to register %s in sysfs\n",
+ dbs_attr_srce_group.name);
+#endif
+
+ if (sysfs_create_group(&u6_power_kobj, &dbs_attr_event_group))
+ printk(PKMOD "Unable to register %s in sysfs\n",
+ dbs_attr_event_group.name);
+
+ return 0;
+}
+
+module_init(u6_mmtu_init_sysfs);
+#endif
--
1.7.1
More information about the linux-arm-kernel
mailing list