Commit b6b7ef93 authored by Sven Peter's avatar Sven Peter Committed by Greg Kroah-Hartman

nvmem: Add Apple eFuse driver

Apple SoCs contain eFuses used to store factory-programmed data such
as calibration values for the PCIe or the Type-C PHY. They are organized
as 32bit values exposed as MMIO.
Signed-off-by: default avatarSven Peter <sven@svenpeter.dev>
Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Link: https://lore.kernel.org/r/20220429162701.2222-6-srinivas.kandagatla@linaro.orgSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 7177042b
......@@ -324,4 +324,16 @@ config NVMEM_SUNPLUS_OCOTP
This driver can also be built as a module. If so, the module
will be called nvmem-sunplus-ocotp.
config NVMEM_APPLE_EFUSES
tristate "Apple eFuse support"
depends on ARCH_APPLE || COMPILE_TEST
default ARCH_APPLE
help
Say y here to enable support for reading eFuses on Apple SoCs
such as the M1. These are e.g. used to store factory programmed
calibration data required for the PCIe or the USB-C PHY.
This driver can also be built as a module. If so, the module will
be called nvmem-apple-efuses.
endif
......@@ -65,3 +65,5 @@ obj-$(CONFIG_NVMEM_LAYERSCAPE_SFP) += nvmem-layerscape-sfp.o
nvmem-layerscape-sfp-y := layerscape-sfp.o
obj-$(CONFIG_NVMEM_SUNPLUS_OCOTP) += nvmem_sunplus_ocotp.o
nvmem_sunplus_ocotp-y := sunplus-ocotp.o
obj-$(CONFIG_NVMEM_APPLE_EFUSES) += nvmem-apple-efuses.o
nvmem-apple-efuses-y := apple-efuses.o
// SPDX-License-Identifier: GPL-2.0-only
/*
* Apple SoC eFuse driver
*
* Copyright (C) The Asahi Linux Contributors
*/
#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/platform_device.h>
struct apple_efuses_priv {
void __iomem *fuses;
};
static int apple_efuses_read(void *context, unsigned int offset, void *val,
size_t bytes)
{
struct apple_efuses_priv *priv = context;
u32 *dst = val;
while (bytes >= sizeof(u32)) {
*dst++ = readl_relaxed(priv->fuses + offset);
bytes -= sizeof(u32);
offset += sizeof(u32);
}
return 0;
}
static int apple_efuses_probe(struct platform_device *pdev)
{
struct apple_efuses_priv *priv;
struct resource *res;
struct nvmem_config config = {
.dev = &pdev->dev,
.read_only = true,
.reg_read = apple_efuses_read,
.stride = sizeof(u32),
.word_size = sizeof(u32),
.name = "apple_efuses_nvmem",
.id = NVMEM_DEVID_AUTO,
.root_only = true,
};
priv = devm_kzalloc(config.dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->fuses = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(priv->fuses))
return PTR_ERR(priv->fuses);
config.priv = priv;
config.size = resource_size(res);
return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
}
static const struct of_device_id apple_efuses_of_match[] = {
{ .compatible = "apple,efuses", },
{}
};
MODULE_DEVICE_TABLE(of, apple_efuses_of_match);
static struct platform_driver apple_efuses_driver = {
.driver = {
.name = "apple_efuses",
.of_match_table = apple_efuses_of_match,
},
.probe = apple_efuses_probe,
};
module_platform_driver(apple_efuses_driver);
MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");
MODULE_LICENSE("GPL");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment