1 /* 2 * (C) Copyright 2017 3 * Vikas Manocha, ST Micoelectronics, vikas.manocha@st.com. 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <linux/bitops.h> 9 #include <asm/armv7m.h> 10 #include <asm/armv7m_mpu.h> 11 #include <asm/io.h> 12 13 #define V7M_MPU_CTRL_ENABLE (1 << 0) 14 #define V7M_MPU_CTRL_DISABLE (0 << 0) 15 #define V7M_MPU_CTRL_HFNMIENA (1 << 1) 16 #define VALID_REGION (1 << 4) 17 18 #define ENABLE_REGION (1 << 0) 19 20 #define AP_SHIFT 24 21 #define XN_SHIFT 28 22 #define TEX_SHIFT 19 23 #define S_SHIFT 18 24 #define C_SHIFT 17 25 #define B_SHIFT 16 26 #define REGION_SIZE_SHIFT 1 27 28 #define CACHEABLE (1 << C_SHIFT) 29 #define BUFFERABLE (1 << B_SHIFT) 30 #define SHAREABLE (1 << S_SHIFT) 31 32 void disable_mpu(void) 33 { 34 writel(0, &V7M_MPU->ctrl); 35 } 36 37 void enable_mpu(void) 38 { 39 writel(V7M_MPU_CTRL_ENABLE | V7M_MPU_CTRL_HFNMIENA, &V7M_MPU->ctrl); 40 41 /* Make sure new mpu config is effective for next memory access */ 42 dsb(); 43 isb(); /* Make sure instruction stream sees it */ 44 } 45 46 void mpu_config(struct mpu_region_config *reg_config) 47 { 48 uint32_t attr; 49 50 switch (reg_config->mr_attr) { 51 case STRONG_ORDER: 52 attr = SHAREABLE; 53 break; 54 case SHARED_WRITE_BUFFERED: 55 attr = BUFFERABLE; 56 break; 57 case O_I_WT_NO_WR_ALLOC: 58 attr = CACHEABLE; 59 break; 60 case O_I_WB_NO_WR_ALLOC: 61 attr = CACHEABLE | BUFFERABLE; 62 break; 63 case O_I_NON_CACHEABLE: 64 attr = 1 << TEX_SHIFT; 65 break; 66 case O_I_WB_RD_WR_ALLOC: 67 attr = (1 << TEX_SHIFT) | CACHEABLE | BUFFERABLE; 68 break; 69 case DEVICE_NON_SHARED: 70 attr = (2 << TEX_SHIFT) | BUFFERABLE; 71 break; 72 default: 73 attr = 0; /* strongly ordered */ 74 break; 75 }; 76 77 writel(reg_config->start_addr | VALID_REGION | reg_config->region_no, 78 &V7M_MPU->rbar); 79 80 writel(reg_config->xn << XN_SHIFT | reg_config->ap << AP_SHIFT | attr 81 | reg_config->reg_size << REGION_SIZE_SHIFT | ENABLE_REGION 82 , &V7M_MPU->rasr); 83 } 84