1
0
mirror of https://git.FreeBSD.org/src.git synced 2025-02-05 18:05:16 +00:00

Eliminate unnecessary read/modify/write sequences during eventtimer setup.

It turns out to be surprisingly expensive to access the gpt hardware (on the
order of 150ns per read/write).  To cut down on the overhead of setting up
each eventtimer event, eliminate read-modify-write sequences to manage the
compare interrupt enable, by keeping a shadow copy of the hardware register
and only writing to the hardware when the enable bits really change.
This commit is contained in:
Ian Lepore 2017-03-19 21:28:37 +00:00
parent 133cbe3b59
commit 5e52290fda
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=315589

View File

@ -83,6 +83,7 @@ struct imx_gpt_softc {
uint32_t sc_period;
uint32_t sc_clksrc;
uint32_t clkfreq;
uint32_t ir_reg;
struct eventtimer et;
};
@ -284,16 +285,20 @@ imx_gpt_timer_start(struct eventtimer *et, sbintime_t first, sbintime_t period)
/* Set expected value */
WRITE4(sc, IMX_GPT_OCR2, READ4(sc, IMX_GPT_CNT) + sc->sc_period);
/* Enable compare register 2 Interrupt */
SET4(sc, IMX_GPT_IR, GPT_IR_OF2);
sc->ir_reg |= GPT_IR_OF2;
WRITE4(sc, IMX_GPT_IR, sc->ir_reg);
return (0);
} else if (first != 0) {
/* Enable compare register 3 interrupt if not already on. */
if ((sc->ir_reg & GPT_IR_OF3) == 0) {
sc->ir_reg |= GPT_IR_OF3;
WRITE4(sc, IMX_GPT_IR, sc->ir_reg);
}
ticks = ((uint32_t)et->et_frequency * first) >> 32;
/* Do not disturb, otherwise event will be lost */
spinlock_enter();
/* Set expected value */
WRITE4(sc, IMX_GPT_OCR3, READ4(sc, IMX_GPT_CNT) + ticks);
/* Enable compare register 1 Interrupt */
SET4(sc, IMX_GPT_IR, GPT_IR_OF3);
/* Now everybody can relax */
spinlock_exit();
return (0);
@ -309,9 +314,10 @@ imx_gpt_timer_stop(struct eventtimer *et)
sc = (struct imx_gpt_softc *)et->et_priv;
/* Disable OF2 Interrupt */
CLEAR4(sc, IMX_GPT_IR, GPT_IR_OF2);
WRITE4(sc, IMX_GPT_SR, GPT_IR_OF2);
/* Disable interrupts and clear any pending status. */
sc->ir_reg &= ~(GPT_IR_OF2 | GPT_IR_OF3);
WRITE4(sc, IMX_GPT_IR, sc->ir_reg);
WRITE4(sc, IMX_GPT_SR, GPT_IR_OF2 | GPT_IR_OF3);
sc->sc_period = 0;
return (0);