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

Commit ef680cdc authored by Vineet Gupta's avatar Vineet Gupta
Browse files

ARC: Disable caches in early boot if so configured



Requested-by: default avatarNoam Camus <noamc@ezchip.com>
Signed-off-by: default avatarVineet Gupta <vgupta@synopsys.com>
parent e87a850b
Loading
Loading
Loading
Loading
+27 −0
Original line number Original line Diff line number Diff line
@@ -55,4 +55,31 @@ extern void read_decode_cache_bcr(void);


#endif	/* !__ASSEMBLY__ */
#endif	/* !__ASSEMBLY__ */


/* Instruction cache related Auxiliary registers */
#define ARC_REG_IC_BCR		0x77	/* Build Config reg */
#define ARC_REG_IC_IVIC		0x10
#define ARC_REG_IC_CTRL		0x11
#define ARC_REG_IC_IVIL		0x19
#if defined(CONFIG_ARC_MMU_V3) || defined (CONFIG_ARC_MMU_V4)
#define ARC_REG_IC_PTAG		0x1E
#endif

/* Bit val in IC_CTRL */
#define IC_CTRL_CACHE_DISABLE   0x1

/* Data cache related Auxiliary registers */
#define ARC_REG_DC_BCR		0x72	/* Build Config reg */
#define ARC_REG_DC_IVDC		0x47
#define ARC_REG_DC_CTRL		0x48
#define ARC_REG_DC_IVDL		0x4A
#define ARC_REG_DC_FLSH		0x4B
#define ARC_REG_DC_FLDL		0x4C
#if defined(CONFIG_ARC_MMU_V3) || defined (CONFIG_ARC_MMU_V4)
#define ARC_REG_DC_PTAG		0x5C
#endif

/* Bit val in DC_CTRL */
#define DC_CTRL_INV_MODE_FLUSH  0x40
#define DC_CTRL_FLUSH_STATUS    0x100

#endif /* _ASM_CACHE_H */
#endif /* _ASM_CACHE_H */
+35 −3
Original line number Original line Diff line number Diff line
@@ -12,10 +12,42 @@
 *      to skip certain things during boot on simulator
 *      to skip certain things during boot on simulator
 */
 */


#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/asm-offsets.h>
#include <asm/entry.h>
#include <asm/entry.h>
#include <linux/linkage.h>
#include <asm/arcregs.h>
#include <asm/arcregs.h>
#include <asm/cache.h>

.macro CPU_EARLY_SETUP

	; Setting up Vectror Table (in case exception happens in early boot
	sr	@_int_vec_base_lds, [AUX_INTR_VEC_BASE]

	; Disable I-cache/D-cache if kernel so configured
	lr	r5, [ARC_REG_IC_BCR]
	breq    r5, 0, 1f		; I$ doesn't exist
	lr	r5, [ARC_REG_IC_CTRL]
#ifdef CONFIG_ARC_HAS_ICACHE
	bclr	r5, r5, 0		; 0 - Enable, 1 is Disable
#else
	bset	r5, r5, 0		; I$ exists, but is not used
#endif
	sr	r5, [ARC_REG_IC_CTRL]

1:
	lr	r5, [ARC_REG_DC_BCR]
	breq    r5, 0, 1f		; D$ doesn't exist
	lr	r5, [ARC_REG_DC_CTRL]
	bclr	r5, r5, 6		; Invalidate (discard w/o wback)
#ifdef CONFIG_ARC_HAS_DCACHE
	bclr	r5, r5, 0		; Enable (+Inv)
#else
	bset	r5, r5, 0		; Disable (+Inv)
#endif
	sr	r5, [ARC_REG_DC_CTRL]

1:
.endm


	.cpu A7
	.cpu A7


@@ -27,7 +59,7 @@ stext:
	; Don't clobber r0-r2 yet. It might have bootloader provided info
	; Don't clobber r0-r2 yet. It might have bootloader provided info
	;-------------------------------------------------------------------
	;-------------------------------------------------------------------


	sr	@_int_vec_base_lds, [AUX_INTR_VEC_BASE]
	CPU_EARLY_SETUP


#ifdef CONFIG_SMP
#ifdef CONFIG_SMP
	; Ensure Boot (Master) proceeds. Others wait in platform dependent way
	; Ensure Boot (Master) proceeds. Others wait in platform dependent way
@@ -90,7 +122,7 @@ stext:


first_lines_of_secondary:
first_lines_of_secondary:


	sr	@_int_vec_base_lds, [AUX_INTR_VEC_BASE]
	CPU_EARLY_SETUP


	; setup per-cpu idle task as "current" on this CPU
	; setup per-cpu idle task as "current" on this CPU
	ld	r0, [@secondary_idle_tsk]
	ld	r0, [@secondary_idle_tsk]
+25 −81
Original line number Original line Diff line number Diff line
@@ -73,33 +73,6 @@
#include <asm/cachectl.h>
#include <asm/cachectl.h>
#include <asm/setup.h>
#include <asm/setup.h>


/* Instruction cache related Auxiliary registers */
#define ARC_REG_IC_BCR		0x77	/* Build Config reg */
#define ARC_REG_IC_IVIC		0x10
#define ARC_REG_IC_CTRL		0x11
#define ARC_REG_IC_IVIL		0x19
#if (CONFIG_ARC_MMU_VER > 2)
#define ARC_REG_IC_PTAG		0x1E
#endif

/* Bit val in IC_CTRL */
#define IC_CTRL_CACHE_DISABLE   0x1

/* Data cache related Auxiliary registers */
#define ARC_REG_DC_BCR		0x72	/* Build Config reg */
#define ARC_REG_DC_IVDC		0x47
#define ARC_REG_DC_CTRL		0x48
#define ARC_REG_DC_IVDL		0x4A
#define ARC_REG_DC_FLSH		0x4B
#define ARC_REG_DC_FLDL		0x4C
#if (CONFIG_ARC_MMU_VER > 2)
#define ARC_REG_DC_PTAG		0x5C
#endif

/* Bit val in DC_CTRL */
#define DC_CTRL_INV_MODE_FLUSH  0x40
#define DC_CTRL_FLUSH_STATUS    0x100

char *arc_cache_mumbojumbo(int c, char *buf, int len)
char *arc_cache_mumbojumbo(int c, char *buf, int len)
{
{
	int n = 0;
	int n = 0;
@@ -168,44 +141,33 @@ void read_decode_cache_bcr(void)
 */
 */
void arc_cache_init(void)
void arc_cache_init(void)
{
{
	unsigned int cpu = smp_processor_id();
	unsigned int __maybe_unused cpu = smp_processor_id();
	struct cpuinfo_arc_cache *ic = &cpuinfo_arc700[cpu].icache;
	struct cpuinfo_arc_cache __maybe_unused *ic, __maybe_unused *dc;
	struct cpuinfo_arc_cache *dc = &cpuinfo_arc700[cpu].dcache;
	unsigned int dcache_does_alias, temp;
	char str[256];
	char str[256];


	printk(arc_cache_mumbojumbo(0, str, sizeof(str)));
	printk(arc_cache_mumbojumbo(0, str, sizeof(str)));


	if (!ic->ver)
		goto chk_dc;

#ifdef CONFIG_ARC_HAS_ICACHE
#ifdef CONFIG_ARC_HAS_ICACHE
	/* 1. Confirm some of I-cache params which Linux assumes */
	ic = &cpuinfo_arc700[cpu].icache;
	if (ic->ver) {
		if (ic->line_len != L1_CACHE_BYTES)
		if (ic->line_len != L1_CACHE_BYTES)
		panic("Cache H/W doesn't match kernel Config");
			panic("ICache line [%d] != kernel Config [%d]",
			      ic->line_len, L1_CACHE_BYTES);


		if (ic->ver != CONFIG_ARC_MMU_VER)
		if (ic->ver != CONFIG_ARC_MMU_VER)
		panic("Cache ver doesn't match MMU ver\n");
			panic("Cache ver [%d] doesn't match MMU ver [%d]\n",
#endif
			      ic->ver, CONFIG_ARC_MMU_VER);

	}
	/* Enable/disable I-Cache */
	temp = read_aux_reg(ARC_REG_IC_CTRL);

#ifdef CONFIG_ARC_HAS_ICACHE
	temp &= ~IC_CTRL_CACHE_DISABLE;
#else
	temp |= IC_CTRL_CACHE_DISABLE;
#endif
#endif


	write_aux_reg(ARC_REG_IC_CTRL, temp);

chk_dc:
	if (!dc->ver)
		return;

#ifdef CONFIG_ARC_HAS_DCACHE
#ifdef CONFIG_ARC_HAS_DCACHE
	dc = &cpuinfo_arc700[cpu].dcache;
	if (dc->ver) {
		unsigned int dcache_does_alias;

		if (dc->line_len != L1_CACHE_BYTES)
		if (dc->line_len != L1_CACHE_BYTES)
		panic("Cache H/W doesn't match kernel Config");
			panic("DCache line [%d] != kernel Config [%d]",
			      dc->line_len, L1_CACHE_BYTES);


		/* check for D-Cache aliasing */
		/* check for D-Cache aliasing */
		dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE;
		dcache_does_alias = (dc->sz / dc->assoc) > PAGE_SIZE;
@@ -214,26 +176,8 @@ chk_dc:
			panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
			panic("Enable CONFIG_ARC_CACHE_VIPT_ALIASING\n");
		else if (!dcache_does_alias && cache_is_vipt_aliasing())
		else if (!dcache_does_alias && cache_is_vipt_aliasing())
			panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n");
			panic("Don't need CONFIG_ARC_CACHE_VIPT_ALIASING\n");
	}
#endif
#endif

	/* Set the default Invalidate Mode to "simpy discard dirty lines"
	 *  as this is more frequent then flush before invalidate
	 * Ofcourse we toggle this default behviour when desired
	 */
	temp = read_aux_reg(ARC_REG_DC_CTRL);
	temp &= ~DC_CTRL_INV_MODE_FLUSH;

#ifdef CONFIG_ARC_HAS_DCACHE
	/* Enable D-Cache: Clear Bit 0 */
	write_aux_reg(ARC_REG_DC_CTRL, temp & ~IC_CTRL_CACHE_DISABLE);
#else
	/* Flush D cache */
	write_aux_reg(ARC_REG_DC_FLSH, 0x1);
	/* Disable D cache */
	write_aux_reg(ARC_REG_DC_CTRL, temp | IC_CTRL_CACHE_DISABLE);
#endif

	return;
}
}


#define OP_INV		0x1
#define OP_INV		0x1