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