diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c index 010ccbf207c7b75b869c14cbf93d816280dd505b..4b9b54bf2ee24c135067a47de20f273625957286 100644 --- a/hw/timer/imx_gpt.c +++ b/hw/timer/imx_gpt.c @@ -296,18 +296,23 @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size) return reg_value; } -static void imx_gpt_reset(DeviceState *dev) -{ - IMXGPTState *s = IMX_GPT(dev); +static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset) +{ /* stop timer */ ptimer_stop(s->timer); - /* - * Soft reset doesn't touch some bits; hard reset clears them + /* Soft reset and hard reset differ only in their handling of the CR + * register -- soft reset preserves the values of some bits there. */ - s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN| - GPT_CR_WAITEN|GPT_CR_DBGEN); + if (is_soft_reset) { + /* Clear all CR bits except those that are preserved by soft reset. */ + s->cr &= GPT_CR_EN | GPT_CR_ENMOD | GPT_CR_STOPEN | GPT_CR_DOZEN | + GPT_CR_WAITEN | GPT_CR_DBGEN | + (GPT_CR_CLKSRC_MASK << GPT_CR_CLKSRC_SHIFT); + } else { + s->cr = 0; + } s->sr = 0; s->pr = 0; s->ir = 0; @@ -333,6 +338,18 @@ static void imx_gpt_reset(DeviceState *dev) } } +static void imx_gpt_soft_reset(DeviceState *dev) +{ + IMXGPTState *s = IMX_GPT(dev); + imx_gpt_reset_common(s, true); +} + +static void imx_gpt_reset(DeviceState *dev) +{ + IMXGPTState *s = IMX_GPT(dev); + imx_gpt_reset_common(s, false); +} + static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) { @@ -348,7 +365,7 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value, s->cr = value & ~0x7c14; if (s->cr & GPT_CR_SWR) { /* force reset */ /* handle the reset */ - imx_gpt_reset(DEVICE(s)); + imx_gpt_soft_reset(DEVICE(s)); } else { /* set our freq, as the source might have changed */ imx_gpt_set_freq(s);