Merge tag 'u-boot-stm32-20211012' of https://source.denx.de/u-boot/custodians/u-boot-stm
[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 <init.h>
9 #include <asm/global_data.h>
10 #include <asm/io.h>
11 #include <dm.h>
12 #include <linux/bitfield.h>
13 #include <regmap.h>
14 #include <syscon.h>
15 #include <linux/bitops.h>
16 #include <linux/err.h>
17
18 #define AO_SEC_SD_CFG8          0xe0
19 #define AO_SEC_SOCINFO_OFFSET   AO_SEC_SD_CFG8
20
21 #define SOCINFO_MAJOR   GENMASK(31, 24)
22 #define SOCINFO_PACK    GENMASK(23, 16)
23 #define SOCINFO_MINOR   GENMASK(15, 8)
24 #define SOCINFO_MISC    GENMASK(7, 0)
25
26 static const struct meson_gx_soc_id {
27         const char *name;
28         unsigned int id;
29 } soc_ids[] = {
30         { "GXBB",   0x1f },
31         { "GXTVBB", 0x20 },
32         { "GXL",    0x21 },
33         { "GXM",    0x22 },
34         { "TXL",    0x23 },
35         { "TXLX",   0x24 },
36         { "AXG",    0x25 },
37         { "GXLX",   0x26 },
38         { "TXHD",   0x27 },
39         { "G12A",   0x28 },
40         { "G12B",   0x29 },
41         { "SM1",    0x2b },
42         { "A1",     0x2c },
43 };
44
45 static const struct meson_gx_package_id {
46         const char *name;
47         unsigned int major_id;
48         unsigned int pack_id;
49         unsigned int pack_mask;
50 } soc_packages[] = {
51         { "S905",   0x1f, 0,    0x20 }, /* pack_id != 0x20 */
52         { "S905H",  0x1f, 0x3,  0xf },  /* pack_id & 0xf == 0x3 */
53         { "S905M",  0x1f, 0x20, 0xf0 }, /* pack_id == 0x20 */
54         { "S905D",  0x21, 0,    0xf0 },
55         { "S905X",  0x21, 0x80, 0xf0 },
56         { "S905W",  0x21, 0xa0, 0xf0 },
57         { "S905L",  0x21, 0xc0, 0xf0 },
58         { "S905M2", 0x21, 0xe0, 0xf0 },
59         { "S805X",  0x21, 0x30, 0xf0 },
60         { "S805Y",  0x21, 0xb0, 0xf0 },
61         { "S912",   0x22, 0,    0x0 },  /* Only S912 is known for GXM */
62         { "962X",   0x24, 0x10, 0xf0 },
63         { "962E",   0x24, 0x20, 0xf0 },
64         { "A113X",  0x25, 0x37, 0xff },
65         { "A113D",  0x25, 0x22, 0xff },
66         { "S905D2", 0x28, 0x10, 0xf0 },
67         { "S905Y2", 0x28, 0x30, 0xf0 },
68         { "S905X2", 0x28, 0x40, 0xf0 },
69         { "A311D",  0x29, 0x10, 0xf0 },
70         { "S922X",  0x29, 0x40, 0xf0 },
71         { "S905D3", 0x2b, 0x4, 0xf5 },
72         { "S905X3", 0x2b, 0x5, 0xf5 },
73         { "S905X3", 0x2b, 0x10, 0x3f },
74         { "S905D3", 0x2b, 0x30, 0x3f },
75         { "A113L", 0x2c, 0x0, 0xf8 },
76 };
77
78 DECLARE_GLOBAL_DATA_PTR;
79
80 static inline unsigned int socinfo_to_major(u32 socinfo)
81 {
82         return FIELD_GET(SOCINFO_MAJOR, socinfo);
83 }
84
85 static inline unsigned int socinfo_to_minor(u32 socinfo)
86 {
87         return FIELD_GET(SOCINFO_MINOR, socinfo);
88 }
89
90 static inline unsigned int socinfo_to_pack(u32 socinfo)
91 {
92         return FIELD_GET(SOCINFO_PACK, socinfo);
93 }
94
95 static inline unsigned int socinfo_to_misc(u32 socinfo)
96 {
97         return FIELD_GET(SOCINFO_MISC, socinfo);
98 }
99
100 static const char *socinfo_to_package_id(u32 socinfo)
101 {
102         unsigned int pack = socinfo_to_pack(socinfo);
103         unsigned int major = socinfo_to_major(socinfo);
104         int i;
105
106         for (i = 0 ; i < ARRAY_SIZE(soc_packages) ; ++i) {
107                 if (soc_packages[i].major_id == major &&
108                     soc_packages[i].pack_id ==
109                     (pack & soc_packages[i].pack_mask))
110                         return soc_packages[i].name;
111         }
112
113         return "Unknown";
114 }
115
116 static const char *socinfo_to_soc_id(u32 socinfo)
117 {
118         unsigned int id = socinfo_to_major(socinfo);
119         int i;
120
121         for (i = 0 ; i < ARRAY_SIZE(soc_ids) ; ++i) {
122                 if (soc_ids[i].id == id)
123                         return soc_ids[i].name;
124         }
125
126         return "Unknown";
127 }
128
129 static void print_board_model(void)
130 {
131         const char *model;
132         model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
133         printf("Model: %s\n", model ? model : "Unknown");
134 }
135
136 static unsigned int get_socinfo(void)
137 {
138         struct regmap *regmap;
139         int nodeoffset, ret;
140         ofnode node;
141         unsigned int socinfo;
142
143         /* find the offset of compatible node */
144         nodeoffset = fdt_node_offset_by_compatible(gd->fdt_blob, -1,
145                                                    "amlogic,meson-gx-ao-secure");
146         if (nodeoffset < 0)
147                 return 0;
148
149         /* check if chip-id is available */
150         if (!fdt_getprop(gd->fdt_blob, nodeoffset, "amlogic,has-chip-id", NULL))
151                 return 0;
152
153         /* get regmap from the syscon node */
154         node = offset_to_ofnode(nodeoffset);
155         regmap = syscon_node_to_regmap(node);
156         if (IS_ERR(regmap)) {
157                 printf("%s: failed to get regmap\n", __func__);
158                 return 0;
159         }
160
161         /* read soc info */
162         ret = regmap_read(regmap, AO_SEC_SOCINFO_OFFSET, &socinfo);
163         if (ret && !socinfo) {
164                 printf("%s: invalid chipid value\n", __func__);
165                 return 0;
166         }
167
168         return socinfo;
169 }
170
171 int show_board_info(void)
172 {
173         unsigned int socinfo;
174
175         /* print board information */
176         print_board_model();
177
178         socinfo = get_socinfo();
179         if (!socinfo)
180                 return 0;
181
182         printf("SoC:   Amlogic Meson %s (%s) Revision %x:%x (%x:%x)\n",
183                socinfo_to_soc_id(socinfo),
184                socinfo_to_package_id(socinfo),
185                socinfo_to_major(socinfo),
186                socinfo_to_minor(socinfo),
187                socinfo_to_pack(socinfo),
188                socinfo_to_misc(socinfo));
189
190         return 0;
191 }
192
193 int meson_get_soc_rev(char *buff, size_t buff_len)
194 {
195         unsigned int socinfo;
196
197         socinfo = get_socinfo();
198         if (!socinfo)
199                 return -1;
200
201         /* Write SoC info */
202         return snprintf(buff, buff_len, "%x", socinfo_to_minor(socinfo));
203 }