root/drivers/soc/renesas/renesas-soc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. renesas_soc_init

   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>
   9 #include <linux/of.h>
  10 #include <linux/of_address.h>
  11 #include <linux/slab.h>
  12 #include <linux/string.h>
  13 #include <linux/sys_soc.h>
  14 
  15 
  16 struct renesas_family {
  17         const char name[16];
  18         u32 reg;                        /* CCCR or PRR, if not in DT */
  19 };
  20 
  21 static const struct renesas_family fam_rcar_gen1 __initconst __maybe_unused = {
  22         .name   = "R-Car Gen1",
  23         .reg    = 0xff000044,           /* PRR (Product Register) */
  24 };
  25 
  26 static const struct renesas_family fam_rcar_gen2 __initconst __maybe_unused = {
  27         .name   = "R-Car Gen2",
  28         .reg    = 0xff000044,           /* PRR (Product Register) */
  29 };
  30 
  31 static const struct renesas_family fam_rcar_gen3 __initconst __maybe_unused = {
  32         .name   = "R-Car Gen3",
  33         .reg    = 0xfff00044,           /* PRR (Product Register) */
  34 };
  35 
  36 static const struct renesas_family fam_rmobile __initconst __maybe_unused = {
  37         .name   = "R-Mobile",
  38         .reg    = 0xe600101c,           /* CCCR (Common Chip Code Register) */
  39 };
  40 
  41 static const struct renesas_family fam_rza1 __initconst __maybe_unused = {
  42         .name   = "RZ/A1",
  43 };
  44 
  45 static const struct renesas_family fam_rza2 __initconst __maybe_unused = {
  46         .name   = "RZ/A2",
  47 };
  48 
  49 static const struct renesas_family fam_rzg1 __initconst __maybe_unused = {
  50         .name   = "RZ/G1",
  51         .reg    = 0xff000044,           /* PRR (Product Register) */
  52 };
  53 
  54 static const struct renesas_family fam_rzg2 __initconst __maybe_unused = {
  55         .name   = "RZ/G2",
  56         .reg    = 0xfff00044,           /* PRR (Product Register) */
  57 };
  58 
  59 static const struct renesas_family fam_shmobile __initconst __maybe_unused = {
  60         .name   = "SH-Mobile",
  61         .reg    = 0xe600101c,           /* CCCR (Common Chip Code Register) */
  62 };
  63 
  64 
  65 struct renesas_soc {
  66         const struct renesas_family *family;
  67         u8 id;
  68 };
  69 
  70 static const struct renesas_soc soc_rz_a1h __initconst __maybe_unused = {
  71         .family = &fam_rza1,
  72 };
  73 
  74 static const struct renesas_soc soc_rz_a2m __initconst __maybe_unused = {
  75         .family = &fam_rza2,
  76         .id     = 0x3b,
  77 };
  78 
  79 static const struct renesas_soc soc_rmobile_ape6 __initconst __maybe_unused = {
  80         .family = &fam_rmobile,
  81         .id     = 0x3f,
  82 };
  83 
  84 static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = {
  85         .family = &fam_rmobile,
  86         .id     = 0x40,
  87 };
  88 
  89 static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = {
  90         .family = &fam_rzg1,
  91         .id     = 0x45,
  92 };
  93 
  94 static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = {
  95         .family = &fam_rzg1,
  96         .id     = 0x47,
  97 };
  98 
  99 static const struct renesas_soc soc_rz_g1n __initconst __maybe_unused = {
 100         .family = &fam_rzg1,
 101         .id     = 0x4b,
 102 };
 103 
 104 static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = {
 105         .family = &fam_rzg1,
 106         .id     = 0x4c,
 107 };
 108 
 109 static const struct renesas_soc soc_rz_g1c __initconst __maybe_unused = {
 110         .family = &fam_rzg1,
 111         .id     = 0x53,
 112 };
 113 
 114 static const struct renesas_soc soc_rz_g2m __initconst __maybe_unused = {
 115         .family = &fam_rzg2,
 116         .id     = 0x52,
 117 };
 118 
 119 static const struct renesas_soc soc_rz_g2e __initconst __maybe_unused = {
 120         .family = &fam_rzg2,
 121         .id     = 0x57,
 122 };
 123 
 124 static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = {
 125         .family = &fam_rcar_gen1,
 126 };
 127 
 128 static const struct renesas_soc soc_rcar_h1 __initconst __maybe_unused = {
 129         .family = &fam_rcar_gen1,
 130         .id     = 0x3b,
 131 };
 132 
 133 static const struct renesas_soc soc_rcar_h2 __initconst __maybe_unused = {
 134         .family = &fam_rcar_gen2,
 135         .id     = 0x45,
 136 };
 137 
 138 static const struct renesas_soc soc_rcar_m2_w __initconst __maybe_unused = {
 139         .family = &fam_rcar_gen2,
 140         .id     = 0x47,
 141 };
 142 
 143 static const struct renesas_soc soc_rcar_v2h __initconst __maybe_unused = {
 144         .family = &fam_rcar_gen2,
 145         .id     = 0x4a,
 146 };
 147 
 148 static const struct renesas_soc soc_rcar_m2_n __initconst __maybe_unused = {
 149         .family = &fam_rcar_gen2,
 150         .id     = 0x4b,
 151 };
 152 
 153 static const struct renesas_soc soc_rcar_e2 __initconst __maybe_unused = {
 154         .family = &fam_rcar_gen2,
 155         .id     = 0x4c,
 156 };
 157 
 158 static const struct renesas_soc soc_rcar_h3 __initconst __maybe_unused = {
 159         .family = &fam_rcar_gen3,
 160         .id     = 0x4f,
 161 };
 162 
 163 static const struct renesas_soc soc_rcar_m3_w __initconst __maybe_unused = {
 164         .family = &fam_rcar_gen3,
 165         .id     = 0x52,
 166 };
 167 
 168 static const struct renesas_soc soc_rcar_m3_n __initconst __maybe_unused = {
 169         .family = &fam_rcar_gen3,
 170         .id     = 0x55,
 171 };
 172 
 173 static const struct renesas_soc soc_rcar_v3m __initconst __maybe_unused = {
 174         .family = &fam_rcar_gen3,
 175         .id     = 0x54,
 176 };
 177 
 178 static const struct renesas_soc soc_rcar_v3h __initconst __maybe_unused = {
 179         .family = &fam_rcar_gen3,
 180         .id     = 0x56,
 181 };
 182 
 183 static const struct renesas_soc soc_rcar_e3 __initconst __maybe_unused = {
 184         .family = &fam_rcar_gen3,
 185         .id     = 0x57,
 186 };
 187 
 188 static const struct renesas_soc soc_rcar_d3 __initconst __maybe_unused = {
 189         .family = &fam_rcar_gen3,
 190         .id     = 0x58,
 191 };
 192 
 193 static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = {
 194         .family = &fam_shmobile,
 195         .id     = 0x37,
 196 };
 197 
 198 
 199 static const struct of_device_id renesas_socs[] __initconst = {
 200 #ifdef CONFIG_ARCH_R7S72100
 201         { .compatible = "renesas,r7s72100",     .data = &soc_rz_a1h },
 202 #endif
 203 #ifdef CONFIG_ARCH_R7S9210
 204         { .compatible = "renesas,r7s9210",      .data = &soc_rz_a2m },
 205 #endif
 206 #ifdef CONFIG_ARCH_R8A73A4
 207         { .compatible = "renesas,r8a73a4",      .data = &soc_rmobile_ape6 },
 208 #endif
 209 #ifdef CONFIG_ARCH_R8A7740
 210         { .compatible = "renesas,r8a7740",      .data = &soc_rmobile_a1 },
 211 #endif
 212 #ifdef CONFIG_ARCH_R8A7742
 213         { .compatible = "renesas,r8a7742",      .data = &soc_rz_g1h },
 214 #endif
 215 #ifdef CONFIG_ARCH_R8A7743
 216         { .compatible = "renesas,r8a7743",      .data = &soc_rz_g1m },
 217 #endif
 218 #ifdef CONFIG_ARCH_R8A7744
 219         { .compatible = "renesas,r8a7744",      .data = &soc_rz_g1n },
 220 #endif
 221 #ifdef CONFIG_ARCH_R8A7745
 222         { .compatible = "renesas,r8a7745",      .data = &soc_rz_g1e },
 223 #endif
 224 #ifdef CONFIG_ARCH_R8A77470
 225         { .compatible = "renesas,r8a77470",     .data = &soc_rz_g1c },
 226 #endif
 227 #ifdef CONFIG_ARCH_R8A774A1
 228         { .compatible = "renesas,r8a774a1",     .data = &soc_rz_g2m },
 229 #endif
 230 #ifdef CONFIG_ARCH_R8A774C0
 231         { .compatible = "renesas,r8a774c0",     .data = &soc_rz_g2e },
 232 #endif
 233 #ifdef CONFIG_ARCH_R8A7778
 234         { .compatible = "renesas,r8a7778",      .data = &soc_rcar_m1a },
 235 #endif
 236 #ifdef CONFIG_ARCH_R8A7779
 237         { .compatible = "renesas,r8a7779",      .data = &soc_rcar_h1 },
 238 #endif
 239 #ifdef CONFIG_ARCH_R8A7790
 240         { .compatible = "renesas,r8a7790",      .data = &soc_rcar_h2 },
 241 #endif
 242 #ifdef CONFIG_ARCH_R8A7791
 243         { .compatible = "renesas,r8a7791",      .data = &soc_rcar_m2_w },
 244 #endif
 245 #ifdef CONFIG_ARCH_R8A7792
 246         { .compatible = "renesas,r8a7792",      .data = &soc_rcar_v2h },
 247 #endif
 248 #ifdef CONFIG_ARCH_R8A7793
 249         { .compatible = "renesas,r8a7793",      .data = &soc_rcar_m2_n },
 250 #endif
 251 #ifdef CONFIG_ARCH_R8A7794
 252         { .compatible = "renesas,r8a7794",      .data = &soc_rcar_e2 },
 253 #endif
 254 #ifdef CONFIG_ARCH_R8A7795
 255         { .compatible = "renesas,r8a7795",      .data = &soc_rcar_h3 },
 256 #endif
 257 #ifdef CONFIG_ARCH_R8A7796
 258         { .compatible = "renesas,r8a7796",      .data = &soc_rcar_m3_w },
 259 #endif
 260 #ifdef CONFIG_ARCH_R8A77965
 261         { .compatible = "renesas,r8a77965",     .data = &soc_rcar_m3_n },
 262 #endif
 263 #ifdef CONFIG_ARCH_R8A77970
 264         { .compatible = "renesas,r8a77970",     .data = &soc_rcar_v3m },
 265 #endif
 266 #ifdef CONFIG_ARCH_R8A77980
 267         { .compatible = "renesas,r8a77980",     .data = &soc_rcar_v3h },
 268 #endif
 269 #ifdef CONFIG_ARCH_R8A77990
 270         { .compatible = "renesas,r8a77990",     .data = &soc_rcar_e3 },
 271 #endif
 272 #ifdef CONFIG_ARCH_R8A77995
 273         { .compatible = "renesas,r8a77995",     .data = &soc_rcar_d3 },
 274 #endif
 275 #ifdef CONFIG_ARCH_SH73A0
 276         { .compatible = "renesas,sh73a0",       .data = &soc_shmobile_ag5 },
 277 #endif
 278         { /* sentinel */ }
 279 };
 280 
 281 static int __init renesas_soc_init(void)
 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;
 290         unsigned int product, eshi = 0, eslo;
 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 
 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 && family->reg) {
 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                 /* R-Car M3-W ES1.3 incorrectly identifies as ES2.1 */
 339                 if ((product & 0x7fff) == 0x5211)
 340                         product ^= 0x12;
 341                 if (soc->id && ((product >> 8) & 0xff) != soc->id) {
 342                         pr_warn("SoC mismatch (product = 0x%x)\n", product);
 343                         return -ENODEV;
 344                 }
 345                 eshi = ((product >> 4) & 0x0f) + 1;
 346                 eslo = product & 0xf;
 347         }
 348 
 349 done:
 350         soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
 351         if (!soc_dev_attr)
 352                 return -ENOMEM;
 353 
 354         np = of_find_node_by_path("/");
 355         of_property_read_string(np, "model", &soc_dev_attr->machine);
 356         of_node_put(np);
 357 
 358         soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL);
 359         soc_dev_attr->soc_id = kstrdup_const(strchr(match->compatible, ',') + 1,
 360                                              GFP_KERNEL);
 361         if (eshi)
 362                 soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", eshi,
 363                                                    eslo);
 364 
 365         pr_info("Detected Renesas %s %s %s\n", soc_dev_attr->family,
 366                 soc_dev_attr->soc_id, soc_dev_attr->revision ?: "");
 367 
 368         soc_dev = soc_device_register(soc_dev_attr);
 369         if (IS_ERR(soc_dev)) {
 370                 kfree(soc_dev_attr->revision);
 371                 kfree_const(soc_dev_attr->soc_id);
 372                 kfree_const(soc_dev_attr->family);
 373                 kfree(soc_dev_attr);
 374                 return PTR_ERR(soc_dev);
 375         }
 376 
 377         return 0;
 378 }
 379 early_initcall(renesas_soc_init);

/* [<][>][^][v][top][bottom][index][help] */