author | zhiqiang 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) |
commit | 70c3be46f69545089a0b29a0caedf93e29201373 (patch) | |
tree | 647355403dfce712c350776c6de9d9cb223428aa | |
parent | 3bfde1d85bb56d457183a8facf60a692fedb7891 (diff) | |
download | uboot-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>
-rw-r--r-- | arch/arm/cpu/armv8/g12a/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/g12a/power_domain.c | 326 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/tm2/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/cpu/armv8/tm2/power_domain.c | 402 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-g12a/regs.h | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/arch-g12a/secure_apb.h | 7 | ||||
-rw-r--r-- | include/amlogic/power_domain.h | 37 |
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); + |