1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Layerscape SFP driver 4 * 5 * Copyright (c) 2022 Michael Walle <michael@walle.cc> 6 * 7 */ 8 9 #include <linux/device.h> 10 #include <linux/io.h> 11 #include <linux/mod_devicetable.h> 12 #include <linux/module.h> 13 #include <linux/nvmem-provider.h> 14 #include <linux/platform_device.h> 15 #include <linux/property.h> 16 17 #define LAYERSCAPE_SFP_OTP_OFFSET 0x0200 18 19 struct layerscape_sfp_priv { 20 void __iomem *base; 21 }; 22 23 struct layerscape_sfp_data { 24 int size; 25 }; 26 27 static int layerscape_sfp_read(void *context, unsigned int offset, void *val, 28 size_t bytes) 29 { 30 struct layerscape_sfp_priv *priv = context; 31 32 memcpy_fromio(val, priv->base + LAYERSCAPE_SFP_OTP_OFFSET + offset, 33 bytes); 34 35 return 0; 36 } 37 38 static struct nvmem_config layerscape_sfp_nvmem_config = { 39 .name = "fsl-sfp", 40 .reg_read = layerscape_sfp_read, 41 }; 42 43 static int layerscape_sfp_probe(struct platform_device *pdev) 44 { 45 const struct layerscape_sfp_data *data; 46 struct layerscape_sfp_priv *priv; 47 struct nvmem_device *nvmem; 48 49 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 50 if (!priv) 51 return -ENOMEM; 52 53 priv->base = devm_platform_ioremap_resource(pdev, 0); 54 if (IS_ERR(priv->base)) 55 return PTR_ERR(priv->base); 56 57 data = device_get_match_data(&pdev->dev); 58 59 layerscape_sfp_nvmem_config.size = data->size; 60 layerscape_sfp_nvmem_config.dev = &pdev->dev; 61 layerscape_sfp_nvmem_config.priv = priv; 62 63 nvmem = devm_nvmem_register(&pdev->dev, &layerscape_sfp_nvmem_config); 64 65 return PTR_ERR_OR_ZERO(nvmem); 66 } 67 68 static const struct layerscape_sfp_data ls1028a_data = { 69 .size = 0x88, 70 }; 71 72 static const struct of_device_id layerscape_sfp_dt_ids[] = { 73 { .compatible = "fsl,ls1028a-sfp", .data = &ls1028a_data }, 74 {}, 75 }; 76 MODULE_DEVICE_TABLE(of, layerscape_sfp_dt_ids); 77 78 static struct platform_driver layerscape_sfp_driver = { 79 .probe = layerscape_sfp_probe, 80 .driver = { 81 .name = "layerscape_sfp", 82 .of_match_table = layerscape_sfp_dt_ids, 83 }, 84 }; 85 module_platform_driver(layerscape_sfp_driver); 86 87 MODULE_AUTHOR("Michael Walle <michael@walle.cc>"); 88 MODULE_DESCRIPTION("Layerscape Security Fuse Processor driver"); 89 MODULE_LICENSE("GPL"); 90