2019-05-15 07:54:58

by Peng Fan

[permalink] [raw]
Subject: [PATCH V3 1/4] dt-bindings: fsl: scu: add ocotp binding

NXP i.MX8QXP is an ARMv8 SoC with a Cortex-M4 core inside as
system controller(SCU), the ocotp controller is being controlled
by the SCU, so Linux need use RPC to SCU for ocotp handling. This
patch adds binding doc for i.MX8 SCU OCOTP driver.

Cc: Mark Rutland <[email protected]>
Cc: Shawn Guo <[email protected]>
Cc: Ulf Hansson <[email protected]>
Cc: Stephen Boyd <[email protected]>
Cc: Anson Huang <[email protected]>
Cc: [email protected]
Reviewed-by: Rob Herring <[email protected]>
Reviewed-by: Dong Aisheng <[email protected]>
Signed-off-by: Peng Fan <[email protected]>
---

V3:
Add R-b tag
V2:
Move OCOTP to end, add example, add "scu"

.../devicetree/bindings/arm/freescale/fsl,scu.txt | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
index 5d7dbabbb784..f378922906f6 100644
--- a/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
+++ b/Documentation/devicetree/bindings/arm/freescale/fsl,scu.txt
@@ -133,6 +133,18 @@ RTC bindings based on SCU Message Protocol
Required properties:
- compatible: should be "fsl,imx8qxp-sc-rtc";

+OCOTP bindings based on SCU Message Protocol
+------------------------------------------------------------
+Required properties:
+- compatible: Should be "fsl,imx8qxp-scu-ocotp"
+- #address-cells: Must be 1. Contains byte index
+- #size-cells: Must be 1. Contains byte length
+
+Optional Child nodes:
+
+- Data cells of ocotp:
+ Detailed bindings are described in bindings/nvmem/nvmem.txt
+
Example (imx8qxp):
-------------
aliases {
@@ -177,6 +189,16 @@ firmware {
...
};

+ ocotp: imx8qx-ocotp {
+ compatible = "fsl,imx8qxp-scu-ocotp";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ fec_mac0: mac@2c4 {
+ reg = <0x2c4 8>;
+ };
+ };
+
pd: imx8qx-pd {
compatible = "fsl,imx8qxp-scu-pd", "fsl,scu-pd";
#power-domain-cells = <1>;
--
2.16.4


2019-05-15 07:56:12

by Peng Fan

[permalink] [raw]
Subject: [PATCH V3 4/4] arm64: dts: imx: add i.MX8QXP ocotp support

Add i.MX8QXP ocotp node

Cc: Rob Herring <[email protected]>
Cc: Mark Rutland <[email protected]>
Cc: Shawn Guo <[email protected]>
Cc: Sascha Hauer <[email protected]>
Cc: Pengutronix Kernel Team <[email protected]>
Cc: Fabio Estevam <[email protected]>
Cc: NXP Linux Team <[email protected]>
Cc: Anson Huang <[email protected]>
Cc: Daniel Baluta <[email protected]>
Cc: [email protected]
Cc: [email protected]
Reviewed-by: Dong Aisheng <[email protected]>
Signed-off-by: Peng Fan <[email protected]>
---

V3:
Add R-b tag
V2:
move address/size-cells below compatible, add "scu"

arch/arm64/boot/dts/freescale/imx8qxp.dtsi | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
index 0683ee2a48ae..725d341ee160 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
@@ -141,6 +141,12 @@
compatible = "fsl,imx8qxp-iomuxc";
};

+ ocotp: imx8qx-ocotp {
+ compatible = "fsl,imx8qxp-scu-ocotp";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
pd: imx8qx-pd {
compatible = "fsl,imx8qxp-scu-pd";
#power-domain-cells = <1>;
--
2.16.4

2019-05-15 07:56:41

by Peng Fan

[permalink] [raw]
Subject: [PATCH V3 3/4] defconfig: arm64: enable i.MX8 SCU octop driver

Build in CONFIG_NVMEM_IMX_OCOTP_SCU.

Cc: Catalin Marinas <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: Shawn Guo <[email protected]>
Cc: Andy Gross <[email protected]>
Cc: Maxime Ripard <[email protected]>
Cc: Olof Johansson <[email protected]>
Cc: Jagan Teki <[email protected]>
Cc: Bjorn Andersson <[email protected]>
Cc: Leonard Crestez <[email protected]>
Cc: Marc Gonzalez <[email protected]>
Cc: Enric Balletbo i Serra <[email protected]>
Cc: [email protected]
Reviewed-by: Dong Aisheng <[email protected]>
Signed-off-by: Peng Fan <[email protected]>
---

V3:
No change
V2:
rename patch title, add review tag

arch/arm64/configs/defconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 979a95c915b6..32b85102b857 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -748,6 +748,7 @@ CONFIG_HISI_PMU=y
CONFIG_QCOM_L2_PMU=y
CONFIG_QCOM_L3_PMU=y
CONFIG_NVMEM_IMX_OCOTP=y
+CONFIG_NVMEM_IMX_OCOTP_SCU=y
CONFIG_QCOM_QFPROM=y
CONFIG_ROCKCHIP_EFUSE=y
CONFIG_UNIPHIER_EFUSE=y
--
2.16.4

2019-05-15 07:58:40

by Peng Fan

[permalink] [raw]
Subject: [PATCH V3 2/4] nvmem: imx: add i.MX8 nvmem driver

This patch adds i.MX8 nvmem ocotp driver to access fuse via
RPC to i.MX8 system controller.

Cc: Srinivas Kandagatla <[email protected]>
Cc: Shawn Guo <[email protected]>
Cc: Sascha Hauer <[email protected]>
Cc: Pengutronix Kernel Team <[email protected]>
Cc: Fabio Estevam <[email protected]>
Cc: NXP Linux Team <[email protected]>
Cc: [email protected]
Signed-off-by: Peng Fan <[email protected]>
---

V3:
Use imx_sc_msg_misc_fuse_read for req/resp
Drop uneccessary check
Drop the unnecessary type conversion
Minor fixes according to v2 comments

V2:
Add "scu" or "SCU", Add imx_sc_misc_otp_fuse_read, minor fixes

drivers/nvmem/Kconfig | 7 ++
drivers/nvmem/Makefile | 2 +
drivers/nvmem/imx-ocotp-scu.c | 161 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 170 insertions(+)
create mode 100644 drivers/nvmem/imx-ocotp-scu.c

diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index 530d570724c9..79afe44195a1 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -36,6 +36,13 @@ config NVMEM_IMX_OCOTP
This driver can also be built as a module. If so, the module
will be called nvmem-imx-ocotp.

+config NVMEM_IMX_OCOTP_SCU
+ tristate "i.MX8 SCU On-Chip OTP Controller support"
+ depends on IMX_SCU
+ help
+ This is a driver for the SCU On-Chip OTP Controller (OCOTP)
+ available on i.MX8 SoCs.
+
config NVMEM_LPC18XX_EEPROM
tristate "NXP LPC18XX EEPROM Memory Support"
depends on ARCH_LPC18XX || COMPILE_TEST
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index 2ece8ffffdda..30d653d34e57 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -13,6 +13,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
nvmem-imx-iim-y := imx-iim.o
obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
nvmem-imx-ocotp-y := imx-ocotp.o
+obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o
+nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) += nvmem_lpc18xx_eeprom.o
nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem_lpc18xx_otp.o
diff --git a/drivers/nvmem/imx-ocotp-scu.c b/drivers/nvmem/imx-ocotp-scu.c
new file mode 100644
index 000000000000..d9dc482ecb2f
--- /dev/null
+++ b/drivers/nvmem/imx-ocotp-scu.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * i.MX8 OCOTP fusebox driver
+ *
+ * Copyright 2019 NXP
+ *
+ * Peng Fan <[email protected]>
+ */
+
+#include <linux/firmware/imx/sci.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+enum ocotp_devtype {
+ IMX8QXP,
+};
+
+struct ocotp_devtype_data {
+ int devtype;
+ int nregs;
+};
+
+struct ocotp_priv {
+ struct device *dev;
+ const struct ocotp_devtype_data *data;
+ struct imx_sc_ipc *nvmem_ipc;
+};
+
+struct imx_sc_msg_misc_fuse_read {
+ struct imx_sc_rpc_msg hdr;
+ u32 word;
+} __packed;
+
+static struct ocotp_devtype_data imx8qxp_data = {
+ .devtype = IMX8QXP,
+ .nregs = 800,
+};
+
+static int imx_sc_misc_otp_fuse_read(struct imx_sc_ipc *ipc, u32 word,
+ u32 *val)
+{
+ struct imx_sc_msg_misc_fuse_read msg;
+ struct imx_sc_rpc_msg *hdr = &msg.hdr;
+ int ret;
+
+ hdr->ver = IMX_SC_RPC_VERSION;
+ hdr->svc = IMX_SC_RPC_SVC_MISC;
+ hdr->func = IMX_SC_MISC_FUNC_OTP_FUSE_READ;
+ hdr->size = 2;
+
+ msg.word = word;
+
+ ret = imx_scu_call_rpc(ipc, &msg, true);
+ if (ret)
+ return ret;
+
+ *val = msg.word;
+
+ return 0;
+}
+
+static int imx_scu_ocotp_read(void *context, unsigned int offset,
+ void *val, size_t bytes)
+{
+ struct ocotp_priv *priv = context;
+ u32 count, index, num_bytes;
+ u32 *buf;
+ void *p;
+ int i, ret;
+
+ index = offset >> 2;
+ num_bytes = round_up((offset % 4) + bytes, 4);
+ count = num_bytes >> 2;
+
+ if (count > (priv->data->nregs - index))
+ count = priv->data->nregs - index;
+
+ p = kzalloc(num_bytes, GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ buf = p;
+
+ for (i = index; i < (index + count); i++) {
+ if (priv->data->devtype == IMX8QXP) {
+ if ((i > 271) && (i < 544)) {
+ *buf++ = 0;
+ continue;
+ }
+ }
+
+ ret = imx_sc_misc_otp_fuse_read(priv->nvmem_ipc, i, buf);
+ if (ret) {
+ kfree(p);
+ return ret;
+ }
+ buf++;
+ }
+
+ memcpy(val, (u8 *)p + offset % 4, bytes);
+
+ kfree(p);
+
+ return 0;
+}
+
+static struct nvmem_config imx_scu_ocotp_nvmem_config = {
+ .name = "imx-scu-ocotp",
+ .read_only = true,
+ .word_size = 4,
+ .stride = 1,
+ .owner = THIS_MODULE,
+ .reg_read = imx_scu_ocotp_read,
+};
+
+static const struct of_device_id imx_scu_ocotp_dt_ids[] = {
+ { .compatible = "fsl,imx8qxp-scu-ocotp", (void *)&imx8qxp_data },
+ { },
+};
+MODULE_DEVICE_TABLE(of, imx_scu_ocotp_dt_ids);
+
+static int imx_scu_ocotp_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ocotp_priv *priv;
+ struct nvmem_device *nvmem;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ ret = imx_scu_get_handle(&priv->nvmem_ipc);
+ if (ret)
+ return ret;
+
+ priv->data = of_device_get_match_data(dev);
+ priv->dev = dev;
+ imx_scu_ocotp_nvmem_config.size = 4 * priv->data->nregs;
+ imx_scu_ocotp_nvmem_config.dev = dev;
+ imx_scu_ocotp_nvmem_config.priv = priv;
+ nvmem = devm_nvmem_register(dev, &imx_scu_ocotp_nvmem_config);
+
+ return PTR_ERR_OR_ZERO(nvmem);
+}
+
+static struct platform_driver imx_scu_ocotp_driver = {
+ .probe = imx_scu_ocotp_probe,
+ .driver = {
+ .name = "imx_scu_ocotp",
+ .of_match_table = imx_scu_ocotp_dt_ids,
+ },
+};
+module_platform_driver(imx_scu_ocotp_driver);
+
+MODULE_AUTHOR("Peng Fan <[email protected]>");
+MODULE_DESCRIPTION("i.MX8 SCU OCOTP fuse box driver");
+MODULE_LICENSE("GPL v2");
--
2.16.4

2019-05-16 11:22:47

by Aisheng Dong

[permalink] [raw]
Subject: RE: [PATCH V3 2/4] nvmem: imx: add i.MX8 nvmem driver

> From: Peng Fan
> Sent: Wednesday, May 15, 2019 3:53 PM
>
> This patch adds i.MX8 nvmem ocotp driver to access fuse via RPC to i.MX8
> system controller.
>
> Cc: Srinivas Kandagatla <[email protected]>
> Cc: Shawn Guo <[email protected]>
> Cc: Sascha Hauer <[email protected]>
> Cc: Pengutronix Kernel Team <[email protected]>
> Cc: Fabio Estevam <[email protected]>
> Cc: NXP Linux Team <[email protected]>
> Cc: [email protected]
> Signed-off-by: Peng Fan <[email protected]>

Reviewed-by: Dong Aisheng <[email protected]>

Regards
Dong Aisheng

2019-05-21 08:35:35

by Srinivas Kandagatla

[permalink] [raw]
Subject: Re: [PATCH V3 2/4] nvmem: imx: add i.MX8 nvmem driver



On 15/05/2019 08:53, Peng Fan wrote:
> This patch adds i.MX8 nvmem ocotp driver to access fuse via
> RPC to i.MX8 system controller.
>
> Cc: Srinivas Kandagatla <[email protected]>
> Cc: Shawn Guo <[email protected]>
> Cc: Sascha Hauer <[email protected]>
> Cc: Pengutronix Kernel Team <[email protected]>
> Cc: Fabio Estevam <[email protected]>
> Cc: NXP Linux Team <[email protected]>
> Cc: [email protected]
> Signed-off-by: Peng Fan <[email protected]>

I don't see any dt-binding patches in my list. May be you forgot to add
me in CC.

Can You please make sure that you add me to the cc of the dt-bindings
patch so that I can take the driver and dt-bindings together via nvmem tree.
I will not be able to apply any driver patches without dt-bindings.

Thanks,
srini
> ---
>
> V3:
> Use imx_sc_msg_misc_fuse_read for req/resp
> Drop uneccessary check
> Drop the unnecessary type conversion
> Minor fixes according to v2 comments
>
> V2:
> Add "scu" or "SCU", Add imx_sc_misc_otp_fuse_read, minor fixes
>
> drivers/nvmem/Kconfig | 7 ++
> drivers/nvmem/Makefile | 2 +
> drivers/nvmem/imx-ocotp-scu.c | 161 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 170 insertions(+)
> create mode 100644 drivers/nvmem/imx-ocotp-scu.c
>
> diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
> index 530d570724c9..79afe44195a1 100644
> --- a/drivers/nvmem/Kconfig
> +++ b/drivers/nvmem/Kconfig
> @@ -36,6 +36,13 @@ config NVMEM_IMX_OCOTP
> This driver can also be built as a module. If so, the module
> will be called nvmem-imx-ocotp.
>
> +config NVMEM_IMX_OCOTP_SCU
> + tristate "i.MX8 SCU On-Chip OTP Controller support"
> + depends on IMX_SCU
> + help
> + This is a driver for the SCU On-Chip OTP Controller (OCOTP)
> + available on i.MX8 SoCs.
> +
> config NVMEM_LPC18XX_EEPROM
> tristate "NXP LPC18XX EEPROM Memory Support"
> depends on ARCH_LPC18XX || COMPILE_TEST
> diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
> index 2ece8ffffdda..30d653d34e57 100644
> --- a/drivers/nvmem/Makefile
> +++ b/drivers/nvmem/Makefile
> @@ -13,6 +13,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM) += nvmem-imx-iim.o
> nvmem-imx-iim-y := imx-iim.o
> obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
> nvmem-imx-ocotp-y := imx-ocotp.o
> +obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o
> +nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
> obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) += nvmem_lpc18xx_eeprom.o
> nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
> obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem_lpc18xx_otp.o
> diff --git a/drivers/nvmem/imx-ocotp-scu.c b/drivers/nvmem/imx-ocotp-scu.c
> new file mode 100644
> index 000000000000..d9dc482ecb2f
> --- /dev/null
> +++ b/drivers/nvmem/imx-ocotp-scu.c
> @@ -0,0 +1,161 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * i.MX8 OCOTP fusebox driver
> + *
> + * Copyright 2019 NXP
> + *
> + * Peng Fan <[email protected]>
> + */
> +
> +#include <linux/firmware/imx/sci.h>
> +#include <linux/module.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +enum ocotp_devtype {
> + IMX8QXP,
> +};
> +
> +struct ocotp_devtype_data {
> + int devtype;
> + int nregs;
> +};
> +
> +struct ocotp_priv {
> + struct device *dev;
> + const struct ocotp_devtype_data *data;
> + struct imx_sc_ipc *nvmem_ipc;
> +};
> +
> +struct imx_sc_msg_misc_fuse_read {
> + struct imx_sc_rpc_msg hdr;
> + u32 word;
> +} __packed;
> +
> +static struct ocotp_devtype_data imx8qxp_data = {
> + .devtype = IMX8QXP,
> + .nregs = 800,
> +};
> +
> +static int imx_sc_misc_otp_fuse_read(struct imx_sc_ipc *ipc, u32 word,
> + u32 *val)
> +{
> + struct imx_sc_msg_misc_fuse_read msg;
> + struct imx_sc_rpc_msg *hdr = &msg.hdr;
> + int ret;
> +
> + hdr->ver = IMX_SC_RPC_VERSION;
> + hdr->svc = IMX_SC_RPC_SVC_MISC;
> + hdr->func = IMX_SC_MISC_FUNC_OTP_FUSE_READ;
> + hdr->size = 2;
> +
> + msg.word = word;
> +
> + ret = imx_scu_call_rpc(ipc, &msg, true);
> + if (ret)
> + return ret;
> +
> + *val = msg.word;
> +
> + return 0;
> +}
> +
> +static int imx_scu_ocotp_read(void *context, unsigned int offset,
> + void *val, size_t bytes)
> +{
> + struct ocotp_priv *priv = context;
> + u32 count, index, num_bytes;
> + u32 *buf;
> + void *p;
> + int i, ret;
> +
> + index = offset >> 2;
> + num_bytes = round_up((offset % 4) + bytes, 4);
> + count = num_bytes >> 2;
> +
> + if (count > (priv->data->nregs - index))
> + count = priv->data->nregs - index;
> +
> + p = kzalloc(num_bytes, GFP_KERNEL);
> + if (!p)
> + return -ENOMEM;
> +
> + buf = p;
> +
> + for (i = index; i < (index + count); i++) {
> + if (priv->data->devtype == IMX8QXP) {
> + if ((i > 271) && (i < 544)) {
> + *buf++ = 0;
> + continue;
> + }
> + }
> +
> + ret = imx_sc_misc_otp_fuse_read(priv->nvmem_ipc, i, buf);
> + if (ret) {
> + kfree(p);
> + return ret;
> + }
> + buf++;
> + }
> +
> + memcpy(val, (u8 *)p + offset % 4, bytes);
> +
> + kfree(p);
> +
> + return 0;
> +}
> +
> +static struct nvmem_config imx_scu_ocotp_nvmem_config = {
> + .name = "imx-scu-ocotp",
> + .read_only = true,
> + .word_size = 4,
> + .stride = 1,
> + .owner = THIS_MODULE,
> + .reg_read = imx_scu_ocotp_read,
> +};
> +
> +static const struct of_device_id imx_scu_ocotp_dt_ids[] = {
> + { .compatible = "fsl,imx8qxp-scu-ocotp", (void *)&imx8qxp_data },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, imx_scu_ocotp_dt_ids);
> +
> +static int imx_scu_ocotp_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct ocotp_priv *priv;
> + struct nvmem_device *nvmem;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + ret = imx_scu_get_handle(&priv->nvmem_ipc);
> + if (ret)
> + return ret;
> +
> + priv->data = of_device_get_match_data(dev);
> + priv->dev = dev;
> + imx_scu_ocotp_nvmem_config.size = 4 * priv->data->nregs;
> + imx_scu_ocotp_nvmem_config.dev = dev;
> + imx_scu_ocotp_nvmem_config.priv = priv;
> + nvmem = devm_nvmem_register(dev, &imx_scu_ocotp_nvmem_config);
> +
> + return PTR_ERR_OR_ZERO(nvmem);
> +}
> +
> +static struct platform_driver imx_scu_ocotp_driver = {
> + .probe = imx_scu_ocotp_probe,
> + .driver = {
> + .name = "imx_scu_ocotp",
> + .of_match_table = imx_scu_ocotp_dt_ids,
> + },
> +};
> +module_platform_driver(imx_scu_ocotp_driver);
> +
> +MODULE_AUTHOR("Peng Fan <[email protected]>");
> +MODULE_DESCRIPTION("i.MX8 SCU OCOTP fuse box driver");
> +MODULE_LICENSE("GPL v2");
>

2019-05-22 01:50:20

by Peng Fan

[permalink] [raw]
Subject: RE: [PATCH V3 2/4] nvmem: imx: add i.MX8 nvmem driver

Hi Srinivas,

> Subject: Re: [PATCH V3 2/4] nvmem: imx: add i.MX8 nvmem driver
>
>
>
> On 15/05/2019 08:53, Peng Fan wrote:
> > This patch adds i.MX8 nvmem ocotp driver to access fuse via RPC to
> > i.MX8 system controller.
> >
> > Cc: Srinivas Kandagatla <[email protected]>
> > Cc: Shawn Guo <[email protected]>
> > Cc: Sascha Hauer <[email protected]>
> > Cc: Pengutronix Kernel Team <[email protected]>
> > Cc: Fabio Estevam <[email protected]>
> > Cc: NXP Linux Team <[email protected]>
> > Cc: [email protected]
> > Signed-off-by: Peng Fan <[email protected]>
>
> I don't see any dt-binding patches in my list. May be you forgot to add me in
> CC.
>
> Can You please make sure that you add me to the cc of the dt-bindings patch
> so that I can take the driver and dt-bindings together via nvmem tree.
> I will not be able to apply any driver patches without dt-bindings.

Sorry. Forgot to add you in that patch. Resent the whole v3 patchset with
you in To list just now.

Thanks,
Peng.

>
> Thanks,
> srini
> > ---
> >
> > V3:
> > Use imx_sc_msg_misc_fuse_read for req/resp
> > Drop uneccessary check
> > Drop the unnecessary type conversion
> > Minor fixes according to v2 comments
> >
> > V2:
> > Add "scu" or "SCU", Add imx_sc_misc_otp_fuse_read, minor fixes
> >
> > drivers/nvmem/Kconfig | 7 ++
> > drivers/nvmem/Makefile | 2 +
> > drivers/nvmem/imx-ocotp-scu.c | 161
> ++++++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 170 insertions(+)
> > create mode 100644 drivers/nvmem/imx-ocotp-scu.c
> >
> > diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index
> > 530d570724c9..79afe44195a1 100644
> > --- a/drivers/nvmem/Kconfig
> > +++ b/drivers/nvmem/Kconfig
> > @@ -36,6 +36,13 @@ config NVMEM_IMX_OCOTP
> > This driver can also be built as a module. If so, the module
> > will be called nvmem-imx-ocotp.
> >
> > +config NVMEM_IMX_OCOTP_SCU
> > + tristate "i.MX8 SCU On-Chip OTP Controller support"
> > + depends on IMX_SCU
> > + help
> > + This is a driver for the SCU On-Chip OTP Controller (OCOTP)
> > + available on i.MX8 SoCs.
> > +
> > config NVMEM_LPC18XX_EEPROM
> > tristate "NXP LPC18XX EEPROM Memory Support"
> > depends on ARCH_LPC18XX || COMPILE_TEST diff --git
> > a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile index
> > 2ece8ffffdda..30d653d34e57 100644
> > --- a/drivers/nvmem/Makefile
> > +++ b/drivers/nvmem/Makefile
> > @@ -13,6 +13,8 @@ obj-$(CONFIG_NVMEM_IMX_IIM) +=
> nvmem-imx-iim.o
> > nvmem-imx-iim-y := imx-iim.o
> > obj-$(CONFIG_NVMEM_IMX_OCOTP) += nvmem-imx-ocotp.o
> > nvmem-imx-ocotp-y := imx-ocotp.o
> > +obj-$(CONFIG_NVMEM_IMX_OCOTP_SCU) += nvmem-imx-ocotp-scu.o
> > +nvmem-imx-ocotp-scu-y := imx-ocotp-scu.o
> > obj-$(CONFIG_NVMEM_LPC18XX_EEPROM) +=
> nvmem_lpc18xx_eeprom.o
> > nvmem_lpc18xx_eeprom-y := lpc18xx_eeprom.o
> > obj-$(CONFIG_NVMEM_LPC18XX_OTP) += nvmem_lpc18xx_otp.o
> > diff --git a/drivers/nvmem/imx-ocotp-scu.c
> > b/drivers/nvmem/imx-ocotp-scu.c new file mode 100644 index
> > 000000000000..d9dc482ecb2f
> > --- /dev/null
> > +++ b/drivers/nvmem/imx-ocotp-scu.c
> > @@ -0,0 +1,161 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * i.MX8 OCOTP fusebox driver
> > + *
> > + * Copyright 2019 NXP
> > + *
> > + * Peng Fan <[email protected]>
> > + */
> > +
> > +#include <linux/firmware/imx/sci.h>
> > +#include <linux/module.h>
> > +#include <linux/nvmem-provider.h>
> > +#include <linux/of_device.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/slab.h>
> > +
> > +enum ocotp_devtype {
> > + IMX8QXP,
> > +};
> > +
> > +struct ocotp_devtype_data {
> > + int devtype;
> > + int nregs;
> > +};
> > +
> > +struct ocotp_priv {
> > + struct device *dev;
> > + const struct ocotp_devtype_data *data;
> > + struct imx_sc_ipc *nvmem_ipc;
> > +};
> > +
> > +struct imx_sc_msg_misc_fuse_read {
> > + struct imx_sc_rpc_msg hdr;
> > + u32 word;
> > +} __packed;
> > +
> > +static struct ocotp_devtype_data imx8qxp_data = {
> > + .devtype = IMX8QXP,
> > + .nregs = 800,
> > +};
> > +
> > +static int imx_sc_misc_otp_fuse_read(struct imx_sc_ipc *ipc, u32 word,
> > + u32 *val)
> > +{
> > + struct imx_sc_msg_misc_fuse_read msg;
> > + struct imx_sc_rpc_msg *hdr = &msg.hdr;
> > + int ret;
> > +
> > + hdr->ver = IMX_SC_RPC_VERSION;
> > + hdr->svc = IMX_SC_RPC_SVC_MISC;
> > + hdr->func = IMX_SC_MISC_FUNC_OTP_FUSE_READ;
> > + hdr->size = 2;
> > +
> > + msg.word = word;
> > +
> > + ret = imx_scu_call_rpc(ipc, &msg, true);
> > + if (ret)
> > + return ret;
> > +
> > + *val = msg.word;
> > +
> > + return 0;
> > +}
> > +
> > +static int imx_scu_ocotp_read(void *context, unsigned int offset,
> > + void *val, size_t bytes)
> > +{
> > + struct ocotp_priv *priv = context;
> > + u32 count, index, num_bytes;
> > + u32 *buf;
> > + void *p;
> > + int i, ret;
> > +
> > + index = offset >> 2;
> > + num_bytes = round_up((offset % 4) + bytes, 4);
> > + count = num_bytes >> 2;
> > +
> > + if (count > (priv->data->nregs - index))
> > + count = priv->data->nregs - index;
> > +
> > + p = kzalloc(num_bytes, GFP_KERNEL);
> > + if (!p)
> > + return -ENOMEM;
> > +
> > + buf = p;
> > +
> > + for (i = index; i < (index + count); i++) {
> > + if (priv->data->devtype == IMX8QXP) {
> > + if ((i > 271) && (i < 544)) {
> > + *buf++ = 0;
> > + continue;
> > + }
> > + }
> > +
> > + ret = imx_sc_misc_otp_fuse_read(priv->nvmem_ipc, i, buf);
> > + if (ret) {
> > + kfree(p);
> > + return ret;
> > + }
> > + buf++;
> > + }
> > +
> > + memcpy(val, (u8 *)p + offset % 4, bytes);
> > +
> > + kfree(p);
> > +
> > + return 0;
> > +}
> > +
> > +static struct nvmem_config imx_scu_ocotp_nvmem_config = {
> > + .name = "imx-scu-ocotp",
> > + .read_only = true,
> > + .word_size = 4,
> > + .stride = 1,
> > + .owner = THIS_MODULE,
> > + .reg_read = imx_scu_ocotp_read,
> > +};
> > +
> > +static const struct of_device_id imx_scu_ocotp_dt_ids[] = {
> > + { .compatible = "fsl,imx8qxp-scu-ocotp", (void *)&imx8qxp_data },
> > + { },
> > +};
> > +MODULE_DEVICE_TABLE(of, imx_scu_ocotp_dt_ids);
> > +
> > +static int imx_scu_ocotp_probe(struct platform_device *pdev) {
> > + struct device *dev = &pdev->dev;
> > + struct ocotp_priv *priv;
> > + struct nvmem_device *nvmem;
> > + int ret;
> > +
> > + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > + if (!priv)
> > + return -ENOMEM;
> > +
> > + ret = imx_scu_get_handle(&priv->nvmem_ipc);
> > + if (ret)
> > + return ret;
> > +
> > + priv->data = of_device_get_match_data(dev);
> > + priv->dev = dev;
> > + imx_scu_ocotp_nvmem_config.size = 4 * priv->data->nregs;
> > + imx_scu_ocotp_nvmem_config.dev = dev;
> > + imx_scu_ocotp_nvmem_config.priv = priv;
> > + nvmem = devm_nvmem_register(dev, &imx_scu_ocotp_nvmem_config);
> > +
> > + return PTR_ERR_OR_ZERO(nvmem);
> > +}
> > +
> > +static struct platform_driver imx_scu_ocotp_driver = {
> > + .probe = imx_scu_ocotp_probe,
> > + .driver = {
> > + .name = "imx_scu_ocotp",
> > + .of_match_table = imx_scu_ocotp_dt_ids,
> > + },
> > +};
> > +module_platform_driver(imx_scu_ocotp_driver);
> > +
> > +MODULE_AUTHOR("Peng Fan <[email protected]>");
> > +MODULE_DESCRIPTION("i.MX8 SCU OCOTP fuse box driver");
> > +MODULE_LICENSE("GPL v2");
> >