aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Blumenstingl <martin.blumenstingl@googlemail.com>2017-09-23 10:14:02 -0400
committerKevin Hilman <khilman@baylibre.com>2017-10-06 18:36:17 -0400
commit5e68c0fc8df8a588b15cd469b27b8b5dbfadc6c3 (patch)
treece65aa6aeac026eb2846cd95d1cc5949083b4836
parent2bd6bf03f4c1c59381d62c61d03f6cc3fe71f66e (diff)
soc: amlogic: Add Meson6/Meson8/Meson8b/Meson8m2 SoC Information driver
Amlogic SoCs have an information register which contains the SoC type and revision information. This patchs adds support for decoding those registers and exposing the resulting information via the SoC bus infrastructure. Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Signed-off-by: Kevin Hilman <khilman@baylibre.com>
-rw-r--r--drivers/soc/amlogic/Kconfig10
-rw-r--r--drivers/soc/amlogic/Makefile1
-rw-r--r--drivers/soc/amlogic/meson-mx-socinfo.c175
3 files changed, 186 insertions, 0 deletions
diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig
index 22acf064531f..ef0b8f6c53e0 100644
--- a/drivers/soc/amlogic/Kconfig
+++ b/drivers/soc/amlogic/Kconfig
@@ -9,4 +9,14 @@ config MESON_GX_SOCINFO
9 Say yes to support decoding of Amlogic Meson GX SoC family 9 Say yes to support decoding of Amlogic Meson GX SoC family
10 information about the type, package and version. 10 information about the type, package and version.
11 11
12config MESON_MX_SOCINFO
13 bool "Amlogic Meson MX SoC Information driver"
14 depends on ARCH_MESON || COMPILE_TEST
15 default ARCH_MESON
16 select SOC_BUS
17 help
18 Say yes to support decoding of Amlogic Meson6, Meson8,
19 Meson8b and Meson8m2 SoC family information about the type
20 and version.
21
12endmenu 22endmenu
diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile
index 3e85fc462c21..1f5df50ebd73 100644
--- a/drivers/soc/amlogic/Makefile
+++ b/drivers/soc/amlogic/Makefile
@@ -1 +1,2 @@
1obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o 1obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o
2obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o
diff --git a/drivers/soc/amlogic/meson-mx-socinfo.c b/drivers/soc/amlogic/meson-mx-socinfo.c
new file mode 100644
index 000000000000..7bfff5ff22a2
--- /dev/null
+++ b/drivers/soc/amlogic/meson-mx-socinfo.c
@@ -0,0 +1,175 @@
1/*
2 * Copyright (c) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 */
6
7#include <linux/io.h>
8#include <linux/of.h>
9#include <linux/of_address.h>
10#include <linux/of_platform.h>
11#include <linux/platform_device.h>
12#include <linux/slab.h>
13#include <linux/sys_soc.h>
14#include <linux/bitfield.h>
15#include <linux/regmap.h>
16#include <linux/mfd/syscon.h>
17
18#define MESON_SOCINFO_MAJOR_VER_MESON6 0x16
19#define MESON_SOCINFO_MAJOR_VER_MESON8 0x19
20#define MESON_SOCINFO_MAJOR_VER_MESON8B 0x1b
21
22#define MESON_MX_ASSIST_HW_REV 0x14c
23
24#define MESON_MX_ANALOG_TOP_METAL_REVISION 0x0
25
26#define MESON_MX_BOOTROM_MISC_VER 0x4
27
28static const char *meson_mx_socinfo_revision(unsigned int major_ver,
29 unsigned int misc_ver,
30 unsigned int metal_rev)
31{
32 unsigned int minor_ver;
33
34 switch (major_ver) {
35 case MESON_SOCINFO_MAJOR_VER_MESON6:
36 minor_ver = 0xa;
37 break;
38
39 case MESON_SOCINFO_MAJOR_VER_MESON8:
40 if (metal_rev == 0x11111112)
41 major_ver = 0x1d;
42
43 if (metal_rev == 0x11111111 || metal_rev == 0x11111112)
44 minor_ver = 0xa;
45 else if (metal_rev == 0x11111113)
46 minor_ver = 0xb;
47 else if (metal_rev == 0x11111133)
48 minor_ver = 0xc;
49 else
50 minor_ver = 0xd;
51
52 break;
53
54 case MESON_SOCINFO_MAJOR_VER_MESON8B:
55 if (metal_rev == 0x11111111)
56 minor_ver = 0xa;
57 else
58 minor_ver = 0xb;
59
60 break;
61
62 default:
63 minor_ver = 0x0;
64 break;
65 }
66
67 return kasprintf(GFP_KERNEL, "Rev%X (%x - 0:%X)", minor_ver, major_ver,
68 misc_ver);
69}
70
71static const char *meson_mx_socinfo_soc_id(unsigned int major_ver,
72 unsigned int metal_rev)
73{
74 const char *soc_id;
75
76 switch (major_ver) {
77 case MESON_SOCINFO_MAJOR_VER_MESON6:
78 soc_id = "Meson6 (AML8726-MX)";
79 break;
80
81 case MESON_SOCINFO_MAJOR_VER_MESON8:
82 if (metal_rev == 0x11111112)
83 soc_id = "Meson8m2 (S812)";
84 else
85 soc_id = "Meson8 (S802)";
86
87 break;
88
89 case MESON_SOCINFO_MAJOR_VER_MESON8B:
90 soc_id = "Meson8b (S805)";
91 break;
92
93 default:
94 soc_id = "Unknown";
95 break;
96 }
97
98 return kstrdup_const(soc_id, GFP_KERNEL);
99}
100
101static const struct of_device_id meson_mx_socinfo_analog_top_ids[] = {
102 { .compatible = "amlogic,meson8-analog-top", },
103 { .compatible = "amlogic,meson8b-analog-top", },
104 { /* sentinel */ }
105};
106
107int __init meson_mx_socinfo_init(void)
108{
109 struct soc_device_attribute *soc_dev_attr;
110 struct soc_device *soc_dev;
111 struct device_node *np;
112 struct regmap *assist_regmap, *bootrom_regmap, *analog_top_regmap;
113 unsigned int major_ver, misc_ver, metal_rev = 0;
114 int ret;
115
116 assist_regmap =
117 syscon_regmap_lookup_by_compatible("amlogic,meson-mx-assist");
118 if (IS_ERR(assist_regmap))
119 return PTR_ERR(assist_regmap);
120
121 bootrom_regmap =
122 syscon_regmap_lookup_by_compatible("amlogic,meson-mx-bootrom");
123 if (IS_ERR(bootrom_regmap))
124 return PTR_ERR(bootrom_regmap);
125
126 np = of_find_matching_node(NULL, meson_mx_socinfo_analog_top_ids);
127 if (np) {
128 analog_top_regmap = syscon_node_to_regmap(np);
129 if (IS_ERR(analog_top_regmap))
130 return PTR_ERR(analog_top_regmap);
131
132 ret = regmap_read(analog_top_regmap,
133 MESON_MX_ANALOG_TOP_METAL_REVISION,
134 &metal_rev);
135 if (ret)
136 return ret;
137 }
138
139 ret = regmap_read(assist_regmap, MESON_MX_ASSIST_HW_REV, &major_ver);
140 if (ret < 0)
141 return ret;
142
143 ret = regmap_read(bootrom_regmap, MESON_MX_BOOTROM_MISC_VER,
144 &misc_ver);
145 if (ret < 0)
146 return ret;
147
148 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
149 if (!soc_dev_attr)
150 return -ENODEV;
151
152 soc_dev_attr->family = "Amlogic Meson";
153
154 np = of_find_node_by_path("/");
155 of_property_read_string(np, "model", &soc_dev_attr->machine);
156 of_node_put(np);
157
158 soc_dev_attr->revision = meson_mx_socinfo_revision(major_ver, misc_ver,
159 metal_rev);
160 soc_dev_attr->soc_id = meson_mx_socinfo_soc_id(major_ver, metal_rev);
161
162 soc_dev = soc_device_register(soc_dev_attr);
163 if (IS_ERR(soc_dev)) {
164 kfree_const(soc_dev_attr->revision);
165 kfree_const(soc_dev_attr->soc_id);
166 kfree(soc_dev_attr);
167 return PTR_ERR(soc_dev);
168 }
169
170 dev_info(soc_device_to_device(soc_dev), "Amlogic %s %s detected\n",
171 soc_dev_attr->soc_id, soc_dev_attr->revision);
172
173 return 0;
174}
175device_initcall(meson_mx_socinfo_init);