diff options
Diffstat (limited to 'arch/arc/kernel/setup.c')
| -rw-r--r-- | arch/arc/kernel/setup.c | 144 | 
1 files changed, 102 insertions, 42 deletions
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index 2e018b8c2e19..7b2340996cf8 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c @@ -123,6 +123,7 @@ static void read_arc_build_cfg_regs(void)  	struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];  	const struct id_to_str *tbl;  	struct bcr_isa_arcv2 isa; +	struct bcr_actionpoint ap;  	FIX_PTR(cpu); @@ -195,20 +196,40 @@ static void read_arc_build_cfg_regs(void)  		cpu->bpu.full = bpu.ft;  		cpu->bpu.num_cache = 256 << bpu.bce;  		cpu->bpu.num_pred = 2048 << bpu.pte; +		cpu->bpu.ret_stk = 4 << bpu.rse;  		if (cpu->core.family >= 0x54) { -			unsigned int exec_ctrl; -			READ_BCR(AUX_EXEC_CTRL, exec_ctrl); -			cpu->extn.dual_enb = !(exec_ctrl & 1); +			struct bcr_uarch_build_arcv2 uarch; -			/* dual issue always present for this core */ -			cpu->extn.dual = 1; +			/* +			 * The first 0x54 core (uarch maj:min 0:1 or 0:2) was +			 * dual issue only (HS4x). But next uarch rev (1:0) +			 * allows it be configured for single issue (HS3x) +			 * Ensure we fiddle with dual issue only on HS4x +			 */ +			READ_BCR(ARC_REG_MICRO_ARCH_BCR, uarch); + +			if (uarch.prod == 4) { +				unsigned int exec_ctrl; + +				/* dual issue hardware always present */ +				cpu->extn.dual = 1; + +				READ_BCR(AUX_EXEC_CTRL, exec_ctrl); + +				/* dual issue hardware enabled ? */ +				cpu->extn.dual_enb = !(exec_ctrl & 1); + +			}  		}  	} -	READ_BCR(ARC_REG_AP_BCR, bcr); -	cpu->extn.ap = bcr.ver ? 1 : 0; +	READ_BCR(ARC_REG_AP_BCR, ap); +	if (ap.ver) { +		cpu->extn.ap_num = 2 << ap.num; +		cpu->extn.ap_full = !ap.min; +	}  	READ_BCR(ARC_REG_SMART_BCR, bcr);  	cpu->extn.smart = bcr.ver ? 1 : 0; @@ -216,8 +237,6 @@ static void read_arc_build_cfg_regs(void)  	READ_BCR(ARC_REG_RTT_BCR, bcr);  	cpu->extn.rtt = bcr.ver ? 1 : 0; -	cpu->extn.debug = cpu->extn.ap | cpu->extn.smart | cpu->extn.rtt; -  	READ_BCR(ARC_REG_ISA_CFG_BCR, isa);  	/* some hacks for lack of feature BCR info in old ARC700 cores */ @@ -299,10 +318,10 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)  	if (cpu->bpu.ver)  		n += scnprintf(buf + n, len - n, -			      "BPU\t\t: %s%s match, cache:%d, Predict Table:%d", +			      "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d",  			      IS_AVAIL1(cpu->bpu.full, "full"),  			      IS_AVAIL1(!cpu->bpu.full, "partial"), -			      cpu->bpu.num_cache, cpu->bpu.num_pred); +			      cpu->bpu.num_cache, cpu->bpu.num_pred, cpu->bpu.ret_stk);  	if (is_isa_arcv2()) {  		struct bcr_lpb lpb; @@ -336,11 +355,17 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)  			       IS_AVAIL1(cpu->extn.fpu_sp, "SP "),  			       IS_AVAIL1(cpu->extn.fpu_dp, "DP ")); -	if (cpu->extn.debug) -		n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n", -			       IS_AVAIL1(cpu->extn.ap, "ActionPoint "), +	if (cpu->extn.ap_num | cpu->extn.smart | cpu->extn.rtt) { +		n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s",  			       IS_AVAIL1(cpu->extn.smart, "smaRT "),  			       IS_AVAIL1(cpu->extn.rtt, "RTT ")); +		if (cpu->extn.ap_num) { +			n += scnprintf(buf + n, len - n, "ActionPoint %d/%s", +				       cpu->extn.ap_num, +				       cpu->extn.ap_full ? "full":"min"); +		} +		n += scnprintf(buf + n, len - n, "\n"); +	}  	if (cpu->dccm.sz || cpu->iccm.sz)  		n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n", @@ -453,43 +478,78 @@ void setup_processor(void)  	arc_chk_core_config();  } -static inline int is_kernel(unsigned long addr) +static inline bool uboot_arg_invalid(unsigned long addr)  { -	if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end) -		return 1; -	return 0; +	/* +	 * Check that it is a untranslated address (although MMU is not enabled +	 * yet, it being a high address ensures this is not by fluke) +	 */ +	if (addr < PAGE_OFFSET) +		return true; + +	/* Check that address doesn't clobber resident kernel image */ +	return addr >= (unsigned long)_stext && addr <= (unsigned long)_end;  } -void __init setup_arch(char **cmdline_p) +#define IGNORE_ARGS		"Ignore U-boot args: " + +/* uboot_tag values for U-boot - kernel ABI revision 0; see head.S */ +#define UBOOT_TAG_NONE		0 +#define UBOOT_TAG_CMDLINE	1 +#define UBOOT_TAG_DTB		2 + +void __init handle_uboot_args(void)  { -#ifdef CONFIG_ARC_UBOOT_SUPPORT -	/* make sure that uboot passed pointer to cmdline/dtb is valid */ -	if (uboot_tag && is_kernel((unsigned long)uboot_arg)) -		panic("Invalid uboot arg\n"); - -	/* See if u-boot passed an external Device Tree blob */ -	machine_desc = setup_machine_fdt(uboot_arg);	/* uboot_tag == 2 */ -	if (!machine_desc) -#endif -	{ -		/* No, so try the embedded one */ +	bool use_embedded_dtb = true; +	bool append_cmdline = false; + +	/* check that we know this tag */ +	if (uboot_tag != UBOOT_TAG_NONE && +	    uboot_tag != UBOOT_TAG_CMDLINE && +	    uboot_tag != UBOOT_TAG_DTB) { +		pr_warn(IGNORE_ARGS "invalid uboot tag: '%08x'\n", uboot_tag); +		goto ignore_uboot_args; +	} + +	if (uboot_tag != UBOOT_TAG_NONE && +            uboot_arg_invalid((unsigned long)uboot_arg)) { +		pr_warn(IGNORE_ARGS "invalid uboot arg: '%px'\n", uboot_arg); +		goto ignore_uboot_args; +	} + +	/* see if U-boot passed an external Device Tree blob */ +	if (uboot_tag == UBOOT_TAG_DTB) { +		machine_desc = setup_machine_fdt((void *)uboot_arg); + +		/* external Device Tree blob is invalid - use embedded one */ +		use_embedded_dtb = !machine_desc; +	} + +	if (uboot_tag == UBOOT_TAG_CMDLINE) +		append_cmdline = true; + +ignore_uboot_args: + +	if (use_embedded_dtb) {  		machine_desc = setup_machine_fdt(__dtb_start);  		if (!machine_desc)  			panic("Embedded DT invalid\n"); +	} -		/* -		 * If we are here, it is established that @uboot_arg didn't -		 * point to DT blob. Instead if u-boot says it is cmdline, -		 * append to embedded DT cmdline. -		 * setup_machine_fdt() would have populated @boot_command_line -		 */ -		if (uboot_tag == 1) { -			/* Ensure a whitespace between the 2 cmdlines */ -			strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); -			strlcat(boot_command_line, uboot_arg, -				COMMAND_LINE_SIZE); -		} +	/* +	 * NOTE: @boot_command_line is populated by setup_machine_fdt() so this +	 * append processing can only happen after. +	 */ +	if (append_cmdline) { +		/* Ensure a whitespace between the 2 cmdlines */ +		strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); +		strlcat(boot_command_line, uboot_arg, COMMAND_LINE_SIZE);  	} +} + +void __init setup_arch(char **cmdline_p) +{ +	handle_uboot_args();  	/* Save unparsed command line copy for /proc/cmdline */  	*cmdline_p = boot_command_line;  |