diff options
author | Arnd Bergmann <arnd@arndb.de> | 2016-11-30 10:49:22 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2016-11-30 10:49:22 -0500 |
commit | bc28ba81db8e4c20b92c08ebec2405fcb87ae120 (patch) | |
tree | da9e72c46a9df0cd40cfd6a7a443d5a632865721 | |
parent | ae1d0a466ef76e1ff5058e2b316c14f46af83675 (diff) | |
parent | 8d6799a9ba23acd675f3243580ee6f1756fb4381 (diff) |
Merge tag 'renesas-soc-match-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas into next/drivers
Merge "Renesas ARM Based SoC Match Updates for v4.10" from Simon Horman:
* Identify SoC and register with the SoC bus
* tag 'renesas-soc-match-for-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/horms/renesas:
soc: renesas: Identify SoC and register with the SoC bus
ARM: shmobile: Document DT bindings for Product Register
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | Documentation/devicetree/bindings/arm/shmobile.txt | 18 | ||||
-rw-r--r-- | arch/arm/mach-shmobile/Kconfig | 1 | ||||
-rw-r--r-- | arch/arm64/Kconfig.platforms | 1 | ||||
-rw-r--r-- | drivers/soc/renesas/Makefile | 2 | ||||
-rw-r--r-- | drivers/soc/renesas/renesas-soc.c | 257 |
5 files changed, 279 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt index 2f0b7169f132..23c77315fdac 100644 --- a/Documentation/devicetree/bindings/arm/shmobile.txt +++ b/Documentation/devicetree/bindings/arm/shmobile.txt | |||
@@ -75,3 +75,21 @@ Boards: | |||
75 | compatible = "renesas,silk", "renesas,r8a7794" | 75 | compatible = "renesas,silk", "renesas,r8a7794" |
76 | - Wheat | 76 | - Wheat |
77 | compatible = "renesas,wheat", "renesas,r8a7792" | 77 | compatible = "renesas,wheat", "renesas,r8a7792" |
78 | |||
79 | |||
80 | Most Renesas ARM SoCs have a Product Register that allows to retrieve SoC | ||
81 | product and revision information. If present, a device node for this register | ||
82 | should be added. | ||
83 | |||
84 | Required properties: | ||
85 | - compatible: Must be "renesas,prr". | ||
86 | - reg: Base address and length of the register block. | ||
87 | |||
88 | |||
89 | Examples | ||
90 | -------- | ||
91 | |||
92 | prr: chipid@ff000044 { | ||
93 | compatible = "renesas,prr"; | ||
94 | reg = <0 0xff000044 0 4>; | ||
95 | }; | ||
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig index 09817bae4558..ebab13e8afa1 100644 --- a/arch/arm/mach-shmobile/Kconfig +++ b/arch/arm/mach-shmobile/Kconfig | |||
@@ -40,6 +40,7 @@ menuconfig ARCH_RENESAS | |||
40 | select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE | 40 | select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE |
41 | select NO_IOPORT_MAP | 41 | select NO_IOPORT_MAP |
42 | select PINCTRL | 42 | select PINCTRL |
43 | select SOC_BUS | ||
43 | select GPIOLIB | 44 | select GPIOLIB |
44 | select ZONE_DMA if ARM_LPAE | 45 | select ZONE_DMA if ARM_LPAE |
45 | 46 | ||
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index cfbdf02ef566..72f4eac5cbbc 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms | |||
@@ -143,6 +143,7 @@ config ARCH_RENESAS | |||
143 | select PM | 143 | select PM |
144 | select PM_GENERIC_DOMAINS | 144 | select PM_GENERIC_DOMAINS |
145 | select RENESAS_IRQC | 145 | select RENESAS_IRQC |
146 | select SOC_BUS | ||
146 | help | 147 | help |
147 | This enables support for the ARMv8 based Renesas SoCs. | 148 | This enables support for the ARMv8 based Renesas SoCs. |
148 | 149 | ||
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index e2249f01b2de..91c42b34705f 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile | |||
@@ -1,3 +1,5 @@ | |||
1 | obj-$(CONFIG_SOC_BUS) += renesas-soc.o | ||
2 | |||
1 | obj-$(CONFIG_ARCH_R8A7743) += rcar-sysc.o r8a7743-sysc.o | 3 | obj-$(CONFIG_ARCH_R8A7743) += rcar-sysc.o r8a7743-sysc.o |
2 | obj-$(CONFIG_ARCH_R8A7745) += rcar-sysc.o r8a7745-sysc.o | 4 | obj-$(CONFIG_ARCH_R8A7745) += rcar-sysc.o r8a7745-sysc.o |
3 | obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o | 5 | obj-$(CONFIG_ARCH_R8A7779) += rcar-sysc.o r8a7779-sysc.o |
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c new file mode 100644 index 000000000000..330960312296 --- /dev/null +++ b/drivers/soc/renesas/renesas-soc.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | * Renesas SoC Identification | ||
3 | * | ||
4 | * Copyright (C) 2014-2016 Glider bvba | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/io.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_address.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/string.h> | ||
21 | #include <linux/sys_soc.h> | ||
22 | |||
23 | |||
24 | struct renesas_family { | ||
25 | const char name[16]; | ||
26 | u32 reg; /* CCCR or PRR, if not in DT */ | ||
27 | }; | ||
28 | |||
29 | static const struct renesas_family fam_rcar_gen1 __initconst __maybe_unused = { | ||
30 | .name = "R-Car Gen1", | ||
31 | .reg = 0xff000044, /* PRR (Product Register) */ | ||
32 | }; | ||
33 | |||
34 | static const struct renesas_family fam_rcar_gen2 __initconst __maybe_unused = { | ||
35 | .name = "R-Car Gen2", | ||
36 | .reg = 0xff000044, /* PRR (Product Register) */ | ||
37 | }; | ||
38 | |||
39 | static const struct renesas_family fam_rcar_gen3 __initconst __maybe_unused = { | ||
40 | .name = "R-Car Gen3", | ||
41 | .reg = 0xfff00044, /* PRR (Product Register) */ | ||
42 | }; | ||
43 | |||
44 | static const struct renesas_family fam_rmobile __initconst __maybe_unused = { | ||
45 | .name = "R-Mobile", | ||
46 | .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */ | ||
47 | }; | ||
48 | |||
49 | static const struct renesas_family fam_rza __initconst __maybe_unused = { | ||
50 | .name = "RZ/A", | ||
51 | }; | ||
52 | |||
53 | static const struct renesas_family fam_rzg __initconst __maybe_unused = { | ||
54 | .name = "RZ/G", | ||
55 | .reg = 0xff000044, /* PRR (Product Register) */ | ||
56 | }; | ||
57 | |||
58 | static const struct renesas_family fam_shmobile __initconst __maybe_unused = { | ||
59 | .name = "SH-Mobile", | ||
60 | .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */ | ||
61 | }; | ||
62 | |||
63 | |||
64 | struct renesas_soc { | ||
65 | const struct renesas_family *family; | ||
66 | u8 id; | ||
67 | }; | ||
68 | |||
69 | static const struct renesas_soc soc_rz_a1h __initconst __maybe_unused = { | ||
70 | .family = &fam_rza, | ||
71 | }; | ||
72 | |||
73 | static const struct renesas_soc soc_rmobile_ape6 __initconst __maybe_unused = { | ||
74 | .family = &fam_rmobile, | ||
75 | .id = 0x3f, | ||
76 | }; | ||
77 | |||
78 | static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = { | ||
79 | .family = &fam_rmobile, | ||
80 | .id = 0x40, | ||
81 | }; | ||
82 | |||
83 | static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = { | ||
84 | .family = &fam_rzg, | ||
85 | .id = 0x47, | ||
86 | }; | ||
87 | |||
88 | static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = { | ||
89 | .family = &fam_rzg, | ||
90 | .id = 0x4c, | ||
91 | }; | ||
92 | |||
93 | static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = { | ||
94 | .family = &fam_rcar_gen1, | ||
95 | }; | ||
96 | |||
97 | static const struct renesas_soc soc_rcar_h1 __initconst __maybe_unused = { | ||
98 | .family = &fam_rcar_gen1, | ||
99 | .id = 0x3b, | ||
100 | }; | ||
101 | |||
102 | static const struct renesas_soc soc_rcar_h2 __initconst __maybe_unused = { | ||
103 | .family = &fam_rcar_gen2, | ||
104 | .id = 0x45, | ||
105 | }; | ||
106 | |||
107 | static const struct renesas_soc soc_rcar_m2_w __initconst __maybe_unused = { | ||
108 | .family = &fam_rcar_gen2, | ||
109 | .id = 0x47, | ||
110 | }; | ||
111 | |||
112 | static const struct renesas_soc soc_rcar_v2h __initconst __maybe_unused = { | ||
113 | .family = &fam_rcar_gen2, | ||
114 | .id = 0x4a, | ||
115 | }; | ||
116 | |||
117 | static const struct renesas_soc soc_rcar_m2_n __initconst __maybe_unused = { | ||
118 | .family = &fam_rcar_gen2, | ||
119 | .id = 0x4b, | ||
120 | }; | ||
121 | |||
122 | static const struct renesas_soc soc_rcar_e2 __initconst __maybe_unused = { | ||
123 | .family = &fam_rcar_gen2, | ||
124 | .id = 0x4c, | ||
125 | }; | ||
126 | |||
127 | static const struct renesas_soc soc_rcar_h3 __initconst __maybe_unused = { | ||
128 | .family = &fam_rcar_gen3, | ||
129 | .id = 0x4f, | ||
130 | }; | ||
131 | |||
132 | static const struct renesas_soc soc_rcar_m3_w __initconst __maybe_unused = { | ||
133 | .family = &fam_rcar_gen3, | ||
134 | .id = 0x52, | ||
135 | }; | ||
136 | |||
137 | static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = { | ||
138 | .family = &fam_shmobile, | ||
139 | .id = 0x37, | ||
140 | }; | ||
141 | |||
142 | |||
143 | static const struct of_device_id renesas_socs[] __initconst = { | ||
144 | #ifdef CONFIG_ARCH_R7S72100 | ||
145 | { .compatible = "renesas,r7s72100", .data = &soc_rz_a1h }, | ||
146 | #endif | ||
147 | #ifdef CONFIG_ARCH_R8A73A4 | ||
148 | { .compatible = "renesas,r8a73a4", .data = &soc_rmobile_ape6 }, | ||
149 | #endif | ||
150 | #ifdef CONFIG_ARCH_R8A7740 | ||
151 | { .compatible = "renesas,r8a7740", .data = &soc_rmobile_a1 }, | ||
152 | #endif | ||
153 | #ifdef CONFIG_ARCH_R8A7743 | ||
154 | { .compatible = "renesas,r8a7743", .data = &soc_rz_g1m }, | ||
155 | #endif | ||
156 | #ifdef CONFIG_ARCH_R8A7745 | ||
157 | { .compatible = "renesas,r8a7745", .data = &soc_rz_g1e }, | ||
158 | #endif | ||
159 | #ifdef CONFIG_ARCH_R8A7778 | ||
160 | { .compatible = "renesas,r8a7778", .data = &soc_rcar_m1a }, | ||
161 | #endif | ||
162 | #ifdef CONFIG_ARCH_R8A7779 | ||
163 | { .compatible = "renesas,r8a7779", .data = &soc_rcar_h1 }, | ||
164 | #endif | ||
165 | #ifdef CONFIG_ARCH_R8A7790 | ||
166 | { .compatible = "renesas,r8a7790", .data = &soc_rcar_h2 }, | ||
167 | #endif | ||
168 | #ifdef CONFIG_ARCH_R8A7791 | ||
169 | { .compatible = "renesas,r8a7791", .data = &soc_rcar_m2_w }, | ||
170 | #endif | ||
171 | #ifdef CONFIG_ARCH_R8A7792 | ||
172 | { .compatible = "renesas,r8a7792", .data = &soc_rcar_v2h }, | ||
173 | #endif | ||
174 | #ifdef CONFIG_ARCH_R8A7793 | ||
175 | { .compatible = "renesas,r8a7793", .data = &soc_rcar_m2_n }, | ||
176 | #endif | ||
177 | #ifdef CONFIG_ARCH_R8A7794 | ||
178 | { .compatible = "renesas,r8a7794", .data = &soc_rcar_e2 }, | ||
179 | #endif | ||
180 | #ifdef CONFIG_ARCH_R8A7795 | ||
181 | { .compatible = "renesas,r8a7795", .data = &soc_rcar_h3 }, | ||
182 | #endif | ||
183 | #ifdef CONFIG_ARCH_R8A7796 | ||
184 | { .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w }, | ||
185 | #endif | ||
186 | #ifdef CONFIG_ARCH_SH73A0 | ||
187 | { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, | ||
188 | #endif | ||
189 | { /* sentinel */ } | ||
190 | }; | ||
191 | |||
192 | static int __init renesas_soc_init(void) | ||
193 | { | ||
194 | struct soc_device_attribute *soc_dev_attr; | ||
195 | const struct renesas_family *family; | ||
196 | const struct of_device_id *match; | ||
197 | const struct renesas_soc *soc; | ||
198 | void __iomem *chipid = NULL; | ||
199 | struct soc_device *soc_dev; | ||
200 | struct device_node *np; | ||
201 | unsigned int product; | ||
202 | |||
203 | match = of_match_node(renesas_socs, of_root); | ||
204 | if (!match) | ||
205 | return -ENODEV; | ||
206 | |||
207 | soc = match->data; | ||
208 | family = soc->family; | ||
209 | |||
210 | /* Try PRR first, then hardcoded fallback */ | ||
211 | np = of_find_compatible_node(NULL, NULL, "renesas,prr"); | ||
212 | if (np) { | ||
213 | chipid = of_iomap(np, 0); | ||
214 | of_node_put(np); | ||
215 | } else if (soc->id) { | ||
216 | chipid = ioremap(family->reg, 4); | ||
217 | } | ||
218 | if (chipid) { | ||
219 | product = readl(chipid); | ||
220 | iounmap(chipid); | ||
221 | if (soc->id && ((product >> 8) & 0xff) != soc->id) { | ||
222 | pr_warn("SoC mismatch (product = 0x%x)\n", product); | ||
223 | return -ENODEV; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | ||
228 | if (!soc_dev_attr) | ||
229 | return -ENOMEM; | ||
230 | |||
231 | np = of_find_node_by_path("/"); | ||
232 | of_property_read_string(np, "model", &soc_dev_attr->machine); | ||
233 | of_node_put(np); | ||
234 | |||
235 | soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL); | ||
236 | soc_dev_attr->soc_id = kstrdup_const(strchr(match->compatible, ',') + 1, | ||
237 | GFP_KERNEL); | ||
238 | if (chipid) | ||
239 | soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", | ||
240 | ((product >> 4) & 0x0f) + 1, | ||
241 | product & 0xf); | ||
242 | |||
243 | pr_info("Detected Renesas %s %s %s\n", soc_dev_attr->family, | ||
244 | soc_dev_attr->soc_id, soc_dev_attr->revision ?: ""); | ||
245 | |||
246 | soc_dev = soc_device_register(soc_dev_attr); | ||
247 | if (IS_ERR(soc_dev)) { | ||
248 | kfree(soc_dev_attr->revision); | ||
249 | kfree_const(soc_dev_attr->soc_id); | ||
250 | kfree_const(soc_dev_attr->family); | ||
251 | kfree(soc_dev_attr); | ||
252 | return PTR_ERR(soc_dev); | ||
253 | } | ||
254 | |||
255 | return 0; | ||
256 | } | ||
257 | core_initcall(renesas_soc_init); | ||