summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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_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")
MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
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,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
index 76be074944a..1db2855e3e5 100644
--- a/arch/arm/mach-s3c2410/mach-vr1000.c
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c
@@ -371,16 +371,12 @@ void __init vr1000_map_io(void)
usb_simtec_init();
}
-void __init vr1000_init_irq(void)
-{
- s3c24xx_init_irq();
-}
MACHINE_START(VR1000, "Thorcom-VR1000")
MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
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,
MACHINE_END
diff --git a/arch/arm/mach-s3c2410/pm-simtec.c b/arch/arm/mach-s3c2410/pm-simtec.c
new file mode 100644
index 00000000000..2cb79883222
--- /dev/null
+++ b/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);
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 9d1f2253e98..f01c0f8a2bb 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -33,6 +33,7 @@
#include <asm/mach-types.h>
#include <asm/hardware/amba.h>
#include <asm/hardware/amba_clcd.h>
+#include <asm/hardware/arm_timer.h>
#include <asm/hardware/icst307.h>
#include <asm/mach/arch.h>
@@ -788,38 +789,25 @@ void __init versatile_init(void)
*/
#define TIMER_INTERVAL (TICKS_PER_uSEC * mSEC_10)
#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)
#elif TIMER_INTERVAL >= 0x10000
#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)
#else
#define TIMER_RELOAD (TIMER_INTERVAL)
-#define TIMER_CTRL 0x80 /* Enable */
+#define TIMER_DIVISOR (TIMER_CTRL_DIV1)
#define TICKS2USECS(x) ((x) / TICKS_PER_uSEC)
#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
* will have been disabled by do_gettimeoffset()
*/
static unsigned long versatile_gettimeoffset(void)
{
- volatile TimerStruct_t *timer0 = (TimerStruct_t *)TIMER0_VA_BASE;
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
* counter has not reloaded between our two reads.
*/
- ticks2 = timer0->TimerValue & 0xffff;
+ ticks2 = readl(TIMER0_VA_BASE + TIMER_VALUE) & 0xffff;
do {
ticks1 = ticks2;
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);
/*
@@ -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)
{
- volatile TimerStruct_t *timer0 = (volatile TimerStruct_t *)TIMER0_VA_BASE;
-
write_seqlock(&xtime_lock);
// ...clear the interrupt
- timer0->TimerClear = 1;
+ writel(1, TIMER0_VA_BASE + TIMER_INTCLR);
timer_tick(regs);
@@ -884,31 +870,32 @@ static struct irqaction versatile_timer_irq = {
*/
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:
* VERSATILE_REFCLK is 32KHz
* 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)
*/
- 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
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 6dcb23d64bf..edffa47a4b2 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -437,7 +437,7 @@ void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc)
memtable_init(mi);
if (mdesc->map_io)
mdesc->map_io();
- flush_tlb_all();
+ local_flush_tlb_all();
/*
* initialise the zones within each node
diff --git a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
index 052ab443ec4..c3bd503b43a 100644
--- a/arch/arm/mm/mm-armv.c
+++ b/arch/arm/mm/mm-armv.c
@@ -682,7 +682,7 @@ void __init memtable_init(struct meminfo *mi)
}
flush_cache_all();
- flush_tlb_all();
+ local_flush_tlb_all();
top_pmd = pmd_off_k(0xffff0000);
}
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index 55a02bc994a..4b97950984e 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -117,7 +117,13 @@ static inline u64 vfp_estimate_div128to64(u64 nh, u64 nl, u64 m)
if (nh >= m)
return ~0ULL;
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);
sub128(&remh, &reml, nh, nl, termh, terml);
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);
}
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;
}
diff --git a/arch/arm/vfp/vfpdouble.c b/arch/arm/vfp/vfpdouble.c
index fa3053e84db..b801cd66b6e 100644
--- a/arch/arm/vfp/vfpdouble.c
+++ b/arch/arm/vfp/vfpdouble.c
@@ -32,6 +32,8 @@
*/
#include <linux/kernel.h>
#include <linux/bitops.h>
+
+#include <asm/div64.h>
#include <asm/ptrace.h>
#include <asm/vfp.h>
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 3aeedd2afc7..22f3da4e082 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/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.trap_no = 6;
- force_sig_info(SIGFPE, &info, current);
+ send_sig_info(SIGFPE, &info, current);
}
static void vfp_panic(char *reason)
diff --git a/arch/arm/vfp/vfpsingle.c b/arch/arm/vfp/vfpsingle.c
index 6849fe35cb2..14dd696ddeb 100644
--- a/arch/arm/vfp/vfpsingle.c
+++ b/arch/arm/vfp/vfpsingle.c
@@ -32,6 +32,8 @@
*/
#include <linux/kernel.h>
#include <linux/bitops.h>
+
+#include <asm/div64.h>
#include <asm/ptrace.h>
#include <asm/vfp.h>
@@ -303,7 +305,11 @@ u32 vfp_estimate_sqrt_significand(u32 exponent, u32 significand)
if (z <= a)
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)
@@ -1107,7 +1113,11 @@ static u32 vfp_single_fdiv(int sd, int sn, s32 m, u32 fpscr)
vsn.significand >>= 1;
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)
vsd.significand |= ((u64)vsm.significand * vsd.significand != (u64)vsn.significand << 32);
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 2e28c201dcc..942a2819576 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -68,7 +68,6 @@ struct etherh_priv {
void __iomem *dma_base;
unsigned int id;
void __iomem *ctrl_port;
- void __iomem *base;
unsigned char ctrl;
u32 supported;
};
@@ -178,7 +177,7 @@ etherh_setif(struct net_device *dev)
switch (etherh_priv(dev)->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
- addr = etherh_priv(dev)->base + EN0_RCNTHI;
+ addr = (void *)dev->base_addr + EN0_RCNTHI;
switch (dev->if_port) {
case IF_PORT_10BASE2:
@@ -219,7 +218,7 @@ etherh_getifstat(struct net_device *dev)
switch (etherh_priv(dev)->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
- addr = etherh_priv(dev)->base + EN0_RCNTHI;
+ addr = (void *)dev->base_addr + EN0_RCNTHI;
switch (dev->if_port) {
case IF_PORT_10BASE2:
stat = 1;
@@ -282,7 +281,7 @@ static void
etherh_reset(struct net_device *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);
@@ -328,7 +327,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
ei_local->dmaing = 1;
- addr = etherh_priv(dev)->base;
+ addr = (void *)dev->base_addr;
dma_base = etherh_priv(dev)->dma_base;
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;
- addr = etherh_priv(dev)->base;
+ addr = (void *)dev->base_addr;
dma_base = etherh_priv(dev)->dma_base;
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;
- addr = etherh_priv(dev)->base;
+ addr = (void *)dev->base_addr;
dma_base = etherh_priv(dev)->dma_base;
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->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->ctrl_port += data->ctrlport_offset;
diff --git a/include/asm-arm/arch-pxa/debug-macro.S b/include/asm-arm/arch-pxa/debug-macro.S
index f288e74b67c..b6ec6887917 100644
--- a/include/asm-arm/arch-pxa/debug-macro.S
+++ b/include/asm-arm/arch-pxa/debug-macro.S
@@ -11,6 +11,8 @@
*
*/
+#include "hardware.h"
+
.macro addruart,rx
mrc p15, 0, \rx, c1, c0
tst \rx, #1 @ MMU enabled?
diff --git a/include/asm-arm/hardware/arm_timer.h b/include/asm-arm/hardware/arm_timer.h
new file mode 100644
index 00000000000..04be3bdf46b
--- /dev/null
+++ b/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
diff --git a/include/asm-arm/system.h b/include/asm-arm/system.h
index 3d0d2860b6d..cdf49f442fd 100644
--- a/include/asm-arm/system.h
+++ b/include/asm-arm/system.h
@@ -290,7 +290,6 @@ do { \
})
#ifdef CONFIG_SMP
-#error SMP not supported
#define smp_mb() mb()
#define smp_rmb() rmb()
@@ -304,6 +303,8 @@ do { \
#define smp_wmb() barrier()
#define smp_read_barrier_depends() do { } while(0)
+#endif /* CONFIG_SMP */
+
#if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110)
/*
* 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
* 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
#endif
+#endif
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;
}
-#endif /* CONFIG_SMP */
-
#endif /* __ASSEMBLY__ */
#define arch_align_stack(x) (x)
diff --git a/include/asm-arm/tlbflush.h b/include/asm-arm/tlbflush.h
index 8a864b11856..9387a5e1ffe 100644
--- a/include/asm-arm/tlbflush.h
+++ b/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)))
-static inline void flush_tlb_all(void)
+static inline void local_flush_tlb_all(void)
{
const int zero = 0;
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));
}
-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 asid = ASID(mm);
@@ -282,7 +282,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
}
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 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));
}
-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 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.
*/
-#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