增加所有文件
This commit is contained in:
287
drivers/source/semag/sdrv_semag.c
Normal file
287
drivers/source/semag/sdrv_semag.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* @file sdrv_semag.c
|
||||
* @brief SemiDrive Semaphore Gate driver source file.
|
||||
*
|
||||
* User should initialize mbox module before using semag driver.
|
||||
*
|
||||
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
#include <compiler.h>
|
||||
#include <debug.h>
|
||||
#include <param.h>
|
||||
#include <reg.h>
|
||||
#include <regs_base.h>
|
||||
#include <sdrv_semag.h>
|
||||
|
||||
#include "sdrv_semag_reg.h"
|
||||
|
||||
/**
|
||||
* brief Read the semag gate's register.
|
||||
*
|
||||
* param [in] offset The address offset of the semag gate's register.
|
||||
* return The value of the register.
|
||||
*/
|
||||
static inline uint32_t sdrv_semag_readl(uint32_t offset)
|
||||
{
|
||||
return readl(MB_REG_BASE + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* brief Write the semag gate's register.
|
||||
*
|
||||
* param [in] offset The address offset of the semag gate's register.
|
||||
*/
|
||||
static inline void sdrv_semag_writel(uint32_t offset, uint32_t value)
|
||||
{
|
||||
writel(value, MB_REG_BASE + offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tries to lock the SEMAG gate.
|
||||
*
|
||||
* This function tries to lock the specific SEMAG gate. If the gate has been
|
||||
* locked by another processor, this function returns an error code.
|
||||
*
|
||||
* @param [in] gate_idx Gate number to lock.
|
||||
* @return SDRV_STATUS_INVALID_PARAM The gate id is unvalid.
|
||||
* SDRV_STATUS_FAIL Semag gate has been locked by another processor.
|
||||
* SDRV_STATUS_OK Lock the semag gate successfully.
|
||||
*/
|
||||
status_t sdrv_semag_trylock(uint32_t gate_idx)
|
||||
{
|
||||
/* If gate id is unvalid. */
|
||||
if (gate_idx >= SDRV_SEMAG_NUM) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
volatile uint32_t val;
|
||||
uint32_t offset;
|
||||
|
||||
/* Get the address offset of current gate id. */
|
||||
offset = SEMAG_OFF(gate_idx);
|
||||
|
||||
/* Lock the semag gate. */
|
||||
val = sdrv_semag_readl(offset);
|
||||
val |= BM_SEMAG_SGC;
|
||||
sdrv_semag_writel(offset, val);
|
||||
|
||||
/* Check the lock status of the gate. */
|
||||
if ((sdrv_semag_readl(offset) & BM_SEMAG_SGC) == BM_SEMAG_SGC) {
|
||||
return SDRV_STATUS_OK;
|
||||
} else {
|
||||
return SDRV_STATUS_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Locks the SEMAG gate.
|
||||
*
|
||||
* This function locks the specific SEMAG gate. If the gate has been
|
||||
* locked by other processors, this function waits until it is unlocked and then
|
||||
* lock it.
|
||||
*
|
||||
* @param [in] gate_idx Gate number to lock.
|
||||
* @return SDRV_STATUS_INVALID_PARAM The gate id is unvalid.
|
||||
* SDRV_STATUS_OK Lock the semag gate successfully.
|
||||
*/
|
||||
status_t sdrv_semag_lock(uint32_t gate_idx)
|
||||
{
|
||||
if (gate_idx >= SDRV_SEMAG_NUM) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
|
||||
uint32_t val;
|
||||
uint32_t offset;
|
||||
|
||||
/* Get the address offset of current gate id. */
|
||||
offset = SEMAG_OFF(gate_idx);
|
||||
|
||||
/* Wait for locking gate successfully. */
|
||||
do {
|
||||
/* Wait for the semag gate to become unlocked. */
|
||||
while ((sdrv_semag_readl(offset) & FM_SEMAG_SGLS) > 0U)
|
||||
;
|
||||
/* Lock the semag gate. */
|
||||
val = sdrv_semag_readl(offset);
|
||||
val |= BM_SEMAG_SGC;
|
||||
sdrv_semag_writel(offset, val);
|
||||
} while (1U != (sdrv_semag_readl(offset) & BM_SEMAG_SGC));
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlocks the SEMAG gate.
|
||||
*
|
||||
* This function unlocks the specific SEMAG gate. It only writes unlock value
|
||||
* to the SEMAG gate register. However, it does not check whether the SEMAG gate
|
||||
* is locked by the current processor or not. As a result, if the SEMAG gate is
|
||||
* not locked by the current processor, this function has no effect.
|
||||
*
|
||||
* @param [in] gate_idx Gate number to unlock.
|
||||
* @return SDRV_STATUS_OK Unlock the semag gate successfully.
|
||||
*/
|
||||
status_t sdrv_semag_unlock(uint32_t gate_idx)
|
||||
{
|
||||
if (gate_idx >= SDRV_SEMAG_NUM) {
|
||||
return SDRV_STATUS_INVALID_PARAM;
|
||||
}
|
||||
uint32_t offset;
|
||||
uint32_t val;
|
||||
|
||||
/* Get the address offset of current gate id. */
|
||||
offset = SEMAG_OFF(gate_idx);
|
||||
|
||||
/* Unlock the semag gate. */
|
||||
val = sdrv_semag_readl(offset);
|
||||
val &= ~BM_SEMAG_SGC;
|
||||
sdrv_semag_writel(offset, val);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the status of the SEMAG gate.
|
||||
*
|
||||
* This function checks the lock status of a specific SEMAG gate.
|
||||
*
|
||||
* @param [in] gate_idx Gate number to check lock status.
|
||||
* @return Return -1 if the gate is unlocked, otherwise return the
|
||||
* processor number which has locked the gate.
|
||||
*/
|
||||
int32_t sdrv_semag_get_lock_proc(uint32_t gate_idx)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t val;
|
||||
|
||||
if (gate_idx < SDRV_SEMAG_NUM) {
|
||||
/* Get the address offset of current gate id. */
|
||||
offset = SEMAG_OFF(gate_idx);
|
||||
|
||||
/* check lock status. */
|
||||
val = sdrv_semag_readl(offset);
|
||||
val = GFV_SEMAG_SGLS(val);
|
||||
for (uint32_t i = 0U; i < SDRV_SEMAG_PROCESSOR_NUM; i++, val >>= 1U) {
|
||||
if ((val & 0x1U) == 0x1U) {
|
||||
return (int32_t)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resets all SEMAG gates to an unlocked status.
|
||||
*
|
||||
* This function resets all SEMAG gate to an unlocked status,
|
||||
* it will only unlock gates which locked by itself, can't reset
|
||||
* gates which locked by other processors.
|
||||
* @return SDRV_STATUS_OK Reset all semag gates successfully.
|
||||
*/
|
||||
status_t sdrv_semag_reset_all_gate(void)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
/* Resets all gates to unlocked state which are locked by current processor.
|
||||
*/
|
||||
val = sdrv_semag_readl(SGR_OFF);
|
||||
val |= BM_SGR_PSGR;
|
||||
sdrv_semag_writel(SGR_OFF, val);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the gate notification interrupt.
|
||||
*
|
||||
* Gate notification provides such feature, when interrupt is enabled, then core
|
||||
* tried to lock the gate and failed, it could get notification when the gate is
|
||||
* idle.
|
||||
*
|
||||
* @param [in] mask Mask of the gate index, for example: (1<<0U) | (1<<1U)
|
||||
* means gate 0 and gate 1.
|
||||
* @return SDRV_STATUS_OK Enable the notify interrupt of the semag gate
|
||||
* successfully.
|
||||
*/
|
||||
status_t sdrv_semag_enable_gate_notify_interrupt(uint32_t mask)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t val;
|
||||
|
||||
for (uint32_t i = 0U; i < SDRV_SEMAG_NUM; i++) {
|
||||
if ((1U << i) & mask) {
|
||||
/* Get the address offset of current gate id. */
|
||||
offset = SEMAG_OFF(i);
|
||||
/* Enable the gate notification interrupt. */
|
||||
val = sdrv_semag_readl(offset);
|
||||
val |= BM_SEMAG_IESGSC;
|
||||
sdrv_semag_writel(offset, val);
|
||||
}
|
||||
}
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the gate notification interrupt.
|
||||
*
|
||||
* Gate notification provides such feature, when interrupt is enabled, then core
|
||||
* tried to lock the gate and failed, it could get notification when the gate is
|
||||
* idle.
|
||||
*
|
||||
* @param [in] mask Mask of the gate index, for example: (1<<0U) | (1<<1U)
|
||||
* means gate 0 and gate 1.
|
||||
* @return SDRV_STATUS_OK Disable the notify interrupt of the semag gate
|
||||
* successfully.
|
||||
*/
|
||||
status_t sdrv_semag_disable_gate_notify_interrupt(uint32_t mask)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t val;
|
||||
|
||||
for (uint32_t i = 0U; i < SDRV_SEMAG_NUM; i++) {
|
||||
if ((1U << i) & mask) {
|
||||
/* Get the address offset of current gate id. */
|
||||
offset = SEMAG_OFF(i);
|
||||
/* Disable the gate notification interrupt. */
|
||||
val = sdrv_semag_readl(offset);
|
||||
val &= ~BM_SEMAG_IESGSC;
|
||||
sdrv_semag_writel(offset, val);
|
||||
}
|
||||
}
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the gate notification flags.
|
||||
*
|
||||
* Gate notification provides such feature, when interrupt is enabled, then core
|
||||
* tried to lock the gate and failed, it could get notification when the gate is
|
||||
* idle.
|
||||
*
|
||||
* @return Mask of the gate index, for example: (1<<0U) | (1<<1U) means
|
||||
* gate 0 and gate 1 flags are pending.
|
||||
*/
|
||||
uint32_t sdrv_semag_get_notify_status(void)
|
||||
{
|
||||
return sdrv_semag_readl(SGI_OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the gate notification interrupt status.
|
||||
*
|
||||
* This function clear SEMAG gate IRQ notifications.
|
||||
*
|
||||
* @param [in] mask Mask of the gate index, for example: (1<<0U) | (1<<1U)
|
||||
* means gate 0 and gate 1.
|
||||
* @return SDRV_STATUS_OK Clear the notify interrupt status of the semag gate
|
||||
* successfully.
|
||||
*/
|
||||
status_t sdrv_semag_clear_notify_status(uint32_t mask)
|
||||
{
|
||||
sdrv_semag_writel(SGI_OFF, mask);
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user