Explorar o código

Merge master.kernel.org:/home/rmk/linux-2.6-arm

Linus Torvalds %!s(int64=20) %!d(string=hai) anos
pai
achega
92dd7ca0af

+ 0 - 6
arch/arm/kernel/armksyms.c

@@ -30,9 +30,6 @@ extern void __lshrdi3(void);
 extern void __modsi3(void);
 extern void __modsi3(void);
 extern void __muldi3(void);
 extern void __muldi3(void);
 extern void __ucmpdi2(void);
 extern void __ucmpdi2(void);
-extern void __udivdi3(void);
-extern void __umoddi3(void);
-extern void __udivmoddi4(void);
 extern void __udivsi3(void);
 extern void __udivsi3(void);
 extern void __umodsi3(void);
 extern void __umodsi3(void);
 extern void __do_div64(void);
 extern void __do_div64(void);
@@ -134,9 +131,6 @@ EXPORT_SYMBOL(__lshrdi3);
 EXPORT_SYMBOL(__modsi3);
 EXPORT_SYMBOL(__modsi3);
 EXPORT_SYMBOL(__muldi3);
 EXPORT_SYMBOL(__muldi3);
 EXPORT_SYMBOL(__ucmpdi2);
 EXPORT_SYMBOL(__ucmpdi2);
-EXPORT_SYMBOL(__udivdi3);
-EXPORT_SYMBOL(__umoddi3);
-EXPORT_SYMBOL(__udivmoddi4);
 EXPORT_SYMBOL(__udivsi3);
 EXPORT_SYMBOL(__udivsi3);
 EXPORT_SYMBOL(__umodsi3);
 EXPORT_SYMBOL(__umodsi3);
 EXPORT_SYMBOL(__do_div64);
 EXPORT_SYMBOL(__do_div64);

+ 2 - 1
arch/arm/kernel/setup.c

@@ -359,7 +359,8 @@ void cpu_init(void)
 	      "I" (offsetof(struct stack, abt[0])),
 	      "I" (offsetof(struct stack, abt[0])),
 	      "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
 	      "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
 	      "I" (offsetof(struct stack, und[0])),
 	      "I" (offsetof(struct stack, und[0])),
-	      "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE));
+	      "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
+	    : "r14");
 }
 }
 
 
 static struct machine_desc * __init setup_machine(unsigned int nr)
 static struct machine_desc * __init setup_machine(unsigned int nr)

+ 123 - 0
arch/arm/kernel/smp.c

@@ -502,3 +502,126 @@ int __init setup_profiling_timer(unsigned int multiplier)
 {
 {
 	return -EINVAL;
 	return -EINVAL;
 }
 }
+
+static int
+on_each_cpu_mask(void (*func)(void *), void *info, int retry, int wait,
+		 cpumask_t mask)
+{
+	int ret = 0;
+
+	preempt_disable();
+
+	ret = smp_call_function_on_cpu(func, info, retry, wait, mask);
+	if (cpu_isset(smp_processor_id(), mask))
+		func(info);
+
+	preempt_enable();
+
+	return ret;
+}
+
+/**********************************************************************/
+
+/*
+ * TLB operations
+ */
+struct tlb_args {
+	struct vm_area_struct *ta_vma;
+	unsigned long ta_start;
+	unsigned long ta_end;
+};
+
+static inline void ipi_flush_tlb_all(void *ignored)
+{
+	local_flush_tlb_all();
+}
+
+static inline void ipi_flush_tlb_mm(void *arg)
+{
+	struct mm_struct *mm = (struct mm_struct *)arg;
+
+	local_flush_tlb_mm(mm);
+}
+
+static inline void ipi_flush_tlb_page(void *arg)
+{
+	struct tlb_args *ta = (struct tlb_args *)arg;
+
+	local_flush_tlb_page(ta->ta_vma, ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_kernel_page(void *arg)
+{
+	struct tlb_args *ta = (struct tlb_args *)arg;
+
+	local_flush_tlb_kernel_page(ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_range(void *arg)
+{
+	struct tlb_args *ta = (struct tlb_args *)arg;
+
+	local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+}
+
+static inline void ipi_flush_tlb_kernel_range(void *arg)
+{
+	struct tlb_args *ta = (struct tlb_args *)arg;
+
+	local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
+}
+
+void flush_tlb_all(void)
+{
+	on_each_cpu(ipi_flush_tlb_all, NULL, 1, 1);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	cpumask_t mask = mm->cpu_vm_mask;
+
+	on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, 1, mask);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+{
+	cpumask_t mask = vma->vm_mm->cpu_vm_mask;
+	struct tlb_args ta;
+
+	ta.ta_vma = vma;
+	ta.ta_start = uaddr;
+
+	on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, 1, mask);
+}
+
+void flush_tlb_kernel_page(unsigned long kaddr)
+{
+	struct tlb_args ta;
+
+	ta.ta_start = kaddr;
+
+	on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1, 1);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma,
+                     unsigned long start, unsigned long end)
+{
+	cpumask_t mask = vma->vm_mm->cpu_vm_mask;
+	struct tlb_args ta;
+
+	ta.ta_vma = vma;
+	ta.ta_start = start;
+	ta.ta_end = end;
+
+	on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, 1, mask);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+	struct tlb_args ta;
+
+	ta.ta_start = start;
+	ta.ta_end = end;
+
+	on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1, 1);
+}

+ 1 - 1
arch/arm/lib/Makefile

@@ -11,7 +11,7 @@ lib-y		:= backtrace.o changebit.o csumipv6.o csumpartial.o   \
 		   strnlen_user.o strchr.o strrchr.o testchangebit.o  \
 		   strnlen_user.o strchr.o strrchr.o testchangebit.o  \
 		   testclearbit.o testsetbit.o uaccess.o getuser.o    \
 		   testclearbit.o testsetbit.o uaccess.o getuser.o    \
 		   putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o   \
 		   putuser.o ashldi3.o ashrdi3.o lshrdi3.o muldi3.o   \
-		   ucmpdi2.o udivdi3.o lib1funcs.o div64.o	      \
+		   ucmpdi2.o lib1funcs.o div64.o	              \
 		   io-readsb.o io-writesb.o io-readsl.o io-writesl.o
 		   io-readsb.o io-writesb.o io-readsl.o io-writesl.o
 
 
 ifeq ($(CONFIG_CPU_32v3),y)
 ifeq ($(CONFIG_CPU_32v3),y)

+ 0 - 183
arch/arm/lib/longlong.h

@@ -1,183 +0,0 @@
-/* longlong.h -- based on code from gcc-2.95.3
-
-   definitions for mixed size 32/64 bit arithmetic.
-   Copyright (C) 1991, 92, 94, 95, 96, 1997, 1998 Free Software Foundation, Inc.
-
-   This definition file is free software; you can redistribute it
-   and/or modify it under the terms of the GNU General Public
-   License as published by the Free Software Foundation; either
-   version 2, or (at your option) any later version.
-
-   This definition file is distributed in the hope that it will be
-   useful, but WITHOUT ANY WARRANTY; without even the implied
-   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-   See the GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-/* Borrowed from GCC 2.95.3, I Molton 29/07/01 */
-
-#ifndef SI_TYPE_SIZE
-#define SI_TYPE_SIZE 32
-#endif
-
-#define __BITS4 (SI_TYPE_SIZE / 4)
-#define __ll_B (1L << (SI_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((u32) (t) % __ll_B)
-#define __ll_highpart(t) ((u32) (t) / __ll_B)
-
-/* Define auxiliary asm macros.
-
-   1) umul_ppmm(high_prod, low_prod, multipler, multiplicand)
-   multiplies two u32 integers MULTIPLER and MULTIPLICAND,
-   and generates a two-part u32 product in HIGH_PROD and
-   LOW_PROD.
-
-   2) __umulsidi3(a,b) multiplies two u32 integers A and B,
-   and returns a u64 product.  This is just a variant of umul_ppmm.
-
-   3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
-   denominator) divides a two-word unsigned integer, composed by the
-   integers HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and
-   places the quotient in QUOTIENT and the remainder in REMAINDER.
-   HIGH_NUMERATOR must be less than DENOMINATOR for correct operation.
-   If, in addition, the most significant bit of DENOMINATOR must be 1,
-   then the pre-processor symbol UDIV_NEEDS_NORMALIZATION is defined to 1.
-
-   4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator,
-   denominator).  Like udiv_qrnnd but the numbers are signed.  The
-   quotient is rounded towards 0.
-
-   5) count_leading_zeros(count, x) counts the number of zero-bits from
-   the msb to the first non-zero bit.  This is the number of steps X
-   needs to be shifted left to set the msb.  Undefined for X == 0.
-
-   6) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1,
-   high_addend_2, low_addend_2) adds two two-word unsigned integers,
-   composed by HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and
-   LOW_ADDEND_2 respectively.  The result is placed in HIGH_SUM and
-   LOW_SUM.  Overflow (i.e. carry out) is not stored anywhere, and is
-   lost.
-
-   7) sub_ddmmss(high_difference, low_difference, high_minuend,
-   low_minuend, high_subtrahend, low_subtrahend) subtracts two
-   two-word unsigned integers, composed by HIGH_MINUEND_1 and
-   LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and LOW_SUBTRAHEND_2
-   respectively.  The result is placed in HIGH_DIFFERENCE and
-   LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
-   and is lost.
-
-   If any of these macros are left undefined for a particular CPU,
-   C macros are used.  */
-
-#if defined (__arm__)
-#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
-  __asm__ ("adds	%1, %4, %5					\n\
-	adc	%0, %2, %3"						\
-	   : "=r" ((u32) (sh)),					\
-	     "=&r" ((u32) (sl))					\
-	   : "%r" ((u32) (ah)),					\
-	     "rI" ((u32) (bh)),					\
-	     "%r" ((u32) (al)),					\
-	     "rI" ((u32) (bl)))
-#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
-  __asm__ ("subs	%1, %4, %5					\n\
-	sbc	%0, %2, %3"						\
-	   : "=r" ((u32) (sh)),					\
-	     "=&r" ((u32) (sl))					\
-	   : "r" ((u32) (ah)),					\
-	     "rI" ((u32) (bh)),					\
-	     "r" ((u32) (al)),					\
-	     "rI" ((u32) (bl)))
-#define umul_ppmm(xh, xl, a, b) \
-{register u32 __t0, __t1, __t2;					\
-  __asm__ ("%@ Inlined umul_ppmm					\n\
-	mov	%2, %5, lsr #16						\n\
-	mov	%0, %6, lsr #16						\n\
-	bic	%3, %5, %2, lsl #16					\n\
-	bic	%4, %6, %0, lsl #16					\n\
-	mul	%1, %3, %4						\n\
-	mul	%4, %2, %4						\n\
-	mul	%3, %0, %3						\n\
-	mul	%0, %2, %0						\n\
-	adds	%3, %4, %3						\n\
-	addcs	%0, %0, #65536						\n\
-	adds	%1, %1, %3, lsl #16					\n\
-	adc	%0, %0, %3, lsr #16"					\
-	   : "=&r" ((u32) (xh)),					\
-	     "=r" ((u32) (xl)),					\
-	     "=&r" (__t0), "=&r" (__t1), "=r" (__t2)			\
-	   : "r" ((u32) (a)),					\
-	     "r" ((u32) (b)));}
-#define UMUL_TIME 20
-#define UDIV_TIME 100
-#endif				/* __arm__ */
-
-#define __umulsidi3(u, v) \
-  ({DIunion __w;							\
-    umul_ppmm (__w.s.high, __w.s.low, u, v);				\
-    __w.ll; })
-
-#define __udiv_qrnnd_c(q, r, n1, n0, d) \
-  do {									\
-    u32 __d1, __d0, __q1, __q0;					\
-    u32 __r1, __r0, __m;						\
-    __d1 = __ll_highpart (d);						\
-    __d0 = __ll_lowpart (d);						\
-									\
-    __r1 = (n1) % __d1;							\
-    __q1 = (n1) / __d1;							\
-    __m = (u32) __q1 * __d0;					\
-    __r1 = __r1 * __ll_B | __ll_highpart (n0);				\
-    if (__r1 < __m)							\
-      {									\
-	__q1--, __r1 += (d);						\
-	if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
-	  if (__r1 < __m)						\
-	    __q1--, __r1 += (d);					\
-      }									\
-    __r1 -= __m;							\
-									\
-    __r0 = __r1 % __d1;							\
-    __q0 = __r1 / __d1;							\
-    __m = (u32) __q0 * __d0;					\
-    __r0 = __r0 * __ll_B | __ll_lowpart (n0);				\
-    if (__r0 < __m)							\
-      {									\
-	__q0--, __r0 += (d);						\
-	if (__r0 >= (d))						\
-	  if (__r0 < __m)						\
-	    __q0--, __r0 += (d);					\
-      }									\
-    __r0 -= __m;							\
-									\
-    (q) = (u32) __q1 * __ll_B | __q0;				\
-    (r) = __r0;								\
-  } while (0)
-
-#define UDIV_NEEDS_NORMALIZATION 1
-#define udiv_qrnnd __udiv_qrnnd_c
-
-#define count_leading_zeros(count, x) \
-  do {									\
-    u32 __xr = (x);							\
-    u32 __a;							\
-									\
-    if (SI_TYPE_SIZE <= 32)						\
-      {									\
-	__a = __xr < ((u32)1<<2*__BITS4)				\
-	  ? (__xr < ((u32)1<<__BITS4) ? 0 : __BITS4)		\
-	  : (__xr < ((u32)1<<3*__BITS4) ?  2*__BITS4 : 3*__BITS4);	\
-      }									\
-    else								\
-      {									\
-	for (__a = SI_TYPE_SIZE - 8; __a > 0; __a -= 8)			\
-	  if (((__xr >> __a) & 0xff) != 0)				\
-	    break;							\
-      }									\
-									\
-    (count) = SI_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a);		\
-  } while (0)

+ 0 - 222
arch/arm/lib/udivdi3.c

@@ -1,222 +0,0 @@
-/* More subroutines needed by GCC output code on some machines.  */
-/* Compile this one with gcc.  */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with other files,
-   some of which are compiled with GCC, to produce an executable,
-   this library does not by itself cause the resulting executable
-   to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.
- */
-/* support functions required by the kernel. based on code from gcc-2.95.3 */
-/* I Molton     29/07/01 */
-
-#include "gcclib.h"
-#include "longlong.h"
-
-static const u8 __clz_tab[] = {
-	0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
-	    5, 5, 5, 5, 5, 5, 5, 5,
-	6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
-	    6, 6, 6, 6, 6, 6, 6, 6,
-	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-	    7, 7, 7, 7, 7, 7, 7, 7,
-	7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-	    7, 7, 7, 7, 7, 7, 7, 7,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	    8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	    8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	    8, 8, 8, 8, 8, 8, 8, 8,
-	8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-	    8, 8, 8, 8, 8, 8, 8, 8,
-};
-
-u64 __udivmoddi4(u64 n, u64 d, u64 * rp)
-{
-	DIunion ww;
-	DIunion nn, dd;
-	DIunion rr;
-	u32 d0, d1, n0, n1, n2;
-	u32 q0, q1;
-	u32 b, bm;
-
-	nn.ll = n;
-	dd.ll = d;
-
-	d0 = dd.s.low;
-	d1 = dd.s.high;
-	n0 = nn.s.low;
-	n1 = nn.s.high;
-
-	if (d1 == 0) {
-		if (d0 > n1) {
-			/* 0q = nn / 0D */
-
-			count_leading_zeros(bm, d0);
-
-			if (bm != 0) {
-				/* Normalize, i.e. make the most significant bit of the
-				   denominator set.  */
-
-				d0 = d0 << bm;
-				n1 = (n1 << bm) | (n0 >> (SI_TYPE_SIZE - bm));
-				n0 = n0 << bm;
-			}
-
-			udiv_qrnnd(q0, n0, n1, n0, d0);
-			q1 = 0;
-
-			/* Remainder in n0 >> bm.  */
-		} else {
-			/* qq = NN / 0d */
-
-			if (d0 == 0)
-				d0 = 1 / d0;	/* Divide intentionally by zero.  */
-
-			count_leading_zeros(bm, d0);
-
-			if (bm == 0) {
-				/* From (n1 >= d0) /\ (the most significant bit of d0 is set),
-				   conclude (the most significant bit of n1 is set) /\ (the
-				   leading quotient digit q1 = 1).
-
-				   This special case is necessary, not an optimization.
-				   (Shifts counts of SI_TYPE_SIZE are undefined.)  */
-
-				n1 -= d0;
-				q1 = 1;
-			} else {
-				/* Normalize.  */
-
-				b = SI_TYPE_SIZE - bm;
-
-				d0 = d0 << bm;
-				n2 = n1 >> b;
-				n1 = (n1 << bm) | (n0 >> b);
-				n0 = n0 << bm;
-
-				udiv_qrnnd(q1, n1, n2, n1, d0);
-			}
-
-			/* n1 != d0...  */
-
-			udiv_qrnnd(q0, n0, n1, n0, d0);
-
-			/* Remainder in n0 >> bm.  */
-		}
-
-		if (rp != 0) {
-			rr.s.low = n0 >> bm;
-			rr.s.high = 0;
-			*rp = rr.ll;
-		}
-	} else {
-		if (d1 > n1) {
-			/* 00 = nn / DD */
-
-			q0 = 0;
-			q1 = 0;
-
-			/* Remainder in n1n0.  */
-			if (rp != 0) {
-				rr.s.low = n0;
-				rr.s.high = n1;
-				*rp = rr.ll;
-			}
-		} else {
-			/* 0q = NN / dd */
-
-			count_leading_zeros(bm, d1);
-			if (bm == 0) {
-				/* From (n1 >= d1) /\ (the most significant bit of d1 is set),
-				   conclude (the most significant bit of n1 is set) /\ (the
-				   quotient digit q0 = 0 or 1).
-
-				   This special case is necessary, not an optimization.  */
-
-				/* The condition on the next line takes advantage of that
-				   n1 >= d1 (true due to program flow).  */
-				if (n1 > d1 || n0 >= d0) {
-					q0 = 1;
-					sub_ddmmss(n1, n0, n1, n0, d1, d0);
-				} else
-					q0 = 0;
-
-				q1 = 0;
-
-				if (rp != 0) {
-					rr.s.low = n0;
-					rr.s.high = n1;
-					*rp = rr.ll;
-				}
-			} else {
-				u32 m1, m0;
-				/* Normalize.  */
-
-				b = SI_TYPE_SIZE - bm;
-
-				d1 = (d1 << bm) | (d0 >> b);
-				d0 = d0 << bm;
-				n2 = n1 >> b;
-				n1 = (n1 << bm) | (n0 >> b);
-				n0 = n0 << bm;
-
-				udiv_qrnnd(q0, n1, n2, n1, d1);
-				umul_ppmm(m1, m0, q0, d0);
-
-				if (m1 > n1 || (m1 == n1 && m0 > n0)) {
-					q0--;
-					sub_ddmmss(m1, m0, m1, m0, d1, d0);
-				}
-
-				q1 = 0;
-
-				/* Remainder in (n1n0 - m1m0) >> bm.  */
-				if (rp != 0) {
-					sub_ddmmss(n1, n0, n1, n0, m1, m0);
-					rr.s.low = (n1 << b) | (n0 >> bm);
-					rr.s.high = n1 >> bm;
-					*rp = rr.ll;
-				}
-			}
-		}
-	}
-
-	ww.s.low = q0;
-	ww.s.high = q1;
-	return ww.ll;
-}
-
-u64 __udivdi3(u64 n, u64 d)
-{
-	return __udivmoddi4(n, d, (u64 *) 0);
-}
-
-u64 __umoddi3(u64 u, u64 v)
-{
-	u64 w;
-
-	(void)__udivmoddi4(u, v, &w);
-
-	return w;
-}

+ 13 - 28
arch/arm/mach-integrator/core.c

@@ -20,6 +20,7 @@
 #include <asm/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/io.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba.h>
+#include <asm/hardware/arm_timer.h>
 #include <asm/arch/cm.h>
 #include <asm/arch/cm.h>
 #include <asm/system.h>
 #include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/leds.h>
@@ -156,16 +157,6 @@ EXPORT_SYMBOL(cm_control);
 #define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
 #define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
 #endif
 #endif
 
 
-/*
- * What does it look like?
- */
-typedef struct TimerStruct {
-	unsigned long TimerLoad;
-	unsigned long TimerValue;
-	unsigned long TimerControl;
-	unsigned long TimerClear;
-} TimerStruct_t;
-
 static unsigned long timer_reload;
 static unsigned long timer_reload;
 
 
 /*
 /*
@@ -174,7 +165,6 @@ static unsigned long timer_reload;
  */
  */
 unsigned long integrator_gettimeoffset(void)
 unsigned long integrator_gettimeoffset(void)
 {
 {
-	volatile TimerStruct_t *timer1 = (TimerStruct_t *)TIMER1_VA_BASE;
 	unsigned long ticks1, ticks2, status;
 	unsigned long ticks1, ticks2, status;
 
 
 	/*
 	/*
@@ -183,11 +173,11 @@ unsigned long integrator_gettimeoffset(void)
 	 * an interrupt.  We get around this by ensuring that the
 	 * an interrupt.  We get around this by ensuring that the
 	 * counter has not reloaded between our two reads.
 	 * counter has not reloaded between our two reads.
 	 */
 	 */
-	ticks2 = timer1->TimerValue & 0xffff;
+	ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff;
 	do {
 	do {
 		ticks1 = ticks2;
 		ticks1 = ticks2;
 		status = __raw_readl(VA_IC_BASE + IRQ_RAW_STATUS);
 		status = __raw_readl(VA_IC_BASE + IRQ_RAW_STATUS);
-		ticks2 = timer1->TimerValue & 0xffff;
+		ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff;
 	} while (ticks2 > ticks1);
 	} while (ticks2 > ticks1);
 
 
 	/*
 	/*
@@ -213,14 +203,12 @@ unsigned long integrator_gettimeoffset(void)
 static irqreturn_t
 static irqreturn_t
 integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 {
-	volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
-
 	write_seqlock(&xtime_lock);
 	write_seqlock(&xtime_lock);
 
 
 	/*
 	/*
 	 * clear the interrupt
 	 * clear the interrupt
 	 */
 	 */
-	timer1->TimerClear = 1;
+	writel(1, TIMER1_VA_BASE + TIMER_INTCLR);
 
 
 	/*
 	/*
 	 * the clock tick routines are only processed on the
 	 * the clock tick routines are only processed on the
@@ -256,32 +244,29 @@ static struct irqaction integrator_timer_irq = {
  */
  */
 void __init integrator_time_init(unsigned long reload, unsigned int ctrl)
 void __init integrator_time_init(unsigned long reload, unsigned int ctrl)
 {
 {
-	volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-	volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
-	volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
-	unsigned int timer_ctrl = 0x80 | 0x40;	/* periodic */
+	unsigned int timer_ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
 
 
 	timer_reload = reload;
 	timer_reload = reload;
 	timer_ctrl |= ctrl;
 	timer_ctrl |= ctrl;
 
 
 	if (timer_reload > 0x100000) {
 	if (timer_reload > 0x100000) {
 		timer_reload >>= 8;
 		timer_reload >>= 8;
-		timer_ctrl |= 0x08; /* /256 */
+		timer_ctrl |= TIMER_CTRL_DIV256;
 	} else if (timer_reload > 0x010000) {
 	} else if (timer_reload > 0x010000) {
 		timer_reload >>= 4;
 		timer_reload >>= 4;
-		timer_ctrl |= 0x04; /* /16 */
+		timer_ctrl |= TIMER_CTRL_DIV16;
 	}
 	}
 
 
 	/*
 	/*
 	 * Initialise to a known state (all timers off)
 	 * Initialise to a known state (all timers off)
 	 */
 	 */
-	timer0->TimerControl = 0;
-	timer1->TimerControl = 0;
-	timer2->TimerControl = 0;
+	writel(0, TIMER0_VA_BASE + TIMER_CTRL);
+	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
+	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
 
 
-	timer1->TimerLoad    = timer_reload;
-	timer1->TimerValue   = timer_reload;
-	timer1->TimerControl = timer_ctrl;
+	writel(timer_reload, TIMER1_VA_BASE + TIMER_LOAD);
+	writel(timer_reload, TIMER1_VA_BASE + TIMER_VALUE);
+	writel(timer_ctrl, TIMER1_VA_BASE + TIMER_CTRL);
 
 
 	/*
 	/*
 	 * Make irqs happen for the system timer
 	 * Make irqs happen for the system timer

+ 10 - 6
arch/arm/mach-omap/pm.c

@@ -41,7 +41,9 @@
 #include <linux/pm.h>
 #include <linux/pm.h>
 
 
 #include <asm/io.h>
 #include <asm/io.h>
+#include <asm/mach/time.h>
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
+
 #include <asm/arch/omap16xx.h>
 #include <asm/arch/omap16xx.h>
 #include <asm/arch/pm.h>
 #include <asm/arch/pm.h>
 #include <asm/arch/mux.h>
 #include <asm/arch/mux.h>
@@ -80,13 +82,13 @@ void omap_pm_idle(void)
 		return;
 		return;
 	}
 	}
 	mask32 = omap_readl(ARM_SYSST);
 	mask32 = omap_readl(ARM_SYSST);
-	local_fiq_enable();
-	local_irq_enable();
 
 
-#if defined(CONFIG_OMAP_32K_TIMER) && defined(CONFIG_NO_IDLE_HZ)
-	/* Override timer to use VST for the next cycle */
-	omap_32k_timer_next_vst_interrupt();
-#endif
+	/*
+	 * Since an interrupt may set up a timer, we don't want to
+	 * reprogram the hardware timer with interrupts enabled.
+	 * Re-enable interrupts only after returning from idle.
+	 */
+	timer_dyn_reprogram();
 
 
 	if ((mask32 & DSP_IDLE) == 0) {
 	if ((mask32 & DSP_IDLE) == 0) {
 		__asm__ volatile ("mcr	p15, 0, r0, c7, c0, 4");
 		__asm__ volatile ("mcr	p15, 0, r0, c7, c0, 4");
@@ -102,6 +104,8 @@ void omap_pm_idle(void)
 
 
 		func_ptr();
 		func_ptr();
 	}
 	}
+	local_fiq_enable();
+	local_irq_enable();
 }
 }
 
 
 /*
 /*

+ 42 - 2
arch/arm/mach-omap/time.c

@@ -4,7 +4,7 @@
  * OMAP Timers
  * OMAP Timers
  *
  *
  * Copyright (C) 2004 Nokia Corporation
  * Copyright (C) 2004 Nokia Corporation
- * Partial timer rewrite and additional VST timer support by
+ * Partial timer rewrite and additional dynamic tick timer support by
  * Tony Lindgen <tony@atomide.com> and
  * Tony Lindgen <tony@atomide.com> and
  * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
  * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
  *
  *
@@ -261,7 +261,6 @@ unsigned long long sched_clock(void)
  * so with HZ = 100, TVR = 327.68.
  * so with HZ = 100, TVR = 327.68.
  */
  */
 #define OMAP_32K_TIMER_TICK_PERIOD	((32768 / HZ) - 1)
 #define OMAP_32K_TIMER_TICK_PERIOD	((32768 / HZ) - 1)
-#define MAX_SKIP_JIFFIES		25
 #define TIMER_32K_SYNCHRONIZED		0xfffbc410
 #define TIMER_32K_SYNCHRONIZED		0xfffbc410
 
 
 #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)			\
 #define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)			\
@@ -347,6 +346,42 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
+#ifdef CONFIG_NO_IDLE_HZ
+/*
+ * Programs the next timer interrupt needed. Called when dynamic tick is
+ * enabled, and to reprogram the ticks to skip from pm_idle. Note that
+ * we can keep the timer continuous, and don't need to set it to run in
+ * one-shot mode. This is because the timer will get reprogrammed again
+ * after next interrupt.
+ */
+void omap_32k_timer_reprogram(unsigned long next_tick)
+{
+	omap_32k_timer_start(JIFFIES_TO_HW_TICKS(next_tick, 32768) + 1);
+}
+
+static struct irqaction omap_32k_timer_irq;
+extern struct timer_update_handler timer_update;
+
+static int omap_32k_timer_enable_dyn_tick(void)
+{
+	/* No need to reprogram timer, just use the next interrupt */
+	return 0;
+}
+
+static int omap_32k_timer_disable_dyn_tick(void)
+{
+	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+	return 0;
+}
+
+static struct dyn_tick_timer omap_dyn_tick_timer = {
+	.enable		= omap_32k_timer_enable_dyn_tick,
+	.disable	= omap_32k_timer_disable_dyn_tick,
+	.reprogram	= omap_32k_timer_reprogram,
+	.handler	= omap_32k_timer_interrupt,
+};
+#endif	/* CONFIG_NO_IDLE_HZ */
+
 static struct irqaction omap_32k_timer_irq = {
 static struct irqaction omap_32k_timer_irq = {
 	.name		= "32KHz timer",
 	.name		= "32KHz timer",
 	.flags		= SA_INTERRUPT | SA_TIMER,
 	.flags		= SA_INTERRUPT | SA_TIMER,
@@ -355,6 +390,11 @@ static struct irqaction omap_32k_timer_irq = {
 
 
 static __init void omap_init_32k_timer(void)
 static __init void omap_init_32k_timer(void)
 {
 {
+
+#ifdef CONFIG_NO_IDLE_HZ
+	omap_timer.dyn_tick = &omap_dyn_tick_timer;
+#endif
+
 	setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
 	setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
 	omap_timer.offset  = omap_32k_timer_gettimeoffset;
 	omap_timer.offset  = omap_32k_timer_gettimeoffset;
 	omap_32k_last_tick = omap_32k_sync_timer_read();
 	omap_32k_last_tick = omap_32k_sync_timer_read();

+ 5 - 0
arch/arm/mach-s3c2410/Kconfig

@@ -154,6 +154,11 @@ config S3C2410_PM_CHECK_CHUNKSIZE
 	  the CRC data block will take more memory, but wil identify any
 	  the CRC data block will take more memory, but wil identify any
 	  faults with better precision.
 	  faults with better precision.
 
 
+config PM_SIMTEC
+	bool
+	depends on PM && (ARCH_BAST || MACH_VR1000)
+	default y
+
 config S3C2410_LOWLEVEL_UART_PORT
 config S3C2410_LOWLEVEL_UART_PORT
 	int "S3C2410 UART to use for low-level messages"
 	int "S3C2410 UART to use for low-level messages"
 	default 0
 	default 0

+ 1 - 0
arch/arm/mach-s3c2410/Makefile

@@ -18,6 +18,7 @@ obj-$(CONFIG_S3C2410_DMA)  += dma.o
 # Power Management support
 # Power Management support
 
 
 obj-$(CONFIG_PM)	   += pm.o sleep.o
 obj-$(CONFIG_PM)	   += pm.o sleep.o
+obj-$(CONFIG_PM_SIMTEC)	   += pm-simtec.o
 
 
 # S3C2440 support
 # S3C2440 support
 
 

+ 2 - 2
arch/arm/mach-s3c2410/devs.c

@@ -96,8 +96,8 @@ struct platform_device s3c_device_lcd = {
 	.num_resources	  = ARRAY_SIZE(s3c_lcd_resource),
 	.num_resources	  = ARRAY_SIZE(s3c_lcd_resource),
 	.resource	  = s3c_lcd_resource,
 	.resource	  = s3c_lcd_resource,
 	.dev              = {
 	.dev              = {
-		.dma_mask = &s3c_device_lcd_dmamask,
-		.coherent_dma_mask = 0xffffffffUL
+		.dma_mask		= &s3c_device_lcd_dmamask,
+		.coherent_dma_mask	= 0xffffffffUL
 	}
 	}
 };
 };
 
 

+ 4 - 35
arch/arm/mach-s3c2410/mach-bast.c

@@ -27,6 +27,7 @@
  *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
  *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
  *     14-Mar-2006 BJD  Updated for __iomem changes
  *     14-Mar-2006 BJD  Updated for __iomem changes
  *     22-Jun-2006 BJD  Added DM9000 platform information
  *     22-Jun-2006 BJD  Added DM9000 platform information
+ *     28-Jun-2006 BJD  Moved pm functionality out to common code
 */
 */
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
@@ -67,7 +68,6 @@
 #include "devs.h"
 #include "devs.h"
 #include "cpu.h"
 #include "cpu.h"
 #include "usb-simtec.h"
 #include "usb-simtec.h"
-#include "pm.h"
 
 
 #define COPYRIGHT ", (c) 2004-2005 Simtec Electronics"
 #define COPYRIGHT ", (c) 2004-2005 Simtec Electronics"
 
 
@@ -405,44 +405,13 @@ void __init bast_map_io(void)
 	usb_simtec_init();
 	usb_simtec_init();
 }
 }
 
 
-void __init bast_init_irq(void)
-{
-	s3c24xx_init_irq();
-}
-
-#ifdef CONFIG_PM
-
-/* bast_init_machine
- *
- * enable the power management functions for the EB2410ITX
-*/
-
-static __init void bast_init_machine(void)
-{
-	unsigned long gstatus4;
-
-	printk(KERN_INFO "BAST Power Manangement" COPYRIGHT "\n");
-
-	gstatus4  = (__raw_readl(S3C2410_BANKCON7) & 0x3) << 30;
-	gstatus4 |= (__raw_readl(S3C2410_BANKCON6) & 0x3) << 28;
-	gstatus4 |= (__raw_readl(S3C2410_BANKSIZE) & S3C2410_BANKSIZE_MASK);
-
-	__raw_writel(gstatus4, S3C2410_GSTATUS4);
-
-	s3c2410_pm_init();
-}
-
-#else
-#define bast_init_machine NULL
-#endif
-
 
 
 MACHINE_START(BAST, "Simtec-BAST")
 MACHINE_START(BAST, "Simtec-BAST")
      MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
      MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
      BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
      BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
-     MAPIO(bast_map_io)
-     INITIRQ(bast_init_irq)
-	.init_machine	= bast_init_machine,
+
+	.map_io		= bast_map_io,
+	.init_irq	= s3c24xx_init_irq,
 	.timer		= &s3c24xx_timer,
 	.timer		= &s3c24xx_timer,
 MACHINE_END
 MACHINE_END

+ 2 - 6
arch/arm/mach-s3c2410/mach-vr1000.c

@@ -371,16 +371,12 @@ void __init vr1000_map_io(void)
 	usb_simtec_init();
 	usb_simtec_init();
 }
 }
 
 
-void __init vr1000_init_irq(void)
-{
-	s3c24xx_init_irq();
-}
 
 
 MACHINE_START(VR1000, "Thorcom-VR1000")
 MACHINE_START(VR1000, "Thorcom-VR1000")
      MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
      MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
      BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
      BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
-     MAPIO(vr1000_map_io)
-     INITIRQ(vr1000_init_irq)
+	.map_io		= vr1000_map_io,
+	.init_irq	= s3c24xx_init_irq,
 	.timer		= &s3c24xx_timer,
 	.timer		= &s3c24xx_timer,
 MACHINE_END
 MACHINE_END

+ 65 - 0
arch/arm/mach-s3c2410/pm-simtec.c

@@ -0,0 +1,65 @@
+/* linux/arch/arm/mach-s3c2410/pm-simtec.c
+ *
+ * Copyright (c) 2004 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://armlinux.simtec.co.uk/
+ *
+ * Power Management helpers for Simtec S3C24XX implementations
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+
+#include <asm/arch/map.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/regs-mem.h>
+
+#include <asm/mach-types.h>
+
+#include "pm.h"
+
+#define COPYRIGHT ", (c) 2005 Simtec Electronics"
+
+/* pm_simtec_init
+ *
+ * enable the power management functions
+*/
+
+static __init int pm_simtec_init(void)
+{
+	unsigned long gstatus4;
+
+	/* check which machine we are running on */
+
+	if (!machine_is_bast() && !machine_is_vr1000())
+		return 0;
+
+	printk(KERN_INFO "Simtec Board Power Manangement" COPYRIGHT "\n");
+
+	gstatus4  = (__raw_readl(S3C2410_BANKCON7) & 0x3) << 30;
+	gstatus4 |= (__raw_readl(S3C2410_BANKCON6) & 0x3) << 28;
+	gstatus4 |= (__raw_readl(S3C2410_BANKSIZE) & S3C2410_BANKSIZE_MASK);
+
+	__raw_writel(gstatus4, S3C2410_GSTATUS4);
+
+	return s3c2410_pm_init();
+}
+
+arch_initcall(pm_simtec_init);

+ 24 - 37
arch/arm/mach-versatile/core.c

@@ -33,6 +33,7 @@
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba.h>
 #include <asm/hardware/amba_clcd.h>
 #include <asm/hardware/amba_clcd.h>
+#include <asm/hardware/arm_timer.h>
 #include <asm/hardware/icst307.h>
 #include <asm/hardware/icst307.h>
 
 
 #include <asm/mach/arch.h>
 #include <asm/mach/arch.h>
@@ -788,38 +789,25 @@ void __init versatile_init(void)
  */
  */
 #define TIMER_INTERVAL	(TICKS_PER_uSEC * mSEC_10)
 #define TIMER_INTERVAL	(TICKS_PER_uSEC * mSEC_10)
 #if TIMER_INTERVAL >= 0x100000
 #if TIMER_INTERVAL >= 0x100000
-#define TIMER_RELOAD	(TIMER_INTERVAL >> 8)		/* Divide by 256 */
-#define TIMER_CTRL	0x88				/* Enable, Clock / 256 */
+#define TIMER_RELOAD	(TIMER_INTERVAL >> 8)
+#define TIMER_DIVISOR	(TIMER_CTRL_DIV256)
 #define TICKS2USECS(x)	(256 * (x) / TICKS_PER_uSEC)
 #define TICKS2USECS(x)	(256 * (x) / TICKS_PER_uSEC)
 #elif TIMER_INTERVAL >= 0x10000
 #elif TIMER_INTERVAL >= 0x10000
 #define TIMER_RELOAD	(TIMER_INTERVAL >> 4)		/* Divide by 16 */
 #define TIMER_RELOAD	(TIMER_INTERVAL >> 4)		/* Divide by 16 */
-#define TIMER_CTRL	0x84				/* Enable, Clock / 16 */
+#define TIMER_DIVISOR	(TIMER_CTRL_DIV16)
 #define TICKS2USECS(x)	(16 * (x) / TICKS_PER_uSEC)
 #define TICKS2USECS(x)	(16 * (x) / TICKS_PER_uSEC)
 #else
 #else
 #define TIMER_RELOAD	(TIMER_INTERVAL)
 #define TIMER_RELOAD	(TIMER_INTERVAL)
-#define TIMER_CTRL	0x80				/* Enable */
+#define TIMER_DIVISOR	(TIMER_CTRL_DIV1)
 #define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
 #define TICKS2USECS(x)	((x) / TICKS_PER_uSEC)
 #endif
 #endif
 
 
-#define TIMER_CTRL_IE	(1 << 5)	/* Interrupt Enable */
-
-/*
- * What does it look like?
- */
-typedef struct TimerStruct {
-	unsigned long TimerLoad;
-	unsigned long TimerValue;
-	unsigned long TimerControl;
-	unsigned long TimerClear;
-} TimerStruct_t;
-
 /*
 /*
  * Returns number of ms since last clock interrupt.  Note that interrupts
  * Returns number of ms since last clock interrupt.  Note that interrupts
  * will have been disabled by do_gettimeoffset()
  * will have been disabled by do_gettimeoffset()
  */
  */
 static unsigned long versatile_gettimeoffset(void)
 static unsigned long versatile_gettimeoffset(void)
 {
 {
-	volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE;
 	unsigned long ticks1, ticks2, status;
 	unsigned long ticks1, ticks2, status;
 
 
 	/*
 	/*
@@ -828,11 +816,11 @@ static unsigned long versatile_gettimeoffset(void)
 	 * an interrupt.  We get around this by ensuring that the
 	 * an interrupt.  We get around this by ensuring that the
 	 * counter has not reloaded between our two reads.
 	 * counter has not reloaded between our two reads.
 	 */
 	 */
-	ticks2 = timer0->TimerValue & 0xffff;
+	ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
 	do {
 	do {
 		ticks1 = ticks2;
 		ticks1 = ticks2;
 		status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS);
 		status = __raw_readl(VA_IC_BASE + VIC_IRQ_RAW_STATUS);
-		ticks2 = timer0->TimerValue & 0xffff;
+		ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
 	} while (ticks2 > ticks1);
 	} while (ticks2 > ticks1);
 
 
 	/*
 	/*
@@ -859,12 +847,10 @@ static unsigned long versatile_gettimeoffset(void)
  */
  */
 static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 static irqreturn_t versatile_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 {
-	volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-
 	write_seqlock(&xtime_lock);
 	write_seqlock(&xtime_lock);
 
 
 	// ...clear the interrupt
 	// ...clear the interrupt
-	timer0->TimerClear = 1;
+	writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
 
 
 	timer_tick(regs);
 	timer_tick(regs);
 
 
@@ -884,31 +870,32 @@ static struct irqaction versatile_timer_irq = {
  */
  */
 static void __init versatile_timer_init(void)
 static void __init versatile_timer_init(void)
 {
 {
-	volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-	volatile TimerStruct_t *timer1 = (volatile TimerStruct_t *)TIMER1_VA_BASE;
-	volatile TimerStruct_t *timer2 = (volatile TimerStruct_t *)TIMER2_VA_BASE;
-	volatile TimerStruct_t *timer3 = (volatile TimerStruct_t *)TIMER3_VA_BASE;
+	u32 val;
 
 
 	/* 
 	/* 
 	 * set clock frequency: 
 	 * set clock frequency: 
 	 *	VERSATILE_REFCLK is 32KHz
 	 *	VERSATILE_REFCLK is 32KHz
 	 *	VERSATILE_TIMCLK is 1MHz
 	 *	VERSATILE_TIMCLK is 1MHz
 	 */
 	 */
-	*(volatile unsigned int *)IO_ADDRESS(VERSATILE_SCTL_BASE) |= 
-	  ((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
-	   (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) | (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel));
+	val = readl(IO_ADDRESS(VERSATILE_SCTL_BASE));
+	writel((VERSATILE_TIMCLK << VERSATILE_TIMER1_EnSel) |
+	       (VERSATILE_TIMCLK << VERSATILE_TIMER2_EnSel) | 
+	       (VERSATILE_TIMCLK << VERSATILE_TIMER3_EnSel) |
+	       (VERSATILE_TIMCLK << VERSATILE_TIMER4_EnSel) | val,
+	       IO_ADDRESS(VERSATILE_SCTL_BASE));
 
 
 	/*
 	/*
 	 * Initialise to a known state (all timers off)
 	 * Initialise to a known state (all timers off)
 	 */
 	 */
-	timer0->TimerControl = 0;
-	timer1->TimerControl = 0;
-	timer2->TimerControl = 0;
-	timer3->TimerControl = 0;
-
-	timer0->TimerLoad    = TIMER_RELOAD;
-	timer0->TimerValue   = TIMER_RELOAD;
-	timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE;  /* periodic + IE */
+	writel(0, TIMER0_VA_BASE + TIMER_CTRL);
+	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
+	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
+	writel(0, TIMER3_VA_BASE + TIMER_CTRL);
+
+	writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_LOAD);
+	writel(TIMER_RELOAD, TIMER0_VA_BASE + TIMER_VALUE);
+	writel(TIMER_DIVISOR | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC |
+	       TIMER_CTRL_IE, TIMER0_VA_BASE + TIMER_CTRL);
 
 
 	/* 
 	/* 
 	 * Make irqs happen for the system timer
 	 * Make irqs happen for the system timer

+ 1 - 1
arch/arm/mm/init.c

@@ -437,7 +437,7 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
 	memtable_init(mi);
 	memtable_init(mi);
 	if (mdesc->map_io)
 	if (mdesc->map_io)
 		mdesc->map_io();
 		mdesc->map_io();
-	flush_tlb_all();
+	local_flush_tlb_all();
 
 
 	/*
 	/*
 	 * initialise the zones within each node
 	 * initialise the zones within each node

+ 1 - 1
arch/arm/mm/mm-armv.c

@@ -682,7 +682,7 @@ void __init memtable_init(struct meminfo *mi)
 	}
 	}
 
 
 	flush_cache_all();
 	flush_cache_all();
-	flush_tlb_all();
+	local_flush_tlb_all();
 
 
 	top_pmd = pmd_off_k(0xffff0000);
 	top_pmd = pmd_off_k(0xffff0000);
 }
 }

+ 13 - 2
arch/arm/vfp/vfp.h

@@ -117,7 +117,13 @@ static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
 	if (nh >= m)
 	if (nh >= m)
 		return ~0ULL;
 		return ~0ULL;
 	mh = m >> 32;
 	mh = m >> 32;
-	z = (mh << 32 <= nh) ? 0xffffffff00000000ULL : (nh / mh) << 32;
+	if (mh << 32 <= nh) {
+		z = 0xffffffff00000000ULL;
+	} else {
+		z = nh;
+		do_div(z, mh);
+		z <<= 32;
+	}
 	mul64to128(&termh, &terml, m, z);
 	mul64to128(&termh, &terml, m, z);
 	sub128(&remh, &reml, nh, nl, termh, terml);
 	sub128(&remh, &reml, nh, nl, termh, terml);
 	ml = m << 32;
 	ml = m << 32;
@@ -126,7 +132,12 @@ static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
 		add128(&remh, &reml, remh, reml, mh, ml);
 		add128(&remh, &reml, remh, reml, mh, ml);
 	}
 	}
 	remh = (remh << 32) | (reml >> 32);
 	remh = (remh << 32) | (reml >> 32);
-	z |= (mh << 32 <= remh) ? 0xffffffff : remh / mh;
+	if (mh << 32 <= remh) {
+		z |= 0xffffffff;
+	} else {
+		do_div(remh, mh);
+		z |= remh;
+	}
 	return z;
 	return z;
 }
 }
 
 

+ 2 - 0
arch/arm/vfp/vfpdouble.c

@@ -32,6 +32,8 @@
  */
  */
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/bitops.h>
 #include <linux/bitops.h>
+
+#include <asm/div64.h>
 #include <asm/ptrace.h>
 #include <asm/ptrace.h>
 #include <asm/vfp.h>
 #include <asm/vfp.h>
 
 

+ 1 - 1
arch/arm/vfp/vfpmodule.c

@@ -89,7 +89,7 @@ void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
 	current->thread.error_code = 0;
 	current->thread.error_code = 0;
 	current->thread.trap_no = 6;
 	current->thread.trap_no = 6;
 
 
-	force_sig_info(SIGFPE, &info, current);
+	send_sig_info(SIGFPE, &info, current);
 }
 }
 
 
 static void vfp_panic(char *reason)
 static void vfp_panic(char *reason)

+ 12 - 2
arch/arm/vfp/vfpsingle.c

@@ -32,6 +32,8 @@
  */
  */
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/bitops.h>
 #include <linux/bitops.h>
+
+#include <asm/div64.h>
 #include <asm/ptrace.h>
 #include <asm/ptrace.h>
 #include <asm/vfp.h>
 #include <asm/vfp.h>
 
 
@@ -303,7 +305,11 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
 		if (z <= a)
 		if (z <= a)
 			return (s32)a >> 1;
 			return (s32)a >> 1;
 	}
 	}
-	return (u32)(((u64)a << 31) / z) + (z >> 1);
+	{
+		u64 v = (u64)a << 31;
+		do_div(v, z);
+		return v + (z >> 1);
+	}
 }
 }
 
 
 static u32 vfp_single_fsqrt(int sd, int unused, s32 m, u32 fpscr)
 static u32 vfp_single_fsqrt(int sd, int unused, s32 m, u32 fpscr)
@@ -1107,7 +1113,11 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr)
 		vsn.significand >>= 1;
 		vsn.significand >>= 1;
 		vsd.exponent++;
 		vsd.exponent++;
 	}
 	}
-	vsd.significand = ((u64)vsn.significand << 32) / vsm.significand;
+	{
+		u64 significand = (u64)vsn.significand << 32;
+		do_div(significand, vsm.significand);
+		vsd.significand = significand;
+	}
 	if ((vsd.significand & 0x3f) == 0)
 	if ((vsd.significand & 0x3f) == 0)
 		vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32);
 		vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32);
 
 

+ 7 - 9
drivers/net/arm/etherh.c

@@ -68,7 +68,6 @@ struct etherh_priv {
 	void __iomem	*dma_base;
 	void __iomem	*dma_base;
 	unsigned int	id;
 	unsigned int	id;
 	void __iomem	*ctrl_port;
 	void __iomem	*ctrl_port;
-	void __iomem	*base;
 	unsigned char	ctrl;
 	unsigned char	ctrl;
 	u32		supported;
 	u32		supported;
 };
 };
@@ -178,7 +177,7 @@ etherh_setif(struct net_device *dev)
 	switch (etherh_priv(dev)->id) {
 	switch (etherh_priv(dev)->id) {
 	case PROD_I3_ETHERLAN600:
 	case PROD_I3_ETHERLAN600:
 	case PROD_I3_ETHERLAN600A:
 	case PROD_I3_ETHERLAN600A:
-		addr = etherh_priv(dev)->base + EN0_RCNTHI;
+		addr = (void *)dev->base_addr + EN0_RCNTHI;
 
 
 		switch (dev->if_port) {
 		switch (dev->if_port) {
 		case IF_PORT_10BASE2:
 		case IF_PORT_10BASE2:
@@ -219,7 +218,7 @@ etherh_getifstat(struct net_device *dev)
 	switch (etherh_priv(dev)->id) {
 	switch (etherh_priv(dev)->id) {
 	case PROD_I3_ETHERLAN600:
 	case PROD_I3_ETHERLAN600:
 	case PROD_I3_ETHERLAN600A:
 	case PROD_I3_ETHERLAN600A:
-		addr = etherh_priv(dev)->base + EN0_RCNTHI;
+		addr = (void *)dev->base_addr + EN0_RCNTHI;
 		switch (dev->if_port) {
 		switch (dev->if_port) {
 		case IF_PORT_10BASE2:
 		case IF_PORT_10BASE2:
 			stat = 1;
 			stat = 1;
@@ -282,7 +281,7 @@ static void
 etherh_reset(struct net_device *dev)
 etherh_reset(struct net_device *dev)
 {
 {
 	struct ei_device *ei_local = netdev_priv(dev);
 	struct ei_device *ei_local = netdev_priv(dev);
-	void __iomem *addr = etherh_priv(dev)->base;
+	void __iomem *addr = (void *)dev->base_addr;
 
 
 	writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
 	writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
 
 
@@ -328,7 +327,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
 
 
 	ei_local->dmaing = 1;
 	ei_local->dmaing = 1;
 
 
-	addr = etherh_priv(dev)->base;
+	addr = (void *)dev->base_addr;
 	dma_base = etherh_priv(dev)->dma_base;
 	dma_base = etherh_priv(dev)->dma_base;
 
 
 	count = (count + 1) & ~1;
 	count = (count + 1) & ~1;
@@ -388,7 +387,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
 
 
 	ei_local->dmaing = 1;
 	ei_local->dmaing = 1;
 
 
-	addr = etherh_priv(dev)->base;
+	addr = (void *)dev->base_addr;
 	dma_base = etherh_priv(dev)->dma_base;
 	dma_base = etherh_priv(dev)->dma_base;
 
 
 	buf = skb->data;
 	buf = skb->data;
@@ -428,7 +427,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
 
 
 	ei_local->dmaing = 1;
 	ei_local->dmaing = 1;
 
 
-	addr = etherh_priv(dev)->base;
+	addr = (void *)dev->base_addr;
 	dma_base = etherh_priv(dev)->dma_base;
 	dma_base = etherh_priv(dev)->dma_base;
 
 
 	writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
 	writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
@@ -697,8 +696,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
 		eh->ctrl_port = eh->ioc_fast;
 		eh->ctrl_port = eh->ioc_fast;
 	}
 	}
 
 
-	eh->base = eh->memc + data->ns8390_offset;
-	dev->base_addr = (unsigned long)eh->base;
+	dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
 	eh->dma_base = eh->memc + data->dataport_offset;
 	eh->dma_base = eh->memc + data->dataport_offset;
 	eh->ctrl_port += data->ctrlport_offset;
 	eh->ctrl_port += data->ctrlport_offset;
 
 

+ 2 - 0
include/asm-arm/arch-pxa/debug-macro.S

@@ -11,6 +11,8 @@
  *
  *
 */
 */
 
 
+#include "hardware.h"
+
 		.macro	addruart,rx
 		.macro	addruart,rx
 		mrc	p15, 0, \rx, c1, c0
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1			@ MMU enabled?
 		tst	\rx, #1			@ MMU enabled?

+ 21 - 0
include/asm-arm/hardware/arm_timer.h

@@ -0,0 +1,21 @@
+#ifndef __ASM_ARM_HARDWARE_ARM_TIMER_H
+#define __ASM_ARM_HARDWARE_ARM_TIMER_H
+
+#define TIMER_LOAD	0x00
+#define TIMER_VALUE	0x04
+#define TIMER_CTRL	0x08
+#define TIMER_CTRL_ONESHOT	(1 << 0)
+#define TIMER_CTRL_32BIT	(1 << 1)
+#define TIMER_CTRL_DIV1		(0 << 2)
+#define TIMER_CTRL_DIV16	(1 << 2)
+#define TIMER_CTRL_DIV256	(2 << 2)
+#define TIMER_CTRL_IE		(1 << 5)	/* Interrupt Enable (versatile only) */
+#define TIMER_CTRL_PERIODIC	(1 << 6)
+#define TIMER_CTRL_ENABLE	(1 << 7)
+
+#define TIMER_INTCLR	0x0c
+#define TIMER_RIS	0x10
+#define TIMER_MIS	0x14
+#define TIMER_BGLOAD	0x18
+
+#endif

+ 9 - 3
include/asm-arm/system.h

@@ -290,7 +290,6 @@ do {									\
 })
 })
 
 
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-#error SMP not supported
 
 
 #define smp_mb()		mb()
 #define smp_mb()		mb()
 #define smp_rmb()		rmb()
 #define smp_rmb()		rmb()
@@ -304,6 +303,8 @@ do {									\
 #define smp_wmb()		barrier()
 #define smp_wmb()		barrier()
 #define smp_read_barrier_depends()		do { } while(0)
 #define smp_read_barrier_depends()		do { } while(0)
 
 
+#endif /* CONFIG_SMP */
+
 #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
 #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
 /*
 /*
  * On the StrongARM, "swp" is terminally broken since it bypasses the
  * On the StrongARM, "swp" is terminally broken since it bypasses the
@@ -316,9 +317,16 @@ do {									\
  *
  *
  * We choose (1) since its the "easiest" to achieve here and is not
  * We choose (1) since its the "easiest" to achieve here and is not
  * dependent on the processor type.
  * dependent on the processor type.
+ *
+ * NOTE that this solution won't work on an SMP system, so explcitly
+ * forbid it here.
  */
  */
+#ifdef CONFIG_SMP
+#error SMP is not supported on SA1100/SA110
+#else
 #define swp_is_buggy
 #define swp_is_buggy
 #endif
 #endif
+#endif
 
 
 static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
 {
 {
@@ -361,8 +369,6 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size
 	return ret;
 	return ret;
 }
 }
 
 
-#endif /* CONFIG_SMP */
-
 #endif /* __ASSEMBLY__ */
 #endif /* __ASSEMBLY__ */
 
 
 #define arch_align_stack(x) (x)
 #define arch_align_stack(x) (x)

+ 22 - 6
include/asm-arm/tlbflush.h

@@ -235,7 +235,7 @@ extern struct cpu_tlb_fns cpu_tlb;
 
 
 #define tlb_flag(f)	((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
 #define tlb_flag(f)	((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
 
 
-static inline void flush_tlb_all(void)
+static inline void local_flush_tlb_all(void)
 {
 {
 	const int zero = 0;
 	const int zero = 0;
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
@@ -253,7 +253,7 @@ static inline void flush_tlb_all(void)
 		asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
 		asm("mcr%? p15, 0, %0, c8, c5, 0" : : "r" (zero));
 }
 }
 
 
-static inline void flush_tlb_mm(struct mm_struct *mm)
+static inline void local_flush_tlb_mm(struct mm_struct *mm)
 {
 {
 	const int zero = 0;
 	const int zero = 0;
 	const int asid = ASID(mm);
 	const int asid = ASID(mm);
@@ -282,7 +282,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
 }
 }
 
 
 static inline void
 static inline void
-flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
 {
 {
 	const int zero = 0;
 	const int zero = 0;
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
@@ -313,7 +313,7 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
 		asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr));
 		asm("mcr%? p15, 0, %0, c8, c5, 1" : : "r" (uaddr));
 }
 }
 
 
-static inline void flush_tlb_kernel_page(unsigned long kaddr)
+static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
 {
 {
 	const int zero = 0;
 	const int zero = 0;
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
 	const unsigned int __tlb_flag = __cpu_tlb_flags;
@@ -384,8 +384,24 @@ static inline void clean_pmd_entry(pmd_t *pmd)
 /*
 /*
  * Convert calls to our calling convention.
  * Convert calls to our calling convention.
  */
  */
-#define flush_tlb_range(vma,start,end)	__cpu_flush_user_tlb_range(start,end,vma)
-#define flush_tlb_kernel_range(s,e)	__cpu_flush_kern_tlb_range(s,e)
+#define local_flush_tlb_range(vma,start,end)	__cpu_flush_user_tlb_range(start,end,vma)
+#define local_flush_tlb_kernel_range(s,e)	__cpu_flush_kern_tlb_range(s,e)
+
+#ifndef CONFIG_SMP
+#define flush_tlb_all		local_flush_tlb_all
+#define flush_tlb_mm		local_flush_tlb_mm
+#define flush_tlb_page		local_flush_tlb_page
+#define flush_tlb_kernel_page	local_flush_tlb_kernel_page
+#define flush_tlb_range		local_flush_tlb_range
+#define flush_tlb_kernel_range	local_flush_tlb_kernel_range
+#else
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr);
+extern void flush_tlb_kernel_page(unsigned long kaddr);
+extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
+extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
+#endif
 
 
 /*
 /*
  * if PG_dcache_dirty is set for the page, we need to ensure that any
  * if PG_dcache_dirty is set for the page, we need to ensure that any