/*
 * Copyright 2025 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/devicetree.h>
#include <zephyr/arch/arm/mpu/arm_mpu_mem_cfg.h>

#ifdef CONFIG_ARM_MPU_SRAM_WRITE_THROUGH
#define ARM_MPU_SRAM_REGION_ATTR  REGION_RAM_WT_ATTR
#else
#define ARM_MPU_SRAM_REGION_ATTR  REGION_RAM_ATTR
#endif

#define MEMORY_REGION_SIZE_KB(SIZE)    (SIZE / 1024)

#define ITCM_SIZE                       DT_REG_SIZE_BY_IDX(DT_NODELABEL(itcm), 0)
#define DTCM_SIZE                       DT_REG_SIZE_BY_IDX(DT_NODELABEL(dtcm), 0)
#define OCRAM1_SHM_SIZE                 DT_REG_SIZE_BY_IDX(DT_NODELABEL(ocram1), 0)
#define OCRAM2_SHM_SIZE                 DT_REG_SIZE_BY_IDX(DT_NODELABEL(ocram2), 0)
#define HYPER_RAM_SIZE                  DT_REG_SIZE_BY_IDX(DT_NODELABEL(flexspi2), 1)
#define QSPI_FLASH_SIZE                 DT_REG_SIZE_BY_IDX(DT_NODELABEL(flexspi), 1)
#define PERIPHERAL_SIZE                 DT_REG_SIZE_BY_IDX(DT_NODELABEL(peripheral), 0)

#define REGION_ITCM_BASE_ADDRESS         DT_REG_ADDR_BY_IDX(DT_NODELABEL(itcm), 0)
#define REGION_ITCM_SIZE                 \
			REGION_CUSTOMED_MEMORY_SIZE(MEMORY_REGION_SIZE_KB(ITCM_SIZE))
#define REGION_DTCM_BASE_ADDRESS         DT_REG_ADDR_BY_IDX(DT_NODELABEL(dtcm), 0)
#define REGION_DTCM_SIZE                 \
			REGION_CUSTOMED_MEMORY_SIZE(MEMORY_REGION_SIZE_KB(DTCM_SIZE))
#define REGION_OCRAM1_SHM_BASE_ADDRESS   DT_REG_ADDR_BY_IDX(DT_NODELABEL(ocram1), 0)
#define REGION_OCRAM1_SHM_SIZE           \
			REGION_CUSTOMED_MEMORY_SIZE(MEMORY_REGION_SIZE_KB(OCRAM1_SHM_SIZE))
#define REGION_OCRAM2_SHM_BASE_ADDRESS   DT_REG_ADDR_BY_IDX(DT_NODELABEL(ocram2), 0)
#define REGION_OCRAM2_SHM_SIZE           \
			REGION_CUSTOMED_MEMORY_SIZE(MEMORY_REGION_SIZE_KB(OCRAM2_SHM_SIZE))
#define REGION_HYPER_RAM_BASE_ADDRESS    DT_REG_ADDR_BY_IDX(DT_NODELABEL(flexspi2), 1)
#define REGION_HYPER_RAM_SIZE            \
			REGION_CUSTOMED_MEMORY_SIZE(MEMORY_REGION_SIZE_KB(HYPER_RAM_SIZE))
#define REGION_QSPI_FLASH_BASE_ADDRESS   DT_REG_ADDR_BY_IDX(DT_NODELABEL(flexspi), 1)
#define REGION_QSPI_FLASH_SIZE           \
			REGION_CUSTOMED_MEMORY_SIZE(MEMORY_REGION_SIZE_KB(QSPI_FLASH_SIZE))
#define REGION_PERIPHERAL_BASE_ADDRESS   DT_REG_ADDR_BY_IDX(DT_NODELABEL(peripheral), 0)
#define REGION_PERIPHERAL_SIZE           \
			REGION_CUSTOMED_MEMORY_SIZE(MEMORY_REGION_SIZE_KB(PERIPHERAL_SIZE))

static const struct arm_mpu_region mpu_regions[] = {
	/*
	 * Add "UNMAPPED" region to deny access to whole address space to
	 * workaround speculative prefetch.
	 * Refer to Arm errata 1013783-B for more details.
	 */
	MPU_REGION_ENTRY("UNMAPPED", 0,
			{REGION_4G | MPU_RASR_XN_Msk | P_NA_U_NA_Msk}),

#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(itcm))
	MPU_REGION_ENTRY("ITCM", REGION_ITCM_BASE_ADDRESS,
			 REGION_FLASH_ATTR(REGION_ITCM_SIZE)),
#endif

#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(dtcm))
	MPU_REGION_ENTRY("DTCM", REGION_DTCM_BASE_ADDRESS,
			 REGION_RAM_NOCACHE_ATTR(REGION_DTCM_SIZE)),
#endif

#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ocram1))
	MPU_REGION_ENTRY("OCRAM1", REGION_OCRAM1_SHM_BASE_ADDRESS,
			 ARM_MPU_SRAM_REGION_ATTR(REGION_OCRAM1_SHM_SIZE)),
#endif

#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ocram2))
	MPU_REGION_ENTRY("OCRAM2", REGION_OCRAM2_SHM_BASE_ADDRESS,
			 REGION_RAM_NOCACHE_ATTR(REGION_OCRAM2_SHM_SIZE)),
#endif

#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(hyperram0))
	MPU_REGION_ENTRY("HYPER_RAM", REGION_HYPER_RAM_BASE_ADDRESS,
			 ARM_MPU_SRAM_REGION_ATTR(REGION_HYPER_RAM_SIZE)),
#endif

#if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(w25q128jw))
	MPU_REGION_ENTRY("QSPI_FLASH", REGION_QSPI_FLASH_BASE_ADDRESS,
			 REGION_FLASH_ATTR(REGION_QSPI_FLASH_SIZE)),
#endif

	MPU_REGION_ENTRY("PERIPHERAL", REGION_PERIPHERAL_BASE_ADDRESS,
			 REGION_PPB_ATTR(REGION_PERIPHERAL_SIZE)),
};

const struct arm_mpu_config mpu_config = {
	.num_regions = ARRAY_SIZE(mpu_regions),
	.mpu_regions = mpu_regions,
};
