summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bus/tegra-aconnect.c66
-rw-r--r--drivers/clk/zynqmp/clkc.c4
-rw-r--r--drivers/firmware/arm_scmi/driver.c8
-rw-r--r--drivers/firmware/imx/Makefile2
-rw-r--r--drivers/firmware/imx/imx-scu-irq.c168
-rw-r--r--drivers/firmware/imx/imx-scu.c6
-rw-r--r--drivers/firmware/imx/scu-pd.c121
-rw-r--r--drivers/firmware/xilinx/zynqmp-debug.c18
-rw-r--r--drivers/firmware/xilinx/zynqmp.c56
-rw-r--r--drivers/fpga/Kconfig9
-rw-r--r--drivers/fpga/Makefile1
-rw-r--r--drivers/fpga/zynqmp-fpga.c159
-rw-r--r--drivers/memory/emif.h4
-rw-r--r--drivers/memory/tegra/mc.c34
-rw-r--r--drivers/memory/tegra/mc.h2
-rw-r--r--drivers/memory/tegra/tegra114.c4
-rw-r--r--drivers/memory/tegra/tegra124.c4
-rw-r--r--drivers/memory/tegra/tegra20.c28
-rw-r--r--drivers/memory/tegra/tegra210.c2
-rw-r--r--drivers/memory/tegra/tegra30.c4
-rw-r--r--drivers/memory/ti-emif-pm.c3
-rw-r--r--drivers/memory/ti-emif-sram-pm.S41
-rw-r--r--drivers/misc/Kconfig24
-rw-r--r--drivers/misc/Makefile3
-rw-r--r--drivers/nvmem/zynqmp_nvmem.c10
-rw-r--r--drivers/reset/reset-zynqmp.c8
-rw-r--r--drivers/rtc/rtc-omap.c49
-rw-r--r--drivers/soc/Kconfig1
-rw-r--r--drivers/soc/Makefile1
-rw-r--r--drivers/soc/amlogic/meson-gx-pwrc-vpu.c160
-rw-r--r--drivers/soc/amlogic/meson-gx-socinfo.c43
-rw-r--r--drivers/soc/aspeed/Kconfig31
-rw-r--r--drivers/soc/aspeed/Makefile3
-rw-r--r--drivers/soc/aspeed/aspeed-lpc-ctrl.c (renamed from drivers/misc/aspeed-lpc-ctrl.c)0
-rw-r--r--drivers/soc/aspeed/aspeed-lpc-snoop.c (renamed from drivers/misc/aspeed-lpc-snoop.c)0
-rw-r--r--drivers/soc/aspeed/aspeed-p2a-ctrl.c (renamed from drivers/misc/aspeed-p2a-ctrl.c)0
-rw-r--r--drivers/soc/imx/Makefile1
-rw-r--r--drivers/soc/imx/gpc.c4
-rw-r--r--drivers/soc/imx/gpcv2.c43
-rw-r--r--drivers/soc/imx/soc-imx8.c115
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c111
-rw-r--r--drivers/soc/qcom/cmd-db.c4
-rw-r--r--drivers/soc/qcom/qmi_interface.c7
-rw-r--r--drivers/soc/qcom/rmtfs_mem.c21
-rw-r--r--drivers/soc/qcom/rpmh-rsc.c2
-rw-r--r--drivers/soc/renesas/renesas-soc.c3
-rw-r--r--drivers/soc/rockchip/grf.c2
-rw-r--r--drivers/soc/tegra/pmc.c171
-rw-r--r--drivers/soc/ti/Kconfig5
-rw-r--r--drivers/soc/ti/pm33xx.c273
-rw-r--r--drivers/soc/xilinx/zynqmp_pm_domains.c18
-rw-r--r--drivers/soc/xilinx/zynqmp_power.c10
-rw-r--r--drivers/spi/spi-zynqmp-gqspi.c6
-rw-r--r--drivers/tee/optee/core.c80
54 files changed, 1571 insertions, 382 deletions
diff --git a/drivers/bus/tegra-aconnect.c b/drivers/bus/tegra-aconnect.c
index 084ae286fa23..ac58142301f4 100644
--- a/drivers/bus/tegra-aconnect.c
+++ b/drivers/bus/tegra-aconnect.c
@@ -12,28 +12,38 @@
 #include <linux/module.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
-#include <linux/pm_clock.h>
 #include <linux/pm_runtime.h>
 
+struct tegra_aconnect {
+	struct clk	*ape_clk;
+	struct clk	*apb2ape_clk;
+};
+
 static int tegra_aconnect_probe(struct platform_device *pdev)
 {
-	int ret;
+	struct tegra_aconnect *aconnect;
 
 	if (!pdev->dev.of_node)
 		return -EINVAL;
 
-	ret = pm_clk_create(&pdev->dev);
-	if (ret)
-		return ret;
+	aconnect = devm_kzalloc(&pdev->dev, sizeof(struct tegra_aconnect),
+				GFP_KERNEL);
+	if (!aconnect)
+		return -ENOMEM;
 
-	ret = of_pm_clk_add_clk(&pdev->dev, "ape");
-	if (ret)
-		goto clk_destroy;
+	aconnect->ape_clk = devm_clk_get(&pdev->dev, "ape");
+	if (IS_ERR(aconnect->ape_clk)) {
+		dev_err(&pdev->dev, "Can't retrieve ape clock\n");
+		return PTR_ERR(aconnect->ape_clk);
+	}
 
-	ret = of_pm_clk_add_clk(&pdev->dev, "apb2ape");
-	if (ret)
-		goto clk_destroy;
+	aconnect->apb2ape_clk = devm_clk_get(&pdev->dev, "apb2ape");
+	if (IS_ERR(aconnect->apb2ape_clk)) {
+		dev_err(&pdev->dev, "Can't retrieve apb2ape clock\n");
+		return PTR_ERR(aconnect->apb2ape_clk);
+	}
 
+	dev_set_drvdata(&pdev->dev, aconnect);
 	pm_runtime_enable(&pdev->dev);
 
 	of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
@@ -41,35 +51,51 @@ static int tegra_aconnect_probe(struct platform_device *pdev)
 	dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n");
 
 	return 0;
-
-clk_destroy:
-	pm_clk_destroy(&pdev->dev);
-
-	return ret;
 }
 
 static int tegra_aconnect_remove(struct platform_device *pdev)
 {
 	pm_runtime_disable(&pdev->dev);
 
-	pm_clk_destroy(&pdev->dev);
-
 	return 0;
 }
 
 static int tegra_aconnect_runtime_resume(struct device *dev)
 {
-	return pm_clk_resume(dev);
+	struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(aconnect->ape_clk);
+	if (ret) {
+		dev_err(dev, "ape clk_enable failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(aconnect->apb2ape_clk);
+	if (ret) {
+		clk_disable_unprepare(aconnect->ape_clk);
+		dev_err(dev, "apb2ape clk_enable failed: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
 }
 
 static int tegra_aconnect_runtime_suspend(struct device *dev)
 {
-	return pm_clk_suspend(dev);
+	struct tegra_aconnect *aconnect = dev_get_drvdata(dev);
+
+	clk_disable_unprepare(aconnect->ape_clk);
+	clk_disable_unprepare(aconnect->apb2ape_clk);
+
+	return 0;
 }
 
 static const struct dev_pm_ops tegra_aconnect_pm_ops = {
 	SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend,
 			   tegra_aconnect_runtime_resume, NULL)
+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+				      pm_runtime_force_resume)
 };
 
 static const struct of_device_id tegra_aconnect_of_match[] = {
diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c
index 8febd2431545..a11f93ecbf34 100644
--- a/drivers/clk/zynqmp/clkc.c
+++ b/drivers/clk/zynqmp/clkc.c
@@ -739,8 +739,8 @@ static int zynqmp_clock_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 
 	eemi_ops = zynqmp_pm_get_eemi_ops();
-	if (!eemi_ops)
-		return -ENXIO;
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
 
 	ret = zynqmp_clk_setup(dev->of_node);
 
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 8f952f2f1a29..b5bc4c7a8fab 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -654,9 +654,7 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
 
 static int scmi_mailbox_check(struct device_node *np)
 {
-	struct of_phandle_args arg;
-
-	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, &arg);
+	return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells", 0, NULL);
 }
 
 static int scmi_mbox_free_channel(int id, void *p, void *data)
@@ -798,7 +796,9 @@ static int scmi_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	desc = of_match_device(scmi_of_match, dev)->data;
+	desc = of_device_get_match_data(dev);
+	if (!desc)
+		return -EINVAL;
 
 	info = devm_kzalloc(dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
index 1b2e15b3c9ca..802c4ad8e8f9 100644
--- a/drivers/firmware/imx/Makefile
+++ b/drivers/firmware/imx/Makefile
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_IMX_SCU)		+= imx-scu.o misc.o
+obj-$(CONFIG_IMX_SCU)		+= imx-scu.o misc.o imx-scu-irq.o
 obj-$(CONFIG_IMX_SCU_PD)	+= scu-pd.o
diff --git a/drivers/firmware/imx/imx-scu-irq.c b/drivers/firmware/imx/imx-scu-irq.c
new file mode 100644
index 000000000000..043833ad3c1a
--- /dev/null
+++ b/drivers/firmware/imx/imx-scu-irq.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 NXP
+ *
+ * Implementation of the SCU IRQ functions using MU.
+ *
+ */
+
+#include <dt-bindings/firmware/imx/rsrc.h>
+#include <linux/firmware/imx/ipc.h>
+#include <linux/mailbox_client.h>
+
+#define IMX_SC_IRQ_FUNC_ENABLE	1
+#define IMX_SC_IRQ_FUNC_STATUS	2
+#define IMX_SC_IRQ_NUM_GROUP	4
+
+static u32 mu_resource_id;
+
+struct imx_sc_msg_irq_get_status {
+	struct imx_sc_rpc_msg hdr;
+	union {
+		struct {
+			u16 resource;
+			u8 group;
+			u8 reserved;
+		} __packed req;
+		struct {
+			u32 status;
+		} resp;
+	} data;
+};
+
+struct imx_sc_msg_irq_enable {
+	struct imx_sc_rpc_msg hdr;
+	u32 mask;
+	u16 resource;
+	u8 group;
+	u8 enable;
+} __packed;
+
+static struct imx_sc_ipc *imx_sc_irq_ipc_handle;
+static struct work_struct imx_sc_irq_work;
+static ATOMIC_NOTIFIER_HEAD(imx_scu_irq_notifier_chain);
+
+int imx_scu_irq_register_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(
+		&imx_scu_irq_notifier_chain, nb);
+}
+EXPORT_SYMBOL(imx_scu_irq_register_notifier);
+
+int imx_scu_irq_unregister_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(
+		&imx_scu_irq_notifier_chain, nb);
+}
+EXPORT_SYMBOL(imx_scu_irq_unregister_notifier);
+
+static int imx_scu_irq_notifier_call_chain(unsigned long status, u8 *group)
+{
+	return atomic_notifier_call_chain(&imx_scu_irq_notifier_chain,
+		status, (void *)group);
+}
+
+static void imx_scu_irq_work_handler(struct work_struct *work)
+{
+	struct imx_sc_msg_irq_get_status msg;
+	struct imx_sc_rpc_msg *hdr = &msg.hdr;
+	u32 irq_status;
+	int ret;
+	u8 i;
+
+	for (i = 0; i < IMX_SC_IRQ_NUM_GROUP; i++) {
+		hdr->ver = IMX_SC_RPC_VERSION;
+		hdr->svc = IMX_SC_RPC_SVC_IRQ;
+		hdr->func = IMX_SC_IRQ_FUNC_STATUS;
+		hdr->size = 2;
+
+		msg.data.req.resource = mu_resource_id;
+		msg.data.req.group = i;
+
+		ret = imx_scu_call_rpc(imx_sc_irq_ipc_handle, &msg, true);
+		if (ret) {
+			pr_err("get irq group %d status failed, ret %d\n",
+			       i, ret);
+			return;
+		}
+
+		irq_status = msg.data.resp.status;
+		if (!irq_status)
+			continue;
+
+		imx_scu_irq_notifier_call_chain(irq_status, &i);
+	}
+}
+
+int imx_scu_irq_group_enable(u8 group, u32 mask, u8 enable)
+{
+	struct imx_sc_msg_irq_enable msg;
+	struct imx_sc_rpc_msg *hdr = &msg.hdr;
+	int ret;
+
+	hdr->ver = IMX_SC_RPC_VERSION;
+	hdr->svc = IMX_SC_RPC_SVC_IRQ;
+	hdr->func = IMX_SC_IRQ_FUNC_ENABLE;
+	hdr->size = 3;
+
+	msg.resource = mu_resource_id;
+	msg.group = group;
+	msg.mask = mask;
+	msg.enable = enable;
+
+	ret = imx_scu_call_rpc(imx_sc_irq_ipc_handle, &msg, true);
+	if (ret)
+		pr_err("enable irq failed, group %d, mask %d, ret %d\n",
+			group, mask, ret);
+
+	return ret;
+}
+EXPORT_SYMBOL(imx_scu_irq_group_enable);
+
+static void imx_scu_irq_callback(struct mbox_client *c, void *msg)
+{
+	schedule_work(&imx_sc_irq_work);
+}
+
+int imx_scu_enable_general_irq_channel(struct device *dev)
+{
+	struct of_phandle_args spec;
+	struct mbox_client *cl;
+	struct mbox_chan *ch;
+	int ret = 0, i = 0;
+
+	ret = imx_scu_get_handle(&imx_sc_irq_ipc_handle);
+	if (ret)
+		return ret;
+
+	cl = devm_kzalloc(dev, sizeof(*cl), GFP_KERNEL);
+	if (!cl)
+		return -ENOMEM;
+
+	cl->dev = dev;
+	cl->rx_callback = imx_scu_irq_callback;
+
+	/* SCU general IRQ uses general interrupt channel 3 */
+	ch = mbox_request_channel_byname(cl, "gip3");
+	if (IS_ERR(ch)) {
+		ret = PTR_ERR(ch);
+		dev_err(dev, "failed to request mbox chan gip3, ret %d\n", ret);
+		devm_kfree(dev, cl);
+		return ret;
+	}
+
+	INIT_WORK(&imx_sc_irq_work, imx_scu_irq_work_handler);
+
+	if (!of_parse_phandle_with_args(dev->of_node, "mboxes",
+				       "#mbox-cells", 0, &spec))
+		i = of_alias_get_id(spec.np, "mu");
+
+	/* use mu1 as general mu irq channel if failed */
+	if (i < 0)
+		i = 1;
+
+	mu_resource_id = IMX_SC_R_MU_0A + i;
+
+	return ret;
+}
+EXPORT_SYMBOL(imx_scu_enable_general_irq_channel);
diff --git a/drivers/firmware/imx/imx-scu.c b/drivers/firmware/imx/imx-scu.c
index 2bb1a19c413f..04a24a863d6e 100644
--- a/drivers/firmware/imx/imx-scu.c
+++ b/drivers/firmware/imx/imx-scu.c
@@ -10,6 +10,7 @@
 #include <linux/err.h>
 #include <linux/firmware/imx/types.h>
 #include <linux/firmware/imx/ipc.h>
+#include <linux/firmware/imx/sci.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/kernel.h>
@@ -246,6 +247,11 @@ static int imx_scu_probe(struct platform_device *pdev)
 
 	imx_sc_ipc_handle = sc_ipc;
 
+	ret = imx_scu_enable_general_irq_channel(dev);
+	if (ret)
+		dev_warn(dev,
+			"failed to enable general irq channel: %d\n", ret);
+
 	dev_info(dev, "NXP i.MX SCU Initialized\n");
 
 	return devm_of_platform_populate(dev);
diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c
index 39a94c7177fc..480cec69e2c9 100644
--- a/drivers/firmware/imx/scu-pd.c
+++ b/drivers/firmware/imx/scu-pd.c
@@ -74,7 +74,10 @@ struct imx_sc_pd_range {
 	char *name;
 	u32 rsrc;
 	u8 num;
+
+	/* add domain index */
 	bool postfix;
+	u8 start_from;
 };
 
 struct imx_sc_pd_soc {
@@ -84,71 +87,75 @@ struct imx_sc_pd_soc {
 
 static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
 	/* LSIO SS */
-	{ "lsio-pwm", IMX_SC_R_PWM_0, 8, 1 },
-	{ "lsio-gpio", IMX_SC_R_GPIO_0, 8, 1 },
-	{ "lsio-gpt", IMX_SC_R_GPT_0, 5, 1 },
-	{ "lsio-kpp", IMX_SC_R_KPP, 1, 0 },
-	{ "lsio-fspi", IMX_SC_R_FSPI_0, 2, 1 },
-	{ "lsio-mu", IMX_SC_R_MU_0A, 14, 1 },
+	{ "pwm", IMX_SC_R_PWM_0, 8, true, 0 },
+	{ "gpio", IMX_SC_R_GPIO_0, 8, true, 0 },
+	{ "gpt", IMX_SC_R_GPT_0, 5, true, 0 },
+	{ "kpp", IMX_SC_R_KPP, 1, false, 0 },
+	{ "fspi", IMX_SC_R_FSPI_0, 2, true, 0 },
+	{ "mu", IMX_SC_R_MU_0A, 14, true, 0 },
 
 	/* CONN SS */
-	{ "con-usb", IMX_SC_R_USB_0, 2, 1 },
-	{ "con-usb0phy", IMX_SC_R_USB_0_PHY, 1, 0 },
-	{ "con-usb2", IMX_SC_R_USB_2, 1, 0 },
-	{ "con-usb2phy", IMX_SC_R_USB_2_PHY, 1, 0 },
-	{ "con-sdhc", IMX_SC_R_SDHC_0, 3, 1 },
-	{ "con-enet", IMX_SC_R_ENET_0, 2, 1 },
-	{ "con-nand", IMX_SC_R_NAND, 1, 0 },
-	{ "con-mlb", IMX_SC_R_MLB_0, 1, 1 },
-
-	/* Audio DMA SS */
-	{ "adma-audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, 0 },
-	{ "adma-audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, 0 },
-	{ "adma-audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, 0 },
-	{ "adma-dma0-ch", IMX_SC_R_DMA_0_CH0, 16, 1 },
-	{ "adma-dma1-ch", IMX_SC_R_DMA_1_CH0, 16, 1 },
-	{ "adma-dma2-ch", IMX_SC_R_DMA_2_CH0, 5, 1 },
-	{ "adma-asrc0", IMX_SC_R_ASRC_0, 1, 0 },
-	{ "adma-asrc1", IMX_SC_R_ASRC_1, 1, 0 },
-	{ "adma-esai0", IMX_SC_R_ESAI_0, 1, 0 },
-	{ "adma-spdif0", IMX_SC_R_SPDIF_0, 1, 0 },
-	{ "adma-sai", IMX_SC_R_SAI_0, 3, 1 },
-	{ "adma-amix", IMX_SC_R_AMIX, 1, 0 },
-	{ "adma-mqs0", IMX_SC_R_MQS_0, 1, 0 },
-	{ "adma-dsp", IMX_SC_R_DSP, 1, 0 },
-	{ "adma-dsp-ram", IMX_SC_R_DSP_RAM, 1, 0 },
-	{ "adma-can", IMX_SC_R_CAN_0, 3, 1 },
-	{ "adma-ftm", IMX_SC_R_FTM_0, 2, 1 },
-	{ "adma-lpi2c", IMX_SC_R_I2C_0, 4, 1 },
-	{ "adma-adc", IMX_SC_R_ADC_0, 1, 1 },
-	{ "adma-lcd", IMX_SC_R_LCD_0, 1, 1 },
-	{ "adma-lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, 1 },
-	{ "adma-lpuart", IMX_SC_R_UART_0, 4, 1 },
-	{ "adma-lpspi", IMX_SC_R_SPI_0, 4, 1 },
-
-	/* VPU SS  */
-	{ "vpu", IMX_SC_R_VPU, 1, 0 },
-	{ "vpu-pid", IMX_SC_R_VPU_PID0, 8, 1 },
-	{ "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, 0 },
-	{ "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, 0 },
+	{ "usb", IMX_SC_R_USB_0, 2, true, 0 },
+	{ "usb0phy", IMX_SC_R_USB_0_PHY, 1, false, 0 },
+	{ "usb2", IMX_SC_R_USB_2, 1, false, 0 },
+	{ "usb2phy", IMX_SC_R_USB_2_PHY, 1, false, 0 },
+	{ "sdhc", IMX_SC_R_SDHC_0, 3, true, 0 },
+	{ "enet", IMX_SC_R_ENET_0, 2, true, 0 },
+	{ "nand", IMX_SC_R_NAND, 1, false, 0 },
+	{ "mlb", IMX_SC_R_MLB_0, 1, true, 0 },
+
+	/* AUDIO SS */
+	{ "audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, false, 0 },
+	{ "audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, false, 0 },
+	{ "audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, false, 0 },
+	{ "dma0-ch", IMX_SC_R_DMA_0_CH0, 16, true, 0 },
+	{ "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 },
+	{ "dma2-ch", IMX_SC_R_DMA_2_CH0, 5, true, 0 },
+	{ "asrc0", IMX_SC_R_ASRC_0, 1, false, 0 },
+	{ "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 },
+	{ "esai0", IMX_SC_R_ESAI_0, 1, false, 0 },
+	{ "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 },
+	{ "sai", IMX_SC_R_SAI_0, 3, true, 0 },
+	{ "amix", IMX_SC_R_AMIX, 1, false, 0 },
+	{ "mqs0", IMX_SC_R_MQS_0, 1, false, 0 },
+	{ "dsp", IMX_SC_R_DSP, 1, false, 0 },
+	{ "dsp-ram", IMX_SC_R_DSP_RAM, 1, false, 0 },
+
+	/* DMA SS */
+	{ "can", IMX_SC_R_CAN_0, 3, true, 0 },
+	{ "ftm", IMX_SC_R_FTM_0, 2, true, 0 },
+	{ "lpi2c", IMX_SC_R_I2C_0, 4, true, 0 },
+	{ "adc", IMX_SC_R_ADC_0, 1, true, 0 },
+	{ "lcd", IMX_SC_R_LCD_0, 1, true, 0 },
+	{ "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 },
+	{ "lpuart", IMX_SC_R_UART_0, 4, true, 0 },
+	{ "lpspi", IMX_SC_R_SPI_0, 4, true, 0 },
+
+	/* VPU SS */
+	{ "vpu", IMX_SC_R_VPU, 1, false, 0 },
+	{ "vpu-pid", IMX_SC_R_VPU_PID0, 8, true, 0 },
+	{ "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, false, 0 },
+	{ "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, false, 0 },
 
 	/* GPU SS */
-	{ "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, 1 },
+	{ "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, true, 0 },
 
 	/* HSIO SS */
-	{ "hsio-pcie-b", IMX_SC_R_PCIE_B, 1, 0 },
-	{ "hsio-serdes-1", IMX_SC_R_SERDES_1, 1, 0 },
-	{ "hsio-gpio", IMX_SC_R_HSIO_GPIO, 1, 0 },
+	{ "pcie-b", IMX_SC_R_PCIE_B, 1, false, 0 },
+	{ "serdes-1", IMX_SC_R_SERDES_1, 1, false, 0 },
+	{ "hsio-gpio", IMX_SC_R_HSIO_GPIO, 1, false, 0 },
+
+	/* MIPI SS */
+	{ "mipi0", IMX_SC_R_MIPI_0, 1, false, 0 },
+	{ "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, false, 0 },
+	{ "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, true, 0 },
 
-	/* MIPI/LVDS SS */
-	{ "mipi0", IMX_SC_R_MIPI_0, 1, 0 },
-	{ "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, 0 },
-	{ "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, 1 },
-	{ "lvds0", IMX_SC_R_LVDS_0, 1, 0 },
+	/* LVDS SS */
+	{ "lvds0", IMX_SC_R_LVDS_0, 1, false, 0 },
 
 	/* DC SS */
-	{ "dc0", IMX_SC_R_DC_0, 1, 0 },
-	{ "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, 1 },
+	{ "dc0", IMX_SC_R_DC_0, 1, false, 0 },
+	{ "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 },
 };
 
 static const struct imx_sc_pd_soc imx8qxp_scu_pd = {
@@ -236,7 +243,7 @@ imx_scu_add_pm_domain(struct device *dev, int idx,
 
 	if (pd_ranges->postfix)
 		snprintf(sc_pd->name, sizeof(sc_pd->name),
-			 "%s%i", pd_ranges->name, idx);
+			 "%s%i", pd_ranges->name, pd_ranges->start_from + idx);
 	else
 		snprintf(sc_pd->name, sizeof(sc_pd->name),
 			 "%s", pd_ranges->name);
diff --git a/drivers/firmware/xilinx/zynqmp-debug.c b/drivers/firmware/xilinx/zynqmp-debug.c
index 2771df6df379..c6d0724da4db 100644
--- a/drivers/firmware/xilinx/zynqmp-debug.c
+++ b/drivers/firmware/xilinx/zynqmp-debug.c
@@ -90,9 +90,6 @@ static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret)
 	int ret;
 	struct zynqmp_pm_query_data qdata = {0};
 
-	if (!eemi_ops)
-		return -ENXIO;
-
 	switch (pm_id) {
 	case PM_GET_API_VERSION:
 		ret = eemi_ops->get_api_version(&pm_api_version);
@@ -163,21 +160,14 @@ static ssize_t zynqmp_pm_debugfs_api_write(struct file *file,
 
 	strcpy(debugfs_buf, "");
 
-	if (*off != 0 || len == 0)
+	if (*off != 0 || len <= 1 || len > PAGE_SIZE - 1)
 		return -EINVAL;
 
-	kern_buff = kzalloc(len, GFP_KERNEL);
-	if (!kern_buff)
-		return -ENOMEM;
-
+	kern_buff = memdup_user_nul(ptr, len);
+	if (IS_ERR(kern_buff))
+		return PTR_ERR(kern_buff);
 	tmp_buff = kern_buff;
 
-	ret = strncpy_from_user(kern_buff, ptr, len);
-	if (ret < 0) {
-		ret = -EFAULT;
-		goto err;
-	}
-
 	/* Read the API name from a user request */
 	pm_api_req = strsep(&kern_buff, " ");
 
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index 98f936125643..fd3d83745208 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -24,6 +24,8 @@
 #include <linux/firmware/xlnx-zynqmp.h>
 #include "zynqmp-debug.h"
 
+static const struct zynqmp_eemi_ops *eemi_ops_tbl;
+
 static const struct mfd_cell firmware_devs[] = {
 	{
 		.name = "zynqmp_power_controller",
@@ -538,6 +540,49 @@ static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset,
 }
 
 /**
+ * zynqmp_pm_fpga_load - Perform the fpga load
+ * @address:	Address to write to
+ * @size:	pl bitstream size
+ * @flags:	Bitstream type
+ *	-XILINX_ZYNQMP_PM_FPGA_FULL:  FPGA full reconfiguration
+ *	-XILINX_ZYNQMP_PM_FPGA_PARTIAL: FPGA partial reconfiguration
+ *
+ * This function provides access to pmufw. To transfer
+ * the required bitstream into PL.
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_fpga_load(const u64 address, const u32 size,
+			       const u32 flags)
+{
+	return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address),
+				   upper_32_bits(address), size, flags, NULL);
+}
+
+/**
+ * zynqmp_pm_fpga_get_status - Read value from PCAP status register
+ * @value: Value to read
+ *
+ * This function provides access to the pmufw to get the PCAP
+ * status
+ *
+ * Return: Returns status, either success or error+reason
+ */
+static int zynqmp_pm_fpga_get_status(u32 *value)
+{
+	u32 ret_payload[PAYLOAD_ARG_CNT];
+	int ret;
+
+	if (!value)
+		return -EINVAL;
+
+	ret = zynqmp_pm_invoke_fn(PM_FPGA_GET_STATUS, 0, 0, 0, 0, ret_payload);
+	*value = ret_payload[1];
+
+	return ret;
+}
+
+/**
  * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller
  *			       master has initialized its own power management
  *
@@ -640,6 +685,8 @@ static const struct zynqmp_eemi_ops eemi_ops = {
 	.request_node = zynqmp_pm_request_node,
 	.release_node = zynqmp_pm_release_node,
 	.set_requirement = zynqmp_pm_set_requirement,
+	.fpga_load = zynqmp_pm_fpga_load,
+	.fpga_get_status = zynqmp_pm_fpga_get_status,
 };
 
 /**
@@ -649,7 +696,11 @@ static const struct zynqmp_eemi_ops eemi_ops = {
  */
 const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void)
 {
-	return &eemi_ops;
+	if (eemi_ops_tbl)
+		return eemi_ops_tbl;
+	else
+		return ERR_PTR(-EPROBE_DEFER);
+
 }
 EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops);
 
@@ -694,6 +745,9 @@ static int zynqmp_firmware_probe(struct platform_device *pdev)
 	pr_info("%s Trustzone version v%d.%d\n", __func__,
 		pm_tz_version >> 16, pm_tz_version & 0xFFFF);
 
+	/* Assign eemi_ops_table */
+	eemi_ops_tbl = &eemi_ops;
+
 	zynqmp_pm_api_debugfs_init();
 
 	ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs,
diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig
index c20445b867ae..d892f3efcd76 100644
--- a/drivers/fpga/Kconfig
+++ b/drivers/fpga/Kconfig
@@ -204,4 +204,13 @@ config FPGA_DFL_PCI
 
 	  To compile this as a module, choose M here.
 
+config FPGA_MGR_ZYNQMP_FPGA
+	tristate "Xilinx ZynqMP FPGA"
+	depends on ARCH_ZYNQMP || COMPILE_TEST
+	help
+	  FPGA manager driver support for Xilinx ZynqMP FPGAs.
+	  This driver uses the processor configuration port(PCAP)
+	  to configure the programmable logic(PL) through PS
+	  on ZynqMP SoC.
+
 endif # FPGA
diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile
index c0dd4c82fbdb..312b9371742f 100644
--- a/drivers/fpga/Makefile
+++ b/drivers/fpga/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_FPGA_MGR_STRATIX10_SOC)	+= stratix10-soc.o
 obj-$(CONFIG_FPGA_MGR_TS73XX)		+= ts73xx-fpga.o
 obj-$(CONFIG_FPGA_MGR_XILINX_SPI)	+= xilinx-spi.o
 obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA)	+= zynq-fpga.o
+obj-$(CONFIG_FPGA_MGR_ZYNQMP_FPGA)	+= zynqmp-fpga.o
 obj-$(CONFIG_ALTERA_PR_IP_CORE)         += altera-pr-ip-core.o
 obj-$(CONFIG_ALTERA_PR_IP_CORE_PLAT)    += altera-pr-ip-core-plat.o
 
diff --git a/drivers/fpga/zynqmp-fpga.c b/drivers/fpga/zynqmp-fpga.c
new file mode 100644
index 000000000000..f7cbaadf49ab
--- /dev/null
+++ b/drivers/fpga/zynqmp-fpga.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Xilinx, Inc.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/string.h>
+#include <linux/firmware/xlnx-zynqmp.h>
+
+/* Constant Definitions */
+#define IXR_FPGA_DONE_MASK	BIT(3)
+
+/**
+ * struct zynqmp_fpga_priv - Private data structure
+ * @dev:	Device data structure
+ * @flags:	flags which is used to identify the bitfile type
+ */
+struct zynqmp_fpga_priv {
+	struct device *dev;
+	u32 flags;
+};
+
+static int zynqmp_fpga_ops_write_init(struct fpga_manager *mgr,
+				      struct fpga_image_info *info,
+				      const char *buf, size_t size)
+{
+	struct zynqmp_fpga_priv *priv;
+
+	priv = mgr->priv;
+	priv->flags = info->flags;
+
+	return 0;
+}
+
+static int zynqmp_fpga_ops_write(struct fpga_manager *mgr,
+				 const char *buf, size_t size)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	struct zynqmp_fpga_priv *priv;
+	dma_addr_t dma_addr;
+	u32 eemi_flags = 0;
+	char *kbuf;
+	int ret;
+
+	if (!eemi_ops || !eemi_ops->fpga_load)
+		return -ENXIO;
+
+	priv = mgr->priv;
+
+	kbuf = dma_alloc_coherent(priv->dev, size, &dma_addr, GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+
+	memcpy(kbuf, buf, size);
+
+	wmb(); /* ensure all writes are done before initiate FW call */
+
+	if (priv->flags & FPGA_MGR_PARTIAL_RECONFIG)
+		eemi_flags |= XILINX_ZYNQMP_PM_FPGA_PARTIAL;
+
+	ret = eemi_ops->fpga_load(dma_addr, size, eemi_flags);
+
+	dma_free_coherent(priv->dev, size, kbuf, dma_addr);
+
+	return ret;
+}
+
+static int zynqmp_fpga_ops_write_complete(struct fpga_manager *mgr,
+					  struct fpga_image_info *info)
+{
+	return 0;
+}
+
+static enum fpga_mgr_states zynqmp_fpga_ops_state(struct fpga_manager *mgr)
+{
+	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	u32 status;
+
+	if (!eemi_ops || !eemi_ops->fpga_get_status)
+		return FPGA_MGR_STATE_UNKNOWN;
+
+	eemi_ops->fpga_get_status(&status);
+	if (status & IXR_FPGA_DONE_MASK)
+		return FPGA_MGR_STATE_OPERATING;
+
+	return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static const struct fpga_manager_ops zynqmp_fpga_ops = {
+	.state = zynqmp_fpga_ops_state,
+	.write_init = zynqmp_fpga_ops_write_init,
+	.write = zynqmp_fpga_ops_write,
+	.write_complete = zynqmp_fpga_ops_write_complete,
+};
+
+static int zynqmp_fpga_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct zynqmp_fpga_priv *priv;
+	struct fpga_manager *mgr;
+	int ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = dev;
+
+	mgr = devm_fpga_mgr_create(dev, "Xilinx ZynqMP FPGA Manager",
+				   &zynqmp_fpga_ops, priv);
+	if (!mgr)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, mgr);
+
+	ret = fpga_mgr_register(mgr);
+	if (ret) {
+		dev_err(dev, "unable to register FPGA manager");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int zynqmp_fpga_remove(struct platform_device *pdev)
+{
+	struct fpga_manager *mgr = platform_get_drvdata(pdev);
+
+	fpga_mgr_unregister(mgr);
+
+	return 0;
+}
+
+static const struct of_device_id zynqmp_fpga_of_match[] = {
+	{ .compatible = "xlnx,zynqmp-pcap-fpga", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, zynqmp_fpga_of_match);
+
+static struct platform_driver zynqmp_fpga_driver = {
+	.probe = zynqmp_fpga_probe,
+	.remove = zynqmp_fpga_remove,
+	.driver = {
+		.name = "zynqmp_fpga_manager",
+		.of_match_table = of_match_ptr(zynqmp_fpga_of_match),
+	},
+};
+
+module_platform_driver(zynqmp_fpga_driver);
+
+MODULE_AUTHOR("Nava kishore Manne <navam@xilinx.com>");
+MODULE_DESCRIPTION("Xilinx ZynqMp FPGA Manager");
+MODULE_LICENSE("GPL");
diff --git a/drivers/memory/emif.h b/drivers/memory/emif.h
index 9e9f8037955d..6b71fadb3cfa 100644
--- a/drivers/memory/emif.h
+++ b/drivers/memory/emif.h
@@ -537,6 +537,9 @@
 #define MCONNID_SHIFT					0
 #define MCONNID_MASK					(0xff << 0)
 
+/* READ_WRITE_LEVELING_CONTROL */
+#define RDWRLVLFULL_START				0x80000000
+
 /* DDR_PHY_CTRL_1 - EMIF4D */
 #define DLL_SLAVE_DLY_CTRL_SHIFT_4D			4
 #define DLL_SLAVE_DLY_CTRL_MASK_4D			(0xFF << 4)
@@ -598,6 +601,7 @@ extern struct emif_regs_amx3 ti_emif_regs_amx3;
 
 void ti_emif_save_context(void);
 void ti_emif_restore_context(void);
+void ti_emif_run_hw_leveling(void);
 void ti_emif_enter_sr(void);
 void ti_emif_exit_sr(void);
 void ti_emif_abort_sr(void);
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index 0a53598d982f..163b6c69e651 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -51,6 +51,9 @@
 #define MC_EMEM_ADR_CFG 0x54
 #define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
 
+#define MC_TIMING_CONTROL		0xfc
+#define MC_TIMING_UPDATE		BIT(0)
+
 static const struct of_device_id tegra_mc_of_match[] = {
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 	{ .compatible = "nvidia,tegra20-mc-gart", .data = &tegra20_mc_soc },
@@ -74,7 +77,7 @@ static const struct of_device_id tegra_mc_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
 
-static int terga_mc_block_dma_common(struct tegra_mc *mc,
+static int tegra_mc_block_dma_common(struct tegra_mc *mc,
 				     const struct tegra_mc_reset *rst)
 {
 	unsigned long flags;
@@ -90,13 +93,13 @@ static int terga_mc_block_dma_common(struct tegra_mc *mc,
 	return 0;
 }
 
-static bool terga_mc_dma_idling_common(struct tegra_mc *mc,
+static bool tegra_mc_dma_idling_common(struct tegra_mc *mc,
 				       const struct tegra_mc_reset *rst)
 {
 	return (mc_readl(mc, rst->status) & BIT(rst->bit)) != 0;
 }
 
-static int terga_mc_unblock_dma_common(struct tegra_mc *mc,
+static int tegra_mc_unblock_dma_common(struct tegra_mc *mc,
 				       const struct tegra_mc_reset *rst)
 {
 	unsigned long flags;
@@ -112,17 +115,17 @@ static int terga_mc_unblock_dma_common(struct tegra_mc *mc,
 	return 0;
 }
 
-static int terga_mc_reset_status_common(struct tegra_mc *mc,
+static int tegra_mc_reset_status_common(struct tegra_mc *mc,
 					const struct tegra_mc_reset *rst)
 {
 	return (mc_readl(mc, rst->control) & BIT(rst->bit)) != 0;
 }
 
-const struct tegra_mc_reset_ops terga_mc_reset_ops_common = {
-	.block_dma = terga_mc_block_dma_common,
-	.dma_idling = terga_mc_dma_idling_common,
-	.unblock_dma = terga_mc_unblock_dma_common,
-	.reset_status = terga_mc_reset_status_common,
+const struct tegra_mc_reset_ops tegra_mc_reset_ops_common = {
+	.block_dma = tegra_mc_block_dma_common,
+	.dma_idling = tegra_mc_dma_idling_common,
+	.unblock_dma = tegra_mc_unblock_dma_common,
+	.reset_status = tegra_mc_reset_status_common,
 };
 
 static inline struct tegra_mc *reset_to_mc(struct reset_controller_dev *rcdev)
@@ -282,25 +285,28 @@ static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
 	u32 value;
 
 	/* compute the number of MC clock cycles per tick */
-	tick = mc->tick * clk_get_rate(mc->clk);
+	tick = (unsigned long long)mc->tick * clk_get_rate(mc->clk);
 	do_div(tick, NSEC_PER_SEC);
 
-	value = readl(mc->regs + MC_EMEM_ARB_CFG);
+	value = mc_readl(mc, MC_EMEM_ARB_CFG);
 	value &= ~MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK;
 	value |= MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(tick);
-	writel(value, mc->regs + MC_EMEM_ARB_CFG);
+	mc_writel(mc, value, MC_EMEM_ARB_CFG);
 
 	/* write latency allowance defaults */
 	for (i = 0; i < mc->soc->num_clients; i++) {
 		const struct tegra_mc_la *la = &mc->soc->clients[i].la;
 		u32 value;
 
-		value = readl(mc->regs + la->reg);
+		value = mc_readl(mc, la->reg);
 		value &= ~(la->mask << la->shift);
 		value |= (la->def & la->mask) << la->shift;
-		writel(value, mc->regs + la->reg);
+		mc_writel(mc, value, la->reg);
 	}
 
+	/* latch new values */
+	mc_writel(mc, MC_TIMING_UPDATE, MC_TIMING_CONTROL);
+
 	return 0;
 }
 
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index 887a3b07334f..392993955c93 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -35,7 +35,7 @@ static inline void mc_writel(struct tegra_mc *mc, u32 value,
 	writel_relaxed(value, mc->regs + offset);
 }
 
-extern const struct tegra_mc_reset_ops terga_mc_reset_ops_common;
+extern const struct tegra_mc_reset_ops tegra_mc_reset_ops_common;
 
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 extern const struct tegra_mc_soc tegra20_mc_soc;
diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c
index 6560a5101322..62305fafd641 100644
--- a/drivers/memory/tegra/tegra114.c
+++ b/drivers/memory/tegra/tegra114.c
@@ -572,7 +572,7 @@ static const struct tegra_mc_client tegra114_mc_clients[] = {
 		},
 	}, {
 		.id = 0x34,
-		.name = "fdcwr2",
+		.name = "fdcdwr2",
 		.swgroup = TEGRA_SWGROUP_NV,
 		.smmu = {
 			.reg = 0x22c,
@@ -975,7 +975,7 @@ const struct tegra_mc_soc tegra114_mc_soc = {
 	.smmu = &tegra114_smmu_soc,
 	.intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
 		   MC_INT_DECERR_EMEM,
-	.reset_ops = &terga_mc_reset_ops_common,
+	.reset_ops = &tegra_mc_reset_ops_common,
 	.resets = tegra114_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra114_mc_resets),
 };
diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c
index b561a1fe7f46..8f8487bda642 100644
--- a/drivers/memory/tegra/tegra124.c
+++ b/drivers/memory/tegra/tegra124.c
@@ -1074,7 +1074,7 @@ const struct tegra_mc_soc tegra124_mc_soc = {
 	.intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
 		   MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
 		   MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
-	.reset_ops = &terga_mc_reset_ops_common,
+	.reset_ops = &tegra_mc_reset_ops_common,
 	.resets = tegra124_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra124_mc_resets),
 };
@@ -1104,7 +1104,7 @@ const struct tegra_mc_soc tegra132_mc_soc = {
 	.intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
 		   MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
 		   MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
-	.reset_ops = &terga_mc_reset_ops_common,
+	.reset_ops = &tegra_mc_reset_ops_common,
 	.resets = tegra124_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra124_mc_resets),
 };
diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c
index 7119e532471c..121237b16add 100644
--- a/drivers/memory/tegra/tegra20.c
+++ b/drivers/memory/tegra/tegra20.c
@@ -198,7 +198,7 @@ static const struct tegra_mc_reset tegra20_mc_resets[] = {
 	TEGRA20_MC_RESET(VI,     0x100, 0x178, 0x104, 14),
 };
 
-static int terga20_mc_hotreset_assert(struct tegra_mc *mc,
+static int tegra20_mc_hotreset_assert(struct tegra_mc *mc,
 				      const struct tegra_mc_reset *rst)
 {
 	unsigned long flags;
@@ -214,7 +214,7 @@ static int terga20_mc_hotreset_assert(struct tegra_mc *mc,
 	return 0;
 }
 
-static int terga20_mc_hotreset_deassert(struct tegra_mc *mc,
+static int tegra20_mc_hotreset_deassert(struct tegra_mc *mc,
 					const struct tegra_mc_reset *rst)
 {
 	unsigned long flags;
@@ -230,7 +230,7 @@ static int terga20_mc_hotreset_deassert(struct tegra_mc *mc,
 	return 0;
 }
 
-static int terga20_mc_block_dma(struct tegra_mc *mc,
+static int tegra20_mc_block_dma(struct tegra_mc *mc,
 				const struct tegra_mc_reset *rst)
 {
 	unsigned long flags;
@@ -246,19 +246,19 @@ static int terga20_mc_block_dma(struct tegra_mc *mc,
 	return 0;
 }
 
-static bool terga20_mc_dma_idling(struct tegra_mc *mc,
+static bool tegra20_mc_dma_idling(struct tegra_mc *mc,
 				  const struct tegra_mc_reset *rst)
 {
 	return mc_readl(mc, rst->status) == 0;
 }
 
-static int terga20_mc_reset_status(struct tegra_mc *mc,
+static int tegra20_mc_reset_status(struct tegra_mc *mc,
 				   const struct tegra_mc_reset *rst)
 {
 	return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0;
 }
 
-static int terga20_mc_unblock_dma(struct tegra_mc *mc,
+static int tegra20_mc_unblock_dma(struct tegra_mc *mc,
 				  const struct tegra_mc_reset *rst)
 {
 	unsigned long flags;
@@ -274,13 +274,13 @@ static int terga20_mc_unblock_dma(struct tegra_mc *mc,
 	return 0;
 }
 
-const struct tegra_mc_reset_ops terga20_mc_reset_ops = {
-	.hotreset_assert = terga20_mc_hotreset_assert,
-	.hotreset_deassert = terga20_mc_hotreset_deassert,
-	.block_dma = terga20_mc_block_dma,
-	.dma_idling = terga20_mc_dma_idling,
-	.unblock_dma = terga20_mc_unblock_dma,
-	.reset_status = terga20_mc_reset_status,
+static const struct tegra_mc_reset_ops tegra20_mc_reset_ops = {
+	.hotreset_assert = tegra20_mc_hotreset_assert,
+	.hotreset_deassert = tegra20_mc_hotreset_deassert,
+	.block_dma = tegra20_mc_block_dma,
+	.dma_idling = tegra20_mc_dma_idling,
+	.unblock_dma = tegra20_mc_unblock_dma,
+	.reset_status = tegra20_mc_reset_status,
 };
 
 const struct tegra_mc_soc tegra20_mc_soc = {
@@ -290,7 +290,7 @@ const struct tegra_mc_soc tegra20_mc_soc = {
 	.client_id_mask = 0x3f,
 	.intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
 		   MC_INT_DECERR_EMEM,
-	.reset_ops = &terga20_mc_reset_ops,
+	.reset_ops = &tegra20_mc_reset_ops,
 	.resets = tegra20_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra20_mc_resets),
 };
diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c
index d00a77160407..aa22cda637eb 100644
--- a/drivers/memory/tegra/tegra210.c
+++ b/drivers/memory/tegra/tegra210.c
@@ -1132,7 +1132,7 @@ const struct tegra_mc_soc tegra210_mc_soc = {
 	.intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
 		   MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
 		   MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
-	.reset_ops = &terga_mc_reset_ops_common,
+	.reset_ops = &tegra_mc_reset_ops_common,
 	.resets = tegra210_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra210_mc_resets),
 };
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
index bee5314ed404..c9af0f682ead 100644
--- a/drivers/memory/tegra/tegra30.c
+++ b/drivers/memory/tegra/tegra30.c
@@ -726,7 +726,7 @@ static const struct tegra_mc_client tegra30_mc_clients[] = {
 		},
 	}, {
 		.id = 0x34,
-		.name = "fdcwr2",
+		.name = "fdcdwr2",
 		.swgroup = TEGRA_SWGROUP_NV2,
 		.smmu = {
 			.reg = 0x22c,
@@ -999,7 +999,7 @@ const struct tegra_mc_soc tegra30_mc_soc = {
 	.smmu = &tegra30_smmu_soc,
 	.intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
 		   MC_INT_DECERR_EMEM,
-	.reset_ops = &terga_mc_reset_ops_common,
+	.reset_ops = &tegra_mc_reset_ops_common,
 	.resets = tegra30_mc_resets,
 	.num_resets = ARRAY_SIZE(tegra30_mc_resets),
 };
diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c
index 2250d03ea17f..ab07aa163138 100644
--- a/drivers/memory/ti-emif-pm.c
+++ b/drivers/memory/ti-emif-pm.c
@@ -138,6 +138,9 @@ static int ti_emif_alloc_sram(struct device *dev,
 	emif_data->pm_functions.exit_sr =
 		sram_resume_address(emif_data,
 				    (unsigned long)ti_emif_exit_sr);
+	emif_data->pm_functions.run_hw_leveling =
+		sram_resume_address(emif_data,
+				    (unsigned long)ti_emif_run_hw_leveling);
 
 	emif_data->pm_data.regs_virt =
 		(struct emif_regs_amx3 *)emif_data->ti_emif_sram_data_virt;
diff --git a/drivers/memory/ti-emif-sram-pm.S b/drivers/memory/ti-emif-sram-pm.S
index a5369181e5c2..d75ae18efa7d 100644
--- a/drivers/memory/ti-emif-sram-pm.S
+++ b/drivers/memory/ti-emif-sram-pm.S
@@ -27,6 +27,7 @@
 #define EMIF_POWER_MGMT_SELF_REFRESH_MODE_MASK		0x0700
 
 #define EMIF_SDCFG_TYPE_DDR2				0x2 << SDRAM_TYPE_SHIFT
+#define EMIF_SDCFG_TYPE_DDR3				0x3 << SDRAM_TYPE_SHIFT
 #define EMIF_STATUS_READY				0x4
 
 #define AM43XX_EMIF_PHY_CTRL_REG_COUNT                  0x120
@@ -245,6 +246,46 @@ emif_skip_restore_extra_regs:
 ENDPROC(ti_emif_restore_context)
 
 /*
+ * void ti_emif_run_hw_leveling(void)
+ *
+ * Used during resume to run hardware leveling again and restore the
+ * configuration of the EMIF PHY, only for DDR3.
+ */
+ENTRY(ti_emif_run_hw_leveling)
+	adr	r4, ti_emif_pm_sram_data
+	ldr	r0, [r4, #EMIF_PM_BASE_ADDR_PHYS_OFFSET]
+
+	ldr	r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
+	orr	r3, r3, #RDWRLVLFULL_START
+	ldr	r2, [r0, #EMIF_SDRAM_CONFIG]
+	and	r2, r2, #SDRAM_TYPE_MASK
+	cmp	r2, #EMIF_SDCFG_TYPE_DDR3
+	bne	skip_hwlvl
+
+	str	r3, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
+
+	/*
+	 * If EMIF registers are touched during initial stage of HW
+	 * leveling sequence there will be an L3 NOC timeout error issued
+	 * as the EMIF will not respond, which is not fatal, but it is
+	 * avoidable. This small wait loop is enough time for this condition
+	 * to clear, even at worst case of CPU running at max speed of 1Ghz.
+	 */
+	mov	r2, #0x2000
+1:
+	subs	r2, r2, #0x1
+	bne	1b
+
+	/* Bit clears when operation is complete */
+2:	ldr     r1, [r0, #EMIF_READ_WRITE_LEVELING_CONTROL]
+	tst     r1, #RDWRLVLFULL_START
+	bne     2b
+
+skip_hwlvl:
+	mov	pc, lr
+ENDPROC(ti_emif_run_hw_leveling)
+
+/*
  * void ti_emif_enter_sr(void)
  *
  * Programs the EMIF to tell the SDRAM to enter into self-refresh
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 3209ee020b15..b80cb6af0cb4 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -496,30 +496,6 @@ config VEXPRESS_SYSCFG
 	  bus. System Configuration interface is one of the possible means
 	  of generating transactions on this bus.
 
-config ASPEED_P2A_CTRL
-	depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
-	tristate "Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC bridge control"
-	help
-	  Control Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC mappings through
-	  ioctl()s, the driver also provides an interface for userspace mappings to
-	  a pre-defined region.
-
-config ASPEED_LPC_CTRL
-	depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
-	tristate "Aspeed ast2400/2500 HOST LPC to BMC bridge control"
-	---help---
-	  Control Aspeed ast2400/2500 HOST LPC to BMC mappings through
-	  ioctl()s, the driver also provides a read/write interface to a BMC ram
-	  region where the host LPC read/write region can be buffered.
-
-config ASPEED_LPC_SNOOP
-	tristate "Aspeed ast2500 HOST LPC snoop support"
-	depends on (ARCH_ASPEED || COMPILE_TEST) && REGMAP && MFD_SYSCON
-	help
-	  Provides a driver to control the LPC snoop interface which
-	  allows the BMC to listen on and save the data written by
-	  the host to an arbitrary LPC I/O port.
-
 config PCI_ENDPOINT_TEST
 	depends on PCI
 	select CRC32
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index c36239573a5c..b9affcdaa3d6 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -54,9 +54,6 @@ obj-$(CONFIG_GENWQE)		+= genwqe/
 obj-$(CONFIG_ECHO)		+= echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)		+= cxl/
-obj-$(CONFIG_ASPEED_LPC_CTRL)	+= aspeed-lpc-ctrl.o
-obj-$(CONFIG_ASPEED_LPC_SNOOP)	+= aspeed-lpc-snoop.o
-obj-$(CONFIG_ASPEED_P2A_CTRL)	+= aspeed-p2a-ctrl.o
 obj-$(CONFIG_PCI_ENDPOINT_TEST)	+= pci_endpoint_test.o
 obj-$(CONFIG_OCXL)		+= ocxl/
 obj-y				+= cardreader/
diff --git a/drivers/nvmem/zynqmp_nvmem.c b/drivers/nvmem/zynqmp_nvmem.c
index 490c8fcaec80..5893543918c8 100644
--- a/drivers/nvmem/zynqmp_nvmem.c
+++ b/drivers/nvmem/zynqmp_nvmem.c
@@ -16,6 +16,8 @@ struct zynqmp_nvmem_data {
 	struct nvmem_device *nvmem;
 };
 
+static const struct zynqmp_eemi_ops *eemi_ops;
+
 static int zynqmp_nvmem_read(void *context, unsigned int offset,
 			     void *val, size_t bytes)
 {
@@ -23,9 +25,7 @@ static int zynqmp_nvmem_read(void *context, unsigned int offset,
 	int idcode, version;
 	struct zynqmp_nvmem_data *priv = context;
 
-	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
-
-	if (!eemi_ops || !eemi_ops->get_chipid)
+	if (!eemi_ops->get_chipid)
 		return -ENXIO;
 
 	ret = eemi_ops->get_chipid(&idcode, &version);
@@ -61,6 +61,10 @@ static int zynqmp_nvmem_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
 	priv->dev = dev;
 	econfig.dev = dev;
 	econfig.reg_read = zynqmp_nvmem_read;
diff --git a/drivers/reset/reset-zynqmp.c b/drivers/reset/reset-zynqmp.c
index 2ef1f13aa47b..99e75d92dada 100644
--- a/drivers/reset/reset-zynqmp.c
+++ b/drivers/reset/reset-zynqmp.c
@@ -79,11 +79,11 @@ static int zynqmp_reset_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
-	platform_set_drvdata(pdev, priv);
-
 	priv->eemi_ops = zynqmp_pm_get_eemi_ops();
-	if (!priv->eemi_ops)
-		return -ENXIO;
+	if (IS_ERR(priv->eemi_ops))
+		return PTR_ERR(priv->eemi_ops);
+
+	platform_set_drvdata(pdev, priv);
 
 	priv->rcdev.ops = &zynqmp_reset_ops;
 	priv->rcdev.owner = THIS_MODULE;
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 32994b0dd139..a2941c875a06 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -403,15 +403,12 @@ static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 
 static struct omap_rtc *omap_rtc_power_off_rtc;
 
-/*
- * omap_rtc_poweroff: RTC-controlled power off
- *
- * The RTC can be used to control an external PMIC via the pmic_power_en pin,
- * which can be configured to transition to OFF on ALARM2 events.
- *
- * Called with local interrupts disabled.
+/**
+ * omap_rtc_power_off_program: Set the pmic power off sequence. The RTC
+ * generates pmic_pwr_enable control, which can be used to control an external
+ * PMIC.
  */
-static void omap_rtc_power_off(void)
+int omap_rtc_power_off_program(struct device *dev)
 {
 	struct omap_rtc *rtc = omap_rtc_power_off_rtc;
 	struct rtc_time tm;
@@ -425,6 +422,9 @@ static void omap_rtc_power_off(void)
 	rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN);
 
 again:
+	/* Clear any existing ALARM2 event */
+	rtc_writel(rtc, OMAP_RTC_STATUS_REG, OMAP_RTC_STATUS_ALARM2);
+
 	/* set alarm one second from now */
 	omap_rtc_read_time_raw(rtc, &tm);
 	seconds = tm.tm_sec;
@@ -461,6 +461,39 @@ again:
 
 	rtc->type->lock(rtc);
 
+	return 0;
+}
+EXPORT_SYMBOL(omap_rtc_power_off_program);
+
+/*
+ * omap_rtc_poweroff: RTC-controlled power off
+ *
+ * The RTC can be used to control an external PMIC via the pmic_power_en pin,
+ * which can be configured to transition to OFF on ALARM2 events.
+ *
+ * Notes:
+ * The one-second alarm offset is the shortest offset possible as the alarm
+ * registers must be set before the next timer update and the offset
+ * calculation is too heavy for everything to be done within a single access
+ * period (~15 us).
+ *
+ * Called with local interrupts disabled.
+ */
+static void omap_rtc_power_off(void)
+{
+	struct rtc_device *rtc = omap_rtc_power_off_rtc->rtc;
+	u32 val;
+
+	omap_rtc_power_off_program(rtc->dev.parent);
+
+	/* Set PMIC power enable and EXT_WAKEUP in case PB power on is used */
+	omap_rtc_power_off_rtc->type->unlock(omap_rtc_power_off_rtc);
+	val = rtc_readl(omap_rtc_power_off_rtc, OMAP_RTC_PMIC_REG);
+	val |= OMAP_RTC_PMIC_POWER_EN_EN | OMAP_RTC_PMIC_EXT_WKUP_POL(0) |
+			OMAP_RTC_PMIC_EXT_WKUP_EN(0);
+	rtc_writel(omap_rtc_power_off_rtc, OMAP_RTC_PMIC_REG, val);
+	omap_rtc_power_off_rtc->type->lock(omap_rtc_power_off_rtc);
+
 	/*
 	 * Wait for alarm to trigger (within one second) and external PMIC to
 	 * power off the system. Add a 500 ms margin for external latencies
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index ae9bf20b26fa..75bdbb2c5140 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -2,6 +2,7 @@ menu "SOC (System On Chip) specific Drivers"
 
 source "drivers/soc/actions/Kconfig"
 source "drivers/soc/amlogic/Kconfig"
+source "drivers/soc/aspeed/Kconfig"
 source "drivers/soc/atmel/Kconfig"
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/fsl/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index c7c1a139ad8d..524ecdc2a9bb 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -4,6 +4,7 @@
 #
 
 obj-$(CONFIG_ARCH_ACTIONS)	+= actions/
+obj-$(CONFIG_SOC_ASPEED)	+= aspeed/
 obj-$(CONFIG_ARCH_AT91)		+= atmel/
 obj-y				+= bcm/
 obj-$(CONFIG_ARCH_DOVE)		+= dove/
diff --git a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c
index 6289965c42e9..511b6856225d 100644
--- a/drivers/soc/amlogic/meson-gx-pwrc-vpu.c
+++ b/drivers/soc/amlogic/meson-gx-pwrc-vpu.c
@@ -11,6 +11,7 @@
 #include <linux/bitfield.h>
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
+#include <linux/of_device.h>
 #include <linux/reset.h>
 #include <linux/clk.h>
 
@@ -26,6 +27,7 @@
 #define HHI_MEM_PD_REG0			(0x40 << 2)
 #define HHI_VPU_MEM_PD_REG0		(0x41 << 2)
 #define HHI_VPU_MEM_PD_REG1		(0x42 << 2)
+#define HHI_VPU_MEM_PD_REG2		(0x4d << 2)
 
 struct meson_gx_pwrc_vpu {
 	struct generic_pm_domain genpd;
@@ -54,12 +56,55 @@ static int meson_gx_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
 	/* Power Down Memories */
 	for (i = 0; i < 32; i += 2) {
 		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
-				   0x2 << i, 0x3 << i);
+				   0x3 << i, 0x3 << i);
 		udelay(5);
 	}
 	for (i = 0; i < 32; i += 2) {
 		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
-				   0x2 << i, 0x3 << i);
+				   0x3 << i, 0x3 << i);
+		udelay(5);
+	}
+	for (i = 8; i < 16; i++) {
+		regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
+				   BIT(i), BIT(i));
+		udelay(5);
+	}
+	udelay(20);
+
+	regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI, GEN_PWR_VPU_HDMI);
+
+	msleep(20);
+
+	clk_disable_unprepare(pd->vpu_clk);
+	clk_disable_unprepare(pd->vapb_clk);
+
+	return 0;
+}
+
+static int meson_g12a_pwrc_vpu_power_off(struct generic_pm_domain *genpd)
+{
+	struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
+	int i;
+
+	regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI_ISO, GEN_PWR_VPU_HDMI_ISO);
+	udelay(20);
+
+	/* Power Down Memories */
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+				   0x3 << i, 0x3 << i);
+		udelay(5);
+	}
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+				   0x3 << i, 0x3 << i);
+		udelay(5);
+	}
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+				   0x3 << i, 0x3 << i);
 		udelay(5);
 	}
 	for (i = 8; i < 16; i++) {
@@ -108,13 +153,67 @@ static int meson_gx_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
 	/* Power Up Memories */
 	for (i = 0; i < 32; i += 2) {
 		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
-				   0x2 << i, 0);
+				   0x3 << i, 0);
+		udelay(5);
+	}
+
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
+				   0x3 << i, 0);
+		udelay(5);
+	}
+
+	for (i = 8; i < 16; i++) {
+		regmap_update_bits(pd->regmap_hhi, HHI_MEM_PD_REG0,
+				   BIT(i), 0);
+		udelay(5);
+	}
+	udelay(20);
+
+	ret = reset_control_assert(pd->rstc);
+	if (ret)
+		return ret;
+
+	regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI_ISO, 0);
+
+	ret = reset_control_deassert(pd->rstc);
+	if (ret)
+		return ret;
+
+	ret = meson_gx_pwrc_vpu_setup_clk(pd);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int meson_g12a_pwrc_vpu_power_on(struct generic_pm_domain *genpd)
+{
+	struct meson_gx_pwrc_vpu *pd = genpd_to_pd(genpd);
+	int ret;
+	int i;
+
+	regmap_update_bits(pd->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
+			   GEN_PWR_VPU_HDMI, 0);
+	udelay(20);
+
+	/* Power Up Memories */
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG0,
+				   0x3 << i, 0);
 		udelay(5);
 	}
 
 	for (i = 0; i < 32; i += 2) {
 		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG1,
-				   0x2 << i, 0);
+				   0x3 << i, 0);
+		udelay(5);
+	}
+
+	for (i = 0; i < 32; i += 2) {
+		regmap_update_bits(pd->regmap_hhi, HHI_VPU_MEM_PD_REG2,
+				   0x3 << i, 0);
 		udelay(5);
 	}
 
@@ -160,15 +259,37 @@ static struct meson_gx_pwrc_vpu vpu_hdmi_pd = {
 	},
 };
 
+static struct meson_gx_pwrc_vpu vpu_hdmi_pd_g12a = {
+	.genpd = {
+		.name = "vpu_hdmi",
+		.power_off = meson_g12a_pwrc_vpu_power_off,
+		.power_on = meson_g12a_pwrc_vpu_power_on,
+	},
+};
+
 static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
 {
+	const struct meson_gx_pwrc_vpu *vpu_pd_match;
 	struct regmap *regmap_ao, *regmap_hhi;
+	struct meson_gx_pwrc_vpu *vpu_pd;
 	struct reset_control *rstc;
 	struct clk *vpu_clk;
 	struct clk *vapb_clk;
 	bool powered_off;
 	int ret;
 
+	vpu_pd_match = of_device_get_match_data(&pdev->dev);
+	if (!vpu_pd_match) {
+		dev_err(&pdev->dev, "failed to get match data\n");
+		return -ENODEV;
+	}
+
+	vpu_pd = devm_kzalloc(&pdev->dev, sizeof(*vpu_pd), GFP_KERNEL);
+	if (!vpu_pd)
+		return -ENOMEM;
+
+	memcpy(vpu_pd, vpu_pd_match, sizeof(*vpu_pd));
+
 	regmap_ao = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node));
 	if (IS_ERR(regmap_ao)) {
 		dev_err(&pdev->dev, "failed to get regmap\n");
@@ -201,39 +322,46 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
 		return PTR_ERR(vapb_clk);
 	}
 
-	vpu_hdmi_pd.regmap_ao = regmap_ao;
-	vpu_hdmi_pd.regmap_hhi = regmap_hhi;
-	vpu_hdmi_pd.rstc = rstc;
-	vpu_hdmi_pd.vpu_clk = vpu_clk;
-	vpu_hdmi_pd.vapb_clk = vapb_clk;
+	vpu_pd->regmap_ao = regmap_ao;
+	vpu_pd->regmap_hhi = regmap_hhi;
+	vpu_pd->rstc = rstc;
+	vpu_pd->vpu_clk = vpu_clk;
+	vpu_pd->vapb_clk = vapb_clk;
+
+	platform_set_drvdata(pdev, vpu_pd);
 
-	powered_off = meson_gx_pwrc_vpu_get_power(&vpu_hdmi_pd);
+	powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd);
 
 	/* If already powered, sync the clock states */
 	if (!powered_off) {
-		ret = meson_gx_pwrc_vpu_setup_clk(&vpu_hdmi_pd);
+		ret = meson_gx_pwrc_vpu_setup_clk(vpu_pd);
 		if (ret)
 			return ret;
 	}
 
-	pm_genpd_init(&vpu_hdmi_pd.genpd, &pm_domain_always_on_gov,
+	pm_genpd_init(&vpu_pd->genpd, &pm_domain_always_on_gov,
 		      powered_off);
 
 	return of_genpd_add_provider_simple(pdev->dev.of_node,
-					    &vpu_hdmi_pd.genpd);
+					    &vpu_pd->genpd);
 }
 
 static void meson_gx_pwrc_vpu_shutdown(struct platform_device *pdev)
 {
+	struct meson_gx_pwrc_vpu *vpu_pd = platform_get_drvdata(pdev);
 	bool powered_off;
 
-	powered_off = meson_gx_pwrc_vpu_get_power(&vpu_hdmi_pd);
+	powered_off = meson_gx_pwrc_vpu_get_power(vpu_pd);
 	if (!powered_off)
-		meson_gx_pwrc_vpu_power_off(&vpu_hdmi_pd.genpd);
+		vpu_pd->genpd.power_off(&vpu_pd->genpd);
 }
 
 static const struct of_device_id meson_gx_pwrc_vpu_match_table[] = {
-	{ .compatible = "amlogic,meson-gx-pwrc-vpu" },
+	{ .compatible = "amlogic,meson-gx-pwrc-vpu", .data = &vpu_hdmi_pd },
+	{
+	  .compatible = "amlogic,meson-g12a-pwrc-vpu",
+	  .data = &vpu_hdmi_pd_g12a
+	},
 	{ /* sentinel */ }
 };
 
diff --git a/drivers/soc/amlogic/meson-gx-socinfo.c b/drivers/soc/amlogic/meson-gx-socinfo.c
index 37ea0a1c24c8..bca34954518e 100644
--- a/drivers/soc/amlogic/meson-gx-socinfo.c
+++ b/drivers/soc/amlogic/meson-gx-socinfo.c
@@ -37,26 +37,34 @@ static const struct meson_gx_soc_id {
 	{ "AXG", 0x25 },
 	{ "GXLX", 0x26 },
 	{ "TXHD", 0x27 },
+	{ "G12A", 0x28 },
+	{ "G12B", 0x29 },
 };
 
 static const struct meson_gx_package_id {
 	const char *name;
 	unsigned int major_id;
 	unsigned int pack_id;
+	unsigned int pack_mask;
 } soc_packages[] = {
-	{ "S905", 0x1f, 0 },
-	{ "S905H", 0x1f, 0x13 },
-	{ "S905M", 0x1f, 0x20 },
-	{ "S905D", 0x21, 0 },
-	{ "S905X", 0x21, 0x80 },
-	{ "S905W", 0x21, 0xa0 },
-	{ "S905L", 0x21, 0xc0 },
-	{ "S905M2", 0x21, 0xe0 },
-	{ "S912", 0x22, 0 },
-	{ "962X", 0x24, 0x10 },
-	{ "962E", 0x24, 0x20 },
-	{ "A113X", 0x25, 0x37 },
-	{ "A113D", 0x25, 0x22 },
+	{ "S905", 0x1f, 0, 0x20 }, /* pack_id != 0x20 */
+	{ "S905H", 0x1f, 0x3, 0xf }, /* pack_id & 0xf == 0x3 */
+	{ "S905M", 0x1f, 0x20, 0xf0 }, /* pack_id == 0x20 */
+	{ "S905D", 0x21, 0, 0xf0 },
+	{ "S905X", 0x21, 0x80, 0xf0 },
+	{ "S905W", 0x21, 0xa0, 0xf0 },
+	{ "S905L", 0x21, 0xc0, 0xf0 },
+	{ "S905M2", 0x21, 0xe0, 0xf0 },
+	{ "S805X", 0x21, 0x30, 0xf0 },
+	{ "S805Y", 0x21, 0xb0, 0xf0 },
+	{ "S912", 0x22, 0, 0x0 }, /* Only S912 is known for GXM */
+	{ "962X", 0x24, 0x10, 0xf0 },
+	{ "962E", 0x24, 0x20, 0xf0 },
+	{ "A113X", 0x25, 0x37, 0xff },
+	{ "A113D", 0x25, 0x22, 0xff },
+	{ "S905D2", 0x28, 0x10, 0xf0 },
+	{ "S905X2", 0x28, 0x40, 0xf0 },
+	{ "S922X", 0x29, 0x40, 0xf0 },
 };
 
 static inline unsigned int socinfo_to_major(u32 socinfo)
@@ -81,13 +89,14 @@ static inline unsigned int socinfo_to_misc(u32 socinfo)
 
 static const char *socinfo_to_package_id(u32 socinfo)
 {
-	unsigned int pack = socinfo_to_pack(socinfo) & 0xf0;
+	unsigned int pack = socinfo_to_pack(socinfo);
 	unsigned int major = socinfo_to_major(socinfo);
 	int i;
 
 	for (i = 0 ; i < ARRAY_SIZE(soc_packages) ; ++i) {
 		if (soc_packages[i].major_id == major &&
-		    soc_packages[i].pack_id == pack)
+		    soc_packages[i].pack_id ==
+				(pack & soc_packages[i].pack_mask))
 			return soc_packages[i].name;
 	}
 
@@ -123,8 +132,10 @@ static int __init meson_gx_socinfo_init(void)
 		return -ENODEV;
 
 	/* check if interface is enabled */
-	if (!of_device_is_available(np))
+	if (!of_device_is_available(np)) {
+		of_node_put(np);
 		return -ENODEV;
+	}
 
 	/* check if chip-id is available */
 	if (!of_property_read_bool(np, "amlogic,has-chip-id"))
diff --git a/drivers/soc/aspeed/Kconfig b/drivers/soc/aspeed/Kconfig
new file mode 100644
index 000000000000..765d10191387
--- /dev/null
+++ b/drivers/soc/aspeed/Kconfig
@@ -0,0 +1,31 @@
+menu "Aspeed SoC drivers"
+
+config SOC_ASPEED
+	def_bool y
+	depends on ARCH_ASPEED || COMPILE_TEST
+
+config ASPEED_LPC_CTRL
+	depends on SOC_ASPEED && REGMAP && MFD_SYSCON
+	tristate "Aspeed ast2400/2500 HOST LPC to BMC bridge control"
+	---help---
+	  Control Aspeed ast2400/2500 HOST LPC to BMC mappings through
+	  ioctl()s, the driver also provides a read/write interface to a BMC ram
+	  region where the host LPC read/write region can be buffered.
+
+config ASPEED_LPC_SNOOP
+	tristate "Aspeed ast2500 HOST LPC snoop support"
+	depends on SOC_ASPEED && REGMAP && MFD_SYSCON
+	help
+	  Provides a driver to control the LPC snoop interface which
+	  allows the BMC to listen on and save the data written by
+	  the host to an arbitrary LPC I/O port.
+
+config ASPEED_P2A_CTRL
+	depends on SOC_ASPEED && REGMAP && MFD_SYSCON
+	tristate "Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC bridge control"
+	help
+	  Control Aspeed ast2400/2500 HOST P2A VGA MMIO to BMC mappings through
+	  ioctl()s, the driver also provides an interface for userspace mappings to
+	  a pre-defined region.
+
+endmenu
diff --git a/drivers/soc/aspeed/Makefile b/drivers/soc/aspeed/Makefile
new file mode 100644
index 000000000000..2f7b6da7be79
--- /dev/null
+++ b/drivers/soc/aspeed/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_ASPEED_LPC_CTRL)	+= aspeed-lpc-ctrl.o
+obj-$(CONFIG_ASPEED_LPC_SNOOP)	+= aspeed-lpc-snoop.o
+obj-$(CONFIG_ASPEED_P2A_CTRL)	+= aspeed-p2a-ctrl.o
diff --git a/drivers/misc/aspeed-lpc-ctrl.c b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
index a024f8042259..a024f8042259 100644
--- a/drivers/misc/aspeed-lpc-ctrl.c
+++ b/drivers/soc/aspeed/aspeed-lpc-ctrl.c
diff --git a/drivers/misc/aspeed-lpc-snoop.c b/drivers/soc/aspeed/aspeed-lpc-snoop.c
index 2feb4347d67f..2feb4347d67f 100644
--- a/drivers/misc/aspeed-lpc-snoop.c
+++ b/drivers/soc/aspeed/aspeed-lpc-snoop.c
diff --git a/drivers/misc/aspeed-p2a-ctrl.c b/drivers/soc/aspeed/aspeed-p2a-ctrl.c
index b60fbeaffcbd..b60fbeaffcbd 100644
--- a/drivers/misc/aspeed-p2a-ctrl.c
+++ b/drivers/soc/aspeed/aspeed-p2a-ctrl.c
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
index 506a6f3c2b9b..d6b529e06d9a 100644
--- a/drivers/soc/imx/Makefile
+++ b/drivers/soc/imx/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
 obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
+obj-$(CONFIG_ARCH_MXC) += soc-imx8.o
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
index 29b43651c261..d9231bd3c691 100644
--- a/drivers/soc/imx/gpc.c
+++ b/drivers/soc/imx/gpc.c
@@ -406,7 +406,6 @@ static int imx_gpc_probe(struct platform_device *pdev)
 	const struct imx_gpc_dt_data *of_id_data = of_id->data;
 	struct device_node *pgc_node;
 	struct regmap *regmap;
-	struct resource *res;
 	void __iomem *base;
 	int ret;
 
@@ -417,8 +416,7 @@ static int imx_gpc_probe(struct platform_device *pdev)
 	    !pgc_node)
 		return 0;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(&pdev->dev, res);
+	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index 176f473127b6..31b8d002d855 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -136,8 +136,8 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
 		GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
 	const bool enable_power_control = !on;
 	const bool has_regulator = !IS_ERR(domain->regulator);
-	unsigned long deadline;
 	int i, ret = 0;
+	u32 pxx_req;
 
 	regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
 			   domain->bits.map, domain->bits.map);
@@ -169,30 +169,19 @@ static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
 	 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
 	 * for PUP_REQ/PDN_REQ bit to be cleared
 	 */
-	deadline = jiffies + msecs_to_jiffies(1);
-	while (true) {
-		u32 pxx_req;
-
-		regmap_read(domain->regmap, offset, &pxx_req);
-
-		if (!(pxx_req & domain->bits.pxx))
-			break;
-
-		if (time_after(jiffies, deadline)) {
-			dev_err(domain->dev, "falied to command PGC\n");
-			ret = -ETIMEDOUT;
-			/*
-			 * If we were in a process of enabling a
-			 * domain and failed we might as well disable
-			 * the regulator we just enabled. And if it
-			 * was the opposite situation and we failed to
-			 * power down -- keep the regulator on
-			 */
-			on = !on;
-			break;
-		}
-
-		cpu_relax();
+	ret = regmap_read_poll_timeout(domain->regmap, offset, pxx_req,
+				       !(pxx_req & domain->bits.pxx),
+				       0, USEC_PER_MSEC);
+	if (ret) {
+		dev_err(domain->dev, "failed to command PGC\n");
+		/*
+		 * If we were in a process of enabling a
+		 * domain and failed we might as well disable
+		 * the regulator we just enabled. And if it
+		 * was the opposite situation and we failed to
+		 * power down -- keep the regulator on
+		 */
+		on = !on;
 	}
 
 	if (enable_power_control)
@@ -574,7 +563,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
 	struct device *dev = &pdev->dev;
 	struct device_node *pgc_np, *np;
 	struct regmap *regmap;
-	struct resource *res;
 	void __iomem *base;
 	int ret;
 
@@ -584,8 +572,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	res  = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	base = devm_ioremap_resource(dev, res);
+	base = devm_platform_ioremap_resource(pdev, 0);
 	if (IS_ERR(base))
 		return PTR_ERR(base);
 
diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c
new file mode 100644
index 000000000000..fc6429f9170a
--- /dev/null
+++ b/drivers/soc/imx/soc-imx8.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 NXP.
+ */
+
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#define REV_B1				0x21
+
+#define IMX8MQ_SW_INFO_B1		0x40
+#define IMX8MQ_SW_MAGIC_B1		0xff0055aa
+
+struct imx8_soc_data {
+	char *name;
+	u32 (*soc_revision)(void);
+};
+
+static u32 __init imx8mq_soc_revision(void)
+{
+	struct device_node *np;
+	void __iomem *ocotp_base;
+	u32 magic;
+	u32 rev = 0;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
+	if (!np)
+		goto out;
+
+	ocotp_base = of_iomap(np, 0);
+	WARN_ON(!ocotp_base);
+
+	magic = readl_relaxed(ocotp_base + IMX8MQ_SW_INFO_B1);
+	if (magic == IMX8MQ_SW_MAGIC_B1)
+		rev = REV_B1;
+
+	iounmap(ocotp_base);
+
+out:
+	of_node_put(np);
+	return rev;
+}
+
+static const struct imx8_soc_data imx8mq_soc_data = {
+	.name = "i.MX8MQ",
+	.soc_revision = imx8mq_soc_revision,
+};
+
+static const struct of_device_id imx8_soc_match[] = {
+	{ .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, },
+	{ }
+};
+
+#define imx8_revision(soc_rev) \
+	soc_rev ? \
+	kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf,  soc_rev & 0xf) : \
+	"unknown"
+
+static int __init imx8_soc_init(void)
+{
+	struct soc_device_attribute *soc_dev_attr;
+	struct soc_device *soc_dev;
+	struct device_node *root;
+	const struct of_device_id *id;
+	u32 soc_rev = 0;
+	const struct imx8_soc_data *data;
+	int ret;
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return -ENODEV;
+
+	soc_dev_attr->family = "Freescale i.MX";
+
+	root = of_find_node_by_path("/");
+	ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
+	if (ret)
+		goto free_soc;
+
+	id = of_match_node(imx8_soc_match, root);
+	if (!id)
+		goto free_soc;
+
+	of_node_put(root);
+
+	data = id->data;
+	if (data) {
+		soc_dev_attr->soc_id = data->name;
+		if (data->soc_revision)
+			soc_rev = data->soc_revision();
+	}
+
+	soc_dev_attr->revision = imx8_revision(soc_rev);
+	if (!soc_dev_attr->revision)
+		goto free_soc;
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR(soc_dev))
+		goto free_rev;
+
+	return 0;
+
+free_rev:
+	kfree(soc_dev_attr->revision);
+free_soc:
+	kfree(soc_dev_attr);
+	of_node_put(root);
+	return -ENODEV;
+}
+device_initcall(imx8_soc_init);
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 8236a6c87e19..c4449a163991 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -381,6 +381,10 @@ enum pwrap_regs {
 	PWRAP_EXT_GPS_AUXADC_RDATA_ADDR,
 	PWRAP_GPSINF_0_STA,
 	PWRAP_GPSINF_1_STA,
+
+	/* MT8516 only regs */
+	PWRAP_OP_TYPE,
+	PWRAP_MSB_FIRST,
 };
 
 static int mt2701_regs[] = {
@@ -852,6 +856,91 @@ static int mt8183_regs[] = {
 	[PWRAP_WACS2_VLDCLR] =			0xC28,
 };
 
+static int mt8516_regs[] = {
+	[PWRAP_MUX_SEL] =		0x0,
+	[PWRAP_WRAP_EN] =		0x4,
+	[PWRAP_DIO_EN] =		0x8,
+	[PWRAP_SIDLY] =			0xc,
+	[PWRAP_RDDMY] =			0x10,
+	[PWRAP_SI_CK_CON] =		0x14,
+	[PWRAP_CSHEXT_WRITE] =		0x18,
+	[PWRAP_CSHEXT_READ] =		0x1c,
+	[PWRAP_CSLEXT_START] =		0x20,
+	[PWRAP_CSLEXT_END] =		0x24,
+	[PWRAP_STAUPD_PRD] =		0x28,
+	[PWRAP_STAUPD_GRPEN] =		0x2c,
+	[PWRAP_STAUPD_MAN_TRIG] =	0x40,
+	[PWRAP_STAUPD_STA] =		0x44,
+	[PWRAP_WRAP_STA] =		0x48,
+	[PWRAP_HARB_INIT] =		0x4c,
+	[PWRAP_HARB_HPRIO] =		0x50,
+	[PWRAP_HIPRIO_ARB_EN] =		0x54,
+	[PWRAP_HARB_STA0] =		0x58,
+	[PWRAP_HARB_STA1] =		0x5c,
+	[PWRAP_MAN_EN] =		0x60,
+	[PWRAP_MAN_CMD] =		0x64,
+	[PWRAP_MAN_RDATA] =		0x68,
+	[PWRAP_MAN_VLDCLR] =		0x6c,
+	[PWRAP_WACS0_EN] =		0x70,
+	[PWRAP_INIT_DONE0] =		0x74,
+	[PWRAP_WACS0_CMD] =		0x78,
+	[PWRAP_WACS0_RDATA] =		0x7c,
+	[PWRAP_WACS0_VLDCLR] =		0x80,
+	[PWRAP_WACS1_EN] =		0x84,
+	[PWRAP_INIT_DONE1] =		0x88,
+	[PWRAP_WACS1_CMD] =		0x8c,
+	[PWRAP_WACS1_RDATA] =		0x90,
+	[PWRAP_WACS1_VLDCLR] =		0x94,
+	[PWRAP_WACS2_EN] =		0x98,
+	[PWRAP_INIT_DONE2] =		0x9c,
+	[PWRAP_WACS2_CMD] =		0xa0,
+	[PWRAP_WACS2_RDATA] =		0xa4,
+	[PWRAP_WACS2_VLDCLR] =		0xa8,
+	[PWRAP_INT_EN] =		0xac,
+	[PWRAP_INT_FLG_RAW] =		0xb0,
+	[PWRAP_INT_FLG] =		0xb4,
+	[PWRAP_INT_CLR] =		0xb8,
+	[PWRAP_SIG_ADR] =		0xbc,
+	[PWRAP_SIG_MODE] =		0xc0,
+	[PWRAP_SIG_VALUE] =		0xc4,
+	[PWRAP_SIG_ERRVAL] =		0xc8,
+	[PWRAP_CRC_EN] =		0xcc,
+	[PWRAP_TIMER_EN] =		0xd0,
+	[PWRAP_TIMER_STA] =		0xd4,
+	[PWRAP_WDT_UNIT] =		0xd8,
+	[PWRAP_WDT_SRC_EN] =		0xdc,
+	[PWRAP_WDT_FLG] =		0xe0,
+	[PWRAP_DEBUG_INT_SEL] =		0xe4,
+	[PWRAP_DVFS_ADR0] =		0xe8,
+	[PWRAP_DVFS_WDATA0] =		0xec,
+	[PWRAP_DVFS_ADR1] =		0xf0,
+	[PWRAP_DVFS_WDATA1] =		0xf4,
+	[PWRAP_DVFS_ADR2] =		0xf8,
+	[PWRAP_DVFS_WDATA2] =		0xfc,
+	[PWRAP_DVFS_ADR3] =		0x100,
+	[PWRAP_DVFS_WDATA3] =		0x104,
+	[PWRAP_DVFS_ADR4] =		0x108,
+	[PWRAP_DVFS_WDATA4] =		0x10c,
+	[PWRAP_DVFS_ADR5] =		0x110,
+	[PWRAP_DVFS_WDATA5] =		0x114,
+	[PWRAP_DVFS_ADR6] =		0x118,
+	[PWRAP_DVFS_WDATA6] =		0x11c,
+	[PWRAP_DVFS_ADR7] =		0x120,
+	[PWRAP_DVFS_WDATA7] =		0x124,
+	[PWRAP_SPMINF_STA] =		0x128,
+	[PWRAP_CIPHER_KEY_SEL] =	0x12c,
+	[PWRAP_CIPHER_IV_SEL] =		0x130,
+	[PWRAP_CIPHER_EN] =		0x134,
+	[PWRAP_CIPHER_RDY] =		0x138,
+	[PWRAP_CIPHER_MODE] =		0x13c,
+	[PWRAP_CIPHER_SWRST] =		0x140,
+	[PWRAP_DCM_EN] =		0x144,
+	[PWRAP_DCM_DBC_PRD] =		0x148,
+	[PWRAP_SW_RST] =		0x168,
+	[PWRAP_OP_TYPE] =		0x16c,
+	[PWRAP_MSB_FIRST] =		0x170,
+};
+
 enum pmic_type {
 	PMIC_MT6323,
 	PMIC_MT6351,
@@ -869,6 +958,7 @@ enum pwrap_type {
 	PWRAP_MT8135,
 	PWRAP_MT8173,
 	PWRAP_MT8183,
+	PWRAP_MT8516,
 };
 
 struct pmic_wrapper;
@@ -1281,7 +1371,7 @@ static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp)
 static int pwrap_init_cipher(struct pmic_wrapper *wrp)
 {
 	int ret;
-	u32 rdata;
+	u32 rdata = 0;
 
 	pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST);
 	pwrap_writel(wrp, 0x0, PWRAP_CIPHER_SWRST);
@@ -1297,6 +1387,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
 	case PWRAP_MT6765:
 	case PWRAP_MT6797:
 	case PWRAP_MT8173:
+	case PWRAP_MT8516:
 		pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
 		break;
 	case PWRAP_MT7622:
@@ -1478,7 +1569,8 @@ static int pwrap_init(struct pmic_wrapper *wrp)
 {
 	int ret;
 
-	reset_control_reset(wrp->rstc);
+	if (wrp->rstc)
+		reset_control_reset(wrp->rstc);
 	if (wrp->rstc_bridge)
 		reset_control_reset(wrp->rstc_bridge);
 
@@ -1764,6 +1856,18 @@ static const struct pmic_wrapper_type pwrap_mt8183 = {
 	.init_soc_specific = pwrap_mt8183_init_soc_specific,
 };
 
+static struct pmic_wrapper_type pwrap_mt8516 = {
+	.regs = mt8516_regs,
+	.type = PWRAP_MT8516,
+	.arb_en_all = 0xff,
+	.int_en_all = ~(u32)(BIT(31) | BIT(2)),
+	.spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+	.wdt_src = PWRAP_WDT_SRC_MASK_ALL,
+	.caps = PWRAP_CAP_DCM,
+	.init_reg_clock = pwrap_mt2701_init_reg_clock,
+	.init_soc_specific = NULL,
+};
+
 static const struct of_device_id of_pwrap_match_tbl[] = {
 	{
 		.compatible = "mediatek,mt2701-pwrap",
@@ -1787,6 +1891,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = {
 		.compatible = "mediatek,mt8183-pwrap",
 		.data = &pwrap_mt8183,
 	}, {
+		.compatible = "mediatek,mt8516-pwrap",
+		.data = &pwrap_mt8516,
+	}, {
 		/* sentinel */
 	}
 };
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index c701b3b010f1..f6c3d17b05c7 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -248,8 +248,8 @@ static int cmd_db_dev_probe(struct platform_device *pdev)
 	}
 
 	cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
-	if (IS_ERR_OR_NULL(cmd_db_header)) {
-		ret = PTR_ERR(cmd_db_header);
+	if (!cmd_db_header) {
+		ret = -ENOMEM;
 		cmd_db_header = NULL;
 		return ret;
 	}
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
index c239a28e503f..f9e309f0acd3 100644
--- a/drivers/soc/qcom/qmi_interface.c
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -345,8 +345,7 @@ int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout)
 	struct qmi_handle *qmi = txn->qmi;
 	int ret;
 
-	ret = wait_for_completion_interruptible_timeout(&txn->completion,
-							timeout);
+	ret = wait_for_completion_timeout(&txn->completion, timeout);
 
 	mutex_lock(&qmi->txn_lock);
 	mutex_lock(&txn->lock);
@@ -354,9 +353,7 @@ int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout)
 	mutex_unlock(&txn->lock);
 	mutex_unlock(&qmi->txn_lock);
 
-	if (ret < 0)
-		return ret;
-	else if (ret == 0)
+	if (ret == 0)
 		return -ETIMEDOUT;
 	else
 		return txn->result;
diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c
index 7200d762a951..6f5e8be9689c 100644
--- a/drivers/soc/qcom/rmtfs_mem.c
+++ b/drivers/soc/qcom/rmtfs_mem.c
@@ -137,6 +137,26 @@ static struct class rmtfs_class = {
 	.name           = "rmtfs",
 };
 
+static int qcom_rmtfs_mem_mmap(struct file *filep, struct vm_area_struct *vma)
+{
+	struct qcom_rmtfs_mem *rmtfs_mem = filep->private_data;
+
+	if (vma->vm_end - vma->vm_start > rmtfs_mem->size) {
+		dev_dbg(&rmtfs_mem->dev,
+			"vm_end[%lu] - vm_start[%lu] [%lu] > mem->size[%pa]\n",
+			vma->vm_end, vma->vm_start,
+			(vma->vm_end - vma->vm_start), &rmtfs_mem->size);
+		return -EINVAL;
+	}
+
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	return remap_pfn_range(vma,
+			       vma->vm_start,
+			       rmtfs_mem->addr >> PAGE_SHIFT,
+			       vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot);
+}
+
 static const struct file_operations qcom_rmtfs_mem_fops = {
 	.owner = THIS_MODULE,
 	.open = qcom_rmtfs_mem_open,
@@ -144,6 +164,7 @@ static const struct file_operations qcom_rmtfs_mem_fops = {
 	.write = qcom_rmtfs_mem_write,
 	.release = qcom_rmtfs_mem_release,
 	.llseek = default_llseek,
+	.mmap = qcom_rmtfs_mem_mmap,
 };
 
 static void qcom_rmtfs_mem_release_device(struct device *dev)
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index 75bd9a83aef0..e278fc11fe5c 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -459,7 +459,7 @@ static int find_slots(struct tcs_group *tcs, const struct tcs_request *msg,
 	do {
 		slot = bitmap_find_next_zero_area(tcs->slots, MAX_TCS_SLOTS,
 						  i, msg->num_cmds, 0);
-		if (slot == tcs->num_tcs * tcs->ncpt)
+		if (slot >= tcs->num_tcs * tcs->ncpt)
 			return -ENOMEM;
 		i += tcs->ncpt;
 	} while (slot + msg->num_cmds - 1 >= i);
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
index 4af96e668a2f..3299cf5365f3 100644
--- a/drivers/soc/renesas/renesas-soc.c
+++ b/drivers/soc/renesas/renesas-soc.c
@@ -335,6 +335,9 @@ static int __init renesas_soc_init(void)
 		/* R-Car M3-W ES1.1 incorrectly identifies as ES2.0 */
 		if ((product & 0x7fff) == 0x5210)
 			product ^= 0x11;
+		/* R-Car M3-W ES1.3 incorrectly identifies as ES2.1 */
+		if ((product & 0x7fff) == 0x5211)
+			product ^= 0x12;
 		if (soc->id && ((product >> 8) & 0xff) != soc->id) {
 			pr_warn("SoC mismatch (product = 0x%x)\n", product);
 			return -ENODEV;
diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c
index 96882ffde67e..3b81e1d75a97 100644
--- a/drivers/soc/rockchip/grf.c
+++ b/drivers/soc/rockchip/grf.c
@@ -66,9 +66,11 @@ static const struct rockchip_grf_info rk3228_grf __initconst = {
 };
 
 #define RK3288_GRF_SOC_CON0		0x244
+#define RK3288_GRF_SOC_CON2		0x24c
 
 static const struct rockchip_grf_value rk3288_defaults[] __initconst = {
 	{ "jtag switching", RK3288_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 12) },
+	{ "pwm select", RK3288_GRF_SOC_CON2, HIWORD_UPDATE(1, 1, 0) },
 };
 
 static const struct rockchip_grf_info rk3288_grf __initconst = {
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 0df258518693..5648e5c09ef5 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -272,6 +272,14 @@ static const char * const tegra30_reset_sources[] = {
 	"WATCHDOG",
 	"SENSOR",
 	"SW_MAIN",
+	"LP0"
+};
+
+static const char * const tegra210_reset_sources[] = {
+	"POWER_ON_RESET",
+	"WATCHDOG",
+	"SENSOR",
+	"SW_MAIN",
 	"LP0",
 	"AOTAG"
 };
@@ -656,10 +664,15 @@ static int tegra_genpd_power_on(struct generic_pm_domain *domain)
 	int err;
 
 	err = tegra_powergate_power_up(pg, true);
-	if (err)
+	if (err) {
 		dev_err(dev, "failed to turn on PM domain %s: %d\n",
 			pg->genpd.name, err);
+		goto out;
+	}
+
+	reset_control_release(pg->reset);
 
+out:
 	return err;
 }
 
@@ -669,10 +682,18 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain)
 	struct device *dev = pg->pmc->dev;
 	int err;
 
+	err = reset_control_acquire(pg->reset);
+	if (err < 0) {
+		pr_err("failed to acquire resets: %d\n", err);
+		return err;
+	}
+
 	err = tegra_powergate_power_down(pg);
-	if (err)
+	if (err) {
 		dev_err(dev, "failed to turn off PM domain %s: %d\n",
 			pg->genpd.name, err);
+		reset_control_release(pg->reset);
+	}
 
 	return err;
 }
@@ -937,38 +958,53 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
 	struct device *dev = pg->pmc->dev;
 	int err;
 
-	pg->reset = of_reset_control_array_get_exclusive(np);
+	pg->reset = of_reset_control_array_get_exclusive_released(np);
 	if (IS_ERR(pg->reset)) {
 		err = PTR_ERR(pg->reset);
 		dev_err(dev, "failed to get device resets: %d\n", err);
 		return err;
 	}
 
-	if (off)
+	err = reset_control_acquire(pg->reset);
+	if (err < 0) {
+		pr_err("failed to acquire resets: %d\n", err);
+		goto out;
+	}
+
+	if (off) {
 		err = reset_control_assert(pg->reset);
-	else
+	} else {
 		err = reset_control_deassert(pg->reset);
+		if (err < 0)
+			goto out;
 
-	if (err)
+		reset_control_release(pg->reset);
+	}
+
+out:
+	if (err) {
+		reset_control_release(pg->reset);
 		reset_control_put(pg->reset);
+	}
 
 	return err;
 }
 
-static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
+static int tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
 {
 	struct device *dev = pmc->dev;
 	struct tegra_powergate *pg;
-	int id, err;
+	int id, err = 0;
 	bool off;
 
 	pg = kzalloc(sizeof(*pg), GFP_KERNEL);
 	if (!pg)
-		return;
+		return -ENOMEM;
 
 	id = tegra_powergate_lookup(pmc, np->name);
 	if (id < 0) {
 		dev_err(dev, "powergate lookup failed for %pOFn: %d\n", np, id);
+		err = -ENODEV;
 		goto free_mem;
 	}
 
@@ -1021,7 +1057,7 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
 
 	dev_dbg(dev, "added PM domain %s\n", pg->genpd.name);
 
-	return;
+	return 0;
 
 remove_genpd:
 	pm_genpd_remove(&pg->genpd);
@@ -1040,25 +1076,67 @@ set_available:
 
 free_mem:
 	kfree(pg);
+
+	return err;
 }
 
-static void tegra_powergate_init(struct tegra_pmc *pmc,
-				 struct device_node *parent)
+static int tegra_powergate_init(struct tegra_pmc *pmc,
+				struct device_node *parent)
 {
 	struct device_node *np, *child;
-	unsigned int i;
+	int err = 0;
+
+	np = of_get_child_by_name(parent, "powergates");
+	if (!np)
+		return 0;
+
+	for_each_child_of_node(np, child) {
+		err = tegra_powergate_add(pmc, child);
+		if (err < 0) {
+			of_node_put(child);
+			break;
+		}
+	}
+
+	of_node_put(np);
+
+	return err;
+}
+
+static void tegra_powergate_remove(struct generic_pm_domain *genpd)
+{
+	struct tegra_powergate *pg = to_powergate(genpd);
+
+	reset_control_put(pg->reset);
+
+	while (pg->num_clks--)
+		clk_put(pg->clks[pg->num_clks]);
+
+	kfree(pg->clks);
 
-	/* Create a bitmap of the available and valid partitions */
-	for (i = 0; i < pmc->soc->num_powergates; i++)
-		if (pmc->soc->powergates[i])
-			set_bit(i, pmc->powergates_available);
+	set_bit(pg->id, pmc->powergates_available);
+
+	kfree(pg);
+}
+
+static void tegra_powergate_remove_all(struct device_node *parent)
+{
+	struct generic_pm_domain *genpd;
+	struct device_node *np, *child;
 
 	np = of_get_child_by_name(parent, "powergates");
 	if (!np)
 		return;
 
-	for_each_child_of_node(np, child)
-		tegra_powergate_add(pmc, child);
+	for_each_child_of_node(np, child) {
+		of_genpd_del_provider(child);
+
+		genpd = of_genpd_remove_last(child);
+		if (IS_ERR(genpd))
+			continue;
+
+		tegra_powergate_remove(genpd);
+	}
 
 	of_node_put(np);
 }
@@ -1709,13 +1787,16 @@ static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
 static ssize_t reset_reason_show(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
-	u32 value, rst_src;
+	u32 value;
 
 	value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
-	rst_src = (value & pmc->soc->regs->rst_source_mask) >>
-			pmc->soc->regs->rst_source_shift;
+	value &= pmc->soc->regs->rst_source_mask;
+	value >>= pmc->soc->regs->rst_source_shift;
+
+	if (WARN_ON(value >= pmc->soc->num_reset_sources))
+		return sprintf(buf, "%s\n", "UNKNOWN");
 
-	return sprintf(buf, "%s\n", pmc->soc->reset_sources[rst_src]);
+	return sprintf(buf, "%s\n", pmc->soc->reset_sources[value]);
 }
 
 static DEVICE_ATTR_RO(reset_reason);
@@ -1723,13 +1804,16 @@ static DEVICE_ATTR_RO(reset_reason);
 static ssize_t reset_level_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	u32 value, rst_lvl;
+	u32 value;
 
 	value = tegra_pmc_readl(pmc, pmc->soc->regs->rst_status);
-	rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
-			pmc->soc->regs->rst_level_shift;
+	value &= pmc->soc->regs->rst_level_mask;
+	value >>= pmc->soc->regs->rst_level_shift;
 
-	return sprintf(buf, "%s\n", pmc->soc->reset_levels[rst_lvl]);
+	if (WARN_ON(value >= pmc->soc->num_reset_levels))
+		return sprintf(buf, "%s\n", "UNKNOWN");
+
+	return sprintf(buf, "%s\n", pmc->soc->reset_levels[value]);
 }
 
 static DEVICE_ATTR_RO(reset_level);
@@ -1999,7 +2083,7 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 	if (IS_ENABLED(CONFIG_DEBUG_FS)) {
 		err = tegra_powergate_debugfs_init();
 		if (err < 0)
-			return err;
+			goto cleanup_sysfs;
 	}
 
 	err = register_restart_handler(&tegra_pmc_restart_handler);
@@ -2013,9 +2097,13 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 	if (err)
 		goto cleanup_restart_handler;
 
+	err = tegra_powergate_init(pmc, pdev->dev.of_node);
+	if (err < 0)
+		goto cleanup_powergates;
+
 	err = tegra_pmc_irq_init(pmc);
 	if (err < 0)
-		goto cleanup_restart_handler;
+		goto cleanup_powergates;
 
 	mutex_lock(&pmc->powergates_lock);
 	iounmap(pmc->base);
@@ -2026,10 +2114,15 @@ static int tegra_pmc_probe(struct platform_device *pdev)
 
 	return 0;
 
+cleanup_powergates:
+	tegra_powergate_remove_all(pdev->dev.of_node);
 cleanup_restart_handler:
 	unregister_restart_handler(&tegra_pmc_restart_handler);
 cleanup_debugfs:
 	debugfs_remove(pmc->debugfs);
+cleanup_sysfs:
+	device_remove_file(&pdev->dev, &dev_attr_reset_reason);
+	device_remove_file(&pdev->dev, &dev_attr_reset_level);
 	return err;
 }
 
@@ -2185,7 +2278,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
 	.init = tegra20_pmc_init,
 	.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
 	.reset_sources = tegra30_reset_sources,
-	.num_reset_sources = 5,
+	.num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
 	.reset_levels = NULL,
 	.num_reset_levels = 0,
 };
@@ -2236,7 +2329,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
 	.init = tegra20_pmc_init,
 	.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
 	.reset_sources = tegra30_reset_sources,
-	.num_reset_sources = 5,
+	.num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
 	.reset_levels = NULL,
 	.num_reset_levels = 0,
 };
@@ -2347,7 +2440,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
 	.init = tegra20_pmc_init,
 	.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
 	.reset_sources = tegra30_reset_sources,
-	.num_reset_sources = 5,
+	.num_reset_sources = ARRAY_SIZE(tegra30_reset_sources),
 	.reset_levels = NULL,
 	.num_reset_levels = 0,
 };
@@ -2452,8 +2545,8 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
 	.regs = &tegra20_pmc_regs,
 	.init = tegra20_pmc_init,
 	.setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
-	.reset_sources = tegra30_reset_sources,
-	.num_reset_sources = 5,
+	.reset_sources = tegra210_reset_sources,
+	.num_reset_sources = ARRAY_SIZE(tegra210_reset_sources),
 	.reset_levels = NULL,
 	.num_reset_levels = 0,
 };
@@ -2578,9 +2671,9 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
 	.init = NULL,
 	.setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
 	.reset_sources = tegra186_reset_sources,
-	.num_reset_sources = 14,
+	.num_reset_sources = ARRAY_SIZE(tegra186_reset_sources),
 	.reset_levels = tegra186_reset_levels,
-	.num_reset_levels = 3,
+	.num_reset_levels = ARRAY_SIZE(tegra186_reset_levels),
 	.num_wake_events = ARRAY_SIZE(tegra186_wake_events),
 	.wake_events = tegra186_wake_events,
 };
@@ -2719,6 +2812,7 @@ static int __init tegra_pmc_early_init(void)
 	const struct of_device_id *match;
 	struct device_node *np;
 	struct resource regs;
+	unsigned int i;
 	bool invert;
 
 	mutex_init(&pmc->powergates_lock);
@@ -2775,7 +2869,10 @@ static int __init tegra_pmc_early_init(void)
 		if (pmc->soc->maybe_tz_only)
 			pmc->tz_only = tegra_pmc_detect_tz_only(pmc);
 
-		tegra_powergate_init(pmc, np);
+		/* Create a bitmap of the available and valid partitions */
+		for (i = 0; i < pmc->soc->num_powergates; i++)
+			if (pmc->soc->powergates[i])
+				set_bit(i, pmc->powergates_available);
 
 		/*
 		 * Invert the interrupt polarity if a PMC device tree node
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
index be4570baad96..57960e92ebe0 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/soc/ti/Kconfig
@@ -45,11 +45,12 @@ config KEYSTONE_NAVIGATOR_DMA
 config AMX3_PM
 	tristate "AMx3 Power Management"
 	depends on SOC_AM33XX || SOC_AM43XX
-	depends on WKUP_M3_IPC && TI_EMIF_SRAM && SRAM
+	depends on WKUP_M3_IPC && TI_EMIF_SRAM && SRAM && RTC_DRV_OMAP
 	help
 	  Enable power management on AM335x and AM437x. Required for suspend to mem
 	  and standby states on both AM335x and AM437x platforms and for deeper cpuidle
-	  c-states on AM335x.
+	  c-states on AM335x. Also required for rtc and ddr in self-refresh low
+	  power mode on AM437x platforms.
 
 config WKUP_M3_IPC
 	tristate "TI AMx3 Wkup-M3 IPC Driver"
diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c
index d0dab323651f..fc5802ccb1c0 100644
--- a/drivers/soc/ti/pm33xx.c
+++ b/drivers/soc/ti/pm33xx.c
@@ -6,6 +6,7 @@
  *	Vaibhav Bedia, Dave Gerlach
  */
 
+#include <linux/clk.h>
 #include <linux/cpu.h>
 #include <linux/err.h>
 #include <linux/genalloc.h>
@@ -13,9 +14,12 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/of.h>
 #include <linux/platform_data/pm33xx.h>
 #include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/rtc/rtc-omap.h>
 #include <linux/sizes.h>
 #include <linux/sram.h>
 #include <linux/suspend.h>
@@ -29,33 +33,162 @@
 #define AMX3_PM_SRAM_SYMBOL_OFFSET(sym) ((unsigned long)(sym) - \
 					 (unsigned long)pm_sram->do_wfi)
 
+#define RTC_SCRATCH_RESUME_REG	0
+#define RTC_SCRATCH_MAGIC_REG	1
+#define RTC_REG_BOOT_MAGIC	0x8cd0 /* RTC */
+#define GIC_INT_SET_PENDING_BASE 0x200
+#define AM43XX_GIC_DIST_BASE	0x48241000
+
+static u32 rtc_magic_val;
+
 static int (*am33xx_do_wfi_sram)(unsigned long unused);
 static phys_addr_t am33xx_do_wfi_sram_phys;
 
 static struct gen_pool *sram_pool, *sram_pool_data;
 static unsigned long ocmcram_location, ocmcram_location_data;
 
+static struct rtc_device *omap_rtc;
+static void __iomem *gic_dist_base;
+
 static struct am33xx_pm_platform_data *pm_ops;
 static struct am33xx_pm_sram_addr *pm_sram;
 
 static struct device *pm33xx_dev;
 static struct wkup_m3_ipc *m3_ipc;
 
+#ifdef CONFIG_SUSPEND
+static int rtc_only_idle;
+static int retrigger_irq;
 static unsigned long suspend_wfi_flags;
 
+static struct wkup_m3_wakeup_src wakeup_src = {.irq_nr = 0,
+	.src = "Unknown",
+};
+
+static struct wkup_m3_wakeup_src rtc_alarm_wakeup = {
+	.irq_nr = 108, .src = "RTC Alarm",
+};
+
+static struct wkup_m3_wakeup_src rtc_ext_wakeup = {
+	.irq_nr = 0, .src = "Ext wakeup",
+};
+#endif
+
 static u32 sram_suspend_address(unsigned long addr)
 {
 	return ((unsigned long)am33xx_do_wfi_sram +
 		AMX3_PM_SRAM_SYMBOL_OFFSET(addr));
 }
 
+static int am33xx_push_sram_idle(void)
+{
+	struct am33xx_pm_ro_sram_data ro_sram_data;
+	int ret;
+	u32 table_addr, ro_data_addr;
+	void *copy_addr;
+
+	ro_sram_data.amx3_pm_sram_data_virt = ocmcram_location_data;
+	ro_sram_data.amx3_pm_sram_data_phys =
+		gen_pool_virt_to_phys(sram_pool_data, ocmcram_location_data);
+	ro_sram_data.rtc_base_virt = pm_ops->get_rtc_base_addr();
+
+	/* Save physical address to calculate resume offset during pm init */
+	am33xx_do_wfi_sram_phys = gen_pool_virt_to_phys(sram_pool,
+							ocmcram_location);
+
+	am33xx_do_wfi_sram = sram_exec_copy(sram_pool, (void *)ocmcram_location,
+					    pm_sram->do_wfi,
+					    *pm_sram->do_wfi_sz);
+	if (!am33xx_do_wfi_sram) {
+		dev_err(pm33xx_dev,
+			"PM: %s: am33xx_do_wfi copy to sram failed\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	table_addr =
+		sram_suspend_address((unsigned long)pm_sram->emif_sram_table);
+	ret = ti_emif_copy_pm_function_table(sram_pool, (void *)table_addr);
+	if (ret) {
+		dev_dbg(pm33xx_dev,
+			"PM: %s: EMIF function copy failed\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	ro_data_addr =
+		sram_suspend_address((unsigned long)pm_sram->ro_sram_data);
+	copy_addr = sram_exec_copy(sram_pool, (void *)ro_data_addr,
+				   &ro_sram_data,
+				   sizeof(ro_sram_data));
+	if (!copy_addr) {
+		dev_err(pm33xx_dev,
+			"PM: %s: ro_sram_data copy to sram failed\n",
+			__func__);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int __init am43xx_map_gic(void)
+{
+	gic_dist_base = ioremap(AM43XX_GIC_DIST_BASE, SZ_4K);
+
+	if (!gic_dist_base)
+		return -ENOMEM;
+
+	return 0;
+}
+
 #ifdef CONFIG_SUSPEND
+struct wkup_m3_wakeup_src rtc_wake_src(void)
+{
+	u32 i;
+
+	i = __raw_readl(pm_ops->get_rtc_base_addr() + 0x44) & 0x40;
+
+	if (i) {
+		retrigger_irq = rtc_alarm_wakeup.irq_nr;
+		return rtc_alarm_wakeup;
+	}
+
+	retrigger_irq = rtc_ext_wakeup.irq_nr;
+
+	return rtc_ext_wakeup;
+}
+
+int am33xx_rtc_only_idle(unsigned long wfi_flags)
+{
+	omap_rtc_power_off_program(&omap_rtc->dev);
+	am33xx_do_wfi_sram(wfi_flags);
+	return 0;
+}
+
 static int am33xx_pm_suspend(suspend_state_t suspend_state)
 {
 	int i, ret = 0;
 
-	ret = pm_ops->soc_suspend((unsigned long)suspend_state,
-				  am33xx_do_wfi_sram, suspend_wfi_flags);
+	if (suspend_state == PM_SUSPEND_MEM &&
+	    pm_ops->check_off_mode_enable()) {
+		pm_ops->prepare_rtc_suspend();
+		pm_ops->save_context();
+		suspend_wfi_flags |= WFI_FLAG_RTC_ONLY;
+		clk_save_context();
+		ret = pm_ops->soc_suspend(suspend_state, am33xx_rtc_only_idle,
+					  suspend_wfi_flags);
+
+		suspend_wfi_flags &= ~WFI_FLAG_RTC_ONLY;
+
+		if (!ret) {
+			clk_restore_context();
+			pm_ops->restore_context();
+			m3_ipc->ops->set_rtc_only(m3_ipc);
+			am33xx_push_sram_idle();
+		}
+	} else {
+		ret = pm_ops->soc_suspend(suspend_state, am33xx_do_wfi_sram,
+					  suspend_wfi_flags);
+	}
 
 	if (ret) {
 		dev_err(pm33xx_dev, "PM: Kernel suspend failure\n");
@@ -77,8 +210,20 @@ static int am33xx_pm_suspend(suspend_state_t suspend_state)
 				"PM: CM3 returned unknown result = %d\n", i);
 			ret = -1;
 		}
+
+		/* print the wakeup reason */
+		if (rtc_only_idle) {
+			wakeup_src = rtc_wake_src();
+			pr_info("PM: Wakeup source %s\n", wakeup_src.src);
+		} else {
+			pr_info("PM: Wakeup source %s\n",
+				m3_ipc->ops->request_wake_src(m3_ipc));
+		}
 	}
 
+	if (suspend_state == PM_SUSPEND_MEM && pm_ops->check_off_mode_enable())
+		pm_ops->prepare_rtc_resume();
+
 	return ret;
 }
 
@@ -101,6 +246,18 @@ static int am33xx_pm_enter(suspend_state_t suspend_state)
 static int am33xx_pm_begin(suspend_state_t state)
 {
 	int ret = -EINVAL;
+	struct nvmem_device *nvmem;
+
+	if (state == PM_SUSPEND_MEM && pm_ops->check_off_mode_enable()) {
+		nvmem = devm_nvmem_device_get(&omap_rtc->dev,
+					      "omap_rtc_scratch0");
+		if (nvmem)
+			nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
+					   (void *)&rtc_magic_val);
+		rtc_only_idle = 1;
+	} else {
+		rtc_only_idle = 0;
+	}
 
 	switch (state) {
 	case PM_SUSPEND_MEM:
@@ -116,7 +273,28 @@ static int am33xx_pm_begin(suspend_state_t state)
 
 static void am33xx_pm_end(void)
 {
+	u32 val = 0;
+	struct nvmem_device *nvmem;
+
+	nvmem = devm_nvmem_device_get(&omap_rtc->dev, "omap_rtc_scratch0");
 	m3_ipc->ops->finish_low_power(m3_ipc);
+	if (rtc_only_idle) {
+		if (retrigger_irq)
+			/*
+			 * 32 bits of Interrupt Set-Pending correspond to 32
+			 * 32 interrupts. Compute the bit offset of the
+			 * Interrupt and set that particular bit
+			 * Compute the register offset by dividing interrupt
+			 * number by 32 and mutiplying by 4
+			 */
+			writel_relaxed(1 << (retrigger_irq & 31),
+				       gic_dist_base + GIC_INT_SET_PENDING_BASE
+				       + retrigger_irq / 32 * 4);
+			nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4, 4,
+					   (void *)&val);
+	}
+
+	rtc_only_idle = 0;
 }
 
 static int am33xx_pm_valid(suspend_state_t state)
@@ -219,51 +397,37 @@ mpu_put_node:
 	return ret;
 }
 
-static int am33xx_push_sram_idle(void)
+static int am33xx_pm_rtc_setup(void)
 {
-	struct am33xx_pm_ro_sram_data ro_sram_data;
-	int ret;
-	u32 table_addr, ro_data_addr;
-	void *copy_addr;
-
-	ro_sram_data.amx3_pm_sram_data_virt = ocmcram_location_data;
-	ro_sram_data.amx3_pm_sram_data_phys =
-		gen_pool_virt_to_phys(sram_pool_data, ocmcram_location_data);
-	ro_sram_data.rtc_base_virt = pm_ops->get_rtc_base_addr();
+	struct device_node *np;
+	unsigned long val = 0;
+	struct nvmem_device *nvmem;
 
-	/* Save physical address to calculate resume offset during pm init */
-	am33xx_do_wfi_sram_phys = gen_pool_virt_to_phys(sram_pool,
-							ocmcram_location);
+	np = of_find_node_by_name(NULL, "rtc");
 
-	am33xx_do_wfi_sram = sram_exec_copy(sram_pool, (void *)ocmcram_location,
-					    pm_sram->do_wfi,
-					    *pm_sram->do_wfi_sz);
-	if (!am33xx_do_wfi_sram) {
-		dev_err(pm33xx_dev,
-			"PM: %s: am33xx_do_wfi copy to sram failed\n",
-			__func__);
-		return -ENODEV;
-	}
-
-	table_addr =
-		sram_suspend_address((unsigned long)pm_sram->emif_sram_table);
-	ret = ti_emif_copy_pm_function_table(sram_pool, (void *)table_addr);
-	if (ret) {
-		dev_dbg(pm33xx_dev,
-			"PM: %s: EMIF function copy failed\n", __func__);
-		return -EPROBE_DEFER;
-	}
+	if (of_device_is_available(np)) {
+		omap_rtc = rtc_class_open("rtc0");
+		if (!omap_rtc) {
+			pr_warn("PM: rtc0 not available");
+			return -EPROBE_DEFER;
+		}
 
-	ro_data_addr =
-		sram_suspend_address((unsigned long)pm_sram->ro_sram_data);
-	copy_addr = sram_exec_copy(sram_pool, (void *)ro_data_addr,
-				   &ro_sram_data,
-				   sizeof(ro_sram_data));
-	if (!copy_addr) {
-		dev_err(pm33xx_dev,
-			"PM: %s: ro_sram_data copy to sram failed\n",
-			__func__);
-		return -ENODEV;
+		nvmem = devm_nvmem_device_get(&omap_rtc->dev,
+					      "omap_rtc_scratch0");
+		if (nvmem) {
+			nvmem_device_read(nvmem, RTC_SCRATCH_MAGIC_REG * 4,
+					  4, (void *)&rtc_magic_val);
+			if ((rtc_magic_val & 0xffff) != RTC_REG_BOOT_MAGIC)
+				pr_warn("PM: bootloader does not support rtc-only!\n");
+
+			nvmem_device_write(nvmem, RTC_SCRATCH_MAGIC_REG * 4,
+					   4, (void *)&val);
+			val = pm_sram->resume_address;
+			nvmem_device_write(nvmem, RTC_SCRATCH_RESUME_REG * 4,
+					   4, (void *)&val);
+		}
+	} else {
+		pr_warn("PM: no-rtc available, rtc-only mode disabled.\n");
 	}
 
 	return 0;
@@ -284,34 +448,42 @@ static int am33xx_pm_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
+	ret = am43xx_map_gic();
+	if (ret) {
+		pr_err("PM: Could not ioremap GIC base\n");
+		return ret;
+	}
+
 	pm_sram = pm_ops->get_sram_addrs();
 	if (!pm_sram) {
 		dev_err(dev, "PM: Cannot get PM asm function addresses!!\n");
 		return -ENODEV;
 	}
 
+	m3_ipc = wkup_m3_ipc_get();
+	if (!m3_ipc) {
+		pr_err("PM: Cannot get wkup_m3_ipc handle\n");
+		return -EPROBE_DEFER;
+	}
+
 	pm33xx_dev = dev;
 
 	ret = am33xx_pm_alloc_sram();
 	if (ret)
 		return ret;
 
-	ret = am33xx_push_sram_idle();
+	ret = am33xx_pm_rtc_setup();
 	if (ret)
 		goto err_free_sram;
 
-	m3_ipc = wkup_m3_ipc_get();
-	if (!m3_ipc) {
-		dev_dbg(dev, "PM: Cannot get wkup_m3_ipc handle\n");
-		ret = -EPROBE_DEFER;
+	ret = am33xx_push_sram_idle();
+	if (ret)
 		goto err_free_sram;
-	}
 
 	am33xx_pm_set_ipc_ops();
 
 #ifdef CONFIG_SUSPEND
 	suspend_set_ops(&am33xx_pm_ops);
-#endif /* CONFIG_SUSPEND */
 
 	/*
 	 * For a system suspend we must flush the caches, we want
@@ -323,6 +495,7 @@ static int am33xx_pm_probe(struct platform_device *pdev)
 	suspend_wfi_flags |= WFI_FLAG_SELF_REFRESH;
 	suspend_wfi_flags |= WFI_FLAG_SAVE_EMIF;
 	suspend_wfi_flags |= WFI_FLAG_WAKE_M3;
+#endif /* CONFIG_SUSPEND */
 
 	ret = pm_ops->init();
 	if (ret) {
diff --git a/drivers/soc/xilinx/zynqmp_pm_domains.c b/drivers/soc/xilinx/zynqmp_pm_domains.c
index 354d256e6e00..600f57cf0c2e 100644
--- a/drivers/soc/xilinx/zynqmp_pm_domains.c
+++ b/drivers/soc/xilinx/zynqmp_pm_domains.c
@@ -23,6 +23,8 @@
 /* Flag stating if PM nodes mapped to the PM domain has been requested */
 #define ZYNQMP_PM_DOMAIN_REQUESTED	BIT(0)
 
+static const struct zynqmp_eemi_ops *eemi_ops;
+
 /**
  * struct zynqmp_pm_domain - Wrapper around struct generic_pm_domain
  * @gpd:		Generic power domain
@@ -71,9 +73,8 @@ static int zynqmp_gpd_power_on(struct generic_pm_domain *domain)
 {
 	int ret;
 	struct zynqmp_pm_domain *pd;
-	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-	if (!eemi_ops || !eemi_ops->set_requirement)
+	if (!eemi_ops->set_requirement)
 		return -ENXIO;
 
 	pd = container_of(domain, struct zynqmp_pm_domain, gpd);
@@ -107,9 +108,8 @@ static int zynqmp_gpd_power_off(struct generic_pm_domain *domain)
 	struct zynqmp_pm_domain *pd;
 	u32 capabilities = 0;
 	bool may_wakeup;
-	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-	if (!eemi_ops || !eemi_ops->set_requirement)
+	if (!eemi_ops->set_requirement)
 		return -ENXIO;
 
 	pd = container_of(domain, struct zynqmp_pm_domain, gpd);
@@ -160,9 +160,8 @@ static int zynqmp_gpd_attach_dev(struct generic_pm_domain *domain,
 {
 	int ret;
 	struct zynqmp_pm_domain *pd;
-	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-	if (!eemi_ops || !eemi_ops->request_node)
+	if (!eemi_ops->request_node)
 		return -ENXIO;
 
 	pd = container_of(domain, struct zynqmp_pm_domain, gpd);
@@ -197,9 +196,8 @@ static void zynqmp_gpd_detach_dev(struct generic_pm_domain *domain,
 {
 	int ret;
 	struct zynqmp_pm_domain *pd;
-	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-	if (!eemi_ops || !eemi_ops->release_node)
+	if (!eemi_ops->release_node)
 		return;
 
 	pd = container_of(domain, struct zynqmp_pm_domain, gpd);
@@ -266,6 +264,10 @@ static int zynqmp_gpd_probe(struct platform_device *pdev)
 	struct zynqmp_pm_domain *pd;
 	struct device *dev = &pdev->dev;
 
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
 	pd = devm_kcalloc(dev, ZYNQMP_NUM_DOMAINS, sizeof(*pd), GFP_KERNEL);
 	if (!pd)
 		return -ENOMEM;
diff --git a/drivers/soc/xilinx/zynqmp_power.c b/drivers/soc/xilinx/zynqmp_power.c
index 771cb59b9d22..1b9d14411a15 100644
--- a/drivers/soc/xilinx/zynqmp_power.c
+++ b/drivers/soc/xilinx/zynqmp_power.c
@@ -31,6 +31,7 @@ static const char *const suspend_modes[] = {
 };
 
 static enum pm_suspend_mode suspend_mode = PM_SUSPEND_MODE_STD;
+static const struct zynqmp_eemi_ops *eemi_ops;
 
 enum pm_api_cb_id {
 	PM_INIT_SUSPEND_CB = 30,
@@ -92,9 +93,8 @@ static ssize_t suspend_mode_store(struct device *dev,
 				  const char *buf, size_t count)
 {
 	int md, ret = -EINVAL;
-	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
 
-	if (!eemi_ops || !eemi_ops->set_suspend_mode)
+	if (!eemi_ops->set_suspend_mode)
 		return ret;
 
 	for (md = PM_SUSPEND_MODE_FIRST; md < ARRAY_SIZE(suspend_modes); md++)
@@ -120,9 +120,11 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
 	int ret, irq;
 	u32 pm_api_version;
 
-	const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops();
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
 
-	if (!eemi_ops || !eemi_ops->get_api_version || !eemi_ops->init_finalize)
+	if (!eemi_ops->get_api_version || !eemi_ops->init_finalize)
 		return -ENXIO;
 
 	eemi_ops->init_finalize();
diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 9f83e1b17aa1..9850a0efe85a 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -14,6 +14,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/firmware/xlnx-zynqmp.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -138,6 +139,7 @@
 
 #define SPI_AUTOSUSPEND_TIMEOUT		3000
 enum mode_type {GQSPI_MODE_IO, GQSPI_MODE_DMA};
+static const struct zynqmp_eemi_ops *eemi_ops;
 
 /**
  * struct zynqmp_qspi - Defines qspi driver instance
@@ -1021,6 +1023,10 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct device *dev = &pdev->dev;
 
+	eemi_ops = zynqmp_pm_get_eemi_ops();
+	if (IS_ERR(eemi_ops))
+		return PTR_ERR(eemi_ops);
+
 	master = spi_alloc_master(&pdev->dev, sizeof(*xqspi));
 	if (!master)
 		return -ENOMEM;
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index 0842b6e6af82..48963eab32f5 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -419,9 +419,35 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn,
 	return true;
 }
 
+static struct tee_shm_pool *optee_config_dyn_shm(void)
+{
+	struct tee_shm_pool_mgr *priv_mgr;
+	struct tee_shm_pool_mgr *dmabuf_mgr;
+	void *rc;
+
+	rc = optee_shm_pool_alloc_pages();
+	if (IS_ERR(rc))
+		return rc;
+	priv_mgr = rc;
+
+	rc = optee_shm_pool_alloc_pages();
+	if (IS_ERR(rc)) {
+		tee_shm_pool_mgr_destroy(priv_mgr);
+		return rc;
+	}
+	dmabuf_mgr = rc;
+
+	rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
+	if (IS_ERR(rc)) {
+		tee_shm_pool_mgr_destroy(priv_mgr);
+		tee_shm_pool_mgr_destroy(dmabuf_mgr);
+	}
+
+	return rc;
+}
+
 static struct tee_shm_pool *
-optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm,
-			  u32 sec_caps)
+optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm)
 {
 	union {
 		struct arm_smccc_res smccc;
@@ -436,10 +462,11 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm,
 	struct tee_shm_pool_mgr *priv_mgr;
 	struct tee_shm_pool_mgr *dmabuf_mgr;
 	void *rc;
+	const int sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
 
 	invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
 	if (res.result.status != OPTEE_SMC_RETURN_OK) {
-		pr_info("shm service not available\n");
+		pr_err("static shm service not available\n");
 		return ERR_PTR(-ENOENT);
 	}
 
@@ -465,28 +492,15 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm,
 	}
 	vaddr = (unsigned long)va;
 
-	/*
-	 * If OP-TEE can work with unregistered SHM, we will use own pool
-	 * for private shm
-	 */
-	if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) {
-		rc = optee_shm_pool_alloc_pages();
-		if (IS_ERR(rc))
-			goto err_memunmap;
-		priv_mgr = rc;
-	} else {
-		const size_t sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
-
-		rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz,
-						    3 /* 8 bytes aligned */);
-		if (IS_ERR(rc))
-			goto err_memunmap;
-		priv_mgr = rc;
-
-		vaddr += sz;
-		paddr += sz;
-		size -= sz;
-	}
+	rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz,
+					    3 /* 8 bytes aligned */);
+	if (IS_ERR(rc))
+		goto err_memunmap;
+	priv_mgr = rc;
+
+	vaddr += sz;
+	paddr += sz;
+	size -= sz;
 
 	rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, size, PAGE_SHIFT);
 	if (IS_ERR(rc))
@@ -552,7 +566,7 @@ static optee_invoke_fn *get_invoke_func(struct device_node *np)
 static struct optee *optee_probe(struct device_node *np)
 {
 	optee_invoke_fn *invoke_fn;
-	struct tee_shm_pool *pool;
+	struct tee_shm_pool *pool = ERR_PTR(-EINVAL);
 	struct optee *optee = NULL;
 	void *memremaped_shm = NULL;
 	struct tee_device *teedev;
@@ -581,13 +595,17 @@ static struct optee *optee_probe(struct device_node *np)
 	}
 
 	/*
-	 * We have no other option for shared memory, if secure world
-	 * doesn't have any reserved memory we can use we can't continue.
+	 * Try to use dynamic shared memory if possible
 	 */
-	if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM))
-		return ERR_PTR(-EINVAL);
+	if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
+		pool = optee_config_dyn_shm();
+
+	/*
+	 * If dynamic shared memory is not available or failed - try static one
+	 */
+	if (IS_ERR(pool) && (sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM))
+		pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm);
 
-	pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm, sec_caps);
 	if (IS_ERR(pool))
 		return (void *)pool;