增加所有文件
This commit is contained in:
177
drivers/source/scr/sdrv_scr.c
Normal file
177
drivers/source/scr/sdrv_scr.c
Normal file
@@ -0,0 +1,177 @@
|
||||
|
||||
/**
|
||||
* @file sdrv_scr.c
|
||||
* @brief Semidrive Status and Controller Register driver
|
||||
*
|
||||
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <bits.h>
|
||||
#include <irq.h>
|
||||
#include <reg.h>
|
||||
|
||||
#include "sdrv_scr.h"
|
||||
|
||||
#define SCR_REG_OFF_TYPE_RW 0x1000
|
||||
#define SCR_REG_OFF_TYPE_RO 0x1100
|
||||
#define SCR_REG_OFF_TYPE_L16 0x1200
|
||||
#define SCR_REG_OFF_TYPE_L31 0x1400
|
||||
#define SCR_REG_OFF_TYPE_R16W16 0x1600
|
||||
|
||||
#define BITFIELD_POS_MSK 0x1Fu
|
||||
|
||||
static inline uint32_t _scr_reg_off(uint32_t type)
|
||||
{
|
||||
static const uint32_t reg_off[] = {
|
||||
[TYPE_RW] = SCR_REG_OFF_TYPE_RW,
|
||||
[TYPE_RO] = SCR_REG_OFF_TYPE_RO,
|
||||
[TYPE_L16] = SCR_REG_OFF_TYPE_L16,
|
||||
[TYPE_L31] = SCR_REG_OFF_TYPE_L31,
|
||||
[TYPE_R16W16] = SCR_REG_OFF_TYPE_R16W16,
|
||||
};
|
||||
|
||||
if (type <= TYPE_R16W16)
|
||||
return reg_off[type];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static inline uint32_t _scr_reg(const uint32_t base, const scr_signal_t *signal)
|
||||
{
|
||||
uint32_t reg_off =
|
||||
_scr_reg_off(signal->type) + (signal->start_bit >> 5) * 4;
|
||||
return base + reg_off;
|
||||
}
|
||||
|
||||
static inline uint32_t _scr_read_reg(const uint32_t base,
|
||||
const scr_signal_t *signal)
|
||||
{
|
||||
return readl(_scr_reg(base, signal));
|
||||
}
|
||||
|
||||
static inline void _scr_write_reg(const uint32_t base,
|
||||
const scr_signal_t *signal, uint32_t val)
|
||||
{
|
||||
writel(val, _scr_reg(base, signal));
|
||||
}
|
||||
|
||||
uint32_t scr_get(const sdrv_scr_t *scr, const scr_signal_t *signal)
|
||||
{
|
||||
ASSERT(scr != NULL && signal != NULL);
|
||||
|
||||
uint32_t val = _scr_read_reg(scr->base, signal);
|
||||
uint32_t start_bit = signal->start_bit & BITFIELD_POS_MSK;
|
||||
|
||||
return (val >> start_bit) & BIT_MASK(signal->width);
|
||||
}
|
||||
|
||||
status_t scr_set(const sdrv_scr_t *scr, const scr_signal_t *signal,
|
||||
uint32_t value)
|
||||
{
|
||||
ASSERT(scr != NULL && signal != NULL);
|
||||
|
||||
uint32_t start_bit;
|
||||
uint32_t val;
|
||||
irq_state_t state;
|
||||
|
||||
start_bit = signal->start_bit & BITFIELD_POS_MSK;
|
||||
value &= BIT_MASK(signal->width);
|
||||
|
||||
if (signal->type == TYPE_L16 || signal->type == TYPE_L31) {
|
||||
if (scr_is_locked(scr, signal))
|
||||
return SDRV_SCR_LOCKED;
|
||||
} else if (signal->type == TYPE_RO) {
|
||||
return SDRV_SCR_CANNOT_WRITE;
|
||||
} else if (signal->type == TYPE_R16W16) {
|
||||
if (start_bit >= 16)
|
||||
return SDRV_SCR_CANNOT_WRITE;
|
||||
}
|
||||
|
||||
state = arch_irq_save();
|
||||
|
||||
val = _scr_read_reg(scr->base, signal);
|
||||
val &= ~(BIT_MASK(signal->width) << start_bit);
|
||||
val |= value << start_bit;
|
||||
_scr_write_reg(scr->base, signal, val);
|
||||
|
||||
arch_irq_restore(state);
|
||||
|
||||
return SDRV_STATUS_OK;
|
||||
}
|
||||
|
||||
status_t scr_lock(const sdrv_scr_t *scr, const scr_signal_t *signal)
|
||||
{
|
||||
ASSERT(scr != NULL && signal != NULL);
|
||||
|
||||
uint32_t start_bit;
|
||||
uint32_t val;
|
||||
irq_state_t state;
|
||||
status_t ret;
|
||||
|
||||
if (scr_is_locked(scr, signal)) {
|
||||
return SDRV_SCR_LOCKED;
|
||||
}
|
||||
|
||||
start_bit = signal->start_bit & BITFIELD_POS_MSK;
|
||||
ret = SDRV_SCR_CANNOT_LOCK;
|
||||
|
||||
switch (signal->type) {
|
||||
case TYPE_L16:
|
||||
if (start_bit < 16) {
|
||||
state = arch_irq_save();
|
||||
|
||||
val = _scr_read_reg(scr->base, signal);
|
||||
val |= BIT_MASK(signal->width) << (start_bit + 16);
|
||||
_scr_write_reg(scr->base, signal, val);
|
||||
|
||||
arch_irq_restore(state);
|
||||
ret = SDRV_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case TYPE_L31:
|
||||
if (start_bit < 31) {
|
||||
state = arch_irq_save();
|
||||
|
||||
val = _scr_read_reg(scr->base, signal);
|
||||
val |= 1ul << 31;
|
||||
_scr_write_reg(scr->base, signal, val);
|
||||
|
||||
arch_irq_restore(state);
|
||||
ret = SDRV_STATUS_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool scr_is_locked(const sdrv_scr_t *scr, const scr_signal_t *signal)
|
||||
{
|
||||
ASSERT(scr != NULL && signal != NULL);
|
||||
|
||||
bool locked = false;
|
||||
|
||||
uint32_t val = _scr_read_reg(scr->base, signal);
|
||||
uint16_t start_bit = signal->start_bit & BITFIELD_POS_MSK;
|
||||
|
||||
switch (signal->type) {
|
||||
case TYPE_L16:
|
||||
if (start_bit < 16)
|
||||
locked = !!(val & (1ul << (start_bit + 16)));
|
||||
break;
|
||||
|
||||
case TYPE_L31:
|
||||
if (start_bit < 31)
|
||||
locked = !!(val & (1ul << 31));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return locked;
|
||||
}
|
||||
Reference in New Issue
Block a user