From: Rafał Miłecki <rafal@xxxxxxxxxx> This driver provides access to Broadcom's NVRAM. Signed-off-by: Rafał Miłecki <rafal@xxxxxxxxxx> --- V2: Applied Srinivas's suggestions: * Simplified brcm_nvram_read * Drop unneeded check & prints from probe * Fixed MODULE_LICENSE * Switched to Broadcom specific binding & driver. This is such a trivial driver that even if we get another similar one, it probably won't be worth it to share their code. Thank you Srinivas! --- drivers/nvmem/Kconfig | 9 +++++ drivers/nvmem/Makefile | 2 + drivers/nvmem/brcm_nvram.c | 78 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 drivers/nvmem/brcm_nvram.c diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index 75d2594c16e1..d2a848fab82a 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -278,4 +278,13 @@ config NVMEM_RMEM This driver can also be built as a module. If so, the module will be called nvmem-rmem. + +config NVMEM_BRCM_NVRAM + tristate "Broadcom's NVRAM support" + depends on ARCH_BCM_5301X || COMPILE_TEST + depends on HAS_IOMEM + help + This driver provides support for Broadcom's NVRAM that can be accessed + using I/O mapping. + endif diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index 5376b8e0dae5..bbea1410240a 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile @@ -57,3 +57,5 @@ obj-$(CONFIG_SPRD_EFUSE) += nvmem_sprd_efuse.o nvmem_sprd_efuse-y := sprd-efuse.o obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o nvmem-rmem-y := rmem.o +obj-$(CONFIG_NVMEM_BRCM_NVRAM) += nvmem_brcm_nvram.o +nvmem_brcm_nvram-y := brcm_nvram.o diff --git a/drivers/nvmem/brcm_nvram.c b/drivers/nvmem/brcm_nvram.c new file mode 100644 index 000000000000..bd2ecaaf4585 --- /dev/null +++ b/drivers/nvmem/brcm_nvram.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2021 Rafał Miłecki <rafal@xxxxxxxxxx> + */ + +#include <linux/io.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/nvmem-provider.h> +#include <linux/platform_device.h> + +struct brcm_nvram { + struct device *dev; + void __iomem *base; +}; + +static int brcm_nvram_read(void *context, unsigned int offset, void *val, + size_t bytes) +{ + struct brcm_nvram *priv = context; + u8 *dst = val; + + while (bytes--) + *dst++ = readb(priv->base + offset++); + + return 0; +} + +static int brcm_nvram_probe(struct platform_device *pdev) +{ + struct nvmem_config config = { + .name = "brcm-nvram", + .reg_read = brcm_nvram_read, + }; + struct device *dev = &pdev->dev; + struct resource *res; + struct brcm_nvram *priv; + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + priv->dev = dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->base = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + config.dev = dev; + config.priv = priv; + config.size = resource_size(res); + + return PTR_ERR_OR_ZERO(devm_nvmem_register(dev, &config)); +} + +static const struct of_device_id brcm_nvram_of_match_table[] = { + { .compatible = "brcm,nvram", }, + {}, +}; + +static struct platform_driver brcm_nvram_driver = { + .probe = brcm_nvram_probe, + .driver = { + .name = "brcm_nvram", + .of_match_table = brcm_nvram_of_match_table, + }, +}; + +static int __init brcm_nvram_init(void) +{ + return platform_driver_register(&brcm_nvram_driver); +} + +subsys_initcall_sync(brcm_nvram_init); + +MODULE_AUTHOR("Rafał Miłecki"); +MODULE_LICENSE("GPL"); +MODULE_DEVICE_TABLE(of, brcm_nvram_of_match_table); -- 2.26.2