Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6

Conflicts:
	drivers/net/wireless/iwlwifi/iwl-6000.c
	net/core/dev.c
This commit is contained in:
David S. Miller 2010-04-21 01:14:25 -07:00
commit 87eb367003
266 changed files with 4540 additions and 2576 deletions

View File

@ -34,7 +34,7 @@ NMI handler.
cpu = smp_processor_id(); cpu = smp_processor_id();
++nmi_count(cpu); ++nmi_count(cpu);
if (!rcu_dereference(nmi_callback)(regs, cpu)) if (!rcu_dereference_sched(nmi_callback)(regs, cpu))
default_do_nmi(regs); default_do_nmi(regs);
nmi_exit(); nmi_exit();
@ -47,12 +47,13 @@ function pointer. If this handler returns zero, do_nmi() invokes the
default_do_nmi() function to handle a machine-specific NMI. Finally, default_do_nmi() function to handle a machine-specific NMI. Finally,
preemption is restored. preemption is restored.
Strictly speaking, rcu_dereference() is not needed, since this code runs In theory, rcu_dereference_sched() is not needed, since this code runs
only on i386, which does not need rcu_dereference() anyway. However, only on i386, which in theory does not need rcu_dereference_sched()
it is a good documentation aid, particularly for anyone attempting to anyway. However, in practice it is a good documentation aid, particularly
do something similar on Alpha. for anyone attempting to do something similar on Alpha or on systems
with aggressive optimizing compilers.
Quick Quiz: Why might the rcu_dereference() be necessary on Alpha, Quick Quiz: Why might the rcu_dereference_sched() be necessary on Alpha,
given that the code referenced by the pointer is read-only? given that the code referenced by the pointer is read-only?
@ -99,17 +100,21 @@ invoke irq_enter() and irq_exit() on NMI entry and exit, respectively.
Answer to Quick Quiz Answer to Quick Quiz
Why might the rcu_dereference() be necessary on Alpha, given Why might the rcu_dereference_sched() be necessary on Alpha, given
that the code referenced by the pointer is read-only? that the code referenced by the pointer is read-only?
Answer: The caller to set_nmi_callback() might well have Answer: The caller to set_nmi_callback() might well have
initialized some data that is to be used by the initialized some data that is to be used by the new NMI
new NMI handler. In this case, the rcu_dereference() handler. In this case, the rcu_dereference_sched() would
would be needed, because otherwise a CPU that received be needed, because otherwise a CPU that received an NMI
an NMI just after the new handler was set might see just after the new handler was set might see the pointer
the pointer to the new NMI handler, but the old to the new NMI handler, but the old pre-initialized
pre-initialized version of the handler's data. version of the handler's data.
More important, the rcu_dereference() makes it clear This same sad story can happen on other CPUs when using
to someone reading the code that the pointer is being a compiler with aggressive pointer-value speculation
protected by RCU. optimizations.
More important, the rcu_dereference_sched() makes it
clear to someone reading the code that the pointer is
being protected by RCU-sched.

View File

@ -260,7 +260,8 @@ over a rather long period of time, but improvements are always welcome!
The reason that it is permissible to use RCU list-traversal The reason that it is permissible to use RCU list-traversal
primitives when the update-side lock is held is that doing so primitives when the update-side lock is held is that doing so
can be quite helpful in reducing code bloat when common code is can be quite helpful in reducing code bloat when common code is
shared between readers and updaters. shared between readers and updaters. Additional primitives
are provided for this case, as discussed in lockdep.txt.
10. Conversely, if you are in an RCU read-side critical section, 10. Conversely, if you are in an RCU read-side critical section,
and you don't hold the appropriate update-side lock, you -must- and you don't hold the appropriate update-side lock, you -must-
@ -344,8 +345,8 @@ over a rather long period of time, but improvements are always welcome!
requiring SRCU's read-side deadlock immunity or low read-side requiring SRCU's read-side deadlock immunity or low read-side
realtime latency. realtime latency.
Note that, rcu_assign_pointer() and rcu_dereference() relate to Note that, rcu_assign_pointer() relates to SRCU just as they do
SRCU just as they do to other forms of RCU. to other forms of RCU.
15. The whole point of call_rcu(), synchronize_rcu(), and friends 15. The whole point of call_rcu(), synchronize_rcu(), and friends
is to wait until all pre-existing readers have finished before is to wait until all pre-existing readers have finished before

View File

@ -32,9 +32,20 @@ checking of rcu_dereference() primitives:
srcu_dereference(p, sp): srcu_dereference(p, sp):
Check for SRCU read-side critical section. Check for SRCU read-side critical section.
rcu_dereference_check(p, c): rcu_dereference_check(p, c):
Use explicit check expression "c". Use explicit check expression "c". This is useful in
code that is invoked by both readers and updaters.
rcu_dereference_raw(p) rcu_dereference_raw(p)
Don't check. (Use sparingly, if at all.) Don't check. (Use sparingly, if at all.)
rcu_dereference_protected(p, c):
Use explicit check expression "c", and omit all barriers
and compiler constraints. This is useful when the data
structure cannot change, for example, in code that is
invoked only by updaters.
rcu_access_pointer(p):
Return the value of the pointer and omit all barriers,
but retain the compiler constraints that prevent duplicating
or coalescsing. This is useful when when testing the
value of the pointer itself, for example, against NULL.
The rcu_dereference_check() check expression can be any boolean The rcu_dereference_check() check expression can be any boolean
expression, but would normally include one of the rcu_read_lock_held() expression, but would normally include one of the rcu_read_lock_held()
@ -59,7 +70,20 @@ In case (1), the pointer is picked up in an RCU-safe manner for vanilla
RCU read-side critical sections, in case (2) the ->file_lock prevents RCU read-side critical sections, in case (2) the ->file_lock prevents
any change from taking place, and finally, in case (3) the current task any change from taking place, and finally, in case (3) the current task
is the only task accessing the file_struct, again preventing any change is the only task accessing the file_struct, again preventing any change
from taking place. from taking place. If the above statement was invoked only from updater
code, it could instead be written as follows:
file = rcu_dereference_protected(fdt->fd[fd],
lockdep_is_held(&files->file_lock) ||
atomic_read(&files->count) == 1);
This would verify cases #2 and #3 above, and furthermore lockdep would
complain if this was used in an RCU read-side critical section unless one
of these two cases held. Because rcu_dereference_protected() omits all
barriers and compiler constraints, it generates better code than do the
other flavors of rcu_dereference(). On the other hand, it is illegal
to use rcu_dereference_protected() if either the RCU-protected pointer
or the RCU-protected data that it points to can change concurrently.
There are currently only "universal" versions of the rcu_assign_pointer() There are currently only "universal" versions of the rcu_assign_pointer()
and RCU list-/tree-traversal primitives, which do not (yet) check for and RCU list-/tree-traversal primitives, which do not (yet) check for

View File

@ -840,6 +840,12 @@ SRCU: Initialization/cleanup
init_srcu_struct init_srcu_struct
cleanup_srcu_struct cleanup_srcu_struct
All: lockdep-checked RCU-protected pointer access
rcu_dereference_check
rcu_dereference_protected
rcu_access_pointer
See the comment headers in the source code (or the docbook generated See the comment headers in the source code (or the docbook generated
from them) for more information. from them) for more information.

View File

@ -68,6 +68,22 @@ like:
SYN_MT_REPORT SYN_MT_REPORT
SYN_REPORT SYN_REPORT
Here is the sequence after lifting one of the fingers:
ABS_MT_POSITION_X
ABS_MT_POSITION_Y
SYN_MT_REPORT
SYN_REPORT
And here is the sequence after lifting the remaining finger:
SYN_MT_REPORT
SYN_REPORT
If the driver reports one of BTN_TOUCH or ABS_PRESSURE in addition to the
ABS_MT events, the last SYN_MT_REPORT event may be omitted. Otherwise, the
last SYN_REPORT will be dropped by the input core, resulting in no
zero-finger event reaching userland.
Event Semantics Event Semantics
--------------- ---------------
@ -217,11 +233,6 @@ where examples can be found.
difference between the contact position and the approaching tool position difference between the contact position and the approaching tool position
could be used to derive tilt. could be used to derive tilt.
[2] The list can of course be extended. [2] The list can of course be extended.
[3] The multi-touch X driver is currently in the prototyping stage. At the [3] Multitouch X driver project: http://bitmath.org/code/multitouch/.
time of writing (April 2009), the MT protocol is not yet merged, and the
prototype implements finger matching, basic mouse support and two-finger
scrolling. The project aims at improving the quality of current multi-touch
functionality available in the Synaptics X driver, and in addition
implement more advanced gestures.
[4] See the section on event computation. [4] See the section on event computation.
[5] See the section on finger tracking. [5] See the section on finger tracking.

View File

@ -320,11 +320,6 @@ and is between 256 and 4096 characters. It is defined in the file
amd_iommu= [HW,X86-84] amd_iommu= [HW,X86-84]
Pass parameters to the AMD IOMMU driver in the system. Pass parameters to the AMD IOMMU driver in the system.
Possible values are: Possible values are:
isolate - enable device isolation (each device, as far
as possible, will get its own protection
domain) [default]
share - put every device behind one IOMMU into the
same protection domain
fullflush - enable flushing of IO/TLB entries when fullflush - enable flushing of IO/TLB entries when
they are unmapped. Otherwise they are they are unmapped. Otherwise they are
flushed before they will be reused, which flushed before they will be reused, which

View File

@ -485,8 +485,8 @@ S: Maintained
F: drivers/input/mouse/bcm5974.c F: drivers/input/mouse/bcm5974.c
APPLE SMC DRIVER APPLE SMC DRIVER
M: Nicolas Boichat <nicolas@boichat.ch> M: Henrik Rydberg <rydberg@euromail.se>
L: mactel-linux-devel@lists.sourceforge.net L: lm-sensors@lm-sensors.org
S: Maintained S: Maintained
F: drivers/hwmon/applesmc.c F: drivers/hwmon/applesmc.c
@ -971,6 +971,16 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.mcuos.com W: http://www.mcuos.com
S: Maintained S: Maintained
ARM/U300 MACHINE SUPPORT
M: Linus Walleij <linus.walleij@stericsson.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported
F: arch/arm/mach-u300/
F: drivers/i2c/busses/i2c-stu300.c
F: drivers/rtc/rtc-coh901331.c
F: drivers/watchdog/coh901327_wdt.c
F: drivers/dma/coh901318*
ARM/U8500 ARM ARCHITECTURE ARM/U8500 ARM ARCHITECTURE
M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)

View File

@ -1,8 +1,8 @@
VERSION = 2 VERSION = 2
PATCHLEVEL = 6 PATCHLEVEL = 6
SUBLEVEL = 34 SUBLEVEL = 34
EXTRAVERSION = -rc3 EXTRAVERSION = -rc5
NAME = Man-Eating Seals of Antiquity NAME = Sheep on Meth
# *DOCUMENTATION* # *DOCUMENTATION*
# To see a list of typical targets execute "make help" # To see a list of typical targets execute "make help"

View File

@ -172,7 +172,7 @@ not_angel:
adr r0, LC0 adr r0, LC0
ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp}) ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp})
THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip} ) THUMB( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip} )
THUMB( ldr sp, [r0, #28] ) THUMB( ldr sp, [r0, #32] )
subs r0, r0, r1 @ calculate the delta offset subs r0, r0, r1 @ calculate the delta offset
@ if delta is zero, we are @ if delta is zero, we are

View File

@ -11,7 +11,11 @@
#define kmap_prot PAGE_KERNEL #define kmap_prot PAGE_KERNEL
#define flush_cache_kmaps() flush_cache_all() #define flush_cache_kmaps() \
do { \
if (cache_is_vivt()) \
flush_cache_all(); \
} while (0)
extern pte_t *pkmap_page_table; extern pte_t *pkmap_page_table;
@ -21,11 +25,20 @@ extern void *kmap_high(struct page *page);
extern void *kmap_high_get(struct page *page); extern void *kmap_high_get(struct page *page);
extern void kunmap_high(struct page *page); extern void kunmap_high(struct page *page);
extern void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte);
extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte);
/*
* The following functions are already defined by <linux/highmem.h>
* when CONFIG_HIGHMEM is not set.
*/
#ifdef CONFIG_HIGHMEM
extern void *kmap(struct page *page); extern void *kmap(struct page *page);
extern void kunmap(struct page *page); extern void kunmap(struct page *page);
extern void *kmap_atomic(struct page *page, enum km_type type); extern void *kmap_atomic(struct page *page, enum km_type type);
extern void kunmap_atomic(void *kvaddr, enum km_type type); extern void kunmap_atomic(void *kvaddr, enum km_type type);
extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type); extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
extern struct page *kmap_atomic_to_page(const void *ptr); extern struct page *kmap_atomic_to_page(const void *ptr);
#endif
#endif #endif

View File

@ -18,6 +18,7 @@ enum km_type {
KM_IRQ1, KM_IRQ1,
KM_SOFTIRQ0, KM_SOFTIRQ0,
KM_SOFTIRQ1, KM_SOFTIRQ1,
KM_L1_CACHE,
KM_L2_CACHE, KM_L2_CACHE,
KM_TYPE_NR KM_TYPE_NR
}; };

View File

@ -59,23 +59,22 @@ struct iwmmxt_sigframe {
#endif /* CONFIG_IWMMXT */ #endif /* CONFIG_IWMMXT */
#ifdef CONFIG_VFP #ifdef CONFIG_VFP
#if __LINUX_ARM_ARCH__ < 6
/* For ARM pre-v6, we use fstmiax and fldmiax. This adds one extra
* word after the registers, and a word of padding at the end for
* alignment. */
#define VFP_MAGIC 0x56465001 #define VFP_MAGIC 0x56465001
#define VFP_STORAGE_SIZE 152
#else
#define VFP_MAGIC 0x56465002
#define VFP_STORAGE_SIZE 144
#endif
struct vfp_sigframe struct vfp_sigframe
{ {
unsigned long magic; unsigned long magic;
unsigned long size; unsigned long size;
union vfp_state storage; struct user_vfp ufp;
}; struct user_vfp_exc ufp_exc;
} __attribute__((__aligned__(8)));
/*
* 8 byte for magic and size, 264 byte for ufp, 12 bytes for ufp_exc,
* 4 bytes padding.
*/
#define VFP_STORAGE_SIZE sizeof(struct vfp_sigframe)
#endif /* CONFIG_VFP */ #endif /* CONFIG_VFP */
/* /*
@ -91,7 +90,7 @@ struct aux_sigframe {
#ifdef CONFIG_IWMMXT #ifdef CONFIG_IWMMXT
struct iwmmxt_sigframe iwmmxt; struct iwmmxt_sigframe iwmmxt;
#endif #endif
#if 0 && defined CONFIG_VFP /* Not yet saved. */ #ifdef CONFIG_VFP
struct vfp_sigframe vfp; struct vfp_sigframe vfp;
#endif #endif
/* Something that isn't a valid magic number for any coprocessor. */ /* Something that isn't a valid magic number for any coprocessor. */

View File

@ -83,11 +83,21 @@ struct user{
/* /*
* User specific VFP registers. If only VFPv2 is present, registers 16 to 31 * User specific VFP registers. If only VFPv2 is present, registers 16 to 31
* are ignored by the ptrace system call. * are ignored by the ptrace system call and the signal handler.
*/ */
struct user_vfp { struct user_vfp {
unsigned long long fpregs[32]; unsigned long long fpregs[32];
unsigned long fpscr; unsigned long fpscr;
}; };
/*
* VFP exception registers exposed to user space during signal delivery.
* Fields not relavant to the current VFP architecture are ignored.
*/
struct user_vfp_exc {
unsigned long fpexc;
unsigned long fpinst;
unsigned long fpinst2;
};
#endif /* _ARM_USER_H */ #endif /* _ARM_USER_H */

View File

@ -18,6 +18,7 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/unistd.h> #include <asm/unistd.h>
#include <asm/vfp.h>
#include "ptrace.h" #include "ptrace.h"
#include "signal.h" #include "signal.h"
@ -175,6 +176,90 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
#endif #endif
#ifdef CONFIG_VFP
static int preserve_vfp_context(struct vfp_sigframe __user *frame)
{
struct thread_info *thread = current_thread_info();
struct vfp_hard_struct *h = &thread->vfpstate.hard;
const unsigned long magic = VFP_MAGIC;
const unsigned long size = VFP_STORAGE_SIZE;
int err = 0;
vfp_sync_hwstate(thread);
__put_user_error(magic, &frame->magic, err);
__put_user_error(size, &frame->size, err);
/*
* Copy the floating point registers. There can be unused
* registers see asm/hwcap.h for details.
*/
err |= __copy_to_user(&frame->ufp.fpregs, &h->fpregs,
sizeof(h->fpregs));
/*
* Copy the status and control register.
*/
__put_user_error(h->fpscr, &frame->ufp.fpscr, err);
/*
* Copy the exception registers.
*/
__put_user_error(h->fpexc, &frame->ufp_exc.fpexc, err);
__put_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
__put_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
return err ? -EFAULT : 0;
}
static int restore_vfp_context(struct vfp_sigframe __user *frame)
{
struct thread_info *thread = current_thread_info();
struct vfp_hard_struct *h = &thread->vfpstate.hard;
unsigned long magic;
unsigned long size;
unsigned long fpexc;
int err = 0;
__get_user_error(magic, &frame->magic, err);
__get_user_error(size, &frame->size, err);
if (err)
return -EFAULT;
if (magic != VFP_MAGIC || size != VFP_STORAGE_SIZE)
return -EINVAL;
/*
* Copy the floating point registers. There can be unused
* registers see asm/hwcap.h for details.
*/
err |= __copy_from_user(&h->fpregs, &frame->ufp.fpregs,
sizeof(h->fpregs));
/*
* Copy the status and control register.
*/
__get_user_error(h->fpscr, &frame->ufp.fpscr, err);
/*
* Sanitise and restore the exception registers.
*/
__get_user_error(fpexc, &frame->ufp_exc.fpexc, err);
/* Ensure the VFP is enabled. */
fpexc |= FPEXC_EN;
/* Ensure FPINST2 is invalid and the exception flag is cleared. */
fpexc &= ~(FPEXC_EX | FPEXC_FP2V);
h->fpexc = fpexc;
__get_user_error(h->fpinst, &frame->ufp_exc.fpinst, err);
__get_user_error(h->fpinst2, &frame->ufp_exc.fpinst2, err);
if (!err)
vfp_flush_hwstate(thread);
return err ? -EFAULT : 0;
}
#endif
/* /*
* Do a signal return; undo the signal stack. These are aligned to 64-bit. * Do a signal return; undo the signal stack. These are aligned to 64-bit.
*/ */
@ -233,8 +318,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
err |= restore_iwmmxt_context(&aux->iwmmxt); err |= restore_iwmmxt_context(&aux->iwmmxt);
#endif #endif
#ifdef CONFIG_VFP #ifdef CONFIG_VFP
// if (err == 0) if (err == 0)
// err |= vfp_restore_state(&sf->aux.vfp); err |= restore_vfp_context(&aux->vfp);
#endif #endif
return err; return err;
@ -348,8 +433,8 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
err |= preserve_iwmmxt_context(&aux->iwmmxt); err |= preserve_iwmmxt_context(&aux->iwmmxt);
#endif #endif
#ifdef CONFIG_VFP #ifdef CONFIG_VFP
// if (err == 0) if (err == 0)
// err |= vfp_save_state(&sf->aux.vfp); err |= preserve_vfp_context(&aux->vfp);
#endif #endif
__put_user_error(0, &aux->end_magic, err); __put_user_error(0, &aux->end_magic, err);

View File

@ -17,7 +17,7 @@ obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_d
obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9RL) += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT91CAP9) += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT572D940HF) += at572d940hf.o at91sam926x_time.o at572d940hf_devices.o sam9_smc.o obj-$(CONFIG_ARCH_AT572D940HF) += at572d940hf.o at91sam926x_time.o at572d940hf_devices.o sam9_smc.o
obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o obj-$(CONFIG_ARCH_AT91X40) += at91x40.o at91x40_time.o

View File

@ -175,8 +175,6 @@ ENTRY(at91_slow_clock)
orr r3, r3, #(1 << 29) /* bit 29 always set */ orr r3, r3, #(1 << 29) /* bit 29 always set */
str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)] str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
wait_pllalock
/* Save PLLB setting and disable it */ /* Save PLLB setting and disable it */
ldr r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)] ldr r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
str r3, .saved_pllbr str r3, .saved_pllbr
@ -184,8 +182,6 @@ ENTRY(at91_slow_clock)
mov r3, #AT91_PMC_PLLCOUNT mov r3, #AT91_PMC_PLLCOUNT
str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)] str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
wait_pllblock
/* Turn off the main oscillator */ /* Turn off the main oscillator */
ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)] ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
bic r3, r3, #AT91_PMC_MOSCEN bic r3, r3, #AT91_PMC_MOSCEN
@ -205,13 +201,25 @@ ENTRY(at91_slow_clock)
ldr r3, .saved_pllbr ldr r3, .saved_pllbr
str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)] str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
tst r3, #(AT91_PMC_MUL & 0xff0000)
bne 1f
tst r3, #(AT91_PMC_MUL & ~0xff0000)
beq 2f
1:
wait_pllblock wait_pllblock
2:
/* Restore PLLA setting */ /* Restore PLLA setting */
ldr r3, .saved_pllar ldr r3, .saved_pllar
str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)] str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
tst r3, #(AT91_PMC_MUL & 0xff0000)
bne 3f
tst r3, #(AT91_PMC_MUL & ~0xff0000)
beq 4f
3:
wait_pllalock wait_pllalock
4:
#ifdef SLOWDOWN_MASTER_CLOCK #ifdef SLOWDOWN_MASTER_CLOCK
/* /*

View File

@ -2221,11 +2221,15 @@ EXPORT_SYMBOL(dma_map_create_descriptor_ring);
int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */ int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */
int dirtied /* non-zero if any of the pages were modified */ int dirtied /* non-zero if any of the pages were modified */
) { ) {
int rc = 0;
int regionIdx; int regionIdx;
int segmentIdx; int segmentIdx;
DMA_Region_t *region; DMA_Region_t *region;
DMA_Segment_t *segment; DMA_Segment_t *segment;
down(&memMap->lock);
for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) { for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; regionIdx++) {
region = &memMap->region[regionIdx]; region = &memMap->region[regionIdx];
@ -2239,7 +2243,8 @@ int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */
printk(KERN_ERR printk(KERN_ERR
"%s: vmalloc'd pages are not yet supported\n", "%s: vmalloc'd pages are not yet supported\n",
__func__); __func__);
return -EINVAL; rc = -EINVAL;
goto out;
} }
case DMA_MEM_TYPE_KMALLOC: case DMA_MEM_TYPE_KMALLOC:
@ -2276,7 +2281,8 @@ int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */
printk(KERN_ERR printk(KERN_ERR
"%s: Unsupported memory type: %d\n", "%s: Unsupported memory type: %d\n",
__func__, region->memType); __func__, region->memType);
return -EINVAL; rc = -EINVAL;
goto out;
} }
} }
@ -2314,9 +2320,10 @@ int dma_unmap(DMA_MemMap_t *memMap, /* Stores state information about the map */
memMap->numRegionsUsed = 0; memMap->numRegionsUsed = 0;
memMap->inUse = 0; memMap->inUse = 0;
out:
up(&memMap->lock); up(&memMap->lock);
return 0; return rc;
} }
EXPORT_SYMBOL(dma_unmap); EXPORT_SYMBOL(dma_unmap);

View File

@ -25,7 +25,7 @@
#include <mach/hardware.h> #include <mach/hardware.h>
/************************************************************************* /*************************************************************************
* GPIO handling for EP93xx * Interrupt handling for EP93xx on-chip GPIOs
*************************************************************************/ *************************************************************************/
static unsigned char gpio_int_unmasked[3]; static unsigned char gpio_int_unmasked[3];
static unsigned char gpio_int_enabled[3]; static unsigned char gpio_int_enabled[3];
@ -40,7 +40,7 @@ static const u8 eoi_register_offset[3] = { 0x98, 0xb4, 0x54 };
static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 }; static const u8 int_en_register_offset[3] = { 0x9c, 0xb8, 0x58 };
static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 }; static const u8 int_debounce_register_offset[3] = { 0xa8, 0xc4, 0x64 };
void ep93xx_gpio_update_int_params(unsigned port) static void ep93xx_gpio_update_int_params(unsigned port)
{ {
BUG_ON(port > 2); BUG_ON(port > 2);
@ -56,7 +56,7 @@ void ep93xx_gpio_update_int_params(unsigned port)
EP93XX_GPIO_REG(int_en_register_offset[port])); EP93XX_GPIO_REG(int_en_register_offset[port]));
} }
void ep93xx_gpio_int_mask(unsigned line) static inline void ep93xx_gpio_int_mask(unsigned line)
{ {
gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7)); gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
} }

View File

@ -62,6 +62,15 @@ config MACH_MX31_3DS
Include support for MX31PDK (3DS) platform. This includes specific Include support for MX31PDK (3DS) platform. This includes specific
configurations for the board and its peripherals. configurations for the board and its peripherals.
config MACH_MX31_3DS_MXC_NAND_USE_BBT
bool "Make the MXC NAND driver use the in flash Bad Block Table"
depends on MACH_MX31_3DS
depends on MTD_NAND_MXC
help
Enable this if you want that the MXC NAND driver uses the in flash
Bad Block Table to know what blocks are bad instead of scanning the
entire flash looking for bad block markers.
config MACH_MX31MOBOARD config MACH_MX31MOBOARD
bool "Support mx31moboard platforms (EPFL Mobots group)" bool "Support mx31moboard platforms (EPFL Mobots group)"
select ARCH_MX31 select ARCH_MX31
@ -95,6 +104,7 @@ config MACH_PCM043
config MACH_ARMADILLO5X0 config MACH_ARMADILLO5X0
bool "Support Atmark Armadillo-500 Development Base Board" bool "Support Atmark Armadillo-500 Development Base Board"
select ARCH_MX31 select ARCH_MX31
select MXC_ULPI if USB_ULPI
help help
Include support for Atmark Armadillo-500 platform. This includes Include support for Atmark Armadillo-500 platform. This includes
specific configurations for the board and its peripherals. specific configurations for the board and its peripherals.

View File

@ -468,6 +468,7 @@ static struct clk ahb_clk = {
} }
DEFINE_CLOCK(perclk_clk, 0, NULL, 0, NULL, NULL, &ipg_clk); DEFINE_CLOCK(perclk_clk, 0, NULL, 0, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(ckil_clk, 0, NULL, 0, clk_ckil_get_rate, NULL, NULL);
DEFINE_CLOCK(sdhc1_clk, 0, MXC_CCM_CGR0, 0, NULL, NULL, &perclk_clk); DEFINE_CLOCK(sdhc1_clk, 0, MXC_CCM_CGR0, 0, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(sdhc2_clk, 1, MXC_CCM_CGR0, 2, NULL, NULL, &perclk_clk); DEFINE_CLOCK(sdhc2_clk, 1, MXC_CCM_CGR0, 2, NULL, NULL, &perclk_clk);
@ -490,7 +491,7 @@ DEFINE_CLOCK(mpeg4_clk, 0, MXC_CCM_CGR1, 0, NULL, NULL, &ahb_clk);
DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1, 2, mstick1_get_rate, NULL, &usb_pll_clk); DEFINE_CLOCK(mstick1_clk, 0, MXC_CCM_CGR1, 2, mstick1_get_rate, NULL, &usb_pll_clk);
DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1, 4, mstick2_get_rate, NULL, &usb_pll_clk); DEFINE_CLOCK(mstick2_clk, 1, MXC_CCM_CGR1, 4, mstick2_get_rate, NULL, &usb_pll_clk);
DEFINE_CLOCK1(csi_clk, 0, MXC_CCM_CGR1, 6, csi, NULL, &serial_pll_clk); DEFINE_CLOCK1(csi_clk, 0, MXC_CCM_CGR1, 6, csi, NULL, &serial_pll_clk);
DEFINE_CLOCK(rtc_clk, 0, MXC_CCM_CGR1, 8, NULL, NULL, &ipg_clk); DEFINE_CLOCK(rtc_clk, 0, MXC_CCM_CGR1, 8, NULL, NULL, &ckil_clk);
DEFINE_CLOCK(wdog_clk, 0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk); DEFINE_CLOCK(wdog_clk, 0, MXC_CCM_CGR1, 10, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(pwm_clk, 0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk); DEFINE_CLOCK(pwm_clk, 0, MXC_CCM_CGR1, 12, NULL, NULL, &perclk_clk);
DEFINE_CLOCK(usb_clk2, 0, MXC_CCM_CGR1, 18, usb_get_rate, NULL, &ahb_clk); DEFINE_CLOCK(usb_clk2, 0, MXC_CCM_CGR1, 18, usb_get_rate, NULL, &ahb_clk);
@ -514,7 +515,6 @@ DEFINE_CLOCK(usb_clk1, 0, NULL, 0, usb_get_rate, NULL, &usb_pll_clk)
DEFINE_CLOCK(nfc_clk, 0, NULL, 0, nfc_get_rate, NULL, &ahb_clk); DEFINE_CLOCK(nfc_clk, 0, NULL, 0, nfc_get_rate, NULL, &ahb_clk);
DEFINE_CLOCK(scc_clk, 0, NULL, 0, NULL, NULL, &ipg_clk); DEFINE_CLOCK(scc_clk, 0, NULL, 0, NULL, NULL, &ipg_clk);
DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk); DEFINE_CLOCK(ipg_clk, 0, NULL, 0, ipg_get_rate, NULL, &ahb_clk);
DEFINE_CLOCK(ckil_clk, 0, NULL, 0, clk_ckil_get_rate, NULL, NULL);
#define _REGISTER_CLOCK(d, n, c) \ #define _REGISTER_CLOCK(d, n, c) \
{ \ { \
@ -572,7 +572,6 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "iim", iim_clk) _REGISTER_CLOCK(NULL, "iim", iim_clk)
_REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk) _REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk)
_REGISTER_CLOCK(NULL, "mbx", mbx_clk) _REGISTER_CLOCK(NULL, "mbx", mbx_clk)
_REGISTER_CLOCK("mxc_rtc", NULL, ckil_clk)
}; };
int __init mx31_clocks_init(unsigned long fref) int __init mx31_clocks_init(unsigned long fref)

View File

@ -575,11 +575,26 @@ struct platform_device imx_ssi_device1 = {
.resource = imx_ssi_resources1, .resource = imx_ssi_resources1,
}; };
static int mx3_devices_init(void) static struct resource imx_wdt_resources[] = {
{
.flags = IORESOURCE_MEM,
},
};
struct platform_device imx_wdt_device0 = {
.name = "imx-wdt",
.id = 0,
.num_resources = ARRAY_SIZE(imx_wdt_resources),
.resource = imx_wdt_resources,
};
static int __init mx3_devices_init(void)
{ {
if (cpu_is_mx31()) { if (cpu_is_mx31()) {
mxc_nand_resources[0].start = MX31_NFC_BASE_ADDR; mxc_nand_resources[0].start = MX31_NFC_BASE_ADDR;
mxc_nand_resources[0].end = MX31_NFC_BASE_ADDR + 0xfff; mxc_nand_resources[0].end = MX31_NFC_BASE_ADDR + 0xfff;
imx_wdt_resources[0].start = MX31_WDOG_BASE_ADDR;
imx_wdt_resources[0].end = MX31_WDOG_BASE_ADDR + 0x3fff;
mxc_register_device(&mxc_rnga_device, NULL); mxc_register_device(&mxc_rnga_device, NULL);
} }
if (cpu_is_mx35()) { if (cpu_is_mx35()) {
@ -597,6 +612,8 @@ static int mx3_devices_init(void)
imx_ssi_resources0[1].end = MX35_INT_SSI1; imx_ssi_resources0[1].end = MX35_INT_SSI1;
imx_ssi_resources1[1].start = MX35_INT_SSI2; imx_ssi_resources1[1].start = MX35_INT_SSI2;
imx_ssi_resources1[1].end = MX35_INT_SSI2; imx_ssi_resources1[1].end = MX35_INT_SSI2;
imx_wdt_resources[0].start = MX35_WDOG_BASE_ADDR;
imx_wdt_resources[0].end = MX35_WDOG_BASE_ADDR + 0x3fff;
} }
return 0; return 0;

View File

@ -25,4 +25,5 @@ extern struct platform_device mxc_spi_device1;
extern struct platform_device mxc_spi_device2; extern struct platform_device mxc_spi_device2;
extern struct platform_device imx_ssi_device0; extern struct platform_device imx_ssi_device0;
extern struct platform_device imx_ssi_device1; extern struct platform_device imx_ssi_device1;
extern struct platform_device imx_ssi_device1;
extern struct platform_device imx_wdt_device0;

View File

@ -36,6 +36,9 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/gpio_keys.h> #include <linux/gpio_keys.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
#include <linux/delay.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
@ -52,6 +55,8 @@
#include <mach/ipu.h> #include <mach/ipu.h>
#include <mach/mx3fb.h> #include <mach/mx3fb.h>
#include <mach/mxc_nand.h> #include <mach/mxc_nand.h>
#include <mach/mxc_ehci.h>
#include <mach/ulpi.h>
#include "devices.h" #include "devices.h"
#include "crm_regs.h" #include "crm_regs.h"
@ -103,8 +108,158 @@ static int armadillo5x0_pins[] = {
/* I2C2 */ /* I2C2 */
MX31_PIN_CSPI2_MOSI__SCL, MX31_PIN_CSPI2_MOSI__SCL,
MX31_PIN_CSPI2_MISO__SDA, MX31_PIN_CSPI2_MISO__SDA,
/* OTG */
MX31_PIN_USBOTG_DATA0__USBOTG_DATA0,
MX31_PIN_USBOTG_DATA1__USBOTG_DATA1,
MX31_PIN_USBOTG_DATA2__USBOTG_DATA2,
MX31_PIN_USBOTG_DATA3__USBOTG_DATA3,
MX31_PIN_USBOTG_DATA4__USBOTG_DATA4,
MX31_PIN_USBOTG_DATA5__USBOTG_DATA5,
MX31_PIN_USBOTG_DATA6__USBOTG_DATA6,
MX31_PIN_USBOTG_DATA7__USBOTG_DATA7,
MX31_PIN_USBOTG_CLK__USBOTG_CLK,
MX31_PIN_USBOTG_DIR__USBOTG_DIR,
MX31_PIN_USBOTG_NXT__USBOTG_NXT,
MX31_PIN_USBOTG_STP__USBOTG_STP,
/* USB host 2 */
IOMUX_MODE(MX31_PIN_USBH2_CLK, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_USBH2_DIR, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_USBH2_NXT, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_USBH2_STP, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_USBH2_DATA0, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_USBH2_DATA1, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_STXD3, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_SRXD3, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_SCK3, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_SFS3, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_STXD6, IOMUX_CONFIG_FUNC),
IOMUX_MODE(MX31_PIN_SRXD6, IOMUX_CONFIG_FUNC),
}; };
/* USB */
#if defined(CONFIG_USB_ULPI)
#define OTG_RESET IOMUX_TO_GPIO(MX31_PIN_STXD4)
#define USBH2_RESET IOMUX_TO_GPIO(MX31_PIN_SCK6)
#define USBH2_CS IOMUX_TO_GPIO(MX31_PIN_GPIO1_3)
#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
static int usbotg_init(struct platform_device *pdev)
{
int err;
mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG);
/* Chip already enabled by hardware */
/* OTG phy reset*/
err = gpio_request(OTG_RESET, "USB-OTG-RESET");
if (err) {
pr_err("Failed to request the usb otg reset gpio\n");
return err;
}
err = gpio_direction_output(OTG_RESET, 1/*HIGH*/);
if (err) {
pr_err("Failed to reset the usb otg phy\n");
goto otg_free_reset;
}
gpio_set_value(OTG_RESET, 0/*LOW*/);
mdelay(5);
gpio_set_value(OTG_RESET, 1/*HIGH*/);
return 0;
otg_free_reset:
gpio_free(OTG_RESET);
return err;
}
static int usbh2_init(struct platform_device *pdev)
{
int err;
mxc_iomux_set_pad(MX31_PIN_USBH2_CLK, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBH2_DIR, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBH2_NXT, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBH2_STP, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBH2_DATA0, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_USBH2_DATA1, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_SRXD6, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_STXD6, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_SFS3, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_SCK3, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_SRXD3, USB_PAD_CFG);
mxc_iomux_set_pad(MX31_PIN_STXD3, USB_PAD_CFG);
mxc_iomux_set_gpr(MUX_PGP_UH2, true);
/* Enable the chip */
err = gpio_request(USBH2_CS, "USB-H2-CS");
if (err) {
pr_err("Failed to request the usb host 2 CS gpio\n");
return err;
}
err = gpio_direction_output(USBH2_CS, 0/*Enabled*/);
if (err) {
pr_err("Failed to drive the usb host 2 CS gpio\n");
goto h2_free_cs;
}
/* H2 phy reset*/
err = gpio_request(USBH2_RESET, "USB-H2-RESET");
if (err) {
pr_err("Failed to request the usb host 2 reset gpio\n");
goto h2_free_cs;
}
err = gpio_direction_output(USBH2_RESET, 1/*HIGH*/);
if (err) {
pr_err("Failed to reset the usb host 2 phy\n");
goto h2_free_reset;
}
gpio_set_value(USBH2_RESET, 0/*LOW*/);
mdelay(5);
gpio_set_value(USBH2_RESET, 1/*HIGH*/);
return 0;
h2_free_reset:
gpio_free(USBH2_RESET);
h2_free_cs:
gpio_free(USBH2_CS);
return err;
}
static struct mxc_usbh_platform_data usbotg_pdata = {
.init = usbotg_init,
.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
.flags = MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
};
static struct mxc_usbh_platform_data usbh2_pdata = {
.init = usbh2_init,
.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
.flags = MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
};
#endif /* CONFIG_USB_ULPI */
/* RTC over I2C*/ /* RTC over I2C*/
#define ARMADILLO5X0_RTC_GPIO IOMUX_TO_GPIO(MX31_PIN_SRXD4) #define ARMADILLO5X0_RTC_GPIO IOMUX_TO_GPIO(MX31_PIN_SRXD4)
@ -393,6 +548,17 @@ static void __init armadillo5x0_init(void)
if (armadillo5x0_i2c_rtc.irq == 0) if (armadillo5x0_i2c_rtc.irq == 0)
pr_warning("armadillo5x0_init: failed to get RTC IRQ\n"); pr_warning("armadillo5x0_init: failed to get RTC IRQ\n");
i2c_register_board_info(1, &armadillo5x0_i2c_rtc, 1); i2c_register_board_info(1, &armadillo5x0_i2c_rtc, 1);
/* USB */
#if defined(CONFIG_USB_ULPI)
usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
mxc_register_device(&mxc_otg_host, &usbotg_pdata);
mxc_register_device(&mxc_usbh2, &usbh2_pdata);
#endif
} }
static void __init armadillo5x0_timer_init(void) static void __init armadillo5x0_timer_init(void)

View File

@ -23,6 +23,9 @@
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/smsc911x.h> #include <linux/smsc911x.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/mfd/mc13783.h>
#include <linux/spi/spi.h>
#include <linux/regulator/machine.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
@ -31,26 +34,96 @@
#include <asm/memory.h> #include <asm/memory.h>
#include <asm/mach/map.h> #include <asm/mach/map.h>
#include <mach/common.h> #include <mach/common.h>
#include <mach/board-mx31pdk.h> #include <mach/board-mx31_3ds.h>
#include <mach/imx-uart.h> #include <mach/imx-uart.h>
#include <mach/iomux-mx3.h> #include <mach/iomux-mx3.h>
#include <mach/mxc_nand.h>
#include <mach/spi.h>
#include "devices.h" #include "devices.h"
/*! /*!
* @file mx31pdk.c * @file mx31_3ds.c
* *
* @brief This file contains the board-specific initialization routines. * @brief This file contains the board-specific initialization routines.
* *
* @ingroup System * @ingroup System
*/ */
static int mx31pdk_pins[] = { static int mx31_3ds_pins[] = {
/* UART1 */ /* UART1 */
MX31_PIN_CTS1__CTS1, MX31_PIN_CTS1__CTS1,
MX31_PIN_RTS1__RTS1, MX31_PIN_RTS1__RTS1,
MX31_PIN_TXD1__TXD1, MX31_PIN_TXD1__TXD1,
MX31_PIN_RXD1__RXD1, MX31_PIN_RXD1__RXD1,
IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO), IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO),
/* SPI 1 */
MX31_PIN_CSPI2_SCLK__SCLK,
MX31_PIN_CSPI2_MOSI__MOSI,
MX31_PIN_CSPI2_MISO__MISO,
MX31_PIN_CSPI2_SPI_RDY__SPI_RDY,
MX31_PIN_CSPI2_SS0__SS0,
MX31_PIN_CSPI2_SS2__SS2, /*CS for MC13783 */
/* MC13783 IRQ */
IOMUX_MODE(MX31_PIN_GPIO1_3, IOMUX_CONFIG_GPIO),
};
/* Regulators */
static struct regulator_init_data pwgtx_init = {
.constraints = {
.boot_on = 1,
.always_on = 1,
},
};
static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
{
.id = MC13783_REGU_PWGT1SPI, /* Power Gate for ARM core. */
.init_data = &pwgtx_init,
}, {
.id = MC13783_REGU_PWGT2SPI, /* Power Gate for L2 Cache. */
.init_data = &pwgtx_init,
},
};
/* MC13783 */
static struct mc13783_platform_data mc13783_pdata __initdata = {
.regulators = mx31_3ds_regulators,
.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
.flags = MC13783_USE_REGULATOR,
};
/* SPI */
static int spi1_internal_chipselect[] = {
MXC_SPI_CS(0),
MXC_SPI_CS(2),
};
static struct spi_imx_master spi1_pdata = {
.chipselect = spi1_internal_chipselect,
.num_chipselect = ARRAY_SIZE(spi1_internal_chipselect),
};
static struct spi_board_info mx31_3ds_spi_devs[] __initdata = {
{
.modalias = "mc13783",
.max_speed_hz = 1000000,
.bus_num = 1,
.chip_select = 1, /* SS2 */
.platform_data = &mc13783_pdata,
.irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
.mode = SPI_CS_HIGH,
},
};
/*
* NAND Flash
*/
static struct mxc_nand_platform_data imx31_3ds_nand_flash_pdata = {
.width = 1,
.hw_ecc = 1,
#ifdef MACH_MX31_3DS_MXC_NAND_USE_BBT
.flash_bbt = 1,
#endif
}; };
static struct imxuart_platform_data uart_pdata = { static struct imxuart_platform_data uart_pdata = {
@ -95,7 +168,7 @@ static struct platform_device smsc911x_device = {
* LEDs, switches, interrupts for Ethernet. * LEDs, switches, interrupts for Ethernet.
*/ */
static void mx31pdk_expio_irq_handler(uint32_t irq, struct irq_desc *desc) static void mx31_3ds_expio_irq_handler(uint32_t irq, struct irq_desc *desc)
{ {
uint32_t imr_val; uint32_t imr_val;
uint32_t int_valid; uint32_t int_valid;
@ -163,7 +236,7 @@ static struct irq_chip expio_irq_chip = {
.unmask = expio_unmask_irq, .unmask = expio_unmask_irq,
}; };
static int __init mx31pdk_init_expio(void) static int __init mx31_3ds_init_expio(void)
{ {
int i; int i;
int ret; int ret;
@ -176,7 +249,7 @@ static int __init mx31pdk_init_expio(void)
return -ENODEV; return -ENODEV;
} }
pr_info("i.MX31PDK Debug board detected, rev = 0x%04X\n", pr_info("i.MX31 3DS Debug board detected, rev = 0x%04X\n",
__raw_readw(CPLD_CODE_VER_REG)); __raw_readw(CPLD_CODE_VER_REG));
/* /*
@ -201,7 +274,7 @@ static int __init mx31pdk_init_expio(void)
set_irq_flags(i, IRQF_VALID); set_irq_flags(i, IRQF_VALID);
} }
set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_LOW); set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_LOW);
set_irq_chained_handler(EXPIO_PARENT_INT, mx31pdk_expio_irq_handler); set_irq_chained_handler(EXPIO_PARENT_INT, mx31_3ds_expio_irq_handler);
return 0; return 0;
} }
@ -209,7 +282,7 @@ static int __init mx31pdk_init_expio(void)
/* /*
* This structure defines the MX31 memory map. * This structure defines the MX31 memory map.
*/ */
static struct map_desc mx31pdk_io_desc[] __initdata = { static struct map_desc mx31_3ds_io_desc[] __initdata = {
{ {
.virtual = MX31_CS5_BASE_ADDR_VIRT, .virtual = MX31_CS5_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(MX31_CS5_BASE_ADDR), .pfn = __phys_to_pfn(MX31_CS5_BASE_ADDR),
@ -221,10 +294,10 @@ static struct map_desc mx31pdk_io_desc[] __initdata = {
/* /*
* Set up static virtual mappings. * Set up static virtual mappings.
*/ */
static void __init mx31pdk_map_io(void) static void __init mx31_3ds_map_io(void)
{ {
mx31_map_io(); mx31_map_io();
iotable_init(mx31pdk_io_desc, ARRAY_SIZE(mx31pdk_io_desc)); iotable_init(mx31_3ds_io_desc, ARRAY_SIZE(mx31_3ds_io_desc));
} }
/*! /*!
@ -232,35 +305,40 @@ static void __init mx31pdk_map_io(void)
*/ */
static void __init mxc_board_init(void) static void __init mxc_board_init(void)
{ {
mxc_iomux_setup_multiple_pins(mx31pdk_pins, ARRAY_SIZE(mx31pdk_pins), mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins),
"mx31pdk"); "mx31_3ds");
mxc_register_device(&mxc_uart_device0, &uart_pdata); mxc_register_device(&mxc_uart_device0, &uart_pdata);
mxc_register_device(&mxc_nand_device, &imx31_3ds_nand_flash_pdata);
if (!mx31pdk_init_expio()) mxc_register_device(&mxc_spi_device1, &spi1_pdata);
spi_register_board_info(mx31_3ds_spi_devs,
ARRAY_SIZE(mx31_3ds_spi_devs));
if (!mx31_3ds_init_expio())
platform_device_register(&smsc911x_device); platform_device_register(&smsc911x_device);
} }
static void __init mx31pdk_timer_init(void) static void __init mx31_3ds_timer_init(void)
{ {
mx31_clocks_init(26000000); mx31_clocks_init(26000000);
} }
static struct sys_timer mx31pdk_timer = { static struct sys_timer mx31_3ds_timer = {
.init = mx31pdk_timer_init, .init = mx31_3ds_timer_init,
}; };
/* /*
* The following uses standard kernel macros defined in arch.h in order to * The following uses standard kernel macros defined in arch.h in order to
* initialize __mach_desc_MX31PDK data structure. * initialize __mach_desc_MX31_3DS data structure.
*/ */
MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)") MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
/* Maintainer: Freescale Semiconductor, Inc. */ /* Maintainer: Freescale Semiconductor, Inc. */
.phys_io = MX31_AIPS1_BASE_ADDR, .phys_io = MX31_AIPS1_BASE_ADDR,
.io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc, .io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100, .boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31pdk_map_io, .map_io = mx31_3ds_map_io,
.init_irq = mx31_init_irq, .init_irq = mx31_init_irq,
.init_machine = mxc_board_init, .init_machine = mxc_board_init,
.timer = &mx31pdk_timer, .timer = &mx31_3ds_timer,
MACHINE_END MACHINE_END

View File

@ -35,7 +35,6 @@
#include <linux/can/platform/sja1000.h> #include <linux/can/platform/sja1000.h>
#include <linux/usb/otg.h> #include <linux/usb/otg.h>
#include <linux/usb/ulpi.h> #include <linux/usb/ulpi.h>
#include <linux/fsl_devices.h>
#include <linux/gfp.h> #include <linux/gfp.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>

View File

@ -28,7 +28,6 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
@ -206,5 +205,6 @@ void __init mx31lite_db_init(void)
mxc_register_device(&mxcsdhc_device0, &mmc_pdata); mxc_register_device(&mxcsdhc_device0, &mmc_pdata);
mxc_register_device(&mxc_spi_device0, &spi0_pdata); mxc_register_device(&mxc_spi_device0, &spi0_pdata);
platform_device_register(&litekit_led_device); platform_device_register(&litekit_led_device);
mxc_register_device(&imx_wdt_device0, NULL);
} }

View File

@ -757,7 +757,7 @@ DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,
/* GPT */ /* GPT */
DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET, DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
NULL, NULL, &ipg_perclk, NULL); NULL, NULL, &ipg_clk, NULL);
DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET, DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,
NULL, NULL, &ipg_clk, NULL); NULL, NULL, &ipg_clk, NULL);

View File

@ -14,9 +14,62 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <asm/io.h> #include <asm/io.h>
static int cpu_silicon_rev = -1;
#define SI_REV 0x48
static void query_silicon_parameter(void)
{
void __iomem *rom = ioremap(MX51_IROM_BASE_ADDR, MX51_IROM_SIZE);
u32 rev;
if (!rom) {
cpu_silicon_rev = -EINVAL;
return;
}
rev = readl(rom + SI_REV);
switch (rev) {
case 0x1:
cpu_silicon_rev = MX51_CHIP_REV_1_0;
break;
case 0x2:
cpu_silicon_rev = MX51_CHIP_REV_1_1;
break;
case 0x10:
cpu_silicon_rev = MX51_CHIP_REV_2_0;
break;
case 0x20:
cpu_silicon_rev = MX51_CHIP_REV_3_0;
break;
default:
cpu_silicon_rev = 0;
}
iounmap(rom);
}
/*
* Returns:
* the silicon revision of the cpu
* -EINVAL - not a mx51
*/
int mx51_revision(void)
{
if (!cpu_is_mx51())
return -EINVAL;
if (cpu_silicon_rev == -1)
query_silicon_parameter();
return cpu_silicon_rev;
}
EXPORT_SYMBOL(mx51_revision);
static int __init post_cpu_init(void) static int __init post_cpu_init(void)
{ {
unsigned int reg; unsigned int reg;

View File

@ -34,11 +34,6 @@ static struct map_desc mxc_io_desc[] __initdata = {
.pfn = __phys_to_pfn(MX51_DEBUG_BASE_ADDR), .pfn = __phys_to_pfn(MX51_DEBUG_BASE_ADDR),
.length = MX51_DEBUG_SIZE, .length = MX51_DEBUG_SIZE,
.type = MT_DEVICE .type = MT_DEVICE
}, {
.virtual = MX51_TZIC_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(MX51_TZIC_BASE_ADDR),
.length = MX51_TZIC_SIZE,
.type = MT_DEVICE
}, { }, {
.virtual = MX51_AIPS1_BASE_ADDR_VIRT, .virtual = MX51_AIPS1_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(MX51_AIPS1_BASE_ADDR), .pfn = __phys_to_pfn(MX51_AIPS1_BASE_ADDR),
@ -54,11 +49,6 @@ static struct map_desc mxc_io_desc[] __initdata = {
.pfn = __phys_to_pfn(MX51_AIPS2_BASE_ADDR), .pfn = __phys_to_pfn(MX51_AIPS2_BASE_ADDR),
.length = MX51_AIPS2_SIZE, .length = MX51_AIPS2_SIZE,
.type = MT_DEVICE .type = MT_DEVICE
}, {
.virtual = MX51_NFC_AXI_BASE_ADDR_VIRT,
.pfn = __phys_to_pfn(MX51_NFC_AXI_BASE_ADDR),
.length = MX51_NFC_AXI_SIZE,
.type = MT_DEVICE
}, },
}; };
@ -69,14 +59,6 @@ static struct map_desc mxc_io_desc[] __initdata = {
*/ */
void __init mx51_map_io(void) void __init mx51_map_io(void)
{ {
u32 tzic_addr;
if (mx51_revision() < MX51_CHIP_REV_2_0)
tzic_addr = 0x8FFFC000;
else
tzic_addr = 0xE0003000;
mxc_io_desc[2].pfn = __phys_to_pfn(tzic_addr);
mxc_set_cpu_type(MXC_CPU_MX51); mxc_set_cpu_type(MXC_CPU_MX51);
mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR)); mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG_BASE_ADDR)); mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG_BASE_ADDR));
@ -85,5 +67,17 @@ void __init mx51_map_io(void)
void __init mx51_init_irq(void) void __init mx51_init_irq(void)
{ {
tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR)); unsigned long tzic_addr;
void __iomem *tzic_virt;
if (mx51_revision() < MX51_CHIP_REV_2_0)
tzic_addr = MX51_TZIC_BASE_ADDR_TO1;
else
tzic_addr = MX51_TZIC_BASE_ADDR;
tzic_virt = ioremap(tzic_addr, SZ_16K);
if (!tzic_virt)
panic("unable to map TZIC interrupt controller\n");
tzic_init_irq(tzic_virt);
} }

View File

@ -41,13 +41,6 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,
kfrom = kmap_atomic(from, KM_USER0); kfrom = kmap_atomic(from, KM_USER0);
kto = kmap_atomic(to, KM_USER1); kto = kmap_atomic(to, KM_USER1);
copy_page(kto, kfrom); copy_page(kto, kfrom);
#ifdef CONFIG_HIGHMEM
/*
* kmap_atomic() doesn't set the page virtual address, and
* kunmap_atomic() takes care of cache flushing already.
*/
if (page_address(to) != NULL)
#endif
__cpuc_flush_dcache_area(kto, PAGE_SIZE); __cpuc_flush_dcache_area(kto, PAGE_SIZE);
kunmap_atomic(kto, KM_USER1); kunmap_atomic(kto, KM_USER1);
kunmap_atomic(kfrom, KM_USER0); kunmap_atomic(kfrom, KM_USER0);

View File

@ -464,6 +464,11 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
vaddr += offset; vaddr += offset;
op(vaddr, len, dir); op(vaddr, len, dir);
kunmap_high(page); kunmap_high(page);
} else if (cache_is_vipt()) {
pte_t saved_pte;
vaddr = kmap_high_l1_vipt(page, &saved_pte);
op(vaddr + offset, len, dir);
kunmap_high_l1_vipt(page, saved_pte);
} }
} else { } else {
vaddr = page_address(page) + offset; vaddr = page_address(page) + offset;

View File

@ -13,6 +13,7 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/cachetype.h> #include <asm/cachetype.h>
#include <asm/highmem.h>
#include <asm/smp_plat.h> #include <asm/smp_plat.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/tlbflush.h> #include <asm/tlbflush.h>
@ -152,21 +153,25 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
void __flush_dcache_page(struct address_space *mapping, struct page *page) void __flush_dcache_page(struct address_space *mapping, struct page *page)
{ {
void *addr = page_address(page);
/* /*
* Writeback any data associated with the kernel mapping of this * Writeback any data associated with the kernel mapping of this
* page. This ensures that data in the physical page is mutually * page. This ensures that data in the physical page is mutually
* coherent with the kernels mapping. * coherent with the kernels mapping.
*/ */
#ifdef CONFIG_HIGHMEM if (!PageHighMem(page)) {
/* __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
* kmap_atomic() doesn't set the page virtual address, and } else {
* kunmap_atomic() takes care of cache flushing already. void *addr = kmap_high_get(page);
*/ if (addr) {
if (addr)
#endif
__cpuc_flush_dcache_area(addr, PAGE_SIZE); __cpuc_flush_dcache_area(addr, PAGE_SIZE);
kunmap_high(page);
} else if (cache_is_vipt()) {
pte_t saved_pte;
addr = kmap_high_l1_vipt(page, &saved_pte);
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
kunmap_high_l1_vipt(page, saved_pte);
}
}
/* /*
* If this is a page cache page, and we have an aliasing VIPT cache, * If this is a page cache page, and we have an aliasing VIPT cache,

View File

@ -79,6 +79,7 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
unsigned int idx = type + KM_TYPE_NR * smp_processor_id(); unsigned int idx = type + KM_TYPE_NR * smp_processor_id();
if (kvaddr >= (void *)FIXADDR_START) { if (kvaddr >= (void *)FIXADDR_START) {
if (cache_is_vivt())
__cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE); __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
#ifdef CONFIG_DEBUG_HIGHMEM #ifdef CONFIG_DEBUG_HIGHMEM
BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
@ -124,3 +125,87 @@ struct page *kmap_atomic_to_page(const void *ptr)
pte = TOP_PTE(vaddr); pte = TOP_PTE(vaddr);
return pte_page(*pte); return pte_page(*pte);
} }
#ifdef CONFIG_CPU_CACHE_VIPT
#include <linux/percpu.h>
/*
* The VIVT cache of a highmem page is always flushed before the page
* is unmapped. Hence unmapped highmem pages need no cache maintenance
* in that case.
*
* However unmapped pages may still be cached with a VIPT cache, and
* it is not possible to perform cache maintenance on them using physical
* addresses unfortunately. So we have no choice but to set up a temporary
* virtual mapping for that purpose.
*
* Yet this VIPT cache maintenance may be triggered from DMA support
* functions which are possibly called from interrupt context. As we don't
* want to keep interrupt disabled all the time when such maintenance is
* taking place, we therefore allow for some reentrancy by preserving and
* restoring the previous fixmap entry before the interrupted context is
* resumed. If the reentrancy depth is 0 then there is no need to restore
* the previous fixmap, and leaving the current one in place allow it to
* be reused the next time without a TLB flush (common with DMA).
*/
static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);
void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte)
{
unsigned int idx, cpu = smp_processor_id();
int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
unsigned long vaddr, flags;
pte_t pte, *ptep;
idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
ptep = TOP_PTE(vaddr);
pte = mk_pte(page, kmap_prot);
if (!in_interrupt())
preempt_disable();
raw_local_irq_save(flags);
(*depth)++;
if (pte_val(*ptep) == pte_val(pte)) {
*saved_pte = pte;
} else {
*saved_pte = *ptep;
set_pte_ext(ptep, pte, 0);
local_flush_tlb_kernel_page(vaddr);
}
raw_local_irq_restore(flags);
return (void *)vaddr;
}
void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte)
{
unsigned int idx, cpu = smp_processor_id();
int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
unsigned long vaddr, flags;
pte_t pte, *ptep;
idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
ptep = TOP_PTE(vaddr);
pte = mk_pte(page, kmap_prot);
BUG_ON(pte_val(*ptep) != pte_val(pte));
BUG_ON(*depth <= 0);
raw_local_irq_save(flags);
(*depth)--;
if (*depth != 0 && pte_val(pte) != pte_val(saved_pte)) {
set_pte_ext(ptep, saved_pte, 0);
local_flush_tlb_kernel_page(vaddr);
}
raw_local_irq_restore(flags);
if (!in_interrupt())
preempt_enable();
}
#endif /* CONFIG_CPU_CACHE_VIPT */

View File

@ -420,6 +420,10 @@ static void __init build_mem_type_table(void)
user_pgprot |= L_PTE_SHARED; user_pgprot |= L_PTE_SHARED;
kern_pgprot |= L_PTE_SHARED; kern_pgprot |= L_PTE_SHARED;
vecs_pgprot |= L_PTE_SHARED; vecs_pgprot |= L_PTE_SHARED;
mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S; mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S; mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
#endif #endif
@ -1050,10 +1054,12 @@ void setup_mm_for_reboot(char mode)
pgd_t *pgd; pgd_t *pgd;
int i; int i;
if (current->mm && current->mm->pgd) /*
pgd = current->mm->pgd; * We need to access to user-mode page tables here. For kernel threads
else * we don't have any user-mode mappings so we use the context that we
pgd = init_mm.pgd; * "borrowed".
*/
pgd = current->active_mm->pgd;
base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT; base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale()) if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())

View File

@ -8,8 +8,8 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#ifndef __ASM_ARCH_MXC_BOARD_MX31PDK_H__ #ifndef __ASM_ARCH_MXC_BOARD_MX31_3DS_H__
#define __ASM_ARCH_MXC_BOARD_MX31PDK_H__ #define __ASM_ARCH_MXC_BOARD_MX31_3DS_H__
/* Definitions for components on the Debug board */ /* Definitions for components on the Debug board */
@ -56,4 +56,4 @@
#define MXC_MAX_EXP_IO_LINES 16 #define MXC_MAX_EXP_IO_LINES 16
#endif /* __ASM_ARCH_MXC_BOARD_MX31PDK_H__ */ #endif /* __ASM_ARCH_MXC_BOARD_MX31_3DS_H__ */

View File

@ -14,7 +14,7 @@
* FB100000 70000000 1M SPBA 0 * FB100000 70000000 1M SPBA 0
* FB000000 73F00000 1M AIPS 1 * FB000000 73F00000 1M AIPS 1
* FB200000 83F00000 1M AIPS 2 * FB200000 83F00000 1M AIPS 2
* FA100000 8FFFC000 16K TZIC (interrupt controller) * 8FFFC000 16K TZIC (interrupt controller)
* 90000000 256M CSD0 SDRAM/DDR * 90000000 256M CSD0 SDRAM/DDR
* A0000000 256M CSD1 SDRAM/DDR * A0000000 256M CSD1 SDRAM/DDR
* B0000000 128M CS0 Flash * B0000000 128M CS0 Flash
@ -23,10 +23,16 @@
* C8000000 64M CS3 Flash * C8000000 64M CS3 Flash
* CC000000 32M CS4 SRAM * CC000000 32M CS4 SRAM
* CE000000 32M CS5 SRAM * CE000000 32M CS5 SRAM
* F9000000 CFFF0000 64K NFC (NAND Flash AXI) * CFFF0000 64K NFC (NAND Flash AXI)
* *
*/ */
/*
* IROM
*/
#define MX51_IROM_BASE_ADDR 0x0
#define MX51_IROM_SIZE SZ_64K
/* /*
* IRAM * IRAM
*/ */
@ -40,7 +46,6 @@
* NFC * NFC
*/ */
#define MX51_NFC_AXI_BASE_ADDR 0xCFFF0000 /* NAND flash AXI */ #define MX51_NFC_AXI_BASE_ADDR 0xCFFF0000 /* NAND flash AXI */
#define MX51_NFC_AXI_BASE_ADDR_VIRT 0xF9000000
#define MX51_NFC_AXI_SIZE SZ_64K #define MX51_NFC_AXI_SIZE SZ_64K
/* /*
@ -49,9 +54,8 @@
#define MX51_GPU_BASE_ADDR 0x20000000 #define MX51_GPU_BASE_ADDR 0x20000000
#define MX51_GPU2D_BASE_ADDR 0xD0000000 #define MX51_GPU2D_BASE_ADDR 0xD0000000
#define MX51_TZIC_BASE_ADDR 0x8FFFC000 #define MX51_TZIC_BASE_ADDR_TO1 0x8FFFC000
#define MX51_TZIC_BASE_ADDR_VIRT 0xFA100000 #define MX51_TZIC_BASE_ADDR 0xE0000000
#define MX51_TZIC_SIZE SZ_16K
#define MX51_DEBUG_BASE_ADDR 0x60000000 #define MX51_DEBUG_BASE_ADDR 0x60000000
#define MX51_DEBUG_BASE_ADDR_VIRT 0xFA200000 #define MX51_DEBUG_BASE_ADDR_VIRT 0xFA200000
@ -232,12 +236,10 @@
#define MX51_IO_ADDRESS(x) \ #define MX51_IO_ADDRESS(x) \
(void __iomem *) \ (void __iomem *) \
(MX51_IS_MODULE(x, IRAM) ? MX51_IRAM_IO_ADDRESS(x) : \ (MX51_IS_MODULE(x, IRAM) ? MX51_IRAM_IO_ADDRESS(x) : \
MX51_IS_MODULE(x, TZIC) ? MX51_TZIC_IO_ADDRESS(x) : \
MX51_IS_MODULE(x, DEBUG) ? MX51_DEBUG_IO_ADDRESS(x) : \ MX51_IS_MODULE(x, DEBUG) ? MX51_DEBUG_IO_ADDRESS(x) : \
MX51_IS_MODULE(x, SPBA0) ? MX51_SPBA0_IO_ADDRESS(x) : \ MX51_IS_MODULE(x, SPBA0) ? MX51_SPBA0_IO_ADDRESS(x) : \
MX51_IS_MODULE(x, AIPS1) ? MX51_AIPS1_IO_ADDRESS(x) : \ MX51_IS_MODULE(x, AIPS1) ? MX51_AIPS1_IO_ADDRESS(x) : \
MX51_IS_MODULE(x, AIPS2) ? MX51_AIPS2_IO_ADDRESS(x) : \ MX51_IS_MODULE(x, AIPS2) ? MX51_AIPS2_IO_ADDRESS(x) : \
MX51_IS_MODULE(x, NFC_AXI) ? MX51_NFC_AXI_IO_ADDRESS(x) : \
0xDEADBEEF) 0xDEADBEEF)
/* /*
@ -246,9 +248,6 @@
#define MX51_IRAM_IO_ADDRESS(x) \ #define MX51_IRAM_IO_ADDRESS(x) \
(((x) - MX51_IRAM_BASE_ADDR) + MX51_IRAM_BASE_ADDR_VIRT) (((x) - MX51_IRAM_BASE_ADDR) + MX51_IRAM_BASE_ADDR_VIRT)
#define MX51_TZIC_IO_ADDRESS(x) \
(((x) - MX51_TZIC_BASE_ADDR) + MX51_TZIC_BASE_ADDR_VIRT)
#define MX51_DEBUG_IO_ADDRESS(x) \ #define MX51_DEBUG_IO_ADDRESS(x) \
(((x) - MX51_DEBUG_BASE_ADDR) + MX51_DEBUG_BASE_ADDR_VIRT) (((x) - MX51_DEBUG_BASE_ADDR) + MX51_DEBUG_BASE_ADDR_VIRT)
@ -261,9 +260,6 @@
#define MX51_AIPS2_IO_ADDRESS(x) \ #define MX51_AIPS2_IO_ADDRESS(x) \
(((x) - MX51_AIPS2_BASE_ADDR) + MX51_AIPS2_BASE_ADDR_VIRT) (((x) - MX51_AIPS2_BASE_ADDR) + MX51_AIPS2_BASE_ADDR_VIRT)
#define MX51_NFC_AXI_IO_ADDRESS(x) \
(((x) - MX51_NFC_AXI_BASE_ADDR) + MX51_NFC_AXI_BASE_ADDR_VIRT)
#define MX51_IS_MEM_DEVICE_NONSHARED(x) 0 #define MX51_IS_MEM_DEVICE_NONSHARED(x) 0
/* /*
@ -443,12 +439,7 @@
#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS) #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
extern unsigned int system_rev; extern int mx51_revision(void);
static inline unsigned int mx51_revision(void)
{
return system_rev;
}
#endif #endif
#endif /* __ASM_ARCH_MXC_MX51_H__ */ #endif /* __ASM_ARCH_MXC_MX51_H__ */

View File

@ -66,6 +66,7 @@ static inline void flush(void)
#define MX2X_UART1_BASE_ADDR 0x1000a000 #define MX2X_UART1_BASE_ADDR 0x1000a000
#define MX3X_UART1_BASE_ADDR 0x43F90000 #define MX3X_UART1_BASE_ADDR 0x43F90000
#define MX3X_UART2_BASE_ADDR 0x43F94000 #define MX3X_UART2_BASE_ADDR 0x43F94000
#define MX51_UART1_BASE_ADDR 0x73fbc000
static __inline__ void __arch_decomp_setup(unsigned long arch_id) static __inline__ void __arch_decomp_setup(unsigned long arch_id)
{ {
@ -101,6 +102,9 @@ static __inline__ void __arch_decomp_setup(unsigned long arch_id)
case MACH_TYPE_MAGX_ZN5: case MACH_TYPE_MAGX_ZN5:
uart_base = MX3X_UART2_BASE_ADDR; uart_base = MX3X_UART2_BASE_ADDR;
break; break;
case MACH_TYPE_MX51_BABBAGE:
uart_base = MX51_UART1_BASE_ADDR;
break;
default: default:
break; break;
} }

View File

@ -428,26 +428,6 @@ static void vfp_pm_init(void)
static inline void vfp_pm_init(void) { } static inline void vfp_pm_init(void) { }
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
/*
* Synchronise the hardware VFP state of a thread other than current with the
* saved one. This function is used by the ptrace mechanism.
*/
#ifdef CONFIG_SMP
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
* context switch. We mark the thread VFP state as belonging to a
* non-existent CPU so that the saved one will be reloaded when
* needed.
*/
thread->vfpstate.hard.cpu = NR_CPUS;
}
#else
void vfp_sync_hwstate(struct thread_info *thread) void vfp_sync_hwstate(struct thread_info *thread)
{ {
unsigned int cpu = get_cpu(); unsigned int cpu = get_cpu();
@ -490,9 +470,18 @@ void vfp_flush_hwstate(struct thread_info *thread)
last_VFP_context[cpu] = NULL; last_VFP_context[cpu] = NULL;
} }
#ifdef CONFIG_SMP
/*
* For SMP we still have to take care of the case where the thread
* migrates to another CPU and then back to the original CPU on which
* the last VFP user is still the same thread. Mark the thread VFP
* state as belonging to a non-existent CPU so that the saved one will
* be reloaded in the above case.
*/
thread->vfpstate.hard.cpu = NR_CPUS;
#endif
put_cpu(); put_cpu();
} }
#endif
#include <linux/smp.h> #include <linux/smp.h>

View File

@ -148,14 +148,18 @@ static inline int atomic_xchg(atomic_t *v, int new)
static inline int atomic_sub_and_test(int i, atomic_t *v) static inline int atomic_sub_and_test(int i, atomic_t *v)
{ {
char c; char c;
__asm__ __volatile__("subl %2,%1; seq %0" : "=d" (c), "+m" (*v): "g" (i)); __asm__ __volatile__("subl %2,%1; seq %0"
: "=d" (c), "+m" (*v)
: "id" (i));
return c != 0; return c != 0;
} }
static inline int atomic_add_negative(int i, atomic_t *v) static inline int atomic_add_negative(int i, atomic_t *v)
{ {
char c; char c;
__asm__ __volatile__("addl %2,%1; smi %0" : "=d" (c), "+m" (*v): "g" (i)); __asm__ __volatile__("addl %2,%1; smi %0"
: "=d" (c), "+m" (*v)
: "id" (i));
return c != 0; return c != 0;
} }

View File

@ -17,13 +17,11 @@ struct sigcontext {
#ifndef __uClinux__ #ifndef __uClinux__
# ifdef __mcoldfire__ # ifdef __mcoldfire__
unsigned long sc_fpregs[2][2]; /* room for two fp registers */ unsigned long sc_fpregs[2][2]; /* room for two fp registers */
unsigned long sc_fpcntl[3];
unsigned char sc_fpstate[16+6*8];
# else # else
unsigned long sc_fpregs[2*3]; /* room for two fp registers */ unsigned long sc_fpregs[2*3]; /* room for two fp registers */
# endif
unsigned long sc_fpcntl[3]; unsigned long sc_fpcntl[3];
unsigned char sc_fpstate[216]; unsigned char sc_fpstate[216];
# endif
#endif #endif
}; };

View File

@ -60,43 +60,6 @@ void __init board_setup(void)
wmb(); wmb();
} }
/* use the hexleds to count the number of times the cpu has entered
* wait, the dots to indicate whether the CPU is currently idle or
* active (dots off = sleeping, dots on = working) for cases where
* the number doesn't change for a long(er) period of time.
*/
static void db1200_wait(void)
{
__asm__(" .set push \n"
" .set mips3 \n"
" .set noreorder \n"
" cache 0x14, 0(%0) \n"
" cache 0x14, 32(%0) \n"
" cache 0x14, 64(%0) \n"
/* dots off: we're about to call wait */
" lui $26, 0xb980 \n"
" ori $27, $0, 3 \n"
" sb $27, 0x18($26) \n"
" sync \n"
" nop \n"
" wait \n"
" nop \n"
" nop \n"
" nop \n"
" nop \n"
" nop \n"
/* dots on: there's work to do, increment cntr */
" lui $26, 0xb980 \n"
" sb $0, 0x18($26) \n"
" lui $26, 0xb9c0 \n"
" lb $27, 0($26) \n"
" addiu $27, $27, 1 \n"
" sb $27, 0($26) \n"
" sync \n"
" .set pop \n"
: : "r" (db1200_wait));
}
static int __init db1200_arch_init(void) static int __init db1200_arch_init(void)
{ {
/* GPIO7 is low-level triggered CPLD cascade */ /* GPIO7 is low-level triggered CPLD cascade */
@ -110,9 +73,6 @@ static int __init db1200_arch_init(void)
irq_to_desc(DB1200_SD0_INSERT_INT)->status |= IRQ_NOAUTOEN; irq_to_desc(DB1200_SD0_INSERT_INT)->status |= IRQ_NOAUTOEN;
irq_to_desc(DB1200_SD0_EJECT_INT)->status |= IRQ_NOAUTOEN; irq_to_desc(DB1200_SD0_EJECT_INT)->status |= IRQ_NOAUTOEN;
if (cpu_wait)
cpu_wait = db1200_wait;
return 0; return 0;
} }
arch_initcall(db1200_arch_init); arch_initcall(db1200_arch_init);

View File

@ -168,7 +168,7 @@ static struct plat_vlynq_data vlynq_high_data = {
.on = vlynq_on, .on = vlynq_on,
.off = vlynq_off, .off = vlynq_off,
}, },
.reset_bit = 26, .reset_bit = 16,
.gpio_bit = 19, .gpio_bit = 19,
}; };
@ -600,6 +600,7 @@ static int __init ar7_register_devices(void)
} }
if (ar7_has_high_cpmac()) { if (ar7_has_high_cpmac()) {
res = fixed_phy_add(PHY_POLL, cpmac_high.id, &fixed_phy_status);
if (!res) { if (!res) {
cpmac_get_mac(1, cpmac_high_data.dev_addr); cpmac_get_mac(1, cpmac_high_data.dev_addr);

View File

@ -18,6 +18,7 @@
#include <asm/addrspace.h> #include <asm/addrspace.h>
#include <bcm63xx_board.h> #include <bcm63xx_board.h>
#include <bcm63xx_cpu.h> #include <bcm63xx_cpu.h>
#include <bcm63xx_dev_uart.h>
#include <bcm63xx_regs.h> #include <bcm63xx_regs.h>
#include <bcm63xx_io.h> #include <bcm63xx_io.h>
#include <bcm63xx_dev_pci.h> #include <bcm63xx_dev_pci.h>
@ -40,6 +41,7 @@ static struct board_info __initdata board_96338gw = {
.name = "96338GW", .name = "96338GW",
.expected_cpu_id = 0x6338, .expected_cpu_id = 0x6338,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.enet0 = { .enet0 = {
.force_speed_100 = 1, .force_speed_100 = 1,
@ -82,6 +84,7 @@ static struct board_info __initdata board_96338w = {
.name = "96338W", .name = "96338W",
.expected_cpu_id = 0x6338, .expected_cpu_id = 0x6338,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.enet0 = { .enet0 = {
.force_speed_100 = 1, .force_speed_100 = 1,
@ -126,6 +129,8 @@ static struct board_info __initdata board_96338w = {
static struct board_info __initdata board_96345gw2 = { static struct board_info __initdata board_96345gw2 = {
.name = "96345GW2", .name = "96345GW2",
.expected_cpu_id = 0x6345, .expected_cpu_id = 0x6345,
.has_uart0 = 1,
}; };
#endif #endif
@ -137,6 +142,7 @@ static struct board_info __initdata board_96348r = {
.name = "96348R", .name = "96348R",
.expected_cpu_id = 0x6348, .expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.has_pci = 1, .has_pci = 1,
@ -180,6 +186,7 @@ static struct board_info __initdata board_96348gw_10 = {
.name = "96348GW-10", .name = "96348GW-10",
.expected_cpu_id = 0x6348, .expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.has_enet1 = 1, .has_enet1 = 1,
.has_pci = 1, .has_pci = 1,
@ -239,6 +246,7 @@ static struct board_info __initdata board_96348gw_11 = {
.name = "96348GW-11", .name = "96348GW-11",
.expected_cpu_id = 0x6348, .expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.has_enet1 = 1, .has_enet1 = 1,
.has_pci = 1, .has_pci = 1,
@ -292,6 +300,7 @@ static struct board_info __initdata board_96348gw = {
.name = "96348GW", .name = "96348GW",
.expected_cpu_id = 0x6348, .expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.has_enet1 = 1, .has_enet1 = 1,
.has_pci = 1, .has_pci = 1,
@ -349,6 +358,7 @@ static struct board_info __initdata board_FAST2404 = {
.name = "F@ST2404", .name = "F@ST2404",
.expected_cpu_id = 0x6348, .expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.has_enet1 = 1, .has_enet1 = 1,
.has_pci = 1, .has_pci = 1,
@ -368,10 +378,30 @@ static struct board_info __initdata board_FAST2404 = {
.has_ehci0 = 1, .has_ehci0 = 1,
}; };
static struct board_info __initdata board_rta1025w_16 = {
.name = "RTA1025W_16",
.expected_cpu_id = 0x6348,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
.enet0 = {
.has_phy = 1,
.use_internal_phy = 1,
},
.enet1 = {
.force_speed_100 = 1,
.force_duplex_full = 1,
},
};
static struct board_info __initdata board_DV201AMR = { static struct board_info __initdata board_DV201AMR = {
.name = "DV201AMR", .name = "DV201AMR",
.expected_cpu_id = 0x6348, .expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_pci = 1, .has_pci = 1,
.has_ohci0 = 1, .has_ohci0 = 1,
@ -391,6 +421,7 @@ static struct board_info __initdata board_96348gw_a = {
.name = "96348GW-A", .name = "96348GW-A",
.expected_cpu_id = 0x6348, .expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.has_enet1 = 1, .has_enet1 = 1,
.has_pci = 1, .has_pci = 1,
@ -416,6 +447,7 @@ static struct board_info __initdata board_96358vw = {
.name = "96358VW", .name = "96358VW",
.expected_cpu_id = 0x6358, .expected_cpu_id = 0x6358,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.has_enet1 = 1, .has_enet1 = 1,
.has_pci = 1, .has_pci = 1,
@ -467,6 +499,7 @@ static struct board_info __initdata board_96358vw2 = {
.name = "96358VW2", .name = "96358VW2",
.expected_cpu_id = 0x6358, .expected_cpu_id = 0x6358,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.has_enet1 = 1, .has_enet1 = 1,
.has_pci = 1, .has_pci = 1,
@ -514,6 +547,7 @@ static struct board_info __initdata board_AGPFS0 = {
.name = "AGPF-S0", .name = "AGPF-S0",
.expected_cpu_id = 0x6358, .expected_cpu_id = 0x6358,
.has_uart0 = 1,
.has_enet0 = 1, .has_enet0 = 1,
.has_enet1 = 1, .has_enet1 = 1,
.has_pci = 1, .has_pci = 1,
@ -531,6 +565,27 @@ static struct board_info __initdata board_AGPFS0 = {
.has_ohci0 = 1, .has_ohci0 = 1,
.has_ehci0 = 1, .has_ehci0 = 1,
}; };
static struct board_info __initdata board_DWVS0 = {
.name = "DWV-S0",
.expected_cpu_id = 0x6358,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
.enet0 = {
.has_phy = 1,
.use_internal_phy = 1,
},
.enet1 = {
.force_speed_100 = 1,
.force_duplex_full = 1,
},
.has_ohci0 = 1,
};
#endif #endif
/* /*
@ -552,15 +607,87 @@ static const struct board_info __initdata *bcm963xx_boards[] = {
&board_FAST2404, &board_FAST2404,
&board_DV201AMR, &board_DV201AMR,
&board_96348gw_a, &board_96348gw_a,
&board_rta1025w_16,
#endif #endif
#ifdef CONFIG_BCM63XX_CPU_6358 #ifdef CONFIG_BCM63XX_CPU_6358
&board_96358vw, &board_96358vw,
&board_96358vw2, &board_96358vw2,
&board_AGPFS0, &board_AGPFS0,
&board_DWVS0,
#endif #endif
}; };
/*
* Register a sane SPROMv2 to make the on-board
* bcm4318 WLAN work
*/
#ifdef CONFIG_SSB_PCIHOST
static struct ssb_sprom bcm63xx_sprom = {
.revision = 0x02,
.board_rev = 0x17,
.country_code = 0x0,
.ant_available_bg = 0x3,
.pa0b0 = 0x15ae,
.pa0b1 = 0xfa85,
.pa0b2 = 0xfe8d,
.pa1b0 = 0xffff,
.pa1b1 = 0xffff,
.pa1b2 = 0xffff,
.gpio0 = 0xff,
.gpio1 = 0xff,
.gpio2 = 0xff,
.gpio3 = 0xff,
.maxpwr_bg = 0x004c,
.itssi_bg = 0x00,
.boardflags_lo = 0x2848,
.boardflags_hi = 0x0000,
};
#endif
/*
* return board name for /proc/cpuinfo
*/
const char *board_get_name(void)
{
return board.name;
}
/*
* register & return a new board mac address
*/
static int board_get_mac_address(u8 *mac)
{
u8 *p;
int count;
if (mac_addr_used >= nvram.mac_addr_count) {
printk(KERN_ERR PFX "not enough mac address\n");
return -ENODEV;
}
memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
p = mac + ETH_ALEN - 1;
count = mac_addr_used;
while (count--) {
do {
(*p)++;
if (*p != 0)
break;
p--;
} while (p != mac);
}
if (p == mac) {
printk(KERN_ERR PFX "unable to fetch mac address\n");
return -ENODEV;
}
mac_addr_used++;
return 0;
}
/* /*
* early init callback, read nvram data from flash and checksum it * early init callback, read nvram data from flash and checksum it
*/ */
@ -659,6 +786,17 @@ void __init board_prom_init(void)
} }
bcm_gpio_writel(val, GPIO_MODE_REG); bcm_gpio_writel(val, GPIO_MODE_REG);
/* Generate MAC address for WLAN and
* register our SPROM */
#ifdef CONFIG_SSB_PCIHOST
if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
if (ssb_arch_set_fallback_sprom(&bcm63xx_sprom) < 0)
printk(KERN_ERR "failed to register fallback SPROM\n");
}
#endif
} }
/* /*
@ -676,49 +814,6 @@ void __init board_setup(void)
panic("unexpected CPU for bcm963xx board"); panic("unexpected CPU for bcm963xx board");
} }
/*
* return board name for /proc/cpuinfo
*/
const char *board_get_name(void)
{
return board.name;
}
/*
* register & return a new board mac address
*/
static int board_get_mac_address(u8 *mac)
{
u8 *p;
int count;
if (mac_addr_used >= nvram.mac_addr_count) {
printk(KERN_ERR PFX "not enough mac address\n");
return -ENODEV;
}
memcpy(mac, nvram.mac_addr_base, ETH_ALEN);
p = mac + ETH_ALEN - 1;
count = mac_addr_used;
while (count--) {
do {
(*p)++;
if (*p != 0)
break;
p--;
} while (p != mac);
}
if (p == mac) {
printk(KERN_ERR PFX "unable to fetch mac address\n");
return -ENODEV;
}
mac_addr_used++;
return 0;
}
static struct mtd_partition mtd_partitions[] = { static struct mtd_partition mtd_partitions[] = {
{ {
.name = "cfe", .name = "cfe",
@ -750,33 +845,6 @@ static struct platform_device mtd_dev = {
}, },
}; };
/*
* Register a sane SPROMv2 to make the on-board
* bcm4318 WLAN work
*/
#ifdef CONFIG_SSB_PCIHOST
static struct ssb_sprom bcm63xx_sprom = {
.revision = 0x02,
.board_rev = 0x17,
.country_code = 0x0,
.ant_available_bg = 0x3,
.pa0b0 = 0x15ae,
.pa0b1 = 0xfa85,
.pa0b2 = 0xfe8d,
.pa1b0 = 0xffff,
.pa1b1 = 0xffff,
.pa1b2 = 0xffff,
.gpio0 = 0xff,
.gpio1 = 0xff,
.gpio2 = 0xff,
.gpio3 = 0xff,
.maxpwr_bg = 0x004c,
.itssi_bg = 0x00,
.boardflags_lo = 0x2848,
.boardflags_hi = 0x0000,
};
#endif
static struct gpio_led_platform_data bcm63xx_led_data; static struct gpio_led_platform_data bcm63xx_led_data;
static struct platform_device bcm63xx_gpio_leds = { static struct platform_device bcm63xx_gpio_leds = {
@ -792,6 +860,12 @@ int __init board_register_devices(void)
{ {
u32 val; u32 val;
if (board.has_uart0)
bcm63xx_uart_register(0);
if (board.has_uart1)
bcm63xx_uart_register(1);
if (board.has_pccard) if (board.has_pccard)
bcm63xx_pcmcia_register(); bcm63xx_pcmcia_register();
@ -806,17 +880,6 @@ int __init board_register_devices(void)
if (board.has_dsp) if (board.has_dsp)
bcm63xx_dsp_register(&board.dsp); bcm63xx_dsp_register(&board.dsp);
/* Generate MAC address for WLAN and
* register our SPROM */
#ifdef CONFIG_SSB_PCIHOST
if (!board_get_mac_address(bcm63xx_sprom.il0mac)) {
memcpy(bcm63xx_sprom.et0mac, bcm63xx_sprom.il0mac, ETH_ALEN);
memcpy(bcm63xx_sprom.et1mac, bcm63xx_sprom.il0mac, ETH_ALEN);
if (ssb_arch_set_fallback_sprom(&bcm63xx_sprom) < 0)
printk(KERN_ERR "failed to register fallback SPROM\n");
}
#endif
/* read base address of boot chip select (0) */ /* read base address of boot chip select (0) */
if (BCMCPU_IS_6345()) if (BCMCPU_IS_6345())
val = 0x1fc00000; val = 0x1fc00000;

View File

@ -36,6 +36,7 @@ static const unsigned long bcm96338_regs_base[] = {
[RSET_TIMER] = BCM_6338_TIMER_BASE, [RSET_TIMER] = BCM_6338_TIMER_BASE,
[RSET_WDT] = BCM_6338_WDT_BASE, [RSET_WDT] = BCM_6338_WDT_BASE,
[RSET_UART0] = BCM_6338_UART0_BASE, [RSET_UART0] = BCM_6338_UART0_BASE,
[RSET_UART1] = BCM_6338_UART1_BASE,
[RSET_GPIO] = BCM_6338_GPIO_BASE, [RSET_GPIO] = BCM_6338_GPIO_BASE,
[RSET_SPI] = BCM_6338_SPI_BASE, [RSET_SPI] = BCM_6338_SPI_BASE,
[RSET_OHCI0] = BCM_6338_OHCI0_BASE, [RSET_OHCI0] = BCM_6338_OHCI0_BASE,
@ -72,6 +73,7 @@ static const unsigned long bcm96345_regs_base[] = {
[RSET_TIMER] = BCM_6345_TIMER_BASE, [RSET_TIMER] = BCM_6345_TIMER_BASE,
[RSET_WDT] = BCM_6345_WDT_BASE, [RSET_WDT] = BCM_6345_WDT_BASE,
[RSET_UART0] = BCM_6345_UART0_BASE, [RSET_UART0] = BCM_6345_UART0_BASE,
[RSET_UART1] = BCM_6345_UART1_BASE,
[RSET_GPIO] = BCM_6345_GPIO_BASE, [RSET_GPIO] = BCM_6345_GPIO_BASE,
[RSET_SPI] = BCM_6345_SPI_BASE, [RSET_SPI] = BCM_6345_SPI_BASE,
[RSET_UDC0] = BCM_6345_UDC0_BASE, [RSET_UDC0] = BCM_6345_UDC0_BASE,
@ -109,6 +111,7 @@ static const unsigned long bcm96348_regs_base[] = {
[RSET_TIMER] = BCM_6348_TIMER_BASE, [RSET_TIMER] = BCM_6348_TIMER_BASE,
[RSET_WDT] = BCM_6348_WDT_BASE, [RSET_WDT] = BCM_6348_WDT_BASE,
[RSET_UART0] = BCM_6348_UART0_BASE, [RSET_UART0] = BCM_6348_UART0_BASE,
[RSET_UART1] = BCM_6348_UART1_BASE,
[RSET_GPIO] = BCM_6348_GPIO_BASE, [RSET_GPIO] = BCM_6348_GPIO_BASE,
[RSET_SPI] = BCM_6348_SPI_BASE, [RSET_SPI] = BCM_6348_SPI_BASE,
[RSET_OHCI0] = BCM_6348_OHCI0_BASE, [RSET_OHCI0] = BCM_6348_OHCI0_BASE,
@ -150,6 +153,7 @@ static const unsigned long bcm96358_regs_base[] = {
[RSET_TIMER] = BCM_6358_TIMER_BASE, [RSET_TIMER] = BCM_6358_TIMER_BASE,
[RSET_WDT] = BCM_6358_WDT_BASE, [RSET_WDT] = BCM_6358_WDT_BASE,
[RSET_UART0] = BCM_6358_UART0_BASE, [RSET_UART0] = BCM_6358_UART0_BASE,
[RSET_UART1] = BCM_6358_UART1_BASE,
[RSET_GPIO] = BCM_6358_GPIO_BASE, [RSET_GPIO] = BCM_6358_GPIO_BASE,
[RSET_SPI] = BCM_6358_SPI_BASE, [RSET_SPI] = BCM_6358_SPI_BASE,
[RSET_OHCI0] = BCM_6358_OHCI0_BASE, [RSET_OHCI0] = BCM_6358_OHCI0_BASE,
@ -170,6 +174,7 @@ static const unsigned long bcm96358_regs_base[] = {
static const int bcm96358_irqs[] = { static const int bcm96358_irqs[] = {
[IRQ_TIMER] = BCM_6358_TIMER_IRQ, [IRQ_TIMER] = BCM_6358_TIMER_IRQ,
[IRQ_UART0] = BCM_6358_UART0_IRQ, [IRQ_UART0] = BCM_6358_UART0_IRQ,
[IRQ_UART1] = BCM_6358_UART1_IRQ,
[IRQ_DSL] = BCM_6358_DSL_IRQ, [IRQ_DSL] = BCM_6358_DSL_IRQ,
[IRQ_ENET0] = BCM_6358_ENET0_IRQ, [IRQ_ENET0] = BCM_6358_ENET0_IRQ,
[IRQ_ENET1] = BCM_6358_ENET1_IRQ, [IRQ_ENET1] = BCM_6358_ENET1_IRQ,

View File

@ -11,31 +11,65 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <bcm63xx_cpu.h> #include <bcm63xx_cpu.h>
static struct resource uart_resources[] = { static struct resource uart0_resources[] = {
{ {
.start = -1, /* filled at runtime */ /* start & end filled at runtime */
.end = -1, /* filled at runtime */
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
{ {
.start = -1, /* filled at runtime */ /* start filled at runtime */
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
}; };
static struct platform_device bcm63xx_uart_device = { static struct resource uart1_resources[] = {
.name = "bcm63xx_uart", {
.id = 0, /* start & end filled at runtime */
.num_resources = ARRAY_SIZE(uart_resources), .flags = IORESOURCE_MEM,
.resource = uart_resources, },
{
/* start filled at runtime */
.flags = IORESOURCE_IRQ,
},
}; };
int __init bcm63xx_uart_register(void) static struct platform_device bcm63xx_uart_devices[] = {
{
.name = "bcm63xx_uart",
.id = 0,
.num_resources = ARRAY_SIZE(uart0_resources),
.resource = uart0_resources,
},
{
.name = "bcm63xx_uart",
.id = 1,
.num_resources = ARRAY_SIZE(uart1_resources),
.resource = uart1_resources,
}
};
int __init bcm63xx_uart_register(unsigned int id)
{ {
uart_resources[0].start = bcm63xx_regset_address(RSET_UART0); if (id >= ARRAY_SIZE(bcm63xx_uart_devices))
uart_resources[0].end = uart_resources[0].start; return -ENODEV;
uart_resources[0].end += RSET_UART_SIZE - 1;
uart_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0); if (id == 1 && !BCMCPU_IS_6358())
return platform_device_register(&bcm63xx_uart_device); return -ENODEV;
if (id == 0) {
uart0_resources[0].start = bcm63xx_regset_address(RSET_UART0);
uart0_resources[0].end = uart0_resources[0].start +
RSET_UART_SIZE - 1;
uart0_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0);
}
if (id == 1) {
uart1_resources[0].start = bcm63xx_regset_address(RSET_UART1);
uart1_resources[0].end = uart1_resources[0].start +
RSET_UART_SIZE - 1;
uart1_resources[1].start = bcm63xx_get_irq_number(IRQ_UART1);
}
return platform_device_register(&bcm63xx_uart_devices[id]);
} }
arch_initcall(bcm63xx_uart_register);

View File

@ -125,10 +125,10 @@ static struct gpio_chip bcm63xx_gpio_chip = {
int __init bcm63xx_gpio_init(void) int __init bcm63xx_gpio_init(void)
{ {
gpio_out_low = bcm_gpio_readl(GPIO_DATA_LO_REG);
gpio_out_high = bcm_gpio_readl(GPIO_DATA_HI_REG);
bcm63xx_gpio_chip.ngpio = bcm63xx_gpio_count(); bcm63xx_gpio_chip.ngpio = bcm63xx_gpio_count();
pr_info("registering %d GPIOs\n", bcm63xx_gpio_chip.ngpio); pr_info("registering %d GPIOs\n", bcm63xx_gpio_chip.ngpio);
return gpiochip_add(&bcm63xx_gpio_chip); return gpiochip_add(&bcm63xx_gpio_chip);
} }
arch_initcall(bcm63xx_gpio_init);

View File

@ -45,9 +45,6 @@ extern struct plat_smp_ops octeon_smp_ops;
extern void pci_console_init(const char *arg); extern void pci_console_init(const char *arg);
#endif #endif
#ifdef CONFIG_CAVIUM_RESERVE32
extern uint64_t octeon_reserve32_memory;
#endif
static unsigned long long MAX_MEMORY = 512ull << 20; static unsigned long long MAX_MEMORY = 512ull << 20;
struct octeon_boot_descriptor *octeon_boot_desc_ptr; struct octeon_boot_descriptor *octeon_boot_desc_ptr;
@ -186,54 +183,6 @@ void octeon_check_cpu_bist(void)
write_octeon_c0_dcacheerr(0); write_octeon_c0_dcacheerr(0);
} }
#ifdef CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB
/**
* Called on every core to setup the wired tlb entry needed
* if CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB is set.
*
*/
static void octeon_hal_setup_per_cpu_reserved32(void *unused)
{
/*
* The config has selected to wire the reserve32 memory for all
* userspace applications. We need to put a wired TLB entry in for each
* 512MB of reserve32 memory. We only handle double 256MB pages here,
* so reserve32 must be multiple of 512MB.
*/
uint32_t size = CONFIG_CAVIUM_RESERVE32;
uint32_t entrylo0 =
0x7 | ((octeon_reserve32_memory & ((1ul << 40) - 1)) >> 6);
uint32_t entrylo1 = entrylo0 + (256 << 14);
uint32_t entryhi = (0x80000000UL - (CONFIG_CAVIUM_RESERVE32 << 20));
while (size >= 512) {
#if 0
pr_info("CPU%d: Adding double wired TLB entry for 0x%lx\n",
smp_processor_id(), entryhi);
#endif
add_wired_entry(entrylo0, entrylo1, entryhi, PM_256M);
entrylo0 += 512 << 14;
entrylo1 += 512 << 14;
entryhi += 512 << 20;
size -= 512;
}
}
#endif /* CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB */
/**
* Called to release the named block which was used to made sure
* that nobody used the memory for something else during
* init. Now we'll free it so userspace apps can use this
* memory region with bootmem_alloc.
*
* This function is called only once from prom_free_prom_memory().
*/
void octeon_hal_setup_reserved32(void)
{
#ifdef CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB
on_each_cpu(octeon_hal_setup_per_cpu_reserved32, NULL, 0, 1);
#endif
}
/** /**
* Reboot Octeon * Reboot Octeon
* *
@ -294,18 +243,6 @@ static void octeon_halt(void)
octeon_kill_core(NULL); octeon_kill_core(NULL);
} }
#if 0
/**
* Platform time init specifics.
* Returns
*/
void __init plat_time_init(void)
{
/* Nothing special here, but we are required to have one */
}
#endif
/** /**
* Handle all the error condition interrupts that might occur. * Handle all the error condition interrupts that might occur.
* *
@ -502,25 +439,13 @@ void __init prom_init(void)
* memory when it is getting memory from the * memory when it is getting memory from the
* bootloader. Later, after the memory allocations are * bootloader. Later, after the memory allocations are
* complete, the reserve32 will be freed. * complete, the reserve32 will be freed.
*/ *
#ifdef CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB
if (CONFIG_CAVIUM_RESERVE32 & 0x1ff)
pr_err("CAVIUM_RESERVE32 isn't a multiple of 512MB. "
"This is required if CAVIUM_RESERVE32_USE_WIRED_TLB "
"is set\n");
else
addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
0, 0, 512 << 20,
"CAVIUM_RESERVE32", 0);
#else
/*
* Allocate memory for RESERVED32 aligned on 2MB boundary. This * Allocate memory for RESERVED32 aligned on 2MB boundary. This
* is in case we later use hugetlb entries with it. * is in case we later use hugetlb entries with it.
*/ */
addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20, addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
0, 0, 2 << 20, 0, 0, 2 << 20,
"CAVIUM_RESERVE32", 0); "CAVIUM_RESERVE32", 0);
#endif
if (addr < 0) if (addr < 0)
pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n"); pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n");
else else
@ -817,9 +742,4 @@ void prom_free_prom_memory(void)
panic("Unable to request_irq(OCTEON_IRQ_RML)\n"); panic("Unable to request_irq(OCTEON_IRQ_RML)\n");
} }
#endif #endif
/* This call is here so that it is performed after any TLB
initializations. It needs to be after these in case the
CONFIG_CAVIUM_RESERVE32_USE_WIRED_TLB option is set */
octeon_hal_setup_reserved32();
} }

View File

@ -279,14 +279,6 @@ static void octeon_cpu_die(unsigned int cpu)
uint32_t avail_coremask; uint32_t avail_coremask;
struct cvmx_bootmem_named_block_desc *block_desc; struct cvmx_bootmem_named_block_desc *block_desc;
#ifdef CONFIG_CAVIUM_OCTEON_WATCHDOG
/* Disable the watchdog */
cvmx_ciu_wdogx_t ciu_wdog;
ciu_wdog.u64 = cvmx_read_csr(CVMX_CIU_WDOGX(cpu));
ciu_wdog.s.mode = 0;
cvmx_write_csr(CVMX_CIU_WDOGX(cpu), ciu_wdog.u64);
#endif
while (per_cpu(cpu_state, cpu) != CPU_DEAD) while (per_cpu(cpu_state, cpu) != CPU_DEAD)
cpu_relax(); cpu_relax();

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,14 @@
#include <asm/siginfo.h> #include <asm/siginfo.h>
struct mips_abi { struct mips_abi {
int (* const setup_frame)(struct k_sigaction * ka, int (* const setup_frame)(void *sig_return, struct k_sigaction *ka,
struct pt_regs *regs, int signr, struct pt_regs *regs, int signr,
sigset_t *set); sigset_t *set);
int (* const setup_rt_frame)(struct k_sigaction * ka, const unsigned long signal_return_offset;
int (* const setup_rt_frame)(void *sig_return, struct k_sigaction *ka,
struct pt_regs *regs, int signr, struct pt_regs *regs, int signr,
sigset_t *set, siginfo_t *info); sigset_t *set, siginfo_t *info);
const unsigned long rt_signal_return_offset;
const unsigned long restart; const unsigned long restart;
}; };

View File

@ -310,6 +310,7 @@ do { \
#endif /* CONFIG_64BIT */ #endif /* CONFIG_64BIT */
struct pt_regs;
struct task_struct; struct task_struct;
extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs); extern void elf_dump_regs(elf_greg_t *, struct pt_regs *regs);
@ -367,4 +368,8 @@ extern const char *__elf_platform;
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
#endif #endif
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);
#endif /* _ASM_ELF_H */ #endif /* _ASM_ELF_H */

View File

@ -41,7 +41,11 @@ struct mips_fpu_emulator_stats {
DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats); DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
#define MIPS_FPU_EMU_INC_STATS(M) \ #define MIPS_FPU_EMU_INC_STATS(M) \
cpu_local_wrap(__local_inc(&__get_cpu_var(fpuemustats).M)) do { \
preempt_disable(); \
__local_inc(&__get_cpu_var(fpuemustats).M); \
preempt_enable(); \
} while (0)
#else #else
#define MIPS_FPU_EMU_INC_STATS(M) do { } while (0) #define MIPS_FPU_EMU_INC_STATS(M) do { } while (0)

View File

@ -85,6 +85,7 @@ enum bcm63xx_regs_set {
RSET_TIMER, RSET_TIMER,
RSET_WDT, RSET_WDT,
RSET_UART0, RSET_UART0,
RSET_UART1,
RSET_GPIO, RSET_GPIO,
RSET_SPI, RSET_SPI,
RSET_UDC0, RSET_UDC0,
@ -123,6 +124,7 @@ enum bcm63xx_regs_set {
#define BCM_6338_TIMER_BASE (0xfffe0200) #define BCM_6338_TIMER_BASE (0xfffe0200)
#define BCM_6338_WDT_BASE (0xfffe021c) #define BCM_6338_WDT_BASE (0xfffe021c)
#define BCM_6338_UART0_BASE (0xfffe0300) #define BCM_6338_UART0_BASE (0xfffe0300)
#define BCM_6338_UART1_BASE (0xdeadbeef)
#define BCM_6338_GPIO_BASE (0xfffe0400) #define BCM_6338_GPIO_BASE (0xfffe0400)
#define BCM_6338_SPI_BASE (0xfffe0c00) #define BCM_6338_SPI_BASE (0xfffe0c00)
#define BCM_6338_UDC0_BASE (0xdeadbeef) #define BCM_6338_UDC0_BASE (0xdeadbeef)
@ -153,6 +155,7 @@ enum bcm63xx_regs_set {
#define BCM_6345_TIMER_BASE (0xfffe0200) #define BCM_6345_TIMER_BASE (0xfffe0200)
#define BCM_6345_WDT_BASE (0xfffe021c) #define BCM_6345_WDT_BASE (0xfffe021c)
#define BCM_6345_UART0_BASE (0xfffe0300) #define BCM_6345_UART0_BASE (0xfffe0300)
#define BCM_6345_UART1_BASE (0xdeadbeef)
#define BCM_6345_GPIO_BASE (0xfffe0400) #define BCM_6345_GPIO_BASE (0xfffe0400)
#define BCM_6345_SPI_BASE (0xdeadbeef) #define BCM_6345_SPI_BASE (0xdeadbeef)
#define BCM_6345_UDC0_BASE (0xdeadbeef) #define BCM_6345_UDC0_BASE (0xdeadbeef)
@ -182,6 +185,7 @@ enum bcm63xx_regs_set {
#define BCM_6348_TIMER_BASE (0xfffe0200) #define BCM_6348_TIMER_BASE (0xfffe0200)
#define BCM_6348_WDT_BASE (0xfffe021c) #define BCM_6348_WDT_BASE (0xfffe021c)
#define BCM_6348_UART0_BASE (0xfffe0300) #define BCM_6348_UART0_BASE (0xfffe0300)
#define BCM_6348_UART1_BASE (0xdeadbeef)
#define BCM_6348_GPIO_BASE (0xfffe0400) #define BCM_6348_GPIO_BASE (0xfffe0400)
#define BCM_6348_SPI_BASE (0xfffe0c00) #define BCM_6348_SPI_BASE (0xfffe0c00)
#define BCM_6348_UDC0_BASE (0xfffe1000) #define BCM_6348_UDC0_BASE (0xfffe1000)
@ -208,6 +212,7 @@ enum bcm63xx_regs_set {
#define BCM_6358_TIMER_BASE (0xfffe0040) #define BCM_6358_TIMER_BASE (0xfffe0040)
#define BCM_6358_WDT_BASE (0xfffe005c) #define BCM_6358_WDT_BASE (0xfffe005c)
#define BCM_6358_UART0_BASE (0xfffe0100) #define BCM_6358_UART0_BASE (0xfffe0100)
#define BCM_6358_UART1_BASE (0xfffe0120)
#define BCM_6358_GPIO_BASE (0xfffe0080) #define BCM_6358_GPIO_BASE (0xfffe0080)
#define BCM_6358_SPI_BASE (0xdeadbeef) #define BCM_6358_SPI_BASE (0xdeadbeef)
#define BCM_6358_UDC0_BASE (0xfffe0800) #define BCM_6358_UDC0_BASE (0xfffe0800)
@ -246,6 +251,8 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
return BCM_6338_WDT_BASE; return BCM_6338_WDT_BASE;
case RSET_UART0: case RSET_UART0:
return BCM_6338_UART0_BASE; return BCM_6338_UART0_BASE;
case RSET_UART1:
return BCM_6338_UART1_BASE;
case RSET_GPIO: case RSET_GPIO:
return BCM_6338_GPIO_BASE; return BCM_6338_GPIO_BASE;
case RSET_SPI: case RSET_SPI:
@ -292,6 +299,8 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
return BCM_6345_WDT_BASE; return BCM_6345_WDT_BASE;
case RSET_UART0: case RSET_UART0:
return BCM_6345_UART0_BASE; return BCM_6345_UART0_BASE;
case RSET_UART1:
return BCM_6345_UART1_BASE;
case RSET_GPIO: case RSET_GPIO:
return BCM_6345_GPIO_BASE; return BCM_6345_GPIO_BASE;
case RSET_SPI: case RSET_SPI:
@ -338,6 +347,8 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
return BCM_6348_WDT_BASE; return BCM_6348_WDT_BASE;
case RSET_UART0: case RSET_UART0:
return BCM_6348_UART0_BASE; return BCM_6348_UART0_BASE;
case RSET_UART1:
return BCM_6348_UART1_BASE;
case RSET_GPIO: case RSET_GPIO:
return BCM_6348_GPIO_BASE; return BCM_6348_GPIO_BASE;
case RSET_SPI: case RSET_SPI:
@ -384,6 +395,8 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
return BCM_6358_WDT_BASE; return BCM_6358_WDT_BASE;
case RSET_UART0: case RSET_UART0:
return BCM_6358_UART0_BASE; return BCM_6358_UART0_BASE;
case RSET_UART1:
return BCM_6358_UART1_BASE;
case RSET_GPIO: case RSET_GPIO:
return BCM_6358_GPIO_BASE; return BCM_6358_GPIO_BASE;
case RSET_SPI: case RSET_SPI:
@ -429,6 +442,7 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
enum bcm63xx_irq { enum bcm63xx_irq {
IRQ_TIMER = 0, IRQ_TIMER = 0,
IRQ_UART0, IRQ_UART0,
IRQ_UART1,
IRQ_DSL, IRQ_DSL,
IRQ_ENET0, IRQ_ENET0,
IRQ_ENET1, IRQ_ENET1,
@ -510,6 +524,7 @@ enum bcm63xx_irq {
*/ */
#define BCM_6358_TIMER_IRQ (IRQ_INTERNAL_BASE + 0) #define BCM_6358_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
#define BCM_6358_UART0_IRQ (IRQ_INTERNAL_BASE + 2) #define BCM_6358_UART0_IRQ (IRQ_INTERNAL_BASE + 2)
#define BCM_6358_UART1_IRQ (IRQ_INTERNAL_BASE + 3)
#define BCM_6358_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5) #define BCM_6358_OHCI0_IRQ (IRQ_INTERNAL_BASE + 5)
#define BCM_6358_ENET1_IRQ (IRQ_INTERNAL_BASE + 6) #define BCM_6358_ENET1_IRQ (IRQ_INTERNAL_BASE + 6)
#define BCM_6358_ENET0_IRQ (IRQ_INTERNAL_BASE + 8) #define BCM_6358_ENET0_IRQ (IRQ_INTERNAL_BASE + 8)

View File

@ -0,0 +1,6 @@
#ifndef BCM63XX_DEV_UART_H_
#define BCM63XX_DEV_UART_H_
int bcm63xx_uart_register(unsigned int id);
#endif /* BCM63XX_DEV_UART_H_ */

View File

@ -10,6 +10,10 @@ static inline unsigned long bcm63xx_gpio_count(void)
switch (bcm63xx_get_cpu_id()) { switch (bcm63xx_get_cpu_id()) {
case BCM6358_CPU_ID: case BCM6358_CPU_ID:
return 40; return 40;
case BCM6338_CPU_ID:
return 8;
case BCM6345_CPU_ID:
return 16;
case BCM6348_CPU_ID: case BCM6348_CPU_ID:
default: default:
return 37; return 37;

View File

@ -45,6 +45,8 @@ struct board_info {
unsigned int has_ohci0:1; unsigned int has_ohci0:1;
unsigned int has_ehci0:1; unsigned int has_ehci0:1;
unsigned int has_dsp:1; unsigned int has_dsp:1;
unsigned int has_uart0:1;
unsigned int has_uart1:1;
/* ethernet config */ /* ethernet config */
struct bcm63xx_enet_platform_data enet0; struct bcm63xx_enet_platform_data enet0;

View File

@ -24,7 +24,7 @@
#define cpu_has_smartmips 0 #define cpu_has_smartmips 0
#define cpu_has_vtag_icache 0 #define cpu_has_vtag_icache 0
#if !defined(BCMCPU_RUNTIME_DETECT) && (defined(CONFIG_BCMCPU_IS_6348) || defined(CONFIG_CPU_IS_6338) || defined(CONFIG_CPU_IS_BCM6345)) #if !defined(BCMCPU_RUNTIME_DETECT) && (defined(CONFIG_BCM63XX_CPU_6348) || defined(CONFIG_BCM63XX_CPU_6345) || defined(CONFIG_BCM63XX_CPU_6338))
#define cpu_has_dc_aliases 0 #define cpu_has_dc_aliases 0
#endif #endif

View File

@ -16,7 +16,11 @@
#if defined(CONFIG_SB1_PASS_1_WORKAROUNDS) || \ #if defined(CONFIG_SB1_PASS_1_WORKAROUNDS) || \
defined(CONFIG_SB1_PASS_2_WORKAROUNDS) defined(CONFIG_SB1_PASS_2_WORKAROUNDS)
#define BCM1250_M3_WAR 1 #ifndef __ASSEMBLY__
extern int sb1250_m3_workaround_needed(void);
#endif
#define BCM1250_M3_WAR sb1250_m3_workaround_needed()
#define SIBYTE_1956_WAR 1 #define SIBYTE_1956_WAR 1
#else #else

View File

@ -1,6 +1,9 @@
#ifndef __ASM_MMU_H #ifndef __ASM_MMU_H
#define __ASM_MMU_H #define __ASM_MMU_H
typedef unsigned long mm_context_t[NR_CPUS]; typedef struct {
unsigned long asid[NR_CPUS];
void *vdso;
} mm_context_t;
#endif /* __ASM_MMU_H */ #endif /* __ASM_MMU_H */

View File

@ -104,7 +104,7 @@ extern unsigned long smtc_asid_mask;
#endif #endif
#define cpu_context(cpu, mm) ((mm)->context[cpu]) #define cpu_context(cpu, mm) ((mm)->context.asid[cpu])
#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK) #define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & ASID_MASK)
#define asid_cache(cpu) (cpu_data[cpu].asid_cache) #define asid_cache(cpu) (cpu_data[cpu].asid_cache)

View File

@ -188,8 +188,10 @@ typedef struct { unsigned long pgprot; } pgprot_t;
#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE + \
#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) PHYS_OFFSET)
#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET - \
PHYS_OFFSET)
#include <asm-generic/memory_model.h> #include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h> #include <asm-generic/getorder.h>

View File

@ -33,13 +33,19 @@ extern void (*cpu_wait)(void);
extern unsigned int vced_count, vcei_count; extern unsigned int vced_count, vcei_count;
/*
* A special page (the vdso) is mapped into all processes at the very
* top of the virtual memory space.
*/
#define SPECIAL_PAGES_SIZE PAGE_SIZE
#ifdef CONFIG_32BIT #ifdef CONFIG_32BIT
/* /*
* User space process size: 2GB. This is hardcoded into a few places, * User space process size: 2GB. This is hardcoded into a few places,
* so don't change it unless you know what you are doing. * so don't change it unless you know what you are doing.
*/ */
#define TASK_SIZE 0x7fff8000UL #define TASK_SIZE 0x7fff8000UL
#define STACK_TOP TASK_SIZE #define STACK_TOP ((TASK_SIZE & PAGE_MASK) - SPECIAL_PAGES_SIZE)
/* /*
* This decides where the kernel will search for a free chunk of vm * This decides where the kernel will search for a free chunk of vm
@ -59,7 +65,8 @@ extern unsigned int vced_count, vcei_count;
#define TASK_SIZE32 0x7fff8000UL #define TASK_SIZE32 0x7fff8000UL
#define TASK_SIZE 0x10000000000UL #define TASK_SIZE 0x10000000000UL
#define STACK_TOP \ #define STACK_TOP \
(test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE) (((test_thread_flag(TIF_32BIT_ADDR) ? \
TASK_SIZE32 : TASK_SIZE) & PAGE_MASK) - SPECIAL_PAGES_SIZE)
/* /*
* This decides where the kernel will search for a free chunk of vm * This decides where the kernel will search for a free chunk of vm

View File

@ -121,6 +121,25 @@
.endm .endm
#else #else
.macro get_saved_sp /* Uniprocessor variation */ .macro get_saved_sp /* Uniprocessor variation */
#ifdef CONFIG_CPU_LOONGSON2F
/*
* Clear BTB (branch target buffer), forbid RAS (return address
* stack) to workaround the Out-of-order Issue in Loongson2F
* via its diagnostic register.
*/
move k0, ra
jal 1f
nop
1: jal 1f
nop
1: jal 1f
nop
1: jal 1f
nop
1: move ra, k0
li k0, 3
mtc0 k0, $22
#endif /* CONFIG_CPU_LOONGSON2F */
#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) #if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
lui k1, %hi(kernelsp) lui k1, %hi(kernelsp)
#else #else

View File

@ -84,6 +84,7 @@ Ip_u2s3u1(_lw);
Ip_u1u2u3(_mfc0); Ip_u1u2u3(_mfc0);
Ip_u1u2u3(_mtc0); Ip_u1u2u3(_mtc0);
Ip_u2u1u3(_ori); Ip_u2u1u3(_ori);
Ip_u3u1u2(_or);
Ip_u2s3u1(_pref); Ip_u2s3u1(_pref);
Ip_0(_rfe); Ip_0(_rfe);
Ip_u2s3u1(_sc); Ip_u2s3u1(_sc);
@ -102,6 +103,7 @@ Ip_0(_tlbwr);
Ip_u3u1u2(_xor); Ip_u3u1u2(_xor);
Ip_u2u1u3(_xori); Ip_u2u1u3(_xori);
Ip_u2u1msbu3(_dins); Ip_u2u1msbu3(_dins);
Ip_u1(_syscall);
/* Handle labels. */ /* Handle labels. */
struct uasm_label { struct uasm_label {

View File

@ -0,0 +1,29 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2009 Cavium Networks
*/
#ifndef __ASM_VDSO_H
#define __ASM_VDSO_H
#include <linux/types.h>
#ifdef CONFIG_32BIT
struct mips_vdso {
u32 signal_trampoline[2];
u32 rt_signal_trampoline[2];
};
#else /* !CONFIG_32BIT */
struct mips_vdso {
u32 o32_signal_trampoline[2];
u32 o32_rt_signal_trampoline[2];
u32 rt_signal_trampoline[2];
u32 n32_rt_signal_trampoline[2];
};
#endif /* CONFIG_32BIT */
#endif /* __ASM_VDSO_H */

View File

@ -6,7 +6,7 @@ extra-y := head.o init_task.o vmlinux.lds
obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
ptrace.o reset.o setup.o signal.o syscall.o \ ptrace.o reset.o setup.o signal.o syscall.o \
time.o topology.o traps.o unaligned.o watch.o time.o topology.o traps.o unaligned.o watch.o vdso.o
ifdef CONFIG_FUNCTION_TRACER ifdef CONFIG_FUNCTION_TRACER
CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_ftrace.o = -pg

View File

@ -164,3 +164,7 @@ void loongson2_cpu_wait(void)
spin_unlock_irqrestore(&loongson2_wait_lock, flags); spin_unlock_irqrestore(&loongson2_wait_lock, flags);
} }
EXPORT_SYMBOL_GPL(loongson2_cpu_wait); EXPORT_SYMBOL_GPL(loongson2_cpu_wait);
MODULE_AUTHOR("Yanhua <yanh@lemote.com>");
MODULE_DESCRIPTION("cpufreq driver for Loongson 2F");
MODULE_LICENSE("GPL");

View File

@ -63,8 +63,13 @@ void __noreturn cpu_idle(void)
smtc_idle_loop_hook(); smtc_idle_loop_hook();
#endif #endif
if (cpu_wait)
if (cpu_wait) {
/* Don't trace irqs off for idle */
stop_critical_timings();
(*cpu_wait)(); (*cpu_wait)();
start_critical_timings();
}
} }
#ifdef CONFIG_HOTPLUG_CPU #ifdef CONFIG_HOTPLUG_CPU
if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) && if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) &&

View File

@ -26,11 +26,6 @@
*/ */
extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size); size_t frame_size);
/*
* install trampoline code to get back from the sig handler
*/
extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall);
/* Check and clear pending FPU exceptions in saved CSR */ /* Check and clear pending FPU exceptions in saved CSR */
extern int fpcsr_pending(unsigned int __user *fpcsr); extern int fpcsr_pending(unsigned int __user *fpcsr);

View File

@ -32,6 +32,7 @@
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/cpu-features.h> #include <asm/cpu-features.h>
#include <asm/war.h> #include <asm/war.h>
#include <asm/vdso.h>
#include "signal-common.h" #include "signal-common.h"
@ -44,47 +45,20 @@ extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc);
extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc);
/*
* Horribly complicated - with the bloody RM9000 workarounds enabled
* the signal trampolines is moving to the end of the structure so we can
* increase the alignment without breaking software compatibility.
*/
#if ICACHE_REFILLS_WORKAROUND_WAR == 0
struct sigframe { struct sigframe {
u32 sf_ass[4]; /* argument save space for o32 */ u32 sf_ass[4]; /* argument save space for o32 */
u32 sf_code[2]; /* signal trampoline */ u32 sf_pad[2]; /* Was: signal trampoline */
struct sigcontext sf_sc; struct sigcontext sf_sc;
sigset_t sf_mask; sigset_t sf_mask;
}; };
struct rt_sigframe { struct rt_sigframe {
u32 rs_ass[4]; /* argument save space for o32 */ u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_code[2]; /* signal trampoline */ u32 rs_pad[2]; /* Was: signal trampoline */
struct siginfo rs_info; struct siginfo rs_info;
struct ucontext rs_uc; struct ucontext rs_uc;
}; };
#else
struct sigframe {
u32 sf_ass[4]; /* argument save space for o32 */
u32 sf_pad[2];
struct sigcontext sf_sc; /* hw context */
sigset_t sf_mask;
u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
};
struct rt_sigframe {
u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_pad[2];
struct siginfo rs_info;
struct ucontext rs_uc;
u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
};
#endif
/* /*
* Helper routines * Helper routines
*/ */
@ -266,32 +240,6 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
} }
int install_sigtramp(unsigned int __user *tramp, unsigned int syscall)
{
int err;
/*
* Set up the return code ...
*
* li v0, __NR__foo_sigreturn
* syscall
*/
err = __put_user(0x24020000 + syscall, tramp + 0);
err |= __put_user(0x0000000c , tramp + 1);
if (ICACHE_REFILLS_WORKAROUND_WAR) {
err |= __put_user(0, tramp + 2);
err |= __put_user(0, tramp + 3);
err |= __put_user(0, tramp + 4);
err |= __put_user(0, tramp + 5);
err |= __put_user(0, tramp + 6);
err |= __put_user(0, tramp + 7);
}
flush_cache_sigtramp((unsigned long) tramp);
return err;
}
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
*/ */
@ -484,8 +432,8 @@ badframe:
} }
#ifdef CONFIG_TRAD_SIGNALS #ifdef CONFIG_TRAD_SIGNALS
static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, static int setup_frame(void *sig_return, struct k_sigaction *ka,
int signr, sigset_t *set) struct pt_regs *regs, int signr, sigset_t *set)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
int err = 0; int err = 0;
@ -494,8 +442,6 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; goto give_sigsegv;
err |= install_sigtramp(frame->sf_code, __NR_sigreturn);
err |= setup_sigcontext(regs, &frame->sf_sc); err |= setup_sigcontext(regs, &frame->sf_sc);
err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
if (err) if (err)
@ -515,7 +461,7 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
regs->regs[ 5] = 0; regs->regs[ 5] = 0;
regs->regs[ 6] = (unsigned long) &frame->sf_sc; regs->regs[ 6] = (unsigned long) &frame->sf_sc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) frame->sf_code; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@ -529,8 +475,9 @@ give_sigsegv:
} }
#endif #endif
static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
int signr, sigset_t *set, siginfo_t *info) struct pt_regs *regs, int signr, sigset_t *set,
siginfo_t *info)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0;
@ -539,8 +486,6 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; goto give_sigsegv;
err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
/* Create siginfo. */ /* Create siginfo. */
err |= copy_siginfo_to_user(&frame->rs_info, info); err |= copy_siginfo_to_user(&frame->rs_info, info);
@ -573,7 +518,7 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
regs->regs[ 5] = (unsigned long) &frame->rs_info; regs->regs[ 5] = (unsigned long) &frame->rs_info;
regs->regs[ 6] = (unsigned long) &frame->rs_uc; regs->regs[ 6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) frame->rs_code; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@ -590,8 +535,11 @@ give_sigsegv:
struct mips_abi mips_abi = { struct mips_abi mips_abi = {
#ifdef CONFIG_TRAD_SIGNALS #ifdef CONFIG_TRAD_SIGNALS
.setup_frame = setup_frame, .setup_frame = setup_frame,
.signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),
#endif #endif
.setup_rt_frame = setup_rt_frame, .setup_rt_frame = setup_rt_frame,
.rt_signal_return_offset =
offsetof(struct mips_vdso, rt_signal_trampoline),
.restart = __NR_restart_syscall .restart = __NR_restart_syscall
}; };
@ -599,6 +547,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
{ {
int ret; int ret;
struct mips_abi *abi = current->thread.abi;
void *vdso = current->mm->context.vdso;
switch(regs->regs[0]) { switch(regs->regs[0]) {
case ERESTART_RESTARTBLOCK: case ERESTART_RESTARTBLOCK:
@ -619,9 +569,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
regs->regs[0] = 0; /* Don't deal with this again. */ regs->regs[0] = 0; /* Don't deal with this again. */
if (sig_uses_siginfo(ka)) if (sig_uses_siginfo(ka))
ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info); ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
ka, regs, sig, oldset, info);
else else
ret = current->thread.abi->setup_frame(ka, regs, sig, oldset); ret = abi->setup_frame(vdso + abi->signal_return_offset,
ka, regs, sig, oldset);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask); sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);

View File

@ -32,6 +32,7 @@
#include <asm/system.h> #include <asm/system.h>
#include <asm/fpu.h> #include <asm/fpu.h>
#include <asm/war.h> #include <asm/war.h>
#include <asm/vdso.h>
#include "signal-common.h" #include "signal-common.h"
@ -47,8 +48,6 @@ extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user
/* /*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ... * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
*/ */
#define __NR_O32_sigreturn 4119
#define __NR_O32_rt_sigreturn 4193
#define __NR_O32_restart_syscall 4253 #define __NR_O32_restart_syscall 4253
/* 32-bit compatibility types */ /* 32-bit compatibility types */
@ -77,47 +76,20 @@ struct ucontext32 {
compat_sigset_t uc_sigmask; /* mask last for extensibility */ compat_sigset_t uc_sigmask; /* mask last for extensibility */
}; };
/*
* Horribly complicated - with the bloody RM9000 workarounds enabled
* the signal trampolines is moving to the end of the structure so we can
* increase the alignment without breaking software compatibility.
*/
#if ICACHE_REFILLS_WORKAROUND_WAR == 0
struct sigframe32 { struct sigframe32 {
u32 sf_ass[4]; /* argument save space for o32 */ u32 sf_ass[4]; /* argument save space for o32 */
u32 sf_code[2]; /* signal trampoline */ u32 sf_pad[2]; /* Was: signal trampoline */
struct sigcontext32 sf_sc; struct sigcontext32 sf_sc;
compat_sigset_t sf_mask; compat_sigset_t sf_mask;
}; };
struct rt_sigframe32 { struct rt_sigframe32 {
u32 rs_ass[4]; /* argument save space for o32 */ u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_code[2]; /* signal trampoline */ u32 rs_pad[2]; /* Was: signal trampoline */
compat_siginfo_t rs_info; compat_siginfo_t rs_info;
struct ucontext32 rs_uc; struct ucontext32 rs_uc;
}; };
#else /* ICACHE_REFILLS_WORKAROUND_WAR */
struct sigframe32 {
u32 sf_ass[4]; /* argument save space for o32 */
u32 sf_pad[2];
struct sigcontext32 sf_sc; /* hw context */
compat_sigset_t sf_mask;
u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
};
struct rt_sigframe32 {
u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_pad[2];
compat_siginfo_t rs_info;
struct ucontext32 rs_uc;
u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
};
#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
/* /*
* sigcontext handlers * sigcontext handlers
*/ */
@ -598,8 +570,8 @@ badframe:
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
} }
static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
int signr, sigset_t *set) struct pt_regs *regs, int signr, sigset_t *set)
{ {
struct sigframe32 __user *frame; struct sigframe32 __user *frame;
int err = 0; int err = 0;
@ -608,8 +580,6 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; goto give_sigsegv;
err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
err |= setup_sigcontext32(regs, &frame->sf_sc); err |= setup_sigcontext32(regs, &frame->sf_sc);
err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
@ -630,7 +600,7 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
regs->regs[ 5] = 0; regs->regs[ 5] = 0;
regs->regs[ 6] = (unsigned long) &frame->sf_sc; regs->regs[ 6] = (unsigned long) &frame->sf_sc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) frame->sf_code; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@ -644,8 +614,9 @@ give_sigsegv:
return -EFAULT; return -EFAULT;
} }
static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
int signr, sigset_t *set, siginfo_t *info) struct pt_regs *regs, int signr, sigset_t *set,
siginfo_t *info)
{ {
struct rt_sigframe32 __user *frame; struct rt_sigframe32 __user *frame;
int err = 0; int err = 0;
@ -655,8 +626,6 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; goto give_sigsegv;
err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
err |= copy_siginfo_to_user32(&frame->rs_info, info); err |= copy_siginfo_to_user32(&frame->rs_info, info);
@ -690,7 +659,7 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
regs->regs[ 5] = (unsigned long) &frame->rs_info; regs->regs[ 5] = (unsigned long) &frame->rs_info;
regs->regs[ 6] = (unsigned long) &frame->rs_uc; regs->regs[ 6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) frame->rs_code; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@ -709,7 +678,11 @@ give_sigsegv:
*/ */
struct mips_abi mips_abi_32 = { struct mips_abi mips_abi_32 = {
.setup_frame = setup_frame_32, .setup_frame = setup_frame_32,
.signal_return_offset =
offsetof(struct mips_vdso, o32_signal_trampoline),
.setup_rt_frame = setup_rt_frame_32, .setup_rt_frame = setup_rt_frame_32,
.rt_signal_return_offset =
offsetof(struct mips_vdso, o32_rt_signal_trampoline),
.restart = __NR_O32_restart_syscall .restart = __NR_O32_restart_syscall
}; };

View File

@ -39,13 +39,13 @@
#include <asm/fpu.h> #include <asm/fpu.h>
#include <asm/cpu-features.h> #include <asm/cpu-features.h>
#include <asm/war.h> #include <asm/war.h>
#include <asm/vdso.h>
#include "signal-common.h" #include "signal-common.h"
/* /*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ... * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
*/ */
#define __NR_N32_rt_sigreturn 6211
#define __NR_N32_restart_syscall 6214 #define __NR_N32_restart_syscall 6214
extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *); extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
@ -67,27 +67,13 @@ struct ucontextn32 {
compat_sigset_t uc_sigmask; /* mask last for extensibility */ compat_sigset_t uc_sigmask; /* mask last for extensibility */
}; };
#if ICACHE_REFILLS_WORKAROUND_WAR == 0
struct rt_sigframe_n32 { struct rt_sigframe_n32 {
u32 rs_ass[4]; /* argument save space for o32 */ u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_code[2]; /* signal trampoline */ u32 rs_pad[2]; /* Was: signal trampoline */
struct compat_siginfo rs_info; struct compat_siginfo rs_info;
struct ucontextn32 rs_uc; struct ucontextn32 rs_uc;
}; };
#else /* ICACHE_REFILLS_WORKAROUND_WAR */
struct rt_sigframe_n32 {
u32 rs_ass[4]; /* argument save space for o32 */
u32 rs_pad[2];
struct compat_siginfo rs_info;
struct ucontextn32 rs_uc;
u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
};
#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
@ -173,7 +159,7 @@ badframe:
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
} }
static int setup_rt_frame_n32(struct k_sigaction * ka, static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
{ {
struct rt_sigframe_n32 __user *frame; struct rt_sigframe_n32 __user *frame;
@ -184,8 +170,6 @@ static int setup_rt_frame_n32(struct k_sigaction * ka,
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; goto give_sigsegv;
install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
/* Create siginfo. */ /* Create siginfo. */
err |= copy_siginfo_to_user32(&frame->rs_info, info); err |= copy_siginfo_to_user32(&frame->rs_info, info);
@ -219,7 +203,7 @@ static int setup_rt_frame_n32(struct k_sigaction * ka,
regs->regs[ 5] = (unsigned long) &frame->rs_info; regs->regs[ 5] = (unsigned long) &frame->rs_info;
regs->regs[ 6] = (unsigned long) &frame->rs_uc; regs->regs[ 6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) frame->rs_code; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@ -235,5 +219,7 @@ give_sigsegv:
struct mips_abi mips_abi_n32 = { struct mips_abi mips_abi_n32 = {
.setup_rt_frame = setup_rt_frame_n32, .setup_rt_frame = setup_rt_frame_n32,
.rt_signal_return_offset =
offsetof(struct mips_vdso, n32_rt_signal_trampoline),
.restart = __NR_N32_restart_syscall .restart = __NR_N32_restart_syscall
}; };

View File

@ -182,7 +182,7 @@ static int vpemask[2][8] = {
{0, 0, 0, 0, 0, 0, 0, 1} {0, 0, 0, 0, 0, 0, 0, 1}
}; };
int tcnoprog[NR_CPUS]; int tcnoprog[NR_CPUS];
static atomic_t idle_hook_initialized = {0}; static atomic_t idle_hook_initialized = ATOMIC_INIT(0);
static int clock_hang_reported[NR_CPUS]; static int clock_hang_reported[NR_CPUS];
#endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */ #endif /* CONFIG_SMTC_IDLE_HOOK_DEBUG */

View File

@ -79,7 +79,11 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
int do_color_align; int do_color_align;
unsigned long task_size; unsigned long task_size;
task_size = STACK_TOP; #ifdef CONFIG_32BIT
task_size = TASK_SIZE;
#else /* Must be CONFIG_64BIT*/
task_size = test_thread_flag(TIF_32BIT_ADDR) ? TASK_SIZE32 : TASK_SIZE;
#endif
if (len > task_size) if (len > task_size)
return -ENOMEM; return -ENOMEM;

View File

@ -1599,7 +1599,7 @@ void __init trap_init(void)
ebase = (unsigned long) ebase = (unsigned long)
__alloc_bootmem(size, 1 << fls(size), 0); __alloc_bootmem(size, 1 << fls(size), 0);
} else { } else {
ebase = CAC_BASE; ebase = CKSEG0;
if (cpu_has_mips_r2) if (cpu_has_mips_r2)
ebase += (read_c0_ebase() & 0x3ffff000); ebase += (read_c0_ebase() & 0x3ffff000);
} }

112
arch/mips/kernel/vdso.c Normal file
View File

@ -0,0 +1,112 @@
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2009, 2010 Cavium Networks, Inc.
*/
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/binfmts.h>
#include <linux/elf.h>
#include <linux/vmalloc.h>
#include <linux/unistd.h>
#include <asm/vdso.h>
#include <asm/uasm.h>
/*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
*/
#define __NR_O32_sigreturn 4119
#define __NR_O32_rt_sigreturn 4193
#define __NR_N32_rt_sigreturn 6211
static struct page *vdso_page;
static void __init install_trampoline(u32 *tramp, unsigned int sigreturn)
{
uasm_i_addiu(&tramp, 2, 0, sigreturn); /* li v0, sigreturn */
uasm_i_syscall(&tramp, 0);
}
static int __init init_vdso(void)
{
struct mips_vdso *vdso;
vdso_page = alloc_page(GFP_KERNEL);
if (!vdso_page)
panic("Cannot allocate vdso");
vdso = vmap(&vdso_page, 1, 0, PAGE_KERNEL);
if (!vdso)
panic("Cannot map vdso");
clear_page(vdso);
install_trampoline(vdso->rt_signal_trampoline, __NR_rt_sigreturn);
#ifdef CONFIG_32BIT
install_trampoline(vdso->signal_trampoline, __NR_sigreturn);
#else
install_trampoline(vdso->n32_rt_signal_trampoline,
__NR_N32_rt_sigreturn);
install_trampoline(vdso->o32_signal_trampoline, __NR_O32_sigreturn);
install_trampoline(vdso->o32_rt_signal_trampoline,
__NR_O32_rt_sigreturn);
#endif
vunmap(vdso);
pr_notice("init_vdso successfull\n");
return 0;
}
device_initcall(init_vdso);
static unsigned long vdso_addr(unsigned long start)
{
return STACK_TOP;
}
int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
{
int ret;
unsigned long addr;
struct mm_struct *mm = current->mm;
down_write(&mm->mmap_sem);
addr = vdso_addr(mm->start_stack);
addr = get_unmapped_area(NULL, addr, PAGE_SIZE, 0, 0);
if (IS_ERR_VALUE(addr)) {
ret = addr;
goto up_fail;
}
ret = install_special_mapping(mm, addr, PAGE_SIZE,
VM_READ|VM_EXEC|
VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC|
VM_ALWAYSDUMP,
&vdso_page);
if (ret)
goto up_fail;
mm->context.vdso = (void *)addr;
up_fail:
up_write(&mm->mmap_sem);
return ret;
}
const char *arch_vma_name(struct vm_area_struct *vma)
{
if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso)
return "[vdso]";
return NULL;
}

View File

@ -41,7 +41,7 @@ EXPORT_SYMBOL(__delay);
void __udelay(unsigned long us) void __udelay(unsigned long us)
{ {
unsigned int lpj = current_cpu_data.udelay_val; unsigned int lpj = raw_current_cpu_data.udelay_val;
__delay((us * 0x000010c7ull * HZ * lpj) >> 32); __delay((us * 0x000010c7ull * HZ * lpj) >> 32);
} }
@ -49,7 +49,7 @@ EXPORT_SYMBOL(__udelay);
void __ndelay(unsigned long ns) void __ndelay(unsigned long ns)
{ {
unsigned int lpj = current_cpu_data.udelay_val; unsigned int lpj = raw_current_cpu_data.udelay_val;
__delay((ns * 0x00000005ull * HZ * lpj) >> 32); __delay((ns * 0x00000005ull * HZ * lpj) >> 32);
} }

View File

@ -17,8 +17,7 @@ struct DWstruct {
#error I feel sick. #error I feel sick.
#endif #endif
typedef union typedef union {
{
struct DWstruct s; struct DWstruct s;
long long ll; long long ll;
} DWunion; } DWunion;

View File

@ -133,7 +133,7 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
} }
unsigned long _page_cachable_default; unsigned long _page_cachable_default;
EXPORT_SYMBOL_GPL(_page_cachable_default); EXPORT_SYMBOL(_page_cachable_default);
static inline void setup_protection_map(void) static inline void setup_protection_map(void)
{ {

View File

@ -788,10 +788,15 @@ static void __cpuinit build_r4000_tlb_refill_handler(void)
* create the plain linear handler * create the plain linear handler
*/ */
if (bcm1250_m3_war()) { if (bcm1250_m3_war()) {
UASM_i_MFC0(&p, K0, C0_BADVADDR); unsigned int segbits = 44;
UASM_i_MFC0(&p, K1, C0_ENTRYHI);
uasm_i_dmfc0(&p, K0, C0_BADVADDR);
uasm_i_dmfc0(&p, K1, C0_ENTRYHI);
uasm_i_xor(&p, K0, K0, K1); uasm_i_xor(&p, K0, K0, K1);
UASM_i_SRL(&p, K0, K0, PAGE_SHIFT + 1); uasm_i_dsrl32(&p, K1, K0, 62 - 32);
uasm_i_dsrl(&p, K0, K0, 12 + 1);
uasm_i_dsll32(&p, K0, K0, 64 + 12 + 1 - segbits - 32);
uasm_i_or(&p, K0, K0, K1);
uasm_il_bnez(&p, &r, K0, label_leave); uasm_il_bnez(&p, &r, K0, label_leave);
/* No need for uasm_i_nop */ /* No need for uasm_i_nop */
} }
@ -1312,10 +1317,15 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
memset(relocs, 0, sizeof(relocs)); memset(relocs, 0, sizeof(relocs));
if (bcm1250_m3_war()) { if (bcm1250_m3_war()) {
UASM_i_MFC0(&p, K0, C0_BADVADDR); unsigned int segbits = 44;
UASM_i_MFC0(&p, K1, C0_ENTRYHI);
uasm_i_dmfc0(&p, K0, C0_BADVADDR);
uasm_i_dmfc0(&p, K1, C0_ENTRYHI);
uasm_i_xor(&p, K0, K0, K1); uasm_i_xor(&p, K0, K0, K1);
UASM_i_SRL(&p, K0, K0, PAGE_SHIFT + 1); uasm_i_dsrl32(&p, K1, K0, 62 - 32);
uasm_i_dsrl(&p, K0, K0, 12 + 1);
uasm_i_dsll32(&p, K0, K0, 64 + 12 + 1 - segbits - 32);
uasm_i_or(&p, K0, K0, K1);
uasm_il_bnez(&p, &r, K0, label_leave); uasm_il_bnez(&p, &r, K0, label_leave);
/* No need for uasm_i_nop */ /* No need for uasm_i_nop */
} }

View File

@ -31,7 +31,8 @@ enum fields {
BIMM = 0x040, BIMM = 0x040,
JIMM = 0x080, JIMM = 0x080,
FUNC = 0x100, FUNC = 0x100,
SET = 0x200 SET = 0x200,
SCIMM = 0x400
}; };
#define OP_MASK 0x3f #define OP_MASK 0x3f
@ -52,6 +53,8 @@ enum fields {
#define FUNC_SH 0 #define FUNC_SH 0
#define SET_MASK 0x7 #define SET_MASK 0x7
#define SET_SH 0 #define SET_SH 0
#define SCIMM_MASK 0xfffff
#define SCIMM_SH 6
enum opcode { enum opcode {
insn_invalid, insn_invalid,
@ -61,10 +64,10 @@ enum opcode {
insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl, insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
insn_dsrl32, insn_drotr, insn_dsubu, insn_eret, insn_j, insn_jal, insn_dsrl32, insn_drotr, insn_dsubu, insn_eret, insn_j, insn_jal,
insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0, insn_jr, insn_ld, insn_ll, insn_lld, insn_lui, insn_lw, insn_mfc0,
insn_mtc0, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd, insn_mtc0, insn_or, insn_ori, insn_pref, insn_rfe, insn_sc, insn_scd,
insn_sd, insn_sll, insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw, insn_sd, insn_sll, insn_sra, insn_srl, insn_rotr, insn_subu, insn_sw,
insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori, insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori,
insn_dins insn_dins, insn_syscall
}; };
struct insn { struct insn {
@ -117,6 +120,7 @@ static struct insn insn_table[] __cpuinitdata = {
{ insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_lw, M(lw_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_mfc0, M(cop0_op, mfc_op, 0, 0, 0, 0), RT | RD | SET},
{ insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET}, { insn_mtc0, M(cop0_op, mtc_op, 0, 0, 0, 0), RT | RD | SET},
{ insn_or, M(spec_op, 0, 0, 0, 0, or_op), RS | RT | RD },
{ insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_ori, M(ori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
{ insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM }, { insn_pref, M(pref_op, 0, 0, 0, 0, 0), RS | RT | SIMM },
{ insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 }, { insn_rfe, M(cop0_op, cop_op, 0, 0, 0, rfe_op), 0 },
@ -136,6 +140,7 @@ static struct insn insn_table[] __cpuinitdata = {
{ insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD }, { insn_xor, M(spec_op, 0, 0, 0, 0, xor_op), RS | RT | RD },
{ insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM }, { insn_xori, M(xori_op, 0, 0, 0, 0, 0), RS | RT | UIMM },
{ insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE }, { insn_dins, M(spec3_op, 0, 0, 0, 0, dins_op), RS | RT | RD | RE },
{ insn_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
{ insn_invalid, 0, 0 } { insn_invalid, 0, 0 }
}; };
@ -208,6 +213,14 @@ static inline __cpuinit u32 build_jimm(u32 arg)
return (arg >> 2) & JIMM_MASK; return (arg >> 2) & JIMM_MASK;
} }
static inline __cpuinit u32 build_scimm(u32 arg)
{
if (arg & ~SCIMM_MASK)
printk(KERN_WARNING "Micro-assembler field overflow\n");
return (arg & SCIMM_MASK) << SCIMM_SH;
}
static inline __cpuinit u32 build_func(u32 arg) static inline __cpuinit u32 build_func(u32 arg)
{ {
if (arg & ~FUNC_MASK) if (arg & ~FUNC_MASK)
@ -266,6 +279,8 @@ static void __cpuinit build_insn(u32 **buf, enum opcode opc, ...)
op |= build_func(va_arg(ap, u32)); op |= build_func(va_arg(ap, u32));
if (ip->fields & SET) if (ip->fields & SET)
op |= build_set(va_arg(ap, u32)); op |= build_set(va_arg(ap, u32));
if (ip->fields & SCIMM)
op |= build_scimm(va_arg(ap, u32));
va_end(ap); va_end(ap);
**buf = op; **buf = op;
@ -373,6 +388,7 @@ I_u2s3u1(_lw)
I_u1u2u3(_mfc0) I_u1u2u3(_mfc0)
I_u1u2u3(_mtc0) I_u1u2u3(_mtc0)
I_u2u1u3(_ori) I_u2u1u3(_ori)
I_u3u1u2(_or)
I_u2s3u1(_pref) I_u2s3u1(_pref)
I_0(_rfe) I_0(_rfe)
I_u2s3u1(_sc) I_u2s3u1(_sc)
@ -391,6 +407,7 @@ I_0(_tlbwr)
I_u3u1u2(_xor) I_u3u1u2(_xor)
I_u2u1u3(_xori) I_u2u1u3(_xori)
I_u2u1msbu3(_dins); I_u2u1msbu3(_dins);
I_u1(_syscall);
/* Handle labels. */ /* Handle labels. */
void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid) void __cpuinit uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)

View File

@ -180,15 +180,21 @@ struct pci_ops loongson_pci_ops = {
}; };
#ifdef CONFIG_CS5536 #ifdef CONFIG_CS5536
DEFINE_RAW_SPINLOCK(msr_lock);
void _rdmsr(u32 msr, u32 *hi, u32 *lo) void _rdmsr(u32 msr, u32 *hi, u32 *lo)
{ {
struct pci_bus bus = { struct pci_bus bus = {
.number = PCI_BUS_CS5536 .number = PCI_BUS_CS5536
}; };
u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0); u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0);
unsigned long flags;
raw_spin_lock_irqsave(&msr_lock, flags);
loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr); loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr);
loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_LO, 4, lo); loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_LO, 4, lo);
loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_HI, 4, hi); loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
raw_spin_unlock_irqrestore(&msr_lock, flags);
} }
EXPORT_SYMBOL(_rdmsr); EXPORT_SYMBOL(_rdmsr);
@ -198,9 +204,13 @@ void _wrmsr(u32 msr, u32 hi, u32 lo)
.number = PCI_BUS_CS5536 .number = PCI_BUS_CS5536
}; };
u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0); u32 devfn = PCI_DEVFN(PCI_IDSEL_CS5536, 0);
unsigned long flags;
raw_spin_lock_irqsave(&msr_lock, flags);
loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr); loongson_pcibios_write(&bus, devfn, PCI_MSR_ADDR, 4, msr);
loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_LO, 4, lo); loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_LO, 4, lo);
loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_HI, 4, hi); loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
raw_spin_unlock_irqrestore(&msr_lock, flags);
} }
EXPORT_SYMBOL(_wrmsr); EXPORT_SYMBOL(_wrmsr);
#endif #endif

View File

@ -87,6 +87,21 @@ static int __init setup_bcm1250(void)
return ret; return ret;
} }
int sb1250_m3_workaround_needed(void)
{
switch (soc_type) {
case K_SYS_SOC_TYPE_BCM1250:
case K_SYS_SOC_TYPE_BCM1250_ALT:
case K_SYS_SOC_TYPE_BCM1250_ALT2:
case K_SYS_SOC_TYPE_BCM1125:
case K_SYS_SOC_TYPE_BCM1125H:
return soc_pass < K_SYS_REVISION_BCM1250_C0;
default:
return 0;
}
}
static int __init setup_bcm112x(void) static int __init setup_bcm112x(void)
{ {
int ret = 0; int ret = 0;

View File

@ -37,6 +37,9 @@ config SPARC64
def_bool 64BIT def_bool 64BIT
select ARCH_SUPPORTS_MSI select ARCH_SUPPORTS_MSI
select HAVE_FUNCTION_TRACER select HAVE_FUNCTION_TRACER
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_GRAPH_FP_TEST
select HAVE_FUNCTION_TRACE_MCOUNT_TEST
select HAVE_KRETPROBES select HAVE_KRETPROBES
select HAVE_KPROBES select HAVE_KPROBES
select HAVE_LMB select HAVE_LMB

View File

@ -19,13 +19,10 @@ config DEBUG_DCFLUSH
bool "D-cache flush debugging" bool "D-cache flush debugging"
depends on SPARC64 && DEBUG_KERNEL depends on SPARC64 && DEBUG_KERNEL
config STACK_DEBUG
bool "Stack Overflow Detection Support"
config MCOUNT config MCOUNT
bool bool
depends on SPARC64 depends on SPARC64
depends on STACK_DEBUG || FUNCTION_TRACER depends on FUNCTION_TRACER
default y default y
config FRAME_POINTER config FRAME_POINTER

View File

@ -17,7 +17,7 @@ typedef struct {
unsigned int __nmi_count; unsigned int __nmi_count;
unsigned long clock_tick; /* %tick's per second */ unsigned long clock_tick; /* %tick's per second */
unsigned long __pad; unsigned long __pad;
unsigned int __pad1; unsigned int irq0_irqs;
unsigned int __pad2; unsigned int __pad2;
/* Dcache line 2, rarely used */ /* Dcache line 2, rarely used */

View File

@ -76,9 +76,26 @@ static inline int raw_irqs_disabled(void)
*/ */
static inline unsigned long __raw_local_irq_save(void) static inline unsigned long __raw_local_irq_save(void)
{ {
unsigned long flags = __raw_local_save_flags(); unsigned long flags, tmp;
raw_local_irq_disable(); /* Disable interrupts to PIL_NORMAL_MAX unless we already
* are using PIL_NMI, in which case PIL_NMI is retained.
*
* The only values we ever program into the %pil are 0,
* PIL_NORMAL_MAX and PIL_NMI.
*
* Since PIL_NMI is the largest %pil value and all bits are
* set in it (0xf), it doesn't matter what PIL_NORMAL_MAX
* actually is.
*/
__asm__ __volatile__(
"rdpr %%pil, %0\n\t"
"or %0, %2, %1\n\t"
"wrpr %1, 0x0, %%pil"
: "=r" (flags), "=r" (tmp)
: "i" (PIL_NORMAL_MAX)
: "memory"
);
return flags; return flags;
} }

View File

@ -111,7 +111,7 @@ struct thread_info {
#define THREAD_SHIFT PAGE_SHIFT #define THREAD_SHIFT PAGE_SHIFT
#endif /* PAGE_SHIFT == 13 */ #endif /* PAGE_SHIFT == 13 */
#define PREEMPT_ACTIVE 0x4000000 #define PREEMPT_ACTIVE 0x10000000
/* /*
* macros/functions for gaining access to the thread information structure * macros/functions for gaining access to the thread information structure

View File

@ -13,6 +13,14 @@ extra-y += init_task.o
CPPFLAGS_vmlinux.lds := -Usparc -m$(BITS) CPPFLAGS_vmlinux.lds := -Usparc -m$(BITS)
extra-y += vmlinux.lds extra-y += vmlinux.lds
ifdef CONFIG_FUNCTION_TRACER
# Do not profile debug and lowlevel utilities
CFLAGS_REMOVE_ftrace.o := -pg
CFLAGS_REMOVE_time_$(BITS).o := -pg
CFLAGS_REMOVE_perf_event.o := -pg
CFLAGS_REMOVE_pcr.o := -pg
endif
obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o
obj-$(CONFIG_SPARC32) += etrap_32.o obj-$(CONFIG_SPARC32) += etrap_32.o
obj-$(CONFIG_SPARC32) += rtrap_32.o obj-$(CONFIG_SPARC32) += rtrap_32.o
@ -85,7 +93,7 @@ obj-$(CONFIG_KGDB) += kgdb_$(BITS).o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
CFLAGS_REMOVE_ftrace.o := -pg obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_EARLYFB) += btext.o obj-$(CONFIG_EARLYFB) += btext.o
obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_STACKTRACE) += stacktrace.o

View File

@ -13,7 +13,7 @@ static const u32 ftrace_nop = 0x01000000;
static u32 ftrace_call_replace(unsigned long ip, unsigned long addr) static u32 ftrace_call_replace(unsigned long ip, unsigned long addr)
{ {
static u32 call; u32 call;
s32 off; s32 off;
off = ((s32)addr - (s32)ip); off = ((s32)addr - (s32)ip);
@ -91,3 +91,61 @@ int __init ftrace_dyn_arch_init(void *data)
return 0; return 0;
} }
#endif #endif
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
#ifdef CONFIG_DYNAMIC_FTRACE
extern void ftrace_graph_call(void);
int ftrace_enable_ftrace_graph_caller(void)
{
unsigned long ip = (unsigned long)(&ftrace_graph_call);
u32 old, new;
old = *(u32 *) &ftrace_graph_call;
new = ftrace_call_replace(ip, (unsigned long) &ftrace_graph_caller);
return ftrace_modify_code(ip, old, new);
}
int ftrace_disable_ftrace_graph_caller(void)
{
unsigned long ip = (unsigned long)(&ftrace_graph_call);
u32 old, new;
old = *(u32 *) &ftrace_graph_call;
new = ftrace_call_replace(ip, (unsigned long) &ftrace_stub);
return ftrace_modify_code(ip, old, new);
}
#endif /* !CONFIG_DYNAMIC_FTRACE */
/*
* Hook the return address and push it in the stack of return addrs
* in current thread info.
*/
unsigned long prepare_ftrace_return(unsigned long parent,
unsigned long self_addr,
unsigned long frame_pointer)
{
unsigned long return_hooker = (unsigned long) &return_to_handler;
struct ftrace_graph_ent trace;
if (unlikely(atomic_read(&current->tracing_graph_pause)))
return parent + 8UL;
if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
frame_pointer) == -EBUSY)
return parent + 8UL;
trace.func = self_addr;
/* Only trace if the calling function expects to */
if (!ftrace_graph_entry(&trace)) {
current->curr_ret_stack--;
return parent + 8UL;
}
return return_hooker;
}
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */

View File

@ -20,7 +20,9 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/ftrace.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/kmemleak.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/processor.h> #include <asm/processor.h>
@ -45,6 +47,7 @@
#include "entry.h" #include "entry.h"
#include "cpumap.h" #include "cpumap.h"
#include "kstack.h"
#define NUM_IVECS (IMAP_INR + 1) #define NUM_IVECS (IMAP_INR + 1)
@ -647,6 +650,14 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
if (unlikely(!bucket)) if (unlikely(!bucket))
return 0; return 0;
/* The only reference we store to the IRQ bucket is
* by physical address which kmemleak can't see, tell
* it that this object explicitly is not a leak and
* should be scanned.
*/
kmemleak_not_leak(bucket);
__flush_dcache_range((unsigned long) bucket, __flush_dcache_range((unsigned long) bucket,
((unsigned long) bucket + ((unsigned long) bucket +
sizeof(struct ino_bucket))); sizeof(struct ino_bucket)));
@ -703,25 +714,7 @@ void ack_bad_irq(unsigned int virt_irq)
void *hardirq_stack[NR_CPUS]; void *hardirq_stack[NR_CPUS];
void *softirq_stack[NR_CPUS]; void *softirq_stack[NR_CPUS];
static __attribute__((always_inline)) void *set_hardirq_stack(void) void __irq_entry handler_irq(int irq, struct pt_regs *regs)
{
void *orig_sp, *sp = hardirq_stack[smp_processor_id()];
__asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp));
if (orig_sp < sp ||
orig_sp > (sp + THREAD_SIZE)) {
sp += THREAD_SIZE - 192 - STACK_BIAS;
__asm__ __volatile__("mov %0, %%sp" : : "r" (sp));
}
return orig_sp;
}
static __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp)
{
__asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp));
}
void handler_irq(int irq, struct pt_regs *regs)
{ {
unsigned long pstate, bucket_pa; unsigned long pstate, bucket_pa;
struct pt_regs *old_regs; struct pt_regs *old_regs;

View File

@ -5,6 +5,7 @@
#include <linux/kgdb.h> #include <linux/kgdb.h>
#include <linux/kdebug.h> #include <linux/kdebug.h>
#include <linux/ftrace.h>
#include <asm/kdebug.h> #include <asm/kdebug.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
@ -108,7 +109,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
void smp_kgdb_capture_client(int irq, struct pt_regs *regs) void __irq_entry smp_kgdb_capture_client(int irq, struct pt_regs *regs)
{ {
unsigned long flags; unsigned long flags;

View File

@ -61,4 +61,23 @@ check_magic:
} }
static inline __attribute__((always_inline)) void *set_hardirq_stack(void)
{
void *orig_sp, *sp = hardirq_stack[smp_processor_id()];
__asm__ __volatile__("mov %%sp, %0" : "=r" (orig_sp));
if (orig_sp < sp ||
orig_sp > (sp + THREAD_SIZE)) {
sp += THREAD_SIZE - 192 - STACK_BIAS;
__asm__ __volatile__("mov %0, %%sp" : : "r" (sp));
}
return orig_sp;
}
static inline __attribute__((always_inline)) void restore_hardirq_stack(void *orig_sp)
{
__asm__ __volatile__("mov %0, %%sp" : : "r" (orig_sp));
}
#endif /* _KSTACK_H */ #endif /* _KSTACK_H */

View File

@ -23,6 +23,8 @@
#include <asm/ptrace.h> #include <asm/ptrace.h>
#include <asm/pcr.h> #include <asm/pcr.h>
#include "kstack.h"
/* We don't have a real NMI on sparc64, but we can fake one /* We don't have a real NMI on sparc64, but we can fake one
* up using profiling counter overflow interrupts and interrupt * up using profiling counter overflow interrupts and interrupt
* levels. * levels.
@ -92,7 +94,7 @@ static void die_nmi(const char *str, struct pt_regs *regs, int do_panic)
notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs) notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
{ {
unsigned int sum, touched = 0; unsigned int sum, touched = 0;
int cpu = smp_processor_id(); void *orig_sp;
clear_softint(1 << irq); clear_softint(1 << irq);
@ -100,13 +102,15 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
nmi_enter(); nmi_enter();
orig_sp = set_hardirq_stack();
if (notify_die(DIE_NMI, "nmi", regs, 0, if (notify_die(DIE_NMI, "nmi", regs, 0,
pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP) pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
touched = 1; touched = 1;
else else
pcr_ops->write(PCR_PIC_PRIV); pcr_ops->write(PCR_PIC_PRIV);
sum = kstat_irqs_cpu(0, cpu); sum = local_cpu_data().irq0_irqs;
if (__get_cpu_var(nmi_touch)) { if (__get_cpu_var(nmi_touch)) {
__get_cpu_var(nmi_touch) = 0; __get_cpu_var(nmi_touch) = 0;
touched = 1; touched = 1;
@ -125,6 +129,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
pcr_ops->write(pcr_enable); pcr_ops->write(pcr_enable);
} }
restore_hardirq_stack(orig_sp);
nmi_exit(); nmi_exit();
} }

View File

@ -371,14 +371,19 @@ static void pci_register_iommu_region(struct pci_pbm_info *pbm)
struct resource *rp = kzalloc(sizeof(*rp), GFP_KERNEL); struct resource *rp = kzalloc(sizeof(*rp), GFP_KERNEL);
if (!rp) { if (!rp) {
prom_printf("Cannot allocate IOMMU resource.\n"); pr_info("%s: Cannot allocate IOMMU resource.\n",
prom_halt(); pbm->name);
return;
} }
rp->name = "IOMMU"; rp->name = "IOMMU";
rp->start = pbm->mem_space.start + (unsigned long) vdma[0]; rp->start = pbm->mem_space.start + (unsigned long) vdma[0];
rp->end = rp->start + (unsigned long) vdma[1] - 1UL; rp->end = rp->start + (unsigned long) vdma[1] - 1UL;
rp->flags = IORESOURCE_BUSY; rp->flags = IORESOURCE_BUSY;
request_resource(&pbm->mem_space, rp); if (request_resource(&pbm->mem_space, rp)) {
pr_info("%s: Unable to request IOMMU resource.\n",
pbm->name);
kfree(rp);
}
} }
} }

View File

@ -8,6 +8,7 @@
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/ftrace.h>
#include <asm/pil.h> #include <asm/pil.h>
#include <asm/pcr.h> #include <asm/pcr.h>
@ -34,7 +35,7 @@ unsigned int picl_shift;
* Therefore in such situations we defer the work by signalling * Therefore in such situations we defer the work by signalling
* a lower level cpu IRQ. * a lower level cpu IRQ.
*/ */
void deferred_pcr_work_irq(int irq, struct pt_regs *regs) void __irq_entry deferred_pcr_work_irq(int irq, struct pt_regs *regs)
{ {
struct pt_regs *old_regs; struct pt_regs *old_regs;

View File

@ -130,7 +130,17 @@ rtrap_xcall:
nop nop
call trace_hardirqs_on call trace_hardirqs_on
nop nop
wrpr %l4, %pil /* Do not actually set the %pil here. We will do that
* below after we clear PSTATE_IE in the %pstate register.
* If we re-enable interrupts here, we can recurse down
* the hardirq stack potentially endlessly, causing a
* stack overflow.
*
* It is tempting to put this test and trace_hardirqs_on
* call at the 'rt_continue' label, but that will not work
* as that path hits unconditionally and we do not want to
* execute this in NMI return paths, for example.
*/
#endif #endif
rtrap_no_irq_enable: rtrap_no_irq_enable:
andcc %l1, TSTATE_PRIV, %l3 andcc %l1, TSTATE_PRIV, %l3

View File

@ -22,6 +22,7 @@
#include <linux/profile.h> #include <linux/profile.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/ftrace.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <linux/slab.h> #include <linux/slab.h>
@ -823,13 +824,13 @@ void arch_send_call_function_single_ipi(int cpu)
&cpumask_of_cpu(cpu)); &cpumask_of_cpu(cpu));
} }
void smp_call_function_client(int irq, struct pt_regs *regs) void __irq_entry smp_call_function_client(int irq, struct pt_regs *regs)
{ {
clear_softint(1 << irq); clear_softint(1 << irq);
generic_smp_call_function_interrupt(); generic_smp_call_function_interrupt();
} }
void smp_call_function_single_client(int irq, struct pt_regs *regs) void __irq_entry smp_call_function_single_client(int irq, struct pt_regs *regs)
{ {
clear_softint(1 << irq); clear_softint(1 << irq);
generic_smp_call_function_single_interrupt(); generic_smp_call_function_single_interrupt();
@ -965,7 +966,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
put_cpu(); put_cpu();
} }
void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs) void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
{ {
struct mm_struct *mm; struct mm_struct *mm;
unsigned long flags; unsigned long flags;
@ -1149,7 +1150,7 @@ void smp_release(void)
*/ */
extern void prom_world(int); extern void prom_world(int);
void smp_penguin_jailcell(int irq, struct pt_regs *regs) void __irq_entry smp_penguin_jailcell(int irq, struct pt_regs *regs)
{ {
clear_softint(1 << irq); clear_softint(1 << irq);
@ -1365,7 +1366,7 @@ void smp_send_reschedule(int cpu)
&cpumask_of_cpu(cpu)); &cpumask_of_cpu(cpu));
} }
void smp_receive_signal_client(int irq, struct pt_regs *regs) void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs)
{ {
clear_softint(1 << irq); clear_softint(1 << irq);
} }

View File

@ -35,6 +35,7 @@
#include <linux/clocksource.h> #include <linux/clocksource.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/ftrace.h>
#include <asm/oplib.h> #include <asm/oplib.h>
#include <asm/timer.h> #include <asm/timer.h>
@ -717,7 +718,7 @@ static struct clock_event_device sparc64_clockevent = {
}; };
static DEFINE_PER_CPU(struct clock_event_device, sparc64_events); static DEFINE_PER_CPU(struct clock_event_device, sparc64_events);
void timer_interrupt(int irq, struct pt_regs *regs) void __irq_entry timer_interrupt(int irq, struct pt_regs *regs)
{ {
struct pt_regs *old_regs = set_irq_regs(regs); struct pt_regs *old_regs = set_irq_regs(regs);
unsigned long tick_mask = tick_ops->softint_mask; unsigned long tick_mask = tick_ops->softint_mask;
@ -728,6 +729,7 @@ void timer_interrupt(int irq, struct pt_regs *regs)
irq_enter(); irq_enter();
local_cpu_data().irq0_irqs++;
kstat_incr_irqs_this_cpu(0, irq_to_desc(0)); kstat_incr_irqs_this_cpu(0, irq_to_desc(0));
if (unlikely(!evt->event_handler)) { if (unlikely(!evt->event_handler)) {

View File

@ -2203,27 +2203,6 @@ void dump_stack(void)
EXPORT_SYMBOL(dump_stack); EXPORT_SYMBOL(dump_stack);
static inline int is_kernel_stack(struct task_struct *task,
struct reg_window *rw)
{
unsigned long rw_addr = (unsigned long) rw;
unsigned long thread_base, thread_end;
if (rw_addr < PAGE_OFFSET) {
if (task != &init_task)
return 0;
}
thread_base = (unsigned long) task_stack_page(task);
thread_end = thread_base + sizeof(union thread_union);
if (rw_addr >= thread_base &&
rw_addr < thread_end &&
!(rw_addr & 0x7UL))
return 1;
return 0;
}
static inline struct reg_window *kernel_stack_up(struct reg_window *rw) static inline struct reg_window *kernel_stack_up(struct reg_window *rw)
{ {
unsigned long fp = rw->ins[6]; unsigned long fp = rw->ins[6];
@ -2252,6 +2231,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
show_regs(regs); show_regs(regs);
add_taint(TAINT_DIE); add_taint(TAINT_DIE);
if (regs->tstate & TSTATE_PRIV) { if (regs->tstate & TSTATE_PRIV) {
struct thread_info *tp = current_thread_info();
struct reg_window *rw = (struct reg_window *) struct reg_window *rw = (struct reg_window *)
(regs->u_regs[UREG_FP] + STACK_BIAS); (regs->u_regs[UREG_FP] + STACK_BIAS);
@ -2259,8 +2239,8 @@ void die_if_kernel(char *str, struct pt_regs *regs)
* find some badly aligned kernel stack. * find some badly aligned kernel stack.
*/ */
while (rw && while (rw &&
count++ < 30&& count++ < 30 &&
is_kernel_stack(current, rw)) { kstack_valid(tp, (unsigned long) rw)) {
printk("Caller[%016lx]: %pS\n", rw->ins[7], printk("Caller[%016lx]: %pS\n", rw->ins[7],
(void *) rw->ins[7]); (void *) rw->ins[7]);

Some files were not shown because too many files have changed in this diff Show More