[PATCH v2 3/3] dm: soc: SoC identification driver for Renesas SoC's
Biju Das
biju.das.jz at bp.renesas.com
Mon Nov 2 16:09:59 CET 2020
Add SoC identification driver for Renesas SoC's. This allows
to identify the SoC type and revision based on Product Register.
This can be checked where needed using soc_device_match().
Signed-off-by: Biju Das <biju.das.jz at bp.renesas.com>
Reviewed-by: Lad Prabhakar <prabhakar.mahadev-lad.rj at bp.renesas.com>
---
v2: New patch
---
drivers/soc/Kconfig | 7 ++
drivers/soc/Makefile | 1 +
drivers/soc/soc_renesas.c | 239 ++++++++++++++++++++++++++++++++++++++
3 files changed, 247 insertions(+)
create mode 100644 drivers/soc/soc_renesas.c
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 864d00a885..475e94cd77 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -16,6 +16,13 @@ config SOC_DEVICE_TI_K3
This allows Texas Instruments Keystone 3 SoCs to identify
specifics about the SoC in use.
+config SOC_DEVICE_RENESAS
+ depends on SOC_DEVICE
+ bool "Enable SoC driver for Renesas SoCs"
+ help
+ This allows Renesas SoCs to identify specifics about the
+ SoC in use.
+
source "drivers/soc/ti/Kconfig"
endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 9ef20ca506..b143eac5fd 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -4,5 +4,6 @@
obj-$(CONFIG_SOC_TI) += ti/
obj-$(CONFIG_SOC_DEVICE) += soc-uclass.o
+obj-$(CONFIG_$(SPL_)SOC_DEVICE_RENESAS) += soc_renesas.o
obj-$(CONFIG_SOC_DEVICE_TI_K3) += soc_ti_k3.o
obj-$(CONFIG_SANDBOX) += soc_sandbox.o
diff --git a/drivers/soc/soc_renesas.c b/drivers/soc/soc_renesas.c
new file mode 100644
index 0000000000..4543e0dbfd
--- /dev/null
+++ b/drivers/soc/soc_renesas.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Renesas Electronics Corp.
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <dm/device-internal.h>
+#include <soc.h>
+
+#include <asm/io.h>
+
+struct soc_renesas_priv {
+ const char *family;
+ const char *soc_id;
+ char revision[6];
+};
+
+struct renesas_family {
+ const char name[16];
+ u32 reg; /* CCCR or PRR, if not in DT */
+};
+
+static const struct renesas_family fam_rcar_gen3 __maybe_unused = {
+ .name = "R-Car Gen3",
+ .reg = 0xfff00044, /* PRR (Product Register) */
+};
+
+static const struct renesas_family fam_rzg2 __maybe_unused = {
+ .name = "RZ/G2",
+ .reg = 0xfff00044, /* PRR (Product Register) */
+};
+
+struct renesas_soc {
+ const struct renesas_family *family;
+ u8 id;
+};
+
+#ifdef CONFIG_R8A774A1
+static const struct renesas_soc soc_rz_g2m = {
+ .family = &fam_rzg2,
+ .id = 0x52,
+};
+#endif
+
+#ifdef CONFIG_R8A774B1
+static const struct renesas_soc soc_rz_g2n = {
+ .family = &fam_rzg2,
+ .id = 0x55,
+};
+#endif
+
+#ifdef CONFIG_R8A774C0
+static const struct renesas_soc soc_rz_g2e = {
+ .family = &fam_rzg2,
+ .id = 0x57,
+};
+#endif
+
+#ifdef CONFIG_R8A774E1
+static const struct renesas_soc soc_rz_g2h = {
+ .family = &fam_rzg2,
+ .id = 0x4f,
+};
+#endif
+
+#ifdef CONFIG_R8A7795
+static const struct renesas_soc soc_rcar_h3 = {
+ .family = &fam_rcar_gen3,
+ .id = 0x4f,
+};
+#endif
+
+#ifdef CONFIG_R8A7796
+static const struct renesas_soc soc_rcar_m3_w = {
+ .family = &fam_rcar_gen3,
+ .id = 0x52,
+};
+#endif
+
+#ifdef CONFIG_R8A77965
+static const struct renesas_soc soc_rcar_m3_n = {
+ .family = &fam_rcar_gen3,
+ .id = 0x55,
+};
+#endif
+
+#ifdef CONFIG_R8A77970
+static const struct renesas_soc soc_rcar_v3m = {
+ .family = &fam_rcar_gen3,
+ .id = 0x54,
+};
+#endif
+
+#ifdef CONFIG_R8A77980
+static const struct renesas_soc soc_rcar_v3h = {
+ .family = &fam_rcar_gen3,
+ .id = 0x56,
+};
+#endif
+
+#ifdef CONFIG_R8A77990
+static const struct renesas_soc soc_rcar_e3 = {
+ .family = &fam_rcar_gen3,
+ .id = 0x57,
+};
+#endif
+
+#ifdef CONFIG_R8A77995
+static const struct renesas_soc soc_rcar_d3 = {
+ .family = &fam_rcar_gen3,
+ .id = 0x58,
+};
+#endif
+
+static int soc_renesas_get_family(struct udevice *dev, char *buf, int size)
+{
+ struct soc_renesas_priv *priv = dev_get_priv(dev);
+
+ snprintf(buf, size, "%s", priv->family);
+
+ return 0;
+}
+
+static int soc_renesas_get_revision(struct udevice *dev, char *buf, int size)
+{
+ struct soc_renesas_priv *priv = dev_get_priv(dev);
+
+ snprintf(buf, size, "%s", priv->revision);
+
+ return 0;
+}
+
+static int soc_renesas_get_soc_id(struct udevice *dev, char *buf, int size)
+{
+ struct soc_renesas_priv *priv = dev_get_priv(dev);
+
+ snprintf(buf, size, "%s", priv->soc_id);
+
+ return 0;
+}
+
+static const struct udevice_id renesas_socs[] = {
+#ifdef CONFIG_R8A774A1
+ { .compatible = "renesas,r8a774a1", .data = (ulong)&soc_rz_g2m, },
+#endif
+#ifdef CONFIG_R8A774B1
+ { .compatible = "renesas,r8a774b1", .data = (ulong)&soc_rz_g2n, },
+#endif
+#ifdef CONFIG_R8A774C0
+ { .compatible = "renesas,r8a774c0", .data = (ulong)&soc_rz_g2e, },
+#endif
+#ifdef CONFIG_R8A774E1
+ { .compatible = "renesas,r8a774e1", .data = (ulong)&soc_rz_g2h, },
+#endif
+#ifdef CONFIG_R8A7795
+ { .compatible = "renesas,r8a7795", .data = (ulong)&soc_rcar_h3, },
+#endif
+#ifdef CONFIG_R8A7796
+ { .compatible = "renesas,r8a7796", .data = (ulong)&soc_rcar_m3_w, },
+#endif
+#ifdef CONFIG_R8A77965
+ { .compatible = "renesas,r8a77965", .data = (ulong)&soc_rcar_m3_n, },
+#endif
+#ifdef CONFIG_R8A77970
+ { .compatible = "renesas,r8a77970", .data = (ulong)&soc_rcar_v3m, },
+#endif
+#ifdef CONFIG_R8A77980
+ { .compatible = "renesas,r8a77980", .data = (ulong)&soc_rcar_v3h, },
+#endif
+#ifdef CONFIG_R8A77990
+ { .compatible = "renesas,r8a77990", .data = (ulong)&soc_rcar_e3, },
+#endif
+#ifdef CONFIG_R8A77995
+ { .compatible = "renesas,r8a77995", .data = (ulong)&soc_rcar_d3, },
+#endif
+ { /* sentinel */ }
+};
+
+static const struct udevice_id prr_ids[] = {
+ { .compatible = "renesas,prr" },
+ { /* sentinel */ }
+};
+
+static const struct soc_ops soc_renesas_ops = {
+ .get_family = soc_renesas_get_family,
+ .get_revision = soc_renesas_get_revision,
+ .get_soc_id = soc_renesas_get_soc_id,
+};
+
+int soc_renesas_probe(struct udevice *dev)
+{
+ struct soc_renesas_priv *priv = dev_get_priv(dev);
+ const struct renesas_family *family;
+ const struct udevice_id *match;
+ struct renesas_soc *soc;
+ unsigned int product, eshi = 0, eslo;
+ ofnode root_node;
+
+ root_node = ofnode_path("/");
+ match = of_match_node(renesas_socs, root_node);
+ if (!match) {
+ printf("SoC entry is missing in DT\n");
+ return 0;
+ }
+
+ soc = (struct renesas_soc *)match->data;
+ family = soc->family;
+
+ product = readl(0xFFF00044);
+ /* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */
+ if ((product & 0x7fff) == 0x5210)
+ product ^= 0x11;
+ /* R-Car M3-W ES1.3 incorrectly identifies as ES2.1 */
+ if ((product & 0x7fff) == 0x5211)
+ product ^= 0x12;
+ if (soc->id && ((product >> 8) & 0xff) != soc->id) {
+ printf("SoC mismatch (product = 0x%x)\n", product);
+ return 0;
+ }
+ eshi = ((product >> 4) & 0x0f) + 1;
+ eslo = product & 0xf;
+
+ priv->family = family->name;
+ priv->soc_id = strchr(match->compatible, ',') + 1;
+ snprintf(priv->revision, sizeof(priv->revision), "ES%u.%u", eshi, eslo);
+
+ return 0;
+}
+
+U_BOOT_DRIVER(soc_renesas) = {
+ .name = "soc_renesas",
+ .id = UCLASS_SOC,
+ .ops = &soc_renesas_ops,
+ .of_match = prr_ids,
+ .probe = soc_renesas_probe,
+ .priv_auto_alloc_size = sizeof(struct soc_renesas_priv),
+};
--
2.17.1
More information about the U-Boot
mailing list