Subject: port-arm/37029: Resubmit of patch for SDP2430/ARM1136/ARMV6-VIPT
To: None <port-arm-maintainer@netbsd.org, gnats-admin@netbsd.org,>
From: None <mfouts@danger.com>
List: netbsd-bugs
Date: 09/26/2007 17:25:00
>Number: 37029
>Category: port-arm
>Synopsis: Resubmit of patch for SDP2430/ARM1136/ARMV6-VIPT
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: port-arm-maintainer
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Sep 26 17:25:00 +0000 2007
>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_ */