aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/sibyte
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/sibyte')
-rw-r--r--arch/mips/sibyte/Kconfig81
-rw-r--r--arch/mips/sibyte/Makefile27
-rw-r--r--arch/mips/sibyte/Platform44
-rw-r--r--arch/mips/sibyte/bcm1480/Makefile2
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c310
-rw-r--r--arch/mips/sibyte/bcm1480/setup.c93
-rw-r--r--arch/mips/sibyte/bcm1480/smp.c107
-rw-r--r--arch/mips/sibyte/bcm1480/time.c123
-rw-r--r--arch/mips/sibyte/cfe/Makefile3
-rw-r--r--arch/mips/sibyte/cfe/cfe_api.c502
-rw-r--r--arch/mips/sibyte/cfe/cfe_api.h185
-rw-r--r--arch/mips/sibyte/cfe/cfe_api_int.h152
-rw-r--r--arch/mips/sibyte/cfe/cfe_error.h85
-rw-r--r--arch/mips/sibyte/cfe/smp.c110
-rw-r--r--arch/mips/sibyte/common/Makefile4
-rw-r--r--arch/mips/sibyte/common/bus_watcher.c (renamed from arch/mips/sibyte/sb1250/bus_watcher.c)104
-rw-r--r--arch/mips/sibyte/common/cfe.c (renamed from arch/mips/sibyte/cfe/setup.c)74
-rw-r--r--arch/mips/sibyte/common/cfe_console.c (renamed from arch/mips/sibyte/cfe/console.c)15
-rw-r--r--arch/mips/sibyte/common/sb_tbprof.c607
-rw-r--r--arch/mips/sibyte/sb1250/Makefile5
-rw-r--r--arch/mips/sibyte/sb1250/bcm1250_tbprof.c406
-rw-r--r--arch/mips/sibyte/sb1250/irq.c265
-rw-r--r--arch/mips/sibyte/sb1250/prom.c98
-rw-r--r--arch/mips/sibyte/sb1250/setup.c147
-rw-r--r--arch/mips/sibyte/sb1250/smp.c107
-rw-r--r--arch/mips/sibyte/sb1250/time.c159
-rw-r--r--arch/mips/sibyte/swarm/Makefile5
-rw-r--r--arch/mips/sibyte/swarm/dbg_io.c76
-rw-r--r--arch/mips/sibyte/swarm/platform.c139
-rw-r--r--arch/mips/sibyte/swarm/rtc_m41t81.c29
-rw-r--r--arch/mips/sibyte/swarm/rtc_xicor1241.c79
-rw-r--r--arch/mips/sibyte/swarm/setup.c141
-rw-r--r--arch/mips/sibyte/swarm/swarm-i2c.c35
-rw-r--r--arch/mips/sibyte/swarm/time.c244
34 files changed, 1584 insertions, 2979 deletions
diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig
index ec7a2cffacf..5fbd3605d24 100644
--- a/arch/mips/sibyte/Kconfig
+++ b/arch/mips/sibyte/Kconfig
@@ -1,52 +1,81 @@
config SIBYTE_SB1250
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select HW_HAS_PCI
- select SIBYTE_HAS_LDT
+ select IRQ_CPU
+ select SIBYTE_ENABLE_LDT_IF_PCI
+ select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
select SYS_SUPPORTS_SMP
config SIBYTE_BCM1120
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
+ select IRQ_CPU
select SIBYTE_BCM112X
+ select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
config SIBYTE_BCM1125
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select HW_HAS_PCI
+ select IRQ_CPU
select SIBYTE_BCM112X
+ select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
config SIBYTE_BCM1125H
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select HW_HAS_PCI
+ select IRQ_CPU
select SIBYTE_BCM112X
- select SIBYTE_HAS_LDT
+ select SIBYTE_ENABLE_LDT_IF_PCI
+ select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
config SIBYTE_BCM112X
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
+ select IRQ_CPU
select SIBYTE_SB1xxx_SOC
+ select SIBYTE_HAS_ZBUS_PROFILING
config SIBYTE_BCM1x80
bool
+ select CEVT_BCM1480
+ select CSRC_BCM1480
select HW_HAS_PCI
+ select IRQ_CPU
+ select SIBYTE_HAS_ZBUS_PROFILING
select SIBYTE_SB1xxx_SOC
select SYS_SUPPORTS_SMP
config SIBYTE_BCM1x55
bool
+ select CEVT_BCM1480
+ select CSRC_BCM1480
select HW_HAS_PCI
+ select IRQ_CPU
select SIBYTE_SB1xxx_SOC
+ select SIBYTE_HAS_ZBUS_PROFILING
select SYS_SUPPORTS_SMP
config SIBYTE_SB1xxx_SOC
bool
- depends on EXPERIMENTAL
select DMA_COHERENT
- select SIBYTE_CFE
+ select IRQ_CPU
select SWAP_IO_SPACE
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
+ select FW_CFE
+ select SYS_HAS_EARLY_PRINTK
choice
prompt "SiByte SOC Stepping"
@@ -95,15 +124,10 @@ config CPU_SB1_PASS_2
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 SIBYTE_ENABLE_LDT_IF_PCI
+ bool
+ select SIBYTE_HAS_LDT if PCI
config SB1_CEX_ALWAYS_FATAL
bool "All cache exceptions considered fatal (no recovery attempted)"
@@ -113,34 +137,18 @@ 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
+ depends on SIBYTE_SB1xxx_SOC
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
+ depends on SIBYTE_SB1xxx_SOC && \
+ (SIBYTE_BCM112X || SIBYTE_SB1250)
help
Handle and keep statistics on the bus error interrupts (COR_ECC,
BAD_ECC, IO_BUS).
@@ -155,10 +163,9 @@ config SIBYTE_BW_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
+ tristate "Support for ZBbus profiling"
+ depends on SIBYTE_HAS_ZBUS_PROFILING
+
+config SIBYTE_HAS_ZBUS_PROFILING
+ bool
diff --git a/arch/mips/sibyte/Makefile b/arch/mips/sibyte/Makefile
new file mode 100644
index 00000000000..c8ed2c807e6
--- /dev/null
+++ b/arch/mips/sibyte/Makefile
@@ -0,0 +1,27 @@
+#
+# Sibyte SB1250 / BCM1480 family of SOCs
+#
+obj-$(CONFIG_SIBYTE_BCM112X) += sb1250/
+obj-$(CONFIG_SIBYTE_BCM112X) += common/
+obj-$(CONFIG_SIBYTE_SB1250) += sb1250/
+obj-$(CONFIG_SIBYTE_SB1250) += common/
+obj-$(CONFIG_SIBYTE_BCM1x55) += bcm1480/
+obj-$(CONFIG_SIBYTE_BCM1x55) += common/
+obj-$(CONFIG_SIBYTE_BCM1x80) += bcm1480/
+obj-$(CONFIG_SIBYTE_BCM1x80) += common/
+
+#
+# Sibyte BCM91120x (Carmel) board
+# Sibyte BCM91120C (CRhine) board
+# Sibyte BCM91125C (CRhone) board
+# Sibyte BCM91125E (Rhone) board
+# Sibyte SWARM board
+# Sibyte BCM91x80 (BigSur) board
+#
+obj-$(CONFIG_SIBYTE_CARMEL) += swarm/
+obj-$(CONFIG_SIBYTE_CRHINE) += swarm/
+obj-$(CONFIG_SIBYTE_CRHONE) += swarm/
+obj-$(CONFIG_SIBYTE_RHONE) += swarm/
+obj-$(CONFIG_SIBYTE_SENTOSA) += swarm/
+obj-$(CONFIG_SIBYTE_SWARM) += swarm/
+obj-$(CONFIG_SIBYTE_BIGSUR) += swarm/
diff --git a/arch/mips/sibyte/Platform b/arch/mips/sibyte/Platform
new file mode 100644
index 00000000000..af117330ce1
--- /dev/null
+++ b/arch/mips/sibyte/Platform
@@ -0,0 +1,44 @@
+#
+# These are all rather similar so we consider them a single platform
+#
+platform-$(CONFIG_SIBYTE_BCM112X) += sibyte/
+platform-$(CONFIG_SIBYTE_SB1250) += sibyte/
+platform-$(CONFIG_SIBYTE_BCM1x55) += sibyte/
+platform-$(CONFIG_SIBYTE_BCM1x80) += sibyte/
+
+#
+# Sibyte SB1250 / BCM1480 family of SOCs
+#
+cflags-$(CONFIG_SIBYTE_BCM112X) += \
+ -I$(srctree)/arch/mips/include/asm/mach-sibyte \
+ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL
+
+cflags-$(CONFIG_SIBYTE_SB1250) += \
+ -I$(srctree)/arch/mips/include/asm/mach-sibyte \
+ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1250_112x_ALL
+
+cflags-$(CONFIG_SIBYTE_BCM1x55) += \
+ -I$(srctree)/arch/mips/include/asm/mach-sibyte \
+ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL
+
+cflags-$(CONFIG_SIBYTE_BCM1x80) += \
+ -I$(srctree)/arch/mips/include/asm/mach-sibyte \
+ -DSIBYTE_HDR_FEATURES=SIBYTE_HDR_FMASK_1480_ALL
+
+#
+# Sibyte BCM91120x (Carmel) board
+# Sibyte BCM91120C (CRhine) board
+# Sibyte BCM91125C (CRhone) board
+# Sibyte BCM91125E (Rhone) board
+# Sibyte BCM91250A (SWARM) board
+# Sibyte BCM91250C2 (LittleSur) board
+# Sibyte BCM91x80 (BigSur) board
+#
+load-$(CONFIG_SIBYTE_CARMEL) := 0xffffffff80100000
+load-$(CONFIG_SIBYTE_CRHINE) := 0xffffffff80100000
+load-$(CONFIG_SIBYTE_CRHONE) := 0xffffffff80100000
+load-$(CONFIG_SIBYTE_RHONE) := 0xffffffff80100000
+load-$(CONFIG_SIBYTE_SENTOSA) := 0xffffffff80100000
+load-$(CONFIG_SIBYTE_SWARM) := 0xffffffff80100000
+load-$(CONFIG_SIBYTE_BIGSUR) := 0xffffffff80100000
+load-$(CONFIG_SIBYTE_LITTLESUR) := 0xffffffff80100000
diff --git a/arch/mips/sibyte/bcm1480/Makefile b/arch/mips/sibyte/bcm1480/Makefile
index 7b36ff3873b..cdc4c56c3e2 100644
--- a/arch/mips/sibyte/bcm1480/Makefile
+++ b/arch/mips/sibyte/bcm1480/Makefile
@@ -1,5 +1,3 @@
obj-y := setup.o irq.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
index a0222fa4416..373fbbc8425 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -19,15 +19,14 @@
#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/interrupt.h>
+#include <linux/smp.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
-#include <linux/slab.h>
#include <linux/kernel_stat.h>
#include <asm/errno.h>
+#include <asm/irq_regs.h>
#include <asm/signal.h>
-#include <asm/system.h>
-#include <asm/ptrace.h>
#include <asm/io.h>
#include <asm/sibyte/bcm1480_regs.h>
@@ -44,69 +43,21 @@
* 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 irq_chip 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);
+static DEFINE_RAW_SPINLOCK(bcm1480_imr_lock);
void bcm1480_mask_irq(int cpu, int irq)
{
- unsigned long flags;
- u64 cur_ints,hl_spacing;
+ unsigned long flags, hl_spacing;
+ u64 cur_ints;
- spin_lock_irqsave(&bcm1480_imr_lock, flags);
+ raw_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;
@@ -115,15 +66,15 @@ void bcm1480_mask_irq(int cpu, int irq)
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);
+ raw_spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
}
void bcm1480_unmask_irq(int cpu, int irq)
{
- unsigned long flags;
- u64 cur_ints,hl_spacing;
+ unsigned long flags, hl_spacing;
+ u64 cur_ints;
- spin_lock_irqsave(&bcm1480_imr_lock, flags);
+ raw_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;
@@ -132,30 +83,25 @@ void bcm1480_unmask_irq(int cpu, int irq)
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);
+ raw_spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
}
#ifdef CONFIG_SMP
-static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
+static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask,
+ bool force)
{
+ unsigned int irq_dirty, irq = d->irq;
int i = 0, old_cpu, cpu, int_on, k;
u64 cur_ints;
- struct irq_desc *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;
- }
+ i = cpumask_first_and(mask, cpu_online_mask);
/* 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);
+ raw_spin_lock_irqsave(&bcm1480_imr_lock, flags);
/* Swizzle each CPU's IMR (but leave the IP selection alone) */
old_cpu = bcm1480_irq_owner[irq];
@@ -180,37 +126,34 @@ static void bcm1480_set_affinity(unsigned int irq, cpumask_t mask)
____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);
+ raw_spin_unlock_irqrestore(&bcm1480_imr_lock, flags);
+
+ return 0;
}
#endif
/*****************************************************************************/
-static unsigned int startup_bcm1480_irq(unsigned int irq)
+static void disable_bcm1480_irq(struct irq_data *d)
{
- bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
+ unsigned int irq = d->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)
+static void enable_bcm1480_irq(struct irq_data *d)
{
+ unsigned int irq = d->irq;
+
bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
}
-static void ack_bcm1480_irq(unsigned int irq)
+static void ack_bcm1480_irq(struct irq_data *d)
{
+ unsigned int irq_dirty, irq = d->irq;
u64 pending;
- unsigned int irq_dirty;
int k;
/*
@@ -257,69 +200,27 @@ static void ack_bcm1480_irq(unsigned int irq)
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);
- }
-}
-
+static struct irq_chip bcm1480_irq_type = {
+ .name = "BCM1480-IMR",
+ .irq_mask_ack = ack_bcm1480_irq,
+ .irq_mask = disable_bcm1480_irq,
+ .irq_unmask = enable_bcm1480_irq,
+#ifdef CONFIG_SMP
+ .irq_set_affinity = bcm1480_set_affinity
+#endif
+};
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].chip = &bcm1480_irq_type;
- bcm1480_irq_owner[i] = 0;
- } else {
- irq_desc[i].chip = &no_irq_chip;
- }
+ for (i = 0; i < BCM1480_NR_IRQS; i++) {
+ irq_set_chip_and_handler(i, &bcm1480_irq_type,
+ handle_level_irq);
+ bcm1480_irq_owner[i] = 0;
}
}
-
-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)
-{
- struct irq_desc *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
@@ -337,7 +238,7 @@ int bcm1480_steal_irq(int irq)
* 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
+ * can do cross-cpu function calls, as required by SMP
*/
#define IMR_IP2_VAL K_BCM1480_INT_MAP_I0
@@ -348,7 +249,6 @@ int bcm1480_steal_irq(int irq)
void __init arch_init_irq(void)
{
-
unsigned int i, cpu;
u64 tmp;
unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
@@ -383,10 +283,10 @@ void __init arch_init_irq(void)
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 */
+ /* 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)));
@@ -405,125 +305,57 @@ void __init arch_init_irq(void)
__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
+ * 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);
-
-#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>
+extern void bcm1480_mailbox_interrupt(void);
-#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)
+static inline void dispatch_ip2(void)
{
+ unsigned long long mask_h, mask_l;
+ unsigned int cpu = smp_processor_id();
+ unsigned long base;
+
/*
- * 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)
+ * 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.
*/
- 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);
+ base = A_BCM1480_IMR_MAPPER(cpu);
+ mask_h = __raw_readq(
+ IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
+ mask_l = __raw_readq(
+ IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
+
+ if (mask_h) {
+ if (mask_h ^ 1)
+ do_IRQ(fls64(mask_h) - 1);
+ else if (mask_l)
+ do_IRQ(63 + fls64(mask_l));
+ }
}
-#endif /* CONFIG_KGDB */
-
-extern void bcm1480_timer_interrupt(struct pt_regs *regs);
-extern void bcm1480_mailbox_interrupt(struct pt_regs *regs);
-extern void bcm1480_kgdb_interrupt(struct pt_regs *regs);
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
{
+ unsigned int cpu = smp_processor_id();
unsigned int pending;
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
- /* Set compare to count to silence count/compare timer interrupts */
- write_c0_compare(read_c0_count());
-#endif
-
- pending = read_c0_cause();
-
-#ifdef CONFIG_SIBYTE_BCM1480_PROF
- if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */
- sbprof_cpu_intr(exception_epc(regs));
- else
-#endif
+ pending = read_c0_cause() & read_c0_status();
if (pending & CAUSEF_IP4)
- bcm1480_timer_interrupt(regs);
-
+ do_IRQ(K_BCM1480_INT_TIMER_0 + cpu);
#ifdef CONFIG_SMP
else if (pending & CAUSEF_IP3)
- bcm1480_mailbox_interrupt(regs);
+ bcm1480_mailbox_interrupt();
#endif
-#ifdef CONFIG_KGDB
- else if (pending & CAUSEF_IP6)
- bcm1480_kgdb_interrupt(regs); /* KGDB (uart 1) */
-#endif
-
- else if (pending & CAUSEF_IP2) {
- unsigned long long mask_h, mask_l;
- unsigned long base;
-
- /*
- * 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.
- */
- base = A_BCM1480_IMR_MAPPER(smp_processor_id());
- mask_h = __raw_readq(
- IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_H));
- mask_l = __raw_readq(
- IOADDR(base + R_BCM1480_IMR_INTERRUPT_STATUS_BASE_L));
-
- if (mask_h) {
- if (mask_h ^ 1)
- do_IRQ(fls64(mask_h) - 1, regs);
- else
- do_IRQ(63 + fls64(mask_l), regs);
- }
- }
+ else if (pending & CAUSEF_IP2)
+ dispatch_ip2();
}
diff --git a/arch/mips/sibyte/bcm1480/setup.c b/arch/mips/sibyte/bcm1480/setup.c
index 8236d0c4854..8e2e04f7787 100644
--- a/arch/mips/sibyte/bcm1480/setup.c
+++ b/arch/mips/sibyte/bcm1480/setup.c
@@ -15,11 +15,14 @@
* 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/kernel.h>
+#include <linux/module.h>
#include <linux/reboot.h>
#include <linux/string.h>
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250.h>
@@ -31,24 +34,59 @@
unsigned int sb1_pass;
unsigned int soc_pass;
unsigned int soc_type;
+EXPORT_SYMBOL(soc_type);
unsigned int periph_rev;
unsigned int zbbus_mhz;
+EXPORT_SYMBOL(zbbus_mhz);
static unsigned int part_type;
static char *soc_str;
static char *pass_str;
-static inline int setup_bcm1x80_bcm1x55(void);
+static int __init 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:
+ printk("Unknown %s rev %x\n", soc_str, soc_pass);
+ periph_rev = 1;
+ pass_str = "Unknown Revision";
+ break;
+ }
+
+ return ret;
+}
/* Setup code likely to be common to all SiByte platforms */
-static inline int sys_rev_decode(void)
+static int __init sys_rev_decode(void)
{
int ret = 0;
switch (soc_type) {
- case K_SYS_SOC_TYPE_BCM1x80:
+ case K_SYS_SOC_TYPE_BCM1x80:
if (part_type == K_SYS_PART_BCM1480)
soc_str = "BCM1480";
else if (part_type == K_SYS_PART_BCM1280)
@@ -58,7 +96,7 @@ static inline int sys_rev_decode(void)
ret = setup_bcm1x80_bcm1x55();
break;
- case K_SYS_SOC_TYPE_BCM1x55:
+ case K_SYS_SOC_TYPE_BCM1x55:
if (part_type == K_SYS_PART_BCM1455)
soc_str = "BCM1455";
else if (part_type == K_SYS_PART_BCM1255)
@@ -68,68 +106,35 @@ static inline int sys_rev_decode(void)
ret = setup_bcm1x80_bcm1x55();
break;
- default:
- prom_printf("Unknown part type %x\n", part_type);
+ default:
+ printk("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)
+void __init bcm1480_setup(void)
{
uint64_t sys_rev;
int plldiv;
- sb1_pass = read_c0_prid() & 0xff;
+ sb1_pass = read_c0_prid() & PRID_REV_MASK;
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");
+ printk("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",
+ printk("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());
+ printk("Board type: %s\n", get_system_type());
}
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index 584a4b33faa..af7d44edd9a 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -20,9 +20,11 @@
#include <linux/delay.h>
#include <linux/smp.h>
#include <linux/kernel_stat.h>
+#include <linux/sched.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
+#include <asm/fw/cfe/cfe_api.h>
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/bcm1480_regs.h>
#include <asm/sibyte/bcm1480_int.h>
@@ -67,13 +69,6 @@ void bcm1480_smp_init(void)
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
@@ -83,27 +78,111 @@ void bcm1480_smp_finish(void)
* 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)
+static void bcm1480_send_ipi_single(int cpu, unsigned int action)
{
__raw_writeq((((u64)action)<< 48), mailbox_0_set_regs[cpu]);
}
-void bcm1480_mailbox_interrupt(struct pt_regs *regs)
+static void bcm1480_send_ipi_mask(const struct cpumask *mask,
+ unsigned int action)
+{
+ unsigned int i;
+
+ for_each_cpu(i, mask)
+ bcm1480_send_ipi_single(i, action);
+}
+
+/*
+ * Code to run on secondary just after probing the CPU
+ */
+static void bcm1480_init_secondary(void)
+{
+ extern void bcm1480_smp_init(void);
+
+ bcm1480_smp_init();
+}
+
+/*
+ * Do any tidying up before marking online and running the idle
+ * loop
+ */
+static void bcm1480_smp_finish(void)
+{
+ extern void sb1480_clockevent_init(void);
+
+ sb1480_clockevent_init();
+ local_irq_enable();
+}
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it
+ * running!
+ */
+static void bcm1480_boot_secondary(int cpu, struct task_struct *idle)
+{
+ int retval;
+
+ retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap,
+ __KSTK_TOS(idle),
+ (unsigned long)task_thread_info(idle), 0);
+ if (retval != 0)
+ printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
+}
+
+/*
+ * Use CFE to find out how many CPUs are available, setting up
+ * cpu_possible_mask and the logical/physical mappings.
+ * XXXKW will the boot CPU ever not be physical 0?
+ *
+ * Common setup before any secondaries are started
+ */
+static void __init bcm1480_smp_setup(void)
+{
+ int i, num;
+
+ init_cpu_possible(cpumask_of(0));
+ __cpu_number_map[0] = 0;
+ __cpu_logical_map[0] = 0;
+
+ for (i = 1, num = 0; i < NR_CPUS; i++) {
+ if (cfe_cpu_stop(i) == 0) {
+ set_cpu_possible(i, true);
+ __cpu_number_map[i] = ++num;
+ __cpu_logical_map[num] = i;
+ }
+ }
+ printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
+}
+
+static void __init bcm1480_prepare_cpus(unsigned int max_cpus)
+{
+}
+
+struct plat_smp_ops bcm1480_smp_ops = {
+ .send_ipi_single = bcm1480_send_ipi_single,
+ .send_ipi_mask = bcm1480_send_ipi_mask,
+ .init_secondary = bcm1480_init_secondary,
+ .smp_finish = bcm1480_smp_finish,
+ .boot_secondary = bcm1480_boot_secondary,
+ .smp_setup = bcm1480_smp_setup,
+ .prepare_cpus = bcm1480_prepare_cpus,
+};
+
+void bcm1480_mailbox_interrupt(void)
{
int cpu = smp_processor_id();
+ int irq = K_BCM1480_INT_MBOX_0_0;
unsigned int action;
- kstat_this_cpu.irqs[K_BCM1480_INT_MBOX_0_0]++;
+ kstat_incr_irq_this_cpu(irq);
/* 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_RESCHEDULE_YOURSELF)
+ scheduler_ipi();
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
index 7e088f6c4a8..1680a68952a 100644
--- a/arch/mips/sibyte/bcm1480/time.c
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -15,124 +15,13 @@
* 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>
-/*
- * 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/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 void sb1480_clockevent_init(void);
+extern void sb1480_clocksource_init(void);
-extern int bcm1480_steal_irq(int irq);
-
-void bcm1480_time_init(void)
+void __init plat_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)));
-
- if (cpu == 0) {
- /*
- * CPU 0 handles the global timer interrupt job
- */
- ll_timer_interrupt(irq, regs);
- }
- else {
- /*
- * other CPUs should just do profiling and process accounting
- */
- 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;
+ sb1480_clocksource_init();
+ sb1480_clockevent_init();
}
diff --git a/arch/mips/sibyte/cfe/Makefile b/arch/mips/sibyte/cfe/Makefile
deleted file mode 100644
index 059d84a1d8a..00000000000
--- a/arch/mips/sibyte/cfe/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-lib-y = cfe_api.o setup.o
-lib-$(CONFIG_SMP) += smp.o
-lib-$(CONFIG_SIBYTE_CFE_CONSOLE) += console.o
diff --git a/arch/mips/sibyte/cfe/cfe_api.c b/arch/mips/sibyte/cfe/cfe_api.c
deleted file mode 100644
index c0213605e18..00000000000
--- a/arch/mips/sibyte/cfe/cfe_api.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 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.
- */
-
-/* *********************************************************************
- *
- * Broadcom Common Firmware Environment (CFE)
- *
- * Device Function stubs File: cfe_api.c
- *
- * This module contains device function stubs (small routines to
- * call the standard "iocb" interface entry point to CFE).
- * There should be one routine here per iocb function call.
- *
- * Authors: Mitch Lichtenberg, Chris Demetriou
- *
- ********************************************************************* */
-
-#include "cfe_api.h"
-#include "cfe_api_int.h"
-
-/* Cast from a native pointer to a cfe_xptr_t and back. */
-#define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n))
-#define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x))
-
-#ifdef CFE_API_IMPL_NAMESPACE
-#define cfe_iocb_dispatch(a) __cfe_iocb_dispatch(a)
-#endif
-int cfe_iocb_dispatch(cfe_xiocb_t * xiocb);
-
-#if defined(CFE_API_common) || defined(CFE_API_ALL)
-/*
- * Declare the dispatch function with args of "intptr_t".
- * This makes sure whatever model we're compiling in
- * puts the pointers in a single register. For example,
- * combining -mlong64 and -mips1 or -mips2 would lead to
- * trouble, since the handle and IOCB pointer will be
- * passed in two registers each, and CFE expects one.
- */
-
-static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb) = 0;
-static cfe_xuint_t cfe_handle = 0;
-
-int cfe_init(cfe_xuint_t handle, cfe_xuint_t ept)
-{
- cfe_dispfunc = NATIVE_FROM_XPTR(ept);
- cfe_handle = handle;
- return 0;
-}
-
-int cfe_iocb_dispatch(cfe_xiocb_t * xiocb)
-{
- if (!cfe_dispfunc)
- return -1;
- return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb);
-}
-#endif /* CFE_API_common || CFE_API_ALL */
-
-#if defined(CFE_API_close) || defined(CFE_API_ALL)
-int cfe_close(int handle)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = 0;
-
- cfe_iocb_dispatch(&xiocb);
-
- return xiocb.xiocb_status;
-
-}
-#endif /* CFE_API_close || CFE_API_ALL */
-
-#if defined(CFE_API_cpu_start) || defined(CFE_API_ALL)
-int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
- xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
- xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START;
- xiocb.plist.xiocb_cpuctl.gp_val = gp;
- xiocb.plist.xiocb_cpuctl.sp_val = sp;
- xiocb.plist.xiocb_cpuctl.a1_val = a1;
- xiocb.plist.xiocb_cpuctl.start_addr = (long) fn;
-
- cfe_iocb_dispatch(&xiocb);
-
- return xiocb.xiocb_status;
-}
-#endif /* CFE_API_cpu_start || CFE_API_ALL */
-
-#if defined(CFE_API_cpu_stop) || defined(CFE_API_ALL)
-int cfe_cpu_stop(int cpu)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t);
- xiocb.plist.xiocb_cpuctl.cpu_number = cpu;
- xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP;
-
- cfe_iocb_dispatch(&xiocb);
-
- return xiocb.xiocb_status;
-}
-#endif /* CFE_API_cpu_stop || CFE_API_ALL */
-
-#if defined(CFE_API_enumenv) || defined(CFE_API_ALL)
-int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
- xiocb.plist.xiocb_envbuf.enum_idx = idx;
- xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_envbuf.name_length = namelen;
- xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
- xiocb.plist.xiocb_envbuf.val_length = vallen;
-
- cfe_iocb_dispatch(&xiocb);
-
- return xiocb.xiocb_status;
-}
-#endif /* CFE_API_enumenv || CFE_API_ALL */
-
-#if defined(CFE_API_enummem) || defined(CFE_API_ALL)
-int
-cfe_enummem(int idx, int flags, cfe_xuint_t * start, cfe_xuint_t * length,
- cfe_xuint_t * type)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = flags;
- xiocb.xiocb_psize = sizeof(xiocb_meminfo_t);
- xiocb.plist.xiocb_meminfo.mi_idx = idx;
-
- cfe_iocb_dispatch(&xiocb);
-
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
-
- *start = xiocb.plist.xiocb_meminfo.mi_addr;
- *length = xiocb.plist.xiocb_meminfo.mi_size;
- *type = xiocb.plist.xiocb_meminfo.mi_type;
-
- return 0;
-}
-#endif /* CFE_API_enummem || CFE_API_ALL */
-
-#if defined(CFE_API_exit) || defined(CFE_API_ALL)
-int cfe_exit(int warm, int status)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_FW_RESTART;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0;
- xiocb.xiocb_psize = sizeof(xiocb_exitstat_t);
- xiocb.plist.xiocb_exitstat.status = status;
-
- cfe_iocb_dispatch(&xiocb);
-
- return xiocb.xiocb_status;
-}
-#endif /* CFE_API_exit || CFE_API_ALL */
-
-#if defined(CFE_API_flushcache) || defined(CFE_API_ALL)
-int cfe_flushcache(int flg)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = flg;
- xiocb.xiocb_psize = 0;
-
- cfe_iocb_dispatch(&xiocb);
-
- return xiocb.xiocb_status;
-}
-#endif /* CFE_API_flushcache || CFE_API_ALL */
-
-#if defined(CFE_API_getdevinfo) || defined(CFE_API_ALL)
-int cfe_getdevinfo(char *name)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
- xiocb.plist.xiocb_buffer.buf_offset = 0;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
-
- cfe_iocb_dispatch(&xiocb);
-
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.plist.xiocb_buffer.buf_devflags;
-}
-#endif /* CFE_API_getdevinfo || CFE_API_ALL */
-
-#if defined(CFE_API_getenv) || defined(CFE_API_ALL)
-int cfe_getenv(char *name, char *dest, int destlen)
-{
- cfe_xiocb_t xiocb;
-
- *dest = 0;
-
- xiocb.xiocb_fcode = CFE_CMD_ENV_GET;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
- xiocb.plist.xiocb_envbuf.enum_idx = 0;
- xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
- xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest);
- xiocb.plist.xiocb_envbuf.val_length = destlen;
-
- cfe_iocb_dispatch(&xiocb);
-
- return xiocb.xiocb_status;
-}
-#endif /* CFE_API_getenv || CFE_API_ALL */
-
-#if defined(CFE_API_getfwinfo) || defined(CFE_API_ALL)
-int cfe_getfwinfo(cfe_fwinfo_t * info)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_fwinfo_t);
-
- cfe_iocb_dispatch(&xiocb);
-
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
-
- info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version;
- info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem;
- info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags;
- info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid;
- info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va;
- info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa;
- info->fwi_bootarea_size =
- xiocb.plist.xiocb_fwinfo.fwi_bootarea_size;
-#if 0
- info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1;
- info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2;
- info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3;
-#endif
-
- return 0;
-}
-#endif /* CFE_API_getfwinfo || CFE_API_ALL */
-
-#if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL)
-int cfe_getstdhandle(int flg)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = flg;
- xiocb.xiocb_psize = 0;
-
- cfe_iocb_dispatch(&xiocb);
-
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.xiocb_handle;
-}
-#endif /* CFE_API_getstdhandle || CFE_API_ALL */
-
-#if defined(CFE_API_getticks) || defined(CFE_API_ALL)
-int64_t
-#ifdef CFE_API_IMPL_NAMESPACE
-__cfe_getticks(void)
-#else
-cfe_getticks(void)
-#endif
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_time_t);
- xiocb.plist.xiocb_time.ticks = 0;
-
- cfe_iocb_dispatch(&xiocb);
-
- return xiocb.plist.xiocb_time.ticks;
-
-}
-#endif /* CFE_API_getticks || CFE_API_ALL */
-
-#if defined(CFE_API_inpstat) || defined(CFE_API_ALL)
-int cfe_inpstat(int handle)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_inpstat_t);
- xiocb.plist.xiocb_inpstat.inp_status = 0;
-
- cfe_iocb_dispatch(&xiocb);
-
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.plist.xiocb_inpstat.inp_status;
-}
-#endif /* CFE_API_inpstat || CFE_API_ALL */
-
-#if defined(CFE_API_ioctl) || defined(CFE_API_ALL)
-int
-cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
- int length, int *retlen, cfe_xuint_t offset)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
- xiocb.plist.xiocb_buffer.buf_offset = offset;
- xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
- xiocb.plist.xiocb_buffer.buf_length = length;
-
- cfe_iocb_dispatch(&xiocb);
-
- if (retlen)
- *retlen = xiocb.plist.xiocb_buffer.buf_retlen;
- return xiocb.xiocb_status;
-}
-#endif /* CFE_API_ioctl || CFE_API_ALL */
-
-#if defined(CFE_API_open) || defined(CFE_API_ALL)
-int cfe_open(char *name)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
- xiocb.plist.xiocb_buffer.buf_offset = 0;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name);
-
- cfe_iocb_dispatch(&xiocb);
-
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.xiocb_handle;
-}
-#endif /* CFE_API_open || CFE_API_ALL */
-
-#if defined(CFE_API_read) || defined(CFE_API_ALL)
-int cfe_read(int handle, unsigned char *buffer, int length)
-{
- return cfe_readblk(handle, 0, buffer, length);
-}
-#endif /* CFE_API_read || CFE_API_ALL */
-
-#if defined(CFE_API_readblk) || defined(CFE_API_ALL)
-int
-cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer,
- int length)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_DEV_READ;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
- xiocb.plist.xiocb_buffer.buf_offset = offset;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
- xiocb.plist.xiocb_buffer.buf_length = length;
-
- cfe_iocb_dispatch(&xiocb);
-
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.plist.xiocb_buffer.buf_retlen;
-}
-#endif /* CFE_API_readblk || CFE_API_ALL */
-
-#if defined(CFE_API_setenv) || defined(CFE_API_ALL)
-int cfe_setenv(char *name, char *val)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_ENV_SET;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = 0;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_envbuf_t);
- xiocb.plist.xiocb_envbuf.enum_idx = 0;
- xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name);
- xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name);
- xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val);
- xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val);
-
- cfe_iocb_dispatch(&xiocb);
-
- return xiocb.xiocb_status;
-}
-#endif /* CFE_API_setenv || CFE_API_ALL */
-
-#if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) \
- && !defined(CFE_API_STRLEN_CUSTOM)
-int cfe_strlen(char *name)
-{
- int count = 0;
-
- while (*name++)
- count++;
-
- return count;
-}
-#endif /* CFE_API_strlen || CFE_API_ALL */
-
-#if defined(CFE_API_write) || defined(CFE_API_ALL)
-int cfe_write(int handle, unsigned char *buffer, int length)
-{
- return cfe_writeblk(handle, 0, buffer, length);
-}
-#endif /* CFE_API_write || CFE_API_ALL */
-
-#if defined(CFE_API_writeblk) || defined(CFE_API_ALL)
-int
-cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer,
- int length)
-{
- cfe_xiocb_t xiocb;
-
- xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE;
- xiocb.xiocb_status = 0;
- xiocb.xiocb_handle = handle;
- xiocb.xiocb_flags = 0;
- xiocb.xiocb_psize = sizeof(xiocb_buffer_t);
- xiocb.plist.xiocb_buffer.buf_offset = offset;
- xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer);
- xiocb.plist.xiocb_buffer.buf_length = length;
-
- cfe_iocb_dispatch(&xiocb);
-
- if (xiocb.xiocb_status < 0)
- return xiocb.xiocb_status;
- return xiocb.plist.xiocb_buffer.buf_retlen;
-}
-#endif /* CFE_API_writeblk || CFE_API_ALL */
diff --git a/arch/mips/sibyte/cfe/cfe_api.h b/arch/mips/sibyte/cfe/cfe_api.h
deleted file mode 100644
index d8230cc53b8..00000000000
--- a/arch/mips/sibyte/cfe/cfe_api.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 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.
- */
-
-/* *********************************************************************
- *
- * Broadcom Common Firmware Environment (CFE)
- *
- * Device function prototypes File: cfe_api.h
- *
- * This file contains declarations for doing callbacks to
- * cfe from an application. It should be the only header
- * needed by the application to use this library
- *
- * Authors: Mitch Lichtenberg, Chris Demetriou
- *
- ********************************************************************* */
-
-#ifndef CFE_API_H
-#define CFE_API_H
-
-/*
- * Apply customizations here for different OSes. These need to:
- * * typedef uint64_t, int64_t, intptr_t, uintptr_t.
- * * define cfe_strlen() if use of an existing function is desired.
- * * define CFE_API_IMPL_NAMESPACE if API functions are to use
- * names in the implementation namespace.
- * Also, optionally, if the build environment does not do so automatically,
- * CFE_API_* can be defined here as desired.
- */
-/* Begin customization. */
-#include <linux/types.h>
-#include <linux/string.h>
-
-typedef long intptr_t;
-
-#define cfe_strlen strlen
-
-#define CFE_API_ALL
-#define CFE_API_STRLEN_CUSTOM
-/* End customization. */
-
-
-/* *********************************************************************
- * Constants
- ********************************************************************* */
-
-/* Seal indicating CFE's presence, passed to user program. */
-#define CFE_EPTSEAL 0x43464531
-
-#define CFE_MI_RESERVED 0 /* memory is reserved, do not use */
-#define CFE_MI_AVAILABLE 1 /* memory is available */
-
-#define CFE_FLG_WARMSTART 0x00000001
-#define CFE_FLG_FULL_ARENA 0x00000001
-#define CFE_FLG_ENV_PERMANENT 0x00000001
-
-#define CFE_CPU_CMD_START 1
-#define CFE_CPU_CMD_STOP 0
-
-#define CFE_STDHANDLE_CONSOLE 0
-
-#define CFE_DEV_NETWORK 1
-#define CFE_DEV_DISK 2
-#define CFE_DEV_FLASH 3
-#define CFE_DEV_SERIAL 4
-#define CFE_DEV_CPU 5
-#define CFE_DEV_NVRAM 6
-#define CFE_DEV_CLOCK 7
-#define CFE_DEV_OTHER 8
-#define CFE_DEV_MASK 0x0F
-
-#define CFE_CACHE_FLUSH_D 1
-#define CFE_CACHE_INVAL_I 2
-#define CFE_CACHE_INVAL_D 4
-#define CFE_CACHE_INVAL_L2 8
-
-#define CFE_FWI_64BIT 0x00000001
-#define CFE_FWI_32BIT 0x00000002
-#define CFE_FWI_RELOC 0x00000004
-#define CFE_FWI_UNCACHED 0x00000008
-#define CFE_FWI_MULTICPU 0x00000010
-#define CFE_FWI_FUNCSIM 0x00000020
-#define CFE_FWI_RTLSIM 0x00000040
-
-typedef struct {
- int64_t fwi_version; /* major, minor, eco version */
- int64_t fwi_totalmem; /* total installed mem */
- int64_t fwi_flags; /* various flags */
- int64_t fwi_boardid; /* board ID */
- int64_t fwi_bootarea_va; /* VA of boot area */
- int64_t fwi_bootarea_pa; /* PA of boot area */
- int64_t fwi_bootarea_size; /* size of boot area */
-} cfe_fwinfo_t;
-
-
-/*
- * cfe_strlen is handled specially: If already defined, it has been
- * overridden in this environment with a standard strlen-like function.
- */
-#ifdef cfe_strlen
-# define CFE_API_STRLEN_CUSTOM
-#else
-# ifdef CFE_API_IMPL_NAMESPACE
-# define cfe_strlen(a) __cfe_strlen(a)
-# endif
-int cfe_strlen(char *name);
-#endif
-
-/*
- * Defines and prototypes for functions which take no arguments.
- */
-#ifdef CFE_API_IMPL_NAMESPACE
-int64_t __cfe_getticks(void);
-#define cfe_getticks() __cfe_getticks()
-#else
-int64_t cfe_getticks(void);
-#endif
-
-/*
- * Defines and prototypes for the rest of the functions.
- */
-#ifdef CFE_API_IMPL_NAMESPACE
-#define cfe_close(a) __cfe_close(a)
-#define cfe_cpu_start(a,b,c,d,e) __cfe_cpu_start(a,b,c,d,e)
-#define cfe_cpu_stop(a) __cfe_cpu_stop(a)
-#define cfe_enumenv(a,b,d,e,f) __cfe_enumenv(a,b,d,e,f)
-#define cfe_enummem(a,b,c,d,e) __cfe_enummem(a,b,c,d,e)
-#define cfe_exit(a,b) __cfe_exit(a,b)
-#define cfe_flushcache(a) __cfe_cacheflush(a)
-#define cfe_getdevinfo(a) __cfe_getdevinfo(a)
-#define cfe_getenv(a,b,c) __cfe_getenv(a,b,c)
-#define cfe_getfwinfo(a) __cfe_getfwinfo(a)
-#define cfe_getstdhandle(a) __cfe_getstdhandle(a)
-#define cfe_init(a,b) __cfe_init(a,b)
-#define cfe_inpstat(a) __cfe_inpstat(a)
-#define cfe_ioctl(a,b,c,d,e,f) __cfe_ioctl(a,b,c,d,e,f)
-#define cfe_open(a) __cfe_open(a)
-#define cfe_read(a,b,c) __cfe_read(a,b,c)
-#define cfe_readblk(a,b,c,d) __cfe_readblk(a,b,c,d)
-#define cfe_setenv(a,b) __cfe_setenv(a,b)
-#define cfe_write(a,b,c) __cfe_write(a,b,c)
-#define cfe_writeblk(a,b,c,d) __cfe_writeblk(a,b,c,d)
-#endif /* CFE_API_IMPL_NAMESPACE */
-
-int cfe_close(int handle);
-int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1);
-int cfe_cpu_stop(int cpu);
-int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen);
-int cfe_enummem(int idx, int flags, uint64_t * start, uint64_t * length,
- uint64_t * type);
-int cfe_exit(int warm, int status);
-int cfe_flushcache(int flg);
-int cfe_getdevinfo(char *name);
-int cfe_getenv(char *name, char *dest, int destlen);
-int cfe_getfwinfo(cfe_fwinfo_t * info);
-int cfe_getstdhandle(int flg);
-int cfe_init(uint64_t handle, uint64_t ept);
-int cfe_inpstat(int handle);
-int cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer,
- int length, int *retlen, uint64_t offset);
-int cfe_open(char *name);
-int cfe_read(int handle, unsigned char *buffer, int length);
-int cfe_readblk(int handle, int64_t offset, unsigned char *buffer,
- int length);
-int cfe_setenv(char *name, char *val);
-int cfe_write(int handle, unsigned char *buffer, int length);
-int cfe_writeblk(int handle, int64_t offset, unsigned char *buffer,
- int length);
-
-#endif /* CFE_API_H */
diff --git a/arch/mips/sibyte/cfe/cfe_api_int.h b/arch/mips/sibyte/cfe/cfe_api_int.h
deleted file mode 100644
index f7e5a64b55f..00000000000
--- a/arch/mips/sibyte/cfe/cfe_api_int.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 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.
- */
-
-/* *********************************************************************
- *
- * Broadcom Common Firmware Environment (CFE)
- *
- * Device function prototypes File: cfe_api_int.h
- *
- * This header defines all internal types and macros for the
- * library. This is stuff that's not exported to an app
- * using the library.
- *
- * Authors: Mitch Lichtenberg, Chris Demetriou
- *
- ********************************************************************* */
-
-#ifndef CFE_API_INT_H
-#define CFE_API_INT_H
-
-/* *********************************************************************
- * Constants
- ********************************************************************* */
-
-#define CFE_CMD_FW_GETINFO 0
-#define CFE_CMD_FW_RESTART 1
-#define CFE_CMD_FW_BOOT 2
-#define CFE_CMD_FW_CPUCTL 3
-#define CFE_CMD_FW_GETTIME 4
-#define CFE_CMD_FW_MEMENUM 5
-#define CFE_CMD_FW_FLUSHCACHE 6
-
-#define CFE_CMD_DEV_GETHANDLE 9
-#define CFE_CMD_DEV_ENUM 10
-#define CFE_CMD_DEV_OPEN 11
-#define CFE_CMD_DEV_INPSTAT 12
-#define CFE_CMD_DEV_READ 13
-#define CFE_CMD_DEV_WRITE 14
-#define CFE_CMD_DEV_IOCTL 15
-#define CFE_CMD_DEV_CLOSE 16
-#define CFE_CMD_DEV_GETINFO 17
-
-#define CFE_CMD_ENV_ENUM 20
-#define CFE_CMD_ENV_GET 22
-#define CFE_CMD_ENV_SET 23
-#define CFE_CMD_ENV_DEL 24
-
-#define CFE_CMD_MAX 32
-
-#define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */
-
-/* *********************************************************************
- * Structures
- ********************************************************************* */
-
-typedef uint64_t cfe_xuint_t;
-typedef int64_t cfe_xint_t;
-typedef int64_t cfe_xptr_t;
-
-typedef struct xiocb_buffer_s {
- cfe_xuint_t buf_offset; /* offset on device (bytes) */
- cfe_xptr_t buf_ptr; /* pointer to a buffer */
- cfe_xuint_t buf_length; /* length of this buffer */
- cfe_xuint_t buf_retlen; /* returned length (for read ops) */
- cfe_xuint_t buf_ioctlcmd; /* IOCTL command (used only for IOCTLs) */
-} xiocb_buffer_t;
-
-#define buf_devflags buf_ioctlcmd /* returned device info flags */
-
-typedef struct xiocb_inpstat_s {
- cfe_xuint_t inp_status; /* 1 means input available */
-} xiocb_inpstat_t;
-
-typedef struct xiocb_envbuf_s {
- cfe_xint_t enum_idx; /* 0-based enumeration index */
- cfe_xptr_t name_ptr; /* name string buffer */
- cfe_xint_t name_length; /* size of name buffer */
- cfe_xptr_t val_ptr; /* value string buffer */
- cfe_xint_t val_length; /* size of value string buffer */
-} xiocb_envbuf_t;
-
-typedef struct xiocb_cpuctl_s {
- cfe_xuint_t cpu_number; /* cpu number to control */
- cfe_xuint_t cpu_command; /* command to issue to CPU */
- cfe_xuint_t start_addr; /* CPU start address */
- cfe_xuint_t gp_val; /* starting GP value */
- cfe_xuint_t sp_val; /* starting SP value */
- cfe_xuint_t a1_val; /* starting A1 value */
-} xiocb_cpuctl_t;
-
-typedef struct xiocb_time_s {
- cfe_xint_t ticks; /* current time in ticks */
-} xiocb_time_t;
-
-typedef struct xiocb_exitstat_s {
- cfe_xint_t status;
-} xiocb_exitstat_t;
-
-typedef struct xiocb_meminfo_s {
- cfe_xint_t mi_idx; /* 0-based enumeration index */
- cfe_xint_t mi_type; /* type of memory block */
- cfe_xuint_t mi_addr; /* physical start address */
- cfe_xuint_t mi_size; /* block size */
-} xiocb_meminfo_t;
-
-typedef struct xiocb_fwinfo_s {
- cfe_xint_t fwi_version; /* major, minor, eco version */
- cfe_xint_t fwi_totalmem; /* total installed mem */
- cfe_xint_t fwi_flags; /* various flags */
- cfe_xint_t fwi_boardid; /* board ID */
- cfe_xint_t fwi_bootarea_va; /* VA of boot area */
- cfe_xint_t fwi_bootarea_pa; /* PA of boot area */
- cfe_xint_t fwi_bootarea_size; /* size of boot area */
- cfe_xint_t fwi_reserved1;
- cfe_xint_t fwi_reserved2;
- cfe_xint_t fwi_reserved3;
-} xiocb_fwinfo_t;
-
-typedef struct cfe_xiocb_s {
- cfe_xuint_t xiocb_fcode; /* IOCB function code */
- cfe_xint_t xiocb_status; /* return status */
- cfe_xint_t xiocb_handle; /* file/device handle */
- cfe_xuint_t xiocb_flags; /* flags for this IOCB */
- cfe_xuint_t xiocb_psize; /* size of parameter list */
- union {
- xiocb_buffer_t xiocb_buffer; /* buffer parameters */
- xiocb_inpstat_t xiocb_inpstat; /* input status parameters */
- xiocb_envbuf_t xiocb_envbuf; /* environment function parameters */
- xiocb_cpuctl_t xiocb_cpuctl; /* CPU control parameters */
- xiocb_time_t xiocb_time; /* timer parameters */
- xiocb_meminfo_t xiocb_meminfo; /* memory arena info parameters */
- xiocb_fwinfo_t xiocb_fwinfo; /* firmware information */
- xiocb_exitstat_t xiocb_exitstat; /* Exit Status */
- } plist;
-} cfe_xiocb_t;
-
-#endif /* CFE_API_INT_H */
diff --git a/arch/mips/sibyte/cfe/cfe_error.h b/arch/mips/sibyte/cfe/cfe_error.h
deleted file mode 100644
index 975f00002cb..00000000000
--- a/arch/mips/sibyte/cfe/cfe_error.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002 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.
- */
-
-/* *********************************************************************
- *
- * Broadcom Common Firmware Environment (CFE)
- *
- * Error codes File: cfe_error.h
- *
- * CFE's global error code list is here.
- *
- * Author: Mitch Lichtenberg
- *
- ********************************************************************* */
-
-
-#define CFE_OK 0
-#define CFE_ERR -1 /* generic error */
-#define CFE_ERR_INV_COMMAND -2
-#define CFE_ERR_EOF -3
-#define CFE_ERR_IOERR -4
-#define CFE_ERR_NOMEM -5
-#define CFE_ERR_DEVNOTFOUND -6
-#define CFE_ERR_DEVOPEN -7
-#define CFE_ERR_INV_PARAM -8
-#define CFE_ERR_ENVNOTFOUND -9
-#define CFE_ERR_ENVREADONLY -10
-
-#define CFE_ERR_NOTELF -11
-#define CFE_ERR_NOT32BIT -12
-#define CFE_ERR_WRONGENDIAN -13
-#define CFE_ERR_BADELFVERS -14
-#define CFE_ERR_NOTMIPS -15
-#define CFE_ERR_BADELFFMT -16
-#define CFE_ERR_BADADDR -17
-
-#define CFE_ERR_FILENOTFOUND -18
-#define CFE_ERR_UNSUPPORTED -19
-
-#define CFE_ERR_HOSTUNKNOWN -20
-
-#define CFE_ERR_TIMEOUT -21
-
-#define CFE_ERR_PROTOCOLERR -22
-
-#define CFE_ERR_NETDOWN -23
-#define CFE_ERR_NONAMESERVER -24
-
-#define CFE_ERR_NOHANDLES -25
-#define CFE_ERR_ALREADYBOUND -26
-
-#define CFE_ERR_CANNOTSET -27
-#define CFE_ERR_NOMORE -28
-#define CFE_ERR_BADFILESYS -29
-#define CFE_ERR_FSNOTAVAIL -30
-
-#define CFE_ERR_INVBOOTBLOCK -31
-#define CFE_ERR_WRONGDEVTYPE -32
-#define CFE_ERR_BBCHECKSUM -33
-#define CFE_ERR_BOOTPROGCHKSUM -34
-
-#define CFE_ERR_LDRNOTAVAIL -35
-
-#define CFE_ERR_NOTREADY -36
-
-#define CFE_ERR_GETMEM -37
-#define CFE_ERR_SETMEM -38
-
-#define CFE_ERR_NOTCONN -39
-#define CFE_ERR_ADDRINUSE -40
diff --git a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c
deleted file mode 100644
index eab20e2db32..00000000000
--- a/arch/mips/sibyte/cfe/smp.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2000, 2001, 2002, 2003 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/sched.h>
-#include <linux/smp.h>
-#include <asm/processor.h>
-
-#include "cfe_api.h"
-#include "cfe_error.h"
-
-/*
- * Use CFE to find out how many CPUs are available, setting up
- * phys_cpu_present_map and the logical/physical mappings.
- * XXXKW will the boot CPU ever not be physical 0?
- *
- * Common setup before any secondaries are started
- */
-void __init plat_smp_setup(void)
-{
- int i, num;
-
- cpus_clear(phys_cpu_present_map);
- cpu_set(0, phys_cpu_present_map);
- __cpu_number_map[0] = 0;
- __cpu_logical_map[0] = 0;
-
- for (i = 1, num = 0; i < NR_CPUS; i++) {
- if (cfe_cpu_stop(i) == 0) {
- cpu_set(i, phys_cpu_present_map);
- __cpu_number_map[i] = ++num;
- __cpu_logical_map[num] = i;
- }
- }
- printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
-}
-
-void __init plat_prepare_cpus(unsigned int max_cpus)
-{
-}
-
-/*
- * Setup the PC, SP, and GP of a secondary processor and start it
- * running!
- */
-void prom_boot_secondary(int cpu, struct task_struct *idle)
-{
- int retval;
-
- retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap,
- __KSTK_TOS(idle),
- (unsigned long)task_thread_info(idle), 0);
- if (retval != 0)
- printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
-}
-
-/*
- * Code to run on secondary just after probing the CPU
- */
-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
-}
-
-/*
- * Do any tidying up before marking online and running the idle
- * loop
- */
-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
-}
-
-/*
- * Final cleanup after all secondaries booted
- */
-void prom_cpus_done(void)
-{
-}
diff --git a/arch/mips/sibyte/common/Makefile b/arch/mips/sibyte/common/Makefile
new file mode 100644
index 00000000000..b3d6bf23a66
--- /dev/null
+++ b/arch/mips/sibyte/common/Makefile
@@ -0,0 +1,4 @@
+obj-y := cfe.o
+obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o
+obj-$(CONFIG_SIBYTE_CFE_CONSOLE) += cfe_console.o
+obj-$(CONFIG_SIBYTE_TBPROF) += sb_tbprof.o
diff --git a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/common/bus_watcher.c
index bb90649fbc4..5581844c919 100644
--- a/arch/mips/sibyte/sb1250/bus_watcher.c
+++ b/arch/mips/sibyte/common/bus_watcher.c
@@ -30,13 +30,16 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
-#include <asm/system.h>
+#include <linux/seq_file.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_int.h>
#include <asm/sibyte/sb1250_scd.h>
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#include <asm/sibyte/bcm1480_regs.h>
+#endif
struct bw_stats_struct {
@@ -72,7 +75,7 @@ static void print_summary(uint32_t status, uint32_t l2_err,
* already been destructively read out of the registers.
*
* notes: this is currently used by the cache error handler
- * should provide locking against the interrupt handler
+ * should provide locking against the interrupt handler
*/
void check_bus_watcher(void)
{
@@ -81,9 +84,15 @@ void check_bus_watcher(void)
#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
/* Destructive read, clears register and interrupt */
status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS));
-#else
+#elif defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250)
/* Use non-destructive register */
status = csr_in32(IOADDR(A_SCD_BUS_ERR_STATUS_DEBUG));
+#elif defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ /* Use non-destructive register */
+ /* Same as 1250 except BUS_ERR_STATUS_DEBUG is in a different place. */
+ status = csr_in32(IOADDR(A_BCM1480_BUS_ERR_STATUS_DEBUG));
+#else
+#error bus watcher being built for unknown Sibyte SOC!
#endif
if (!(status & 0x7fffffff)) {
printk("Using last values reaped by bus watcher driver\n");
@@ -100,63 +109,60 @@ void check_bus_watcher(void)
printk("Bus watcher indicates no error\n");
}
-static int bw_print_buffer(char *page, struct bw_stats_struct *stats)
+#ifdef CONFIG_PROC_FS
+
+/* For simplicity, I want to assume a single read is required each
+ time */
+static int bw_proc_show(struct seq_file *m, void *v)
{
- int len;
-
- len = sprintf(page, "SiByte Bus Watcher statistics\n");
- len += sprintf(page+len, "-----------------------------\n");
- len += sprintf(page+len, "L2-d-cor %8ld\nL2-d-bad %8ld\n",
- stats->l2_cor_d, stats->l2_bad_d);
- len += sprintf(page+len, "L2-t-cor %8ld\nL2-t-bad %8ld\n",
- stats->l2_cor_t, stats->l2_bad_t);
- len += sprintf(page+len, "MC-d-cor %8ld\nMC-d-bad %8ld\n",
- stats->mem_cor_d, stats->mem_bad_d);
- len += sprintf(page+len, "IO-err %8ld\n", stats->bus_error);
- len += sprintf(page+len, "\nLast recorded signature:\n");
- len += sprintf(page+len, "Request %02x from %d, answered by %d with Dcode %d\n",
- (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f),
- (int)(G_SCD_BERR_TID(stats->status) >> 6),
- (int)G_SCD_BERR_RID(stats->status),
- (int)G_SCD_BERR_DCODE(stats->status));
+ struct bw_stats_struct *stats = m->private;
+
+ seq_puts(m, "SiByte Bus Watcher statistics\n");
+ seq_puts(m, "-----------------------------\n");
+ seq_printf(m, "L2-d-cor %8ld\nL2-d-bad %8ld\n",
+ stats->l2_cor_d, stats->l2_bad_d);
+ seq_printf(m, "L2-t-cor %8ld\nL2-t-bad %8ld\n",
+ stats->l2_cor_t, stats->l2_bad_t);
+ seq_printf(m, "MC-d-cor %8ld\nMC-d-bad %8ld\n",
+ stats->mem_cor_d, stats->mem_bad_d);
+ seq_printf(m, "IO-err %8ld\n", stats->bus_error);
+ seq_puts(m, "\nLast recorded signature:\n");
+ seq_printf(m, "Request %02x from %d, answered by %d with Dcode %d\n",
+ (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f),
+ (int)(G_SCD_BERR_TID(stats->status) >> 6),
+ (int)G_SCD_BERR_RID(stats->status),
+ (int)G_SCD_BERR_DCODE(stats->status));
/* XXXKW indicate multiple errors between printings, or stats
- collection (or both)? */
+ collection (or both)? */
if (stats->status & M_SCD_BERR_MULTERRS)
- len += sprintf(page+len, "Multiple errors observed since last check.\n");
+ seq_puts(m, "Multiple errors observed since last check.\n");
if (stats->status_printed) {
- len += sprintf(page+len, "(no change since last printing)\n");
+ seq_puts(m, "(no change since last printing)\n");
} else {
stats->status_printed = 1;
}
- return len;
+ return 0;
}
-#ifdef CONFIG_PROC_FS
-
-/* For simplicity, I want to assume a single read is required each
- time */
-static int bw_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int bw_proc_open(struct inode *inode, struct file *file)
{
- int len;
-
- if (off == 0) {
- len = bw_print_buffer(page, data);
- *start = page;
- } else {
- len = 0;
- *eof = 1;
- }
- return len;
+ return single_open(file, bw_proc_show, PDE_DATA(inode));
}
+static const struct file_operations bw_proc_fops = {
+ .open = bw_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static void create_proc_decoder(struct bw_stats_struct *stats)
{
struct proc_dir_entry *ent;
- ent = create_proc_read_entry("bus_watcher", S_IWUSR | S_IRUGO, NULL,
- bw_read_proc, stats);
+ ent = proc_create_data("bus_watcher", S_IWUSR | S_IRUGO, NULL,
+ &bw_proc_fops, stats);
if (!ent) {
printk(KERN_INFO "Unable to initialize bus_watcher /proc entry\n");
return;
@@ -169,18 +175,15 @@ static void create_proc_decoder(struct bw_stats_struct *stats)
* sibyte_bw_int - handle bus watcher interrupts and accumulate counts
*
* notes: possible re-entry due to multiple sources
- * should check/indicate saturation
+ * should check/indicate saturation
*/
-static irqreturn_t sibyte_bw_int(int irq, void *data, struct pt_regs *regs)
+static irqreturn_t sibyte_bw_int(int irq, void *data)
{
struct bw_stats_struct *stats = data;
unsigned long cntr;
#ifdef CONFIG_SIBYTE_BW_TRACE
int i;
#endif
-#ifndef CONFIG_PROC_FS
- char bw_buf[1024];
-#endif
#ifdef CONFIG_SIBYTE_BW_TRACE
csr_out32(M_SCD_TRACE_CFG_FREEZE, IOADDR(A_SCD_TRACE_CFG));
@@ -211,11 +214,6 @@ static irqreturn_t sibyte_bw_int(int irq, void *data, struct pt_regs *regs)
stats->bus_error += G_SCD_MEM_BUSERR(cntr);
csr_out32(0, IOADDR(A_BUS_MEM_IO_ERRORS));
-#ifndef CONFIG_PROC_FS
- bw_print_buffer(bw_buf, stats);
- printk(bw_buf);
-#endif
-
return IRQ_HANDLED;
}
diff --git a/arch/mips/sibyte/cfe/setup.c b/arch/mips/sibyte/common/cfe.c
index 6e8952da6e2..588e1806a1a 100644
--- a/arch/mips/sibyte/cfe/setup.c
+++ b/arch/mips/sibyte/common/cfe.c
@@ -28,9 +28,10 @@
#include <asm/bootinfo.h>
#include <asm/reboot.h>
#include <asm/sibyte/board.h>
+#include <asm/smp-ops.h>
-#include "cfe_api.h"
-#include "cfe_error.h"
+#include <asm/fw/cfe/cfe_api.h>
+#include <asm/fw/cfe/cfe_error.h>
/* Max ram addressable in 32-bit segments */
#ifdef CONFIG_64BIT
@@ -58,11 +59,7 @@ int cfe_cons_handle;
extern unsigned long initrd_start, initrd_end;
#endif
-#ifdef CONFIG_KGDB
-extern int kgdb_port;
-#endif
-
-static void ATTRIB_NORET cfe_linux_exit(void *arg)
+static void __noreturn cfe_linux_exit(void *arg)
{
int warm = *(int *)arg;
@@ -73,7 +70,7 @@ static void ATTRIB_NORET cfe_linux_exit(void *arg)
if (!reboot_smp) {
/* Get CPU 0 to do the cfe_exit */
reboot_smp = 1;
- smp_call_function(cfe_linux_exit, arg, 1, 0);
+ smp_call_function(cfe_linux_exit, arg, 0);
}
} else {
printk("Passing control back to CFE...\n");
@@ -83,14 +80,14 @@ static void ATTRIB_NORET cfe_linux_exit(void *arg)
while (1);
}
-static void ATTRIB_NORET cfe_linux_restart(char *command)
+static void __noreturn cfe_linux_restart(char *command)
{
static const int zero;
cfe_linux_exit((void *)&zero);
}
-static void ATTRIB_NORET cfe_linux_halt(void)
+static void __noreturn cfe_linux_halt(void)
{
static const int one = 1;
@@ -130,8 +127,8 @@ static __init void prom_meminit(void)
if ((initrd_pstart > addr) &&
(initrd_pstart < (addr + size))) {
add_memory_region(addr,
- initrd_pstart - addr,
- BOOT_MEM_RAM);
+ initrd_pstart - addr,
+ BOOT_MEM_RAM);
rd_flag = 1;
}
if ((initrd_pend > addr) &&
@@ -198,7 +195,7 @@ static int __init initrd_setup(char *str)
/*
*Initrd location comes in the form "<hex size of ramdisk in bytes>@<location in memory>"
- * e.g. initrd=3abfd@80010000. This is set up by the loader.
+ * e.g. initrd=3abfd@80010000. This is set up by the loader.
*/
for (tmp = str; *tmp != '@'; tmp++) {
if (!*tmp) {
@@ -221,10 +218,10 @@ static int __init initrd_setup(char *str)
goto fail;
}
initrd_end = initrd_start + initrd_size;
- prom_printf("Found initrd of %lx@%lx\n", initrd_size, initrd_start);
+ printk("Found initrd of %lx@%lx\n", initrd_size, initrd_start);
return 1;
fail:
- prom_printf("Bad initrd argument. Disabling initrd\n");
+ printk("Bad initrd argument. Disabling initrd\n");
initrd_start = 0;
initrd_end = 0;
return 1;
@@ -232,6 +229,9 @@ static int __init initrd_setup(char *str)
#endif
+extern struct plat_smp_ops sb_smp_ops;
+extern struct plat_smp_ops bcm1480_smp_ops;
+
/*
* prom_init is called just after the cpu type is determined, from setup_arch()
*/
@@ -242,12 +242,9 @@ void __init prom_init(void)
int argc = fw_arg0;
char **envp = (char **) fw_arg2;
int *prom_vec = (int *) fw_arg3;
-#ifdef CONFIG_KGDB
- char *arg;
-#endif
_machine_restart = cfe_linux_restart;
- _machine_halt = cfe_linux_halt;
+ _machine_halt = cfe_linux_halt;
pm_power_off = cfe_linux_halt;
/*
@@ -281,7 +278,7 @@ void __init prom_init(void)
}
if (cfe_eptseal != CFE_EPTSEAL) {
/* too early for panic to do any good */
- prom_printf("CFE's entrypoint seal doesn't match. Spinning.");
+ printk("CFE's entrypoint seal doesn't match. Spinning.");
while (1) ;
}
cfe_init(cfe_handle, cfe_ept);
@@ -290,35 +287,19 @@ void __init prom_init(void)
* boot console
*/
cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
- if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, CL_SIZE) < 0) {
- if (argc < 0) {
- /*
- * It's OK for direct boot to not provide a
- * command line
- */
- strcpy(arcs_cmdline, "root=/dev/ram0 ");
-#ifdef CONFIG_SIBYTE_PTSWARM
- strcat(arcs_cmdline, "console=ttyS0,115200 ");
-#endif
- } else {
+ if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, COMMAND_LINE_SIZE) < 0) {
+ if (argc >= 0) {
/* The loader should have set the command line */
/* too early for panic to do any good */
- prom_printf("LINUX_CMDLINE not defined in cfe.");
+ printk("LINUX_CMDLINE not defined in cfe.");
while (1) ;
}
}
-#ifdef CONFIG_KGDB
- if ((arg = strstr(arcs_cmdline,"kgdb=duart")) != NULL)
- kgdb_port = (arg[10] == '0') ? 0 : 1;
- else
- kgdb_port = 1;
-#endif
-
#ifdef CONFIG_BLK_DEV_INITRD
{
char *ptr;
- /* Need to find out early whether we've got an initrd. So scan
+ /* Need to find out early whether we've got an initrd. So scan
the list looking now */
for (ptr = arcs_cmdline; *ptr; ptr++) {
while (*ptr == ' ') {
@@ -337,16 +318,21 @@ void __init prom_init(void)
#endif /* CONFIG_BLK_DEV_INITRD */
/* Not sure this is needed, but it's the safe way. */
- arcs_cmdline[CL_SIZE-1] = 0;
+ arcs_cmdline[COMMAND_LINE_SIZE-1] = 0;
- mips_machgroup = MACH_GROUP_SIBYTE;
prom_meminit();
+
+#if defined(CONFIG_SIBYTE_BCM112X) || defined(CONFIG_SIBYTE_SB1250)
+ register_smp_ops(&sb_smp_ops);
+#endif
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ register_smp_ops(&bcm1480_smp_ops);
+#endif
}
-unsigned long __init prom_free_prom_memory(void)
+void __init prom_free_prom_memory(void)
{
/* Not sure what I'm supposed to do here. Nothing, I think */
- return 0;
}
void prom_putchar(char c)
diff --git a/arch/mips/sibyte/cfe/console.c b/arch/mips/sibyte/common/cfe_console.c
index c6ec748175b..1ad2da103fe 100644
--- a/arch/mips/sibyte/cfe/console.c
+++ b/arch/mips/sibyte/common/cfe_console.c
@@ -4,8 +4,8 @@
#include <asm/sibyte/board.h>
-#include "cfe_api.h"
-#include "cfe_error.h"
+#include <asm/fw/cfe/cfe_api.h>
+#include <asm/fw/cfe/cfe_error.h>
extern int cfe_cons_handle;
@@ -14,7 +14,7 @@ static void cfe_console_write(struct console *cons, const char *str,
{
int i, last, written;
- for (i=0,last=0; i<count; i++) {
+ for (i=0, last=0; i<count; i++) {
if (!str[i])
/* XXXKW can/should this ever happen? */
return;
@@ -46,17 +46,18 @@ static int cfe_console_setup(struct console *cons, char *str)
/* XXXKW think about interaction with 'console=' cmdline arg */
/* If none of the console options are configured, the build will break. */
if (cfe_getenv("BOOT_CONSOLE", consdev, 32) >= 0) {
-#ifdef CONFIG_SIBYTE_SB1250_DUART
+#ifdef CONFIG_SERIAL_SB1250_DUART
if (!strcmp(consdev, "uart0")) {
setleds("u0cn");
} else if (!strcmp(consdev, "uart1")) {
setleds("u1cn");
+ } else
#endif
#ifdef CONFIG_VGA_CONSOLE
- } else if (!strcmp(consdev, "pcconsole0")) {
- setleds("pccn");
-#endif
+ if (!strcmp(consdev, "pcconsole0")) {
+ setleds("pccn");
} else
+#endif
return -ENODEV;
}
return 0;
diff --git a/arch/mips/sibyte/common/sb_tbprof.c b/arch/mips/sibyte/common/sb_tbprof.c
new file mode 100644
index 00000000000..059e28c8fd9
--- /dev/null
+++ b/arch/mips/sibyte/common/sb_tbprof.c
@@ -0,0 +1,607 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2001, 2002, 2003 Broadcom Corporation
+ * Copyright (C) 2007 Ralf Baechle <ralf@linux-mips.org>
+ * Copyright (C) 2007 MIPS Technologies, Inc.
+ * written by Ralf Baechle <ralf@linux-mips.org>
+ */
+
+#undef DEBUG
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <asm/io.h>
+#include <asm/sibyte/sb1250.h>
+
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#include <asm/sibyte/bcm1480_regs.h>
+#include <asm/sibyte/bcm1480_scd.h>
+#include <asm/sibyte/bcm1480_int.h>
+#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
+#include <asm/sibyte/sb1250_regs.h>
+#include <asm/sibyte/sb1250_scd.h>
+#include <asm/sibyte/sb1250_int.h>
+#else
+#error invalid SiByte UART configuration
+#endif
+
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+#undef K_INT_TRACE_FREEZE
+#define K_INT_TRACE_FREEZE K_BCM1480_INT_TRACE_FREEZE
+#undef K_INT_PERF_CNT
+#define K_INT_PERF_CNT K_BCM1480_INT_PERF_CNT
+#endif
+
+#include <asm/uaccess.h>
+
+#define SBPROF_TB_MAJOR 240
+
+typedef u64 tb_sample_t[6*256];
+
+enum open_status {
+ SB_CLOSED,
+ SB_OPENING,
+ SB_OPEN
+};
+
+struct sbprof_tb {
+ wait_queue_head_t tb_sync;
+ wait_queue_head_t tb_read;
+ struct mutex lock;
+ enum open_status open;
+ tb_sample_t *sbprof_tbbuf;
+ int next_tb_sample;
+
+ volatile int tb_enable;
+ volatile int tb_armed;
+
+};
+
+static struct sbprof_tb sbp;
+
+#define MAX_SAMPLE_BYTES (24*1024*1024)
+#define MAX_TBSAMPLE_BYTES (12*1024*1024)
+
+#define MAX_SAMPLES (MAX_SAMPLE_BYTES/sizeof(u_int32_t))
+#define TB_SAMPLE_SIZE (sizeof(tb_sample_t))
+#define MAX_TB_SAMPLES (MAX_TBSAMPLE_BYTES/TB_SAMPLE_SIZE)
+
+/* ioctls */
+#define SBPROF_ZBSTART _IOW('s', 0, int)
+#define SBPROF_ZBSTOP _IOW('s', 1, int)
+#define SBPROF_ZBWAITFULL _IOW('s', 2, int)
+
+/*
+ * Routines for using 40-bit SCD cycle counter
+ *
+ * Client responsible for either handling interrupts or making sure
+ * the cycles counter never saturates, e.g., by doing
+ * zclk_timer_init(0) at least every 2^40 - 1 ZCLKs.
+ */
+
+/*
+ * Configures SCD counter 0 to count ZCLKs starting from val;
+ * Configures SCD counters1,2,3 to count nothing.
+ * Must not be called while gathering ZBbus profiles.
+ */
+
+#define zclk_timer_init(val) \
+ __asm__ __volatile__ (".set push;" \
+ ".set mips64;" \
+ "la $8, 0xb00204c0;" /* SCD perf_cnt_cfg */ \
+ "sd %0, 0x10($8);" /* write val to counter0 */ \
+ "sd %1, 0($8);" /* config counter0 for zclks*/ \
+ ".set pop" \
+ : /* no outputs */ \
+ /* enable, counter0 */ \
+ : /* inputs */ "r"(val), "r" ((1ULL << 33) | 1ULL) \
+ : /* modifies */ "$8" )
+
+
+/* Reads SCD counter 0 and puts result in value
+ unsigned long long val; */
+#define zclk_get(val) \
+ __asm__ __volatile__ (".set push;" \
+ ".set mips64;" \
+ "la $8, 0xb00204c0;" /* SCD perf_cnt_cfg */ \
+ "ld %0, 0x10($8);" /* write val to counter0 */ \
+ ".set pop" \
+ : /* outputs */ "=r"(val) \
+ : /* inputs */ \
+ : /* modifies */ "$8" )
+
+#define DEVNAME "sb_tbprof"
+
+#define TB_FULL (sbp.next_tb_sample == MAX_TB_SAMPLES)
+
+/*
+ * Support for ZBbus sampling using the trace buffer
+ *
+ * We use the SCD performance counter interrupt, caused by a Zclk counter
+ * overflow, to trigger the start of tracing.
+ *
+ * We set the trace buffer to sample everything and freeze on
+ * overflow.
+ *
+ * We map the interrupt for trace_buffer_freeze to handle it on CPU 0.
+ *
+ */
+
+static u64 tb_period;
+
+static void arm_tb(void)
+{
+ u64 scdperfcnt;
+ u64 next = (1ULL << 40) - tb_period;
+ u64 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
+ */
+ __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.
+ */
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ __raw_writeq((scdperfcnt & ~M_SPC_CFG_SRC1) |
+ /* keep counters 0,2,3,4,5,6,7 as is */
+ V_SPC_CFG_SRC1(1), /* counter 1 counts cycles */
+ IOADDR(A_BCM1480_SCD_PERF_CNT_CFG0));
+ __raw_writeq(
+ M_SPC_CFG_ENABLE | /* enable counting */
+ M_SPC_CFG_CLEAR | /* clear all counters */
+ V_SPC_CFG_SRC1(1), /* counter 1 counts cycles */
+ IOADDR(A_BCM1480_SCD_PERF_CNT_CFG1));
+#else
+ __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));
+#endif
+ __raw_writeq(next, IOADDR(A_SCD_PERF_CNT_1));
+ /* Reset the trace buffer */
+ __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
+ __raw_writeq(tb_options, IOADDR(A_SCD_TRACE_CFG));
+ sbp.tb_armed = 1;
+}
+
+static irqreturn_t sbprof_tb_intr(int irq, void *dev_id)
+{
+ int i;
+
+ pr_debug(DEVNAME ": tb_intr\n");
+
+ if (sbp.next_tb_sample < MAX_TB_SAMPLES) {
+ /* XXX should use XKPHYS to make writes bypass L2 */
+ u64 *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++];
+ /* Read out trace */
+ __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] = __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) {
+ pr_debug(DEVNAME ": tb_intr shutdown\n");
+ __raw_writeq(M_SCD_TRACE_CFG_RESET,
+ IOADDR(A_SCD_TRACE_CFG));
+ sbp.tb_armed = 0;
+ wake_up_interruptible(&sbp.tb_sync);
+ } else {
+ /* knock down current interrupt and get another one later */
+ arm_tb();
+ }
+ } else {
+ /* No more trace buffer samples */
+ pr_debug(DEVNAME ": tb_intr full\n");
+ __raw_writeq(M_SCD_TRACE_CFG_RESET, IOADDR(A_SCD_TRACE_CFG));
+ sbp.tb_armed = 0;
+ if (!sbp.tb_enable)
+ wake_up_interruptible(&sbp.tb_sync);
+ wake_up_interruptible(&sbp.tb_read);
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t sbprof_pc_intr(int irq, void *dev_id)
+{
+ printk(DEVNAME ": unexpected pc_intr");
+ return IRQ_NONE;
+}
+
+/*
+ * Requires: Already called zclk_timer_init with a value that won't
+ * saturate 40 bits. No subsequent use of SCD performance counters
+ * or trace buffer.
+ */
+
+static int sbprof_zbprof_start(struct file *filp)
+{
+ u64 scdperfcnt;
+ int err;
+
+ if (xchg(&sbp.tb_enable, 1))
+ return -EBUSY;
+
+ pr_debug(DEVNAME ": starting\n");
+
+ sbp.next_tb_sample = 0;
+ filp->f_pos = 0;
+
+ err = request_irq(K_INT_TRACE_FREEZE, sbprof_tb_intr, 0,
+ DEVNAME " trace freeze", &sbp);
+ if (err)
+ return -EBUSY;
+
+ /* Make sure there isn't a perf-cnt interrupt waiting */
+ scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
+ /* Disable and clear counters, override SRC_1 */
+ __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
+ * (they only feed into the trace-on-interrupt mechanism)
+ */
+ if (request_irq(K_INT_PERF_CNT, sbprof_pc_intr, 0, DEVNAME " scd perfcnt", &sbp)) {
+ free_irq(K_INT_TRACE_FREEZE, &sbp);
+ return -EBUSY;
+ }
+
+ /*
+ * 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
+ */
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ __raw_writeq(K_BCM1480_INT_MAP_I3,
+ IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_MAP_BASE_L) +
+ ((K_BCM1480_INT_PERF_CNT & 0x3f) << 3)));
+#else
+ __raw_writeq(K_INT_MAP_I3,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
+ (K_INT_PERF_CNT << 3)));
+#endif
+
+ /* Initialize address traps */
+ __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));
+
+ __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));
+
+ __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 */
+ __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) */
+ __raw_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff,
+ IOADDR(A_SCD_TRACE_SEQUENCE_0));
+ /* dsamp when d used | asamp when a used */
+ __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 */
+#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
+ __raw_writeq(1ULL << (K_BCM1480_INT_PERF_CNT & 0x3f),
+ IOADDR(A_BCM1480_IMR_REGISTER(0, R_BCM1480_IMR_INTERRUPT_TRACE_L)));
+#else
+ __raw_writeq(1ULL << K_INT_PERF_CNT,
+ IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)));
+#endif
+ arm_tb();
+
+ pr_debug(DEVNAME ": done starting\n");
+
+ return 0;
+}
+
+static int sbprof_zbprof_stop(void)
+{
+ int err = 0;
+
+ pr_debug(DEVNAME ": stopping\n");
+
+ if (sbp.tb_enable) {
+ /*
+ * XXXKW there is a window here where the intr handler may run,
+ * see the disable, and do the wake_up before this sleep
+ * happens.
+ */
+ pr_debug(DEVNAME ": wait for disarm\n");
+ err = wait_event_interruptible(sbp.tb_sync, !sbp.tb_armed);
+ pr_debug(DEVNAME ": disarm complete, stat %d\n", err);
+
+ if (err)
+ return err;
+
+ sbp.tb_enable = 0;
+ free_irq(K_INT_TRACE_FREEZE, &sbp);
+ free_irq(K_INT_PERF_CNT, &sbp);
+ }
+
+ pr_debug(DEVNAME ": done stopping\n");
+
+ return err;
+}
+
+static int sbprof_tb_open(struct inode *inode, struct file *filp)
+{
+ int minor;
+
+ minor = iminor(inode);
+ if (minor != 0)
+ return -ENODEV;
+
+ if (xchg(&sbp.open, SB_OPENING) != SB_CLOSED)
+ return -EBUSY;
+
+ memset(&sbp, 0, sizeof(struct sbprof_tb));
+ sbp.sbprof_tbbuf = vzalloc(MAX_TBSAMPLE_BYTES);
+ if (!sbp.sbprof_tbbuf) {
+ sbp.open = SB_CLOSED;
+ wmb();
+ return -ENOMEM;
+ }
+
+ init_waitqueue_head(&sbp.tb_sync);
+ init_waitqueue_head(&sbp.tb_read);
+ mutex_init(&sbp.lock);
+
+ sbp.open = SB_OPEN;
+ wmb();
+
+ return 0;
+}
+
+static int sbprof_tb_release(struct inode *inode, struct file *filp)
+{
+ int minor;
+
+ minor = iminor(inode);
+ if (minor != 0 || sbp.open != SB_CLOSED)
+ return -ENODEV;
+
+ mutex_lock(&sbp.lock);
+
+ if (sbp.tb_armed || sbp.tb_enable)
+ sbprof_zbprof_stop();
+
+ vfree(sbp.sbprof_tbbuf);
+ sbp.open = SB_CLOSED;
+ wmb();
+
+ mutex_unlock(&sbp.lock);
+
+ return 0;
+}
+
+static ssize_t sbprof_tb_read(struct file *filp, char *buf,
+ size_t size, loff_t *offp)
+{
+ int cur_sample, sample_off, cur_count, sample_left;
+ char *src;
+ int count = 0;
+ char *dest = buf;
+ long cur_off = *offp;
+
+ if (!access_ok(VERIFY_WRITE, buf, size))
+ return -EFAULT;
+
+ mutex_lock(&sbp.lock);
+
+ count = 0;
+ cur_sample = cur_off / TB_SAMPLE_SIZE;
+ sample_off = cur_off % TB_SAMPLE_SIZE;
+ sample_left = TB_SAMPLE_SIZE - sample_off;
+
+ while (size && (cur_sample < sbp.next_tb_sample)) {
+ int err;
+
+ cur_count = size < sample_left ? size : sample_left;
+ src = (char *)(((long)sbp.sbprof_tbbuf[cur_sample])+sample_off);
+ err = __copy_to_user(dest, src, cur_count);
+ if (err) {
+ *offp = cur_off + cur_count - err;
+ mutex_unlock(&sbp.lock);
+ return err;
+ }
+ pr_debug(DEVNAME ": read from sample %d, %d bytes\n",
+ cur_sample, cur_count);
+ size -= cur_count;
+ sample_left -= cur_count;
+ if (!sample_left) {
+ cur_sample++;
+ sample_off = 0;
+ sample_left = TB_SAMPLE_SIZE;
+ } else {
+ sample_off += cur_count;
+ }
+ cur_off += cur_count;
+ dest += cur_count;
+ count += cur_count;
+ }
+ *offp = cur_off;
+ mutex_unlock(&sbp.lock);
+
+ return count;
+}
+
+static long sbprof_tb_ioctl(struct file *filp,
+ unsigned int command,
+ unsigned long arg)
+{
+ int err = 0;
+
+ switch (command) {
+ case SBPROF_ZBSTART:
+ mutex_lock(&sbp.lock);
+ err = sbprof_zbprof_start(filp);
+ mutex_unlock(&sbp.lock);
+ break;
+
+ case SBPROF_ZBSTOP:
+ mutex_lock(&sbp.lock);
+ err = sbprof_zbprof_stop();
+ mutex_unlock(&sbp.lock);
+ break;
+
+ case SBPROF_ZBWAITFULL: {
+ err = wait_event_interruptible(sbp.tb_read, TB_FULL);
+ if (err)
+ break;
+
+ err = put_user(TB_FULL, (int *) arg);
+ break;
+ }
+
+ default:
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static const struct file_operations sbprof_tb_fops = {
+ .owner = THIS_MODULE,
+ .open = sbprof_tb_open,
+ .release = sbprof_tb_release,
+ .read = sbprof_tb_read,
+ .unlocked_ioctl = sbprof_tb_ioctl,
+ .compat_ioctl = sbprof_tb_ioctl,
+ .mmap = NULL,
+ .llseek = default_llseek,
+};
+
+static struct class *tb_class;
+static struct device *tb_dev;
+
+static int __init sbprof_tb_init(void)
+{
+ struct device *dev;
+ struct class *tbc;
+ int err;
+
+ if (register_chrdev(SBPROF_TB_MAJOR, DEVNAME, &sbprof_tb_fops)) {
+ printk(KERN_WARNING DEVNAME ": initialization failed (dev %d)\n",
+ SBPROF_TB_MAJOR);
+ return -EIO;
+ }
+
+ tbc = class_create(THIS_MODULE, "sb_tracebuffer");
+ if (IS_ERR(tbc)) {
+ err = PTR_ERR(tbc);
+ goto out_chrdev;
+ }
+
+ tb_class = tbc;
+
+ dev = device_create(tbc, NULL, MKDEV(SBPROF_TB_MAJOR, 0), NULL, "tb");
+ if (IS_ERR(dev)) {
+ err = PTR_ERR(dev);
+ goto out_class;
+ }
+ tb_dev = dev;
+
+ sbp.open = SB_CLOSED;
+ wmb();
+ tb_period = zbbus_mhz * 10000LL;
+ pr_info(DEVNAME ": initialized - tb_period = %lld\n",
+ (long long) tb_period);
+ return 0;
+
+out_class:
+ class_destroy(tb_class);
+out_chrdev:
+ unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME);
+
+ return err;
+}
+
+static void __exit sbprof_tb_cleanup(void)
+{
+ device_destroy(tb_class, MKDEV(SBPROF_TB_MAJOR, 0));
+ unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME);
+ class_destroy(tb_class);
+}
+
+module_init(sbprof_tb_init);
+module_exit(sbprof_tb_cleanup);
+
+MODULE_ALIAS_CHARDEV_MAJOR(SBPROF_TB_MAJOR);
+MODULE_AUTHOR("Ralf Baechle <ralf@linux-mips.org>");
+MODULE_LICENSE("GPL");
diff --git a/arch/mips/sibyte/sb1250/Makefile b/arch/mips/sibyte/sb1250/Makefile
index a2fdbd62f8a..cdc4c56c3e2 100644
--- a/arch/mips/sibyte/sb1250/Makefile
+++ b/arch/mips/sibyte/sb1250/Makefile
@@ -1,8 +1,3 @@
obj-y := setup.o irq.o time.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_SIBYTE_TBPROF) += bcm1250_tbprof.o
-obj-$(CONFIG_SIBYTE_STANDALONE) += prom.o
-obj-$(CONFIG_SIBYTE_BUS_WATCHER) += bus_watcher.o
-
-EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c b/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
deleted file mode 100644
index 992e0d8dbb6..00000000000
--- a/arch/mips/sibyte/sb1250/bcm1250_tbprof.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright (C) 2001, 2002, 2003 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.
- */
-
-#define SBPROF_TB_DEBUG 0
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#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>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_scd.h>
-#include <asm/sibyte/sb1250_int.h>
-#include <asm/sibyte/trace_prof.h>
-
-#define DEVNAME "bcm1250_tbprof"
-
-static struct sbprof_tb sbp;
-
-#define TB_FULL (sbp.next_tb_sample == MAX_TB_SAMPLES)
-
-/************************************************************************
- * Support for ZBbus sampling using the trace buffer
- *
- * We use the SCD performance counter interrupt, caused by a Zclk counter
- * overflow, to trigger the start of tracing.
- *
- * We set the trace buffer to sample everything and freeze on
- * overflow.
- *
- * We map the interrupt for trace_buffer_freeze to handle it on CPU 0.
- *
- ************************************************************************/
-
-static u_int64_t tb_period;
-
-static void arm_tb(void)
-{
- u_int64_t scdperfcnt;
- u_int64_t next = (1ULL << 40) - tb_period;
- 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 */
- __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. */
- __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 */
- __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
- __raw_writeq(tb_options, IOADDR(A_SCD_TRACE_CFG));
- sbp.tb_armed = 1;
-}
-
-static irqreturn_t sbprof_tb_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
- int i;
- DBG(printk(DEVNAME ": tb_intr\n"));
- if (sbp.next_tb_sample < MAX_TB_SAMPLES) {
- /* XXX should use XKPHYS to make writes bypass L2 */
- u_int64_t *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++];
- /* Read out trace */
- __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] = __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"));
- __raw_writeq(M_SCD_TRACE_CFG_RESET,
- IOADDR(A_SCD_TRACE_CFG));
- sbp.tb_armed = 0;
- wake_up(&sbp.tb_sync);
- } else {
- arm_tb(); // knock down current interrupt and get another one later
- }
- } else {
- /* No more trace buffer samples */
- DBG(printk(DEVNAME ": tb_intr full\n"));
- __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);
- }
- wake_up(&sbp.tb_read);
- }
- return IRQ_HANDLED;
-}
-
-static irqreturn_t sbprof_pc_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
- printk(DEVNAME ": unexpected pc_intr");
- return IRQ_NONE;
-}
-
-int sbprof_zbprof_start(struct file *filp)
-{
- u_int64_t scdperfcnt;
-
- if (sbp.tb_enable)
- return -EBUSY;
-
- DBG(printk(DEVNAME ": starting\n"));
-
- sbp.tb_enable = 1;
- sbp.next_tb_sample = 0;
- filp->f_pos = 0;
-
- if (request_irq
- (K_INT_TRACE_FREEZE, sbprof_tb_intr, 0, DEVNAME " trace freeze", &sbp)) {
- return -EBUSY;
- }
- /* Make sure there isn't a perf-cnt interrupt waiting */
- scdperfcnt = __raw_readq(IOADDR(A_SCD_PERF_CNT_CFG));
- /* Disable and clear counters, override SRC_1 */
- __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
- (they only feed into the trace-on-interrupt mechanism) */
- if (request_irq
- (K_INT_PERF_CNT, sbprof_pc_intr, 0, DEVNAME " scd perfcnt", &sbp)) {
- free_irq(K_INT_TRACE_FREEZE, &sbp);
- return -EBUSY;
- }
-
- /* 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 */
- __raw_writeq(K_INT_MAP_I3,
- IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) +
- (K_INT_PERF_CNT << 3)));
-
- /* Initialize address traps */
- __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));
-
- __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));
-
- __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
- __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)
- __raw_writeq(V_SCD_TRSEQ_FUNC_START | 0x0fff,
- IOADDR(A_SCD_TRACE_SEQUENCE_0));
- // dsamp when d used | asamp when a used
- __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 */
- __raw_writeq(1ULL << K_INT_PERF_CNT,
- IOADDR(A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)));
-
- arm_tb();
-
- DBG(printk(DEVNAME ": done starting\n"));
-
- return 0;
-}
-
-int sbprof_zbprof_stop(void)
-{
- DEFINE_WAIT(wait);
- DBG(printk(DEVNAME ": stopping\n"));
-
- if (sbp.tb_enable) {
- sbp.tb_enable = 0;
- /* XXXKW there is a window here where the intr handler
- may run, see the disable, and do the wake_up before
- this sleep happens. */
- if (sbp.tb_armed) {
- DBG(printk(DEVNAME ": wait for disarm\n"));
- 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);
- free_irq(K_INT_PERF_CNT, &sbp);
- }
-
- DBG(printk(DEVNAME ": done stopping\n"));
-
- return 0;
-}
-
-static int sbprof_tb_open(struct inode *inode, struct file *filp)
-{
- int minor;
-
- minor = iminor(inode);
- if (minor != 0) {
- return -ENODEV;
- }
- if (sbp.open) {
- return -EBUSY;
- }
-
- memset(&sbp, 0, sizeof(struct sbprof_tb));
- sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES);
- if (!sbp.sbprof_tbbuf) {
- return -ENOMEM;
- }
- memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES);
- init_waitqueue_head(&sbp.tb_sync);
- init_waitqueue_head(&sbp.tb_read);
- sbp.open = 1;
-
- return 0;
-}
-
-static int sbprof_tb_release(struct inode *inode, struct file *filp)
-{
- int minor;
-
- minor = iminor(inode);
- if (minor != 0 || !sbp.open) {
- return -ENODEV;
- }
-
- if (sbp.tb_armed || sbp.tb_enable) {
- sbprof_zbprof_stop();
- }
-
- vfree(sbp.sbprof_tbbuf);
- sbp.open = 0;
-
- return 0;
-}
-
-static ssize_t sbprof_tb_read(struct file *filp, char *buf,
- size_t size, loff_t *offp)
-{
- int cur_sample, sample_off, cur_count, sample_left;
- char *src;
- int count = 0;
- char *dest = buf;
- long cur_off = *offp;
-
- count = 0;
- cur_sample = cur_off / TB_SAMPLE_SIZE;
- sample_off = cur_off % TB_SAMPLE_SIZE;
- sample_left = TB_SAMPLE_SIZE - sample_off;
- while (size && (cur_sample < sbp.next_tb_sample)) {
- cur_count = size < sample_left ? size : sample_left;
- src = (char *)(((long)sbp.sbprof_tbbuf[cur_sample])+sample_off);
- copy_to_user(dest, src, cur_count);
- DBG(printk(DEVNAME ": read from sample %d, %d bytes\n",
- cur_sample, cur_count));
- size -= cur_count;
- sample_left -= cur_count;
- if (!sample_left) {
- cur_sample++;
- sample_off = 0;
- sample_left = TB_SAMPLE_SIZE;
- } else {
- sample_off += cur_count;
- }
- cur_off += cur_count;
- dest += cur_count;
- count += cur_count;
- }
- *offp = cur_off;
-
- return count;
-}
-
-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);
- break;
- case SBPROF_ZBSTOP:
- error = sbprof_zbprof_stop();
- break;
- case SBPROF_ZBWAITFULL:
- 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;
-}
-
-static struct file_operations sbprof_tb_fops = {
- .owner = THIS_MODULE,
- .open = sbprof_tb_open,
- .release = sbprof_tb_release,
- .read = sbprof_tb_read,
- .unlocked_ioctl = sbprof_tb_ioctl,
- .compat_ioctl = sbprof_tb_ioctl,
- .mmap = NULL,
-};
-
-static int __init sbprof_tb_init(void)
-{
- if (register_chrdev(SBPROF_TB_MAJOR, DEVNAME, &sbprof_tb_fops)) {
- printk(KERN_WARNING DEVNAME ": initialization failed (dev %d)\n",
- SBPROF_TB_MAJOR);
- return -EIO;
- }
- sbp.open = 0;
- tb_period = zbbus_mhz * 10000LL;
- printk(KERN_INFO DEVNAME ": initialized - tb_period = %lld\n", tb_period);
- return 0;
-}
-
-static void __exit sbprof_tb_cleanup(void)
-{
- unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME);
-}
-
-module_init(sbprof_tb_init);
-module_exit(sbprof_tb_cleanup);
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index a451b4c7732..6d8dba5cf34 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -22,13 +22,11 @@
#include <linux/spinlock.h>
#include <linux/smp.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/time.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250_regs.h>
@@ -44,61 +42,27 @@
* for interrupt lines
*/
-
-#define shutdown_sb1250_irq disable_sb1250_irq
-static void end_sb1250_irq(unsigned int irq);
-static void enable_sb1250_irq(unsigned int irq);
-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, cpumask_t mask);
-#endif
-
#ifdef CONFIG_SIBYTE_HAS_LDT
extern unsigned long ldt_eoi_space;
#endif
-#ifdef CONFIG_KGDB
-static int kgdb_irq;
-
-/* Default to UART1 */
-int kgdb_port = 1;
-#ifdef CONFIG_SIBYTE_SB1250_DUART
-extern char sb1250_duart_present[];
-#endif
-#endif
-
-static struct irq_chip sb1250_irq_type = {
- .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
- .set_affinity = sb1250_set_affinity
-#endif
-};
-
/* Store the CPU id (not the logical number) */
int sb1250_irq_owner[SB1250_NR_IRQS];
-DEFINE_SPINLOCK(sb1250_imr_lock);
+static DEFINE_RAW_SPINLOCK(sb1250_imr_lock);
void sb1250_mask_irq(int cpu, int irq)
{
unsigned long flags;
u64 cur_ints;
- spin_lock_irqsave(&sb1250_imr_lock, flags);
+ raw_spin_lock_irqsave(&sb1250_imr_lock, flags);
cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
R_IMR_INTERRUPT_MASK));
cur_ints |= (((u64) 1) << irq);
____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
R_IMR_INTERRUPT_MASK));
- spin_unlock_irqrestore(&sb1250_imr_lock, flags);
+ raw_spin_unlock_irqrestore(&sb1250_imr_lock, flags);
}
void sb1250_unmask_irq(int cpu, int irq)
@@ -106,36 +70,31 @@ void sb1250_unmask_irq(int cpu, int irq)
unsigned long flags;
u64 cur_ints;
- spin_lock_irqsave(&sb1250_imr_lock, flags);
+ raw_spin_lock_irqsave(&sb1250_imr_lock, flags);
cur_ints = ____raw_readq(IOADDR(A_IMR_MAPPER(cpu) +
R_IMR_INTERRUPT_MASK));
cur_ints &= ~(((u64) 1) << irq);
____raw_writeq(cur_ints, IOADDR(A_IMR_MAPPER(cpu) +
R_IMR_INTERRUPT_MASK));
- spin_unlock_irqrestore(&sb1250_imr_lock, flags);
+ raw_spin_unlock_irqrestore(&sb1250_imr_lock, flags);
}
#ifdef CONFIG_SMP
-static void sb1250_set_affinity(unsigned int irq, cpumask_t mask)
+static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask,
+ bool force)
{
int i = 0, old_cpu, cpu, int_on;
+ unsigned int irq = d->irq;
u64 cur_ints;
- struct irq_desc *desc = irq_desc + irq;
unsigned long flags;
- i = first_cpu(mask);
-
- if (cpus_weight(mask) > 1) {
- printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq);
- return;
- }
+ i = cpumask_first_and(mask, cpu_online_mask);
/* 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(&sb1250_imr_lock);
+ raw_spin_lock_irqsave(&sb1250_imr_lock, flags);
/* Swizzle each CPU's IMR (but leave the IP selection alone) */
old_cpu = sb1250_irq_owner[irq];
@@ -157,34 +116,30 @@ static void sb1250_set_affinity(unsigned int irq, cpumask_t 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);
+ raw_spin_unlock_irqrestore(&sb1250_imr_lock, flags);
+
+ return 0;
}
#endif
-/*****************************************************************************/
-
-static unsigned int startup_sb1250_irq(unsigned int irq)
+static void disable_sb1250_irq(struct irq_data *d)
{
- sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
-
- return 0; /* never anything pending */
-}
+ unsigned int irq = d->irq;
-
-static void disable_sb1250_irq(unsigned int irq)
-{
sb1250_mask_irq(sb1250_irq_owner[irq], irq);
}
-static void enable_sb1250_irq(unsigned int irq)
+static void enable_sb1250_irq(struct irq_data *d)
{
+ unsigned int irq = d->irq;
+
sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
}
-static void ack_sb1250_irq(unsigned int irq)
+static void ack_sb1250_irq(struct irq_data *d)
{
+ unsigned int irq = d->irq;
#ifdef CONFIG_SIBYTE_HAS_LDT
u64 pending;
@@ -227,69 +182,28 @@ static void ack_sb1250_irq(unsigned int irq)
sb1250_mask_irq(sb1250_irq_owner[irq], irq);
}
-
-static void end_sb1250_irq(unsigned int irq)
-{
- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
- sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
- }
-}
-
+static struct irq_chip sb1250_irq_type = {
+ .name = "SB1250-IMR",
+ .irq_mask_ack = ack_sb1250_irq,
+ .irq_unmask = enable_sb1250_irq,
+ .irq_mask = disable_sb1250_irq,
+#ifdef CONFIG_SMP
+ .irq_set_affinity = sb1250_set_affinity
+#endif
+};
void __init init_sb1250_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 < SB1250_NR_IRQS) {
- irq_desc[i].chip = &sb1250_irq_type;
- sb1250_irq_owner[i] = 0;
- } else {
- irq_desc[i].chip = &no_irq_chip;
- }
+ for (i = 0; i < SB1250_NR_IRQS; i++) {
+ irq_set_chip_and_handler(i, &sb1250_irq_type,
+ handle_level_irq);
+ sb1250_irq_owner[i] = 0;
}
}
-static irqreturn_t sb1250_dummy_handler(int irq, void *dev_id,
- struct pt_regs *regs)
-{
- return IRQ_NONE;
-}
-
-static struct irqaction sb1250_dummy_action = {
- .handler = sb1250_dummy_handler,
- .flags = 0,
- .mask = CPU_MASK_NONE,
- .name = "sb1250-private",
- .next = NULL,
- .dev_id = 0
-};
-
-int sb1250_steal_irq(int irq)
-{
- struct irq_desc *desc = irq_desc + irq;
- unsigned long flags;
- int retval = 0;
-
- if (irq >= SB1250_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 = &sb1250_dummy_action;
- desc->depth = 0;
- }
- spin_unlock_irqrestore(&desc->lock,flags);
- return 0;
-}
-
/*
* arch_init_irq is called early in the boot sequence from init/main.c via
* init_IRQ. It is responsible for setting up the interrupt mapper and
@@ -307,7 +221,7 @@ int sb1250_steal_irq(int irq)
* 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
+ * can do cross-cpu function calls, as required by SMP
*/
#define IMR_IP2_VAL K_INT_MAP_I0
@@ -350,7 +264,7 @@ void __init arch_init_irq(void)
IOADDR(A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) +
(K_INT_MBOX_0 << 3)));
- /* Clear the mailboxes. The firmware may leave them dirty */
+ /* Clear the mailboxes. The firmware may leave them dirty */
__raw_writeq(0xffffffffffffffffULL,
IOADDR(A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU)));
__raw_writeq(0xffffffffffffffffULL,
@@ -361,77 +275,39 @@ void __init arch_init_irq(void)
__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);
-
/*
* Note that the timer interrupts are also mapped, but this is
- * done in sb1250_time_init(). Also, the profiling driver
+ * done in sb1250_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);
-
-#ifdef CONFIG_KGDB
- if (kgdb_flag) {
- kgdb_irq = K_INT_UART_0 + kgdb_port;
-
-#ifdef CONFIG_SIBYTE_SB1250_DUART
- sb1250_duart_present[kgdb_port] = 0;
-#endif
- /* Setup uart 1 settings, mapper */
- __raw_writeq(M_DUART_IMR_BRK,
- IOADDR(A_DUART_IMRREG(kgdb_port)));
-
- sb1250_steal_irq(kgdb_irq);
- __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
}
-#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)))
+extern void sb1250_mailbox_interrupt(void);
-static void sb1250_kgdb_interrupt(struct pt_regs *regs)
+static inline void dispatch_ip2(void)
{
+ unsigned int cpu = smp_processor_id();
+ unsigned long long mask;
+
/*
- * 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)
+ * Default...we've hit an IP[2] interrupt, which means we've got to
+ * check the 1250 interrupt registers to figure out what to do. Need
+ * to detect which CPU we're on, now that smp_affinity is supported.
*/
- kstat_this_cpu.irqs[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);
+ mask = __raw_readq(IOADDR(A_IMR_REGISTER(cpu,
+ R_IMR_INTERRUPT_STATUS_BASE)));
+ if (mask)
+ do_IRQ(fls64(mask) - 1);
}
-#endif /* CONFIG_KGDB */
-
-extern void sb1250_timer_interrupt(struct pt_regs *regs);
-extern void sb1250_mailbox_interrupt(struct pt_regs *regs);
-extern void sb1250_kgdb_interrupt(struct pt_regs *regs);
-
-asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
+asmlinkage void plat_irq_dispatch(void)
{
+ unsigned int cpu = smp_processor_id();
unsigned int pending;
-#ifdef CONFIG_SIBYTE_SB1250_PROF
- /* Set compare to count to silence count/compare timer interrupts */
- write_c0_compare(read_c0_count());
-#endif
-
/*
* 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
@@ -442,39 +318,20 @@ asmlinkage void plat_irq_dispatch(struct pt_regs *regs)
* blasting the high 32 bits.
*/
- pending = read_c0_cause();
-
-#ifdef CONFIG_SIBYTE_SB1250_PROF
- if (pending & CAUSEF_IP7) /* Cpu performance counter interrupt */
- sbprof_cpu_intr(exception_epc(regs));
- else
-#endif
+ pending = read_c0_cause() & read_c0_status() & ST0_IM;
- if (pending & CAUSEF_IP4)
- sb1250_timer_interrupt(regs);
+ if (pending & CAUSEF_IP7) /* CPU performance counter interrupt */
+ do_IRQ(MIPS_CPU_IRQ_BASE + 7);
+ else if (pending & CAUSEF_IP4)
+ do_IRQ(K_INT_TIMER_0 + cpu); /* sb1250_timer_interrupt() */
#ifdef CONFIG_SMP
else if (pending & CAUSEF_IP3)
- sb1250_mailbox_interrupt(regs);
+ sb1250_mailbox_interrupt();
#endif
-#ifdef CONFIG_KGDB
- else if (pending & CAUSEF_IP6) /* KGDB (uart 1) */
- sb1250_kgdb_interrupt(regs);
-#endif
-
- else if (pending & CAUSEF_IP2) {
- unsigned long long mask;
-
- /*
- * Default...we've hit an IP[2] interrupt, which means we've
- * got to check the 1250 interrupt registers to figure out what
- * to do. Need to detect which CPU we're on, now that
- * smp_affinity is supported.
- */
- mask = __raw_readq(IOADDR(A_IMR_REGISTER(smp_processor_id(),
- R_IMR_INTERRUPT_STATUS_BASE)));
- if (mask)
- do_IRQ(fls64(mask) - 1, regs);
- }
+ else if (pending & CAUSEF_IP2)
+ dispatch_ip2();
+ else
+ spurious_interrupt();
}
diff --git a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c
deleted file mode 100644
index 3c33a4517bc..00000000000
--- a/arch/mips/sibyte/sb1250/prom.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 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/kernel.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/bootmem.h>
-#include <linux/smp.h>
-#include <linux/initrd.h>
-#include <linux/pm.h>
-
-#include <asm/bootinfo.h>
-#include <asm/reboot.h>
-
-#define MAX_RAM_SIZE ((CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024) - 1)
-
-static __init void prom_meminit(void)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
- unsigned long initrd_pstart;
- unsigned long initrd_pend;
-
- initrd_pstart = __pa(initrd_start);
- initrd_pend = __pa(initrd_end);
- if (initrd_start &&
- ((initrd_pstart > MAX_RAM_SIZE)
- || (initrd_pend > MAX_RAM_SIZE))) {
- panic("initrd out of addressable memory");
- }
-
- add_memory_region(0, initrd_pstart,
- BOOT_MEM_RAM);
- add_memory_region(initrd_pstart, initrd_pend - initrd_pstart,
- BOOT_MEM_RESERVED);
- add_memory_region(initrd_pend,
- (CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024) - initrd_pend,
- BOOT_MEM_RAM);
-#else
- add_memory_region(0, CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024,
- BOOT_MEM_RAM);
-#endif
-}
-
-void prom_cpu0_exit(void *unused)
-{
- while (1) ;
-}
-
-static void prom_linux_exit(void)
-{
-#ifdef CONFIG_SMP
- if (smp_processor_id()) {
- smp_call_function(prom_cpu0_exit,NULL,1,1);
- }
-#endif
- while(1);
-}
-
-/*
- * prom_init is called just after the cpu type is determined, from setup_arch()
- */
-void __init prom_init(void)
-{
- _machine_restart = (void (*)(char *))prom_linux_exit;
- _machine_halt = prom_linux_exit;
- pm_power_off = prom_linux_exit;
-
- strcpy(arcs_cmdline, "root=/dev/ram0 ");
-
- mips_machgroup = MACH_GROUP_SIBYTE;
- prom_meminit();
-}
-
-unsigned long __init prom_free_prom_memory(void)
-{
- /* Not sure what I'm supposed to do here. Nothing, I think */
- return 0;
-}
-
-void prom_putchar(char c)
-{
-}
diff --git a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c
index d0ee1d5b822..3c02b2a77ae 100644
--- a/arch/mips/sibyte/sb1250/setup.c
+++ b/arch/mips/sibyte/sb1250/setup.c
@@ -16,11 +16,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/reboot.h>
#include <linux/string.h>
#include <asm/bootinfo.h>
+#include <asm/cpu.h>
#include <asm/mipsregs.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250.h>
@@ -30,50 +32,15 @@
unsigned int sb1_pass;
unsigned int soc_pass;
unsigned int soc_type;
+EXPORT_SYMBOL(soc_type);
unsigned int periph_rev;
unsigned int zbbus_mhz;
+EXPORT_SYMBOL(zbbus_mhz);
static char *soc_str;
static char *pass_str;
static unsigned int war_pass; /* XXXKW don't overload PASS defines? */
-static inline int setup_bcm1250(void);
-static inline int setup_bcm112x(void);
-
-/* Setup code likely to be common to all SiByte platforms */
-
-static int __init sys_rev_decode(void)
-{
- int ret = 0;
-
- war_pass = soc_pass;
- switch (soc_type) {
- case K_SYS_SOC_TYPE_BCM1250:
- case K_SYS_SOC_TYPE_BCM1250_ALT:
- case K_SYS_SOC_TYPE_BCM1250_ALT2:
- soc_str = "BCM1250";
- ret = setup_bcm1250();
- break;
- case K_SYS_SOC_TYPE_BCM1120:
- soc_str = "BCM1120";
- ret = setup_bcm112x();
- break;
- case K_SYS_SOC_TYPE_BCM1125:
- soc_str = "BCM1125";
- ret = setup_bcm112x();
- break;
- case K_SYS_SOC_TYPE_BCM1125H:
- soc_str = "BCM1125H";
- ret = setup_bcm112x();
- break;
- default:
- prom_printf("Unknown SOC type %x\n", soc_type);
- ret = 1;
- break;
- }
- return ret;
-}
-
static int __init setup_bcm1250(void)
{
int ret = 0;
@@ -112,14 +79,30 @@ static int __init setup_bcm1250(void)
pass_str = "A0-A6";
war_pass = K_SYS_REVISION_BCM1250_PASS2;
} else {
- prom_printf("Unknown BCM1250 rev %x\n", soc_pass);
+ printk("Unknown BCM1250 rev %x\n", soc_pass);
ret = 1;
}
break;
}
+
return ret;
}
+int sb1250_m3_workaround_needed(void)
+{
+ switch (soc_type) {
+ case K_SYS_SOC_TYPE_BCM1250:
+ case K_SYS_SOC_TYPE_BCM1250_ALT:
+ case K_SYS_SOC_TYPE_BCM1250_ALT2:
+ case K_SYS_SOC_TYPE_BCM1125:
+ case K_SYS_SOC_TYPE_BCM1125H:
+ return soc_pass < K_SYS_REVISION_BCM1250_C0;
+
+ default:
+ return 0;
+ }
+}
+
static int __init setup_bcm112x(void)
{
int ret = 0;
@@ -139,10 +122,58 @@ static int __init setup_bcm112x(void)
periph_rev = 3;
pass_str = "A2";
break;
+ case K_SYS_REVISION_BCM112x_A3:
+ periph_rev = 3;
+ pass_str = "A3";
+ break;
+ case K_SYS_REVISION_BCM112x_A4:
+ periph_rev = 3;
+ pass_str = "A4";
+ break;
+ case K_SYS_REVISION_BCM112x_B0:
+ periph_rev = 3;
+ pass_str = "B0";
+ break;
+ default:
+ printk("Unknown %s rev %x\n", soc_str, soc_pass);
+ ret = 1;
+ }
+
+ return ret;
+}
+
+/* Setup code likely to be common to all SiByte platforms */
+
+static int __init sys_rev_decode(void)
+{
+ int ret = 0;
+
+ war_pass = soc_pass;
+ switch (soc_type) {
+ case K_SYS_SOC_TYPE_BCM1250:
+ case K_SYS_SOC_TYPE_BCM1250_ALT:
+ case K_SYS_SOC_TYPE_BCM1250_ALT2:
+ soc_str = "BCM1250";
+ ret = setup_bcm1250();
+ break;
+ case K_SYS_SOC_TYPE_BCM1120:
+ soc_str = "BCM1120";
+ ret = setup_bcm112x();
+ break;
+ case K_SYS_SOC_TYPE_BCM1125:
+ soc_str = "BCM1125";
+ ret = setup_bcm112x();
+ break;
+ case K_SYS_SOC_TYPE_BCM1125H:
+ soc_str = "BCM1125H";
+ ret = setup_bcm112x();
+ break;
default:
- prom_printf("Unknown %s rev %x\n", soc_str, soc_pass);
+ printk("Unknown SOC type %x\n", soc_type);
ret = 1;
+ break;
}
+
return ret;
}
@@ -152,29 +183,29 @@ void __init sb1250_setup(void)
int plldiv;
int bad_config = 0;
- sb1_pass = read_c0_prid() & 0xff;
+ sb1_pass = read_c0_prid() & PRID_REV_MASK;
sys_rev = __raw_readq(IOADDR(A_SCD_SYSTEM_REVISION));
soc_type = SYS_SOC_TYPE(sys_rev);
soc_pass = G_SYS_REVISION(sys_rev);
if (sys_rev_decode()) {
- prom_printf("Restart after failure to identify SiByte chip\n");
+ printk("Restart after failure to identify SiByte chip\n");
machine_restart(NULL);
}
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",
+ printk("Broadcom SiByte %s %s @ %d MHz (SB1 rev %d)\n",
soc_str, pass_str, zbbus_mhz * 2, sb1_pass);
- prom_printf("Board type: %s\n", get_system_type());
+ printk("Board type: %s\n", get_system_type());
switch (war_pass) {
case K_SYS_REVISION_BCM1250_PASS1:
#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS
- prom_printf("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
- "and the kernel doesn't have the proper "
- "workarounds compiled in. @@@@\n");
+ printk("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, "
+ "and the kernel doesn't have the proper "
+ "workarounds compiled in. @@@@\n");
bad_config = 1;
#endif
break;
@@ -182,36 +213,36 @@ void __init sb1250_setup(void)
/* Pass 2 - easiest as default for now - so many numbers */
#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || \
!defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS)
- prom_printf("@@@@ This is a BCM1250 A3-A10 board, and the "
- "kernel doesn't have the proper workarounds "
- "compiled in. @@@@\n");
+ printk("@@@@ This is a BCM1250 A3-A10 board, and the "
+ "kernel doesn't have the proper workarounds "
+ "compiled in. @@@@\n");
bad_config = 1;
#endif
#ifdef CONFIG_CPU_HAS_PREFETCH
- prom_printf("@@@@ Prefetches may be enabled in this kernel, "
- "but are buggy on this board. @@@@\n");
+ printk("@@@@ Prefetches may be enabled in this kernel, "
+ "but are buggy on this board. @@@@\n");
bad_config = 1;
#endif
break;
case K_SYS_REVISION_BCM1250_PASS2_2:
#ifndef CONFIG_SB1_PASS_2_WORKAROUNDS
- prom_printf("@@@@ This is a BCM1250 B1/B2. board, and the "
- "kernel doesn't have the proper workarounds "
- "compiled in. @@@@\n");
+ printk("@@@@ This is a BCM1250 B1/B2. board, and the "
+ "kernel doesn't have the proper workarounds "
+ "compiled in. @@@@\n");
bad_config = 1;
#endif
#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || \
!defined(CONFIG_CPU_HAS_PREFETCH)
- prom_printf("@@@@ This is a BCM1250 B1/B2, but the kernel is "
- "conservatively configured for an 'A' stepping. "
- "@@@@\n");
+ printk("@@@@ This is a BCM1250 B1/B2, but the kernel is "
+ "conservatively configured for an 'A' stepping. "
+ "@@@@\n");
#endif
break;
default:
break;
}
if (bad_config) {
- prom_printf("Invalid configuration for this chip.\n");
+ printk("Invalid configuration for this chip.\n");
machine_restart(NULL);
}
}
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index f859db02d3c..c0c4b3f88a0 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -21,9 +21,11 @@
#include <linux/interrupt.h>
#include <linux/smp.h>
#include <linux/kernel_stat.h>
+#include <linux/sched.h>
#include <asm/mmu_context.h>
#include <asm/io.h>
+#include <asm/fw/cfe/cfe_api.h>
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_int.h>
@@ -55,13 +57,6 @@ void sb1250_smp_init(void)
change_c0_status(ST0_IM, imask);
}
-void sb1250_smp_finish(void)
-{
- extern void sb1250_time_init(void);
- sb1250_time_init();
- local_irq_enable();
-}
-
/*
* These are routines for dealing with the sb1250 smp capabilities
* independent of board/firmware
@@ -71,27 +66,111 @@ void sb1250_smp_finish(void)
* 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)
+static void sb1250_send_ipi_single(int cpu, unsigned int action)
{
__raw_writeq((((u64)action) << 48), mailbox_set_regs[cpu]);
}
-void sb1250_mailbox_interrupt(struct pt_regs *regs)
+static inline void sb1250_send_ipi_mask(const struct cpumask *mask,
+ unsigned int action)
+{
+ unsigned int i;
+
+ for_each_cpu(i, mask)
+ sb1250_send_ipi_single(i, action);
+}
+
+/*
+ * Code to run on secondary just after probing the CPU
+ */
+static void sb1250_init_secondary(void)
+{
+ extern void sb1250_smp_init(void);
+
+ sb1250_smp_init();
+}
+
+/*
+ * Do any tidying up before marking online and running the idle
+ * loop
+ */
+static void sb1250_smp_finish(void)
+{
+ extern void sb1250_clockevent_init(void);
+
+ sb1250_clockevent_init();
+ local_irq_enable();
+}
+
+/*
+ * Setup the PC, SP, and GP of a secondary processor and start it
+ * running!
+ */
+static void sb1250_boot_secondary(int cpu, struct task_struct *idle)
+{
+ int retval;
+
+ retval = cfe_cpu_start(cpu_logical_map(cpu), &smp_bootstrap,
+ __KSTK_TOS(idle),
+ (unsigned long)task_thread_info(idle), 0);
+ if (retval != 0)
+ printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval);
+}
+
+/*
+ * Use CFE to find out how many CPUs are available, setting up
+ * cpu_possible_mask and the logical/physical mappings.
+ * XXXKW will the boot CPU ever not be physical 0?
+ *
+ * Common setup before any secondaries are started
+ */
+static void __init sb1250_smp_setup(void)
+{
+ int i, num;
+
+ init_cpu_possible(cpumask_of(0));
+ __cpu_number_map[0] = 0;
+ __cpu_logical_map[0] = 0;
+
+ for (i = 1, num = 0; i < NR_CPUS; i++) {
+ if (cfe_cpu_stop(i) == 0) {
+ set_cpu_possible(i, true);
+ __cpu_number_map[i] = ++num;
+ __cpu_logical_map[num] = i;
+ }
+ }
+ printk(KERN_INFO "Detected %i available secondary CPU(s)\n", num);
+}
+
+static void __init sb1250_prepare_cpus(unsigned int max_cpus)
+{
+}
+
+struct plat_smp_ops sb_smp_ops = {
+ .send_ipi_single = sb1250_send_ipi_single,
+ .send_ipi_mask = sb1250_send_ipi_mask,
+ .init_secondary = sb1250_init_secondary,
+ .smp_finish = sb1250_smp_finish,
+ .boot_secondary = sb1250_boot_secondary,
+ .smp_setup = sb1250_smp_setup,
+ .prepare_cpus = sb1250_prepare_cpus,
+};
+
+void sb1250_mailbox_interrupt(void)
{
int cpu = smp_processor_id();
+ int irq = K_INT_MBOX_0;
unsigned int action;
- kstat_this_cpu.irqs[K_INT_MBOX_0]++;
+ kstat_incr_irq_this_cpu(irq);
/* Load the mailbox register to figure out what we're supposed to do */
action = (____raw_readq(mailbox_regs[cpu]) >> 48) & 0xffff;
/* Clear the mailbox to clear the interrupt */
____raw_writeq(((u64)action) << 48, mailbox_clear_regs[cpu]);
- /*
- * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the
- * interrupt will do the reschedule for us
- */
+ if (action & SMP_RESCHEDULE_YOURSELF)
+ scheduler_ipi();
if (action & SMP_CALL_FUNCTION)
smp_call_function_interrupt();
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 4b669dc86ef..68337bf7a5a 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -15,160 +15,13 @@
* 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>
-/*
- * These are routines to set up and handle interrupts from the
- * sb1250 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/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/sb1250.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_int.h>
-#include <asm/sibyte/sb1250_scd.h>
-
-
-#define IMR_IP2_VAL K_INT_MAP_I0
-#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, and we use last one as hpt */
- if (cpu > 2) {
- BUG();
- }
-
- sb1250_mask_irq(cpu, irq);
-
- /* Map the timer interrupt to ip[4] of this cpu */
- __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 */
- __raw_writeq(0, IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
-#ifdef CONFIG_SIMULATION
- __raw_writeq((50000 / HZ) - 1,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
-#else
- __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)));
-#endif
-
- /* 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)));
-
- sb1250_unmask_irq(cpu, irq);
- sb1250_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. sb1250_timer_interrupt is
- * called directly from irq_handler.S when IP[4] is set during an
- * interrupt
- */
-}
-
-void sb1250_timer_interrupt(struct pt_regs *regs)
-{
- int cpu = smp_processor_id();
- int irq = K_INT_TIMER_0 + cpu;
-
- /* ACK interrupt */
- ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
-
- if (cpu == 0) {
- /*
- * CPU 0 handles the global timer interrupt job
- */
- ll_timer_interrupt(irq, regs);
- }
- else {
- /*
- * other CPUs should just do profiling and process accounting
- */
- ll_local_timer_interrupt(irq, regs);
- }
-}
-
-/*
- * 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.
- */
-static unsigned int sb1250_hpt_read(void)
-{
- unsigned int 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;
-}
+extern void sb1250_clocksource_init(void);
+extern void sb1250_clockevent_init(void);
-static void sb1250_hpt_init(unsigned int count)
+void __init plat_time_init(void)
{
- hpt_offset = count;
- return;
+ sb1250_clocksource_init();
+ sb1250_clockevent_init();
}
diff --git a/arch/mips/sibyte/swarm/Makefile b/arch/mips/sibyte/swarm/Makefile
index 2d626039195..7b45f199d92 100644
--- a/arch/mips/sibyte/swarm/Makefile
+++ b/arch/mips/sibyte/swarm/Makefile
@@ -1,3 +1,4 @@
-lib-y = setup.o rtc_xicor1241.o rtc_m41t81.o
+obj-y := platform.o setup.o rtc_xicor1241.o \
+ rtc_m41t81.o
-lib-$(CONFIG_KGDB) += dbg_io.o
+obj-$(CONFIG_I2C_BOARDINFO) += swarm-i2c.o
diff --git a/arch/mips/sibyte/swarm/dbg_io.c b/arch/mips/sibyte/swarm/dbg_io.c
deleted file mode 100644
index 75ce14c8eb6..00000000000
--- a/arch/mips/sibyte/swarm/dbg_io.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * kgdb debug routines for SiByte boards.
- *
- * Copyright (C) 2001 MontaVista Software Inc.
- * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
- *
- * 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.
- *
- */
-
-/* -------------------- BEGINNING OF CONFIG --------------------- */
-
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_uart.h>
-#include <asm/sibyte/sb1250_int.h>
-#include <asm/addrspace.h>
-
-/*
- * We use the second serial port for kgdb traffic.
- * 115200, 8, N, 1.
- */
-
-#define BAUD_RATE 115200
-#define CLK_DIVISOR V_DUART_BAUD_RATE(BAUD_RATE)
-#define DATA_BITS V_DUART_BITS_PER_CHAR_8 /* or 7 */
-#define PARITY V_DUART_PARITY_MODE_NONE /* or even */
-#define STOP_BITS M_DUART_STOP_BIT_LEN_1 /* or 2 */
-
-static int duart_initialized = 0; /* 0: need to be init'ed by kgdb */
-
-/* -------------------- END OF CONFIG --------------------- */
-extern int kgdb_port;
-
-#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 putDebugChar(unsigned char c);
-unsigned char getDebugChar(void);
-static void
-duart_init(int clk_divisor, int data, int parity, int stop)
-{
- duart_out(R_DUART_MODE_REG_1, data | parity);
- duart_out(R_DUART_MODE_REG_2, stop);
- duart_out(R_DUART_CLK_SEL, clk_divisor);
-
- duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN); /* enable rx and tx */
-}
-
-void
-putDebugChar(unsigned char c)
-{
- if (!duart_initialized) {
- duart_initialized = 1;
- duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
- }
- while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0);
- duart_out(R_DUART_TX_HOLD, c);
-}
-
-unsigned char
-getDebugChar(void)
-{
- if (!duart_initialized) {
- duart_initialized = 1;
- duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS);
- }
- while ((duart_in(R_DUART_STATUS) & M_DUART_RX_RDY) == 0) ;
- return duart_in(R_DUART_RX_HOLD);
-}
-
diff --git a/arch/mips/sibyte/swarm/platform.c b/arch/mips/sibyte/swarm/platform.c
new file mode 100644
index 00000000000..9480c14ec66
--- /dev/null
+++ b/arch/mips/sibyte/swarm/platform.c
@@ -0,0 +1,139 @@
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+
+#include <asm/sibyte/board.h>
+#include <asm/sibyte/sb1250_genbus.h>
+#include <asm/sibyte/sb1250_regs.h>
+
+#if defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR)
+
+#define DRV_NAME "pata-swarm"
+
+#define SWARM_IDE_SHIFT 5
+#define SWARM_IDE_BASE 0x1f0
+#define SWARM_IDE_CTRL 0x3f6
+
+static struct resource swarm_pata_resource[] = {
+ {
+ .name = "Swarm GenBus IDE",
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "Swarm GenBus IDE",
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "Swarm GenBus IDE",
+ .flags = IORESOURCE_IRQ,
+ .start = K_INT_GB_IDE,
+ .end = K_INT_GB_IDE,
+ },
+};
+
+static struct pata_platform_info pata_platform_data = {
+ .ioport_shift = SWARM_IDE_SHIFT,
+};
+
+static struct platform_device swarm_pata_device = {
+ .name = "pata_platform",
+ .id = -1,
+ .resource = swarm_pata_resource,
+ .num_resources = ARRAY_SIZE(swarm_pata_resource),
+ .dev = {
+ .platform_data = &pata_platform_data,
+ .coherent_dma_mask = ~0, /* grumble */
+ },
+};
+
+static int __init swarm_pata_init(void)
+{
+ u8 __iomem *base;
+ phys_t offset, size;
+ struct resource *r;
+
+ if (!SIBYTE_HAVE_IDE)
+ return -ENODEV;
+
+ base = ioremap(A_IO_EXT_BASE, 0x800);
+ offset = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_START_ADDR, IDE_CS));
+ size = __raw_readq(base + R_IO_EXT_REG(R_IO_EXT_MULT_SIZE, IDE_CS));
+ iounmap(base);
+
+ offset = G_IO_START_ADDR(offset) << S_IO_ADDRBASE;
+ size = (G_IO_MULT_SIZE(size) + 1) << S_IO_REGSIZE;
+ if (offset < A_PHYS_GENBUS || offset >= A_PHYS_GENBUS_END) {
+ pr_info(DRV_NAME ": PATA interface at GenBus disabled\n");
+
+ return -EBUSY;
+ }
+
+ pr_info(DRV_NAME ": PATA interface at GenBus slot %i\n", IDE_CS);
+
+ r = swarm_pata_resource;
+ r[0].start = offset + (SWARM_IDE_BASE << SWARM_IDE_SHIFT);
+ r[0].end = offset + ((SWARM_IDE_BASE + 8) << SWARM_IDE_SHIFT) - 1;
+ r[1].start = offset + (SWARM_IDE_CTRL << SWARM_IDE_SHIFT);
+ r[1].end = offset + ((SWARM_IDE_CTRL + 1) << SWARM_IDE_SHIFT) - 1;
+
+ return platform_device_register(&swarm_pata_device);
+}
+
+device_initcall(swarm_pata_init);
+
+#endif /* defined(CONFIG_SIBYTE_SWARM) || defined(CONFIG_SIBYTE_LITTLESUR) */
+
+#define sb1250_dev_struct(num) \
+ static struct resource sb1250_res##num = { \
+ .name = "SB1250 MAC " __stringify(num), \
+ .flags = IORESOURCE_MEM, \
+ .start = A_MAC_CHANNEL_BASE(num), \
+ .end = A_MAC_CHANNEL_BASE(num + 1) -1, \
+ };\
+ static struct platform_device sb1250_dev##num = { \
+ .name = "sb1250-mac", \
+ .id = num, \
+ .resource = &sb1250_res##num, \
+ .num_resources = 1, \
+ }
+
+sb1250_dev_struct(0);
+sb1250_dev_struct(1);
+sb1250_dev_struct(2);
+sb1250_dev_struct(3);
+
+static struct platform_device *sb1250_devs[] __initdata = {
+ &sb1250_dev0,
+ &sb1250_dev1,
+ &sb1250_dev2,
+ &sb1250_dev3,
+};
+
+static int __init sb1250_device_init(void)
+{
+ int ret;
+
+ /* Set the number of available units based on the SOC type. */
+ switch (soc_type) {
+ case K_SYS_SOC_TYPE_BCM1250:
+ case K_SYS_SOC_TYPE_BCM1250_ALT:
+ ret = platform_add_devices(sb1250_devs, 3);
+ break;
+ case K_SYS_SOC_TYPE_BCM1120:
+ case K_SYS_SOC_TYPE_BCM1125:
+ case K_SYS_SOC_TYPE_BCM1125H:
+ case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */
+ ret = platform_add_devices(sb1250_devs, 2);
+ break;
+ case K_SYS_SOC_TYPE_BCM1x55:
+ case K_SYS_SOC_TYPE_BCM1x80:
+ ret = platform_add_devices(sb1250_devs, 4);
+ break;
+ default:
+ ret = -ENODEV;
+ break;
+ }
+ return ret;
+}
+device_initcall(sb1250_device_init);
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c
index c13914bdda5..b732600b47f 100644
--- a/arch/mips/sibyte/swarm/rtc_m41t81.c
+++ b/arch/mips/sibyte/swarm/rtc_m41t81.c
@@ -146,7 +146,8 @@ int m41t81_set_time(unsigned long t)
struct rtc_time tm;
unsigned long flags;
- to_tm(t, &tm);
+ /* Note we don't care about the century */
+ rtc_time_to_tm(t, &tm);
/*
* Note the write order matters as it ensures the correctness.
@@ -155,32 +156,32 @@ int m41t81_set_time(unsigned long t)
*/
spin_lock_irqsave(&rtc_lock, flags);
- tm.tm_sec = BIN2BCD(tm.tm_sec);
+ tm.tm_sec = bin2bcd(tm.tm_sec);
m41t81_write(M41T81REG_SC, tm.tm_sec);
- tm.tm_min = BIN2BCD(tm.tm_min);
+ tm.tm_min = bin2bcd(tm.tm_min);
m41t81_write(M41T81REG_MN, tm.tm_min);
- tm.tm_hour = BIN2BCD(tm.tm_hour);
+ tm.tm_hour = bin2bcd(tm.tm_hour);
tm.tm_hour = (tm.tm_hour & 0x3f) | (m41t81_read(M41T81REG_HR) & 0xc0);
m41t81_write(M41T81REG_HR, tm.tm_hour);
/* tm_wday starts from 0 to 6 */
if (tm.tm_wday == 0) tm.tm_wday = 7;
- tm.tm_wday = BIN2BCD(tm.tm_wday);
+ tm.tm_wday = bin2bcd(tm.tm_wday);
m41t81_write(M41T81REG_DY, tm.tm_wday);
- tm.tm_mday = BIN2BCD(tm.tm_mday);
+ tm.tm_mday = bin2bcd(tm.tm_mday);
m41t81_write(M41T81REG_DT, tm.tm_mday);
/* tm_mon starts from 0, *ick* */
tm.tm_mon ++;
- tm.tm_mon = BIN2BCD(tm.tm_mon);
+ tm.tm_mon = bin2bcd(tm.tm_mon);
m41t81_write(M41T81REG_MO, tm.tm_mon);
/* we don't do century, everything is beyond 2000 */
tm.tm_year %= 100;
- tm.tm_year = BIN2BCD(tm.tm_year);
+ tm.tm_year = bin2bcd(tm.tm_year);
m41t81_write(M41T81REG_YR, tm.tm_year);
spin_unlock_irqrestore(&rtc_lock, flags);
@@ -208,12 +209,12 @@ unsigned long m41t81_get_time(void)
year = m41t81_read(M41T81REG_YR);
spin_unlock_irqrestore(&rtc_lock, flags);
- sec = BCD2BIN(sec);
- min = BCD2BIN(min);
- hour = BCD2BIN(hour);
- day = BCD2BIN(day);
- mon = BCD2BIN(mon);
- year = BCD2BIN(year);
+ sec = bcd2bin(sec);
+ min = bcd2bin(min);
+ hour = bcd2bin(hour);
+ day = bcd2bin(day);
+ mon = bcd2bin(mon);
+ year = bcd2bin(year);
year += 2000;
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c
index f4a17883641..178a824b28d 100644
--- a/arch/mips/sibyte/swarm/rtc_xicor1241.c
+++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c
@@ -4,8 +4,8 @@
* Copyright (C) 2002 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
- * 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
+ * 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.
*/
@@ -28,15 +28,15 @@
* Register bits
*/
-#define X1241REG_SR_BAT 0x80 /* currently on battery power */
+#define X1241REG_SR_BAT 0x80 /* currently on battery power */
#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
#define X1241REG_SR_RTCF 0x01 /* clock failed */
#define X1241REG_BL_BP2 0x80 /* block protect 2 */
#define X1241REG_BL_BP1 0x40 /* block protect 1 */
#define X1241REG_BL_BP0 0x20 /* block protect 0 */
-#define X1241REG_BL_WD1 0x10
-#define X1241REG_BL_WD0 0x08
+#define X1241REG_BL_WD1 0x10
+#define X1241REG_BL_WD0 0x08
#define X1241REG_HR_MIL 0x80 /* military time format */
/*
@@ -61,50 +61,50 @@
static int xicor_read(uint8_t addr)
{
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
__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 (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
__raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
SMB_CSR(R_SMB_START));
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
- if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
- /* Clear error bit by writing a 1 */
- __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
- return -1;
- }
+ if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ return -1;
+ }
return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
}
static int xicor_write(uint8_t addr, int b)
{
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
__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 (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
+ while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
+ ;
- if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
- /* Clear error bit by writing a 1 */
- __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
- return -1;
- } else {
+ if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
+ /* Clear error bit by writing a 1 */
+ __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
+ return -1;
+ } else {
return 0;
}
}
@@ -115,7 +115,8 @@ int xicor_set_time(unsigned long t)
int tmp;
unsigned long flags;
- to_tm(t, &tm);
+ rtc_time_to_tm(t, &tm);
+ tm.tm_year += 1900;
spin_lock_irqsave(&rtc_lock, flags);
/* unlock writes to the CCR */
@@ -123,18 +124,18 @@ int xicor_set_time(unsigned long t)
xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
/* trivial ones */
- tm.tm_sec = BIN2BCD(tm.tm_sec);
+ tm.tm_sec = bin2bcd(tm.tm_sec);
xicor_write(X1241REG_SC, tm.tm_sec);
- tm.tm_min = BIN2BCD(tm.tm_min);
+ tm.tm_min = bin2bcd(tm.tm_min);
xicor_write(X1241REG_MN, tm.tm_min);
- tm.tm_mday = BIN2BCD(tm.tm_mday);
+ tm.tm_mday = bin2bcd(tm.tm_mday);
xicor_write(X1241REG_DT, tm.tm_mday);
/* tm_mon starts from 0, *ick* */
tm.tm_mon ++;
- tm.tm_mon = BIN2BCD(tm.tm_mon);
+ tm.tm_mon = bin2bcd(tm.tm_mon);
xicor_write(X1241REG_MO, tm.tm_mon);
/* year is split */
@@ -147,7 +148,7 @@ int xicor_set_time(unsigned long t)
tmp = xicor_read(X1241REG_HR);
if (tmp & X1241REG_HR_MIL) {
/* 24 hour format */
- tm.tm_hour = BIN2BCD(tm.tm_hour);
+ tm.tm_hour = bin2bcd(tm.tm_hour);
tmp = (tmp & ~0x3f) | (tm.tm_hour & 0x3f);
} else {
/* 12 hour format, with 0x2 for pm */
@@ -156,7 +157,7 @@ int xicor_set_time(unsigned long t)
tmp |= 0x20;
tm.tm_hour -= 12;
}
- tm.tm_hour = BIN2BCD(tm.tm_hour);
+ tm.tm_hour = bin2bcd(tm.tm_hour);
tmp |= tm.tm_hour;
}
xicor_write(X1241REG_HR, tmp);
@@ -190,13 +191,13 @@ unsigned long xicor_get_time(void)
y2k = xicor_read(X1241REG_Y2K);
spin_unlock_irqrestore(&rtc_lock, flags);
- sec = BCD2BIN(sec);
- min = BCD2BIN(min);
- hour = BCD2BIN(hour);
- day = BCD2BIN(day);
- mon = BCD2BIN(mon);
- year = BCD2BIN(year);
- y2k = BCD2BIN(y2k);
+ sec = bcd2bin(sec);
+ min = bcd2bin(min);
+ hour = bcd2bin(hour);
+ day = bcd2bin(day);
+ mon = bcd2bin(mon);
+ year = bcd2bin(year);
+ y2k = bcd2bin(y2k);
year += (y2k * 100);
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index ac342f5643c..3462c831d0e 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -43,7 +43,7 @@
#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
#include <asm/sibyte/sb1250_regs.h>
#else
-#error invalid SiByte board configuation
+#error invalid SiByte board configuration
#endif
#include <asm/sibyte/sb1250_genbus.h>
#include <asm/sibyte/board.h>
@@ -53,7 +53,7 @@ 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
+#error invalid SiByte board configuration
#endif
extern int xicor_probe(void);
@@ -69,39 +69,59 @@ const char *get_system_type(void)
return "SiByte " SIBYTE_BOARD_NAME;
}
-void __init swarm_time_init(void)
+int swarm_be_handler(struct pt_regs *regs, int is_fixup)
{
-#if defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
- /* Setup HPT */
- sb1250_hpt_setup();
-#endif
+ if (!is_fixup && (regs->cp0_cause & 4)) {
+ /* Data bus error - print PA */
+ printk("DBE physical address: %010Lx\n",
+ __read_64bit_c0_register($26, 1));
+ }
+ return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
}
-void __init plat_timer_setup(struct irqaction *irq)
+enum swarm_rtc_type {
+ RTC_NONE,
+ RTC_XICOR,
+ RTC_M41T81,
+};
+
+enum swarm_rtc_type swarm_rtc_type;
+
+void read_persistent_clock(struct timespec *ts)
{
- /*
- * we don't set up irqaction, because we will deliver timer
- * interrupts through low-level (direct) meachanism.
- */
+ unsigned long sec;
- /* We only need to setup the generic timer */
-#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
+ switch (swarm_rtc_type) {
+ case RTC_XICOR:
+ sec = xicor_get_time();
+ break;
+
+ case RTC_M41T81:
+ sec = m41t81_get_time();
+ break;
+
+ case RTC_NONE:
+ default:
+ sec = mktime(2000, 1, 1, 0, 0, 0);
+ break;
+ }
+ ts->tv_sec = sec;
+ ts->tv_nsec = 0;
}
-int swarm_be_handler(struct pt_regs *regs, int is_fixup)
+int rtc_mips_set_time(unsigned long sec)
{
- if (!is_fixup && (regs->cp0_cause & 4)) {
- /* Data bus error - print PA */
- printk("DBE physical address: %010Lx\n",
- __read_64bit_c0_register($26, 1));
+ switch (swarm_rtc_type) {
+ case RTC_XICOR:
+ return xicor_set_time(sec);
+
+ case RTC_M41T81:
+ return m41t81_set_time(sec);
+
+ case RTC_NONE:
+ default:
+ return -1;
}
- return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL);
}
void __init plat_mem_setup(void)
@@ -111,51 +131,26 @@ void __init plat_mem_setup(void)
#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
sb1250_setup();
#else
-#error invalid SiByte board configuation
+#error invalid SiByte board configuration
#endif
- panic_timeout = 5; /* For debug. */
-
- board_time_init = swarm_time_init;
board_be_handler = swarm_be_handler;
- if (xicor_probe()) {
- printk("swarm setup: Xicor 1241 RTC detected.\n");
- rtc_mips_get_time = xicor_get_time;
- rtc_mips_set_time = xicor_set_time;
- }
-
- if (m41t81_probe()) {
- printk("swarm setup: M41T81 RTC detected.\n");
- rtc_mips_get_time = m41t81_get_time;
- rtc_mips_set_time = m41t81_set_time;
- }
-
- printk("This kernel optimized for "
-#ifdef CONFIG_SIMULATION
- "simulation"
-#else
- "board"
-#endif
- " runs "
-#ifdef CONFIG_SIBYTE_CFE
- "with"
-#else
- "without"
-#endif
- " CFE\n");
+ if (xicor_probe())
+ swarm_rtc_type = RTC_XICOR;
+ if (m41t81_probe())
+ swarm_rtc_type = RTC_M41T81;
#ifdef CONFIG_VT
screen_info = (struct screen_info) {
- 0, 0, /* orig-x, orig-y */
- 0, /* unused */
- 52, /* orig_video_page */
- 3, /* orig_video_mode */
- 80, /* orig_video_cols */
- 4626, 3, 9, /* unused, ega_bx, unused */
- 25, /* orig_video_lines */
- 0x22, /* orig_video_isVGA */
- 16 /* orig_video_points */
+ .orig_video_page = 52,
+ .orig_video_mode = 3,
+ .orig_video_cols = 80,
+ .flags = 12,
+ .orig_video_ega_bx = 3,
+ .orig_video_lines = 25,
+ .orig_video_isVGA = 0x22,
+ .orig_video_points = 16,
};
/* XXXKW for CFE, get lines/cols from environment */
#endif
@@ -169,17 +164,19 @@ void __init plat_mem_setup(void)
#define LEDS_PHYS MLEDS_PHYS
#endif
-#define setled(index, c) \
- ((unsigned char *)(IOADDR(LEDS_PHYS)+0x20))[(3-(index))<<3] = (c)
void setleds(char *str)
{
+ void *reg;
int i;
+
for (i = 0; i < 4; i++) {
- if (!str[i]) {
- setled(i, ' ');
- } else {
- setled(i, str[i]);
- }
+ reg = IOADDR(LEDS_PHYS) + 0x20 + ((3 - i) << 3);
+
+ if (!str[i])
+ writeb(' ', reg);
+ else
+ writeb(str[i], reg);
}
}
-#endif
+
+#endif /* LEDS_PHYS */
diff --git a/arch/mips/sibyte/swarm/swarm-i2c.c b/arch/mips/sibyte/swarm/swarm-i2c.c
new file mode 100644
index 00000000000..062505054d4
--- /dev/null
+++ b/arch/mips/sibyte/swarm/swarm-i2c.c
@@ -0,0 +1,35 @@
+/*
+ * Broadcom BCM91250A (SWARM), etc. I2C platform setup.
+ *
+ * Copyright (c) 2008 Maciej W. Rozycki
+ *
+ * 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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+
+static struct i2c_board_info swarm_i2c_info1[] __initdata = {
+ {
+ I2C_BOARD_INFO("m41t81", 0x68),
+ },
+};
+
+static int __init swarm_i2c_init(void)
+{
+ int err;
+
+ err = i2c_register_board_info(1, swarm_i2c_info1,
+ ARRAY_SIZE(swarm_i2c_info1));
+ if (err < 0)
+ printk(KERN_ERR
+ "swarm-i2c: cannot register board I2C devices\n");
+ return err;
+}
+
+arch_initcall(swarm_i2c_init);
diff --git a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c
deleted file mode 100644
index 97c73c793c3..00000000000
--- a/arch/mips/sibyte/swarm/time.c
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2000, 2001 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.
- */
-
-/*
- * Time routines for the swarm board. We pass all the hard stuff
- * through to the sb1250 handling code. Only thing we really keep
- * track of here is what time of day we think it is. And we don't
- * really even do a good job of that...
- */
-
-
-#include <linux/bcd.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <asm/system.h>
-#include <asm/addrspace.h>
-#include <asm/io.h>
-
-#include <asm/sibyte/sb1250.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_smbus.h>
-
-static unsigned long long sec_bias = 0;
-static unsigned int usec_bias = 0;
-
-/* Xicor 1241 definitions */
-
-/*
- * Register bits
- */
-
-#define X1241REG_SR_BAT 0x80 /* currently on battery power */
-#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
-#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
-#define X1241REG_SR_RTCF 0x01 /* clock failed */
-#define X1241REG_BL_BP2 0x80 /* block protect 2 */
-#define X1241REG_BL_BP1 0x40 /* block protect 1 */
-#define X1241REG_BL_BP0 0x20 /* block protect 0 */
-#define X1241REG_BL_WD1 0x10
-#define X1241REG_BL_WD0 0x08
-#define X1241REG_HR_MIL 0x80 /* military time format */
-
-/*
- * Register numbers
- */
-
-#define X1241REG_BL 0x10 /* block protect bits */
-#define X1241REG_INT 0x11 /* */
-#define X1241REG_SC 0x30 /* Seconds */
-#define X1241REG_MN 0x31 /* Minutes */
-#define X1241REG_HR 0x32 /* Hours */
-#define X1241REG_DT 0x33 /* Day of month */
-#define X1241REG_MO 0x34 /* Month */
-#define X1241REG_YR 0x35 /* Year */
-#define X1241REG_DW 0x36 /* Day of Week */
-#define X1241REG_Y2K 0x37 /* Year 2K */
-#define X1241REG_SR 0x3F /* Status register */
-
-#define X1241_CCR_ADDRESS 0x6F
-
-#define SMB_CSR(reg) (IOADDR(A_SMB_REGISTER(1, reg)))
-
-static int xicor_read(uint8_t addr)
-{
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- __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 (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- __raw_writeq(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE,
- SMB_CSR(R_SMB_START));
-
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
- /* Clear error bit by writing a 1 */
- __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
- return -1;
- }
-
- return (__raw_readq(SMB_CSR(R_SMB_DATA)) & 0xff);
-}
-
-static int xicor_write(uint8_t addr, int b)
-{
- while (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- __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 (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY)
- ;
-
- if (__raw_readq(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) {
- /* Clear error bit by writing a 1 */
- __raw_writeq(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS));
- return -1;
- } else {
- return 0;
- }
-}
-
-/*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
- * called 500 ms after the second nowtime has started, because when
- * nowtime is written into the registers of the CMOS clock, it will
- * jump to the next second precisely 500 ms later. Check the Motorola
- * MC146818A or Dallas DS12887 data sheet for details.
- *
- * BUG: This routine does not handle hour overflow properly; it just
- * sets the minutes. Usually you'll only notice that after reboot!
- */
-int set_rtc_mmss(unsigned long nowtime)
-{
- int retval = 0;
- int real_seconds, real_minutes, cmos_minutes;
-
- cmos_minutes = xicor_read(X1241REG_MN);
- cmos_minutes = BCD2BIN(cmos_minutes);
-
- /*
- * since we're only adjusting minutes and seconds,
- * don't interfere with hour overflow. This avoids
- * messing with unknown time zones but requires your
- * RTC not to be off by more than 15 minutes
- */
- real_seconds = nowtime % 60;
- real_minutes = nowtime / 60;
- if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
- real_minutes += 30; /* correct for half hour time zone */
- real_minutes %= 60;
-
- /* unlock writes to the CCR */
- xicor_write(X1241REG_SR, X1241REG_SR_WEL);
- xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
-
- if (abs(real_minutes - cmos_minutes) < 30) {
- real_seconds = BIN2BCD(real_seconds);
- real_minutes = BIN2BCD(real_minutes);
- xicor_write(X1241REG_SC, real_seconds);
- xicor_write(X1241REG_MN, real_minutes);
- } else {
- printk(KERN_WARNING
- "set_rtc_mmss: can't update from %d to %d\n",
- cmos_minutes, real_minutes);
- retval = -1;
- }
-
- xicor_write(X1241REG_SR, 0);
-
- printk("set_rtc_mmss: %02d:%02d\n", real_minutes, real_seconds);
-
- return retval;
-}
-
-static unsigned long __init get_swarm_time(void)
-{
- unsigned int year, mon, day, hour, min, sec, y2k;
-
- sec = xicor_read(X1241REG_SC);
- min = xicor_read(X1241REG_MN);
- hour = xicor_read(X1241REG_HR);
-
- if (hour & X1241REG_HR_MIL) {
- hour &= 0x3f;
- } else {
- if (hour & 0x20)
- hour = (hour & 0xf) + 0x12;
- }
-
- sec = BCD2BIN(sec);
- min = BCD2BIN(min);
- hour = BCD2BIN(hour);
-
- day = xicor_read(X1241REG_DT);
- mon = xicor_read(X1241REG_MO);
- year = xicor_read(X1241REG_YR);
- y2k = xicor_read(X1241REG_Y2K);
-
- day = BCD2BIN(day);
- mon = BCD2BIN(mon);
- year = BCD2BIN(year);
- y2k = BCD2BIN(y2k);
-
- year += (y2k * 100);
-
- return mktime(year, mon, day, hour, min, sec);
-}
-
-/*
- * Bring up the timer at 100 Hz.
- */
-void __init swarm_time_init(void)
-{
- unsigned int flags;
- int status;
-
- /* Set up the scd general purpose timer 0 to cpu 0 */
- sb1250_time_init();
-
- /* Establish communication with the Xicor 1241 RTC */
- /* XXXKW how do I share the SMBus with the I2C subsystem? */
-
- __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");
- } else {
- if (status & X1241REG_SR_RTCF)
- printk("x1241: battery failed -- time is probably wrong\n");
- write_seqlock_irqsave(&xtime_lock, flags);
- xtime.tv_sec = get_swarm_time();
- xtime.tv_nsec = 0;
- write_sequnlock_irqrestore(&xtime_lock, flags);
- }
-}