aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-29 20:59:55 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-29 20:59:55 -0700
commit92dd7ca0af8f769569bde98a83b4a8f4daec6ac5 (patch)
tree9217bee214128a4a45b2e0a3d9784d05fea2c8fb
parent164cad9bacc2cf190493d2ee4918dc2869ba6f53 (diff)
parentda41119af78864d27ccbf505949df788d5e8aaf5 (diff)
Merge master.kernel.org:/home/rmk/linux-2.6-arm
-rw-r--r--arch/arm/kernel/armksyms.c6
-rw-r--r--arch/arm/kernel/setup.c3
-rw-r--r--arch/arm/kernel/smp.c123
-rw-r--r--arch/arm/lib/Makefile2
-rw-r--r--arch/arm/lib/longlong.h183
-rw-r--r--arch/arm/lib/udivdi3.c222
-rw-r--r--arch/arm/mach-integrator/core.c41
-rw-r--r--arch/arm/mach-omap/pm.c16
-rw-r--r--arch/arm/mach-omap/time.c44
-rw-r--r--arch/arm/mach-s3c2410/Kconfig5
-rw-r--r--arch/arm/mach-s3c2410/Makefile1
-rw-r--r--arch/arm/mach-s3c2410/devs.c4
-rw-r--r--arch/arm/mach-s3c2410/mach-bast.c39
-rw-r--r--arch/arm/mach-s3c2410/mach-vr1000.c8
-rw-r--r--arch/arm/mach-s3c2410/pm-simtec.c65
-rw-r--r--arch/arm/mach-versatile/core.c61
-rw-r--r--arch/arm/mm/init.c2
-rw-r--r--arch/arm/mm/mm-armv.c2
-rw-r--r--arch/arm/vfp/vfp.h15
-rw-r--r--arch/arm/vfp/vfpdouble.c2
-rw-r--r--arch/arm/vfp/vfpmodule.c2
-rw-r--r--arch/arm/vfp/vfpsingle.c14
-rw-r--r--drivers/net/arm/etherh.c16
-rw-r--r--include/asm-arm/arch-pxa/debug-macro.S2
-rw-r--r--include/asm-arm/hardware/arm_timer.h21
-rw-r--r--include/asm-arm/system.h12
-rw-r--r--include/asm-arm/tlbflush.h28
27 files changed, 385 insertions, 554 deletions
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 4c38bd8bc29..b713c44c6fb 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -30,9 +30,6 @@ extern void __lshrdi3(void);
extern void __modsi3(void);
extern void __muldi3(void);
extern void __ucmpdi2(void);
-extern void __udivdi3(void);
-extern void __umoddi3(void);
-extern void __udivmoddi4(void);
extern void __udivsi3(void);
extern void __umodsi3(void);
extern void __do_div64(void);
@@ -134,9 +131,6 @@ EXPORT_SYMBOL(__lshrdi3);
EXPORT_SYMBOL(__modsi3);
EXPORT_SYMBOL(__muldi3);
EXPORT_SYMBOL(__ucmpdi2);
-EXPORT_SYMBOL(__udivdi3);
-EXPORT_SYMBOL(__umoddi3);
-EXPORT_SYMBOL(__udivmoddi4);
EXPORT_SYMBOL(__udivsi3);
EXPORT_SYMBOL(__umodsi3);
EXPORT_SYMBOL(__do_div64);
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 8cf733daa80..35b7273cfdb 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -359,7 +359,8 @@ void cpu_init(void)
"I" (offsetof(struct stack, abt[0])),
"I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
"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)
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 34892758f09..a931409c8fe 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -502,3 +502,126 @@ int __init setup_profiling_timer(unsigned int multiplier)
{
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);
+}
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index c0e65833ffc..8725d63e421 100644
--- a/arch/arm/lib/Makefile
+++ b/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 \
testclearbit.o testsetbit.o uaccess.o getuser.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
ifeq ($(CONFIG_CPU_32v3),y)
diff --git a/arch/arm/lib/longlong.h b/arch/arm/lib/longlong.h
deleted file mode 100644
index 90ae647e4d7..00000000000
--- a/arch/arm/lib/longlong.h
+++ /dev/null
@@ -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)
diff --git a/arch/arm/lib/udivdi3.c b/arch/arm/lib/udivdi3.c
deleted file mode 100644
index e343be4c664..00000000000
--- a/arch/arm/lib/udivdi3.c
+++ /dev/null
@@ -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;
-}
diff --git a/arch/arm/mach-integrator/core.c b/arch/arm/mach-integrator/core.c
index 9222e57bd87..dacbf504dae 100644
--- a/arch/arm/mach-integrator/core.c
+++ b/arch/arm/mach-integrator/core.c
@@ -20,6 +20,7 @@
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/hardware/amba.h>
+#include <asm/hardware/arm_timer.h>
#include <asm/arch/cm.h>
#include <asm/system.h>
#include <asm/leds.h>
@@ -156,16 +157,6 @@ EXPORT_SYMBOL(cm_control);
#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
#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;
/*
@@ -174,7 +165,6 @@ static unsigned long timer_reload;
*/
unsigned long integrator_gettimeoffset(void)
{
- volatile TimerStruct_t *timer1 = (TimerStruct_t *)TIMER1_VA_BASE;
unsigned long ticks1, ticks2, status;
/*
@@ -183,11 +173,11 @@ unsigned long integrator_gettimeoffset(void)
* an interrupt. We get around this by ensuring that the
* counter has not reloaded between our two reads.
*/
- ticks2 = timer1->TimerValue & 0xffff;
+ ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff;
do {
ticks1 = ticks2;
status = __raw_readl(VA_IC_BASE + IRQ_RAW_STATUS);
- ticks2 = timer1->TimerValue & 0xffff;
+ ticks2 = readl(TIMER1_VA_BASE + TIMER_VALUE) & 0xffff;
} while (ticks2 > ticks1);
/*
@@ -213,14 +203,12 @@ unsigned long integrator_gettimeoffset(void)
static irqreturn_t
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);
/*
* clear the interrupt
*/
- timer1->TimerClear = 1;
+ writel(1, TIMER1_VA_BASE + TIMER_INTCLR);
/*
* 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)
{
- 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_ctrl |= ctrl;
if (timer_reload > 0x100000) {
timer_reload >>= 8;
- timer_ctrl |= 0x08; /* /256 */
+ timer_ctrl |= TIMER_CTRL_DIV256;
} else if (timer_reload > 0x010000) {
timer_reload >>= 4;
- timer_ctrl |= 0x04; /* /16 */
+ timer_ctrl |= TIMER_CTRL_DIV16;
}
/*
* 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
diff --git a/arch/arm/mach-omap/pm.c b/arch/arm/mach-omap/pm.c
index 00fac155df2..6b03ccdc1e9 100644
--- a/arch/arm/mach-omap/pm.c
+++ b/arch/arm/mach-omap/pm.c
@@ -41,7 +41,9 @@
#include <linux/pm.h>
#include <asm/io.h>
+#include <asm/mach/time.h>
#include <asm/mach-types.h>
+
#include <asm/arch/omap16xx.h>
#include <asm/arch/pm.h>
#include <asm/arch/mux.h>
@@ -80,13 +82,13 @@ void omap_pm_idle(void)
return;
}
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) {
__asm__ volatile ("mcr p15, 0, r0, c7, c0, 4");
@@ -102,6 +104,8 @@ void omap_pm_idle(void)
func_ptr();
}
+ local_fiq_enable();
+ local_irq_enable();
}
/*
diff --git a/arch/arm/mach-omap/time.c b/arch/arm/mach-omap/time.c
index 589e8b2740d..dd34e9f4c41 100644
--- a/arch/arm/mach-omap/time.c
+++ b/arch/arm/mach-omap/time.c
@@ -4,7 +4,7 @@
* OMAP Timers
*
* 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
* Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
*
@@ -261,7 +261,6 @@ unsigned long long sched_clock(void)
* so with HZ = 100, TVR = 327.68.
*/
#define OMAP_32K_TIMER_TICK_PERIOD ((32768 / HZ) - 1)
-#define MAX_SKIP_JIFFIES 25
#define TIMER_32K_SYNCHRONIZED 0xfffbc410
#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;
}
+#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 = {
.name = "32KHz 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)
{
+
+#ifdef CONFIG_NO_IDLE_HZ
+ omap_timer.dyn_tick = &omap_dyn_tick_timer;
+#endif
+
setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
omap_timer.offset = omap_32k_timer_gettimeoffset;
omap_32k_last_tick = omap_32k_sync_timer_read();
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
index 534df0c6c77..d4d03d0daae 100644
--- a/arch/arm/mach-s3c2410/Kconfig
+++ b/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
faults with better precision.
+config PM_SIMTEC
+ bool
+ depends on PM && (ARCH_BAST || MACH_VR1000)
+ default y
+
config S3C2410_LOWLEVEL_UART_PORT
int "S3C2410 UART to use for low-level messages"
default 0
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
index 7c379aad5d6..f99b689e439 100644
--- a/arch/arm/mach-s3c2410/Makefile
+++ b/arch/arm/mach-s3c2410/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_S3C2410_DMA) += dma.o
# Power Management support
obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
# S3C2440 support
diff --git a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
index 64792f67866..4664bd11adc 100644
--- a/arch/arm/mach-s3c2410/devs.c
+++ b/arch/arm/mach-s3c2410/devs.c
@@ -96,8 +96,8 @@ struct platform_device s3c_device_lcd = {
.num_resources = ARRAY_SIZE(s3c_lcd_resource),
.resource = s3c_lcd_resource,
.dev = {
- .dma_mask = &s3c_device_lcd_dmamask,
- .coherent_dma_mask = 0xffffffffUL
+ .dma_mask = &s3c_device_lcd_dmamask,
+ .coherent_dma_mask = 0xffffffffUL
}
};
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
index f3e970039b6..549bcb1f32c 100644
--- a/arch/arm/mach-s3c2410/mach-bast.c
+++ b/arch/arm/mach-s3c2410/mach-bast.c
@@ -27,6 +27,7 @@
* 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
* 14-Mar-2006 BJD Updated for __iomem changes
* 22-Jun-2006 BJD Added DM9000 platform information
+ * 28-Jun-2006 BJD Moved pm functionality out to common code
*/
#include <linux/kernel.h>
@@ -67,7 +68,6 @@
#include "devs.h"
#include "cpu.h"
#include "usb-simtec.h"
-#include "pm.h"
#define COPYRIGHT ", (c) 2004-2005 Simtec Electronics"
@@ -405,44 +405,13 @@ void __init bast_map_io(void)
usb_simtec_init();
}
-void __init bast_init_