Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: [MIPS] SB1: Check for -mno-sched-prolog if building corelis debug kernel. [MIPS] Sibyte: Fix race in sb1250_gettimeoffset(). [MIPS] Sibyte: Fix interrupt timer off by one bug. [MIPS] Sibyte: Fix M_SCD_TIMER_INIT and M_SCD_TIMER_CNT wrong field width. [MIPS] Protect more of timer_interrupt() by xtime_lock. [MIPS] Work around bad code generation for <asm/io.h>. [MIPS] Simple patch to power off DBAU1200 [MIPS] Fix DBAu1550 software power off. [MIPS] local_r4k_flush_cache_page fix [MIPS] SB1: Fix interrupt disable hazard. [MIPS] Get rid of the IP22-specific code in arclib. Update MAINTAINERS entry for MIPS.
This commit is contained in:
Коммит
4657190936
|
@ -1752,7 +1752,8 @@ P: Ralf Baechle
|
||||||
M: ralf@linux-mips.org
|
M: ralf@linux-mips.org
|
||||||
W: http://www.linux-mips.org/
|
W: http://www.linux-mips.org/
|
||||||
L: linux-mips@linux-mips.org
|
L: linux-mips@linux-mips.org
|
||||||
S: Maintained
|
T: git www.linux-mips.org:/pub/scm/linux.git
|
||||||
|
S: Supported
|
||||||
|
|
||||||
MISCELLANEOUS MCA-SUPPORT
|
MISCELLANEOUS MCA-SUPPORT
|
||||||
P: James Bottomley
|
P: James Bottomley
|
||||||
|
|
|
@ -108,7 +108,8 @@ MODFLAGS += -mlong-calls
|
||||||
cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB)
|
cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' && echo -EB)
|
||||||
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL)
|
cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += $(shell $(CC) -dumpmachine |grep -q 'mips.*el-.*' || echo -EL)
|
||||||
|
|
||||||
cflags-$(CONFIG_SB1XXX_CORELIS) += -mno-sched-prolog -fno-omit-frame-pointer
|
cflags-$(CONFIG_SB1XXX_CORELIS) += $(call cc-option,-mno-sched-prolog) \
|
||||||
|
-fno-omit-frame-pointer
|
||||||
|
|
||||||
#
|
#
|
||||||
# Use: $(call set_gccflags,<cpu0>,<isa0>,<cpu1>,<isa1>,<isa2>)
|
# Use: $(call set_gccflags,<cpu0>,<isa0>,<cpu1>,<isa1>,<isa2>)
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
* Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
|
* Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
|
||||||
* Copyright (C) 1999 Silicon Graphics, Inc.
|
* Copyright (C) 1999 Silicon Graphics, Inc.
|
||||||
*/
|
*/
|
||||||
#include <linux/config.h>
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
|
@ -20,17 +19,11 @@
|
||||||
#include <asm/bootinfo.h>
|
#include <asm/bootinfo.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
|
||||||
extern void *sgiwd93_host;
|
|
||||||
extern void reset_wd33c93(void *instance);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
ArcHalt(VOID)
|
ArcHalt(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
#ifdef CONFIG_SCSI_SGIWD93
|
|
||||||
reset_wd33c93(sgiwd93_host);
|
|
||||||
#endif
|
|
||||||
ARC_CALL0(halt);
|
ARC_CALL0(halt);
|
||||||
never: goto never;
|
never: goto never;
|
||||||
}
|
}
|
||||||
|
@ -40,9 +33,6 @@ ArcPowerDown(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
#ifdef CONFIG_SCSI_SGIWD93
|
|
||||||
reset_wd33c93(sgiwd93_host);
|
|
||||||
#endif
|
|
||||||
ARC_CALL0(pdown);
|
ARC_CALL0(pdown);
|
||||||
never: goto never;
|
never: goto never;
|
||||||
}
|
}
|
||||||
|
@ -53,9 +43,6 @@ ArcRestart(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
#ifdef CONFIG_SCSI_SGIWD93
|
|
||||||
reset_wd33c93(sgiwd93_host);
|
|
||||||
#endif
|
|
||||||
ARC_CALL0(restart);
|
ARC_CALL0(restart);
|
||||||
never: goto never;
|
never: goto never;
|
||||||
}
|
}
|
||||||
|
@ -65,9 +52,6 @@ ArcReboot(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
#ifdef CONFIG_SCSI_SGIWD93
|
|
||||||
reset_wd33c93(sgiwd93_host);
|
|
||||||
#endif
|
|
||||||
ARC_CALL0(reboot);
|
ARC_CALL0(reboot);
|
||||||
never: goto never;
|
never: goto never;
|
||||||
}
|
}
|
||||||
|
@ -77,9 +61,6 @@ ArcEnterInteractiveMode(VOID)
|
||||||
{
|
{
|
||||||
bc_disable();
|
bc_disable();
|
||||||
local_irq_disable();
|
local_irq_disable();
|
||||||
#ifdef CONFIG_SCSI_SGIWD93
|
|
||||||
reset_wd33c93(sgiwd93_host);
|
|
||||||
#endif
|
|
||||||
ARC_CALL0(imode);
|
ARC_CALL0(imode);
|
||||||
never: goto never;
|
never: goto never;
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,17 +164,20 @@ void au1000_restart(char *command)
|
||||||
|
|
||||||
void au1000_halt(void)
|
void au1000_halt(void)
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_MIPS_PB1550)
|
#if defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550)
|
||||||
/* power off system */
|
/* power off system */
|
||||||
printk("\n** Powering off Pb1550\n");
|
printk("\n** Powering off...\n");
|
||||||
au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
|
au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
|
||||||
au_sync();
|
au_sync();
|
||||||
while(1); /* should not get here */
|
while(1); /* should not get here */
|
||||||
#endif
|
#else
|
||||||
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
|
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
|
||||||
#ifdef CONFIG_MIPS_MIRAGE
|
#ifdef CONFIG_MIPS_MIRAGE
|
||||||
au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
|
au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_MIPS_DB1200
|
||||||
|
au_writew(au_readw(0xB980001C) | (1<<14), 0xB980001C);
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
au_sleep();
|
au_sleep();
|
||||||
|
|
||||||
|
@ -187,6 +190,7 @@ void au1000_halt(void)
|
||||||
"wait\n\t"
|
"wait\n\t"
|
||||||
".set\tmips0");
|
".set\tmips0");
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550) */
|
||||||
}
|
}
|
||||||
|
|
||||||
void au1000_power_off(void)
|
void au1000_power_off(void)
|
||||||
|
|
|
@ -424,6 +424,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||||
unsigned long j;
|
unsigned long j;
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
|
|
||||||
|
write_seqlock(&xtime_lock);
|
||||||
|
|
||||||
count = mips_hpt_read();
|
count = mips_hpt_read();
|
||||||
mips_timer_ack();
|
mips_timer_ack();
|
||||||
|
|
||||||
|
@ -441,7 +443,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||||
* CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
|
* CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
|
||||||
* called as close as possible to 500 ms before the new second starts.
|
* called as close as possible to 500 ms before the new second starts.
|
||||||
*/
|
*/
|
||||||
write_seqlock(&xtime_lock);
|
|
||||||
if (ntp_synced() &&
|
if (ntp_synced() &&
|
||||||
xtime.tv_sec > last_rtc_update + 660 &&
|
xtime.tv_sec > last_rtc_update + 660 &&
|
||||||
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
|
(xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 &&
|
||||||
|
@ -453,7 +454,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||||
last_rtc_update = xtime.tv_sec - 600;
|
last_rtc_update = xtime.tv_sec - 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
write_sequnlock(&xtime_lock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If jiffies has overflown in this timer_interrupt, we must
|
* If jiffies has overflown in this timer_interrupt, we must
|
||||||
|
@ -496,6 +496,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write_sequnlock(&xtime_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In UP mode, we call local_timer_interrupt() to do profiling
|
* In UP mode, we call local_timer_interrupt() to do profiling
|
||||||
* and process accouting.
|
* and process accouting.
|
||||||
|
|
|
@ -375,6 +375,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
|
||||||
struct flush_cache_page_args {
|
struct flush_cache_page_args {
|
||||||
struct vm_area_struct *vma;
|
struct vm_area_struct *vma;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
|
unsigned long pfn;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void local_r4k_flush_cache_page(void *args)
|
static inline void local_r4k_flush_cache_page(void *args)
|
||||||
|
@ -382,6 +383,7 @@ static inline void local_r4k_flush_cache_page(void *args)
|
||||||
struct flush_cache_page_args *fcp_args = args;
|
struct flush_cache_page_args *fcp_args = args;
|
||||||
struct vm_area_struct *vma = fcp_args->vma;
|
struct vm_area_struct *vma = fcp_args->vma;
|
||||||
unsigned long addr = fcp_args->addr;
|
unsigned long addr = fcp_args->addr;
|
||||||
|
unsigned long paddr = fcp_args->pfn << PAGE_SHIFT;
|
||||||
int exec = vma->vm_flags & VM_EXEC;
|
int exec = vma->vm_flags & VM_EXEC;
|
||||||
struct mm_struct *mm = vma->vm_mm;
|
struct mm_struct *mm = vma->vm_mm;
|
||||||
pgd_t *pgdp;
|
pgd_t *pgdp;
|
||||||
|
@ -431,11 +433,12 @@ static inline void local_r4k_flush_cache_page(void *args)
|
||||||
* Do indexed flush, too much work to get the (possible) TLB refills
|
* Do indexed flush, too much work to get the (possible) TLB refills
|
||||||
* to work correctly.
|
* to work correctly.
|
||||||
*/
|
*/
|
||||||
addr = INDEX_BASE + (addr & (dcache_size - 1));
|
|
||||||
if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
|
if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
|
||||||
r4k_blast_dcache_page_indexed(addr);
|
r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ?
|
||||||
if (exec && !cpu_icache_snoops_remote_store)
|
paddr : addr);
|
||||||
r4k_blast_scache_page_indexed(addr);
|
if (exec && !cpu_icache_snoops_remote_store) {
|
||||||
|
r4k_blast_scache_page_indexed(paddr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (exec) {
|
if (exec) {
|
||||||
if (cpu_has_vtag_icache) {
|
if (cpu_has_vtag_icache) {
|
||||||
|
@ -455,6 +458,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
|
||||||
|
|
||||||
args.vma = vma;
|
args.vma = vma;
|
||||||
args.addr = addr;
|
args.addr = addr;
|
||||||
|
args.pfn = pfn;
|
||||||
|
|
||||||
on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
|
on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
|
||||||
}
|
}
|
||||||
|
@ -956,6 +960,7 @@ static void __init probe_pcache(void)
|
||||||
switch (c->cputype) {
|
switch (c->cputype) {
|
||||||
case CPU_20KC:
|
case CPU_20KC:
|
||||||
case CPU_25KF:
|
case CPU_25KF:
|
||||||
|
c->dcache.flags |= MIPS_CACHE_PINDEX;
|
||||||
case CPU_R10000:
|
case CPU_R10000:
|
||||||
case CPU_R12000:
|
case CPU_R12000:
|
||||||
case CPU_SB1:
|
case CPU_SB1:
|
||||||
|
|
|
@ -210,7 +210,6 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page
|
||||||
* Do indexed flush, too much work to get the (possible) TLB refills
|
* Do indexed flush, too much work to get the (possible) TLB refills
|
||||||
* to work correctly.
|
* to work correctly.
|
||||||
*/
|
*/
|
||||||
page = (KSEG0 + (page & (dcache_size - 1)));
|
|
||||||
if (cpu_has_dc_aliases || exec)
|
if (cpu_has_dc_aliases || exec)
|
||||||
tx39_blast_dcache_page_indexed(page);
|
tx39_blast_dcache_page_indexed(page);
|
||||||
if (exec)
|
if (exec)
|
||||||
|
|
|
@ -47,23 +47,51 @@
|
||||||
#define IMR_IP3_VAL K_INT_MAP_I1
|
#define IMR_IP3_VAL K_INT_MAP_I1
|
||||||
#define IMR_IP4_VAL K_INT_MAP_I2
|
#define IMR_IP4_VAL K_INT_MAP_I2
|
||||||
|
|
||||||
|
#define SB1250_HPT_NUM 3
|
||||||
|
#define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */
|
||||||
|
#define SB1250_HPT_SHIFT ((sizeof(unsigned int)*8)-V_SCD_TIMER_WIDTH)
|
||||||
|
|
||||||
|
|
||||||
extern int sb1250_steal_irq(int irq);
|
extern int sb1250_steal_irq(int irq);
|
||||||
|
|
||||||
|
static unsigned int sb1250_hpt_read(void);
|
||||||
|
static void sb1250_hpt_init(unsigned int);
|
||||||
|
|
||||||
|
static unsigned int hpt_offset;
|
||||||
|
|
||||||
|
void __init sb1250_hpt_setup(void)
|
||||||
|
{
|
||||||
|
int cpu = smp_processor_id();
|
||||||
|
|
||||||
|
if (!cpu) {
|
||||||
|
/* Setup hpt using timer #3 but do not enable irq for it */
|
||||||
|
__raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
|
||||||
|
__raw_writeq(SB1250_HPT_VALUE,
|
||||||
|
IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_INIT)));
|
||||||
|
__raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
|
||||||
|
IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CFG)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we need to fill 32 bits, so just use the upper 23 bits and pretend
|
||||||
|
* the timer is going 512Mhz instead of 1Mhz
|
||||||
|
*/
|
||||||
|
mips_hpt_frequency = V_SCD_TIMER_FREQ << SB1250_HPT_SHIFT;
|
||||||
|
mips_hpt_init = sb1250_hpt_init;
|
||||||
|
mips_hpt_read = sb1250_hpt_read;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void sb1250_time_init(void)
|
void sb1250_time_init(void)
|
||||||
{
|
{
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
int irq = K_INT_TIMER_0+cpu;
|
int irq = K_INT_TIMER_0+cpu;
|
||||||
|
|
||||||
/* Only have 4 general purpose timers */
|
/* Only have 4 general purpose timers, and we use last one as hpt */
|
||||||
if (cpu > 3) {
|
if (cpu > 2) {
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cpu) {
|
|
||||||
/* Use our own gettimeoffset() routine */
|
|
||||||
do_gettimeoffset = sb1250_gettimeoffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
sb1250_mask_irq(cpu, irq);
|
sb1250_mask_irq(cpu, irq);
|
||||||
|
|
||||||
/* Map the timer interrupt to ip[4] of this cpu */
|
/* Map the timer interrupt to ip[4] of this cpu */
|
||||||
|
@ -75,10 +103,10 @@ void sb1250_time_init(void)
|
||||||
/* Disable the timer and set up the count */
|
/* Disable the timer and set up the count */
|
||||||
__raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
|
__raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
|
||||||
#ifdef CONFIG_SIMULATION
|
#ifdef CONFIG_SIMULATION
|
||||||
__raw_writeq(50000 / HZ,
|
__raw_writeq((50000 / HZ) - 1,
|
||||||
IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
|
IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
|
||||||
#else
|
#else
|
||||||
__raw_writeq(1000000 / HZ,
|
__raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1,
|
||||||
IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
|
IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -103,7 +131,7 @@ void sb1250_timer_interrupt(struct pt_regs *regs)
|
||||||
int cpu = smp_processor_id();
|
int cpu = smp_processor_id();
|
||||||
int irq = K_INT_TIMER_0 + cpu;
|
int irq = K_INT_TIMER_0 + cpu;
|
||||||
|
|
||||||
/* Reset the timer */
|
/* ACK interrupt */
|
||||||
____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
|
____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
|
||||||
IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
|
IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
|
||||||
|
|
||||||
|
@ -122,15 +150,26 @@ void sb1250_timer_interrupt(struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We use our own do_gettimeoffset() instead of the generic one,
|
* The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
|
||||||
* because the generic one does not work for SMP case.
|
* again. There's no easy way to set to a specific value so store init value
|
||||||
* In addition, since we use general timer 0 for system time,
|
* in hpt_offset and subtract each time.
|
||||||
* we can get accurate intra-jiffy offset without calibration.
|
*
|
||||||
|
* Note: Timer isn't full 32bits so shift it into the upper part making
|
||||||
|
* it appear to run at a higher frequency.
|
||||||
*/
|
*/
|
||||||
unsigned long sb1250_gettimeoffset(void)
|
static unsigned int sb1250_hpt_read(void)
|
||||||
{
|
{
|
||||||
unsigned long count =
|
unsigned int count;
|
||||||
__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
|
|
||||||
|
|
||||||
return 1000000/HZ - count;
|
count = G_SCD_TIMER_CNT(__raw_readq(IOADDR(A_SCD_TIMER_REGISTER(SB1250_HPT_NUM, R_SCD_TIMER_CNT))));
|
||||||
}
|
|
||||||
|
count = (SB1250_HPT_VALUE - count) << SB1250_HPT_SHIFT;
|
||||||
|
|
||||||
|
return count - hpt_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sb1250_hpt_init(unsigned int count)
|
||||||
|
{
|
||||||
|
hpt_offset = count;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
|
@ -70,6 +70,12 @@ const char *get_system_type(void)
|
||||||
return "SiByte " SIBYTE_BOARD_NAME;
|
return "SiByte " SIBYTE_BOARD_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void __init swarm_time_init(void)
|
||||||
|
{
|
||||||
|
/* Setup HPT */
|
||||||
|
sb1250_hpt_setup();
|
||||||
|
}
|
||||||
|
|
||||||
void __init swarm_timer_setup(struct irqaction *irq)
|
void __init swarm_timer_setup(struct irqaction *irq)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -109,6 +115,7 @@ void __init plat_setup(void)
|
||||||
|
|
||||||
panic_timeout = 5; /* For debug. */
|
panic_timeout = 5; /* For debug. */
|
||||||
|
|
||||||
|
board_time_init = swarm_time_init;
|
||||||
board_timer_setup = swarm_timer_setup;
|
board_timer_setup = swarm_timer_setup;
|
||||||
board_be_handler = swarm_be_handler;
|
board_be_handler = swarm_be_handler;
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,9 @@
|
||||||
#ifndef cpu_has_ic_fills_f_dc
|
#ifndef cpu_has_ic_fills_f_dc
|
||||||
#define cpu_has_ic_fills_f_dc (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC)
|
#define cpu_has_ic_fills_f_dc (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC)
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef cpu_has_pindexed_dcache
|
||||||
|
#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I-Cache snoops remote store. This only matters on SMP. Some multiprocessors
|
* I-Cache snoops remote store. This only matters on SMP. Some multiprocessors
|
||||||
|
|
|
@ -39,6 +39,7 @@ struct cache_desc {
|
||||||
#define MIPS_CACHE_ALIASES 0x00000004 /* Cache could have aliases */
|
#define MIPS_CACHE_ALIASES 0x00000004 /* Cache could have aliases */
|
||||||
#define MIPS_CACHE_IC_F_DC 0x00000008 /* Ic can refill from D-cache */
|
#define MIPS_CACHE_IC_F_DC 0x00000008 /* Ic can refill from D-cache */
|
||||||
#define MIPS_IC_SNOOPS_REMOTE 0x00000010 /* Ic snoops remote stores */
|
#define MIPS_IC_SNOOPS_REMOTE 0x00000010 /* Ic snoops remote stores */
|
||||||
|
#define MIPS_CACHE_PINDEX 0x00000020 /* Physically indexed cache */
|
||||||
|
|
||||||
struct cpuinfo_mips {
|
struct cpuinfo_mips {
|
||||||
unsigned long udelay_val;
|
unsigned long udelay_val;
|
||||||
|
|
|
@ -3,7 +3,9 @@
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
* License. See the file "COPYING" in the main directory of this archive
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2003, 2004 Ralf Baechle
|
* Copyright (C) 2003, 2004 Ralf Baechle <ralf@linux-mips.org>
|
||||||
|
* Copyright (C) MIPS Technologies, Inc.
|
||||||
|
* written by Ralf Baechle <ralf@linux-mips.org>
|
||||||
*/
|
*/
|
||||||
#ifndef _ASM_HAZARDS_H
|
#ifndef _ASM_HAZARDS_H
|
||||||
#define _ASM_HAZARDS_H
|
#define _ASM_HAZARDS_H
|
||||||
|
@ -74,8 +76,7 @@
|
||||||
#define irq_disable_hazard
|
#define irq_disable_hazard
|
||||||
_ehb
|
_ehb
|
||||||
|
|
||||||
#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
|
#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
|
||||||
defined(CONFIG_CPU_SB1)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
|
* R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
|
||||||
|
@ -99,13 +100,13 @@
|
||||||
#else /* __ASSEMBLY__ */
|
#else /* __ASSEMBLY__ */
|
||||||
|
|
||||||
__asm__(
|
__asm__(
|
||||||
" .macro _ssnop \n\t"
|
" .macro _ssnop \n"
|
||||||
" sll $0, $0, 1 \n\t"
|
" sll $0, $0, 1 \n"
|
||||||
" .endm \n\t"
|
" .endm \n"
|
||||||
" \n\t"
|
" \n"
|
||||||
" .macro _ehb \n\t"
|
" .macro _ehb \n"
|
||||||
" sll $0, $0, 3 \n\t"
|
" sll $0, $0, 3 \n"
|
||||||
" .endm \n\t");
|
" .endm \n");
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_RM9000
|
#ifdef CONFIG_CPU_RM9000
|
||||||
|
|
||||||
|
@ -117,17 +118,21 @@ __asm__(
|
||||||
|
|
||||||
#define mtc0_tlbw_hazard() \
|
#define mtc0_tlbw_hazard() \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
".set\tmips32\n\t" \
|
" .set mips32 \n" \
|
||||||
"_ssnop; _ssnop; _ssnop; _ssnop\n\t" \
|
" _ssnop \n" \
|
||||||
".set\tmips0")
|
" _ssnop \n" \
|
||||||
|
" _ssnop \n" \
|
||||||
|
" _ssnop \n" \
|
||||||
|
" .set mips0 \n")
|
||||||
|
|
||||||
#define tlbw_use_hazard() \
|
#define tlbw_use_hazard() \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
".set\tmips32\n\t" \
|
" .set mips32 \n" \
|
||||||
"_ssnop; _ssnop; _ssnop; _ssnop\n\t" \
|
" _ssnop \n" \
|
||||||
".set\tmips0")
|
" _ssnop \n" \
|
||||||
|
" _ssnop \n" \
|
||||||
#define back_to_back_c0_hazard() do { } while (0)
|
" _ssnop \n" \
|
||||||
|
" .set mips0 \n")
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -136,15 +141,25 @@ __asm__(
|
||||||
*/
|
*/
|
||||||
#define mtc0_tlbw_hazard() \
|
#define mtc0_tlbw_hazard() \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
".set noreorder\n\t" \
|
" .set noreorder \n" \
|
||||||
"nop; nop; nop; nop; nop; nop;\n\t" \
|
" nop \n" \
|
||||||
".set reorder\n\t")
|
" nop \n" \
|
||||||
|
" nop \n" \
|
||||||
|
" nop \n" \
|
||||||
|
" nop \n" \
|
||||||
|
" nop \n" \
|
||||||
|
" .set reorder \n")
|
||||||
|
|
||||||
#define tlbw_use_hazard() \
|
#define tlbw_use_hazard() \
|
||||||
__asm__ __volatile__( \
|
__asm__ __volatile__( \
|
||||||
".set noreorder\n\t" \
|
" .set noreorder \n" \
|
||||||
"nop; nop; nop; nop; nop; nop;\n\t" \
|
" nop \n" \
|
||||||
".set reorder\n\t")
|
" nop \n" \
|
||||||
|
" nop \n" \
|
||||||
|
" nop \n" \
|
||||||
|
" nop \n" \
|
||||||
|
" nop \n" \
|
||||||
|
" .set reorder \n")
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -156,49 +171,26 @@ __asm__(
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_MIPSR2
|
#ifdef CONFIG_CPU_MIPSR2
|
||||||
|
|
||||||
__asm__(
|
__asm__(" .macro irq_enable_hazard \n"
|
||||||
" .macro\tirq_enable_hazard \n\t"
|
" _ehb \n"
|
||||||
" _ehb \n\t"
|
" .endm \n"
|
||||||
" .endm \n\t"
|
" \n"
|
||||||
" \n\t"
|
" .macro irq_disable_hazard \n"
|
||||||
" .macro\tirq_disable_hazard \n\t"
|
" _ehb \n"
|
||||||
" _ehb \n\t"
|
" .endm \n");
|
||||||
" .endm \n\t"
|
|
||||||
" \n\t"
|
|
||||||
" .macro\tback_to_back_c0_hazard \n\t"
|
|
||||||
" _ehb \n\t"
|
|
||||||
" .endm");
|
|
||||||
|
|
||||||
#define irq_enable_hazard() \
|
#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
|
||||||
__asm__ __volatile__( \
|
|
||||||
"irq_enable_hazard")
|
|
||||||
|
|
||||||
#define irq_disable_hazard() \
|
|
||||||
__asm__ __volatile__( \
|
|
||||||
"irq_disable_hazard")
|
|
||||||
|
|
||||||
#define back_to_back_c0_hazard() \
|
|
||||||
__asm__ __volatile__( \
|
|
||||||
"back_to_back_c0_hazard")
|
|
||||||
|
|
||||||
#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
|
|
||||||
defined(CONFIG_CPU_SB1)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
|
* R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
__asm__(
|
__asm__(
|
||||||
" .macro\tirq_enable_hazard \n\t"
|
" .macro irq_enable_hazard \n"
|
||||||
" .endm \n\t"
|
" .endm \n"
|
||||||
" \n\t"
|
" \n"
|
||||||
" .macro\tirq_disable_hazard \n\t"
|
" .macro irq_disable_hazard \n"
|
||||||
" .endm");
|
" .endm \n");
|
||||||
|
|
||||||
#define irq_enable_hazard() do { } while (0)
|
|
||||||
#define irq_disable_hazard() do { } while (0)
|
|
||||||
|
|
||||||
#define back_to_back_c0_hazard() do { } while (0)
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -209,29 +201,63 @@ __asm__(
|
||||||
*/
|
*/
|
||||||
|
|
||||||
__asm__(
|
__asm__(
|
||||||
" # \n\t"
|
" # \n"
|
||||||
" # There is a hazard but we do not care \n\t"
|
" # There is a hazard but we do not care \n"
|
||||||
" # \n\t"
|
" # \n"
|
||||||
" .macro\tirq_enable_hazard \n\t"
|
" .macro\tirq_enable_hazard \n"
|
||||||
" .endm \n\t"
|
" .endm \n"
|
||||||
" \n\t"
|
" \n"
|
||||||
" .macro\tirq_disable_hazard \n\t"
|
" .macro\tirq_disable_hazard \n"
|
||||||
" _ssnop; _ssnop; _ssnop \n\t"
|
" _ssnop \n"
|
||||||
" .endm");
|
" _ssnop \n"
|
||||||
|
" _ssnop \n"
|
||||||
#define irq_enable_hazard() do { } while (0)
|
" .endm \n");
|
||||||
#define irq_disable_hazard() \
|
|
||||||
__asm__ __volatile__( \
|
|
||||||
"irq_disable_hazard")
|
|
||||||
|
|
||||||
#define back_to_back_c0_hazard() \
|
|
||||||
__asm__ __volatile__( \
|
|
||||||
" .set noreorder \n" \
|
|
||||||
" nop; nop; nop \n" \
|
|
||||||
" .set reorder \n")
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define irq_enable_hazard() \
|
||||||
|
__asm__ __volatile__("irq_enable_hazard")
|
||||||
|
#define irq_disable_hazard() \
|
||||||
|
__asm__ __volatile__("irq_disable_hazard")
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Back-to-back hazards -
|
||||||
|
*
|
||||||
|
* What is needed to separate a move to cp0 from a subsequent read from the
|
||||||
|
* same cp0 register?
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_CPU_MIPSR2
|
||||||
|
|
||||||
|
__asm__(" .macro back_to_back_c0_hazard \n"
|
||||||
|
" _ehb \n"
|
||||||
|
" .endm \n");
|
||||||
|
|
||||||
|
#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
|
||||||
|
defined(CONFIG_CPU_SB1)
|
||||||
|
|
||||||
|
__asm__(" .macro back_to_back_c0_hazard \n"
|
||||||
|
" .endm \n");
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
__asm__(" .macro back_to_back_c0_hazard \n"
|
||||||
|
" .set noreorder \n"
|
||||||
|
" _ssnop \n"
|
||||||
|
" _ssnop \n"
|
||||||
|
" _ssnop \n"
|
||||||
|
" .set reorder \n"
|
||||||
|
" .endm");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define back_to_back_c0_hazard() \
|
||||||
|
__asm__ __volatile__("back_to_back_c0_hazard")
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instruction execution hazard
|
||||||
|
*/
|
||||||
#ifdef CONFIG_CPU_MIPSR2
|
#ifdef CONFIG_CPU_MIPSR2
|
||||||
/*
|
/*
|
||||||
* gcc has a tradition of misscompiling the previous construct using the
|
* gcc has a tradition of misscompiling the previous construct using the
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* Copyright (C) 1994, 1995 Waldorf GmbH
|
* Copyright (C) 1994, 1995 Waldorf GmbH
|
||||||
* Copyright (C) 1994 - 2000 Ralf Baechle
|
* Copyright (C) 1994 - 2000, 06 Ralf Baechle
|
||||||
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
||||||
* Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
|
* Copyright (C) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
|
||||||
* Author: Maciej W. Rozycki <macro@mips.com>
|
* Author: Maciej W. Rozycki <macro@mips.com>
|
||||||
|
@ -103,8 +103,20 @@
|
||||||
*/
|
*/
|
||||||
extern const unsigned long mips_io_port_base;
|
extern const unsigned long mips_io_port_base;
|
||||||
|
|
||||||
#define set_io_port_base(base) \
|
/*
|
||||||
do { * (unsigned long *) &mips_io_port_base = (base); } while (0)
|
* Gcc will generate code to load the value of mips_io_port_base after each
|
||||||
|
* function call which may be fairly wasteful in some cases. So we don't
|
||||||
|
* play quite by the book. We tell gcc mips_io_port_base is a long variable
|
||||||
|
* which solves the code generation issue. Now we need to violate the
|
||||||
|
* aliasing rules a little to make initialization possible and finally we
|
||||||
|
* will need the barrier() to fight side effects of the aliasing chat.
|
||||||
|
* This trickery will eventually collapse under gcc's optimizer. Oh well.
|
||||||
|
*/
|
||||||
|
static inline void set_io_port_base(unsigned long base)
|
||||||
|
{
|
||||||
|
* (unsigned long *) &mips_io_port_base = base;
|
||||||
|
barrier();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Thanks to James van Artsdalen for a better timing-fix than
|
* Thanks to James van Artsdalen for a better timing-fix than
|
||||||
|
|
|
@ -257,7 +257,8 @@ static inline void blast_##pfx##cache##lsize##_page(unsigned long page) \
|
||||||
\
|
\
|
||||||
static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
|
static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page) \
|
||||||
{ \
|
{ \
|
||||||
unsigned long start = page; \
|
unsigned long indexmask = current_cpu_data.desc.waysize - 1; \
|
||||||
|
unsigned long start = INDEX_BASE + (page & indexmask); \
|
||||||
unsigned long end = start + PAGE_SIZE; \
|
unsigned long end = start + PAGE_SIZE; \
|
||||||
unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \
|
unsigned long ws_inc = 1UL << current_cpu_data.desc.waybit; \
|
||||||
unsigned long ws_end = current_cpu_data.desc.ways << \
|
unsigned long ws_end = current_cpu_data.desc.ways << \
|
||||||
|
|
|
@ -45,8 +45,8 @@ extern unsigned int soc_type;
|
||||||
extern unsigned int periph_rev;
|
extern unsigned int periph_rev;
|
||||||
extern unsigned int zbbus_mhz;
|
extern unsigned int zbbus_mhz;
|
||||||
|
|
||||||
|
extern void sb1250_hpt_setup(void);
|
||||||
extern void sb1250_time_init(void);
|
extern void sb1250_time_init(void);
|
||||||
extern unsigned long sb1250_gettimeoffset(void);
|
|
||||||
extern void sb1250_mask_irq(int cpu, int irq);
|
extern void sb1250_mask_irq(int cpu, int irq);
|
||||||
extern void sb1250_unmask_irq(int cpu, int irq);
|
extern void sb1250_unmask_irq(int cpu, int irq);
|
||||||
extern void sb1250_smp_finish(void);
|
extern void sb1250_smp_finish(void);
|
||||||
|
|
|
@ -359,14 +359,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define V_SCD_TIMER_FREQ 1000000
|
#define V_SCD_TIMER_FREQ 1000000
|
||||||
|
#define V_SCD_TIMER_WIDTH 23
|
||||||
|
|
||||||
#define S_SCD_TIMER_INIT 0
|
#define S_SCD_TIMER_INIT 0
|
||||||
#define M_SCD_TIMER_INIT _SB_MAKEMASK(20,S_SCD_TIMER_INIT)
|
#define M_SCD_TIMER_INIT _SB_MAKEMASK(V_SCD_TIMER_WIDTH,S_SCD_TIMER_INIT)
|
||||||
#define V_SCD_TIMER_INIT(x) _SB_MAKEVALUE(x,S_SCD_TIMER_INIT)
|
#define V_SCD_TIMER_INIT(x) _SB_MAKEVALUE(x,S_SCD_TIMER_INIT)
|
||||||
#define G_SCD_TIMER_INIT(x) _SB_GETVALUE(x,S_SCD_TIMER_INIT,M_SCD_TIMER_INIT)
|
#define G_SCD_TIMER_INIT(x) _SB_GETVALUE(x,S_SCD_TIMER_INIT,M_SCD_TIMER_INIT)
|
||||||
|
|
||||||
#define S_SCD_TIMER_CNT 0
|
#define S_SCD_TIMER_CNT 0
|
||||||
#define M_SCD_TIMER_CNT _SB_MAKEMASK(20,S_SCD_TIMER_CNT)
|
#define M_SCD_TIMER_CNT _SB_MAKEMASK(V_SCD_TIMER_WIDTH,S_SCD_TIMER_CNT)
|
||||||
#define V_SCD_TIMER_CNT(x) _SB_MAKEVALUE(x,S_SCD_TIMER_CNT)
|
#define V_SCD_TIMER_CNT(x) _SB_MAKEVALUE(x,S_SCD_TIMER_CNT)
|
||||||
#define G_SCD_TIMER_CNT(x) _SB_GETVALUE(x,S_SCD_TIMER_CNT,M_SCD_TIMER_CNT)
|
#define G_SCD_TIMER_CNT(x) _SB_GETVALUE(x,S_SCD_TIMER_CNT,M_SCD_TIMER_CNT)
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче