Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b5850f8 authored by Vineet Gupta's avatar Vineet Gupta
Browse files

ARC: Support for single cycle Close Coupled Mem (CCM)



* Includes mapping of CCMs in address space
* Annotations to move arbitrary code/data into CCM
* Moving some of the critical code/data into CCM
* Runtime detection/reporting

Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent 9c57564e
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -198,6 +198,33 @@ config ARC_CACHE_PAGES

endif	#ARC_CACHE

config ARC_HAS_ICCM
	bool "Use ICCM"
	help
	  Single Cycle RAMS to store Fast Path Code
	default n

config ARC_ICCM_SZ
	int "ICCM Size in KB"
	default "64"
	depends on ARC_HAS_ICCM

config ARC_HAS_DCCM
	bool "Use DCCM"
	help
	  Single Cycle RAMS to store Fast Path Data
	default n

config ARC_DCCM_SZ
	int "DCCM Size in KB"
	default "64"
	depends on ARC_HAS_DCCM

config ARC_DCCM_BASE
	hex "DCCM map address"
	default "0xA0000000"
	depends on ARC_HAS_DCCM

config ARC_HAS_HW_MPY
	bool "Use Hardware Multiplier (Normal or Faster XMAC)"
	default y
+33 −0
Original line number Diff line number Diff line
@@ -25,6 +25,39 @@
	.size \ name, ASM_PREV_SYM_ADDR(\name)
.endm

/* annotation for data we want in DCCM - if enabled in .config */
.macro ARCFP_DATA nm
#ifdef CONFIG_ARC_HAS_DCCM
	.section .data.arcfp
#else
	.section .data
#endif
	.global \nm
.endm

/* annotation for data we want in DCCM - if enabled in .config */
.macro ARCFP_CODE
#ifdef CONFIG_ARC_HAS_ICCM
	.section .text.arcfp, "ax",@progbits
#else
	.section .text, "ax",@progbits
#endif
.endm

#else	/* !__ASSEMBLY__ */

#ifdef CONFIG_ARC_HAS_ICCM
#define __arcfp_code __attribute__((__section__(".text.arcfp")))
#else
#define __arcfp_code __attribute__((__section__(".text")))
#endif

#ifdef CONFIG_ARC_HAS_DCCM
#define __arcfp_data __attribute__((__section__(".data.arcfp")))
#else
#define __arcfp_data __attribute__((__section__(".data")))
#endif

#endif /* __ASSEMBLY__ */

#endif
+2 −2
Original line number Diff line number Diff line
@@ -149,7 +149,7 @@ VECTOR reserved ; Reserved Exceptions

;##################### Scratch Mem for IRQ stack switching #############

	.section .data		; NOT .global
ARCFP_DATA int1_saved_reg
	.align 32
	.type   int1_saved_reg, @object
	.size   int1_saved_reg, 4
@@ -159,7 +159,7 @@ int1_saved_reg:
/* Each Interrupt level needs it's own scratch */
#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS

	.section .data		; NOT .global
ARCFP_DATA int2_saved_reg
	.type   int2_saved_reg, @object
	.size   int2_saved_reg, 4
int2_saved_reg:
+52 −1
Original line number Diff line number Diff line
@@ -64,6 +64,33 @@ void __init read_arc_build_cfg_regs(void)
	cpu->extn.ext_arith = read_aux_reg(ARC_REG_EXTARITH_BCR);
	cpu->extn.crc = read_aux_reg(ARC_REG_CRC_BCR);

	/* Note that we read the CCM BCRs independent of kernel config
	 * This is to catch the cases where user doesn't know that
	 * CCMs are present in hardware build
	 */
	{
		struct bcr_iccm iccm;
		struct bcr_dccm dccm;
		struct bcr_dccm_base dccm_base;
		unsigned int bcr_32bit_val;

		bcr_32bit_val = read_aux_reg(ARC_REG_ICCM_BCR);
		if (bcr_32bit_val) {
			iccm = *((struct bcr_iccm *)&bcr_32bit_val);
			cpu->iccm.base_addr = iccm.base << 16;
			cpu->iccm.sz = 0x2000 << (iccm.sz - 1);
		}

		bcr_32bit_val = read_aux_reg(ARC_REG_DCCM_BCR);
		if (bcr_32bit_val) {
			dccm = *((struct bcr_dccm *)&bcr_32bit_val);
			cpu->dccm.sz = 0x800 << (dccm.sz);

			READ_BCR(ARC_REG_DCCMBASE_BCR, dccm_base);
			cpu->dccm.base_addr = dccm_base.addr << 8;
		}
	}

	READ_BCR(ARC_REG_XY_MEM_BCR, cpu->extn_xymem);

	read_decode_mmu_bcr();
@@ -211,6 +238,30 @@ char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
	return buf;
}

void __init arc_chk_ccms(void)
{
#if defined(CONFIG_ARC_HAS_DCCM) || defined(CONFIG_ARC_HAS_ICCM)
	struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];

#ifdef CONFIG_ARC_HAS_DCCM
	/*
	 * DCCM can be arbit placed in hardware.
	 * Make sure it's placement/sz matches what Linux is built with
	 */
	if ((unsigned int)__arc_dccm_base != cpu->dccm.base_addr)
		panic("Linux built with incorrect DCCM Base address\n");

	if (CONFIG_ARC_DCCM_SZ != cpu->dccm.sz)
		panic("Linux built with incorrect DCCM Size\n");
#endif

#ifdef CONFIG_ARC_HAS_ICCM
	if (CONFIG_ARC_ICCM_SZ != cpu->iccm.sz)
		panic("Linux built with incorrect ICCM Size\n");
#endif
#endif
}

/*
 * Ensure that FP hardware and kernel config match
 * -If hardware contains DPFP, kernel needs to save/restore FPU state
@@ -255,7 +306,7 @@ void __init setup_processor(void)

	arc_mmu_init();
	arc_cache_init();

	arc_chk_ccms();

	printk(arc_extn_mumbojumbo(cpu_id, str, sizeof(str)));

+21 −0
Original line number Diff line number Diff line
@@ -23,6 +23,12 @@ jiffies = jiffies_64;

SECTIONS
{
	/*
	 * ICCM starts at 0x8000_0000. So if kernel is relocated to some other
	 * address, make sure peripheral at 0x8z doesn't clash with ICCM
	 * Essentially vector is also in ICCM.
	 */

	. = CONFIG_LINUX_LINK_BASE;

	_int_vec_base_lds = .;
@@ -31,6 +37,13 @@ SECTIONS
		. = ALIGN(PAGE_SIZE);
	}

#ifdef CONFIG_ARC_HAS_ICCM
	.text.arcfp : {
		*(.text.arcfp)
		. = ALIGN(CONFIG_ARC_ICCM_SZ * 1024);
	}
#endif

	/*
	 * The reason for having a seperate subsection .init.ramfs is to
	 * prevent objump from including it in kernel dumps
@@ -134,4 +147,12 @@ SECTIONS
	.debug_loc 0 : { *(.debug_loc) }
	.debug_macinfo 0 : { *(.debug_macinfo) }

#ifdef CONFIG_ARC_HAS_DCCM
	. = CONFIG_ARC_DCCM_BASE;
	__arc_dccm_base = .;
	.data.arcfp : {
		*(.data.arcfp)
	}
	. = ALIGN(CONFIG_ARC_DCCM_SZ * 1024);
#endif
}
Loading