mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 23:29:46 +00:00
Merge master.kernel.org:/home/rmk/linux-2.6-arm
This commit is contained in:
commit
92dd7ca0af
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
65
arch/arm/mach-s3c2410/pm-simtec.c
Normal file
65
arch/arm/mach-s3c2410/pm-simtec.c
Normal file
@ -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);
|
@ -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;
|
||||
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);
|
||||
|
||||
timer0->TimerLoad = TIMER_RELOAD;
|
||||
timer0->TimerValue = TIMER_RELOAD;
|
||||
timer0->TimerControl = TIMER_CTRL | 0x40 | TIMER_CTRL_IE; /* periodic + IE */
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,8 @@
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <asm/div64.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/vfp.h>
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -11,6 +11,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
.macro addruart,rx
|
||||
mrc p15, 0, \rx, c1, c0
|
||||
tst \rx, #1 @ MMU enabled?
|
||||
|
21
include/asm-arm/hardware/arm_timer.h
Normal file
21
include/asm-arm/hardware/arm_timer.h
Normal file
@ -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
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user