311 lines
8.7 KiB
C
311 lines
8.7 KiB
C
/*
|
|
* 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
|
|
}
|