[PATCH v2 2/2] nvmem: Add Apple eFuse driver

Krzysztof Kozlowski krzysztof.kozlowski at canonical.com
Sun Mar 6 04:25:55 PST 2022


On 06/03/2022 13:18, Sven Peter wrote:
> 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: Sven Peter <sven at svenpeter.dev>
> ---
> v1 -> v2:
>   - fixed sparse warning about __iomem by introducing
>     struct apple_efuses_priv as done in other nvmem drivers
>   - make sure the driver actually works as a module by
>     setting .owner to THIS_MODULE and adding MODULE_DEVICE_TABLE
>     pointed out by Joey Gouly
> 
>  MAINTAINERS                  |  1 +
>  drivers/nvmem/Kconfig        | 12 ++++++
>  drivers/nvmem/Makefile       |  2 +
>  drivers/nvmem/apple-efuses.c | 82 ++++++++++++++++++++++++++++++++++++
>  4 files changed, 97 insertions(+)
>  create mode 100644 drivers/nvmem/apple-efuses.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index f70d8525cbd4..e3e973a3f651 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1781,6 +1781,7 @@ F:	drivers/i2c/busses/i2c-pasemi-core.c
>  F:	drivers/i2c/busses/i2c-pasemi-platform.c
>  F:	drivers/irqchip/irq-apple-aic.c
>  F:	drivers/mailbox/apple-mailbox.c
> +F:	drivers/nvmem/apple-efuses.c
>  F:	drivers/pinctrl/pinctrl-apple-gpio.c
>  F:	drivers/soc/apple/*
>  F:	drivers/watchdog/apple_wdt.c
> diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
> index da414617a54d..bba29d1aec96 100644
> --- a/drivers/nvmem/Kconfig
> +++ b/drivers/nvmem/Kconfig
> @@ -300,4 +300,16 @@ config NVMEM_BRCM_NVRAM
>  	  This driver provides support for Broadcom's NVRAM that can be accessed
>  	  using I/O mapping.
>  
> +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
> diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
> index dcbbde35b6a8..1a8e54691d3e 100644
> --- a/drivers/nvmem/Makefile
> +++ b/drivers/nvmem/Makefile
> @@ -61,3 +61,5 @@ 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
> +obj-$(CONFIG_NVMEM_APPLE_EFUSES)	+= nvmem-apple-efuses.o
> +nvmem-apple-efuses-y 		:= apple-efuses.o
> diff --git a/drivers/nvmem/apple-efuses.c b/drivers/nvmem/apple-efuses.c
> new file mode 100644
> index 000000000000..dd5576ec5408
> --- /dev/null
> +++ b/drivers/nvmem/apple-efuses.c
> @@ -0,0 +1,82 @@
> +// 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,
> +		.owner = THIS_MODULE,
> +		.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,
> +		.owner = THIS_MODULE,

You wrote it also in changelog, but why do you need it? Doesn't core set
it? Coccinelle should complain about this as well.

Best regards,
Krzysztof



More information about the linux-arm-kernel mailing list