diff --git a/bsps/shared/grlib/l2c/l2c.c b/bsps/shared/grlib/l2c/l2c.c index 9e2d135179..366301dc90 100644 --- a/bsps/shared/grlib/l2c/l2c.c +++ b/bsps/shared/grlib/l2c/l2c.c @@ -40,6 +40,10 @@ #include #include +#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); diff --git a/bsps/sparc/leon3/include/bsp/leon3.h b/bsps/sparc/leon3/include/bsp/leon3.h index 650e2db744..df36e043bd 100644 --- a/bsps/sparc/leon3/include/bsp/leon3.h +++ b/bsps/sparc/leon3/include/bsp/leon3.h @@ -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 diff --git a/bsps/sparc/leon3/start/cache.c b/bsps/sparc/leon3/start/cache.c index 11af2f4d01..2978848667 100644 --- a/bsps/sparc/leon3/start/cache.c +++ b/bsps/sparc/leon3/start/cache.c @@ -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(®s->l2cs); + status = l2c_load_32(®s->l2cs); ways = L2CACHE_L2CS_WAY_GET(status) + 1; set_size = L2CACHE_L2CS_WAY_SIZE_GET(status) * 1024;