summaryrefslogtreecommitdiff
authorzhiqiang liang <zhiqiang.liang@amlogic.com>2019-12-04 09:34:55 (GMT)
committer Zhiqiang Liang <zhiqiang.liang@amlogic.com>2019-12-13 03:10:39 (GMT)
commit70c3be46f69545089a0b29a0caedf93e29201373 (patch)
tree647355403dfce712c350776c6de9d9cb223428aa
parent3bfde1d85bb56d457183a8facf60a692fedb7891 (diff)
downloaduboot-70c3be46f69545089a0b29a0caedf93e29201373.zip
uboot-70c3be46f69545089a0b29a0caedf93e29201373.tar.gz
uboot-70c3be46f69545089a0b29a0caedf93e29201373.tar.bz2
power: bl33 add the power domain control API [1/1]
PD#SWPL-17563 Problem: add power domain control API for TM2 and SM1 Solution: add power domain control API for TM2 and SM1 Verify: T962E2 Change-Id: I5e0a642791d84cc9cdcf559432c855f745d4df51 Signed-off-by: zhiqiang liang <zhiqiang.liang@amlogic.com>
Diffstat
-rw-r--r--arch/arm/cpu/armv8/g12a/Makefile1
-rw-r--r--arch/arm/cpu/armv8/g12a/power_domain.c326
-rw-r--r--arch/arm/cpu/armv8/tm2/Makefile1
-rw-r--r--arch/arm/cpu/armv8/tm2/power_domain.c402
-rw-r--r--arch/arm/include/asm/arch-g12a/regs.h4
-rw-r--r--arch/arm/include/asm/arch-g12a/secure_apb.h7
-rw-r--r--include/amlogic/power_domain.h37
7 files changed, 776 insertions, 2 deletions
diff --git a/arch/arm/cpu/armv8/g12a/Makefile b/arch/arm/cpu/armv8/g12a/Makefile
index a3837c2..559f9cd 100644
--- a/arch/arm/cpu/armv8/g12a/Makefile
+++ b/arch/arm/cpu/armv8/g12a/Makefile
@@ -8,6 +8,7 @@ obj-y += timer.o
obj-y += mailbox.o
obj-y += gate_init.o
obj-y += power_cal.o
+obj-y += power_domain.o
obj-$(CONFIG_CMD_PLLTEST) += pll.o
obj-$(CONFIG_CMD_AML_MTEST) += core.o
obj-$(CONFIG_AML_HDMITX20) += sound.o
diff --git a/arch/arm/cpu/armv8/g12a/power_domain.c b/arch/arm/cpu/armv8/g12a/power_domain.c
new file mode 100644
index 0000000..5bbb95f
--- a/dev/null
+++ b/arch/arm/cpu/armv8/g12a/power_domain.c
@@ -0,0 +1,326 @@
+/*
+ * drivers/amlogic/power/power_domain.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/io.h>
+#include <asm/arch/regs.h>
+#include <asm/arch/secure_apb.h>
+#include <amlogic/power_domain.h>
+
+static void power_switch(int pwr_domain, bool pwr_switch)
+{
+ unsigned int value;
+
+ value = readl(AO_RTI_GEN_PWR_SLEEP0);
+ if (pwr_switch == PWR_ON)
+ value &= ~(1 << pwr_domain);
+ else
+ value |= (1 << pwr_domain);
+ writel(value, (AO_RTI_GEN_PWR_SLEEP0));
+}
+
+static void mem_pd_switch(int pwr_domain, bool pwr_switch)
+{
+ unsigned int value;
+
+ if (pwr_switch == PWR_ON) {
+ switch (pwr_domain) {
+ case PM_DOS_HCODEC:
+ writel(0x0, P_DOS_MEM_PD_HCODEC);
+ break;
+ case PM_DOS_VDEC:
+ writel(0x0, P_DOS_MEM_PD_VDEC);
+ break;
+ case PM_DOS_HEVC:
+ writel(0x0, P_DOS_MEM_PD_HEVC);
+ break;
+ case PM_WAVE420L:
+ writel(0x0, (P_DOS_MEM_PD_WAVE420L));
+ break;
+ case PM_CSI:
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0x3 << 6);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_VPU:
+ writel(0x0, HHI_VPU_MEM_PD_REG0);
+ writel(0x0, HHI_VPU_MEM_PD_REG1);
+ writel(0x0, HHI_VPU_MEM_PD_REG2);
+ writel(0x0, HHI_VPU_MEM_PD_REG3);
+ writel(0x0, HHI_VPU_MEM_PD_REG4);
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0xff << 8);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_NN:
+ writel(0x0, HHI_NANOQ_MEM_PD_REG0);
+ writel(0x0, HHI_NANOQ_MEM_PD_REG1);
+ break;
+ case PM_USB:
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0x3 << 30);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_PCIE0:
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0xf<<26);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_GE2D:
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0xff<<18);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ }
+ } else {
+ switch (pwr_domain) {
+ case PM_DOS_HCODEC:
+ writel(0xffffffff, P_DOS_MEM_PD_HCODEC);
+ break;
+ case PM_DOS_VDEC:
+ writel(0xffffffff, P_DOS_MEM_PD_VDEC);
+ break;
+ case PM_DOS_HEVC:
+ writel(0xffffffff, P_DOS_MEM_PD_HEVC);
+ break;
+ case PM_WAVE420L:
+ writel(0xffffffff, P_DOS_MEM_PD_WAVE420L);
+ break;
+ case PM_CSI:
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0x3 << 6);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_VPU:
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG0);
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG1);
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG2);
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG3);
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG4);
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0xff << 8);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_NN:
+ writel(0xffffffff, HHI_NANOQ_MEM_PD_REG0);
+ writel(0xffffffff, HHI_NANOQ_MEM_PD_REG1);
+ break;
+ case PM_USB:
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0x3 << 30);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_PCIE0:
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0xf<<26);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_GE2D:
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0xff<<18);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ }
+ }
+}
+
+static void reset_switch(int pwr_domain, bool pwr_switch)
+{
+ unsigned int value;
+ unsigned int tmp;
+
+ if (pwr_switch == PWR_ON) {
+ switch (pwr_domain) {
+ case PM_DOS_HCODEC:
+ value = readl(P_DOS_SW_RESET1);
+ value &= ~(0xffff<<2);
+ writel(value, P_DOS_SW_RESET1);
+ break;
+ case PM_DOS_VDEC:
+ value = readl(P_DOS_SW_RESET0);
+ value &= ~(0x1fff<<2);
+ writel(value, P_DOS_SW_RESET0);
+ break;
+ case PM_DOS_HEVC:
+ value = readl(P_DOS_SW_RESET3);
+ value &= ~(0x3ffff<<2 | 1<<24);
+ writel(value, P_DOS_SW_RESET3);
+ break;
+ case PM_WAVE420L:
+ value = readl(P_DOS_SW_RESET4);
+ value &= ~(0xf<<8);
+ writel(value, P_DOS_SW_RESET4);
+ break;
+ case PM_VPU:
+ tmp = 0x1 << 5 | 0x1 << 10 | 0x1 << 19 | 0x1 << 13;
+ value = readl(P_RESET0_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET0_LEVEL);
+ tmp = 0x1 << 5 | 0x1 << 4;
+ value = readl(P_RESET1_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET1_LEVEL);
+ tmp = 0x1 << 15;
+ value = readl(P_RESET2_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET2_LEVEL);
+ tmp = 0x1 << 6 | 0x1 << 7 | 0x1 << 13 |
+ 0x1 << 5 | 0x1 << 9 | 0x1 << 4 | 0x1 << 12;
+ value = readl(P_RESET4_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET4_LEVEL);
+ tmp = 0x1 << 7;
+ value = readl(P_RESET7_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET7_LEVEL);
+ break;
+ case PM_NN:
+ value = readl(P_RESET2_LEVEL);
+ value |= (0x1<<12);
+ writel(value, P_RESET2_LEVEL);
+ break;
+ case PM_USB:
+ value = readl(P_RESET1_LEVEL);
+ value |= (0x1<<2);
+ writel(value, P_RESET1_LEVEL);
+ break;
+ case PM_PCIE0:
+ value = readl(P_RESET0_LEVEL);
+ value |= ((0x1<<12)|(0x3<<14));
+ writel(value, P_RESET0_LEVEL);
+ break;
+ case PM_GE2D:
+ value = readl(P_RESET2_LEVEL);
+ value |= (0x1<<6);
+ writel(value, P_RESET2_LEVEL);
+ break;
+ }
+ } else {
+ switch (pwr_domain) {
+ case PM_DOS_HCODEC:
+ value = readl(P_DOS_SW_RESET1);
+ value |= (0xffff<<2);
+ writel(value, P_DOS_SW_RESET1);
+ break;
+ case PM_DOS_VDEC:
+ value = readl(P_DOS_SW_RESET0);
+ value |= (0x1fff<<2);
+ writel(value, P_DOS_SW_RESET0);
+ break;
+ case PM_DOS_HEVC:
+ value = readl(P_DOS_SW_RESET3);
+ value |= (0x3ffff<<2 | 1<<24);
+ writel(value, P_DOS_SW_RESET3);
+ break;
+ case PM_WAVE420L:
+ value = readl(P_DOS_SW_RESET4);
+ value |= (0xf<<8);
+ writel(value, P_DOS_SW_RESET4);
+ break;
+ case PM_VPU:
+ tmp = 0x1 << 5 | 0x1 << 10 | 0x1 << 19 | 0x1 << 13;
+ value = readl(P_RESET0_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET0_LEVEL);
+ tmp = 0x1 << 5 | 0x1 << 4;
+ value = readl(P_RESET1_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET1_LEVEL);
+ tmp = 0x1 << 15;
+ value = readl(P_RESET2_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET2_LEVEL);
+ tmp = 0x1 << 6 | 0x1 << 7 | 0x1 << 13 |
+ 0x1 << 5 | 0x1 << 9 | 0x1 << 4 | 0x1 << 12;
+ value = readl(P_RESET4_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET4_LEVEL);
+ tmp = 0x1 << 7;
+ value = readl(P_RESET7_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET7_LEVEL);
+ break;
+ case PM_NN:
+ value = readl(P_RESET2_LEVEL);
+ value &= ~(0x1<<12);
+ writel(value, P_RESET2_LEVEL);
+ break;
+ case PM_USB:
+ value = readl(P_RESET1_LEVEL);
+ value &= ~(0x1<<2);
+ writel(value, P_RESET1_LEVEL);
+ break;
+ case PM_PCIE0:
+ value = readl(P_RESET0_LEVEL);
+ value &= ~((0x1<<12)|(0x3<<14));
+ writel(value, P_RESET0_LEVEL);
+ break;
+ case PM_GE2D:
+ value = readl(P_RESET2_LEVEL);
+ value &= ~(0x1<<6);
+ writel(value, P_RESET2_LEVEL);
+ break;
+ }
+ }
+}
+
+static void iso_switch(int pwr_domain, bool pwr_switch)
+{
+ unsigned int value;
+
+ value = readl(AO_RTI_GEN_PWR_ISO0);
+ if (pwr_switch == PWR_ON)
+ value &= ~(1 << pwr_domain);
+ else
+ value |= (1 << pwr_domain);
+ writel(value, AO_RTI_GEN_PWR_ISO0);
+}
+
+void power_domain_switch(int pwr_domain, bool pwr_switch)
+{
+ if (pwr_switch == PWR_ON) {
+ /* Powerup Power Domain */
+ power_switch(pwr_domain, PWR_ON);
+ udelay(50);
+
+ /* Powerup memories */
+ mem_pd_switch(pwr_domain, PWR_ON);
+ udelay(150);
+
+ reset_switch(pwr_domain, PWR_OFF);
+
+ /* remove isolations */
+ iso_switch(pwr_domain, PWR_ON);
+
+ /* deassert reset */
+ reset_switch(pwr_domain, PWR_ON);
+
+ } else {
+ /* reset */
+ reset_switch(pwr_domain, PWR_OFF);
+
+ /* add isolation to domain */
+ iso_switch(pwr_domain, PWR_OFF);
+
+ /* Power down memories */
+ mem_pd_switch(pwr_domain, PWR_OFF);
+ udelay(50);
+
+ /* Power off domain */
+ power_switch(pwr_domain, PWR_OFF);
+ }
+}
diff --git a/arch/arm/cpu/armv8/tm2/Makefile b/arch/arm/cpu/armv8/tm2/Makefile
index 4be814b..0dc8fb4 100644
--- a/arch/arm/cpu/armv8/tm2/Makefile
+++ b/arch/arm/cpu/armv8/tm2/Makefile
@@ -8,6 +8,7 @@ obj-y += timer.o
obj-y += mailbox.o
obj-y += gate_init.o
obj-y += power_cal.o
+obj-y += power_domain.o
obj-$(CONFIG_CMD_PLLTEST) += pll.o
obj-$(CONFIG_CMD_AML_MTEST) += core.o
obj-$(CONFIG_CMD_HDMIRX) += hdmirx/ \ No newline at end of file
diff --git a/arch/arm/cpu/armv8/tm2/power_domain.c b/arch/arm/cpu/armv8/tm2/power_domain.c
new file mode 100644
index 0000000..1f8a479
--- a/dev/null
+++ b/arch/arm/cpu/armv8/tm2/power_domain.c
@@ -0,0 +1,402 @@
+/*
+ * drivers/amlogic/power/power_domain.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/io.h>
+#include <asm/arch/regs.h>
+#include <asm/arch/secure_apb.h>
+#include <amlogic/power_domain.h>
+
+static void power_switch(int pwr_domain, bool pwr_switch)
+{
+ unsigned int value;
+
+ value = readl(AO_RTI_GEN_PWR_SLEEP0);
+ if (pwr_switch == PWR_ON)
+ value &= ~(1 << pwr_domain);
+ else
+ value |= (1 << pwr_domain);
+ writel(value, (AO_RTI_GEN_PWR_SLEEP0));
+}
+
+static void mem_pd_switch(int pwr_domain, bool pwr_switch)
+{
+ unsigned int value;
+
+ if (pwr_switch == PWR_ON) {
+ switch (pwr_domain) {
+ case PM_DOS_HCODEC:
+ writel(0x0, P_DOS_MEM_PD_HCODEC);
+ break;
+ case PM_DOS_VDEC:
+ writel(0x0, P_DOS_MEM_PD_VDEC);
+ break;
+ case PM_DOS_HEVC:
+ writel(0x0, P_DOS_MEM_PD_HEVC);
+ break;
+ case PM_CSI:
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0x3 << 6);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_VPU:
+ writel(0x0, HHI_VPU_MEM_PD_REG0);
+ writel(0x0, HHI_VPU_MEM_PD_REG1);
+ writel(0x0, HHI_VPU_MEM_PD_REG2);
+ writel(0x0, HHI_VPU_MEM_PD_REG3);
+ writel(0x0, HHI_VPU_MEM_PD_REG4);
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0xff << 8);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_NN:
+ writel(0x0, HHI_NANOQ_MEM_PD_REG0);
+ writel(0x0, HHI_NANOQ_MEM_PD_REG1);
+ break;
+ case PM_USB:
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0x3 << 30);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_PCIE0:
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0xf<<26);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_GE2D:
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0xff<<18);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_PCIE1:
+ value = readl(HHI_MEM_PD_REG0);
+ value &= ~(0xf<<4);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_DSPA:
+ value = readl(HHI_DSP_MEM_PD_REG0);
+ value &= ~(0xffff);
+ writel(value, HHI_DSP_MEM_PD_REG0);
+ break;
+ case PM_DSPB:
+ value = readl(HHI_DSP_MEM_PD_REG0);
+ value &= ~(0xffff<<16);
+ writel(value, HHI_DSP_MEM_PD_REG0);
+ break;
+ case PM_DEMOD:
+ value = readl(HHI_DEMOD_MEM_PD_REG);
+ value &= ~0x2fff;
+ writel(value, HHI_DEMOD_MEM_PD_REG);
+ break;
+ }
+ } else {
+ switch (pwr_domain) {
+ case PM_DOS_HCODEC:
+ writel(0xffffffff, P_DOS_MEM_PD_HCODEC);
+ break;
+ case PM_DOS_VDEC:
+ writel(0xffffffff, P_DOS_MEM_PD_VDEC);
+ break;
+ case PM_DOS_HEVC:
+ writel(0xffffffff, P_DOS_MEM_PD_HEVC);
+ break;
+ case PM_CSI:
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0x3 << 6);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_VPU:
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG0);
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG1);
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG2);
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG3);
+ writel(0xffffffff, HHI_VPU_MEM_PD_REG4);
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0xff << 8);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_NN:
+ writel(0xffffffff, HHI_NANOQ_MEM_PD_REG0);
+ writel(0xffffffff, HHI_NANOQ_MEM_PD_REG1);
+ break;
+ case PM_USB:
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0x3 << 30);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_PCIE0:
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0xf<<26);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_GE2D:
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0xff<<18);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_PCIE1:
+ value = readl(HHI_MEM_PD_REG0);
+ value |= (0xf<<4);
+ writel(value, HHI_MEM_PD_REG0);
+ break;
+ case PM_DSPA:
+ value = readl(HHI_DSP_MEM_PD_REG0);
+ value |= (0xffff);
+ writel(value, HHI_DSP_MEM_PD_REG0);
+ break;
+ case PM_DSPB:
+ value = readl(HHI_DSP_MEM_PD_REG0);
+ value |= (0xffff<<16);
+ writel(value, HHI_DSP_MEM_PD_REG0);
+ break;
+ case PM_DEMOD:
+ value = readl(HHI_DEMOD_MEM_PD_REG);
+ value |= 0x2fff;
+ writel(value, HHI_DEMOD_MEM_PD_REG);
+ break;
+ }
+ }
+}
+
+static void reset_switch(int pwr_domain, bool pwr_switch)
+{
+ unsigned int value;
+ unsigned int tmp;
+
+ if (pwr_switch == PWR_ON) {
+ switch (pwr_domain) {
+ case PM_DOS_HCODEC:
+ value = readl(P_DOS_SW_RESET1);
+ value &= ~(0xffff<<2);
+ writel(value, P_DOS_SW_RESET1);
+ break;
+ case PM_DOS_VDEC:
+ value = readl(P_DOS_SW_RESET0);
+ value &= ~(0x1fff<<2);
+ writel(value, P_DOS_SW_RESET0);
+ break;
+ case PM_DOS_HEVC:
+ value = readl(P_DOS_SW_RESET3);
+ value &= ~(0x3ffff<<2 | 1<<24);
+ writel(value, P_DOS_SW_RESET3);
+ break;
+ case PM_VPU:
+ tmp = 0x1 << 5 | 0x1 << 10 | 0x1 << 19 | 0x1 << 13;
+ value = readl(P_RESET0_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET0_LEVEL);
+ tmp = 0x1 << 5 | 0x1 << 4;
+ value = readl(P_RESET1_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET1_LEVEL);
+ tmp = 0x1 << 15;
+ value = readl(P_RESET2_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET2_LEVEL);
+ tmp = 0x1 << 6 | 0x1 << 7 | 0x1 << 13 |
+ 0x1 << 5 | 0x1 << 9 | 0x1 << 4 | 0x1 << 12;
+ value = readl(P_RESET4_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET4_LEVEL);
+ tmp = 0x1 << 7;
+ value = readl(P_RESET7_LEVEL);
+ value |= tmp;
+ writel(value, P_RESET7_LEVEL);
+ break;
+ case PM_NN:
+ value = readl(P_RESET2_LEVEL);
+ value |= (0x1<<12);
+ writel(value, P_RESET2_LEVEL);
+ break;
+ case PM_USB:
+ value = readl(P_RESET1_LEVEL);
+ value |= (0x1<<2);
+ writel(value, P_RESET1_LEVEL);
+ break;
+ case PM_PCIE0:
+ value = readl(P_RESET0_LEVEL);
+ value |= ((0x1<<12)|(0x3<<14));
+ writel(value, P_RESET0_LEVEL);
+ break;
+ case PM_GE2D:
+ value = readl(P_RESET2_LEVEL);
+ value |= (0x1<<6);
+ writel(value, P_RESET2_LEVEL);
+ break;
+ case PM_PCIE1:
+ value = readl(P_RESET0_LEVEL);
+ value |= (0x7<<28);
+ writel(value, P_RESET0_LEVEL);
+ break;
+ case PM_DSPA:
+ value = readl(P_RESET4_LEVEL);
+ value |= 0x1;
+ writel(value, P_RESET4_LEVEL);
+ value = readl(P_RESET1_LEVEL);
+ value |= (0x1<<20);
+ writel(value, P_RESET1_LEVEL);
+ break;
+ case PM_DSPB:
+ value = readl(P_RESET4_LEVEL);
+ value |= (0x1<<1);
+ writel(value, P_RESET4_LEVEL);
+ value = readl(P_RESET1_LEVEL);
+ value |= (0x1<<21);
+ writel(value, P_RESET1_LEVEL);
+ break;
+ case PM_DEMOD:
+ value = readl(P_RESET0_LEVEL);
+ value |= (0x1<<8);
+ writel(value, P_RESET0_LEVEL);
+ break;
+ }
+ } else {
+ switch (pwr_domain) {
+ case PM_DOS_HCODEC:
+ value = readl(P_DOS_SW_RESET1);
+ value |= (0xffff<<2);
+ writel(value, P_DOS_SW_RESET1);
+ break;
+ case PM_DOS_VDEC:
+ value = readl(P_DOS_SW_RESET0);
+ value |= (0x1fff<<2);
+ writel(value, P_DOS_SW_RESET0);
+ break;
+ case PM_DOS_HEVC:
+ value = readl(P_DOS_SW_RESET3);
+ value |= (0x3ffff<<2 | 1<<24);
+ writel(value, P_DOS_SW_RESET3);
+ break;
+ case PM_VPU:
+ tmp = 0x1 << 5 | 0x1 << 10 | 0x1 << 19 | 0x1 << 13;
+ value = readl(P_RESET0_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET0_LEVEL);
+ tmp = 0x1 << 5 | 0x1 << 4;
+ value = readl(P_RESET1_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET1_LEVEL);
+ tmp = 0x1 << 15;
+ value = readl(P_RESET2_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET2_LEVEL);
+ tmp = 0x1 << 6 | 0x1 << 7 | 0x1 << 13 |
+ 0x1 << 5 | 0x1 << 9 | 0x1 << 4 | 0x1 << 12;
+ value = readl(P_RESET4_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET4_LEVEL);
+ tmp = 0x1 << 7;
+ value = readl(P_RESET7_LEVEL);
+ value &= ~tmp;
+ writel(value, P_RESET7_LEVEL);
+ break;
+ case PM_NN:
+ value = readl(P_RESET2_LEVEL);
+ value &= ~(0x1<<12);
+ writel(value, P_RESET2_LEVEL);
+ break;
+ case PM_USB:
+ value = readl(P_RESET1_LEVEL);
+ value &= ~(0x1<<2);
+ writel(value, P_RESET1_LEVEL);
+ break;
+ case PM_PCIE0:
+ value = readl(P_RESET0_LEVEL);
+ value &= ~((0x1<<12)|(0x3<<14));
+ writel(value, P_RESET0_LEVEL);
+ break;
+ case PM_GE2D:
+ value = readl(P_RESET2_LEVEL);
+ value &= ~(0x1<<6);
+ writel(value, P_RESET2_LEVEL);
+ break;
+ case PM_PCIE1:
+ value = readl(P_RESET0_LEVEL);
+ value &= ~(0x7<<28);
+ writel(value, P_RESET0_LEVEL);
+ break;
+ case PM_DSPA:
+ value = readl(P_RESET4_LEVEL);
+ value &= ~0x1;
+ writel(value, P_RESET4_LEVEL);
+ value = readl(P_RESET1_LEVEL);
+ value &= ~(0x1<<20);
+ writel(value, P_RESET1_LEVEL);
+ break;
+ case PM_DSPB:
+ value = readl(P_RESET4_LEVEL);
+ value &= ~(0x1<<1);
+ writel(value, P_RESET4_LEVEL);
+ value = readl(P_RESET1_LEVEL);
+ value &= ~(0x1<<21);
+ writel(value, P_RESET1_LEVEL);
+ break;
+ case PM_DEMOD:
+ value = readl(P_RESET0_LEVEL);
+ value &= ~(0x1<<8);
+ writel(value, P_RESET0_LEVEL);
+ break;
+ }
+ }
+}
+
+static void iso_switch(int pwr_domain, bool pwr_switch)
+{
+ unsigned int value;
+
+ value = readl(AO_RTI_GEN_PWR_ISO0);
+ if (pwr_switch == PWR_ON)
+ value &= ~(1 << pwr_domain);
+ else
+ value |= (1 << pwr_domain);
+ writel(value, AO_RTI_GEN_PWR_ISO0);
+}
+
+void power_domain_switch(int pwr_domain, bool pwr_switch)
+{
+ if (pwr_switch == PWR_ON) {
+ /* Powerup Power Domain */
+ power_switch(pwr_domain, PWR_ON);
+ udelay(50);
+
+ /* Powerup memories */
+ mem_pd_switch(pwr_domain, PWR_ON);
+ udelay(150);
+
+ reset_switch(pwr_domain, PWR_OFF);
+
+ /* remove isolations */
+ iso_switch(pwr_domain, PWR_ON);
+
+ /* deassert reset */
+ reset_switch(pwr_domain, PWR_ON);
+
+ } else {
+ /* reset */
+ reset_switch(pwr_domain, PWR_OFF);
+
+ /* add isolation to domain */
+ iso_switch(pwr_domain, PWR_OFF);
+
+ /* Power down memories */
+ mem_pd_switch(pwr_domain, PWR_OFF);
+ udelay(50);
+
+ /* Power off domain */
+ power_switch(pwr_domain, PWR_OFF);
+ }
+}
diff --git a/arch/arm/include/asm/arch-g12a/regs.h b/arch/arm/include/asm/arch-g12a/regs.h
index d5dfb56..931be25 100644
--- a/arch/arm/include/asm/arch-g12a/regs.h
+++ b/arch/arm/include/asm/arch-g12a/regs.h
@@ -6325,8 +6325,8 @@ Description:
#define P_DOS_SW_RESET4 (volatile unsigned int *)((0x3f37 << 2) + 0xff620000)
#define DOS_GCLK_EN4 (0x3f38)
#define P_DOS_GCLK_EN4 (volatile unsigned int *)((0x3f38 << 2) + 0xff620000)
-#define DOS_MEM_PD_VP9DEC (0x3f39)
-#define P_DOS_MEM_PD_VP9DEC (volatile unsigned int *)((0x3f39 << 2) + 0xff620000)
+#define DOS_MEM_PD_WAVE420L (0x3f39)
+#define P_DOS_MEM_PD_WAVE420L (volatile unsigned int *)((0x3f39 << 2) + 0xff620000)
// bit[31] mcrcc_stall_en
// bit[30:28] Reserved
// bit[27:20] target_canvas
diff --git a/arch/arm/include/asm/arch-g12a/secure_apb.h b/arch/arm/include/asm/arch-g12a/secure_apb.h
index e3e9c89..fb98665 100644
--- a/arch/arm/include/asm/arch-g12a/secure_apb.h
+++ b/arch/arm/include/asm/arch-g12a/secure_apb.h
@@ -2461,6 +2461,13 @@ Description:
#define HHI_VPU_MEM_PD_REG4 (0xff63c000 + (0x044 << 2))
#define SEC_HHI_VPU_MEM_PD_REG4 (0xff63c000 + (0x044 << 2))
#define P_HHI_VPU_MEM_PD_REG4 (volatile uint32_t *)(0xff63c000 + (0x044 << 2))
+#define HHI_NANOQ_MEM_PD_REG0 (0xff63c000 + (0x046 << 2))
+#define SEC_HHI_NANOQ_MEM_PD_REG0 (0xff63c000 + (0x046 << 2))
+#define P_HHI_NANOQ_MEM_PD_REG0 (volatile uint32_t *)(0xff63c000 + (0x046 << 2))
+#define HHI_NANOQ_MEM_PD_REG1 (0xff63c000 + (0x047 << 2))
+#define SEC_HHI_NANOQ_MEM_PD_REG1 (0xff63c000 + (0x047 << 2))
+#define P_HHI_NANOQ_MEM_PD_REG1 (volatile uint32_t *)(0xff63c000 + (0x047 << 2))
+
//`define HHI_DEMOD_MEM_PD_REG 8'h43
//`define HHI_AUD_DAC_CTRL 8'h44
// `define HHI_VIID_PLL_CNTL4 8'h46 // video PLL read back
diff --git a/include/amlogic/power_domain.h b/include/amlogic/power_domain.h
new file mode 100644
index 0000000..55a1ff6
--- a/dev/null
+++ b/include/amlogic/power_domain.h
@@ -0,0 +1,37 @@
+/*
+ * include/linux/amlogic/power_domain.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#define PWR_ON 0
+#define PWR_OFF 1
+
+#define PM_DOS_HCODEC 0
+#define PM_DOS_VDEC 1
+#define PM_DOS_HEVC 2
+#define PM_WAVE420L 3
+#define PM_CSI 6
+#define PM_VPU 8
+#define PM_NN 16
+#define PM_USB 17
+#define PM_PCIE0 18
+#define PM_GE2D 19
+#define PM_PCIE1 20
+#define PM_DSPA 21
+#define PM_DSPB 22
+#define PM_DEMOD 23
+
+void power_domain_switch(int pwr_domain, bool pwr_switch);
+