提交 c98c9eba 编写于 作者: K Kurban Mallachiev 提交者: Peter Maydell

ARM i.MX timers: fix reset handling

The i.MX timer device can be reset by writing to the SWR bit
of the CR register. This has to behave differently from hard
(power-on) reset because it does not reset all of the bits
in the CR register.

We were incorrectly implementing soft reset and hard reset
the same way, and in addition had a logic error which meant
that we were clearing the bits that soft-reset is supposed
to preserve and not touching the bits that soft-reset clears.
This was not correct behaviour for either kind of reset.

Separate out the soft reset and hard reset code paths, and
correct the handling of reset of the CR register so that it
is correct in both cases.
Signed-off-by: NKurban Mallachiev <mallachiev@ispras.ru>
[PMM: rephrased commit message, spacing on operators;
 use bool rather than int for is_soft_reset]
Reviewed-by: NPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
上级 ccc11b02
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册