/******************************************************************************* * DISCLAIMER * This software is supplied by Renesas Electronics Corporation and is only * intended for use with Renesas products. No other uses are authorized. This * software is owned by Renesas Electronics Corporation and is protected under * all applicable laws, including copyright laws. * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * Renesas reserves the right, without notice, to make changes to this software * and to discontinue the availability of this software. By using this software, * you agree to the additional terms and conditions found by accessing the * following link: * http://www.renesas.com/disclaimer * Copyright 2021-2023 Renesas Electronics Corporation All rights reserved. *******************************************************************************/ /******************************************************************************* * DESCRIPTION : remap driver ******************************************************************************/ /****************************************************************************** * @file remap.c * - Version : 0.06 * @brief 1. Setting of SIC REMAP AREA. * 2. Release of SIC REMAP AREA. * 3. Calculation of logical address. * 4. Calculation of physical address. * . *****************************************************************************/ /****************************************************************************** * History : DD.MM.YYYY Version Description * : 28.07.2021 0.01 First Release * : 03.09.2021 0.02 Modify remap_reg_write function to inline. * : 06.01.2022 0.03 Static analysis support * : 23.05.2022 0.04 Supported SICREMAP address for S4 ver1.0 * S4/V4H differences applied to s_remap_tbl. * : 15.05.2023 0.05 Add get_cfremap_addr() function to jump * the secure firmware on CF remap Area. * : 21.08.2023 0.06 Add support for V4M. *****************************************************************************/ #include #include #include #include #include #include /* Range of SICREMAP2M register */ #define REMAP_REG_MAX (16U) #define REMAP_2M_BITS (21U) #define REMAP_2M_SIZE ((uint32_t)1U << REMAP_2M_BITS) #define REMAP_2M_MASK (REMAP_2M_SIZE - 1U) #define REMAP_TBL_MAX (sizeof(s_remap_tbl)/sizeof(s_remap_tbl[0])) #define REMAP_UNUSED (0xFFFFFFFFU) typedef struct { uint32_t number; uint32_t address; }st_remap_address_table_t; /* Remap management table */ static st_remap_address_table_t s_remap_tbl[REMAP_REG_MAX] = { [0] = {REMAP_UNUSED, 0x00000000U}, [1] = {REMAP_UNUSED, 0x00000000U}, [2] = {REMAP_UNUSED, 0x00000000U}, [3] = {REMAP_UNUSED, 0x00000000U}, #if (RCAR_LSI == RCAR_S4) [4] = {4, 0xD8E00000}, /* MCU */ #elif ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M)) [4] = {REMAP_UNUSED, 0x00000000U}, #endif [5] = {5, 0xE7600000U}, /* Region ID */ [6] = {6, 0xE7200000U}, /* SYS-DMAC0 */ [7] = {7, 0xE6400000U}, /* HSCIF */ [8] = {8, 0xEE000000U}, /* MMC */ [9] = {9, 0xE6E00000U}, /* SCIF */ [10] = {10, 0xFFC00000U}, /* RT-DMAC0,PFC(MCU) */ [11] = {11, 0xEE200000U}, /* RPC */ [12] = {12, 0xE6200000U}, /* ECM,AP-System Core */ [13] = {13, 0xE6000000U}, /* PFC,GPIO,CPGA,RESET */ [14] = {14, 0xE6600000U}, /* CC63S,AXMM,QoS,FCPR */ [15] = {15, 0xEB200000U}, /* RT-SRAM */ }; static inline uint32_t get_sicremap2m_addr(uint32_t num) { return (REMAP_BASE + (num * 0x0004U)); } /* End of function get_sicremap2m_addr(uint32_t num) */ static inline void remap_reg_write(uint32_t num, uint32_t value) { /* Specific write Procedure for Write-Protected Register. */ do { mem_write32(ICUMX_PROT0PCMD, PROTCMD_START); mem_write32(get_sicremap2m_addr(num), value); mem_write32(get_sicremap2m_addr(num), ~value); mem_write32(get_sicremap2m_addr(num), value); } while (mem_read32(ICUMX_PROT0PS) == PROTS0ERR); } /* End of function remap_reg_write(uint32_t num, uint32_t value) */ void remap_register(uint32_t addr, uint32_t *remap_addr) { uint32_t loop; uint32_t set_addr; /* Check unused area in order from the top of the remap management table. */ for (loop = 0U; loop < REMAP_TBL_MAX; ++loop) { if (REMAP_UNUSED == s_remap_tbl[loop].number) { break; } } /* When necessary area can not be secured */ if (REMAP_TBL_MAX <= loop) { ERROR("There is no space in the logical address area.\n"); panic; } syncm(); /* Set remap area */ set_addr = addr & ~REMAP_2M_MASK; /* Update the table managing the remap space */ s_remap_tbl[loop].address = set_addr; s_remap_tbl[loop].number = (uint8_t)loop; /* Set SICREMAP register */ remap_reg_write(loop, set_addr); INFO("s_remap_tbl[%d].number = 0x%x\n",loop,s_remap_tbl[loop].number); INFO("s_remap_tbl[%d].address = 0x%x\n",loop,s_remap_tbl[loop].address); syncm(); /* Calculating the logical address of the address received as an argument */ *remap_addr = icu_remap_calc(loop); *remap_addr += addr & REMAP_2M_MASK; } /* End of function remap_register(uint32_t addr, uint32_t size, uint32_t *remap_addr) */ void remap_unregister(uint32_t remap_addr) { uint32_t loop; /* Is the remap space where the address of the argument is used? */ for (loop = 0U; loop < REMAP_TBL_MAX; ++loop) { INFO("s_remap_tbl[%d].number = 0x%x\n",loop,s_remap_tbl[loop].number); if ((REMAP_UNUSED != s_remap_tbl[loop].number) && ((icu_remap_calc(loop) <= remap_addr) && (remap_addr < icu_remap_calc(loop + 1U)))) { break; } } /* When an area to release can not be found */ if (REMAP_TBL_MAX <= loop) { ERROR("Not registered in the logical address.\n" "remap address = 0x%x\n",remap_addr); panic; } syncm(); /* release remap area */ /* Update the table managing the remap space */ s_remap_tbl[loop].address = 0U; s_remap_tbl[loop].number = REMAP_UNUSED; /* Release SICREMAP register */ remap_reg_write(loop, icu_remap_calc(loop)); syncm(); } /* End of function remap_unregister(uint32_t remap_addr) */ uint32_t remap_get_phys_addr(uint32_t remap_addr) { uint32_t phys_addr; uint32_t reg; /* It checks whether the argument is within the range of the logical address. */ if ((ICU_REMAP0 > remap_addr) || (icu_remap_calc(REMAP_REG_MAX) <= remap_addr)) { ERROR("Address convert error.\n" "source address = 0x%x\n",remap_addr); panic; } /* Calculate the physical address of the argument */ phys_addr = remap_addr - ICU_REMAP0; phys_addr >>= REMAP_2M_BITS; reg = get_sicremap2m_addr(phys_addr); reg = mem_read32(reg); phys_addr = reg + (remap_addr & REMAP_2M_MASK); return phys_addr; } /* End of function remap_get_phys_addr(uint32_t remap_addr) */ uint32_t remap_get_remap_addr(uint32_t phys_addr) { uint32_t remap_addr; uint32_t reg; uint32_t loop; /* It checks whether the argument is within the range of the physical address registered in SICREMAP. */ for (loop = 0U; loop < REMAP_REG_MAX; loop++) { reg = mem_read32(get_sicremap2m_addr(loop)); if ((reg <= phys_addr) && (phys_addr <= (reg + REMAP_2M_MASK))) { break; } } /* argument value is not used in the remap area. */ if (REMAP_REG_MAX <= loop) { ERROR("Address convert error.\n" "source address = 0x%x\n",phys_addr); panic; } /* Calculate the logical address of the argument */ remap_addr = icu_remap_calc(loop); remap_addr += phys_addr - reg; return remap_addr; } /* End of function remap_get_remap_addr(uint32_t phys_addr) */ uint32_t get_cfremap_addr(uint32_t fetch_addr) { uint32_t cf_remap_addr = 0x0U; uint32_t cf_current_base = mem_read32(ICUMX_CFREMAP); /* Get current setting of "physical address for cf remap base", and calculate cf remap address of target fetch */ cf_remap_addr = fetch_addr - cf_current_base; /* Check whether the calculated address is outside of Code Fetch area */ if ((CFREMAP_AREA_SIZE <= cf_remap_addr) || (fetch_addr < cf_current_base)) { ERROR("Target fetch address is invalid: 0x%08x\n", fetch_addr); panic; } return cf_remap_addr; } void set_sicremap_s4v10(void) { #if (RCAR_LSI == RCAR_S4) /* Change the setting of SICREMAP for S4 Ver1.0 to be the setting of SICREMAP for S4 Ver1.1. */ remap_reg_write(ICU_REMAP_NUM_RGID, ICU_REMAP_RGID); /* SIC REMAP5:Region ID */ remap_reg_write(ICU_REMAP_NUM_MCU , ICU_REMAP_MCU); /* SIC REMAP4:MCU */ #endif } /* End of function set_sicremap_s4v10(void) */ void set_sicremap_fcpr(void) { remap_reg_write(ICU_REMAP_NUM_FCPR, ICU_REMAP_FCPR); /* SIC REMAP14:FCPR */ } /* End of function set_sicremap_fcpr(void) */