summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryagi <yagi@ke66.alps.lineo.co.jp>2012-06-25 13:09:05 +0900
committerJustin Waters <justin.waters@timesys.com>2012-07-03 17:15:24 -0400
commite20a0d13f15e61a737e05abd34743c31dec97604 (patch)
treebc0b8e25cf9d389f2edc75e589a28200a01dff70
parent112d2429ef6459979bbb4b5ea54624674b6f6b2b (diff)
Update: kernel timer
-rw-r--r--arch/arm/include/asm/entry-macro-multi.S3
-rw-r--r--arch/arm/include/asm/hardirq.h2
-rw-r--r--arch/arm/include/asm/hardware/entry-macro-gic.S3
-rw-r--r--arch/arm/kernel/irq.c2
-rw-r--r--arch/arm/mach-mvf/Kconfig8
-rw-r--r--arch/arm/mach-mvf/clock.c9
-rwxr-xr-xarch/arm/plat-mxc/Makefile5
-rw-r--r--arch/arm/plat-mxc/include/mach/irqs.h2
-rw-r--r--arch/arm/plat-mxc/mvf_pit_time.c37
9 files changed, 44 insertions, 27 deletions
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
index 459d47f60962..0936372e99e6 100644
--- a/arch/arm/include/asm/entry-macro-multi.S
+++ b/arch/arm/include/asm/entry-macro-multi.S
@@ -34,7 +34,8 @@
#endif
#endif
-#ifdef CONFIG_ARCH_MVF /* MVF Global Timer Support*/
+#if defined(CONFIG_ARCH_MVF) && !defined(CONFIG_MVF_USE_PIT)
+ /* MVF Global Timer Support*/
test_for_gtirq r0, r6, r5, lr
movne r0, sp
adrne lr, BSYM(1b)
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
index eb55ef11286a..5fc5883e3214 100644
--- a/arch/arm/include/asm/hardirq.h
+++ b/arch/arm/include/asm/hardirq.h
@@ -15,7 +15,7 @@ typedef struct {
#ifdef CONFIG_SMP
unsigned int ipi_irqs[NR_IPI];
#endif
-#ifdef CONFIG_ARCH_MVF
+#if defined(CONFIG_ARCH_MVF) && !defined(CONFIG_MVF_USE_PIT)
unsigned int global_timer_irqs;
#endif
} ____cacheline_aligned irq_cpustat_t;
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S
index 6cf181a64dc9..5b8988b068d8 100644
--- a/arch/arm/include/asm/hardware/entry-macro-gic.S
+++ b/arch/arm/include/asm/hardware/entry-macro-gic.S
@@ -74,7 +74,8 @@
cmp \tmp, #0
.endm
-#ifdef CONFIG_ARCH_MVF /* MVF Global Timer Support*/
+#if defined(CONFIG_ARCH_MVF) && !defined(CONFIG_MVF_USE_PIT)
+ /* MVF Global Timer Support*/
.macro test_for_gtirq, irqnr, irqstat, base, tmp
bic \irqnr, \irqstat, #0x1c00
mov \tmp, #0
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index ac9ca03f219d..84f0de0f6fb4 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -62,7 +62,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
#ifdef CONFIG_LOCAL_TIMERS
show_local_irqs(p, prec);
#endif
-#ifdef CONFIG_ARCH_MVF
+#if defined(CONFIG_ARCH_MVF) && !defined(CONFIG_MVF_USE_PIT)
show_global_timer_irqs(p, prec);
#endif
seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
diff --git a/arch/arm/mach-mvf/Kconfig b/arch/arm/mach-mvf/Kconfig
index 08a5c33d1dce..6250be1e4b88 100644
--- a/arch/arm/mach-mvf/Kconfig
+++ b/arch/arm/mach-mvf/Kconfig
@@ -61,6 +61,14 @@ config MACH_TWR_VF600
comment "MVF Options:"
+config MVF_USE_PIT
+ bool "Use PIT instead of Global Timer"
+ help
+ Use PIT as the system timer on systems that have it. Normally you
+ don't have a reason to do so as the PIT has the same features and
+ uses the same clocks as the Global Timer. Anyway, on some systems
+ the Global Timer may be in use for other purposes.
+
menu "IOMUX Setting"
choice
diff --git a/arch/arm/mach-mvf/clock.c b/arch/arm/mach-mvf/clock.c
index 7c537f561662..98741aacb05a 100644
--- a/arch/arm/mach-mvf/clock.c
+++ b/arch/arm/mach-mvf/clock.c
@@ -4252,12 +4252,15 @@ int __init mvf_clocks_init(unsigned long sirc, unsigned long firc,
3 << MXC_CCM_CCGRx_CG8_OFFSET,
MXC_CCM_CCGR11);
- /* setup Global Timer */
- base = MVF_IO_ADDRESS(MVF_CA5_SCU_GIC_BASE_ADDR + 0x200);
- mvf_timer_init(&ca5_scu_clk, base, IRQ_GLOBALTIMER);
+#ifdef CONFIG_MVF_USE_PIT
/* setup PIT(Periodic Interrupt Timer) */
base = ioremap(MVF_PIT_BASE_ADDR, SZ_4K);
mvf_pit_timer_init(&pit_clk, base, MXC_INT_PIT);
+#else
+ /* setup Global Timer */
+ base = MVF_IO_ADDRESS(MVF_CA5_SCU_GIC_BASE_ADDR + 0x200);
+ mvf_timer_init(&ca5_scu_clk, base, IRQ_GLOBALTIMER);
+#endif
lp_high_freq = 0;
lp_med_freq = 0;
diff --git a/arch/arm/plat-mxc/Makefile b/arch/arm/plat-mxc/Makefile
index c78262c2cd19..b2609e282ad7 100755
--- a/arch/arm/plat-mxc/Makefile
+++ b/arch/arm/plat-mxc/Makefile
@@ -7,9 +7,12 @@ obj-y := clock.o devices.o cpu.o system.o irq-common.o usb_common.o usb_wakeup.o
ifdef CONFIG_ARCH_MVF
obj-y += mvf_gpio.o
-obj-y += mvf_time.o
+ifdef CONFIG_MVF_USE_PIT
obj-y += mvf_pit_time.o
else
+obj-y += mvf_time.o
+endif
+else
obj-y += gpio.o
obj-y += time.o
endif
diff --git a/arch/arm/plat-mxc/include/mach/irqs.h b/arch/arm/plat-mxc/include/mach/irqs.h
index 16e42f29b52d..9d06bd9d529a 100644
--- a/arch/arm/plat-mxc/include/mach/irqs.h
+++ b/arch/arm/plat-mxc/include/mach/irqs.h
@@ -83,7 +83,7 @@ extern int imx_irq_set_priority(unsigned char irq, unsigned char prio);
/* switch between IRQ and FIQ */
extern int mxc_set_irq_fiq(unsigned int irq, unsigned int type);
-#ifdef CONFIG_ARCH_MVF
+#if defined(CONFIG_ARCH_MVF) && !defined(CONFIG_MVF_USE_PIT)
struct seq_file;
extern void show_global_timer_irqs(struct seq_file *, int);
#endif
diff --git a/arch/arm/plat-mxc/mvf_pit_time.c b/arch/arm/plat-mxc/mvf_pit_time.c
index 99c16eff0389..cd11d6d9726b 100644
--- a/arch/arm/plat-mxc/mvf_pit_time.c
+++ b/arch/arm/plat-mxc/mvf_pit_time.c
@@ -66,6 +66,7 @@
static struct clock_event_device clockevent_mvf_pit;
static enum clock_event_mode clockevent_mode = CLOCK_EVT_MODE_UNUSED;
static unsigned long ticks_per_jiffy;
+static unsigned long int_cnt = 0;
static void __iomem *timer_base;
@@ -118,6 +119,7 @@ cycle_t clocksource_mmio_readl_pit(struct clocksource *c)
cycle_t cyc;
cyc = __raw_readl(timer_base + PIT_LDVAL(TIMER_CH)) -
__raw_readl(timer_base + PIT_CVAL(TIMER_CH));
+ cyc += int_cnt * ticks_per_jiffy;
return cyc;
}
@@ -150,6 +152,7 @@ static int __init mvf_pit_clocksource_init(struct clk *timer_clk)
static void mvf_pit_set_mode(enum clock_event_mode mode,
struct clock_event_device *evt)
{
+ unsigned long reg;
unsigned long flags;
/*
@@ -176,10 +179,14 @@ static void mvf_pit_set_mode(enum clock_event_mode mode,
/* Remember timer mode */
clockevent_mode = mode;
local_irq_restore(flags);
-
+
+ reg = __raw_readl(timer_base + PIT_TCTRL(TIMER_CH));
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
local_irq_save(flags);
+ __raw_writel(ticks_per_jiffy, timer_base + PIT_LDVAL(TIMER_CH));
+ reg |= PIT_TCTRL_TEN;
+ __raw_writel(reg, timer_base + PIT_TCTRL(TIMER_CH));
pit_irq_enable();
local_irq_restore(flags);
#if 0
@@ -200,6 +207,11 @@ static void mvf_pit_set_mode(enum clock_event_mode mode,
break;
case CLOCK_EVT_MODE_SHUTDOWN:
case CLOCK_EVT_MODE_UNUSED:
+ reg &= ~PIT_TCTRL_TEN;
+ __raw_writel(reg, timer_base + PIT_TCTRL(TIMER_CH));
+ int_cnt = 0;
+ pit_irq_disable();
+ break;
case CLOCK_EVT_MODE_RESUME:
/* Left event sources disabled, no more interrupts appear */
break;
@@ -222,11 +234,8 @@ static irqreturn_t mvf_pit_timer_interrupt(int irq, void *dev_id)
if ( tstat ) {
__raw_writel(tstat, timer_base + PIT_TFLG(TIMER_CH));
pit_irq_acknowledge();
-#if 1
evt->event_handler(evt);
-#else
- xtime_update(1);
-#endif
+ int_cnt++;
return IRQ_HANDLED;
}
return IRQ_NONE;
@@ -324,8 +333,11 @@ void __init mvf_pit_timer_init(struct clk *timer_clk, void __iomem *base, int ir
* Initialise to a known state (all timers off, and timing reset)
*/
- // __raw_writel(PIT_MCR_MDIS, timer_base + PIT_MCR); /* Stop PIT */
- __raw_writel(0, timer_base + PIT_MCR); /* Stop PIT */
+ __raw_writel(0, timer_base + PIT_MCR); /* enable PIT */
+ /* STOP Time */
+ __raw_writel(__raw_readl(timer_base + PIT_TCTRL(TIMER_CH))
+ & ~(PIT_TCTRL_TEN),
+ timer_base + PIT_TCTRL(TIMER_CH));
/* init and register the timer to the framework */
mvf_pit_clocksource_init(timer_clk);
@@ -333,17 +345,6 @@ void __init mvf_pit_timer_init(struct clk *timer_clk, void __iomem *base, int ir
/* Make irqs happen */
setup_irq(irq, &mvf_pit_timer_irq);
-
- /* STOP Time */
- __raw_writel(__raw_readl(timer_base + PIT_TCTRL(TIMER_CH))
- & ~(PIT_TCTRL_TEN),
- timer_base + PIT_TCTRL(TIMER_CH));
-
- __raw_writel(ticks_per_jiffy, timer_base + PIT_LDVAL(TIMER_CH));
pit_irq_enable();
- /* Start Timer */
- __raw_writel(__raw_readl(timer_base + PIT_TCTRL(TIMER_CH))
- | (PIT_TCTRL_TEN),
- timer_base + PIT_TCTRL(TIMER_CH));
}