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) | |||
| 123 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; | 123 | struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()]; |
| 124 | const struct id_to_str *tbl; | 124 | const struct id_to_str *tbl; |
| 125 | struct bcr_isa_arcv2 isa; | 125 | struct bcr_isa_arcv2 isa; |
| 126 | struct bcr_actionpoint ap; | ||
| 126 | 127 | ||
| 127 | FIX_PTR(cpu); | 128 | FIX_PTR(cpu); |
| 128 | 129 | ||
| @@ -195,20 +196,40 @@ static void read_arc_build_cfg_regs(void) | |||
| 195 | cpu->bpu.full = bpu.ft; | 196 | cpu->bpu.full = bpu.ft; |
| 196 | cpu->bpu.num_cache = 256 << bpu.bce; | 197 | cpu->bpu.num_cache = 256 << bpu.bce; |
| 197 | cpu->bpu.num_pred = 2048 << bpu.pte; | 198 | cpu->bpu.num_pred = 2048 << bpu.pte; |
| 199 | cpu->bpu.ret_stk = 4 << bpu.rse; | ||
| 198 | 200 | ||
| 199 | if (cpu->core.family >= 0x54) { | 201 | if (cpu->core.family >= 0x54) { |
| 200 | unsigned int exec_ctrl; | ||
| 201 | 202 | ||
| 202 | READ_BCR(AUX_EXEC_CTRL, exec_ctrl); | 203 | struct bcr_uarch_build_arcv2 uarch; |
| 203 | cpu->extn.dual_enb = !(exec_ctrl & 1); | ||
| 204 | 204 | ||
| 205 | /* dual issue always present for this core */ | 205 | /* |
| 206 | cpu->extn.dual = 1; | 206 | * The first 0x54 core (uarch maj:min 0:1 or 0:2) was |
| 207 | * dual issue only (HS4x). But next uarch rev (1:0) | ||
| 208 | * allows it be configured for single issue (HS3x) | ||
| 209 | * Ensure we fiddle with dual issue only on HS4x | ||
| 210 | */ | ||
| 211 | READ_BCR(ARC_REG_MICRO_ARCH_BCR, uarch); | ||
| 212 | |||
| 213 | if (uarch.prod == 4) { | ||
| 214 | unsigned int exec_ctrl; | ||
| 215 | |||
| 216 | /* dual issue hardware always present */ | ||
| 217 | cpu->extn.dual = 1; | ||
| 218 | |||
| 219 | READ_BCR(AUX_EXEC_CTRL, exec_ctrl); | ||
| 220 | |||
| 221 | /* dual issue hardware enabled ? */ | ||
| 222 | cpu->extn.dual_enb = !(exec_ctrl & 1); | ||
| 223 | |||
| 224 | } | ||
| 207 | } | 225 | } |
| 208 | } | 226 | } |
| 209 | 227 | ||
| 210 | READ_BCR(ARC_REG_AP_BCR, bcr); | 228 | READ_BCR(ARC_REG_AP_BCR, ap); |
| 211 | cpu->extn.ap = bcr.ver ? 1 : 0; | 229 | if (ap.ver) { |
| 230 | cpu->extn.ap_num = 2 << ap.num; | ||
| 231 | cpu->extn.ap_full = !ap.min; | ||
| 232 | } | ||
| 212 | 233 | ||
| 213 | READ_BCR(ARC_REG_SMART_BCR, bcr); | 234 | READ_BCR(ARC_REG_SMART_BCR, bcr); |
| 214 | cpu->extn.smart = bcr.ver ? 1 : 0; | 235 | cpu->extn.smart = bcr.ver ? 1 : 0; |
| @@ -216,8 +237,6 @@ static void read_arc_build_cfg_regs(void) | |||
| 216 | READ_BCR(ARC_REG_RTT_BCR, bcr); | 237 | READ_BCR(ARC_REG_RTT_BCR, bcr); |
| 217 | cpu->extn.rtt = bcr.ver ? 1 : 0; | 238 | cpu->extn.rtt = bcr.ver ? 1 : 0; |
| 218 | 239 | ||
| 219 | cpu->extn.debug = cpu->extn.ap | cpu->extn.smart | cpu->extn.rtt; | ||
| 220 | |||
| 221 | READ_BCR(ARC_REG_ISA_CFG_BCR, isa); | 240 | READ_BCR(ARC_REG_ISA_CFG_BCR, isa); |
| 222 | 241 | ||
| 223 | /* some hacks for lack of feature BCR info in old ARC700 cores */ | 242 | /* 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) | |||
| 299 | 318 | ||
| 300 | if (cpu->bpu.ver) | 319 | if (cpu->bpu.ver) |
| 301 | n += scnprintf(buf + n, len - n, | 320 | n += scnprintf(buf + n, len - n, |
| 302 | "BPU\t\t: %s%s match, cache:%d, Predict Table:%d", | 321 | "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d", |
| 303 | IS_AVAIL1(cpu->bpu.full, "full"), | 322 | IS_AVAIL1(cpu->bpu.full, "full"), |
| 304 | IS_AVAIL1(!cpu->bpu.full, "partial"), | 323 | IS_AVAIL1(!cpu->bpu.full, "partial"), |
| 305 | cpu->bpu.num_cache, cpu->bpu.num_pred); | 324 | cpu->bpu.num_cache, cpu->bpu.num_pred, cpu->bpu.ret_stk); |
| 306 | 325 | ||
| 307 | if (is_isa_arcv2()) { | 326 | if (is_isa_arcv2()) { |
| 308 | struct bcr_lpb lpb; | 327 | struct bcr_lpb lpb; |
| @@ -336,11 +355,17 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len) | |||
| 336 | IS_AVAIL1(cpu->extn.fpu_sp, "SP "), | 355 | IS_AVAIL1(cpu->extn.fpu_sp, "SP "), |
| 337 | IS_AVAIL1(cpu->extn.fpu_dp, "DP ")); | 356 | IS_AVAIL1(cpu->extn.fpu_dp, "DP ")); |
| 338 | 357 | ||
| 339 | if (cpu->extn.debug) | 358 | if (cpu->extn.ap_num | cpu->extn.smart | cpu->extn.rtt) { |
| 340 | n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n", | 359 | n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s", |
| 341 | IS_AVAIL1(cpu->extn.ap, "ActionPoint "), | ||
| 342 | IS_AVAIL1(cpu->extn.smart, "smaRT "), | 360 | IS_AVAIL1(cpu->extn.smart, "smaRT "), |
| 343 | IS_AVAIL1(cpu->extn.rtt, "RTT ")); | 361 | IS_AVAIL1(cpu->extn.rtt, "RTT ")); |
| 362 | if (cpu->extn.ap_num) { | ||
| 363 | n += scnprintf(buf + n, len - n, "ActionPoint %d/%s", | ||
| 364 | cpu->extn.ap_num, | ||
| 365 | cpu->extn.ap_full ? "full":"min"); | ||
| 366 | } | ||
| 367 | n += scnprintf(buf + n, len - n, "\n"); | ||
| 368 | } | ||
| 344 | 369 | ||
| 345 | if (cpu->dccm.sz || cpu->iccm.sz) | 370 | if (cpu->dccm.sz || cpu->iccm.sz) |
| 346 | n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n", | 371 | 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) | |||
| 453 | arc_chk_core_config(); | 478 | arc_chk_core_config(); |
| 454 | } | 479 | } |
| 455 | 480 | ||
| 456 | static inline int is_kernel(unsigned long addr) | 481 | static inline bool uboot_arg_invalid(unsigned long addr) |
| 457 | { | 482 | { |
| 458 | if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end) | 483 | /* |
| 459 | return 1; | 484 | * Check that it is a untranslated address (although MMU is not enabled |
| 460 | return 0; | 485 | * yet, it being a high address ensures this is not by fluke) |
| 486 | */ | ||
| 487 | if (addr < PAGE_OFFSET) | ||
| 488 | return true; | ||
| 489 | |||
| 490 | /* Check that address doesn't clobber resident kernel image */ | ||
| 491 | return addr >= (unsigned long)_stext && addr <= (unsigned long)_end; | ||
| 461 | } | 492 | } |
| 462 | 493 | ||
| 463 | void __init setup_arch(char **cmdline_p) | 494 | #define IGNORE_ARGS "Ignore U-boot args: " |
| 495 | |||
| 496 | /* uboot_tag values for U-boot - kernel ABI revision 0; see head.S */ | ||
| 497 | #define UBOOT_TAG_NONE 0 | ||
| 498 | #define UBOOT_TAG_CMDLINE 1 | ||
| 499 | #define UBOOT_TAG_DTB 2 | ||
| 500 | |||
| 501 | void __init handle_uboot_args(void) | ||
| 464 | { | 502 | { |
| 465 | #ifdef CONFIG_ARC_UBOOT_SUPPORT | 503 | bool use_embedded_dtb = true; |
| 466 | /* make sure that uboot passed pointer to cmdline/dtb is valid */ | 504 | bool append_cmdline = false; |
| 467 | if (uboot_tag && is_kernel((unsigned long)uboot_arg)) | 505 | |
| 468 | panic("Invalid uboot arg\n"); | 506 | /* check that we know this tag */ |
| 469 | 507 | if (uboot_tag != UBOOT_TAG_NONE && | |
| 470 | /* See if u-boot passed an external Device Tree blob */ | 508 | uboot_tag != UBOOT_TAG_CMDLINE && |
| 471 | machine_desc = setup_machine_fdt(uboot_arg); /* uboot_tag == 2 */ | 509 | uboot_tag != UBOOT_TAG_DTB) { |
| 472 | if (!machine_desc) | 510 | pr_warn(IGNORE_ARGS "invalid uboot tag: '%08x'\n", uboot_tag); |
| 473 | #endif | 511 | goto ignore_uboot_args; |
| 474 | { | 512 | } |
| 475 | /* No, so try the embedded one */ | 513 | |
| 514 | if (uboot_tag != UBOOT_TAG_NONE && | ||
| 515 | uboot_arg_invalid((unsigned long)uboot_arg)) { | ||
| 516 | pr_warn(IGNORE_ARGS "invalid uboot arg: '%px'\n", uboot_arg); | ||
| 517 | goto ignore_uboot_args; | ||
| 518 | } | ||
| 519 | |||
| 520 | /* see if U-boot passed an external Device Tree blob */ | ||
| 521 | if (uboot_tag == UBOOT_TAG_DTB) { | ||
| 522 | machine_desc = setup_machine_fdt((void *)uboot_arg); | ||
| 523 | |||
| 524 | /* external Device Tree blob is invalid - use embedded one */ | ||
| 525 | use_embedded_dtb = !machine_desc; | ||
| 526 | } | ||
| 527 | |||
| 528 | if (uboot_tag == UBOOT_TAG_CMDLINE) | ||
| 529 | append_cmdline = true; | ||
| 530 | |||
| 531 | ignore_uboot_args: | ||
| 532 | |||
| 533 | if (use_embedded_dtb) { | ||
| 476 | machine_desc = setup_machine_fdt(__dtb_start); | 534 | machine_desc = setup_machine_fdt(__dtb_start); |
| 477 | if (!machine_desc) | 535 | if (!machine_desc) |
| 478 | panic("Embedded DT invalid\n"); | 536 | panic("Embedded DT invalid\n"); |
| 537 | } | ||
| 479 | 538 | ||
| 480 | /* | 539 | /* |
| 481 | * If we are here, it is established that @uboot_arg didn't | 540 | * NOTE: @boot_command_line is populated by setup_machine_fdt() so this |
| 482 | * point to DT blob. Instead if u-boot says it is cmdline, | 541 | * append processing can only happen after. |
| 483 | * append to embedded DT cmdline. | 542 | */ |
| 484 | * setup_machine_fdt() would have populated @boot_command_line | 543 | if (append_cmdline) { |
| 485 | */ | 544 | /* Ensure a whitespace between the 2 cmdlines */ |
| 486 | if (uboot_tag == 1) { | 545 | strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); |
| 487 | /* Ensure a whitespace between the 2 cmdlines */ | 546 | strlcat(boot_command_line, uboot_arg, COMMAND_LINE_SIZE); |
| 488 | strlcat(boot_command_line, " ", COMMAND_LINE_SIZE); | ||
| 489 | strlcat(boot_command_line, uboot_arg, | ||
| 490 | COMMAND_LINE_SIZE); | ||
| 491 | } | ||
| 492 | } | 547 | } |
| 548 | } | ||
| 549 | |||
| 550 | void __init setup_arch(char **cmdline_p) | ||
| 551 | { | ||
| 552 | handle_uboot_args(); | ||
| 493 | 553 | ||
| 494 | /* Save unparsed command line copy for /proc/cmdline */ | 554 | /* Save unparsed command line copy for /proc/cmdline */ |
| 495 | *cmdline_p = boot_command_line; | 555 | *cmdline_p = boot_command_line; |
