noinline void __init arc_ioc_setup()

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();
}