act_mpu_arm.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. #if defined(CONFIG_CPU_CORTEX_M)
  12. #include <arch/arm/aarch32/cortex_m/cmsis.h>
  13. #endif
  14. #define MPU_ATTR_NO 0
  15. #define MPU_ATTR_RW 1
  16. #define MPU_ATTR_RO 2
  17. static const char *mpu_attr_str[3] = { "NO", "RW", "RO"};
  18. /*MPU set, mem_base= must align to size , size = 2^n, n >= 5 (32-2GB),*/
  19. void act_mpu_set(uint32_t chan, uint32_t mem_base, uint32_t size, uint32_t attr)
  20. {
  21. uint32_t i, mpu_base, mpu_size, mpu_attr;
  22. uint32_t num_region ;
  23. num_region = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
  24. if(chan >= num_region){
  25. printk("mpu set over max region:%d >= %d\n", chan, num_region);
  26. return;
  27. }
  28. if(!(MPU->CTRL & MPU_CTRL_ENABLE_Msk))
  29. MPU->CTRL = MPU_CTRL_ENABLE_Msk | MPU_CTRL_PRIVDEFENA_Msk;
  30. if(attr > MPU_ATTR_RO)
  31. attr = MPU_ATTR_RO;
  32. for(i = 31; i >= 0; i--){
  33. if(size & (1 << i))
  34. break;
  35. }
  36. if(i < 5){
  37. mpu_size = 0x20;
  38. i = 5;
  39. }else{
  40. mpu_size = size & (1 << i);
  41. }
  42. mpu_base = mem_base & (~(mpu_size-1));
  43. mpu_attr = (i-1) << MPU_RASR_SIZE_Pos;
  44. if(attr == MPU_ATTR_NO){
  45. mpu_attr |= MPU_RASR_XN_Msk| (0 << MPU_RASR_AP_Pos); //no exe, no access
  46. }else if(attr == MPU_ATTR_RW){
  47. mpu_attr |= (3 << MPU_RASR_AP_Pos); // exe, rw
  48. } else {
  49. mpu_attr |= (7 << MPU_RASR_AP_Pos); // exe, ro
  50. }
  51. printk("mpu %d: 0x%x-0x%x, set=0x%x-0x%x,attr=%s\n", chan , mpu_base, mpu_base+mpu_size,
  52. mem_base, mem_base+size, mpu_attr_str[attr]);
  53. MPU->RNR = chan;
  54. MPU->RBAR = (mpu_base&MPU_RBAR_ADDR_Msk) | MPU_RBAR_VALID_Msk | chan;
  55. MPU->RASR = mpu_attr | MPU_RASR_ENABLE_Msk;
  56. }
  57. void act_mpu_unset(uint32_t chan)
  58. {
  59. uint32_t num_region ;
  60. num_region = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
  61. if(chan >= num_region){
  62. printk("mpu unset over max region:%d >= %d\n", chan, num_region);
  63. return;
  64. }
  65. MPU->RNR = chan;
  66. MPU->RBAR = chan;
  67. MPU->RASR = 0;
  68. printk("mpu %d unset\n", chan);
  69. }