* [PATCH v2 1/2] dt-bindings: nvmem: Add Spreadtrum SC27XX efuse controller documentation @ 2018-06-25 6:31 Baolin Wang 2018-06-25 6:31 ` [PATCH v2 2/2] nvmem: Add Spreadtrum SC27XX efuse support Baolin Wang 0 siblings, 1 reply; 5+ messages in thread From: Baolin Wang @ 2018-06-25 6:31 UTC (permalink / raw) To: srinivas.kandagatla, robh+dt, mark.rutland Cc: broonie, freeman.liu, baolin.wang, devicetree, linux-kernel This patch adds the binding documentation for Spreadtrum SC27XX series PMICs efuse controller device. Signed-off-by: Baolin Wang <baolin.wang@linaro.org> Reviewed-by: Rob Herring <robh@kernel.org> --- Changes since v1: - Add reviewed tag from Rob. --- .../devicetree/bindings/nvmem/sc27xx-efuse.txt | 52 ++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt diff --git a/Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt b/Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt new file mode 100644 index 0000000..586c082 --- /dev/null +++ b/Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt @@ -0,0 +1,52 @@ += Spreadtrum SC27XX PMIC eFuse device tree bindings = + +Required properties: +- compatible: Should be one of the following. + "sprd,sc2720-efuse" + "sprd,sc2721-efuse" + "sprd,sc2723-efuse" + "sprd,sc2730-efuse" + "sprd,sc2731-efuse" +- reg: Specify the address offset of efuse controller. +- hwlocks: Reference to a phandle of a hwlock provider node. + += Data cells = +Are child nodes of eFuse, bindings of which as described in +bindings/nvmem/nvmem.txt + +Example: + + sc2731_pmic: pmic@0 { + compatible = "sprd,sc2731"; + reg = <0>; + spi-max-frequency = <26000000>; + interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; + interrupt-controller; + #interrupt-cells = <2>; + #address-cells = <1>; + #size-cells = <0>; + + efuse@380 { + compatible = "sprd,sc2731-efuse"; + reg = <0x380>; + #address-cells = <1>; + #size-cells = <1>; + hwlocks = <&hwlock 12>; + + /* Data cells */ + thermal_calib: calib@10 { + reg = <0x10 0x2>; + }; + }; + }; + += Data consumers = +Are device nodes which consume nvmem data cells. + +Example: + + thermal { + ... + nvmem-cells = <&thermal_calib>; + nvmem-cell-names = "calibration"; + }; -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] nvmem: Add Spreadtrum SC27XX efuse support 2018-06-25 6:31 [PATCH v2 1/2] dt-bindings: nvmem: Add Spreadtrum SC27XX efuse controller documentation Baolin Wang @ 2018-06-25 6:31 ` Baolin Wang 2018-07-09 9:26 ` Baolin Wang 0 siblings, 1 reply; 5+ messages in thread From: Baolin Wang @ 2018-06-25 6:31 UTC (permalink / raw) To: srinivas.kandagatla, robh+dt, mark.rutland Cc: broonie, freeman.liu, baolin.wang, devicetree, linux-kernel From: Freeman Liu <freeman.liu@spreadtrum.com> This patch add the efuse driver which is embeded in Spreadtrum SC27XX series PMICs. The sc27xx efuse contains 32 blocks and each block's data width is 16 bits. Signed-off-by: Freeman Liu <freeman.liu@spreadtrum.com> Signed-off-by: Baolin Wang <baolin.wang@linaro.org> --- Changes since v1: - Fix one typo. --- drivers/nvmem/Kconfig | 11 ++ drivers/nvmem/Makefile | 3 +- drivers/nvmem/sc27xx-efuse.c | 263 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 drivers/nvmem/sc27xx-efuse.c diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index 54a3c29..0a7a470e 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -181,4 +181,15 @@ config RAVE_SP_EEPROM help Say y here to enable Rave SP EEPROM support. +config SC27XX_EFUSE + tristate "Spreadtrum SC27XX eFuse Support" + depends on MFD_SC27XX_PMIC || COMPILE_TEST + depends on HAS_IOMEM + help + This is a simple driver to dump specified values of Spreadtrum + SC27XX PMICs from eFuse. + + This driver can also be built as a module. If so, the module + will be called nvmem-sc27xx-efuse. + endif diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index 27e96a8..4e8c616 100644 --- a/drivers/nvmem/Makefile +++ b/drivers/nvmem/Makefile @@ -39,4 +39,5 @@ obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o nvmem_snvs_lpgpr-y := snvs_lpgpr.o obj-$(CONFIG_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o - +obj-$(CONFIG_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o +nvmem-sc27xx-efuse-y := sc27xx-efuse.o diff --git a/drivers/nvmem/sc27xx-efuse.c b/drivers/nvmem/sc27xx-efuse.c new file mode 100644 index 0000000..07c210c --- /dev/null +++ b/drivers/nvmem/sc27xx-efuse.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2018 Spreadtrum Communications Inc. + +#include <linux/hwspinlock.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/nvmem-provider.h> + +/* PMIC global registers definition */ +#define SC27XX_MODULE_EN 0xc08 +#define SC27XX_EFUSE_EN BIT(6) + +/* Efuse controller registers definition */ +#define SC27XX_EFUSE_GLB_CTRL 0x0 +#define SC27XX_EFUSE_DATA_RD 0x4 +#define SC27XX_EFUSE_DATA_WR 0x8 +#define SC27XX_EFUSE_BLOCK_INDEX 0xc +#define SC27XX_EFUSE_MODE_CTRL 0x10 +#define SC27XX_EFUSE_STATUS 0x14 +#define SC27XX_EFUSE_WR_TIMING_CTRL 0x20 +#define SC27XX_EFUSE_RD_TIMING_CTRL 0x24 +#define SC27XX_EFUSE_EFUSE_DEB_CTRL 0x28 + +/* Mask definition for SC27XX_EFUSE_BLOCK_INDEX register */ +#define SC27XX_EFUSE_BLOCK_MASK GENMASK(4, 0) + +/* Bits definitions for SC27XX_EFUSE_MODE_CTRL register */ +#define SC27XX_EFUSE_PG_START BIT(0) +#define SC27XX_EFUSE_RD_START BIT(1) +#define SC27XX_EFUSE_CLR_RDDONE BIT(2) + +/* Bits definitions for SC27XX_EFUSE_STATUS register */ +#define SC27XX_EFUSE_PGM_BUSY BIT(0) +#define SC27XX_EFUSE_READ_BUSY BIT(1) +#define SC27XX_EFUSE_STANDBY BIT(2) +#define SC27XX_EFUSE_GLOBAL_PROT BIT(3) +#define SC27XX_EFUSE_RD_DONE BIT(4) + +/* Block number and block width (bytes) definitions */ +#define SC27XX_EFUSE_BLOCK_MAX 32 +#define SC27XX_EFUSE_BLOCK_WIDTH 2 + +/* Timeout (ms) for the trylock of hardware spinlocks */ +#define SC27XX_EFUSE_HWLOCK_TIMEOUT 5000 + +/* Timeout (us) of polling the status */ +#define SC27XX_EFUSE_POLL_TIMEOUT 3000000 +#define SC27XX_EFUSE_POLL_DELAY_US 10000 + +struct sc27xx_efuse { + struct device *dev; + struct regmap *regmap; + struct hwspinlock *hwlock; + struct mutex mutex; + u32 base; +}; + +/* + * On Spreadtrum platform, we have multi-subsystems will access the unique + * efuse controller, so we need one hardware spinlock to synchronize between + * the multiple subsystems. + */ +static int sc27xx_efuse_lock(struct sc27xx_efuse *efuse) +{ + int ret; + + mutex_lock(&efuse->mutex); + + ret = hwspin_lock_timeout_raw(efuse->hwlock, + SC27XX_EFUSE_HWLOCK_TIMEOUT); + if (ret) { + dev_err(efuse->dev, "timeout to get the hwspinlock\n"); + mutex_unlock(&efuse->mutex); + return ret; + } + + return 0; +} + +static void sc27xx_efuse_unlock(struct sc27xx_efuse *efuse) +{ + hwspin_unlock_raw(efuse->hwlock); + mutex_unlock(&efuse->mutex); +} + +static int sc27xx_efuse_poll_status(struct sc27xx_efuse *efuse, u32 bits) +{ + int ret; + u32 val; + + ret = regmap_read_poll_timeout(efuse->regmap, + efuse->base + SC27XX_EFUSE_STATUS, + val, (val & bits), + SC27XX_EFUSE_POLL_DELAY_US, + SC27XX_EFUSE_POLL_TIMEOUT); + if (ret) { + dev_err(efuse->dev, "timeout to update the efuse status\n"); + return ret; + } + + return 0; +} + +static int sc27xx_efuse_read(void *context, u32 offset, void *val, size_t bytes) +{ + struct sc27xx_efuse *efuse = context; + u32 buf; + int ret; + + if (offset > SC27XX_EFUSE_BLOCK_MAX || bytes > SC27XX_EFUSE_BLOCK_WIDTH) + return -EINVAL; + + ret = sc27xx_efuse_lock(efuse); + if (ret) + return ret; + + /* Enable the efuse controller. */ + ret = regmap_update_bits(efuse->regmap, SC27XX_MODULE_EN, + SC27XX_EFUSE_EN, SC27XX_EFUSE_EN); + if (ret) + goto unlock_efuse; + + /* + * Before reading, we should ensure the efuse controller is in + * standby state. + */ + ret = sc27xx_efuse_poll_status(efuse, SC27XX_EFUSE_STANDBY); + if (ret) + goto disable_efuse; + + /* Set the block address to be read. */ + ret = regmap_write(efuse->regmap, efuse->base + SC27XX_EFUSE_BLOCK_INDEX, + offset & SC27XX_EFUSE_BLOCK_MASK); + if (ret) + goto disable_efuse; + + /* Start reading process from efuse memory. */ + ret = regmap_update_bits(efuse->regmap, + efuse->base + SC27XX_EFUSE_MODE_CTRL, + SC27XX_EFUSE_RD_START, + SC27XX_EFUSE_RD_START); + if (ret) + goto disable_efuse; + + /* + * Polling the read done status to make sure the reading process + * is completed, that means the data can be read out now. + */ + ret = sc27xx_efuse_poll_status(efuse, SC27XX_EFUSE_RD_DONE); + if (ret) + goto disable_efuse; + + /* Read data from efuse memory. */ + ret = regmap_read(efuse->regmap, efuse->base + SC27XX_EFUSE_DATA_RD, + &buf); + if (ret) + goto disable_efuse; + + /* Clear the read done flag. */ + ret = regmap_update_bits(efuse->regmap, + efuse->base + SC27XX_EFUSE_MODE_CTRL, + SC27XX_EFUSE_CLR_RDDONE, + SC27XX_EFUSE_CLR_RDDONE); + +disable_efuse: + /* Disable the efuse controller after reading. */ + regmap_update_bits(efuse->regmap, SC27XX_MODULE_EN, SC27XX_EFUSE_EN, 0); +unlock_efuse: + sc27xx_efuse_unlock(efuse); + + if (!ret) + memcpy(val, &buf, bytes); + + return ret; +} + +static int sc27xx_efuse_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct nvmem_config econfig = { }; + struct nvmem_device *nvmem; + struct sc27xx_efuse *efuse; + int ret; + + efuse = devm_kzalloc(&pdev->dev, sizeof(*efuse), GFP_KERNEL); + if (!efuse) + return -ENOMEM; + + efuse->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!efuse->regmap) { + dev_err(&pdev->dev, "failed to get efuse regmap\n"); + return -ENODEV; + } + + ret = of_property_read_u32(np, "reg", &efuse->base); + if (ret) { + dev_err(&pdev->dev, "failed to get efuse base address\n"); + return ret; + } + + ret = of_hwspin_lock_get_id(np, 0); + if (ret < 0) { + dev_err(&pdev->dev, "failed to get hwspinlock id\n"); + return ret; + } + + efuse->hwlock = hwspin_lock_request_specific(ret); + if (!efuse->hwlock) { + dev_err(&pdev->dev, "failed to request hwspinlock\n"); + return -ENXIO; + } + + mutex_init(&efuse->mutex); + efuse->dev = &pdev->dev; + platform_set_drvdata(pdev, efuse); + + econfig.stride = 1; + econfig.word_size = 1; + econfig.read_only = true; + econfig.name = "sc27xx-efuse"; + econfig.size = SC27XX_EFUSE_BLOCK_MAX * SC27XX_EFUSE_BLOCK_WIDTH; + econfig.reg_read = sc27xx_efuse_read; + econfig.priv = efuse; + econfig.dev = &pdev->dev; + nvmem = devm_nvmem_register(&pdev->dev, &econfig); + if (IS_ERR(nvmem)) { + dev_err(&pdev->dev, "failed to register nvmem config\n"); + hwspin_lock_free(efuse->hwlock); + return PTR_ERR(nvmem); + } + + return 0; +} + +static int sc27xx_efuse_remove(struct platform_device *pdev) +{ + struct sc27xx_efuse *efuse = platform_get_drvdata(pdev); + + hwspin_lock_free(efuse->hwlock); + return 0; +} + +static const struct of_device_id sc27xx_efuse_of_match[] = { + { .compatible = "sprd,sc2731-efuse" }, + { } +}; + +static struct platform_driver sc27xx_efuse_driver = { + .probe = sc27xx_efuse_probe, + .remove = sc27xx_efuse_remove, + .driver = { + .name = "sc27xx-efuse", + .of_match_table = sc27xx_efuse_of_match, + }, +}; + +module_platform_driver(sc27xx_efuse_driver); + +MODULE_AUTHOR("Freeman Liu <freeman.liu@spreadtrum.com>"); +MODULE_DESCRIPTION("Spreadtrum SC27xx efuse driver"); +MODULE_LICENSE("GPL v2"); -- 1.7.9.5 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] nvmem: Add Spreadtrum SC27XX efuse support 2018-06-25 6:31 ` [PATCH v2 2/2] nvmem: Add Spreadtrum SC27XX efuse support Baolin Wang @ 2018-07-09 9:26 ` Baolin Wang 2018-07-09 9:41 ` Srinivas Kandagatla 0 siblings, 1 reply; 5+ messages in thread From: Baolin Wang @ 2018-07-09 9:26 UTC (permalink / raw) To: Srinivas Kandagatla, Rob Herring, Mark Rutland Cc: Mark Brown, freeman.liu, Baolin Wang, DTML, LKML Hi Srinivas, On 25 June 2018 at 14:31, Baolin Wang <baolin.wang@linaro.org> wrote: > From: Freeman Liu <freeman.liu@spreadtrum.com> > > This patch add the efuse driver which is embeded in Spreadtrum SC27XX > series PMICs. The sc27xx efuse contains 32 blocks and each block's > data width is 16 bits. > > Signed-off-by: Freeman Liu <freeman.liu@spreadtrum.com> > Signed-off-by: Baolin Wang <baolin.wang@linaro.org> > --- > Changes since v1: > - Fix one typo. > --- Do you have any comments for this patch set? Thanks. > drivers/nvmem/Kconfig | 11 ++ > drivers/nvmem/Makefile | 3 +- > drivers/nvmem/sc27xx-efuse.c | 263 ++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 276 insertions(+), 1 deletion(-) > create mode 100644 drivers/nvmem/sc27xx-efuse.c > > diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig > index 54a3c29..0a7a470e 100644 > --- a/drivers/nvmem/Kconfig > +++ b/drivers/nvmem/Kconfig > @@ -181,4 +181,15 @@ config RAVE_SP_EEPROM > help > Say y here to enable Rave SP EEPROM support. > > +config SC27XX_EFUSE > + tristate "Spreadtrum SC27XX eFuse Support" > + depends on MFD_SC27XX_PMIC || COMPILE_TEST > + depends on HAS_IOMEM > + help > + This is a simple driver to dump specified values of Spreadtrum > + SC27XX PMICs from eFuse. > + > + This driver can also be built as a module. If so, the module > + will be called nvmem-sc27xx-efuse. > + > endif > diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile > index 27e96a8..4e8c616 100644 > --- a/drivers/nvmem/Makefile > +++ b/drivers/nvmem/Makefile > @@ -39,4 +39,5 @@ obj-$(CONFIG_NVMEM_SNVS_LPGPR) += nvmem_snvs_lpgpr.o > nvmem_snvs_lpgpr-y := snvs_lpgpr.o > obj-$(CONFIG_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o > nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o > - > +obj-$(CONFIG_SC27XX_EFUSE) += nvmem-sc27xx-efuse.o > +nvmem-sc27xx-efuse-y := sc27xx-efuse.o > diff --git a/drivers/nvmem/sc27xx-efuse.c b/drivers/nvmem/sc27xx-efuse.c > new file mode 100644 > index 0000000..07c210c > --- /dev/null > +++ b/drivers/nvmem/sc27xx-efuse.c > @@ -0,0 +1,263 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// Copyright (C) 2018 Spreadtrum Communications Inc. > + > +#include <linux/hwspinlock.h> > +#include <linux/module.h> > +#include <linux/of.h> > +#include <linux/platform_device.h> > +#include <linux/regmap.h> > +#include <linux/nvmem-provider.h> > + > +/* PMIC global registers definition */ > +#define SC27XX_MODULE_EN 0xc08 > +#define SC27XX_EFUSE_EN BIT(6) > + > +/* Efuse controller registers definition */ > +#define SC27XX_EFUSE_GLB_CTRL 0x0 > +#define SC27XX_EFUSE_DATA_RD 0x4 > +#define SC27XX_EFUSE_DATA_WR 0x8 > +#define SC27XX_EFUSE_BLOCK_INDEX 0xc > +#define SC27XX_EFUSE_MODE_CTRL 0x10 > +#define SC27XX_EFUSE_STATUS 0x14 > +#define SC27XX_EFUSE_WR_TIMING_CTRL 0x20 > +#define SC27XX_EFUSE_RD_TIMING_CTRL 0x24 > +#define SC27XX_EFUSE_EFUSE_DEB_CTRL 0x28 > + > +/* Mask definition for SC27XX_EFUSE_BLOCK_INDEX register */ > +#define SC27XX_EFUSE_BLOCK_MASK GENMASK(4, 0) > + > +/* Bits definitions for SC27XX_EFUSE_MODE_CTRL register */ > +#define SC27XX_EFUSE_PG_START BIT(0) > +#define SC27XX_EFUSE_RD_START BIT(1) > +#define SC27XX_EFUSE_CLR_RDDONE BIT(2) > + > +/* Bits definitions for SC27XX_EFUSE_STATUS register */ > +#define SC27XX_EFUSE_PGM_BUSY BIT(0) > +#define SC27XX_EFUSE_READ_BUSY BIT(1) > +#define SC27XX_EFUSE_STANDBY BIT(2) > +#define SC27XX_EFUSE_GLOBAL_PROT BIT(3) > +#define SC27XX_EFUSE_RD_DONE BIT(4) > + > +/* Block number and block width (bytes) definitions */ > +#define SC27XX_EFUSE_BLOCK_MAX 32 > +#define SC27XX_EFUSE_BLOCK_WIDTH 2 > + > +/* Timeout (ms) for the trylock of hardware spinlocks */ > +#define SC27XX_EFUSE_HWLOCK_TIMEOUT 5000 > + > +/* Timeout (us) of polling the status */ > +#define SC27XX_EFUSE_POLL_TIMEOUT 3000000 > +#define SC27XX_EFUSE_POLL_DELAY_US 10000 > + > +struct sc27xx_efuse { > + struct device *dev; > + struct regmap *regmap; > + struct hwspinlock *hwlock; > + struct mutex mutex; > + u32 base; > +}; > + > +/* > + * On Spreadtrum platform, we have multi-subsystems will access the unique > + * efuse controller, so we need one hardware spinlock to synchronize between > + * the multiple subsystems. > + */ > +static int sc27xx_efuse_lock(struct sc27xx_efuse *efuse) > +{ > + int ret; > + > + mutex_lock(&efuse->mutex); > + > + ret = hwspin_lock_timeout_raw(efuse->hwlock, > + SC27XX_EFUSE_HWLOCK_TIMEOUT); > + if (ret) { > + dev_err(efuse->dev, "timeout to get the hwspinlock\n"); > + mutex_unlock(&efuse->mutex); > + return ret; > + } > + > + return 0; > +} > + > +static void sc27xx_efuse_unlock(struct sc27xx_efuse *efuse) > +{ > + hwspin_unlock_raw(efuse->hwlock); > + mutex_unlock(&efuse->mutex); > +} > + > +static int sc27xx_efuse_poll_status(struct sc27xx_efuse *efuse, u32 bits) > +{ > + int ret; > + u32 val; > + > + ret = regmap_read_poll_timeout(efuse->regmap, > + efuse->base + SC27XX_EFUSE_STATUS, > + val, (val & bits), > + SC27XX_EFUSE_POLL_DELAY_US, > + SC27XX_EFUSE_POLL_TIMEOUT); > + if (ret) { > + dev_err(efuse->dev, "timeout to update the efuse status\n"); > + return ret; > + } > + > + return 0; > +} > + > +static int sc27xx_efuse_read(void *context, u32 offset, void *val, size_t bytes) > +{ > + struct sc27xx_efuse *efuse = context; > + u32 buf; > + int ret; > + > + if (offset > SC27XX_EFUSE_BLOCK_MAX || bytes > SC27XX_EFUSE_BLOCK_WIDTH) > + return -EINVAL; > + > + ret = sc27xx_efuse_lock(efuse); > + if (ret) > + return ret; > + > + /* Enable the efuse controller. */ > + ret = regmap_update_bits(efuse->regmap, SC27XX_MODULE_EN, > + SC27XX_EFUSE_EN, SC27XX_EFUSE_EN); > + if (ret) > + goto unlock_efuse; > + > + /* > + * Before reading, we should ensure the efuse controller is in > + * standby state. > + */ > + ret = sc27xx_efuse_poll_status(efuse, SC27XX_EFUSE_STANDBY); > + if (ret) > + goto disable_efuse; > + > + /* Set the block address to be read. */ > + ret = regmap_write(efuse->regmap, efuse->base + SC27XX_EFUSE_BLOCK_INDEX, > + offset & SC27XX_EFUSE_BLOCK_MASK); > + if (ret) > + goto disable_efuse; > + > + /* Start reading process from efuse memory. */ > + ret = regmap_update_bits(efuse->regmap, > + efuse->base + SC27XX_EFUSE_MODE_CTRL, > + SC27XX_EFUSE_RD_START, > + SC27XX_EFUSE_RD_START); > + if (ret) > + goto disable_efuse; > + > + /* > + * Polling the read done status to make sure the reading process > + * is completed, that means the data can be read out now. > + */ > + ret = sc27xx_efuse_poll_status(efuse, SC27XX_EFUSE_RD_DONE); > + if (ret) > + goto disable_efuse; > + > + /* Read data from efuse memory. */ > + ret = regmap_read(efuse->regmap, efuse->base + SC27XX_EFUSE_DATA_RD, > + &buf); > + if (ret) > + goto disable_efuse; > + > + /* Clear the read done flag. */ > + ret = regmap_update_bits(efuse->regmap, > + efuse->base + SC27XX_EFUSE_MODE_CTRL, > + SC27XX_EFUSE_CLR_RDDONE, > + SC27XX_EFUSE_CLR_RDDONE); > + > +disable_efuse: > + /* Disable the efuse controller after reading. */ > + regmap_update_bits(efuse->regmap, SC27XX_MODULE_EN, SC27XX_EFUSE_EN, 0); > +unlock_efuse: > + sc27xx_efuse_unlock(efuse); > + > + if (!ret) > + memcpy(val, &buf, bytes); > + > + return ret; > +} > + > +static int sc27xx_efuse_probe(struct platform_device *pdev) > +{ > + struct device_node *np = pdev->dev.of_node; > + struct nvmem_config econfig = { }; > + struct nvmem_device *nvmem; > + struct sc27xx_efuse *efuse; > + int ret; > + > + efuse = devm_kzalloc(&pdev->dev, sizeof(*efuse), GFP_KERNEL); > + if (!efuse) > + return -ENOMEM; > + > + efuse->regmap = dev_get_regmap(pdev->dev.parent, NULL); > + if (!efuse->regmap) { > + dev_err(&pdev->dev, "failed to get efuse regmap\n"); > + return -ENODEV; > + } > + > + ret = of_property_read_u32(np, "reg", &efuse->base); > + if (ret) { > + dev_err(&pdev->dev, "failed to get efuse base address\n"); > + return ret; > + } > + > + ret = of_hwspin_lock_get_id(np, 0); > + if (ret < 0) { > + dev_err(&pdev->dev, "failed to get hwspinlock id\n"); > + return ret; > + } > + > + efuse->hwlock = hwspin_lock_request_specific(ret); > + if (!efuse->hwlock) { > + dev_err(&pdev->dev, "failed to request hwspinlock\n"); > + return -ENXIO; > + } > + > + mutex_init(&efuse->mutex); > + efuse->dev = &pdev->dev; > + platform_set_drvdata(pdev, efuse); > + > + econfig.stride = 1; > + econfig.word_size = 1; > + econfig.read_only = true; > + econfig.name = "sc27xx-efuse"; > + econfig.size = SC27XX_EFUSE_BLOCK_MAX * SC27XX_EFUSE_BLOCK_WIDTH; > + econfig.reg_read = sc27xx_efuse_read; > + econfig.priv = efuse; > + econfig.dev = &pdev->dev; > + nvmem = devm_nvmem_register(&pdev->dev, &econfig); > + if (IS_ERR(nvmem)) { > + dev_err(&pdev->dev, "failed to register nvmem config\n"); > + hwspin_lock_free(efuse->hwlock); > + return PTR_ERR(nvmem); > + } > + > + return 0; > +} > + > +static int sc27xx_efuse_remove(struct platform_device *pdev) > +{ > + struct sc27xx_efuse *efuse = platform_get_drvdata(pdev); > + > + hwspin_lock_free(efuse->hwlock); > + return 0; > +} > + > +static const struct of_device_id sc27xx_efuse_of_match[] = { > + { .compatible = "sprd,sc2731-efuse" }, > + { } > +}; > + > +static struct platform_driver sc27xx_efuse_driver = { > + .probe = sc27xx_efuse_probe, > + .remove = sc27xx_efuse_remove, > + .driver = { > + .name = "sc27xx-efuse", > + .of_match_table = sc27xx_efuse_of_match, > + }, > +}; > + > +module_platform_driver(sc27xx_efuse_driver); > + > +MODULE_AUTHOR("Freeman Liu <freeman.liu@spreadtrum.com>"); > +MODULE_DESCRIPTION("Spreadtrum SC27xx efuse driver"); > +MODULE_LICENSE("GPL v2"); > -- > 1.7.9.5 > -- Baolin Wang Best Regards ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] nvmem: Add Spreadtrum SC27XX efuse support 2018-07-09 9:26 ` Baolin Wang @ 2018-07-09 9:41 ` Srinivas Kandagatla 2018-07-09 10:30 ` Baolin Wang 0 siblings, 1 reply; 5+ messages in thread From: Srinivas Kandagatla @ 2018-07-09 9:41 UTC (permalink / raw) To: Baolin Wang, Rob Herring, Mark Rutland Cc: Mark Brown, freeman.liu, DTML, LKML On 09/07/18 10:26, Baolin Wang wrote: > Hi Srinivas, > > On 25 June 2018 at 14:31, Baolin Wang<baolin.wang@linaro.org> wrote: >> From: Freeman Liu<freeman.liu@spreadtrum.com> >> >> This patch add the efuse driver which is embeded in Spreadtrum SC27XX >> series PMICs. The sc27xx efuse contains 32 blocks and each block's >> data width is 16 bits. >> >> Signed-off-by: Freeman Liu<freeman.liu@spreadtrum.com> >> Signed-off-by: Baolin Wang<baolin.wang@linaro.org> >> --- >> Changes since v1: >> - Fix one typo. >> --- > Do you have any comments for this patch set? Thanks. Thanks for your patience! These patches look good!, Normally I tend to send nvmem patches to Greg K.H just before rc5! I will queue them by end of this week! Thanks Srini > ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] nvmem: Add Spreadtrum SC27XX efuse support 2018-07-09 9:41 ` Srinivas Kandagatla @ 2018-07-09 10:30 ` Baolin Wang 0 siblings, 0 replies; 5+ messages in thread From: Baolin Wang @ 2018-07-09 10:30 UTC (permalink / raw) To: Srinivas Kandagatla Cc: Rob Herring, Mark Rutland, Mark Brown, freeman.liu, DTML, LKML On 9 July 2018 at 17:41, Srinivas Kandagatla <srinivas.kandagatla@linaro.org> wrote: > > > On 09/07/18 10:26, Baolin Wang wrote: >> >> Hi Srinivas, >> >> On 25 June 2018 at 14:31, Baolin Wang<baolin.wang@linaro.org> wrote: >>> >>> From: Freeman Liu<freeman.liu@spreadtrum.com> >>> >>> This patch add the efuse driver which is embeded in Spreadtrum SC27XX >>> series PMICs. The sc27xx efuse contains 32 blocks and each block's >>> data width is 16 bits. >>> >>> Signed-off-by: Freeman Liu<freeman.liu@spreadtrum.com> >>> Signed-off-by: Baolin Wang<baolin.wang@linaro.org> >>> --- >>> Changes since v1: >>> - Fix one typo. >>> --- >> >> Do you have any comments for this patch set? Thanks. > > Thanks for your patience! > > These patches look good!, Normally I tend to send nvmem patches to Greg K.H > just before rc5! I will queue them by end of this week! Thanks. -- Baolin Wang Best Regards ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-07-09 10:30 UTC | newest] Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-06-25 6:31 [PATCH v2 1/2] dt-bindings: nvmem: Add Spreadtrum SC27XX efuse controller documentation Baolin Wang 2018-06-25 6:31 ` [PATCH v2 2/2] nvmem: Add Spreadtrum SC27XX efuse support Baolin Wang 2018-07-09 9:26 ` Baolin Wang 2018-07-09 9:41 ` Srinivas Kandagatla 2018-07-09 10:30 ` Baolin Wang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).