[PATCH v4 0/4] Add Renesas SoC identification driver support

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH v4 0/4] Add Renesas SoC identification driver support

Biju Das
This patch series aims to support Renesas SoC identification driver.

Added a helper function of_match_node to find the matching of_match structure. This helper function can be used to replace the following code in u-boot [1] and [2]

[1] https://elixir.bootlin.com/u-boot/latest/source/drivers/serial/serial_uniphier.c#L129
[2] https://elixir.bootlin.com/u-boot/latest/source/drivers/usb/phy/rockchip_usb2_phy.c#L77

Also added soc_id attribute support in UCLASS_SOC which is required for Renesas SoC identification driver similar to mainline linux.

v3->v4
  * Added Simon's Rb tag
  * Updated patch description for SoC identification using soc_id
  * Updated probe function of Renesas SoC identification driver.

Biju Das (4):
  dm: core: Add of_match_node helper function
  soc: Fix comments from SOC to SoC
  dm: soc: Add SoC id for attribute matching
  dm: soc: SoC identification driver for Renesas SoC's

 drivers/core/device.c     |  21 ++++
 drivers/soc/Kconfig       |   7 ++
 drivers/soc/Makefile      |   1 +
 drivers/soc/soc-uclass.c  |  19 ++-
 drivers/soc/soc_renesas.c | 244 ++++++++++++++++++++++++++++++++++++++
 drivers/soc/soc_sandbox.c |   8 ++
 include/dm/device.h       |  13 ++
 include/soc.h             |  39 +++++-
 test/dm/core.c            |  31 +++++
 test/dm/soc.c             |   8 ++
 10 files changed, 384 insertions(+), 7 deletions(-)
 create mode 100644 drivers/soc/soc_renesas.c

--
2.17.1

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 1/4] dm: core: Add of_match_node helper function

Biju Das
Add of_match_node() helper function to iterate over the device tree
and tell if a device_node has a matching of_match structure.

Signed-off-by: Biju Das <[hidden email]>
Reviewed-by: Lad Prabhakar <[hidden email]>
Reviewed-by: Simon Glass <[hidden email]>
---
v3->v4: No change
 * Added Simon's Rb tag.
v2->v3:
 * Added a test case for of_match_node helper function.
 (Ref: https://patchwork.ozlabs.org/project/uboot/patch/20201102150959.4793-2-biju.das.jz@.../)
v1->v2:
  * No Change.
---
 drivers/core/device.c | 21 +++++++++++++++++++++
 include/dm/device.h   | 13 +++++++++++++
 test/dm/core.c        | 31 +++++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+)

diff --git a/drivers/core/device.c b/drivers/core/device.c
index 4b3dcb3b37..5db4c5e78b 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -1010,6 +1010,27 @@ bool of_machine_is_compatible(const char *compat)
  return !fdt_node_check_compatible(fdt, 0, compat);
 }
 
+static
+const struct udevice_id *__of_match_node(const struct udevice_id *matches,
+ const ofnode node)
+{
+ if (!matches)
+ return NULL;
+
+ for (; matches->compatible; matches++) {
+ if (ofnode_device_is_compatible(node, matches->compatible))
+ return matches;
+ }
+
+ return NULL;
+}
+
+const struct udevice_id *of_match_node(const struct udevice_id *matches,
+       const ofnode node)
+{
+ return __of_match_node(matches, node);
+}
+
 int dev_disable_by_path(const char *path)
 {
  struct uclass *uc;
diff --git a/include/dm/device.h b/include/dm/device.h
index 5bef484247..4c357d46ec 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -754,6 +754,19 @@ bool device_is_compatible(const struct udevice *dev, const char *compat);
  */
 bool of_machine_is_compatible(const char *compat);
 
+/**
+ * of_match_node() - Tell if a device_node has a matching of_match structure
+ *
+ *
+ * Low level utility function used by device matching.
+ *
+ * @matches: array of of device match structures to search in
+ * @node: the of device structure to match against
+ * @return matching structure on success, NULL if the match is not found
+ */
+const struct udevice_id *of_match_node(const struct udevice_id *matches,
+       const ofnode node);
+
 /**
  * dev_disable_by_path() - Disable a device given its device tree path
  *
diff --git a/test/dm/core.c b/test/dm/core.c
index 6f380a574c..b94b78d9ba 100644
--- a/test/dm/core.c
+++ b/test/dm/core.c
@@ -11,6 +11,7 @@
 #include <fdtdec.h>
 #include <log.h>
 #include <malloc.h>
+#include <dm/device.h>
 #include <dm/device-internal.h>
 #include <dm/root.h>
 #include <dm/util.h>
@@ -1066,3 +1067,33 @@ static int dm_test_inactive_child(struct unit_test_state *uts)
  return 0;
 }
 DM_TEST(dm_test_inactive_child, UT_TESTF_SCAN_PDATA);
+
+static int dm_test_of_match_node(struct unit_test_state *uts)
+{
+ const ulong test_data_expected = 0x1234;
+ ofnode root_node = ofnode_path("/");
+ const struct udevice_id *match;
+ unsigned long match_data;
+
+ const struct udevice_id soc_device_ids[] = {
+ { .compatible = "sandbox", .data = test_data_expected, },
+ { /* sentinel */ }
+ };
+
+ const struct udevice_id soc_device_nomatch_ids[] = {
+ { .compatible = "sandbox123", .data = test_data_expected, },
+ { /* sentinel */ }
+ };
+
+ match = of_match_node(soc_device_ids, root_node);
+ ut_assert(match);
+
+ match_data = match->data;
+ ut_asserteq(match_data, test_data_expected);
+
+ match = of_match_node(soc_device_nomatch_ids, root_node);
+ ut_asserteq_ptr(match, NULL);
+
+ return 0;
+}
+DM_TEST(dm_test_of_match_node, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
--
2.17.1

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 2/4] soc: Fix comments from SOC to SoC

Biju Das
In reply to this post by Biju Das
Fix the comments from "an SOC" to "an SoC".

Signed-off-by: Biju Das <[hidden email]>
Reviewed-by: Lad Prabhakar <[hidden email]>
Reviewed-by: Simon Glass <[hidden email]>
---
 v3->v4: No Change
 * Added Simon's Rb tag.
 v3:
 * New patch
 (Ref: https://patchwork.ozlabs.org/project/uboot/patch/20201102150959.4793-3-biju.das.jz@.../)
---
 include/soc.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/soc.h b/include/soc.h
index a55eb1b572..05058f9331 100644
--- a/include/soc.h
+++ b/include/soc.h
@@ -31,7 +31,7 @@ struct soc_attr {
 
 struct soc_ops {
  /**
- * get_machine() - Get machine name of an SOC
+ * get_machine() - Get machine name of an SoC
  *
  * @dev: Device to check (UCLASS_SOC)
  * @buf: Buffer to place string
@@ -41,7 +41,7 @@ struct soc_ops {
  int (*get_machine)(struct udevice *dev, char *buf, int size);
 
  /**
- * get_revision() - Get revision name of a SOC
+ * get_revision() - Get revision name of an SoC
  *
  * @dev: Device to check (UCLASS_SOC)
  * @buf: Buffer to place string
@@ -51,7 +51,7 @@ struct soc_ops {
  int (*get_revision)(struct udevice *dev, char *buf, int size);
 
  /**
- * get_family() - Get family name of an SOC
+ * get_family() - Get family name of an SoC
  *
  * @dev: Device to check (UCLASS_SOC)
  * @buf: Buffer to place string
@@ -76,7 +76,7 @@ struct soc_ops {
 int soc_get(struct udevice **devp);
 
 /**
- * soc_get_machine() - Get machine name of an SOC
+ * soc_get_machine() - Get machine name of an SoC
  * @dev: Device to check (UCLASS_SOC)
  * @buf: Buffer to place string
  * @size: Size of string space
@@ -86,7 +86,7 @@ int soc_get(struct udevice **devp);
 int soc_get_machine(struct udevice *dev, char *buf, int size);
 
 /**
- * soc_get_revision() - Get revision name of an SOC
+ * soc_get_revision() - Get revision name of an SoC
  * @dev: Device to check (UCLASS_SOC)
  * @buf: Buffer to place string
  * @size: Size of string space
@@ -96,7 +96,7 @@ int soc_get_machine(struct udevice *dev, char *buf, int size);
 int soc_get_revision(struct udevice *dev, char *buf, int size);
 
 /**
- * soc_get_family() - Get family name of an SOC
+ * soc_get_family() - Get family name of an SoC
  * @dev: Device to check (UCLASS_SOC)
  * @buf: Buffer to place string
  * @size: Size of string space
--
2.17.1

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 3/4] dm: soc: Add SoC id for attribute matching

Biju Das
In reply to this post by Biju Das
Mainline kernel uses the "soc_id" attribute to identify the SoC for some
of the h/w platforms. Adding this attribute in u-boot will make SoC
identification similar to the mainline kernel, so that it can be easily
maintained.

Add a new attribute named "soc_id" to SOC uclass, in order to allow device
drivers for identifying the SoC using SoC identification string and also
for matching this attribute for selecting SoC specific data.

Signed-off-by: Biju Das <[hidden email]>
Reviewed-by: Lad Prabhakar <[hidden email]>
Reviewed-by: Simon Glass <[hidden email]>
---
v3->v4:
 * Updated patch description
 * Added Simon's Rb tag.

v2->v3:
 * split the comments patch seperate.
 Ref:https://patchwork.ozlabs.org/project/uboot/patch/20201102150959.4793-3-biju.das.jz@.../

v1->v2: Changed the comments from "a SoC" to "an SoC"
 Ref: https://patchwork.ozlabs.org/project/uboot/patch/20201030140724.12773-1-biju.das.jz@.../
---
 drivers/soc/soc-uclass.c  | 19 ++++++++++++++++++-
 drivers/soc/soc_sandbox.c |  8 ++++++++
 include/soc.h             | 27 +++++++++++++++++++++++++++
 test/dm/soc.c             |  8 ++++++++
 4 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/soc-uclass.c b/drivers/soc/soc-uclass.c
index c32d647864..a3f8be841b 100644
--- a/drivers/soc/soc-uclass.c
+++ b/drivers/soc/soc-uclass.c
@@ -46,6 +46,16 @@ int soc_get_revision(struct udevice *dev, char *buf, int size)
  return ops->get_revision(dev, buf, size);
 }
 
+int soc_get_soc_id(struct udevice *dev, char *buf, int size)
+{
+ struct soc_ops *ops = soc_get_ops(dev);
+
+ if (!ops->get_soc_id)
+ return -ENOSYS;
+
+ return ops->get_soc_id(dev, buf, size);
+}
+
 const struct soc_attr *
 soc_device_match(const struct soc_attr *matches)
 {
@@ -61,7 +71,7 @@ soc_device_match(const struct soc_attr *matches)
 
  while (1) {
  if (!(matches->machine || matches->family ||
-      matches->revision))
+      matches->revision || matches->soc_id))
  break;
 
  match = true;
@@ -87,6 +97,13 @@ soc_device_match(const struct soc_attr *matches)
  }
  }
 
+ if (matches->soc_id) {
+ if (!soc_get_soc_id(soc, str, SOC_MAX_STR_SIZE)) {
+ if (strcmp(matches->soc_id, str))
+ match = false;
+ }
+ }
+
  if (match)
  return matches;
 
diff --git a/drivers/soc/soc_sandbox.c b/drivers/soc/soc_sandbox.c
index 5c82ad84fc..1a81d3562a 100644
--- a/drivers/soc/soc_sandbox.c
+++ b/drivers/soc/soc_sandbox.c
@@ -31,10 +31,18 @@ int soc_sandbox_get_revision(struct udevice *dev, char *buf, int size)
  return 0;
 }
 
+int soc_sandbox_get_soc_id(struct udevice *dev, char *buf, int size)
+{
+ snprintf(buf, size, "r8a774a1");
+
+ return 0;
+}
+
 static const struct soc_ops soc_sandbox_ops = {
  .get_family = soc_sandbox_get_family,
  .get_revision = soc_sandbox_get_revision,
  .get_machine = soc_sandbox_get_machine,
+ .get_soc_id = soc_sandbox_get_soc_id,
 };
 
 int soc_sandbox_probe(struct udevice *dev)
diff --git a/include/soc.h b/include/soc.h
index 05058f9331..db0e8880d1 100644
--- a/include/soc.h
+++ b/include/soc.h
@@ -20,12 +20,14 @@
  *       variants. Example: am33
  * @machine  - Name of a specific SoC. Example: am3352
  * @revision - Name of a specific SoC revision. Example: SR1.1
+ * @soc_id   - SoC identification string. Example: r8a774a1
  * @data     - A pointer to user data for the SoC variant
  */
 struct soc_attr {
  const char *family;
  const char *machine;
  const char *revision;
+ const char *soc_id;
  const void *data;
 };
 
@@ -59,6 +61,16 @@ struct soc_ops {
  * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
  */
  int (*get_family)(struct udevice *dev, char *buf, int size);
+
+ /**
+ * get_soc_id() - Get SoC identification name of an SoC
+ *
+ * @dev: Device to check (UCLASS_SOC)
+ * @buf: Buffer to place string
+ * @size: Size of string space
+ * @return 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+ int (*get_soc_id)(struct udevice *dev, char *buf, int size);
 };
 
 #define soc_get_ops(dev)        ((struct soc_ops *)(dev)->driver->ops)
@@ -105,6 +117,16 @@ int soc_get_revision(struct udevice *dev, char *buf, int size);
  */
 int soc_get_family(struct udevice *dev, char *buf, int size);
 
+/**
+ * soc_get_soc_id() - Get SoC identification name of an SoC
+ * @dev: Device to check (UCLASS_SOC)
+ * @buf: Buffer to place string
+ * @size: Size of string space
+ *
+ * Return: 0 if OK, -ENOSPC if buffer is too small, other -ve on error
+ */
+int soc_get_soc_id(struct udevice *dev, char *buf, int size);
+
 /**
  * soc_device_match() - Return match from an array of soc_attr
  * @matches: Array with any combination of family, revision or machine set
@@ -136,6 +158,11 @@ static inline int soc_get_family(struct udevice *dev, char *buf, int size)
  return -ENOSYS;
 }
 
+static inline int soc_get_soc_id(struct udevice *dev, char *buf, int size)
+{
+ return -ENOSYS;
+}
+
 static inline const struct soc_attr *
 soc_device_match(const struct soc_attr *matches)
 {
diff --git a/test/dm/soc.c b/test/dm/soc.c
index 17e1b5ba01..82cd53ff29 100644
--- a/test/dm/soc.c
+++ b/test/dm/soc.c
@@ -32,24 +32,28 @@ static int dm_test_soc(struct unit_test_state *uts)
  .family = "SANDBOX0xx",
  .machine = "SANDBOX012",
  .revision = "1.0",
+ .soc_id = "r8a774a1",
  .data = NULL,
  },
  {
  .family = "SANDBOX1xx",
  .machine = "SANDBOX107",
  .revision = "1.0",
+ .soc_id = "r8a774a1",
  .data = NULL,
  },
  {
  .family = "SANDBOX1xx",
  .machine = "SANDBOX123",
  .revision = "1.0",
+ .soc_id = "r8a774a1",
  .data = &soc_sandbox123_data,
  },
  {
  .family = "SANDBOX1xx",
  .machine = "SANDBOX131",
  .revision = "2.0",
+ .soc_id = "r8a774a1",
  .data = NULL,
  },
  { /* sentinel */ }
@@ -78,6 +82,7 @@ static int dm_test_soc(struct unit_test_state *uts)
  {
  .family = "SANDBOX0xx",
  .revision = "1.0",
+ .soc_id = "r8a774b1",
  .data = NULL,
  },
  {
@@ -99,6 +104,9 @@ static int dm_test_soc(struct unit_test_state *uts)
  ut_assertok(soc_get_revision(dev, text, sizeof(text)));
  ut_asserteq_str(text, "1.0");
 
+ ut_assertok(soc_get_soc_id(dev, text, sizeof(text)));
+ ut_asserteq_str(text, "r8a774a1");
+
  soc_data = soc_device_match(sb_soc_devices_full);
  ut_assert(soc_data);
 
--
2.17.1

Reply | Threaded
Open this post in threaded view
|

[PATCH v4 4/4] dm: soc: SoC identification driver for Renesas SoC's

Biju Das
In reply to this post by Biju Das
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 <[hidden email]>
Reviewed-by: Lad Prabhakar <[hidden email]>
---
v3->v4:
 * Updated Copy right information from Linux.
 * Updated probe function, use the prr address from DT.
v2->v3: No Change.
v2: New patch
---
 drivers/soc/Kconfig       |   7 ++
 drivers/soc/Makefile      |   1 +
 drivers/soc/soc_renesas.c | 244 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 252 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..a42c6342fa
--- /dev/null
+++ b/drivers/soc/soc_renesas.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2014-2016 Glider bvba
+ * 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);
+ void *prr_addr = dev_read_addr_ptr(dev);
+ unsigned int product, eshi = 0, eslo;
+ const struct renesas_family *family;
+ const struct udevice_id *match;
+ struct renesas_soc *soc;
+ ofnode root_node;
+
+ if (!prr_addr)
+ return -EINVAL;
+
+ root_node = ofnode_path("/");
+ match = of_match_node(renesas_socs, root_node);
+ if (!match) {
+ printf("SoC entry is missing in DT\n");
+ return -EINVAL;
+ }
+
+ soc = (struct renesas_soc *)match->data;
+ family = soc->family;
+
+ product = readl(prr_addr);
+ /* 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 -EINVAL;
+ }
+ 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