aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-gemini
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-gemini')
-rw-r--r--arch/arm/mach-gemini/Makefile2
-rw-r--r--arch/arm/mach-gemini/board-nas4220b.c7
-rw-r--r--arch/arm/mach-gemini/board-rut1xx.c8
-rw-r--r--arch/arm/mach-gemini/board-wbd111.c7
-rw-r--r--arch/arm/mach-gemini/board-wbd222.c7
-rw-r--r--arch/arm/mach-gemini/common.h2
-rw-r--r--arch/arm/mach-gemini/gpio.c19
-rw-r--r--arch/arm/mach-gemini/idle.c6
-rw-r--r--arch/arm/mach-gemini/include/mach/debug-macro.S21
-rw-r--r--arch/arm/mach-gemini/include/mach/gpio.h20
-rw-r--r--arch/arm/mach-gemini/include/mach/hardware.h2
-rw-r--r--arch/arm/mach-gemini/include/mach/timex.h13
-rw-r--r--arch/arm/mach-gemini/include/mach/uncompress.h2
-rw-r--r--arch/arm/mach-gemini/irq.c9
-rw-r--r--arch/arm/mach-gemini/mm.c22
-rw-r--r--arch/arm/mach-gemini/reset.c (renamed from arch/arm/mach-gemini/include/mach/system.h)2
-rw-r--r--arch/arm/mach-gemini/time.c97
17 files changed, 134 insertions, 112 deletions
diff --git a/arch/arm/mach-gemini/Makefile b/arch/arm/mach-gemini/Makefile
index 7355c0bbcb5..7963a77be63 100644
--- a/arch/arm/mach-gemini/Makefile
+++ b/arch/arm/mach-gemini/Makefile
@@ -4,7 +4,7 @@
# Object file lists.
-obj-y := irq.o mm.o time.o devices.o gpio.o idle.o
+obj-y := irq.o mm.o time.o devices.o gpio.o idle.o reset.o
# Board-specific support
obj-$(CONFIG_MACH_NAS4220B) += board-nas4220b.o
diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c
index 5927d3c253a..ca8a25bb352 100644
--- a/arch/arm/mach-gemini/board-nas4220b.c
+++ b/arch/arm/mach-gemini/board-nas4220b.c
@@ -31,10 +31,6 @@
#include "common.h"
-static struct sys_timer ib4220b_timer = {
- .init = gemini_timer_init,
-};
-
static struct gpio_led ib4220b_leds[] = {
{
.name = "nas4220b:orange:hdd",
@@ -105,6 +101,7 @@ MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
.atag_offset = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
- .timer = &ib4220b_timer,
+ .init_time = gemini_timer_init,
.init_machine = ib4220b_init,
+ .restart = gemini_restart,
MACHINE_END
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c
index cd7437a1cea..7a675f88ffd 100644
--- a/arch/arm/mach-gemini/board-rut1xx.c
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -14,6 +14,7 @@
#include <linux/leds.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
+#include <linux/sizes.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -71,10 +72,6 @@ static struct platform_device rut1xx_leds = {
},
};
-static struct sys_timer rut1xx_timer = {
- .init = gemini_timer_init,
-};
-
static void __init rut1xx_init(void)
{
gemini_gpio_init();
@@ -89,6 +86,7 @@ MACHINE_START(RUT100, "Teltonika RUT100")
.atag_offset = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
- .timer = &rut1xx_timer,
+ .init_time = gemini_timer_init,
.init_machine = rut1xx_init,
+ .restart = gemini_restart,
MACHINE_END
diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c
index a367880368f..418188cd171 100644
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -80,10 +80,6 @@ static struct platform_device wbd111_leds_device = {
},
};
-static struct sys_timer wbd111_timer = {
- .init = gemini_timer_init,
-};
-
static struct mtd_partition wbd111_partitions[] = {
{
.name = "RedBoot",
@@ -132,6 +128,7 @@ MACHINE_START(WBD111, "Wiliboard WBD-111")
.atag_offset = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
- .timer = &wbd111_timer,
+ .init_time = gemini_timer_init,
.init_machine = wbd111_init,
+ .restart = gemini_restart,
MACHINE_END
diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c
index f382811c131..266b265090c 100644
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -80,10 +80,6 @@ static struct platform_device wbd222_leds_device = {
},
};
-static struct sys_timer wbd222_timer = {
- .init = gemini_timer_init,
-};
-
static struct mtd_partition wbd222_partitions[] = {
{
.name = "RedBoot",
@@ -132,6 +128,7 @@ MACHINE_START(WBD222, "Wiliboard WBD-222")
.atag_offset = 0x100,
.map_io = gemini_map_io,
.init_irq = gemini_init_irq,
- .timer = &wbd222_timer,
+ .init_time = gemini_timer_init,
.init_machine = wbd222_init,
+ .restart = gemini_restart,
MACHINE_END
diff --git a/arch/arm/mach-gemini/common.h b/arch/arm/mach-gemini/common.h
index 7670c39acb2..38a45260a7c 100644
--- a/arch/arm/mach-gemini/common.h
+++ b/arch/arm/mach-gemini/common.h
@@ -26,4 +26,6 @@ extern int platform_register_pflash(unsigned int size,
struct mtd_partition *parts,
unsigned int nr_parts);
+extern void gemini_restart(char mode, const char *cmd);
+
#endif /* __GEMINI_COMMON_H__ */
diff --git a/arch/arm/mach-gemini/gpio.c b/arch/arm/mach-gemini/gpio.c
index fdc7ef1391d..f8cb5710d6e 100644
--- a/arch/arm/mach-gemini/gpio.c
+++ b/arch/arm/mach-gemini/gpio.c
@@ -23,6 +23,7 @@
#include <mach/irqs.h>
#define GPIO_BASE(x) IO_ADDRESS(GEMINI_GPIO_BASE(x))
+#define irq_to_gpio(x) ((x) - GPIO_IRQ_BASE)
/* GPIO registers definition */
#define GPIO_DATA_OUT 0x0
@@ -44,7 +45,7 @@
#define GPIO_PORT_NUM 3
-static void _set_gpio_irqenable(unsigned int base, unsigned int index,
+static void _set_gpio_irqenable(void __iomem *base, unsigned int index,
int enable)
{
unsigned int reg;
@@ -57,7 +58,7 @@ static void _set_gpio_irqenable(unsigned int base, unsigned int index,
static void gpio_ack_irq(struct irq_data *d)
{
unsigned int gpio = irq_to_gpio(d->irq);
- unsigned int base = GPIO_BASE(gpio / 32);
+ void __iomem *base = GPIO_BASE(gpio / 32);
__raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR);
}
@@ -65,7 +66,7 @@ static void gpio_ack_irq(struct irq_data *d)
static void gpio_mask_irq(struct irq_data *d)
{
unsigned int gpio = irq_to_gpio(d->irq);
- unsigned int base = GPIO_BASE(gpio / 32);
+ void __iomem *base = GPIO_BASE(gpio / 32);
_set_gpio_irqenable(base, gpio % 32, 0);
}
@@ -73,7 +74,7 @@ static void gpio_mask_irq(struct irq_data *d)
static void gpio_unmask_irq(struct irq_data *d)
{
unsigned int gpio = irq_to_gpio(d->irq);
- unsigned int base = GPIO_BASE(gpio / 32);
+ void __iomem *base = GPIO_BASE(gpio / 32);
_set_gpio_irqenable(base, gpio % 32, 1);
}
@@ -82,7 +83,7 @@ static int gpio_set_irq_type(struct irq_data *d, unsigned int type)
{
unsigned int gpio = irq_to_gpio(d->irq);
unsigned int gpio_mask = 1 << (gpio % 32);
- unsigned int base = GPIO_BASE(gpio / 32);
+ void __iomem *base = GPIO_BASE(gpio / 32);
unsigned int reg_both, reg_level, reg_type;
reg_type = __raw_readl(base + GPIO_INT_TYPE);
@@ -120,7 +121,7 @@ static int gpio_set_irq_type(struct irq_data *d, unsigned int type)
__raw_writel(reg_level, base + GPIO_INT_LEVEL);
__raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
- gpio_ack_irq(d->irq);
+ gpio_ack_irq(d);
return 0;
}
@@ -153,7 +154,7 @@ static struct irq_chip gpio_irq_chip = {
static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
int dir)
{
- unsigned int base = GPIO_BASE(offset / 32);
+ void __iomem *base = GPIO_BASE(offset / 32);
unsigned int reg;
reg = __raw_readl(base + GPIO_DIR);
@@ -166,7 +167,7 @@ static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
- unsigned int base = GPIO_BASE(offset / 32);
+ void __iomem *base = GPIO_BASE(offset / 32);
if (value)
__raw_writel(1 << (offset % 32), base + GPIO_DATA_SET);
@@ -176,7 +177,7 @@ static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- unsigned int base = GPIO_BASE(offset / 32);
+ void __iomem *base = GPIO_BASE(offset / 32);
return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1;
}
diff --git a/arch/arm/mach-gemini/idle.c b/arch/arm/mach-gemini/idle.c
index 92bbd6bb600..ddf8ec9d203 100644
--- a/arch/arm/mach-gemini/idle.c
+++ b/arch/arm/mach-gemini/idle.c
@@ -3,7 +3,7 @@
*/
#include <linux/init.h>
-#include <asm/system.h>
+#include <asm/system_misc.h>
#include <asm/proc-fns.h>
static void gemini_idle(void)
@@ -13,9 +13,11 @@ static void gemini_idle(void)
* will never wakeup... Acctualy it is not very good to enable
* interrupts first since scheduler can miss a tick, but there is
* no other way around this. Platforms that needs it for power saving
- * should call enable_hlt() in init code, since by default it is
+ * should enable it in init code, since by default it is
* disabled.
*/
+
+ /* FIXME: Enabling interrupts here is racy! */
local_irq_enable();
cpu_do_idle();
}
diff --git a/arch/arm/mach-gemini/include/mach/debug-macro.S b/arch/arm/mach-gemini/include/mach/debug-macro.S
deleted file mode 100644
index 837670763b8..00000000000
--- a/arch/arm/mach-gemini/include/mach/debug-macro.S
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Debugging macro include header
- *
- * Copyright (C) 1994-1999 Russell King
- * Copyright (C) 2001-2006 Storlink, Corp.
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <mach/hardware.h>
-
- .macro addruart, rp, rv, tmp
- ldr \rp, =GEMINI_UART_BASE @ physical
- ldr \rv, =IO_ADDRESS(GEMINI_UART_BASE) @ virtual
- .endm
-
-#define UART_SHIFT 2
-#define FLOW_CONTROL
-#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-gemini/include/mach/gpio.h b/arch/arm/mach-gemini/include/mach/gpio.h
deleted file mode 100644
index 40a0527bada..00000000000
--- a/arch/arm/mach-gemini/include/mach/gpio.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Gemini gpiolib specific defines
- *
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * 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.
- */
-
-#ifndef __MACH_GPIO_H__
-#define __MACH_GPIO_H__
-
-#include <mach/irqs.h>
-
-#define gpio_to_irq(x) ((x) + GPIO_IRQ_BASE)
-#define irq_to_gpio(x) ((x) - GPIO_IRQ_BASE)
-
-#endif /* __MACH_GPIO_H__ */
diff --git a/arch/arm/mach-gemini/include/mach/hardware.h b/arch/arm/mach-gemini/include/mach/hardware.h
index 8c950e1d06b..98e7b0f286b 100644
--- a/arch/arm/mach-gemini/include/mach/hardware.h
+++ b/arch/arm/mach-gemini/include/mach/hardware.h
@@ -69,6 +69,6 @@
/*
* macro to get at IO space when running virtually
*/
-#define IO_ADDRESS(x) ((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000)
+#define IO_ADDRESS(x) IOMEM((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000)
#endif
diff --git a/arch/arm/mach-gemini/include/mach/timex.h b/arch/arm/mach-gemini/include/mach/timex.h
deleted file mode 100644
index dc5690ba975..00000000000
--- a/arch/arm/mach-gemini/include/mach/timex.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Gemini timex specifications
- *
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * 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.
- */
-
-/* When AHB bus frequency is 150MHz */
-#define CLOCK_TICK_RATE 38000000
diff --git a/arch/arm/mach-gemini/include/mach/uncompress.h b/arch/arm/mach-gemini/include/mach/uncompress.h
index 0efa2624723..02e225673ac 100644
--- a/arch/arm/mach-gemini/include/mach/uncompress.h
+++ b/arch/arm/mach-gemini/include/mach/uncompress.h
@@ -39,6 +39,4 @@ static inline void flush(void)
*/
#define arch_decomp_setup()
-#define arch_decomp_wdog()
-
#endif /* __MACH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-gemini/irq.c b/arch/arm/mach-gemini/irq.c
index ca70e5fcc7a..44f50dcb616 100644
--- a/arch/arm/mach-gemini/irq.c
+++ b/arch/arm/mach-gemini/irq.c
@@ -15,8 +15,11 @@
#include <linux/stddef.h>
#include <linux/list.h>
#include <linux/sched.h>
+#include <linux/cpu.h>
+
#include <asm/irq.h>
#include <asm/mach/irq.h>
+#include <asm/system_misc.h>
#include <mach/hardware.h>
#define IRQ_SOURCE(base_addr) (base_addr + 0x00)
@@ -64,8 +67,8 @@ static struct irq_chip gemini_irq_chip = {
static struct resource irq_resource = {
.name = "irq_handler",
- .start = IO_ADDRESS(GEMINI_INTERRUPT_BASE),
- .end = IO_ADDRESS(FIQ_STATUS(GEMINI_INTERRUPT_BASE)) + 4,
+ .start = GEMINI_INTERRUPT_BASE,
+ .end = FIQ_STATUS(GEMINI_INTERRUPT_BASE) + 4,
};
void __init gemini_init_irq(void)
@@ -76,7 +79,7 @@ void __init gemini_init_irq(void)
* Disable the idle handler by default since it is buggy
* For more info see arch/arm/mach-gemini/idle.c
*/
- disable_hlt();
+ cpu_idle_poll_ctrl(true);
request_resource(&iomem_resource, &irq_resource);
diff --git a/arch/arm/mach-gemini/mm.c b/arch/arm/mach-gemini/mm.c
index 51948242ec0..2c2cd284bb6 100644
--- a/arch/arm/mach-gemini/mm.c
+++ b/arch/arm/mach-gemini/mm.c
@@ -19,57 +19,57 @@
/* Page table mapping for I/O region */
static struct map_desc gemini_io_desc[] __initdata = {
{
- .virtual = IO_ADDRESS(GEMINI_GLOBAL_BASE),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_GLOBAL_BASE),
.pfn =__phys_to_pfn(GEMINI_GLOBAL_BASE),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_UART_BASE),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_UART_BASE),
.pfn = __phys_to_pfn(GEMINI_UART_BASE),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_TIMER_BASE),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_TIMER_BASE),
.pfn = __phys_to_pfn(GEMINI_TIMER_BASE),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_INTERRUPT_BASE),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_INTERRUPT_BASE),
.pfn = __phys_to_pfn(GEMINI_INTERRUPT_BASE),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_POWER_CTRL_BASE),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_POWER_CTRL_BASE),
.pfn = __phys_to_pfn(GEMINI_POWER_CTRL_BASE),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_GPIO_BASE(0)),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_GPIO_BASE(0)),
.pfn = __phys_to_pfn(GEMINI_GPIO_BASE(0)),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_GPIO_BASE(1)),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_GPIO_BASE(1)),
.pfn = __phys_to_pfn(GEMINI_GPIO_BASE(1)),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_GPIO_BASE(2)),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_GPIO_BASE(2)),
.pfn = __phys_to_pfn(GEMINI_GPIO_BASE(2)),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
.pfn = __phys_to_pfn(GEMINI_FLASH_CTRL_BASE),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_DRAM_CTRL_BASE),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_DRAM_CTRL_BASE),
.pfn = __phys_to_pfn(GEMINI_DRAM_CTRL_BASE),
.length = SZ_512K,
.type = MT_DEVICE,
}, {
- .virtual = IO_ADDRESS(GEMINI_GENERAL_DMA_BASE),
+ .virtual = (unsigned long)IO_ADDRESS(GEMINI_GENERAL_DMA_BASE),
.pfn = __phys_to_pfn(GEMINI_GENERAL_DMA_BASE),
.length = SZ_512K,
.type = MT_DEVICE,
diff --git a/arch/arm/mach-gemini/include/mach/system.h b/arch/arm/mach-gemini/reset.c
index a33b5a1f8ab..b26659759e2 100644
--- a/arch/arm/mach-gemini/include/mach/system.h
+++ b/arch/arm/mach-gemini/reset.c
@@ -14,7 +14,7 @@
#include <mach/hardware.h>
#include <mach/global_reg.h>
-static inline void arch_reset(char mode, const char *cmd)
+void gemini_restart(char mode, const char *cmd)
{
__raw_writel(RESET_GLOBAL | RESET_CPU1,
IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_RESET);
diff --git a/arch/arm/mach-gemini/time.c b/arch/arm/mach-gemini/time.c
index 21dc5a89d1c..0a63c4d25b6 100644
--- a/arch/arm/mach-gemini/time.c
+++ b/arch/arm/mach-gemini/time.c
@@ -13,6 +13,8 @@
#include <mach/hardware.h>
#include <mach/global_reg.h>
#include <asm/mach/time.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
/*
* Register definitions for the timers
@@ -33,19 +35,89 @@
#define TIMER_3_CR_CLOCK (1 << 7)
#define TIMER_3_CR_INT (1 << 8)
+static unsigned int tick_rate;
+
+static int gemini_timer_set_next_event(unsigned long cycles,
+ struct clock_event_device *evt)
+{
+ u32 cr;
+
+ cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+
+ /* This may be overdoing it, feel free to test without this */
+ cr &= ~TIMER_2_CR_ENABLE;
+ cr &= ~TIMER_2_CR_INT;
+ writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+
+ /* Set next event */
+ writel(cycles, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+ writel(cycles, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+ cr |= TIMER_2_CR_ENABLE;
+ cr |= TIMER_2_CR_INT;
+ writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+
+ return 0;
+}
+
+static void gemini_timer_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ);
+ u32 cr;
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ /* Start the timer */
+ writel(period,
+ TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+ writel(period,
+ TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
+ cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+ cr |= TIMER_2_CR_ENABLE;
+ cr |= TIMER_2_CR_INT;
+ writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_RESUME:
+ /*
+ * Disable also for oneshot: the set_next() call will
+ * arm the timer instead.
+ */
+ cr = readl(TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+ cr &= ~TIMER_2_CR_ENABLE;
+ cr &= ~TIMER_2_CR_INT;
+ writel(cr, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+ break;
+ default:
+ break;
+ }
+}
+
+/* Use TIMER2 as clock event */
+static struct clock_event_device gemini_clockevent = {
+ .name = "TIMER2",
+ .rating = 300, /* Reasonably fast and accurate clock event */
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_next_event = gemini_timer_set_next_event,
+ .set_mode = gemini_timer_set_mode,
+};
+
/*
* IRQ handler for the timer
*/
static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id)
{
- timer_tick();
+ struct clock_event_device *evt = &gemini_clockevent;
+ evt->event_handler(evt);
return IRQ_HANDLED;
}
static struct irqaction gemini_timer_irq = {
.name = "Gemini Timer Tick",
- .flags = IRQF_DISABLED | IRQF_TIMER,
+ .flags = IRQF_TIMER,
.handler = gemini_timer_interrupt,
};
@@ -54,9 +126,9 @@ static struct irqaction gemini_timer_irq = {
*/
void __init gemini_timer_init(void)
{
- unsigned int tick_rate, reg_v;
+ u32 reg_v;
- reg_v = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE + GLOBAL_STATUS));
+ reg_v = readl(IO_ADDRESS(GEMINI_GLOBAL_BASE + GLOBAL_STATUS));
tick_rate = REG_TO_AHB_SPEED(reg_v) * 1000000;
printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000);
@@ -82,8 +154,17 @@ void __init gemini_timer_init(void)
* Make irqs happen for the system timer
*/
setup_irq(IRQ_TIMER2, &gemini_timer_irq);
- /* Start the timer */
- __raw_writel(tick_rate / HZ, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER2_BASE)));
- __raw_writel(tick_rate / HZ, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER2_BASE)));
- __raw_writel(TIMER_2_CR_ENABLE | TIMER_2_CR_INT, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+
+ /* Enable and use TIMER1 as clock source */
+ writel(0xffffffff, TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)));
+ writel(0xffffffff, TIMER_LOAD(IO_ADDRESS(GEMINI_TIMER1_BASE)));
+ writel(TIMER_1_CR_ENABLE, TIMER_CR(IO_ADDRESS(GEMINI_TIMER_BASE)));
+ if (clocksource_mmio_init(TIMER_COUNT(IO_ADDRESS(GEMINI_TIMER1_BASE)),
+ "TIMER1", tick_rate, 300, 32,
+ clocksource_mmio_readl_up))
+ pr_err("timer: failed to initialize gemini clock source\n");
+
+ /* Configure and register the clockevent */
+ clockevents_config_and_register(&gemini_clockevent, tick_rate,
+ 1, 0xffffffff);
}