diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2012-01-25 21:16:46 +0000 |
---|---|---|
committer | Vincent Palatin <vpalatin@chromium.org> | 2012-01-25 22:50:07 +0000 |
commit | 645dad5d3f658d7c5e0d54453964e91afe7b43c0 (patch) | |
tree | 432904125c384bc93f3792d337c08e6718fa81f3 | |
parent | c89bea4a5b183f24d71277aa6b9d55c92001eda7 (diff) | |
download | chrome-ec-645dad5d3f658d7c5e0d54453964e91afe7b43c0.tar.gz |
Split the timer code between OS code and hardware dependant code.
Preparatory work to introduce a second SoC : 2/5
The hwtimer.* files implement the driver for the SoC timer block.
The timer.* files provides the OS level clock/timer functions.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BUG=None
TEST=on BDS, check 'waitms' and 'gettime' on the EC console.
Change-Id: Icbc58d9be59ee268e2d5a94f8b20de0cabcdc91d
-rw-r--r-- | chip/lm4/build.mk | 2 | ||||
-rw-r--r-- | chip/lm4/hwtimer.c | 91 | ||||
-rw-r--r-- | chip/lm4/timer.c | 91 | ||||
-rw-r--r-- | include/hwtimer.h | 43 |
4 files changed, 147 insertions, 80 deletions
diff --git a/chip/lm4/build.mk b/chip/lm4/build.mk index 093b052e01..a7fb4e740b 100644 --- a/chip/lm4/build.mk +++ b/chip/lm4/build.mk @@ -10,5 +10,5 @@ CFLAGS_CPU=-mcpu=cortex-m4 -mthumb -Os -mno-sched-prolog chip-y=init.o panic.o switch.o task.o timer.o pwm.o i2c.o adc.o jtag.o chip-y+=clock.o gpio.o system.o lpc.o uart.o power_button.o -chip-y+=flash.o watchdog.o eeprom.o temp_sensor.o +chip-y+=flash.o watchdog.o eeprom.o temp_sensor.o hwtimer.o chip-$(CONFIG_TASK_KEYSCAN)+=keyboard_scan.o diff --git a/chip/lm4/hwtimer.c b/chip/lm4/hwtimer.c new file mode 100644 index 0000000000..9b221010c8 --- /dev/null +++ b/chip/lm4/hwtimer.c @@ -0,0 +1,91 @@ +/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Hardware timers driver */ + +#include <stdint.h> + +#include "board.h" +#include "hwtimer.h" +#include "registers.h" +#include "task.h" + +#define US_PER_SECOND 1000000 + +/* Divider to get microsecond for the clock */ +#define CLOCKSOURCE_DIVIDER (CPU_CLOCK/US_PER_SECOND) + +void __hw_clock_event_set(uint32_t deadline) +{ + /* set the match on the deadline */ + LM4_TIMER_TAMATCHR(6) = 0xffffffff - deadline; + /* Set the match interrupt */ + LM4_TIMER_IMR(6) |= 0x10; +} + +uint32_t __hw_clock_event_get(void) +{ + return 0xffffffff - LM4_TIMER_TAMATCHR(6); +} + +void __hw_clock_event_clear(void) +{ + /* Disable the match interrupt */ + LM4_TIMER_IMR(6) &= ~0x10; +} + +uint32_t __hw_clock_source_read(void) +{ + return 0xffffffff - LM4_TIMER_TAV(6); +} + +static void __hw_clock_source_irq(void) +{ + uint32_t status = LM4_TIMER_RIS(6); + + /* clear interrupt */ + LM4_TIMER_ICR(6) = status; + + /* + * Find expired timers and set the new timer deadline + * get from the IRQ status if the free running counter as overflowed + */ + process_timers(status & 0x01); +} +DECLARE_IRQ(LM4_IRQ_TIMERW0A, __hw_clock_source_irq, 1); + + +int __hw_clock_source_init(void) +{ + volatile uint32_t scratch __attribute__((unused)); + + /* Use WTIMER0 (timer 6) configured as a free running counter with 1 us + * period */ + + /* Enable WTIMER0 clock */ + LM4_SYSTEM_RCGCWTIMER |= 1; + /* wait 3 clock cycles before using the module */ + scratch = LM4_SYSTEM_RCGCWTIMER; + + /* Ensure timer is disabled : TAEN = TBEN = 0 */ + LM4_TIMER_CTL(6) &= ~0x101; + /* Set overflow interrupt */ + LM4_TIMER_IMR(6) = 0x1; + /* 32-bit timer mode */ + LM4_TIMER_CFG(6) = 4; + /* set the prescaler to increment every microsecond */ + LM4_TIMER_TAPR(6) = CLOCKSOURCE_DIVIDER; + /* Periodic mode, counting down */ + LM4_TIMER_TAMR(6) = 0x22; + /* use the full 32-bits of the timer */ + LM4_TIMER_TAILR(6) = 0xffffffff; + /* Starts counting in timer A */ + LM4_TIMER_CTL(6) |= 0x1; + + /* Enable interrupt */ + task_enable_irq(LM4_IRQ_TIMERW0A); + + return LM4_IRQ_TIMERW0A; +} diff --git a/chip/lm4/timer.c b/chip/lm4/timer.c index cb4b24fb77..56b67a9d2f 100644 --- a/chip/lm4/timer.c +++ b/chip/lm4/timer.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. +/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -9,18 +9,13 @@ #include "task.h" #include "timer.h" +#include "hwtimer.h" #include "atomic.h" #include "board.h" #include "console.h" #include "uart.h" -#include "registers.h" #include "util.h" -#define US_PER_SECOND 1000000 - -/* Divider to get microsecond for the clock */ -#define CLOCKSOURCE_DIVIDER (CPU_CLOCK/US_PER_SECOND) - /* high word of the 64-bit timestamp counter */ static volatile uint32_t clksrc_high; @@ -32,24 +27,8 @@ static timestamp_t timer_deadline[TASK_ID_COUNT]; static uint32_t next_deadline = 0xffffffff; -void __hw_clock_event_set(uint32_t deadline) -{ - /* set the match on the deadline */ - LM4_TIMER_TAMATCHR(6) = 0xffffffff - deadline; - /* Set the match interrupt */ - LM4_TIMER_IMR(6) |= 0x10; -} - -void __hw_clock_event_clear(void) -{ - /* Disable the match interrupt */ - LM4_TIMER_IMR(6) &= ~0x10; -} - -static uint32_t __hw_clock_source_read(void) -{ - return 0xffffffff - LM4_TIMER_TAV(6); -} +/* Hardware timer routine IRQ number */ +static int timer_irq; static void expire_timer(task_id_t tskid) { @@ -62,14 +41,17 @@ static void expire_timer(task_id_t tskid) /** * Search the next deadline and program it in the timer hardware * - * It returns a bitmap of expired timers. + * overflow: if true, the 32-bit counter as overflowed since the last call. */ -static void process_timers(void) +void process_timers(int overflow) { uint32_t check_timer, running_t0; timestamp_t next; timestamp_t now; + if (overflow) + clksrc_high++; + reprocess_timers: next.val = 0xffffffffffffffff; now = get_time(); @@ -105,54 +87,6 @@ reprocess_timers: //TODO narrow race: deadline might have been reached before } -static void __hw_clock_source_irq(void) -{ - uint32_t status = LM4_TIMER_RIS(6); - - /* clear interrupt */ - LM4_TIMER_ICR(6) = status; - /* free running counter as overflowed */ - if (status & 0x01) { - clksrc_high++; - } - /* Find expired timers and set the new timer deadline */ - process_timers(); -} -DECLARE_IRQ(LM4_IRQ_TIMERW0A, __hw_clock_source_irq, 1); - - -static void __hw_clock_source_init(void) -{ - volatile uint32_t scratch __attribute__((unused)); - - /* Use WTIMER0 (timer 6) configured as a free running counter with 1 us - * period */ - - /* Enable WTIMER0 clock */ - LM4_SYSTEM_RCGCWTIMER |= 1; - /* wait 3 clock cycles before using the module */ - scratch = LM4_SYSTEM_RCGCWTIMER; - - /* Ensure timer is disabled : TAEN = TBEN = 0 */ - LM4_TIMER_CTL(6) &= ~0x101; - /* Set overflow interrupt */ - LM4_TIMER_IMR(6) = 0x1; - /* 32-bit timer mode */ - LM4_TIMER_CFG(6) = 4; - /* set the prescaler to increment every microsecond */ - LM4_TIMER_TAPR(6) = CLOCKSOURCE_DIVIDER; - /* Periodic mode, counting down */ - LM4_TIMER_TAMR(6) = 0x22; - /* use the full 32-bits of the timer */ - LM4_TIMER_TAILR(6) = 0xffffffff; - /* Starts counting in timer A */ - LM4_TIMER_CTL(6) |= 0x1; - - /* Enable interrupt */ - task_enable_irq(LM4_IRQ_TIMERW0A); -} - - void udelay(unsigned us) { timestamp_t deadline = get_time(); @@ -174,12 +108,11 @@ int timer_arm(timestamp_t tstamp, task_id_t tskid) /* modify the next event if needed */ if ((tstamp.le.hi < clksrc_high) || ((tstamp.le.hi == clksrc_high) && (tstamp.le.lo <= next_deadline))) - task_trigger_irq(LM4_IRQ_TIMERW0A); + task_trigger_irq(timer_irq); return EC_SUCCESS; } - int timer_cancel(task_id_t tskid) { ASSERT(tskid < TASK_ID_COUNT); @@ -251,7 +184,7 @@ int command_timer_info(int argc, char **argv) "Deadline: 0x%08x%08x us\n" "Active timers:\n", ts.le.hi, ts.le.lo, clksrc_high, - 0xffffffff - LM4_TIMER_TAMATCHR(6)); + __hw_clock_event_get()); for (tskid = 0; tskid < TASK_ID_COUNT; tskid++) { if (timer_running & (1<<tskid)) uart_printf("Tsk %d tmr 0x%08x%08x\n", tskid, @@ -267,7 +200,7 @@ int timer_init(void) { BUILD_ASSERT(TASK_ID_COUNT < sizeof(timer_running) * 8); - __hw_clock_source_init(); + timer_irq = __hw_clock_source_init(); return EC_SUCCESS; } diff --git a/include/hwtimer.h b/include/hwtimer.h new file mode 100644 index 0000000000..384e3613dd --- /dev/null +++ b/include/hwtimer.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* Hardware timer driver API */ + +#ifndef __EC_HWTIMER_H +#define __EC_HWTIMER_H + +/** + * Programs when the next timer should fire an interrupt. + * deadline: timestamp of the event. + */ +void __hw_clock_event_set(uint32_t deadline); + +/* Returns the timestamp of the next programed event */ +uint32_t __hw_clock_event_get(void); + +/* Cancel the next event programed by __hw_clock_event_set */ +void __hw_clock_event_clear(void); + +/* Returns the value of the free-running counter used as clock. */ +uint32_t __hw_clock_source_read(void); + +/** + * Initializes the hardware timer used to provide clock services. + * + * It returns the IRQ number of the timer routine. + */ +int __hw_clock_source_init(void); + +/** + * Searches the next deadline and program it in the timer hardware. + * + * overflow: if true, the 32-bit counter as overflowed since the last call. + * + * This function is exported from the common timers code as an helper for the + * hardware timer interrupt routine. + */ +void process_timers(int overflow); + +#endif /* __EC_HWTIMER_H */ |