/******************************************************************************
 * $Revision: 423 $
 * $Date:: 2017-04-07 16:03:30 +0900#$
 *****************************************************************************/
/* __DISCLAIMER_START__                                                      */
/******************************************************************************
* (c)2017, Cypress Semiconductor Corporation
* or a subsidiary of Cypress Semiconductor Corporation. All rights
* reserved.
*
* This software, including source code, documentation and related
* materials ( "Software" ), is owned by Cypress Semiconductor
* Corporation or one of its subsidiaries ( "Cypress" ) and is protected by
* and subject to worldwide patent protection (United States and foreign),
* United States copyright laws and international treaty provisions.
* Therefore, you may use this Software only as provided in the license
* agreement accompanying the software package from which you
* obtained this Software ( "EULA" ).
*
* If no EULA applies, Cypress hereby grants you a personal, nonexclusive,
* non-transferable license to copy, modify, and compile the
* Software source code solely for use in connection with Cypress' s
* integrated circuit products. Any reproduction, modification, translation,
* compilation, or representation of this Software except as specified
* above is prohibited without the express written permission of Cypress.
*
* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO
* WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING,
* BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. Cypress reserves the right to make
* changes to the Software without notice. Cypress does not assume any
* liability arising out of the application or use of the Software or any
* product or circuit described in the Software. Cypress does not
* authorize its products for use in any products where a malfunction or
* failure of the Cypress product may reasonably be expected to result in
* significant property damage, injury or death ( "High Risk Product" ). By
* including Cypress' s product in a High Risk Product, the manufacturer
* of such system or application assumes all risk of such use and in doing
* so agrees to indemnify Cypress against all liability.
******************************************************************************/
/* __DISCLAIMER_END__                                                        */
/*****************************************************************************
 ** \file  mem.c
 **
 ** Mem Functions
 **
 ** History:
 **   - 2014-06-02  0.01  HS   Initial version for Traveo
 **   - 2014-10-21  0.23  CEy  Added function for GFX Sub-System MPU setup
 *****************************************************************************/

/*****************************************************************************/
/* Include files                                                             */
/*****************************************************************************/
#include "pdl.h"


#if defined(PDL_PERIPHERAL_MEM_ACTIVE)

/**
 ******************************************************************************
 ** \addtogroup MemGroup Memory Functions (MEM)
 *****************************************************************************/
/*!@{ */

/*****************************************************************************/
/* Local pre-processor symbols/macros ('#define')                            */
/*****************************************************************************/

/*****************************************************************************/
/* Global variable definitions (declared in header file with 'extern')       */
/*****************************************************************************/

/*****************************************************************************/
/* Local type definitions ('typedef')                                        */
/*****************************************************************************/

/** \brief Bits and Bit fields in c1, Coprocessor System Control Registers */
typedef struct stc_mpu_control_field
{
    /** \brief MPU Enable
     ** Enables the MPU:
     ** 0 => MPU disabled. This is the reset value.
     ** 1 => MPU enabled.
     ** If no MPU is implemented, this bit is SBZ.
     **/
    uint_io32_t u1M :0x01;
    /** \brief strict alignment Enable
     ** Enables strict alignment of data to detect alignment faults in data accesses:
     ** 0 => strict alignment fault checking disabled. This is the reset value.
     ** 1 => strict alignment fault checking enabled.
     **/
    uint_io32_t u1A :0x01;
    /** \brief L1 data cache Enable
     ** Enables L1 data cache:
     ** 0 = data caching disabled. This is the reset value.
     ** 1 = data caching enabled.
     ** If no data cache is implemented, then this bit is SBZ.
     **/
    uint_io32_t u1C :0x01;
    /** reserved (SBO) */
    uint_io32_t :0x04;
    /** reserved (SBZ)*/
    uint_io32_t :0x03;
    /** \brief  Enables SWP and SWPB instructions
     ** 0 = SWP and SWPB are Undefined
     ** 1 = SWP and SWPB are executed with full locking support on the bus
     ** The reset value of this bit is 0.
     **/
    uint_io32_t u1SW :0x01;
    /** \brief  Branch prediction enable bit.
     ** The processor supports branch prediction. This bit is SBO.
     ** The ACTLR can control branch prediction,
     ** see c1, Auxiliary Control Register on page 4-41 of ARM Cortex r5 manual.
     **/
    uint_io32_t u1Z :0x01;
    /** \brief  L1 instruction cache enable bit.
     ** Enables L1 instruction cache:
     ** 0 = instruction caching disabled. This is the reset value.
     ** 1 = instruction caching enabled.
     ** If no instruction cache is implemented, then this bit is SBZ.
     **/
    uint_io32_t u1I :0x01;
    /** \brief  Determines the location of exception vectors:
     ** 0 => normal exception vectors selected,
     **      address range = 0x00000000-0x0000001C
     ** 1 => high exception vectors (HIVECS) selected,
     **      address range = 0xFFFF0000-0xFFFF001C.
     ** The primary input VINITHI defines the reset value.
     **/
    uint_io32_t u1V :0x01;
    /** \brief  Round-robin bit.
     ** controls replacement strategy for instruction and data caches:
     ** 0 = random replacement strategy
     ** 1 = round-robin replacement strategy.
     ** The reset value of this bit is 0.
     ** The processor always uses a random replacement strategy,regardless of
     ** the state of this bit.
     **/
    uint_io32_t u1RR :0x01;
    /** reserved (SBZ) */
    uint_io32_t :0x01;
    /** reserved (SBO)*/
    uint_io32_t :0x01;
    /** \brief  MPU background region enable
     **/
    uint_io32_t u1BR :0x01;
    /** reserved (SBO)*/
    uint_io32_t :0x01;
    /** \brief  Divide by zero:.
     ** Divide by zero
     ** 0 = do not generate an Undefined Instruction exception
     ** 1 = generate an Undefined Instruction exception.
     ** The reset value of this bit is 0.
     **/
    uint_io32_t u1DZ :0x01;
    /** reserved (SBZ)*/
    uint_io32_t :0x01;
    /** \brief  Fast Interrupts enable.
     ** On the processor Fast Interrupts are always enabled.
     ** This bit is SBO.
     **/
    uint_io32_t u1FI :0x01;
    /** reserved (SBO)*/
    uint_io32_t :0x02;
    /** \brief  vectored interrupt configuration.
     ** Configures vectored interrupt:
     ** 0 = exception vector address for IRQ is 0x00000018 or 0xFFFF0018.
     **     See V bit.
     ** 1 = VIC controller provides handler address for IRQ.
     ** The reset value of this bit is 0.
     **/
    uint_io32_t u1VE :0x01;
    /** \brief  EE
     ** Determines how the E bit in the CPSR is set on an exception:
     ** 0 => CPSR E bit is set to 0 on an exception
     ** 1 => CPSR E bit is set to 1 on an exception.
     ** The primary input CFGEE defines the reset value.
     **/
    uint_io32_t u1EE :0x01;
    /** reserved (SBZ)*/
    uint_io32_t :0x01;
    /** \brief  NMFI
     ** NMFI, non-maskable fast interrupt enable:
     ** 0 => Software can disable FIQs
     ** 1 => Software cannot disable FIQs.
     ** This bit is read-only.
     ** The configuration input CFGNMFI defines its value.
     **/
    uint_io32_t u1NMFI :0x01;
    /** \brief TEX Remap Enable
     ** TEX Remap Enable
     ** On the processor this bit is SBZ.
     **/
    uint_io32_t u1TRE :0x01;
    /** \brief Access Flag Enable.
     ** Access Flag Enable.
     ** On the processor this bit is SBZ.
     **/
    uint_io32_t u1AFE :0x01;
    /** \brief Thumb exception enable
     ** 0 => enable ARM exception generation
     ** 1 => enable Thumb exception generation.
     ** The primary input TEINIT defines the reset value.
     **/
    uint_io32_t u1TE :0x01;
    /** \brief little or big instruction endianness identification
     ** Identifies little or big instruction endianness in use:
     ** 0 => little-endianness
     ** 1 => big-endianness.
     ** The primary input CFGIE defines the reset value. This bit is read-only.
     **/
    uint_io32_t u1IE :0x01;
}stc_mpu_control_field_t;

/** \brief Type for Coprocessor System Control Registers */
typedef union un_mpu_control
{
    /** Full register */
    uint_io32_t                     u32Register;
    /** Bits and Bit fields */
    stc_mpu_control_field_t         stcField;
    /** Standard fields */
    uint_io8_t                      au8Byte[4];
    uint_io16_t                     au16Halfword[2];
} un_mpu_control_t;

/** \brief Bits and Bit fields in Coprocessor MPU Region Base Address Registers */
typedef struct stc_mpu_regionbase_field
{
    /** reserved */
    uint_io32_t :0x05;
    /** \brief  Base address
     ** Defines bits [31:5] of the base address of a region.
     **/
    uint_io32_t u27BaseAddress :0x1B;
}stc_mpu_regionbase_field_t;

/** \brief Type for Coprocessor MPU Region Base Address Registers */
typedef union un_mpu_regionbase
{
    /** Full register */
    uint_io32_t                     u32Register;
    /** Bits and Bit fields */
    stc_mpu_regionbase_field_t      stcField;
    /** Standard fields */
    uint_io8_t                      au8Byte[4];
    uint_io16_t                     au16Halfword[2];
} un_mpu_regionbase_t;

/** \brief Bits and Bit fields in Coprocessor MPU Region Size and Enable Registers */
typedef struct stc_mpu_regionsize_field
{
    /** \brief Enable
     ** Enables or disables a memory region:
     ** 0 => Memory region disabled.
     **      Memory regions are disabled on reset.
     ** 1 => Memory region enabled.
     **      A memory region must be enabled before it is used.
     **/
    uint_io32_t u1Enable :0x01;
    /** \brief Region size
     ** Defines the region size:         b01100 = 8KB      b10110 = 8MB
     ** b00000 - b00011=Unpredictable    b01101 = 16KB     b10111 = 16MB
     ** b00100 = 32 bytes                b01110 = 32KB     b11000 = 32MB
     ** b00101 = 64 bytes                b01111 = 64KB     b11001 = 64MB
     ** b00110 = 128 bytes               b10000 = 128KB    b11010 = 128MB
     ** b00111 = 256 bytes               b10001 = 256KB    b11011 = 256MB
     ** b01000 = 512 bytes               b10010 = 512KB    b11100 = 512MB
     ** b01001 = 1KB                     b10011 = 1MB      b11101 = 1GB
     ** b01010 = 2KB                     b10100 = 2MB      b11110 = 2GB
     ** b01011 = 4KB                     b10101 = 4MB      b11111 = 4GB.
     **/
    uint_io32_t u5RegionSize :0x05;
    /** reserved (SBZ)*/
    uint_io32_t :0x02;
    /** \brief Sub-region disable
     ** Enables or disables a memory region:
     ** Each bit position represents a sub-region, 0-7.
     ** Bit [8] corresponds to sub-region 0
     ** ...
     ** Bit [15] corresponds to sub-region 7
     ** The meaning of each bit is:
     ** 0 = address range is part of this region
     ** 1 = address range is not part of this region.
     **/
    uint_io32_t u8SubRegionDisable :0x08;
    /** reserved (SBZ)*/
    uint_io32_t :0x10;
}stc_mpu_regionsize_field_t;

/** \brief Type for Coprocessor MPU Region Size and Enable Registers */
typedef union un_mpu_regionsize
{
    /** Full register */
    uint_io32_t                     u32Register;
    /** Bits and Bit fields */
    stc_mpu_regionsize_field_t      stcField;
    /** Standard fields */
    uint_io8_t                      au8Byte[4];
    uint_io16_t                     au16Halfword[2];
} un_mpu_regionsize_t;

/** \brief Bits and Bit fields in Coprocessor MPU Region Access Control Register */
typedef struct stc_mpu_regionaccess_field
{
    /** \brief B bit
     ** For more information on this region attribute,
     ** see Table 4-36 in Cortex r5 manual
     **/
    uint_io32_t u1B :0x01;
    /** \brief C bit
     ** For more information on this region attribute,
     ** see Table 4-36 in Cortex r5 manual
     **/
    uint_io32_t u1C :0x01;
    /** \brief Share
     ** Determines if the memory region is Shared or Non-shared:
     ** 0 => Non-shared.
     ** 1 => Shared.
     ** This bit only applies to Normal, not Device or Strongly-ordered memory.
     **/
    uint_io32_t u1S :0x01;
    /** \brief Type extension[2:0]
     **  Defines the type extension attribute.
     ** For more information on this region attribute,
     ** see Table 4-36 in Cortex r5 manual
     **/
    uint_io32_t u3TEX :0x03;
    /** reserved (SBZ) */
    uint_io32_t :0x02;
    /** \brief Access permission[2:0]
     ** AP bit values  Privileged permissions  User permissions  Description
     **    b000        No access               No access         All accesses generate a permission fault
     **    b001        Read/write              No access         Privileged access only
     **    b010        Read/write              Read-only         Writes in User mode generate permission faults
     **    b011        Read/write              Read/write        Full access
     **    b100        UNP                     UNP               Reserved
     **    b101        Read-only               No access         Privileged read-only
     **    b110        Read-only               Read-only         Privileged/User read-only
     **    b111        UNP                     UNP               Reserved
     **/
    uint_io32_t u3AP :0x03;
    /** reserved */
    uint_io32_t :0x01;
    /** \brief Execute Never.
     ** Determines if a region of memory is executable:
     ** 0 => all instruction fetches enabled
     ** 1 => no instruction fetches enabled.
     **/
    uint_io32_t u1XN :0x01;
    /** reserved (SBZ) */
    uint_io32_t :0x13;
}stc_mpu_regionaccess_field_t;

/** \brief Type for Coprocessor MPU Region Access Control Register */
typedef union un_mpu_regionaccess
{
    /** Full register */
    uint_io32_t                     u32Register;
    /** Bits and Bit fields */
    stc_mpu_regionaccess_field_t    stcField;
    /** Standard fields */
    uint_io8_t                      au8Byte[4];
    uint_io16_t                     au16Halfword[2];
} un_mpu_regionaccess_t;

/** \brief Bits and Bit fields in Coprocessor MPU Memory Region Number Register */
typedef struct stc_mpu_regionnumber_field
{
    /** \brief Region [3:0]
     ** Defines the group of registers to be accessed.
     ** Read the MPUIR to determine the number of supported regions,
     ** see c0, MPU Type Register on page 4-17 of ARM Cortex r5 manual
     **/
    uint_io32_t u4Region :0x04;
    /** reserved (SBZ) */
    uint_io32_t :0x1C;
}stc_mpu_regionnumber_field_t;

/** \brief Type for Coprocessor MPU Memory Region Number Register */
typedef union un_mpu_regionnumber
{
    /** Full register */
    uint_io32_t                     u32Register;
    /** Bits and Bit fields */
    stc_mpu_regionnumber_field_t    stcField;
    /** Standard fields */
    uint_io8_t                      au8Byte[4];
    uint_io16_t                     au16Halfword[2];
} un_mpu_regionnumber_t;

/** \brief Bits and Bit fields in Coprocessor MPU Type Register */
typedef struct stc_mpu_type_field
{
    /** \brief type of MPU regions
     ** Specifies the type of MPU regions, unified or separate, in the processor.
     ** Always set to 0, the processor has unified memory regions.
     **/
    uint_io32_t u1S :0x01;
    /** reserved (SBZ) */
    uint_io32_t :0x07;
    /** \brief Number of unified MPU regions
     ** Specifies the number of unified MPU regions.
     ** Set to 0, 8 or 12 data MPU regions.
     **/
    uint_io32_t u8DRegion :0x08;
    /** reserved (SBZ) */
    uint_io32_t :0x10;
}stc_mpu_type_field_t;

/** \brief Type for Coprocessor MPU Type Register */
typedef union un_mpu_type
{
    /** Full register */
    uint_io32_t                     u32Register;
    /** Bits and Bit fields */
    stc_mpu_type_field_t            stcField;
    /** Standard fields */
    uint_io8_t                      au8Byte[4];
    uint_io16_t                     au16Halfword[2];
} un_mpu_type_t;

/*****************************************************************************/
/* Local variable definitions ('static')                                     */
/*****************************************************************************/

/*****************************************************************************/
/* Local function prototypes ('static')                                      */
/*****************************************************************************/

/*****************************************************************************/
/* Function implementation - global ('extern') and local ('static')          */
/*****************************************************************************/

/**
 *****************************************************************************
 ** \brief Setup MPU configuration.
 **
 ** \pre Must be in privileged mode.
 **
 ** \param [in]  pstcConfig         MPU configuration parameters.See #stc_mem_mpu_config_t.
 ** 
 ** \retval Ok                      Set of MPU configuration successfully done.
 ** \retval ErrorAccessRights       Function was not called in privileged (system) mode.
 ** \retval ErrorInvalidParameter   pstcConfig == NULL or invalid memory type.
 *****************************************************************************/
en_result_t Mem_SetMpuConfig(const stc_mem_mpu_config_t* pstcConfig)
{
    boolean_t               bPrivilegedMode;
    un_mpu_control_t        unMpuControl;
    un_mpu_type_t           unMpuType;
    un_mpu_regionsize_t     unMpuRegionsize;
    un_mpu_regionaccess_t   unMpuAccess;
    uint8_t                 u8SubDisbale;
    uint32_t                i, j;

    bPrivilegedMode = Cpu_CpuIsInPrivilegedMode();
    if (bPrivilegedMode == FALSE)
    {
        return ErrorAccessRights;
    }

    if (pstcConfig == NULL)
    {
        return ErrorInvalidParameter;
    }

    /* Disable MPU core */
    unMpuControl.u32Register = CPU_GET_SYSTEMCONTROL(); /* Read CP15 register 1 */
    DSB();                                              /* Ensure the completion of memory accesses, */
    unMpuControl.stcField.u1M = 0;                      /* Disable MPU */
    CPU_SET_SYSTEMCONTROL(unMpuControl.u32Register);    /* Copy settings back to CP15 */
    ISB();                                              /* Instruction Synchronization Barrier */

    /* Get number of the undefined MPU regions */
    unMpuType.u32Register = CPU_GET_MPU_TYPE();
    for (i = 0; i < unMpuType.stcField.u8DRegion; i++)
    {
        if (pstcConfig->astcRegion[i].bEnable == TRUE)
        {
            /* Select MPU region number for configuration */
            CPU_SET_MPU_REGIONNUMBER(i);
            /* Set region base address */
            CPU_SET_MPU_REGIONBASE(pstcConfig->astcRegion[i].u32StartAddress);
            /* Set region size and enable */
            unMpuRegionsize.u32Register = CPU_GET_MPU_REGIONSIZE_ENABLE();
            unMpuRegionsize.stcField.u5RegionSize =
                    pstcConfig->astcRegion[i].enRegionSize;
            unMpuRegionsize.stcField.u1Enable = 1;

            /* Setting of sub region disable bits */
            u8SubDisbale = 0;
            for (j = 0; j < MEM_MPU_SUB_REGION_NUM; j++)
            {
                u8SubDisbale |= (pstcConfig->astcRegion[i].aenSubDisables[j] << j);
            }
            unMpuRegionsize.stcField.u8SubRegionDisable = u8SubDisbale;

            CPU_SET_MPU_REGIONSIZE_ENABLE(unMpuRegionsize.u32Register);
            /* Set region access control */
            unMpuAccess.u32Register = CPU_GET_MPU_REGIONACCESS();
            unMpuAccess.stcField.u3AP =
                    pstcConfig->astcRegion[i].enAccessPermission;
            unMpuAccess.stcField.u1B =
                    pstcConfig->astcRegion[i].stcRegionAttributes.enMainMemAttribute
                            & 0x1;
            unMpuAccess.stcField.u1C =
                    (pstcConfig->astcRegion[i].stcRegionAttributes.enMainMemAttribute
                            & 0x2) >> 1;
            unMpuAccess.stcField.u3TEX =
                    (pstcConfig->astcRegion[i].stcRegionAttributes.enMainMemAttribute
                            & 0x1c) >> 2;
            unMpuAccess.stcField.u1S =
                    pstcConfig->astcRegion[i].stcRegionAttributes.enShareAttribute;
            unMpuAccess.stcField.u1XN =
                    pstcConfig->astcRegion[i].enExecNever;
            /* In case user has selected different cache policies, the settings above are overwritten */
            if (pstcConfig->astcRegion[i].stcRegionAttributes.enMainMemAttribute
                    == MemMpuRegionMainAttribNormalDiffCachePolicy)
            {
                /* Inner policy is defined in C and B bits */
                unMpuAccess.stcField.u1B =
                        pstcConfig->astcRegion[i].stcRegionAttributes.enInnerCachePolicy
                                & 0x1;
                unMpuAccess.stcField.u1C =
                        (pstcConfig->astcRegion[i].stcRegionAttributes.enInnerCachePolicy
                                & 0x2) >> 1;
                /* Outer policy is defined in lower TEX bits */
                unMpuAccess.stcField.u3TEX |=
                        pstcConfig->astcRegion[i].stcRegionAttributes.enOuterCachePolicy;
            }
            CPU_SET_MPU_REGIONACCESS(unMpuAccess.u32Register);
        } else
        {
            /* Select MPU region number for configuration */
            CPU_SET_MPU_REGIONNUMBER(i);
            /* Set region disable */
            unMpuRegionsize.u32Register = CPU_GET_MPU_REGIONSIZE_ENABLE();
            unMpuRegionsize.stcField.u1Enable = 0;
            CPU_SET_MPU_REGIONSIZE_ENABLE(unMpuRegionsize.u32Register);
        }
    }

    /* Check whether enable MPU */
    if (pstcConfig->bEnableMpu == TRUE)
    {
        /* Enable MPU core */
        unMpuControl.u32Register = CPU_GET_SYSTEMCONTROL(); /* Read CP15 register 1 */
        DSB();                                              /* Ensure the completion of memory accesses, */
        unMpuControl.stcField.u1M = 1;                      /* Enable MPU */
        unMpuControl.stcField.u1BR =
                (pstcConfig->bEnableBackgroundRegion == TRUE) ? 1 : 0;
                                                            /* Enable or Disable MPU background region */
        CPU_SET_SYSTEMCONTROL(unMpuControl.u32Register);    /* Copy settings back to CP15 */
        ISB();                                              /* Instruction Synchronization Barrier. */
    }

    return Ok;
}


/**
 *****************************************************************************
 ** \brief Get MPU configuration.
 **
 ** \pre Must be in privileged mode
 **
 ** \param [out] pstcConfig         MPU configuration parameters. See #stc_mem_mpu_config_t.
 ** 
 ** \retval Ok                      MPU configuration parameter successfully read.
 ** \retval ErrorAccessRights       Function was not called in privileged (system) mode.
 ** \retval ErrorInvalidParameter   pstcConfig == NULL or invalid memory type.
 *****************************************************************************/
en_result_t Mem_GetMpuConfig(stc_mem_mpu_config_t* pstcConfig)
{
    boolean_t               bPrivilegedMode;
    un_mpu_control_t        unMpuControl;
    un_mpu_type_t           unMpuType;
    un_mpu_regionsize_t     unMpuRegionsize;
    un_mpu_regionaccess_t   unMpuAccess;
    uint32_t                i, j;
    
    bPrivilegedMode = Cpu_CpuIsInPrivilegedMode();
    if (bPrivilegedMode == FALSE)
    {
        return ErrorAccessRights;
    }
    
    if (pstcConfig == NULL)
    {
        return ErrorInvalidParameter;
    }

    unMpuControl.u32Register = CPU_GET_SYSTEMCONTROL();         /* Read CP15 register 1 */
    pstcConfig->bEnableMpu =
            (unMpuControl.stcField.u1M == 1)? TRUE : FALSE;     /* Get MPU Enbable state */
    pstcConfig->bEnableBackgroundRegion =
            (unMpuControl.stcField.u1BR == 1)? TRUE : FALSE;    /* Get MPU background region state */

    /* Get number of the undefined MPU regions */
    unMpuType.u32Register = CPU_GET_MPU_TYPE();
    for (i = 0; i < unMpuType.stcField.u8DRegion; i++)
    {
        /* Select MPU region number for configuration */
        CPU_SET_MPU_REGIONNUMBER(i);
        /* Get region base address */
        pstcConfig->astcRegion[i].u32StartAddress = CPU_GET_MPU_REGIONBASE();
        /* Get region size and enable */
        unMpuRegionsize.u32Register = CPU_GET_MPU_REGIONSIZE_ENABLE();
        pstcConfig->astcRegion[i].enRegionSize =
                (en_mem_mpu_region_size_t) unMpuRegionsize.stcField.u5RegionSize;
        pstcConfig->astcRegion[i].bEnable =
                (unMpuRegionsize.stcField.u1Enable == 1) ? TRUE : FALSE;
        /* Setting of sub region disable bits */
        for (j = 0; j < MEM_MPU_SUB_REGION_NUM; j++)
        {
            pstcConfig->astcRegion[i].aenSubDisables[j] =
                    (en_mem_mpu_region_sub_disable_t)((unMpuRegionsize.stcField.u8SubRegionDisable >> j) & 0x01);
        }

        /* Get region access control */
        unMpuAccess.u32Register = CPU_GET_MPU_REGIONACCESS();
        pstcConfig->astcRegion[i].enAccessPermission = (en_mem_mpu_access_permission_t)unMpuAccess.stcField.u3AP;
        /* Build up the enum value from the 3 related bit fields */
        if ((unMpuAccess.stcField.u3TEX & 0x4) == 0)
        {
            pstcConfig->astcRegion[i].stcRegionAttributes.enMainMemAttribute =
                    (en_mem_mpu_region_main_attrib_t)
                     ((unMpuAccess.stcField.u3TEX << 2) |
                      (unMpuAccess.stcField.u1C << 1)   |
                      (unMpuAccess.stcField.u1B));
        }
        /* In case of different cache policy the statement above cannot be used */
        /* because C, B, and lower TEX bits have different meaning */
        else
        {
            pstcConfig->astcRegion[i].stcRegionAttributes.enMainMemAttribute = MemMpuRegionMainAttribNormalDiffCachePolicy;
        }
        pstcConfig->astcRegion[i].stcRegionAttributes.enShareAttribute   =
                (en_mem_mpu_region_share_attrib_t) unMpuAccess.stcField.u1S;
        pstcConfig->astcRegion[i].stcRegionAttributes.enOuterCachePolicy =
                (en_mem_mpu_region_cache_attrib_t) (unMpuAccess.stcField.u3TEX & 0x3);
        pstcConfig->astcRegion[i].stcRegionAttributes.enInnerCachePolicy =
                (en_mem_mpu_region_cache_attrib_t) ((unMpuAccess.stcField.u1C << 1) |
                                                    (unMpuAccess.stcField.u1B));
        pstcConfig->astcRegion[i].enExecNever = (en_mem_mpu_region_exec_never_t) unMpuAccess.stcField.u1XN ;

    }
    return Ok;
}



/**
*****************************************************************************
** \brief Set CPU MPU for Graphic register and video memory access
**
** Configures Iris registers as Device Memory so that every Load and Store
** really results in an access to the register and with the programmed access
** size. The video RAM is configured as non-cacheable because it may be
** used as shared memory for CPU and Iris masters.
**
** \warning If other regions are needed as well, the overall MPU handling must be changed!
**
** \param [in]  none
**
** \retval Ok                      Set of MPU configuration successfully done.
** \retval ErrorAccessRights       Function was not called in privileged (system) mode.
** \retval ErrorInvalidParameter   pstcConfig == NULL or invalid memory type.
*****************************************************************************/
en_result_t Mem_SetMpuForGfxSubSystem(void)
{
    stc_mem_mpu_config_t stcMpuConfig = {0};     // clear whole structure to zero (important to disable all regions by default!)
    
    stcMpuConfig.bEnableMpu              = TRUE; // Enable MPU
    stcMpuConfig.bEnableBackgroundRegion = TRUE; // Enable MPU background region (enable default memory map
                                                 // for all addresses not configured in regions)
       
    // Region 0 (Iris registers as "Device Memory")
    stcMpuConfig.astcRegion[0].bEnable            = TRUE;                               // Enable memory region 0
    stcMpuConfig.astcRegion[0].enAccessPermission = MemMpuRWPRWNP;                      // Read and write possible in privileged and non privileged mode
    stcMpuConfig.astcRegion[0].u32StartAddress    = 0x50200000u;                        // Region start address = Start of Iris registers
    stcMpuConfig.astcRegion[0].enRegionSize       = MemMpuRegionSize2MB;                // Region size (buffer size)
    stcMpuConfig.astcRegion[0].stcRegionAttributes.enMainMemAttribute = MemMpuRegionMainAttribDeviceNonShareable;   // device memory type
    stcMpuConfig.astcRegion[0].stcRegionAttributes.enShareAttribute   = MemMpuRegionShareAttribNonShareable;        // Non-shareable

    // Region 1 (Iris video memory as non-cacheable "Normal Memory")
    stcMpuConfig.astcRegion[1].bEnable            = TRUE;                               // Enable memory region 1
    stcMpuConfig.astcRegion[1].enAccessPermission = MemMpuRWPRWNP;                      // Read and write possible in privileged and non privileged mode
    stcMpuConfig.astcRegion[1].u32StartAddress    = 0x50000000u;                        // Region start address = Start of video memory
    stcMpuConfig.astcRegion[1].enRegionSize       = MemMpuRegionSize2MB;                // Region size (buffer size)
    stcMpuConfig.astcRegion[1].stcRegionAttributes.enMainMemAttribute = MemMpuRegionMainAttribNormalNonCacheable;   // Normal memory, non-cacheable
    stcMpuConfig.astcRegion[1].stcRegionAttributes.enShareAttribute   = MemMpuRegionShareAttribShareable;           // Memory region is shareable
    
    return Mem_SetMpuConfig (&stcMpuConfig);    
}





/*!@} */

#endif /* defined(PDL_PERIPHERAL_MEM_ACTIVE) */
/*****************************************************************************/
/* EOF (not truncated)                                                       */
/*****************************************************************************/
