Commit cfec9c54 authored by Nishanth Menon's avatar Nishanth Menon Committed by Kevin Hilman

ARM: OMAP3+: SmartReflex: clear ERRCONFIG_VPBOUNDINTST only on a need

The VPBOUNDINTST field of the ERRCONFIG register has an additional
functional meaning of force clearing the SR internal signal with VP
(sr_interruptz).
This can result in scenarios where the VP->SR protocol is violated
because the SR internal signal with VP is already high and VP will
never clear the vpirqclr signal.
Therefore during the next force update to reset to nominal voltage,
VP cannot pulse vpirqclr, so the PRCM HW cannot generate the tranxdone
IRQ and the situation is not recoverable until a cold reset is invoked.

To prevent this situation, check if status is set before clearing it
as this needs to be done only on a need basis.
Reported-by: default avatarVincent Bour <v-bour@ti.com>
Signed-off-by: default avatarNishanth Menon <nm@ti.com>
Signed-off-by: default avatarJean Pihet <j-pihet@ti.com>
Reviewed-by: default avatarKevin Hilman <khilman@ti.com>
Signed-off-by: default avatarKevin Hilman <khilman@ti.com>
parent ade6ec05
......@@ -289,6 +289,8 @@ static int sr_late_init(struct omap_sr *sr_info)
static void sr_v1_disable(struct omap_sr *sr)
{
int timeout = 0;
int errconf_val = ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
ERRCONFIG_MCUBOUNDINTST;
/* Enable MCUDisableAcknowledge interrupt */
sr_modify_reg(sr, ERRCONFIG_V1,
......@@ -297,13 +299,13 @@ static void sr_v1_disable(struct omap_sr *sr)
/* SRCONFIG - disable SR */
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
/* Disable all other SR interrupts and clear the status */
/* Disable all other SR interrupts and clear the status as needed */
if (sr_read_reg(sr, ERRCONFIG_V1) & ERRCONFIG_VPBOUNDINTST_V1)
errconf_val |= ERRCONFIG_VPBOUNDINTST_V1;
sr_modify_reg(sr, ERRCONFIG_V1,
(ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
(ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
ERRCONFIG_MCUBOUNDINTST |
ERRCONFIG_VPBOUNDINTST_V1));
errconf_val);
/*
* Wait for SR to be disabled.
......@@ -332,9 +334,17 @@ static void sr_v2_disable(struct omap_sr *sr)
/* SRCONFIG - disable SR */
sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
/* Disable all other SR interrupts and clear the status */
sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
/*
* Disable all other SR interrupts and clear the status
* write to status register ONLY on need basis - only if status
* is set.
*/
if (sr_read_reg(sr, ERRCONFIG_V2) & ERRCONFIG_VPBOUNDINTST_V2)
sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
ERRCONFIG_VPBOUNDINTST_V2);
else
sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
0x0);
sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
IRQENABLE_MCUVALIDINT |
IRQENABLE_MCUBOUNDSINT));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment