[PATCH v2 4/8] pinctrl: renesas: Add R-Car Gen3 fuse support

From: Geert Uytterhoeven
Date: Wed May 29 2024 - 05:31:38 EST


On R-Car Gen3 SoCs, the fuse registers are tightly integrated into the
Pin Function Controller. Add support for them by providing the
rcar-fuse driver with all needed info through a platform device and
platform data.

Note that the number of fuse registers on R-Car V3H and V3H2 differs,
while their PFC blocks use the same compatible value, hence this is
handled by checking the top-level compatible value.

Signed-off-by: Geert Uytterhoeven <geert+renesas@xxxxxxxxx>
Reviewed-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx>
---
v2:
- Add Reviewed-by.

FUSE_MON[1-3] on R-Car V3M were only briefly documented in Hardware
User's Manual Rev. 0.52/0.53
---
drivers/pinctrl/renesas/core.c | 18 ++++++++++++++++++
drivers/pinctrl/renesas/pfc-r8a77951.c | 2 ++
drivers/pinctrl/renesas/pfc-r8a7796.c | 4 ++++
drivers/pinctrl/renesas/pfc-r8a77965.c | 2 ++
drivers/pinctrl/renesas/pfc-r8a77970.c | 2 ++
drivers/pinctrl/renesas/pfc-r8a77980.c | 14 +++++++++++++-
drivers/pinctrl/renesas/pfc-r8a77990.c | 2 ++
drivers/pinctrl/renesas/pfc-r8a77995.c | 2 ++
drivers/pinctrl/renesas/sh_pfc.h | 4 +++-
9 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/renesas/core.c b/drivers/pinctrl/renesas/core.c
index 96d6040a8871419b..1c8447fcfb1180e3 100644
--- a/drivers/pinctrl/renesas/core.c
+++ b/drivers/pinctrl/renesas/core.c
@@ -20,6 +20,7 @@
#include <linux/math.h>
#include <linux/of.h>
#include <linux/pinctrl/machine.h>
+#include <linux/platform_data/rcar_fuse.h>
#include <linux/platform_device.h>
#include <linux/psci.h>
#include <linux/slab.h>
@@ -27,6 +28,8 @@

#include "core.h"

+#define FUSE_MON0 0x3e4 /* R-Car Gen3 */
+
static int sh_pfc_map_resources(struct sh_pfc *pfc,
struct platform_device *pdev)
{
@@ -1372,6 +1375,21 @@ static int sh_pfc_probe(struct platform_device *pdev)
}
#endif

+ if (pfc->info->nr_fuse_regs) {
+ struct rcar_fuse_platform_data pdata = {
+ .base = pfc->windows[0].virt,
+ .offset = FUSE_MON0,
+ .nregs = pfc->info->nr_fuse_regs,
+ };
+ struct platform_device *fdev;
+
+ fdev = platform_device_register_data(pfc->dev, "rcar_fuse", -1,
+ &pdata, sizeof(pdata));
+ if (IS_ERR(fdev))
+ dev_err_probe(pfc->dev, PTR_ERR(fdev),
+ "failed to register fuses, ignoring\n");
+ }
+
platform_set_drvdata(pdev, pfc);

dev_info(pfc->dev, "%s support registered\n", info->name);
diff --git a/drivers/pinctrl/renesas/pfc-r8a77951.c b/drivers/pinctrl/renesas/pfc-r8a77951.c
index a1d74f61fd8cce64..ae60bc5f70f0c223 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77951.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77951.c
@@ -6187,5 +6187,7 @@ const struct sh_pfc_soc_info r8a77951_pinmux_info = {

.pinmux_data = pinmux_data,
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
+
+ .nr_fuse_regs = 1,
};
#endif
diff --git a/drivers/pinctrl/renesas/pfc-r8a7796.c b/drivers/pinctrl/renesas/pfc-r8a7796.c
index 807834f319f07d8c..b1ebd9a0b612e5b8 100644
--- a/drivers/pinctrl/renesas/pfc-r8a7796.c
+++ b/drivers/pinctrl/renesas/pfc-r8a7796.c
@@ -6139,6 +6139,8 @@ const struct sh_pfc_soc_info r8a77960_pinmux_info = {

.pinmux_data = pinmux_data,
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
+
+ .nr_fuse_regs = 1,
};
#endif

@@ -6166,5 +6168,7 @@ const struct sh_pfc_soc_info r8a77961_pinmux_info = {

.pinmux_data = pinmux_data,
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
+
+ .nr_fuse_regs = 1,
};
#endif
diff --git a/drivers/pinctrl/renesas/pfc-r8a77965.c b/drivers/pinctrl/renesas/pfc-r8a77965.c
index e7c88a5d983f4343..47f9843a336225ac 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77965.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77965.c
@@ -6380,5 +6380,7 @@ const struct sh_pfc_soc_info r8a77965_pinmux_info = {

.pinmux_data = pinmux_data,
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
+
+ .nr_fuse_regs = 1,
};
#endif
diff --git a/drivers/pinctrl/renesas/pfc-r8a77970.c b/drivers/pinctrl/renesas/pfc-r8a77970.c
index e1b3e3b38ec3b864..688fe31c5b98ac14 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77970.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77970.c
@@ -2557,4 +2557,6 @@ const struct sh_pfc_soc_info r8a77970_pinmux_info = {

.pinmux_data = pinmux_data,
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
+
+ .nr_fuse_regs = 4,
};
diff --git a/drivers/pinctrl/renesas/pfc-r8a77980.c b/drivers/pinctrl/renesas/pfc-r8a77980.c
index 877134d78c7e50c6..085eb6090420d013 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77980.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77980.c
@@ -15,6 +15,7 @@
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/of.h>

#include "sh_pfc.h"

@@ -3048,13 +3049,22 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = {
{ /* sentinel */ }
};

+static int r8a77980_pinmux_init(struct sh_pfc *pfc)
+{
+ if (of_machine_is_compatible("renesas,r8a77980a"))
+ r8a77980_pinmux_info.nr_fuse_regs = 5;
+
+ return 0;
+}
+
static const struct sh_pfc_soc_operations r8a77980_pfc_ops = {
+ .init = r8a77980_pinmux_init,
.pin_to_pocctrl = r8a77980_pin_to_pocctrl,
.get_bias = rcar_pinmux_get_bias,
.set_bias = rcar_pinmux_set_bias,
};

-const struct sh_pfc_soc_info r8a77980_pinmux_info = {
+struct sh_pfc_soc_info r8a77980_pinmux_info = {
.name = "r8a77980_pfc",
.ops = &r8a77980_pfc_ops,
.unlock_reg = 0xe6060000, /* PMMR */
@@ -3074,4 +3084,6 @@ const struct sh_pfc_soc_info r8a77980_pinmux_info = {

.pinmux_data = pinmux_data,
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
+
+ .nr_fuse_regs = 1,
};
diff --git a/drivers/pinctrl/renesas/pfc-r8a77990.c b/drivers/pinctrl/renesas/pfc-r8a77990.c
index 262390dd7d67a101..748b9198d1efd820 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77990.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77990.c
@@ -5336,5 +5336,7 @@ const struct sh_pfc_soc_info r8a77990_pinmux_info = {

.pinmux_data = pinmux_data,
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
+
+ .nr_fuse_regs = 1,
};
#endif
diff --git a/drivers/pinctrl/renesas/pfc-r8a77995.c b/drivers/pinctrl/renesas/pfc-r8a77995.c
index 298e7a07e4934e67..f9003b8236a8881e 100644
--- a/drivers/pinctrl/renesas/pfc-r8a77995.c
+++ b/drivers/pinctrl/renesas/pfc-r8a77995.c
@@ -3193,4 +3193,6 @@ const struct sh_pfc_soc_info r8a77995_pinmux_info = {

.pinmux_data = pinmux_data,
.pinmux_data_size = ARRAY_SIZE(pinmux_data),
+
+ .nr_fuse_regs = 1,
};
diff --git a/drivers/pinctrl/renesas/sh_pfc.h b/drivers/pinctrl/renesas/sh_pfc.h
index 0061e96400598e49..ce9b591a275ffbd3 100644
--- a/drivers/pinctrl/renesas/sh_pfc.h
+++ b/drivers/pinctrl/renesas/sh_pfc.h
@@ -290,6 +290,8 @@ struct sh_pfc_soc_info {
unsigned int pinmux_data_size;

u32 unlock_reg; /* can be literal address or mask */
+
+ unsigned int nr_fuse_regs;
};

extern const struct sh_pfc_soc_info emev2_pinmux_info;
@@ -316,7 +318,7 @@ extern const struct sh_pfc_soc_info r8a77960_pinmux_info;
extern const struct sh_pfc_soc_info r8a77961_pinmux_info;
extern const struct sh_pfc_soc_info r8a77965_pinmux_info;
extern const struct sh_pfc_soc_info r8a77970_pinmux_info;
-extern const struct sh_pfc_soc_info r8a77980_pinmux_info;
+extern struct sh_pfc_soc_info r8a77980_pinmux_info;
extern const struct sh_pfc_soc_info r8a77990_pinmux_info;
extern const struct sh_pfc_soc_info r8a77995_pinmux_info;
extern const struct sh_pfc_soc_info r8a779a0_pinmux_info;
--
2.34.1