simio_timer: implement TAIV register.

This commit is contained in:
Sean Burford 2012-07-20 09:20:37 +12:00 committed by Daniel Beer
parent 65d15ef680
commit ad6c39a0aa
1 changed files with 25 additions and 5 deletions

View File

@ -244,16 +244,24 @@ static int timer_config(struct simio_device *dev,
return -1; return -1;
} }
static uint16_t calc_iv(struct timer *tr) static uint16_t calc_iv(struct timer *tr, int update)
{ {
int i; int i;
for (i = 0; i < tr->size; i++) for (i = 0; i < tr->size; i++)
if ((tr->ctls[i] & (CCIE | CCIFG)) == (CCIE | CCIFG)) if ((tr->ctls[i] & (CCIE | CCIFG)) == (CCIE | CCIFG)) {
/* Reading or writing TAIV clears the highest flag.
TACCR0 is cleared in timer_ack_interrupt(). */
if (update && (i > 0))
tr->ctls[i] &= ~CCIFG;
return i * 2; return i * 2;
}
if ((tr->tactl & (TAIFG | TAIE)) == (TAIFG | TAIE)) if ((tr->tactl & (TAIFG | TAIE)) == (TAIFG | TAIE)) {
if (update)
tr->tactl &= ~TAIFG;
return 0xa; return 0xa;
}
return 0; return 0;
} }
@ -270,7 +278,7 @@ static int timer_info(struct simio_device *dev)
printc("\n"); printc("\n");
printc("TACTL: 0x%04x\n", tr->tactl); printc("TACTL: 0x%04x\n", tr->tactl);
printc("TAR: 0x%04x\n", tr->tar); printc("TAR: 0x%04x\n", tr->tar);
printc("TAIV: 0x%02x\n", calc_iv(tr)); printc("TAIV: 0x%02x\n", calc_iv(tr, 0));
printc("\n"); printc("\n");
for (i = 0; i < tr->size; i++) for (i = 0; i < tr->size; i++)
@ -315,6 +323,12 @@ static int timer_write(struct simio_device *dev,
return 0; return 0;
} }
if (addr == tr->iv_addr) {
/* Writing to TAIV clears the highest priority bit. */
calc_iv(tr, 1);
return 0;
}
return 1; return 1;
} }
@ -335,7 +349,7 @@ static int timer_read(struct simio_device *dev,
if (addr >= tr->base_addr + 2 && if (addr >= tr->base_addr + 2 &&
addr < tr->base_addr + tr->size + 2) { addr < tr->base_addr + tr->size + 2) {
*data = tr->ctls[((addr - 0xf) - 2) >> 1]; *data = tr->ctls[((addr & 0xf) - 2) >> 1];
return 0; return 0;
} }
@ -345,6 +359,11 @@ static int timer_read(struct simio_device *dev,
return 0; return 0;
} }
if (addr == tr->iv_addr) {
*data = calc_iv(tr, 1);
return 0;
}
return 1; return 1;
} }
@ -372,6 +391,7 @@ static void timer_ack_interrupt(struct simio_device *dev, int irq)
if (irq == tr->irq0) if (irq == tr->irq0)
tr->ctls[0] &= ~CCIFG; tr->ctls[0] &= ~CCIFG;
/* By design irq1 does not clear CCIFG or TAIFG automatically */
} }
static void tar_step(struct timer *tr) static void tar_step(struct timer *tr)