leopard_mpu_arm.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright (c) 2019 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file arm mpu
  8. */
  9. #include <kernel.h>
  10. #include <string.h>
  11. #include <arch/arm/aarch32/cortex_m/cmsis.h>
  12. #include <act_arm_mpu.h>
  13. #include <linker/linker-defs.h>
  14. #include <soc.h>
  15. /* Global MAIR configurations */
  16. #define MPU_MAIR_INDEX_NC 0
  17. #define MPU_RBAR_AP_Pos 1U
  18. /* Privileged Read Write, Unprivileged Read Write */
  19. #define P_RW_U_RW 0x1
  20. #define P_RW_U_RW_Msk (P_RW_U_RW << MPU_RBAR_AP_Pos)
  21. /* Privileged Read Only, Unprivileged Read Only */
  22. #define P_RO_U_RO 0x3
  23. #define P_RO_U_RO_Msk (P_RO_U_RO << MPU_RBAR_AP_Pos)
  24. #define MPU_RBAR_SH_Pos 3U
  25. #define INNER_SHAREABLE 0x3
  26. #define INNER_SHAREABLE_Msk (INNER_SHAREABLE << MPU_RBAR_SH_Pos)
  27. /* Attribute flag for not-allowing execution (eXecute Never) */
  28. #define NOT_EXEC 0x01
  29. static const char *mpu_attr_str[3] = { "NO", "RW", "RO"};
  30. /*MPU set, mem_base= must align to size , n >= 5 (32-2GB),*/
  31. void act_mpu_set(uint32_t chan, uint32_t mem_base, uint32_t size, uint32_t attr)
  32. {
  33. uint32_t mpu_base, mpu_end, mpu_attr;
  34. uint32_t num_region ;
  35. num_region = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
  36. if(chan >= num_region){
  37. printk("mpu set over max region:%d >= %d\n", chan, num_region);
  38. return;
  39. }
  40. if(!(MPU->CTRL & MPU_CTRL_ENABLE_Msk)){
  41. // Memory Attribute Indirection Register 0
  42. MPU->MAIR0 = ((0x44 & MPU_MAIR0_Attr0_Msk) | // Normal memory, Inner Non-cacheable, Outer Non-cacheable
  43. (0x44 << MPU_MAIR0_Attr1_Pos) | // Normal memory, Inner Non-cacheable, Outer Non-cacheable
  44. (0x44 << MPU_MAIR0_Attr2_Pos) | // Normal memory, Inner Non-cacheable, Outer Non-cacheable
  45. (0x44 << MPU_MAIR0_Attr3_Pos)); // Normal memory, Inner Non-cacheable, Outer Non-cacheable
  46. MPU->CTRL = MPU_CTRL_ENABLE_Msk | MPU_CTRL_PRIVDEFENA_Msk;
  47. }
  48. mpu_base = (mem_base+0x1f) & (~0x1f); // 32B align
  49. mpu_end = ((mem_base+size) & (~0x1f))-1;
  50. if(attr == MPU_ATTR_NO){
  51. mpu_attr = P_RO_U_RO_Msk | INNER_SHAREABLE_Msk | NOT_EXEC; //no exe, ro
  52. }else if(attr == MPU_ATTR_RW){
  53. mpu_attr = P_RW_U_RW_Msk | INNER_SHAREABLE_Msk ; // exe, rw
  54. } else {
  55. mpu_attr = P_RO_U_RO_Msk | INNER_SHAREABLE_Msk ; // exe, ro
  56. }
  57. printk("mpu %d(%d): 0x%x-0x%x, set=0x%x-0x%x,attr=%s\n", chan , num_region, mpu_base, mpu_end,
  58. mem_base, mem_base+size, mpu_attr_str[attr]);
  59. MPU->RNR = chan;
  60. // Base address
  61. MPU->RBAR = (mpu_base | mpu_attr);
  62. // Limit register
  63. MPU->RLAR = ((mpu_end & MPU_RLAR_LIMIT_Msk) | // Size
  64. (MPU_MAIR_INDEX_NC << MPU_RLAR_AttrIndx_Pos) | // AttrIndex - 0
  65. (0x1 << MPU_RLAR_EN_Pos)); // Enable - On
  66. }
  67. void act_mpu_unset(uint32_t chan)
  68. {
  69. uint32_t num_region ;
  70. num_region = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
  71. if(chan >= num_region){
  72. printk("mpu unset over max region:%d >= %d\n", chan, num_region);
  73. return;
  74. }
  75. MPU->RNR = chan;
  76. MPU->RBAR = 0;
  77. MPU->RLAR = 0;
  78. printk("mpu %d unset\n", chan);
  79. }
  80. void arm_mpu_protect_init(void)
  81. {
  82. /* protect rom section */
  83. act_mpu_set(MPU_CHAN_ROM, 0x0, 0x10000, MPU_ATTR_RO);
  84. /* protect flash cache all address section */
  85. act_mpu_set(MPU_CHAN_CODE, (CONFIG_FLASH_BASE_ADDRESS + CONFIG_FLASH_LOAD_OFFSET), 0x1000000, MPU_ATTR_RO);
  86. #if defined(CONFIG_ARCH_HAS_RAMFUNC_SUPPORT)
  87. act_mpu_set(MPU_CHAN_RAMFUC, (uint32_t)&__ramfunc_start, (uint32_t)&__ramfunc_size, MPU_ATTR_RO);
  88. #endif /* CONFIG_ARCH_HAS_RAMFUNC_SUPPORT */
  89. }
  90. #define CPU_TRACE_RAM_ADDR 0x31000000
  91. #define CPU_TRACE_RAM_MAXLEN 1024
  92. static void trace_dump_str(unsigned int *buf, unsigned int len)
  93. {
  94. int i;
  95. for(i = 0; i < len/4; i++) {
  96. if((i&0x7)==0){
  97. printk("%08x:",CPU_TRACE_RAM_ADDR+i*4);
  98. }
  99. printk("%08x ", buf[i]);
  100. if( (i&0x7)==7 )
  101. printk("\n");
  102. }
  103. printk("\n");
  104. }
  105. void cpu_trace_enable(int enable)
  106. {
  107. if(enable){
  108. sys_write32(0 , 0xe0043004);
  109. memset((void*)CPU_TRACE_RAM_ADDR, 0, CPU_TRACE_RAM_MAXLEN);
  110. sys_write32(0 , 0xe0043000);
  111. sys_write32((1<<31)|0xf , 0xe0043004);
  112. }else{
  113. sys_write32(0 , 0xe0043004);
  114. }
  115. }
  116. static int act_mpu_init(const struct device *arg)
  117. {
  118. //unsigned int val = 0;
  119. ARG_UNUSED(arg);
  120. printk("arm mpu init\n");
  121. arm_mpu_protect_init();
  122. //soc_pstore_get(SOC_PSTORE_TAG_SYS_PANIC,&val);
  123. //if(val){
  124. printk("arm trace dump:\n");
  125. trace_dump_str((unsigned int *)CPU_TRACE_RAM_ADDR, CPU_TRACE_RAM_MAXLEN);
  126. //}
  127. cpu_trace_enable(1);
  128. return 0;
  129. }
  130. SYS_INIT(act_mpu_init, APPLICATION, 20);