/* * Copyright 2015 Freescale Semiconductor, Inc. * * SPDX-License-Identifier: GPL-2.0+ */ #include #include static u32 get_sec_mon_state(void) { struct ccsr_sec_mon_regs *sec_mon_regs = (void *) (CONFIG_SYS_SEC_MON_ADDR); 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); sts = get_sec_mon_state(); 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); /* 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--; } 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); /* polling loop till SEC_MON is in Non Secure*/ while (timeout) { sts = get_sec_mon_state(); 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: printf("SEC_MON already in Non Secure state.\n"); return 0; } return 0; } 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; 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; }