From ahmad at a3f.at  Fri Jan  1 17:51:39 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Fri,  1 Jan 2021 23:51:39 +0100
Subject: [PATCH] driver: provide dev_request_mem_resource_by_name() helper
Message-ID: <20210101225139.2165289-1-ahmad@a3f.at>

There are both dev_request_mem_resource() and dev_request_mem_region(),
which return the struct resource and a IOMEM(.start) respectively.

There is only dev_request_mem_region_by_name(), but
no dev_request_mem_resource_by_name(), so add the latter for symmetry.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/base/driver.c | 12 ++++++++++--
 include/driver.h      |  5 +++++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 3205bbc3c33b..6763bbc6f512 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -372,7 +372,7 @@ struct resource *dev_get_resource_by_name(struct device_d *dev,
 	return ERR_PTR(-ENOENT);
 }
 
-void __iomem *dev_request_mem_region_by_name(struct device_d *dev, const char *name)
+struct resource *dev_request_mem_resource_by_name(struct device_d *dev, const char *name)
 {
 	struct resource *res;
 
@@ -380,7 +380,15 @@ void __iomem *dev_request_mem_region_by_name(struct device_d *dev, const char *n
 	if (IS_ERR(res))
 		return ERR_CAST(res);
 
-	res = request_iomem_region(dev_name(dev), res->start, res->end);
+	return request_iomem_region(dev_name(dev), res->start, res->end);
+}
+EXPORT_SYMBOL(dev_request_mem_resource_by_name);
+
+void __iomem *dev_request_mem_region_by_name(struct device_d *dev, const char *name)
+{
+	struct resource *res;
+
+	res = dev_request_mem_resource_by_name(dev, name);
 	if (IS_ERR(res))
 		return ERR_CAST(res);
 
diff --git a/include/driver.h b/include/driver.h
index e2886d051d4f..0d43b3614863 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -214,6 +214,11 @@ void __iomem *dev_request_mem_region(struct device_d *dev, int num);
  */
 struct resource *dev_request_mem_resource(struct device_d *dev, int num);
 
+/*
+ * exlusively request resource 'name' for a device
+ */
+struct resource *dev_request_mem_resource_by_name(struct device_d *dev, const char *name);
+
 /*
  * exlusively request register base 'num' for a device
  * will return NULL on error
-- 
2.29.2



From ahmad at a3f.at  Fri Jan  1 17:52:26 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Fri,  1 Jan 2021 23:52:26 +0100
Subject: [PATCH 2/4] video: edid: make edid_check_header externally visible
In-Reply-To: <20210101225228.2166084-1-ahmad@a3f.at>
References: <20210101225228.2166084-1-ahmad@a3f.at>
Message-ID: <20210101225228.2166084-2-ahmad@a3f.at>

For non-i2c EDID use, drivers will want to verify the EDID header. We
already have a function for this, but internal linkage. Change this and
while at it change the type to a more appropriate type.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/video/edid.c |  8 ++++----
 drivers/video/edid.h | 10 ++++++++++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/video/edid.c b/drivers/video/edid.c
index 41d40d0297b6..1baff7317b7c 100644
--- a/drivers/video/edid.c
+++ b/drivers/video/edid.c
@@ -223,19 +223,19 @@ static int edid_checksum(unsigned char *edid)
 	return err;
 }
 
-static int edid_check_header(unsigned char *edid)
+bool edid_check_header(unsigned char *edid)
 {
-	int i, err = 1, fix = check_edid(edid);
+	int i, fix = check_edid(edid);
 
 	if (fix)
 		fix_edid(edid, fix);
 
 	for (i = 0; i < 8; i++) {
 		if (edid[i] != edid_v1_header[i])
-			err = 0;
+			return false;
 	}
 
-	return err;
+	return true;
 }
 
 /*
diff --git a/drivers/video/edid.h b/drivers/video/edid.h
index 006d9f283450..60c5b6422ea5 100644
--- a/drivers/video/edid.h
+++ b/drivers/video/edid.h
@@ -135,4 +135,14 @@
 #define DPMS_SUSPEND		(1 << 6)
 #define DPMS_STANDBY		(1 << 7)
 
+/**
+ * edid_check_header - sanity check the header of the base EDID block
+ * @raw_edid: pointer to raw base EDID block
+ *
+ * Sanity check the header of the base EDID block.
+ *
+ * Return: true if the header is perfect, false if any byte is wrong.
+ */
+bool edid_check_header(unsigned char *edid);
+
 #endif /* __EDID_H__ */
-- 
2.29.2



From ahmad at a3f.at  Fri Jan  1 17:52:25 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Fri,  1 Jan 2021 23:52:25 +0100
Subject: [PATCH 1/4] video: edid: make accessible without i2c
Message-ID: <20210101225228.2166084-1-ahmad@a3f.at>

Users can already populate fb_info::edid_data for cases where the EDID
doesn't come via an i2c controller managed by barebox.

Only thing missing is to be able to compile without i2c, thus drop
the dependency.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/video/Kconfig | 1 -
 drivers/video/edid.c  | 3 +++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index a26bace176a1..56d009529ea4 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -106,7 +106,6 @@ config DRIVER_VIDEO_SIMPLEFB
 	  based on the active barebox framebuffer.
 
 config DRIVER_VIDEO_EDID
-	depends on I2C
 	bool "Add EDID support"
 	help
 	  This enabled support for reading and parsing EDID data from an attached
diff --git a/drivers/video/edid.c b/drivers/video/edid.c
index bee4594118bb..41d40d0297b6 100644
--- a/drivers/video/edid.c
+++ b/drivers/video/edid.c
@@ -858,6 +858,9 @@ void *edid_read_i2c(struct i2c_adapter *adapter)
 {
 	u8 *block;
 
+	if (!IS_ENABLED(CONFIG_I2C))
+		return NULL;
+
 	block = xmalloc(EDID_LENGTH);
 
 	if (edid_do_read_i2c(adapter, block, 0, EDID_LENGTH))
-- 
2.29.2



From ahmad at a3f.at  Fri Jan  1 17:52:28 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Fri,  1 Jan 2021 23:52:28 +0100
Subject: [PATCH 4/4] MIPS: qemu-malta_defconfig: enable VGA output
In-Reply-To: <20210101225228.2166084-1-ahmad@a3f.at>
References: <20210101225228.2166084-1-ahmad@a3f.at>
Message-ID: <20210101225228.2166084-4-ahmad@a3f.at>

Now that we have a driver for the Qemu's default -device VGA, enable it
in defconfig, along with fbtest for testing it.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 Documentation/boards/mips/qemu-malta.rst | 4 ++--
 arch/mips/configs/qemu-malta_defconfig   | 4 ++++
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/Documentation/boards/mips/qemu-malta.rst b/Documentation/boards/mips/qemu-malta.rst
index 2bb81350a109..470be32f1f49 100644
--- a/Documentation/boards/mips/qemu-malta.rst
+++ b/Documentation/boards/mips/qemu-malta.rst
@@ -9,7 +9,7 @@ QEMU run string:
 .. code-block:: sh
 
   qemu-system-mips -nodefaults -M malta -m 256 \
-      -nographic -serial stdio -monitor null \
+      -device VGA -serial stdio -monitor null \
       -bios barebox-flash-image
 
 
@@ -33,7 +33,7 @@ QEMU run string:
 .. code-block:: sh
 
   qemu-system-mipsel -nodefaults -M malta -m 256 \
-      -nographic -serial stdio -monitor null \
+      -devica VGA -serial stdio -monitor null \
       -bios barebox-flash-image
 
 
diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig
index ac0577c217e3..b9994f392c47 100644
--- a/arch/mips/configs/qemu-malta_defconfig
+++ b/arch/mips/configs/qemu-malta_defconfig
@@ -42,6 +42,7 @@ CONFIG_CMD_LOGIN=y
 CONFIG_CMD_MENU=y
 CONFIG_CMD_MENU_MANAGEMENT=y
 CONFIG_CMD_PASSWD=y
+CONFIG_CMD_FBTEST=y
 CONFIG_CMD_READLINE=y
 CONFIG_CMD_TIMEOUT=y
 CONFIG_CMD_CRC=y
@@ -68,6 +69,9 @@ CONFIG_DRIVER_CFI=y
 # CONFIG_DRIVER_CFI_BANK_WIDTH_1 is not set
 # CONFIG_DRIVER_CFI_BANK_WIDTH_2 is not set
 CONFIG_CFI_BUFFER_WRITE=y
+CONFIG_VIDEO=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_DRIVER_VIDEO_BOCHS_PCI=y
 CONFIG_GPIO_MALTA_FPGA_I2C=y
 CONFIG_PCI=y
 CONFIG_PCI_DEBUG=y
-- 
2.29.2



From ahmad at a3f.at  Fri Jan  1 17:52:27 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Fri,  1 Jan 2021 23:52:27 +0100
Subject: [PATCH 3/4] video: implement bochs dispi / QEMU VGA driver for PCI
 and ISA
In-Reply-To: <20210101225228.2166084-1-ahmad@a3f.at>
References: <20210101225228.2166084-1-ahmad@a3f.at>
Message-ID: <20210101225228.2166084-3-ahmad@a3f.at>

All SVGA devices in Qemu, except for Cirrus, support the bochs display
interface, which is very easy to set up. Add a driver for it.

This has been tested with:

 PCI: qemu-system-mips(el) -device VGA + barebox qemu-malta_defconfig
 ISA: qemu-system-x86_64 -device isa-vga + barebox efi_defconfig

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/video/Kconfig           |   2 +
 drivers/video/Makefile          |   2 +-
 drivers/video/bochs/Kconfig     |  22 ++++
 drivers/video/bochs/Makefile    |   3 +
 drivers/video/bochs/bochs_hw.c  | 203 ++++++++++++++++++++++++++++++++
 drivers/video/bochs/bochs_hw.h  |  13 ++
 drivers/video/bochs/bochs_isa.c |  31 +++++
 drivers/video/bochs/bochs_pci.c |  37 ++++++
 8 files changed, 312 insertions(+), 1 deletion(-)
 create mode 100644 drivers/video/bochs/Kconfig
 create mode 100644 drivers/video/bochs/Makefile
 create mode 100644 drivers/video/bochs/bochs_hw.c
 create mode 100644 drivers/video/bochs/bochs_hw.h
 create mode 100644 drivers/video/bochs/bochs_isa.c
 create mode 100644 drivers/video/bochs/bochs_pci.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 56d009529ea4..9ec6ea4248c1 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -98,6 +98,8 @@ config DRIVER_VIDEO_BCM283X
 
 source "drivers/video/imx-ipu-v3/Kconfig"
 
+source "drivers/video/bochs/Kconfig"
+
 config DRIVER_VIDEO_SIMPLEFB
 	bool "Simple framebuffer support"
 	depends on OFTREE
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 01fabe880920..28d0fe205b83 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -24,4 +24,4 @@ obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += imx-ipu-v3/
 obj-$(CONFIG_DRIVER_VIDEO_EFI_GOP) += efi_gop.o
 obj-$(CONFIG_DRIVER_VIDEO_FB_SSD1307) += ssd1307fb.o
 obj-$(CONFIG_BACKLIGHT_RAVE_SP)	+= rave-sp-backlight.o
-
+obj-$(CONFIG_DRIVER_VIDEO_BOCHS) += bochs/
diff --git a/drivers/video/bochs/Kconfig b/drivers/video/bochs/Kconfig
new file mode 100644
index 000000000000..e23e68f1126c
--- /dev/null
+++ b/drivers/video/bochs/Kconfig
@@ -0,0 +1,22 @@
+config DRIVER_VIDEO_BOCHS
+	select DRIVER_VIDEO_EDID
+	bool
+
+config DRIVER_VIDEO_BOCHS_PCI
+	bool "bochs dispi / QEMU standard VGA PCI driver"
+	select DRIVER_VIDEO_BOCHS
+	depends on PCI
+	help
+	  Say yes here if you have a PCI VGA display controller that
+	  implements the bochs dispi VBE extension. This is a very simple
+	  interface to drive the graphical output of virtual machines
+	  like bochs, VirtualBox and Qemu (-device VGA).
+
+config DRIVER_VIDEO_BOCHS_ISA
+	bool "bochs dispi / QEMU standard VGA ISA driver"
+	select DRIVER_VIDEO_BOCHS
+	help
+	  Say yes here if you have a ISA (I/O ports) VGA display controller that
+	  implements the bochs dispi VBE extension. This is a very simple
+	  interface to drive the graphical output of virtual machines
+	  like bochs, VirtualBox and Qemu (-device isa-vga).
diff --git a/drivers/video/bochs/Makefile b/drivers/video/bochs/Makefile
new file mode 100644
index 000000000000..78ec1fe0ca81
--- /dev/null
+++ b/drivers/video/bochs/Makefile
@@ -0,0 +1,3 @@
+obj-y += bochs_hw.o
+obj-$(CONFIG_DRIVER_VIDEO_BOCHS_PCI) += bochs_pci.o
+obj-$(CONFIG_DRIVER_VIDEO_BOCHS_ISA) += bochs_isa.o
diff --git a/drivers/video/bochs/bochs_hw.c b/drivers/video/bochs/bochs_hw.c
new file mode 100644
index 000000000000..4f908a60318d
--- /dev/null
+++ b/drivers/video/bochs/bochs_hw.c
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: Copyright (c) 2020 Ahmad Fatoum, Pengutronix
+/*
+ *  PCI Driver for VGA with the Bochs VBE / QEMU stdvga extensions.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <linux/pci.h>
+#include <fb.h>
+#include "../edid.h"
+#include "bochs_hw.h"
+
+#define VBE_DISPI_INDEX_ID               0x0
+#define VBE_DISPI_INDEX_XRES             0x1
+#define VBE_DISPI_INDEX_YRES             0x2
+#define VBE_DISPI_INDEX_BPP              0x3
+#define VBE_DISPI_INDEX_ENABLE           0x4
+#define VBE_DISPI_INDEX_BANK             0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH       0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT      0x7
+#define VBE_DISPI_INDEX_X_OFFSET         0x8
+#define VBE_DISPI_INDEX_Y_OFFSET         0x9
+#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
+
+#define VBE_DISPI_ENABLED                0x01
+#define VBE_DISPI_GETCAPS                0x02
+#define VBE_DISPI_8BIT_DAC               0x20
+#define VBE_DISPI_LFB_ENABLED            0x40
+#define VBE_DISPI_NOCLEARMEM             0x80
+
+/* Offsets for accessing ioports via PCI BAR1 (MMIO) */
+#define VGA_MMIO_OFFSET (0x400 - 0x3c0)
+#define VBE_MMIO_OFFSET 0x500
+
+struct bochs {
+	struct fb_info fb;
+	void __iomem *fb_map;
+	void __iomem *mmio;
+};
+
+static void bochs_vga_writeb(struct bochs *bochs, u16 ioport, u8 val)
+{
+	if (WARN_ON(ioport < 0x3c0 || ioport > 0x3df))
+		return;
+
+	if (bochs->mmio) {
+		int offset = ioport + VGA_MMIO_OFFSET;
+		writeb(val, bochs->mmio + offset);
+	} else {
+		outb(val, ioport);
+	}
+}
+
+static u16 bochs_dispi_read(struct bochs *bochs, u16 reg)
+{
+	u16 ret = 0;
+
+	if (bochs->mmio) {
+		int offset = VBE_MMIO_OFFSET + (reg << 1);
+		ret = readw(bochs->mmio + offset);
+	} else {
+		outw(reg, VBE_DISPI_IOPORT_INDEX);
+		ret = inw(VBE_DISPI_IOPORT_DATA);
+	}
+	return ret;
+}
+
+static void bochs_dispi_write(struct bochs *bochs, u16 reg, u16 val)
+{
+	if (bochs->mmio) {
+		int offset = VBE_MMIO_OFFSET + (reg << 1);
+		writew(val, bochs->mmio + offset);
+	} else {
+		outw(reg, VBE_DISPI_IOPORT_INDEX);
+		outw(val, VBE_DISPI_IOPORT_DATA);
+	}
+}
+
+static void bochs_fb_enable(struct fb_info *fb)
+{
+	struct bochs *bochs = fb->priv;
+
+	bochs_vga_writeb(bochs, 0x3c0, 0x20); /* unblank */
+
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE, 0);
+
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_BPP,		fb->bits_per_pixel);
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_XRES,		fb->xres);
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_YRES,		fb->yres);
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_BANK,		0);
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_WIDTH,	fb->xres);
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_VIRT_HEIGHT,	fb->yres);
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_X_OFFSET,	0);
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_Y_OFFSET,	0);
+
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
+			  VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED );
+}
+
+static void bochs_fb_disable(struct fb_info *fb)
+{
+	struct bochs *bochs = fb->priv;
+
+	bochs_dispi_write(bochs, VBE_DISPI_INDEX_ENABLE,
+			 bochs_dispi_read(bochs, VBE_DISPI_INDEX_ENABLE) &
+			 ~VBE_DISPI_ENABLED);
+}
+
+static struct fb_ops bochs_fb_ops = {
+	.fb_enable = bochs_fb_enable,
+	.fb_disable = bochs_fb_disable,
+};
+
+static int bochs_hw_load_edid(struct bochs *bochs)
+{
+	u8 *edid;
+	int i;
+
+	edid = xzalloc(EDID_LENGTH);
+
+	for (i = 0; i <= EDID_HEADER_END; i++)
+		edid[i] = readb(bochs->mmio + i);
+
+	/* check header to detect whenever edid support is enabled in qemu */
+	if (!edid_check_header(edid)) {
+		free(edid);
+		return -1;
+	}
+
+	for (i = EDID_HEADER_END + 1; i < EDID_LENGTH; i++)
+		edid[i] = readb(bochs->mmio + i);
+
+	bochs->fb.edid_data = edid;
+	return 0;
+}
+
+static int bochs_hw_read_version(struct bochs *bochs)
+{
+	u16 ver;
+
+	ver = bochs_dispi_read(bochs, VBE_DISPI_INDEX_ID);
+
+	if ((ver & 0xB0C0) != 0xB0C0)
+		return -ENODEV;
+
+	return ver & 0xF;
+}
+
+int bochs_hw_probe(struct device_d *dev, void __iomem *fb_map, void __iomem *mmio)
+{
+	struct bochs *bochs;
+	struct fb_info *fb;
+	int ret;
+
+	bochs = xzalloc(sizeof(*bochs));
+
+	bochs->fb_map	= IOMEM(fb_map);
+	bochs->mmio	= IOMEM(mmio);
+
+	ret = bochs_hw_read_version(bochs);
+	if (ret < 0) {
+		free(bochs);
+		return ret;
+	}
+
+	dev_info(dev, "detected bochs dispi v%u\n", ret);
+
+	fb = &bochs->fb;
+	fb->screen_base = bochs->fb_map;
+
+	fb->bits_per_pixel = 16;
+	fb->red.length = 5;
+	fb->green.length = 6;
+	fb->blue.length = 5;
+	fb->red.offset = 11;
+	fb->green.offset = 5;
+	fb->blue.offset = 0;
+
+	/* EDID is only exposed over PCI */
+	ret = -ENODEV;
+
+	if (mmio) {
+		ret = bochs_hw_load_edid(bochs);
+		if (ret)
+			dev_warn(dev, "couldn't read EDID information\n");
+	}
+
+	if (ret) {
+		fb->mode = xzalloc(sizeof(*fb->mode));
+		fb->modes.modes = fb->mode;
+		fb->modes.num_modes = 1;
+
+		fb->mode->name = "640x480";
+		fb->mode->xres = 640;
+		fb->mode->yres = 480;
+	}
+
+	fb->priv = bochs;
+	fb->fbops = &bochs_fb_ops;
+
+	return register_framebuffer(fb);
+}
diff --git a/drivers/video/bochs/bochs_hw.h b/drivers/video/bochs/bochs_hw.h
new file mode 100644
index 000000000000..36c2cc1cc376
--- /dev/null
+++ b/drivers/video/bochs/bochs_hw.h
@@ -0,0 +1,13 @@
+#ifndef BOCHS_HW_H
+#define BOCHS_HW_H
+
+#include <linux/compiler.h>
+
+#define VBE_DISPI_IOPORT_INDEX           0x01CE
+#define VBE_DISPI_IOPORT_DATA            0x01CF
+
+struct device_d;
+
+int bochs_hw_probe(struct device_d *dev, void *fb_map, void __iomem *mmio);
+
+#endif
diff --git a/drivers/video/bochs/bochs_isa.c b/drivers/video/bochs/bochs_isa.c
new file mode 100644
index 000000000000..7f75803baa0c
--- /dev/null
+++ b/drivers/video/bochs/bochs_isa.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: Copyright (c) 2020 Ahmad Fatoum, Pengutronix
+/*
+ *  ISA Driver for VGA with the Bochs VBE / QEMU stdvga extensions.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <linux/ioport.h>
+#include "bochs_hw.h"
+
+static int bochs_isa_detect(void)
+{
+	struct device_d *dev;
+	int ret;
+
+	outw(0, VBE_DISPI_IOPORT_INDEX);
+	ret = inw(VBE_DISPI_IOPORT_DATA);
+
+	if ((ret & 0xB0C0) != 0xB0C0)
+		return -ENODEV;
+
+	dev = device_alloc("bochs-dispi", 0);
+
+	ret = platform_device_register(dev);
+	if (ret)
+		return ret;
+
+	return bochs_hw_probe(dev, (void *)0xe0000000, NULL);
+}
+device_initcall(bochs_isa_detect);
diff --git a/drivers/video/bochs/bochs_pci.c b/drivers/video/bochs/bochs_pci.c
new file mode 100644
index 000000000000..39f582029d35
--- /dev/null
+++ b/drivers/video/bochs/bochs_pci.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: Copyright (c) 2020 Ahmad Fatoum, Pengutronix
+/*
+ *  PCI Driver for VGA with the Bochs VBE / QEMU stdvga extensions.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <linux/pci.h>
+#include "bochs_hw.h"
+
+static int bochs_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	void __iomem *fb_map, *mmio;
+	int ret;
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		return ret;
+
+	fb_map	= pci_iomap(pdev, 0);
+	mmio	= pci_iomap(pdev, 2);
+
+	return bochs_hw_probe(&pdev->dev, fb_map, mmio);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(bochs_pci_tbl) = {
+	/* https://github.com/qemu/qemu/blob/master/docs/specs/standard-vga.txt */
+	{ PCI_DEVICE(0x1234, 0x1111) },
+};
+
+static struct pci_driver bochs_pci_driver = {
+	.name		= "bochs-dispi",
+	.probe		= bochs_pci_probe,
+	.id_table	= bochs_pci_tbl,
+};
+device_pci_driver(bochs_pci_driver);
-- 
2.29.2



From ahmad at a3f.at  Sat Jan  2 06:10:39 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sat,  2 Jan 2021 12:10:39 +0100
Subject: [PATCH] fixup! video: implement bochs dispi / QEMU VGA driver for PCI
 and ISA
In-Reply-To: <20210101225228.2166084-3-ahmad@a3f.at>
References: <20210101225228.2166084-3-ahmad@a3f.at>
Message-ID: <20210102111039.2219861-1-ahmad@a3f.at>

Fix few comments and while at it, replace a -1 error with a more
descriptive error code. No functional change.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/video/bochs/Kconfig     | 2 ++
 drivers/video/bochs/Makefile    | 2 ++
 drivers/video/bochs/bochs_hw.c  | 6 ++++--
 drivers/video/bochs/bochs_hw.h  | 2 ++
 drivers/video/bochs/bochs_isa.c | 2 +-
 drivers/video/bochs/bochs_pci.c | 2 +-
 6 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/video/bochs/Kconfig b/drivers/video/bochs/Kconfig
index e23e68f1126c..ae5d38a8ad46 100644
--- a/drivers/video/bochs/Kconfig
+++ b/drivers/video/bochs/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
 config DRIVER_VIDEO_BOCHS
 	select DRIVER_VIDEO_EDID
 	bool
diff --git a/drivers/video/bochs/Makefile b/drivers/video/bochs/Makefile
index 78ec1fe0ca81..3ab7ade8a180 100644
--- a/drivers/video/bochs/Makefile
+++ b/drivers/video/bochs/Makefile
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
 obj-y += bochs_hw.o
 obj-$(CONFIG_DRIVER_VIDEO_BOCHS_PCI) += bochs_pci.o
 obj-$(CONFIG_DRIVER_VIDEO_BOCHS_ISA) += bochs_isa.o
diff --git a/drivers/video/bochs/bochs_hw.c b/drivers/video/bochs/bochs_hw.c
index 4f908a60318d..252350aebb5a 100644
--- a/drivers/video/bochs/bochs_hw.c
+++ b/drivers/video/bochs/bochs_hw.c
@@ -1,7 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 // SPDX-FileCopyrightText: Copyright (c) 2020 Ahmad Fatoum, Pengutronix
 /*
- *  PCI Driver for VGA with the Bochs VBE / QEMU stdvga extensions.
+ *  Driver for VGA with the Bochs VBE / QEMU stdvga extensions.
+ *
+ *  Based on the Linux v5.11-rc1 bochs-dispi DRM driver.
  */
 
 #include <common.h>
@@ -125,7 +127,7 @@ static int bochs_hw_load_edid(struct bochs *bochs)
 	/* check header to detect whenever edid support is enabled in qemu */
 	if (!edid_check_header(edid)) {
 		free(edid);
-		return -1;
+		return -EILSEQ;
 	}
 
 	for (i = EDID_HEADER_END + 1; i < EDID_LENGTH; i++)
diff --git a/drivers/video/bochs/bochs_hw.h b/drivers/video/bochs/bochs_hw.h
index 36c2cc1cc376..420b58f4dad6 100644
--- a/drivers/video/bochs/bochs_hw.h
+++ b/drivers/video/bochs/bochs_hw.h
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
 #ifndef BOCHS_HW_H
 #define BOCHS_HW_H
 
diff --git a/drivers/video/bochs/bochs_isa.c b/drivers/video/bochs/bochs_isa.c
index 7f75803baa0c..f273ac5f74a8 100644
--- a/drivers/video/bochs/bochs_isa.c
+++ b/drivers/video/bochs/bochs_isa.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 // SPDX-FileCopyrightText: Copyright (c) 2020 Ahmad Fatoum, Pengutronix
 /*
- *  ISA Driver for VGA with the Bochs VBE / QEMU stdvga extensions.
+ *  ISA driver entry point for VGA with the Bochs VBE / QEMU stdvga extensions.
  */
 
 #include <common.h>
diff --git a/drivers/video/bochs/bochs_pci.c b/drivers/video/bochs/bochs_pci.c
index 39f582029d35..28785e1c0667 100644
--- a/drivers/video/bochs/bochs_pci.c
+++ b/drivers/video/bochs/bochs_pci.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 // SPDX-FileCopyrightText: Copyright (c) 2020 Ahmad Fatoum, Pengutronix
 /*
- *  PCI Driver for VGA with the Bochs VBE / QEMU stdvga extensions.
+ *  PCI driver entry point for VGA with the Bochs VBE / QEMU stdvga extensions.
  */
 
 #include <common.h>
-- 
2.29.2



From a.fatoum at pengutronix.de  Mon Jan  4 04:33:27 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  4 Jan 2021 10:33:27 +0100
Subject: [PATCH] ARM: at91: constify struct at91_ddramc_register parameters
Message-ID: <20210104093327.5830-1-a.fatoum@pengutronix.de>

The SDRAM config passed as struct at91_ddramc_register is read-only,
so make it const everywhere to document and enforce this.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/mach-at91/ddramc_ll.c                       | 6 +++---
 arch/arm/mach-at91/include/mach/ddramc.h             | 6 +++---
 arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h | 2 +-
 arch/arm/mach-at91/include/mach/sama5d2_ll.h         | 2 +-
 arch/arm/mach-at91/sama5d2_ll.c                      | 2 +-
 5 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-at91/ddramc_ll.c b/arch/arm/mach-at91/ddramc_ll.c
index 4768fdcd6281..77d03720cca4 100644
--- a/arch/arm/mach-at91/ddramc_ll.c
+++ b/arch/arm/mach-at91/ddramc_ll.c
@@ -12,7 +12,7 @@
 
 void at91_ddram_initialize(void __iomem *base_address,
 			   void __iomem *ram_address,
-			   struct at91_ddramc_register *ddramc_config)
+			   const struct at91_ddramc_register *ddramc_config)
 {
 	unsigned long ba_offset;
 	unsigned long cr = 0;
@@ -235,7 +235,7 @@ void at91_ddram_initialize(void __iomem *base_address,
 
 void at91_lpddr2_sdram_initialize(void __iomem *base_address,
 				  void __iomem *ram_address,
-				  struct at91_ddramc_register *ddramc_config)
+				  const struct at91_ddramc_register *ddramc_config)
 {
 	unsigned long reg;
 
@@ -386,7 +386,7 @@ void at91_lpddr2_sdram_initialize(void __iomem *base_address,
 
 void at91_lpddr1_sdram_initialize(void __iomem *base_address,
 				  void __iomem *ram_address,
-				  struct at91_ddramc_register *ddramc_config)
+				  const struct at91_ddramc_register *ddramc_config)
 {
 	unsigned long ba_offset;
 
diff --git a/arch/arm/mach-at91/include/mach/ddramc.h b/arch/arm/mach-at91/include/mach/ddramc.h
index b929bf5f58e8..5d6f3a70b788 100644
--- a/arch/arm/mach-at91/include/mach/ddramc.h
+++ b/arch/arm/mach-at91/include/mach/ddramc.h
@@ -21,16 +21,16 @@ struct at91_ddramc_register {
 
 void at91_ddram_initialize(void __iomem *base_address,
 			   void __iomem *ram_address,
-			   struct at91_ddramc_register *ddramc_config);
+			   const struct at91_ddramc_register *ddramc_config);
 
 void at91_lpddr2_sdram_initialize(void __iomem *base_address,
 				  void __iomem *ram_address,
-				  struct at91_ddramc_register *ddramc_config);
+				  const struct at91_ddramc_register *ddramc_config);
 
 
 void at91_lpddr1_sdram_initialize(void __iomem *base_address,
 				  void __iomem *ram_address,
-				  struct at91_ddramc_register *ddramc_config);
+				  const struct at91_ddramc_register *ddramc_config);
 
 void __noreturn sama5d2_barebox_entry(unsigned int r4, void *boarddata);
 
diff --git a/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h b/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h
index 35c92c43fce8..6a75ac71fc35 100644
--- a/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h
+++ b/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h
@@ -11,7 +11,7 @@
 
 static inline void sama5d2_d1g_ddrconf(void) /* DDR2 1Gbit SDRAM */
 {
-	struct at91_ddramc_register conf = {
+	const struct at91_ddramc_register conf = {
 		.mdr = AT91_DDRC2_DBW_16_BITS | AT91_DDRC2_MD_DDR2_SDRAM,
 
 		.cr = AT91_DDRC2_NC_DDR10_SDR9 | AT91_DDRC2_NR_13 |
diff --git a/arch/arm/mach-at91/include/mach/sama5d2_ll.h b/arch/arm/mach-at91/include/mach/sama5d2_ll.h
index 96f3bc545284..244b1a706594 100644
--- a/arch/arm/mach-at91/include/mach/sama5d2_ll.h
+++ b/arch/arm/mach-at91/include/mach/sama5d2_ll.h
@@ -25,7 +25,7 @@ static inline void sama5d2_udelay_init(unsigned int msc)
 }
 
 
-void sama5d2_ddr2_init(struct at91_ddramc_register *ddramc_reg_config);
+void sama5d2_ddr2_init(const struct at91_ddramc_register *ddramc_reg_config);
 
 static inline int sama5d2_pmc_enable_generic_clock(unsigned int periph_id,
 						   unsigned int clk_source,
diff --git a/arch/arm/mach-at91/sama5d2_ll.c b/arch/arm/mach-at91/sama5d2_ll.c
index c3b50617778a..3366a50e8fba 100644
--- a/arch/arm/mach-at91/sama5d2_ll.c
+++ b/arch/arm/mach-at91/sama5d2_ll.c
@@ -18,7 +18,7 @@
 #define sama5d2_pmc_write(off, val) writel(val, SAMA5D2_BASE_PMC + off)
 #define sama5d2_pmc_read(off) readl(SAMA5D2_BASE_PMC + off)
 
-void sama5d2_ddr2_init(struct at91_ddramc_register *ddramc_reg_config)
+void sama5d2_ddr2_init(const struct at91_ddramc_register *ddramc_reg_config)
 {
 	unsigned int reg;
 
-- 
2.29.2



From a.fatoum at pengutronix.de  Mon Jan  4 04:34:32 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon,  4 Jan 2021 10:34:32 +0100
Subject: [PATCH master] ARM: at91: at91sam9x5: fix co-existance of
 erratum-aware and generic reset
Message-ID: <20210104093432.6257-1-a.fatoum@pengutronix.de>

We have a generic at91sam9 reset driver, but it's unaware of the
erratum on the at91sam9x5, which can prevent reboot from NAND due to
interference from SDRAM. The workaround is packing the powering down
of the DDR and the system reset into a single cache line and executing
that. This would be a bit tedious to add into the device tree probed
driver, thus:

 - Don't activate the work around if we are device-tree enabled, but
   have a newer SoC
 - Give the workaround a slightly higher priority, so it's taken instead
   of the generic DT driver

This fixes an issue of failing reset with the at91_multi_defconfig,
because both reset drivers have the same priority of 100.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/mach-at91/at91sam9x5.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
index 086e27a79f51..8266b512c999 100644
--- a/arch/arm/mach-at91/at91sam9x5.c
+++ b/arch/arm/mach-at91/at91sam9x5.c
@@ -11,10 +11,17 @@ static void at91sam9x5_restart(struct restart_handler *rst)
 			  IOMEM(AT91SAM9X5_BASE_RSTC + AT91_RSTC_CR));
 }
 
+static struct restart_handler restart;
+
 static int at91sam9x5_initialize(void)
 {
-	restart_handler_register_fn("soc", at91sam9x5_restart);
+	if (IS_ENABLED(CONFIG_OFDEVICE) && !of_machine_is_compatible("atmel,at91sam9x5"))
+		return 0;
+
+	restart.name = "soc";
+	restart.priority = 110;
+	restart.restart = at91sam9x5_restart;
 
-	return 0;
+	return restart_handler_register(&restart);
 }
 coredevice_initcall(at91sam9x5_initialize);
-- 
2.29.2



From sha at pengutronix.de  Tue Jan  5 07:02:06 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 5 Jan 2021 13:02:06 +0100
Subject: [PATCH master] ARM: at91: at91sam9x5: fix co-existance of
 erratum-aware and generic reset
In-Reply-To: <20210104093432.6257-1-a.fatoum@pengutronix.de>
References: <20210104093432.6257-1-a.fatoum@pengutronix.de>
Message-ID: <20210105120206.GB19063@pengutronix.de>

On Mon, Jan 04, 2021 at 10:34:32AM +0100, Ahmad Fatoum wrote:
> We have a generic at91sam9 reset driver, but it's unaware of the
> erratum on the at91sam9x5, which can prevent reboot from NAND due to
> interference from SDRAM. The workaround is packing the powering down
> of the DDR and the system reset into a single cache line and executing
> that. This would be a bit tedious to add into the device tree probed
> driver, thus:
> 
>  - Don't activate the work around if we are device-tree enabled, but
>    have a newer SoC
>  - Give the workaround a slightly higher priority, so it's taken instead
>    of the generic DT driver
> 
> This fixes an issue of failing reset with the at91_multi_defconfig,
> because both reset drivers have the same priority of 100.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  arch/arm/mach-at91/at91sam9x5.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c
> index 086e27a79f51..8266b512c999 100644
> --- a/arch/arm/mach-at91/at91sam9x5.c
> +++ b/arch/arm/mach-at91/at91sam9x5.c
> @@ -11,10 +11,17 @@ static void at91sam9x5_restart(struct restart_handler *rst)
>  			  IOMEM(AT91SAM9X5_BASE_RSTC + AT91_RSTC_CR));
>  }
>  
> +static struct restart_handler restart;
> +
>  static int at91sam9x5_initialize(void)
>  {
> -	restart_handler_register_fn("soc", at91sam9x5_restart);
> +	if (IS_ENABLED(CONFIG_OFDEVICE) && !of_machine_is_compatible("atmel,at91sam9x5"))
> +		return 0;
> +
> +	restart.name = "soc";
> +	restart.priority = 110;
> +	restart.restart = at91sam9x5_restart;
>  
> -	return 0;
> +	return restart_handler_register(&restart);
>  }
>  coredevice_initcall(at91sam9x5_initialize);
> -- 
> 2.29.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Jan  5 07:02:44 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 5 Jan 2021 13:02:44 +0100
Subject: [PATCH] ARM: at91: constify struct at91_ddramc_register parameters
In-Reply-To: <20210104093327.5830-1-a.fatoum@pengutronix.de>
References: <20210104093327.5830-1-a.fatoum@pengutronix.de>
Message-ID: <20210105120244.GC19063@pengutronix.de>

On Mon, Jan 04, 2021 at 10:33:27AM +0100, Ahmad Fatoum wrote:
> The SDRAM config passed as struct at91_ddramc_register is read-only,
> so make it const everywhere to document and enforce this.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  arch/arm/mach-at91/ddramc_ll.c                       | 6 +++---
>  arch/arm/mach-at91/include/mach/ddramc.h             | 6 +++---
>  arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h | 2 +-
>  arch/arm/mach-at91/include/mach/sama5d2_ll.h         | 2 +-
>  arch/arm/mach-at91/sama5d2_ll.c                      | 2 +-
>  5 files changed, 9 insertions(+), 9 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/mach-at91/ddramc_ll.c b/arch/arm/mach-at91/ddramc_ll.c
> index 4768fdcd6281..77d03720cca4 100644
> --- a/arch/arm/mach-at91/ddramc_ll.c
> +++ b/arch/arm/mach-at91/ddramc_ll.c
> @@ -12,7 +12,7 @@
>  
>  void at91_ddram_initialize(void __iomem *base_address,
>  			   void __iomem *ram_address,
> -			   struct at91_ddramc_register *ddramc_config)
> +			   const struct at91_ddramc_register *ddramc_config)
>  {
>  	unsigned long ba_offset;
>  	unsigned long cr = 0;
> @@ -235,7 +235,7 @@ void at91_ddram_initialize(void __iomem *base_address,
>  
>  void at91_lpddr2_sdram_initialize(void __iomem *base_address,
>  				  void __iomem *ram_address,
> -				  struct at91_ddramc_register *ddramc_config)
> +				  const struct at91_ddramc_register *ddramc_config)
>  {
>  	unsigned long reg;
>  
> @@ -386,7 +386,7 @@ void at91_lpddr2_sdram_initialize(void __iomem *base_address,
>  
>  void at91_lpddr1_sdram_initialize(void __iomem *base_address,
>  				  void __iomem *ram_address,
> -				  struct at91_ddramc_register *ddramc_config)
> +				  const struct at91_ddramc_register *ddramc_config)
>  {
>  	unsigned long ba_offset;
>  
> diff --git a/arch/arm/mach-at91/include/mach/ddramc.h b/arch/arm/mach-at91/include/mach/ddramc.h
> index b929bf5f58e8..5d6f3a70b788 100644
> --- a/arch/arm/mach-at91/include/mach/ddramc.h
> +++ b/arch/arm/mach-at91/include/mach/ddramc.h
> @@ -21,16 +21,16 @@ struct at91_ddramc_register {
>  
>  void at91_ddram_initialize(void __iomem *base_address,
>  			   void __iomem *ram_address,
> -			   struct at91_ddramc_register *ddramc_config);
> +			   const struct at91_ddramc_register *ddramc_config);
>  
>  void at91_lpddr2_sdram_initialize(void __iomem *base_address,
>  				  void __iomem *ram_address,
> -				  struct at91_ddramc_register *ddramc_config);
> +				  const struct at91_ddramc_register *ddramc_config);
>  
>  
>  void at91_lpddr1_sdram_initialize(void __iomem *base_address,
>  				  void __iomem *ram_address,
> -				  struct at91_ddramc_register *ddramc_config);
> +				  const struct at91_ddramc_register *ddramc_config);
>  
>  void __noreturn sama5d2_barebox_entry(unsigned int r4, void *boarddata);
>  
> diff --git a/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h b/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h
> index 35c92c43fce8..6a75ac71fc35 100644
> --- a/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h
> +++ b/arch/arm/mach-at91/include/mach/sama5d2-sip-ddramc.h
> @@ -11,7 +11,7 @@
>  
>  static inline void sama5d2_d1g_ddrconf(void) /* DDR2 1Gbit SDRAM */
>  {
> -	struct at91_ddramc_register conf = {
> +	const struct at91_ddramc_register conf = {
>  		.mdr = AT91_DDRC2_DBW_16_BITS | AT91_DDRC2_MD_DDR2_SDRAM,
>  
>  		.cr = AT91_DDRC2_NC_DDR10_SDR9 | AT91_DDRC2_NR_13 |
> diff --git a/arch/arm/mach-at91/include/mach/sama5d2_ll.h b/arch/arm/mach-at91/include/mach/sama5d2_ll.h
> index 96f3bc545284..244b1a706594 100644
> --- a/arch/arm/mach-at91/include/mach/sama5d2_ll.h
> +++ b/arch/arm/mach-at91/include/mach/sama5d2_ll.h
> @@ -25,7 +25,7 @@ static inline void sama5d2_udelay_init(unsigned int msc)
>  }
>  
>  
> -void sama5d2_ddr2_init(struct at91_ddramc_register *ddramc_reg_config);
> +void sama5d2_ddr2_init(const struct at91_ddramc_register *ddramc_reg_config);
>  
>  static inline int sama5d2_pmc_enable_generic_clock(unsigned int periph_id,
>  						   unsigned int clk_source,
> diff --git a/arch/arm/mach-at91/sama5d2_ll.c b/arch/arm/mach-at91/sama5d2_ll.c
> index c3b50617778a..3366a50e8fba 100644
> --- a/arch/arm/mach-at91/sama5d2_ll.c
> +++ b/arch/arm/mach-at91/sama5d2_ll.c
> @@ -18,7 +18,7 @@
>  #define sama5d2_pmc_write(off, val) writel(val, SAMA5D2_BASE_PMC + off)
>  #define sama5d2_pmc_read(off) readl(SAMA5D2_BASE_PMC + off)
>  
> -void sama5d2_ddr2_init(struct at91_ddramc_register *ddramc_reg_config)
> +void sama5d2_ddr2_init(const struct at91_ddramc_register *ddramc_reg_config)
>  {
>  	unsigned int reg;
>  
> -- 
> 2.29.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Jan  5 07:19:17 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 5 Jan 2021 13:19:17 +0100
Subject: [PATCH 3/4] video: implement bochs dispi / QEMU VGA driver for
 PCI and ISA
In-Reply-To: <20210101225228.2166084-3-ahmad@a3f.at>
References: <20210101225228.2166084-1-ahmad@a3f.at>
 <20210101225228.2166084-3-ahmad@a3f.at>
Message-ID: <20210105121917.GD19063@pengutronix.de>

On Fri, Jan 01, 2021 at 11:52:27PM +0100, Ahmad Fatoum wrote:
> All SVGA devices in Qemu, except for Cirrus, support the bochs display
> interface, which is very easy to set up. Add a driver for it.
> 
> This has been tested with:
> 
>  PCI: qemu-system-mips(el) -device VGA + barebox qemu-malta_defconfig
>  ISA: qemu-system-x86_64 -device isa-vga + barebox efi_defconfig
> 
> Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>

I gave this a shot on MIPS qemu and indeed, works for me as well.

Applied this series, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Jan  5 07:55:27 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 5 Jan 2021 13:55:27 +0100
Subject: [PATCH] driver: provide dev_request_mem_resource_by_name() helper
In-Reply-To: <20210101225139.2165289-1-ahmad@a3f.at>
References: <20210101225139.2165289-1-ahmad@a3f.at>
Message-ID: <20210105125527.GE19063@pengutronix.de>

On Fri, Jan 01, 2021 at 11:51:39PM +0100, Ahmad Fatoum wrote:
> There are both dev_request_mem_resource() and dev_request_mem_region(),
> which return the struct resource and a IOMEM(.start) respectively.
> 
> There is only dev_request_mem_region_by_name(), but
> no dev_request_mem_resource_by_name(), so add the latter for symmetry.
> 
> Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
> ---
>  drivers/base/driver.c | 12 ++++++++++--
>  include/driver.h      |  5 +++++
>  2 files changed, 15 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/base/driver.c b/drivers/base/driver.c
> index 3205bbc3c33b..6763bbc6f512 100644
> --- a/drivers/base/driver.c
> +++ b/drivers/base/driver.c
> @@ -372,7 +372,7 @@ struct resource *dev_get_resource_by_name(struct device_d *dev,
>  	return ERR_PTR(-ENOENT);
>  }
>  
> -void __iomem *dev_request_mem_region_by_name(struct device_d *dev, const char *name)
> +struct resource *dev_request_mem_resource_by_name(struct device_d *dev, const char *name)
>  {
>  	struct resource *res;
>  
> @@ -380,7 +380,15 @@ void __iomem *dev_request_mem_region_by_name(struct device_d *dev, const char *n
>  	if (IS_ERR(res))
>  		return ERR_CAST(res);
>  
> -	res = request_iomem_region(dev_name(dev), res->start, res->end);
> +	return request_iomem_region(dev_name(dev), res->start, res->end);
> +}
> +EXPORT_SYMBOL(dev_request_mem_resource_by_name);
> +
> +void __iomem *dev_request_mem_region_by_name(struct device_d *dev, const char *name)
> +{
> +	struct resource *res;
> +
> +	res = dev_request_mem_resource_by_name(dev, name);
>  	if (IS_ERR(res))
>  		return ERR_CAST(res);
>  
> diff --git a/include/driver.h b/include/driver.h
> index e2886d051d4f..0d43b3614863 100644
> --- a/include/driver.h
> +++ b/include/driver.h
> @@ -214,6 +214,11 @@ void __iomem *dev_request_mem_region(struct device_d *dev, int num);
>   */
>  struct resource *dev_request_mem_resource(struct device_d *dev, int num);
>  
> +/*
> + * exlusively request resource 'name' for a device
> + */
> +struct resource *dev_request_mem_resource_by_name(struct device_d *dev, const char *name);
> +
>  /*
>   * exlusively request register base 'num' for a device
>   * will return NULL on error
> -- 
> 2.29.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Jan  5 08:35:07 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 5 Jan 2021 14:35:07 +0100
Subject: [PATCH] ARM: imx8mq: reclock ARM PLL to 800MHz
In-Reply-To: <20201229202328.13857-1-dev@lynxeye.de>
References: <20201229202328.13857-1-dev@lynxeye.de>
Message-ID: <20210105133507.GF19063@pengutronix.de>

On Tue, Dec 29, 2020 at 09:23:28PM +0100, Lucas Stach wrote:
> The BootROM sets up the ARM PLL to run at 1.6GHz and then uses the
> divider after the PLL the achieve a CPU clock rate of 800MHz. New Linux
> kernels (>= 5.8) switch to a clock path that bypasses the divider, as
> the divider should not be used for CPU clock frequencies >1GHz. If the
> BootROM setup is left unchanged this causes the CPU clock to jump to
> the full 1.6GHz until CPUfreq takes over and reprograms the PLL. This
> rate is outside of the chip specification and leads to crashes.
> 
> Fix this by reclocking the ARM PLL to 800MHz.
> 
> Signed-off-by: Lucas Stach <dev at lynxeye.de>
> ---
>  arch/arm/dts/imx8mq.dtsi | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/dts/imx8mq.dtsi b/arch/arm/dts/imx8mq.dtsi
> index ec8347f38fa8..e56cdfe1308e 100644
> --- a/arch/arm/dts/imx8mq.dtsi
> +++ b/arch/arm/dts/imx8mq.dtsi
> @@ -17,7 +17,9 @@
>  			  <&clk IMX8MQ_CLK_USDHC2>,
>  			  <&clk IMX8MQ_CLK_ENET_AXI>,
>  			  <&clk IMX8MQ_CLK_ENET_TIMER>,
> -			  <&clk IMX8MQ_CLK_ENET_REF>;
> +			  <&clk IMX8MQ_CLK_ENET_REF>,
> +			  <&clk IMX8MQ_ARM_PLL>,
> +			  <&clk IMX8MQ_CLK_A53_DIV>;
>  
>  	assigned-clock-parents =  <&clk IMX8MQ_SYS1_PLL_400M>,
>  				  <&clk IMX8MQ_SYS1_PLL_400M>,
> @@ -29,5 +31,7 @@
>  			       <200000000>,
>  			       <266000000>,
>  			       <25000000>,
> -			       <125000000>;
> +			       <125000000>,
> +			       <800000000>,
> +			       <800000000>;
>  };
> -- 
> 2.29.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Jan  5 08:36:26 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 5 Jan 2021 14:36:26 +0100
Subject: [PATCH] video: sdl: delete useless debug output
In-Reply-To: <20201229123433.1054113-1-ahmad@a3f.at>
References: <20201229123433.1054113-1-ahmad@a3f.at>
Message-ID: <20210105133626.GG19063@pengutronix.de>

On Tue, Dec 29, 2020 at 01:34:33PM +0100, Ahmad Fatoum wrote:
> The information on the color mode is only populated at framebuffer
> enable time. At probe time, it's all zero, so it's useless to print it
> out. Drop it.
> 
> Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
> ---
>  drivers/video/sdl.c | 9 ---------
>  1 file changed, 9 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/video/sdl.c b/drivers/video/sdl.c
> index 8f5b409efb4a..9811b2cf128e 100644
> --- a/drivers/video/sdl.c
> +++ b/drivers/video/sdl.c
> @@ -59,15 +59,6 @@ static int sdlfb_probe(struct device_d *dev)
>  	fb->screen_base = xzalloc(fb->xres * fb->yres *
>  				  fb->bits_per_pixel >> 3);
>  
> -	dev_dbg(dev, "red: length = %d, offset = %d\n",
> -		fb->red.length, fb->red.offset);
> -	dev_dbg(dev, "green: length = %d, offset = %d\n",
> -		fb->green.length, fb->green.offset);
> -	dev_dbg(dev, "blue: length = %d, offset = %d\n",
> -		fb->blue.length, fb->blue.offset);
> -	dev_dbg(dev, "transp: length = %d, offset = %d\n",
> -		fb->transp.length, fb->transp.offset);
> -
>  	/* add runtime hardware info */
>  	dev->priv = fb;
>  
> -- 
> 2.29.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Jan  5 08:38:12 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 5 Jan 2021 14:38:12 +0100
Subject: [PATCH] include: <linux/math64.h>: sync with upstream
In-Reply-To: <20201229123254.1053519-1-ahmad@a3f.at>
References: <20201229123254.1053519-1-ahmad@a3f.at>
Message-ID: <20210105133811.GH19063@pengutronix.de>

On Tue, Dec 29, 2020 at 01:32:54PM +0100, Ahmad Fatoum wrote:
> The header implements definitions for the 64-bit division helpers
> on 64-bit builds only. For 32-bit builds, it can only provide prototypes
> and the actual implementation will need to come from elsewhere.
> 
> We didn't have any out-of-line definitions in barebox with the result
> that functions like div_s64_rem() were so far only usable in
> 64-bit barebox builds. On 32-bit builds, they would result in a linker
> error.
> 
> Import the Linux v5.11-rc1 generic out-of-line 64-bit math on 32-bit
> implementation to fix this. While at it, synchronize the header to
> reduce diff to upstream.
> 
> Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
> ---
>  include/linux/math64.h | 211 +++++++++++++++++++++++++++++++++++-
>  lib/Makefile           |   1 +
>  lib/math/Makefile      |   1 +
>  lib/math/div64.c       | 235 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 443 insertions(+), 5 deletions(-)
>  create mode 100644 lib/math/Makefile
>  create mode 100644 lib/math/div64.c

Applied, thanks

Sascha

> 
> diff --git a/include/linux/math64.h b/include/linux/math64.h
> index 71dd6d7109b7..e8b737e70e50 100644
> --- a/include/linux/math64.h
> +++ b/include/linux/math64.h
> @@ -1,3 +1,4 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
>  #ifndef _LINUX_MATH64_H
>  #define _LINUX_MATH64_H
>  
> @@ -6,10 +7,16 @@
>  
>  #if BITS_PER_LONG == 64
>  
> -#define div64_long(x,y) div64_s64((x),(y))
> +#define div64_long(x, y) div64_s64((x), (y))
> +#define div64_ul(x, y)   div64_u64((x), (y))
>  
>  /**
>   * div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
> + * @dividend: unsigned 64bit dividend
> + * @divisor: unsigned 32bit divisor
> + * @remainder: pointer to unsigned 32bit remainder
> + *
> + * Return: sets ``*remainder``, then returns dividend / divisor
>   *
>   * This is commonly provided by 32bit archs to provide an optimized 64bit
>   * divide.
> @@ -20,8 +27,13 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
>  	return dividend / divisor;
>  }
>  
> -/**
> +/*
>   * div_s64_rem - signed 64bit divide with 32bit divisor with remainder
> + * @dividend: signed 64bit dividend
> + * @divisor: signed 32bit divisor
> + * @remainder: pointer to signed 32bit remainder
> + *
> + * Return: sets ``*remainder``, then returns dividend / divisor
>   */
>  static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
>  {
> @@ -29,16 +41,38 @@ static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
>  	return dividend / divisor;
>  }
>  
> -/**
> +/*
> + * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
> + * @dividend: unsigned 64bit dividend
> + * @divisor: unsigned 64bit divisor
> + * @remainder: pointer to unsigned 64bit remainder
> + *
> + * Return: sets ``*remainder``, then returns dividend / divisor
> + */
> +static inline u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
> +{
> +	*remainder = dividend % divisor;
> +	return dividend / divisor;
> +}
> +
> +/*
>   * div64_u64 - unsigned 64bit divide with 64bit divisor
> + * @dividend: unsigned 64bit dividend
> + * @divisor: unsigned 64bit divisor
> + *
> + * Return: dividend / divisor
>   */
>  static inline u64 div64_u64(u64 dividend, u64 divisor)
>  {
>  	return dividend / divisor;
>  }
>  
> -/**
> +/*
>   * div64_s64 - signed 64bit divide with 64bit divisor
> + * @dividend: signed 64bit dividend
> + * @divisor: signed 64bit divisor
> + *
> + * Return: dividend / divisor
>   */
>  static inline s64 div64_s64(s64 dividend, s64 divisor)
>  {
> @@ -47,7 +81,8 @@ static inline s64 div64_s64(s64 dividend, s64 divisor)
>  
>  #elif BITS_PER_LONG == 32
>  
> -#define div64_long(x,y) div_s64((x),(y))
> +#define div64_long(x, y) div_s64((x), (y))
> +#define div64_ul(x, y)   div_u64((x), (y))
>  
>  #ifndef div_u64_rem
>  static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
> @@ -61,6 +96,10 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
>  extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
>  #endif
>  
> +#ifndef div64_u64_rem
> +extern u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder);
> +#endif
> +
>  #ifndef div64_u64
>  extern u64 div64_u64(u64 dividend, u64 divisor);
>  #endif
> @@ -73,6 +112,8 @@ extern s64 div64_s64(s64 dividend, s64 divisor);
>  
>  /**
>   * div_u64 - unsigned 64bit divide with 32bit divisor
> + * @dividend: unsigned 64bit dividend
> + * @divisor: unsigned 32bit divisor
>   *
>   * This is the most common 64bit divide and should be used if possible,
>   * as many 32bit archs can optimize this variant better than a full 64bit
> @@ -88,6 +129,8 @@ static inline u64 div_u64(u64 dividend, u32 divisor)
>  
>  /**
>   * div_s64 - signed 64bit divide with 32bit divisor
> + * @dividend: signed 64bit dividend
> + * @divisor: signed 32bit divisor
>   */
>  #ifndef div_s64
>  static inline s64 div_s64(s64 dividend, s32 divisor)
> @@ -99,6 +142,164 @@ static inline s64 div_s64(s64 dividend, s32 divisor)
>  
>  u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder);
>  
> +#ifndef mul_u32_u32
> +/*
> + * Many a GCC version messes this up and generates a 64x64 mult :-(
> + */
> +static inline u64 mul_u32_u32(u32 a, u32 b)
> +{
> +	return (u64)a * b;
> +}
> +#endif
> +
> +#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
> +
> +#ifndef mul_u64_u32_shr
> +static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
> +{
> +	return (u64)(((unsigned __int128)a * mul) >> shift);
> +}
> +#endif /* mul_u64_u32_shr */
> +
> +#ifndef mul_u64_u64_shr
> +static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
> +{
> +	return (u64)(((unsigned __int128)a * mul) >> shift);
> +}
> +#endif /* mul_u64_u64_shr */
> +
> +#else
> +
> +#ifndef mul_u64_u32_shr
> +static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
> +{
> +	u32 ah, al;
> +	u64 ret;
> +
> +	al = a;
> +	ah = a >> 32;
> +
> +	ret = mul_u32_u32(al, mul) >> shift;
> +	if (ah)
> +		ret += mul_u32_u32(ah, mul) << (32 - shift);
> +
> +	return ret;
> +}
> +#endif /* mul_u64_u32_shr */
> +
> +#ifndef mul_u64_u64_shr
> +static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift)
> +{
> +	union {
> +		u64 ll;
> +		struct {
> +#ifdef __BIG_ENDIAN
> +			u32 high, low;
> +#else
> +			u32 low, high;
> +#endif
> +		} l;
> +	} rl, rm, rn, rh, a0, b0;
> +	u64 c;
> +
> +	a0.ll = a;
> +	b0.ll = b;
> +
> +	rl.ll = mul_u32_u32(a0.l.low, b0.l.low);
> +	rm.ll = mul_u32_u32(a0.l.low, b0.l.high);
> +	rn.ll = mul_u32_u32(a0.l.high, b0.l.low);
> +	rh.ll = mul_u32_u32(a0.l.high, b0.l.high);
> +
> +	/*
> +	 * Each of these lines computes a 64-bit intermediate result into "c",
> +	 * starting at bits 32-95.  The low 32-bits go into the result of the
> +	 * multiplication, the high 32-bits are carried into the next step.
> +	 */
> +	rl.l.high = c = (u64)rl.l.high + rm.l.low + rn.l.low;
> +	rh.l.low = c = (c >> 32) + rm.l.high + rn.l.high + rh.l.low;
> +	rh.l.high = (c >> 32) + rh.l.high;
> +
> +	/*
> +	 * The 128-bit result of the multiplication is in rl.ll and rh.ll,
> +	 * shift it right and throw away the high part of the result.
> +	 */
> +	if (shift == 0)
> +		return rl.ll;
> +	if (shift < 64)
> +		return (rl.ll >> shift) | (rh.ll << (64 - shift));
> +	return rh.ll >> (shift & 63);
> +}
> +#endif /* mul_u64_u64_shr */
> +
> +#endif
> +
> +#ifndef mul_u64_u32_div
> +static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
> +{
> +	union {
> +		u64 ll;
> +		struct {
> +#ifdef __BIG_ENDIAN
> +			u32 high, low;
> +#else
> +			u32 low, high;
> +#endif
> +		} l;
> +	} u, rl, rh;
> +
> +	u.ll = a;
> +	rl.ll = mul_u32_u32(u.l.low, mul);
> +	rh.ll = mul_u32_u32(u.l.high, mul) + rl.l.high;
> +
> +	/* Bits 32-63 of the result will be in rh.l.low. */
> +	rl.l.high = do_div(rh.ll, divisor);
> +
> +	/* Bits 0-31 of the result will be in rl.l.low.	*/
> +	do_div(rl.ll, divisor);
> +
> +	rl.l.high = rh.l.low;
> +	return rl.ll;
> +}
> +#endif /* mul_u64_u32_div */
> +
> +u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div);
> +
> +#define DIV64_U64_ROUND_UP(ll, d)	\
> +	({ u64 _tmp = (d); div64_u64((ll) + _tmp - 1, _tmp); })
> +
> +/**
> + * DIV64_U64_ROUND_CLOSEST - unsigned 64bit divide with 64bit divisor rounded to nearest integer
> + * @dividend: unsigned 64bit dividend
> + * @divisor: unsigned 64bit divisor
> + *
> + * Divide unsigned 64bit dividend by unsigned 64bit divisor
> + * and round to closest integer.
> + *
> + * Return: dividend / divisor rounded to nearest integer
> + */
> +#define DIV64_U64_ROUND_CLOSEST(dividend, divisor)	\
> +	({ u64 _tmp = (divisor); div64_u64((dividend) + _tmp / 2, _tmp); })
> +
> +/*
> + * DIV_S64_ROUND_CLOSEST - signed 64bit divide with 32bit divisor rounded to nearest integer
> + * @dividend: signed 64bit dividend
> + * @divisor: signed 32bit divisor
> + *
> + * Divide signed 64bit dividend by signed 32bit divisor
> + * and round to closest integer.
> + *
> + * Return: dividend / divisor rounded to nearest integer
> + */
> +#define DIV_S64_ROUND_CLOSEST(dividend, divisor)(	\
> +{							\
> +	s64 __x = (dividend);				\
> +	s32 __d = (divisor);				\
> +	((__x > 0) == (__d > 0)) ?			\
> +		div_s64((__x + (__d / 2)), __d) :	\
> +		div_s64((__x - (__d / 2)), __d);	\
> +}							\
> +)
> +
>  static __always_inline u32
>  __iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
>  {
> diff --git a/lib/Makefile b/lib/Makefile
> index ba6af6f2ab24..9c6f4133d77c 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -25,6 +25,7 @@ obj-y			+= cmdlinepart.o
>  obj-y			+= recursive_action.o
>  obj-y			+= make_directory.o
>  obj-y			+= math.o
> +obj-y			+= math/
>  obj-$(CONFIG_XXHASH)	+= xxhash.o
>  obj-$(CONFIG_BZLIB)	+= decompress_bunzip2.o
>  obj-$(CONFIG_ZLIB)	+= decompress_inflate.o zlib_inflate/
> diff --git a/lib/math/Makefile b/lib/math/Makefile
> new file mode 100644
> index 000000000000..3341a8e4744b
> --- /dev/null
> +++ b/lib/math/Makefile
> @@ -0,0 +1 @@
> +obj-y += div64.o
> diff --git a/lib/math/div64.c b/lib/math/div64.c
> new file mode 100644
> index 000000000000..507de8216a3e
> --- /dev/null
> +++ b/lib/math/div64.c
> @@ -0,0 +1,235 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2003 Bernardo Innocenti <bernie at develer.com>
> + *
> + * Based on former do_div() implementation from asm-parisc/div64.h:
> + *	Copyright (C) 1999 Hewlett-Packard Co
> + *	Copyright (C) 1999 David Mosberger-Tang <davidm at hpl.hp.com>
> + *
> + *
> + * Generic C version of 64bit/32bit division and modulo, with
> + * 64bit result and 32bit remainder.
> + *
> + * The fast case for (n>>32 == 0) is handled inline by do_div().
> + *
> + * Code generated for this function might be very inefficient
> + * for some CPUs. __div64_32() can be overridden by linking arch-specific
> + * assembly versions such as arch/ppc/lib/div64.S and arch/sh/lib/div64.S
> + * or by defining a preprocessor macro in arch/include/asm/div64.h.
> + */
> +
> +#include <linux/bitops.h>
> +#include <linux/export.h>
> +#include <linux/kernel.h>
> +#include <linux/math64.h>
> +#include <linux/log2.h>
> +
> +/* Not needed on 64bit architectures */
> +#if BITS_PER_LONG == 32
> +
> +#ifndef __div64_32
> +uint32_t __attribute__((weak)) __div64_32(uint64_t *n, uint32_t base)
> +{
> +	uint64_t rem = *n;
> +	uint64_t b = base;
> +	uint64_t res, d = 1;
> +	uint32_t high = rem >> 32;
> +
> +	/* Reduce the thing a bit first */
> +	res = 0;
> +	if (high >= base) {
> +		high /= base;
> +		res = (uint64_t) high << 32;
> +		rem -= (uint64_t) (high*base) << 32;
> +	}
> +
> +	while ((int64_t)b > 0 && b < rem) {
> +		b = b+b;
> +		d = d+d;
> +	}
> +
> +	do {
> +		if (rem >= b) {
> +			rem -= b;
> +			res += d;
> +		}
> +		b >>= 1;
> +		d >>= 1;
> +	} while (d);
> +
> +	*n = res;
> +	return rem;
> +}
> +EXPORT_SYMBOL(__div64_32);
> +#endif
> +
> +/**
> + * div_s64_rem - signed 64bit divide with 64bit divisor and remainder
> + * @dividend:	64bit dividend
> + * @divisor:	64bit divisor
> + * @remainder:  64bit remainder
> + */
> +#ifndef div_s64_rem
> +s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
> +{
> +	u64 quotient;
> +
> +	if (dividend < 0) {
> +		quotient = div_u64_rem(-dividend, abs(divisor), (u32 *)remainder);
> +		*remainder = -*remainder;
> +		if (divisor > 0)
> +			quotient = -quotient;
> +	} else {
> +		quotient = div_u64_rem(dividend, abs(divisor), (u32 *)remainder);
> +		if (divisor < 0)
> +			quotient = -quotient;
> +	}
> +	return quotient;
> +}
> +EXPORT_SYMBOL(div_s64_rem);
> +#endif
> +
> +/**
> + * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
> + * @dividend:	64bit dividend
> + * @divisor:	64bit divisor
> + * @remainder:  64bit remainder
> + *
> + * This implementation is a comparable to algorithm used by div64_u64.
> + * But this operation, which includes math for calculating the remainder,
> + * is kept distinct to avoid slowing down the div64_u64 operation on 32bit
> + * systems.
> + */
> +#ifndef div64_u64_rem
> +u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
> +{
> +	u32 high = divisor >> 32;
> +	u64 quot;
> +
> +	if (high == 0) {
> +		u32 rem32;
> +		quot = div_u64_rem(dividend, divisor, &rem32);
> +		*remainder = rem32;
> +	} else {
> +		int n = fls(high);
> +		quot = div_u64(dividend >> n, divisor >> n);
> +
> +		if (quot != 0)
> +			quot--;
> +
> +		*remainder = dividend - quot * divisor;
> +		if (*remainder >= divisor) {
> +			quot++;
> +			*remainder -= divisor;
> +		}
> +	}
> +
> +	return quot;
> +}
> +EXPORT_SYMBOL(div64_u64_rem);
> +#endif
> +
> +/**
> + * div64_u64 - unsigned 64bit divide with 64bit divisor
> + * @dividend:	64bit dividend
> + * @divisor:	64bit divisor
> + *
> + * This implementation is a modified version of the algorithm proposed
> + * by the book 'Hacker's Delight'.  The original source and full proof
> + * can be found here and is available for use without restriction.
> + *
> + * 'http://www.hackersdelight.org/hdcodetxt/divDouble.c.txt'
> + */
> +#ifndef div64_u64
> +u64 div64_u64(u64 dividend, u64 divisor)
> +{
> +	u32 high = divisor >> 32;
> +	u64 quot;
> +
> +	if (high == 0) {
> +		quot = div_u64(dividend, divisor);
> +	} else {
> +		int n = fls(high);
> +		quot = div_u64(dividend >> n, divisor >> n);
> +
> +		if (quot != 0)
> +			quot--;
> +		if ((dividend - quot * divisor) >= divisor)
> +			quot++;
> +	}
> +
> +	return quot;
> +}
> +EXPORT_SYMBOL(div64_u64);
> +#endif
> +
> +/**
> + * div64_s64 - signed 64bit divide with 64bit divisor
> + * @dividend:	64bit dividend
> + * @divisor:	64bit divisor
> + */
> +#ifndef div64_s64
> +s64 div64_s64(s64 dividend, s64 divisor)
> +{
> +	s64 quot, t;
> +
> +	quot = div64_u64(abs(dividend), abs(divisor));
> +	t = (dividend ^ divisor) >> 63;
> +
> +	return (quot ^ t) - t;
> +}
> +EXPORT_SYMBOL(div64_s64);
> +#endif
> +
> +#endif /* BITS_PER_LONG == 32 */
> +
> +/*
> + * Iterative div/mod for use when dividend is not expected to be much
> + * bigger than divisor.
> + */
> +u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
> +{
> +	return __iter_div_u64_rem(dividend, divisor, remainder);
> +}
> +EXPORT_SYMBOL(iter_div_u64_rem);
> +
> +#ifndef mul_u64_u64_div_u64
> +u64 mul_u64_u64_div_u64(u64 a, u64 b, u64 c)
> +{
> +	u64 res = 0, div, rem;
> +	int shift;
> +
> +	/* can a * b overflow ? */
> +	if (ilog2(a) + ilog2(b) > 62) {
> +		/*
> +		 * (b * a) / c is equal to
> +		 *
> +		 *      (b / c) * a +
> +		 *      (b % c) * a / c
> +		 *
> +		 * if nothing overflows. Can the 1st multiplication
> +		 * overflow? Yes, but we do not care: this can only
> +		 * happen if the end result can't fit in u64 anyway.
> +		 *
> +		 * So the code below does
> +		 *
> +		 *      res = (b / c) * a;
> +		 *      b = b % c;
> +		 */
> +		div = div64_u64_rem(b, c, &rem);
> +		res = div * a;
> +		b = rem;
> +
> +		shift = ilog2(a) + ilog2(b) - 62;
> +		if (shift > 0) {
> +			/* drop precision */
> +			b >>= shift;
> +			c >>= shift;
> +			if (!c)
> +				return res;
> +		}
> +	}
> +
> +	return res + div64_u64(a * b, c);
> +}
> +#endif
> -- 
> 2.29.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan  6 03:47:40 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 6 Jan 2021 09:47:40 +0100
Subject: [PATCH 1/5] ddr: imx8m: implement i.MX8MQ support
In-Reply-To: <20201227215042.101009-1-dev@lynxeye.de>
References: <20201227215042.101009-1-dev@lynxeye.de>
Message-ID: <20210106084740.GJ19063@pengutronix.de>

On Sun, Dec 27, 2020 at 10:50:38PM +0100, Lucas Stach wrote:
> The i.MX8MQ uses a different PLL type than the later i.MX8M family
> members, so the PLL setup did not actually work on this SoC. In U-Boot
> the used PLL setup routine is a compile time decision. As we want
> our DRAM init code to work for multi-image builds, this passes the
> SoC type through to the PLL init, so we can use the correct setup
> routine depending on the SoC we are running on.
> 
> Signed-off-by: Lucas Stach <dev at lynxeye.de>
> ---
>  drivers/ddr/imx8m/ddr_init.c     |   4 +-
>  drivers/ddr/imx8m/ddrphy_train.c |   4 +-
>  drivers/ddr/imx8m/ddrphy_utils.c | 107 ++++++++++++++++++++++++++++---
>  include/soc/imx8m/ddr.h          |   4 +-
>  4 files changed, 104 insertions(+), 15 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/ddr/imx8m/ddr_init.c b/drivers/ddr/imx8m/ddr_init.c
> index 1cd7b7406dc7..34da44af6446 100644
> --- a/drivers/ddr/imx8m/ddr_init.c
> +++ b/drivers/ddr/imx8m/ddr_init.c
> @@ -62,7 +62,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
>  
>  	initial_drate = dram_timing->fsp_msg[0].drate;
>  	/* default to the frequency point 0 clock */
> -	ddrphy_init_set_dfi_clk(initial_drate);
> +	ddrphy_init_set_dfi_clk(initial_drate, type);
>  
>  	/* D-aasert the presetn */
>  	reg32_write(src_ddrc_rcr, 0x8F000006);
> @@ -115,7 +115,7 @@ static int imx8m_ddr_init(struct dram_timing_info *dram_timing,
>  	 */
>  	pr_debug("ddrphy config start\n");
>  
> -	ret = ddr_cfg_phy(dram_timing);
> +	ret = ddr_cfg_phy(dram_timing, type);
>  	if (ret)
>  		return ret;
>  
> diff --git a/drivers/ddr/imx8m/ddrphy_train.c b/drivers/ddr/imx8m/ddrphy_train.c
> index 9280c853aa1c..a4677f903c6b 100644
> --- a/drivers/ddr/imx8m/ddrphy_train.c
> +++ b/drivers/ddr/imx8m/ddrphy_train.c
> @@ -31,7 +31,7 @@ void ddr_load_train_code(enum fw_type type)
>  			       DDRC_PHY_DMEM, dmem, dsize);
>  }
>  
> -int ddr_cfg_phy(struct dram_timing_info *dram_timing)
> +int ddr_cfg_phy(struct dram_timing_info *dram_timing, enum ddrc_type type)
>  {
>  	struct dram_cfg_param *dram_cfg;
>  	struct dram_fsp_msg *fsp_msg;
> @@ -54,7 +54,7 @@ int ddr_cfg_phy(struct dram_timing_info *dram_timing)
>  	for (i = 0; i < dram_timing->fsp_msg_num; i++) {
>  		pr_debug("DRAM PHY training for %dMTS\n", fsp_msg->drate);
>  		/* set dram PHY input clocks to desired frequency */
> -		ddrphy_init_set_dfi_clk(fsp_msg->drate);
> +		ddrphy_init_set_dfi_clk(fsp_msg->drate, type);
>  
>  		/* load the dram training firmware image */
>  		dwc_ddrphy_apb_wr(0xd0000, 0x0);
> diff --git a/drivers/ddr/imx8m/ddrphy_utils.c b/drivers/ddr/imx8m/ddrphy_utils.c
> index c48372491015..9a4e1a22ee5e 100644
> --- a/drivers/ddr/imx8m/ddrphy_utils.c
> +++ b/drivers/ddr/imx8m/ddrphy_utils.c
> @@ -214,7 +214,7 @@ static struct imx_int_pll_rate_table *fracpll(u32 freq)
>  	return NULL;
>  }
>  
> -static int dram_pll_init(u32 freq)
> +static int dram_frac_pll_init(u32 freq)
>  {
>  	volatile int i;
>  	u32 tmp;
> @@ -261,35 +261,124 @@ static int dram_pll_init(u32 freq)
>  	return 0;
>  }
>  
> -void ddrphy_init_set_dfi_clk(unsigned int drate)
> +#define SSCG_PLL_LOCK			BIT(31)
> +#define SSCG_PLL_DRAM_PLL_CLKE		BIT(9)
> +#define SSCG_PLL_PD			BIT(7)
> +#define SSCG_PLL_BYPASS1		BIT(5)
> +#define SSCG_PLL_BYPASS2		BIT(4)
> +
> +#define SSCG_PLL_REF_DIVR2_MASK		(0x3f << 19)
> +#define SSCG_PLL_REF_DIVR2_VAL(n)	(((n) << 19) & SSCG_PLL_REF_DIVR2_MASK)
> +#define SSCG_PLL_FEEDBACK_DIV_F1_MASK	(0x3f << 13)
> +#define SSCG_PLL_FEEDBACK_DIV_F1_VAL(n)	(((n) << 13) & SSCG_PLL_FEEDBACK_DIV_F1_MASK)
> +#define SSCG_PLL_FEEDBACK_DIV_F2_MASK	(0x3f << 7)
> +#define SSCG_PLL_FEEDBACK_DIV_F2_VAL(n)	(((n) << 7) & SSCG_PLL_FEEDBACK_DIV_F2_MASK)
> +#define SSCG_PLL_OUTPUT_DIV_VAL_MASK	(0x3f << 1)
> +#define SSCG_PLL_OUTPUT_DIV_VAL(n)	(((n) << 1) & SSCG_PLL_OUTPUT_DIV_VAL_MASK)
> +
> +static int dram_sscg_pll_init(u32 freq)
> +{
> +	u32 val;
> +	void __iomem *pll_base = IOMEM(MX8M_ANATOP_BASE_ADDR) + 0x60;
> +
> +	/* Bypass */
> +	setbits_le32(pll_base, SSCG_PLL_BYPASS1 | SSCG_PLL_BYPASS2);
> +
> +	val = readl(pll_base + 0x8);
> +	val &= ~(SSCG_PLL_OUTPUT_DIV_VAL_MASK |
> +		 SSCG_PLL_FEEDBACK_DIV_F2_MASK |
> +		 SSCG_PLL_FEEDBACK_DIV_F1_MASK |
> +		 SSCG_PLL_REF_DIVR2_MASK);
> +
> +	switch (freq) {
> +	case MHZ(800):
> +		val |= SSCG_PLL_OUTPUT_DIV_VAL(0);
> +		val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11);
> +		val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39);
> +		val |= SSCG_PLL_REF_DIVR2_VAL(29);
> +		break;
> +	case MHZ(600):
> +		val |= SSCG_PLL_OUTPUT_DIV_VAL(1);
> +		val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(17);
> +		val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39);
> +		val |= SSCG_PLL_REF_DIVR2_VAL(29);
> +		break;
> +	case MHZ(400):
> +		val |= SSCG_PLL_OUTPUT_DIV_VAL(1);
> +		val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(11);
> +		val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(39);
> +		val |= SSCG_PLL_REF_DIVR2_VAL(29);
> +		break;
> +	case MHZ(167):
> +		val |= SSCG_PLL_OUTPUT_DIV_VAL(3);
> +		val |= SSCG_PLL_FEEDBACK_DIV_F2_VAL(8);
> +		val |= SSCG_PLL_FEEDBACK_DIV_F1_VAL(45);
> +		val |= SSCG_PLL_REF_DIVR2_VAL(30);
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	writel(val, pll_base + 0x8);
> +
> +	/* Clear power down bit */
> +	clrbits_le32(pll_base, SSCG_PLL_PD);
> +	/* Enable PLL  */
> +	setbits_le32(pll_base, SSCG_PLL_DRAM_PLL_CLKE);
> +
> +	/* Clear bypass */
> +	clrbits_le32(pll_base, SSCG_PLL_BYPASS1);
> +	udelay(100);
> +	clrbits_le32(pll_base, SSCG_PLL_BYPASS2);
> +	/* Wait lock */
> +	while (!(readl(pll_base) & SSCG_PLL_LOCK))
> +		;
> +
> +	return 0;
> +}
> +
> +static int dram_pll_init(u32 freq, enum ddrc_type type)
> +{
> +	switch (type) {
> +	case DDRC_TYPE_MQ:
> +		return dram_sscg_pll_init(freq);
> +	case DDRC_TYPE_MM:
> +	case DDRC_TYPE_MP:
> +		return dram_frac_pll_init(freq);
> +	default:
> +		return -ENODEV;
> +	}
> +}
> +
> +void ddrphy_init_set_dfi_clk(unsigned int drate, enum ddrc_type type)
>  {
>  	switch (drate) {
>  	case 4000:
> -		dram_pll_init(MHZ(1000));
> +		dram_pll_init(MHZ(1000), type);
>  		dram_disable_bypass();
>  		break;
>  	case 3200:
> -		dram_pll_init(MHZ(800));
> +		dram_pll_init(MHZ(800), type);
>  		dram_disable_bypass();
>  		break;
>  	case 3000:
> -		dram_pll_init(MHZ(750));
> +		dram_pll_init(MHZ(750), type);
>  		dram_disable_bypass();
>  		break;
>  	case 2400:
> -		dram_pll_init(MHZ(600));
> +		dram_pll_init(MHZ(600), type);
>  		dram_disable_bypass();
>  		break;
>  	case 1600:
> -		dram_pll_init(MHZ(400));
> +		dram_pll_init(MHZ(400), type);
>  		dram_disable_bypass();
>  		break;
>  	case 1066:
> -		dram_pll_init(MHZ(266));
> +		dram_pll_init(MHZ(266),type);
>  		dram_disable_bypass();
>  		break;
>  	case 667:
> -		dram_pll_init(MHZ(167));
> +		dram_pll_init(MHZ(167), type);
>  		dram_disable_bypass();
>  		break;
>  	case 400:
> diff --git a/include/soc/imx8m/ddr.h b/include/soc/imx8m/ddr.h
> index a5a610909212..78b15f1d461a 100644
> --- a/include/soc/imx8m/ddr.h
> +++ b/include/soc/imx8m/ddr.h
> @@ -372,14 +372,14 @@ enum ddrc_type {
>  int imx8mm_ddr_init(struct dram_timing_info *timing_info);
>  int imx8mq_ddr_init(struct dram_timing_info *timing_info);
>  int imx8mp_ddr_init(struct dram_timing_info *timing_info);
> -int ddr_cfg_phy(struct dram_timing_info *timing_info);
> +int ddr_cfg_phy(struct dram_timing_info *timing_info, enum ddrc_type type);
>  void load_lpddr4_phy_pie(void);
>  void ddrphy_trained_csr_save(struct dram_cfg_param *param, unsigned int num);
>  void dram_config_save(struct dram_timing_info *info, unsigned long base);
>  
>  /* utils function for ddr phy training */
>  int wait_ddrphy_training_complete(void);
> -void ddrphy_init_set_dfi_clk(unsigned int drate);
> +void ddrphy_init_set_dfi_clk(unsigned int drate, enum ddrc_type type);
>  void ddrphy_init_read_msg_block(enum fw_type type);
>  
>  void update_umctl2_rank_space_setting(unsigned int pstat_num,
> -- 
> 2.29.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan  6 03:57:38 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 6 Jan 2021 09:57:38 +0100
Subject: [PATCH v2 2/5] usb: dwc2: add clk dependency for probe via oftree
In-Reply-To: <20201217110731.14914-3-m.grzeschik@pengutronix.de>
References: <20201217110731.14914-1-m.grzeschik@pengutronix.de>
 <20201217110731.14914-3-m.grzeschik@pengutronix.de>
Message-ID: <20210106085738.GK19063@pengutronix.de>

On Thu, Dec 17, 2020 at 12:07:28PM +0100, Michael Grzeschik wrote:
> The dwc2 controller at least needs one core clock which needs to be
> enabled before it is able to address the core registers. This patch adds
> the referenced clock in the devicetree to be used.
> 
> Signed-off-by: Michael Grzeschik <m.grzeschik at pengutronix.de>
> ---
>  drivers/usb/dwc2/core.h |  1 +
>  drivers/usb/dwc2/dwc2.c | 19 +++++++++++++++++--
>  2 files changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
> index b9845b5524..780efb262c 100644
> --- a/drivers/usb/dwc2/core.h
> +++ b/drivers/usb/dwc2/core.h
> @@ -467,6 +467,7 @@ struct dwc2 {
>  	struct dwc2_core_params params;
>  
>  	struct phy *phy; /* optional */
> +	struct clk *clk;
>  
>  #ifdef CONFIG_USB_DWC2_HOST
>  	struct usb_host host;
> diff --git a/drivers/usb/dwc2/dwc2.c b/drivers/usb/dwc2/dwc2.c
> index 82b5ef2813..13455479ef 100644
> --- a/drivers/usb/dwc2/dwc2.c
> +++ b/drivers/usb/dwc2/dwc2.c
> @@ -50,15 +50,26 @@ static int dwc2_probe(struct device_d *dev)
>  	dwc2->regs = IOMEM(iores->start);
>  	dwc2->dev = dev;
>  
> +	dwc2->clk = clk_get(dev, NULL);

According to the binding doc the clock should be named "otg", I think
this should be changed accordingly.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan  6 04:11:20 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 6 Jan 2021 10:11:20 +0100
Subject: [PATCH] arm/at91: Replace license and copyright boilerplate by
 SPDX identifiers
In-Reply-To: <20201217214816.405537-1-u.kleine-koenig@pengutronix.de>
References: <20201217214816.405537-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210106091120.GL19063@pengutronix.de>

On Thu, Dec 17, 2020 at 10:48:16PM +0100, Uwe Kleine-K?nig wrote:
> Converts the files that licensecheck can determine to be licensed under
> GPL-2.0-only or GPL-2.0-or-later and also convert the copyright statements
> to SPDX.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> ---

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.grzeschik at pengutronix.de  Wed Jan  6 04:42:16 2021
From: m.grzeschik at pengutronix.de (Michael Grzeschik)
Date: Wed,  6 Jan 2021 10:42:16 +0100
Subject: [PATCH] fixup! usb: dwc2: add clk dependency for probe via oftree
In-Reply-To: <20201217110731.14914-3-m.grzeschik@pengutronix.de>
References: <20201217110731.14914-3-m.grzeschik@pengutronix.de>
Message-ID: <20210106094216.26005-1-m.grzeschik@pengutronix.de>

The documentation says this clock is named otg, so we use the
named clock as documented.

Signed-off-by: Michael Grzeschik <m.grzeschik at pengutronix.de>
---
 drivers/usb/dwc2/dwc2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/dwc2.c b/drivers/usb/dwc2/dwc2.c
index 13455479ef..33d418e280 100644
--- a/drivers/usb/dwc2/dwc2.c
+++ b/drivers/usb/dwc2/dwc2.c
@@ -50,7 +50,7 @@ static int dwc2_probe(struct device_d *dev)
 	dwc2->regs = IOMEM(iores->start);
 	dwc2->dev = dev;
 
-	dwc2->clk = clk_get(dev, NULL);
+	dwc2->clk = clk_get(dev, "otg");
 	if (IS_ERR(dwc2->clk)) {
 		ret = PTR_ERR(dwc2->clk);
 		dev_err(dev, "Failed to get USB clock %d\n", ret);
-- 
2.30.0



From sha at pengutronix.de  Wed Jan  6 04:54:17 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 6 Jan 2021 10:54:17 +0100
Subject: [PATCH] overlay: return error if target for firmware is missing
In-Reply-To: <20201218093258.1736578-1-m.tretter@pengutronix.de>
References: <20201218093258.1736578-1-m.tretter@pengutronix.de>
Message-ID: <20210106095417.GM19063@pengutronix.de>

On Fri, Dec 18, 2020 at 10:32:58AM +0100, Michael Tretter wrote:
> If the overlay references a firmware, the overlay must not be applied if
> the firmware cannot be loaded. However, if the target node of the
> firmware (i.e., the firmware manager) was not found, the fragment was
> ignored and the firmware not loaded, but the overlay applied anyway.
> 
> If the overlay does not reference a firmware, of_process_overlay must
> succeed even if the target node cannot be found, because the overlay
> might still apply to the Linux device tree.
> 
> Always call the process function on a fragment, even if the target node
> was not found. This allows the caller to decide, if a missing target is
> fatal or if the overlay can be applied anyway.
> 
> Fix load_firmware to fail if a overlay references a firmware and the
> target is NULL. Also, rephrase and clarify the comment that documents
> this behavior.
> 
> Reported-by: Matthias Fend <matthias.fend at wolfvision.net>
> Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
> ---
>  drivers/of/of_firmware.c | 11 ++++++++---
>  drivers/of/overlay.c     |  5 +++--
>  2 files changed, 11 insertions(+), 5 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/of/of_firmware.c b/drivers/of/of_firmware.c
> index 0135631fb899..096f84572e63 100644
> --- a/drivers/of/of_firmware.c
> +++ b/drivers/of/of_firmware.c
> @@ -43,6 +43,9 @@ static int load_firmware(struct device_node *target,
>  	else if (err)
>  		return -EINVAL;
>  
> +	if (!target)
> +		return -EINVAL;
> +
>  	mgr = of_node_get_mgr(target);
>  	if (!mgr)
>  		return -EINVAL;
> @@ -69,11 +72,13 @@ int of_firmware_load_overlay(struct device_node *overlay, const char *path)
>  	struct device_node *ovl;
>  
>  	root = of_get_root_node();
> +	resolved = of_resolve_phandles(root, overlay);
>  	/*
> -	 * If we cannot resolve the symbols in the overlay, ensure that the
> -	 * overlay does depend on firmware to be loaded.
> +	 * If the overlay cannot be resolved, use the load_firmware callback
> +	 * with the unresolved overlay to verify that the overlay does not
> +	 * depend on a firmware to be loaded. If a required firmware cannot be
> +	 * loaded, the overlay must not be applied.
>  	 */
> -	resolved = of_resolve_phandles(root, overlay);
>  	ovl = resolved ? resolved : overlay;
>  
>  	err = of_process_overlay(root, ovl,
> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> index b79dbff94dbf..eb47378258b6 100644
> --- a/drivers/of/overlay.c
> +++ b/drivers/of/overlay.c
> @@ -215,12 +215,13 @@ int of_process_overlay(struct device_node *root,
>  
>  		target = find_target(root, fragment);
>  		if (!target)
> -			continue;
> +			pr_debug("cannot find target for fragment",
> +				 fragment->name);
>  
>  		err = process(target, ovl, data);
>  		if (err) {
>  			pr_warn("failed to process overlay for %s\n",
> -				target->name);
> +				target ? target->name : "unknown");
>  			break;
>  		}
>  	}
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan  6 05:00:57 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 6 Jan 2021 11:00:57 +0100
Subject: [PATCH v2 0/5] dwc2: improve gadget support
In-Reply-To: <20201217110731.14914-1-m.grzeschik@pengutronix.de>
References: <20201217110731.14914-1-m.grzeschik@pengutronix.de>
Message-ID: <20210106100057.GN19063@pengutronix.de>

On Thu, Dec 17, 2020 at 12:07:26PM +0100, Michael Grzeschik wrote:
> This series adds support for clk and reset controller defined by dts. It also
> enables the hardware force mode for the gadget in case the
> otg.mode="peripheral" is set.
> 
> Michael Grzeschik (5):
>   usb: dwc2: cleanup on error for deferred probing
>   usb: dwc2: add clk dependency for probe via oftree
>   usb: dwc2: add reset controller dependency for probe via oftree
>   usb: dwc2: update the dr_mode on set_mode callback
>   usb: dwc2: add support to force gadget mode
> 
>  drivers/usb/dwc2/core.h   |   1 +
>  drivers/usb/dwc2/dwc2.c   |  33 ++++++++-
>  drivers/usb/dwc2/gadget.c | 144 ++++++++++++++++++++++++++++++++++++++
>  3 files changed, 175 insertions(+), 3 deletions(-)

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan  6 05:05:43 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 6 Jan 2021 11:05:43 +0100
Subject: [PATCH 1/2] fixup! usb: dwc2: Add support for optional usb phy
In-Reply-To: <20201221003251.83042-2-ahmad@a3f.at>
References: <20201221003251.83042-1-ahmad@a3f.at>
 <20201221003251.83042-2-ahmad@a3f.at>
Message-ID: <20210106100543.GO19063@pengutronix.de>

On Mon, Dec 21, 2020 at 01:32:50AM +0100, Ahmad Fatoum wrote:
> Linux doesn't seem to enforce a fixed order between phy_init and
> phy_power_on. The Linux dwc2 driver does power_on and then phy_init,
> which is the inverse of what barebox is currently doing.
> 
> The PHYs normally used with dwc2 are written with this in mind.
> For example, our stm32-usbphyc driver fails to disable:
> 
>   ERROR: stm32-usbphyc 5a006000.usbphyc at 5a006000.of: PLL not reset
>   ERROR: phy1: phy exit failed --> -5
> 
> Because Linux does exit -> power_off, but barebox does power_off ->
> exit.
> 
> Issue was raised upstream:
> https://lore.kernel.org/lkml/6cd01e79-fdc0-3bd4-32b5-a85142533f8a at pengutronix.de/T/#t
> 
> Until this is settled, swap the order to follow what Linux does.
> This is suboptimal, because it means controller drivers have different
> order of the operations and that you can't combine arbitrary PHYs and
> controllers, but it seems unlikely we will support combinations that
> aren't supported by Linux in the first place anyway.

This is valuable information and I don't want it to be lost, so instead
of applying this as a fixup I rewrote the subject to:

usb: dwc2: swap order of phy_init and phy_power_on to what Linux does

and applied it as a separate patch.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan  6 05:08:28 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 6 Jan 2021 11:08:28 +0100
Subject: [PATCH 1/3] i.MX7: Add CCM definitions for UART3
In-Reply-To: <20201216130949.25830-1-s.trumtrar@pengutronix.de>
References: <20201216130949.25830-1-s.trumtrar@pengutronix.de>
Message-ID: <20210106100828.GS19063@pengutronix.de>

On Wed, Dec 16, 2020 at 02:09:47PM +0100, Steffen Trumtrar wrote:
> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> ---
>  arch/arm/mach-imx/include/mach/imx7-ccm-regs.h | 4 ++++
>  1 file changed, 4 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/mach-imx/include/mach/imx7-ccm-regs.h b/arch/arm/mach-imx/include/mach/imx7-ccm-regs.h
> index de6eb1bbd10d..5c60794ca74f 100644
> --- a/arch/arm/mach-imx/include/mach/imx7-ccm-regs.h
> +++ b/arch/arm/mach-imx/include/mach/imx7-ccm-regs.h
> @@ -3,6 +3,7 @@
>  
>  #define IMX7_CCM_CCGR_UART1		148
>  #define IMX7_CCM_CCGR_UART2		149
> +#define IMX7_CCM_CCGR_UART3		150
>  
>  #define IMX7_CLOCK_ROOT_INDEX(x)	(((x) - 0x8000) / 128)
>  
> @@ -16,6 +17,9 @@
>  #define IMX7_UART2_CLK_ROOT		IMX7_CLOCK_ROOT_INDEX(0xb000)
>  #define IMX7_UART2_CLK_ROOT__OSC_24M IMX7_CCM_TARGET_ROOTn_MUX(0b000)
>  
> +#define IMX7_UART3_CLK_ROOT		IMX7_CLOCK_ROOT_INDEX(0xb080)
> +#define IMX7_UART3_CLK_ROOT__OSC_24M IMX7_CCM_TARGET_ROOTn_MUX(0b000)
> +
>  /* 0 <= n <= 190 */
>  #define IMX7_CCM_CCGRn_SET(n)	(0x4004 + 16 * (n))
>  #define IMX7_CCM_CCGRn_CLR(n)	(0x4008 + 16 * (n))
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan  6 05:35:25 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 6 Jan 2021 11:35:25 +0100
Subject: No oob scheme defined for oobsize 224 on imx6ull board
In-Reply-To: <CADbCKyKLBG=eSoKeqnvvGMCGdkpwNo_xGvH1D1xHHTgk0tMU1Q@mail.gmail.com>
References: <CADbCKyKLBG=eSoKeqnvvGMCGdkpwNo_xGvH1D1xHHTgk0tMU1Q@mail.gmail.com>
Message-ID: <20210106103525.GT19063@pengutronix.de>

Hi,

On Fri, Dec 18, 2020 at 05:11:11PM +0800, ??? wrote:
> Hi, all
>     I am trying to run barebox on my i.mx6ull board.  I inherit from
> nxp-imx6ull-evk. When I added nand flash support, system crashed. I
> found that the pointer "chip->legacy.set_features" and
> "chip->legacy.get_features" in nand_mxs.c was NULL.
> I replaced it with nand_set_features() and nand_get_features().

This looks like the correct solution for this. Care to send a patch?

> Barebox didn't crash again, but I get the errors:
>         nand_base: device found, Manufacturer ID: 0x2c, Chip ID: 0xdc
>         nand_base: Micron MT29F4G08ABAEAWP
>         nand_base: 512 MiB, SLC, erase size: 256 KiB, page size: 4096,
> OOB size: 224
>         WARNING: at drivers/mtd/nand/nand_base.c:5591/nand_scan_tail()!
>         WARNING: No oob scheme defined for oobsize 224
>         mxs_nand 1806000.nand-controller at 1806000.of: probe failed:
> Invalid argument

You are falling into:

	/*
	 * If no default placement scheme is given, select an appropriate one.
	 */
	if (!mtd->ooblayout &&
	    !(ecc->mode == NAND_ECC_SOFT && ecc->algo == NAND_ECC_BCH)) {
			...
	}

Normally mtd->ooblayout should be set at this point. the nand_mxs driver
currently misses to set it. I think you have to adopt
gpmi_ooblayout_ecc() and gpmi_ooblayout_free() from the Linux driver for
barebox.

This bug seems to trigger for NANDs with bigger page sizes. I only
tested the last NAND layer update with smaller page sizes. So it's not
you who misses something, it's me who missed something ;)

Regards,
  Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From jameszxj at gmail.com  Wed Jan  6 21:19:38 2021
From: jameszxj at gmail.com (=?ISO-8859-1?B?amFtZXN6eGo=?=)
Date: Thu, 7 Jan 2021 10:19:38 +0800
Subject: [PATCH 1/1]mtd:nand_mxs:update get/set features legacy function call
Message-ID: <tencent_1F5884D31C07819F5E1EA02A84FDD10FDC0A@qq.com>

update get/set features legacy function call to avoid NULL pointer crash.

Signed-off-by: zhengxiaojun <jameszxj at gmail.com>
--- 
 drivers/mtd/nand/nand_mxs.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index 9f7ab1442..ad8aeb41f 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -2055,14 +2055,12 @@ static int mxs_nand_enable_edo_mode(struct mxs_nand_info *info)
 		/* [1] send SET FEATURE commond to NAND */
 		feature[0] = mode;
 
-		ret = chip->legacy.set_features(chip,
-				ONFI_FEATURE_ADDR_TIMING_MODE, feature);
+		ret = nand_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE, feature);
 		if (ret)
 			goto err_out;
 
 		/* [2] send GET FEATURE command to double-check the timing mode */
-		ret = chip->legacy.get_features(chip,
-				ONFI_FEATURE_ADDR_TIMING_MODE, feature);
+		ret = nand_get_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE, feature);
 		if (ret || feature[0] != mode)
 			goto err_out;
 	}
-- 
2.29.2

From jameszxj at gmail.com  Wed Jan  6 21:27:37 2021
From: jameszxj at gmail.com (=?gb18030?B?amFtZXN6eGo=?=)
Date: Thu, 7 Jan 2021 10:27:37 +0800
Subject: No oob scheme defined for oobsize 224 on imx6ull board
In-Reply-To: <20210106103525.GT19063@pengutronix.de>
References: <CADbCKyKLBG=eSoKeqnvvGMCGdkpwNo_xGvH1D1xHHTgk0tMU1Q@mail.gmail.com>
 <20210106103525.GT19063@pengutronix.de>
Message-ID: <tencent_32C731E0539771A8566113F4823732E1FD08@qq.com>

Hi,
 
> 
> 
> ------------------ Original ------------------
> From: "Sascha Hauer" <sha at pengutronix.de>;
> Date: Wed, Jan 6, 2021 06:35 PM
> To: "???"<jameszxj at gmail.com>;
> Cc: "barebox"<barebox at lists.infradead.org>;
> Subject: Re: No oob scheme defined for oobsize 224 on imx6ull board
> 
> Hi,
> 
> On Fri, Dec 18, 2020 at 05:11:11PM +0800, ??? wrote:
> > Hi, all
> >     I am trying to run barebox on my i.mx6ull board.  I inherit from
> > nxp-imx6ull-evk. When I added nand flash support, system crashed. I
> > found that the pointer "chip->legacy.set_features" and
> > "chip->legacy.get_features" in nand_mxs.c was NULL.
> > I replaced it with nand_set_features() and nand_get_features().
> 
> This looks like the correct solution for this. Care to send a patch?
I have sent a patch email. My first time send a patch to barebox, so if
the format is improper, feel free to tell me.

> 
> > Barebox didn't crash again, but I get the errors:
> >         nand_base: device found, Manufacturer ID: 0x2c, Chip ID: 0xdc
> >         nand_base: Micron MT29F4G08ABAEAWP
> >         nand_base: 512 MiB, SLC, erase size: 256 KiB, page size: 4096,
> > OOB size: 224
> >         WARNING: at drivers/mtd/nand/nand_base.c:5591/nand_scan_tail()!
> >         WARNING: No oob scheme defined for oobsize 224
> >         mxs_nand 1806000.nand-controller at 1806000.of: probe failed:
> > Invalid argument
> 
> You are falling into:
> 
> /*
> * If no default placement scheme is given, select an appropriate one.
> */
> if (!mtd->ooblayout &&
>     !(ecc->mode == NAND_ECC_SOFT && ecc->algo == NAND_ECC_BCH)) {
> ...
> }
> 
> Normally mtd->ooblayout should be set at this point. the nand_mxs driver
> currently misses to set it. I think you have to adopt
> gpmi_ooblayout_ecc() and gpmi_ooblayout_free() from the Linux driver for
> barebox.
> 
> This bug seems to trigger for NANDs with bigger page sizes. I only
> tested the last NAND layer update with smaller page sizes. So it's not
> you who misses something, it's me who missed something ;)
> 
thanks, I'll try it. If it runs, I'll send another patch.

> Regards,
>   Sascha
> 
> -- 
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

From sha at pengutronix.de  Thu Jan  7 02:17:04 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 7 Jan 2021 08:17:04 +0100
Subject: [PATCH 1/1]mtd:nand_mxs:update get/set features legacy function
 call
In-Reply-To: <tencent_1F5884D31C07819F5E1EA02A84FDD10FDC0A@qq.com>
References: <tencent_1F5884D31C07819F5E1EA02A84FDD10FDC0A@qq.com>
Message-ID: <20210107071704.GU19063@pengutronix.de>

On Thu, Jan 07, 2021 at 10:19:38AM +0800, jameszxj wrote:
> update get/set features legacy function call to avoid NULL pointer crash.
> 
> Signed-off-by: zhengxiaojun <jameszxj at gmail.com>
> --- 
>  drivers/mtd/nand/nand_mxs.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)

The format is perfectly fine, thanks :)

Applied.

Sascha

> 
> diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
> index 9f7ab1442..ad8aeb41f 100644
> --- a/drivers/mtd/nand/nand_mxs.c
> +++ b/drivers/mtd/nand/nand_mxs.c
> @@ -2055,14 +2055,12 @@ static int mxs_nand_enable_edo_mode(struct mxs_nand_info *info)
>  		/* [1] send SET FEATURE commond to NAND */
>  		feature[0] = mode;
>  
> -		ret = chip->legacy.set_features(chip,
> -				ONFI_FEATURE_ADDR_TIMING_MODE, feature);
> +		ret = nand_set_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE, feature);
>  		if (ret)
>  			goto err_out;
>  
>  		/* [2] send GET FEATURE command to double-check the timing mode */
> -		ret = chip->legacy.get_features(chip,
> -				ONFI_FEATURE_ADDR_TIMING_MODE, feature);
> +		ret = nand_get_features(chip, ONFI_FEATURE_ADDR_TIMING_MODE, feature);
>  		if (ret || feature[0] != mode)
>  			goto err_out;
>  	}
> -- 
> 2.29.2
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From o.rempel at pengutronix.de  Thu Jan  7 02:55:08 2021
From: o.rempel at pengutronix.de (Oleksij Rempel)
Date: Thu,  7 Jan 2021 08:55:08 +0100
Subject: [PATCH v1] MIPS: dts: ar9331: add stdout-path properties
Message-ID: <20210107075508.15261-1-o.rempel@pengutronix.de>

With the kernel v5.11-rc2 the console will be automatically redirected
to null if no default console is configured. Make sure the barebox is
doing it to make kernel happy.

Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
---
 arch/mips/dts/ar9331-dptechnics-dpt-module.dts   | 2 ++
 arch/mips/dts/ar9331-okud-max9331.dts            | 2 ++
 arch/mips/dts/ar9331-openembed-som9331-board.dts | 2 ++
 3 files changed, 6 insertions(+)

diff --git a/arch/mips/dts/ar9331-dptechnics-dpt-module.dts b/arch/mips/dts/ar9331-dptechnics-dpt-module.dts
index cbaf5ab39e..24ce0d0d67 100644
--- a/arch/mips/dts/ar9331-dptechnics-dpt-module.dts
+++ b/arch/mips/dts/ar9331-dptechnics-dpt-module.dts
@@ -7,6 +7,8 @@
 	};
 
 	chosen {
+		stdout-path = &uart;
+
 		environment {
 			compatible = "barebox,environment";
 			device-path = &spiflash, "partname:barebox-environment";
diff --git a/arch/mips/dts/ar9331-okud-max9331.dts b/arch/mips/dts/ar9331-okud-max9331.dts
index 53350899f9..3b93bee93b 100644
--- a/arch/mips/dts/ar9331-okud-max9331.dts
+++ b/arch/mips/dts/ar9331-okud-max9331.dts
@@ -17,6 +17,8 @@
 	};
 
 	chosen {
+		stdout-path = &uart;
+
 		environment {
 			compatible = "barebox,environment";
 			device-path = &spiflash, "partname:barebox-environment";
diff --git a/arch/mips/dts/ar9331-openembed-som9331-board.dts b/arch/mips/dts/ar9331-openembed-som9331-board.dts
index ff9d25e352..4736332f8f 100644
--- a/arch/mips/dts/ar9331-openembed-som9331-board.dts
+++ b/arch/mips/dts/ar9331-openembed-som9331-board.dts
@@ -33,6 +33,8 @@
 
 
 	chosen {
+		stdout-path = &uart;
+
 		environment {
 			compatible = "barebox,environment";
 			device-path = &spiflash, "partname:barebox-environment";
-- 
2.30.0



From donnie at sihovision.com  Thu Jan  7 23:42:55 2021
From: donnie at sihovision.com (donnie at sihovision.com)
Date: Fri, 8 Jan 2021 12:42:55 +0800
Subject: Rugged Design Industrial touchscreen panel PC
In-Reply-To: <2021010008124200550766@tradepro.net>
Message-ID: <2021010008124200550766@tradepro.net>

Hi,
This is Donnie from Sihovision which is professional manufacturer of Industrial Panel PC in Shenzhen,China.
Recently we launched a new type Cordless Design Industrial Touch Panel PC as following: 
Cordless Mothreboard Design 
If further information is required, pls feel free to contact me, thanks
_______________________________
Best regards,
Donnie Nie
SHINHO ELECTRONIC
www.sihovision.com
TEL/Whatsapp: 0086 13163734006
Skype: donnie.shinho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210108/66f13d9b/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-5.jpg
Type: image/jpeg
Size: 36783 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210108/66f13d9b/attachment-0005.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-3.jpg
Type: image/jpeg
Size: 36765 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210108/66f13d9b/attachment-0006.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-4.jpg
Type: image/jpeg
Size: 44663 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210108/66f13d9b/attachment-0007.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-1.jpg
Type: image/jpeg
Size: 47661 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210108/66f13d9b/attachment-0008.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: logo2.jpg
Type: image/jpeg
Size: 2231 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210108/66f13d9b/attachment-0009.jpg>

From s.trumtrar at pengutronix.de  Mon Jan 11 05:32:05 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Mon, 11 Jan 2021 11:32:05 +0100
Subject: [PATCH 2/2] image-sparse: change chunk_data_sz to u64
In-Reply-To: <20210111103205.4330-1-s.trumtrar@pengutronix.de>
References: <20210111103205.4330-1-s.trumtrar@pengutronix.de>
Message-ID: <20210111103205.4330-2-s.trumtrar@pengutronix.de>

chunk_data_sz is set to the result of a __le32 * __le32 multiplication:

  chunk_data_sz = si->sparse.blk_sz * si->chunk.chunk_sz;

This will overflow.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 lib/image-sparse.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/image-sparse.c b/lib/image-sparse.c
index 8e7a52fd71..c375c78d63 100644
--- a/lib/image-sparse.c
+++ b/lib/image-sparse.c
@@ -62,7 +62,8 @@ struct sparse_image_ctx {
 
 static int sparse_seek(struct sparse_image_ctx *si)
 {
-	unsigned int chunk_data_sz, payload;
+	uint64_t chunk_data_sz;
+	unsigned int payload;
 	loff_t offs;
 	int ret;
 
@@ -94,7 +95,7 @@ again:
 			return -errno;
 	}
 
-	chunk_data_sz = si->sparse.blk_sz * si->chunk.chunk_sz;
+	chunk_data_sz = (uint64_t) si->sparse.blk_sz * si->chunk.chunk_sz;
 	payload = si->chunk.total_sz - si->sparse.chunk_hdr_sz;
 
 	si->processed_chunks++;
-- 
2.20.1



From s.trumtrar at pengutronix.de  Mon Jan 11 05:32:04 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Mon, 11 Jan 2021 11:32:04 +0100
Subject: [PATCH 1/2] image-sparse: change retlen to size_t
Message-ID: <20210111103205.4330-1-s.trumtrar@pengutronix.de>

retlen can potentially overflow. Also, write_full() in
fastboot_handle_sparse() expects size_t anyway.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 common/fastboot.c      | 2 +-
 include/image-sparse.h | 2 +-
 lib/image-sparse.c     | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/common/fastboot.c b/common/fastboot.c
index 1b6dc28d8e..40b92d9982 100644
--- a/common/fastboot.c
+++ b/common/fastboot.c
@@ -566,7 +566,7 @@ static int fastboot_handle_sparse(struct fastboot *fb,
 	}
 
 	while (1) {
-		int retlen;
+		size_t retlen;
 		loff_t pos;
 
 		ret = sparse_image_read(sparse, buf, &pos, bufsiz, &retlen);
diff --git a/include/image-sparse.h b/include/image-sparse.h
index 29242f4fd5..6bff844411 100644
--- a/include/image-sparse.h
+++ b/include/image-sparse.h
@@ -60,7 +60,7 @@ struct sparse_image_ctx;
 
 struct sparse_image_ctx *sparse_image_open(const char *path);
 int sparse_image_read(struct sparse_image_ctx *si, void *buf,
-		      loff_t *pos, size_t len, int *retlen);
+		      loff_t *pos, size_t len, size_t *retlen);
 void sparse_image_close(struct sparse_image_ctx *si);
 loff_t sparse_image_size(struct sparse_image_ctx *si);
 
diff --git a/lib/image-sparse.c b/lib/image-sparse.c
index 0c31742ab6..8e7a52fd71 100644
--- a/lib/image-sparse.c
+++ b/lib/image-sparse.c
@@ -190,7 +190,7 @@ out:
 }
 
 int sparse_image_read(struct sparse_image_ctx *si, void *buf, loff_t *pos,
-		      size_t len, int *retlen)
+		      size_t len, size_t *retlen)
 {
 	size_t now;
 	int ret, i;
-- 
2.20.1



From a.fatoum at pengutronix.de  Mon Jan 11 09:35:55 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 11 Jan 2021 15:35:55 +0100
Subject: [PATCH] Documentation: boards: sandbox: describe --image flags
Message-ID: <20210111143555.13002-1-a.fatoum@pengutronix.de>

barebox partition table parsing can be tested in sandbox using the
recently added ,blkdev flag. Extend the documentation to cover this.

Cc: Juergen Borleis <jbe at pengutronix.de>
Reported-by: Lucas Stach <lst at pengutronix.de>
Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 Documentation/boards/sandbox.rst | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/Documentation/boards/sandbox.rst b/Documentation/boards/sandbox.rst
index 8b24b6a64584..e9e5183653e6 100644
--- a/Documentation/boards/sandbox.rst
+++ b/Documentation/boards/sandbox.rst
@@ -34,6 +34,20 @@ Available sandbox invocation options include:
     Map a <file> to barebox. This option can be given multiple times. The <file>s
     will show up as ``/dev/fd0`` ... ``/dev/fdX`` in the barebox simulator.
 
+    How the file is mapped in barebox can be controlled by a number of flags:
+
+    * ``,ro``: The host file is mapped read-only
+
+    * ``,blkdev``: The host file is to be mapped as block device. This is the
+      default when passing block devices from the host. The file's size must
+      be a multiple of the barebox sector size of 512 bytes.
+
+    * ``,cdev``: The host file is mapped as character device. This is the default,
+      unless the the host file is a block device.
+
+    Multiple options can be appended if they don't clash. Literal commas within the
+    file path can be escaped with a backslash. Example: ``-i './0\,0.hdimg,blkdev,ro'``.
+
   ``-e <file>``
 
     Map <file> to barebox. With this option <file>s are mapped as
-- 
2.30.0



From str at pengutronix.de  Tue Jan 12 04:38:01 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Tue, 12 Jan 2021 10:38:01 +0100
Subject: [PATCH] imd: change disabled checksum tag info to debug
Message-ID: <20210112093801.2632-1-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

When the checksum tag is disabled the CRC is most likely invalid.
And if the checksum tag is disabled and the CRC is actually invalid the
user doesn't care for it anyway.

This information only confuses the user so make it a debug message.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 common/imd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/imd.c b/common/imd.c
index ef9eff876b..aff3b00b6b 100644
--- a/common/imd.c
+++ b/common/imd.c
@@ -406,7 +406,7 @@ int imd_verify_crc32(void *buf, size_t size)
 			       *p, crc);
 			return -EILSEQ;
 		} else if (*p != crc && !imd_crc32_is_valid(*flags)) {
-			printf("CRC: is invalid, but the checksum tag is not enabled\n");
+			debug("CRC: is invalid, but the checksum tag is not enabled\n");
 			return -EINVAL;
 		} else {
 			printf("CRC: valid\n");
-- 
2.20.1



From a.fatoum at pengutronix.de  Tue Jan 12 08:51:20 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 12 Jan 2021 14:51:20 +0100
Subject: [PATCH] documentation: devicetree: migrate remaining binding to reST
Message-ID: <20210112135120.15811-1-a.fatoum@pengutronix.de>

Eventually, we will want to have formalized YAML bindings and scripts to
turn them into reST for display in the online documentation.

For now, just turn the remaining text files into reST, so they can be
searched as well.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 ...ive-serial.txt => altr,passive-serial.rst} | 16 +++----
 ...fpga-mgr.txt => altr,socfpga-fpga-mgr.rst} |  8 ++--
 .../devicetree/bindings/mtd/partition.rst     | 42 +++++++++++++++++++
 .../devicetree/bindings/mtd/partition.txt     | 39 -----------------
 4 files changed, 56 insertions(+), 49 deletions(-)
 rename Documentation/devicetree/bindings/firmware/{altr,passive-serial.txt => altr,passive-serial.rst} (51%)
 rename Documentation/devicetree/bindings/firmware/{altr,socfpga-fpga-mgr.txt => altr,socfpga-fpga-mgr.rst} (74%)
 create mode 100644 Documentation/devicetree/bindings/mtd/partition.rst
 delete mode 100644 Documentation/devicetree/bindings/mtd/partition.txt

diff --git a/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt b/Documentation/devicetree/bindings/firmware/altr,passive-serial.rst
similarity index 51%
rename from Documentation/devicetree/bindings/firmware/altr,passive-serial.txt
rename to Documentation/devicetree/bindings/firmware/altr,passive-serial.rst
index eec12fbace52..1012137bc93b 100644
--- a/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt
+++ b/Documentation/devicetree/bindings/firmware/altr,passive-serial.rst
@@ -1,20 +1,22 @@
 Altera FPGAs in passive serial mode
------------------------------------
+===================================
 
 This binding defines the control interface to Altera FPGAs in
 passive serial mode. This is used to upload the firmware and
 to start the FPGA.
 
 Required properties:
-- compatible: shall be "altr,fpga-passive-serial" or
-  "altr,fpga-arria10-passive-serial" for Arria 10
-- reg: SPI chip select
-- nstat-gpios: Specify GPIO for controlling the nstat pin
-- confd-gpios: Specify GPIO for controlling the confd pin
-- nconfig-gpios: Specify GPIO for controlling the nconfig pin
+- ``compatible``: shall be ``"altr,fpga-passive-serial"`` or
+  ``"altr,fpga-arria10-passive-serial"`` for Arria 10
+- ``reg``: SPI chip select
+- ``nstat-gpios``: Specify GPIO for controlling the nstat pin
+- ``confd-gpios``: Specify GPIO for controlling the confd pin
+- ``nconfig-gpios``: Specify GPIO for controlling the nconfig pin
 
 Example:
 
+.. code-block:: none
+
 	fpga at 0 {
 		compatible = "altr,fpga-passive-serial";
 		nstat-gpios = <&gpio4 18 0>;
diff --git a/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt b/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst
similarity index 74%
rename from Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt
rename to Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst
index 70ec4abf25b4..9f7de6b98580 100644
--- a/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt
+++ b/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst
@@ -1,17 +1,19 @@
 Altera SOCFPGA FPGA Manager
----------------------------
+===========================
 
 This binding defines the FPGA Manager on Altera SOCFPGAs. This is used to upload
 the firmware to the FPGA part of the SoC.
 
 Required properties:
-- compatible: shall be "altr,socfpga-fpga-mgr"
-- reg: Must contain 2 register ranges:
+- ``compatible``: shall be ``"altr,socfpga-fpga-mgr"``
+- ``reg``: Must contain 2 register ranges:
 	1. The control address space of the FPGA manager.
 	2. The configuration data address space where the firmware data is written to.
 
 Example:
 
+.. code-block:: none
+
 	fpgamgr at ff706000 {
 		compatible = "altr,socfpga-fpga-mgr";
 		reg = <0xff706000 0x1000>,
diff --git a/Documentation/devicetree/bindings/mtd/partition.rst b/Documentation/devicetree/bindings/mtd/partition.rst
new file mode 100644
index 000000000000..6db54070a991
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/partition.rst
@@ -0,0 +1,42 @@
+Representing flash partitions in devicetree
+===========================================
+
+In addition to the upstream binding, another property is added:
+
+Optional properties:
+- ``partuuid`` : The partition UUID for this partition.
+
+Additionally, barebox also supports partitioning the eMMC boot partitions if
+the partition table node is named appropriately:
+- ``partitions`` : user partition
+- ``boot0-partitions`` : boot0 partition
+- ``boot1-partitions`` : boot1 partition
+
+Examples:
+
+.. code-block:: none
+
+  flash at 0 {
+  	partitions {
+  		compatible = "fixed-partitions";
+  		#address-cells = <1>;
+  		#size-cells = <1>;
+
+  		state_part: state {
+  			partuuid = "16367da7-c518-499f-9aad-e1f366692365";
+  		};
+  	};
+  };
+
+  emmc at 1 {
+  	boot0-partitions {
+  		compatible = "fixed-partitions";
+  		#address-cells = <1>;
+  		#size-cells = <1>;
+
+  		barebox at 0 {
+  			label = "barebox";
+  			reg = <0x0 0x300000>;
+  		};
+  	};
+  };
diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt
deleted file mode 100644
index 4288a82437b4..000000000000
--- a/Documentation/devicetree/bindings/mtd/partition.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-Representing flash partitions in devicetree
-
-In addition to the upstream binding, another property is added:
-
-Optional properties:
-- partuuid : The partition UUID for this partition.
-
-Additionally, barebox also supports partitioning the eMMC boot partitions if
-the partition table node is named appropriately:
-- partitions : user partition
-- boot0-partitions : boot0 partition
-- boot1-partitions : boot1 partition
-
-Examples:
-
-flash at 0 {
-	partitions {
-		compatible = "fixed-partitions";
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		state_part: state {
-			partuuid = "16367da7-c518-499f-9aad-e1f366692365";
-		};
-	};
-};
-
-emmc at 1 {
-	boot0-partitions {
-		compatible = "fixed-partitions";
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		barebox at 0 {
-			label = "barebox";
-			reg = <0x0 0x300000>;
-		};
-	};
-};
-- 
2.30.0



From r.czerwinski at pengutronix.de  Wed Jan 13 02:57:57 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Wed, 13 Jan 2021 08:57:57 +0100
Subject: [PATCH 2/2] ARM: qemu: support for state & env via DT overlay
In-Reply-To: <20210113075757.21478-1-r.czerwinski@pengutronix.de>
References: <20210113075757.21478-1-r.czerwinski@pengutronix.de>
Message-ID: <20210113075757.21478-2-r.czerwinski@pengutronix.de>

Add support for state and barebox environment by applying an overlay on
top of the qemu generated device tree. If qemu is used with a persistent
flash partition, this allows usage of environments and state across qemu
reboots.
Simple testing can be performed by starting with

  qemu-system-arm -m 256M -M virt -kernel images/barebox-dt-2nd.img -nographic

Storing data, changing into the qemu console via Ctrl-A Ctrl-C, issuing
'system_reset' and Ctrl-A Ctrl-C to get back into the barebox console.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 arch/arm/boards/qemu-virt/.gitignore          |  1 +
 arch/arm/boards/qemu-virt/Makefile            |  1 +
 arch/arm/boards/qemu-virt/board.c             | 34 +++++++
 .../arm/boards/qemu-virt/overlay-of-flash.dts | 97 +++++++++++++++++++
 arch/arm/configs/vexpress_defconfig           |  1 +
 arch/arm/mach-vexpress/Kconfig                |  1 +
 6 files changed, 135 insertions(+)
 create mode 100644 arch/arm/boards/qemu-virt/.gitignore
 create mode 100644 arch/arm/boards/qemu-virt/overlay-of-flash.dts

diff --git a/arch/arm/boards/qemu-virt/.gitignore b/arch/arm/boards/qemu-virt/.gitignore
new file mode 100644
index 0000000000..5d65b54bf1
--- /dev/null
+++ b/arch/arm/boards/qemu-virt/.gitignore
@@ -0,0 +1 @@
+*.dtb*
diff --git a/arch/arm/boards/qemu-virt/Makefile b/arch/arm/boards/qemu-virt/Makefile
index dcfc2937d3..8451c7832d 100644
--- a/arch/arm/boards/qemu-virt/Makefile
+++ b/arch/arm/boards/qemu-virt/Makefile
@@ -1 +1,2 @@
 obj-y += board.o
+obj-y += overlay-of-flash.dtb.o
diff --git a/arch/arm/boards/qemu-virt/board.c b/arch/arm/boards/qemu-virt/board.c
index 3aeea1a017..9d8c90eb5b 100644
--- a/arch/arm/boards/qemu-virt/board.c
+++ b/arch/arm/boards/qemu-virt/board.c
@@ -5,7 +5,41 @@
  */
 #include <common.h>
 #include <init.h>
+#include <of.h>
 #include <asm/system_info.h>
+#include <asm/barebox-arm.h>
+
+extern char __dtb_overlay_of_flash_start[];
+
+static int replace_dtb(void) {
+	struct device_node *overlay;
+	void *fdt;
+	struct device_node *root;
+
+	fdt = barebox_arm_boot_dtb();
+	if (fdt)
+		pr_debug("using boarddata provided DTB\n");
+
+	if (!fdt) {
+		pr_debug("No DTB found\n");
+		return 0;
+	}
+
+	root = of_unflatten_dtb(fdt);
+
+	if (!of_device_is_compatible(root, "linux,dummy-virt")) {
+		of_delete_node(root);
+		return 0;
+	}
+
+	overlay = of_unflatten_dtb(__dtb_overlay_of_flash_start);
+	of_overlay_apply_tree(root, overlay);
+	barebox_register_of(root);
+
+	return 0;
+}
+
+pure_initcall(replace_dtb);
 
 static int virt_probe(struct device_d *dev)
 {
diff --git a/arch/arm/boards/qemu-virt/overlay-of-flash.dts b/arch/arm/boards/qemu-virt/overlay-of-flash.dts
new file mode 100644
index 0000000000..e00dc5d7e2
--- /dev/null
+++ b/arch/arm/boards/qemu-virt/overlay-of-flash.dts
@@ -0,0 +1,97 @@
+/dts-v1/;
+/plugin/;
+/ {
+	fragment at 0 {
+		target-path = "/flash at 0";
+		__overlay__ {
+			partitions {
+				compatible = "fixed-partitions";
+				#address-cells = <1>;
+				#size-cells = <1>;
+
+				partition at 0 {
+					label = "initramfs";
+					reg = <0x0 0x3c00000>;
+				};
+
+				environment_flash: partition at 3c00000 {
+					label = "barebox-environment";
+					reg = <0x3c00000 0x200000>;
+				};
+
+				backend_state_flash: partition at 3e00000 {
+					label = "barebox-state";
+					reg = <0x3e00000 0x200000>;
+				};
+			};
+		};
+	};
+	fragment at 1 {
+		target-path="/";
+		__overlay__ {
+			chosen {
+				environment {
+					compatible = "barebox,environment";
+					device-path = "/flash at 0/partitions/partition at 3c00000";
+				};
+			};
+			aliases {
+				state = "/state";
+			};
+
+			state {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "barebox,state";
+				magic = <0x290cf8c6>;
+				backend-type = "raw";
+				backend = < &backend_state_flash >;
+				backend-stridesize = <0x200>;
+
+				bootstate {
+					#address-cells = <1>;
+					#size-cells = <1>;
+
+					system0 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+
+						remaining_attempts at 0 {
+							reg = <0x0 0x4>;
+							type = "uint32";
+							default = <3>;
+						};
+
+						priority at 4 {
+							reg = <0x4 0x4>;
+							type = "uint32";
+							default = <20>;
+						};
+					};
+
+					system1 {
+						#address-cells = <1>;
+						#size-cells = <1>;
+
+						remaining_attempts at 8 {
+							reg = <0x8 0x4>;
+							type = "uint32";
+							default = <3>;
+						};
+
+						priority at c {
+							reg = <0xc 0x4>;
+							type = "uint32";
+							default = <21>;
+						};
+					};
+
+					last_chosen at 10 {
+						reg = <0x10 0x4>;
+						type = "uint32";
+					};
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/configs/vexpress_defconfig b/arch/arm/configs/vexpress_defconfig
index f17af2bb95..760e39b440 100644
--- a/arch/arm/configs/vexpress_defconfig
+++ b/arch/arm/configs/vexpress_defconfig
@@ -50,6 +50,7 @@ CONFIG_NET=y
 CONFIG_NET_NFS=y
 CONFIG_NET_NETCONSOLE=y
 CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_OF_OVERLAY=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_DRIVER_NET_SMC91111=y
 # CONFIG_SPI is not set
diff --git a/arch/arm/mach-vexpress/Kconfig b/arch/arm/mach-vexpress/Kconfig
index 9d301f7ae8..557c9653f4 100644
--- a/arch/arm/mach-vexpress/Kconfig
+++ b/arch/arm/mach-vexpress/Kconfig
@@ -11,5 +11,6 @@ config MACH_VIRT
 	bool "QEMU virt"
 	select ARM_PSCI_CLIENT
 	select BOARD_ARM_GENERIC_DT
+	select OF_OVERLAY
 
 endif
-- 
2.29.2



From r.czerwinski at pengutronix.de  Wed Jan 13 02:57:56 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Wed, 13 Jan 2021 08:57:56 +0100
Subject: [PATCH 1/2] of: overlay: do not parse phandles as properties
Message-ID: <20210113075757.21478-1-r.czerwinski@pengutronix.de>

Instead of handling phandles as properties, assign them directly as a
handle to the node. This allows phandles within nodes inside the device
tree overlays to be handled correctly.

Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
---
 drivers/of/overlay.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index b79dbff94d..0bebe26e39 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -58,6 +58,11 @@ static int of_overlay_apply(struct device_node *target,
 		if (of_prop_cmp(prop->name, "name") == 0)
 			continue;
 
+		if (of_prop_cmp(prop->name, "phandle") == 0) {
+			target->phandle = be32_to_cpup(prop->value);
+			continue;
+		}
+
 		err = of_set_property(target, prop->name, prop->value,
 				      prop->length, true);
 		if (err)
-- 
2.29.2



From sha at pengutronix.de  Wed Jan 13 04:03:50 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 13 Jan 2021 10:03:50 +0100
Subject: [PATCH 1/2] image-sparse: change retlen to size_t
In-Reply-To: <20210111103205.4330-1-s.trumtrar@pengutronix.de>
References: <20210111103205.4330-1-s.trumtrar@pengutronix.de>
Message-ID: <20210113090350.GF19063@pengutronix.de>

On Mon, Jan 11, 2021 at 11:32:04AM +0100, Steffen Trumtrar wrote:
> retlen can potentially overflow. Also, write_full() in
> fastboot_handle_sparse() expects size_t anyway.
> 
> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> ---
>  common/fastboot.c      | 2 +-
>  include/image-sparse.h | 2 +-
>  lib/image-sparse.c     | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)

Applied to master, thanks

Sascha

> 
> diff --git a/common/fastboot.c b/common/fastboot.c
> index 1b6dc28d8e..40b92d9982 100644
> --- a/common/fastboot.c
> +++ b/common/fastboot.c
> @@ -566,7 +566,7 @@ static int fastboot_handle_sparse(struct fastboot *fb,
>  	}
>  
>  	while (1) {
> -		int retlen;
> +		size_t retlen;
>  		loff_t pos;
>  
>  		ret = sparse_image_read(sparse, buf, &pos, bufsiz, &retlen);
> diff --git a/include/image-sparse.h b/include/image-sparse.h
> index 29242f4fd5..6bff844411 100644
> --- a/include/image-sparse.h
> +++ b/include/image-sparse.h
> @@ -60,7 +60,7 @@ struct sparse_image_ctx;
>  
>  struct sparse_image_ctx *sparse_image_open(const char *path);
>  int sparse_image_read(struct sparse_image_ctx *si, void *buf,
> -		      loff_t *pos, size_t len, int *retlen);
> +		      loff_t *pos, size_t len, size_t *retlen);
>  void sparse_image_close(struct sparse_image_ctx *si);
>  loff_t sparse_image_size(struct sparse_image_ctx *si);
>  
> diff --git a/lib/image-sparse.c b/lib/image-sparse.c
> index 0c31742ab6..8e7a52fd71 100644
> --- a/lib/image-sparse.c
> +++ b/lib/image-sparse.c
> @@ -190,7 +190,7 @@ out:
>  }
>  
>  int sparse_image_read(struct sparse_image_ctx *si, void *buf, loff_t *pos,
> -		      size_t len, int *retlen)
> +		      size_t len, size_t *retlen)
>  {
>  	size_t now;
>  	int ret, i;
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan 13 04:04:42 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 13 Jan 2021 10:04:42 +0100
Subject: [PATCH v1] MIPS: dts: ar9331: add stdout-path properties
In-Reply-To: <20210107075508.15261-1-o.rempel@pengutronix.de>
References: <20210107075508.15261-1-o.rempel@pengutronix.de>
Message-ID: <20210113090442.GG19063@pengutronix.de>

On Thu, Jan 07, 2021 at 08:55:08AM +0100, Oleksij Rempel wrote:
> With the kernel v5.11-rc2 the console will be automatically redirected
> to null if no default console is configured. Make sure the barebox is
> doing it to make kernel happy.
> 
> Signed-off-by: Oleksij Rempel <o.rempel at pengutronix.de>
> ---
>  arch/mips/dts/ar9331-dptechnics-dpt-module.dts   | 2 ++
>  arch/mips/dts/ar9331-okud-max9331.dts            | 2 ++
>  arch/mips/dts/ar9331-openembed-som9331-board.dts | 2 ++
>  3 files changed, 6 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/arch/mips/dts/ar9331-dptechnics-dpt-module.dts b/arch/mips/dts/ar9331-dptechnics-dpt-module.dts
> index cbaf5ab39e..24ce0d0d67 100644
> --- a/arch/mips/dts/ar9331-dptechnics-dpt-module.dts
> +++ b/arch/mips/dts/ar9331-dptechnics-dpt-module.dts
> @@ -7,6 +7,8 @@
>  	};
>  
>  	chosen {
> +		stdout-path = &uart;
> +
>  		environment {
>  			compatible = "barebox,environment";
>  			device-path = &spiflash, "partname:barebox-environment";
> diff --git a/arch/mips/dts/ar9331-okud-max9331.dts b/arch/mips/dts/ar9331-okud-max9331.dts
> index 53350899f9..3b93bee93b 100644
> --- a/arch/mips/dts/ar9331-okud-max9331.dts
> +++ b/arch/mips/dts/ar9331-okud-max9331.dts
> @@ -17,6 +17,8 @@
>  	};
>  
>  	chosen {
> +		stdout-path = &uart;
> +
>  		environment {
>  			compatible = "barebox,environment";
>  			device-path = &spiflash, "partname:barebox-environment";
> diff --git a/arch/mips/dts/ar9331-openembed-som9331-board.dts b/arch/mips/dts/ar9331-openembed-som9331-board.dts
> index ff9d25e352..4736332f8f 100644
> --- a/arch/mips/dts/ar9331-openembed-som9331-board.dts
> +++ b/arch/mips/dts/ar9331-openembed-som9331-board.dts
> @@ -33,6 +33,8 @@
>  
>  
>  	chosen {
> +		stdout-path = &uart;
> +
>  		environment {
>  			compatible = "barebox,environment";
>  			device-path = &spiflash, "partname:barebox-environment";
> -- 
> 2.30.0
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan 13 04:05:26 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 13 Jan 2021 10:05:26 +0100
Subject: [PATCH] Documentation: boards: sandbox: describe --image flags
In-Reply-To: <20210111143555.13002-1-a.fatoum@pengutronix.de>
References: <20210111143555.13002-1-a.fatoum@pengutronix.de>
Message-ID: <20210113090526.GH19063@pengutronix.de>

On Mon, Jan 11, 2021 at 03:35:55PM +0100, Ahmad Fatoum wrote:
> barebox partition table parsing can be tested in sandbox using the
> recently added ,blkdev flag. Extend the documentation to cover this.
> 
> Cc: Juergen Borleis <jbe at pengutronix.de>
> Reported-by: Lucas Stach <lst at pengutronix.de>
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
>  Documentation/boards/sandbox.rst | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/Documentation/boards/sandbox.rst b/Documentation/boards/sandbox.rst
> index 8b24b6a64584..e9e5183653e6 100644
> --- a/Documentation/boards/sandbox.rst
> +++ b/Documentation/boards/sandbox.rst
> @@ -34,6 +34,20 @@ Available sandbox invocation options include:
>      Map a <file> to barebox. This option can be given multiple times. The <file>s
>      will show up as ``/dev/fd0`` ... ``/dev/fdX`` in the barebox simulator.
>  
> +    How the file is mapped in barebox can be controlled by a number of flags:
> +
> +    * ``,ro``: The host file is mapped read-only
> +
> +    * ``,blkdev``: The host file is to be mapped as block device. This is the
> +      default when passing block devices from the host. The file's size must
> +      be a multiple of the barebox sector size of 512 bytes.
> +
> +    * ``,cdev``: The host file is mapped as character device. This is the default,
> +      unless the the host file is a block device.
> +
> +    Multiple options can be appended if they don't clash. Literal commas within the
> +    file path can be escaped with a backslash. Example: ``-i './0\,0.hdimg,blkdev,ro'``.
> +
>    ``-e <file>``
>  
>      Map <file> to barebox. With this option <file>s are mapped as
> -- 
> 2.30.0
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan 13 04:06:21 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 13 Jan 2021 10:06:21 +0100
Subject: [PATCH] imd: change disabled checksum tag info to debug
In-Reply-To: <20210112093801.2632-1-str@pengutronix.de>
References: <20210112093801.2632-1-str@pengutronix.de>
Message-ID: <20210113090621.GI19063@pengutronix.de>

On Tue, Jan 12, 2021 at 10:38:01AM +0100, Steffen Trumtrar wrote:
> From: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> 
> When the checksum tag is disabled the CRC is most likely invalid.
> And if the checksum tag is disabled and the CRC is actually invalid the
> user doesn't care for it anyway.
> 
> This information only confuses the user so make it a debug message.
> 
> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> ---
>  common/imd.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Applied to master, thanks

Sascha

> 
> diff --git a/common/imd.c b/common/imd.c
> index ef9eff876b..aff3b00b6b 100644
> --- a/common/imd.c
> +++ b/common/imd.c
> @@ -406,7 +406,7 @@ int imd_verify_crc32(void *buf, size_t size)
>  			       *p, crc);
>  			return -EILSEQ;
>  		} else if (*p != crc && !imd_crc32_is_valid(*flags)) {
> -			printf("CRC: is invalid, but the checksum tag is not enabled\n");
> +			debug("CRC: is invalid, but the checksum tag is not enabled\n");
>  			return -EINVAL;
>  		} else {
>  			printf("CRC: valid\n");
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan 13 04:08:08 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 13 Jan 2021 10:08:08 +0100
Subject: [PATCH] documentation: devicetree: migrate remaining binding to
 reST
In-Reply-To: <20210112135120.15811-1-a.fatoum@pengutronix.de>
References: <20210112135120.15811-1-a.fatoum@pengutronix.de>
Message-ID: <20210113090808.GJ19063@pengutronix.de>

On Tue, Jan 12, 2021 at 02:51:20PM +0100, Ahmad Fatoum wrote:
> Eventually, we will want to have formalized YAML bindings and scripts to
> turn them into reST for display in the online documentation.
> 
> For now, just turn the remaining text files into reST, so they can be
> searched as well.
> 
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---

Applied, thanks

Sascha

>  ...ive-serial.txt => altr,passive-serial.rst} | 16 +++----
>  ...fpga-mgr.txt => altr,socfpga-fpga-mgr.rst} |  8 ++--
>  .../devicetree/bindings/mtd/partition.rst     | 42 +++++++++++++++++++
>  .../devicetree/bindings/mtd/partition.txt     | 39 -----------------
>  4 files changed, 56 insertions(+), 49 deletions(-)
>  rename Documentation/devicetree/bindings/firmware/{altr,passive-serial.txt => altr,passive-serial.rst} (51%)
>  rename Documentation/devicetree/bindings/firmware/{altr,socfpga-fpga-mgr.txt => altr,socfpga-fpga-mgr.rst} (74%)
>  create mode 100644 Documentation/devicetree/bindings/mtd/partition.rst
>  delete mode 100644 Documentation/devicetree/bindings/mtd/partition.txt
> 
> diff --git a/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt b/Documentation/devicetree/bindings/firmware/altr,passive-serial.rst
> similarity index 51%
> rename from Documentation/devicetree/bindings/firmware/altr,passive-serial.txt
> rename to Documentation/devicetree/bindings/firmware/altr,passive-serial.rst
> index eec12fbace52..1012137bc93b 100644
> --- a/Documentation/devicetree/bindings/firmware/altr,passive-serial.txt
> +++ b/Documentation/devicetree/bindings/firmware/altr,passive-serial.rst
> @@ -1,20 +1,22 @@
>  Altera FPGAs in passive serial mode
> ------------------------------------
> +===================================
>  
>  This binding defines the control interface to Altera FPGAs in
>  passive serial mode. This is used to upload the firmware and
>  to start the FPGA.
>  
>  Required properties:
> -- compatible: shall be "altr,fpga-passive-serial" or
> -  "altr,fpga-arria10-passive-serial" for Arria 10
> -- reg: SPI chip select
> -- nstat-gpios: Specify GPIO for controlling the nstat pin
> -- confd-gpios: Specify GPIO for controlling the confd pin
> -- nconfig-gpios: Specify GPIO for controlling the nconfig pin
> +- ``compatible``: shall be ``"altr,fpga-passive-serial"`` or
> +  ``"altr,fpga-arria10-passive-serial"`` for Arria 10
> +- ``reg``: SPI chip select
> +- ``nstat-gpios``: Specify GPIO for controlling the nstat pin
> +- ``confd-gpios``: Specify GPIO for controlling the confd pin
> +- ``nconfig-gpios``: Specify GPIO for controlling the nconfig pin
>  
>  Example:
>  
> +.. code-block:: none
> +
>  	fpga at 0 {
>  		compatible = "altr,fpga-passive-serial";
>  		nstat-gpios = <&gpio4 18 0>;
> diff --git a/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt b/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst
> similarity index 74%
> rename from Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt
> rename to Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst
> index 70ec4abf25b4..9f7de6b98580 100644
> --- a/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.txt
> +++ b/Documentation/devicetree/bindings/firmware/altr,socfpga-fpga-mgr.rst
> @@ -1,17 +1,19 @@
>  Altera SOCFPGA FPGA Manager
> ----------------------------
> +===========================
>  
>  This binding defines the FPGA Manager on Altera SOCFPGAs. This is used to upload
>  the firmware to the FPGA part of the SoC.
>  
>  Required properties:
> -- compatible: shall be "altr,socfpga-fpga-mgr"
> -- reg: Must contain 2 register ranges:
> +- ``compatible``: shall be ``"altr,socfpga-fpga-mgr"``
> +- ``reg``: Must contain 2 register ranges:
>  	1. The control address space of the FPGA manager.
>  	2. The configuration data address space where the firmware data is written to.
>  
>  Example:
>  
> +.. code-block:: none
> +
>  	fpgamgr at ff706000 {
>  		compatible = "altr,socfpga-fpga-mgr";
>  		reg = <0xff706000 0x1000>,
> diff --git a/Documentation/devicetree/bindings/mtd/partition.rst b/Documentation/devicetree/bindings/mtd/partition.rst
> new file mode 100644
> index 000000000000..6db54070a991
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mtd/partition.rst
> @@ -0,0 +1,42 @@
> +Representing flash partitions in devicetree
> +===========================================
> +
> +In addition to the upstream binding, another property is added:
> +
> +Optional properties:
> +- ``partuuid`` : The partition UUID for this partition.
> +
> +Additionally, barebox also supports partitioning the eMMC boot partitions if
> +the partition table node is named appropriately:
> +- ``partitions`` : user partition
> +- ``boot0-partitions`` : boot0 partition
> +- ``boot1-partitions`` : boot1 partition
> +
> +Examples:
> +
> +.. code-block:: none
> +
> +  flash at 0 {
> +  	partitions {
> +  		compatible = "fixed-partitions";
> +  		#address-cells = <1>;
> +  		#size-cells = <1>;
> +
> +  		state_part: state {
> +  			partuuid = "16367da7-c518-499f-9aad-e1f366692365";
> +  		};
> +  	};
> +  };
> +
> +  emmc at 1 {
> +  	boot0-partitions {
> +  		compatible = "fixed-partitions";
> +  		#address-cells = <1>;
> +  		#size-cells = <1>;
> +
> +  		barebox at 0 {
> +  			label = "barebox";
> +  			reg = <0x0 0x300000>;
> +  		};
> +  	};
> +  };
> diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt
> deleted file mode 100644
> index 4288a82437b4..000000000000
> --- a/Documentation/devicetree/bindings/mtd/partition.txt
> +++ /dev/null
> @@ -1,39 +0,0 @@
> -Representing flash partitions in devicetree
> -
> -In addition to the upstream binding, another property is added:
> -
> -Optional properties:
> -- partuuid : The partition UUID for this partition.
> -
> -Additionally, barebox also supports partitioning the eMMC boot partitions if
> -the partition table node is named appropriately:
> -- partitions : user partition
> -- boot0-partitions : boot0 partition
> -- boot1-partitions : boot1 partition
> -
> -Examples:
> -
> -flash at 0 {
> -	partitions {
> -		compatible = "fixed-partitions";
> -		#address-cells = <1>;
> -		#size-cells = <1>;
> -
> -		state_part: state {
> -			partuuid = "16367da7-c518-499f-9aad-e1f366692365";
> -		};
> -	};
> -};
> -
> -emmc at 1 {
> -	boot0-partitions {
> -		compatible = "fixed-partitions";
> -		#address-cells = <1>;
> -		#size-cells = <1>;
> -
> -		barebox at 0 {
> -			label = "barebox";
> -			reg = <0x0 0x300000>;
> -		};
> -	};
> -};
> -- 
> 2.30.0
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Wed Jan 13 04:22:18 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 13 Jan 2021 10:22:18 +0100
Subject: [PATCH 1/2] of: overlay: do not parse phandles as properties
In-Reply-To: <20210113075757.21478-1-r.czerwinski@pengutronix.de>
References: <20210113075757.21478-1-r.czerwinski@pengutronix.de>
Message-ID: <20210113092218.GK19063@pengutronix.de>

On Wed, Jan 13, 2021 at 08:57:56AM +0100, Rouven Czerwinski wrote:
> Instead of handling phandles as properties, assign them directly as a
> handle to the node. This allows phandles within nodes inside the device
> tree overlays to be handled correctly.
> 
> Signed-off-by: Rouven Czerwinski <r.czerwinski at pengutronix.de>
> ---
>  drivers/of/overlay.c | 5 +++++
>  1 file changed, 5 insertions(+)

Applied, thanks

Sascha

> 
> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> index b79dbff94d..0bebe26e39 100644
> --- a/drivers/of/overlay.c
> +++ b/drivers/of/overlay.c
> @@ -58,6 +58,11 @@ static int of_overlay_apply(struct device_node *target,
>  		if (of_prop_cmp(prop->name, "name") == 0)
>  			continue;
>  
> +		if (of_prop_cmp(prop->name, "phandle") == 0) {
> +			target->phandle = be32_to_cpup(prop->value);
> +			continue;
> +		}
> +
>  		err = of_set_property(target, prop->name, prop->value,
>  				      prop->length, true);
>  		if (err)
> -- 
> 2.29.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.felsch at pengutronix.de  Wed Jan 13 06:07:47 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 13 Jan 2021 12:07:47 +0100
Subject: Barebox OF-Overlay Handling
Message-ID: <20210113110747.j25v7lnrlgdx62ns@pengutronix.de>

Hi there,

I have the following problem. My customer is using overlays for
external devices like: display, camera, etc. The current overlay support
is awesome and most of it works out of the box. There is only one
nitpick: If Barebox isn't build with CONFIG_OF_OVERLAY_LIVE enabled many
error's are printed during boot. Those error's are ignored but let the
user assume that something went really bad:

ERROR: of_resolver: __symbols__ missing from base devicetree
ERROR: of_overlay: fragment 30164b88: phandle 0xffffffff not found
ERROR: of_overlay: fragment 30164c84: phandle 0xffffffff not found
ERROR: of_overlay: fragment 3012fb08: phandle 0xffffffff not found
ERROR: of_overlay: fragment 3012fc34: phandle 0xffffffff not found
ERROR: of_overlay: fragment 3012fd60: phandle 0xffffffff not found
ERROR: of_overlay: fragment 3012fe8c: phandle 0xffffffff not found
ERROR: of_overlay: fragment 3012ffb8: phandle 0xffffffff not found
ERROR: of_overlay: fragment 301300e4: phandle 0xffffffff not found
ERROR: of_overlay: fragment 30130210: phandle 0xffffffff not found
ERROR: of_overlay: fragment 3013033c: phandle 0xffffffff not found
ERROR: of_resolver: __symbols__ missing from base devicetree
ERROR: of_overlay: fragment 30130e94: phandle 0xffffffff not found
ERROR: of_overlay: fragment 30130fc4: phandle 0xffffffff not found
ERROR: of_resolver: __symbols__ missing from base devicetree
ERROR: of_overlay: fragment 30131a14: phandle 0xffffffff not found
ERROR: of_overlay: fragment 301342d4: phandle 0xffffffff not found

The of_firmware_load_overlay() calls triggering those errors.
The error's by itself are correct and I don't wanna change them but the
context must be correct by context I mean:

 - barebox-dt on fpga-platform: An FPGA platform needs a barebox
   base devicetree with __symbols__ and those error are correct because
   the firmware manager needs to load the firmware.
 - barebox-dt on non fpga-platform: Those errors are not correct.
   We don't need __symbols__ for the barebox base devicetree.
 - kernel-dt on any platform: Those error's are correct if
   the overlays are using phandles which should be the case most the
   time.

My proposed solution would be a stub like this:

#ifdef CONFIG_OF_OVERLAY_LIVE
int of_firmware_load_overlay(struct device_node *overlay, const char *path);
#else
static inline int of_firmware_load_overlay(struct device_node *overlay, const char *path)
{
       return 0;
}
#endif /* CONFIG_OF_OVERLAY_LIVE */

The disadvantage of this solution is that it can happen to end in a
non-booting device for FPGA platforms using overlays to programm the
bit stream and forget to enable CONFIG_OF_OVERLAY_LIVE because the
kernel tries to access regions not existing.

I've discussed this with Michael in private but we didn't came to a
conclusion. Therefore I'm asking here any input would be helpfull :)

Regards,
  Marco


From r.czerwinski at pengutronix.de  Wed Jan 13 09:07:48 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Wed, 13 Jan 2021 15:07:48 +0100
Subject: Barebox OF-Overlay Handling
In-Reply-To: <20210113110747.j25v7lnrlgdx62ns@pengutronix.de>
References: <20210113110747.j25v7lnrlgdx62ns@pengutronix.de>
Message-ID: <6d092867cfc86c63c2eb12fd7a156769d8a8d1f1.camel@pengutronix.de>

On Wed, 2021-01-13 at 12:07 +0100, Marco Felsch wrote:
> Hi there,
> 
> I have the following problem. My customer is using overlays for
> external devices like: display, camera, etc. The current overlay support
> is awesome and most of it works out of the box. There is only one
> nitpick: If Barebox isn't build with CONFIG_OF_OVERLAY_LIVE enabled many
> error's are printed during boot. Those error's are ignored but let the
> user assume that something went really bad:
> 
> ERROR: of_resolver: __symbols__ missing from base devicetree
> ERROR: of_overlay: fragment 30164b88: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 30164c84: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 3012fb08: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 3012fc34: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 3012fd60: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 3012fe8c: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 3012ffb8: phandle 0xffffwfffffff not found
> ERROR: of_overlay: fragment 301300e4: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 30130210: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 3013033c: phandle 0xffffffff not found
> ERROR: of_resolver: __symbols__ missing from base devicetree
> ERROR: of_overlay: fragment 30130e94: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 30130fc4: phandle 0xffffffff not found
> ERROR: of_resolver: __symbols__ missing from base devicetree
> ERROR: of_overlay: fragment 30131a14: phandle 0xffffffff not found
> ERROR: of_overlay: fragment 301342d4: phandle 0xffffffff not found
> 
> The of_firmware_load_overlay() calls triggering those errors.
> The error's by itself are correct and I don't wanna change them but the
> context must be correct by context I mean:
> 
> ?- barebox-dt on fpga-platform: An FPGA platform needs a barebox
> ???base devicetree with __symbols__ and those error are correct because
> ???the firmware manager needs to load the firmware.
> ?- barebox-dt on non fpga-platform: Those errors are not correct.
> ???We don't need __symbols__ for the barebox base devicetree.

I was wondering why you were getting this error even on a platform
without FPGA, turns out of_firmware_load_overlay() is always called if
a devicetree overlay is passed via the DT. This in itself isn't a
problem, but IMO of_firmware_load_overlay() should check first whether
the overlay contains the right compatible ("fpga-region") and property
("firmware-name") before doing of_resolve_phandles and
of_process_overlay. This way we can skip a lot of unnecessary overlay
handling if we don't end up loading a firmware.
 
> ?- kernel-dt on any platform: Those error's are correct if
> ???the overlays are using phandles which should be the case most the
> ???time.

AFAICS this should also fix this case.

> My proposed solution would be a stub like this:
> 
> #ifdef CONFIG_OF_OVERLAY_LIVE
> int of_firmware_load_overlay(struct device_node *overlay, const char *path);
> #else
> static inline int of_firmware_load_overlay(struct device_node *overlay, const char *path)
> {
> ???????return 0;
> }
> #endif /* CONFIG_OF_OVERLAY_LIVE */

While correct in case all firmware overlays use phandles, in theory
overlays could be purely path-based, with not dependency on the
__symbols__ node. Not sure how common this is.

> The disadvantage of this solution is that it can happen to end in a
> non-booting device for FPGA platforms using overlays to programm the
> bit stream and forget to enable CONFIG_OF_OVERLAY_LIVE because the
> kernel tries to access regions not existing.
> 
> I've discussed this with Michael in private but we didn't came to a
> conclusion. Therefore I'm asking here any input would be helpfull :)

Regards,
Rouven Czerwinski



From m.tretter at pengutronix.de  Wed Jan 13 09:52:23 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Wed, 13 Jan 2021 15:52:23 +0100
Subject: Barebox OF-Overlay Handling
In-Reply-To: <6d092867cfc86c63c2eb12fd7a156769d8a8d1f1.camel@pengutronix.de>
References: <20210113110747.j25v7lnrlgdx62ns@pengutronix.de>
 <6d092867cfc86c63c2eb12fd7a156769d8a8d1f1.camel@pengutronix.de>
Message-ID: <20210113145223.GD29774@pengutronix.de>

On Wed, 13 Jan 2021 15:07:48 +0100, Rouven Czerwinski wrote:
> On Wed, 2021-01-13 at 12:07 +0100, Marco Felsch wrote:
> > Hi there,
> > 
> > I have the following problem. My customer is using overlays for
> > external devices like: display, camera, etc. The current overlay support
> > is awesome and most of it works out of the box. There is only one
> > nitpick: If Barebox isn't build with CONFIG_OF_OVERLAY_LIVE enabled many
> > error's are printed during boot. Those error's are ignored but let the
> > user assume that something went really bad:
> > 
> > ERROR: of_resolver: __symbols__ missing from base devicetree
> > ERROR: of_overlay: fragment 30164b88: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 30164c84: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 3012fb08: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 3012fc34: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 3012fd60: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 3012fe8c: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 3012ffb8: phandle 0xffffwfffffff not found
> > ERROR: of_overlay: fragment 301300e4: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 30130210: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 3013033c: phandle 0xffffffff not found
> > ERROR: of_resolver: __symbols__ missing from base devicetree
> > ERROR: of_overlay: fragment 30130e94: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 30130fc4: phandle 0xffffffff not found
> > ERROR: of_resolver: __symbols__ missing from base devicetree
> > ERROR: of_overlay: fragment 30131a14: phandle 0xffffffff not found
> > ERROR: of_overlay: fragment 301342d4: phandle 0xffffffff not found
> > 
> > The of_firmware_load_overlay() calls triggering those errors.
> > The error's by itself are correct and I don't wanna change them but the
> > context must be correct by context I mean:
> > 
> > ?- barebox-dt on fpga-platform: An FPGA platform needs a barebox
> > ???base devicetree with __symbols__ and those error are correct because
> > ???the firmware manager needs to load the firmware.
> > ?- barebox-dt on non fpga-platform: Those errors are not correct.
> > ???We don't need __symbols__ for the barebox base devicetree.
> 
> I was wondering why you were getting this error even on a platform
> without FPGA, turns out of_firmware_load_overlay() is always called if
> a devicetree overlay is passed via the DT. This in itself isn't a
> problem, but IMO of_firmware_load_overlay() should check first whether
> the overlay contains the right compatible ("fpga-region") and property
> ("firmware-name") before doing of_resolve_phandles and
> of_process_overlay. This way we can skip a lot of unnecessary overlay
> handling if we don't end up loading a firmware.

At the moment, the check and firmware load path use the same code path,
because there is no difference except that firmware load requires a resolved
overlay and the check does not. This is a viable solution and there is even a
helper to iterate the fragments and call a check function for each fragment.
However the helper calls find_target, which is responsible for most of the
error messages, and therefore, does not completely resolve the issue.

(Indeed, the check if the fragment has the "fpga-region" compatible is
missing. That's a bug.)

I would rather change the error logging to only log errors if actually
something goes wrong. Because none of the aforementioned errors is actually
fatal from a system perspective, but only from a function perspective.
Furthermore, the messages are not helpful at all to actually find the problem
in case of a unresolved overlay.

>  
> > ?- kernel-dt on any platform: Those error's are correct if
> > ???the overlays are using phandles which should be the case most the
> > ???time.
> 
> AFAICS this should also fix this case.
> 
> > My proposed solution would be a stub like this:
> > 
> > #ifdef CONFIG_OF_OVERLAY_LIVE
> > int of_firmware_load_overlay(struct device_node *overlay, const char *path);
> > #else
> > static inline int of_firmware_load_overlay(struct device_node *overlay, const char *path)
> > {
> > ???????return 0;
> > }
> > #endif /* CONFIG_OF_OVERLAY_LIVE */

Nack. of_firmware_load_overlay must fail if the overlay describes an
fpga-region. Otherwise the device tree that is passed to the kernel might have
an fpga-region with a firmware-name property and that per specification
requires that the fpga is programmed.

Michael

> 
> While correct in case all firmware overlays use phandles, in theory
> overlays could be purely path-based, with not dependency on the
> __symbols__ node. Not sure how common this is.

> 
> > The disadvantage of this solution is that it can happen to end in a
> > non-booting device for FPGA platforms using overlays to programm the
> > bit stream and forget to enable CONFIG_OF_OVERLAY_LIVE because the
> > kernel tries to access regions not existing.
> > 
> > I've discussed this with Michael in private but we didn't came to a
> > conclusion. Therefore I'm asking here any input would be helpfull :)
> 
> Regards,
> Rouven Czerwinski
> 
> 


From r.czerwinski at pengutronix.de  Wed Jan 13 12:00:18 2021
From: r.czerwinski at pengutronix.de (Rouven Czerwinski)
Date: Wed, 13 Jan 2021 18:00:18 +0100
Subject: [PATCH] fixup! of: overlay: do not parse phandles as properties
Message-ID: <20210113170018.8045-1-r.czerwinski@pengutronix.de>

This breaks the eventual fixup of phandles into the linux device tree.
Fix this by also keeping the phandle properties in the DT.
---
 drivers/of/overlay.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 0bebe26e39..d7695726fc 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -60,7 +60,6 @@ static int of_overlay_apply(struct device_node *target,
 
 		if (of_prop_cmp(prop->name, "phandle") == 0) {
 			target->phandle = be32_to_cpup(prop->value);
-			continue;
 		}
 
 		err = of_set_property(target, prop->name, prop->value,
-- 
2.29.2



From m.felsch at pengutronix.de  Wed Jan 13 12:12:58 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 13 Jan 2021 18:12:58 +0100
Subject: [PATCH] fixup! of: overlay: do not parse phandles as properties
In-Reply-To: <20210113170018.8045-1-r.czerwinski@pengutronix.de>
References: <20210113170018.8045-1-r.czerwinski@pengutronix.de>
Message-ID: <20210113171258.sk3k6cph7irdsl3s@pengutronix.de>

On 21-01-13 18:00, Rouven Czerwinski wrote:
> This breaks the eventual fixup of phandles into the linux device tree.
> Fix this by also keeping the phandle properties in the DT.
> ---
>  drivers/of/overlay.c | 1 -
>  1 file changed, 1 deletion(-)
> 
> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> index 0bebe26e39..d7695726fc 100644
> --- a/drivers/of/overlay.c
> +++ b/drivers/of/overlay.c
> @@ -60,7 +60,6 @@ static int of_overlay_apply(struct device_node *target,
>  
>  		if (of_prop_cmp(prop->name, "phandle") == 0) {
>  			target->phandle = be32_to_cpup(prop->value);
> -			continue;
>  		}

Nit:

We could also remove the {} so it's becoming a two-liner :)

Regards,
  Marco

>  
>  		err = of_set_property(target, prop->name, prop->value,
> -- 
> 2.29.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From donnie at sihovision.com  Thu Jan 14 00:05:05 2021
From: donnie at sihovision.com (donnie at sihovision.com)
Date: Thu, 14 Jan 2021 13:05:05 +0800
Subject: Cordless Design Industrial Embedded Touch Panel PC
In-Reply-To: <2021010014130500050753@tradepro.net>
Message-ID: <2021010014130500050753@tradepro.net>

Dear Sir/Madame,
This is Donnie from Sihovison, I'd like to introduce our new type Cordless Design Industrial Touch Panel PC, for more ruged enviroments.
Cordless Motherboard Design 
If you are interested, pls feel free to contact me for specs and quotation.
_________________________________________________
Best regards,
Donnie Nie
SHINHO ELECTRONIC
www.sihovision.com
TEL/Whatsapp: 0086 13163734006
Skype: donnie.shinho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/e4480e80/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-2.jpg
Type: image/jpeg
Size: 33388 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/e4480e80/attachment-0005.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-3.jpg
Type: image/jpeg
Size: 36765 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/e4480e80/attachment-0006.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-4.jpg
Type: image/jpeg
Size: 44663 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/e4480e80/attachment-0007.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-1.jpg
Type: image/jpeg
Size: 47661 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/e4480e80/attachment-0008.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: logo2.jpg
Type: image/jpeg
Size: 2231 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/e4480e80/attachment-0009.jpg>

From donnie at sihovision.com  Thu Jan 14 00:37:39 2021
From: donnie at sihovision.com (donnie at sihovision.com)
Date: Thu, 14 Jan 2021 13:37:39 +0800
Subject: Shock-proof Design Industrial AIO Panel PC
In-Reply-To: <2021010014133700390911@tradepro.net>
Message-ID: <2021010014133700390911@tradepro.net>

Hi,
I'd like to introduce a new type Industrial Touch Panel PC, 
cordless motherboard design, 
shock-proof design, 
authentic industrial grade compter, 
for more ruged environments.
cordless motherboard design
If you need more information, pls feel free to contact me, thanks. 
____________________________________________
Best regards,
Donnie Nie
SHINHO ELECTRONIC
www.sihovision.com
TEL/Whatsapp: 0086 13163734006
Skype: donnie.shinho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/f959edd2/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-2.jpg
Type: image/jpeg
Size: 33388 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/f959edd2/attachment-0005.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-3.jpg
Type: image/jpeg
Size: 36765 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/f959edd2/attachment-0006.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-4.jpg
Type: image/jpeg
Size: 44663 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/f959edd2/attachment-0007.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-1.jpg
Type: image/jpeg
Size: 47661 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/f959edd2/attachment-0008.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: logo2.jpg
Type: image/jpeg
Size: 2231 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/f959edd2/attachment-0009.jpg>

From s.hauer at pengutronix.de  Thu Jan 14 04:30:40 2021
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 14 Jan 2021 10:30:40 +0100
Subject: [PATCH] mtd: nand: fix NAND_ECC_HW mode
Message-ID: <20210114093040.9480-1-s.hauer@pengutronix.de>

6748f466a3 made NAND_ECC_HW_SYNDROME mode optional by bailing out
with -ENOSYS when the mode is not enabled in Kconfig. Unfortunately
with NAND_ECC_HW mode the code falls through to this test, so with
NAND_ECC_HW_SYNDROME support disabled NAND_ECC_HW stopped working as
well. Fix this.

fixes: 6748f466a3 ("mtd: nand: Make support for syndrome hardware ecc optional")
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/mtd/nand/nand_base.c | 35 ++++++++++++++++++-----------------
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 427aa7f0ec..b37017372f 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -5622,10 +5622,6 @@ int nand_scan_tail(struct nand_chip *chip)
 		if (!ecc->write_subpage && ecc->hwctl && ecc->calculate)
 			ecc->write_subpage = nand_write_subpage_hwecc;
 	case NAND_ECC_HW_SYNDROME:
-		if (!IS_ENABLED(CONFIG_NAND_ECC_HW_SYNDROME)) {
-			ret = -ENOSYS;
-			goto err_nand_manuf_cleanup;
-		}
 		if ((!ecc->calculate || !ecc->correct || !ecc->hwctl) &&
 		    (!ecc->read_page ||
 		     ecc->read_page == nand_read_page_hwecc ||
@@ -5635,19 +5631,24 @@ int nand_scan_tail(struct nand_chip *chip)
 			ret = -EINVAL;
 			goto err_nand_manuf_cleanup;
 		}
-		/* Use standard syndrome read/write page function? */
-		if (!ecc->read_page)
-			ecc->read_page = nand_read_page_syndrome;
-		if (!ecc->write_page)
-			ecc->write_page = nand_write_page_syndrome;
-		if (!ecc->read_page_raw)
-			ecc->read_page_raw = nand_read_page_raw_syndrome;
-		if (!ecc->write_page_raw)
-			ecc->write_page_raw = nand_write_page_raw_syndrome;
-		if (!ecc->read_oob)
-			ecc->read_oob = nand_read_oob_syndrome;
-		if (!ecc->write_oob)
-			ecc->write_oob = nand_write_oob_syndrome;
+		if (IS_ENABLED(CONFIG_NAND_ECC_HW_SYNDROME)) {
+			/* Use standard syndrome read/write page function? */
+			if (!ecc->read_page)
+				ecc->read_page = nand_read_page_syndrome;
+			if (!ecc->write_page)
+				ecc->write_page = nand_write_page_syndrome;
+			if (!ecc->read_page_raw)
+				ecc->read_page_raw = nand_read_page_raw_syndrome;
+			if (!ecc->write_page_raw)
+				ecc->write_page_raw = nand_write_page_raw_syndrome;
+			if (!ecc->read_oob)
+				ecc->read_oob = nand_read_oob_syndrome;
+			if (!ecc->write_oob)
+				ecc->write_oob = nand_write_oob_syndrome;
+		} else if (ecc->mode == NAND_ECC_HW_SYNDROME) {
+			ret = -ENOSYS;
+			goto err_nand_manuf_cleanup;
+		}
 
 		if (mtd->writesize >= ecc->size) {
 			if (!ecc->strength) {
-- 
2.20.1



From s.hauer at pengutronix.de  Thu Jan 14 04:30:55 2021
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Thu, 14 Jan 2021 10:30:55 +0100
Subject: [PATCH] startup: export PATH variable
Message-ID: <20210114093055.10154-1-s.hauer@pengutronix.de>

The PATH environment variable is set at the shell prompt, but it is not
exported, so currently scripts can't execute other scripts in PATH
anymore. PATH used to be exported in the init script, but this part was
lost when converting the init script to C. Add it back.

Fixes: 90df2a955e ("defaultenv: Convert init script to C")
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/startup.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/common/startup.c b/common/startup.c
index 767d178de8..1ac36d950c 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -307,6 +307,7 @@ static int run_init(void)
 	struct stat s;
 
 	setenv("PATH", "/env/bin");
+	export("PATH");
 
 	/* Run legacy /env/bin/init if it exists */
 	env_bin_init_exists = stat(INITFILE, &s) == 0;
-- 
2.20.1



From donnie at sihovision.com  Thu Jan 14 08:07:32 2021
From: donnie at sihovision.com (donnie at sihovision.com)
Date: Thu, 14 Jan 2021 21:07:32 +0800
Subject: Cordless Design Industrial Embedded Touch Panel PC
In-Reply-To: <2021010014210700320105@tradepro.net>
Message-ID: <2021010014210700320105@tradepro.net>

Dear Sir/Madame,
This is Donnie from Sihovison, I'd like to introduce our new type Cordless Design Industrial Touch Panel PC, for more ruged enviroments.
Cordless Motherboard Design 
If you are interested, pls feel free to contact me for specs and quotation.
_________________________________________________
Best regards,
Donnie Nie
SHINHO ELECTRONIC
www.sihovision.com
TEL/Whatsapp: 0086 13163734006
Skype: donnie.shinho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/52cdb8da/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-2.jpg
Type: image/jpeg
Size: 33388 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/52cdb8da/attachment-0005.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-3.jpg
Type: image/jpeg
Size: 36765 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/52cdb8da/attachment-0006.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-4.jpg
Type: image/jpeg
Size: 44663 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/52cdb8da/attachment-0007.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-1.jpg
Type: image/jpeg
Size: 47661 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/52cdb8da/attachment-0008.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: logo2.jpg
Type: image/jpeg
Size: 2231 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210114/52cdb8da/attachment-0009.jpg>

From ad.ensi at netc.fr  Fri Jan 15 05:22:29 2021
From: ad.ensi at netc.fr (AD)
Date: Fri, 15 Jan 2021 11:22:29 +0100
Subject: Environment is not overwritten at barebox update
Message-ID: <32b1e760-325e-b145-ba97-21aaee6ed868@netc.fr>


Dear all,

I've compiled an image and try to get my environment scripts on my 
target but I can't get them.

Here a snippet of my DTS :

/ {
 ??????? model = "Main Board";

 ??????? compatible = "fsl,imx6dl";
 ??? chosen {
 ??? ??????? stdout-path = &uart3;
 ??? };

 ??? environment at 0 {
 ??? ??? compatible = "barebox,environment";
 ??? ??? device-path = &usdhc3, "partname:barebox-environment";
 ??? };
};

&usdhc3 {
 ??? partition at 0 {
 ??? ??? label = "barebox";
 ??? ??? reg = <0x0 0x80000>;
 ??? };
 ??? partition at 1 {
 ??? ??? label = "barebox-environment";
 ??? ??? reg = <0x80000 0x80000>;
 ??? };

 ??????? ...

 ??????? # Many other partitions

 ??????? ...

};


Here a snippet of my .config :

CONFIG_DEFAULT_ENVIRONMENT=y
# CONFIG_DEFAULT_COMPRESSION_GZIP is not set
# CONFIG_DEFAULT_COMPRESSION_LZO is not set
# CONFIG_DEFAULT_COMPRESSION_LZ4 is not set
# CONFIG_DEFAULT_COMPRESSION_XZ is not set
CONFIG_DEFAULT_COMPRESSION_NONE=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW_MENU=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW_DFU=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/al-mx6/env/"

And here the content of : "arch/arm/boards/al-mx6/env/"

ad at debian:~/workspace/barebox/chrysalis/arch/arm/boards/al-mx6/env$ tree
.
??? bin
??? ??? init
??? boot
??? ??? al
??? ??? tftp
??? ??? usb
??? config
??? data
 ??? ??? ansi-colors


Now, on the target, I'm upgrading barebox using a simple : cp 
barebox.img /dev/mmc2


With the compiled date and hour from the Barebox logs at starting, I can 
see that the "new" barebox is really the one that I juste compiled.

But I don't have my env correctly updated :

barebox at Main Board:/env ls -l
drwxrwxrwx????????????? 0 .
d---------????????????? 0 ..
drwxrwxrwx????????????? 0 bin
-rwxrwxrwx???????????? 25 config
drwxrwxrwx????????????? 0 data
drwxrwxrwx????????????? 0 init
drwxrwxrwx????????????? 0 menu
drwxrwxrwx????????????? 0 network
drwxrwxrwx????????????? 0 nv


My config file is not the one that I compiled, and the boot/ directory 
has not been updated...
But the newly created files are always updated.
Only the already existing ones are not overwritten.
Not sure of that, but it seems to be different between several boards...


I am missing something?


Here the starting logs :


barebox 2019.07.0-06872-g2c7ca71f9-dirty #2 Tue Dec 8 18:41:29 CET 2020


Board: Main Board
detected i.MX6 DualLite revision 1.4
i.MX reset reason POR (SRSR: 0x00000001)
i.MX6 DualLite unique ID: f21fd23e181bc1d4
mdio_bus: miibus0: probed
imx-usb 2184200.usb at 02184200.of: USB EHCI 1.00
imx-esdhc 2194000.usdhc at 02194000.of: registered as mmc1
imx-esdhc 2198000.usdhc at 02198000.of: registered as mmc2
imx-ipuv3 2400000.ipu at 02400000.of: IPUv3H probed
caam 2100000.caam at 2100000.of: Instantiated RNG4 SH0
caam 2100000.caam at 2100000.of: Instantiated RNG4 SH1
caam 2100000.caam at 2100000.of: registering rng-caam
netconsole: registered as netconsole-1
GPR1 = 48600005
malloc space: 0x3fdf6540 -> 0x4fdf653f (size 256 MiB)
mmc2: detected MMC card version 5.0
mmc2: registered mmc2.boot0
mmc2: registered mmc2.boot1
mmc2: registered mmc2
running /env/bin/init...

Hit m for menu or any other key to stop autoboot:
type exit to get to the menu
barebox at Chrysalis Main Board:/


Thanks for everything,

AD






From a.fatoum at pengutronix.de  Fri Jan 15 05:35:25 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 15 Jan 2021 11:35:25 +0100
Subject: Environment is not overwritten at barebox update
In-Reply-To: <32b1e760-325e-b145-ba97-21aaee6ed868@netc.fr>
References: <32b1e760-325e-b145-ba97-21aaee6ed868@netc.fr>
Message-ID: <cc7279d9-f943-8b03-630e-fc7c41c9d0f2@pengutronix.de>



On 15.01.21 11:22, AD wrote:
> 
> Dear all,
> 
> I've compiled an image and try to get my environment scripts on my target but I can't get them.
> 
> Here a snippet of my DTS :
> 
> / {
> ??????? model = "Main Board";
> 
> ??????? compatible = "fsl,imx6dl";
> ??? chosen {
> ??? ??????? stdout-path = &uart3;
> ??? };
> 
> ??? environment at 0 {
> ??? ??? compatible = "barebox,environment";
> ??? ??? device-path = &usdhc3, "partname:barebox-environment";
> ??? };
> };
> 
> &usdhc3 {
> ??? partition at 0 {
> ??? ??? label = "barebox";
> ??? ??? reg = <0x0 0x80000>;
> ??? };
> ??? partition at 1 {
> ??? ??? label = "barebox-environment";
> ??? ??? reg = <0x80000 0x80000>;
> ??? };
> 
> ??????? ...
> 
> ??????? # Many other partitions
> 
> ??????? ...
> 
> };
> 
> 
> Here a snippet of my .config :
> 
> CONFIG_DEFAULT_ENVIRONMENT=y
> # CONFIG_DEFAULT_COMPRESSION_GZIP is not set
> # CONFIG_DEFAULT_COMPRESSION_LZO is not set
> # CONFIG_DEFAULT_COMPRESSION_LZ4 is not set
> # CONFIG_DEFAULT_COMPRESSION_XZ is not set
> CONFIG_DEFAULT_COMPRESSION_NONE=y
> CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
> CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW_MENU=y
> CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW_DFU=y
> CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/al-mx6/env/"
> 
> And here the content of : "arch/arm/boards/al-mx6/env/"
> 
> ad at debian:~/workspace/barebox/chrysalis/arch/arm/boards/al-mx6/env$ tree
> .
> ??? bin
> ??? ??? init
> ??? boot
> ??? ??? al
> ??? ??? tftp
> ??? ??? usb
> ??? config
> ??? data
> ??? ??? ansi-colors
> 
> 
> Now, on the target, I'm upgrading barebox using a simple : cp barebox.img /dev/mmc2
> 
> 
> With the compiled date and hour from the Barebox logs at starting, I can see that the "new" barebox is really the one that I juste compiled.
> 
> But I don't have my env correctly updated :
> 
> barebox at Main Board:/env ls -l
> drwxrwxrwx????????????? 0 .
> d---------????????????? 0 ..
> drwxrwxrwx????????????? 0 bin
> -rwxrwxrwx???????????? 25 config
> drwxrwxrwx????????????? 0 data
> drwxrwxrwx????????????? 0 init
> drwxrwxrwx????????????? 0 menu
> drwxrwxrwx????????????? 0 network
> drwxrwxrwx????????????? 0 nv
> 
> 
> My config file is not the one that I compiled, and the boot/ directory has not been updated...
> But the newly created files are always updated.
> Only the already existing ones are not overwritten.
> Not sure of that, but it seems to be different between several boards...
> 
> 
> I am missing something?
> 
> 
> Here the starting logs :
> 
> 
> barebox 2019.07.0-06872-g2c7ca71f9-dirty #2 Tue Dec 8 18:41:29 CET 2020
> 
> 
> Board: Main Board
> detected i.MX6 DualLite revision 1.4
> i.MX reset reason POR (SRSR: 0x00000001)
> i.MX6 DualLite unique ID: f21fd23e181bc1d4
> mdio_bus: miibus0: probed
> imx-usb 2184200.usb at 02184200.of: USB EHCI 1.00
> imx-esdhc 2194000.usdhc at 02194000.of: registered as mmc1
> imx-esdhc 2198000.usdhc at 02198000.of: registered as mmc2
> imx-ipuv3 2400000.ipu at 02400000.of: IPUv3H probed
> caam 2100000.caam at 2100000.of: Instantiated RNG4 SH0
> caam 2100000.caam at 2100000.of: Instantiated RNG4 SH1
> caam 2100000.caam at 2100000.of: registering rng-caam
> netconsole: registered as netconsole-1
> GPR1 = 48600005
> malloc space: 0x3fdf6540 -> 0x4fdf653f (size 256 MiB)
> mmc2: detected MMC card version 5.0
> mmc2: registered mmc2.boot0
> mmc2: registered mmc2.boot1
> mmc2: registered mmc2
> running /env/bin/init...
> 
> Hit m for menu or any other key to stop autoboot:
> type exit to get to the menu
> barebox at Chrysalis Main Board:/
> 
> 
> Thanks for everything,

The barebox mutable environment is meant as development
feature, so you can override the built-in environment.

You'll probably want to run saveenv -z to override this
and force use of the built-in environment.

Cheers,
Ahmad

> 
> AD
> 
> 
> 
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From ad.ensi at netc.fr  Fri Jan 15 07:12:21 2021
From: ad.ensi at netc.fr (AD)
Date: Fri, 15 Jan 2021 13:12:21 +0100
Subject: Environment is not overwritten at barebox update
In-Reply-To: <cc7279d9-f943-8b03-630e-fc7c41c9d0f2@pengutronix.de>
References: <32b1e760-325e-b145-ba97-21aaee6ed868@netc.fr>
 <cc7279d9-f943-8b03-630e-fc7c41c9d0f2@pengutronix.de>
Message-ID: <3add69f4-c8a3-3848-a1ea-8a041a8dafd4@netc.fr>

Dear Ahmad,

thanks for your help.

On 15/01/2021 11:35, Ahmad Fatoum wrote:
>
> On 15.01.21 11:22, AD wrote:
>> Dear all,
>>
>> I've compiled an image and try to get my environment scripts on my target but I can't get them.
>>
>> Here a snippet of my DTS :
>>
>> / {
>>  ??????? model = "Main Board";
>>
>>  ??????? compatible = "fsl,imx6dl";
>>  ??? chosen {
>>  ??? ??????? stdout-path = &uart3;
>>  ??? };
>>
>>  ??? environment at 0 {
>>  ??? ??? compatible = "barebox,environment";
>>  ??? ??? device-path = &usdhc3, "partname:barebox-environment";
>>  ??? };
>> };
>>
>> &usdhc3 {
>>  ??? partition at 0 {
>>  ??? ??? label = "barebox";
>>  ??? ??? reg = <0x0 0x80000>;
>>  ??? };
>>  ??? partition at 1 {
>>  ??? ??? label = "barebox-environment";
>>  ??? ??? reg = <0x80000 0x80000>;
>>  ??? };
>>
>>  ??????? ...
>>
>>  ??????? # Many other partitions
>>
>>  ??????? ...
>>
>> };
>>
>>
>> Here a snippet of my .config :
>>
>> CONFIG_DEFAULT_ENVIRONMENT=y
>> # CONFIG_DEFAULT_COMPRESSION_GZIP is not set
>> # CONFIG_DEFAULT_COMPRESSION_LZO is not set
>> # CONFIG_DEFAULT_COMPRESSION_LZ4 is not set
>> # CONFIG_DEFAULT_COMPRESSION_XZ is not set
>> CONFIG_DEFAULT_COMPRESSION_NONE=y
>> CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
>> CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW_MENU=y
>> CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW_DFU=y
>> CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/al-mx6/env/"
>>
>> And here the content of : "arch/arm/boards/al-mx6/env/"
>>
>> ad at debian:~/workspace/barebox/chrysalis/arch/arm/boards/al-mx6/env$ tree
>> .
>> ??? bin
>> ??? ??? init
>> ??? boot
>> ??? ??? al
>> ??? ??? tftp
>> ??? ??? usb
>> ??? config
>> ??? data
>>  ??? ??? ansi-colors
>>
>>
>> Now, on the target, I'm upgrading barebox using a simple : cp barebox.img /dev/mmc2
>>
>>
>> With the compiled date and hour from the Barebox logs at starting, I can see that the "new" barebox is really the one that I juste compiled.
>>
>> But I don't have my env correctly updated :
>>
>> barebox at Main Board:/env ls -l
>> drwxrwxrwx????????????? 0 .
>> d---------????????????? 0 ..
>> drwxrwxrwx????????????? 0 bin
>> -rwxrwxrwx???????????? 25 config
>> drwxrwxrwx????????????? 0 data
>> drwxrwxrwx????????????? 0 init
>> drwxrwxrwx????????????? 0 menu
>> drwxrwxrwx????????????? 0 network
>> drwxrwxrwx????????????? 0 nv
>>
>>
>> My config file is not the one that I compiled, and the boot/ directory has not been updated...
>> But the newly created files are always updated.
>> Only the already existing ones are not overwritten.
>> Not sure of that, but it seems to be different between several boards...
>>
>>
>> I am missing something?
>>
>>
>> Here the starting logs :
>>
>>
>> barebox 2019.07.0-06872-g2c7ca71f9-dirty #2 Tue Dec 8 18:41:29 CET 2020
>>
>>
>> Board: Main Board
>> detected i.MX6 DualLite revision 1.4
>> i.MX reset reason POR (SRSR: 0x00000001)
>> i.MX6 DualLite unique ID: f21fd23e181bc1d4
>> mdio_bus: miibus0: probed
>> imx-usb 2184200.usb at 02184200.of: USB EHCI 1.00
>> imx-esdhc 2194000.usdhc at 02194000.of: registered as mmc1
>> imx-esdhc 2198000.usdhc at 02198000.of: registered as mmc2
>> imx-ipuv3 2400000.ipu at 02400000.of: IPUv3H probed
>> caam 2100000.caam at 2100000.of: Instantiated RNG4 SH0
>> caam 2100000.caam at 2100000.of: Instantiated RNG4 SH1
>> caam 2100000.caam at 2100000.of: registering rng-caam
>> netconsole: registered as netconsole-1
>> GPR1 = 48600005
>> malloc space: 0x3fdf6540 -> 0x4fdf653f (size 256 MiB)
>> mmc2: detected MMC card version 5.0
>> mmc2: registered mmc2.boot0
>> mmc2: registered mmc2.boot1
>> mmc2: registered mmc2
>> running /env/bin/init...
>>
>> Hit m for menu or any other key to stop autoboot:
>> type exit to get to the menu
>> barebox at Chrysalis Main Board:/
>>
>>
>> Thanks for everything,
> The barebox mutable environment is meant as development
> feature, so you can override the built-in environment.
>
> You'll probably want to run saveenv -z to override this
> and force use of the built-in environment.

If I understand well, the issue is not that my built-in env is not 
"updated" on the target, but that it is not loaded at startup.
And it is not loaded, because I already have a modified environment, on 
which I did a "saveenv" previously ; as a consequence, at startup, this 
"local dev env" is loaded instead of the built-in one?
I tried a saveenv -z on a modified env, and it restores properly the 
built-in env at the next startup.

On some targets, I don't have the issue.
Is it possible that on those targets, I never did a saveenv which would 
have created a "local" env ; as a consequence, every time I update 
Barebox, the built-in env is always used?

As a conclusion, I guess that updating barebox with "cp ${image} 
/dev/mmc2" and "saveenv -z" instead of only using the first command 
would solve this issue.


In any case, many thanks for helping me to understand this mechanism.

Best Regards,
AD




From m.tretter at pengutronix.de  Fri Jan 15 08:47:17 2021
From: m.tretter at pengutronix.de (Michael Tretter)
Date: Fri, 15 Jan 2021 14:47:17 +0100
Subject: Barebox OF-Overlay Handling
In-Reply-To: <20210113145223.GD29774@pengutronix.de>
References: <20210113110747.j25v7lnrlgdx62ns@pengutronix.de>
 <6d092867cfc86c63c2eb12fd7a156769d8a8d1f1.camel@pengutronix.de>
 <20210113145223.GD29774@pengutronix.de>
Message-ID: <20210115134717.GD30739@pengutronix.de>

On Wed, 13 Jan 2021 15:52:23 +0100, Michael Tretter wrote:
> On Wed, 13 Jan 2021 15:07:48 +0100, Rouven Czerwinski wrote:
> > On Wed, 2021-01-13 at 12:07 +0100, Marco Felsch wrote:
> > > Hi there,
> > > 
> > > I have the following problem. My customer is using overlays for
> > > external devices like: display, camera, etc. The current overlay support
> > > is awesome and most of it works out of the box. There is only one
> > > nitpick: If Barebox isn't build with CONFIG_OF_OVERLAY_LIVE enabled many
> > > error's are printed during boot. Those error's are ignored but let the
> > > user assume that something went really bad:
> > > 
> > > ERROR: of_resolver: __symbols__ missing from base devicetree
> > > ERROR: of_overlay: fragment 30164b88: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 30164c84: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 3012fb08: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 3012fc34: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 3012fd60: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 3012fe8c: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 3012ffb8: phandle 0xffffwfffffff not found
> > > ERROR: of_overlay: fragment 301300e4: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 30130210: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 3013033c: phandle 0xffffffff not found
> > > ERROR: of_resolver: __symbols__ missing from base devicetree
> > > ERROR: of_overlay: fragment 30130e94: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 30130fc4: phandle 0xffffffff not found
> > > ERROR: of_resolver: __symbols__ missing from base devicetree
> > > ERROR: of_overlay: fragment 30131a14: phandle 0xffffffff not found
> > > ERROR: of_overlay: fragment 301342d4: phandle 0xffffffff not found
> > > 
> > > The of_firmware_load_overlay() calls triggering those errors.
> > > The error's by itself are correct and I don't wanna change them but the
> > > context must be correct by context I mean:
> > > 
> > > ?- barebox-dt on fpga-platform: An FPGA platform needs a barebox
> > > ???base devicetree with __symbols__ and those error are correct because
> > > ???the firmware manager needs to load the firmware.
> > > ?- barebox-dt on non fpga-platform: Those errors are not correct.
> > > ???We don't need __symbols__ for the barebox base devicetree.
> > 
> > I was wondering why you were getting this error even on a platform
> > without FPGA, turns out of_firmware_load_overlay() is always called if
> > a devicetree overlay is passed via the DT. This in itself isn't a
> > problem, but IMO of_firmware_load_overlay() should check first whether
> > the overlay contains the right compatible ("fpga-region") and property
> > ("firmware-name") before doing of_resolve_phandles and
> > of_process_overlay. This way we can skip a lot of unnecessary overlay
> > handling if we don't end up loading a firmware.
> 
> At the moment, the check and firmware load path use the same code path,
> because there is no difference except that firmware load requires a resolved
> overlay and the check does not. This is a viable solution and there is even a
> helper to iterate the fragments and call a check function for each fragment.
> However the helper calls find_target, which is responsible for most of the
> error messages, and therefore, does not completely resolve the issue.
> 
> (Indeed, the check if the fragment has the "fpga-region" compatible is
> missing. That's a bug.)

This is wrong. The overlay does not have the "fpga-region" compatible. Only
the target node determines if an overlay targets an fpga-region or not.

Michael

> 
> I would rather change the error logging to only log errors if actually
> something goes wrong. Because none of the aforementioned errors is actually
> fatal from a system perspective, but only from a function perspective.
> Furthermore, the messages are not helpful at all to actually find the problem
> in case of a unresolved overlay.
> 
> >  
> > > ?- kernel-dt on any platform: Those error's are correct if
> > > ???the overlays are using phandles which should be the case most the
> > > ???time.
> > 
> > AFAICS this should also fix this case.
> > 
> > > My proposed solution would be a stub like this:
> > > 
> > > #ifdef CONFIG_OF_OVERLAY_LIVE
> > > int of_firmware_load_overlay(struct device_node *overlay, const char *path);
> > > #else
> > > static inline int of_firmware_load_overlay(struct device_node *overlay, const char *path)
> > > {
> > > ???????return 0;
> > > }
> > > #endif /* CONFIG_OF_OVERLAY_LIVE */
> 
> Nack. of_firmware_load_overlay must fail if the overlay describes an
> fpga-region. Otherwise the device tree that is passed to the kernel might have
> an fpga-region with a firmware-name property and that per specification
> requires that the fpga is programmed.
> 
> Michael
> 
> > 
> > While correct in case all firmware overlays use phandles, in theory
> > overlays could be purely path-based, with not dependency on the
> > __symbols__ node. Not sure how common this is.
> 
> > 
> > > The disadvantage of this solution is that it can happen to end in a
> > > non-booting device for FPGA platforms using overlays to programm the
> > > bit stream and forget to enable CONFIG_OF_OVERLAY_LIVE because the
> > > kernel tries to access regions not existing.
> > > 
> > > I've discussed this with Michael in private but we didn't came to a
> > > conclusion. Therefore I'm asking here any input would be helpfull :)
> > 
> > Regards,
> > Rouven Czerwinski
> > 
> > 


From sha at pengutronix.de  Mon Jan 18 03:02:24 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 18 Jan 2021 09:02:24 +0100
Subject: [PATCH] fixup! of: overlay: do not parse phandles as properties
In-Reply-To: <20210113171258.sk3k6cph7irdsl3s@pengutronix.de>
References: <20210113170018.8045-1-r.czerwinski@pengutronix.de>
 <20210113171258.sk3k6cph7irdsl3s@pengutronix.de>
Message-ID: <20210118080224.GP19063@pengutronix.de>

On Wed, Jan 13, 2021 at 06:12:58PM +0100, Marco Felsch wrote:
> On 21-01-13 18:00, Rouven Czerwinski wrote:
> > This breaks the eventual fixup of phandles into the linux device tree.
> > Fix this by also keeping the phandle properties in the DT.
> > ---
> >  drivers/of/overlay.c | 1 -
> >  1 file changed, 1 deletion(-)
> > 
> > diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> > index 0bebe26e39..d7695726fc 100644
> > --- a/drivers/of/overlay.c
> > +++ b/drivers/of/overlay.c
> > @@ -60,7 +60,6 @@ static int of_overlay_apply(struct device_node *target,
> >  
> >  		if (of_prop_cmp(prop->name, "phandle") == 0) {
> >  			target->phandle = be32_to_cpup(prop->value);
> > -			continue;
> >  		}
> 
> Nit:
> 
> We could also remove the {} so it's becoming a two-liner :)

Did that while applying

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Jan 18 05:32:09 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 18 Jan 2021 11:32:09 +0100
Subject: v2021.01.0
Message-ID: <20210118103209.GQ19063@pengutronix.de>

Hi All,

The first release for the new year is out: barebox-2021.01.0

This release brings us support for the qemu virt platform on ARM, thanks
Rouven. Furthermore there are several fixes for the updated NAND layer,
among other things different ECC modes and write support are now optional
again, so that the produced binaries are small enough again to compile
NAND boot for AM335x platforms. Ahmad has improved Raspberry Pi support
a bit: The RPi zero now has the UART support straight, so output should
appear on the right port. Apart from that there are several more fixes
and small improvements, see below.

Have Fun!
  Sascha

----------------------------------------------------------------
Ahmad Fatoum (36):
      fs: introduce unsetenv() to prepare for changing setenv(var, "") behavior
      setenv: align with POSIX in handling of setenv(var, "")
      fb: sync enable device parameter with internal state
      bootm: adapt help text and naming for bootm.provide_machine_id
      boot: drop uneeded header #includes
      commands: boot: fix error code/clean up behavior when not booting
      commands: boot: display each list entry in a separate line
      commands: boot: include blspec path name in entry title
      clk: imx6: demote warning about ldb_di_clk reparenting
      ARM: at91: sama5d2: giantboard: fix typo in SPDX-License-Identifier
      common: dummy_malloc: remove unintended GPL2 eCos-exception-2.0
      LICENSES: exceptions: factor out eCos-exception-2.0 for GPL
      common: replace license statements with SPDX-License-Identifiers
      hush: remove non-functional code
      commands: nv: fix set/remove of multiple variables in one go
      commands: nv: pass empty string for nv
      commands: implement and use parse_assignment helper
      watchdog: implement watchdog_get_alias_id_from
      boot: introduce option to pass barebox-enabled watchdog to systemd
      usb: host: ehci: fix mismatch in format string
      commands: memtester: fix mismatched format string
      ARM: i.MX: add low level gpio helpers for i.MX8M
      ARM: i.MX8M: bbu: rename imx8mq_bbu_* functions to imx8m_bbu_*
      Revert "ARM: dts: bcm2835-rpi: re-enable booting from SD card"
      ARM: dts: rpi: drop unnecessary /chosen/stdout-path overrides
      ARM: rpi: make functions in rpi-common.c static
      ARM: rpi: move rpi_model_init() to postcore
      ARM: rpi: support raspberry pi 1 and zero mini-uart
      ARM: rpi: add new init function for Raspberry Pi Zero
      ARM: rpi: Add Raspberry Pi Zero W mini-uart support
      ARM: rpi: drop no longer needed environment
      ARM: rpi: fix model description string
      ARM: rpi: add new rpi boot target
      doc: bcm283x: document use of mini-uart on Raspberry Pi Zero W / CM3
      ARM: at91: at91sam9x5: fix co-existance of erratum-aware and generic reset
      Documentation: boards: sandbox: describe --image flags

Alexander Shiyan (2):
      ARM: dts: imx6qdl: pfla02: Use upstream som_flash node
      ARM: dts: imx6qdl: pfla02: Fix NAND offsets for partitions

Du Huanpeng (1):
      clk: ls1b200: add clk driver for loongson 1b

Lucas Stach (2):
      usb: imx: add support for setting power pin polarity on i.MX6/7
      usb: imx: get power pin polarity from DT

Michael Tretter (1):
      overlay: return error if target for firmware is missing

Oleksij Rempel (1):
      ARM i.MX6Q: fix network configuration for Protonic PRTI6G board

Robert Karszniewicz (1):
      ARM: i.MX: OCOTP: read serial number with correct endianness

Rouven Czerwinski (6):
      amba: add *_amba_driver helper macros
      ARM: vexpress: remove unused KConfig file
      ARM: vexpress: convert to board driver
      ARM: vexpress: move Options to ARCH_VEXPRESS
      ARM: qemu: add support for qemu virt platform
      ARM: vexpress: enable virt and vexpress boards

Sascha Hauer (35):
      ARM: nxp i.MX8MP evk: make locally used data static
      ARM: i.MX: esdctl: Add missing compatible
      usb: fastboot: Fix error path
      i.MX: HABv4: Improve HAB event printing
      mtd: Remove set but not used of_path
      of: Add no-op wrappers for of reproducible name functions
      of: partitions: export of_fixup_partitions
      mtd: Add hook to fix up kernel partitions
      mtd: nand: denali: cope with kernel device trees without chip subnodes
      dts: update to v5.10-rc4
      dts: update to v5.10-rc5
      dts: update to v5.10-rc6
      imd command: Bail out when crc generation/check fails
      imd command: Document verbose option
      mtd: nand: omap: print error when ELM config failed
      mtd: nand: omap: Bail out when omap_gpmc_eccmode() fails
      mtd: spi-nor: Make write support optional
      mtd: nand: Make support for syndrome hardware ecc optional
      mtd: nand: Make software ECC support optional
      spi: store names in struct spi_device_id as pointers
      dts: update to v5.10-rc7
      Merge branch 'for-next/arm-qemu'
      Merge branch 'for-next/dts'
      Merge branch 'for-next/imd'
      Merge branch 'for-next/imx'
      Merge branch 'for-next/mips'
      Merge branch 'for-next/misc'
      Merge branch 'for-next/mtd'
      Merge branch 'for-next/rpi'
      Merge branch 'for-next/spdx'
      mtd:nand_mxs: Add missing include
      MIPS: ls1b200: move ls1b-clk.h to include/dt-bindings
      mtd: nand: fix NAND_ECC_HW mode
      startup: export PATH variable
      Release v2021.01.0

Steffen Trumtrar (3):
      image-sparse: change retlen to size_t
      image-sparse: change chunk_data_sz to u64
      imd: change disabled checksum tag info to debug

Uwe Kleine-K?nig (2):
      arm/lib: Replace license and copyright boilerplate by SPDX identifiers
      mci: Replace license and copyright boilerplate by SPDX identifiers

jameszxj (1):
      mtd:nand_mxs:update get/set features legacy function call

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Mon Jan 18 12:32:34 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 18 Jan 2021 18:32:34 +0100
Subject: Environment is not overwritten at barebox update
In-Reply-To: <3add69f4-c8a3-3848-a1ea-8a041a8dafd4@netc.fr>
References: <32b1e760-325e-b145-ba97-21aaee6ed868@netc.fr>
 <cc7279d9-f943-8b03-630e-fc7c41c9d0f2@pengutronix.de>
 <3add69f4-c8a3-3848-a1ea-8a041a8dafd4@netc.fr>
Message-ID: <9a9a0528-0a95-918b-6cd8-48d7c341bea8@pengutronix.de>

Hello,

On 15.01.21 13:12, AD wrote:
>> You'll probably want to run saveenv -z to override this
>> and force use of the built-in environment.
> 
> If I understand well, the issue is not that my built-in env is not "updated" on the target, but that it is not loaded at startup.

Exactly.

> And it is not loaded, because I already have a modified environment, on which I did a "saveenv" previously ; as a consequence, at startup, this "local dev env" is loaded instead of the built-in one?

Yep.

> I tried a saveenv -z on a modified env, and it restores properly the built-in env at the next startup.
> 
> On some targets, I don't have the issue.
> Is it possible that on those targets, I never did a saveenv which would have created a "local" env ; as a consequence, every time I update Barebox, the built-in env is always used?

That's my assumption as well.

> As a conclusion, I guess that updating barebox with "cp ${image} /dev/mmc2" and "saveenv -z" instead of only using the first command would solve this issue.

Preferably, you'd update barebox with barebox_update ${image}. barebox_update knows
how to handle eMMC boot partitions if you need that and it can be readily exported
over Android Fastboot.

saveenv -z is something you need to do when you have written an environment manually
during development. When bringing up a board in the factory, there shouldn't be
a valid environment in the eMMC, so you could skip that step.

> In any case, many thanks for helping me to understand this mechanism.

Glad it helped,
Ahmad

> 
> Best Regards,
> AD
> 
> 
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.grzeschik at pengutronix.de  Mon Jan 18 14:09:23 2021
From: m.grzeschik at pengutronix.de (Michael Grzeschik)
Date: Mon, 18 Jan 2021 20:09:23 +0100
Subject: [PATCH] usb: hub: fix state change check for not powercycled ports
Message-ID: <20210118190923.531-1-m.grzeschik@pengutronix.de>

Since we don't power cycle the ports on start since patch "19bb0b2a usb:
hub: Do not power-cycle usb devices on init" it is possible that the
device on this port is already active from a previous enumeration. This
way barebox will never get any change in USB_PORT_STAT_C_CONNECTION bit
change.

Although the device will probably still work fine after the following
port reset, the current code will always miss reenumerating these still
plugged devices. This patch fixes this by ignoring the check for
STAT_C_CONNECTION bit and only go for USB_PORT_STAT_CONNECTION which
should be enough.

Signed-off-by: Michael Grzeschik <m.grzeschik at pengutronix.de>
---
 drivers/usb/core/hub.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 01653d8c20..d1112248ee 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -336,8 +336,7 @@ static void usb_scan_port(struct usb_device_scan *usb_scan)
 	dev_dbg(&dev->dev, "port%d: Status 0x%04x Change 0x%04x\n",
 			port + 1, portstatus, portchange);
 
-	if (!(portchange & USB_PORT_STAT_C_CONNECTION) ||
-	    !(portstatus & USB_PORT_STAT_CONNECTION)) {
+	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
 		if (get_time_ns() >= hub->connect_timeout) {
 			dev_dbg(&dev->dev, "port%d: timeout\n", port + 1);
 			/* Remove this device from scanning list */
-- 
2.30.0



From m.felsch at pengutronix.de  Mon Jan 18 15:22:40 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:22:40 +0100
Subject: [PATCH] of: overlay: split debug messages for of_overlay_apply_symbols
Message-ID: <20210118202240.2184-1-m.felsch@pengutronix.de>

Overlays don't need to have __symbols__ therefore it shouldn't be
printed on info level. Move it to debug so interested users can print it
still.

I also fixed a minor alignment issue while on it.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 drivers/of/overlay.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index b79dbff94d..dc9711dac5 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -106,7 +106,7 @@ static char *of_overlay_fix_path(struct device_node *root,
 }
 
 static void of_overlay_apply_symbols(struct device_node *root,
-				    struct device_node *overlay)
+				     struct device_node *overlay)
 {
 	const char *old_path;
 	char *new_path;
@@ -117,8 +117,13 @@ static void of_overlay_apply_symbols(struct device_node *root,
 	root_symbols = of_get_child_by_name(root, "__symbols__");
 	overlay_symbols = of_get_child_by_name(overlay, "__symbols__");
 
-	if (!overlay_symbols || !root_symbols) {
-		pr_info("overlay/root doesn't have a __symbols__ node\n");
+	if (!overlay_symbols) {
+		pr_debug("overlay doesn't have a __symbols__ node\n");
+		return;
+	}
+
+	if (!root_symbols) {
+		pr_info("root doesn't have a __symbols__ node\n");
 		return;
 	}
 
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:29:22 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:29:22 +0100
Subject: [PATCH 6/6] ARM: dts: imx6qdl-samx6i: cosmetic partition cleanup
In-Reply-To: <20210118202922.3581-1-m.felsch@pengutronix.de>
References: <20210118202922.3581-1-m.felsch@pengutronix.de>
Message-ID: <20210118202922.3581-6-m.felsch@pengutronix.de>

The reg property is always the first property and the label is the
following. No functional changes.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/arm/dts/imx6qdl-smarc-samx6i.dtsi | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi b/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
index 197b5cbf8b..504cd06de1 100644
--- a/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
+++ b/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
@@ -42,18 +42,18 @@
 	#size-cells = <1>;
 
 	partition at 0 {
+		reg = <0x0 0x0c0000>;
 		label = "bootloader";
-		reg = <0x000000 0x0c0000>;
 	};
 
 	flash_bareboxenv: partition at c0000 {
-		label = "environment";
 		reg = <0x0c0000 0x010000>;
+		label = "environment";
 	};
 
 	partition at d0000 {
-		label = "user";
 		reg = <0x0d0000 0x130000>;
+		label = "user";
 	};
 };
 
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:29:19 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:29:19 +0100
Subject: [PATCH 3/6] ARM: dts: imx6qdl-smarc-samx6i: remove iomuxc hog
In-Reply-To: <20210118202922.3581-1-m.felsch@pengutronix.de>
References: <20210118202922.3581-1-m.felsch@pengutronix.de>
Message-ID: <20210118202922.3581-3-m.felsch@pengutronix.de>

Move the muxing into the gpioX nodes so we can get rid of the iomuxc
hog. While on it set the correct mux config and don't rely on the reset
value.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/arm/dts/imx6qdl-smarc-samx6i.dtsi | 37 +++++++++++++++++---------
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi b/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
index 363da66ec7..1381a551d0 100644
--- a/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
+++ b/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
@@ -129,6 +129,16 @@
 	status = "okay";
 };
 
+&gpio2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpio2_hog>;
+};
+
+&gpio6 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gpio6_hog>;
+};
+
 &i2c_pfuze {
 	pfuze100 at 08 {
 		compatible = "fsl,pfuze100";
@@ -352,18 +362,6 @@
 };
 
 &iomuxc {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_boot>;
-
-	pinctrl_boot: boot {
-		fsl,pins = <
-			/* GPIOS for version and id detection */
-			MX6QDL_PAD_NANDF_CLE__GPIO6_IO07	0x80000000
-			MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09	0x80000000
-			MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0x80000000
-		>;
-	};
-
 	pinctrl_flexcan1: flexcan1-smarc {
 		fsl,pins = <
 			MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x80000000
@@ -378,6 +376,21 @@
 		>;
 	};
 
+	pinctrl_gpio2_hog: gpio2-hog {
+		fsl,pins = <
+			/* GPIO for version detection */
+			MX6QDL_PAD_NANDF_D2__GPIO2_IO02		0xb0b0
+		>;
+	};
+
+	pinctrl_gpio6_hog: gpio6-hog {
+		fsl,pins = <
+			/* GPIOs for ddr3 size detection */
+			MX6QDL_PAD_NANDF_CLE__GPIO6_IO07	0xb0b0
+			MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09	0xb0b0
+		>;
+	};
+
 	pinctrl_enet_smarc: fecgrp-smarc {
 		fsl,pins = <
 			MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:29:18 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:29:18 +0100
Subject: [PATCH 2/6] ARM: boards: kontron-samx6i: simplify memory detection
 function
In-Reply-To: <20210118202922.3581-1-m.felsch@pengutronix.de>
References: <20210118202922.3581-1-m.felsch@pengutronix.de>
Message-ID: <20210118202922.3581-2-m.felsch@pengutronix.de>

The Dual/Quad modules always have twice the size of the Solo/DualLite
modules. Determine the size once and multiply it if we are running on a
Quad/Dual module. The only special case is the 4GB size where I've
copied the value from the vendor u-boot [1].

[1] https://github.com/kontron/u-boot-smarc-samx7/blob/master/board/kontron/amx6/amx6.c

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/arm/boards/kontron-samx6i/mem.c | 34 ++++++++++++----------------
 1 file changed, 15 insertions(+), 19 deletions(-)

diff --git a/arch/arm/boards/kontron-samx6i/mem.c b/arch/arm/boards/kontron-samx6i/mem.c
index 8132624e3b..08dceb55c0 100644
--- a/arch/arm/boards/kontron-samx6i/mem.c
+++ b/arch/arm/boards/kontron-samx6i/mem.c
@@ -49,26 +49,22 @@ resource_size_t samx6i_get_size(void)
 	id0 = imx6_gpio_val(gpio6, 7);
 	id1 = imx6_gpio_val(gpio6, 9);
 
-	if (cpu_type == IMX6_CPUTYPE_IMX6D ||
-			cpu_type == IMX6_CPUTYPE_IMX6Q) {
-		if (id0 && id1)
-			size = SZ_2G;
-		else if (id0)
-			size = SZ_2G;
-		else if (id1)
-			size = SZ_1G;
-		else
-			size = SZ_512M;
-	} else if (cpu_type == IMX6_CPUTYPE_IMX6S ||
-			cpu_type == IMX6_CPUTYPE_IMX6DL) {
-		if (id0 && id1)
-			size = SZ_2G;
-		else if (id0)
-			size = SZ_1G;
-		else if (id1)
-			size = SZ_512M;
+	/* Solo/DualLite module sizes */
+	if (id0 && id1)
+		size = SZ_2G;
+	else if (id0)
+		size = SZ_1G;
+	else if (id1)
+		size = SZ_512M;
+	else
+		size = SZ_256M;
+
+	/* Dual/Quad modules always have twice the size */
+	if (cpu_type == IMX6_CPUTYPE_IMX6D || cpu_type == IMX6_CPUTYPE_IMX6Q) {
+		if (size == SZ_2G)
+			size = 0xf0000000; /* 4G on a 32bit system */
 		else
-			size = SZ_256M;
+			size *= 2;
 	}
 
 	return size;
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:29:17 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:29:17 +0100
Subject: [PATCH 1/6] ARM: boards: kontron-samx6i: fix memory detection helper
Message-ID: <20210118202922.3581-1-m.felsch@pengutronix.de>

According the vendor u-boot version [1] the version pin is not involved
in the memory size detection algorithm. So drop the usage here.

Also fix the id0 gpio request. Instead of requesting GPIO6_6 we need to
request GPIO6_7.

Last we need to fix the size for the solo/duallite modules. Those
modules are populated with at least 256M of RAM according [1].

I fixed also the alignment while on it.

[1] https://github.com/kontron/u-boot-smarc-samx7/blob/master/board/kontron/amx6/amx6.c

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/arm/boards/kontron-samx6i/mem.c | 24 ++++++------------------
 1 file changed, 6 insertions(+), 18 deletions(-)

diff --git a/arch/arm/boards/kontron-samx6i/mem.c b/arch/arm/boards/kontron-samx6i/mem.c
index 3b9fbd464a..8132624e3b 100644
--- a/arch/arm/boards/kontron-samx6i/mem.c
+++ b/arch/arm/boards/kontron-samx6i/mem.c
@@ -17,7 +17,6 @@
 
 #include "mem.h"
 
-#define PCBVERSION_PIN IMX_GPIO_NR(2, 2)
 #define PCBID0_PIN IMX_GPIO_NR(6, 7)
 #define PCBID1_PIN IMX_GPIO_NR(6, 9)
 
@@ -25,43 +24,34 @@
 	IOMUX_PAD(0x0658, 0x0270, 5, 0x0000, 0, 0)
 #define MX6S_PAD_NANDF_WP_B__GPIO_6_9 \
 	IOMUX_PAD(0x0690, 0x02A8, 5, 0x0000, 0, 0)
-#define MX6S_PAD_NANDF_D2__GPIO_2_2 \
-	IOMUX_PAD(0x028c, 0x0674, 5, 0x0000, 0, 0)
 
 resource_size_t samx6i_get_size(void)
 {
 	resource_size_t size = 0;
-	int ver, id0, id1;
+	int id0, id1;
 	int cpu_type = __imx6_cpu_type();
 	void __iomem *iomuxbase = IOMEM(MX6_IOMUXC_BASE_ADDR);
 	void __iomem *gpio6 = IOMEM(MX6_GPIO6_BASE_ADDR);
-	void __iomem *gpio2 = IOMEM(MX6_GPIO2_BASE_ADDR);
 
 	if (cpu_type == IMX6_CPUTYPE_IMX6D ||
-			cpu_type == IMX6_CPUTYPE_IMX6Q) {
+	    cpu_type == IMX6_CPUTYPE_IMX6Q) {
 		imx_setup_pad(iomuxbase, MX6Q_PAD_NANDF_CLE__GPIO_6_7);
 		imx_setup_pad(iomuxbase, MX6Q_PAD_NANDF_WP_B__GPIO_6_9);
-		imx_setup_pad(iomuxbase, MX6Q_PAD_NANDF_D2__GPIO_2_2);
 	} else if (cpu_type == IMX6_CPUTYPE_IMX6S ||
-			cpu_type == IMX6_CPUTYPE_IMX6DL) {
+		   cpu_type == IMX6_CPUTYPE_IMX6DL) {
 		imx_setup_pad(iomuxbase, MX6S_PAD_NANDF_CLE__GPIO_6_7);
 		imx_setup_pad(iomuxbase, MX6S_PAD_NANDF_WP_B__GPIO_6_9);
-		imx_setup_pad(iomuxbase, MX6S_PAD_NANDF_D2__GPIO_2_2);
 	};
 
-	imx6_gpio_direction_input(gpio6, 6);
+	imx6_gpio_direction_input(gpio6, 7);
 	imx6_gpio_direction_input(gpio6, 9);
-	imx6_gpio_direction_input(gpio2, 2);
 
-	ver = imx6_gpio_val(gpio2, 2);
 	id0 = imx6_gpio_val(gpio6, 7);
 	id1 = imx6_gpio_val(gpio6, 9);
 
 	if (cpu_type == IMX6_CPUTYPE_IMX6D ||
 			cpu_type == IMX6_CPUTYPE_IMX6Q) {
-		if (ver)
-			size = SZ_1G;
-		else if (id0 && id1)
+		if (id0 && id1)
 			size = SZ_2G;
 		else if (id0)
 			size = SZ_2G;
@@ -71,8 +61,6 @@ resource_size_t samx6i_get_size(void)
 			size = SZ_512M;
 	} else if (cpu_type == IMX6_CPUTYPE_IMX6S ||
 			cpu_type == IMX6_CPUTYPE_IMX6DL) {
-		if (ver)
-			size = SZ_512M;
 		if (id0 && id1)
 			size = SZ_2G;
 		else if (id0)
@@ -80,7 +68,7 @@ resource_size_t samx6i_get_size(void)
 		else if (id1)
 			size = SZ_512M;
 		else
-			size = SZ_128M;
+			size = SZ_256M;
 	}
 
 	return size;
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:29:20 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:29:20 +0100
Subject: [PATCH 4/6] ARM: dts: imx6qdl-samx6i: switch to SPDX license
 identifier
In-Reply-To: <20210118202922.3581-1-m.felsch@pengutronix.de>
References: <20210118202922.3581-1-m.felsch@pengutronix.de>
Message-ID: <20210118202922.3581-4-m.felsch@pengutronix.de>

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/arm/dts/imx6dl-samx6i.dts         |  8 +-----
 arch/arm/dts/imx6q-samx6i.dts          |  8 +-----
 arch/arm/dts/imx6qdl-smarc-samx6i.dtsi | 40 +-------------------------
 3 files changed, 3 insertions(+), 53 deletions(-)

diff --git a/arch/arm/dts/imx6dl-samx6i.dts b/arch/arm/dts/imx6dl-samx6i.dts
index d688b9c6ca..c94573d0a8 100644
--- a/arch/arm/dts/imx6dl-samx6i.dts
+++ b/arch/arm/dts/imx6dl-samx6i.dts
@@ -1,12 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright 2018 (C) Pengutronix, Michael Grzeschik <mgr at pengutronix.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/imx6q-samx6i.dts b/arch/arm/dts/imx6q-samx6i.dts
index 83f19bcaf8..0f269aa287 100644
--- a/arch/arm/dts/imx6q-samx6i.dts
+++ b/arch/arm/dts/imx6q-samx6i.dts
@@ -1,12 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright 2018 (C) Pengutronix, Michael Grzeschik <mgr at pengutronix.de>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
  */
 
 /dts-v1/;
diff --git a/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi b/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
index 1381a551d0..759cd694e8 100644
--- a/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
+++ b/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
@@ -1,47 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
 /*
  * Copyright 2017 (C) Priit Laes <plaes at plaes.org>
  * Copyright 2018 (C) Pengutronix, Michael Grzeschik <mgr at pengutronix.de>
  *
  * Based on initial work by Nikita Yushchenko <nyushchenko at dev.rtsoft.ru>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- *  a) This file is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of
- *     the License, or (at your option) any later version.
- *
- *     This file is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- * Or, alternatively,
- *
- *  b) Permission is hereby granted, free of charge, to any person
- *     obtaining a copy of this software and associated documentation
- *     files (the "Software"), to deal in the Software without
- *     restriction, including without limitation the rights to use,
- *     copy, modify, merge, publish, distribute, sublicense, and/or
- *     sell copies of the Software, and to permit persons to whom the
- *     Software is furnished to do so, subject to the following
- *     conditions:
- *
- *     The above copyright notice and this permission notice shall be
- *     included in all copies or substantial portions of the Software.
- *
- *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- *     OTHER DEALINGS IN THE SOFTWARE.
- *
  */
 
 #include <dt-bindings/gpio/gpio.h>
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:29:21 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:29:21 +0100
Subject: [PATCH 5/6] ARM: dts: imx6qdl-samx6i: use upstream device tree files
In-Reply-To: <20210118202922.3581-1-m.felsch@pengutronix.de>
References: <20210118202922.3581-1-m.felsch@pengutronix.de>
Message-ID: <20210118202922.3581-5-m.felsch@pengutronix.de>

Make use of upstream available device tree files to avoid duplications.
A few interfaces had a "default on" behaviour which is dropped now.
Enabling those interfaces within the SoM dtsi seems to be wrong anyway.
Since boards have to turn it off again if those interfaces are unused.

I've adapted all upstream boards which are using the the
imx6qdl-smarc-samx6i.dtsi so the behaviour for those boards is
unchanged.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 arch/arm/dts/imx6dl-samx6i.dts         |  28 +-
 arch/arm/dts/imx6q-samx6i.dts          |  28 +-
 arch/arm/dts/imx6qdl-smarc-samx6i.dtsi | 422 +------------------------
 3 files changed, 62 insertions(+), 416 deletions(-)

diff --git a/arch/arm/dts/imx6dl-samx6i.dts b/arch/arm/dts/imx6dl-samx6i.dts
index c94573d0a8..da648ef5b8 100644
--- a/arch/arm/dts/imx6dl-samx6i.dts
+++ b/arch/arm/dts/imx6dl-samx6i.dts
@@ -1,14 +1,34 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright 2018 (C) Pengutronix, Michael Grzeschik <mgr at pengutronix.de>
+ * Copyright 2019 (C) Pengutronix, Marco Felsch <kernel at pengutronix.de>
  */
 
 /dts-v1/;
-#include <arm/imx6dl.dtsi>
+#include <arm/imx6dl-kontron-samx6i.dtsi>
 #include "imx6dl.dtsi"
 #include "imx6qdl-smarc-samx6i.dtsi"
 
-/ {
-	model = "Kontron sAMX6i";
-	compatible = "kontron,imx6dl-samx6i", "fsl,imx6dl";
+&fec {
+	status = "okay";
+};
+
+&ecspi4 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usdhc4 {
+	status = "okay";
 };
diff --git a/arch/arm/dts/imx6q-samx6i.dts b/arch/arm/dts/imx6q-samx6i.dts
index 0f269aa287..a2ea076edf 100644
--- a/arch/arm/dts/imx6q-samx6i.dts
+++ b/arch/arm/dts/imx6q-samx6i.dts
@@ -1,14 +1,34 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Copyright 2018 (C) Pengutronix, Michael Grzeschik <mgr at pengutronix.de>
+ * Copyright 2019 (C) Pengutronix, Marco Felsch <kernel at pengutronix.de>
  */
 
 /dts-v1/;
-#include <arm/imx6q.dtsi>
+#include <arm/imx6q-kontron-samx6i.dtsi>
 #include "imx6q.dtsi"
 #include "imx6qdl-smarc-samx6i.dtsi"
 
-/ {
-	model = "Kontron sAMX6i";
-	compatible = "kontron,imx6q-samx6i", "fsl,imx6q";
+&fec {
+	status = "okay";
+};
+
+&ecspi4 {
+	status = "okay";
+};
+
+&uart2 {
+	status = "okay";
+};
+
+&usbotg {
+	status = "okay";
+};
+
+&usbh1 {
+	status = "okay";
+};
+
+&usdhc4 {
+	status = "okay";
 };
diff --git a/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi b/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
index 759cd694e8..197b5cbf8b 100644
--- a/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
+++ b/arch/arm/dts/imx6qdl-smarc-samx6i.dtsi
@@ -2,6 +2,7 @@
 /*
  * Copyright 2017 (C) Priit Laes <plaes at plaes.org>
  * Copyright 2018 (C) Pengutronix, Michael Grzeschik <mgr at pengutronix.de>
+ * Copyright 2019 (C) Pengutronix, Marco Felsch <kernel at pengutronix.de>
  *
  * Based on initial work by Nikita Yushchenko <nyushchenko at dev.rtsoft.ru>
  */
@@ -24,71 +25,6 @@
 			status = "disabled";
 		};
 	};
-
-	reg_3v3_s5: regulator at 0 {
-		compatible = "regulator-fixed";
-		regulator-name = "V_3V3_S5";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		regulator-boot-on;
-		regulator-always-on;
-	};
-
-	reg_1v8_s5: regulator at 1 {
-		compatible = "regulator-fixed";
-		regulator-name = "V_1V8_S5";
-		regulator-min-microvolt = <1800000>;
-		regulator-max-microvolt = <1800000>;
-		regulator-boot-on;
-		regulator-always-on;
-	};
-
-	reg_3v3_s0: regulator at 2 {
-		compatible = "regulator-fixed";
-		regulator-name = "V_3V3_S0";
-		regulator-min-microvolt = <3300000>;
-		regulator-max-microvolt = <3300000>;
-		regulator-boot-on;
-		regulator-always-on;
-	};
-
-	reg_1v0_s0: regulator at 3 {
-		compatible = "regulator-fixed";
-		regulator-name = "V_1V0_S0";
-		regulator-min-microvolt = <1000000>;
-		regulator-max-microvolt = <1000000>;
-		regulator-boot-on;
-		regulator-always-on;
-	};
-
-	i2c_pfuze: i2c-gpio-0 {
-		compatible = "i2c-gpio";
-		pinctrl-names = "default";
-		pinctrl-0 = <&pinctrl_i2c_gpio_0>;
-		sda-gpios = <&gpio1 28 0>;
-		scl-gpios = <&gpio1 30 0>;
-		#address-cells = <1>;
-		#size-cells = <0>;
-		i2c-gpio,delay-us = <2>;
-	};
-};
-
-&can1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_flexcan1>;
-};
-
-&can2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_flexcan2>;
-};
-
-&fec {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_enet_smarc>;
-	phy-reset-gpios = <&gpio1 25 GPIO_ACTIVE_LOW>;
-	phy-mode = "rgmii";
-	status = "okay";
 };
 
 &gpio2 {
@@ -101,214 +37,27 @@
 	pinctrl-0 = <&pinctrl_gpio6_hog>;
 };
 
-&i2c_pfuze {
-	pfuze100 at 08 {
-		compatible = "fsl,pfuze100";
-		reg = <0x08>;
-
-		/* Looks unused by pfuze100 driver */
-		interrupt-parent = <&gpio7>;
-		interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
-
-		regulators {
-			reg_v_core_s0: sw1ab {
-				regulator-name = "V_CORE_S0";
-				regulator-min-microvolt = <300000>;
-				regulator-max-microvolt = <1875000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			reg_vddsoc_s0: sw1c {
-				regulator-name = "V_VDDSOC_S0";
-				regulator-min-microvolt = <300000>;
-				regulator-max-microvolt = <1875000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			reg_3v15_s0: sw2 {
-				regulator-name = "V_3V15_S0";
-				regulator-min-microvolt = <800000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			/* sw3a/b is used in dual mode, but driver does not
-			 * support it? Although, there's no need to control
-			 * DDR power - so just leaving dummy entries for sw3a
-			 * and sw3b for now.
-			 */
-			sw3a {
-				regulator-min-microvolt = <400000>;
-				regulator-max-microvolt = <1975000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			sw3b {
-				regulator-min-microvolt = <400000>;
-				regulator-max-microvolt = <1975000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			reg_1v8_s0: sw4 {
-				regulator-name = "V_1V8_S0";
-				regulator-min-microvolt = <800000>;
-				regulator-max-microvolt = <3300000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			/* Regulator for USB */
-			reg_5v0_s0: swbst {
-				regulator-name = "V_5V0_S0";
-				regulator-min-microvolt = <5000000>;
-				regulator-max-microvolt = <5150000>;
-				regulator-boot-on;
-			};
-
-			reg_vsnvs: vsnvs {
-				regulator-min-microvolt = <1000000>;
-				regulator-max-microvolt = <3000000>;
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			reg_vrefddr: vrefddr {
-				regulator-boot-on;
-				regulator-always-on;
-			};
-
-			/* Per schematics, of all VGEN's, only VGEN5 has some
-			 * usage ... but even that - over DNI resistor
-			 */
-			vgen1 {
-				regulator-min-microvolt = <800000>;
-				regulator-max-microvolt = <1550000>;
-			};
-
-			vgen2 {
-				regulator-min-microvolt = <800000>;
-				regulator-max-microvolt = <1550000>;
-			};
-
-			vgen3 {
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <3300000>;
-			};
-
-			vgen4 {
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <3300000>;
-			};
-
-			reg_2v5_s0: vgen5 {
-				regulator-name = "V_2V5_S0";
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <3300000>;
-			};
+&smarc_flash {
+	#address-cells = <1>;
+	#size-cells = <1>;
 
-			vgen6 {
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <3300000>;
-			};
-		};
+	partition at 0 {
+		label = "bootloader";
+		reg = <0x000000 0x0c0000>;
 	};
-};
 
-&ecspi4 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_ecspi4>;
-	fsl,spi-num-chipselects = <3>;
-	cs-gpios = <&gpio3 24 0>, <&gpio3 29 0>, <&gpio3 25 0>;
-	status = "okay";
-
-	flash: m25p80 at 0 {
-		compatible = "winbond,w25q16dw", "jedec,spi-nor";
-		spi-max-frequency = <20000000>;
-		reg = <0>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		partition at 0 {
-			label = "bootloader";
-			reg = <0x000000 0x0c0000>;
-		};
-
-		flash_bareboxenv: partition at c0000 {
-			label = "environment";
-			reg = <0x0c0000 0x010000>;
-		};
-
-		partition at d0000 {
-			label = "user";
-			reg = <0x0d0000 0x130000>;
-		};
+	flash_bareboxenv: partition at c0000 {
+		label = "environment";
+		reg = <0x0c0000 0x010000>;
 	};
-};
-
-&i2c3 {
-	clock-frequency = <100000>;
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_i2c3>;
-};
-
-&pcie {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_pcie>;
-	wake-up-gpio = <&gpio6 18 GPIO_ACTIVE_HIGH>;
-	reset-gpio = <&gpio3 13 GPIO_ACTIVE_HIGH>;
-};
 
-&uart1 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart1_smarc>;
-	fsl,uart-has-rtscts;
-};
-
-&uart2 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart2_smarc>;
-	status = "okay";
-};
-
-&uart4 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart4_smarc>;
-	fsl,uart-has-rtscts;
-};
-
-&uart5 {
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_uart5_smarc>;
-};
-
-&usbotg {
-	/*
-	 * no 'imx6-usb-charger-detection'
-	 * since USB_OTG_CHD_B pin is not wired
-	 */
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usbotg>;
-	status = "okay";
-};
-
-&usbh1 {
-	vbus-supply = <&reg_5v0_s0>;
-	status = "okay";
+	partition at d0000 {
+		label = "user";
+		reg = <0x0d0000 0x130000>;
+	};
 };
 
 &usdhc4 {
-	/* Internal eMMC, optional on some boards */
-	pinctrl-names = "default";
-	pinctrl-0 = <&pinctrl_usdhc4>;
-	bus-width = <8>;
-	no-1-8-v;
-	non-removable;
-	status = "okay";
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -324,20 +73,6 @@
 };
 
 &iomuxc {
-	pinctrl_flexcan1: flexcan1-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x80000000
-			MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x80000000
-		>;
-	};
-
-	pinctrl_flexcan2: flexcan2-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x80000000
-			MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 0x80000000
-		>;
-	};
-
 	pinctrl_gpio2_hog: gpio2-hog {
 		fsl,pins = <
 			/* GPIO for version detection */
@@ -352,133 +87,4 @@
 			MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09	0xb0b0
 		>;
 	};
-
-	pinctrl_enet_smarc: fecgrp-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_ENET_MDIO__ENET_MDIO       0x1b0b0
-			MX6QDL_PAD_ENET_MDC__ENET_MDC         0x1b0b0
-			MX6QDL_PAD_RGMII_TXC__RGMII_TXC       0x1b0b0
-			MX6QDL_PAD_RGMII_TD0__RGMII_TD0       0x1b0b0
-			MX6QDL_PAD_RGMII_TD1__RGMII_TD1       0x1b0b0
-			MX6QDL_PAD_RGMII_TD2__RGMII_TD2       0x1b0b0
-			MX6QDL_PAD_RGMII_TD3__RGMII_TD3       0x1b0b0
-			MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
-			MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK  0x1b0b0
-			MX6QDL_PAD_RGMII_RXC__RGMII_RXC       0x1b0b0
-			MX6QDL_PAD_RGMII_RD0__RGMII_RD0       0x1b0b0
-			MX6QDL_PAD_RGMII_RD1__RGMII_RD1       0x1b0b0
-			MX6QDL_PAD_RGMII_RD2__RGMII_RD2       0x1b0b0
-			MX6QDL_PAD_RGMII_RD3__RGMII_RD3       0x1b0b0
-			MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
-			MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25    0x80000000
-		>;
-	};
-
-	pinctrl_i2c_gpio_0: i2c-gpio-0-smarc {
-		fsl,pins = <
-			/* SCL GPIO */
-			MX6QDL_PAD_ENET_TXD0__GPIO1_IO30  0x80000000
-			/* SDA GPIO */
-			MX6QDL_PAD_ENET_TX_EN__GPIO1_IO28 0x80000000
-		>;
-	};
-
-	pinctrl_i2c3: i2c3-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_EIM_D17__I2C3_SCL		0x4001b8b1
-			MX6QDL_PAD_EIM_D18__I2C3_SDA		0x4001b8b1
-		>;
-	};
-
-	pinctrl_ecspi4: ecspi4-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_EIM_D21__ECSPI4_SCLK 0x80000000
-			MX6QDL_PAD_EIM_D28__ECSPI4_MOSI 0x80000000
-			MX6QDL_PAD_EIM_D22__ECSPI4_MISO 0x80000000
-			MX6QDL_PAD_EIM_D29__ECSPI4_SS0  0x80000000
-
-			/* In hardware, ECSPI4's SS0,SS1,SS3 are wired.
-			   But spi-imx driver support only continuous
-			   numbering, and only can use GPIOs (and not
-			   ECSPI's hardware SS) for CS. So linux view
-			   of CS numbers differs from hw view, and
-			   pins are configured as GPIOs */
-
-			/* physical - CS2, in linux - CS0, either internal flash or SMARC CS0 */
-			MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x80000000
-			/* physical - CS0, in linux - CS1, either SMARC CS0 or not-connected */
-			MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000
-			/* physical - CS3, in linux - CS2, SMARC CS1 */
-			MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x80000000
-		>;
-	};
-
-	pinctrl_pcie: pcie-smarc {
-		fsl,pins = <
-			/* RST_PCIE_A# */
-			MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x80000000
-			/* PCIE_WAKE# */
-			MX6QDL_PAD_SD3_DAT6__GPIO6_IO18 0x80000000
-		>;
-	};
-
-	pinctrl_uart1_smarc: uart1grp-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
-			MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA 0x1b0b1
-			MX6QDL_PAD_EIM_D20__UART1_RTS_B 0x1b0b1
-			MX6QDL_PAD_EIM_D19__UART1_CTS_B 0x1b0b1
-		>;
-	};
-
-	pinctrl_uart2_smarc: uart2grp-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
-			MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
-		>;
-	};
-
-	pinctrl_uart4_smarc: uart4grp-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
-			MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
-			MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B 0x1b0b1
-			MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B 0x1b0b1
-		>;
-	};
-
-	pinctrl_uart5_smarc: uart5grp-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_CSI0_DAT15__UART5_RX_DATA 0x1b0b1
-			MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA 0x1b0b1
-		>;
-	};
-
-	pinctrl_usbotg: usbotg-grp-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x1f8b0
-			/* TODO: Comment out power and OC gpio's for now, since
-			 * these are not used by driver
-			 */
-			/* USB power */
-			// MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18 0x80000000
-			/* USB OC */
-			// MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x80000000
-		>;
-	};
-
-	pinctrl_usdhc4: usdhc4grp-smarc {
-		fsl,pins = <
-			MX6QDL_PAD_SD4_CLK__SD4_CLK 0x17059
-			MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
-			MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
-			MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
-			MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
-			MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
-			MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
-			MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
-			MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
-			MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
-		>;
-	};
 };
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:48:49 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:48:49 +0100
Subject: [PATCH 1/2] blspec: allow board files to overwrite config file
 settings
Message-ID: <20210118204850.8420-1-m.felsch@pengutronix.de>

This commit adds the support to overwrite and/or adapt blspec config
files by the following global variables:
  - global.blspec.fixup.devicetree
  - global.blspec.fixup.initrd
  - global.blspec.fixup.options
  - global.blspec.fixup.linux
  - global.blspec.fixup.devicetree-overlay.

Overwriting blspec-config's shouldn't be the normal case but there are
cases where this support is needed. One use-case can be a special
handling during update. E.g. the normal boot-flow don't need the initrd
but the update-flow uses it because the update system is on the initrd.
Another use-case could be a dynamic devicetree-overlay handling. E.g.
the board code dynamically checks which periphery boards are connected
and adds the required overlays dynamically.

A warning is printed if a already set option is overwritten to identify
unintended wrong boot behaviour early.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 common/blspec.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/common/blspec.c b/common/blspec.c
index a07343f427..b527731a27 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -210,12 +210,21 @@ err_out:
  */
 const char *blspec_entry_var_get(struct blspec_entry *entry, const char *name)
 {
+	const char *match, *fixup;
 	const char *str;
 	int ret;
 
 	ret = of_property_read_string(entry->node, name, &str);
 
-	return ret ? NULL : str;
+	/* Check user specific overrides */
+	match = basprintf("global.blspec.fixup.%s", name);
+	fixup = getenv_nonempty(match);
+	free((void *)match);
+
+	if (!ret && fixup)
+		pr_warn("Overwrite %s blspec entry by fixup\n", name);
+
+	return fixup ? fixup : (ret ? NULL : str);
 }
 
 static void blspec_entry_free(struct bootentry *be)
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:48:50 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:48:50 +0100
Subject: [PATCH 2/2] Documentation: blspec: Add blspec fixup documentation
In-Reply-To: <20210118204850.8420-1-m.felsch@pengutronix.de>
References: <20210118204850.8420-1-m.felsch@pengutronix.de>
Message-ID: <20210118204850.8420-2-m.felsch@pengutronix.de>

Document the fixup mechanism.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 Documentation/user/booting-linux.rst | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index 60babb513c..fd7575bbe9 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -232,6 +232,28 @@ device where the entry is found on. This makes it possible to use the same rootf
 image on different devices without having to specify a different root= option each
 time.
 
+The following environment variables can be used to update the bootloader spec entry
+values on the fly.
+
+.. warning::
+
+  In most use cases this is not necessary. Modifying the bootloader spec values on
+  the fly can trigger unwanted boot behaviours.
+
++-----------------------------------------+
+| name                                    |
++=========================================+
+| global.blspec.fixup.devicetree          |
++-----------------------------------------+
+| global.blspec.fixup.initrd              |
++-----------------------------------------+
+| global.blspec.fixup.options             |
++-----------------------------------------+
+| global.blspec.fixup.linux               |
++-----------------------------------------+
+| global.blspec.fixup.devicetree-overlay  |
++-----------------------------------------+
+
 Network boot
 ------------
 
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:55:26 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:55:26 +0100
Subject: [PATCH 2/4] nvmem: add missing stubs
In-Reply-To: <20210118205528.9797-1-m.felsch@pengutronix.de>
References: <20210118205528.9797-1-m.felsch@pengutronix.de>
Message-ID: <20210118205528.9797-2-m.felsch@pengutronix.de>

Add missing stubs for nvmem_device_cell_read/write().

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 include/linux/nvmem-consumer.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 2f79014c0f..d86377bfda 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -84,6 +84,20 @@ static inline struct nvmem_device *nvmem_device_get(struct device_d *dev,
 static inline void nvmem_device_put(struct nvmem_device *nvmem)
 {
 }
+
+static inline ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+					 struct nvmem_cell_info *info,
+					 void *buf)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
+					  struct nvmem_cell_info *info,
+					  void *buf)
+{
+	return -EOPNOTSUPP;
+}
 #endif /* CONFIG_NVMEM */
 
 #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OFTREE)
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:55:28 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:55:28 +0100
Subject: [PATCH 4/4] nvmem: make id optional for of_nvmem_device_get()
In-Reply-To: <20210118205528.9797-1-m.felsch@pengutronix.de>
References: <20210118205528.9797-1-m.felsch@pengutronix.de>
Message-ID: <20210118205528.9797-4-m.felsch@pengutronix.de>

Port upstream linux commit
8<----------------------------------------------------------------------
commit d4e7fef1a9a5d2bf3f859ba9f50f4d5409a09ab0
Author: Alban Bedel <albeu at free.fr>
Date:   Mon Jan 28 15:55:03 2019 +0000

    nvmem: core: Properly handle connection ID in of_nvmem_device_get()

    of_nvmem_device_get() would crash if NULL was passed as a connection
    ID. Rework this to use the usual sementic of assuming the first
    connection when no connection ID is given.

    Furthermore of_nvmem_device_get() would return -EINVAL when it failed
    to resolve the connection, making it impossible to properly implement
    an optional connection. Return -ENOENT instead to let the caller know
    that the connection doesn't exists.

    Signed-off-by: Alban Bedel <albeu at free.fr>
    Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
8<----------------------------------------------------------------------

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 drivers/nvmem/core.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index b9af31f4b5..9b55f47b4c 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -284,13 +284,14 @@ struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
 {
 
 	struct device_node *nvmem_np;
-	int index;
+	int index = 0;
 
-	index = of_property_match_string(np, "nvmem-names", id);
+	if (id)
+		index = of_property_match_string(np, "nvmem-names", id);
 
 	nvmem_np = of_parse_phandle(np, "nvmem", index);
 	if (!nvmem_np)
-		return ERR_PTR(-EINVAL);
+		return ERR_PTR(-ENOENT);
 
 	return __nvmem_device_get(nvmem_np, NULL, NULL);
 }
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:55:25 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:55:25 +0100
Subject: [PATCH 1/4] nvmem: sync stub return values with linux code
Message-ID: <20210118205528.9797-1-m.felsch@pengutronix.de>

Based on linux commit:
8<------------------------------------------------------------------------
commit 20167b70c894f20cd01e2579fad206de440816ef
Author: Bartosz Golaszewski <bgolaszewski at baylibre.com>
Date:   Fri Sep 21 06:40:22 2018 -0700

    nvmem: use EOPNOTSUPP instead of ENOSYS

    Checkpatch emits warnings when using ENOSYS. Some of the frameworks
    started using EOPNOTSUPP as return values for API functions when given
    subsystem is disabled in Kconfig.

    Signed-off-by: Bartosz Golaszewski <bgolaszewski at baylibre.com>
    Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
8<------------------------------------------------------------------------

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 include/linux/nvmem-consumer.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index 9e0fd4265e..2f79014c0f 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -50,7 +50,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
 static inline struct nvmem_cell *nvmem_cell_get(struct device_d *dev,
 						const char *name)
 {
-	return ERR_PTR(-ENOSYS);
+	return ERR_PTR(-EOPNOTSUPP);
 }
 
 static inline void nvmem_cell_put(struct nvmem_cell *cell)
@@ -59,26 +59,26 @@ static inline void nvmem_cell_put(struct nvmem_cell *cell)
 
 static inline char *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
 {
-	return ERR_PTR(-ENOSYS);
+	return ERR_PTR(-EOPNOTSUPP);
 }
 
 static inline void *nvmem_cell_get_and_read(struct device_node *np,
 					    const char *cell_name,
 					    size_t bytes)
 {
-	return ERR_PTR(-ENOSYS);
+	return ERR_PTR(-EOPNOTSUPP);
 }
 
 static inline int nvmem_cell_write(struct nvmem_cell *cell,
 				    const char *buf, size_t len)
 {
-	return -ENOSYS;
+	return -EOPNOTSUPP;
 }
 
 static inline struct nvmem_device *nvmem_device_get(struct device_d *dev,
 						    const char *name)
 {
-	return ERR_PTR(-ENOSYS);
+	return ERR_PTR(-EOPNOTSUPP);
 }
 
 static inline void nvmem_device_put(struct nvmem_device *nvmem)
-- 
2.20.1



From m.felsch at pengutronix.de  Mon Jan 18 15:55:27 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Mon, 18 Jan 2021 21:55:27 +0100
Subject: [PATCH 3/4] nvmem: make nvmem_device_write/read public
In-Reply-To: <20210118205528.9797-1-m.felsch@pengutronix.de>
References: <20210118205528.9797-1-m.felsch@pengutronix.de>
Message-ID: <20210118205528.9797-3-m.felsch@pengutronix.de>

Those functions already export their symbols so make it public
available. Compared to the nvmem_device_cell_read/write() APIs these
functions are a bit easier to use.

Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
---
 drivers/nvmem/core.c           |  6 ------
 include/linux/nvmem-consumer.h | 19 +++++++++++++++++++
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 06e1414769..b9af31f4b5 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -48,12 +48,6 @@ struct nvmem_cell {
 static LIST_HEAD(nvmem_cells);
 static LIST_HEAD(nvmem_devs);
 
-int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
-		      size_t bytes, void *buf);
-int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
-		       size_t bytes, const void *buf);
-
-
 static ssize_t nvmem_cdev_read(struct cdev *cdev, void *buf, size_t count,
 			       loff_t offset, unsigned long flags)
 {
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
index d86377bfda..5d3d72837b 100644
--- a/include/linux/nvmem-consumer.h
+++ b/include/linux/nvmem-consumer.h
@@ -40,6 +40,10 @@ int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
 /* direct nvmem device read/write interface */
 struct nvmem_device *nvmem_device_get(struct device_d *dev, const char *name);
 void nvmem_device_put(struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+		      size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+		       size_t bytes, const void *buf);
 ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
 			       struct nvmem_cell_info *info, void *buf);
 int nvmem_device_cell_write(struct nvmem_device *nvmem,
@@ -98,6 +102,21 @@ static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
 {
 	return -EOPNOTSUPP;
 }
+
+static inline int nvmem_device_read(struct nvmem_device *nvmem,
+				    unsigned int offset, size_t bytes,
+				    void *buf)
+{
+	return -EOPNOTSUPP;
+}
+
+static inline int nvmem_device_write(struct nvmem_device *nvmem,
+				     unsigned int offset, size_t bytes,
+				     const void *buf)
+{
+	return -EOPNOTSUPP;
+}
+
 #endif /* CONFIG_NVMEM */
 
 #if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OFTREE)
-- 
2.20.1



From sha at pengutronix.de  Tue Jan 19 04:33:48 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 19 Jan 2021 10:33:48 +0100
Subject: [PATCH] of: overlay: split debug messages for
 of_overlay_apply_symbols
In-Reply-To: <20210118202240.2184-1-m.felsch@pengutronix.de>
References: <20210118202240.2184-1-m.felsch@pengutronix.de>
Message-ID: <20210119093348.GU19063@pengutronix.de>

On Mon, Jan 18, 2021 at 09:22:40PM +0100, Marco Felsch wrote:
> Overlays don't need to have __symbols__ therefore it shouldn't be
> printed on info level. Move it to debug so interested users can print it
> still.
> 
> I also fixed a minor alignment issue while on it.
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  drivers/of/overlay.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
> index b79dbff94d..dc9711dac5 100644
> --- a/drivers/of/overlay.c
> +++ b/drivers/of/overlay.c
> @@ -106,7 +106,7 @@ static char *of_overlay_fix_path(struct device_node *root,
>  }
>  
>  static void of_overlay_apply_symbols(struct device_node *root,
> -				    struct device_node *overlay)
> +				     struct device_node *overlay)
>  {
>  	const char *old_path;
>  	char *new_path;
> @@ -117,8 +117,13 @@ static void of_overlay_apply_symbols(struct device_node *root,
>  	root_symbols = of_get_child_by_name(root, "__symbols__");
>  	overlay_symbols = of_get_child_by_name(overlay, "__symbols__");
>  
> -	if (!overlay_symbols || !root_symbols) {
> -		pr_info("overlay/root doesn't have a __symbols__ node\n");
> +	if (!overlay_symbols) {
> +		pr_debug("overlay doesn't have a __symbols__ node\n");
> +		return;
> +	}
> +
> +	if (!root_symbols) {
> +		pr_info("root doesn't have a __symbols__ node\n");
>  		return;
>  	}
>  
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Jan 19 05:01:33 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 19 Jan 2021 11:01:33 +0100
Subject: [PATCH 1/6] ARM: boards: kontron-samx6i: fix memory detection
 helper
In-Reply-To: <20210118202922.3581-1-m.felsch@pengutronix.de>
References: <20210118202922.3581-1-m.felsch@pengutronix.de>
Message-ID: <20210119100133.GV19063@pengutronix.de>

On Mon, Jan 18, 2021 at 09:29:17PM +0100, Marco Felsch wrote:
> According the vendor u-boot version [1] the version pin is not involved
> in the memory size detection algorithm. So drop the usage here.
> 
> Also fix the id0 gpio request. Instead of requesting GPIO6_6 we need to
> request GPIO6_7.
> 
> Last we need to fix the size for the solo/duallite modules. Those
> modules are populated with at least 256M of RAM according [1].
> 
> I fixed also the alignment while on it.
> 
> [1] https://github.com/kontron/u-boot-smarc-samx7/blob/master/board/kontron/amx6/amx6.c
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  arch/arm/boards/kontron-samx6i/mem.c | 24 ++++++------------------
>  1 file changed, 6 insertions(+), 18 deletions(-)

Applied, thanks

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Jan 19 05:15:27 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 19 Jan 2021 11:15:27 +0100
Subject: [PATCH 1/4] nvmem: sync stub return values with linux code
In-Reply-To: <20210118205528.9797-1-m.felsch@pengutronix.de>
References: <20210118205528.9797-1-m.felsch@pengutronix.de>
Message-ID: <20210119101527.GW19063@pengutronix.de>

On Mon, Jan 18, 2021 at 09:55:25PM +0100, Marco Felsch wrote:
> Based on linux commit:
> 8<------------------------------------------------------------------------
> commit 20167b70c894f20cd01e2579fad206de440816ef
> Author: Bartosz Golaszewski <bgolaszewski at baylibre.com>
> Date:   Fri Sep 21 06:40:22 2018 -0700
> 
>     nvmem: use EOPNOTSUPP instead of ENOSYS
> 
>     Checkpatch emits warnings when using ENOSYS. Some of the frameworks
>     started using EOPNOTSUPP as return values for API functions when given
>     subsystem is disabled in Kconfig.
> 
>     Signed-off-by: Bartosz Golaszewski <bgolaszewski at baylibre.com>
>     Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla at linaro.org>
>     Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
> 8<------------------------------------------------------------------------
> 
> Signed-off-by: Marco Felsch <m.felsch at pengutronix.de>
> ---
>  include/linux/nvmem-consumer.h | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
> index 9e0fd4265e..2f79014c0f 100644
> --- a/include/linux/nvmem-consumer.h
> +++ b/include/linux/nvmem-consumer.h
> @@ -50,7 +50,7 @@ int nvmem_device_cell_write(struct nvmem_device *nvmem,
>  static inline struct nvmem_cell *nvmem_cell_get(struct device_d *dev,
>  						const char *name)
>  {
> -	return ERR_PTR(-ENOSYS);
> +	return ERR_PTR(-EOPNOTSUPP);
>  }
>  
>  static inline void nvmem_cell_put(struct nvmem_cell *cell)
> @@ -59,26 +59,26 @@ static inline void nvmem_cell_put(struct nvmem_cell *cell)
>  
>  static inline char *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
>  {
> -	return ERR_PTR(-ENOSYS);
> +	return ERR_PTR(-EOPNOTSUPP);
>  }
>  
>  static inline void *nvmem_cell_get_and_read(struct device_node *np,
>  					    const char *cell_name,
>  					    size_t bytes)
>  {
> -	return ERR_PTR(-ENOSYS);
> +	return ERR_PTR(-EOPNOTSUPP);
>  }
>  
>  static inline int nvmem_cell_write(struct nvmem_cell *cell,
>  				    const char *buf, size_t len)
>  {
> -	return -ENOSYS;
> +	return -EOPNOTSUPP;
>  }
>  
>  static inline struct nvmem_device *nvmem_device_get(struct device_d *dev,
>  						    const char *name)
>  {
> -	return ERR_PTR(-ENOSYS);
> +	return ERR_PTR(-EOPNOTSUPP);
>  }
>  
>  static inline void nvmem_device_put(struct nvmem_device *nvmem)
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Tue Jan 19 06:01:34 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 19 Jan 2021 12:01:34 +0100
Subject: [PATCH 1/2] blspec: allow board files to overwrite config file
 settings
In-Reply-To: <20210118204850.8420-1-m.felsch@pengutronix.de>
References: <20210118204850.8420-1-m.felsch@pengutronix.de>
Message-ID: <20210119110134.GX19063@pengutronix.de>

Hi Marco,
On Mon, Jan 18, 2021 at 09:48:49PM +0100, Marco Felsch wrote:
> This commit adds the support to overwrite and/or adapt blspec config
> files by the following global variables:
>   - global.blspec.fixup.devicetree
>   - global.blspec.fixup.initrd
>   - global.blspec.fixup.options
>   - global.blspec.fixup.linux
>   - global.blspec.fixup.devicetree-overlay.
> 
> Overwriting blspec-config's shouldn't be the normal case but there are
> cases where this support is needed. One use-case can be a special
> handling during update. E.g. the normal boot-flow don't need the initrd
> but the update-flow uses it because the update system is on the initrd.

When you have an update system and a regular system on the same
filesystem then I would expect an additional bootspec entry for the
update system.

> Another use-case could be a dynamic devicetree-overlay handling. E.g.
> the board code dynamically checks which periphery boards are connected
> and adds the required overlays dynamically.

Board code can register overlays already, there's no need for bootspec
to do that.

Overall overwriting bootspec variables somewhat contradicts the whole
purpose of bootspec. I don't like that very much, so you'll need very
good reasons to get this through ;)

Regards,
 Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.felsch at pengutronix.de  Tue Jan 19 06:42:08 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Tue, 19 Jan 2021 12:42:08 +0100
Subject: [PATCH 1/2] blspec: allow board files to overwrite config file
 settings
In-Reply-To: <20210119110134.GX19063@pengutronix.de>
References: <20210118204850.8420-1-m.felsch@pengutronix.de>
 <20210119110134.GX19063@pengutronix.de>
Message-ID: <20210119114208.6kxdsj5pa5zo25qo@pengutronix.de>

Hi Sascha,

On 21-01-19 12:01, Sascha Hauer wrote:
> Hi Marco,
> On Mon, Jan 18, 2021 at 09:48:49PM +0100, Marco Felsch wrote:
> > This commit adds the support to overwrite and/or adapt blspec config
> > files by the following global variables:
> >   - global.blspec.fixup.devicetree
> >   - global.blspec.fixup.initrd
> >   - global.blspec.fixup.options
> >   - global.blspec.fixup.linux
> >   - global.blspec.fixup.devicetree-overlay.
> > 
> > Overwriting blspec-config's shouldn't be the normal case but there are
> > cases where this support is needed. One use-case can be a special
> > handling during update. E.g. the normal boot-flow don't need the initrd
> > but the update-flow uses it because the update system is on the initrd.
> 
> When you have an update system and a regular system on the same
> filesystem then I would expect an additional bootspec entry for the
> update system.

AFAIK, barebox tries to find the correct entry by checking all config
files and loads the first matching config file. Is there a way to
specify an explicite config file?

> > Another use-case could be a dynamic devicetree-overlay handling. E.g.
> > the board code dynamically checks which periphery boards are connected
> > and adds the required overlays dynamically.
> 
> Board code can register overlays already, there's no need for bootspec
> to do that.

But this needs a lot more handling if we boot from nfs or from emmc.
Therefore I utilized the already existing code :)

> Overall overwriting bootspec variables somewhat contradicts the whole
> purpose of bootspec. I don't like that very much, so you'll need very
> good reasons to get this through ;)

Yep, I thought so ;) Therefore I wrote a big warning. It gives you a lot
opportunities to shot yourself in the foot. Therefore I print a warning
if you overwrite a already exisiting config.

Regards,
  Marco


From sha at pengutronix.de  Wed Jan 20 04:03:21 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 20 Jan 2021 10:03:21 +0100
Subject: [PATCH 1/2] blspec: allow board files to overwrite config file
 settings
In-Reply-To: <20210119114208.6kxdsj5pa5zo25qo@pengutronix.de>
References: <20210118204850.8420-1-m.felsch@pengutronix.de>
 <20210119110134.GX19063@pengutronix.de>
 <20210119114208.6kxdsj5pa5zo25qo@pengutronix.de>
Message-ID: <20210120090321.GY19063@pengutronix.de>

On Tue, Jan 19, 2021 at 12:42:08PM +0100, Marco Felsch wrote:
> Hi Sascha,
> 
> On 21-01-19 12:01, Sascha Hauer wrote:
> > Hi Marco,
> > On Mon, Jan 18, 2021 at 09:48:49PM +0100, Marco Felsch wrote:
> > > This commit adds the support to overwrite and/or adapt blspec config
> > > files by the following global variables:
> > >   - global.blspec.fixup.devicetree
> > >   - global.blspec.fixup.initrd
> > >   - global.blspec.fixup.options
> > >   - global.blspec.fixup.linux
> > >   - global.blspec.fixup.devicetree-overlay.
> > > 
> > > Overwriting blspec-config's shouldn't be the normal case but there are
> > > cases where this support is needed. One use-case can be a special
> > > handling during update. E.g. the normal boot-flow don't need the initrd
> > > but the update-flow uses it because the update system is on the initrd.
> > 
> > When you have an update system and a regular system on the same
> > filesystem then I would expect an additional bootspec entry for the
> > update system.
> 
> AFAIK, barebox tries to find the correct entry by checking all config
> files and loads the first matching config file. Is there a way to
> specify an explicite config file?

Not yet, but maybe we are at a point where a way should be added.

> 
> > > Another use-case could be a dynamic devicetree-overlay handling. E.g.
> > > the board code dynamically checks which periphery boards are connected
> > > and adds the required overlays dynamically.
> > 
> > Board code can register overlays already, there's no need for bootspec
> > to do that.
> 
> But this needs a lot more handling if we boot from nfs or from emmc.
> Therefore I utilized the already existing code :)

I'm not sure I understand you correctly. You probably mean that you have
to decide which overlay to use when the path to the rootfs is already
known, right?

> 
> > Overall overwriting bootspec variables somewhat contradicts the whole
> > purpose of bootspec. I don't like that very much, so you'll need very
> > good reasons to get this through ;)
> 
> Yep, I thought so ;) Therefore I wrote a big warning. It gives you a lot
> opportunities to shot yourself in the foot. Therefore I print a warning
> if you overwrite a already exisiting config.

Your code shouldn't issue a warning when it's exactly used like
intended. A warning tells people they are doing something wrong, but in
this case they are doing everything correctly, so they might be tempted
to just patch the warning away.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From m.felsch at pengutronix.de  Wed Jan 20 05:54:22 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 20 Jan 2021 11:54:22 +0100
Subject: [PATCH 1/2] blspec: allow board files to overwrite config file
 settings
In-Reply-To: <20210120090321.GY19063@pengutronix.de>
References: <20210118204850.8420-1-m.felsch@pengutronix.de>
 <20210119110134.GX19063@pengutronix.de>
 <20210119114208.6kxdsj5pa5zo25qo@pengutronix.de>
 <20210120090321.GY19063@pengutronix.de>
Message-ID: <20210120105422.zpizm7bet22ze4dq@pengutronix.de>

Hi Sascha,

On 21-01-20 10:03, Sascha Hauer wrote:
> On Tue, Jan 19, 2021 at 12:42:08PM +0100, Marco Felsch wrote:
> > Hi Sascha,
> > 
> > On 21-01-19 12:01, Sascha Hauer wrote:
> > > Hi Marco,
> > > On Mon, Jan 18, 2021 at 09:48:49PM +0100, Marco Felsch wrote:
> > > > This commit adds the support to overwrite and/or adapt blspec config
> > > > files by the following global variables:
> > > >   - global.blspec.fixup.devicetree
> > > >   - global.blspec.fixup.initrd
> > > >   - global.blspec.fixup.options
> > > >   - global.blspec.fixup.linux
> > > >   - global.blspec.fixup.devicetree-overlay.
> > > > 
> > > > Overwriting blspec-config's shouldn't be the normal case but there are
> > > > cases where this support is needed. One use-case can be a special
> > > > handling during update. E.g. the normal boot-flow don't need the initrd
> > > > but the update-flow uses it because the update system is on the initrd.
> > > 
> > > When you have an update system and a regular system on the same
> > > filesystem then I would expect an additional bootspec entry for the
> > > update system.
> > 
> > AFAIK, barebox tries to find the correct entry by checking all config
> > files and loads the first matching config file. Is there a way to
> > specify an explicite config file?
> 
> Not yet, but maybe we are at a point where a way should be added.

Maybe but how do you decide it? Also IMHO this wouldn't be that flexible
as this solution.

> > 
> > > > Another use-case could be a dynamic devicetree-overlay handling. E.g.
> > > > the board code dynamically checks which periphery boards are connected
> > > > and adds the required overlays dynamically.
> > > 
> > > Board code can register overlays already, there's no need for bootspec
> > > to do that.
> > 
> > But this needs a lot more handling if we boot from nfs or from emmc.
> > Therefore I utilized the already existing code :)
> 
> I'm not sure I understand you correctly. You probably mean that you have
> to decide which overlay to use when the path to the rootfs is already
> known, right?

Hopefully I get it right. What I mean is that the blspec code already
determines the correct boot medium and all blspec entries are relative
to this boot medium. Therefore I love it since booting a device behaves
the same for nfs or emmc :)

So yes, you're right :)

> > > Overall overwriting bootspec variables somewhat contradicts the whole
> > > purpose of bootspec. I don't like that very much, so you'll need very
> > > good reasons to get this through ;)
> > 
> > Yep, I thought so ;) Therefore I wrote a big warning. It gives you a lot
> > opportunities to shot yourself in the foot. Therefore I print a warning
> > if you overwrite a already exisiting config.
> 
> Your code shouldn't issue a warning when it's exactly used like
> intended. A warning tells people they are doing something wrong, but in
> this case they are doing everything correctly, so they might be tempted
> to just patch the warning away.

Mh.. The blspec config shouldn't contain any dynamic entry, therefore I
added the warning. E.g. on my system we check for the connected daughter
boards and add the devicetree-overlay entry. The original blspec-config
file don't have a entry for it.

Regards,
  Marco


From m.olbrich at pengutronix.de  Wed Jan 20 07:31:33 2021
From: m.olbrich at pengutronix.de (Michael Olbrich)
Date: Wed, 20 Jan 2021 13:31:33 +0100
Subject: [PATCH 1/2] blspec: allow board files to overwrite config file
 settings
In-Reply-To: <20210120105422.zpizm7bet22ze4dq@pengutronix.de>
References: <20210118204850.8420-1-m.felsch@pengutronix.de>
 <20210119110134.GX19063@pengutronix.de>
 <20210119114208.6kxdsj5pa5zo25qo@pengutronix.de>
 <20210120090321.GY19063@pengutronix.de>
 <20210120105422.zpizm7bet22ze4dq@pengutronix.de>
Message-ID: <20210120123133.GY9321@pengutronix.de>

On Wed, Jan 20, 2021 at 11:54:22AM +0100, Marco Felsch wrote:
> On 21-01-20 10:03, Sascha Hauer wrote:
> > On Tue, Jan 19, 2021 at 12:42:08PM +0100, Marco Felsch wrote:
> > > Hi Sascha,
> > > 
> > > On 21-01-19 12:01, Sascha Hauer wrote:
> > > > Hi Marco,
> > > > On Mon, Jan 18, 2021 at 09:48:49PM +0100, Marco Felsch wrote:
> > > > > This commit adds the support to overwrite and/or adapt blspec config
> > > > > files by the following global variables:
> > > > >   - global.blspec.fixup.devicetree
> > > > >   - global.blspec.fixup.initrd
> > > > >   - global.blspec.fixup.options
> > > > >   - global.blspec.fixup.linux
> > > > >   - global.blspec.fixup.devicetree-overlay.
> > > > > 
> > > > > Overwriting blspec-config's shouldn't be the normal case but there are
> > > > > cases where this support is needed. One use-case can be a special
> > > > > handling during update. E.g. the normal boot-flow don't need the initrd
> > > > > but the update-flow uses it because the update system is on the initrd.
> > > > 
> > > > When you have an update system and a regular system on the same
> > > > filesystem then I would expect an additional bootspec entry for the
> > > > update system.
> > > 
> > > AFAIK, barebox tries to find the correct entry by checking all config
> > > files and loads the first matching config file. Is there a way to
> > > specify an explicite config file?
> > 
> > Not yet, but maybe we are at a point where a way should be added.
> 
> Maybe but how do you decide it? Also IMHO this wouldn't be that flexible
> as this solution.

Maybe allow globing?

So I can say I want to boot 'default.conf' and create that as a symlink in
the filesystem. That would be for the desktop use-case with multiple kernel
versions.

Or I could switch between '*-regular.conf' and '*-update.conf'. And then
provide two entries for each device-tree.

Michael


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From andrej.picej at norik.com  Wed Jan 20 07:51:04 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Wed, 20 Jan 2021 13:51:04 +0100
Subject: [PATCH 0/3] GPMI NAND xload for i.MX6
Message-ID: <20210120125107.736121-1-andrej.picej@norik.com>

Hi all,

these patches implement GPMI NAND xload mechanism for i.MX6 SoCs. The xload from
GPMI NAND is needed in case board wants to boot from internal SRAM (limited in
size) and then load remaining barebox image from NAND.

The usual use-case for xload mechanism is board DRAM size auto-detection and
runtime configuration without the need for separate DCD tables for each SoM
variant.

In our case patches were required to support DRAM size auto-detection on
Phytec's phycard-imx6 SoM with 1GiB and 2GiB DRAM variants. Thus we decided to
submit example implementation on the mentioned board as RFC patch that will
follow these patch series.

Nonetheless, the majority of work was already provided by Sascha Hauer, but his
patches were in WIP stage and not found in the mainline. We added missing parts
for detecting NAND's page and oob size necessary for initial FCB page
reading, etc.

We hope patches spawn ideas for future implementations and work!

Best regards,
Andrej Picej

Andrej Picej (1):
  ARM: i.MX: xload-gpmi-nand: apply errata 007117

Primoz Fiser (1):
  ARM: i.MX: move BCB structures to header file

Sascha Hauer (1):
  ARM: i.MX: implement GPMI NAND xload

 arch/arm/mach-imx/Makefile                    |    2 +-
 arch/arm/mach-imx/include/mach/imx-nand-bcb.h |   80 ++
 arch/arm/mach-imx/include/mach/xload.h        |    1 +
 arch/arm/mach-imx/xload-gpmi-nand.c           | 1225 +++++++++++++++++
 common/imx-bbu-nand-fcb.c                     |   69 +-
 5 files changed, 1308 insertions(+), 69 deletions(-)
 create mode 100644 arch/arm/mach-imx/include/mach/imx-nand-bcb.h
 create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c

-- 
2.25.1



From andrej.picej at norik.com  Wed Jan 20 07:51:05 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Wed, 20 Jan 2021 13:51:05 +0100
Subject: [PATCH 1/3] ARM: i.MX: move BCB structures to header file
In-Reply-To: <20210120125107.736121-1-andrej.picej@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
Message-ID: <20210120125107.736121-2-andrej.picej@norik.com>

From: Primoz Fiser <primoz.fiser at norik.com>

Move i.MX BCB related structures to header file so they can be used by
others.

Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
Signed-off-by: Andrej Picej <andrej.picej at norik.com>
---
 arch/arm/mach-imx/include/mach/imx-nand-bcb.h | 80 +++++++++++++++++++
 common/imx-bbu-nand-fcb.c                     | 69 +---------------
 2 files changed, 81 insertions(+), 68 deletions(-)
 create mode 100644 arch/arm/mach-imx/include/mach/imx-nand-bcb.h

diff --git a/arch/arm/mach-imx/include/mach/imx-nand-bcb.h b/arch/arm/mach-imx/include/mach/imx-nand-bcb.h
new file mode 100644
index 000000000..b60205bd5
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/imx-nand-bcb.h
@@ -0,0 +1,80 @@
+#ifndef __MACH_IMX_NAND_BCB_H
+#define __MACH_IMX_NAND_BCB_H
+
+#define	FCB_FINGERPRINT		0x20424346	/* 'FCB' */
+#define	FCB_VERSION_1		0x01000000
+#define	FCB_FINGERPRINT_OFF	0x4		/* FCB fingerprint offset*/
+
+#define	DBBT_FINGERPRINT	0x54424244	/* 'DBBT' */
+#define	DBBT_VERSION_1		0x01000000
+#define	DBBT_FINGERPRINT_OFF	0x4		/* DBBT fingerprint offset*/
+
+struct dbbt_block {
+	uint32_t Checksum;
+	uint32_t FingerPrint;
+	uint32_t Version;
+	uint32_t numberBB; /* reserved on i.MX6 */
+	uint32_t DBBTNumOfPages;
+};
+
+struct fcb_block {
+	uint32_t Checksum;		/* First fingerprint in first byte */
+	uint32_t FingerPrint;		/* 2nd fingerprint at byte 4 */
+	uint32_t Version;		/* 3rd fingerprint at byte 8 */
+	uint8_t DataSetup;
+	uint8_t DataHold;
+	uint8_t AddressSetup;
+	uint8_t DSAMPLE_TIME;
+	/* These are for application use only and not for ROM. */
+	uint8_t NandTimingState;
+	uint8_t REA;
+	uint8_t RLOH;
+	uint8_t RHOH;
+	uint32_t PageDataSize;		/* 2048 for 2K pages, 4096 for 4K pages */
+	uint32_t TotalPageSize;		/* 2112 for 2K pages, 4314 for 4K pages */
+	uint32_t SectorsPerBlock;	/* Number of 2K sections per block */
+	uint32_t NumberOfNANDs;		/* Total Number of NANDs - not used by ROM */
+	uint32_t TotalInternalDie;	/* Number of separate chips in this NAND */
+	uint32_t CellType;		/* MLC or SLC */
+	uint32_t EccBlockNEccType;	/* Type of ECC, can be one of BCH-0-20 */
+	uint32_t EccBlock0Size;		/* Number of bytes for Block0 - BCH */
+	uint32_t EccBlockNSize;		/* Block size in bytes for all blocks other than Block0 - BCH */
+	uint32_t EccBlock0EccType;	/* Ecc level for Block 0 - BCH */
+	uint32_t MetadataBytes;		/* Metadata size - BCH */
+	uint32_t NumEccBlocksPerPage;	/* Number of blocks per page for ROM use - BCH */
+	uint32_t EccBlockNEccLevelSDK;	/* Type of ECC, can be one of BCH-0-20 */
+	uint32_t EccBlock0SizeSDK;	/* Number of bytes for Block0 - BCH */
+	uint32_t EccBlockNSizeSDK;	/* Block size in bytes for all blocks other than Block0 - BCH */
+	uint32_t EccBlock0EccLevelSDK;	/* Ecc level for Block 0 - BCH */
+	uint32_t NumEccBlocksPerPageSDK;/* Number of blocks per page for SDK use - BCH */
+	uint32_t MetadataBytesSDK;	/* Metadata size - BCH */
+	uint32_t EraseThreshold;	/* To set into BCH_MODE register */
+	uint32_t BootPatch;		/* 0 for normal boot and 1 to load patch starting next to FCB */
+	uint32_t PatchSectors;		/* Size of patch in sectors */
+	uint32_t Firmware1_startingPage;/* Firmware image starts on this sector */
+	uint32_t Firmware2_startingPage;/* Secondary FW Image starting Sector */
+	uint32_t PagesInFirmware1;	/* Number of sectors in firmware image */
+	uint32_t PagesInFirmware2;	/* Number of sector in secondary FW image */
+	uint32_t DBBTSearchAreaStartAddress; /* Page address where dbbt search area begins */
+	uint32_t BadBlockMarkerByte;	/* Byte in page data that have manufacturer marked bad block marker, */
+					/* this will be swapped with metadata[0] to complete page data. */
+	uint32_t BadBlockMarkerStartBit;/* For BCH ECC sizes other than 8 and 16 the bad block marker does not */
+					/* start at 0th bit of BadBlockMarkerByte. This field is used to get to */
+					/* the start bit of bad block marker byte with in BadBlockMarkerByte */
+	uint32_t BBMarkerPhysicalOffset;/* FCB value that gives byte offset for bad block marker on physical NAND page */
+	uint32_t BCHType;
+
+	uint32_t TMTiming2_ReadLatency;
+	uint32_t TMTiming2_PreambleDelay;
+	uint32_t TMTiming2_CEDelay;
+	uint32_t TMTiming2_PostambleDelay;
+	uint32_t TMTiming2_CmdAddPause;
+	uint32_t TMTiming2_DataPause;
+	uint32_t TMSpeed;
+	uint32_t TMTiming1_BusyTimeout;
+
+	uint32_t DISBBM;	/* the flag to enable (1)/disable(0) bi swap */
+	uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
+};
+
+#endif /* __MACH_IMX_NAND_BCB_H */
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index f8c457805..a08a1d834 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -25,6 +25,7 @@
 #include <crc.h>
 #include <mach/generic.h>
 #include <mtd/mtd-peb.h>
+#include <mach/imx-nand-bcb.h>
 
 #ifdef CONFIG_ARCH_IMX6
 #include <mach/imx6.h>
@@ -39,74 +40,6 @@ static inline int fcb_is_bch_encoded(void)
 }
 #endif
 
-struct dbbt_block {
-	uint32_t Checksum;
-	uint32_t FingerPrint;
-	uint32_t Version;
-	uint32_t numberBB; /* reserved on i.MX6 */
-	uint32_t DBBTNumOfPages;
-};
-
-struct fcb_block {
-	uint32_t Checksum;		/* First fingerprint in first byte */
-	uint32_t FingerPrint;		/* 2nd fingerprint at byte 4 */
-	uint32_t Version;		/* 3rd fingerprint at byte 8 */
-	uint8_t DataSetup;
-	uint8_t DataHold;
-	uint8_t AddressSetup;
-	uint8_t DSAMPLE_TIME;
-	/* These are for application use only and not for ROM. */
-	uint8_t NandTimingState;
-	uint8_t REA;
-	uint8_t RLOH;
-	uint8_t RHOH;
-	uint32_t PageDataSize;		/* 2048 for 2K pages, 4096 for 4K pages */
-	uint32_t TotalPageSize;		/* 2112 for 2K pages, 4314 for 4K pages */
-	uint32_t SectorsPerBlock;	/* Number of 2K sections per block */
-	uint32_t NumberOfNANDs;		/* Total Number of NANDs - not used by ROM */
-	uint32_t TotalInternalDie;	/* Number of separate chips in this NAND */
-	uint32_t CellType;		/* MLC or SLC */
-	uint32_t EccBlockNEccType;	/* Type of ECC, can be one of BCH-0-20 */
-	uint32_t EccBlock0Size;		/* Number of bytes for Block0 - BCH */
-	uint32_t EccBlockNSize;		/* Block size in bytes for all blocks other than Block0 - BCH */
-	uint32_t EccBlock0EccType;	/* Ecc level for Block 0 - BCH */
-	uint32_t MetadataBytes;		/* Metadata size - BCH */
-	uint32_t NumEccBlocksPerPage;	/* Number of blocks per page for ROM use - BCH */
-	uint32_t EccBlockNEccLevelSDK;	/* Type of ECC, can be one of BCH-0-20 */
-	uint32_t EccBlock0SizeSDK;	/* Number of bytes for Block0 - BCH */
-	uint32_t EccBlockNSizeSDK;	/* Block size in bytes for all blocks other than Block0 - BCH */
-	uint32_t EccBlock0EccLevelSDK;	/* Ecc level for Block 0 - BCH */
-	uint32_t NumEccBlocksPerPageSDK;/* Number of blocks per page for SDK use - BCH */
-	uint32_t MetadataBytesSDK;	/* Metadata size - BCH */
-	uint32_t EraseThreshold;	/* To set into BCH_MODE register */
-	uint32_t BootPatch;		/* 0 for normal boot and 1 to load patch starting next to FCB */
-	uint32_t PatchSectors;		/* Size of patch in sectors */
-	uint32_t Firmware1_startingPage;/* Firmware image starts on this sector */
-	uint32_t Firmware2_startingPage;/* Secondary FW Image starting Sector */
-	uint32_t PagesInFirmware1;	/* Number of sectors in firmware image */
-	uint32_t PagesInFirmware2;	/* Number of sector in secondary FW image */
-	uint32_t DBBTSearchAreaStartAddress; /* Page address where dbbt search area begins */
-	uint32_t BadBlockMarkerByte;	/* Byte in page data that have manufacturer marked bad block marker, */
-					/* this will be swapped with metadata[0] to complete page data. */
-	uint32_t BadBlockMarkerStartBit;/* For BCH ECC sizes other than 8 and 16 the bad block marker does not */
-					/* start at 0th bit of BadBlockMarkerByte. This field is used to get to */
-					/* the start bit of bad block marker byte with in BadBlockMarkerByte */
-	uint32_t BBMarkerPhysicalOffset;/* FCB value that gives byte offset for bad block marker on physical NAND page */
-	uint32_t BCHType;
-
-	uint32_t TMTiming2_ReadLatency;
-	uint32_t TMTiming2_PreambleDelay;
-	uint32_t TMTiming2_CEDelay;
-	uint32_t TMTiming2_PostambleDelay;
-	uint32_t TMTiming2_CmdAddPause;
-	uint32_t TMTiming2_DataPause;
-	uint32_t TMSpeed;
-	uint32_t TMTiming1_BusyTimeout;
-
-	uint32_t DISBBM;	/* the flag to enable (1)/disable(0) bi swap */
-	uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
-};
-
 struct imx_nand_fcb_bbu_handler {
 	struct bbu_handler handler;
 
-- 
2.25.1



From andrej.picej at norik.com  Wed Jan 20 07:51:07 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Wed, 20 Jan 2021 13:51:07 +0100
Subject: [PATCH 3/3] ARM: i.MX: xload-gpmi-nand: apply errata 007117
In-Reply-To: <20210120125107.736121-1-andrej.picej@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
Message-ID: <20210120125107.736121-4-andrej.picej@norik.com>

During raw NAND booting, GPMI/BCH clock generation might fail due to
improper clock gating conditions and consequently booting from NAND will
fail. This is caused by silicon errata ERR007117. Apply errata fix
workaround before GPMI NAND xload to prevent this from occurring.

Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
Signed-off-by: Andrej Picej <andrej.picej at norik.com>
---
 arch/arm/mach-imx/xload-gpmi-nand.c | 62 +++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index 04f799604..4be6d1890 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -20,6 +20,8 @@
 #include <mach/xload.h>
 #include <mach/imx-nand-bcb.h>
 #include <linux/mtd/rawnand.h>
+#include <mach/imx6-regs.h>
+#include <mach/clock-imx6.h>
 
 /*
  * MXS DMA hardware command.
@@ -256,6 +258,63 @@ struct mxs_nand_info {
 	unsigned long nand_size;
 };
 
+/**
+ * It was discovered that xloading barebox from NAND sometimes fails. Observed
+ * behaviour is similar to silicon errata ERR007117 for i.MX6.
+ *
+ * ERR007117 description:
+ * For raw NAND boot, ROM switches the source of enfc_clk_root from PLL2_PFD2
+ * to PLL3. The root clock is required to be gated before switching the source
+ * clock. If the root clock is not gated, clock glitches might be passed to the
+ * divider that follows the clock mux, and the divider might behave
+ * unpredictably. This can cause the clock generation to fail and the chip will
+ * not boot successfully.
+ *
+ * Workaround solution for this errata:
+ * 1) gate all GPMI/BCH related clocks (CG15, G14, CG13, CG12 and CG6)
+ * 2) reconfigure clocks
+ * 3) ungate all GPMI/BCH related clocks
+ *
+ */
+static inline void imx6_errata_007117_enable(void)
+{
+	u32 reg;
+
+	/* Gate (disable) the GPMI/BCH clocks in CCM_CCGR4 */
+	reg = readl(MXC_CCM_CCGR4);
+	reg &= ~(0xFF003000);
+	writel(reg, MXC_CCM_CCGR4);
+
+	/**
+	 * Gate (disable) the enfc_clk_root before changing the enfc_clk_root
+	 * source or dividers by clearing CCM_CCGR2[CG7] to 2'b00. This
+	 * disables the iomux_ipt_clk_io_clk.
+	 */
+	reg = readl(MXC_CCM_CCGR2);
+	reg &= ~(0x3 << 14);
+	writel(reg, MXC_CCM_CCGR2);
+
+	/* Configure CCM_CS2CDR for the new clock source configuration */
+	reg = readl(MXC_CCM_CS2CDR);
+	reg &= ~(0x7FF0000);
+	writel(reg, MXC_CCM_CS2CDR);
+	reg |= 0xF0000;
+	writel(reg, MXC_CCM_CS2CDR);
+
+	/**
+	 * Enable enfc_clk_root by setting CCM_CCGR2[CG7] to 2'b11. This
+	 * enables the iomux_ipt_clk_io_clk.
+	 */
+	reg = readl(MXC_CCM_CCGR2);
+	reg |= 0x3 << 14;
+	writel(reg, MXC_CCM_CCGR2);
+
+	/* Ungate (enable) the GPMI/BCH clocks in CCM_CCGR4 */
+	reg = readl(MXC_CCM_CCGR4);
+	reg |= 0xFF003000;
+	writel(reg, MXC_CCM_CCGR4);
+}
+
 static uint32_t mxs_nand_aux_status_offset(void)
 {
 	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
@@ -1147,6 +1206,9 @@ int imx6_nand_start_image(void)
 		sizeof(struct mxs_dma_cmd) * MXS_NAND_DMA_DESCRIPTOR_COUNT;
 	bb = (void *)PAGE_ALIGN((unsigned long)databuf + SZ_8K);
 
+	/* Apply ERR007117 workaround */
+	imx6_errata_007117_enable();
+
 	ret = imx6_nand_load_image(cmdbuf, descs, databuf,
 		bb, imx_image_size());
 	if (ret) {
-- 
2.25.1



From andrej.picej at norik.com  Wed Jan 20 07:51:06 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Wed, 20 Jan 2021 13:51:06 +0100
Subject: [PATCH 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <20210120125107.736121-1-andrej.picej@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
Message-ID: <20210120125107.736121-3-andrej.picej@norik.com>

From: Sascha Hauer <s.hauer at pengutronix.de>

Commit is based on initial Sascha Hauer's work. It implements PBL xload
mechanism to load image from GPMI NAND flash.

Additional work was done, so that the NAND's size, page size and OOB's
size are autodetected and not hardcoded. Detection method follows the
same methods as used in NAND driver, meaning NAND ONFI support is probed
and if NAND supports ONFI, NAND memory organization is read from ONFI
parameter page otherwise "READ ID" is used.

Currently only implemented for i.MX6 familly of SoCs.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
Signed-off-by: Andrej Picej <andrej.picej at norik.com>
---
 arch/arm/mach-imx/Makefile             |    2 +-
 arch/arm/mach-imx/include/mach/xload.h |    1 +
 arch/arm/mach-imx/xload-gpmi-nand.c    | 1163 ++++++++++++++++++++++++
 3 files changed, 1165 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index e45f758e9..d94c846a1 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -26,4 +26,4 @@ obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
 obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o
 obj-$(CONFIG_RESET_IMX_SRC) += src.o
 lwl-y += cpu_init.o
-pbl-y += xload-spi.o xload-common.o xload-imx-nand.o
+pbl-y += xload-spi.o xload-common.o xload-imx-nand.o xload-gpmi-nand.o
diff --git a/arch/arm/mach-imx/include/mach/xload.h b/arch/arm/mach-imx/include/mach/xload.h
index 94b2f3761..7187787f5 100644
--- a/arch/arm/mach-imx/include/mach/xload.h
+++ b/arch/arm/mach-imx/include/mach/xload.h
@@ -5,6 +5,7 @@ int imx53_nand_start_image(void);
 int imx6_spi_load_image(int instance, unsigned int flash_offset, void *buf, int len);
 int imx6_spi_start_image(int instance);
 int imx6_esdhc_start_image(int instance);
+int imx6_nand_start_image(void);
 int imx7_esdhc_start_image(int instance);
 int imx8m_esdhc_load_image(int instance, bool start);
 int imx8mp_esdhc_load_image(int instance, bool start);
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
new file mode 100644
index 000000000..04f799604
--- /dev/null
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -0,0 +1,1163 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "xload-gpmi-nand: " fmt
+
+#include <common.h>
+#include <stmp-device.h>
+#include <asm-generic/io.h>
+#include <linux/sizes.h>
+#include <linux/mtd/nand.h>
+#include <asm/cache.h>
+#include <mach/xload.h>
+#include <mach/imx-nand-bcb.h>
+#include <linux/mtd/rawnand.h>
+
+/*
+ * MXS DMA hardware command.
+ *
+ * This structure describes the in-memory layout of an entire DMA command,
+ * including space for the maximum number of PIO accesses. See the appropriate
+ * reference manual for a detailed description of what these fields mean to the
+ * DMA hardware.
+ */
+#define	DMACMD_COMMAND_DMA_WRITE	0x1
+#define	DMACMD_COMMAND_DMA_READ		0x2
+#define	DMACMD_COMMAND_DMA_SENSE	0x3
+#define	DMACMD_CHAIN			(1 << 2)
+#define	DMACMD_IRQ			(1 << 3)
+#define	DMACMD_NAND_LOCK		(1 << 4)
+#define	DMACMD_NAND_WAIT_4_READY	(1 << 5)
+#define	DMACMD_DEC_SEM			(1 << 6)
+#define	DMACMD_WAIT4END			(1 << 7)
+#define	DMACMD_HALT_ON_TERMINATE	(1 << 8)
+#define	DMACMD_TERMINATE_FLUSH		(1 << 9)
+#define	DMACMD_PIO_WORDS(words)		((words) << 12)
+#define	DMACMD_XFER_COUNT(x)		((x) << 16)
+
+struct mxs_dma_cmd {
+	unsigned long		next;
+	unsigned long		data;
+	unsigned long		address;
+#define	APBH_DMA_PIO_WORDS	6
+	unsigned long		pio_words[APBH_DMA_PIO_WORDS];
+};
+
+enum mxs_dma_id {
+	IMX23_DMA,
+	IMX28_DMA,
+};
+
+struct apbh_dma {
+	void __iomem *regs;
+	enum mxs_dma_id id;
+};
+
+struct mxs_dma_chan {
+	unsigned int flags;
+	int channel;
+	struct apbh_dma *apbh;
+};
+
+#define	HW_APBHX_CTRL0				0x000
+#define	BM_APBH_CTRL0_APB_BURST8_EN		(1 << 29)
+#define	BM_APBH_CTRL0_APB_BURST_EN		(1 << 28)
+#define	BP_APBH_CTRL0_CLKGATE_CHANNEL		8
+#define	BP_APBH_CTRL0_RESET_CHANNEL		16
+#define	HW_APBHX_CTRL1				0x010
+#define	BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN	16
+#define	HW_APBHX_CTRL2				0x020
+#define	HW_APBHX_CHANNEL_CTRL			0x030
+#define	BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL	16
+#define	BP_APBHX_VERSION_MAJOR			24
+#define	HW_APBHX_CHn_NXTCMDAR_MX23(n)		(0x050 + (n) * 0x70)
+#define	HW_APBHX_CHn_NXTCMDAR_MX28(n)		(0x110 + (n) * 0x70)
+#define	HW_APBHX_CHn_SEMA_MX23(n)		(0x080 + (n) * 0x70)
+#define	HW_APBHX_CHn_SEMA_MX28(n)		(0x140 + (n) * 0x70)
+#define	NAND_ONFI_CRC_BASE			0x4f4e
+
+#define apbh_dma_is_imx23(aphb) ((apbh)->id == IMX23_DMA)
+
+/* udelay() is not available in PBL, need to improvise */
+static void __udelay(int us)
+{
+	volatile int i;
+
+	for (i = 0; i < us * 4; i++);
+}
+
+/*
+ * Enable a DMA channel.
+ *
+ * If the given channel has any DMA descriptors on its active list, this
+ * function causes the DMA hardware to begin processing them.
+ *
+ * This function marks the DMA channel as "busy," whether or not there are any
+ * descriptors to process.
+ */
+static int mxs_dma_enable(struct mxs_dma_chan *pchan,
+	struct mxs_dma_cmd *pdesc)
+{
+	struct apbh_dma *apbh = pchan->apbh;
+	int channel_bit;
+	int channel = pchan->channel;
+
+	if (apbh_dma_is_imx23(apbh)) {
+		writel((uint32_t)pdesc,
+			apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX23(channel));
+		writel(1, apbh->regs + HW_APBHX_CHn_SEMA_MX23(channel));
+		channel_bit = channel + BP_APBH_CTRL0_CLKGATE_CHANNEL;
+	} else {
+		writel((uint32_t)pdesc,
+			apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX28(channel));
+		writel(1, apbh->regs + HW_APBHX_CHn_SEMA_MX28(channel));
+		channel_bit = channel;
+	}
+
+	writel(1 << channel_bit, apbh->regs +
+		HW_APBHX_CTRL0 + STMP_OFFSET_REG_CLR);
+
+	return 0;
+}
+
+/*
+ * Resets the DMA channel hardware.
+ */
+static int mxs_dma_reset(struct mxs_dma_chan *pchan)
+{
+	struct apbh_dma *apbh = pchan->apbh;
+
+	if (apbh_dma_is_imx23(apbh))
+		writel(1 << (pchan->channel + BP_APBH_CTRL0_RESET_CHANNEL),
+			apbh->regs + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET);
+	else
+		writel(1 << (pchan->channel +
+			BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL),
+			apbh->regs + HW_APBHX_CHANNEL_CTRL +
+			STMP_OFFSET_REG_SET);
+
+	return 0;
+}
+
+static int mxs_dma_wait_complete(struct mxs_dma_chan *pchan)
+{
+	struct apbh_dma *apbh = pchan->apbh;
+	int timeout = 1000000;
+
+	while (1) {
+		if (readl(apbh->regs + HW_APBHX_CTRL1) & (1 << pchan->channel))
+			return 0;
+
+		if (!timeout--)
+			return -ETIMEDOUT;
+	}
+}
+
+/*
+ * Execute the DMA channel
+ */
+static int mxs_dma_run(struct mxs_dma_chan *pchan, struct mxs_dma_cmd *pdesc,
+		int num)
+{
+	struct apbh_dma *apbh = pchan->apbh;
+	int i, ret;
+
+	/* chain descriptors */
+	for (i = 0; i < num - 1; i++) {
+		pdesc[i].next = (uint32_t)(&pdesc[i + 1]);
+		pdesc[i].data |= DMACMD_CHAIN;
+	}
+
+	writel(1 << (pchan->channel + BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN),
+		apbh->regs + HW_APBHX_CTRL1 + STMP_OFFSET_REG_SET);
+
+	ret = mxs_dma_enable(pchan, pdesc);
+	if (ret) {
+		pr_err("%s: Failed to enable dma channel: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	ret = mxs_dma_wait_complete(pchan);
+	if (ret) {
+		pr_err("%s: Failed to wait for completion: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	/* Shut the DMA channel down. */
+	writel(1 << pchan->channel, apbh->regs +
+		HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR);
+	writel(1 << pchan->channel, apbh->regs +
+		HW_APBHX_CTRL2 + STMP_OFFSET_REG_CLR);
+
+	mxs_dma_reset(pchan);
+
+	writel(1 << (pchan->channel + BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN),
+		apbh->regs + HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR);
+
+	return 0;
+}
+
+/* ----------------------------- NAND driver part -------------------------- */
+
+#define	GPMI_CTRL0					0x00000000
+#define	GPMI_CTRL0_RUN					(1 << 29)
+#define	GPMI_CTRL0_DEV_IRQ_EN				(1 << 28)
+#define	GPMI_CTRL0_UDMA					(1 << 26)
+#define	GPMI_CTRL0_COMMAND_MODE_MASK			(0x3 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_OFFSET			24
+#define	GPMI_CTRL0_COMMAND_MODE_WRITE			(0x0 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ			(0x1 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE	(0x2 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY		(0x3 << 24)
+#define	GPMI_CTRL0_WORD_LENGTH				(1 << 23)
+#define	GPMI_CTRL0_CS(cs)				((cs) << 20)
+#define	GPMI_CTRL0_ADDRESS_MASK				(0x7 << 17)
+#define	GPMI_CTRL0_ADDRESS_OFFSET			17
+#define	GPMI_CTRL0_ADDRESS_NAND_DATA			(0x0 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_CLE			(0x1 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_ALE			(0x2 << 17)
+#define	GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define	GPMI_CTRL0_XFER_COUNT_MASK			0xffff
+#define	GPMI_CTRL0_XFER_COUNT_OFFSET			0
+
+#define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
+#define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE		0x1ff
+
+#define	BCH_CTRL					0x00000000
+#define	BCH_CTRL_COMPLETE_IRQ				(1 << 0)
+
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT			6
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE			512
+#define	MXS_NAND_METADATA_SIZE				10
+#define	MXS_NAND_COMMAND_BUFFER_SIZE			128
+
+struct mxs_nand_info {
+	void __iomem *io_base;
+	void __iomem *bch_base;
+	struct mxs_dma_chan *dma_channel;
+	int cs;
+	uint8_t *cmd_buf;
+	struct mxs_dma_cmd *desc;
+	struct fcb_block fcb;
+	int dbbt_num_entries;
+	u32 *dbbt;
+	struct nand_memory_organization organization;
+	unsigned long nand_size;
+};
+
+static uint32_t mxs_nand_aux_status_offset(void)
+{
+	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
+}
+
+static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
+		int oobsize, int pagenum, void *databuf, int raw)
+{
+	void __iomem *bch_regs = info->bch_base;
+	unsigned column = 0;
+	struct mxs_dma_cmd *d;
+	int cmd_queue_len;
+	u8 *cmd_buf;
+	int ret;
+	uint8_t	*status;
+	int i;
+	int timeout;
+	int descnum = 0;
+	int max_pagenum = info->nand_size /
+		info->organization.pagesize;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - read0 */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_READ0;
+	cmd_buf[cmd_queue_len++] = column;
+	cmd_buf[cmd_queue_len++] = column >> 8;
+	cmd_buf[cmd_queue_len++] = pagenum;
+	cmd_buf[cmd_queue_len++] = pagenum >> 8;
+
+	if ((max_pagenum - 1) >= SZ_64K)
+		cmd_buf[cmd_queue_len++] = pagenum >> 16;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - readstart */
+	cmd_buf = &info->cmd_buf[8];
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+
+	cmd_buf[cmd_queue_len++] = NAND_CMD_READSTART;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - wait for ready. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_CHAIN |
+		DMACMD_NAND_WAIT_4_READY |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(2);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	if (raw) {
+		/* Compile DMA descriptor - read. */
+		d = &info->desc[descnum++];
+		d->data = DMACMD_WAIT4END |
+			DMACMD_PIO_WORDS(1) |
+			DMACMD_XFER_COUNT(writesize + oobsize) |
+			DMACMD_COMMAND_DMA_WRITE;
+		d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+			GPMI_CTRL0_WORD_LENGTH |
+			GPMI_CTRL0_CS(info->cs) |
+			GPMI_CTRL0_ADDRESS_NAND_DATA |
+			(writesize + oobsize);
+		d->address = (dma_addr_t)databuf;
+	} else {
+		/* Compile DMA descriptor - enable the BCH block and read. */
+		d = &info->desc[descnum++];
+		d->data = DMACMD_WAIT4END | DMACMD_PIO_WORDS(6);
+		d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+			GPMI_CTRL0_WORD_LENGTH |
+			GPMI_CTRL0_CS(info->cs) |
+			GPMI_CTRL0_ADDRESS_NAND_DATA |
+			(writesize + oobsize);
+		d->pio_words[1] = 0;
+		d->pio_words[2] = GPMI_ECCCTRL_ENABLE_ECC |
+			GPMI_ECCCTRL_ECC_CMD_DECODE |
+			GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+		d->pio_words[3] = writesize + oobsize;
+		d->pio_words[4] = (dma_addr_t)databuf;
+		d->pio_words[5] = (dma_addr_t)(databuf + writesize);
+
+		/* Compile DMA descriptor - disable the BCH block. */
+		d = &info->desc[descnum++];
+		d->data = DMACMD_NAND_WAIT_4_READY |
+			DMACMD_WAIT4END |
+			DMACMD_PIO_WORDS(3);
+		d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+			GPMI_CTRL0_WORD_LENGTH |
+			GPMI_CTRL0_CS(info->cs) |
+			GPMI_CTRL0_ADDRESS_NAND_DATA |
+			(writesize + oobsize);
+	}
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		goto err;
+	}
+
+	if (raw)
+		return 0;
+
+	timeout = 1000000;
+
+	while (1) {
+		if (!timeout--) {
+			ret = -ETIMEDOUT;
+			goto err;
+		}
+
+		if (readl(bch_regs + BCH_CTRL) & BCH_CTRL_COMPLETE_IRQ)
+			break;
+	}
+
+	writel(BCH_CTRL_COMPLETE_IRQ,
+		bch_regs + BCH_CTRL + STMP_OFFSET_REG_CLR);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	status = databuf + writesize + mxs_nand_aux_status_offset();
+	for (i = 0; i < writesize / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; i++) {
+		if (status[i] == 0xfe) {
+			ret = -EBADMSG;
+			goto err;
+		}
+	}
+
+	ret = 0;
+err:
+	return ret;
+}
+
+static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
+{
+	int ret;
+	u8 *cmd_buf;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - READ STATUS */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_STATUS;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - read. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(1) |
+		DMACMD_COMMAND_DMA_WRITE;
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(1);
+	d->address = (dma_addr_t)databuf;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int mxs_nand_reset(struct mxs_nand_info *info, void *databuf)
+{
+	int ret, i;
+	u8 *cmd_buf;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+	u8 read_status;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - RESET */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_RESET;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	/* Wait for NAND to wake up */
+	for (i = 0; i < 10; i++) {
+		__udelay(50000);
+		ret = mxs_nand_get_read_status(info, databuf);
+		if (ret)
+			return ret;
+		memcpy(&read_status, databuf, 1);
+		if (read_status == 0xe0)
+			return 0;
+	}
+
+	pr_warn("NAND Reset failed\n");
+	return -1;
+}
+
+/* function taken from nand_onfi.c */
+static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
+{
+	int i;
+
+	while (len--) {
+		crc ^= *p++ << 8;
+		for (i = 0; i < 8; i++)
+			crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
+	}
+	return crc;
+}
+
+static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
+{
+	int ret;
+	u8 *cmd_buf;
+	u16 crc;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+	struct nand_onfi_params nand_params;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - READ PARAMETER PAGE */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_PARAM;
+	cmd_buf[cmd_queue_len++] = 0x00;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - wait for ready. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_CHAIN |
+		DMACMD_NAND_WAIT_4_READY |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(2);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	/* Compile DMA descriptor - read. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(sizeof(struct nand_onfi_params)) |
+		DMACMD_COMMAND_DMA_WRITE;
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(sizeof(struct nand_onfi_params));
+	d->address = (dma_addr_t)databuf;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	memcpy(&nand_params, databuf, sizeof(struct nand_onfi_params));
+
+	crc = onfi_crc16(NAND_ONFI_CRC_BASE, (u8 *)&nand_params, 254);
+	pr_debug("ONFI CRC: 0x%x, CALC. CRC 0x%x\n", nand_params.crc, crc);
+	if (crc != le16_to_cpu(nand_params.crc)) {
+		pr_debug("ONFI CRC mismatch!\n");
+		ret = -EUCLEAN;
+		return ret;
+	}
+
+	/* Fill the NAND organization struct with data */
+	info->organization.bits_per_cell = nand_params.bits_per_cell;
+	info->organization.pagesize = le32_to_cpu(nand_params.byte_per_page);
+	info->organization.oobsize =
+		le16_to_cpu(nand_params.spare_bytes_per_page);
+	info->organization.pages_per_eraseblock =
+		le32_to_cpu(nand_params.pages_per_block);
+	info->organization.eraseblocks_per_lun =
+		le32_to_cpu(nand_params.blocks_per_lun);
+	info->organization.max_bad_eraseblocks_per_lun =
+		le16_to_cpu(nand_params.bb_per_lun);
+	info->organization.luns_per_target = nand_params.lun_count;
+	info->nand_size = info->organization.pagesize *
+		info->organization.pages_per_eraseblock *
+		info->organization.eraseblocks_per_lun *
+		info->organization.luns_per_target;
+
+	return ret;
+}
+
+static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
+{
+	int ret;
+	u8 *cmd_buf;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+
+	struct onfi_header {
+		u8 byte0;
+		u8 byte1;
+		u8 byte2;
+		u8 byte3;
+	} onfi_head;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - READID + 0x20 (ADDR) */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_READID;
+	cmd_buf[cmd_queue_len++] = 0x20;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - read. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(sizeof(struct onfi_header)) |
+		DMACMD_COMMAND_DMA_WRITE;
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(sizeof(struct onfi_header));
+	d->address = (dma_addr_t)databuf;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	memcpy(&onfi_head, databuf, sizeof(struct onfi_header));
+
+	pr_debug("ONFI Byte0: 0x%x\n", onfi_head.byte0);
+	pr_debug("ONFI Byte1: 0x%x\n", onfi_head.byte1);
+	pr_debug("ONFI Byte2: 0x%x\n", onfi_head.byte2);
+	pr_debug("ONFI Byte3: 0x%x\n", onfi_head.byte3);
+
+	/* check if returned values correspond to ascii characters "ONFI" */
+	if (onfi_head.byte0 != 0x4f || onfi_head.byte1 != 0x4e ||
+		onfi_head.byte2 != 0x46 || onfi_head.byte3 != 0x49) {
+		pr_warn("ONFI not supported\n");
+		return 1;
+	}
+
+	return 0;
+}
+
+static int mxs_nand_get_readid(struct mxs_nand_info *info, void *databuf)
+{
+	int ret;
+	u8 *cmd_buf;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+
+	struct readid_data {
+		u8 byte0;
+		u8 byte1;
+		u8 byte2;
+		u8 byte3;
+		u8 byte4;
+	} id_data;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - READID */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_READID;
+	cmd_buf[cmd_queue_len++] = 0x00;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - read. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(sizeof(struct readid_data)) |
+		DMACMD_COMMAND_DMA_WRITE;
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(sizeof(struct readid_data));
+	d->address = (dma_addr_t)databuf;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	memcpy(&id_data, databuf, sizeof(struct readid_data));
+
+	pr_debug("NAND Byte0: 0x%x\n", id_data.byte0);
+	pr_debug("NAND Byte1: 0x%x\n", id_data.byte1);
+	pr_debug("NAND Byte2: 0x%x\n", id_data.byte2);
+	pr_debug("NAND Byte3: 0x%x\n", id_data.byte3);
+	pr_debug("NAND Byte4: 0x%x\n", id_data.byte4);
+
+	if (id_data.byte0 == 0xff || id_data.byte1 == 0xff ||
+		id_data.byte2 == 0xff || id_data.byte3 == 0xff ||
+		id_data.byte4 == 0xff) {
+		pr_err("\"READ ID\" returned 0xff, possible error!\n");
+		return -EOVERFLOW;
+	}
+
+	/* Fill the NAND organization struct with data */
+	info->organization.bits_per_cell =
+		(1 << ((id_data.byte2 >> 2) & 0x3)) * 2;
+	info->organization.pagesize =
+		(1 << (id_data.byte3 & 0x3)) * SZ_1K;
+	info->organization.oobsize = id_data.byte3 & 0x4 ?
+		info->organization.pagesize / 512 * 16 :
+		info->organization.pagesize / 512 * 8;
+	info->organization.pages_per_eraseblock =
+		(1 << ((id_data.byte3 >> 4) & 0x3)) * SZ_64K /
+		info->organization.pagesize;
+	info->organization.planes_per_lun =
+		1 << ((id_data.byte4 >> 2) & 0x3);
+	info->nand_size = info->organization.planes_per_lun *
+		(1 << ((id_data.byte4 >> 4) & 0x7)) * SZ_8M;
+	info->organization.eraseblocks_per_lun = info->nand_size /
+		(info->organization.pages_per_eraseblock *
+		info->organization.pagesize);
+
+	return ret;
+}
+
+static int mxs_nand_get_info(struct mxs_nand_info *info, void *databuf)
+{
+	int ret, i;
+
+	ret = mxs_nand_check_onfi(info, databuf);
+	if (ret) {
+		if (ret != 1)
+			return ret;
+		pr_warn("ONFI not supported, try \"READ ID\"...\n");
+	} else {
+		/*
+		 * Some NAND's don't return the correct data the first time
+		 * "READ PARAMETER PAGE" is returned. Execute the command
+		 * multimple times
+		 */
+		for (i = 0; i < 3; i++) {
+			/*
+			 * Some NAND's need to be reset before "READ PARAMETER
+			 * PAGE" can be successfully executed.
+			 */
+			ret = mxs_nand_reset(info, databuf);
+			if (ret)
+				return ret;
+			ret = mxs_nand_get_onfi(info, databuf);
+			if (ret)
+				pr_err("ONFI error: %d\n", ret);
+			else
+				break;
+		}
+		if (!ret)
+			goto succ;
+	}
+
+	/*
+	 * If ONFI is not supported or if it fails try to get NAND's info from
+	 * "READ ID" command.
+	 */
+	pr_debug("Trying \"READ ID\" command...\n");
+	ret = mxs_nand_get_readid(info, databuf);
+	if (ret) {
+		if (ret != -EOVERFLOW)
+			return ret;
+
+		/*
+		 * If NAND's "READ ID" returns bad values, try to set them to
+		 * default (most common NAND memory org.) and continue.
+		 */
+		pr_warn("NANDs READ ID command returned bad values" \
+			" set them to default and try to continue!\n");
+		info->organization.pagesize = 2048;
+		info->organization.oobsize = 64;
+		info->nand_size = SZ_1G;
+	}
+succ:
+	pr_debug("NAND page_size: %d\n", info->organization.pagesize);
+	pr_debug("NAND block_size: %d\n",
+		info->organization.pages_per_eraseblock
+		* info->organization.pagesize);
+	pr_debug("NAND oob_size: %d\n", info->organization.oobsize);
+	pr_debug("NAND nand_size: %lu\n", info->nand_size);
+	pr_debug("NAND bits_per_cell: %d\n", info->organization.bits_per_cell);
+	pr_debug("NAND planes_per_lun: %d\n",
+		info->organization.planes_per_lun);
+	pr_debug("NAND luns_per_target: %d\n",
+		info->organization.luns_per_target);
+	pr_debug("NAND eraseblocks_per_lun: %d\n",
+		info->organization.eraseblocks_per_lun);
+	pr_debug("NAND ntargets: %d\n", info->organization.ntargets);
+
+
+	return 0;
+}
+
+/* ---------------------------- BCB handling part -------------------------- */
+
+static uint32_t calc_chksum(void *buf, size_t size)
+{
+	u32 chksum = 0;
+	u8 *bp = buf;
+	size_t i;
+
+	for (i = 0; i < size; i++)
+		chksum += bp[i];
+
+	return ~chksum;
+}
+
+static int get_fcb(struct mxs_nand_info *info, void *databuf)
+{
+	int i, pagenum, ret;
+	uint32_t checksum;
+	struct fcb_block *fcb = &info->fcb;
+
+	/* First page read fails, this shouldn't be necessary */
+	mxs_nand_read_page(info, info->organization.pagesize,
+		info->organization.oobsize, 0, databuf, 1);
+
+	for (i = 0; i < 4; i++) {
+		pagenum = 64 * i;
+
+		ret = mxs_nand_read_page(info, info->organization.pagesize,
+			info->organization.oobsize, pagenum, databuf, 1);
+		if (ret)
+			continue;
+
+		memcpy(fcb, databuf + mxs_nand_aux_status_offset(),
+			sizeof(*fcb));
+
+		if (fcb->FingerPrint != FCB_FINGERPRINT) {
+			pr_err("No FCB found on page %d\n", pagenum);
+			continue;
+		}
+
+		checksum = calc_chksum((void *)fcb +
+			sizeof(uint32_t), sizeof(*fcb) - sizeof(uint32_t));
+
+		if (checksum != fcb->Checksum) {
+			pr_err("FCB on page %d has invalid checksum. " \
+				"Expected: 0x%08x, calculated: 0x%08x",
+				pagenum, fcb->Checksum, checksum);
+			continue;
+		}
+
+		pr_debug("Found FCB:\n");
+		pr_debug("PageDataSize:     0x%08x\n", fcb->PageDataSize);
+		pr_debug("TotalPageSize:    0x%08x\n", fcb->TotalPageSize);
+		pr_debug("SectorsPerBlock:  0x%08x\n", fcb->SectorsPerBlock);
+		pr_debug("FW1_startingPage: 0x%08x\n",
+			fcb->Firmware1_startingPage);
+		pr_debug("PagesInFW1:       0x%08x\n", fcb->PagesInFirmware1);
+		pr_debug("FW2_startingPage: 0x%08x\n",
+			fcb->Firmware2_startingPage);
+		pr_debug("PagesInFW2:       0x%08x\n", fcb->PagesInFirmware2);
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int get_dbbt(struct mxs_nand_info *info, void *databuf)
+{
+	int i, ret;
+	int page;
+	int startpage = info->fcb.DBBTSearchAreaStartAddress;
+	struct dbbt_block dbbt;
+
+	for (i = 0; i < 4; i++) {
+		page = startpage + i * 64;
+
+		ret = mxs_nand_read_page(info, info->organization.pagesize,
+			info->organization.oobsize, page, databuf, 0);
+		if (ret)
+			continue;
+
+		memcpy(&dbbt, databuf, sizeof(struct dbbt_block));
+
+		if (*(u32 *)(databuf + sizeof(u32)) != DBBT_FINGERPRINT)
+			continue;
+
+		/* Version check */
+		if (be32_to_cpup(databuf + 2 * sizeof(u32)) < 1)
+			return -ENOENT;
+
+		ret = mxs_nand_read_page(info, info->organization.pagesize,
+			info->organization.oobsize, page + 4, databuf, 0);
+		if (ret)
+			continue;
+
+		info->dbbt_num_entries = *(u32 *)(databuf + sizeof(u32));
+
+		pr_debug("Found DBBT with %d entries\n",
+			info->dbbt_num_entries);
+		pr_debug("Checksum = 0x%08x\n", dbbt.Checksum);
+		pr_debug("FingerPrint = 0x%08x\n", dbbt.FingerPrint);
+		pr_debug("Version = 0x%08x\n", dbbt.Version);
+		pr_debug("numberBB = 0x%08x\n", dbbt.numberBB);
+		pr_debug("DBBTNumOfPages= 0x%08x\n", dbbt.DBBTNumOfPages);
+
+		for (i = 0; i < info->dbbt_num_entries; i++)
+			pr_debug("badblock %d at block %d\n", i,
+				*(u32 *)(databuf + (2 + i) * sizeof(u32)));
+
+		info->dbbt = databuf + 2 * sizeof(u32);
+
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+static int block_is_bad(struct mxs_nand_info *info, int blocknum)
+{
+	int i;
+	u32 *dbbt = info->dbbt;
+
+	if (!dbbt)
+		return 0;
+
+	for (i = 0; i < info->dbbt_num_entries; i++) {
+		if (dbbt[i] == blocknum)
+			return 1;
+	}
+
+	return 0;
+}
+
+static int read_firmware(struct mxs_nand_info *info, int startpage,
+	void *dest, int len)
+{
+	int curpage = startpage;
+	struct fcb_block *fcb = &info->fcb;
+	int pagesperblock = fcb->SectorsPerBlock;
+	int numpages = (len / fcb->PageDataSize) + 1;
+	int ret;
+	int pagesize = fcb->PageDataSize;
+	int oobsize = fcb->TotalPageSize - pagesize;
+
+	pr_debug("Reading %d pages starting from page %d\n",
+		numpages, startpage);
+
+	if (block_is_bad(info, curpage / pagesperblock))
+		curpage = ALIGN_DOWN(curpage + pagesperblock, pagesperblock);
+
+	while (numpages) {
+		if (!(curpage & (pagesperblock - 1))) {
+			/* Check for bad blocks on each block boundary */
+			if (block_is_bad(info, curpage / pagesperblock)) {
+				pr_debug("Skipping bad block at page %d\n",
+					curpage);
+				curpage += pagesperblock;
+				continue;
+			}
+		}
+
+		ret = mxs_nand_read_page(info, pagesize, oobsize,
+			curpage, dest, 0);
+		if (ret) {
+			pr_debug("Failed to read page %d\n", curpage);
+			return ret;
+		}
+
+		*((u8 *)dest + fcb->BadBlockMarkerByte) =
+			*(u8 *)(dest + pagesize);
+
+		numpages--;
+		dest += pagesize;
+		curpage++;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused imx6_nand_load_image(void *cmdbuf, void *descs,
+	void *databuf, void *dest, int len)
+{
+	struct mxs_nand_info info = {
+		.io_base = (void *)0x00112000,
+		.bch_base = (void *)0x00114000,
+	};
+	struct apbh_dma apbh = {
+		.id = IMX28_DMA,
+		.regs = (void *)0x00110000,
+	};
+	struct mxs_dma_chan pchan = {
+		.channel = 0, /* MXS: MXS_DMA_CHANNEL_AHB_APBH_GPMI0 */
+		.apbh = &apbh,
+	};
+	int ret;
+	struct fcb_block *fcb;
+
+	info.dma_channel = &pchan;
+
+	pr_debug("cmdbuf: 0x%p descs: 0x%p databuf: 0x%p dest: 0x%p\n",
+			cmdbuf, descs, databuf, dest);
+
+	/* Command buffers */
+	info.cmd_buf = cmdbuf;
+	info.desc = descs;
+
+	ret = mxs_nand_get_info(&info, databuf);
+	if (ret)
+		return ret;
+
+	ret = get_fcb(&info, databuf);
+	if (ret)
+		return ret;
+
+	fcb = &info.fcb;
+
+	get_dbbt(&info, databuf);
+
+	ret = read_firmware(&info, fcb->Firmware1_startingPage, dest, len);
+	if (ret) {
+		pr_err("Failed to read firmware1, trying firmware2\n");
+		ret = read_firmware(&info, fcb->Firmware2_startingPage,
+			dest, len);
+		if (ret) {
+			pr_err("Failed to also read firmware2\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int imx6_nand_start_image(void)
+{
+	int ret;
+	void *sdram = (void *)0x10000000;
+	void __noreturn (*bb)(void);
+	void *cmdbuf, *databuf, *descs;
+
+	cmdbuf = sdram;
+	descs = sdram + MXS_NAND_COMMAND_BUFFER_SIZE;
+	databuf = descs +
+		sizeof(struct mxs_dma_cmd) * MXS_NAND_DMA_DESCRIPTOR_COUNT;
+	bb = (void *)PAGE_ALIGN((unsigned long)databuf + SZ_8K);
+
+	ret = imx6_nand_load_image(cmdbuf, descs, databuf,
+		bb, imx_image_size());
+	if (ret) {
+		pr_err("Loading image failed: %d\n", ret);
+		return ret;
+	}
+
+	pr_debug("Starting barebox image at 0x%p\n", bb);
+
+	arm_early_mmu_cache_invalidate();
+	barrier();
+
+	bb();
+}
-- 
2.25.1



From andrej.picej at norik.com  Wed Jan 20 07:52:03 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Wed, 20 Jan 2021 13:52:03 +0100
Subject: [RFC PATCH] ARM: phytec-som-imx6: phycard DRAM autodetection
Message-ID: <20210120125203.736421-1-andrej.picej@norik.com>

Add support for automatic DRAM size detection on phytec phycard imx6q
machines. Currently supported SoM variants are 1 GiB (1 bank) and 2 GiB
variant. Machines now boot from internal SRAM (see DCD table loadaddr
0x00907000) and then do DRAM size detection and configuration in plain
C code (instead of hardcoded DCD table values). After initializing DRAM,
remaining barebox image is xloaded from GPMI NAND to DRAM and started
from there.

Booting process / strategy on phycard machines:
 1) lowlevel in SRAM (PBL)
  1.1) detect DRAM size
  1.2) configure DRAM accordingly
  1.3) copy remaining barebox image from NAND to DRAM (addr 0x10000000)
  1.4) jump to DRAM (addr 0x10000000)
 2) lowlevel in DRAM (PBL)
  2.1) skip DRAM detection since already running from DRAM
  2.2) main barebox entry
 3) board code
 4) ...

Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
Signed-off-by: Andrej Picej <andrej.picej at norik.com>
---
 .../flash-header-phytec-pcaaxl3.imxcfg        |   4 +
 arch/arm/boards/phytec-som-imx6/lowlevel.c    | 255 ++++++++++++++++++
 images/Makefile.imx                           |   2 +
 3 files changed, 261 insertions(+)
 create mode 100644 arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3.imxcfg

diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3.imxcfg
new file mode 100644
index 000000000..fcfef9c23
--- /dev/null
+++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3.imxcfg
@@ -0,0 +1,4 @@
+soc imx6
+loadaddr 0x00907000
+max_load_size 0x31000
+ivtofs 0x400
diff --git a/arch/arm/boards/phytec-som-imx6/lowlevel.c b/arch/arm/boards/phytec-som-imx6/lowlevel.c
index 62a1c8de7..7bc9d123a 100644
--- a/arch/arm/boards/phytec-som-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-som-imx6/lowlevel.c
@@ -16,6 +16,261 @@
 #include <asm/cache.h>
 #include <asm/mmu.h>
 #include <mach/imx6.h>
+#include <mach/imx6-mmdc.h>
+#include <mach/esdctl.h>
+#include <mach/xload.h>
+
+/* udelay() is not available in PBL, need to improvise */
+static void __udelay(int us)
+{
+	volatile int i;
+
+	for (i = 0; i < us * 4; i++);
+}
+
+#define	IMX6Q_UART2			2
+#define	IMX6Q_UART3			3
+#define	DRIVE_STRENGTH_40_OHM		0x30
+#define	DRIVE_STRENGTH_48_OHM		0x28
+
+/* mmdc DDR io registers */
+static struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = {
+	.dram_sdclk_0 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdclk_1 = DRIVE_STRENGTH_40_OHM,
+	.dram_cas = DRIVE_STRENGTH_40_OHM,
+	.dram_ras = DRIVE_STRENGTH_40_OHM,
+	.dram_reset = DRIVE_STRENGTH_40_OHM,
+	.dram_sdcke0 = 0x00003000,
+	.dram_sdcke1 = 0x00003000,
+	.dram_sdba2 = 0x00000000,
+	.dram_sdodt0 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdodt1 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdqs0 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdqs1 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdqs2 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdqs3 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdqs4 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdqs5 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdqs6 = DRIVE_STRENGTH_40_OHM,
+	.dram_sdqs7 = DRIVE_STRENGTH_40_OHM,
+	.dram_dqm0 = DRIVE_STRENGTH_40_OHM,
+	.dram_dqm1 = DRIVE_STRENGTH_40_OHM,
+	.dram_dqm2 = DRIVE_STRENGTH_40_OHM,
+	.dram_dqm3 = DRIVE_STRENGTH_40_OHM,
+	.dram_dqm4 = DRIVE_STRENGTH_40_OHM,
+	.dram_dqm5 = DRIVE_STRENGTH_40_OHM,
+	.dram_dqm6 = DRIVE_STRENGTH_40_OHM,
+	.dram_dqm7 = DRIVE_STRENGTH_40_OHM,
+};
+
+static struct mx6_mmdc_calibration mx6q_mmdc_calib = {
+	.p0_mpwldectrl0 = 0x0013001b,
+	.p0_mpwldectrl1 = 0x003b0034,
+	.p1_mpwldectrl0 = 0x0037004b,
+	.p1_mpwldectrl1 = 0x004b0055,
+	.p0_mpdgctrl0 = 0x4350035e,
+	.p0_mpdgctrl1 = 0x035c0358,
+	.p1_mpdgctrl0 = 0x436e0376,
+	.p1_mpdgctrl1 = 0x03770352,
+	.p0_mprddlctl = 0x3c333436,
+	.p1_mprddlctl = 0x35332f3b,
+	.p0_mpwrdlctl = 0x37363e39,
+	.p1_mpwrdlctl = 0x432f433d,
+};
+
+/* MT41K128M16JT-125 IT */
+static struct mx6_ddr3_cfg mt41k128m16jt = {
+	.mem_speed = 1600,
+	.density = 2,
+	.width = 16,
+	.banks = 8,
+	.rowaddr = 14,
+	.coladdr = 10,
+	.pagesz = 2,
+	.trcd = 1375,
+	.trcmin = 4875,
+	.trasmin = 3500,
+};
+
+/* DDR 64bit 1GB */
+static struct mx6_ddr_sysinfo mem1g_q = {
+	.dsize		= 2,
+	.cs1_mirror	= 1,
+	.cs_density	= 8,
+	.ncs		= 1,
+	.bi_on		= 1,
+	.rtt_nom	= 1,
+	.rtt_wr		= 0,
+	.ralat		= 5,
+	.walat		= 1,
+	.mif3_mode	= 3,
+	.rst_to_cke	= 0x23,
+	.sde_to_rst	= 0x10,
+};
+
+/* DDR 64bit 2GB */
+static struct mx6_ddr_sysinfo mem2g_q = {
+	.dsize		= 2,
+	.cs1_mirror	= 1,
+	.cs_density	= 8,
+	.ncs		= 2,
+	.bi_on		= 1,
+	.rtt_nom	= 1,
+	.rtt_wr		= 0,
+	.ralat		= 5,
+	.walat		= 1,
+	.mif3_mode	= 3,
+	.rst_to_cke	= 0x23,
+	.sde_to_rst	= 0x10,
+};
+
+/* mmdc GRP io registers */
+static struct mx6dq_iomux_grp_regs mx6dq_grp_ioregs = {
+	.grp_ddr_type = 0x000c0000,
+	.grp_ddrmode_ctl = 0x00020000,
+	.grp_ddrpke = 0x00000000,
+	.grp_addds = DRIVE_STRENGTH_40_OHM,
+	.grp_ctlds = DRIVE_STRENGTH_40_OHM,
+	.grp_ddrmode = 0x00020000,
+	.grp_b0ds = DRIVE_STRENGTH_40_OHM,
+	.grp_b1ds = DRIVE_STRENGTH_40_OHM,
+	.grp_b2ds = DRIVE_STRENGTH_40_OHM,
+	.grp_b3ds = DRIVE_STRENGTH_40_OHM,
+	.grp_b4ds = DRIVE_STRENGTH_40_OHM,
+	.grp_b5ds = DRIVE_STRENGTH_40_OHM,
+	.grp_b6ds = DRIVE_STRENGTH_40_OHM,
+	.grp_b7ds = DRIVE_STRENGTH_40_OHM,
+};
+
+static inline void setup_uart_phycard_imx6q(int UARTn)
+{
+	void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
+
+	switch (UARTn) {
+	case IMX6Q_UART2:
+		/* Setup UART2 pin muxing */
+		writel(0x4, iomuxbase + 0xc0);
+		writel(0x4, iomuxbase + 0xbc);
+		writel(0x1, iomuxbase + 0x928);
+
+		imx6_ungate_all_peripherals();
+		imx6_uart_setup((void *)MX6_UART2_BASE_ADDR);
+		pbl_set_putc(imx_uart_putc, (void *)MX6_UART2_BASE_ADDR);
+		break;
+	case IMX6Q_UART3:
+		/* Setup UART3 pin muxing */
+		writel(0x2, iomuxbase + 0xb4);
+		writel(0x2, iomuxbase + 0xb8);
+		writel(0x1, iomuxbase + 0x930);
+
+		imx6_ungate_all_peripherals();
+		imx6_uart_setup((void *)MX6_UART3_BASE_ADDR);
+		pbl_set_putc(imx_uart_putc, (void *)MX6_UART3_BASE_ADDR);
+		break;
+	default:
+		return;
+	}
+
+	putc_ll('>');
+}
+
+#define DRAM_CONFIG_DELAY	5000
+#define DRAM_CALIB_DELAY	50000
+
+static unsigned long phycard_imx6q_ll_autodetect_dram_init(void)
+{
+	unsigned long memsize = SZ_2G;
+	unsigned long dram_size = 0;
+
+	pr_debug("DRAM init & size detection\n");
+
+	/* First try with 2 GiB DRAM configuration */
+	mx6dq_dram_iocfg(64, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
+	mx6_dram_cfg(&mem2g_q, &mx6q_mmdc_calib, &mt41k128m16jt);
+	__udelay(DRAM_CONFIG_DELAY);
+
+	mmdc_do_write_level_calibration();
+	mmdc_do_dqs_calibration();
+	__udelay(DRAM_CALIB_DELAY);
+
+	pr_debug("DRAM probe with 2 GiB config\n");
+
+	dram_size = get_ram_size((volatile long *)0x10000000, (long)memsize);
+	pr_debug("DRAM detected size: 0x%lx\n", dram_size);
+
+	if (dram_size != SZ_2G) {
+		/* Next try with 1 GiB DRAM configuration */
+		memsize = SZ_1G;
+
+		mx6dq_dram_iocfg(64, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
+		mx6_dram_cfg(&mem1g_q, &mx6q_mmdc_calib, &mt41k128m16jt);
+		__udelay(DRAM_CONFIG_DELAY);
+
+		mmdc_do_write_level_calibration();
+		mmdc_do_dqs_calibration();
+		__udelay(DRAM_CALIB_DELAY);
+
+		pr_debug("DRAM probe with 1 GiB config\n");
+	} else {
+		pr_debug("DRAM size 0x%lx already detected, " \
+			"skipping DRAM re-configuration\n", dram_size);
+	}
+
+	dram_size = get_ram_size((volatile long *)0x10000000, (long)memsize);
+	pr_debug("DRAM final detected size: 0x%lx\n", dram_size);
+
+#ifdef DEBUG
+	pr_debug("DRAM calibration results:\n");
+	mmdc_print_calibration_results();
+#endif
+	return memsize;
+}
+
+static void phycard_imx6q_ll_autodetect_init(void)
+{
+	if (IS_ENABLED(CONFIG_DEBUG_LL))
+		setup_uart_phycard_imx6q(IMX6Q_UART3);
+
+	/* Already running from DRAM? */
+	if (get_pc() > 0x10000000) {
+		pr_debug("DRAM already initialized, skipping...\n");
+		return;
+	}
+
+	/* Running from SRAM, need to configure DRAM */
+	phycard_imx6q_ll_autodetect_dram_init();
+
+	/* Now xload remaining part of barebox image from NAND */
+	pr_debug("xloading barebox image from NAND\n");
+	imx6_nand_start_image();
+
+	pr_err("Booting failed!\n");
+	hang();
+}
+
+extern char __dtb_imx6q_phytec_phycard_start[];
+
+static noinline void phycard_imx6q_ll_autodetect_start(void)
+{
+	void *fdt = __dtb_imx6q_phytec_phycard_start + get_runtime_offset();
+
+	phycard_imx6q_ll_autodetect_init();
+
+	imx6q_barebox_entry(fdt);
+}
+
+ENTRY_FUNCTION(start_phycard_imx6q_ll_autodetect, r0, r1, r2)
+{
+	imx6_cpu_lowlevel_init();
+
+	arm_setup_stack(0x00940000);
+
+	relocate_to_current_adr();
+	setup_c();
+	barrier();
+
+	phycard_imx6q_ll_autodetect_start();
+}
 
 static inline void setup_uart(void)
 {
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 514db326b..80d2fd805 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -205,6 +205,8 @@ $(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phyboard_su
 
 $(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phyboard_subra_1gib_1bank, phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank, phytec-phyboard-subra-1gib-1bank)
 
+$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phycard_imx6q_ll_autodetect, phytec-som-imx6/flash-header-phytec-pcaaxl3, phytec-phycard-imx6q-som-nand)
+
 $(call build_imx_habv4img, CONFIG_MACH_DFI_FS700_M60, start_imx6dl_dfi_fs700_m60_6s, dfi-fs700-m60/flash-header-fs700-m60-6s, dfi-fs700-m60-6s)
 
 $(call build_imx_habv4img, CONFIG_MACH_DFI_FS700_M60, start_imx6q_dfi_fs700_m60_6q_micron, dfi-fs700-m60/flash-header-fs700-m60-6q-micron, dfi-fs700-m60-6q-micron)
-- 
2.25.1



From m.felsch at pengutronix.de  Wed Jan 20 08:26:54 2021
From: m.felsch at pengutronix.de (Marco Felsch)
Date: Wed, 20 Jan 2021 14:26:54 +0100
Subject: [PATCH 1/2] blspec: allow board files to overwrite config file
 settings
In-Reply-To: <20210120123133.GY9321@pengutronix.de>
References: <20210118204850.8420-1-m.felsch@pengutronix.de>
 <20210119110134.GX19063@pengutronix.de>
 <20210119114208.6kxdsj5pa5zo25qo@pengutronix.de>
 <20210120090321.GY19063@pengutronix.de>
 <20210120105422.zpizm7bet22ze4dq@pengutronix.de>
 <20210120123133.GY9321@pengutronix.de>
Message-ID: <20210120132654.odcbdxu64v6clibs@pengutronix.de>

On 21-01-20 13:31, Michael Olbrich wrote:
> On Wed, Jan 20, 2021 at 11:54:22AM +0100, Marco Felsch wrote:
> > On 21-01-20 10:03, Sascha Hauer wrote:
> > > On Tue, Jan 19, 2021 at 12:42:08PM +0100, Marco Felsch wrote:
> > > > Hi Sascha,
> > > > 
> > > > On 21-01-19 12:01, Sascha Hauer wrote:
> > > > > Hi Marco,
> > > > > On Mon, Jan 18, 2021 at 09:48:49PM +0100, Marco Felsch wrote:
> > > > > > This commit adds the support to overwrite and/or adapt blspec config
> > > > > > files by the following global variables:
> > > > > >   - global.blspec.fixup.devicetree
> > > > > >   - global.blspec.fixup.initrd
> > > > > >   - global.blspec.fixup.options
> > > > > >   - global.blspec.fixup.linux
> > > > > >   - global.blspec.fixup.devicetree-overlay.
> > > > > > 
> > > > > > Overwriting blspec-config's shouldn't be the normal case but there are
> > > > > > cases where this support is needed. One use-case can be a special
> > > > > > handling during update. E.g. the normal boot-flow don't need the initrd
> > > > > > but the update-flow uses it because the update system is on the initrd.
> > > > > 
> > > > > When you have an update system and a regular system on the same
> > > > > filesystem then I would expect an additional bootspec entry for the
> > > > > update system.
> > > > 
> > > > AFAIK, barebox tries to find the correct entry by checking all config
> > > > files and loads the first matching config file. Is there a way to
> > > > specify an explicite config file?
> > > 
> > > Not yet, but maybe we are at a point where a way should be added.
> > 
> > Maybe but how do you decide it? Also IMHO this wouldn't be that flexible
> > as this solution.
> 
> Maybe allow globing?
> 
> So I can say I want to boot 'default.conf' and create that as a symlink in
> the filesystem. That would be for the desktop use-case with multiple kernel
> versions.

That would be a solution. But...

> Or I could switch between '*-regular.conf' and '*-update.conf'. And then
> provide two entries for each device-tree.

.. if I wanna cover all platforms I have at least 2 platform confs for
each platform. The reason for that is because different platforms using
different overlays. By platform I mean a different variant of the same
platform family. Therefore I use my abbroach to patch the needed
overlays live and the platform is always the same.

Regards,
  Marco


From barebox+mailing at cookiesoft.de  Wed Jan 20 09:14:04 2021
From: barebox+mailing at cookiesoft.de (barebox+mailing at cookiesoft.de)
Date: Wed, 20 Jan 2021 15:14:04 +0100 (CET)
Subject: /env/init script order
Message-ID: <199631954.110480.1611152044705@office.mailbox.org>

Hey folks, 

according to the doc[0] the scripts in /env/init will be "executed in alphabetical order". But certainly, this isn't the case (for me). 

If I look into the source[1], I see a `readdir` call, which certainly guarantees no order at all. But I want a certain order, at least I want my script to be executed after the automount script. 

1. Why is there a discrepancy? Was there a time where the scripts were executed in order? 
2. How can I achieve, that "my script" get's executed after a certain (the autmount) script? 

Greetings, 
Marcel 


[0]: https://barebox.org/doc/latest/user/defaultenv-2.html#env-init
[1]: https://git.pengutronix.de/cgit/barebox/tree/common/startup.c#n333


From sha at pengutronix.de  Wed Jan 20 10:02:47 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Wed, 20 Jan 2021 16:02:47 +0100
Subject: /env/init script order
In-Reply-To: <199631954.110480.1611152044705@office.mailbox.org>
References: <199631954.110480.1611152044705@office.mailbox.org>
Message-ID: <20210120150247.GB19063@pengutronix.de>

Hi Marcel,

On Wed, Jan 20, 2021 at 03:14:04PM +0100, barebox+mailing at cookiesoft.de wrote:
> Hey folks, 
> 
> according to the doc[0] the scripts in /env/init will be "executed in
> alphabetical order". But certainly, this isn't the case (for me). 
> 
> If I look into the source[1], I see a `readdir` call, which certainly
> guarantees no order at all. But I want a certain order, at least I
> want my script to be executed after the automount script. 
> 
> 1. Why is there a discrepancy? Was there a time where the scripts were
> executed in order?

Yes, indeed. The init scripts once were executed from a shell script
using "for i in /env/init/*; do...". This is guaranteed to be sorted.

When I converted this to C I used plain readdir() and introduced this
bug :(

> 2. How can I achieve, that "my script" get's executed after a certain
> (the autmount) script?

Please try the following patch. This should fix the issues.

Regards,
  Sascha

-----------------------8<---------------------------

>From 5f01cf0e38bf60a5380298ba56f697dc40a1f35e Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer at pengutronix.de>
Date: Wed, 20 Jan 2021 15:54:44 +0100
Subject: [PATCH] startup: Execute init scripts in alphabetical order

Documentation states that init scripts are executed in order and this
had been the case before 90df2a955e. This patch replaced the shell loop
around /env/init/* with a plain readdir which is not sorted at all.
Iterate over the files with glob() which guarantees sorted results.

Reported-by: Marcel <barebox+mailing at cookiesoft.de>
Fixes: 90df2a955e ("defaultenv: Convert init script to C")
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/startup.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/common/startup.c b/common/startup.c
index 1ac36d950c..080feebf05 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -36,6 +36,7 @@
 #include <environment.h>
 #include <linux/ctype.h>
 #include <watchdog.h>
+#include <glob.h>
 
 extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
 		  __barebox_initcalls_end[];
@@ -298,13 +299,12 @@ postcore_initcall(register_autoboot_vars);
 
 static int run_init(void)
 {
-	DIR *dir;
-	struct dirent *d;
-	const char *initdir = "/env/init";
 	const char *bmode;
 	bool env_bin_init_exists;
 	enum autoboot_state autoboot;
 	struct stat s;
+	glob_t g;
+	int i, ret;
 
 	setenv("PATH", "/env/bin");
 	export("PATH");
@@ -326,23 +326,28 @@ static int run_init(void)
 	}
 
 	/* Run scripts in /env/init/ */
-	dir = opendir(initdir);
-	if (dir) {
-		char *scr;
+	ret = glob("/env/init/*", 0, NULL, &g);
+	if (!ret) {
+		for (i = 0; i < g.gl_pathc; i++) {
+			const char *path = g.gl_pathv[i];
+			char *scr;
+
+			ret = stat(path, &s);
+			if (ret)
+				continue;
 
-		while ((d = readdir(dir))) {
-			if (*d->d_name == '.')
+			if (!S_ISREG(s.st_mode))
 				continue;
 
-			pr_debug("Executing '%s/%s'...\n", initdir, d->d_name);
-			scr = basprintf("source %s/%s", initdir, d->d_name);
+			pr_debug("Executing '%s'...\n", path);
+			scr = basprintf("source %s", path);
 			run_command(scr);
 			free(scr);
 		}
-
-		closedir(dir);
 	}
 
+	globfree(&g);
+
 	/* source matching script in /env/bmode/ */
 	bmode = reboot_mode_get();
 	if (bmode) {
-- 
2.20.1

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From rhi at pengutronix.de  Wed Jan 20 16:45:18 2021
From: rhi at pengutronix.de (Roland Hieber)
Date: Wed, 20 Jan 2021 22:45:18 +0100
Subject: [PATCH 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <20210120125107.736121-3-andrej.picej@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-3-andrej.picej@norik.com>
Message-ID: <20210120214518.grammoec2et5uvft@pengutronix.de>

On Wed, Jan 20, 2021 at 01:51:06PM +0100, Andrej Picej wrote:
> From: Sascha Hauer <s.hauer at pengutronix.de>
> 
> Commit is based on initial Sascha Hauer's work. It implements PBL xload
> mechanism to load image from GPMI NAND flash.
> 
> Additional work was done, so that the NAND's size, page size and OOB's
> size are autodetected and not hardcoded. Detection method follows the
> same methods as used in NAND driver, meaning NAND ONFI support is probed
> and if NAND supports ONFI, NAND memory organization is read from ONFI
> parameter page otherwise "READ ID" is used.
> 
> Currently only implemented for i.MX6 familly of SoCs.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
> Signed-off-by: Andrej Picej <andrej.picej at norik.com>

I did not look at the code, but I appreciate how those names line up
nicely :-)

 - Roland

-- 
Roland Hieber, Pengutronix e.K.          | r.hieber at pengutronix.de     |
Steuerwalder Str. 21                     | https://www.pengutronix.de/ |
31137 Hildesheim, Germany                | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686         | Fax:   +49-5121-206917-5555 |


From barebox+mailing at cookiesoft.de  Thu Jan 21 01:56:58 2021
From: barebox+mailing at cookiesoft.de (barebox+mailing at cookiesoft.de)
Date: Thu, 21 Jan 2021 07:56:58 +0100 (CET)
Subject: /env/init script order
In-Reply-To: <20210120150247.GB19063@pengutronix.de>
References: <199631954.110480.1611152044705@office.mailbox.org>
 <20210120150247.GB19063@pengutronix.de>
Message-ID: <455862580.118925.1611212218785@office.mailbox.org>

Hey Sasha,

thanks for that patch, LGTM.
I will integrate that into our yocto build system, should be fairly easy.

Are you planning to patch that upstream?

Greetings
Marcel

I will include it into our yocto environment, should 
> Sascha Hauer <sha at pengutronix.de> hat am 20.01.2021 16:02 geschrieben:
> 
>  
> Hi Marcel,
> 
> On Wed, Jan 20, 2021 at 03:14:04PM +0100, barebox+mailing at cookiesoft.de wrote:
> > Hey folks, 
> > 
> > according to the doc[0] the scripts in /env/init will be "executed in
> > alphabetical order". But certainly, this isn't the case (for me). 
> > 
> > If I look into the source[1], I see a `readdir` call, which certainly
> > guarantees no order at all. But I want a certain order, at least I
> > want my script to be executed after the automount script. 
> > 
> > 1. Why is there a discrepancy? Was there a time where the scripts were
> > executed in order?
> 
> Yes, indeed. The init scripts once were executed from a shell script
> using "for i in /env/init/*; do...". This is guaranteed to be sorted.
> 
> When I converted this to C I used plain readdir() and introduced this
> bug :(
> 
> > 2. How can I achieve, that "my script" get's executed after a certain
> > (the autmount) script?
> 
> Please try the following patch. This should fix the issues.
> 
> Regards,
>   Sascha
> 
> -----------------------8<---------------------------
> 
> From 5f01cf0e38bf60a5380298ba56f697dc40a1f35e Mon Sep 17 00:00:00 2001
> From: Sascha Hauer <s.hauer at pengutronix.de>
> Date: Wed, 20 Jan 2021 15:54:44 +0100
> Subject: [PATCH] startup: Execute init scripts in alphabetical order
> 
> Documentation states that init scripts are executed in order and this
> had been the case before 90df2a955e. This patch replaced the shell loop
> around /env/init/* with a plain readdir which is not sorted at all.
> Iterate over the files with glob() which guarantees sorted results.
> 
> Reported-by: Marcel <barebox+mailing at cookiesoft.de>
> Fixes: 90df2a955e ("defaultenv: Convert init script to C")
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> ---
>  common/startup.c | 29 +++++++++++++++++------------
>  1 file changed, 17 insertions(+), 12 deletions(-)
> 
> diff --git a/common/startup.c b/common/startup.c
> index 1ac36d950c..080feebf05 100644
> --- a/common/startup.c
> +++ b/common/startup.c
> @@ -36,6 +36,7 @@
>  #include <environment.h>
>  #include <linux/ctype.h>
>  #include <watchdog.h>
> +#include <glob.h>
>  
>  extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
>  		  __barebox_initcalls_end[];
> @@ -298,13 +299,12 @@ postcore_initcall(register_autoboot_vars);
>  
>  static int run_init(void)
>  {
> -	DIR *dir;
> -	struct dirent *d;
> -	const char *initdir = "/env/init";
>  	const char *bmode;
>  	bool env_bin_init_exists;
>  	enum autoboot_state autoboot;
>  	struct stat s;
> +	glob_t g;
> +	int i, ret;
>  
>  	setenv("PATH", "/env/bin");
>  	export("PATH");
> @@ -326,23 +326,28 @@ static int run_init(void)
>  	}
>  
>  	/* Run scripts in /env/init/ */
> -	dir = opendir(initdir);
> -	if (dir) {
> -		char *scr;
> +	ret = glob("/env/init/*", 0, NULL, &g);
> +	if (!ret) {
> +		for (i = 0; i < g.gl_pathc; i++) {
> +			const char *path = g.gl_pathv[i];
> +			char *scr;
> +
> +			ret = stat(path, &s);
> +			if (ret)
> +				continue;
>  
> -		while ((d = readdir(dir))) {
> -			if (*d->d_name == '.')
> +			if (!S_ISREG(s.st_mode))
>  				continue;
>  
> -			pr_debug("Executing '%s/%s'...\n", initdir, d->d_name);
> -			scr = basprintf("source %s/%s", initdir, d->d_name);
> +			pr_debug("Executing '%s'...\n", path);
> +			scr = basprintf("source %s", path);
>  			run_command(scr);
>  			free(scr);
>  		}
> -
> -		closedir(dir);
>  	}
>  
> +	globfree(&g);
> +
>  	/* source matching script in /env/bmode/ */
>  	bmode = reboot_mode_get();
>  	if (bmode) {
> -- 
> 2.20.1
> 
> -- 
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Thu Jan 21 03:18:16 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 21 Jan 2021 09:18:16 +0100
Subject: /env/init script order
In-Reply-To: <455862580.118925.1611212218785@office.mailbox.org>
References: <199631954.110480.1611152044705@office.mailbox.org>
 <20210120150247.GB19063@pengutronix.de>
 <455862580.118925.1611212218785@office.mailbox.org>
Message-ID: <20210121081816.GE19063@pengutronix.de>

On Thu, Jan 21, 2021 at 07:56:58AM +0100, barebox+mailing at cookiesoft.de wrote:
> Hey Sasha,
> 
> thanks for that patch, LGTM.
> I will integrate that into our yocto build system, should be fairly easy.
> 
> Are you planning to patch that upstream?

Sure, I'll queue this for the next release.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Thu Jan 21 04:01:48 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 21 Jan 2021 10:01:48 +0100
Subject: [PATCH 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <20210120125107.736121-3-andrej.picej@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-3-andrej.picej@norik.com>
Message-ID: <20210121090148.GF19063@pengutronix.de>

Hi Andrej,

Some comments inline.

On Wed, Jan 20, 2021 at 01:51:06PM +0100, Andrej Picej wrote:
> From: Sascha Hauer <s.hauer at pengutronix.de>
> 
> Commit is based on initial Sascha Hauer's work. It implements PBL xload
> mechanism to load image from GPMI NAND flash.
> 
> Additional work was done, so that the NAND's size, page size and OOB's
> size are autodetected and not hardcoded. Detection method follows the
> same methods as used in NAND driver, meaning NAND ONFI support is probed
> and if NAND supports ONFI, NAND memory organization is read from ONFI
> parameter page otherwise "READ ID" is used.
> 
> Currently only implemented for i.MX6 familly of SoCs.
> 
> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
> ---
>  arch/arm/mach-imx/Makefile             |    2 +-
>  arch/arm/mach-imx/include/mach/xload.h |    1 +
>  arch/arm/mach-imx/xload-gpmi-nand.c    | 1163 ++++++++++++++++++++++++
>  3 files changed, 1165 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c
> 
> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> index e45f758e9..d94c846a1 100644
> --- a/arch/arm/mach-imx/Makefile
> +++ b/arch/arm/mach-imx/Makefile
> +static int mxs_nand_get_info(struct mxs_nand_info *info, void *databuf)
> +{
> +	int ret, i;
> +
> +	ret = mxs_nand_check_onfi(info, databuf);
> +	if (ret) {
> +		if (ret != 1)
> +			return ret;
> +		pr_warn("ONFI not supported, try \"READ ID\"...\n");

You already printed a "ONFI not supported\n" message. Printing it once
is enough. Also this message appears with every non-ONFI nand, right? In
that case it should rather be pr_info()

> +	/*
> +	 * If ONFI is not supported or if it fails try to get NAND's info from
> +	 * "READ ID" command.
> +	 */
> +	pr_debug("Trying \"READ ID\" command...\n");
> +	ret = mxs_nand_get_readid(info, databuf);
> +	if (ret) {
> +		if (ret != -EOVERFLOW)
> +			return ret;
> +
> +		/*
> +		 * If NAND's "READ ID" returns bad values, try to set them to
> +		 * default (most common NAND memory org.) and continue.
> +		 */
> +		pr_warn("NANDs READ ID command returned bad values" \
> +			" set them to default and try to continue!\n");
> +		info->organization.pagesize = 2048;
> +		info->organization.oobsize = 64;
> +		info->nand_size = SZ_1G;

Is this worth it? READ ID is the most basic command, when this doesn't
work I don't think there's a point in continuing.

> +	}
> +succ:
> +	pr_debug("NAND page_size: %d\n", info->organization.pagesize);
> +	pr_debug("NAND block_size: %d\n",
> +		info->organization.pages_per_eraseblock
> +		* info->organization.pagesize);
> +	pr_debug("NAND oob_size: %d\n", info->organization.oobsize);
> +	pr_debug("NAND nand_size: %lu\n", info->nand_size);
> +	pr_debug("NAND bits_per_cell: %d\n", info->organization.bits_per_cell);
> +	pr_debug("NAND planes_per_lun: %d\n",
> +		info->organization.planes_per_lun);
> +	pr_debug("NAND luns_per_target: %d\n",
> +		info->organization.luns_per_target);
> +	pr_debug("NAND eraseblocks_per_lun: %d\n",
> +		info->organization.eraseblocks_per_lun);
> +	pr_debug("NAND ntargets: %d\n", info->organization.ntargets);
> +
> +
> +	return 0;
> +}
> +
> +/* ---------------------------- BCB handling part -------------------------- */
> +
> +static uint32_t calc_chksum(void *buf, size_t size)
> +{
> +	u32 chksum = 0;
> +	u8 *bp = buf;
> +	size_t i;
> +
> +	for (i = 0; i < size; i++)
> +		chksum += bp[i];
> +
> +	return ~chksum;
> +}
> +
> +static int get_fcb(struct mxs_nand_info *info, void *databuf)
> +{
> +	int i, pagenum, ret;
> +	uint32_t checksum;
> +	struct fcb_block *fcb = &info->fcb;
> +
> +	/* First page read fails, this shouldn't be necessary */
> +	mxs_nand_read_page(info, info->organization.pagesize,
> +		info->organization.oobsize, 0, databuf, 1);
> +
> +	for (i = 0; i < 4; i++) {
> +		pagenum = 64 * i;

I haven't looked at the documentation, but the '64' should probably be pages
per block, so better info->organization.pages_per_eraseblock?

> +
> +		ret = mxs_nand_read_page(info, info->organization.pagesize,
> +			info->organization.oobsize, pagenum, databuf, 1);
> +		if (ret)
> +			continue;
> +
> +		memcpy(fcb, databuf + mxs_nand_aux_status_offset(),
> +			sizeof(*fcb));
> +
> +		if (fcb->FingerPrint != FCB_FINGERPRINT) {
> +			pr_err("No FCB found on page %d\n", pagenum);
> +			continue;
> +		}
> +
> +		checksum = calc_chksum((void *)fcb +
> +			sizeof(uint32_t), sizeof(*fcb) - sizeof(uint32_t));
> +
> +		if (checksum != fcb->Checksum) {
> +			pr_err("FCB on page %d has invalid checksum. " \
> +				"Expected: 0x%08x, calculated: 0x%08x",
> +				pagenum, fcb->Checksum, checksum);
> +			continue;
> +		}
> +
> +		pr_debug("Found FCB:\n");
> +		pr_debug("PageDataSize:     0x%08x\n", fcb->PageDataSize);
> +		pr_debug("TotalPageSize:    0x%08x\n", fcb->TotalPageSize);
> +		pr_debug("SectorsPerBlock:  0x%08x\n", fcb->SectorsPerBlock);
> +		pr_debug("FW1_startingPage: 0x%08x\n",
> +			fcb->Firmware1_startingPage);
> +		pr_debug("PagesInFW1:       0x%08x\n", fcb->PagesInFirmware1);
> +		pr_debug("FW2_startingPage: 0x%08x\n",
> +			fcb->Firmware2_startingPage);
> +		pr_debug("PagesInFW2:       0x%08x\n", fcb->PagesInFirmware2);
> +
> +		return 0;
> +	}
> +
> +	return -EINVAL;
> +}
> +
> +static int get_dbbt(struct mxs_nand_info *info, void *databuf)
> +{
> +	int i, ret;
> +	int page;
> +	int startpage = info->fcb.DBBTSearchAreaStartAddress;
> +	struct dbbt_block dbbt;
> +
> +	for (i = 0; i < 4; i++) {
> +		page = startpage + i * 64;

Same here.

Regards,
 Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Thu Jan 21 04:11:29 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 21 Jan 2021 10:11:29 +0100
Subject: [PATCH 3/3] ARM: i.MX: xload-gpmi-nand: apply errata 007117
In-Reply-To: <20210120125107.736121-4-andrej.picej@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-4-andrej.picej@norik.com>
Message-ID: <20210121091128.GG19063@pengutronix.de>

On Wed, Jan 20, 2021 at 01:51:07PM +0100, Andrej Picej wrote:
> During raw NAND booting, GPMI/BCH clock generation might fail due to
> improper clock gating conditions and consequently booting from NAND will
> fail. This is caused by silicon errata ERR007117. Apply errata fix
> workaround before GPMI NAND xload to prevent this from occurring.
> 
> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
> ---
>  arch/arm/mach-imx/xload-gpmi-nand.c | 62 +++++++++++++++++++++++++++++
>  1 file changed, 62 insertions(+)
> 
> diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
> index 04f799604..4be6d1890 100644
> --- a/arch/arm/mach-imx/xload-gpmi-nand.c
> +++ b/arch/arm/mach-imx/xload-gpmi-nand.c
> @@ -20,6 +20,8 @@
>  #include <mach/xload.h>
>  #include <mach/imx-nand-bcb.h>
>  #include <linux/mtd/rawnand.h>
> +#include <mach/imx6-regs.h>
> +#include <mach/clock-imx6.h>
>  
>  /*
>   * MXS DMA hardware command.
> @@ -256,6 +258,63 @@ struct mxs_nand_info {
>  	unsigned long nand_size;
>  };
>  
> +/**
> + * It was discovered that xloading barebox from NAND sometimes fails. Observed
> + * behaviour is similar to silicon errata ERR007117 for i.MX6.

Have you really seen this behaviour? I wonder because the ROM has
already loaded the initial code that is just running from NAND, so it
surprises me that we still have to apply clock fixes.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Thu Jan 21 05:04:08 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 21 Jan 2021 11:04:08 +0100
Subject: [RFC PATCH] ARM: phytec-som-imx6: phycard DRAM autodetection
In-Reply-To: <20210120125203.736421-1-andrej.picej@norik.com>
References: <20210120125203.736421-1-andrej.picej@norik.com>
Message-ID: <20210121100408.GJ19063@pengutronix.de>

+Cc some Phytec guys

On Wed, Jan 20, 2021 at 01:52:03PM +0100, Andrej Picej wrote:
> Add support for automatic DRAM size detection on phytec phycard imx6q
> machines. Currently supported SoM variants are 1 GiB (1 bank) and 2 GiB
> variant. Machines now boot from internal SRAM (see DCD table loadaddr
> 0x00907000) and then do DRAM size detection and configuration in plain
> C code (instead of hardcoded DCD table values). After initializing DRAM,
> remaining barebox image is xloaded from GPMI NAND to DRAM and started
> from there.
> 
> Booting process / strategy on phycard machines:
>  1) lowlevel in SRAM (PBL)
>   1.1) detect DRAM size
>   1.2) configure DRAM accordingly
>   1.3) copy remaining barebox image from NAND to DRAM (addr 0x10000000)
>   1.4) jump to DRAM (addr 0x10000000)
>  2) lowlevel in DRAM (PBL)
>   2.1) skip DRAM detection since already running from DRAM
>   2.2) main barebox entry
>  3) board code
>  4) ...
> 
> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
> ---
>  .../flash-header-phytec-pcaaxl3.imxcfg        |   4 +
>  arch/arm/boards/phytec-som-imx6/lowlevel.c    | 255 ++++++++++++++++++
>  images/Makefile.imx                           |   2 +
>  3 files changed, 261 insertions(+)
>  create mode 100644 arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3.imxcfg
> 
> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3.imxcfg
> new file mode 100644
> index 000000000..fcfef9c23
> --- /dev/null
> +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3.imxcfg
> @@ -0,0 +1,4 @@
> +soc imx6
> +loadaddr 0x00907000
> +max_load_size 0x31000
> +ivtofs 0x400
> diff --git a/arch/arm/boards/phytec-som-imx6/lowlevel.c b/arch/arm/boards/phytec-som-imx6/lowlevel.c
> index 62a1c8de7..7bc9d123a 100644
> --- a/arch/arm/boards/phytec-som-imx6/lowlevel.c
> +++ b/arch/arm/boards/phytec-som-imx6/lowlevel.c
> @@ -16,6 +16,261 @@
>  #include <asm/cache.h>
>  #include <asm/mmu.h>
>  #include <mach/imx6.h>
> +#include <mach/imx6-mmdc.h>
> +#include <mach/esdctl.h>
> +#include <mach/xload.h>
> +
> +/* udelay() is not available in PBL, need to improvise */
> +static void __udelay(int us)
> +{
> +	volatile int i;
> +
> +	for (i = 0; i < us * 4; i++);
> +}
> +
> +#define	IMX6Q_UART2			2
> +#define	IMX6Q_UART3			3
> +#define	DRIVE_STRENGTH_40_OHM		0x30
> +#define	DRIVE_STRENGTH_48_OHM		0x28
> +
> +/* mmdc DDR io registers */
> +static struct mx6dq_iomux_ddr_regs mx6dq_ddr_ioregs = {
> +	.dram_sdclk_0 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdclk_1 = DRIVE_STRENGTH_40_OHM,
> +	.dram_cas = DRIVE_STRENGTH_40_OHM,
> +	.dram_ras = DRIVE_STRENGTH_40_OHM,
> +	.dram_reset = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdcke0 = 0x00003000,
> +	.dram_sdcke1 = 0x00003000,
> +	.dram_sdba2 = 0x00000000,
> +	.dram_sdodt0 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdodt1 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdqs0 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdqs1 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdqs2 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdqs3 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdqs4 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdqs5 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdqs6 = DRIVE_STRENGTH_40_OHM,
> +	.dram_sdqs7 = DRIVE_STRENGTH_40_OHM,
> +	.dram_dqm0 = DRIVE_STRENGTH_40_OHM,
> +	.dram_dqm1 = DRIVE_STRENGTH_40_OHM,
> +	.dram_dqm2 = DRIVE_STRENGTH_40_OHM,
> +	.dram_dqm3 = DRIVE_STRENGTH_40_OHM,
> +	.dram_dqm4 = DRIVE_STRENGTH_40_OHM,
> +	.dram_dqm5 = DRIVE_STRENGTH_40_OHM,
> +	.dram_dqm6 = DRIVE_STRENGTH_40_OHM,
> +	.dram_dqm7 = DRIVE_STRENGTH_40_OHM,
> +};
> +
> +static struct mx6_mmdc_calibration mx6q_mmdc_calib = {
> +	.p0_mpwldectrl0 = 0x0013001b,
> +	.p0_mpwldectrl1 = 0x003b0034,
> +	.p1_mpwldectrl0 = 0x0037004b,
> +	.p1_mpwldectrl1 = 0x004b0055,
> +	.p0_mpdgctrl0 = 0x4350035e,
> +	.p0_mpdgctrl1 = 0x035c0358,
> +	.p1_mpdgctrl0 = 0x436e0376,
> +	.p1_mpdgctrl1 = 0x03770352,
> +	.p0_mprddlctl = 0x3c333436,
> +	.p1_mprddlctl = 0x35332f3b,
> +	.p0_mpwrdlctl = 0x37363e39,
> +	.p1_mpwrdlctl = 0x432f433d,
> +};
> +
> +/* MT41K128M16JT-125 IT */
> +static struct mx6_ddr3_cfg mt41k128m16jt = {
> +	.mem_speed = 1600,
> +	.density = 2,
> +	.width = 16,
> +	.banks = 8,
> +	.rowaddr = 14,
> +	.coladdr = 10,
> +	.pagesz = 2,
> +	.trcd = 1375,
> +	.trcmin = 4875,
> +	.trasmin = 3500,
> +};
> +
> +/* DDR 64bit 1GB */
> +static struct mx6_ddr_sysinfo mem1g_q = {
> +	.dsize		= 2,
> +	.cs1_mirror	= 1,
> +	.cs_density	= 8,
> +	.ncs		= 1,
> +	.bi_on		= 1,
> +	.rtt_nom	= 1,
> +	.rtt_wr		= 0,
> +	.ralat		= 5,
> +	.walat		= 1,
> +	.mif3_mode	= 3,
> +	.rst_to_cke	= 0x23,
> +	.sde_to_rst	= 0x10,
> +};
> +
> +/* DDR 64bit 2GB */
> +static struct mx6_ddr_sysinfo mem2g_q = {
> +	.dsize		= 2,
> +	.cs1_mirror	= 1,
> +	.cs_density	= 8,
> +	.ncs		= 2,
> +	.bi_on		= 1,
> +	.rtt_nom	= 1,
> +	.rtt_wr		= 0,
> +	.ralat		= 5,
> +	.walat		= 1,
> +	.mif3_mode	= 3,
> +	.rst_to_cke	= 0x23,
> +	.sde_to_rst	= 0x10,
> +};
> +
> +/* mmdc GRP io registers */
> +static struct mx6dq_iomux_grp_regs mx6dq_grp_ioregs = {
> +	.grp_ddr_type = 0x000c0000,
> +	.grp_ddrmode_ctl = 0x00020000,
> +	.grp_ddrpke = 0x00000000,
> +	.grp_addds = DRIVE_STRENGTH_40_OHM,
> +	.grp_ctlds = DRIVE_STRENGTH_40_OHM,
> +	.grp_ddrmode = 0x00020000,
> +	.grp_b0ds = DRIVE_STRENGTH_40_OHM,
> +	.grp_b1ds = DRIVE_STRENGTH_40_OHM,
> +	.grp_b2ds = DRIVE_STRENGTH_40_OHM,
> +	.grp_b3ds = DRIVE_STRENGTH_40_OHM,
> +	.grp_b4ds = DRIVE_STRENGTH_40_OHM,
> +	.grp_b5ds = DRIVE_STRENGTH_40_OHM,
> +	.grp_b6ds = DRIVE_STRENGTH_40_OHM,
> +	.grp_b7ds = DRIVE_STRENGTH_40_OHM,
> +};
> +
> +static inline void setup_uart_phycard_imx6q(int UARTn)
> +{
> +	void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
> +
> +	switch (UARTn) {
> +	case IMX6Q_UART2:
> +		/* Setup UART2 pin muxing */
> +		writel(0x4, iomuxbase + 0xc0);
> +		writel(0x4, iomuxbase + 0xbc);
> +		writel(0x1, iomuxbase + 0x928);
> +
> +		imx6_ungate_all_peripherals();
> +		imx6_uart_setup((void *)MX6_UART2_BASE_ADDR);
> +		pbl_set_putc(imx_uart_putc, (void *)MX6_UART2_BASE_ADDR);
> +		break;
> +	case IMX6Q_UART3:
> +		/* Setup UART3 pin muxing */
> +		writel(0x2, iomuxbase + 0xb4);
> +		writel(0x2, iomuxbase + 0xb8);
> +		writel(0x1, iomuxbase + 0x930);
> +
> +		imx6_ungate_all_peripherals();
> +		imx6_uart_setup((void *)MX6_UART3_BASE_ADDR);
> +		pbl_set_putc(imx_uart_putc, (void *)MX6_UART3_BASE_ADDR);
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	putc_ll('>');
> +}
> +
> +#define DRAM_CONFIG_DELAY	5000
> +#define DRAM_CALIB_DELAY	50000
> +
> +static unsigned long phycard_imx6q_ll_autodetect_dram_init(void)
> +{
> +	unsigned long memsize = SZ_2G;
> +	unsigned long dram_size = 0;
> +
> +	pr_debug("DRAM init & size detection\n");
> +
> +	/* First try with 2 GiB DRAM configuration */
> +	mx6dq_dram_iocfg(64, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
> +	mx6_dram_cfg(&mem2g_q, &mx6q_mmdc_calib, &mt41k128m16jt);
> +	__udelay(DRAM_CONFIG_DELAY);
> +
> +	mmdc_do_write_level_calibration();
> +	mmdc_do_dqs_calibration();
> +	__udelay(DRAM_CALIB_DELAY);
> +
> +	pr_debug("DRAM probe with 2 GiB config\n");
> +
> +	dram_size = get_ram_size((volatile long *)0x10000000, (long)memsize);
> +	pr_debug("DRAM detected size: 0x%lx\n", dram_size);
> +
> +	if (dram_size != SZ_2G) {
> +		/* Next try with 1 GiB DRAM configuration */
> +		memsize = SZ_1G;
> +
> +		mx6dq_dram_iocfg(64, &mx6dq_ddr_ioregs, &mx6dq_grp_ioregs);
> +		mx6_dram_cfg(&mem1g_q, &mx6q_mmdc_calib, &mt41k128m16jt);
> +		__udelay(DRAM_CONFIG_DELAY);
> +
> +		mmdc_do_write_level_calibration();
> +		mmdc_do_dqs_calibration();
> +		__udelay(DRAM_CALIB_DELAY);
> +
> +		pr_debug("DRAM probe with 1 GiB config\n");
> +	} else {
> +		pr_debug("DRAM size 0x%lx already detected, " \
> +			"skipping DRAM re-configuration\n", dram_size);
> +	}
> +
> +	dram_size = get_ram_size((volatile long *)0x10000000, (long)memsize);
> +	pr_debug("DRAM final detected size: 0x%lx\n", dram_size);
> +
> +#ifdef DEBUG
> +	pr_debug("DRAM calibration results:\n");
> +	mmdc_print_calibration_results();
> +#endif
> +	return memsize;
> +}
> +
> +static void phycard_imx6q_ll_autodetect_init(void)
> +{
> +	if (IS_ENABLED(CONFIG_DEBUG_LL))
> +		setup_uart_phycard_imx6q(IMX6Q_UART3);
> +
> +	/* Already running from DRAM? */
> +	if (get_pc() > 0x10000000) {
> +		pr_debug("DRAM already initialized, skipping...\n");
> +		return;
> +	}
> +
> +	/* Running from SRAM, need to configure DRAM */
> +	phycard_imx6q_ll_autodetect_dram_init();
> +
> +	/* Now xload remaining part of barebox image from NAND */
> +	pr_debug("xloading barebox image from NAND\n");
> +	imx6_nand_start_image();

You should detect where we are booting from and load the rest from the
same device. Speaking of which, we should finally add some
imx6_xload_start_image() function which does that generically for i.MX6.

> +
> +	pr_err("Booting failed!\n");
> +	hang();
> +}
> +
> +extern char __dtb_imx6q_phytec_phycard_start[];
> +
> +static noinline void phycard_imx6q_ll_autodetect_start(void)
> +{
> +	void *fdt = __dtb_imx6q_phytec_phycard_start + get_runtime_offset();
> +
> +	phycard_imx6q_ll_autodetect_init();
> +
> +	imx6q_barebox_entry(fdt);
> +}
> +
> +ENTRY_FUNCTION(start_phycard_imx6q_ll_autodetect, r0, r1, r2)
> +{
> +	imx6_cpu_lowlevel_init();
> +
> +	arm_setup_stack(0x00940000);
> +
> +	relocate_to_current_adr();
> +	setup_c();
> +	barrier();
> +
> +	phycard_imx6q_ll_autodetect_start();
> +}
>  
>  static inline void setup_uart(void)
>  {
> diff --git a/images/Makefile.imx b/images/Makefile.imx
> index 514db326b..80d2fd805 100644
> --- a/images/Makefile.imx
> +++ b/images/Makefile.imx
> @@ -205,6 +205,8 @@ $(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phyboard_su
>  
>  $(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phyboard_subra_1gib_1bank, phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank, phytec-phyboard-subra-1gib-1bank)
>  
> +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phycard_imx6q_ll_autodetect, phytec-som-imx6/flash-header-phytec-pcaaxl3, phytec-phycard-imx6q-som-nand)
> +
>  $(call build_imx_habv4img, CONFIG_MACH_DFI_FS700_M60, start_imx6dl_dfi_fs700_m60_6s, dfi-fs700-m60/flash-header-fs700-m60-6s, dfi-fs700-m60-6s)
>  
>  $(call build_imx_habv4img, CONFIG_MACH_DFI_FS700_M60, start_imx6q_dfi_fs700_m60_6q_micron, dfi-fs700-m60/flash-header-fs700-m60-6q-micron, dfi-fs700-m60-6q-micron)
> -- 
> 2.25.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From andrej.picej at norik.com  Thu Jan 21 05:28:39 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Thu, 21 Jan 2021 11:28:39 +0100
Subject: [PATCH 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <20210121090148.GF19063@pengutronix.de>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-3-andrej.picej@norik.com>
 <20210121090148.GF19063@pengutronix.de>
Message-ID: <7df4659e-7237-c5fa-767f-7dedd5c44005@norik.com>

Hi Sascha,

thanks for your comments.

Responses inline.

On 21. 01. 21 10:01, Sascha Hauer wrote:
> Hi Andrej,
> 
> Some comments inline.
> 
> On Wed, Jan 20, 2021 at 01:51:06PM +0100, Andrej Picej wrote:
>> From: Sascha Hauer <s.hauer at pengutronix.de>
>>
>> Commit is based on initial Sascha Hauer's work. It implements PBL xload
>> mechanism to load image from GPMI NAND flash.
>>
>> Additional work was done, so that the NAND's size, page size and OOB's
>> size are autodetected and not hardcoded. Detection method follows the
>> same methods as used in NAND driver, meaning NAND ONFI support is probed
>> and if NAND supports ONFI, NAND memory organization is read from ONFI
>> parameter page otherwise "READ ID" is used.
>>
>> Currently only implemented for i.MX6 familly of SoCs.
>>
>> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
>> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
>> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
>> ---
>>   arch/arm/mach-imx/Makefile             |    2 +-
>>   arch/arm/mach-imx/include/mach/xload.h |    1 +
>>   arch/arm/mach-imx/xload-gpmi-nand.c    | 1163 ++++++++++++++++++++++++
>>   3 files changed, 1165 insertions(+), 1 deletion(-)
>>   create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c
>>
>> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
>> index e45f758e9..d94c846a1 100644
>> --- a/arch/arm/mach-imx/Makefile
>> +++ b/arch/arm/mach-imx/Makefile
>> +static int mxs_nand_get_info(struct mxs_nand_info *info, void *databuf)
>> +{
>> +	int ret, i;
>> +
>> +	ret = mxs_nand_check_onfi(info, databuf);
>> +	if (ret) {
>> +		if (ret != 1)
>> +			return ret;
>> +		pr_warn("ONFI not supported, try \"READ ID\"...\n");
> 
> You already printed a "ONFI not supported\n" message. Printing it once
> is enough. Also this message appears with every non-ONFI nand, right? In
> that case it should rather be pr_info()

OK, I agree, will fix it in v2.

> 
>> +	/*
>> +	 * If ONFI is not supported or if it fails try to get NAND's info from
>> +	 * "READ ID" command.
>> +	 */
>> +	pr_debug("Trying \"READ ID\" command...\n");
>> +	ret = mxs_nand_get_readid(info, databuf);
>> +	if (ret) {
>> +		if (ret != -EOVERFLOW)
>> +			return ret;
>> +
>> +		/*
>> +		 * If NAND's "READ ID" returns bad values, try to set them to
>> +		 * default (most common NAND memory org.) and continue.
>> +		 */
>> +		pr_warn("NANDs READ ID command returned bad values" \
>> +			" set them to default and try to continue!\n");
>> +		info->organization.pagesize = 2048;
>> +		info->organization.oobsize = 64;
>> +		info->nand_size = SZ_1G;
> 
> Is this worth it? READ ID is the most basic command, when this doesn't
> work I don't think there's a point in continuing.

We had a case with Samsung K9K8G08U0E when sometimes (reasons not known) 
the 5th byte returned 0xff instead of correct values, all other returned 
values were correct. In this case the device booted successfully because 
of this hook. Maybe a better solution would be to check only the 5th 
byte for 0xff value (5th byte is not supported from all NAND vendors), 
if this is the case set the NAND size to 1GB.
Would that make more sense?

> 
>> +	}
>> +succ:
>> +	pr_debug("NAND page_size: %d\n", info->organization.pagesize);
>> +	pr_debug("NAND block_size: %d\n",
>> +		info->organization.pages_per_eraseblock
>> +		* info->organization.pagesize);
>> +	pr_debug("NAND oob_size: %d\n", info->organization.oobsize);
>> +	pr_debug("NAND nand_size: %lu\n", info->nand_size);
>> +	pr_debug("NAND bits_per_cell: %d\n", info->organization.bits_per_cell);
>> +	pr_debug("NAND planes_per_lun: %d\n",
>> +		info->organization.planes_per_lun);
>> +	pr_debug("NAND luns_per_target: %d\n",
>> +		info->organization.luns_per_target);
>> +	pr_debug("NAND eraseblocks_per_lun: %d\n",
>> +		info->organization.eraseblocks_per_lun);
>> +	pr_debug("NAND ntargets: %d\n", info->organization.ntargets);
>> +
>> +
>> +	return 0;
>> +}
>> +
>> +/* ---------------------------- BCB handling part -------------------------- */
>> +
>> +static uint32_t calc_chksum(void *buf, size_t size)
>> +{
>> +	u32 chksum = 0;
>> +	u8 *bp = buf;
>> +	size_t i;
>> +
>> +	for (i = 0; i < size; i++)
>> +		chksum += bp[i];
>> +
>> +	return ~chksum;
>> +}
>> +
>> +static int get_fcb(struct mxs_nand_info *info, void *databuf)
>> +{
>> +	int i, pagenum, ret;
>> +	uint32_t checksum;
>> +	struct fcb_block *fcb = &info->fcb;
>> +
>> +	/* First page read fails, this shouldn't be necessary */
>> +	mxs_nand_read_page(info, info->organization.pagesize,
>> +		info->organization.oobsize, 0, databuf, 1);
>> +
>> +	for (i = 0; i < 4; i++) {
>> +		pagenum = 64 * i;
> 
> I haven't looked at the documentation, but the '64' should probably be pages
> per block, so better info->organization.pages_per_eraseblock.
Yes, I agree, will fix it in v2.

> 
>> +
>> +		ret = mxs_nand_read_page(info, info->organization.pagesize,
>> +			info->organization.oobsize, pagenum, databuf, 1);
>> +		if (ret)
>> +			continue;
>> +
>> +		memcpy(fcb, databuf + mxs_nand_aux_status_offset(),
>> +			sizeof(*fcb));
>> +
>> +		if (fcb->FingerPrint != FCB_FINGERPRINT) {
>> +			pr_err("No FCB found on page %d\n", pagenum);
>> +			continue;
>> +		}
>> +
>> +		checksum = calc_chksum((void *)fcb +
>> +			sizeof(uint32_t), sizeof(*fcb) - sizeof(uint32_t));
>> +
>> +		if (checksum != fcb->Checksum) {
>> +			pr_err("FCB on page %d has invalid checksum. " \
>> +				"Expected: 0x%08x, calculated: 0x%08x",
>> +				pagenum, fcb->Checksum, checksum);
>> +			continue;
>> +		}
>> +
>> +		pr_debug("Found FCB:\n");
>> +		pr_debug("PageDataSize:     0x%08x\n", fcb->PageDataSize);
>> +		pr_debug("TotalPageSize:    0x%08x\n", fcb->TotalPageSize);
>> +		pr_debug("SectorsPerBlock:  0x%08x\n", fcb->SectorsPerBlock);
>> +		pr_debug("FW1_startingPage: 0x%08x\n",
>> +			fcb->Firmware1_startingPage);
>> +		pr_debug("PagesInFW1:       0x%08x\n", fcb->PagesInFirmware1);
>> +		pr_debug("FW2_startingPage: 0x%08x\n",
>> +			fcb->Firmware2_startingPage);
>> +		pr_debug("PagesInFW2:       0x%08x\n", fcb->PagesInFirmware2);
>> +
>> +		return 0;
>> +	}
>> +
>> +	return -EINVAL;
>> +}
>> +
>> +static int get_dbbt(struct mxs_nand_info *info, void *databuf)
>> +{
>> +	int i, ret;
>> +	int page;
>> +	int startpage = info->fcb.DBBTSearchAreaStartAddress;
>> +	struct dbbt_block dbbt;
>> +
>> +	for (i = 0; i < 4; i++) {
>> +		page = startpage + i * 64;
> 
> Same here.

Again, will fix it in v2.

> 
> Regards,
>   Sascha
> 

Thank you for your comments and review.

Best regards,
Andrej Picej


From str at pengutronix.de  Thu Jan 21 06:29:48 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:48 +0100
Subject: [PATCH 03/13] firmware: socfpga: set APPLYCFG after loading bitstream
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-3-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

To make changes to the SDRAM controller effective, the APPLYCFG bit must
be set after programming the bitstream to the FPGA. This has to be done
without any SDRAM usage. Therefore copy the function to execute to the
OCRAM and execute it from there.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 .../mach-socfpga/include/mach/cyclone5-regs.h |  1 +
 drivers/firmware/Makefile                     |  2 +-
 drivers/firmware/socfpga.c                    | 21 +++++++++++++++++++
 drivers/firmware/socfpga_sdr.S                | 17 +++++++++++++++
 4 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/socfpga_sdr.S

diff --git a/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h b/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h
index e88daf7189..1a7d787a27 100644
--- a/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h
+++ b/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h
@@ -18,5 +18,6 @@
 #define CYCLONE5_SYSMGR_ADDRESS		0xffd08000
 #define CYCLONE5_SCANMGR_ADDRESS	0xfff02000
 #define CYCLONE5_SMP_TWD_ADDRESS	0xfffec600
+#define CYCLONE5_OCRAM_ADDRESS		0xffff0000
 
 #endif /* __MACH_SOCFPGA_REGS_H */
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index b162b08b0a..bbd2bcda97 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_FIRMWARE_ALTERA_SERIAL) += altera_serial.o
-obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o
+obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o socfpga_sdr.o
 obj-$(CONFIG_FIRMWARE_ZYNQMP_FPGA) += zynqmp-fpga.o
diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 393c78c45d..c468c74372 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -38,6 +38,9 @@
 #include <mach/cyclone5-reset-manager.h>
 #include <mach/cyclone5-regs.h>
 #include <mach/cyclone5-sdram.h>
+#include <asm/fncpy.h>
+#include <mmu.h>
+#include <asm/cache.h>
 
 #define FPGAMGRREGS_STAT			0x0
 #define FPGAMGRREGS_CTRL			0x4
@@ -77,6 +80,9 @@
 #define CDRATIO_x4	0x2
 #define CDRATIO_x8	0x3
 
+extern void socfpga_sdram_apply_static_cfg(void __iomem *sdrctrlgrp);
+extern void socfpga_sdram_apply_static_cfg_end(void *);
+
 struct fpgamgr {
 	struct firmware_handler fh;
 	struct device_d dev;
@@ -353,6 +359,9 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
 	int status;
+	unsigned int func_size = &socfpga_sdram_apply_static_cfg_end -
+				 &socfpga_sdram_apply_static_cfg;
+	void (*ocram_func)(void __iomem *ocram_base);
 
 	/* Ensure the FPGA entering config done */
 	status = fpgamgr_program_poll_cd(mgr);
@@ -382,6 +391,18 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 		return status;
 	}
 
+	remap_range((void *)CYCLONE5_OCRAM_ADDRESS, PAGE_SIZE, MAP_CACHED);
+
+	dev_dbg(&mgr->dev, "Setting APPLYCFG bit...\n");
+
+	ocram_func = fncpy((void __iomem *)CYCLONE5_OCRAM_ADDRESS,
+			   &socfpga_sdram_apply_static_cfg, func_size);
+
+	sync_caches_for_execution();
+
+	ocram_func((void __iomem *) (CYCLONE5_SDR_ADDRESS +
+				     SDR_CTRLGRP_STATICCFG_ADDRESS));
+
 	return 0;
 }
 
diff --git a/drivers/firmware/socfpga_sdr.S b/drivers/firmware/socfpga_sdr.S
new file mode 100644
index 0000000000..d634d63627
--- /dev/null
+++ b/drivers/firmware/socfpga_sdr.S
@@ -0,0 +1,17 @@
+#include <linux/linkage.h>
+
+	.arch	armv7-a
+	.arm
+
+/*
+ * r0 : sdram controller staticcfg
+ */
+
+ENTRY(socfpga_sdram_apply_static_cfg)
+	push {ip,lr}
+	ldr r1, [r0]
+	orr r1, r1, #8
+	str r1, [r0]
+	pop {ip,pc}
+	.align
+ENTRY(socfpga_sdram_apply_static_cfg_end)
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:47 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:47 +0100
Subject: [PATCH 02/13] ARM: mmu: inherit pte flags from pmd
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-2-str@pengutronix.de>

From: Sascha Hauer <s.hauer at pengutronix.de>

When creating a 2nd level page table from a section inherit the flags
from the section rather than assuming the section was mapped cached
previously. This fixes creating a 2nd level pagetable when the section
was mapped differently than we expected.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/cpu/mmu.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index 6af228505d..6388e1bf14 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -138,6 +138,29 @@ static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
 	return table;
 }
 
+static u32 pmd_flags_to_pte(u32 pmd)
+{
+	u32 pte = 0;
+
+	if (pmd & PMD_SECT_BUFFERABLE)
+		pte |= PTE_BUFFERABLE;
+	if (pmd & PMD_SECT_CACHEABLE)
+		pte |= PTE_CACHEABLE;
+	if (pmd & PMD_SECT_nG)
+		pte |= PTE_EXT_NG;
+	if (pmd & PMD_SECT_XN)
+		pte |= PTE_EXT_XN;
+
+	/* TEX[2:0] */
+	pte |= PTE_EXT_TEX((pmd >> 12) & 7);
+	/* AP[1:0] */
+	pte |= ((pmd >> 10) & 0x3) << 4;
+	/* AP[2] */
+	pte |= ((pmd >> 15) & 0x1) << 9;
+
+	return pte;
+}
+
 int arch_remap_range(void *start, size_t size, unsigned flags)
 {
 	u32 addr = (u32)start;
@@ -206,11 +229,8 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
 				 * If PTE is not found it means that
 				 * we needs to split this section and
 				 * create a new page table for it
-				 *
-				 * NOTE: Here we assume that section
-				 * we just split was mapped as cached
 				 */
-				table = arm_create_pte(addr, pte_flags_cached);
+				table = arm_create_pte(addr, pmd_flags_to_pte(*pgd));
 				pte = find_pte(addr);
 				BUG_ON(!pte);
 			}
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:58 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:58 +0100
Subject: [PATCH 13/13] firmware: add support for compressed images
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-13-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

At least bitstreams for FPGAs can consist of a lot of zeros depending on
device utilization. These bitstreams can be compressed very effectively.

Let the firmware code accept these images and decompress them before
handing it to the firmware-manager in question.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 common/firmware.c | 43 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 5 deletions(-)

diff --git a/common/firmware.c b/common/firmware.c
index 58509d5da6..c617ecc0f1 100644
--- a/common/firmware.c
+++ b/common/firmware.c
@@ -14,6 +14,8 @@
 #include <linux/list.h>
 #include <linux/stat.h>
 #include <linux/err.h>
+#include <uncompress.h>
+#include <filetype.h>
 
 #define BUFSIZ 4096
 
@@ -211,12 +213,43 @@ out:
  */
 int firmwaremgr_load_file(struct firmware_mgr *mgr, const char *firmware)
 {
-	int ret;
-	char *name = basprintf("/dev/%s", mgr->handler->id);
-
-	ret = copy_file(firmware, name, 0);
+	char *dst;
+	enum filetype type;
+	int ret = -ENOENT;
+	int srcfd = 0;
+	int dstfd = 0;
+
+	if (mgr->handler->id) {
+		dst = basprintf("/dev/%s", mgr->handler->id);
+	} else {
+		pr_err("id not defined for handler\n");
+		return -ENODEV;
+	}
 
-	free(name);
+	if (firmware) {
+		type = file_name_detect_type(firmware);
+		if (type == filetype_unknown) {
+			ret = copy_file(firmware, dst, 0);
+		} else {
+			srcfd = open(firmware, O_RDONLY);
+			if (srcfd < 0)
+				return srcfd;
+			dstfd = open(dst, O_WRONLY | O_CREAT);
+
+			if (dstfd < 0) {
+				printf("could not open %s: %s\n", dst, errno_str());
+				ret = dstfd;
+				goto out;
+			}
+
+			ret = uncompress_fd_to_fd(srcfd, dstfd, uncompress_err_stdout);
+
+			close(dstfd);
+		}
+	}
+out:
+	close(srcfd);
+	free(dst);
 
 	return ret;
 }
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:54 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:54 +0100
Subject: [PATCH 09/13] of: kconfig: of_overlay uses firmwaremgr_load_file
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-9-str@pengutronix.de>

As of_firmware.c uses the firmwaremgr_load_file function, it depends on
FIRMWARE.

Signed-off-by: Steffen Trumtrar <str at pengutronix.de>
---
 drivers/of/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 23be25d85d..e58fe50f70 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -49,6 +49,7 @@ config OF_BAREBOX_ENV_IN_FS
 
 config OF_OVERLAY
 	select OFTREE
+	select FIRMWARE
 	bool "Devicetree overlays"
 	help
 	  Overlays allow to patch the devicetree. Unlike Linux, Barebox does
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:57 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:57 +0100
Subject: [PATCH 12/13] drivers: firmware: socfpga: remove bridges shutdown
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-12-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

The bridges are now handled via the bridges driver. There is no
need to hardcode the memory writes anymore.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/firmware/socfpga.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 605c931604..eb3fc557c7 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -294,15 +294,6 @@ static int socfpga_fpgamgr_program_start(struct firmware_handler *fh)
 	/* disable all signals from hps peripheral controller to fpga */
 	writel(0, SYSMGR_FPGAINTF_MODULE);
 
-	/* disable all signals from fpga to hps sdram */
-	writel(0, (CYCLONE5_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS));
-
-	/* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
-	writel(~0, CYCLONE5_RSTMGR_ADDRESS + RESET_MGR_BRG_MOD_RESET_OFS);
-
-	/* unmap the bridges from NIC-301 */
-	writel(0x1, CYCLONE5_L3REGS_ADDRESS);
-
 	dev_dbg(&mgr->dev, "start programming...\n");
 
 	/* initialize the FPGA Manager */
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:46 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:46 +0100
Subject: [PATCH 01/13] ARM: add fncpy.h from linux v4.6
Message-ID: <20210121112958.25937-1-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

Description from the linux commit 5756e9dd0de6d5c307773f8f734c0684b3098fdd:

    ARM: 6640/1: Thumb-2: Symbol manipulation macros for function body copying

    In low-level board support code, there is sometimes a need to
    copy a function body to another location at run-time.

    A straightforward call to memcpy doesn't work in Thumb-2,
    because bit 0 of external Thumb function symbols is set to 1,
    indicating that the function is Thumb.  Without corrective
    measures, this will cause an off-by-one copy, and the copy
    may be called using the wrong instruction set.

    This patch adds an fncpy() macro to help with such copies.

    Particular care is needed, because C doesn't guarantee any
    defined behaviour when casting a function pointer to any other
    type.  This has been observed to lead to strange optimisation
    side-effects when doing the arithmetic which is required in
    order to copy/move function bodies correctly in Thumb-2.

    Thanks to Russell King and Nicolas Pitre for their input
    on this patch.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 arch/arm/include/asm/fncpy.h | 82 ++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)
 create mode 100644 arch/arm/include/asm/fncpy.h

diff --git a/arch/arm/include/asm/fncpy.h b/arch/arm/include/asm/fncpy.h
new file mode 100644
index 0000000000..d13876bffa
--- /dev/null
+++ b/arch/arm/include/asm/fncpy.h
@@ -0,0 +1,82 @@
+/*
+ * arch/arm/include/asm/fncpy.h - helper macros for function body copying
+ *
+ * Copyright (C) 2011 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * These macros are intended for use when there is a need to copy a low-level
+ * function body into special memory.
+ *
+ * For example, when reconfiguring the SDRAM controller, the code doing the
+ * reconfiguration may need to run from SRAM.
+ *
+ * NOTE: that the copied function body must be entirely self-contained and
+ * position-independent in order for this to work properly.
+ *
+ * NOTE: in order for embedded literals and data to get referenced correctly,
+ * the alignment of functions must be preserved when copying.  To ensure this,
+ * the source and destination addresses for fncpy() must be aligned to a
+ * multiple of 8 bytes: you will be get a BUG() if this condition is not met.
+ * You will typically need a ".align 3" directive in the assembler where the
+ * function to be copied is defined, and ensure that your allocator for the
+ * destination buffer returns 8-byte-aligned pointers.
+ *
+ * Typical usage example:
+ *
+ * extern int f(args);
+ * extern uint32_t size_of_f;
+ * int (*copied_f)(args);
+ * void *sram_buffer;
+ *
+ * copied_f = fncpy(sram_buffer, &f, size_of_f);
+ *
+ * ... later, call the function: ...
+ *
+ * copied_f(args);
+ *
+ * The size of the function to be copied can't be determined from C:
+ * this must be determined by other means, such as adding assmbler directives
+ * in the file where f is defined.
+ */
+
+#ifndef __ASM_FNCPY_H
+#define __ASM_FNCPY_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+
+/*
+ * Minimum alignment requirement for the source and destination addresses
+ * for function copying.
+ */
+#define FNCPY_ALIGN 8
+
+#define fncpy(dest_buf, funcp, size) ({					\
+	uintptr_t __funcp_address;					\
+	typeof(funcp) __result;						\
+									\
+	asm("" : "=r" (__funcp_address) : "0" (funcp));			\
+									\
+	memcpy(dest_buf, (void const *)(__funcp_address & ~1), size);	\
+									\
+	asm("" : "=r" (__result)					\
+		: "0" ((uintptr_t)(dest_buf) | (__funcp_address & 1)));	\
+									\
+	__result;							\
+})
+
+#endif /* !__ASM_FNCPY_H */
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:49 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:49 +0100
Subject: [PATCH 04/13] reset: add of_reset_control_get to header
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-4-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/reset/core.c  | 2 +-
 include/linux/reset.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 26a54f21df..1c9eeaec54 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -147,7 +147,7 @@ EXPORT_SYMBOL_GPL(reset_control_deassert);
  *
  * Use of id names is optional.
  */
-static struct reset_control *of_reset_control_get(struct device_node *node,
+struct reset_control *of_reset_control_get(struct device_node *node,
 						  const char *id)
 {
 	struct reset_control *rstc;
diff --git a/include/linux/reset.h b/include/linux/reset.h
index 4a92a177bc..76f40145d9 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -11,6 +11,8 @@ int reset_control_assert(struct reset_control *rstc);
 int reset_control_deassert(struct reset_control *rstc);
 
 struct reset_control *reset_control_get(struct device_d *dev, const char *id);
+struct reset_control *of_reset_control_get(struct device_node *node,
+					   const char *id);
 void reset_control_put(struct reset_control *rstc);
 
 int __must_check device_reset(struct device_d *dev);
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:56 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:56 +0100
Subject: [PATCH 11/13] commands: firmwareload: allow loading firmware from dt
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-11-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

firmwareload can only load a bitstream into an FPGA without any
knowledge of possible additional needs (e.g. FPGA bridges).

These are defined in the fpga-region nodes in the devicetree. The
fpga-region describes the layout of the FPGA and the bridges it needs
en/disabled.

Add an option to let firmwareload go via the oftree route and load the
firmware that way.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 commands/firmwareload.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/commands/firmwareload.c b/commands/firmwareload.c
index b735088f61..f2b7a74be0 100644
--- a/commands/firmwareload.c
+++ b/commands/firmwareload.c
@@ -5,18 +5,23 @@
 #include <command.h>
 #include <getopt.h>
 #include <firmware.h>
+#include <of.h>
 
 static int do_firmwareload(int argc, char *argv[])
 {
 	int ret, opt;
 	const char *name = NULL, *firmware;
 	struct firmware_mgr *mgr;
+	int oftree = 0;
 
-	while ((opt = getopt(argc, argv, "t:l")) > 0) {
+	while ((opt = getopt(argc, argv, "t:lo")) > 0) {
 		switch (opt) {
 		case 't':
 			name = optarg;
 			break;
+		case 'o':
+			oftree = 1;
+			break;
 		case 'l':
 			firmwaremgr_list_handlers();
 			return 0;
@@ -30,6 +35,11 @@ static int do_firmwareload(int argc, char *argv[])
 
 	firmware = argv[optind];
 
+	if (oftree) {
+		ret = of_firmware_load_file(firmware);
+		return ret;
+	}
+
 	mgr = firmwaremgr_find(name);
 
 	if (!mgr) {
@@ -46,6 +56,7 @@ static int do_firmwareload(int argc, char *argv[])
 BAREBOX_CMD_HELP_START(firmwareload)
 BAREBOX_CMD_HELP_TEXT("Options:")
 BAREBOX_CMD_HELP_OPT("-t <target>", "define the firmware handler by name")
+BAREBOX_CMD_HELP_OPT("-o\t", "find firmware definition from devicetree")
 BAREBOX_CMD_HELP_OPT("-l\t", "list devices capable of firmware loading")
 BAREBOX_CMD_HELP_END
 
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:52 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:52 +0100
Subject: [PATCH 07/13] firmware: socfpga: change function prefixes
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-7-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

Since there is now a fpgamgr framework in barebox, the function names are
misleading. Change that to be SoCFPGA specific.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/firmware/socfpga.c | 58 +++++++++++++++++++-------------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index c468c74372..14875214b1 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -92,12 +92,12 @@ struct fpgamgr {
 };
 
 /* Get the FPGA mode */
-static uint32_t fpgamgr_get_mode(struct fpgamgr *mgr)
+static uint32_t socfpga_fpgamgr_get_mode(struct fpgamgr *mgr)
 {
 	return readl(mgr->regs + FPGAMGRREGS_STAT) & FPGAMGRREGS_STAT_MODE_MASK;
 }
 
-static int fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
+static int socfpga_fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
 {
 	uint64_t start;
 
@@ -121,7 +121,7 @@ static int fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
 }
 
 /* Start the FPGA programming by initialize the FPGA Manager */
-static int fpgamgr_program_init(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_init(struct fpgamgr *mgr)
 {
 	unsigned long reg;
 	uint32_t ctrl = 0, ratio;
@@ -170,7 +170,7 @@ static int fpgamgr_program_init(struct fpgamgr *mgr)
 	/* (1) wait until FPGA enter reset phase */
 	start = get_time_ns();
 	while (1) {
-		if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_RESETPHASE)
+		if (socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_RESETPHASE)
 			break;
 		if (is_timeout(start, 100 * MSECOND))
 			return -ETIMEDOUT;
@@ -184,7 +184,7 @@ static int fpgamgr_program_init(struct fpgamgr *mgr)
 	/* (2) wait until FPGA enter configuration phase */
 	start = get_time_ns();
 	while (1) {
-		if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_CFGPHASE)
+		if (socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_CFGPHASE)
 			break;
 		if (is_timeout(start, 100 * MSECOND))
 			return -ETIMEDOUT;
@@ -202,7 +202,7 @@ static int fpgamgr_program_init(struct fpgamgr *mgr)
 }
 
 /* Ensure the FPGA entering config done */
-static int fpgamgr_program_poll_cd(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_poll_cd(struct fpgamgr *mgr)
 {
 	unsigned long reg;
 	uint32_t val;
@@ -236,18 +236,18 @@ static int fpgamgr_program_poll_cd(struct fpgamgr *mgr)
 }
 
 /* Ensure the FPGA entering init phase */
-static int fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
 {
 	uint64_t start;
 
 	/* additional clocks for the CB to enter initialization phase */
-	if (fpgamgr_dclkcnt_set(mgr, 0x4) != 0)
+	if (socfpga_fpgamgr_dclkcnt_set(mgr, 0x4) != 0)
 		return -5;
 
 	/* (4) wait until FPGA enter init phase or user mode */
 	start = get_time_ns();
 	while (1) {
-		int mode = fpgamgr_get_mode(mgr);
+		int mode = socfpga_fpgamgr_get_mode(mgr);
 
 		if (mode == FPGAMGRREGS_MODE_INITPHASE ||
 				mode == FPGAMGRREGS_MODE_USERMODE)
@@ -261,19 +261,19 @@ static int fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
 }
 
 /* Ensure the FPGA entering user mode */
-static int fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
 {
 	uint32_t val;
 	uint64_t start;
 
 	/* additional clocks for the CB to exit initialization phase */
-	if (fpgamgr_dclkcnt_set(mgr, 0x5000) != 0)
+	if (socfpga_fpgamgr_dclkcnt_set(mgr, 0x5000) != 0)
 		return -7;
 
 	/* (5) wait until FPGA enter user mode */
 	start = get_time_ns();
 	while (1) {
-		if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE)
+		if (socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE)
 			break;
 		if (is_timeout(start, 100 * MSECOND))
 			return -ETIMEDOUT;
@@ -291,7 +291,7 @@ static int fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
  * Using FPGA Manager to program the FPGA
  * Return 0 for sucess
  */
-static int fpgamgr_program_start(struct firmware_handler *fh)
+static int socfpga_fpgamgr_program_start(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
 	int status;
@@ -313,7 +313,7 @@ static int fpgamgr_program_start(struct firmware_handler *fh)
 	dev_dbg(&mgr->dev, "start programming...\n");
 
 	/* initialize the FPGA Manager */
-	status = fpgamgr_program_init(mgr);
+	status = socfpga_fpgamgr_program_init(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "program init failed with: %s\n",
 				strerror(-status));
@@ -324,7 +324,7 @@ static int fpgamgr_program_start(struct firmware_handler *fh)
 }
 
 /* Write the RBF data to FPGA Manager */
-static int fpgamgr_program_write_buf(struct firmware_handler *fh, const void *buf,
+static int socfpga_fpgamgr_program_write_buf(struct firmware_handler *fh, const void *buf,
 		size_t size)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
@@ -355,7 +355,7 @@ static int fpgamgr_program_write_buf(struct firmware_handler *fh, const void *bu
 	return 0;
 }
 
-static int fpgamgr_program_finish(struct firmware_handler *fh)
+static int socfpga_fpgamgr_program_finish(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
 	int status;
@@ -364,7 +364,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	void (*ocram_func)(void __iomem *ocram_base);
 
 	/* Ensure the FPGA entering config done */
-	status = fpgamgr_program_poll_cd(mgr);
+	status = socfpga_fpgamgr_program_poll_cd(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "poll for config done failed with: %s\n",
 				strerror(-status));
@@ -374,7 +374,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	dev_dbg(&mgr->dev, "waiting for init phase...\n");
 
 	/* Ensure the FPGA entering init phase */
-	status = fpgamgr_program_poll_initphase(mgr);
+	status = socfpga_fpgamgr_program_poll_initphase(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "poll for init phase failed with: %s\n",
 				strerror(-status));
@@ -384,7 +384,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	dev_dbg(&mgr->dev, "waiting for user mode...\n");
 
 	/* Ensure the FPGA entering user mode */
-	status = fpgamgr_program_poll_usermode(mgr);
+	status = socfpga_fpgamgr_program_poll_usermode(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "poll for user mode with: %s\n",
 				strerror(-status));
@@ -410,11 +410,11 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 static int programmed_get(struct param_d *p, void *priv)
 {
 	struct fpgamgr *mgr = priv;
-	mgr->programmed = fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE;
+	mgr->programmed = socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE;
 	return 0;
 }
 
-static int fpgamgr_probe(struct device_d *dev)
+static int socfpga_fpgamgr_probe(struct device_d *dev)
 {
 	struct resource *iores;
 	struct fpgamgr *mgr;
@@ -448,9 +448,9 @@ static int fpgamgr_probe(struct device_d *dev)
 	else
 		fh->id = xstrdup("socfpga-fpga");
 
-	fh->open = fpgamgr_program_start;
-	fh->write = fpgamgr_program_write_buf;
-	fh->close = fpgamgr_program_finish;
+	fh->open = socfpga_fpgamgr_program_start;
+	fh->write = socfpga_fpgamgr_program_write_buf;
+	fh->close = socfpga_fpgamgr_program_finish;
 	of_property_read_string(dev->device_node, "compatible", &model);
 	if (model)
 		fh->model = xstrdup(model);
@@ -488,7 +488,7 @@ out:
 	return ret;
 }
 
-static struct of_device_id fpgamgr_id_table[] = {
+static struct of_device_id socfpga_fpgamgr_id_table[] = {
 	{
 		.compatible = "altr,socfpga-fpga-mgr",
 	},
@@ -498,9 +498,9 @@ static struct of_device_id fpgamgr_id_table[] = {
 	{ /* sentinel */ }
 };
 
-static struct driver_d fpgamgr_driver = {
+static struct driver_d socfpga_fpgamgr_driver = {
 	.name = "socfpa-fpgamgr",
-	.of_compatible = DRV_OF_COMPAT(fpgamgr_id_table),
-	.probe = fpgamgr_probe,
+	.of_compatible = DRV_OF_COMPAT(socfpga_fpgamgr_id_table),
+	.probe = socfpga_fpgamgr_probe,
 };
-device_platform_driver(fpgamgr_driver);
+device_platform_driver(socfpga_fpgamgr_driver);
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:55 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:55 +0100
Subject: [PATCH 10/13] of: of_firmware: add support for fpga bridges
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-10-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

Add support for potentially defined FPGA-bridges in the overlay.

While at it also add support for loading the firmware directly via a
path instead of 'needing' an overlay for that.
The direct loading will be done with the existent firmwareload command.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/of/Makefile      |  3 +-
 drivers/of/of_firmware.c | 88 ++++++++++++++++++++++++++++++++++++----
 include/of.h             | 21 +++++++---
 3 files changed, 96 insertions(+), 16 deletions(-)

diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index b6847752d2..6199c9791f 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -6,4 +6,5 @@ obj-y += partition.o
 obj-y += of_net.o
 obj-$(CONFIG_MTD) += of_mtd.o
 obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o
-obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o of_firmware.o
+obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o
+obj-$(CONFIG_FIRMWARE) += of_firmware.o
diff --git a/drivers/of/of_firmware.c b/drivers/of/of_firmware.c
index 096f84572e..ef0ccd0221 100644
--- a/drivers/of/of_firmware.c
+++ b/drivers/of/of_firmware.c
@@ -4,12 +4,52 @@
  */
 #include <common.h>
 #include <firmware.h>
+#include <fpga-bridge.h>
 #include <of.h>
 
 struct overlay_info {
 	const char *firmware_path;
 };
 
+#ifdef CONFIG_FPGA_BRIDGE 
+static int of_get_bridges(struct device_node *region, struct list_head *bridges)
+{
+	struct device_node *br, *parent_br = NULL;
+	int i, ret;
+
+	/* If parent is a bridge, add to list */
+	ret = fpga_bridge_get_to_list(region->parent, bridges);
+	if (!ret) {
+		parent_br = region->parent;
+		pr_debug("Add %s to list of bridges\n", parent_br->name);
+	}
+
+	for (i = 0; ; i++) {
+		br = of_parse_phandle(region, "fpga-bridges", i);
+		if (!br)
+			break;
+
+		/* If parent bridge is in list, skip it. */
+		if (br == parent_br)
+			continue;
+
+		/* If node is a bridge, get it and add to list */
+		ret = fpga_bridge_get_to_list(br, bridges);
+		if (ret)
+			return ret;
+
+		pr_debug("Add %s to list of bridges\n", br->name);
+	}
+
+	return 0;
+}
+#else
+static int of_get_bridges(struct device_node *np, struct list_head *br)
+{
+	return 0;
+}
+#endif
+
 static struct firmware_mgr *of_node_get_mgr(struct device_node *np)
 {
 	struct device_node *mgr_node;
@@ -25,15 +65,49 @@ static struct firmware_mgr *of_node_get_mgr(struct device_node *np)
 	return NULL;
 }
 
-static int load_firmware(struct device_node *target,
-			 struct device_node *fragment, void *data)
+static int of_load_firmware(struct device_node *target, const char *path)
+{
+	struct list_head bridge_list;
+	struct firmware_mgr *mgr;
+	int err;
+
+	mgr = of_node_get_mgr(target);
+	if (!mgr)
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&bridge_list);
+
+	of_get_bridges(target, &bridge_list);
+
+	fpga_bridges_disable(&bridge_list);
+
+	err = firmwaremgr_load_file(mgr, path);
+
+	fpga_bridges_enable(&bridge_list);
+
+	return err;
+}
+
+int of_firmware_load_file(const char *path)
+{
+	int err;
+	struct device_node *target;
+
+	target = of_find_compatible_node(NULL, NULL, "fpga-region");
+
+	err = of_load_firmware(target, path);
+
+	return err;
+}
+
+static int load_overlay(struct device_node *target,
+			struct device_node *fragment, void *data)
 {
 	struct overlay_info *info = data;
 	const char *firmware_name;
 	const char *firmware_path = info->firmware_path;
 	char *firmware;
 	int err;
-	struct firmware_mgr *mgr;
 
 	err = of_property_read_string(fragment,
 				      "firmware-name", &firmware_name);
@@ -46,15 +120,11 @@ static int load_firmware(struct device_node *target,
 	if (!target)
 		return -EINVAL;
 
-	mgr = of_node_get_mgr(target);
-	if (!mgr)
-		return -EINVAL;
-
 	firmware = basprintf("%s/%s", firmware_path, firmware_name);
 	if (!firmware)
 		return -ENOMEM;
 
-	err = firmwaremgr_load_file(mgr, firmware);
+	err = of_load_firmware(target, firmware);
 
 	free(firmware);
 
@@ -82,7 +152,7 @@ int of_firmware_load_overlay(struct device_node *overlay, const char *path)
 	ovl = resolved ? resolved : overlay;
 
 	err = of_process_overlay(root, ovl,
-				 load_firmware, &info);
+				 load_overlay, &info);
 
 	if (resolved)
 		of_delete_node(resolved);
diff --git a/include/of.h b/include/of.h
index 645f429bde..e3deec9b4c 100644
--- a/include/of.h
+++ b/include/of.h
@@ -1020,6 +1020,21 @@ static inline struct device_node *of_find_root_node(struct device_node *node)
 	return node;
 }
 
+#ifdef CONFIG_FIRMWARE
+int of_firmware_load_file(const char *path);
+int of_firmware_load_overlay(struct device_node *overlay, const char *path);
+#else
+static inline int of_firmware_load_file(const char *path)
+{
+	return -ENOSYS;
+}
+
+static inline int of_firmware_load_overlay(const char *path)
+{
+	return -ENOSYS;
+}
+#endif
+
 #ifdef CONFIG_OF_OVERLAY
 struct device_node *of_resolve_phandles(struct device_node *root,
 					const struct device_node *overlay);
@@ -1032,7 +1047,6 @@ int of_process_overlay(struct device_node *root,
 				   struct device_node *overlay, void *data),
 		    void *data);
 
-int of_firmware_load_overlay(struct device_node *overlay, const char *path);
 #else
 static inline struct device_node *of_resolve_phandles(struct device_node *root,
 					const struct device_node *overlay)
@@ -1059,11 +1073,6 @@ static inline int of_process_overlay(struct device_node *root,
 {
 	return -ENOSYS;
 }
-
-static inline int of_firmware_load_overlay(struct device_node *overlay, const char *path)
-{
-	return -ENOSYS;
-}
 #endif
 
 #endif /* __OF_H */
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:53 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:53 +0100
Subject: [PATCH 08/13] firmware: import fpga-mgr.h from linux
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-8-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

Instead of defining the fpga-mgr structure in the socfpga driver, import
the fpga-mgr.h file from linux v4.13.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/firmware/socfpga.c |   9 +---
 include/firmware.h         |   1 +
 include/fpga-mgr.h         | 102 +++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 8 deletions(-)
 create mode 100644 include/fpga-mgr.h

diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 14875214b1..605c931604 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -27,6 +27,7 @@
  */
 
 #include <firmware.h>
+#include <fpga-mgr.h>
 #include <command.h>
 #include <common.h>
 #include <malloc.h>
@@ -83,14 +84,6 @@
 extern void socfpga_sdram_apply_static_cfg(void __iomem *sdrctrlgrp);
 extern void socfpga_sdram_apply_static_cfg_end(void *);
 
-struct fpgamgr {
-	struct firmware_handler fh;
-	struct device_d dev;
-	void __iomem *regs;
-	void __iomem *regs_data;
-	int programmed;
-};
-
 /* Get the FPGA mode */
 static uint32_t socfpga_fpgamgr_get_mode(struct fpgamgr *mgr)
 {
diff --git a/include/firmware.h b/include/firmware.h
index 19777d9bf7..2fef97a48f 100644
--- a/include/firmware.h
+++ b/include/firmware.h
@@ -13,6 +13,7 @@ struct firmware_handler {
 	char *id; /* unique identifier for this firmware device */
 	char *model; /* description for this device */
 	struct device_d *dev;
+	void *priv;
 	/* called once to prepare the firmware's programming cycle */
 	int (*open)(struct firmware_handler*);
 	/* called multiple times to program the firmware with the given data */
diff --git a/include/fpga-mgr.h b/include/fpga-mgr.h
new file mode 100644
index 0000000000..a120b39189
--- /dev/null
+++ b/include/fpga-mgr.h
@@ -0,0 +1,102 @@
+/*
+ * FPGA Framework
+ *
+ *  Copyright (C) 2013-2015 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _LINUX_FPGA_MGR_H
+#define _LINUX_FPGA_MGR_H
+
+#include <firmware.h>
+
+struct fpga_manager;
+
+/**
+ * enum fpga_mgr_states - fpga framework states
+ * @FPGA_MGR_STATE_UNKNOWN: can't determine state
+ * @FPGA_MGR_STATE_POWER_OFF: FPGA power is off
+ * @FPGA_MGR_STATE_POWER_UP: FPGA reports power is up
+ * @FPGA_MGR_STATE_RESET: FPGA in reset state
+ * @FPGA_MGR_STATE_FIRMWARE_REQ: firmware request in progress
+ * @FPGA_MGR_STATE_FIRMWARE_REQ_ERR: firmware request failed
+ * @FPGA_MGR_STATE_WRITE_INIT: preparing FPGA for programming
+ * @FPGA_MGR_STATE_WRITE_INIT_ERR: Error during WRITE_INIT stage
+ * @FPGA_MGR_STATE_WRITE: writing image to FPGA
+ * @FPGA_MGR_STATE_WRITE_ERR: Error while writing FPGA
+ * @FPGA_MGR_STATE_WRITE_COMPLETE: Doing post programming steps
+ * @FPGA_MGR_STATE_WRITE_COMPLETE_ERR: Error during WRITE_COMPLETE
+ * @FPGA_MGR_STATE_OPERATING: FPGA is programmed and operating
+ */
+enum fpga_mgr_states {
+	/* default FPGA states */
+	FPGA_MGR_STATE_UNKNOWN,
+	FPGA_MGR_STATE_POWER_OFF,
+	FPGA_MGR_STATE_POWER_UP,
+	FPGA_MGR_STATE_RESET,
+
+	/* getting an image for loading */
+	FPGA_MGR_STATE_FIRMWARE_REQ,
+	FPGA_MGR_STATE_FIRMWARE_REQ_ERR,
+
+	/* write sequence: init, write, complete */
+	FPGA_MGR_STATE_WRITE_INIT,
+	FPGA_MGR_STATE_WRITE_INIT_ERR,
+	FPGA_MGR_STATE_WRITE,
+	FPGA_MGR_STATE_WRITE_ERR,
+	FPGA_MGR_STATE_WRITE_COMPLETE,
+	FPGA_MGR_STATE_WRITE_COMPLETE_ERR,
+
+	/* fpga is programmed and operating */
+	FPGA_MGR_STATE_OPERATING,
+};
+
+/*
+ * FPGA Manager flags
+ * FPGA_MGR_PARTIAL_RECONFIG: do partial reconfiguration if supported
+ * FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
+ * FPGA_MGR_BITSTREAM_LSB_FIRST: SPI bitstream bit order is LSB first
+ * FPGA_MGR_COMPRESSED_BITSTREAM: FPGA bitstream is compressed
+ */
+#define FPGA_MGR_PARTIAL_RECONFIG	BIT(0)
+#define FPGA_MGR_EXTERNAL_CONFIG	BIT(1)
+#define FPGA_MGR_ENCRYPTED_BITSTREAM	BIT(2)
+#define FPGA_MGR_BITSTREAM_LSB_FIRST	BIT(3)
+#define FPGA_MGR_COMPRESSED_BITSTREAM	BIT(4)
+
+/**
+ * struct fpga_image_info - information specific to a FPGA image
+ * @flags: boolean flags as defined above
+ * @enable_timeout_us: maximum time to enable traffic through bridge (uSec)
+ * @disable_timeout_us: maximum time to disable traffic through bridge (uSec)
+ * @config_complete_timeout_us: maximum time for FPGA to switch to operating
+ *	   status in the write_complete op.
+ */
+struct fpga_image_info {
+	u32 flags;
+	u32 enable_timeout_us;
+	u32 disable_timeout_us;
+	u32 config_complete_timeout_us;
+};
+
+struct fpgamgr {
+	struct firmware_handler fh;
+	struct device_d dev;
+	void *priv;
+	void __iomem *regs;
+	void __iomem *regs_data;
+	int programmed;
+};
+
+
+#endif /*_LINUX_FPGA_MGR_H */
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:51 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:51 +0100
Subject: [PATCH 06/13] drivers: fpga: add socfpga bridges
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-6-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

Import the SoCFPGA bridges drivers from linux v4.10-rc2.

Description from the original commit:
e5f8efa5c8bf86c1fa698551d54db8f6aee221fd

    ARM: socfpga: fpga bridge driver support

    Supports Altera SOCFPGA bridges:
     * fpga2sdram
     * fpga2hps
     * hps2fpga
     * lwhps2fpga

    Allows enabling/disabling the bridges through the FPGA
    Bridge Framework API functions.

    The fpga2sdram driver only supports enabling and disabling
    of the ports that been configured early on.  This is due to
    a hardware limitation where the read, write, and command
    ports on the fpga2sdram bridge can only be reconfigured
    while there are no transactions to the sdram, i.e. when
    running out of OCRAM before the kernel boots.

    Device tree property 'init-val' configures the driver to
    enable or disable the bridge during probe.  If the property
    does not exist, the driver will leave the bridge in its
    current state.

    Signed-off-by: Alan Tull <atull at opensource.altera.com>
    Signed-off-by: Matthew Gerlach <mgerlach at altera.com>
    Signed-off-by: Dinh Nguyen <dinguyen at opensource.altera.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/fpga/Kconfig                     |   8 +
 drivers/fpga/Makefile                    |   1 +
 drivers/fpga/fpga-bridge.c               |   2 +-
 drivers/fpga/socfpga-fpga2sdram-bridge.c | 139 ++++++++++++++++++
 drivers/fpga/socfpga-hps2fpga-bridge.c   | 179 +++++++++++++++++++++++
 5 files changed, 328 insertions(+), 1 deletion(-)
 create mode 100644 drivers/fpga/socfpga-fpga2sdram-bridge.c
 create mode 100644 drivers/fpga/socfpga-hps2fpga-bridge.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index fccdbff6eb..64ce9f91b6 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -17,6 +17,14 @@ config FPGA_BRIDGE
 	  Say Y here if you want to support bridges connected between host
 	  processors and FPGAs or between FPGAs.
 
+config SOCFPGA_FPGA_BRIDGE
+	tristate "Altera SoCFPGA FPGA Bridges"
+	depends on ARCH_SOCFPGA && FPGA_BRIDGE
+	select RESET_CONTROLLER
+	help
+	  Say Y to enable drivers for FPGA bridges for Altera SOCFPGA
+	  devices.
+
 endif # FPGA
 
 endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index fc71a29d3b..86178fe7c0 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -4,3 +4,4 @@
 
 # FPGA Bridge Drivers
 obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
+obj-$(CONFIG_SOCFPGA_FPGA_BRIDGE)	+= socfpga-hps2fpga-bridge.o socfpga-fpga2sdram-bridge.o
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
index edf29b0ecf..b5c74a6e63 100644
--- a/drivers/fpga/fpga-bridge.c
+++ b/drivers/fpga/fpga-bridge.c
@@ -68,7 +68,7 @@ struct fpga_bridge *of_fpga_bridge_get(struct device_node *np)
 {
 	struct device_d *dev;
 	struct fpga_bridge *bridge;
-	int ret = -ENODEV;
+	int ret = -EPROBE_DEFER;
 
 	dev = of_find_device_by_node(np);
 	if (!dev || !dev->priv)
diff --git a/drivers/fpga/socfpga-fpga2sdram-bridge.c b/drivers/fpga/socfpga-fpga2sdram-bridge.c
new file mode 100644
index 0000000000..a9760597dd
--- /dev/null
+++ b/drivers/fpga/socfpga-fpga2sdram-bridge.c
@@ -0,0 +1,139 @@
+/*
+ * FPGA to SDRAM Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This driver manages a bridge between an FPGA and the SDRAM used by the ARM
+ * host processor system (HPS).
+ *
+ * The bridge contains 4 read ports, 4 write ports, and 6 command ports.
+ * Reconfiguring these ports requires that no SDRAM transactions occur during
+ * reconfiguration.  The code reconfiguring the ports cannot run out of SDRAM
+ * nor can the FPGA access the SDRAM during reconfiguration.  This driver does
+ * not support reconfiguring the ports.  The ports are configured by code
+ * running out of on chip ram before Linux is started and the configuration
+ * is passed in a handoff register in the system manager.
+ *
+ * This driver supports enabling and disabling of the configured ports, which
+ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
+ * uses the same port configuration.  Bridges must be disabled before
+ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <fpga-bridge.h>
+#include <mfd/syscon.h>
+#include <of_device.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define SOCFPGA_SDRCTL_ADDR			0xffc25000
+#define ALT_SDR_CTL_FPGAPORTRST_OFST		0x80
+#define ALT_SDR_CTL_FPGAPORTRST_PORTRSTN_MSK	0x00003fff
+#define ALT_SDR_CTL_FPGAPORTRST_RD_SHIFT	0
+#define ALT_SDR_CTL_FPGAPORTRST_WR_SHIFT	4
+#define ALT_SDR_CTL_FPGAPORTRST_CTRL_SHIFT	8
+
+#define SOCFPGA_SYSMGR_ADDR			0xffd08000
+/*
+ * From the Cyclone V HPS Memory Map document:
+ *   These registers are used to store handoff information between the
+ *   preloader and the OS. These 8 registers can be used to store any
+ *   information. The contents of these registers have no impact on
+ *   the state of the HPS hardware.
+ */
+#define SYSMGR_ISWGRP_HANDOFF3          (0x8C)
+
+#define F2S_BRIDGE_NAME "fpga2sdram"
+
+struct alt_fpga2sdram_data {
+	struct device_d *dev;
+	int mask;
+};
+
+static inline int _alt_fpga2sdram_enable_set(struct alt_fpga2sdram_data *priv,
+					     bool enable)
+{
+	int val;
+
+	val = readl(SOCFPGA_SDRCTL_ADDR + ALT_SDR_CTL_FPGAPORTRST_OFST);
+
+	if (enable)
+		val |= priv->mask;
+	else
+		val = 0;
+
+	/* The kernel driver expects this value in this register :-( */
+	writel(priv->mask, SOCFPGA_SYSMGR_ADDR + SYSMGR_ISWGRP_HANDOFF3);
+
+	dev_dbg(priv->dev, "setting fpgaportrst to 0x%08x\n", val);
+
+	return writel(val, SOCFPGA_SDRCTL_ADDR + ALT_SDR_CTL_FPGAPORTRST_OFST);
+}
+
+static int alt_fpga2sdram_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	return _alt_fpga2sdram_enable_set(bridge->priv, enable);
+}
+
+struct prop_map {
+	char *prop_name;
+	u32 *prop_value;
+	u32 prop_max;
+};
+
+static const struct fpga_bridge_ops altera_fpga2sdram_br_ops = {
+	.enable_set = alt_fpga2sdram_enable_set,
+};
+
+static struct of_device_id altera_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-fpga2sdram-bridge" },
+	{},
+};
+
+static int alt_fpga_bridge_probe(struct device_d *dev)
+{
+	struct alt_fpga2sdram_data *priv;
+	int ret = 0;
+
+	priv = xzalloc(sizeof(*priv));
+	if (!priv)
+		return -ENOMEM;
+
+	/* enable all ports for now */
+	priv->mask = ALT_SDR_CTL_FPGAPORTRST_PORTRSTN_MSK;
+
+	priv->dev = dev;
+
+	ret = fpga_bridge_register(dev, F2S_BRIDGE_NAME,
+				   &altera_fpga2sdram_br_ops, priv);
+	if (ret)
+		return ret;
+
+	dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
+
+	return ret;
+}
+
+static struct driver_d altera_fpga_driver = {
+	.probe = alt_fpga_bridge_probe,
+	.name = "altera-fpga2sdram-bridge",
+	.of_compatible = DRV_OF_COMPAT(altera_fpga_of_match),
+};
+device_platform_driver(altera_fpga_driver);
diff --git a/drivers/fpga/socfpga-hps2fpga-bridge.c b/drivers/fpga/socfpga-hps2fpga-bridge.c
new file mode 100644
index 0000000000..ecb33ea0b3
--- /dev/null
+++ b/drivers/fpga/socfpga-hps2fpga-bridge.c
@@ -0,0 +1,179 @@
+/*
+ * FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * Includes this patch from the mailing list:
+ *   fpga: altera-hps2fpga: fix HPS2FPGA bridge visibility to L3 masters
+ *   Signed-off-by: Anatolij Gustschin <agust at denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This driver manages bridges on a Altera SOCFPGA between the ARM host
+ * processor system (HPS) and the embedded FPGA.
+ *
+ * This driver supports enabling and disabling of the configured ports, which
+ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
+ * uses the same port configuration.  Bridges must be disabled before
+ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <fpga-bridge.h>
+#include <mfd/syscon.h>
+#include <of_device.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define SOCFPGA_L3_ADDR				0xff800000
+#define ALT_L3_REMAP_OFST			0x0
+#define ALT_L3_REMAP_MPUZERO_MSK		0x00000001
+#define ALT_L3_REMAP_H2F_MSK			0x00000008
+#define ALT_L3_REMAP_LWH2F_MSK			0x00000010
+
+#define HPS2FPGA_BRIDGE_NAME			"hps2fpga"
+#define LWHPS2FPGA_BRIDGE_NAME			"lwhps2fpga"
+#define FPGA2HPS_BRIDGE_NAME			"fpga2hps"
+
+struct altera_hps2fpga_data {
+	struct device_d *dev;
+	const char *name;
+	struct reset_control *bridge_reset;
+	unsigned int remap_mask;
+	struct clk *clk;
+};
+
+/* The L3 REMAP register is write only, so keep a cached value. */
+static unsigned int l3_remap_shadow;
+
+static int _alt_hps2fpga_enable_set(struct altera_hps2fpga_data *priv,
+				    bool enable)
+{
+	int ret;
+
+	/* bring bridge out of reset */
+	if (enable)
+		ret = reset_control_deassert(priv->bridge_reset);
+	else
+		ret = reset_control_assert(priv->bridge_reset);
+	if (ret)
+		return ret;
+
+	/* Allow bridge to be visible to L3 masters or not */
+	if (priv->remap_mask) {
+		l3_remap_shadow |= ALT_L3_REMAP_MPUZERO_MSK;
+
+		if (enable)
+			l3_remap_shadow |= priv->remap_mask;
+		else
+			l3_remap_shadow &= ~priv->remap_mask;
+
+		dev_dbg(priv->dev, "setting L3 visibility to 0x%08x\n",
+			l3_remap_shadow);
+
+		writel(l3_remap_shadow, SOCFPGA_L3_ADDR + ALT_L3_REMAP_OFST);
+	}
+
+	return ret;
+}
+
+static int alt_hps2fpga_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	return _alt_hps2fpga_enable_set(bridge->priv, enable);
+}
+
+static const struct fpga_bridge_ops altera_hps2fpga_br_ops = {
+	.enable_set = alt_hps2fpga_enable_set,
+};
+
+static struct altera_hps2fpga_data hps2fpga_data  = {
+	.name = HPS2FPGA_BRIDGE_NAME,
+	.remap_mask = ALT_L3_REMAP_H2F_MSK,
+};
+
+static struct altera_hps2fpga_data lwhps2fpga_data  = {
+	.name = LWHPS2FPGA_BRIDGE_NAME,
+	.remap_mask = ALT_L3_REMAP_LWH2F_MSK,
+};
+
+static struct altera_hps2fpga_data fpga2hps_data  = {
+	.name = FPGA2HPS_BRIDGE_NAME,
+};
+
+static struct of_device_id altera_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-hps2fpga-bridge",
+	  .data = &hps2fpga_data },
+	{ .compatible = "altr,socfpga-lwhps2fpga-bridge",
+	  .data = &lwhps2fpga_data },
+	{ .compatible = "altr,socfpga-fpga2hps-bridge",
+	  .data = &fpga2hps_data },
+	{ /* sentinel */ },
+};
+
+static int alt_fpga_bridge_probe(struct device_d *dev)
+{
+	struct altera_hps2fpga_data *priv;
+	const struct of_device_id *of_id;
+	u32 enable;
+	int ret;
+
+	of_id = of_match_device(altera_fpga_of_match, dev);
+	priv = (struct altera_hps2fpga_data *)of_id->data;
+
+	priv->bridge_reset = of_reset_control_get(dev->device_node, NULL);
+	if (IS_ERR(priv->bridge_reset)) {
+		dev_err(dev, "Could not get %s reset control\n", priv->name);
+		return PTR_ERR(priv->bridge_reset);
+	}
+
+	priv->clk = clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "no clock specified\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	ret = clk_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "could not enable clock\n");
+		return -EBUSY;
+	}
+
+	priv->dev = dev;
+
+	if (!of_property_read_u32(dev->device_node, "bridge-enable", &enable)) {
+		if (enable > 1) {
+			dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
+		} else {
+			dev_info(dev, "%s bridge\n",
+				 (enable ? "enabling" : "disabling"));
+
+			ret = _alt_hps2fpga_enable_set(priv, enable);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops,
+				    priv);
+}
+
+static struct driver_d alt_fpga_bridge_driver = {
+	.probe = alt_fpga_bridge_probe,
+	.name = "altera-hps2fpga-bridge",
+	.of_compatible = DRV_OF_COMPAT(altera_fpga_of_match),
+};
+device_platform_driver(alt_fpga_bridge_driver);
-- 
2.20.1



From str at pengutronix.de  Thu Jan 21 06:29:50 2021
From: str at pengutronix.de (Steffen Trumtrar)
Date: Thu, 21 Jan 2021 12:29:50 +0100
Subject: [PATCH 05/13] drivers: add fpga bridge framework
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210121112958.25937-5-str@pengutronix.de>

From: Steffen Trumtrar <s.trumtrar at pengutronix.de>

Import the fpga bridge framework from linux v4.10-rc2.

Description from the initial commit adding this to linux:
21aeda950c5f84a8351b862816d832120b217a9b

    fpga: add fpga bridge framework

    This framework adds API functions for enabling/
    disabling FPGA bridges under kernel control.

    This allows the Linux kernel to disable FPGA bridges
    during FPGA reprogramming and to enable FPGA bridges
    when FPGA reprogramming is done.  This framework is
    be manufacturer-agnostic, allowing it to be used in
    interfaces that use the FPGA Manager Framework to
    reprogram FPGA's.

    The functions are:
    * of_fpga_bridge_get
    * fpga_bridge_put
       Get/put an exclusive reference to a FPGA bridge.

    * fpga_bridge_enable
    * fpga_bridge_disable
       Enable/Disable traffic through a bridge.

    * fpga_bridge_register
    * fpga_bridge_unregister
       Register/unregister a device-specific low level FPGA
       Bridge driver.

    Get an exclusive reference to a bridge and add it to a list:
    * fpga_bridge_get_to_list

    To enable/disable/put a set of bridges that are on a list:
    * fpga_bridges_enable
    * fpga_bridges_disable
    * fpga_bridges_put

    Signed-off-by: Alan Tull <atull at opensource.altera.com>

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/Kconfig            |   1 +
 drivers/Makefile           |   1 +
 drivers/fpga/Kconfig       |  22 ++++
 drivers/fpga/Makefile      |   6 +
 drivers/fpga/fpga-bridge.c | 226 +++++++++++++++++++++++++++++++++++++
 include/fpga-bridge.h      |  69 +++++++++++
 6 files changed, 325 insertions(+)
 create mode 100644 drivers/fpga/Kconfig
 create mode 100644 drivers/fpga/Makefile
 create mode 100644 drivers/fpga/fpga-bridge.c
 create mode 100644 include/fpga-bridge.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index dda2405780..3bb9c09536 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -36,6 +36,7 @@ source "drivers/reset/Kconfig"
 source "drivers/pci/Kconfig"
 source "drivers/rtc/Kconfig"
 source "drivers/firmware/Kconfig"
+source "drivers/fpga/Kconfig"
 source "drivers/phy/Kconfig"
 source "drivers/crypto/Kconfig"
 source "drivers/memory/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 5a03bdceab..5221c2ca55 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_RESET_CONTROLLER) += reset/
 obj-$(CONFIG_PCI) += pci/
 obj-y += rtc/
 obj-$(CONFIG_FIRMWARE) += firmware/
+obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_GENERIC_PHY) += phy/
 obj-$(CONFIG_HAB) += hab/
 obj-$(CONFIG_CRYPTO_HW) += crypto/
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
new file mode 100644
index 0000000000..fccdbff6eb
--- /dev/null
+++ b/drivers/fpga/Kconfig
@@ -0,0 +1,22 @@
+#
+# FPGA framework configuration
+#
+
+menu "FPGA Configuration Support"
+
+config FPGA
+	tristate "FPGA Configuration Framework"
+	help
+	  Say Y here if you want support for configuring FPGAs from barebox.
+
+if FPGA
+
+config FPGA_BRIDGE
+	tristate "FPGA Bridge Framework"
+	help
+	  Say Y here if you want to support bridges connected between host
+	  processors and FPGAs or between FPGAs.
+
+endif # FPGA
+
+endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
new file mode 100644
index 0000000000..fc71a29d3b
--- /dev/null
+++ b/drivers/fpga/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the fpga framework and fpga manager drivers.
+#
+
+# FPGA Bridge Drivers
+obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
new file mode 100644
index 0000000000..edf29b0ecf
--- /dev/null
+++ b/drivers/fpga/fpga-bridge.c
@@ -0,0 +1,226 @@
+/*
+ * FPGA Bridge Framework Driver
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <common.h>
+#include <fpga-bridge.h>
+
+/**
+ * fpga_bridge_enable - Enable transactions on the bridge
+ *
+ * @bridge: FPGA bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_enable(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "enable\n");
+
+	if (bridge->br_ops && bridge->br_ops->enable_set)
+		return bridge->br_ops->enable_set(bridge, 1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_enable);
+
+/**
+ * fpga_bridge_disable - Disable transactions on the bridge
+ *
+ * @bridge: FPGA bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_disable(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "disable\n");
+
+	if (bridge->br_ops && bridge->br_ops->enable_set)
+		return bridge->br_ops->enable_set(bridge, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_disable);
+
+/**
+ * of_fpga_bridge_get - get an exclusive reference to a fpga bridge
+ *
+ * @np: node pointer of a FPGA bridge
+ *
+ * Return fpga_bridge struct if successful.
+ * Return -EBUSY if someone already has a reference to the bridge.
+ * Return -ENODEV if @np is not a FPGA Bridge.
+ */
+struct fpga_bridge *of_fpga_bridge_get(struct device_node *np)
+
+{
+	struct device_d *dev;
+	struct fpga_bridge *bridge;
+	int ret = -ENODEV;
+
+	dev = of_find_device_by_node(np);
+	if (!dev || !dev->priv)
+		return ERR_PTR(ret);
+
+	bridge = dev->priv;
+
+	return bridge;
+}
+EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
+
+/**
+ * fpga_bridges_enable - enable bridges in a list
+ * @bridge_list: list of FPGA bridges
+ *
+ * Enable each bridge in the list.  If list is empty, do nothing.
+ *
+ * Return 0 for success or empty bridge list; return error code otherwise.
+ */
+int fpga_bridges_enable(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	int ret;
+
+	list_for_each_entry(bridge, bridge_list, node) {
+		ret = fpga_bridge_enable(bridge);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_enable);
+
+/**
+ * fpga_bridges_disable - disable bridges in a list
+ *
+ * @bridge_list: list of FPGA bridges
+ *
+ * Disable each bridge in the list.  If list is empty, do nothing.
+ *
+ * Return 0 for success or empty bridge list; return error code otherwise.
+ */
+int fpga_bridges_disable(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	int ret;
+
+	list_for_each_entry(bridge, bridge_list, node) {
+		ret = fpga_bridge_disable(bridge);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_disable);
+
+/**
+ * fpga_bridges_get_to_list - get a bridge, add it to a list
+ *
+ * @np: node pointer of a FPGA bridge
+ * @bridge_list: list of FPGA bridges
+ *
+ * Get an exclusive reference to the bridge and and it to the list.
+ *
+ * Return 0 for success, error code from of_fpga_bridge_get() othewise.
+ */
+int fpga_bridge_get_to_list(struct device_node *np,
+			    struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+
+	bridge = of_fpga_bridge_get(np);
+	if (IS_ERR(bridge))
+		return PTR_ERR(bridge);
+	list_add(&bridge->node, bridge_list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
+
+static int set_enable(struct param_d *p, void *priv)
+{
+	struct fpga_bridge *bridge = priv;
+
+	if (bridge->enable)
+		fpga_bridge_enable(bridge);
+	else
+		fpga_bridge_disable(bridge);
+
+	return 0;
+}
+
+/**
+ * fpga_bridge_register - register a fpga bridge driver
+ * @dev:	FPGA bridge device from pdev
+ * @name:	FPGA bridge name
+ * @br_ops:	pointer to structure of fpga bridge ops
+ * @priv:	FPGA bridge private data
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_register(struct device_d *dev, const char *name,
+			 const struct fpga_bridge_ops *br_ops, void *priv)
+{
+	struct fpga_bridge *bridge;
+	struct param_d *p;
+	int ret = 0;
+
+	if (!name || !strlen(name)) {
+		dev_err(dev, "Attempt to register with no name!\n");
+		return -EINVAL;
+	}
+
+	bridge = xzalloc(sizeof(*bridge));
+	if (!bridge)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&bridge->node);
+
+	bridge->br_ops = br_ops;
+	bridge->priv = priv;
+
+	bridge->dev.parent = dev;
+	bridge->dev.device_node = dev->device_node;
+	bridge->dev.id = DEVICE_ID_DYNAMIC;
+
+	bridge->dev.name = xstrdup(name);
+
+	ret = register_device(&bridge->dev);
+	if (ret)
+		goto out;
+
+	dev->priv = bridge;
+
+	bridge->enable = 0;
+	p = dev_add_param_bool(&bridge->dev, "enable", set_enable,
+			       NULL, &bridge->enable, bridge);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+
+	of_platform_populate(dev->device_node, NULL, dev);
+
+	dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n",
+		 bridge->dev.name);
+
+	return 0;
+
+out:
+	kfree(bridge);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_register);
diff --git a/include/fpga-bridge.h b/include/fpga-bridge.h
new file mode 100644
index 0000000000..8d55043a77
--- /dev/null
+++ b/include/fpga-bridge.h
@@ -0,0 +1,69 @@
+#include <common.h>
+
+#ifndef _LINUX_FPGA_BRIDGE_H
+#define _LINUX_FPGA_BRIDGE_H
+
+struct fpga_bridge;
+
+/**
+ * struct fpga_bridge_ops - ops for low level FPGA bridge drivers
+ * @enable_show: returns the FPGA bridge's status
+ * @enable_set: set a FPGA bridge as enabled or disabled
+ * @fpga_bridge_remove: set FPGA into a specific state during driver remove
+ */
+struct fpga_bridge_ops {
+	int (*enable_show)(struct fpga_bridge *bridge);
+	int (*enable_set)(struct fpga_bridge *bridge, bool enable);
+	void (*fpga_bridge_remove)(struct fpga_bridge *bridge);
+};
+
+/**
+ * struct fpga_bridge - FPGA bridge structure
+ * @name: name of low level FPGA bridge
+ * @dev: FPGA bridge device
+ * @mutex: enforces exclusive reference to bridge
+ * @br_ops: pointer to struct of FPGA bridge ops
+ * @info: fpga image specific information
+ * @node: FPGA bridge list node
+ * @priv: low level driver private date
+ */
+struct fpga_bridge {
+	struct device_d dev;
+	const struct fpga_bridge_ops *br_ops;
+	struct list_head node;
+	unsigned int enable;
+	void *priv;
+};
+
+#define to_fpga_bridge(d) container_of(d, struct fpga_bridge, dev)
+
+struct fpga_bridge *of_fpga_bridge_get(struct device_node *node);
+void fpga_bridge_put(struct fpga_bridge *bridge);
+int fpga_bridge_enable(struct fpga_bridge *bridge);
+int fpga_bridge_disable(struct fpga_bridge *bridge);
+
+#ifdef CONFIG_FPGA_BRIDGE
+int fpga_bridges_enable(struct list_head *bridge_list);
+int fpga_bridges_disable(struct list_head *bridge_list);
+int fpga_bridge_get_to_list(struct device_node *np,
+			    struct list_head *bridge_list);
+#else
+static inline int fpga_bridges_enable(struct list_head *bridge_list)
+{
+	return -ENOSYS;
+};
+static inline int fpga_bridges_disable(struct list_head *bridge_list)
+{
+	return -ENOSYS;
+};
+static inline int fpga_bridge_get_to_list(struct device_node *np,
+			    struct list_head *bridge_list)
+{
+	return -ENOSYS;
+};
+#endif
+
+int fpga_bridge_register(struct device_d *dev, const char *name,
+			 const struct fpga_bridge_ops *br_ops, void *priv);
+
+#endif /* _LINUX_FPGA_BRIDGE_H */
-- 
2.20.1



From andrej.picej at norik.com  Thu Jan 21 07:23:16 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Thu, 21 Jan 2021 13:23:16 +0100
Subject: [PATCH 3/3] ARM: i.MX: xload-gpmi-nand: apply errata 007117
In-Reply-To: <20210121091128.GG19063@pengutronix.de>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-4-andrej.picej@norik.com>
 <20210121091128.GG19063@pengutronix.de>
Message-ID: <435bb8a9-96b8-4a09-1a42-19cc77e42ebf@norik.com>

Hi Sascha,

yes, unfortunately we have. We applied this just because we experienced 
hangs in device booting tests. After this patch the NAND booting 
problems went away. The booting failed during DMA page reading.
I just tested this again and after excluding the changes in this patch 
the device fails at executing DMA commands. The boot fails in 
approximately one out of 10 boots.

Best regards,
Andrej

On 21. 01. 21 10:11, Sascha Hauer wrote:
> On Wed, Jan 20, 2021 at 01:51:07PM +0100, Andrej Picej wrote:
>> During raw NAND booting, GPMI/BCH clock generation might fail due to
>> improper clock gating conditions and consequently booting from NAND will
>> fail. This is caused by silicon errata ERR007117. Apply errata fix
>> workaround before GPMI NAND xload to prevent this from occurring.
>>
>> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
>> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
>> ---
>>   arch/arm/mach-imx/xload-gpmi-nand.c | 62 +++++++++++++++++++++++++++++
>>   1 file changed, 62 insertions(+)
>>
>> diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
>> index 04f799604..4be6d1890 100644
>> --- a/arch/arm/mach-imx/xload-gpmi-nand.c
>> +++ b/arch/arm/mach-imx/xload-gpmi-nand.c
>> @@ -20,6 +20,8 @@
>>   #include <mach/xload.h>
>>   #include <mach/imx-nand-bcb.h>
>>   #include <linux/mtd/rawnand.h>
>> +#include <mach/imx6-regs.h>
>> +#include <mach/clock-imx6.h>
>>   
>>   /*
>>    * MXS DMA hardware command.
>> @@ -256,6 +258,63 @@ struct mxs_nand_info {
>>   	unsigned long nand_size;
>>   };
>>   
>> +/**
>> + * It was discovered that xloading barebox from NAND sometimes fails. Observed
>> + * behaviour is similar to silicon errata ERR007117 for i.MX6.
> 
> Have you really seen this behaviour? I wonder because the ROM has
> already loaded the initial code that is just running from NAND, so it
> surprises me that we still have to apply clock fixes.
> 
> Sascha
> 


From sha at pengutronix.de  Fri Jan 22 03:12:15 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Fri, 22 Jan 2021 09:12:15 +0100
Subject: [PATCH 3/3] ARM: i.MX: xload-gpmi-nand: apply errata 007117
In-Reply-To: <435bb8a9-96b8-4a09-1a42-19cc77e42ebf@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-4-andrej.picej@norik.com>
 <20210121091128.GG19063@pengutronix.de>
 <435bb8a9-96b8-4a09-1a42-19cc77e42ebf@norik.com>
Message-ID: <20210122081215.GM19063@pengutronix.de>

On Thu, Jan 21, 2021 at 01:23:16PM +0100, Andrej Picej wrote:
> Hi Sascha,
> 
> yes, unfortunately we have. We applied this just because we experienced
> hangs in device booting tests. After this patch the NAND booting problems
> went away. The booting failed during DMA page reading.
> I just tested this again and after excluding the changes in this patch the
> device fails at executing DMA commands. The boot fails in approximately one
> out of 10 boots.

Where exactly did it hang? In the xloader or later in the real barebox
driver?
You probably mean that it hangs in the xloader. Sorry to ask, but I'm
still trying to understand. That would mean the ROM leaves the GPMI in
an unusable state and I really wonder how this can happen.

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From andrej.picej at norik.com  Fri Jan 22 04:47:09 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Fri, 22 Jan 2021 10:47:09 +0100
Subject: [PATCH 3/3] ARM: i.MX: xload-gpmi-nand: apply errata 007117
In-Reply-To: <20210122081215.GM19063@pengutronix.de>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-4-andrej.picej@norik.com>
 <20210121091128.GG19063@pengutronix.de>
 <435bb8a9-96b8-4a09-1a42-19cc77e42ebf@norik.com>
 <20210122081215.GM19063@pengutronix.de>
Message-ID: <65415553-750c-810d-7902-b1052d764bec@norik.com>



On 22. 01. 21 09:12, Sascha Hauer wrote:
> On Thu, Jan 21, 2021 at 01:23:16PM +0100, Andrej Picej wrote:
>> Hi Sascha,
>>
>> yes, unfortunately we have. We applied this just because we experienced
>> hangs in device booting tests. After this patch the NAND booting problems
>> went away. The booting failed during DMA page reading.
>> I just tested this again and after excluding the changes in this patch the
>> device fails at executing DMA commands. The boot fails in approximately one
>> out of 10 boots.
> 
> Where exactly did it hang? In the xloader or later in the real barebox
> driver?
> You probably mean that it hangs in the xloader. Sorry to ask, but I'm
> still trying to understand. That would mean the ROM leaves the GPMI in
> an unusable state and I really wonder how this can happen.
> 
> Sascha
> 

Sorry for not being clear enough the first time. You are correct, it 
hangs in xloader.

Maybe some additional information that may be relevant. When we boot 
barebox without PBL support barebox boots without problem and NAND 
behaves normal, so i guess the ROM sets the GPMI in usable state.
Just a thought: could it be that the problem is in xloader and we 
somehow repair or reset the GPMI with this errata fix, so it works with 
xloader?

Andrej


From eagle.alexander923 at gmail.com  Mon Jan 25 03:20:04 2021
From: eagle.alexander923 at gmail.com (Alexander Shiyan)
Date: Mon, 25 Jan 2021 11:20:04 +0300
Subject: AM335x NAND write hungs
Message-ID: <CAP1tNvT79QvYYTL9O+V+HR=XVTKHS=UxJtc1ZvNaMu1yQZns9w@mail.gmail.com>

Hello.

I recently upgraded my barebox from 2020.11 to 2021.01 for a custom board
based on TI AM335x processor.
The update revealed the inoperability of writing to NAND. When trying to write,
the bootloader hangs forever.
Reverting the commit "mtd: nand: omap_gpmc: Fix wrong length check" helps
to solve the problem.
Does anyone have similar problems?

Thanks!


From a.fatoum at pengutronix.de  Mon Jan 25 03:37:41 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 25 Jan 2021 09:37:41 +0100
Subject: AM335x NAND write hungs
In-Reply-To: <CAP1tNvT79QvYYTL9O+V+HR=XVTKHS=UxJtc1ZvNaMu1yQZns9w@mail.gmail.com>
References: <CAP1tNvT79QvYYTL9O+V+HR=XVTKHS=UxJtc1ZvNaMu1yQZns9w@mail.gmail.com>
Message-ID: <a8d24265-a9e7-c521-c0b1-cc8e0691d636@pengutronix.de>

Hello,

On 25.01.21 09:20, Alexander Shiyan wrote:
> Hello.
> 
> I recently upgraded my barebox from 2020.11 to 2021.01 for a custom board
> based on TI AM335x processor.
> The update revealed the inoperability of writing to NAND. When trying to write,
> the bootloader hangs forever.
> Reverting the commit "mtd: nand: omap_gpmc: Fix wrong length check" helps
> to solve the problem.

What happens when changing the condition to len > 0?

> Does anyone have similar problems?
> 
> Thanks!
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From eagle.alexander923 at gmail.com  Mon Jan 25 03:56:34 2021
From: eagle.alexander923 at gmail.com (Alexander Shiyan)
Date: Mon, 25 Jan 2021 11:56:34 +0300
Subject: AM335x NAND write hungs
In-Reply-To: <a8d24265-a9e7-c521-c0b1-cc8e0691d636@pengutronix.de>
References: <CAP1tNvT79QvYYTL9O+V+HR=XVTKHS=UxJtc1ZvNaMu1yQZns9w@mail.gmail.com>
 <a8d24265-a9e7-c521-c0b1-cc8e0691d636@pengutronix.de>
Message-ID: <CAP1tNvSGFXWxVKoQanR9S6FxjV_U0DUMrkL-C1Bg7Ze5TaS1+w@mail.gmail.com>

Works as expected.
Can you commit this change into master?
Thanks!

??, 25 ???. 2021 ?. ? 11:37, Ahmad Fatoum <a.fatoum at pengutronix.de>:
>
> Hello,
>
> On 25.01.21 09:20, Alexander Shiyan wrote:
> > Hello.
> >
> > I recently upgraded my barebox from 2020.11 to 2021.01 for a custom board
> > based on TI AM335x processor.
> > The update revealed the inoperability of writing to NAND. When trying to write,
> > the bootloader hangs forever.
> > Reverting the commit "mtd: nand: omap_gpmc: Fix wrong length check" helps
> > to solve the problem.
>
> What happens when changing the condition to len > 0?
>
> > Does anyone have similar problems?
> >
> > Thanks!
> >
> > _______________________________________________
> > barebox mailing list
> > barebox at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/barebox
> >
>
> --
> Pengutronix e.K.                           |                             |
> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Jan 25 03:57:17 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 25 Jan 2021 09:57:17 +0100
Subject: [PATCH 3/3] ARM: i.MX: xload-gpmi-nand: apply errata 007117
In-Reply-To: <65415553-750c-810d-7902-b1052d764bec@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-4-andrej.picej@norik.com>
 <20210121091128.GG19063@pengutronix.de>
 <435bb8a9-96b8-4a09-1a42-19cc77e42ebf@norik.com>
 <20210122081215.GM19063@pengutronix.de>
 <65415553-750c-810d-7902-b1052d764bec@norik.com>
Message-ID: <20210125085717.GC31738@pengutronix.de>

On Fri, Jan 22, 2021 at 10:47:09AM +0100, Andrej Picej wrote:
> 
> 
> On 22. 01. 21 09:12, Sascha Hauer wrote:
> > On Thu, Jan 21, 2021 at 01:23:16PM +0100, Andrej Picej wrote:
> > > Hi Sascha,
> > > 
> > > yes, unfortunately we have. We applied this just because we experienced
> > > hangs in device booting tests. After this patch the NAND booting problems
> > > went away. The booting failed during DMA page reading.
> > > I just tested this again and after excluding the changes in this patch the
> > > device fails at executing DMA commands. The boot fails in approximately one
> > > out of 10 boots.
> > 
> > Where exactly did it hang? In the xloader or later in the real barebox
> > driver?
> > You probably mean that it hangs in the xloader. Sorry to ask, but I'm
> > still trying to understand. That would mean the ROM leaves the GPMI in
> > an unusable state and I really wonder how this can happen.
> > 
> > Sascha
> > 
> 
> Sorry for not being clear enough the first time. You are correct, it hangs
> in xloader.
> 
> Maybe some additional information that may be relevant. When we boot barebox
> without PBL support barebox boots without problem and NAND behaves normal,
> so i guess the ROM sets the GPMI in usable state.
> Just a thought: could it be that the problem is in xloader and we somehow
> repair or reset the GPMI with this errata fix, so it works with xloader?

It could be that the ROM changes parts of the clock tree after having
loaded the image from NAND and before it jumps to the payload. It might
be that we would have the same problem in the real barebox driver if we
wouldn't reconfigure the clocks anyway in the clock driver.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Jan 25 04:15:47 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 25 Jan 2021 10:15:47 +0100
Subject: [PATCH 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <7df4659e-7237-c5fa-767f-7dedd5c44005@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-3-andrej.picej@norik.com>
 <20210121090148.GF19063@pengutronix.de>
 <7df4659e-7237-c5fa-767f-7dedd5c44005@norik.com>
Message-ID: <20210125091547.GB8233@pengutronix.de>

On Thu, Jan 21, 2021 at 11:28:39AM +0100, Andrej Picej wrote:
> Hi Sascha,
> 
> thanks for your comments.
> 
> Responses inline.
> 
> On 21. 01. 21 10:01, Sascha Hauer wrote:
> > Hi Andrej,
> > 
> > Some comments inline.
> > 
> > On Wed, Jan 20, 2021 at 01:51:06PM +0100, Andrej Picej wrote:
> > > From: Sascha Hauer <s.hauer at pengutronix.de>
> > > 
> > > Commit is based on initial Sascha Hauer's work. It implements PBL xload
> > > mechanism to load image from GPMI NAND flash.
> > > 
> > > Additional work was done, so that the NAND's size, page size and OOB's
> > > size are autodetected and not hardcoded. Detection method follows the
> > > same methods as used in NAND driver, meaning NAND ONFI support is probed
> > > and if NAND supports ONFI, NAND memory organization is read from ONFI
> > > parameter page otherwise "READ ID" is used.
> > > 
> > > Currently only implemented for i.MX6 familly of SoCs.
> > > 
> > > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > > Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
> > > Signed-off-by: Andrej Picej <andrej.picej at norik.com>
> > > ---
> > >   arch/arm/mach-imx/Makefile             |    2 +-
> > >   arch/arm/mach-imx/include/mach/xload.h |    1 +
> > >   arch/arm/mach-imx/xload-gpmi-nand.c    | 1163 ++++++++++++++++++++++++
> > >   3 files changed, 1165 insertions(+), 1 deletion(-)
> > >   create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c
> > > 
> > > diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> > > index e45f758e9..d94c846a1 100644
> > > --- a/arch/arm/mach-imx/Makefile
> > > +++ b/arch/arm/mach-imx/Makefile
> > > +static int mxs_nand_get_info(struct mxs_nand_info *info, void *databuf)
> > > +{
> > > +	int ret, i;
> > > +
> > > +	ret = mxs_nand_check_onfi(info, databuf);
> > > +	if (ret) {
> > > +		if (ret != 1)
> > > +			return ret;
> > > +		pr_warn("ONFI not supported, try \"READ ID\"...\n");
> > 
> > You already printed a "ONFI not supported\n" message. Printing it once
> > is enough. Also this message appears with every non-ONFI nand, right? In
> > that case it should rather be pr_info()
> 
> OK, I agree, will fix it in v2.
> 
> > 
> > > +	/*
> > > +	 * If ONFI is not supported or if it fails try to get NAND's info from
> > > +	 * "READ ID" command.
> > > +	 */
> > > +	pr_debug("Trying \"READ ID\" command...\n");
> > > +	ret = mxs_nand_get_readid(info, databuf);
> > > +	if (ret) {
> > > +		if (ret != -EOVERFLOW)
> > > +			return ret;
> > > +
> > > +		/*
> > > +		 * If NAND's "READ ID" returns bad values, try to set them to
> > > +		 * default (most common NAND memory org.) and continue.
> > > +		 */
> > > +		pr_warn("NANDs READ ID command returned bad values" \
> > > +			" set them to default and try to continue!\n");
> > > +		info->organization.pagesize = 2048;
> > > +		info->organization.oobsize = 64;
> > > +		info->nand_size = SZ_1G;
> > 
> > Is this worth it? READ ID is the most basic command, when this doesn't
> > work I don't think there's a point in continuing.
> 
> We had a case with Samsung K9K8G08U0E when sometimes (reasons not known) the
> 5th byte returned 0xff instead of correct values, all other returned values
> were correct. In this case the device booted successfully because of this
> hook. Maybe a better solution would be to check only the 5th byte for 0xff
> value (5th byte is not supported from all NAND vendors), if this is the case
> set the NAND size to 1GB.
> Would that make more sense?

The best would be to track the issue down and to fix it ;)
It's not very nice to assume it in case of read id failures it's exactly
that NAND type you have troubles with.
Does it help to reset the NAND chip before reading the ID?

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Mon Jan 25 04:21:25 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Mon, 25 Jan 2021 10:21:25 +0100
Subject: AM335x NAND write hungs
In-Reply-To: <CAP1tNvSGFXWxVKoQanR9S6FxjV_U0DUMrkL-C1Bg7Ze5TaS1+w@mail.gmail.com>
References: <CAP1tNvT79QvYYTL9O+V+HR=XVTKHS=UxJtc1ZvNaMu1yQZns9w@mail.gmail.com>
 <a8d24265-a9e7-c521-c0b1-cc8e0691d636@pengutronix.de>
 <CAP1tNvSGFXWxVKoQanR9S6FxjV_U0DUMrkL-C1Bg7Ze5TaS1+w@mail.gmail.com>
Message-ID: <b5da0650-b5a0-a81b-a2e6-5a24ae1c81a5@pengutronix.de>

On 25.01.21 09:56, Alexander Shiyan wrote:
> Works as expected.
> Can you commit this change into master?

I'd prefer Sascha did that (after confirming that's
the correct fix).

> Thanks!
> 
> ??, 25 ???. 2021 ?. ? 11:37, Ahmad Fatoum <a.fatoum at pengutronix.de>:
>>
>> Hello,
>>
>> On 25.01.21 09:20, Alexander Shiyan wrote:
>>> Hello.
>>>
>>> I recently upgraded my barebox from 2020.11 to 2021.01 for a custom board
>>> based on TI AM335x processor.
>>> The update revealed the inoperability of writing to NAND. When trying to write,
>>> the bootloader hangs forever.
>>> Reverting the commit "mtd: nand: omap_gpmc: Fix wrong length check" helps
>>> to solve the problem.
>>
>> What happens when changing the condition to len > 0?
>>
>>> Does anyone have similar problems?
>>>
>>> Thanks!
>>>
>>> _______________________________________________
>>> barebox mailing list
>>> barebox at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/barebox
>>>
>>
>> --
>> Pengutronix e.K.                           |                             |
>> Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
>> 31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
>> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.hauer at pengutronix.de  Mon Jan 25 04:21:36 2021
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Mon, 25 Jan 2021 10:21:36 +0100
Subject: [PATCH] mtd: nand: omap_gpmc: Fix wrong length check for real
In-Reply-To: <CAP1tNvT79QvYYTL9O+V+HR=XVTKHS=UxJtc1ZvNaMu1yQZns9w@mail.gmail.com>
References: <CAP1tNvT79QvYYTL9O+V+HR=XVTKHS=UxJtc1ZvNaMu1yQZns9w@mail.gmail.com>
Message-ID: <20210125092136.32404-1-s.hauer@pengutronix.de>

Check for length > 0 because otherwise len may become smaller than
0 in which case the loop never ends.

Reported-by: Alexander Shiyan <eagle.alexander923 at gmail.com>
Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 drivers/mtd/nand/nand_omap_gpmc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c
index db1ca88791..0f3ffa1c0e 100644
--- a/drivers/mtd/nand/nand_omap_gpmc.c
+++ b/drivers/mtd/nand/nand_omap_gpmc.c
@@ -636,7 +636,7 @@ static void omap_write_buf_pref(struct nand_chip *nand_chip,
 	gpmc_prefetch_enable(info->gpmc_cs,
 			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1);
 
-	while (len) {
+	while (len > 0) {
 		w_count = readl(info->gpmc_base + GPMC_PREFETCH_STATUS);
 		w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
 		w_count = w_count >> 2;
-- 
2.20.1



From andrej.picej at norik.com  Mon Jan 25 04:43:57 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Mon, 25 Jan 2021 10:43:57 +0100
Subject: [PATCH 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <20210125091547.GB8233@pengutronix.de>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-3-andrej.picej@norik.com>
 <20210121090148.GF19063@pengutronix.de>
 <7df4659e-7237-c5fa-767f-7dedd5c44005@norik.com>
 <20210125091547.GB8233@pengutronix.de>
Message-ID: <200bfc2a-e616-0e34-b2c4-91ef67915836@norik.com>

On 25. 01. 21 10:15, Sascha Hauer wrote:
> On Thu, Jan 21, 2021 at 11:28:39AM +0100, Andrej Picej wrote:
>> Hi Sascha,
>>
>> thanks for your comments.
>>
>> Responses inline.
>>
>> On 21. 01. 21 10:01, Sascha Hauer wrote:
>>> Hi Andrej,
>>>
>>> Some comments inline.
>>>
>>> On Wed, Jan 20, 2021 at 01:51:06PM +0100, Andrej Picej wrote:
>>>> From: Sascha Hauer <s.hauer at pengutronix.de>
>>>>
>>>> Commit is based on initial Sascha Hauer's work. It implements PBL xload
>>>> mechanism to load image from GPMI NAND flash.
>>>>
>>>> Additional work was done, so that the NAND's size, page size and OOB's
>>>> size are autodetected and not hardcoded. Detection method follows the
>>>> same methods as used in NAND driver, meaning NAND ONFI support is probed
>>>> and if NAND supports ONFI, NAND memory organization is read from ONFI
>>>> parameter page otherwise "READ ID" is used.
>>>>
>>>> Currently only implemented for i.MX6 familly of SoCs.
>>>>
>>>> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
>>>> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
>>>> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
>>>> ---
>>>>    arch/arm/mach-imx/Makefile             |    2 +-
>>>>    arch/arm/mach-imx/include/mach/xload.h |    1 +
>>>>    arch/arm/mach-imx/xload-gpmi-nand.c    | 1163 ++++++++++++++++++++++++
>>>>    3 files changed, 1165 insertions(+), 1 deletion(-)
>>>>    create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c
>>>>
>>>> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
>>>> index e45f758e9..d94c846a1 100644
>>>> --- a/arch/arm/mach-imx/Makefile
>>>> +++ b/arch/arm/mach-imx/Makefile
>>>> +static int mxs_nand_get_info(struct mxs_nand_info *info, void *databuf)
>>>> +{
>>>> +	int ret, i;
>>>> +
>>>> +	ret = mxs_nand_check_onfi(info, databuf);
>>>> +	if (ret) {
>>>> +		if (ret != 1)
>>>> +			return ret;
>>>> +		pr_warn("ONFI not supported, try \"READ ID\"...\n");
>>>
>>> You already printed a "ONFI not supported\n" message. Printing it once
>>> is enough. Also this message appears with every non-ONFI nand, right? In
>>> that case it should rather be pr_info()
>>
>> OK, I agree, will fix it in v2.
>>
>>>
>>>> +	/*
>>>> +	 * If ONFI is not supported or if it fails try to get NAND's info from
>>>> +	 * "READ ID" command.
>>>> +	 */
>>>> +	pr_debug("Trying \"READ ID\" command...\n");
>>>> +	ret = mxs_nand_get_readid(info, databuf);
>>>> +	if (ret) {
>>>> +		if (ret != -EOVERFLOW)
>>>> +			return ret;
>>>> +
>>>> +		/*
>>>> +		 * If NAND's "READ ID" returns bad values, try to set them to
>>>> +		 * default (most common NAND memory org.) and continue.
>>>> +		 */
>>>> +		pr_warn("NANDs READ ID command returned bad values" \
>>>> +			" set them to default and try to continue!\n");
>>>> +		info->organization.pagesize = 2048;
>>>> +		info->organization.oobsize = 64;
>>>> +		info->nand_size = SZ_1G;
>>>
>>> Is this worth it? READ ID is the most basic command, when this doesn't
>>> work I don't think there's a point in continuing.
>>
>> We had a case with Samsung K9K8G08U0E when sometimes (reasons not known) the
>> 5th byte returned 0xff instead of correct values, all other returned values
>> were correct. In this case the device booted successfully because of this
>> hook. Maybe a better solution would be to check only the 5th byte for 0xff
>> value (5th byte is not supported from all NAND vendors), if this is the case
>> set the NAND size to 1GB.
>> Would that make more sense?
> 
> The best would be to track the issue down and to fix it ;)
> It's not very nice to assume it in case of read id failures it's exactly
> that NAND type you have troubles with.
> Does it help to reset the NAND chip before reading the ID?
> 
> Sascha
> 

I totally agree with fixing the issue and will look into it a bit more.
I will reset the NAND before reading the ID in the same way as it is 
done before reading parameter page. I will leave the testing on over 
night (reading the ID failed in about 1 out of 500 boots) and report the 
results tomorrow.

BR,
Andrej


From sha at pengutronix.de  Mon Jan 25 04:52:42 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 25 Jan 2021 10:52:42 +0100
Subject: [PATCH 10/13] of: of_firmware: add support for fpga bridges
In-Reply-To: <20210121112958.25937-10-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
 <20210121112958.25937-10-str@pengutronix.de>
Message-ID: <20210125095242.GD31738@pengutronix.de>

On Thu, Jan 21, 2021 at 12:29:55PM +0100, Steffen Trumtrar wrote:
> From: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> 
> Add support for potentially defined FPGA-bridges in the overlay.
> 
> While at it also add support for loading the firmware directly via a
> path instead of 'needing' an overlay for that.
> The direct loading will be done with the existent firmwareload command.
> 
> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> ---
>  drivers/of/Makefile      |  3 +-
>  drivers/of/of_firmware.c | 88 ++++++++++++++++++++++++++++++++++++----
>  include/of.h             | 21 +++++++---
>  3 files changed, 96 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index b6847752d2..6199c9791f 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -6,4 +6,5 @@ obj-y += partition.o
>  obj-y += of_net.o
>  obj-$(CONFIG_MTD) += of_mtd.o
>  obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o
> -obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o of_firmware.o
> +obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o
> +obj-$(CONFIG_FIRMWARE) += of_firmware.o
> diff --git a/drivers/of/of_firmware.c b/drivers/of/of_firmware.c
> index 096f84572e..ef0ccd0221 100644
> --- a/drivers/of/of_firmware.c
> +++ b/drivers/of/of_firmware.c
> @@ -4,12 +4,52 @@
>   */
>  #include <common.h>
>  #include <firmware.h>
> +#include <fpga-bridge.h>
>  #include <of.h>
>  
>  struct overlay_info {
>  	const char *firmware_path;
>  };
>  
> +#ifdef CONFIG_FPGA_BRIDGE 

Trailing whitespace here.

> +int of_firmware_load_file(const char *path)
> +{
> +	int err;
> +	struct device_node *target;
> +
> +	target = of_find_compatible_node(NULL, NULL, "fpga-region");

This assumes there is only one node compatible to fpga-region. What
about others?

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Jan 25 04:53:39 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 25 Jan 2021 10:53:39 +0100
Subject: [PATCH] usb: hub: fix state change check for not powercycled ports
In-Reply-To: <20210118190923.531-1-m.grzeschik@pengutronix.de>
References: <20210118190923.531-1-m.grzeschik@pengutronix.de>
Message-ID: <20210125095339.GE31738@pengutronix.de>

On Mon, Jan 18, 2021 at 08:09:23PM +0100, Michael Grzeschik wrote:
> Since we don't power cycle the ports on start since patch "19bb0b2a usb:
> hub: Do not power-cycle usb devices on init" it is possible that the
> device on this port is already active from a previous enumeration. This
> way barebox will never get any change in USB_PORT_STAT_C_CONNECTION bit
> change.
> 
> Although the device will probably still work fine after the following
> port reset, the current code will always miss reenumerating these still
> plugged devices. This patch fixes this by ignoring the check for
> STAT_C_CONNECTION bit and only go for USB_PORT_STAT_CONNECTION which
> should be enough.
> 
> Signed-off-by: Michael Grzeschik <m.grzeschik at pengutronix.de>
> ---
>  drivers/usb/core/hub.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
> index 01653d8c20..d1112248ee 100644
> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -336,8 +336,7 @@ static void usb_scan_port(struct usb_device_scan *usb_scan)
>  	dev_dbg(&dev->dev, "port%d: Status 0x%04x Change 0x%04x\n",
>  			port + 1, portstatus, portchange);
>  
> -	if (!(portchange & USB_PORT_STAT_C_CONNECTION) ||
> -	    !(portstatus & USB_PORT_STAT_CONNECTION)) {
> +	if (!(portstatus & USB_PORT_STAT_CONNECTION)) {
>  		if (get_time_ns() >= hub->connect_timeout) {
>  			dev_dbg(&dev->dev, "port%d: timeout\n", port + 1);
>  			/* Remove this device from scanning list */
> -- 
> 2.30.0
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Mon Jan 25 04:56:06 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 25 Jan 2021 10:56:06 +0100
Subject: [PATCH 01/13] ARM: add fncpy.h from linux v4.6
In-Reply-To: <20210121112958.25937-1-str@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
Message-ID: <20210125095606.GF31738@pengutronix.de>

On Thu, Jan 21, 2021 at 12:29:46PM +0100, Steffen Trumtrar wrote:
> From: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> 
> Description from the linux commit 5756e9dd0de6d5c307773f8f734c0684b3098fdd:
> 
>     ARM: 6640/1: Thumb-2: Symbol manipulation macros for function body copying
> 
>     In low-level board support code, there is sometimes a need to
>     copy a function body to another location at run-time.
> 
>     A straightforward call to memcpy doesn't work in Thumb-2,
>     because bit 0 of external Thumb function symbols is set to 1,
>     indicating that the function is Thumb.  Without corrective
>     measures, this will cause an off-by-one copy, and the copy
>     may be called using the wrong instruction set.
> 
>     This patch adds an fncpy() macro to help with such copies.
> 
>     Particular care is needed, because C doesn't guarantee any
>     defined behaviour when casting a function pointer to any other
>     type.  This has been observed to lead to strange optimisation
>     side-effects when doing the arithmetic which is required in
>     order to copy/move function bodies correctly in Thumb-2.
> 
>     Thanks to Russell King and Nicolas Pitre for their input
>     on this patch.
> 
> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> ---
>  arch/arm/include/asm/fncpy.h | 82 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 82 insertions(+)
>  create mode 100644 arch/arm/include/asm/fncpy.h

Applied this patch for now, but with an update to v5.10 with the only
change that the licence header is changed to SPDX now.

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From shc_work at mail.ru  Mon Jan 25 05:00:47 2021
From: shc_work at mail.ru (Alexander Shiyan)
Date: Mon, 25 Jan 2021 13:00:47 +0300
Subject: [PATCH] ARM: dts: imx6qdl: pfla02: Use NAND pinmux entries from
 upstream
Message-ID: <20210125100047.7498-1-shc_work@mail.ru>

The gpminand pinmux entries are in the upstream dtsi now, so use them.

Signed-off-by: Alexander Shiyan <shc_work at mail.ru>
---
 arch/arm/dts/imx6qdl-phytec-pfla02.dtsi | 24 ------------------------
 1 file changed, 24 deletions(-)

diff --git a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
index f499ca568..e1aa3183b 100644
--- a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
+++ b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
@@ -127,30 +127,6 @@
 				MX6QDL_PAD_SD4_DAT7__GPIO2_IO15	0x80000000
 			>;
 		};
-
-		pinctrl_gpmi_nand: gpminandgrp {
-			fsl,pins = <
-				MX6QDL_PAD_NANDF_CLE__NAND_CLE     0xb0b1
-				MX6QDL_PAD_NANDF_ALE__NAND_ALE     0xb0b1
-				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
-				MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
-				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
-				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
-				MX6QDL_PAD_NANDF_CS2__NAND_CE2_B   0xb0b1
-				MX6QDL_PAD_NANDF_CS3__NAND_CE3_B   0xb0b1
-				MX6QDL_PAD_SD4_CMD__NAND_RE_B      0xb0b1
-				MX6QDL_PAD_SD4_CLK__NAND_WE_B      0xb0b1
-				MX6QDL_PAD_NANDF_D0__NAND_DATA00   0xb0b1
-				MX6QDL_PAD_NANDF_D1__NAND_DATA01   0xb0b1
-				MX6QDL_PAD_NANDF_D2__NAND_DATA02   0xb0b1
-				MX6QDL_PAD_NANDF_D3__NAND_DATA03   0xb0b1
-				MX6QDL_PAD_NANDF_D4__NAND_DATA04   0xb0b1
-				MX6QDL_PAD_NANDF_D5__NAND_DATA05   0xb0b1
-				MX6QDL_PAD_NANDF_D6__NAND_DATA06   0xb0b1
-				MX6QDL_PAD_NANDF_D7__NAND_DATA07   0xb0b1
-				MX6QDL_PAD_SD4_DAT0__NAND_DQS      0x00b1
-			>;
-		};
 	};
 };
 
-- 
2.26.2



From sha at pengutronix.de  Mon Jan 25 05:12:24 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Mon, 25 Jan 2021 11:12:24 +0100
Subject: [PATCH] ARM: dts: imx6qdl: pfla02: Use NAND pinmux entries from
 upstream
In-Reply-To: <20210125100047.7498-1-shc_work@mail.ru>
References: <20210125100047.7498-1-shc_work@mail.ru>
Message-ID: <20210125101224.GG31738@pengutronix.de>

On Mon, Jan 25, 2021 at 01:00:47PM +0300, Alexander Shiyan wrote:
> The gpminand pinmux entries are in the upstream dtsi now, so use them.
> 
> Signed-off-by: Alexander Shiyan <shc_work at mail.ru>
> ---
>  arch/arm/dts/imx6qdl-phytec-pfla02.dtsi | 24 ------------------------
>  1 file changed, 24 deletions(-)

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
> index f499ca568..e1aa3183b 100644
> --- a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
> +++ b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
> @@ -127,30 +127,6 @@
>  				MX6QDL_PAD_SD4_DAT7__GPIO2_IO15	0x80000000
>  			>;
>  		};
> -
> -		pinctrl_gpmi_nand: gpminandgrp {
> -			fsl,pins = <
> -				MX6QDL_PAD_NANDF_CLE__NAND_CLE     0xb0b1
> -				MX6QDL_PAD_NANDF_ALE__NAND_ALE     0xb0b1
> -				MX6QDL_PAD_NANDF_WP_B__NAND_WP_B   0xb0b1
> -				MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
> -				MX6QDL_PAD_NANDF_CS0__NAND_CE0_B   0xb0b1
> -				MX6QDL_PAD_NANDF_CS1__NAND_CE1_B   0xb0b1
> -				MX6QDL_PAD_NANDF_CS2__NAND_CE2_B   0xb0b1
> -				MX6QDL_PAD_NANDF_CS3__NAND_CE3_B   0xb0b1
> -				MX6QDL_PAD_SD4_CMD__NAND_RE_B      0xb0b1
> -				MX6QDL_PAD_SD4_CLK__NAND_WE_B      0xb0b1
> -				MX6QDL_PAD_NANDF_D0__NAND_DATA00   0xb0b1
> -				MX6QDL_PAD_NANDF_D1__NAND_DATA01   0xb0b1
> -				MX6QDL_PAD_NANDF_D2__NAND_DATA02   0xb0b1
> -				MX6QDL_PAD_NANDF_D3__NAND_DATA03   0xb0b1
> -				MX6QDL_PAD_NANDF_D4__NAND_DATA04   0xb0b1
> -				MX6QDL_PAD_NANDF_D5__NAND_DATA05   0xb0b1
> -				MX6QDL_PAD_NANDF_D6__NAND_DATA06   0xb0b1
> -				MX6QDL_PAD_NANDF_D7__NAND_DATA07   0xb0b1
> -				MX6QDL_PAD_SD4_DAT0__NAND_DQS      0x00b1
> -			>;
> -		};
>  	};
>  };
>  
> -- 
> 2.26.2
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From s.trumtrar at pengutronix.de  Tue Jan 26 03:47:07 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Tue, 26 Jan 2021 09:47:07 +0100
Subject: [PATCH 10/13] of: of_firmware: add support for fpga bridges
In-Reply-To: <20210125095242.GD31738@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
 <20210121112958.25937-10-str@pengutronix.de>
 <20210125095242.GD31738@pengutronix.de>
Message-ID: <87sg6ot790.fsf@pengutronix.de>


Sascha Hauer <sha at pengutronix.de> writes:

> On Thu, Jan 21, 2021 at 12:29:55PM +0100, Steffen Trumtrar wrote:
>> From: Steffen Trumtrar <s.trumtrar at pengutronix.de>
>>
>> Add support for potentially defined FPGA-bridges in the overlay.
>>
>> While at it also add support for loading the firmware directly via a
>> path instead of 'needing' an overlay for that.
>> The direct loading will be done with the existent firmwareload command.
>>
>> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
>> ---
>>  drivers/of/Makefile      |  3 +-
>>  drivers/of/of_firmware.c | 88 ++++++++++++++++++++++++++++++++++++----
>>  include/of.h             | 21 +++++++---
>>  3 files changed, 96 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
>> index b6847752d2..6199c9791f 100644
>> --- a/drivers/of/Makefile
>> +++ b/drivers/of/Makefile
>> @@ -6,4 +6,5 @@ obj-y += partition.o
>>  obj-y += of_net.o
>>  obj-$(CONFIG_MTD) += of_mtd.o
>>  obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o
>> -obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o of_firmware.o
>> +obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o
>> +obj-$(CONFIG_FIRMWARE) += of_firmware.o
>> diff --git a/drivers/of/of_firmware.c b/drivers/of/of_firmware.c
>> index 096f84572e..ef0ccd0221 100644
>> --- a/drivers/of/of_firmware.c
>> +++ b/drivers/of/of_firmware.c
>> @@ -4,12 +4,52 @@
>>   */
>>  #include <common.h>
>>  #include <firmware.h>
>> +#include <fpga-bridge.h>
>>  #include <of.h>
>>
>>  struct overlay_info {
>>  	const char *firmware_path;
>>  };
>>
>> +#ifdef CONFIG_FPGA_BRIDGE
>
> Trailing whitespace here.
>

Meh :(

>> +int of_firmware_load_file(const char *path)
>> +{
>> +	int err;
>> +	struct device_node *target;
>> +
>> +	target = of_find_compatible_node(NULL, NULL, "fpga-region");
>
> This assumes there is only one node compatible to fpga-region. What
> about others?

Ah, right, it is actually allowed to have multiple regions in one FPGA.
I didn't think about that.


Steffen

--
Pengutronix e.K.                | Dipl.-Inform. Steffen Trumtrar |
Steuerwalder Str. 21            | https://www.pengutronix.de/    |
31137 Hildesheim, Germany       | Phone: +49-5121-206917-0       |
Amtsgericht Hildesheim, HRA 2686| Fax:   +49-5121-206917-5555    |


From sha at pengutronix.de  Tue Jan 26 06:02:02 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 26 Jan 2021 12:02:02 +0100
Subject: [PATCH 10/13] of: of_firmware: add support for fpga bridges
In-Reply-To: <87sg6ot790.fsf@pengutronix.de>
References: <20210121112958.25937-1-str@pengutronix.de>
 <20210121112958.25937-10-str@pengutronix.de>
 <20210125095242.GD31738@pengutronix.de>
 <87sg6ot790.fsf@pengutronix.de>
Message-ID: <20210126110202.GC28722@pengutronix.de>

On Tue, Jan 26, 2021 at 09:47:07AM +0100, Steffen Trumtrar wrote:
> 
> Sascha Hauer <sha at pengutronix.de> writes:
> 
> > On Thu, Jan 21, 2021 at 12:29:55PM +0100, Steffen Trumtrar wrote:
> >> From: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> >>
> >> Add support for potentially defined FPGA-bridges in the overlay.
> >>
> >> While at it also add support for loading the firmware directly via a
> >> path instead of 'needing' an overlay for that.
> >> The direct loading will be done with the existent firmwareload command.
> >>
> >> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> >> ---
> >>  drivers/of/Makefile      |  3 +-
> >>  drivers/of/of_firmware.c | 88 ++++++++++++++++++++++++++++++++++++----
> >>  include/of.h             | 21 +++++++---
> >>  3 files changed, 96 insertions(+), 16 deletions(-)
> >>
> >> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> >> index b6847752d2..6199c9791f 100644
> >> --- a/drivers/of/Makefile
> >> +++ b/drivers/of/Makefile
> >> @@ -6,4 +6,5 @@ obj-y += partition.o
> >>  obj-y += of_net.o
> >>  obj-$(CONFIG_MTD) += of_mtd.o
> >>  obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o
> >> -obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o of_firmware.o
> >> +obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o
> >> +obj-$(CONFIG_FIRMWARE) += of_firmware.o
> >> diff --git a/drivers/of/of_firmware.c b/drivers/of/of_firmware.c
> >> index 096f84572e..ef0ccd0221 100644
> >> --- a/drivers/of/of_firmware.c
> >> +++ b/drivers/of/of_firmware.c
> >> @@ -4,12 +4,52 @@
> >>   */
> >>  #include <common.h>
> >>  #include <firmware.h>
> >> +#include <fpga-bridge.h>
> >>  #include <of.h>
> >>
> >>  struct overlay_info {
> >>  	const char *firmware_path;
> >>  };
> >>
> >> +#ifdef CONFIG_FPGA_BRIDGE
> >
> > Trailing whitespace here.
> >
> 
> Meh :(
> 
> >> +int of_firmware_load_file(const char *path)
> >> +{
> >> +	int err;
> >> +	struct device_node *target;
> >> +
> >> +	target = of_find_compatible_node(NULL, NULL, "fpga-region");
> >
> > This assumes there is only one node compatible to fpga-region. What
> > about others?
> 
> Ah, right, it is actually allowed to have multiple regions in one FPGA.
> I didn't think about that.

Also multiple regions in multiple FPGAs

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From andrej.picej at norik.com  Tue Jan 26 06:40:17 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Tue, 26 Jan 2021 12:40:17 +0100
Subject: [PATCH 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <200bfc2a-e616-0e34-b2c4-91ef67915836@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-3-andrej.picej@norik.com>
 <20210121090148.GF19063@pengutronix.de>
 <7df4659e-7237-c5fa-767f-7dedd5c44005@norik.com>
 <20210125091547.GB8233@pengutronix.de>
 <200bfc2a-e616-0e34-b2c4-91ef67915836@norik.com>
Message-ID: <da704371-9ad7-e42d-675c-08a34afa5159@norik.com>


On 25. 01. 21 10:43, Andrej Picej wrote:
> On 25. 01. 21 10:15, Sascha Hauer wrote:
>> On Thu, Jan 21, 2021 at 11:28:39AM +0100, Andrej Picej wrote:
>>> Hi Sascha,
>>>
>>> thanks for your comments.
>>>
>>> Responses inline.
>>>
>>> On 21. 01. 21 10:01, Sascha Hauer wrote:
>>>> Hi Andrej,
>>>>
>>>> Some comments inline.
>>>>
>>>> On Wed, Jan 20, 2021 at 01:51:06PM +0100, Andrej Picej wrote:
>>>>> From: Sascha Hauer <s.hauer at pengutronix.de>
>>>>>
>>>>> Commit is based on initial Sascha Hauer's work. It implements PBL 
>>>>> xload
>>>>> mechanism to load image from GPMI NAND flash.
>>>>>
>>>>> Additional work was done, so that the NAND's size, page size and OOB's
>>>>> size are autodetected and not hardcoded. Detection method follows the
>>>>> same methods as used in NAND driver, meaning NAND ONFI support is 
>>>>> probed
>>>>> and if NAND supports ONFI, NAND memory organization is read from ONFI
>>>>> parameter page otherwise "READ ID" is used.
>>>>>
>>>>> Currently only implemented for i.MX6 familly of SoCs.
>>>>>
>>>>> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
>>>>> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
>>>>> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
>>>>> ---
>>>>> ?? arch/arm/mach-imx/Makefile???????????? |??? 2 +-
>>>>> ?? arch/arm/mach-imx/include/mach/xload.h |??? 1 +
>>>>> ?? arch/arm/mach-imx/xload-gpmi-nand.c??? | 1163 
>>>>> ++++++++++++++++++++++++
>>>>> ?? 3 files changed, 1165 insertions(+), 1 deletion(-)
>>>>> ?? create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c
>>>>>
>>>>> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
>>>>> index e45f758e9..d94c846a1 100644
>>>>> --- a/arch/arm/mach-imx/Makefile
>>>>> +++ b/arch/arm/mach-imx/Makefile
>>>>> +static int mxs_nand_get_info(struct mxs_nand_info *info, void 
>>>>> *databuf)
>>>>> +{
>>>>> +??? int ret, i;
>>>>> +
>>>>> +??? ret = mxs_nand_check_onfi(info, databuf);
>>>>> +??? if (ret) {
>>>>> +??????? if (ret != 1)
>>>>> +??????????? return ret;
>>>>> +??????? pr_warn("ONFI not supported, try \"READ ID\"...\n");
>>>>
>>>> You already printed a "ONFI not supported\n" message. Printing it once
>>>> is enough. Also this message appears with every non-ONFI nand, 
>>>> right? In
>>>> that case it should rather be pr_info()
>>>
>>> OK, I agree, will fix it in v2.
>>>
>>>>
>>>>> +??? /*
>>>>> +???? * If ONFI is not supported or if it fails try to get NAND's 
>>>>> info from
>>>>> +???? * "READ ID" command.
>>>>> +???? */
>>>>> +??? pr_debug("Trying \"READ ID\" command...\n");
>>>>> +??? ret = mxs_nand_get_readid(info, databuf);
>>>>> +??? if (ret) {
>>>>> +??????? if (ret != -EOVERFLOW)
>>>>> +??????????? return ret;
>>>>> +
>>>>> +??????? /*
>>>>> +???????? * If NAND's "READ ID" returns bad values, try to set them to
>>>>> +???????? * default (most common NAND memory org.) and continue.
>>>>> +???????? */
>>>>> +??????? pr_warn("NANDs READ ID command returned bad values" \
>>>>> +??????????? " set them to default and try to continue!\n");
>>>>> +??????? info->organization.pagesize = 2048;
>>>>> +??????? info->organization.oobsize = 64;
>>>>> +??????? info->nand_size = SZ_1G;
>>>>
>>>> Is this worth it? READ ID is the most basic command, when this doesn't
>>>> work I don't think there's a point in continuing.
>>>
>>> We had a case with Samsung K9K8G08U0E when sometimes (reasons not 
>>> known) the
>>> 5th byte returned 0xff instead of correct values, all other returned 
>>> values
>>> were correct. In this case the device booted successfully because of 
>>> this
>>> hook. Maybe a better solution would be to check only the 5th byte for 
>>> 0xff
>>> value (5th byte is not supported from all NAND vendors), if this is 
>>> the case
>>> set the NAND size to 1GB.
>>> Would that make more sense?
>>
>> The best would be to track the issue down and to fix it ;)
>> It's not very nice to assume it in case of read id failures it's exactly
>> that NAND type you have troubles with.
>> Does it help to reset the NAND chip before reading the ID?
>>
>> Sascha
>>
> 
> I totally agree with fixing the issue and will look into it a bit more.
> I will reset the NAND before reading the ID in the same way as it is 
> done before reading parameter page. I will leave the testing on over 
> night (reading the ID failed in about 1 out of 500 boots) and report the 
> results tomorrow.
> 

I guess resetting fixed this problem, I got 50.000 boots without any 
problems. Will fix this in v2 :).

Should I now completely abandon setting the NANDs memory to default 
values and just return error on failure?
Something like this:

> 	/*
> 	 * If ONFI is not supported or if it fails try to get NAND's info from
> 	 * "READ ID" command.
> 	 */
> 	ret = mxs_nand_reset(info, databuf);
> 	if (ret)
> 		return ret;
> 	pr_debug("Trying \"READ ID\" command...\n");
> 	ret = mxs_nand_get_readid(info, databuf);
> 	if (ret) {
> 		pr_err("xloader supports only ONFI and generic \"READ ID\" " \
> 			"supported NANDs\n");
> 		return -1;
> 	}

I'm asking this because NANDs ID command is manufacturer specific, some 
manufacturers follow generic values and other unfortunately don't. In 
barebox NAND driver decoding is done based on manufacturer. I guess we 
could do the same here but I don't want to expand the PBL part too much 
just for reading FCB, where all NAND's memory parameters are decoded from.

BR,
Andrej


From sha at pengutronix.de  Tue Jan 26 07:08:30 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Tue, 26 Jan 2021 13:08:30 +0100
Subject: [PATCH 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <da704371-9ad7-e42d-675c-08a34afa5159@norik.com>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-3-andrej.picej@norik.com>
 <20210121090148.GF19063@pengutronix.de>
 <7df4659e-7237-c5fa-767f-7dedd5c44005@norik.com>
 <20210125091547.GB8233@pengutronix.de>
 <200bfc2a-e616-0e34-b2c4-91ef67915836@norik.com>
 <da704371-9ad7-e42d-675c-08a34afa5159@norik.com>
Message-ID: <20210126120830.GE28722@pengutronix.de>

On Tue, Jan 26, 2021 at 12:40:17PM +0100, Andrej Picej wrote:
> 
> On 25. 01. 21 10:43, Andrej Picej wrote:
> > On 25. 01. 21 10:15, Sascha Hauer wrote:
> > > On Thu, Jan 21, 2021 at 11:28:39AM +0100, Andrej Picej wrote:
> > > > Hi Sascha,
> > > > 
> > > > thanks for your comments.
> > > > 
> > > > Responses inline.
> > > > 
> > > > On 21. 01. 21 10:01, Sascha Hauer wrote:
> > > > > Hi Andrej,
> > > > > 
> > > > > Some comments inline.
> > > > > 
> > > > > On Wed, Jan 20, 2021 at 01:51:06PM +0100, Andrej Picej wrote:
> > > > > > From: Sascha Hauer <s.hauer at pengutronix.de>
> > > > > > 
> > > > > > Commit is based on initial Sascha Hauer's work. It
> > > > > > implements PBL xload
> > > > > > mechanism to load image from GPMI NAND flash.
> > > > > > 
> > > > > > Additional work was done, so that the NAND's size, page size and OOB's
> > > > > > size are autodetected and not hardcoded. Detection method follows the
> > > > > > same methods as used in NAND driver, meaning NAND ONFI
> > > > > > support is probed
> > > > > > and if NAND supports ONFI, NAND memory organization is read from ONFI
> > > > > > parameter page otherwise "READ ID" is used.
> > > > > > 
> > > > > > Currently only implemented for i.MX6 familly of SoCs.
> > > > > > 
> > > > > > Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
> > > > > > Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
> > > > > > Signed-off-by: Andrej Picej <andrej.picej at norik.com>
> > > > > > ---
> > > > > > ?? arch/arm/mach-imx/Makefile???????????? |??? 2 +-
> > > > > > ?? arch/arm/mach-imx/include/mach/xload.h |??? 1 +
> > > > > > ?? arch/arm/mach-imx/xload-gpmi-nand.c??? | 1163
> > > > > > ++++++++++++++++++++++++
> > > > > > ?? 3 files changed, 1165 insertions(+), 1 deletion(-)
> > > > > > ?? create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c
> > > > > > 
> > > > > > diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> > > > > > index e45f758e9..d94c846a1 100644
> > > > > > --- a/arch/arm/mach-imx/Makefile
> > > > > > +++ b/arch/arm/mach-imx/Makefile
> > > > > > +static int mxs_nand_get_info(struct mxs_nand_info
> > > > > > *info, void *databuf)
> > > > > > +{
> > > > > > +??? int ret, i;
> > > > > > +
> > > > > > +??? ret = mxs_nand_check_onfi(info, databuf);
> > > > > > +??? if (ret) {
> > > > > > +??????? if (ret != 1)
> > > > > > +??????????? return ret;
> > > > > > +??????? pr_warn("ONFI not supported, try \"READ ID\"...\n");
> > > > > 
> > > > > You already printed a "ONFI not supported\n" message. Printing it once
> > > > > is enough. Also this message appears with every non-ONFI
> > > > > nand, right? In
> > > > > that case it should rather be pr_info()
> > > > 
> > > > OK, I agree, will fix it in v2.
> > > > 
> > > > > 
> > > > > > +??? /*
> > > > > > +???? * If ONFI is not supported or if it fails try to
> > > > > > get NAND's info from
> > > > > > +???? * "READ ID" command.
> > > > > > +???? */
> > > > > > +??? pr_debug("Trying \"READ ID\" command...\n");
> > > > > > +??? ret = mxs_nand_get_readid(info, databuf);
> > > > > > +??? if (ret) {
> > > > > > +??????? if (ret != -EOVERFLOW)
> > > > > > +??????????? return ret;
> > > > > > +
> > > > > > +??????? /*
> > > > > > +???????? * If NAND's "READ ID" returns bad values, try to set them to
> > > > > > +???????? * default (most common NAND memory org.) and continue.
> > > > > > +???????? */
> > > > > > +??????? pr_warn("NANDs READ ID command returned bad values" \
> > > > > > +??????????? " set them to default and try to continue!\n");
> > > > > > +??????? info->organization.pagesize = 2048;
> > > > > > +??????? info->organization.oobsize = 64;
> > > > > > +??????? info->nand_size = SZ_1G;
> > > > > 
> > > > > Is this worth it? READ ID is the most basic command, when this doesn't
> > > > > work I don't think there's a point in continuing.
> > > > 
> > > > We had a case with Samsung K9K8G08U0E when sometimes (reasons
> > > > not known) the
> > > > 5th byte returned 0xff instead of correct values, all other
> > > > returned values
> > > > were correct. In this case the device booted successfully
> > > > because of this
> > > > hook. Maybe a better solution would be to check only the 5th
> > > > byte for 0xff
> > > > value (5th byte is not supported from all NAND vendors), if this
> > > > is the case
> > > > set the NAND size to 1GB.
> > > > Would that make more sense?
> > > 
> > > The best would be to track the issue down and to fix it ;)
> > > It's not very nice to assume it in case of read id failures it's exactly
> > > that NAND type you have troubles with.
> > > Does it help to reset the NAND chip before reading the ID?
> > > 
> > > Sascha
> > > 
> > 
> > I totally agree with fixing the issue and will look into it a bit more.
> > I will reset the NAND before reading the ID in the same way as it is
> > done before reading parameter page. I will leave the testing on over
> > night (reading the ID failed in about 1 out of 500 boots) and report the
> > results tomorrow.
> > 
> 
> I guess resetting fixed this problem, I got 50.000 boots without any
> problems. Will fix this in v2 :).
> 
> Should I now completely abandon setting the NANDs memory to default values
> and just return error on failure?

Yes please.

> Something like this:
> 
> > 	/*
> > 	 * If ONFI is not supported or if it fails try to get NAND's info from
> > 	 * "READ ID" command.
> > 	 */
> > 	ret = mxs_nand_reset(info, databuf);
> > 	if (ret)
> > 		return ret;
> > 	pr_debug("Trying \"READ ID\" command...\n");
> > 	ret = mxs_nand_get_readid(info, databuf);
> > 	if (ret) {
> > 		pr_err("xloader supports only ONFI and generic \"READ ID\" " \
> > 			"supported NANDs\n");
> > 		return -1;
> > 	}
> 
> I'm asking this because NANDs ID command is manufacturer specific, some
> manufacturers follow generic values and other unfortunately don't. In
> barebox NAND driver decoding is done based on manufacturer. I guess we could
> do the same here but I don't want to expand the PBL part too much just for
> reading FCB, where all NAND's memory parameters are decoded from.

We can do that once we have to later. Decoding the ID into page/block
sizes should also be done generically and not part of the i.MX6 NAND
loader.  Maybe we could also utilize parts of the NAND layer instead of
adding new code.

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From andrej.picej at norik.com  Tue Jan 26 07:18:19 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Tue, 26 Jan 2021 13:18:19 +0100
Subject: [PATCH 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <20210126120830.GE28722@pengutronix.de>
References: <20210120125107.736121-1-andrej.picej@norik.com>
 <20210120125107.736121-3-andrej.picej@norik.com>
 <20210121090148.GF19063@pengutronix.de>
 <7df4659e-7237-c5fa-767f-7dedd5c44005@norik.com>
 <20210125091547.GB8233@pengutronix.de>
 <200bfc2a-e616-0e34-b2c4-91ef67915836@norik.com>
 <da704371-9ad7-e42d-675c-08a34afa5159@norik.com>
 <20210126120830.GE28722@pengutronix.de>
Message-ID: <67f31258-a167-aea6-f5b8-1541953a1495@norik.com>

On 26. 01. 21 13:08, Sascha Hauer wrote:
> On Tue, Jan 26, 2021 at 12:40:17PM +0100, Andrej Picej wrote:
>>
>> On 25. 01. 21 10:43, Andrej Picej wrote:
>>> On 25. 01. 21 10:15, Sascha Hauer wrote:
>>>> On Thu, Jan 21, 2021 at 11:28:39AM +0100, Andrej Picej wrote:
>>>>> Hi Sascha,
>>>>>
>>>>> thanks for your comments.
>>>>>
>>>>> Responses inline.
>>>>>
>>>>> On 21. 01. 21 10:01, Sascha Hauer wrote:
>>>>>> Hi Andrej,
>>>>>>
>>>>>> Some comments inline.
>>>>>>
>>>>>> On Wed, Jan 20, 2021 at 01:51:06PM +0100, Andrej Picej wrote:
>>>>>>> From: Sascha Hauer <s.hauer at pengutronix.de>
>>>>>>>
>>>>>>> Commit is based on initial Sascha Hauer's work. It
>>>>>>> implements PBL xload
>>>>>>> mechanism to load image from GPMI NAND flash.
>>>>>>>
>>>>>>> Additional work was done, so that the NAND's size, page size and OOB's
>>>>>>> size are autodetected and not hardcoded. Detection method follows the
>>>>>>> same methods as used in NAND driver, meaning NAND ONFI
>>>>>>> support is probed
>>>>>>> and if NAND supports ONFI, NAND memory organization is read from ONFI
>>>>>>> parameter page otherwise "READ ID" is used.
>>>>>>>
>>>>>>> Currently only implemented for i.MX6 familly of SoCs.
>>>>>>>
>>>>>>> Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
>>>>>>> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
>>>>>>> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
>>>>>>> ---
>>>>>>>  ?? arch/arm/mach-imx/Makefile???????????? |??? 2 +-
>>>>>>>  ?? arch/arm/mach-imx/include/mach/xload.h |??? 1 +
>>>>>>>  ?? arch/arm/mach-imx/xload-gpmi-nand.c??? | 1163
>>>>>>> ++++++++++++++++++++++++
>>>>>>>  ?? 3 files changed, 1165 insertions(+), 1 deletion(-)
>>>>>>>  ?? create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c
>>>>>>>
>>>>>>> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
>>>>>>> index e45f758e9..d94c846a1 100644
>>>>>>> --- a/arch/arm/mach-imx/Makefile
>>>>>>> +++ b/arch/arm/mach-imx/Makefile
>>>>>>> +static int mxs_nand_get_info(struct mxs_nand_info
>>>>>>> *info, void *databuf)
>>>>>>> +{
>>>>>>> +??? int ret, i;
>>>>>>> +
>>>>>>> +??? ret = mxs_nand_check_onfi(info, databuf);
>>>>>>> +??? if (ret) {
>>>>>>> +??????? if (ret != 1)
>>>>>>> +??????????? return ret;
>>>>>>> +??????? pr_warn("ONFI not supported, try \"READ ID\"...\n");
>>>>>>
>>>>>> You already printed a "ONFI not supported\n" message. Printing it once
>>>>>> is enough. Also this message appears with every non-ONFI
>>>>>> nand, right? In
>>>>>> that case it should rather be pr_info()
>>>>>
>>>>> OK, I agree, will fix it in v2.
>>>>>
>>>>>>
>>>>>>> +??? /*
>>>>>>> +???? * If ONFI is not supported or if it fails try to
>>>>>>> get NAND's info from
>>>>>>> +???? * "READ ID" command.
>>>>>>> +???? */
>>>>>>> +??? pr_debug("Trying \"READ ID\" command...\n");
>>>>>>> +??? ret = mxs_nand_get_readid(info, databuf);
>>>>>>> +??? if (ret) {
>>>>>>> +??????? if (ret != -EOVERFLOW)
>>>>>>> +??????????? return ret;
>>>>>>> +
>>>>>>> +??????? /*
>>>>>>> +???????? * If NAND's "READ ID" returns bad values, try to set them to
>>>>>>> +???????? * default (most common NAND memory org.) and continue.
>>>>>>> +???????? */
>>>>>>> +??????? pr_warn("NANDs READ ID command returned bad values" \
>>>>>>> +??????????? " set them to default and try to continue!\n");
>>>>>>> +??????? info->organization.pagesize = 2048;
>>>>>>> +??????? info->organization.oobsize = 64;
>>>>>>> +??????? info->nand_size = SZ_1G;
>>>>>>
>>>>>> Is this worth it? READ ID is the most basic command, when this doesn't
>>>>>> work I don't think there's a point in continuing.
>>>>>
>>>>> We had a case with Samsung K9K8G08U0E when sometimes (reasons
>>>>> not known) the
>>>>> 5th byte returned 0xff instead of correct values, all other
>>>>> returned values
>>>>> were correct. In this case the device booted successfully
>>>>> because of this
>>>>> hook. Maybe a better solution would be to check only the 5th
>>>>> byte for 0xff
>>>>> value (5th byte is not supported from all NAND vendors), if this
>>>>> is the case
>>>>> set the NAND size to 1GB.
>>>>> Would that make more sense?
>>>>
>>>> The best would be to track the issue down and to fix it ;)
>>>> It's not very nice to assume it in case of read id failures it's exactly
>>>> that NAND type you have troubles with.
>>>> Does it help to reset the NAND chip before reading the ID?
>>>>
>>>> Sascha
>>>>
>>>
>>> I totally agree with fixing the issue and will look into it a bit more.
>>> I will reset the NAND before reading the ID in the same way as it is
>>> done before reading parameter page. I will leave the testing on over
>>> night (reading the ID failed in about 1 out of 500 boots) and report the
>>> results tomorrow.
>>>
>>
>> I guess resetting fixed this problem, I got 50.000 boots without any
>> problems. Will fix this in v2 :).
>>
>> Should I now completely abandon setting the NANDs memory to default values
>> and just return error on failure?
> 
> Yes please.
> 
>> Something like this:
>>
>>> 	/*
>>> 	 * If ONFI is not supported or if it fails try to get NAND's info from
>>> 	 * "READ ID" command.
>>> 	 */
>>> 	ret = mxs_nand_reset(info, databuf);
>>> 	if (ret)
>>> 		return ret;
>>> 	pr_debug("Trying \"READ ID\" command...\n");
>>> 	ret = mxs_nand_get_readid(info, databuf);
>>> 	if (ret) {
>>> 		pr_err("xloader supports only ONFI and generic \"READ ID\" " \
>>> 			"supported NANDs\n");
>>> 		return -1;
>>> 	}
>>
>> I'm asking this because NANDs ID command is manufacturer specific, some
>> manufacturers follow generic values and other unfortunately don't. In
>> barebox NAND driver decoding is done based on manufacturer. I guess we could
>> do the same here but I don't want to expand the PBL part too much just for
>> reading FCB, where all NAND's memory parameters are decoded from.
> 
> We can do that once we have to later. Decoding the ID into page/block
> sizes should also be done generically and not part of the i.MX6 NAND
> loader.  Maybe we could also utilize parts of the NAND layer instead of
> adding new code.
> 
Ok, will prepare v2 and submit it when done.
Thank you for your kind comments and guidance so far.

BR,
Andrej



From antoine.demirdjian at airliquide.com  Tue Jan 26 12:06:13 2021
From: antoine.demirdjian at airliquide.com (DEMIRDJIAN, Antoine)
Date: Tue, 26 Jan 2021 18:06:13 +0100
Subject: MAC address set in OCOTP but not visible from ETH0 - i.MX6
Message-ID: <CAEuS4-0HDxrsvQ_2ONfXiLdVn8=xaxR=erz5vtH=km44+HpLTA@mail.gmail.com>

Dear all,

I'm working on a custom board based on an i.MX6 Dual Lite.
I've set a MAC address on OCOTP, and I can see it :

barebox at Main Board:/ devinfo ocotp0
Parameters:
  mac_addr: 70:82:0e:12:73:6f (type: MAC)
  mac_addr0: 70:82:0e:12:73:6f (type: MAC)
  permanent_write_enable: 0 (type: bool)
  sense_enable: 0 (type: bool)

The issue is that I can't get it from eth0 :

barebox at Chrysalis Main Board:/ devinfo eth0
Parameters:
  ethaddr: 00:00:00:00:00:00 (type: MAC)
  gateway: 192.1.1.100 (type: ipv4)
  ipaddr: 0.0.0.0 (type: ipv4)
  linux.bootargs: ip=0.0.0.0:192.1.1.46:192.1.1.100:255.255.255.0:::
(type: string)
  linux.devname:  (type: string)
  mode: static (type: enum) (values: "dhcp", "static", "disabled")
  netmask: 255.255.255.0 (type: ipv4)
  serverip: 192.1.1.46 (type: string)

My operating system's driver does not see it neither ...

Am I missing something?

Best Regards,
Antoine


From a.fatoum at pengutronix.de  Tue Jan 26 12:24:47 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Tue, 26 Jan 2021 18:24:47 +0100
Subject: MAC address set in OCOTP but not visible from ETH0 - i.MX6
In-Reply-To: <CAEuS4-0HDxrsvQ_2ONfXiLdVn8=xaxR=erz5vtH=km44+HpLTA@mail.gmail.com>
References: <CAEuS4-0HDxrsvQ_2ONfXiLdVn8=xaxR=erz5vtH=km44+HpLTA@mail.gmail.com>
Message-ID: <8fd72cdd-9d34-f6e3-6e80-46b00d11cb5d@pengutronix.de>

Hi,

On 26.01.21 18:06, DEMIRDJIAN, Antoine wrote:
> Dear all,
> 
> I'm working on a custom board based on an i.MX6 Dual Lite.
> I've set a MAC address on OCOTP, and I can see it :
> 
> barebox at Main Board:/ devinfo ocotp0
> Parameters:
>   mac_addr: 70:82:0e:12:73:6f (type: MAC)
>   mac_addr0: 70:82:0e:12:73:6f (type: MAC)
>   permanent_write_enable: 0 (type: bool)
>   sense_enable: 0 (type: bool)
> 
> The issue is that I can't get it from eth0 :
> 
> barebox at Chrysalis Main Board:/ devinfo eth0
> Parameters:
>   ethaddr: 00:00:00:00:00:00 (type: MAC)
>   gateway: 192.1.1.100 (type: ipv4)
>   ipaddr: 0.0.0.0 (type: ipv4)
>   linux.bootargs: ip=0.0.0.0:192.1.1.46:192.1.1.100:255.255.255.0:::
> (type: string)
>   linux.devname:  (type: string)
>   mode: static (type: enum) (values: "dhcp", "static", "disabled")
>   netmask: 255.255.255.0 (type: ipv4)
>   serverip: 192.1.1.46 (type: string)
> 
> My operating system's driver does not see it neither ...
> 
> Am I missing something?

Yes: https://barebox.org/doc/latest/devicetree/bindings/misc/fsl,imx-ocotp.html

Check the other i.MX board in arch/arm/dts for an example.

Cheers,
Ahmad

> 
> Best Regards,
> Antoine
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From antoine.demirdjian at airliquide.com  Tue Jan 26 13:06:48 2021
From: antoine.demirdjian at airliquide.com (DEMIRDJIAN, Antoine)
Date: Tue, 26 Jan 2021 19:06:48 +0100
Subject: MAC address set in OCOTP but not visible from ETH0 - i.MX6
In-Reply-To: <8fd72cdd-9d34-f6e3-6e80-46b00d11cb5d@pengutronix.de>
References: <CAEuS4-0HDxrsvQ_2ONfXiLdVn8=xaxR=erz5vtH=km44+HpLTA@mail.gmail.com>
 <8fd72cdd-9d34-f6e3-6e80-46b00d11cb5d@pengutronix.de>
Message-ID: <CAEuS4-0yFUOwkfkMbuwc=VSdEux94y8CVv6V7Gv-tzOt6hX3bA@mail.gmail.com>

Hi,

Le mar. 26 janv. 2021 ? 18:25, Ahmad Fatoum <a.fatoum at pengutronix.de> a ?crit :
>
> Hi,
>
> On 26.01.21 18:06, DEMIRDJIAN, Antoine wrote:
> > Dear all,
> >
> > I'm working on a custom board based on an i.MX6 Dual Lite.
> > I've set a MAC address on OCOTP, and I can see it :
> >
> > barebox at Main Board:/ devinfo ocotp0
> > Parameters:
> >   mac_addr: 70:82:0e:12:73:6f (type: MAC)
> >   mac_addr0: 70:82:0e:12:73:6f (type: MAC)
> >   permanent_write_enable: 0 (type: bool)
> >   sense_enable: 0 (type: bool)
> >
> > The issue is that I can't get it from eth0 :
> >
> > barebox at Chrysalis Main Board:/ devinfo eth0
> > Parameters:
> >   ethaddr: 00:00:00:00:00:00 (type: MAC)
> >   gateway: 192.1.1.100 (type: ipv4)
> >   ipaddr: 0.0.0.0 (type: ipv4)
> >   linux.bootargs: ip=0.0.0.0:192.1.1.46:192.1.1.100:255.255.255.0:::
> > (type: string)
> >   linux.devname:  (type: string)
> >   mode: static (type: enum) (values: "dhcp", "static", "disabled")
> >   netmask: 255.255.255.0 (type: ipv4)
> >   serverip: 192.1.1.46 (type: string)
> >
> > My operating system's driver does not see it neither ...
> >
> > Am I missing something?
>
> Yes: https://barebox.org/doc/latest/devicetree/bindings/misc/fsl,imx-ocotp.html
>
> Check the other i.MX board in arch/arm/dts for an example.

Many thanks !

Sorry for the noise...

Best regards,
Antoine


From andrej.picej at norik.com  Wed Jan 27 02:51:13 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Wed, 27 Jan 2021 08:51:13 +0100
Subject: [PATCH v2 1/3] ARM: i.MX: move BCB structures to header file
Message-ID: <20210127075115.63425-1-andrej.picej@norik.com>

From: Primoz Fiser <primoz.fiser at norik.com>

Move i.MX BCB related structures to header file so they can be used by
others.

Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
Signed-off-by: Andrej Picej <andrej.picej at norik.com>
---
v2:
- no changes

 arch/arm/mach-imx/include/mach/imx-nand-bcb.h | 80 +++++++++++++++++++
 common/imx-bbu-nand-fcb.c                     | 69 +---------------
 2 files changed, 81 insertions(+), 68 deletions(-)
 create mode 100644 arch/arm/mach-imx/include/mach/imx-nand-bcb.h

diff --git a/arch/arm/mach-imx/include/mach/imx-nand-bcb.h b/arch/arm/mach-imx/include/mach/imx-nand-bcb.h
new file mode 100644
index 000000000..b60205bd5
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/imx-nand-bcb.h
@@ -0,0 +1,80 @@
+#ifndef __MACH_IMX_NAND_BCB_H
+#define __MACH_IMX_NAND_BCB_H
+
+#define	FCB_FINGERPRINT		0x20424346	/* 'FCB' */
+#define	FCB_VERSION_1		0x01000000
+#define	FCB_FINGERPRINT_OFF	0x4		/* FCB fingerprint offset*/
+
+#define	DBBT_FINGERPRINT	0x54424244	/* 'DBBT' */
+#define	DBBT_VERSION_1		0x01000000
+#define	DBBT_FINGERPRINT_OFF	0x4		/* DBBT fingerprint offset*/
+
+struct dbbt_block {
+	uint32_t Checksum;
+	uint32_t FingerPrint;
+	uint32_t Version;
+	uint32_t numberBB; /* reserved on i.MX6 */
+	uint32_t DBBTNumOfPages;
+};
+
+struct fcb_block {
+	uint32_t Checksum;		/* First fingerprint in first byte */
+	uint32_t FingerPrint;		/* 2nd fingerprint at byte 4 */
+	uint32_t Version;		/* 3rd fingerprint at byte 8 */
+	uint8_t DataSetup;
+	uint8_t DataHold;
+	uint8_t AddressSetup;
+	uint8_t DSAMPLE_TIME;
+	/* These are for application use only and not for ROM. */
+	uint8_t NandTimingState;
+	uint8_t REA;
+	uint8_t RLOH;
+	uint8_t RHOH;
+	uint32_t PageDataSize;		/* 2048 for 2K pages, 4096 for 4K pages */
+	uint32_t TotalPageSize;		/* 2112 for 2K pages, 4314 for 4K pages */
+	uint32_t SectorsPerBlock;	/* Number of 2K sections per block */
+	uint32_t NumberOfNANDs;		/* Total Number of NANDs - not used by ROM */
+	uint32_t TotalInternalDie;	/* Number of separate chips in this NAND */
+	uint32_t CellType;		/* MLC or SLC */
+	uint32_t EccBlockNEccType;	/* Type of ECC, can be one of BCH-0-20 */
+	uint32_t EccBlock0Size;		/* Number of bytes for Block0 - BCH */
+	uint32_t EccBlockNSize;		/* Block size in bytes for all blocks other than Block0 - BCH */
+	uint32_t EccBlock0EccType;	/* Ecc level for Block 0 - BCH */
+	uint32_t MetadataBytes;		/* Metadata size - BCH */
+	uint32_t NumEccBlocksPerPage;	/* Number of blocks per page for ROM use - BCH */
+	uint32_t EccBlockNEccLevelSDK;	/* Type of ECC, can be one of BCH-0-20 */
+	uint32_t EccBlock0SizeSDK;	/* Number of bytes for Block0 - BCH */
+	uint32_t EccBlockNSizeSDK;	/* Block size in bytes for all blocks other than Block0 - BCH */
+	uint32_t EccBlock0EccLevelSDK;	/* Ecc level for Block 0 - BCH */
+	uint32_t NumEccBlocksPerPageSDK;/* Number of blocks per page for SDK use - BCH */
+	uint32_t MetadataBytesSDK;	/* Metadata size - BCH */
+	uint32_t EraseThreshold;	/* To set into BCH_MODE register */
+	uint32_t BootPatch;		/* 0 for normal boot and 1 to load patch starting next to FCB */
+	uint32_t PatchSectors;		/* Size of patch in sectors */
+	uint32_t Firmware1_startingPage;/* Firmware image starts on this sector */
+	uint32_t Firmware2_startingPage;/* Secondary FW Image starting Sector */
+	uint32_t PagesInFirmware1;	/* Number of sectors in firmware image */
+	uint32_t PagesInFirmware2;	/* Number of sector in secondary FW image */
+	uint32_t DBBTSearchAreaStartAddress; /* Page address where dbbt search area begins */
+	uint32_t BadBlockMarkerByte;	/* Byte in page data that have manufacturer marked bad block marker, */
+					/* this will be swapped with metadata[0] to complete page data. */
+	uint32_t BadBlockMarkerStartBit;/* For BCH ECC sizes other than 8 and 16 the bad block marker does not */
+					/* start at 0th bit of BadBlockMarkerByte. This field is used to get to */
+					/* the start bit of bad block marker byte with in BadBlockMarkerByte */
+	uint32_t BBMarkerPhysicalOffset;/* FCB value that gives byte offset for bad block marker on physical NAND page */
+	uint32_t BCHType;
+
+	uint32_t TMTiming2_ReadLatency;
+	uint32_t TMTiming2_PreambleDelay;
+	uint32_t TMTiming2_CEDelay;
+	uint32_t TMTiming2_PostambleDelay;
+	uint32_t TMTiming2_CmdAddPause;
+	uint32_t TMTiming2_DataPause;
+	uint32_t TMSpeed;
+	uint32_t TMTiming1_BusyTimeout;
+
+	uint32_t DISBBM;	/* the flag to enable (1)/disable(0) bi swap */
+	uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
+};
+
+#endif /* __MACH_IMX_NAND_BCB_H */
diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
index f8c457805..a08a1d834 100644
--- a/common/imx-bbu-nand-fcb.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -25,6 +25,7 @@
 #include <crc.h>
 #include <mach/generic.h>
 #include <mtd/mtd-peb.h>
+#include <mach/imx-nand-bcb.h>
 
 #ifdef CONFIG_ARCH_IMX6
 #include <mach/imx6.h>
@@ -39,74 +40,6 @@ static inline int fcb_is_bch_encoded(void)
 }
 #endif
 
-struct dbbt_block {
-	uint32_t Checksum;
-	uint32_t FingerPrint;
-	uint32_t Version;
-	uint32_t numberBB; /* reserved on i.MX6 */
-	uint32_t DBBTNumOfPages;
-};
-
-struct fcb_block {
-	uint32_t Checksum;		/* First fingerprint in first byte */
-	uint32_t FingerPrint;		/* 2nd fingerprint at byte 4 */
-	uint32_t Version;		/* 3rd fingerprint at byte 8 */
-	uint8_t DataSetup;
-	uint8_t DataHold;
-	uint8_t AddressSetup;
-	uint8_t DSAMPLE_TIME;
-	/* These are for application use only and not for ROM. */
-	uint8_t NandTimingState;
-	uint8_t REA;
-	uint8_t RLOH;
-	uint8_t RHOH;
-	uint32_t PageDataSize;		/* 2048 for 2K pages, 4096 for 4K pages */
-	uint32_t TotalPageSize;		/* 2112 for 2K pages, 4314 for 4K pages */
-	uint32_t SectorsPerBlock;	/* Number of 2K sections per block */
-	uint32_t NumberOfNANDs;		/* Total Number of NANDs - not used by ROM */
-	uint32_t TotalInternalDie;	/* Number of separate chips in this NAND */
-	uint32_t CellType;		/* MLC or SLC */
-	uint32_t EccBlockNEccType;	/* Type of ECC, can be one of BCH-0-20 */
-	uint32_t EccBlock0Size;		/* Number of bytes for Block0 - BCH */
-	uint32_t EccBlockNSize;		/* Block size in bytes for all blocks other than Block0 - BCH */
-	uint32_t EccBlock0EccType;	/* Ecc level for Block 0 - BCH */
-	uint32_t MetadataBytes;		/* Metadata size - BCH */
-	uint32_t NumEccBlocksPerPage;	/* Number of blocks per page for ROM use - BCH */
-	uint32_t EccBlockNEccLevelSDK;	/* Type of ECC, can be one of BCH-0-20 */
-	uint32_t EccBlock0SizeSDK;	/* Number of bytes for Block0 - BCH */
-	uint32_t EccBlockNSizeSDK;	/* Block size in bytes for all blocks other than Block0 - BCH */
-	uint32_t EccBlock0EccLevelSDK;	/* Ecc level for Block 0 - BCH */
-	uint32_t NumEccBlocksPerPageSDK;/* Number of blocks per page for SDK use - BCH */
-	uint32_t MetadataBytesSDK;	/* Metadata size - BCH */
-	uint32_t EraseThreshold;	/* To set into BCH_MODE register */
-	uint32_t BootPatch;		/* 0 for normal boot and 1 to load patch starting next to FCB */
-	uint32_t PatchSectors;		/* Size of patch in sectors */
-	uint32_t Firmware1_startingPage;/* Firmware image starts on this sector */
-	uint32_t Firmware2_startingPage;/* Secondary FW Image starting Sector */
-	uint32_t PagesInFirmware1;	/* Number of sectors in firmware image */
-	uint32_t PagesInFirmware2;	/* Number of sector in secondary FW image */
-	uint32_t DBBTSearchAreaStartAddress; /* Page address where dbbt search area begins */
-	uint32_t BadBlockMarkerByte;	/* Byte in page data that have manufacturer marked bad block marker, */
-					/* this will be swapped with metadata[0] to complete page data. */
-	uint32_t BadBlockMarkerStartBit;/* For BCH ECC sizes other than 8 and 16 the bad block marker does not */
-					/* start at 0th bit of BadBlockMarkerByte. This field is used to get to */
-					/* the start bit of bad block marker byte with in BadBlockMarkerByte */
-	uint32_t BBMarkerPhysicalOffset;/* FCB value that gives byte offset for bad block marker on physical NAND page */
-	uint32_t BCHType;
-
-	uint32_t TMTiming2_ReadLatency;
-	uint32_t TMTiming2_PreambleDelay;
-	uint32_t TMTiming2_CEDelay;
-	uint32_t TMTiming2_PostambleDelay;
-	uint32_t TMTiming2_CmdAddPause;
-	uint32_t TMTiming2_DataPause;
-	uint32_t TMSpeed;
-	uint32_t TMTiming1_BusyTimeout;
-
-	uint32_t DISBBM;	/* the flag to enable (1)/disable(0) bi swap */
-	uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
-};
-
 struct imx_nand_fcb_bbu_handler {
 	struct bbu_handler handler;
 
-- 
2.25.1



From andrej.picej at norik.com  Wed Jan 27 02:51:15 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Wed, 27 Jan 2021 08:51:15 +0100
Subject: [PATCH v2 3/3] ARM: i.MX: xload-gpmi-nand: apply errata 007117
In-Reply-To: <20210127075115.63425-1-andrej.picej@norik.com>
References: <20210127075115.63425-1-andrej.picej@norik.com>
Message-ID: <20210127075115.63425-3-andrej.picej@norik.com>

During raw NAND booting, GPMI/BCH clock generation might fail due to
improper clock gating conditions and consequently booting from NAND will
fail. This is caused by silicon errata ERR007117. Apply errata fix
workaround before GPMI NAND xload to prevent this from occurring.

Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
Signed-off-by: Andrej Picej <andrej.picej at norik.com>
---
v2:
- no changes

 arch/arm/mach-imx/xload-gpmi-nand.c | 62 +++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)

diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
index 163929d81..ce707088f 100644
--- a/arch/arm/mach-imx/xload-gpmi-nand.c
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -20,6 +20,8 @@
 #include <mach/xload.h>
 #include <mach/imx-nand-bcb.h>
 #include <linux/mtd/rawnand.h>
+#include <mach/imx6-regs.h>
+#include <mach/clock-imx6.h>
 
 /*
  * MXS DMA hardware command.
@@ -256,6 +258,63 @@ struct mxs_nand_info {
 	unsigned long nand_size;
 };
 
+/**
+ * It was discovered that xloading barebox from NAND sometimes fails. Observed
+ * behaviour is similar to silicon errata ERR007117 for i.MX6.
+ *
+ * ERR007117 description:
+ * For raw NAND boot, ROM switches the source of enfc_clk_root from PLL2_PFD2
+ * to PLL3. The root clock is required to be gated before switching the source
+ * clock. If the root clock is not gated, clock glitches might be passed to the
+ * divider that follows the clock mux, and the divider might behave
+ * unpredictably. This can cause the clock generation to fail and the chip will
+ * not boot successfully.
+ *
+ * Workaround solution for this errata:
+ * 1) gate all GPMI/BCH related clocks (CG15, G14, CG13, CG12 and CG6)
+ * 2) reconfigure clocks
+ * 3) ungate all GPMI/BCH related clocks
+ *
+ */
+static inline void imx6_errata_007117_enable(void)
+{
+	u32 reg;
+
+	/* Gate (disable) the GPMI/BCH clocks in CCM_CCGR4 */
+	reg = readl(MXC_CCM_CCGR4);
+	reg &= ~(0xFF003000);
+	writel(reg, MXC_CCM_CCGR4);
+
+	/**
+	 * Gate (disable) the enfc_clk_root before changing the enfc_clk_root
+	 * source or dividers by clearing CCM_CCGR2[CG7] to 2'b00. This
+	 * disables the iomux_ipt_clk_io_clk.
+	 */
+	reg = readl(MXC_CCM_CCGR2);
+	reg &= ~(0x3 << 14);
+	writel(reg, MXC_CCM_CCGR2);
+
+	/* Configure CCM_CS2CDR for the new clock source configuration */
+	reg = readl(MXC_CCM_CS2CDR);
+	reg &= ~(0x7FF0000);
+	writel(reg, MXC_CCM_CS2CDR);
+	reg |= 0xF0000;
+	writel(reg, MXC_CCM_CS2CDR);
+
+	/**
+	 * Enable enfc_clk_root by setting CCM_CCGR2[CG7] to 2'b11. This
+	 * enables the iomux_ipt_clk_io_clk.
+	 */
+	reg = readl(MXC_CCM_CCGR2);
+	reg |= 0x3 << 14;
+	writel(reg, MXC_CCM_CCGR2);
+
+	/* Ungate (enable) the GPMI/BCH clocks in CCM_CCGR4 */
+	reg = readl(MXC_CCM_CCGR4);
+	reg |= 0xFF003000;
+	writel(reg, MXC_CCM_CCGR4);
+}
+
 static uint32_t mxs_nand_aux_status_offset(void)
 {
 	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
@@ -1139,6 +1198,9 @@ int imx6_nand_start_image(void)
 		sizeof(struct mxs_dma_cmd) * MXS_NAND_DMA_DESCRIPTOR_COUNT;
 	bb = (void *)PAGE_ALIGN((unsigned long)databuf + SZ_8K);
 
+	/* Apply ERR007117 workaround */
+	imx6_errata_007117_enable();
+
 	ret = imx6_nand_load_image(cmdbuf, descs, databuf,
 		bb, imx_image_size());
 	if (ret) {
-- 
2.25.1



From andrej.picej at norik.com  Wed Jan 27 02:51:14 2021
From: andrej.picej at norik.com (Andrej Picej)
Date: Wed, 27 Jan 2021 08:51:14 +0100
Subject: [PATCH v2 2/3] ARM: i.MX: implement GPMI NAND xload
In-Reply-To: <20210127075115.63425-1-andrej.picej@norik.com>
References: <20210127075115.63425-1-andrej.picej@norik.com>
Message-ID: <20210127075115.63425-2-andrej.picej@norik.com>

From: Sascha Hauer <s.hauer at pengutronix.de>

Commit is based on initial Sascha Hauer's work. It implements PBL xload
mechanism to load image from GPMI NAND flash.

Additional work was done, so that the NAND's size, page size and OOB's
size are autodetected and not hardcoded. Detection method follows the
same methods as used in NAND driver, meaning NAND ONFI support is probed
and if NAND supports ONFI, NAND memory organization is read from ONFI
parameter page otherwise "READ ID" is used.

Currently only implemented for i.MX6 familly of SoCs.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
Signed-off-by: Andrej Picej <andrej.picej at norik.com>
---
v2:
- print ONFI not supported msg. only once and change it to pr_info
- use NAND's organization parameter for pages_per_eraseblock
- reset the NAND before executing "READ ID" command
- return err. if "READ ID" fails

 arch/arm/mach-imx/Makefile             |    2 +-
 arch/arm/mach-imx/include/mach/xload.h |    1 +
 arch/arm/mach-imx/xload-gpmi-nand.c    | 1155 ++++++++++++++++++++++++
 3 files changed, 1157 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/xload-gpmi-nand.c

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index e45f758e9..d94c846a1 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -26,4 +26,4 @@ obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
 obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o
 obj-$(CONFIG_RESET_IMX_SRC) += src.o
 lwl-y += cpu_init.o
-pbl-y += xload-spi.o xload-common.o xload-imx-nand.o
+pbl-y += xload-spi.o xload-common.o xload-imx-nand.o xload-gpmi-nand.o
diff --git a/arch/arm/mach-imx/include/mach/xload.h b/arch/arm/mach-imx/include/mach/xload.h
index 94b2f3761..7187787f5 100644
--- a/arch/arm/mach-imx/include/mach/xload.h
+++ b/arch/arm/mach-imx/include/mach/xload.h
@@ -5,6 +5,7 @@ int imx53_nand_start_image(void);
 int imx6_spi_load_image(int instance, unsigned int flash_offset, void *buf, int len);
 int imx6_spi_start_image(int instance);
 int imx6_esdhc_start_image(int instance);
+int imx6_nand_start_image(void);
 int imx7_esdhc_start_image(int instance);
 int imx8m_esdhc_load_image(int instance, bool start);
 int imx8mp_esdhc_load_image(int instance, bool start);
diff --git a/arch/arm/mach-imx/xload-gpmi-nand.c b/arch/arm/mach-imx/xload-gpmi-nand.c
new file mode 100644
index 000000000..163929d81
--- /dev/null
+++ b/arch/arm/mach-imx/xload-gpmi-nand.c
@@ -0,0 +1,1155 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "xload-gpmi-nand: " fmt
+
+#include <common.h>
+#include <stmp-device.h>
+#include <asm-generic/io.h>
+#include <linux/sizes.h>
+#include <linux/mtd/nand.h>
+#include <asm/cache.h>
+#include <mach/xload.h>
+#include <mach/imx-nand-bcb.h>
+#include <linux/mtd/rawnand.h>
+
+/*
+ * MXS DMA hardware command.
+ *
+ * This structure describes the in-memory layout of an entire DMA command,
+ * including space for the maximum number of PIO accesses. See the appropriate
+ * reference manual for a detailed description of what these fields mean to the
+ * DMA hardware.
+ */
+#define	DMACMD_COMMAND_DMA_WRITE	0x1
+#define	DMACMD_COMMAND_DMA_READ		0x2
+#define	DMACMD_COMMAND_DMA_SENSE	0x3
+#define	DMACMD_CHAIN			(1 << 2)
+#define	DMACMD_IRQ			(1 << 3)
+#define	DMACMD_NAND_LOCK		(1 << 4)
+#define	DMACMD_NAND_WAIT_4_READY	(1 << 5)
+#define	DMACMD_DEC_SEM			(1 << 6)
+#define	DMACMD_WAIT4END			(1 << 7)
+#define	DMACMD_HALT_ON_TERMINATE	(1 << 8)
+#define	DMACMD_TERMINATE_FLUSH		(1 << 9)
+#define	DMACMD_PIO_WORDS(words)		((words) << 12)
+#define	DMACMD_XFER_COUNT(x)		((x) << 16)
+
+struct mxs_dma_cmd {
+	unsigned long		next;
+	unsigned long		data;
+	unsigned long		address;
+#define	APBH_DMA_PIO_WORDS	6
+	unsigned long		pio_words[APBH_DMA_PIO_WORDS];
+};
+
+enum mxs_dma_id {
+	IMX23_DMA,
+	IMX28_DMA,
+};
+
+struct apbh_dma {
+	void __iomem *regs;
+	enum mxs_dma_id id;
+};
+
+struct mxs_dma_chan {
+	unsigned int flags;
+	int channel;
+	struct apbh_dma *apbh;
+};
+
+#define	HW_APBHX_CTRL0				0x000
+#define	BM_APBH_CTRL0_APB_BURST8_EN		(1 << 29)
+#define	BM_APBH_CTRL0_APB_BURST_EN		(1 << 28)
+#define	BP_APBH_CTRL0_CLKGATE_CHANNEL		8
+#define	BP_APBH_CTRL0_RESET_CHANNEL		16
+#define	HW_APBHX_CTRL1				0x010
+#define	BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN	16
+#define	HW_APBHX_CTRL2				0x020
+#define	HW_APBHX_CHANNEL_CTRL			0x030
+#define	BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL	16
+#define	BP_APBHX_VERSION_MAJOR			24
+#define	HW_APBHX_CHn_NXTCMDAR_MX23(n)		(0x050 + (n) * 0x70)
+#define	HW_APBHX_CHn_NXTCMDAR_MX28(n)		(0x110 + (n) * 0x70)
+#define	HW_APBHX_CHn_SEMA_MX23(n)		(0x080 + (n) * 0x70)
+#define	HW_APBHX_CHn_SEMA_MX28(n)		(0x140 + (n) * 0x70)
+#define	NAND_ONFI_CRC_BASE			0x4f4e
+
+#define apbh_dma_is_imx23(aphb) ((apbh)->id == IMX23_DMA)
+
+/* udelay() is not available in PBL, need to improvise */
+static void __udelay(int us)
+{
+	volatile int i;
+
+	for (i = 0; i < us * 4; i++);
+}
+
+/*
+ * Enable a DMA channel.
+ *
+ * If the given channel has any DMA descriptors on its active list, this
+ * function causes the DMA hardware to begin processing them.
+ *
+ * This function marks the DMA channel as "busy," whether or not there are any
+ * descriptors to process.
+ */
+static int mxs_dma_enable(struct mxs_dma_chan *pchan,
+	struct mxs_dma_cmd *pdesc)
+{
+	struct apbh_dma *apbh = pchan->apbh;
+	int channel_bit;
+	int channel = pchan->channel;
+
+	if (apbh_dma_is_imx23(apbh)) {
+		writel((uint32_t)pdesc,
+			apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX23(channel));
+		writel(1, apbh->regs + HW_APBHX_CHn_SEMA_MX23(channel));
+		channel_bit = channel + BP_APBH_CTRL0_CLKGATE_CHANNEL;
+	} else {
+		writel((uint32_t)pdesc,
+			apbh->regs + HW_APBHX_CHn_NXTCMDAR_MX28(channel));
+		writel(1, apbh->regs + HW_APBHX_CHn_SEMA_MX28(channel));
+		channel_bit = channel;
+	}
+
+	writel(1 << channel_bit, apbh->regs +
+		HW_APBHX_CTRL0 + STMP_OFFSET_REG_CLR);
+
+	return 0;
+}
+
+/*
+ * Resets the DMA channel hardware.
+ */
+static int mxs_dma_reset(struct mxs_dma_chan *pchan)
+{
+	struct apbh_dma *apbh = pchan->apbh;
+
+	if (apbh_dma_is_imx23(apbh))
+		writel(1 << (pchan->channel + BP_APBH_CTRL0_RESET_CHANNEL),
+			apbh->regs + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET);
+	else
+		writel(1 << (pchan->channel +
+			BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL),
+			apbh->regs + HW_APBHX_CHANNEL_CTRL +
+			STMP_OFFSET_REG_SET);
+
+	return 0;
+}
+
+static int mxs_dma_wait_complete(struct mxs_dma_chan *pchan)
+{
+	struct apbh_dma *apbh = pchan->apbh;
+	int timeout = 1000000;
+
+	while (1) {
+		if (readl(apbh->regs + HW_APBHX_CTRL1) & (1 << pchan->channel))
+			return 0;
+
+		if (!timeout--)
+			return -ETIMEDOUT;
+	}
+}
+
+/*
+ * Execute the DMA channel
+ */
+static int mxs_dma_run(struct mxs_dma_chan *pchan, struct mxs_dma_cmd *pdesc,
+		int num)
+{
+	struct apbh_dma *apbh = pchan->apbh;
+	int i, ret;
+
+	/* chain descriptors */
+	for (i = 0; i < num - 1; i++) {
+		pdesc[i].next = (uint32_t)(&pdesc[i + 1]);
+		pdesc[i].data |= DMACMD_CHAIN;
+	}
+
+	writel(1 << (pchan->channel + BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN),
+		apbh->regs + HW_APBHX_CTRL1 + STMP_OFFSET_REG_SET);
+
+	ret = mxs_dma_enable(pchan, pdesc);
+	if (ret) {
+		pr_err("%s: Failed to enable dma channel: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	ret = mxs_dma_wait_complete(pchan);
+	if (ret) {
+		pr_err("%s: Failed to wait for completion: %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	/* Shut the DMA channel down. */
+	writel(1 << pchan->channel, apbh->regs +
+		HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR);
+	writel(1 << pchan->channel, apbh->regs +
+		HW_APBHX_CTRL2 + STMP_OFFSET_REG_CLR);
+
+	mxs_dma_reset(pchan);
+
+	writel(1 << (pchan->channel + BP_APBHX_CTRL1_CH_CMDCMPLT_IRQ_EN),
+		apbh->regs + HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR);
+
+	return 0;
+}
+
+/* ----------------------------- NAND driver part -------------------------- */
+
+#define	GPMI_CTRL0					0x00000000
+#define	GPMI_CTRL0_RUN					(1 << 29)
+#define	GPMI_CTRL0_DEV_IRQ_EN				(1 << 28)
+#define	GPMI_CTRL0_UDMA					(1 << 26)
+#define	GPMI_CTRL0_COMMAND_MODE_MASK			(0x3 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_OFFSET			24
+#define	GPMI_CTRL0_COMMAND_MODE_WRITE			(0x0 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ			(0x1 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_READ_AND_COMPARE	(0x2 << 24)
+#define	GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY		(0x3 << 24)
+#define	GPMI_CTRL0_WORD_LENGTH				(1 << 23)
+#define	GPMI_CTRL0_CS(cs)				((cs) << 20)
+#define	GPMI_CTRL0_ADDRESS_MASK				(0x7 << 17)
+#define	GPMI_CTRL0_ADDRESS_OFFSET			17
+#define	GPMI_CTRL0_ADDRESS_NAND_DATA			(0x0 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_CLE			(0x1 << 17)
+#define	GPMI_CTRL0_ADDRESS_NAND_ALE			(0x2 << 17)
+#define	GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define	GPMI_CTRL0_XFER_COUNT_MASK			0xffff
+#define	GPMI_CTRL0_XFER_COUNT_OFFSET			0
+
+#define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
+#define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
+#define	GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE		0x1ff
+
+#define	BCH_CTRL					0x00000000
+#define	BCH_CTRL_COMPLETE_IRQ				(1 << 0)
+
+#define	MXS_NAND_DMA_DESCRIPTOR_COUNT			6
+#define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE			512
+#define	MXS_NAND_METADATA_SIZE				10
+#define	MXS_NAND_COMMAND_BUFFER_SIZE			128
+
+struct mxs_nand_info {
+	void __iomem *io_base;
+	void __iomem *bch_base;
+	struct mxs_dma_chan *dma_channel;
+	int cs;
+	uint8_t *cmd_buf;
+	struct mxs_dma_cmd *desc;
+	struct fcb_block fcb;
+	int dbbt_num_entries;
+	u32 *dbbt;
+	struct nand_memory_organization organization;
+	unsigned long nand_size;
+};
+
+static uint32_t mxs_nand_aux_status_offset(void)
+{
+	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
+}
+
+static int mxs_nand_read_page(struct mxs_nand_info *info, int writesize,
+		int oobsize, int pagenum, void *databuf, int raw)
+{
+	void __iomem *bch_regs = info->bch_base;
+	unsigned column = 0;
+	struct mxs_dma_cmd *d;
+	int cmd_queue_len;
+	u8 *cmd_buf;
+	int ret;
+	uint8_t	*status;
+	int i;
+	int timeout;
+	int descnum = 0;
+	int max_pagenum = info->nand_size /
+		info->organization.pagesize;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - read0 */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_READ0;
+	cmd_buf[cmd_queue_len++] = column;
+	cmd_buf[cmd_queue_len++] = column >> 8;
+	cmd_buf[cmd_queue_len++] = pagenum;
+	cmd_buf[cmd_queue_len++] = pagenum >> 8;
+
+	if ((max_pagenum - 1) >= SZ_64K)
+		cmd_buf[cmd_queue_len++] = pagenum >> 16;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - readstart */
+	cmd_buf = &info->cmd_buf[8];
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+
+	cmd_buf[cmd_queue_len++] = NAND_CMD_READSTART;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - wait for ready. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_CHAIN |
+		DMACMD_NAND_WAIT_4_READY |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(2);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	if (raw) {
+		/* Compile DMA descriptor - read. */
+		d = &info->desc[descnum++];
+		d->data = DMACMD_WAIT4END |
+			DMACMD_PIO_WORDS(1) |
+			DMACMD_XFER_COUNT(writesize + oobsize) |
+			DMACMD_COMMAND_DMA_WRITE;
+		d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+			GPMI_CTRL0_WORD_LENGTH |
+			GPMI_CTRL0_CS(info->cs) |
+			GPMI_CTRL0_ADDRESS_NAND_DATA |
+			(writesize + oobsize);
+		d->address = (dma_addr_t)databuf;
+	} else {
+		/* Compile DMA descriptor - enable the BCH block and read. */
+		d = &info->desc[descnum++];
+		d->data = DMACMD_WAIT4END | DMACMD_PIO_WORDS(6);
+		d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+			GPMI_CTRL0_WORD_LENGTH |
+			GPMI_CTRL0_CS(info->cs) |
+			GPMI_CTRL0_ADDRESS_NAND_DATA |
+			(writesize + oobsize);
+		d->pio_words[1] = 0;
+		d->pio_words[2] = GPMI_ECCCTRL_ENABLE_ECC |
+			GPMI_ECCCTRL_ECC_CMD_DECODE |
+			GPMI_ECCCTRL_BUFFER_MASK_BCH_PAGE;
+		d->pio_words[3] = writesize + oobsize;
+		d->pio_words[4] = (dma_addr_t)databuf;
+		d->pio_words[5] = (dma_addr_t)(databuf + writesize);
+
+		/* Compile DMA descriptor - disable the BCH block. */
+		d = &info->desc[descnum++];
+		d->data = DMACMD_NAND_WAIT_4_READY |
+			DMACMD_WAIT4END |
+			DMACMD_PIO_WORDS(3);
+		d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+			GPMI_CTRL0_WORD_LENGTH |
+			GPMI_CTRL0_CS(info->cs) |
+			GPMI_CTRL0_ADDRESS_NAND_DATA |
+			(writesize + oobsize);
+	}
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		goto err;
+	}
+
+	if (raw)
+		return 0;
+
+	timeout = 1000000;
+
+	while (1) {
+		if (!timeout--) {
+			ret = -ETIMEDOUT;
+			goto err;
+		}
+
+		if (readl(bch_regs + BCH_CTRL) & BCH_CTRL_COMPLETE_IRQ)
+			break;
+	}
+
+	writel(BCH_CTRL_COMPLETE_IRQ,
+		bch_regs + BCH_CTRL + STMP_OFFSET_REG_CLR);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	status = databuf + writesize + mxs_nand_aux_status_offset();
+	for (i = 0; i < writesize / MXS_NAND_CHUNK_DATA_CHUNK_SIZE; i++) {
+		if (status[i] == 0xfe) {
+			ret = -EBADMSG;
+			goto err;
+		}
+	}
+
+	ret = 0;
+err:
+	return ret;
+}
+
+static int mxs_nand_get_read_status(struct mxs_nand_info *info, void *databuf)
+{
+	int ret;
+	u8 *cmd_buf;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - READ STATUS */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_STATUS;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - read. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(1) |
+		DMACMD_COMMAND_DMA_WRITE;
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(1);
+	d->address = (dma_addr_t)databuf;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	return ret;
+}
+
+static int mxs_nand_reset(struct mxs_nand_info *info, void *databuf)
+{
+	int ret, i;
+	u8 *cmd_buf;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+	u8 read_status;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - RESET */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_RESET;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	/* Wait for NAND to wake up */
+	for (i = 0; i < 10; i++) {
+		__udelay(50000);
+		ret = mxs_nand_get_read_status(info, databuf);
+		if (ret)
+			return ret;
+		memcpy(&read_status, databuf, 1);
+		if (read_status & NAND_STATUS_READY)
+			return 0;
+	}
+
+	pr_warn("NAND Reset failed\n");
+	return -1;
+}
+
+/* function taken from nand_onfi.c */
+static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
+{
+	int i;
+
+	while (len--) {
+		crc ^= *p++ << 8;
+		for (i = 0; i < 8; i++)
+			crc = (crc << 1) ^ ((crc & 0x8000) ? 0x8005 : 0);
+	}
+	return crc;
+}
+
+static int mxs_nand_get_onfi(struct mxs_nand_info *info, void *databuf)
+{
+	int ret;
+	u8 *cmd_buf;
+	u16 crc;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+	struct nand_onfi_params nand_params;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - READ PARAMETER PAGE */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_PARAM;
+	cmd_buf[cmd_queue_len++] = 0x00;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - wait for ready. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_CHAIN |
+		DMACMD_NAND_WAIT_4_READY |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(2);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WAIT_FOR_READY |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA;
+
+	/* Compile DMA descriptor - read. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(sizeof(struct nand_onfi_params)) |
+		DMACMD_COMMAND_DMA_WRITE;
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(sizeof(struct nand_onfi_params));
+	d->address = (dma_addr_t)databuf;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	memcpy(&nand_params, databuf, sizeof(struct nand_onfi_params));
+
+	crc = onfi_crc16(NAND_ONFI_CRC_BASE, (u8 *)&nand_params, 254);
+	pr_debug("ONFI CRC: 0x%x, CALC. CRC 0x%x\n", nand_params.crc, crc);
+	if (crc != le16_to_cpu(nand_params.crc)) {
+		pr_debug("ONFI CRC mismatch!\n");
+		ret = -EUCLEAN;
+		return ret;
+	}
+
+	/* Fill the NAND organization struct with data */
+	info->organization.bits_per_cell = nand_params.bits_per_cell;
+	info->organization.pagesize = le32_to_cpu(nand_params.byte_per_page);
+	info->organization.oobsize =
+		le16_to_cpu(nand_params.spare_bytes_per_page);
+	info->organization.pages_per_eraseblock =
+		le32_to_cpu(nand_params.pages_per_block);
+	info->organization.eraseblocks_per_lun =
+		le32_to_cpu(nand_params.blocks_per_lun);
+	info->organization.max_bad_eraseblocks_per_lun =
+		le16_to_cpu(nand_params.bb_per_lun);
+	info->organization.luns_per_target = nand_params.lun_count;
+	info->nand_size = info->organization.pagesize *
+		info->organization.pages_per_eraseblock *
+		info->organization.eraseblocks_per_lun *
+		info->organization.luns_per_target;
+
+	return ret;
+}
+
+static int mxs_nand_check_onfi(struct mxs_nand_info *info, void *databuf)
+{
+	int ret;
+	u8 *cmd_buf;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+
+	struct onfi_header {
+		u8 byte0;
+		u8 byte1;
+		u8 byte2;
+		u8 byte3;
+	} onfi_head;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - READID + 0x20 (ADDR) */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_READID;
+	cmd_buf[cmd_queue_len++] = 0x20;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - read. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(sizeof(struct onfi_header)) |
+		DMACMD_COMMAND_DMA_WRITE;
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(sizeof(struct onfi_header));
+	d->address = (dma_addr_t)databuf;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	memcpy(&onfi_head, databuf, sizeof(struct onfi_header));
+
+	pr_debug("ONFI Byte0: 0x%x\n", onfi_head.byte0);
+	pr_debug("ONFI Byte1: 0x%x\n", onfi_head.byte1);
+	pr_debug("ONFI Byte2: 0x%x\n", onfi_head.byte2);
+	pr_debug("ONFI Byte3: 0x%x\n", onfi_head.byte3);
+
+	/* check if returned values correspond to ascii characters "ONFI" */
+	if (onfi_head.byte0 != 0x4f || onfi_head.byte1 != 0x4e ||
+		onfi_head.byte2 != 0x46 || onfi_head.byte3 != 0x49)
+		return 1;
+
+	return 0;
+}
+
+static int mxs_nand_get_readid(struct mxs_nand_info *info, void *databuf)
+{
+	int ret;
+	u8 *cmd_buf;
+	struct mxs_dma_cmd *d;
+	int descnum = 0;
+	int cmd_queue_len;
+
+	struct readid_data {
+		u8 byte0;
+		u8 byte1;
+		u8 byte2;
+		u8 byte3;
+		u8 byte4;
+	} id_data;
+
+	memset(info->desc, 0,
+		sizeof(*info->desc) * MXS_NAND_DMA_DESCRIPTOR_COUNT);
+
+	/* Compile DMA descriptor - READID */
+	cmd_buf = info->cmd_buf;
+	cmd_queue_len = 0;
+	d = &info->desc[descnum++];
+	d->address = (dma_addr_t)(cmd_buf);
+	cmd_buf[cmd_queue_len++] = NAND_CMD_READID;
+	cmd_buf[cmd_queue_len++] = 0x00;
+
+	d->data = DMACMD_COMMAND_DMA_READ |
+		DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(cmd_queue_len);
+
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_WRITE |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_CLE |
+		GPMI_CTRL0_ADDRESS_INCREMENT |
+		cmd_queue_len;
+
+	/* Compile DMA descriptor - read. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_WAIT4END |
+		DMACMD_PIO_WORDS(1) |
+		DMACMD_XFER_COUNT(sizeof(struct readid_data)) |
+		DMACMD_COMMAND_DMA_WRITE;
+	d->pio_words[0] = GPMI_CTRL0_COMMAND_MODE_READ |
+		GPMI_CTRL0_WORD_LENGTH |
+		GPMI_CTRL0_CS(info->cs) |
+		GPMI_CTRL0_ADDRESS_NAND_DATA |
+		(sizeof(struct readid_data));
+	d->address = (dma_addr_t)databuf;
+
+	/* Compile DMA descriptor - de-assert the NAND lock and interrupt. */
+	d = &info->desc[descnum++];
+	d->data = DMACMD_IRQ | DMACMD_DEC_SEM;
+
+	/* Execute the DMA chain. */
+	ret = mxs_dma_run(info->dma_channel, info->desc, descnum);
+	if (ret) {
+		pr_err("DMA read error\n");
+		return ret;
+	}
+
+	memcpy(&id_data, databuf, sizeof(struct readid_data));
+
+	pr_debug("NAND Byte0: 0x%x\n", id_data.byte0);
+	pr_debug("NAND Byte1: 0x%x\n", id_data.byte1);
+	pr_debug("NAND Byte2: 0x%x\n", id_data.byte2);
+	pr_debug("NAND Byte3: 0x%x\n", id_data.byte3);
+	pr_debug("NAND Byte4: 0x%x\n", id_data.byte4);
+
+	if (id_data.byte0 == 0xff || id_data.byte1 == 0xff ||
+		id_data.byte2 == 0xff || id_data.byte3 == 0xff ||
+		id_data.byte4 == 0xff) {
+		pr_err("\"READ ID\" returned 0xff, possible error!\n");
+		return -EOVERFLOW;
+	}
+
+	/* Fill the NAND organization struct with data */
+	info->organization.bits_per_cell =
+		(1 << ((id_data.byte2 >> 2) & 0x3)) * 2;
+	info->organization.pagesize =
+		(1 << (id_data.byte3 & 0x3)) * SZ_1K;
+	info->organization.oobsize = id_data.byte3 & 0x4 ?
+		info->organization.pagesize / 512 * 16 :
+		info->organization.pagesize / 512 * 8;
+	info->organization.pages_per_eraseblock =
+		(1 << ((id_data.byte3 >> 4) & 0x3)) * SZ_64K /
+		info->organization.pagesize;
+	info->organization.planes_per_lun =
+		1 << ((id_data.byte4 >> 2) & 0x3);
+	info->nand_size = info->organization.planes_per_lun *
+		(1 << ((id_data.byte4 >> 4) & 0x7)) * SZ_8M;
+	info->organization.eraseblocks_per_lun = info->nand_size /
+		(info->organization.pages_per_eraseblock *
+		info->organization.pagesize);
+
+	return ret;
+}
+
+static int mxs_nand_get_info(struct mxs_nand_info *info, void *databuf)
+{
+	int ret, i;
+
+	ret = mxs_nand_check_onfi(info, databuf);
+	if (ret) {
+		if (ret != 1)
+			return ret;
+		pr_info("ONFI not supported, try \"READ ID\"...\n");
+	} else {
+		/*
+		 * Some NAND's don't return the correct data the first time
+		 * "READ PARAMETER PAGE" is returned. Execute the command
+		 * multimple times
+		 */
+		for (i = 0; i < 3; i++) {
+			/*
+			 * Some NAND's need to be reset before "READ PARAMETER
+			 * PAGE" can be successfully executed.
+			 */
+			ret = mxs_nand_reset(info, databuf);
+			if (ret)
+				return ret;
+			ret = mxs_nand_get_onfi(info, databuf);
+			if (ret)
+				pr_err("ONFI error: %d\n", ret);
+			else
+				break;
+		}
+		if (!ret)
+			goto succ;
+	}
+
+	/*
+	 * If ONFI is not supported or if it fails try to get NAND's info from
+	 * "READ ID" command.
+	 */
+	ret = mxs_nand_reset(info, databuf);
+	if (ret)
+		return ret;
+	pr_debug("Trying \"READ ID\" command...\n");
+	ret = mxs_nand_get_readid(info, databuf);
+	if (ret) {
+		pr_err("xloader supports only ONFI and generic \"READ ID\" " \
+			"supported NANDs\n");
+		return -1;
+	}
+succ:
+	pr_debug("NAND page_size: %d\n", info->organization.pagesize);
+	pr_debug("NAND block_size: %d\n",
+		info->organization.pages_per_eraseblock
+		* info->organization.pagesize);
+	pr_debug("NAND oob_size: %d\n", info->organization.oobsize);
+	pr_debug("NAND nand_size: %lu\n", info->nand_size);
+	pr_debug("NAND bits_per_cell: %d\n", info->organization.bits_per_cell);
+	pr_debug("NAND planes_per_lun: %d\n",
+		info->organization.planes_per_lun);
+	pr_debug("NAND luns_per_target: %d\n",
+		info->organization.luns_per_target);
+	pr_debug("NAND eraseblocks_per_lun: %d\n",
+		info->organization.eraseblocks_per_lun);
+	pr_debug("NAND ntargets: %d\n", info->organization.ntargets);
+
+
+	return 0;
+}
+
+/* ---------------------------- BCB handling part -------------------------- */
+
+static uint32_t calc_chksum(void *buf, size_t size)
+{
+	u32 chksum = 0;
+	u8 *bp = buf;
+	size_t i;
+
+	for (i = 0; i < size; i++)
+		chksum += bp[i];
+
+	return ~chksum;
+}
+
+static int get_fcb(struct mxs_nand_info *info, void *databuf)
+{
+	int i, pagenum, ret;
+	uint32_t checksum;
+	struct fcb_block *fcb = &info->fcb;
+
+	/* First page read fails, this shouldn't be necessary */
+	mxs_nand_read_page(info, info->organization.pagesize,
+		info->organization.oobsize, 0, databuf, 1);
+
+	for (i = 0; i < 4; i++) {
+		pagenum = info->organization.pages_per_eraseblock * i;
+
+		ret = mxs_nand_read_page(info, info->organization.pagesize,
+			info->organization.oobsize, pagenum, databuf, 1);
+		if (ret)
+			continue;
+
+		memcpy(fcb, databuf + mxs_nand_aux_status_offset(),
+			sizeof(*fcb));
+
+		if (fcb->FingerPrint != FCB_FINGERPRINT) {
+			pr_err("No FCB found on page %d\n", pagenum);
+			continue;
+		}
+
+		checksum = calc_chksum((void *)fcb +
+			sizeof(uint32_t), sizeof(*fcb) - sizeof(uint32_t));
+
+		if (checksum != fcb->Checksum) {
+			pr_err("FCB on page %d has invalid checksum. " \
+				"Expected: 0x%08x, calculated: 0x%08x",
+				pagenum, fcb->Checksum, checksum);
+			continue;
+		}
+
+		pr_debug("Found FCB:\n");
+		pr_debug("PageDataSize:     0x%08x\n", fcb->PageDataSize);
+		pr_debug("TotalPageSize:    0x%08x\n", fcb->TotalPageSize);
+		pr_debug("SectorsPerBlock:  0x%08x\n", fcb->SectorsPerBlock);
+		pr_debug("FW1_startingPage: 0x%08x\n",
+			fcb->Firmware1_startingPage);
+		pr_debug("PagesInFW1:       0x%08x\n", fcb->PagesInFirmware1);
+		pr_debug("FW2_startingPage: 0x%08x\n",
+			fcb->Firmware2_startingPage);
+		pr_debug("PagesInFW2:       0x%08x\n", fcb->PagesInFirmware2);
+
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int get_dbbt(struct mxs_nand_info *info, void *databuf)
+{
+	int i, ret;
+	int page;
+	int startpage = info->fcb.DBBTSearchAreaStartAddress;
+	struct dbbt_block dbbt;
+
+	for (i = 0; i < 4; i++) {
+		page = startpage + i * info->organization.pages_per_eraseblock;
+
+		ret = mxs_nand_read_page(info, info->organization.pagesize,
+			info->organization.oobsize, page, databuf, 0);
+		if (ret)
+			continue;
+
+		memcpy(&dbbt, databuf, sizeof(struct dbbt_block));
+
+		if (*(u32 *)(databuf + sizeof(u32)) != DBBT_FINGERPRINT)
+			continue;
+
+		/* Version check */
+		if (be32_to_cpup(databuf + 2 * sizeof(u32)) < 1)
+			return -ENOENT;
+
+		ret = mxs_nand_read_page(info, info->organization.pagesize,
+			info->organization.oobsize, page + 4, databuf, 0);
+		if (ret)
+			continue;
+
+		info->dbbt_num_entries = *(u32 *)(databuf + sizeof(u32));
+
+		pr_debug("Found DBBT with %d entries\n",
+			info->dbbt_num_entries);
+		pr_debug("Checksum = 0x%08x\n", dbbt.Checksum);
+		pr_debug("FingerPrint = 0x%08x\n", dbbt.FingerPrint);
+		pr_debug("Version = 0x%08x\n", dbbt.Version);
+		pr_debug("numberBB = 0x%08x\n", dbbt.numberBB);
+		pr_debug("DBBTNumOfPages= 0x%08x\n", dbbt.DBBTNumOfPages);
+
+		for (i = 0; i < info->dbbt_num_entries; i++)
+			pr_debug("badblock %d at block %d\n", i,
+				*(u32 *)(databuf + (2 + i) * sizeof(u32)));
+
+		info->dbbt = databuf + 2 * sizeof(u32);
+
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+static int block_is_bad(struct mxs_nand_info *info, int blocknum)
+{
+	int i;
+	u32 *dbbt = info->dbbt;
+
+	if (!dbbt)
+		return 0;
+
+	for (i = 0; i < info->dbbt_num_entries; i++) {
+		if (dbbt[i] == blocknum)
+			return 1;
+	}
+
+	return 0;
+}
+
+static int read_firmware(struct mxs_nand_info *info, int startpage,
+	void *dest, int len)
+{
+	int curpage = startpage;
+	struct fcb_block *fcb = &info->fcb;
+	int pagesperblock = fcb->SectorsPerBlock;
+	int numpages = (len / fcb->PageDataSize) + 1;
+	int ret;
+	int pagesize = fcb->PageDataSize;
+	int oobsize = fcb->TotalPageSize - pagesize;
+
+	pr_debug("Reading %d pages starting from page %d\n",
+		numpages, startpage);
+
+	if (block_is_bad(info, curpage / pagesperblock))
+		curpage = ALIGN_DOWN(curpage + pagesperblock, pagesperblock);
+
+	while (numpages) {
+		if (!(curpage & (pagesperblock - 1))) {
+			/* Check for bad blocks on each block boundary */
+			if (block_is_bad(info, curpage / pagesperblock)) {
+				pr_debug("Skipping bad block at page %d\n",
+					curpage);
+				curpage += pagesperblock;
+				continue;
+			}
+		}
+
+		ret = mxs_nand_read_page(info, pagesize, oobsize,
+			curpage, dest, 0);
+		if (ret) {
+			pr_debug("Failed to read page %d\n", curpage);
+			return ret;
+		}
+
+		*((u8 *)dest + fcb->BadBlockMarkerByte) =
+			*(u8 *)(dest + pagesize);
+
+		numpages--;
+		dest += pagesize;
+		curpage++;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused imx6_nand_load_image(void *cmdbuf, void *descs,
+	void *databuf, void *dest, int len)
+{
+	struct mxs_nand_info info = {
+		.io_base = (void *)0x00112000,
+		.bch_base = (void *)0x00114000,
+	};
+	struct apbh_dma apbh = {
+		.id = IMX28_DMA,
+		.regs = (void *)0x00110000,
+	};
+	struct mxs_dma_chan pchan = {
+		.channel = 0, /* MXS: MXS_DMA_CHANNEL_AHB_APBH_GPMI0 */
+		.apbh = &apbh,
+	};
+	int ret;
+	struct fcb_block *fcb;
+
+	info.dma_channel = &pchan;
+
+	pr_debug("cmdbuf: 0x%p descs: 0x%p databuf: 0x%p dest: 0x%p\n",
+			cmdbuf, descs, databuf, dest);
+
+	/* Command buffers */
+	info.cmd_buf = cmdbuf;
+	info.desc = descs;
+
+	ret = mxs_nand_get_info(&info, databuf);
+	if (ret)
+		return ret;
+
+	ret = get_fcb(&info, databuf);
+	if (ret)
+		return ret;
+
+	fcb = &info.fcb;
+
+	get_dbbt(&info, databuf);
+
+	ret = read_firmware(&info, fcb->Firmware1_startingPage, dest, len);
+	if (ret) {
+		pr_err("Failed to read firmware1, trying firmware2\n");
+		ret = read_firmware(&info, fcb->Firmware2_startingPage,
+			dest, len);
+		if (ret) {
+			pr_err("Failed to also read firmware2\n");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int imx6_nand_start_image(void)
+{
+	int ret;
+	void *sdram = (void *)0x10000000;
+	void __noreturn (*bb)(void);
+	void *cmdbuf, *databuf, *descs;
+
+	cmdbuf = sdram;
+	descs = sdram + MXS_NAND_COMMAND_BUFFER_SIZE;
+	databuf = descs +
+		sizeof(struct mxs_dma_cmd) * MXS_NAND_DMA_DESCRIPTOR_COUNT;
+	bb = (void *)PAGE_ALIGN((unsigned long)databuf + SZ_8K);
+
+	ret = imx6_nand_load_image(cmdbuf, descs, databuf,
+		bb, imx_image_size());
+	if (ret) {
+		pr_err("Loading image failed: %d\n", ret);
+		return ret;
+	}
+
+	pr_debug("Starting barebox image at 0x%p\n", bb);
+
+	arm_early_mmu_cache_invalidate();
+	barrier();
+
+	bb();
+}
-- 
2.25.1



From donnie at sihovision.com  Wed Jan 27 03:09:30 2021
From: donnie at sihovision.com (donnie at sihovision.com)
Date: Wed, 27 Jan 2021 16:09:30 +0800
Subject: Rugged industrial touch monitor for harsh environment
In-Reply-To: <2021010027160900300341@tradepro.net>
Message-ID: <2021010027160900300341@tradepro.net>

Dear customer,
Good day!
Sihovision lanuached a new model Rugged Industrial Touch Monitor for harsh environment as following:
Front panel IP65 waterproof                                                                                                     
Function: VGA+HDMI+DVI+USB for touch
Brightness: 300 cd/m2                                                  
Touch type: 10 point capacitive touch/ 5 wire resistive touch
12-24V wide voltage
With Phoenix terminal, shock proof 
Anti-electromagnetic interference/ anti-static/Anti surge
Size 7'', 8'', 10.1'', 10.4'', 11.6'', 12'', 15'', 15.6'', 17'', 17.3'', 19'', 21.5''
If you are interested, pls feel free to contact me.
---------------------------------------------
Best regards,
Donnie Nie
SHINHO ELECTRONIC
www.sihovision.com
TEL/Whatsapp: 0086 13163734006
Skype: donnie.shinho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/fc2c752a/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-1.jpg
Type: image/jpeg
Size: 33868 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/fc2c752a/attachment-0006.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-2.jpg
Type: image/jpeg
Size: 35170 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/fc2c752a/attachment-0007.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-3.jpg
Type: image/jpeg
Size: 30491 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/fc2c752a/attachment-0008.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-4.jpg
Type: image/jpeg
Size: 31279 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/fc2c752a/attachment-0009.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-5.jpg
Type: image/jpeg
Size: 17113 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/fc2c752a/attachment-0010.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: logo2.jpg
Type: image/jpeg
Size: 2231 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/fc2c752a/attachment-0011.jpg>

From s.hauer at pengutronix.de  Wed Jan 27 03:19:33 2021
From: s.hauer at pengutronix.de (Sascha Hauer)
Date: Wed, 27 Jan 2021 09:19:33 +0100
Subject: [PATCH] hush: stop parsing string at its end
Message-ID: <20210127081933.12678-1-s.hauer@pengutronix.de>

remove_quotes_in_str() doesn't stop parsing at the string end when
there's a single "'" in the string.
Handling quotes and double quotes is broken in many ways in hush, so
I am not exactly sure this is the right thing to do, but at least it
avoids going out of the string boundaries.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 common/hush.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/common/hush.c b/common/hush.c
index 9ced67af48..44ce4e5225 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -623,8 +623,11 @@ static void remove_quotes_in_str(char *src)
 	while (*src) {
 		if (*src == '\'') {
 			src++;
-			while (*src != '\'')
+			while (*src != '\'') {
+				if (!*src)
+					return;
 				*trg++ = *src++;
+			}
 			src++;
 			continue;
 		}
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:18 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:18 +0100
Subject: [PATCH v2 07/12] firmware: import fpga-mgr.h from linux
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-7-s.trumtrar@pengutronix.de>

Instead of defining the fpga-mgr structure in the socfpga driver, import
the fpga-mgr.h file from linux v4.13.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/firmware/socfpga.c |   9 +---
 include/firmware.h         |   1 +
 include/fpga-mgr.h         | 102 +++++++++++++++++++++++++++++++++++++
 3 files changed, 104 insertions(+), 8 deletions(-)
 create mode 100644 include/fpga-mgr.h

diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 14875214b1aa..605c931604c9 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -27,6 +27,7 @@
  */
 
 #include <firmware.h>
+#include <fpga-mgr.h>
 #include <command.h>
 #include <common.h>
 #include <malloc.h>
@@ -83,14 +84,6 @@
 extern void socfpga_sdram_apply_static_cfg(void __iomem *sdrctrlgrp);
 extern void socfpga_sdram_apply_static_cfg_end(void *);
 
-struct fpgamgr {
-	struct firmware_handler fh;
-	struct device_d dev;
-	void __iomem *regs;
-	void __iomem *regs_data;
-	int programmed;
-};
-
 /* Get the FPGA mode */
 static uint32_t socfpga_fpgamgr_get_mode(struct fpgamgr *mgr)
 {
diff --git a/include/firmware.h b/include/firmware.h
index 19777d9bf711..2fef97a48f56 100644
--- a/include/firmware.h
+++ b/include/firmware.h
@@ -13,6 +13,7 @@ struct firmware_handler {
 	char *id; /* unique identifier for this firmware device */
 	char *model; /* description for this device */
 	struct device_d *dev;
+	void *priv;
 	/* called once to prepare the firmware's programming cycle */
 	int (*open)(struct firmware_handler*);
 	/* called multiple times to program the firmware with the given data */
diff --git a/include/fpga-mgr.h b/include/fpga-mgr.h
new file mode 100644
index 000000000000..a120b3918990
--- /dev/null
+++ b/include/fpga-mgr.h
@@ -0,0 +1,102 @@
+/*
+ * FPGA Framework
+ *
+ *  Copyright (C) 2013-2015 Altera Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _LINUX_FPGA_MGR_H
+#define _LINUX_FPGA_MGR_H
+
+#include <firmware.h>
+
+struct fpga_manager;
+
+/**
+ * enum fpga_mgr_states - fpga framework states
+ * @FPGA_MGR_STATE_UNKNOWN: can't determine state
+ * @FPGA_MGR_STATE_POWER_OFF: FPGA power is off
+ * @FPGA_MGR_STATE_POWER_UP: FPGA reports power is up
+ * @FPGA_MGR_STATE_RESET: FPGA in reset state
+ * @FPGA_MGR_STATE_FIRMWARE_REQ: firmware request in progress
+ * @FPGA_MGR_STATE_FIRMWARE_REQ_ERR: firmware request failed
+ * @FPGA_MGR_STATE_WRITE_INIT: preparing FPGA for programming
+ * @FPGA_MGR_STATE_WRITE_INIT_ERR: Error during WRITE_INIT stage
+ * @FPGA_MGR_STATE_WRITE: writing image to FPGA
+ * @FPGA_MGR_STATE_WRITE_ERR: Error while writing FPGA
+ * @FPGA_MGR_STATE_WRITE_COMPLETE: Doing post programming steps
+ * @FPGA_MGR_STATE_WRITE_COMPLETE_ERR: Error during WRITE_COMPLETE
+ * @FPGA_MGR_STATE_OPERATING: FPGA is programmed and operating
+ */
+enum fpga_mgr_states {
+	/* default FPGA states */
+	FPGA_MGR_STATE_UNKNOWN,
+	FPGA_MGR_STATE_POWER_OFF,
+	FPGA_MGR_STATE_POWER_UP,
+	FPGA_MGR_STATE_RESET,
+
+	/* getting an image for loading */
+	FPGA_MGR_STATE_FIRMWARE_REQ,
+	FPGA_MGR_STATE_FIRMWARE_REQ_ERR,
+
+	/* write sequence: init, write, complete */
+	FPGA_MGR_STATE_WRITE_INIT,
+	FPGA_MGR_STATE_WRITE_INIT_ERR,
+	FPGA_MGR_STATE_WRITE,
+	FPGA_MGR_STATE_WRITE_ERR,
+	FPGA_MGR_STATE_WRITE_COMPLETE,
+	FPGA_MGR_STATE_WRITE_COMPLETE_ERR,
+
+	/* fpga is programmed and operating */
+	FPGA_MGR_STATE_OPERATING,
+};
+
+/*
+ * FPGA Manager flags
+ * FPGA_MGR_PARTIAL_RECONFIG: do partial reconfiguration if supported
+ * FPGA_MGR_EXTERNAL_CONFIG: FPGA has been configured prior to Linux booting
+ * FPGA_MGR_BITSTREAM_LSB_FIRST: SPI bitstream bit order is LSB first
+ * FPGA_MGR_COMPRESSED_BITSTREAM: FPGA bitstream is compressed
+ */
+#define FPGA_MGR_PARTIAL_RECONFIG	BIT(0)
+#define FPGA_MGR_EXTERNAL_CONFIG	BIT(1)
+#define FPGA_MGR_ENCRYPTED_BITSTREAM	BIT(2)
+#define FPGA_MGR_BITSTREAM_LSB_FIRST	BIT(3)
+#define FPGA_MGR_COMPRESSED_BITSTREAM	BIT(4)
+
+/**
+ * struct fpga_image_info - information specific to a FPGA image
+ * @flags: boolean flags as defined above
+ * @enable_timeout_us: maximum time to enable traffic through bridge (uSec)
+ * @disable_timeout_us: maximum time to disable traffic through bridge (uSec)
+ * @config_complete_timeout_us: maximum time for FPGA to switch to operating
+ *	   status in the write_complete op.
+ */
+struct fpga_image_info {
+	u32 flags;
+	u32 enable_timeout_us;
+	u32 disable_timeout_us;
+	u32 config_complete_timeout_us;
+};
+
+struct fpgamgr {
+	struct firmware_handler fh;
+	struct device_d dev;
+	void *priv;
+	void __iomem *regs;
+	void __iomem *regs_data;
+	int programmed;
+};
+
+
+#endif /*_LINUX_FPGA_MGR_H */
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:21 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:21 +0100
Subject: [PATCH v2 10/12] commands: firmwareload: allow loading firmware from
 dt
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-10-s.trumtrar@pengutronix.de>

firmwareload can only load a bitstream into an FPGA without any
knowledge of possible additional needs (e.g. FPGA bridges).

These are defined in the fpga-region nodes in the devicetree. The
fpga-region describes the layout of the FPGA and the bridges it needs
en/disabled.

Add an option to let firmwareload go via the oftree route and load the
firmware that way.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 commands/firmwareload.c | 42 +++++++++++++++++++++++++++++++++++------
 1 file changed, 36 insertions(+), 6 deletions(-)

diff --git a/commands/firmwareload.c b/commands/firmwareload.c
index b735088f6117..2b1e770662d1 100644
--- a/commands/firmwareload.c
+++ b/commands/firmwareload.c
@@ -5,18 +5,38 @@
 #include <command.h>
 #include <getopt.h>
 #include <firmware.h>
+#include <of.h>
 
 static int do_firmwareload(int argc, char *argv[])
 {
-	int ret, opt;
+	int opt;
 	const char *name = NULL, *firmware;
 	struct firmware_mgr *mgr;
+	char *path = NULL;
+	char *search_path = NULL;
+	char *compatible = NULL;
+	int oftree = 0;
 
-	while ((opt = getopt(argc, argv, "t:l")) > 0) {
+	while ((opt = getopt(argc, argv, "t:c:S:D:lo")) > 0) {
 		switch (opt) {
 		case 't':
 			name = optarg;
 			break;
+		case 'c':
+			compatible = xzalloc(strlen(optarg) + 1);
+			strcpy(compatible, optarg);
+			oftree = 1;
+			break;
+		case 'S':
+			search_path = xzalloc(strlen(optarg) + 1);
+			strcpy(search_path, optarg);
+			oftree = 1;
+			break;
+		case 'D':
+			path = xzalloc(strlen(optarg) + 1);
+			strcpy(path, optarg);
+			oftree = 1;
+			break;
 		case 'l':
 			firmwaremgr_list_handlers();
 			return 0;
@@ -25,11 +45,20 @@ static int do_firmwareload(int argc, char *argv[])
 		}
 	}
 
-	if (!(argc - optind))
+	if (!oftree && !(argc - optind))
 		return COMMAND_ERROR_USAGE;
 
 	firmware = argv[optind];
 
+	if (oftree) {
+		if (!search_path && !firmware) {
+			printf("Provide at least a file to load or a search path (-S)\n");
+			return 1;
+		}
+
+		return of_firmware_load_file(path, compatible, search_path, firmware);
+	}
+
 	mgr = firmwaremgr_find(name);
 
 	if (!mgr) {
@@ -38,14 +67,15 @@ static int do_firmwareload(int argc, char *argv[])
 		return 1;
 	}
 
-	ret = firmwaremgr_load_file(mgr, firmware);
-
-	return ret;
+	return firmwaremgr_load_file(mgr, firmware);
 }
 
 BAREBOX_CMD_HELP_START(firmwareload)
 BAREBOX_CMD_HELP_TEXT("Options:")
 BAREBOX_CMD_HELP_OPT("-t <target>", "define the firmware handler by name")
+BAREBOX_CMD_HELP_OPT("-c <compatible>", "type of firmware device (e.g. 'fpga-region')")
+BAREBOX_CMD_HELP_OPT("-D <path>", "load firmware to oftree path")
+BAREBOX_CMD_HELP_OPT("-S <path>", "load firmware using this search path")
 BAREBOX_CMD_HELP_OPT("-l\t", "list devices capable of firmware loading")
 BAREBOX_CMD_HELP_END
 
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:13 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:13 +0100
Subject: [PATCH v2 02/12] firmware: socfpga: set APPLYCFG after loading
 bitstream
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-2-s.trumtrar@pengutronix.de>

To make changes to the SDRAM controller effective, the APPLYCFG bit must
be set after programming the bitstream to the FPGA. This has to be done
without any SDRAM usage. Therefore copy the function to execute to the
OCRAM and execute it from there.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 .../mach-socfpga/include/mach/cyclone5-regs.h |  1 +
 drivers/firmware/Makefile                     |  2 +-
 drivers/firmware/socfpga.c                    | 21 +++++++++++++++++++
 drivers/firmware/socfpga_sdr.S                | 17 +++++++++++++++
 4 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/socfpga_sdr.S

diff --git a/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h b/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h
index e88daf718917..1a7d787a27bf 100644
--- a/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h
+++ b/arch/arm/mach-socfpga/include/mach/cyclone5-regs.h
@@ -18,5 +18,6 @@
 #define CYCLONE5_SYSMGR_ADDRESS		0xffd08000
 #define CYCLONE5_SCANMGR_ADDRESS	0xfff02000
 #define CYCLONE5_SMP_TWD_ADDRESS	0xfffec600
+#define CYCLONE5_OCRAM_ADDRESS		0xffff0000
 
 #endif /* __MACH_SOCFPGA_REGS_H */
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index b162b08b0a80..bbd2bcda9780 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -1,3 +1,3 @@
 obj-$(CONFIG_FIRMWARE_ALTERA_SERIAL) += altera_serial.o
-obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o
+obj-$(CONFIG_FIRMWARE_ALTERA_SOCFPGA) += socfpga.o socfpga_sdr.o
 obj-$(CONFIG_FIRMWARE_ZYNQMP_FPGA) += zynqmp-fpga.o
diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 393c78c45d79..c468c743720f 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -38,6 +38,9 @@
 #include <mach/cyclone5-reset-manager.h>
 #include <mach/cyclone5-regs.h>
 #include <mach/cyclone5-sdram.h>
+#include <asm/fncpy.h>
+#include <mmu.h>
+#include <asm/cache.h>
 
 #define FPGAMGRREGS_STAT			0x0
 #define FPGAMGRREGS_CTRL			0x4
@@ -77,6 +80,9 @@
 #define CDRATIO_x4	0x2
 #define CDRATIO_x8	0x3
 
+extern void socfpga_sdram_apply_static_cfg(void __iomem *sdrctrlgrp);
+extern void socfpga_sdram_apply_static_cfg_end(void *);
+
 struct fpgamgr {
 	struct firmware_handler fh;
 	struct device_d dev;
@@ -353,6 +359,9 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
 	int status;
+	unsigned int func_size = &socfpga_sdram_apply_static_cfg_end -
+				 &socfpga_sdram_apply_static_cfg;
+	void (*ocram_func)(void __iomem *ocram_base);
 
 	/* Ensure the FPGA entering config done */
 	status = fpgamgr_program_poll_cd(mgr);
@@ -382,6 +391,18 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 		return status;
 	}
 
+	remap_range((void *)CYCLONE5_OCRAM_ADDRESS, PAGE_SIZE, MAP_CACHED);
+
+	dev_dbg(&mgr->dev, "Setting APPLYCFG bit...\n");
+
+	ocram_func = fncpy((void __iomem *)CYCLONE5_OCRAM_ADDRESS,
+			   &socfpga_sdram_apply_static_cfg, func_size);
+
+	sync_caches_for_execution();
+
+	ocram_func((void __iomem *) (CYCLONE5_SDR_ADDRESS +
+				     SDR_CTRLGRP_STATICCFG_ADDRESS));
+
 	return 0;
 }
 
diff --git a/drivers/firmware/socfpga_sdr.S b/drivers/firmware/socfpga_sdr.S
new file mode 100644
index 000000000000..d634d6362722
--- /dev/null
+++ b/drivers/firmware/socfpga_sdr.S
@@ -0,0 +1,17 @@
+#include <linux/linkage.h>
+
+	.arch	armv7-a
+	.arm
+
+/*
+ * r0 : sdram controller staticcfg
+ */
+
+ENTRY(socfpga_sdram_apply_static_cfg)
+	push {ip,lr}
+	ldr r1, [r0]
+	orr r1, r1, #8
+	str r1, [r0]
+	pop {ip,pc}
+	.align
+ENTRY(socfpga_sdram_apply_static_cfg_end)
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:23 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:23 +0100
Subject: [PATCH v2 12/12] firmware: add support for compressed images
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-12-s.trumtrar@pengutronix.de>

At least bitstreams for FPGAs can consist of a lot of zeros depending on
device utilization. These bitstreams can be compressed very effectively.

Let the firmware code accept these images and decompress them before
handing it to the firmware-manager in question.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 common/firmware.c | 43 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 5 deletions(-)

diff --git a/common/firmware.c b/common/firmware.c
index 58509d5da615..c617ecc0f129 100644
--- a/common/firmware.c
+++ b/common/firmware.c
@@ -14,6 +14,8 @@
 #include <linux/list.h>
 #include <linux/stat.h>
 #include <linux/err.h>
+#include <uncompress.h>
+#include <filetype.h>
 
 #define BUFSIZ 4096
 
@@ -211,12 +213,43 @@ int firmwaremgr_register(struct firmware_handler *fh)
  */
 int firmwaremgr_load_file(struct firmware_mgr *mgr, const char *firmware)
 {
-	int ret;
-	char *name = basprintf("/dev/%s", mgr->handler->id);
-
-	ret = copy_file(firmware, name, 0);
+	char *dst;
+	enum filetype type;
+	int ret = -ENOENT;
+	int srcfd = 0;
+	int dstfd = 0;
+
+	if (mgr->handler->id) {
+		dst = basprintf("/dev/%s", mgr->handler->id);
+	} else {
+		pr_err("id not defined for handler\n");
+		return -ENODEV;
+	}
 
-	free(name);
+	if (firmware) {
+		type = file_name_detect_type(firmware);
+		if (type == filetype_unknown) {
+			ret = copy_file(firmware, dst, 0);
+		} else {
+			srcfd = open(firmware, O_RDONLY);
+			if (srcfd < 0)
+				return srcfd;
+			dstfd = open(dst, O_WRONLY | O_CREAT);
+
+			if (dstfd < 0) {
+				printf("could not open %s: %s\n", dst, errno_str());
+				ret = dstfd;
+				goto out;
+			}
+
+			ret = uncompress_fd_to_fd(srcfd, dstfd, uncompress_err_stdout);
+
+			close(dstfd);
+		}
+	}
+out:
+	close(srcfd);
+	free(dst);
 
 	return ret;
 }
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:19 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:19 +0100
Subject: [PATCH v2 08/12] of: kconfig: of_overlay uses firmwaremgr_load_file
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-8-s.trumtrar@pengutronix.de>

From: Steffen Trumtrar <str at pengutronix.de>

As of_firmware.c uses the firmwaremgr_load_file function, it depends on
FIRMWARE.

Signed-off-by: Steffen Trumtrar <str at pengutronix.de>
---
 drivers/of/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 23be25d85d09..e58fe50f7090 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -49,6 +49,7 @@ config OF_BAREBOX_ENV_IN_FS
 
 config OF_OVERLAY
 	select OFTREE
+	select FIRMWARE
 	bool "Devicetree overlays"
 	help
 	  Overlays allow to patch the devicetree. Unlike Linux, Barebox does
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:16 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:16 +0100
Subject: [PATCH v2 05/12] drivers: fpga: add socfpga bridges
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-5-s.trumtrar@pengutronix.de>

Import the SoCFPGA bridges drivers from linux v4.10-rc2.

Description from the original commit:
e5f8efa5c8bf86c1fa698551d54db8f6aee221fd

    ARM: socfpga: fpga bridge driver support

    Supports Altera SOCFPGA bridges:
     * fpga2sdram
     * fpga2hps
     * hps2fpga
     * lwhps2fpga

    Allows enabling/disabling the bridges through the FPGA
    Bridge Framework API functions.

    The fpga2sdram driver only supports enabling and disabling
    of the ports that been configured early on.  This is due to
    a hardware limitation where the read, write, and command
    ports on the fpga2sdram bridge can only be reconfigured
    while there are no transactions to the sdram, i.e. when
    running out of OCRAM before the kernel boots.

    Device tree property 'init-val' configures the driver to
    enable or disable the bridge during probe.  If the property
    does not exist, the driver will leave the bridge in its
    current state.

    Signed-off-by: Alan Tull <atull at opensource.altera.com>
    Signed-off-by: Matthew Gerlach <mgerlach at altera.com>
    Signed-off-by: Dinh Nguyen <dinguyen at opensource.altera.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/fpga/Kconfig                     |   8 +
 drivers/fpga/Makefile                    |   1 +
 drivers/fpga/fpga-bridge.c               |   2 +-
 drivers/fpga/socfpga-fpga2sdram-bridge.c | 139 ++++++++++++++++++
 drivers/fpga/socfpga-hps2fpga-bridge.c   | 179 +++++++++++++++++++++++
 5 files changed, 328 insertions(+), 1 deletion(-)
 create mode 100644 drivers/fpga/socfpga-fpga2sdram-bridge.c
 create mode 100644 drivers/fpga/socfpga-hps2fpga-bridge.c

diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index fccdbff6eb3f..64ce9f91b6a8 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -17,6 +17,14 @@ config FPGA_BRIDGE
 	  Say Y here if you want to support bridges connected between host
 	  processors and FPGAs or between FPGAs.
 
+config SOCFPGA_FPGA_BRIDGE
+	tristate "Altera SoCFPGA FPGA Bridges"
+	depends on ARCH_SOCFPGA && FPGA_BRIDGE
+	select RESET_CONTROLLER
+	help
+	  Say Y to enable drivers for FPGA bridges for Altera SOCFPGA
+	  devices.
+
 endif # FPGA
 
 endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index fc71a29d3b33..86178fe7c078 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -4,3 +4,4 @@
 
 # FPGA Bridge Drivers
 obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
+obj-$(CONFIG_SOCFPGA_FPGA_BRIDGE)	+= socfpga-hps2fpga-bridge.o socfpga-fpga2sdram-bridge.o
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
index edf29b0ecf13..b5c74a6e63d4 100644
--- a/drivers/fpga/fpga-bridge.c
+++ b/drivers/fpga/fpga-bridge.c
@@ -68,7 +68,7 @@ struct fpga_bridge *of_fpga_bridge_get(struct device_node *np)
 {
 	struct device_d *dev;
 	struct fpga_bridge *bridge;
-	int ret = -ENODEV;
+	int ret = -EPROBE_DEFER;
 
 	dev = of_find_device_by_node(np);
 	if (!dev || !dev->priv)
diff --git a/drivers/fpga/socfpga-fpga2sdram-bridge.c b/drivers/fpga/socfpga-fpga2sdram-bridge.c
new file mode 100644
index 000000000000..a9760597ddb5
--- /dev/null
+++ b/drivers/fpga/socfpga-fpga2sdram-bridge.c
@@ -0,0 +1,139 @@
+/*
+ * FPGA to SDRAM Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This driver manages a bridge between an FPGA and the SDRAM used by the ARM
+ * host processor system (HPS).
+ *
+ * The bridge contains 4 read ports, 4 write ports, and 6 command ports.
+ * Reconfiguring these ports requires that no SDRAM transactions occur during
+ * reconfiguration.  The code reconfiguring the ports cannot run out of SDRAM
+ * nor can the FPGA access the SDRAM during reconfiguration.  This driver does
+ * not support reconfiguring the ports.  The ports are configured by code
+ * running out of on chip ram before Linux is started and the configuration
+ * is passed in a handoff register in the system manager.
+ *
+ * This driver supports enabling and disabling of the configured ports, which
+ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
+ * uses the same port configuration.  Bridges must be disabled before
+ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <fpga-bridge.h>
+#include <mfd/syscon.h>
+#include <of_device.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define SOCFPGA_SDRCTL_ADDR			0xffc25000
+#define ALT_SDR_CTL_FPGAPORTRST_OFST		0x80
+#define ALT_SDR_CTL_FPGAPORTRST_PORTRSTN_MSK	0x00003fff
+#define ALT_SDR_CTL_FPGAPORTRST_RD_SHIFT	0
+#define ALT_SDR_CTL_FPGAPORTRST_WR_SHIFT	4
+#define ALT_SDR_CTL_FPGAPORTRST_CTRL_SHIFT	8
+
+#define SOCFPGA_SYSMGR_ADDR			0xffd08000
+/*
+ * From the Cyclone V HPS Memory Map document:
+ *   These registers are used to store handoff information between the
+ *   preloader and the OS. These 8 registers can be used to store any
+ *   information. The contents of these registers have no impact on
+ *   the state of the HPS hardware.
+ */
+#define SYSMGR_ISWGRP_HANDOFF3          (0x8C)
+
+#define F2S_BRIDGE_NAME "fpga2sdram"
+
+struct alt_fpga2sdram_data {
+	struct device_d *dev;
+	int mask;
+};
+
+static inline int _alt_fpga2sdram_enable_set(struct alt_fpga2sdram_data *priv,
+					     bool enable)
+{
+	int val;
+
+	val = readl(SOCFPGA_SDRCTL_ADDR + ALT_SDR_CTL_FPGAPORTRST_OFST);
+
+	if (enable)
+		val |= priv->mask;
+	else
+		val = 0;
+
+	/* The kernel driver expects this value in this register :-( */
+	writel(priv->mask, SOCFPGA_SYSMGR_ADDR + SYSMGR_ISWGRP_HANDOFF3);
+
+	dev_dbg(priv->dev, "setting fpgaportrst to 0x%08x\n", val);
+
+	return writel(val, SOCFPGA_SDRCTL_ADDR + ALT_SDR_CTL_FPGAPORTRST_OFST);
+}
+
+static int alt_fpga2sdram_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	return _alt_fpga2sdram_enable_set(bridge->priv, enable);
+}
+
+struct prop_map {
+	char *prop_name;
+	u32 *prop_value;
+	u32 prop_max;
+};
+
+static const struct fpga_bridge_ops altera_fpga2sdram_br_ops = {
+	.enable_set = alt_fpga2sdram_enable_set,
+};
+
+static struct of_device_id altera_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-fpga2sdram-bridge" },
+	{},
+};
+
+static int alt_fpga_bridge_probe(struct device_d *dev)
+{
+	struct alt_fpga2sdram_data *priv;
+	int ret = 0;
+
+	priv = xzalloc(sizeof(*priv));
+	if (!priv)
+		return -ENOMEM;
+
+	/* enable all ports for now */
+	priv->mask = ALT_SDR_CTL_FPGAPORTRST_PORTRSTN_MSK;
+
+	priv->dev = dev;
+
+	ret = fpga_bridge_register(dev, F2S_BRIDGE_NAME,
+				   &altera_fpga2sdram_br_ops, priv);
+	if (ret)
+		return ret;
+
+	dev_info(dev, "driver initialized with handoff %08x\n", priv->mask);
+
+	return ret;
+}
+
+static struct driver_d altera_fpga_driver = {
+	.probe = alt_fpga_bridge_probe,
+	.name = "altera-fpga2sdram-bridge",
+	.of_compatible = DRV_OF_COMPAT(altera_fpga_of_match),
+};
+device_platform_driver(altera_fpga_driver);
diff --git a/drivers/fpga/socfpga-hps2fpga-bridge.c b/drivers/fpga/socfpga-hps2fpga-bridge.c
new file mode 100644
index 000000000000..ecb33ea0b3a5
--- /dev/null
+++ b/drivers/fpga/socfpga-hps2fpga-bridge.c
@@ -0,0 +1,179 @@
+/*
+ * FPGA to/from HPS Bridge Driver for Altera SoCFPGA Devices
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * Includes this patch from the mailing list:
+ *   fpga: altera-hps2fpga: fix HPS2FPGA bridge visibility to L3 masters
+ *   Signed-off-by: Anatolij Gustschin <agust at denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This driver manages bridges on a Altera SOCFPGA between the ARM host
+ * processor system (HPS) and the embedded FPGA.
+ *
+ * This driver supports enabling and disabling of the configured ports, which
+ * allows for safe reprogramming of the FPGA, assuming that the new FPGA image
+ * uses the same port configuration.  Bridges must be disabled before
+ * reprogramming the FPGA and re-enabled after the FPGA has been programmed.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <fpga-bridge.h>
+#include <mfd/syscon.h>
+#include <of_device.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+
+#define SOCFPGA_L3_ADDR				0xff800000
+#define ALT_L3_REMAP_OFST			0x0
+#define ALT_L3_REMAP_MPUZERO_MSK		0x00000001
+#define ALT_L3_REMAP_H2F_MSK			0x00000008
+#define ALT_L3_REMAP_LWH2F_MSK			0x00000010
+
+#define HPS2FPGA_BRIDGE_NAME			"hps2fpga"
+#define LWHPS2FPGA_BRIDGE_NAME			"lwhps2fpga"
+#define FPGA2HPS_BRIDGE_NAME			"fpga2hps"
+
+struct altera_hps2fpga_data {
+	struct device_d *dev;
+	const char *name;
+	struct reset_control *bridge_reset;
+	unsigned int remap_mask;
+	struct clk *clk;
+};
+
+/* The L3 REMAP register is write only, so keep a cached value. */
+static unsigned int l3_remap_shadow;
+
+static int _alt_hps2fpga_enable_set(struct altera_hps2fpga_data *priv,
+				    bool enable)
+{
+	int ret;
+
+	/* bring bridge out of reset */
+	if (enable)
+		ret = reset_control_deassert(priv->bridge_reset);
+	else
+		ret = reset_control_assert(priv->bridge_reset);
+	if (ret)
+		return ret;
+
+	/* Allow bridge to be visible to L3 masters or not */
+	if (priv->remap_mask) {
+		l3_remap_shadow |= ALT_L3_REMAP_MPUZERO_MSK;
+
+		if (enable)
+			l3_remap_shadow |= priv->remap_mask;
+		else
+			l3_remap_shadow &= ~priv->remap_mask;
+
+		dev_dbg(priv->dev, "setting L3 visibility to 0x%08x\n",
+			l3_remap_shadow);
+
+		writel(l3_remap_shadow, SOCFPGA_L3_ADDR + ALT_L3_REMAP_OFST);
+	}
+
+	return ret;
+}
+
+static int alt_hps2fpga_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	return _alt_hps2fpga_enable_set(bridge->priv, enable);
+}
+
+static const struct fpga_bridge_ops altera_hps2fpga_br_ops = {
+	.enable_set = alt_hps2fpga_enable_set,
+};
+
+static struct altera_hps2fpga_data hps2fpga_data  = {
+	.name = HPS2FPGA_BRIDGE_NAME,
+	.remap_mask = ALT_L3_REMAP_H2F_MSK,
+};
+
+static struct altera_hps2fpga_data lwhps2fpga_data  = {
+	.name = LWHPS2FPGA_BRIDGE_NAME,
+	.remap_mask = ALT_L3_REMAP_LWH2F_MSK,
+};
+
+static struct altera_hps2fpga_data fpga2hps_data  = {
+	.name = FPGA2HPS_BRIDGE_NAME,
+};
+
+static struct of_device_id altera_fpga_of_match[] = {
+	{ .compatible = "altr,socfpga-hps2fpga-bridge",
+	  .data = &hps2fpga_data },
+	{ .compatible = "altr,socfpga-lwhps2fpga-bridge",
+	  .data = &lwhps2fpga_data },
+	{ .compatible = "altr,socfpga-fpga2hps-bridge",
+	  .data = &fpga2hps_data },
+	{ /* sentinel */ },
+};
+
+static int alt_fpga_bridge_probe(struct device_d *dev)
+{
+	struct altera_hps2fpga_data *priv;
+	const struct of_device_id *of_id;
+	u32 enable;
+	int ret;
+
+	of_id = of_match_device(altera_fpga_of_match, dev);
+	priv = (struct altera_hps2fpga_data *)of_id->data;
+
+	priv->bridge_reset = of_reset_control_get(dev->device_node, NULL);
+	if (IS_ERR(priv->bridge_reset)) {
+		dev_err(dev, "Could not get %s reset control\n", priv->name);
+		return PTR_ERR(priv->bridge_reset);
+	}
+
+	priv->clk = clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		dev_err(dev, "no clock specified\n");
+		return PTR_ERR(priv->clk);
+	}
+
+	ret = clk_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "could not enable clock\n");
+		return -EBUSY;
+	}
+
+	priv->dev = dev;
+
+	if (!of_property_read_u32(dev->device_node, "bridge-enable", &enable)) {
+		if (enable > 1) {
+			dev_warn(dev, "invalid bridge-enable %u > 1\n", enable);
+		} else {
+			dev_info(dev, "%s bridge\n",
+				 (enable ? "enabling" : "disabling"));
+
+			ret = _alt_hps2fpga_enable_set(priv, enable);
+			if (ret)
+				return ret;
+		}
+	}
+
+	return fpga_bridge_register(dev, priv->name, &altera_hps2fpga_br_ops,
+				    priv);
+}
+
+static struct driver_d alt_fpga_bridge_driver = {
+	.probe = alt_fpga_bridge_probe,
+	.name = "altera-hps2fpga-bridge",
+	.of_compatible = DRV_OF_COMPAT(altera_fpga_of_match),
+};
+device_platform_driver(alt_fpga_bridge_driver);
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:15 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:15 +0100
Subject: [PATCH v2 04/12] drivers: add fpga bridge framework
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-4-s.trumtrar@pengutronix.de>

Import the fpga bridge framework from linux v4.10-rc2.

Description from the initial commit adding this to linux:
21aeda950c5f84a8351b862816d832120b217a9b

    fpga: add fpga bridge framework

    This framework adds API functions for enabling/
    disabling FPGA bridges under kernel control.

    This allows the Linux kernel to disable FPGA bridges
    during FPGA reprogramming and to enable FPGA bridges
    when FPGA reprogramming is done.  This framework is
    be manufacturer-agnostic, allowing it to be used in
    interfaces that use the FPGA Manager Framework to
    reprogram FPGA's.

    The functions are:
    * of_fpga_bridge_get
    * fpga_bridge_put
       Get/put an exclusive reference to a FPGA bridge.

    * fpga_bridge_enable
    * fpga_bridge_disable
       Enable/Disable traffic through a bridge.

    * fpga_bridge_register
    * fpga_bridge_unregister
       Register/unregister a device-specific low level FPGA
       Bridge driver.

    Get an exclusive reference to a bridge and add it to a list:
    * fpga_bridge_get_to_list

    To enable/disable/put a set of bridges that are on a list:
    * fpga_bridges_enable
    * fpga_bridges_disable
    * fpga_bridges_put

    Signed-off-by: Alan Tull <atull at opensource.altera.com>

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/Kconfig            |   1 +
 drivers/Makefile           |   1 +
 drivers/fpga/Kconfig       |  22 ++++
 drivers/fpga/Makefile      |   6 +
 drivers/fpga/fpga-bridge.c | 226 +++++++++++++++++++++++++++++++++++++
 include/fpga-bridge.h      |  69 +++++++++++
 6 files changed, 325 insertions(+)
 create mode 100644 drivers/fpga/Kconfig
 create mode 100644 drivers/fpga/Makefile
 create mode 100644 drivers/fpga/fpga-bridge.c
 create mode 100644 include/fpga-bridge.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index dda240578067..3bb9c09536e8 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -36,6 +36,7 @@ source "drivers/reset/Kconfig"
 source "drivers/pci/Kconfig"
 source "drivers/rtc/Kconfig"
 source "drivers/firmware/Kconfig"
+source "drivers/fpga/Kconfig"
 source "drivers/phy/Kconfig"
 source "drivers/crypto/Kconfig"
 source "drivers/memory/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 5a03bdceab81..5221c2ca5586 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_RESET_CONTROLLER) += reset/
 obj-$(CONFIG_PCI) += pci/
 obj-y += rtc/
 obj-$(CONFIG_FIRMWARE) += firmware/
+obj-$(CONFIG_FPGA) += fpga/
 obj-$(CONFIG_GENERIC_PHY) += phy/
 obj-$(CONFIG_HAB) += hab/
 obj-$(CONFIG_CRYPTO_HW) += crypto/
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
new file mode 100644
index 000000000000..fccdbff6eb3f
--- /dev/null
+++ b/drivers/fpga/Kconfig
@@ -0,0 +1,22 @@
+#
+# FPGA framework configuration
+#
+
+menu "FPGA Configuration Support"
+
+config FPGA
+	tristate "FPGA Configuration Framework"
+	help
+	  Say Y here if you want support for configuring FPGAs from barebox.
+
+if FPGA
+
+config FPGA_BRIDGE
+	tristate "FPGA Bridge Framework"
+	help
+	  Say Y here if you want to support bridges connected between host
+	  processors and FPGAs or between FPGAs.
+
+endif # FPGA
+
+endmenu
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
new file mode 100644
index 000000000000..fc71a29d3b33
--- /dev/null
+++ b/drivers/fpga/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the fpga framework and fpga manager drivers.
+#
+
+# FPGA Bridge Drivers
+obj-$(CONFIG_FPGA_BRIDGE)		+= fpga-bridge.o
diff --git a/drivers/fpga/fpga-bridge.c b/drivers/fpga/fpga-bridge.c
new file mode 100644
index 000000000000..edf29b0ecf13
--- /dev/null
+++ b/drivers/fpga/fpga-bridge.c
@@ -0,0 +1,226 @@
+/*
+ * FPGA Bridge Framework Driver
+ *
+ *  Copyright (C) 2013-2016 Altera Corporation, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <common.h>
+#include <fpga-bridge.h>
+
+/**
+ * fpga_bridge_enable - Enable transactions on the bridge
+ *
+ * @bridge: FPGA bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_enable(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "enable\n");
+
+	if (bridge->br_ops && bridge->br_ops->enable_set)
+		return bridge->br_ops->enable_set(bridge, 1);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_enable);
+
+/**
+ * fpga_bridge_disable - Disable transactions on the bridge
+ *
+ * @bridge: FPGA bridge
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_disable(struct fpga_bridge *bridge)
+{
+	dev_dbg(&bridge->dev, "disable\n");
+
+	if (bridge->br_ops && bridge->br_ops->enable_set)
+		return bridge->br_ops->enable_set(bridge, 0);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_disable);
+
+/**
+ * of_fpga_bridge_get - get an exclusive reference to a fpga bridge
+ *
+ * @np: node pointer of a FPGA bridge
+ *
+ * Return fpga_bridge struct if successful.
+ * Return -EBUSY if someone already has a reference to the bridge.
+ * Return -ENODEV if @np is not a FPGA Bridge.
+ */
+struct fpga_bridge *of_fpga_bridge_get(struct device_node *np)
+
+{
+	struct device_d *dev;
+	struct fpga_bridge *bridge;
+	int ret = -ENODEV;
+
+	dev = of_find_device_by_node(np);
+	if (!dev || !dev->priv)
+		return ERR_PTR(ret);
+
+	bridge = dev->priv;
+
+	return bridge;
+}
+EXPORT_SYMBOL_GPL(of_fpga_bridge_get);
+
+/**
+ * fpga_bridges_enable - enable bridges in a list
+ * @bridge_list: list of FPGA bridges
+ *
+ * Enable each bridge in the list.  If list is empty, do nothing.
+ *
+ * Return 0 for success or empty bridge list; return error code otherwise.
+ */
+int fpga_bridges_enable(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	int ret;
+
+	list_for_each_entry(bridge, bridge_list, node) {
+		ret = fpga_bridge_enable(bridge);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_enable);
+
+/**
+ * fpga_bridges_disable - disable bridges in a list
+ *
+ * @bridge_list: list of FPGA bridges
+ *
+ * Disable each bridge in the list.  If list is empty, do nothing.
+ *
+ * Return 0 for success or empty bridge list; return error code otherwise.
+ */
+int fpga_bridges_disable(struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+	int ret;
+
+	list_for_each_entry(bridge, bridge_list, node) {
+		ret = fpga_bridge_disable(bridge);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridges_disable);
+
+/**
+ * fpga_bridges_get_to_list - get a bridge, add it to a list
+ *
+ * @np: node pointer of a FPGA bridge
+ * @bridge_list: list of FPGA bridges
+ *
+ * Get an exclusive reference to the bridge and and it to the list.
+ *
+ * Return 0 for success, error code from of_fpga_bridge_get() othewise.
+ */
+int fpga_bridge_get_to_list(struct device_node *np,
+			    struct list_head *bridge_list)
+{
+	struct fpga_bridge *bridge;
+
+	bridge = of_fpga_bridge_get(np);
+	if (IS_ERR(bridge))
+		return PTR_ERR(bridge);
+	list_add(&bridge->node, bridge_list);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_get_to_list);
+
+static int set_enable(struct param_d *p, void *priv)
+{
+	struct fpga_bridge *bridge = priv;
+
+	if (bridge->enable)
+		fpga_bridge_enable(bridge);
+	else
+		fpga_bridge_disable(bridge);
+
+	return 0;
+}
+
+/**
+ * fpga_bridge_register - register a fpga bridge driver
+ * @dev:	FPGA bridge device from pdev
+ * @name:	FPGA bridge name
+ * @br_ops:	pointer to structure of fpga bridge ops
+ * @priv:	FPGA bridge private data
+ *
+ * Return: 0 for success, error code otherwise.
+ */
+int fpga_bridge_register(struct device_d *dev, const char *name,
+			 const struct fpga_bridge_ops *br_ops, void *priv)
+{
+	struct fpga_bridge *bridge;
+	struct param_d *p;
+	int ret = 0;
+
+	if (!name || !strlen(name)) {
+		dev_err(dev, "Attempt to register with no name!\n");
+		return -EINVAL;
+	}
+
+	bridge = xzalloc(sizeof(*bridge));
+	if (!bridge)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&bridge->node);
+
+	bridge->br_ops = br_ops;
+	bridge->priv = priv;
+
+	bridge->dev.parent = dev;
+	bridge->dev.device_node = dev->device_node;
+	bridge->dev.id = DEVICE_ID_DYNAMIC;
+
+	bridge->dev.name = xstrdup(name);
+
+	ret = register_device(&bridge->dev);
+	if (ret)
+		goto out;
+
+	dev->priv = bridge;
+
+	bridge->enable = 0;
+	p = dev_add_param_bool(&bridge->dev, "enable", set_enable,
+			       NULL, &bridge->enable, bridge);
+	if (IS_ERR(p))
+		return PTR_ERR(p);
+
+	of_platform_populate(dev->device_node, NULL, dev);
+
+	dev_info(bridge->dev.parent, "fpga bridge [%s] registered\n",
+		 bridge->dev.name);
+
+	return 0;
+
+out:
+	kfree(bridge);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fpga_bridge_register);
diff --git a/include/fpga-bridge.h b/include/fpga-bridge.h
new file mode 100644
index 000000000000..8d55043a7738
--- /dev/null
+++ b/include/fpga-bridge.h
@@ -0,0 +1,69 @@
+#include <common.h>
+
+#ifndef _LINUX_FPGA_BRIDGE_H
+#define _LINUX_FPGA_BRIDGE_H
+
+struct fpga_bridge;
+
+/**
+ * struct fpga_bridge_ops - ops for low level FPGA bridge drivers
+ * @enable_show: returns the FPGA bridge's status
+ * @enable_set: set a FPGA bridge as enabled or disabled
+ * @fpga_bridge_remove: set FPGA into a specific state during driver remove
+ */
+struct fpga_bridge_ops {
+	int (*enable_show)(struct fpga_bridge *bridge);
+	int (*enable_set)(struct fpga_bridge *bridge, bool enable);
+	void (*fpga_bridge_remove)(struct fpga_bridge *bridge);
+};
+
+/**
+ * struct fpga_bridge - FPGA bridge structure
+ * @name: name of low level FPGA bridge
+ * @dev: FPGA bridge device
+ * @mutex: enforces exclusive reference to bridge
+ * @br_ops: pointer to struct of FPGA bridge ops
+ * @info: fpga image specific information
+ * @node: FPGA bridge list node
+ * @priv: low level driver private date
+ */
+struct fpga_bridge {
+	struct device_d dev;
+	const struct fpga_bridge_ops *br_ops;
+	struct list_head node;
+	unsigned int enable;
+	void *priv;
+};
+
+#define to_fpga_bridge(d) container_of(d, struct fpga_bridge, dev)
+
+struct fpga_bridge *of_fpga_bridge_get(struct device_node *node);
+void fpga_bridge_put(struct fpga_bridge *bridge);
+int fpga_bridge_enable(struct fpga_bridge *bridge);
+int fpga_bridge_disable(struct fpga_bridge *bridge);
+
+#ifdef CONFIG_FPGA_BRIDGE
+int fpga_bridges_enable(struct list_head *bridge_list);
+int fpga_bridges_disable(struct list_head *bridge_list);
+int fpga_bridge_get_to_list(struct device_node *np,
+			    struct list_head *bridge_list);
+#else
+static inline int fpga_bridges_enable(struct list_head *bridge_list)
+{
+	return -ENOSYS;
+};
+static inline int fpga_bridges_disable(struct list_head *bridge_list)
+{
+	return -ENOSYS;
+};
+static inline int fpga_bridge_get_to_list(struct device_node *np,
+			    struct list_head *bridge_list)
+{
+	return -ENOSYS;
+};
+#endif
+
+int fpga_bridge_register(struct device_d *dev, const char *name,
+			 const struct fpga_bridge_ops *br_ops, void *priv);
+
+#endif /* _LINUX_FPGA_BRIDGE_H */
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:20 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:20 +0100
Subject: [PATCH v2 09/12] of: of_firmware: add support for fpga bridges
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-9-s.trumtrar@pengutronix.de>

Add support for potentially defined FPGA-bridges in the overlay.

While at it also add support for loading the firmware directly via a
path instead of 'needing' an overlay for that.
The direct loading will be done with the existent firmwareload command.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/of/Makefile      |   3 +-
 drivers/of/of_firmware.c | 130 +++++++++++++++++++++++++++++++++++++--
 include/of.h             |  23 +++++--
 3 files changed, 143 insertions(+), 13 deletions(-)

diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index b6847752d247..6199c9791f52 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -6,4 +6,5 @@ obj-y += partition.o
 obj-y += of_net.o
 obj-$(CONFIG_MTD) += of_mtd.o
 obj-$(CONFIG_OF_BAREBOX_DRIVERS) += barebox.o
-obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o of_firmware.o
+obj-$(CONFIG_OF_OVERLAY) += overlay.o resolver.o
+obj-$(CONFIG_FIRMWARE) += of_firmware.o
diff --git a/drivers/of/of_firmware.c b/drivers/of/of_firmware.c
index 096f84572e63..ff5ac60e9fd5 100644
--- a/drivers/of/of_firmware.c
+++ b/drivers/of/of_firmware.c
@@ -4,12 +4,52 @@
  */
 #include <common.h>
 #include <firmware.h>
+#include <fpga-bridge.h>
 #include <of.h>
 
 struct overlay_info {
 	const char *firmware_path;
 };
 
+#ifdef CONFIG_FPGA_BRIDGE
+static int of_get_bridges(struct device_node *region, struct list_head *bridges)
+{
+	struct device_node *br, *parent_br = NULL;
+	int i, ret;
+
+	/* If parent is a bridge, add to list */
+	ret = fpga_bridge_get_to_list(region->parent, bridges);
+	if (!ret) {
+		parent_br = region->parent;
+		pr_debug("Add %s to list of bridges\n", parent_br->name);
+	}
+
+	for (i = 0; ; i++) {
+		br = of_parse_phandle(region, "fpga-bridges", i);
+		if (!br)
+			break;
+
+		/* If parent bridge is in list, skip it. */
+		if (br == parent_br)
+			continue;
+
+		/* If node is a bridge, get it and add to list */
+		ret = fpga_bridge_get_to_list(br, bridges);
+		if (ret)
+			return ret;
+
+		pr_debug("Add %s to list of bridges\n", br->name);
+	}
+
+	return 0;
+}
+#else
+static int of_get_bridges(struct device_node *np, struct list_head *br)
+{
+	return 0;
+}
+#endif
+
 static struct firmware_mgr *of_node_get_mgr(struct device_node *np)
 {
 	struct device_node *mgr_node;
@@ -25,6 +65,33 @@ static struct firmware_mgr *of_node_get_mgr(struct device_node *np)
 	return NULL;
 }
 
+static int of_load_firmware(struct device_node *target, const char *path)
+{
+	struct list_head bridge_list;
+	struct firmware_mgr *mgr;
+	int err;
+
+	mgr = of_node_get_mgr(target);
+	if (!mgr)
+		return -EINVAL;
+
+	pr_debug("Found firmware manager @%s\n", target->name);
+
+	INIT_LIST_HEAD(&bridge_list);
+
+	of_get_bridges(target, &bridge_list);
+
+	fpga_bridges_disable(&bridge_list);
+
+	pr_debug("Loading %s to %s\n", path, target->name);
+
+	err = firmwaremgr_load_file(mgr, path);
+
+	fpga_bridges_enable(&bridge_list);
+
+	return err;
+}
+
 static int load_firmware(struct device_node *target,
 			 struct device_node *fragment, void *data)
 {
@@ -33,7 +100,6 @@ static int load_firmware(struct device_node *target,
 	const char *firmware_path = info->firmware_path;
 	char *firmware;
 	int err;
-	struct firmware_mgr *mgr;
 
 	err = of_property_read_string(fragment,
 				      "firmware-name", &firmware_name);
@@ -46,21 +112,73 @@ static int load_firmware(struct device_node *target,
 	if (!target)
 		return -EINVAL;
 
-	mgr = of_node_get_mgr(target);
-	if (!mgr)
-		return -EINVAL;
-
 	firmware = basprintf("%s/%s", firmware_path, firmware_name);
 	if (!firmware)
 		return -ENOMEM;
 
-	err = firmwaremgr_load_file(mgr, firmware);
+	err = of_load_firmware(target, firmware);
 
 	free(firmware);
 
 	return err;
 }
 
+int of_firmware_load_file(const char *path, const char *compatible,
+			  const char *search_path, const char *firmware)
+{
+	struct overlay_info info = {
+		.firmware_path = search_path,
+	};
+	struct device_node *target;
+	struct device_node *node;
+	struct device_node *root;
+
+	if (!compatible) {
+		compatible = basprintf("fpga-region");
+		if (!compatible)
+			return -ENOMEM;
+	}
+
+	/*
+	 * firmware-name not specified. Use load_firmware function to get it from
+	 * the devicetree. This allows loading firmware to multiple devices.
+	 */
+	if (!firmware && !path) {
+		int err;
+
+		pr_debug("No firmware specified. Searching devicetree for %s\n", compatible);
+		for_each_compatible_node(node, NULL, compatible) {
+			pr_debug("Load firmware from %s\n", node->name);
+			err = load_firmware(node, node, &info);
+			if (err == -ENOMEM)
+				return err;
+		}
+
+		return 0;
+	}
+
+	root = of_get_root_node();
+
+	if (path) {
+		target = of_find_node_by_path_or_alias(root, path);
+		if (!target) {
+			pr_debug("Cannot find nodepath %s\n", path);
+			return -ENOENT;
+		}
+	} else {
+		target = of_find_compatible_node(NULL, NULL, compatible);
+		if (!target) {
+			pr_debug("No node matching %s found\n", compatible);
+			return -ENOSYS;
+		}
+	}
+	
+	if (!firmware)
+		return load_firmware(target, target, &info);
+
+	return of_load_firmware(target, firmware);
+}
+
 int of_firmware_load_overlay(struct device_node *overlay, const char *path)
 {
 	struct overlay_info info = {
diff --git a/include/of.h b/include/of.h
index 645f429bdeed..b18875478dc0 100644
--- a/include/of.h
+++ b/include/of.h
@@ -1020,6 +1020,23 @@ static inline struct device_node *of_find_root_node(struct device_node *node)
 	return node;
 }
 
+#ifdef CONFIG_FIRMWARE
+int of_firmware_load_file(const char *path, const char *compatible,
+			  const char *search_path, const char *firmware);
+int of_firmware_load_overlay(struct device_node *overlay, const char *path);
+#else
+int of_firmware_load_file(const char *path, const char *compatible,
+			  const char *search_path, const char *firmware)
+{
+	return -ENOSYS;
+}
+
+static inline int of_firmware_load_overlay(const char *path)
+{
+	return -ENOSYS;
+}
+#endif
+
 #ifdef CONFIG_OF_OVERLAY
 struct device_node *of_resolve_phandles(struct device_node *root,
 					const struct device_node *overlay);
@@ -1032,7 +1049,6 @@ int of_process_overlay(struct device_node *root,
 				   struct device_node *overlay, void *data),
 		    void *data);
 
-int of_firmware_load_overlay(struct device_node *overlay, const char *path);
 #else
 static inline struct device_node *of_resolve_phandles(struct device_node *root,
 					const struct device_node *overlay)
@@ -1059,11 +1075,6 @@ static inline int of_process_overlay(struct device_node *root,
 {
 	return -ENOSYS;
 }
-
-static inline int of_firmware_load_overlay(struct device_node *overlay, const char *path)
-{
-	return -ENOSYS;
-}
 #endif
 
 #endif /* __OF_H */
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:17 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:17 +0100
Subject: [PATCH v2 06/12] firmware: socfpga: change function prefixes
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-6-s.trumtrar@pengutronix.de>

Since there is now a fpgamgr framework in barebox, the function names are
misleading. Change that to be SoCFPGA specific.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/firmware/socfpga.c | 58 +++++++++++++++++++-------------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index c468c743720f..14875214b1aa 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -92,12 +92,12 @@ struct fpgamgr {
 };
 
 /* Get the FPGA mode */
-static uint32_t fpgamgr_get_mode(struct fpgamgr *mgr)
+static uint32_t socfpga_fpgamgr_get_mode(struct fpgamgr *mgr)
 {
 	return readl(mgr->regs + FPGAMGRREGS_STAT) & FPGAMGRREGS_STAT_MODE_MASK;
 }
 
-static int fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
+static int socfpga_fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
 {
 	uint64_t start;
 
@@ -121,7 +121,7 @@ static int fpgamgr_dclkcnt_set(struct fpgamgr *mgr, unsigned long cnt)
 }
 
 /* Start the FPGA programming by initialize the FPGA Manager */
-static int fpgamgr_program_init(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_init(struct fpgamgr *mgr)
 {
 	unsigned long reg;
 	uint32_t ctrl = 0, ratio;
@@ -170,7 +170,7 @@ static int fpgamgr_program_init(struct fpgamgr *mgr)
 	/* (1) wait until FPGA enter reset phase */
 	start = get_time_ns();
 	while (1) {
-		if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_RESETPHASE)
+		if (socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_RESETPHASE)
 			break;
 		if (is_timeout(start, 100 * MSECOND))
 			return -ETIMEDOUT;
@@ -184,7 +184,7 @@ static int fpgamgr_program_init(struct fpgamgr *mgr)
 	/* (2) wait until FPGA enter configuration phase */
 	start = get_time_ns();
 	while (1) {
-		if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_CFGPHASE)
+		if (socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_CFGPHASE)
 			break;
 		if (is_timeout(start, 100 * MSECOND))
 			return -ETIMEDOUT;
@@ -202,7 +202,7 @@ static int fpgamgr_program_init(struct fpgamgr *mgr)
 }
 
 /* Ensure the FPGA entering config done */
-static int fpgamgr_program_poll_cd(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_poll_cd(struct fpgamgr *mgr)
 {
 	unsigned long reg;
 	uint32_t val;
@@ -236,18 +236,18 @@ static int fpgamgr_program_poll_cd(struct fpgamgr *mgr)
 }
 
 /* Ensure the FPGA entering init phase */
-static int fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
 {
 	uint64_t start;
 
 	/* additional clocks for the CB to enter initialization phase */
-	if (fpgamgr_dclkcnt_set(mgr, 0x4) != 0)
+	if (socfpga_fpgamgr_dclkcnt_set(mgr, 0x4) != 0)
 		return -5;
 
 	/* (4) wait until FPGA enter init phase or user mode */
 	start = get_time_ns();
 	while (1) {
-		int mode = fpgamgr_get_mode(mgr);
+		int mode = socfpga_fpgamgr_get_mode(mgr);
 
 		if (mode == FPGAMGRREGS_MODE_INITPHASE ||
 				mode == FPGAMGRREGS_MODE_USERMODE)
@@ -261,19 +261,19 @@ static int fpgamgr_program_poll_initphase(struct fpgamgr *mgr)
 }
 
 /* Ensure the FPGA entering user mode */
-static int fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
+static int socfpga_fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
 {
 	uint32_t val;
 	uint64_t start;
 
 	/* additional clocks for the CB to exit initialization phase */
-	if (fpgamgr_dclkcnt_set(mgr, 0x5000) != 0)
+	if (socfpga_fpgamgr_dclkcnt_set(mgr, 0x5000) != 0)
 		return -7;
 
 	/* (5) wait until FPGA enter user mode */
 	start = get_time_ns();
 	while (1) {
-		if (fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE)
+		if (socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE)
 			break;
 		if (is_timeout(start, 100 * MSECOND))
 			return -ETIMEDOUT;
@@ -291,7 +291,7 @@ static int fpgamgr_program_poll_usermode(struct fpgamgr *mgr)
  * Using FPGA Manager to program the FPGA
  * Return 0 for sucess
  */
-static int fpgamgr_program_start(struct firmware_handler *fh)
+static int socfpga_fpgamgr_program_start(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
 	int status;
@@ -313,7 +313,7 @@ static int fpgamgr_program_start(struct firmware_handler *fh)
 	dev_dbg(&mgr->dev, "start programming...\n");
 
 	/* initialize the FPGA Manager */
-	status = fpgamgr_program_init(mgr);
+	status = socfpga_fpgamgr_program_init(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "program init failed with: %s\n",
 				strerror(-status));
@@ -324,7 +324,7 @@ static int fpgamgr_program_start(struct firmware_handler *fh)
 }
 
 /* Write the RBF data to FPGA Manager */
-static int fpgamgr_program_write_buf(struct firmware_handler *fh, const void *buf,
+static int socfpga_fpgamgr_program_write_buf(struct firmware_handler *fh, const void *buf,
 		size_t size)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
@@ -355,7 +355,7 @@ static int fpgamgr_program_write_buf(struct firmware_handler *fh, const void *bu
 	return 0;
 }
 
-static int fpgamgr_program_finish(struct firmware_handler *fh)
+static int socfpga_fpgamgr_program_finish(struct firmware_handler *fh)
 {
 	struct fpgamgr *mgr = container_of(fh, struct fpgamgr, fh);
 	int status;
@@ -364,7 +364,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	void (*ocram_func)(void __iomem *ocram_base);
 
 	/* Ensure the FPGA entering config done */
-	status = fpgamgr_program_poll_cd(mgr);
+	status = socfpga_fpgamgr_program_poll_cd(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "poll for config done failed with: %s\n",
 				strerror(-status));
@@ -374,7 +374,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	dev_dbg(&mgr->dev, "waiting for init phase...\n");
 
 	/* Ensure the FPGA entering init phase */
-	status = fpgamgr_program_poll_initphase(mgr);
+	status = socfpga_fpgamgr_program_poll_initphase(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "poll for init phase failed with: %s\n",
 				strerror(-status));
@@ -384,7 +384,7 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 	dev_dbg(&mgr->dev, "waiting for user mode...\n");
 
 	/* Ensure the FPGA entering user mode */
-	status = fpgamgr_program_poll_usermode(mgr);
+	status = socfpga_fpgamgr_program_poll_usermode(mgr);
 	if (status) {
 		dev_err(&mgr->dev, "poll for user mode with: %s\n",
 				strerror(-status));
@@ -410,11 +410,11 @@ static int fpgamgr_program_finish(struct firmware_handler *fh)
 static int programmed_get(struct param_d *p, void *priv)
 {
 	struct fpgamgr *mgr = priv;
-	mgr->programmed = fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE;
+	mgr->programmed = socfpga_fpgamgr_get_mode(mgr) == FPGAMGRREGS_MODE_USERMODE;
 	return 0;
 }
 
-static int fpgamgr_probe(struct device_d *dev)
+static int socfpga_fpgamgr_probe(struct device_d *dev)
 {
 	struct resource *iores;
 	struct fpgamgr *mgr;
@@ -448,9 +448,9 @@ static int fpgamgr_probe(struct device_d *dev)
 	else
 		fh->id = xstrdup("socfpga-fpga");
 
-	fh->open = fpgamgr_program_start;
-	fh->write = fpgamgr_program_write_buf;
-	fh->close = fpgamgr_program_finish;
+	fh->open = socfpga_fpgamgr_program_start;
+	fh->write = socfpga_fpgamgr_program_write_buf;
+	fh->close = socfpga_fpgamgr_program_finish;
 	of_property_read_string(dev->device_node, "compatible", &model);
 	if (model)
 		fh->model = xstrdup(model);
@@ -488,7 +488,7 @@ static int fpgamgr_probe(struct device_d *dev)
 	return ret;
 }
 
-static struct of_device_id fpgamgr_id_table[] = {
+static struct of_device_id socfpga_fpgamgr_id_table[] = {
 	{
 		.compatible = "altr,socfpga-fpga-mgr",
 	},
@@ -498,9 +498,9 @@ static struct of_device_id fpgamgr_id_table[] = {
 	{ /* sentinel */ }
 };
 
-static struct driver_d fpgamgr_driver = {
+static struct driver_d socfpga_fpgamgr_driver = {
 	.name = "socfpa-fpgamgr",
-	.of_compatible = DRV_OF_COMPAT(fpgamgr_id_table),
-	.probe = fpgamgr_probe,
+	.of_compatible = DRV_OF_COMPAT(socfpga_fpgamgr_id_table),
+	.probe = socfpga_fpgamgr_probe,
 };
-device_platform_driver(fpgamgr_driver);
+device_platform_driver(socfpga_fpgamgr_driver);
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:14 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:14 +0100
Subject: [PATCH v2 03/12] reset: add of_reset_control_get to header
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-3-s.trumtrar@pengutronix.de>

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/reset/core.c  | 2 +-
 include/linux/reset.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 26a54f21dff0..1c9eeaec5491 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -147,7 +147,7 @@ EXPORT_SYMBOL_GPL(reset_control_deassert);
  *
  * Use of id names is optional.
  */
-static struct reset_control *of_reset_control_get(struct device_node *node,
+struct reset_control *of_reset_control_get(struct device_node *node,
 						  const char *id)
 {
 	struct reset_control *rstc;
diff --git a/include/linux/reset.h b/include/linux/reset.h
index 4a92a177bc75..76f40145d949 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -11,6 +11,8 @@ int reset_control_assert(struct reset_control *rstc);
 int reset_control_deassert(struct reset_control *rstc);
 
 struct reset_control *reset_control_get(struct device_d *dev, const char *id);
+struct reset_control *of_reset_control_get(struct device_node *node,
+					   const char *id);
 void reset_control_put(struct reset_control *rstc);
 
 int __must_check device_reset(struct device_d *dev);
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:12 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:12 +0100
Subject: [PATCH v2 01/12] ARM: mmu: inherit pte flags from pmd
Message-ID: <20210127134423.31587-1-s.trumtrar@pengutronix.de>

From: Sascha Hauer <s.hauer at pengutronix.de>

When creating a 2nd level page table from a section inherit the flags
from the section rather than assuming the section was mapped cached
previously. This fixes creating a 2nd level pagetable when the section
was mapped differently than we expected.

Signed-off-by: Sascha Hauer <s.hauer at pengutronix.de>
---
 arch/arm/cpu/mmu.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index 6af228505dd1..6388e1bf14f6 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -138,6 +138,29 @@ static u32 *arm_create_pte(unsigned long virt, uint32_t flags)
 	return table;
 }
 
+static u32 pmd_flags_to_pte(u32 pmd)
+{
+	u32 pte = 0;
+
+	if (pmd & PMD_SECT_BUFFERABLE)
+		pte |= PTE_BUFFERABLE;
+	if (pmd & PMD_SECT_CACHEABLE)
+		pte |= PTE_CACHEABLE;
+	if (pmd & PMD_SECT_nG)
+		pte |= PTE_EXT_NG;
+	if (pmd & PMD_SECT_XN)
+		pte |= PTE_EXT_XN;
+
+	/* TEX[2:0] */
+	pte |= PTE_EXT_TEX((pmd >> 12) & 7);
+	/* AP[1:0] */
+	pte |= ((pmd >> 10) & 0x3) << 4;
+	/* AP[2] */
+	pte |= ((pmd >> 15) & 0x1) << 9;
+
+	return pte;
+}
+
 int arch_remap_range(void *start, size_t size, unsigned flags)
 {
 	u32 addr = (u32)start;
@@ -206,11 +229,8 @@ int arch_remap_range(void *start, size_t size, unsigned flags)
 				 * If PTE is not found it means that
 				 * we needs to split this section and
 				 * create a new page table for it
-				 *
-				 * NOTE: Here we assume that section
-				 * we just split was mapped as cached
 				 */
-				table = arm_create_pte(addr, pte_flags_cached);
+				table = arm_create_pte(addr, pmd_flags_to_pte(*pgd));
 				pte = find_pte(addr);
 				BUG_ON(!pte);
 			}
-- 
2.20.1



From s.trumtrar at pengutronix.de  Wed Jan 27 08:44:22 2021
From: s.trumtrar at pengutronix.de (Steffen Trumtrar)
Date: Wed, 27 Jan 2021 14:44:22 +0100
Subject: [PATCH v2 11/12] drivers: firmware: socfpga: remove bridges shutdown
In-Reply-To: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
Message-ID: <20210127134423.31587-11-s.trumtrar@pengutronix.de>

The bridges are now handled via the bridges driver. There is no
need to hardcode the memory writes anymore.

Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
---
 drivers/firmware/socfpga.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/drivers/firmware/socfpga.c b/drivers/firmware/socfpga.c
index 605c931604c9..eb3fc557c7fe 100644
--- a/drivers/firmware/socfpga.c
+++ b/drivers/firmware/socfpga.c
@@ -294,15 +294,6 @@ static int socfpga_fpgamgr_program_start(struct firmware_handler *fh)
 	/* disable all signals from hps peripheral controller to fpga */
 	writel(0, SYSMGR_FPGAINTF_MODULE);
 
-	/* disable all signals from fpga to hps sdram */
-	writel(0, (CYCLONE5_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS));
-
-	/* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
-	writel(~0, CYCLONE5_RSTMGR_ADDRESS + RESET_MGR_BRG_MOD_RESET_OFS);
-
-	/* unmap the bridges from NIC-301 */
-	writel(0x1, CYCLONE5_L3REGS_ADDRESS);
-
 	dev_dbg(&mgr->dev, "start programming...\n");
 
 	/* initialize the FPGA Manager */
-- 
2.20.1



From donnie at sihovision.com  Wed Jan 27 10:12:40 2021
From: donnie at sihovision.com (donnie at sihovision.com)
Date: Wed, 27 Jan 2021 23:12:40 +0800
Subject: Durable Industrial Touchsceen Monitor dusproof/waterproof design
In-Reply-To: <2021010027231200400235@tradepro.net>
Message-ID: <2021010027231200400235@tradepro.net>

Hello,
This is Donnie from Sihovision which is professional manufacturer of industrial monitor in Shenzhen,China. 
I'd like to introduce a new model industrial monitor(SL700M), it is the best prric/quality ratio industrial touch monitor in the matket. 
Size options:  7'', 8'', 10.1'', 10.4'', 11.6'', 12'', 15'', 15.6'', 17'', 17.3'', 19'', 21.5''
Wecome inquiry!
-------------------------------
Best regards,
Donnie Nie
SHINHO ELECTRONIC
www.sihovision.com
TEL/Whatsapp: 0086 13163734006
Skype: donnie.shinho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/2629c222/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-1.jpg
Type: image/jpeg
Size: 33868 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/2629c222/attachment-0006.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-2.jpg
Type: image/jpeg
Size: 35170 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/2629c222/attachment-0007.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-3.jpg
Type: image/jpeg
Size: 30491 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/2629c222/attachment-0008.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-4.jpg
Type: image/jpeg
Size: 31279 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/2629c222/attachment-0009.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-5.jpg
Type: image/jpeg
Size: 17113 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/2629c222/attachment-0010.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: logo2.jpg
Type: image/jpeg
Size: 2231 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210127/2629c222/attachment-0011.jpg>

From jmaselbas at kalray.eu  Wed Jan 27 11:49:37 2021
From: jmaselbas at kalray.eu (Jules Maselbas)
Date: Wed, 27 Jan 2021 17:49:37 +0100
Subject: [RFC PATCH] usb: gadget: dfu: Wrap fs operation in workqueue
Message-ID: <20210127164937.20328-1-jmaselbas@kalray.eu>

File system operation shouldn't be executed in a poller. Use
a workqueue to delay filesystem operation to command context.

This is an RFC, extra work must be done to properly handle error
cases and dfu cleanup.

Signed-off-by: Jules Maselbas <jmaselbas at kalray.eu>
---
 drivers/usb/gadget/dfu.c | 321 ++++++++++++++++++++++++++-------------
 1 file changed, 216 insertions(+), 105 deletions(-)

diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c
index 9d6a9d252..75abd1576 100644
--- a/drivers/usb/gadget/dfu.c
+++ b/drivers/usb/gadget/dfu.c
@@ -54,6 +54,7 @@
 #include <fs.h>
 #include <ioctl.h>
 #include <linux/mtd/mtd-abi.h>
+#include <work.h>
 
 #define USB_DT_DFU			0x21
 
@@ -153,6 +154,7 @@ struct f_dfu {
 	u8	dfu_state;
 	u8	dfu_status;
 	struct usb_request		*dnreq;
+	struct work_queue wq;
 };
 
 static inline struct f_dfu *func_to_dfu(struct usb_function *f)
@@ -173,6 +175,178 @@ static struct usb_gadget_strings *dfu_strings[] = {
 };
 
 static void dn_complete(struct usb_ep *ep, struct usb_request *req);
+static void up_complete(struct usb_ep *ep, struct usb_request *req);
+static void dfu_cleanup(struct f_dfu *dfu);
+
+struct dfu_work {
+	struct work_struct work;
+	struct f_dfu *dfu;
+	void (*task)(struct dfu_work *dw);
+	size_t len;
+	uint8_t *rbuf;
+	uint8_t wbuf[CONFIG_USBD_DFU_XFER_SIZE];
+};
+
+static void dfu_do_work(struct work_struct *w)
+{
+	struct dfu_work *dw = container_of(w, struct dfu_work, work);
+
+	/* TODO: find a better way to skip tasks when the dfu gadget
+	 * has encounter an error and dfu_cleanup has been called */
+	if (dw->task && dw->dfu->dfu_status == DFU_STATUS_OK)
+		dw->task(dw);
+
+	free(dw);
+}
+
+static void dfu_work_cancel(struct work_struct *w)
+{
+	struct dfu_work *dw = container_of(w, struct dfu_work, work);
+
+	free(dw);
+}
+
+static void dfu_do_write(struct dfu_work *dw)
+{
+	struct f_dfu *dfu = dw->dfu;
+	size_t size, wlen = dw->len;
+	int ret;
+
+	debug("do write\n");
+
+	if (prog_erase && (dfu_written + wlen) > dfu_erased) {
+		size = roundup(wlen, dfu_mtdinfo.erasesize);
+		ret = erase(dfufd, size, dfu_erased);
+		dfu_erased += size;
+		if (ret && ret != -ENOSYS) {
+			perror("erase");
+			dfu->dfu_status = DFU_STATUS_errERASE;
+			dfu_cleanup(dfu);
+			return;
+		}
+	}
+
+	dfu_written += wlen;
+	ret = write(dfufd, dw->wbuf, wlen);
+	if (ret < (int)wlen) {
+		perror("write");
+		dfu->dfu_status = DFU_STATUS_errWRITE;
+		dfu_cleanup(dfu);
+	}
+}
+
+static void dfu_do_read(struct dfu_work *dw)
+{
+	struct f_dfu *dfu = dw->dfu;
+	struct usb_composite_dev *cdev = dfu->func.config->cdev;
+	size_t size, rlen = dw->len;
+
+	debug("do read\n");
+
+	size = read(dfufd, dfu->dnreq->buf, rlen);
+	dfu->dnreq->length = size;
+	if (size < (int)rlen) {
+		perror("read");
+		dfu_cleanup(dfu);
+		dfu->dfu_state = DFU_STATE_dfuIDLE;
+	}
+
+	dfu->dnreq->complete = up_complete;
+	usb_ep_queue(cdev->gadget->ep0, dfu->dnreq);
+}
+
+static void dfu_do_open_dnload(struct dfu_work *dw)
+{
+	struct f_dfu *dfu = dw->dfu;
+	int ret;
+
+	debug("do open dnload\n");
+
+	if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
+		dfufd = open(DFU_TEMPFILE, O_WRONLY | O_CREAT);
+	} else {
+		unsigned flags = O_WRONLY;
+
+		if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
+			flags |= O_CREAT | O_TRUNC;
+
+		dfufd = open(dfu_file_entry->filename, flags);
+	}
+
+	if (dfufd < 0) {
+		perror("open");
+		dfu->dfu_status = DFU_STATUS_errFILE;
+		goto out;
+	}
+
+	if (!(dfu_file_entry->flags & FILE_LIST_FLAG_SAFE)) {
+		ret = ioctl(dfufd, MEMGETINFO, &dfu_mtdinfo);
+		if (!ret) /* file is on a mtd device */
+			prog_erase = 1;
+	}
+
+	return;
+out:
+	dfu->dfu_state = DFU_STATE_dfuERROR;
+	dfu_cleanup(dfu);
+}
+
+static void dfu_do_open_upload(struct dfu_work *dw)
+{
+	struct f_dfu *dfu = dw->dfu;
+
+	debug("do open upload\n");
+
+	dfufd = open(dfu_file_entry->filename, O_RDONLY);
+	if (dfufd < 0) {
+		perror("open");
+		dfu->dfu_status = DFU_STATUS_errFILE;
+		dfu->dfu_state = DFU_STATE_dfuERROR;
+		dfu_cleanup(dfu);
+	}
+}
+
+static void dfu_do_copy(struct dfu_work *dw)
+{
+	struct f_dfu *dfu = dw->dfu;
+	unsigned flags = O_WRONLY;
+	int ret, fd;
+
+	debug("do copy\n");
+
+	if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
+		flags |= O_CREAT | O_TRUNC;
+
+	fd = open(dfu_file_entry->filename, flags);
+	if (fd < 0) {
+		perror("open");
+		dfu->dfu_status = DFU_STATUS_errERASE;
+		goto out;
+	}
+
+	ret = erase(fd, ERASE_SIZE_ALL, 0);
+	close(fd);
+	if (ret && ret != -ENOSYS) {
+		perror("erase");
+		dfu->dfu_status = DFU_STATUS_errERASE;
+		goto out;
+	}
+
+	ret = copy_file(DFU_TEMPFILE, dfu_file_entry->filename, 0);
+	if (ret) {
+		dfu->dfu_status = DFU_STATUS_errWRITE;
+		printf("copy file failed\n");
+		goto out;
+	}
+
+	dfu->dfu_state = DFU_STATE_dfuIDLE;
+	dfu_cleanup(dfu);
+
+	return;
+out:
+	dfu->dfu_state = DFU_STATE_dfuERROR;
+	dfu_cleanup(dfu);
+}
 
 static int
 dfu_bind(struct usb_configuration *c, struct usb_function *f)
@@ -223,6 +397,10 @@ dfu_bind(struct usb_configuration *c, struct usb_function *f)
 		goto out;
 	}
 
+	dfu->wq.fn = dfu_do_work;
+	dfu->wq.cancel = dfu_work_cancel;
+	wq_register(&dfu->wq);
+
 	/* allocate instance-specific interface IDs, and patch descriptors */
 	status = usb_interface_id(c, f);
 	if (status < 0)
@@ -278,6 +456,8 @@ dfu_unbind(struct usb_configuration *c, struct usb_function *f)
 	dfu_file_entry = NULL;
 	dfudetach = 0;
 
+	wq_unregister(&dfu->wq);
+
 	usb_free_all_descriptors(f);
 
 	dma_free(dfu->dnreq->buf);
@@ -327,6 +507,9 @@ static void dfu_cleanup(struct f_dfu *dfu)
 	dfu_erased = 0;
 	prog_erase = 0;
 
+	/* TODO: Right now, close and stat operation can be called
+	 * in a poller, in dfu_abort and dfu_disable. */
+
 	if (dfufd > 0) {
 		close(dfufd);
 		dfufd = -EINVAL;
@@ -339,28 +522,15 @@ static void dfu_cleanup(struct f_dfu *dfu)
 static void dn_complete(struct usb_ep *ep, struct usb_request *req)
 {
 	struct f_dfu		*dfu = req->context;
-	loff_t size;
-	int ret;
+	struct dfu_work *dw;
 
-	if (prog_erase && (dfu_written + req->length) > dfu_erased) {
-		size = roundup(req->length, dfu_mtdinfo.erasesize);
-		ret = erase(dfufd, size, dfu_erased);
-		dfu_erased += size;
-		if (ret && ret != -ENOSYS) {
-			perror("erase");
-			dfu->dfu_status = DFU_STATUS_errERASE;
-			dfu_cleanup(dfu);
-			return;
-		}
-	}
+	dw = xzalloc(sizeof(*dw));
+	dw->dfu = dfu;
+	dw->task = dfu_do_write;
+	dw->len = min_t(unsigned int, req->length, CONFIG_USBD_DFU_XFER_SIZE);
+	memcpy(dw->wbuf, req->buf, dw->len);
 
-	dfu_written += req->length;
-	ret = write(dfufd, req->buf, req->length);
-	if (ret < (int)req->length) {
-		perror("write");
-		dfu->dfu_status = DFU_STATUS_errWRITE;
-		dfu_cleanup(dfu);
-	}
+	wq_queue_work(&dfu->wq, &dw->work);
 }
 
 static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
@@ -370,12 +540,7 @@ static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *c
 	u16			w_length = le16_to_cpu(ctrl->wLength);
 
 	if (w_length == 0) {
-		if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
-			dfu->dfu_state = DFU_STATE_dfuMANIFEST;
-		} else {
-			dfu->dfu_state = DFU_STATE_dfuIDLE;
-			dfu_cleanup(dfu);
-		}
+		dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
 		return 0;
 	}
 
@@ -389,48 +554,18 @@ static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *c
 static int handle_manifest(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 {
 	struct f_dfu		*dfu = func_to_dfu(f);
-	int ret;
+	struct dfu_work *dw;
 
 	dfu->dfu_state = DFU_STATE_dfuIDLE;
 
 	if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
-		int fd;
-		unsigned flags = O_WRONLY;
-
-		if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
-			flags |= O_CREAT | O_TRUNC;
-
-		fd = open(dfu_file_entry->filename, flags);
-		if (fd < 0) {
-			perror("open");
-			dfu->dfu_status = DFU_STATUS_errERASE;
-			ret = -EINVAL;
-			goto out;
-		}
-
-		ret = erase(fd, ERASE_SIZE_ALL, 0);
-		close(fd);
-		if (ret && ret != -ENOSYS) {
-			dfu->dfu_status = DFU_STATUS_errERASE;
-			perror("erase");
-			goto out;
-		}
-
-		ret = copy_file(DFU_TEMPFILE, dfu_file_entry->filename, 0);
-		if (ret) {
-			printf("copy file failed\n");
-			ret = -EINVAL;
-			goto out;
-		}
+		dw = xzalloc(sizeof(*dw));
+		dw->dfu = dfu;
+		dw->task = dfu_do_copy;
+		wq_queue_work(&dfu->wq, &dw->work);
 	}
 
 	return 0;
-
-out:
-	dfu->dfu_status = DFU_STATUS_errWRITE;
-	dfu->dfu_state = DFU_STATE_dfuERROR;
-	dfu_cleanup(dfu);
-	return ret;
 }
 
 static void up_complete(struct usb_ep *ep, struct usb_request *req)
@@ -440,20 +575,17 @@ static void up_complete(struct usb_ep *ep, struct usb_request *req)
 static int handle_upload(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 {
 	struct f_dfu		*dfu = func_to_dfu(f);
-	struct usb_composite_dev *cdev = f->config->cdev;
+	struct dfu_work *dw;
 	u16			w_length = le16_to_cpu(ctrl->wLength);
-	int len;
-
-	len = read(dfufd, dfu->dnreq->buf, w_length);
-
-	dfu->dnreq->length = len;
-	if (len < w_length) {
-		dfu_cleanup(dfu);
-		dfu->dfu_state = DFU_STATE_dfuIDLE;
-	}
 
-	dfu->dnreq->complete = up_complete;
-	usb_ep_queue(cdev->gadget->ep0, dfu->dnreq);
+	/* RFC: I didn't found a better way to queue the usb response other
+	 * than making dfu_do_read call usb_ep_queue after reading from file */
+	dw = xzalloc(sizeof(*dw));
+	dw->dfu = dfu;
+	dw->task = dfu_do_read;
+	dw->len = w_length;
+	dw->rbuf = dfu->dnreq->buf;
+	wq_queue_work(&dfu->wq, &dw->work);
 
 	return 0;
 }
@@ -474,7 +606,7 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 	int			value = -EOPNOTSUPP;
 	int			w_length = le16_to_cpu(ctrl->wLength);
 	int			w_value = le16_to_cpu(ctrl->wValue);
-	int ret;
+	struct dfu_work *dw;
 
 	if (ctrl->bRequestType == USB_DIR_IN && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR
 			&& (w_value >> 8) == 0x21) {
@@ -501,28 +633,10 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 				goto out;
 			}
 			debug("dfu: starting download to %s\n", dfu_file_entry->filename);
-			if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
-				dfufd = open(DFU_TEMPFILE, O_WRONLY | O_CREAT);
-			} else {
-				unsigned flags = O_WRONLY;
-
-				if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
-					flags |= O_CREAT | O_TRUNC;
-
-				dfufd = open(dfu_file_entry->filename, flags);
-			}
-
-			if (dfufd < 0) {
-				dfu->dfu_state = DFU_STATE_dfuERROR;
-				perror("open");
-				goto out;
-			}
-
-			if (!(dfu_file_entry->flags & FILE_LIST_FLAG_SAFE)) {
-				ret = ioctl(dfufd, MEMGETINFO, &dfu_mtdinfo);
-				if (!ret) /* file is on a mtd device */
-					prog_erase = 1;
-			}
+			dw = xzalloc(sizeof(*dw));
+			dw->dfu = dfu;
+			dw->task = dfu_do_open_dnload;
+			wq_queue_work(&dfu->wq, &dw->work);
 
 			value = handle_dnload(f, ctrl);
 			dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
@@ -534,12 +648,12 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 				dfu->dfu_state = DFU_STATE_dfuERROR;
 				goto out;
 			}
-			dfufd = open(dfu_file_entry->filename, O_RDONLY);
-			if (dfufd < 0) {
-				dfu->dfu_state = DFU_STATE_dfuERROR;
-				perror("open");
-				goto out;
-			}
+
+			dw = xzalloc(sizeof(*dw));
+			dw->dfu = dfu;
+			dw->task = dfu_do_open_upload;
+			wq_queue_work(&dfu->wq, &dw->work);
+
 			handle_upload(f, ctrl);
 			return 0;
 		case USB_REQ_DFU_ABORT:
@@ -648,9 +762,6 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
 		break;
 	case DFU_STATE_dfuMANIFEST:
 		value = handle_manifest(f, ctrl);
-		if (dfu->dfu_state != DFU_STATE_dfuIDLE) {
-			return 0;
-		}
 		switch (ctrl->bRequest) {
 		case USB_REQ_DFU_GETSTATUS:
 			value = dfu_status(f, ctrl);
-- 
2.17.1




From donnie at sihovision.com  Thu Jan 28 05:02:45 2021
From: donnie at sihovision.com (donnie at sihovision.com)
Date: Thu, 28 Jan 2021 18:02:45 +0800
Subject: Shock-proof Design Industrial AIO Panel PC
In-Reply-To: <2021010028180200450759@tradepro.net>
Message-ID: <2021010028180200450759@tradepro.net>

Hi,
I'd like to introduce a new type Industrial Touch Panel PC, 
cordless motherboard design, 
shock-proof design, 
authentic industrial grade compter, 
for more ruged environments.
cordless motherboard design
If you need more information, pls feel free to contact me, thanks. 
____________________________________________
Best regards,
Donnie Nie
SHINHO ELECTRONIC
www.sihovision.com
TEL/Whatsapp: 0086 13163734006
Skype: donnie.shinho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/1d7e258c/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-2.jpg
Type: image/jpeg
Size: 33388 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/1d7e258c/attachment-0005.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-3.jpg
Type: image/jpeg
Size: 36765 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/1d7e258c/attachment-0006.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-4.jpg
Type: image/jpeg
Size: 44663 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/1d7e258c/attachment-0007.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: PPC-1-1.jpg
Type: image/jpeg
Size: 47661 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/1d7e258c/attachment-0008.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: logo2.jpg
Type: image/jpeg
Size: 2231 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/1d7e258c/attachment-0009.jpg>

From donnie at sihovision.com  Thu Jan 28 06:13:08 2021
From: donnie at sihovision.com (donnie at sihovision.com)
Date: Thu, 28 Jan 2021 19:13:08 +0800
Subject: Durable Industrial Touchsceen Monitor dusproof/waterproof design
In-Reply-To: <2021010028191300080949@tradepro.net>
Message-ID: <2021010028191300080949@tradepro.net>

Hello,
This is Donnie from Sihovision which is professional manufacturer of industrial monitor in Shenzhen,China. 
I'd like to introduce a new model industrial monitor(SL700M), it is the best prric/quality ratio industrial touch monitor in the matket. 
Size options:  7'', 8'', 10.1'', 10.4'', 11.6'', 12'', 15'', 15.6'', 17'', 17.3'', 19'', 21.5''
Wecome inquiry!
-------------------------------
Best regards,
Donnie Nie
SHINHO ELECTRONIC
www.sihovision.com
TEL/Whatsapp: 0086 13163734006
Skype: donnie.shinho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/c6a0554b/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-1.jpg
Type: image/jpeg
Size: 33868 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/c6a0554b/attachment-0006.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-2.jpg
Type: image/jpeg
Size: 35170 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/c6a0554b/attachment-0007.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-3.jpg
Type: image/jpeg
Size: 30491 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/c6a0554b/attachment-0008.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-4.jpg
Type: image/jpeg
Size: 31279 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/c6a0554b/attachment-0009.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SL700M-5.jpg
Type: image/jpeg
Size: 17113 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/c6a0554b/attachment-0010.jpg>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: logo2.jpg
Type: image/jpeg
Size: 2231 bytes
Desc: Photo
URL: <http://lists.infradead.org/pipermail/barebox/attachments/20210128/c6a0554b/attachment-0011.jpg>

From u.kleine-koenig at pengutronix.de  Thu Jan 28 08:34:16 2021
From: u.kleine-koenig at pengutronix.de (=?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?=)
Date: Thu, 28 Jan 2021 14:34:16 +0100
Subject: [PATCH] scripts: Replace license and copyright boilerplate by SPDX
 identifiers
Message-ID: <20210128133416.27579-1-u.kleine-koenig@pengutronix.de>

Convert the files that licensecheck can determine to be licensed under
GPL-2.0-only or GPL-2.0-or-later and also convert the copyright statements
to SPDX.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
---
 scripts/bareboxcrc32.c                       | 19 ++++------------
 scripts/bareboxenv.c                         | 19 ++++------------
 scripts/bareboximd.c                         | 16 ++-----------
 scripts/imx/imx.c                            | 16 ++-----------
 scripts/include/asm-generic/barrier.h        | 11 +++------
 scripts/include/linux/log2.h                 | 14 ++++--------
 scripts/kwbimage.c                           | 16 +++----------
 scripts/mk-omap-image.c                      | 24 ++++----------------
 scripts/mkimage.c                            | 22 +++---------------
 scripts/mkublheader.c                        | 23 ++++---------------
 scripts/mod/sumversion.c                     | 16 +++++--------
 scripts/omap3-usb-loader.c                   | 20 ++++------------
 scripts/omap4_usbboot.c                      | 16 +++----------
 scripts/omap_signGP.c                        | 14 +++---------
 scripts/s5p_cksum.c                          | 15 ++----------
 scripts/setupmbr/setupmbr.c                  | 17 ++------------
 scripts/tegra/bct_dump.c                     | 17 ++------------
 scripts/tegra/cbootimage.c                   | 17 ++------------
 scripts/tegra/cbootimage.h                   | 17 ++------------
 scripts/tegra/context.c                      | 17 ++------------
 scripts/tegra/context.h                      | 17 ++------------
 scripts/tegra/crypto.c                       | 17 ++------------
 scripts/tegra/crypto.h                       | 17 ++------------
 scripts/tegra/data_layout.c                  | 17 ++------------
 scripts/tegra/data_layout.h                  | 17 ++------------
 scripts/tegra/nvaes_ref.h                    | 17 ++------------
 scripts/tegra/parse.c                        | 17 ++------------
 scripts/tegra/parse.h                        | 17 ++------------
 scripts/tegra/set.c                          | 17 ++------------
 scripts/tegra/set.h                          | 17 ++------------
 scripts/tegra/t114/nvbctlib_t114.c           | 17 ++------------
 scripts/tegra/t114/nvboot_bct_t114.h         | 17 ++------------
 scripts/tegra/t114/nvboot_sdram_param_t114.h | 17 ++------------
 scripts/tegra/t114/parse_t114.c              | 17 ++------------
 scripts/tegra/t124/nvbctlib_t124.c           | 17 ++------------
 scripts/tegra/t124/nvboot_bct_t124.h         | 17 ++------------
 scripts/tegra/t124/nvboot_sdram_param_t124.h | 17 ++------------
 scripts/tegra/t124/parse_t124.c              | 17 ++------------
 scripts/tegra/t20/nvbctlib_t20.c             | 17 ++------------
 scripts/tegra/t20/nvboot_bct_t20.h           | 17 ++------------
 scripts/tegra/t20/nvboot_sdram_param_t20.h   | 17 ++------------
 scripts/tegra/t20/parse_t20.c                | 17 ++------------
 scripts/tegra/t30/nvbctlib_t30.c             | 17 ++------------
 scripts/tegra/t30/nvboot_bct_t30.h           | 17 ++------------
 scripts/tegra/t30/nvboot_sdram_param_t30.h   | 17 ++------------
 scripts/tegra/t30/parse_t30.c                | 17 ++------------
 scripts/zynq_mkimage.c                       | 15 ++----------
 47 files changed, 117 insertions(+), 686 deletions(-)

diff --git a/scripts/bareboxcrc32.c b/scripts/bareboxcrc32.c
index 409e1cbba36f..6d39fa047d09 100644
--- a/scripts/bareboxcrc32.c
+++ b/scripts/bareboxcrc32.c
@@ -1,18 +1,7 @@
-/*
- * bareboxcrc32.c - generate crc32 checksum in little endian
- *
- * Copyright (c) 2013 Michael Grzeschik <mgr at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2013 Michael Grzeschik <mgr at pengutronix.de>
+
+/* bareboxcrc32.c - generate crc32 checksum in little endian */
 
 #include <stdio.h>
 #include <sys/types.h>
diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c
index 3c743435fe48..bdff64433591 100644
--- a/scripts/bareboxenv.c
+++ b/scripts/bareboxenv.c
@@ -1,18 +1,7 @@
-/*
- * bareboxenv.c - generate or read a barebox environment archive
- *
- * Copyright (c) 2007 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2007 Sascha Hauer <s.hauer at pengutronix.de>, Pengutronix
+
+/* bareboxenv.c - generate or read a barebox environment archive */
 
 #include <stdio.h>
 #include <sys/types.h>
diff --git a/scripts/bareboximd.c b/scripts/bareboximd.c
index 0500e01cc224..9558c77d1a22 100644
--- a/scripts/bareboximd.c
+++ b/scripts/bareboximd.c
@@ -1,17 +1,5 @@
-/*
- * (C) Copyright 2014 Sascha Hauer, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2014 Sascha Hauer, Pengutronix
 
 #include <stdio.h>
 #include <sys/types.h>
diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c
index e9f05b83a3ca..6b8dabd047d0 100644
--- a/scripts/imx/imx.c
+++ b/scripts/imx/imx.c
@@ -1,17 +1,5 @@
-/*
- * (C) Copyright 2016 Sascha Hauer, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2016 Sascha Hauer, Pengutronix
 
 #define _GNU_SOURCE
 #include <stdio.h>
diff --git a/scripts/include/asm-generic/barrier.h b/scripts/include/asm-generic/barrier.h
index 47b933903eaf..2e78c3f328fc 100644
--- a/scripts/include/asm-generic/barrier.h
+++ b/scripts/include/asm-generic/barrier.h
@@ -1,3 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2007 Red Hat (David Howells <dhowells at redhat.com>) */
+
 /*
  * Copied from the kernel sources to tools/perf/:
  *
@@ -5,14 +8,6 @@
  *
  * It should be possible to use these on really simple architectures,
  * but it serves more as a starting point for new ports.
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells at redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public Licence
- * as published by the Free Software Foundation; either version
- * 2 of the Licence, or (at your option) any later version.
  */
 #ifndef __TOOLS_LINUX_ASM_GENERIC_BARRIER_H
 #define __TOOLS_LINUX_ASM_GENERIC_BARRIER_H
diff --git a/scripts/include/linux/log2.h b/scripts/include/linux/log2.h
index 41446668ccce..abc38f4c632d 100644
--- a/scripts/include/linux/log2.h
+++ b/scripts/include/linux/log2.h
@@ -1,13 +1,7 @@
-/* Integer base 2 logarithm calculation
- *
- * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells at redhat.com)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: 2006 Red Hat (David Howells <dhowells at redhat.com>) */
+
+/* Integer base 2 logarithm calculation */
 
 #ifndef _TOOLS_LINUX_LOG2_H
 #define _TOOLS_LINUX_LOG2_H
diff --git a/scripts/kwbimage.c b/scripts/kwbimage.c
index 75c9e9cda9c2..28c9a68e1871 100644
--- a/scripts/kwbimage.c
+++ b/scripts/kwbimage.c
@@ -1,20 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2013 Thomas Petazzoni <thomas.petazzoni at free-electrons.com>
+
 /*
  * Image manipulator for Marvell SoCs
  *  supports Kirkwood, Dove, Armada 370, and Armada XP
  *
- * (C) Copyright 2013 Thomas Petazzoni
- * <thomas.petazzoni at free-electrons.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
  * This tool allows to extract and create bootable images for Marvell
  * Kirkwood, Dove, Armada 370, and Armada XP SoCs. It supports two
  * versions of the bootable image format: version 0 (used on Marvell
diff --git a/scripts/mk-omap-image.c b/scripts/mk-omap-image.c
index 234b7e37c2a0..5741b0afbc76 100644
--- a/scripts/mk-omap-image.c
+++ b/scripts/mk-omap-image.c
@@ -1,22 +1,8 @@
-/*
- * mk-am35xx-spi-image.c - convert a barebox image for SPI loading on AM35xx
- *
- * Copyright (C) 2012 Jan Luebbe <j.luebbe at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2012 Jan Luebbe <j.luebbe at pengutronix.de>
+
+/* mk-am35xx-spi-image.c - convert a barebox image for SPI loading on AM35xx */
+
 /**
  * @file
  * @brief convert a barebox image for SPI loading on AM35xx
diff --git a/scripts/mkimage.c b/scripts/mkimage.c
index 7d283c550930..a76c061aee3b 100644
--- a/scripts/mkimage.c
+++ b/scripts/mkimage.c
@@ -1,22 +1,6 @@
-/*
- * (C) Copyright 2008 Semihalf
- *
- * (C) Copyright 2000-2004
- * DENX Software Engineering
- * Wolfgang Denk, wd at denx.de
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2008 Semihalf
+// SPDX-FileCopyrightText: 2000-2004 DENX Software Engineering (Wolfgang Denk <wd at denx.de>)
 
 #include <sys/stat.h>
 #include <time.h>
diff --git a/scripts/mkublheader.c b/scripts/mkublheader.c
index 496ba0b5001c..db3e284a8ad6 100644
--- a/scripts/mkublheader.c
+++ b/scripts/mkublheader.c
@@ -1,22 +1,7 @@
-/*
- * mkublheader.c - produce the header needed to load barebox on OMAP-L138
- *
- * Copyright (C) 2012 Jan Luebbe <j.luebbe at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2012 Jan Luebbe <j.luebbe at pengutronix.de>
+
+/* mkublheader.c - produce the header needed to load barebox on OMAP-L138 */
 
 #define _BSD_SOURCE
 #define _DEFAULT_SOURCE
diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c
index d9cc6901d680..b5f1824a6934 100644
--- a/scripts/mod/sumversion.c
+++ b/scripts/mod/sumversion.c
@@ -1,3 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 1997-1998 Andrew Tridgell
+// SPDX-FileCopyrightText: Cryptoapi developers.
+// SPDX-FileCopyrightText: 2002 David S. Miller <davem at redhat.com>
+// SPDX-FileCopyrightText: 2002 James Morris <jmorris at intercode.com.au>
+
 #include <netinet/in.h>
 #ifdef __sun__
 #include <inttypes.h>
@@ -20,17 +26,7 @@
  * originally based on the public domain implementation written
  * by Colin Plumb in 1993.
  *
- * Copyright (c) Andrew Tridgell 1997-1998.
  * Modified by Steve French (sfrench at us.ibm.com) 2002
- * Copyright (c) Cryptoapi developers.
- * Copyright (c) 2002 David S. Miller (davem at redhat.com)
- * Copyright (c) 2002 James Morris <jmorris at intercode.com.au>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
  */
 #define MD4_DIGEST_SIZE		16
 #define MD4_HMAC_BLOCK_SIZE	64
diff --git a/scripts/omap3-usb-loader.c b/scripts/omap3-usb-loader.c
index ae6f1258df05..599a93856ac3 100644
--- a/scripts/omap3-usb-loader.c
+++ b/scripts/omap3-usb-loader.c
@@ -1,18 +1,8 @@
-/*
- * OMAP Loader, a USB uploader application targeted at OMAP3 processors
- * Copyright (C) 2008 Martin Mueller <martinmm at pfump.org>
- * Copyright (C) 2014 Grant Hernandez <grant.h.hernandez at gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2008 Martin Mueller <martinmm at pfump.org>
+// SPDX-FileCopyrightText: 2014 Grant Hernandez <grant.h.hernandez at gmail.com>
+
+/* OMAP Loader, a USB uploader application targeted at OMAP3 processors */
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/scripts/omap4_usbboot.c b/scripts/omap4_usbboot.c
index 44236259dca5..342efd0c9a40 100644
--- a/scripts/omap4_usbboot.c
+++ b/scripts/omap4_usbboot.c
@@ -1,16 +1,6 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * Inspired by: https://github.com/simu/usbboot-omap4.git
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/* Inspired by: https://github.com/simu/usbboot-omap4.git */
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/scripts/omap_signGP.c b/scripts/omap_signGP.c
index ac47fdf08988..b89414931e70 100644
--- a/scripts/omap_signGP.c
+++ b/scripts/omap_signGP.c
@@ -1,3 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2010 Texas Instruments Incorporated (http://www.ti.com/)
+
 /**
  * signGP.c - Read the x-load.bin file and write out the x-load.bin.ift file
  *
@@ -5,17 +8,6 @@
  * and the load address.  If not entered on command line, file name is
  * assumed to be x-load.bin in current directory and load address is
  * 0x40200800.
- *
- * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2  of
- * the License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <stdio.h>
diff --git a/scripts/s5p_cksum.c b/scripts/s5p_cksum.c
index 29cf539a2845..0f53ee1dd238 100644
--- a/scripts/s5p_cksum.c
+++ b/scripts/s5p_cksum.c
@@ -1,16 +1,5 @@
-/*
- * Copyright (C) 2012 Alexey Galakhov
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 Alexey Galakhov
 
 #include <stdio.h>
 #include <stdint.h>
diff --git a/scripts/setupmbr/setupmbr.c b/scripts/setupmbr/setupmbr.c
index 1487498f1f2a..38af55080907 100644
--- a/scripts/setupmbr/setupmbr.c
+++ b/scripts/setupmbr/setupmbr.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (C) 2009 Juergen Beisert, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- *
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2009 Juergen Beisert, Pengutronix
 
 /**
  * @file
diff --git a/scripts/tegra/bct_dump.c b/scripts/tegra/bct_dump.c
index 74f4d595e073..bf4c146bac49 100644
--- a/scripts/tegra/bct_dump.c
+++ b/scripts/tegra/bct_dump.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 #include "cbootimage.h"
 #include "data_layout.h"
diff --git a/scripts/tegra/cbootimage.c b/scripts/tegra/cbootimage.c
index d64f322f11d9..7714893d2861 100644
--- a/scripts/tegra/cbootimage.c
+++ b/scripts/tegra/cbootimage.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 /*
  * cbootimage.c - Implementation of the cbootimage tool.
diff --git a/scripts/tegra/cbootimage.h b/scripts/tegra/cbootimage.h
index 04d1a8b2749a..99b37d156358 100644
--- a/scripts/tegra/cbootimage.h
+++ b/scripts/tegra/cbootimage.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 /*
  * cbootimage.h - Definitions for the cbootimage code.
diff --git a/scripts/tegra/context.c b/scripts/tegra/context.c
index 47e65d570bdc..93a5e33ce1c6 100644
--- a/scripts/tegra/context.c
+++ b/scripts/tegra/context.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 #include "cbootimage.h"
 #include "data_layout.h"
diff --git a/scripts/tegra/context.h b/scripts/tegra/context.h
index bdfa25b45135..f0f5d0587adb 100644
--- a/scripts/tegra/context.h
+++ b/scripts/tegra/context.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 #ifndef INCLUDED_CONTEXT_H
 #define INCLUDED_CONTEXT_H
diff --git a/scripts/tegra/crypto.c b/scripts/tegra/crypto.c
index e40f56e47411..17d422990bde 100644
--- a/scripts/tegra/crypto.c
+++ b/scripts/tegra/crypto.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 /*
  * crypto.c - Cryptography support
diff --git a/scripts/tegra/crypto.h b/scripts/tegra/crypto.h
index 2220ac83671e..db687d037170 100644
--- a/scripts/tegra/crypto.h
+++ b/scripts/tegra/crypto.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 /*
  * crypto.h - Definitions for the crypto support.
diff --git a/scripts/tegra/data_layout.c b/scripts/tegra/data_layout.c
index 99ae8d92c8d9..abfbf6efae8d 100644
--- a/scripts/tegra/data_layout.c
+++ b/scripts/tegra/data_layout.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 /*
  * data_layout.c - Code to manage the layout of data in the boot device.
diff --git a/scripts/tegra/data_layout.h b/scripts/tegra/data_layout.h
index c708da4a1579..002a1ab43e9c 100644
--- a/scripts/tegra/data_layout.h
+++ b/scripts/tegra/data_layout.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 /*
  * data_layout.h - Definitions for the cbootimage data layout code.
diff --git a/scripts/tegra/nvaes_ref.h b/scripts/tegra/nvaes_ref.h
index 1d06e7190327..7a7e5ec3bf65 100644
--- a/scripts/tegra/nvaes_ref.h
+++ b/scripts/tegra/nvaes_ref.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 #include "cbootimage.h"
 #include "string.h"
diff --git a/scripts/tegra/parse.c b/scripts/tegra/parse.c
index 9180adfda390..d861deed17cb 100644
--- a/scripts/tegra/parse.c
+++ b/scripts/tegra/parse.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 /*
  * parse.c - Parsing support for the cbootimage tool
diff --git a/scripts/tegra/parse.h b/scripts/tegra/parse.h
index 7402a1dd9870..2d953bb85876 100644
--- a/scripts/tegra/parse.h
+++ b/scripts/tegra/parse.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 /*
  * parse.h - Definitions for the cbootimage parsing code.
diff --git a/scripts/tegra/set.c b/scripts/tegra/set.c
index 1c5e8dda8c7d..9de879f22e1b 100644
--- a/scripts/tegra/set.c
+++ b/scripts/tegra/set.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 /*
  * set.c - State setting support for the cbootimage tool
diff --git a/scripts/tegra/set.h b/scripts/tegra/set.h
index 7e7245aaf4f8..0b905fd050a5 100644
--- a/scripts/tegra/set.h
+++ b/scripts/tegra/set.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 /*
  * set.h - Definitions for the cbootimage state setting code.
diff --git a/scripts/tegra/t114/nvbctlib_t114.c b/scripts/tegra/t114/nvbctlib_t114.c
index 3bda785f5739..1085146ee065 100644
--- a/scripts/tegra/t114/nvbctlib_t114.c
+++ b/scripts/tegra/t114/nvbctlib_t114.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 #include "../cbootimage.h"
 #include "../parse.h"
diff --git a/scripts/tegra/t114/nvboot_bct_t114.h b/scripts/tegra/t114/nvboot_bct_t114.h
index a2a6b865f67f..9b8e20ae4a6d 100644
--- a/scripts/tegra/t114/nvboot_bct_t114.h
+++ b/scripts/tegra/t114/nvboot_bct_t114.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 #ifndef INCLUDED_NVBOOT_BCT_T114_H
 #define INCLUDED_NVBOOT_BCT_T114_H
diff --git a/scripts/tegra/t114/nvboot_sdram_param_t114.h b/scripts/tegra/t114/nvboot_sdram_param_t114.h
index 78151dcfb843..2f8f0407f107 100644
--- a/scripts/tegra/t114/nvboot_sdram_param_t114.h
+++ b/scripts/tegra/t114/nvboot_sdram_param_t114.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 /**
  * Defines the SDRAM parameter structure.
diff --git a/scripts/tegra/t114/parse_t114.c b/scripts/tegra/t114/parse_t114.c
index 79c2ed8f53cf..0f6d4dbcddb7 100644
--- a/scripts/tegra/t114/parse_t114.c
+++ b/scripts/tegra/t114/parse_t114.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 /*
  * parse_t114.h - Definitions for the dev/sdram parameters
diff --git a/scripts/tegra/t124/nvbctlib_t124.c b/scripts/tegra/t124/nvbctlib_t124.c
index 55b840926eac..9cc312b2e4b9 100644
--- a/scripts/tegra/t124/nvbctlib_t124.c
+++ b/scripts/tegra/t124/nvbctlib_t124.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2013 NVIDIA CORPORATION
 
 #include "../cbootimage.h"
 #include "../parse.h"
diff --git a/scripts/tegra/t124/nvboot_bct_t124.h b/scripts/tegra/t124/nvboot_bct_t124.h
index bc07add3dbda..479ce976540b 100644
--- a/scripts/tegra/t124/nvboot_bct_t124.h
+++ b/scripts/tegra/t124/nvboot_bct_t124.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2013 NVIDIA CORPORATION */
 
 #ifndef INCLUDED_NVBOOT_BCT_T124_H
 #define INCLUDED_NVBOOT_BCT_T124_H
diff --git a/scripts/tegra/t124/nvboot_sdram_param_t124.h b/scripts/tegra/t124/nvboot_sdram_param_t124.h
index bae40b135371..46adba519b56 100644
--- a/scripts/tegra/t124/nvboot_sdram_param_t124.h
+++ b/scripts/tegra/t124/nvboot_sdram_param_t124.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2013 NVIDIA CORPORATION */
 
 /**
  * Defines the SDRAM parameter structure.
diff --git a/scripts/tegra/t124/parse_t124.c b/scripts/tegra/t124/parse_t124.c
index 8468209b610c..8a63dd237786 100644
--- a/scripts/tegra/t124/parse_t124.c
+++ b/scripts/tegra/t124/parse_t124.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2013 NVIDIA CORPORATION
 
 /*
  * parse_t124.c - The implementation for parsing dev/sdram parameters
diff --git a/scripts/tegra/t20/nvbctlib_t20.c b/scripts/tegra/t20/nvbctlib_t20.c
index 42ad1467555f..972c37befe53 100644
--- a/scripts/tegra/t20/nvbctlib_t20.c
+++ b/scripts/tegra/t20/nvbctlib_t20.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 #include "../cbootimage.h"
 #include "../parse.h"
diff --git a/scripts/tegra/t20/nvboot_bct_t20.h b/scripts/tegra/t20/nvboot_bct_t20.h
index bf94d50b400e..97ceeed659fc 100644
--- a/scripts/tegra/t20/nvboot_bct_t20.h
+++ b/scripts/tegra/t20/nvboot_bct_t20.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 #ifndef INCLUDED_NVBOOT_BCT_T20_H
 #define INCLUDED_NVBOOT_BCT_T20_H
diff --git a/scripts/tegra/t20/nvboot_sdram_param_t20.h b/scripts/tegra/t20/nvboot_sdram_param_t20.h
index de002f0c38c6..397397a0cde9 100644
--- a/scripts/tegra/t20/nvboot_sdram_param_t20.h
+++ b/scripts/tegra/t20/nvboot_sdram_param_t20.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 /**
  * Defines the SDRAM parameter structure.
diff --git a/scripts/tegra/t20/parse_t20.c b/scripts/tegra/t20/parse_t20.c
index 5db74d559721..c613ecf85e87 100644
--- a/scripts/tegra/t20/parse_t20.c
+++ b/scripts/tegra/t20/parse_t20.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 /*
  * parse_t20.c - Parsing code for t20
diff --git a/scripts/tegra/t30/nvbctlib_t30.c b/scripts/tegra/t30/nvbctlib_t30.c
index 04e8974fbfc2..77c4aceb0acb 100644
--- a/scripts/tegra/t30/nvbctlib_t30.c
+++ b/scripts/tegra/t30/nvbctlib_t30.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 #include "../cbootimage.h"
 #include "../parse.h"
diff --git a/scripts/tegra/t30/nvboot_bct_t30.h b/scripts/tegra/t30/nvboot_bct_t30.h
index c5fee4c0a2db..5f4997ed8e37 100644
--- a/scripts/tegra/t30/nvboot_bct_t30.h
+++ b/scripts/tegra/t30/nvboot_bct_t30.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 #ifndef INCLUDED_NVBOOT_BCT_T30_H
 #define INCLUDED_NVBOOT_BCT_T30_H
diff --git a/scripts/tegra/t30/nvboot_sdram_param_t30.h b/scripts/tegra/t30/nvboot_sdram_param_t30.h
index 24c176858f18..fb0dffa0a02f 100644
--- a/scripts/tegra/t30/nvboot_sdram_param_t30.h
+++ b/scripts/tegra/t30/nvboot_sdram_param_t30.h
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION */
 
 /**
  * Defines the SDRAM parameter structure.
diff --git a/scripts/tegra/t30/parse_t30.c b/scripts/tegra/t30/parse_t30.c
index e5f4e93b2809..bd85a96d12b6 100644
--- a/scripts/tegra/t30/parse_t30.c
+++ b/scripts/tegra/t30/parse_t30.c
@@ -1,18 +1,5 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: 2012 NVIDIA CORPORATION
 
 /*
  * parse_t30.h - Definitions for the dev/sdram parameters
diff --git a/scripts/zynq_mkimage.c b/scripts/zynq_mkimage.c
index a211b79c2872..8b95b4196089 100644
--- a/scripts/zynq_mkimage.c
+++ b/scripts/zynq_mkimage.c
@@ -1,16 +1,5 @@
-/*
- * Copyright (C) 2013 Steffen Trumtrar <s.trumtrar at pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2013 Steffen Trumtrar <s.trumtrar at pengutronix.de>
 
 #include <endian.h>
 #include <errno.h>
-- 
2.29.2



From sha at pengutronix.de  Thu Jan 28 09:52:35 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 28 Jan 2021 15:52:35 +0100
Subject: [PATCH v2 1/3] ARM: i.MX: move BCB structures to header file
In-Reply-To: <20210127075115.63425-1-andrej.picej@norik.com>
References: <20210127075115.63425-1-andrej.picej@norik.com>
Message-ID: <20210128145235.GA19583@pengutronix.de>

On Wed, Jan 27, 2021 at 08:51:13AM +0100, Andrej Picej wrote:
> From: Primoz Fiser <primoz.fiser at norik.com>
> 
> Move i.MX BCB related structures to header file so they can be used by
> others.
> 
> Signed-off-by: Primoz Fiser <primoz.fiser at norik.com>
> Signed-off-by: Andrej Picej <andrej.picej at norik.com>
> ---
> v2:
> - no changes
> 
>  arch/arm/mach-imx/include/mach/imx-nand-bcb.h | 80 +++++++++++++++++++
>  common/imx-bbu-nand-fcb.c                     | 69 +---------------
>  2 files changed, 81 insertions(+), 68 deletions(-)
>  create mode 100644 arch/arm/mach-imx/include/mach/imx-nand-bcb.h

Applied, thanks

Sascha

> 
> diff --git a/arch/arm/mach-imx/include/mach/imx-nand-bcb.h b/arch/arm/mach-imx/include/mach/imx-nand-bcb.h
> new file mode 100644
> index 000000000..b60205bd5
> --- /dev/null
> +++ b/arch/arm/mach-imx/include/mach/imx-nand-bcb.h
> @@ -0,0 +1,80 @@
> +#ifndef __MACH_IMX_NAND_BCB_H
> +#define __MACH_IMX_NAND_BCB_H
> +
> +#define	FCB_FINGERPRINT		0x20424346	/* 'FCB' */
> +#define	FCB_VERSION_1		0x01000000
> +#define	FCB_FINGERPRINT_OFF	0x4		/* FCB fingerprint offset*/
> +
> +#define	DBBT_FINGERPRINT	0x54424244	/* 'DBBT' */
> +#define	DBBT_VERSION_1		0x01000000
> +#define	DBBT_FINGERPRINT_OFF	0x4		/* DBBT fingerprint offset*/
> +
> +struct dbbt_block {
> +	uint32_t Checksum;
> +	uint32_t FingerPrint;
> +	uint32_t Version;
> +	uint32_t numberBB; /* reserved on i.MX6 */
> +	uint32_t DBBTNumOfPages;
> +};
> +
> +struct fcb_block {
> +	uint32_t Checksum;		/* First fingerprint in first byte */
> +	uint32_t FingerPrint;		/* 2nd fingerprint at byte 4 */
> +	uint32_t Version;		/* 3rd fingerprint at byte 8 */
> +	uint8_t DataSetup;
> +	uint8_t DataHold;
> +	uint8_t AddressSetup;
> +	uint8_t DSAMPLE_TIME;
> +	/* These are for application use only and not for ROM. */
> +	uint8_t NandTimingState;
> +	uint8_t REA;
> +	uint8_t RLOH;
> +	uint8_t RHOH;
> +	uint32_t PageDataSize;		/* 2048 for 2K pages, 4096 for 4K pages */
> +	uint32_t TotalPageSize;		/* 2112 for 2K pages, 4314 for 4K pages */
> +	uint32_t SectorsPerBlock;	/* Number of 2K sections per block */
> +	uint32_t NumberOfNANDs;		/* Total Number of NANDs - not used by ROM */
> +	uint32_t TotalInternalDie;	/* Number of separate chips in this NAND */
> +	uint32_t CellType;		/* MLC or SLC */
> +	uint32_t EccBlockNEccType;	/* Type of ECC, can be one of BCH-0-20 */
> +	uint32_t EccBlock0Size;		/* Number of bytes for Block0 - BCH */
> +	uint32_t EccBlockNSize;		/* Block size in bytes for all blocks other than Block0 - BCH */
> +	uint32_t EccBlock0EccType;	/* Ecc level for Block 0 - BCH */
> +	uint32_t MetadataBytes;		/* Metadata size - BCH */
> +	uint32_t NumEccBlocksPerPage;	/* Number of blocks per page for ROM use - BCH */
> +	uint32_t EccBlockNEccLevelSDK;	/* Type of ECC, can be one of BCH-0-20 */
> +	uint32_t EccBlock0SizeSDK;	/* Number of bytes for Block0 - BCH */
> +	uint32_t EccBlockNSizeSDK;	/* Block size in bytes for all blocks other than Block0 - BCH */
> +	uint32_t EccBlock0EccLevelSDK;	/* Ecc level for Block 0 - BCH */
> +	uint32_t NumEccBlocksPerPageSDK;/* Number of blocks per page for SDK use - BCH */
> +	uint32_t MetadataBytesSDK;	/* Metadata size - BCH */
> +	uint32_t EraseThreshold;	/* To set into BCH_MODE register */
> +	uint32_t BootPatch;		/* 0 for normal boot and 1 to load patch starting next to FCB */
> +	uint32_t PatchSectors;		/* Size of patch in sectors */
> +	uint32_t Firmware1_startingPage;/* Firmware image starts on this sector */
> +	uint32_t Firmware2_startingPage;/* Secondary FW Image starting Sector */
> +	uint32_t PagesInFirmware1;	/* Number of sectors in firmware image */
> +	uint32_t PagesInFirmware2;	/* Number of sector in secondary FW image */
> +	uint32_t DBBTSearchAreaStartAddress; /* Page address where dbbt search area begins */
> +	uint32_t BadBlockMarkerByte;	/* Byte in page data that have manufacturer marked bad block marker, */
> +					/* this will be swapped with metadata[0] to complete page data. */
> +	uint32_t BadBlockMarkerStartBit;/* For BCH ECC sizes other than 8 and 16 the bad block marker does not */
> +					/* start at 0th bit of BadBlockMarkerByte. This field is used to get to */
> +					/* the start bit of bad block marker byte with in BadBlockMarkerByte */
> +	uint32_t BBMarkerPhysicalOffset;/* FCB value that gives byte offset for bad block marker on physical NAND page */
> +	uint32_t BCHType;
> +
> +	uint32_t TMTiming2_ReadLatency;
> +	uint32_t TMTiming2_PreambleDelay;
> +	uint32_t TMTiming2_CEDelay;
> +	uint32_t TMTiming2_PostambleDelay;
> +	uint32_t TMTiming2_CmdAddPause;
> +	uint32_t TMTiming2_DataPause;
> +	uint32_t TMSpeed;
> +	uint32_t TMTiming1_BusyTimeout;
> +
> +	uint32_t DISBBM;	/* the flag to enable (1)/disable(0) bi swap */
> +	uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
> +};
> +
> +#endif /* __MACH_IMX_NAND_BCB_H */
> diff --git a/common/imx-bbu-nand-fcb.c b/common/imx-bbu-nand-fcb.c
> index f8c457805..a08a1d834 100644
> --- a/common/imx-bbu-nand-fcb.c
> +++ b/common/imx-bbu-nand-fcb.c
> @@ -25,6 +25,7 @@
>  #include <crc.h>
>  #include <mach/generic.h>
>  #include <mtd/mtd-peb.h>
> +#include <mach/imx-nand-bcb.h>
>  
>  #ifdef CONFIG_ARCH_IMX6
>  #include <mach/imx6.h>
> @@ -39,74 +40,6 @@ static inline int fcb_is_bch_encoded(void)
>  }
>  #endif
>  
> -struct dbbt_block {
> -	uint32_t Checksum;
> -	uint32_t FingerPrint;
> -	uint32_t Version;
> -	uint32_t numberBB; /* reserved on i.MX6 */
> -	uint32_t DBBTNumOfPages;
> -};
> -
> -struct fcb_block {
> -	uint32_t Checksum;		/* First fingerprint in first byte */
> -	uint32_t FingerPrint;		/* 2nd fingerprint at byte 4 */
> -	uint32_t Version;		/* 3rd fingerprint at byte 8 */
> -	uint8_t DataSetup;
> -	uint8_t DataHold;
> -	uint8_t AddressSetup;
> -	uint8_t DSAMPLE_TIME;
> -	/* These are for application use only and not for ROM. */
> -	uint8_t NandTimingState;
> -	uint8_t REA;
> -	uint8_t RLOH;
> -	uint8_t RHOH;
> -	uint32_t PageDataSize;		/* 2048 for 2K pages, 4096 for 4K pages */
> -	uint32_t TotalPageSize;		/* 2112 for 2K pages, 4314 for 4K pages */
> -	uint32_t SectorsPerBlock;	/* Number of 2K sections per block */
> -	uint32_t NumberOfNANDs;		/* Total Number of NANDs - not used by ROM */
> -	uint32_t TotalInternalDie;	/* Number of separate chips in this NAND */
> -	uint32_t CellType;		/* MLC or SLC */
> -	uint32_t EccBlockNEccType;	/* Type of ECC, can be one of BCH-0-20 */
> -	uint32_t EccBlock0Size;		/* Number of bytes for Block0 - BCH */
> -	uint32_t EccBlockNSize;		/* Block size in bytes for all blocks other than Block0 - BCH */
> -	uint32_t EccBlock0EccType;	/* Ecc level for Block 0 - BCH */
> -	uint32_t MetadataBytes;		/* Metadata size - BCH */
> -	uint32_t NumEccBlocksPerPage;	/* Number of blocks per page for ROM use - BCH */
> -	uint32_t EccBlockNEccLevelSDK;	/* Type of ECC, can be one of BCH-0-20 */
> -	uint32_t EccBlock0SizeSDK;	/* Number of bytes for Block0 - BCH */
> -	uint32_t EccBlockNSizeSDK;	/* Block size in bytes for all blocks other than Block0 - BCH */
> -	uint32_t EccBlock0EccLevelSDK;	/* Ecc level for Block 0 - BCH */
> -	uint32_t NumEccBlocksPerPageSDK;/* Number of blocks per page for SDK use - BCH */
> -	uint32_t MetadataBytesSDK;	/* Metadata size - BCH */
> -	uint32_t EraseThreshold;	/* To set into BCH_MODE register */
> -	uint32_t BootPatch;		/* 0 for normal boot and 1 to load patch starting next to FCB */
> -	uint32_t PatchSectors;		/* Size of patch in sectors */
> -	uint32_t Firmware1_startingPage;/* Firmware image starts on this sector */
> -	uint32_t Firmware2_startingPage;/* Secondary FW Image starting Sector */
> -	uint32_t PagesInFirmware1;	/* Number of sectors in firmware image */
> -	uint32_t PagesInFirmware2;	/* Number of sector in secondary FW image */
> -	uint32_t DBBTSearchAreaStartAddress; /* Page address where dbbt search area begins */
> -	uint32_t BadBlockMarkerByte;	/* Byte in page data that have manufacturer marked bad block marker, */
> -					/* this will be swapped with metadata[0] to complete page data. */
> -	uint32_t BadBlockMarkerStartBit;/* For BCH ECC sizes other than 8 and 16 the bad block marker does not */
> -					/* start at 0th bit of BadBlockMarkerByte. This field is used to get to */
> -					/* the start bit of bad block marker byte with in BadBlockMarkerByte */
> -	uint32_t BBMarkerPhysicalOffset;/* FCB value that gives byte offset for bad block marker on physical NAND page */
> -	uint32_t BCHType;
> -
> -	uint32_t TMTiming2_ReadLatency;
> -	uint32_t TMTiming2_PreambleDelay;
> -	uint32_t TMTiming2_CEDelay;
> -	uint32_t TMTiming2_PostambleDelay;
> -	uint32_t TMTiming2_CmdAddPause;
> -	uint32_t TMTiming2_DataPause;
> -	uint32_t TMSpeed;
> -	uint32_t TMTiming1_BusyTimeout;
> -
> -	uint32_t DISBBM;	/* the flag to enable (1)/disable(0) bi swap */
> -	uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
> -};
> -
>  struct imx_nand_fcb_bbu_handler {
>  	struct bbu_handler handler;
>  
> -- 
> 2.25.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Thu Jan 28 10:10:11 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 28 Jan 2021 16:10:11 +0100
Subject: [PATCH v2 09/12] of: of_firmware: add support for fpga bridges
In-Reply-To: <20210127134423.31587-9-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
 <20210127134423.31587-9-s.trumtrar@pengutronix.de>
Message-ID: <20210128151011.GB19583@pengutronix.de>

On Wed, Jan 27, 2021 at 02:44:20PM +0100, Steffen Trumtrar wrote:
> +static int of_load_firmware(struct device_node *target, const char *path)
> +{
> +	struct list_head bridge_list;
> +	struct firmware_mgr *mgr;
> +	int err;
> +
> +	mgr = of_node_get_mgr(target);
> +	if (!mgr)
> +		return -EINVAL;
> +
> +	pr_debug("Found firmware manager @%s\n", target->name);
> +
> +	INIT_LIST_HEAD(&bridge_list);
> +
> +	of_get_bridges(target, &bridge_list);
> +
> +	fpga_bridges_disable(&bridge_list);
> +
> +	pr_debug("Loading %s to %s\n", path, target->name);
> +
> +	err = firmwaremgr_load_file(mgr, path);
> +
> +	fpga_bridges_enable(&bridge_list);

The resources added to this list are never freed.

> +
> +	return err;
> +}
> +
>  static int load_firmware(struct device_node *target,
>  			 struct device_node *fragment, void *data)
>  {
> @@ -33,7 +100,6 @@ static int load_firmware(struct device_node *target,
>  	const char *firmware_path = info->firmware_path;
>  	char *firmware;
>  	int err;
> -	struct firmware_mgr *mgr;
>  
>  	err = of_property_read_string(fragment,
>  				      "firmware-name", &firmware_name);
> @@ -46,21 +112,73 @@ static int load_firmware(struct device_node *target,
>  	if (!target)
>  		return -EINVAL;
>  
> -	mgr = of_node_get_mgr(target);
> -	if (!mgr)
> -		return -EINVAL;
> -
>  	firmware = basprintf("%s/%s", firmware_path, firmware_name);
>  	if (!firmware)
>  		return -ENOMEM;
>  
> -	err = firmwaremgr_load_file(mgr, firmware);
> +	err = of_load_firmware(target, firmware);
>  
>  	free(firmware);
>  
>  	return err;
>  }
>  
> +int of_firmware_load_file(const char *path, const char *compatible,
> +			  const char *search_path, const char *firmware)
> +{
> +	struct overlay_info info = {
> +		.firmware_path = search_path,
> +	};
> +	struct device_node *target;
> +	struct device_node *node;
> +	struct device_node *root;
> +
> +	if (!compatible) {
> +		compatible = basprintf("fpga-region");
> +		if (!compatible)
> +			return -ENOMEM;
> +	}

compatible is not freed. The original pointer comes in as a const char *,
allocated and freed outside of this function, so you can do a plain

	if (!compatible)
		comaptible = "fpga-region";

> +
> +	/*
> +	 * firmware-name not specified. Use load_firmware function to get it from
> +	 * the devicetree. This allows loading firmware to multiple devices.
> +	 */
> +	if (!firmware && !path) {
> +		int err;
> +
> +		pr_debug("No firmware specified. Searching devicetree for %s\n", compatible);
> +		for_each_compatible_node(node, NULL, compatible) {
> +			pr_debug("Load firmware from %s\n", node->name);
> +			err = load_firmware(node, node, &info);
> +			if (err == -ENOMEM)
> +				return err;
> +		}
> +
> +		return 0;
> +	}
> +
> +	root = of_get_root_node();

root is only used in the if () path below, so you can assign it there.

> +
> +	if (path) {
> +		target = of_find_node_by_path_or_alias(root, path);
> +		if (!target) {
> +			pr_debug("Cannot find nodepath %s\n", path);
> +			return -ENOENT;
> +		}
> +	} else {
> +		target = of_find_compatible_node(NULL, NULL, compatible);
> +		if (!target) {
> +			pr_debug("No node matching %s found\n", compatible);
> +			return -ENOSYS;
> +		}
> +	}
> +	
> +	if (!firmware)
> +		return load_firmware(target, target, &info);
> +
> +	return of_load_firmware(target, firmware);
> +}
> +
>  int of_firmware_load_overlay(struct device_node *overlay, const char *path)
>  {
>  	struct overlay_info info = {
> diff --git a/include/of.h b/include/of.h
> index 645f429bdeed..b18875478dc0 100644
> --- a/include/of.h
> +++ b/include/of.h
> @@ -1020,6 +1020,23 @@ static inline struct device_node *of_find_root_node(struct device_node *node)
>  	return node;
>  }
>  
> +#ifdef CONFIG_FIRMWARE
> +int of_firmware_load_file(const char *path, const char *compatible,
> +			  const char *search_path, const char *firmware);
> +int of_firmware_load_overlay(struct device_node *overlay, const char *path);
> +#else
> +int of_firmware_load_file(const char *path, const char *compatible,
> +			  const char *search_path, const char *firmware)
> +{
> +	return -ENOSYS;
> +}
> +
> +static inline int of_firmware_load_overlay(const char *path)
> +{
> +	return -ENOSYS;
> +}
> +#endif
> +
>  #ifdef CONFIG_OF_OVERLAY
>  struct device_node *of_resolve_phandles(struct device_node *root,
>  					const struct device_node *overlay);
> @@ -1032,7 +1049,6 @@ int of_process_overlay(struct device_node *root,
>  				   struct device_node *overlay, void *data),
>  		    void *data);
>  
> -int of_firmware_load_overlay(struct device_node *overlay, const char *path);
>  #else
>  static inline struct device_node *of_resolve_phandles(struct device_node *root,
>  					const struct device_node *overlay)
> @@ -1059,11 +1075,6 @@ static inline int of_process_overlay(struct device_node *root,
>  {
>  	return -ENOSYS;
>  }
> -
> -static inline int of_firmware_load_overlay(struct device_node *overlay, const char *path)
> -{
> -	return -ENOSYS;
> -}
>  #endif
>  
>  #endif /* __OF_H */
> -- 
> 2.20.1
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Thu Jan 28 10:16:32 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 28 Jan 2021 16:16:32 +0100
Subject: [PATCH v2 10/12] commands: firmwareload: allow loading firmware
 from dt
In-Reply-To: <20210127134423.31587-10-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
 <20210127134423.31587-10-s.trumtrar@pengutronix.de>
Message-ID: <20210128151632.GC19583@pengutronix.de>

On Wed, Jan 27, 2021 at 02:44:21PM +0100, Steffen Trumtrar wrote:
> firmwareload can only load a bitstream into an FPGA without any
> knowledge of possible additional needs (e.g. FPGA bridges).
> 
> These are defined in the fpga-region nodes in the devicetree. The
> fpga-region describes the layout of the FPGA and the bridges it needs
> en/disabled.
> 
> Add an option to let firmwareload go via the oftree route and load the
> firmware that way.
> 
> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> ---
>  commands/firmwareload.c | 42 +++++++++++++++++++++++++++++++++++------
>  1 file changed, 36 insertions(+), 6 deletions(-)
> 
> diff --git a/commands/firmwareload.c b/commands/firmwareload.c
> index b735088f6117..2b1e770662d1 100644
> --- a/commands/firmwareload.c
> +++ b/commands/firmwareload.c
> @@ -5,18 +5,38 @@
>  #include <command.h>
>  #include <getopt.h>
>  #include <firmware.h>
> +#include <of.h>
>  
>  static int do_firmwareload(int argc, char *argv[])
>  {
> -	int ret, opt;
> +	int opt;
>  	const char *name = NULL, *firmware;
>  	struct firmware_mgr *mgr;
> +	char *path = NULL;
> +	char *search_path = NULL;
> +	char *compatible = NULL;
> +	int oftree = 0;
>  
> -	while ((opt = getopt(argc, argv, "t:l")) > 0) {
> +	while ((opt = getopt(argc, argv, "t:c:S:D:lo")) > 0) {

'o' is added but not handled.

>  		switch (opt) {
>  		case 't':
>  			name = optarg;
>  			break;
> +		case 'c':
> +			compatible = xzalloc(strlen(optarg) + 1);
> +			strcpy(compatible, optarg);

Use xstrdup(). The string is not freed.

> +			oftree = 1;
> +			break;
> +		case 'S':
> +			search_path = xzalloc(strlen(optarg) + 1);
> +			strcpy(search_path, optarg);

ditto

> +			oftree = 1;
> +			break;
> +		case 'D':
> +			path = xzalloc(strlen(optarg) + 1);
> +			strcpy(path, optarg);

ditto

Sascha

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Thu Jan 28 10:27:33 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 28 Jan 2021 16:27:33 +0100
Subject: [PATCH v2 12/12] firmware: add support for compressed images
In-Reply-To: <20210127134423.31587-12-s.trumtrar@pengutronix.de>
References: <20210127134423.31587-1-s.trumtrar@pengutronix.de>
 <20210127134423.31587-12-s.trumtrar@pengutronix.de>
Message-ID: <20210128152733.GD19583@pengutronix.de>

On Wed, Jan 27, 2021 at 02:44:23PM +0100, Steffen Trumtrar wrote:
> At least bitstreams for FPGAs can consist of a lot of zeros depending on
> device utilization. These bitstreams can be compressed very effectively.
> 
> Let the firmware code accept these images and decompress them before
> handing it to the firmware-manager in question.
> 
> Signed-off-by: Steffen Trumtrar <s.trumtrar at pengutronix.de>
> ---
>  common/firmware.c | 43 ++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 38 insertions(+), 5 deletions(-)
> 
> diff --git a/common/firmware.c b/common/firmware.c
> index 58509d5da615..c617ecc0f129 100644
> --- a/common/firmware.c
> +++ b/common/firmware.c
> @@ -14,6 +14,8 @@
>  #include <linux/list.h>
>  #include <linux/stat.h>
>  #include <linux/err.h>
> +#include <uncompress.h>
> +#include <filetype.h>
>  
>  #define BUFSIZ 4096
>  
> @@ -211,12 +213,43 @@ int firmwaremgr_register(struct firmware_handler *fh)
>   */
>  int firmwaremgr_load_file(struct firmware_mgr *mgr, const char *firmware)
>  {
> -	int ret;
> -	char *name = basprintf("/dev/%s", mgr->handler->id);
> -
> -	ret = copy_file(firmware, name, 0);
> +	char *dst;
> +	enum filetype type;
> +	int ret = -ENOENT;
> +	int srcfd = 0;
> +	int dstfd = 0;
> +
> +	if (mgr->handler->id) {
> +		dst = basprintf("/dev/%s", mgr->handler->id);
> +	} else {
> +		pr_err("id not defined for handler\n");
> +		return -ENODEV;
> +	}

I'd do the error handling for !mgr->handler->id first, then the dst =
basprintf(...) doesn't have to be done conditionally.

>  
> -	free(name);
> +	if (firmware) {

This function seems to do nothing when firmware is not given. Is this
the correct behaviour? If yes, then you could bail out early instead of
putting the rest of the function inside an if() {}

> +		type = file_name_detect_type(firmware);
> +		if (type == filetype_unknown) {
> +			ret = copy_file(firmware, dst, 0);

When going this way srcfd is closed below, but never opened.

> +		} else {
> +			srcfd = open(firmware, O_RDONLY);
> +			if (srcfd < 0)
> +				return srcfd;

'dst' is not freed here.

> +			dstfd = open(dst, O_WRONLY | O_CREAT);

You'll probably want to add a O_TRUNC here because otherwise if the file
existed before and was bigger than the data you gonna write to it you'll
have garbage at the end of the file.
OTOH I don't know what 'dst' is. When this could be a device file then
truncating it will fail.

> +
> +			if (dstfd < 0) {
> +				printf("could not open %s: %s\n", dst, errno_str());
> +				ret = dstfd;
> +				goto out;
> +			}
> +
> +			ret = uncompress_fd_to_fd(srcfd, dstfd, uncompress_err_stdout);
> +
> +			close(dstfd);
> +		}
> +	}
> +out:
> +	close(srcfd);
> +	free(dst);
>  
>  	return ret;
>  }

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From sha at pengutronix.de  Thu Jan 28 10:34:34 2021
From: sha at pengutronix.de (Sascha Hauer)
Date: Thu, 28 Jan 2021 16:34:34 +0100
Subject: [PATCH] scripts: Replace license and copyright boilerplate by
 SPDX identifiers
In-Reply-To: <20210128133416.27579-1-u.kleine-koenig@pengutronix.de>
References: <20210128133416.27579-1-u.kleine-koenig@pengutronix.de>
Message-ID: <20210128153434.GE19583@pengutronix.de>

On Thu, Jan 28, 2021 at 02:34:16PM +0100, Uwe Kleine-K?nig wrote:
> Convert the files that licensecheck can determine to be licensed under
> GPL-2.0-only or GPL-2.0-or-later and also convert the copyright statements
> to SPDX.
> 
> Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig at pengutronix.de>
> ---

Applied, thanks

Sascha


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From rhi at pengutronix.de  Thu Jan 28 16:00:22 2021
From: rhi at pengutronix.de (Roland Hieber)
Date: Thu, 28 Jan 2021 22:00:22 +0100
Subject: [PATCH] common: Kconfig: improve defaultenv help texts
Message-ID: <20210128210022.31841-1-rhi@pengutronix.de>

Signed-off-by: Roland Hieber <rhi at pengutronix.de>
---
 common/Kconfig | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/common/Kconfig b/common/Kconfig
index b350f5c355fa..c62c70fb27eb 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -874,6 +874,13 @@ config DEFAULT_ENVIRONMENT_GENERIC_NEW
 	select NET_CMD_IFUP if NET
 	select CMD_IP_ROUTE_GET if NET
 	select CMD_HOST if NET
+	help
+	  With this option barebox will use the files found under
+	  defaultenv/defaultenv-2-base/ in the source tree as a template for
+	  the defaultenv. The directories specified in DEFAULT_ENVIRONMENT_PATH
+	  will be added to the default environment. If a file is present in
+	  both locations, the file from DEFAULT_ENVIRONMENT_PATH will overwrite
+	  that from the template.
 
 config DEFAULT_ENVIRONMENT_GENERIC
 	bool "Generic environment template (old version)"
@@ -887,9 +894,12 @@ config DEFAULT_ENVIRONMENT_GENERIC
 	select CMD_CRC_CMP
 	select CMD_GLOBAL
 	help
-	  With this option barebox will use the generic default
-	  environment found under defaultenv/ in the src tree.
-	  The Directory given with DEFAULT_ENVIRONMENT_PATH
+	  Note: this option is not recommended for new boards; use
+	  DEFAULT_ENVIRONMENT_GENERIC_NEW instead.
+
+	  With this option barebox will use the old generic default environment
+	  found under defaultenv/defaultenv-1/ in the source tree.
+	  The directory given with DEFAULT_ENVIRONMENT_PATH
 	  will be added to the default environment. This should
 	  at least contain a /env/config file.
 	  This will be able to overwrite the files from defaultenv.
@@ -899,21 +909,27 @@ config DEFAULT_ENVIRONMENT_GENERIC_NEW_MENU
 	depends on DEFAULT_ENVIRONMENT_GENERIC_NEW
 	depends on CMD_MENUTREE
 	default y
+	help
+	  Extend the defaultenv template with a menu that is displayed at boot.
+	  The menu files are taken from defaultenv/defaultenv-2-menu/.
 
 config DEFAULT_ENVIRONMENT_GENERIC_NEW_DFU
 	bool
 	depends on DEFAULT_ENVIRONMENT_GENERIC_NEW
 	depends on USB_GADGET_DFU
 	default y
+	help
+	  Extend the defaultenv template with the 'dfu' boot entry, which
+	  allows uploading the kernel and oftree over USB via the dfu protocol.
 
 config DEFAULT_ENVIRONMENT_PATH
 	string
 	depends on DEFAULT_ENVIRONMENT
 	prompt "Default environment path"
 	help
-	  Space separated list of paths the default environment will be taken from.
-	  Relative paths will be relative to the barebox Toplevel dir, but absolute
-	  paths are fine as well.
+	  Space separated list of paths from which the default environment will
+	  be taken. Relative paths will be relative to the barebox top-level
+	  directory, but absolute paths are fine as well.
 
 config BAREBOXENV_TARGET
 	bool
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 04:51:18 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 10:51:18 +0100
Subject: [RFC PATCH] usb: gadget: dfu: Wrap fs operation in workqueue
In-Reply-To: <20210127164937.20328-1-jmaselbas@kalray.eu>
References: <20210127164937.20328-1-jmaselbas@kalray.eu>
Message-ID: <91ec3053-201d-ff02-0f78-6d86a6b8a0f0@pengutronix.de>

Hello Jules,

On 27.01.21 17:49, Jules Maselbas wrote:
> File system operation shouldn't be executed in a poller. Use
> a workqueue to delay filesystem operation to command context.
> 
> This is an RFC, extra work must be done to properly handle error
> cases and dfu cleanup.

I erroneously thought the poller is within the DFU bits. I wonder what
side-effect moving the whole USB gadget polling into a workqueue would
have. In that case, we wouldn't need to any changes for DFU itself.

Jules, Sascha, thoughts?

Cheers,
Ahmad

> 
> Signed-off-by: Jules Maselbas <jmaselbas at kalray.eu>
> ---
>  drivers/usb/gadget/dfu.c | 321 ++++++++++++++++++++++++++-------------
>  1 file changed, 216 insertions(+), 105 deletions(-)
> 
> diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c
> index 9d6a9d252..75abd1576 100644
> --- a/drivers/usb/gadget/dfu.c
> +++ b/drivers/usb/gadget/dfu.c
> @@ -54,6 +54,7 @@
>  #include <fs.h>
>  #include <ioctl.h>
>  #include <linux/mtd/mtd-abi.h>
> +#include <work.h>
>  
>  #define USB_DT_DFU			0x21
>  
> @@ -153,6 +154,7 @@ struct f_dfu {
>  	u8	dfu_state;
>  	u8	dfu_status;
>  	struct usb_request		*dnreq;
> +	struct work_queue wq;
>  };
>  
>  static inline struct f_dfu *func_to_dfu(struct usb_function *f)
> @@ -173,6 +175,178 @@ static struct usb_gadget_strings *dfu_strings[] = {
>  };
>  
>  static void dn_complete(struct usb_ep *ep, struct usb_request *req);
> +static void up_complete(struct usb_ep *ep, struct usb_request *req);
> +static void dfu_cleanup(struct f_dfu *dfu);
> +
> +struct dfu_work {
> +	struct work_struct work;
> +	struct f_dfu *dfu;
> +	void (*task)(struct dfu_work *dw);
> +	size_t len;
> +	uint8_t *rbuf;
> +	uint8_t wbuf[CONFIG_USBD_DFU_XFER_SIZE];
> +};
> +
> +static void dfu_do_work(struct work_struct *w)
> +{
> +	struct dfu_work *dw = container_of(w, struct dfu_work, work);
> +
> +	/* TODO: find a better way to skip tasks when the dfu gadget
> +	 * has encounter an error and dfu_cleanup has been called */
> +	if (dw->task && dw->dfu->dfu_status == DFU_STATUS_OK)
> +		dw->task(dw);
> +
> +	free(dw);
> +}
> +
> +static void dfu_work_cancel(struct work_struct *w)
> +{
> +	struct dfu_work *dw = container_of(w, struct dfu_work, work);
> +
> +	free(dw);
> +}
> +
> +static void dfu_do_write(struct dfu_work *dw)
> +{
> +	struct f_dfu *dfu = dw->dfu;
> +	size_t size, wlen = dw->len;
> +	int ret;
> +
> +	debug("do write\n");
> +
> +	if (prog_erase && (dfu_written + wlen) > dfu_erased) {
> +		size = roundup(wlen, dfu_mtdinfo.erasesize);
> +		ret = erase(dfufd, size, dfu_erased);
> +		dfu_erased += size;
> +		if (ret && ret != -ENOSYS) {
> +			perror("erase");
> +			dfu->dfu_status = DFU_STATUS_errERASE;
> +			dfu_cleanup(dfu);
> +			return;
> +		}
> +	}
> +
> +	dfu_written += wlen;
> +	ret = write(dfufd, dw->wbuf, wlen);
> +	if (ret < (int)wlen) {
> +		perror("write");
> +		dfu->dfu_status = DFU_STATUS_errWRITE;
> +		dfu_cleanup(dfu);
> +	}
> +}
> +
> +static void dfu_do_read(struct dfu_work *dw)
> +{
> +	struct f_dfu *dfu = dw->dfu;
> +	struct usb_composite_dev *cdev = dfu->func.config->cdev;
> +	size_t size, rlen = dw->len;
> +
> +	debug("do read\n");
> +
> +	size = read(dfufd, dfu->dnreq->buf, rlen);
> +	dfu->dnreq->length = size;
> +	if (size < (int)rlen) {
> +		perror("read");
> +		dfu_cleanup(dfu);
> +		dfu->dfu_state = DFU_STATE_dfuIDLE;
> +	}
> +
> +	dfu->dnreq->complete = up_complete;
> +	usb_ep_queue(cdev->gadget->ep0, dfu->dnreq);
> +}
> +
> +static void dfu_do_open_dnload(struct dfu_work *dw)
> +{
> +	struct f_dfu *dfu = dw->dfu;
> +	int ret;
> +
> +	debug("do open dnload\n");
> +
> +	if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
> +		dfufd = open(DFU_TEMPFILE, O_WRONLY | O_CREAT);
> +	} else {
> +		unsigned flags = O_WRONLY;
> +
> +		if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
> +			flags |= O_CREAT | O_TRUNC;
> +
> +		dfufd = open(dfu_file_entry->filename, flags);
> +	}
> +
> +	if (dfufd < 0) {
> +		perror("open");
> +		dfu->dfu_status = DFU_STATUS_errFILE;
> +		goto out;
> +	}
> +
> +	if (!(dfu_file_entry->flags & FILE_LIST_FLAG_SAFE)) {
> +		ret = ioctl(dfufd, MEMGETINFO, &dfu_mtdinfo);
> +		if (!ret) /* file is on a mtd device */
> +			prog_erase = 1;
> +	}
> +
> +	return;
> +out:
> +	dfu->dfu_state = DFU_STATE_dfuERROR;
> +	dfu_cleanup(dfu);
> +}
> +
> +static void dfu_do_open_upload(struct dfu_work *dw)
> +{
> +	struct f_dfu *dfu = dw->dfu;
> +
> +	debug("do open upload\n");
> +
> +	dfufd = open(dfu_file_entry->filename, O_RDONLY);
> +	if (dfufd < 0) {
> +		perror("open");
> +		dfu->dfu_status = DFU_STATUS_errFILE;
> +		dfu->dfu_state = DFU_STATE_dfuERROR;
> +		dfu_cleanup(dfu);
> +	}
> +}
> +
> +static void dfu_do_copy(struct dfu_work *dw)
> +{
> +	struct f_dfu *dfu = dw->dfu;
> +	unsigned flags = O_WRONLY;
> +	int ret, fd;
> +
> +	debug("do copy\n");
> +
> +	if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
> +		flags |= O_CREAT | O_TRUNC;
> +
> +	fd = open(dfu_file_entry->filename, flags);
> +	if (fd < 0) {
> +		perror("open");
> +		dfu->dfu_status = DFU_STATUS_errERASE;
> +		goto out;
> +	}
> +
> +	ret = erase(fd, ERASE_SIZE_ALL, 0);
> +	close(fd);
> +	if (ret && ret != -ENOSYS) {
> +		perror("erase");
> +		dfu->dfu_status = DFU_STATUS_errERASE;
> +		goto out;
> +	}
> +
> +	ret = copy_file(DFU_TEMPFILE, dfu_file_entry->filename, 0);
> +	if (ret) {
> +		dfu->dfu_status = DFU_STATUS_errWRITE;
> +		printf("copy file failed\n");
> +		goto out;
> +	}
> +
> +	dfu->dfu_state = DFU_STATE_dfuIDLE;
> +	dfu_cleanup(dfu);
> +
> +	return;
> +out:
> +	dfu->dfu_state = DFU_STATE_dfuERROR;
> +	dfu_cleanup(dfu);
> +}
>  
>  static int
>  dfu_bind(struct usb_configuration *c, struct usb_function *f)
> @@ -223,6 +397,10 @@ dfu_bind(struct usb_configuration *c, struct usb_function *f)
>  		goto out;
>  	}
>  
> +	dfu->wq.fn = dfu_do_work;
> +	dfu->wq.cancel = dfu_work_cancel;
> +	wq_register(&dfu->wq);
> +
>  	/* allocate instance-specific interface IDs, and patch descriptors */
>  	status = usb_interface_id(c, f);
>  	if (status < 0)
> @@ -278,6 +456,8 @@ dfu_unbind(struct usb_configuration *c, struct usb_function *f)
>  	dfu_file_entry = NULL;
>  	dfudetach = 0;
>  
> +	wq_unregister(&dfu->wq);
> +
>  	usb_free_all_descriptors(f);
>  
>  	dma_free(dfu->dnreq->buf);
> @@ -327,6 +507,9 @@ static void dfu_cleanup(struct f_dfu *dfu)
>  	dfu_erased = 0;
>  	prog_erase = 0;
>  
> +	/* TODO: Right now, close and stat operation can be called
> +	 * in a poller, in dfu_abort and dfu_disable. */
> +
>  	if (dfufd > 0) {
>  		close(dfufd);
>  		dfufd = -EINVAL;
> @@ -339,28 +522,15 @@ static void dfu_cleanup(struct f_dfu *dfu)
>  static void dn_complete(struct usb_ep *ep, struct usb_request *req)
>  {
>  	struct f_dfu		*dfu = req->context;
> -	loff_t size;
> -	int ret;
> +	struct dfu_work *dw;
>  
> -	if (prog_erase && (dfu_written + req->length) > dfu_erased) {
> -		size = roundup(req->length, dfu_mtdinfo.erasesize);
> -		ret = erase(dfufd, size, dfu_erased);
> -		dfu_erased += size;
> -		if (ret && ret != -ENOSYS) {
> -			perror("erase");
> -			dfu->dfu_status = DFU_STATUS_errERASE;
> -			dfu_cleanup(dfu);
> -			return;
> -		}
> -	}
> +	dw = xzalloc(sizeof(*dw));
> +	dw->dfu = dfu;
> +	dw->task = dfu_do_write;
> +	dw->len = min_t(unsigned int, req->length, CONFIG_USBD_DFU_XFER_SIZE);
> +	memcpy(dw->wbuf, req->buf, dw->len);
>  
> -	dfu_written += req->length;
> -	ret = write(dfufd, req->buf, req->length);
> -	if (ret < (int)req->length) {
> -		perror("write");
> -		dfu->dfu_status = DFU_STATUS_errWRITE;
> -		dfu_cleanup(dfu);
> -	}
> +	wq_queue_work(&dfu->wq, &dw->work);
>  }
>  
>  static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
> @@ -370,12 +540,7 @@ static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *c
>  	u16			w_length = le16_to_cpu(ctrl->wLength);
>  
>  	if (w_length == 0) {
> -		if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
> -			dfu->dfu_state = DFU_STATE_dfuMANIFEST;
> -		} else {
> -			dfu->dfu_state = DFU_STATE_dfuIDLE;
> -			dfu_cleanup(dfu);
> -		}
> +		dfu->dfu_state = DFU_STATE_dfuMANIFEST_SYNC;
>  		return 0;
>  	}
>  
> @@ -389,48 +554,18 @@ static int handle_dnload(struct usb_function *f, const struct usb_ctrlrequest *c
>  static int handle_manifest(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
>  {
>  	struct f_dfu		*dfu = func_to_dfu(f);
> -	int ret;
> +	struct dfu_work *dw;
>  
>  	dfu->dfu_state = DFU_STATE_dfuIDLE;
>  
>  	if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
> -		int fd;
> -		unsigned flags = O_WRONLY;
> -
> -		if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
> -			flags |= O_CREAT | O_TRUNC;
> -
> -		fd = open(dfu_file_entry->filename, flags);
> -		if (fd < 0) {
> -			perror("open");
> -			dfu->dfu_status = DFU_STATUS_errERASE;
> -			ret = -EINVAL;
> -			goto out;
> -		}
> -
> -		ret = erase(fd, ERASE_SIZE_ALL, 0);
> -		close(fd);
> -		if (ret && ret != -ENOSYS) {
> -			dfu->dfu_status = DFU_STATUS_errERASE;
> -			perror("erase");
> -			goto out;
> -		}
> -
> -		ret = copy_file(DFU_TEMPFILE, dfu_file_entry->filename, 0);
> -		if (ret) {
> -			printf("copy file failed\n");
> -			ret = -EINVAL;
> -			goto out;
> -		}
> +		dw = xzalloc(sizeof(*dw));
> +		dw->dfu = dfu;
> +		dw->task = dfu_do_copy;
> +		wq_queue_work(&dfu->wq, &dw->work);
>  	}
>  
>  	return 0;
> -
> -out:
> -	dfu->dfu_status = DFU_STATUS_errWRITE;
> -	dfu->dfu_state = DFU_STATE_dfuERROR;
> -	dfu_cleanup(dfu);
> -	return ret;
>  }
>  
>  static void up_complete(struct usb_ep *ep, struct usb_request *req)
> @@ -440,20 +575,17 @@ static void up_complete(struct usb_ep *ep, struct usb_request *req)
>  static int handle_upload(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
>  {
>  	struct f_dfu		*dfu = func_to_dfu(f);
> -	struct usb_composite_dev *cdev = f->config->cdev;
> +	struct dfu_work *dw;
>  	u16			w_length = le16_to_cpu(ctrl->wLength);
> -	int len;
> -
> -	len = read(dfufd, dfu->dnreq->buf, w_length);
> -
> -	dfu->dnreq->length = len;
> -	if (len < w_length) {
> -		dfu_cleanup(dfu);
> -		dfu->dfu_state = DFU_STATE_dfuIDLE;
> -	}
>  
> -	dfu->dnreq->complete = up_complete;
> -	usb_ep_queue(cdev->gadget->ep0, dfu->dnreq);
> +	/* RFC: I didn't found a better way to queue the usb response other
> +	 * than making dfu_do_read call usb_ep_queue after reading from file */
> +	dw = xzalloc(sizeof(*dw));
> +	dw->dfu = dfu;
> +	dw->task = dfu_do_read;
> +	dw->len = w_length;
> +	dw->rbuf = dfu->dnreq->buf;
> +	wq_queue_work(&dfu->wq, &dw->work);
>  
>  	return 0;
>  }
> @@ -474,7 +606,7 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
>  	int			value = -EOPNOTSUPP;
>  	int			w_length = le16_to_cpu(ctrl->wLength);
>  	int			w_value = le16_to_cpu(ctrl->wValue);
> -	int ret;
> +	struct dfu_work *dw;
>  
>  	if (ctrl->bRequestType == USB_DIR_IN && ctrl->bRequest == USB_REQ_GET_DESCRIPTOR
>  			&& (w_value >> 8) == 0x21) {
> @@ -501,28 +633,10 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
>  				goto out;
>  			}
>  			debug("dfu: starting download to %s\n", dfu_file_entry->filename);
> -			if (dfu_file_entry->flags & FILE_LIST_FLAG_SAFE) {
> -				dfufd = open(DFU_TEMPFILE, O_WRONLY | O_CREAT);
> -			} else {
> -				unsigned flags = O_WRONLY;
> -
> -				if (dfu_file_entry->flags & FILE_LIST_FLAG_CREATE)
> -					flags |= O_CREAT | O_TRUNC;
> -
> -				dfufd = open(dfu_file_entry->filename, flags);
> -			}
> -
> -			if (dfufd < 0) {
> -				dfu->dfu_state = DFU_STATE_dfuERROR;
> -				perror("open");
> -				goto out;
> -			}
> -
> -			if (!(dfu_file_entry->flags & FILE_LIST_FLAG_SAFE)) {
> -				ret = ioctl(dfufd, MEMGETINFO, &dfu_mtdinfo);
> -				if (!ret) /* file is on a mtd device */
> -					prog_erase = 1;
> -			}
> +			dw = xzalloc(sizeof(*dw));
> +			dw->dfu = dfu;
> +			dw->task = dfu_do_open_dnload;
> +			wq_queue_work(&dfu->wq, &dw->work);
>  
>  			value = handle_dnload(f, ctrl);
>  			dfu->dfu_state = DFU_STATE_dfuDNLOAD_IDLE;
> @@ -534,12 +648,12 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
>  				dfu->dfu_state = DFU_STATE_dfuERROR;
>  				goto out;
>  			}
> -			dfufd = open(dfu_file_entry->filename, O_RDONLY);
> -			if (dfufd < 0) {
> -				dfu->dfu_state = DFU_STATE_dfuERROR;
> -				perror("open");
> -				goto out;
> -			}
> +
> +			dw = xzalloc(sizeof(*dw));
> +			dw->dfu = dfu;
> +			dw->task = dfu_do_open_upload;
> +			wq_queue_work(&dfu->wq, &dw->work);
> +
>  			handle_upload(f, ctrl);
>  			return 0;
>  		case USB_REQ_DFU_ABORT:
> @@ -648,9 +762,6 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
>  		break;
>  	case DFU_STATE_dfuMANIFEST:
>  		value = handle_manifest(f, ctrl);
> -		if (dfu->dfu_state != DFU_STATE_dfuIDLE) {
> -			return 0;
> -		}
>  		switch (ctrl->bRequest) {
>  		case USB_REQ_DFU_GETSTATUS:
>  			value = dfu_status(f, ctrl);
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From jmaselbas at kalray.eu  Fri Jan 29 05:51:52 2021
From: jmaselbas at kalray.eu (Jules Maselbas)
Date: Fri, 29 Jan 2021 11:51:52 +0100
Subject: [RFC PATCH] usb: gadget: dfu: Wrap fs operation in workqueue
In-Reply-To: <91ec3053-201d-ff02-0f78-6d86a6b8a0f0@pengutronix.de>
References: <20210127164937.20328-1-jmaselbas@kalray.eu>
 <91ec3053-201d-ff02-0f78-6d86a6b8a0f0@pengutronix.de>
Message-ID: <20210129105152.GA22732@tellis.lin.mbt.kalray.eu>

Hi Ahmad,

On Fri, Jan 29, 2021 at 10:51:18AM +0100, Ahmad Fatoum wrote:
> Hello Jules,
> 
> On 27.01.21 17:49, Jules Maselbas wrote:
> > File system operation shouldn't be executed in a poller. Use
> > a workqueue to delay filesystem operation to command context.
> > 
> > This is an RFC, extra work must be done to properly handle error
> > cases and dfu cleanup.
> 
> I erroneously thought the poller is within the DFU bits. I wonder what
> side-effect moving the whole USB gadget polling into a workqueue would
> have. In that case, we wouldn't need to any changes for DFU itself.
> 
If I understood correctly you're suggesting to wrap the entire dfu
gadget inside a poller. I have not tried this and it might work.
However wrapping each fs operation allow the dfu gadget to respond
to GET_STATUS queries will erase/write operation are on-going.

Jules



From bst at pengutronix.de  Fri Jan 29 07:59:36 2021
From: bst at pengutronix.de (Bastian Krause)
Date: Fri, 29 Jan 2021 13:59:36 +0100
Subject: [PATCH] Documentation: state: recommend a partition type GUID for
 state GPT partitions
Message-ID: <20210129125936.20053-1-bst@pengutronix.de>

The partition type GUID was generated randomly. Having a defined GUID
should reduce the risk of collisions in the future.

A dedicated GUID could also allow us to implement a fallback in case no
state backend property is defined. This could then look for a GPT
partition with this partition type GUID and use that as the backend.
dt-utils could do the same in userspace. This would be similar to [1].

[1] https://www.freedesktop.org/wiki/Specifications/DiscoverablePartitionsSpec/

Signed-off-by: Bastian Krause <bst at pengutronix.de>
---
 Documentation/user/state.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Documentation/user/state.rst b/Documentation/user/state.rst
index 54aa396257..a0e27d4fe8 100644
--- a/Documentation/user/state.rst
+++ b/Documentation/user/state.rst
@@ -579,6 +579,9 @@ content, its backend-type and *state* variable layout.
 		};
 	};
 
+If the *state* variable set is set to be located in a GPT partition, use
+``4778ed65-bf42-45fa-9c5b-287a1dc4aab1`` as the partition type GUID.
+
 SRAM
 ####
 
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 08:58:33 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 14:58:33 +0100
Subject: [PATCH] efi: declare prototype for close_protocol BootService
Message-ID: <20210129135833.5748-1-a.fatoum@pengutronix.de>

Sometimes, drivers need to probe whether the EFI device in front of them
is the actual hardware they expect. If it's not, the driver should call
close_protocol to leave the decision on whether to match this device to
another driver. Use the correct type for close_protocol to facilitate
this.

No functional change, as no in-tree driver makes use of this yet.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 include/efi.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/efi.h b/include/efi.h
index 43c05939513d..f6833fde1e75 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -256,7 +256,8 @@ typedef struct {
 	efi_status_t (EFIAPI *open_protocol)(efi_handle_t handle, efi_guid_t *protocol,
 			void ** interface, efi_handle_t agent_handle,
 			efi_handle_t controller_handle, u32 attributes);
-	void *close_protocol;
+	efi_status_t (EFIAPI *close_protocol)(efi_handle_t handle, efi_guid_t *protocol,
+					      efi_handle_t agent, efi_handle_t controller);
 	efi_status_t(EFIAPI *open_protocol_information)(efi_handle_t handle, efi_guid_t *Protocol,
 			struct efi_open_protocol_information_entry **entry_buffer,
 			unsigned long *entry_count);
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 10:25:53 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 16:25:53 +0100
Subject: [PATCH 1/2] ARM: i.MX8MM: fix sparse warnings in early clock code
Message-ID: <20210129152553.15792-1-a.fatoum@pengutronix.de>

Some __iomem markers were being casted away. Fix that.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/mach-imx/imx8m.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-imx/imx8m.c b/arch/arm/mach-imx/imx8m.c
index b9e01a1d1854..350d203539fc 100644
--- a/arch/arm/mach-imx/imx8m.c
+++ b/arch/arm/mach-imx/imx8m.c
@@ -35,14 +35,14 @@
 
 void imx8m_clock_set_target_val(int clock_id, u32 val)
 {
-	void *ccm = IOMEM(MX8M_CCM_BASE_ADDR);
+	void __iomem *ccm = IOMEM(MX8M_CCM_BASE_ADDR);
 
 	writel(val, ccm + IMX8M_CCM_TARGET_ROOTn(clock_id));
 }
 
 void imx8m_ccgr_clock_enable(int index)
 {
-	void *ccm = IOMEM(MX8M_CCM_BASE_ADDR);
+	void __iomem *ccm = IOMEM(MX8M_CCM_BASE_ADDR);
 
 	writel(IMX8M_CCM_CCGR_SETTINGn_NEEDED(0),
 	       ccm + IMX8M_CCM_CCGRn_SET(index));
@@ -50,7 +50,7 @@ void imx8m_ccgr_clock_enable(int index)
 
 void imx8m_ccgr_clock_disable(int index)
 {
-	void *ccm = IOMEM(MX8M_CCM_BASE_ADDR);
+	void __iomem *ccm = IOMEM(MX8M_CCM_BASE_ADDR);
 
 	writel(IMX8M_CCM_CCGR_SETTINGn_NEEDED(0),
 	       ccm + IMX8M_CCM_CCGRn_CLR(index));
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 10:25:54 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 16:25:54 +0100
Subject: [PATCH 2/2] ARM: i.MX8MM: move system counter enabling into
 imx8mm_cpu_lowlevel_init
In-Reply-To: <20210129152553.15792-1-a.fatoum@pengutronix.de>
References: <20210129152553.15792-1-a.fatoum@pengutronix.de>
Message-ID: <20210129152553.15792-2-a.fatoum@pengutronix.de>

From: Ahmad Fatoum <ahmad at a3f.at>

Other i.MX8MM boards will likely need this as well, so just move it
into the helper and while at it, rewrite it using
imx8m_ccgr_clock_enable, which is defined as:

  void __iomem *ccm = IOMEM(MX8M_CCM_BASE_ADDR);

  writel(IMX8M_CCM_CCGR_SETTINGn_NEEDED(0),
    ccm + IMX8M_CCM_CCGRn_SET(index));

No functional change.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/boards/nxp-imx8mm-evk/lowlevel.c | 5 -----
 arch/arm/mach-imx/cpu_init.c              | 4 ++++
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c b/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c
index 2297dc01e77f..4bd29c226912 100644
--- a/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c
+++ b/arch/arm/boards/nxp-imx8mm-evk/lowlevel.c
@@ -172,11 +172,6 @@ static __noreturn noinline void nxp_imx8mm_evk_start(void)
 
 ENTRY_FUNCTION(start_nxp_imx8mm_evk, r0, r1, r2)
 {
-	void __iomem *ccm = IOMEM(MX8M_CCM_BASE_ADDR);
-
-	writel(IMX8M_CCM_CCGR_SETTINGn_NEEDED(0),
-	       ccm + IMX8M_CCM_CCGRn_SET(IMX8M_CCM_CCGR_SCTR));
-
 	imx8mm_cpu_lowlevel_init();
 
 	relocate_to_current_adr();
diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c
index cc7a409e373a..9d86353e2255 100644
--- a/arch/arm/mach-imx/cpu_init.c
+++ b/arch/arm/mach-imx/cpu_init.c
@@ -20,6 +20,7 @@
 #include <mach/generic.h>
 #include <mach/imx7-regs.h>
 #include <mach/imx8mq-regs.h>
+#include <mach/imx8m-ccm-regs.h>
 #include <common.h>
 #include <io.h>
 #include <asm/syscounter.h>
@@ -79,6 +80,9 @@ static void imx8m_cpu_lowlevel_init(void)
 
 void imx8mm_cpu_lowlevel_init(void)
 {
+	/* ungate system counter */
+	imx8m_ccgr_clock_enable(IMX8M_CCM_CCGR_SCTR);
+
 	imx8m_cpu_lowlevel_init();
 }
 
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 11:11:09 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 17:11:09 +0100
Subject: [PATCH 1/8] commands: usbgadget: remove deprecated s option from help
 text
Message-ID: <20210129161116.9971-1-a.fatoum@pengutronix.de>

Prior to 44add42d4330 ("usbgadget: autostart: add DFU support"), -s used
to do nothing. That commit made it behave like -a, but deprecated it and
changed the help text to omit it. Remove it from the short help text as
well.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 commands/usbgadget.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/commands/usbgadget.c b/commands/usbgadget.c
index 9133402f52fb..3b115f147d80 100644
--- a/commands/usbgadget.c
+++ b/commands/usbgadget.c
@@ -67,7 +67,7 @@ BAREBOX_CMD_HELP_END
 BAREBOX_CMD_START(usbgadget)
 	.cmd		= do_usbgadget,
 	BAREBOX_CMD_DESC("Create USB Gadget multifunction device")
-	BAREBOX_CMD_OPTS("[-asdAD]")
+	BAREBOX_CMD_OPTS("[-adAD]")
 	BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
 	BAREBOX_CMD_HELP(cmd_usbgadget_help)
 BAREBOX_CMD_END
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 11:11:15 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 17:11:15 +0100
Subject: [PATCH 7/8] usb: add fallback ->detect method for USB host drivers
In-Reply-To: <20210129161116.9971-1-a.fatoum@pengutronix.de>
References: <20210129161116.9971-1-a.fatoum@pengutronix.de>
Message-ID: <20210129161116.9971-7-a.fatoum@pengutronix.de>

We already maintain a list of USB host controllers, so we can use that
to implement a generic detect callback. Currently, all drivers define
their own, which uses driver-specific means to arrive at the struct
usb_host and then call usb_host_detect().

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/usb/core/usb.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index ea244d4bcf6c..938a28e030bf 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -88,11 +88,25 @@ static inline void usb_host_release(struct usb_host *host)
 	slice_release(&host->slice);
 }
 
+static int usb_hw_detect(struct device_d *dev)
+{
+	struct usb_host *host;
+
+	list_for_each_entry(host, &host_list, list) {
+		if (dev == host->hw_dev)
+			return usb_host_detect(host);
+	}
+
+	return -ENODEV;
+}
+
 int usb_register_host(struct usb_host *host)
 {
 	list_add_tail(&host->list, &host_list);
 	host->busnum = host_busnum++;
 	slice_init(&host->slice, dev_name(host->hw_dev));
+	if (!host->hw_dev->detect)
+		host->hw_dev->detect = usb_hw_detect;
 	return 0;
 }
 
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 11:11:16 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 17:11:16 +0100
Subject: [PATCH 8/8] usb: host: ehci: remove duplicated usb_host_detect() calls
In-Reply-To: <20210129161116.9971-1-a.fatoum@pengutronix.de>
References: <20210129161116.9971-1-a.fatoum@pengutronix.de>
Message-ID: <20210129161116.9971-8-a.fatoum@pengutronix.de>

With the last patch adding a fallback detect, we no longer need the
duplication in the host controller drivers. Drop them.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/usb/dwc2/host.c         |  9 ---------
 drivers/usb/host/ehci-atmel.c   |  8 --------
 drivers/usb/host/ehci-hcd.c     | 13 -------------
 drivers/usb/host/xhci.c         |  8 --------
 drivers/usb/imx/chipidea-imx.c  |  9 ---------
 drivers/usb/musb/musb_barebox.c |  9 ---------
 include/usb/ehci.h              |  6 ------
 7 files changed, 62 deletions(-)

diff --git a/drivers/usb/dwc2/host.c b/drivers/usb/dwc2/host.c
index 510a07dfb9a9..7a070d91f3bc 100644
--- a/drivers/usb/dwc2/host.c
+++ b/drivers/usb/dwc2/host.c
@@ -766,13 +766,6 @@ static int dwc2_host_init(struct usb_host *host)
 	return 0;
 }
 
-static int dwc2_detect(struct device_d *dev)
-{
-	struct dwc2 *dwc2 = dev->priv;
-
-	return usb_host_detect(&dwc2->host);
-}
-
 int dwc2_register_host(struct dwc2 *dwc2)
 {
 	struct usb_host *host;
@@ -784,8 +777,6 @@ int dwc2_register_host(struct dwc2 *dwc2)
 	host->submit_control_msg = dwc2_submit_control_msg;
 	host->submit_int_msg = dwc2_submit_int_msg;
 
-	dwc2->dev->detect = dwc2_detect;
-
 	return usb_register_host(host);
 }
 
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 192c5ef9d185..c3f8ab7ad591 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -57,13 +57,6 @@ static void atmel_stop_clock(struct atmel_ehci_priv *atehci)
 	clk_disable(atehci->uclk);
 }
 
-static int atmel_ehci_detect(struct device_d *dev)
-{
-	struct atmel_ehci_priv *atehci = dev->priv;
-
-	return ehci_detect(atehci->ehci);
-}
-
 static int atmel_ehci_probe(struct device_d *dev)
 {
 	int ret;
@@ -78,7 +71,6 @@ static int atmel_ehci_probe(struct device_d *dev)
 	atehci = xzalloc(sizeof(*atehci));
 	atehci->dev = dev;
 	dev->priv = atehci;
-	dev->detect = atmel_ehci_detect;
 
 	atehci->iclk = clk_get(dev, "ehci_clk");
 	if (IS_ERR(atehci->iclk)) {
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 287849102d68..8c4da9fd12e2 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1349,11 +1349,6 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	return result;
 }
 
-int ehci_detect(struct ehci_host *ehci)
-{
-	return usb_host_detect(&ehci->host);
-}
-
 struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data)
 {
 	struct usb_host *host;
@@ -1411,13 +1406,6 @@ void ehci_unregister(struct ehci_host *ehci)
 	free(ehci);
 }
 
-static int ehci_dev_detect(struct device_d *dev)
-{
-	struct ehci_host *ehci = dev->priv;
-
-	return ehci_detect(ehci);
-}
-
 static int ehci_probe(struct device_d *dev)
 {
 	struct resource *iores;
@@ -1457,7 +1445,6 @@ static int ehci_probe(struct device_d *dev)
 		return PTR_ERR(ehci);
 
 	dev->priv = ehci;
-	dev->detect = ehci_dev_detect;
 
 	return 0;
 }
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 317000d65006..caab2400d8d6 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1389,13 +1389,6 @@ int xhci_deregister(struct xhci_ctrl *ctrl)
 	return 0;
 }
 
-static int xhci_detect(struct device_d *dev)
-{
-	struct xhci_ctrl *ctrl = dev->priv;
-
-	return usb_host_detect(&ctrl->host);
-}
-
 /*
  * xHCI platform driver
  */
@@ -1417,7 +1410,6 @@ static int xhci_probe(struct device_d *dev)
 		HC_LENGTH(xhci_readl(&(ctrl->hccr)->cr_capbase)));
 
 	dev->priv = ctrl;
-	dev->detect = xhci_detect;
 
 	return xhci_register(ctrl);
 }
diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c
index b144f41437a9..7b87f302a921 100644
--- a/drivers/usb/imx/chipidea-imx.c
+++ b/drivers/usb/imx/chipidea-imx.c
@@ -178,13 +178,6 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci)
 	return 0;
 }
 
-static int ci_ehci_detect(struct device_d *dev)
-{
-	struct imx_chipidea *ci = dev->priv;
-
-	return ehci_detect(ci->ehci);
-}
-
 static int ci_set_mode(void *ctx, enum usb_dr_mode mode)
 {
 	struct imx_chipidea *ci = ctx;
@@ -205,8 +198,6 @@ static int ci_set_mode(void *ctx, enum usb_dr_mode mode)
 			}
 
 			ci->ehci = ehci;
-
-			ci->dev->detect = ci_ehci_detect;
 		} else {
 			dev_err(ci->dev, "Host support not available\n");
 			return -ENODEV;
diff --git a/drivers/usb/musb/musb_barebox.c b/drivers/usb/musb/musb_barebox.c
index b1f38c35ac0b..f54ad5e6e472 100644
--- a/drivers/usb/musb/musb_barebox.c
+++ b/drivers/usb/musb/musb_barebox.c
@@ -121,13 +121,6 @@ submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
 	return submit_urb(dev, urb, 100);
 }
 
-static int musb_detect(struct device_d *dev)
-{
-	struct musb *musb = dev->priv;
-
-	return usb_host_detect(&musb->host);
-}
-
 int musb_register(struct musb *musb)
 {
 	struct usb_host *host;
@@ -139,8 +132,6 @@ int musb_register(struct musb *musb)
 	host->submit_control_msg = submit_control_msg;
 	host->submit_bulk_msg = submit_bulk_msg;
 
-	musb->controller->priv = musb;
-	musb->controller->detect = musb_detect;
 	usb_register_host(host);
 
 	return 0;
diff --git a/include/usb/ehci.h b/include/usb/ehci.h
index 9ca9252eb1d2..327500d49aed 100644
--- a/include/usb/ehci.h
+++ b/include/usb/ehci.h
@@ -24,7 +24,6 @@ struct ehci_host;
 #ifdef CONFIG_USB_EHCI
 struct ehci_host *ehci_register(struct device_d *dev, struct ehci_data *data);
 void ehci_unregister(struct ehci_host *);
-int ehci_detect(struct ehci_host *ehci);
 #else
 static inline struct ehci_host *ehci_register(struct device_d *dev,
 					      struct ehci_data *data)
@@ -35,11 +34,6 @@ static inline struct ehci_host *ehci_register(struct device_d *dev,
 static inline void ehci_unregister(struct ehci_host *ehci)
 {
 }
-
-static inline int ehci_detect(struct ehci_host *ehci)
-{
-	return 0;
-}
 #endif
 
 #endif  /* __USB_EHCI_H */
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 11:11:12 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 17:11:12 +0100
Subject: [PATCH 4/8] asm-generic: io.h: remove wrong use of IOMEM
In-Reply-To: <20210129161116.9971-1-a.fatoum@pengutronix.de>
References: <20210129161116.9971-1-a.fatoum@pengutronix.de>
Message-ID: <20210129161116.9971-4-a.fatoum@pengutronix.de>

addr is already __iomem, but we need to force strip that away to use it
as normal pointer. Define __io_virt like Linux does and use it.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 include/asm-generic/io.h | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 150a97645b6b..a4b0dc4b4337 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -425,6 +425,8 @@ static inline void iowrite64be(u64 value, volatile void __iomem *addr)
 #define IOMEM(addr)	((void __force __iomem *)(addr))
 #endif
 
+#define __io_virt(x) ((void __force *)(x))
+
 #ifndef memset_io
 #define memset_io memset_io
 /**
@@ -438,7 +440,7 @@ static inline void iowrite64be(u64 value, volatile void __iomem *addr)
 static inline void memset_io(volatile void __iomem *addr, int value,
 			     size_t size)
 {
-	memset(IOMEM(addr), value, size);
+	memset(__io_virt(addr), value, size);
 }
 #endif
 
@@ -456,7 +458,7 @@ static inline void memcpy_fromio(void *buffer,
 				 const volatile void __iomem *addr,
 				 size_t size)
 {
-	memcpy(buffer, IOMEM(addr), size);
+	memcpy(buffer, __io_virt(addr), size);
 }
 #endif
 
@@ -473,7 +475,7 @@ static inline void memcpy_fromio(void *buffer,
 static inline void memcpy_toio(volatile void __iomem *addr, const void *buffer,
 			       size_t size)
 {
-	memcpy(IOMEM(addr), buffer, size);
+	memcpy(__io_virt(addr), buffer, size);
 }
 #endif
 
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 11:11:13 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 17:11:13 +0100
Subject: [PATCH 5/8] ppc: <asm/io.h>: remove duplicate definition
In-Reply-To: <20210129161116.9971-1-a.fatoum@pengutronix.de>
References: <20210129161116.9971-1-a.fatoum@pengutronix.de>
Message-ID: <20210129161116.9971-5-a.fatoum@pengutronix.de>

This implementation is equivalent to the one now provided by
<asm-generic/io.h>, so it can be dropped.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/powerpc/include/asm/io.h | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index 025c06f3b735..8488c36f6558 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -86,10 +86,6 @@ extern void _outsl_ns(volatile u32 *port, const void *buf, int nl);
 
 #define IO_SPACE_LIMIT ~0
 
-#define memset_io(a,b,c)       memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)   memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)  memcpy((void *)(a),(b),(c))
-
 /*
  * Enforce In-order Execution of I/O:
  * Acts as a barrier to ensure all previous I/O accesses have
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 11:11:14 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 17:11:14 +0100
Subject: [PATCH 6/8] printk: port over Linux
 print_hex_dump_bytes/print_hex_dump_debug
In-Reply-To: <20210129161116.9971-1-a.fatoum@pengutronix.de>
References: <20210129161116.9971-1-a.fatoum@pengutronix.de>
Message-ID: <20210129161116.9971-6-a.fatoum@pengutronix.de>

print_hex_dump in barebox always prints a hex dump. Most users use
it for debugging though, so import Linux helpers to do so to cut
down on the #ifdef DEBUG.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 drivers/crypto/caam/caamrng.c | 16 ++++++----------
 drivers/mfd/rave-sp.c         | 10 ++++------
 drivers/mtd/ubi/debug.c       | 10 +++++-----
 drivers/video/tc358767.c      |  3 +--
 fs/ubifs/scan.c               |  2 +-
 include/printk.h              | 28 ++++++++++++++++++++++++++++
 6 files changed, 45 insertions(+), 24 deletions(-)

diff --git a/drivers/crypto/caam/caamrng.c b/drivers/crypto/caam/caamrng.c
index 39a90568dfe8..5d8cfb8bff93 100644
--- a/drivers/crypto/caam/caamrng.c
+++ b/drivers/crypto/caam/caamrng.c
@@ -91,10 +91,8 @@ static void rng_done(struct device_d *jrdev, u32 *desc, u32 err, void *context)
 	/* Buffer refilled, invalidate cache */
 	dma_sync_single_for_cpu(bd->addr, RN_BUF_SIZE, DMA_FROM_DEVICE);
 
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "rng refreshed buf@: ",
-		       DUMP_PREFIX_OFFSET, 16, 4, bd->buf, RN_BUF_SIZE, 1);
-#endif
+	print_hex_dump_debug("rng refreshed buf@: ", DUMP_PREFIX_OFFSET,
+			     16, 4, bd->buf, RN_BUF_SIZE, 1);
 }
 
 static inline int submit_job(struct caam_rng_ctx *ctx, int to_current)
@@ -186,10 +184,9 @@ static inline int rng_create_sh_desc(struct caam_rng_ctx *ctx)
 
 	dma_sync_single_for_device((unsigned long)desc, desc_bytes(desc),
 				   DMA_TO_DEVICE);
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "rng shdesc@: ", DUMP_PREFIX_OFFSET, 16, 4,
+
+	print_hex_dump_debug("rng shdesc@: ", DUMP_PREFIX_OFFSET, 16, 4,
 		       desc, desc_bytes(desc), 1);
-#endif
 	return 0;
 }
 
@@ -203,10 +200,9 @@ static inline int rng_create_job_desc(struct caam_rng_ctx *ctx, int buf_id)
 			     HDR_REVERSE);
 
 	append_seq_out_ptr_intlen(desc, bd->addr, RN_BUF_SIZE, 0);
-#ifdef DEBUG
-	print_hex_dump(KERN_ERR, "rng job desc@: ", DUMP_PREFIX_OFFSET, 16, 4,
+
+	print_hex_dump_debug("rng job desc@: ", DUMP_PREFIX_OFFSET, 16, 4,
 		       desc, desc_bytes(desc), 1);
-#endif
 	return 0;
 }
 
diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c
index 8fc46b66bb2c..ef569dd513b5 100644
--- a/drivers/mfd/rave-sp.c
+++ b/drivers/mfd/rave-sp.c
@@ -269,9 +269,8 @@ static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size)
 
 	length = dest - frame;
 
-	if (IS_ENABLED(DEBUG))
-		print_hex_dump(0, "rave-sp tx: ", DUMP_PREFIX_NONE,
-			       16, 1, frame, length, false);
+	print_hex_dump_debug("rave-sp tx: ", DUMP_PREFIX_NONE, 16, 1,
+			     frame, length, false);
 
 	return serdev_device_write(sp->serdev, frame, length, SECOND);
 }
@@ -406,9 +405,8 @@ static void rave_sp_receive_frame(struct rave_sp *sp,
 	struct device_d *dev         = sp->serdev->dev;
 	u8 crc_calculated[checksum_length];
 
-	if (IS_ENABLED(DEBUG))
-		print_hex_dump(0, "rave-sp rx: ", DUMP_PREFIX_NONE,
-			       16, 1, data, length, false);
+	print_hex_dump_debug("rave-sp rx: ", DUMP_PREFIX_NONE, 16, 1,
+			     data, length, false);
 
 	if (unlikely(length <= checksum_length)) {
 		dev_warn(dev, "Dropping short frame\n");
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 6ae797c2bfd6..75d6b69f090e 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -42,7 +42,7 @@ void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len)
 
 	ubi_msg(ubi, "dumping %d bytes of data from PEB %d, offset %d",
 		len, pnum, offset);
-	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
+	print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
 out:
 	vfree(buf);
 	return;
@@ -63,8 +63,8 @@ void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr)
 	pr_err("\timage_seq      %d\n", be32_to_cpu(ec_hdr->image_seq));
 	pr_err("\thdr_crc        %#08x\n", be32_to_cpu(ec_hdr->hdr_crc));
 	pr_err("erase counter header hexdump:\n");
-	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-		       ec_hdr, UBI_EC_HDR_SIZE, 1);
+	print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 32, 1,
+			     ec_hdr, UBI_EC_HDR_SIZE, 1);
 }
 
 /**
@@ -88,8 +88,8 @@ void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr)
 		(unsigned long long)be64_to_cpu(vid_hdr->sqnum));
 	pr_err("\thdr_crc   %08x\n", be32_to_cpu(vid_hdr->hdr_crc));
 	pr_err("Volume identifier header hexdump:\n");
-	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-		       vid_hdr, UBI_VID_HDR_SIZE, 1);
+	print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 32, 1,
+			     vid_hdr, UBI_VID_HDR_SIZE, 1);
 }
 
 /**
diff --git a/drivers/video/tc358767.c b/drivers/video/tc358767.c
index e64dde1ddf3f..7d14aca9115b 100644
--- a/drivers/video/tc358767.c
+++ b/drivers/video/tc358767.c
@@ -1191,8 +1191,7 @@ static int tc_read_edid(struct tc_data *tc)
 
 #ifdef DEBUG
 	printk(KERN_DEBUG "eDP display EDID:\n");
-	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, tc->edid,
-		       EDID_LENGTH, true);
+	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, tc->edid, EDID_LENGTH);
 #endif
 
 	return 0;
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index ea88926163f4..113c2cf755de 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -244,7 +244,7 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
 	if (len > 8192)
 		len = 8192;
 	ubifs_err(c, "first %d bytes from LEB %d:%d", len, lnum, offs);
-	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
+	print_hex_dump_debug("", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
 }
 
 /**
diff --git a/include/printk.h b/include/printk.h
index 9941ddb12cd7..f92e477298aa 100644
--- a/include/printk.h
+++ b/include/printk.h
@@ -160,4 +160,32 @@ extern void print_hex_dump(const char *level, const char *prefix_str,
 			   int prefix_type, int rowsize, int groupsize,
 			   const void *buf, size_t len, bool ascii);
 
+#if LOGLEVEL <= MSG_DEBUG
+#define print_hex_dump_debug(prefix_str, prefix_type, rowsize,		\
+			     groupsize, buf, len, ascii)		\
+	print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize,	\
+		       groupsize, buf, len, ascii)
+#else
+static inline void print_hex_dump_debug(const char *prefix_str, int prefix_type,
+                                        int rowsize, int groupsize,
+                                        const void *buf, size_t len, bool ascii)
+{
+}
+#endif
+
+/**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
+ *  caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ *  is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Calls print_hex_dump(), with log level of KERN_DEBUG,
+ * rowsize of 16, groupsize of 1, and ASCII output included.
+ */
+#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len)	\
+	print_hex_dump_debug(prefix_str, prefix_type, 16, 1, buf, len, true)
+
 #endif
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 11:11:10 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 17:11:10 +0100
Subject: [PATCH 2/8] asm-generic: define fallback memcpy and memset for device
 I/O
In-Reply-To: <20210129161116.9971-1-a.fatoum@pengutronix.de>
References: <20210129161116.9971-1-a.fatoum@pengutronix.de>
Message-ID: <20210129161116.9971-2-a.fatoum@pengutronix.de>

The Atmel quadspi driver makes use of the memcpy_(to|from)io,
but we don't define them on all platforms. Fix this to allow
for easier porting of kernel code.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 include/asm-generic/io.h | 53 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h
index 76e6d0dc1112..150a97645b6b 100644
--- a/include/asm-generic/io.h
+++ b/include/asm-generic/io.h
@@ -11,6 +11,7 @@
 #ifndef __ASM_GENERIC_IO_H
 #define __ASM_GENERIC_IO_H
 
+#include <linux/string.h> /* for memset() and memcpy() */
 #include <linux/types.h>
 #include <asm/byteorder.h>
 
@@ -424,4 +425,56 @@ static inline void iowrite64be(u64 value, volatile void __iomem *addr)
 #define IOMEM(addr)	((void __force __iomem *)(addr))
 #endif
 
+#ifndef memset_io
+#define memset_io memset_io
+/**
+ * memset_io	Set a range of I/O memory to a constant value
+ * @addr:	The beginning of the I/O-memory range to set
+ * @val:	The value to set the memory to
+ * @count:	The number of bytes to set
+ *
+ * Set a range of I/O memory to a given value.
+ */
+static inline void memset_io(volatile void __iomem *addr, int value,
+			     size_t size)
+{
+	memset(IOMEM(addr), value, size);
+}
+#endif
+
+#ifndef memcpy_fromio
+#define memcpy_fromio memcpy_fromio
+/**
+ * memcpy_fromio	Copy a block of data from I/O memory
+ * @dst:		The (RAM) destination for the copy
+ * @src:		The (I/O memory) source for the data
+ * @count:		The number of bytes to copy
+ *
+ * Copy a block of data from I/O memory.
+ */
+static inline void memcpy_fromio(void *buffer,
+				 const volatile void __iomem *addr,
+				 size_t size)
+{
+	memcpy(buffer, IOMEM(addr), size);
+}
+#endif
+
+#ifndef memcpy_toio
+#define memcpy_toio memcpy_toio
+/**
+ * memcpy_toio		Copy a block of data into I/O memory
+ * @dst:		The (I/O memory) destination for the copy
+ * @src:		The (RAM) source for the data
+ * @count:		The number of bytes to copy
+ *
+ * Copy a block of data to I/O memory.
+ */
+static inline void memcpy_toio(volatile void __iomem *addr, const void *buffer,
+			       size_t size)
+{
+	memcpy(IOMEM(addr), buffer, size);
+}
+#endif
+
 #endif /* __ASM_GENERIC_IO_H */
-- 
2.30.0



From a.fatoum at pengutronix.de  Fri Jan 29 11:11:11 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Fri, 29 Jan 2021 17:11:11 +0100
Subject: [PATCH 3/8] ARM: <asm/io.h>: define macros for I/O memcpy/memset
In-Reply-To: <20210129161116.9971-1-a.fatoum@pengutronix.de>
References: <20210129161116.9971-1-a.fatoum@pengutronix.de>
Message-ID: <20210129161116.9971-3-a.fatoum@pengutronix.de>

<asm-generic/io.h> expects architectures to define memcpy_toio,
memcpy_fromio and memset_io as macros as it checks for their existence
with #ifndef. Only ARM defines an own implementation, but does so
as function declaration. Add the missing macros.

Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
---
 arch/arm/include/asm/io.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index 072b47317c03..b442a37b9c1d 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -3,6 +3,10 @@
 
 #define	IO_SPACE_LIMIT	0
 
+#define memcpy_fromio memcpy_fromio
+#define memcpy_toio memcpy_toio
+#define memset_io memset_io
+
 #include <asm-generic/io.h>
 #include <asm-generic/bitio.h>
 
-- 
2.30.0



From michael.nawrocki at gtri.gatech.edu  Fri Jan 29 12:44:35 2021
From: michael.nawrocki at gtri.gatech.edu (Mike Nawrocki)
Date: Fri, 29 Jan 2021 12:44:35 -0500
Subject: [PATCH] drivers: smc911x fix inverted wait_on_timeout
Message-ID: <20210129174435.17699-1-michael.nawrocki@gtri.gatech.edu>

The smc911x driver probe routine polls the READY bit using
wait_on_timeout, which returns 0 on success. The error check following
the wait_on_timeout invocation in the probe routine interprets a
returned 0 as failure.

This patch correctly interprets the return value of wait_on_timeout.

Signed-off-by: Mike Nawrocki <michael.nawrocki at gtri.gatech.edu>
---
 drivers/net/smc911x.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index ea7cea5f1..1edc16ce4 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -541,7 +541,7 @@ static int smc911x_probe(struct device_d *dev)
 	 * forbidden while this bit isn't set. Try for 100ms
 	 */
 	ret = wait_on_timeout(100 * MSECOND, smc911x_reg_read(priv, PMT_CTRL) & PMT_CTRL_READY);
-	if (!ret) {
+	if (ret) {
 		dev_err(dev, "Device not READY in 100ms aborting\n");
 		return -ENODEV;
 	}
-- 
2.20.1



From renaud.barbier at abaco.com  Fri Jan 29 12:59:02 2021
From: renaud.barbier at abaco.com (Barbier, Renaud)
Date: Fri, 29 Jan 2021 17:59:02 +0000
Subject: Layerscape secure boot
Message-ID: <MN2PR16MB31357A9BB6E7D4B2B31274A591B99@MN2PR16MB3135.namprd16.prod.outlook.com>

Is secure boot supported or planned to be supported on Layerscape (LS1046A)?
This will be our first board supporting secure boot.

If not supported yet we intend to support it (pending having the documentation/SDK...) and would like to do in a way that could be accepted upstream.

Are other boards like the IMX6/8 in barebox supporting secure boot a reference to do secure boot for other boards? 
I guess it quite hardware specific.



Cheers,
Renaud


From a.fatoum at pengutronix.de  Sun Jan 31 14:34:07 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 20:34:07 +0100
Subject: [RFC PATCH] usb: gadget: dfu: Wrap fs operation in workqueue
In-Reply-To: <20210129105152.GA22732@tellis.lin.mbt.kalray.eu>
References: <20210127164937.20328-1-jmaselbas@kalray.eu>
 <91ec3053-201d-ff02-0f78-6d86a6b8a0f0@pengutronix.de>
 <20210129105152.GA22732@tellis.lin.mbt.kalray.eu>
Message-ID: <ef7e5e11-9aef-49dc-c6f9-32a232c2926b@pengutronix.de>

Hello Jules,

On 29.01.21 11:51, Jules Maselbas wrote:
> Hi Ahmad,
> 
> On Fri, Jan 29, 2021 at 10:51:18AM +0100, Ahmad Fatoum wrote:
>> Hello Jules,
>>
>> On 27.01.21 17:49, Jules Maselbas wrote:
>>> File system operation shouldn't be executed in a poller. Use
>>> a workqueue to delay filesystem operation to command context.
>>>
>>> This is an RFC, extra work must be done to properly handle error
>>> cases and dfu cleanup.
>>
>> I erroneously thought the poller is within the DFU bits. I wonder what
>> side-effect moving the whole USB gadget polling into a workqueue would
>> have. In that case, we wouldn't need to any changes for DFU itself.
>>
> If I understood correctly you're suggesting to wrap the entire dfu
> gadget inside a poller. I have not tried this and it might work.
> However wrapping each fs operation allow the dfu gadget to respond
> to GET_STATUS queries will erase/write operation are on-going.

To allow running in the "background", the UDC calls into the gadget code
in a poller. I was wondering if replacing that poller with a workqueue
would just make the problem go away, not for DFU. It now know it wouldn't:
Work queues work in shell context and doing console stuff in shell context
(via ttyACM gadget) is not a wise choice. So please dismiss my suggestion ^^.

> 
> Jules
> 
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From a.fatoum at pengutronix.de  Sun Jan 31 14:38:11 2021
From: a.fatoum at pengutronix.de (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 20:38:11 +0100
Subject: [PATCH] drivers: smc911x fix inverted wait_on_timeout
In-Reply-To: <20210129174435.17699-1-michael.nawrocki@gtri.gatech.edu>
References: <20210129174435.17699-1-michael.nawrocki@gtri.gatech.edu>
Message-ID: <a3831f52-27d0-085d-755d-439ea0b415c8@pengutronix.de>

Hello Mike,

On 29.01.21 18:44, Mike Nawrocki wrote:
> The smc911x driver probe routine polls the READY bit using
> wait_on_timeout, which returns 0 on success. The error check following
> the wait_on_timeout invocation in the probe routine interprets a
> returned 0 as failure.
> 
> This patch correctly interprets the return value of wait_on_timeout.

Apparently two wrongs indeed make one right..

It used to be !smc911x_reg_read(priv, PMT_CTRL) & PMT_CTRL_READY,
which was flagged by static analysis and I dropped the !, because
it's clearly wrong. Now I understand why it did work..

Thanks for fixing this properly.

Reviewed-by: Ahmad Fatoum <a.fatoum at pengutronix.de>

Cheers,
Ahmad

> 
> Signed-off-by: Mike Nawrocki <michael.nawrocki at gtri.gatech.edu>
> ---
>  drivers/net/smc911x.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
> index ea7cea5f1..1edc16ce4 100644
> --- a/drivers/net/smc911x.c
> +++ b/drivers/net/smc911x.c
> @@ -541,7 +541,7 @@ static int smc911x_probe(struct device_d *dev)
>  	 * forbidden while this bit isn't set. Try for 100ms
>  	 */
>  	ret = wait_on_timeout(100 * MSECOND, smc911x_reg_read(priv, PMT_CTRL) & PMT_CTRL_READY);
> -	if (!ret) {
> +	if (ret) {
>  		dev_err(dev, "Device not READY in 100ms aborting\n");
>  		return -ENODEV;
>  	}
> 

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |


From ahmad at a3f.at  Sun Jan 31 14:40:04 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 20:40:04 +0100
Subject: [PATCH] Kbuild: add compile_commands.json target
Message-ID: <20210131194004.3369551-1-ahmad@a3f.at>

The JSON compilation database format specification describes a
compile_commands.json file that lists how translation units are
compiled by a build system. This makes integration of external tools,
like IDEs, LSP servers and static analyzers easier.

Import the Linux bits. The database can now be manually generated
with make compile_commands.json.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
Cc: Rouven Czerwinski <rcz at pengutronix.de>
---
 .gitignore                                  |   1 +
 Makefile                                    |  16 +-
 scripts/clang-tools/gen_compile_commands.py | 237 ++++++++++++++++++++
 3 files changed, 252 insertions(+), 2 deletions(-)
 create mode 100755 scripts/clang-tools/gen_compile_commands.py

diff --git a/.gitignore b/.gitignore
index 7fa2948bf4a4..d7a37b3c9b39 100644
--- a/.gitignore
+++ b/.gitignore
@@ -87,3 +87,4 @@ GTAGS
 /allno.config
 /allrandom.config
 /allyes.config
+/compile_commands.json
diff --git a/Makefile b/Makefile
index ea1d5dae1c5e..f3c85cff9430 100644
--- a/Makefile
+++ b/Makefile
@@ -541,7 +541,7 @@ endif
 # in addition to whatever we do anyway.
 # Just "make" or "make all" shall build modules as well
 
-ifneq ($(filter all _all modules,$(MAKECMDGOALS)),)
+ifneq ($(filter all _all modules %compile_commands.json,$(MAKECMDGOALS)),)
   KBUILD_MODULES := 1
 endif
 
@@ -1104,7 +1104,7 @@ endif # CONFIG_MODULES
 CLEAN_DIRS  += $(MODVERDIR)
 CLEAN_FILES +=	barebox System.map include/generated/barebox_default_env.h \
                 .tmp_version .tmp_barebox* barebox.bin barebox.map barebox.S \
-		.tmp_kallsyms* barebox.ldr \
+		.tmp_kallsyms* barebox.ldr compile_commands.json \
 		scripts/bareboxenv-target barebox-flash-image \
 		barebox.srec barebox.s5p barebox.ubl barebox.zynq \
 		barebox.uimage barebox.spi barebox.kwb barebox.kwbuart \
@@ -1162,6 +1162,18 @@ distclean: mrproper
 		-o -name 'core' \) \
 		-type f -print | xargs rm -f
 
+# Clang Tooling
+# ---------------------------------------------------------------------------
+
+quiet_cmd_gen_compile_commands = GEN     $@
+      cmd_gen_compile_commands = $(PYTHON3) $< -a $(AR) -o $@ $(filter-out $<, $(real-prereqs))
+
+compile_commands.json: scripts/clang-tools/gen_compile_commands.py \
+	$(BAREBOX_OBJS) $(if $(CONFIG_PBL_IMAGE),$(BAREBOX_PBL_OBJS),) FORCE
+	$(call if_changed,gen_compile_commands)
+
+PHONY += compile_commands.json
+
 # Brief documentation of the typical targets used
 # ---------------------------------------------------------------------------
 
diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py
new file mode 100755
index 000000000000..7ed3919f453a
--- /dev/null
+++ b/scripts/clang-tools/gen_compile_commands.py
@@ -0,0 +1,237 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) Google LLC, 2018
+#
+# Author: Tom Roeder <tmroeder at google.com>
+#
+"""A tool for generating compile_commands.json in the Linux kernel."""
+
+import argparse
+import json
+import logging
+import os
+import sys
+import re
+import subprocess
+
+_DEFAULT_OUTPUT = 'compile_commands.json'
+_DEFAULT_LOG_LEVEL = 'WARNING'
+
+_FILENAME_PATTERN = r'^\..*\.cmd$'
+_LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$'
+_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
+
+
+def parse_arguments():
+    """Sets up and parses command-line arguments.
+
+    Returns:
+        log_level: A logging level to filter log output.
+        directory: The work directory where the objects were built.
+        ar: Command used for parsing .a archives.
+        output: Where to write the compile-commands JSON file.
+        paths: The list of files/directories to handle to find .cmd files.
+    """
+    usage = 'Creates a compile_commands.json database from kernel .cmd files'
+    parser = argparse.ArgumentParser(description=usage)
+
+    directory_help = ('specify the output directory used for the kernel build '
+                      '(defaults to the working directory)')
+    parser.add_argument('-d', '--directory', type=str, default='.',
+                        help=directory_help)
+
+    output_help = ('path to the output command database (defaults to ' +
+                   _DEFAULT_OUTPUT + ')')
+    parser.add_argument('-o', '--output', type=str, default=_DEFAULT_OUTPUT,
+                        help=output_help)
+
+    log_level_help = ('the level of log messages to produce (defaults to ' +
+                      _DEFAULT_LOG_LEVEL + ')')
+    parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS,
+                        default=_DEFAULT_LOG_LEVEL, help=log_level_help)
+
+    ar_help = 'command used for parsing .a archives'
+    parser.add_argument('-a', '--ar', type=str, default='llvm-ar', help=ar_help)
+
+    paths_help = ('directories to search or files to parse '
+                  '(files should be *.o, *.a, or modules.order). '
+                  'If nothing is specified, the current directory is searched')
+    parser.add_argument('paths', type=str, nargs='*', help=paths_help)
+
+    args = parser.parse_args()
+
+    return (args.log_level,
+            os.path.abspath(args.directory),
+            args.output,
+            args.ar,
+            args.paths if len(args.paths) > 0 else [args.directory])
+
+
+def cmdfiles_in_dir(directory):
+    """Generate the iterator of .cmd files found under the directory.
+
+    Walk under the given directory, and yield every .cmd file found.
+
+    Args:
+        directory: The directory to search for .cmd files.
+
+    Yields:
+        The path to a .cmd file.
+    """
+
+    filename_matcher = re.compile(_FILENAME_PATTERN)
+
+    for dirpath, _, filenames in os.walk(directory):
+        for filename in filenames:
+            if filename_matcher.match(filename):
+                yield os.path.join(dirpath, filename)
+
+
+def to_cmdfile(path):
+    """Return the path of .cmd file used for the given build artifact
+
+    Args:
+        Path: file path
+
+    Returns:
+        The path to .cmd file
+    """
+    dir, base = os.path.split(path)
+    return os.path.join(dir, '.' + base + '.cmd')
+
+
+def cmdfiles_for_o(obj):
+    """Generate the iterator of .cmd files associated with the object
+
+    Yield the .cmd file used to build the given object
+
+    Args:
+        obj: The object path
+
+    Yields:
+        The path to .cmd file
+    """
+    yield to_cmdfile(obj)
+
+
+def cmdfiles_for_a(archive, ar):
+    """Generate the iterator of .cmd files associated with the archive.
+
+    Parse the given archive, and yield every .cmd file used to build it.
+
+    Args:
+        archive: The archive to parse
+
+    Yields:
+        The path to every .cmd file found
+    """
+    for obj in subprocess.check_output([ar, '-t', archive]).decode().split():
+        yield to_cmdfile(obj)
+
+
+def cmdfiles_for_modorder(modorder):
+    """Generate the iterator of .cmd files associated with the modules.order.
+
+    Parse the given modules.order, and yield every .cmd file used to build the
+    contained modules.
+
+    Args:
+        modorder: The modules.order file to parse
+
+    Yields:
+        The path to every .cmd file found
+    """
+    with open(modorder) as f:
+        for line in f:
+            ko = line.rstrip()
+            base, ext = os.path.splitext(ko)
+            if ext != '.ko':
+                sys.exit('{}: module path must end with .ko'.format(ko))
+            mod = base + '.mod'
+	    # The first line of *.mod lists the objects that compose the module.
+            with open(mod) as m:
+                for obj in m.readline().split():
+                    yield to_cmdfile(obj)
+
+
+def process_line(root_directory, command_prefix, file_path):
+    """Extracts information from a .cmd line and creates an entry from it.
+
+    Args:
+        root_directory: The directory that was searched for .cmd files. Usually
+            used directly in the "directory" entry in compile_commands.json.
+        command_prefix: The extracted command line, up to the last element.
+        file_path: The .c file from the end of the extracted command.
+            Usually relative to root_directory, but sometimes absolute.
+
+    Returns:
+        An entry to append to compile_commands.
+
+    Raises:
+        ValueError: Could not find the extracted file based on file_path and
+            root_directory or file_directory.
+    """
+    # The .cmd files are intended to be included directly by Make, so they
+    # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the
+    # kernel version). The compile_commands.json file is not interepreted
+    # by Make, so this code replaces the escaped version with '#'.
+    prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#')
+
+    # Use os.path.abspath() to normalize the path resolving '.' and '..' .
+    abs_path = os.path.abspath(os.path.join(root_directory, file_path))
+    if not os.path.exists(abs_path):
+        raise ValueError('File %s not found' % abs_path)
+    return {
+        'directory': root_directory,
+        'file': abs_path,
+        'command': prefix + file_path,
+    }
+
+
+def main():
+    """Walks through the directory and finds and parses .cmd files."""
+    log_level, directory, output, ar, paths = parse_arguments()
+
+    level = getattr(logging, log_level)
+    logging.basicConfig(format='%(levelname)s: %(message)s', level=level)
+
+    line_matcher = re.compile(_LINE_PATTERN)
+
+    compile_commands = []
+
+    for path in paths:
+        # If 'path' is a directory, handle all .cmd files under it.
+        # Otherwise, handle .cmd files associated with the file.
+        # Most of built-in objects are linked via archives (built-in.a or lib.a)
+        # but some objects are linked to vmlinux directly.
+        # Modules are listed in modules.order.
+        if os.path.isdir(path):
+            cmdfiles = cmdfiles_in_dir(path)
+        elif path.endswith('.o'):
+            cmdfiles = cmdfiles_for_o(path)
+        elif path.endswith('.a'):
+            cmdfiles = cmdfiles_for_a(path, ar)
+        elif path.endswith('modules.order'):
+            cmdfiles = cmdfiles_for_modorder(path)
+        else:
+            sys.exit('{}: unknown file type'.format(path))
+
+        for cmdfile in cmdfiles:
+            with open(cmdfile, 'rt') as f:
+                result = line_matcher.match(f.readline())
+                if result:
+                    try:
+                        entry = process_line(directory, result.group(1),
+                                             result.group(2))
+                        compile_commands.append(entry)
+                    except ValueError as err:
+                        logging.info('Could not add line from %s: %s',
+                                     cmdfile, err)
+
+    with open(output, 'wt') as f:
+        json.dump(compile_commands, f, indent=2, sort_keys=True)
+
+
+if __name__ == '__main__':
+    main()
-- 
2.30.0



From ahmad at a3f.at  Sun Jan 31 15:18:39 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 21:18:39 +0100
Subject: [PATCH 0/7] Add sound and GRUB beep tune support
Message-ID: <20210131201846.3440477-1-ahmad@a3f.at>

I've been meaning to upstream pwm-beeper support for a piezobuzzer,
but it would be a real shame if the obnoxious buzzing would delay the
boot. So let me present asynchronous beeping support for barebox.

If you don't have the suitable hardware lying around you can synth
your own tunes on the barebox sandbox shell as well.

The Imperial March:
  beep 480 440 4 440 4 440 4 349 3 523 1 440 4 349 3 523 1 440 8 659 4 659 4 659 4 698 3 523 1 415 4 349 3 523 1 440 8

Rebel's sabotage:
  beep -c

Cheers,
Ahmad Fatoum (7):
  sandbox: migrate to SDL 2.0
  drivers: add sound card driver support
  sound: add basic synthesizers for PCM beeper use
  sound: add SDL 2.0 sound driver
  commands: add beep command
  sound: add PWM beeper support
  sound: add gpio-beeper support

 arch/sandbox/Kconfig                          |   3 +
 arch/sandbox/Makefile                         |   6 +-
 arch/sandbox/configs/sandbox_defconfig        |   1 +
 arch/sandbox/dts/sandbox.dts                  |   4 +
 .../sandbox/mach-sandbox/include/mach/linux.h |  22 ++-
 arch/sandbox/os/Makefile                      |   4 +-
 arch/sandbox/os/sdl.c                         | 184 +++++++++++-------
 commands/Kconfig                              |   7 +
 commands/Makefile                             |   1 +
 commands/beep.c                               |  99 ++++++++++
 drivers/Kconfig                               |   1 +
 drivers/Makefile                              |   1 +
 drivers/sound/Kconfig                         |  38 ++++
 drivers/sound/Makefile                        |   5 +
 drivers/sound/core.c                          | 121 ++++++++++++
 drivers/sound/gpio-beeper.c                   |  77 ++++++++
 drivers/sound/pwm-beeper.c                    | 124 ++++++++++++
 drivers/sound/sdl.c                           |  87 +++++++++
 drivers/sound/synth.c                         |  43 ++++
 drivers/video/Kconfig                         |   1 +
 drivers/video/sdl.c                           |  37 ++--
 include/linux/fixp-arith.h                    | 144 ++++++++++++++
 include/poller.h                              |   4 +
 include/pwm.h                                 |  33 ++++
 include/sound.h                               |  77 ++++++++
 25 files changed, 1033 insertions(+), 91 deletions(-)
 create mode 100644 commands/beep.c
 create mode 100644 drivers/sound/Kconfig
 create mode 100644 drivers/sound/Makefile
 create mode 100644 drivers/sound/core.c
 create mode 100644 drivers/sound/gpio-beeper.c
 create mode 100644 drivers/sound/pwm-beeper.c
 create mode 100644 drivers/sound/sdl.c
 create mode 100644 drivers/sound/synth.c
 create mode 100644 include/linux/fixp-arith.h
 create mode 100644 include/sound.h

-- 
2.30.0



From ahmad at a3f.at  Sun Jan 31 15:18:41 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 21:18:41 +0100
Subject: [PATCH 2/7] drivers: add sound card driver support
In-Reply-To: <20210131201846.3440477-1-ahmad@a3f.at>
References: <20210131201846.3440477-1-ahmad@a3f.at>
Message-ID: <20210131201846.3440477-3-ahmad@a3f.at>

Add driver core boilerplate for sound support in barebox. Using the
provided API in <sound.h>, consumers can play beeps for a fixed duration
of time.

Playing beeps is not blocking and new beeps can be enqueued while one
is already playing. They will be played in succession by a poller, which
will also turn off the sound card when the beep tune is over.

API is also available for blocking until all beeps are played and for
cancelling an underway beep tune.

The API could be later extended for arbitrary PCM audio, should the
need arise.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/Kconfig        |   1 +
 drivers/Makefile       |   1 +
 drivers/sound/Kconfig  |   8 +++
 drivers/sound/Makefile |   2 +
 drivers/sound/core.c   | 121 +++++++++++++++++++++++++++++++++++++++++
 include/poller.h       |   4 ++
 include/sound.h        |  45 +++++++++++++++
 7 files changed, 182 insertions(+)
 create mode 100644 drivers/sound/Kconfig
 create mode 100644 drivers/sound/Makefile
 create mode 100644 drivers/sound/core.c
 create mode 100644 include/sound.h

diff --git a/drivers/Kconfig b/drivers/Kconfig
index dda240578067..0b87c2af2a83 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -13,6 +13,7 @@ source "drivers/mtd/Kconfig"
 source "drivers/ata/Kconfig"
 source "drivers/usb/Kconfig"
 source "drivers/video/Kconfig"
+source "drivers/sound/Kconfig"
 source "drivers/mci/Kconfig"
 source "drivers/clk/Kconfig"
 source "drivers/clocksource/Kconfig"
diff --git a/drivers/Makefile b/drivers/Makefile
index 5a03bdceab81..fab3790288f7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -43,3 +43,4 @@ obj-y	+= soc/imx/
 obj-y	+= nvme/
 obj-y	+= ddr/
 obj-y	+= power/
+obj-$(CONFIG_SOUND) += sound/
diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig
new file mode 100644
index 000000000000..cce5c760afdc
--- /dev/null
+++ b/drivers/sound/Kconfig
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0-only
+menuconfig SOUND
+	bool "Sound drivers"
+	select POLLER
+	help
+	  Say Y here for sound support. At the moment that's just beep tones.
+	  Tones are played asynchronously in a poller. Check the beep command
+	  for how to exercise the API.
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
new file mode 100644
index 000000000000..e343e0fa72b0
--- /dev/null
+++ b/drivers/sound/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += core.o
diff --git a/drivers/sound/core.c b/drivers/sound/core.c
new file mode 100644
index 000000000000..801b1fade552
--- /dev/null
+++ b/drivers/sound/core.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: ? 2021 Ahmad Fatoum
+
+#include <common.h>
+#include <linux/list.h>
+#include <sound.h>
+#include <poller.h>
+#include <linux/iopoll.h>
+
+static LIST_HEAD(card_list);
+
+struct beep {
+	int freq;
+	unsigned int us;
+	struct list_head list;
+};
+
+static int sound_card_do_beep(struct sound_card *card,
+			      int freq, unsigned int us)
+{
+	if (freq == -1)
+		freq = card->bell_frequency;
+
+	return card->beep(card, freq, us);
+}
+
+static void sound_card_poller_cb(void *_card)
+{
+	struct sound_card *card = _card;
+	struct beep *beep;
+
+	beep = list_first_entry_or_null(&card->tune, struct beep, list);
+	if (!beep) {
+		sound_card_do_beep(card, 0, 0);
+		return;
+	}
+
+	list_del(&beep->list);
+
+	poller_call_async(&card->poller, beep->us * 1000ULL,
+			  sound_card_poller_cb, card);
+	sound_card_do_beep(card, beep->freq, beep->us);
+
+	free(beep);
+}
+
+int sound_card_register(struct sound_card *card)
+{
+	if (!card->name)
+		return -EINVAL;
+
+	if (card->bell_frequency <= 0)
+		card->bell_frequency = 1000;
+
+	poller_async_register(&card->poller, card->name);
+	INIT_LIST_HEAD(&card->tune);
+
+	list_add_tail(&card->list, &card_list);
+	return 0;
+}
+
+struct sound_card *sound_card_get_default(void)
+{
+	return list_first_entry_or_null(&card_list, struct sound_card, list);
+}
+
+int sound_card_beep(struct sound_card *card, int freq, unsigned int us)
+{
+	struct beep *beep;
+	int ret;
+
+	if (!card)
+		return -ENODEV;
+
+	if (!poller_async_active(&card->poller)) {
+		ret = sound_card_do_beep(card, freq, us);
+		if (!ret)
+			poller_call_async(&card->poller, us * 1000ULL,
+					  sound_card_poller_cb, card);
+
+		return ret;
+	}
+
+	beep = malloc(sizeof(*beep));
+	if (!beep)
+		return -ENOMEM;
+
+	beep->freq = freq;
+	beep->us = us;
+
+	list_add_tail(&beep->list, &card->tune);
+
+	return 0;
+}
+
+int sound_card_beep_wait(struct sound_card *card, unsigned timeout)
+{
+	bool active;
+	return read_poll_timeout(poller_async_active, active,
+				 !active, timeout, &card->poller);
+}
+
+int sound_card_beep_cancel(struct sound_card *card)
+{
+	struct beep *beep, *tmp;
+	int ret;
+
+	if (!card)
+		return -ENODEV;
+
+	poller_async_cancel(&card->poller);
+
+	ret = card->beep(card, 0, 0);
+
+	list_for_each_entry_safe(beep, tmp, &card->tune, list) {
+		list_del(&beep->list);
+		free(beep);
+	}
+
+	return ret;
+}
diff --git a/include/poller.h b/include/poller.h
index 886557252b69..db773265b2f6 100644
--- a/include/poller.h
+++ b/include/poller.h
@@ -34,6 +34,10 @@ int poller_async_unregister(struct poller_async *pa);
 int poller_call_async(struct poller_async *pa, uint64_t delay_ns,
 		void (*fn)(void *), void *ctx);
 int poller_async_cancel(struct poller_async *pa);
+static inline bool poller_async_active(struct poller_async *pa)
+{
+	return pa->active;
+}
 
 #ifdef CONFIG_POLLER
 void poller_call(void);
diff --git a/include/sound.h b/include/sound.h
new file mode 100644
index 000000000000..f5124aebbda1
--- /dev/null
+++ b/include/sound.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: ? 2021 Ahmad Fatoum */
+
+#ifndef __SOUND_H_
+#define __SOUND_H_
+
+#include <linux/list.h>
+#include <poller.h>
+
+#define BELL_DEFAULT_FREQUENCY	-1
+
+struct sound_card {
+	const char *name;
+	int bell_frequency;
+	int (*beep)(struct sound_card *, unsigned freq, unsigned us);
+
+	/* private */
+	struct list_head list;
+	struct list_head tune;
+	struct poller_async poller;
+};
+
+int sound_card_register(struct sound_card *card);
+int sound_card_beep_wait(struct sound_card *card, unsigned timeout_us);
+int sound_card_beep(struct sound_card *card, int freq, unsigned int us);
+int sound_card_beep_cancel(struct sound_card *card);
+
+struct sound_card *sound_card_get_default(void);
+
+static inline int beep(int freq, unsigned us)
+{
+	return sound_card_beep(sound_card_get_default(), freq, us);
+}
+
+static inline int beep_wait(unsigned timeout_us)
+{
+	return sound_card_beep_wait(sound_card_get_default(), timeout_us);
+}
+
+static inline int beep_cancel(void)
+{
+	return sound_card_beep_cancel(sound_card_get_default());
+}
+
+#endif
-- 
2.30.0



From ahmad at a3f.at  Sun Jan 31 15:18:42 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 21:18:42 +0100
Subject: [PATCH 3/7] sound: add basic synthesizers for PCM beeper use
In-Reply-To: <20210131201846.3440477-1-ahmad@a3f.at>
References: <20210131201846.3440477-1-ahmad@a3f.at>
Message-ID: <20210131201846.3440477-4-ahmad@a3f.at>

For beeping on PCM sound cards, barebox will need to synthesize samples.
Add basic sine and square wave synthesizers to achieve this.

Client code can either call __synth_F to explicitly select synth F or
synth_F, which depending on CONFIG_SYNTH_SQUARES may expand to either
__synth_F or a gain-adjusted __synth_generate_square.

The latter is mainly useful for slow systems that can't synthesize
enough sine samples in a poller without impacting boot performance.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/sound/Kconfig      |  13 ++++
 drivers/sound/Makefile     |   2 +-
 drivers/sound/synth.c      |  43 +++++++++++
 include/linux/fixp-arith.h | 144 +++++++++++++++++++++++++++++++++++++
 include/sound.h            |  32 +++++++++
 5 files changed, 233 insertions(+), 1 deletion(-)
 create mode 100644 drivers/sound/synth.c
 create mode 100644 include/linux/fixp-arith.h

diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig
index cce5c760afdc..d9f63a5f3c55 100644
--- a/drivers/sound/Kconfig
+++ b/drivers/sound/Kconfig
@@ -6,3 +6,16 @@ menuconfig SOUND
 	  Say Y here for sound support. At the moment that's just beep tones.
 	  Tones are played asynchronously in a poller. Check the beep command
 	  for how to exercise the API.
+
+if SOUND
+
+config SYNTH_SQUARES
+	bool "Synthesize square waves only"
+	help
+	  For beeping on PCM sound cards, barebox needs to synthesize samples,
+	  which can take too much poller time for crisp playback and/or quick
+	  booting. If your playback stutters, say Y here. This will have all
+	  synthesizers output a gain-adjusted square wave instead, which is
+	  less time-consuming to compute.
+
+endif
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index e343e0fa72b0..69873faab985 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -1,2 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-y += core.o
+obj-y += core.o synth.o
diff --git a/drivers/sound/synth.c b/drivers/sound/synth.c
new file mode 100644
index 000000000000..c9de62b51684
--- /dev/null
+++ b/drivers/sound/synth.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2012 Samsung Electronics, R. Chandrasekar <rcsekar at samsung.com>
+ * Copyright (C) 2021 Ahmad Fatoum
+ */
+
+#include <common.h>
+#include <linux/fixp-arith.h>
+#include <linux/math64.h>
+#include <sound.h>
+
+void __synth_sin(unsigned freq, s16 amplitude, s16 *stream,
+		 unsigned sample_rate, unsigned nsamples)
+{
+    int64_t v = 0;
+    int i = 0;
+
+    for (i = 0; i < nsamples; i++) {
+	    /* Assume RHS sign extension, true for GCC */
+	    stream[i] = (fixp_sin32(div_s64(v * 360, sample_rate)) * (int64_t)amplitude) >> 31;
+	    v += freq;
+    }
+}
+
+void __synth_square(unsigned freq, s16 amplitude, s16 *stream,
+		    unsigned sample_rate, unsigned nsamples)
+{
+	unsigned period = freq ? sample_rate / freq : 0;
+	int half = period / 2;
+
+	while (nsamples) {
+		int i;
+
+		for (i = 0; nsamples && i < half; i++) {
+			nsamples--;
+			*stream++ = amplitude;
+		}
+		for (i = 0; nsamples && i < period - half; i++) {
+			nsamples--;
+			*stream++ = -amplitude;
+		}
+	}
+}
diff --git a/include/linux/fixp-arith.h b/include/linux/fixp-arith.h
new file mode 100644
index 000000000000..8396013785ef
--- /dev/null
+++ b/include/linux/fixp-arith.h
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _FIXP_ARITH_H
+#define _FIXP_ARITH_H
+
+#include <linux/math64.h>
+
+/*
+ * Simplistic fixed-point arithmetics.
+ * Hmm, I'm probably duplicating some code :(
+ *
+ * Copyright (c) 2002 Johann Deneux
+ */
+
+/*
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to <johann.deneux at gmail.com>
+ */
+
+#include <linux/types.h>
+
+static const s32 sin_table[] = {
+	0x00000000, 0x023be165, 0x04779632, 0x06b2f1d2, 0x08edc7b6, 0x0b27eb5c,
+	0x0d61304d, 0x0f996a26, 0x11d06c96, 0x14060b67, 0x163a1a7d, 0x186c6ddd,
+	0x1a9cd9ac, 0x1ccb3236, 0x1ef74bf2, 0x2120fb82, 0x234815ba, 0x256c6f9e,
+	0x278dde6e, 0x29ac379f, 0x2bc750e8, 0x2ddf003f, 0x2ff31bdd, 0x32037a44,
+	0x340ff241, 0x36185aee, 0x381c8bb5, 0x3a1c5c56, 0x3c17a4e7, 0x3e0e3ddb,
+	0x3fffffff, 0x41ecc483, 0x43d464fa, 0x45b6bb5d, 0x4793a20f, 0x496af3e1,
+	0x4b3c8c11, 0x4d084650, 0x4ecdfec6, 0x508d9210, 0x5246dd48, 0x53f9be04,
+	0x55a6125a, 0x574bb8e5, 0x58ea90c2, 0x5a827999, 0x5c135399, 0x5d9cff82,
+	0x5f1f5ea0, 0x609a52d1, 0x620dbe8a, 0x637984d3, 0x64dd894f, 0x6639b039,
+	0x678dde6d, 0x68d9f963, 0x6a1de735, 0x6b598ea1, 0x6c8cd70a, 0x6db7a879,
+	0x6ed9eba0, 0x6ff389de, 0x71046d3c, 0x720c8074, 0x730baeec, 0x7401e4bf,
+	0x74ef0ebb, 0x75d31a5f, 0x76adf5e5, 0x777f903b, 0x7847d908, 0x7906c0af,
+	0x79bc384c, 0x7a6831b8, 0x7b0a9f8c, 0x7ba3751c, 0x7c32a67c, 0x7cb82884,
+	0x7d33f0c8, 0x7da5f5a3, 0x7e0e2e31, 0x7e6c924f, 0x7ec11aa3, 0x7f0bc095,
+	0x7f4c7e52, 0x7f834ecf, 0x7fb02dc4, 0x7fd317b3, 0x7fec09e1, 0x7ffb025e,
+	0x7fffffff
+};
+
+/**
+ * __fixp_sin32() returns the sin of an angle in degrees
+ *
+ * @degrees: angle, in degrees, from 0 to 360.
+ *
+ * The returned value ranges from -0x7fffffff to +0x7fffffff.
+ */
+static inline s32 __fixp_sin32(int degrees)
+{
+	s32 ret;
+	bool negative = false;
+
+	if (degrees > 180) {
+		negative = true;
+		degrees -= 180;
+	}
+	if (degrees > 90)
+		degrees = 180 - degrees;
+
+	ret = sin_table[degrees];
+
+	return negative ? -ret : ret;
+}
+
+/**
+ * fixp_sin32() returns the sin of an angle in degrees
+ *
+ * @degrees: angle, in degrees. The angle can be positive or negative
+ *
+ * The returned value ranges from -0x7fffffff to +0x7fffffff.
+ */
+static inline s32 fixp_sin32(int degrees)
+{
+	degrees = (degrees % 360 + 360) % 360;
+
+	return __fixp_sin32(degrees);
+}
+
+/* cos(x) = sin(x + 90 degrees) */
+#define fixp_cos32(v) fixp_sin32((v) + 90)
+
+/*
+ * 16 bits variants
+ *
+ * The returned value ranges from -0x7fff to 0x7fff
+ */
+
+#define fixp_sin16(v) (fixp_sin32(v) >> 16)
+#define fixp_cos16(v) (fixp_cos32(v) >> 16)
+
+/**
+ * fixp_sin32_rad() - calculates the sin of an angle in radians
+ *
+ * @radians: angle, in radians
+ * @twopi: value to be used for 2*pi
+ *
+ * Provides a variant for the cases where just 360
+ * values is not enough. This function uses linear
+ * interpolation to a wider range of values given by
+ * twopi var.
+ *
+ * Experimental tests gave a maximum difference of
+ * 0.000038 between the value calculated by sin() and
+ * the one produced by this function, when twopi is
+ * equal to 360000. That seems to be enough precision
+ * for practical purposes.
+ *
+ * Please notice that two high numbers for twopi could cause
+ * overflows, so the routine will not allow values of twopi
+ * bigger than 1^18.
+ */
+static inline s32 fixp_sin32_rad(u32 radians, u32 twopi)
+{
+	int degrees;
+	s32 v1, v2, dx, dy;
+	s64 tmp;
+
+	/*
+	 * Avoid too large values for twopi, as we don't want overflows.
+	 */
+	BUG_ON(twopi > 1 << 18);
+
+	degrees = (radians * 360) / twopi;
+	tmp = radians - (degrees * twopi) / 360;
+
+	degrees = (degrees % 360 + 360) % 360;
+	v1 = __fixp_sin32(degrees);
+
+	v2 = fixp_sin32(degrees + 1);
+
+	dx = twopi / 360;
+	dy = v2 - v1;
+
+	tmp *= dy;
+
+	return v1 +  div_s64(tmp, dx);
+}
+
+/* cos(x) = sin(x + pi/2 radians) */
+
+#define fixp_cos32_rad(rad, twopi)	\
+	fixp_sin32_rad(rad + twopi / 4, twopi)
+
+#endif
diff --git a/include/sound.h b/include/sound.h
index f5124aebbda1..62fef106ee73 100644
--- a/include/sound.h
+++ b/include/sound.h
@@ -42,4 +42,36 @@ static inline int beep_cancel(void)
 	return sound_card_beep_cancel(sound_card_get_default());
 }
 
+
+/*
+ * Synthesizers all have the same prototype, but their implementation
+ * is replaced with a gain-adjusted square wave if CONFIG_SYNTH_SQUARES=y.
+ * This is to support PCM beeping on systems, where sine generation may
+ * spend to much time in the poller.
+ */
+typedef void synth_t(unsigned freq, s16 amplitude, s16 *stream,
+		     unsigned sample_rate, unsigned nsamples);
+
+#ifdef CONFIG_SYNTH_SQUARES
+#define SYNTH(fn, volume_percent)                                \
+	static inline void fn(unsigned f, s16 amplitude, s16 *s, \
+			      unsigned r, unsigned n) {          \
+		synth_t __synth_square;                          \
+		amplitude = amplitude * volume_percent / 100;    \
+		__synth_square(f, amplitude, s, r, n);           \
+	}                                                        \
+	synth_t __##fn
+#else
+#define SYNTH(fn, volume_percent)                                \
+	static inline void fn(unsigned f, s16 a, s16 *s,         \
+			      unsigned r, unsigned n) {          \
+		synth_t __##fn;                                  \
+		__##fn(f, a, s, r, n);                           \
+	}                                                        \
+        synth_t __##fn
+#endif
+
+SYNTH(synth_square, 100);	/* square wave always has full amplitude */
+SYNTH(synth_sin, 64);		/* ??? sin(?x) dx ? 64% */
+
 #endif
-- 
2.30.0



From ahmad at a3f.at  Sun Jan 31 15:18:44 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 21:18:44 +0100
Subject: [PATCH 5/7] commands: add beep command
In-Reply-To: <20210131201846.3440477-1-ahmad@a3f.at>
References: <20210131201846.3440477-1-ahmad@a3f.at>
Message-ID: <20210131201846.3440477-6-ahmad@a3f.at>

Add a beep command that's compatible with GRUB's

  play "tempo pitch1 duration1..."

Unlike the GRUB command, playing a tune is not a blocking operating.
For this reason barebox, additionally supports:
  * -w: wait until tune is over
  * -c: cancel playing tune

Additionally, `beep tempo` can be used to ring the bell at a frequency
chosen by the sound card.

Examples:

  # 1-up
  beep 1750 523 1 392 1 523 1 659 1 784 1 1047 1 784 1 415 1 523 \
	1 622 1 831 1 622 1 831 1 1046 1 1244 1 1661 1

  # 1-second beep
  beep 60

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 commands/Kconfig  |  7 ++++
 commands/Makefile |  1 +
 commands/beep.c   | 99 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+)
 create mode 100644 commands/beep.c

diff --git a/commands/Kconfig b/commands/Kconfig
index 03ddfc887074..b672f0c16a85 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -1474,6 +1474,13 @@ config CMD_FBTEST
 	  Framebuffer test command that allows to produce a number of
 	  test patterns on a screen.
 
+config CMD_BEEP
+	def_bool y
+	depends on SOUND
+	prompt "Beep"
+	help
+	  Play beeps. Accepts same format as GRUB play
+
 config CMD_READLINE
 	tristate
 	prompt "readline"
diff --git a/commands/Makefile b/commands/Makefile
index dc285cd00e1b..034c0e6383d3 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_CMD_LSMOD)		+= lsmod.o
 obj-$(CONFIG_CMD_INSMOD)	+= insmod.o
 obj-$(CONFIG_CMD_SPLASH)	+= splash.o
 obj-$(CONFIG_CMD_FBTEST)	+= fbtest.o
+obj-$(CONFIG_CMD_BEEP)		+= beep.o
 obj-$(CONFIG_USB_GADGET_DFU)	+= dfu.o
 obj-$(CONFIG_USB_GADGET_SERIAL)	+= usbserial.o
 obj-$(CONFIG_CMD_GPIO)		+= gpio.o
diff --git a/commands/beep.c b/commands/beep.c
new file mode 100644
index 000000000000..4e90215cbf26
--- /dev/null
+++ b/commands/beep.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// SPDX-FileCopyrightText: ? 2021 Ahmad Fatoum
+
+#include <common.h>
+#include <command.h>
+#include <sound.h>
+#include <getopt.h>
+
+static int do_beep(int argc, char *argv[])
+{
+	int ret, i, opt;
+	u32 tempo, total_us = 0;
+	bool wait = false;
+
+	while((opt = getopt(argc, argv, "wc")) > 0) {
+		switch(opt) {
+		case 'w':
+			wait = true;
+			break;
+		case 'c':
+			return beep_cancel();
+		default:
+			return COMMAND_ERROR_USAGE;
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (argc == 0 || argc % 2 != 1)
+		return COMMAND_ERROR_USAGE;
+
+	ret = kstrtou32(argv[0], 0, &tempo);
+	if (ret || tempo == 0)
+		return COMMAND_ERROR_USAGE;
+
+	tempo = 60 * USEC_PER_SEC / tempo;
+
+	if (argc == 1) {
+		ret = beep(BELL_DEFAULT_FREQUENCY, tempo);
+		if (ret)
+			return ret;
+
+		total_us += tempo;
+		goto out;
+	}
+
+	for (i = 1; i < argc; i += 2) {
+		u32 pitch = 0, duration;
+		u16 val;
+
+		ret = kstrtou16(argv[i], 0, &val);
+		if (ret)
+			return COMMAND_ERROR_USAGE;
+
+		if (val)
+			pitch = clamp_t(unsigned, val, 20, 20000);
+
+		ret = kstrtou16(argv[i+1], 0, &val);
+		if (ret)
+			return COMMAND_ERROR_USAGE;
+
+		duration = val * tempo;
+
+		ret = beep(pitch, duration);
+		if (ret)
+			return ret;
+
+		total_us += duration;
+	}
+
+out:
+	if (wait)
+		beep_wait(total_us);
+
+	return 0;
+}
+
+/* https://www.gnu.org/software/grub/manual/grub/html_node/play.html */
+BAREBOX_CMD_HELP_START(beep)
+BAREBOX_CMD_HELP_TEXT("Tempo is an unsigned 32bit number. It's followed by pairs of unsigned")
+BAREBOX_CMD_HELP_TEXT("16bit numbers for pitch and duration.")
+BAREBOX_CMD_HELP_TEXT("The tempo is the base for all note durations. 60 gives a 1-second base,")
+BAREBOX_CMD_HELP_TEXT("120 gives a half-second base, etc. Pitches are Hz.")
+BAREBOX_CMD_HELP_TEXT("Set pitch to 0 to produce a rest.")
+BAREBOX_CMD_HELP_TEXT("When only tempo is given, a beep of duration 1 at bell frequency results.")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-c",  "cancel pending beeps")
+BAREBOX_CMD_HELP_OPT ("-w",  "wait until beep is over")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(beep)
+	.cmd = do_beep,
+	BAREBOX_CMD_DESC("play a GRUB beep tune")
+	BAREBOX_CMD_OPTS("tempo [pitch1 duration1 [pitch2 diraction2] ...]")
+	BAREBOX_CMD_HELP(cmd_beep_help)
+	BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE)
+BAREBOX_CMD_END
-- 
2.30.0



From ahmad at a3f.at  Sun Jan 31 15:18:43 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 21:18:43 +0100
Subject: [PATCH 4/7] sound: add SDL 2.0 sound driver
In-Reply-To: <20210131201846.3440477-1-ahmad@a3f.at>
References: <20210131201846.3440477-1-ahmad@a3f.at>
Message-ID: <20210131201846.3440477-5-ahmad@a3f.at>

SDL 2.0.4 features SDL_QueueAudio, which we could use to just queue
buffers for audio playback. Use it to implement the new sound API for
the sandbox architecture.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 arch/sandbox/configs/sandbox_defconfig        |  1 +
 arch/sandbox/dts/sandbox.dts                  |  4 +
 .../sandbox/mach-sandbox/include/mach/linux.h |  5 ++
 arch/sandbox/os/sdl.c                         | 44 ++++++++++
 drivers/sound/Kconfig                         |  5 ++
 drivers/sound/Makefile                        |  1 +
 drivers/sound/sdl.c                           | 87 +++++++++++++++++++
 7 files changed, 147 insertions(+)
 create mode 100644 drivers/sound/sdl.c

diff --git a/arch/sandbox/configs/sandbox_defconfig b/arch/sandbox/configs/sandbox_defconfig
index ca24d81acac7..66fcfbdbd0a3 100644
--- a/arch/sandbox/configs/sandbox_defconfig
+++ b/arch/sandbox/configs/sandbox_defconfig
@@ -107,6 +107,7 @@ CONFIG_MTD=y
 CONFIG_MTD_M25P80=y
 CONFIG_VIDEO=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
 CONFIG_MFD_SYSCON=y
 CONFIG_STATE_DRV=y
 CONFIG_UBOOTVAR=y
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index afe48154c488..ef1fa7b8661f 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -94,4 +94,8 @@ barebox,sandbox-power
 		compatible = "barebox,sandbox-watchdog";
 		barebox,reset-source = <&stickypage 0>;
 	};
+
+	sound {
+		compatible = "barebox,sandbox-sound";
+	};
 };
diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h
index c636a9af9cd2..6e10fdbe6d80 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -49,6 +49,11 @@ int sdl_video_open(const struct sdl_fb_info *);
 void sdl_video_pause(void);
 void sdl_video_close(void);
 
+int sdl_sound_init(unsigned sample_rate);
+int sdl_sound_play(const void *data, unsigned nsamples);
+void sdl_sound_stop(void);
+void sdl_sound_close(void);
+
 struct ft2232_bitbang;
 struct ft2232_bitbang *barebox_libftdi1_open(int vendor_id, int device_id,
 						const char *serial);
diff --git a/arch/sandbox/os/sdl.c b/arch/sandbox/os/sdl.c
index 623e24cf0b26..13178abfc044 100644
--- a/arch/sandbox/os/sdl.c
+++ b/arch/sandbox/os/sdl.c
@@ -111,3 +111,47 @@ quit_subsystem:
 
 	return -1;
 }
+
+static SDL_AudioDeviceID dev;
+
+int sdl_sound_init(unsigned sample_rate)
+{
+	SDL_AudioSpec audiospec = {
+		.freq = sample_rate,
+		.format = AUDIO_S16,
+		.channels = 1,
+		.samples = 2048,
+	};
+
+	if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
+		sdl_perror("initialize SDL Audio");
+		return -1;
+	}
+
+	dev = SDL_OpenAudioDevice(NULL, 0, &audiospec, NULL, 0);
+	if (!dev) {
+		sdl_perror("initialize open audio device");
+		SDL_QuitSubSystem(SDL_INIT_AUDIO);
+		return -1;
+	}
+
+	SDL_PauseAudioDevice(dev, 0);
+	return 0;
+}
+
+void sdl_sound_close(void)
+{
+	SDL_QuitSubSystem(SDL_INIT_AUDIO);
+}
+
+int sdl_sound_play(const void *data, unsigned nsamples)
+{
+	/* core sound support handles all the queueing for us */
+	SDL_ClearQueuedAudio(dev);
+	return SDL_QueueAudio(dev, data, nsamples * sizeof(uint16_t));
+}
+
+void sdl_sound_stop(void)
+{
+	SDL_ClearQueuedAudio(dev);
+}
diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig
index d9f63a5f3c55..889657305b0b 100644
--- a/drivers/sound/Kconfig
+++ b/drivers/sound/Kconfig
@@ -9,6 +9,11 @@ menuconfig SOUND
 
 if SOUND
 
+config SOUND_SDL
+	bool "SDL sound driver for sandbox"
+	depends on SANDBOX && OFDEVICE
+	select SDL
+
 config SYNTH_SQUARES
 	bool "Synthesize square waves only"
 	help
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 69873faab985..692105fd6b59 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -1,2 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y += core.o synth.o
+obj-$(CONFIG_SOUND_SDL)		+= sdl.o
diff --git a/drivers/sound/sdl.c b/drivers/sound/sdl.c
new file mode 100644
index 000000000000..118d7742955f
--- /dev/null
+++ b/drivers/sound/sdl.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <common.h>
+#include <errno.h>
+#include <driver.h>
+#include <mach/linux.h>
+#include <linux/time.h>
+#include <linux/math64.h>
+#include <of.h>
+#include <sound.h>
+
+#define AMPLITUDE	28000
+#define SAMPLERATE	44000ULL
+
+struct sandbox_sound {
+	struct sound_card card;
+};
+
+static int sandbox_sound_beep(struct sound_card *card, unsigned freq, unsigned duration)
+{
+    size_t nsamples = div_s64(SAMPLERATE * duration, USEC_PER_SEC);
+    int16_t *data;
+    int ret;
+
+    if (!freq) {
+	    sdl_sound_stop();
+	    return 0;
+    }
+
+    data = malloc(nsamples * sizeof(*data));
+    if (!data)
+	    return -ENOMEM;
+
+    synth_sin(freq, AMPLITUDE, data, SAMPLERATE, nsamples);
+    ret = sdl_sound_play(data, nsamples);
+    if (ret)
+	    ret = -EIO;
+    free(data);
+
+    return ret;
+}
+
+static int sandbox_sound_probe(struct device_d *dev)
+{
+	struct sandbox_sound *priv;
+	struct sound_card *card;
+	int ret;
+
+	priv = xzalloc(sizeof(*priv));
+
+	card = &priv->card;
+	card->name = "SDL-Audio";
+	card->beep = sandbox_sound_beep;
+
+	ret = sdl_sound_init(SAMPLERATE);
+	if (ret) {
+		ret = -ENODEV;
+		goto free_priv;
+	}
+
+	ret = sound_card_register(card);
+	if (ret)
+		goto sdl_sound_close;
+
+	dev_info(dev, "probed\n");
+	return 0;
+
+sdl_sound_close:
+	sdl_sound_close();
+free_priv:
+	free(priv);
+
+	return ret;
+}
+
+
+static __maybe_unused struct of_device_id sandbox_sound_dt_ids[] = {
+	{ .compatible = "barebox,sandbox-sound" },
+	{ /* sentinel */ }
+};
+
+static struct driver_d sandbox_sound_drv = {
+	.name  = "sandbox-sound",
+	.of_compatible = sandbox_sound_dt_ids,
+	.probe = sandbox_sound_probe,
+};
+device_platform_driver(sandbox_sound_drv);
-- 
2.30.0



From ahmad at a3f.at  Sun Jan 31 15:18:40 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 21:18:40 +0100
Subject: [PATCH 1/7] sandbox: migrate to SDL 2.0
In-Reply-To: <20210131201846.3440477-1-ahmad@a3f.at>
References: <20210131201846.3440477-1-ahmad@a3f.at>
Message-ID: <20210131201846.3440477-2-ahmad@a3f.at>

SDL 2.0 has been released more than 7 years ago and should be available
everywhere. Replace barebox's SDL 1.2 with SDL 2.0 instead:

 - better maintained

 - At least on Debian, you can't install x86_64 and i386 libsdl-dev at
   the same time, which makes a quick use of CONFIG_SANDBOX_LINUX_I386
   harder as the user needs to reinstall libraries. With SDL 2.0, it
   works

 - SDL 2.0 has easier audio API, which will be used in a later commit

 - Wayland support for sandbox video driver

Port to SDL 2.0 and as we touch everything anyway, rename the
sdl_ functions to start with sdl_video_ to differentiate from upcoming
sdl_sound_.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 arch/sandbox/Kconfig                          |   3 +
 arch/sandbox/Makefile                         |   6 +-
 .../sandbox/mach-sandbox/include/mach/linux.h |  17 +-
 arch/sandbox/os/Makefile                      |   4 +-
 arch/sandbox/os/sdl.c                         | 146 ++++++++++--------
 drivers/video/Kconfig                         |   1 +
 drivers/video/sdl.c                           |  37 +++--
 7 files changed, 120 insertions(+), 94 deletions(-)

diff --git a/arch/sandbox/Kconfig b/arch/sandbox/Kconfig
index d9fc0c947b02..deff7f56a025 100644
--- a/arch/sandbox/Kconfig
+++ b/arch/sandbox/Kconfig
@@ -43,3 +43,6 @@ config 64BIT
 
 config SANDBOX_LINUX_I386
 	bool "32-bit x86 barebox" if CC_HAS_LINUX_I386_SUPPORT
+
+config SDL
+	bool
diff --git a/arch/sandbox/Makefile b/arch/sandbox/Makefile
index 17f9a298d773..ea594944e4eb 100644
--- a/arch/sandbox/Makefile
+++ b/arch/sandbox/Makefile
@@ -37,8 +37,8 @@ archprepare: maketools
 
 PHONY += maketools
 
-ifeq ($(CONFIG_DRIVER_VIDEO_SDL),y)
-SDL_LIBS := $(shell pkg-config sdl --libs)
+ifeq ($(CONFIG_SDL),y)
+SDL_LIBS := $(shell pkg-config sdl2 --libs)
 endif
 
 ifeq ($(CONFIG_GPIO_LIBFTDI1),y)
@@ -64,7 +64,7 @@ endif
 BAREBOX_LDFLAGS += \
 	-Wl,-T,$(BAREBOX_LDS) \
 	-Wl,--whole-archive $(BAREBOX_OBJS) -Wl,--no-whole-archive \
-	-lrt -lpthread $(SDL_LIBS) $(FTDI1_LIBS) \
+	-lrt $(SDL_LIBS) $(FTDI1_LIBS) \
 	$(SANITIZER_LIBS)
 
 cmd_barebox__ = $(CC) -o $@ $(BAREBOX_LDFLAGS)
diff --git a/arch/sandbox/mach-sandbox/include/mach/linux.h b/arch/sandbox/mach-sandbox/include/mach/linux.h
index b26bfc24a291..c636a9af9cd2 100644
--- a/arch/sandbox/mach-sandbox/include/mach/linux.h
+++ b/arch/sandbox/mach-sandbox/include/mach/linux.h
@@ -38,13 +38,16 @@ struct linux_console_data {
 
 extern int sdl_xres;
 extern int sdl_yres;
-void sdl_close(void);
-int sdl_open(int xres, int yres, int bpp, void* buf);
-void sdl_stop_timer(void);
-void sdl_start_timer(void);
-void sdl_get_bitfield_rgba(struct fb_bitfield *r, struct fb_bitfield *g,
-			    struct fb_bitfield *b, struct fb_bitfield *a);
-void sdl_setpixel(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
+struct sdl_fb_info {
+	void *screen_base;
+	int xres;
+	int yres;
+	int bpp;
+	int rmask, gmask, bmask, amask;
+};
+int sdl_video_open(const struct sdl_fb_info *);
+void sdl_video_pause(void);
+void sdl_video_close(void);
 
 struct ft2232_bitbang;
 struct ft2232_bitbang *barebox_libftdi1_open(int vendor_id, int device_id,
diff --git a/arch/sandbox/os/Makefile b/arch/sandbox/os/Makefile
index 15d688bfdd1b..575b1a213050 100644
--- a/arch/sandbox/os/Makefile
+++ b/arch/sandbox/os/Makefile
@@ -17,8 +17,8 @@ endif
 obj-y = common.o tap.o
 obj-$(CONFIG_MALLOC_LIBC) += libc_malloc.o
 
-CFLAGS_sdl.o = $(shell pkg-config sdl --cflags)
-obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o
+CFLAGS_sdl.o = $(shell pkg-config sdl2 --cflags)
+obj-$(CONFIG_SDL) += sdl.o
 
 CFLAGS_ftdi.o = $(shell pkg-config libftdi1 --cflags)
 obj-$(CONFIG_GPIO_LIBFTDI1) += ftdi.o
diff --git a/arch/sandbox/os/sdl.c b/arch/sandbox/os/sdl.c
index 9a35279eb79e..623e24cf0b26 100644
--- a/arch/sandbox/os/sdl.c
+++ b/arch/sandbox/os/sdl.c
@@ -1,103 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
- *
- * GPL v2
+ * Copyright (c) 2021 Ahmad Fatoum
  */
 
 #include <stdio.h>
+#include <stdbool.h>
 #include <SDL.h>
-#include <time.h>
-#include <signal.h>
 #include <mach/linux.h>
-#include <unistd.h>
-#include <pthread.h>
 
-struct fb_bitfield {
-	uint32_t offset;			/* beginning of bitfield	*/
-	uint32_t length;			/* length of bitfield		*/
-	uint32_t msb_right;			/* != 0 : Most significant bit is */
-					/* right */
-};
+static void sdl_perror(const char *what)
+{
+	printf("SDL: Could not %s: %s.\n", what, SDL_GetError());
+}
 
-static SDL_Surface *real_screen;
-static void *buffer = NULL;
-pthread_t th;
+static struct sdl_fb_info info;
+static SDL_atomic_t shutdown;
+SDL_Window *window;
 
-static void sdl_copy_buffer(SDL_Surface *screen)
+static int scanout(void *ptr)
 {
-	if (SDL_MUSTLOCK(screen)) {
-		if (SDL_LockSurface(screen) < 0)
-			return;
+	SDL_Renderer *renderer;
+	SDL_Surface *surface;
+	SDL_Texture *texture;
+	void *buf = info.screen_base;
+	int ret = -1;
+
+	renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
+	if (!renderer) {
+		sdl_perror("create renderer");
+		return -1;
 	}
 
-	memcpy(screen->pixels, buffer, screen->pitch * screen->h);
+	surface = SDL_CreateRGBSurface(0, info.xres, info.yres, info.bpp,
+				       info.rmask, info.gmask, info.bmask, info.amask);
+	if (!surface) {
+		sdl_perror("create surface");
+		goto destroy_renderer;
+	}
 
-	if(SDL_MUSTLOCK(screen))
-		SDL_UnlockSurface(screen);
-}
+	texture = SDL_CreateTextureFromSurface(renderer, surface);
+	if (!texture) {
+		sdl_perror("create texture");
+		goto free_surface;
+	}
 
-static void *threadStart(void *ptr)
-{
-	while (1) {
-		usleep(1000 * 100);
+	while (!SDL_AtomicGet(&shutdown)) {
+		SDL_Delay(100);
 
-		sdl_copy_buffer(real_screen);
-		SDL_Flip(real_screen);
+		SDL_UpdateTexture(texture, NULL, buf, surface->pitch);
+		SDL_RenderClear(renderer);
+		SDL_RenderCopy(renderer, texture, NULL, NULL);
+		SDL_RenderPresent(renderer);
 	}
 
-	return 0;
-}
+	ret = 0;
 
-void sdl_start_timer(void)
-{
-	pthread_attr_t attr;
-	pthread_attr_init(&attr);
-	pthread_create(&th, &attr, threadStart, NULL);
-}
+	SDL_DestroyTexture(texture);
+free_surface:
+	SDL_FreeSurface(surface);
+destroy_renderer:
+	SDL_DestroyRenderer(renderer);
 
-void sdl_stop_timer(void)
-{
-	pthread_cancel(th);
+	return ret;
 }
 
-void sdl_get_bitfield_rgba(struct fb_bitfield *r, struct fb_bitfield *g,
-			    struct fb_bitfield *b, struct fb_bitfield *a)
+static SDL_Thread *thread;
+
+void sdl_video_close(void)
 {
-	SDL_Surface *screen = real_screen;
-
-	r->length = 8 - screen->format->Rloss;
-	r->offset = screen->format->Rshift;
-	g->length = 8 - screen->format->Gloss;
-	g->offset = screen->format->Gshift;
-	b->length = 8 - screen->format->Bloss;
-	b->offset = screen->format->Bshift;
-	a->length = 8 - screen->format->Aloss;
-	a->offset = screen->format->Ashift;
+	SDL_AtomicSet(&shutdown, true); /* implies full memory barrier */
+	SDL_WaitThread(thread, NULL);
+	SDL_AtomicSet(&shutdown, false);
+	SDL_DestroyWindow(window);
+	SDL_QuitSubSystem(SDL_INIT_VIDEO);
 }
 
-int sdl_open(int xres, int yres, int bpp, void* buf)
+int sdl_video_open(const struct sdl_fb_info *_info)
 {
-	int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
+	info = *_info;
 
-	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
-		printf("Could not initialize SDL: %s.\n", SDL_GetError());
+	if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
+		sdl_perror("initialize SDL Video");
 		return -1;
 	}
 
-	real_screen = SDL_SetVideoMode(xres, yres, bpp, flags);
-	if (!real_screen) {
-		sdl_close();
-		fprintf(stderr, "Couldn't create renderer: %s\n", SDL_GetError());
-		return -1;
+	window = SDL_CreateWindow("barebox", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
+				  info.xres, info.yres, 0);
+	if (!window) {
+		sdl_perror("create window");
+		goto quit_subsystem;
 	}
 
-	buffer = buf;
+	/* All scanout needs to happen in the same thread, because not all
+	 * graphic backends are thread-safe. The window is created in the main
+	 * thread though to work around libEGL crashing with SDL_VIDEODRIVER=wayland
+	 */
+
+	thread = SDL_CreateThread(scanout, "video-scanout", NULL);
+	if (!thread) {
+		sdl_perror("start scanout thread");
+		goto destroy_window;
+	}
 
 	return 0;
-}
 
-void sdl_close(void)
-{
-	sdl_stop_timer();
-	SDL_Quit();
+destroy_window:
+	SDL_DestroyWindow(window);
+quit_subsystem:
+	SDL_QuitSubSystem(SDL_INIT_VIDEO);
+
+	return -1;
 }
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 9ec6ea4248c1..b6d468c63c03 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -82,6 +82,7 @@ endif
 config DRIVER_VIDEO_SDL
 	bool "SDL framebuffer driver"
 	depends on SANDBOX
+	select SDL
 
 config DRIVER_VIDEO_PXA
 	bool "PXA27x framebuffer driver"
diff --git a/drivers/video/sdl.c b/drivers/video/sdl.c
index 9811b2cf128e..e9debc51b1e9 100644
--- a/drivers/video/sdl.c
+++ b/drivers/video/sdl.c
@@ -13,23 +13,25 @@
 #include <errno.h>
 #include <gui/graphic_utils.h>
 
+#define to_mask(color) GENMASK(color.length - 1, color.offset)
+
 static void sdlfb_enable(struct fb_info *info)
 {
-	int ret;
-
-	ret = sdl_open(info->xres, info->yres, info->bits_per_pixel,
-		     info->screen_base);
-	if (ret)
-		return;
-	sdl_get_bitfield_rgba(&info->red, &info->green, &info->blue, &info->transp);
-
-	sdl_start_timer();
+	struct sdl_fb_info sdl_info = {
+		.screen_base = info->screen_base,
+		.xres = info->xres, .yres = info->yres, .bpp = info->bits_per_pixel,
+		.rmask = to_mask(info->red),
+		.gmask = to_mask(info->green),
+		.bmask = to_mask(info->blue),
+		.amask = to_mask(info->transp),
+	};
+
+	sdl_video_open(&sdl_info);
 }
 
 static void sdlfb_disable(struct fb_info *info)
 {
-	sdl_stop_timer();
-	sdl_close();
+	sdl_video_close();
 }
 
 static struct fb_ops sdlfb_ops = {
@@ -48,10 +50,19 @@ static int sdlfb_probe(struct device_d *dev)
 	fb = xzalloc(sizeof(*fb));
 	fb->modes.modes = fb->mode = dev->platform_data;
 	fb->modes.num_modes = 1;
-	fb->bits_per_pixel = 4 << 3;
 	fb->xres = fb->mode->xres;
 	fb->yres = fb->mode->yres;
 
+	fb->bits_per_pixel = 32;
+	fb->transp.length = 8;
+	fb->red.length = 8;
+	fb->green.length = 8;
+	fb->blue.length = 8;
+	fb->transp.offset = 24;
+	fb->red.offset = 16;
+	fb->green.offset = 8;
+	fb->blue.offset = 0;
+
 	fb->priv = fb;
 	fb->fbops = &sdlfb_ops;
 
@@ -68,7 +79,6 @@ static int sdlfb_probe(struct device_d *dev)
 
 	kfree(fb->screen_base);
 	kfree(fb);
-	sdl_close();
 	return ret;
 }
 
@@ -78,7 +88,6 @@ static void sdlfb_remove(struct device_d *dev)
 
 	kfree(fb->screen_base);
 	kfree(fb);
-	sdl_close();
 }
 
 static struct driver_d sdlfb_driver = {
-- 
2.30.0



From ahmad at a3f.at  Sun Jan 31 15:18:45 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 21:18:45 +0100
Subject: [PATCH 6/7] sound: add PWM beeper support
In-Reply-To: <20210131201846.3440477-1-ahmad@a3f.at>
References: <20210131201846.3440477-1-ahmad@a3f.at>
Message-ID: <20210131201846.3440477-7-ahmad@a3f.at>

This driver can be used to drive a piezo-buzzer attached to a PWM.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/sound/Kconfig      |   6 ++
 drivers/sound/Makefile     |   1 +
 drivers/sound/pwm-beeper.c | 124 +++++++++++++++++++++++++++++++++++++
 include/pwm.h              |  33 ++++++++++
 4 files changed, 164 insertions(+)
 create mode 100644 drivers/sound/pwm-beeper.c

diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig
index 889657305b0b..9b7bbd7e7a33 100644
--- a/drivers/sound/Kconfig
+++ b/drivers/sound/Kconfig
@@ -14,6 +14,12 @@ config SOUND_SDL
 	depends on SANDBOX && OFDEVICE
 	select SDL
 
+config PWM_BEEPER
+	bool "PWM beeper support"
+	depends on PWM && OFDEVICE
+	help
+	  Say Y here to get support for PWM based beeper devices.
+
 config SYNTH_SQUARES
 	bool "Synthesize square waves only"
 	help
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 692105fd6b59..468e5bee838d 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y += core.o synth.o
 obj-$(CONFIG_SOUND_SDL)		+= sdl.o
+obj-$(CONFIG_PWM_BEEPER) 	+= pwm-beeper.o
diff --git a/drivers/sound/pwm-beeper.c b/drivers/sound/pwm-beeper.c
new file mode 100644
index 000000000000..ef053f97cf47
--- /dev/null
+++ b/drivers/sound/pwm-beeper.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  Copyright (C) 2010, Lars-Peter Clausen <lars at metafoo.de>
+ *  Copyright (C) 2021, Ahmad Fatoum
+ */
+
+#include <common.h>
+#include <regulator.h>
+#include <sound.h>
+#include <of.h>
+#include <pwm.h>
+
+struct pwm_beeper {
+	struct pwm_device *pwm;
+	struct regulator *amplifier;
+	struct sound_card card;
+};
+
+#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
+
+static int pwm_beeper_beep(struct sound_card *card, unsigned freq, unsigned duration)
+{
+	struct pwm_beeper *beeper = container_of(card, struct pwm_beeper, card);
+	struct pwm_state state;
+	int error = 0;
+
+	if (!freq) {
+		regulator_disable(beeper->amplifier);
+		goto pwm_disable;
+	}
+
+	pwm_get_state(beeper->pwm, &state);
+
+	state.p_enable = true;
+	state.period_ns = HZ_TO_NANOSECONDS(freq);
+	pwm_set_relative_duty_cycle(&state, 50, 100);
+
+	error = pwm_apply_state(beeper->pwm, &state);
+	if (error)
+		return error;
+
+	error = regulator_enable(beeper->amplifier);
+	if (error)
+		goto pwm_disable;
+
+	return 0;
+pwm_disable:
+	pwm_disable(beeper->pwm);
+	return error;
+}
+
+static int pwm_beeper_probe(struct device_d *dev)
+{
+	struct pwm_beeper *beeper;
+	struct sound_card *card;
+	struct pwm_state state;
+	u32 bell_frequency;
+	int error;
+
+	beeper = xzalloc(sizeof(*beeper));
+	dev->priv = beeper;
+
+	beeper->pwm = of_pwm_request(dev->device_node, NULL);
+	if (IS_ERR(beeper->pwm)) {
+		error = PTR_ERR(beeper->pwm);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to request PWM device: %d\n",
+				error);
+		return error;
+	}
+
+	/* Sync up PWM state and ensure it is off. */
+	pwm_init_state(beeper->pwm, &state);
+	state.p_enable = false;
+	error = pwm_apply_state(beeper->pwm, &state);
+	if (error) {
+		dev_err(dev, "failed to apply initial PWM state: %d\n",
+			error);
+		return error;
+	}
+
+	beeper->amplifier = regulator_get(dev, "amp");
+	if (IS_ERR(beeper->amplifier)) {
+		error = PTR_ERR(beeper->amplifier);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get 'amp' regulator: %d\n",
+				error);
+		return error;
+	}
+
+	error = of_property_read_u32(dev->device_node, "beeper-hz", &bell_frequency);
+	if (error) {
+		bell_frequency = 1000;
+		dev_dbg(dev, "failed to parse 'beeper-hz' property, using default: %uHz\n",
+			bell_frequency);
+	}
+
+	card = &beeper->card;
+	card->name = dev->device_node->full_name;
+	card->bell_frequency = bell_frequency;
+	card->beep = pwm_beeper_beep;
+
+	return sound_card_register(card);
+}
+
+static void pwm_beeper_suspend(struct device_d *dev)
+{
+	struct pwm_beeper *beeper = dev->priv;
+
+	pwm_beeper_beep(&beeper->card, 0, 0);
+}
+
+static const struct of_device_id pwm_beeper_match[] = {
+	{ .compatible = "pwm-beeper", },
+	{ },
+};
+
+static struct driver_d pwm_beeper_driver = {
+	.name		= "pwm-beeper",
+	.probe		= pwm_beeper_probe,
+	.remove		= pwm_beeper_suspend,
+	.of_compatible	= pwm_beeper_match,
+};
+device_platform_driver(pwm_beeper_driver);
diff --git a/include/pwm.h b/include/pwm.h
index b67ab13d2e2d..2bd59fb8d3b6 100644
--- a/include/pwm.h
+++ b/include/pwm.h
@@ -3,6 +3,7 @@
 #define __PWM_H
 
 #include <dt-bindings/pwm/pwm.h>
+#include <errno.h>
 
 struct pwm_device;
 struct device_d;
@@ -63,6 +64,38 @@ void pwm_disable(struct pwm_device *pwm);
 
 unsigned int pwm_get_period(struct pwm_device *pwm);
 
+/**
+ * pwm_set_relative_duty_cycle() - Set a relative duty cycle value
+ * @state: PWM state to fill
+ * @duty_cycle: relative duty cycle value
+ * @scale: scale in which @duty_cycle is expressed
+ *
+ * This functions converts a relative into an absolute duty cycle (expressed
+ * in nanoseconds), and puts the result in state->duty_cycle.
+ *
+ * For example if you want to configure a 50% duty cycle, call:
+ *
+ * pwm_init_state(pwm, &state);
+ * pwm_set_relative_duty_cycle(&state, 50, 100);
+ * pwm_apply_state(pwm, &state);
+ *
+ * This functions returns -EINVAL if @duty_cycle and/or @scale are
+ * inconsistent (@scale == 0 or @duty_cycle > @scale).
+ */
+static inline int
+pwm_set_relative_duty_cycle(struct pwm_state *state, unsigned int duty_cycle,
+			    unsigned int scale)
+{
+	if (!scale || duty_cycle > scale)
+		return -EINVAL;
+
+	state->duty_ns = DIV_ROUND_CLOSEST_ULL((u64)duty_cycle *
+					       state->period_ns,
+					       scale);
+
+	return 0;
+}
+
 struct pwm_chip;
 
 /**
-- 
2.30.0



From ahmad at a3f.at  Sun Jan 31 15:18:46 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 21:18:46 +0100
Subject: [PATCH 7/7] sound: add gpio-beeper support
In-Reply-To: <20210131201846.3440477-1-ahmad@a3f.at>
References: <20210131201846.3440477-1-ahmad@a3f.at>
Message-ID: <20210131201846.3440477-8-ahmad@a3f.at>

Add support for simple gpio-beepers.

Note that unlike with PWM buzzers, GPIO buzzers can't be controlled
in frequency and thus it doesn't make much sense to use the multiple
argument version of beep with them.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/sound/Kconfig       |  6 +++
 drivers/sound/Makefile      |  1 +
 drivers/sound/gpio-beeper.c | 77 +++++++++++++++++++++++++++++++++++++
 3 files changed, 84 insertions(+)
 create mode 100644 drivers/sound/gpio-beeper.c

diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig
index 9b7bbd7e7a33..bf6f715200e0 100644
--- a/drivers/sound/Kconfig
+++ b/drivers/sound/Kconfig
@@ -20,6 +20,12 @@ config PWM_BEEPER
 	help
 	  Say Y here to get support for PWM based beeper devices.
 
+config GPIO_BEEPER
+	bool "GPIO beeper support"
+	depends on GPIOLIB && OFDEVICE
+	help
+	  Say Y here to get support for GPIO based beeper devices.
+
 config SYNTH_SQUARES
 	bool "Synthesize square waves only"
 	help
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 468e5bee838d..57d9cbd332f7 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -2,3 +2,4 @@
 obj-y += core.o synth.o
 obj-$(CONFIG_SOUND_SDL)		+= sdl.o
 obj-$(CONFIG_PWM_BEEPER) 	+= pwm-beeper.o
+obj-$(CONFIG_GPIO_BEEPER)	+= gpio-beeper.o
diff --git a/drivers/sound/gpio-beeper.c b/drivers/sound/gpio-beeper.c
new file mode 100644
index 000000000000..86fd4a4ee67c
--- /dev/null
+++ b/drivers/sound/gpio-beeper.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ *  Copyright (C) 2021, Ahmad Fatoum
+ */
+
+#include <common.h>
+#include <regulator.h>
+#include <sound.h>
+#include <of.h>
+#include <gpio.h>
+#include <of_gpio.h>
+
+struct gpio_beeper {
+	int gpio;
+	struct sound_card card;
+};
+
+static int gpio_beeper_beep(struct sound_card *card, unsigned freq, unsigned duration)
+{
+	struct gpio_beeper *beeper = container_of(card, struct gpio_beeper, card);
+
+	gpio_set_active(beeper->gpio, freq);
+	return 0;
+}
+
+static int gpio_beeper_probe(struct device_d *dev)
+{
+	struct device_node *np = dev->device_node;
+	struct gpio_beeper *beeper;
+	struct sound_card *card;
+	enum of_gpio_flags of_flags;
+	unsigned long gpio_flags = GPIOF_OUT_INIT_ACTIVE;
+	int ret, gpio;
+
+	gpio = of_get_named_gpio_flags(np, "gpios", 0, &of_flags);
+	if (!gpio_is_valid(gpio))
+		return gpio;
+
+	if (of_flags & OF_GPIO_ACTIVE_LOW)
+		gpio_flags |= GPIOF_ACTIVE_LOW;
+
+	ret = gpio_request_one(gpio, gpio_flags, "gpio-beeper");
+	if (ret) {
+		dev_err(dev, "failed to request gpio %d: %d\n", gpio, ret);
+		return ret;
+	}
+
+	beeper = xzalloc(sizeof(*beeper));
+	beeper->gpio = gpio;
+	dev->priv = beeper;
+
+	card = &beeper->card;
+	card->name = np->full_name;
+	card->beep = gpio_beeper_beep;
+
+	return sound_card_register(card);
+}
+
+static void gpio_beeper_suspend(struct device_d *dev)
+{
+	struct gpio_beeper *beeper = dev->priv;
+
+	gpio_beeper_beep(&beeper->card, 0, 0);
+}
+
+static const struct of_device_id gpio_beeper_match[] = {
+	{ .compatible = "gpio-beeper", },
+	{ },
+};
+
+static struct driver_d gpio_beeper_driver = {
+	.name		= "gpio-beeper",
+	.probe		= gpio_beeper_probe,
+	.remove		= gpio_beeper_suspend,
+	.of_compatible	= gpio_beeper_match,
+};
+device_platform_driver(gpio_beeper_driver);
-- 
2.30.0



From ahmad at a3f.at  Sun Jan 31 15:38:43 2021
From: ahmad at a3f.at (Ahmad Fatoum)
Date: Sun, 31 Jan 2021 21:38:43 +0100
Subject: [PATCH] of: overlay: fix warning about format specifier in debug
 message
Message-ID: <20210131203843.3459595-1-ahmad@a3f.at>

GCC catches a -Wformat-extra-args. Fix it.

Signed-off-by: Ahmad Fatoum <ahmad at a3f.at>
---
 drivers/of/overlay.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index e2a68b0ae8bd..8f4ee3f0a245 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -223,7 +223,7 @@ int of_process_overlay(struct device_node *root,
 
 		target = find_target(root, fragment);
 		if (!target)
-			pr_debug("cannot find target for fragment",
+			pr_debug("cannot find target for fragment %s\n",
 				 fragment->name);
 
 		err = process(target, ovl, data);
-- 
2.30.0



