blob: 651c50dcb0abdf7c46a60f586537339fc5fbf9d2 [file] [log] [blame]
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: GPL-2.0+
*/
/*!
* @file hal/inc/fsl_mu_hal.h
*
* Header file containing HAL API for the MU.
*
* @addtogroup MU_HAL (HAL) MU Hardware Abstraction Layer
*
* Module for low-level MU hardware access.
*
* @{
*/
#ifndef __FSL_MU_HAL_H__
#define __FSL_MU_HAL_H__
#include <asm/imx-common/sci/scfw.h>
#ifdef DEBUG
#include <assert.h>
#else
#define assert(x) ((void) 0)
#endif
#include <asm/arch/fsl_device_registers.h>
#if FSL_FEATURE_SOC_MU_COUNT
/* Defines */
/*!
* This define is used to access MU registers.
*/
#define DSC_MU_BASE_ADDR(X, Y) ((MU_Type *) (((uint32_t) DSC_BASE_ADDR(X)) \
+ 0xC000 + (0x80 * Y)))
/******************************************************************************
* Definitions
*****************************************************************************/
/*!@brief Bit mask for general purpose interrupt 0 pending. */
#define MU_SR_GIP0_MASK (1U<<31U)
/*!@brief Bit mask for RX full interrupt 0 pending. */
#define MU_SR_RF0_MASK (1U<<27U)
/*!@brief Bit mask for TX empty interrupt 0 pending. */
#define MU_SR_TE0_MASK (1U<<23U)
/*!@brief Bit mask for general purpose interrupt 0 enable. */
#define MU_CR_GIE0_MASK (1U<<31U)
/*!@brief Bit mask for RX full interrupt 0 enable. */
#define MU_CR_RIE0_MASK (1U<<27U)
/*!@brief Bit mask for TX empty interrupt 0 enable. */
#define MU_CR_TIE0_MASK (1U<<23U)
/*!@brief Bit mask to trigger general purpose interrupt 0. */
#define MU_CR_GIR0_MASK (1U<<19U)
/*!@brief Number of general purpose interrupt. */
#define MU_GPn_COUNT (4U)
/* Mask for MU_CR_GIRN and MU_CR_NMI. When read-modify-write to MU_CR, should
pay attention to these bits in case of trigger interrupts by mistake.*/
#define MU_CR_GIRn_NMI_MASK (MU_CR_GIRn_MASK | MU_CR_NMI_MASK)
/*!
* @brief MU status return codes.
*/
typedef enum _mu_status {
kStatus_MU_Success = 0U, /*!< Success. */
kStatus_MU_TxNotEmpty = 1U, /*!< TX register is not empty. */
kStatus_MU_RxNotFull = 2U, /*!< RX register is not full. */
kStatus_MU_FlagPending = 3U, /*!< Previous flags update pending. */
kStatus_MU_EventPending = 4U, /*!< MU event is pending. */
kStatus_MU_Initialized = 5U, /*!< MU driver has initialized previously. */
kStatus_MU_IntPending = 6U, /*!< Previous general interrupt still pending. */
kStatus_MU_Failed = 7U /*!< Execution failed. */
} mu_status_t;
/*!
* @brief MU message status.
*/
typedef enum _mu_msg_status {
kMuTxEmpty0 = MU_SR_TE0_MASK, /*!< TX0 empty status. */
kMuTxEmpty1 = MU_SR_TE0_MASK >> 1U, /*!< TX1 empty status. */
kMuTxEmpty2 = MU_SR_TE0_MASK >> 2U, /*!< TX2 empty status. */
kMuTxEmpty3 = MU_SR_TE0_MASK >> 3U, /*!< TX3 empty status. */
kMuTxEmpty = kMuTxEmpty0 |
kMuTxEmpty1 |
kMuTxEmpty2 |
kMuTxEmpty3, /*!< TX empty status. */
kMuRxFull0 = MU_SR_RF0_MASK, /*!< RX0 full status. */
kMuRxFull1 = MU_SR_RF0_MASK >> 1U, /*!< RX1 full status. */
kMuRxFull2 = MU_SR_RF0_MASK >> 2U, /*!< RX2 full status. */
kMuRxFull3 = MU_SR_RF0_MASK >> 3U, /*!< RX3 full status. */
kMuRxFull = kMuRxFull0 |
kMuRxFull1 |
kMuRxFull2 |
kMuRxFull3, /*!< RX empty status. */
kMuGenInt0 = MU_SR_GIP0_MASK, /*!< General purpose interrupt 0 pending status. */
kMuGenInt1 = MU_SR_GIP0_MASK >> 1U, /*!< General purpose interrupt 2 pending status. */
kMuGenInt2 = MU_SR_GIP0_MASK >> 2U, /*!< General purpose interrupt 2 pending status. */
kMuGenInt3 = MU_SR_GIP0_MASK >> 3U, /*!< General purpose interrupt 3 pending status. */
kMuGenInt = kMuGenInt0 |
kMuGenInt1 |
kMuGenInt2 |
kMuGenInt3, /*!< General purpose interrupt pending status. */
kMuStatusAll = kMuTxEmpty |
kMuRxFull |
kMuGenInt, /*!< All MU status. */
} mu_msg_status_t;
/*!
* @brief Core boot configuration.
*/
typedef enum _mu_core_boot_config {
kMuCoreBootFromDmem = 0x01U, /*!< Boot from DMEM base. */
kMuCoreBootFromImem = 0x02U, /*!< Boot from IMEM base. */
kMuCoreBootFrom0 = 0x03U, /*!< Boot from 0x00. */
} mu_core_boot_config_t;
/*!
* @brief Power mode definition.
*/
typedef enum _mu_power_mode {
kMuPowerModeRun = 0x00U, /*!< Run mode. */
kMuPowerModeWait = 0x01U, /*!< WAIT mode. */
kMuPowerModeStop = 0x02U, /*!< STOP mode. */
kMuPowerModeDsm = 0x03U, /*!< DSM mode. */
} mu_power_mode_t;
/*******************************************************************************
* API
******************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif
/*!
* @name Initialization Functions
* @{
*/
/*!
* @brief Initializes the MU module to reset state.
*
* This function sets the MU module control register to its default reset value.
*
* @param base Register base address for the module.
*/
static inline void MU_HAL_Init(MU_Type *base)
{
/* Clear GIEn, RIEn, TIEn, GIRn and ABFn. */
MU_WR_CR(base, (MU_RD_CR(base)
& ~(MU_CR_GIEn_MASK |
MU_CR_RIEn_MASK |
MU_CR_TIEn_MASK |
MU_CR_GIRn_MASK |
MU_CR_Fn_MASK)));
}
/* @} */
/*!
* @name Send Message Functions
* @{
*/
/*!
* @brief Try to send a message.
*
* This function tries to send a message, if the RX register is not empty,
* this function returns kStatus_MU_TxNotEmpty.
*
* @param base Register base address for the module.
* @param regIdex Tx register index.
* @param msg Message to send.
* @retval kStatus_MU_Success Message send successfully.
* @retval kStatus_MU_TxNotEmpty Message not send because TX is not empty.
*/
mu_status_t MU_HAL_TrySendMsg(MU_Type *base, uint32_t regIndex, uint32_t msg);
/*!
* @brief Block to send a message.
*
* This function waits until TX register is empty and send the message.
*
* @param base Register base address for the module.
* @param regIdex Tx register index.
* @param msg Message to send.
*/
void MU_HAL_SendMsg(MU_Type *base, uint32_t regIndex, uint32_t msg);
/*!
* @brief Check TX empty status.
*
* This function checks the specific tramsmit register empty status.
*
* @param base Register base address for the module.
* @param index TX register index to check.
* @retval true TX register is empty.
* @retval false TX register is not empty.
*/
static inline bool MU_HAL_IsTxEmpty(MU_Type *base, uint32_t index)
{
return (bool)(MU_RD_SR(base) & (MU_SR_TE0_MASK >> index));
}
/*!
* @brief Enable TX empty interrupt.
*
* This function enables specific TX empty interrupt.
*
* @param base Register base address for the module.
* @param index TX interrupt index to enable.
*
* Example:
@code
// To enable TX0 empty interrupts.
MU_HAL_EnableTxEmptyInt(MU0_BASE, 0U);
@endcode
*/
static inline void MU_HAL_EnableTxEmptyInt(MU_Type *base, uint32_t index)
{
MU_WR_CR(base, (MU_RD_CR(base)
& ~MU_CR_GIRn_NMI_MASK) /* Clear GIRn and NMI */
| (MU_CR_TIE0_MASK>>index)); /* Set TIEn */
}
/*!
* @brief Disable TX empty interrupt.
*
* This function disables specific TX empty interrupt.
*
* @param base Register base address for the module.
* @param disableMask Bitmap of the interrupts to disable.
*
* Example:
@code
// To disable TX0 empty interrupts.
MU_HAL_DisableTxEmptyInt(MU0_BASE, 0U);
@endcode
*/
static inline void MU_HAL_DisableTxEmptyInt(MU_Type *base, uint32_t index)
{
MU_WR_CR(base, (MU_RD_CR(base)
& ~MU_CR_GIRn_NMI_MASK) /* Clear GIRn and NMI */
& ~(MU_CR_TIE0_MASK>>index)); /* Clear TIEn */
}
/* @} */
/*!
* @name Receive Message Functions
* @{
*/
/*!
* @brief Try to receive a message.
*
* This function tries to receive a message, if the RX register is not full,
* this function returns kStatus_MU_RxNotFull.
*
* @param base Register base address for the module.
* @param regIdex Rx register index.
* @param msg Message to receive.
* @retval kStatus_MU_Success Message receive successfully.
* @retval kStatus_MU_RxNotFull Message not received because RX is not full.
*/
mu_status_t MU_HAL_TryReceiveMsg(MU_Type *base, uint32_t regIndex, uint32_t *msg);
/*!
* @brief Block to receive a message.
*
* This function waits until RX register is full and receive the message.
*
* @param base Register base address for the module.
* @param regIdex Rx register index.
* @param msg Message to receive.
*/
void MU_HAL_ReceiveMsg(MU_Type *base, uint32_t regIndex, uint32_t *msg);
/*!
* @brief Check RX full status.
*
* This function checks the specific receive register full status.
*
* @param base Register base address for the module.
* @param index RX register index to check.
* @retval true RX register is full.
* @retval false RX register is not full.
*/
static inline bool MU_HAL_IsRxFull(MU_Type *base, uint32_t index)
{
return (bool)(MU_RD_SR(base) & (MU_SR_RF0_MASK >> index));
}
/*!
* @brief Enable RX full interrupt.
*
* This function enables specific RX full interrupt.
*
* @param base Register base address for the module.
* @param index RX interrupt index to enable.
*
* Example:
@code
// To enable RX0 full interrupts.
MU_HAL_EnableRxFullInt(MU0_BASE, 0U);
@endcode
*/
static inline void MU_HAL_EnableRxFullInt(MU_Type *base, uint32_t index)
{
MU_WR_CR(base, (MU_RD_CR(base)
& ~MU_CR_GIRn_NMI_MASK) /* Clear GIRn and NMI */
| (MU_CR_RIE0_MASK>>index)); /* Set RIEn */
}
/*!
* @brief Disable RX full interrupt.
*
* This function disables specific RX full interrupt.
*
* @param base Register base address for the module.
* @param disableMask Bitmap of the interrupts to disable.
*
* Example:
@code
// To disable RX0 full interrupts.
MU_HAL_DisableRxFullInt(MU0_BASE, 0U);
@endcode
*/
static inline void MU_HAL_DisableRxFullInt(MU_Type *base, uint32_t index)
{
MU_WR_CR(base, (MU_RD_CR(base)
& ~MU_CR_GIRn_NMI_MASK) /* Clear GIRn and NMI */
& ~(MU_CR_RIE0_MASK>>index)); /* Clear RIEn */
}
/* @} */
/*!
* @name General Purpose Interrupt Functions
* @{
*/
/*!
* @brief Enable general purpose interrupt.
*
* This function enables specific general purpose interrupt.
*
* @param base Register base address for the module.
* @param index General purpose interrupt index to enable.
*
* Example:
@code
// To enable general purpose interrupts 0.
MU_HAL_EnableGeneralInt(MU0_BASE, 0U);
@endcode
*/
static inline void MU_HAL_EnableGeneralInt(MU_Type *base, uint32_t index)
{
MU_WR_CR(base, (MU_RD_CR(base)
& ~MU_CR_GIRn_NMI_MASK) /* Clear GIRn and NMI */
| (MU_CR_GIE0_MASK>>index)); /* Set GIEn */
}
/*!
* @brief Disable general purpose interrupt.
*
* This function disables specific general purpose interrupt.
*
* @param base Register base address for the module.
* @param index General purpose interrupt index to disable.
*
* Example:
@code
// To disable general purpose interrupts 0.
MU_HAL_DisableGeneralInt(MU0_BASE, 0U);
@endcode
*/
static inline void MU_HAL_DisableGeneralInt(MU_Type *base, uint32_t index)
{
MU_WR_CR(base, (MU_RD_CR(base)
& ~MU_CR_GIRn_NMI_MASK) /* Clear GIRn and NMI */
& ~(MU_CR_GIE0_MASK>>index)); /* Clear GIEn */
}
/*!
* @brief Check specific general purpose interrupt pending flag.
*
* This function checks the specific general purpose interrupt pending status.
*
* @param base Register base address for the module.
* @param index Index of the general purpose interrupt flag to check.
* @retval true General purpose interrupt is pending.
* @retval false General purpose interrupt is not pending.
*/
static inline bool MU_HAL_IsGeneralIntPending(MU_Type *base, uint32_t index)
{
return (bool)(MU_RD_SR(base) & (MU_SR_GIP0_MASK >> index));
}
/*!
* @brief Clear specific general purpose interrupt pending flag.
*
* This function clears the specific general purpose interrupt pending status.
*
* @param base Register base address for the module.
* @param index Index of the general purpose interrupt flag to clear.
*/
static inline void MU_HAL_ClearGeneralIntPending(MU_Type *base, uint32_t index)
{
MU_WR_SR(base, MU_SR_GIP0_MASK >> index);
}
/*!
* @brief Trigger specific general purpose interrupt.
*
* This function triggers specific general purpose interrupt to other core.
*
* To ensure proper operations, please make sure the correspond general purpose
* interrupt triggerd previously has been accepted by the other core. The
* function MU_HAL_IsGeneralIntAccepted could be used for this check. If the
* previous general interrupt has not been accepted by the other core, this
* function does not trigger interrupt acctually and returns error.
*
* @param base Register base address for the module.
* @param index Index of general purpose interrupt to trigger.
* @retval kStatus_MU_Success Interrupt has been triggered successfully.
* @retval kStatus_MU_IntPending Previous interrupt has not been accepted.
*/
mu_status_t MU_HAL_TriggerGeneralInt(MU_Type *base, uint32_t index);
/*!
* @brief Check specific general purpose interrupt is accepted or not.
*
* This function checks whether the specific general purpose interrupt has
* been accepted by the other core or not.
*
* @param base Register base address for the module.
* @param index Index of the general purpose interrupt to check.
* @retval true General purpose interrupt is accepted.
* @retval false General purpose interrupt is not accepted.
*/
static inline bool MU_HAL_IsGeneralIntAccepted(MU_Type *base, uint32_t index)
{
return !(bool)(MU_RD_CR(base) & (MU_CR_GIR0_MASK >> index));
}
/* @} */
/*!
* @name Non-maskable Interrupt (NMI) Functions
* @{
*/
/*!
* @brief Trigger non-maskable interrupt (NMI) to the other core.
*
* This functions triggers the NMI to the other core.
*
* @param base Register base address for the module.
*/
static inline void MU_HAL_TriggerNmi(MU_Type *base)
{
MU_WR_CR_NMI(base, 1U);
}
/*!
* @brief Get non-maskable interrupt (NMI) trigger status.
*
* This functions get the NMI trigger status. It is used to check whether the NMI
* triggered by the function MU_HAL_TriggerNmi has been accepted by the other
* core. When the NMI has been accepted by the other core, MU_HAL_TriggerNmi
* could be used to trigger another NMI.
*
* @param base Register base address for the module.
* @retval true NMI is issued and not accepted by the other core.
* @retval false NMI is not issued or has been accepted by the other core.
*/
static inline bool MU_HAL_IsNmiIssued(MU_Type *base)
{
return (bool)MU_RD_CR_NMI(base);
}
/* @} */
/*!
* @name Flag Functions
* @{
*/
/*!
* @brief Try to set some bits of the 3-bit flag reflect on the other MU side.
*
* This functions tries to set some bits of the 3-bit flag. If previous flags
* update is still pending, this function returns kStatus_MU_FlagPending.
*
* @param base Register base address for the module.
* @retval kStatus_MU_Success Flag set successfully.
* @retval kStatus_MU_FlagPending Previous flag update is pending.
*/
mu_status_t MU_HAL_TrySetFlags(MU_Type *base, uint32_t flags);
/*!
* @brief Set some bits of the 3-bit flag reflect on the other MU side.
*
* This functions set some bits of the 3-bit flag. If previous flags update is
* still pending, this function will block and poll to set the flag.
*
* @param base Register base address for the module.
*/
void MU_HAL_SetFlags(MU_Type *base, uint32_t flags);
/*!
* @brief Checks whether the previous flag update is pending.
*
* After setting flags, the flags update request is pending untill internally
* acknowledged. During the pending period, it is not allowed to set flags again.
* This function is used to check the pending status, it could be used together
* with function MU_HAL_TrySetFlags.
*
* @param base Register base address for the module.
* @return True if pending, faulse if not.
*/
static inline bool MU_HAL_IsFlagPending(MU_Type *base)
{
return (bool)MU_RD_SR_FUP(base);
}
/*!
* @brief Get the current value of the 3-bit flag set by other side.
*
* This functions gets the current value of the 3-bit flag.
*
* @param base Register base address for the module.
* @return flags Current value of the 3-bit flag.
*/
static inline uint32_t MU_HAL_GetFlags(MU_Type *base)
{
return MU_RD_SR_Fn(base);
}
/* @} */
/*!
* @name Misc. Functions
* @{
*/
/*!
* @brief Reset MU for both A side and B side.
*
* This function resets MU for both A side and B side. Before reset, it is
* recommend to interrupt processor B, because this function may affect the
* ongoing processor B program.
*
* @param base Register base address for the module.
* @note Only MU side A could use this function.
*/
static inline void MU_HAL_Reset(MU_Type *base)
{
MU_WR_CR_MUR(base, 1U);
}
/*!
* @brief Get the power mode of the other core.
*
* This functions gets the power mode of the other core.
*
* @param base Register base address for the module.
* @return powermode Power mode of the other core.
*/
static inline mu_power_mode_t MU_HAL_GetOtherCorePowerMode(MU_Type *base)
{
return (mu_power_mode_t)MU_RD_SR_PM(base);
}
/*!
* @brief Get the event pending status.
*
* This functions gets the event pending status. To ensure events have been
* posted to the other side before entering STOP mode, please verify the
* event pending status using this function.
*
* @param base Register base address for the module.
* @retval true Event is pending.
* @retval false Event is not pending.
*/
static inline bool MU_HAL_IsEventPending(MU_Type *base)
{
return (bool)MU_RD_SR_EP(base);
}
/*!
* @brief Get the the MU message status.
*
* This functions gets TX/RX and general purpose interrupt pending status. The
* parameter is passed in as bitmask of the status to check.
*
* @param base Register base address for the module.
* @param statusToCheck The status to check, see mu_msg_status_t.
* @return Status checked.
*
* Example:
@code
// To check TX0 empty status.
MU_HAL_GetMsgStatus(MU0_BASE, kMuTxEmpty0);
// To check all RX full status.
MU_HAL_GetMsgStatus(MU0_BASE, kMuRxFull);
// To check general purpose interrupt 0 and 3 pending status.
MU_HAL_GetMsgStatus(MU0_BASE, kMuGenInt0 | kMuGenInt3);
// To check all status.
MU_HAL_GetMsgStatus(MU0_BASE, kMuStatusAll);
@endcode
*/
static inline uint32_t MU_HAL_GetMsgStatus(MU_Type *base, uint32_t statusToCheck)
{
return MU_RD_SR(base) & statusToCheck;
}
/* @} */
#if defined(__cplusplus)
}
#endif
/*!
* @}
*/
#endif
#endif /* __FSL_MU_HAL_H__ */
/******************************************************************************
* EOF
*****************************************************************************/