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