diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/fsl_sec_mon.c | 240 |
1 files changed, 129 insertions, 111 deletions
diff --git a/drivers/misc/fsl_sec_mon.c b/drivers/misc/fsl_sec_mon.c index d482a7db9ca..415232e1c15 100644 --- a/drivers/misc/fsl_sec_mon.c +++ b/drivers/misc/fsl_sec_mon.c @@ -7,140 +7,158 @@ #include <common.h> #include <fsl_sec_mon.h> -int change_sec_mon_state(u32 initial_state, u32 final_state) +static u32 get_sec_mon_state(void) { struct ccsr_sec_mon_regs *sec_mon_regs = (void *) (CONFIG_SYS_SEC_MON_ADDR); - u32 sts = sec_mon_in32(&sec_mon_regs->hp_stat); + return sec_mon_in32(&sec_mon_regs->hp_stat) & HPSR_SSM_ST_MASK; +} + +static int set_sec_mon_state_non_sec(void) +{ + u32 sts; int timeout = 10; + struct ccsr_sec_mon_regs *sec_mon_regs = (void *) + (CONFIG_SYS_SEC_MON_ADDR); - if ((sts & HPSR_SSM_ST_MASK) != initial_state) - return -1; + sts = get_sec_mon_state(); - if (initial_state == HPSR_SSM_ST_TRUST) { - switch (final_state) { - case HPSR_SSM_ST_NON_SECURE: - printf("SEC_MON state transitioning to Soft Fail.\n"); - sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_SV); - - /* - * poll till SEC_MON is in - * Soft Fail state - */ - while (((sts & HPSR_SSM_ST_MASK) != - HPSR_SSM_ST_SOFT_FAIL)) { - while (timeout) { - sts = sec_mon_in32 - (&sec_mon_regs->hp_stat); - - if ((sts & HPSR_SSM_ST_MASK) == - HPSR_SSM_ST_SOFT_FAIL) - break; - - udelay(10); - timeout--; - } - } + switch (sts) { + /* + * If initial state is check or Non-Secure, then set the Software + * Security Violation Bit and transition to Non-Secure State. + */ + case HPSR_SSM_ST_CHECK: + printf("SEC_MON state transitioning to Non Secure.\n"); + sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_SV); - if (timeout == 0) { - printf("SEC_MON state transition timeout.\n"); - return -1; - } + /* polling loop till SEC_MON is in Non Secure state */ + while (timeout) { + sts = get_sec_mon_state(); + + if ((sts & HPSR_SSM_ST_MASK) == + HPSR_SSM_ST_NON_SECURE) + break; + + udelay(10); + timeout--; + } - timeout = 10; + if (timeout == 0) { + printf("SEC_MON state transition timeout.\n"); + return -1; + } + break; + + /* + * If initial state is Trusted, Secure or Soft-Fail, then first set + * the Software Security Violation Bit and transition to Soft-Fail + * State. + */ + case HPSR_SSM_ST_TRUST: + case HPSR_SSM_ST_SECURE: + case HPSR_SSM_ST_SOFT_FAIL: + printf("SEC_MON state transitioning to Soft Fail.\n"); + sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_SV); + + /* polling loop till SEC_MON is in Soft-Fail state */ + while (timeout) { + sts = get_sec_mon_state(); + + if ((sts & HPSR_SSM_ST_MASK) == + HPSR_SSM_ST_SOFT_FAIL) + break; + + udelay(10); + timeout--; + } + + if (timeout == 0) { + printf("SEC_MON state transition timeout.\n"); + return -1; + } + + timeout = 10; + /* + * If SSM Soft Fail to Non-Secure State Transition + * disable is not set, then set SSM_ST bit and + * transition to Non-Secure State. + */ + if ((sec_mon_in32(&sec_mon_regs->hp_com) & + HPCOMR_SSM_SFNS_DIS) == 0) { printf("SEC_MON state transitioning to Non Secure.\n"); sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SSM_ST); - /* - * poll till SEC_MON is in - * Non Secure state - */ - while (((sts & HPSR_SSM_ST_MASK) != - HPSR_SSM_ST_NON_SECURE)) { - while (timeout) { - sts = sec_mon_in32 - (&sec_mon_regs->hp_stat); - - if ((sts & HPSR_SSM_ST_MASK) == - HPSR_SSM_ST_NON_SECURE) - break; - - udelay(10); - timeout--; - } - } + /* polling loop till SEC_MON is in Non Secure*/ + while (timeout) { + sts = get_sec_mon_state(); - if (timeout == 0) { - printf("SEC_MON state transition timeout.\n"); - return -1; - } - break; - case HPSR_SSM_ST_SOFT_FAIL: - printf("SEC_MON state transitioning to Soft Fail.\n"); - sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_FSV); - - /* - * polling loop till SEC_MON is in - * Soft Fail state - */ - while (((sts & HPSR_SSM_ST_MASK) != - HPSR_SSM_ST_SOFT_FAIL)) { - while (timeout) { - sts = sec_mon_in32 - (&sec_mon_regs->hp_stat); - - if ((sts & HPSR_SSM_ST_MASK) == - HPSR_SSM_ST_SOFT_FAIL) - break; - - udelay(10); - timeout--; - } + if ((sts & HPSR_SSM_ST_MASK) == + HPSR_SSM_ST_NON_SECURE) + break; + + udelay(10); + timeout--; } if (timeout == 0) { printf("SEC_MON state transition timeout.\n"); return -1; } - break; - default: - return -1; } - } else if (initial_state == HPSR_SSM_ST_NON_SECURE) { - switch (final_state) { - case HPSR_SSM_ST_SOFT_FAIL: - printf("SEC_MON state transitioning to Soft Fail.\n"); - sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_FSV); - - /* - * polling loop till SEC_MON is in - * Soft Fail state - */ - while (((sts & HPSR_SSM_ST_MASK) != - HPSR_SSM_ST_SOFT_FAIL)) { - while (timeout) { - sts = sec_mon_in32 - (&sec_mon_regs->hp_stat); - - if ((sts & HPSR_SSM_ST_MASK) == - HPSR_SSM_ST_SOFT_FAIL) - break; - - udelay(10); - timeout--; - } - } + break; + default: + printf("SEC_MON already in Non Secure state.\n"); + return 0; + } + return 0; +} - if (timeout == 0) { - printf("SEC_MON state transition timeout.\n"); - return -1; - } +static int set_sec_mon_state_soft_fail(void) +{ + u32 sts; + int timeout = 10; + struct ccsr_sec_mon_regs *sec_mon_regs = (void *) + (CONFIG_SYS_SEC_MON_ADDR); + + printf("SEC_MON state transitioning to Soft Fail.\n"); + sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_FSV); + + /* polling loop till SEC_MON is in Soft-Fail state */ + while (timeout) { + sts = get_sec_mon_state(); + + if ((sts & HPSR_SSM_ST_MASK) == + HPSR_SSM_ST_SOFT_FAIL) break; - default: - return -1; - } + + udelay(10); + timeout--; } + if (timeout == 0) { + printf("SEC_MON state transition timeout.\n"); + return -1; + } return 0; } + +int set_sec_mon_state(u32 state) +{ + int ret = -1; + + switch (state) { + case HPSR_SSM_ST_NON_SECURE: + ret = set_sec_mon_state_non_sec(); + break; + case HPSR_SSM_ST_SOFT_FAIL: + ret = set_sec_mon_state_soft_fail(); + break; + default: + printf("SEC_MON state transition not supported.\n"); + return 0; + } + + return ret; +} |