OSDN Git Service

ARCv2: don't assume core 0x54 has dual issue
[uclinux-h8/linux.git] / arch / arc / kernel / setup.c
index 2e018b8..7b23409 100644 (file)
@@ -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;