sparc/leon3: Add leon3_l2c_lock

Use a single lock for all L2C support functions.

Close #4925.
This commit is contained in:
Sebastian Huber
2024-11-20 04:25:41 +01:00
committed by Kinsey Moore
parent 7d5c08db80
commit e53dfabe36
3 changed files with 38 additions and 13 deletions

View File

@@ -40,6 +40,10 @@
#include <grlib/l2c.h>
#include <grlib/grlib_impl.h>
#if RTEMS_INTERRUPT_LOCK_NEEDS_OBJECT
extern rtems_interrupt_lock leon3_l2c_lock;
#endif
/*#define STATIC*/
#define STATIC static
@@ -318,8 +322,6 @@ struct l2cache_priv {
int ft_support;
int split_support;
int atomic_flush;
/* Avoid concurrent accesses to L2C registers. */
SPIN_DECLARE(devlock);
/* User defined ISR */
l2cache_isr_t isr;
@@ -387,22 +389,20 @@ static char * repl_names[4] = {"LRU","Random","Master-Idx-1","Master-IDx-2"};
#endif
static void REG_WRITE(volatile unsigned int *addr, unsigned int val) {
struct l2cache_priv *priv = l2cachepriv;
SPIN_IRQFLAGS(irqflags);
SPIN_LOCK_IRQ(&priv->devlock, irqflags);
SPIN_LOCK_IRQ(&leon3_l2c_lock, irqflags);
*addr = val;
SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
SPIN_UNLOCK_IRQ(&leon3_l2c_lock, irqflags);
}
static unsigned int REG_READ(volatile unsigned int *addr) {
struct l2cache_priv *priv = l2cachepriv;
SPIN_IRQFLAGS(irqflags);
unsigned int val;
SPIN_LOCK_IRQ(&priv->devlock, irqflags);
SPIN_LOCK_IRQ(&leon3_l2c_lock, irqflags);
val = *addr;
SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
SPIN_UNLOCK_IRQ(&leon3_l2c_lock, irqflags);
return val;
}
@@ -418,12 +418,11 @@ static inline uint32_t atomic_swap32(uint32_t *addr, uint32_t val) {
}
static void REG_WRITE_ATOMIC(volatile unsigned int *addr, unsigned int val) {
struct l2cache_priv *priv = l2cachepriv;
SPIN_IRQFLAGS(irqflags);
SPIN_LOCK_IRQ(&priv->devlock, irqflags);
SPIN_LOCK_IRQ(&leon3_l2c_lock, irqflags);
atomic_swap32((uint32_t *) addr, val);
SPIN_UNLOCK_IRQ(&priv->devlock, irqflags);
SPIN_UNLOCK_IRQ(&leon3_l2c_lock, irqflags);
}
#else
@@ -541,7 +540,6 @@ int l2cache_init1(struct drvmgr_dev *dev)
priv->dev = dev;
strncpy(&priv->devname[0], "l2cache0", DEVNAME_LEN);
l2cachepriv = priv;
SPIN_INIT(&priv->devlock, priv->devname);
/* Initialize L2CACHE Hardware */
status = l2cache_init(priv);

View File

@@ -378,6 +378,16 @@ typedef struct {
*/
extern leon3_timecounter leon3_timecounter_instance;
#if RTEMS_INTERRUPT_LOCK_NEEDS_OBJECT
/**
* @brief This interrupt lock prevents concurrent access to L2C registers.
*
* This is required as a workaround for the in GR740 errata: Level-2 Cache
* Issues H1 2023 (GRLIB-TN-0021).
*/
extern rtems_interrupt_lock leon3_l2c_lock;
#endif
/** @} */
#ifdef __cplusplus

View File

@@ -37,6 +37,23 @@
#define CPU_DATA_CACHE_ALIGNMENT 64
#if RTEMS_INTERRUPT_LOCK_NEEDS_OBJECT
rtems_interrupt_lock leon3_l2c_lock =
RTEMS_INTERRUPT_LOCK_INITIALIZER( "LEON3 L2C" );
#endif
static inline uint32_t l2c_load_32(const volatile uint32_t *address)
{
rtems_interrupt_lock_context lock_context;
uint32_t value;
rtems_interrupt_lock_acquire(&leon3_l2c_lock, &lock_context);
value = grlib_load_32(address);
rtems_interrupt_lock_release(&leon3_l2c_lock, &lock_context);
return value;
}
#if !defined(LEON3_L2CACHE_BASE)
static inline l2cache *get_l2c_regs(void)
{
@@ -85,7 +102,7 @@ static inline size_t get_l2_size(void)
}
#endif
status = grlib_load_32(&regs->l2cs);
status = l2c_load_32(&regs->l2cs);
ways = L2CACHE_L2CS_WAY_GET(status) + 1;
set_size = L2CACHE_L2CS_WAY_SIZE_GET(status) * 1024;