1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2021 Rafał Miłecki <rafal@milecki.pl> 4 */ 5 6 #include <linux/io.h> 7 #include <linux/mod_devicetable.h> 8 #include <linux/module.h> 9 #include <linux/nvmem-provider.h> 10 #include <linux/platform_device.h> 11 12 struct brcm_nvram { 13 struct device *dev; 14 void __iomem *base; 15 }; 16 17 static int brcm_nvram_read(void *context, unsigned int offset, void *val, 18 size_t bytes) 19 { 20 struct brcm_nvram *priv = context; 21 u8 *dst = val; 22 23 while (bytes--) 24 *dst++ = readb(priv->base + offset++); 25 26 return 0; 27 } 28 29 static int brcm_nvram_probe(struct platform_device *pdev) 30 { 31 struct nvmem_config config = { 32 .name = "brcm-nvram", 33 .reg_read = brcm_nvram_read, 34 }; 35 struct device *dev = &pdev->dev; 36 struct resource *res; 37 struct brcm_nvram *priv; 38 39 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 40 if (!priv) 41 return -ENOMEM; 42 priv->dev = dev; 43 44 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 45 priv->base = devm_ioremap_resource(dev, res); 46 if (IS_ERR(priv->base)) 47 return PTR_ERR(priv->base); 48 49 config.dev = dev; 50 config.priv = priv; 51 config.size = resource_size(res); 52 53 return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); 54 } 55 56 static const struct of_device_id brcm_nvram_of_match_table[] = { 57 { .compatible = "brcm,nvram", }, 58 {}, 59 }; 60 61 static struct platform_driver brcm_nvram_driver = { 62 .probe = brcm_nvram_probe, 63 .driver = { 64 .name = "brcm_nvram", 65 .of_match_table = brcm_nvram_of_match_table, 66 }, 67 }; 68 69 static int __init brcm_nvram_init(void) 70 { 71 return platform_driver_register(&brcm_nvram_driver); 72 } 73 74 subsys_initcall_sync(brcm_nvram_init); 75 76 MODULE_AUTHOR("Rafał Miłecki"); 77 MODULE_LICENSE("GPL"); 78 MODULE_DEVICE_TABLE(of, brcm_nvram_of_match_table); 79