NetBSD Problem Report #37029

From mfouts@gremlin.danger.com  Wed Sep 26 17:21:33 2007
Return-Path: <mfouts@gremlin.danger.com>
Received: from mail.netbsd.org (mail.netbsd.org [204.152.190.11])
	by narn.NetBSD.org (Postfix) with ESMTP id 22A5A63B8C2
	for <gnats-bugs@gnats.NetBSD.org>; Wed, 26 Sep 2007 17:21:33 +0000 (UTC)
Message-Id: <20070925203325.16E7AFD44@gremlin.danger.com>
Date: Tue, 25 Sep 2007 13:33:25 -0700 (PDT)
From: mfouts@danger.com
Reply-To: mfouts@danger.com
To: gnats-bugs@NetBSD.org
Cc: mfouts@danger.com
Subject: Resubmit of patch for SDP2430/ARM1136/ARMV6-VIPT
X-Send-Pr-Version: 3.95

>Number:         37029
>Category:       port-arm
>Synopsis:       Resubmit of patch for SDP2430/ARM1136/ARMV6-VIPT
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    matt
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Sep 26 17:25:00 +0000 2007
>Closed-Date:    Sat Mar 17 13:06:12 +0000 2012
>Last-Modified:  Sat Mar 17 13:06:12 +0000 2012
>Originator:     Marty Fouts
>Release:        NetBSD 4.0_RC1
>Organization:
Danger Inc
>Environment:
System: NetBSD sdp2430v5 4.0_RC1 NetBSD 4.0_RC1 (SDP2430) #3: Mon Sep 24 09:48:30 PDT 20
07  mfouts@sponge.danger.com:/space/projects/netbsd/netbsd_3am/obj/evbarm/sys/ar
ch/evbarm/compile/SDP2430 evbarm
Architecture: arm
Machine: evbarm
>Description:
	NetBSD does not support the TI SDP2430
>How-To-Repeat:
	try to build a NetBSD kernel for the SDP2430
>Fix:

diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm/ast.c sys/arch/arm/arm/ast.c
--- ../../netbsd_40/src/sys/arch/arm/arm/ast.c	2005-12-11 04:16:41.000000000 -0800
+++ sys/arch/arm/arm/ast.c	2007-09-25 10:55:22.000000000 -0700
@@ -43,6 +43,7 @@
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: ast.c,v 1.7 2005/12/11 12:16:41 christos Exp $");

+#include "opt_cputypes.h"
 #include "opt_ddb.h"

 #include <sys/param.h>
@@ -79,11 +80,17 @@
 void
 userret(struct lwp *l)
 {
+	struct cpu_info * const ci = curcpu();

 	/* Invoke MI userret code */
 	mi_userret(l);

-	curcpu()->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri;
+	ci->ci_schedstate.spc_curpriority = l->l_priority = l->l_usrpri;
+#if defined(CPU_ARM11) || defined(CPU_ARM1136)
+	if (ci->ci_arm_cputype == CPU_ID_ARM1136JS
+	    || ci->ci_arm_cputype == CPU_ID_ARM1136JSR1)
+		__asm("mcr p15, 0, %0, c7, c10, 0" :: "r"(0));
+#endif
 }


diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm/cpufunc.c sys/arch/arm/arm/cpufunc.c
--- ../../netbsd_40/src/sys/arch/arm/arm/cpufunc.c	2007-02-21 10:36:03.000000000 -0800
+++ sys/arch/arm/arm/cpufunc.c	2007-09-25 10:55:22.000000000 -0700
@@ -5,6 +5,7 @@
  * arm8 support code Copyright (c) 1997 ARM Limited
  * arm8 support code Copyright (c) 1997 Causality Limited
  * arm9 support code Copyright (C) 2001 ARM Ltd
+ * arm11 support code Copyright (c) 2007 Danger Inc
  * Copyright (c) 1997 Mark Brinicombe.
  * Copyright (c) 1997 Causality Limited
  * All rights reserved.
@@ -96,6 +97,9 @@
 int	arm_pdcache_size;	/* and unified */
 int	arm_pdcache_line_size;
 int	arm_pdcache_ways;
+#if (ARM_MMU_V6) != 0
+int	arm_cache_prefer_mask;
+#endif

 int	arm_pcache_type;
 int	arm_pcache_unified;
@@ -501,7 +505,7 @@
 	cpufunc_nullop,			/* flush_brnchtgt_C	*/
 	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/

-	(void *)cpufunc_nullop,		/* sleep		*/
+	cpufunc_sleep,			/* sleep		*/

 	/* Soft functions */

@@ -599,16 +603,16 @@

 	/* Cache operations */

-	armv5_icache_sync_all,		/* icache_sync_all	*/
-	armv5_icache_sync_range,	/* icache_sync_range	*/
+	armv6_icache_sync_all,		/* icache_sync_all	*/
+	armv6_icache_sync_range,	/* icache_sync_range	*/

-	armv5_dcache_wbinv_all,		/* dcache_wbinv_all	*/
-	armv5_dcache_wbinv_range,	/* dcache_wbinv_range	*/
-/*XXX*/	armv5_dcache_wbinv_range,	/* dcache_inv_range	*/
-	armv5_dcache_wb_range,		/* dcache_wb_range	*/
+	armv6_dcache_wbinv_all,		/* dcache_wbinv_all	*/
+	armv6_dcache_wbinv_range,	/* dcache_wbinv_range	*/
+	armv6_dcache_inv_range,		/* dcache_inv_range	*/
+	armv6_dcache_wb_range,		/* dcache_wb_range	*/

-	armv5_idcache_wbinv_all,	/* idcache_wbinv_all	*/
-	armv5_idcache_wbinv_range,	/* idcache_wbinv_range	*/
+	armv6_idcache_wbinv_all,	/* idcache_wbinv_all	*/
+	armv6_idcache_wbinv_range,	/* idcache_wbinv_range	*/

 	/* Other functions */

@@ -631,6 +635,64 @@
 };
 #endif /* CPU_ARM11 */

+#ifdef CPU_ARM1136
+struct cpu_functions arm1136_cpufuncs = {
+	/* CPU functions */
+
+	cpufunc_id,			/* id			*/
+	cpufunc_nullop,			/* cpwait		*/
+
+	/* MMU functions */
+
+	cpufunc_control,		/* control		*/
+	cpufunc_domains,		/* Domain		*/
+	arm1136_setttb,			/* Setttb		*//*411920*/
+	cpufunc_faultstatus,		/* Faultstatus		*/
+	cpufunc_faultaddress,		/* Faultaddress		*/
+
+	/* TLB functions */
+
+	arm11_tlb_flushID,		/* tlb_flushID		*/
+	arm11_tlb_flushID_SE,		/* tlb_flushID_SE	*/
+	arm11_tlb_flushI,		/* tlb_flushI		*/
+	arm11_tlb_flushI_SE,		/* tlb_flushI_SE	*/
+	arm11_tlb_flushD,		/* tlb_flushD		*/
+	arm11_tlb_flushD_SE,		/* tlb_flushD_SE	*/
+
+	/* Cache operations */
+
+	arm1136_icache_sync_all,	/* icache_sync_all	*//*411920*/
+	arm1136_icache_sync_range,	/* icache_sync_range	*//*371025*/
+
+	arm1136_dcache_wbinv_all,	/* dcache_wbinv_all	*//*411920*/
+	armv6_dcache_wbinv_range,	/* dcache_wbinv_range	*/
+	armv6_dcache_inv_range,		/* dcache_inv_range	*/
+	armv6_dcache_wb_range,		/* dcache_wb_range	*/
+
+	arm1136_idcache_wbinv_all,	/* idcache_wbinv_all	*//*411920*/
+	arm1136_idcache_wbinv_range,	/* idcache_wbinv_range	*//*371025*/
+
+	/* Other functions */
+
+	arm1136_flush_prefetchbuf,	/* flush_prefetchbuf	*/
+	arm11_drain_writebuf,		/* drain_writebuf	*/
+	cpufunc_nullop,			/* flush_brnchtgt_C	*/
+	(void *)cpufunc_nullop,		/* flush_brnchtgt_E	*/
+
+	(void *)cpufunc_nullop,		/* sleep		*/
+
+	/* Soft functions */
+
+	cpufunc_null_fixup,		/* dataabt_fixup	*/
+	cpufunc_null_fixup,		/* prefetchabt_fixup	*/
+
+	arm11_context_switch,		/* context_switch	*/
+
+	arm1136_setup			/* cpu setup		*/
+
+};
+#endif /* CPU_ARM1136 */
+
 #ifdef CPU_SA110
 struct cpu_functions sa110_cpufuncs = {
 	/* CPU functions */
@@ -872,7 +934,9 @@
 #if defined(CPU_ARM7TDMI) || defined(CPU_ARM8) || defined(CPU_ARM9) || \
     defined (CPU_ARM9E) || defined (CPU_ARM10) || defined (CPU_ARM11) || \
     defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
-    defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425)
+    defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425) || \
+    defined(CPU_ARM1136)
+
 static void get_cachetype_cp15 __P((void));

 /* Additional cache information local to this file.  Log2 of some of the
@@ -921,6 +985,13 @@
 		} else {
 			arm_picache_ways = multiplier <<
 			    (CPU_CT_xSIZE_ASSOC(isize) - 1);
+#if (ARM_MMU_V6) != 0
+			if (CPU_CT_xSIZE_P & isize)
+				arm_cache_prefer_mask |=
+				    __BIT(9 + CPU_CT_xSIZE_SIZE(isize)
+					  - CPU_CT_xSIZE_ASSOC(isize))
+				    - PAGE_SIZE;
+#endif
 		}
 		arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
 	}
@@ -936,6 +1007,13 @@
 	} else {
 		arm_pdcache_ways = multiplier <<
 		    (CPU_CT_xSIZE_ASSOC(dsize) - 1);
+#if (ARM_MMU_V6) != 0
+		if (CPU_CT_xSIZE_P & dsize)
+			arm_cache_prefer_mask |=
+			    __BIT(9 + CPU_CT_xSIZE_SIZE(dsize)
+				  - CPU_CT_xSIZE_ASSOC(dsize))
+			    - PAGE_SIZE;
+#endif
 	}
 	arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);

@@ -1108,6 +1186,7 @@
 		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
 		get_cachetype_cp15();
 		pmap_pte_init_generic();
+
 		return 0;
 	}
 #endif /* CPU_ARM9E || CPU_ARM10 */
@@ -1137,16 +1216,24 @@
 		cpufuncs = arm11_cpufuncs;
 		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
 		get_cachetype_cp15();
-		armv5_dcache_sets_inc = 1U << arm_dcache_l2_linesize;
-		armv5_dcache_sets_max = 
-		    (1U << (arm_dcache_l2_linesize + arm_dcache_l2_nsets)) -
-		    armv5_dcache_sets_inc;
-		armv5_dcache_index_inc = 1U << (32 - arm_dcache_l2_assoc);
-		armv5_dcache_index_max = 0U - armv5_dcache_index_inc;
 		pmap_pte_init_generic();
+		if (arm_cache_prefer_mask)
+			uvmexp.ncolors = (arm_cache_prefer_mask >> PGSHIFT) + 1;
 		return 0;
 	}
 #endif /* CPU_ARM11 */
+#ifdef CPU_ARM1136
+	if (cputype == CPU_ID_ARM1136JS ||
+	    cputype == CPU_ID_ARM1136JSR1) {
+		cpufuncs = arm1136_cpufuncs;
+		cpu_reset_needs_v4_MMU_disable = 1;	/* V4 or higher */
+		get_cachetype_cp15();
+		pmap_pte_init_generic();
+		if (arm_cache_prefer_mask)
+			uvmexp.ncolors = (arm_cache_prefer_mask >> PGSHIFT) + 1;
+		return 0;
+	}
+#endif /* CPU_ARM1136 */
 #ifdef CPU_SA110
 	if (cputype == CPU_ID_SA110) {
 		cpufuncs = sa110_cpufuncs;
@@ -1687,7 +1774,7 @@
 	defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \
 	defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
 	defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425) || \
-	defined(CPU_ARM10) || defined(CPU_ARM11)
+	defined(CPU_ARM10) || defined(CPU_ARM11) || defined(CPU_ARM1136)

 #define IGN	0
 #define OR	1
@@ -2082,7 +2169,7 @@
 }
 #endif	/* CPU_ARM9E || CPU_ARM10 */

-#ifdef CPU_ARM11
+#if defined(CPU_ARM11)
 struct cpu_option arm11_options[] = {
 	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
 	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
@@ -2117,6 +2204,9 @@
 	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
 #endif

+	if (vector_page == ARM_VECTORS_HIGH)
+		cpuctrl |= CPU_CONTROL_VECRELOC;
+
 	/* Clear out the cache */
 	cpu_idcache_wbinv_all();

@@ -2132,6 +2222,74 @@
 }
 #endif	/* CPU_ARM11 */

+#if defined(CPU_ARM1136)
+struct cpu_option arm11_options[] = {
+	{ "cpu.cache",		BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+	{ "cpu.nocache",	OR,  BIC, (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+	{ "arm1136.cache",	BIC, OR,  (CPU_CONTROL_IC_ENABLE | CPU_CONTROL_DC_ENABLE) },
+	{ "arm1136.icache",	BIC, OR,  CPU_CONTROL_IC_ENABLE },
+	{ "arm1136.dcache",	BIC, OR,  CPU_CONTROL_DC_ENABLE },
+	{ "arm1136.writebuf",	BIC, OR,  CPU_CONTROL_WBUF_ENABLE },
+	{ NULL,			IGN, IGN, 0 }
+};
+
+void
+arm1136_setup(args)
+	char *args;
+{
+	int cpuctrl, cpuctrl_wax;
+	uint32_t sbz=0;
+
+	cpuctrl =
+		CPU_CONTROL_MMU_ENABLE  |
+		CPU_CONTROL_DC_ENABLE   |
+		CPU_CONTROL_WBUF_ENABLE |
+		CPU_CONTROL_32BP_ENABLE |
+		CPU_CONTROL_32BD_ENABLE |
+		CPU_CONTROL_LABT_ENABLE |
+		CPU_CONTROL_SYST_ENABLE |
+		CPU_CONTROL_IC_ENABLE;
+
+	/*
+	 * "write as existing" bits
+	 * inverse of this is mask
+	 */
+	cpuctrl_wax =
+		(3 << 30) |
+		(1 << 29) |
+		(1 << 28) |
+		(3 << 26) |
+		(7 << 19) |	/* make sure we save bit 21 */
+		(1 << 17);
+
+#ifndef ARM32_DISABLE_ALIGNMENT_FAULTS
+	cpuctrl |= CPU_CONTROL_AFLT_ENABLE;
+#endif
+
+	cpuctrl = parse_cpu_options(args, arm11_options, cpuctrl);
+
+#ifdef __ARMEB__
+	cpuctrl |= CPU_CONTROL_BEND_ENABLE;
+#endif
+
+	if (vector_page == ARM_VECTORS_HIGH)
+		cpuctrl |= CPU_CONTROL_VECRELOC;
+
+	/* Clear out the cache */
+	cpu_idcache_wbinv_all();
+
+	/* Now really make sure they are clean.  */
+	__asm volatile ("mcr\tp15, 0, %0, c7, c7, 0" : : "r"(sbz));
+
+	/* Set the control register */
+	curcpu()->ci_ctrl = cpuctrl;
+	cpu_control(~cpuctrl_wax, cpuctrl);
+
+	/* And again. */
+	cpu_idcache_wbinv_all();
+}
+#endif	/* CPU_ARM1136 */
+
 #ifdef CPU_SA110
 struct cpu_option sa110_options[] = {
 #ifdef COMPAT_12
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm/cpufunc_asm_arm11.S sys/arch/arm/arm/cpufunc_asm_arm11.S
--- ../../netbsd_40/src/sys/arch/arm/arm/cpufunc_asm_arm11.S	2005-12-11 04:16:41.000000000 -0800
+++ sys/arch/arm/arm/cpufunc_asm_arm11.S	2007-09-25 10:55:22.000000000 -0700
@@ -45,7 +45,7 @@
  */
 ENTRY(arm11_setttb)
 	stmfd	sp!, {r0, lr}
-	bl	_C_LABEL(armv5_idcache_wbinv_all)
+	bl	_C_LABEL(armv6_idcache_wbinv_all)
 	ldmfd	sp!, {r0, lr}

 	mcr	p15, 0, r0, c2, c0, 0	/* load new TTB */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm/cpufunc_asm_arm1136.S sys/arch/arm/arm/cpufunc_asm_arm1136.S
--- ../../netbsd_40/src/sys/arch/arm/arm/cpufunc_asm_arm1136.S	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/arm/cpufunc_asm_arm1136.S	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,149 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <machine/cpu.h>
+#include <machine/asm.h>
+
+RCSID("$NetBSD$")
+
+/*
+ * Workaround Erratum 411920 
+ * 
+ *	- value of arg 'reg' Should Be Zero
+ */
+#define Invalidate_I_cache(Rtmp1, Rtmp2) \
+	mov	Rtmp1, #0		/* SBZ */			;\
+	mrs	Rtmp2, cpsr						;\
+	cpsid	ifa							;\
+	mcr	p15, 0, Rtmp1, c7, c5, 0 /* Invalidate Entire I cache */;\
+	mcr	p15, 0, Rtmp1, c7, c5, 0 /* Invalidate Entire I cache */;\
+	mcr	p15, 0, Rtmp1, c7, c5, 0 /* Invalidate Entire I cache */;\
+	mcr	p15, 0, Rtmp1, c7, c5, 0 /* Invalidate Entire I cache */;\
+	msr	cpsr_cx, Rtmp2						;\
+	nop								;\
+	nop								;\
+	nop								;\
+	nop								;\
+	nop								;\
+	nop								;\
+	nop								;\
+	nop								;\
+	nop								;\
+	nop								;\
+	nop
+
+#define Flush_D_cache(reg) \
+	mov	reg, #0;		/* SBZ */					\
+	mcr	p15, 0, reg, c7, c14, 0;/* Clean and Invalidate Entire Data Cache */	\
+	mcr	p15, 0, reg, c7, c10, 4;/* Data Synchronization Barrier */
+
+ENTRY(arm1136_setttb)
+#ifdef PMAP_CACHE_VIVT
+	Flush_D_cache(r1)
+#endif
+#ifdef PMAP_CACHE_VIVT
+	Invalidate_I_cache(r1, r2)
+#endif
+	mcr	p15, 0, r0, c2, c0, 0	/* load new TTB */
+	mcr	p15, 0, r1, c8, c7, 0	/* invalidate I+D TLBs */
+	mcr	p15, 0, r1, c7, c10, 4	/* drain write buffer */
+	RET
+
+ENTRY_NP(arm1136_idcache_wbinv_all)
+	Flush_D_cache(r0)
+	Invalidate_I_cache(r0, r1)
+	RET
+
+ENTRY_NP(arm1136_dcache_wbinv_all)
+	Flush_D_cache(r0)
+	RET
+
+ENTRY_NP(arm1136_icache_sync_all)
+	mov	r0, #0			/* SBZ */				
+	mcr	p15, 0, r0, c7, c10, 0	/* Clean Entire Data Cache */
+	mcr	p15, 0, r0, c7, c10, 4	/* Data Synchronization Barrier */
+	Invalidate_I_cache(r0, r1)
+	RET
+
+ENTRY_NP(arm1136_flush_prefetchbuf)
+	mcr	p15, 0, r0, c7, c5, 4	/* Flush Prefetch Buffer */
+	RET
+
+ENTRY_NP(arm1136_icache_sync_range)
+	add	r1, r1, r0
+	sub	r1, r1, #1
+	/* Erratum 371025, workaround #2 */
+	mrs	r2, cpsr		/* save the CPSR */
+	cpsid	ifa			/* disable interrupts (irq,fiq,abort) */
+	mov	r3, #0 
+	mcr	p15, 0, r3, c13, c0, 0	/* write FCSE (uTLB invalidate) */
+	mcr	p15, 0, r3, c7, c5, 4	/* flush prefetch buffer */
+	add	r3, pc, #0x24 
+	mcr	p15, 0, r3, c7, c13, 1	/* prefetch I-cache line */
+	mcrr	p15, 0, r1, r0, c5	/* invalidate I-cache range */
+	msr	cpsr_cx, r2		/* local_irq_restore */
+	nop 
+	nop 
+	nop 
+	nop 
+	nop 
+	nop 
+	nop 
+
+	mcrr	p15, 0, r1, r0, c12	/* clean and invalidate D cache range */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+	RET
+
+ENTRY_NP(arm1136_idcache_wbinv_range)
+	add	r1, r1, r0
+	sub	r1, r1, #1
+	/* Erratum 371025, workaround #2 */
+	mrs	r2, cpsr		/* save the CPSR */
+	cpsid	ifa			/* disable interrupts (irq,fiq,abort) */
+	mov	r3, #0 
+	mcr	p15, 0, r3, c13, c0, 0	/* write FCSE (uTLB invalidate) */
+	mcr	p15, 0, r3, c7, c5, 4	/* flush prefetch buffer */
+	add	r3, pc, #0x24 
+	mcr	p15, 0, r3, c7, c13, 1	/* prefetch I-cache line */
+	mcrr	p15, 0, r1, r0, c5	/* invalidate I-cache range */
+	msr	cpsr_cx, r2		/* local_irq_restore */
+	nop 
+	nop 
+	nop 
+	nop 
+	nop 
+	nop 
+	nop 
+
+	mcrr	p15, 0, r1, r0, c14	/* clean and invalidate D cache range */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+	RET
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm/cpufunc_asm_armv6.S sys/arch/arm/arm/cpufunc_asm_armv6.S
--- ../../netbsd_40/src/sys/arch/arm/arm/cpufunc_asm_armv6.S	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/arm/cpufunc_asm_armv6.S	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,133 @@
+/*	$NetBSD: cpufunc_asm_armv6.S,v 1.3 2007/01/06 00:50:54 christos Exp $	*/
+
+/*
+ * Copyright (c) 2002, 2005 ARM Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * ARMv6 assembly functions for manipulating caches.
+ * These routines can be used by any core that supports the mcrr address
+ * range operations.
+ * Portions Copyright (c) 2007 Danger Inc
+ */
+ 
+#include <machine/cpu.h>
+#include <machine/asm.h>
+
+/*
+ * Functions to set the MMU Translation Table Base register
+ *
+ * We need to clean and flush the cache as it uses virtual
+ * addresses that are about to change.
+ */
+ENTRY(armv6_setttb)
+	mcr	p15, 0, r0, c7, c5, 0	/* Flush I cache */
+	mcr	p15, 0, r0, c7, c14, 0	/* clean and invalidate D cache */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+
+	mcr	p15, 0, r0, c2, c0, 0	/* load new TTB */
+
+	mcr	p15, 0, r0, c8, c7, 0	/* invalidate I+D TLBs */
+	RET
+
+/*
+ * Cache operations.
+ */
+
+/* LINTSTUB: void armv6_icache_sync_range(vaddr_t, vsize_t); */
+ENTRY_NP(armv6_icache_sync_range)
+	add	r1, r1, r0
+	sub	r1, r1, #1
+	mcrr	p15, 0, r1, r0, c5	/* invalidate I cache range */
+	mcrr	p15, 0, r1, r0, c12	/* clean D cache range */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+	RET
+
+/* LINTSTUB: void armv6_icache_sync_all(void); */
+ENTRY_NP(armv6_icache_sync_all)
+	/*
+	 * We assume that the code here can never be out of sync with the
+	 * dcache, so that we can safely flush the Icache and fall through
+	 * into the Dcache cleaning code.
+	 */
+	mcr	p15, 0, r0, c7, c5, 0	/* Flush I cache */
+	mcr	p15, 0, r0, c7, c10, 0	/* Clean D cache */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+	RET
+
+/* LINTSTUB: void armv6_icache_sync_range(vaddr_t, vsize_t); */
+ENTRY(armv6_dcache_wb_range)
+	add	r1, r1, r0
+	sub	r1, r1, #1
+	mcrr	p15, 0, r1, r0, c12	/* clean D cache range */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+	RET
+	
+/* LINTSTUB: void armv6_dcache_wbinv_range(vaddr_t, vsize_t); */
+ENTRY(armv6_dcache_wbinv_range)
+	add	r1, r1, r0
+	sub	r1, r1, #1
+	mcrr	p15, 0, r1, r0, c14	/* clean and invaliate D cache range */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+	RET
+	
+/*
+ * Note, we must not invalidate everything.  If the range is too big we
+ * must use wb-inv of the entire cache.
+ *
+ * LINTSTUB: void armv6_dcache_inv_range(vaddr_t, vsize_t);
+ */
+ENTRY(armv6_dcache_inv_range)
+	add	r1, r1, r0
+	sub	r1, r1, #1
+	mcrr	p15, 0, r1, r0, c6	/* invaliate D cache range */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+	RET
+
+/* LINTSTUB: void armv6_idcache_wbinv_range(vaddr_t, vsize_t); */
+ENTRY(armv6_idcache_wbinv_range)
+	add	r1, r1, r0
+	sub	r1, r1, #1
+	mcrr	p15, 0, r1, r0, c5	/* invaliate I cache range */
+	mcrr	p15, 0, r1, r0, c14	/* clean & invaliate D cache range */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+	RET
+
+/* LINTSTUB: void armv6_idcache_wbinv_all(void); */
+ENTRY_NP(armv6_idcache_wbinv_all)
+	/*
+	 * We assume that the code here can never be out of sync with the
+	 * dcache, so that we can safely flush the Icache and fall through
+	 * into the Dcache purging code.
+	 */
+	mcr	p15, 0, r0, c7, c5, 0	/* Flush I cache */
+	/* Fall through to purge Dcache. */
+
+/* LINTSTUB: void armv6_dcache_wbinv_all(void); */
+ENTRY(armv6_dcache_wbinv_all)
+	mcr	p15, 0, r0, c7, c14, 0	/* clean and invalidate D cache */
+	mcr	p15, 0, r0, c7, c10, 4	/* drain the write buffer */
+	RET
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm/disassem.c sys/arch/arm/arm/disassem.c
--- ../../netbsd_40/src/sys/arch/arm/arm/disassem.c	2005-12-11 04:16:41.000000000 -0800
+++ sys/arch/arm/arm/disassem.c	2007-09-25 10:55:22.000000000 -0700
@@ -211,6 +211,9 @@
     { 0x0f100010, 0x0e100010, "mrc",	"#z" },
     { 0xff000010, 0xfe000000, "cdp2",	"#y" },
     { 0x0f000010, 0x0e000000, "cdp",	"#y" },
+    { 0x0f100010, 0x0e000010, "mcr",	"#z" },
+    { 0x0ff00000, 0x0c400000, "mcrr",	"#&" },
+    { 0x0ff00000, 0x0c500000, "mrrc",	"#&" },
     { 0xfe100090, 0xfc100000, "ldc2",	"L#v" },
     { 0x0e100090, 0x0c100000, "ldc",	"L#v" },
     { 0xfe100090, 0xfc000000, "stc2",	"L#v" },
@@ -501,6 +504,12 @@
 /*			if (((insn >> 5) & 0x07) != 0)
 				di->di_printf(", %d", (insn >> 5) & 0x07);*/
 			break;
+		/* & - co-processor register range transfer registers */
+		case '&':
+			di->di_printf("%d, r%d, r%d, c%d",
+			    (insn >> 4) & 0x0f, (insn >> 12) & 0x0f,
+			    (insn >> 16) & 0x0f, insn & 0x0f);
+			break;
 		default:
 			di->di_printf("[%c - unknown]", *f_ptr);
 			break;
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm32/arm1136_pmc.c sys/arch/arm/arm32/arm1136_pmc.c
--- ../../netbsd_40/src/sys/arch/arm/arm32/arm1136_pmc.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/arm32/arm1136_pmc.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,149 @@
+/*	$Id$	*/
+
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * support for ARM 1136 Performance Monitor Counters
+ */
+
+#include <sys/cdefs.h>
+#include "opt_perfctrs.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>  
+#include <sys/time.h>
+#include <sys/timetc.h>
+#include <dev/clock_subr.h>
+#include <arm/cpufunc.h>
+#include <arm/arm32/arm1136_pmc.h>
+
+#ifndef ARM1136_PMC_CCNT_HZ
+# define ARM1136_PMC_CCNT_HZ	400000000	/* 400MHz */
+#endif
+
+#define COUNTS_PER_USEC	(ARM1136_PMC_CCNT_HZ / 1000000)
+
+static uint32_t counts_per_wrap = ~0UL;		/* XXX off by 1 */
+
+int	clockhandler(void *);
+
+
+static inline uint32_t
+arm1136_pmc_ctrl_read(void)
+{
+	uint32_t val;
+
+	__asm volatile ("mrc p15, 0, %0, c15, c12, 0;" : "=r" (val));
+
+	return val;
+}
+
+static inline void
+arm1136_pmc_ctrl_write(uint32_t val)
+{
+	__asm volatile ("mcr p15, 0, %0, c15, c12, 0;" :: "r" (val));
+}
+
+static inline uint32_t
+arm1136_pmc_ccnt_read(void)
+{
+	uint32_t val;
+
+	__asm volatile ("mrc p15, 0, %0, c15, c12, 1;" : "=r" (val));
+
+	return val;
+}
+
+static inline void
+arm1136_pmc_ccnt_write(uint32_t val)
+{
+	__asm volatile ("mcr p15, 0, %0, c15, c12, 1;" :: "r" (val));
+}
+
+/*
+ * enable the PMC CCNT for delay()
+ */
+void
+arm1136_pmc_ccnt_init(void)
+{
+	uint32_t val;
+
+	val = ARM1136_PMCCTL_E | ARM1136_PMCCTL_P | ARM1136_PMCCTL_C;
+
+	arm1136_pmc_ctrl_write(val);
+}
+
+/*
+ * delay - for "at least" arg usec
+ *
+ *	NOTE: at 400MHz we are restricted to (uint32_t)~0 "counts"
+ *	if this is a problem, accumulate counts in LL vars
+ */
+#define DELAY_ARG_LIMIT (((uint32_t)~0) / COUNTS_PER_USEC)	/* about 10 sec */
+void
+delay(u_int arg)
+{
+	uint32_t ctrl;
+	uint32_t cur;
+	uint32_t last;
+	uint32_t delta = 0;
+	uint32_t usecs = 0;
+
+	if (arg > DELAY_ARG_LIMIT)
+		panic("delay: arg %u overflow, limit is %d usec\n", arg, DELAY_ARG_LIMIT);
+
+	last = arm1136_pmc_ccnt_read();
+	delta = usecs = 0;
+
+	while (arg > usecs) {
+		cur  = arm1136_pmc_ccnt_read();
+		ctrl = arm1136_pmc_ctrl_read();
+		if (ctrl & ARM1136_PMCCTL_CCR) {
+			/*
+			 * reset CCR, do not reset other write-to-clear flags;
+			 * maintain the rest of the PMC Control Reg configuration
+			 */
+			ctrl &= ~(ARM1136_PMCCTL_CR0|ARM1136_PMCCTL_CR1);
+			arm1136_pmc_ctrl_write(ctrl);
+			delta += (last + (counts_per_wrap - cur));
+		} else {
+			delta += (last - cur);
+		}
+		last = cur;
+		if (delta >= COUNTS_PER_USEC) {
+			usecs += delta / COUNTS_PER_USEC;
+			delta %= COUNTS_PER_USEC;
+		}
+	}
+}
+
+
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm32/cpu.c sys/arch/arm/arm32/cpu.c
--- ../../netbsd_40/src/sys/arch/arm/arm32/cpu.c	2007-02-21 10:36:03.000000000 -0800
+++ sys/arch/arm/arm32/cpu.c	2007-09-25 10:55:22.000000000 -0700
@@ -184,6 +184,11 @@
 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
 };

+static const char * const pN_steppings[16] = {
+	"*p0",	"*p1",	"*p2",	"*p3",	"*p4",	"*p5",	"*p6",	"*p7",
+	"*p8",	"*p9",	"*p10",	"*p11",	"*p12",	"*p13",	"*p14",	"*p15",
+};
+
 static const char * const sa110_steppings[16] = {
 	"rev 0",	"step J",	"step K",	"step S",
 	"step T",	"rev 5",	"rev 6",	"rev 7",
@@ -386,10 +391,10 @@
 	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
 	  ixp425_steppings },

-	{ CPU_ID_ARM1136JS,	CPU_CLASS_ARM11J,	"ARM1136J-S",
-	  generic_steppings },
-	{ CPU_ID_ARM1136JSR1,	CPU_CLASS_ARM11J,	"ARM1136J-S R1",
-	  generic_steppings },
+	{ CPU_ID_ARM1136JS,	CPU_CLASS_ARM11J,	"ARM1136J-S r0",
+	  pN_steppings },
+	{ CPU_ID_ARM1136JSR1,	CPU_CLASS_ARM11J,	"ARM1136J-S r1",
+	  pN_steppings },

 	{ 0, CPU_CLASS_NONE, NULL, NULL }
 };
@@ -449,6 +454,7 @@
 	u_int cpuid;
 	enum cpu_class cpu_class = CPU_CLASS_NONE;
 	int i;
+	const char *steppingstr;

 	cpuid = ci->ci_arm_cpuid;

@@ -460,10 +466,12 @@
 	for (i = 0; cpuids[i].cpuid != 0; i++)
 		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
 			cpu_class = cpuids[i].cpu_class;
-			sprintf(cpu_model, "%s %s (%s core)",
+			steppingstr = cpuids[i].cpu_steppings[cpuid &
+			    CPU_ID_REVISION_MASK],
+			sprintf(cpu_model, "%s%s%s (%s core)",
 			    cpuids[i].cpu_name,
-			    cpuids[i].cpu_steppings[cpuid &
-						    CPU_ID_REVISION_MASK],
+			    steppingstr[0] == '*' ? "" : " ",
+			    &steppingstr[steppingstr[0] == '*'],
 			    cpu_classes[cpu_class].class_name);
 			break;
 		}
@@ -586,6 +594,9 @@
 #ifdef CPU_ARM11
 	case CPU_CLASS_ARM11J:
 #endif
+#ifdef CPU_ARM1136
+	case CPU_CLASS_ARM11J:
+#endif
 		break;
 	default:
 		if (cpu_classes[cpu_class].class_option == NULL)
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm32/cpuswitch.S sys/arch/arm/arm32/cpuswitch.S
--- ../../netbsd_40/src/sys/arch/arm/arm32/cpuswitch.S	2007-03-04 04:15:39.000000000 -0800
+++ sys/arch/arm/arm32/cpuswitch.S	2007-09-25 10:55:22.000000000 -0700
@@ -565,11 +565,7 @@
 	mov	r12, #0
 	cmp	r5, #0				/* No last vm? (switch_exit) */
 	beq	.Lcs_cache_purge_skipped	/* No, we can skip cache flsh */
-
-	mov	r2, #DOMAIN_CLIENT
-	cmp	r1, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */
-	beq	.Lcs_cache_purge_skipped	/* Yup. Don't flush cache */
-
+#ifdef PMAP_CACHE_VIVT
 	cmp	r5, r8				/* Same userland VM space? */
 	ldrneb	r12, [r5, #(CS_CACHE_ID)]	/* Last VM space cache state */

@@ -582,6 +578,7 @@
 	 */
 	tst	r12, #0xff			/* Test cs_cache_id */
 	beq	.Lcs_cache_purge_skipped	/* VM space is not in cache */
+#endif /* PMAP_CACHE_VIVT */

 	/*
 	 * Definately need to flush the cache.
@@ -591,6 +588,7 @@
 	strb	r2, [r5, #(CS_CACHE_ID)]
 	strb	r2, [r5, #(CS_CACHE_D)]

+#ifdef PMAP_CACHE_VIVT
 	/*
 	 * Don't allow user space access between the purge and the switch.
 	 */
@@ -602,6 +600,7 @@
 	mov	lr, pc
 	ldr	pc, [r1, #CF_IDCACHE_WBINV_ALL]
 	ldmfd	sp!, {r0-r3}
+#endif

 .Lcs_cache_purge_skipped:
 	/* rem: r1 = new DACR */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm32/locore.S sys/arch/arm/arm32/locore.S
--- ../../netbsd_40/src/sys/arch/arm/arm32/locore.S	2005-12-11 04:16:41.000000000 -0800
+++ sys/arch/arm/arm32/locore.S	2007-09-24 09:46:50.000000000 -0700
@@ -212,5 +212,4 @@
 ENTRY_NP(abort)
 	b	_C_LABEL(abort)

-
 /* End of locore.S */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/arm32/pmap.c sys/arch/arm/arm32/pmap.c
--- ../../netbsd_40/src/sys/arch/arm/arm32/pmap.c	2007-02-21 10:33:19.000000000 -0800
+++ sys/arch/arm/arm32/pmap.c	2007-09-25 10:55:22.000000000 -0700
@@ -140,6 +140,11 @@
  */

 /*
+ * armv6 and VIPT cache support by 3am Software Foundry,
+ * Copyright (c) 2007 Danger Inc
+ */
+
+/*
  * Performance improvements, UVM changes, overhauls and part-rewrites
  * were contributed by Neil A. Carson <neil@causality.com>.
  */
@@ -240,6 +245,7 @@
 #define	PDB_VAC		0x10000
 #define	PDB_KENTER	0x20000
 #define	PDB_KREMOVE	0x40000
+#define	PDB_EXEC	0x80000

 int debugmap = 1;
 int pmapdebug = 0; 
@@ -301,6 +307,126 @@
 static vaddr_t pmap_kernel_l2ptp_kva;
 static paddr_t pmap_kernel_l2ptp_phys;

+#define	PMAP_EVCNT_INITIALIZER(name) \
+	EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "pmap", name)
+
+static struct evcnt pmap_ev_vac_color_new =
+   PMAP_EVCNT_INITIALIZER("new page color");
+static struct evcnt pmap_ev_vac_color_reuse =
+   PMAP_EVCNT_INITIALIZER("ok first page color");
+static struct evcnt pmap_ev_vac_color_ok =
+   PMAP_EVCNT_INITIALIZER("ok page color");
+static struct evcnt pmap_ev_vac_color_change =
+   PMAP_EVCNT_INITIALIZER("change page color");
+static struct evcnt pmap_ev_vac_color_erase =
+   PMAP_EVCNT_INITIALIZER("erase page color");
+static struct evcnt pmap_ev_vac_color_none =
+   PMAP_EVCNT_INITIALIZER("no page color");
+static struct evcnt pmap_ev_vac_color_restore =
+   PMAP_EVCNT_INITIALIZER("restore page color");
+
+EVCNT_ATTACH_STATIC(pmap_ev_vac_color_new);
+EVCNT_ATTACH_STATIC(pmap_ev_vac_color_reuse);
+EVCNT_ATTACH_STATIC(pmap_ev_vac_color_ok);
+EVCNT_ATTACH_STATIC(pmap_ev_vac_color_change);
+EVCNT_ATTACH_STATIC(pmap_ev_vac_color_erase);
+EVCNT_ATTACH_STATIC(pmap_ev_vac_color_none);
+EVCNT_ATTACH_STATIC(pmap_ev_vac_color_restore);
+
+static struct evcnt pmap_ev_mappings =
+   PMAP_EVCNT_INITIALIZER("pages mapped");
+static struct evcnt pmap_ev_unmappings =
+   PMAP_EVCNT_INITIALIZER("pages unmapped");
+static struct evcnt pmap_ev_remappings =
+   PMAP_EVCNT_INITIALIZER("pages remapped");
+
+EVCNT_ATTACH_STATIC(pmap_ev_mappings);
+EVCNT_ATTACH_STATIC(pmap_ev_unmappings);
+EVCNT_ATTACH_STATIC(pmap_ev_remappings);
+
+static struct evcnt pmap_ev_kernel_mappings =
+   PMAP_EVCNT_INITIALIZER("kernel pages mapped");
+static struct evcnt pmap_ev_kernel_unmappings =
+   PMAP_EVCNT_INITIALIZER("kernel pages unmapped");
+static struct evcnt pmap_ev_kernel_remappings =
+   PMAP_EVCNT_INITIALIZER("kernel pages remapped");
+
+EVCNT_ATTACH_STATIC(pmap_ev_kernel_mappings);
+EVCNT_ATTACH_STATIC(pmap_ev_kernel_unmappings);
+EVCNT_ATTACH_STATIC(pmap_ev_kernel_remappings);
+
+static struct evcnt pmap_ev_kenter_mappings =
+   PMAP_EVCNT_INITIALIZER("kenter pages mapped");
+static struct evcnt pmap_ev_kenter_unmappings =
+   PMAP_EVCNT_INITIALIZER("kenter pages unmapped");
+static struct evcnt pmap_ev_kenter_remappings =
+   PMAP_EVCNT_INITIALIZER("kenter pages remapped");
+static struct evcnt pmap_ev_pt_mappings =
+   PMAP_EVCNT_INITIALIZER("page table pages mapped");
+
+EVCNT_ATTACH_STATIC(pmap_ev_kenter_mappings);
+EVCNT_ATTACH_STATIC(pmap_ev_kenter_unmappings);
+EVCNT_ATTACH_STATIC(pmap_ev_kenter_remappings);
+EVCNT_ATTACH_STATIC(pmap_ev_pt_mappings);
+
+static struct evcnt pmap_ev_exec_mappings =
+   PMAP_EVCNT_INITIALIZER("exec pages mapped");
+static struct evcnt pmap_ev_exec_cached =
+   PMAP_EVCNT_INITIALIZER("exec pages cached");
+
+EVCNT_ATTACH_STATIC(pmap_ev_exec_mappings);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_cached);
+
+static struct evcnt pmap_ev_exec_synced =
+   PMAP_EVCNT_INITIALIZER("exec pages synced");
+static struct evcnt pmap_ev_exec_synced_map =
+   PMAP_EVCNT_INITIALIZER("exec pages synced (MP)");
+static struct evcnt pmap_ev_exec_synced_unmap =
+   PMAP_EVCNT_INITIALIZER("exec pages synced (UM)");
+static struct evcnt pmap_ev_exec_synced_remap =
+   PMAP_EVCNT_INITIALIZER("exec pages synced (RM)");
+static struct evcnt pmap_ev_exec_synced_clearbit =
+   PMAP_EVCNT_INITIALIZER("exec pages synced (DG)");
+static struct evcnt pmap_ev_exec_synced_kremove =
+   PMAP_EVCNT_INITIALIZER("exec pages synced (KU)");
+
+EVCNT_ATTACH_STATIC(pmap_ev_exec_synced);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_synced_map);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_synced_unmap);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_synced_remap);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_synced_clearbit);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_synced_kremove);
+
+static struct evcnt pmap_ev_exec_discarded_unmap =
+   PMAP_EVCNT_INITIALIZER("exec pages discarded (UM)");
+static struct evcnt pmap_ev_exec_discarded_zero =
+   PMAP_EVCNT_INITIALIZER("exec pages discarded (ZP)");
+static struct evcnt pmap_ev_exec_discarded_copy =
+   PMAP_EVCNT_INITIALIZER("exec pages discarded (CP)");
+static struct evcnt pmap_ev_exec_discarded_page_protect =
+   PMAP_EVCNT_INITIALIZER("exec pages discarded (PP)");
+static struct evcnt pmap_ev_exec_discarded_clearbit =
+   PMAP_EVCNT_INITIALIZER("exec pages discarded (DG)");
+static struct evcnt pmap_ev_exec_discarded_kremove =
+   PMAP_EVCNT_INITIALIZER("exec pages discarded (KU)");
+
+EVCNT_ATTACH_STATIC(pmap_ev_exec_discarded_unmap);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_discarded_zero);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_discarded_copy);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_discarded_page_protect);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_discarded_clearbit);
+EVCNT_ATTACH_STATIC(pmap_ev_exec_discarded_kremove);
+
+static struct evcnt pmap_ev_updates = PMAP_EVCNT_INITIALIZER("updates");
+static struct evcnt pmap_ev_collects = PMAP_EVCNT_INITIALIZER("collects");
+static struct evcnt pmap_ev_activations = PMAP_EVCNT_INITIALIZER("activations");
+
+EVCNT_ATTACH_STATIC(pmap_ev_updates);
+EVCNT_ATTACH_STATIC(pmap_ev_collects);
+EVCNT_ATTACH_STATIC(pmap_ev_activations);
+
+#define	PMAPCOUNT(x)	((void)(pmap_ev_##x.ev_count++))
+
 /*
  * pmap copy/zero page, and mem(5) hook point
  */
@@ -471,6 +597,7 @@
  * instruction cache and/or TLB
  */
 #define	PV_BEEN_EXECD(f)  (((f) & (PVF_REF | PVF_EXEC)) == (PVF_REF | PVF_EXEC))
+#define	PV_IS_EXEC_P(f)   (((f) & PVF_EXEC) != 0)

 /*
  * Macro to determine if a mapping might be resident in the
@@ -507,11 +634,19 @@
 static int		pmap_l2dtable_ctor(void *, void *, int);

 static void		pmap_vac_me_harder(struct vm_page *, pmap_t, vaddr_t);
+#ifdef PMAP_CACHE_VIVT
 static void		pmap_vac_me_kpmap(struct vm_page *, pmap_t, vaddr_t);
 static void		pmap_vac_me_user(struct vm_page *, pmap_t, vaddr_t);
+#endif

 static void		pmap_clearbit(struct vm_page *, u_int);
+#ifdef PMAP_CACHE_VIVT
 static int		pmap_clean_page(struct pv_entry *, boolean_t);
+#endif
+#ifdef PMAP_CACHE_VIPT
+static void		pmap_syncicache_page(struct vm_page *);
+static void		pmap_flush_page(struct vm_page *);
+#endif
 static void		pmap_page_remove(struct vm_page *);

 static void		pmap_init_l1(struct l1_ttable *, pd_entry_t *);
@@ -588,12 +723,13 @@
 	}
 }

+#ifdef PMAP_CACHE_VIVT
 static inline void
 pmap_idcache_wbinv_range(pmap_t pm, vaddr_t va, vsize_t len)
 {
-
-	if (pm->pm_cstate.cs_cache_id)
+	if (pm->pm_cstate.cs_cache_id) {
 		cpu_idcache_wbinv_range(va, len);
+	}
 }

 static inline void
@@ -616,7 +752,6 @@
 static inline void
 pmap_idcache_wbinv_all(pmap_t pm)
 {
-
 	if (pm->pm_cstate.cs_cache_id) {
 		cpu_idcache_wbinv_all();
 		pm->pm_cstate.cs_cache = 0;
@@ -626,12 +761,12 @@
 static inline void
 pmap_dcache_wbinv_all(pmap_t pm)
 {
-
 	if (pm->pm_cstate.cs_cache_d) {
 		cpu_dcache_wbinv_all();
 		pm->pm_cstate.cs_cache_d = 0;
 	}
 }
+#endif /* PMAP_CACHE_VIVT */

 static inline boolean_t
 pmap_is_current(pmap_t pm)
@@ -710,6 +845,7 @@
 	pg->mdpage.pvh_list = pve;		/* ... locked list */
 	pg->mdpage.pvh_attrs |= flags & (PVF_REF | PVF_MOD);
 	if (pm == pmap_kernel()) {
+		PMAPCOUNT(kernel_mappings);
 		if (flags & PVF_WRITE)
 			pg->mdpage.krw_mappings++;
 		else
@@ -719,6 +855,22 @@
 		pg->mdpage.urw_mappings++;
 	else
 		pg->mdpage.uro_mappings++;
+
+#ifdef PMAP_CACHE_VIPT
+	/*
+	 * If this is an exec mapping and its the first exec mapping
+	 * for this page, make sure to sync the I-cache.
+	 */
+	if (PV_IS_EXEC_P(flags)) {
+		if (!PV_IS_EXEC_P(pg->mdpage.pvh_attrs)) {
+			pmap_syncicache_page(pg);
+			PMAPCOUNT(exec_synced_map);
+		}
+		PMAPCOUNT(exec_mappings);
+	}
+#endif
+
+	PMAPCOUNT(mappings);
 	simple_unlock(&pg->mdpage.pvh_slock);	/* unlock, done! */

 	if (pve->pv_flags & PVF_WIRED)
@@ -776,6 +928,7 @@
 			}
 			*prevptr = pve->pv_next;		/* remove it! */
 			if (pm == pmap_kernel()) {
+				PMAPCOUNT(kernel_unmappings);
 				if (pve->pv_flags & PVF_WRITE)
 					pg->mdpage.krw_mappings--;
 				else
@@ -785,6 +938,26 @@
 				pg->mdpage.urw_mappings--;
 			else
 				pg->mdpage.uro_mappings--;
+
+			PMAPCOUNT(unmappings);
+#ifdef PMAP_CACHE_VIPT
+			if (!(pve->pv_flags & PVF_WRITE))
+				break;
+			/*
+			 * If this page has had an exec mapping, then if
+			 * this was the last mapping, discard the contents,
+			 * otherwise sync the i-cache for this page.
+			 */
+			if (PV_IS_EXEC_P(pg->mdpage.pvh_attrs)) {
+				if (pg->mdpage.pvh_list == NULL) {
+					pg->mdpage.pvh_attrs &= ~PVF_EXEC;
+					PMAPCOUNT(exec_discarded_unmap);
+				} else {
+					pmap_syncicache_page(pg);
+					PMAPCOUNT(exec_synced_unmap);
+				}
+			}
+#endif
 			break;
 		}
 		prevptr = &pve->pv_next;		/* previous pointer */
@@ -854,6 +1027,22 @@
 			pg->mdpage.urw_mappings--;
 		}
 	}
+#ifdef PMAP_CACHE_VIPT
+	/*
+	 * We have two cases here: the first is from enter_pv (new exec
+	 * page), the second is a combined pmap_remove_pv/pmap_enter_pv.
+	 * Since in latter, pmap_enter_pv won't do anything, we just have
+	 * to do what pmap_remove_pv would do.
+	 */
+	if ((PV_IS_EXEC_P(flags) && !PV_IS_EXEC_P(pg->mdpage.pvh_attrs))
+	    || (PV_IS_EXEC_P(pg->mdpage.pvh_attrs)
+		|| (!(flags & PVF_WRITE) && (oflags & PVF_WRITE)))) {
+		pmap_syncicache_page(pg);
+		PMAPCOUNT(exec_synced_remap);
+	}
+#endif
+
+	PMAPCOUNT(remappings);

 	return (oflags);
 }
@@ -1004,12 +1193,13 @@
 #endif
 {
 #ifdef PMAP_INCLUDE_PTE_SYNC
+#ifdef PMAP_CACHE_VIVT
 	/*
 	 * Note: With a write-back cache, we may need to sync this
 	 * L2 table before re-using it.
 	 * This is because it may have belonged to a non-current
 	 * pmap, in which case the cache syncs would have been
-	 * skipped when the pages were being unmapped. If the
+	 * skipped for the pages that were being unmapped. If the
 	 * L2 table were then to be immediately re-allocated to
 	 * the *current* pmap, it may well contain stale mappings
 	 * which have not yet been cleared by a cache write-back
@@ -1017,7 +1207,8 @@
 	 */
 	if (need_sync)
 		PTE_SYNC_RANGE(l2, L2_TABLE_SIZE_REAL / sizeof(pt_entry_t));
-#endif
+#endif /* PMAP_CACHE_VIVT */
+#endif /* PMAP_INCLUDE_PTE_SYNC */
 	pool_cache_put_paddr(&pmap_l2ptp_cache, (void *)l2, pa);
 }

@@ -1255,6 +1446,7 @@
 	return (0);
 }

+#ifdef PMAP_CACHE_VIVT
 /*
  * Since we have a virtually indexed cache, we may need to inhibit caching if
  * there is more than one mapping and at least one of them is writable.
@@ -1474,15 +1666,19 @@
 			if ((va != pv->pv_va || pm != pv->pv_pmap) &&
 			    l2pte_valid(pte)) {
 				if (PV_BEEN_EXECD(pv->pv_flags)) {
+#ifdef PMAP_CACHE_VIVT
 					pmap_idcache_wbinv_range(pv->pv_pmap,
 					    pv->pv_va, PAGE_SIZE);
+#endif
 					pmap_tlb_flushID_SE(pv->pv_pmap,
 					    pv->pv_va);
 				} else
 				if (PV_BEEN_REFD(pv->pv_flags)) {
+#ifdef PMAP_CACHE_VIVT
 					pmap_dcache_wb_range(pv->pv_pmap,
 					    pv->pv_va, PAGE_SIZE, TRUE,
 					    (pv->pv_flags & PVF_WRITE) == 0);
+#endif
 					pmap_tlb_flushD_SE(pv->pv_pmap,
 					    pv->pv_va);
 				}
@@ -1525,6 +1721,192 @@
 		}
 	}
 }
+#endif
+
+#ifdef PMAP_CACHE_VIPT
+/*
+ * For virtually indexed / physically tagged caches, what we have to worry
+ * about is illegal cache aliases.  To prevent this, we must ensure that
+ * virtual addresses that map the physical page use the same bits for those
+ * bits masked by "arm_cache_prefer_mask" (bits 12+).  If there is a conflict,
+ * all mappings of the page must be non-cached.
+ */
+static void
+pmap_vac_me_harder(struct vm_page *pg, pmap_t pm, vaddr_t va)
+{
+	struct pv_entry *pv, pv0;
+	vaddr_t tst_mask;
+	bool bad_alias;
+	struct l2_bucket *l2b;
+	pt_entry_t *ptep, pte, opte;
+
+	/* do we need to do anything? */
+	if (arm_cache_prefer_mask == 0)
+		return;
+
+	NPDEBUG(PDB_VAC, printf("pmap_vac_me_harder: pg=%p, pmap=%p va=%08lx\n",
+	    pg, pm, va));
+
+#define popc4(x) \
+	(((0x94 >> ((x & 3) << 1)) & 3) + ((0x94 >> ((x & 12) >> 1)) & 3))
+
+	KASSERT(!va || pm || (pg->mdpage.pvh_attrs & PVF_KENTRY));
+
+	/* Already a conflict? */
+	if (__predict_false(pg->mdpage.pvh_attrs & PVF_NC)) {
+		/* just an add, things are already non-cached */
+		bad_alias = false;
+		if (va) {
+			PMAPCOUNT(vac_color_none);
+			bad_alias = true;
+			goto fixup;
+		}
+		pv = pg->mdpage.pvh_list;
+		/* the list can't be empty because it would be cachable */
+		if (pg->mdpage.pvh_attrs & PVF_KENTRY) {
+			tst_mask = pg->mdpage.pvh_attrs;
+		} else {
+			KASSERT(pv);
+			tst_mask = pv->pv_va;
+			pv = pv->pv_next;
+		}
+		tst_mask &= arm_cache_prefer_mask;
+		for (; pv && !bad_alias; pv = pv->pv_next) {
+			/* if there's a bad alias, stop checking. */
+			if (tst_mask != (pv->pv_va & arm_cache_prefer_mask))
+				bad_alias = true;
+		}
+		/* If no conflicting colors, set everything back to cached */
+		if (!bad_alias) {
+			PMAPCOUNT(vac_color_restore);
+			pg->mdpage.pvh_attrs |= PVF_COLORED;
+			if (!(pg->mdpage.pvh_attrs & PVF_KENTRY)) {
+				pg->mdpage.pvh_attrs &= PAGE_SIZE - 1;
+				pg->mdpage.pvh_attrs |= tst_mask;
+			}
+			pg->mdpage.pvh_attrs &= ~PVF_NC;
+		} else {
+			KASSERT(pg->mdpage.pvh_list != NULL);
+			KASSERT((pg->mdpage.pvh_attrs & PVF_KENTRY)
+			     || pg->mdpage.pvh_list->pv_next != NULL);
+		}
+	} else if (!va) {
+		KASSERT(pmap_is_page_colored_p(pg));
+		if (pm == NULL)
+			pg->mdpage.pvh_attrs &=
+			    (PAGE_SIZE - 1) | arm_cache_prefer_mask;
+		return;
+	} else if (!pmap_is_page_colored_p(pg)) {
+		/* not colored so we just use its color */
+		PMAPCOUNT(vac_color_new);
+		pg->mdpage.pvh_attrs &= PAGE_SIZE - 1;
+		if (pm == NULL)
+			pg->mdpage.pvh_attrs |= PVF_COLORED | va;
+		else
+			pg->mdpage.pvh_attrs |= PVF_COLORED
+			    | (va & arm_cache_prefer_mask);
+		return;
+	} else if (!((pg->mdpage.pvh_attrs ^ va) & arm_cache_prefer_mask)) {
+		if (pm == NULL) {
+			pg->mdpage.pvh_attrs &= PAGE_SIZE - 1;
+			pg->mdpage.pvh_attrs |= va;
+		}
+		if (pg->mdpage.pvh_list)
+			PMAPCOUNT(vac_color_reuse);
+		else
+			PMAPCOUNT(vac_color_ok);
+		/* matching color, just return */
+		return;
+	} else {
+		/* color conflict.  evict from cache. */
+		pmap_flush_page(pg);
+
+		/* the list can't be empty because this was a enter/modify */
+		pv = pg->mdpage.pvh_list;
+		KASSERT((pg->mdpage.pvh_attrs & PVF_KENTRY) || pv);
+
+		/*
+		 * If there's only one mapped page, change color to the
+		 * page's new color and return.
+		 */
+		if (((pg->mdpage.pvh_attrs & PVF_KENTRY)
+		    ? pv : pv->pv_next) == NULL) {
+			PMAPCOUNT(vac_color_change);
+			pg->mdpage.pvh_attrs &= PAGE_SIZE - 1;
+			if (pm == NULL)
+				pg->mdpage.pvh_attrs |= va;
+			else
+				pg->mdpage.pvh_attrs |=
+				    (va & arm_cache_prefer_mask);
+			return;
+		}
+		bad_alias = true;
+		pg->mdpage.pvh_attrs &= ~PVF_COLORED;
+		pg->mdpage.pvh_attrs |= PVF_NC;
+		PMAPCOUNT(vac_color_erase);
+	}
+
+  fixup:
+	/*
+	 * If the pmap is NULL, then we got called from pmap_kenter_pa
+	 * and we must save the kenter'ed va.  And this changes the
+	 * color to match the kenter'ed page.  if this is a remove clear
+	 * saved va bits which retaining the color bits.
+	 */
+	if (pm == NULL) {
+		if (va) {
+			pg->mdpage.pvh_attrs &= (PAGE_SIZE - 1);
+			pg->mdpage.pvh_attrs |= va;
+		} else {
+			pg->mdpage.pvh_attrs &=
+			    ((PAGE_SIZE - 1) | arm_cache_prefer_mask);
+		}
+	}
+
+	pv = pg->mdpage.pvh_list;
+
+	/*
+	 * If this page has an kenter'ed mapping, fake up a pv entry.
+	 */
+	if (__predict_false(pg->mdpage.pvh_attrs & PVF_KENTRY)) {
+		pv0.pv_pmap = pmap_kernel();
+		pv0.pv_va = pg->mdpage.pvh_attrs & ~(PAGE_SIZE - 1);
+		pv0.pv_next = pv;
+		pv0.pv_flags = PVF_REF;
+		pv = &pv0;
+	}
+
+	/*
+	 * Turn cacheing on/off for all pages.
+	 */
+	for (; pv; pv = pv->pv_next) {
+		l2b = pmap_get_l2_bucket(pv->pv_pmap, pv->pv_va);
+		ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
+		opte = *ptep;
+		pte = opte & ~L2_S_CACHE_MASK;
+		if (bad_alias) {
+			pv->pv_flags |= PVF_NC;
+		} else {
+			pv->pv_flags &= ~PVF_NC;
+			pte |= pte_l2_s_cache_mode;
+		}
+		if (opte == pte)	/* only update is there's a change */
+			continue;
+
+		if (l2pte_valid(pte)) {
+			if (PV_BEEN_EXECD(pv->pv_flags)) {
+				pmap_tlb_flushID_SE(pv->pv_pmap, pv->pv_va);
+			} else if (PV_BEEN_REFD(pv->pv_flags)) {
+				pmap_tlb_flushD_SE(pv->pv_pmap, pv->pv_va);
+			}
+		}
+
+		*ptep = pte;
+		PTE_SYNC_CURRENT(pv->pv_pmap, ptep);
+	}
+}
+#endif	/* PMAP_CACHE_VIPT */
+

 /*
  * Modify pte bits for all ptes corresponding to the given physical address.
@@ -1540,6 +1922,11 @@
 	pmap_t pm;
 	vaddr_t va;
 	u_int oflags;
+#ifdef PMAP_CACHE_VIPT
+	const bool want_syncicache = PV_IS_EXEC_P(pg->mdpage.pvh_attrs);
+	bool need_syncicache = false;
+	bool did_syncicache = false;
+#endif

 	NPDEBUG(PDB_BITS,
 	    printf("pmap_clearbit: pg %p (0x%08lx) mask 0x%x\n",
@@ -1548,12 +1935,30 @@
 	PMAP_HEAD_TO_MAP_LOCK();
 	simple_lock(&pg->mdpage.pvh_slock);

+#ifdef PMAP_CACHE_VIPT
+	/*
+	 * If we might want to sync the I-cache and we've modified it,
+	 * then we know we definitely need to sync or discard it.
+	 */
+	if (want_syncicache)
+		need_syncicache = pg->mdpage.pvh_attrs & PVF_MOD;
+#endif
 	/*
 	 * Clear saved attributes (modify, reference)
 	 */
 	pg->mdpage.pvh_attrs &= ~(maskbits & (PVF_MOD | PVF_REF));

 	if (pg->mdpage.pvh_list == NULL) {
+#ifdef PMAP_CACHE_VIPT
+		if (need_syncicache) {
+			/*
+			 * No one has it mapped, so just discard it.  The next
+			 * exec remapping will cause it to be synced.
+			 */
+			pg->mdpage.pvh_attrs &= ~PVF_EXEC;
+			PMAPCOUNT(exec_discarded_clearbit);
+		}
+#endif
 		simple_unlock(&pg->mdpage.pvh_slock);
 		PMAP_HEAD_TO_MAP_UNLOCK();
 		return;
@@ -1582,6 +1987,7 @@
 		    pv, pv->pv_pmap, pv->pv_va, oflags));

 		if (maskbits & (PVF_WRITE|PVF_MOD)) {
+#ifdef PMAP_CACHE_VIVT
 			if ((pv->pv_flags & PVF_NC)) {
 				/* 
 				 * Entry is not cacheable:
@@ -1617,58 +2023,51 @@
 					    (maskbits & PVF_REF) ? TRUE : FALSE,
 					    FALSE);
 			}
+#endif

 			/* make the pte read only */
 			npte &= ~L2_S_PROT_W;

-			if (maskbits & PVF_WRITE) {
+			if (maskbits & oflags & PVF_WRITE) {
 				/*
 				 * Keep alias accounting up to date
 				 */
 				if (pv->pv_pmap == pmap_kernel()) {
-					if (oflags & PVF_WRITE) {
-						pg->mdpage.krw_mappings--;
-						pg->mdpage.kro_mappings++;
-					}
-				} else
-				if (oflags & PVF_WRITE) {
+					pg->mdpage.krw_mappings--;
+					pg->mdpage.kro_mappings++;
+				} else {
 					pg->mdpage.urw_mappings--;
 					pg->mdpage.uro_mappings++;
 				}
+#ifdef PMAP_CACHE_VIPT
+				if (want_syncicache)
+					need_syncicache = true;
+#endif
 			}
 		}

 		if (maskbits & PVF_REF) {
+#ifdef PMAP_CACHE_VIVT
 			if ((pv->pv_flags & PVF_NC) == 0 &&
-			    (maskbits & (PVF_WRITE|PVF_MOD)) == 0) {
+			    (maskbits & (PVF_WRITE|PVF_MOD)) == 0 &&
+			    l2pte_valid(npte)) {
 				/*
 				 * Check npte here; we may have already
 				 * done the wbinv above, and the validity
 				 * of the PTE is the same for opte and
 				 * npte.
 				 */
-				if (npte & L2_S_PROT_W) {
-					if (PV_BEEN_EXECD(oflags))
-						pmap_idcache_wbinv_range(pm,
-						    pv->pv_va, PAGE_SIZE);
-					else
-					if (PV_BEEN_REFD(oflags))
-						pmap_dcache_wb_range(pm,
-						    pv->pv_va, PAGE_SIZE,
-						    TRUE, FALSE);
-				} else
-				if ((npte & L2_TYPE_MASK) != L2_TYPE_INV) {
-					/* XXXJRT need idcache_inv_range */
-					if (PV_BEEN_EXECD(oflags))
-						pmap_idcache_wbinv_range(pm,
-						    pv->pv_va, PAGE_SIZE);
-					else
-					if (PV_BEEN_REFD(oflags))
-						pmap_dcache_wb_range(pm,
-						    pv->pv_va, PAGE_SIZE,
-						    TRUE, TRUE);
-				}
+				/* XXXJRT need idcache_inv_range */
+				if (PV_BEEN_EXECD(oflags))
+					pmap_idcache_wbinv_range(pm,
+					    pv->pv_va, PAGE_SIZE);
+				else
+				if (PV_BEEN_REFD(oflags))
+					pmap_dcache_wb_range(pm,
+					    pv->pv_va, PAGE_SIZE,
+					    TRUE, TRUE);
 			}
+#endif

 			/*
 			 * Make the PTE invalid so that we will take a
@@ -1697,6 +2096,16 @@
 		    pm, va, opte, npte));
 	}

+#ifdef PMAP_CACHE_VIPT
+	/*
+	 * If we need to sync the I-cache and we haven't done it yet, do it.
+	 */
+	if (need_syncicache && !did_syncicache) {
+		pmap_syncicache_page(pg);
+		PMAPCOUNT(exec_synced_clearbit);
+	}
+#endif
+
 	simple_unlock(&pg->mdpage.pvh_slock);
 	PMAP_HEAD_TO_MAP_UNLOCK();
 }
@@ -1721,6 +2130,7 @@
  * just the 1 page. Since this should not occur in everyday use and if it does
  * it will just result in not the most efficient clean for the page.
  */
+#ifdef PMAP_CACHE_VIVT
 static int
 pmap_clean_page(struct pv_entry *pv, boolean_t is_src)
 {
@@ -1788,6 +2198,87 @@
 	}
 	return (0);
 }
+#endif
+
+#ifdef PMAP_CACHE_VIPT
+/*
+ * Sync a page with the I-cache.  Since this is a VIPT, we must pick the
+ * right cache alias to make sure we flush the right stuff.
+ */
+void
+pmap_syncicache_page(struct vm_page *pg)
+{
+	const vsize_t va_offset = pg->mdpage.pvh_attrs & arm_cache_prefer_mask;
+	pt_entry_t * const ptep = &cdst_pte[va_offset >> PGSHIFT];
+
+	NPDEBUG(PDB_EXEC, printf("pmap_syncicache_page: pg=%p (attrs=%#x)\n",
+	    pg, pg->mdpage.pvh_attrs));
+	/*
+	 * No need to clean the page if it's non-cached.
+	 */
+	if (pg->mdpage.pvh_attrs & PVF_NC)
+		return;
+	KASSERT(pg->mdpage.pvh_attrs & PVF_COLORED);
+
+	pmap_tlb_flushID_SE(pmap_kernel(), cdstp + va_offset);
+	/*
+	 * Set up a PTE with the right coloring to flush existing cache lines.
+	 */
+	*ptep = L2_S_PROTO |
+	    VM_PAGE_TO_PHYS(pg)
+	    | L2_S_PROT(PTE_KERNEL, VM_PROT_READ|VM_PROT_WRITE)
+	    | pte_l2_s_cache_mode;
+	PTE_SYNC(ptep);
+
+	/*
+	 * Flush it.
+	 */
+	cpu_icache_sync_range(cdstp + va_offset, PAGE_SIZE);
+	/*
+	 * Unmap the page.
+	 */
+	*ptep = 0;
+	PTE_SYNC(ptep);
+	pmap_tlb_flushID_SE(pmap_kernel(), cdstp + va_offset);
+
+	pg->mdpage.pvh_attrs |= PVF_EXEC;
+	PMAPCOUNT(exec_synced);
+}
+
+void
+pmap_flush_page(struct vm_page *pg)
+{
+	const vsize_t va_offset = pg->mdpage.pvh_attrs & arm_cache_prefer_mask;
+	const size_t pte_offset = va_offset >> PGSHIFT;
+	pt_entry_t * const ptep = &cdst_pte[pte_offset];
+
+	KASSERT(!(pg->mdpage.pvh_attrs & PVF_NC));
+
+	NPDEBUG(PDB_VAC, printf("pmap_flush_page: pg=%p (attrs=%#x)\n",
+	    pg, pg->mdpage.pvh_attrs));
+	pmap_tlb_flushID_SE(pmap_kernel(), cdstp + va_offset);
+	/*
+	 * Set up a PTE with the right coloring to flush existing cache entries.
+	 */
+	*ptep = L2_S_PROTO
+	    | VM_PAGE_TO_PHYS(pg)
+	    | L2_S_PROT(PTE_KERNEL, VM_PROT_READ|VM_PROT_WRITE)
+	    | pte_l2_s_cache_mode;
+	PTE_SYNC(ptep);
+
+	/*
+	 * Flush it.
+	 */
+	cpu_idcache_wbinv_range(cdstp + va_offset, PAGE_SIZE);
+
+	/*
+	 * Unmap the page.
+	 */
+	*ptep = 0;
+	PTE_SYNC(ptep);
+	pmap_tlb_flushID_SE(pmap_kernel(), cdstp + va_offset);
+}
+#endif /* PMAP_CACHE_VIPT */

 /*
  * Routine:	pmap_page_remove
@@ -1815,10 +2306,22 @@

 	pv = pg->mdpage.pvh_list;
 	if (pv == NULL) {
+#ifdef PMAP_CACHE_VIPT
+		/*
+		 * We *know* the page contents are about to be replaced.
+		 * Discard the exec contents
+		 */
+		if (PV_IS_EXEC_P(pg->mdpage.pvh_attrs))
+			PMAPCOUNT(exec_discarded_page_protect);
+		pg->mdpage.pvh_attrs &= ~PVF_EXEC;
+#endif
 		simple_unlock(&pg->mdpage.pvh_slock);
 		PMAP_HEAD_TO_MAP_UNLOCK();
 		return;
 	}
+#ifdef PMAP_CACHE_VIPT
+	KASSERT(pmap_is_page_colored_p(pg));
+#endif

 	/*
 	 * Clear alias counts
@@ -1833,13 +2336,19 @@
 	else
 		curpm = pmap_kernel();

+#ifdef PMAP_CACHE_VIVT
 	pmap_clean_page(pv, FALSE);
+#endif

 	while (pv) {
 		pm = pv->pv_pmap;
 		if (flush == FALSE && (pm == curpm || pm == pmap_kernel()))
 			flush = TRUE;

+		if (pm == pmap_kernel())
+			PMAPCOUNT(kernel_unmappings);
+		PMAPCOUNT(unmappings);
+
 		pmap_acquire_pmap_lock(pm);

 		l2b = pmap_get_l2_bucket(pm, pv->pv_va);
@@ -1869,9 +2378,33 @@
 		npv = pv->pv_next;
 		pool_put(&pmap_pv_pool, pv);
 		pv = npv;
+#ifdef PMAP_CACHE_VIPT
+		/*
+		 * If this is the last pv entry and there is a kenter alias
+		 * we must call pmap_me_me_harder to restore its cacheability.
+		 * We need a pmap (to indicate we are removing a normal
+		 * mapping) so use this one.
+		 */
+		if (pv == NULL) {
+			pg->mdpage.pvh_list = NULL;
+			if (pg->mdpage.pvh_attrs & PVF_KENTRY)
+				pmap_vac_me_harder(pg, pm, 0);
+		}
+#endif
 		pmap_release_pmap_lock(pm);
 	}
+#ifdef PMAP_CACHE_VIPT
+	/*
+	 * Since there are now no mappings, there isn't reason to mark it
+	 * as uncached.  Its EXEC cache is also gone.
+	 */
+	if (PV_IS_EXEC_P(pg->mdpage.pvh_attrs))
+		PMAPCOUNT(exec_discarded_page_protect);
+	pg->mdpage.pvh_attrs &= ~(PVF_NC|PVF_EXEC);
+#endif
+#ifdef PMAP_CACHE_VIVT
 	pg->mdpage.pvh_list = NULL;
+#endif
 	simple_unlock(&pg->mdpage.pvh_slock);
 	PMAP_HEAD_TO_MAP_UNLOCK();

@@ -2051,6 +2584,7 @@
 			    PVF_MOD | PVF_REF, nflags);
 			simple_unlock(&pg->mdpage.pvh_slock);

+#ifdef PMAP_CACHE_VIVT
 			/*
 			 * We may need to flush the cache if we're
 			 * doing rw-ro...
@@ -2060,6 +2594,7 @@
 			    (opte & L2_S_PROT_W) != 0 &&
 			    (prot & VM_PROT_WRITE) == 0)
 				cpu_dcache_wb_range(va, PAGE_SIZE);
+#endif
 		} else {
 			/*
 			 * New mapping, or changing the backing page
@@ -2077,6 +2612,7 @@
 				simple_unlock(&opg->mdpage.pvh_slock);
 				oflags = pve->pv_flags;

+#ifdef PMAP_CACHE_VIVT
 				/*
 				 * If the old mapping was valid (ref/mod
 				 * emulation creates 'invalid' mappings
@@ -2095,6 +2631,7 @@
 						    (oflags & PVF_WRITE) == 0);
 					}
 				}
+#endif
 			} else
 			if ((pve = pool_get(&pmap_pv_pool, PR_NOWAIT)) == NULL){
 				if ((flags & PMAP_CANFAIL) == 0)
@@ -2138,6 +2675,7 @@
 			simple_unlock(&opg->mdpage.pvh_slock);
 			oflags = pve->pv_flags;

+#ifdef PMAP_CACHE_VIVT
 			if ((oflags & PVF_NC) == 0 && l2pte_valid(opte)) {
 				if (PV_BEEN_EXECD(oflags))
 					pmap_idcache_wbinv_range(pm, va,
@@ -2147,6 +2685,7 @@
 					pmap_dcache_wb_range(pm, va, PAGE_SIZE,
 					    TRUE, (oflags & PVF_WRITE) == 0);
 			}
+#endif
 			pool_put(&pmap_pv_pool, pve);
 		}
 	}
@@ -2255,7 +2794,7 @@
 	u_int cleanlist_idx, total, cnt;
 	struct {
 		vaddr_t va;
-		pt_entry_t *pte;
+		pt_entry_t *ptep;
 	} cleanlist[PMAP_REMOVE_CLEAN_LIST_SIZE];
 	u_int mappings, is_exec, is_refd;

@@ -2354,14 +2893,16 @@

 			if (cleanlist_idx < PMAP_REMOVE_CLEAN_LIST_SIZE) {
 				/* Add to the clean list. */
-				cleanlist[cleanlist_idx].pte = ptep;
+				cleanlist[cleanlist_idx].ptep = ptep;
 				cleanlist[cleanlist_idx].va =
 				    sva | (is_exec & 1);
 				cleanlist_idx++;
 			} else
 			if (cleanlist_idx == PMAP_REMOVE_CLEAN_LIST_SIZE) {
 				/* Nuke everything if needed. */
+#ifdef PMAP_CACHE_VIVT
 				pmap_idcache_wbinv_all(pm);
+#endif
 				pmap_tlb_flushID(pm);

 				/*
@@ -2370,7 +2911,7 @@
 				 */
 				for (cnt = 0;
 				     cnt < PMAP_REMOVE_CLEAN_LIST_SIZE; cnt++) {
-					*cleanlist[cnt].pte = 0;
+					*cleanlist[cnt].ptep = 0;
 				}
 				*ptep = 0;
 				PTE_SYNC(ptep);
@@ -2398,18 +2939,22 @@
 				if (pm->pm_cstate.cs_all != 0) {
 					vaddr_t clva = cleanlist[cnt].va & ~1;
 					if (cleanlist[cnt].va & 1) {
+#ifdef PMAP_CACHE_VIVT
 						pmap_idcache_wbinv_range(pm,
 						    clva, PAGE_SIZE);
+#endif
 						pmap_tlb_flushID_SE(pm, clva);
 					} else {
+#ifdef PMAP_CACHE_VIVT
 						pmap_dcache_wb_range(pm,
 						    clva, PAGE_SIZE, TRUE,
 						    FALSE);
+#endif
 						pmap_tlb_flushD_SE(pm, clva);
 					}
 				}
-				*cleanlist[cnt].pte = 0;
-				PTE_SYNC_CURRENT(pm, cleanlist[cnt].pte);
+				*cleanlist[cnt].ptep = 0;
+				PTE_SYNC_CURRENT(pm, cleanlist[cnt].ptep);
 			}

 			/*
@@ -2422,7 +2967,9 @@
 				cleanlist_idx = 0;
 			else {
 				cleanlist_idx = PMAP_REMOVE_CLEAN_LIST_SIZE + 1;
+#ifdef PMAP_CACHE_VIVT
 				pmap_idcache_wbinv_all(pm);
+#endif
 				pm->pm_remove_all = TRUE;
 			}
 		}
@@ -2447,6 +2994,11 @@
 {
 	struct l2_bucket *l2b;
 	pt_entry_t *ptep, opte;
+#ifdef PMAP_CACHE_VIPT
+	struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
+	struct vm_page *opg;
+#endif
+

 	NPDEBUG(PDB_KENTER,
 	    printf("pmap_kenter_pa: va 0x%08lx, pa 0x%08lx, prot 0x%x\n",
@@ -2458,17 +3010,55 @@
 	ptep = &l2b->l2b_kva[l2pte_index(va)];
 	opte = *ptep;

-	if (l2pte_valid(opte)) {
-		cpu_dcache_wbinv_range(va, PAGE_SIZE);
-		cpu_tlb_flushD_SE(va);
-		cpu_cpwait();
-	} else
-	if (opte == 0)
+	if (opte == 0) {
+		PMAPCOUNT(kenter_mappings);
 		l2b->l2b_occupancy++;
+	} else {
+		PMAPCOUNT(kenter_remappings);
+#ifdef PMAP_CACHE_VIPT
+		opg = PHYS_TO_VM_PAGE(l2pte_pa(opte));
+		if (opg) {
+			KASSERT(opg != pg);
+			simple_lock(&opg->mdpage.pvh_slock);
+			KASSERT(opg->mdpage.pvh_attrs & PVF_KENTRY);
+			if (PV_IS_EXEC_P(opg->mdpage.pvh_attrs)
+			    && !(opg->mdpage.pvh_attrs & PVF_NC)) {
+				if (opg->mdpage.pvh_list == NULL) {
+					opg->mdpage.pvh_attrs &= ~PVF_EXEC;
+					PMAPCOUNT(exec_discarded_kremove);
+				} else {
+					pmap_syncicache_page(opg);
+					PMAPCOUNT(exec_synced_kremove);
+				}
+			}
+			KASSERT(opg->mdpage.pvh_attrs | (PVF_COLORED|PVF_NC));
+			opg->mdpage.pvh_attrs &= ~PVF_KENTRY;
+			pmap_vac_me_harder(opg, NULL, 0);
+			simple_unlock(&opg->mdpage.pvh_slock);
+		}
+#endif
+		if (l2pte_valid(opte)) {
+#ifdef PMAP_CACHE_VIVT
+			cpu_dcache_wbinv_range(va, PAGE_SIZE);
+#endif
+			cpu_tlb_flushD_SE(va);
+			cpu_cpwait();
+		}
+	}

 	*ptep = L2_S_PROTO | pa | L2_S_PROT(PTE_KERNEL, prot) |
 	    pte_l2_s_cache_mode;
 	PTE_SYNC(ptep);
+
+#ifdef PMAP_CACHE_VIPT
+	if (pg) {
+		simple_lock(&pg->mdpage.pvh_slock);
+		KASSERT((pg->mdpage.pvh_attrs & PVF_KENTRY) == 0);
+		pg->mdpage.pvh_attrs |= PVF_KENTRY;
+		pmap_vac_me_harder(pg, NULL, va);
+		simple_unlock(&pg->mdpage.pvh_slock);
+	}
+#endif
 }

 void
@@ -2478,6 +3068,11 @@
 	pt_entry_t *ptep, *sptep, opte;
 	vaddr_t next_bucket, eva;
 	u_int mappings;
+#ifdef PMAP_CACHE_VIPT
+	struct vm_page *opg;
+#endif
+
+	PMAPCOUNT(kenter_unmappings);

 	NPDEBUG(PDB_KREMOVE, printf("pmap_kremove: va 0x%08lx, len 0x%08lx\n",
 	    va, len));
@@ -2497,8 +3092,32 @@

 		while (va < next_bucket) {
 			opte = *ptep;
+#ifdef PMAP_CACHE_VIPT
+			opg = PHYS_TO_VM_PAGE(l2pte_pa(opte));
+			if (opg) {
+				simple_lock(&opg->mdpage.pvh_slock);
+				KASSERT(opg->mdpage.pvh_attrs & PVF_KENTRY);
+				if (PV_IS_EXEC_P(opg->mdpage.pvh_attrs)
+				    && !(opg->mdpage.pvh_attrs & PVF_NC)) {
+					if (opg->mdpage.pvh_list == NULL) {
+						opg->mdpage.pvh_attrs &=
+						    ~PVF_EXEC;
+						PMAPCOUNT(exec_discarded_kremove);
+					} else {
+						pmap_syncicache_page(opg);
+						PMAPCOUNT(exec_synced_kremove);
+					}
+				}
+				KASSERT(opg->mdpage.pvh_attrs | (PVF_COLORED|PVF_NC));
+				opg->mdpage.pvh_attrs &= ~PVF_KENTRY;
+				pmap_vac_me_harder(opg, NULL, 0);
+				simple_unlock(&opg->mdpage.pvh_slock);
+			}
+#endif
 			if (l2pte_valid(opte)) {
+#ifdef PMAP_CACHE_VIVT
 				cpu_dcache_wbinv_range(va, PAGE_SIZE);
+#endif
 				cpu_tlb_flushD_SE(va);
 			}
 			if (opte) {
@@ -2582,6 +3201,7 @@
 	pt_entry_t *ptep, pte;
 	vaddr_t next_bucket;
 	u_int flags;
+	u_int clr_mask;
 	int flush;

 	NPDEBUG(PDB_PROTECT,
@@ -2604,14 +3224,9 @@
 	PMAP_MAP_TO_HEAD_LOCK();
 	pmap_acquire_pmap_lock(pm);

-	/*
-	 * OK, at this point, we know we're doing write-protect operation.
-	 * If the pmap is active, write-back the range.
-	 */
-	pmap_dcache_wb_range(pm, sva, eva - sva, FALSE, FALSE);
-
 	flush = ((eva - sva) >= (PAGE_SIZE * 4)) ? 0 : -1;
 	flags = 0;
+	clr_mask = PVF_WRITE | ((prot & VM_PROT_EXECUTE) ? 0 : PVF_EXEC);

 	while (sva < eva) {
 		next_bucket = L2_NEXT_BUCKET(sva);
@@ -2627,10 +3242,21 @@
 		ptep = &l2b->l2b_kva[l2pte_index(sva)];

 		while (sva < next_bucket) {
-			if ((pte = *ptep) != 0 && (pte & L2_S_PROT_W) != 0) {
+			pte = *ptep;
+			if (l2pte_valid(pte) != 0 && (pte & L2_S_PROT_W) != 0) {
 				struct vm_page *pg;
 				u_int f;

+#ifdef PMAP_CACHE_VIVT
+				/*
+				 * OK, at this point, we know we're doing
+				 * write-protect operation.  If the pmap is
+				 * active, write-back the page.
+				 */
+				pmap_dcache_wb_range(pm, sva, PAGE_SIZE,
+				    FALSE, FALSE);
+#endif
+
 				pg = PHYS_TO_VM_PAGE(l2pte_pa(pte));
 				pte &= ~L2_S_PROT_W;
 				*ptep = pte;
@@ -2639,7 +3265,7 @@
 				if (pg != NULL) {
 					simple_lock(&pg->mdpage.pvh_slock);
 					f = pmap_modify_pv(pg, pm, sva,
-					    PVF_WRITE, 0);
+					    clr_mask, 0);
 					pmap_vac_me_harder(pg, pm, sva);
 					simple_unlock(&pg->mdpage.pvh_slock);
 				} else
@@ -2682,11 +3308,20 @@
 	    pg, VM_PAGE_TO_PHYS(pg), prot));

 	switch(prot) {
-	case VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE:
-	case VM_PROT_READ|VM_PROT_WRITE:
 		return;
+	case VM_PROT_READ|VM_PROT_WRITE:
+#if defined(PMAP_CHECK_VIPT) && defined(PMAP_APX)
+		pmap_clearbit(pg, PVF_EXEC);
+		break;
+#endif
+	case VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE:
+		break;

 	case VM_PROT_READ:
+#if defined(PMAP_CHECK_VIPT) && defined(PMAP_APX)
+		pmap_clearbit(pg, PVF_WRITE|PVF_EXEC);
+		break;
+#endif
 	case VM_PROT_READ|VM_PROT_EXECUTE:
 		pmap_clearbit(pg, PVF_WRITE);
 		break;
@@ -2989,10 +3624,13 @@
 pmap_collect(pmap_t pm)
 {

+#ifdef PMAP_CACHE_VIVT
 	pmap_idcache_wbinv_all(pm);
+#endif
 	pm->pm_remove_all = TRUE;
 	pmap_do_remove(pm, VM_MIN_ADDRESS, VM_MAX_ADDRESS, 1);
 	pmap_update(pm);
+	PMAPCOUNT(collects);
 }

 /*
@@ -3062,6 +3700,8 @@

 	pmap_set_pcb_pagedir(pm, pcb);

+	PMAPCOUNT(activations);
+
 	if (l == curlwp) {
 		u_int cur_dacr, cur_ttb;

@@ -3153,6 +3793,8 @@
 		pm->pm_cstate.cs_all = PMAP_CACHE_STATE_ALL;
 	}

+	PMAPCOUNT(updates);
+
 	/*
 	 * make sure TLB/cache operations have completed.
 	 */
@@ -3169,7 +3811,9 @@
 	 * to pmap_remove(). We can make life much simpler by flushing
 	 * the cache now, and deferring TLB invalidation to pmap_update().
 	 */
+#ifdef PMAP_CACHE_VIVT
 	pmap_idcache_wbinv_all(pm);
+#endif
 	pm->pm_remove_all = TRUE;
 }

@@ -3268,6 +3912,33 @@
 	simple_unlock(&pm->pm_lock);
 }

+#if ARM_MMU_V6 > 0
+
+static struct evcnt pmap_prefer_nochange_ev =
+    EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "pmap prefer", "nochange");
+static struct evcnt pmap_prefer_change_ev =
+    EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "pmap prefer", "change");
+
+EVCNT_ATTACH_STATIC(pmap_prefer_change_ev);
+EVCNT_ATTACH_STATIC(pmap_prefer_nochange_ev);
+
+void
+pmap_prefer(vaddr_t hint, vaddr_t *vap, int td)
+{
+	vsize_t mask = arm_cache_prefer_mask | (PAGE_SIZE - 1);
+	vaddr_t va = *vap;
+	vaddr_t diff = (hint - va) & mask;
+	if (diff == 0) {
+		pmap_prefer_nochange_ev.ev_count++;
+	} else {
+		pmap_prefer_change_ev.ev_count++;
+		if (__predict_false(td))
+			va -= mask + 1;
+		*vap = va + diff;
+	}
+}
+#endif /* ARM_MMU_V6 */
+
 /*
  * pmap_zero_page()
  * 
@@ -3276,13 +3947,22 @@
  * StrongARM accesses to non-cached pages are non-burst making writing
  * _any_ bulk data very slow.
  */
-#if (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0
+#if (ARM_MMU_GENERIC + ARM_MMU_SA1 + ARM_MMU_V6) != 0
 void
 pmap_zero_page_generic(paddr_t phys)
 {
-#ifdef DEBUG
+#if defined(PMAP_CACHE_VIPT) || defined(DEBUG)
 	struct vm_page *pg = PHYS_TO_VM_PAGE(phys);
+#endif
+#ifdef PMAP_CACHE_VIPT
+	/* Choose the last page color it had, if any */
+	const vsize_t va_offset = pg->mdpage.pvh_attrs & arm_cache_prefer_mask;
+#else
+	const vsize_t va_offset = 0;
+#endif
+	pt_entry_t * const ptep = &cdst_pte[va_offset >> PGSHIFT];

+#ifdef DEBUG
 	if (pg->mdpage.pvh_list != NULL)
 		panic("pmap_zero_page: page has mappings");
 #endif
@@ -3293,15 +3973,37 @@
 	 * Hook in the page, zero it, and purge the cache for that
 	 * zeroed page. Invalidate the TLB as needed.
 	 */
-	*cdst_pte = L2_S_PROTO | phys |
+	*ptep = L2_S_PROTO | phys |
 	    L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) | pte_l2_s_cache_mode;
-	PTE_SYNC(cdst_pte);
-	cpu_tlb_flushD_SE(cdstp);
+	PTE_SYNC(ptep);
+	cpu_tlb_flushD_SE(cdstp + va_offset);
 	cpu_cpwait();
-	bzero_page(cdstp);
-	cpu_dcache_wbinv_range(cdstp, PAGE_SIZE);
+	bzero_page(cdstp + va_offset);
+	/*
+	 * Unmap the page.
+	 */
+	*ptep = 0;
+	PTE_SYNC(ptep);
+	cpu_tlb_flushD_SE(cdstp + va_offset);
+#ifdef PMAP_CACHE_VIVT
+	cpu_dcache_wbinv_range(cdstp + va_offset, PAGE_SIZE);
+#endif
+#ifdef PMAP_CACHE_VIPT
+	/*
+	 * This page is now cache resident so it now has a page color.
+	 * Any contents have been obliterated so clear the EXEC flag.
+	 */
+	if (!pmap_is_page_colored_p(pg)) {
+		PMAPCOUNT(vac_color_new);
+		pg->mdpage.pvh_attrs |= PVF_COLORED;
+	}
+	if (PV_IS_EXEC_P(pg->mdpage.pvh_attrs)) {
+		pg->mdpage.pvh_attrs &= ~PVF_EXEC;
+		PMAPCOUNT(exec_discarded_zero);
+	}
+#endif
 }
-#endif /* (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0 */
+#endif /* (ARM_MMU_GENERIC + ARM_MMU_SA1 + ARM_MMU_V6) != 0 */

 #if ARM_MMU_XSCALE == 1
 void
@@ -3343,10 +4045,19 @@
 	unsigned int i;
 	int *ptr;
 	boolean_t rv = TRUE;
+#if defined(PMAP_CACHE_VIPT) || defined(DEBUG)
+	struct vm_page * const pg = PHYS_TO_VM_PAGE(phys);
+#endif
+#ifdef PMAP_CACHE_VIPT
+	/* Choose the last page color it had, if any */
+	const vsize_t va_offset = pg->mdpage.pvh_attrs & arm_cache_prefer_mask;
+#else
+	const vsize_t va_offset = 0;
+#endif
+	pt_entry_t * const ptep = &csrc_pte[va_offset >> PGSHIFT];
+
+
 #ifdef DEBUG
-	struct vm_page *pg;
-	
-	pg = PHYS_TO_VM_PAGE(phys);
 	if (pg->mdpage.pvh_list != NULL)
 		panic("pmap_pageidlezero: page has mappings");
 #endif
@@ -3357,13 +4068,13 @@
 	 * Hook in the page, zero it, and purge the cache for that
 	 * zeroed page. Invalidate the TLB as needed.
 	 */
-	*cdst_pte = L2_S_PROTO | phys |
+	*ptep = L2_S_PROTO | phys |
 	    L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) | pte_l2_s_cache_mode;
-	PTE_SYNC(cdst_pte);
-	cpu_tlb_flushD_SE(cdstp);
+	PTE_SYNC(ptep);
+	cpu_tlb_flushD_SE(cdstp + va_offset);
 	cpu_cpwait();

-	for (i = 0, ptr = (int *)cdstp;
+	for (i = 0, ptr = (int *)(cdstp + va_offset);
 			i < (PAGE_SIZE / sizeof(int)); i++) {
 		if (sched_whichqs != 0) {
 			/*
@@ -3378,12 +4089,33 @@
 		*ptr++ = 0;
 	}

+#ifdef PMAP_CACHE_VIVT
 	if (rv)
 		/* 
 		 * if we aborted we'll rezero this page again later so don't
 		 * purge it unless we finished it
 		 */
 		cpu_dcache_wbinv_range(cdstp, PAGE_SIZE);
+#elif defined(PMAP_CACHE_VIPT)
+	/*
+	 * This page is now cache resident so it now has a page color.
+	 * Any contents have been obliterated so clear the EXEC flag.
+	 */
+	if (!pmap_is_page_colored_p(pg)) {
+		PMAPCOUNT(vac_color_new);
+		pg->mdpage.pvh_attrs |= PVF_COLORED;
+	}
+	if (PV_IS_EXEC_P(pg->mdpage.pvh_attrs)) {
+		pg->mdpage.pvh_attrs &= ~PVF_EXEC;
+		PMAPCOUNT(exec_discarded_zero);
+	}
+#endif
+	/*
+	 * Unmap the page.
+	 */
+	*ptep = 0;
+	PTE_SYNC(ptep);
+	cpu_tlb_flushD_SE(cdstp + va_offset);

 	return (rv);
 }
@@ -3395,18 +4127,32 @@
  * hook points. The same comment regarding cachability as in
  * pmap_zero_page also applies here.
  */
-#if (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0
+#if (ARM_MMU_GENERIC + ARM_MMU_SA1 + ARM_MMU_V6) != 0
 void
 pmap_copy_page_generic(paddr_t src, paddr_t dst)
 {
-	struct vm_page *src_pg = PHYS_TO_VM_PAGE(src);
-#ifdef DEBUG
-	struct vm_page *dst_pg = PHYS_TO_VM_PAGE(dst);
+	struct vm_page * const src_pg = PHYS_TO_VM_PAGE(src);
+#if defined(PMAP_CACHE_VIPT) || defined(DEBUG)
+	struct vm_page * const dst_pg = PHYS_TO_VM_PAGE(dst);
+#endif
+#ifdef PMAP_CACHE_VIPT
+	const vsize_t src_va_offset = src_pg->mdpage.pvh_attrs & arm_cache_prefer_mask;
+	const vsize_t dst_va_offset = dst_pg->mdpage.pvh_attrs & arm_cache_prefer_mask;
+#else
+	const vsize_t src_va_offset = 0;
+	const vsize_t dst_va_offset = 0;
+#endif
+	pt_entry_t * const src_ptep = &csrc_pte[src_va_offset >> PGSHIFT];
+	pt_entry_t * const dst_ptep = &cdst_pte[dst_va_offset >> PGSHIFT];

+#ifdef DEBUG
 	if (dst_pg->mdpage.pvh_list != NULL)
 		panic("pmap_copy_page: dst page has mappings");
 #endif

+#ifdef PMAP_CACHE_VIPT
+	KASSERT(src_pg->mdpage.pvh_attrs & (PVF_COLORED|PVF_NC));
+#endif
 	KDASSERT((src & PGOFSET) == 0);
 	KDASSERT((dst & PGOFSET) == 0);

@@ -3416,28 +4162,64 @@
 	 * be created while we have a potentially aliased mapping.
 	 */
 	simple_lock(&src_pg->mdpage.pvh_slock);
+#ifdef PMAP_CACHE_VIVT
 	(void) pmap_clean_page(src_pg->mdpage.pvh_list, TRUE);
+#endif

 	/*
 	 * Map the pages into the page hook points, copy them, and purge
 	 * the cache for the appropriate page. Invalidate the TLB
 	 * as required.
 	 */
-	*csrc_pte = L2_S_PROTO | src |
-	    L2_S_PROT(PTE_KERNEL, VM_PROT_READ) | pte_l2_s_cache_mode;
-	PTE_SYNC(csrc_pte);
-	*cdst_pte = L2_S_PROTO | dst |
+	*src_ptep = L2_S_PROTO
+	    | src
+#ifdef PMAP_CACHE_VIPT
+	    | ((src_pg->mdpage.pvh_attrs & PVF_NC) ? 0 : pte_l2_s_cache_mode)
+#endif
+#ifdef PMAP_CACHE_VIVT
+	    | pte_l2_s_cache_mode
+#endif
+	    | L2_S_PROT(PTE_KERNEL, VM_PROT_READ);
+	*dst_ptep = L2_S_PROTO | dst |
 	    L2_S_PROT(PTE_KERNEL, VM_PROT_WRITE) | pte_l2_s_cache_mode;
-	PTE_SYNC(cdst_pte);
-	cpu_tlb_flushD_SE(csrcp);
-	cpu_tlb_flushD_SE(cdstp);
+	PTE_SYNC(src_ptep);
+	PTE_SYNC(dst_ptep);
+	cpu_tlb_flushD_SE(csrcp + src_va_offset);
+	cpu_tlb_flushD_SE(cdstp + dst_va_offset);
 	cpu_cpwait();
-	bcopy_page(csrcp, cdstp);
-	cpu_dcache_inv_range(csrcp, PAGE_SIZE);
+	bcopy_page(csrcp + src_va_offset, cdstp + dst_va_offset);
+#ifdef PMAP_CACHE_VIVT
+	cpu_dcache_inv_range(csrcp + src_va_offset, PAGE_SIZE);
+#endif
 	simple_unlock(&src_pg->mdpage.pvh_slock); /* cache is safe again */
-	cpu_dcache_wbinv_range(cdstp, PAGE_SIZE);
+#ifdef PMAP_CACHE_VIVT
+	cpu_dcache_wbinv_range(cdstp + dst_va_offset, PAGE_SIZE);
+#endif
+	/*
+	 * Unmap the pages.
+	 */
+	*src_ptep = 0;
+	*dst_ptep = 0;
+	PTE_SYNC(src_ptep);
+	PTE_SYNC(dst_ptep);
+	cpu_tlb_flushD_SE(csrcp + src_va_offset);
+	cpu_tlb_flushD_SE(cdstp + dst_va_offset);
+#ifdef PMAP_CACHE_VIPT
+	/*
+	 * Now that the destination page is in the cache, mark it as colored.
+	 * If this was an exec page, discard it.
+	 */
+	if (!pmap_is_page_colored_p(dst_pg)) {
+		PMAPCOUNT(vac_color_new);
+		dst_pg->mdpage.pvh_attrs |= PVF_COLORED;
+	}
+	if (PV_IS_EXEC_P(dst_pg->mdpage.pvh_attrs)) {
+		dst_pg->mdpage.pvh_attrs &= ~PVF_EXEC;
+		PMAPCOUNT(exec_discarded_copy);
+	}
+#endif
 }
-#endif /* (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0 */
+#endif /* (ARM_MMU_GENERIC + ARM_MMU_SA1 + ARM_MMU_V6) != 0 */

 #if ARM_MMU_XSCALE == 1
 void
@@ -3460,7 +4242,9 @@
 	 * be created while we have a potentially aliased mapping.
 	 */
 	simple_lock(&src_pg->mdpage.pvh_slock);
+#ifdef PMAP_CACHE_VIVT
 	(void) pmap_clean_page(src_pg->mdpage.pvh_list, TRUE);
+#endif

 	/*
 	 * Map the pages into the page hook points, copy them, and purge
@@ -3517,11 +4301,40 @@
 		if (pg == NULL)
 			return (1);
 		pa = VM_PAGE_TO_PHYS(pg);
+#ifdef PMAP_CACHE_VIPT
+		/*
+		 * This new page must not have any mappings.  However, it might
+		 * have previously used and therefore present in the cache.  If
+		 * it doesn't have the desired color, we have to flush it from
+		 * the cache.  And while we are at it, make sure to clear its
+		 * EXEC status.
+		 */
+		KASSERT(!(pg->mdpage.pvh_attrs & PVF_KENTRY));
+		KASSERT(pg->mdpage.pvh_list == NULL);
+		if (pmap_is_page_colored_p(pg)) {
+			if ((va ^ pg->mdpage.pvh_attrs) & arm_cache_prefer_mask) {
+				pmap_flush_page(pg);
+				PMAPCOUNT(vac_color_change);
+			} else {
+				PMAPCOUNT(vac_color_reuse);
+			}
+		} else {
+			PMAPCOUNT(vac_color_new);
+		}
+		if (PV_IS_EXEC_P(pg->mdpage.pvh_attrs))
+			PMAPCOUNT(exec_discarded_kremove);
+		/*
+		 * We'll pretend this page was entered by pmap_kenter_pa
+		 */
+		pg->mdpage.pvh_attrs &= (PAGE_SIZE - 1) & ~PVF_EXEC;
+		pg->mdpage.pvh_attrs |= va | PVF_KENTRY | PVF_COLORED | PVF_REF | PVF_MOD;
+#endif
 	}

 	if (pap)
 		*pap = pa;

+	PMAPCOUNT(pt_mappings);
 	l2b = pmap_get_l2_bucket(pmap_kernel(), va);
 	KDASSERT(l2b != NULL);

@@ -3846,7 +4659,7 @@
 	paddr_t pa;
 	vaddr_t va;
 	vsize_t size;
-	int l1idx, l2idx, l2next = 0;
+	int nptes, l1idx, l2idx, l2next = 0;

 	/*
 	 * Initialise the kernel pmap object
@@ -3957,9 +4770,19 @@
 	virtual_avail = vstart;
 	virtual_end = vend;

-	pmap_alloc_specials(&virtual_avail, 1, &csrcp, &csrc_pte);
+#ifdef PMAP_CACHE_VIPT
+	/*
+	 * If we have a VIPT cache, we need one page/pte per possible alias
+	 * page so we won't violate cache aliasing rules.
+	 */
+	virtual_avail = (virtual_avail + arm_cache_prefer_mask) & ~arm_cache_prefer_mask; 
+	nptes = (arm_cache_prefer_mask >> PGSHIFT) + 1;
+#else
+	nptes = 1;
+#endif
+	pmap_alloc_specials(&virtual_avail, nptes, &csrcp, &csrc_pte);
 	pmap_set_pt_cache_mode(kernel_l1pt, (vaddr_t)csrc_pte);
-	pmap_alloc_specials(&virtual_avail, 1, &cdstp, &cdst_pte);
+	pmap_alloc_specials(&virtual_avail, nptes, &cdstp, &cdst_pte);
 	pmap_set_pt_cache_mode(kernel_l1pt, (vaddr_t)cdst_pte);
 	pmap_alloc_specials(&virtual_avail, 1, (void *)&memhook, NULL);
 	pmap_alloc_specials(&virtual_avail, round_page(MSGBUFSIZE) / PAGE_SIZE,
@@ -4650,7 +5473,7 @@
 void		(*pmap_copy_page_func)(paddr_t, paddr_t);
 void		(*pmap_zero_page_func)(paddr_t);

-#if (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0
+#if (ARM_MMU_GENERIC + ARM_MMU_SA1 + ARM_MMU_V6) != 0
 void
 pmap_pte_init_generic(void)
 {
@@ -4674,9 +5497,15 @@
 		pte_l2_l_cache_mode_pt = L2_B|L2_C;
 		pte_l2_s_cache_mode_pt = L2_B|L2_C;
 	} else {
+#if ARM_MMU_V6 > 1
+		pte_l1_s_cache_mode_pt = L1_S_B|L1_S_C; /* arm116 errata 399234 */
+		pte_l2_l_cache_mode_pt = L2_B|L2_C; /* arm116 errata 399234 */
+		pte_l2_s_cache_mode_pt = L2_B|L2_C; /* arm116 errata 399234 */
+#else
 		pte_l1_s_cache_mode_pt = L1_S_C;
 		pte_l2_l_cache_mode_pt = L2_C;
 		pte_l2_s_cache_mode_pt = L2_C;
+#endif
 	}

 	pte_l2_s_prot_u = L2_S_PROT_U_generic;
@@ -4728,7 +5557,7 @@
 	pte_l2_s_cache_mode_pt = L2_C;
 }
 #endif /* CPU_ARM9 */
-#endif /* (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0 */
+#endif /* (ARM_MMU_GENERIC + ARM_MMU_SA1 + ARM_MMU_V6) != 0 */

 #if defined(CPU_ARM10)
 void
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/conf/files.arm sys/arch/arm/conf/files.arm
--- ../../netbsd_40/src/sys/arch/arm/conf/files.arm	2007-02-21 10:36:03.000000000 -0800
+++ sys/arch/arm/conf/files.arm	2007-09-25 10:55:22.000000000 -0700
@@ -7,6 +7,7 @@
 defflag	opt_cputypes.h		CPU_ARM2 CPU_ARM250 CPU_ARM3
 defflag	opt_cputypes.h		CPU_ARM6 CPU_ARM7 CPU_ARM7TDMI CPU_ARM8
 				CPU_ARM9 CPU_ARM9E CPU_ARM10 CPU_ARM11
+				CPU_ARM1136
 				CPU_SA110 CPU_SA1100 CPU_SA1110 CPU_IXP12X0
 				CPU_XSCALE_80200 CPU_XSCALE_80321
 				CPU_XSCALE_PXA250 CPU_XSCALE_PXA270
@@ -57,7 +58,7 @@
 file	arch/arm/arm/fiq_subr.S

 # mainbus files
-device	mainbus { [base = -1], [dack = -1], [irq = -1] }
+device	mainbus { [base = -1], [size = 0], [dack = -1], [irq = -1] }
 attach	mainbus at root
 file	arch/arm/mainbus/mainbus.c		mainbus & arm32
 file	arch/arm/mainbus/mainbus_io.c		mainbus & arm32
@@ -91,7 +92,8 @@
 file	arch/arm/arm/cpufunc_asm_arm8.S		cpu_arm8
 file	arch/arm/arm/cpufunc_asm_arm9.S		cpu_arm9
 file	arch/arm/arm/cpufunc_asm_arm10.S	cpu_arm9e | cpu_arm10
-file	arch/arm/arm/cpufunc_asm_arm11.S	cpu_arm11
+file	arch/arm/arm/cpufunc_asm_arm11.S	cpu_arm11 | cpu_arm1136
+file	arch/arm/arm/cpufunc_asm_arm1136.S	cpu_arm1136
 file	arch/arm/arm/cpufunc_asm_armv4.S	cpu_arm9 | cpu_arm9e |
 							cpu_arm10 |
 							cpu_sa110 |
@@ -102,9 +104,11 @@
 							cpu_xscale_80321 |
 							cpu_xscale_ixp425 |
 							cpu_xscale_pxa250 |
-							cpu_xscale_pxa270
-file	arch/arm/arm/cpufunc_asm_armv5.S	cpu_arm10 | cpu_arm11
+							cpu_xscale_pxa270 |
+							cpu_arm1136
+file	arch/arm/arm/cpufunc_asm_armv5.S	cpu_arm10
 file	arch/arm/arm/cpufunc_asm_armv5_ec.S	cpu_arm9e | cpu_arm10
+file	arch/arm/arm/cpufunc_asm_armv6.S	cpu_arm11 | cpu_arm1136
 file	arch/arm/arm/cpufunc_asm_sa1.S		cpu_sa110 | cpu_sa1100 |
 							cpu_sa1110 |
 							cpu_ixp12x0
@@ -143,6 +147,9 @@
 file	arch/arm/arm32/vm_machdep.c		arm32
 file	arch/arm/arm32/atomic.S			arm32

+# files less common to arm32 implementations...
+file	arch/arm/arm32/arm1136_pmc.c		arm1136_pmc
+
 # arm32 library functions
 file	arch/arm/arm32/bcopy_page.S		arm32

diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/include/arm32/arm1136_pmc.h sys/arch/arm/include/arm32/arm1136_pmc.h
--- ../../netbsd_40/src/sys/arch/arm/include/arm32/arm1136_pmc.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/include/arm32/arm1136_pmc.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,64 @@
+/*	$Id$	*/
+
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * defines and such for amd1136 Performance Moniitor Counters
+ */
+
+#ifndef _ARM1136_PMC_H
+#define _ARM1136_PMC_H
+
+#define BITS(hi,lo)	((uint32_t)(~((~0ULL)<<((hi)+1)))&((~0)<<(lo)))
+#define BIT(n)		((uint32_t)(1 << (n)))
+
+#define ARM1136_PMCCTL_E	BIT(0)		/* enable all three counters */
+#define ARM1136_PMCCTL_P	BIT(1)		/* reset both Count Registers to zero */
+#define ARM1136_PMCCTL_C	BIT(2)		/* reset the Cycle Counter Register to zero */
+#define ARM1136_PMCCTL_D	BIT(3)		/* cycle count divide by 64 */
+#define ARM1136_PMCCTL_EC0	BIT(4)		/* Enable Counter Register 0 interrupt */
+#define ARM1136_PMCCTL_EC1	BIT(5)		/* Enable Counter Register 1 interrupt */
+#define ARM1136_PMCCTL_ECC	BIT(6)		/* Enable Cycle Counter interrupt */
+#define ARM1136_PMCCTL_SBZa	BIT(7)		/* UNP/SBZ */
+#define ARM1136_PMCCTL_CR0	BIT(8)		/* Count Register 0 overflow flag */
+#define ARM1136_PMCCTL_CR1	BIT(9)		/* Count Register 1 overflow flag */
+#define ARM1136_PMCCTL_CCR	BIT(10)		/* Cycle Count Register overflow flag */
+#define ARM1136_PMCCTL_X	BIT(11)		/* Enable Export of the events to the event bus */
+#define ARM1136_PMCCTL_EVT1	BITS(19,12)	/* source of events for Count Register 1 */
+#define ARM0036_PMCCTL_EVT0	BITS(27,20)	/* source of events for Count Register 0 */
+#define ARM0036_PMCCTL_SBZb	BITS(31,28)	/* UNP/SBZ */
+#define ARM0036_PMCCTL_SBZ	\
+		(ARM1136_PMCCTL_SBZa | ARM0036_PMCCTL_SBZb)
+
+
+extern void arm1136_pmc_ccnt_init(void);
+
+#endif	/* _ARM1136_PMC_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/include/arm32/pmap.h sys/arch/arm/include/arm32/pmap.h
--- ../../netbsd_40/src/sys/arch/arm/include/arm32/pmap.h	2005-12-24 12:06:52.000000000 -0800
+++ sys/arch/arm/include/arm32/pmap.h	2007-09-25 10:55:22.000000000 -0700
@@ -65,6 +65,11 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */

+/*
+ * armv6 and VIPT cache support by 3am Software Foundry,
+ * Copyright (c) 2007 Danger Inc
+ */
+
 #ifndef	_ARM32_PMAP_H_
 #define	_ARM32_PMAP_H_

@@ -221,6 +226,8 @@
 #define	PVF_EXEC	0x10		/* mapping is executable */
 #define	PVF_UNC		0x20		/* mapping is 'user' non-cacheable */
 #define	PVF_KNC		0x40		/* mapping is 'kernel' non-cacheable */
+#define	PVF_COLORED	0x80		/* page has a color */
+#define	PVF_KENTRY	0x0100		/* page entered via pmap_kenter_pa */
 #define	PVF_NC		(PVF_UNC|PVF_KNC)

 /*
@@ -242,6 +249,8 @@
 	(((pg)->mdpage.pvh_attrs & PVF_MOD) != 0)
 #define	pmap_is_referenced(pg)	\
 	(((pg)->mdpage.pvh_attrs & PVF_REF) != 0)
+#define	pmap_is_page_colored_p(pg)	\
+	(((pg)->mdpage.pvh_attrs & PVF_COLORED) != 0)

 #define	pmap_copy(dp, sp, da, l, sa)	/* nothing */

@@ -257,6 +266,11 @@
 #define	PMAP_NEED_PROCWR
 #define PMAP_GROWKERNEL		/* turn on pmap_growkernel interface */

+#if ARM_MMU_V6 > 0
+#define	PMAP_PREFER(hint, vap, sz, td)	pmap_prefer((hint), (vap), (td))
+void	pmap_prefer(vaddr_t, vaddr_t *, int);
+#endif
+
 /* Functions we use internally. */
 void	pmap_bootstrap(pd_entry_t *, vaddr_t, vaddr_t);

@@ -341,7 +355,7 @@
  * we need to do PTE syncs.  If only SA-1 is configured, then evaluate
  * this at compile time.
  */
-#if (ARM_MMU_SA1 == 1) && (ARM_NMMUS == 1)
+#if (ARM_MMU_SA1 == 1 || ARM_MMU_V6 == 1) && (ARM_NMMUS == 1)
 #define	PMAP_NEEDS_PTE_SYNC	1
 #define	PMAP_INCLUDE_PTE_SYNC
 #elif (ARM_MMU_SA1 == 0)
@@ -378,7 +392,7 @@
 #define	l1pte_fpage_p(pde)	(((pde) & L1_TYPE_MASK) == L1_TYPE_F)

 #define l2pte_index(v)		(((v) & L2_ADDR_BITS) >> L2_S_SHIFT)
-#define	l2pte_valid(pte)	((pte) != 0)
+#define	l2pte_valid(pte)	(((pte) & L2_TYPE_MASK) != L2_TYPE_INV)
 #define	l2pte_pa(pte)		((pte) & L2_S_FRAME)
 #define l2pte_minidata(pte)	(((pte) & \
 				 (L2_B | L2_C | L2_XSCALE_T_TEX(TEX_XSCALE_X)))\
@@ -399,7 +413,7 @@

 /************************* ARM MMU configuration *****************************/

-#if (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0
+#if (ARM_MMU_GENERIC + ARM_MMU_SA1 + ARM_MMU_V6) != 0
 void	pmap_copy_page_generic(paddr_t, paddr_t);
 void	pmap_zero_page_generic(paddr_t);

@@ -460,9 +474,14 @@
 /*****************************************************************************/

 /*
- * tell MI code that the cache is virtually-indexed *and* virtually-tagged.
+ * tell MI code whether the cache is virtually-indexed and virtually-tagged
+ * or vitually-indexed and physically tagged.
  */
+#if ARM_MMU_V6 > 0
+#define PMAP_CACHE_VIPT
+#else
 #define PMAP_CACHE_VIVT
+#endif

 /*
  * Definitions for MMU domains
@@ -532,7 +551,7 @@

 #define	pmap_copy_page(s, d)	(*pmap_copy_page_func)((s), (d))
 #define	pmap_zero_page(d)	(*pmap_zero_page_func)((d))
-#elif (ARM_MMU_GENERIC + ARM_MMU_SA1) != 0
+#elif (ARM_MMU_GENERIC + ARM_MMU_SA1 + ARM_MMU_V6) != 0
 #define	L2_S_PROT_U		L2_S_PROT_U_generic
 #define	L2_S_PROT_W		L2_S_PROT_W_generic
 #define	L2_S_PROT_MASK		L2_S_PROT_MASK_generic
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/include/arm32/vmparam.h sys/arch/arm/include/arm32/vmparam.h
--- ../../netbsd_40/src/sys/arch/arm/include/arm32/vmparam.h	2007-02-21 10:31:42.000000000 -0800
+++ sys/arch/arm/include/arm32/vmparam.h	2007-09-25 10:55:22.000000000 -0700
@@ -122,6 +122,16 @@
 #define	krw_mappings	k_u.s_mappings[1]
 #define	k_mappings	k_u.i_mappings
 };
+/*
+ * Set the default color of each page.
+ */
+#if ARM_MMU_V6 > 0
+#define	VM_MDPAGE_PVH_ATTRS_INIT(pg) \
+	(pg)->mdpage.pvh_attrs = (pg)->phys_addr & arm_cache_prefer_mask
+#else
+#define	VM_MDPAGE_PVH_ATTRS_INIT(pg) \
+	(pg)->mdpage.pvh_attrs = 0
+#endif

 #define	VM_MDPAGE_INIT(pg)						\
 do {									\
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/include/armreg.h sys/arch/arm/include/armreg.h
--- ../../netbsd_40/src/sys/arch/arm/include/armreg.h	2007-02-21 10:36:02.000000000 -0800
+++ sys/arch/arm/include/armreg.h	2007-09-25 10:55:22.000000000 -0700
@@ -314,6 +314,7 @@
 #define	CPU_CT_xSIZE_M		(1U << 2)		/* multiplier */
 #define	CPU_CT_xSIZE_ASSOC(x)	(((x) >> 3) & 0x7)	/* associativity */
 #define	CPU_CT_xSIZE_SIZE(x)	(((x) >> 6) & 0x7)	/* size */
+#define	CPU_CT_xSIZE_P		(1U << 11)		/* page-color */

 /* Fault status register definitions */

diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/include/cpuconf.h sys/arch/arm/include/cpuconf.h
--- ../../netbsd_40/src/sys/arch/arm/include/cpuconf.h	2007-02-21 10:36:02.000000000 -0800
+++ sys/arch/arm/include/cpuconf.h	2007-09-25 10:55:22.000000000 -0700
@@ -33,6 +33,8 @@
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Portions Copyright (c) 2007 Danger Inc
  */

 #ifndef _ARM_CPUCONF_H_
@@ -74,7 +76,8 @@
 			 defined(CPU_XSCALE_80200) +			\
 			 defined(CPU_XSCALE_80321) +			\
 			 defined(__CPU_XSCALE_PXA2XX) +			\
-			 defined(CPU_XSCALE_IXP425))
+			 defined(CPU_XSCALE_IXP425))			\
+			 defined(CPU_ARM1136))
 #else
 #define	CPU_NTYPES	2
 #endif /* _KERNEL_OPT */
@@ -114,7 +117,7 @@
 #define	ARM_ARCH_5	0
 #endif

-#if defined(CPU_ARM11)
+#if defined(CPU_ARM11) || defined(CPU_ARM1136)
 #define ARM_ARCH_6	1
 #else
 #define ARM_ARCH_6	0
@@ -148,6 +151,10 @@
  *	ARM_MMU_XSCALE		XScale MMU.  Compatible with generic ARM
  *				MMU, but also has several extensions which
  *				require different PTE layout to use.
+ *
+ *	ARM_MMU_V6		ARM v6 MMU.  Compatible with generic ARM
+ *				MMU, but also has several extensions which
+ *				require different PTE layouts to use.
  */
 #if !defined(_KERNEL_OPT) ||						\
     (defined(CPU_ARM2) || defined(CPU_ARM250) || defined(CPU_ARM3))
@@ -159,7 +166,7 @@
 #if !defined(_KERNEL_OPT) ||						\
     (defined(CPU_ARM6) || defined(CPU_ARM7) || defined(CPU_ARM7TDMI) ||	\
      defined(CPU_ARM8) || defined(CPU_ARM9) || defined(CPU_ARM9E) ||	\
-     defined(CPU_ARM10) || defined(CPU_ARM11))
+     defined(CPU_ARM10))
 #define	ARM_MMU_GENERIC		1
 #else
 #define	ARM_MMU_GENERIC		0
@@ -181,8 +188,15 @@
 #define	ARM_MMU_XSCALE		0
 #endif

+#if !defined(_KERNEL_OPT) ||						\
+     (defined(CPU_ARM11) || defined(CPU_ARM1136))
+#define	ARM_MMU_V6		1
+#else
+#define	ARM_MMU_V6		0
+#endif
+
 #define	ARM_NMMUS		(ARM_MMU_MEMC + ARM_MMU_GENERIC +	\
-				 ARM_MMU_SA1 + ARM_MMU_XSCALE)
+				 ARM_MMU_SA1 + ARM_MMU_XSCALE + ARM_MMU_V6)
 #if ARM_NMMUS == 0
 #error ARM_NMMUS is 0
 #endif
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/include/cpufunc.h sys/arch/arm/include/cpufunc.h
--- ../../netbsd_40/src/sys/arch/arm/include/cpufunc.h	2007-02-21 10:36:02.000000000 -0800
+++ sys/arch/arm/include/cpufunc.h	2007-09-25 10:55:22.000000000 -0700
@@ -209,6 +209,7 @@
 void	cpufunc_domains		__P((u_int));
 u_int	cpufunc_faultstatus	__P((void));
 u_int	cpufunc_faultaddress	__P((void));
+void	cpufunc_sleep		__P((int));

 #ifdef CPU_ARM3
 u_int	arm3_control		__P((u_int, u_int));
@@ -343,7 +344,7 @@
 void	arm10_setup		__P((char *));
 #endif

-#ifdef CPU_ARM11
+#if defined(CPU_ARM11) || defined(CPU_ARM1136)
 void	arm11_setttb		__P((u_int));

 void	arm11_tlb_flushID_SE	__P((u_int));
@@ -356,6 +357,8 @@
 void	arm11_tlb_flushI	__P((void));
 void	arm11_tlb_flushD	__P((void));
 void	arm11_tlb_flushD_SE	__P((u_int va));
+void	armv11_dcache_wbinv_all	__P((void));
+void	armv11_idcache_wbinv_all	__P((void));

 void	arm11_drain_writebuf	__P((void));
 #endif
@@ -375,7 +378,7 @@
 void	armv5_ec_idcache_wbinv_range	__P((vaddr_t, vsize_t));
 #endif

-#if defined (CPU_ARM10) || defined (CPU_ARM11)
+#if defined (CPU_ARM10)
 void	armv5_setttb		__P((u_int));

 void	armv5_icache_sync_all	__P((void));
@@ -395,6 +398,32 @@
 extern unsigned armv5_dcache_index_inc;
 #endif

+#if defined (CPU_ARM11) || defined(CPU_ARM1136)
+void	armv6_setttb		__P((u_int));
+
+void	armv6_icache_sync_all	__P((void));
+void	armv6_icache_sync_range	__P((vaddr_t, vsize_t));
+
+void	armv6_dcache_wbinv_all	__P((void));
+void	armv6_dcache_wbinv_range __P((vaddr_t, vsize_t));
+void	armv6_dcache_inv_range	__P((vaddr_t, vsize_t));
+void	armv6_dcache_wb_range	__P((vaddr_t, vsize_t));
+
+void	armv6_idcache_wbinv_all	__P((void));
+void	armv6_idcache_wbinv_range __P((vaddr_t, vsize_t));
+#endif
+
+#if defined(CPU_ARM1136)
+void	arm1136_setttb			__P((u_int));
+void	arm1136_idcache_wbinv_all	__P((void));
+void	arm1136_dcache_wbinv_all	__P((void));
+void	arm1136_icache_sync_all		__P((void));
+void	arm1136_flush_prefetchbuf	__P((void));
+void	arm1136_icache_sync_range	__P((vaddr_t, vsize_t));
+void	arm1136_idcache_wbinv_range	__P((vaddr_t, vsize_t));
+void	arm1136_setup			__P((char *string));
+#endif
+
 #if defined(CPU_ARM9) || defined(CPU_ARM9E) || defined(CPU_ARM10) || \
     defined(CPU_SA110) || defined(CPU_SA1100) || defined(CPU_SA1110) || \
     defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
@@ -490,6 +519,9 @@

 #define restore_interrupts(old_cpsr)					\
 	(__set_cpsr_c((I32_bit | F32_bit), (old_cpsr) & (I32_bit | F32_bit)))
+#define disint_stats_force(mask)
+#define disint_stats_irq(irqno)
+#define disint_stats_gpioirq(pin)
 #else /* ! __PROG32 */
 #define	disable_interrupts(mask)					\
 	(set_r15((mask) & (R15_IRQ_DISABLE | R15_FIQ_DISABLE),		\
@@ -545,6 +577,7 @@
 extern int	arm_pdcache_size;	/* and unified */
 extern int	arm_pdcache_line_size;
 extern int	arm_pdcache_ways;
+extern int	arm_cache_prefer_mask;

 extern int	arm_pcache_type;
 extern int	arm_pcache_unified;
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/mainbus/mainbus.c sys/arch/arm/mainbus/mainbus.c
--- ../../netbsd_40/src/sys/arch/arm/mainbus/mainbus.c	2005-12-11 04:16:51.000000000 -0800
+++ sys/arch/arm/mainbus/mainbus.c	2007-09-25 10:55:22.000000000 -0700
@@ -139,7 +139,7 @@
 	do {
 		if (cf->cf_loc[MAINBUSCF_BASE] == MAINBUSCF_BASE_DEFAULT) {
 			mb.mb_iobase = MAINBUSCF_BASE_DEFAULT;
-			mb.mb_iosize = 0;
+			mb.mb_iosize = MAINBUSCF_SIZE_DEFAULT;
 			mb.mb_drq = MAINBUSCF_DACK_DEFAULT;
 			mb.mb_irq = MAINBUSCF_IRQ_DEFAULT;
 		} else {    
@@ -147,7 +147,7 @@
 #if defined(arm32) && !defined(EB7500ATX)
 			mb.mb_iobase += IO_CONF_BASE;
 #endif
-			mb.mb_iosize = 0;
+			mb.mb_iosize = cf->cf_loc[MAINBUSCF_SIZE];;
 			mb.mb_drq = cf->cf_loc[MAINBUSCF_DACK];
 			mb.mb_irq = cf->cf_loc[MAINBUSCF_IRQ];
 		}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/files.omap sys/arch/arm/omap/files.omap
--- ../../netbsd_40/src/sys/arch/arm/omap/files.omap	2007-02-21 10:41:50.000000000 -0800
+++ sys/arch/arm/omap/files.omap	2007-09-25 10:55:22.000000000 -0700
@@ -9,6 +9,15 @@

 # Memory size in megabytes
 defparam opt_omap.h				MEMSIZE
+defparam opt_omap.h				OMAP_EMIFF_PBASE OMAP_EMIFF_SIZE
+defflag opt_omap.h				OMAP_2430
+
+# OBIO
+# like tipb but no regs to program... just an attach point
+device obio { [addr=-1], [size=0], [intr=-1], [mult=1], [nobyteacc=0]
+	     } : bus_space_generic
+attach obio at mainbus
+file	arch/arm/omap/omap_obio.c		obio needs-count

 # Texas Instruments Peripheral Bus.
 # addr: Address of the peripheral in the OMAP address space
@@ -28,6 +37,7 @@
 attach tipb at mainbus
 file	arch/arm/omap/omap_tipb.c		tipb
 defparam opt_omap.h				OMAP_TIPB_PBASE OMAP_TIPB_SIZE
+file	arch/arm/omap/omap_dma.c

 # Extended Memory Interface Slow
 # Same parameters as for TIPB, but with the addition of parameters to
@@ -84,22 +94,23 @@
 	       [wrwst=0], [welen=0], [advhold=0], [btwst=0], [btmode=0]
 	     } : bus_space_generic
 attach emifs at mainbus
+defparam opt_omap.h				OMAP_EMIFS_PBASE OMAP_EMIFS_SIZE
 file	arch/arm/omap/omap_emifs.c		emifs
-file	arch/arm/omap/omap_nobyteacc_space.c	emifs
-file	arch/arm/omap/omap_nobyteacc_io.S	emifs
 defparam opt_omap.h				OMAP_TC_CLOCK_FREQ

 # OCP
 device ocp { [addr=-1], [size=0], [intr=-1], [mult=1]} : bus_space_generic
 attach ocp at mainbus
+defparam opt_omap.h				OMAP_OCP_T1_PBASE OMAP_OCP_T1_SIZE
+defparam opt_omap.h				OMAP_OCP_T2_PBASE OMAP_OCP_T2_SIZE
 file	arch/arm/omap/omap_ocp.c		ocp

 # TIPB/EMIFS/OCP common files
-file	arch/arm/omap/omap_space.c		tipb | emifs | ocp
-file	arch/arm/omap/omap_a2x_space.c		tipb | emifs | ocp
-file	arch/arm/omap/omap_a2x_io.S		tipb | emifs | ocp
-file	arch/arm/omap/omap_a4x_space.c		tipb | emifs | ocp
-file	arch/arm/xscale/pxa2x0_a4x_io.S		tipb | emifs | ocp
+file	arch/arm/omap/omap_space.c		obio | tipb | emifs | ocp
+file	arch/arm/omap/omap_a2x_space.c		obio | tipb | emifs | ocp
+file	arch/arm/omap/omap_a2x_io.S		obio | tipb | emifs | ocp
+file	arch/arm/omap/omap_a4x_space.c		obio | tipb | emifs | ocp
+file	arch/arm/xscale/pxa2x0_a4x_io.S		obio | tipb | emifs | ocp

 # NS16550 compatible serial ports
 attach com at tipb with omapuart
@@ -113,19 +124,102 @@
 device omap5912intc: omapintc
 attach omap5912intc at tipb
 file	arch/arm/omap/omap5912_intr.c		omap5912intc
+# OMAP2430 specific INTC controller code
+file	arch/arm/omap/omap2430_intr.c		omap_2430

-# MPU Timer
+# OMAP1 MPU Timer
 device omapmputmr
 attach omapmputmr at tipb
 file	arch/arm/omap/omap_mputmr.c		omapmputmr
 defparam opt_omap.h				OMAP_MPU_TIMER_CLOCK_FREQ

-# OMAP GPIO Block
-device omapgpio
-attach omapgpio at tipb
-file  arch/arm/omap/omap_gpio.c       omapgpio	needs-count
+# OMAP 2430 General Purpose Timer
+device omap2430mputmr
+file	arch/arm/omap/omap2430_mputmr.c		omap2430mputmr
+defparam opt_omap.h				OMAP_GP_TIMER_CLOCK_FREQ
+
+# OBIO/2430 GP Timer
+attach omap2430mputmr at obio with obiomputmr
+file	arch/arm/omap/obio_mputmr.c		obiomputmr

 # RTC
 device omaprtc
 attach omaprtc at tipb
 file arch/arm/omap/omap_rtc.c			omaprtc
+
+# Dual Mode (General Purpose) Timer
+device omapgptmr
+attach omapgptmr at obio
+file	arch/arm/omap/omap_gptmr.c		omapgptmr
+file	arch/arm/omap/omap_pwm.c		omapgptmr
+
+# OMAP GPIO Block
+device omapgpio
+attach omapgpio at tipb
+file  arch/arm/omap/omap_gpio.c       omapgpio	needs-count
+
+# OMAP GPIO Bus
+device	omapiobus: gpiobus
+attach	omapiobus at tipb
+file	arch/arm/omap/omap_iobus.c		omapiobus
+
+# OMAP I2C controller
+device	omapi2c: i2cbus
+attach	omapi2c at tipb
+file	arch/arm/omap/omap_i2c.c		omapi2c
+defparam	opt_omap.h		OMAP_I2C_ADDRESS
+defparam	opt_omap.h		I2C_LOW_TIME_nSEC
+defparam	opt_omap.h		I2C_HIGH_TIME_nSEC
+
+#attach udc at tipb with omapudc
+#file	arch/arm/omap/omap_udc.c		omapudc
+
+# OMAP McBsp controller
+
+device	omapmcbsp
+attach	omapmcbsp at tipb
+file	arch/arm/omap/omap_mcbsp.c	omapmcbsp
+
+# Watchdog timers
+
+device omapwdt32k: sysmon_wdog
+file arch/arm/omap/omap_wdt.c			omapwdt32k needs-flag
+
+attach omapwdt32k at tipb with tipbwdt32k
+file arch/arm/omap/tipb_wdt.c			tipbwdt32k
+
+attach omapwdt32k at obio with obiowdt32k
+file arch/arm/omap/obio_wdt.c			obiowdt32k
+
+# Hardware clock and power management
+
+device omapdpll
+attach omapdpll at tipb
+device omapmpuclkm
+attach omapmpuclkm at tipb
+device omapulpd
+attach omapulpd at tipb
+device omapconfig
+attach omapconfig at tipb
+
+file arch/arm/omap/hwclock_omap1.c	hwclock
+defparam	opt_hwclock_machine.h		OMAP_CK_REF_SPEED
+
+# L3 Interconnect
+device L3i { [addr=-1], [size=0], [intr=-1], [mult=1], [nobyteacc=0]
+	     } : bus_space_generic
+attach L3i at mainbus
+file	arch/arm/omap/omap_L3i.c			omap_2430
+
+# General Purpose Memory Controller
+# XXX some addl. chip select config parms may be desired here (e.g. timing)
+# XXX so far we just use the setup established by boot firmware
+device gpmc { [addr=-1], [size=0], [intr=-1], [mult=1], [nobyteacc=0]
+	     } : bus_space_generic
+attach gpmc at mainbus
+file	arch/arm/omap/omap_gpmc.c		gpmc
+
+# these bus space methods are not bus-specific ...
+#
+file	arch/arm/omap/omap_nobyteacc_space.c	emifs | gpmc
+file	arch/arm/omap/omap_nobyteacc_io.S	emifs | gpmc
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/hwclock_omap1.c sys/arch/arm/omap/hwclock_omap1.c
--- ../../netbsd_40/src/sys/arch/arm/omap/hwclock_omap1.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/hwclock_omap1.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,1238 @@
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/conf.h>
+#include <sys/hwclock.h>
+#include <machine/bus.h>
+#include <arm/omap/omap_tipb.h>
+#include "opt_omap.h"
+
+unsigned int omap_reset_reason;
+
+/* Common */
+
+/* Get frequency of clock that directly sources its parent. */
+
+static int get_parent_freq(struct hwclock *hwc, unsigned long *freq)
+{
+	return hwc->parent->getfreq(hwc->parent, freq);
+}
+
+
+/* REF_CK */
+
+static int ref_ck_getfreq(struct hwclock *hwc, unsigned long *freq)
+{
+	*freq = OMAP_CK_REF_SPEED;
+	return 0;
+}
+
+static struct hwclock hwclock_ref_ck = {
+	.name = "ref_ck",
+	.getfreq = ref_ck_getfreq,
+};
+
+
+/* DPLL1 */
+
+struct omapdpll1_softc {
+        struct device           sc_dev;
+        bus_space_tag_t         sc_iot;
+        bus_space_handle_t      sc_ioh;
+};
+
+static struct omapdpll1_softc *dpll1_sc = NULL;
+
+static int omapdpll_match(struct device *, struct cfdata *, void *);
+static void omapdpll_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(omapdpll, sizeof(struct omapdpll1_softc),
+    omapdpll_match, omapdpll_attach, NULL, NULL);
+
+#define DPLL1_CTL_REG	0x0
+
+#define PLL_MULT(dpll)		(((dpll) >> 7) & 0x1f)
+#define PLL_DIV(dpll)		(((dpll) >> 5) & 0x02)
+#define BYPASS_DIV(dpll)	(((dpll) >> 2) & 0x02)
+
+static int dpll1_getfreq(struct hwclock *hwc, unsigned long *freq);
+static int dpll1_setfreq(struct hwclock *hwc, unsigned long freq);
+
+static struct hwclock hwclock_dpll1 = {
+	.name = "dpll1",
+	.parent = &hwclock_ref_ck,
+	.getfreq = dpll1_getfreq,
+	.setfreq = dpll1_setfreq,
+};
+
+static int dpll1_getfreq(struct hwclock *hwc, unsigned long *freq)
+{
+	unsigned long ref_ck_freq;
+	unsigned dpll1_val;
+
+	/* TODO?: bypass mode */
+
+	dpll1_val = bus_space_read_2(dpll1_sc->sc_iot, dpll1_sc->sc_ioh,
+				     DPLL1_CTL_REG);
+	ref_ck_getfreq(&hwclock_ref_ck, &ref_ck_freq);
+	*freq = ref_ck_freq * PLL_MULT(dpll1_val) / (PLL_DIV(dpll1_val)+1);
+	return 0;
+}
+
+static int dpll1_setfreq(struct hwclock *hwc, unsigned long freq)
+{
+	// todo: DPLL reprogram sometimes not safe from SDRAM.
+	return 0;
+}
+
+static int dpll1_freq_req(struct hwclock *hwc, unsigned long fcmin,
+			  unsigned long fcmax, unsigned long *pfcmin,
+			  unsigned long *pfcmax)
+{
+	// todo: determine what min/max frequencies can be generated from REF_CK.
+	*pfcmin = fcmin;
+	*pfcmax = fcmax;
+	return 0;
+}
+
+static int
+omapdpll_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct tipb_attach_args *tipb = aux;
+
+	if (tipb->tipb_addr == -1)
+		panic("omapdpll must have tipb bus addr specified in config.");
+
+	if (tipb->tipb_size == 0)
+		tipb->tipb_size = 256;
+
+	return 1;
+}
+
+static void
+omapdpll_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct omapdpll1_softc *sc = (struct omapdpll1_softc*) self;
+	struct tipb_attach_args *tipb = aux;
+	unsigned long dpll1_freq;
+
+	sc->sc_iot = tipb->tipb_iot;
+
+	if (bus_space_map(sc->sc_iot, tipb->tipb_addr, tipb->tipb_size,
+			  0, &sc->sc_ioh))
+		panic("%s: Cannot map registers", self->dv_xname);
+
+	dpll1_sc = sc;
+
+	hwclock_register(&hwclock_dpll1);
+	hwclock_getfreq("dpll1", &dpll1_freq);
+	aprint_normal(": DPLL1 speed %luMHz\n", dpll1_freq/1000/1000);
+}
+
+/* MPU CLKM */
+
+struct omapmpuclkm_softc {
+        struct device           sc_dev;
+        bus_space_tag_t         sc_iot;
+        bus_space_handle_t      sc_ioh;
+};
+
+static struct omapmpuclkm_softc *mpuclkm_sc = NULL;
+
+static int omapmpuclkm_match(struct device *, struct cfdata *, void *);
+static void omapmpuclkm_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(omapmpuclkm, sizeof(struct omapmpuclkm_softc),
+	      omapmpuclkm_match, omapmpuclkm_attach, NULL, NULL);
+
+/* Register offsets from MPU CLKM. */
+
+#define ARM_CKCTL		0x00
+#define ARM_IDLECT1		0x04
+#define ARM_IDLECT2		0x08
+#define ARM_SYSST		0x18
+#define ARM_IDLECT3		0x24
+
+/* ARM_CKCTL fields */
+
+#define ARM_TIMXO		12
+#define TCDIV			8
+#define ARMDIV			4
+#define LCDDIV			2
+#define ARM_PERDIV		0
+
+/* ARM_IDLECT1 fields */
+
+#define IDL_CLKOUT_ARM		12
+#define IDLTIM_ARM		9
+#define IDLAPI_ARM		8
+#define IDLDPLL_ARM		7
+#define IDLIF_ARM		6
+#define IDLWDT_ARM		0
+
+/* ARM_IDLECT2 fields */
+
+#define EN_CKOUT_ARM		11
+#define DMACK_REQ		8
+#define EN_TIMCK		7
+#define EN_APICK		6
+#define EN_LCDCK		3
+#define EN_PERCK		2
+#define EN_XORPCK		1
+#define EN_WDTCK		0
+
+/* ARM_IDLECT3 fields */
+
+#define IDLTC2_ARM		5
+#define EN_TC2_CK		4
+#define IDLTC1_ARM		3
+#define EN_OCPI_CK		0
+
+/* ARM_SYSST fields */
+
+#define POR				5
+#define EXT_RST			4
+#define ARM_MCRST		3
+#define ARM_WDRST		2
+#define GLOB_SWRST		1
+
+static int ckctl_getfreq(struct hwclock *hwc, unsigned long *freq);
+static int ckctl_setfreq(struct hwclock *hwc, unsigned long freq);
+static int idlectx_getenable(struct hwclock *hwc, unsigned long *value);
+static int idlectx_setenable(struct hwclock *hwc, unsigned long value);
+static int idlectx_setattr(struct hwclock *hwc, enum hwclock_arch_attr attr,
+			   unsigned long value);
+static void armtim_init(struct hwclock *hwc);
+
+static struct hwclock hwclock_arm = {
+	.name = "arm",
+	.parent = &hwclock_dpll1,
+	.getfreq = ckctl_getfreq,
+	.setfreq = ckctl_setfreq,
+	.machine = {
+		.freq_field = ARMDIV,
+	},
+};
+
+static struct hwclock hwclock_armper = {
+	.name = "armper",
+	.parent = &hwclock_dpll1,
+	.getfreq = ckctl_getfreq,
+	.setfreq = ckctl_setfreq,
+	.getenable = idlectx_getenable,
+	.setenable = idlectx_setenable,
+	.parent_freq_req = dpll1_freq_req,
+	.machine = {
+		.freq_field = ARM_PERDIV,
+		.enable_reg = ARM_IDLECT2,
+		.enable_field = EN_PERCK,
+	},
+};
+
+static struct hwclock hwclock_tc = {
+	.name = "tc",
+	.parent = &hwclock_dpll1,
+	.getfreq = ckctl_getfreq,
+	.setfreq = ckctl_setfreq,
+	.machine = {
+		.freq_field = TCDIV,
+	},
+};
+
+static struct hwclock hwclock_lcd = {
+	.name = "lcd",
+	.parent = &hwclock_dpll1,
+	.getfreq = ckctl_getfreq,
+	.setfreq = ckctl_setfreq,
+	.getenable = idlectx_getenable,
+	.setenable = idlectx_setenable,
+	.machine = {
+		.freq_field = LCDDIV,
+		.enable_reg = ARM_IDLECT2,
+		.enable_field = EN_LCDCK,
+	},
+};
+
+static struct hwclock hwclock_armtim = {
+	.name = "armtim",
+	.parent = &hwclock_ref_ck, /* .init chooses this parent */
+	.getfreq = get_parent_freq,
+	.getenable = idlectx_getenable,
+	.setenable = idlectx_setenable,
+	.setattr = idlectx_setattr,
+	.init = armtim_init,
+	.machine = {
+		.enable_reg = ARM_IDLECT2,
+		.enable_field = EN_TIMCK,
+		.pm_reg = ARM_IDLECT1,
+		.pm_field = IDLTIM_ARM,
+	},
+};
+
+static struct hwclock hwclock_ocpi = {
+	.name = "ocpi", /* aka "l3_ocpi" */
+	.parent = &hwclock_tc,
+	.getfreq = get_parent_freq,
+	.getenable = idlectx_getenable,
+	.setenable = idlectx_setenable,
+	.machine = {
+		.enable_reg = ARM_IDLECT3,
+		.enable_field = EN_OCPI_CK,
+	},
+};
+
+static struct hwclock hwclock_tc2 = {
+	.name = "tc2",
+	.parent = &hwclock_tc,
+	.getfreq = get_parent_freq,
+	.getenable = idlectx_getenable,
+	.setenable = idlectx_setenable,
+	.machine = {
+		.enable_reg = ARM_IDLECT3,
+		.enable_field = EN_TC2_CK,
+	},
+};
+
+static int ckctl_getfreq(struct hwclock *hwc, unsigned long *freq)
+{
+	unsigned long dpll1_freq, ckctl_val;
+
+	dpll1_getfreq(&hwclock_dpll1, &dpll1_freq);
+	ckctl_val = bus_space_read_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+				     ARM_CKCTL);
+	*freq = dpll1_freq / 
+	    (1 << ((ckctl_val >> hwc->machine.freq_field) & 0x3));
+	return 0;
+}
+
+static int ckctl_setfreq(struct hwclock *hwc, unsigned long freq)
+{
+	unsigned long dpll1_freq, newfreq;
+	unsigned ckctl_val;
+	int newdiv;
+	int s;
+
+	dpll1_getfreq(&hwclock_dpll1, &dpll1_freq);
+
+	/* Requested speed greater than DPLL1 speed? */
+	/* todo: Assume current DPLL1 frequency is a given for now. */
+
+	if (freq > dpll1_freq)
+		return EINVAL;
+
+	for (newdiv = 3; newdiv >= 0; newdiv--) {
+		newfreq = dpll1_freq >> newdiv;
+
+		if (newfreq >= freq)
+			break;
+	}
+
+	/* Sanity check, should have already ensured a dpll1 divider will
+	   work. */
+
+	if (newfreq < freq)
+		return EINVAL;
+
+	/* If new value violates a max constraint, just warn for now. */
+
+	if (freq > hwc->freqcons_max)
+		printf("Requested %s freq %lu, DPLL1 requires %lu,"
+		       " violates max %lu\n",
+		       hwc->name, freq, newfreq, hwc->freqcons_max);
+
+	s = splhigh();
+	ckctl_val = bus_space_read_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+				     ARM_CKCTL);
+	ckctl_val &= ~(0x3 << hwc->machine.freq_field);
+	ckctl_val |= newdiv << hwc->machine.freq_field;
+
+	bus_space_write_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+			  ARM_CKCTL, ckctl_val);
+	splx(s);
+	return 0;
+}
+
+static int idlectx_getenable(struct hwclock *hwc, unsigned long *value)
+{
+	unsigned int idlectx_val;
+
+	idlectx_val = bus_space_read_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+				       hwc->machine.enable_reg);
+	*value = idlectx_val & (0x1 << hwc->machine.enable_field) ?
+		HWCLOCK_ENABLED : HWCLOCK_DISABLED;
+	return 0;
+}
+
+static int idlectx_setenable(struct hwclock *hwc, unsigned long value)
+{
+	unsigned int idlectx_val;
+	int s;
+
+	s = splhigh();
+	idlectx_val = bus_space_read_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+				       hwc->machine.enable_reg);
+	if (value == HWCLOCK_ENABLED)
+		idlectx_val |= (0x1 << hwc->machine.enable_field);
+	else
+		idlectx_val &= ~(0x1 << hwc->machine.enable_field);
+
+	bus_space_write_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+			  hwc->machine.enable_reg, idlectx_val);
+	splx(s);
+	return 0;
+}
+
+static int idlectx_setattr(struct hwclock *hwc, enum hwclock_arch_attr attr,
+						   unsigned long value)
+{
+	unsigned int idlectx_val;
+	int s;
+
+	if (attr != AUTOIDLE)
+		return EINVAL;
+
+	s = splhigh();
+	idlectx_val = bus_space_read_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+				       hwc->machine.pm_reg);
+	if (value == HWCLOCK_ENABLED)
+		idlectx_val |= (0x1 << hwc->machine.pm_field);
+	else
+		idlectx_val &= ~(0x1 << hwc->machine.pm_field);
+
+	bus_space_write_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+			  hwc->machine.pm_reg, idlectx_val);
+	splx(s);
+	return 0;
+}
+
+static void armtim_init(struct hwclock *hwc)
+{
+	unsigned int ckctl_val;
+	int s;
+
+	s = splhigh();
+
+	/*
+	 * Set ARMTIM clock (MPU OS timers) to CK_REF source instead of
+	 * DPLL1out clock source by clearing ARM_CKCTL[ARM_TIMXO].
+	 */
+
+	ckctl_val = bus_space_read_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+				     ARM_CKCTL);
+	ckctl_val &= ~(1 << ARM_TIMXO);
+	bus_space_write_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+			  ARM_CKCTL, ckctl_val);
+	splx(s);
+}
+
+
+static int
+omapmpuclkm_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct tipb_attach_args *tipb = aux;
+
+	if (tipb->tipb_addr == -1)
+		panic("omapmpuclkm must have tipb bus addr specified in config.");
+
+	if (tipb->tipb_size == 0)
+		tipb->tipb_size = 256;
+
+	return 1;
+}
+
+static void
+omapmpuclkm_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct omapmpuclkm_softc *sc = (struct omapmpuclkm_softc*) self;
+	struct tipb_attach_args *tipb = aux;
+	unsigned long arm_freq, tc_freq;
+	unsigned int val;
+	int s;
+
+	sc->sc_iot = tipb->tipb_iot;
+
+	if (bus_space_map(sc->sc_iot, tipb->tipb_addr, tipb->tipb_size,
+			  0, &sc->sc_ioh))
+		panic("%s: Cannot map registers", self->dv_xname);
+
+	mpuclkm_sc = sc;
+
+	hwclock_register(&hwclock_arm);
+	hwclock_register(&hwclock_armper);
+	hwclock_register(&hwclock_tc);
+	hwclock_register(&hwclock_lcd);
+	hwclock_register(&hwclock_armtim);
+	hwclock_register(&hwclock_ocpi);
+	hwclock_register(&hwclock_tc2);
+
+	s = splhigh();
+
+	/*
+	 * Save and clear ARM_SYSST reset reason bits.
+	 */
+
+	val = bus_space_read_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+			       ARM_SYSST);
+	omap_reset_reason = val & (1 << POR | 1 << EXT_RST | 1 << ARM_MCRST |
+				   1 << ARM_WDRST | 1 << GLOB_SWRST);
+	val &= ~(1 << POR | 1 << EXT_RST | 1 << ARM_MCRST |
+		 1 << ARM_WDRST | 1 << GLOB_SWRST);
+	bus_space_write_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+			  ARM_SYSST, val);
+	splx(s);
+
+	hwclock_getfreq("arm", &arm_freq);
+	hwclock_getfreq("tc", &tc_freq);
+	aprint_normal(": ARM %luMHz TC %luMHz\n", arm_freq/1000/1000,
+		      tc_freq/1000/1000);
+
+	/* preset ARM_IDLECT registers for idle mode */
+
+	bus_space_write_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+			  ARM_IDLECT1,
+			  1 << IDL_CLKOUT_ARM |
+			  1 << IDLDPLL_ARM |
+			  1 << IDLIF_ARM |
+			  1 << IDLAPI_ARM |
+			  1 << IDLWDT_ARM);
+
+	bus_space_write_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+			  ARM_IDLECT2,
+			  bus_space_read_4(mpuclkm_sc->sc_iot,
+					   mpuclkm_sc->sc_ioh,
+					   ARM_IDLECT2)
+			  | 1 << EN_CKOUT_ARM
+			  | 1 << DMACK_REQ
+			  | 1 << EN_TIMCK
+			  | 1 << EN_APICK
+			  | 1 << EN_LCDCK
+			  | 1 << EN_PERCK
+			  | 1 << EN_XORPCK
+			  | 1 << EN_WDTCK);
+
+	bus_space_write_4(mpuclkm_sc->sc_iot, mpuclkm_sc->sc_ioh,
+			  ARM_IDLECT3,
+			  bus_space_read_4(mpuclkm_sc->sc_iot,
+					   mpuclkm_sc->sc_ioh,
+					   ARM_IDLECT3)
+			  | 1 << IDLTC2_ARM
+			  | 1 << IDLTC1_ARM);
+}
+
+/* ULPD */
+
+struct omapulpd_softc {
+        struct device           sc_dev;
+        bus_space_tag_t         sc_iot;
+        bus_space_handle_t      sc_ioh;
+};
+
+static struct omapulpd_softc *ulpd_sc = NULL;
+
+static int omapulpd_match(struct device *, struct cfdata *, void *);
+static void omapulpd_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(omapulpd, sizeof(struct omapulpd_softc),
+	      omapulpd_match, omapulpd_attach, NULL, NULL);
+
+
+/* ULPD register offsets */
+
+#define CLOCK_CTRL_REG			0x30
+#define SOFT_REQ_REG			0x34
+#define POWER_CTRL_REG			0x50
+#define SLEEP_STATUS			0x58
+#define SOFT_DISABLE_REQ_REG		0x68
+#define COM_CLK_DIV_CTRL_SEL		0x78
+
+/* CLOCK_CTRL_REG fields */
+
+#define DIS_USB_PVCI_CLK		5
+#define USB_MCLK_EN			4
+
+/* SOFT_REQ_REG fields */
+
+#define SOFT_MMC2_DPLL_REQ		13
+#define SOFT_MMC_DPLL_REQ		12
+#define SOFT_UART3_DPLL_REQ		11
+#define SOFT_UART2_DPLL_REQ		10
+#define SOFT_UART1_DPLL_REQ		9
+#define SOFT_USB_OTG_DPLL_REQ		8
+#define SOFT_COM_MCKO_REQ		6
+#define USB_REQ_EN			4
+#define SOFT_USB_REQ			3
+
+/* POWER_CTRL_REG bits */
+
+#define DVS_ENABLE			10
+#define OSC_STOP_EN			9
+#define LDO_CTRL_EN			7
+#define DEEP_SLEEP_TRANSITION_EN	4
+#define LOW_PWR_EN			0
+
+/* SLEEP_STATUS fields */
+
+#define BIG_SLEEP			1
+#define DEEP_SLEEP			0
+
+/* SOFT_DISABLE_REQ_REG bits */
+
+#define DIS_MMC2_DPLL_REQ		11
+#define DIS_MMC_DPLL_REQ		10
+#define DIS_UART3_DPLL_REQ		9
+#define DIS_UART2_DPLL_REQ		8
+#define DIS_UART1_DPLL_REQ		7
+#define DIS_USB_HOST_DPLL_REQ		6
+#define DIS_COM_MCLK_REQ		0
+
+/* COM_CLK_DIV_CTRL_SEL fields */
+
+#define COM_ULPD_PLL_CLK_REQ	1
+#define COM_SYSCLK_PLLCLK_SEL	0
+
+static int ulpd_getenable(struct hwclock *hwc, unsigned long *value);
+static int ulpd_setenable(struct hwclock *hwc, unsigned long value);
+static int ulpd_get_swhw_enable(struct hwclock *hwc, unsigned long *value);
+static int ulpd_set_swhw_enable(struct hwclock *hwc, unsigned long value);
+static int ulpd_get_mclk_enable(struct hwclock *hwc, unsigned long *value);
+static int ulpd_set_mclk_enable(struct hwclock *hwc, unsigned long value);
+static int ulpd_setattr(struct hwclock *hwc, enum hwclock_arch_attr attr,
+			unsigned long value);
+
+static int config_set_mclk_src(struct hwclock *hwc,
+			       enum hwclock_mclk_src src);
+static int config_set_mmcsdio1_enable(struct hwclock *hwc,
+				      unsigned long value);
+
+static struct hwclock hwclock_mclk = {
+	.name = "mclk",
+	.getenable = ulpd_get_mclk_enable,
+	.setenable = ulpd_set_mclk_enable,
+	.setattr = ulpd_setattr,
+	.machine = {
+		.swreqenable_bit = SOFT_COM_MCKO_REQ,
+		.hwreqdisable_bit = DIS_COM_MCLK_REQ,
+	},
+};
+
+static struct hwclock hwclock_uart1 = {
+	.name = "uart1",
+	.getenable = ulpd_get_swhw_enable,
+	.setenable = ulpd_set_swhw_enable,
+	.setattr = ulpd_setattr,
+	.machine = {
+		.swreqenable_bit = SOFT_UART1_DPLL_REQ,
+		.hwreqdisable_bit = DIS_UART1_DPLL_REQ,
+	},
+};
+
+static struct hwclock hwclock_uart2 = {
+	.name = "uart2",
+	.getenable = ulpd_get_swhw_enable,
+	.setenable = ulpd_set_swhw_enable,
+	.setattr = ulpd_setattr,
+	.machine = {
+		.swreqenable_bit = SOFT_UART2_DPLL_REQ,
+		.hwreqdisable_bit = DIS_UART2_DPLL_REQ,
+	},
+};
+
+static struct hwclock hwclock_uart3 = {
+	.name = "uart3",
+	.getenable = ulpd_get_swhw_enable,
+	.setenable = ulpd_set_swhw_enable,
+	.setattr = ulpd_setattr,
+	.machine = {
+		.swreqenable_bit = SOFT_UART3_DPLL_REQ,
+		.hwreqdisable_bit = DIS_UART3_DPLL_REQ,
+	},
+};
+
+static struct hwclock hwclock_mmc = {
+	.name = "mmc",
+	.getenable = ulpd_get_swhw_enable,
+	.setenable = ulpd_set_swhw_enable,
+	.setattr = ulpd_setattr,
+	.machine = {
+		.swreqenable_bit = SOFT_MMC_DPLL_REQ,
+		.hwreqdisable_bit = DIS_MMC_DPLL_REQ,
+	},
+};
+
+static struct hwclock hwclock_mmc2 = {
+	.name = "mmc2",
+	.getenable = ulpd_get_swhw_enable,
+	.setenable = ulpd_set_swhw_enable,
+	.setattr = ulpd_setattr,
+	.machine = {
+		.swreqenable_bit = SOFT_MMC2_DPLL_REQ,
+		.hwreqdisable_bit = DIS_MMC2_DPLL_REQ,
+	},
+};
+
+static struct hwclock hwclock_usbh = {
+	.name = "usbh",
+	.getenable = ulpd_getenable,
+	.setenable = ulpd_setenable,
+	.machine = {
+		.enable_reg = SOFT_REQ_REG,
+		.enable_field = SOFT_USB_REQ,
+	},
+};
+
+static struct hwclock hwclock_usbd = {
+	.name = "usbd",
+	.getenable = ulpd_getenable,
+	.setenable = ulpd_setenable,
+	.machine = {
+		.enable_reg = SOFT_REQ_REG,
+		.enable_field = USB_REQ_EN,
+	},
+};
+
+static struct hwclock hwclock_usbotg = {
+	.name = "usbotg",
+	.getenable = ulpd_get_swhw_enable,
+	.setenable = ulpd_set_swhw_enable,
+	.setattr = ulpd_setattr,
+	.machine = {
+		.swreqenable_bit = SOFT_USB_OTG_DPLL_REQ,
+		.hwreqdisable_bit = DIS_USB_HOST_DPLL_REQ,
+	},
+};
+
+static struct hwclock hwclock_usb_mclk = {
+	.name = "usb_mclk",
+	.getenable = ulpd_getenable,
+	.setenable = ulpd_setenable,
+	.machine = {
+		.enable_reg = CLOCK_CTRL_REG,
+		.enable_field = USB_MCLK_EN,
+	},
+};
+
+static struct hwclock hwclock_mmcsdio1 = {
+	.name = "mmcsdio1",
+	.setenable = config_set_mmcsdio1_enable,
+};
+
+static int ulpd_getenable(struct hwclock *hwc, unsigned long *value)
+{
+	unsigned int reg_val;
+
+	reg_val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+				   hwc->machine.enable_reg);
+	*value = reg_val & (0x1 << hwc->machine.enable_field) ?
+		HWCLOCK_ENABLED : HWCLOCK_DISABLED;
+	return 0;
+}
+
+static int ulpd_setenable(struct hwclock *hwc, unsigned long value)
+{
+	unsigned int reg_val;
+	int s;
+
+	s = splhigh();
+	reg_val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+				   hwc->machine.enable_reg);
+	if (value == HWCLOCK_ENABLED)
+		reg_val |= (0x1 << hwc->machine.enable_field);
+	else
+		reg_val &= ~(0x1 << hwc->machine.enable_field);
+
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+			  hwc->machine.enable_reg, reg_val);
+	splx(s);
+	return 0;
+}
+
+static int ulpd_get_swhw_enable(struct hwclock *hwc, unsigned long *value)
+{
+	unsigned int reg_val;
+
+	if (hwc->machine.flags & FLAG_HWREQ) {
+		reg_val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+					   SOFT_DISABLE_REQ_REG);
+		*value = reg_val & (0x1 << hwc->machine.hwreqdisable_bit) ?
+			HWCLOCK_DISABLED : HWCLOCK_ENABLED;
+
+	} else {
+		reg_val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+					   SOFT_REQ_REG);
+		*value = reg_val & (0x1 << hwc->machine.swreqenable_bit) ?
+			HWCLOCK_ENABLED : HWCLOCK_DISABLED;
+	}
+
+	return 0;
+}
+
+static int ulpd_set_swhw_enable(struct hwclock *hwc, unsigned long value)
+{
+	unsigned int reg_val;
+	int s;
+
+	s = splhigh();
+
+	if (value == HWCLOCK_ENABLED) {
+		if (hwc->machine.flags & FLAG_HWREQ) {
+			reg_val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+						   SOFT_DISABLE_REQ_REG);
+			reg_val &= ~(1 << hwc->machine.hwreqdisable_bit);
+			bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+					  SOFT_DISABLE_REQ_REG, reg_val);
+		} else {
+			reg_val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+						   SOFT_REQ_REG);
+			reg_val |= (1 << hwc->machine.swreqenable_bit);
+			bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+					  SOFT_REQ_REG, reg_val);
+		}
+	} else {
+			reg_val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+						   SOFT_DISABLE_REQ_REG);
+			reg_val |= (1 << hwc->machine.hwreqdisable_bit);
+			bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+					  SOFT_DISABLE_REQ_REG, reg_val);
+			reg_val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+						   SOFT_REQ_REG);
+			reg_val &= ~(1 << hwc->machine.swreqenable_bit);
+			bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+					  SOFT_REQ_REG, reg_val);
+	}
+	splx(s);
+	return 0;
+}
+
+static int ulpd_get_mclk_enable(struct hwclock *hwc, unsigned long *value)
+{
+	if (hwc->machine.src != MCLK_SYSTEM_CLOCK)
+		return EINVAL; 	// todo
+
+	return ulpd_get_swhw_enable(hwc, value);
+}
+
+static int ulpd_set_mclk_enable(struct hwclock *hwc, unsigned long value)
+{
+	if (hwc->machine.src != MCLK_SYSTEM_CLOCK)
+		return EINVAL; 	// todo
+
+	return ulpd_set_swhw_enable(hwc, value);
+}
+
+static int ulpd_set_mclk_src(struct hwclock *hwc, enum hwclock_mclk_src src)
+{
+	unsigned int reg_val;
+	int s;
+	int ret = 0;
+
+	s = splhigh();
+
+	switch (src) {
+	case MCLK_SYSTEM_CLOCK:
+			reg_val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+						   COM_CLK_DIV_CTRL_SEL);
+			/* system or undivided 48MHz on MCLK */
+			reg_val |= (1 << COM_SYSCLK_PLLCLK_SEL);
+			bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+					  COM_CLK_DIV_CTRL_SEL, reg_val);
+			ret = 0;
+			break;
+
+	default:
+		ret = EINVAL; // todo: APLL 48MHz sources
+		break;
+	}
+
+	splx(s);
+
+	return ret;
+}
+
+static int ulpd_setattr(struct hwclock *hwc, enum hwclock_arch_attr attr,
+			unsigned long value)
+{
+	int ret = 0;
+
+	switch (attr) {
+	case HWSWREQ:
+		if (value == HWREQ)
+			hwc->machine.flags |= FLAG_HWREQ;
+		else
+			hwc->machine.flags &= ~FLAG_HWREQ;
+
+		ret = 0;
+		break;
+
+	case SOURCE:
+		if (hwc == &hwclock_mclk) {
+			ret = ulpd_set_mclk_src(hwc, value) ||
+				config_set_mclk_src(hwc, value);
+
+			if (ret == 0)
+				hwc->machine.src = value;
+
+		} else {
+			ret = EINVAL;
+		}
+
+		break;
+
+	default:
+		printf("ulpd_setattr: unknown attribute %d\n", (int) attr);
+		ret = EINVAL;
+	}
+
+	return ret;
+}
+
+
+static int
+omapulpd_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct tipb_attach_args *tipb = aux;
+
+
+	if (tipb->tipb_addr == -1)
+		panic("omapulpd must have tipb bus addr specified in config.");
+
+	if (tipb->tipb_size == 0)
+		tipb->tipb_size = 2048;
+
+	return 1;
+}
+
+static void
+omapulpd_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct omapulpd_softc *sc = (struct omapulpd_softc*) self;
+	struct tipb_attach_args *tipb = aux;
+
+	sc->sc_iot = tipb->tipb_iot;
+
+	if (bus_space_map(sc->sc_iot, tipb->tipb_addr, tipb->tipb_size,
+			  0, &sc->sc_ioh))
+		panic("%s: Cannot map registers", self->dv_xname);
+
+	ulpd_sc = sc;
+
+	hwclock_register(&hwclock_mclk);
+	hwclock_register(&hwclock_uart1);
+	hwclock_register(&hwclock_uart2);
+	hwclock_register(&hwclock_uart3);
+	hwclock_register(&hwclock_mmc);
+	hwclock_register(&hwclock_mmc2);
+	hwclock_register(&hwclock_usbh);
+	hwclock_register(&hwclock_usbd);
+	hwclock_register(&hwclock_usbotg);
+	hwclock_register(&hwclock_usb_mclk);
+	hwclock_register(&hwclock_mmcsdio1);
+
+	aprint_normal(": Ultra Low Power Device\n");
+
+	/* Enable Deep Sleep */
+
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+			  POWER_CTRL_REG,
+			  (1 << DVS_ENABLE) |
+			  (1 << OSC_STOP_EN) |
+			  (1 << DEEP_SLEEP_TRANSITION_EN));
+
+}
+
+static unsigned int soft_req_save;
+static unsigned int soft_disable_req_save;
+static unsigned int clock_ctrl_save;
+static unsigned int com_div_ctrl_save;
+
+static void ulpd_suspend(void)
+{
+
+	/* All ULPD software requests inactive, disable any hardware
+	   requests. */
+
+	soft_req_save = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+					 SOFT_REQ_REG);
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh, SOFT_REQ_REG,
+			  0);
+	soft_disable_req_save =
+		bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+				 SOFT_DISABLE_REQ_REG);
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+			  SOFT_DISABLE_REQ_REG, 0xffff);
+
+	/*
+	 * Disable USB W2FC PVCI clock. (move to USB driver?)
+	 */
+
+	clock_ctrl_save =
+		bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+				 CLOCK_CTRL_REG);
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh, CLOCK_CTRL_REG,
+			  clock_ctrl_save | (1 << DIS_USB_PVCI_CLK));
+
+	/*
+	 * Inactivate the MCLK software request (move to aic28 driver?).
+	 */
+
+	com_div_ctrl_save =
+		bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+						 COM_CLK_DIV_CTRL_SEL);
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+			  COM_CLK_DIV_CTRL_SEL,
+			  com_div_ctrl_save & ~(1 << COM_ULPD_PLL_CLK_REQ));
+}
+
+
+static void ulpd_resume(void)
+{
+	unsigned int val;
+
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh, SOFT_REQ_REG,
+			  soft_req_save);
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+			  SOFT_DISABLE_REQ_REG, soft_disable_req_save);
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh, CLOCK_CTRL_REG,
+			  clock_ctrl_save);
+	bus_space_write_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh,
+			  COM_CLK_DIV_CTRL_SEL, com_div_ctrl_save);
+
+	val = bus_space_read_2(ulpd_sc->sc_iot, ulpd_sc->sc_ioh, SLEEP_STATUS);
+
+	printf("ULPD awake");
+
+	if (val & BIG_SLEEP)
+		printf(" from Big Sleep");
+
+	if (val & DEEP_SLEEP)
+		printf(" from Deep Sleep");
+
+
+	printf("\n");
+}
+
+
+/* CONFIG */
+
+struct omapconfig_softc {
+        struct device           sc_dev;
+        bus_space_tag_t         sc_iot;
+        bus_space_handle_t      sc_ioh;
+};
+
+static struct omapconfig_softc *config_sc = NULL;
+
+static int omapconfig_match(struct device *, struct cfdata *, void *);
+static void omapconfig_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(omapconfig, sizeof(struct omapconfig_softc),
+	      omapconfig_match, omapconfig_attach, NULL, NULL);
+
+
+/* CONFIG register offsets */
+
+#define MOD_CONF_CTRL_0		0x80
+#define MOD_CONF_CTRL_1		0x110
+#define RESET_CONTROL		0x140
+
+/* MOD_CONF_CTRL_0 fields */
+
+#define CONF_MOD_MMC_SD_CLK_REQ_R	23
+#define CONF_MOD_COM_MCLK_12_48_SEL_R	12
+
+/* MOD_CONF_CTRL_1 fields */
+
+#define SSI_INTERCONNECT_GATE_EN_R	26
+#define OCP_INTERCON_GATE_EN_R		25
+#define CONF_MCBSP1_CLK_DIS		21
+
+/* RESET_CONTROL bitmasks */
+
+#define CONF_RNG_IDLE_MODE		0x40
+#define CONF_CAMERAIF_RESET_R		0x20
+#define CONF_UWIRE_RESET_R		0x10
+#define CONF_OSTIMER_RESET_R		0x08
+#define CONF_ARMIO_RESET_R		0x04
+#define CONF_SSI_RESET_R		0x02
+#define CONF_OCP_RESET_R		0x01
+
+static int config_set_mod_conf(struct hwclock *hwc, unsigned long reg,
+			       unsigned int bit, unsigned long value)
+{
+	unsigned int reg_val;
+	int s;
+
+	s = splhigh();
+	reg_val = bus_space_read_4(config_sc->sc_iot, config_sc->sc_ioh,
+				   reg);
+	if (value == HWCLOCK_ENABLED)
+		reg_val |= 0x1 << bit;
+	else
+		reg_val &= ~(0x1 << bit);
+
+	bus_space_write_4(config_sc->sc_iot, config_sc->sc_ioh,
+			  reg, reg_val);
+	splx(s);
+	return 0;
+}
+
+static int config_set_mclk_src(struct hwclock *hwc, enum hwclock_mclk_src src)
+{
+	int ret = 0;
+
+	switch (src) {
+	case MCLK_SYSTEM_CLOCK:
+		ret = config_set_mod_conf(hwc, MOD_CONF_CTRL_0,
+					  CONF_MOD_COM_MCLK_12_48_SEL_R,
+					  HWCLOCK_DISABLED);
+		break;
+
+	default:
+		ret = EINVAL; // todo: 48MHz sources
+	}
+
+	return ret;
+}
+
+static int config_set_mmcsdio1_enable(struct hwclock *hwc, unsigned long value)
+{
+	return config_set_mod_conf(hwc, MOD_CONF_CTRL_0,
+				   CONF_MOD_MMC_SD_CLK_REQ_R, value);
+}
+
+
+static int
+omapconfig_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct tipb_attach_args *tipb = aux;
+
+
+	if (tipb->tipb_addr == -1)
+		panic("omapconfig must have tipb bus addr specified in config.");
+
+	if (tipb->tipb_size == 0)
+		tipb->tipb_size = 2048;
+
+	return 1;
+}
+
+static void
+omapconfig_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct omapconfig_softc *sc = (struct omapconfig_softc*) self;
+	struct tipb_attach_args *tipb = aux;
+
+	sc->sc_iot = tipb->tipb_iot;
+
+	if (bus_space_map(sc->sc_iot, tipb->tipb_addr, tipb->tipb_size,
+			  0, &sc->sc_ioh))
+		panic("%s: Cannot map registers", self->dv_xname);
+
+	config_sc = sc;
+	aprint_normal(": Configuration module\n");
+
+        /* enable autoidle on OCP and SSI interconnect */
+
+	bus_space_write_4(config_sc->sc_iot, config_sc->sc_ioh,
+			  MOD_CONF_CTRL_1,
+			  bus_space_read_4(config_sc->sc_iot,
+					   config_sc->sc_ioh,
+					   MOD_CONF_CTRL_1)
+			  | (1 << SSI_INTERCONNECT_GATE_EN_R)
+			  | (1 << OCP_INTERCON_GATE_EN_R));
+}
+
+static unsigned int mod_conf0_save;
+static unsigned int mod_conf1_save;
+static unsigned int reset_control_save;
+
+static void config_suspend(void)
+{
+	/*
+	 * MOD_CONF_CTRL_*: Turn off various clocks.
+	 */
+
+	mod_conf0_save = bus_space_read_4(config_sc->sc_iot,
+					  config_sc->sc_ioh, MOD_CONF_CTRL_0);
+	bus_space_write_4(config_sc->sc_iot, config_sc->sc_ioh,
+			  MOD_CONF_CTRL_0, 0);
+	mod_conf1_save = bus_space_read_4(config_sc->sc_iot,
+					  config_sc->sc_ioh, MOD_CONF_CTRL_1);
+	bus_space_write_4(config_sc->sc_iot, config_sc->sc_ioh,
+			  MOD_CONF_CTRL_1, mod_conf1_save |
+			  (1 << CONF_MCBSP1_CLK_DIS));
+
+	/*
+	 * RESET_CONTROL: RNGidle disabled; camera IF, uWire, OS timer, MPUIO,
+	 * SSI, and OCP functional (not in reset).
+	 */
+
+	reset_control_save = 
+	    bus_space_read_4(config_sc->sc_iot, config_sc->sc_ioh,
+			     RESET_CONTROL);
+
+	bus_space_write_4(config_sc->sc_iot, config_sc->sc_ioh,
+			  RESET_CONTROL,
+			  CONF_CAMERAIF_RESET_R | CONF_UWIRE_RESET_R |
+			  CONF_OSTIMER_RESET_R | CONF_ARMIO_RESET_R |
+			  CONF_SSI_RESET_R | CONF_OCP_RESET_R);
+}
+
+
+static void config_resume(void)
+{
+	bus_space_write_4(config_sc->sc_iot, config_sc->sc_ioh,
+			  RESET_CONTROL, reset_control_save);
+	bus_space_write_4(config_sc->sc_iot, config_sc->sc_ioh,
+			  MOD_CONF_CTRL_1, mod_conf1_save);
+	bus_space_write_4(config_sc->sc_iot, config_sc->sc_ioh,
+			  MOD_CONF_CTRL_0, mod_conf0_save);
+}
+
+
+/* Suspend/resume */
+
+int hwclock_omap1_suspend(void)
+{
+	ulpd_suspend();
+	config_suspend();
+	return 0;
+}
+
+
+void hwclock_omap1_resume(void)
+{
+	ulpd_resume();
+	config_resume();
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/hwclock_omap1.h sys/arch/arm/omap/hwclock_omap1.h
--- ../../netbsd_40/src/sys/arch/arm/omap/hwclock_omap1.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/hwclock_omap1.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef _ARM_OMAP_HWCLOCK_H_
+#define _ARM_OMAP_HWCLOCK_H_
+
+enum hwclock_arch_attr {
+	AUTOIDLE,
+	SOURCE,
+	HWSWREQ,
+};
+
+enum hwclock_mclk_src {
+	MCLK_SYSTEM_CLOCK,	/* system clock on MCLK, boot default */
+	MCLK_APLL48,		/* APLL 48MHz clock on MCLK */
+	MCLK_APLL48DIV,		/* APLL 48MHz clock divided down on MCLK */
+};
+
+enum hwclock_hwswreq {
+	HWREQ,
+	SWREQ,
+};
+
+#define FLAG_HWREQ		0x0001 /* Use h/w, not s/w, clock request */
+
+struct hwclock_machine {
+	unsigned int freq_field;
+	unsigned long enable_reg;
+	unsigned int enable_field;
+	unsigned int swreqenable_bit;
+	unsigned int hwreqdisable_bit;
+	unsigned int flags;
+	unsigned long pm_reg;
+	unsigned int pm_field;
+	unsigned int src;
+};
+
+
+extern int hwclock_omap1_suspend(void);
+extern void hwclock_omap1_resume(void);
+
+#endif /* _ARM_OMAP_HWCLOCK_H_ */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/obio_com.c sys/arch/arm/omap/obio_com.c
--- ../../netbsd_40/src/sys/arch/arm/omap/obio_com.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/obio_com.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,224 @@
+/*	$NetBSD$	*/
+
+/*
+ * Based on arch/arm/omap/omap_com.c
+ *
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed for the NetBSD Project by
+ *      Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * OMAP support Copyright (c) 2007 Danger Inc
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: omap_com.c,v 1.1.6.1 2007/02/21 18:27:16 snj Exp $");
+
+#include "opt_omap.h"
+#include "opt_com.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/termios.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+
+#include <arm/omap/omap_reg.h>
+#if defined(OMAP_2430)
+# include <arm/omap/omap2430obiovar.h>
+# include <arm/omap/omap2430reg.h>
+#else
+# error unknown OMAP implementation
+#endif
+#include <arm/omap/omap_com.h>
+
+#include "locators.h"
+
+static int	obiouart_match(struct device *, struct cfdata *, void *);
+static void	obiouart_attach(struct device *, struct device *, void *);
+static int	uart_enable(struct obio_attach_args *);
+static void	obiouart_callout(void *);
+
+struct com_obio_softc {
+	struct com_softc sc_sc;
+	struct callout sc_callout;
+};
+
+CFATTACH_DECL(obiouart, sizeof(struct com_obio_softc),
+    obiouart_match, obiouart_attach, NULL, NULL);
+
+static int
+obiouart_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+	struct obio_attach_args *obio = aux;
+	bus_space_handle_t bh;
+	int rv;
+
+	if (obio->obio_addr == OBIOCF_ADDR_DEFAULT)
+		panic("obiouart must have addr specified in config.");
+
+#if !defined(OMAP_2430)
+	/*
+	 * XXX this should be ifdefed on a board-dependent switch
+	 * We don't know what is the irq for com0 on the sdp2430 
+	 */
+	if (obio->obio_intr == OBIOCF_INTR_DEFAULT)
+		panic("obiouart must have addr specified in config.");
+#endif
+
+	if (obio->obio_size == OBIOCF_SIZE_DEFAULT)
+		obio->obio_size = OMAP_COM_SIZE;
+
+	if (com_is_console(obio->obio_iot, obio->obio_addr, NULL))
+		return 1;
+
+	if (uart_enable(obio) != 0)
+		return 1;
+
+	if (bus_space_map(obio->obio_iot, obio->obio_addr, obio->obio_size,
+			  0, &bh))
+		return 1;
+
+	rv = comprobe1(obio->obio_iot, bh);
+
+	bus_space_unmap(obio->obio_iot, bh, obio->obio_size);
+
+	return rv;
+}
+
+static void
+obiouart_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct com_obio_softc *osc = (struct com_obio_softc *)self;
+	struct com_softc *sc = (struct com_softc *)self;
+	struct obio_attach_args *obio = aux;
+	bus_space_tag_t iot;
+	bus_space_handle_t ioh = 0;
+	bus_addr_t iobase;
+
+
+	iot = obio->obio_iot;
+	iobase = obio->obio_addr;
+	sc->sc_frequency = OMAP_COM_FREQ;
+	sc->sc_type = COM_TYPE_NORMAL;
+
+	if (com_is_console(iot, iobase, &ioh) == 0 &&
+	    bus_space_map(iot, iobase, obio->obio_size, 0, &ioh)) {
+		panic(": can't map registers\n");
+		return;
+	}
+	COM_INIT_REGS(sc->sc_regs, iot, ioh, iobase);
+
+	com_attach_subr(sc);
+	aprint_naive("\n");
+
+	if (obio->obio_intr != OBIOCF_INTR_DEFAULT) {
+		omap_intr_establish(obio->obio_intr, IPL_SERIAL,
+			sc->sc_dev.dv_xname, comintr, sc);
+	} else {
+		callout_init(&osc->sc_callout);
+		callout_reset(&osc->sc_callout, 1, obiouart_callout, osc);
+	}
+}
+
+static void
+obiouart_callout(void *arg)
+{
+	struct com_obio_softc * const osc = arg;
+	int s;
+	s = splserial();
+	comintr(arg);
+	splx(s);
+	callout_schedule(&osc->sc_callout, 1);
+}
+
+
+#if defined(OMAP_2430)
+static int
+uart_enable(struct obio_attach_args *obio)
+{
+	bus_space_handle_t ioh;
+	uint32_t r;
+	uint32_t fclken1;
+	uint32_t iclken1;
+	int err;
+	int n=-1;
+
+	KASSERT(obio != NULL);
+
+	err = bus_space_map(obio->obio_iot, OMAP2430_CM_BASE,
+		OMAP2430_CM_SIZE, 0, &ioh);
+	KASSERT(err == 0);
+
+
+	switch(obio->obio_addr) {
+	case 0x4806a000:
+		fclken1 = OMAP2430_CM_FCLKEN1_CORE_EN_UART1;
+		iclken1 = OMAP2430_CM_ICLKEN1_CORE_EN_UART1;
+		n = 1;
+		break;
+	case 0x4806c000:
+		fclken1 = OMAP2430_CM_FCLKEN1_CORE_EN_UART2;
+		iclken1 = OMAP2430_CM_ICLKEN1_CORE_EN_UART2;
+		n = 2;
+		break;
+	case 0x4806e000:
+		fclken1 = OMAP2430_CM_FCLKEN2_CORE_EN_UART3;
+		iclken1 = OMAP2430_CM_ICLKEN2_CORE_EN_UART3;
+		n = 3;
+		break;
+	default:
+		goto err;
+	}
+
+printf("%s: UART#%d\n", __func__, n);
+
+	r = bus_space_read_4(obio->obio_iot, ioh, OMAP2430_CM_FCLKEN1_CORE);
+	r |= fclken1;
+	bus_space_write_4(obio->obio_iot, ioh, OMAP2430_CM_FCLKEN1_CORE, r);
+
+	r = bus_space_read_4(obio->obio_iot, ioh, OMAP2430_CM_ICLKEN1_CORE);
+	r |= iclken1;
+	bus_space_write_4(obio->obio_iot, ioh, OMAP2430_CM_ICLKEN1_CORE, r);
+
+err:
+//	bus_space_unmap(obio->obio_iot, ioh, OMAP2430_CM_SIZE);
+
+	return 0;
+}
+#else
+# error unknown OMAP implementation
+#endif
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/obio_mputmr.c sys/arch/arm/omap/obio_mputmr.c
--- ../../netbsd_40/src/sys/arch/arm/omap/obio_mputmr.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/obio_mputmr.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,385 @@
+/* $NetBSD$ */
+
+/*
+ * Based on omap_mputmr.c
+ * Based on i80321_timer.c and arch/arm/sa11x0/sa11x0_ost.c
+ *
+ * Copyright (c) 1997 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed for the NetBSD Project by
+ *	Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: omap_mputmr.c,v 1.1.6.1 2007/02/21 18:27:17 snj Exp $");
+
+#include "opt_omap.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+#include <sys/device.h>
+
+#include <dev/clock_subr.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <arm/omap/omap_reg.h>
+#include <arm/omap/omap2430obiovar.h>
+
+#include <arm/omap/omapmputmrvar.h>
+#include <arm/omap/omapmputmrreg.h>
+
+
+#if defined(OMAP_2430)
+# include <arm/omap/omap2430reg.h>
+#else
+# error unknown OMAP implementation
+#endif
+
+
+#ifndef OMAP_MPU_TIMER_CLOCK_FREQ
+#error Specify the timer frequency in Hz with the OMAP_MPU_TIMER_CLOCK_FREQ option.
+#endif
+
+#if defined(OMAP_2430)
+typedef struct {
+	uint       gptn;
+	bus_addr_t addr;
+	uint       intr;
+	uint32_t   clksel2;
+	uint32_t   fclken1;
+	uint32_t   iclken1;
+} gptimer_instance_t;
+
+/* XXX
+ * this table can be used to initialize the GP Timers
+ * until we use config(8) locators for CLKSEL2 values, you may want to edit here.
+ */
+static gptimer_instance_t gptimer_instance_tab[] = {
+	{
+		2, 0x4802a000, 38,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(2, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT2,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT2,
+	},
+	{
+		3, 0x48078000, 39,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(3, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT3,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT3,
+	},
+	{
+		4, 0x4807A000, 40,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(4, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT4,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT4,
+	},
+	{
+		5, 0x4807C000, 41,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(5, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT5,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT5,
+	},
+	{
+		6, 0x4807E000, 42,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(6, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT6,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT6,
+	},
+	{
+		7, 0x48080000, 43,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(7, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT7,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT7,
+	},
+	{
+		8, 0x48082000, 44,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(8, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT8,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT8,
+	},
+	{
+		9, 0x48084000, 45,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(9, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT9,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT9,
+	},
+	{
+		10, 0x48086000, 46,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(10, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT10,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT10,
+	},
+	{
+		11, 0x48088000, 47,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(11, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT11,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT11,
+	},
+	{
+		12, 0x4808A000, 48,
+		OMAP2430_CM_CLKSEL2_CORE_GPTn(12, CLKSEL2_CORE_GPT_SYS_CLK),
+		OMAP2430_CM_FCLKEN1_CORE_EN_GPT12,
+		OMAP2430_CM_ICLKEN1_CORE_EN_GPT12,
+	},
+};
+#define GPTIMER_INSTANCE_CNT \
+		(sizeof(gptimer_instance_tab) / sizeof(gptimer_instance_tab[0]))
+
+static gptimer_instance_t *
+		gpt_lookup(struct obio_attach_args *);
+static void	gpt_enable(struct omapmputmr_softc *,
+			struct obio_attach_args *, gptimer_instance_t *);
+#endif	/* OMAP_2430 */
+
+
+static int	obiomputmr_match(struct device *, struct cfdata *, void *);
+static void	obiomputmr_attach(struct device *, struct device *, void *);
+
+
+
+CFATTACH_DECL(obiomputmr, sizeof(struct omapmputmr_softc),
+    obiomputmr_match, obiomputmr_attach, NULL, NULL);
+
+static int
+obiomputmr_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct obio_attach_args *obio = aux;
+
+	if (obio->obio_addr == -1 || obio->obio_intr == -1)
+	    panic("omapmputmr must have addr and intr specified in config.");
+
+	if (obio->obio_size == 0)
+		obio->obio_size = 256;	/* Per the OMAP TRM. */
+
+#ifdef OMAP_2430
+	if (gpt_lookup(obio) == NULL)
+		return 0;
+#endif
+
+	/* We implicitly trust the config file. */
+	return 1;
+}
+
+void
+obiomputmr_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct omapmputmr_softc *sc = (struct omapmputmr_softc*)self;
+	struct obio_attach_args *obio = aux;
+	int ints_per_sec;
+
+
+	sc->sc_iot = obio->obio_iot;
+	sc->sc_intr = obio->obio_intr;
+
+	if (bus_space_map(obio->obio_iot, obio->obio_addr, obio->obio_size, 0,
+			 &sc->sc_ioh))
+		panic("%s: Cannot map registers", self->dv_xname);
+
+	switch (self->dv_unit) {
+	case 0:
+		clock_sc = sc;
+		ints_per_sec = hz;
+		break;
+	case 1:
+		stat_sc = sc;
+		ints_per_sec = profhz = stathz = STATHZ;
+		break;
+	case 2:
+		ref_sc = sc;
+		ints_per_sec = hz;	/* Same rate as clock */
+		break;
+	default:
+		ints_per_sec = hz;	/* Better value? */
+		break;
+	}
+
+	aprint_normal(": OMAP MPU Timer");
+#ifdef OMAP_2430
+	gpt_enable(sc, obio, gpt_lookup(obio));
+#endif
+	aprint_normal("\n");
+	aprint_naive("\n");
+
+	/* Stop the timer from counting, but keep the timer module working. */
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MPU_CNTL_TIMER,
+			  MPU_CLOCK_ENABLE);
+
+	timer_factors tf;
+	calc_timer_factors(ints_per_sec, &tf);
+
+	switch (self->dv_unit) {
+	case 0:
+		counts_per_hz = tf.reload + 1;
+		counts_per_usec = tf.counts_per_usec;
+		break;
+	case 2:
+
+		/*
+		 * The microtime reference clock for all practical purposes
+		 * just wraps around as an unsigned int.
+		 */
+
+		tf.reload = 0xffffffff;
+		break;
+
+	default:
+		break;
+	}
+
+	/* Set the reload value. */
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MPU_LOAD_TIMER, tf.reload);
+	/* Set the PTV and the other required bits and pieces. */
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MPU_CNTL_TIMER,
+			  ( MPU_CLOCK_ENABLE
+			    | (tf.ptv << MPU_PTV_SHIFT)
+			    | MPU_AR
+			    | MPU_ST));
+	/* The clock is now running, but is not generating interrupts. */
+}
+
+static gptimer_instance_t *
+gpt_lookup(struct obio_attach_args *obio)
+{
+	gptimer_instance_t *ip = NULL;
+	uint i;
+
+	ip = gptimer_instance_tab;
+	for (i=0; i < GPTIMER_INSTANCE_CNT; i++) {
+		if ((ip->addr == obio->obio_addr)
+		&&  (ip->intr == obio->obio_intr))
+			break;
+		ip++;
+	}
+
+
+	return ip;
+}
+
+void
+gpt_enable(
+	struct omapmputmr_softc *sc,
+	struct obio_attach_args *obio,
+	gptimer_instance_t *ip)
+{
+	bus_space_handle_t ioh;
+	uint32_t r;
+	int err;
+
+	KASSERT(ip != NULL);
+
+
+	aprint_normal(" #%d", ip->gptn);
+
+	err = bus_space_map(obio->obio_iot, OMAP2430_CM_BASE,
+		OMAP2430_CM_SIZE, 0, &ioh);
+	KASSERT(err == 0);
+
+	r = bus_space_read_4(obio->obio_iot, ioh, OMAP2430_CM_CLKSEL2_CORE);
+	r |= ip->clksel2;
+	bus_space_write_4(obio->obio_iot, ioh, OMAP2430_CM_CLKSEL2_CORE, r);
+
+	r = bus_space_read_4(obio->obio_iot, ioh, OMAP2430_CM_FCLKEN1_CORE);
+	r |= ip->fclken1;
+	bus_space_write_4(obio->obio_iot, ioh, OMAP2430_CM_FCLKEN1_CORE, r);
+
+	r = bus_space_read_4(obio->obio_iot, ioh, OMAP2430_CM_ICLKEN1_CORE);
+	r |= ip->iclken1;
+	bus_space_write_4(obio->obio_iot, ioh, OMAP2430_CM_ICLKEN1_CORE, r);
+
+	bus_space_unmap(obio->obio_iot, ioh, OMAP2430_CM_SIZE);
+}
+
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/obio_wdt.c sys/arch/arm/omap/obio_wdt.c
--- ../../netbsd_40/src/sys/arch/arm/omap/obio_wdt.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/obio_wdt.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * obio attachment for OMAP watchdog timers
+ */
+#include "opt_omap.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: $");
+
+#include <sys/param.h>
+#include <sys/callout.h>
+#include <sys/cdefs.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/wdog.h>
+
+#include <machine/param.h>
+#include <machine/bus.h>
+#include <dev/sysmon/sysmonvar.h>
+
+#include <arm/omap/omap_reg.h>
+
+#if defined(OMAP_2430)
+#include <arm/omap/omap2430obiovar.h>
+#else
+#error unknown OMAP implementation
+#endif
+
+#include <arm/omap/omap_wdt.h>
+#include <arm/omap/omap_wdtvar.h>
+#include <arm/omap/omap_wdtreg.h>
+
+static int obiowdt32k_match(struct device *, struct cfdata *, void *);
+static void obiowdt32k_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(obiowdt32k, sizeof(struct omapwdt32k_softc),
+    obiowdt32k_match, obiowdt32k_attach, NULL, NULL);
+
+static int
+obiowdt32k_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+	return (1);
+}
+
+static void
+obiowdt32k_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct omapwdt32k_softc *sc = (void *)self;
+	struct obio_attach_args *obio = aux;
+	unsigned int val;
+
+	sc->sc_smw.smw_name = sc->sc_dev.dv_xname;
+	sc->sc_smw.smw_cookie = sc;
+	sc->sc_smw.smw_setmode = omapwdt32k_setmode;
+	sc->sc_smw.smw_tickle = omapwdt32k_tickle;
+	sc->sc_smw.smw_period = OMAPWDT32K_DEFAULT_PERIOD;
+	sc->sc_iot = obio->obio_iot;
+
+	if (bus_space_map(sc->sc_iot, obio->obio_addr, obio->obio_size,
+			  0, &sc->sc_ioh))
+		panic("%s: Cannot map registers", self->dv_xname);
+
+	val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, WIDR);
+	aprint_normal(": rev %d.%d\n", (val & WD_REV) >> 4,
+		      (val & WD_REV & 0xf));
+
+	if (sysmon_wdog_register(&sc->sc_smw) != 0)
+		aprint_error("%s: unable to register with sysmon\n",
+			     sc->sc_dev.dv_xname);
+
+	omapwdt32k_sc = sc;
+
+	/* Turn on autoidle. */
+
+    	omapwdt_sysconfig = 
+	    bus_space_read_4(omapwdt32k_sc->sc_iot,
+			     omapwdt32k_sc->sc_ioh, WD_SYSCONFIG) |
+	    (1 << WD_SYSCONFIG_AUTOIDLE);
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh,
+			  WD_SYSCONFIG, omapwdt_sysconfig);
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap2430_intr.c sys/arch/arm/omap/omap2430_intr.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap2430_intr.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap2430_intr.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,738 @@
+/*
+ * Define the SDP2430 specific information and then include the generic OMAP
+ * interrupt header.
+ */
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "opt_omap.h"
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: $");
+
+#include <sys/param.h>
+#include <sys/evcnt.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <machine/intr.h>
+
+#include <arm/cpu.h>
+#include <arm/armreg.h>
+#include <arm/cpufunc.h>
+#include <machine/atomic.h>
+#include <arm/softintr.h>
+#include <arm/omap/omap2430reg.h>
+#include <arm/omap/omap2430reg.h>
+
+#include <machine/bus.h>
+
+#define	NIGROUPS	8
+
+#define	IRQ_SOFTSERIAL	M_IRQ_22
+#define	IRQ_SOFTCLOCK	M_IRQ_23
+#define	IRQ_SOFTNET	M_IRQ_34
+#define	IRQ_SOFT	M_IRQ_35
+
+#define	SOFTIPL_MASK	(BIT(IPL_SOFT)|BIT(IPL_SOFTCLOCK)|\
+			 BIT(IPL_SOFTNET)|BIT(IPL_SOFTSERIAL))
+
+struct intrsource {
+	struct evcnt is_ev;
+	uint8_t is_ipl;
+	uint8_t is_group;
+	int (*is_func)(void *);
+	void *is_arg;
+	uint64_t is_marked;
+};
+
+static struct intrgroup {
+	uint32_t ig_irqsbyipl[NIPL];
+	uint32_t ig_irqs;
+	volatile uint32_t ig_pending_irqs;
+	uint32_t ig_enabled_irqs;
+	uint32_t ig_edge_rising;
+	uint32_t ig_edge_falling;
+	uint32_t ig_level_low;
+	uint32_t ig_level_high;
+	struct intrsource ig_sources[32];
+	bus_space_tag_t ig_memt;
+	bus_space_handle_t ig_memh;
+} intrgroups[NIGROUPS] = {
+	[0].ig_sources[ 0 ... 31 ].is_group = 0,
+	[1].ig_sources[ 0 ... 31 ].is_group = 1,
+	[2].ig_sources[ 0 ... 31 ].is_group = 2,
+	[3].ig_sources[ 0 ... 31 ].is_group = 3,
+	[4].ig_sources[ 0 ... 31 ].is_group = 4,
+	[5].ig_sources[ 0 ... 31 ].is_group = 5,
+	[6].ig_sources[ 0 ... 31 ].is_group = 6,
+	[7].ig_sources[ 0 ... 31 ].is_group = 7,
+	[IRQ_SOFTSERIAL/32].ig_sources[IRQ_SOFTSERIAL&31] = {
+		.is_ev = EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL,
+					   "soft serial", "intr"),
+		.is_ipl = IPL_SOFTSERIAL,
+		.is_func = (int (*)(void *)) softintr_dispatch,
+		.is_arg = (void *) SI_SOFTSERIAL,
+		.is_group = IRQ_SOFTSERIAL/32,
+	},
+	[IRQ_SOFTCLOCK/32].ig_sources[IRQ_SOFTCLOCK&31] = {
+		.is_ev = EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL,
+					   "soft clock", "intr"),
+		.is_ipl = IPL_SOFTCLOCK,
+		.is_func = (int (*)(void *)) softintr_dispatch,
+		.is_arg = (void *) SI_SOFTCLOCK,
+		.is_group = IRQ_SOFTCLOCK/32,
+	},
+	[IRQ_SOFTNET/32].ig_sources[IRQ_SOFTNET&31] = {
+		.is_ev = EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL,
+					   "soft net", "intr"),
+		.is_ipl = IPL_SOFTNET,
+		.is_func = (int (*)(void *)) softintr_dispatch,
+		.is_arg = (void *) SI_SOFTNET,
+		.is_group = IRQ_SOFTNET/32,
+	},
+	[IRQ_SOFT/32].ig_sources[IRQ_SOFT&31] = {
+		.is_ev = EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL,
+					   "soft", "intr"),
+		.is_ipl = IPL_SOFT,
+		.is_func = (int (*)(void *)) softintr_dispatch,
+		.is_arg = (void *) SI_SOFT,
+		.is_group = IRQ_SOFT/32,
+	},
+};
+
+int current_spl_level;
+volatile uint32_t pending_ipls;
+volatile uint32_t pending_igroupsbyipl[NIPL];
+void omap2430_intr_init(bus_space_tag_t);
+
+#define	INTC_READ(ig, o)		\
+	bus_space_read_4((ig)->ig_memt, (ig)->ig_memh, o)
+#define	INTC_WRITE(ig, o, v)	\
+	bus_space_write_4((ig)->ig_memt, (ig)->ig_memh, o, v)
+#define	GPIO_READ(ig, o)		\
+	bus_space_read_4((ig)->ig_memt, (ig)->ig_memh, o)
+#define	GPIO_WRITE(ig, o, v)	\
+	bus_space_write_4((ig)->ig_memt, (ig)->ig_memh, o, v)
+
+static void
+unblock_irq(unsigned int group, int irq_mask)
+{
+	struct intrgroup * const ig = &intrgroups[group];
+	KASSERT((irq_mask & ig->ig_enabled_irqs) == 0);
+	ig->ig_enabled_irqs |= irq_mask;
+	if (group < 3) {
+		INTC_WRITE(ig, INTC_MIR_CLEAR, irq_mask);
+	} else {
+		GPIO_WRITE(ig, GPIO_SETIRQENABLE1, irq_mask);
+		/*
+		 * Clear IRQSTATUS of level interrupts, if they are still
+		 * asserted, IRQSTATUS will become set again and they will
+		 * refire.  This avoids one spurious interrupt for every
+		 * real interrupt.
+		 */
+		if (irq_mask & (ig->ig_level_low|ig->ig_level_high))
+			GPIO_WRITE(ig, GPIO_IRQSTATUS1,
+			    irq_mask & (ig->ig_level_low|ig->ig_level_high));
+	}
+
+	/* Force INTC to recompute IRQ availability */
+	INTC_WRITE(&intrgroups[0], INTC_CONTROL, INTC_CONTROL_NEWIRQAGR);
+}
+
+static void
+block_irq(unsigned int group, int irq_mask)
+{
+	struct intrgroup * const ig = &intrgroups[group];
+	ig->ig_enabled_irqs &= ~irq_mask;
+	if (group < 3) {
+		INTC_WRITE(ig, INTC_MIR_SET, irq_mask);
+		return;
+	}
+	GPIO_WRITE(ig, GPIO_CLEARIRQENABLE1, irq_mask);
+	/*
+	 * Only clear(reenable) edge interrupts.
+	 */
+	if (irq_mask & (ig->ig_edge_falling|ig->ig_edge_rising))
+		GPIO_WRITE(ig, GPIO_IRQSTATUS1, /* reset int bits */
+		    irq_mask & (ig->ig_edge_falling|ig->ig_edge_rising));
+}
+
+static void
+init_irq(int irq, int spl, int type)
+{
+	struct intrgroup * const ig = &intrgroups[irq / 32];
+	uint32_t irq_mask = BIT(irq & 31);
+	uint32_t v;
+
+	KASSERT(irq >= 0 && irq < 256);
+	ig->ig_sources[irq & 31].is_ipl = spl;
+	if (irq < 96) {
+		KASSERT(type == IST_LEVEL);
+		return;
+	}
+
+	ig->ig_enabled_irqs &= ~irq_mask;
+	GPIO_WRITE(ig, GPIO_CLEARIRQENABLE1, irq_mask);
+
+	v = GPIO_READ(ig, GPIO_OE);
+	GPIO_WRITE(ig, GPIO_OE, v | irq_mask);	/* set as input */
+
+	ig->ig_edge_rising &= ~irq_mask;
+	ig->ig_edge_falling &= ~irq_mask;
+	ig->ig_level_low &= ~irq_mask;
+	ig->ig_level_high &= ~irq_mask;
+
+	switch (type) {
+	case IST_EDGE_BOTH:
+		ig->ig_edge_rising |= irq_mask;
+		ig->ig_edge_falling |= irq_mask;
+		break;
+	case IST_EDGE_RISING:
+		ig->ig_edge_rising |= irq_mask;
+		break;
+	case IST_EDGE_FALLING:
+		ig->ig_edge_falling |= irq_mask;
+		break;
+	case IST_LEVEL_LOW:
+		ig->ig_level_low |= irq_mask;
+		break;
+	case IST_LEVEL_HIGH:
+		ig->ig_level_high |= irq_mask;
+		break;
+	}
+
+	GPIO_WRITE(ig, GPIO_LEVELDETECT0, ig->ig_level_low);
+	GPIO_WRITE(ig, GPIO_LEVELDETECT1, ig->ig_level_high);
+	GPIO_WRITE(ig, GPIO_RISINGDETECT, ig->ig_edge_rising);
+	GPIO_WRITE(ig, GPIO_FALLINGDETECT, ig->ig_edge_falling);
+}
+
+/*
+ * Called with interrupt disabled
+ */
+static void
+calculate_irq_masks(struct intrgroup *ig)
+{
+	u_int irq;
+	int ipl;
+	uint32_t irq_mask;
+
+	memset(ig->ig_irqsbyipl, 0, sizeof(ig->ig_irqsbyipl));
+	ig->ig_irqs = 0;
+
+	for (irq_mask = 1, irq = 0; irq < 32; irq_mask <<= 1, irq++) {
+		if ((ipl = ig->ig_sources[irq].is_ipl) == IPL_NONE)
+			continue;
+
+		ig->ig_irqsbyipl[ipl] |= irq_mask;
+		ig->ig_irqs |= irq_mask;
+	}
+}
+
+/*
+ * Called with interrupts disabled
+ */
+static uint32_t
+mark_pending_irqs(int group, uint32_t pending)
+{
+	struct intrgroup * const ig = &intrgroups[group];
+	struct intrsource *is;
+	int n;
+	int ipl_mask = 0;
+
+	if (pending == 0)
+		return ipl_mask;
+
+	KASSERT((ig->ig_enabled_irqs & pending) == pending);
+	KASSERT((ig->ig_pending_irqs & pending) == 0);
+
+	ig->ig_pending_irqs |= pending;
+	block_irq(group, pending);
+	for (;;) {
+		n = ffs(pending);
+		if (n-- == 0)
+			break;
+		is = &ig->ig_sources[n];
+		KASSERT(ig->ig_irqsbyipl[is->is_ipl] & pending);
+		pending &= ~ig->ig_irqsbyipl[is->is_ipl];
+		ipl_mask |= BIT(is->is_ipl);
+		KASSERT(ipl_mask < BIT(NIPL));
+		pending_igroupsbyipl[is->is_ipl] |= BIT(group);
+		is->is_marked++;
+	}
+	KASSERT(ipl_mask < BIT(NIPL));
+	return ipl_mask;
+}
+
+/*
+ * Called with interrupts disabled
+ */
+static uint32_t
+get_pending_irqs(void)
+{
+	uint32_t pending[3];
+	uint32_t ipl_mask = 0;
+	uint32_t xpending;
+
+	pending[0] = INTC_READ(&intrgroups[0], INTC_PENDING_IRQ);
+	pending[1] = INTC_READ(&intrgroups[1], INTC_PENDING_IRQ);
+	pending[2] = INTC_READ(&intrgroups[2], INTC_PENDING_IRQ);
+
+	/* Get interrupt status of GPIO1 */
+	if (pending[GPIO1_MPU_IRQ / 32] & BIT(GPIO1_MPU_IRQ & 31)) {
+		KASSERT(intrgroups[3].ig_enabled_irqs);
+		xpending = GPIO_READ(&intrgroups[3], GPIO_IRQSTATUS1);
+		xpending &= intrgroups[3].ig_enabled_irqs;
+		ipl_mask |= mark_pending_irqs(3, xpending);
+	}
+
+	/* Get interrupt status of GPIO2 */
+	if (pending[GPIO2_MPU_IRQ / 32] & BIT(GPIO2_MPU_IRQ & 31)) {
+		KASSERT(intrgroups[4].ig_enabled_irqs);
+		xpending = GPIO_READ(&intrgroups[4], GPIO_IRQSTATUS1);
+		xpending &= intrgroups[4].ig_enabled_irqs;
+		ipl_mask |= mark_pending_irqs(4, xpending);
+	}
+
+	/* Get interrupt status of GPIO3 */
+	if (pending[GPIO3_MPU_IRQ / 32] & BIT(GPIO3_MPU_IRQ & 31)) {
+		KASSERT(intrgroups[5].ig_enabled_irqs);
+		xpending = GPIO_READ(&intrgroups[5], GPIO_IRQSTATUS1);
+		xpending &= intrgroups[5].ig_enabled_irqs;
+		ipl_mask |= mark_pending_irqs(5, xpending);
+	}
+
+	/* Get interrupt status of GPIO4 */
+	if (pending[GPIO4_MPU_IRQ / 32] & BIT(GPIO4_MPU_IRQ & 31)) {
+		KASSERT(intrgroups[6].ig_enabled_irqs);
+		xpending = GPIO_READ(&intrgroups[6], GPIO_IRQSTATUS1);
+		xpending &= intrgroups[6].ig_enabled_irqs;
+		ipl_mask |= mark_pending_irqs(6, xpending);
+	}
+
+	/* Get interrupt status of GPIO5 */
+	if (pending[GPIO5_MPU_IRQ / 32] & BIT(GPIO5_MPU_IRQ & 31)) {
+		KASSERT(intrgroups[7].ig_enabled_irqs);
+		xpending = GPIO_READ(&intrgroups[7], GPIO_IRQSTATUS1);
+		xpending = GPIO_READ(&intrgroups[7], GPIO_IRQSTATUS1);
+		xpending &= intrgroups[7].ig_enabled_irqs;
+		ipl_mask |= mark_pending_irqs(7, xpending);
+	}
+
+	/* Clear GPIO indication from summaries */
+	pending[GPIO1_MPU_IRQ / 32] &= ~BIT(GPIO1_MPU_IRQ & 31);
+	pending[GPIO2_MPU_IRQ / 32] &= ~BIT(GPIO2_MPU_IRQ & 31);
+	pending[GPIO3_MPU_IRQ / 32] &= ~BIT(GPIO3_MPU_IRQ & 31);
+	pending[GPIO4_MPU_IRQ / 32] &= ~BIT(GPIO4_MPU_IRQ & 31);
+	pending[GPIO5_MPU_IRQ / 32] &= ~BIT(GPIO5_MPU_IRQ & 31);
+
+	/* Now handle the primaries interrupt summaries */
+	ipl_mask |= mark_pending_irqs(0, pending[0]);
+	ipl_mask |= mark_pending_irqs(1, pending[1]);
+	ipl_mask |= mark_pending_irqs(2, pending[2]);
+
+	/* Force INTC to recompute IRQ availability */
+	INTC_WRITE(&intrgroups[0], INTC_CONTROL, INTC_CONTROL_NEWIRQAGR);
+
+	return ipl_mask;
+}
+
+static int last_delivered_ipl;
+static u_long no_pending_irqs[NIPL][NIGROUPS];
+
+static void
+deliver_irqs(register_t psw, int ipl, void *frame)
+{
+	struct intrgroup *ig;
+	struct intrsource *is;
+	uint32_t pending_irqs;
+	uint32_t irq_mask;
+	uint32_t blocked_irqs;
+	volatile uint32_t * const pending_igroups = &pending_igroupsbyipl[ipl];
+	const uint32_t ipl_mask = BIT(ipl);
+	int n;
+	int saved_ipl;
+	unsigned int group;
+	int rv;
+
+	if (frame == NULL) {
+		saved_ipl = last_delivered_ipl;
+		KASSERT(saved_ipl < ipl);
+		last_delivered_ipl = ipl;
+	}
+	/*
+	 * We only must be called is there is this IPL has pending interrupts
+	 * and therefore there must be at least one intrgroup with a pending
+	 * interrupt.
+	 */
+	KASSERT(pending_ipls & ipl_mask);
+	KASSERT(*pending_igroups);
+
+	/*
+	 * We loop until there are no more intrgroups with pending interrupts.
+	 */
+	do {
+		group = 31 - __builtin_clz(*pending_igroups);
+		KASSERT(group < NIGROUPS);
+
+		ig = &intrgroups[group];
+		irq_mask = ig->ig_irqsbyipl[ipl];
+		pending_irqs = ig->ig_pending_irqs & irq_mask;
+		blocked_irqs = pending_irqs;
+		if ((*pending_igroups &= ~BIT(group)) == 0)
+			pending_ipls &= ~ipl_mask;
+		/*
+		 * We couldn't gotten here unless there was at least one
+		 * pending interrupt in this intrgroup.
+		 */
+		if (pending_irqs == 0) {
+			no_pending_irqs[ipl][group]++;
+			continue;
+		}
+		do {
+			n = 31 - __builtin_clz(pending_irqs);
+			KASSERT(ig->ig_irqs & BIT(n));
+			KASSERT(irq_mask & BIT(n));
+
+			/*
+			 * If this was the last bit cleared for this IRQ,
+			 * we need to clear this group's bit in 
+			 * pending_igroupsbyipl[ipl].  Now if that's now 0,
+			 * we need to clear pending_ipls for this IPL.
+			 */
+			ig->ig_pending_irqs &= ~BIT(n);
+			if (irq_mask == BIT(n))
+				KASSERT((ig->ig_pending_irqs & irq_mask) == 0);
+			is = &ig->ig_sources[n];
+			if (__predict_false(frame != NULL)) {
+				(*is->is_func)(frame);
+			} else {
+				restore_interrupts(psw);
+				rv = (*is->is_func)(is->is_arg);
+				disable_interrupts(I32_bit);
+			}
+			is->is_ev.ev_count++;
+			pending_irqs = ig->ig_pending_irqs & irq_mask;
+		} while (pending_irqs);
+		/*
+		 * We don't block the interrupts individually because even if
+		 * one was unblocked it couldn't be delivered since our
+		 * current IPL would prevent it.  So we wait until we can do
+		 * them all at once.
+		 */
+		if ((ipl_mask & SOFTIPL_MASK) == 0)
+			unblock_irq(group, blocked_irqs);
+	} while (*pending_igroups);
+	/*
+	 * Since there are no more pending interrupts for this IPL,
+	 * this IPL must not be present in the pending IPLs.
+	 */
+	KASSERT((pending_ipls & ipl_mask) == 0);
+	KASSERT((intrgroups[0].ig_pending_irqs & intrgroups[0].ig_irqsbyipl[ipl]) == 0);
+	KASSERT((intrgroups[1].ig_pending_irqs & intrgroups[1].ig_irqsbyipl[ipl]) == 0);
+	KASSERT((intrgroups[2].ig_pending_irqs & intrgroups[2].ig_irqsbyipl[ipl]) == 0);
+	KASSERT((intrgroups[3].ig_pending_irqs & intrgroups[3].ig_irqsbyipl[ipl]) == 0);
+	KASSERT((intrgroups[4].ig_pending_irqs & intrgroups[4].ig_irqsbyipl[ipl]) == 0);
+	KASSERT((intrgroups[5].ig_pending_irqs & intrgroups[5].ig_irqsbyipl[ipl]) == 0);
+	KASSERT((intrgroups[6].ig_pending_irqs & intrgroups[6].ig_irqsbyipl[ipl]) == 0);
+	KASSERT((intrgroups[7].ig_pending_irqs & intrgroups[7].ig_irqsbyipl[ipl]) == 0);
+	if (frame == NULL)
+		last_delivered_ipl = saved_ipl;
+}
+
+static inline void
+do_pending_ints(register_t psw, int newipl)
+{
+	while ((pending_ipls & ~BIT(newipl)) > BIT(newipl)) {
+		KASSERT(pending_ipls < BIT(NIPL));
+		for (;;) {
+			int ipl = 31 - __builtin_clz(pending_ipls);
+			KASSERT(ipl < NIPL);
+			if (ipl <= newipl)
+				break;
+		
+			current_spl_level = ipl;
+			deliver_irqs(psw, ipl, NULL);
+		}
+	}
+	current_spl_level = newipl;
+}
+
+int
+_splraise(int newipl)
+{
+	const int oldipl = current_spl_level;
+	KASSERT(newipl < NIPL);
+	if (newipl > current_spl_level)
+		current_spl_level = newipl;
+	return oldipl;
+}
+int
+_spllower(int newipl)
+{
+	const int oldipl = current_spl_level;
+	KASSERT(panicstr || newipl <= current_spl_level);
+	if (newipl < current_spl_level) {
+		register_t psw = disable_interrupts(I32_bit);
+		do_pending_ints(psw, newipl);
+		restore_interrupts(psw);
+	}
+	return oldipl;
+}
+
+void
+splx(int savedipl)
+{
+	KASSERT(savedipl < NIPL);
+	if (savedipl < current_spl_level) {
+		register_t psw = disable_interrupts(I32_bit);
+		do_pending_ints(psw, savedipl);
+		restore_interrupts(psw);
+	}
+	current_spl_level = savedipl;
+}
+
+static struct intrsource * const si_to_is[4] = {
+	[SI_SOFTSERIAL] =
+	    &intrgroups[IRQ_SOFTSERIAL / 32].ig_sources[IRQ_SOFTSERIAL & 31],
+	[SI_SOFTCLOCK] =
+	    &intrgroups[IRQ_SOFTCLOCK / 32].ig_sources[IRQ_SOFTCLOCK & 31],
+	[SI_SOFTNET] =
+	    &intrgroups[IRQ_SOFTNET / 32].ig_sources[IRQ_SOFTNET & 31],
+	[SI_SOFT] =
+	    &intrgroups[IRQ_SOFT / 32].ig_sources[IRQ_SOFT & 31],
+};
+
+void
+_setsoftintr(int si)
+{
+	struct intrsource * const is = si_to_is[si];
+	struct intrgroup * const ig = &intrgroups[is->is_group];
+
+	if (__predict_false(current_spl_level < is->is_ipl)) {
+		/*
+		 * If we are less than the desired IPL, raise IPL and dispatch
+		 * it immediately.  This is improbable.
+		 */
+		int s = _splraise(is->is_ipl);
+		softintr_dispatch(si);
+		splx(s);
+	} else {
+		/*
+		 * Mark the software interrupt for delivery.
+		 */
+		register_t psw = disable_interrupts(I32_bit);
+		ig->ig_pending_irqs |= BIT(is - ig->ig_sources);
+		pending_igroupsbyipl[is->is_ipl] |= BIT(is->is_group);
+		pending_ipls |= BIT(is->is_ipl);
+		is->is_marked++;
+		restore_interrupts(psw);
+	}
+}
+
+void
+omap_irq_handler(void *frame)
+{
+	const int oldipl = current_spl_level;
+	const uint32_t oldipl_mask = BIT(oldipl);
+
+	/*
+	 * When we enter there must be no pending IRQs for IPL greater than
+	 * the current IPL.  There might be pending IRQs for the current IPL
+	 * if we are servicing interrupts.
+	 */
+	KASSERT((pending_ipls & ~oldipl_mask) < oldipl_mask);
+	pending_ipls |= get_pending_irqs();
+
+	uvmexp.intrs++;
+	/*
+	 * We assume this isn't a clock intr.  But if it is, deliver it 
+	 * unconditionally so it will always have the interrupted frame.
+	 * The clock intr will handle being called at IPLs != IPL_CLOCK.
+	 */
+	if (__predict_false(pending_ipls & BIT(IPL_STATCLOCK))) {
+		deliver_irqs(0, IPL_STATCLOCK, frame);
+		pending_ipls &= ~BIT(IPL_STATCLOCK);
+	}
+	if (__predict_false(pending_ipls & BIT(IPL_CLOCK))) {
+		deliver_irqs(0, IPL_CLOCK, frame);
+		pending_ipls &= ~BIT(IPL_CLOCK);
+	}
+
+	/*
+	 * Record the pending_ipls and deliver them if we can.
+	 */
+	if ((pending_ipls & ~oldipl_mask) > oldipl_mask)
+		do_pending_ints(I32_bit, oldipl);
+}
+
+void *
+omap_intr_establish(int irq, int ipl, const char *name,
+	int (*func)(void *), void *arg)
+{
+	struct intrgroup *ig = &intrgroups[irq / 32];
+	struct intrsource *is;
+	register_t psw;
+
+	KASSERT(irq >= 0 && irq < 256);
+	is = &ig->ig_sources[irq & 0x1f];
+	KASSERT(irq != GPIO1_MPU_IRQ);
+	KASSERT(irq != GPIO2_MPU_IRQ);
+	KASSERT(irq != GPIO3_MPU_IRQ);
+	KASSERT(irq != GPIO4_MPU_IRQ);
+	KASSERT(irq != GPIO5_MPU_IRQ);
+	KASSERT(is->is_ipl == IPL_NONE);
+
+	is->is_func = func;
+	is->is_arg = arg;
+	psw = disable_interrupts(I32_bit);
+	evcnt_attach_dynamic(&is->is_ev, EVCNT_TYPE_INTR, NULL, name, "intr");
+	init_irq(irq, ipl, IST_LEVEL);
+
+	calculate_irq_masks(ig);
+	unblock_irq(is->is_group, BIT(irq & 31));
+	restore_interrupts(psw);
+	return is;
+}
+
+void
+omap_intr_disestablish(void *ih)
+{
+	struct intrsource * const is = ih;
+	struct intrgroup *ig;
+	register_t psw;
+	uint32_t mask;
+
+	KASSERT(ih != NULL);
+
+	ig = &intrgroups[is->is_group];
+	psw = disable_interrupts(I32_bit);
+	mask = BIT(is - ig->ig_sources);
+	block_irq(is->is_group, mask);
+	ig->ig_pending_irqs &= ~mask;
+	calculate_irq_masks(ig);
+	evcnt_detach(&is->is_ev);
+	restore_interrupts(psw);
+}
+
+static void
+gpio5_clkinit(bus_space_tag_t memt)
+{
+	bus_space_handle_t memh;
+	uint32_t r;
+	int error;
+
+	error = bus_space_map(memt, OMAP2430_CM_BASE,
+	    OMAP2430_CM_SIZE, 0, &memh);
+	if (error != 0)
+		panic("%s: cannot map OMAP2430_CM_BASE at %#x: %d\n",
+			__func__, OMAP2430_CM_BASE, error);
+
+	r = bus_space_read_4(memt, memh, OMAP2430_CM_FCLKEN2_CORE);
+	r |= OMAP2430_CM_FCLKEN2_CORE_EN_GPIO5;
+	bus_space_write_4(memt, memh, OMAP2430_CM_FCLKEN2_CORE, r);
+
+	r = bus_space_read_4(memt, memh, OMAP2430_CM_ICLKEN2_CORE);
+	r |= OMAP2430_CM_ICLKEN2_CORE_EN_GPIO5;
+	bus_space_write_4(memt, memh, OMAP2430_CM_ICLKEN2_CORE, r);
+
+	bus_space_unmap(memt, memh, OMAP2430_CM_SIZE);
+}
+
+void
+omap2430_intr_init(bus_space_tag_t memt)
+{
+	int error;
+	int group;
+
+	evcnt_attach_static(&intrgroups[IRQ_SOFTSERIAL/32].ig_sources[IRQ_SOFTSERIAL&31].is_ev);
+	evcnt_attach_static(&intrgroups[IRQ_SOFTCLOCK/32].ig_sources[IRQ_SOFTCLOCK&31].is_ev);
+	evcnt_attach_static(&intrgroups[IRQ_SOFTNET/32].ig_sources[IRQ_SOFTNET&31].is_ev);
+	evcnt_attach_static(&intrgroups[IRQ_SOFT/32].ig_sources[IRQ_SOFT&31].is_ev);
+
+	for (group = 0; group < NIGROUPS; group++)
+		intrgroups[group].ig_memt = memt;
+	error = bus_space_map(memt, INTC_BASE, 0x1000, 0,
+	    &intrgroups[0].ig_memh);
+	if (error)
+		panic("failed to map interrupt registers: %d", error);
+	error = bus_space_subregion(memt, intrgroups[0].ig_memh, 0x20, 0x20,
+	    &intrgroups[1].ig_memh);
+	if (error)
+		panic("failed to region interrupt registers: %d", error);
+	error = bus_space_subregion(memt, intrgroups[0].ig_memh, 0x40, 0x20,
+	    &intrgroups[2].ig_memh);
+	if (error)
+		panic("failed to subregion interrupt registers: %d", error);
+	error = bus_space_map(memt, GPIO1_BASE, 0x400, 0,
+	    &intrgroups[3].ig_memh);
+	if (error)
+		panic("failed to map gpio #1 registers: %d", error);
+	error = bus_space_map(memt, GPIO2_BASE, 0x400, 0,
+	    &intrgroups[4].ig_memh);
+	if (error)
+		panic("failed to map gpio #2 registers: %d", error);
+	error = bus_space_map(memt, GPIO3_BASE, 0x400, 0,
+	    &intrgroups[5].ig_memh);
+	if (error)
+		panic("failed to map gpio #3 registers: %d", error);
+	error = bus_space_map(memt, GPIO4_BASE, 0x400, 0,
+	    &intrgroups[6].ig_memh);
+	if (error)
+		panic("failed to map gpio #4 registers: %d", error);
+
+	gpio5_clkinit(memt);
+	error = bus_space_map(memt, GPIO5_BASE, 0x400, 0,
+	    &intrgroups[7].ig_memh);
+	if (error)
+		panic("failed to map gpio #5 registers: %d", error);
+
+	INTC_WRITE(&intrgroups[0], INTC_MIR_SET, 0xffffffff);
+	INTC_WRITE(&intrgroups[1], INTC_MIR_SET, 0xffffffff);
+	INTC_WRITE(&intrgroups[2], INTC_MIR_SET, 0xffffffff);
+	INTC_WRITE(&intrgroups[GPIO1_MPU_IRQ / 32], INTC_MIR_CLEAR,
+	    BIT(GPIO1_MPU_IRQ & 31));
+	INTC_WRITE(&intrgroups[GPIO2_MPU_IRQ / 32], INTC_MIR_CLEAR,
+	    BIT(GPIO2_MPU_IRQ & 31));
+	INTC_WRITE(&intrgroups[GPIO3_MPU_IRQ / 32], INTC_MIR_CLEAR,
+	    BIT(GPIO3_MPU_IRQ & 31));
+	INTC_WRITE(&intrgroups[GPIO4_MPU_IRQ / 32], INTC_MIR_CLEAR,
+	    BIT(GPIO4_MPU_IRQ & 31));
+	INTC_WRITE(&intrgroups[GPIO5_MPU_IRQ / 32], INTC_MIR_CLEAR,
+	    BIT(GPIO5_MPU_IRQ & 31));
+
+	/*
+	 * Setup the primary intrgroups.
+	 */
+	calculate_irq_masks(&intrgroups[0]);
+	calculate_irq_masks(&intrgroups[1]);
+	calculate_irq_masks(&intrgroups[2]);
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap2430_intr.h sys/arch/arm/omap/omap2430_intr.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap2430_intr.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap2430_intr.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,173 @@
+/*	$NetBSD: omap2430_intr.h,v 1.1.6.1 2007/02/21 18:39:20 snj Exp $ */
+
+/*
+ * Define the SDP2430 specific information and then include the generic OMAP
+ * interrupt header.
+ */
+
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _ARM_OMAP_SDP2430_INTR_H_
+#define _ARM_OMAP_SDP2430_INTR_H_
+
+#define	ARM_IRQ_HANDLER	_C_LABEL(omap_irq_handler)
+
+#ifndef _LOCORE
+
+#define OMAP_INTC_DEVICE		"omap2430intc"
+
+#include <arm/cpu.h>
+#include <arm/armreg.h>
+#include <arm/cpufunc.h>
+#include <machine/atomic.h>
+#include <arm/softintr.h>
+
+uint32_t omap_microtimer_read(void);
+uint32_t omap_microtimer_interval(uint32_t start, uint32_t end);
+
+extern int current_spl_level;
+
+#define	EMUINT_IRQ		0	/* MPU emulation (1) */
+#define	COMMRX_IRQ		1	/* MPU emulation (1) */
+#define	COMMTX_IRQ		2	/* MPU emulation (1) */
+#define	BENCH_IRQ		3	/* MPU emulation (1) */
+#define	XTI_IRQ			4	/* XTI module (2) (3) */
+#define	XTI_WKUP_IRQ		5	/* XTI module (3) */
+#define	SSM_ABORT_IRQ		6	/* MPU subsystem secure state-machine abort */
+#define	SYS_nIRQ0		7	/* External interrupt (active low) */
+#define	D2D_FW_STACKED		8	/* Occurs when modem does a security violation and has been automatically put DEVICE_SECURITY [0] under reset. */
+#define	M_IRQ_9				9	/* Reserved */
+#define	SMX_APE_IA_ARM1136	10	/* Error flag for reporting application and unknown errors from SMX-APE (4) rd_wrSError_o */
+#define	PRCM_MPU_IRQ		11	/* PRCM */
+#define	SDMA_IRQ0		12	/* System DMA interrupt request 0 (5) */
+#define	SDMA_IRQ1		13	/* System DMA interrupt request 1 (5) */
+#define	SDMA_IRQ2		14	/* System DMA interrupt request 2 */
+#define	SDMA_IRQ3		15	/* System DMA interrupt request 3 */
+#define	McBSP2_COMMON_IRQ	16	/* McBSP2 common IRQ. This IRQ regroups all interrupt sources of the McBSPLP. Not backward-compatible with the previous McBSP. */
+#define	McBSP3_COMMON_IRQ	17	/* McBSP3 common IRQ. This IRQ regroups all interrupt sources of the McBSPLP. Not backward-compatible with the previous McBSP. */
+#define	McBSP4_COMMON_IRQ	18	/* McBSP4 common IRQ. This IRQ regroups all interrupt sources of the McBSPLP. Not backward-compatible with the previous McBSP. */
+#define	McBSP5_COMMON_IRQ	19	/* McBSP5 common IRQ. This IRQ regroups all interrupt sources of the McBSPLP. Not backward-compatible with the previous McBSP. */
+#define	GPMC_IRQ		20	/* General-purpose memory controller module */
+#define	GFX_IRQ			21	/* 2D/3D graphics module */
+#define	M_IRQ_22		22	/* Reserved */
+#define	M_IRQ_23		23	/* Reserved */
+#define	CAM_IRQ0		24	/* Camera interface interrupt request 0 */
+#define	DSS_IRQ			25	/* Display subsystem module (5) */
+#define	MAIL_U0_MPU_IRQ		26	/* Mailbox user 0 interrupt request */
+#define	M_IRQ_27		27	/* Reserved */
+#define	IVA2_MMU_IRQ		28	/* IVA2 MMU interrupt */
+#define	GPIO1_MPU_IRQ		29	/* GPIO module 1 (5) (3) */
+#define	GPIO2_MPU_IRQ		30	/* GPIO module 2 (5) (3) */
+#define	GPIO3_MPU_IRQ		31	/* GPIO module 3 (5) (3) */
+#define	GPIO4_MPU_IRQ		32	/* GPIO module 4 (5) (3) */
+#define	GPIO5_MPU_IRQ		33	/* GPIO module 5 (5) */
+#define	M_IRQ_34		34	/* Reserved */
+#define	M_IRQ_35		35	/* Reserved */
+#define	IVA2WDT_IRQ		36	/* IVA2 watchdog timer interrupt */
+#define	GPT1_IRQ		37	/* General-purpose timer module 1 */
+#define	GPT2_IRQ		38	/* General-purpose timer module 2 */
+#define	GPT3_IRQ		39	/* General-purpose timer module 3 */
+#define	GPT4_IRQ		40	/* General-purpose timer module 4 */
+#define	GPT5_IRQ		41	/* General-purpose timer module 5 (5) */
+#define	GPT6_IRQ		42	/* General-purpose timer module 6 (5) (3) */
+#define	GPT7_IRQ		43	/* General-purpose timer module 7 (5) (3) */
+#define	GPT8_IRQ		44	/* General-purpose timer module 8 (5) (3) */
+#define	GPT9_IRQ		45	/* General-purpose timer module 9 (3) */
+#define	GPT10_IRQ		46	/* General-purpose timer module 10 */
+#define	GPT11_IRQ		47	/* General-purpose timer module 11 (PWM) */
+#define	GPT12_IRQ		48	/* General-purpose timer module 12 (PWM) */
+#define	M_IRQ_49		49	/* Reserved */
+#define	PKA_IRQ			50	/* PKA crypto-accelerator */
+#define	SHA1MD5_IRQ		51	/* SHA-1/MD5 crypto-accelerator */
+#define	RNG_IRQ			52	/* RNG module */
+#define	MG_IRQ			53	/* MG function (5) */
+#define	MCBSP4_IRQ_TX		54	/* McBSP module 4 transmit (5) */
+#define	MCBSP4_IRQ_RX		55	/* McBSP module 4 receive (5) */
+#define	I2C1_IRQ		56	/* I2C module 1 */
+#define	I2C2_IRQ		57	/* I2C module 2 */
+#define	HDQ_IRQ			58	/* HDQ/1-wire */
+#define	McBSP1_IRQ_TX		59	/* McBSP module 1 transmit (5) */
+#define	McBSP1_IRQ_RX		60	/* McBSP module 1 receive (5) */
+#define	MCBSP1_IRQ_OVR		61	/* McBSP module 1 overflow interrupt (5) */
+#define	McBSP2_IRQ_TX		62	/* McBSP module 2 transmit (5) */
+#define	McBSP2_IRQ_RX		63	/* McBSP module 2 receive (5) */
+#define	McBSP1_COMMON_IRQ	64	/* McBSP1 common IRQ. This IRQ regroups all the interrupt sources of the McBSPLP. Not backward compatible with previous McBSP. */
+#define	SPI1_IRQ		65	/* McSPI module 1 */
+#define	SPI2_IRQ		66	/* McSPI module 2 */
+#define	SSI_P1_MPU_IRQ0		67	/* Dual SSI port 1 interrupt request 0 (5) */
+#define	SSI_P1_MPU_IRQ1		68	/* Dual SSI port 1 interrupt request 1 (5) */
+#define	SSI_P2_MPU_IRQ0		69	/* Dual SSI port 2 interrupt request 0 (5) */
+#define	SSI_P2_MPU_IRQ1		70	/* Dual SSI port 2 interrupt request 1 (5) */
+#define	SSI_GDD_MPU_IRQ		71	/* Dual SSI GDD (5) */
+#define	UART1_IRQ		72	/* UART module 1 (3) */
+#define	UART2_IRQ		73	/* UART module 2 (3) */
+#define	UART3_IRQ		74	/* UART module 3 (also infrared) (5) (3) */
+#define	USB_IRQ_GEN		75	/* USB device general interrupt (3) */
+#define	USB_IRQ_NISO		76	/* USB device non-ISO (3) */
+#define	USB_IRQ_ISO		77	/* USB device ISO (3) */
+#define	USB_IRQ_HGEN		78	/* USB host general interrupt (3) */
+#define	USB_IRQ_HSOF		79	/* USB host start-of-frame (3) */
+#define	USB_IRQ_OTG		80	/* USB OTG */
+#define	MCBSP5_IRQ_TX		81	/* McBSP module 5 transmit (5) */
+#define	MCBSP5_IRQ_RX		82	/* McBSP module 5 receive (5) */
+#define	MMC1_IRQ		83	/* MMC/SD module 1 (3) */
+#define	MS_IRQ			84	/* MS-PRO module */
+#define	FAC_IRQ			85	/* FAC module */
+#define	MMC2_IRQ		86	/* MMC/SD module 2 */
+#define	ARM11_ICR_IRQ		87	/* ARM11 ICR interrupt */
+#define	D2DFRINT		88	/* From 3G coprocessor hardware when used in chassis mode */
+#define	MCBSP3_IRQ_TX		89	/* McBSP module 3 transmit (5) */
+#define	MCBSP3_IRQ_RX		90	/* McBSP module 3 receive (5) */
+#define	SPI3_IRQ		91	/* Module McSPI 3 */
+#define	HS_USB_MC_NINT		92	/* Module HS USB OTG controller (3) */
+#define	HS_USB_DMA_NINT		93	/* Module HS USB OTG DMA controller interrupt (3) */
+#define	Carkit_IRQ		94	/* Carkit interrupt when the external HS USB transceiver is used in carkit mode (2) */
+#define	M_IRQ_95		95	/* Reserved */
+
+int	_splraise(int);
+int	_spllower(int);
+void	splx(int);
+void	_setsoftintr(int);
+
+#define	omap_splx		splx
+#define	omap_splrasise		_splrasise
+#define	omap_spllower		_spllower
+#define	omap_setsoftintr	_setsoftintr
+
+void omap_irq_handler(void *);
+void *omap_intr_establish(int, int, const char *, int (*)(void *), void *);
+void omap_intr_disestablish(void *);
+int omapintc_match(struct device *, struct cfdata *, void *);
+void omapintc_attach(struct device *, struct device *, void *);
+
+#endif /* ! _LOCORE */
+
+#endif /* _ARM_OMAP_SDP2430_INTR_H_ */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap2430_mputmr.c sys/arch/arm/omap/omap2430_mputmr.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap2430_mputmr.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap2430_mputmr.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,428 @@
+/*	$NetBSD: omap2430_mputmr.c,v 1.1.6.1 2007/02/21 18:27:17 snj Exp $	*/
+
+/*
+ * OMAP 2430 GP timers
+ */
+
+/*
+ * Based on i80321_timer.c and arch/arm/sa11x0/sa11x0_ost.c
+ *
+ * Copyright (c) 1997 Mark Brinicombe.
+ * Copyright (c) 1997 Causality Limited.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed for the NetBSD Project by
+ *	Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: omap_mputmr.c,v 1.1.6.1 2007/02/21 18:27:17 snj Exp $");
+
+#include "opt_omap.h"
+#ifndef OMAP_2430
+# error unknown OMAP implementation
+#endif
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/time.h>
+#include <sys/device.h>
+
+#include <dev/clock_subr.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+
+#include <arm/omap/omap_reg.h>
+
+#include <arm/omap/omap_gptmrreg.h>
+#include <arm/omap/omap2430mputmrvar.h>
+
+uint32_t counts_per_usec, counts_per_hz;
+uint32_t hardref;
+struct timeval hardtime;
+struct omap2430mputmr_softc *clock_sc;
+struct omap2430mputmr_softc *stat_sc;
+struct omap2430mputmr_softc *ref_sc;
+
+static inline void
+_timer_intr_dis(struct omap2430mputmr_softc *sc)
+{
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, TIER, 0);
+}
+
+static inline void
+_timer_intr_enb(struct omap2430mputmr_softc *sc)
+{
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, TIER, TIER_OVF_IT_ENA);
+}
+
+static inline uint32_t
+_timer_intr_sts(struct omap2430mputmr_softc *sc)
+{
+	uint32_t r;
+	r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, TISR);
+	return r;
+}
+
+static inline void
+_timer_intr_ack(struct omap2430mputmr_softc *sc)
+{
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, TISR, TIER_OVF_IT_ENA);
+}
+
+static inline uint32_t
+_timer_read(struct omap2430mputmr_softc *sc)
+{
+	uint32_t r;
+	r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, TCRR);
+	return r;
+}
+
+static inline void
+_timer_stop(struct omap2430mputmr_softc *sc)
+{
+	uint32_t r;
+
+	r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, TCLR);
+	r &= ~TCLR_ST;
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, TCLR, r);
+}
+
+static inline void
+_timer_reload(struct omap2430mputmr_softc *sc, uint32_t val)
+{
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, TLDR, val);
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, TCRR, val);
+}
+
+static inline void
+_timer_start(struct omap2430mputmr_softc *sc, timer_factors *tfp)
+{
+	uint32_t r=0;
+
+	if (tfp->ptv != 0) {
+		r |= TCLR_PRE(1);
+		r |= (TCLR_PTV(tfp->ptv - 1) & TCLR_PTV_MASK);
+	}
+	r |= (TCLR_CE | TCLR_AR | TCLR_ST);
+
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, TCLR, r);
+}
+
+
+static volatile ulong ticks_pending;
+int
+clockintr(void *arg)
+{
+	struct clockframe *frame = arg;
+	unsigned int ticks;
+	uint32_t oipl = current_spl_level;
+
+	_timer_intr_ack(clock_sc);
+
+	if (oipl >= IPL_CLOCK) {
+		ticks_pending++;
+		return 1;
+	}
+
+	current_spl_level = IPL_CLOCK;
+	ticks = ticks_pending;
+	ticks_pending = 0;
+	ticks++;			/* this tick */
+	while (ticks--) {
+		enable_interrupts(I32_bit);
+		hardclock(frame);
+		disable_interrupts(I32_bit);
+		ticks += ticks_pending;
+		ticks_pending = 0;
+	}
+	current_spl_level = oipl;
+	return 1;
+}
+
+int
+statintr(void *arg)
+{
+	struct clockframe *frame = arg;
+	uint32_t oipl = current_spl_level;
+
+	_timer_intr_ack(stat_sc);
+
+	/* XXX what about missed ticks? */
+	if (oipl >= IPL_STATCLOCK)
+		return 1;
+
+	current_spl_level = IPL_CLOCK;
+	enable_interrupts(I32_bit);
+
+	statclock(frame);
+
+	disable_interrupts(I32_bit);
+	current_spl_level = oipl;
+	return 1;
+}
+
+static void
+setclockrate(struct omap2430mputmr_softc *sc, int schz)
+{
+	timer_factors tf;
+
+	_timer_stop(sc);
+	calc_timer_factors(schz, &tf);
+	_timer_reload(sc, tf.reload);
+	_timer_start(sc, &tf);
+}
+
+void
+setstatclockrate(int schz)
+{
+	setclockrate(stat_sc, schz);
+}
+
+void
+cpu_initclocks(void)
+{
+	if (clock_sc == NULL)
+		panic("Clock timer was not configured.");
+	if (stat_sc == NULL)
+		panic("Statistics timer was not configured.");
+	if (ref_sc == NULL)
+		panic("Microtime reference timer was not configured.");
+
+	/*
+	 * We already have the timers running, but not generating interrupts.
+	 * In addition, we've set stathz and profhz.
+	 */
+	printf("clock: hz=%d stathz=%d\n", hz, stathz);
+
+	_timer_intr_dis(clock_sc);
+	_timer_intr_dis(stat_sc);
+	_timer_intr_dis(ref_sc);
+
+	setclockrate(clock_sc, hz);
+	setclockrate(stat_sc, stathz);
+	setclockrate(ref_sc, hz);
+
+
+	/*
+	 * The "cookie" parameter must be zero to pass the interrupt frame
+	 * through to hardclock() and statclock().
+	 */
+
+	omap_intr_establish(clock_sc->sc_intr, IPL_CLOCK,
+			    clock_sc->sc_dev.dv_xname, clockintr, 0);
+	omap_intr_establish(stat_sc->sc_intr, IPL_STATCLOCK,
+			    stat_sc->sc_dev.dv_xname, statintr, 0);
+
+	_timer_intr_enb(clock_sc);
+	_timer_intr_enb(stat_sc);
+}
+
+uint32_t
+omap_microtimer_read(void)
+{
+	if (ref_sc != NULL)
+		return _timer_read(ref_sc);
+	else
+		return 0;
+}
+
+uint32_t
+omap_microtimer_interval(uint32_t start, uint32_t end)
+{
+	if (counts_per_usec)
+		return (start - end) / counts_per_usec;
+	else
+		return 0;
+}
+
+void
+microtime(struct timeval *tvp)
+{
+	u_int oldirqstate;
+	uint32_t ref, baseref;
+	static struct timeval lasttime;
+	static uint32_t lastref;
+
+	if (clock_sc == NULL) {
+		tvp->tv_sec = 0;
+		tvp->tv_usec = 0;
+		return;
+	}
+
+	oldirqstate = disable_interrupts(I32_bit);
+	ref = _timer_read(ref_sc);
+
+	*tvp = hardtime;
+	baseref = hardref;
+
+	/*
+	 * If time was just jumped forward and hardtime hasn't caught up
+	 * then just use time.
+	 */
+
+	if (time.tv_sec - hardtime.tv_sec > 1)
+		*tvp = time;
+
+	if (tvp->tv_sec < lasttime.tv_sec ||
+	    (tvp->tv_sec == lasttime.tv_sec &&
+	     tvp->tv_usec < lasttime.tv_usec)) {
+		*tvp = lasttime;
+		baseref = lastref;
+
+	} else {
+		lasttime = *tvp;
+		lastref = ref;
+	}
+
+	restore_interrupts(oldirqstate);
+
+	/* Prior to the first hardclock completion we don't have a
+	   microtimer reference. */
+
+	if (baseref)
+		tvp->tv_usec += (baseref - ref) / counts_per_usec;
+
+	/* Make sure microseconds doesn't overflow. */
+	while (tvp->tv_usec >= 1000000) {
+		tvp->tv_usec -= 1000000;
+		tvp->tv_sec++;
+	}
+}
+
+#ifndef ARM1136_PMC
+void
+delay(u_int n)
+{
+	uint32_t cur, last, delta, usecs;
+
+	if (clock_sc == NULL)
+		panic("The timer must be initialized sooner.");
+
+	/*
+	 * This works by polling the timer and counting the
+	 * number of microseconds that go by.
+	 */
+	last = _timer_read(clock_sc);
+
+	delta = usecs = 0;
+
+	while (n > usecs) {
+		cur = _timer_read(clock_sc);
+
+		/* Check to see if the timer has wrapped around. */
+		if (last < cur)
+			delta += (last + (counts_per_hz - cur));
+		else
+			delta += (last - cur);
+
+		last = cur;
+
+		if (delta >= counts_per_usec) {
+			usecs += delta / counts_per_usec;
+			delta %= counts_per_usec;
+		}
+	}
+}
+#endif /* ARM1136_PMC */
+
+/*
+ * OVF_Rate =
+ *	(0xFFFFFFFF - GPTn.TLDR + 1) * (timer functional clock period)  * PS
+ */
+void
+calc_timer_factors(int ints_per_sec, timer_factors *tf)
+{
+	uint32_t ptv_power;	/* PS */
+	uint32_t count_freq;
+	static const uint32_t us_per_sec = 1000000;
+	
+
+	tf->ptv = 8;
+	for (;;) {
+		ptv_power = 1 << tf->ptv;
+		count_freq = OMAP_MPU_TIMER_CLOCK_FREQ;
+		count_freq /= hz;
+		count_freq /= ptv_power;
+		tf->reload = -count_freq;
+		tf->counts_per_usec = count_freq / us_per_sec;
+		if ((tf->reload * ptv_power * ints_per_sec
+		     == OMAP_MPU_TIMER_CLOCK_FREQ)
+		    && (tf->counts_per_usec * ptv_power * us_per_sec
+			== OMAP_MPU_TIMER_CLOCK_FREQ))
+		{	/* Exact match.  Life is good. */
+			/* Currently reload is MPU_LOAD_TIMER+1.  Fix it. */
+			tf->reload--;
+			return;
+		}
+		if (tf->ptv == 0) {
+			tf->counts_per_usec++;
+			return;
+		}
+		tf->ptv--;
+	}
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap2430gpmcreg.h sys/arch/arm/omap/omap2430gpmcreg.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap2430gpmcreg.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap2430gpmcreg.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,228 @@
+/*	$NetBSD$	*/
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _OMAP2430GPMCREG_H
+#define _OMAP2430GPMCREG_H
+
+#ifndef OMAP_2430
+# error whay are you including this file
+#endif
+
+#define BITS(hi,lo)	((uint32_t)(~((~0ULL)<<((hi)+1)))&((~0)<<(lo)))
+#define BIT(n)		((uint32_t)(1 << (n)))
+
+/*
+ * Header for OMAP2430 General Purpose Memory Controller
+ */
+
+/*
+ * GPMC register base address, offsets, and size
+ */
+#define OMAP2430_GPMC_BASE		0x6e000000
+
+#define OMAP_GPMC_REVISION		0x000
+#define OMAP_GPMC_SYSCONFIG		0x010
+#define OMAP_GPMC_SYSSTATUS		0x014
+#define OMAP_GPMC_IRQSTATUS		0x018
+#define OMAP_GPMC_IRQENABLE		0x01C
+#define OMAP_GPMC_TIMEOUT_CONTROL	0x040
+#define OMAP_GPMC_ERR_ADDRESS		0x044
+#define OMAP_GPMC_ERR_TYPE		0x048
+#define OMAP_GPMC_CONFIG		0x050
+#define OMAP_GPMC_STATUS		0x054
+#define OMAP_GPMC_CONFIG1_0		0x060
+#define OMAP_GPMC_CONFIG2_0		0x064
+#define OMAP_GPMC_CONFIG3_0		0x068
+#define OMAP_GPMC_CONFIG4_0		0x06C
+#define OMAP_GPMC_CONFIG5_0		0x070
+#define OMAP_GPMC_CONFIG6_0		0x074
+#define OMAP_GPMC_CONFIG7_0		0x078
+#define OMAP_GPMC_NAND_COMMAND_0	0x07C
+#define OMAP_GPMC_NAND_ADDRESS_0	0x080
+#define OMAP_GPMC_NAND_DATA_0		0x084
+#define OMAP_GPMC_CONFIG1_1		0x090
+#define OMAP_GPMC_CONFIG2_1		0x094
+#define OMAP_GPMC_CONFIG3_1		0x098
+#define OMAP_GPMC_CONFIG4_1		0x09C
+#define OMAP_GPMC_CONFIG5_1		0x0A0
+#define OMAP_GPMC_CONFIG6_1		0x0A4
+#define OMAP_GPMC_CONFIG7_1		0x0A8
+#define OMAP_GPMC_NAND_COMMAND_1	0x0AC
+#define OMAP_GPMC_NAND_ADDRESS_1	0x0B0
+#define OMAP_GPMC_NAND_DATA_1		0x0B4
+#define OMAP_GPMC_CONFIG1_2		0x0C0
+#define OMAP_GPMC_CONFIG2_2		0x0C4
+#define OMAP_GPMC_CONFIG3_2		0x0C8
+#define OMAP_GPMC_CONFIG4_2		0x0CC
+#define OMAP_GPMC_CONFIG5_2		0x0D0
+#define OMAP_GPMC_CONFIG6_2		0x0D4
+#define OMAP_GPMC_CONFIG7_2		0x0D8
+#define OMAP_GPMC_NAND_COMMAND_2	0x0DC
+#define OMAP_GPMC_NAND_ADDRESS_2	0x0E0
+#define OMAP_GPMC_NAND_DATA_2		0x0E4
+#define OMAP_GPMC_CONFIG1_3		0x0F0
+#define OMAP_GPMC_CONFIG2_3		0x0F4
+#define OMAP_GPMC_CONFIG3_3		0x0F8
+#define OMAP_GPMC_CONFIG4_3		0x0FC
+#define OMAP_GPMC_CONFIG5_3		0x100
+#define OMAP_GPMC_CONFIG6_3		0x104
+#define OMAP_GPMC_CONFIG7_3		0x108
+#define OMAP_GPMC_NAND_COMMAND_3	0x10C
+#define OMAP_GPMC_NAND_ADDRESS_3	0x110
+#define OMAP_GPMC_NAND_DATA_3		0x114
+#define OMAP_GPMC_CONFIG1_4		0x120
+#define OMAP_GPMC_CONFIG2_4		0x124
+#define OMAP_GPMC_CONFIG3_4		0x128
+#define OMAP_GPMC_CONFIG4_4		0x12C
+#define OMAP_GPMC_CONFIG5_4		0x130
+#define OMAP_GPMC_CONFIG6_4		0x134
+#define OMAP_GPMC_CONFIG7_4		0x138
+#define OMAP_GPMC_NAND_COMMAND_4	0x13C
+#define OMAP_GPMC_NAND_ADDRESS_4	0x140
+#define OMAP_GPMC_NAND_DATA_4		0x144
+#define OMAP_GPMC_CONFIG1_5		0x150
+#define OMAP_GPMC_CONFIG2_5		0x154
+#define OMAP_GPMC_CONFIG3_5		0x158
+#define OMAP_GPMC_CONFIG4_5		0x15C
+#define OMAP_GPMC_CONFIG5_5		0x160
+#define OMAP_GPMC_CONFIG6_5		0x164
+#define OMAP_GPMC_CONFIG7_5		0x168
+#define OMAP_GPMC_NAND_COMMAND_5	0x16C
+#define OMAP_GPMC_NAND_ADDRESS_5	0x170
+#define OMAP_GPMC_NAND_DATA_5		0x174
+#define OMAP_GPMC_CONFIG1_6		0x180
+#define OMAP_GPMC_CONFIG2_6		0x184
+#define OMAP_GPMC_CONFIG3_6		0x188
+#define OMAP_GPMC_CONFIG4_6		0x18C
+#define OMAP_GPMC_CONFIG5_6		0x190
+#define OMAP_GPMC_CONFIG6_6		0x194
+#define OMAP_GPMC_CONFIG7_6		0x198
+#define OMAP_GPMC_NAND_COMMAND_6	0x19C
+#define OMAP_GPMC_NAND_ADDRESS_6	0x1A0
+#define OMAP_GPMC_NAND_DATA_6		0x1A4
+#define OMAP_GPMC_CONFIG1_7		0x1B0
+#define OMAP_GPMC_CONFIG2_7		0x1B4
+#define OMAP_GPMC_CONFIG3_7		0x1B8
+#define OMAP_GPMC_CONFIG4_7		0x1BC
+#define OMAP_GPMC_CONFIG5_7		0x1C0
+#define OMAP_GPMC_CONFIG6_7		0x1C4
+#define OMAP_GPMC_CONFIG7_7		0x1C8
+#define OMAP_GPMC_NAND_COMMAND_7	0x1CC
+#define OMAP_GPMC_NAND_ADDRESS_7	0x1D0
+#define OMAP_GPMC_NAND_DATA_7		0x1D4
+#define OMAP_GPMC_PREFETCH_CONFIG1	0x1E0
+#define OMAP_GPMC_PREFETCH_CONFIG2	0x1E4
+#define OMAP_GPMC_PREFETCH_CONTROL	0x1EC
+#define OMAP_GPMC_CONFIG1_6		0x180
+#define OMAP_GPMC_CONFIG2_6		0x184
+#define OMAP_GPMC_CONFIG3_6		0x188
+#define OMAP_GPMC_CONFIG4_6		0x18C
+#define OMAP_GPMC_CONFIG5_6		0x190
+#define OMAP_GPMC_CONFIG6_6		0x194
+#define OMAP_GPMC_CONFIG7_6		0x198
+#define OMAP_GPMC_NAND_COMMAND_6	0x19C
+#define OMAP_GPMC_NAND_ADDRESS_6	0x1A0
+#define OMAP_GPMC_NAND_DATA_6		0x1A4
+#define OMAP_GPMC_CONFIG1_7		0x1B0
+#define OMAP_GPMC_CONFIG2_7		0x1B4
+#define OMAP_GPMC_CONFIG3_7		0x1B8
+#define OMAP_GPMC_CONFIG4_7		0x1BC
+#define OMAP_GPMC_CONFIG5_7		0x1C0
+#define OMAP_GPMC_CONFIG6_7		0x1C4
+#define OMAP_GPMC_CONFIG7_7		0x1C8
+#define OMAP_GPMC_NAND_COMMAND_7	0x1CC
+#define OMAP_GPMC_NAND_ADDRESS_7	0x1D0
+#define OMAP_GPMC_NAND_DATA_7		0x1D4
+#define OMAP_GPMC_PREFETCH_CONFIG1	0x1E0
+#define OMAP_GPMC_PREFETCH_CONFIG2	0x1E4
+#define OMAP_GPMC_PREFETCH_CONTROL	0x1EC
+#define OMAP_GPMC_PREFETCH_STATUS	0x1F0
+#define OMAP_GPMC_ECC_CONFIG		0x1F4
+#define OMAP_GPMC_ECC_CONTROL		0x1F8
+#define OMAP_GPMC_ECC_SIZE_CONFIG	0x1FC
+#define OMAP_GPMC_ECC1_RESULT		0x200
+#define OMAP_GPMC_ECC2_RESULT		0x204
+#define OMAP_GPMC_ECC3_RESULT		0x208
+#define OMAP_GPMC_ECC4_RESULT		0x20C
+#define OMAP_GPMC_ECC5_RESULT		0x210
+#define OMAP_GPMC_ECC6_RESULT		0x214
+#define OMAP_GPMC_ECC7_RESULT		0x218
+#define OMAP_GPMC_ECC8_RESULT		0x21C
+#define OMAP_GPMC_ECC9_RESULT		0x220
+#define OMAP_GPMC_TESTMODE_CTRL		0x230
+#define OMAP_GPMC_PSA_LSB		0x234
+#define OMAP_GPMC_PSA_MSB		0x238
+
+#define OMAP_GPMC_SIZE			(OMAP_GPMC_PSA_MSB + 4)
+#define OMAP_GPMC_NCS			8	/* # Chip Selects */
+
+/*
+ * GPMC OMAP2430_GPMC_REVISION
+ */
+#define OMAP_GPMC_REVISION_REV		BITS(7,0)
+#define OMAP_GPMC_REVISION_REV_MAJ(r)	(((r) >> 4) & 0xf)
+#define OMAP_GPMC_REVISION_REV_MIN(r)	(((r) >> 0) & 0xf)
+
+/*
+ * GPMC CONFIG7_[0-7] bits
+ */
+#define OMAP_GPMC_CONFIG7_BASEADDRESS	BITS(5,0)
+#define OMAP_GPMC_CONFIG7_CSVALID	BIT(6)
+#define OMAP_GPMC_CONFIG7_MASKADDRESS	BITS(11,8)
+static __inline ulong
+omap_gpmc_config7_addr(uint32_t r)
+{
+	return ((r) & OMAP_GPMC_CONFIG7_BASEADDRESS) << 24;
+}
+static __inline ulong
+omap_gpmc_config7_size(uint32_t r)
+{
+	uint i;
+	uint mask;
+	const struct {
+		uint  mask;
+		ulong size;
+	} gpmc_config7_size_tab[5] = {
+		{ 0x0, (256 << 20) },		/* 256 MB */
+		{ 0x8, (128 << 20) },		/* 128 MB */
+		{ 0xc, ( 64 << 20) },		/*  64 MB */
+		{ 0xe, ( 32 << 20) },		/*  32 MB */
+		{ 0xf, ( 16 << 20) },		/*  16 MB */
+	};
+	mask = ((r) & OMAP_GPMC_CONFIG7_MASKADDRESS) >> 8;
+	for (i=0; i < 5; i++) {
+		if (gpmc_config7_size_tab[i].mask == mask)
+		return gpmc_config7_size_tab[i].size;
+	}
+	return 0;
+}
+
+#endif	/* _OMAP2430GPMCREG_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap2430gpmcvar.h sys/arch/arm/omap/omap2430gpmcvar.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap2430gpmcvar.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap2430gpmcvar.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,44 @@
+/*	$NetBSD$	*/
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _OMAP2430GPMCVAR_H
+#define _OMAP2430GPMCVAR_H
+
+struct gpmc_attach_args {
+	bus_space_tag_t	gpmc_iot;
+	bus_addr_t	gpmc_addr;
+	bus_size_t	gpmc_size;
+	int		gpmc_intr;
+	bus_dma_tag_t	gpmc_dmac;
+	unsigned int	gpmc_mult;
+};
+
+#endif /* _OMAP2430GPMCVAR_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap2430mputmrvar.h sys/arch/arm/omap/omap2430mputmrvar.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap2430mputmrvar.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap2430mputmrvar.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,70 @@
+/* $NetBSD$ */
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+/*
+ * derived from omapmputmrvar.h
+ */
+
+#ifndef _OMAP2430GPTMRVAR_H
+#define _OMAP2430GPTMRVAR_H
+
+
+#ifndef STATHZ
+# define STATHZ	64
+#endif
+
+typedef struct timer_factors {
+	uint32_t ptv;
+	uint32_t reload;
+	uint32_t counts_per_usec;
+} timer_factors;
+
+struct omap2430mputmr_softc {
+	struct device		sc_dev;
+	bus_space_tag_t		sc_iot;
+	bus_space_handle_t	sc_ioh;
+	int			sc_intr;
+};
+
+
+
+extern uint32_t counts_per_usec, counts_per_hz;
+extern uint32_t hardref;
+extern struct timeval hardtime;
+extern struct omap2430mputmr_softc *clock_sc;
+extern struct omap2430mputmr_softc *stat_sc;
+extern struct omap2430mputmr_softc *ref_sc;
+
+extern void calc_timer_factors(int, struct timer_factors *);
+extern int	clockintr(void *);
+extern int	statintr(void *);
+extern void	rtcinit(void);
+
+#endif	/* _OMAP2430GPTMRVAR_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap2430obioreg.h sys/arch/arm/omap/omap2430obioreg.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap2430obioreg.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap2430obioreg.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,46 @@
+/*	$NetBSD$	*/
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef _OMAP2430OBIOREG_H
+#define _OMAP2430OBIOREG_H
+
+#include <arm/omap/omap2430reg.h>
+
+#ifndef OMAP_2430
+# error whay are you including this file
+#endif
+
+#define	OMAP2430_OBIO_0_BASE	OMAP2430_L4_CORE_BASE
+#define	OMAP2430_OBIO_0_SIZE	OMAP2430_L4_CORE_SIZE
+
+#define	OMAP2430_OBIO_1_BASE	OMAP2430_L4_WAKEUP_BASE
+#define	OMAP2430_OBIO_1_SIZE	OMAP2430_L4_WAKEUP_SIZE
+
+#endif	/* _OMAP2430OBIOREG_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap2430obiovar.h sys/arch/arm/omap/omap2430obiovar.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap2430obiovar.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap2430obiovar.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,43 @@
+/* $NetBSD$ */
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef _OMAP2430OBIOVAR_H
+#define _OMAP2430OBIOVAR_H
+
+struct obio_attach_args {
+	bus_space_tag_t	obio_iot;
+	bus_addr_t	obio_addr;
+	bus_size_t	obio_size;
+	int		obio_intr;
+	bus_dma_tag_t	obio_dmac;
+	unsigned int	obio_mult;
+};
+
+#endif /* _OMAP2430OBIOVAR_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap2430reg.h sys/arch/arm/omap/omap2430reg.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap2430reg.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap2430reg.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,432 @@
+/* $NetBSD$ */
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _OMAP2430REG_H
+#define _OMAP2430REG_H
+
+#ifndef OMAP_2430
+# error why are you including this file
+#endif
+
+#define BITS(hi,lo)	((uint32_t)(~((~0ULL)<<((hi)+1)))&((~0)<<(lo)))
+#define BIT(n)		((uint32_t)(1 << (n)))
+
+/*
+ * Header for misc. omap2430 registers
+ */
+
+/*
+ * L4 Interconnect WAKEUP address space
+ */
+#define OMAP2430_L4_WAKEUP_BASE			0x49000000
+#define OMAP2430_L4_WAKEUP_SIZE			(8 << 20)	/* 8 MB */
+
+
+/*
+ * Clock Management registers base, offsets, and size
+ */
+#define	OMAP2430_CM_BASE		0x49006000
+#define	OMAP2430_CM_CLKSEL_MPU		0x140
+#define	OMAP2430_CM_FCLKEN1_CORE	0x200
+#define	OMAP2430_CM_FCLKEN2_CORE	0x204
+#define	OMAP2430_CM_ICLKEN1_CORE	0x210
+#define	OMAP2430_CM_ICLKEN2_CORE	0x214
+#define	OMAP2430_CM_CLKSEL2_CORE	0x244
+#define	OMAP2430_CM_SIZE		(OMAP2430_CM_CLKSEL2_CORE + 4)
+
+
+/*
+ * bit defines for OMAP2430_CM_CLKSEL_MPU
+ */
+#define	OMAP2430_CM_CLKSEL_MPU_FULLSPEED	1
+#define	OMAP2430_CM_CLKSEL_MPU_HALFSPEED	2
+
+/*
+ * bit defines for OMAP2430_CM_FCLKEN2_CORE
+ */
+#define OMAP2430_CM_FCLKEN1_CORE_EN_DSS1	BIT(0)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_DSS2	BIT(1)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_TV		BIT(2)
+#define OMAP2430_CM_FCLKEN1_CORE_RESa	BIT(3)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT2	BIT(4)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT3	BIT(5)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT4	BIT(6)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT5	BIT(7)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT6	BIT(8)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT7	BIT(9)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT8	BIT(10)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT9	BIT(11)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT10	BIT(12)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT11	BIT(13)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_GPT12	BIT(14)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_MCBSP1	BIT(15)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_MCBSP2	BIT(16)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_MCSPI1	BIT(17)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_MCSPI2	BIT(18)
+#define OMAP2430_CM_FCLKEN1_CORE_RESb	BITS(20,19)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_UART1	BIT(21)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_UART2	BIT(22)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_HDQ		BIT(23)
+#define OMAP2430_CM_FCLKEN1_CORE_RESc	BIT(24)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_FAC		BIT(25)
+#define OMAP2430_CM_FCLKEN1_CORE_RESd	BIT(26)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_MSPRO	BIT(27)
+#define OMAP2430_CM_FCLKEN1_CORE_RESe	BIT(28)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_WDT4	BIT(29)
+#define OMAP2430_CM_FCLKEN1_CORE_RESf	BIT(30)
+#define OMAP2430_CM_FCLKEN1_CORE_EN_CAM		BIT(31)
+#define OMAP2430_CM_FCLKEN1_CORE_RESV \
+		(OMAP2430_CM_FCLKEN1_CORE_RESa \
+		|OMAP2430_CM_FCLKEN1_CORE_RESb \
+		|OMAP2430_CM_FCLKEN1_CORE_RESc \
+		|OMAP2430_CM_FCLKEN1_CORE_RESd \
+		|OMAP2430_CM_FCLKEN1_CORE_RESe \
+		|OMAP2430_CM_FCLKEN1_CORE_RESf)
+
+
+/*
+ * bit defines for OMAP2430_CM_FCLKEN2_CORE
+ */
+#define OMAP2430_CM_FCLKEN2_CORE_EN_USB		BIT(0)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_SSI		BIT(1)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_UART3	BIT(2)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_MCBSP3	BIT(3)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_MCBSP4	BIT(4)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_MCBSP5	BIT(5)
+#define OMAP2430_CM_FCLKEN2_CORE_RESa		BIT(6)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_MMCHS1	BIT(7)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_MMCHS2	BIT(8)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_NCSPI3	BIT(9)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_GPIO5	BIT(10)
+#define OMAP2430_CM_FCLKEN2_CORE_RESb		BITS(15,11)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_MMCHSDB1	BIT(16)
+#define OMAP2430_CM_FCLKEN2_CORE_EN_MMCHSDB2	BIT(17)
+#define OMAP2430_CM_FCLKEN2_CORE_RESc		BIT(18)
+#define OMAP2430_CM_FCLKEN2_CORE_I2CHS1		BIT(19)
+#define OMAP2430_CM_FCLKEN2_CORE_I2CHS2		BIT(20)
+#define OMAP2430_CM_FCLKEN2_CORE_RESd		BITS(31,21)
+#define OMAP2430_CM_FCLKEN2_CORE_RESV \
+		(OMAP2430_CM_FCLKEN2_CORE_RESa  \
+		|OMAP2430_CM_FCLKEN2_CORE_RESb  \
+		|OMAP2430_CM_FCLKEN2_CORE_RESc  \
+		|OMAP2430_CM_FCLKEN2_CORE_RESd)
+
+
+/*
+ * bit defines for OMAP2430_CM_ICLKEN1_CORE
+ */
+#define OMAP2430_CM_ICLKEN1_CORE_EN_DSS		BIT(0)
+#define OMAP2430_CM_ICLKEN1_CORE_RESa	BITS(3,1)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT2	BIT(4)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT3	BIT(5)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT4	BIT(6)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT5	BIT(7)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT6	BIT(8)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT7	BIT(9)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT8	BIT(10)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT9	BIT(11)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT10	BIT(12)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT11	BIT(13)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_GPT12	BIT(14)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_MCBSP1	BIT(15)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_MCBSP2	BIT(16)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_MCSPI1	BIT(17)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_MCSPI2	BIT(18)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_I2C1	BIT(19)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_I2C2	BIT(20)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_UART1	BIT(21)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_UART2	BIT(22)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_HDQ		BIT(23)
+#define OMAP2430_CM_ICLKEN1_CORE_RESb	BIT(24)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_FAC		BIT(25)
+#define OMAP2430_CM_ICLKEN1_CORE_RESc	BIT(26)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_MSPR0	BIT(27)
+#define OMAP2430_CM_ICLKEN1_CORE_RESd	BIT(28)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_WDT4	BIT(29)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_MAILBOXES	BIT(30)
+#define OMAP2430_CM_ICLKEN1_CORE_EN_CAM		BIT(31)
+#define OMAP2430_CM_ICLKEN1_CORE_RESV \
+		(OMAP2430_CM_ICLKEN1_CORE_RESa \
+		|OMAP2430_CM_ICLKEN1_CORE_RESb \
+		|OMAP2430_CM_ICLKEN1_CORE_RESc \
+		|OMAP2430_CM_ICLKEN1_CORE_RESd)
+
+
+/*
+ * bit defines for OMAP2430_CM_ICLKEN2_CORE
+ */
+#define OMAP2430_CM_ICLKEN2_CORE_EN_USB		BIT(0)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_SSI		BIT(1)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_UART3	BIT(2)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_MCBSP3	BIT(3)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_MCBSP4	BIT(4)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_MCBSP5	BIT(5)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_USBHS	BIT(6)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_MMCHS1	BIT(7)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_MMCHS2	BIT(8)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_NCSPI3	BIT(9)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_GPIO5	BIT(10)
+#define OMAP2430_CM_ICLKEN2_CORE_EN_MDM_INTC	BIT(11)
+#define OMAP2430_CM_ICLKEN2_CORE_RESV		BIT(31,12)
+
+/*
+ * bit defines for OMAP2430_CM_CLKSEL2_CORE
+ */
+#define OMAP2430_CM_CLKSEL2_CORE_GPTn(n, v) \
+		(((v) & 0x3) << (2 + ((((n) - 2) << 1))))
+# define CLKSEL2_CORE_GPT_FUNC_32K_CLK		0x0
+# define CLKSEL2_CORE_GPT_SYS_CLK		0x1
+# define CLKSEL2_CORE_GPT_ALT_CLK		0x2
+# define CLKSEL2_CORE_GPT_ALT_RESV		0x3
+
+#define OMAP2430_CM_CLKSEL2_CORE_RESa	BITS(1,0)
+#define OMAP2430_CM_CLKSEL2_CORE_RESb	BITS(31,24)
+#define OMAP2430_CM_CLKSEL2_CORE_RESV \
+		(OMAP2430_CM_CLKSEL2_CORE_RESa \
+		|OMAP2430_CM_CLKSEL2_CORE_RESb)
+
+
+/*
+ * L3 Interconnect Target Agent Common Registers
+ */
+#define OMAP2430_TA_GPMC	0x68002400
+#define OMAP2430_TA_L4_CORE	0x68006800
+
+/*
+ * L3 Interconnect Target Agent Common Register offsets
+ */
+#define OMAP2430_TA_COMPONENT		0x0
+#define OMAP2430_TA_CORE		0x18
+#define OMAP2430_TA_AGENT_CONTROL	0x20
+#define OMAP2430_TA_AGENT_STATUS	0x28
+#define OMAP2430_TA_ERROR_LOG		0x58
+#define OMAP2430_TA_ERROR_LOG_ADDR	0x60
+
+/*
+ * OMAP2430_TA_COMPONENT bits
+ */
+#define	TA_COMPONENT_REV(r)		((r) & BITS(15,0))
+#define	TA_COMPONENT_CODE(r)		(((r) >> 16) & BITS(15,0))
+
+/*
+ * OMAP2430_TA_CORE bits
+ */
+#define	TA_AGENT_CORE_REV(r)		((r) & BITS(15,0))
+#define	TA_AGENT_CORE_CODE(r)		(((r) >> 16) & BITS(15,0))
+
+/*
+ * OMAP2430_TA_AGENT_CONTROL bits
+ */
+#define TA_AGENT_CONTROL_CORE_RESET		BIT(0)
+#define TA_AGENT_CONTROL_CORE_REJECT		BIT(4)
+#define TA_AGENT_CONTROL_CORE_TIMEOUT_BASE	BITS(10,8)
+#define TA_AGENT_CONTROL_CORE_TIMEOUT_BASE_SHFT	8
+#define TA_AGENT_CONTROL_CORE_TIMEOUT_BASE_NONE		0
+#define TA_AGENT_CONTROL_CORE_TIMEOUT_BASE_1		1
+#define TA_AGENT_CONTROL_CORE_TIMEOUT_BASE_4		2
+#define TA_AGENT_CONTROL_CORE_TIMEOUT_BASE_16		3
+#define TA_AGENT_CONTROL_CORE_TIMEOUT_BASE_64		4
+#define TA_AGENT_CONTROL_CORE_SERROR_REP	BIT(24)
+#define TA_AGENT_CONTROL_CORE_REQ_TIMEOUT_REP	BIT(25)
+
+/*
+ * OMAP2430_TA_AGENT_STATUS bits
+ */
+#define TA_AGENT_STATUS_CORE_RESET	BIT(0)
+#define TA_AGENT_STATUS_RESVa		BITS(3,1)
+#define TA_AGENT_STATUS_REQ_WAITING	BIT(4)
+#define TA_AGENT_STATUS_RESP_ACTIVE	BIT(5)
+#define TA_AGENT_STATUS_BURST		BIT(6)
+#define TA_AGENT_STATUS_READEX		BIT(7)
+#define TA_AGENT_STATUS_REQ_TIMEOUT	BIT(8)
+#define TA_AGENT_STATUS_RESVb		BITS(11,9)
+#define TA_AGENT_STATUS_TIMEBASE	BITS(15,12)
+#define TA_AGENT_STATUS_BURST_CLOSE	BIT(16)
+#define TA_AGENT_STATUS_RESVc		BITS(23,17)
+#define TA_AGENT_STATUS_SERROR		BIT(24)		/* XXX */
+#define TA_AGENT_STATUS_RESVd		BITS(31,25)
+
+/*
+ * OMAP2430_TA_ERROR_LOG bits
+ */
+#define TA_ERROR_LOG_CMD		BITS(2,0)
+#define TA_ERROR_LOG_RESa		BITS(7,3)
+#define TA_ERROR_LOG_INITID		BITS(15,8)	/* initiator */
+#define TA_ERROR_LOG_RESb		BITS(23,16)
+#define TA_ERROR_LOG_CODE		BITS(27,24)	/* error */
+#define TA_ERROR_LOG_RESc		BITS(30,28)
+#define TA_ERROR_LOG_MULTI		BIT(31)		/* write to clear */
+
+/*
+ * L4 Interconnect CORE address space
+ */
+#define OMAP2430_L4_CORE_BASE			0x48000000
+#define OMAP2430_L4_CORE_SIZE			(16 << 20)	/* 16 MB */
+
+#define OMAP2430_L4_S3220_2430_WATCHDOGOCP24	0x48027000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC2	0x4802B000
+#define OMAP2430_L4_S3220_2430_AP		0x48040000
+#define OMAP2430_L4_S3220_2430_IA		0x48040800
+#define OMAP2430_L4_S3220_2430_LA		0x48041000
+#define OMAP2430_L4_S3220_2430_MPU_SS		0x4804A000
+#define OMAP2430_L4_S3220_2430_DISPLAY_SUBS	0x48051000
+#define OMAP2430_L4_S3220_2430_CAMERA_CORE	0x48053000
+#define OMAP2430_L4_S3220_2430_SDMA		0x48057000
+#define OMAP2430_L4_S3220_2430_SSI		0x4805C000
+#define OMAP2430_L4_S3220_2430_USB_OTG_FS	0x4805F000
+#define OMAP2430_L4_S3220_2430_XTI		0x48069000
+#define OMAP2430_L4_S3220_2430_UART1		0x4806B000
+#define OMAP2430_L4_S3220_2430_UART2		0x4806D000
+#define OMAP2430_L4_S3220_2430_UART3		0x4806F000
+#define OMAP2430_L4_S3220_2430_MSHSI2C1		0x48071000
+#define OMAP2430_L4_S3220_2430_MSHSI2C2		0x48073000
+#define OMAP2430_L4_S3220_2430_MCBSP1		0x48075000
+#define OMAP2430_L4_S3220_2430_MCBSP2		0x48077000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC3	0x48079000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC4	0x4807B000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC5	0x4807D000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC6	0x4807F000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC7	0x48081000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC8	0x48083000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC9	0x48085000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC10	0x48087000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC11	0x48089000
+#define OMAP2430_L4_S3220_2430_DMTIMER_DMC12	0x4808B000
+#define OMAP2430_L4_S3220_2430_MCBSP3		0x4808D000
+#define OMAP2430_L4_S3220_2430_MCBSP4		0x4808F000
+#define OMAP2430_L4_S3220_2430_FAC		0x48093000
+#define OMAP2430_L4_S3220_2430_MAILBOX1		0x48095000
+#define OMAP2430_L4_S3220_2430_MCBSP5		0x48097000
+#define OMAP2430_L4_S3220_2430_MCSPI1		0x48099000
+#define OMAP2430_L4_S3220_2430_MCSPI2		0x4809B000
+#define OMAP2430_L4_S3220_2430_MMCHS1		0x4809D000
+#define OMAP2430_L4_S3220_2430_MSPRO		0x4809F000
+#define OMAP2430_L4_S3220_2430_RNG		0x480A1000
+#define OMAP2430_L4_S3220_2430_DESOCP		0x480A3000
+#define OMAP2430_L4_S3220_2430_SHA1MD5OCP	0x480A5000
+#define OMAP2430_L4_S3220_2430_AESOCP		0x480A7000
+#define OMAP2430_L4_S3220_2430_PKA		0x480AA000
+#define OMAP2430_L4_S3220_2430_USBHHCOCP	0x480AE000
+#define OMAP2430_L4_S3220_2430_MGATE		0x480B1000
+#define OMAP2430_L4_S3220_2430_HDQ1WOCP		0x480B3000
+#define OMAP2430_L4_S3220_2430_MMCHS2		0x480B5000
+#define OMAP2430_L4_S3220_2430_GPIO		0x480B7000
+#define OMAP2430_L4_S3220_2430_MCSPI3		0x480B9000
+#define OMAP2430_L4_S3220_2430_MODEM_INTH	0x480C3000
+
+/*
+ * L3 Interconnect Sideband Interconnect register base
+ */
+#define OMAP2430_SI_BASE	0x68000400
+
+/*
+ * L3 Interconnect Sideband Interconnect register offsets
+ */
+#define OMAP2430_SI_CONTOL			0x20
+#define OMAP2430_SI_FLAG_STATUS_0		0x110	/* APE_app */
+#define OMAP2430_SI_FLAG_STATUS_1		0x130	/* APE_dbg */
+#define OMAP2430_SI_FLAG_STATUS_2		0x150	/* MODEM_app */
+#define OMAP2430_SI_FLAG_STATUS_3		0x170	/* MODEM_dbg */
+
+/*
+ * Interrupts
+ */
+#define	INTC_BASE		0x480FE000	
+#define	INTC_REVISISON		0x0000
+#define	INTC_SYSCONFIG		0x0010
+#define	INTC_SYSSTATUS		0x0014
+#define	INTC_SIR_IRQ		0x0040	/* active IRQ */
+#define	INTC_SIR_FIQ		0x0044	/* active FIQ */
+#define	INTC_CONTROL		0x0048
+#define	INTC_PROTECTION		0x004c
+#define	INTC_IDLE		0x0050
+
+#define	INTC_ITR		0x0080	/* unmask intr state */
+#define	INTC_MIR		0x0084	/* intr mask */
+#define	INTC_MIR_CLEAR		0x0088	/* clr intr mask bits */
+#define	INTC_MIR_SET		0x008c	/* set intr mask bits */
+#define	INTC_ISR_SET		0x0090	/* r/w soft intr mask */
+#define	INTC_ISR_CLEAR		0x0094	/* clr soft intr mask */
+#define	INTC_PENDING_IRQ	0x0098	/* masked irq state */
+#define	INTC_PENDING_FIQ(n)	0x009c	/* masked fiq state */
+
+#define	INTC_ILR(n)		0x0100	
+
+#define	INTC_SYSCONFIG_SOFTRESET	0x2
+#define	INTC_SYSCONFIG_AUTOIDLE		0x1
+
+#define	INTC_SYSSTATUS_RESETDONE	0x1
+
+#define	INTC_CONTROL_GLOBALMASK		0x4	/* All IRQ & FIQ are masked */
+#define	INTC_CONTROL_NEWFIQAGR		0x2
+#define	INTC_CONTROL_NEWIRQAGR		0x1
+
+#define	INTC_PROTECTION_ENABLED		0x1	/* only diddle if prived */
+
+#define	INTC_IDLE_TURBO			0x2
+#define	INTC_IDLE_FUNCIDLE		0x1
+
+#define INTC_ILR_PRIORTY_SHFT		2
+#define	INTC_ILR_FIQNIRQ		0x1	/* intr is a FIQ */
+
+/*
+ * GPIO
+ */
+#define	GPIO1_BASE			0x4900c000
+#define	GPIO2_BASE			0x4900e000
+#define	GPIO3_BASE			0x49010000
+#define	GPIO4_BASE			0x49012000
+#define	GPIO5_BASE			0x480b6000
+#define	GPIO_IRQSTATUS1			0x018
+#define	GPIO_IRQENABLE1			0x01c
+#define	GPIO_WAKEUPENABLE		0x020
+#define	GPIO_IRQSTATUS2			0x028
+#define	GPIO_IRQENABLE2			0x02c
+#define	GPIO_CTRL			0x030
+#define	GPIO_OE				0x034
+#define	GPIO_DATAIN			0x038
+#define	GPIO_DATAOUT			0x03c
+#define	GPIO_LEVELDETECT0		0x040
+#define	GPIO_LEVELDETECT1		0x044
+#define	GPIO_RISINGDETECT		0x048
+#define	GPIO_FALLINGDETECT		0x04c
+#define	GPIO_DEBOUNCENABLE		0x050
+#define	GPIO_DEBOUNINGTIME		0x054
+#define	GPIO_CLEARIRQENABLE1		0x060
+#define	GPIO_SETIRQENABLE1		0x064
+#define	GPIO_CLEARIRQENABLE2		0x070
+#define	GPIO_SETIRQENABLE2		0x074
+#define	GPIO_CLEANWKUENA		0x080
+#define GPIO_SETWKUENA			0x084
+#define GPIO_CLEARDATAOUT		0x090
+#define GPIO_SETDATAOUT			0x094
+
+#endif	/* _OMAP2430H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_L3i.c sys/arch/arm/omap/omap_L3i.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_L3i.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_L3i.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,336 @@
+/*	$Id$	*/
+
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "opt_omap.h"
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: omap_L3i.c,v 1.1.6.1 2007/02/21 18:27:16 snj Exp $");
+
+#include "omapdmac.h"	/* for NOMAPDMAC */
+#include "locators.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+
+#include <arm/cpufunc.h>
+#include <arm/mainbus/mainbus.h>
+#include <arm/omap/omap_reg.h>
+#include <arm/omap/omap_var.h>
+
+#if defined(OMAP_2430)
+#include <arm/omap/omap2430reg.h>
+#ifdef NOTYET
+#include <arm/omap/omap2430var.h>
+#endif
+#else
+/*
+ * we have only used this with OMAP 2430 so far....
+ * some of the 2430 stuff may generalize to other OMAP implementations,
+ * or not.  Either generalize the include files accordingly, or
+ * add your own implementation-specific includes.
+ */
+# error unknown OMAP L3 Interconnect implementation
+#endif
+
+struct L3i_softc {
+	struct device		sc_dev;
+	bus_dma_tag_t		sc_dmac;
+	bus_space_tag_t		sc_iot;
+	bus_space_handle_t	sc_ioh;
+};
+
+
+/* prototypes */
+static int	L3i_match(struct device *, struct cfdata *, void *);
+static void	L3i_attach(struct device *, struct device *, void *);
+void		L3i_target_agent_check(struct L3i_softc *, bus_addr_t, char *);
+static void	L3i_decode_ta_COMPONENT(uint32_t);
+static void	L3i_decode_ta_CORE(uint32_t);
+static void	L3i_decode_ta_AGENT_CONTROL(uint32_t);
+static void	L3i_decode_ta_AGENT_STATUS(uint32_t);
+static void	L3i_decode_ta_ERROR_LOG(uint32_t);
+static void	L3i_decode_ta_ERROR_LOG_ADDR(uint32_t);
+#ifdef NOTYET
+static int 	L3i_search(struct device *, struct cfdata *,
+			     const int *, void *);
+static int	L3i_print(void *, const char *);
+#endif
+
+#define TARGET_AGENT_REGS_ENTRY(reg) \
+	{ OMAP2430_TA_ ## reg, L3i_decode_ta_ ## reg, #reg }
+struct {
+	bus_size_t offset;
+	void (*decode)(uint32_t);
+	const char *name;
+} target_agent_regs[] = {
+	TARGET_AGENT_REGS_ENTRY(COMPONENT),
+	TARGET_AGENT_REGS_ENTRY(CORE),
+	TARGET_AGENT_REGS_ENTRY(AGENT_CONTROL),
+	TARGET_AGENT_REGS_ENTRY(AGENT_STATUS),
+	TARGET_AGENT_REGS_ENTRY(ERROR_LOG),
+	TARGET_AGENT_REGS_ENTRY(ERROR_LOG_ADDR),
+};
+#define TARGET_AGENT_REGS_NENTRIES \
+		(sizeof(target_agent_regs) / sizeof(target_agent_regs[0]))
+
+
+/* attach structures */
+CFATTACH_DECL(L3i, sizeof(struct L3i_softc),
+	L3i_match, L3i_attach, NULL, NULL);
+
+static int L3i_attached;	/* XXX assumes only 1 instance */
+
+static int
+L3i_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	if (L3i_attached != 0)
+		return 0;
+
+	return 1;
+}
+
+static void
+L3i_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct L3i_softc *sc = (struct L3i_softc *)self;
+
+	sc->sc_iot = &omap_bs_tag;
+
+	aprint_normal(": L3i Interconnect\n");
+
+	sc->sc_ioh = 0;
+	sc->sc_dmac = &omap_bus_dma_tag;
+
+	L3i_attached = 1;
+
+#ifdef L3I_DEBUG
+	L3i_target_agent_check(sc, (bus_addr_t)OMAP2430_TA_L4_CORE, "L4 core");
+	L3i_target_agent_check(sc, (bus_addr_t)OMAP2430_TA_GPMC, "GPMC");
+#endif
+
+#ifdef NOTYET
+	/*
+	 * Attach all our devices
+	 */
+	config_search_ia(L3i_search, self, "L3i", NULL);
+#endif
+}
+
+static void
+L3i_decode_ta_COMPONENT(uint32_t val)
+{
+	aprint_normal("\tCODE %#x\n", TA_COMPONENT_CODE(val));
+	aprint_normal("\tREV  %#x\n", TA_COMPONENT_REV(val));
+}
+
+static void
+L3i_decode_ta_CORE(uint32_t val)
+{
+	aprint_normal("\tCODE %#x\n", TA_AGENT_CORE_CODE(val));
+	aprint_normal("\tREV  %#x\n", TA_AGENT_CORE_REV(val));
+}
+
+static void
+L3i_decode_ta_AGENT_CONTROL(uint32_t val)
+{
+	const uint core_timeout_base_tab[8] = {
+		0, 1, 2, 3, 4, -1, -1, -1
+	};
+	uint core_timeout_ix;
+
+	core_timeout_ix = (val & TA_AGENT_CONTROL_CORE_TIMEOUT_BASE)
+				>> TA_AGENT_CONTROL_CORE_TIMEOUT_BASE_SHFT;
+
+	aprint_normal("\tCORE_REQ_TIMEOUT_REP %d\n",
+			((val & TA_AGENT_CONTROL_CORE_REQ_TIMEOUT_REP) != 0));
+	aprint_normal("\tCORE_SERROR_REP %d\n",
+			((val & TA_AGENT_CONTROL_CORE_SERROR_REP) != 0));
+	aprint_normal("\tCORE_TIMEOUT_BASE %d\n",
+			core_timeout_base_tab[core_timeout_ix]);
+	aprint_normal("\tCORE_REJECT %d\n",
+			((val & TA_AGENT_CONTROL_CORE_REJECT) != 0));
+	aprint_normal("\tCORE_RESET %d\n",
+			((val & TA_AGENT_CONTROL_CORE_RESET) != 0));
+}
+
+static void
+L3i_decode_ta_AGENT_STATUS(uint32_t val)
+{
+	aprint_normal("\tSERROR %d\n",
+			((val & TA_AGENT_STATUS_SERROR) != 0));
+	aprint_normal("\tBURST_CLOSE %d\n",
+			((val & TA_AGENT_STATUS_BURST_CLOSE) != 0));
+	aprint_normal("\tTA_AGENT_STATUS_TIMEBASE %d\n",
+			((val & TA_AGENT_STATUS_TIMEBASE) >> 12));
+	aprint_normal("\tREQ_TIMEOUT %d\n",
+			((val & TA_AGENT_STATUS_REQ_TIMEOUT) != 0));
+	aprint_normal("\tREADEX %d\n",
+			((val & TA_AGENT_STATUS_READEX) != 0));
+	aprint_normal("\tBURST %d\n",
+			((val & TA_AGENT_STATUS_BURST) != 0));
+	aprint_normal("\tRESP_ACTIVE %d\n",
+			((val & TA_AGENT_STATUS_RESP_ACTIVE) != 0));
+	aprint_normal("\tREQ_WAITING %d\n",
+			((val & TA_AGENT_STATUS_REQ_WAITING) != 0));
+	aprint_normal("\tCORE_RESET %d\n",
+			((val & TA_AGENT_STATUS_CORE_RESET) != 0));
+}
+
+static void
+L3i_decode_ta_ERROR_LOG(uint32_t val)
+{
+	aprint_normal("\tCMD %d\n",
+			(val & TA_ERROR_LOG_CMD));
+	aprint_normal("\tINITID %d\n",
+			(val & TA_ERROR_LOG_INITID) >> 8);
+	aprint_normal("\tCODE %d\n",
+			(val & TA_ERROR_LOG_CODE) >> 24);
+	aprint_normal("\tMULTI %d\n",
+			((val & TA_ERROR_LOG_MULTI) != 0));
+}
+
+static void
+L3i_decode_ta_ERROR_LOG_ADDR(uint32_t val)
+{
+}
+
+
+void
+L3i_target_agent_check(struct L3i_softc *sc, bus_addr_t ba, char *agent)
+{
+	bus_space_tag_t iot = sc->sc_iot;
+	bus_space_handle_t ioh;
+	uint32_t r;
+	uint i;
+	int err;
+
+	err = bus_space_map(sc->sc_iot, ba, 1024, 0, &ioh);
+	if (err != 0) {
+		aprint_error("%s: cannot map L3 Target Agent %s at %#lx\n",
+			sc->sc_dev.dv_xname, agent, ba);
+		return;
+	} 
+
+	for (i=0; i < TARGET_AGENT_REGS_NENTRIES; i++) {
+		r = bus_space_read_4(iot, ioh, target_agent_regs[i].offset);
+		aprint_normal("%s: Agent %s Reg %s: %#x\n", sc->sc_dev.dv_xname,
+			agent, target_agent_regs[i].name, r);
+		target_agent_regs[i].decode(r);
+			
+	}
+
+	bus_space_unmap(sc->sc_iot, ioh, 1024);
+}
+
+
+#ifdef NOTYET
+
+static int
+L3i_search(struct device *parent, struct cfdata *cf,
+	     const int *ldesc, void *aux)
+{
+	struct L3i_softc *sc = (struct L3i_softc *)parent;
+	struct L3i_attach_args aa;
+
+	/* Set up the attach args. */
+	if (cf->cf_loc[L3iCF_NOBYTEACC] == 1) {
+		if (cf->cf_loc[L3iCF_MULT] == 1)
+			aa.L3i_iot = &nobyteacc_bs_tag;
+		else
+			panic("nobyteacc specified for device with "
+				"non-byte multiplier\n");
+	} else {
+		switch (cf->cf_loc[L3iCF_MULT]) {
+		case 1:
+			aa.L3i_iot = &omap_bs_tag;
+			break;
+		case 2:
+			aa.L3i_iot = &omap_a2x_bs_tag;
+			break;
+		case 4:
+			aa.L3i_iot = &omap_a4x_bs_tag;
+			break;
+		default:
+			panic("Unsupported EMIFS multiplier.");
+			break;
+		}
+	}
+
+	aa.L3i_dmac = sc->sc_dmac;
+	aa.L3i_addr = cf->cf_loc[L3iCF_ADDR];
+	aa.L3i_size = cf->cf_loc[L3iCF_SIZE];
+	aa.L3i_intr = cf->cf_loc[L3iCF_INTR];
+
+#if defined(OMAP_2430)
+	if ((aa.L3i_addr >= OMAP2430_L3i_BASE)
+	&&  (aa.L3i_addr < (OMAP2430_L4_CORE_BASE + OMAP2430_L3i_SIZE))) {
+		/* XXX
+		 * if size was specified, then check it too
+		 * otherwise just assume it is OK
+		 */
+		if ((aa.L3i_size != L3iCF_SIZE_DEFAULT)
+		&&  ((aa.L3i_addr + aa.L3i_size)
+			>= (OMAP2430_L4_CORE_BASE + OMAP2430_L3i_SIZE)))
+				return 1;		/* NG */
+		if (config_match(parent, cf, &aa)) {
+			config_attach(parent, cf, &aa, L3i_print);
+			return 0;			/* love it */
+		}
+	}
+#endif
+
+	return 1;	/* NG */
+}
+
+static int
+L3i_print(void *aux, const char *name)
+{
+	struct L3i_attach_args *sa = (struct L3i_attach_args*)aux;
+
+	if (sa->L3i_addr != L3iCF_ADDR_DEFAULT) {
+		aprint_normal(" addr 0x%08lx", sa->L3i_addr);
+		if (sa->L3i_size != L3iCF_SIZE_DEFAULT)
+			aprint_normal("-0x%08lx",
+				sa->L3i_addr + sa->L3i_size-1);
+	}
+	if (sa->L3i_intr != L3iCF_INTR_DEFAULT)
+		aprint_normal(" intr %d", sa->L3i_intr);
+
+	return UNCONF;
+}
+
+#endif /* NOTYET */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_dma.c sys/arch/arm/omap/omap_dma.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_dma.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_dma.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,36 @@
+/*
+ * bus dma tag for OMAP processor.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+
+#include <uvm/uvm_extern.h>
+
+#define	_ARM32_BUS_DMA_PRIVATE
+#include <machine/bus.h>
+
+struct arm32_bus_dma_tag omap_bus_dma_tag = {
+	0,
+	0,
+	NULL,			/* _cookie */
+	_bus_dmamap_create,
+	_bus_dmamap_destroy,
+	_bus_dmamap_load,
+	_bus_dmamap_load_mbuf,
+	_bus_dmamap_load_uio,
+	_bus_dmamap_load_raw,
+	_bus_dmamap_unload,
+	_bus_dmamap_sync,
+	NULL,			/* sync_post */
+	_bus_dmamem_alloc,
+	_bus_dmamem_free,
+	_bus_dmamem_map,
+	_bus_dmamem_unmap,
+	_bus_dmamem_mmap
+};
+
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_emifs.c sys/arch/arm/omap/omap_emifs.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_emifs.c	2007-02-21 10:27:16.000000000 -0800
+++ sys/arch/arm/omap/omap_emifs.c	2007-09-25 10:55:22.000000000 -0700
@@ -127,6 +127,7 @@
 #include <sys/cdefs.h>
 __KERNEL_RCSID(0, "$NetBSD: omap_emifs.c,v 1.1.6.1 2007/02/21 18:27:16 snj Exp $");

+#include "omapdmac.h"	/* for NOMAPDMAC */
 #include "locators.h"

 #include <sys/param.h>
@@ -233,8 +234,7 @@
 	emifs_attached = 1;

 #if NOMAPDMAC > 0
-#error DMA not implemented
-	sc->sc_dmac = &omap_bus_dma_tag;
+	sc->sc_dmac = omap_bus_dma_init(&omap_bus_dma_tag);
 #else
 	sc->sc_dmac = NULL;
 #endif
@@ -286,9 +286,9 @@
 static void
 emifs_set_timing(struct emifs_softc *sc, struct cfdata *cf)
 {
-	static const u_int tc_freq = OMAP_TC_CLOCK_FREQ;
+	const u_int tc_freq = OMAP_TC_CLOCK_FREQ;
 	/* We force REF to be the same frequency as TC. */
-	static const u_int ref_freq = tc_freq;
+	const u_int ref_freq = tc_freq;

 	int cs, i;
 	uint32_t ccs, acs;
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_gpmc.c sys/arch/arm/omap/omap_gpmc.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_gpmc.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_gpmc.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,360 @@
+/*	$Id$	*/
+
+/* adapted from: */
+/*	$NetBSD: omap_emifs.c,v 1.1.6.1 2007/02/21 18:27:16 snj Exp $ */
+
+
+/*
+ * Autoconfiguration support for the Texas Instruments OMAP GPMC bus.
+ * Based on arm/omap/omap_emifs.c which in turn was derived
+ * Based on arm/xscale/pxa2x0.c which in turn was derived
+ * from arm/sa11x0/sa11x0.c
+ *
+ * Copyright (c) 2002, 2005  Genetec Corporation.  All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed for the NetBSD Project by
+ *	Genetec Corporation.
+ * 4. The name of Genetec Corporation may not be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright (c) 2001, The NetBSD Foundation, Inc.  All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the NetBSD
+ *      Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Copyright (c) 1999
+ *         Shin Takemura and PocketBSD Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the PocketBSD project
+ *	and its contributors.
+ * 4. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1997,1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_omap.h"
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: omap_emifs.c,v 1.1.6.1 2007/02/21 18:27:16 snj Exp $");
+
+#include "omapdmac.h"	/* for NOMAPDMAC */
+#include "locators.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+
+#include <arm/cpufunc.h>
+#include <arm/mainbus/mainbus.h>
+#include <arm/omap/omap_reg.h>
+#include <arm/omap/omap_var.h>
+
+#if defined(OMAP_2430)
+# include <arm/omap/omap2430gpmcreg.h>
+# include <arm/omap/omap2430gpmcvar.h>
+#else
+/*
+ * we have only used this with OMAP 2430 so far....
+ * some of the 2430 stuff may generalize to other OMAP implementations,
+ * or not.  Either generalize the include files accordingly, or
+ * add your own implementation-specific includes.
+ */
+# error unknown OMAP GPMC implementation
+#endif
+
+typedef struct {
+	boolean_t	cs_valid;
+	ulong		cs_addr;
+	ulong		cs_size;
+} gpmc_csconfig_t;
+
+struct gpmc_softc {
+	struct device		sc_dev;
+	bus_dma_tag_t		sc_dmac;
+	bus_space_tag_t		sc_iot;
+	bus_space_handle_t	sc_ioh;
+	gpmc_csconfig_t		sc_csconfig[OMAP_GPMC_NCS];
+};
+
+
+static bus_size_t csreg7[OMAP_GPMC_NCS] = {
+	OMAP_GPMC_CONFIG7_0,
+	OMAP_GPMC_CONFIG7_1,
+	OMAP_GPMC_CONFIG7_2,
+	OMAP_GPMC_CONFIG7_3,
+	OMAP_GPMC_CONFIG7_4,
+	OMAP_GPMC_CONFIG7_5,
+	OMAP_GPMC_CONFIG7_6,
+	OMAP_GPMC_CONFIG7_7,
+};
+
+
+/* prototypes */
+static int	gpmc_match(struct device *, struct cfdata *, void *);
+static void	gpmc_attach(struct device *, struct device *, void *);
+static void	gpmc_csconfig_init(struct gpmc_softc *);
+static int 	gpmc_search(struct device *, struct cfdata *,
+			     const int *, void *);
+static int	gpmc_print(void *, const char *);
+
+/* attach structures */
+CFATTACH_DECL(gpmc, sizeof(struct gpmc_softc),
+	gpmc_match, gpmc_attach, NULL, NULL);
+
+static int gpmc_attached;	/* XXX assumes only 1 instance */
+
+static int
+gpmc_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct mainbus_attach_args *mb = aux;
+
+	if (gpmc_attached != 0)
+		return 0;
+
+#if defined(OMAP_2430)
+	if (mb->mb_iobase != OMAP2430_GPMC_BASE)
+		return 0;
+#endif
+
+	return 1;
+}
+
+static void
+gpmc_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct gpmc_softc *sc = (struct gpmc_softc *)self;
+	struct mainbus_attach_args *mb = aux;
+	bus_space_handle_t ioh;
+	uint32_t rev;
+	int err;
+
+	sc->sc_iot = &omap_bs_tag;
+
+	err = bus_space_map(sc->sc_iot, mb->mb_iobase,
+		OMAP_GPMC_SIZE, 0, &ioh);
+	if (err != 0)
+		panic("%s: Cannot map registers, error %d",
+			self->dv_xname, err);
+
+	aprint_normal(": General Purpose Memory Controller");
+
+	rev = bus_space_read_4(sc->sc_iot, ioh, OMAP_GPMC_REVISION);
+
+	aprint_normal(", rev %d.%d\n",
+		OMAP_GPMC_REVISION_REV_MAJ(rev), 
+		OMAP_GPMC_REVISION_REV_MIN(rev));
+
+	sc->sc_ioh = ioh;
+	sc->sc_dmac = NULL;
+
+	gpmc_csconfig_init(sc);
+
+	gpmc_attached = 1;
+
+	/*
+	 * Attach all our devices
+	 */
+	config_search_ia(gpmc_search, self, "gpmc", NULL);
+}
+
+static void
+gpmc_csconfig_init(struct gpmc_softc *sc)
+{
+	gpmc_csconfig_t *cs;
+	uint32_t r;
+	int i;
+	
+
+	cs = &sc->sc_csconfig[0];
+	for (i=0; i < OMAP_GPMC_NCS; i++) {
+		memset(cs, 0, sizeof(gpmc_csconfig_t));
+		r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, csreg7[i]);
+		if ((r & OMAP_GPMC_CONFIG7_CSVALID) != 0) {
+			cs->cs_valid = TRUE;
+			cs->cs_addr = omap_gpmc_config7_addr(r);
+			cs->cs_size = omap_gpmc_config7_size(r);
+			aprint_normal("%s: CS#%d valid, "
+				"addr 0x%08lx, size %3ldMB\n",
+				sc->sc_dev.dv_xname, i,
+				cs->cs_addr, (cs->cs_size >> 20));
+		}
+		cs++;
+	}
+}
+
+static int
+gpmc_search(struct device *parent, struct cfdata *cf,
+	     const int *ldesc, void *aux)
+{
+	struct gpmc_softc *sc = (struct gpmc_softc *)parent;
+	struct gpmc_attach_args aa;
+	gpmc_csconfig_t *cs;
+	int i;
+
+	/* Set up the attach args. */
+	if (cf->cf_loc[GPMCCF_NOBYTEACC] == 1) {
+		if (cf->cf_loc[GPMCCF_MULT] == 1)
+			aa.gpmc_iot = &nobyteacc_bs_tag;
+		else
+			panic("nobyteacc specified for device with "
+				"non-byte multiplier\n");
+	} else {
+		switch (cf->cf_loc[GPMCCF_MULT]) {
+		case 1:
+			aa.gpmc_iot = &omap_bs_tag;
+			break;
+		case 2:
+			aa.gpmc_iot = &omap_a2x_bs_tag;
+			break;
+		case 4:
+			aa.gpmc_iot = &omap_a4x_bs_tag;
+			break;
+		default:
+			panic("Unsupported EMIFS multiplier.");
+			break;
+		}
+	}
+
+	aa.gpmc_dmac = sc->sc_dmac;
+	aa.gpmc_addr = cf->cf_loc[GPMCCF_ADDR];
+	aa.gpmc_size = cf->cf_loc[GPMCCF_SIZE];
+	aa.gpmc_intr = cf->cf_loc[GPMCCF_INTR];
+
+	cs = &sc->sc_csconfig[0];
+	for (i=0; i < OMAP_GPMC_NCS; i++) {
+		if ((aa.gpmc_addr >= cs->cs_addr)
+		&&  (aa.gpmc_addr < (cs->cs_addr + cs->cs_size))) {
+			/* XXX
+			 * if size was specified, then check it too
+			 * otherwise just assume it is OK
+			 */
+			if ((aa.gpmc_size != GPMCCF_SIZE_DEFAULT)
+			&&  ((aa.gpmc_addr + aa.gpmc_size)
+				>= (cs->cs_addr + cs->cs_size)))
+					continue;	/* NG */
+			if (config_match(parent, cf, &aa)) {
+				config_attach(parent, cf, &aa, gpmc_print);
+				return 0;		/* love it */
+			}
+		}
+		cs++;
+	}
+	return 1;	/* NG */
+}
+
+static int
+gpmc_print(void *aux, const char *name)
+{
+	struct gpmc_attach_args *sa = (struct gpmc_attach_args*)aux;
+
+	if (sa->gpmc_addr != GPMCCF_ADDR_DEFAULT) {
+		aprint_normal(" addr 0x%08lx", sa->gpmc_addr);
+		if (sa->gpmc_size != GPMCCF_SIZE_DEFAULT)
+			aprint_normal("-0x%08lx",
+				sa->gpmc_addr + sa->gpmc_size-1);
+	}
+	if (sa->gpmc_intr != GPMCCF_INTR_DEFAULT)
+		aprint_normal(" intr %d", sa->gpmc_intr);
+
+	return UNCONF;
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_gptmrreg.h sys/arch/arm/omap/omap_gptmrreg.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_gptmrreg.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_gptmrreg.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,75 @@
+#ifndef _ARM_OMAP_OMAP_GPTMRREG_H_
+#define _ARM_OMAP_OMAP_GPTMRREG_H_
+
+/* Registers */
+#define TIDR		0x00
+#define TIOCP_CFG	0x10
+#define TISTAT		0x14
+#define TISR		0x18
+#define TIER		0x1C
+#define TWER		0x20
+#define TCLR		0x24
+#define TCRR		0x28
+#define TLDR		0x2C
+#define TTGR		0x30
+#define TWPS		0x34
+#define TMAR		0x38
+#define TCAR		0x3C
+#define TSICR		0x40
+
+
+#define TIDR_TID_REV_MASK		0xF
+
+#define TIOCP_CFG_AUTOIDLE		(1<<0)
+#define TIOCP_CFG_SOFTRESET		(1<<1)
+#define TIOCP_CFG_ENAWAKEUP		(1<<2)
+#define TIOCP_CFG_IDLEMODE_MASK	(3<<3)
+#define TIOCP_CFG_IDLEMODE(n)	(((n)&0x3)<<3)
+#define TIOCP_CFG_EMUFREE		(1<<5)
+
+#define TISTAT_RESETDONE		(1<<0)
+
+#define TISR_MAT_IT_FLAG		(1<<0)
+#define TISR_OVF_IT_FLAG		(1<<1)
+#define TISR_TCAR_IT_FLAG		(1<<2)
+
+#define TIER_MAT_IT_ENA			(1<<0)
+#define TIER_OVF_IT_ENA			(1<<1)
+#define TIER_TCAR_IT_ENA		(1<<2)
+
+#define TWER_MAT_WUP_ENA		(1<<0)
+#define TWER_OVF_WUP_ENA		(1<<2)
+#define TWER_TCAR_WUP_ENA		(1<<3)
+
+#define TCLR_ST					(1<<0)
+#define TCLR_AR					(1<<1)
+#define TCLR_PTV_MASK			(7<<2)
+#define TCLR_PTV(n)				((n)<<2)
+#define TCLR_PRE(n)				((n)<<5)
+#define TCLR_CE					(1<<6)
+#define TCLR_SCPWM				(1<<7)
+#define TCLR_TCM(n)				((n)<<8)
+#define TCLR_TCM_MASK			(3<<8)
+#define TCLR_TRG(n)				((n)<<10)
+#define TCLR_TRG_MASK			(3<<10)
+#define TCLR_PT					(1<<12)
+
+#define TCLR_TCM_NONE			0
+#define TCLR_TCM_RISING			1
+#define TCLR_TCM_FALLING		2
+#define TCLR_TCM_BOTH			3
+
+#define TCLR_TRG_NONE			0
+#define TCLR_TRG_OVERFLOW		1
+#define TCLR_TRG_OVERFLOW_AND_MATCH 2
+
+#define TWPS_W_PEND__TCLR		(1<<0)
+#define TWPS_W_PEND__TCRR		(1<<1)
+#define TWPS_W_PEND__TLDR		(1<<2)
+#define TWPS_W_PEND__TTGR		(1<<3)
+#define TWPS_W_PEND__TMAR		(1<<4)
+
+#define TSICR_POSTED			(1<<2)
+#define TSICR_SFT				(1<<1)
+
+#endif
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_mputmr.c sys/arch/arm/omap/omap_mputmr.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_mputmr.c	2007-02-21 10:27:17.000000000 -0800
+++ sys/arch/arm/omap/omap_mputmr.c	2007-09-25 10:55:22.000000000 -0700
@@ -248,12 +248,6 @@
 	if (ticks == 0)
 		ticks = 1;

-#ifdef DEBUG
-	if (ticks > 1)
-		printf("Missed %d ticks.\n", ticks-1);
-#endif
-
-
 	for (i = 0; i < ticks; i++)
 		hardclock(frame);

@@ -327,6 +321,23 @@
 			    stat_sc->sc_dev.dv_xname, statintr, 0);
 }

+uint32_t omap_microtimer_read(void)
+{
+	if (ref_sc != NULL)
+		return bus_space_read_4(ref_sc->sc_iot, ref_sc->sc_ioh,
+					MPU_READ_TIMER);
+	else
+		return 0;
+}
+
+uint32_t omap_microtimer_interval(uint32_t start, uint32_t end)
+{
+	if (counts_per_usec)
+		return (start - end) / counts_per_usec;
+	else
+		return 0;
+}
+
 void
 microtime(struct timeval *tvp)
 {
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_obio.c sys/arch/arm/omap/omap_obio.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_obio.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_obio.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,318 @@
+/*	$Id$	*/
+
+/* adapted from: */
+/*	$NetBSD: omap_emifs.c,v 1.1.6.1 2007/02/21 18:27:16 snj Exp $ */
+
+
+/*
+ * Autoconfiguration support for the Texas Instruments OMAP "On Board" I/O.
+ *
+ * Based on arm/omap/omap_emifs.c which in turn was derived
+ * Based on arm/xscale/pxa2x0.c which in turn was derived
+ * from arm/sa11x0/sa11x0.c
+ *
+ * Copyright (c) 2002, 2005  Genetec Corporation.  All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed for the NetBSD Project by
+ *	Genetec Corporation.
+ * 4. The name of Genetec Corporation may not be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright (c) 2001, The NetBSD Foundation, Inc.  All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by IWAMOTO Toshihiro and Ichiro FUKUHARA.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed by the NetBSD
+ *      Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Copyright (c) 1999
+ *         Shin Takemura and PocketBSD Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the PocketBSD project
+ *	and its contributors.
+ * 4. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1997,1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "opt_omap.h"
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: omap_emifs.c,v 1.1.6.1 2007/02/21 18:27:16 snj Exp $");
+
+#include "omapdmac.h"	/* for NOMAPDMAC */
+#include "locators.h"
+#include "obio.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/reboot.h>
+
+#include <machine/cpu.h>
+#include <machine/bus.h>
+
+#include <arm/cpufunc.h>
+#include <arm/mainbus/mainbus.h>
+#include <arm/omap/omap_reg.h>
+#include <arm/omap/omap_var.h>
+
+#if defined(OMAP_2430)
+# include <arm/omap/omap2430obioreg.h>
+# include <arm/omap/omap2430obiovar.h>
+#else
+/*
+ * we have only used this with OMAP 2430 so far....
+ * some of the 2430 stuff may generalize to other OMAP implementations,
+ * or not.  Either generalize the include files accordingly, or
+ * add your own implementation-specific includes.
+ */
+# error unknown OMAP OBIO implementation
+#endif
+
+typedef struct {
+	boolean_t	cs_valid;
+	ulong		cs_addr;
+	ulong		cs_size;
+} obio_csconfig_t;
+
+struct obio_softc {
+	struct device		sc_dev;
+	bus_dma_tag_t		sc_dmac;
+	bus_space_tag_t		sc_iot;
+	bus_space_handle_t	sc_ioh;
+	bus_addr_t		sc_base;
+	bus_size_t		sc_size;
+};
+
+
+/* prototypes */
+static int	obio_match(struct device *, struct cfdata *, void *);
+static void	obio_attach(struct device *, struct device *, void *);
+static int 	obio_search(struct device *, struct cfdata *,
+			     const int *, void *);
+static int	obio_print(void *, const char *);
+
+/* attach structures */
+CFATTACH_DECL(obio, sizeof(struct obio_softc),
+	obio_match, obio_attach, NULL, NULL);
+
+static int obio_attached[NOBIO];
+
+static int
+obio_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct mainbus_attach_args *mb = aux;
+
+
+#if defined(OMAP_2430)
+	if ((mb->mb_iobase == OMAP2430_OBIO_0_BASE)
+	&&  (mb->mb_iosize == OMAP2430_OBIO_0_SIZE)
+	&&  (obio_attached[0] == 0))
+		return 1;
+	if ((mb->mb_iobase == OMAP2430_OBIO_1_BASE)
+	&&  (mb->mb_iosize == OMAP2430_OBIO_1_SIZE)
+	&&  (obio_attached[1] == 0))
+		return 1;
+#else
+# error unknown OMAP implementation
+#endif
+
+	return 0;
+}
+
+static void
+obio_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct obio_softc *sc = (struct obio_softc *)self;
+	struct mainbus_attach_args *mb = (struct mainbus_attach_args *)aux;
+
+	sc->sc_iot = &omap_bs_tag;
+
+	aprint_normal(": On-Board IO\n");
+
+	sc->sc_ioh = 0;
+	sc->sc_dmac = &omap_bus_dma_tag;
+	sc->sc_base = mb->mb_iobase;
+	sc->sc_size = mb->mb_iosize;
+
+#if defined(OMAP_2430)
+	if (mb->mb_iobase == OMAP2430_OBIO_0_BASE)
+		obio_attached[0] = 1;
+	if (mb->mb_iobase == OMAP2430_OBIO_1_BASE)
+		obio_attached[1] = 1;
+#endif
+
+	/*
+	 * Attach all our devices
+	 */
+	config_search_ia(obio_search, self, "obio", NULL);
+}
+
+static int
+obio_search(struct device *parent, struct cfdata *cf,
+	     const int *ldesc, void *aux)
+{
+	struct obio_softc *sc = (struct obio_softc *)parent;
+	struct obio_attach_args aa;
+
+	/* Set up the attach args. */
+	if (cf->cf_loc[OBIOCF_NOBYTEACC] == 1) {
+		if (cf->cf_loc[OBIOCF_MULT] == 1)
+			aa.obio_iot = &nobyteacc_bs_tag;
+		else
+			panic("nobyteacc specified for device with "
+				"non-byte multiplier\n");
+	} else {
+		switch (cf->cf_loc[OBIOCF_MULT]) {
+		case 1:
+			aa.obio_iot = &omap_bs_tag;
+			break;
+		case 2:
+			aa.obio_iot = &omap_a2x_bs_tag;
+			break;
+		case 4:
+			aa.obio_iot = &omap_a4x_bs_tag;
+			break;
+		default:
+			panic("Unsupported EMIFS multiplier.");
+			break;
+		}
+	}
+
+	aa.obio_dmac = sc->sc_dmac;
+	aa.obio_addr = cf->cf_loc[OBIOCF_ADDR];
+	aa.obio_size = cf->cf_loc[OBIOCF_SIZE];
+	aa.obio_intr = cf->cf_loc[OBIOCF_INTR];
+
+#if defined(OMAP_2430)
+	if ((aa.obio_addr >= sc->sc_base)
+	&&  (aa.obio_addr < (sc->sc_base + sc->sc_size))) {
+		/* XXX
+		 * if size was specified, then check it too
+		 * otherwise just assume it is OK
+		 */
+		if ((aa.obio_size != OBIOCF_SIZE_DEFAULT)
+		&&  ((aa.obio_addr + aa.obio_size)
+			>= (sc->sc_base + sc->sc_size)))
+				return 1;		/* NG */
+		if (config_match(parent, cf, &aa)) {
+			config_attach(parent, cf, &aa, obio_print);
+			return 0;			/* love it */
+		}
+	}
+#endif
+
+	return 1;	/* NG */
+}
+
+static int
+obio_print(void *aux, const char *name)
+{
+	struct obio_attach_args *sa = (struct obio_attach_args*)aux;
+
+	if (sa->obio_addr != OBIOCF_ADDR_DEFAULT) {
+		aprint_normal(" addr 0x%08lx", sa->obio_addr);
+		if (sa->obio_size != OBIOCF_SIZE_DEFAULT)
+			aprint_normal("-0x%08lx",
+				sa->obio_addr + sa->obio_size-1);
+	}
+	if (sa->obio_intr != OBIOCF_INTR_DEFAULT)
+		aprint_normal(" intr %d", sa->obio_intr);
+
+	return UNCONF;
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_reg.h sys/arch/arm/omap/omap_reg.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_reg.h	2007-02-21 10:27:17.000000000 -0800
+++ sys/arch/arm/omap/omap_reg.h	2007-09-25 10:55:22.000000000 -0700
@@ -32,6 +32,10 @@
 #endif
 #define MEMSIZE_BYTES (MEMSIZE * 1024 * 1024)

+#if !defined(OMAP_2430)
+/*
+ * these assertions belong in platform specific files that care
+ */
 #ifndef OMAP_TIPB_PBASE
 #error Specify the TIPB physical address with the OMAP_TIPB_PBASE option.
 #endif
@@ -39,4 +43,6 @@
 #error Specify the TIPB size with the OMAP_TIPB_SIZE option.
 #endif

+#endif	/* OMAP_2430 */
+
 #endif /* _ARM_OMAP_OMAP_REG_H_ */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_rtc.c sys/arch/arm/omap/omap_rtc.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_rtc.c	2007-02-21 10:41:50.000000000 -0800
+++ sys/arch/arm/omap/omap_rtc.c	2007-09-25 10:55:22.000000000 -0700
@@ -3,11 +3,9 @@
 /*
  * OMAP RTC driver, based on i80321_timer.c.
  *
- * Copyright (c) 2001, 2002 Wasabi Systems, Inc.
+ * Copyright (c) 2007 Danger Inc.
  * All rights reserved.
  *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -18,23 +16,20 @@
  *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software
  *    must display the following acknowledgement:
- *	This product includes software developed for the NetBSD Project by
- *	Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- *    or promote products derived from this software without specific prior
- *    written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
  */

 #include <sys/cdefs.h>
@@ -46,6 +41,7 @@
 #include <sys/kernel.h>
 #include <sys/time.h>
 #include <sys/device.h>
+
 #include <dev/clock_subr.h>

 #include <machine/bus.h>
@@ -58,6 +54,10 @@

 #define	BASEYEAR		2000

+/* Minimum plausible year for times. */
+
+#define SANEYEAR		2006
+
 /* Register offsets and bit fields. */

 #define SECONDS_REG		0x00
@@ -93,22 +93,24 @@
 	bus_space_handle_t	sc_ioh;
 	int			sc_intr;
 	void			*sc_irqcookie;
-	struct todr_chip_handle	sc_todr;
 };

+static struct omaprtc_softc *rtc_sc = NULL;
+
 CFATTACH_DECL(omaprtc, sizeof(struct omaprtc_softc),
     omaprtc_match, omaprtc_attach, NULL, NULL);

-static int omaprtc_gettime(todr_chip_handle_t, struct clock_ymdhms *);
-static int omaprtc_settime(todr_chip_handle_t, struct clock_ymdhms *);
+int omaprtc_gettime(volatile struct timeval *tv);
+int omaprtc_settime(volatile struct timeval *tv);
+int omaprtc_setalarmtime(struct timeval *tv);

-#define rtc_is_busy()	(bus_space_read_1(sc->sc_iot, sc->sc_ioh, \
+#define rtc_is_busy()	(bus_space_read_1(rtc_sc->sc_iot, rtc_sc->sc_ioh, \
 					  RTC_STATUS_REG) & 1<<BUSY)

-static int
-omaprtc_gettime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
+int
+omaprtc_gettime(volatile struct timeval *tv)
 {
-	struct omaprtc_softc *sc = tch->cookie;
+	struct clock_ymdhms dt;
 	int s;

 	/* Wait for RTC_STATUS_REG:BUSY to go low to
@@ -132,44 +134,52 @@
 		;
 	}

-	dt->dt_year =
-		FROMBCD(bus_space_read_1(sc->sc_iot,
-					 sc->sc_ioh,
+	dt.dt_year =
+		FROMBCD(bus_space_read_1(rtc_sc->sc_iot,
+					 rtc_sc->sc_ioh,
 					 YEARS_REG)) + BASEYEAR;
-	dt->dt_mon =
-		FROMBCD(bus_space_read_1(sc->sc_iot,
-					 sc->sc_ioh,
+	dt.dt_mon =
+		FROMBCD(bus_space_read_1(rtc_sc->sc_iot,
+					 rtc_sc->sc_ioh,
 					 MONTHS_REG));
-	dt->dt_wday =
-		FROMBCD(bus_space_read_1(sc->sc_iot,
-					 sc->sc_ioh,
+	dt.dt_wday =
+		FROMBCD(bus_space_read_1(rtc_sc->sc_iot,
+					 rtc_sc->sc_ioh,
 					 WEEKS_REG) & 0x0f);
-	dt->dt_day =
-		FROMBCD(bus_space_read_1(sc->sc_iot,
-					 sc->sc_ioh,
+	dt.dt_day =
+		FROMBCD(bus_space_read_1(rtc_sc->sc_iot,
+					 rtc_sc->sc_ioh,
 					 DAYS_REG));
-	dt->dt_sec =
-		FROMBCD(bus_space_read_1(sc->sc_iot,
-					 sc->sc_ioh,
+	dt.dt_sec =
+		FROMBCD(bus_space_read_1(rtc_sc->sc_iot,
+					 rtc_sc->sc_ioh,
 					 SECONDS_REG));
-	dt->dt_hour =
-		FROMBCD(bus_space_read_1(sc->sc_iot,
-					 sc->sc_ioh,
+	dt.dt_hour =
+		FROMBCD(bus_space_read_1(rtc_sc->sc_iot,
+					 rtc_sc->sc_ioh,
 					 HOURS_REG));
-	dt->dt_min =
-		FROMBCD(bus_space_read_1(sc->sc_iot,
-					 sc->sc_ioh,
+	dt.dt_min =
+		FROMBCD(bus_space_read_1(rtc_sc->sc_iot,
+					 rtc_sc->sc_ioh,
 					 MINUTES_REG));
 	restore_interrupts(s);
+	tv->tv_sec = clock_ymdhms_to_secs(&dt);
+        tv->tv_usec = 0;
         return 0;
 }

-static int
-omaprtc_settime(todr_chip_handle_t tch, struct clock_ymdhms *dt)
+int
+omaprtc_settime(volatile struct timeval *tv)
 {
-	struct omaprtc_softc *sc = tch->cookie;
+	struct clock_ymdhms dt;
 	int s;

+	clock_secs_to_ymdhms(tv->tv_sec, &dt);
+
+	/* Cancel any pending alarm since it may fire at the wrong time
+	   after the time change. */
+
+	omaprtc_setalarmtime(NULL);
 	s = disable_interrupts(I32_bit);

 	while (rtc_is_busy()) {
@@ -182,25 +192,167 @@
 	 * seconds into minutes.
 	 */

-	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
-			  YEARS_REG, TOBCD(dt->dt_year - BASEYEAR));
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
-			  MONTHS_REG, TOBCD(dt->dt_mon));
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
-			  WEEKS_REG, TOBCD(dt->dt_wday & 0x0f));
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
-			  DAYS_REG, TOBCD(dt->dt_day));
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
-			  SECONDS_REG, TOBCD(dt->dt_sec));
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
-			  HOURS_REG, TOBCD(dt->dt_hour));
-	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
-			  MINUTES_REG, TOBCD(dt->dt_min));
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  YEARS_REG, TOBCD(dt.dt_year - BASEYEAR));
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  MONTHS_REG, TOBCD(dt.dt_mon));
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  WEEKS_REG, TOBCD(dt.dt_wday & 0x0f));
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  DAYS_REG, TOBCD(dt.dt_day));
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  SECONDS_REG, TOBCD(dt.dt_sec));
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  HOURS_REG, TOBCD(dt.dt_hour));
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  MINUTES_REG, TOBCD(dt.dt_min));
+	restore_interrupts(s);
+        return 0;
+}
+
+int
+omaprtc_setalarmtime(struct timeval *tv)
+{
+	struct clock_ymdhms dt;
+	unsigned char val, intval;
+	int s;
+
+	if (tv)
+		clock_secs_to_ymdhms(tv->tv_sec, &dt);
+
+	s = disable_interrupts(I32_bit);
+
+	/* disarm alarm interrupt */
+	intval = bus_space_read_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			       RTC_INTERRUPTS_REG);
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  RTC_INTERRUPTS_REG, intval & ~(1<<IT_ALARM));
+
+	/* clear pending alarm */
+	/* todo: correct?  write 1 to clear interrupt? */
+	val = bus_space_read_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			       RTC_STATUS_REG);
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  RTC_STATUS_REG, val & ~(1<<ALARM));
+
+	/* TODO: Need to clear in interrupt controller? */
+
+	if (tv) {
+		bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+				  ALARM_YEARS_REG,
+				  TOBCD(dt.dt_year - BASEYEAR));
+		bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+				  ALARM_MONTHS_REG, TOBCD(dt.dt_mon));
+		bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+				  ALARM_DAYS_REG, TOBCD(dt.dt_day));
+		bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+				  ALARM_SECONDS_REG, TOBCD(dt.dt_sec));
+		bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+				  ALARM_HOURS_REG, TOBCD(dt.dt_hour));
+		bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+				  ALARM_MINUTES_REG, TOBCD(dt.dt_min));
+
+		/* Enable the interrupt */
+		bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+				  RTC_INTERRUPTS_REG, intval | (1<<IT_ALARM));
+	}
+
 	restore_interrupts(s);
         return 0;
 }

 static int
+omaprtc_alarmintr(void *arg)
+{
+	unsigned char val;
+
+	/* De-assert the IRQ_ALARM_CHIP line
+	 * by writing into RTC_STATUS_REG:ALARM.
+	 */
+	val = bus_space_read_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			       RTC_STATUS_REG);
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh,
+			  RTC_STATUS_REG, val | (1<<ALARM));
+	printf("RTC alarm interrupt.\n");
+	return 1;
+}
+
+
+/*
+ * inittodr:
+ *
+ *	Initialize time from the time-of-day register.
+ */
+
+void
+inittodr(time_t base)
+{
+	time_t deltat;
+	int badbase;
+
+	if (base < (SANEYEAR - 1970) * SECYR) {
+		printf("WARNING: preposterous time in file system\n");
+		/* read the system clock anyway */
+		base = (SANEYEAR - 1970) * SECYR;
+		badbase = 1;
+        } else {
+                badbase = 0;
+	}
+
+	time.tv_sec = base;
+	time.tv_usec = 0;
+
+        if (omaprtc_gettime(&time) != 0 ||
+	    (time.tv_sec < (SANEYEAR - 1970) * SECYR)) {
+                /*
+                 * Believe the time in the file system for lack of
+                 * anything better, resetting the TODR.
+                 */
+                time.tv_sec = base;
+                time.tv_usec = 0;
+                if (!badbase) {
+                        printf("WARNING: preposterous clock chip time\n");
+                        resettodr();
+                }
+                goto bad;
+        }
+
+        if (!badbase) {
+                /*
+                 * See if we gained/lost two or more days; if
+                 * so, assume something is amiss.
+                 */
+                deltat = time.tv_sec - base;
+                if (deltat < 0)
+                        deltat = -deltat;
+                if (deltat < 2 * SECDAY)
+                        return;         /* all is well */
+                printf("WARNING: clock %s %ld days\n",
+                    time.tv_sec < base ? "lost" : "gained",
+                    (long)deltat / SECDAY);
+        }
+ bad:
+        printf("WARNING: CHECK AND RESET THE DATE!\n");
+
+
+}
+
+/*
+ * resettodr:
+ *
+ *	Reset the time-of-day register with the current time.
+ */
+void
+resettodr(void)
+{
+        if (time.tv_sec == 0)
+                return;
+
+        if (omaprtc_settime(&time) != 0)
+                printf("resettodr: failed to set time\n");
+}
+
+static int
 omaprtc_match(struct device *parent, struct cfdata *match, void *aux)
 {
 	struct tipb_attach_args *tipb = aux;
@@ -230,6 +382,18 @@

 	aprint_normal(": OMAP RTC\n");
 	aprint_naive("\n");
+	rtc_sc = sc;
+
+	if (sc->sc_intr != -1) {
+		sc->sc_irqcookie = omap_intr_establish(sc->sc_intr, IPL_CLOCK,
+						       sc->sc_dev.dv_xname,
+						       omaprtc_alarmintr, sc);
+		if (sc->sc_irqcookie == NULL) {
+			aprint_error("%s: Failed to install alarm interrupt"
+				     " handler.\n",
+				     sc->sc_dev.dv_xname);
+		}
+	}

 	/*
 	 * Start RTC (STOP_RTC=1 starts it, go figure), 24 hour mode,
@@ -237,12 +401,6 @@
 	 * cannot use split power, no test mode.
 	 */

-	bus_space_write_1(sc->sc_iot, sc->sc_ioh, RTC_CTRL_REG,
+	bus_space_write_1(rtc_sc->sc_iot, rtc_sc->sc_ioh, RTC_CTRL_REG,
 			  1 << STOP_RTC);
-
-	sc->sc_todr.cookie = sc;
-	sc->sc_todr.todr_gettime_ymdhms = omaprtc_gettime;
-	sc->sc_todr.todr_settime_ymdhms = omaprtc_settime;
-	todr_attach(&sc->sc_todr);
 }
-
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_start.S sys/arch/arm/omap/omap_start.S
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_start.S	2007-02-21 10:27:18.000000000 -0800
+++ sys/arch/arm/omap/omap_start.S	2007-09-25 10:55:22.000000000 -0700
@@ -61,6 +61,33 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
  */

 #include "assym.h"
@@ -92,6 +119,15 @@
 	 */
 	/* Build page table from scratch */
 	ldr	r0, Ltemp_l1_table
+	/* Page table address -> round_page(_end) */
+	mov	r1, #PAGE_SIZE
+	sub	r1, r1, #1
+	add	r0, r0, r1  
+ 	mvn	r1, r1	
+	and	r0, r0, r1 
+	ldr 	r1, =KERNEL_BASE_phys
+	add	r0, r0, r1 
+	sub 	r0, r0, #KERNEL_BASE
 	mov	r1, r0			/* Save the page table address. */
 	/* Zero the entire table so all virtual addresses are invalid. */
 	mov	r2, #L1_TABLE_SIZE	/* in bytes */
@@ -182,8 +218,8 @@
 Ll1_s_frame:
 	.word	L1_S_FRAME
 Ltemp_l1_table:
-	/* Put the temporary L1 translation table at the end of SDRAM. */
-	.word	KERNEL_BASE_phys + MEMSIZE_BYTES - L1_TABLE_SIZE
+	/* Put the temporary L1 translation table after the kernel. */
+	.word 	_end
 Lcpsr:
 	/* What we want to have the CPSR be when we jump to start. */
 	.word CPU_CONTROL_MMU_ENABLE | \
@@ -204,6 +240,10 @@
 	.word	attr					    ;

 mmu_init_table:
+	/* Map PA=VA WHOLE REGION*/
+	MMU_INIT(KERNEL_BASE_phys + L1_S_SIZE, KERNEL_BASE_phys + L1_S_SIZE,
+		(MEMSIZE_BYTES - 1) / L1_S_SIZE
+		, L1_S_PROTO|L1_S_AP(AP_KRW));
 	/* Map SDRAM where we're executing from VA==PA, read-only */
 	MMU_INIT(KERNEL_BASE_phys, KERNEL_BASE_phys,
 		1,
@@ -218,3 +258,5 @@
 		L1_S_PROTO | L1_S_AP(AP_KRW))
 	/* end of table */
 	MMU_INIT(0, 0, 0, 0)
+
+
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_var.h sys/arch/arm/omap/omap_var.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_var.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_var.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,19 @@
+#ifndef _ARM_OMAP_OMAP_VAR_H_
+#define _ARM_OMAP_OMAP_VAR_H_
+
+#include <sys/types.h>
+#include <machine/bus.h>
+
+/* Texas Instruments OMAP generic */
+
+
+extern struct bus_space omap_bs_tag;
+extern struct arm32_bus_dma_tag omap_bus_dma_tag;
+extern struct bus_space omap_a4x_bs_tag;
+extern struct bus_space omap_a2x_bs_tag;
+extern struct bus_space nobyteacc_bs_tag;
+
+/* platform needs to provide this */
+bus_dma_tag_t omap_bus_dma_init(struct arm32_bus_dma_tag *);
+
+#endif /* _ARM_OMAP_OMAP_VAR_H_ */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_wdt.c sys/arch/arm/omap/omap_wdt.c
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_wdt.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_wdt.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,240 @@
+/*
+ * OMAP watchdog timers, common code
+ */
+
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/callout.h>
+#include <sys/cdefs.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/wdog.h>
+
+#include <machine/param.h>
+#include <machine/bus.h>
+#include <dev/sysmon/sysmonvar.h>
+
+#include <arm/omap/omap_reg.h>
+#include <arm/omap/omap_tipb.h>
+#include <arm/omap/omap_wdt.h>
+#include <arm/omap/omap_wdtvar.h>
+#include <arm/omap/omap_wdtreg.h>
+
+struct omapwdt32k_softc *omapwdt32k_sc;
+int omapwdt_sysconfig;
+
+static void
+omapwdt32k_sync(void)
+{
+	/* The WCLR, WCRR, WLDR, WTGR and WSPR registers are
+	 * synchronized to the 32kHz clock.  Each has an
+	 * associated status bit that's set when there's
+	 * a pending write.  This function will wait for
+	 * all of those status bits to become clear so
+	 * the caller can safely write to any of the registers.
+	 */
+	while (bus_space_read_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh,
+				WWPS) &
+	       (W_PEND_WSPR | W_PEND_WTGR | W_PEND_WLDR | W_PEND_WCRR |
+		W_PEND_WCLR))
+		delay(10);
+}
+
+static void
+omapwdt32k_start(void)
+{
+	omapwdt32k_sync();
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WSPR,
+			  WD_ENABLE_WORD1);
+	omapwdt32k_sync();
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WSPR,
+			  WD_ENABLE_WORD2);
+}
+
+static void
+omapwdt32k_stop(void)
+{
+	omapwdt32k_sync();
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WSPR,
+			  WD_DISABLE_WORD1);
+	omapwdt32k_sync();
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WSPR,
+			  WD_DISABLE_WORD2);
+}
+
+static void
+omapwdt32k_do_set_timeout(void)
+{
+	if (omapwdt32k_sc->sc_armed) {
+		/*
+		 * The watchdog must be disabled before writing to
+		 * the WCRR, WCLR:PTV, or WLDR registers.
+		 */
+		omapwdt32k_stop();
+	}
+
+	/* Make sure WLDR, WCRR, and WCLR are ready to be written to.
+	 */
+	omapwdt32k_sync();
+
+	/* Make sure that the prescaler is set.
+	 */
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WCLR,
+			  (WCLR_PTV(PTV) | WCLR_PRE(PRE)));
+
+	/* Write the new count value to the load and
+	 * counter registers.
+	 */
+
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WLDR,
+			  omapwdt32k_sc->sc_smw.smw_period ?
+			  WATCHDOG_COUNT(omapwdt32k_sc->sc_smw.smw_period)
+			  : 0xffffffff);
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WCRR,
+			  omapwdt32k_sc->sc_smw.smw_period ?
+			  WATCHDOG_COUNT(omapwdt32k_sc->sc_smw.smw_period)
+			  : 0xffffffff);
+
+	/* Wait for the pending writes to go through.
+	 */
+	omapwdt32k_sync();
+
+	/* Resume the watchdog if we had stopped it.
+	 */
+	if (omapwdt32k_sc->sc_armed)
+		omapwdt32k_start();
+}
+
+void
+omapwdt32k_set_timeout(unsigned int period)
+{
+	int s = splhigh();
+
+	if (period != omapwdt32k_sc->sc_smw.smw_period) {
+		omapwdt32k_sc->sc_smw.smw_period = period;
+		omapwdt32k_do_set_timeout();
+	}
+
+	splx(s);
+}
+
+int
+omapwdt32k_enable(int enable)
+{
+	int s;
+	int prev_state = omapwdt32k_sc->sc_armed;
+
+	/* Normalize the int to a boolean so we can compare values directly.
+	 */
+	enable = !!enable;
+
+	s = splhigh();
+
+	if (enable != omapwdt32k_sc->sc_armed) {
+		if (enable) {
+			/* Make sure that the watchdog timeout is up to date.
+			 */
+			omapwdt32k_do_set_timeout();
+			omapwdt32k_start();
+		} else {
+			omapwdt32k_stop();
+		}
+		omapwdt32k_sc->sc_armed = enable;
+	}
+
+	splx(s);
+	return prev_state;
+}
+
+int
+omapwdt32k_setmode(struct sysmon_wdog *smw)
+{
+	struct omapwdt32k_softc *sc = smw->smw_cookie;
+	int error = 0;
+
+	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) {
+		omapwdt32k_enable(0);
+	} else {
+		if (smw->smw_period == WDOG_PERIOD_DEFAULT)
+			sc->sc_smw.smw_period = OMAPWDT32K_DEFAULT_PERIOD;
+		else
+			sc->sc_smw.smw_period = smw->smw_period;
+		omapwdt32k_set_timeout(sc->sc_smw.smw_period);
+		omapwdt32k_enable(1);
+	}
+	return error;
+}
+
+int
+omapwdt32k_tickle(struct sysmon_wdog *smw)
+{
+	int s = splhigh();
+
+	/*
+	 *     To reload the timer counter and reset the prescaler counter
+	 *     values without reaching overflow, a reload command can be
+	 *     executed by accessing the watchdog trigger register (WTGR)
+	 *     using a specific reload sequence.
+	 *
+	 *     The specific reload sequence is performed when the written
+	 *     value on the watchdog trigger register (WTGR) is different
+	 *     from its previous value. In this case, reload is executed in
+	 *     the same way as overflow autoreload, without a reset pulse
+	 *     generation. The timer is loaded with the watchdog load register
+	 *     (WLDR) value and the prescaler counter is reset.
+	 *
+	 * Write a new value into WTGR to reload WCRR (counter register)
+	 * with the value in WLDR (load register), thereby resetting the
+	 * watchdog.
+	 */
+	omapwdt32k_sync();
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh, WTGR,
+			  ~bus_space_read_4(omapwdt32k_sc->sc_iot,
+					    omapwdt32k_sc->sc_ioh, WTGR));
+
+	splx(s);
+	return 0;
+}
+
+void
+omapwdt32k_reboot(void)
+{
+	int s = splhigh();
+
+	omapwdt32k_set_timeout(0);
+	omapwdt32k_start();
+	delay(100);
+	splx(s);
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_wdt.h sys/arch/arm/omap/omap_wdt.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_wdt.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_wdt.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,8 @@
+#ifndef _ARM_OMAP_WDT_H_
+#define _ARM_OMAP_WDT_H_
+
+void omapwdt32k_set_timeout(unsigned int period);
+int omapwdt32k_enable(int enable);
+void omapwdt32k_reboot(void);
+
+#endif /* _ARM_OMAP_WDT_H_ */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_wdtreg.h sys/arch/arm/omap/omap_wdtreg.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_wdtreg.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_wdtreg.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,73 @@
+/*
+ * adapted/extracted from omap_wdt.c
+ */
+
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef  _OMAP_WDTREG_H
+#define  _OMAP_WDTREG_H
+
+#define PTV			1		/* prescaler ratio: clock is divided by 2 */
+#define PRE			1		/* enable divided input clock */
+#define TCLK		32768	/* timer clock period in normal mode */
+
+#define WIDR		0x00	/* watchdog ID reg offset */
+#define WD_REV		0xff	/* WIDR rev field mask */
+
+#define WD_SYSCONFIG		0x10	/* WD System Configuration register */
+#define WD_SYSCONFIG_AUTOIDLE	0x0	/* interface clock autogating */
+
+#define WCLR		0x24	/* watchdog control register */
+#define WCLR_PRE(PRE)           ((PRE & 0x1)<<5)
+#define WCLR_PTV(PTV)           ((PTV & 0x7)<<2)
+
+#define WCRR		0x28	/* watchdog counter register */
+#define WLDR		0x2c	/* watchdog load register */
+#define WTGR		0x30	/* watchdog trigger register */
+
+#define WWPS		0x34	/* watchdog write pending register */
+#define W_PEND_WSPR          (1<<4)
+#define W_PEND_WTGR          (1<<3)
+#define W_PEND_WLDR          (1<<2)
+#define W_PEND_WCRR          (1<<1)
+#define W_PEND_WCLR          (1<<0)
+
+#define WSPR		0x48	/* watchdog start/stop register */
+#define WD_ENABLE_WORD1         0x0000BBBB
+#define WD_ENABLE_WORD2         0x00004444
+#define WD_DISABLE_WORD1        0x0000AAAA
+#define WD_DISABLE_WORD2        0x00005555
+
+
+/* compute number of ticks corresponding to timeout seconds */
+#define WATCHDOG_COUNT(timeout)	(~((timeout) * TCLK / (1<<PTV) -1))
+
+
+#endif	/* _OMAP_WDTREG_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omap_wdtvar.h sys/arch/arm/omap/omap_wdtvar.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omap_wdtvar.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omap_wdtvar.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,52 @@
+/*
+ * adapted/extracted from omap_wdt.c
+ */
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef  _OMAP_WDTVAR_H 
+#define  _OMAP_WDTVAR_H
+ 
+#define	OMAPWDT32K_DEFAULT_PERIOD	4		/* in seconds */
+
+struct omapwdt32k_softc {
+	struct device sc_dev;
+	bus_space_tag_t sc_iot;
+	bus_space_handle_t sc_ioh;
+	struct sysmon_wdog sc_smw;
+	int sc_armed;
+};
+
+extern struct omapwdt32k_softc *omapwdt32k_sc;
+extern int omapwdt_sysconfig;
+
+extern int omapwdt32k_setmode(struct sysmon_wdog *);
+extern int omapwdt32k_tickle(struct sysmon_wdog *);
+
+#endif  /* _OMAP_WDTVAR_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omapmputmrreg.h sys/arch/arm/omap/omapmputmrreg.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omapmputmrreg.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omapmputmrreg.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,45 @@
+#ifndef _OMAPMPUTMRREG_H
+#define _OMAPMPUTMRREG_H
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * OMAP GP Timer Register offsets and values
+ */
+#define MPU_CNTL_TIMER	0x00
+#define  MPU_FREE		(1<<6)
+#define  MPU_CLOCK_ENABLE	(1<<5)
+#define  MPU_PTV_SHIFT		2
+#define  MPU_AR			(1<<1)
+#define  MPU_ST			(1<<0)
+#define MPU_LOAD_TIMER	0x04
+#define MPU_READ_TIMER	0x08
+
+#endif	/* _OMAPMPUTMRREG_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/omapmputmrvar.h sys/arch/arm/omap/omapmputmrvar.h
--- ../../netbsd_40/src/sys/arch/arm/omap/omapmputmrvar.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/omapmputmrvar.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#ifndef _OMAPMPUTMRVAR_h
+#define _OMAPMPUTMRVAR_h
+
+#ifndef STATHZ
+# define STATHZ	64
+#endif
+
+typedef struct timer_factors {
+	uint32_t ptv;
+	uint32_t reload;
+	uint32_t counts_per_usec;
+} timer_factors;
+
+struct omapmputmr_softc {
+	struct device		sc_dev;
+	bus_space_tag_t		sc_iot;
+	bus_space_handle_t	sc_ioh;
+	int			sc_intr;
+};
+
+
+
+extern uint32_t counts_per_usec, counts_per_hz;
+extern uint32_t hardref;
+extern struct timeval hardtime;
+extern struct omapmputmr_softc *clock_sc;
+extern struct omapmputmr_softc *stat_sc;
+extern struct omapmputmr_softc *ref_sc;
+
+extern void calc_timer_factors(int, struct timer_factors *);
+extern int	clockintr(void *);
+extern int	statintr(void *);
+extern void	rtcinit(void);
+
+#endif	/* _OMAPMPUTMRVAR_h */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/arm/omap/tipb_wdt.c sys/arch/arm/omap/tipb_wdt.c
--- ../../netbsd_40/src/sys/arch/arm/omap/tipb_wdt.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/arm/omap/tipb_wdt.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,106 @@
+/*
+ * OMAP watchdog timers
+ */
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/callout.h>
+#include <sys/cdefs.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/wdog.h>
+
+#include <machine/param.h>
+#include <machine/bus.h>
+#include <dev/sysmon/sysmonvar.h>
+
+#include <arm/omap/omap_reg.h>
+#include <arm/omap/omap_tipb.h>
+#include <arm/omap/omap_wdt.h>
+#include <arm/omap/omap_wdtvar.h>
+#include <arm/omap/omap_wdtreg.h>
+
+/*
+ * OMAP 32K watchdog timer
+ */
+
+static int tipbwdt32k_match(struct device *, struct cfdata *, void *);
+static void tipbwdt32k_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(tipbwdt32k, sizeof(struct omapwdt32k_softc),
+    tipbwdt32k_match, tipbwdt32k_attach, NULL, NULL);
+
+static int
+tipbwdt32k_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+	return (1);
+}
+
+static void
+tipbwdt32k_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct omapwdt32k_softc *sc = (void *)self;
+	struct tipb_attach_args *tipb = aux;
+	unsigned int val;
+
+	sc->sc_smw.smw_name = sc->sc_dev.dv_xname;
+	sc->sc_smw.smw_cookie = sc;
+	sc->sc_smw.smw_setmode = omapwdt32k_setmode;
+	sc->sc_smw.smw_tickle = omapwdt32k_tickle;
+	sc->sc_smw.smw_period = OMAPWDT32K_DEFAULT_PERIOD;
+	sc->sc_iot = tipb->tipb_iot;
+
+	if (bus_space_map(sc->sc_iot, tipb->tipb_addr, tipb->tipb_size,
+			  0, &sc->sc_ioh))
+		panic("%s: Cannot map registers", self->dv_xname);
+
+	val = bus_space_read_4(sc->sc_iot, sc->sc_ioh, WIDR);
+	aprint_normal(": rev %d.%d\n", (val & WD_REV) >> 4,
+		      (val & WD_REV & 0xf));
+
+	if (sysmon_wdog_register(&sc->sc_smw) != 0)
+		aprint_error("%s: unable to register with sysmon\n",
+			     sc->sc_dev.dv_xname);
+
+	omapwdt32k_sc = sc;
+
+	/* Turn on autoidle. */
+
+    	omapwdt_sysconfig = 
+	    bus_space_read_4(omapwdt32k_sc->sc_iot,
+			     omapwdt32k_sc->sc_ioh, WD_SYSCONFIG) |
+	    (1 << WD_SYSCONFIG_AUTOIDLE);
+	bus_space_write_4(omapwdt32k_sc->sc_iot, omapwdt32k_sc->sc_ioh,
+			  WD_SYSCONFIG, omapwdt_sysconfig);
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/conf/SDP2430 sys/arch/evbarm/conf/SDP2430
--- ../../netbsd_40/src/sys/arch/evbarm/conf/SDP2430	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/evbarm/conf/SDP2430	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,271 @@
+#
+#	SDP2430 -- TI OMAP 2430 Eval Board Kernel
+#
+
+include	"arch/evbarm/conf/std.sdp2430"
+
+# estimated number of users
+
+maxusers	32
+
+# Standard system options
+
+options 	RTC_OFFSET=0	# hardware clock is this many mins. west of GMT
+#options 	NTP		# NTP phase/frequency locked loop
+
+# CPU options
+
+options 	CPU_ARM1136
+options 	OMAP_2430
+
+# Architecture options
+
+# File systems
+
+file-system	FFS		# UFS
+#file-system	LFS		# log-structured file system
+file-system	MFS		# memory file system
+file-system	NFS		# Network file system
+#file-system 	ADOSFS		# AmigaDOS-compatible file system
+#file-system 	EXT2FS		# second extended file system (linux)
+#file-system	CD9660		# ISO 9660 + Rock Ridge file system
+file-system	MSDOSFS		# MS-DOS file system
+#file-system	FDESC		# /dev/fd
+#file-system	KERNFS		# /kern
+#file-system	NULLFS		# loopback file system
+#file-system	PORTAL		# portal filesystem (still experimental)
+#file-system	PROCFS		# /proc
+#file-system	UMAPFS		# NULLFS + uid and gid remapping
+#file-system	UNION		# union file system
+file-system	TMPFS		# memory file system
+file-system	PTYFS		# /dev/pts/N support
+
+# File system options
+#options 	QUOTA		# UFS quotas
+#options 	FFS_EI		# FFS Endian Independant support
+#options 	NFSSERVER
+#options 	SOFTDEP
+#options 	FFS_NO_SNAPSHOT	# No FFS snapshot support
+
+# Networking options
+
+#options 	GATEWAY		# packet forwarding
+options 	INET		# IP + ICMP + TCP + UDP
+options 	INET6		# IPV6
+#options 	IPSEC		# IP security
+#options 	IPSEC_ESP	# IP security (encryption part; define w/ IPSEC)
+#options 	IPSEC_NAT_T	# IPsec NAT traversal (NAT-T)
+#options 	IPSEC_DEBUG	# debug for IP security
+#options 	MROUTING	# IP multicast routing
+#options 	PIM		# Protocol Independent Multicast
+#options 	NS		# XNS
+#options 	NSIP		# XNS tunneling over IP
+#options 	ISO,TPIP	# OSI
+#options 	EON		# OSI tunneling over IP
+#options 	CCITT,LLC,HDLC	# X.25
+#options 	NETATALK	# AppleTalk networking
+#options 	PFIL_HOOKS	# pfil(9) packet filter hooks
+#options 	PPP_BSDCOMP	# BSD-Compress compression support for PPP
+#options 	PPP_DEFLATE	# Deflate compression support for PPP
+#options 	PPP_FILTER	# Active filter support for PPP (requires bpf)
+#options 	TCP_DEBUG	# Record last TCP_NDEBUG packets with SO_DEBUG
+
+options 	NFS_BOOT_BOOTP
+options 	NFS_BOOT_DHCP
+
+options		NFS_BOOT_RWSIZE=1024
+
+# Compatibility options
+
+#options 	COMPAT_43	# 4.3BSD compatibility.
+options 	COMPAT_30	# NetBSD 3.0 compatibility.
+#options 	COMPAT_20	# NetBSD 2.0 compatibility.
+#options 	COMPAT_16	# NetBSD 1.6 compatibility.
+#options 	COMPAT_15	# NetBSD 1.5 compatibility.
+#options 	COMPAT_14	# NetBSD 1.4 compatibility.
+#options 	COMPAT_13	# NetBSD 1.3 compatibility.
+#options 	COMPAT_12	# NetBSD 1.2 compatibility.
+#options 	COMPAT_11	# NetBSD 1.1 compatibility.
+#options 	COMPAT_10	# NetBSD 1.0 compatibility.
+#options 	COMPAT_09	# NetBSD 0.9 compatibility.
+#options 	TCP_COMPAT_42	# 4.2BSD TCP/IP bug compat. Not recommended.
+#options		COMPAT_BSDPTY	# /dev/[pt]ty?? ptys.
+
+# Shared memory options
+
+options 	SYSVMSG		# System V-like message queues
+options 	SYSVSEM		# System V-like semaphores
+#options 	SEMMNI=10	# number of semaphore identifiers
+#options 	SEMMNS=60	# number of semaphores in system
+#options 	SEMUME=10	# max number of undo entries per process
+#options 	SEMMNU=30	# number of undo structures in system
+options 	SYSVSHM		# System V-like memory sharing
+#options 	SHMMAXPGS=1024	# 1024 pages is the default
+
+# Device options
+
+#options 	MEMORY_DISK_HOOKS	# boottime setup of ramdisk
+#options 	MEMORY_DISK_ROOT_SIZE=8192	# Size in blocks
+#options 	MEMORY_DISK_DYNAMIC
+#options 	MINIROOTSIZE=1000	# Size in blocks
+#options 	MEMORY_DISK_IS_ROOT	# use memory disk as root
+
+# Miscellaneous kernel options
+options 	KTRACE		# system call tracing, a la ktrace(1)
+#options 	LKM		# loadable kernel modules
+#options 	KMEMSTATS	# kernel memory statistics
+#options 	SCSIVERBOSE	# Verbose SCSI errors
+#options 	MIIVERBOSE	# Verbose MII autoconfuration messages
+#options 	DDB_KEYCODE=0x40
+#options 	USERCONF	# userconf(4) support
+#options	PIPE_SOCKETPAIR	# smaller, but slower pipe(2)
+
+# Development and Debugging options
+
+#options 	PERFCTRS	# performance counters
+options 	DIAGNOSTIC	# internally consistency checks
+options 	DEBUG
+#options 	PMAP_DEBUG	# Enable pmap_debug_level code
+#options 	IPKDB		# remote kernel debugging
+options 	VERBOSE_INIT_ARM # verbose bootstraping messages
+options 	DDB		# in-kernel debugger
+options		DDB_ONPANIC=1
+options 	DDB_HISTORY_SIZE=100	# Enable history editing in DDB
+#options 	KGDB
+makeoptions	DEBUG="-g"	# compile full symbol table
+options 	SYMTAB_SPACE=300000
+
+## USB Debugging options
+options USB_DEBUG
+options OHCI_DEBUG 
+options UHUB_DEBUG 
+
+
+# Valid options for BOOT_ARGS:
+#  single		Boot to single user only
+#  kdb			Give control to kernel debugger
+#  ask			Ask for file name to reboot from
+#  pmapdebug=<n>	If PMAP_DEBUG, set pmap_debug_level to <n>
+#  memorydisk=<n>	Set memorydisk size to <n> KB
+#  quiet		Show aprint_naive output
+#  verbose		Show aprint_normal and aprint_verbose output
+options		BOOT_ARGS="\"\""
+
+#options	SPL_STATS	# SPL time stats
+#options	DISINT_STATS	# Interrupt disable stats
+
+config		netbsd		root on ? type ?
+##config		netbsd-sm0	root on sm0 type nfs
+
+# The main bus device
+mainbus0	at root
+
+# The boot cpu
+cpu0		at mainbus?
+
+# Specify the memory size in megabytes.
+options		MEMSIZE=128
+
+# L3 Interconnect
+L3i0		at mainbus?
+
+# OBIO
+obio0		at mainbus? base 0x48000000 size 0x1000000	# L4 CORE 
+obio1		at mainbus? base 0x49000000 size 0x0800000	# L4 WAKEUP
+
+# General Purpose Memory Controller
+gpmc0		at mainbus? base 0x6e000000
+
+
+# # I2C Controller
+# omapi2c0	at tipb? addr 0xfffb3800 intr 36 mult 4
+# iic*		at omapi2c?
+# # omap's own i2c address
+# options		OMAP_I2C_ADDRESS=0xe
+# # i2c bus clock low and high times in ns
+# options		I2C_LOW_TIME_nSEC=1500
+# options		I2C_HIGH_TIME_nSEC=1000
+
+# On-board 16550 UARTs
+com0		at obio? addr 0x4806a000 intr -1 mult 4	# UART1
+##com1		at obio? addr 0x4806c000 intr 73 mult 4	# UART2
+##com2		at obio? addr 0x4806e000 intr 74 mult 4	# UART3 (IR)
+options CONSADDR=0x4806a000, CONSPEED=115200
+##options KGDB_DEVADDR=0x4806e000, KGDB_DEVRATE=115200	# UART3
+
+# Interrupt controller
+##omap2430intc0	at obio?	# Interrupt controller
+
+# Operating System Timer
+omap2430mputmr0	at obio? addr 0x4802a000 intr 38	# GP Timer 2
+# Statistics Timer
+omap2430mputmr1	at obio? addr 0x48078000 intr 39	# GP Timer 3
+# Microtime Reference Timer
+omap2430mputmr2	at obio? addr 0x4807A000 intr 40	# GP Timer 4
+options OMAP_MPU_TIMER_CLOCK_FREQ=12000000
+
+# Real Time Clock
+##omaprtc0	at tipb? addr 0xfffb4800 intr 58	# alarm interrupt
+
+# On-board GPIO controllers
+##omapgpio0	at tipb? addr 0xfffbe400 intr 14
+##omapgpio1	at tipb? addr 0xfffbec00 intr 72
+##omapgpio2	at tipb? addr 0xfffbb400 intr 73
+##omapgpio3	at tipb? addr 0xfffbbc00 intr 80
+
+##omapiobus0	at tipb?
+##gpio0		at omapiobus0
+
+# On-board SPI controller
+
+##omapspi0		at tipb? addr 0xfffb0c00 intr 81
+##spi*	at omapspi?
+
+# Watchdog timers
+omapwdt32k*	at obio? addr 0x48026000 size 2048	# WDT4
+#omapwdt32k*	at obio? addr 0x49014000 size 2048	# WDT1
+#omapwdt32k*	at obio? addr 0x49016000 size 2048	# WDT2
+
+# On-board SMSC LAN91C96 Ethernet Controller
+sm0		at gpmc? addr 0x08000300 intr 245
+
+# On-board USB
+##ohci*		at obio? addr 0x4805e000 size 0x1000 intr 75
+##usb*		at ohci?
+##uhub*		at usb?
+##umass*		at uhub? port ? configuration ? interface ?
+##wd*		at umass?
+
+
+# OCP
+##ocp0		at mainbus?
+
+# Hardware clocking and power management
+
+##omapulpd0		at tipb? addr 0xfffe0800 size 2048
+##omapmpuclkm0	at tipb? addr 0xfffece00 size 256
+##omapdpll1		at tipb? addr 0xfffecf00 size 256
+##omapconfig0		at tipb? addr 0xfffe1000 size 2048
+
+options     HWCLOCK
+options     HWCLOCK_MACHINE="<arch/arm/omap/hwclock_omap1.h>"
+options		OMAP_CK_REF_SPEED=12000000
+
+# Pseudo-Devices
+
+# disk/mass storage pseudo-devices
+pseudo-device	md		1	# memory disk device (ramdisk)
+#pseudo-device	vnd			# disk-like interface to files
+#pseudo-device	fss		4	# file system snapshot device
+
+# network pseudo-devices
+pseudo-device	bpfilter		# Berkeley packet filter
+pseudo-device	loop			# network loopback
+#pseudo-device	kttcp			# network loopback
+
+# miscellaneous pseudo-devices
+pseudo-device	pty			# pseudo-terminals
+pseudo-device	rnd			# /dev/random and in-kernel generator
+#options	RND_COM
+#pseudo-device	clockctl		# user control of clock subsystem
+pseudo-device	ksyms			# /dev/ksyms
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/conf/files.sdp2430 sys/arch/evbarm/conf/files.sdp2430
--- ../../netbsd_40/src/sys/arch/evbarm/conf/files.sdp2430	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/evbarm/conf/files.sdp2430	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,22 @@
+#	$NetBSD: files.osk5912,v 1.1.6.1 2007/02/24 19:03:14 snj Exp $
+#
+# TI OSK5912 evaluation board configuration info
+#
+
+file	arch/evbarm/sdp2430/sdp2430_machdep.c
+
+# Kernel boot arguments
+defparam opt_machdep.h				BOOT_ARGS
+
+# CPU support and integrated peripherals
+include "arch/arm/omap/files.omap"
+
+# SMSC LAN91C96
+attach	sm at gpmc with sm_gpmc
+file	arch/evbarm/sdp2430/if_sm_gpmc.c	sm_gpmc
+
+# NS16550 compatible serial ports
+attach com at obio with obiouart
+file	arch/arm/omap/obio_com.c		obiouart
+##defparam opt_com.h				CONSADDR CONSPEED CONMODE
+
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/conf/ldscript.evbarm sys/arch/evbarm/conf/ldscript.evbarm
--- ../../netbsd_40/src/sys/arch/evbarm/conf/ldscript.evbarm	2003-05-22 17:57:27.000000000 -0700
+++ sys/arch/evbarm/conf/ldscript.evbarm	2007-09-25 10:55:22.000000000 -0700
@@ -26,9 +26,9 @@
   PROVIDE (__etext = .);
   PROVIDE (_etext = .);
   PROVIDE (etext = .);
-  /* Adjust the address for the data segment to start on the next page
-     boundary.  */
-  . = ALIGN(0x8000);
+  /* Adjust the address for the data segment to start on the next
+     (64KB) Large page boundary.  */
+  . = ALIGN(0x10000);
   .data    :
   AT (LOADADDR(.text) + (ADDR(.data) - ADDR(.text)))
   {
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/conf/mk.sdp2430 sys/arch/evbarm/conf/mk.sdp2430
--- ../../netbsd_40/src/sys/arch/evbarm/conf/mk.sdp2430	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/evbarm/conf/mk.sdp2430	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,14 @@
+#	$NetBSD: mk.osk5912,v 1.1.6.1 2007/02/24 19:03:13 snj Exp $
+COPTS+=-mcpu=arm1136jf-s
+
+SYSTEM_FIRST_OBJ=	sdp2430_start.o
+SYSTEM_FIRST_SFILE=	${THISARM}/sdp2430/sdp2430_start.S
+
+KERNEL_BASE_PHYS=0x80300000
+KERNEL_BASE_VIRT=0xc0000000
+
+SYSTEM_LD_TAIL_EXTRA+=; \
+	echo ${OBJCOPY} -S -O binary $@ $@.bin; \
+	${OBJCOPY} -S -O binary $@ $@.bin; \
+
+EXTRA_KERNELS+= ${KERNELS:@.KERNEL.@${.KERNEL.}.bin@}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/conf/std.sdp2430 sys/arch/evbarm/conf/std.sdp2430
--- ../../netbsd_40/src/sys/arch/evbarm/conf/std.sdp2430	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/evbarm/conf/std.sdp2430	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,26 @@
+#	$NetBSD: std.osk5912,v 1.1.6.1 2007/02/24 19:03:13 snj Exp $
+#
+# standard NetBSD/evbarm for SDP2430 options
+
+machine	evbarm arm
+include		"conf/std"	# MI standard options
+
+# Pull in SDP2430 config definitions.
+include "arch/evbarm/conf/files.sdp2430"
+
+options 	EXEC_ELF32
+options 	EXEC_SCRIPT
+
+# To support easy transit to ../arch/arm/arm32
+options 	ARM32
+options 	ARM1136_PMC
+
+makeoptions	LOADADDRESS="0xc0000000"
+makeoptions	BOARDTYPE="sdp2430"
+makeoptions	BOARDMKFRAG="${THISARM}/conf/mk.sdp2430"
+makeoptions	CPPFLAGS+="-I$S/../../../include"
+
+##makeoptions	CPPFLAGS+="-I$S/../../../target/netbsd/m2/include"
+
+options 	ARM_INTR_IMPL="<arch/arm/omap/omap2430_intr.h>"
+options		ARM_GENERIC_TODR
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/include/types.h sys/arch/evbarm/include/types.h
--- ../../netbsd_40/src/sys/arch/evbarm/include/types.h	2007-03-04 04:15:39.000000000 -0800
+++ sys/arch/evbarm/include/types.h	2007-09-25 10:55:22.000000000 -0700
@@ -10,6 +10,8 @@
 #endif
 #define	__HAVE_DEVICE_REGISTER

-#define	__HAVE_GENERIC_TODR
+#ifdef ARM_GENERIC_TODR
+# define	__HAVE_GENERIC_TODR
+#endif

 #endif
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/sdp2430/if_sm_gpmc.c sys/arch/evbarm/sdp2430/if_sm_gpmc.c
--- ../../netbsd_40/src/sys/arch/evbarm/sdp2430/if_sm_gpmc.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/evbarm/sdp2430/if_sm_gpmc.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,198 @@
+/* adapted from: */
+/*	NetBSD: if_sm_emifs.c,v 1.1.6.1 2007/02/24 19:03:14 snj Exp	*/
+
+/*
+ * OSK5912 SMC91Cxx wrapper, based on sys/arch/evbarm/viper/if_sm_pxaip.c
+ *
+ * Copyright (c) 2005 Antti Kantee.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by The NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: if_sm_emifs.c,v 1.1.6.1 2007/02/24 19:03:14 snj Exp $");
+
+#include "locators.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+
+#include <machine/intr.h>
+#include <machine/bus.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/ic/smc91cxxreg.h>
+#include <dev/ic/smc91cxxvar.h>
+
+#include <arch/arm/omap/omap2430gpmcvar.h>
+#include <arch/arm/omap/omap_gpio.h>
+
+static int	sm_gpmc_match(struct device *, struct cfdata *, void *);
+static void	sm_gpmc_attach(struct device *, struct device *, void *);
+
+struct sm_gpmc_softc {
+	struct smc91cxx_softc sc_sm;
+	struct evcnt sc_incomplete_ev[8];
+	struct evcnt sc_spurious_ev;
+	void *ih;
+};
+
+CFATTACH_DECL(sm_gpmc, sizeof(struct sm_gpmc_softc), sm_gpmc_match,
+    sm_gpmc_attach, NULL, NULL);
+
+static int
+sm_gpmc_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	struct gpmc_attach_args *gpmc = aux;
+
+	if (gpmc->gpmc_addr == GPMCCF_ADDR_DEFAULT)
+		panic("sm must have addr specified in config.");
+
+	if (gpmc->gpmc_intr == GPMCCF_INTR_DEFAULT)
+		panic("sm must have intr specified in config.");
+
+	/* Trust the config file. */
+	return (1);
+}
+
+static int
+sm_gpmc_intr(void *arg)
+{
+	struct sm_gpmc_softc * const gpmcsc = (struct sm_gpmc_softc *)arg;
+	struct smc91cxx_softc * const sc = &gpmcsc->sc_sm;
+
+	if (bus_space_read_2(sc->sc_bst, sc->sc_bsh, 0x1a)) {
+		int rv = smc91cxx_intr(sc);
+		if (bus_space_read_2(sc->sc_bst, sc->sc_bsh, 0x1a)) {
+			uint32_t v;
+			SMC_SELECT_BANK(sc, 2);
+
+			/*
+			 * Obtain the current interrupt status and mask.
+			 */
+			v = bus_space_read_2(sc->sc_bst, sc->sc_bsh, INTR_STAT_REG_B);
+
+			v = (v >> 8) & v & 0xff;
+			if (v & 1)  gpmcsc->sc_incomplete_ev[0].ev_count++;
+			if (v & 2)  gpmcsc->sc_incomplete_ev[1].ev_count++;
+			if (v & 4)  gpmcsc->sc_incomplete_ev[2].ev_count++;
+			if (v & 8)  gpmcsc->sc_incomplete_ev[3].ev_count++;
+			if (v & 16)  gpmcsc->sc_incomplete_ev[4].ev_count++;
+			if (v & 32)  gpmcsc->sc_incomplete_ev[5].ev_count++;
+			if (v & 64)  gpmcsc->sc_incomplete_ev[6].ev_count++;
+			if (v & 128) gpmcsc->sc_incomplete_ev[7].ev_count++;
+		}
+		return rv;
+	} else {
+		gpmcsc->sc_spurious_ev.ev_count++;
+		return 0;
+	}
+}
+
+static void
+sm_gpmc_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct sm_gpmc_softc *gpmcsc = (struct sm_gpmc_softc *)self;
+	struct smc91cxx_softc *sc = &gpmcsc->sc_sm;
+	struct gpmc_attach_args *gpmc = aux;
+	bus_space_tag_t bst;
+	bus_space_handle_t bsh;
+	unsigned int count = 0;
+
+	bst = gpmc->gpmc_iot;
+
+	/* map i/o space */
+	if (bus_space_map(bst, gpmc->gpmc_addr, SMC_IOSIZE + 16, 0, &bsh) != 0) {
+		aprint_error(": sm_gpmc_attach: can't map i/o space");
+		return;
+	}
+
+	aprint_normal("\n");
+
+	/* fill in master sc */
+	sc->sc_bst = bst;
+	sc->sc_bsh = bsh;
+
+	/* register the interrupt handler */
+	gpmcsc->ih = omap_intr_establish(gpmc->gpmc_intr, IPL_NET,
+	    sc->sc_dev.dv_xname, sm_gpmc_intr, gpmcsc);
+
+	if (gpmcsc->ih == NULL) {
+		aprint_error(": couldn't establish interrupt\n");
+		bus_space_unmap(bst, bsh, SMC_IOSIZE + 16);
+		return;
+	}
+
+	evcnt_attach_dynamic(&gpmcsc->sc_spurious_ev, EVCNT_TYPE_INTR, NULL,
+	    self->dv_xname, "spurious intr");
+	evcnt_attach_dynamic(&gpmcsc->sc_incomplete_ev[0], EVCNT_TYPE_INTR, NULL,
+	    self->dv_xname, "incomplete rx intr");
+	evcnt_attach_dynamic(&gpmcsc->sc_incomplete_ev[1], EVCNT_TYPE_INTR, NULL,
+	    self->dv_xname, "incomplete tx intr");
+	evcnt_attach_dynamic(&gpmcsc->sc_incomplete_ev[2], EVCNT_TYPE_INTR, NULL,
+	    self->dv_xname, "incomplete tx empty intr");
+	evcnt_attach_dynamic(&gpmcsc->sc_incomplete_ev[3], EVCNT_TYPE_INTR, NULL,
+	    self->dv_xname, "incomplete alloc intr");
+	evcnt_attach_dynamic(&gpmcsc->sc_incomplete_ev[4], EVCNT_TYPE_INTR, NULL,
+	    self->dv_xname, "incomplete rx ovrn intr");
+	evcnt_attach_dynamic(&gpmcsc->sc_incomplete_ev[5], EVCNT_TYPE_INTR, NULL,
+	    self->dv_xname, "incomplete eph intr");
+	evcnt_attach_dynamic(&gpmcsc->sc_incomplete_ev[6], EVCNT_TYPE_INTR, NULL,
+	    self->dv_xname, "incomplete early rx intr");
+	evcnt_attach_dynamic(&gpmcsc->sc_incomplete_ev[7], EVCNT_TYPE_INTR, NULL,
+	    self->dv_xname, "incomplete md intr");
+
+	/*
+	 * Reset the SMC
+	 */
+	bus_space_write_2(bst, bsh, 0x1c, 1);
+	delay(2);
+	bus_space_write_2(bst, bsh, 0x1c, 6);
+
+	/*
+	 * Wait for the reset to complete.
+	 */
+	while (bus_space_read_2(bst, bsh, 0x1a) & 1) {
+		if (++count > 1000) {
+			aprint_error(": didn't come out of reset\n");
+			return;
+		}
+	}
+
+	/* Perform generic attach. */
+	sc->sc_flags |= SMC_FLAGS_ENABLED;
+	smc91cxx_attach(sc, NULL);
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/sdp2430/sdp2430.h sys/arch/evbarm/sdp2430/sdp2430.h
--- ../../netbsd_40/src/sys/arch/evbarm/sdp2430/sdp2430.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/evbarm/sdp2430/sdp2430.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,54 @@
+/*	$NetBSD$	*/
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _EVBARM_SDP2430_REG_H
+#define _EVBARM_SDP2430_REG_H
+
+#include <arm/omap/omap2430reg.h>
+
+/*
+ * Kernel VM space: 192MB at KERNEL_VM_BASE
+ */
+#define	KERNEL_VM_BASE		(KERNEL_BASE + 0x01000000)
+#define KERNEL_VM_SIZE		0x0C000000
+
+/*
+ * We devmap IO starting at KERNEL_VM_BASE + KERNEL_VM_SIZE
+ */
+#define	OMAP2430_KERNEL_IO_VBASE	(KERNEL_VM_BASE + KERNEL_VM_SIZE)
+#define	OMAP2430_L4_CORE_VBASE		OMAP2430_KERNEL_IO_VBASE
+#define	OMAP2430_L4_WAKEUP_VBASE	(OMAP2430_L4_CORE_VBASE   + OMAP2430_L4_CORE_SIZE)
+#define	OMAP2430_KERNEL_IO_VEND		(OMAP2430_L4_WAKEUP_VBASE + OMAP2430_L4_WAKEUP_SIZE)
+
+#define CONSADDR_VA	((CONSADDR - OMAP2430_L4_CORE_BASE) + OMAP2430_L4_CORE_VBASE)
+
+
+#endif /* _EVBARM_SDP2430_REG_H */
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/sdp2430/sdp2430_machdep.c sys/arch/evbarm/sdp2430/sdp2430_machdep.c
--- ../../netbsd_40/src/sys/arch/evbarm/sdp2430/sdp2430_machdep.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/evbarm/sdp2430/sdp2430_machdep.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,928 @@
+/*	$NetBSD: sdp2430_machdep.c,v 1.1.6.1 2007/02/24 19:03:14 snj Exp $ */
+
+/*
+ * Machine dependent functions for kernel setup for TI SDP2430 board.
+ * Based on lubbock_machdep.c which in turn was based on iq80310_machhdep.c
+ *
+ * Copyright (c) 2002, 2003, 2005  Genetec Corporation.  All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of Genetec Corporation may not be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed for the NetBSD Project by
+ *	Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ *    or promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright (c) 1997,1998 Mark Brinicombe.
+ * Copyright (c) 1997,1998 Causality Limited.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Mark Brinicombe
+ *	for the NetBSD Project.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: sdp2430_machdep.c,v 1.1.6.1 2007/02/24 19:03:14 snj Exp $");
+
+#include "opt_machdep.h"
+#include "opt_ddb.h"
+#include "opt_kgdb.h"
+#include "opt_ipkdb.h"
+#include "opt_md.h"
+#include "opt_com.h"
+#include "md.h"
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/exec.h>
+#include <sys/proc.h>
+#include <sys/msgbuf.h>
+#include <sys/reboot.h>
+#include <sys/termios.h>
+#include <sys/ksyms.h>
+
+#include <uvm/uvm_extern.h>
+
+#include <sys/conf.h>
+#include <dev/cons.h>
+#include <dev/md.h>
+
+#include <machine/db_machdep.h>
+#include <ddb/db_sym.h>
+#include <ddb/db_extern.h>
+#ifdef KGDB
+#include <sys/kgdb.h>
+#endif
+
+#include <machine/bootconfig.h>
+#include <machine/bus.h>
+#include <machine/cpu.h>
+#include <machine/frame.h>
+#include <arm/undefined.h>
+
+#include <arm/arm32/machdep.h>
+#include <arm/arm32/arm1136_pmc.h>
+
+#include <arm/omap/omap_reg.h>
+#include <arm/omap/omap_tipb.h>
+#include <arm/omap/omap_com.h>
+#include <arm/omap/omap_wdt.h>
+
+#include <arm/omap/omap_var.h>
+
+#include <evbarm/sdp2430/sdp2430.h>
+
+#include "omapwdt32k.h"
+
+/*
+ * Address to call from cpu_reset() to reset the machine.
+ * This is machine architecture dependant as it varies depending
+ * on where the ROM appears when you turn the MMU off.
+ */
+
+u_int cpu_reset_address = 0;
+
+/* Define various stack sizes in pages */
+#define IRQ_STACK_SIZE	1
+#define ABT_STACK_SIZE	1
+#ifdef IPKDB
+#define UND_STACK_SIZE	2
+#else
+#define UND_STACK_SIZE	1
+#endif
+
+BootConfig bootconfig;		/* Boot config storage */
+char *boot_args = NULL;
+char *boot_file = NULL;
+
+/* Physical address of the beginning of SDRAM. */
+paddr_t physical_start;
+/* Physical address of the first byte after the end of SDRAM. */
+paddr_t physical_end;
+/* Number of pages of memory. */
+int physmem = 0;
+
+/* Same things, but for the free (unused by the kernel) memory. */
+static paddr_t physical_freestart, physical_freeend;
+static u_int free_pages;
+
+/* Physical and virtual addresses for some global pages */
+pv_addr_t systempage;		/* exception vectors */
+pv_addr_t irqstack;
+pv_addr_t undstack;
+pv_addr_t abtstack;
+pv_addr_t kernelstack;	/* stack for SVC mode */
+static pv_addr_t kernel_l1pt;	/* First level page table. */
+
+/* Physical address of the message buffer. */
+paddr_t msgbufphys;
+
+extern u_int data_abort_handler_address;
+extern u_int prefetch_abort_handler_address;
+extern u_int undefined_handler_address;
+extern char KERNEL_BASE_phys[];
+extern char etext[], __data_start[], _edata[], __bss_start[], __bss_end__[];
+extern char _end[];
+
+#define KERNEL_PT_SYS		0	/* Page table for mapping proc0 zero page */
+#define KERNEL_PT_KERNEL	1	/* Page table for mapping kernel */
+#define	KERNEL_PT_KERNEL_NUM	4
+#define KERNEL_PT_VMDATA	(KERNEL_PT_KERNEL+KERNEL_PT_KERNEL_NUM)
+				        /* Page tables for mapping kernel VM */
+#define	KERNEL_PT_VMDATA_NUM	4	/* start with 16MB of KVM */
+#define NUM_KERNEL_PTS		(KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM)
+
+pv_addr_t kernel_pt_table[NUM_KERNEL_PTS];
+
+extern struct user *proc0paddr;
+
+/*
+ * Macros to translate between physical and virtual for a subset of the
+ * kernel address space.  *Not* for general use.
+ */
+#define KERNEL_BASE_PHYS ((paddr_t)&KERNEL_BASE_phys)
+#define KERN_VTOPHYS(va) \
+	((paddr_t)((vaddr_t)va - KERNEL_BASE + KERNEL_BASE_PHYS))
+#define KERN_PHYSTOV(pa) \
+	((vaddr_t)((paddr_t)pa - KERNEL_BASE_PHYS + KERNEL_BASE))
+
+/* Prototypes */
+
+void omap2430_intr_init(bus_space_tag_t);
+void consinit(void);
+#ifdef KGDB
+static void kgdb_port_init(void);
+#endif
+
+static void setup_real_page_tables(void);
+static void init_clocks(void);
+
+bs_protos(bs_notimpl);
+
+#include "com.h"
+#if NCOM > 0
+#include <dev/ic/comreg.h>
+#include <dev/ic/comvar.h>
+#endif
+
+/*
+ * void cpu_reboot(int howto, char *bootstr)
+ *
+ * Reboots the system
+ *
+ * Deal with any syncing, unmounting, dumping and shutdown hooks,
+ * then reset the CPU.
+ */
+void
+cpu_reboot(int howto, char *bootstr)
+{
+#ifdef DIAGNOSTIC
+	/* info */
+	printf("boot: howto=%08x curproc=%p\n", howto, curproc);
+#endif
+
+	/*
+	 * If we are still cold then hit the air brakes
+	 * and crash to earth fast
+	 */
+	if (cold) {
+		doshutdownhooks();
+		printf("The operating system has halted.\n");
+		printf("Please press any key to reboot.\n\n");
+		cngetc();
+		printf("rebooting...\n");
+#if NOMAPWDT32K > 0
+		omapwdt32k_reboot();
+#endif
+		cpu_reset();
+		/*NOTREACHED*/
+	}
+
+	/* Disable console buffering */
+/*	cnpollc(1);*/
+
+	/*
+	 * If RB_NOSYNC was not specified sync the discs.
+	 * Note: Unless cold is set to 1 here, syslogd will die during the
+	 * unmount.  It looks like syslogd is getting woken up only to find
+	 * that it cannot page part of the binary in as the filesystem has
+	 * been unmounted.
+	 */
+	if (!(howto & RB_NOSYNC))
+		bootsync();
+
+	/* Say NO to interrupts */
+	splhigh();
+
+	/* Do a dump if requested. */
+	if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP)
+		dumpsys();
+
+	/* Run any shutdown hooks */
+	doshutdownhooks();
+
+	/* Make sure IRQ's are disabled */
+	IRQdisable;
+
+	if (howto & RB_HALT) {
+		printf("The operating system has halted.\n");
+		printf("Please press any key to reboot.\n\n");
+		cngetc();
+	}
+
+	printf("rebooting...\n");
+#if NOMAPWDT32K > 0
+	omapwdt32k_reboot();
+#endif
+	cpu_reset();
+	/*NOTREACHED*/
+}
+
+/*
+ * Static device mappings. These peripheral registers are mapped at
+ * fixed virtual addresses very early in initarm() so that we can use
+ * them while booting the kernel, and stay at the same address
+ * throughout whole kernel's life time.
+ *
+ * We use this table twice; once with bootstrap page table, and once
+ * with kernel's page table which we build up in initarm().
+ *
+ * Since we map these registers into the bootstrap page table using
+ * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map
+ * registers segment-aligned and segment-rounded in order to avoid
+ * using the 2nd page tables.
+ */
+
+#define	_A(a)	((a) & ~L1_S_OFFSET)
+#define	_S(s)	(((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1))
+
+static const struct pmap_devmap devmap[] = {
+	{
+		/*
+		 * Map the first 1MB of L4 Core area
+		 * this gets us the console UART, GP timers, interrupt
+		 * controller and GPIO5.
+		 */
+		.pd_va = _A(OMAP2430_L4_CORE_VBASE),
+		.pd_pa = _A(OMAP2430_L4_CORE_BASE),
+		.pd_size = _S(1 << 20),
+		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,
+		.pd_cache = PTE_NOCACHE
+	},
+	{
+		/*
+		 * Map the first 1MB of L4 Wakeup area
+		 * this gets us GPIO[1-4] and Clock Management regs
+		 */
+		.pd_va = _A(OMAP2430_L4_WAKEUP_VBASE),
+		.pd_pa = _A(OMAP2430_L4_WAKEUP_BASE),
+		.pd_size = _S(1 << 20),
+		.pd_prot = VM_PROT_READ|VM_PROT_WRITE,
+		.pd_cache = PTE_NOCACHE
+	},
+	{0}
+};
+
+#undef	_A
+#undef	_S
+
+#ifdef DDB
+static void sdp_db_trap(int where)
+{
+#if  NOMAPWDT32K > 0
+	static int oldwatchdogstate;
+
+	if (where) {
+		oldwatchdogstate = omapwdt32k_enable(0);
+	} else {
+		omapwdt32k_enable(oldwatchdogstate);
+	}
+#endif
+}
+#endif
+
+void sdp_putchar(char c);
+void
+sdp_putchar(char c)
+{
+	unsigned char *com0addr = (char *)CONSADDR_VA;
+	int timo = 150000;
+
+	while ((com0addr[5 * 4] & 0x20) == 0)
+		if (--timo == 0)
+			break;
+
+	com0addr[0] = c;
+
+	while ((com0addr[5 * 4] & 0x20) == 0)
+		if (--timo == 0)
+			break;
+}
+
+/*
+ * u_int initarm(...)
+ *
+ * Initial entry point on startup. This gets called before main() is
+ * entered.
+ * It should be responsible for setting up everything that must be
+ * in place when main is called.
+ * This includes
+ *   Taking a copy of the boot configuration structure.
+ *   Initialising the physical console so characters can be printed.
+ *   Setting up page tables for the kernel
+ *   Relocating the kernel to the bottom of physical memory
+ */
+u_int
+initarm(void *arg)
+{
+	/*
+	 * When we enter here, we are using a temporary first level
+	 * translation table with section entries in it to cover the OBIO
+	 * peripherals and SDRAM.  The temporary first level translation table
+	 * is at the end of SDRAM.
+	 */
+
+	/* Heads up ... Setup the CPU / MMU / TLB functions. */
+	if (set_cpufuncs())
+		panic("cpu not recognized!");
+
+	init_clocks();
+
+	/* The console is going to try to map things.  Give pmap a devmap. */
+	pmap_devmap_register(devmap);
+	consinit();
+	omap2430_intr_init(&omap_bs_tag);
+#ifdef KGDB
+	kgdb_port_init();
+#endif
+
+#ifdef VERBOSE_INIT_ARM
+	/* Talk to the user */
+	printf("\nNetBSD/evbarm (SDP2430) booting ...\n");
+#endif
+
+#ifdef BOOT_ARGS
+	char mi_bootargs[] = BOOT_ARGS;
+	parse_mi_bootargs(mi_bootargs);
+#endif
+
+#ifdef VERBOSE_INIT_ARM
+	printf("initarm: Configuring system ...\n");
+#endif
+
+	/*
+	 * Set up the variables that define the availability of physical
+	 * memory.
+	 */
+	physical_start = KERNEL_BASE_PHYS;
+	physical_end = physical_start + (MEMSIZE_BYTES - 0x00300000);
+	physmem = (MEMSIZE_BYTES - 0x00300000) / PAGE_SIZE;
+
+	/* Fake bootconfig structure for the benefit of pmap.c. */
+	bootconfig.dramblocks = 1;
+	bootconfig.dram[0].address = physical_start;
+	bootconfig.dram[0].pages = physmem;
+
+	/*
+	 * Our kernel is at the beginning of memory, so set our free space to
+	 * all the memory after the kernel.
+	 */
+	physical_freestart = KERN_VTOPHYS(round_page((vaddr_t) _end));
+	physical_freeend = physical_end;
+	free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE;
+
+	/*
+	 * This is going to do all the hard work of setting up the first and
+	 * and second level page tables.  Pages of memory will be allocated
+	 * and mapped for other structures that are required for system
+	 * operation.  When it returns, physical_freestart and free_pages will
+	 * have been updated to reflect the allocations that were made.  In
+	 * addition, kernel_l1pt, kernel_pt_table[], systempage, irqstack,
+	 * abtstack, undstack, kernelstack, msgbufphys will be set to point to
+	 * the memory that was allocated for them.
+	 */
+	setup_real_page_tables();
+
+	/*
+	 * Moved from cpu_startup() as data_abort_handler() references
+	 * this during uvm init.
+	 */
+	proc0paddr = (struct user *)kernelstack.pv_va;
+	lwp0.l_addr = proc0paddr;
+
+#ifdef VERBOSE_INIT_ARM
+	printf("bootstrap done.\n");
+#endif
+
+	arm32_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
+
+	/*
+	 * Pages were allocated during the secondary bootstrap for the
+	 * stacks for different CPU modes.
+	 * We must now set the r13 registers in the different CPU modes to
+	 * point to these stacks.
+	 * Since the ARM stacks use STMFD etc. we must set r13 to the top end
+	 * of the stack memory.
+	 */
+#ifdef VERBOSE_INIT_ARM
+	printf("init subsystems: stacks ");
+#endif
+
+	set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE);
+	set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE);
+	set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE);
+
+	/*
+	 * Well we should set a data abort handler.
+	 * Once things get going this will change as we will need a proper
+	 * handler.
+	 * Until then we will use a handler that just panics but tells us
+	 * why.
+	 * Initialisation of the vectors will just panic on a data abort.
+	 * This just fills in a slightly better one.
+	 */
+#ifdef VERBOSE_INIT_ARM
+	printf("vectors ");
+#endif
+	data_abort_handler_address = (u_int)data_abort_handler;
+	prefetch_abort_handler_address = (u_int)prefetch_abort_handler;
+	undefined_handler_address = (u_int)undefinedinstruction_bounce;
+
+	/* Initialise the undefined instruction handlers */
+#ifdef VERBOSE_INIT_ARM
+	printf("undefined ");
+#endif
+	undefined_init();
+
+	/* Load memory into UVM. */
+#ifdef VERBOSE_INIT_ARM
+	printf("page ");
+#endif
+	uvm_setpagesize();        /* initialize PAGE_SIZE-dependent variables */
+	uvm_page_physload(atop(physical_freestart), atop(physical_freeend),
+	    atop(physical_freestart), atop(physical_freeend),
+	    VM_FREELIST_DEFAULT);
+
+	/* Boot strap pmap telling it where the kernel page table is */
+#ifdef VERBOSE_INIT_ARM
+	printf("pmap ");
+#endif
+	pmap_bootstrap((pd_entry_t *)kernel_l1pt.pv_va, KERNEL_VM_BASE,
+	    KERNEL_VM_BASE + KERNEL_VM_SIZE);
+
+#ifdef VERBOSE_INIT_ARM
+	printf("done.\n");
+#endif
+
+#ifdef IPKDB
+	/* Initialise ipkdb */
+	ipkdb_init();
+	if (boothowto & RB_KDB)
+		ipkdb_connect(0);
+#endif
+
+#ifdef KGDB
+	if (boothowto & RB_KDB) {
+		kgdb_debug_init = 1;
+		kgdb_connect(1);
+	}
+#endif
+
+#ifdef DDB
+	db_trap_callback = sdp_db_trap;
+	db_machine_init();
+
+	/* Firmware doesn't load symbols. */
+	ddb_init(0, NULL, NULL);
+
+	if (boothowto & RB_KDB)
+		Debugger();
+#endif
+
+	/* We return the new stack pointer address */
+	return(kernelstack.pv_va + USPACE_SVC_STACK_TOP);
+}
+
+static void
+init_clocks(void)
+{
+#ifdef NOTYET
+	static volatile uint32_t * const clksel_reg = (volatile uint32_t *) (OMAP2430_L4_WAKEUP_VBASE + OMAP2430_CM_BASE + OMAP2430_CM_CLKSEL_MPU - OMAP2430_L4_WAKEUP_BASE);
+	uint32_t v;
+	sdp_putchar('E');
+	v = *clksel_reg;
+	sdp_putchar('F');
+	if (v != OMAP2430_CM_CLKSEL_MPU_FULLSPEED) {
+		printf("Changed CPU speed from half (%d) ", v);
+		*clksel_reg = OMAP2430_CM_CLKSEL_MPU_FULLSPEED;
+		printf("to full speed.\n");
+	}
+	sdp_putchar('G');
+#endif
+	arm1136_pmc_ccnt_init();
+}
+
+#ifndef CONSADDR
+#error Specify the address of the console UART with the CONSADDR option.
+#endif
+#ifndef CONSPEED
+#define CONSPEED 115200
+#endif
+#ifndef CONMODE
+#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
+#endif
+
+static const bus_addr_t consaddr = CONSADDR;
+static const int conspeed = CONSPEED;
+static const int conmode = CONMODE;
+
+void
+consinit(void)
+{
+	bus_space_handle_t bh;
+	static int consinit_called = 0;
+
+	if (consinit_called != 0)
+		return;
+
+	consinit_called = 1;
+
+	sdp_putchar('e');
+
+	if (bus_space_map(&omap_a4x_bs_tag, consaddr, OMAP_COM_SIZE, 0, &bh))
+		panic("Serial console can not be mapped.");
+
+	if (comcnattach(&omap_a4x_bs_tag, consaddr, conspeed,
+			OMAP_COM_FREQ, COM_TYPE_NORMAL, conmode))
+		panic("Serial console can not be initialized.");
+
+	bus_space_unmap(&omap_a4x_bs_tag, bh, OMAP_COM_SIZE);
+
+	sdp_putchar('f');
+	sdp_putchar('g');
+}
+
+#ifdef KGDB
+#ifndef KGDB_DEVADDR
+#error Specify the address of the kgdb UART with the KGDB_DEVADDR option.
+#endif
+#ifndef KGDB_DEVRATE
+#define KGDB_DEVRATE 115200
+#endif
+
+#ifndef KGDB_DEVMODE
+#define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */
+#endif
+static const vaddr_t comkgdbaddr = KGDB_DEVADDR;
+static const int comkgdbspeed = KGDB_DEVRATE;
+static const int comkgdbmode = KGDB_DEVMODE;
+
+void
+static kgdb_port_init(void)
+{
+	static int kgdbsinit_called = 0;
+
+	if (kgdbsinit_called != 0)
+		return;
+
+	kgdbsinit_called = 1;
+
+	bus_space_handle_t bh;
+	if (bus_space_map(&omap_a4x_bs_tag, comkgdbaddr, OMAP_COM_SIZE, 0, &bh))
+		panic("kgdb port can not be mapped.");
+
+	if (com_kgdb_attach(&omap_a4x_bs_tag, comkgdbaddr, comkgdbspeed,
+			OMAP_COM_FREQ, COM_TYPE_NORMAL, comkgdbmode))
+		panic("KGDB uart can not be initialized.");
+
+	bus_space_unmap(&omap_a4x_bs_tag, bh, OMAP_COM_SIZE);
+}
+#endif
+
+static void
+setup_real_page_tables(void)
+{
+	/*
+	 * We need to allocate some fixed page tables to get the kernel going.
+	 *
+	 * We are going to allocate our bootstrap pages from the beginning of
+	 * the free space that we just calculated.  We allocate one page
+	 * directory and a number of page tables and store the physical
+	 * addresses in the kernel_pt_table array.
+	 *
+	 * The kernel page directory must be on a 16K boundary.  The page
+	 * tables must be on 4K boundaries.  What we do is allocate the
+	 * page directory on the first 16K boundary that we encounter, and
+	 * the page tables on 4K boundaries otherwise.  Since we allocate
+	 * at least 3 L2 page tables, we are guaranteed to encounter at
+	 * least one 16K aligned region.
+	 */
+
+#ifdef VERBOSE_INIT_ARM
+	printf("Allocating page tables\n");
+#endif
+
+	/*
+	 * Define a macro to simplify memory allocation.  As we allocate the
+	 * memory, make sure that we don't walk over our temporary first level
+	 * translation table.
+	 */
+#define valloc_pages(var, np)						\
+	(var).pv_pa = physical_freestart;				\
+	physical_freestart += ((np) * PAGE_SIZE);			\
+	if (physical_freestart > (physical_freeend - L1_TABLE_SIZE))	\
+		panic("initarm: out of memory");			\
+	free_pages -= (np);						\
+	(var).pv_va = KERN_PHYSTOV((var).pv_pa);			\
+	memset((char *)(var).pv_va, 0, ((np) * PAGE_SIZE));
+
+	int loop, pt_index;
+
+	pt_index = 0;
+	kernel_l1pt.pv_pa = 0;
+	kernel_l1pt.pv_va = 0;
+printf("%s: physical_freestart %#lx\n", __FUNCTION__, physical_freestart);
+	for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) {
+		/* Are we 16KB aligned for an L1 ? */
+		if ((physical_freestart & (L1_TABLE_SIZE - 1)) == 0
+		    && kernel_l1pt.pv_pa == 0) {
+			valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE);
+		} else {
+			valloc_pages(kernel_pt_table[pt_index],
+			    L2_TABLE_SIZE / PAGE_SIZE);
+			++pt_index;
+		}
+	}
+pt_index=0;
+printf("%s: kernel_l1pt: %#lx:%#lx\n", __FUNCTION__, kernel_l1pt.pv_va, kernel_l1pt.pv_pa);
+printf("%s: kernel_pt_table:\n", __FUNCTION__);
+for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+printf("\t%#lx:%#lx\n", kernel_pt_table[pt_index].pv_va, kernel_pt_table[pt_index].pv_pa);
+++pt_index;
+}
+
+	/* This should never be able to happen but better confirm that. */
+	if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0)
+		panic("initarm: Failed to align the kernel page directory");
+
+	/*
+	 * Allocate a page for the system page mapped to V0x00000000
+	 * This page will just contain the system vectors and can be
+	 * shared by all processes.
+	 */
+	valloc_pages(systempage, 1);
+	systempage.pv_va = 0x00000000;
+
+	/* Allocate stacks for all modes */
+	valloc_pages(irqstack, IRQ_STACK_SIZE);
+	valloc_pages(abtstack, ABT_STACK_SIZE);
+	valloc_pages(undstack, UND_STACK_SIZE);
+	valloc_pages(kernelstack, UPAGES);
+
+	/* Allocate the message buffer. */
+	pv_addr_t msgbuf;
+	int msgbuf_pgs = round_page(MSGBUFSIZE) / PAGE_SIZE;
+	valloc_pages(msgbuf, msgbuf_pgs);
+	msgbufphys = msgbuf.pv_pa;
+
+	/*
+	 * Ok we have allocated physical pages for the primary kernel
+	 * page tables
+	 */
+
+#ifdef VERBOSE_INIT_ARM
+	printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa);
+#endif
+
+	/*
+	 * Now we start construction of the L1 page table
+	 * We start by mapping the L2 page tables into the L1.
+	 * This means that we can replace L1 mappings later on if necessary
+	 */
+	vaddr_t l1_va = kernel_l1pt.pv_va;
+	paddr_t l1_pa = kernel_l1pt.pv_pa;
+
+	/* Map the L2 pages tables in the L1 page table */
+	pmap_link_l2pt(l1_va, ARM_VECTORS_HIGH & ~(0x00400000 - 1),
+		       &kernel_pt_table[KERNEL_PT_SYS]);
+	for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++)
+		pmap_link_l2pt(l1_va, KERNEL_BASE + loop * 0x00400000,
+			       &kernel_pt_table[KERNEL_PT_KERNEL + loop]);
+	for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++)
+		pmap_link_l2pt(l1_va, KERNEL_VM_BASE + loop * 0x00400000,
+			       &kernel_pt_table[KERNEL_PT_VMDATA + loop]);
+
+	/* update the top of the kernel VM */
+	pmap_curmaxkvaddr =
+	    KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000);
+
+#ifdef VERBOSE_INIT_ARM
+	printf("Mapping kernel\n");
+#endif
+
+	/* Now we fill in the L2 pagetable for the kernel static code/data */
+#define round_L_page(x) (((x) + L2_L_OFFSET) & L2_L_FRAME)
+	size_t textsize = round_L_page((uintptr_t) etext - KERNEL_BASE);
+	size_t totalsize = round_L_page((uintptr_t) _end - KERNEL_BASE);
+	u_int offset = 0;	/* offset of kernel in RAM */
+
+	/* Map text section read-only. */
+	offset += pmap_map_chunk(l1_va, KERNEL_BASE + offset,
+				 physical_start + offset, textsize,
+				 VM_PROT_READ, PTE_CACHE);
+	/* Map data and bss sections read-write. */
+	offset += pmap_map_chunk(l1_va, KERNEL_BASE + offset,
+				 physical_start + offset, totalsize - textsize,
+				 VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+#ifdef VERBOSE_INIT_ARM
+	printf("Constructing L2 page tables\n");
+#endif
+
+	/* Map the stack pages */
+	pmap_map_chunk(l1_va, irqstack.pv_va, irqstack.pv_pa,
+	    IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+	pmap_map_chunk(l1_va, abtstack.pv_va, abtstack.pv_pa,
+	    ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+	pmap_map_chunk(l1_va, undstack.pv_va, undstack.pv_pa,
+	    UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+	pmap_map_chunk(l1_va, kernelstack.pv_va, kernelstack.pv_pa,
+	    UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE);
+
+	pmap_map_chunk(l1_va, kernel_l1pt.pv_va, kernel_l1pt.pv_pa,
+	    L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE);
+
+	for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) {
+		pmap_map_chunk(l1_va, kernel_pt_table[loop].pv_va,
+			       kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE,
+			       VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE);
+	}
+
+	/* Map the vector page. */
+	pmap_map_entry(l1_va, ARM_VECTORS_HIGH, systempage.pv_pa,
+		       VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE);
+
+	/*
+	 * Map integrated peripherals at same address in first level page
+	 * table so that we can continue to use console.
+	 */
+	pmap_devmap_bootstrap(l1_va, devmap);
+
+
+#ifdef VERBOSE_INIT_ARM
+	/* Tell the user about where all the bits and pieces live. */
+	printf("%22s       Physical              Virtual        Num\n", " ");
+	printf("%22s Starting    Ending    Starting    Ending   Pages\n", " ");
+
+	static const char mem_fmt[] =
+	    "%20s: 0x%08lx 0x%08lx 0x%08lx 0x%08lx %d\n";
+	static const char mem_fmt_nov[] =
+	    "%20s: 0x%08lx 0x%08lx                       %d\n";
+
+	printf(mem_fmt, "SDRAM", physical_start, physical_end-1,
+	    KERN_PHYSTOV(physical_start), KERN_PHYSTOV(physical_end-1),
+	    physmem);
+	printf(mem_fmt, "text section",
+	       KERN_VTOPHYS(KERNEL_BASE), KERN_VTOPHYS(etext-1),
+	       (vaddr_t)KERNEL_BASE, (vaddr_t)etext-1,
+	       (int)(textsize / PAGE_SIZE));
+	printf(mem_fmt, "data section",
+	       KERN_VTOPHYS(__data_start), KERN_VTOPHYS(_edata),
+	       (vaddr_t)__data_start, (vaddr_t)_edata,
+	       (int)((round_page((vaddr_t)_edata)
+		      - trunc_page((vaddr_t)__data_start)) / PAGE_SIZE));
+	printf(mem_fmt, "bss section",
+	       KERN_VTOPHYS(__bss_start), KERN_VTOPHYS(__bss_end__),
+	       (vaddr_t)__bss_start, (vaddr_t)__bss_end__,
+	       (int)((round_page((vaddr_t)__bss_end__)
+		      - trunc_page((vaddr_t)__bss_start)) / PAGE_SIZE));
+	printf(mem_fmt, "L1 page directory",
+	    kernel_l1pt.pv_pa, kernel_l1pt.pv_pa + L1_TABLE_SIZE - 1,
+	    kernel_l1pt.pv_va, kernel_l1pt.pv_va + L1_TABLE_SIZE - 1,
+	    L1_TABLE_SIZE / PAGE_SIZE);
+	printf(mem_fmt, "Exception Vectors",
+	    systempage.pv_pa, systempage.pv_pa + PAGE_SIZE - 1,
+	    (vaddr_t)ARM_VECTORS_HIGH, (vaddr_t)ARM_VECTORS_HIGH + PAGE_SIZE - 1,
+	    1);
+	printf(mem_fmt, "IRQ stack",
+	    irqstack.pv_pa, irqstack.pv_pa + (IRQ_STACK_SIZE * PAGE_SIZE) - 1,
+	    irqstack.pv_va, irqstack.pv_va + (IRQ_STACK_SIZE * PAGE_SIZE) - 1,
+	    IRQ_STACK_SIZE);
+	printf(mem_fmt, "ABT stack",
+	    abtstack.pv_pa, abtstack.pv_pa + (ABT_STACK_SIZE * PAGE_SIZE) - 1,
+	    abtstack.pv_va, abtstack.pv_va + (ABT_STACK_SIZE * PAGE_SIZE) - 1,
+	    ABT_STACK_SIZE);
+	printf(mem_fmt, "UND stack",
+	    undstack.pv_pa, undstack.pv_pa + (UND_STACK_SIZE * PAGE_SIZE) - 1,
+	    undstack.pv_va, undstack.pv_va + (UND_STACK_SIZE * PAGE_SIZE) - 1,
+	    UND_STACK_SIZE);
+	printf(mem_fmt, "SVC stack",
+	    kernelstack.pv_pa, kernelstack.pv_pa + (UPAGES * PAGE_SIZE) - 1,
+	    kernelstack.pv_va, kernelstack.pv_va + (UPAGES * PAGE_SIZE) - 1,
+	    UPAGES);
+	printf(mem_fmt_nov, "Message Buffer",
+	    msgbufphys, msgbufphys + msgbuf_pgs * PAGE_SIZE - 1, msgbuf_pgs);
+	printf(mem_fmt, "Free Memory", physical_freestart, physical_freeend-1,
+	    KERN_PHYSTOV(physical_freestart), KERN_PHYSTOV(physical_freeend-1),
+	    free_pages);
+#endif
+
+	/*
+	 * Now we have the real page tables in place so we can switch to them.
+	 * Once this is done we will be running with the REAL kernel page
+	 * tables.
+	 */
+
+	/* Switch tables */
+#ifdef VERBOSE_INIT_ARM
+	printf("switching to new L1 page table  @%#lx...", l1_pa);
+#endif
+
+	cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT);
+	setttb(l1_pa);
+	cpu_tlb_flushID();
+	cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2));
+
+#ifdef VERBOSE_INIT_ARM
+	printf("OK.\n");
+#endif
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/arch/evbarm/sdp2430/sdp2430_start.S sys/arch/evbarm/sdp2430/sdp2430_start.S
--- ../../netbsd_40/src/sys/arch/evbarm/sdp2430/sdp2430_start.S	1969-12-31 16:00:00.000000000 -0800
+++ sys/arch/evbarm/sdp2430/sdp2430_start.S	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,311 @@
+/*
+ * Machine dependant startup code for SDP2430 boards.
+ * Based on omap_start.S
+ *
+ * Copyright (c) 2002, 2003  Genetec Corporation.  All rights reserved.
+ * Written by Hiroyuki Bessho for Genetec Corporation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of Genetec Corporation may not be used to endorse or
+ *    promote products derived from this software without specific prior
+ *    written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright (c) 2003
+ *	Ichiro FUKUHARA <ichiro@ichiro.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Ichiro FUKUHARA.
+ * 4. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ICHIRO FUKUHARA ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ICHIRO FUKUHARA OR THE VOICES IN HIS HEAD BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "opt_com.h"
+#include "assym.h"
+
+#include <machine/asm.h>
+#include <arm/armreg.h>
+#undef DOMAIN_CLIENT	/* assym.h defines as 1, but pte.h defines as 0x01 */
+#include <arm/arm32/pmap.h>
+#include <arm/omap/omap_reg.h>
+#include <arm/omap/omap2430obioreg.h>
+#include <evbarm/sdp2430/sdp2430.h>  
+
+RCSID("$NetBSD$")
+
+/*
+ * Workaround Erratum 411920 
+ * 
+ *	- value of arg 'reg' Should Be Zero
+ */
+#define Invalidate_I_cache(reg) \
+	.p2align 5;								\
+	mcr	p15, 0, reg, c7, c5, 0;	/* Invalidate Entire I cache */		\
+	mcr	p15, 0, reg, c7, c5, 0;	/* Invalidate Entire I cache */		\
+	mcr	p15, 0, reg, c7, c5, 0;	/* Invalidate Entire I cache */		\
+	mcr	p15, 0, reg, c7, c5, 0;	/* Invalidate Entire I cache */		\
+	nop;									\
+	nop;									\
+	nop;									\
+	nop;									\
+	nop;									\
+	nop;									\
+	nop;									\
+	nop;									\
+	nop;									\
+	nop;									\
+	nop;
+
+/*
+ * Kernel start routine for OMAP 1136 boards.
+ * At this point, this code has been loaded into SDRAM
+ * and the MMU is off
+ */
+	.section .start,"ax",%progbits
+
+	.global	_C_LABEL(omap_start)
+_C_LABEL(sdp2430_start):
+	/* Move into supervisor mode and disable IRQs/FIQs. */
+	cpsid	if, #PSR_SVC32_MODE
+
+	/*
+	 * Set up a preliminary mapping in the MMU to allow us to run
+	 * at KERNEL_BASE with caches on.
+	 */
+	/* Build page table from scratch */
+	ldr	r0, Ltemp_l1_table
+	mov	r1, r0			/* Save the page table address. */
+	/* Zero the entire table so all virtual addresses are invalid. */
+	mov	r2, #L1_TABLE_SIZE	/* in bytes */
+	mov	r3, #0
+	mov	r4, r3
+	mov	r5, r3
+	mov	r6, r3
+	mov	r7, r3
+	mov	r8, r3
+	mov	r10, r3
+	mov	r11, r3
+1:	stmia	r1!, {r3-r8,r10-r11}
+	stmia	r1!, {r3-r8,r10-r11}
+	stmia	r1!, {r3-r8,r10-r11}
+	stmia	r1!, {r3-r8,r10-r11}
+	subs	r2, r2, #(4 * 4 * 8)	/* bytes per loop */
+	bne	1b
+
+	/* Now create our entries per the mmu_init_table. */
+	l1table	.req r0
+	va	.req r1
+	pa	.req r2
+	n_sec	.req r3
+	attr	.req r4
+	itable	.req r5
+	l1sfrm	.req r6
+	adr	itable, mmu_init_table
+	ldr	l1sfrm, Ll1_s_frame
+	b	3f
+2:	str	pa, [l1table, va]
+	add	va, va, #4
+	add	pa, pa, #(L1_S_SIZE)
+	adds	n_sec, n_sec, #-1
+	bhi	2b
+3:	ldmia	itable!, {va,pa,n_sec,attr}
+	/* Convert va to l1 offset:	va = 4 * (va >> L1_S_SHIFT)	*/
+	mov	va, va, LSR #L1_S_SHIFT
+	mov	va, va, LSL #2
+	/* Convert pa to l1 entry:	pa = (pa & L1_S_FRAME) | attr	*/
+	and	pa, pa, l1sfrm
+	orr	pa, pa, attr
+	cmp	n_sec, #0
+	bne	2b
+	.unreq	va
+	.unreq	pa
+	.unreq	n_sec
+	.unreq	attr
+	.unreq	itable
+	.unreq	l1table
+	.unreq	l1sfrm
+
+	/*
+	 * In theory, because the MMU is off, we shouldn't need all of this,
+	 * but let's not take any chances and do a typical sequence to set
+	 * the Translation Table Base.
+	 */
+
+	Invalidate_I_cache(r0)
+
+	mcr	p15, 0, r0, c7, c14, 0	/* Clean and Invalidate Entire Data Cache */
+
+        ldr     r2, Lctl_ID_dis		/* Disable I+D caches */
+	mrc	p15, 0, r1, c1, c0, 0	/*  "       "   "     */
+	and	r1, r1, r2		/*  "       "   "     */
+	mcr	p15, 0, r1, c1, c0, 0	/*  "       "   "     */
+
+#ifdef NOTYET
+	/*
+	 * XXX Restrict cache size is reported to be unsupported on SDP2340
+	 * XXX your CPU mileage may vary... as yet there is not generalized way to do this
+	 */
+        ldr     r2, Lauxctl_CZ_restrict	/* Restrict cache size */
+	mrc	p15, 0, r1, c1, c0, 1	/*  "        "     "   */
+	orr	r1, r1, r2		/*  "        "     "   */
+	mcr	p15, 0, r1, c1, c0, 1	/*  "        "     "   */
+#endif
+
+	mcr	p15, 0, r0, c7, c10, 4	/* Drain the write buffers. */
+	mcr	p15, 0, r0, c2, c0, 0	/* Set Translation Table Base */
+	mcr	p15, 0, r0, c8, c7, 0	/* Invalidate TLBs */
+
+	/* Set the Domain Access register.  Very important! */
+        mov     r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT)
+	mcr	p15, 0, r0, c3, c0, 0
+
+	/*
+	 * Enable the MMU, etc.
+	 */
+	mrc     p15, 0, r0, c1, c0, 0
+	ldr     r1, Lcontrol_wax
+	and	r0, r0, r1
+	ldr     r1, Lcontrol_clr
+	mvn	r1, r1
+	and	r0, r0, r1
+	ldr     r1, Lcontrol_set
+	orr	r0, r0, r1
+	mcr     p15, 0, r0, c1, c0, 0
+
+	/*
+	 * Ensure that the coprocessor has finished turning on the MMU.
+	 */
+	mrc	p15, 0, r0, c2, c0, 0	/* Read an arbitrary value. */
+	mov	r0, r0			/* Stall until read completes. */
+
+	/*
+	 * Jump to start in locore.S, which in turn will call initarm and main.
+	 */
+	ldr	pc, Lstart		/* Jump to start (flushes pipeline). */
+	nop
+	nop
+	nop
+	nop
+	
+	/* NOTREACHED */
+
+Lstart:
+	.word	start
+Ll1_s_frame:
+	.word	L1_S_FRAME
+Ltemp_l1_table:
+	/* Put the temporary L1 translation table at the end of SDRAM. */
+	.word	0x80000000 + MEMSIZE_BYTES - L1_TABLE_SIZE
+
+/*
+ * Coprocessor register initialization values
+ */
+# define CPU_AUXCTL_CZ	(1 << 6)		/* Restrict Cache Size */
+
+	/* bits to set in the Control Register */
+Lcontrol_set:
+	.word CPU_CONTROL_MMU_ENABLE  | \
+	      CPU_CONTROL_AFLT_ENABLE | \
+	      CPU_CONTROL_DC_ENABLE   | \
+	      CPU_CONTROL_WBUF_ENABLE | \
+	      CPU_CONTROL_32BP_ENABLE | \
+	      CPU_CONTROL_32BD_ENABLE | \
+	      CPU_CONTROL_LABT_ENABLE | \
+	      CPU_CONTROL_SYST_ENABLE | \
+	      CPU_CONTROL_IC_ENABLE
+
+	/* bits to clear in the Control Register */
+Lcontrol_clr:
+	.word	0
+
+	/* bits to "write as existing" in the Control Register */
+Lcontrol_wax:
+	.word	(3 << 30) | \
+		(1 << 29) | \
+		(1 << 28) | \
+		(3 << 26) | \
+		(3 << 19) | \
+		(1 << 17)
+		
+	/* bits to disable the caches */
+Lctl_ID_dis:
+	.word	~(CPU_CONTROL_IC_ENABLE|CPU_CONTROL_DC_ENABLE)
+
+	/* bit to restrict cache size */
+Lauxctl_CZ_restrict:
+	.word	CPU_AUXCTL_CZ
+
+
+/* We'll modify va and pa at run time so we can use relocatable addresses. */
+#define MMU_INIT(va,pa,n_sec,attr) \
+	.word	va					    ; \
+	.word	pa					    ; \
+	.word	n_sec					    ; \
+	.word	attr					    ;
+
+#define KERNEL_BASE_phys_off	(KERNEL_BASE_phys - 0x80000000)
+
+mmu_init_table:
+	/* Map SDRAM where we're executing from VA==PA, read-only */
+	MMU_INIT(KERNEL_BASE_phys, KERNEL_BASE_phys,
+		1,
+		L1_S_PROTO | L1_S_AP(AP_KR))
+
+	/* Map KERNEL_BASE VA to SDRAM PA, write-back cacheable */
+	MMU_INIT(KERNEL_BASE, KERNEL_BASE_phys,
+		((MEMSIZE_BYTES - 0x00300000) + L1_S_SIZE - 1) / L1_S_SIZE,
+		L1_S_PROTO | L1_S_AP(AP_KRW) | L1_S_B | L1_S_C)
+
+	/* Map first 1MB of L4 CORE (so console will work) */
+	MMU_INIT(OMAP2430_L4_CORE_VBASE, OMAP2430_L4_CORE_BASE,
+		1,
+		L1_S_PROTO | L1_S_AP(AP_KRW))
+
+	/* Map first 1MB of L4 WAKEUP (so console will work) */
+	MMU_INIT(OMAP2430_L4_WAKEUP_VBASE, OMAP2430_L4_WAKEUP_BASE,
+		1,
+		L1_S_PROTO | L1_S_AP(AP_KRW))
+
+	/* end of table */
+	MMU_INIT(0, 0, 0, 0)
diff --exclude CVS -ruN ../../netbsd_40/src/sys/conf/files sys/conf/files
--- ../../netbsd_40/src/sys/conf/files	2007-08-31 13:09:24.000000000 -0700
+++ sys/conf/files	2007-09-25 10:55:22.000000000 -0700
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.819.2.5 2007/08/31 20:09:24 pavel Exp $
+#	$NetBSD: files,v 1.819.2.4 2007/05/13 10:28:08 jdc Exp $

 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93

@@ -260,6 +260,7 @@
 define 	pckbport	{[slot = -1]}
 define	pckbport_machdep_cnattach
 define	firmload
+define	mmcbus		{ }

 # audio device attributes
 #
@@ -1028,6 +1029,8 @@
 define	tcbus	{ }			# TurboChannel attachment
 define	mcabus	{ }			# MicroChannel attachment
 define	usbus	{ }			# USB attachment
+define	usbfbus	{ }			# USB function attachment
+define	usbtbus { }			# USB transceiver attachment
 define	fwbus	{ }			# IEEE 1394 attachment
 define	vmebus	{ }			# VME bus attachment
 define	acpibus	{ }			# ACPI "bus" attachment
@@ -1233,6 +1236,12 @@
 #
 include "uvm/files.uvm"

+# Hardware clocks
+
+defparam opt_hwclock_machine.h	HWCLOCK_MACHINE
+file	kern/hwclock.c			hwclock
+
+
 #
 # Security models
 #
diff --exclude CVS -ruN ../../netbsd_40/src/sys/dev/ic/smc91cxx.c sys/dev/ic/smc91cxx.c
--- ../../netbsd_40/src/sys/dev/ic/smc91cxx.c	2006-11-15 17:32:52.000000000 -0800
+++ sys/dev/ic/smc91cxx.c	2007-09-25 10:55:22.000000000 -0700
@@ -140,6 +140,7 @@

 /* XXX Hardware padding doesn't work yet(?) */
 #define	SMC91CXX_SW_PAD
+#define SMC_NO_BYTE_WRITE

 const char *smc91cxx_idstrs[] = {
 	NULL,				/* 0 */
@@ -200,7 +201,7 @@
 void	smc91cxx_read(struct smc91cxx_softc *);
 void	smc91cxx_reset(struct smc91cxx_softc *);
 void	smc91cxx_start(struct ifnet *);
-void	smc91cxx_copy_tx_frame(struct smc91cxx_softc *, struct mbuf *);
+uint8_t	smc91cxx_copy_tx_frame(struct smc91cxx_softc *, struct mbuf *);
 void	smc91cxx_resume(struct smc91cxx_softc *);
 void	smc91cxx_stop(struct smc91cxx_softc *);
 void	smc91cxx_watchdog(struct ifnet *);
@@ -218,6 +219,41 @@
 		(a[2] != b[2]) || (a[1] != b[1]) || (a[0] != b[0]));
 }

+static inline void
+smc91cxx_intr_mask_write(bus_space_tag_t bst, bus_space_handle_t bsh,
+	uint8_t mask)
+{
+	KDASSERT((mask & IM_ERCV_INT) == 0);
+#ifdef SMC_NO_BYTE_WRITE
+#if BYTE_ORDER == LITTLE_ENDIAN
+	bus_space_write_2(bst, bsh, INTR_STAT_REG_B, mask << 8);
+#else
+	bus_space_write_2(bst, bsh, INTR_STAT_REG_B);
+#endif
+#else
+	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
+#endif
+	KDASSERT(!(bus_space_read_1(bst, bsh, INTR_MASK_REG_B) & IM_ERCV_INT));
+}
+
+static inline void
+smc91cxx_intr_ack_write(bus_space_tag_t bst, bus_space_handle_t bsh,
+	uint8_t mask)
+{
+#ifdef SMC_NO_BYTE_WRITE
+#if BYTE_ORDER == LITTLE_ENDIAN
+	bus_space_write_2(bst, bsh, INTR_ACK_REG_B,
+	    mask | (bus_space_read_2(bst, bsh, INTR_ACK_REG_B) & 0xff00));
+#else
+	bus_space_write_2(bst, bsh, INTR_ACK_REG_B,
+	    (mask << 8) | (bus_space_read_2(bst, bsh, INTR_ACK_REG_B) & 0xff));
+#endif
+#else
+	bus_space_write_1(bst, bsh, INTR_ACK_REG_B, mask);
+#endif
+	KDASSERT(!(bus_space_read_1(bst, bsh, INTR_MASK_REG_B) & IM_ERCV_INT));
+}
+
 void
 smc91cxx_attach(sc, myea)
 	struct smc91cxx_softc *sc;
@@ -515,6 +551,7 @@
 	 * Reset the MMU and wait for it to be un-busy.
 	 */
 	SMC_SELECT_BANK(sc, 2);
+	sc->sc_txpacketno = ARR_FAILED;
 	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RESET);
 	for (;;) {
 		tmp = bus_space_read_2(bst, bsh, MMU_CMD_REG_W);
@@ -527,7 +564,7 @@
 	/*
 	 * Disable all interrupts.
 	 */
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
+	smc91cxx_intr_mask_write(bst, bsh, 0);

 	/*
 	 * On the 91c111, enable auto-negotiation, and set the LED
@@ -583,14 +620,11 @@
 	 */
 	SMC_SELECT_BANK(sc, 2);

+	sc->sc_intmask = IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT;
 	if (sc->sc_chipid == CHIP_91C111 && sc->sc_internal_phy) {
-		bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
-		    IM_EPH_INT | IM_RX_OVRN_INT |
-		    IM_RCV_INT | IM_TX_INT | IM_MD_INT);
-	} else {
-		bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
-		    IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
+		sc->sc_intmask |= IM_MD_INT;
 	}
+	smc91cxx_intr_mask_write(bst, bsh, sc->sc_intmask);

 	/* Interface is now running, with no output active. */
 	ifp->if_flags |= IFF_RUNNING;
@@ -623,6 +657,7 @@
 	u_int len;
 	struct mbuf *m;
 	u_int16_t length, npages;
+	u_int16_t oddbyte;
 	u_int8_t packetno;
 	int timo, pad;

@@ -673,22 +708,28 @@
 	 * ask for "npages - 1".  We include space for the status word,
 	 * byte count, and control bytes in the allocation request.
 	 */
-	npages = (length + 6) >> 8;
-
-	/*
-	 * Now allocate the memory.
-	 */
-	SMC_SELECT_BANK(sc, 2);
-	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ALLOC | npages);
+	npages = ((length & ~1) + 6) >> 8;

 	timo = MEMORY_WAIT_TIME;
-	do {
-		if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT)
-			break;
-		delay(1);
-	} while (--timo);
+	if ((sc->sc_txpacketno & ARR_FAILED) == 0) {
+		packetno = sc->sc_txpacketno;
+		sc->sc_txpacketno = ARR_FAILED;
+	} else {
+		/*
+		 * Now allocate the memory.
+		 */
+		SMC_SELECT_BANK(sc, 2);
+		bus_space_write_2(bst, bsh, MMU_CMD_REG_W,
+		    MMUCR_ALLOC | npages);
+
+		do {
+			if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT)
+				break;
+			delay(1);
+		} while (--timo);

-	packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
+		packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
+	}

 	if (packetno & ARR_FAILED || timo == 0) {
 		/*
@@ -699,9 +740,9 @@
 		 * no one else attempts to transmit while we're allocating
 		 * memory.
 		 */
-		bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
-		    bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | IM_ALLOC_INT);
-
+		KASSERT(sc->sc_txpacketno & ARR_FAILED);
+		sc->sc_intmask |= IM_ALLOC_INT;
+		smc91cxx_intr_mask_write(bst, bsh, sc->sc_intmask);
 		ifp->if_timer = 5;
 		ifp->if_flags |= IFF_OACTIVE;

@@ -734,9 +775,21 @@
 	/*
 	 * Push the packet out to the card.
 	 */
-	smc91cxx_copy_tx_frame(sc, m);
+	oddbyte = smc91cxx_copy_tx_frame(sc, m);

 #ifdef SMC91CXX_SW_PAD
+#if BYTE_ORDER == LITTLE_ENDIAN
+	if (pad > 1 && (pad & 1)) {
+		bus_space_write_2(bst, bsh, DATA_REG_W, oddbyte << 0);
+		oddbyte = 0;
+	}
+#else
+	if (pad > 1 && (pad & 1))
+		bus_space_write_2(bst, bsh, DATA_REG_W, oddbyte << 8);
+		oddbyte = 0;
+	}
+#endif
+
 	/*
 	 * Push out padding.
 	 */
@@ -744,8 +797,6 @@
 		bus_space_write_2(bst, bsh, DATA_REG_W, 0);
 		pad -= 2;
 	}
-	if (pad)
-		bus_space_write_1(bst, bsh, DATA_REG_B, 0);
 #endif

 	/*
@@ -753,15 +804,20 @@
 	 * is 0, meaning the packet is even lengthed and no special
 	 * CRC handling is necessary.
 	 */
-	bus_space_write_2(bst, bsh, DATA_REG_W, 0);
+#if BYTE_ORDER == LITTLE_ENDIAN
+	bus_space_write_2(bst, bsh, DATA_REG_W,
+	    oddbyte | (pad ? (CTLB_ODD << 8) : 0));
+#else
+	bus_space_write_2(bst, bsh, DATA_REG_W,
+	    (oddbyte << 8) | (pad ? CTLB_ODD : 0));
+#endif

 	/*
 	 * Enable transmit interrupts and let the chip go.  Set a watchdog
 	 * in case we miss the interrupt.
 	 */
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
-	    bus_space_read_1(bst, bsh, INTR_MASK_REG_B) |
-	    IM_TX_INT | IM_TX_EMPTY_INT);
+	sc->sc_intmask |= IM_TX_INT | IM_TX_EMPTY_INT;
+	smc91cxx_intr_mask_write(bst, bsh, sc->sc_intmask);

 	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ENQUEUE);

@@ -789,7 +845,7 @@
 /*
  * Squirt a (possibly misaligned) mbuf to the device
  */
-void
+uint8_t
 smc91cxx_copy_tx_frame(sc, m0)
 	struct smc91cxx_softc *sc;
 	struct mbuf *m0;
@@ -862,8 +918,7 @@
 			panic("smc91cxx_copy_tx_frame: p != lim");
 #endif
 	}
-	if (leftover)
-		bus_space_write_1(bst, bsh, DATA_REG_B, dbuf);
+	return dbuf;
 }

 /*
@@ -878,7 +933,7 @@
 	bus_space_tag_t bst = sc->sc_bst;
 	bus_space_handle_t bsh = sc->sc_bsh;
 	u_int8_t mask, interrupts, status;
-	u_int16_t packetno, tx_status, card_stats;
+	u_int16_t packetno, tx_status, card_stats, v;

 	if ((sc->sc_flags & SMC_FLAGS_ENABLED) == 0 ||
 	    !device_is_active(&sc->sc_dev))
@@ -887,15 +942,22 @@
 	SMC_SELECT_BANK(sc, 2);

 	/*
-	 * Obtain the current interrupt mask.
+	 * Obtain the current interrupt status and mask.
 	 */
-	mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
+	v = bus_space_read_2(bst, bsh, INTR_STAT_REG_B);

 	/*
 	 * Get the set of interrupt which occurred and eliminate any
 	 * which are not enabled.
 	 */
-	interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B);
+#if BYTE_ORDER == LITTLE_ENDIAN
+	mask = v >> 8;
+	interrupts = v & 0xff;
+#else
+	interrupts = v >> 8;
+	mask = v & 0xff;
+#endif
+	KDASSERT(mask == sc->sc_intmask);
 	status = interrupts & mask;

 	/* Ours? */
@@ -905,13 +967,13 @@
 	/*
 	 * It's ours; disable all interrupts while we process them.
 	 */
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
+	smc91cxx_intr_mask_write(bst, bsh, 0);

 	/*
 	 * Receive overrun interrupts.
 	 */
 	if (status & IM_RX_OVRN_INT) {
-		bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_RX_OVRN_INT);
+		smc91cxx_intr_ack_write(bst, bsh, IM_RX_OVRN_INT);
 		ifp->if_ierrors++;
 	}

@@ -936,15 +998,17 @@
 	if (status & IM_ALLOC_INT) {
 		/* Disable this interrupt. */
 		mask &= ~IM_ALLOC_INT;
+		sc->sc_intmask &= ~IM_ALLOC_INT;

 		/*
-		 * Release the just-allocated memory.  We will reallocate
-		 * it through the normal start logic.
+		 * Remember the just allocated packet number.
+		 */
+		packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
+		KASSERT(sc->sc_txpacketno & ARR_FAILED);
+		sc->sc_txpacketno = packetno;
+		/*
+		 * Reanble transmits
 		 */
-		while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
-			/* XXX bound this loop! */ ;
-		bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
-
 		ifp->if_flags &= ~IFF_OACTIVE;
 		ifp->if_timer = 0;
 	}
@@ -955,7 +1019,7 @@
 	 * mode.
 	 */
 	if (status & IM_TX_INT) {
-		bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_INT);
+		smc91cxx_intr_ack_write(bst, bsh, IM_TX_INT);

 		packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) &
 		    FIFO_TX_MASK;
@@ -978,15 +1042,22 @@
 		 */
 		tx_status = bus_space_read_2(bst, bsh, DATA_REG_W);

-		if (tx_status & EPHSR_TX_SUC)
-			printf("%s: successful packet caused TX interrupt?!\n",
-			    sc->sc_dev.dv_xname);
-		else
+		if (tx_status & EPHSR_TX_SUC) {
+			static struct timeval txsuc_last;
+			static int txsuc_count;
+			if (ppsratecheck(&txsuc_last, &txsuc_count, 1))
+				printf("%s: successful packet caused TX"
+				    " interrupt?!\n", sc->sc_dev.dv_xname);
+		} else
 			ifp->if_oerrors++;

 		if (tx_status & EPHSR_LATCOL)
 			ifp->if_collisions++;

+		/* Disable this interrupt (start will reenable if needed). */
+		mask &= ~IM_TX_INT;
+		sc->sc_intmask &= ~IM_TX_INT;
+
 		/*
 		 * Some of these errors disable the transmitter; reenable it.
 		 */
@@ -1014,10 +1085,11 @@
 	 * update transmit statistics from the card.
 	 */
 	if (status & IM_TX_EMPTY_INT) {
-		bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_EMPTY_INT);
+		smc91cxx_intr_ack_write(bst, bsh, IM_TX_EMPTY_INT);

 		/* Disable this interrupt. */
 		mask &= ~IM_TX_EMPTY_INT;
+		sc->sc_intmask &= ~IM_TX_EMPTY_INT;

 		SMC_SELECT_BANK(sc, 0);
 		card_stats = bus_space_read_2(bst, bsh, COUNTER_REG_W);
@@ -1059,8 +1131,8 @@
 	 * Reenable the interrupts we wish to receive now that processing
 	 * is complete.
 	 */
-	mask |= bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
+	mask |= sc->sc_intmask;
+	smc91cxx_intr_mask_write(bst, bsh, mask);

 #if NRND > 0
 	if (status)
@@ -1093,6 +1165,10 @@
 	 * PTR_RCV is set, the packet number will be found automatically
 	 * in FIFO_PORTS_REG_W, FIFO_RX_MASK.
 	 */
+	packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
+	if (packetno & FIFO_REMPTY)
+		return;
+
 	bus_space_write_2(bst, bsh, POINTER_REG_W,
 	    PTR_READ | PTR_RCV | PTR_AUTOINC /* | 0x0000 */);

@@ -1114,6 +1190,10 @@
 	}

 	packetlen &= RLEN_MASK;
+	if (packetlen < ETHER_MIN_LEN - ETHER_CRC_LEN + 6 || packetlen > 1534) {
+		ifp->if_ierrors++;
+		goto out;
+	}

 	/*
 	 * The packet length includes 3 extra words: status, length,
@@ -1167,6 +1247,7 @@

 		eh = mtod(m, struct ether_header *);
 		data = mtod(m, u_int8_t *);
+		KASSERT(trunc_page((uintptr_t)data) == trunc_page((uintptr_t)data + packetlen - 1));
 		if (packetlen > 1)
 			bus_space_read_multi_stream_2(bst, bsh, DATA_REG_W,
 			    (u_int16_t *)data, packetlen >> 1);
@@ -1180,6 +1261,7 @@
 		m->m_data = (caddr_t) ALIGN(mtod(m, caddr_t));
 		eh = mtod(m, struct ether_header *);
 		dp = data = mtod(m, u_int8_t *);
+		KASSERT(trunc_page((uintptr_t)data) == trunc_page((uintptr_t)data + packetlen - 1));
 		if (packetlen > 3)
 			bus_space_read_multi_stream_4(bst, bsh, DATA_REG_W,
 			    (u_int32_t *)data, packetlen >> 2);
@@ -1378,7 +1460,7 @@
 	 * Clear interrupt mask; disable all interrupts.
 	 */
 	SMC_SELECT_BANK(sc, 2);
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
+	smc91cxx_intr_mask_write(bst, bsh, 0);

 	/*
 	 * Disable transmitter and receiver.
diff --exclude CVS -ruN ../../netbsd_40/src/sys/dev/ic/smc91cxxvar.h sys/dev/ic/smc91cxxvar.h
--- ../../netbsd_40/src/sys/dev/ic/smc91cxxvar.h	2005-12-11 04:21:28.000000000 -0800
+++ sys/dev/ic/smc91cxxvar.h	2007-09-25 10:55:22.000000000 -0700
@@ -65,6 +65,9 @@
 	u_int8_t	sc_chipid;
 	u_int8_t	sc_internal_phy;	/* 91C111 only */

+	uint8_t		sc_intmask;
+	uint8_t		sc_txpacketno;
+
 #if NRND > 0
 	rndsource_element_t rnd_source;
 #endif
diff --exclude CVS -ruN ../../netbsd_40/src/sys/kern/hwclock.c sys/kern/hwclock.c
--- ../../netbsd_40/src/sys/kern/hwclock.c	1969-12-31 16:00:00.000000000 -0800
+++ sys/kern/hwclock.c	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,537 @@
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/conf.h>
+#include <sys/lock.h>
+#include <sys/queue.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/hwclock.h>
+
+static LIST_HEAD(, hwclock) hwclocks = LIST_HEAD_INITIALIZER(hwclocks);
+struct simplelock hwclocks_lock = SIMPLELOCK_INITIALIZER;
+
+static hwclock_policy_mgr_t policy_mgr;
+
+/* Caller must hold hwclocks_lock */
+
+static struct hwclock *clocknamelookup(const char *clockname)
+{
+	struct hwclock *hwc;
+
+	LIST_FOREACH(hwc, &hwclocks, clks) {
+		if (strcmp(clockname, hwc->name) == 0)
+			break;
+	}
+
+	return hwc;
+}
+
+
+int hwclock_getfreq(const char *clockname, unsigned long *freq)
+{
+	struct hwclock *hwc;
+	int ret = 0;
+
+	simple_lock(&hwclocks_lock);
+
+	if (((hwc = clocknamelookup(clockname)) == NULL) ||
+		(! hwc->getfreq)) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	ret = (*hwc->getfreq)(hwc, freq);
+
+out:
+	simple_unlock(&hwclocks_lock);
+	return ret;
+}
+
+
+int hwclock_setfreq(const char *clockname, unsigned long freq)
+{
+	struct hwclock *hwc;
+	int ret = 0;
+
+	simple_lock(&hwclocks_lock);
+
+	if (((hwc = clocknamelookup(clockname)) == NULL) ||
+		(! hwc->setfreq)) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	// todo: Check constraints?
+
+	if ((*hwc->setfreq)(hwc, freq) == 0) {
+		/* Just set "current constraints" to the new value */
+		hwc->freqcons_min = freq;
+		hwc->freqcons_max = freq;
+	} else {
+		ret = EINVAL;
+		goto out;
+	}
+
+
+out:
+	simple_unlock(&hwclocks_lock);
+	return ret;
+}
+
+
+int hwclock_getenable(const char *clockname, unsigned long *value)
+{
+	struct hwclock *hwc;
+	int ret = 0;
+
+	simple_lock(&hwclocks_lock);
+
+	if (((hwc = clocknamelookup(clockname)) == NULL) ||
+		(! hwc->getenable)) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	ret = (*hwc->getenable)(hwc, value);
+
+out:
+	simple_unlock(&hwclocks_lock);
+	return ret;
+}
+
+
+int hwclock_setenable(const char *clockname, unsigned long value)
+{
+	struct hwclock *hwc;
+	int ret = 0;
+
+	simple_lock(&hwclocks_lock);
+
+	if (((hwc = clocknamelookup(clockname)) == NULL)
+		|| (! hwc->setenable)) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	// todo: check constraints?
+
+	ret = hwc->setenable(hwc, value);
+
+out:
+	simple_unlock(&hwclocks_lock);
+	return ret;
+}
+
+
+static int constrain_freq_tree(struct hwclock *hwc, unsigned long fcmin,
+							   unsigned long fcmax)
+{
+	struct hwclock_constraint *constraint;
+	unsigned long newmin, newmax;
+	int ret = 0;
+
+	if (hwc->parent && hwc->parent->setfreq && hwc->parent_freq_req) {
+		unsigned long pfcmin, pfcmax;
+
+		if ((ret = hwc->parent_freq_req(hwc, fcmin, fcmax, &pfcmin, &pfcmax))
+			!= 0)
+			return ret;
+
+		if ((ret = constrain_freq_tree(hwc->parent, pfcmin, pfcmax)) != 0)
+			return ret;
+	}
+
+	if ((constraint = malloc(sizeof(struct hwclock_constraint), M_TEMP,
+							 M_WAITOK)) == NULL)
+		ret = ENOMEM;
+	else {
+		constraint->type = HWCLOCK_FREQ_CONSTRAINT;
+		constraint->freqcons_min = fcmin;
+		constraint->freqcons_max = fcmax;
+		LIST_INSERT_HEAD(&hwc->constraints, constraint, clkconstraints);
+	}
+
+	newmin = hwc->freqcons_min;
+	newmax = hwc->freqcons_max;
+
+	if (fcmin > newmin)
+		newmin = fcmin;
+
+	if (fcmax < newmax)
+		newmax = fcmax;
+
+	if (newmin != hwc->freqcons_min || newmax != hwc->freqcons_max) {
+		hwc->freqcons_min = newmin;
+		hwc->freqcons_max = newmax;
+
+		if (policy_mgr && (newmin != newmax))
+			ret = (*policy_mgr)(hwc, FREQ_CONSTRAINT_CHANGE);
+		else if (hwc->getfreq && hwc->setfreq) {
+			unsigned long curfreq;
+
+			/*
+			 * In the absence of a policy maker: if the current clock
+			 * rate is outside the new constraints, set it to the minimum
+			 * value that satisfies the constraints.
+			 */
+
+			if ((hwc->getfreq(hwc, &curfreq) == 0) &&
+				((curfreq < newmin) || (curfreq > newmax)))
+				ret = (*hwc->setfreq)(hwc, newmin);
+		}
+	}
+
+
+	return ret;
+}
+
+int hwclock_constrain_freq(const char *clockname, unsigned long fcmin,
+						   unsigned long fcmax)
+{
+	struct hwclock *hwc;
+	int ret = 0;
+
+	simple_lock(&hwclocks_lock);
+
+	if ((hwc = clocknamelookup(clockname)) == NULL) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	ret = constrain_freq_tree(hwc, fcmin, fcmax);
+
+out:
+	simple_unlock(&hwclocks_lock);
+	return ret;
+}
+
+
+static int unconstrain_freq_tree(struct hwclock *hwc, unsigned long fcmin,
+								 unsigned long fcmax)
+{
+	struct hwclock_constraint *constraint;
+	struct hwclock_constraint *delconstraint = NULL;
+	unsigned long newmin, newmax;
+	int ret = 0;
+
+	newmin = 0;
+	newmax = (unsigned long) -1;
+
+	LIST_FOREACH(constraint, &hwc->constraints, clkconstraints) {
+		if ((delconstraint == NULL) &&
+			(constraint->type == HWCLOCK_FREQ_CONSTRAINT) &&
+			((constraint->freqcons_min == fcmin) &&
+			 (constraint->freqcons_max == fcmax))) {
+			delconstraint = constraint;
+		} else {
+			if (constraint->freqcons_min > newmin)
+				newmin = constraint->freqcons_min;
+			if (constraint->freqcons_max < newmax)
+				newmax = constraint->freqcons_max;
+		}
+	}
+
+	if (delconstraint != NULL) {
+		LIST_REMOVE(delconstraint, clkconstraints);
+		free(delconstraint, M_TEMP);
+	} else {
+		printf("Error: clock %s freq constraint %lu-%lu not found.\n",
+			   hwc->name, fcmin, fcmax);
+		return EINVAL;
+	}
+
+	if (hwc->freqcons_min != newmin || hwc->freqcons_max != newmax) {
+		hwc->freqcons_min = newmin;
+		hwc->freqcons_max = newmax;
+
+		if (policy_mgr && (newmin != newmax))
+			ret = (*policy_mgr)(hwc, FREQ_CONSTRAINT_CHANGE);
+		else if (hwc->setfreq && (newmin != 0))
+			ret = (*hwc->setfreq)(hwc, newmin);
+	}
+
+	if (hwc->parent && hwc->parent->setfreq && hwc->parent_freq_req) {
+		unsigned long pfcmin, pfcmax;
+
+		if ((ret = hwc->parent_freq_req(hwc, fcmin, fcmax, &pfcmin,
+										&pfcmax)) != 0)
+			return ret;
+
+		if ((ret = unconstrain_freq_tree(hwc->parent, pfcmin, pfcmax)) != 0)
+			return ret;
+	}
+
+	return ret;
+}
+
+int hwclock_unconstrain_freq(const char *clockname, unsigned long fcmin,
+							 unsigned long fcmax)
+{
+	struct hwclock *hwc;
+	int ret = 0;
+
+	simple_lock(&hwclocks_lock);
+
+	if ((hwc = clocknamelookup(clockname)) == NULL) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	ret = unconstrain_freq_tree(hwc, fcmin, fcmax);
+
+out:
+	simple_unlock(&hwclocks_lock);
+	return ret;
+}
+
+
+static int
+constrain_enable_tree(struct hwclock *hwc, unsigned long value)
+{
+	struct hwclock_constraint *constraint;
+	unsigned long oldval;
+	int ret = 0;
+
+	if ((constraint = malloc(sizeof(struct hwclock_constraint), M_TEMP,
+							 M_WAITOK)) == NULL)
+		ret = ENOMEM;
+	else {
+		constraint->type = HWCLOCK_ENABLE_CONSTRAINT;
+		constraint->enabcons_val = value;
+		LIST_INSERT_HEAD(&hwc->constraints, constraint, clkconstraints);
+	}
+
+	if (hwc->parent && hwc->parent->setenable) {
+		if ((ret = constrain_enable_tree(hwc->parent, value)) != 0)
+			return ret;
+	}
+
+	if (hwc->getenable && ((ret = (*hwc->getenable)(hwc, &oldval)) == 0) &&
+		(oldval != value) && hwc->setenable) {
+		ret = (*hwc->setenable)(hwc, value);
+	}
+
+	return ret;
+}
+
+int hwclock_constrain_enable(const char *clockname, unsigned long value)
+{
+	struct hwclock *hwc;
+	int ret = 0;
+
+	simple_lock(&hwclocks_lock);
+
+	if ((hwc = clocknamelookup(clockname)) == NULL) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	ret = constrain_enable_tree(hwc, value);
+
+out:
+	simple_unlock(&hwclocks_lock);
+	return ret;
+}
+
+
+static int unconstrain_enable_tree(struct hwclock *hwc,
+								   unsigned long value)
+{
+	struct hwclock_constraint *constraint;
+	struct hwclock_constraint *delconstraint = NULL;
+	int stillconstrained = 0;
+	int ret = 0;
+
+	LIST_FOREACH(constraint, &hwc->constraints, clkconstraints) {
+		if ((delconstraint == NULL) &&
+			(constraint->type == HWCLOCK_ENABLE_CONSTRAINT) &&
+			(constraint->enabcons_val == value)) {
+			delconstraint = constraint;
+		} else if (constraint->type == HWCLOCK_ENABLE_CONSTRAINT) {
+			stillconstrained = 1;
+		}
+	}
+
+	if (delconstraint != NULL) {
+		LIST_REMOVE(delconstraint, clkconstraints);
+		free(delconstraint, M_TEMP);
+	} else {
+		printf("Error: clock %s enable constraint %lu not found.\n",
+			   hwc->name, value);
+	}
+
+	if (! stillconstrained) {
+		if (policy_mgr)
+			ret = (*policy_mgr)(hwc, ENABLE_CONSTRAINT_DROP);
+		else if ((value == HWCLOCK_ENABLED) && (hwc->setenable))
+			ret = (*hwc->setenable)(hwc, HWCLOCK_DISABLED);
+	}
+
+	if ((ret == 0) && hwc->parent && hwc->setenable)
+		ret = unconstrain_enable_tree(hwc->parent, value);
+
+	return ret;
+}
+
+int hwclock_unconstrain_enable(const char *clockname, unsigned long value)
+{
+	struct hwclock *hwc;
+	int ret = 0;
+
+	simple_lock(&hwclocks_lock);
+
+	if ((hwc = clocknamelookup(clockname)) == NULL) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	ret = unconstrain_enable_tree(hwc, value);
+
+out:
+	simple_unlock(&hwclocks_lock);
+	return ret;
+}
+
+
+int hwclock_setattr(const char *clockname, enum hwclock_arch_attr attr,
+					unsigned long value)
+{
+	struct hwclock *hwc;
+	int ret = 0;
+
+	simple_lock(&hwclocks_lock);
+
+	if (((hwc = clocknamelookup(clockname)) == NULL)
+		|| (! hwc->setattr)) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	ret = (*hwc->setattr)(hwc, attr, value);
+
+out:
+	simple_unlock(&hwclocks_lock);
+	return ret;
+}
+
+
+void hwclock_register(struct hwclock *hwc)
+{
+	simple_lock(&hwclocks_lock);
+	LIST_INSERT_HEAD(&hwclocks, hwc, clks);
+	LIST_INIT(&hwc->constraints);
+	LIST_INIT(&hwc->children);
+
+	if (hwc->parent)
+		LIST_INSERT_HEAD(&hwc->parent->children, hwc, siblings);
+
+	hwc->freqcons_min = 0;
+	hwc->freqcons_max = (unsigned long) -1;
+
+	if (hwc->init)
+		hwc->init(hwc);
+
+	simple_unlock(&hwclocks_lock);
+}
+
+
+void hwclock_unregister(struct hwclock *hwc)
+{
+	simple_lock(&hwclocks_lock);
+	LIST_REMOVE(hwc, clks);
+	simple_unlock(&hwclocks_lock);
+}
+
+
+int hwclock_register_policy_manager(hwclock_policy_mgr_t mgr)
+{
+	policy_mgr = mgr;
+	return 0;
+}
+
+void hwclock_dump_tree(void);
+
+void hwclock_dump_tree(void)
+{
+	struct hwclock *hwc;
+	struct hwclock *hwc2;
+	struct hwclock_constraint *constraint;
+
+	printf("\nhwclock tree...\n");
+
+	simple_lock(&hwclocks_lock);
+	LIST_FOREACH(hwc, &hwclocks, clks) {
+		printf("clock %s", hwc->name);
+
+		if (hwc->getfreq) {
+			unsigned long freq;
+
+			hwc->getfreq(hwc, &freq);
+			printf(" freq=%lu cons %lu-%lu", freq, hwc->freqcons_min,
+				   hwc->freqcons_max);
+		}
+
+		if (hwc->getenable) {
+			unsigned long value;
+
+			hwc->getenable(hwc, &value);
+			printf(" enabled=%lu", value);
+		}
+
+		printf("\n");
+
+		LIST_FOREACH(constraint, &hwc->constraints, clkconstraints) {
+			if (constraint->type == HWCLOCK_FREQ_CONSTRAINT)
+				printf("   freq constraint: %lu-%lu\n",
+					   constraint->freqcons_min, constraint->freqcons_max);
+			else
+				printf("   enable constraint: %s\n",
+					   constraint->enabcons_val == HWCLOCK_DISABLED ?
+					   "disable" : "enable");
+		}
+
+		if (hwc->parent)
+			printf("   parent: %s\n", hwc->parent->name);
+
+		if (! LIST_EMPTY(&hwc->children)) {
+				printf("   children: ");
+
+				LIST_FOREACH(hwc2, &hwc->children, siblings)
+					printf("%s ", hwc2->name);
+
+				printf("\n");
+			}
+	}
+
+	simple_unlock(&hwclocks_lock);
+}
diff --exclude CVS -ruN ../../netbsd_40/src/sys/sys/hwclock.h sys/sys/hwclock.h
--- ../../netbsd_40/src/sys/sys/hwclock.h	1969-12-31 16:00:00.000000000 -0800
+++ sys/sys/hwclock.h	2007-09-25 10:55:22.000000000 -0700
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2007 Danger Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by Danger Inc.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _SYS_HWCLOCK_H_
+#define _SYS_HWCLOCK_H_
+
+#include <sys/queue.h>
+#include "opt_hwclock_machine.h"
+
+#if defined(HWCLOCK_MACHINE)
+#include HWCLOCK_MACHINE
+#else
+#error "HWCLOCK_MACHINE not defined"
+#endif
+
+#define HWCLOCK_DISABLED 0
+#define HWCLOCK_ENABLED 1
+
+enum hwclock_constraint_type {
+	HWCLOCK_FREQ_CONSTRAINT,
+	HWCLOCK_ENABLE_CONSTRAINT,
+};
+
+struct hwclock_constraint {
+	enum hwclock_constraint_type type;
+	unsigned long freqcons_min;
+	unsigned long freqcons_max;
+	unsigned long enabcons_val;
+	LIST_ENTRY(hwclock_constraint) clkconstraints;
+};
+
+
+struct hwclock {
+	const char *name;
+	struct hwclock_machine machine;
+	unsigned long freqcons_min;
+	unsigned long freqcons_max;
+	int (*setfreq)(struct hwclock *hwc, unsigned long freq);
+	int (*getfreq)(struct hwclock *hwc, unsigned long *freq);
+	int (*setenable)(struct hwclock *hwc, unsigned long val);
+	int (*getenable)(struct hwclock *hwc, unsigned long *val);
+	int (*setattr)(struct hwclock *hwc, enum hwclock_arch_attr attr,
+				   unsigned long val);
+	int (*parent_freq_req)(struct hwclock *hwc, unsigned long fcmin,
+						   unsigned long fcmax, unsigned long *pfcmin,
+						   unsigned long *pfcmax);
+	void (*init)(struct hwclock *hwc);
+	LIST_HEAD(, hwclock_constraint) constraints;
+	LIST_ENTRY(hwclock) clks;
+	struct hwclock *parent;
+	LIST_HEAD(, hwclock) children;
+	LIST_ENTRY(hwclock) siblings;
+};
+
+enum hwclock_policy_action {
+	FREQ_CONSTRAINT_CHANGE,
+	ENABLE_CONSTRAINT_DROP,
+};
+
+typedef int (*hwclock_policy_mgr_t)(struct hwclock *hwc,
+									enum hwclock_policy_action action);
+
+extern void hwclock_register(struct hwclock *hwc);
+extern void hwclock_unregister(struct hwclock *hwc);
+extern int hwclock_getfreq(const char *clockname, unsigned long *freq);
+extern int hwclock_setfreq(const char *clockname, unsigned long freq);
+extern int hwclock_constrain_freq(const char *clockname, unsigned long cmin,
+								  unsigned long cmax);
+extern int hwclock_unconstrain_freq(const char *clockname, unsigned long cmin,
+									unsigned long cmax);
+extern int hwclock_getenable(const char *clockname, unsigned long *value);
+extern int hwclock_setenable(const char *clockname, unsigned long value);
+extern int hwclock_constrain_enable(const char *clockname,
+									unsigned long value);
+extern int hwclock_unconstrain_enable(const char *clockname,
+									  unsigned long value);
+extern int hwclock_setattr(const char *clockname, enum hwclock_arch_attr attr,
+						   unsigned long value);
+extern int hwclock_register_policy_manager(hwclock_policy_mgr_t mgr);
+
+#endif /* _SYS_HWCLOCK_H_ */

>Release-Note:

>Audit-Trail:

Responsible-Changed-From-To: port-arm-maintainer->matt
Responsible-Changed-By: matt@netbsd.org
Responsible-Changed-When: Thu, 27 Sep 2007 00:09:26 +0000
Responsible-Changed-Why:
I took ownership


State-Changed-From-To: open->feedback
State-Changed-By: skrll@NetBSD.org
State-Changed-When: Tue, 10 Jan 2012 15:13:19 +0000
State-Changed-Why:
matt-armv6 was merged to -current. ok to close?


State-Changed-From-To: feedback->closed
State-Changed-By: dholland@NetBSD.org
State-Changed-When: Sat, 17 Mar 2012 13:06:12 +0000
State-Changed-Why:
Submitter's mail is bouncing.


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2007 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.