Merge branch 'master' of git://git.denx.de/u-boot-uniphier
[platform/kernel/u-boot.git] / drivers / misc / fsl_sec_mon.c
index d482a7d..415232e 100644 (file)
 #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;
+}