renesas-soc.c (de4fb176622d54a82ea3ceb7362392aaf5ff0b5a) renesas-soc.c (2f89bef90de4740be33b2cb4ba95e0107df0d25e)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Renesas SoC Identification
4 *
5 * Copyright (C) 2014-2016 Glider bvba
6 */
7
8#include <linux/io.h>

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

59 .name = "RZ/G2",
60 .reg = 0xfff00044, /* PRR (Product Register) */
61};
62
63static const struct renesas_family fam_rzg2l __initconst __maybe_unused = {
64 .name = "RZ/G2L",
65};
66
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Renesas SoC Identification
4 *
5 * Copyright (C) 2014-2016 Glider bvba
6 */
7
8#include <linux/io.h>

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

59 .name = "RZ/G2",
60 .reg = 0xfff00044, /* PRR (Product Register) */
61};
62
63static const struct renesas_family fam_rzg2l __initconst __maybe_unused = {
64 .name = "RZ/G2L",
65};
66
67static const struct renesas_family fam_rzg2ul __initconst __maybe_unused = {
68 .name = "RZ/G2UL",
69};
70
71static const struct renesas_family fam_rzv2l __initconst __maybe_unused = {
72 .name = "RZ/V2L",
73};
74
67static const struct renesas_family fam_shmobile __initconst __maybe_unused = {
68 .name = "SH-Mobile",
69 .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */
70};
71
72
73struct renesas_soc {
74 const struct renesas_family *family;

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

139 .id = 0x4f,
140};
141
142static const struct renesas_soc soc_rz_g2l __initconst __maybe_unused = {
143 .family = &fam_rzg2l,
144 .id = 0x841c447,
145};
146
75static const struct renesas_family fam_shmobile __initconst __maybe_unused = {
76 .name = "SH-Mobile",
77 .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */
78};
79
80
81struct renesas_soc {
82 const struct renesas_family *family;

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

147 .id = 0x4f,
148};
149
150static const struct renesas_soc soc_rz_g2l __initconst __maybe_unused = {
151 .family = &fam_rzg2l,
152 .id = 0x841c447,
153};
154
155static const struct renesas_soc soc_rz_g2ul __initconst __maybe_unused = {
156 .family = &fam_rzg2ul,
157 .id = 0x8450447,
158};
159
160static const struct renesas_soc soc_rz_v2l __initconst __maybe_unused = {
161 .family = &fam_rzv2l,
162 .id = 0x8447447,
163};
164
147static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = {
148 .family = &fam_rcar_gen1,
149};
150
151static const struct renesas_soc soc_rcar_h1 __initconst __maybe_unused = {
152 .family = &fam_rcar_gen1,
153 .id = 0x3b,
154};

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

326 { .compatible = "renesas,r8a779m7", .data = &soc_rcar_d3 },
327#endif
328#ifdef CONFIG_ARCH_R8A779A0
329 { .compatible = "renesas,r8a779a0", .data = &soc_rcar_v3u },
330#endif
331#ifdef CONFIG_ARCH_R8A779F0
332 { .compatible = "renesas,r8a779f0", .data = &soc_rcar_s4 },
333#endif
165static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = {
166 .family = &fam_rcar_gen1,
167};
168
169static const struct renesas_soc soc_rcar_h1 __initconst __maybe_unused = {
170 .family = &fam_rcar_gen1,
171 .id = 0x3b,
172};

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

344 { .compatible = "renesas,r8a779m7", .data = &soc_rcar_d3 },
345#endif
346#ifdef CONFIG_ARCH_R8A779A0
347 { .compatible = "renesas,r8a779a0", .data = &soc_rcar_v3u },
348#endif
349#ifdef CONFIG_ARCH_R8A779F0
350 { .compatible = "renesas,r8a779f0", .data = &soc_rcar_s4 },
351#endif
352#if defined(CONFIG_ARCH_R9A07G043)
353 { .compatible = "renesas,r9a07g043", .data = &soc_rz_g2ul },
354#endif
334#if defined(CONFIG_ARCH_R9A07G044)
335 { .compatible = "renesas,r9a07g044", .data = &soc_rz_g2l },
336#endif
355#if defined(CONFIG_ARCH_R9A07G044)
356 { .compatible = "renesas,r9a07g044", .data = &soc_rz_g2l },
357#endif
358#if defined(CONFIG_ARCH_R9A07G054)
359 { .compatible = "renesas,r9a07g054", .data = &soc_rz_v2l },
360#endif
337#ifdef CONFIG_ARCH_SH73A0
338 { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 },
339#endif
340 { /* sentinel */ }
341};
342
343struct renesas_id {
344 unsigned int offset;

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

361
362static const struct renesas_id id_prr __initconst = {
363 .offset = 0,
364 .mask = 0xff00,
365};
366
367static const struct of_device_id renesas_ids[] __initconst = {
368 { .compatible = "renesas,bsid", .data = &id_bsid },
361#ifdef CONFIG_ARCH_SH73A0
362 { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 },
363#endif
364 { /* sentinel */ }
365};
366
367struct renesas_id {
368 unsigned int offset;

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

385
386static const struct renesas_id id_prr __initconst = {
387 .offset = 0,
388 .mask = 0xff00,
389};
390
391static const struct of_device_id renesas_ids[] __initconst = {
392 { .compatible = "renesas,bsid", .data = &id_bsid },
393 { .compatible = "renesas,r9a07g043-sysc", .data = &id_rzg2l },
369 { .compatible = "renesas,r9a07g044-sysc", .data = &id_rzg2l },
394 { .compatible = "renesas,r9a07g044-sysc", .data = &id_rzg2l },
395 { .compatible = "renesas,r9a07g054-sysc", .data = &id_rzg2l },
370 { .compatible = "renesas,prr", .data = &id_prr },
371 { /* sentinel */ }
372};
373
374static int __init renesas_soc_init(void)
375{
376 struct soc_device_attribute *soc_dev_attr;
377 unsigned int product, eshi = 0, eslo;
378 const struct renesas_family *family;
379 const struct of_device_id *match;
380 const struct renesas_soc *soc;
381 const struct renesas_id *id;
382 void __iomem *chipid = NULL;
396 { .compatible = "renesas,prr", .data = &id_prr },
397 { /* sentinel */ }
398};
399
400static int __init renesas_soc_init(void)
401{
402 struct soc_device_attribute *soc_dev_attr;
403 unsigned int product, eshi = 0, eslo;
404 const struct renesas_family *family;
405 const struct of_device_id *match;
406 const struct renesas_soc *soc;
407 const struct renesas_id *id;
408 void __iomem *chipid = NULL;
409 const char *rev_prefix = "";
383 struct soc_device *soc_dev;
384 struct device_node *np;
385 const char *soc_id;
410 struct soc_device *soc_dev;
411 struct device_node *np;
412 const char *soc_id;
413 int ret;
386
387 match = of_match_node(renesas_socs, of_root);
388 if (!match)
389 return -ENODEV;
390
391 soc_id = strchr(match->compatible, ',') + 1;
392 soc = match->data;
393 family = soc->family;

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

398 chipid = of_iomap(np, 0);
399 of_node_put(np);
400 } else if (soc->id && family->reg) {
401 /* Try hardcoded CCCR/PRR fallback */
402 id = &id_prr;
403 chipid = ioremap(family->reg, 4);
404 }
405
414
415 match = of_match_node(renesas_socs, of_root);
416 if (!match)
417 return -ENODEV;
418
419 soc_id = strchr(match->compatible, ',') + 1;
420 soc = match->data;
421 family = soc->family;

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

426 chipid = of_iomap(np, 0);
427 of_node_put(np);
428 } else if (soc->id && family->reg) {
429 /* Try hardcoded CCCR/PRR fallback */
430 id = &id_prr;
431 chipid = ioremap(family->reg, 4);
432 }
433
434 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
435 if (!soc_dev_attr)
436 return -ENOMEM;
437
438 np = of_find_node_by_path("/");
439 of_property_read_string(np, "model", &soc_dev_attr->machine);
440 of_node_put(np);
441
442 soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL);
443 soc_dev_attr->soc_id = kstrdup_const(soc_id, GFP_KERNEL);
444
406 if (chipid) {
407 product = readl(chipid + id->offset);
408 iounmap(chipid);
409
410 if (id == &id_prr) {
411 /* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */
412 if ((product & 0x7fff) == 0x5210)
413 product ^= 0x11;
414 /* R-Car M3-W ES1.3 incorrectly identifies as ES2.1 */
415 if ((product & 0x7fff) == 0x5211)
416 product ^= 0x12;
417
418 eshi = ((product >> 4) & 0x0f) + 1;
419 eslo = product & 0xf;
445 if (chipid) {
446 product = readl(chipid + id->offset);
447 iounmap(chipid);
448
449 if (id == &id_prr) {
450 /* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */
451 if ((product & 0x7fff) == 0x5210)
452 product ^= 0x11;
453 /* R-Car M3-W ES1.3 incorrectly identifies as ES2.1 */
454 if ((product & 0x7fff) == 0x5211)
455 product ^= 0x12;
456
457 eshi = ((product >> 4) & 0x0f) + 1;
458 eslo = product & 0xf;
459 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u",
460 eshi, eslo);
461 } else if (id == &id_rzg2l) {
462 eshi = ((product >> 28) & 0x0f);
463 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u",
464 eshi);
465 rev_prefix = "Rev ";
420 }
421
422 if (soc->id &&
423 ((product & id->mask) >> __ffs(id->mask)) != soc->id) {
424 pr_warn("SoC mismatch (product = 0x%x)\n", product);
466 }
467
468 if (soc->id &&
469 ((product & id->mask) >> __ffs(id->mask)) != soc->id) {
470 pr_warn("SoC mismatch (product = 0x%x)\n", product);
425 return -ENODEV;
471 ret = -ENODEV;
472 goto free_soc_dev_attr;
426 }
427 }
428
473 }
474 }
475
429 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
430 if (!soc_dev_attr)
431 return -ENOMEM;
476 pr_info("Detected Renesas %s %s %s%s\n", soc_dev_attr->family,
477 soc_dev_attr->soc_id, rev_prefix, soc_dev_attr->revision ?: "");
432
478
433 np = of_find_node_by_path("/");
434 of_property_read_string(np, "model", &soc_dev_attr->machine);
435 of_node_put(np);
436
437 soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL);
438 soc_dev_attr->soc_id = kstrdup_const(soc_id, GFP_KERNEL);
439 if (eshi)
440 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", eshi,
441 eslo);
442
443 pr_info("Detected Renesas %s %s %s\n", soc_dev_attr->family,
444 soc_dev_attr->soc_id, soc_dev_attr->revision ?: "");
445
446 soc_dev = soc_device_register(soc_dev_attr);
447 if (IS_ERR(soc_dev)) {
479 soc_dev = soc_device_register(soc_dev_attr);
480 if (IS_ERR(soc_dev)) {
448 kfree(soc_dev_attr->revision);
449 kfree_const(soc_dev_attr->soc_id);
450 kfree_const(soc_dev_attr->family);
451 kfree(soc_dev_attr);
452 return PTR_ERR(soc_dev);
481 ret = PTR_ERR(soc_dev);
482 goto free_soc_dev_attr;
453 }
454
455 return 0;
483 }
484
485 return 0;
486
487free_soc_dev_attr:
488 kfree(soc_dev_attr->revision);
489 kfree_const(soc_dev_attr->soc_id);
490 kfree_const(soc_dev_attr->family);
491 kfree(soc_dev_attr);
492 return ret;
456}
457early_initcall(renesas_soc_init);
493}
494early_initcall(renesas_soc_init);