diff options
-rw-r--r-- | chip/ish/hpet.h | 11 | ||||
-rw-r--r-- | chip/ish/hwtimer.c | 80 | ||||
-rw-r--r-- | chip/ish/registers.h | 4 |
3 files changed, 53 insertions, 42 deletions
diff --git a/chip/ish/hpet.h b/chip/ish/hpet.h index c14df86ffb..dac5d95b9a 100644 --- a/chip/ish/hpet.h +++ b/chip/ish/hpet.h @@ -26,18 +26,21 @@ #define TIMER2_COMP_VAL_REG 0x148 #define TIMER2_FSB_IR_REG 0x150 +/* ISH 4: Special status register + * Use this register to see HPET timer are settled after a write. + */ #define CONTROL_AND_STATUS_REG 0x160 +#define HPET_T_CONF_CAP_BIT 0x4 #define HPET_ENABLE_CNF (1<<0) -#define HPET_LEGACY_RT_CNF (1<<1) -#define HPET_Tn_INT_TYPE_CNF (1<<1) +#define HPET_Tn_INT_TYPE_CNF (1<<1) #define HPET_Tn_INT_ENB_CNF (1<<2) #define HPET_Tn_TYPE_CNF (1<<3) +#define HPET_Tn_VAL_SET_CNF (1<<6) #define HPET_Tn_32MODE_CNF (1<<8) + #define HPET_Tn_INT_ROUTE_CNF_SHIFT 0x9 #define HPET_Tn_INT_ROUTE_CNF_MASK (0x1f << 9) -#define HPET_GEN_CONF_STATUS_BIT 0x8 -#define HPET_T0_CONF_CAP_BIT 0x4 #define HPET_GENERAL_CONFIG REG32(ISH_HPET_BASE + GENERAL_CONFIG_REG) #define HPET_MAIN_COUNTER REG32(ISH_HPET_BASE + MAIN_COUNTER_REG) diff --git a/chip/ish/hwtimer.c b/chip/ish/hwtimer.c index 13c07decd2..800b728fb7 100644 --- a/chip/ish/hwtimer.c +++ b/chip/ish/hwtimer.c @@ -5,6 +5,7 @@ /* Hardware timers driver - HPET */ +#include "console.h" #include "hpet.h" #include "hwtimer.h" #include "registers.h" @@ -14,15 +15,24 @@ #define CPRINTS(format, args...) cprints(CC_CLOCK, format, ## args) #define CPRINTF(format, args...) cprintf(CC_CLOCK, format, ## args) +static uint32_t last_deadline; + +/* TODO: Conform to EC API + * ISH supports 32KHz and 12MHz clock sources. + * EC expects timer value in 1MHz. + * Scale the values and support it. + */ + void __hw_clock_event_set(uint32_t deadline) { - HPET_TIMER_COMP(1) = HPET_MAIN_COUNTER + deadline; + last_deadline = deadline; + HPET_TIMER_COMP(1) = deadline; HPET_TIMER_CONF_CAP(1) |= HPET_Tn_INT_ENB_CNF; } uint32_t __hw_clock_event_get(void) { - return 0; + return last_deadline; } void __hw_clock_event_clear(void) @@ -38,11 +48,7 @@ uint32_t __hw_clock_source_read(void) void __hw_clock_source_set(uint32_t ts) { HPET_GENERAL_CONFIG &= ~HPET_ENABLE_CNF; - HPET_MAIN_COUNTER = 0x00; - - while (HPET_CTRL_STATUS & HPET_GEN_CONF_STATUS_BIT) - ; - + HPET_MAIN_COUNTER = ts; HPET_GENERAL_CONFIG |= HPET_ENABLE_CNF; } @@ -77,53 +83,55 @@ int __hw_clock_source_init(uint32_t start_t) * - Timer 1 as event timer */ + uint32_t timer0_config = 0x00000000; + uint32_t timer1_config = 0x00000000; + /* Disable HPET */ HPET_GENERAL_CONFIG &= ~HPET_ENABLE_CNF; - HPET_MAIN_COUNTER = 0x00; + HPET_MAIN_COUNTER = start_t; /* Set comparator value */ - HPET_TIMER_COMP(0) = ISH_HPET_CLK_FREQ / ISH_TICKS_PER_SEC; - - /* Wait for timer to settle */ - while (HPET_CTRL_STATUS & HPET_GEN_CONF_STATUS_BIT) - ; + HPET_TIMER_COMP(0) = 0XFFFFFFFF; /* Timer 0 - enable periodic mode */ - HPET_TIMER_CONF_CAP(0) |= HPET_Tn_TYPE_CNF; - HPET_TIMER_CONF_CAP(0) |= HPET_Tn_32MODE_CNF; + timer0_config |= HPET_Tn_TYPE_CNF; + timer0_config |= HPET_Tn_32MODE_CNF; + timer0_config |= HPET_Tn_VAL_SET_CNF; - while (HPET_CTRL_STATUS & HPET_T0_CONF_CAP_BIT) - ; + /* Timer 0 - IRQ routing */ + timer0_config &= ~HPET_Tn_INT_ROUTE_CNF_MASK; + timer0_config |= (ISH_HPET_TIMER0_IRQ << + HPET_Tn_INT_ROUTE_CNF_SHIFT); - /* Set IRQ routing */ -#if ISH_HPET_TIMER0_IRQ < 32 - HPET_TIMER_CONF_CAP(0) &= ~HPET_Tn_INT_ROUTE_CNF_MASK; - HPET_TIMER_CONF_CAP(0) |= (ISH_HPET_TIMER0_IRQ << - HPET_Tn_INT_ROUTE_CNF_SHIFT); -#else - HPET_TIMER_CONF_CAP(0) &= ~HPET_Tn_INT_ROUTE_CNF_MASK; -#endif + /* Timer 1 - IRQ routing */ + timer1_config &= ~HPET_Tn_INT_ROUTE_CNF_MASK; + timer1_config |= (ISH_HPET_TIMER1_IRQ << + HPET_Tn_INT_ROUTE_CNF_SHIFT); - while (HPET_CTRL_STATUS & HPET_T0_CONF_CAP_BIT) - ; + /* Level triggered interrupt */ + timer0_config |= HPET_Tn_INT_TYPE_CNF; + timer1_config |= HPET_Tn_INT_TYPE_CNF; - /* Level interrupt */ - HPET_TIMER_CONF_CAP(0) |= HPET_Tn_INT_TYPE_CNF; - HPET_TIMER_CONF_CAP(1) |= HPET_Tn_INT_TYPE_CNF; + /* Enable interrupt */ + timer0_config |= HPET_Tn_INT_ENB_CNF; + timer1_config |= HPET_Tn_INT_ENB_CNF; /* Unask HPET IRQ in IOAPIC */ task_enable_irq(ISH_HPET_TIMER0_IRQ); task_enable_irq(ISH_HPET_TIMER1_IRQ); - /* Enable interrupt */ - HPET_TIMER_CONF_CAP(0) |= HPET_Tn_INT_ENB_CNF; - HPET_TIMER_CONF_CAP(1) |= HPET_Tn_INT_ENB_CNF; + /* Set timer 0/1 config */ + HPET_TIMER_CONF_CAP(0) |= timer0_config; + HPET_TIMER_CONF_CAP(1) |= timer1_config; - while (HPET_CTRL_STATUS & HPET_T0_CONF_CAP_BIT) +#if defined CONFIG_ISH_40 + /* Wait for timer to settle. required for ISH 4 */ + while (HPET_CTRL_STATUS & HPET_T_CONF_CAP_BIT) ; +#endif - /* Enable HPET main counter */ + /* Enable HPET main counter */ HPET_GENERAL_CONFIG |= HPET_ENABLE_CNF; - return ISH_HPET_TIMER1_IRQ; /* One shot */ + return ISH_HPET_TIMER1_IRQ; } diff --git a/chip/ish/registers.h b/chip/ish/registers.h index f92770ddbd..32239d3975 100644 --- a/chip/ish/registers.h +++ b/chip/ish/registers.h @@ -39,14 +39,14 @@ enum ish_i2c_port { /* HW interrupt pins mapped to IOAPIC, from I/O sources */ #define ISH_I2C0_IRQ 0 #define ISH_I2C1_IRQ 1 -#define ISH_HPET_TIMER1_IRQ 8 +#define ISH_HPET_TIMER0_IRQ 22 +#define ISH_HPET_TIMER1_IRQ 23 #define ISH_HPET_TIMER2_IRQ 11 #define ISH_IPC_HOST2ISH_IRQ 12 #define ISH_IPC_ISH2HOST_CLR_IRQ 24 #define ISH_UART0_IRQ 34 #define ISH_UART1_IRQ 35 #define ISH_I2C2_IRQ 40 -#define ISH_HPET_TIMER0_IRQ 55 /* Interrupt vectors 0-31 are architecture reserved. * Vectors 32-255 are user-defined. |