Commit 2fdb1a1df925f885afc677e61755125844a9b7ef

Authored by Anatolij Gustschin
Committed by Stefano Babic
1 parent 70b4b49b91

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