[PATCH 1/6] U6/U6715 ARM architecture files

Philippe Langlais philippe.langlais at stericsson.com
Wed Apr 28 03:32:51 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                    |   24 +
 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        |  122 +++++
 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, 1894 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 184a6bd..8599afd 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -718,6 +718,13 @@ config ARCH_BCMRING
 	help
 	  Support for Broadcom's BCMRing platform.
 
+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
@@ -830,6 +837,9 @@ endif
 
 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 356d702..f8f3211 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -168,6 +168,7 @@ machine-$(CONFIG_ARCH_SHARK)		:= shark
 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_W90X900)		:= w90x900
@@ -185,6 +186,7 @@ plat-$(CONFIG_PLAT_PXA)		:= pxa
 plat-$(CONFIG_PLAT_S3C24XX)	:= s3c24xx s3c samsung
 plat-$(CONFIG_PLAT_S3C64XX)	:= s3c64xx s3c samsung
 plat-$(CONFIG_PLAT_S5PC1XX)	:= s5pc1xx s3c samsung
+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..c9a8f63
--- /dev/null
+++ b/arch/arm/mach-u67xx/Kconfig
@@ -0,0 +1,24 @@
+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
+
+comment "U67XX Specific configuration"
+	depends on ARCH_U67XX
+
+config MACHINE_NAME
+	prompt "Machine Name"
+	depends on ARCH_U67XX
+	default "STE_U67xx_refd"
+	string
+	help
+		Change the machine name for application framework convenience
+		It will be set in board_u6*.c file
+
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..edfb983
--- /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, CONFIG_MACHINE_NAME)
+	/* 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..63ecd02
--- /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_ADDR  @ physical base address
+		ldrne	\rx, = UART1_BASE       @ virtual base
+		.endm
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx, #UART1_RBR_OFFSET]
+		.endm
+
+		.macro	waituart,rd,rx
+1001:
+		ldr	\rd, [\rx, #UART1_LSR_OFFSET]
+		tst	\rd, #1 << UARTX_THRE_SHIFT	@ LSR_THRE - 0 when full
+		beq	1001b
+		.endm
+
+		.macro	busyuart,rd,rx
+1001:
+		ldr	\rd, [\rx, #UART1_LSR_OFFSET]
+		tst	\rd, #1 << UARTX_TEMT_SHIFT	@ 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..02057d6
--- /dev/null
+++ b/arch/arm/plat-u6xxx/include/mach/scon.h
@@ -0,0 +1,122 @@
+/*
+ * 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.0.4




More information about the linux-arm-kernel mailing list