it83xx: fix observation register latch issue for event timer

Adding fix of event timer for CL:358730.

Signed-off-by: Dino Li <dino.li@ite.com.tw>

BRANCH=none
BUG=chrome-os-partner:55044
TEST=We simulate the delay time between first and second read,
     and prove this method can avoid latch fail.

Change-Id: I82cd4ce470ffc9a8262d9303e3fd390812c89cac
Reviewed-on: https://chromium-review.googlesource.com/380349
Commit-Ready: Dino Li <Dino.Li@ite.com.tw>
Tested-by: Dino Li <Dino.Li@ite.com.tw>
Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
This commit is contained in:
Dino Li
2016-09-02 11:52:38 +08:00
committed by chrome-bot
parent c8548f6405
commit edb727f8a3
3 changed files with 54 additions and 31 deletions

View File

@@ -310,7 +310,12 @@ static void clock_htimer_enable(void)
uint32_t c;
/* change event timer clock source to 32.768 KHz */
#if 0
c = TIMER_CNT_8M_32P768K(IT83XX_ETWD_ETXCNTOR(EVENT_EXT_TIMER));
#else
/* TODO(crosbug.com/p/55044) */
c = TIMER_CNT_8M_32P768K(ext_observation_reg_read(EVENT_EXT_TIMER));
#endif
clock_event_timer_clock_change(EXT_PSR_32P768K_HZ, c);
}
@@ -323,7 +328,12 @@ static int clock_allow_low_power_idle(void)
et_ctrl_regs[EVENT_EXT_TIMER].mask)
return 0;
#if 0
if (EVENT_TIMER_COUNT_TO_US(IT83XX_ETWD_ETXCNTOR(EVENT_EXT_TIMER)) <
#else
/* TODO(crosbug.com/p/55044) */
if (EVENT_TIMER_COUNT_TO_US(ext_observation_reg_read(EVENT_EXT_TIMER)) <
#endif
SLEEP_SET_HTIMER_DELAY_USEC)
return 0;

View File

@@ -105,37 +105,8 @@ uint32_t __ram_code __hw_clock_source_read(void)
*/
return IT83XX_ETWD_ETXCNTOR(FREE_EXT_TIMER_H);
#else
/* Number of CPU cycles in 125 us */
#define CYCLES_125NS (125*(PLL_CLOCK/SECOND) / 1000)
/*
* TODO(crosbug.com/p/55044):
* observation register of external timer latch issue.
* we can remove this workaround after version change.
*/
uint32_t prev_mask = get_int_mask();
uint32_t val;
interrupt_disable();
asm volatile(
/* read observation register for the first time */
"lwi %0,[%1]\n\t"
/*
* the delay time between reading the first and second
* observation registers need to be greater than 0.125us and
* smaller than 0.250us.
*/
".rept %2\n\t"
"nop\n\t"
".endr\n\t"
/* read for the second time */
"lwi %0,[%1]\n\t"
: "=&r"(val)
: "r"((uintptr_t) &IT83XX_ETWD_ETXCNTOR(FREE_EXT_TIMER_H)),
"i"(CYCLES_125NS));
/* restore interrupts */
set_int_mask(prev_mask);
return val;
/* TODO(crosbug.com/p/55044) */
return ext_observation_reg_read(FREE_EXT_TIMER_H);
#endif
}
@@ -172,7 +143,12 @@ uint32_t __hw_clock_event_get(void)
if (IT83XX_ETWD_ETXCTRL(EVENT_EXT_TIMER) & (1 << 0)) {
/* timer counter observation value to microseconds */
next_event_us += EVENT_TIMER_COUNT_TO_US(
#if 0
IT83XX_ETWD_ETXCNTOR(EVENT_EXT_TIMER));
#else
/* TODO(crosbug.com/p/55044) */
ext_observation_reg_read(EVENT_EXT_TIMER));
#endif
}
return next_event_us;
}
@@ -249,6 +225,41 @@ static void __hw_clock_source_irq(void)
}
DECLARE_IRQ(CPU_INT_GROUP_3, __hw_clock_source_irq, 1);
/*
* TODO(crosbug.com/p/55044):
* observation register of external timer latch issue.
* we can remove this workaround after version change.
*/
/* Number of CPU cycles in 125 us */
#define CYCLES_125NS (125*(PLL_CLOCK/SECOND) / 1000)
uint32_t __ram_code ext_observation_reg_read(enum ext_timer_sel ext_timer)
{
uint32_t prev_mask = get_int_mask();
uint32_t val;
interrupt_disable();
asm volatile(
/* read observation register for the first time */
"lwi %0,[%1]\n\t"
/*
* the delay time between reading the first and second
* observation registers need to be greater than 0.125us and
* smaller than 0.250us.
*/
".rept %2\n\t"
"nop\n\t"
".endr\n\t"
/* read for the second time */
"lwi %0,[%1]\n\t"
: "=&r"(val)
: "r"((uintptr_t) &IT83XX_ETWD_ETXCNTOR(ext_timer)),
"i"(CYCLES_125NS));
/* restore interrupts */
set_int_mask(prev_mask);
return val;
}
void ext_timer_start(enum ext_timer_sel ext_timer, int en_irq)
{
/* enable external timer n */

View File

@@ -57,6 +57,8 @@ struct ext_timer_ctrl_t {
};
extern const struct ext_timer_ctrl_t et_ctrl_regs[];
/* TODO(crosbug.com/p/55044) */
uint32_t __ram_code ext_observation_reg_read(enum ext_timer_sel ext_timer);
void ext_timer_start(enum ext_timer_sel ext_timer, int en_irq);
void ext_timer_stop(enum ext_timer_sel ext_timer, int dis_irq);
void fan_ext_timer_interrupt(void);