in mm/cache.c [1072:1125]
noinline void __init arc_ioc_setup(void)
{
unsigned int ioc_base, mem_sz;
/*
* If IOC was already enabled (due to bootloader) it technically needs to
* be reconfigured with aperture base,size corresponding to Linux memory map
* which will certainly be different than uboot's. But disabling and
* reenabling IOC when DMA might be potentially active is tricky business.
* To avoid random memory issues later, just panic here and ask user to
* upgrade bootloader to one which doesn't enable IOC
*/
if (read_aux_reg(ARC_REG_IO_COH_ENABLE) & ARC_IO_COH_ENABLE_BIT)
panic("IOC already enabled, please upgrade bootloader!\n");
if (!ioc_enable)
return;
/* 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);
/*
* currently IOC Aperture covers entire DDR
* TBD: fix for PGU + 1GB of low mem
* TBD: fix for PAE
*/
mem_sz = arc_get_mem_sz();
if (!is_power_of_2(mem_sz) || mem_sz < 4096)
panic("IOC Aperture size must be power of 2 larger than 4KB");
/*
* IOC Aperture size decoded as 2 ^ (SIZE + 2) KB,
* so setting 0x11 implies 512MB, 0x12 implies 1GB...
*/
write_aux_reg(ARC_REG_IO_COH_AP0_SIZE, order_base_2(mem_sz >> 10) - 2);
/* for now assume kernel base is start of IOC aperture */
ioc_base = CONFIG_LINUX_RAM_BASE;
if (ioc_base % mem_sz != 0)
panic("IOC Aperture start must be aligned to the size of the aperture");
write_aux_reg(ARC_REG_IO_COH_AP0_BASE, ioc_base >> 12);
write_aux_reg(ARC_REG_IO_COH_PARTIAL, ARC_IO_COH_PARTIAL_BIT);
write_aux_reg(ARC_REG_IO_COH_ENABLE, ARC_IO_COH_ENABLE_BIT);
/* Re-enable L1 dcache */
__dc_enable();
}