Commit 2741ecb4 authored by Russell King's avatar Russell King

Merge branch 'misc2' into devel

parents bc85e585 5de813b6
...@@ -59,7 +59,11 @@ PAGE_OFFSET high_memory-1 Kernel direct-mapped RAM region. ...@@ -59,7 +59,11 @@ PAGE_OFFSET high_memory-1 Kernel direct-mapped RAM region.
This maps the platforms RAM, and typically This maps the platforms RAM, and typically
maps all platform RAM in a 1:1 relationship. maps all platform RAM in a 1:1 relationship.
TASK_SIZE PAGE_OFFSET-1 Kernel module space PKMAP_BASE PAGE_OFFSET-1 Permanent kernel mappings
One way of mapping HIGHMEM pages into kernel
space.
MODULES_VADDR MODULES_END-1 Kernel module space
Kernel modules inserted via insmod are Kernel modules inserted via insmod are
placed here using dynamic mappings. placed here using dynamic mappings.
......
...@@ -12,6 +12,7 @@ config ARM ...@@ -12,6 +12,7 @@ config ARM
select HAVE_IDE select HAVE_IDE
select RTC_LIB select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION select SYS_SUPPORTS_APM_EMULATION
select GENERIC_ATOMIC64 if (!CPU_32v6K)
select HAVE_OPROFILE select HAVE_OPROFILE
select HAVE_ARCH_KGDB select HAVE_ARCH_KGDB
select HAVE_KPROBES if (!XIP_KERNEL) select HAVE_KPROBES if (!XIP_KERNEL)
...@@ -54,6 +55,9 @@ config HAVE_TCM ...@@ -54,6 +55,9 @@ config HAVE_TCM
bool bool
select GENERIC_ALLOCATOR select GENERIC_ALLOCATOR
config HAVE_PROC_CPU
bool
config NO_IOPORT config NO_IOPORT
bool bool
...@@ -163,6 +167,11 @@ config ARCH_MTD_XIP ...@@ -163,6 +167,11 @@ config ARCH_MTD_XIP
config GENERIC_HARDIRQS_NO__DO_IRQ config GENERIC_HARDIRQS_NO__DO_IRQ
def_bool y def_bool y
config ARM_L1_CACHE_SHIFT_6
bool
help
Setting ARM L1 cache line size to 64 Bytes.
if OPROFILE if OPROFILE
config OPROFILE_ARMV6 config OPROFILE_ARMV6
...@@ -649,6 +658,7 @@ config ARCH_S5PC1XX ...@@ -649,6 +658,7 @@ config ARCH_S5PC1XX
select GENERIC_GPIO select GENERIC_GPIO
select HAVE_CLK select HAVE_CLK
select CPU_V7 select CPU_V7
select ARM_L1_CACHE_SHIFT_6
help help
Samsung S5PC1XX series based systems Samsung S5PC1XX series based systems
...@@ -938,6 +948,19 @@ config ARM_ERRATA_460075 ...@@ -938,6 +948,19 @@ config ARM_ERRATA_460075
ACTLR register. Note that setting specific bits in the ACTLR register ACTLR register. Note that setting specific bits in the ACTLR register
may not be available in non-secure mode. may not be available in non-secure mode.
config PL310_ERRATA_588369
bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
depends on CACHE_L2X0 && ARCH_OMAP4
help
The PL310 L2 cache controller implements three types of Clean &
Invalidate maintenance operations: by Physical Address
(offset 0x7F0), by Index/Way (0x7F8) and by Way (0x7FC).
They are architecturally defined to behave as the execution of a
clean operation followed immediately by an invalidate operation,
both performing to the same memory location. This functionality
is not correctly implemented in PL310 as clean lines are not
invalidated as a result of these operations. Note that this errata
uses Texas Instrument's secure monitor api.
endmenu endmenu
source "arch/arm/common/Kconfig" source "arch/arm/common/Kconfig"
...@@ -1255,6 +1278,7 @@ config ALIGNMENT_TRAP ...@@ -1255,6 +1278,7 @@ config ALIGNMENT_TRAP
bool bool
depends on CPU_CP15_MMU depends on CPU_CP15_MMU
default y if !ARCH_EBSA110 default y if !ARCH_EBSA110
select HAVE_PROC_CPU if PROC_FS
help help
ARM processors cannot fetch/store information which is not ARM processors cannot fetch/store information which is not
naturally aligned on the bus, i.e., a 4 byte fetch must start at an naturally aligned on the bus, i.e., a 4 byte fetch must start at an
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# #
HEAD = head.o HEAD = head.o
OBJS = misc.o OBJS = misc.o decompress.o
FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c
# #
...@@ -106,10 +106,6 @@ lib1funcs = $(obj)/lib1funcs.o ...@@ -106,10 +106,6 @@ lib1funcs = $(obj)/lib1funcs.o
$(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S FORCE
$(call cmd,shipped) $(call cmd,shipped)
# Don't allow any static data in misc.o, which
# would otherwise mess up our GOT table
CFLAGS_misc.o := -Dstatic=
$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \
$(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE
$(call if_changed,ld) $(call if_changed,ld)
......
#define _LINUX_STRING_H_
#include <linux/compiler.h> /* for inline */
#include <linux/types.h> /* for size_t */
#include <linux/stddef.h> /* for NULL */
#include <linux/linkage.h>
#include <asm/string.h>
extern unsigned long free_mem_ptr;
extern unsigned long free_mem_end_ptr;
extern void error(char *);
#define STATIC static
#define ARCH_HAS_DECOMP_WDOG
/* Diagnostic functions */
#ifdef DEBUG
# define Assert(cond,msg) {if(!(cond)) error(msg);}
# define Trace(x) fprintf x
# define Tracev(x) {if (verbose) fprintf x ;}
# define Tracevv(x) {if (verbose>1) fprintf x ;}
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
#ifdef CONFIG_KERNEL_LZO
#include "../../../../lib/decompress_unlzo.c"
#endif
void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x))
{
decompress(input, len, NULL, NULL, output, NULL, error);
}
...@@ -23,8 +23,8 @@ unsigned int __machine_arch_type; ...@@ -23,8 +23,8 @@ unsigned int __machine_arch_type;
#include <linux/compiler.h> /* for inline */ #include <linux/compiler.h> /* for inline */
#include <linux/types.h> /* for size_t */ #include <linux/types.h> /* for size_t */
#include <linux/stddef.h> /* for NULL */ #include <linux/stddef.h> /* for NULL */
#include <asm/string.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include <asm/string.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -117,57 +117,7 @@ static void putstr(const char *ptr) ...@@ -117,57 +117,7 @@ static void putstr(const char *ptr)
#endif #endif
#define __ptr_t void * void *memcpy(void *__dest, __const void *__src, size_t __n)
#define memzero(s,n) __memzero(s,n)
/*
* Optimised C version of memzero for the ARM.
*/
void __memzero (__ptr_t s, size_t n)
{
union { void *vp; unsigned long *ulp; unsigned char *ucp; } u;
int i;
u.vp = s;
for (i = n >> 5; i > 0; i--) {
*u.ulp++ = 0;
*u.ulp++ = 0;
*u.ulp++ = 0;
*u.ulp++ = 0;
*u.ulp++ = 0;
*u.ulp++ = 0;
*u.ulp++ = 0;
*u.ulp++ = 0;
}
if (n & 1 << 4) {
*u.ulp++ = 0;
*u.ulp++ = 0;
*u.ulp++ = 0;
*u.ulp++ = 0;
}
if (n & 1 << 3) {
*u.ulp++ = 0;
*u.ulp++ = 0;
}
if (n & 1 << 2)
*u.ulp++ = 0;
if (n & 1 << 1) {
*u.ucp++ = 0;
*u.ucp++ = 0;
}
if (n & 1)
*u.ucp++ = 0;
}
static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
size_t __n)
{ {
int i = 0; int i = 0;
unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src; unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
...@@ -204,59 +154,20 @@ static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, ...@@ -204,59 +154,20 @@ static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src,
/* /*
* gzip delarations * gzip delarations
*/ */
#define STATIC static
/* Diagnostic functions */
#ifdef DEBUG
# define Assert(cond,msg) {if(!(cond)) error(msg);}
# define Trace(x) fprintf x
# define Tracev(x) {if (verbose) fprintf x ;}
# define Tracevv(x) {if (verbose>1) fprintf x ;}
# define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
#else
# define Assert(cond,msg)
# define Trace(x)
# define Tracev(x)
# define Tracevv(x)
# define Tracec(c,x)
# define Tracecv(c,x)
#endif
static void error(char *m);
extern char input_data[]; extern char input_data[];
extern char input_data_end[]; extern char input_data_end[];
static unsigned char *output_data; unsigned char *output_data;
static unsigned long output_ptr; unsigned long output_ptr;
static void error(char *m);
static void putstr(const char *); unsigned long free_mem_ptr;
unsigned long free_mem_end_ptr;
static unsigned long free_mem_ptr;
static unsigned long free_mem_end_ptr;
#ifdef STANDALONE_DEBUG
#define NO_INFLATE_MALLOC
#endif
#define ARCH_HAS_DECOMP_WDOG
#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
#ifdef CONFIG_KERNEL_LZO
#include "../../../../lib/decompress_unlzo.c"
#endif
#ifndef arch_error #ifndef arch_error
#define arch_error(x) #define arch_error(x)
#endif #endif
static void error(char *x) void error(char *x)
{ {
arch_error(x); arch_error(x);
...@@ -272,6 +183,8 @@ asmlinkage void __div0(void) ...@@ -272,6 +183,8 @@ asmlinkage void __div0(void)
error("Attempting division by 0!"); error("Attempting division by 0!");
} }
extern void do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
#ifndef STANDALONE_DEBUG #ifndef STANDALONE_DEBUG
unsigned long unsigned long
...@@ -292,8 +205,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, ...@@ -292,8 +205,8 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
output_ptr = get_unaligned_le32(tmp); output_ptr = get_unaligned_le32(tmp);
putstr("Uncompressing Linux..."); putstr("Uncompressing Linux...");
decompress(input_data, input_data_end - input_data, do_decompress(input_data, input_data_end - input_data,
NULL, NULL, output_data, NULL, error); output_data, error);
putstr(" done, booting the kernel.\n"); putstr(" done, booting the kernel.\n");
return output_ptr; return output_ptr;
} }
......
...@@ -14,6 +14,13 @@ SECTIONS ...@@ -14,6 +14,13 @@ SECTIONS
/DISCARD/ : { /DISCARD/ : {
*(.ARM.exidx*) *(.ARM.exidx*)
*(.ARM.extab*) *(.ARM.extab*)
/*
* Discard any r/w data - this produces a link error if we have any,
* which is required for PIC decompression. Local data generates
* GOTOFF relocations, which prevents it being relocated independently
* of the text/got segments.
*/
*(.data)
} }
. = TEXT_START; . = TEXT_START;
...@@ -40,7 +47,6 @@ SECTIONS ...@@ -40,7 +47,6 @@ SECTIONS
.got : { *(.got) } .got : { *(.got) }
_got_end = .; _got_end = .;
.got.plt : { *(.got.plt) } .got.plt : { *(.got.plt) }
.data : { *(.data) }
_edata = .; _edata = .;
. = BSS_START; . = BSS_START;
......
...@@ -242,10 +242,13 @@ CONFIG_CPU_CP15_MMU=y ...@@ -242,10 +242,13 @@ CONFIG_CPU_CP15_MMU=y
# CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set
# CONFIG_CPU_BPREDICT_DISABLE is not set # CONFIG_CPU_BPREDICT_DISABLE is not set
CONFIG_HAS_TLS_REG=y CONFIG_HAS_TLS_REG=y
CONFIG_OUTER_CACHE=y
CONFIG_CACHE_L2X0=y
CONFIG_ARM_L1_CACHE_SHIFT=5 CONFIG_ARM_L1_CACHE_SHIFT=5
# CONFIG_ARM_ERRATA_430973 is not set # CONFIG_ARM_ERRATA_430973 is not set
# CONFIG_ARM_ERRATA_458693 is not set # CONFIG_ARM_ERRATA_458693 is not set
# CONFIG_ARM_ERRATA_460075 is not set # CONFIG_ARM_ERRATA_460075 is not set
CONFIG_PL310_ERRATA_588369=y
CONFIG_ARM_GIC=y CONFIG_ARM_GIC=y
# #
......
...@@ -235,6 +235,234 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) ...@@ -235,6 +235,234 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u)
#define smp_mb__before_atomic_inc() smp_mb() #define smp_mb__before_atomic_inc() smp_mb()
#define smp_mb__after_atomic_inc() smp_mb() #define smp_mb__after_atomic_inc() smp_mb()
#ifndef CONFIG_GENERIC_ATOMIC64
typedef struct {
u64 __aligned(8) counter;
} atomic64_t;
#define ATOMIC64_INIT(i) { (i) }
static inline u64 atomic64_read(atomic64_t *v)
{
u64 result;
__asm__ __volatile__("@ atomic64_read\n"
" ldrexd %0, %H0, [%1]"
: "=&r" (result)
: "r" (&v->counter)
);
return result;
}
static inline void atomic64_set(atomic64_t *v, u64 i)
{
u64 tmp;
__asm__ __volatile__("@ atomic64_set\n"
"1: ldrexd %0, %H0, [%1]\n"
" strexd %0, %2, %H2, [%1]\n"
" teq %0, #0\n"
" bne 1b"
: "=&r" (tmp)
: "r" (&v->counter), "r" (i)
: "cc");
}
static inline void atomic64_add(u64 i, atomic64_t *v)
{
u64 result;
unsigned long tmp;
__asm__ __volatile__("@ atomic64_add\n"
"1: ldrexd %0, %H0, [%2]\n"
" adds %0, %0, %3\n"
" adc %H0, %H0, %H3\n"
" strexd %1, %0, %H0, [%2]\n"
" teq %1, #0\n"
" bne 1b"
: "=&r" (result), "=&r" (tmp)
: "r" (&v->counter), "r" (i)
: "cc");
}
static inline u64 atomic64_add_return(u64 i, atomic64_t *v)
{
u64 result;
unsigned long tmp;
smp_mb();
__asm__ __volatile__("@ atomic64_add_return\n"
"1: ldrexd %0, %H0, [%2]\n"
" adds %0, %0, %3\n"
" adc %H0, %H0, %H3\n"
" strexd %1, %0, %H0, [%2]\n"
" teq %1, #0\n"
" bne 1b"
: "=&r" (result), "=&r" (tmp)
: "r" (&v->counter), "r" (i)
: "cc");
smp_mb();
return result;
}
static inline void atomic64_sub(u64 i, atomic64_t *v)
{
u64 result;
unsigned long tmp;
__asm__ __volatile__("@ atomic64_sub\n"
"1: ldrexd %0, %H0, [%2]\n"
" subs %0, %0, %3\n"
" sbc %H0, %H0, %H3\n"
" strexd %1, %0, %H0, [%2]\n"
" teq %1, #0\n"
" bne 1b"
: "=&r" (result), "=&r" (tmp)
: "r" (&v->counter), "r" (i)
: "cc");
}
static inline u64 atomic64_sub_return(u64 i, atomic64_t *v)
{
u64 result;
unsigned long tmp;
smp_mb();
__asm__ __volatile__("@ atomic64_sub_return\n"
"1: ldrexd %0, %H0, [%2]\n"
" subs %0, %0, %3\n"
" sbc %H0, %H0, %H3\n"
" strexd %1, %0, %H0, [%2]\n"
" teq %1, #0\n"
" bne 1b"
: "=&r" (result), "=&r" (tmp)
: "r" (&v->counter), "r" (i)
: "cc");
smp_mb();
return result;
}
static inline u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old, u64 new)
{
u64 oldval;
unsigned long res;
smp_mb();
do {
__asm__ __volatile__("@ atomic64_cmpxchg\n"
"ldrexd %1, %H1, [%2]\n"
"mov %0, #0\n"
"teq %1, %3\n"
"teqeq %H1, %H3\n"
"strexdeq %0, %4, %H4, [%2]"
: "=&r" (res), "=&r" (oldval)
: "r" (&ptr->counter), "r" (old), "r" (new)
: "cc");
} while (res);
smp_mb();
return oldval;
}
static inline u64 atomic64_xchg(atomic64_t *ptr, u64 new)
{
u64 result;
unsigned long tmp;
smp_mb();
__asm__ __volatile__("@ atomic64_xchg\n"
"1: ldrexd %0, %H0, [%2]\n"
" strexd %1, %3, %H3, [%2]\n"
" teq %1, #0\n"
" bne 1b"
: "=&r" (result), "=&r" (tmp)
: "r" (&ptr->counter), "r" (new)
: "cc");
smp_mb();
return result;
}
static inline u64 atomic64_dec_if_positive(atomic64_t *v)
{
u64 result;
unsigned long tmp;
smp_mb();
__asm__ __volatile__("@ atomic64_dec_if_positive\n"
"1: ldrexd %0, %H0, [%2]\n"
" subs %0, %0, #1\n"
" sbc %H0, %H0, #0\n"
" teq %H0, #0\n"
" bmi 2f\n"
" strexd %1, %0, %H0, [%2]\n"
" teq %1, #0\n"
" bne 1b\n"
"2:"
: "=&r" (result), "=&r" (tmp)
: "r" (&v->counter)
: "cc");
smp_mb();
return result;
}
static inline int atomic64_add_unless(atomic64_t *v, u64 a, u64 u)
{
u64 val;
unsigned long tmp;
int ret = 1;
smp_mb();
__asm__ __volatile__("@ atomic64_add_unless\n"
"1: ldrexd %0, %H0, [%3]\n"
" teq %0, %4\n"
" teqeq %H0, %H4\n"
" moveq %1, #0\n"
" beq 2f\n"
" adds %0, %0, %5\n"
" adc %H0, %H0, %H5\n"
" strexd %2, %0, %H0, [%3]\n"
" teq %2, #0\n"
" bne 1b\n"
"2:"
: "=&r" (val), "=&r" (ret), "=&r" (tmp)
: "r" (&v->counter), "r" (u), "r" (a)
: "cc");
if (ret)
smp_mb();
return ret;
}
#define atomic64_add_negative(a, v) (atomic64_add_return((a), (v)) < 0)
#define atomic64_inc(v) atomic64_add(1LL, (v))
#define atomic64_inc_return(v) atomic64_add_return(1LL, (v))
#define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0)
#define atomic64_sub_and_test(a, v) (atomic64_sub_return((a), (v)) == 0)
#define atomic64_dec(v) atomic64_sub(1LL, (v))
#define atomic64_dec_return(v) atomic64_sub_return(1LL, (v))
#define atomic64_dec_and_test(v) (atomic64_dec_return((v)) == 0)
#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1LL, 0LL)
#else /* !CONFIG_GENERIC_ATOMIC64 */
#include <asm-generic/atomic64.h>
#endif
#include <asm-generic/atomic-long.h> #include <asm-generic/atomic-long.h>
#endif #endif
#endif #endif
...@@ -69,9 +69,16 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); ...@@ -69,9 +69,16 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
/* /*
* __arm_ioremap takes CPU physical address. * __arm_ioremap takes CPU physical address.
* __arm_ioremap_pfn takes a Page Frame Number and an offset into that page * __arm_ioremap_pfn takes a Page Frame Number and an offset into that page
* The _caller variety takes a __builtin_return_address(0) value for
* /proc/vmalloc to use - and should only be used in non-inline functions.
*/ */
extern void __iomem * __arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int); extern void __iomem *__arm_ioremap_pfn_caller(unsigned long, unsigned long,
extern void __iomem * __arm_ioremap(unsigned long, size_t, unsigned int); size_t, unsigned int, void *);
extern void __iomem *__arm_ioremap_caller(unsigned long, size_t, unsigned int,
void *);
extern void __iomem *__arm_ioremap_pfn(unsigned long, unsigned long, size_t, unsigned int);
extern void __iomem *__arm_ioremap(unsigned long, size_t, unsigned int);
extern void __iounmap(volatile void __iomem *addr); extern void __iounmap(volatile void __iomem *addr);
/* /*
......
...@@ -46,12 +46,4 @@ struct sys_timer { ...@@ -46,12 +46,4 @@ struct sys_timer {
extern struct sys_timer *system_timer; extern struct sys_timer *system_timer;
extern void timer_tick(void); extern void timer_tick(void);
/*
* Kernel time keeping support.
*/
struct timespec;
extern int (*set_rtc)(void);
extern void save_time_delta(struct timespec *delta, struct timespec *rtc);
extern void restore_time_delta(struct timespec *delta, struct timespec *rtc);
#endif #endif
...@@ -76,6 +76,17 @@ ...@@ -76,6 +76,17 @@
*/ */
#define IOREMAP_MAX_ORDER 24 #define IOREMAP_MAX_ORDER 24
/*
* Size of DMA-consistent memory region. Must be multiple of 2M,
* between 2MB and 14MB inclusive.
*/
#ifndef CONSISTENT_DMA_SIZE
#define CONSISTENT_DMA_SIZE SZ_2M
#endif
#define CONSISTENT_END (0xffe00000UL)
#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE)
#else /* CONFIG_MMU */ #else /* CONFIG_MMU */
/* /*
...@@ -93,11 +104,11 @@ ...@@ -93,11 +104,11 @@
#endif #endif
#ifndef PHYS_OFFSET #ifndef PHYS_OFFSET
#define PHYS_OFFSET (CONFIG_DRAM_BASE) #define PHYS_OFFSET UL(CONFIG_DRAM_BASE)
#endif #endif
#ifndef END_MEM #ifndef END_MEM
#define END_MEM (CONFIG_DRAM_BASE + CONFIG_DRAM_SIZE) #define END_MEM (UL(CONFIG_DRAM_BASE) + CONFIG_DRAM_SIZE)
#endif #endif
#ifndef PAGE_OFFSET #ifndef PAGE_OFFSET
...@@ -112,14 +123,6 @@ ...@@ -112,14 +123,6 @@
#endif /* !CONFIG_MMU */ #endif /* !CONFIG_MMU */
/*
* Size of DMA-consistent memory region. Must be multiple of 2M,
* between 2MB and 14MB inclusive.
*/
#ifndef CONSISTENT_DMA_SIZE
#define CONSISTENT_DMA_SIZE SZ_2M
#endif
/* /*
* Physical vs virtual RAM address space conversion. These are * Physical vs virtual RAM address space conversion. These are
* private definitions which should NOT be used outside memory.h * private definitions which should NOT be used outside memory.h
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
typedef struct { typedef struct {
#ifdef CONFIG_CPU_HAS_ASID #ifdef CONFIG_CPU_HAS_ASID
unsigned int id; unsigned int id;
spinlock_t id_lock;
#endif #endif
unsigned int kvm_seq; unsigned int kvm_seq;
} mm_context_t; } mm_context_t;
......
...@@ -43,12 +43,23 @@ void __check_kvm_seq(struct mm_struct *mm); ...@@ -43,12 +43,23 @@ void __check_kvm_seq(struct mm_struct *mm);
#define ASID_FIRST_VERSION (1 << ASID_BITS) #define ASID_FIRST_VERSION (1 << ASID_BITS)
extern unsigned int cpu_last_asid; extern unsigned int cpu_last_asid;
#ifdef CONFIG_SMP
DECLARE_PER_CPU(struct mm_struct *, current_mm);
#endif
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm); void __init_new_context(struct task_struct *tsk, struct mm_struct *mm);
void __new_context(struct mm_struct *mm); void __new_context(struct mm_struct *mm);
static inline void check_context(struct mm_struct *mm) static inline void check_context(struct mm_struct *mm)
{ {
/*
* This code is executed with interrupts enabled. Therefore,
* mm->context.id cannot be updated to the latest ASID version
* on a different CPU (and condition below not triggered)
* without first getting an IPI to reset the context. The
* alternative is to take a read_lock on mm->context.id_lock
* (after changing its type to rwlock_t).
*/
if (unlikely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) if (unlikely((mm->context.id ^ cpu_last_asid) >> ASID_BITS))
__new_context(mm); __new_context(mm);
...@@ -108,6 +119,10 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, ...@@ -108,6 +119,10 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
__flush_icache_all(); __flush_icache_all();
#endif #endif
if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) { if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) {
#ifdef CONFIG_SMP
struct mm_struct **crt_mm = &per_cpu(current_mm, cpu);
*crt_mm = next;
#endif
check_context(next); check_context(next);
cpu_switch_mm(next->pgd, next); cpu_switch_mm(next->pgd, next);
if (cache_is_vivt()) if (cache_is_vivt())
......
...@@ -86,8 +86,8 @@ extern unsigned int kobjsize(const void *objp); ...@@ -86,8 +86,8 @@ extern unsigned int kobjsize(const void *objp);
* All 32bit addresses are effectively valid for vmalloc... * All 32bit addresses are effectively valid for vmalloc...
* Sort of meaningless for non-VM targets. * Sort of meaningless for non-VM targets.
*/ */
#define VMALLOC_START 0 #define VMALLOC_START 0UL
#define VMALLOC_END 0xffffffff #define VMALLOC_END 0xffffffffUL
#define FIRST_USER_ADDRESS (0) #define FIRST_USER_ADDRESS (0)
......
...@@ -223,18 +223,6 @@ extern struct meminfo meminfo; ...@@ -223,18 +223,6 @@ extern struct meminfo meminfo;
#define bank_phys_end(bank) ((bank)->start + (bank)->size) #define bank_phys_end(bank) ((bank)->start + (bank)->size)
#define bank_phys_size(bank) (bank)->size #define bank_phys_size(bank) (bank)->size
/*
* Early command line parameters.
*/
struct early_params {
const char *arg;
void (*fn)(char **p);
};
#define __early_param(name,fn) \
static struct early_params __early_##fn __used \
__attribute__((__section__(".early_param.init"))) = { name, fn }
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif #endif
...@@ -5,6 +5,22 @@ ...@@ -5,6 +5,22 @@
#error SMP not supported on pre-ARMv6 CPUs #error SMP not supported on pre-ARMv6 CPUs
#endif #endif
static inline void dsb_sev(void)
{
#if __LINUX_ARM_ARCH__ >= 7
__asm__ __volatile__ (
"dsb\n"
"sev"
);
#elif defined(CONFIG_CPU_32v6K)
__asm__ __volatile__ (
"mcr p15, 0, %0, c7, c10, 4\n"
"sev"
: : "r" (0)
);
#endif
}
/* /*
* ARMv6 Spin-locking. * ARMv6 Spin-locking.
* *
...@@ -69,13 +85,11 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock) ...@@ -69,13 +85,11 @@ static inline void arch_spin_unlock(arch_spinlock_t *lock)
__asm__ __volatile__( __asm__ __volatile__(
" str %1, [%0]\n" " str %1, [%0]\n"
#ifdef CONFIG_CPU_32v6K
" mcr p15, 0, %1, c7, c10, 4\n" /* DSB */
" sev"
#endif
: :
: "r" (&lock->lock), "r" (0) : "r" (&lock->lock), "r" (0)
: "cc"); : "cc");
dsb_sev();
} }
/* /*
...@@ -132,13 +146,11 @@ static inline void arch_write_unlock(arch_rwlock_t *rw) ...@@ -132,13 +146,11 @@ static inline void arch_write_unlock(arch_rwlock_t *rw)
__asm__ __volatile__( __asm__ __volatile__(
"str %1, [%0]\n" "str %1, [%0]\n"
#ifdef CONFIG_CPU_32v6K
" mcr p15, 0, %1, c7, c10, 4\n" /* DSB */
" sev\n"
#endif
: :
: "r" (&rw->lock), "r" (0) : "r" (&rw->lock), "r" (0)
: "cc"); : "cc");
dsb_sev();
} }
/* write_can_lock - would write_trylock() succeed? */ /* write_can_lock - would write_trylock() succeed? */
...@@ -188,14 +200,12 @@ static inline void arch_read_unlock(arch_rwlock_t *rw) ...@@ -188,14 +200,12 @@ static inline void arch_read_unlock(arch_rwlock_t *rw)
" strex %1, %0, [%2]\n" " strex %1, %0, [%2]\n"
" teq %1, #0\n" " teq %1, #0\n"
" bne 1b" " bne 1b"
#ifdef CONFIG_CPU_32v6K
"\n cmp %0, #0\n"
" mcreq p15, 0, %0, c7, c10, 4\n"
" seveq"
#endif
: "=&r" (tmp), "=&r" (tmp2) : "=&r" (tmp), "=&r" (tmp2)
: "r" (&rw->lock) : "r" (&rw->lock)
: "cc"); : "cc");
if (tmp == 0)
dsb_sev();
} }
static inline int arch_read_trylock(arch_rwlock_t *rw) static inline int arch_read_trylock(arch_rwlock_t *rw)
......
...@@ -73,8 +73,7 @@ extern unsigned int mem_fclk_21285; ...@@ -73,8 +73,7 @@ extern unsigned int mem_fclk_21285;
struct pt_regs; struct pt_regs;
void die(const char *msg, struct pt_regs *regs, int err) void die(const char *msg, struct pt_regs *regs, int err);
__attribute__((noreturn));
struct siginfo; struct siginfo;
void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info, void arm_notify_die(const char *str, struct pt_regs *regs, struct siginfo *info,
......
...@@ -115,7 +115,8 @@ extern void iwmmxt_task_restore(struct thread_info *, void *); ...@@ -115,7 +115,8 @@ extern void iwmmxt_task_restore(struct thread_info *, void *);
extern void iwmmxt_task_release(struct thread_info *); extern void iwmmxt_task_release(struct thread_info *);
extern void iwmmxt_task_switch(struct thread_info *); extern void iwmmxt_task_switch(struct thread_info *);
extern void vfp_sync_state(struct thread_info *thread); extern void vfp_sync_hwstate(struct thread_info *);
extern void vfp_flush_hwstate(struct thread_info *);
#endif #endif
......
...@@ -17,6 +17,7 @@ obj-y := compat.o elf.o entry-armv.o entry-common.o irq.o \ ...@@ -17,6 +17,7 @@ obj-y := compat.o elf.o entry-armv.o entry-common.o irq.o \
process.o ptrace.o return_address.o setup.o signal.o \ process.o ptrace.o return_address.o setup.o signal.o \
sys_arm.o stacktrace.o time.o traps.o sys_arm.o stacktrace.o time.o traps.o
obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_OC_ETM) += etm.o obj-$(CONFIG_OC_ETM) += etm.o
obj-$(CONFIG_ISA_DMA_API) += dma.o obj-$(CONFIG_ISA_DMA_API) += dma.o
......
/*
* LED support code, ripped out of arch/arm/kernel/time.c
*
* Copyright (C) 1994-2001 Russell King
*
* 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/module.h>
#include <linux/init.h>
#include <linux/sysdev.h>
#include <asm/leds.h>
static void dummy_leds_event(led_event_t evt)
{
}
void (*leds_event)(led_event_t) = dummy_leds_event;
struct leds_evt_name {
const char name[8];
int on;
int off;
};
static const struct leds_evt_name evt_names[] = {
{ "amber", led_amber_on, led_amber_off },
{ "blue", led_blue_on, led_blue_off },
{ "green", led_green_on, led_green_off },
{ "red", led_red_on, led_red_off },
};
static ssize_t leds_store(struct sys_device *dev,
struct sysdev_attribute *attr,
const char *buf, size_t size)
{
int ret = -EINVAL, len = strcspn(buf, " ");
if (len > 0 && buf[len] == '\0')
len--;
if (strncmp(buf, "claim", len) == 0) {
leds_event(led_claim);
ret = size;
} else if (strncmp(buf, "release", len) == 0) {
leds_event(led_release);
ret = size;
} else {
int i;
for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
if (strlen(evt_names[i].name) != len ||
strncmp(buf, evt_names[i].name, len) != 0)
continue;
if (strncmp(buf+len, " on", 3) == 0) {
leds_event(evt_names[i].on);
ret = size;
} else if (strncmp(buf+len, " off", 4) == 0) {
leds_event(evt_names[i].off);
ret = size;
}
break;
}
}
return ret;
}
static SYSDEV_ATTR(event, 0200, NULL, leds_store);
static int leds_suspend(struct sys_device *dev, pm_message_t state)
{
leds_event(led_stop);
return 0;
}
static int leds_resume(struct sys_device *dev)
{
leds_event(led_start);
return 0;
}
static int leds_shutdown(struct sys_device *dev)
{
leds_event(led_halted);
return 0;
}
static struct sysdev_class leds_sysclass = {
.name = "leds",
.shutdown = leds_shutdown,
.suspend = leds_suspend,
.resume = leds_resume,
};
static struct sys_device leds_device = {
.id = 0,
.cls = &leds_sysclass,
};
static int __init leds_init(void)
{
int ret;
ret = sysdev_class_register(&leds_sysclass);
if (ret == 0)
ret = sysdev_register(&leds_device);
if (ret == 0)
ret = sysdev_create_file(&leds_device, &attr_event);
return ret;
}
device_initcall(leds_init);
EXPORT_SYMBOL(leds_event);
...@@ -499,10 +499,41 @@ static struct undef_hook thumb_break_hook = { ...@@ -499,10 +499,41 @@ static struct undef_hook thumb_break_hook = {
.fn = break_trap, .fn = break_trap,
}; };
static int thumb2_break_trap(struct pt_regs *regs, unsigned int instr)
{
unsigned int instr2;
void __user *pc;
/* Check the second half of the instruction. */
pc = (void __user *)(instruction_pointer(regs) + 2);
if (processor_mode(regs) == SVC_MODE) {
instr2 = *(u16 *) pc;
} else {
get_user(instr2, (u16 __user *)pc);
}
if (instr2 == 0xa000) {
ptrace_break(current, regs);
return 0;
} else {
return 1;
}
}
static struct undef_hook thumb2_break_hook = {
.instr_mask = 0xffff,
.instr_val = 0xf7f0,
.cpsr_mask = PSR_T_BIT,
.cpsr_val = PSR_T_BIT,
.fn = thumb2_break_trap,
};
static int __init ptrace_break_init(void) static int __init ptrace_break_init(void)
{ {
register_undef_hook(&arm_break_hook); register_undef_hook(&arm_break_hook);
register_undef_hook(&thumb_break_hook); register_undef_hook(&thumb_break_hook);
register_undef_hook(&thumb2_break_hook);
return 0; return 0;
} }
...@@ -669,7 +700,7 @@ static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data) ...@@ -669,7 +700,7 @@ static int ptrace_getvfpregs(struct task_struct *tsk, void __user *data)
union vfp_state *vfp = &thread->vfpstate; union vfp_state *vfp = &thread->vfpstate;
struct user_vfp __user *ufp = data; struct user_vfp __user *ufp = data;
vfp_sync_state(thread); vfp_sync_hwstate(thread);
/* copy the floating point registers */ /* copy the floating point registers */
if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs, if (copy_to_user(&ufp->fpregs, &vfp->hard.fpregs,
...@@ -692,7 +723,7 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data) ...@@ -692,7 +723,7 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
union vfp_state *vfp = &thread->vfpstate; union vfp_state *vfp = &thread->vfpstate;
struct user_vfp __user *ufp = data; struct user_vfp __user *ufp = data;
vfp_sync_state(thread); vfp_sync_hwstate(thread);
/* copy the floating point registers */ /* copy the floating point registers */
if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs, if (copy_from_user(&vfp->hard.fpregs, &ufp->fpregs,
...@@ -703,6 +734,8 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data) ...@@ -703,6 +734,8 @@ static int ptrace_setvfpregs(struct task_struct *tsk, void __user *data)
if (get_user(vfp->hard.fpscr, &ufp->fpscr)) if (get_user(vfp->hard.fpscr, &ufp->fpscr))
return -EFAULT; return -EFAULT;
vfp_flush_hwstate(thread);
return 0; return 0;
} }
#endif #endif
...@@ -712,26 +745,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -712,26 +745,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
int ret; int ret;
switch (request) { switch (request) {
/*
* read word at location "addr" in the child process.
*/
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
ret = generic_ptrace_peekdata(child, addr, data);
break;
case PTRACE_PEEKUSR: case PTRACE_PEEKUSR:
ret = ptrace_read_user(child, addr, (unsigned long __user *)data); ret = ptrace_read_user(child, addr, (unsigned long __user *)data);
break; break;
/*
* write the word at location addr.
*/
case PTRACE_POKETEXT:
case PTRACE_POKEDATA:
ret = generic_ptrace_pokedata(child, addr, data);
break;
case PTRACE_POKEUSR: case PTRACE_POKEUSR:
ret = ptrace_write_user(child, addr, data); ret = ptrace_write_user(child, addr, data);
break; break;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/proc_fs.h>
#include <asm/unified.h> #include <asm/unified.h>
#include <asm/cpu.h> #include <asm/cpu.h>
...@@ -117,7 +118,7 @@ EXPORT_SYMBOL(elf_platform); ...@@ -117,7 +118,7 @@ EXPORT_SYMBOL(elf_platform);
static const char *cpu_name; static const char *cpu_name;
static const char *machine_name; static const char *machine_name;
static char __initdata command_line[COMMAND_LINE_SIZE]; static char __initdata cmd_line[COMMAND_LINE_SIZE];
static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } }; static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
...@@ -417,10 +418,11 @@ static int __init arm_add_memory(unsigned long start, unsigned long size) ...@@ -417,10 +418,11 @@ static int __init arm_add_memory(unsigned long start, unsigned long size)
* Pick out the memory size. We look for mem=size@start, * Pick out the memory size. We look for mem=size@start,
* where start and size are "size[KkMm]" * where start and size are "size[KkMm]"
*/ */
static void __init early_mem(char **p) static int __init early_mem(char *p)
{ {
static int usermem __initdata = 0; static int usermem __initdata = 0;
unsigned long size, start; unsigned long size, start;
char *endp;
/* /*
* If the user specifies memory size, we * If the user specifies memory size, we
...@@ -433,52 +435,15 @@ static void __init early_mem(char **p) ...@@ -433,52 +435,15 @@ static void __init early_mem(char **p)
} }
start = PHYS_OFFSET; start = PHYS_OFFSET;
size = memparse(*p, p); size = memparse(p, &endp);
if (**p == '@') if (*endp == '@')
start = memparse(*p + 1, p); start = memparse(endp + 1, NULL);
arm_add_memory(start, size); arm_add_memory(start, size);
}
__early_param("mem=", early_mem);
/*
* Initial parsing of the command line.
*/
static void __init parse_cmdline(char **cmdline_p, char *from)
{
char c = ' ', *to = command_line;
int len = 0;
for (;;) {
if (c == ' ') {
extern struct early_params __early_begin, __early_end;
struct early_params *p;
for (p = &__early_begin; p < &__early_end; p++) {
int arglen = strlen(p->arg);
if (memcmp(from, p->arg, arglen) == 0) { return 0;
if (to != command_line)
to -= 1;
from += arglen;
p->fn(&from);
while (*from != ' ' && *from != '\0')
from++;
break;
}
}
}
c = *from++;
if (!c)
break;
if (COMMAND_LINE_SIZE <= ++len)
break;
*to++ = c;
}
*to = '\0';
*cmdline_p = command_line;
} }
early_param("mem", early_mem);
static void __init static void __init
setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz) setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
...@@ -739,9 +704,15 @@ void __init setup_arch(char **cmdline_p) ...@@ -739,9 +704,15 @@ void __init setup_arch(char **cmdline_p)
init_mm.end_data = (unsigned long) _edata; init_mm.end_data = (unsigned long) _edata;
init_mm.brk = (unsigned long) _end; init_mm.brk = (unsigned long) _end;
memcpy(boot_command_line, from, COMMAND_LINE_SIZE); /* parse_early_param needs a boot_command_line */
boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
parse_cmdline(cmdline_p, from);
/* populate cmd_line too for later use, preserving boot_command_line */
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
*cmdline_p = cmd_line;
parse_early_param();
paging_init(mdesc); paging_init(mdesc);
request_standard_resources(&meminfo, mdesc); request_standard_resources(&meminfo, mdesc);
...@@ -782,9 +753,21 @@ static int __init topology_init(void) ...@@ -782,9 +753,21 @@ static int __init topology_init(void)
return 0; return 0;
} }
subsys_initcall(topology_init); subsys_initcall(topology_init);
#ifdef CONFIG_HAVE_PROC_CPU
static int __init proc_cpu_init(void)
{
struct proc_dir_entry *res;
res = proc_mkdir("cpu", NULL);
if (!res)
return -ENOMEM;
return 0;
}
fs_initcall(proc_cpu_init);
#endif
static const char *hwcap_str[] = { static const char *hwcap_str[] = {
"swp", "swp",
"half", "half",
......
...@@ -10,11 +10,6 @@ ...@@ -10,11 +10,6 @@
* *
* This file contains the ARM-specific time handling details: * This file contains the ARM-specific time handling details:
* reading the RTC at bootup, etc... * reading the RTC at bootup, etc...
*
* 1994-07-02 Alan Modra
* fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
* 1998-12-20 Updated NTP code according to technical memorandum Jan '96
* "A Kernel Model for Precision Timekeeping" by Dave Mills
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -77,11 +72,6 @@ unsigned long profile_pc(struct pt_regs *regs) ...@@ -77,11 +72,6 @@ unsigned long profile_pc(struct pt_regs *regs)
EXPORT_SYMBOL(profile_pc); EXPORT_SYMBOL(profile_pc);
#endif #endif
/*
* hook for setting the RTC's idea of the current time.
*/
int (*set_rtc)(void);
#ifndef CONFIG_GENERIC_TIME #ifndef CONFIG_GENERIC_TIME
static unsigned long dummy_gettimeoffset(void) static unsigned long dummy_gettimeoffset(void)
{ {
...@@ -89,140 +79,6 @@ static unsigned long dummy_gettimeoffset(void) ...@@ -89,140 +79,6 @@ static unsigned long dummy_gettimeoffset(void)
} }
#endif #endif
static unsigned long next_rtc_update;
/*
* If we have an externally synchronized linux clock, then update
* CMOS clock accordingly every ~11 minutes. set_rtc() has to be
* called as close as possible to 500 ms before the new second
* starts.
*/
static inline void do_set_rtc(void)
{
if (!ntp_synced() || set_rtc == NULL)
return;
if (next_rtc_update &&
time_before((unsigned long)xtime.tv_sec, next_rtc_update))
return;
if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) &&
xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1))
return;
if (set_rtc())
/*
* rtc update failed. Try again in 60s
*/
next_rtc_update = xtime.tv_sec + 60;
else
next_rtc_update = xtime.tv_sec + 660;
}
#ifdef CONFIG_LEDS
static void dummy_leds_event(led_event_t evt)
{
}
void (*leds_event)(led_event_t) = dummy_leds_event;
struct leds_evt_name {
const char name[8];
int on;
int off;
};
static const struct leds_evt_name evt_names[] = {
{ "amber", led_amber_on, led_amber_off },
{ "blue", led_blue_on, led_blue_off },
{ "green", led_green_on, led_green_off },
{ "red", led_red_on, led_red_off },
};
static ssize_t leds_store(struct sys_device *dev,
struct sysdev_attribute *attr,
const char *buf, size_t size)
{
int ret = -EINVAL, len = strcspn(buf, " ");
if (len > 0 && buf[len] == '\0')
len--;
if (strncmp(buf, "claim", len) == 0) {
leds_event(led_claim);
ret = size;
} else if (strncmp(buf, "release", len) == 0) {
leds_event(led_release);
ret = size;
} else {
int i;
for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
if (strlen(evt_names[i].name) != len ||
strncmp(buf, evt_names[i].name, len) != 0)
continue;
if (strncmp(buf+len, " on", 3) == 0) {
leds_event(evt_names[i].on);
ret = size;
} else if (strncmp(buf+len, " off", 4) == 0) {
leds_event(evt_names[i].off);
ret = size;
}
break;
}
}
return ret;
}
static SYSDEV_ATTR(event, 0200, NULL, leds_store);
static int leds_suspend(struct sys_device *dev, pm_message_t state)
{
leds_event(led_stop);
return 0;
}
static int leds_resume(struct sys_device *dev)
{
leds_event(led_start);
return 0;
}
static int leds_shutdown(struct sys_device *dev)
{
leds_event(led_halted);
return 0;
}
static struct sysdev_class leds_sysclass = {
.name = "leds",
.shutdown = leds_shutdown,
.suspend = leds_suspend,
.resume = leds_resume,
};
static struct sys_device leds_device = {
.id = 0,
.cls = &leds_sysclass,
};
static int __init leds_init(void)
{
int ret;
ret = sysdev_class_register(&leds_sysclass);
if (ret == 0)
ret = sysdev_register(&leds_device);
if (ret == 0)
ret = sysdev_create_file(&leds_device, &attr_event);
return ret;
}
device_initcall(leds_init);
EXPORT_SYMBOL(leds_event);
#endif
#ifdef CONFIG_LEDS_TIMER #ifdef CONFIG_LEDS_TIMER
static inline void do_leds(void) static inline void do_leds(void)
{ {
...@@ -295,39 +151,6 @@ int do_settimeofday(struct timespec *tv) ...@@ -295,39 +151,6 @@ int do_settimeofday(struct timespec *tv)
EXPORT_SYMBOL(do_settimeofday); EXPORT_SYMBOL(do_settimeofday);
#endif /* !CONFIG_GENERIC_TIME */ #endif /* !CONFIG_GENERIC_TIME */
/**
* save_time_delta - Save the offset between system time and RTC time
* @delta: pointer to timespec to store delta
* @rtc: pointer to timespec for current RTC time
*
* Return a delta between the system time and the RTC time, such
* that system time can be restored later with restore_time_delta()
*/
void save_time_delta(struct timespec *delta, struct timespec *rtc)
{
set_normalized_timespec(delta,
xtime.tv_sec - rtc->tv_sec,
xtime.tv_nsec - rtc->tv_nsec);
}
EXPORT_SYMBOL(save_time_delta);
/**
* restore_time_delta - Restore the current system time
* @delta: delta returned by save_time_delta()
* @rtc: pointer to timespec for current RTC time
*/
void restore_time_delta(struct timespec *delta, struct timespec *rtc)
{
struct timespec ts;
set_normalized_timespec(&ts,
delta->tv_sec + rtc->tv_sec,
delta->tv_nsec + rtc->tv_nsec);
do_settimeofday(&ts);
}
EXPORT_SYMBOL(restore_time_delta);
#ifndef CONFIG_GENERIC_CLOCKEVENTS #ifndef CONFIG_GENERIC_CLOCKEVENTS
/* /*
* Kernel system timer support. * Kernel system timer support.
...@@ -336,7 +159,6 @@ void timer_tick(void) ...@@ -336,7 +159,6 @@ void timer_tick(void)
{ {
profile_tick(CPU_PROFILING); profile_tick(CPU_PROFILING);
do_leds(); do_leds();
do_set_rtc();
write_seqlock(&xtime_lock); write_seqlock(&xtime_lock);
do_timer(1); do_timer(1);
write_sequnlock(&xtime_lock); write_sequnlock(&xtime_lock);
......
...@@ -12,15 +12,17 @@ ...@@ -12,15 +12,17 @@
* 'linux/arch/arm/lib/traps.S'. Mostly a debugging aid, but will probably * 'linux/arch/arm/lib/traps.S'. Mostly a debugging aid, but will probably
* kill the offending process. * kill the offending process.
*/ */
#include <linux/module.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/spinlock.h>
#include <linux/personality.h> #include <linux/personality.h>
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/delay.h> #include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include <linux/kdebug.h>
#include <linux/module.h>
#include <linux/kexec.h>
#include <linux/delay.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/uaccess.h>
#include <asm/atomic.h> #include <asm/atomic.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
...@@ -224,14 +226,21 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) ...@@ -224,14 +226,21 @@ void show_stack(struct task_struct *tsk, unsigned long *sp)
#define S_SMP "" #define S_SMP ""
#endif #endif
static void __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs)
{ {
struct task_struct *tsk = thread->task; struct task_struct *tsk = thread->task;
static int die_counter; static int die_counter;
int ret;
printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n", printk(KERN_EMERG "Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",
str, err, ++die_counter); str, err, ++die_counter);
sysfs_printk_last_file(); sysfs_printk_last_file();
/* trap and error numbers are mostly meaningless on ARM */
ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV);
if (ret == NOTIFY_STOP)
return ret;
print_modules(); print_modules();
__show_regs(regs); __show_regs(regs);
printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
...@@ -243,6 +252,8 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p ...@@ -243,6 +252,8 @@ static void __die(const char *str, int err, struct thread_info *thread, struct p
dump_backtrace(regs, tsk); dump_backtrace(regs, tsk);
dump_instr(KERN_EMERG, regs); dump_instr(KERN_EMERG, regs);
} }
return ret;
} }
DEFINE_SPINLOCK(die_lock); DEFINE_SPINLOCK(die_lock);
...@@ -250,16 +261,21 @@ DEFINE_SPINLOCK(die_lock); ...@@ -250,16 +261,21 @@ DEFINE_SPINLOCK(die_lock);
/* /*
* This function is protected against re-entrancy. * This function is protected against re-entrancy.
*/ */
NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) void die(const char *str, struct pt_regs *regs, int err)
{ {
struct thread_info *thread = current_thread_info(); struct thread_info *thread = current_thread_info();
int ret;
oops_enter(); oops_enter();
spin_lock_irq(&die_lock); spin_lock_irq(&die_lock);
console_verbose(); console_verbose();
bust_spinlocks(1); bust_spinlocks(1);
__die(str, err, thread, regs); ret = __die(str, err, thread, regs);
if (regs && kexec_should_crash(thread->task))
crash_kexec(regs);
bust_spinlocks(0); bust_spinlocks(0);
add_taint(TAINT_DIE); add_taint(TAINT_DIE);
spin_unlock_irq(&die_lock); spin_unlock_irq(&die_lock);
...@@ -267,10 +283,9 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err) ...@@ -267,10 +283,9 @@ NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
if (in_interrupt()) if (in_interrupt())
panic("Fatal exception in interrupt"); panic("Fatal exception in interrupt");
if (panic_on_oops) if (panic_on_oops)
panic("Fatal exception"); panic("Fatal exception");
if (ret != NOTIFY_STOP)
do_exit(SIGSEGV); do_exit(SIGSEGV);
} }
......
...@@ -43,10 +43,6 @@ SECTIONS ...@@ -43,10 +43,6 @@ SECTIONS
INIT_SETUP(16) INIT_SETUP(16)
__early_begin = .;
*(.early_param.init)
__early_end = .;
INIT_CALLS INIT_CALLS
CON_INITCALL CON_INITCALL
SECURITY_INITCALL SECURITY_INITCALL
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
/* /*
* I/O mapping * I/O mapping
*/ */
#define IO_PHYS 0x01c00000 #define IO_PHYS 0x01c00000UL
#define IO_OFFSET 0xfd000000 /* Virtual IO = 0xfec00000 */ #define IO_OFFSET 0xfd000000 /* Virtual IO = 0xfec00000 */
#define IO_SIZE 0x00400000 #define IO_SIZE 0x00400000
#define IO_VIRT (IO_PHYS + IO_OFFSET) #define IO_VIRT (IO_PHYS + IO_OFFSET)
......
...@@ -24,7 +24,7 @@ void __iomem *davinci_ioremap(unsigned long p, size_t size, unsigned int type) ...@@ -24,7 +24,7 @@ void __iomem *davinci_ioremap(unsigned long p, size_t size, unsigned int type)
if (BETWEEN(p, IO_PHYS, IO_SIZE)) if (BETWEEN(p, IO_PHYS, IO_SIZE))
return XLATE(p, IO_PHYS, IO_VIRT); return XLATE(p, IO_PHYS, IO_VIRT);
return __arm_ioremap(p, size, type); return __arm_ioremap_caller(p, size, type, __builtin_return_address(0));
} }
EXPORT_SYMBOL(davinci_ioremap); EXPORT_SYMBOL(davinci_ioremap);
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
* arch/arm/mach-dove/include/mach/vmalloc.h * arch/arm/mach-dove/include/mach/vmalloc.h
*/ */
#define VMALLOC_END 0xfd800000 #define VMALLOC_END 0xfd800000UL
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
* arch/arm/mach-ep93xx/include/mach/vmalloc.h * arch/arm/mach-ep93xx/include/mach/vmalloc.h
*/ */
#define VMALLOC_END 0xfe800000 #define VMALLOC_END 0xfe800000UL
...@@ -32,12 +32,13 @@ unsigned int mem_fclk_21285 = 50000000; ...@@ -32,12 +32,13 @@ unsigned int mem_fclk_21285 = 50000000;
EXPORT_SYMBOL(mem_fclk_21285); EXPORT_SYMBOL(mem_fclk_21285);
static void __init early_fclk(char **arg) static int __init early_fclk(char *arg)
{ {
mem_fclk_21285 = simple_strtoul(*arg, arg, 0); mem_fclk_21285 = simple_strtoul(arg, NULL, 0);
return 0;
} }
__early_param("mem_fclk_21285=", early_fclk); early_param("mem_fclk_21285", early_fclk);
static int __init parse_tag_memclk(const struct tag *tag) static int __init parse_tag_memclk(const struct tag *tag)
{ {
......
...@@ -7,4 +7,4 @@ ...@@ -7,4 +7,4 @@
* (at your option) any later version. * (at your option) any later version.
*/ */
#define VMALLOC_END 0xF0000000 #define VMALLOC_END 0xf0000000UL
...@@ -61,9 +61,9 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size, ...@@ -61,9 +61,9 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
(cookie - IOP13XX_PCIE_LOWER_MEM_RA)); (cookie - IOP13XX_PCIE_LOWER_MEM_RA));
break; break;
case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA: case IOP13XX_PBI_LOWER_MEM_RA ... IOP13XX_PBI_UPPER_MEM_RA:
retval = __arm_ioremap(IOP13XX_PBI_LOWER_MEM_PA + retval = __arm_ioremap_caller(IOP13XX_PBI_LOWER_MEM_PA +
(cookie - IOP13XX_PBI_LOWER_MEM_RA), (cookie - IOP13XX_PBI_LOWER_MEM_RA),
size, mtype); size, mtype, __builtin_return_address(0));
break; break;
case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA: case IOP13XX_PCIE_LOWER_IO_PA ... IOP13XX_PCIE_UPPER_IO_PA:
retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie); retval = (void *) IOP13XX_PCIE_IO_PHYS_TO_VIRT(cookie);
...@@ -75,7 +75,8 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size, ...@@ -75,7 +75,8 @@ void * __iomem __iop13xx_ioremap(unsigned long cookie, size_t size,
retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie); retval = (void *) IOP13XX_PMMR_PHYS_TO_VIRT(cookie);
break; break;
default: default:
retval = __arm_ioremap(cookie, size, mtype); retval = __arm_ioremap_caller(cookie, size, mtype,
__builtin_return_address(0));
} }
return retval; return retval;
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
* arch/arm/mach-iop32x/include/mach/vmalloc.h * arch/arm/mach-iop32x/include/mach/vmalloc.h
*/ */
#define VMALLOC_END 0xfe000000 #define VMALLOC_END 0xfe000000UL
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
* arch/arm/mach-iop33x/include/mach/vmalloc.h * arch/arm/mach-iop33x/include/mach/vmalloc.h
*/ */
#define VMALLOC_END 0xfe000000 #define VMALLOC_END 0xfe000000UL
...@@ -17,4 +17,4 @@ ...@@ -17,4 +17,4 @@
* The vmalloc() routines leaves a hole of 4kB between each vmalloced * The vmalloc() routines leaves a hole of 4kB between each vmalloced
* area for the same reason. ;) * area for the same reason. ;)
*/ */
#define VMALLOC_END 0xfb000000 #define VMALLOC_END 0xfb000000UL
...@@ -7,4 +7,4 @@ ...@@ -7,4 +7,4 @@
* specific static I/O. * specific static I/O.
*/ */
#define VMALLOC_END (0xec000000) #define VMALLOC_END (0xec000000UL)
/* /*
* arch/arm/mach-ixp4xx/include/mach/vmalloc.h * arch/arm/mach-ixp4xx/include/mach/vmalloc.h
*/ */
#define VMALLOC_END (0xFF000000) #define VMALLOC_END (0xff000000UL)
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
* arch/arm/mach-kirkwood/include/mach/vmalloc.h * arch/arm/mach-kirkwood/include/mach/vmalloc.h
*/ */
#define VMALLOC_END 0xfe800000 #define VMALLOC_END 0xfe800000UL
...@@ -7,4 +7,4 @@ ...@@ -7,4 +7,4 @@
* version 2 as published by the Free Software Foundation. * version 2 as published by the Free Software Foundation.
* *
*/ */
#define VMALLOC_END (0xe8000000) #define VMALLOC_END (0xe8000000UL)
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
* arch/arm/mach-loki/include/mach/vmalloc.h * arch/arm/mach-loki/include/mach/vmalloc.h
*/ */
#define VMALLOC_END 0xfe800000 #define VMALLOC_END 0xfe800000UL
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
* linux/arch/arm/mach-mmp/include/mach/vmalloc.h * linux/arch/arm/mach-mmp/include/mach/vmalloc.h
*/ */
#define VMALLOC_END 0xfe000000 #define VMALLOC_END 0xfe000000UL
...@@ -76,5 +76,6 @@ __msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) ...@@ -76,5 +76,6 @@ __msm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
mtype = MT_DEVICE_NONSHARED; mtype = MT_DEVICE_NONSHARED;
} }
return __arm_ioremap(phys_addr, size, mtype); return __arm_ioremap_caller(phys_addr, size, mtype,
__builtin_return_address(0));
} }
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
* arch/arm/mach-mv78xx0/include/mach/vmalloc.h * arch/arm/mach-mv78xx0/include/mach/vmalloc.h
*/ */
#define VMALLOC_END 0xfe000000 #define VMALLOC_END 0xfe000000UL
#define VMALLOC_END 0xe8000000 #define VMALLOC_END 0xe8000000UL
...@@ -11,6 +11,6 @@ ...@@ -11,6 +11,6 @@
#ifndef __ASM_ARCH_VMALLOC_H #ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H #define __ASM_ARCH_VMALLOC_H
#define VMALLOC_END (0xf0000000) #define VMALLOC_END (0xf0000000UL)
#endif /* ifndef __ASM_ARCH_VMALLOC_H */ #endif /* ifndef __ASM_ARCH_VMALLOC_H */
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <plat/control.h> #include <plat/control.h>
#include <plat/timer-gp.h> #include <plat/timer-gp.h>
#include <asm/hardware/gic.h> #include <asm/hardware/gic.h>
#include <asm/hardware/cache-l2x0.h>
static struct platform_device sdp4430_lcd_device = { static struct platform_device sdp4430_lcd_device = {
.name = "sdp4430_lcd", .name = "sdp4430_lcd",
...@@ -50,6 +51,59 @@ static struct omap_board_config_kernel sdp4430_config[] __initdata = { ...@@ -50,6 +51,59 @@ static struct omap_board_config_kernel sdp4430_config[] __initdata = {
{ OMAP_TAG_LCD, &sdp4430_lcd_config }, { OMAP_TAG_LCD, &sdp4430_lcd_config },
}; };
#ifdef CONFIG_CACHE_L2X0
noinline void omap_smc1(u32 fn, u32 arg)
{
register u32 r12 asm("r12") = fn;
register u32 r0 asm("r0") = arg;
/* This is common routine cache secure monitor API used to
* modify the PL310 secure registers.
* r0 contains the value to be modified and "r12" contains
* the monitor API number. It uses few CPU registers
* internally and hence they need be backed up including
* link register "lr".
* Explicitly save r11 and r12 the compiler generated code
* won't save it.
*/
asm volatile(
"stmfd r13!, {r11,r12}\n"
"dsb\n"
"smc\n"
"ldmfd r13!, {r11,r12}\n"
: "+r" (r0), "+r" (r12)
:
: "r4", "r5", "r10", "lr", "cc");
}
EXPORT_SYMBOL(omap_smc1);
static int __init omap_l2_cache_init(void)
{
void __iomem *l2cache_base;
/* To avoid code running on other OMAPs in
* multi-omap builds
*/
if (!cpu_is_omap44xx())
return -ENODEV;
/* Static mapping, never released */
l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K);
BUG_ON(!l2cache_base);
/* Enable PL310 L2 Cache controller */
omap_smc1(0x102, 0x1);
/* 32KB way size, 16-way associativity,
* parity disabled
*/
l2x0_init(l2cache_base, 0x0e050000, 0xc0000fff);
return 0;
}
early_initcall(omap_l2_cache_init);
#endif
static void __init gic_init_irq(void) static void __init gic_init_irq(void)
{ {
void __iomem *base; void __iomem *base;
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
* arch/arm/mach-orion5x/include/mach/vmalloc.h * arch/arm/mach-orion5x/include/mach/vmalloc.h
*/ */
#define VMALLOC_END 0xfd800000 #define VMALLOC_END 0xfd800000UL
...@@ -8,4 +8,4 @@ ...@@ -8,4 +8,4 @@
* it under the terms of the GNU General Public License version 2 as * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#define VMALLOC_END (0xe8000000) #define VMALLOC_END (0xe8000000UL)
...@@ -18,4 +18,4 @@ ...@@ -18,4 +18,4 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define VMALLOC_END 0xf8000000 #define VMALLOC_END 0xf8000000UL
...@@ -12,6 +12,6 @@ ...@@ -12,6 +12,6 @@
#ifndef __ASM_ARCH_VMALLOC_H #ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H #define __ASM_ARCH_VMALLOC_H
#define VMALLOC_END (0xE0000000) #define VMALLOC_END (0xe0000000UL)
#endif /* __ASM_ARCH_VMALLOC_H */ #endif /* __ASM_ARCH_VMALLOC_H */
/* /*
* arch/arm/mach-sa1100/include/mach/vmalloc.h * arch/arm/mach-sa1100/include/mach/vmalloc.h
*/ */
#define VMALLOC_END (0xe8000000) #define VMALLOC_END (0xe8000000UL)
...@@ -9,4 +9,4 @@ ...@@ -9,4 +9,4 @@
* End must be above the I/O registers and on an even 2MiB boundary. * End must be above the I/O registers and on an even 2MiB boundary.
* Author: Linus Walleij <linus.walleij@stericsson.com> * Author: Linus Walleij <linus.walleij@stericsson.com>
*/ */
#define VMALLOC_END 0xfe800000 #define VMALLOC_END 0xfe800000UL
...@@ -15,4 +15,4 @@ ...@@ -15,4 +15,4 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define VMALLOC_END 0xf0000000 #define VMALLOC_END 0xf0000000UL
...@@ -18,6 +18,6 @@ ...@@ -18,6 +18,6 @@
#ifndef __ASM_ARCH_VMALLOC_H #ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H #define __ASM_ARCH_VMALLOC_H
#define VMALLOC_END (0xE0000000) #define VMALLOC_END (0xe0000000UL)
#endif /* __ASM_ARCH_VMALLOC_H */ #endif /* __ASM_ARCH_VMALLOC_H */
...@@ -399,7 +399,7 @@ config CPU_V6 ...@@ -399,7 +399,7 @@ config CPU_V6
config CPU_32v6K config CPU_32v6K
bool "Support ARM V6K processor extensions" if !SMP bool "Support ARM V6K processor extensions" if !SMP
depends on CPU_V6 depends on CPU_V6
default y if SMP && !ARCH_MX3 default y if SMP && !(ARCH_MX3 || ARCH_OMAP2)
help help
Say Y here if your ARMv6 processor supports the 'K' extension. Say Y here if your ARMv6 processor supports the 'K' extension.
This enables the kernel to use some instructions not present This enables the kernel to use some instructions not present
...@@ -410,7 +410,7 @@ config CPU_32v6K ...@@ -410,7 +410,7 @@ config CPU_32v6K
# ARMv7 # ARMv7
config CPU_V7 config CPU_V7
bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
select CPU_32v6K select CPU_32v6K if !ARCH_OMAP2
select CPU_32v7 select CPU_32v7
select CPU_ABRT_EV7 select CPU_ABRT_EV7
select CPU_PABRT_V7 select CPU_PABRT_V7
...@@ -754,7 +754,7 @@ config CACHE_FEROCEON_L2_WRITETHROUGH ...@@ -754,7 +754,7 @@ config CACHE_FEROCEON_L2_WRITETHROUGH
config CACHE_L2X0 config CACHE_L2X0
bool "Enable the L2x0 outer cache controller" bool "Enable the L2x0 outer cache controller"
depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \ depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK REALVIEW_EB_A9MP || ARCH_MX35 || ARCH_MX31 || MACH_REALVIEW_PBX || ARCH_NOMADIK || ARCH_OMAP4
default y default y
select OUTER_CACHE select OUTER_CACHE
help help
...@@ -779,5 +779,5 @@ config CACHE_XSC3L2 ...@@ -779,5 +779,5 @@ config CACHE_XSC3L2
config ARM_L1_CACHE_SHIFT config ARM_L1_CACHE_SHIFT
int int
default 6 if ARCH_OMAP3 || ARCH_S5PC1XX default 6 if ARM_L1_CACHE_SHIFT_6
default 5 default 5
...@@ -898,11 +898,7 @@ static int __init alignment_init(void) ...@@ -898,11 +898,7 @@ static int __init alignment_init(void)
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
struct proc_dir_entry *res; struct proc_dir_entry *res;
res = proc_mkdir("cpu", NULL); res = create_proc_entry("cpu/alignment", S_IWUSR | S_IRUGO, NULL);
if (!res)
return -ENOMEM;
res = create_proc_entry("alignment", S_IWUSR | S_IRUGO, res);
if (!res) if (!res)
return -ENOMEM; return -ENOMEM;
......
...@@ -42,6 +42,57 @@ static inline void cache_sync(void) ...@@ -42,6 +42,57 @@ static inline void cache_sync(void)
cache_wait(base + L2X0_CACHE_SYNC, 1); cache_wait(base + L2X0_CACHE_SYNC, 1);
} }
static inline void l2x0_clean_line(unsigned long addr)
{
void __iomem *base = l2x0_base;
cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
writel(addr, base + L2X0_CLEAN_LINE_PA);
}
static inline void l2x0_inv_line(unsigned long addr)
{
void __iomem *base = l2x0_base;
cache_wait(base + L2X0_INV_LINE_PA, 1);
writel(addr, base + L2X0_INV_LINE_PA);
}
#ifdef CONFIG_PL310_ERRATA_588369
static void debug_writel(unsigned long val)
{
extern void omap_smc1(u32 fn, u32 arg);
/*
* Texas Instrument secure monitor api to modify the
* PL310 Debug Control Register.
*/
omap_smc1(0x100, val);
}
static inline void l2x0_flush_line(unsigned long addr)
{
void __iomem *base = l2x0_base;
/* Clean by PA followed by Invalidate by PA */
cache_wait(base + L2X0_CLEAN_LINE_PA, 1);
writel(addr, base + L2X0_CLEAN_LINE_PA);
cache_wait(base + L2X0_INV_LINE_PA, 1);
writel(addr, base + L2X0_INV_LINE_PA);
}
#else
/* Optimised out for non-errata case */
static inline void debug_writel(unsigned long val)
{
}
static inline void l2x0_flush_line(unsigned long addr)
{
void __iomem *base = l2x0_base;
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1);
writel(addr, base + L2X0_CLEAN_INV_LINE_PA);
}
#endif
static inline void l2x0_inv_all(void) static inline void l2x0_inv_all(void)
{ {
unsigned long flags; unsigned long flags;
...@@ -62,23 +113,24 @@ static void l2x0_inv_range(unsigned long start, unsigned long end) ...@@ -62,23 +113,24 @@ static void l2x0_inv_range(unsigned long start, unsigned long end)
spin_lock_irqsave(&l2x0_lock, flags); spin_lock_irqsave(&l2x0_lock, flags);
if (start & (CACHE_LINE_SIZE - 1)) { if (start & (CACHE_LINE_SIZE - 1)) {
start &= ~(CACHE_LINE_SIZE - 1); start &= ~(CACHE_LINE_SIZE - 1);
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); debug_writel(0x03);
writel(start, base + L2X0_CLEAN_INV_LINE_PA); l2x0_flush_line(start);
debug_writel(0x00);
start += CACHE_LINE_SIZE; start += CACHE_LINE_SIZE;
} }
if (end & (CACHE_LINE_SIZE - 1)) { if (end & (CACHE_LINE_SIZE - 1)) {
end &= ~(CACHE_LINE_SIZE - 1); end &= ~(CACHE_LINE_SIZE - 1);
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); debug_writel(0x03);
writel(end, base + L2X0_CLEAN_INV_LINE_PA); l2x0_flush_line(end);
debug_writel(0x00);
} }
while (start < end) { while (start < end) {
unsigned long blk_end = start + min(end - start, 4096UL); unsigned long blk_end = start + min(end - start, 4096UL);
while (start < blk_end) { while (start < blk_end) {
cache_wait(base + L2X0_INV_LINE_PA, 1); l2x0_inv_line(start);
writel(start, base + L2X0_INV_LINE_PA);
start += CACHE_LINE_SIZE; start += CACHE_LINE_SIZE;
} }
...@@ -103,8 +155,7 @@ static void l2x0_clean_range(unsigned long start, unsigned long end) ...@@ -103,8 +155,7 @@ static void l2x0_clean_range(unsigned long start, unsigned long end)
unsigned long blk_end = start + min(end - start, 4096UL); unsigned long blk_end = start + min(end - start, 4096UL);
while (start < blk_end) { while (start < blk_end) {
cache_wait(base + L2X0_CLEAN_LINE_PA, 1); l2x0_clean_line(start);
writel(start, base + L2X0_CLEAN_LINE_PA);
start += CACHE_LINE_SIZE; start += CACHE_LINE_SIZE;
} }
...@@ -128,11 +179,12 @@ static void l2x0_flush_range(unsigned long start, unsigned long end) ...@@ -128,11 +179,12 @@ static void l2x0_flush_range(unsigned long start, unsigned long end)
while (start < end) { while (start < end) {
unsigned long blk_end = start + min(end - start, 4096UL); unsigned long blk_end = start + min(end - start, 4096UL);
debug_writel(0x03);
while (start < blk_end) { while (start < blk_end) {
cache_wait(base + L2X0_CLEAN_INV_LINE_PA, 1); l2x0_flush_line(start);
writel(start, base + L2X0_CLEAN_INV_LINE_PA);
start += CACHE_LINE_SIZE; start += CACHE_LINE_SIZE;
} }
debug_writel(0x00);
if (blk_end < end) { if (blk_end < end) {
spin_unlock_irqrestore(&l2x0_lock, flags); spin_unlock_irqrestore(&l2x0_lock, flags);
......
...@@ -10,12 +10,17 @@ ...@@ -10,12 +10,17 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/smp.h>
#include <linux/percpu.h>
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
static DEFINE_SPINLOCK(cpu_asid_lock); static DEFINE_SPINLOCK(cpu_asid_lock);
unsigned int cpu_last_asid = ASID_FIRST_VERSION; unsigned int cpu_last_asid = ASID_FIRST_VERSION;
#ifdef CONFIG_SMP
DEFINE_PER_CPU(struct mm_struct *, current_mm);
#endif
/* /*
* We fork()ed a process, and we need a new context for the child * We fork()ed a process, and we need a new context for the child
...@@ -26,13 +31,109 @@ unsigned int cpu_last_asid = ASID_FIRST_VERSION; ...@@ -26,13 +31,109 @@ unsigned int cpu_last_asid = ASID_FIRST_VERSION;
void __init_new_context(struct task_struct *tsk, struct mm_struct *mm) void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{ {
mm->context.id = 0; mm->context.id = 0;
spin_lock_init(&mm->context.id_lock);
} }
static void flush_context(void)
{
/* set the reserved ASID before flushing the TLB */
asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (0));
isb();
local_flush_tlb_all();
if (icache_is_vivt_asid_tagged()) {
__flush_icache_all();
dsb();
}
}
#ifdef CONFIG_SMP
static void set_mm_context(struct mm_struct *mm, unsigned int asid)
{
unsigned long flags;
/*
* Locking needed for multi-threaded applications where the
* same mm->context.id could be set from different CPUs during
* the broadcast. This function is also called via IPI so the
* mm->context.id_lock has to be IRQ-safe.
*/
spin_lock_irqsave(&mm->context.id_lock, flags);
if (likely((mm->context.id ^ cpu_last_asid) >> ASID_BITS)) {
/*
* Old version of ASID found. Set the new one and
* reset mm_cpumask(mm).
*/
mm->context.id = asid;
cpumask_clear(mm_cpumask(mm));
}
spin_unlock_irqrestore(&mm->context.id_lock, flags);
/*
* Set the mm_cpumask(mm) bit for the current CPU.
*/
cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
}
/*
* Reset the ASID on the current CPU. This function call is broadcast
* from the CPU handling the ASID rollover and holding cpu_asid_lock.
*/
static void reset_context(void *info)
{
unsigned int asid;
unsigned int cpu = smp_processor_id();
struct mm_struct *mm = per_cpu(current_mm, cpu);
/*
* Check if a current_mm was set on this CPU as it might still
* be in the early booting stages and using the reserved ASID.
*/
if (!mm)
return;
smp_rmb();
asid = cpu_last_asid + cpu + 1;
flush_context();
set_mm_context(mm, asid);
/* set the new ASID */
asm("mcr p15, 0, %0, c13, c0, 1\n" : : "r" (mm->context.id));
isb();
}
#else
static inline void set_mm_context(struct mm_struct *mm, unsigned int asid)
{
mm->context.id = asid;
cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id()));
}
#endif
void __new_context(struct mm_struct *mm) void __new_context(struct mm_struct *mm)
{ {
unsigned int asid; unsigned int asid;
spin_lock(&cpu_asid_lock); spin_lock(&cpu_asid_lock);
#ifdef CONFIG_SMP
/*
* Check the ASID again, in case the change was broadcast from
* another CPU before we acquired the lock.
*/
if (unlikely(((mm->context.id ^ cpu_last_asid) >> ASID_BITS) == 0)) {
cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm));
spin_unlock(&cpu_asid_lock);
return;
}
#endif
/*
* At this point, it is guaranteed that the current mm (with
* an old ASID) isn't active on any other CPU since the ASIDs
* are changed simultaneously via IPI.
*/
asid = ++cpu_last_asid; asid = ++cpu_last_asid;
if (asid == 0) if (asid == 0)
asid = cpu_last_asid = ASID_FIRST_VERSION; asid = cpu_last_asid = ASID_FIRST_VERSION;
...@@ -42,20 +143,15 @@ void __new_context(struct mm_struct *mm) ...@@ -42,20 +143,15 @@ void __new_context(struct mm_struct *mm)
* to start a new version and flush the TLB. * to start a new version and flush the TLB.
*/ */
if (unlikely((asid & ~ASID_MASK) == 0)) { if (unlikely((asid & ~ASID_MASK) == 0)) {
asid = ++cpu_last_asid; asid = cpu_last_asid + smp_processor_id() + 1;
/* set the reserved ASID before flushing the TLB */ flush_context();
asm("mcr p15, 0, %0, c13, c0, 1 @ set reserved context ID\n" #ifdef CONFIG_SMP
: smp_wmb();
: "r" (0)); smp_call_function(reset_context, NULL, 1);
isb(); #endif
flush_tlb_all(); cpu_last_asid += NR_CPUS;
if (icache_is_vivt_asid_tagged()) {
__flush_icache_all();
dsb();
} }
}
spin_unlock(&cpu_asid_lock);
cpumask_copy(mm_cpumask(mm), cpumask_of(smp_processor_id())); set_mm_context(mm, asid);
mm->context.id = asid; spin_unlock(&cpu_asid_lock);
} }
...@@ -29,9 +29,6 @@ ...@@ -29,9 +29,6 @@
#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB" #error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
#endif #endif
#define CONSISTENT_END (0xffe00000)
#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE)
#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) #define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT) #define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT)
#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) #define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT)
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/sizes.h> #include <asm/sizes.h>
#include <asm/tlb.h> #include <asm/tlb.h>
#include <asm/fixmap.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
...@@ -32,19 +33,21 @@ ...@@ -32,19 +33,21 @@
static unsigned long phys_initrd_start __initdata = 0; static unsigned long phys_initrd_start __initdata = 0;
static unsigned long phys_initrd_size __initdata = 0; static unsigned long phys_initrd_size __initdata = 0;
static void __init early_initrd(char **p) static int __init early_initrd(char *p)
{ {
unsigned long start, size; unsigned long start, size;
char *endp;
start = memparse(*p, p); start = memparse(p, &endp);
if (**p == ',') { if (*endp == ',') {
size = memparse((*p) + 1, p); size = memparse(endp + 1, NULL);
phys_initrd_start = start; phys_initrd_start = start;
phys_initrd_size = size; phys_initrd_size = size;
} }
return 0;
} }
__early_param("initrd=", early_initrd); early_param("initrd", early_initrd);
static int __init parse_tag_initrd(const struct tag *tag) static int __init parse_tag_initrd(const struct tag *tag)
{ {
...@@ -560,7 +563,7 @@ static void __init free_unused_memmap_node(int node, struct meminfo *mi) ...@@ -560,7 +563,7 @@ static void __init free_unused_memmap_node(int node, struct meminfo *mi)
*/ */
void __init mem_init(void) void __init mem_init(void)
{ {
unsigned int codesize, datasize, initsize; unsigned long reserved_pages, free_pages;
int i, node; int i, node;
#ifndef CONFIG_DISCONTIGMEM #ifndef CONFIG_DISCONTIGMEM
...@@ -596,6 +599,33 @@ void __init mem_init(void) ...@@ -596,6 +599,33 @@ void __init mem_init(void)
totalram_pages += totalhigh_pages; totalram_pages += totalhigh_pages;
#endif #endif
reserved_pages = free_pages = 0;
for_each_online_node(node) {
pg_data_t *n = NODE_DATA(node);
struct page *map = pgdat_page_nr(n, 0) - n->node_start_pfn;
for_each_nodebank(i, &meminfo, node) {
struct membank *bank = &meminfo.bank[i];
unsigned int pfn1, pfn2;
struct page *page, *end;
pfn1 = bank_pfn_start(bank);
pfn2 = bank_pfn_end(bank);
page = map + pfn1;
end = map + pfn2;
do {
if (PageReserved(page))
reserved_pages++;
else if (!page_count(page))
free_pages++;
page++;
} while (page < end);
}
}
/* /*
* Since our memory may not be contiguous, calculate the * Since our memory may not be contiguous, calculate the
* real number of pages we have in this system * real number of pages we have in this system
...@@ -608,16 +638,71 @@ void __init mem_init(void) ...@@ -608,16 +638,71 @@ void __init mem_init(void)
} }
printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT)); printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
codesize = _etext - _text; printk(KERN_NOTICE "Memory: %luk/%luk available, %luk reserved, %luK highmem\n",
datasize = _end - _data; nr_free_pages() << (PAGE_SHIFT-10),
initsize = __init_end - __init_begin; free_pages << (PAGE_SHIFT-10),
reserved_pages << (PAGE_SHIFT-10),
printk(KERN_NOTICE "Memory: %luKB available (%dK code, "
"%dK data, %dK init, %luK highmem)\n",
nr_free_pages() << (PAGE_SHIFT-10), codesize >> 10,
datasize >> 10, initsize >> 10,
totalhigh_pages << (PAGE_SHIFT-10)); totalhigh_pages << (PAGE_SHIFT-10));
#define MLK(b, t) b, t, ((t) - (b)) >> 10
#define MLM(b, t) b, t, ((t) - (b)) >> 20
#define MLK_ROUNDUP(b, t) b, t, DIV_ROUND_UP(((t) - (b)), SZ_1K)
printk(KERN_NOTICE "Virtual kernel memory layout:\n"
" vector : 0x%08lx - 0x%08lx (%4ld kB)\n"
" fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
#ifdef CONFIG_MMU
" DMA : 0x%08lx - 0x%08lx (%4ld MB)\n"
#endif
" vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
" lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
#ifdef CONFIG_HIGHMEM
" pkmap : 0x%08lx - 0x%08lx (%4ld MB)\n"
#endif
" modules : 0x%08lx - 0x%08lx (%4ld MB)\n"
" .init : 0x%p" " - 0x%p" " (%4d kB)\n"
" .text : 0x%p" " - 0x%p" " (%4d kB)\n"
" .data : 0x%p" " - 0x%p" " (%4d kB)\n",
MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) +
(PAGE_SIZE)),
MLK(FIXADDR_START, FIXADDR_TOP),
#ifdef CONFIG_MMU
MLM(CONSISTENT_BASE, CONSISTENT_END),
#endif
MLM(VMALLOC_START, VMALLOC_END),
MLM(PAGE_OFFSET, (unsigned long)high_memory),
#ifdef CONFIG_HIGHMEM
MLM(PKMAP_BASE, (PKMAP_BASE) + (LAST_PKMAP) *
(PAGE_SIZE)),
#endif
MLM(MODULES_VADDR, MODULES_END),
MLK_ROUNDUP(__init_begin, __init_end),
MLK_ROUNDUP(_text, _etext),
MLK_ROUNDUP(_data, _edata));
#undef MLK
#undef MLM
#undef MLK_ROUNDUP
/*
* Check boundaries twice: Some fundamental inconsistencies can
* be detected at build time already.
*/
#ifdef CONFIG_MMU
BUILD_BUG_ON(VMALLOC_END > CONSISTENT_BASE);
BUG_ON(VMALLOC_END > CONSISTENT_BASE);
BUILD_BUG_ON(TASK_SIZE > MODULES_VADDR);
BUG_ON(TASK_SIZE > MODULES_VADDR);
#endif
#ifdef CONFIG_HIGHMEM
BUILD_BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > PAGE_OFFSET);
BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > PAGE_OFFSET);
#endif
if (PAGE_SIZE >= 16384 && num_physpages <= 128) { if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
extern int sysctl_overcommit_memory; extern int sysctl_overcommit_memory;
/* /*
......
...@@ -139,8 +139,8 @@ void __check_kvm_seq(struct mm_struct *mm) ...@@ -139,8 +139,8 @@ void __check_kvm_seq(struct mm_struct *mm)
* which requires the new ioremap'd region to be referenced, the CPU will * which requires the new ioremap'd region to be referenced, the CPU will
* reference the _old_ region. * reference the _old_ region.
* *
* Note that get_vm_area() allocates a guard 4K page, so we need to mask * Note that get_vm_area_caller() allocates a guard 4K page, so we need to
* the size back to 1MB aligned or we will overflow in the loop below. * mask the size back to 1MB aligned or we will overflow in the loop below.
*/ */
static void unmap_area_sections(unsigned long virt, unsigned long size) static void unmap_area_sections(unsigned long virt, unsigned long size)
{ {
...@@ -254,22 +254,8 @@ remap_area_supersections(unsigned long virt, unsigned long pfn, ...@@ -254,22 +254,8 @@ remap_area_supersections(unsigned long virt, unsigned long pfn,
} }
#endif #endif
void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
/* unsigned long offset, size_t size, unsigned int mtype, void *caller)
* Remap an arbitrary physical address space into the kernel virtual
* address space. Needed when the kernel wants to access high addresses
* directly.
*
* NOTE! We need to allow non-page-aligned mappings too: we will obviously
* have to convert them into an offset in a page-aligned mapping, but the
* caller shouldn't need to know that small detail.
*
* 'flags' are the extra L_PTE_ flags that you want to specify for this
* mapping. See <asm/pgtable.h> for more information.
*/
void __iomem *
__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
unsigned int mtype)
{ {
const struct mem_type *type; const struct mem_type *type;
int err; int err;
...@@ -291,7 +277,7 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, ...@@ -291,7 +277,7 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
*/ */
size = PAGE_ALIGN(offset + size); size = PAGE_ALIGN(offset + size);
area = get_vm_area(size, VM_IOREMAP); area = get_vm_area_caller(size, VM_IOREMAP, caller);
if (!area) if (!area)
return NULL; return NULL;
addr = (unsigned long)area->addr; addr = (unsigned long)area->addr;
...@@ -318,10 +304,9 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size, ...@@ -318,10 +304,9 @@ __arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
flush_cache_vmap(addr, addr + size); flush_cache_vmap(addr, addr + size);
return (void __iomem *) (offset + addr); return (void __iomem *) (offset + addr);
} }
EXPORT_SYMBOL(__arm_ioremap_pfn);
void __iomem * void __iomem *__arm_ioremap_caller(unsigned long phys_addr, size_t size,
__arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) unsigned int mtype, void *caller)
{ {
unsigned long last_addr; unsigned long last_addr;
unsigned long offset = phys_addr & ~PAGE_MASK; unsigned long offset = phys_addr & ~PAGE_MASK;
...@@ -334,7 +319,33 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype) ...@@ -334,7 +319,33 @@ __arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
if (!size || last_addr < phys_addr) if (!size || last_addr < phys_addr)
return NULL; return NULL;
return __arm_ioremap_pfn(pfn, offset, size, mtype); return __arm_ioremap_pfn_caller(pfn, offset, size, mtype,
caller);
}
/*
* Remap an arbitrary physical address space into the kernel virtual
* address space. Needed when the kernel wants to access high addresses
* directly.
*
* NOTE! We need to allow non-page-aligned mappings too: we will obviously
* have to convert them into an offset in a page-aligned mapping, but the
* caller shouldn't need to know that small detail.
*/
void __iomem *
__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
unsigned int mtype)
{
return __arm_ioremap_pfn_caller(pfn, offset, size, mtype,
__builtin_return_address(0));
}
EXPORT_SYMBOL(__arm_ioremap_pfn);
void __iomem *
__arm_ioremap(unsigned long phys_addr, size_t size, unsigned int mtype)
{
return __arm_ioremap_caller(phys_addr, size, mtype,
__builtin_return_address(0));
} }
EXPORT_SYMBOL(__arm_ioremap); EXPORT_SYMBOL(__arm_ioremap);
......
...@@ -100,18 +100,17 @@ static struct cachepolicy cache_policies[] __initdata = { ...@@ -100,18 +100,17 @@ static struct cachepolicy cache_policies[] __initdata = {
* writebuffer to be turned off. (Note: the write * writebuffer to be turned off. (Note: the write
* buffer should not be on and the cache off). * buffer should not be on and the cache off).
*/ */
static void __init early_cachepolicy(char **p) static int __init early_cachepolicy(char *p)
{ {
int i; int i;
for (i = 0; i < ARRAY_SIZE(cache_policies); i++) { for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
int len = strlen(cache_policies[i].policy); int len = strlen(cache_policies[i].policy);
if (memcmp(*p, cache_policies[i].policy, len) == 0) { if (memcmp(p, cache_policies[i].policy, len) == 0) {
cachepolicy = i; cachepolicy = i;
cr_alignment &= ~cache_policies[i].cr_mask; cr_alignment &= ~cache_policies[i].cr_mask;
cr_no_alignment &= ~cache_policies[i].cr_mask; cr_no_alignment &= ~cache_policies[i].cr_mask;
*p += len;
break; break;
} }
} }
...@@ -130,36 +129,37 @@ static void __init early_cachepolicy(char **p) ...@@ -130,36 +129,37 @@ static void __init early_cachepolicy(char **p)
} }
flush_cache_all(); flush_cache_all();
set_cr(cr_alignment); set_cr(cr_alignment);
return 0;
} }
__early_param("cachepolicy=", early_cachepolicy); early_param("cachepolicy", early_cachepolicy);
static void __init early_nocache(char **__unused) static int __init early_nocache(char *__unused)
{ {
char *p = "buffered"; char *p = "buffered";
printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p); printk(KERN_WARNING "nocache is deprecated; use cachepolicy=%s\n", p);
early_cachepolicy(&p); early_cachepolicy(p);
return 0;
} }
__early_param("nocache", early_nocache); early_param("nocache", early_nocache);
static void __init early_nowrite(char **__unused) static int __init early_nowrite(char *__unused)
{ {
char *p = "uncached"; char *p = "uncached";
printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p); printk(KERN_WARNING "nowb is deprecated; use cachepolicy=%s\n", p);
early_cachepolicy(&p); early_cachepolicy(p);
return 0;
} }
__early_param("nowb", early_nowrite); early_param("nowb", early_nowrite);
static void __init early_ecc(char **p) static int __init early_ecc(char *p)
{ {
if (memcmp(*p, "on", 2) == 0) { if (memcmp(p, "on", 2) == 0)
ecc_mask = PMD_PROTECTION; ecc_mask = PMD_PROTECTION;
*p += 2; else if (memcmp(p, "off", 3) == 0)
} else if (memcmp(*p, "off", 3) == 0) {
ecc_mask = 0; ecc_mask = 0;
*p += 3; return 0;
}
} }
__early_param("ecc=", early_ecc); early_param("ecc", early_ecc);
static int __init noalign_setup(char *__unused) static int __init noalign_setup(char *__unused)
{ {
...@@ -670,9 +670,9 @@ static unsigned long __initdata vmalloc_reserve = SZ_128M; ...@@ -670,9 +670,9 @@ static unsigned long __initdata vmalloc_reserve = SZ_128M;
* bytes. This can be used to increase (or decrease) the vmalloc * bytes. This can be used to increase (or decrease) the vmalloc
* area - the default is 128m. * area - the default is 128m.
*/ */
static void __init early_vmalloc(char **arg) static int __init early_vmalloc(char *arg)
{ {
vmalloc_reserve = memparse(*arg, arg); vmalloc_reserve = memparse(arg, NULL);
if (vmalloc_reserve < SZ_16M) { if (vmalloc_reserve < SZ_16M) {
vmalloc_reserve = SZ_16M; vmalloc_reserve = SZ_16M;
...@@ -687,8 +687,9 @@ static void __init early_vmalloc(char **arg) ...@@ -687,8 +687,9 @@ static void __init early_vmalloc(char **arg)
"vmalloc area is too big, limiting to %luMB\n", "vmalloc area is too big, limiting to %luMB\n",
vmalloc_reserve >> 20); vmalloc_reserve >> 20);
} }
return 0;
} }
__early_param("vmalloc=", early_vmalloc); early_param("vmalloc", early_vmalloc);
#define VMALLOC_MIN (void *)(VMALLOC_END - vmalloc_reserve) #define VMALLOC_MIN (void *)(VMALLOC_END - vmalloc_reserve)
......
...@@ -74,6 +74,12 @@ void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset, ...@@ -74,6 +74,12 @@ void __iomem *__arm_ioremap_pfn(unsigned long pfn, unsigned long offset,
} }
EXPORT_SYMBOL(__arm_ioremap_pfn); EXPORT_SYMBOL(__arm_ioremap_pfn);
void __iomem *__arm_ioremap_pfn_caller(unsigned long pfn, unsigned long offset,
size_t size, unsigned int mtype, void *caller)
{
return __arm_ioremap_pfn(pfn, offset, size, mtype);
}
void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size,
unsigned int mtype) unsigned int mtype)
{ {
...@@ -81,6 +87,12 @@ void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size, ...@@ -81,6 +87,12 @@ void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size,
} }
EXPORT_SYMBOL(__arm_ioremap); EXPORT_SYMBOL(__arm_ioremap);
void __iomem *__arm_ioremap(unsigned long phys_addr, size_t size,
unsigned int mtype, void *caller)
{
return __arm_ioremap(phys_addr, size, mtype);
}
void __iounmap(volatile void __iomem *addr) void __iounmap(volatile void __iomem *addr)
{ {
} }
......
...@@ -34,7 +34,8 @@ void * __iomem __iop3xx_ioremap(unsigned long cookie, size_t size, ...@@ -34,7 +34,8 @@ void * __iomem __iop3xx_ioremap(unsigned long cookie, size_t size,
retval = (void *) IOP3XX_PMMR_PHYS_TO_VIRT(cookie); retval = (void *) IOP3XX_PMMR_PHYS_TO_VIRT(cookie);
break; break;
default: default:
retval = __arm_ioremap(cookie, size, mtype); retval = __arm_ioremap_caller(cookie, size, mtype,
__builtin_return_address(0));
} }
return retval; return retval;
......
...@@ -21,6 +21,6 @@ ...@@ -21,6 +21,6 @@
#define __ASM_ARCH_MXC_VMALLOC_H__ #define __ASM_ARCH_MXC_VMALLOC_H__
/* vmalloc ending address */ /* vmalloc ending address */
#define VMALLOC_END 0xF4000000 #define VMALLOC_END 0xf4000000UL
#endif /* __ASM_ARCH_MXC_VMALLOC_H__ */ #endif /* __ASM_ARCH_MXC_VMALLOC_H__ */
...@@ -22,6 +22,7 @@ config ARCH_OMAP3 ...@@ -22,6 +22,7 @@ config ARCH_OMAP3
bool "TI OMAP3" bool "TI OMAP3"
select CPU_V7 select CPU_V7
select COMMON_CLKDEV select COMMON_CLKDEV
select ARM_L1_CACHE_SHIFT_6
config ARCH_OMAP4 config ARCH_OMAP4
bool "TI OMAP4" bool "TI OMAP4"
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#define OMAP44XX_GIC_CPU_BASE 0x48240100 #define OMAP44XX_GIC_CPU_BASE 0x48240100
#define OMAP44XX_SCU_BASE 0x48240000 #define OMAP44XX_SCU_BASE 0x48240000
#define OMAP44XX_LOCAL_TWD_BASE 0x48240600 #define OMAP44XX_LOCAL_TWD_BASE 0x48240600
#define OMAP44XX_L2CACHE_BASE 0x48242000
#define OMAP44XX_WKUPGEN_BASE 0x48281000 #define OMAP44XX_WKUPGEN_BASE 0x48281000
#define OMAP44XX_MAILBOX_BASE (L4_44XX_BASE + 0xF4000) #define OMAP44XX_MAILBOX_BASE (L4_44XX_BASE + 0xF4000)
......
...@@ -128,7 +128,7 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type) ...@@ -128,7 +128,7 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type)
return XLATE(p, L4_EMU_44XX_PHYS, L4_EMU_44XX_VIRT); return XLATE(p, L4_EMU_44XX_PHYS, L4_EMU_44XX_VIRT);
} }
#endif #endif
return __arm_ioremap(p, size, type); return __arm_ioremap_caller(p, size, type, __builtin_return_address(0));
} }
EXPORT_SYMBOL(omap_ioremap); EXPORT_SYMBOL(omap_ioremap);
......
...@@ -15,6 +15,6 @@ ...@@ -15,6 +15,6 @@
#ifndef __ASM_ARCH_VMALLOC_H #ifndef __ASM_ARCH_VMALLOC_H
#define __ASM_ARCH_VMALLOC_H #define __ASM_ARCH_VMALLOC_H
#define VMALLOC_END (0xE0000000) #define VMALLOC_END (0xe0000000UL)
#endif /* __ASM_ARCH_VMALLOC_H */ #endif /* __ASM_ARCH_VMALLOC_H */
...@@ -9,4 +9,4 @@ ...@@ -9,4 +9,4 @@
* http://www.opensource.org/licenses/gpl-license.html * http://www.opensource.org/licenses/gpl-license.html
* http://www.gnu.org/copyleft/gpl.html * http://www.gnu.org/copyleft/gpl.html
*/ */
#define VMALLOC_END (0xF0000000) #define VMALLOC_END 0xf0000000UL
...@@ -430,7 +430,11 @@ static inline void vfp_pm_init(void) { } ...@@ -430,7 +430,11 @@ static inline void vfp_pm_init(void) { }
* saved one. This function is used by the ptrace mechanism. * saved one. This function is used by the ptrace mechanism.
*/ */
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void vfp_sync_state(struct thread_info *thread) void vfp_sync_hwstate(struct thread_info *thread)
{
}
void vfp_flush_hwstate(struct thread_info *thread)
{ {
/* /*
* On SMP systems, the VFP state is automatically saved at every * On SMP systems, the VFP state is automatically saved at every
...@@ -441,35 +445,48 @@ void vfp_sync_state(struct thread_info *thread) ...@@ -441,35 +445,48 @@ void vfp_sync_state(struct thread_info *thread)
thread->vfpstate.hard.cpu = NR_CPUS; thread->vfpstate.hard.cpu = NR_CPUS;
} }
#else #else
void vfp_sync_state(struct thread_info *thread) void vfp_sync_hwstate(struct thread_info *thread)
{ {
unsigned int cpu = get_cpu(); unsigned int cpu = get_cpu();
u32 fpexc = fmrx(FPEXC);
/* /*
* If VFP is enabled, the previous state was already saved and * If the thread we're interested in is the current owner of the
* last_VFP_context updated. * hardware VFP state, then we need to save its state.
*/ */
if (fpexc & FPEXC_EN) if (last_VFP_context[cpu] == &thread->vfpstate) {
goto out; u32 fpexc = fmrx(FPEXC);
if (!last_VFP_context[cpu])
goto out;
/* /*
* Save the last VFP state on this CPU. * Save the last VFP state on this CPU.
*/ */
fmxr(FPEXC, fpexc | FPEXC_EN); fmxr(FPEXC, fpexc | FPEXC_EN);
vfp_save_state(last_VFP_context[cpu], fpexc); vfp_save_state(&thread->vfpstate, fpexc | FPEXC_EN);
fmxr(FPEXC, fpexc); fmxr(FPEXC, fpexc);
}
put_cpu();
}
void vfp_flush_hwstate(struct thread_info *thread)
{
unsigned int cpu = get_cpu();
/*
* If the thread we're interested in is the current owner of the
* hardware VFP state, then we need to save its state.
*/
if (last_VFP_context[cpu] == &thread->vfpstate) {
u32 fpexc = fmrx(FPEXC);
fmxr(FPEXC, fpexc & ~FPEXC_EN);
/* /*
* Set the context to NULL to force a reload the next time the thread * Set the context to NULL to force a reload the next time
* uses the VFP. * the thread uses the VFP.
*/ */
last_VFP_context[cpu] = NULL; last_VFP_context[cpu] = NULL;
}
out:
put_cpu(); put_cpu();
} }
#endif #endif
......
...@@ -71,6 +71,7 @@ struct uart_amba_port { ...@@ -71,6 +71,7 @@ struct uart_amba_port {
unsigned int im; /* interrupt mask */ unsigned int im; /* interrupt mask */
unsigned int old_status; unsigned int old_status;
unsigned int ifls; /* vendor-specific */ unsigned int ifls; /* vendor-specific */
bool autorts;
}; };
/* There is by now at least one vendor with differing details, so handle it */ /* There is by now at least one vendor with differing details, so handle it */
...@@ -308,6 +309,11 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl) ...@@ -308,6 +309,11 @@ static void pl011_set_mctrl(struct uart_port *port, unsigned int mctrl)
TIOCMBIT(TIOCM_OUT1, UART011_CR_OUT1); TIOCMBIT(TIOCM_OUT1, UART011_CR_OUT1);
TIOCMBIT(TIOCM_OUT2, UART011_CR_OUT2); TIOCMBIT(TIOCM_OUT2, UART011_CR_OUT2);
TIOCMBIT(TIOCM_LOOP, UART011_CR_LBE); TIOCMBIT(TIOCM_LOOP, UART011_CR_LBE);
if (uap->autorts) {
/* We need to disable auto-RTS if we want to turn RTS off */
TIOCMBIT(TIOCM_RTS, UART011_CR_RTSEN);
}
#undef TIOCMBIT #undef TIOCMBIT
writew(cr, uap->port.membase + UART011_CR); writew(cr, uap->port.membase + UART011_CR);
...@@ -437,6 +443,7 @@ static void pl011_shutdown(struct uart_port *port) ...@@ -437,6 +443,7 @@ static void pl011_shutdown(struct uart_port *port)
/* /*
* disable the port * disable the port
*/ */
uap->autorts = false;
writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR); writew(UART01x_CR_UARTEN | UART011_CR_TXE, uap->port.membase + UART011_CR);
/* /*
...@@ -456,6 +463,7 @@ static void ...@@ -456,6 +463,7 @@ static void
pl011_set_termios(struct uart_port *port, struct ktermios *termios, pl011_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old) struct ktermios *old)
{ {
struct uart_amba_port *uap = (struct uart_amba_port *)port;
unsigned int lcr_h, old_cr; unsigned int lcr_h, old_cr;
unsigned long flags; unsigned long flags;
unsigned int baud, quot; unsigned int baud, quot;
...@@ -532,6 +540,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -532,6 +540,17 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
old_cr = readw(port->membase + UART011_CR); old_cr = readw(port->membase + UART011_CR);
writew(0, port->membase + UART011_CR); writew(0, port->membase + UART011_CR);
if (termios->c_cflag & CRTSCTS) {
if (old_cr & UART011_CR_RTS)
old_cr |= UART011_CR_RTSEN;
old_cr |= UART011_CR_CTSEN;
uap->autorts = true;
} else {
old_cr &= ~(UART011_CR_CTSEN | UART011_CR_RTSEN);
uap->autorts = false;
}
/* Set baud rate */ /* Set baud rate */
writew(quot & 0x3f, port->membase + UART011_FBRD); writew(quot & 0x3f, port->membase + UART011_FBRD);
writew(quot >> 6, port->membase + UART011_IBRD); writew(quot >> 6, port->membase + UART011_IBRD);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment