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 14 struct s32g_ocotp_priv { 15 struct device *dev; 16 void __iomem *base; 17 }; 18 19 static 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 35 static 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 49 static 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 59 static const struct of_device_id ocotp_of_match[] = { 60 { .compatible = "nxp,s32g2-ocotp" }, 61 { /* sentinel */ } 62 }; 63 64 static 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 90 static 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 }; 97 module_platform_driver(s32g_ocotp_driver); 98 MODULE_AUTHOR("NXP"); 99 MODULE_DESCRIPTION("S32G OCOTP driver"); 100 MODULE_LICENSE("GPL"); 101