Commit ba50ea7e authored by Kalle Jokiniemi's avatar Kalle Jokiniemi Committed by Kevin Hilman

OMAP3: PM: Fix secure SRAM context save/restore

The secure sram context save uses dma channels 0 and 1.
In order to avoid collision between kernel DMA transfers and
ROM code dma transfers, we need to reserve DMA channels 0
1 on high security devices.

A bug in ROM code leaves dma irq status bits uncleared.
Hence those irq status bits need to be cleared when restoring
DMA context after off mode.

There was also a faulty parameter given to PPA in the secure
ram context save assembly code, which caused interrupts to
be enabled during secure ram context save. This caused the
save to fail sometimes, which resulted the saved context
to be corrupted, but also left DMA channels in secure mode.
The secure mode DMA channels caused "DMA secure error with
device 0" errors to be displayed.
Signed-off-by: default avatarKalle Jokiniemi <kalle.jokiniemi@digia.com>
Signed-off-by: default avatarJouni Hogander <jouni.hogander@nokia.com>
Signed-off-by: default avatarKevin Hilman <khilman@deeprootsystems.com>
parent 133464dc
...@@ -130,9 +130,6 @@ static void omap3_save_secure_ram_context(u32 target_mpu_state) ...@@ -130,9 +130,6 @@ static void omap3_save_secure_ram_context(u32 target_mpu_state)
u32 ret; u32 ret;
if (omap_type() != OMAP2_DEVICE_TYPE_GP) { if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
/* Disable dma irq before calling secure rom code API */
omap_dma_disable_irq(0);
omap_dma_disable_irq(1);
/* /*
* MPU next state must be set to POWER_ON temporarily, * MPU next state must be set to POWER_ON temporarily,
* otherwise the WFI executed inside the ROM code * otherwise the WFI executed inside the ROM code
......
...@@ -68,7 +68,7 @@ save_secure_ram_debug: ...@@ -68,7 +68,7 @@ save_secure_ram_debug:
mov r0, #25 @ set service ID for PPA mov r0, #25 @ set service ID for PPA
mov r12, r0 @ copy secure service ID in r12 mov r12, r0 @ copy secure service ID in r12
mov r1, #0 @ set task id for ROM code in r1 mov r1, #0 @ set task id for ROM code in r1
mov r2, #7 @ set some flags in r2, r6 mov r2, #4 @ set some flags in r2, r6
mov r6, #0xff mov r6, #0xff
mcr p15, 0, r0, c7, c10, 4 @ data write barrier mcr p15, 0, r0, c7, c10, 4 @ data write barrier
mcr p15, 0, r0, c7, c10, 5 @ data memory barrier mcr p15, 0, r0, c7, c10, 5 @ data memory barrier
......
...@@ -2358,26 +2358,20 @@ void omap_dma_global_context_save(void) ...@@ -2358,26 +2358,20 @@ void omap_dma_global_context_save(void)
void omap_dma_global_context_restore(void) void omap_dma_global_context_restore(void)
{ {
dma_write(0x2, OCP_SYSCONFIG);
while (!__raw_readl(omap_dma_base + OMAP_DMA4_SYSSTATUS))
;
dma_write(omap_dma_global_context.dma_gcr, GCR); dma_write(omap_dma_global_context.dma_gcr, GCR);
dma_write(omap_dma_global_context.dma_ocp_sysconfig, dma_write(omap_dma_global_context.dma_ocp_sysconfig,
OCP_SYSCONFIG); OCP_SYSCONFIG);
dma_write(omap_dma_global_context.dma_irqenable_l0, dma_write(omap_dma_global_context.dma_irqenable_l0,
IRQENABLE_L0); IRQENABLE_L0);
}
void omap_dma_disable_irq(int lch)
{
u32 val;
if (cpu_class_is_omap2()) { /*
/* Disable interrupts */ * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared
val = dma_read(IRQENABLE_L0); * after secure sram context save and restore. Hence we need to
val &= ~(1 << lch); * manually clear those IRQs to avoid spurious interrupts. This
dma_write(val, IRQENABLE_L0); * affects only secure devices.
} */
if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP))
dma_write(0x3 , IRQSTATUS_L0);
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
...@@ -2515,8 +2509,8 @@ static int __init omap_init_dma(void) ...@@ -2515,8 +2509,8 @@ static int __init omap_init_dma(void)
setup_irq(irq, &omap24xx_dma_irq); setup_irq(irq, &omap24xx_dma_irq);
} }
/* Enable smartidle idlemodes and autoidle */
if (cpu_is_omap34xx()) { if (cpu_is_omap34xx()) {
/* Enable smartidle idlemodes and autoidle */
u32 v = dma_read(OCP_SYSCONFIG); u32 v = dma_read(OCP_SYSCONFIG);
v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK |
DMA_SYSCONFIG_SIDLEMODE_MASK | DMA_SYSCONFIG_SIDLEMODE_MASK |
...@@ -2525,6 +2519,13 @@ static int __init omap_init_dma(void) ...@@ -2525,6 +2519,13 @@ static int __init omap_init_dma(void)
DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) |
DMA_SYSCONFIG_AUTOIDLE); DMA_SYSCONFIG_AUTOIDLE);
dma_write(v , OCP_SYSCONFIG); dma_write(v , OCP_SYSCONFIG);
/* reserve dma channels 0 and 1 in high security devices */
if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
printk(KERN_INFO "Reserving DMA channels 0 and 1 for "
"HS ROM code\n");
dma_chan[0].dev_id = 0;
dma_chan[1].dev_id = 1;
}
} }
......
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