Skip to content

Commit

Permalink
ARCv2: SLC: provide a line based flush routine for debugging
Browse files Browse the repository at this point in the history
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
  • Loading branch information
Vineet Gupta committed Aug 30, 2017
1 parent 9f82e90 commit ae0b63d
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
2 changes: 2 additions & 0 deletions arch/arc/include/asm/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ extern unsigned long perip_base, perip_end;
#define ARC_REG_SLC_CTRL 0x903
#define ARC_REG_SLC_FLUSH 0x904
#define ARC_REG_SLC_INVALIDATE 0x905
#define ARC_AUX_SLC_IVDL 0x910
#define ARC_AUX_SLC_FLDL 0x912
#define ARC_REG_SLC_RGN_START 0x914
#define ARC_REG_SLC_RGN_START1 0x915
#define ARC_REG_SLC_RGN_END 0x916
Expand Down
54 changes: 53 additions & 1 deletion arch/arc/mm/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ static void __ic_line_inv_vaddr(phys_addr_t paddr, unsigned long vaddr,

#endif /* CONFIG_ARC_HAS_ICACHE */

noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op)
noinline void slc_op_rgn(phys_addr_t paddr, unsigned long sz, const int op)
{
#ifdef CONFIG_ISA_ARCV2
/*
Expand Down Expand Up @@ -715,6 +715,58 @@ noinline void slc_op(phys_addr_t paddr, unsigned long sz, const int op)
#endif
}

noinline void slc_op_line(phys_addr_t paddr, unsigned long sz, const int op)
{
#ifdef CONFIG_ISA_ARCV2
/*
* SLC is shared between all cores and concurrent aux operations from
* multiple cores need to be serialized using a spinlock
* A concurrent operation can be silently ignored and/or the old/new
* operation can remain incomplete forever (lockup in SLC_CTRL_BUSY loop
* below)
*/
static DEFINE_SPINLOCK(lock);

const unsigned long SLC_LINE_MASK = ~(l2_line_sz - 1);
unsigned int ctrl, cmd;
unsigned long flags;
int num_lines;

spin_lock_irqsave(&lock, flags);

ctrl = read_aux_reg(ARC_REG_SLC_CTRL);

/* Don't rely on default value of IM bit */
if (!(op & OP_FLUSH)) /* i.e. OP_INV */
ctrl &= ~SLC_CTRL_IM; /* clear IM: Disable flush before Inv */
else
ctrl |= SLC_CTRL_IM;

write_aux_reg(ARC_REG_SLC_CTRL, ctrl);

cmd = op & OP_INV ? ARC_AUX_SLC_IVDL : ARC_AUX_SLC_FLDL;

sz += paddr & ~SLC_LINE_MASK;
paddr &= SLC_LINE_MASK;

num_lines = DIV_ROUND_UP(sz, l2_line_sz);

while (num_lines-- > 0) {
write_aux_reg(cmd, paddr);
paddr += l2_line_sz;
}

/* Make sure "busy" bit reports correct stataus, see STAR 9001165532 */
read_aux_reg(ARC_REG_SLC_CTRL);

while (read_aux_reg(ARC_REG_SLC_CTRL) & SLC_CTRL_BUSY);

spin_unlock_irqrestore(&lock, flags);
#endif
}

#define slc_op(paddr, sz, op) slc_op_rgn(paddr, sz, op)

noinline static void slc_entire_op(const int op)
{
unsigned int ctrl, r = ARC_REG_SLC_CTRL;
Expand Down

0 comments on commit ae0b63d

Please sign in to comment.