use small lock to protect register about l2cc, involving the following files:
arch/arm/src/armv7-a/arm_l2cc_pl310.c arch/arm/src/armv7-r/arm_l2cc_pl310.c arch/arm/src/armv8-r/arm_l2cc_pl310.c Signed-off-by: wangzhi16 <wangzhi16@xiaomi.com>
This commit is contained in:
parent
575c608be8
commit
f179cb81b5
3 changed files with 291 additions and 156 deletions
|
@ -38,6 +38,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "barriers.h"
|
||||
|
@ -225,6 +226,12 @@
|
|||
|
||||
#define PL310_GULP_SIZE 4096
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static spinlock_t g_l2cc_lock = SP_UNLOCKED;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -262,6 +269,66 @@ static void pl310_flush_all(void)
|
|||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_disable_nolock
|
||||
*
|
||||
* Description:
|
||||
* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR)
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_disable_nolock(void)
|
||||
{
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
pl310_flush_all();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_invalidate_all_nolock
|
||||
*
|
||||
* Description:
|
||||
* Invalidate all ways using the Invalidate Way Register (IWR).
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_invalidate_all_nolock(void)
|
||||
{
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -457,18 +524,18 @@ void l2cc_enable(void)
|
|||
|
||||
/* Invalidate and enable the cache (must be disabled to do this!) */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
if ((getreg32(L2CC_CR) & L2CC_CR_L2CEN) != 0)
|
||||
{
|
||||
l2cc_disable();
|
||||
l2cc_disable_nolock();
|
||||
}
|
||||
|
||||
l2cc_invalidate_all();
|
||||
l2cc_invalidate_all_nolock();
|
||||
putreg32(L2CC_CR_L2CEN, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -489,17 +556,11 @@ void l2cc_disable(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
pl310_flush_all();
|
||||
l2cc_disable_nolock();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -525,9 +586,9 @@ void l2cc_sync(void)
|
|||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -548,27 +609,11 @@ void l2cc_invalidate_all(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Invalidate all ways */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
l2cc_invalidate_all_nolock();
|
||||
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -595,7 +640,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Check if the start address is aligned with a cacheline */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
if ((startaddr & PL310_CACHE_LINE_MASK) != 0)
|
||||
{
|
||||
/* No.. align down and flush the cache line by writing the address to
|
||||
|
@ -622,7 +667,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
putreg32(endaddr, L2CC_CIPALR);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
|
||||
/* Loop, invalidated the address range by cache line. Interrupts are re-
|
||||
* enabled momentarily every PL310_GULP_SIZE bytes.
|
||||
|
@ -640,7 +685,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and invalidate the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Invalidate the cache line by writing the address to the
|
||||
|
@ -656,16 +701,16 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -690,7 +735,7 @@ void l2cc_clean_all(void)
|
|||
* Ways Register (CWR).
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(PL310_WAY_MASK, L2CC_CWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
@ -702,7 +747,7 @@ void l2cc_clean_all(void)
|
|||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -758,7 +803,7 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and clean the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Clean the cache line by writing the address to the Clean
|
||||
|
@ -774,16 +819,16 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -806,9 +851,9 @@ void l2cc_flush_all(void)
|
|||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
pl310_flush_all();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -864,7 +909,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Disable interrupts and flush the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Flush the cache line by writing the address to the Clean
|
||||
|
@ -880,16 +925,16 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARMV7A_L2CC_PL310 */
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "barriers.h"
|
||||
|
@ -225,6 +226,12 @@
|
|||
|
||||
#define PL310_GULP_SIZE 4096
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static volatile spinlock_t g_l2cc_lock = SP_UNLOCKED;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -262,6 +269,66 @@ static void pl310_flush_all(void)
|
|||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_disable_nolock
|
||||
*
|
||||
* Description:
|
||||
* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR)
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_disable_nolock(void)
|
||||
{
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
pl310_flush_all();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_invalidate_all_nolock
|
||||
*
|
||||
* Description:
|
||||
* Invalidate all ways using the Invalidate Way Register (IWR).
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_invalidate_all_nolock(void)
|
||||
{
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -457,18 +524,18 @@ void l2cc_enable(void)
|
|||
|
||||
/* Invalidate and enable the cache (must be disabled to do this!) */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
if ((getreg32(L2CC_CR) & L2CC_CR_L2CEN) != 0)
|
||||
{
|
||||
l2cc_disable();
|
||||
l2cc_disable_nolock();
|
||||
}
|
||||
|
||||
l2cc_invalidate_all();
|
||||
l2cc_invalidate_all_nolock();
|
||||
putreg32(L2CC_CR_L2CEN, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -489,17 +556,11 @@ void l2cc_disable(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
pl310_flush_all();
|
||||
l2cc_disable_nolock();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -525,9 +586,9 @@ void l2cc_sync(void)
|
|||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -548,27 +609,11 @@ void l2cc_invalidate_all(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Invalidate all ways */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
l2cc_invalidate_all_nolock();
|
||||
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -595,7 +640,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Check if the start address is aligned with a cacheline */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
if ((startaddr & PL310_CACHE_LINE_MASK) != 0)
|
||||
{
|
||||
/* No.. align down and flush the cache line by writing the address to
|
||||
|
@ -622,7 +667,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
putreg32(endaddr, L2CC_CIPALR);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
|
||||
/* Loop, invalidated the address range by cache line. Interrupts are re-
|
||||
* enabled momentarily every PL310_GULP_SIZE bytes.
|
||||
|
@ -640,7 +685,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and invalidate the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Invalidate the cache line by writing the address to the
|
||||
|
@ -656,16 +701,16 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -690,7 +735,7 @@ void l2cc_clean_all(void)
|
|||
* Ways Register (CWR).
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(PL310_WAY_MASK, L2CC_CWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
@ -702,7 +747,7 @@ void l2cc_clean_all(void)
|
|||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -758,7 +803,7 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and clean the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Clean the cache line by writing the address to the Clean
|
||||
|
@ -774,16 +819,16 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -806,9 +851,9 @@ void l2cc_flush_all(void)
|
|||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
pl310_flush_all();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -864,7 +909,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Disable interrupts and flush the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Flush the cache line by writing the address to the Clean
|
||||
|
@ -880,16 +925,16 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARMV7R_L2CC_PL310 */
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/spinlock.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
#include "barriers.h"
|
||||
|
@ -225,6 +226,12 @@
|
|||
|
||||
#define PL310_GULP_SIZE 4096
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static volatile spinlock_t g_l2cc_lock = SP_UNLOCKED;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
@ -262,6 +269,66 @@ static void pl310_flush_all(void)
|
|||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_disable_nolock
|
||||
*
|
||||
* Description:
|
||||
* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR)
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_disable_nolock(void)
|
||||
{
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
pl310_flush_all();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: l2cc_invalidate_all_nolock
|
||||
*
|
||||
* Description:
|
||||
* Invalidate all ways using the Invalidate Way Register (IWR).
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void l2cc_invalidate_all_nolock(void)
|
||||
{
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -457,18 +524,18 @@ void l2cc_enable(void)
|
|||
|
||||
/* Invalidate and enable the cache (must be disabled to do this!) */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
if ((getreg32(L2CC_CR) & L2CC_CR_L2CEN) != 0)
|
||||
{
|
||||
l2cc_disable();
|
||||
l2cc_disable_nolock();
|
||||
}
|
||||
|
||||
l2cc_invalidate_all();
|
||||
l2cc_invalidate_all_nolock();
|
||||
putreg32(L2CC_CR_L2CEN, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -489,17 +556,11 @@ void l2cc_disable(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
pl310_flush_all();
|
||||
l2cc_disable_nolock();
|
||||
|
||||
/* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */
|
||||
|
||||
putreg32(0, L2CC_CR);
|
||||
ARM_DSB();
|
||||
ARM_ISB();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -525,9 +586,9 @@ void l2cc_sync(void)
|
|||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -548,27 +609,11 @@ void l2cc_invalidate_all(void)
|
|||
{
|
||||
irqstate_t flags;
|
||||
|
||||
/* Invalidate all ways */
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
|
||||
flags = enter_critical_section();
|
||||
l2cc_invalidate_all_nolock();
|
||||
|
||||
/* Invalidate all ways by writing the bit mask of ways to be invalidated
|
||||
* the Invalidate Way Register (IWR).
|
||||
*/
|
||||
|
||||
putreg32(PL310_WAY_MASK, L2CC_IWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
||||
while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0);
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -595,7 +640,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Check if the start address is aligned with a cacheline */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
if ((startaddr & PL310_CACHE_LINE_MASK) != 0)
|
||||
{
|
||||
/* No.. align down and flush the cache line by writing the address to
|
||||
|
@ -622,7 +667,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
putreg32(endaddr, L2CC_CIPALR);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
|
||||
/* Loop, invalidated the address range by cache line. Interrupts are re-
|
||||
* enabled momentarily every PL310_GULP_SIZE bytes.
|
||||
|
@ -640,7 +685,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and invalidate the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Invalidate the cache line by writing the address to the
|
||||
|
@ -656,16 +701,16 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -690,7 +735,7 @@ void l2cc_clean_all(void)
|
|||
* Ways Register (CWR).
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(PL310_WAY_MASK, L2CC_CWR);
|
||||
|
||||
/* Wait for cache operation by way to complete */
|
||||
|
@ -702,7 +747,7 @@ void l2cc_clean_all(void)
|
|||
*/
|
||||
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -758,7 +803,7 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Disable interrupts and clean the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Clean the cache line by writing the address to the Clean
|
||||
|
@ -774,16 +819,16 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -806,9 +851,9 @@ void l2cc_flush_all(void)
|
|||
|
||||
/* Flush all ways using the Clean Invalidate Way Register (CIWR). */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
pl310_flush_all();
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -864,7 +909,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Disable interrupts and flush the gulp */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
while (startaddr < gulpend)
|
||||
{
|
||||
/* Flush the cache line by writing the address to the Clean
|
||||
|
@ -880,16 +925,16 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr)
|
|||
|
||||
/* Enable interrupts momentarily */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
/* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and
|
||||
* EB, are empty.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave(&g_l2cc_lock);
|
||||
putreg32(0, L2CC_CSR);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(&g_l2cc_lock, flags);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARMV8R_L2CC_PL310 */
|
||||
|
|
Loading…
Reference in a new issue