aboutsummaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-02 19:37:26 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-11-02 19:37:26 -0700
commit29dd5a7733fcb72696e90247ffbab57b0a591f67 (patch)
treeaafbbdc38ea9f9ea42a594fc47b8bd37dc720c23 /arch/mips
parent71527bf8332ced9a961827272fe2f83fc5514f42 (diff)
parent3be51f70e1f5e11a723d28b3dde26bc3aacdbc71 (diff)
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus: (25 commits) [MIPS] Jazz: disable PIT; cleanup R4030 clockevent [MIPS] Bigsur supports highmem. [MIPS] mtx-1: Enable -Werror. [MIPS] mtx-1: Remove unused mtx1_sys_btn. [MIPS] Pb1200: Enable -Werror. [MIPS] Fix and cleanup the MIPS part of the (ab)use of CLOCK_TICK_RATE. [MIPS] SNI: register a02r clockevent; don't use PIT timer [MIPS] i8253.h: Remove all i8259 related definitions. [MIPS] i8253: Cleanup. [MIPS] Cobalt: Fix IRQ comment; the Cobalt kernel uses CP0 counter now. [MIPS] Pb1200: Fix warning. [MIPS] Pb1200: Fix warning. [MIPS] IP27: Fix build error. [MIPS] Excite: Fix build error. [MIPS] Sibyte: Split and move clock code. [MIPS] Sibyte: Fixes for oneshot timer mode. [MIPS] Sibyte: Remove blank line. [MIPS] Swarm: Fix build failure [MIPS] time: Code cleanups [MIPS] time: Remove now unused local_timer_interrupt. ...
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/Kconfig13
-rw-r--r--arch/mips/au1000/mtx-1/Makefile2
-rw-r--r--arch/mips/au1000/mtx-1/platform.c9
-rw-r--r--arch/mips/au1000/pb1200/Makefile2
-rw-r--r--arch/mips/au1000/pb1200/board_setup.c6
-rw-r--r--arch/mips/au1000/pb1200/irqmap.c100
-rw-r--r--arch/mips/basler/excite/excite_setup.c2
-rw-r--r--arch/mips/jazz/irq.c27
-rw-r--r--arch/mips/kernel/Makefile4
-rw-r--r--arch/mips/kernel/cevt-bcm1480.c149
-rw-r--r--arch/mips/kernel/cevt-sb1250.c148
-rw-r--r--arch/mips/kernel/csrc-bcm1480.c54
-rw-r--r--arch/mips/kernel/csrc-sb1250.c70
-rw-r--r--arch/mips/kernel/i8253.c23
-rw-r--r--arch/mips/kernel/time.c73
-rw-r--r--arch/mips/qemu/q-irq.c1
-rw-r--r--arch/mips/sgi-ip27/ip27-timer.c4
-rw-r--r--arch/mips/sgi-ip32/ip32-platform.c2
-rw-r--r--arch/mips/sibyte/Kconfig14
-rw-r--r--arch/mips/sibyte/bcm1480/irq.c16
-rw-r--r--arch/mips/sibyte/bcm1480/time.c159
-rw-r--r--arch/mips/sibyte/sb1250/irq.c14
-rw-r--r--arch/mips/sibyte/sb1250/time.c191
-rw-r--r--arch/mips/sni/time.c5
24 files changed, 569 insertions, 519 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 97da953eb5d..2c7d6c240b7 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -546,6 +546,7 @@ config SIBYTE_BIGSUR
select SWAP_IO_SPACE
select SYS_HAS_CPU_SB1
select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_HIGHMEM
select SYS_SUPPORTS_LITTLE_ENDIAN
config SNI_RM
@@ -733,15 +734,27 @@ config ARCH_MAY_HAVE_PC_FDC
config BOOT_RAW
bool
+config CEVT_BCM1480
+ bool
+
config CEVT_GT641XX
bool
config CEVT_R4K
bool
+config CEVT_SB1250
+ bool
+
config CEVT_TXX9
bool
+config CSRC_BCM1480
+ bool
+
+config CSRC_SB1250
+ bool
+
config CFE
bool
diff --git a/arch/mips/au1000/mtx-1/Makefile b/arch/mips/au1000/mtx-1/Makefile
index afa7007d67f..85a90941de4 100644
--- a/arch/mips/au1000/mtx-1/Makefile
+++ b/arch/mips/au1000/mtx-1/Makefile
@@ -9,3 +9,5 @@
lib-y := init.o board_setup.o irqmap.o
obj-y := platform.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/au1000/mtx-1/platform.c b/arch/mips/au1000/mtx-1/platform.c
index 01ebff67797..49c0fb409fe 100644
--- a/arch/mips/au1000/mtx-1/platform.c
+++ b/arch/mips/au1000/mtx-1/platform.c
@@ -34,15 +34,6 @@ static struct resource mtx1_wdt_res[] = {
}
};
-static struct resource mtx1_sys_btn[] = {
- [0] = {
- .start = 7,
- .end = 7,
- .name = "mtx1-sys-btn-gpio",
- .flags = IORESOURCE_IRQ,
- }
-};
-
static struct platform_device mtx1_wdt = {
.name = "mtx1-wdt",
.id = 0,
diff --git a/arch/mips/au1000/pb1200/Makefile b/arch/mips/au1000/pb1200/Makefile
index 22b673cf55a..970b1b1d5cd 100644
--- a/arch/mips/au1000/pb1200/Makefile
+++ b/arch/mips/au1000/pb1200/Makefile
@@ -3,3 +3,5 @@
#
lib-y := init.o board_setup.o irqmap.o
+
+EXTRA_CFLAGS += -Werror
diff --git a/arch/mips/au1000/pb1200/board_setup.c b/arch/mips/au1000/pb1200/board_setup.c
index 5dbc9868f59..b98bebfa87c 100644
--- a/arch/mips/au1000/pb1200/board_setup.c
+++ b/arch/mips/au1000/pb1200/board_setup.c
@@ -68,9 +68,11 @@ void board_reset(void)
void __init board_setup(void)
{
char *argptr = NULL;
- u32 pin_func;
#if 0
+ {
+ u32 pin_func;
+
/* Enable PSC1 SYNC for AC97. Normaly done in audio driver,
* but it is board specific code, so put it here.
*/
@@ -81,11 +83,13 @@ void __init board_setup(void)
au_writel(0, (u32)bcsr|0x10); /* turn off pcmcia power */
au_sync();
+ }
#endif
#if defined(CONFIG_I2C_AU1550)
{
u32 freq0, clksrc;
+ u32 pin_func;
/* Select SMBUS in CPLD */
bcsr->resets &= ~(BCSR_RESETS_PCS0MUX);
diff --git a/arch/mips/au1000/pb1200/irqmap.c b/arch/mips/au1000/pb1200/irqmap.c
index bdf00e2a35e..c096be4ed4e 100644
--- a/arch/mips/au1000/pb1200/irqmap.c
+++ b/arch/mips/au1000/pb1200/irqmap.c
@@ -94,51 +94,41 @@ inline void pb1200_disable_irq(unsigned int irq_nr)
bcsr->intclr = 1<<(irq_nr - PB1200_INT_BEGIN);
}
-static unsigned int pb1200_startup_irq( unsigned int irq_nr )
+static unsigned int pb1200_setup_cascade(void)
{
- if (++pb1200_cascade_en == 1)
- {
- request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
- 0, "Pb1200 Cascade", (void *)&pb1200_cascade_handler );
-#ifdef CONFIG_MIPS_PB1200
- /* We have a problem with CPLD rev3. Enable a workaround */
- if( ((bcsr->whoami & BCSR_WHOAMI_CPLD)>>4) <= 3)
- {
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("Pb1200 must be at CPLD rev4. Please have Pb1200\n");
- printk("updated to latest revision. This software will not\n");
- printk("work on anything less than CPLD rev4\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- printk("\nWARNING!!!\n");
- while(1);
- }
-#endif
- }
- pb1200_enable_irq(irq_nr);
+ int err;
+
+ err = request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
+ 0, "Pb1200 Cascade", &pb1200_cascade_handler);
+ if (err)
+ return err;
+
return 0;
}
-static void pb1200_shutdown_irq( unsigned int irq_nr )
+static unsigned int pb1200_startup_irq(unsigned int irq)
{
- pb1200_disable_irq(irq_nr);
- if (--pb1200_cascade_en == 0)
- {
- free_irq(AU1000_GPIO_7, &pb1200_cascade_handler );
+ if (++pb1200_cascade_en == 1) {
+ int res;
+
+ res = pb1200_setup_cascade();
+ if (res)
+ return res;
}
- return;
+
+ pb1200_enable_irq(irq);
+
+ return 0;
}
-static struct irq_chip external_irq_type =
+static void pb1200_shutdown_irq(unsigned int irq)
{
+ pb1200_disable_irq(irq);
+ if (--pb1200_cascade_en == 0)
+ free_irq(AU1000_GPIO_7, &pb1200_cascade_handler);
+}
+
+static struct irq_chip external_irq_type = {
#ifdef CONFIG_MIPS_PB1200
.name = "Pb1200 Ext",
#endif
@@ -155,16 +145,38 @@ static struct irq_chip external_irq_type =
void _board_init_irq(void)
{
- int irq_nr;
+ unsigned int irq;
- for (irq_nr = PB1200_INT_BEGIN; irq_nr <= PB1200_INT_END; irq_nr++)
- {
- set_irq_chip_and_handler(irq_nr, &external_irq_type,
+#ifdef CONFIG_MIPS_PB1200
+ /* We have a problem with CPLD rev3. Enable a workaround */
+ if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) {
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("Pb1200 must be at CPLD rev4. Please have Pb1200\n");
+ printk("updated to latest revision. This software will not\n");
+ printk("work on anything less than CPLD rev4\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ printk("\nWARNING!!!\n");
+ panic("Game over. Your score is 0.");
+ }
+#endif
+
+ for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) {
+ set_irq_chip_and_handler(irq, &external_irq_type,
handle_level_irq);
- pb1200_disable_irq(irq_nr);
+ pb1200_disable_irq(irq);
}
- /* GPIO_7 can not be hooked here, so it is hooked upon first
- request of any source attached to the cascade */
+ /*
+ * GPIO_7 can not be hooked here, so it is hooked upon first
+ * request of any source attached to the cascade
+ */
}
-
diff --git a/arch/mips/basler/excite/excite_setup.c b/arch/mips/basler/excite/excite_setup.c
index 24378b9223f..6dd8f0d46d0 100644
--- a/arch/mips/basler/excite/excite_setup.c
+++ b/arch/mips/basler/excite/excite_setup.c
@@ -77,7 +77,7 @@ int titan_irqflags;
void __init plat_time_init(void)
{
const u32 modebit5 = ocd_readl(0x00e4);
- unsigned int mult = ((modebit5 >> 11) & 0x1f) + 2,
+ unsigned int mult = ((modebit5 >> 11) & 0x1f) + 2;
unsigned int div = ((modebit5 >> 16) & 0x1f) + 2;
if (div == 33)
diff --git a/arch/mips/jazz/irq.c b/arch/mips/jazz/irq.c
index ae25b480723..d7f8a782aae 100644
--- a/arch/mips/jazz/irq.c
+++ b/arch/mips/jazz/irq.c
@@ -97,9 +97,10 @@ asmlinkage void plat_irq_dispatch(void)
if (pending & IE_IRQ4) {
r4030_read_reg32(JAZZ_TIMER_REGISTER);
do_IRQ(JAZZ_TIMER_IRQ);
- } else if (pending & IE_IRQ2)
- do_IRQ(r4030_read_reg32(JAZZ_EISA_IRQ_ACK));
- else if (pending & IE_IRQ1) {
+ } else if (pending & IE_IRQ2) {
+ irq = *(volatile u8 *)JAZZ_EISA_IRQ_ACK;
+ do_IRQ(irq);
+ } else if (pending & IE_IRQ1) {
irq = *(volatile u8 *)JAZZ_IO_IRQ_SOURCE >> 2;
if (likely(irq > 0))
do_IRQ(irq + JAZZ_IRQ_START - 1);
@@ -117,16 +118,16 @@ static void r4030_set_mode(enum clock_event_mode mode,
struct clock_event_device r4030_clockevent = {
.name = "r4030",
.features = CLOCK_EVT_FEAT_PERIODIC,
- .rating = 100,
+ .rating = 300,
.irq = JAZZ_TIMER_IRQ,
- .cpumask = CPU_MASK_CPU0,
.set_mode = r4030_set_mode,
};
static irqreturn_t r4030_timer_interrupt(int irq, void *dev_id)
{
- r4030_clockevent.event_handler(&r4030_clockevent);
+ struct clock_event_device *cd = dev_id;
+ cd->event_handler(cd);
return IRQ_HANDLED;
}
@@ -134,15 +135,22 @@ static struct irqaction r4030_timer_irqaction = {
.handler = r4030_timer_interrupt,
.flags = IRQF_DISABLED,
.mask = CPU_MASK_CPU0,
- .name = "timer",
+ .name = "R4030 timer",
};
void __init plat_time_init(void)
{
- struct irqaction *irq = &r4030_timer_irqaction;
+ struct clock_event_device *cd = &r4030_clockevent;
+ struct irqaction *action = &r4030_timer_irqaction;
+ unsigned int cpu = smp_processor_id();
BUG_ON(HZ != 100);
+ cd->cpumask = cpumask_of_cpu(cpu);
+ clockevents_register_device(cd);
+ action->dev_id = cd;
+ setup_irq(JAZZ_TIMER_IRQ, action);
+
/*
* Set clock to 100Hz.
*
@@ -150,8 +158,5 @@ void __init plat_time_init(void)
* a programmable 4-bit divider. This makes it fairly inflexible.
*/
r4030_write_reg32(JAZZ_TIMER_INTERVAL, 9);
- setup_irq(JAZZ_TIMER_IRQ, irq);
-
- clockevents_register_device(&r4030_clockevent);
setup_pit_timer();
}
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 3196509a28d..b551535b7e4 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -8,9 +8,13 @@ obj-y += cpu-probe.o branch.o entry.o genex.o irq.o process.o \
ptrace.o reset.o semaphore.o setup.o signal.o syscall.o \
time.o topology.o traps.o unaligned.o
+obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm1480.o
obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
+obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o
obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
+obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o
+obj-$(CONFIG_CSRC_SB1250) += csrc-sb1250.o
binfmt_irix-objs := irixelf.o irixinv.o irixioctl.o irixsig.o \
irix5sys.o sysirix.o
diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c
new file mode 100644
index 00000000000..21e6d63eb4d
--- /dev/null
+++ b/arch/mips/kernel/cevt-bcm1480.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2000,2001,2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/time.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
+
+/*
+ * The general purpose timer ticks at 1MHz independent if
+ * the rest of the system
+ */
+static void sibyte_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ unsigned int cpu = smp_processor_id();
+ void __iomem *cfg, *init;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ __raw_writeq(0, cfg);
+ __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+ cfg);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* Stop the timer until we actually program a shot */
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ __raw_writeq(0, cfg);
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
+ case CLOCK_EVT_MODE_RESUME:
+ ;
+ }
+}
+
+static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd)
+{
+ unsigned int cpu = smp_processor_id();
+ void __iomem *cfg, *init;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+
+ __raw_writeq(delta - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE, cfg);
+
+ return 0;
+}
+
+static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
+{
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *cd = dev_id;
+ void __iomem *cfg;
+ unsigned long tmode;
+
+ if (cd->mode == CLOCK_EVT_MODE_PERIODIC)
+ tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS;
+ else
+ tmode = 0;
+
+ /* ACK interrupt */
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ ____raw_writeq(tmode, cfg);
+
+ cd->event_handler(cd);
+
+ return IRQ_HANDLED;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent);
+static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction);
+static DEFINE_PER_CPU(char [18], sibyte_hpt_name);
+
+void __cpuinit sb1480_clockevent_init(void)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu;
+ struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu);
+ struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu);
+ unsigned char *name = per_cpu(sibyte_hpt_name, cpu);
+
+ BUG_ON(cpu > 3); /* Only have 4 general purpose timers */
+
+ sprintf(name, "bcm1480-counter-%d", cpu);
+ cd->name = name;
+ cd->features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT;
+ clockevent_set_clock(cd, V_SCD_TIMER_FREQ);
+ cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd);
+ cd->min_delta_ns = clockevent_delta2ns(1, cd);
+ cd->rating = 200;
+ cd->irq = irq;
+ cd->cpumask = cpumask_of_cpu(cpu);
+ cd->set_next_event = sibyte_next_event;
+ cd->set_mode = sibyte_set_mode;
+ clockevents_register_device(cd);
+
+ 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)));
+
+ bcm1480_unmask_irq(cpu, irq);
+
+ action->handler = sibyte_counter_handler;
+ action->flags = IRQF_DISABLED | IRQF_PERCPU;
+ action->name = name;
+ action->dev_id = cd;
+ setup_irq(irq, action);
+}
diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c
new file mode 100644
index 00000000000..e2029d0fc39
--- /dev/null
+++ b/arch/mips/kernel/cevt-sb1250.c
@@ -0,0 +1,148 @@
+/*
+ * 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/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/percpu.h>
+
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/time.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
+
+/*
+ * The general purpose timer ticks at 1MHz independent if
+ * the rest of the system
+ */
+static void sibyte_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ unsigned int cpu = smp_processor_id();
+ void __iomem *cfg, *init;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ __raw_writeq(0, cfg);
+ __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
+ cfg);
+ break;
+
+ case CLOCK_EVT_MODE_ONESHOT:
+ /* Stop the timer until we actually program a shot */
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ __raw_writeq(0, cfg);
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
+ case CLOCK_EVT_MODE_RESUME:
+ ;
+ }
+}
+
+static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd)
+{
+ unsigned int cpu = smp_processor_id();
+ void __iomem *cfg, *init;
+
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
+
+ __raw_writeq(delta - 1, init);
+ __raw_writeq(M_SCD_TIMER_ENABLE, cfg);
+
+ return 0;
+}
+
+static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
+{
+ unsigned int cpu = smp_processor_id();
+ struct clock_event_device *cd = dev_id;
+ void __iomem *cfg;
+ unsigned long tmode;
+
+ if (cd->mode == CLOCK_EVT_MODE_PERIODIC)
+ tmode = M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS;
+ else
+ tmode = 0;
+
+ /* ACK interrupt */
+ cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ ____raw_writeq(tmode, cfg);
+
+ cd->event_handler(cd);
+
+ return IRQ_HANDLED;
+}
+
+static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent);
+static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction);
+static DEFINE_PER_CPU(char [18], sibyte_hpt_name);
+
+void __cpuinit sb1250_clockevent_init(void)
+{
+ unsigned int cpu = smp_processor_id();
+ unsigned int irq = K_INT_TIMER_0 + cpu;
+ struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu);
+ struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu);
+ unsigned char *name = per_cpu(sibyte_hpt_name, cpu);
+
+ /* Only have 4 general purpose timers, and we use last one as hpt */
+ BUG_ON(cpu > 2);
+
+ sprintf(name, "sb1250-counter-%d", cpu);
+ cd->name = name;
+ cd->features = CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_ONESHOT;
+ clockevent_set_clock(cd, V_SCD_TIMER_FREQ);
+ cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd);
+ cd->min_delta_ns = clockevent_delta2ns(1, cd);
+ cd->rating = 200;
+ cd->irq = irq;
+ cd->cpumask = cpumask_of_cpu(cpu);
+ cd->set_next_event = sibyte_next_event;
+ cd->set_mode = sibyte_set_mode;
+ clockevents_register_device(cd);
+
+ 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)));
+
+ sb1250_unmask_irq(cpu, irq);
+
+ action->handler = sibyte_counter_handler;
+ action->flags = IRQF_DISABLED | IRQF_PERCPU;
+ action->name = name;
+ action->dev_id = cd;
+ setup_irq(irq, action);
+}
diff --git a/arch/mips/kernel/csrc-bcm1480.c b/arch/mips/kernel/csrc-bcm1480.c
new file mode 100644
index 00000000000..868745e7184
--- /dev/null
+++ b/arch/mips/kernel/csrc-bcm1480.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2000,2001,2004 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include <linux/clocksource.h>
+
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/time.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>
+
+static cycle_t bcm1480_hpt_read(void)
+{
+ return (cycle_t) __raw_readq(IOADDR(A_SCD_ZBBUS_CYCLE_COUNT));
+}
+
+struct clocksource bcm1480_clocksource = {
+ .name = "zbbus-cycles",
+ .rating = 200,
+ .read = bcm1480_hpt_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void __init sb1480_clocksource_init(void)
+{
+ struct clocksource *cs = &bcm1480_clocksource;
+ unsigned int plldiv;
+ unsigned long zbbus;
+
+ plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
+ zbbus = ((plldiv >> 1) * 50000000) + ((plldiv & 1) * 25000000);
+ clocksource_set_clock(cs, zbbus);
+ clocksource_register(cs);
+}
diff --git a/arch/mips/kernel/csrc-sb1250.c b/arch/mips/kernel/csrc-sb1250.c
new file mode 100644
index 00000000000..ebb16e66887
--- /dev/null
+++ b/arch/mips/kernel/csrc-sb1250.c
@@ -0,0 +1,70 @@
+/*
+ * 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/clocksource.h>
+
+#include <asm/addrspace.h>
+#include <asm/io.h>
+#include <asm/time.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 SB1250_HPT_NUM 3
+#define SB1250_HPT_VALUE M_SCD_TIMER_CNT /* max value */
+
+/*
+ * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
+ * again.
+ */
+static cycle_t 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))));
+
+ return SB1250_HPT_VALUE - count;
+}
+
+struct clocksource bcm1250_clocksource = {
+ .name = "MIPS",
+ .rating = 200,
+ .read = sb1250_hpt_read,
+ .mask = CLOCKSOURCE_MASK(23),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void __init sb1250_clocksource_init(void)
+{
+ struct clocksource *cs = &bcm1250_clocksource;
+
+ /* 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)));
+
+ clocksource_set_clock(cs, V_SCD_TIMER_FREQ);
+ clocksource_register(cs);
+}
diff --git a/arch/mips/kernel/i8253.c b/arch/mips/kernel/i8253.c
index 5d9830df359..a925abd8d29 100644
--- a/arch/mips/kernel/i8253.c
+++ b/arch/mips/kernel/i8253.c
@@ -12,6 +12,7 @@
#include <asm/delay.h>
#include <asm/i8253.h>
#include <asm/io.h>
+#include <asm/time.h>
static DEFINE_SPINLOCK(i8253_lock);
@@ -87,11 +88,10 @@ struct clock_event_device pit_clockevent = {
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
.set_mode = init_pit_timer,
.set_next_event = pit_next_event,
- .shift = 32,
.irq = 0,
};
-irqreturn_t timer_interrupt(int irq, void *dev_id)
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
pit_clockevent.event_handler(&pit_clockevent);
@@ -111,19 +111,20 @@ static struct irqaction irq0 = {
*/
void __init setup_pit_timer(void)
{
+ struct clock_event_device *cd = &pit_clockevent;
+ unsigned int cpu = smp_processor_id();
+
/*
* Start pit with the boot cpu mask and make it global after the
* IO_APIC has been initialized.
*/
- pit_clockevent.cpumask = cpumask_of_cpu(0);
- pit_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, 32);
- pit_clockevent.max_delta_ns =
- clockevent_delta2ns(0x7FFF, &pit_clockevent);
- pit_clockevent.min_delta_ns =
- clockevent_delta2ns(0xF, &pit_clockevent);
- clockevents_register_device(&pit_clockevent);
-
- irq0.mask = cpumask_of_cpu(0);
+ cd->cpumask = cpumask_of_cpu(cpu);
+ clockevent_set_clock(cd, CLOCK_TICK_RATE);
+ cd->max_delta_ns = clockevent_delta2ns(0x7FFF, cd);
+ cd->min_delta_ns = clockevent_delta2ns(0xF, cd);
+ clockevents_register_device(cd);
+
+ irq0.mask = cpumask_of_cpu(cpu);
setup_irq(0, &irq0);
}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 27228f583da..3284b9b4eca 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -3,8 +3,7 @@
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
* Copyright (c) 2003, 2004 Maciej W. Rozycki
*
- * Common time service routines for MIPS machines. See
- * Documentation/mips/time.README.
+ * Common time service routines for MIPS machines.
*
* 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
@@ -18,28 +17,17 @@
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/param.h>
-#include <linux/profile.h>
#include <linux/time.h>
#include <linux/timex.h>
#include <linux/smp.h>
-#include <linux/kernel_stat.h>
#include <linux/spinlock.h>
-#include <linux/interrupt.h>
#include <linux/module.h>
-#include <linux/kallsyms.h>
-#include <asm/bootinfo.h>
-#include <asm/cache.h>
-#include <asm/compiler.h>
-#include <asm/cpu.h>
#include <asm/cpu-features.h>
#include <asm/div64.h>
-#include <asm/sections.h>
#include <asm/smtc_ipi.h>
#include <asm/time.h>
-#include <irq.h>
-
/*
* forward reference
*/
@@ -63,14 +51,6 @@ int update_persistent_clock(struct timespec now)
}
/*
- * Null high precision timer functions for systems lacking one.
- */
-static cycle_t null_hpt_read(void)
-{
- return 0;
-}
-
-/*
* High precision timer functions for a R4k-compatible timer.
*/
static cycle_t c0_hpt_read(void)
@@ -80,22 +60,6 @@ static cycle_t c0_hpt_read(void)
int (*mips_timer_state)(void);
-/*
- * local_timer_interrupt() does profiling and process accounting
- * on a per-CPU basis.
- *
- * In UP mode, it is invoked from the (global) timer_interrupt.
- *
- * In SMP mode, it might invoked by per-CPU timer interrupt, or
- * a broadcasted inter-processor interrupt which itself is triggered
- * by the global timer interrupt.
- */
-void local_timer_interrupt(int irq, void *dev_id)
-{
- profile_tick(CPU_PROFILING);
- update_process_times(user_mode(get_irq_regs()));
-}
-
int null_perf_irq(void)
{
return 0;
@@ -120,6 +84,13 @@ EXPORT_SYMBOL(perf_irq);
unsigned int mips_hpt_frequency;
+static struct clocksource clocksource_mips = {
+ .name = "MIPS",
+ .read = c0_hpt_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
static unsigned int __init calibrate_hpt(void)
{
cycle_t frequency, hpt_start, hpt_end, hpt_count, hz;
@@ -162,12 +133,6 @@ static unsigned int __init calibrate_hpt(void)
return frequency >> log_2_loops;
}
-struct clocksource clocksource_mips = {
- .name = "MIPS",
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock)
{
u64 temp;
@@ -203,9 +168,6 @@ void __cpuinit clockevent_set_clock(struct clock_event_device *cd,
static void __init init_mips_clocksource(void)
{
- if (!mips_hpt_frequency || clocksource_mips.read == null_hpt_read)
- return;
-
/* Calclate a somewhat reasonable rating value */
clocksource_mips.rating = 200 + mips_hpt_frequency / 10000000;
@@ -227,7 +189,7 @@ void __init __weak plat_time_init(void)
* setup_irq calls and each clock_event_device should use its own
* struct irqrequest.
*/
-void __init plat_timer_setup(struct irqaction *irq)
+void __init plat_timer_setup(void)
{
BUG();
}
@@ -236,21 +198,8 @@ void __init time_init(void)
{
plat_time_init();
- /* Choose appropriate high precision timer routines. */
- if (!cpu_has_counter && !clocksource_mips.read)
- /* No high precision timer -- sorry. */
- clocksource_mips.read = null_hpt_read;
- else if (!mips_hpt_frequency && !mips_timer_state) {
- /* A high precision timer of unknown frequency. */
- if (!clocksource_mips.read)
- /* No external high precision timer -- use R4k. */
- clocksource_mips.read = c0_hpt_read;
- } else {
+ if (cpu_has_counter && (mips_hpt_frequency || mips_timer_state)) {
/* We know counter frequency. Or we can get it. */
- if (!clocksource_mips.read) {
- /* No external high precision timer -- use R4k. */
- clocksource_mips.read = c0_hpt_read;
- }
if (!mips_hpt_frequency)
mips_hpt_frequency = calibrate_hpt();
@@ -258,8 +207,8 @@ void __init time_init(void)
printk("Using %u.%03u MHz high precision timer.\n",
((mips_hpt_frequency + 500) / 1000) / 1000,
((mips_hpt_frequency + 500) / 1000) % 1000);
+ init_mips_clocksource();
}
- init_mips_clocksource();
mips_clockevent_init();
}
diff --git a/arch/mips/qemu/q-irq.c b/arch/mips/qemu/q-irq.c
index 4681757460a..11f98476788 100644
--- a/arch/mips/qemu/q-irq.c
+++ b/arch/mips/qemu/q-irq.c
@@ -1,4 +1,5 @@
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/linkage.h>
#include <asm/i8259.h>
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c
index dc59c3b708e..08d45369be4 100644
--- a/arch/mips/sgi-ip27/ip27-timer.c
+++ b/arch/mips/sgi-ip27/ip27-timer.c
@@ -131,7 +131,7 @@ static struct irq_chip rt_irq_type = {
static int rt_next_event(unsigned long delta, struct clock_event_device *evt)
{
unsigned int cpu = smp_processor_id();
- int slice putoslice(cpu);
+ int slice = cputoslice(cpu);
unsigned long cnt;
cnt = LOCAL_HUB_L(PI_RT_COUNT);
@@ -169,7 +169,7 @@ static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id)
/*
* Ack
*/
- LOCAL_HUB_S(PI_RT_PEND_A + PI_COUNT_OFFSET * slice, cnt);
+ LOCAL_HUB_S(PI_RT_PEND_A + PI_COUNT_OFFSET * slice, 0);
cd->event_handler(cd);
return IRQ_HANDLED;
diff --git a/arch/mips/sgi-ip32/ip32-platform.c b/arch/mips/sgi-ip32/ip32-platform.c
index 7309e48d163..77febd68fcd 100644
--- a/arch/mips/sgi-ip32/ip32-platform.c
+++ b/arch/mips/sgi-ip32/ip32-platform.c
@@ -42,7 +42,7 @@ static struct platform_device uart8250_device = {
static int __init uart8250_init(void)
{
uart8250_data[0].membase = (void __iomem *) &mace->isa.serial1;
- uart8250_data[1].membase = (void __iomem *) &mace->isa.serial1;
+ uart8250_data[1].membase = (void __iomem *) &mace->isa.serial2;
return platform_device_register(&uart8250_device);
}
diff --git a/arch/mips/sibyte/Kconfig b/arch/mips/sibyte/Kconfig
index e8fb880272b..366b19d33f7 100644
--- a/arch/mips/sibyte/Kconfig
+++ b/arch/mips/sibyte/Kconfig
@@ -1,5 +1,7 @@
config SIBYTE_SB1250
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_ENABLE_LDT_IF_PCI
@@ -9,6 +11,8 @@ config SIBYTE_SB1250
config SIBYTE_BCM1120
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select IRQ_CPU
select SIBYTE_BCM112X
select SIBYTE_HAS_ZBUS_PROFILING
@@ -16,6 +20,8 @@ config SIBYTE_BCM1120
config SIBYTE_BCM1125
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
@@ -24,6 +30,8 @@ config SIBYTE_BCM1125
config SIBYTE_BCM1125H
bool
+ select CEVT_SB1250
+ select CSRC_SB1250
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_BCM112X
@@ -33,12 +41,16 @@ config SIBYTE_BCM1125H
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
@@ -47,6 +59,8 @@ config SIBYTE_BCM1x80
config SIBYTE_BCM1x55
bool
+ select CEVT_BCM1480
+ select CSRC_BCM1480
select HW_HAS_PCI
select IRQ_CPU
select SIBYTE_SB1xxx_SOC
diff --git a/arch/mips/sibyte/bcm1480/irq.c b/arch/mips/sibyte/bcm1480/irq.c
index 61790c4bfb6..e28d626255a 100644
--- a/arch/mips/sibyte/bcm1480/irq.c
+++ b/arch/mips/sibyte/bcm1480/irq.c
@@ -265,21 +265,6 @@ void __init init_bcm1480_irqs(void)
}
}
-
-static irqreturn_t bcm1480_dummy_handler(int irq, void *dev_id)
-{
- 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
-};
-
/*
* 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
@@ -308,7 +293,6 @@ static struct irqaction bcm1480_dummy_action = {
void __init arch_init_irq(void)
{
-
unsigned int i, cpu;
u64 tmp;
unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 |
diff --git a/arch/mips/sibyte/bcm1480/time.c b/arch/mips/sibyte/bcm1480/time.c
index bbf19bfabcc..1680a68952a 100644
--- a/arch/mips/sibyte/bcm1480/time.c
+++ b/arch/mips/sibyte/bcm1480/time.c
@@ -15,163 +15,10 @@
* 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/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/percpu.h>
-#include <linux/spinlock.h>
+#include <linux/init.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
-
-/*
- * The general purpose timer ticks at 1MHz independent if
- * the rest of the system
- */
-static void sibyte_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- unsigned int cpu = smp_processor_id();
- void __iomem *timer_cfg, *timer_init;
-
- timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
- timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
-
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- __raw_writeq(0, timer_cfg);
- __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, timer_init);
- __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* Stop the timer until we actually program a shot */
- case CLOCK_EVT_MODE_SHUTDOWN:
- __raw_writeq(0, timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
- case CLOCK_EVT_MODE_RESUME:
- ;
- }
-}
-
-static int sibyte_next_event(unsigned long delta, struct clock_event_device *cd)
-{
- unsigned int cpu = smp_processor_id();
- void __iomem *timer_init;
- unsigned int cnt;
- int res;
-
- timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
- cnt = __raw_readq(timer_init);
- cnt += delta;
- __raw_writeq(cnt, timer_init);
- res = ((long)(__raw_readq(timer_init) - cnt ) > 0) ? -ETIME : 0;
-
- return res;
-}
-
-static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
-{
- unsigned int cpu = smp_processor_id();
- struct clock_event_device *cd = dev_id;
- void __iomem *timer_cfg;
-
- timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
-
- /* Reset the timer */
- __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- timer_cfg);
- cd->event_handler(cd);
-
- return IRQ_HANDLED;
-}
-
-static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent);
-static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction);
-static DEFINE_PER_CPU(char [18], sibyte_hpt_name);
-
-void __cpuinit sb1480_clockevent_init(void)
-{
- unsigned int cpu = smp_processor_id();
- unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu;
- struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu);
- struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu);
- unsigned char *name = per_cpu(sibyte_hpt_name, cpu);
-
- BUG_ON(cpu > 3); /* Only have 4 general purpose timers */
-
- sprintf(name, "bcm1480-counter %d", cpu);
- cd->name = name;
- cd->features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT;
- clockevent_set_clock(cd, V_SCD_TIMER_FREQ);
- cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd);
- cd->min_delta_ns = clockevent_delta2ns(1, cd);
- cd->rating = 200;
- cd->irq = irq;
- cd->cpumask = cpumask_of_cpu(cpu);
- cd->set_next_event = sibyte_next_event;
- cd->set_mode = sibyte_set_mode;
- clockevents_register_device(cd);
-
- bcm1480_mask_irq(cpu, irq);
-
- /*
- * Map 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)));
-
- bcm1480_unmask_irq(cpu, irq);
-
- action->handler = sibyte_counter_handler;
- action->flags = IRQF_DISABLED | IRQF_PERCPU;
- action->name = name;
- action->dev_id = cd;
- setup_irq(irq, action);
-}
-
-static cycle_t bcm1480_hpt_read(void)
-{
- return (cycle_t) __raw_readq(IOADDR(A_SCD_ZBBUS_CYCLE_COUNT));
-}
-
-struct clocksource bcm1480_clocksource = {
- .name = "zbbus-cycles",
- .rating = 200,
- .read = bcm1480_hpt_read,
- .mask = CLOCKSOURCE_MASK(64),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-void __init sb1480_clocksource_init(void)
-{
- struct clocksource *cs = &bcm1480_clocksource;
- unsigned int plldiv;
- unsigned long zbbus;
-
- plldiv = G_BCM1480_SYS_PLL_DIV(__raw_readq(IOADDR(A_SCD_SYSTEM_CFG)));
- zbbus = ((plldiv >> 1) * 50000000) + ((plldiv & 1) * 25000000);
- clocksource_set_clock(cs, zbbus);
- clocksource_register(cs);
-}
+extern void sb1480_clockevent_init(void);
+extern void sb1480_clocksource_init(void);
void __init plat_time_init(void)
{
diff --git a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c
index 52d18fc91f3..eac9065ffe0 100644
--- a/arch/mips/sibyte/sb1250/irq.c
+++ b/arch/mips/sibyte/sb1250/irq.c
@@ -236,20 +236,6 @@ void __init init_sb1250_irqs(void)
}
-static irqreturn_t sb1250_dummy_handler(int irq, void *dev_id)
-{
- 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
-};
-
/*
* 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
diff --git a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c
index 95ad34e3fba..68337bf7a5a 100644
--- a/arch/mips/sibyte/sb1250/time.c
+++ b/arch/mips/sibyte/sb1250/time.c
@@ -15,195 +15,10 @@
* 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/clockchips.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/kernel_stat.h>
-
-#include <asm/irq.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 */
-
-
-/*
- * The general purpose timer ticks at 1 Mhz independent if
- * the rest of the system
- */
-static void sibyte_set_mode(enum clock_event_mode mode,
- struct clock_event_device *evt)
-{
- unsigned int cpu = smp_processor_id();
- void __iomem *timer_cfg, *timer_init;
-
- timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
- timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
-
- switch(mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- __raw_writeq(0, timer_cfg);
- __raw_writeq((V_SCD_TIMER_FREQ / HZ) - 1, timer_init);
- __raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_ONESHOT:
- /* Stop the timer until we actually program a shot */
- case CLOCK_EVT_MODE_SHUTDOWN:
- __raw_writeq(0, timer_cfg);
- break;
-
- case CLOCK_EVT_MODE_UNUSED: /* shuddup gcc */
- case CLOCK_EVT_MODE_RESUME:
- ;
- }
-}
-
-static int
-sibyte_next_event(unsigned long delta, struct clock_event_device *evt)
-{
- unsigned int cpu = smp_processor_id();
- void __iomem *timer_cfg, *timer_init;
-
- timer_cfg = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
- timer_init = IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT));
-
- __raw_writeq(0, timer_cfg);
- __raw_writeq(delta, timer_init);
- __raw_writeq(M_SCD_TIMER_ENABLE, timer_cfg);
-
- return 0;
-}
-
-static irqreturn_t sibyte_counter_handler(int irq, void *dev_id)
-{
- unsigned int cpu = smp_processor_id();
- struct clock_event_device *cd = dev_id;
-
- /* ACK interrupt */
- ____raw_writeq(M_SCD_TIMER_ENABLE | M_SCD_TIMER_MODE_CONTINUOUS,
- IOADDR(A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)));
-
- cd->event_handler(cd);
-
- return IRQ_HANDLED;
-}
-
-static struct irqaction sibyte_irqaction = {
- .handler = sibyte_counter_handler,
- .flags = IRQF_DISABLED | IRQF_PERCPU,
- .name = "timer",
-};
-
-static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent);
-static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction);
-static DEFINE_PER_CPU(char [18], sibyte_hpt_name);
-
-void __cpuinit sb1250_clockevent_init(void)
-{
- unsigned int cpu = smp_processor_id();
- unsigned int irq = K_INT_TIMER_0 + cpu;
- struct irqaction *action = &per_cpu(sibyte_hpt_irqaction, cpu);
- struct clock_event_device *cd = &per_cpu(sibyte_hpt_clockevent, cpu);
- unsigned char *name = per_cpu(sibyte_hpt_name, cpu);
-
- /* Only have 4 general purpose timers, and we use last one as hpt */
- BUG_ON(cpu > 2);
-
- sprintf(name, "bcm1480-counter %d", cpu);
- cd->name = name;
- cd->features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT;
- clockevent_set_clock(cd, V_SCD_TIMER_FREQ);
- cd->max_delta_ns = clockevent_delta2ns(0x7fffff, cd);
- cd->min_delta_ns = clockevent_delta2ns(1, cd);
- cd->rating = 200;
- cd->irq = irq;
- cd->cpumask = cpumask_of_cpu(cpu);
- cd->set_next_event = sibyte_next_event;
- cd->set_mode = sibyte_set_mode;
- clockevents_register_device(cd);
-
- 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)));
- cd->cpumask = cpumask_of_cpu(0);
-
- sb1250_unmask_irq(cpu, irq);
-
- action->handler = sibyte_counter_handler;
- action->flags = IRQF_DISABLED | IRQF_PERCPU;
- action->name = name;
- action->dev_id = cd;
- setup_irq(irq, &sibyte_irqaction);
-}
-
-/*
- * The HPT is free running from SB1250_HPT_VALUE down to 0 then starts over
- * again.
- */
-static cycle_t 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))));
-
- return SB1250_HPT_VALUE - count;
-}
-
-struct clocksource bcm1250_clocksource = {
- .name = "MIPS",
- .rating = 200,
- .read = sb1250_hpt_read,
- .mask = CLOCKSOURCE_MASK(23),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-void __init sb1250_clocksource_init(void)
-{
- struct clocksource *cs = &bcm1250_clocksource;
-
- /* 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)));
-
- clocksource_set_clock(cs, V_SCD_TIMER_FREQ);
- clocksource_register(cs);
-}
+extern void sb1250_clocksource_init(void);
+extern void sb1250_clockevent_init(void);
void __init plat_time_init(void)
{
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index 60bc62ef093..6f339af08d2 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -1,6 +1,7 @@
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/time.h>
+#include <linux/clockchips.h>
#include <asm/i8253.h>
#include <asm/sni.h>
@@ -80,7 +81,7 @@ static void __init sni_a20r_timer_setup(void)
unsigned int cpu = smp_processor_id();
cd->cpumask = cpumask_of_cpu(cpu);
-
+ clockevents_register_device(cd);
action->dev_id = cd;
setup_irq(SNI_A20R_IRQ_TIMER, &a20r_irqaction);
}
@@ -169,8 +170,6 @@ void __init plat_time_init(void)
mips_hpt_frequency = r4k_tick * HZ;
- setup_pit_timer();
-
switch (sni_brd_type) {
case SNI_BRD_10:
case SNI_BRD_10NEW: