aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--target/linux/ipq806x/config-5.42
-rw-r--r--target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap148.dts4
-rw-r--r--target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap161.dts4
-rw-r--r--target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-g10.dts2
-rw-r--r--target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts2
-rw-r--r--target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ecw5410.dts2
-rw-r--r--target/linux/ipq806x/patches-5.10/0031-mtd-add-SMEM-parser-for-QCOM-platforms.patch282
-rw-r--r--target/linux/ipq806x/patches-5.10/0061-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch23
-rw-r--r--target/linux/ipq806x/patches-5.10/100-v5.11-dmaengine-qcom-add_ADM_driver.patch (renamed from target/linux/ipq806x/patches-5.10/0002-dmaengine-Add-ADM-driver.patch)287
-rw-r--r--target/linux/ipq806x/patches-5.10/101-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch227
-rw-r--r--target/linux/ipq806x/patches-5.10/102-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch24
-rw-r--r--target/linux/ipq806x/patches-5.4/0031-mtd-add-SMEM-parser-for-QCOM-platforms.patch282
-rw-r--r--target/linux/ipq806x/patches-5.4/0061-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch23
-rw-r--r--target/linux/ipq806x/patches-5.4/100-v5.11-dmaengine-qcom-add_ADM_driver.patch (renamed from target/linux/ipq806x/patches-5.4/0002-dmaengine-Add-ADM-driver.patch)287
-rw-r--r--target/linux/ipq806x/patches-5.4/101-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch227
-rw-r--r--target/linux/ipq806x/patches-5.4/102-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch24
16 files changed, 806 insertions, 896 deletions
diff --git a/target/linux/ipq806x/config-5.4 b/target/linux/ipq806x/config-5.4
index 78a9ad7077..c582b7a52b 100644
--- a/target/linux/ipq806x/config-5.4
+++ b/target/linux/ipq806x/config-5.4
@@ -313,7 +313,7 @@ CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_NAND_CORE=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
CONFIG_MTD_NAND_QCOM=y
-CONFIG_MTD_QCOM_SMEM_PARTS=y
+CONFIG_MTD_QCOMSMEM_PARTS=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_SPI_NOR=y
CONFIG_MTD_SPLIT_FIRMWARE=y
diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap148.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
index b2fdc427e2..29476e3877 100644
--- a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
+++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap148.dts
@@ -30,7 +30,7 @@
&flash {
partitions {
- compatible = "qcom,smem";
+ compatible = "qcom,smem-part";
};
};
@@ -66,7 +66,7 @@
nand-ecc-step-size = <512>;
partitions {
- compatible = "qcom,smem";
+ compatible = "qcom,smem-part";
};
};
};
diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap161.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap161.dts
index 6ba3d70808..914c370552 100644
--- a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap161.dts
+++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-ap161.dts
@@ -38,7 +38,7 @@
&flash {
partitions {
- compatible = "qcom,smem";
+ compatible = "qcom,smem-part";
};
};
@@ -78,7 +78,7 @@
nand-ecc-step-size = <512>;
partitions {
- compatible = "qcom,smem";
+ compatible = "qcom,smem-part";
};
};
};
diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-g10.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-g10.dts
index 15ed5b4773..ccefc23011 100644
--- a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-g10.dts
+++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8064-g10.dts
@@ -179,7 +179,7 @@
nand-ecc-step-size = <512>;
partitions {
- compatible = "qcom,smem";
+ compatible = "qcom,smem-part";
};
};
};
diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts
index 119598d074..34b9c5fc87 100644
--- a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts
+++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8065-nbg6817.dts
@@ -182,7 +182,7 @@
reg = <0>;
partitions {
- compatible = "qcom,smem";
+ compatible = "qcom,smem-part";
};
};
};
diff --git a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ecw5410.dts b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ecw5410.dts
index 712910c261..9b14bb2c29 100644
--- a/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ecw5410.dts
+++ b/target/linux/ipq806x/files/arch/arm/boot/dts/qcom-ipq8068-ecw5410.dts
@@ -184,7 +184,7 @@
reg = <0>;
partitions {
- compatible = "qcom,smem";
+ compatible = "qcom,smem-part";
};
};
};
diff --git a/target/linux/ipq806x/patches-5.10/0031-mtd-add-SMEM-parser-for-QCOM-platforms.patch b/target/linux/ipq806x/patches-5.10/0031-mtd-add-SMEM-parser-for-QCOM-platforms.patch
deleted file mode 100644
index 6aa404c8c5..0000000000
--- a/target/linux/ipq806x/patches-5.10/0031-mtd-add-SMEM-parser-for-QCOM-platforms.patch
+++ /dev/null
@@ -1,282 +0,0 @@
-From d8eeb4de90e968ba32d956728c866f20752cf2c3 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Thu, 9 Mar 2017 08:18:08 +0100
-Subject: [PATCH 31/69] mtd: add SMEM parser for QCOM platforms
-
-On QCOM platforms using MTD devices storage (such as IPQ806x), SMEM is
-used to store partition layout. This new parser can now be used to read
-SMEM and use it to register an MTD layout according to its content.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
-Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org>
----
- drivers/mtd/parsers/Kconfig | 7 ++
- drivers/mtd/parsers/Makefile | 1 +
- drivers/mtd/parsers/qcom_smem_part.c | 228 +++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 236 insertions(+)
- create mode 100644 drivers/mtd/parsers/qcom_smem_part.c
-
---- a/drivers/mtd/parsers/Kconfig
-+++ b/drivers/mtd/parsers/Kconfig
-@@ -119,6 +119,13 @@ config MTD_PARSER_TRX
- This driver will parse TRX header and report at least two partitions:
- kernel and rootfs.
-
-+config MTD_QCOM_SMEM_PARTS
-+ tristate "QCOM SMEM partitioning support"
-+ depends on QCOM_SMEM
-+ help
-+ This provides partitions parser for QCOM devices using SMEM
-+ such as IPQ806x.
-+
- config MTD_SHARPSL_PARTS
- tristate "Sharp SL Series NAND flash partition parser"
- depends on MTD_NAND_SHARPSL || MTD_NAND_TMIO || COMPILE_TEST
---- a/drivers/mtd/parsers/Makefile
-+++ b/drivers/mtd/parsers/Makefile
-@@ -8,6 +8,7 @@ obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
- obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
- obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
- obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
-+obj-$(CONFIG_MTD_QCOM_SMEM_PARTS) += qcom_smem_part.o
- obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
- obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
- obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o
---- /dev/null
-+++ b/drivers/mtd/parsers/qcom_smem_part.c
-@@ -0,0 +1,235 @@
-+/*
-+ * Copyright (c) 2015, The Linux Foundation. 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 version 2 and
-+ * only 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.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/device.h>
-+#include <linux/slab.h>
-+
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/partitions.h>
-+#include <linux/spi/spi.h>
-+#include <linux/module.h>
-+
-+#include <linux/soc/qcom/smem.h>
-+
-+/* Processor/host identifier for the application processor */
-+#define SMEM_HOST_APPS 0
-+
-+/* SMEM items index */
-+#define SMEM_AARM_PARTITION_TABLE 9
-+#define SMEM_BOOT_FLASH_TYPE 421
-+#define SMEM_BOOT_FLASH_BLOCK_SIZE 424
-+
-+/* SMEM Flash types */
-+#define SMEM_FLASH_NAND 2
-+#define SMEM_FLASH_SPI 6
-+
-+#define SMEM_PART_NAME_SZ 16
-+#define SMEM_PARTS_MAX 32
-+
-+struct smem_partition {
-+ char name[SMEM_PART_NAME_SZ];
-+ __le32 start;
-+ __le32 size;
-+ __le32 attr;
-+};
-+
-+struct smem_partition_table {
-+ u8 magic[8];
-+ __le32 version;
-+ __le32 len;
-+ struct smem_partition parts[SMEM_PARTS_MAX];
-+};
-+
-+/* SMEM Magic values in partition table */
-+static const u8 SMEM_PTABLE_MAGIC[] = {
-+ 0xaa, 0x73, 0xee, 0x55,
-+ 0xdb, 0xbd, 0x5e, 0xe3,
-+};
-+
-+static int qcom_smem_get_flash_blksz(u64 **smem_blksz)
-+{
-+ size_t size;
-+
-+ *smem_blksz = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_BLOCK_SIZE,
-+ &size);
-+
-+ if (IS_ERR(*smem_blksz)) {
-+ pr_err("Unable to read flash blksz from SMEM\n");
-+ return -ENOENT;
-+ }
-+
-+ if (size != sizeof(**smem_blksz)) {
-+ pr_err("Invalid flash blksz size in SMEM\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int qcom_smem_get_flash_type(u64 **smem_flash_type)
-+{
-+ size_t size;
-+
-+ *smem_flash_type = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_TYPE,
-+ &size);
-+
-+ if (IS_ERR(*smem_flash_type)) {
-+ pr_err("Unable to read flash type from SMEM\n");
-+ return -ENOENT;
-+ }
-+
-+ if (size != sizeof(**smem_flash_type)) {
-+ pr_err("Invalid flash type size in SMEM\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int qcom_smem_get_flash_partitions(struct smem_partition_table **pparts)
-+{
-+ size_t size;
-+
-+ *pparts = qcom_smem_get(SMEM_HOST_APPS, SMEM_AARM_PARTITION_TABLE,
-+ &size);
-+
-+ if (IS_ERR(*pparts)) {
-+ pr_err("Unable to read partition table from SMEM\n");
-+ return -ENOENT;
-+ }
-+
-+ return 0;
-+}
-+
-+static int of_dev_node_match(struct device *dev, const void *data)
-+{
-+ return dev->of_node == data;
-+}
-+
-+static bool is_spi_device(struct device_node *np)
-+{
-+ struct device *dev;
-+
-+ dev = bus_find_device(&spi_bus_type, NULL, np, of_dev_node_match);
-+ if (!dev)
-+ return false;
-+
-+ put_device(dev);
-+ return true;
-+}
-+
-+static int parse_qcom_smem_partitions(struct mtd_info *master,
-+ const struct mtd_partition **pparts,
-+ struct mtd_part_parser_data *data)
-+{
-+ struct smem_partition_table *smem_parts;
-+ u64 *smem_flash_type, *smem_blksz;
-+ struct mtd_partition *mtd_parts;
-+ struct device_node *of_node = master->dev.of_node;
-+ int i, ret;
-+
-+ /*
-+ * SMEM will only store the partition table of the boot device.
-+ * If this is not the boot device, do not return any partition.
-+ */
-+ ret = qcom_smem_get_flash_type(&smem_flash_type);
-+ if (ret < 0)
-+ return ret;
-+
-+ if ((*smem_flash_type == SMEM_FLASH_NAND && !mtd_type_is_nand(master))
-+ || (*smem_flash_type == SMEM_FLASH_SPI && !is_spi_device(of_node)))
-+ return 0;
-+
-+ /*
-+ * Just for sanity purpose, make sure the block size in SMEM matches the
-+ * block size of the MTD device
-+ */
-+ ret = qcom_smem_get_flash_blksz(&smem_blksz);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (*smem_blksz != master->erasesize) {
-+ pr_err("SMEM block size differs from MTD block size\n");
-+ return -EINVAL;
-+ }
-+
-+ /* Get partition pointer from SMEM */
-+ ret = qcom_smem_get_flash_partitions(&smem_parts);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (memcmp(SMEM_PTABLE_MAGIC, smem_parts->magic,
-+ sizeof(SMEM_PTABLE_MAGIC))) {
-+ pr_err("SMEM partition magic invalid\n");
-+ return -EINVAL;
-+ }
-+
-+ /* Allocate and populate the mtd structures */
-+ mtd_parts = kcalloc(le32_to_cpu(smem_parts->len), sizeof(*mtd_parts),
-+ GFP_KERNEL);
-+ if (!mtd_parts)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < smem_parts->len; i++) {
-+ struct smem_partition *s_part = &smem_parts->parts[i];
-+ struct mtd_partition *m_part = &mtd_parts[i];
-+
-+ m_part->name = s_part->name;
-+ m_part->size = le32_to_cpu(s_part->size) * (*smem_blksz);
-+ m_part->offset = le32_to_cpu(s_part->start) * (*smem_blksz);
-+
-+ /*
-+ * The last SMEM partition may have its size marked as
-+ * something like 0xffffffff, which means "until the end of the
-+ * flash device". In this case, truncate it.
-+ */
-+ if (m_part->offset + m_part->size > master->size)
-+ m_part->size = master->size - m_part->offset;
-+ }
-+
-+ *pparts = mtd_parts;
-+
-+ return smem_parts->len;
-+}
-+
-+static const struct of_device_id qcom_smem_of_match_table[] = {
-+ { .compatible = "qcom,smem" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, qcom_smem_of_match_table);
-+
-+static struct mtd_part_parser qcom_smem_parser = {
-+ .owner = THIS_MODULE,
-+ .parse_fn = parse_qcom_smem_partitions,
-+ .name = "qcom-smem",
-+ .of_match_table = qcom_smem_of_match_table,
-+};
-+
-+static int __init qcom_smem_parser_init(void)
-+{
-+ register_mtd_parser(&qcom_smem_parser);
-+ return 0;
-+}
-+
-+static void __exit qcom_smem_parser_exit(void)
-+{
-+ deregister_mtd_parser(&qcom_smem_parser);
-+}
-+
-+module_init(qcom_smem_parser_init);
-+module_exit(qcom_smem_parser_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Mathieu Olivari <mathieu@codeaurora.org>");
-+MODULE_DESCRIPTION("Parsing code for SMEM based partition tables");
diff --git a/target/linux/ipq806x/patches-5.10/0061-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch b/target/linux/ipq806x/patches-5.10/0061-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch
deleted file mode 100644
index ff6f6edf49..0000000000
--- a/target/linux/ipq806x/patches-5.10/0061-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From 5001f2e1a325b68dbf225bd17f69a4d3d975cca5 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-Date: Thu, 9 Mar 2017 09:31:44 +0100
-Subject: [PATCH 61/69] mtd: "rootfs" conflicts with OpenWrt auto mounting
-
-Signed-off-by: John Crispin <john@phrozen.org>
----
- drivers/mtd/parsers/qcom_smem_part.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/mtd/parsers/qcom_smem_part.c
-+++ b/drivers/mtd/parsers/qcom_smem_part.c
-@@ -189,6 +189,10 @@ static int parse_qcom_smem_partitions(st
- m_part->size = le32_to_cpu(s_part->size) * (*smem_blksz);
- m_part->offset = le32_to_cpu(s_part->start) * (*smem_blksz);
-
-+ /* "rootfs" conflicts with OpenWrt auto mounting */
-+ if (mtd_type_is_nand(master) && !strcmp(m_part->name, "rootfs"))
-+ m_part->name = "ubi";
-+
- /*
- * The last SMEM partition may have its size marked as
- * something like 0xffffffff, which means "until the end of the
diff --git a/target/linux/ipq806x/patches-5.10/0002-dmaengine-Add-ADM-driver.patch b/target/linux/ipq806x/patches-5.10/100-v5.11-dmaengine-qcom-add_ADM_driver.patch
index aa7d2e791e..45062d52fc 100644
--- a/target/linux/ipq806x/patches-5.10/0002-dmaengine-Add-ADM-driver.patch
+++ b/target/linux/ipq806x/patches-5.10/100-v5.11-dmaengine-qcom-add_ADM_driver.patch
@@ -1,86 +1,95 @@
-From 563fa24db4e529c5a3311928d73a8a90531ee527 Mon Sep 17 00:00:00 2001
-From: Thomas Pedersen <twp@codeaurora.org>
-Date: Mon, 16 May 2016 17:58:51 -0700
-Subject: [PATCH 02/69] dmaengine: Add ADM driver
-
-Original patch by Andy Gross.
+From 5c9f8c2dbdbe53818bcde6aa6695e1331e5f841f Mon Sep 17 00:00:00 2001
+From: Jonathan McDowell <noodles@earth.li>
+Date: Sat, 14 Nov 2020 14:02:33 +0000
+Subject: dmaengine: qcom: Add ADM driver
Add the DMA engine driver for the QCOM Application Data Mover (ADM) DMA
controller found in the MSM8x60 and IPQ/APQ8064 platforms.
The ADM supports both memory to memory transactions and memory
-to/from peripheral device transactions. The controller also provides flow
-control capabilities for transactions to/from peripheral devices.
+to/from peripheral device transactions. The controller also provides
+flow control capabilities for transactions to/from peripheral devices.
+
+The initial release of this driver supports slave transfers to/from
+peripherals and also incorporates CRCI (client rate control interface)
+flow control.
-The initial release of this driver supports slave transfers to/from peripherals
-and also incorporates CRCI (client rate control interface) flow control.
+The hardware only supports a 32 bit physical address, so specifying
+!PHYS_ADDR_T_64BIT gives maximum COMPILE_TEST coverage without having to
+spend effort on kludging things in the code that will never actually be
+needed on real hardware.
Signed-off-by: Andy Gross <agross@codeaurora.org>
Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+Signed-off-by: Jonathan McDowell <noodles@earth.li>
+Link: https://lore.kernel.org/r/20201114140233.GM32650@earth.li
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
- drivers/dma/qcom/Kconfig | 10 +
+ drivers/dma/qcom/Kconfig | 11 +
drivers/dma/qcom/Makefile | 1 +
- drivers/dma/qcom/qcom_adm.c | 900 ++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 911 insertions(+)
+ drivers/dma/qcom/qcom_adm.c | 903 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 915 insertions(+)
create mode 100644 drivers/dma/qcom/qcom_adm.c
+diff --git a/drivers/dma/qcom/Kconfig b/drivers/dma/qcom/Kconfig
+index 3bcb689162c67..0389d60d2604a 100644
--- a/drivers/dma/qcom/Kconfig
+++ b/drivers/dma/qcom/Kconfig
-@@ -28,3 +28,13 @@ config QCOM_HIDMA
- (user to kernel, kernel to kernel, etc.). It only supports
- memcpy interface. The core is not intended for general
- purpose slave DMA.
-+
+@@ -1,4 +1,15 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+config QCOM_ADM
+ tristate "Qualcomm ADM support"
-+ depends on ARCH_QCOM || (COMPILE_TEST && OF && ARM)
++ depends on (ARCH_QCOM || COMPILE_TEST) && !PHYS_ADDR_T_64BIT
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
-+ ---help---
-+ Enable support for the Qualcomm ADM DMA controller. This controller
-+ provides DMA capabilities for both general purpose and on-chip
-+ peripheral devices.
++ help
++ Enable support for the Qualcomm Application Data Mover (ADM) DMA
++ controller, as present on MSM8x60, APQ8064, and IPQ8064 devices.
++ This controller provides DMA capabilities for both general purpose
++ and on-chip peripheral devices.
++
+ config QCOM_BAM_DMA
+ tristate "QCOM BAM DMA support"
+ depends on ARCH_QCOM || (COMPILE_TEST && OF && ARM)
+diff --git a/drivers/dma/qcom/Makefile b/drivers/dma/qcom/Makefile
+index 1ae92da88b0c9..346e643fbb6db 100644
--- a/drivers/dma/qcom/Makefile
+++ b/drivers/dma/qcom/Makefile
-@@ -4,3 +4,4 @@ obj-$(CONFIG_QCOM_HIDMA_MGMT) += hdma_mg
- hdma_mgmt-objs := hidma_mgmt.o hidma_mgmt_sys.o
- obj-$(CONFIG_QCOM_HIDMA) += hdma.o
- hdma-objs := hidma_ll.o hidma.o hidma_dbg.o
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_QCOM_ADM) += qcom_adm.o
+ obj-$(CONFIG_QCOM_BAM_DMA) += bam_dma.o
+ obj-$(CONFIG_QCOM_HIDMA_MGMT) += hdma_mgmt.o
+ hdma_mgmt-objs := hidma_mgmt.o hidma_mgmt_sys.o
+diff --git a/drivers/dma/qcom/qcom_adm.c b/drivers/dma/qcom/qcom_adm.c
+new file mode 100644
+index 0000000000000..9b6f8e050ecce
--- /dev/null
+++ b/drivers/dma/qcom/qcom_adm.c
-@@ -0,0 +1,914 @@
+@@ -0,0 +1,903 @@
++// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. 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 version 2 and
-+ * only 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.
-+ *
+ */
+
-+#include <linux/kernel.h>
-+#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/dmaengine.h>
++#include <linux/dma-mapping.h>
+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
+#include <linux/interrupt.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/scatterlist.h>
-+#include <linux/device.h>
-+#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_dma.h>
++#include <linux/platform_device.h>
+#include <linux/reset.h>
-+#include <linux/clk.h>
-+#include <linux/dmaengine.h>
++#include <linux/scatterlist.h>
++#include <linux/slab.h>
+
+#include "../dmaengine.h"
+#include "../virt-dma.h"
@@ -90,10 +99,10 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+#define ADM_CI_MULTI 0x4
+#define ADM_CRCI_MULTI 0x4
+#define ADM_EE_MULTI 0x800
-+#define ADM_CHAN_OFFS(chan) (ADM_CHAN_MULTI * chan)
-+#define ADM_EE_OFFS(ee) (ADM_EE_MULTI * ee)
++#define ADM_CHAN_OFFS(chan) (ADM_CHAN_MULTI * (chan))
++#define ADM_EE_OFFS(ee) (ADM_EE_MULTI * (ee))
+#define ADM_CHAN_EE_OFFS(chan, ee) (ADM_CHAN_OFFS(chan) + ADM_EE_OFFS(ee))
-+#define ADM_CHAN_OFFS(chan) (ADM_CHAN_MULTI * chan)
++#define ADM_CHAN_OFFS(chan) (ADM_CHAN_MULTI * (chan))
+#define ADM_CI_OFFS(ci) (ADM_CHAN_OFF(ci))
+#define ADM_CH_CMD_PTR(chan, ee) (ADM_CHAN_EE_OFFS(chan, ee))
+#define ADM_CH_RSLT(chan, ee) (0x40 + ADM_CHAN_EE_OFFS(chan, ee))
@@ -102,62 +111,62 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+#define ADM_CH_CONF(chan) (0x240 + ADM_CHAN_OFFS(chan))
+#define ADM_CH_RSLT_CONF(chan, ee) (0x300 + ADM_CHAN_EE_OFFS(chan, ee))
+#define ADM_SEC_DOMAIN_IRQ_STATUS(ee) (0x380 + ADM_EE_OFFS(ee))
-+#define ADM_CI_CONF(ci) (0x390 + ci * ADM_CI_MULTI)
++#define ADM_CI_CONF(ci) (0x390 + (ci) * ADM_CI_MULTI)
+#define ADM_GP_CTL 0x3d8
-+#define ADM_CRCI_CTL(crci, ee) (0x400 + crci * ADM_CRCI_MULTI + \
++#define ADM_CRCI_CTL(crci, ee) (0x400 + (crci) * ADM_CRCI_MULTI + \
+ ADM_EE_OFFS(ee))
+
+/* channel status */
-+#define ADM_CH_STATUS_VALID BIT(1)
++#define ADM_CH_STATUS_VALID BIT(1)
+
+/* channel result */
-+#define ADM_CH_RSLT_VALID BIT(31)
-+#define ADM_CH_RSLT_ERR BIT(3)
-+#define ADM_CH_RSLT_FLUSH BIT(2)
-+#define ADM_CH_RSLT_TPD BIT(1)
++#define ADM_CH_RSLT_VALID BIT(31)
++#define ADM_CH_RSLT_ERR BIT(3)
++#define ADM_CH_RSLT_FLUSH BIT(2)
++#define ADM_CH_RSLT_TPD BIT(1)
+
+/* channel conf */
+#define ADM_CH_CONF_SHADOW_EN BIT(12)
+#define ADM_CH_CONF_MPU_DISABLE BIT(11)
+#define ADM_CH_CONF_PERM_MPU_CONF BIT(9)
+#define ADM_CH_CONF_FORCE_RSLT_EN BIT(7)
-+#define ADM_CH_CONF_SEC_DOMAIN(ee) (((ee & 0x3) << 4) | ((ee & 0x4) << 11))
++#define ADM_CH_CONF_SEC_DOMAIN(ee) ((((ee) & 0x3) << 4) | (((ee) & 0x4) << 11))
+
+/* channel result conf */
+#define ADM_CH_RSLT_CONF_FLUSH_EN BIT(1)
+#define ADM_CH_RSLT_CONF_IRQ_EN BIT(0)
+
+/* CRCI CTL */
-+#define ADM_CRCI_CTL_MUX_SEL BIT(18)
-+#define ADM_CRCI_CTL_RST BIT(17)
++#define ADM_CRCI_CTL_MUX_SEL BIT(18)
++#define ADM_CRCI_CTL_RST BIT(17)
+
+/* CI configuration */
-+#define ADM_CI_RANGE_END(x) (x << 24)
-+#define ADM_CI_RANGE_START(x) (x << 16)
-+#define ADM_CI_BURST_4_WORDS BIT(2)
-+#define ADM_CI_BURST_8_WORDS BIT(3)
++#define ADM_CI_RANGE_END(x) ((x) << 24)
++#define ADM_CI_RANGE_START(x) ((x) << 16)
++#define ADM_CI_BURST_4_WORDS BIT(2)
++#define ADM_CI_BURST_8_WORDS BIT(3)
+
+/* GP CTL */
-+#define ADM_GP_CTL_LP_EN BIT(12)
-+#define ADM_GP_CTL_LP_CNT(x) (x << 8)
++#define ADM_GP_CTL_LP_EN BIT(12)
++#define ADM_GP_CTL_LP_CNT(x) ((x) << 8)
+
+/* Command pointer list entry */
-+#define ADM_CPLE_LP BIT(31)
-+#define ADM_CPLE_CMD_PTR_LIST BIT(29)
++#define ADM_CPLE_LP BIT(31)
++#define ADM_CPLE_CMD_PTR_LIST BIT(29)
+
+/* Command list entry */
-+#define ADM_CMD_LC BIT(31)
-+#define ADM_CMD_DST_CRCI(n) (((n) & 0xf) << 7)
-+#define ADM_CMD_SRC_CRCI(n) (((n) & 0xf) << 3)
++#define ADM_CMD_LC BIT(31)
++#define ADM_CMD_DST_CRCI(n) (((n) & 0xf) << 7)
++#define ADM_CMD_SRC_CRCI(n) (((n) & 0xf) << 3)
+
-+#define ADM_CMD_TYPE_SINGLE 0x0
-+#define ADM_CMD_TYPE_BOX 0x3
++#define ADM_CMD_TYPE_SINGLE 0x0
++#define ADM_CMD_TYPE_BOX 0x3
+
-+#define ADM_CRCI_MUX_SEL BIT(4)
-+#define ADM_DESC_ALIGN 8
-+#define ADM_MAX_XFER (SZ_64K-1)
-+#define ADM_MAX_ROWS (SZ_64K-1)
-+#define ADM_MAX_CHANNELS 16
++#define ADM_CRCI_MUX_SEL BIT(4)
++#define ADM_DESC_ALIGN 8
++#define ADM_MAX_XFER (SZ_64K - 1)
++#define ADM_MAX_ROWS (SZ_64K - 1)
++#define ADM_MAX_CHANNELS 16
+
+struct adm_desc_hw_box {
+ u32 cmd;
@@ -255,7 +264,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ case 32:
+ case 64:
+ case 128:
-+ ret = ffs(burst>>4) - 1;
++ ret = ffs(burst >> 4) - 1;
+ break;
+ case 192:
+ ret = 4;
@@ -281,9 +290,10 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * @burst: Burst size of transaction
+ * @direction: DMA transfer direction
+ */
-+static void *adm_process_fc_descriptors(struct adm_chan *achan,
-+ void *desc, struct scatterlist *sg, u32 crci, u32 burst,
-+ enum dma_transfer_direction direction)
++static void *adm_process_fc_descriptors(struct adm_chan *achan, void *desc,
++ struct scatterlist *sg, u32 crci,
++ u32 burst,
++ enum dma_transfer_direction direction)
+{
+ struct adm_desc_hw_box *box_desc = NULL;
+ struct adm_desc_hw_single *single_desc;
@@ -349,9 +359,9 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * @sg: Scatterlist entry
+ * @direction: DMA transfer direction
+ */
-+static void *adm_process_non_fc_descriptors(struct adm_chan *achan,
-+ void *desc, struct scatterlist *sg,
-+ enum dma_transfer_direction direction)
++static void *adm_process_non_fc_descriptors(struct adm_chan *achan, void *desc,
++ struct scatterlist *sg,
++ enum dma_transfer_direction direction)
+{
+ struct adm_desc_hw_single *single_desc;
+ u32 remainder = sg_dma_len(sg);
@@ -398,9 +408,11 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * @context: transfer context (unused)
+ */
+static struct dma_async_tx_descriptor *adm_prep_slave_sg(struct dma_chan *chan,
-+ struct scatterlist *sgl, unsigned int sg_len,
-+ enum dma_transfer_direction direction, unsigned long flags,
-+ void *context)
++ struct scatterlist *sgl,
++ unsigned int sg_len,
++ enum dma_transfer_direction direction,
++ unsigned long flags,
++ void *context)
+{
+ struct adm_chan *achan = to_adm_chan(chan);
+ struct adm_device *adev = achan->adev;
@@ -427,7 +439,6 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ /* if using flow control, validate burst and crci values */
+ if (achan->slave.device_fc) {
-+
+ blk_size = adm_get_blksize(burst);
+ if (blk_size < 0) {
+ dev_err(adev->dev, "invalid burst value: %d\n",
@@ -455,7 +466,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ }
+ }
+
-+ async_desc = kzalloc(sizeof(*async_desc), GFP_ATOMIC);
++ async_desc = kzalloc(sizeof(*async_desc), GFP_NOWAIT);
+ if (!async_desc)
+ return ERR_PTR(-ENOMEM);
+
@@ -468,7 +479,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ box_count * sizeof(struct adm_desc_hw_box) +
+ sizeof(*cple) + 2 * ADM_DESC_ALIGN;
+
-+ async_desc->cpl = kzalloc(async_desc->dma_len, GFP_ATOMIC);
++ async_desc->cpl = kzalloc(async_desc->dma_len, GFP_NOWAIT);
+ if (!async_desc->cpl)
+ goto free;
+
@@ -483,10 +494,10 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ if (achan->slave.device_fc)
+ desc = adm_process_fc_descriptors(achan, desc, sg, crci,
-+ burst, direction);
++ burst, direction);
+ else
+ desc = adm_process_non_fc_descriptors(achan, desc, sg,
-+ direction);
++ direction);
+ }
+
+ async_desc->dma_addr = dma_map_single(adev->dev, async_desc->cpl,
@@ -532,7 +543,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ /* send flush command to terminate current transaction */
+ writel_relaxed(0x0,
-+ adev->regs + ADM_CH_FLUSH_STATE0(achan->id, adev->ee));
++ adev->regs + ADM_CH_FLUSH_STATE0(achan->id, adev->ee));
+
+ spin_unlock_irqrestore(&achan->vc.lock, flags);
+
@@ -586,7 +597,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ adev->regs + ADM_CH_CONF(achan->id));
+
+ writel(ADM_CH_RSLT_CONF_IRQ_EN | ADM_CH_RSLT_CONF_FLUSH_EN,
-+ adev->regs + ADM_CH_RSLT_CONF(achan->id, adev->ee));
++ adev->regs + ADM_CH_RSLT_CONF(achan->id, adev->ee));
+
+ achan->initialized = 1;
+ }
@@ -594,7 +605,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ /* set the crci block size if this transaction requires CRCI */
+ if (async_desc->crci) {
+ writel(async_desc->mux | async_desc->blk_size,
-+ adev->regs + ADM_CRCI_CTL(async_desc->crci, adev->ee));
++ adev->regs + ADM_CRCI_CTL(async_desc->crci, adev->ee));
+ }
+
+ /* make sure IRQ enable doesn't get reordered */
@@ -602,7 +613,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ /* write next command list out to the CMD FIFO */
+ writel(ALIGN(async_desc->dma_addr, ADM_DESC_ALIGN) >> 3,
-+ adev->regs + ADM_CH_CMD_PTR(achan->id, adev->ee));
++ adev->regs + ADM_CH_CMD_PTR(achan->id, adev->ee));
+}
+
+/**
@@ -628,7 +639,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ if (srcs & BIT(i)) {
+ status = readl_relaxed(adev->regs +
-+ ADM_CH_STATUS_SD(i, adev->ee));
++ ADM_CH_STATUS_SD(i, adev->ee));
+
+ /* if no result present, skip */
+ if (!(status & ADM_CH_STATUS_VALID))
@@ -673,7 +684,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * Return status of dma transaction
+ */
+static enum dma_status adm_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
-+ struct dma_tx_state *txstate)
++ struct dma_tx_state *txstate)
+{
+ struct adm_chan *achan = to_adm_chan(chan);
+ struct virt_dma_desc *vd;
@@ -697,7 +708,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * residue is either the full length if it is in the issued list, or 0
+ * if it is in progress. We have no reliable way of determining
+ * anything inbetween
-+ */
++ */
+ dma_set_residue(txstate, residue);
+
+ if (achan->error)
@@ -741,7 +752,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+}
+
+static void adm_channel_init(struct adm_device *adev, struct adm_chan *achan,
-+ u32 index)
++ u32 index)
+{
+ achan->id = index;
+ achan->adev = adev;
@@ -753,7 +764,6 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+static int adm_dma_probe(struct platform_device *pdev)
+{
+ struct adm_device *adev;
-+ struct resource *iores;
+ int ret;
+ u32 i;
+
@@ -763,8 +773,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ adev->dev = &pdev->dev;
+
-+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ adev->regs = devm_ioremap_resource(&pdev->dev, iores);
++ adev->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(adev->regs))
+ return PTR_ERR(adev->regs);
+
@@ -782,50 +791,44 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ if (IS_ERR(adev->core_clk))
+ return PTR_ERR(adev->core_clk);
+
-+ ret = clk_prepare_enable(adev->core_clk);
-+ if (ret) {
-+ dev_err(adev->dev, "failed to prepare/enable core clock\n");
-+ return ret;
-+ }
-+
+ adev->iface_clk = devm_clk_get(adev->dev, "iface");
-+ if (IS_ERR(adev->iface_clk)) {
-+ ret = PTR_ERR(adev->iface_clk);
-+ goto err_disable_core_clk;
-+ }
-+
-+ ret = clk_prepare_enable(adev->iface_clk);
-+ if (ret) {
-+ dev_err(adev->dev, "failed to prepare/enable iface clock\n");
-+ goto err_disable_core_clk;
-+ }
++ if (IS_ERR(adev->iface_clk))
++ return PTR_ERR(adev->iface_clk);
+
-+ adev->clk_reset = devm_reset_control_get(&pdev->dev, "clk");
++ adev->clk_reset = devm_reset_control_get_exclusive(&pdev->dev, "clk");
+ if (IS_ERR(adev->clk_reset)) {
+ dev_err(adev->dev, "failed to get ADM0 reset\n");
-+ ret = PTR_ERR(adev->clk_reset);
-+ goto err_disable_clks;
++ return PTR_ERR(adev->clk_reset);
+ }
+
-+ adev->c0_reset = devm_reset_control_get(&pdev->dev, "c0");
++ adev->c0_reset = devm_reset_control_get_exclusive(&pdev->dev, "c0");
+ if (IS_ERR(adev->c0_reset)) {
+ dev_err(adev->dev, "failed to get ADM0 C0 reset\n");
-+ ret = PTR_ERR(adev->c0_reset);
-+ goto err_disable_clks;
++ return PTR_ERR(adev->c0_reset);
+ }
+
-+ adev->c1_reset = devm_reset_control_get(&pdev->dev, "c1");
++ adev->c1_reset = devm_reset_control_get_exclusive(&pdev->dev, "c1");
+ if (IS_ERR(adev->c1_reset)) {
+ dev_err(adev->dev, "failed to get ADM0 C1 reset\n");
-+ ret = PTR_ERR(adev->c1_reset);
-+ goto err_disable_clks;
++ return PTR_ERR(adev->c1_reset);
+ }
+
-+ adev->c2_reset = devm_reset_control_get(&pdev->dev, "c2");
++ adev->c2_reset = devm_reset_control_get_exclusive(&pdev->dev, "c2");
+ if (IS_ERR(adev->c2_reset)) {
+ dev_err(adev->dev, "failed to get ADM0 C2 reset\n");
-+ ret = PTR_ERR(adev->c2_reset);
-+ goto err_disable_clks;
++ return PTR_ERR(adev->c2_reset);
++ }
++
++ ret = clk_prepare_enable(adev->core_clk);
++ if (ret) {
++ dev_err(adev->dev, "failed to prepare/enable core clock\n");
++ return ret;
++ }
++
++ ret = clk_prepare_enable(adev->iface_clk);
++ if (ret) {
++ dev_err(adev->dev, "failed to prepare/enable iface clock\n");
++ goto err_disable_core_clk;
+ }
+
+ reset_control_assert(adev->clk_reset);
@@ -833,13 +836,15 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ reset_control_assert(adev->c1_reset);
+ reset_control_assert(adev->c2_reset);
+
++ udelay(2);
++
+ reset_control_deassert(adev->clk_reset);
+ reset_control_deassert(adev->c0_reset);
+ reset_control_deassert(adev->c1_reset);
+ reset_control_deassert(adev->c2_reset);
+
+ adev->channels = devm_kcalloc(adev->dev, ADM_MAX_CHANNELS,
-+ sizeof(*adev->channels), GFP_KERNEL);
++ sizeof(*adev->channels), GFP_KERNEL);
+
+ if (!adev->channels) {
+ ret = -ENOMEM;
@@ -859,16 +864,16 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ /* configure client interfaces */
+ writel(ADM_CI_RANGE_START(0x40) | ADM_CI_RANGE_END(0xb0) |
-+ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(0));
++ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(0));
+ writel(ADM_CI_RANGE_START(0x2a) | ADM_CI_RANGE_END(0x2c) |
-+ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(1));
++ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(1));
+ writel(ADM_CI_RANGE_START(0x12) | ADM_CI_RANGE_END(0x28) |
-+ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(2));
++ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(2));
+ writel(ADM_GP_CTL_LP_EN | ADM_GP_CTL_LP_CNT(0xf),
-+ adev->regs + ADM_GP_CTL);
++ adev->regs + ADM_GP_CTL);
+
+ ret = devm_request_irq(adev->dev, adev->irq, adm_dma_irq,
-+ 0, "adm_dma", adev);
++ 0, "adm_dma", adev);
+ if (ret)
+ goto err_disable_clks;
+
@@ -933,6 +938,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ /* mask IRQs for this channel/EE pair */
+ writel(0, adev->regs + ADM_CH_RSLT_CONF(achan->id, adev->ee));
+
++ tasklet_kill(&adev->channels[i].vc.task);
+ adm_terminate_all(&adev->channels[i].vc.chan);
+ }
+
@@ -964,3 +970,6 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
+MODULE_DESCRIPTION("QCOM ADM DMA engine driver");
+MODULE_LICENSE("GPL v2");
+--
+cgit 1.2.3-1.el7
+
diff --git a/target/linux/ipq806x/patches-5.10/101-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch b/target/linux/ipq806x/patches-5.10/101-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch
new file mode 100644
index 0000000000..7aec4fcc83
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.10/101-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch
@@ -0,0 +1,227 @@
+From 803eb124e1a64e42888542c3444bfe6dac412c7f Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Mon, 4 Jan 2021 09:41:35 +0530
+Subject: mtd: parsers: Add Qcom SMEM parser
+
+NAND based Qualcomm platforms have the partition table populated in the
+Shared Memory (SMEM). Hence, add a parser for parsing the partitions
+from it.
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20210104041137.113075-3-manivannan.sadhasivam@linaro.org
+---
+ drivers/mtd/parsers/Kconfig | 8 ++
+ drivers/mtd/parsers/Makefile | 1 +
+ drivers/mtd/parsers/qcomsmempart.c | 170 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 179 insertions(+)
+ create mode 100644 drivers/mtd/parsers/qcomsmempart.c
+
+diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig
+index e72354322f628..d90c302290522 100644
+--- a/drivers/mtd/parsers/Kconfig
++++ b/drivers/mtd/parsers/Kconfig
+@@ -160,6 +160,14 @@ config MTD_REDBOOT_PARTS_READONLY
+ 'FIS directory' images, enable this option.
+
+ endif # MTD_REDBOOT_PARTS
++
++config MTD_QCOMSMEM_PARTS
++ tristate "Qualcomm SMEM NAND flash partition parser"
++ depends on MTD_NAND_QCOM || COMPILE_TEST
++ depends on QCOM_SMEM
++ help
++ This provides support for parsing partitions from Shared Memory (SMEM)
++ for NAND flash on Qualcomm platforms.
+
+ config MTD_ROUTERBOOT_PARTS
+ tristate "RouterBoot flash partition parser"
+diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile
+index b0c5f62f9e858..50eb0b0a22105 100644
+--- a/drivers/mtd/parsers/Makefile
++++ b/drivers/mtd/parsers/Makefile
+@@ -9,4 +9,5 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
+ obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
+ obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
+ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
++obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o
+ obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o
+diff --git a/drivers/mtd/parsers/qcomsmempart.c b/drivers/mtd/parsers/qcomsmempart.c
+new file mode 100644
+index 0000000000000..808cb33d71f8e
+--- /dev/null
++++ b/drivers/mtd/parsers/qcomsmempart.c
+@@ -0,0 +1,170 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm SMEM NAND flash partition parser
++ *
++ * Copyright (C) 2020, Linaro Ltd.
++ */
++
++#include <linux/ctype.h>
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/slab.h>
++#include <linux/soc/qcom/smem.h>
++
++#define SMEM_AARM_PARTITION_TABLE 9
++#define SMEM_APPS 0
++
++#define SMEM_FLASH_PART_MAGIC1 0x55ee73aa
++#define SMEM_FLASH_PART_MAGIC2 0xe35ebddb
++#define SMEM_FLASH_PTABLE_V3 3
++#define SMEM_FLASH_PTABLE_V4 4
++#define SMEM_FLASH_PTABLE_MAX_PARTS_V3 16
++#define SMEM_FLASH_PTABLE_MAX_PARTS_V4 48
++#define SMEM_FLASH_PTABLE_HDR_LEN (4 * sizeof(u32))
++#define SMEM_FLASH_PTABLE_NAME_SIZE 16
++
++/**
++ * struct smem_flash_pentry - SMEM Flash partition entry
++ * @name: Name of the partition
++ * @offset: Offset in blocks
++ * @length: Length of the partition in blocks
++ * @attr: Flags for this partition
++ */
++struct smem_flash_pentry {
++ char name[SMEM_FLASH_PTABLE_NAME_SIZE];
++ __le32 offset;
++ __le32 length;
++ u8 attr;
++} __packed __aligned(4);
++
++/**
++ * struct smem_flash_ptable - SMEM Flash partition table
++ * @magic1: Partition table Magic 1
++ * @magic2: Partition table Magic 2
++ * @version: Partition table version
++ * @numparts: Number of partitions in this ptable
++ * @pentry: Flash partition entries belonging to this ptable
++ */
++struct smem_flash_ptable {
++ __le32 magic1;
++ __le32 magic2;
++ __le32 version;
++ __le32 numparts;
++ struct smem_flash_pentry pentry[SMEM_FLASH_PTABLE_MAX_PARTS_V4];
++} __packed __aligned(4);
++
++static int parse_qcomsmem_part(struct mtd_info *mtd,
++ const struct mtd_partition **pparts,
++ struct mtd_part_parser_data *data)
++{
++ struct smem_flash_pentry *pentry;
++ struct smem_flash_ptable *ptable;
++ size_t len = SMEM_FLASH_PTABLE_HDR_LEN;
++ struct mtd_partition *parts;
++ int ret, i, numparts;
++ char *name, *c;
++
++ pr_debug("Parsing partition table info from SMEM\n");
++ ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len);
++ if (IS_ERR(ptable)) {
++ pr_err("Error reading partition table header\n");
++ return PTR_ERR(ptable);
++ }
++
++ /* Verify ptable magic */
++ if (le32_to_cpu(ptable->magic1) != SMEM_FLASH_PART_MAGIC1 ||
++ le32_to_cpu(ptable->magic2) != SMEM_FLASH_PART_MAGIC2) {
++ pr_err("Partition table magic verification failed\n");
++ return -EINVAL;
++ }
++
++ /* Ensure that # of partitions is less than the max we have allocated */
++ numparts = le32_to_cpu(ptable->numparts);
++ if (numparts > SMEM_FLASH_PTABLE_MAX_PARTS_V4) {
++ pr_err("Partition numbers exceed the max limit\n");
++ return -EINVAL;
++ }
++
++ /* Find out length of partition data based on table version */
++ if (le32_to_cpu(ptable->version) <= SMEM_FLASH_PTABLE_V3) {
++ len = SMEM_FLASH_PTABLE_HDR_LEN + SMEM_FLASH_PTABLE_MAX_PARTS_V3 *
++ sizeof(struct smem_flash_pentry);
++ } else if (le32_to_cpu(ptable->version) == SMEM_FLASH_PTABLE_V4) {
++ len = SMEM_FLASH_PTABLE_HDR_LEN + SMEM_FLASH_PTABLE_MAX_PARTS_V4 *
++ sizeof(struct smem_flash_pentry);
++ } else {
++ pr_err("Unknown ptable version (%d)", le32_to_cpu(ptable->version));
++ return -EINVAL;
++ }
++
++ /*
++ * Now that the partition table header has been parsed, verified
++ * and the length of the partition table calculated, read the
++ * complete partition table
++ */
++ ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len);
++ if (IS_ERR_OR_NULL(ptable)) {
++ pr_err("Error reading partition table\n");
++ return PTR_ERR(ptable);
++ }
++
++ parts = kcalloc(numparts, sizeof(*parts), GFP_KERNEL);
++ if (!parts)
++ return -ENOMEM;
++
++ for (i = 0; i < numparts; i++) {
++ pentry = &ptable->pentry[i];
++ if (pentry->name[0] == '\0')
++ continue;
++
++ name = kstrdup(pentry->name, GFP_KERNEL);
++ if (!name) {
++ ret = -ENOMEM;
++ goto out_free_parts;
++ }
++
++ /* Convert name to lower case */
++ for (c = name; *c != '\0'; c++)
++ *c = tolower(*c);
++
++ parts[i].name = name;
++ parts[i].offset = le32_to_cpu(pentry->offset) * mtd->erasesize;
++ parts[i].mask_flags = pentry->attr;
++ parts[i].size = le32_to_cpu(pentry->length) * mtd->erasesize;
++ pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n",
++ i, pentry->name, le32_to_cpu(pentry->offset),
++ le32_to_cpu(pentry->length), pentry->attr);
++ }
++
++ pr_debug("SMEM partition table found: ver: %d len: %d\n",
++ le32_to_cpu(ptable->version), numparts);
++ *pparts = parts;
++
++ return numparts;
++
++out_free_parts:
++ while (--i >= 0)
++ kfree(parts[i].name);
++ kfree(parts);
++ *pparts = NULL;
++
++ return ret;
++}
++
++static const struct of_device_id qcomsmem_of_match_table[] = {
++ { .compatible = "qcom,smem-part" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, qcomsmem_of_match_table);
++
++static struct mtd_part_parser mtd_parser_qcomsmem = {
++ .parse_fn = parse_qcomsmem_part,
++ .name = "qcomsmem",
++ .of_match_table = qcomsmem_of_match_table,
++};
++module_mtd_part_parser(mtd_parser_qcomsmem);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
++MODULE_DESCRIPTION("Qualcomm SMEM NAND flash partition parser");
+--
+cgit 1.2.3-1.el7
+
diff --git a/target/linux/ipq806x/patches-5.10/102-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch b/target/linux/ipq806x/patches-5.10/102-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch
new file mode 100644
index 0000000000..47f3bfba8d
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.10/102-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch
@@ -0,0 +1,24 @@
+From 5001f2e1a325b68dbf225bd17f69a4d3d975cca5 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 9 Mar 2017 09:31:44 +0100
+Subject: [PATCH 61/69] mtd: "rootfs" conflicts with OpenWrt auto mounting
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/mtd/parsers/qcomsmempart.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/mtd/parsers/qcomsmempart.c
++++ b/drivers/mtd/parsers/qcomsmempart.c
+@@ -189,6 +189,11 @@ static int parse_qcomsmem_part(st
+ parts[i].offset = le32_to_cpu(pentry->offset) * mtd->erasesize;
+ parts[i].mask_flags = pentry->attr;
+ parts[i].size = le32_to_cpu(pentry->length) * mtd->erasesize;
++
++ /* "rootfs" conflicts with OpenWrt auto mounting */
++ if (mtd_type_is_nand(mtd) && !strcmp(name, "rootfs"))
++ parts[i].name = "ubi";
++
+ pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n",
+ i, pentry->name, le32_to_cpu(pentry->offset),
+ le32_to_cpu(pentry->length), pentry->attr);
diff --git a/target/linux/ipq806x/patches-5.4/0031-mtd-add-SMEM-parser-for-QCOM-platforms.patch b/target/linux/ipq806x/patches-5.4/0031-mtd-add-SMEM-parser-for-QCOM-platforms.patch
deleted file mode 100644
index 6b7119b8e0..0000000000
--- a/target/linux/ipq806x/patches-5.4/0031-mtd-add-SMEM-parser-for-QCOM-platforms.patch
+++ /dev/null
@@ -1,282 +0,0 @@
-From d8eeb4de90e968ba32d956728c866f20752cf2c3 Mon Sep 17 00:00:00 2001
-From: Mathieu Olivari <mathieu@codeaurora.org>
-Date: Thu, 9 Mar 2017 08:18:08 +0100
-Subject: [PATCH 31/69] mtd: add SMEM parser for QCOM platforms
-
-On QCOM platforms using MTD devices storage (such as IPQ806x), SMEM is
-used to store partition layout. This new parser can now be used to read
-SMEM and use it to register an MTD layout according to its content.
-
-Signed-off-by: Mathieu Olivari <mathieu@codeaurora.org>
-Signed-off-by: Ram Chandra Jangir <rjangi@codeaurora.org>
----
- drivers/mtd/parsers/Kconfig | 7 ++
- drivers/mtd/parsers/Makefile | 1 +
- drivers/mtd/parsers/qcom_smem_part.c | 228 +++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 236 insertions(+)
- create mode 100644 drivers/mtd/parsers/qcom_smem_part.c
-
---- a/drivers/mtd/parsers/Kconfig
-+++ b/drivers/mtd/parsers/Kconfig
-@@ -138,6 +138,13 @@ config MTD_PARSER_TRX
- This driver will parse TRX header and report at least two partitions:
- kernel and rootfs.
-
-+config MTD_QCOM_SMEM_PARTS
-+ tristate "QCOM SMEM partitioning support"
-+ depends on QCOM_SMEM
-+ help
-+ This provides partitions parser for QCOM devices using SMEM
-+ such as IPQ806x.
-+
- config MTD_SHARPSL_PARTS
- tristate "Sharp SL Series NAND flash partition parser"
- depends on MTD_NAND_SHARPSL || MTD_NAND_TMIO || COMPILE_TEST
---- a/drivers/mtd/parsers/Makefile
-+++ b/drivers/mtd/parsers/Makefile
-@@ -11,6 +11,7 @@ ofpart-$(CONFIG_MTD_OF_PARTS_LINKSYS_NS)
- obj-$(CONFIG_MTD_PARSER_IMAGETAG) += parser_imagetag.o
- obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
- obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
-+obj-$(CONFIG_MTD_QCOM_SMEM_PARTS) += qcom_smem_part.o
- obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
- obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
- obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o
---- /dev/null
-+++ b/drivers/mtd/parsers/qcom_smem_part.c
-@@ -0,0 +1,235 @@
-+/*
-+ * Copyright (c) 2015, The Linux Foundation. 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 version 2 and
-+ * only 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.
-+ */
-+
-+#include <linux/kernel.h>
-+#include <linux/device.h>
-+#include <linux/slab.h>
-+
-+#include <linux/mtd/mtd.h>
-+#include <linux/mtd/partitions.h>
-+#include <linux/spi/spi.h>
-+#include <linux/module.h>
-+
-+#include <linux/soc/qcom/smem.h>
-+
-+/* Processor/host identifier for the application processor */
-+#define SMEM_HOST_APPS 0
-+
-+/* SMEM items index */
-+#define SMEM_AARM_PARTITION_TABLE 9
-+#define SMEM_BOOT_FLASH_TYPE 421
-+#define SMEM_BOOT_FLASH_BLOCK_SIZE 424
-+
-+/* SMEM Flash types */
-+#define SMEM_FLASH_NAND 2
-+#define SMEM_FLASH_SPI 6
-+
-+#define SMEM_PART_NAME_SZ 16
-+#define SMEM_PARTS_MAX 32
-+
-+struct smem_partition {
-+ char name[SMEM_PART_NAME_SZ];
-+ __le32 start;
-+ __le32 size;
-+ __le32 attr;
-+};
-+
-+struct smem_partition_table {
-+ u8 magic[8];
-+ __le32 version;
-+ __le32 len;
-+ struct smem_partition parts[SMEM_PARTS_MAX];
-+};
-+
-+/* SMEM Magic values in partition table */
-+static const u8 SMEM_PTABLE_MAGIC[] = {
-+ 0xaa, 0x73, 0xee, 0x55,
-+ 0xdb, 0xbd, 0x5e, 0xe3,
-+};
-+
-+static int qcom_smem_get_flash_blksz(u64 **smem_blksz)
-+{
-+ size_t size;
-+
-+ *smem_blksz = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_BLOCK_SIZE,
-+ &size);
-+
-+ if (IS_ERR(*smem_blksz)) {
-+ pr_err("Unable to read flash blksz from SMEM\n");
-+ return -ENOENT;
-+ }
-+
-+ if (size != sizeof(**smem_blksz)) {
-+ pr_err("Invalid flash blksz size in SMEM\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int qcom_smem_get_flash_type(u64 **smem_flash_type)
-+{
-+ size_t size;
-+
-+ *smem_flash_type = qcom_smem_get(SMEM_HOST_APPS, SMEM_BOOT_FLASH_TYPE,
-+ &size);
-+
-+ if (IS_ERR(*smem_flash_type)) {
-+ pr_err("Unable to read flash type from SMEM\n");
-+ return -ENOENT;
-+ }
-+
-+ if (size != sizeof(**smem_flash_type)) {
-+ pr_err("Invalid flash type size in SMEM\n");
-+ return -EINVAL;
-+ }
-+
-+ return 0;
-+}
-+
-+static int qcom_smem_get_flash_partitions(struct smem_partition_table **pparts)
-+{
-+ size_t size;
-+
-+ *pparts = qcom_smem_get(SMEM_HOST_APPS, SMEM_AARM_PARTITION_TABLE,
-+ &size);
-+
-+ if (IS_ERR(*pparts)) {
-+ pr_err("Unable to read partition table from SMEM\n");
-+ return -ENOENT;
-+ }
-+
-+ return 0;
-+}
-+
-+static int of_dev_node_match(struct device *dev, const void *data)
-+{
-+ return dev->of_node == data;
-+}
-+
-+static bool is_spi_device(struct device_node *np)
-+{
-+ struct device *dev;
-+
-+ dev = bus_find_device(&spi_bus_type, NULL, np, of_dev_node_match);
-+ if (!dev)
-+ return false;
-+
-+ put_device(dev);
-+ return true;
-+}
-+
-+static int parse_qcom_smem_partitions(struct mtd_info *master,
-+ const struct mtd_partition **pparts,
-+ struct mtd_part_parser_data *data)
-+{
-+ struct smem_partition_table *smem_parts;
-+ u64 *smem_flash_type, *smem_blksz;
-+ struct mtd_partition *mtd_parts;
-+ struct device_node *of_node = master->dev.of_node;
-+ int i, ret;
-+
-+ /*
-+ * SMEM will only store the partition table of the boot device.
-+ * If this is not the boot device, do not return any partition.
-+ */
-+ ret = qcom_smem_get_flash_type(&smem_flash_type);
-+ if (ret < 0)
-+ return ret;
-+
-+ if ((*smem_flash_type == SMEM_FLASH_NAND && !mtd_type_is_nand(master))
-+ || (*smem_flash_type == SMEM_FLASH_SPI && !is_spi_device(of_node)))
-+ return 0;
-+
-+ /*
-+ * Just for sanity purpose, make sure the block size in SMEM matches the
-+ * block size of the MTD device
-+ */
-+ ret = qcom_smem_get_flash_blksz(&smem_blksz);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (*smem_blksz != master->erasesize) {
-+ pr_err("SMEM block size differs from MTD block size\n");
-+ return -EINVAL;
-+ }
-+
-+ /* Get partition pointer from SMEM */
-+ ret = qcom_smem_get_flash_partitions(&smem_parts);
-+ if (ret < 0)
-+ return ret;
-+
-+ if (memcmp(SMEM_PTABLE_MAGIC, smem_parts->magic,
-+ sizeof(SMEM_PTABLE_MAGIC))) {
-+ pr_err("SMEM partition magic invalid\n");
-+ return -EINVAL;
-+ }
-+
-+ /* Allocate and populate the mtd structures */
-+ mtd_parts = kcalloc(le32_to_cpu(smem_parts->len), sizeof(*mtd_parts),
-+ GFP_KERNEL);
-+ if (!mtd_parts)
-+ return -ENOMEM;
-+
-+ for (i = 0; i < smem_parts->len; i++) {
-+ struct smem_partition *s_part = &smem_parts->parts[i];
-+ struct mtd_partition *m_part = &mtd_parts[i];
-+
-+ m_part->name = s_part->name;
-+ m_part->size = le32_to_cpu(s_part->size) * (*smem_blksz);
-+ m_part->offset = le32_to_cpu(s_part->start) * (*smem_blksz);
-+
-+ /*
-+ * The last SMEM partition may have its size marked as
-+ * something like 0xffffffff, which means "until the end of the
-+ * flash device". In this case, truncate it.
-+ */
-+ if (m_part->offset + m_part->size > master->size)
-+ m_part->size = master->size - m_part->offset;
-+ }
-+
-+ *pparts = mtd_parts;
-+
-+ return smem_parts->len;
-+}
-+
-+static const struct of_device_id qcom_smem_of_match_table[] = {
-+ { .compatible = "qcom,smem" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, qcom_smem_of_match_table);
-+
-+static struct mtd_part_parser qcom_smem_parser = {
-+ .owner = THIS_MODULE,
-+ .parse_fn = parse_qcom_smem_partitions,
-+ .name = "qcom-smem",
-+ .of_match_table = qcom_smem_of_match_table,
-+};
-+
-+static int __init qcom_smem_parser_init(void)
-+{
-+ register_mtd_parser(&qcom_smem_parser);
-+ return 0;
-+}
-+
-+static void __exit qcom_smem_parser_exit(void)
-+{
-+ deregister_mtd_parser(&qcom_smem_parser);
-+}
-+
-+module_init(qcom_smem_parser_init);
-+module_exit(qcom_smem_parser_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Mathieu Olivari <mathieu@codeaurora.org>");
-+MODULE_DESCRIPTION("Parsing code for SMEM based partition tables");
diff --git a/target/linux/ipq806x/patches-5.4/0061-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch b/target/linux/ipq806x/patches-5.4/0061-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch
deleted file mode 100644
index ff6f6edf49..0000000000
--- a/target/linux/ipq806x/patches-5.4/0061-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From 5001f2e1a325b68dbf225bd17f69a4d3d975cca5 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-Date: Thu, 9 Mar 2017 09:31:44 +0100
-Subject: [PATCH 61/69] mtd: "rootfs" conflicts with OpenWrt auto mounting
-
-Signed-off-by: John Crispin <john@phrozen.org>
----
- drivers/mtd/parsers/qcom_smem_part.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/mtd/parsers/qcom_smem_part.c
-+++ b/drivers/mtd/parsers/qcom_smem_part.c
-@@ -189,6 +189,10 @@ static int parse_qcom_smem_partitions(st
- m_part->size = le32_to_cpu(s_part->size) * (*smem_blksz);
- m_part->offset = le32_to_cpu(s_part->start) * (*smem_blksz);
-
-+ /* "rootfs" conflicts with OpenWrt auto mounting */
-+ if (mtd_type_is_nand(master) && !strcmp(m_part->name, "rootfs"))
-+ m_part->name = "ubi";
-+
- /*
- * The last SMEM partition may have its size marked as
- * something like 0xffffffff, which means "until the end of the
diff --git a/target/linux/ipq806x/patches-5.4/0002-dmaengine-Add-ADM-driver.patch b/target/linux/ipq806x/patches-5.4/100-v5.11-dmaengine-qcom-add_ADM_driver.patch
index aa7d2e791e..45062d52fc 100644
--- a/target/linux/ipq806x/patches-5.4/0002-dmaengine-Add-ADM-driver.patch
+++ b/target/linux/ipq806x/patches-5.4/100-v5.11-dmaengine-qcom-add_ADM_driver.patch
@@ -1,86 +1,95 @@
-From 563fa24db4e529c5a3311928d73a8a90531ee527 Mon Sep 17 00:00:00 2001
-From: Thomas Pedersen <twp@codeaurora.org>
-Date: Mon, 16 May 2016 17:58:51 -0700
-Subject: [PATCH 02/69] dmaengine: Add ADM driver
-
-Original patch by Andy Gross.
+From 5c9f8c2dbdbe53818bcde6aa6695e1331e5f841f Mon Sep 17 00:00:00 2001
+From: Jonathan McDowell <noodles@earth.li>
+Date: Sat, 14 Nov 2020 14:02:33 +0000
+Subject: dmaengine: qcom: Add ADM driver
Add the DMA engine driver for the QCOM Application Data Mover (ADM) DMA
controller found in the MSM8x60 and IPQ/APQ8064 platforms.
The ADM supports both memory to memory transactions and memory
-to/from peripheral device transactions. The controller also provides flow
-control capabilities for transactions to/from peripheral devices.
+to/from peripheral device transactions. The controller also provides
+flow control capabilities for transactions to/from peripheral devices.
+
+The initial release of this driver supports slave transfers to/from
+peripherals and also incorporates CRCI (client rate control interface)
+flow control.
-The initial release of this driver supports slave transfers to/from peripherals
-and also incorporates CRCI (client rate control interface) flow control.
+The hardware only supports a 32 bit physical address, so specifying
+!PHYS_ADDR_T_64BIT gives maximum COMPILE_TEST coverage without having to
+spend effort on kludging things in the code that will never actually be
+needed on real hardware.
Signed-off-by: Andy Gross <agross@codeaurora.org>
Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+Signed-off-by: Jonathan McDowell <noodles@earth.li>
+Link: https://lore.kernel.org/r/20201114140233.GM32650@earth.li
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
- drivers/dma/qcom/Kconfig | 10 +
+ drivers/dma/qcom/Kconfig | 11 +
drivers/dma/qcom/Makefile | 1 +
- drivers/dma/qcom/qcom_adm.c | 900 ++++++++++++++++++++++++++++++++++++++++++++
- 3 files changed, 911 insertions(+)
+ drivers/dma/qcom/qcom_adm.c | 903 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 915 insertions(+)
create mode 100644 drivers/dma/qcom/qcom_adm.c
+diff --git a/drivers/dma/qcom/Kconfig b/drivers/dma/qcom/Kconfig
+index 3bcb689162c67..0389d60d2604a 100644
--- a/drivers/dma/qcom/Kconfig
+++ b/drivers/dma/qcom/Kconfig
-@@ -28,3 +28,13 @@ config QCOM_HIDMA
- (user to kernel, kernel to kernel, etc.). It only supports
- memcpy interface. The core is not intended for general
- purpose slave DMA.
-+
+@@ -1,4 +1,15 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+config QCOM_ADM
+ tristate "Qualcomm ADM support"
-+ depends on ARCH_QCOM || (COMPILE_TEST && OF && ARM)
++ depends on (ARCH_QCOM || COMPILE_TEST) && !PHYS_ADDR_T_64BIT
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
-+ ---help---
-+ Enable support for the Qualcomm ADM DMA controller. This controller
-+ provides DMA capabilities for both general purpose and on-chip
-+ peripheral devices.
++ help
++ Enable support for the Qualcomm Application Data Mover (ADM) DMA
++ controller, as present on MSM8x60, APQ8064, and IPQ8064 devices.
++ This controller provides DMA capabilities for both general purpose
++ and on-chip peripheral devices.
++
+ config QCOM_BAM_DMA
+ tristate "QCOM BAM DMA support"
+ depends on ARCH_QCOM || (COMPILE_TEST && OF && ARM)
+diff --git a/drivers/dma/qcom/Makefile b/drivers/dma/qcom/Makefile
+index 1ae92da88b0c9..346e643fbb6db 100644
--- a/drivers/dma/qcom/Makefile
+++ b/drivers/dma/qcom/Makefile
-@@ -4,3 +4,4 @@ obj-$(CONFIG_QCOM_HIDMA_MGMT) += hdma_mg
- hdma_mgmt-objs := hidma_mgmt.o hidma_mgmt_sys.o
- obj-$(CONFIG_QCOM_HIDMA) += hdma.o
- hdma-objs := hidma_ll.o hidma.o hidma_dbg.o
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_QCOM_ADM) += qcom_adm.o
+ obj-$(CONFIG_QCOM_BAM_DMA) += bam_dma.o
+ obj-$(CONFIG_QCOM_HIDMA_MGMT) += hdma_mgmt.o
+ hdma_mgmt-objs := hidma_mgmt.o hidma_mgmt_sys.o
+diff --git a/drivers/dma/qcom/qcom_adm.c b/drivers/dma/qcom/qcom_adm.c
+new file mode 100644
+index 0000000000000..9b6f8e050ecce
--- /dev/null
+++ b/drivers/dma/qcom/qcom_adm.c
-@@ -0,0 +1,914 @@
+@@ -0,0 +1,903 @@
++// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. 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 version 2 and
-+ * only 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.
-+ *
+ */
+
-+#include <linux/kernel.h>
-+#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/dmaengine.h>
++#include <linux/dma-mapping.h>
+#include <linux/init.h>
-+#include <linux/slab.h>
-+#include <linux/module.h>
+#include <linux/interrupt.h>
-+#include <linux/dma-mapping.h>
-+#include <linux/scatterlist.h>
-+#include <linux/device.h>
-+#include <linux/platform_device.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_dma.h>
++#include <linux/platform_device.h>
+#include <linux/reset.h>
-+#include <linux/clk.h>
-+#include <linux/dmaengine.h>
++#include <linux/scatterlist.h>
++#include <linux/slab.h>
+
+#include "../dmaengine.h"
+#include "../virt-dma.h"
@@ -90,10 +99,10 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+#define ADM_CI_MULTI 0x4
+#define ADM_CRCI_MULTI 0x4
+#define ADM_EE_MULTI 0x800
-+#define ADM_CHAN_OFFS(chan) (ADM_CHAN_MULTI * chan)
-+#define ADM_EE_OFFS(ee) (ADM_EE_MULTI * ee)
++#define ADM_CHAN_OFFS(chan) (ADM_CHAN_MULTI * (chan))
++#define ADM_EE_OFFS(ee) (ADM_EE_MULTI * (ee))
+#define ADM_CHAN_EE_OFFS(chan, ee) (ADM_CHAN_OFFS(chan) + ADM_EE_OFFS(ee))
-+#define ADM_CHAN_OFFS(chan) (ADM_CHAN_MULTI * chan)
++#define ADM_CHAN_OFFS(chan) (ADM_CHAN_MULTI * (chan))
+#define ADM_CI_OFFS(ci) (ADM_CHAN_OFF(ci))
+#define ADM_CH_CMD_PTR(chan, ee) (ADM_CHAN_EE_OFFS(chan, ee))
+#define ADM_CH_RSLT(chan, ee) (0x40 + ADM_CHAN_EE_OFFS(chan, ee))
@@ -102,62 +111,62 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+#define ADM_CH_CONF(chan) (0x240 + ADM_CHAN_OFFS(chan))
+#define ADM_CH_RSLT_CONF(chan, ee) (0x300 + ADM_CHAN_EE_OFFS(chan, ee))
+#define ADM_SEC_DOMAIN_IRQ_STATUS(ee) (0x380 + ADM_EE_OFFS(ee))
-+#define ADM_CI_CONF(ci) (0x390 + ci * ADM_CI_MULTI)
++#define ADM_CI_CONF(ci) (0x390 + (ci) * ADM_CI_MULTI)
+#define ADM_GP_CTL 0x3d8
-+#define ADM_CRCI_CTL(crci, ee) (0x400 + crci * ADM_CRCI_MULTI + \
++#define ADM_CRCI_CTL(crci, ee) (0x400 + (crci) * ADM_CRCI_MULTI + \
+ ADM_EE_OFFS(ee))
+
+/* channel status */
-+#define ADM_CH_STATUS_VALID BIT(1)
++#define ADM_CH_STATUS_VALID BIT(1)
+
+/* channel result */
-+#define ADM_CH_RSLT_VALID BIT(31)
-+#define ADM_CH_RSLT_ERR BIT(3)
-+#define ADM_CH_RSLT_FLUSH BIT(2)
-+#define ADM_CH_RSLT_TPD BIT(1)
++#define ADM_CH_RSLT_VALID BIT(31)
++#define ADM_CH_RSLT_ERR BIT(3)
++#define ADM_CH_RSLT_FLUSH BIT(2)
++#define ADM_CH_RSLT_TPD BIT(1)
+
+/* channel conf */
+#define ADM_CH_CONF_SHADOW_EN BIT(12)
+#define ADM_CH_CONF_MPU_DISABLE BIT(11)
+#define ADM_CH_CONF_PERM_MPU_CONF BIT(9)
+#define ADM_CH_CONF_FORCE_RSLT_EN BIT(7)
-+#define ADM_CH_CONF_SEC_DOMAIN(ee) (((ee & 0x3) << 4) | ((ee & 0x4) << 11))
++#define ADM_CH_CONF_SEC_DOMAIN(ee) ((((ee) & 0x3) << 4) | (((ee) & 0x4) << 11))
+
+/* channel result conf */
+#define ADM_CH_RSLT_CONF_FLUSH_EN BIT(1)
+#define ADM_CH_RSLT_CONF_IRQ_EN BIT(0)
+
+/* CRCI CTL */
-+#define ADM_CRCI_CTL_MUX_SEL BIT(18)
-+#define ADM_CRCI_CTL_RST BIT(17)
++#define ADM_CRCI_CTL_MUX_SEL BIT(18)
++#define ADM_CRCI_CTL_RST BIT(17)
+
+/* CI configuration */
-+#define ADM_CI_RANGE_END(x) (x << 24)
-+#define ADM_CI_RANGE_START(x) (x << 16)
-+#define ADM_CI_BURST_4_WORDS BIT(2)
-+#define ADM_CI_BURST_8_WORDS BIT(3)
++#define ADM_CI_RANGE_END(x) ((x) << 24)
++#define ADM_CI_RANGE_START(x) ((x) << 16)
++#define ADM_CI_BURST_4_WORDS BIT(2)
++#define ADM_CI_BURST_8_WORDS BIT(3)
+
+/* GP CTL */
-+#define ADM_GP_CTL_LP_EN BIT(12)
-+#define ADM_GP_CTL_LP_CNT(x) (x << 8)
++#define ADM_GP_CTL_LP_EN BIT(12)
++#define ADM_GP_CTL_LP_CNT(x) ((x) << 8)
+
+/* Command pointer list entry */
-+#define ADM_CPLE_LP BIT(31)
-+#define ADM_CPLE_CMD_PTR_LIST BIT(29)
++#define ADM_CPLE_LP BIT(31)
++#define ADM_CPLE_CMD_PTR_LIST BIT(29)
+
+/* Command list entry */
-+#define ADM_CMD_LC BIT(31)
-+#define ADM_CMD_DST_CRCI(n) (((n) & 0xf) << 7)
-+#define ADM_CMD_SRC_CRCI(n) (((n) & 0xf) << 3)
++#define ADM_CMD_LC BIT(31)
++#define ADM_CMD_DST_CRCI(n) (((n) & 0xf) << 7)
++#define ADM_CMD_SRC_CRCI(n) (((n) & 0xf) << 3)
+
-+#define ADM_CMD_TYPE_SINGLE 0x0
-+#define ADM_CMD_TYPE_BOX 0x3
++#define ADM_CMD_TYPE_SINGLE 0x0
++#define ADM_CMD_TYPE_BOX 0x3
+
-+#define ADM_CRCI_MUX_SEL BIT(4)
-+#define ADM_DESC_ALIGN 8
-+#define ADM_MAX_XFER (SZ_64K-1)
-+#define ADM_MAX_ROWS (SZ_64K-1)
-+#define ADM_MAX_CHANNELS 16
++#define ADM_CRCI_MUX_SEL BIT(4)
++#define ADM_DESC_ALIGN 8
++#define ADM_MAX_XFER (SZ_64K - 1)
++#define ADM_MAX_ROWS (SZ_64K - 1)
++#define ADM_MAX_CHANNELS 16
+
+struct adm_desc_hw_box {
+ u32 cmd;
@@ -255,7 +264,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ case 32:
+ case 64:
+ case 128:
-+ ret = ffs(burst>>4) - 1;
++ ret = ffs(burst >> 4) - 1;
+ break;
+ case 192:
+ ret = 4;
@@ -281,9 +290,10 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * @burst: Burst size of transaction
+ * @direction: DMA transfer direction
+ */
-+static void *adm_process_fc_descriptors(struct adm_chan *achan,
-+ void *desc, struct scatterlist *sg, u32 crci, u32 burst,
-+ enum dma_transfer_direction direction)
++static void *adm_process_fc_descriptors(struct adm_chan *achan, void *desc,
++ struct scatterlist *sg, u32 crci,
++ u32 burst,
++ enum dma_transfer_direction direction)
+{
+ struct adm_desc_hw_box *box_desc = NULL;
+ struct adm_desc_hw_single *single_desc;
@@ -349,9 +359,9 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * @sg: Scatterlist entry
+ * @direction: DMA transfer direction
+ */
-+static void *adm_process_non_fc_descriptors(struct adm_chan *achan,
-+ void *desc, struct scatterlist *sg,
-+ enum dma_transfer_direction direction)
++static void *adm_process_non_fc_descriptors(struct adm_chan *achan, void *desc,
++ struct scatterlist *sg,
++ enum dma_transfer_direction direction)
+{
+ struct adm_desc_hw_single *single_desc;
+ u32 remainder = sg_dma_len(sg);
@@ -398,9 +408,11 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * @context: transfer context (unused)
+ */
+static struct dma_async_tx_descriptor *adm_prep_slave_sg(struct dma_chan *chan,
-+ struct scatterlist *sgl, unsigned int sg_len,
-+ enum dma_transfer_direction direction, unsigned long flags,
-+ void *context)
++ struct scatterlist *sgl,
++ unsigned int sg_len,
++ enum dma_transfer_direction direction,
++ unsigned long flags,
++ void *context)
+{
+ struct adm_chan *achan = to_adm_chan(chan);
+ struct adm_device *adev = achan->adev;
@@ -427,7 +439,6 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ /* if using flow control, validate burst and crci values */
+ if (achan->slave.device_fc) {
-+
+ blk_size = adm_get_blksize(burst);
+ if (blk_size < 0) {
+ dev_err(adev->dev, "invalid burst value: %d\n",
@@ -455,7 +466,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ }
+ }
+
-+ async_desc = kzalloc(sizeof(*async_desc), GFP_ATOMIC);
++ async_desc = kzalloc(sizeof(*async_desc), GFP_NOWAIT);
+ if (!async_desc)
+ return ERR_PTR(-ENOMEM);
+
@@ -468,7 +479,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ box_count * sizeof(struct adm_desc_hw_box) +
+ sizeof(*cple) + 2 * ADM_DESC_ALIGN;
+
-+ async_desc->cpl = kzalloc(async_desc->dma_len, GFP_ATOMIC);
++ async_desc->cpl = kzalloc(async_desc->dma_len, GFP_NOWAIT);
+ if (!async_desc->cpl)
+ goto free;
+
@@ -483,10 +494,10 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ if (achan->slave.device_fc)
+ desc = adm_process_fc_descriptors(achan, desc, sg, crci,
-+ burst, direction);
++ burst, direction);
+ else
+ desc = adm_process_non_fc_descriptors(achan, desc, sg,
-+ direction);
++ direction);
+ }
+
+ async_desc->dma_addr = dma_map_single(adev->dev, async_desc->cpl,
@@ -532,7 +543,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ /* send flush command to terminate current transaction */
+ writel_relaxed(0x0,
-+ adev->regs + ADM_CH_FLUSH_STATE0(achan->id, adev->ee));
++ adev->regs + ADM_CH_FLUSH_STATE0(achan->id, adev->ee));
+
+ spin_unlock_irqrestore(&achan->vc.lock, flags);
+
@@ -586,7 +597,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ adev->regs + ADM_CH_CONF(achan->id));
+
+ writel(ADM_CH_RSLT_CONF_IRQ_EN | ADM_CH_RSLT_CONF_FLUSH_EN,
-+ adev->regs + ADM_CH_RSLT_CONF(achan->id, adev->ee));
++ adev->regs + ADM_CH_RSLT_CONF(achan->id, adev->ee));
+
+ achan->initialized = 1;
+ }
@@ -594,7 +605,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ /* set the crci block size if this transaction requires CRCI */
+ if (async_desc->crci) {
+ writel(async_desc->mux | async_desc->blk_size,
-+ adev->regs + ADM_CRCI_CTL(async_desc->crci, adev->ee));
++ adev->regs + ADM_CRCI_CTL(async_desc->crci, adev->ee));
+ }
+
+ /* make sure IRQ enable doesn't get reordered */
@@ -602,7 +613,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ /* write next command list out to the CMD FIFO */
+ writel(ALIGN(async_desc->dma_addr, ADM_DESC_ALIGN) >> 3,
-+ adev->regs + ADM_CH_CMD_PTR(achan->id, adev->ee));
++ adev->regs + ADM_CH_CMD_PTR(achan->id, adev->ee));
+}
+
+/**
@@ -628,7 +639,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ if (srcs & BIT(i)) {
+ status = readl_relaxed(adev->regs +
-+ ADM_CH_STATUS_SD(i, adev->ee));
++ ADM_CH_STATUS_SD(i, adev->ee));
+
+ /* if no result present, skip */
+ if (!(status & ADM_CH_STATUS_VALID))
@@ -673,7 +684,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * Return status of dma transaction
+ */
+static enum dma_status adm_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
-+ struct dma_tx_state *txstate)
++ struct dma_tx_state *txstate)
+{
+ struct adm_chan *achan = to_adm_chan(chan);
+ struct virt_dma_desc *vd;
@@ -697,7 +708,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ * residue is either the full length if it is in the issued list, or 0
+ * if it is in progress. We have no reliable way of determining
+ * anything inbetween
-+ */
++ */
+ dma_set_residue(txstate, residue);
+
+ if (achan->error)
@@ -741,7 +752,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+}
+
+static void adm_channel_init(struct adm_device *adev, struct adm_chan *achan,
-+ u32 index)
++ u32 index)
+{
+ achan->id = index;
+ achan->adev = adev;
@@ -753,7 +764,6 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+static int adm_dma_probe(struct platform_device *pdev)
+{
+ struct adm_device *adev;
-+ struct resource *iores;
+ int ret;
+ u32 i;
+
@@ -763,8 +773,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ adev->dev = &pdev->dev;
+
-+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ adev->regs = devm_ioremap_resource(&pdev->dev, iores);
++ adev->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(adev->regs))
+ return PTR_ERR(adev->regs);
+
@@ -782,50 +791,44 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ if (IS_ERR(adev->core_clk))
+ return PTR_ERR(adev->core_clk);
+
-+ ret = clk_prepare_enable(adev->core_clk);
-+ if (ret) {
-+ dev_err(adev->dev, "failed to prepare/enable core clock\n");
-+ return ret;
-+ }
-+
+ adev->iface_clk = devm_clk_get(adev->dev, "iface");
-+ if (IS_ERR(adev->iface_clk)) {
-+ ret = PTR_ERR(adev->iface_clk);
-+ goto err_disable_core_clk;
-+ }
-+
-+ ret = clk_prepare_enable(adev->iface_clk);
-+ if (ret) {
-+ dev_err(adev->dev, "failed to prepare/enable iface clock\n");
-+ goto err_disable_core_clk;
-+ }
++ if (IS_ERR(adev->iface_clk))
++ return PTR_ERR(adev->iface_clk);
+
-+ adev->clk_reset = devm_reset_control_get(&pdev->dev, "clk");
++ adev->clk_reset = devm_reset_control_get_exclusive(&pdev->dev, "clk");
+ if (IS_ERR(adev->clk_reset)) {
+ dev_err(adev->dev, "failed to get ADM0 reset\n");
-+ ret = PTR_ERR(adev->clk_reset);
-+ goto err_disable_clks;
++ return PTR_ERR(adev->clk_reset);
+ }
+
-+ adev->c0_reset = devm_reset_control_get(&pdev->dev, "c0");
++ adev->c0_reset = devm_reset_control_get_exclusive(&pdev->dev, "c0");
+ if (IS_ERR(adev->c0_reset)) {
+ dev_err(adev->dev, "failed to get ADM0 C0 reset\n");
-+ ret = PTR_ERR(adev->c0_reset);
-+ goto err_disable_clks;
++ return PTR_ERR(adev->c0_reset);
+ }
+
-+ adev->c1_reset = devm_reset_control_get(&pdev->dev, "c1");
++ adev->c1_reset = devm_reset_control_get_exclusive(&pdev->dev, "c1");
+ if (IS_ERR(adev->c1_reset)) {
+ dev_err(adev->dev, "failed to get ADM0 C1 reset\n");
-+ ret = PTR_ERR(adev->c1_reset);
-+ goto err_disable_clks;
++ return PTR_ERR(adev->c1_reset);
+ }
+
-+ adev->c2_reset = devm_reset_control_get(&pdev->dev, "c2");
++ adev->c2_reset = devm_reset_control_get_exclusive(&pdev->dev, "c2");
+ if (IS_ERR(adev->c2_reset)) {
+ dev_err(adev->dev, "failed to get ADM0 C2 reset\n");
-+ ret = PTR_ERR(adev->c2_reset);
-+ goto err_disable_clks;
++ return PTR_ERR(adev->c2_reset);
++ }
++
++ ret = clk_prepare_enable(adev->core_clk);
++ if (ret) {
++ dev_err(adev->dev, "failed to prepare/enable core clock\n");
++ return ret;
++ }
++
++ ret = clk_prepare_enable(adev->iface_clk);
++ if (ret) {
++ dev_err(adev->dev, "failed to prepare/enable iface clock\n");
++ goto err_disable_core_clk;
+ }
+
+ reset_control_assert(adev->clk_reset);
@@ -833,13 +836,15 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ reset_control_assert(adev->c1_reset);
+ reset_control_assert(adev->c2_reset);
+
++ udelay(2);
++
+ reset_control_deassert(adev->clk_reset);
+ reset_control_deassert(adev->c0_reset);
+ reset_control_deassert(adev->c1_reset);
+ reset_control_deassert(adev->c2_reset);
+
+ adev->channels = devm_kcalloc(adev->dev, ADM_MAX_CHANNELS,
-+ sizeof(*adev->channels), GFP_KERNEL);
++ sizeof(*adev->channels), GFP_KERNEL);
+
+ if (!adev->channels) {
+ ret = -ENOMEM;
@@ -859,16 +864,16 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+
+ /* configure client interfaces */
+ writel(ADM_CI_RANGE_START(0x40) | ADM_CI_RANGE_END(0xb0) |
-+ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(0));
++ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(0));
+ writel(ADM_CI_RANGE_START(0x2a) | ADM_CI_RANGE_END(0x2c) |
-+ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(1));
++ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(1));
+ writel(ADM_CI_RANGE_START(0x12) | ADM_CI_RANGE_END(0x28) |
-+ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(2));
++ ADM_CI_BURST_8_WORDS, adev->regs + ADM_CI_CONF(2));
+ writel(ADM_GP_CTL_LP_EN | ADM_GP_CTL_LP_CNT(0xf),
-+ adev->regs + ADM_GP_CTL);
++ adev->regs + ADM_GP_CTL);
+
+ ret = devm_request_irq(adev->dev, adev->irq, adm_dma_irq,
-+ 0, "adm_dma", adev);
++ 0, "adm_dma", adev);
+ if (ret)
+ goto err_disable_clks;
+
@@ -933,6 +938,7 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+ /* mask IRQs for this channel/EE pair */
+ writel(0, adev->regs + ADM_CH_RSLT_CONF(achan->id, adev->ee));
+
++ tasklet_kill(&adev->channels[i].vc.task);
+ adm_terminate_all(&adev->channels[i].vc.chan);
+ }
+
@@ -964,3 +970,6 @@ Signed-off-by: Thomas Pedersen <twp@codeaurora.org>
+MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
+MODULE_DESCRIPTION("QCOM ADM DMA engine driver");
+MODULE_LICENSE("GPL v2");
+--
+cgit 1.2.3-1.el7
+
diff --git a/target/linux/ipq806x/patches-5.4/101-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch b/target/linux/ipq806x/patches-5.4/101-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch
new file mode 100644
index 0000000000..7aec4fcc83
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.4/101-5.12-mtd-parsers-Add-Qcom-SMEM-parser.patch
@@ -0,0 +1,227 @@
+From 803eb124e1a64e42888542c3444bfe6dac412c7f Mon Sep 17 00:00:00 2001
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Date: Mon, 4 Jan 2021 09:41:35 +0530
+Subject: mtd: parsers: Add Qcom SMEM parser
+
+NAND based Qualcomm platforms have the partition table populated in the
+Shared Memory (SMEM). Hence, add a parser for parsing the partitions
+from it.
+
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20210104041137.113075-3-manivannan.sadhasivam@linaro.org
+---
+ drivers/mtd/parsers/Kconfig | 8 ++
+ drivers/mtd/parsers/Makefile | 1 +
+ drivers/mtd/parsers/qcomsmempart.c | 170 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 179 insertions(+)
+ create mode 100644 drivers/mtd/parsers/qcomsmempart.c
+
+diff --git a/drivers/mtd/parsers/Kconfig b/drivers/mtd/parsers/Kconfig
+index e72354322f628..d90c302290522 100644
+--- a/drivers/mtd/parsers/Kconfig
++++ b/drivers/mtd/parsers/Kconfig
+@@ -160,6 +160,14 @@ config MTD_REDBOOT_PARTS_READONLY
+ 'FIS directory' images, enable this option.
+
+ endif # MTD_REDBOOT_PARTS
++
++config MTD_QCOMSMEM_PARTS
++ tristate "Qualcomm SMEM NAND flash partition parser"
++ depends on MTD_NAND_QCOM || COMPILE_TEST
++ depends on QCOM_SMEM
++ help
++ This provides support for parsing partitions from Shared Memory (SMEM)
++ for NAND flash on Qualcomm platforms.
+
+ config MTD_ROUTERBOOT_PARTS
+ tristate "RouterBoot flash partition parser"
+diff --git a/drivers/mtd/parsers/Makefile b/drivers/mtd/parsers/Makefile
+index b0c5f62f9e858..50eb0b0a22105 100644
+--- a/drivers/mtd/parsers/Makefile
++++ b/drivers/mtd/parsers/Makefile
+@@ -9,4 +9,5 @@ obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
+ obj-$(CONFIG_MTD_PARSER_TRX) += parser_trx.o
+ obj-$(CONFIG_MTD_SHARPSL_PARTS) += sharpslpart.o
+ obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
++obj-$(CONFIG_MTD_QCOMSMEM_PARTS) += qcomsmempart.o
+ obj-$(CONFIG_MTD_ROUTERBOOT_PARTS) += routerbootpart.o
+diff --git a/drivers/mtd/parsers/qcomsmempart.c b/drivers/mtd/parsers/qcomsmempart.c
+new file mode 100644
+index 0000000000000..808cb33d71f8e
+--- /dev/null
++++ b/drivers/mtd/parsers/qcomsmempart.c
+@@ -0,0 +1,170 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Qualcomm SMEM NAND flash partition parser
++ *
++ * Copyright (C) 2020, Linaro Ltd.
++ */
++
++#include <linux/ctype.h>
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/partitions.h>
++#include <linux/slab.h>
++#include <linux/soc/qcom/smem.h>
++
++#define SMEM_AARM_PARTITION_TABLE 9
++#define SMEM_APPS 0
++
++#define SMEM_FLASH_PART_MAGIC1 0x55ee73aa
++#define SMEM_FLASH_PART_MAGIC2 0xe35ebddb
++#define SMEM_FLASH_PTABLE_V3 3
++#define SMEM_FLASH_PTABLE_V4 4
++#define SMEM_FLASH_PTABLE_MAX_PARTS_V3 16
++#define SMEM_FLASH_PTABLE_MAX_PARTS_V4 48
++#define SMEM_FLASH_PTABLE_HDR_LEN (4 * sizeof(u32))
++#define SMEM_FLASH_PTABLE_NAME_SIZE 16
++
++/**
++ * struct smem_flash_pentry - SMEM Flash partition entry
++ * @name: Name of the partition
++ * @offset: Offset in blocks
++ * @length: Length of the partition in blocks
++ * @attr: Flags for this partition
++ */
++struct smem_flash_pentry {
++ char name[SMEM_FLASH_PTABLE_NAME_SIZE];
++ __le32 offset;
++ __le32 length;
++ u8 attr;
++} __packed __aligned(4);
++
++/**
++ * struct smem_flash_ptable - SMEM Flash partition table
++ * @magic1: Partition table Magic 1
++ * @magic2: Partition table Magic 2
++ * @version: Partition table version
++ * @numparts: Number of partitions in this ptable
++ * @pentry: Flash partition entries belonging to this ptable
++ */
++struct smem_flash_ptable {
++ __le32 magic1;
++ __le32 magic2;
++ __le32 version;
++ __le32 numparts;
++ struct smem_flash_pentry pentry[SMEM_FLASH_PTABLE_MAX_PARTS_V4];
++} __packed __aligned(4);
++
++static int parse_qcomsmem_part(struct mtd_info *mtd,
++ const struct mtd_partition **pparts,
++ struct mtd_part_parser_data *data)
++{
++ struct smem_flash_pentry *pentry;
++ struct smem_flash_ptable *ptable;
++ size_t len = SMEM_FLASH_PTABLE_HDR_LEN;
++ struct mtd_partition *parts;
++ int ret, i, numparts;
++ char *name, *c;
++
++ pr_debug("Parsing partition table info from SMEM\n");
++ ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len);
++ if (IS_ERR(ptable)) {
++ pr_err("Error reading partition table header\n");
++ return PTR_ERR(ptable);
++ }
++
++ /* Verify ptable magic */
++ if (le32_to_cpu(ptable->magic1) != SMEM_FLASH_PART_MAGIC1 ||
++ le32_to_cpu(ptable->magic2) != SMEM_FLASH_PART_MAGIC2) {
++ pr_err("Partition table magic verification failed\n");
++ return -EINVAL;
++ }
++
++ /* Ensure that # of partitions is less than the max we have allocated */
++ numparts = le32_to_cpu(ptable->numparts);
++ if (numparts > SMEM_FLASH_PTABLE_MAX_PARTS_V4) {
++ pr_err("Partition numbers exceed the max limit\n");
++ return -EINVAL;
++ }
++
++ /* Find out length of partition data based on table version */
++ if (le32_to_cpu(ptable->version) <= SMEM_FLASH_PTABLE_V3) {
++ len = SMEM_FLASH_PTABLE_HDR_LEN + SMEM_FLASH_PTABLE_MAX_PARTS_V3 *
++ sizeof(struct smem_flash_pentry);
++ } else if (le32_to_cpu(ptable->version) == SMEM_FLASH_PTABLE_V4) {
++ len = SMEM_FLASH_PTABLE_HDR_LEN + SMEM_FLASH_PTABLE_MAX_PARTS_V4 *
++ sizeof(struct smem_flash_pentry);
++ } else {
++ pr_err("Unknown ptable version (%d)", le32_to_cpu(ptable->version));
++ return -EINVAL;
++ }
++
++ /*
++ * Now that the partition table header has been parsed, verified
++ * and the length of the partition table calculated, read the
++ * complete partition table
++ */
++ ptable = qcom_smem_get(SMEM_APPS, SMEM_AARM_PARTITION_TABLE, &len);
++ if (IS_ERR_OR_NULL(ptable)) {
++ pr_err("Error reading partition table\n");
++ return PTR_ERR(ptable);
++ }
++
++ parts = kcalloc(numparts, sizeof(*parts), GFP_KERNEL);
++ if (!parts)
++ return -ENOMEM;
++
++ for (i = 0; i < numparts; i++) {
++ pentry = &ptable->pentry[i];
++ if (pentry->name[0] == '\0')
++ continue;
++
++ name = kstrdup(pentry->name, GFP_KERNEL);
++ if (!name) {
++ ret = -ENOMEM;
++ goto out_free_parts;
++ }
++
++ /* Convert name to lower case */
++ for (c = name; *c != '\0'; c++)
++ *c = tolower(*c);
++
++ parts[i].name = name;
++ parts[i].offset = le32_to_cpu(pentry->offset) * mtd->erasesize;
++ parts[i].mask_flags = pentry->attr;
++ parts[i].size = le32_to_cpu(pentry->length) * mtd->erasesize;
++ pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n",
++ i, pentry->name, le32_to_cpu(pentry->offset),
++ le32_to_cpu(pentry->length), pentry->attr);
++ }
++
++ pr_debug("SMEM partition table found: ver: %d len: %d\n",
++ le32_to_cpu(ptable->version), numparts);
++ *pparts = parts;
++
++ return numparts;
++
++out_free_parts:
++ while (--i >= 0)
++ kfree(parts[i].name);
++ kfree(parts);
++ *pparts = NULL;
++
++ return ret;
++}
++
++static const struct of_device_id qcomsmem_of_match_table[] = {
++ { .compatible = "qcom,smem-part" },
++ {},
++};
++MODULE_DEVICE_TABLE(of, qcomsmem_of_match_table);
++
++static struct mtd_part_parser mtd_parser_qcomsmem = {
++ .parse_fn = parse_qcomsmem_part,
++ .name = "qcomsmem",
++ .of_match_table = qcomsmem_of_match_table,
++};
++module_mtd_part_parser(mtd_parser_qcomsmem);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
++MODULE_DESCRIPTION("Qualcomm SMEM NAND flash partition parser");
+--
+cgit 1.2.3-1.el7
+
diff --git a/target/linux/ipq806x/patches-5.4/102-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch b/target/linux/ipq806x/patches-5.4/102-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch
new file mode 100644
index 0000000000..e83872935f
--- /dev/null
+++ b/target/linux/ipq806x/patches-5.4/102-mtd-rootfs-conflicts-with-OpenWrt-auto-mounting.patch
@@ -0,0 +1,24 @@
+From 5001f2e1a325b68dbf225bd17f69a4d3d975cca5 Mon Sep 17 00:00:00 2001
+From: John Crispin <john@phrozen.org>
+Date: Thu, 9 Mar 2017 09:31:44 +0100
+Subject: [PATCH 61/69] mtd: "rootfs" conflicts with OpenWrt auto mounting
+
+Signed-off-by: John Crispin <john@phrozen.org>
+---
+ drivers/mtd/parsers/qcomsmempart.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/mtd/parsers/qcomsmempart.c
++++ b/drivers/mtd/parsers/qcomsmempart.c
+@@ -132,6 +132,11 @@ static int parse_qcomsmem_part(struct mt
+ parts[i].offset = le32_to_cpu(pentry->offset) * mtd->erasesize;
+ parts[i].mask_flags = pentry->attr;
+ parts[i].size = le32_to_cpu(pentry->length) * mtd->erasesize;
++
++ /* "rootfs" conflicts with OpenWrt auto mounting */
++ if (mtd_type_is_nand(mtd) && !strcmp(name, "rootfs"))
++ parts[i].name = "ubi";
++
+ pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n",
+ i, pentry->name, le32_to_cpu(pentry->offset),
+ le32_to_cpu(pentry->length), pentry->attr);