mx7: psci: add basic psci support
1. add basic psci support for imx7 chip. 2. support cpu_on and cpu_off. 3. switch to non-secure mode when boot linux kernel. 4. set csu allow accessing all peripherial register in non-secure mode. Signed-off-by: Frank Li <Frank.Li@freescale.com> Signed-off-by: Peng Fan <Peng.Fan@freescale.com> Cc: Stefano Babic <sbabic@denx.de> Cc: Fabio Estevam <fabio.estevam@freescale.com>
This commit is contained in:
parent
d47cb0b61a
commit
7de4703691
5 changed files with 139 additions and 0 deletions
|
@ -6,3 +6,7 @@
|
|||
#
|
||||
|
||||
obj-y := soc.o clock.o clock_slice.o
|
||||
|
||||
ifdef CONFIG_ARMV7_PSCI
|
||||
obj-y += psci-mx7.o psci.o
|
||||
endif
|
||||
|
|
69
arch/arm/cpu/armv7/mx7/psci-mx7.c
Normal file
69
arch/arm/cpu/armv7/mx7/psci-mx7.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include <asm/io.h>
|
||||
#include <asm/psci.h>
|
||||
#include <asm/arch/imx-regs.h>
|
||||
#include <common.h>
|
||||
|
||||
#define __secure __attribute__((section("._secure.text")))
|
||||
|
||||
#define GPC_CPU_PGC_SW_PDN_REQ 0xfc
|
||||
#define GPC_CPU_PGC_SW_PUP_REQ 0xf0
|
||||
#define GPC_PGC_C1 0x840
|
||||
|
||||
#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2
|
||||
|
||||
/* below is for i.MX7D */
|
||||
#define SRC_GPR1_MX7D 0x074
|
||||
#define SRC_A7RCR0 0x004
|
||||
#define SRC_A7RCR1 0x008
|
||||
|
||||
#define BP_SRC_A7RCR0_A7_CORE_RESET0 0
|
||||
#define BP_SRC_A7RCR1_A7_CORE1_ENABLE 1
|
||||
|
||||
static inline void imx_gpcv2_set_m_core_pgc(bool enable, u32 offset)
|
||||
{
|
||||
writel(enable, GPC_IPS_BASE_ADDR + offset);
|
||||
}
|
||||
|
||||
__secure void imx_gpcv2_set_core1_power(bool pdn)
|
||||
{
|
||||
u32 reg = pdn ? GPC_CPU_PGC_SW_PUP_REQ : GPC_CPU_PGC_SW_PDN_REQ;
|
||||
u32 val;
|
||||
|
||||
imx_gpcv2_set_m_core_pgc(true, GPC_PGC_C1);
|
||||
|
||||
val = readl(GPC_IPS_BASE_ADDR + reg);
|
||||
val |= BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7;
|
||||
writel(val, GPC_IPS_BASE_ADDR + reg);
|
||||
|
||||
while ((readl(GPC_IPS_BASE_ADDR + reg) &
|
||||
BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7) != 0)
|
||||
;
|
||||
|
||||
imx_gpcv2_set_m_core_pgc(false, GPC_PGC_C1);
|
||||
}
|
||||
|
||||
__secure void imx_enable_cpu_ca7(int cpu, bool enable)
|
||||
{
|
||||
u32 mask, val;
|
||||
|
||||
mask = 1 << (BP_SRC_A7RCR1_A7_CORE1_ENABLE + cpu - 1);
|
||||
val = readl(SRC_BASE_ADDR + SRC_A7RCR1);
|
||||
val = enable ? val | mask : val & ~mask;
|
||||
writel(val, SRC_BASE_ADDR + SRC_A7RCR1);
|
||||
}
|
||||
|
||||
__secure int imx_cpu_on(int fn, int cpu, int pc)
|
||||
{
|
||||
writel(pc, SRC_BASE_ADDR + cpu * 8 + SRC_GPR1_MX7D);
|
||||
imx_gpcv2_set_core1_power(true);
|
||||
imx_enable_cpu_ca7(cpu, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__secure int imx_cpu_off(int cpu)
|
||||
{
|
||||
imx_enable_cpu_ca7(cpu, false);
|
||||
imx_gpcv2_set_core1_power(false);
|
||||
writel(0, SRC_BASE_ADDR + cpu * 8 + SRC_GPR1_MX7D + 4);
|
||||
return 0;
|
||||
}
|
54
arch/arm/cpu/armv7/mx7/psci.S
Normal file
54
arch/arm/cpu/armv7/mx7/psci.S
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include <config.h>
|
||||
#include <linux/linkage.h>
|
||||
|
||||
#include <asm/armv7.h>
|
||||
#include <asm/arch-armv7/generictimer.h>
|
||||
#include <asm/psci.h>
|
||||
|
||||
.pushsection ._secure.text, "ax"
|
||||
|
||||
.arch_extension sec
|
||||
|
||||
@ r1 = target CPU
|
||||
@ r2 = target PC
|
||||
|
||||
.globl psci_arch_init
|
||||
psci_arch_init:
|
||||
mov r6, lr
|
||||
|
||||
bl psci_get_cpu_id
|
||||
bl psci_get_cpu_stack_top
|
||||
mov sp, r0
|
||||
|
||||
bx r6
|
||||
|
||||
@ r1 = target CPU
|
||||
@ r2 = target PC
|
||||
|
||||
.globl psci_cpu_on
|
||||
psci_cpu_on:
|
||||
push {lr}
|
||||
|
||||
mov r0, r1
|
||||
bl psci_get_cpu_stack_top
|
||||
str r2, [r0]
|
||||
dsb
|
||||
|
||||
ldr r2, =psci_cpu_entry
|
||||
bl imx_cpu_on
|
||||
|
||||
pop {pc}
|
||||
|
||||
.globl psci_cpu_off
|
||||
psci_cpu_off:
|
||||
|
||||
bl psci_cpu_off_common
|
||||
bl psci_get_cpu_id
|
||||
bl imx_cpu_off
|
||||
|
||||
1: wfi
|
||||
b 1b
|
||||
|
||||
.globl psci_text_end
|
||||
psci_text_end:
|
||||
.popsection
|
|
@ -122,10 +122,19 @@ u32 __weak get_board_rev(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* enable all periherial can be accessed in nosec mode */
|
||||
static void init_csu(void)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < CSU_NUM_REGS; i++)
|
||||
writel(CSU_INIT_SEC_LEVEL0, CSU_IPS_BASE_ADDR + i * 4);
|
||||
}
|
||||
|
||||
int arch_cpu_init(void)
|
||||
{
|
||||
init_aips();
|
||||
|
||||
init_csu();
|
||||
/* Disable PDE bit of WMCR register */
|
||||
imx_set_wdog_powerdown(false);
|
||||
|
||||
|
|
|
@ -866,6 +866,9 @@ struct cspi_regs {
|
|||
ECSPI3_BASE_ADDR, \
|
||||
ECSPI4_BASE_ADDR
|
||||
|
||||
#define CSU_INIT_SEC_LEVEL0 0x00FF00FF
|
||||
#define CSU_NUM_REGS 64
|
||||
|
||||
struct ocotp_regs {
|
||||
u32 ctrl;
|
||||
u32 ctrl_set;
|
||||
|
|
Loading…
Reference in a new issue