[ARM] 4303/3: base kernel support for TI DaVinci

Add base kernel support for the TI DaVinci platform.

This patch only includes interrupts, timers, CPU identification,
serial support and basic power and sleep controller init.  More
drivers to come.

Signed-off-by: Kevin Hilman <khilman@mvista.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
new file mode 100644
index 0000000..bac988e
--- /dev/null
+++ b/arch/arm/mach-davinci/Kconfig
@@ -0,0 +1,23 @@
+if ARCH_DAVINCI
+
+menu "TI DaVinci Implementations"
+
+comment "DaVinci Core Type"
+
+config ARCH_DAVINCI644x
+	default y
+	bool "DaVinci 644x based system"
+
+comment "DaVinci Board Type"
+
+config MACH_DAVINCI_EVM
+	bool "TI DaVinci EVM"
+	default y
+	depends on ARCH_DAVINCI644x
+	help
+	  Configure this option to specify the whether the board used
+	  for development is a DaVinci EVM
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
new file mode 100644
index 0000000..a8f88cd
--- /dev/null
+++ b/arch/arm/mach-davinci/Makefile
@@ -0,0 +1,10 @@
+#
+# Makefile for the linux kernel.
+#
+#
+
+# Common objects
+obj-y 			:= time.o irq.o serial.o io.o id.o psc.o
+
+# Board specific
+obj-$(CONFIG_MACH_DAVINCI_EVM)  += board-evm.o
diff --git a/arch/arm/mach-davinci/Makefile.boot b/arch/arm/mach-davinci/Makefile.boot
new file mode 100644
index 0000000..e1dd366
--- /dev/null
+++ b/arch/arm/mach-davinci/Makefile.boot
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x80008000
+params_phys-y	:= 0x80000100
+initrd_phys-y	:= 0x80800000
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c
new file mode 100644
index 0000000..633c12e
--- /dev/null
+++ b/arch/arm/mach-davinci/board-evm.c
@@ -0,0 +1,131 @@
+/*
+ * TI DaVinci EVM board support
+ *
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+
+#include <asm/setup.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <asm/arch/common.h>
+
+/* other misc. init functions */
+void __init davinci_psc_init(void);
+void __init davinci_irq_init(void);
+void __init davinci_map_common_io(void);
+
+/* NOR Flash base address set to CS0 by default */
+#define NOR_FLASH_PHYS 0x02000000
+
+static struct mtd_partition davinci_evm_partitions[] = {
+	/* bootloader (U-Boot, etc) in first 4 sectors */
+	{
+		.name		= "bootloader",
+		.offset		= 0,
+		.size		= 4 * SZ_64K,
+		.mask_flags	= MTD_WRITEABLE, /* force read-only */
+	},
+	/* bootloader params in the next 1 sectors */
+	{
+		.name		= "params",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_64K,
+		.mask_flags	= 0,
+	},
+	/* kernel */
+	{
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_2M,
+		.mask_flags	= 0
+	},
+	/* file system */
+	{
+		.name		= "filesystem",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+		.mask_flags	= 0
+	}
+};
+
+static struct physmap_flash_data davinci_evm_flash_data = {
+	.width		= 2,
+	.parts		= davinci_evm_partitions,
+	.nr_parts	= ARRAY_SIZE(davinci_evm_partitions),
+};
+
+/* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF
+ * limits addresses to 16M, so using addresses past 16M will wrap */
+static struct resource davinci_evm_flash_resource = {
+	.start		= NOR_FLASH_PHYS,
+	.end		= NOR_FLASH_PHYS + SZ_16M - 1,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device davinci_evm_flash_device = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &davinci_evm_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &davinci_evm_flash_resource,
+};
+
+static struct platform_device *davinci_evm_devices[] __initdata = {
+	&davinci_evm_flash_device,
+};
+
+static void __init
+davinci_evm_map_io(void)
+{
+	davinci_map_common_io();
+}
+
+static __init void davinci_evm_init(void)
+{
+	davinci_psc_init();
+
+#if defined(CONFIG_BLK_DEV_DAVINCI) || defined(CONFIG_BLK_DEV_DAVINCI_MODULE)
+	printk(KERN_WARNING "WARNING: both IDE and NOR flash are enabled, "
+	       "but share pins.\n\t Disable IDE for NOR support.\n");
+#endif
+
+	platform_add_devices(davinci_evm_devices,
+			     ARRAY_SIZE(davinci_evm_devices));
+}
+
+static __init void davinci_evm_irq_init(void)
+{
+	davinci_irq_init();
+}
+
+MACHINE_START(DAVINCI_EVM, "DaVinci EVM")
+	/* Maintainer: MontaVista Software <source@mvista.com> */
+	.phys_io      = IO_PHYS,
+	.io_pg_offst  = (io_p2v(IO_PHYS) >> 18) & 0xfffc,
+	.boot_params  = (DAVINCI_DDR_BASE + 0x100),
+	.map_io	      = davinci_evm_map_io,
+	.init_irq     = davinci_evm_irq_init,
+	.timer	      = &davinci_timer,
+	.init_machine = davinci_evm_init,
+MACHINE_END
diff --git a/arch/arm/mach-davinci/id.c b/arch/arm/mach-davinci/id.c
new file mode 100644
index 0000000..70608f7
--- /dev/null
+++ b/arch/arm/mach-davinci/id.c
@@ -0,0 +1,94 @@
+/*
+ * Davinci CPU identification code
+ *
+ * Copyright (C) 2006 Komal Shah <komal_shah802003@yahoo.com>
+ *
+ * Derived from OMAP1 CPU identification code.
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+
+#define JTAG_ID_BASE		0x01c40028
+
+struct davinci_id {
+	u8	variant;	/* JTAG ID bits 31:28 */
+	u16	part_no;	/* JTAG ID bits 27:12 */
+	u32	manufacturer;	/* JTAG ID bits 11:1 */
+	u32	type;		/* Cpu id bits [31:8], cpu class bits [7:0] */
+};
+
+/* Register values to detect the DaVinci version */
+static struct davinci_id davinci_ids[] __initdata = {
+	{
+		/* DM6446 */
+		.part_no      = 0xb700,
+		.variant      = 0x0,
+		.manufacturer = 0x017,
+		.type	      = 0x64460000,
+	},
+};
+
+/*
+ * Get Device Part No. from JTAG ID register
+ */
+static u16 __init davinci_get_part_no(void)
+{
+	u32 dev_id, part_no;
+
+	dev_id = davinci_readl(JTAG_ID_BASE);
+
+	part_no = ((dev_id >> 12) & 0xffff);
+
+	return part_no;
+}
+
+/*
+ * Get Device Revision from JTAG ID register
+ */
+static u8 __init davinci_get_variant(void)
+{
+	u32 variant;
+
+	variant = davinci_readl(JTAG_ID_BASE);
+
+	variant = (variant >> 28) & 0xf;
+
+	return variant;
+}
+
+void __init davinci_check_revision(void)
+{
+	int i;
+	u16 part_no;
+	u8 variant;
+
+	part_no = davinci_get_part_no();
+	variant = davinci_get_variant();
+
+	/* First check only the major version in a safe way */
+	for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
+		if (part_no == (davinci_ids[i].part_no)) {
+			system_rev = davinci_ids[i].type;
+			break;
+		}
+	}
+
+	/* Check if we can find the dev revision */
+	for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
+		if (part_no == davinci_ids[i].part_no &&
+		    variant == davinci_ids[i].variant) {
+			system_rev = davinci_ids[i].type;
+			break;
+		}
+	}
+
+	printk("DaVinci DM%04x variant 0x%x\n", system_rev >> 16, variant);
+}
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c
new file mode 100644
index 0000000..87fae6f
--- /dev/null
+++ b/arch/arm/mach-davinci/io.c
@@ -0,0 +1,51 @@
+/*
+ * DaVinci I/O mapping code
+ *
+ * Copyright (C) 2005-2006 Texas Instruments
+ *
+ * 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 <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/tlb.h>
+#include <asm/io.h>
+#include <asm/memory.h>
+
+#include <asm/mach/map.h>
+
+extern void davinci_check_revision(void);
+
+/*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+ */
+static struct map_desc davinci_io_desc[] __initdata = {
+	{
+		.virtual	= IO_VIRT,
+		.pfn		= __phys_to_pfn(IO_PHYS),
+		.length		= IO_SIZE,
+		.type		= MT_DEVICE
+	},
+};
+
+void __init davinci_map_common_io(void)
+{
+	iotable_init(davinci_io_desc, ARRAY_SIZE(davinci_io_desc));
+
+	/* Normally devicemaps_init() would flush caches and tlb after
+	 * mdesc->map_io(), but we must also do it here because of the CPU
+	 * revision check below.
+	 */
+	local_flush_tlb_all();
+	flush_cache_all();
+
+	/* We want to check CPU revision early for cpu_is_xxxx() macros.
+	 * IO space mapping must be initialized before we can do that.
+	 */
+	davinci_check_revision();
+}
diff --git a/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c
new file mode 100644
index 0000000..1333d84
--- /dev/null
+++ b/arch/arm/mach-davinci/irq.c
@@ -0,0 +1,226 @@
+/*
+ * Interrupt handler for DaVinci boards.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach/irq.h>
+
+#define IRQ_BIT(irq)		((irq) & 0x1f)
+
+#define FIQ_REG0_OFFSET		0x0000
+#define FIQ_REG1_OFFSET		0x0004
+#define IRQ_REG0_OFFSET		0x0008
+#define IRQ_REG1_OFFSET		0x000C
+#define IRQ_ENT_REG0_OFFSET	0x0018
+#define IRQ_ENT_REG1_OFFSET	0x001C
+#define IRQ_INCTL_REG_OFFSET	0x0020
+#define IRQ_EABASE_REG_OFFSET	0x0024
+#define IRQ_INTPRI0_REG_OFFSET	0x0030
+#define IRQ_INTPRI7_REG_OFFSET	0x004C
+
+static inline unsigned int davinci_irq_readl(int offset)
+{
+	return davinci_readl(DAVINCI_ARM_INTC_BASE + offset);
+}
+
+static inline void davinci_irq_writel(unsigned long value, int offset)
+{
+	davinci_writel(value, DAVINCI_ARM_INTC_BASE + offset);
+}
+
+/* Disable interrupt */
+static void davinci_mask_irq(unsigned int irq)
+{
+	unsigned int mask;
+	u32 l;
+
+	mask = 1 << IRQ_BIT(irq);
+
+	if (irq > 31) {
+		l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
+		l &= ~mask;
+		davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
+	} else {
+		l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
+		l &= ~mask;
+		davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
+	}
+}
+
+/* Enable interrupt */
+static void davinci_unmask_irq(unsigned int irq)
+{
+	unsigned int mask;
+	u32 l;
+
+	mask = 1 << IRQ_BIT(irq);
+
+	if (irq > 31) {
+		l = davinci_irq_readl(IRQ_ENT_REG1_OFFSET);
+		l |= mask;
+		davinci_irq_writel(l, IRQ_ENT_REG1_OFFSET);
+	} else {
+		l = davinci_irq_readl(IRQ_ENT_REG0_OFFSET);
+		l |= mask;
+		davinci_irq_writel(l, IRQ_ENT_REG0_OFFSET);
+	}
+}
+
+/* EOI interrupt */
+static void davinci_ack_irq(unsigned int irq)
+{
+	unsigned int mask;
+
+	mask = 1 << IRQ_BIT(irq);
+
+	if (irq > 31)
+		davinci_irq_writel(mask, IRQ_REG1_OFFSET);
+	else
+		davinci_irq_writel(mask, IRQ_REG0_OFFSET);
+}
+
+static struct irq_chip davinci_irq_chip_0 = {
+	.name	= "AINTC",
+	.ack	= davinci_ack_irq,
+	.mask	= davinci_mask_irq,
+	.unmask = davinci_unmask_irq,
+};
+
+
+/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
+static const u8 default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
+	[IRQ_VDINT0]		= 2,
+	[IRQ_VDINT1]		= 6,
+	[IRQ_VDINT2]		= 6,
+	[IRQ_HISTINT]		= 6,
+	[IRQ_H3AINT]		= 6,
+	[IRQ_PRVUINT]		= 6,
+	[IRQ_RSZINT]		= 6,
+	[7]			= 7,
+	[IRQ_VENCINT]		= 6,
+	[IRQ_ASQINT]		= 6,
+	[IRQ_IMXINT]		= 6,
+	[IRQ_VLCDINT]		= 6,
+	[IRQ_USBINT]		= 4,
+	[IRQ_EMACINT]		= 4,
+	[14]			= 7,
+	[15]			= 7,
+	[IRQ_CCINT0]		= 5,	/* dma */
+	[IRQ_CCERRINT]		= 5,	/* dma */
+	[IRQ_TCERRINT0]		= 5,	/* dma */
+	[IRQ_TCERRINT]		= 5,	/* dma */
+	[IRQ_PSCIN]		= 7,
+	[21]			= 7,
+	[IRQ_IDE]		= 4,
+	[23]			= 7,
+	[IRQ_MBXINT]		= 7,
+	[IRQ_MBRINT]		= 7,
+	[IRQ_MMCINT]		= 7,
+	[IRQ_SDIOINT]		= 7,
+	[28]			= 7,
+	[IRQ_DDRINT]		= 7,
+	[IRQ_AEMIFINT]		= 7,
+	[IRQ_VLQINT]		= 4,
+	[IRQ_TINT0_TINT12]	= 2,	/* clockevent */
+	[IRQ_TINT0_TINT34]	= 2,	/* clocksource */
+	[IRQ_TINT1_TINT12]	= 7,	/* DSP timer */
+	[IRQ_TINT1_TINT34]	= 7,	/* system tick */
+	[IRQ_PWMINT0]		= 7,
+	[IRQ_PWMINT1]		= 7,
+	[IRQ_PWMINT2]		= 7,
+	[IRQ_I2C]		= 3,
+	[IRQ_UARTINT0]		= 3,
+	[IRQ_UARTINT1]		= 3,
+	[IRQ_UARTINT2]		= 3,
+	[IRQ_SPINT0]		= 3,
+	[IRQ_SPINT1]		= 3,
+	[45]			= 7,
+	[IRQ_DSP2ARM0]		= 4,
+	[IRQ_DSP2ARM1]		= 4,
+	[IRQ_GPIO0]		= 7,
+	[IRQ_GPIO1]		= 7,
+	[IRQ_GPIO2]		= 7,
+	[IRQ_GPIO3]		= 7,
+	[IRQ_GPIO4]		= 7,
+	[IRQ_GPIO5]		= 7,
+	[IRQ_GPIO6]		= 7,
+	[IRQ_GPIO7]		= 7,
+	[IRQ_GPIOBNK0]		= 7,
+	[IRQ_GPIOBNK1]		= 7,
+	[IRQ_GPIOBNK2]		= 7,
+	[IRQ_GPIOBNK3]		= 7,
+	[IRQ_GPIOBNK4]		= 7,
+	[IRQ_COMMTX]		= 7,
+	[IRQ_COMMRX]		= 7,
+	[IRQ_EMUINT]		= 7,
+};
+
+/* ARM Interrupt Controller Initialization */
+void __init davinci_irq_init(void)
+{
+	unsigned i;
+	const u8 *priority = default_priorities;
+
+	/* Clear all interrupt requests */
+	davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
+	davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
+	davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
+	davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
+
+	/* Disable all interrupts */
+	davinci_irq_writel(0x0, IRQ_ENT_REG0_OFFSET);
+	davinci_irq_writel(0x0, IRQ_ENT_REG1_OFFSET);
+
+	/* Interrupts disabled immediately, IRQ entry reflects all */
+	davinci_irq_writel(0x0, IRQ_INCTL_REG_OFFSET);
+
+	/* we don't use the hardware vector table, just its entry addresses */
+	davinci_irq_writel(0, IRQ_EABASE_REG_OFFSET);
+
+	/* Clear all interrupt requests */
+	davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
+	davinci_irq_writel(~0x0, FIQ_REG1_OFFSET);
+	davinci_irq_writel(~0x0, IRQ_REG0_OFFSET);
+	davinci_irq_writel(~0x0, IRQ_REG1_OFFSET);
+
+	for (i = IRQ_INTPRI0_REG_OFFSET; i <= IRQ_INTPRI7_REG_OFFSET; i += 4) {
+		unsigned	j;
+		u32		pri;
+
+		for (j = 0, pri = 0; j < 32; j += 4, priority++)
+			pri |= (*priority & 0x07) << j;
+		davinci_irq_writel(pri, i);
+	}
+
+	/* set up genirq dispatch for ARM INTC */
+	for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
+		set_irq_chip(i, &davinci_irq_chip_0);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+		if (i != IRQ_TINT1_TINT34)
+			set_irq_handler(i, handle_edge_irq);
+		else
+			set_irq_handler(i, handle_level_irq);
+	}
+}
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
new file mode 100644
index 0000000..e1b0050
--- /dev/null
+++ b/arch/arm/mach-davinci/psc.c
@@ -0,0 +1,113 @@
+/*
+ * TI DaVinci Power and Sleep Controller (PSC)
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/psc.h>
+
+#define PTCMD	     __REG(0x01C41120)
+#define PDSTAT	     __REG(0x01C41200)
+#define PDCTL1	     __REG(0x01C41304)
+#define EPCPR	     __REG(0x01C41070)
+#define PTSTAT	     __REG(0x01C41128)
+
+#define MDSTAT	     IO_ADDRESS(0x01C41800)
+#define MDCTL	     IO_ADDRESS(0x01C41A00)
+
+#define PINMUX0	     __REG(0x01c40000)
+#define PINMUX1	     __REG(0x01c40004)
+#define VDD3P3V_PWDN __REG(0x01C40048)
+
+static void davinci_psc_mux(unsigned int id)
+{
+	switch (id) {
+	case DAVINCI_LPSC_ATA:
+		PINMUX0 |= (1 << 17) | (1 << 16);
+		break;
+	case DAVINCI_LPSC_MMC_SD:
+		/* VDD power manupulations are done in U-Boot for CPMAC
+		 * so applies to MMC as well
+		 */
+		/*Set up the pull regiter for MMC */
+		VDD3P3V_PWDN = 0x0;
+		PINMUX1 &= (~(1 << 9));
+		break;
+	case DAVINCI_LPSC_I2C:
+		PINMUX1 |= (1 << 7);
+		break;
+	case DAVINCI_LPSC_McBSP:
+		PINMUX1 |= (1 << 10);
+		break;
+	default:
+		break;
+	}
+}
+
+/* Enable or disable a PSC domain */
+void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
+{
+	volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id);
+	volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id);
+
+	if (id < 0)
+		return;
+
+	if (enable)
+		*mdctl |= 0x00000003;	/* Enable Module */
+	else
+		*mdctl &= 0xFFFFFFF2;	/* Disable Module */
+
+	if ((PDSTAT & 0x00000001) == 0) {
+		PDCTL1 |= 0x1;
+		PTCMD = (1 << domain);
+		while ((((EPCPR >> domain) & 1) == 0));
+
+		PDCTL1 |= 0x100;
+		while (!(((PTSTAT >> domain) & 1) == 0));
+	} else {
+		PTCMD = (1 << domain);
+		while (!(((PTSTAT >> domain) & 1) == 0));
+	}
+
+	if (enable)
+		while (!((*mdstat & 0x0000001F) == 0x3));
+	else
+		while (!((*mdstat & 0x0000001F) == 0x2));
+
+	if (enable)
+		davinci_psc_mux(id);
+}
+
+void __init davinci_psc_init(void)
+{
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1);
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1);
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1);
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1);
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1);
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1);
+
+	/* Turn on WatchDog timer LPSC.	 Needed for RESET to work */
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1);
+}
diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c
new file mode 100644
index 0000000..8368c93
--- /dev/null
+++ b/arch/arm/mach-davinci/serial.c
@@ -0,0 +1,96 @@
+/*
+ * TI DaVinci serial driver
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/serial_8250.h>
+#include <linux/serial_reg.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/arch/serial.h>
+#include <asm/arch/irqs.h>
+
+#define UART_DAVINCI_PWREMU 0x0c
+
+static inline unsigned int davinci_serial_in(struct plat_serial8250_port *up,
+					  int offset)
+{
+	offset <<= up->regshift;
+	return (unsigned int)__raw_readb(up->membase + offset);
+}
+
+static inline void davinci_serial_outp(struct plat_serial8250_port *p,
+				       int offset, int value)
+{
+	offset <<= p->regshift;
+	__raw_writeb(value, p->membase + offset);
+}
+
+static struct plat_serial8250_port serial_platform_data[] = {
+	{
+		.membase	= (char *)IO_ADDRESS(DAVINCI_UART0_BASE),
+		.mapbase	= (unsigned long)DAVINCI_UART0_BASE,
+		.irq		= IRQ_UARTINT0,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 27000000,
+	},
+	{
+		.flags		= 0
+	},
+};
+
+static struct platform_device serial_device = {
+	.name			= "serial8250",
+	.id			= PLAT8250_DEV_PLATFORM,
+	.dev			= {
+		.platform_data	= serial_platform_data,
+	},
+};
+
+static void __init davinci_serial_reset(struct plat_serial8250_port *p)
+{
+	/* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
+	unsigned int pwremu = 0;
+
+	davinci_serial_outp(p, UART_IER, 0);  /* disable all interrupts */
+
+	davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu);
+	mdelay(10);
+
+	pwremu |= (0x3 << 13);
+	pwremu |= 0x1;
+	davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu);
+}
+
+static int __init davinci_init(void)
+{
+	davinci_serial_reset(&serial_platform_data[0]);
+	return platform_device_register(&serial_device);
+}
+
+arch_initcall(davinci_init);
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
new file mode 100644
index 0000000..4d8425d
--- /dev/null
+++ b/arch/arm/mach-davinci/time.c
@@ -0,0 +1,372 @@
+/*
+ * DaVinci timer subsystem
+ *
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. 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 <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/mach/irq.h>
+#include <asm/mach/time.h>
+#include <asm/errno.h>
+#include <asm/arch/io.h>
+
+static struct clock_event_device clockevent_davinci;
+
+#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
+#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
+#define DAVINCI_WDOG_BASE   (IO_PHYS + 0x21C00)
+
+enum {
+	T0_BOT = 0, T0_TOP, T1_BOT, T1_TOP, NUM_TIMERS,
+};
+
+#define IS_TIMER1(id)    (id & 0x2)
+#define IS_TIMER0(id)    (!IS_TIMER1(id))
+#define IS_TIMER_TOP(id) ((id & 0x1))
+#define IS_TIMER_BOT(id) (!IS_TIMER_TOP(id))
+
+static int timer_irqs[NUM_TIMERS] = {
+	IRQ_TINT0_TINT12,
+	IRQ_TINT0_TINT34,
+	IRQ_TINT1_TINT12,
+	IRQ_TINT1_TINT34,
+};
+
+/*
+ * This driver configures the 2 64-bit count-up timers as 4 independent
+ * 32-bit count-up timers used as follows:
+ *
+ * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
+ * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
+ * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
+ * T1_TOP: Timer 1, top   :  <unused>
+ */
+#define TID_CLOCKEVENT  T0_BOT
+#define TID_CLOCKSOURCE T0_TOP
+
+/* Timer register offsets */
+#define PID12                        0x0
+#define TIM12                        0x10
+#define TIM34                        0x14
+#define PRD12                        0x18
+#define PRD34                        0x1c
+#define TCR                          0x20
+#define TGCR                         0x24
+#define WDTCR                        0x28
+
+/* Timer register bitfields */
+#define TCR_ENAMODE_DISABLE          0x0
+#define TCR_ENAMODE_ONESHOT          0x1
+#define TCR_ENAMODE_PERIODIC         0x2
+#define TCR_ENAMODE_MASK             0x3
+
+#define TGCR_TIMMODE_SHIFT           2
+#define TGCR_TIMMODE_64BIT_GP        0x0
+#define TGCR_TIMMODE_32BIT_UNCHAINED 0x1
+#define TGCR_TIMMODE_64BIT_WDOG      0x2
+#define TGCR_TIMMODE_32BIT_CHAINED   0x3
+
+#define TGCR_TIM12RS_SHIFT           0
+#define TGCR_TIM34RS_SHIFT           1
+#define TGCR_RESET                   0x0
+#define TGCR_UNRESET                 0x1
+#define TGCR_RESET_MASK              0x3
+
+#define WDTCR_WDEN_SHIFT             14
+#define WDTCR_WDEN_DISABLE           0x0
+#define WDTCR_WDEN_ENABLE            0x1
+#define WDTCR_WDKEY_SHIFT            16
+#define WDTCR_WDKEY_SEQ0             0xa5c6
+#define WDTCR_WDKEY_SEQ1             0xda7e
+
+struct timer_s {
+	char *name;
+	unsigned int id;
+	unsigned long period;
+	unsigned long opts;
+	unsigned long reg_base;
+	unsigned long tim_reg;
+	unsigned long prd_reg;
+	unsigned long enamode_shift;
+	struct irqaction irqaction;
+};
+static struct timer_s timers[];
+
+/* values for 'opts' field of struct timer_s */
+#define TIMER_OPTS_DISABLED   0x00
+#define TIMER_OPTS_ONESHOT    0x01
+#define TIMER_OPTS_PERIODIC   0x02
+
+static int timer32_config(struct timer_s *t)
+{
+	u32 tcr = davinci_readl(t->reg_base + TCR);
+
+	/* disable timer */
+	tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
+	davinci_writel(tcr, t->reg_base + TCR);
+
+	/* reset counter to zero, set new period */
+	davinci_writel(0, t->tim_reg);
+	davinci_writel(t->period, t->prd_reg);
+
+	/* Set enable mode */
+	if (t->opts & TIMER_OPTS_ONESHOT) {
+		tcr |= TCR_ENAMODE_ONESHOT << t->enamode_shift;
+	} else if (t->opts & TIMER_OPTS_PERIODIC) {
+		tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
+	}
+
+	davinci_writel(tcr, t->reg_base + TCR);
+	return 0;
+}
+
+static inline u32 timer32_read(struct timer_s *t)
+{
+	return davinci_readl(t->tim_reg);
+}
+
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &clockevent_davinci;
+
+	evt->event_handler(evt);
+	return IRQ_HANDLED;
+}
+
+/* called when 32-bit counter wraps */
+static irqreturn_t freerun_interrupt(int irq, void *dev_id)
+{
+	return IRQ_HANDLED;
+}
+
+static struct timer_s timers[] = {
+	[TID_CLOCKEVENT] = {
+		.name      = "clockevent",
+		.opts      = TIMER_OPTS_DISABLED,
+		.irqaction = {
+			.flags   = IRQF_DISABLED | IRQF_TIMER,
+			.handler = timer_interrupt,
+		}
+	},
+	[TID_CLOCKSOURCE] = {
+		.name       = "free-run counter",
+		.period     = ~0,
+		.opts       = TIMER_OPTS_PERIODIC,
+		.irqaction = {
+			.flags   = IRQF_DISABLED | IRQF_TIMER,
+			.handler = freerun_interrupt,
+		}
+	},
+};
+
+static void __init timer_init(void)
+{
+	u32 bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE};
+	int i;
+
+	/* Global init of each 64-bit timer as a whole */
+	for(i=0; i<2; i++) {
+		u32 tgcr, base = bases[i];
+
+		/* Disabled, Internal clock source */
+		davinci_writel(0, base + TCR);
+
+		/* reset both timers, no pre-scaler for timer34 */
+		tgcr = 0;
+		davinci_writel(tgcr, base + TGCR);
+
+		/* Set both timers to unchained 32-bit */
+		tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT;
+		davinci_writel(tgcr, base + TGCR);
+
+		/* Unreset timers */
+		tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
+			(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
+		davinci_writel(tgcr, base + TGCR);
+
+		/* Init both counters to zero */
+		davinci_writel(0, base + TIM12);
+		davinci_writel(0, base + TIM34);
+	}
+
+	/* Init of each timer as a 32-bit timer */
+	for (i=0; i< ARRAY_SIZE(timers); i++) {
+		struct timer_s *t = &timers[i];
+
+		if (t->name) {
+			t->id = i;
+			t->reg_base = (IS_TIMER1(t->id) ?
+			       DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE);
+
+			if (IS_TIMER_BOT(t->id)) {
+				t->enamode_shift = 6;
+				t->tim_reg = t->reg_base + TIM12;
+				t->prd_reg = t->reg_base + PRD12;
+			} else {
+				t->enamode_shift = 22;
+				t->tim_reg = t->reg_base + TIM34;
+				t->prd_reg = t->reg_base + PRD34;
+			}
+
+			/* Register interrupt */
+			t->irqaction.name = t->name;
+			t->irqaction.dev_id = (void *)t;
+			if (t->irqaction.handler != NULL) {
+				setup_irq(timer_irqs[t->id], &t->irqaction);
+			}
+
+			timer32_config(&timers[i]);
+		}
+	}
+}
+
+/*
+ * clocksource
+ */
+static cycle_t read_cycles(void)
+{
+	struct timer_s *t = &timers[TID_CLOCKSOURCE];
+
+	return (cycles_t)timer32_read(t);
+}
+
+static struct clocksource clocksource_davinci = {
+	.name		= "timer0_1",
+	.rating		= 300,
+	.read		= read_cycles,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.shift		= 24,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+/*
+ * clockevent
+ */
+static int davinci_set_next_event(unsigned long cycles,
+				  struct clock_event_device *evt)
+{
+	struct timer_s *t = &timers[TID_CLOCKEVENT];
+
+	t->period = cycles;
+	timer32_config(t);
+	return 0;
+}
+
+static void davinci_set_mode(enum clock_event_mode mode,
+			     struct clock_event_device *evt)
+{
+	struct timer_s *t = &timers[TID_CLOCKEVENT];
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		t->period = CLOCK_TICK_RATE / (HZ);
+		t->opts = TIMER_OPTS_PERIODIC;
+		timer32_config(t);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		t->opts = TIMER_OPTS_ONESHOT;
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		t->opts = TIMER_OPTS_DISABLED;
+		break;
+	}
+}
+
+static struct clock_event_device clockevent_davinci = {
+	.name		= "timer0_0",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.shift		= 32,
+	.set_next_event	= davinci_set_next_event,
+	.set_mode	= davinci_set_mode,
+};
+
+
+static void __init davinci_timer_init(void)
+{
+	static char err[] __initdata = KERN_ERR
+		"%s: can't register clocksource!\n";
+
+	/* init timer hw */
+	timer_init();
+
+	/* setup clocksource */
+	clocksource_davinci.mult =
+		clocksource_khz2mult(CLOCK_TICK_RATE/1000,
+				     clocksource_davinci.shift);
+	if (clocksource_register(&clocksource_davinci))
+		printk(err, clocksource_davinci.name);
+
+	/* setup clockevent */
+	clockevent_davinci.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
+					 clockevent_davinci.shift);
+	clockevent_davinci.max_delta_ns =
+		clockevent_delta2ns(0xfffffffe, &clockevent_davinci);
+	clockevent_davinci.min_delta_ns =
+		clockevent_delta2ns(1, &clockevent_davinci);
+
+	clockevent_davinci.cpumask = cpumask_of_cpu(0);
+	clockevents_register_device(&clockevent_davinci);
+}
+
+struct sys_timer davinci_timer = {
+	.init   = davinci_timer_init,
+};
+
+
+/* reset board using watchdog timer */
+void davinci_watchdog_reset(void) {
+	u32 tgcr, wdtcr, base = DAVINCI_WDOG_BASE;
+
+	/* disable, internal clock source */
+	davinci_writel(0, base + TCR);
+
+	/* reset timer, set mode to 64-bit watchdog, and unreset */
+	tgcr = 0;
+	davinci_writel(tgcr, base + TCR);
+	tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT;
+	tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
+		(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
+	davinci_writel(tgcr, base + TCR);
+
+	/* clear counter and period regs */
+	davinci_writel(0, base + TIM12);
+	davinci_writel(0, base + TIM34);
+	davinci_writel(0, base + PRD12);
+	davinci_writel(0, base + PRD34);
+
+	/* enable */
+	wdtcr = davinci_readl(base + WDTCR);
+	wdtcr |= WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT;
+	davinci_writel(wdtcr, base + WDTCR);
+
+	/* put watchdog in pre-active state */
+	wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
+		(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
+	davinci_writel(wdtcr, base + WDTCR);
+
+	/* put watchdog in active state */
+	wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
+		(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
+	davinci_writel(wdtcr, base + WDTCR);
+
+	/* write an invalid value to the WDKEY field to trigger
+	 * a watchdog reset */
+	wdtcr = 0x00004000;
+	davinci_writel(wdtcr, base + WDTCR);
+}