mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-27 06:34:11 +08:00
ARCv2: IOC: Adhere to progamming model guidelines to avoid DMA corruption
On AXS103 release bitfiles, DMA data corruptions were seen because IOC setup was not following the recommended way in documentation. Flipping IOC on when caches are enabled or coherency transactions are in flight, might cause some of the memory operations to not observe coherency as expected. So strictly follow the programming model recommendations as documented in comment header above arc_ioc_setup() Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
This commit is contained in:
parent
d4911cdd32
commit
8c47f83ba4
@ -67,7 +67,7 @@ extern unsigned long perip_base, perip_end;
|
||||
#define ARC_REG_IC_PTAG_HI 0x1F
|
||||
|
||||
/* Bit val in IC_CTRL */
|
||||
#define IC_CTRL_CACHE_DISABLE 0x1
|
||||
#define IC_CTRL_DIS 0x1
|
||||
|
||||
/* Data cache related Auxiliary registers */
|
||||
#define ARC_REG_DC_BCR 0x72 /* Build Config reg */
|
||||
@ -80,7 +80,8 @@ extern unsigned long perip_base, perip_end;
|
||||
#define ARC_REG_DC_PTAG_HI 0x5F
|
||||
|
||||
/* Bit val in DC_CTRL */
|
||||
#define DC_CTRL_INV_MODE_FLUSH 0x40
|
||||
#define DC_CTRL_DIS 0x001
|
||||
#define DC_CTRL_INV_MODE_FLUSH 0x040
|
||||
#define DC_CTRL_FLUSH_STATUS 0x100
|
||||
|
||||
/*System-level cache (L2 cache) related Auxiliary registers */
|
||||
|
@ -462,6 +462,21 @@ static inline void __dc_entire_op(const int op)
|
||||
__after_dc_op(op);
|
||||
}
|
||||
|
||||
static inline void __dc_disable(void)
|
||||
{
|
||||
const int r = ARC_REG_DC_CTRL;
|
||||
|
||||
__dc_entire_op(OP_FLUSH_N_INV);
|
||||
write_aux_reg(r, read_aux_reg(r) | DC_CTRL_DIS);
|
||||
}
|
||||
|
||||
static void __dc_enable(void)
|
||||
{
|
||||
const int r = ARC_REG_DC_CTRL;
|
||||
|
||||
write_aux_reg(r, read_aux_reg(r) & ~DC_CTRL_DIS);
|
||||
}
|
||||
|
||||
/* For kernel mappings cache operation: index is same as paddr */
|
||||
#define __dc_line_op_k(p, sz, op) __dc_line_op(p, p, sz, op)
|
||||
|
||||
@ -487,6 +502,8 @@ static inline void __dc_line_op(phys_addr_t paddr, unsigned long vaddr,
|
||||
#else
|
||||
|
||||
#define __dc_entire_op(op)
|
||||
#define __dc_disable()
|
||||
#define __dc_enable()
|
||||
#define __dc_line_op(paddr, vaddr, sz, op)
|
||||
#define __dc_line_op_k(paddr, sz, op)
|
||||
|
||||
@ -961,12 +978,41 @@ SYSCALL_DEFINE3(cacheflush, uint32_t, start, uint32_t, sz, uint32_t, flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* IO-Coherency (IOC) setup rules:
|
||||
*
|
||||
* 1. Needs to be at system level, so only once by Master core
|
||||
* Non-Masters need not be accessing caches at that time
|
||||
* - They are either HALT_ON_RESET and kick started much later or
|
||||
* - if run on reset, need to ensure that arc_platform_smp_wait_to_boot()
|
||||
* doesn't perturb caches or coherency unit
|
||||
*
|
||||
* 2. caches (L1 and SLC) need to be purged (flush+inv) before setting up IOC,
|
||||
* otherwise any straggler data might behave strangely post IOC enabling
|
||||
*
|
||||
* 3. All Caches need to be disabled when setting up IOC to elide any in-flight
|
||||
* Coherency transactions
|
||||
*/
|
||||
noinline void arc_ioc_setup(void)
|
||||
{
|
||||
/* Flush + invalidate + disable L1 dcache */
|
||||
__dc_disable();
|
||||
|
||||
/* Flush + invalidate SLC */
|
||||
if (read_aux_reg(ARC_REG_SLC_BCR))
|
||||
slc_entire_op(OP_FLUSH_N_INV);
|
||||
|
||||
/* IOC Aperture start: TDB: handle non default CONFIG_LINUX_LINK_BASE */
|
||||
write_aux_reg(ARC_REG_IO_COH_AP0_BASE, 0x80000);
|
||||
|
||||
/* IOC Aperture size: TBD: handle different mem sizes, PAE... */
|
||||
write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, 0x11);
|
||||
|
||||
write_aux_reg(ARC_REG_IO_COH_PARTIAL, 1);
|
||||
write_aux_reg(ARC_REG_IO_COH_ENABLE, 1);
|
||||
|
||||
/* Re-enable L1 dcache */
|
||||
__dc_enable();
|
||||
}
|
||||
|
||||
void arc_cache_init(void)
|
||||
|
Loading…
Reference in New Issue
Block a user