提交 46571909 编写于 作者: L Linus Torvalds

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.
...@@ -1752,7 +1752,8 @@ P: Ralf Baechle ...@@ -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 ...@@ -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 @@ ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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 ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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 { ...@@ -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 @@ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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__( ...@@ -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__( ...@@ -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__( ...@@ -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() \
__asm__ __volatile__( \
"irq_enable_hazard")
#define irq_disable_hazard() \ #elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
__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__( ...@@ -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"
" .endm \n");
#define irq_enable_hazard() do { } while (0) #endif
#define irq_enable_hazard() \
__asm__ __volatile__("irq_enable_hazard")
#define irq_disable_hazard() \ #define irq_disable_hazard() \
__asm__ __volatile__( \ __asm__ __volatile__("irq_disable_hazard")
"irq_disable_hazard")
#define back_to_back_c0_hazard() \
__asm__ __volatile__( \ /*
" .set noreorder \n" \ * Back-to-back hazards -
" nop; nop; nop \n" \ *
" .set reorder \n") * 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 #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 @@ ...@@ -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 @@ ...@@ -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) \ ...@@ -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; ...@@ -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 @@ ...@@ -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)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册