Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2023-2025 NXP
4 */
5
6#include <linux/device.h>
7#include <linux/io.h>
8#include <linux/module.h>
9#include <linux/nvmem-provider.h>
10#include <linux/of.h>
11#include <linux/of_device.h>
12#include <linux/platform_device.h>
13
14struct s32g_ocotp_priv {
15 struct device *dev;
16 void __iomem *base;
17};
18
19static int s32g_ocotp_read(void *context, unsigned int offset,
20 void *val, size_t bytes)
21{
22 struct s32g_ocotp_priv *s32g_data = context;
23 u32 *dst = val;
24
25 while (bytes >= sizeof(u32)) {
26 *dst++ = ioread32(s32g_data->base + offset);
27
28 bytes -= sizeof(u32);
29 offset += sizeof(u32);
30 }
31
32 return 0;
33}
34
35static struct nvmem_keepout s32g_keepouts[] = {
36 { .start = 0, .end = 520 },
37 { .start = 540, .end = 564 },
38 { .start = 596, .end = 664 },
39 { .start = 668, .end = 676 },
40 { .start = 684, .end = 732 },
41 { .start = 744, .end = 864 },
42 { .start = 908, .end = 924 },
43 { .start = 928, .end = 936 },
44 { .start = 948, .end = 964 },
45 { .start = 968, .end = 976 },
46 { .start = 984, .end = 1012 },
47};
48
49static struct nvmem_config s32g_ocotp_nvmem_config = {
50 .name = "s32g-ocotp",
51 .add_legacy_fixed_of_cells = true,
52 .read_only = true,
53 .word_size = 4,
54 .reg_read = s32g_ocotp_read,
55 .keepout = s32g_keepouts,
56 .nkeepout = ARRAY_SIZE(s32g_keepouts),
57};
58
59static const struct of_device_id ocotp_of_match[] = {
60 { .compatible = "nxp,s32g2-ocotp" },
61 { /* sentinel */ }
62};
63
64static int s32g_ocotp_probe(struct platform_device *pdev)
65{
66 struct s32g_ocotp_priv *s32g_data;
67 struct device *dev = &pdev->dev;
68 struct nvmem_device *nvmem;
69 struct resource *res;
70
71 s32g_data = devm_kzalloc(dev, sizeof(*s32g_data), GFP_KERNEL);
72 if (!s32g_data)
73 return -ENOMEM;
74
75 s32g_data->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
76 if (IS_ERR(s32g_data->base))
77 return dev_err_probe(dev, PTR_ERR(s32g_data->base),
78 "Cannot map OCOTP device.\n");
79
80 s32g_data->dev = dev;
81 s32g_ocotp_nvmem_config.dev = dev;
82 s32g_ocotp_nvmem_config.priv = s32g_data;
83 s32g_ocotp_nvmem_config.size = resource_size(res);
84
85 nvmem = devm_nvmem_register(dev, &s32g_ocotp_nvmem_config);
86
87 return PTR_ERR_OR_ZERO(nvmem);
88}
89
90static struct platform_driver s32g_ocotp_driver = {
91 .probe = s32g_ocotp_probe,
92 .driver = {
93 .name = "s32g-ocotp",
94 .of_match_table = ocotp_of_match,
95 },
96};
97module_platform_driver(s32g_ocotp_driver);
98MODULE_AUTHOR("NXP");
99MODULE_DESCRIPTION("S32G OCOTP driver");
100MODULE_LICENSE("GPL");