blob: eb472e582caa3097b8015323695c70dc241da842 [file] [log] [blame]
/*
* Copyright (c) 2017 Linaro Limited.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <device.h>
#include <init.h>
#include <kernel.h>
#include <soc.h>
#include <arch/arm/cortex_m/cmsis.h>
#include <arch/arm/cortex_m/mpu/nxp_mpu.h>
#include <logging/sys_log.h>
#include <misc/__assert.h>
static inline u8_t _get_num_regions(void)
{
u32_t type = (SYSMPU->CESR & SYSMPU_CESR_NRGD_MASK)
>> SYSMPU_CESR_NRGD_SHIFT;
switch (type) {
case 0:
return 8;
case 1:
return 12;
case 2:
return 16;
default:
__ASSERT(0, "Unsupported MPU configuration.");
return 0;
}
return NXP_MPU_REGION_NUMBER;
}
static void _region_init(u32_t index, u32_t region_base,
u32_t region_end, u32_t region_attr)
{
SYSMPU->WORD[index][0] = region_base;
SYSMPU->WORD[index][1] = region_end;
SYSMPU->WORD[index][2] = region_attr;
SYSMPU->WORD[index][3] = SYSMPU_WORD_VLD_MASK;
SYS_LOG_DBG("[%d] 0x%08x 0x%08x 0x%08x 0x%08x", index,
SYSMPU->WORD[index][0],
SYSMPU->WORD[index][1],
SYSMPU->WORD[index][2],
SYSMPU->WORD[index][3]);
}
/*
* @brief MPU default configuration
*
* This function provides the default configuration mechanism for the Memory
* Protection Unit (MPU).
*/
static void _nxp_mpu_config(void)
{
u32_t r_index;
SYS_LOG_DBG("region number: %d", _get_num_regions());
/* NXP MPU supports up to 16 Regions */
if (mpu_config.num_regions > _get_num_regions()) {
return;
}
/* Disable MPU */
SYSMPU->CESR &= ~SYSMPU_CESR_VLD_MASK;
/* Clear Interrupts */
SYSMPU->CESR |= SYSMPU_CESR_SPERR_MASK;
/* MPU Configuration */
/* Disable Region 0 */
SYSMPU->WORD[0][2] = 0;
/*
* Configure regions:
* r_index starts from 0 but is passed to region_init as r_index + 1,
* region 0 is not configurable
*/
for (r_index = 0; r_index < mpu_config.num_regions; r_index++) {
_region_init(r_index + 1,
mpu_config.mpu_regions[r_index].base,
mpu_config.mpu_regions[r_index].end,
mpu_config.mpu_regions[r_index].attr);
}
/* Enable MPU */
SYSMPU->CESR |= SYSMPU_CESR_VLD_MASK;
/* Make sure that all the registers are set before proceeding */
__DSB();
__ISB();
}
/*
* @brief MPU clock configuration
*
* This function provides the clock configuration for the Memory Protection
* Unit (MPU).
*/
static void _nxp_mpu_clock_cfg(void)
{
/* Enable Clock */
CLOCK_EnableClock(kCLOCK_Sysmpu0);
}
static int nxp_mpu_init(struct device *arg)
{
ARG_UNUSED(arg);
_nxp_mpu_clock_cfg();
_nxp_mpu_config();
return 0;
}
#if defined(CONFIG_SYS_LOG)
/* To have logging the driver needs to be initialized later */
SYS_INIT(nxp_mpu_init, POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
#else
SYS_INIT(nxp_mpu_init, PRE_KERNEL_1,
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
#endif