• Santosh Shilimkar's avatar
    ARM: OMAP4460: Workaround for ROM bug because of CA9 r2pX GIC control register change. · ff999b8a
    Santosh Shilimkar authored
    On OMAP4+ devices, GIC register context is lost when MPUSS hits
    the OSWR(Open Switch Retention). On the CPU wakeup path, ROM code
    gets executed and one of the steps in it is to restore the
    saved context of the GIC. The ROM Code GIC distributor restoration
    is split in two parts: CPU specific register done by each CPU and
    common register done by only one CPU.
    
    Below is the abstract flow.
    
    ...............................................................
    - MPUSS in OSWR state.
    - CPU0 wakes up on the event(interrupt) and start executing ROM code.
    
    [..]
    
    - CPU0 executes "GIC Restoration:"
    
    [...]
    
    - CPU0 swicthes to non-secure mode and jumps to OS resume code.
    
    [...]
    
    - CPU0 is online in OS
    - CPU0 enables the GIC distributor. GICD.Enable Non-secure = 1
    - CPU0 wakes up CPU1 with clock-domain force wakeup method.
    - CPU0 continues it's execution.
    [..]
    
    - CPU1 wakes up and start executing ROM code.
    
    [..]
    
    - CPU1 executes "GIC Restoration:"
    
    [..]
    
    - CPU1 swicthes to non-secure mode and jumps to OS resume code.
    
    [...]
    
    - CPU1 is online in OS and start executing.
    [...]   -
    
    GIC Restoration: /* Common routine for HS and GP devices */
    {
           if (GICD != 1)  { /* This will be true in OSWR state */
                   if (GIC_SAR_BACKUP_STATE == SAVED)
                           - CPU restores GIC distributor
                   else
                           - reconfigure GIC distributor to boot values.
    
                   GICD.Enable secure = 1
           }
    
           if (GIC_SAR_BACKUP_STATE == SAVED)
                   - CPU restore its GIC CPU interface registers if saved.
           else
                   - reconfigure its GIC CPU interface registers to boot
                           values.
    }
    ...............................................................
    
    So as mentioned in the flow, GICD != 1 condition decides how
    the GIC registers are handled in ROM code wakeup path from
    OSWR. As evident from the flow, ROM code relies on the entire
    GICD register value and not specific register bits.
    
    The assumption was valid till CortexA9 r1pX version since there
    was only one banked bit to control secure and non-secure GICD.
    Secure view which ROM code sees:
           bit 0 == Enable Non-secure
    Non-secure view which HLOS sees:
           bit 0 == Enable secure
    
    But GICD register has changed between CortexA9 r1pX and r2pX.
    On r2pX GICD register is composed of 2 bits.
    Secure view which ROM code sees:
           bit 1 == Enable Non-secure
           bit 0 == Enable secure
    Non-secure view which HLOS sees:
           bit 0 == Enable Non-secure
    
    Hence on OMAP4460(r2pX) devices, if you go through the
    above flow again during CPU1 wakeup, GICD == 3 and hence
    ROM code fails to understand the real wakeup power state
    and reconfigures GIC distributor to boot values. This is
    nasty since you loose the entire interrupt controller
    context in a live system.
    
    The ROM code fix done on next OMAP4 device (OMAP4470 - r2px) is to
    check "GICD.Enable secure != 1" for GIC restoration in OSWR wakeup path.
    
    Since ROM code can't be fixed on OMAP4460 devices, a work around
    needs to be implemented. As evident from the flow, as long as
    CPU1 sees GICD == 1 in it's wakeup path from OSWR, the issue
    won't happen. Below is the flow with the work-around.
    
    ...............................................................
    - MPUSS in OSWR state.
    - CPU0 wakes up on the event(interrupt) and start executing ROM code.
    
    [..]
    
    - CPU0 executes "GIC Restoration:"
    
    [..]
    
    - CPU0 swicthes to non-secure mode and jumps to OS resume code.
    
    [..]
    
    - CPU0 is online in OS.
    - CPU0 does GICD.Enable Non-secure = 0
    - CPU0 wakes up CPU1 with clock domain force wakeup method.
    - CPU0 waits for GICD.Enable Non-secure = 1
    - CPU0 coninues it's execution.
    [..]
    
    - CPU1 wakes up and start executing ROM code.
    
    [..]
    
    - CPU1 executes "GIC Restoration:"
    
    [..]
    
    - CPU1 swicthes to non-secure mode and jumps to OS resume code.
    
    [..]
    
    - CPU1 is online in OS
    - CPU1 does GICD.Enable Non-secure = 1
    - CPU1 start executing
    [...]
    ...............................................................
    
    With this procedure, the GIC configuration done between the
    CPU0 wakeup and CPU1 wakeup will not be lost but during this
    short windows, the CPU0 will not receive interrupts.
    
    The BUG is applicable to only OMAP4460(r2pX) devices.
    OMAP4470 (also r2pX) is not affected by this bug because
    ROM code has been fixed.
    Signed-off-by: default avatarSantosh Shilimkar <santosh.shilimkar@ti.com>
    Signed-off-by: default avatarTero Kristo <t-kristo@ti.com>
    Signed-off-by: default avatarKevin Hilman <khilman@ti.com>
    ff999b8a
omap-smp.c 6.48 KB