0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/io.h>
0009 #include <linux/of.h>
0010 #include <linux/of_address.h>
0011 #include <linux/slab.h>
0012 #include <linux/string.h>
0013 #include <linux/sys_soc.h>
0014
0015
0016 struct renesas_family {
0017 const char name[16];
0018 u32 reg;
0019 };
0020
0021 static const struct renesas_family fam_rcar_gen1 __initconst __maybe_unused = {
0022 .name = "R-Car Gen1",
0023 .reg = 0xff000044,
0024 };
0025
0026 static const struct renesas_family fam_rcar_gen2 __initconst __maybe_unused = {
0027 .name = "R-Car Gen2",
0028 .reg = 0xff000044,
0029 };
0030
0031 static const struct renesas_family fam_rcar_gen3 __initconst __maybe_unused = {
0032 .name = "R-Car Gen3",
0033 .reg = 0xfff00044,
0034 };
0035
0036 static const struct renesas_family fam_rcar_gen4 __initconst __maybe_unused = {
0037 .name = "R-Car Gen4",
0038 };
0039
0040 static const struct renesas_family fam_rmobile __initconst __maybe_unused = {
0041 .name = "R-Mobile",
0042 .reg = 0xe600101c,
0043 };
0044
0045 static const struct renesas_family fam_rza1 __initconst __maybe_unused = {
0046 .name = "RZ/A1",
0047 };
0048
0049 static const struct renesas_family fam_rza2 __initconst __maybe_unused = {
0050 .name = "RZ/A2",
0051 };
0052
0053 static const struct renesas_family fam_rzg1 __initconst __maybe_unused = {
0054 .name = "RZ/G1",
0055 .reg = 0xff000044,
0056 };
0057
0058 static const struct renesas_family fam_rzg2 __initconst __maybe_unused = {
0059 .name = "RZ/G2",
0060 .reg = 0xfff00044,
0061 };
0062
0063 static const struct renesas_family fam_rzg2l __initconst __maybe_unused = {
0064 .name = "RZ/G2L",
0065 };
0066
0067 static const struct renesas_family fam_rzg2ul __initconst __maybe_unused = {
0068 .name = "RZ/G2UL",
0069 };
0070
0071 static const struct renesas_family fam_rzv2l __initconst __maybe_unused = {
0072 .name = "RZ/V2L",
0073 };
0074
0075 static const struct renesas_family fam_shmobile __initconst __maybe_unused = {
0076 .name = "SH-Mobile",
0077 .reg = 0xe600101c,
0078 };
0079
0080
0081 struct renesas_soc {
0082 const struct renesas_family *family;
0083 u32 id;
0084 };
0085
0086 static const struct renesas_soc soc_rz_a1h __initconst __maybe_unused = {
0087 .family = &fam_rza1,
0088 };
0089
0090 static const struct renesas_soc soc_rz_a2m __initconst __maybe_unused = {
0091 .family = &fam_rza2,
0092 .id = 0x3b,
0093 };
0094
0095 static const struct renesas_soc soc_rmobile_ape6 __initconst __maybe_unused = {
0096 .family = &fam_rmobile,
0097 .id = 0x3f,
0098 };
0099
0100 static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = {
0101 .family = &fam_rmobile,
0102 .id = 0x40,
0103 };
0104
0105 static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = {
0106 .family = &fam_rzg1,
0107 .id = 0x45,
0108 };
0109
0110 static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = {
0111 .family = &fam_rzg1,
0112 .id = 0x47,
0113 };
0114
0115 static const struct renesas_soc soc_rz_g1n __initconst __maybe_unused = {
0116 .family = &fam_rzg1,
0117 .id = 0x4b,
0118 };
0119
0120 static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = {
0121 .family = &fam_rzg1,
0122 .id = 0x4c,
0123 };
0124
0125 static const struct renesas_soc soc_rz_g1c __initconst __maybe_unused = {
0126 .family = &fam_rzg1,
0127 .id = 0x53,
0128 };
0129
0130 static const struct renesas_soc soc_rz_g2m __initconst __maybe_unused = {
0131 .family = &fam_rzg2,
0132 .id = 0x52,
0133 };
0134
0135 static const struct renesas_soc soc_rz_g2n __initconst __maybe_unused = {
0136 .family = &fam_rzg2,
0137 .id = 0x55,
0138 };
0139
0140 static const struct renesas_soc soc_rz_g2e __initconst __maybe_unused = {
0141 .family = &fam_rzg2,
0142 .id = 0x57,
0143 };
0144
0145 static const struct renesas_soc soc_rz_g2h __initconst __maybe_unused = {
0146 .family = &fam_rzg2,
0147 .id = 0x4f,
0148 };
0149
0150 static const struct renesas_soc soc_rz_g2l __initconst __maybe_unused = {
0151 .family = &fam_rzg2l,
0152 .id = 0x841c447,
0153 };
0154
0155 static const struct renesas_soc soc_rz_g2ul __initconst __maybe_unused = {
0156 .family = &fam_rzg2ul,
0157 .id = 0x8450447,
0158 };
0159
0160 static const struct renesas_soc soc_rz_v2l __initconst __maybe_unused = {
0161 .family = &fam_rzv2l,
0162 .id = 0x8447447,
0163 };
0164
0165 static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = {
0166 .family = &fam_rcar_gen1,
0167 };
0168
0169 static const struct renesas_soc soc_rcar_h1 __initconst __maybe_unused = {
0170 .family = &fam_rcar_gen1,
0171 .id = 0x3b,
0172 };
0173
0174 static const struct renesas_soc soc_rcar_h2 __initconst __maybe_unused = {
0175 .family = &fam_rcar_gen2,
0176 .id = 0x45,
0177 };
0178
0179 static const struct renesas_soc soc_rcar_m2_w __initconst __maybe_unused = {
0180 .family = &fam_rcar_gen2,
0181 .id = 0x47,
0182 };
0183
0184 static const struct renesas_soc soc_rcar_v2h __initconst __maybe_unused = {
0185 .family = &fam_rcar_gen2,
0186 .id = 0x4a,
0187 };
0188
0189 static const struct renesas_soc soc_rcar_m2_n __initconst __maybe_unused = {
0190 .family = &fam_rcar_gen2,
0191 .id = 0x4b,
0192 };
0193
0194 static const struct renesas_soc soc_rcar_e2 __initconst __maybe_unused = {
0195 .family = &fam_rcar_gen2,
0196 .id = 0x4c,
0197 };
0198
0199 static const struct renesas_soc soc_rcar_h3 __initconst __maybe_unused = {
0200 .family = &fam_rcar_gen3,
0201 .id = 0x4f,
0202 };
0203
0204 static const struct renesas_soc soc_rcar_m3_w __initconst __maybe_unused = {
0205 .family = &fam_rcar_gen3,
0206 .id = 0x52,
0207 };
0208
0209 static const struct renesas_soc soc_rcar_m3_n __initconst __maybe_unused = {
0210 .family = &fam_rcar_gen3,
0211 .id = 0x55,
0212 };
0213
0214 static const struct renesas_soc soc_rcar_v3m __initconst __maybe_unused = {
0215 .family = &fam_rcar_gen3,
0216 .id = 0x54,
0217 };
0218
0219 static const struct renesas_soc soc_rcar_v3h __initconst __maybe_unused = {
0220 .family = &fam_rcar_gen3,
0221 .id = 0x56,
0222 };
0223
0224 static const struct renesas_soc soc_rcar_e3 __initconst __maybe_unused = {
0225 .family = &fam_rcar_gen3,
0226 .id = 0x57,
0227 };
0228
0229 static const struct renesas_soc soc_rcar_d3 __initconst __maybe_unused = {
0230 .family = &fam_rcar_gen3,
0231 .id = 0x58,
0232 };
0233
0234 static const struct renesas_soc soc_rcar_v3u __initconst __maybe_unused = {
0235 .family = &fam_rcar_gen4,
0236 .id = 0x59,
0237 };
0238
0239 static const struct renesas_soc soc_rcar_s4 __initconst __maybe_unused = {
0240 .family = &fam_rcar_gen4,
0241 .id = 0x5a,
0242 };
0243
0244 static const struct renesas_soc soc_rcar_v4h __initconst __maybe_unused = {
0245 .family = &fam_rcar_gen4,
0246 .id = 0x5c,
0247 };
0248
0249 static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = {
0250 .family = &fam_shmobile,
0251 .id = 0x37,
0252 };
0253
0254
0255 static const struct of_device_id renesas_socs[] __initconst = {
0256 #ifdef CONFIG_ARCH_R7S72100
0257 { .compatible = "renesas,r7s72100", .data = &soc_rz_a1h },
0258 #endif
0259 #ifdef CONFIG_ARCH_R7S9210
0260 { .compatible = "renesas,r7s9210", .data = &soc_rz_a2m },
0261 #endif
0262 #ifdef CONFIG_ARCH_R8A73A4
0263 { .compatible = "renesas,r8a73a4", .data = &soc_rmobile_ape6 },
0264 #endif
0265 #ifdef CONFIG_ARCH_R8A7740
0266 { .compatible = "renesas,r8a7740", .data = &soc_rmobile_a1 },
0267 #endif
0268 #ifdef CONFIG_ARCH_R8A7742
0269 { .compatible = "renesas,r8a7742", .data = &soc_rz_g1h },
0270 #endif
0271 #ifdef CONFIG_ARCH_R8A7743
0272 { .compatible = "renesas,r8a7743", .data = &soc_rz_g1m },
0273 #endif
0274 #ifdef CONFIG_ARCH_R8A7744
0275 { .compatible = "renesas,r8a7744", .data = &soc_rz_g1n },
0276 #endif
0277 #ifdef CONFIG_ARCH_R8A7745
0278 { .compatible = "renesas,r8a7745", .data = &soc_rz_g1e },
0279 #endif
0280 #ifdef CONFIG_ARCH_R8A77470
0281 { .compatible = "renesas,r8a77470", .data = &soc_rz_g1c },
0282 #endif
0283 #ifdef CONFIG_ARCH_R8A774A1
0284 { .compatible = "renesas,r8a774a1", .data = &soc_rz_g2m },
0285 #endif
0286 #ifdef CONFIG_ARCH_R8A774B1
0287 { .compatible = "renesas,r8a774b1", .data = &soc_rz_g2n },
0288 #endif
0289 #ifdef CONFIG_ARCH_R8A774C0
0290 { .compatible = "renesas,r8a774c0", .data = &soc_rz_g2e },
0291 #endif
0292 #ifdef CONFIG_ARCH_R8A774E1
0293 { .compatible = "renesas,r8a774e1", .data = &soc_rz_g2h },
0294 #endif
0295 #ifdef CONFIG_ARCH_R8A7778
0296 { .compatible = "renesas,r8a7778", .data = &soc_rcar_m1a },
0297 #endif
0298 #ifdef CONFIG_ARCH_R8A7779
0299 { .compatible = "renesas,r8a7779", .data = &soc_rcar_h1 },
0300 #endif
0301 #ifdef CONFIG_ARCH_R8A7790
0302 { .compatible = "renesas,r8a7790", .data = &soc_rcar_h2 },
0303 #endif
0304 #ifdef CONFIG_ARCH_R8A7791
0305 { .compatible = "renesas,r8a7791", .data = &soc_rcar_m2_w },
0306 #endif
0307 #ifdef CONFIG_ARCH_R8A7792
0308 { .compatible = "renesas,r8a7792", .data = &soc_rcar_v2h },
0309 #endif
0310 #ifdef CONFIG_ARCH_R8A7793
0311 { .compatible = "renesas,r8a7793", .data = &soc_rcar_m2_n },
0312 #endif
0313 #ifdef CONFIG_ARCH_R8A7794
0314 { .compatible = "renesas,r8a7794", .data = &soc_rcar_e2 },
0315 #endif
0316 #if defined(CONFIG_ARCH_R8A77950) || defined(CONFIG_ARCH_R8A77951)
0317 { .compatible = "renesas,r8a7795", .data = &soc_rcar_h3 },
0318 #endif
0319 #ifdef CONFIG_ARCH_R8A77951
0320 { .compatible = "renesas,r8a779m0", .data = &soc_rcar_h3 },
0321 { .compatible = "renesas,r8a779m1", .data = &soc_rcar_h3 },
0322 { .compatible = "renesas,r8a779m8", .data = &soc_rcar_h3 },
0323 #endif
0324 #ifdef CONFIG_ARCH_R8A77960
0325 { .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w },
0326 #endif
0327 #ifdef CONFIG_ARCH_R8A77961
0328 { .compatible = "renesas,r8a77961", .data = &soc_rcar_m3_w },
0329 { .compatible = "renesas,r8a779m2", .data = &soc_rcar_m3_w },
0330 { .compatible = "renesas,r8a779m3", .data = &soc_rcar_m3_w },
0331 #endif
0332 #ifdef CONFIG_ARCH_R8A77965
0333 { .compatible = "renesas,r8a77965", .data = &soc_rcar_m3_n },
0334 { .compatible = "renesas,r8a779m4", .data = &soc_rcar_m3_n },
0335 { .compatible = "renesas,r8a779m5", .data = &soc_rcar_m3_n },
0336 #endif
0337 #ifdef CONFIG_ARCH_R8A77970
0338 { .compatible = "renesas,r8a77970", .data = &soc_rcar_v3m },
0339 #endif
0340 #ifdef CONFIG_ARCH_R8A77980
0341 { .compatible = "renesas,r8a77980", .data = &soc_rcar_v3h },
0342 #endif
0343 #ifdef CONFIG_ARCH_R8A77990
0344 { .compatible = "renesas,r8a77990", .data = &soc_rcar_e3 },
0345 { .compatible = "renesas,r8a779m6", .data = &soc_rcar_e3 },
0346 #endif
0347 #ifdef CONFIG_ARCH_R8A77995
0348 { .compatible = "renesas,r8a77995", .data = &soc_rcar_d3 },
0349 { .compatible = "renesas,r8a779m7", .data = &soc_rcar_d3 },
0350 #endif
0351 #ifdef CONFIG_ARCH_R8A779A0
0352 { .compatible = "renesas,r8a779a0", .data = &soc_rcar_v3u },
0353 #endif
0354 #ifdef CONFIG_ARCH_R8A779F0
0355 { .compatible = "renesas,r8a779f0", .data = &soc_rcar_s4 },
0356 #endif
0357 #ifdef CONFIG_ARCH_R8A779G0
0358 { .compatible = "renesas,r8a779g0", .data = &soc_rcar_v4h },
0359 #endif
0360 #if defined(CONFIG_ARCH_R9A07G043)
0361 { .compatible = "renesas,r9a07g043", .data = &soc_rz_g2ul },
0362 #endif
0363 #if defined(CONFIG_ARCH_R9A07G044)
0364 { .compatible = "renesas,r9a07g044", .data = &soc_rz_g2l },
0365 #endif
0366 #if defined(CONFIG_ARCH_R9A07G054)
0367 { .compatible = "renesas,r9a07g054", .data = &soc_rz_v2l },
0368 #endif
0369 #ifdef CONFIG_ARCH_SH73A0
0370 { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 },
0371 #endif
0372 { }
0373 };
0374
0375 struct renesas_id {
0376 unsigned int offset;
0377 u32 mask;
0378 };
0379
0380 static const struct renesas_id id_bsid __initconst = {
0381 .offset = 0,
0382 .mask = 0xff0000,
0383
0384
0385
0386
0387 };
0388
0389 static const struct renesas_id id_rzg2l __initconst = {
0390 .offset = 0xa04,
0391 .mask = 0xfffffff,
0392 };
0393
0394 static const struct renesas_id id_prr __initconst = {
0395 .offset = 0,
0396 .mask = 0xff00,
0397 };
0398
0399 static const struct of_device_id renesas_ids[] __initconst = {
0400 { .compatible = "renesas,bsid", .data = &id_bsid },
0401 { .compatible = "renesas,r9a07g043-sysc", .data = &id_rzg2l },
0402 { .compatible = "renesas,r9a07g044-sysc", .data = &id_rzg2l },
0403 { .compatible = "renesas,r9a07g054-sysc", .data = &id_rzg2l },
0404 { .compatible = "renesas,prr", .data = &id_prr },
0405 { }
0406 };
0407
0408 static int __init renesas_soc_init(void)
0409 {
0410 struct soc_device_attribute *soc_dev_attr;
0411 unsigned int product, eshi = 0, eslo;
0412 const struct renesas_family *family;
0413 const struct of_device_id *match;
0414 const struct renesas_soc *soc;
0415 const struct renesas_id *id;
0416 void __iomem *chipid = NULL;
0417 const char *rev_prefix = "";
0418 struct soc_device *soc_dev;
0419 struct device_node *np;
0420 const char *soc_id;
0421 int ret;
0422
0423 match = of_match_node(renesas_socs, of_root);
0424 if (!match)
0425 return -ENODEV;
0426
0427 soc_id = strchr(match->compatible, ',') + 1;
0428 soc = match->data;
0429 family = soc->family;
0430
0431 np = of_find_matching_node_and_match(NULL, renesas_ids, &match);
0432 if (np) {
0433 id = match->data;
0434 chipid = of_iomap(np, 0);
0435 of_node_put(np);
0436 } else if (soc->id && family->reg) {
0437
0438 id = &id_prr;
0439 chipid = ioremap(family->reg, 4);
0440 }
0441
0442 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
0443 if (!soc_dev_attr)
0444 return -ENOMEM;
0445
0446 np = of_find_node_by_path("/");
0447 of_property_read_string(np, "model", &soc_dev_attr->machine);
0448 of_node_put(np);
0449
0450 soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL);
0451 soc_dev_attr->soc_id = kstrdup_const(soc_id, GFP_KERNEL);
0452
0453 if (chipid) {
0454 product = readl(chipid + id->offset);
0455 iounmap(chipid);
0456
0457 if (id == &id_prr) {
0458
0459 if ((product & 0x7fff) == 0x5210)
0460 product ^= 0x11;
0461
0462 if ((product & 0x7fff) == 0x5211)
0463 product ^= 0x12;
0464
0465 eshi = ((product >> 4) & 0x0f) + 1;
0466 eslo = product & 0xf;
0467 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u",
0468 eshi, eslo);
0469 } else if (id == &id_rzg2l) {
0470 eshi = ((product >> 28) & 0x0f);
0471 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u",
0472 eshi);
0473 rev_prefix = "Rev ";
0474 }
0475
0476 if (soc->id &&
0477 ((product & id->mask) >> __ffs(id->mask)) != soc->id) {
0478 pr_warn("SoC mismatch (product = 0x%x)\n", product);
0479 ret = -ENODEV;
0480 goto free_soc_dev_attr;
0481 }
0482 }
0483
0484 pr_info("Detected Renesas %s %s %s%s\n", soc_dev_attr->family,
0485 soc_dev_attr->soc_id, rev_prefix, soc_dev_attr->revision ?: "");
0486
0487 soc_dev = soc_device_register(soc_dev_attr);
0488 if (IS_ERR(soc_dev)) {
0489 ret = PTR_ERR(soc_dev);
0490 goto free_soc_dev_attr;
0491 }
0492
0493 return 0;
0494
0495 free_soc_dev_attr:
0496 kfree(soc_dev_attr->revision);
0497 kfree_const(soc_dev_attr->soc_id);
0498 kfree_const(soc_dev_attr->family);
0499 kfree(soc_dev_attr);
0500 return ret;
0501 }
0502 early_initcall(renesas_soc_init);