diff options
author | yagi <yagi@ke66.alps.lineo.co.jp> | 2012-06-25 13:09:05 +0900 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2012-07-03 17:15:24 -0400 |
commit | e20a0d13f15e61a737e05abd34743c31dec97604 (patch) | |
tree | bc0b8e25cf9d389f2edc75e589a28200a01dff70 | |
parent | 112d2429ef6459979bbb4b5ea54624674b6f6b2b (diff) |
Update: kernel timer
-rw-r--r-- | arch/arm/include/asm/entry-macro-multi.S | 3 | ||||
-rw-r--r-- | arch/arm/include/asm/hardirq.h | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/hardware/entry-macro-gic.S | 3 | ||||
-rw-r--r-- | arch/arm/kernel/irq.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-mvf/Kconfig | 8 | ||||
-rw-r--r-- | arch/arm/mach-mvf/clock.c | 9 | ||||
-rwxr-xr-x | arch/arm/plat-mxc/Makefile | 5 | ||||
-rw-r--r-- | arch/arm/plat-mxc/include/mach/irqs.h | 2 | ||||
-rw-r--r-- | arch/arm/plat-mxc/mvf_pit_time.c | 37 |
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)); } |