| /* |
| * Copyright 2017-2020 NXP |
| * All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include "fsl_rdc.h" |
| |
| /****************************************************************************** |
| * Definitions |
| *****************************************************************************/ |
| |
| /* Component ID definition, used by tools. */ |
| #ifndef FSL_COMPONENT_ID |
| #define FSL_COMPONENT_ID "platform.drivers.rdc" |
| #endif |
| |
| typedef union |
| { |
| rdc_domain_assignment_t _mda; |
| uint32_t _u32; |
| } rdc_mda_reg_t; |
| |
| typedef union |
| { |
| rdc_hardware_config_t _vir; |
| uint32_t _u32; |
| } rdc_vir_reg_t; |
| |
| /******************************************************************************* |
| * Prototypes |
| ******************************************************************************/ |
| |
| /*! |
| * @brief Get instance number for RDC module. |
| * |
| * @param base RDC peripheral base address. |
| */ |
| uint32_t RDC_GetInstance(RDC_Type *base); |
| |
| /******************************************************************************* |
| * Variables |
| ******************************************************************************/ |
| |
| /*! @brief Pointers to rdc bases for each instance. */ |
| static RDC_Type *const s_rdcBases[] = RDC_BASE_PTRS; |
| |
| #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
| /*! @brief Pointers to rdc clocks for each instance. */ |
| static const clock_ip_name_t s_rdcClocks[] = RDC_CLOCKS; |
| #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
| |
| /****************************************************************************** |
| * CODE |
| *****************************************************************************/ |
| |
| uint32_t RDC_GetInstance(RDC_Type *base) |
| { |
| uint32_t instance; |
| |
| /* Find the instance index from base address mappings. */ |
| for (instance = 0; instance < ARRAY_SIZE(s_rdcBases); instance++) |
| { |
| if (s_rdcBases[instance] == base) |
| { |
| break; |
| } |
| } |
| |
| assert(instance < ARRAY_SIZE(s_rdcBases)); |
| |
| return instance; |
| } |
| |
| /*! |
| * brief Initializes the RDC module. |
| * |
| * This function enables the RDC clock. |
| * |
| * param base RDC peripheral base address. |
| */ |
| void RDC_Init(RDC_Type *base) |
| { |
| #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
| CLOCK_EnableClock(s_rdcClocks[RDC_GetInstance(base)]); |
| #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
| } |
| |
| /*! |
| * brief De-initializes the RDC module. |
| * |
| * This function disables the RDC clock. |
| * |
| * param base RDC peripheral base address. |
| */ |
| void RDC_Deinit(RDC_Type *base) |
| { |
| #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) |
| CLOCK_DisableClock(s_rdcClocks[RDC_GetInstance(base)]); |
| #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */ |
| } |
| |
| /*! |
| * brief Gets the RDC hardware configuration. |
| * |
| * This function gets the RDC hardware configurations, including number of bus |
| * masters, number of domains, number of memory regions and number of peripherals. |
| * |
| * param base RDC peripheral base address. |
| * param config Pointer to the structure to get the configuration. |
| */ |
| void RDC_GetHardwareConfig(RDC_Type *base, rdc_hardware_config_t *config) |
| { |
| assert(NULL != config); |
| |
| rdc_vir_reg_t vir; |
| vir._u32 = base->VIR; |
| |
| *config = vir._vir; |
| } |
| |
| /*! |
| * brief Set master domain assignment |
| * |
| * param base RDC peripheral base address. |
| * param master Which master to set. |
| * param domainAssignment Pointer to the assignment. |
| */ |
| void RDC_SetMasterDomainAssignment(RDC_Type *base, rdc_master_t master, const rdc_domain_assignment_t *domainAssignment) |
| { |
| assert((uint32_t)master < RDC_MDA_COUNT); |
| |
| rdc_mda_reg_t mda; |
| |
| mda._mda = *domainAssignment; |
| |
| base->MDA[master] = mda._u32; |
| } |
| |
| /*! |
| * brief Get default master domain assignment |
| * |
| * The default configuration is: |
| * code |
| assignment->domainId = 0U; |
| assignment->lock = 0U; |
| endcode |
| * |
| * param domainAssignment Pointer to the assignment. |
| */ |
| void RDC_GetDefaultMasterDomainAssignment(rdc_domain_assignment_t *domainAssignment) |
| { |
| assert(NULL != domainAssignment); |
| |
| rdc_mda_reg_t mda; |
| mda._u32 = 0U; |
| |
| *domainAssignment = mda._mda; |
| } |
| |
| /*! |
| * brief Set peripheral access policy. |
| * |
| * param base RDC peripheral base address. |
| * param config Pointer to the policy configuration. |
| */ |
| void RDC_SetPeriphAccessConfig(RDC_Type *base, const rdc_periph_access_config_t *config) |
| { |
| assert((uint32_t)config->periph < RDC_PDAP_COUNT); |
| |
| uint32_t periph = (uint32_t)config->periph; |
| uint32_t regPDAP = config->policy; |
| |
| if (config->lock) |
| { |
| regPDAP |= RDC_PDAP_LCK_MASK; |
| } |
| |
| if (config->enableSema) |
| { |
| regPDAP |= RDC_PDAP_SREQ_MASK; |
| } |
| |
| base->PDAP[periph] = regPDAP; |
| |
| __DSB(); |
| } |
| |
| /*! |
| * brief Get default peripheral access policy. |
| * |
| * The default configuration is: |
| * code |
| config->lock = false; |
| config->enableSema = false; |
| config->policy = RDC_ACCESS_POLICY(0, kRDC_ReadWrite) | |
| RDC_ACCESS_POLICY(1, kRDC_ReadWrite) | |
| RDC_ACCESS_POLICY(2, kRDC_ReadWrite) | |
| RDC_ACCESS_POLICY(3, kRDC_ReadWrite); |
| endcode |
| * |
| * param config Pointer to the policy configuration. |
| */ |
| void RDC_GetDefaultPeriphAccessConfig(rdc_periph_access_config_t *config) |
| { |
| assert(NULL != config); |
| |
| /* Initializes the configure structure to zero. */ |
| (void)memset(config, 0, sizeof(*config)); |
| |
| config->lock = false; |
| config->enableSema = false; |
| config->policy = RDC_ACCESS_POLICY(0U, kRDC_ReadWrite) | RDC_ACCESS_POLICY(1U, kRDC_ReadWrite) | |
| RDC_ACCESS_POLICY(2U, kRDC_ReadWrite) | RDC_ACCESS_POLICY(3U, kRDC_ReadWrite); |
| } |
| |
| /*! |
| * brief Set memory region access policy. |
| * |
| * Note that when setting the baseAddress and endAddress in p config, |
| * should be aligned to the region resolution, see rdc_mem_t |
| * definitions. |
| * |
| * param base RDC peripheral base address. |
| * param config Pointer to the policy configuration. |
| */ |
| void RDC_SetMemAccessConfig(RDC_Type *base, const rdc_mem_access_config_t *config) |
| { |
| assert((uint32_t)config->mem < RDC_MRC_COUNT); |
| |
| uint32_t mem = (uint32_t)config->mem; |
| /* The configuration is enabled by default. */ |
| uint32_t regMRC = config->policy | RDC_MRC_ENA_MASK; |
| |
| if (config->lock) |
| { |
| regMRC |= RDC_MRC_LCK_MASK; |
| } |
| |
| #if (defined(FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT) && FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT) |
| base->MR[mem].MRSA = (uint32_t)(config->baseAddress >> (uint32_t)FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT); |
| base->MR[mem].MREA = (uint32_t)(config->endAddress >> (uint32_t)FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT); |
| #else |
| base->MR[mem].MRSA = (uint32_t)config->baseAddress; |
| base->MR[mem].MREA = (uint32_t)config->endAddress; |
| #endif |
| base->MR[mem].MRC = regMRC; |
| |
| __DSB(); |
| } |
| |
| /*! |
| * brief Get default memory region access policy. |
| * |
| * The default configuration is: |
| * code |
| config->lock = false; |
| config->baseAddress = 0; |
| config->endAddress = 0; |
| config->policy = RDC_ACCESS_POLICY(0, kRDC_ReadWrite) | |
| RDC_ACCESS_POLICY(1, kRDC_ReadWrite) | |
| RDC_ACCESS_POLICY(2, kRDC_ReadWrite) | |
| RDC_ACCESS_POLICY(3, kRDC_ReadWrite); |
| endcode |
| * |
| * param config Pointer to the policy configuration. |
| */ |
| void RDC_GetDefaultMemAccessConfig(rdc_mem_access_config_t *config) |
| { |
| assert(NULL != config); |
| |
| /* Initializes the configure structure to zero. */ |
| (void)memset(config, 0, sizeof(*config)); |
| |
| config->lock = false; |
| config->baseAddress = 0; |
| config->endAddress = 0; |
| config->policy = RDC_ACCESS_POLICY(0U, kRDC_ReadWrite) | RDC_ACCESS_POLICY(1U, kRDC_ReadWrite) | |
| RDC_ACCESS_POLICY(2U, kRDC_ReadWrite) | RDC_ACCESS_POLICY(3U, kRDC_ReadWrite); |
| } |
| |
| /*! |
| * brief Get the memory region violation status. |
| * |
| * The first access violation is captured. Subsequent violations are ignored |
| * until the status register is cleared. Contents are cleared upon reading the |
| * register. Clearing of contents occurs only when the status is read by the |
| * memory region's associated domain ID(s). |
| * |
| * param base RDC peripheral base address. |
| * param mem Which memory region to get. |
| * param status The returned status. |
| */ |
| void RDC_GetMemViolationStatus(RDC_Type *base, rdc_mem_t mem, rdc_mem_status_t *status) |
| { |
| assert((uint32_t)mem < RDC_MRC_COUNT); |
| |
| uint32_t regMRVS = base->MR[mem].MRVS; |
| |
| status->hasViolation = ((regMRVS & RDC_MRVS_AD_MASK) != 0U); |
| status->domainID = (uint8_t)((regMRVS & RDC_MRVS_VDID_MASK) >> RDC_MRVS_VDID_SHIFT); |
| #if (defined(FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT) && FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT) |
| regMRVS &= RDC_MRVS_VADR_MASK; |
| status->address = ((uint64_t)regMRVS) << (uint32_t)FSL_FEATURE_RDC_MEM_REGION_ADDR_SHIFT; |
| #else |
| regMRVS &= RDC_MRVS_VADR_MASK; |
| status->address = (uint64_t)regMRVS; |
| #endif |
| } |