Merge tag 'u-boot-rockchip-20190809' of https://gitlab.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / arch / arm / mach-meson / board-info.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2019 Julien Masson <jmasson@baylibre.com>
4  * (C) Copyright 2019 Neil Armstrong <narmstrong@baylibre.com>
5  */
6
7 #include <common.h>
8 #include <asm/io.h>
9 #include <dm.h>
10 #include <linux/bitfield.h>
11 #include <regmap.h>
12 #include <syscon.h>
13
14 #define AO_SEC_SD_CFG8          0xe0
15 #define AO_SEC_SOCINFO_OFFSET   AO_SEC_SD_CFG8
16
17 #define SOCINFO_MAJOR   GENMASK(31, 24)
18 #define SOCINFO_PACK    GENMASK(23, 16)
19 #define SOCINFO_MINOR   GENMASK(15, 8)
20 #define SOCINFO_MISC    GENMASK(7, 0)
21
22 static const struct meson_gx_soc_id {
23         const char *name;
24         unsigned int id;
25 } soc_ids[] = {
26         { "GXBB",   0x1f },
27         { "GXTVBB", 0x20 },
28         { "GXL",    0x21 },
29         { "GXM",    0x22 },
30         { "TXL",    0x23 },
31         { "TXLX",   0x24 },
32         { "AXG",    0x25 },
33         { "GXLX",   0x26 },
34         { "TXHD",   0x27 },
35         { "G12A",   0x28 },
36         { "G12B",   0x29 },
37 };
38
39 static const struct meson_gx_package_id {
40         const char *name;
41         unsigned int major_id;
42         unsigned int pack_id;
43         unsigned int pack_mask;
44 } soc_packages[] = {
45         { "S905",   0x1f, 0,    0x20 }, /* pack_id != 0x20 */
46         { "S905H",  0x1f, 0x3,  0xf },  /* pack_id & 0xf == 0x3 */
47         { "S905M",  0x1f, 0x20, 0xf0 }, /* pack_id == 0x20 */
48         { "S905D",  0x21, 0,    0xf0 },
49         { "S905X",  0x21, 0x80, 0xf0 },
50         { "S905W",  0x21, 0xa0, 0xf0 },
51         { "S905L",  0x21, 0xc0, 0xf0 },
52         { "S905M2", 0x21, 0xe0, 0xf0 },
53         { "S805X",  0x21, 0x30, 0xf0 },
54         { "S805Y",  0x21, 0xb0, 0xf0 },
55         { "S912",   0x22, 0,    0x0 },  /* Only S912 is known for GXM */
56         { "962X",   0x24, 0x10, 0xf0 },
57         { "962E",   0x24, 0x20, 0xf0 },
58         { "A113X",  0x25, 0x37, 0xff },
59         { "A113D",  0x25, 0x22, 0xff },
60         { "S905D2", 0x28, 0x10, 0xf0 },
61         { "S905X2", 0x28, 0x40, 0xf0 },
62         { "S922X",  0x29, 0x40, 0xf0 },
63 };
64
65 DECLARE_GLOBAL_DATA_PTR;
66
67 static inline unsigned int socinfo_to_major(u32 socinfo)
68 {
69         return FIELD_GET(SOCINFO_MAJOR, socinfo);
70 }
71
72 static inline unsigned int socinfo_to_minor(u32 socinfo)
73 {
74         return FIELD_GET(SOCINFO_MINOR, socinfo);
75 }
76
77 static inline unsigned int socinfo_to_pack(u32 socinfo)
78 {
79         return FIELD_GET(SOCINFO_PACK, socinfo);
80 }
81
82 static inline unsigned int socinfo_to_misc(u32 socinfo)
83 {
84         return FIELD_GET(SOCINFO_MISC, socinfo);
85 }
86
87 static const char *socinfo_to_package_id(u32 socinfo)
88 {
89         unsigned int pack = socinfo_to_pack(socinfo);
90         unsigned int major = socinfo_to_major(socinfo);
91         int i;
92
93         for (i = 0 ; i < ARRAY_SIZE(soc_packages) ; ++i) {
94                 if (soc_packages[i].major_id == major &&
95                     soc_packages[i].pack_id ==
96                     (pack & soc_packages[i].pack_mask))
97                         return soc_packages[i].name;
98         }
99
100         return "Unknown";
101 }
102
103 static const char *socinfo_to_soc_id(u32 socinfo)
104 {
105         unsigned int id = socinfo_to_major(socinfo);
106         int i;
107
108         for (i = 0 ; i < ARRAY_SIZE(soc_ids) ; ++i) {
109                 if (soc_ids[i].id == id)
110                         return soc_ids[i].name;
111         }
112
113         return "Unknown";
114 }
115
116 static void print_board_model(void)
117 {
118         const char *model;
119         model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
120         printf("Model: %s\n", model ? model : "Unknown");
121 }
122
123 int show_board_info(void)
124 {
125         struct regmap *regmap;
126         int nodeoffset, ret;
127         ofnode node;
128         unsigned int socinfo;
129
130         /* find the offset of compatible node */
131         nodeoffset = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
132                                                    "amlogic,meson-gx-ao-secure");
133         if (nodeoffset < 0)
134                 return 0;
135
136         /* check if chip-id is available */
137         if (!fdt_getprop(gd->fdt_blob, nodeoffset, "amlogic,has-chip-id", NULL))
138                 return 0;
139
140         /* get regmap from the syscon node */
141         node = offset_to_ofnode(nodeoffset);
142         regmap = syscon_node_to_regmap(node);
143         if (IS_ERR(regmap)) {
144                 printf("%s: failed to get regmap\n", __func__);
145                 return 0;
146         }
147
148         /* read soc info */
149         ret = regmap_read(regmap, AO_SEC_SOCINFO_OFFSET, &socinfo);
150         if (ret && !socinfo) {
151                 printf("%s: invalid chipid value\n", __func__);
152                 return 0;
153         }
154
155         /* print board information */
156         print_board_model();
157         printf("Soc:   Amlogic Meson %s (%s) Revision %x:%x (%x:%x)\n",
158                socinfo_to_soc_id(socinfo),
159                socinfo_to_package_id(socinfo),
160                socinfo_to_major(socinfo),
161                socinfo_to_minor(socinfo),
162                socinfo_to_pack(socinfo),
163                socinfo_to_misc(socinfo));
164
165         return 0;
166 }