ITE drivers/ite_it8xxx2_timer: re-write ite timer driver
Re-write ite timer driver. Signed-off-by: Ruibin Chang <ruibin.chang@ite.com.tw>
This commit is contained in:
parent
78ef5ace6a
commit
21f0f958fe
4 changed files with 335 additions and 265 deletions
|
@ -3,218 +3,103 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <sys/util.h>
|
||||
#define DT_DRV_COMPAT ite_it8xxx2_timer
|
||||
|
||||
#include <drivers/timer/system_timer.h>
|
||||
#include <dt-bindings/interrupt-controller/ite-intc.h>
|
||||
#include <soc.h>
|
||||
#include <sys/printk.h>
|
||||
#include <spinlock.h>
|
||||
#include <sys_clock.h>
|
||||
|
||||
/**
|
||||
* Macro Define
|
||||
*/
|
||||
#define EXT_TIMER_BASE (DT_REG_ADDR_BY_IDX(DT_NODELABEL(timer), 0))
|
||||
#define EXT_CTL_B (EXT_TIMER_BASE + 0x10)
|
||||
#define EXT_PSC_B (EXT_TIMER_BASE + 0x11)
|
||||
#define EXT_LLR_B (EXT_TIMER_BASE + 0x14)
|
||||
#define EXT_LHR_B (EXT_TIMER_BASE + 0x15)
|
||||
#define EXT_LH2R_B (EXT_TIMER_BASE + 0x16)
|
||||
#define EXT_LH3R_B (EXT_TIMER_BASE + 0x17)
|
||||
#define EXT_CNTO_B (EXT_TIMER_BASE + 0x48)
|
||||
#include <logging/log.h>
|
||||
LOG_MODULE_REGISTER(timer, LOG_LEVEL_ERR);
|
||||
|
||||
#define CTIMER_HW_TIMER_INDEX EXT_TIMER_3
|
||||
#define ETIMER_HW_TIMER_INDEX EXT_TIMER_5
|
||||
#define RTIMER_HW_TIMER_INDEX EXT_TIMER_7
|
||||
#define CYC_PER_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \
|
||||
/ CONFIG_SYS_CLOCK_TICKS_PER_SEC)
|
||||
#define MAX_TICKS ((0x00ffffffu - CYC_PER_TICK) / CYC_PER_TICK)
|
||||
/* Control external timer3~8 */
|
||||
#define IT8XXX2_EXT_TIMER_BASE (DT_INST_REG_ADDR(0))/*0x00F01F10*/
|
||||
#define IT8XXX2_EXT_CTRLX(n) ECREG(IT8XXX2_EXT_TIMER_BASE + (n << 3))
|
||||
#define IT8XXX2_EXT_PSRX(n) ECREG(IT8XXX2_EXT_TIMER_BASE + 0x01 + (n << 3))
|
||||
#define IT8XXX2_EXT_CNTX(n) ECREG_u32(IT8XXX2_EXT_TIMER_BASE + 0x04 + \
|
||||
(n << 3))
|
||||
#define IT8XXX2_EXT_CNTOX(n) ECREG_u32(IT8XXX2_EXT_TIMER_BASE + 0x38 + \
|
||||
(n << 2))
|
||||
|
||||
#define MAX_TIMER_NUM 8
|
||||
#define REG_ADDR_OFFSET(idx) (idx * MAX_TIMER_NUM)
|
||||
#define IDX_SHIFT(idx, rsh, lsh) ((idx >> rsh) << lsh)
|
||||
/* Event timer configurations */
|
||||
#define EVENT_TIMER EXT_TIMER_3
|
||||
#define EVENT_TIMER_IRQ DT_INST_IRQ_BY_IDX(0, 0, irq)
|
||||
#define EVENT_TIMER_FLAG DT_INST_IRQ_BY_IDX(0, 0, flags)
|
||||
/* Event timer max count is 512 sec (base on clock source 32768Hz) */
|
||||
#define EVENT_TIMER_MAX_CNT 0x00FFFFFFUL
|
||||
|
||||
enum _EXT_TIMER_PRESCALE_TYPE_ {
|
||||
ET_PSR_32K,
|
||||
ET_PSR_1K,
|
||||
ET_PSR_32,
|
||||
ET_PSR_8M,
|
||||
};
|
||||
enum _EXT_TIMER_IDX_ {
|
||||
EXT_TIMER_3 = 0, /* ctimer */
|
||||
EXT_TIMER_4, /* ctimer */
|
||||
EXT_TIMER_5, /* etimer */
|
||||
EXT_TIMER_6, /* NULL */
|
||||
EXT_TIMER_7, /* rtimer */
|
||||
EXT_TIMER_8 /* NULL */
|
||||
};
|
||||
|
||||
/* Be careful of overflow issue */
|
||||
#define MILLI_SEC_TO_COUNT(hz, ms) ((hz) * (ms) / 1000)
|
||||
#define MICRO_SEC_TO_COUNT(hz, us) ((hz) * (us) / 1000000)
|
||||
|
||||
/**
|
||||
* ITE timer control api
|
||||
*/
|
||||
static void ite_timer_reload(uint8_t idx, uint32_t cnt)
|
||||
{
|
||||
/* timer_start */
|
||||
sys_set_bit((EXT_CTL_B + REG_ADDR_OFFSET(idx)), 0);
|
||||
sys_write8(((cnt >> 24) & 0xFF), (EXT_LH3R_B + REG_ADDR_OFFSET(idx)));
|
||||
sys_write8(((cnt >> 16) & 0xFF), (EXT_LH2R_B + REG_ADDR_OFFSET(idx)));
|
||||
sys_write8(((cnt >> 8) & 0xFF), (EXT_LHR_B + REG_ADDR_OFFSET(idx)));
|
||||
sys_write8(((cnt >> 0) & 0xFF), (EXT_LLR_B + REG_ADDR_OFFSET(idx)));
|
||||
}
|
||||
|
||||
/* The following function:
|
||||
* disable, enable, check_flag, clear_flag, wait,
|
||||
* can be used only for Timer #3 ~ #7
|
||||
*/
|
||||
static void ite_timer_disable(uint8_t idx)
|
||||
{
|
||||
CLEAR_MASK(IER19, (BIT(3 + (idx))));
|
||||
}
|
||||
|
||||
static void ite_timer_enable(uint8_t idx)
|
||||
{
|
||||
SET_MASK(IER19, (BIT(3 + (idx))));
|
||||
}
|
||||
|
||||
static void ite_timer_clear_flag(uint8_t idx)
|
||||
{
|
||||
ISR19 = BIT(3 + (idx));
|
||||
}
|
||||
|
||||
/**
|
||||
* timer_init()
|
||||
*/
|
||||
static int timer_init(uint8_t idx, uint8_t psr, uint8_t initial_state,
|
||||
uint8_t enable_isr, uint32_t cnt)
|
||||
{
|
||||
/* Setup Triggered Mode -> Rising-Edge Trig. */
|
||||
if (idx != EXT_TIMER_8) {
|
||||
IELMR19 |= BIT(3 + idx);
|
||||
IPOLR19 &= (~(BIT(3 + idx)));
|
||||
} else {
|
||||
IELMR10 |= BIT(0);
|
||||
IPOLR10 &= (~(BIT(0)));
|
||||
}
|
||||
|
||||
/* Setup prescaler */
|
||||
sys_write8(psr, (EXT_PSC_B + REG_ADDR_OFFSET(idx)));
|
||||
|
||||
/* Reload counter */
|
||||
ite_timer_reload(idx, cnt);
|
||||
|
||||
/* Start counting or not */
|
||||
if (initial_state) {
|
||||
/* timer restart */
|
||||
/* timer_stop */
|
||||
sys_clear_bit((EXT_CTL_B + REG_ADDR_OFFSET(idx)), 0);
|
||||
|
||||
/* timer_start */
|
||||
sys_set_bit((EXT_CTL_B + REG_ADDR_OFFSET(idx)), 0);
|
||||
} else {
|
||||
/* timer_stop */
|
||||
sys_clear_bit((EXT_CTL_B + REG_ADDR_OFFSET(idx)), 0);
|
||||
}
|
||||
|
||||
/* Enable ISR or not & Clear flag */
|
||||
if (idx != EXT_TIMER_8) {
|
||||
if (enable_isr) {
|
||||
ite_timer_enable(idx);
|
||||
} else {
|
||||
ite_timer_disable(idx);
|
||||
}
|
||||
ite_timer_clear_flag(idx);
|
||||
} else {
|
||||
if (enable_isr) {
|
||||
SET_MASK(IER10, BIT(0));
|
||||
} else {
|
||||
CLEAR_MASK(IER10, BIT(0));
|
||||
}
|
||||
ISR10 = BIT(0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int timer_init_ms(uint8_t idx, uint8_t psr, uint8_t initial_state,
|
||||
uint8_t enable_isr, uint32_t u32MilliSec)
|
||||
{
|
||||
uint32_t cnt;
|
||||
|
||||
if (psr == ET_PSR_32K) {
|
||||
cnt = MILLI_SEC_TO_COUNT(32768, u32MilliSec);
|
||||
} else if (psr == ET_PSR_1K) {
|
||||
cnt = MILLI_SEC_TO_COUNT(1024, u32MilliSec);
|
||||
} else if (psr == ET_PSR_32) {
|
||||
cnt = MILLI_SEC_TO_COUNT(32, u32MilliSec);
|
||||
} else if (psr == ET_PSR_8M) {
|
||||
cnt = u32MilliSec * 8000; /* fixed overflow issue */
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 24-bits only */
|
||||
if (cnt >> 24) {
|
||||
return -2;
|
||||
}
|
||||
return timer_init(idx, psr, initial_state, enable_isr, cnt);
|
||||
}
|
||||
|
||||
static void timer_init_combine(uint8_t idx, uint8_t bEnable)
|
||||
{
|
||||
if (bEnable) {
|
||||
sys_set_bit((EXT_CTL_B + IDX_SHIFT(idx, 1, (1 + 3))), 3);
|
||||
} else {
|
||||
sys_clear_bit((EXT_CTL_B + IDX_SHIFT(idx, 1, (1 + 3))), 3);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_timer_combine_count(uint8_t idx)
|
||||
{
|
||||
return sys_read32(EXT_CNTO_B + ((IDX_SHIFT(idx, 1, 1) + 1) * 4));
|
||||
}
|
||||
|
||||
static void timer_count_reset(uint8_t idx, uint32_t cnt)
|
||||
{
|
||||
/* Reload counter */
|
||||
ite_timer_reload(idx, cnt);
|
||||
|
||||
/* Start counting or not */
|
||||
/* timer_stop */
|
||||
sys_clear_bit((EXT_CTL_B + REG_ADDR_OFFSET(idx)), 0);
|
||||
/* timer_start */
|
||||
sys_set_bit((EXT_CTL_B + REG_ADDR_OFFSET(idx)), 0);
|
||||
}
|
||||
|
||||
static struct k_spinlock lock;
|
||||
static volatile uint32_t accumulated_cycle_count;
|
||||
static void timer_isr(const void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
|
||||
/* timer_stop */
|
||||
sys_clear_bit((EXT_CTL_B + ((ETIMER_HW_TIMER_INDEX) * MAX_TIMER_NUM)),
|
||||
0);
|
||||
uint32_t dticks = (get_timer_combine_count(CTIMER_HW_TIMER_INDEX)
|
||||
- accumulated_cycle_count) / CYC_PER_TICK;
|
||||
accumulated_cycle_count += dticks * CYC_PER_TICK;
|
||||
k_spin_unlock(&lock, key);
|
||||
sys_clock_announce(dticks);
|
||||
}
|
||||
/* Free run timer configurations */
|
||||
#define FREE_RUN_TIMER EXT_TIMER_4
|
||||
#define FREE_RUN_TIMER_IRQ DT_INST_IRQ_BY_IDX(0, 1, irq)
|
||||
#define FREE_RUN_TIMER_FLAG DT_INST_IRQ_BY_IDX(0, 1, flags)
|
||||
/* Free run timer max count is 36.4 hr (base on clock source 32768Hz) */
|
||||
#define FREE_RUN_TIMER_MAX_CNT 0xFFFFFFFFUL
|
||||
|
||||
#ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
|
||||
/*
|
||||
* One shot timer configurations
|
||||
*
|
||||
* NOTE: Timer1/2 register address isn't regular like timer3/4/5/6/7/8, and
|
||||
* timer1 is used for printing watchdog warning message. So now we use
|
||||
* timer2 only one shot to wake up chip and change pll.
|
||||
*/
|
||||
#define WDT_BASE DT_REG_ADDR(DT_NODELABEL(twd0))
|
||||
#define WDT_REG (struct wdt_it8xxx2_regs *)(WDT_BASE)
|
||||
#define ONE_SHOT_TIMER_IRQ DT_IRQ_BY_IDX(DT_NODELABEL(twd0), 1, irq)
|
||||
#define ONE_SHOT_TIMER_FLAG DT_IRQ_BY_IDX(DT_NODELABEL(twd0), 1, flags)
|
||||
#endif
|
||||
|
||||
#define MS_TO_COUNT(hz, ms) ((hz) * (ms) / 1000)
|
||||
/*
|
||||
* One system (kernel) tick is as how much HW timer counts
|
||||
*
|
||||
* NOTE: Event and free run timer individually select the same clock source
|
||||
* frequency, so they can use the same HW_CNT_PER_SYS_TICK to tranform
|
||||
* unit between HW count and system tick. If clock source frequency is
|
||||
* different, then we should define another to tranform.
|
||||
*/
|
||||
#define HW_CNT_PER_SYS_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \
|
||||
/ CONFIG_SYS_CLOCK_TICKS_PER_SEC)
|
||||
/* Event timer max count is as how much system (kernal) tick */
|
||||
#define EVEN_TIMER_MAX_CNT_SYS_TICK (EVENT_TIMER_MAX_CNT \
|
||||
/ HW_CNT_PER_SYS_TICK)
|
||||
|
||||
enum ext_clk_src_sel {
|
||||
EXT_PSR_32P768K = 0,
|
||||
EXT_PSR_1P024K,
|
||||
EXT_PSR_32,
|
||||
EXT_PSR_8M,
|
||||
};
|
||||
|
||||
/*
|
||||
* 24-bit timers: external timer 3, 5, and 7
|
||||
* 32-bit timers: external timer 4, 6, and 8
|
||||
*/
|
||||
enum ext_timer_idx {
|
||||
EXT_TIMER_3 = 0, /* Event timer */
|
||||
EXT_TIMER_4, /* Free run timer */
|
||||
EXT_TIMER_5,
|
||||
EXT_TIMER_6,
|
||||
EXT_TIMER_7,
|
||||
EXT_TIMER_8,
|
||||
};
|
||||
|
||||
static struct k_spinlock lock;
|
||||
/* Last HW count that we called sys_clock_announce() */
|
||||
static volatile uint32_t last_announced_hw_cnt;
|
||||
|
||||
#ifdef CONFIG_SOC_IT8XXX2_PLL_FLASH_48M
|
||||
#define TIMER_CHANGE_PLL EXT_TIMER_8
|
||||
static void timer_5ms_one_shot_isr(const void *unused)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
/*
|
||||
* We are here because we have completed changing PLL sequence.
|
||||
* Disabled the timer.
|
||||
* We are here because we have completed changing PLL sequence,
|
||||
* so disabled one shot timer interrupt.
|
||||
*/
|
||||
timer_init_ms(TIMER_CHANGE_PLL, ET_PSR_32K, 0, 0, 5);
|
||||
irq_disable(ONE_SHOT_TIMER_IRQ);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -223,52 +108,258 @@ static void timer_5ms_one_shot_isr(const void *unused)
|
|||
*/
|
||||
void timer_5ms_one_shot(void)
|
||||
{
|
||||
/* Initialize interrupt handler of external timer8. */
|
||||
IRQ_CONNECT(DT_IRQ_BY_IDX(DT_NODELABEL(timer), 8, irq),
|
||||
0, timer_5ms_one_shot_isr, NULL,
|
||||
DT_IRQ_BY_IDX(DT_NODELABEL(timer), 8, flags));
|
||||
/* enable 5ms timer with 32.768khz clock source */
|
||||
timer_init_ms(TIMER_CHANGE_PLL, ET_PSR_32K, 1, 1, 5);
|
||||
struct wdt_it8xxx2_regs *const timer2_reg = WDT_REG;
|
||||
uint32_t hw_cnt;
|
||||
|
||||
/* Initialize interrupt handler of one shot timer */
|
||||
IRQ_CONNECT(ONE_SHOT_TIMER_IRQ, 0, timer_5ms_one_shot_isr, NULL,
|
||||
ONE_SHOT_TIMER_FLAG);
|
||||
|
||||
/* Set rising edge triggered of one shot timer */
|
||||
ite_intc_irq_priority_set(ONE_SHOT_TIMER_IRQ, 0, ONE_SHOT_TIMER_FLAG);
|
||||
|
||||
/* Clear interrupt status of one shot timer */
|
||||
ite_intc_isr_clear(ONE_SHOT_TIMER_IRQ);
|
||||
|
||||
/* Set clock source of one shot timer */
|
||||
timer2_reg->ET2PSR = EXT_PSR_32P768K;
|
||||
|
||||
/*
|
||||
* Set count of one shot timer,
|
||||
* and after write ET2CNTLLR timer will start
|
||||
*/
|
||||
hw_cnt = MS_TO_COUNT(32768, 5/*ms*/);
|
||||
timer2_reg->ET2CNTLH2R = (uint8_t)((hw_cnt >> 16) & 0xff);
|
||||
timer2_reg->ET2CNTLHR = (uint8_t)((hw_cnt >> 8) & 0xff);
|
||||
timer2_reg->ET2CNTLLR = (uint8_t)(hw_cnt & 0xff);
|
||||
|
||||
irq_enable(ONE_SHOT_TIMER_IRQ);
|
||||
}
|
||||
#endif /* CONFIG_SOC_IT8XXX2_PLL_FLASH_48M */
|
||||
|
||||
int sys_clock_driver_init(const struct device *dev)
|
||||
static void evt_timer_isr(const void *unused)
|
||||
{
|
||||
timer_init_combine(CTIMER_HW_TIMER_INDEX, TRUE);
|
||||
timer_init(CTIMER_HW_TIMER_INDEX, ET_PSR_32K, TRUE, FALSE, 0);
|
||||
irq_connect_dynamic(DT_IRQ_BY_IDX(DT_NODELABEL(timer), 5, irq),
|
||||
0, timer_isr, NULL,
|
||||
DT_IRQ_BY_IDX(DT_NODELABEL(timer), 5, flags));
|
||||
timer_init_ms(ETIMER_HW_TIMER_INDEX, ET_PSR_32K, FALSE, TRUE, 0);
|
||||
return 0;
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
/* Disable event timer */
|
||||
IT8XXX2_EXT_CTRLX(EVENT_TIMER) &= ~IT8XXX2_EXT_ETXEN;
|
||||
/* W/C event timer interrupt status */
|
||||
ite_intc_isr_clear(EVENT_TIMER_IRQ);
|
||||
|
||||
if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
|
||||
/*
|
||||
* Get free run observer count from last time announced and
|
||||
* trnaform unit to system tick
|
||||
*/
|
||||
uint32_t dticks = (~(IT8XXX2_EXT_CNTOX(FREE_RUN_TIMER)) -
|
||||
last_announced_hw_cnt) / HW_CNT_PER_SYS_TICK;
|
||||
last_announced_hw_cnt += (dticks * HW_CNT_PER_SYS_TICK);
|
||||
|
||||
sys_clock_announce(dticks);
|
||||
} else {
|
||||
/* Enable and re-start event timer */
|
||||
IT8XXX2_EXT_CTRLX(EVENT_TIMER) |= (IT8XXX2_EXT_ETXEN |
|
||||
IT8XXX2_EXT_ETXRST);
|
||||
|
||||
/* Informs kernel that one system tick has elapsed */
|
||||
sys_clock_announce(1);
|
||||
}
|
||||
}
|
||||
|
||||
void sys_clock_set_timeout(int32_t ticks, bool idle)
|
||||
{
|
||||
uint32_t hw_cnt;
|
||||
|
||||
ARG_UNUSED(idle);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
|
||||
/* Always return for non-tickless kernel system */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Critical section */
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
|
||||
ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks;
|
||||
ticks = MAX(MIN(ticks, (int32_t)MAX_TICKS), 1);
|
||||
timer_count_reset(ETIMER_HW_TIMER_INDEX, ticks * CYC_PER_TICK);
|
||||
/* NOTE: To reduce cpu effort, we don't add critical section here */
|
||||
if (ticks == K_TICKS_FOREVER) {
|
||||
hw_cnt = EVENT_TIMER_MAX_CNT;
|
||||
} else if (ticks <= 1) {
|
||||
/*
|
||||
* Ticks <= 1 means the kernel wants the tick announced
|
||||
* as soon as possible, ideally no more than one system tick
|
||||
* in the future. So set event timer count to 1 system tick or
|
||||
* at least 1 hw count.
|
||||
*/
|
||||
hw_cnt = MAX((1 * HW_CNT_PER_SYS_TICK), 1);
|
||||
} else {
|
||||
if (ticks > EVEN_TIMER_MAX_CNT_SYS_TICK)
|
||||
/*
|
||||
* Set event timer count to EVENT_TIMER_MAX_CNT, after
|
||||
* interrupt fired the remaining time will be set again
|
||||
* by sys_clock_announce().
|
||||
*/
|
||||
hw_cnt = EVENT_TIMER_MAX_CNT;
|
||||
else
|
||||
/*
|
||||
* Set event timer count to system tick or at least
|
||||
* 1 hw count
|
||||
*/
|
||||
hw_cnt = MAX((ticks * HW_CNT_PER_SYS_TICK), 1);
|
||||
}
|
||||
|
||||
/* Set event timer 24-bit count */
|
||||
IT8XXX2_EXT_CNTX(EVENT_TIMER) = hw_cnt;
|
||||
|
||||
/* Enable and re-start event timer */
|
||||
IT8XXX2_EXT_CTRLX(EVENT_TIMER) |= (IT8XXX2_EXT_ETXEN |
|
||||
IT8XXX2_EXT_ETXRST);
|
||||
|
||||
/* W/C event timer interrupt status */
|
||||
ite_intc_isr_clear(EVENT_TIMER_IRQ);
|
||||
|
||||
k_spin_unlock(&lock, key);
|
||||
|
||||
LOG_DBG("timeout is 0x%x, set hw count 0x%x", ticks, hw_cnt);
|
||||
}
|
||||
|
||||
uint32_t sys_clock_elapsed(void)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
|
||||
/* Always return 0 for non-tickless kernel system */
|
||||
return 0;
|
||||
}
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
|
||||
uint32_t ret = (get_timer_combine_count(CTIMER_HW_TIMER_INDEX)
|
||||
- accumulated_cycle_count) / CYC_PER_TICK;
|
||||
/* Critical section */
|
||||
k_spinlock_key_t key = k_spin_lock(&lock);
|
||||
/*
|
||||
* Get free run observer count from last time announced and trnaform
|
||||
* unit to system tick
|
||||
*/
|
||||
uint32_t dticks = (~(IT8XXX2_EXT_CNTOX(FREE_RUN_TIMER)) -
|
||||
last_announced_hw_cnt) / HW_CNT_PER_SYS_TICK;
|
||||
k_spin_unlock(&lock, key);
|
||||
return ret;
|
||||
|
||||
return dticks;
|
||||
}
|
||||
|
||||
uint32_t sys_clock_cycle_get_32(void)
|
||||
{
|
||||
return get_timer_combine_count(CTIMER_HW_TIMER_INDEX);
|
||||
/*
|
||||
* Get free run observer count and trnaform unit to system tick
|
||||
*
|
||||
* NOTE: Timer is counting down from 0xffffffff. In not combined
|
||||
* mode, the observer count value is the same as count, so after
|
||||
* NOT count operation we can get counting up value; In
|
||||
* combined mode, the observer count value is the same as NOT
|
||||
* count operation.
|
||||
*/
|
||||
uint32_t dticks = (~(IT8XXX2_EXT_CNTOX(FREE_RUN_TIMER)))
|
||||
/ HW_CNT_PER_SYS_TICK;
|
||||
|
||||
return dticks;
|
||||
}
|
||||
|
||||
static int timer_init(enum ext_timer_idx ext_timer,
|
||||
enum ext_clk_src_sel clock_source_sel,
|
||||
uint32_t raw,
|
||||
uint32_t ms,
|
||||
uint8_t first_time_enable,
|
||||
uint32_t irq_num,
|
||||
uint32_t irq_flag,
|
||||
uint8_t with_int,
|
||||
uint8_t start)
|
||||
{
|
||||
uint32_t hw_cnt;
|
||||
|
||||
if (raw) {
|
||||
hw_cnt = ms;
|
||||
} else {
|
||||
if (clock_source_sel == EXT_PSR_32P768K)
|
||||
hw_cnt = MS_TO_COUNT(32768, ms);
|
||||
else if (clock_source_sel == EXT_PSR_1P024K)
|
||||
hw_cnt = MS_TO_COUNT(1024, ms);
|
||||
else if (clock_source_sel == EXT_PSR_32)
|
||||
hw_cnt = MS_TO_COUNT(32, ms);
|
||||
else if (clock_source_sel == EXT_PSR_8M)
|
||||
hw_cnt = 8000 * ms;
|
||||
else {
|
||||
LOG_ERR("Timer %d clock source error !", ext_timer);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hw_cnt == 0) {
|
||||
LOG_ERR("Timer %d count shouldn't be 0 !", ext_timer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (first_time_enable) {
|
||||
/* Enable and re-start external timer x */
|
||||
IT8XXX2_EXT_CTRLX(ext_timer) |= (IT8XXX2_EXT_ETXEN |
|
||||
IT8XXX2_EXT_ETXRST);
|
||||
/* Disable external timer x */
|
||||
IT8XXX2_EXT_CTRLX(ext_timer) &= ~IT8XXX2_EXT_ETXEN;
|
||||
}
|
||||
|
||||
/* Set rising edge triggered of external timer x */
|
||||
ite_intc_irq_priority_set(irq_num, 0, irq_flag);
|
||||
|
||||
/* Clear interrupt status of external timer x */
|
||||
ite_intc_isr_clear(irq_num);
|
||||
|
||||
/* Set clock source of external timer x */
|
||||
IT8XXX2_EXT_PSRX(ext_timer) = clock_source_sel;
|
||||
|
||||
/* Set count of external timer x */
|
||||
IT8XXX2_EXT_CNTX(ext_timer) = hw_cnt;
|
||||
|
||||
/* Disable external timer x */
|
||||
IT8XXX2_EXT_CTRLX(ext_timer) &= ~IT8XXX2_EXT_ETXEN;
|
||||
if (start)
|
||||
/* Enable and re-start external timer x */
|
||||
IT8XXX2_EXT_CTRLX(ext_timer) |= (IT8XXX2_EXT_ETXEN |
|
||||
IT8XXX2_EXT_ETXRST);
|
||||
|
||||
if (with_int)
|
||||
irq_enable(irq_num);
|
||||
else
|
||||
irq_disable(irq_num);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sys_clock_driver_init(const struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
/* Set 32-bit timer4 for free run*/
|
||||
ret = timer_init(FREE_RUN_TIMER, EXT_PSR_32P768K, TRUE,
|
||||
FREE_RUN_TIMER_MAX_CNT, TRUE, FREE_RUN_TIMER_IRQ,
|
||||
FREE_RUN_TIMER_FLAG, FALSE, TRUE);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Init free run timer failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set 24-bit timer3 for timeout event */
|
||||
IRQ_CONNECT(EVENT_TIMER_IRQ, 0, evt_timer_isr, NULL, EVENT_TIMER_FLAG);
|
||||
if (IS_ENABLED(CONFIG_TICKLESS_KERNEL)) {
|
||||
ret = timer_init(EVENT_TIMER, EXT_PSR_32P768K, TRUE,
|
||||
EVENT_TIMER_MAX_CNT, TRUE, EVENT_TIMER_IRQ,
|
||||
EVENT_TIMER_FLAG, TRUE, FALSE);
|
||||
} else {
|
||||
/* Start a event timer in one system tick */
|
||||
ret = timer_init(EVENT_TIMER, EXT_PSR_32P768K, TRUE,
|
||||
MAX((1 * HW_CNT_PER_SYS_TICK), 1), TRUE,
|
||||
EVENT_TIMER_IRQ, EVENT_TIMER_FLAG,
|
||||
TRUE, TRUE);
|
||||
}
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Init event timer failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -263,23 +263,21 @@
|
|||
compatible = "ite,it8xxx2-watchdog";
|
||||
reg = <0x00f01f00 0x0062>;
|
||||
label = "TWD_0";
|
||||
interrupts = <30 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupts = <IT8XXX2_IRQ_TIMER1 IRQ_TYPE_EDGE_RISING /* Warning timer */
|
||||
IT8XXX2_IRQ_TIMER2 IRQ_TYPE_EDGE_RISING>; /* One shot timer */
|
||||
interrupt-parent = <&intc>;
|
||||
};
|
||||
|
||||
timer: timer@f01f10 {
|
||||
compatible = "ite,it8xxx2-timer";
|
||||
reg = <0x00f01f00 0x0062>;
|
||||
label = "sys_clock";
|
||||
interrupts = <0 IRQ_TYPE_NONE
|
||||
30 IRQ_TYPE_EDGE_RISING
|
||||
58 IRQ_TYPE_EDGE_RISING
|
||||
155 IRQ_TYPE_EDGE_FALLING
|
||||
156 IRQ_TYPE_EDGE_FALLING
|
||||
157 IRQ_TYPE_EDGE_FALLING
|
||||
158 IRQ_TYPE_EDGE_FALLING
|
||||
159 IRQ_TYPE_EDGE_FALLING
|
||||
80 IRQ_TYPE_EDGE_RISING>;
|
||||
reg = <0x00f01f10 0x0052>;
|
||||
label = "TIMER";
|
||||
interrupts = <IT8XXX2_IRQ_TIMER3 IRQ_TYPE_EDGE_RISING /* Event timer */
|
||||
IT8XXX2_IRQ_TIMER4 IRQ_TYPE_EDGE_RISING /* Free run timer */
|
||||
IT8XXX2_IRQ_TIMER5 IRQ_TYPE_EDGE_RISING
|
||||
IT8XXX2_IRQ_TIMER6 IRQ_TYPE_EDGE_RISING
|
||||
IT8XXX2_IRQ_TIMER7 IRQ_TYPE_EDGE_RISING
|
||||
IT8XXX2_IRQ_TIMER8 IRQ_TYPE_EDGE_RISING>;
|
||||
interrupt-parent = <&intc>;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#define IT8XXX2_IRQ_WU24 17
|
||||
#define IT8XXX2_IRQ_WU22 21
|
||||
/* Group 3 */
|
||||
#define IT8XXX2_IRQ_TIMER1 30
|
||||
#define IT8XXX2_IRQ_WU21 31
|
||||
/* Group 5 */
|
||||
#define IT8XXX2_IRQ_WU50 40
|
||||
|
@ -43,6 +44,8 @@
|
|||
#define IT8XXX2_IRQ_WU65 53
|
||||
#define IT8XXX2_IRQ_WU66 54
|
||||
#define IT8XXX2_IRQ_WU67 55
|
||||
/* Group 7 */
|
||||
#define IT8XXX2_IRQ_TIMER2 58
|
||||
/* Group 9 */
|
||||
#define IT8XXX2_IRQ_WU70 72
|
||||
#define IT8XXX2_IRQ_WU71 73
|
||||
|
@ -53,6 +56,7 @@
|
|||
#define IT8XXX2_IRQ_WU76 78
|
||||
#define IT8XXX2_IRQ_WU77 79
|
||||
/* Group 10 */
|
||||
#define IT8XXX2_IRQ_TIMER8 80
|
||||
#define IT8XXX2_IRQ_WU88 85
|
||||
#define IT8XXX2_IRQ_WU89 86
|
||||
#define IT8XXX2_IRQ_WU90 87
|
||||
|
@ -124,6 +128,12 @@
|
|||
#define IT8XXX2_IRQ_WU124 145
|
||||
#define IT8XXX2_IRQ_WU125 146
|
||||
#define IT8XXX2_IRQ_WU126 147
|
||||
/* Group 19 */
|
||||
#define IT8XXX2_IRQ_TIMER3 155
|
||||
#define IT8XXX2_IRQ_TIMER4 156
|
||||
#define IT8XXX2_IRQ_TIMER5 157
|
||||
#define IT8XXX2_IRQ_TIMER6 158
|
||||
#define IT8XXX2_IRQ_TIMER7 159
|
||||
/* Group 20 */
|
||||
#define IT8XXX2_IRQ_USBPD0 165
|
||||
#define IT8XXX2_IRQ_USBPD1 166
|
||||
|
|
|
@ -1200,39 +1200,10 @@ struct wdt_it8xxx2_regs {
|
|||
#define IT8XXX2_WDT_ET1TC BIT(1)
|
||||
#define IT8XXX2_WDT_ET1RST BIT(0)
|
||||
|
||||
#define ET3CTRL ECREG(EC_REG_BASE_ADDR + 0x1F10)
|
||||
#define ET3PSR ECREG(EC_REG_BASE_ADDR + 0x1F11)
|
||||
#define ET3CNTLLR ECREG(EC_REG_BASE_ADDR + 0x1F14)
|
||||
#define ET3CNTLHR ECREG(EC_REG_BASE_ADDR + 0x1F15)
|
||||
#define ET3CNTLH2R ECREG(EC_REG_BASE_ADDR + 0x1F16)
|
||||
#define ET4CTRL ECREG(EC_REG_BASE_ADDR + 0x1F18)
|
||||
#define ET4PSR ECREG(EC_REG_BASE_ADDR + 0x1F19)
|
||||
#define ET4CNTLLR ECREG(EC_REG_BASE_ADDR + 0x1F1C)
|
||||
#define ET4CNTLHR ECREG(EC_REG_BASE_ADDR + 0x1F1D)
|
||||
#define ET4CNTLH2R ECREG(EC_REG_BASE_ADDR + 0x1F1E)
|
||||
#define ET4CNTLH3R ECREG(EC_REG_BASE_ADDR + 0x1F1F)
|
||||
#define ET5CTRL ECREG(EC_REG_BASE_ADDR + 0x1F20)
|
||||
#define ET5PSR ECREG(EC_REG_BASE_ADDR + 0x1F21)
|
||||
#define ET5CNTLLR ECREG(EC_REG_BASE_ADDR + 0x1F24)
|
||||
#define ET5CNTLHR ECREG(EC_REG_BASE_ADDR + 0x1F25)
|
||||
#define ET5CNTLH2R ECREG(EC_REG_BASE_ADDR + 0x1F26)
|
||||
#define ET6CTRL ECREG(EC_REG_BASE_ADDR + 0x1F28)
|
||||
#define ET6PSR ECREG(EC_REG_BASE_ADDR + 0x1F29)
|
||||
#define ET6CNTLLR ECREG(EC_REG_BASE_ADDR + 0x1F2C)
|
||||
#define ET6CNTLHR ECREG(EC_REG_BASE_ADDR + 0x1F2D)
|
||||
#define ET6CNTLH2R ECREG(EC_REG_BASE_ADDR + 0x1F2E)
|
||||
#define ET6CNTLH3R ECREG(EC_REG_BASE_ADDR + 0x1F2F)
|
||||
#define ET7CTRL ECREG(EC_REG_BASE_ADDR + 0x1F30)
|
||||
#define ET7PSR ECREG(EC_REG_BASE_ADDR + 0x1F31)
|
||||
#define ET7CNTLLR ECREG(EC_REG_BASE_ADDR + 0x1F34)
|
||||
#define ET7CNTLHR ECREG(EC_REG_BASE_ADDR + 0x1F35)
|
||||
#define ET7CNTLH2R ECREG(EC_REG_BASE_ADDR + 0x1F36)
|
||||
#define ET8CTRL ECREG(EC_REG_BASE_ADDR + 0x1F38)
|
||||
#define ET8PSR ECREG(EC_REG_BASE_ADDR + 0x1F39)
|
||||
#define ET8CNTLLR ECREG(EC_REG_BASE_ADDR + 0x1F3C)
|
||||
#define ET8CNTLHR ECREG(EC_REG_BASE_ADDR + 0x1F3D)
|
||||
#define ET8CNTLH2R ECREG(EC_REG_BASE_ADDR + 0x1F3E)
|
||||
#define ET8CNTLH3R ECREG(EC_REG_BASE_ADDR + 0x1F3F)
|
||||
/* External Timer register fields */
|
||||
/* External Timer 3~8 control */
|
||||
#define IT8XXX2_EXT_ETXRST BIT(1)
|
||||
#define IT8XXX2_EXT_ETXEN BIT(0)
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue