Merge branch 'master' of /repos/git/net-next-2.6

Conflicts:
	net/bridge/br_device.c
	net/bridge/br_forward.c

Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Patrick McHardy 2010-05-10 18:39:28 +02:00
commit 1e4b105712
744 changed files with 38167 additions and 17720 deletions

View File

@ -34,7 +34,7 @@ NMI handler.
cpu = smp_processor_id();
++nmi_count(cpu);
if (!rcu_dereference(nmi_callback)(regs, cpu))
if (!rcu_dereference_sched(nmi_callback)(regs, cpu))
default_do_nmi(regs);
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,
preemption is restored.
Strictly speaking, rcu_dereference() is not needed, since this code runs
only on i386, which does not need rcu_dereference() anyway. However,
it is a good documentation aid, particularly for anyone attempting to
do something similar on Alpha.
In theory, rcu_dereference_sched() is not needed, since this code runs
only on i386, which in theory does not need rcu_dereference_sched()
anyway. However, in practice it is a good documentation aid, particularly
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?
@ -99,17 +100,21 @@ invoke irq_enter() and irq_exit() on NMI entry and exit, respectively.
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?
Answer: The caller to set_nmi_callback() might well have
initialized some data that is to be used by the
new NMI handler. In this case, the rcu_dereference()
would be needed, because otherwise a CPU that received
an NMI just after the new handler was set might see
the pointer to the new NMI handler, but the old
pre-initialized version of the handler's data.
initialized some data that is to be used by the new NMI
handler. In this case, the rcu_dereference_sched() would
be needed, because otherwise a CPU that received an NMI
just after the new handler was set might see the pointer
to the new NMI handler, but the old pre-initialized
version of the handler's data.
More important, the rcu_dereference() makes it clear
to someone reading the code that the pointer is being
protected by RCU.
This same sad story can happen on other CPUs when using
a compiler with aggressive pointer-value speculation
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
primitives when the update-side lock is held is that doing so
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,
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
realtime latency.
Note that, rcu_assign_pointer() and rcu_dereference() relate to
SRCU just as they do to other forms of RCU.
Note that, rcu_assign_pointer() relates to SRCU just as they do
to other forms of RCU.
15. The whole point of call_rcu(), synchronize_rcu(), and friends
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):
Check for SRCU read-side critical section.
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)
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
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
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
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()
and RCU list-/tree-traversal primitives, which do not (yet) check for

View File

@ -840,6 +840,12 @@ SRCU: Initialization/cleanup
init_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
from them) for more information.

View File

@ -68,6 +68,22 @@ like:
SYN_MT_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
---------------
@ -217,11 +233,6 @@ where examples can be found.
difference between the contact position and the approaching tool position
could be used to derive tilt.
[2] The list can of course be extended.
[3] The multi-touch X driver is currently in the prototyping stage. At the
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.
[3] Multitouch X driver project: http://bitmath.org/code/multitouch/.
[4] See the section on event computation.
[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]
Pass parameters to the AMD IOMMU driver in the system.
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
they are unmapped. Otherwise they are
flushed before they will be reused, which

View File

@ -20,23 +20,23 @@ the rest of the skbuff, if any more information does exist.
Packet Layer to Device Driver
-----------------------------
First Byte = 0x00
First Byte = 0x00 (X25_IFACE_DATA)
This indicates that the rest of the skbuff contains data to be transmitted
over the LAPB link. The LAPB link should already exist before any data is
passed down.
First Byte = 0x01
First Byte = 0x01 (X25_IFACE_CONNECT)
Establish the LAPB link. If the link is already established then the connect
confirmation message should be returned as soon as possible.
First Byte = 0x02
First Byte = 0x02 (X25_IFACE_DISCONNECT)
Terminate the LAPB link. If it is already disconnected then the disconnect
confirmation message should be returned as soon as possible.
First Byte = 0x03
First Byte = 0x03 (X25_IFACE_PARAMS)
LAPB parameters. To be defined.
@ -44,22 +44,22 @@ LAPB parameters. To be defined.
Device Driver to Packet Layer
-----------------------------
First Byte = 0x00
First Byte = 0x00 (X25_IFACE_DATA)
This indicates that the rest of the skbuff contains data that has been
received over the LAPB link.
First Byte = 0x01
First Byte = 0x01 (X25_IFACE_CONNECT)
LAPB link has been established. The same message is used for both a LAPB
link connect_confirmation and a connect_indication.
First Byte = 0x02
First Byte = 0x02 (X25_IFACE_DISCONNECT)
LAPB link has been terminated. This same message is used for both a LAPB
link disconnect_confirmation and a disconnect_indication.
First Byte = 0x03
First Byte = 0x03 (X25_IFACE_PARAMS)
LAPB parameters. To be defined.

View File

@ -485,8 +485,8 @@ S: Maintained
F: drivers/input/mouse/bcm5974.c
APPLE SMC DRIVER
M: Nicolas Boichat <nicolas@boichat.ch>
L: mactel-linux-devel@lists.sourceforge.net
M: Henrik Rydberg <rydberg@euromail.se>
L: lm-sensors@lm-sensors.org
S: Maintained
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
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
M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@ -3946,6 +3956,7 @@ F: net/rfkill/
F: net/wireless/
F: include/net/ieee80211*
F: include/linux/wireless.h
F: include/linux/iw_handler.h
F: drivers/net/wireless/
NETWORKING DRIVERS

View File

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

View File

@ -172,7 +172,7 @@ not_angel:
adr r0, LC0
ARM( ldmia r0, {r1, r2, r3, r4, r5, r6, r11, ip, sp})
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
@ if delta is zero, we are

View File

@ -11,7 +11,11 @@
#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;
@ -21,11 +25,20 @@ extern void *kmap_high(struct page *page);
extern void *kmap_high_get(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 kunmap(struct page *page);
extern void *kmap_atomic(struct page *page, 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 struct page *kmap_atomic_to_page(const void *ptr);
#endif
#endif

View File

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

View File

@ -59,23 +59,22 @@ struct iwmmxt_sigframe {
#endif /* CONFIG_IWMMXT */
#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_STORAGE_SIZE 152
#else
#define VFP_MAGIC 0x56465002
#define VFP_STORAGE_SIZE 144
#endif
struct vfp_sigframe
{
unsigned long magic;
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 */
/*
@ -91,7 +90,7 @@ struct aux_sigframe {
#ifdef CONFIG_IWMMXT
struct iwmmxt_sigframe iwmmxt;
#endif
#if 0 && defined CONFIG_VFP /* Not yet saved. */
#ifdef CONFIG_VFP
struct vfp_sigframe vfp;
#endif
/* 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
* are ignored by the ptrace system call.
* are ignored by the ptrace system call and the signal handler.
*/
struct user_vfp {
unsigned long long fpregs[32];
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 */

View File

@ -18,6 +18,7 @@
#include <asm/cacheflush.h>
#include <asm/ucontext.h>
#include <asm/unistd.h>
#include <asm/vfp.h>
#include "ptrace.h"
#include "signal.h"
@ -175,6 +176,90 @@ static int restore_iwmmxt_context(struct iwmmxt_sigframe *frame)
#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.
*/
@ -233,8 +318,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
err |= restore_iwmmxt_context(&aux->iwmmxt);
#endif
#ifdef CONFIG_VFP
// if (err == 0)
// err |= vfp_restore_state(&sf->aux.vfp);
if (err == 0)
err |= restore_vfp_context(&aux->vfp);
#endif
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);
#endif
#ifdef CONFIG_VFP
// if (err == 0)
// err |= vfp_save_state(&sf->aux.vfp);
if (err == 0)
err |= preserve_vfp_context(&aux->vfp);
#endif
__put_user_error(0, &aux->end_magic, err);

View File

@ -16,8 +16,8 @@ obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_d
obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_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_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_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_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_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 */
str r3, [r1, #(AT91_CKGR_PLLAR - AT91_PMC)]
wait_pllalock
/* Save PLLB setting and disable it */
ldr r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
str r3, .saved_pllbr
@ -184,8 +182,6 @@ ENTRY(at91_slow_clock)
mov r3, #AT91_PMC_PLLCOUNT
str r3, [r1, #(AT91_CKGR_PLLBR - AT91_PMC)]
wait_pllblock
/* Turn off the main oscillator */
ldr r3, [r1, #(AT91_CKGR_MOR - AT91_PMC)]
bic r3, r3, #AT91_PMC_MOSCEN
@ -205,13 +201,25 @@ ENTRY(at91_slow_clock)
ldr r3, .saved_pllbr
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
2:
/* Restore PLLA setting */
ldr r3, .saved_pllar
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
4:
#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 dirtied /* non-zero if any of the pages were modified */
) {
int rc = 0;
int regionIdx;
int segmentIdx;
DMA_Region_t *region;
DMA_Segment_t *segment;
down(&memMap->lock);
for (regionIdx = 0; regionIdx < memMap->numRegionsUsed; 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
"%s: vmalloc'd pages are not yet supported\n",
__func__);
return -EINVAL;
rc = -EINVAL;
goto out;
}
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
"%s: Unsupported memory type: %d\n",
__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->inUse = 0;
out:
up(&memMap->lock);
return 0;
return rc;
}
EXPORT_SYMBOL(dma_unmap);

View File

@ -25,7 +25,7 @@
#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_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_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);
@ -56,7 +56,7 @@ void ep93xx_gpio_update_int_params(unsigned 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));
}

View File

@ -62,6 +62,15 @@ config MACH_MX31_3DS
Include support for MX31PDK (3DS) platform. This includes specific
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
bool "Support mx31moboard platforms (EPFL Mobots group)"
select ARCH_MX31
@ -95,6 +104,7 @@ config MACH_PCM043
config MACH_ARMADILLO5X0
bool "Support Atmark Armadillo-500 Development Base Board"
select ARCH_MX31
select MXC_ULPI if USB_ULPI
help
Include support for Atmark Armadillo-500 platform. This includes
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(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(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(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_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(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);
@ -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(scc_clk, 0, NULL, 0, NULL, NULL, &ipg_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) \
{ \
@ -572,7 +572,6 @@ static struct clk_lookup lookups[] = {
_REGISTER_CLOCK(NULL, "iim", iim_clk)
_REGISTER_CLOCK(NULL, "mpeg4", mpeg4_clk)
_REGISTER_CLOCK(NULL, "mbx", mbx_clk)
_REGISTER_CLOCK("mxc_rtc", NULL, ckil_clk)
};
int __init mx31_clocks_init(unsigned long fref)

View File

@ -575,11 +575,26 @@ struct platform_device imx_ssi_device1 = {
.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()) {
mxc_nand_resources[0].start = MX31_NFC_BASE_ADDR;
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);
}
if (cpu_is_mx35()) {
@ -597,6 +612,8 @@ static int mx3_devices_init(void)
imx_ssi_resources0[1].end = MX35_INT_SSI1;
imx_ssi_resources1[1].start = 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;

View File

@ -25,4 +25,5 @@ extern struct platform_device mxc_spi_device1;
extern struct platform_device mxc_spi_device2;
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_wdt_device0;

View File

@ -36,6 +36,9 @@
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/i2c.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
#include <linux/delay.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@ -52,6 +55,8 @@
#include <mach/ipu.h>
#include <mach/mx3fb.h>
#include <mach/mxc_nand.h>
#include <mach/mxc_ehci.h>
#include <mach/ulpi.h>
#include "devices.h"
#include "crm_regs.h"
@ -103,8 +108,158 @@ static int armadillo5x0_pins[] = {
/* I2C2 */
MX31_PIN_CSPI2_MOSI__SCL,
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*/
#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)
pr_warning("armadillo5x0_init: failed to get RTC IRQ\n");
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)

View File

@ -23,6 +23,9 @@
#include <linux/gpio.h>
#include <linux/smsc911x.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 <asm/mach-types.h>
@ -31,26 +34,96 @@
#include <asm/memory.h>
#include <asm/mach/map.h>
#include <mach/common.h>
#include <mach/board-mx31pdk.h>
#include <mach/board-mx31_3ds.h>
#include <mach/imx-uart.h>
#include <mach/iomux-mx3.h>
#include <mach/mxc_nand.h>
#include <mach/spi.h>
#include "devices.h"
/*!
* @file mx31pdk.c
* @file mx31_3ds.c
*
* @brief This file contains the board-specific initialization routines.
*
* @ingroup System
*/
static int mx31pdk_pins[] = {
static int mx31_3ds_pins[] = {
/* UART1 */
MX31_PIN_CTS1__CTS1,
MX31_PIN_RTS1__RTS1,
MX31_PIN_TXD1__TXD1,
MX31_PIN_RXD1__RXD1,
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 = {
@ -95,7 +168,7 @@ static struct platform_device smsc911x_device = {
* 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 int_valid;
@ -163,7 +236,7 @@ static struct irq_chip expio_irq_chip = {
.unmask = expio_unmask_irq,
};
static int __init mx31pdk_init_expio(void)
static int __init mx31_3ds_init_expio(void)
{
int i;
int ret;
@ -176,7 +249,7 @@ static int __init mx31pdk_init_expio(void)
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));
/*
@ -201,7 +274,7 @@ static int __init mx31pdk_init_expio(void)
set_irq_flags(i, IRQF_VALID);
}
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;
}
@ -209,7 +282,7 @@ static int __init mx31pdk_init_expio(void)
/*
* 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,
.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.
*/
static void __init mx31pdk_map_io(void)
static void __init mx31_3ds_map_io(void)
{
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)
{
mxc_iomux_setup_multiple_pins(mx31pdk_pins, ARRAY_SIZE(mx31pdk_pins),
"mx31pdk");
mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins),
"mx31_3ds");
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);
}
static void __init mx31pdk_timer_init(void)
static void __init mx31_3ds_timer_init(void)
{
mx31_clocks_init(26000000);
}
static struct sys_timer mx31pdk_timer = {
.init = mx31pdk_timer_init,
static struct sys_timer mx31_3ds_timer = {
.init = mx31_3ds_timer_init,
};
/*
* 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)")
/* Maintainer: Freescale Semiconductor, Inc. */
.phys_io = MX31_AIPS1_BASE_ADDR,
.io_pg_offst = (MX31_AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
.boot_params = MX3x_PHYS_OFFSET + 0x100,
.map_io = mx31pdk_map_io,
.map_io = mx31_3ds_map_io,
.init_irq = mx31_init_irq,
.init_machine = mxc_board_init,
.timer = &mx31pdk_timer,
.timer = &mx31_3ds_timer,
MACHINE_END

View File

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

View File

@ -28,7 +28,6 @@
#include <linux/types.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/leds.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(&mxc_spi_device0, &spi0_pdata);
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 */
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,
NULL, NULL, &ipg_clk, NULL);

View File

@ -14,9 +14,62 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <mach/hardware.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)
{
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),
.length = MX51_DEBUG_SIZE,
.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,
.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),
.length = MX51_AIPS2_SIZE,
.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)
{
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_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_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)
{
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,14 +41,7 @@ static void v6_copy_user_highpage_nonaliasing(struct page *to,
kfrom = kmap_atomic(from, KM_USER0);
kto = kmap_atomic(to, KM_USER1);
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(kfrom, KM_USER0);
}

View File

@ -464,6 +464,11 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
vaddr += offset;
op(vaddr, len, dir);
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 {
vaddr = page_address(page) + offset;

View File

@ -13,6 +13,7 @@
#include <asm/cacheflush.h>
#include <asm/cachetype.h>
#include <asm/highmem.h>
#include <asm/smp_plat.h>
#include <asm/system.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 *addr = page_address(page);
/*
* Writeback any data associated with the kernel mapping of this
* page. This ensures that data in the physical page is mutually
* coherent with the kernels mapping.
*/
#ifdef CONFIG_HIGHMEM
/*
* kmap_atomic() doesn't set the page virtual address, and
* kunmap_atomic() takes care of cache flushing already.
*/
if (addr)
#endif
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
if (!PageHighMem(page)) {
__cpuc_flush_dcache_area(page_address(page), PAGE_SIZE);
} else {
void *addr = kmap_high_get(page);
if (addr) {
__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,

View File

@ -79,7 +79,8 @@ void kunmap_atomic(void *kvaddr, enum km_type type)
unsigned int idx = type + KM_TYPE_NR * smp_processor_id();
if (kvaddr >= (void *)FIXADDR_START) {
__cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
if (cache_is_vivt())
__cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
#ifdef CONFIG_DEBUG_HIGHMEM
BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
set_pte_ext(TOP_PTE(vaddr), __pte(0), 0);
@ -124,3 +125,87 @@ struct page *kmap_atomic_to_page(const void *ptr)
pte = TOP_PTE(vaddr);
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;
kern_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_NONCACHED].prot_sect |= PMD_SECT_S;
#endif
@ -1050,10 +1054,12 @@ void setup_mm_for_reboot(char mode)
pgd_t *pgd;
int i;
if (current->mm && current->mm->pgd)
pgd = current->mm->pgd;
else
pgd = init_mm.pgd;
/*
* We need to access to user-mode page tables here. For kernel threads
* we don't have any user-mode mappings so we use the context that we
* "borrowed".
*/
pgd = current->active_mm->pgd;
base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())

View File

@ -8,8 +8,8 @@
* published by the Free Software Foundation.
*/
#ifndef __ASM_ARCH_MXC_BOARD_MX31PDK_H__
#define __ASM_ARCH_MXC_BOARD_MX31PDK_H__
#ifndef __ASM_ARCH_MXC_BOARD_MX31_3DS_H__
#define __ASM_ARCH_MXC_BOARD_MX31_3DS_H__
/* Definitions for components on the Debug board */
@ -56,4 +56,4 @@
#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
* FB000000 73F00000 1M AIPS 1
* FB200000 83F00000 1M AIPS 2
* FA100000 8FFFC000 16K TZIC (interrupt controller)
* 8FFFC000 16K TZIC (interrupt controller)
* 90000000 256M CSD0 SDRAM/DDR
* A0000000 256M CSD1 SDRAM/DDR
* B0000000 128M CS0 Flash
@ -23,10 +23,16 @@
* C8000000 64M CS3 Flash
* CC000000 32M CS4 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
*/
@ -40,7 +46,6 @@
* NFC
*/
#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
/*
@ -49,9 +54,8 @@
#define MX51_GPU_BASE_ADDR 0x20000000
#define MX51_GPU2D_BASE_ADDR 0xD0000000
#define MX51_TZIC_BASE_ADDR 0x8FFFC000
#define MX51_TZIC_BASE_ADDR_VIRT 0xFA100000
#define MX51_TZIC_SIZE SZ_16K
#define MX51_TZIC_BASE_ADDR_TO1 0x8FFFC000
#define MX51_TZIC_BASE_ADDR 0xE0000000
#define MX51_DEBUG_BASE_ADDR 0x60000000
#define MX51_DEBUG_BASE_ADDR_VIRT 0xFA200000
@ -232,12 +236,10 @@
#define MX51_IO_ADDRESS(x) \
(void __iomem *) \
(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, SPBA0) ? MX51_SPBA0_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, NFC_AXI) ? MX51_NFC_AXI_IO_ADDRESS(x) : \
MX51_IS_MODULE(x, AIPS2) ? MX51_AIPS2_IO_ADDRESS(x) : \
0xDEADBEEF)
/*
@ -246,9 +248,6 @@
#define MX51_IRAM_IO_ADDRESS(x) \
(((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) \
(((x) - MX51_DEBUG_BASE_ADDR) + MX51_DEBUG_BASE_ADDR_VIRT)
@ -261,9 +260,6 @@
#define MX51_AIPS2_IO_ADDRESS(x) \
(((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
/*
@ -443,12 +439,7 @@
#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
extern unsigned int system_rev;
static inline unsigned int mx51_revision(void)
{
return system_rev;
}
extern int mx51_revision(void);
#endif
#endif /* __ASM_ARCH_MXC_MX51_H__ */

View File

@ -66,6 +66,7 @@ static inline void flush(void)
#define MX2X_UART1_BASE_ADDR 0x1000a000
#define MX3X_UART1_BASE_ADDR 0x43F90000
#define MX3X_UART2_BASE_ADDR 0x43F94000
#define MX51_UART1_BASE_ADDR 0x73fbc000
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:
uart_base = MX3X_UART2_BASE_ADDR;
break;
case MACH_TYPE_MX51_BABBAGE:
uart_base = MX51_UART1_BASE_ADDR;
break;
default:
break;
}

View File

@ -428,26 +428,6 @@ static void vfp_pm_init(void)
static inline void vfp_pm_init(void) { }
#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)
{
unsigned int cpu = get_cpu();
@ -490,9 +470,18 @@ void vfp_flush_hwstate(struct thread_info *thread)
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();
}
#endif
#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)
{
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;
}
static inline int atomic_add_negative(int i, atomic_t *v)
{
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;
}

View File

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

View File

@ -60,43 +60,6 @@ void __init board_setup(void)
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)
{
/* 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_EJECT_INT)->status |= IRQ_NOAUTOEN;
if (cpu_wait)
cpu_wait = db1200_wait;
return 0;
}
arch_initcall(db1200_arch_init);

View File

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

View File

@ -18,6 +18,7 @@
#include <asm/addrspace.h>
#include <bcm63xx_board.h>
#include <bcm63xx_cpu.h>
#include <bcm63xx_dev_uart.h>
#include <bcm63xx_regs.h>
#include <bcm63xx_io.h>
#include <bcm63xx_dev_pci.h>
@ -40,6 +41,7 @@ static struct board_info __initdata board_96338gw = {
.name = "96338GW",
.expected_cpu_id = 0x6338,
.has_uart0 = 1,
.has_enet0 = 1,
.enet0 = {
.force_speed_100 = 1,
@ -82,6 +84,7 @@ static struct board_info __initdata board_96338w = {
.name = "96338W",
.expected_cpu_id = 0x6338,
.has_uart0 = 1,
.has_enet0 = 1,
.enet0 = {
.force_speed_100 = 1,
@ -126,6 +129,8 @@ static struct board_info __initdata board_96338w = {
static struct board_info __initdata board_96345gw2 = {
.name = "96345GW2",
.expected_cpu_id = 0x6345,
.has_uart0 = 1,
};
#endif
@ -137,6 +142,7 @@ static struct board_info __initdata board_96348r = {
.name = "96348R",
.expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1,
.has_pci = 1,
@ -180,6 +186,7 @@ static struct board_info __initdata board_96348gw_10 = {
.name = "96348GW-10",
.expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
@ -239,6 +246,7 @@ static struct board_info __initdata board_96348gw_11 = {
.name = "96348GW-11",
.expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
@ -292,6 +300,7 @@ static struct board_info __initdata board_96348gw = {
.name = "96348GW",
.expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
@ -349,9 +358,10 @@ static struct board_info __initdata board_FAST2404 = {
.name = "F@ST2404",
.expected_cpu_id = 0x6348,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
.has_uart0 = 1,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
.enet0 = {
.has_phy = 1,
@ -368,10 +378,30 @@ static struct board_info __initdata board_FAST2404 = {
.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 = {
.name = "DV201AMR",
.expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_pci = 1,
.has_ohci0 = 1,
@ -391,6 +421,7 @@ static struct board_info __initdata board_96348gw_a = {
.name = "96348GW-A",
.expected_cpu_id = 0x6348,
.has_uart0 = 1,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
@ -416,6 +447,7 @@ static struct board_info __initdata board_96358vw = {
.name = "96358VW",
.expected_cpu_id = 0x6358,
.has_uart0 = 1,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
@ -467,6 +499,7 @@ static struct board_info __initdata board_96358vw2 = {
.name = "96358VW2",
.expected_cpu_id = 0x6358,
.has_uart0 = 1,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
@ -514,6 +547,7 @@ static struct board_info __initdata board_AGPFS0 = {
.name = "AGPF-S0",
.expected_cpu_id = 0x6358,
.has_uart0 = 1,
.has_enet0 = 1,
.has_enet1 = 1,
.has_pci = 1,
@ -531,6 +565,27 @@ static struct board_info __initdata board_AGPFS0 = {
.has_ohci0 = 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
/*
@ -552,15 +607,87 @@ static const struct board_info __initdata *bcm963xx_boards[] = {
&board_FAST2404,
&board_DV201AMR,
&board_96348gw_a,
&board_rta1025w_16,
#endif
#ifdef CONFIG_BCM63XX_CPU_6358
&board_96358vw,
&board_96358vw2,
&board_AGPFS0,
&board_DWVS0,
#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
*/
@ -659,6 +786,17 @@ void __init board_prom_init(void)
}
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");
}
/*
* 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[] = {
{
.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 platform_device bcm63xx_gpio_leds = {
@ -792,6 +860,12 @@ int __init board_register_devices(void)
{
u32 val;
if (board.has_uart0)
bcm63xx_uart_register(0);
if (board.has_uart1)
bcm63xx_uart_register(1);
if (board.has_pccard)
bcm63xx_pcmcia_register();
@ -806,17 +880,6 @@ int __init board_register_devices(void)
if (board.has_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) */
if (BCMCPU_IS_6345())
val = 0x1fc00000;

View File

@ -36,6 +36,7 @@ static const unsigned long bcm96338_regs_base[] = {
[RSET_TIMER] = BCM_6338_TIMER_BASE,
[RSET_WDT] = BCM_6338_WDT_BASE,
[RSET_UART0] = BCM_6338_UART0_BASE,
[RSET_UART1] = BCM_6338_UART1_BASE,
[RSET_GPIO] = BCM_6338_GPIO_BASE,
[RSET_SPI] = BCM_6338_SPI_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_WDT] = BCM_6345_WDT_BASE,
[RSET_UART0] = BCM_6345_UART0_BASE,
[RSET_UART1] = BCM_6345_UART1_BASE,
[RSET_GPIO] = BCM_6345_GPIO_BASE,
[RSET_SPI] = BCM_6345_SPI_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_WDT] = BCM_6348_WDT_BASE,
[RSET_UART0] = BCM_6348_UART0_BASE,
[RSET_UART1] = BCM_6348_UART1_BASE,
[RSET_GPIO] = BCM_6348_GPIO_BASE,
[RSET_SPI] = BCM_6348_SPI_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_WDT] = BCM_6358_WDT_BASE,
[RSET_UART0] = BCM_6358_UART0_BASE,
[RSET_UART1] = BCM_6358_UART1_BASE,
[RSET_GPIO] = BCM_6358_GPIO_BASE,
[RSET_SPI] = BCM_6358_SPI_BASE,
[RSET_OHCI0] = BCM_6358_OHCI0_BASE,
@ -170,6 +174,7 @@ static const unsigned long bcm96358_regs_base[] = {
static const int bcm96358_irqs[] = {
[IRQ_TIMER] = BCM_6358_TIMER_IRQ,
[IRQ_UART0] = BCM_6358_UART0_IRQ,
[IRQ_UART1] = BCM_6358_UART1_IRQ,
[IRQ_DSL] = BCM_6358_DSL_IRQ,
[IRQ_ENET0] = BCM_6358_ENET0_IRQ,
[IRQ_ENET1] = BCM_6358_ENET1_IRQ,

View File

@ -11,31 +11,65 @@
#include <linux/platform_device.h>
#include <bcm63xx_cpu.h>
static struct resource uart_resources[] = {
static struct resource uart0_resources[] = {
{
.start = -1, /* filled at runtime */
.end = -1, /* filled at runtime */
/* start & end filled at runtime */
.flags = IORESOURCE_MEM,
},
{
.start = -1, /* filled at runtime */
/* start filled at runtime */
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device bcm63xx_uart_device = {
.name = "bcm63xx_uart",
.id = 0,
.num_resources = ARRAY_SIZE(uart_resources),
.resource = uart_resources,
static struct resource uart1_resources[] = {
{
/* start & end filled at runtime */
.flags = IORESOURCE_MEM,
},
{
/* 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);
uart_resources[0].end = uart_resources[0].start;
uart_resources[0].end += RSET_UART_SIZE - 1;
uart_resources[1].start = bcm63xx_get_irq_number(IRQ_UART0);
return platform_device_register(&bcm63xx_uart_device);
if (id >= ARRAY_SIZE(bcm63xx_uart_devices))
return -ENODEV;
if (id == 1 && !BCMCPU_IS_6358())
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)
{
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();
pr_info("registering %d GPIOs\n", bcm63xx_gpio_chip.ngpio);
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);
#endif
#ifdef CONFIG_CAVIUM_RESERVE32
extern uint64_t octeon_reserve32_memory;
#endif
static unsigned long long MAX_MEMORY = 512ull << 20;
struct octeon_boot_descriptor *octeon_boot_desc_ptr;
@ -186,54 +183,6 @@ void octeon_check_cpu_bist(void)
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
*
@ -294,18 +243,6 @@ static void octeon_halt(void)
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.
*
@ -502,25 +439,13 @@ void __init prom_init(void)
* memory when it is getting memory from the
* bootloader. Later, after the memory allocations are
* 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
* is in case we later use hugetlb entries with it.
*/
addr = cvmx_bootmem_phy_named_block_alloc(CONFIG_CAVIUM_RESERVE32 << 20,
0, 0, 2 << 20,
"CAVIUM_RESERVE32", 0);
#endif
if (addr < 0)
pr_err("Failed to allocate CAVIUM_RESERVE32 memory area\n");
else
@ -817,9 +742,4 @@ void prom_free_prom_memory(void)
panic("Unable to request_irq(OCTEON_IRQ_RML)\n");
}
#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;
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)
cpu_relax();

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,14 @@
#include <asm/siginfo.h>
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,
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,
sigset_t *set, siginfo_t *info);
const unsigned long rt_signal_return_offset;
const unsigned long restart;
};

View File

@ -310,6 +310,7 @@ do { \
#endif /* CONFIG_64BIT */
struct pt_regs;
struct task_struct;
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)
#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 */

View File

@ -41,7 +41,11 @@ struct mips_fpu_emulator_stats {
DECLARE_PER_CPU(struct mips_fpu_emulator_stats, fpuemustats);
#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
#define MIPS_FPU_EMU_INC_STATS(M) do { } while (0)

View File

@ -85,6 +85,7 @@ enum bcm63xx_regs_set {
RSET_TIMER,
RSET_WDT,
RSET_UART0,
RSET_UART1,
RSET_GPIO,
RSET_SPI,
RSET_UDC0,
@ -123,6 +124,7 @@ enum bcm63xx_regs_set {
#define BCM_6338_TIMER_BASE (0xfffe0200)
#define BCM_6338_WDT_BASE (0xfffe021c)
#define BCM_6338_UART0_BASE (0xfffe0300)
#define BCM_6338_UART1_BASE (0xdeadbeef)
#define BCM_6338_GPIO_BASE (0xfffe0400)
#define BCM_6338_SPI_BASE (0xfffe0c00)
#define BCM_6338_UDC0_BASE (0xdeadbeef)
@ -153,6 +155,7 @@ enum bcm63xx_regs_set {
#define BCM_6345_TIMER_BASE (0xfffe0200)
#define BCM_6345_WDT_BASE (0xfffe021c)
#define BCM_6345_UART0_BASE (0xfffe0300)
#define BCM_6345_UART1_BASE (0xdeadbeef)
#define BCM_6345_GPIO_BASE (0xfffe0400)
#define BCM_6345_SPI_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_WDT_BASE (0xfffe021c)
#define BCM_6348_UART0_BASE (0xfffe0300)
#define BCM_6348_UART1_BASE (0xdeadbeef)
#define BCM_6348_GPIO_BASE (0xfffe0400)
#define BCM_6348_SPI_BASE (0xfffe0c00)
#define BCM_6348_UDC0_BASE (0xfffe1000)
@ -208,6 +212,7 @@ enum bcm63xx_regs_set {
#define BCM_6358_TIMER_BASE (0xfffe0040)
#define BCM_6358_WDT_BASE (0xfffe005c)
#define BCM_6358_UART0_BASE (0xfffe0100)
#define BCM_6358_UART1_BASE (0xfffe0120)
#define BCM_6358_GPIO_BASE (0xfffe0080)
#define BCM_6358_SPI_BASE (0xdeadbeef)
#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;
case RSET_UART0:
return BCM_6338_UART0_BASE;
case RSET_UART1:
return BCM_6338_UART1_BASE;
case RSET_GPIO:
return BCM_6338_GPIO_BASE;
case RSET_SPI:
@ -292,6 +299,8 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
return BCM_6345_WDT_BASE;
case RSET_UART0:
return BCM_6345_UART0_BASE;
case RSET_UART1:
return BCM_6345_UART1_BASE;
case RSET_GPIO:
return BCM_6345_GPIO_BASE;
case RSET_SPI:
@ -338,6 +347,8 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
return BCM_6348_WDT_BASE;
case RSET_UART0:
return BCM_6348_UART0_BASE;
case RSET_UART1:
return BCM_6348_UART1_BASE;
case RSET_GPIO:
return BCM_6348_GPIO_BASE;
case RSET_SPI:
@ -384,6 +395,8 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
return BCM_6358_WDT_BASE;
case RSET_UART0:
return BCM_6358_UART0_BASE;
case RSET_UART1:
return BCM_6358_UART1_BASE;
case RSET_GPIO:
return BCM_6358_GPIO_BASE;
case RSET_SPI:
@ -429,6 +442,7 @@ static inline unsigned long bcm63xx_regset_address(enum bcm63xx_regs_set set)
enum bcm63xx_irq {
IRQ_TIMER = 0,
IRQ_UART0,
IRQ_UART1,
IRQ_DSL,
IRQ_ENET0,
IRQ_ENET1,
@ -510,6 +524,7 @@ enum bcm63xx_irq {
*/
#define BCM_6358_TIMER_IRQ (IRQ_INTERNAL_BASE + 0)
#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_ENET1_IRQ (IRQ_INTERNAL_BASE + 6)
#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()) {
case BCM6358_CPU_ID:
return 40;
case BCM6338_CPU_ID:
return 8;
case BCM6345_CPU_ID:
return 16;
case BCM6348_CPU_ID:
default:
return 37;

View File

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

View File

@ -24,7 +24,7 @@
#define cpu_has_smartmips 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
#endif

View File

@ -16,7 +16,11 @@
#if defined(CONFIG_SB1_PASS_1_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
#else

View File

@ -1,6 +1,9 @@
#ifndef __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 */

View File

@ -104,7 +104,7 @@ extern unsigned long smtc_asid_mask;
#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 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 | \
VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE)
#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET)
#define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE + \
PHYS_OFFSET)
#define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET - \
PHYS_OFFSET)
#include <asm-generic/memory_model.h>
#include <asm-generic/getorder.h>

View File

@ -33,13 +33,19 @@ extern void (*cpu_wait)(void);
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
/*
* User space process size: 2GB. This is hardcoded into a few places,
* so don't change it unless you know what you are doing.
*/
#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
@ -59,7 +65,8 @@ extern unsigned int vced_count, vcei_count;
#define TASK_SIZE32 0x7fff8000UL
#define TASK_SIZE 0x10000000000UL
#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

View File

@ -121,6 +121,25 @@
.endm
#else
.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)
lui k1, %hi(kernelsp)
#else

View File

@ -84,6 +84,7 @@ Ip_u2s3u1(_lw);
Ip_u1u2u3(_mfc0);
Ip_u1u2u3(_mtc0);
Ip_u2u1u3(_ori);
Ip_u3u1u2(_or);
Ip_u2s3u1(_pref);
Ip_0(_rfe);
Ip_u2s3u1(_sc);
@ -102,6 +103,7 @@ Ip_0(_tlbwr);
Ip_u3u1u2(_xor);
Ip_u2u1u3(_xori);
Ip_u2u1msbu3(_dins);
Ip_u1(_syscall);
/* Handle labels. */
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 \
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
CFLAGS_REMOVE_ftrace.o = -pg

View File

@ -164,3 +164,7 @@ void loongson2_cpu_wait(void)
spin_unlock_irqrestore(&loongson2_wait_lock, flags);
}
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();
#endif
if (cpu_wait)
if (cpu_wait) {
/* Don't trace irqs off for idle */
stop_critical_timings();
(*cpu_wait)();
start_critical_timings();
}
}
#ifdef CONFIG_HOTPLUG_CPU
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,
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 */
extern int fpcsr_pending(unsigned int __user *fpcsr);

View File

@ -32,6 +32,7 @@
#include <asm/ucontext.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
#include <asm/vdso.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_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 {
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;
sigset_t sf_mask;
};
struct rt_sigframe {
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 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
*/
@ -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));
}
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.
*/
@ -484,8 +432,8 @@ badframe:
}
#ifdef CONFIG_TRAD_SIGNALS
static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set)
static int setup_frame(void *sig_return, struct k_sigaction *ka,
struct pt_regs *regs, int signr, sigset_t *set)
{
struct sigframe __user *frame;
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)))
goto give_sigsegv;
err |= install_sigtramp(frame->sf_code, __NR_sigreturn);
err |= setup_sigcontext(regs, &frame->sf_sc);
err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
if (err)
@ -515,7 +461,7 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
regs->regs[ 5] = 0;
regs->regs[ 6] = (unsigned long) &frame->sf_sc;
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;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@ -529,8 +475,9 @@ give_sigsegv:
}
#endif
static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set, siginfo_t *info)
static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
struct pt_regs *regs, int signr, sigset_t *set,
siginfo_t *info)
{
struct rt_sigframe __user *frame;
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)))
goto give_sigsegv;
err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
/* Create siginfo. */
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[ 6] = (unsigned long) &frame->rs_uc;
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;
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 = {
#ifdef CONFIG_TRAD_SIGNALS
.setup_frame = setup_frame,
.signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),
#endif
.setup_rt_frame = setup_rt_frame,
.rt_signal_return_offset =
offsetof(struct mips_vdso, rt_signal_trampoline),
.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)
{
int ret;
struct mips_abi *abi = current->thread.abi;
void *vdso = current->mm->context.vdso;
switch(regs->regs[0]) {
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. */
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
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);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);

View File

@ -32,6 +32,7 @@
#include <asm/system.h>
#include <asm/fpu.h>
#include <asm/war.h>
#include <asm/vdso.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 ...
*/
#define __NR_O32_sigreturn 4119
#define __NR_O32_rt_sigreturn 4193
#define __NR_O32_restart_syscall 4253
/* 32-bit compatibility types */
@ -77,47 +76,20 @@ struct ucontext32 {
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 {
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;
compat_sigset_t sf_mask;
};
struct rt_sigframe32 {
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;
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
*/
@ -598,8 +570,8 @@ badframe:
force_sig(SIGSEGV, current);
}
static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set)
static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
struct pt_regs *regs, int signr, sigset_t *set)
{
struct sigframe32 __user *frame;
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)))
goto give_sigsegv;
err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
err |= setup_sigcontext32(regs, &frame->sf_sc);
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[ 6] = (unsigned long) &frame->sf_sc;
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;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@ -644,8 +614,9 @@ give_sigsegv:
return -EFAULT;
}
static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set, siginfo_t *info)
static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
struct pt_regs *regs, int signr, sigset_t *set,
siginfo_t *info)
{
struct rt_sigframe32 __user *frame;
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)))
goto give_sigsegv;
err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
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[ 6] = (unsigned long) &frame->rs_uc;
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;
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 = {
.setup_frame = setup_frame_32,
.signal_return_offset =
offsetof(struct mips_vdso, o32_signal_trampoline),
.setup_rt_frame = setup_rt_frame_32,
.rt_signal_return_offset =
offsetof(struct mips_vdso, o32_rt_signal_trampoline),
.restart = __NR_O32_restart_syscall
};

View File

@ -39,13 +39,13 @@
#include <asm/fpu.h>
#include <asm/cpu-features.h>
#include <asm/war.h>
#include <asm/vdso.h>
#include "signal-common.h"
/*
* Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
*/
#define __NR_N32_rt_sigreturn 6211
#define __NR_N32_restart_syscall 6214
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 */
};
#if ICACHE_REFILLS_WORKAROUND_WAR == 0
struct rt_sigframe_n32 {
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 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);
asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
@ -173,7 +159,7 @@ badframe:
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 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)))
goto give_sigsegv;
install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
/* Create siginfo. */
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[ 6] = (unsigned long) &frame->rs_uc;
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;
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 = {
.setup_rt_frame = setup_rt_frame_n32,
.rt_signal_return_offset =
offsetof(struct mips_vdso, n32_rt_signal_trampoline),
.restart = __NR_N32_restart_syscall
};

View File

@ -182,7 +182,7 @@ static int vpemask[2][8] = {
{0, 0, 0, 0, 0, 0, 0, 1}
};
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];
#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;
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)
return -ENOMEM;

View File

@ -1599,7 +1599,7 @@ void __init trap_init(void)
ebase = (unsigned long)
__alloc_bootmem(size, 1 << fls(size), 0);
} else {
ebase = CAC_BASE;
ebase = CKSEG0;
if (cpu_has_mips_r2)
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)
{
unsigned int lpj = current_cpu_data.udelay_val;
unsigned int lpj = raw_current_cpu_data.udelay_val;
__delay((us * 0x000010c7ull * HZ * lpj) >> 32);
}
@ -49,7 +49,7 @@ EXPORT_SYMBOL(__udelay);
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);
}

View File

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

View File

@ -133,7 +133,7 @@ void __update_cache(struct vm_area_struct *vma, unsigned long address,
}
unsigned long _page_cachable_default;
EXPORT_SYMBOL_GPL(_page_cachable_default);
EXPORT_SYMBOL(_page_cachable_default);
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
*/
if (bcm1250_m3_war()) {
UASM_i_MFC0(&p, K0, C0_BADVADDR);
UASM_i_MFC0(&p, K1, C0_ENTRYHI);
unsigned int segbits = 44;
uasm_i_dmfc0(&p, K0, C0_BADVADDR);
uasm_i_dmfc0(&p, K1, C0_ENTRYHI);
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);
/* No need for uasm_i_nop */
}
@ -1312,10 +1317,15 @@ static void __cpuinit build_r4000_tlb_load_handler(void)
memset(relocs, 0, sizeof(relocs));
if (bcm1250_m3_war()) {
UASM_i_MFC0(&p, K0, C0_BADVADDR);
UASM_i_MFC0(&p, K1, C0_ENTRYHI);
unsigned int segbits = 44;
uasm_i_dmfc0(&p, K0, C0_BADVADDR);
uasm_i_dmfc0(&p, K1, C0_ENTRYHI);
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);
/* No need for uasm_i_nop */
}

View File

@ -31,7 +31,8 @@ enum fields {
BIMM = 0x040,
JIMM = 0x080,
FUNC = 0x100,
SET = 0x200
SET = 0x200,
SCIMM = 0x400
};
#define OP_MASK 0x3f
@ -52,6 +53,8 @@ enum fields {
#define FUNC_SH 0
#define SET_MASK 0x7
#define SET_SH 0
#define SCIMM_MASK 0xfffff
#define SCIMM_SH 6
enum opcode {
insn_invalid,
@ -61,10 +64,10 @@ enum opcode {
insn_dmtc0, insn_dsll, insn_dsll32, insn_dsra, insn_dsrl,
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_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_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_xor, insn_xori,
insn_dins
insn_dins, insn_syscall
};
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_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_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_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 },
@ -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_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_syscall, M(spec_op, 0, 0, 0, 0, syscall_op), SCIMM},
{ insn_invalid, 0, 0 }
};
@ -208,6 +213,14 @@ static inline __cpuinit u32 build_jimm(u32 arg)
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)
{
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));
if (ip->fields & SET)
op |= build_set(va_arg(ap, u32));
if (ip->fields & SCIMM)
op |= build_scimm(va_arg(ap, u32));
va_end(ap);
**buf = op;
@ -373,6 +388,7 @@ I_u2s3u1(_lw)
I_u1u2u3(_mfc0)
I_u1u2u3(_mtc0)
I_u2u1u3(_ori)
I_u3u1u2(_or)
I_u2s3u1(_pref)
I_0(_rfe)
I_u2s3u1(_sc)
@ -391,6 +407,7 @@ I_0(_tlbwr)
I_u3u1u2(_xor)
I_u2u1u3(_xori)
I_u2u1msbu3(_dins);
I_u1(_syscall);
/* Handle labels. */
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
DEFINE_RAW_SPINLOCK(msr_lock);
void _rdmsr(u32 msr, u32 *hi, u32 *lo)
{
struct pci_bus bus = {
.number = PCI_BUS_CS5536
};
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_read(&bus, devfn, PCI_MSR_DATA_LO, 4, lo);
loongson_pcibios_read(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
raw_spin_unlock_irqrestore(&msr_lock, flags);
}
EXPORT_SYMBOL(_rdmsr);
@ -198,9 +204,13 @@ void _wrmsr(u32 msr, u32 hi, u32 lo)
.number = PCI_BUS_CS5536
};
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_DATA_LO, 4, lo);
loongson_pcibios_write(&bus, devfn, PCI_MSR_DATA_HI, 4, hi);
raw_spin_unlock_irqrestore(&msr_lock, flags);
}
EXPORT_SYMBOL(_wrmsr);
#endif

View File

@ -87,6 +87,21 @@ static int __init setup_bcm1250(void)
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)
{
int ret = 0;

View File

@ -83,3 +83,57 @@ static int __init swarm_pata_init(void)
device_initcall(swarm_pata_init);
#endif /* defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR) */
#define sb1250_dev_struct(num) \
static struct resource sb1250_res##num = { \
.name = "SB1250 MAC " __stringify(num), \
.flags = IORESOURCE_MEM, \
.start = A_MAC_CHANNEL_BASE(num), \
.end = A_MAC_CHANNEL_BASE(num + 1) -1, \
};\
static struct platform_device sb1250_dev##num = { \
.name = "sb1250-mac", \
.id = num, \
.resource = &sb1250_res##num, \
.num_resources = 1, \
}
sb1250_dev_struct(0);
sb1250_dev_struct(1);
sb1250_dev_struct(2);
sb1250_dev_struct(3);
static struct platform_device *sb1250_devs[] __initdata = {
&sb1250_dev0,
&sb1250_dev1,
&sb1250_dev2,
&sb1250_dev3,
};
static int __init sb1250_device_init(void)
{
int ret;
/* Set the number of available units based on the SOC type. */
switch (soc_type) {
case K_SYS_SOC_TYPE_BCM1250:
case K_SYS_SOC_TYPE_BCM1250_ALT:
ret = platform_add_devices(sb1250_devs, 3);
break;
case K_SYS_SOC_TYPE_BCM1120:
case K_SYS_SOC_TYPE_BCM1125:
case K_SYS_SOC_TYPE_BCM1125H:
case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */
ret = platform_add_devices(sb1250_devs, 2);
break;
case K_SYS_SOC_TYPE_BCM1x55:
case K_SYS_SOC_TYPE_BCM1x80:
ret = platform_add_devices(sb1250_devs, 4);
break;
default:
ret = -ENODEV;
break;
}
return ret;
}
device_initcall(sb1250_device_init);

View File

@ -37,6 +37,9 @@ config SPARC64
def_bool 64BIT
select ARCH_SUPPORTS_MSI
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_KPROBES
select HAVE_LMB

View File

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

View File

@ -17,7 +17,7 @@ typedef struct {
unsigned int __nmi_count;
unsigned long clock_tick; /* %tick's per second */
unsigned long __pad;
unsigned int __pad1;
unsigned int irq0_irqs;
unsigned int __pad2;
/* 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)
{
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;
}

View File

@ -111,7 +111,7 @@ struct thread_info {
#define THREAD_SHIFT PAGE_SHIFT
#endif /* PAGE_SHIFT == 13 */
#define PREEMPT_ACTIVE 0x4000000
#define PREEMPT_ACTIVE 0x10000000
/*
* 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)
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) += etrap_32.o
obj-$(CONFIG_SPARC32) += rtrap_32.o
@ -85,7 +93,7 @@ obj-$(CONFIG_KGDB) += kgdb_$(BITS).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_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 call;
u32 call;
s32 off;
off = ((s32)addr - (s32)ip);
@ -91,3 +91,61 @@ int __init ftrace_dyn_arch_init(void *data)
return 0;
}
#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/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/ftrace.h>
#include <linux/irq.h>
#include <linux/kmemleak.h>
#include <asm/ptrace.h>
#include <asm/processor.h>
@ -45,6 +47,7 @@
#include "entry.h"
#include "cpumap.h"
#include "kstack.h"
#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);
if (unlikely(!bucket))
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,
((unsigned long) bucket +
sizeof(struct ino_bucket)));
@ -703,25 +714,7 @@ void ack_bad_irq(unsigned int virt_irq)
void *hardirq_stack[NR_CPUS];
void *softirq_stack[NR_CPUS];
static __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 __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)
void __irq_entry handler_irq(int irq, struct pt_regs *regs)
{
unsigned long pstate, bucket_pa;
struct pt_regs *old_regs;

View File

@ -5,6 +5,7 @@
#include <linux/kgdb.h>
#include <linux/kdebug.h>
#include <linux/ftrace.h>
#include <asm/kdebug.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
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;

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 */

View File

@ -23,6 +23,8 @@
#include <asm/ptrace.h>
#include <asm/pcr.h>
#include "kstack.h"
/* We don't have a real NMI on sparc64, but we can fake one
* up using profiling counter overflow interrupts and interrupt
* 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)
{
unsigned int sum, touched = 0;
int cpu = smp_processor_id();
void *orig_sp;
clear_softint(1 << irq);
@ -100,13 +102,15 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
nmi_enter();
orig_sp = set_hardirq_stack();
if (notify_die(DIE_NMI, "nmi", regs, 0,
pt_regs_trap_type(regs), SIGINT) == NOTIFY_STOP)
touched = 1;
else
pcr_ops->write(PCR_PIC_PRIV);
sum = kstat_irqs_cpu(0, cpu);
sum = local_cpu_data().irq0_irqs;
if (__get_cpu_var(nmi_touch)) {
__get_cpu_var(nmi_touch) = 0;
touched = 1;
@ -125,6 +129,8 @@ notrace __kprobes void perfctr_irq(int irq, struct pt_regs *regs)
pcr_ops->write(pcr_enable);
}
restore_hardirq_stack(orig_sp);
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);
if (!rp) {
prom_printf("Cannot allocate IOMMU resource.\n");
prom_halt();
pr_info("%s: Cannot allocate IOMMU resource.\n",
pbm->name);
return;
}
rp->name = "IOMMU";
rp->start = pbm->mem_space.start + (unsigned long) vdma[0];
rp->end = rp->start + (unsigned long) vdma[1] - 1UL;
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/perf_event.h>
#include <linux/ftrace.h>
#include <asm/pil.h>
#include <asm/pcr.h>
@ -34,7 +35,7 @@ unsigned int picl_shift;
* Therefore in such situations we defer the work by signalling
* 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;

View File

@ -130,7 +130,17 @@ rtrap_xcall:
nop
call trace_hardirqs_on
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
rtrap_no_irq_enable:
andcc %l1, TSTATE_PRIV, %l3

View File

@ -22,6 +22,7 @@
#include <linux/profile.h>
#include <linux/bootmem.h>
#include <linux/vmalloc.h>
#include <linux/ftrace.h>
#include <linux/cpu.h>
#include <linux/slab.h>
@ -823,13 +824,13 @@ void arch_send_call_function_single_ipi(int 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);
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);
generic_smp_call_function_single_interrupt();
@ -965,7 +966,7 @@ void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
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;
unsigned long flags;
@ -1149,7 +1150,7 @@ void smp_release(void)
*/
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);
@ -1365,7 +1366,7 @@ void smp_send_reschedule(int 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);
}

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