diff options
Diffstat (limited to 'chip/npcx/hwtimer.c')
-rw-r--r-- | chip/npcx/hwtimer.c | 341 |
1 files changed, 0 insertions, 341 deletions
diff --git a/chip/npcx/hwtimer.c b/chip/npcx/hwtimer.c deleted file mode 100644 index 92f9843d09..0000000000 --- a/chip/npcx/hwtimer.c +++ /dev/null @@ -1,341 +0,0 @@ -/* Copyright 2014 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 "clock.h" -#include "clock_chip.h" -#include "common.h" -#include "hooks.h" -#include "hwtimer.h" -#include "hwtimer_chip.h" -#include "math_util.h" -#include "registers.h" -#include "console.h" -#include "task.h" -#include "timer.h" -#include "util.h" - -/* Depth of event timer */ -#define TICK_EVT_DEPTH 16 /* Depth of event timer Unit: bits */ -#define TICK_EVT_INTERVAL BIT(TICK_EVT_DEPTH) /* Unit: us */ -#define TICK_EVT_INTERVAL_MASK (TICK_EVT_INTERVAL - 1) /* Mask of interval */ -#define TICK_EVT_MAX_CNT (TICK_EVT_INTERVAL - 1) /* Maximum event counter */ - -/* Time when event will be expired unit:us */ -static volatile uint32_t evt_expired_us; -/* 32-bits event counter */ -static volatile uint32_t evt_cnt; -/* Debugger information */ -#if DEBUG_TMR -static volatile uint32_t evt_cnt_us_dbg; -static volatile uint32_t cur_cnt_us_dbg; -#endif - -#if !(DEBUG_TMR) -#define CPUTS(...) -#define CPRINTS(...) -#else -#define CPUTS(outstr) cputs(CC_CLOCK, outstr) -#define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) -#endif - -/*****************************************************************************/ -/* Internal functions */ -void init_hw_timer(int itim_no, enum ITIM_SOURCE_CLOCK_T source) -{ - /* Select which clock to use for this timer */ - UPDATE_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_CKSEL, - source != ITIM_SOURCE_CLOCK_APB2); - - /* Clear timeout status */ - SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_STS); - - /* ITIM timeout interrupt enable */ - SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_IE); - - /* ITIM timeout wake-up enable */ - SET_BIT(NPCX_ITCTS(itim_no), NPCX_ITCTS_TO_WUE); -} - -/*****************************************************************************/ -/* HWTimer event handlers */ -void __hw_clock_event_set(uint32_t deadline) -{ - fp_t inv_evt_tick = FLOAT_TO_FP(INT_32K_CLOCK/(float)SECOND); - int32_t evt_cnt_us; - /* Is deadline min value? */ - if (evt_expired_us != 0 && evt_expired_us < deadline) - return; - - /* mark min event value */ - evt_expired_us = deadline; - evt_cnt_us = deadline - __hw_clock_source_read(); -#if DEBUG_TMR - evt_cnt_us_dbg = deadline - __hw_clock_source_read(); -#endif - /* Deadline is behind current timer */ - if (evt_cnt_us < 0) - evt_cnt_us = 1; - - /* Event module disable */ - CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN); - - /* - * ITIM count down : event expired : Unit: 1/32768 sec - * It must exceed evt_expired_us for process_timers function - */ - evt_cnt = FP_TO_INT((fp_inter_t)(evt_cnt_us) * inv_evt_tick); - if (evt_cnt > TICK_EVT_MAX_CNT) { - CPRINTS("Event overflow! 0x%08x, us is %d", - evt_cnt, evt_cnt_us); - evt_cnt = TICK_EVT_MAX_CNT; - } - - /* Wait for module disable to take effect before updating count */ - while (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN)) - ; - - NPCX_ITCNT(ITIM_EVENT_NO) = MAX(evt_cnt, 1); - - /* Event module enable */ - SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN); - - /* Wait for module enable */ - while (!IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN)) - ; - - /* Enable interrupt of ITIM */ - task_enable_irq(ITIM_INT(ITIM_EVENT_NO)); -} - -/* Returns the time-stamp of the next programmed event */ -uint32_t __hw_clock_event_get(void) -{ - if (evt_expired_us) - return evt_expired_us; - else /* No events. Give maximum deadline */ - return EVT_MAX_EXPIRED_US; -} - -/* Get current counter value of event timer */ -uint16_t __hw_clock_event_count(void) -{ - uint16_t cnt, cnt2; - - cnt = NPCX_ITCNT(ITIM_EVENT_NO); - /* Wait for two consecutive equal values are read */ - while ((cnt2 = NPCX_ITCNT(ITIM_EVENT_NO)) != cnt) - cnt = cnt2; - - return cnt; -} - -/* Returns time delay cause of deep idle */ -uint32_t __hw_clock_get_sleep_time(uint16_t pre_evt_cnt) -{ - fp_t evt_tick = FLOAT_TO_FP(SECOND/(float)INT_32K_CLOCK); - uint32_t sleep_time; - uint16_t cnt = __hw_clock_event_count(); - - /* Event has been triggered but timer ISR doesn't handle it */ - if (IS_BIT_SET(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_TO_STS)) - sleep_time = FP_TO_INT((fp_inter_t)(pre_evt_cnt+1) * evt_tick); - /* Event hasn't been triggered */ - else - sleep_time = FP_TO_INT((fp_inter_t)(pre_evt_cnt+1 - cnt) * - evt_tick); - - return sleep_time; -} - -/* Cancel the next event programmed by __hw_clock_event_set */ -void __hw_clock_event_clear(void) -{ - /* ITIM event module disable */ - CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN); - - /* Disable interrupt of Event */ - task_disable_irq(ITIM_INT(ITIM_EVENT_NO)); - - /* Clear event parameters */ - evt_expired_us = 0; - evt_cnt = 0; -} - -/* Irq for hwtimer event */ -void __hw_clock_event_irq(void) -{ - /* ITIM event module disable */ - CLEAR_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_ITEN); - - /* Disable interrupt of event */ - task_disable_irq(ITIM_INT(ITIM_EVENT_NO)); - - /* Clear timeout status for event */ - SET_BIT(NPCX_ITCTS(ITIM_EVENT_NO), NPCX_ITCTS_TO_STS); - - /* Clear event parameters */ - evt_expired_us = 0; - evt_cnt = 0; - - /* handle upper driver */ - process_timers(0); - -#ifdef CONFIG_LOW_POWER_IDLE - /* - * Set event for ITIM32 after process_timers() since no events set if - * event's deadline is over 32 bits but current source clock isn't. - * ITIM32 is based on apb2 and ec won't wake-up in deep-idle even if it - * expires. - */ - if (evt_expired_us == 0) - __hw_clock_event_set(EVT_MAX_EXPIRED_US); -#endif - -} -DECLARE_IRQ(ITIM_INT(ITIM_EVENT_NO), __hw_clock_event_irq, 3); - -/*****************************************************************************/ -/* HWTimer tick handlers */ - -/* Modify preload counter of source clock. */ -void hw_clock_source_set_preload(uint32_t ts, uint8_t clear) -{ - /* ITIM32 module disable */ - CLEAR_BIT(NPCX_ITCTS(ITIM_SYSTEM_NO), NPCX_ITCTS_ITEN); - CLEAR_BIT(NPCX_ITCTS(ITIM_SYSTEM_NO), NPCX_ITCTS_CKSEL); - - /* Set preload counter to current time */ - NPCX_ITCNT_SYSTEM = TICK_ITIM32_MAX_CNT - ts; - /* Clear timeout status or not */ - if (clear) - SET_BIT(NPCX_ITCTS(ITIM_SYSTEM_NO), NPCX_ITCTS_TO_STS); - /* ITIM32 module enable */ - SET_BIT(NPCX_ITCTS(ITIM_SYSTEM_NO), NPCX_ITCTS_ITEN); -} - -/* Returns the value of the free-running counter used as clock. */ -uint32_t __hw_clock_source_read(void) -{ - uint32_t cnt, cnt2; - - cnt = NPCX_ITCNT_SYSTEM; - /* - * Wait for two consecutive equal values are read no matter - * ITIM's source clock is APB2 or 32K since mux's delay. - */ - while ((cnt2 = NPCX_ITCNT_SYSTEM) != cnt) - cnt = cnt2; - -#if DEBUG_TMR - cur_cnt_us_dbg = TICK_ITIM32_MAX_CNT - cnt; -#endif - return TICK_ITIM32_MAX_CNT - cnt; -} - -/* Override the current value of the hardware counter */ -void __hw_clock_source_set(uint32_t ts) -{ -#if DEBUG_TMR - cur_cnt_us_dbg = TICK_ITIM32_MAX_CNT - ts; -#endif - hw_clock_source_set_preload(ts, 0); -} - -/* Irq for hwtimer tick */ -void __hw_clock_source_irq(void) -{ - /* Is timeout trigger trigger? */ - if (IS_BIT_SET(NPCX_ITCTS(ITIM_SYSTEM_NO), NPCX_ITCTS_TO_STS)) { - /* Restore ITIM32 preload counter value to maximum value */ - hw_clock_source_set_preload(0, 1); - /* 32-bits timer count overflow */ - process_timers(1); - - } else { /* Handle soft trigger */ - process_timers(0); -#ifdef CONFIG_LOW_POWER_IDLE - /* Set event for ITIM32. Please see above for detail */ - if (evt_expired_us == 0) - __hw_clock_event_set(EVT_MAX_EXPIRED_US); -#endif - } -} -DECLARE_IRQ(ITIM_INT(ITIM_SYSTEM_NO), __hw_clock_source_irq, 3); - -/* Handle ITIM32 overflow if interrupt is disabled */ -void __hw_clock_handle_overflow(uint32_t clksrc_high) -{ - timestamp_t newtime; - - /* Overflow occurred? */ - if (!IS_BIT_SET(NPCX_ITCTS(ITIM_SYSTEM_NO), NPCX_ITCTS_TO_STS)) - return; - - /* Clear timeout status */ - SET_BIT(NPCX_ITCTS(ITIM_SYSTEM_NO), NPCX_ITCTS_TO_STS); - - /* - * Restore ITIM32 preload counter value to maximum and execute - * process_timers() later in ISR by trigger software interrupt in - * force_time(). - */ - newtime.le.hi = clksrc_high + 1; - newtime.le.lo = 0; - force_time(newtime); -} - -static void update_prescaler(void) -{ - /* - * prescaler to time tick - * Ttick_unit = (PRE_8+1) * Tapb2_clk - * PRE_8 = (Ttick_unit/Tapb2_clk) -1 - */ - NPCX_ITPRE(ITIM_SYSTEM_NO) = (clock_get_apb2_freq() / SECOND) - 1; - /* Set event tick unit = 1/32768 sec */ - NPCX_ITPRE(ITIM_EVENT_NO) = 0; - -} -DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT); - -void __hw_early_init_hwtimer(uint32_t start_t) -{ - /* - * 1. Use ITIM16-1 as internal time reading - * 2. Use ITIM16-2 for event handling - */ - - /* Enable clock for ITIM peripheral */ - clock_enable_peripheral(CGC_OFFSET_TIMER, CGC_TIMER_MASK, - CGC_MODE_RUN | CGC_MODE_SLEEP); - - /* init tick & event timer first */ - init_hw_timer(ITIM_SYSTEM_NO, ITIM_SOURCE_CLOCK_APB2); - init_hw_timer(ITIM_EVENT_NO, ITIM_SOURCE_CLOCK_32K); - - /* Set initial prescaler */ - update_prescaler(); - - hw_clock_source_set_preload(start_t, 1); -} - -/* Note that early_init_hwtimer() has already executed by this point */ -int __hw_clock_source_init(uint32_t start_t) -{ - /* - * Override the count with the start value now that counting has - * started. Note that we may have already called this function from - * gpio_pre_init(), but only in the case where we expected a reset, so - * we should not get here in that case. - */ - __hw_early_init_hwtimer(start_t); - - /* Enable interrupt of ITIM */ - task_enable_irq(ITIM_INT(ITIM_SYSTEM_NO)); - - return ITIM_INT(ITIM_SYSTEM_NO); -} |