1 // SPDX-License-Identifier: GPL-2.0-only
3 * Renesas R-Car E-FUSE/OTP Driver
5 * Copyright (C) 2024 Glider bv
8 #include <linux/device.h>
9 #include <linux/export.h>
11 #include <linux/mod_devicetable.h>
12 #include <linux/nvmem-provider.h>
13 #include <linux/platform_device.h>
14 #include <linux/pm_runtime.h>
15 #include <linux/property.h>
18 struct nvmem_keepout keepouts
[2];
19 struct nvmem_device
*nvmem
;
24 struct rcar_fuse_data
{
25 unsigned int bank
; /* 0: PFC + E-FUSE, 1: OPT_MEM + E-FUSE */
26 unsigned int start
; /* inclusive */
27 unsigned int end
; /* exclusive */
30 static int rcar_fuse_reg_read(void *priv
, unsigned int offset
, void *val
,
33 struct rcar_fuse
*fuse
= priv
;
36 ret
= pm_runtime_resume_and_get(fuse
->dev
);
40 __ioread32_copy(val
, fuse
->base
+ offset
, bytes
/ 4);
42 pm_runtime_put(fuse
->dev
);
47 static int rcar_fuse_probe(struct platform_device
*pdev
)
49 struct device
*dev
= &pdev
->dev
;
50 const struct rcar_fuse_data
*data
= device_get_match_data(dev
);
51 struct nvmem_config config
= {
54 .id
= NVMEM_DEVID_NONE
,
56 .type
= NVMEM_TYPE_OTP
,
59 .reg_read
= rcar_fuse_reg_read
,
63 struct rcar_fuse
*fuse
;
67 ret
= devm_pm_runtime_enable(dev
);
71 fuse
= devm_kzalloc(dev
, sizeof(*fuse
), GFP_KERNEL
);
75 fuse
->base
= devm_platform_get_and_ioremap_resource(pdev
, data
->bank
,
77 if (IS_ERR(fuse
->base
))
78 return PTR_ERR(fuse
->base
);
81 fuse
->keepouts
[0].start
= 0;
82 fuse
->keepouts
[0].end
= data
->start
;
83 fuse
->keepouts
[1].start
= data
->end
;
84 fuse
->keepouts
[1].end
= resource_size(res
);
86 config
.keepout
= fuse
->keepouts
;
87 config
.nkeepout
= ARRAY_SIZE(fuse
->keepouts
);
88 config
.size
= resource_size(res
);
91 fuse
->nvmem
= devm_nvmem_register(dev
, &config
);
92 if (IS_ERR(fuse
->nvmem
))
93 return dev_err_probe(dev
, PTR_ERR(fuse
->nvmem
),
94 "Failed to register NVMEM device\n");
99 static const struct rcar_fuse_data rcar_fuse_v3u
= {
105 static const struct rcar_fuse_data rcar_fuse_s4
= {
111 static const struct rcar_fuse_data rcar_fuse_v4h
= {
117 static const struct rcar_fuse_data rcar_fuse_v4m
= {
123 static const struct of_device_id rcar_fuse_match
[] = {
124 { .compatible
= "renesas,r8a779a0-efuse", .data
= &rcar_fuse_v3u
},
125 { .compatible
= "renesas,r8a779f0-efuse", .data
= &rcar_fuse_s4
},
126 { .compatible
= "renesas,r8a779g0-otp", .data
= &rcar_fuse_v4h
},
127 { .compatible
= "renesas,r8a779h0-otp", .data
= &rcar_fuse_v4m
},
131 static struct platform_driver rcar_fuse_driver
= {
132 .probe
= rcar_fuse_probe
,
135 .of_match_table
= rcar_fuse_match
,
138 module_platform_driver(rcar_fuse_driver
);
140 MODULE_DESCRIPTION("Renesas R-Car E-FUSE/OTP driver");
141 MODULE_LICENSE("GPL");
142 MODULE_AUTHOR("Geert Uytterhoeven");