aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-03-19 21:12:00 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-19 21:12:00 -0800
commit4657190936883adb819f81957e33439d447c0035 (patch)
tree70342debfb779a8b10d2a8440c1ae99593806079
parent4a29cc2e503b33a1e96db4c3f9a94165f153f259 (diff)
parent9007c9a2b03ea325ee593a161dbf01dbb8222d7e (diff)
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.
-rw-r--r--MAINTAINERS3
-rw-r--r--arch/mips/Makefile3
-rw-r--r--arch/mips/arc/misc.c19
-rw-r--r--arch/mips/au1000/common/reset.c10
-rw-r--r--arch/mips/kernel/time.c6
-rw-r--r--arch/mips/mm/c-r4k.c13
-rw-r--r--arch/mips/mm/c-tx39.c1
-rw-r--r--arch/mips/sibyte/sb1250/time.c77
-rw-r--r--arch/mips/sibyte/swarm/setup.c7
-rw-r--r--include/asm-mips/cpu-features.h3
-rw-r--r--include/asm-mips/cpu-info.h1
-rw-r--r--include/asm-mips/hazards.h180
-rw-r--r--include/asm-mips/io.h18
-rw-r--r--include/asm-mips/r4kcache.h3
-rw-r--r--include/asm-mips/sibyte/sb1250.h2
-rw-r--r--include/asm-mips/sibyte/sb1250_scd.h5
16 files changed, 217 insertions, 134 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 3d7d30dc543..8db5c339845 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1752,7 +1752,8 @@ P: Ralf Baechle
M: ralf@linux-mips.org
W: http://www.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
P: James Bottomley
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index fe9da16f3a4..3d8dac681c6 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -108,7 +108,8 @@ MODFLAGS += -mlong-calls
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_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>)
diff --git a/arch/mips/arc/misc.c b/arch/mips/arc/misc.c
index 84867de2202..b2e10b9e945 100644
--- a/arch/mips/arc/misc.c
+++ b/arch/mips/arc/misc.c
@@ -9,7 +9,6 @@
* Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
-#include <linux/config.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -20,17 +19,11 @@
#include <asm/bootinfo.h>
#include <asm/system.h>
-extern void *sgiwd93_host;
-extern void reset_wd33c93(void *instance);
-
VOID
ArcHalt(VOID)
{
bc_disable();
local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
- reset_wd33c93(sgiwd93_host);
-#endif
ARC_CALL0(halt);
never: goto never;
}
@@ -40,9 +33,6 @@ ArcPowerDown(VOID)
{
bc_disable();
local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
- reset_wd33c93(sgiwd93_host);
-#endif
ARC_CALL0(pdown);
never: goto never;
}
@@ -53,9 +43,6 @@ ArcRestart(VOID)
{
bc_disable();
local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
- reset_wd33c93(sgiwd93_host);
-#endif
ARC_CALL0(restart);
never: goto never;
}
@@ -65,9 +52,6 @@ ArcReboot(VOID)
{
bc_disable();
local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
- reset_wd33c93(sgiwd93_host);
-#endif
ARC_CALL0(reboot);
never: goto never;
}
@@ -77,9 +61,6 @@ ArcEnterInteractiveMode(VOID)
{
bc_disable();
local_irq_disable();
-#ifdef CONFIG_SCSI_SGIWD93
- reset_wd33c93(sgiwd93_host);
-#endif
ARC_CALL0(imode);
never: goto never;
}
diff --git a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c
index 4ffccedf596..c93af224c1b 100644
--- a/arch/mips/au1000/common/reset.c
+++ b/arch/mips/au1000/common/reset.c
@@ -164,17 +164,20 @@ void au1000_restart(char *command)
void au1000_halt(void)
{
-#if defined(CONFIG_MIPS_PB1550)
+#if defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550)
/* power off system */
- printk("\n** Powering off Pb1550\n");
+ printk("\n** Powering off...\n");
au_writew(au_readw(0xAF00001C) | (3<<14), 0xAF00001C);
au_sync();
while(1); /* should not get here */
-#endif
+#else
printk(KERN_NOTICE "\n** You can safely turn off the power\n");
#ifdef CONFIG_MIPS_MIRAGE
au_writel((1 << 26) | (1 << 10), GPIO2_OUTPUT);
#endif
+#ifdef CONFIG_MIPS_DB1200
+ au_writew(au_readw(0xB980001C) | (1<<14), 0xB980001C);
+#endif
#ifdef CONFIG_PM
au_sleep();
@@ -187,6 +190,7 @@ void au1000_halt(void)
"wait\n\t"
".set\tmips0");
#endif
+#endif /* defined(CONFIG_MIPS_PB1550) || defined(CONFIG_MIPS_DB1550) */
}
void au1000_power_off(void)
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 42c94c771af..51273b7297a 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -424,6 +424,8 @@ irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
unsigned long j;
unsigned int count;
+ write_seqlock(&xtime_lock);
+
count = mips_hpt_read();
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
* called as close as possible to 500 ms before the new second starts.
*/
- write_seqlock(&xtime_lock);
if (ntp_synced() &&
xtime.tv_sec > last_rtc_update + 660 &&
(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;
}
}
- write_sequnlock(&xtime_lock);
/*
* 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
* and process accouting.
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index 0668e9bfce4..9572ed44f0d 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -375,6 +375,7 @@ static void r4k_flush_cache_mm(struct mm_struct *mm)
struct flush_cache_page_args {
struct vm_area_struct *vma;
unsigned long addr;
+ unsigned long pfn;
};
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 vm_area_struct *vma = fcp_args->vma;
unsigned long addr = fcp_args->addr;
+ unsigned long paddr = fcp_args->pfn << PAGE_SHIFT;
int exec = vma->vm_flags & VM_EXEC;
struct mm_struct *mm = vma->vm_mm;
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
* to work correctly.
*/
- addr = INDEX_BASE + (addr & (dcache_size - 1));
if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
- r4k_blast_dcache_page_indexed(addr);
- if (exec && !cpu_icache_snoops_remote_store)
- r4k_blast_scache_page_indexed(addr);
+ r4k_blast_dcache_page_indexed(cpu_has_pindexed_dcache ?
+ paddr : addr);
+ if (exec && !cpu_icache_snoops_remote_store) {
+ r4k_blast_scache_page_indexed(paddr);
+ }
}
if (exec) {
if (cpu_has_vtag_icache) {
@@ -455,6 +458,7 @@ static void r4k_flush_cache_page(struct vm_area_struct *vma,
args.vma = vma;
args.addr = addr;
+ args.pfn = pfn;
on_each_cpu(local_r4k_flush_cache_page, &args, 1, 1);
}
@@ -956,6 +960,7 @@ static void __init probe_pcache(void)
switch (c->cputype) {
case CPU_20KC:
case CPU_25KF:
+ c->dcache.flags |= MIPS_CACHE_PINDEX;
case CPU_R10000:
case CPU_R12000:
case CPU_SB1:
diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
index 7c572bea4a9..fe232e3988e 100644
--- a/arch/mips/mm/c-tx39.c
+++ b/arch/mips/mm/c-tx39.c
@@ -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
* to work correctly.
*/
- page = (KSEG0 + (page & (dcache_size - 1)));
if (cpu_has_dc_aliases || exec)
tx39_blast_dcache_page_indexed(page);
if (exec)
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 511c89d65f3..1588f6debd9 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -47,23 +47,51 @@
#define IMR_IP3_VAL K_INT_MAP_I1
#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);
+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)
{
int cpu = smp_processor_id();
int irq = K_INT_TIMER_0+cpu;
- /* Only have 4 general purpose timers */
- if (cpu > 3) {
+ /* Only have 4 general purpose timers, and we use last one as hpt */
+ if (cpu > 2) {
BUG();
}
- if (!cpu) {
- /* Use our own gettimeoffset() routine */
- do_gettimeoffset = sb1250_gettimeoffset;
- }
-
sb1250_mask_irq(cpu, irq);
/* 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 */
__raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
#ifdef CONFIG_SIMULATION
- __raw_writeq(50000 / HZ,
+ __raw_writeq((50000 / HZ) - 1,
IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
#else
- __raw_writeq(1000000 / HZ,
+ __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1,
IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
#endif
@@ -103,7 +131,7 @@ void sb1250_timer_interrupt(struct pt_regs *regs)
int cpu = smp_processor_id();
int irq = K_INT_TIMER_0 + cpu;
- /* Reset the timer */
+ /* ACK interrupt */
____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
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,
- * because the generic one does not work for SMP case.
- * In addition, since we use general timer 0 for system time,
- * we can get accurate intra-jiffy offset without calibration.
+ * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
+ * again. There's no easy way to set to a specific value so store init value
+ * in hpt_offset and subtract each time.
+ *
+ * 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 =
- __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
+ unsigned int count;
- 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;
+}
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index b614ca0ddb6..b661d2425a3 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -70,6 +70,12 @@ const char *get_system_type(void)
return "SiByte " SIBYTE_BOARD_NAME;
}
+void __init swarm_time_init(void)
+{
+ /* Setup HPT */
+ sb1250_hpt_setup();
+}
+
void __init swarm_timer_setup(struct irqaction *irq)
{
/*
@@ -109,6 +115,7 @@ void __init plat_setup(void)
panic_timeout = 5; /* For debug. */
+ board_time_init = swarm_time_init;
board_timer_setup = swarm_timer_setup;
board_be_handler = swarm_be_handler;
diff --git a/include/asm-mips/cpu-features.h b/include/asm-mips/cpu-features.h
index 78c9cc2735d..3f2b6d9ac45 100644
--- a/include/asm-mips/cpu-features.h
+++ b/include/asm-mips/cpu-features.h
@@ -96,6 +96,9 @@
#ifndef cpu_has_ic_fills_f_dc
#define cpu_has_ic_fills_f_dc (cpu_data[0].icache.flags & MIPS_CACHE_IC_F_DC)
#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
diff --git a/include/asm-mips/cpu-info.h b/include/asm-mips/cpu-info.h
index d5cf519f8fc..140be1c67da 100644
--- a/include/asm-mips/cpu-info.h
+++ b/include/asm-mips/cpu-info.h
@@ -39,6 +39,7 @@ struct cache_desc {
#define MIPS_CACHE_ALIASES 0x00000004 /* Cache could have aliases */
#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_CACHE_PINDEX 0x00000020 /* Physically indexed cache */
struct cpuinfo_mips {
unsigned long udelay_val;
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index 6111a0ce58c..feb29a79388 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -3,7 +3,9 @@
* License. See the file "COPYING" in the main directory of this archive
* 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
#define _ASM_HAZARDS_H
@@ -74,8 +76,7 @@
#define irq_disable_hazard
_ehb
-#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
- defined(CONFIG_CPU_SB1)
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
/*
* R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
@@ -99,13 +100,13 @@
#else /* __ASSEMBLY__ */
__asm__(
- " .macro _ssnop \n\t"
- " sll $0, $0, 1 \n\t"
- " .endm \n\t"
- " \n\t"
- " .macro _ehb \n\t"
- " sll $0, $0, 3 \n\t"
- " .endm \n\t");
+ " .macro _ssnop \n"
+ " sll $0, $0, 1 \n"
+ " .endm \n"
+ " \n"
+ " .macro _ehb \n"
+ " sll $0, $0, 3 \n"
+ " .endm \n");
#ifdef CONFIG_CPU_RM9000
@@ -117,17 +118,21 @@ __asm__(
#define mtc0_tlbw_hazard() \
__asm__ __volatile__( \
- ".set\tmips32\n\t" \
- "_ssnop; _ssnop; _ssnop; _ssnop\n\t" \
- ".set\tmips0")
+ " .set mips32 \n" \
+ " _ssnop \n" \
+ " _ssnop \n" \
+ " _ssnop \n" \
+ " _ssnop \n" \
+ " .set mips0 \n")
#define tlbw_use_hazard() \
__asm__ __volatile__( \
- ".set\tmips32\n\t" \
- "_ssnop; _ssnop; _ssnop; _ssnop\n\t" \
- ".set\tmips0")
-
-#define back_to_back_c0_hazard() do { } while (0)
+ " .set mips32 \n" \
+ " _ssnop \n" \
+ " _ssnop \n" \
+ " _ssnop \n" \
+ " _ssnop \n" \
+ " .set mips0 \n")
#else
@@ -136,15 +141,25 @@ __asm__(
*/
#define mtc0_tlbw_hazard() \
__asm__ __volatile__( \
- ".set noreorder\n\t" \
- "nop; nop; nop; nop; nop; nop;\n\t" \
- ".set reorder\n\t")
+ " .set noreorder \n" \
+ " nop \n" \
+ " nop \n" \
+ " nop \n" \
+ " nop \n" \
+ " nop \n" \
+ " nop \n" \
+ " .set reorder \n")
#define tlbw_use_hazard() \
__asm__ __volatile__( \
- ".set noreorder\n\t" \
- "nop; nop; nop; nop; nop; nop;\n\t" \
- ".set reorder\n\t")
+ " .set noreorder \n" \
+ " nop \n" \
+ " nop \n" \
+ " nop \n" \
+ " nop \n" \
+ " nop \n" \
+ " nop \n" \
+ " .set reorder \n")
#endif
@@ -156,49 +171,26 @@ __asm__(
#ifdef CONFIG_CPU_MIPSR2
-__asm__(
- " .macro\tirq_enable_hazard \n\t"
- " _ehb \n\t"
- " .endm \n\t"
- " \n\t"
- " .macro\tirq_disable_hazard \n\t"
- " _ehb \n\t"
- " .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")
+__asm__(" .macro irq_enable_hazard \n"
+ " _ehb \n"
+ " .endm \n"
+ " \n"
+ " .macro irq_disable_hazard \n"
+ " _ehb \n"
+ " .endm \n");
-#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)
+#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
/*
* R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
*/
__asm__(
- " .macro\tirq_enable_hazard \n\t"
- " .endm \n\t"
- " \n\t"
- " .macro\tirq_disable_hazard \n\t"
- " .endm");
-
-#define irq_enable_hazard() do { } while (0)
-#define irq_disable_hazard() do { } while (0)
-
-#define back_to_back_c0_hazard() do { } while (0)
+ " .macro irq_enable_hazard \n"
+ " .endm \n"
+ " \n"
+ " .macro irq_disable_hazard \n"
+ " .endm \n");
#else
@@ -209,29 +201,63 @@ __asm__(
*/
__asm__(
- " # \n\t"
- " # There is a hazard but we do not care \n\t"
- " # \n\t"
- " .macro\tirq_enable_hazard \n\t"
- " .endm \n\t"
- " \n\t"
- " .macro\tirq_disable_hazard \n\t"
- " _ssnop; _ssnop; _ssnop \n\t"
- " .endm");
+ " # \n"
+ " # There is a hazard but we do not care \n"
+ " # \n"
+ " .macro\tirq_enable_hazard \n"
+ " .endm \n"
+ " \n"
+ " .macro\tirq_disable_hazard \n"
+ " _ssnop \n"
+ " _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() \
- __asm__ __volatile__( \
- "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")
+
+/*
+ * 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
/*
* gcc has a tradition of misscompiling the previous construct using the
diff --git a/include/asm-mips/io.h b/include/asm-mips/io.h
index 8c011aa61af..ba1d7bbc15d 100644
--- a/include/asm-mips/io.h
+++ b/include/asm-mips/io.h
@@ -4,7 +4,7 @@
* for more details.
*
* 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) 2004, 2005 MIPS Technologies, Inc. All rights reserved.
* Author: Maciej W. Rozycki <macro@mips.com>
@@ -103,8 +103,20 @@
*/
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
diff --git a/include/asm-mips/r4kcache.h b/include/asm-mips/r4kcache.h
index 9632c27dad1..0bcb79a58ee 100644
--- a/include/asm-mips/r4kcache.h
+++ b/include/asm-mips/r4kcache.h
@@ -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) \
{ \
- 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 ws_inc = 1UL << current_cpu_data.desc.waybit; \
unsigned long ws_end = current_cpu_data.desc.ways << \
diff --git a/include/asm-mips/sibyte/sb1250.h b/include/asm-mips/sibyte/sb1250.h
index a474c29cd70..b09e16c93ca 100644
--- a/include/asm-mips/sibyte/sb1250.h
+++ b/include/asm-mips/sibyte/sb1250.h
@@ -45,8 +45,8 @@ extern unsigned int soc_type;
extern unsigned int periph_rev;
extern unsigned int zbbus_mhz;
+extern void sb1250_hpt_setup(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_unmask_irq(int cpu, int irq);
extern void sb1250_smp_finish(void);
diff --git a/include/asm-mips/sibyte/sb1250_scd.h b/include/asm-mips/sibyte/sb1250_scd.h
index a667bc14a7c..f4178bdcfcb 100644
--- a/include/asm-mips/sibyte/sb1250_scd.h
+++ b/include/asm-mips/sibyte/sb1250_scd.h
@@ -359,14 +359,15 @@
*/
#define V_SCD_TIMER_FREQ 1000000
+#define V_SCD_TIMER_WIDTH 23
#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 G_SCD_TIMER_INIT(x) _SB_GETVALUE(x,S_SCD_TIMER_INIT,M_SCD_TIMER_INIT)
#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 G_SCD_TIMER_CNT(x) _SB_GETVALUE(x,S_SCD_TIMER_CNT,M_SCD_TIMER_CNT)