renesas-soc.c (2a4056a759e26745f3a19431f5428c581fd8f347) renesas-soc.c (175f435f44b724e389f23c154d94fda45870c1f6)
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.

--- 32 unchanged lines hidden (view full) ---

41 .reg = 0xfff00044, /* PRR (Product Register) */
42};
43
44static const struct renesas_family fam_rmobile __initconst __maybe_unused = {
45 .name = "R-Mobile",
46 .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */
47};
48
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.

--- 32 unchanged lines hidden (view full) ---

41 .reg = 0xfff00044, /* PRR (Product Register) */
42};
43
44static const struct renesas_family fam_rmobile __initconst __maybe_unused = {
45 .name = "R-Mobile",
46 .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */
47};
48
49static const struct renesas_family fam_rza __initconst __maybe_unused = {
50 .name = "RZ/A",
49static const struct renesas_family fam_rza1 __initconst __maybe_unused = {
50 .name = "RZ/A1",
51};
52
51};
52
53static const struct renesas_family fam_rza2 __initconst __maybe_unused = {
54 .name = "RZ/A2",
55};
56
53static const struct renesas_family fam_rzg1 __initconst __maybe_unused = {
54 .name = "RZ/G1",
55 .reg = 0xff000044, /* PRR (Product Register) */
56};
57
58static const struct renesas_family fam_rzg2 __initconst __maybe_unused = {
59 .name = "RZ/G2",
60 .reg = 0xfff00044, /* PRR (Product Register) */

--- 6 unchanged lines hidden (view full) ---

67
68
69struct renesas_soc {
70 const struct renesas_family *family;
71 u8 id;
72};
73
74static const struct renesas_soc soc_rz_a1h __initconst __maybe_unused = {
57static const struct renesas_family fam_rzg1 __initconst __maybe_unused = {
58 .name = "RZ/G1",
59 .reg = 0xff000044, /* PRR (Product Register) */
60};
61
62static const struct renesas_family fam_rzg2 __initconst __maybe_unused = {
63 .name = "RZ/G2",
64 .reg = 0xfff00044, /* PRR (Product Register) */

--- 6 unchanged lines hidden (view full) ---

71
72
73struct renesas_soc {
74 const struct renesas_family *family;
75 u8 id;
76};
77
78static const struct renesas_soc soc_rz_a1h __initconst __maybe_unused = {
75 .family = &fam_rza,
79 .family = &fam_rza1,
76};
77
80};
81
82static const struct renesas_soc soc_rz_a2m __initconst __maybe_unused = {
83 .family = &fam_rza2,
84 .id = 0x3b,
85};
86
78static const struct renesas_soc soc_rmobile_ape6 __initconst __maybe_unused = {
79 .family = &fam_rmobile,
80 .id = 0x3f,
81};
82
83static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = {
84 .family = &fam_rmobile,
85 .id = 0x40,

--- 103 unchanged lines hidden (view full) ---

189 .id = 0x37,
190};
191
192
193static const struct of_device_id renesas_socs[] __initconst = {
194#ifdef CONFIG_ARCH_R7S72100
195 { .compatible = "renesas,r7s72100", .data = &soc_rz_a1h },
196#endif
87static const struct renesas_soc soc_rmobile_ape6 __initconst __maybe_unused = {
88 .family = &fam_rmobile,
89 .id = 0x3f,
90};
91
92static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = {
93 .family = &fam_rmobile,
94 .id = 0x40,

--- 103 unchanged lines hidden (view full) ---

198 .id = 0x37,
199};
200
201
202static const struct of_device_id renesas_socs[] __initconst = {
203#ifdef CONFIG_ARCH_R7S72100
204 { .compatible = "renesas,r7s72100", .data = &soc_rz_a1h },
205#endif
206#ifdef CONFIG_ARCH_R7S9210
207 { .compatible = "renesas,r7s9210", .data = &soc_rz_a2m },
208#endif
197#ifdef CONFIG_ARCH_R8A73A4
198 { .compatible = "renesas,r8a73a4", .data = &soc_rmobile_ape6 },
199#endif
200#ifdef CONFIG_ARCH_R8A7740
201 { .compatible = "renesas,r8a7740", .data = &soc_rmobile_a1 },
202#endif
203#ifdef CONFIG_ARCH_R8A7742
204 { .compatible = "renesas,r8a7742", .data = &soc_rz_g1h },

--- 65 unchanged lines hidden (view full) ---

270{
271 struct soc_device_attribute *soc_dev_attr;
272 const struct renesas_family *family;
273 const struct of_device_id *match;
274 const struct renesas_soc *soc;
275 void __iomem *chipid = NULL;
276 struct soc_device *soc_dev;
277 struct device_node *np;
209#ifdef CONFIG_ARCH_R8A73A4
210 { .compatible = "renesas,r8a73a4", .data = &soc_rmobile_ape6 },
211#endif
212#ifdef CONFIG_ARCH_R8A7740
213 { .compatible = "renesas,r8a7740", .data = &soc_rmobile_a1 },
214#endif
215#ifdef CONFIG_ARCH_R8A7742
216 { .compatible = "renesas,r8a7742", .data = &soc_rz_g1h },

--- 65 unchanged lines hidden (view full) ---

282{
283 struct soc_device_attribute *soc_dev_attr;
284 const struct renesas_family *family;
285 const struct of_device_id *match;
286 const struct renesas_soc *soc;
287 void __iomem *chipid = NULL;
288 struct soc_device *soc_dev;
289 struct device_node *np;
278 unsigned int product;
290 unsigned int product, eshi = 0, eslo;
279
280 match = of_match_node(renesas_socs, of_root);
281 if (!match)
282 return -ENODEV;
283
284 soc = match->data;
285 family = soc->family;
286
291
292 match = of_match_node(renesas_socs, of_root);
293 if (!match)
294 return -ENODEV;
295
296 soc = match->data;
297 family = soc->family;
298
299 np = of_find_compatible_node(NULL, NULL, "renesas,bsid");
300 if (np) {
301 chipid = of_iomap(np, 0);
302 of_node_put(np);
303
304 if (chipid) {
305 product = readl(chipid);
306 iounmap(chipid);
307
308 if (soc->id && ((product >> 16) & 0xff) != soc->id) {
309 pr_warn("SoC mismatch (product = 0x%x)\n",
310 product);
311 return -ENODEV;
312 }
313 }
314
315 /*
316 * TODO: Upper 4 bits of BSID are for chip version, but the
317 * format is not known at this time so we don't know how to
318 * specify eshi and eslo
319 */
320
321 goto done;
322 }
323
287 /* Try PRR first, then hardcoded fallback */
288 np = of_find_compatible_node(NULL, NULL, "renesas,prr");
289 if (np) {
290 chipid = of_iomap(np, 0);
291 of_node_put(np);
292 } else if (soc->id) {
293 chipid = ioremap(family->reg, 4);
294 }
295 if (chipid) {
296 product = readl(chipid);
297 iounmap(chipid);
298 /* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */
299 if ((product & 0x7fff) == 0x5210)
300 product ^= 0x11;
301 if (soc->id && ((product >> 8) & 0xff) != soc->id) {
302 pr_warn("SoC mismatch (product = 0x%x)\n", product);
303 return -ENODEV;
304 }
324 /* Try PRR first, then hardcoded fallback */
325 np = of_find_compatible_node(NULL, NULL, "renesas,prr");
326 if (np) {
327 chipid = of_iomap(np, 0);
328 of_node_put(np);
329 } else if (soc->id) {
330 chipid = ioremap(family->reg, 4);
331 }
332 if (chipid) {
333 product = readl(chipid);
334 iounmap(chipid);
335 /* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */
336 if ((product & 0x7fff) == 0x5210)
337 product ^= 0x11;
338 if (soc->id && ((product >> 8) & 0xff) != soc->id) {
339 pr_warn("SoC mismatch (product = 0x%x)\n", product);
340 return -ENODEV;
341 }
342 eshi = ((product >> 4) & 0x0f) + 1;
343 eslo = product & 0xf;
305 }
306
344 }
345
346done:
307 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
308 if (!soc_dev_attr)
309 return -ENOMEM;
310
311 np = of_find_node_by_path("/");
312 of_property_read_string(np, "model", &soc_dev_attr->machine);
313 of_node_put(np);
314
315 soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL);
316 soc_dev_attr->soc_id = kstrdup_const(strchr(match->compatible, ',') + 1,
317 GFP_KERNEL);
347 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
348 if (!soc_dev_attr)
349 return -ENOMEM;
350
351 np = of_find_node_by_path("/");
352 of_property_read_string(np, "model", &soc_dev_attr->machine);
353 of_node_put(np);
354
355 soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL);
356 soc_dev_attr->soc_id = kstrdup_const(strchr(match->compatible, ',') + 1,
357 GFP_KERNEL);
318 if (chipid)
319 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u",
320 ((product >> 4) & 0x0f) + 1,
321 product & 0xf);
358 if (eshi)
359 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", eshi,
360 eslo);
322
323 pr_info("Detected Renesas %s %s %s\n", soc_dev_attr->family,
324 soc_dev_attr->soc_id, soc_dev_attr->revision ?: "");
325
326 soc_dev = soc_device_register(soc_dev_attr);
327 if (IS_ERR(soc_dev)) {
328 kfree(soc_dev_attr->revision);
329 kfree_const(soc_dev_attr->soc_id);
330 kfree_const(soc_dev_attr->family);
331 kfree(soc_dev_attr);
332 return PTR_ERR(soc_dev);
333 }
334
335 return 0;
336}
337early_initcall(renesas_soc_init);
361
362 pr_info("Detected Renesas %s %s %s\n", soc_dev_attr->family,
363 soc_dev_attr->soc_id, soc_dev_attr->revision ?: "");
364
365 soc_dev = soc_device_register(soc_dev_attr);
366 if (IS_ERR(soc_dev)) {
367 kfree(soc_dev_attr->revision);
368 kfree_const(soc_dev_attr->soc_id);
369 kfree_const(soc_dev_attr->family);
370 kfree(soc_dev_attr);
371 return PTR_ERR(soc_dev);
372 }
373
374 return 0;
375}
376early_initcall(renesas_soc_init);