summaryrefslogtreecommitdiff
path: root/drivers/misc/fsl_sec_mon.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/fsl_sec_mon.c')
-rw-r--r--drivers/misc/fsl_sec_mon.c240
1 files changed, 129 insertions, 111 deletions
diff --git a/drivers/misc/fsl_sec_mon.c b/drivers/misc/fsl_sec_mon.c
index d482a7db9c..415232e1c1 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;
+}