All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] arm: layerscape: Add sfp driver
@ 2022-04-19 20:58 Sean Anderson
  2022-04-19 20:58 ` [PATCH 2/2] arch: layerscape: Add SFP binding Sean Anderson
  2022-04-19 21:00 ` [PATCH 1/2] arm: layerscape: Add sfp driver Sean Anderson
  0 siblings, 2 replies; 7+ messages in thread
From: Sean Anderson @ 2022-04-19 20:58 UTC (permalink / raw)
  To: u-boot, Tom Rini
  Cc: Mingkai Hu, Alison Wang, Manish Tomar, Rajesh Bhagat, Mingkai Hu,
	Pramod Kumar, Vladimir Oltean, Sean Anderson

This adds a driver for the Security Fuse Processor (SFP) present on
LS1012A, LS1021A, LS1043A, and LS1046A processors. It holds the
Super-Root Key (SRK), One-Time-Programmable Master Key (OTPMK), and
other "security" related fuses. Similar devices (sharing the same name)
are present on other processors, but for the moment this just supports
the LS2 variants.

The mirror registers are loaded during power-on reset. All mirror
registers must be programmed or read at once. Because of this, `fuse
prog` will program all fuses, even though only one might be specified.
To prevent accidentally burning through all your fuse programming cycles
with something like `fuse prog 0 0 A B C D`, we limit ourselves to one
programming cycle per reset. Fuses are numbered based on their address.
The fuse at 0x1e80200 is 0, the fuse at 0x1e80204 is 1, etc.

The TA_PROG_SFP supply must be enabled when programming fuses, but must
be disabled when reading them. Typically this supply is enabled by
inserting a jumper or by setting a register in the board's FPGA. I've
also added support for using a regulator. This could be helpful for
automatically issuing the FPGA write, or for toggling a GPIO controlling
the supply.

I suggest using the following procedure for programming:

1. Override the fuses you wish to program
   => fuse override 0 2 A B C D
2. Inspect the values and ensure that they are what you expect
   => fuse sense 0 2 4
3. Enable TA_PROG_SFP
4. Issue a program command using OSPR0 as a dummy. Since it contains the
   write-protect bit you will usually want to write it last anyway.
   => fuse prog 0 0 0
5. Disable TA_PROG_SFP
6. Read back the fuses and ensure they are correct
   => fuse read 0 2 4

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 MAINTAINERS            |   5 +
 drivers/misc/Kconfig   |  14 ++
 drivers/misc/Makefile  |   1 +
 drivers/misc/ls2_sfp.c | 350 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 370 insertions(+)
 create mode 100644 drivers/misc/ls2_sfp.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 7a9e3156f4..6a302b35e2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -271,6 +271,11 @@ F:	drivers/spi/spi-qup.c
 F:	drivers/net/mdio-ipq4019.c
 F:	drivers/rng/msm_rng.c
 
+ARM LAYERSCAPE SFP
+M:	Sean Anderson <sean.anderson@seco.com>
+S:	Maintained
+F:	drivers/misc/ls2_sfp.c
+
 ARM MARVELL KIRKWOOD ARMADA-XP ARMADA-38X ARMADA-37XX ARMADA-7K/8K
 M:	Stefan Roese <sr@denx.de>
 S:	Maintained
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 7029bb7b5c..2a86c42017 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -224,6 +224,20 @@ config JZ4780_EFUSE
 	help
 	  This selects support for the eFUSE on Ingenic JZ4780 SoCs.
 
+config LS2_SFP
+	bool "Layerscape Security Fuse Processor"
+	depends on FSL_LSCH2 || ARCH_LS1021A
+	depends on MISC
+	imply DM_REGULATOR
+	help
+	  This adds support for the Security Fuse Processor found on Layerscape
+	  SoCs. It contains various fuses related to secure boot, including the
+	  Super Root Key hash, One-Time-Programmable Master Key, Debug
+	  Challenge/Response values, and others. Fuses are numbered according
+	  to their four-byte offset from the start of the bank.
+
+	  If you don't need to read/program fuses, say 'n'.
+
 config MXC_OCOTP
 	bool "Enable MXC OCOTP Driver"
 	depends on ARCH_IMX8M || ARCH_MX6 || ARCH_MX7 || ARCH_MX7ULP || ARCH_VF610
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b7a8ef68ab..4926671833 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_IMX8ULP) += imx8ulp/
 obj-$(CONFIG_LED_STATUS) += status_led.o
 obj-$(CONFIG_LED_STATUS_GPIO) += gpio_led.o
 obj-$(CONFIG_MPC83XX_SERDES) += mpc83xx_serdes.o
+obj-$(CONFIG_$(SPL_TPL_)LS2_SFP) += ls2_sfp.o
 obj-$(CONFIG_$(SPL_)MXC_OCOTP) += mxc_ocotp.o
 obj-$(CONFIG_MXS_OCOTP) += mxs_ocotp.o
 obj-$(CONFIG_NUVOTON_NCT6102D) += nuvoton_nct6102d.o
diff --git a/drivers/misc/ls2_sfp.c b/drivers/misc/ls2_sfp.c
new file mode 100644
index 0000000000..df54b0c89e
--- /dev/null
+++ b/drivers/misc/ls2_sfp.c
@@ -0,0 +1,350 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ *
+ * This driver supports the Security Fuse Processor device found on some
+ * Layerscape processors. At the moment, we only support a few processors.
+ * This driver was written with reference to the Layerscape SDK User
+ * Guide [1] and the ATF SFP driver [2].
+ *
+ * [1] https://docs.nxp.com/bundle/GUID-487B2E69-BB19-42CB-AC38-7EF18C0FE3AE/page/GUID-27FC40AD-3321-4A82-B29E-7BB49EE94F23.html
+ * [2] https://source.codeaurora.org/external/qoriq/qoriq-components/atf/tree/drivers/nxp/sfp?h=github.com/master
+ */
+
+#define LOG_CATEGORY UCLASS_MISC
+#include <common.h>
+#include <clk.h>
+#include <fuse.h>
+#include <misc.h>
+#include <asm/io.h>
+#include <dm/device_compat.h>
+#include <dm/read.h>
+#include <linux/bitfield.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SFP_INGR	0x20
+#define SFP_SVHESR	0x24
+#define SFP_SFPCR	0x28
+
+#define SFP_START	0x200
+#define SFP_END		0x284
+#define SFP_SIZE	(SFP_END - SFP_START + 4)
+
+#define SFP_INGR_ERR	BIT(8)
+#define SFP_INGR_INST	GENMASK(7, 0)
+
+#define SFP_INGR_READFB	0x01
+#define SFP_INGR_PROGFB	0x02
+
+#define SFP_SFPCR_PPW	GENMASK(15, 0)
+
+enum ls2_sfp_ioctl {
+	LS2_SFP_IOCTL_READ,
+	LS2_SFP_IOCTL_PROG,
+};
+
+/**
+ * struct ls2_sfp_priv - private data for LS2 SFP
+ * @base: Base address of SFP
+ * @supply: The (optional) supply for TA_PROG_SFP
+ * @programmed: Whether we've already programmed the fuses since the last
+ *              reset. The SFP has a *very* limited amount of programming
+ *              cycles (two to six, depending on the model), so we try and
+ *              prevent accidentally performing additional programming
+ *              cycles.
+ * @dirty: Whether the mirror registers have been written to (overridden)
+ *         since we've last read the fuses (either as part of the reset
+ *         process or using a READFB instruction). There is a much larger,
+ *         but still finite, limit on the number of SFP read cycles (around
+ *         300,000), so we try and minimize reads as well.
+ */
+struct ls2_sfp_priv {
+	void __iomem *base;
+	struct udevice *supply;
+	bool programmed, dirty;
+};
+
+static u32 ls2_sfp_readl(struct ls2_sfp_priv *priv, ulong off)
+{
+	u32 val = be32_to_cpu(readl(priv->base + off));
+
+	log_debug("%08x = readl(%p)\n", val, priv->base + off);
+	return val;
+}
+
+static void ls2_sfp_writel(struct ls2_sfp_priv *priv, ulong val, ulong off)
+{
+	log_debug("writel(%08lx, %p)\n", val, priv->base + off);
+	writel(cpu_to_be32(val), priv->base + off);
+}
+
+static bool ls2_sfp_validate(struct udevice *dev, int offset, int size)
+{
+	if (offset < 0 || size < 0) {
+		dev_notice(dev, "size and offset must be positive\n");
+		return false;
+	}
+
+	if (offset & 3 || size & 3) {
+		dev_notice(dev, "size and offset must be multiples of 4\n");
+		return false;
+	}
+
+	if (offset + size > SFP_SIZE) {
+		dev_notice(dev, "size + offset must be <= %#x\n", SFP_SIZE);
+		return false;
+	}
+
+	return true;
+}
+
+static int ls2_sfp_read(struct udevice *dev, int offset, void *buf_bytes,
+			int size)
+{
+	int i;
+	struct ls2_sfp_priv *priv = dev_get_priv(dev);
+	u32 *buf = buf_bytes;
+
+	if (!ls2_sfp_validate(dev, offset, size))
+		return -EINVAL;
+
+	for (i = 0; i < size; i += 4)
+		buf[i >> 2] = ls2_sfp_readl(priv, SFP_START + offset + i);
+
+	return size;
+}
+
+static int ls2_sfp_write(struct udevice *dev, int offset,
+			 const void *buf_bytes, int size)
+{
+	int i;
+	struct ls2_sfp_priv *priv = dev_get_priv(dev);
+	const u32 *buf = buf_bytes;
+
+	if (!ls2_sfp_validate(dev, offset, size))
+		return -EINVAL;
+
+	for (i = 0; i < size; i += 4)
+		ls2_sfp_writel(priv, buf[i >> 2], SFP_START + offset + i);
+
+	priv->dirty = true;
+	return size;
+}
+
+static int ls2_sfp_check_secret(struct udevice *dev)
+{
+	struct ls2_sfp_priv *priv = dev_get_priv(dev);
+	u32 svhesr = ls2_sfp_readl(priv, SFP_SVHESR);
+
+	if (svhesr) {
+		dev_warn(dev, "secret value hamming error not zero: %08x\n",
+			 svhesr);
+		return -EIO;
+	}
+	return 0;
+}
+
+static int ls2_sfp_transaction(struct ls2_sfp_priv *priv, ulong inst)
+{
+	u32 ingr;
+
+	ls2_sfp_writel(priv, inst, SFP_INGR);
+
+	do {
+		ingr = ls2_sfp_readl(priv, SFP_INGR);
+	} while (FIELD_GET(SFP_INGR_INST, ingr));
+
+	return FIELD_GET(SFP_INGR_ERR, ingr) ? -EIO : 0;
+}
+
+static int ls2_sfp_ioctl(struct udevice *dev, unsigned long request, void *buf)
+{
+	int ret;
+	struct ls2_sfp_priv *priv = dev_get_priv(dev);
+
+	switch (request) {
+	case LS2_SFP_IOCTL_READ:
+		if (!priv->dirty) {
+			dev_dbg(dev, "ignoring read request, since fuses are not dirty\n");
+			return 0;
+		}
+
+		ret = ls2_sfp_transaction(priv, SFP_INGR_READFB);
+		if (ret) {
+			dev_err(dev, "error reading fuses\n");
+			return ret;
+		}
+
+		ls2_sfp_check_secret(dev);
+		priv->dirty = false;
+		return 0;
+	case LS2_SFP_IOCTL_PROG:
+		if (priv->programmed) {
+			dev_warn(dev, "fuses already programmed\n");
+			return -EPERM;
+		}
+
+		ret = ls2_sfp_check_secret(dev);
+		if (ret)
+			return ret;
+
+		if (priv->supply) {
+			ret = regulator_set_enable(priv->supply, true);
+			if (ret)
+				return ret;
+		}
+
+		ret = ls2_sfp_transaction(priv, SFP_INGR_PROGFB);
+		priv->programmed = true;
+		if (priv->supply)
+			regulator_set_enable(priv->supply, false);
+
+		if (ret)
+			dev_err(dev, "error programming fuses\n");
+		return ret;
+	default:
+		dev_dbg(dev, "unknown ioctl %lu\n", request);
+		return -EINVAL;
+	}
+}
+
+static const struct misc_ops ls2_sfp_ops = {
+	.read = ls2_sfp_read,
+	.write = ls2_sfp_write,
+	.ioctl = ls2_sfp_ioctl,
+};
+
+static int ls2_sfp_probe(struct udevice *dev)
+{
+	int ret;
+	struct clk clk;
+	struct ls2_sfp_priv *priv = dev_get_priv(dev);
+	ulong rate;
+
+	priv->base = dev_read_addr_ptr(dev);
+	if (!priv->base) {
+		dev_dbg(dev, "could not read register base\n");
+		return -EINVAL;
+	}
+
+	ret = device_get_supply_regulator(dev, "ta-sfp-prog", &priv->supply);
+	if (ret && ret != -ENODEV && ret != -ENOSYS) {
+		dev_dbg(dev, "problem getting supply (err %d)\n", ret);
+		return ret;
+	}
+
+	ret = clk_get_by_name(dev, "ipg", &clk);
+	if (ret == -ENOSYS) {
+		rate = gd->bus_clk;
+	} else if (ret) {
+		dev_dbg(dev, "could not get clock (err %d)\n", ret);
+		return ret;
+	} else {
+		ret = clk_enable(&clk);
+		if (ret) {
+			dev_dbg(dev, "could not enable clock (err %d)\n", ret);
+			return ret;
+		}
+
+		rate = clk_get_rate(&clk);
+		clk_free(&clk);
+		if (!rate || IS_ERR_VALUE(rate)) {
+			ret = rate ? rate : -ENOENT;
+			dev_dbg(dev, "could not get clock rate (err %d)\n",
+				ret);
+			return ret;
+		}
+	}
+
+	/* platform clock in MHz / 4 * 12 */
+	ls2_sfp_writel(priv, FIELD_PREP(SFP_SFPCR_PPW, rate * 3 / 1000000),
+		       SFP_SFPCR);
+
+	ls2_sfp_check_secret(dev);
+	return 0;
+}
+
+static const struct udevice_id ls2_sfp_ids[] = {
+	{ .compatible = "fsl,ls1021a-sfp" },
+	{ }
+};
+
+U_BOOT_DRIVER(ls2_sfp) = {
+	.name		= "ls2_sfp",
+	.id		= UCLASS_MISC,
+	.of_match	= ls2_sfp_ids,
+	.probe		= ls2_sfp_probe,
+	.ops		= &ls2_sfp_ops,
+	.priv_auto	= sizeof(struct ls2_sfp_priv),
+};
+
+static int ls2_sfp_device(struct udevice **dev)
+{
+	int ret = uclass_get_device_by_driver(UCLASS_MISC,
+					      DM_DRIVER_GET(ls2_sfp), dev);
+
+	if (ret)
+		log_debug("device not found (err %d)\n", ret);
+	return ret;
+}
+
+int fuse_read(u32 bank, u32 word, u32 *val)
+{
+	int ret;
+	struct udevice *dev;
+
+	ret = ls2_sfp_device(&dev);
+	if (ret)
+		return ret;
+
+	ret = misc_ioctl(dev, LS2_SFP_IOCTL_READ, NULL);
+	if (ret)
+		return ret;
+
+	ret = misc_read(dev, word << 2, val, sizeof(*val));
+	return ret < 0 ? ret : 0;
+}
+
+int fuse_sense(u32 bank, u32 word, u32 *val)
+{
+	int ret;
+	struct udevice *dev;
+
+	ret = ls2_sfp_device(&dev);
+	if (ret)
+		return ret;
+
+	ret = misc_read(dev, word << 2, val, sizeof(*val));
+	return ret < 0 ? ret : 0;
+}
+
+int fuse_prog(u32 bank, u32 word, u32 val)
+{
+	int ret;
+	struct udevice *dev;
+
+	ret = ls2_sfp_device(&dev);
+	if (ret)
+		return ret;
+
+	ret = misc_write(dev, word << 2, &val, sizeof(val));
+	if (ret < 0)
+		return ret;
+
+	return misc_ioctl(dev, LS2_SFP_IOCTL_PROG, NULL);
+}
+
+int fuse_override(u32 bank, u32 word, u32 val)
+{
+	int ret;
+	struct udevice *dev;
+
+	ret = ls2_sfp_device(&dev);
+	if (ret)
+		return ret;
+
+	ret = misc_write(dev, word << 2, &val, sizeof(val));
+	return ret < 0 ? ret : 0;
+}
-- 
2.35.1.1320.gc452695387.dirty


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] arch: layerscape: Add SFP binding
  2022-04-19 20:58 [PATCH 1/2] arm: layerscape: Add sfp driver Sean Anderson
@ 2022-04-19 20:58 ` Sean Anderson
  2022-04-19 23:26   ` Michael Walle
  2022-04-19 21:00 ` [PATCH 1/2] arm: layerscape: Add sfp driver Sean Anderson
  1 sibling, 1 reply; 7+ messages in thread
From: Sean Anderson @ 2022-04-19 20:58 UTC (permalink / raw)
  To: u-boot, Tom Rini
  Cc: Mingkai Hu, Alison Wang, Manish Tomar, Rajesh Bhagat, Mingkai Hu,
	Pramod Kumar, Vladimir Oltean, Sean Anderson, Alexey Brodkin,
	Andy Fleming, Angelo Dureghello, Bin Meng, Daniel Schwierzeck,
	Macpaul Lin, Marek Vasut, Mario Six, Michal Simek,
	Nobuhiro Iwamatsu, Priyanka Jain, Scott McNutt, Simon Glass,
	Stefan Roese, Thomas Chou, Wolfgang Denk

This adds an SFP binding for the processors it is present on. I have
only tested this for the LS1046A.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
---

 arch/arm/dts/fsl-ls1012a.dtsi | 7 +++++++
 arch/arm/dts/fsl-ls1043a.dtsi | 7 +++++++
 arch/arm/dts/fsl-ls1046a.dtsi | 7 +++++++
 arch/arm/dts/ls1021a.dtsi     | 7 +++++++
 4 files changed, 28 insertions(+)

diff --git a/arch/arm/dts/fsl-ls1012a.dtsi b/arch/arm/dts/fsl-ls1012a.dtsi
index 0ea899c7d7..510d863a66 100644
--- a/arch/arm/dts/fsl-ls1012a.dtsi
+++ b/arch/arm/dts/fsl-ls1012a.dtsi
@@ -34,6 +34,13 @@
 		#size-cells = <2>;
 		ranges;
 
+		sfp: efuse@1e80000 {
+			compatible = "fsl,ls1021a-sfp";
+			reg = <0x0 0x1e80000 0x0 0x1000>;
+			clocks = <&clockgen 4 0>;
+			clock-names = "ipg";
+		};
+
 		clockgen: clocking@1ee1000 {
 			compatible = "fsl,ls1012a-clockgen";
 			reg = <0x0 0x1ee1000 0x0 0x1000>;
diff --git a/arch/arm/dts/fsl-ls1043a.dtsi b/arch/arm/dts/fsl-ls1043a.dtsi
index 52dc5a9638..13a999f6f4 100644
--- a/arch/arm/dts/fsl-ls1043a.dtsi
+++ b/arch/arm/dts/fsl-ls1043a.dtsi
@@ -38,6 +38,13 @@
 		#size-cells = <2>;
 		ranges;
 
+		sfp: efuse@1e80000 {
+			compatible = "fsl,ls1021a-sfp";
+			reg = <0x0 0x1e80000 0x0 0x1000>;
+			clocks = <&clockgen 4 0>;
+			clock-names = "ipg";
+		};
+
 		clockgen: clocking@1ee1000 {
 			compatible = "fsl,ls1043a-clockgen";
 			reg = <0x0 0x1ee1000 0x0 0x1000>;
diff --git a/arch/arm/dts/fsl-ls1046a.dtsi b/arch/arm/dts/fsl-ls1046a.dtsi
index a60cbf11fc..f7026e16e0 100644
--- a/arch/arm/dts/fsl-ls1046a.dtsi
+++ b/arch/arm/dts/fsl-ls1046a.dtsi
@@ -37,6 +37,13 @@
 		#size-cells = <2>;
 		ranges;
 
+		sfp: efuse@1e80000 {
+			compatible = "fsl,ls1021a-sfp";
+			reg = <0x0 0x1e80000 0x0 0x1000>;
+			clocks = <&clockgen 4 0>;
+			clock-names = "ipg";
+		};
+
 		clockgen: clocking@1ee1000 {
 			compatible = "fsl,ls1046a-clockgen";
 			reg = <0x0 0x1ee1000 0x0 0x1000>;
diff --git a/arch/arm/dts/ls1021a.dtsi b/arch/arm/dts/ls1021a.dtsi
index 86192cbb7f..1e1b52eab4 100644
--- a/arch/arm/dts/ls1021a.dtsi
+++ b/arch/arm/dts/ls1021a.dtsi
@@ -81,6 +81,13 @@
 			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
+		sfp: efuse@1e80000 {
+			compatible = "fsl,ls1021a-sfp";
+			reg = <0x0 0x1e80000 0x0 0x1000>;
+			clocks = <&platform_clk 1>;
+			clock-names = "ipg";
+		};
+
 		dcfg: dcfg@1ee0000 {
 			compatible = "fsl,ls1021a-dcfg", "syscon";
 			reg = <0x1ee0000 0x10000>;
-- 
2.35.1.1320.gc452695387.dirty


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] arm: layerscape: Add sfp driver
  2022-04-19 20:58 [PATCH 1/2] arm: layerscape: Add sfp driver Sean Anderson
  2022-04-19 20:58 ` [PATCH 2/2] arch: layerscape: Add SFP binding Sean Anderson
@ 2022-04-19 21:00 ` Sean Anderson
  1 sibling, 0 replies; 7+ messages in thread
From: Sean Anderson @ 2022-04-19 21:00 UTC (permalink / raw)
  To: u-boot, Tom Rini
  Cc: Mingkai Hu, Alison Wang, Manish Tomar, Rajesh Bhagat,
	Pramod Kumar, Vladimir Oltean

On 4/19/22 4:58 PM, Sean Anderson wrote:
> This adds a driver for the Security Fuse Processor (SFP) present on
> LS1012A, LS1021A, LS1043A, and LS1046A processors. It holds the
> Super-Root Key (SRK), One-Time-Programmable Master Key (OTPMK), and
> other "security" related fuses. Similar devices (sharing the same name)
> are present on other processors, but for the moment this just supports
> the LS2 variants.
> 
> The mirror registers are loaded during power-on reset. All mirror
> registers must be programmed or read at once. Because of this, `fuse
> prog` will program all fuses, even though only one might be specified.
> To prevent accidentally burning through all your fuse programming cycles
> with something like `fuse prog 0 0 A B C D`, we limit ourselves to one
> programming cycle per reset. Fuses are numbered based on their address.
> The fuse at 0x1e80200 is 0, the fuse at 0x1e80204 is 1, etc.
> 
> The TA_PROG_SFP supply must be enabled when programming fuses, but must
> be disabled when reading them. Typically this supply is enabled by
> inserting a jumper or by setting a register in the board's FPGA. I've
> also added support for using a regulator. This could be helpful for
> automatically issuing the FPGA write, or for toggling a GPIO controlling
> the supply.
> 
> I suggest using the following procedure for programming:
> 
> 1. Override the fuses you wish to program
>    => fuse override 0 2 A B C D
> 2. Inspect the values and ensure that they are what you expect
>    => fuse sense 0 2 4
> 3. Enable TA_PROG_SFP
> 4. Issue a program command using OSPR0 as a dummy. Since it contains the
>    write-protect bit you will usually want to write it last anyway.
>    => fuse prog 0 0 0
> 5. Disable TA_PROG_SFP
> 6. Read back the fuses and ensure they are correct
>    => fuse read 0 2 4
> 
> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
> ---

I forgot to mention this, but this patch depends on

https://lore.kernel.org/u-boot/20220419191245.3749739-1-sean.anderson@seco.com/T/#u

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] arch: layerscape: Add SFP binding
  2022-04-19 20:58 ` [PATCH 2/2] arch: layerscape: Add SFP binding Sean Anderson
@ 2022-04-19 23:26   ` Michael Walle
  2022-04-19 23:51     ` Sean Anderson
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Walle @ 2022-04-19 23:26 UTC (permalink / raw)
  To: sean.anderson
  Cc: afleming, alexey.brodkin, alison.wang, angelo, bmeng.cn,
	daniel.schwierzeck, iwamatsu, macpaul, manish.tomar, marex,
	mario.six, mingkai.hu, monstr, olteanv, pramod.kumar_1,
	priyanka.jain, rajesh.bhagat, sjg, smcnutt, sr, thomas, trini,
	u-boot, wd, Michael Walle

Hi Sean,

> This adds an SFP binding for the processors it is present on. I have
> only tested this for the LS1046A.
> 
> Signed-off-by: Sean Anderson <sean.anderson@seco.com>

There is an upstream binding
Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml

Are you aware of that? Could you submit a patch there to add
your new compatibles? Esp. because you are using a clock which
isn't described in the upstream binding. I'm curious, do you need the
clock? I only know the LS1028A and it seems you don't have to turn on
any clock there. It might also be the case I've missed something.

-michael

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] arch: layerscape: Add SFP binding
  2022-04-19 23:26   ` Michael Walle
@ 2022-04-19 23:51     ` Sean Anderson
  2022-04-20  8:06       ` Michael Walle
  0 siblings, 1 reply; 7+ messages in thread
From: Sean Anderson @ 2022-04-19 23:51 UTC (permalink / raw)
  To: Michael Walle, sean.anderson
  Cc: afleming, alexey.brodkin, alison.wang, angelo, bmeng.cn,
	daniel.schwierzeck, iwamatsu, macpaul, manish.tomar, marex,
	mario.six, mingkai.hu, monstr, olteanv, pramod.kumar_1,
	priyanka.jain, rajesh.bhagat, sjg, smcnutt, sr, thomas, trini,
	u-boot, wd

Hi Michael,

On 4/19/22 7:26 PM, Michael Walle wrote:
> Hi Sean,
> 
>> This adds an SFP binding for the processors it is present on. I have
>> only tested this for the LS1046A.
>>
>> Signed-off-by: Sean Anderson <sean.anderson@seco.com>
> 
> There is an upstream binding
> Documentation/devicetree/bindings/nvmem/fsl,layerscape-sfp.yaml

I see it will be added in 5.18, neat.

> Are you aware of that?

I am now.

> Could you submit a patch there to add your new compatibles?

Sure. I didn't know there was an upstream binding, but I'll try and add these properties.

> Esp. because you are using a clock which
> isn't described in the upstream binding. I'm curious, do you need the
> clock? I only know the LS1028A and it seems you don't have to turn on
> any clock there. It might also be the case I've missed something.

You need the clock to set the programming duration properly. See the probe
function for this driver. For read-only access, it is not necessary.

--Sean


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] arch: layerscape: Add SFP binding
  2022-04-19 23:51     ` Sean Anderson
@ 2022-04-20  8:06       ` Michael Walle
  2022-04-21 14:41         ` Sean Anderson
  0 siblings, 1 reply; 7+ messages in thread
From: Michael Walle @ 2022-04-20  8:06 UTC (permalink / raw)
  To: Sean Anderson
  Cc: sean.anderson, afleming, alexey.brodkin, alison.wang, angelo,
	bmeng.cn, daniel.schwierzeck, iwamatsu, macpaul, manish.tomar,
	marex, mario.six, mingkai.hu, monstr, olteanv, pramod.kumar_1,
	priyanka.jain, rajesh.bhagat, sjg, smcnutt, sr, thomas, trini,
	u-boot, wd

Am 2022-04-20 01:51, schrieb Sean Anderson:
>> Could you submit a patch there to add your new compatibles?
> 
> Sure. I didn't know there was an upstream binding, but I'll try and
> add these properties.

If you'll submit the patch(es) before 5.18 is released, I think we
can still add the clock as mandatory.

>> Esp. because you are using a clock which
>> isn't described in the upstream binding. I'm curious, do you need the
>> clock? I only know the LS1028A and it seems you don't have to turn on
>> any clock there. It might also be the case I've missed something.
> 
> You need the clock to set the programming duration properly. See the 
> probe
> function for this driver. For read-only access, it is not necessary.

Ahh thanks, I had a quick glance at your driver and just saw the prepare
clock and enable. I see you are also setting the program pulse width
field. I think it is preset for the LS1028A so in theory it would
work without. In any case, the clock should be added to the binding.

The ta-sfp-prog supply property is also neat :)

-michael

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/2] arch: layerscape: Add SFP binding
  2022-04-20  8:06       ` Michael Walle
@ 2022-04-21 14:41         ` Sean Anderson
  0 siblings, 0 replies; 7+ messages in thread
From: Sean Anderson @ 2022-04-21 14:41 UTC (permalink / raw)
  To: Michael Walle, Sean Anderson
  Cc: afleming, alexey.brodkin, alison.wang, angelo, bmeng.cn,
	daniel.schwierzeck, iwamatsu, macpaul, manish.tomar, marex,
	mario.six, mingkai.hu, monstr, olteanv, pramod.kumar_1,
	priyanka.jain, rajesh.bhagat, sjg, smcnutt, sr, thomas, trini,
	u-boot, wd

Hi Michael,

On 4/20/22 4:06 AM, Michael Walle wrote:
> Am 2022-04-20 01:51, schrieb Sean Anderson:
>>> Could you submit a patch there to add your new compatibles?
>>
>> Sure. I didn't know there was an upstream binding, but I'll try and
>> add these properties.
> 
> If you'll submit the patch(es) before 5.18 is released, I think we
> can still add the clock as mandatory.
> 
>>> Esp. because you are using a clock which
>>> isn't described in the upstream binding. I'm curious, do you need the
>>> clock? I only know the LS1028A and it seems you don't have to turn on
>>> any clock there. It might also be the case I've missed something.
>>
>> You need the clock to set the programming duration properly. See the probe
>> function for this driver. For read-only access, it is not necessary.
> 
> Ahh thanks, I had a quick glance at your driver and just saw the prepare
> clock and enable. I see you are also setting the program pulse width
> field. I think it is preset for the LS1028A so in theory it would
> work without. In any case, the clock should be added to the binding.

Well,

> The reset value is a safe default for programming under typical
> conditions (at top frequency bin)

I'm not sure whether it's better to under/overshoot, but if we have
the clock available it's simple to set it correctly.

--Sean

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-04-21 14:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-19 20:58 [PATCH 1/2] arm: layerscape: Add sfp driver Sean Anderson
2022-04-19 20:58 ` [PATCH 2/2] arch: layerscape: Add SFP binding Sean Anderson
2022-04-19 23:26   ` Michael Walle
2022-04-19 23:51     ` Sean Anderson
2022-04-20  8:06       ` Michael Walle
2022-04-21 14:41         ` Sean Anderson
2022-04-19 21:00 ` [PATCH 1/2] arm: layerscape: Add sfp driver Sean Anderson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.