Home | History | Annotate | Download | only in stm32
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdbool.h>
     18 #include <stdint.h>
     19 
     20 #include <bl.h>
     21 #include <cpu.h>
     22 #include <mpu.h>
     23 #include <platform.h>
     24 
     25 struct CortexMpu {
     26     volatile uint32_t CTRL;
     27     volatile uint32_t RNR;
     28     volatile uint32_t RBAR;
     29     volatile uint32_t RASR;
     30 };
     31 
     32 #define MPU ((struct CortexMpu*)0xE000ED94UL)
     33 
     34 #define MPU_REG_ROM          0
     35 #define MPU_REG_RAM          1
     36 #define MPU_REG_NULL_PAGE    2
     37 
     38 
     39 /* region type */
     40 #define MPU_TYPE_DEVICE (0x10UL << 16)
     41 #define MPU_TYPE_MEMORY (0x0FUL << 16)
     42 
     43 /* region execute priviledges */
     44 #define MPU_BIT_XN      (1UL << 28) /* no execute */
     45 
     46 /* region access priviledges */
     47 #define MPU_NA          (0UL << 24) /* S: no access   U: no access */
     48 #define MPU_U_NA_S_RW   (1UL << 24) /* S: RW          U: no access */
     49 #define MPU_U_RO_S_RW   (2UL << 24) /* S: RW          U: RO        */
     50 #define MPU_RW          (3UL << 24) /* S: RW          U: RW        */
     51 #define MPU_U_NA_S_RO   (5UL << 24) /* S: RO          U: no access */
     52 #define MPU_U_RO_S_RO   (6UL << 24) /* S: RO          U: RO        */
     53 
     54 /* subregion mask (not used so all ones) */
     55 #define MPU_SRD_BITS    0xFF00UL
     56 #define MPU_BIT_ENABLE  1UL
     57 
     58 /* these define rom */
     59 extern uint8_t __shared_end[];
     60 extern uint8_t __ram_start[];
     61 extern uint8_t __ram_end[];
     62 
     63 static void mpuRegionCfg(uint32_t regionNo, uint32_t start, uint32_t len, uint32_t attrs) /* region will be rounded to acceptable boundaries (32B minimum, self-aligned) by GROWTH */
     64 {
     65     uint32_t proposedStart, proposedLen, lenVal = 1;
     66     uint64_t intState;
     67 
     68     /* expand until it works */
     69     do {
     70         /* special case 4GB region */
     71         if (lenVal == 32) {
     72             proposedStart = 0;
     73             break;
     74         }
     75 
     76         proposedStart = start &~ ((1ULL << lenVal) - 1);
     77         proposedLen = start + len - proposedStart;
     78         if (proposedLen < 32)
     79             proposedLen = 32;
     80         lenVal = (proposedLen & (proposedLen - 1)) ? 32 - __builtin_clz(proposedLen) : 31 - __builtin_clz(proposedLen);
     81 
     82     } while (proposedStart & ((1ULL << lenVal) - 1));
     83 
     84     intState = cpuIntsOff();
     85     asm volatile("dsb\nisb");
     86 
     87     MPU->RNR = regionNo;
     88     MPU->RASR = 0; /* disable region before changing it */
     89     MPU->RBAR = proposedStart;
     90     MPU->RASR = MPU_SRD_BITS | MPU_BIT_ENABLE | attrs | (lenVal << 1);
     91 
     92     asm volatile("dsb\nisb");
     93     cpuIntsRestore(intState);
     94 }
     95 
     96 static void mpuCfgRom(bool allowSvcWrite)
     97 {
     98     mpuRegionCfg(MPU_REG_ROM, (uint32_t)&BL, __shared_end - (uint8_t*)&BL, MPU_TYPE_MEMORY | (allowSvcWrite ? MPU_U_RO_S_RW : MPU_U_RO_S_RO));
     99 }
    100 
    101 static void mpuCfgRam(bool allowSvcExecute)
    102 {
    103     mpuRegionCfg(MPU_REG_RAM, (uint32_t)&__ram_start, __ram_end - __ram_start, MPU_TYPE_MEMORY | MPU_RW | (allowSvcExecute ? 0 : MPU_BIT_XN));
    104 }
    105 
    106 
    107 void mpuStart(void)
    108 {
    109     MPU->CTRL = 0x07; //MPU on, even during faults, supervisor default: allow, user default: default deny
    110 
    111     mpuCfgRom(false);
    112     mpuCfgRam(false);
    113     mpuRegionCfg(MPU_REG_NULL_PAGE, 0, 4096, MPU_TYPE_MEMORY | MPU_NA | MPU_BIT_XN);
    114 }
    115 
    116 void mpuAllowRamExecution(bool allowSvcExecute)
    117 {
    118     mpuCfgRam(allowSvcExecute);
    119 }
    120 
    121 void mpuAllowRomWrite(bool allowSvcWrite)
    122 {
    123     mpuCfgRom(allowSvcWrite);
    124 }
    125 
    126