|
|
@@ -196,13 +196,29 @@ static void read_arc_build_cfg_regs(void)
|
|
|
cpu->bpu.num_pred = 2048 << bpu.pte;
|
|
|
|
|
|
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);
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -449,43 +465,80 @@ 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)
|
|
|
{
|
|
|
+ bool use_embedded_dtb = true;
|
|
|
+ bool append_cmdline = false;
|
|
|
+
|
|
|
#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");
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
- /* See if u-boot passed an external Device Tree blob */
|
|
|
- machine_desc = setup_machine_fdt(uboot_arg); /* uboot_tag == 2 */
|
|
|
- if (!machine_desc)
|
|
|
+ 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:
|
|
|
#endif
|
|
|
- {
|
|
|
- /* No, so try the embedded one */
|
|
|
+
|
|
|
+ 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;
|