stm32: switch 32-bit timer to use TIM3/4

Chain TIM3/4 as the 32-bit timer instead of TIM2/3. This frees
up TIM2 to be used for other purposes.

BUG=chrome-os-partner:10647
TEST=Flashed onto Snow, stuff works and timerinfo output is sane

Signed-off-by: David Hendricks <dhendrix@chromium.org>

Change-Id: Icdfe3596a15bc2ee8536f160b1f08ac3041b9193
Reviewed-on: https://gerrit.chromium.org/gerrit/26202
Commit-Ready: David Hendricks <dhendrix@chromium.org>
Tested-by: David Hendricks <dhendrix@chromium.org>
Reviewed-by: David Hendricks <dhendrix@chromium.org>
This commit is contained in:
David Hendricks
2012-06-26 20:32:37 -07:00
committed by Gerrit
parent 3c3319df8b
commit 6900449d0c

View File

@@ -24,26 +24,26 @@ void __hw_clock_event_set(uint32_t deadline)
{
last_deadline = deadline;
if ((deadline >> 16) == STM32_TIM_CNT(2)) {
if ((deadline >> 16) == STM32_TIM_CNT(3)) {
/* we can set a match on the LSB only */
STM32_TIM_CCR1(3) = deadline & 0xffff;
STM32_TIM_CCR1(4) = deadline & 0xffff;
/* disable MSB match */
STM32_TIM_DIER(2) &= ~2;
/* Clear the match flags */
STM32_TIM_SR(2) = ~2;
STM32_TIM_SR(3) = ~2;
/* Set the match interrupt */
STM32_TIM_DIER(3) |= 2;
} else if ((deadline >> 16) > STM32_TIM_CNT(2)) {
/* first set a match on the MSB */
STM32_TIM_CCR1(2) = deadline >> 16;
/* disable LSB match */
STM32_TIM_DIER(3) &= ~2;
/* Clear the match flags */
STM32_TIM_SR(2) = ~2;
STM32_TIM_SR(3) = ~2;
STM32_TIM_SR(4) = ~2;
/* Set the match interrupt */
STM32_TIM_DIER(2) |= 2;
STM32_TIM_DIER(4) |= 2;
} else if ((deadline >> 16) > STM32_TIM_CNT(3)) {
/* first set a match on the MSB */
STM32_TIM_CCR1(3) = deadline >> 16;
/* disable LSB match */
STM32_TIM_DIER(4) &= ~2;
/* Clear the match flags */
STM32_TIM_SR(3) = ~2;
STM32_TIM_SR(4) = ~2;
/* Set the match interrupt */
STM32_TIM_DIER(3) |= 2;
}
}
@@ -55,8 +55,8 @@ uint32_t __hw_clock_event_get(void)
void __hw_clock_event_clear(void)
{
/* Disable the match interrupts */
STM32_TIM_DIER(4) &= ~2;
STM32_TIM_DIER(3) &= ~2;
STM32_TIM_DIER(2) &= ~2;
}
uint32_t __hw_clock_source_read(void)
@@ -66,82 +66,82 @@ uint32_t __hw_clock_source_read(void)
/* ensure the two half-words are coherent */
do {
hi = STM32_TIM_CNT(2);
lo = STM32_TIM_CNT(3);
} while (hi != STM32_TIM_CNT(2));
hi = STM32_TIM_CNT(3);
lo = STM32_TIM_CNT(4);
} while (hi != STM32_TIM_CNT(3));
return (hi << 16) | lo;
}
static void __hw_clock_source_irq(void)
{
uint32_t stat_tim2 = STM32_TIM_SR(2);
uint32_t stat_tim3 = STM32_TIM_SR(3);
/* clear status */
STM32_TIM_SR(4) = 0;
STM32_TIM_SR(3) = 0;
STM32_TIM_SR(2) = 0;
/*
* Find expired timers and set the new timer deadline
* signal overflow if the 16-bit MSB counter has overflowed.
*/
process_timers(stat_tim2 & 0x01);
process_timers(stat_tim3 & 0x01);
}
DECLARE_IRQ(STM32_IRQ_TIM2, __hw_clock_source_irq, 1);
DECLARE_IRQ(STM32_IRQ_TIM3, __hw_clock_source_irq, 1);
DECLARE_IRQ(STM32_IRQ_TIM4, __hw_clock_source_irq, 1);
int __hw_clock_source_init(uint32_t start_t)
{
/*
* we use 2 chained 16-bit counters to emulate a 32-bit one :
* TIM2 is the MSB (Slave)
* TIM3 is the LSB (Master)
* TIM3 is the MSB (Slave)
* TIM4 is the LSB (Master)
*/
/* Enable TIM2 and TIM3 clocks */
STM32_RCC_APB1ENR |= 0x3;
/* Enable TIM3 and TIM4 clocks */
STM32_RCC_APB1ENR |= 0x6;
/*
* Timer configuration : Upcounter, counter disabled, update event only
* on overflow.
*/
STM32_TIM_CR1(2) = 0x0004;
STM32_TIM_CR1(3) = 0x0004;
/* TIM3 (master mode) generates a periodic trigger signal on each UEV */
STM32_TIM_CR2(2) = 0x0000;
STM32_TIM_CR2(3) = 0x0020;
/* TIM2 (slave mode) uses ITR2 as internal trigger */
STM32_TIM_SMCR(2) = 0x0027;
STM32_TIM_SMCR(3) = 0x0000;
STM32_TIM_CR1(4) = 0x0004;
/* TIM4 (master mode) generates a periodic trigger signal on each UEV */
STM32_TIM_CR2(3) = 0x0000;
STM32_TIM_CR2(4) = 0x0020;
/* TIM3 (slave mode) uses ITR3 as internal trigger */
STM32_TIM_SMCR(3) = 0x0037;
STM32_TIM_SMCR(4) = 0x0000;
/* Auto-reload value : 16-bit free-running counters */
STM32_TIM_ARR(2) = 0xffff;
STM32_TIM_ARR(3) = 0xffff;
STM32_TIM_ARR(4) = 0xffff;
/* Pre-scaler value :
* TIM3 is counting microseconds, TIM2 is counting every TIM3 overflow.
* TIM4 is counting microseconds, TIM3 is counting every TIM4 overflow.
*/
STM32_TIM_PSC(2) = 0;
STM32_TIM_PSC(3) = CLOCKSOURCE_DIVIDER - 1;
STM32_TIM_PSC(3) = 0;
STM32_TIM_PSC(4) = CLOCKSOURCE_DIVIDER - 1;
/* Reload the pre-scaler */
STM32_TIM_EGR(2) = 0x0000;
STM32_TIM_EGR(3) = 0x0000;
STM32_TIM_EGR(4) = 0x0000;
/* setup the overflow interrupt on TIM2 */
STM32_TIM_DIER(2) = 0x0001;
STM32_TIM_DIER(3) = 0x0000;
/* setup the overflow interrupt on TIM3 */
STM32_TIM_DIER(3) = 0x0001;
STM32_TIM_DIER(4) = 0x0000;
/* Start counting */
STM32_TIM_CR1(2) |= 1;
STM32_TIM_CR1(3) |= 1;
STM32_TIM_CR1(4) |= 1;
/* Override the count with the start value now that counting has
* started. */
STM32_TIM_CNT(2) = start_t >> 16;
STM32_TIM_CNT(3) = start_t & 0xffff;
STM32_TIM_CNT(3) = start_t >> 16;
STM32_TIM_CNT(4) = start_t & 0xffff;
/* Enable timer interrupts */
task_enable_irq(STM32_IRQ_TIM2);
task_enable_irq(STM32_IRQ_TIM3);
task_enable_irq(STM32_IRQ_TIM4);
return STM32_IRQ_TIM3;
return STM32_IRQ_TIM4;
}