From bfb63f801707e281317789c1a63ce745d5bae6e2 Mon Sep 17 00:00:00 2001 From: Cástor Muñoz Date: Mon, 1 Dec 2014 02:33:41 +0100 Subject: iPod Classic: minor modifications in TIMER The current behaviour should not change. Change-Id: Ia8f44cdccf41dbc3881722f9aebab91de51a9bc5 --- firmware/target/arm/s5l8702/kernel-s5l8702.c | 11 ++++------ firmware/target/arm/s5l8702/system-s5l8702.c | 3 ++- firmware/target/arm/s5l8702/timer-s5l8702.c | 33 +++++++++++++++------------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/firmware/target/arm/s5l8702/kernel-s5l8702.c b/firmware/target/arm/s5l8702/kernel-s5l8702.c index b39b384696..6a70981c93 100644 --- a/firmware/target/arm/s5l8702/kernel-s5l8702.c +++ b/firmware/target/arm/s5l8702/kernel-s5l8702.c @@ -39,19 +39,16 @@ void tick_start(unsigned int interval_in_ms) { int cycles = 10 * interval_in_ms; - /* configure timer for 10 kHz (external source) */ + /* configure timer for 10 kHz (12 MHz / 16 / 75) */ TBCMD = (1 << 1); /* TB_CLR */ - TBPRE = 75 - 1; /* prescaler */ /* 12 MHz / 16 / 75 = 10 KHz */ + TBPRE = 75 - 1; /* prescaler */ TBCON = (0 << 13) | /* TB_INT1_EN */ (1 << 12) | /* TB_INT0_EN */ (0 << 11) | /* TB_START */ - (2 << 8) | /* TB_CS = PCLK / 16 */ - (1 << 6) | /* UNKNOWN bit */ /* external 12 MHz clock (?) */ + (2 << 8) | /* TB_CS = ECLK / 16 */ + (1 << 6) | /* select ECLK (12 MHz) */ (0 << 4); /* TB_MODE_SEL = interval mode */ TBDATA0 = cycles; /* set interval period */ TBCMD = (1 << 0); /* TB_EN */ - - /* enable timer interrupt */ - VIC0INTENABLE = 1 << IRQ_TIMER; } diff --git a/firmware/target/arm/s5l8702/system-s5l8702.c b/firmware/target/arm/s5l8702/system-s5l8702.c index 09aff3d84e..5b03f3bc5c 100644 --- a/firmware/target/arm/s5l8702/system-s5l8702.c +++ b/firmware/target/arm/s5l8702/system-s5l8702.c @@ -134,7 +134,7 @@ void INT_TIMER32(void) ICODE_ATTR; void INT_TIMER32() { uint32_t tstat = TSTAT; - /*if ((TECON >> 12) & 0x7 & (tstat >> 24)) INT_TIMERE();*/ + if ((TECON >> 12) & 0x7 & (tstat >> 24)) INT_TIMERE(); if ((TFCON >> 12) & 0x7 & (tstat >> 16)) INT_TIMERF(); if ((TGCON >> 12) & 0x7 & (tstat >> 8)) INT_TIMERG(); if ((THCON >> 12) & 0x7 & tstat) INT_TIMERH(); @@ -226,6 +226,7 @@ void system_init(void) VIC0INTENABLE = 1 << IRQ_WHEEL; VIC0INTENABLE = 1 << IRQ_ATA; VIC1INTENABLE = 1 << (IRQ_MMC - 32); + VIC0INTENABLE = 1 << IRQ_TIMER; VIC0INTENABLE = 1 << IRQ_TIMER32; } diff --git a/firmware/target/arm/s5l8702/timer-s5l8702.c b/firmware/target/arm/s5l8702/timer-s5l8702.c index 7c69ab123a..5b145ed7e3 100644 --- a/firmware/target/arm/s5l8702/timer-s5l8702.c +++ b/firmware/target/arm/s5l8702/timer-s5l8702.c @@ -38,8 +38,10 @@ void INT_TIMERF(void) bool timer_set(long cycles, bool start) { + int tf_en = TFCMD & (1 << 0); /* save TF_EN status */ + /* stop timer */ - TFCMD = (0 << 0); /* TF_ENABLE */ + TFCMD = (0 << 0); /* TF_EN = disable */ /* optionally unregister any previously registered timer user */ if (start) { @@ -49,33 +51,34 @@ bool timer_set(long cycles, bool start) } } - /* There is an odd behaviour when the 32-bit timers are launched - for the first time, the interrupt status bits are set and an - unexpected interrupt is generated if they are enabled. A way to - workaround this is to write the data registers before clearing - the counter. */ - TFDATA0 = cycles; - TFCMD = (1 << 1); /* TF_CLR */ - /* configure timer */ TFCON = (1 << 12) | /* TF_INT0_EN */ - (4 << 8) | /* TF_CS, 4 = ECLK / 1 */ - (1 << 6) | /* use ECLK (12MHz) */ - (0 << 4); /* TF_MODE_SEL, 0 = interval mode */ + (4 << 8) | /* TF_CS = ECLK / 1 */ + (1 << 6) | /* select ECLK (12 MHz) */ + (0 << 4); /* TF_MODE_SEL = interval mode */ TFPRE = 0; /* no prescaler */ + TFDATA0 = cycles; /* set interval period */ - TFCMD = (1 << 0); /* TF_ENABLE */ + /* After the configuration, we must write '1' in TF_CLR to + * initialize the timer (s5l8700 DS): + * - Clear the counter register. + * - The value of TF_START is set to TF_OUT. + * - TF_DATA0 and TF_DATA1 are updated to the internal buffers. + * - Initialize the state of the previously captured signal. + */ + TFCMD = (1 << 1) | /* TF_CLR = initialize timer */ + (tf_en << 0); /* TF_EN = restore previous status */ return true; } bool timer_start(void) { - TFCMD = (1 << 0); /* TF_ENABLE */ + TFCMD = (1 << 0); /* TF_EN = enable */ return true; } void timer_stop(void) { - TFCMD = (0 << 0); /* TF_ENABLE */ + TFCMD = (0 << 0); /* TF_EN = disable */ } -- cgit v1.2.3