summaryrefslogtreecommitdiffstats
path: root/arch/mips/sibyte
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2005-10-31 10:51:57 -0800
committerTony Luck <tony.luck@intel.com>2005-10-31 10:51:57 -0800
commitc7fb577e2a6cb04732541f2dc402bd46747f7558 (patch)
treedf3b1a1922ed13bfbcc45d08650c38beeb1a7bd1 /arch/mips/sibyte
parent9cec58dc138d6fcad9f447a19c8ff69f6540e667 (diff)
parent581c1b14394aee60aff46ea67d05483261ed6527 (diff)
manual update from upstream:
Applied Al's change 06a544971fad0992fe8b92c5647538d573089dd4 to new location of swiotlb.c Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/mips/sibyte')
-rw-r--r--arch/mips/sibyte/Kconfig161
-rw-r--r--arch/mips/sibyte/bcm1480/Makefile5
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c476
-rw-r--r--arch/mips/sibyte/bcm1480/irq_handler.S165
-rw-r--r--arch/mips/sibyte/bcm1480/setup.c136
-rw-r--r--arch/mips/sibyte/bcm1480/smp.c110
-rw-r--r--arch/mips/sibyte/bcm1480/time.c138
-rw-r--r--arch/mips/sibyte/cfe/smp.c14
-rw-r--r--arch/mips/sibyte/sb1250/bcm1250_tbprof.c154
-rw-r--r--arch/mips/sibyte/sb1250/bus_watcher.c2
-rw-r--r--arch/mips/sibyte/sb1250/irq.c121
-rw-r--r--arch/mips/sibyte/sb1250/setup.c4
-rw-r--r--arch/mips/sibyte/sb1250/smp.c18
-rw-r--r--arch/mips/sibyte/sb1250/time.c44
-rw-r--r--arch/mips/sibyte/swarm/rtc_m41t81.c47
-rw-r--r--arch/mips/sibyte/swarm/rtc_xicor1241.c42
-rw-r--r--arch/mips/sibyte/swarm/setup.c41
-rw-r--r--arch/mips/sibyte/swarm/time.c44
18 files changed, 1477 insertions, 245 deletions
diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig
new file mode 100644
index 00000000000..de46f62ac46
--- /dev/null
+++ b/arch/mips/sibyte/Kconfig
@@ -0,0 +1,161 @@
+config SIBYTE_SB1250
+ bool
+ select HW_HAS_PCI
+ select SIBYTE_HAS_LDT
+ select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1120
+ bool
+ select SIBYTE_BCM112X
+ select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1125
+ bool
+ select HW_HAS_PCI
+ select SIBYTE_BCM112X
+ select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1125H
+ bool
+ select HW_HAS_PCI
+ select SIBYTE_BCM112X
+ select SIBYTE_HAS_LDT
+ select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM112X
+ bool
+ select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1x80
+ bool
+ select HW_HAS_PCI
+ select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_BCM1x55
+ bool
+ select HW_HAS_PCI
+ select SIBYTE_SB1xxx_SOC
+
+config SIBYTE_SB1xxx_SOC
+ bool
+ depends on EXPERIMENTAL
+ select DMA_COHERENT
+ select SIBYTE_CFE
+ select SWAP_IO_SPACE
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_64BIT_KERNEL
+
+choice
+ prompt "SiByte SOC Stepping"
+ depends on SIBYTE_SB1xxx_SOC
+
+config CPU_SB1_PASS_1
+ bool "1250 Pass1"
+ depends on SIBYTE_SB1250
+ select CPU_HAS_PREFETCH
+
+config CPU_SB1_PASS_2_1250
+ bool "1250 An"
+ depends on SIBYTE_SB1250
+ select CPU_SB1_PASS_2
+ help
+ Also called BCM1250 Pass 2
+
+config CPU_SB1_PASS_2_2
+ bool "1250 Bn"
+ depends on SIBYTE_SB1250
+ select CPU_HAS_PREFETCH
+ help
+ Also called BCM1250 Pass 2.2
+
+config CPU_SB1_PASS_4
+ bool "1250 Cn"
+ depends on SIBYTE_SB1250
+ select CPU_HAS_PREFETCH
+ help
+ Also called BCM1250 Pass 3
+
+config CPU_SB1_PASS_2_112x
+ bool "112x Hybrid"
+ depends on SIBYTE_BCM112X
+ select CPU_SB1_PASS_2
+
+config CPU_SB1_PASS_3
+ bool "112x An"
+ depends on SIBYTE_BCM112X
+ select CPU_HAS_PREFETCH
+
+endchoice
+
+config CPU_SB1_PASS_2
+ bool
+
+config SIBYTE_HAS_LDT
+ bool
+ depends on PCI && (SIBYTE_SB1250 || SIBYTE_BCM1125H)
+ default y
+
+config SIMULATION
+ bool "Running under simulation"
+ depends on SIBYTE_SB1xxx_SOC
+ help
+ Build a kernel suitable for running under the GDB simulator.
+ Primarily adjusts the kernel's notion of time.
+
+config CONFIG_SB1_CEX_ALWAYS_FATAL
+ bool "All cache exceptions considered fatal (no recovery attempted)"
+ depends on SIBYTE_SB1xxx_SOC
+
+config CONFIG_SB1_CERR_STALL
+ bool "Stall (rather than panic) on fatal cache error"
+ depends on SIBYTE_SB1xxx_SOC
+
+config SIBYTE_CFE
+ bool "Booting from CFE"
+ depends on SIBYTE_SB1xxx_SOC
+ help
+ Make use of the CFE API for enumerating available memory,
+ controlling secondary CPUs, and possibly console output.
+
+config SIBYTE_CFE_CONSOLE
+ bool "Use firmware console"
+ depends on SIBYTE_CFE
+ help
+ Use the CFE API's console write routines during boot. Other console
+ options (VT console, sb1250 duart console, etc.) should not be
+ configured.
+
+config SIBYTE_STANDALONE
+ bool
+ depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE
+ default y
+
+config SIBYTE_STANDALONE_RAM_SIZE
+ int "Memory size (in megabytes)"
+ depends on SIBYTE_STANDALONE
+ default "32"
+
+config SIBYTE_BUS_WATCHER
+ bool "Support for Bus Watcher statistics"
+ depends on SIBYTE_SB1xxx_SOC
+ help
+ Handle and keep statistics on the bus error interrupts (COR_ECC,
+ BAD_ECC, IO_BUS).
+
+config SIBYTE_BW_TRACE
+ bool "Capture bus trace before bus error"
+ depends on SIBYTE_BUS_WATCHER
+ help
+ Run a continuous bus trace, dumping the raw data as soon as
+ a ZBbus error is detected. Cannot work if ZBbus profiling
+ is turned on, and also will interfere with JTAG-based trace
+ buffer activity. Raw buffer data is dumped to console, and
+ must be processed off-line.
+
+config SIBYTE_SB1250_PROF
+ bool "Support for SB1/SOC profiling - SB1/SCD perf counters"
+ depends on SIBYTE_SB1xxx_SOC
+
+config SIBYTE_TBPROF
+ bool "Support for ZBbus profiling"
+ depends on SIBYTE_SB1xxx_SOC
diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile
new file mode 100644
index 00000000000..538d5a51ae9
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/Makefile
@@ -0,0 +1,5 @@
+obj-y := setup.o irq.o irq_handler.o time.o
+
+obj-$(CONFIG_SMP) += smp.o
+
+EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
new file mode 100644
index 00000000000..b2a1ba5d23d
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/errno.h>
+#include <asm/signal.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+#include <asm/sibyte/bcm1480_scd.h>
+
+#include <asm/sibyte/sb1250_uart.h>
+#include <asm/sibyte/sb1250.h>
+
+/*
+ * These are the routines that handle all the low level interrupt stuff.
+ * Actions handled here are: initialization of the interrupt map, requesting of
+ * interrupt lines by handlers, dispatching if interrupts to handlers, probing
+ * for interrupt lines
+ */
+
+
+#define shutdown_bcm1480_irq disable_bcm1480_irq
+static void end_bcm1480_irq(unsigned int irq);
+static void enable_bcm1480_irq(unsigned int irq);
+static void disable_bcm1480_irq(unsigned int irq);
+static unsigned int startup_bcm1480_irq(unsigned int irq);
+static void ack_bcm1480_irq(unsigned int irq);
+#ifdef CONFIG_SMP
+static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask);
+#endif
+
+#ifdef CONFIG_PCI
+extern unsigned long ht_eoi_space;
+#endif
+
+#ifdef CONFIG_KGDB
+#include <asm/gdb-stub.h>
+extern void breakpoint(void);
+static int kgdb_irq;
+#ifdef CONFIG_GDB_CONSOLE
+extern void register_gdb_console(void);
+#endif
+
+/* kgdb is on when configured. Pass "nokgdb" kernel arg to turn it off */
+static int kgdb_flag = 1;
+static int __init nokgdb(char *str)
+{
+ kgdb_flag = 0;
+ return 1;
+}
+__setup("nokgdb", nokgdb);
+
+/* Default to UART1 */
+int kgdb_port = 1;
+#ifdef CONFIG_SIBYTE_SB1250_DUART
+extern char sb1250_duart_present[];
+#endif
+#endif
+
+static struct hw_interrupt_type bcm1480_irq_type = {
+ .typename = "BCM1480-IMR",
+ .startup = startup_bcm1480_irq,
+ .shutdown = shutdown_bcm1480_irq,
+ .enable = enable_bcm1480_irq,
+ .disable = disable_bcm1480_irq,
+ .ack = ack_bcm1480_irq,
+ .end = end_bcm1480_irq,
+#ifdef CONFIG_SMP
+ .set_affinity = bcm1480_set_affinity
+#endif
+};
+
+/* Store the CPU id (not the logical number) */
+int bcm1480_irq_owner[BCM1480_NR_IRQS];
+
+DEFINE_SPINLOCK(bcm1480_imr_lock);
+
+void bcm1480_mask_irq(int cpu, int irq)
+{
+ unsigned long flags;
+ u64 cur_ints,hl_spacing;
+
+ spin_lock_irqsave(&bcm1480_imr_lock, flags);
+ hl_spacing = 0;
+ if ((irq >= BCM1480_NR_IRQS_HALF) && (irq <= BCM1480_NR_IRQS)) {
+ hl_spacing = BCM1480_IMR_HL_SPACING;
+ irq -= BCM1480_NR_IRQS_HALF;
+ }
+ cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
+ cur_ints |= (((u64) 1) << irq);
+ ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
+ spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
+}
+
+void bcm1480_unmask_irq(int cpu, int irq)
+{
+ unsigned long flags;
+ u64 cur_ints,hl_spacing;
+
+ spin_lock_irqsave(&bcm1480_imr_lock, flags);
+ hl_spacing = 0;
+ if ((irq >= BCM1480_NR_IRQS_HALF) && (irq <= BCM1480_NR_IRQS)) {
+ hl_spacing = BCM1480_IMR_HL_SPACING;
+ irq -= BCM1480_NR_IRQS_HALF;
+ }
+ cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
+ cur_ints &= ~(((u64) 1) << irq);
+ ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + hl_spacing));
+ spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
+}
+
+#ifdef CONFIG_SMP
+static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
+{
+ int i = 0, old_cpu, cpu, int_on;
+ u64 cur_ints;
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned long flags;
+ unsigned int irq_dirty;
+
+ i = first_cpu(mask);
+ if (next_cpu(i, mask) <= NR_CPUS) {
+ printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
+ return;
+ }
+
+ /* Convert logical CPU to physical CPU */
+ cpu = cpu_logical_map(i);
+
+ /* Protect against other affinity changers and IMR manipulation */
+ spin_lock_irqsave(&desc->lock, flags);
+ spin_lock(&bcm1480_imr_lock);
+
+ /* Swizzle each CPU's IMR (but leave the IP selection alone) */
+ old_cpu = bcm1480_irq_owner[irq];
+ irq_dirty = irq;
+ if ((irq_dirty >= BCM1480_NR_IRQS_HALF) && (irq_dirty <= BCM1480_NR_IRQS)) {
+ irq_dirty -= BCM1480_NR_IRQS_HALF;
+ }
+
+ int k;
+ for (k=0; k<2; k++) { /* Loop through high and low interrupt mask register */
+ cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(old_cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
+ int_on = !(cur_ints & (((u64) 1) << irq_dirty));
+ if (int_on) {
+ /* If it was on, mask it */
+ cur_ints |= (((u64) 1) << irq_dirty);
+ ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(old_cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
+ }
+ bcm1480_irq_owner[irq] = cpu;
+ if (int_on) {
+ /* unmask for the new CPU */
+ cur_ints = ____raw_readq(IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
+ cur_ints &= ~(((u64) 1) << irq_dirty);
+ ____raw_writeq(cur_ints, IOADDR(A_BCM1480_IMR_MAPPER(cpu) + R_BCM1480_IMR_INTERRUPT_MASK_H + (k*BCM1480_IMR_HL_SPACING)));
+ }
+ }
+ spin_unlock(&bcm1480_imr_lock);
+ spin_unlock_irqrestore(&desc->lock, flags);
+}
+#endif
+
+
+/* Defined in arch/mips/sibyte/bcm1480/irq_handler.S */
+extern void bcm1480_irq_handler(void);
+
+/*****************************************************************************/
+
+static unsigned int startup_bcm1480_irq(unsigned int irq)
+{
+ bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
+
+ return 0; /* never anything pending */
+}
+
+
+static void disable_bcm1480_irq(unsigned int irq)
+{
+ bcm1480_mask_irq(bcm1480_irq_owner[irq], irq);
+}
+
+static void enable_bcm1480_irq(unsigned int irq)
+{
+ bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
+}
+
+
+static void ack_bcm1480_irq(unsigned int irq)
+{
+ u64 pending;
+ unsigned int irq_dirty;
+
+ /*
+ * If the interrupt was an HT interrupt, now is the time to
+ * clear it. NOTE: we assume the HT bridge was set up to
+ * deliver the interrupts to all CPUs (which makes affinity
+ * changing easier for us)
+ */
+ irq_dirty = irq;
+ if ((irq_dirty >= BCM1480_NR_IRQS_HALF) && (irq_dirty <= BCM1480_NR_IRQS)) {
+ irq_dirty -= BCM1480_NR_IRQS_HALF;
+ }
+ int k;
+ for (k=0; k<2; k++) { /* Loop through high and low LDT interrupts */
+ pending = __raw_readq(IOADDR(A_BCM1480_IMR_REGISTER(bcm1480_irq_owner[irq],
+ R_BCM1480_IMR_LDT_INTERRUPT_H + (k*BCM1480_IMR_HL_SPACING))));
+ pending &= ((u64)1 << (irq_dirty));
+ if (pending) {
+#ifdef CONFIG_SMP
+ int i;
+ for (i=0; i<NR_CPUS; i++) {
+ /*
+ * Clear for all CPUs so an affinity switch
+ * doesn't find an old status
+ */
+ __raw_writeq(pending, IOADDR(A_BCM1480_IMR_REGISTER(cpu_logical_map(i),
+ R_BCM1480_IMR_LDT_INTERRUPT_CLR_H + (k*BCM1480_IMR_HL_SPACING))));
+ }
+#else
+ __raw_writeq(pending, IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_LDT_INTERRUPT_CLR_H + (k*BCM1480_IMR_HL_SPACING))));
+#endif
+
+ /*
+ * Generate EOI. For Pass 1 parts, EOI is a nop. For
+ * Pass 2, the LDT world may be edge-triggered, but
+ * this EOI shouldn't hurt. If they are
+ * level-sensitive, the EOI is required.
+ */
+#ifdef CONFIG_PCI
+ if (ht_eoi_space)
+ *(uint32_t *)(ht_eoi_space+(irq<<16)+(7<<2)) = 0;
+#endif
+ }
+ }
+ bcm1480_mask_irq(bcm1480_irq_owner[irq], irq);
+}
+
+
+static void end_bcm1480_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+ bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
+ }
+}
+
+
+void __init init_bcm1480_irqs(void)
+{
+ int i;
+
+ for (i = 0; i < NR_IRQS; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ if (i < BCM1480_NR_IRQS) {
+ irq_desc[i].handler = &bcm1480_irq_type;
+ bcm1480_irq_owner[i] = 0;
+ } else {
+ irq_desc[i].handler = &no_irq_type;
+ }
+ }
+}
+
+
+static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id,
+ struct pt_regs *regs)
+{
+ return IRQ_NONE;
+}
+
+static struct irqaction bcm1480_dummy_action = {
+ .handler = bcm1480_dummy_handler,
+ .flags = 0,
+ .mask = CPU_MASK_NONE,
+ .name = "bcm1480-private",
+ .next = NULL,
+ .dev_id = 0
+};
+
+int bcm1480_steal_irq(int irq)
+{
+ irq_desc_t *desc = irq_desc + irq;
+ unsigned long flags;
+ int retval = 0;
+
+ if (irq >= BCM1480_NR_IRQS)
+ return -EINVAL;
+
+ spin_lock_irqsave(&desc->lock,flags);
+ /* Don't allow sharing at all for these */
+ if (desc->action != NULL)
+ retval = -EBUSY;
+ else {
+ desc->action = &bcm1480_dummy_action;
+ desc->depth = 0;
+ }
+ spin_unlock_irqrestore(&desc->lock,flags);
+ return 0;
+}
+
+/*
+ * init_IRQ is called early in the boot sequence from init/main.c. It
+ * is responsible for setting up the interrupt mapper and installing the
+ * handler that will be responsible for dispatching interrupts to the
+ * "right" place.
+ */
+/*
+ * For now, map all interrupts to IP[2]. We could save
+ * some cycles by parceling out system interrupts to different
+ * IP lines, but keep it simple for bringup. We'll also direct
+ * all interrupts to a single CPU; we should probably route
+ * PCI and LDT to one cpu and everything else to the other
+ * to balance the load a bit.
+ *
+ * On the second cpu, everything is set to IP5, which is
+ * ignored, EXCEPT the mailbox interrupt. That one is
+ * set to IP[2] so it is handled. This is needed so we
+ * can do cross-cpu function calls, as requred by SMP
+ */
+
+#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0
+#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1
+#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2
+#define IMR_IP5_VAL K_BCM1480_INT_MAP_I3
+#define IMR_IP6_VAL K_BCM1480_INT_MAP_I4
+
+void __init arch_init_irq(void)
+{
+
+ unsigned int i, cpu;
+ u64 tmp;
+ unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
+ STATUSF_IP1 | STATUSF_IP0;
+
+ /* Default everything to IP2 */
+ /* Start with _high registers which has no bit 0 interrupt source */
+ for (i = 1; i < BCM1480_NR_IRQS_HALF; i++) { /* was I0 */
+ for (cpu = 0; cpu < 4; cpu++) {
+ __raw_writeq(IMR_IP2_VAL,
+ IOADDR(A_BCM1480_IMR_REGISTER(cpu,
+ R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) + (i << 3)));
+ }
+ }
+
+ /* Now do _low registers */
+ for (i = 0; i < BCM1480_NR_IRQS_HALF; i++) {
+ for (cpu = 0; cpu < 4; cpu++) {
+ __raw_writeq(IMR_IP2_VAL,
+ IOADDR(A_BCM1480_IMR_REGISTER(cpu,
+ R_BCM1480_IMR_INTERRUPT_MAP_BASE_L) + (i << 3)));
+ }
+ }
+
+ init_bcm1480_irqs();
+
+ /*
+ * Map the high 16 bits of mailbox_0 registers to IP[3], for
+ * inter-cpu messages
+ */
+ /* Was I1 */
+ for (cpu = 0; cpu < 4; cpu++) {
+ __raw_writeq(IMR_IP3_VAL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
+ (K_BCM1480_INT_MBOX_0_0 << 3)));
+ }
+
+
+ /* Clear the mailboxes. The firmware may leave them dirty */
+ for (cpu = 0; cpu < 4; cpu++) {
+ __raw_writeq(0xffffffffffffffffULL,
+ IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_MAILBOX_0_CLR_CPU)));
+ __raw_writeq(0xffffffffffffffffULL,
+ IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_MAILBOX_1_CLR_CPU)));
+ }
+
+
+ /* Mask everything except the high 16 bit of mailbox_0 registers for all cpus */
+ tmp = ~((u64) 0) ^ ( (((u64) 1) << K_BCM1480_INT_MBOX_0_0));
+ for (cpu = 0; cpu < 4; cpu++) {
+ __raw_writeq(tmp, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MASK_H)));
+ }
+ tmp = ~((u64) 0);
+ for (cpu = 0; cpu < 4; cpu++) {
+ __raw_writeq(tmp, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MASK_L)));
+ }
+
+ bcm1480_steal_irq(K_BCM1480_INT_MBOX_0_0);
+
+ /*
+ * Note that the timer interrupts are also mapped, but this is
+ * done in bcm1480_time_init(). Also, the profiling driver
+ * does its own management of IP7.
+ */
+
+#ifdef CONFIG_KGDB
+ imask |= STATUSF_IP6;
+#endif
+ /* Enable necessary IPs, disable the rest */
+ change_c0_status(ST0_IM, imask);
+ set_except_vector(0, bcm1480_irq_handler);
+
+#ifdef CONFIG_KGDB
+ if (kgdb_flag) {
+ kgdb_irq = K_BCM1480_INT_UART_0 + kgdb_port;
+
+#ifdef CONFIG_SIBYTE_SB1250_DUART
+ sb1250_duart_present[kgdb_port] = 0;
+#endif
+ /* Setup uart 1 settings, mapper */
+ /* QQQ FIXME */
+ __raw_writeq(M_DUART_IMR_BRK, IO_SPACE_BASE + A_DUART_IMRREG(kgdb_port));
+
+ bcm1480_steal_irq(kgdb_irq);
+ __raw_writeq(IMR_IP6_VAL,
+ IO_SPACE_BASE + A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H) +
+ (kgdb_irq<<3));
+ bcm1480_unmask_irq(0, kgdb_irq);
+
+#ifdef CONFIG_GDB_CONSOLE
+ register_gdb_console();
+#endif
+ prom_printf("Waiting for GDB on UART port %d\n", kgdb_port);
+ set_debug_traps();
+ breakpoint();
+ }
+#endif
+}
+
+#ifdef CONFIG_KGDB
+
+#include <linux/delay.h>
+
+#define duart_out(reg, val) csr_out32(val, IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+#define duart_in(reg) csr_in32(IOADDR(A_DUART_CHANREG(kgdb_port,reg)))
+
+void bcm1480_kgdb_interrupt(struct pt_regs *regs)
+{
+ /*
+ * Clear break-change status (allow some time for the remote
+ * host to stop the break, since we would see another
+ * interrupt on the end-of-break too)
+ */
+ kstat.irqs[smp_processor_id()][kgdb_irq]++;
+ mdelay(500);
+ duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT |
+ M_DUART_RX_EN | M_DUART_TX_EN);
+ set_async_breakpoint(&regs->cp0_epc);
+}
+
+#endif /* CONFIG_KGDB */
diff --git a/arch/mips/sibyte/bcm1480/irq_handler.S b/arch/mips/sibyte/bcm1480/irq_handler.S
new file mode 100644
index 00000000000..408db88d050
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/irq_handler.S
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * bcm1480_irq_handler() is the routine that is actually called when an
+ * interrupt occurs. It is installed as the exception vector handler in
+ * init_IRQ() in arch/mips/sibyte/bcm1480/irq.c
+ *
+ * In the handle we figure out which interrupts need handling, and use that
+ * to call the dispatcher, which will take care of actually calling
+ * registered handlers
+ *
+ * Note that we take care of all raised interrupts in one go at the handler.
+ * This is more BSDish than the Indy code, and also, IMHO, more sane.
+ */
+#include <linux/config.h>
+
+#include <asm/addrspace.h>
+#include <asm/asm.h>
+#include <asm/mipsregs.h>
+#include <asm/regdef.h>
+#include <asm/stackframe.h>
+#include <asm/sibyte/sb1250_defs.h>
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+
+/*
+ * What a pain. We have to be really careful saving the upper 32 bits of any
+ * register across function calls if we don't want them trashed--since were
+ * running in -o32, the calling routing never saves the full 64 bits of a
+ * register across a function call. Being the interrupt handler, we're
+ * guaranteed that interrupts are disabled during this code so we don't have
+ * to worry about random interrupts blasting the high 32 bits.
+ */
+
+ .text
+ .set push
+ .set noreorder
+ .set noat
+ .set mips64
+ #.set mips4
+ .align 5
+ NESTED(bcm1480_irq_handler, PT_SIZE, sp)
+ SAVE_ALL
+ CLI
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+ /* Set compare to count to silence count/compare timer interrupts */
+ mfc0 t1, CP0_COUNT
+ mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */
+#endif
+ /* Read cause */
+ mfc0 s0, CP0_CAUSE
+
+#ifdef CONFIG_SIBYTE_BCM1480_PROF
+ /* Cpu performance counter interrupt is routed to IP[7] */
+ andi t1, s0, CAUSEF_IP7
+ beqz t1, 0f
+ srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */
+ and t1, t1, 0x4 /* mask to get just BD bit */
+#ifdef CONFIG_MIPS64
+ dmfc0 a0, CP0_EPC
+ daddu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
+#else
+ mfc0 a0, CP0_EPC
+ addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */
+#endif
+ jal sbprof_cpu_intr
+ nop
+ j ret_from_irq
+ nop
+0:
+#endif
+
+ /* Timer interrupt is routed to IP[4] */
+ andi t1, s0, CAUSEF_IP4
+ beqz t1, 1f
+ nop
+ jal bcm1480_timer_interrupt
+ move a0, sp /* Pass the registers along */
+ j ret_from_irq
+ nop /* delay slot */
+1:
+
+#ifdef CONFIG_SMP
+ /* Mailbox interrupt is routed to IP[3] */
+ andi t1, s0, CAUSEF_IP3
+ beqz t1, 2f
+ nop
+ jal bcm1480_mailbox_interrupt
+ move a0, sp
+ j ret_from_irq
+ nop /* delay slot */
+2:
+#endif
+
+#ifdef CONFIG_KGDB
+ /* KGDB (uart 1) interrupt is routed to IP[6] */
+ andi t1, s0, CAUSEF_IP6
+ beqz t1, 3f
+ nop /* delay slot */
+ jal bcm1480_kgdb_interrupt
+ move a0, sp
+ j ret_from_irq
+ nop /* delay slot */
+3:
+#endif
+
+ and t1, s0, CAUSEF_IP2
+ beqz t1, 9f
+ nop
+
+ /*
+ * Default...we've hit an IP[2] interrupt, which means we've got
+ * to check the 1480 interrupt registers to figure out what to do
+ * Need to detect which CPU we're on, now that smp_affinity is
+ * supported.
+ */
+ PTR_LA v0, CKSEG1 + A_BCM1480_IMR_CPU0_BASE
+#ifdef CONFIG_SMP
+ lw t1, TI_CPU($28)
+ sll t1, t1, BCM1480_IMR_REGISTER_SPACING_SHIFT
+ addu v0, v0, t1
+#endif
+
+ /* Read IP[2] status (get both high and low halves of status) */
+ ld s0, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H(v0)
+ ld s1, R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L(v0)
+
+ move s2, zero /* intr number */
+ li s3, 64
+
+ beqz s0, 9f /* No interrupts. Return. */
+ move a1, sp
+
+ xori s4, s0, 1 /* if s0 (_H) == 1, it's a low intr, so... */
+ movz s2, s3, s4 /* start the intr number at 64, and */
+ movz s0, s1, s4 /* look at the low status value. */
+
+ dclz s1, s0 /* Find the next interrupt. */
+ dsubu a0, zero, s1
+ daddiu a0, a0, 63
+ jal do_IRQ
+ daddu a0, a0, s2
+
+9: j ret_from_irq
+ nop
+
+ .set pop
+ END(bcm1480_irq_handler)
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
new file mode 100644
index 00000000000..d90a0b87874
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2000,2001,2002,2003,2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/string.h>
+
+#include <asm/bootinfo.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_scd.h>
+#include <asm/sibyte/sb1250_scd.h>
+
+unsigned int sb1_pass;
+unsigned int soc_pass;
+unsigned int soc_type;
+unsigned int periph_rev;
+unsigned int zbbus_mhz;
+
+static unsigned int part_type;
+
+static char *soc_str;
+static char *pass_str;
+
+static inline int setup_bcm1x80_bcm1x55(void);
+
+/* Setup code likely to be common to all SiByte platforms */
+
+static inline int sys_rev_decode(void)
+{
+ int ret = 0;
+
+ switch (soc_type) {
+ case K_SYS_SOC_TYPE_BCM1x80:
+ if (part_type == K_SYS_PART_BCM1480)
+ soc_str = "BCM1480";
+ else if (part_type == K_SYS_PART_BCM1280)
+ soc_str = "BCM1280";
+ else
+ soc_str = "BCM1x80";
+ ret = setup_bcm1x80_bcm1x55();
+ break;
+
+ case K_SYS_SOC_TYPE_BCM1x55:
+ if (part_type == K_SYS_PART_BCM1455)
+ soc_str = "BCM1455";
+ else if (part_type == K_SYS_PART_BCM1255)
+ soc_str = "BCM1255";
+ else
+ soc_str = "BCM1x55";
+ ret = setup_bcm1x80_bcm1x55();
+ break;
+
+ default:
+ prom_printf("Unknown part type %x\n", part_type);
+ ret = 1;
+ break;
+ }
+ return ret;
+}
+
+static inline int setup_bcm1x80_bcm1x55(void)
+{
+ int ret = 0;
+
+ switch (soc_pass) {
+ case K_SYS_REVISION_BCM1480_S0:
+ periph_rev = 1;
+ pass_str = "S0 (pass1)";
+ break;
+ case K_SYS_REVISION_BCM1480_A1:
+ periph_rev = 1;
+ pass_str = "A1 (pass1)";
+ break;
+ case K_SYS_REVISION_BCM1480_A2:
+ periph_rev = 1;
+ pass_str = "A2 (pass1)";
+ break;
+ case K_SYS_REVISION_BCM1480_A3:
+ periph_rev = 1;
+ pass_str = "A3 (pass1)";
+ break;
+ case K_SYS_REVISION_BCM1480_B0:
+ periph_rev = 1;
+ pass_str = "B0 (pass2)";
+ break;
+ default:
+ prom_printf("Unknown %s rev %x\n", soc_str, soc_pass);
+ periph_rev = 1;
+ pass_str = "Unknown Revision";
+ break;
+ }
+ return ret;
+}
+
+void bcm1480_setup(void)
+{
+ uint64_t sys_rev;
+ int plldiv;
+
+ sb1_pass = read_c0_prid() & 0xff;
+ sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
+ soc_type = SYS_SOC_TYPE(sys_rev);
+ part_type = G_SYS_PART(sys_rev);
+ soc_pass = G_SYS_REVISION(sys_rev);
+
+ if (sys_rev_decode()) {
+ prom_printf("Restart after failure to identify SiByte chip\n");
+ machine_restart(NULL);
+ }
+
+ plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
+ zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
+
+ prom_printf("Broadcom SiByte %s %s @ %d MHz (SB-1A rev %d)\n",
+ soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
+ prom_printf("Board type: %s\n", get_system_type());
+}
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
new file mode 100644
index 00000000000..584a4b33faa
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2001,2002,2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+
+extern void smp_call_function_interrupt(void);
+
+/*
+ * These are routines for dealing with the bcm1480 smp capabilities
+ * independent of board/firmware
+ */
+
+static void *mailbox_0_set_regs[] = {
+ IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
+ IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
+ IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
+ IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_SET_CPU),
+};
+
+static void *mailbox_0_clear_regs[] = {
+ IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
+ IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
+ IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
+ IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CLR_CPU),
+};
+
+static void *mailbox_0_regs[] = {
+ IOADDR(A_BCM1480_IMR_CPU0_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
+ IOADDR(A_BCM1480_IMR_CPU1_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
+ IOADDR(A_BCM1480_IMR_CPU2_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
+ IOADDR(A_BCM1480_IMR_CPU3_BASE + R_BCM1480_IMR_MAILBOX_0_CPU),
+};
+
+/*
+ * SMP init and finish on secondary CPUs
+ */
+void bcm1480_smp_init(void)
+{
+ unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
+ STATUSF_IP1 | STATUSF_IP0;
+
+ /* Set interrupt mask, but don't enable */
+ change_c0_status(ST0_IM, imask);
+}
+
+void bcm1480_smp_finish(void)
+{
+ extern void bcm1480_time_init(void);
+ bcm1480_time_init();
+ local_irq_enable();
+}
+
+/*
+ * These are routines for dealing with the sb1250 smp capabilities
+ * independent of board/firmware
+ */
+
+/*
+ * Simple enough; everything is set up, so just poke the appropriate mailbox
+ * register, and we should be set
+ */
+void core_send_ipi(int cpu, unsigned int action)
+{
+ __raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]);
+}
+
+void bcm1480_mailbox_interrupt(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+ unsigned int action;
+
+ kstat_this_cpu.irqs[K_BCM1480_INT_MBOX_0_0]++;
+ /* Load the mailbox register to figure out what we're supposed to do */
+ action = (__raw_readq(mailbox_0_regs[cpu]) >> 48) & 0xffff;
+
+ /* Clear the mailbox to clear the interrupt */
+ __raw_writeq(((u64)action)<<48, mailbox_0_clear_regs[cpu]);
+
+ /*
+ * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
+ * interrupt will do the reschedule for us
+ */
+
+ if (action & SMP_CALL_FUNCTION)
+ smp_call_function_interrupt();
+}
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
new file mode 100644
index 00000000000..e545752695a
--- /dev/null
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2000,2001,2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * These are routines to set up and handle interrupts from the
+ * bcm1480 general purpose timer 0. We're using the timer as a
+ * system clock, so we set it up to run at 100 Hz. On every
+ * interrupt, we update our idea of what the time of day is,
+ * then call do_timer() in the architecture-independent kernel
+ * code to do general bookkeeping (e.g. update jiffies, run
+ * bottom halves, etc.)
+ */
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/irq.h>
+#include <asm/ptrace.h>
+#include <asm/addrspace.h>
+#include <asm/time.h>
+#include <asm/io.h>
+
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/bcm1480_int.h>
+#include <asm/sibyte/bcm1480_scd.h>
+
+#include <asm/sibyte/sb1250.h>
+
+
+#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0
+#define IMR_IP3_VAL K_BCM1480_INT_MAP_I1
+#define IMR_IP4_VAL K_BCM1480_INT_MAP_I2
+
+extern int bcm1480_steal_irq(int irq);
+
+void bcm1480_time_init(void)
+{
+ int cpu = smp_processor_id();
+ int irq = K_BCM1480_INT_TIMER_0+cpu;
+
+ /* Only have 4 general purpose timers */
+ if (cpu > 3) {
+ BUG();
+ }
+
+ if (!cpu) {
+ /* Use our own gettimeoffset() routine */
+ do_gettimeoffset = bcm1480_gettimeoffset;
+ }
+
+ bcm1480_mask_irq(cpu, irq);
+
+ /* Map the timer interrupt to ip[4] of this cpu */
+ __raw_writeq(IMR_IP4_VAL, IOADDR(A_BCM1480_IMR_REGISTER(cpu, R_BCM1480_IMR_INTERRUPT_MAP_BASE_H)
+ + (irq<<3)));
+
+ /* the general purpose timer ticks at 1 Mhz independent of the rest of the system */
+ /* Disable the timer and set up the count */
+ __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+ __raw_writeq(
+#ifndef CONFIG_SIMULATION
+ 1000000/HZ
+#else
+ 50000/HZ
+#endif
+ , IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
+
+ /* Set the timer running */
+ __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+
+ bcm1480_unmask_irq(cpu, irq);
+ bcm1480_steal_irq(irq);
+ /*
+ * This interrupt is "special" in that it doesn't use the request_irq
+ * way to hook the irq line. The timer interrupt is initialized early
+ * enough to make this a major pain, and it's also firing enough to
+ * warrant a bit of special case code. bcm1480_timer_interrupt is
+ * called directly from irq_handler.S when IP[4] is set during an
+ * interrupt
+ */
+}
+
+#include <asm/sibyte/sb1250.h>
+
+void bcm1480_timer_interrupt(struct pt_regs *regs)
+{
+ int cpu = smp_processor_id();
+ int irq = K_BCM1480_INT_TIMER_0+cpu;
+
+ /* Reset the timer */
+ __raw_writeq(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+
+ /*
+ * CPU 0 handles the global timer interrupt job
+ */
+ if (cpu == 0) {
+ ll_timer_interrupt(irq, regs);
+ }
+
+ /*
+ * every CPU should do profiling and process accouting
+ */
+ ll_local_timer_interrupt(irq, 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.
+ */
+unsigned long bcm1480_gettimeoffset(void)
+{
+ unsigned long count =
+ __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
+
+ return 1000000/HZ - count;
+}
diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c
index e44ce1a9eea..e8485124b8f 100644
--- a/arch/mips/sibyte/cfe/smp.c
+++ b/arch/mips/sibyte/cfe/smp.c
@@ -70,8 +70,15 @@ void prom_boot_secondary(int cpu, struct task_struct *idle)
*/
void prom_init_secondary(void)
{
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ extern void bcm1480_smp_init(void);
+ bcm1480_smp_init();
+#elif defined(CONFIG_SIBYTE_SB1250)
extern void sb1250_smp_init(void);
sb1250_smp_init();
+#else
+#error invalid SMP configuration
+#endif
}
/*
@@ -80,8 +87,15 @@ void prom_init_secondary(void)
*/
void prom_smp_finish(void)
{
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ extern void bcm1480_smp_finish(void);
+ bcm1480_smp_finish();
+#elif defined(CONFIG_SIBYTE_SB1250)
extern void sb1250_smp_finish(void);
sb1250_smp_finish();
+#else
+#error invalid SMP configuration
+#endif
}
/*
diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
index 7f813ae9eaf..992e0d8dbb6 100644
--- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
+++ b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
@@ -28,6 +28,8 @@
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/reboot.h>
+#include <linux/smp_lock.h>
+#include <linux/wait.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250.h>
@@ -64,24 +66,25 @@ static void arm_tb(void)
u_int64_t tb_options = M_SCD_TRACE_CFG_FREEZE_FULL;
/* Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to
trigger start of trace. XXX vary sampling period */
- bus_writeq(0, IOADDR(A_SCD_PERF_CNT_1));
- scdperfcnt = bus_readq(IOADDR(A_SCD_PERF_CNT_CFG));
+ __raw_writeq(0, IOADDR(A_SCD_PERF_CNT_1));
+ scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
/* Unfortunately, in Pass 2 we must clear all counters to knock down
a previous interrupt request. This means that bus profiling
requires ALL of the SCD perf counters. */
- bus_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) | // keep counters 0,2,3 as is
- M_SPC_CFG_ENABLE | // enable counting
- M_SPC_CFG_CLEAR | // clear all counters
- V_SPC_CFG_SRC1(1), // counter 1 counts cycles
- IOADDR(A_SCD_PERF_CNT_CFG));
- bus_writeq(next, IOADDR(A_SCD_PERF_CNT_1));
+ __raw_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) |
+ // keep counters 0,2,3 as is
+ M_SPC_CFG_ENABLE | // enable counting
+ M_SPC_CFG_CLEAR | // clear all counters
+ V_SPC_CFG_SRC1(1), // counter 1 counts cycles
+ IOADDR(A_SCD_PERF_CNT_CFG));
+ __raw_writeq(next, IOADDR(A_SCD_PERF_CNT_1));
/* Reset the trace buffer */
- bus_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+ __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
#if 0 && defined(M_SCD_TRACE_CFG_FORCECNT)
/* XXXKW may want to expose control to the data-collector */
tb_options |= M_SCD_TRACE_CFG_FORCECNT;
#endif
- bus_writeq(tb_options, IOADDR(A_SCD_TRACE_CFG));
+ __raw_writeq(tb_options, IOADDR(A_SCD_TRACE_CFG));
sbp.tb_armed = 1;
}
@@ -93,23 +96,30 @@ static irqreturn_t sbprof_tb_intr(int irq, void *dev_id, struct pt_regs *regs)
/* XXX should use XKPHYS to make writes bypass L2 */
u_int64_t *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++];
/* Read out trace */
- bus_writeq(M_SCD_TRACE_CFG_START_READ, IOADDR(A_SCD_TRACE_CFG));
+ __raw_writeq(M_SCD_TRACE_CFG_START_READ,
+ IOADDR(A_SCD_TRACE_CFG));
__asm__ __volatile__ ("sync" : : : "memory");
/* Loop runs backwards because bundles are read out in reverse order */
for (i = 256 * 6; i > 0; i -= 6) {
// Subscripts decrease to put bundle in the order
// t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi
- p[i-1] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 hi
- p[i-2] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t2 lo
- p[i-3] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 hi
- p[i-4] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t1 lo
- p[i-5] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 hi
- p[i-6] = bus_readq(IOADDR(A_SCD_TRACE_READ)); // read t0 lo
+ p[i - 1] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+ // read t2 hi
+ p[i - 2] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+ // read t2 lo
+ p[i - 3] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+ // read t1 hi
+ p[i - 4] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+ // read t1 lo
+ p[i - 5] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+ // read t0 hi
+ p[i - 6] = __raw_readq(IOADDR(A_SCD_TRACE_READ));
+ // read t0 lo
}
if (!sbp.tb_enable) {
DBG(printk(DEVNAME ": tb_intr shutdown\n"));
- bus_writeq(M_SCD_TRACE_CFG_RESET,
- IOADDR(A_SCD_TRACE_CFG));
+ __raw_writeq(M_SCD_TRACE_CFG_RESET,
+ IOADDR(A_SCD_TRACE_CFG));
sbp.tb_armed = 0;
wake_up(&sbp.tb_sync);
} else {
@@ -118,7 +128,7 @@ static irqreturn_t sbprof_tb_intr(int irq, void *dev_id, struct pt_regs *regs)
} else {
/* No more trace buffer samples */
DBG(printk(DEVNAME ": tb_intr full\n"));
- bus_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+ __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
sbp.tb_armed = 0;
if (!sbp.tb_enable) {
wake_up(&sbp.tb_sync);
@@ -152,13 +162,11 @@ int sbprof_zbprof_start(struct file *filp)
return -EBUSY;
}
/* Make sure there isn't a perf-cnt interrupt waiting */
- scdperfcnt = bus_readq(IOADDR(A_SCD_PERF_CNT_CFG));
+ scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
/* Disable and clear counters, override SRC_1 */
- bus_writeq((scdperfcnt & ~(M_SPC_CFG_SRC1 | M_SPC_CFG_ENABLE)) |
- M_SPC_CFG_ENABLE |
- M_SPC_CFG_CLEAR |
- V_SPC_CFG_SRC1(1),
- IOADDR(A_SCD_PERF_CNT_CFG));
+ __raw_writeq((scdperfcnt & ~(M_SPC_CFG_SRC1 | M_SPC_CFG_ENABLE)) |
+ M_SPC_CFG_ENABLE | M_SPC_CFG_CLEAR | V_SPC_CFG_SRC1(1),
+ IOADDR(A_SCD_PERF_CNT_CFG));
/* We grab this interrupt to prevent others from trying to use
it, even though we don't want to service the interrupts
@@ -172,55 +180,55 @@ int sbprof_zbprof_start(struct file *filp)
/* I need the core to mask these, but the interrupt mapper to
pass them through. I am exploiting my knowledge that
cp0_status masks out IP[5]. krw */
- bus_writeq(K_INT_MAP_I3,
- IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
- (K_INT_PERF_CNT << 3)));
+ __raw_writeq(K_INT_MAP_I3,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+ (K_INT_PERF_CNT << 3)));
/* Initialize address traps */
- bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_0));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_1));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_2));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_UP_3));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_0));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_1));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_2));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_UP_3));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_0));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_1));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_2));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_3));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_0));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_1));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_2));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_DOWN_3));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_0));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_1));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_2));
- bus_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_0));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_1));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_2));
+ __raw_writeq(0, IOADDR(A_ADDR_TRAP_CFG_3));
/* Initialize Trace Event 0-7 */
// when interrupt
- bus_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0));
- bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1));
- bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2));
- bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_3));
- bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_4));
- bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_5));
- bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_6));
- bus_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7));
+ __raw_writeq(M_SCD_TREVT_INTERRUPT, IOADDR(A_SCD_TRACE_EVENT_0));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_1));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_2));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_3));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_4));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_5));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_6));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_EVENT_7));
/* Initialize Trace Sequence 0-7 */
// Start on event 0 (interrupt)
- bus_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff,
- IOADDR(A_SCD_TRACE_SEQUENCE_0));
+ __raw_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff,
+ IOADDR(A_SCD_TRACE_SEQUENCE_0));
// dsamp when d used | asamp when a used
- bus_writeq(M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
- K_SCD_TRSEQ_TRIGGER_ALL,
- IOADDR(A_SCD_TRACE_SEQUENCE_1));
- bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_2));
- bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_3));
- bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_4));
- bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_5));
- bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_6));
- bus_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7));
+ __raw_writeq(M_SCD_TRSEQ_ASAMPLE | M_SCD_TRSEQ_DSAMPLE |
+ K_SCD_TRSEQ_TRIGGER_ALL,
+ IOADDR(A_SCD_TRACE_SEQUENCE_1));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_2));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_3));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_4));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_5));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_6));
+ __raw_writeq(0, IOADDR(A_SCD_TRACE_SEQUENCE_7));
/* Now indicate the PERF_CNT interrupt as a trace-relevant interrupt */
- bus_writeq((1ULL << K_INT_PERF_CNT),
- IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)));
+ __raw_writeq(1ULL << K_INT_PERF_CNT,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)));
arm_tb();
@@ -231,6 +239,7 @@ int sbprof_zbprof_start(struct file *filp)
int sbprof_zbprof_stop(void)
{
+ DEFINE_WAIT(wait);
DBG(printk(DEVNAME ": stopping\n"));
if (sbp.tb_enable) {
@@ -240,7 +249,9 @@ int sbprof_zbprof_stop(void)
this sleep happens. */
if (sbp.tb_armed) {
DBG(printk(DEVNAME ": wait for disarm\n"));
- interruptible_sleep_on(&sbp.tb_sync);
+ prepare_to_wait(&sbp.tb_sync, &wait, TASK_INTERRUPTIBLE);
+ schedule();
+ finish_wait(&sbp.tb_sync, &wait);
DBG(printk(DEVNAME ": disarm complete\n"));
}
free_irq(K_INT_TRACE_FREEZE, &sbp);
@@ -333,13 +344,13 @@ static ssize_t sbprof_tb_read(struct file *filp, char *buf,
return count;
}
-static int sbprof_tb_ioctl(struct inode *inode,
- struct file *filp,
- unsigned int command,
- unsigned long arg)
+static long sbprof_tb_ioctl(struct file *filp,
+ unsigned int command,
+ unsigned long arg)
{
int error = 0;
+ lock_kernel();
switch (command) {
case SBPROF_ZBSTART:
error = sbprof_zbprof_start(filp);
@@ -348,13 +359,17 @@ static int sbprof_tb_ioctl(struct inode *inode,
error = sbprof_zbprof_stop();
break;
case SBPROF_ZBWAITFULL:
- interruptible_sleep_on(&sbp.tb_read);
+ DEFINE_WAIT(wait);
+ prepare_to_wait(&sbp.tb_read, &wait, TASK_INTERRUPTIBLE);
+ schedule();
+ finish_wait(&sbp.tb_read, &wait);
/* XXXKW check if interrupted? */
return put_user(TB_FULL, (int *) arg);
default:
error = -EINVAL;
break;
}
+ unlock_kernel();
return error;
}
@@ -364,7 +379,8 @@ static struct file_operations sbprof_tb_fops = {
.open = sbprof_tb_open,
.release = sbprof_tb_release,
.read = sbprof_tb_read,
- .ioctl = sbprof_tb_ioctl,
+ .unlocked_ioctl = sbprof_tb_ioctl,
+ .compat_ioctl = sbprof_tb_ioctl,
.mmap = NULL,
};
diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c
index 1a97e3127ae..482dee054e6 100644
--- a/arch/mips/sibyte/sb1250/bus_watcher.c
+++ b/arch/mips/sibyte/sb1250/bus_watcher.c
@@ -189,7 +189,7 @@ static irqreturn_t sibyte_bw_int(int irq, void *data, struct pt_regs *regs)
for (i=0; i<256*6; i++)
printk("%016llx\n",
- (unsigned long long)bus_readq(IOADDR(A_SCD_TRACE_READ)));
+ (long long)__raw_readq(IOADDR(A_SCD_TRACE_READ)));
csr_out32(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
csr_out32(M_SCD_TRACE_CFG_START, IOADDR(A_SCD_TRACE_CFG));
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 2725b263cce..589537bfcc3 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -53,7 +53,7 @@ static void disable_sb1250_irq(unsigned int irq);
static unsigned int startup_sb1250_irq(unsigned int irq);
static void ack_sb1250_irq(unsigned int irq);
#ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, unsigned long mask);
+static void sb1250_set_affinity(unsigned int irq, cpumask_t mask);
#endif
#ifdef CONFIG_SIBYTE_HAS_LDT
@@ -71,17 +71,15 @@ extern char sb1250_duart_present[];
#endif
static struct hw_interrupt_type sb1250_irq_type = {
- "SB1250-IMR",
- startup_sb1250_irq,
- shutdown_sb1250_irq,
- enable_sb1250_irq,
- disable_sb1250_irq,
- ack_sb1250_irq,
- end_sb1250_irq,
+ .typename = "SB1250-IMR",
+ .startup = startup_sb1250_irq,
+ .shutdown = shutdown_sb1250_irq,
+ .enable = enable_sb1250_irq,
+ .disable = disable_sb1250_irq,
+ .ack = ack_sb1250_irq,
+ .end = end_sb1250_irq,
#ifdef CONFIG_SMP
- sb1250_set_affinity
-#else
- NULL
+ .set_affinity = sb1250_set_affinity
#endif
};
@@ -96,11 +94,11 @@ void sb1250_mask_irq(int cpu, int irq)
u64 cur_ints;
spin_lock_irqsave(&sb1250_imr_lock, flags);
- cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(cpu) +
- R_IMR_INTERRUPT_MASK));
+ cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
cur_ints |= (((u64) 1) << irq);
- __bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
- R_IMR_INTERRUPT_MASK));
+ ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
spin_unlock_irqrestore(&sb1250_imr_lock, flags);
}
@@ -110,32 +108,25 @@ void sb1250_unmask_irq(int cpu, int irq)
u64 cur_ints;
spin_lock_irqsave(&sb1250_imr_lock, flags);
- cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(cpu) +
- R_IMR_INTERRUPT_MASK));
+ cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
cur_ints &= ~(((u64) 1) << irq);
- __bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
- R_IMR_INTERRUPT_MASK));
+ ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
spin_unlock_irqrestore(&sb1250_imr_lock, flags);
}
#ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, unsigned long mask)
+static void sb1250_set_affinity(unsigned int irq, cpumask_t mask)
{
int i = 0, old_cpu, cpu, int_on;
u64 cur_ints;
irq_desc_t *desc = irq_desc + irq;
unsigned long flags;
- while (mask) {
- if (mask & 1) {
- mask >>= 1;
- break;
- }
- mask >>= 1;
- i++;
- }
+ i = first_cpu(mask);
- if (mask) {
+ if (cpus_weight(mask) > 1) {
printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
return;
}
@@ -149,23 +140,23 @@ static void sb1250_set_affinity(unsigned int irq, unsigned long mask)
/* Swizzle each CPU's IMR (but leave the IP selection alone) */
old_cpu = sb1250_irq_owner[irq];
- cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(old_cpu) +
- R_IMR_INTERRUPT_MASK));
+ cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(old_cpu) +
+ R_IMR_INTERRUPT_MASK));
int_on = !(cur_ints & (((u64) 1) << irq));
if (int_on) {
/* If it was on, mask it */
cur_ints |= (((u64) 1) << irq);
- __bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(old_cpu) +
- R_IMR_INTERRUPT_MASK));
+ ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(old_cpu) +
+ R_IMR_INTERRUPT_MASK));
}
sb1250_irq_owner[irq] = cpu;
if (int_on) {
/* unmask for the new CPU */
- cur_ints = __bus_readq(IOADDR(A_IMR_MAPPER(cpu) +
- R_IMR_INTERRUPT_MASK));
+ cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
cur_ints &= ~(((u64) 1) << irq);
- __bus_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
- R_IMR_INTERRUPT_MASK));
+ ____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
+ R_IMR_INTERRUPT_MASK));
}
spin_unlock(&sb1250_imr_lock);
spin_unlock_irqrestore(&desc->lock, flags);
@@ -208,8 +199,8 @@ static void ack_sb1250_irq(unsigned int irq)
* deliver the interrupts to all CPUs (which makes affinity
* changing easier for us)
*/
- pending = bus_readq(IOADDR(A_IMR_REGISTER(sb1250_irq_owner[irq],
- R_IMR_LDT_INTERRUPT)));
+ pending = __raw_readq(IOADDR(A_IMR_REGISTER(sb1250_irq_owner[irq],
+ R_IMR_LDT_INTERRUPT)));
pending &= ((u64)1 << (irq));
if (pending) {
int i;
@@ -224,8 +215,8 @@ static void ack_sb1250_irq(unsigned int irq)
* Clear for all CPUs so an affinity switch
* doesn't find an old status
*/
- bus_writeq(pending,
- IOADDR(A_IMR_REGISTER(cpu,
+ __raw_writeq(pending,
+ IOADDR(A_IMR_REGISTER(cpu,
R_IMR_LDT_INTERRUPT_CLR)));
}
@@ -340,12 +331,14 @@ void __init arch_init_irq(void)
/* Default everything to IP2 */
for (i = 0; i < SB1250_NR_IRQS; i++) { /* was I0 */
- bus_writeq(IMR_IP2_VAL,
- IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
- (i << 3)));
- bus_writeq(IMR_IP2_VAL,
- IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
- (i << 3)));
+ __raw_writeq(IMR_IP2_VAL,
+ IOADDR(A_IMR_REGISTER(0,
+ R_IMR_INTERRUPT_MAP_BASE) +
+ (i << 3)));
+ __raw_writeq(IMR_IP2_VAL,
+ IOADDR(A_IMR_REGISTER(1,
+ R_IMR_INTERRUPT_MAP_BASE) +
+ (i << 3)));
}
init_sb1250_irqs();
@@ -355,23 +348,23 @@ void __init arch_init_irq(void)
* inter-cpu messages
*/
/* Was I1 */
- bus_writeq(IMR_IP3_VAL,
- IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
- (K_INT_MBOX_0 << 3)));
- bus_writeq(IMR_IP3_VAL,
- IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
- (K_INT_MBOX_0 << 3)));
+ __raw_writeq(IMR_IP3_VAL,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+ (K_INT_MBOX_0 << 3)));
+ __raw_writeq(IMR_IP3_VAL,
+ IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
+ (K_INT_MBOX_0 << 3)));
/* Clear the mailboxes. The firmware may leave them dirty */
- bus_writeq(0xffffffffffffffffULL,
- IOADDR(A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU)));
- bus_writeq(0xffffffffffffffffULL,
- IOADDR(A_IMR_REGISTER(1, R_IMR_MAILBOX_CLR_CPU)));
+ __raw_writeq(0xffffffffffffffffULL,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU)));
+ __raw_writeq(0xffffffffffffffffULL,
+ IOADDR(A_IMR_REGISTER(1, R_IMR_MAILBOX_CLR_CPU)));
/* Mask everything except the mailbox registers for both cpus */
tmp = ~((u64) 0) ^ (((u64) 1) << K_INT_MBOX_0);
- bus_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)));
- bus_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)));
+ __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)));
+ __raw_writeq(tmp, IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)));
sb1250_steal_irq(K_INT_MBOX_0);
@@ -396,12 +389,14 @@ void __init arch_init_irq(void)
sb1250_duart_present[kgdb_port] = 0;
#endif
/* Setup uart 1 settings, mapper */
- bus_writeq(M_DUART_IMR_BRK, IOADDR(A_DUART_IMRREG(kgdb_port)));
+ __raw_writeq(M_DUART_IMR_BRK,
+ IOADDR(A_DUART_IMRREG(kgdb_port)));
sb1250_steal_irq(kgdb_irq);
- bus_writeq(IMR_IP6_VAL,
- IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
- (kgdb_irq<<3)));
+ __raw_writeq(IMR_IP6_VAL,
+ IOADDR(A_IMR_REGISTER(0,
+ R_IMR_INTERRUPT_MAP_BASE) +
+ (kgdb_irq << 3)));
sb1250_unmask_irq(0, kgdb_irq);
}
#endif
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index f8c605be96c..df2e266c700 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -153,7 +153,7 @@ void sb1250_setup(void)
int bad_config = 0;
sb1_pass = read_c0_prid() & 0xff;
- sys_rev = bus_readq(IOADDR(A_SCD_SYSTEM_REVISION));
+ sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
soc_type = SYS_SOC_TYPE(sys_rev);
soc_pass = G_SYS_REVISION(sys_rev);
@@ -162,7 +162,7 @@ void sb1250_setup(void)
machine_restart(NULL);
}
- plldiv = G_SYS_PLL_DIV(bus_readq(IOADDR(A_SCD_SYSTEM_CFG)));
+ plldiv = G_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
zbbus_mhz = ((plldiv >> 1) * 50) + ((plldiv & 1) * 25);
prom_printf("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index be91b399095..f859db02d3c 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -29,18 +29,18 @@
#include <asm/sibyte/sb1250_int.h>
static void *mailbox_set_regs[] = {
- (void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU),
- (void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU)
+ IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU),
+ IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU)
};
static void *mailbox_clear_regs[] = {
- (void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU),
- (void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU)
+ IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU),
+ IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU)
};
static void *mailbox_regs[] = {
- (void *)IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU),
- (void *)IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU)
+ IOADDR(A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU),
+ IOADDR(A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU)
};
/*
@@ -73,7 +73,7 @@ void sb1250_smp_finish(void)
*/
void core_send_ipi(int cpu, unsigned int action)
{
- bus_writeq((((u64)action) << 48), mailbox_set_regs[cpu]);
+ __raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]);
}
void sb1250_mailbox_interrupt(struct pt_regs *regs)
@@ -83,10 +83,10 @@ void sb1250_mailbox_interrupt(struct pt_regs *regs)
kstat_this_cpu.irqs[K_INT_MBOX_0]++;
/* Load the mailbox register to figure out what we're supposed to do */
- action = (__bus_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
+ action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
/* Clear the mailbox to clear the interrupt */
- __bus_writeq(((u64)action) << 48, mailbox_clear_regs[cpu]);
+ ____raw_writeq(((u64)action) << 48, mailbox_clear_regs[cpu]);
/*
* Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 8b4c848c907..511c89d65f3 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -67,24 +67,24 @@ void sb1250_time_init(void)
sb1250_mask_irq(cpu, irq);
/* Map the timer interrupt to ip[4] of this cpu */
- bus_writeq(IMR_IP4_VAL,
- IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) +
- (irq << 3)));
+ __raw_writeq(IMR_IP4_VAL,
+ IOADDR(A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) +
+ (irq << 3)));
/* the general purpose timer ticks at 1 Mhz independent if the rest of the system */
/* Disable the timer and set up the count */
- bus_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
- bus_writeq(50000 / HZ,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
+ __raw_writeq(50000 / HZ,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
#else
- bus_writeq(1000000/HZ,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
+ __raw_writeq(1000000 / HZ,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
#endif
/* Set the timer running */
- bus_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+ __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
sb1250_unmask_irq(cpu, irq);
sb1250_steal_irq(irq);
@@ -100,25 +100,25 @@ void sb1250_time_init(void)
void sb1250_timer_interrupt(struct pt_regs *regs)
{
- extern asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs);
int cpu = smp_processor_id();
int irq = K_INT_TIMER_0 + cpu;
/* Reset the timer */
- __bus_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
+ ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+ IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
- /*
- * CPU 0 handles the global timer interrupt job
- */
if (cpu == 0) {
+ /*
+ * CPU 0 handles the global timer interrupt job
+ */
ll_timer_interrupt(irq, regs);
}
-
- /*
- * every CPU should do profiling and process accouting
- */
- ll_local_timer_interrupt(irq, regs);
+ else {
+ /*
+ * other CPUs should just do profiling and process accounting
+ */
+ ll_local_timer_interrupt(irq, regs);
+ }
}
/*
@@ -130,7 +130,7 @@ void sb1250_timer_interrupt(struct pt_regs *regs)
unsigned long sb1250_gettimeoffset(void)
{
unsigned long count =
- bus_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
+ __raw_readq(IOADDR(A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)));
return 1000000/HZ - count;
}
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c
index a686bb716ec..5b4fc26c1b3 100644
--- a/arch/mips/sibyte/swarm/rtc_m41t81.c
+++ b/arch/mips/sibyte/swarm/rtc_m41t81.c
@@ -82,59 +82,60 @@
#define M41T81REG_SQW 0x13 /* square wave register */
#define M41T81_CCR_ADDRESS 0x68
-#define SMB_CSR(reg) ((u8 *) (IOADDR(A_SMB_REGISTER(1, reg))))
+
+#define SMB_CSR(reg) IOADDR(A_SMB_REGISTER(1, reg))
static int m41t81_read(uint8_t addr)
{
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- bus_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD));
- bus_writeq((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR1BYTE),
- SMB_CSR(R_SMB_START));
+ __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD));
+ __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR1BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- bus_writeq((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
- SMB_CSR(R_SMB_START));
+ __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
/* Clear error bit by writing a 1 */
- bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
return -1;
}
- return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
+ return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
}
static int m41t81_write(uint8_t addr, int b)
{
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- bus_writeq((addr & 0xFF), SMB_CSR(R_SMB_CMD));
- bus_writeq((b & 0xff), SMB_CSR(R_SMB_DATA));
- bus_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
- SMB_CSR(R_SMB_START));
+ __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_CMD));
+ __raw_writeq(b & 0xff, SMB_CSR(R_SMB_DATA));
+ __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
/* Clear error bit by writing a 1 */
- bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
return -1;
}
/* read the same byte again to make sure it is written */
- bus_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
- SMB_CSR(R_SMB_START));
+ __raw_writeq(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
return 0;
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c
index 981d21f16e6..d9ff9323f24 100644
--- a/arch/mips/sibyte/swarm/rtc_xicor1241.c
+++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c
@@ -57,52 +57,52 @@
#define X1241_CCR_ADDRESS 0x6F
-#define SMB_CSR(reg) ((u8 *) (IOADDR(A_SMB_REGISTER(1, reg))))
+#define SMB_CSR(reg) IOADDR(A_SMB_REGISTER(1, reg))
static int xicor_read(uint8_t addr)
{
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- bus_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
- bus_writeq((addr & 0xff), SMB_CSR(R_SMB_DATA));
- bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE),
- SMB_CSR(R_SMB_START));
+ __raw_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
+ __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_DATA));
+ __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
- SMB_CSR(R_SMB_START));
+ __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
/* Clear error bit by writing a 1 */
- bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
return -1;
}
- return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
+ return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
}
static int xicor_write(uint8_t addr, int b)
{
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- bus_writeq(addr, SMB_CSR(R_SMB_CMD));
- bus_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
- bus_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
- SMB_CSR(R_SMB_START));
+ __raw_writeq(addr, SMB_CSR(R_SMB_CMD));
+ __raw_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
+ __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
/* Clear error bit by writing a 1 */
- bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
return -1;
} else {
return 0;
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index 4daeaa413de..b614ca0ddb6 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation
+ * Copyright (C) 2000, 2001, 2002, 2003, 2004 Broadcom Corporation
* Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
*
* This program is free software; you can redistribute it and/or
@@ -39,11 +39,23 @@
#include <asm/time.h>
#include <asm/traps.h>
#include <asm/sibyte/sb1250.h>
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#include <asm/sibyte/bcm1480_regs.h>
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
#include <asm/sibyte/sb1250_regs.h>
+#else
+#error invalid SiByte board configuation
+#endif
#include <asm/sibyte/sb1250_genbus.h>
#include <asm/sibyte/board.h>
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+extern void bcm1480_setup(void);
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
extern void sb1250_setup(void);
+#else
+#error invalid SiByte board configuation
+#endif
extern int xicor_probe(void);
extern int xicor_set_time(unsigned long);
@@ -66,27 +78,34 @@ void __init swarm_timer_setup(struct irqaction *irq)
*/
/* We only need to setup the generic timer */
- sb1250_time_init();
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ bcm1480_time_init();
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
+ sb1250_time_init();
+#else
+#error invalid SiByte board configuation
+#endif
}
int swarm_be_handler(struct pt_regs *regs, int is_fixup)
{
if (!is_fixup && (regs->cp0_cause & 4)) {
/* Data bus error - print PA */
-#ifdef CONFIG_64BIT
- printk("DBE physical address: %010lx\n",
+ printk("DBE physical address: %010Lx\n",
__read_64bit_c0_register($26, 1));
-#else
- printk("DBE physical address: %010llx\n",
- __read_64bit_c0_split($26, 1));
-#endif
}
return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
}
-static int __init swarm_setup(void)
+void __init plat_setup(void)
{
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ bcm1480_setup();
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
sb1250_setup();
+#else
+#error invalid SiByte board configuation
+#endif
panic_timeout = 5; /* For debug. */
@@ -133,12 +152,8 @@ static int __init swarm_setup(void)
};
/* XXXKW for CFE, get lines/cols from environment */
#endif
-
- return 0;
}
-early_initcall(swarm_setup);
-
#ifdef LEDS_PHYS
#ifdef CONFIG_SIBYTE_CARMEL
diff --git a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c
index c1f1a9defee..97c73c793c3 100644
--- a/arch/mips/sibyte/swarm/time.c
+++ b/arch/mips/sibyte/swarm/time.c
@@ -79,48 +79,48 @@ static unsigned int usec_bias = 0;
static int xicor_read(uint8_t addr)
{
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- bus_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
- bus_writeq((addr & 0xff), SMB_CSR(R_SMB_DATA));
- bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE),
- SMB_CSR(R_SMB_START));
+ __raw_writeq((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD));
+ __raw_writeq(addr & 0xff, SMB_CSR(R_SMB_DATA));
+ __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- bus_writeq((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE),
- SMB_CSR(R_SMB_START));
+ __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
/* Clear error bit by writing a 1 */
- bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
return -1;
}
- return (bus_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
+ return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
}
static int xicor_write(uint8_t addr, int b)
{
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- bus_writeq(addr, SMB_CSR(R_SMB_CMD));
- bus_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
- bus_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
- SMB_CSR(R_SMB_START));
+ __raw_writeq(addr, SMB_CSR(R_SMB_CMD));
+ __raw_writeq((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA));
+ __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE,
+ SMB_CSR(R_SMB_START));
- while (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
;
- if (bus_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
/* Clear error bit by writing a 1 */
- bus_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
return -1;
} else {
return 0;
@@ -228,8 +228,8 @@ void __init swarm_time_init(void)
/* Establish communication with the Xicor 1241 RTC */
/* XXXKW how do I share the SMBus with the I2C subsystem? */
- bus_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
- bus_writeq(0, SMB_CSR(R_SMB_CONTROL));
+ __raw_writeq(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ));
+ __raw_writeq(0, SMB_CSR(R_SMB_CONTROL));
if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) {
printk("x1241: couldn't detect on SWARM SMBus 1\n");