// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2023-2025 NXP */ #include #include #include #include #include #include #include struct s32g_ocotp_priv { struct device *dev; void __iomem *base; }; static int s32g_ocotp_read(void *context, unsigned int offset, void *val, size_t bytes) { struct s32g_ocotp_priv *s32g_data = context; u32 *dst = val; while (bytes >= sizeof(u32)) { *dst++ = ioread32(s32g_data->base + offset); bytes -= sizeof(u32); offset += sizeof(u32); } return 0; } static struct nvmem_keepout s32g_keepouts[] = { { .start = 0, .end = 520 }, { .start = 540, .end = 564 }, { .start = 596, .end = 664 }, { .start = 668, .end = 676 }, { .start = 684, .end = 732 }, { .start = 744, .end = 864 }, { .start = 908, .end = 924 }, { .start = 928, .end = 936 }, { .start = 948, .end = 964 }, { .start = 968, .end = 976 }, { .start = 984, .end = 1012 }, }; static struct nvmem_config s32g_ocotp_nvmem_config = { .name = "s32g-ocotp", .add_legacy_fixed_of_cells = true, .read_only = true, .word_size = 4, .reg_read = s32g_ocotp_read, .keepout = s32g_keepouts, .nkeepout = ARRAY_SIZE(s32g_keepouts), }; static const struct of_device_id ocotp_of_match[] = { { .compatible = "nxp,s32g2-ocotp" }, { /* sentinel */ } }; static int s32g_ocotp_probe(struct platform_device *pdev) { struct s32g_ocotp_priv *s32g_data; struct device *dev = &pdev->dev; struct nvmem_device *nvmem; struct resource *res; s32g_data = devm_kzalloc(dev, sizeof(*s32g_data), GFP_KERNEL); if (!s32g_data) return -ENOMEM; s32g_data->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(s32g_data->base)) return dev_err_probe(dev, PTR_ERR(s32g_data->base), "Cannot map OCOTP device.\n"); s32g_data->dev = dev; s32g_ocotp_nvmem_config.dev = dev; s32g_ocotp_nvmem_config.priv = s32g_data; s32g_ocotp_nvmem_config.size = resource_size(res); nvmem = devm_nvmem_register(dev, &s32g_ocotp_nvmem_config); return PTR_ERR_OR_ZERO(nvmem); } static struct platform_driver s32g_ocotp_driver = { .probe = s32g_ocotp_probe, .driver = { .name = "s32g-ocotp", .of_match_table = ocotp_of_match, }, }; module_platform_driver(s32g_ocotp_driver); MODULE_AUTHOR("NXP"); MODULE_DESCRIPTION("S32G OCOTP driver"); MODULE_LICENSE("GPL");