| // SPDX-License-Identifier: GPL-2.0 | 
 | /* | 
 |  *  Copyright (C) 2023  Westermo Network Technologies AB | 
 |  */ | 
 |  | 
 | #include <linux/device.h> | 
 | #include <linux/io.h> | 
 | #include <linux/module.h> | 
 | #include <linux/mod_devicetable.h> | 
 | #include <linux/nvmem-provider.h> | 
 | #include <linux/platform_device.h> | 
 |  | 
 | struct qoriq_efuse_priv { | 
 | 	void __iomem *base; | 
 | }; | 
 |  | 
 | static int qoriq_efuse_read(void *context, unsigned int offset, void *val, | 
 | 			    size_t bytes) | 
 | { | 
 | 	struct qoriq_efuse_priv *priv = context; | 
 |  | 
 | 	/* .stride = 4 so offset is guaranteed to be aligned */ | 
 | 	__ioread32_copy(val, priv->base + offset, bytes / 4); | 
 |  | 
 | 	/* Ignore trailing bytes (there shouldn't be any) */ | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int qoriq_efuse_probe(struct platform_device *pdev) | 
 | { | 
 | 	struct nvmem_config config = { | 
 | 		.dev = &pdev->dev, | 
 | 		.read_only = true, | 
 | 		.reg_read = qoriq_efuse_read, | 
 | 		.stride = sizeof(u32), | 
 | 		.word_size = sizeof(u32), | 
 | 		.name = "qoriq_efuse_read", | 
 | 		.id = NVMEM_DEVID_AUTO, | 
 | 		.root_only = true, | 
 | 	}; | 
 | 	struct qoriq_efuse_priv *priv; | 
 | 	struct nvmem_device *nvmem; | 
 | 	struct resource *res; | 
 |  | 
 | 	priv = devm_kzalloc(config.dev, sizeof(*priv), GFP_KERNEL); | 
 | 	if (!priv) | 
 | 		return -ENOMEM; | 
 |  | 
 | 	priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); | 
 | 	if (IS_ERR(priv->base)) | 
 | 		return PTR_ERR(priv->base); | 
 |  | 
 | 	config.size = resource_size(res); | 
 | 	config.priv = priv; | 
 | 	nvmem = devm_nvmem_register(config.dev, &config); | 
 |  | 
 | 	return PTR_ERR_OR_ZERO(nvmem); | 
 | } | 
 |  | 
 | static const struct of_device_id qoriq_efuse_of_match[] = { | 
 | 	{ .compatible = "fsl,t1023-sfp", }, | 
 | 	{/* sentinel */}, | 
 | }; | 
 | MODULE_DEVICE_TABLE(of, qoriq_efuse_of_match); | 
 |  | 
 | static struct platform_driver qoriq_efuse_driver = { | 
 | 	.probe = qoriq_efuse_probe, | 
 | 	.driver = { | 
 | 		.name = "qoriq-efuse", | 
 | 		.of_match_table = qoriq_efuse_of_match, | 
 | 	}, | 
 | }; | 
 | module_platform_driver(qoriq_efuse_driver); | 
 |  | 
 | MODULE_AUTHOR("Richard Alpe <richard.alpe@bit42.se>"); | 
 | MODULE_DESCRIPTION("NXP QorIQ Security Fuse Processor (SFP) Reader"); | 
 | MODULE_LICENSE("GPL"); |