Commit 2fdb1a1df925f885afc677e61755125844a9b7ef
Committed by
Stefano Babic
1 parent
70b4b49b91
Exists in
smarc_8mq_lf_v2020.04
and in
11 other branches
imx8: cpu: add uclass based CPU driver
print_cpuinfo() in board init code requires uclass CPU driver, add it to be able to display CPU info when CONFIG_DISPLAY_CPUINFO option is enabled. CPU node in DT will have to include 'clocks' and 'u-boot,dm-pre-reloc' properties for generic print_cpuinfo() to work as expected. The driver outputs info for i.MX8QXP Rev A and Rev B CPUs. Signed-off-by: Anatolij Gustschin <agust@denx.de> Cc: Stefano Babic <sbabic@denx.de> Reviewed-by: Peng Fan <peng.fan@nxp.com>
Showing 2 changed files with 142 additions and 78 deletions Side-by-side Diff
arch/arm/include/asm/arch-imx/cpu.h
... | ... | @@ -25,6 +25,7 @@ |
25 | 25 | #define MXC_CPU_MX7S 0x71 /* dummy ID */ |
26 | 26 | #define MXC_CPU_MX7D 0x72 |
27 | 27 | #define MXC_CPU_MX8MQ 0x82 |
28 | +#define MXC_CPU_IMX8QXP_A0 0x90 /* dummy ID */ | |
28 | 29 | #define MXC_CPU_IMX8QXP 0x92 /* dummy ID */ |
29 | 30 | #define MXC_CPU_MX7ULP 0xE1 /* Temporally hard code */ |
30 | 31 | #define MXC_CPU_VF610 0xF6 /* dummy ID */ |
... | ... | @@ -43,8 +44,8 @@ |
43 | 44 | #define CHIP_REV_2_5 0x25 |
44 | 45 | #define CHIP_REV_3_0 0x30 |
45 | 46 | |
46 | -#define CHIP_REV_A 0x0 | |
47 | -#define CHIP_REV_B 0x1 | |
47 | +#define CHIP_REV_A 0x0 | |
48 | +#define CHIP_REV_B 0x1 | |
48 | 49 | |
49 | 50 | #define BOARD_REV_1_0 0x0 |
50 | 51 | #define BOARD_REV_2_0 0x1 |
arch/arm/mach-imx/imx8/cpu.c
... | ... | @@ -5,6 +5,7 @@ |
5 | 5 | |
6 | 6 | #include <common.h> |
7 | 7 | #include <clk.h> |
8 | +#include <cpu.h> | |
8 | 9 | #include <dm.h> |
9 | 10 | #include <dm/device-internal.h> |
10 | 11 | #include <dm/lists.h> |
... | ... | @@ -19,82 +20,6 @@ |
19 | 20 | |
20 | 21 | DECLARE_GLOBAL_DATA_PTR; |
21 | 22 | |
22 | -u32 get_cpu_rev(void) | |
23 | -{ | |
24 | - u32 id = 0, rev = 0; | |
25 | - int ret; | |
26 | - | |
27 | - ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id); | |
28 | - if (ret) | |
29 | - return 0; | |
30 | - | |
31 | - rev = (id >> 5) & 0xf; | |
32 | - id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */ | |
33 | - | |
34 | - return (id << 12) | rev; | |
35 | -} | |
36 | - | |
37 | -#ifdef CONFIG_DISPLAY_CPUINFO | |
38 | -const char *get_imx8_type(u32 imxtype) | |
39 | -{ | |
40 | - switch (imxtype) { | |
41 | - case MXC_CPU_IMX8QXP: | |
42 | - return "8QXP"; | |
43 | - default: | |
44 | - return "??"; | |
45 | - } | |
46 | -} | |
47 | - | |
48 | -const char *get_imx8_rev(u32 rev) | |
49 | -{ | |
50 | - switch (rev) { | |
51 | - case CHIP_REV_A: | |
52 | - return "A"; | |
53 | - case CHIP_REV_B: | |
54 | - return "B"; | |
55 | - default: | |
56 | - return "?"; | |
57 | - } | |
58 | -} | |
59 | - | |
60 | -const char *get_core_name(void) | |
61 | -{ | |
62 | - if (is_cortex_a35()) | |
63 | - return "A35"; | |
64 | - else | |
65 | - return "?"; | |
66 | -} | |
67 | - | |
68 | -int print_cpuinfo(void) | |
69 | -{ | |
70 | - struct udevice *dev; | |
71 | - struct clk cpu_clk; | |
72 | - int ret; | |
73 | - | |
74 | - ret = uclass_get_device(UCLASS_CPU, 0, &dev); | |
75 | - if (ret) | |
76 | - return 0; | |
77 | - | |
78 | - ret = clk_get_by_index(dev, 0, &cpu_clk); | |
79 | - if (ret) { | |
80 | - dev_err(dev, "failed to clk\n"); | |
81 | - return 0; | |
82 | - } | |
83 | - | |
84 | - u32 cpurev; | |
85 | - | |
86 | - cpurev = get_cpu_rev(); | |
87 | - | |
88 | - printf("CPU: Freescale i.MX%s rev%s %s at %ld MHz\n", | |
89 | - get_imx8_type((cpurev & 0xFF000) >> 12), | |
90 | - get_imx8_rev((cpurev & 0xFFF)), | |
91 | - get_core_name(), | |
92 | - clk_get_rate(&cpu_clk) / 1000000); | |
93 | - | |
94 | - return 0; | |
95 | -} | |
96 | -#endif | |
97 | - | |
98 | 23 | #define BT_PASSOVER_TAG 0x504F |
99 | 24 | struct pass_over_info_t *get_pass_over_info(void) |
100 | 25 | { |
... | ... | @@ -581,4 +506,142 @@ |
581 | 506 | err: |
582 | 507 | printf("%s: fuse %d, err: %d\n", __func__, word[i], ret); |
583 | 508 | } |
509 | + | |
510 | +#if CONFIG_IS_ENABLED(CPU) | |
511 | +struct cpu_imx_platdata { | |
512 | + const char *name; | |
513 | + const char *rev; | |
514 | + const char *type; | |
515 | + u32 cpurev; | |
516 | + u32 freq_mhz; | |
517 | +}; | |
518 | + | |
519 | +u32 get_cpu_rev(void) | |
520 | +{ | |
521 | + u32 id = 0, rev = 0; | |
522 | + int ret; | |
523 | + | |
524 | + ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id); | |
525 | + if (ret) | |
526 | + return 0; | |
527 | + | |
528 | + rev = (id >> 5) & 0xf; | |
529 | + id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */ | |
530 | + | |
531 | + return (id << 12) | rev; | |
532 | +} | |
533 | + | |
534 | +const char *get_imx8_type(u32 imxtype) | |
535 | +{ | |
536 | + switch (imxtype) { | |
537 | + case MXC_CPU_IMX8QXP: | |
538 | + case MXC_CPU_IMX8QXP_A0: | |
539 | + return "QXP"; | |
540 | + default: | |
541 | + return "??"; | |
542 | + } | |
543 | +} | |
544 | + | |
545 | +const char *get_imx8_rev(u32 rev) | |
546 | +{ | |
547 | + switch (rev) { | |
548 | + case CHIP_REV_A: | |
549 | + return "A"; | |
550 | + case CHIP_REV_B: | |
551 | + return "B"; | |
552 | + default: | |
553 | + return "?"; | |
554 | + } | |
555 | +} | |
556 | + | |
557 | +const char *get_core_name(void) | |
558 | +{ | |
559 | + if (is_cortex_a35()) | |
560 | + return "A35"; | |
561 | + else if (is_cortex_a53()) | |
562 | + return "A53"; | |
563 | + else if (is_cortex_a72()) | |
564 | + return "A72"; | |
565 | + else | |
566 | + return "?"; | |
567 | +} | |
568 | + | |
569 | +int cpu_imx_get_desc(struct udevice *dev, char *buf, int size) | |
570 | +{ | |
571 | + struct cpu_imx_platdata *plat = dev_get_platdata(dev); | |
572 | + | |
573 | + if (size < 100) | |
574 | + return -ENOSPC; | |
575 | + | |
576 | + snprintf(buf, size, "CPU: Freescale i.MX8%s Rev%s %s at %u MHz\n", | |
577 | + plat->type, plat->rev, plat->name, plat->freq_mhz); | |
578 | + | |
579 | + return 0; | |
580 | +} | |
581 | + | |
582 | +static int cpu_imx_get_info(struct udevice *dev, struct cpu_info *info) | |
583 | +{ | |
584 | + struct cpu_imx_platdata *plat = dev_get_platdata(dev); | |
585 | + | |
586 | + info->cpu_freq = plat->freq_mhz * 1000; | |
587 | + info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU); | |
588 | + return 0; | |
589 | +} | |
590 | + | |
591 | +static int cpu_imx_get_count(struct udevice *dev) | |
592 | +{ | |
593 | + return 4; | |
594 | +} | |
595 | + | |
596 | +static int cpu_imx_get_vendor(struct udevice *dev, char *buf, int size) | |
597 | +{ | |
598 | + snprintf(buf, size, "NXP"); | |
599 | + return 0; | |
600 | +} | |
601 | + | |
602 | +static const struct cpu_ops cpu_imx8_ops = { | |
603 | + .get_desc = cpu_imx_get_desc, | |
604 | + .get_info = cpu_imx_get_info, | |
605 | + .get_count = cpu_imx_get_count, | |
606 | + .get_vendor = cpu_imx_get_vendor, | |
607 | +}; | |
608 | + | |
609 | +static const struct udevice_id cpu_imx8_ids[] = { | |
610 | + { .compatible = "arm,cortex-a35" }, | |
611 | + { } | |
612 | +}; | |
613 | + | |
614 | +static int imx8_cpu_probe(struct udevice *dev) | |
615 | +{ | |
616 | + struct cpu_imx_platdata *plat = dev_get_platdata(dev); | |
617 | + struct clk cpu_clk; | |
618 | + u32 cpurev; | |
619 | + int ret; | |
620 | + | |
621 | + cpurev = get_cpu_rev(); | |
622 | + plat->cpurev = cpurev; | |
623 | + plat->name = get_core_name(); | |
624 | + plat->rev = get_imx8_rev(cpurev & 0xFFF); | |
625 | + plat->type = get_imx8_type((cpurev & 0xFF000) >> 12); | |
626 | + | |
627 | + ret = clk_get_by_index(dev, 0, &cpu_clk); | |
628 | + if (ret) { | |
629 | + debug("%s: Failed to get CPU clk: %d\n", __func__, ret); | |
630 | + return 0; | |
631 | + } | |
632 | + | |
633 | + plat->freq_mhz = clk_get_rate(&cpu_clk) / 1000000; | |
634 | + return 0; | |
635 | +} | |
636 | + | |
637 | +U_BOOT_DRIVER(cpu_imx8_drv) = { | |
638 | + .name = "imx8x_cpu", | |
639 | + .id = UCLASS_CPU, | |
640 | + .of_match = cpu_imx8_ids, | |
641 | + .ops = &cpu_imx8_ops, | |
642 | + .probe = imx8_cpu_probe, | |
643 | + .platdata_auto_alloc_size = sizeof(struct cpu_imx_platdata), | |
644 | + .flags = DM_FLAG_PRE_RELOC, | |
645 | +}; | |
646 | +#endif |