1019 lines
29 KiB
Diff
1019 lines
29 KiB
Diff
|
From c7b16d749d1746e3ab081f8550c3aba252969d26 Mon Sep 17 00:00:00 2001
|
||
|
From: Dan Johansen <strit@manjaro.org>
|
||
|
Date: Mon, 1 Jun 2020 23:14:16 +0200
|
||
|
Subject: [PATCH] add suspend to rk3399/PBP
|
||
|
|
||
|
---
|
||
|
.../soc/rockchip/rockchip-pm-config.txt | 40 +++
|
||
|
.../boot/dts/rockchip/rk3399-pinebook-pro.dts | 35 +++
|
||
|
arch/arm64/boot/dts/rockchip/rk3399.dtsi | 24 ++
|
||
|
drivers/firmware/Kconfig | 7 +
|
||
|
drivers/firmware/Makefile | 1 +
|
||
|
drivers/firmware/rockchip_sip.c | 263 ++++++++++++++++++
|
||
|
drivers/regulator/core.c | 49 +++-
|
||
|
drivers/soc/rockchip/Kconfig | 6 +
|
||
|
drivers/soc/rockchip/Makefile | 1 +
|
||
|
drivers/soc/rockchip/rockchip_pm_config.c | 213 ++++++++++++++
|
||
|
include/dt-bindings/suspend/rockchip-rk3399.h | 60 ++++
|
||
|
include/linux/regulator/driver.h | 3 +
|
||
|
include/linux/rockchip/rockchip_sip.h | 149 ++++++++++
|
||
|
13 files changed, 847 insertions(+), 4 deletions(-)
|
||
|
create mode 100644 Documentation/devicetree/bindings/soc/rockchip/rockchip-pm-config.txt
|
||
|
create mode 100644 drivers/firmware/rockchip_sip.c
|
||
|
create mode 100644 drivers/soc/rockchip/rockchip_pm_config.c
|
||
|
create mode 100644 include/dt-bindings/suspend/rockchip-rk3399.h
|
||
|
create mode 100644 include/linux/rockchip/rockchip_sip.h
|
||
|
|
||
|
diff --git a/Documentation/devicetree/bindings/soc/rockchip/rockchip-pm-config.txt b/Documentation/devicetree/bindings/soc/rockchip/rockchip-pm-config.txt
|
||
|
new file mode 100644
|
||
|
index 000000000000..e15af33d3a9f
|
||
|
--- /dev/null
|
||
|
+++ b/Documentation/devicetree/bindings/soc/rockchip/rockchip-pm-config.txt
|
||
|
@@ -0,0 +1,40 @@
|
||
|
+* the suspend mode config
|
||
|
+
|
||
|
+- compatible: "rockchip,pm-config"
|
||
|
+ Compatibility with rk3399
|
||
|
+
|
||
|
+- rockchip,sleep-mode-config : the sleep mode config,
|
||
|
+ ARMOFF, OSC disabled ...
|
||
|
+
|
||
|
+- rockchip,wakeup-config: the wake up sourece enable.
|
||
|
+ GPIO, USB, SD...
|
||
|
+
|
||
|
+- rockchip,pwm-regulator-config: the pwm regulator name.
|
||
|
+
|
||
|
+Example:
|
||
|
+ rockchip_suspend: rockchip_suspend {
|
||
|
+ compatible = "rockchip,pm-rk3399";
|
||
|
+ status = "okay";
|
||
|
+ rockchip,sleep-mode-config = <
|
||
|
+ (0
|
||
|
+ | RKPM_SLP_ARMPD
|
||
|
+ | RKPM_SLP_PERILPPD
|
||
|
+ | RKPM_SLP_DDR_RET
|
||
|
+ | RKPM_SLP_PLLPD
|
||
|
+ | RKPM_SLP_OSC_DIS
|
||
|
+ | RKPM_SLP_CENTER_PD
|
||
|
+ | RKPM_SLP_AP_PWROFF
|
||
|
+ )
|
||
|
+ >;
|
||
|
+ rockchip,wakeup-config = <
|
||
|
+ (0 |
|
||
|
+ RKPM_GPIO_WKUP_EN |
|
||
|
+ RKPM_PWM_WKUP_EN)
|
||
|
+ >;
|
||
|
+ rockchip,pwm-regulator-config = <
|
||
|
+ (0 |
|
||
|
+ PWM2_REGULATOR_EN
|
||
|
+ )
|
||
|
+ >;
|
||
|
+ };
|
||
|
+
|
||
|
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
|
||
|
index c49982dfd8fc..9643cae1537a 100644
|
||
|
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
|
||
|
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinebook-pro.dts
|
||
|
@@ -19,9 +19,15 @@ / {
|
||
|
compatible = "pine64,pinebook-pro", "rockchip,rk3399";
|
||
|
|
||
|
chosen {
|
||
|
+ bootargs = "earlycon=uart8250,mmio32,0xff1a0000";
|
||
|
stdout-path = "serial2:1500000n8";
|
||
|
};
|
||
|
|
||
|
+ memory {
|
||
|
+ device_type = "memory";
|
||
|
+ reg = <0x0 0x00200000 0x0 0xf7e00000>;
|
||
|
+ };
|
||
|
+
|
||
|
backlight: edp-backlight {
|
||
|
compatible = "pwm-backlight";
|
||
|
power-supply = <&vcc_12v>;
|
||
|
@@ -125,6 +131,12 @@ sdio_pwrseq: sdio-pwrseq {
|
||
|
reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
|
||
|
};
|
||
|
|
||
|
+ /* first 128k(0xff8d0000~0xff8f0000) for ddr and ATF */
|
||
|
+ sram@ff8d0000 {
|
||
|
+ compatible = "mmio-sram";
|
||
|
+ reg = <0x0 0xff8d0000 0x0 0x20000>; /* 128k */
|
||
|
+ };
|
||
|
+
|
||
|
/* Audio components */
|
||
|
es8316-sound {
|
||
|
compatible = "simple-audio-card";
|
||
|
@@ -906,6 +918,29 @@ &pwm2 {
|
||
|
status = "okay";
|
||
|
};
|
||
|
|
||
|
+&rockchip_suspend {
|
||
|
+ status = "okay";
|
||
|
+ rockchip,sleep-debug-en = <1>;
|
||
|
+ rockchip,sleep-mode-config = <
|
||
|
+ (0
|
||
|
+ | RKPM_SLP_ARMPD
|
||
|
+ | RKPM_SLP_PERILPPD
|
||
|
+ | RKPM_SLP_DDR_RET
|
||
|
+ | RKPM_SLP_PLLPD
|
||
|
+ | RKPM_SLP_CENTER_PD
|
||
|
+ | RKPM_SLP_AP_PWROFF
|
||
|
+ )
|
||
|
+ >;
|
||
|
+ rockchip,pwm-regulator-config = <
|
||
|
+ (0
|
||
|
+ | PWM2_REGULATOR_EN
|
||
|
+ )
|
||
|
+ >;
|
||
|
+ rockchip,power-ctrl =
|
||
|
+ <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>,
|
||
|
+ <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>;
|
||
|
+};
|
||
|
+
|
||
|
&saradc {
|
||
|
vref-supply = <&vcca1v8_s3>;
|
||
|
status = "okay";
|
||
|
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
|
||
|
index 1448f358ed0a..a91fc5c8b43b 100644
|
||
|
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
|
||
|
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
|
||
|
@@ -9,6 +9,7 @@
|
||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||
|
#include <dt-bindings/pinctrl/rockchip.h>
|
||
|
#include <dt-bindings/power/rk3399-power.h>
|
||
|
+#include <dt-bindings/suspend/rockchip-rk3399.h>
|
||
|
#include <dt-bindings/thermal/thermal.h>
|
||
|
|
||
|
/ {
|
||
|
@@ -2652,4 +2653,27 @@ pcie_clkreqnb_cpm: pci-clkreqnb-cpm {
|
||
|
};
|
||
|
|
||
|
};
|
||
|
+
|
||
|
+ rockchip_suspend: rockchip-suspend {
|
||
|
+ compatible = "rockchip,pm-rk3399";
|
||
|
+ status = "disabled";
|
||
|
+ rockchip,sleep-debug-en = <0>;
|
||
|
+ rockchip,virtual-poweroff = <0>;
|
||
|
+ rockchip,sleep-mode-config = <
|
||
|
+ (0
|
||
|
+ | RKPM_SLP_ARMPD
|
||
|
+ | RKPM_SLP_PERILPPD
|
||
|
+ | RKPM_SLP_DDR_RET
|
||
|
+ | RKPM_SLP_PLLPD
|
||
|
+ | RKPM_SLP_OSC_DIS
|
||
|
+ | RKPM_SLP_CENTER_PD
|
||
|
+ | RKPM_SLP_AP_PWROFF
|
||
|
+ )
|
||
|
+ >;
|
||
|
+ rockchip,wakeup-config = <
|
||
|
+ (0
|
||
|
+ | RKPM_GPIO_WKUP_EN
|
||
|
+ )
|
||
|
+ >;
|
||
|
+ };
|
||
|
};
|
||
|
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
|
||
|
index 8007d4aa76dc..37f8039a5e27 100644
|
||
|
--- a/drivers/firmware/Kconfig
|
||
|
+++ b/drivers/firmware/Kconfig
|
||
|
@@ -296,6 +296,13 @@
|
||
|
other manufacturing data and also utilize the Entropy Bit Generator
|
||
|
for hardware random number generation.
|
||
|
|
||
|
+config ROCKCHIP_SIP
|
||
|
+ bool "Rockchip SIP interface"
|
||
|
+ depends on ARM64 && ARM_PSCI_FW
|
||
|
+ help
|
||
|
+ Say Y here if you want to enable SIP callbacks for Rockchip platforms
|
||
|
+ This option enables support for communicating with the ATF.
|
||
|
+
|
||
|
source "drivers/firmware/arm_ffa/Kconfig"
|
||
|
source "drivers/firmware/broadcom/Kconfig"
|
||
|
source "drivers/firmware/google/Kconfig"
|
||
|
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
|
||
|
index e9fb838af4df..575f45d55939 100644
|
||
|
--- a/drivers/firmware/Makefile
|
||
|
+++ b/drivers/firmware/Makefile
|
||
|
@@ -29,6 +29,7 @@ obj-y += meson/
|
||
|
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
|
||
|
obj-$(CONFIG_EFI) += efi/
|
||
|
obj-$(CONFIG_UEFI_CPER) += efi/
|
||
|
+obj-$(CONFIG_ROCKCHIP_SIP) += rockchip_sip.o
|
||
|
obj-y += imx/
|
||
|
obj-y += tegra/
|
||
|
obj-y += xilinx/
|
||
|
diff --git a/drivers/firmware/rockchip_sip.c b/drivers/firmware/rockchip_sip.c
|
||
|
new file mode 100644
|
||
|
index 000000000000..6844c5bad5b1
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/firmware/rockchip_sip.c
|
||
|
@@ -0,0 +1,263 @@
|
||
|
+/*
|
||
|
+ * This program is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License version 2 as
|
||
|
+ * published by the Free Software Foundation.
|
||
|
+ *
|
||
|
+ * This program is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * Copyright (C) 2016, Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ */
|
||
|
+
|
||
|
+#include <linux/arm-smccc.h>
|
||
|
+#include <linux/io.h>
|
||
|
+#include <linux/rockchip/rockchip_sip.h>
|
||
|
+#include <asm/cputype.h>
|
||
|
+#include <asm/smp_plat.h>
|
||
|
+#include <uapi/linux/psci.h>
|
||
|
+#include <linux/ptrace.h>
|
||
|
+
|
||
|
+#ifdef CONFIG_64BIT
|
||
|
+#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name
|
||
|
+#else
|
||
|
+#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name
|
||
|
+#endif
|
||
|
+
|
||
|
+#define SIZE_PAGE(n) ((n) << 12)
|
||
|
+
|
||
|
+static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
|
||
|
+ unsigned long arg0,
|
||
|
+ unsigned long arg1,
|
||
|
+ unsigned long arg2)
|
||
|
+{
|
||
|
+ struct arm_smccc_res res;
|
||
|
+
|
||
|
+ arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
|
||
|
+ return res;
|
||
|
+}
|
||
|
+
|
||
|
+struct arm_smccc_res sip_smc_ddr_cfg(u32 arg0, u32 arg1, u32 arg2)
|
||
|
+{
|
||
|
+ return __invoke_sip_fn_smc(SIP_DDR_CFG, arg0, arg1, arg2);
|
||
|
+}
|
||
|
+
|
||
|
+struct arm_smccc_res sip_smc_get_atf_version(void)
|
||
|
+{
|
||
|
+ return __invoke_sip_fn_smc(SIP_ATF_VERSION, 0, 0, 0);
|
||
|
+}
|
||
|
+
|
||
|
+struct arm_smccc_res sip_smc_get_sip_version(void)
|
||
|
+{
|
||
|
+ return __invoke_sip_fn_smc(SIP_SIP_VERSION, 0, 0, 0);
|
||
|
+}
|
||
|
+
|
||
|
+int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2)
|
||
|
+{
|
||
|
+ struct arm_smccc_res res;
|
||
|
+
|
||
|
+ res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE, ctrl, config1, config2);
|
||
|
+ return res.a0;
|
||
|
+}
|
||
|
+
|
||
|
+int sip_smc_virtual_poweroff(void)
|
||
|
+{
|
||
|
+ struct arm_smccc_res res;
|
||
|
+
|
||
|
+ res = __invoke_sip_fn_smc(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND), 0, 0, 0);
|
||
|
+ return res.a0;
|
||
|
+}
|
||
|
+
|
||
|
+struct arm_smccc_res sip_smc_request_share_mem(u32 page_num,
|
||
|
+ share_page_type_t page_type)
|
||
|
+{
|
||
|
+ struct arm_smccc_res res;
|
||
|
+ unsigned long share_mem_phy;
|
||
|
+
|
||
|
+ res = __invoke_sip_fn_smc(SIP_SHARE_MEM, page_num, page_type, 0);
|
||
|
+ if (IS_SIP_ERROR(res.a0))
|
||
|
+ goto error;
|
||
|
+
|
||
|
+ share_mem_phy = res.a1;
|
||
|
+ res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
|
||
|
+
|
||
|
+error:
|
||
|
+ return res;
|
||
|
+}
|
||
|
+
|
||
|
+struct arm_smccc_res sip_smc_mcu_el3fiq(u32 arg0, u32 arg1, u32 arg2)
|
||
|
+{
|
||
|
+ return __invoke_sip_fn_smc(SIP_MCU_EL3FIQ_CFG, arg0, arg1, arg2);
|
||
|
+}
|
||
|
+
|
||
|
+/************************** fiq debugger **************************************/
|
||
|
+#ifdef CONFIG_ARM64
|
||
|
+#define SIP_UARTDBG_FN SIP_UARTDBG_CFG64
|
||
|
+#else
|
||
|
+#define SIP_UARTDBG_FN SIP_UARTDBG_CFG
|
||
|
+#endif
|
||
|
+
|
||
|
+static int fiq_sip_enabled;
|
||
|
+static int fiq_target_cpu;
|
||
|
+static phys_addr_t ft_fiq_mem_phy;
|
||
|
+static void __iomem *ft_fiq_mem_base;
|
||
|
+static void (*sip_fiq_debugger_uart_irq_tf)(struct pt_regs _pt_regs,
|
||
|
+ unsigned long cpu);
|
||
|
+int sip_fiq_debugger_is_enabled(void)
|
||
|
+{
|
||
|
+ return fiq_sip_enabled;
|
||
|
+}
|
||
|
+
|
||
|
+static struct pt_regs sip_fiq_debugger_get_pt_regs(void *reg_base,
|
||
|
+ unsigned long sp_el1)
|
||
|
+{
|
||
|
+ struct pt_regs fiq_pt_regs;
|
||
|
+
|
||
|
+#ifdef CONFIG_ARM64
|
||
|
+ /* copy cpu context */
|
||
|
+ memcpy(&fiq_pt_regs, reg_base, 8 * 31);
|
||
|
+
|
||
|
+ /* copy pstate */
|
||
|
+ memcpy(&fiq_pt_regs.pstate, reg_base + 0x110, 8);
|
||
|
+
|
||
|
+ /* EL1 mode */
|
||
|
+ if (fiq_pt_regs.pstate & 0x10)
|
||
|
+ memcpy(&fiq_pt_regs.sp, reg_base + 0xf8, 8);
|
||
|
+ /* EL0 mode */
|
||
|
+ else
|
||
|
+ fiq_pt_regs.sp = sp_el1;
|
||
|
+
|
||
|
+ /* copy pc */
|
||
|
+ memcpy(&fiq_pt_regs.pc, reg_base + 0x118, 8);
|
||
|
+#else
|
||
|
+ struct sm_nsec_ctx *nsec_ctx = reg_base;
|
||
|
+
|
||
|
+ fiq_pt_regs.ARM_r0 = nsec_ctx->r0;
|
||
|
+ fiq_pt_regs.ARM_r1 = nsec_ctx->r1;
|
||
|
+ fiq_pt_regs.ARM_r2 = nsec_ctx->r2;
|
||
|
+ fiq_pt_regs.ARM_r3 = nsec_ctx->r3;
|
||
|
+ fiq_pt_regs.ARM_r4 = nsec_ctx->r4;
|
||
|
+ fiq_pt_regs.ARM_r5 = nsec_ctx->r5;
|
||
|
+ fiq_pt_regs.ARM_r6 = nsec_ctx->r6;
|
||
|
+ fiq_pt_regs.ARM_r7 = nsec_ctx->r7;
|
||
|
+ fiq_pt_regs.ARM_r8 = nsec_ctx->r8;
|
||
|
+ fiq_pt_regs.ARM_r9 = nsec_ctx->r9;
|
||
|
+ fiq_pt_regs.ARM_r10 = nsec_ctx->r10;
|
||
|
+ fiq_pt_regs.ARM_fp = nsec_ctx->r11;
|
||
|
+ fiq_pt_regs.ARM_ip = nsec_ctx->r12;
|
||
|
+ fiq_pt_regs.ARM_sp = nsec_ctx->svc_sp;
|
||
|
+ fiq_pt_regs.ARM_lr = nsec_ctx->svc_lr;
|
||
|
+ fiq_pt_regs.ARM_pc = nsec_ctx->mon_lr;
|
||
|
+ fiq_pt_regs.ARM_cpsr = nsec_ctx->mon_spsr;
|
||
|
+#endif
|
||
|
+
|
||
|
+ return fiq_pt_regs;
|
||
|
+}
|
||
|
+
|
||
|
+static void sip_fiq_debugger_uart_irq_tf_cb(unsigned long sp_el1,
|
||
|
+ unsigned long offset,
|
||
|
+ unsigned long cpu)
|
||
|
+{
|
||
|
+ struct pt_regs fiq_pt_regs;
|
||
|
+ char *cpu_context;
|
||
|
+
|
||
|
+ /* calling fiq handler */
|
||
|
+ if (ft_fiq_mem_base) {
|
||
|
+ cpu_context = (char *)ft_fiq_mem_base + offset;
|
||
|
+ fiq_pt_regs = sip_fiq_debugger_get_pt_regs(cpu_context, sp_el1);
|
||
|
+ sip_fiq_debugger_uart_irq_tf(fiq_pt_regs, cpu);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* fiq handler done, return to EL3(then EL3 return to EL1 entry) */
|
||
|
+ __invoke_sip_fn_smc(SIP_UARTDBG_FN, 0, 0, UARTDBG_CFG_OSHDL_TO_OS);
|
||
|
+}
|
||
|
+
|
||
|
+int sip_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback_fn)
|
||
|
+{
|
||
|
+ struct arm_smccc_res res;
|
||
|
+
|
||
|
+ fiq_target_cpu = 0;
|
||
|
+
|
||
|
+ /* init fiq debugger callback */
|
||
|
+ sip_fiq_debugger_uart_irq_tf = callback_fn;
|
||
|
+ res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, irq_id,
|
||
|
+ (unsigned long)sip_fiq_debugger_uart_irq_tf_cb,
|
||
|
+ UARTDBG_CFG_INIT);
|
||
|
+ if (IS_SIP_ERROR(res.a0)) {
|
||
|
+ pr_err("%s error: %d\n", __func__, (int)res.a0);
|
||
|
+ return res.a0;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* share memory ioremap */
|
||
|
+ if (!ft_fiq_mem_base) {
|
||
|
+ ft_fiq_mem_phy = res.a1;
|
||
|
+ ft_fiq_mem_base = ioremap(ft_fiq_mem_phy,
|
||
|
+ FIQ_UARTDBG_SHARE_MEM_SIZE);
|
||
|
+ if (!ft_fiq_mem_base) {
|
||
|
+ pr_err("%s: share memory ioremap failed\n", __func__);
|
||
|
+ return -ENOMEM;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ fiq_sip_enabled = 1;
|
||
|
+
|
||
|
+ return SIP_RET_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+int sip_fiq_debugger_switch_cpu(u32 cpu)
|
||
|
+{
|
||
|
+ struct arm_smccc_res res;
|
||
|
+
|
||
|
+ fiq_target_cpu = cpu;
|
||
|
+ res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, cpu_logical_map(cpu),
|
||
|
+ 0, UARTDBG_CFG_OSHDL_CPUSW);
|
||
|
+ return res.a0;
|
||
|
+}
|
||
|
+
|
||
|
+void sip_fiq_debugger_enable_debug(bool enable)
|
||
|
+{
|
||
|
+ unsigned long val;
|
||
|
+
|
||
|
+ val = enable ? UARTDBG_CFG_OSHDL_DEBUG_ENABLE :
|
||
|
+ UARTDBG_CFG_OSHDL_DEBUG_DISABLE;
|
||
|
+
|
||
|
+ __invoke_sip_fn_smc(SIP_UARTDBG_FN, 0, 0, val);
|
||
|
+}
|
||
|
+
|
||
|
+int sip_fiq_debugger_set_print_port(u32 port_phyaddr, u32 baudrate)
|
||
|
+{
|
||
|
+ struct arm_smccc_res res;
|
||
|
+
|
||
|
+ res = __invoke_sip_fn_smc(SIP_UARTDBG_FN, port_phyaddr, baudrate,
|
||
|
+ UARTDBG_CFG_PRINT_PORT);
|
||
|
+ return res.a0;
|
||
|
+}
|
||
|
+
|
||
|
+int sip_fiq_debugger_request_share_memory(void)
|
||
|
+{
|
||
|
+ struct arm_smccc_res res;
|
||
|
+
|
||
|
+ /* request page share memory */
|
||
|
+ res = sip_smc_request_share_mem(FIQ_UARTDBG_PAGE_NUMS,
|
||
|
+ SHARE_PAGE_TYPE_UARTDBG);
|
||
|
+ if (IS_SIP_ERROR(res.a0))
|
||
|
+ return res.a0;
|
||
|
+
|
||
|
+ return SIP_RET_SUCCESS;
|
||
|
+}
|
||
|
+
|
||
|
+int sip_fiq_debugger_get_target_cpu(void)
|
||
|
+{
|
||
|
+ return fiq_target_cpu;
|
||
|
+}
|
||
|
+
|
||
|
+void sip_fiq_debugger_enable_fiq(bool enable, uint32_t tgt_cpu)
|
||
|
+{
|
||
|
+ u32 en;
|
||
|
+
|
||
|
+ fiq_target_cpu = tgt_cpu;
|
||
|
+ en = enable ? UARTDBG_CFG_FIQ_ENABEL : UARTDBG_CFG_FIQ_DISABEL;
|
||
|
+ __invoke_sip_fn_smc(SIP_UARTDBG_FN, tgt_cpu, 0, en);
|
||
|
+}
|
||
|
+
|
||
|
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
|
||
|
index 7486f6e4e613..d46a267ea309 100644
|
||
|
--- a/drivers/regulator/core.c
|
||
|
+++ b/drivers/regulator/core.c
|
||
|
@@ -5268,6 +5268,14 @@ void regulator_unregister(struct regulator_dev *rdev)
|
||
|
EXPORT_SYMBOL_GPL(regulator_unregister);
|
||
|
|
||
|
#ifdef CONFIG_SUSPEND
|
||
|
+static inline int can_enable(struct regulator_dev *rdev) {
|
||
|
+ return rdev->ena_pin || rdev->desc->ops->enable;
|
||
|
+}
|
||
|
+
|
||
|
+static inline int can_disable(struct regulator_dev *rdev) {
|
||
|
+ return rdev->ena_pin || rdev->desc->ops->disable;
|
||
|
+}
|
||
|
+
|
||
|
/**
|
||
|
* regulator_suspend - prepare regulators for system wide suspend
|
||
|
* @dev: ``&struct device`` pointer that is passed to _regulator_suspend()
|
||
|
@@ -5430,6 +5438,21 @@ static int regulator_suspend(struct device *dev)
|
||
|
|
||
|
regulator_lock(rdev);
|
||
|
ret = __suspend_set_state(rdev, rstate);
|
||
|
+
|
||
|
+ if (rstate->enabled == ENABLE_IN_SUSPEND && can_enable(rdev)) {
|
||
|
+ if (!rdev->desc->ops->set_suspend_enable) {
|
||
|
+ rdev->resume_state = _regulator_is_enabled(rdev);
|
||
|
+ rdev_info(rdev, "Entering suspend %d, enabling forcibly, was %s\n", state, rdev->resume_state ? "on" : "off");
|
||
|
+ ret = _regulator_do_enable(rdev);
|
||
|
+ }
|
||
|
+ } else if (rstate->enabled == DISABLE_IN_SUSPEND && can_disable(rdev)) {
|
||
|
+ if (!rdev->desc->ops->set_suspend_disable) {
|
||
|
+ rdev->resume_state = _regulator_is_enabled(rdev);
|
||
|
+ rdev_info(rdev, "Entering suspend %d, disabling forcibly, was %s\n", state, rdev->resume_state ? "on" : "off");
|
||
|
+ ret = _regulator_do_disable(rdev);
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
regulator_unlock(rdev);
|
||
|
|
||
|
return ret;
|
||
|
@@ -5452,9 +5475,19 @@ static int regulator_resume(struct device *dev)
|
||
|
|
||
|
regulator_lock(rdev);
|
||
|
|
||
|
- if (rstate->enabled == ENABLE_IN_SUSPEND ||
|
||
|
- rstate->enabled == DISABLE_IN_SUSPEND)
|
||
|
- ret = rdev->desc->ops->resume(rdev);
|
||
|
+ if (rstate->enabled == ENABLE_IN_SUSPEND || rstate->enabled == DISABLE_IN_SUSPEND) {
|
||
|
+ if (rdev->desc->ops->resume) {
|
||
|
+ ret = rdev->desc->ops->resume(rdev);
|
||
|
+ } else if ((rstate->enabled == ENABLE_IN_SUSPEND && !rdev->desc->ops->set_suspend_enable) ||
|
||
|
+ (rstate->enabled == DISABLE_IN_SUSPEND && !rdev->desc->ops->set_suspend_disable)) {
|
||
|
+ rdev_info(rdev, "Resuming, restoring state to %s\n", rdev->resume_state ? "on" : "off");
|
||
|
+ if (rdev->resume_state && can_enable(rdev)) {
|
||
|
+ ret = _regulator_do_enable(rdev);
|
||
|
+ } else if (!rdev->resume_state && can_disable(rdev)) {
|
||
|
+ ret = _regulator_do_disable(rdev);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
|
||
|
regulator_unlock(rdev);
|
||
|
|
||
|
diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig
|
||
|
index b71b73bf5fc5..bfadbecd0df8 100644
|
||
|
--- a/drivers/soc/rockchip/Kconfig
|
||
|
+++ b/drivers/soc/rockchip/Kconfig
|
||
|
@@ -26,4 +26,10 @@ config ROCKCHIP_PM_DOMAINS
|
||
|
|
||
|
If unsure, say N.
|
||
|
|
||
|
+config ROCKCHIP_SUSPEND_MODE
|
||
|
+ bool "Rockchip suspend mode config"
|
||
|
+ depends on ROCKCHIP_SIP
|
||
|
+ help
|
||
|
+ Say Y here if you want to set the suspend mode to the ATF.
|
||
|
+
|
||
|
endif
|
||
|
diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile
|
||
|
index afca0a4c4b72..a15c0a395a33 100644
|
||
|
--- a/drivers/soc/rockchip/Makefile
|
||
|
+++ b/drivers/soc/rockchip/Makefile
|
||
|
@@ -4,3 +4,4 @@
|
||
|
#
|
||
|
obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
|
||
|
obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
|
||
|
+obj-$(CONFIG_ROCKCHIP_SUSPEND_MODE) += rockchip_pm_config.o
|
||
|
diff --git a/drivers/soc/rockchip/rockchip_pm_config.c b/drivers/soc/rockchip/rockchip_pm_config.c
|
||
|
new file mode 100644
|
||
|
index 000000000000..4a3038f22639
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/soc/rockchip/rockchip_pm_config.c
|
||
|
@@ -0,0 +1,213 @@
|
||
|
+/*
|
||
|
+ * Rockchip Generic power configuration support.
|
||
|
+ *
|
||
|
+ * Copyright (c) 2017 ROCKCHIP, Co. Ltd.
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License version 2 as
|
||
|
+ * published by the Free Software Foundation.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <linux/arm-smccc.h>
|
||
|
+#include <linux/bitops.h>
|
||
|
+#include <linux/cpu.h>
|
||
|
+#include <linux/of_gpio.h>
|
||
|
+#include <linux/platform_device.h>
|
||
|
+#include <linux/regulator/machine.h>
|
||
|
+#include <linux/rockchip/rockchip_sip.h>
|
||
|
+#include <linux/suspend.h>
|
||
|
+#include <dt-bindings/input/input.h>
|
||
|
+
|
||
|
+#define PM_INVALID_GPIO 0xffff
|
||
|
+
|
||
|
+static const struct of_device_id pm_match_table[] = {
|
||
|
+ { .compatible = "rockchip,pm-rk3399",},
|
||
|
+ { },
|
||
|
+};
|
||
|
+
|
||
|
+#define MAX_PWRKEY_NUMS 20
|
||
|
+#define MAX_NUM_KEYS 60
|
||
|
+
|
||
|
+struct rkxx_remote_key_table {
|
||
|
+ int scancode;
|
||
|
+ int keycode;
|
||
|
+};
|
||
|
+
|
||
|
+static int parse_ir_pwrkeys(unsigned int *pwrkey, int size, int *nkey)
|
||
|
+{
|
||
|
+ struct device_node *node;
|
||
|
+ struct device_node *child_node;
|
||
|
+ struct rkxx_remote_key_table key_table[MAX_NUM_KEYS];
|
||
|
+ int i;
|
||
|
+ int len = 0, nbuttons;
|
||
|
+ int num = 0;
|
||
|
+ u32 usercode, scancode;
|
||
|
+
|
||
|
+ for_each_node_by_name(node, "pwm") {
|
||
|
+ for_each_child_of_node(node, child_node) {
|
||
|
+ if (of_property_read_u32(child_node,
|
||
|
+ "rockchip,usercode",
|
||
|
+ &usercode))
|
||
|
+ break;
|
||
|
+
|
||
|
+ if (of_get_property(child_node,
|
||
|
+ "rockchip,key_table",
|
||
|
+ &len) == NULL ||
|
||
|
+ len <= 0)
|
||
|
+ break;
|
||
|
+
|
||
|
+ len = len < sizeof(key_table) ? len : sizeof(key_table);
|
||
|
+ len /= sizeof(u32);
|
||
|
+ if (of_property_read_u32_array(child_node,
|
||
|
+ "rockchip,key_table",
|
||
|
+ (u32 *)key_table,
|
||
|
+ len))
|
||
|
+ break;
|
||
|
+
|
||
|
+ nbuttons = len / 2;
|
||
|
+ for (i = 0; i < nbuttons && num < size; ++i) {
|
||
|
+ if (key_table[i].keycode == KEY_POWER) {
|
||
|
+ scancode = key_table[i].scancode;
|
||
|
+ pr_debug("usercode=%x, key=%x\n",
|
||
|
+ usercode, scancode);
|
||
|
+ pwrkey[num] = (usercode & 0xffff) << 16;
|
||
|
+ pwrkey[num] |= (scancode & 0xff) << 8;
|
||
|
+ ++num;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ *nkey = num;
|
||
|
+
|
||
|
+ return num ? 0 : -1;
|
||
|
+}
|
||
|
+
|
||
|
+static void rockchip_pm_virt_pwroff_prepare(void)
|
||
|
+{
|
||
|
+ int error;
|
||
|
+ int i, nkey;
|
||
|
+ u32 power_key[MAX_PWRKEY_NUMS];
|
||
|
+
|
||
|
+ if ((parse_ir_pwrkeys(power_key, ARRAY_SIZE(power_key), &nkey))) {
|
||
|
+ pr_err("Parse ir powerkey code failed!\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ for (i = 0; i < nkey; ++i)
|
||
|
+ sip_smc_set_suspend_mode(VIRTUAL_POWEROFF, 1, power_key[i]);
|
||
|
+
|
||
|
+ regulator_suspend_prepare(PM_SUSPEND_MEM);
|
||
|
+
|
||
|
+ error = freeze_secondary_cpus(0);
|
||
|
+ if (error) {
|
||
|
+ pr_err("Freeze secondary cpus failed!\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ sip_smc_set_suspend_mode(VIRTUAL_POWEROFF, 0, 1);
|
||
|
+ sip_smc_virtual_poweroff();
|
||
|
+}
|
||
|
+
|
||
|
+static int __init pm_config_init(struct platform_device *pdev)
|
||
|
+{
|
||
|
+ const struct of_device_id *match_id;
|
||
|
+ struct device_node *node;
|
||
|
+ u32 mode_config = 0;
|
||
|
+ u32 wakeup_config = 0;
|
||
|
+ u32 pwm_regulator_config = 0;
|
||
|
+ int gpio_temp[10];
|
||
|
+ u32 sleep_debug_en = 0;
|
||
|
+ u32 apios_suspend = 0;
|
||
|
+ u32 virtual_poweroff_en = 0;
|
||
|
+ enum of_gpio_flags flags;
|
||
|
+ int i = 0;
|
||
|
+ int length;
|
||
|
+
|
||
|
+ match_id = of_match_node(pm_match_table, pdev->dev.of_node);
|
||
|
+ if (!match_id)
|
||
|
+ return -ENODEV;
|
||
|
+
|
||
|
+ node = of_find_node_by_name(NULL, "rockchip-suspend");
|
||
|
+
|
||
|
+ if (IS_ERR_OR_NULL(node)) {
|
||
|
+ dev_err(&pdev->dev, "%s dev node err\n", __func__);
|
||
|
+ return -ENODEV;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (of_property_read_u32_array(node,
|
||
|
+ "rockchip,sleep-mode-config",
|
||
|
+ &mode_config, 1))
|
||
|
+ dev_warn(&pdev->dev, "not set sleep mode config\n");
|
||
|
+ else
|
||
|
+ sip_smc_set_suspend_mode(SUSPEND_MODE_CONFIG, mode_config, 0);
|
||
|
+
|
||
|
+ if (of_property_read_u32_array(node,
|
||
|
+ "rockchip,wakeup-config",
|
||
|
+ &wakeup_config, 1))
|
||
|
+ dev_warn(&pdev->dev, "not set wakeup-config\n");
|
||
|
+ else
|
||
|
+ sip_smc_set_suspend_mode(WKUP_SOURCE_CONFIG, wakeup_config, 0);
|
||
|
+
|
||
|
+ if (of_property_read_u32_array(node,
|
||
|
+ "rockchip,pwm-regulator-config",
|
||
|
+ &pwm_regulator_config, 1))
|
||
|
+ dev_warn(&pdev->dev, "not set pwm-regulator-config\n");
|
||
|
+ else
|
||
|
+ sip_smc_set_suspend_mode(PWM_REGULATOR_CONFIG,
|
||
|
+ pwm_regulator_config,
|
||
|
+ 0);
|
||
|
+
|
||
|
+ length = of_gpio_named_count(node, "rockchip,power-ctrl");
|
||
|
+
|
||
|
+ if (length > 0 && length < 10) {
|
||
|
+ for (i = 0; i < length; i++) {
|
||
|
+ gpio_temp[i] = of_get_named_gpio_flags(node,
|
||
|
+ "rockchip,power-ctrl",
|
||
|
+ i,
|
||
|
+ &flags);
|
||
|
+ if (!gpio_is_valid(gpio_temp[i]))
|
||
|
+ break;
|
||
|
+ sip_smc_set_suspend_mode(GPIO_POWER_CONFIG,
|
||
|
+ i,
|
||
|
+ gpio_temp[i]);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ sip_smc_set_suspend_mode(GPIO_POWER_CONFIG, i, PM_INVALID_GPIO);
|
||
|
+
|
||
|
+ if (!of_property_read_u32_array(node,
|
||
|
+ "rockchip,sleep-debug-en",
|
||
|
+ &sleep_debug_en, 1))
|
||
|
+ sip_smc_set_suspend_mode(SUSPEND_DEBUG_ENABLE,
|
||
|
+ sleep_debug_en,
|
||
|
+ 0);
|
||
|
+
|
||
|
+ if (!of_property_read_u32_array(node,
|
||
|
+ "rockchip,apios-suspend",
|
||
|
+ &apios_suspend, 1))
|
||
|
+ sip_smc_set_suspend_mode(APIOS_SUSPEND_CONFIG,
|
||
|
+ apios_suspend,
|
||
|
+ 0);
|
||
|
+
|
||
|
+ if (!of_property_read_u32_array(node,
|
||
|
+ "rockchip,virtual-poweroff",
|
||
|
+ &virtual_poweroff_en, 1) &&
|
||
|
+ virtual_poweroff_en)
|
||
|
+ pm_power_off_prepare = rockchip_pm_virt_pwroff_prepare;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static struct platform_driver pm_driver = {
|
||
|
+ .driver = {
|
||
|
+ .name = "rockchip-pm",
|
||
|
+ .of_match_table = pm_match_table,
|
||
|
+ },
|
||
|
+};
|
||
|
+
|
||
|
+static int __init rockchip_pm_drv_register(void)
|
||
|
+{
|
||
|
+ return platform_driver_probe(&pm_driver, pm_config_init);
|
||
|
+}
|
||
|
+subsys_initcall(rockchip_pm_drv_register);
|
||
|
+
|
||
|
diff --git a/include/dt-bindings/suspend/rockchip-rk3399.h b/include/dt-bindings/suspend/rockchip-rk3399.h
|
||
|
new file mode 100644
|
||
|
index 000000000000..de23670b43ea
|
||
|
--- /dev/null
|
||
|
+++ b/include/dt-bindings/suspend/rockchip-rk3399.h
|
||
|
@@ -0,0 +1,60 @@
|
||
|
+/*
|
||
|
+ * Header providing constants for Rockchip suspend bindings.
|
||
|
+ *
|
||
|
+ * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ * Author: Tony.Xie
|
||
|
+ *
|
||
|
+ * 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.
|
||
|
+ */
|
||
|
+
|
||
|
+#ifndef __DT_BINDINGS_SUSPEND_ROCKCHIP_RK3399_H__
|
||
|
+#define __DT_BINDINGS_SUSPEND_ROCKCHIP_RK3399_H__
|
||
|
+
|
||
|
+/* the suspend mode */
|
||
|
+#define RKPM_SLP_WFI (1 << 0)
|
||
|
+#define RKPM_SLP_ARMPD (1 << 1)
|
||
|
+#define RKPM_SLP_PERILPPD (1 << 2)
|
||
|
+#define RKPM_SLP_DDR_RET (1 << 3)
|
||
|
+#define RKPM_SLP_PLLPD (1 << 4)
|
||
|
+#define RKPM_SLP_OSC_DIS (1 << 5)
|
||
|
+#define RKPM_SLP_CENTER_PD (1 << 6)
|
||
|
+#define RKPM_SLP_AP_PWROFF (1 << 7)
|
||
|
+
|
||
|
+/* the wake up source */
|
||
|
+#define RKPM_CLUSTER_L_WKUP_EN (1 << 0)
|
||
|
+#define RKPM_CLUSTER_B_WKUPB_EN (1 << 1)
|
||
|
+#define RKPM_GPIO_WKUP_EN (1 << 2)
|
||
|
+#define RKPM_SDIO_WKUP_EN (1 << 3)
|
||
|
+#define RKPM_SDMMC_WKUP_EN (1 << 4)
|
||
|
+#define RKPM_TIMER_WKUP_EN (1 << 6)
|
||
|
+#define RKPM_USB_WKUP_EN (1 << 7)
|
||
|
+#define RKPM_SFT_WKUP_EN (1 << 8)
|
||
|
+#define RKPM_WDT_M0_WKUP_EN (1 << 9)
|
||
|
+#define RKPM_TIME_OUT_WKUP_EN (1 << 10)
|
||
|
+#define RKPM_PWM_WKUP_EN (1 << 11)
|
||
|
+#define RKPM_PCIE_WKUP_EN (1 << 13)
|
||
|
+
|
||
|
+/* the pwm regulator */
|
||
|
+#define PWM0_REGULATOR_EN (1 << 0)
|
||
|
+#define PWM1_REGULATOR_EN (1 << 1)
|
||
|
+#define PWM2_REGULATOR_EN (1 << 2)
|
||
|
+#define PWM3A_REGULATOR_EN (1 << 3)
|
||
|
+#define PWM3B_REGULATOR_EN (1 << 4)
|
||
|
+
|
||
|
+/* the APIO voltage domain */
|
||
|
+#define RKPM_APIO0_SUSPEND (1 << 0)
|
||
|
+#define RKPM_APIO1_SUSPEND (1 << 1)
|
||
|
+#define RKPM_APIO2_SUSPEND (1 << 2)
|
||
|
+#define RKPM_APIO3_SUSPEND (1 << 3)
|
||
|
+#define RKPM_APIO4_SUSPEND (1 << 4)
|
||
|
+#define RKPM_APIO5_SUSPEND (1 << 5)
|
||
|
+
|
||
|
+#endif
|
||
|
diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h
|
||
|
index 29d920516e0b..549b68c58e68 100644
|
||
|
--- a/include/linux/regulator/driver.h
|
||
|
+++ b/include/linux/regulator/driver.h
|
||
|
@@ -632,6 +632,9 @@
|
||
|
|
||
|
/* time when this regulator was disabled last time */
|
||
|
ktime_t last_off;
|
||
|
+
|
||
|
+ /* state when resuming */
|
||
|
+ int resume_state;
|
||
|
int cached_err;
|
||
|
bool use_cached_err;
|
||
|
spinlock_t err_lock;
|
||
|
diff --git a/include/linux/rockchip/rockchip_sip.h b/include/linux/rockchip/rockchip_sip.h
|
||
|
new file mode 100644
|
||
|
index 000000000000..9e8bbb2251c6
|
||
|
--- /dev/null
|
||
|
+++ b/include/linux/rockchip/rockchip_sip.h
|
||
|
@@ -0,0 +1,149 @@
|
||
|
+/* Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
|
||
|
+ *
|
||
|
+ * This program is free software; you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License version 2 and
|
||
|
+ * only version 2 as published by the Free Software Foundation.
|
||
|
+ *
|
||
|
+ * This program is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ */
|
||
|
+#ifndef __ROCKCHIP_SIP_H
|
||
|
+#define __ROCKCHIP_SIP_H
|
||
|
+
|
||
|
+#include <linux/arm-smccc.h>
|
||
|
+#include <linux/io.h>
|
||
|
+
|
||
|
+/* SMC function IDs for SiP Service queries, compatible with kernel-3.10 */
|
||
|
+#define SIP_ATF_VERSION 0x82000001
|
||
|
+#define SIP_ACCESS_REG 0x82000002
|
||
|
+#define SIP_SUSPEND_MODE 0x82000003
|
||
|
+#define SIP_PENDING_CPUS 0x82000004
|
||
|
+#define SIP_UARTDBG_CFG 0x82000005
|
||
|
+#define SIP_UARTDBG_CFG64 0xc2000005
|
||
|
+#define SIP_MCU_EL3FIQ_CFG 0x82000006
|
||
|
+#define SIP_ACCESS_CHIP_STATE64 0xc2000006
|
||
|
+#define SIP_SECURE_MEM_CONFIG 0x82000007
|
||
|
+#define SIP_ACCESS_CHIP_EXTRA_STATE64 0xc2000007
|
||
|
+#define SIP_DDR_CFG 0x82000008
|
||
|
+#define SIP_SHARE_MEM 0x82000009
|
||
|
+#define SIP_SIP_VERSION 0x8200000a
|
||
|
+#define SIP_REMOTECTL_CFG 0x8200000b
|
||
|
+
|
||
|
+/* Trust firmware version */
|
||
|
+#define ATF_VER_MAJOR(ver) (((ver) >> 16) & 0xffff)
|
||
|
+#define ATF_VER_MINOR(ver) (((ver) >> 0) & 0xffff)
|
||
|
+
|
||
|
+/* SIP_ACCESS_REG: read or write */
|
||
|
+#define SECURE_REG_RD 0x0
|
||
|
+#define SECURE_REG_WR 0x1
|
||
|
+
|
||
|
+/* Fiq debugger share memory: 8KB enough */
|
||
|
+#define FIQ_UARTDBG_PAGE_NUMS 2
|
||
|
+#define FIQ_UARTDBG_SHARE_MEM_SIZE ((FIQ_UARTDBG_PAGE_NUMS) * 4096)
|
||
|
+
|
||
|
+/* Error return code */
|
||
|
+#define IS_SIP_ERROR(x) (!!(x))
|
||
|
+
|
||
|
+#define SIP_RET_SUCCESS 0
|
||
|
+#define SIP_RET_SMC_UNKNOWN -1
|
||
|
+#define SIP_RET_NOT_SUPPORTED -2
|
||
|
+#define SIP_RET_INVALID_PARAMS -3
|
||
|
+#define SIP_RET_INVALID_ADDRESS -4
|
||
|
+#define SIP_RET_DENIED -5
|
||
|
+
|
||
|
+/* SIP_UARTDBG_CFG64 call types */
|
||
|
+#define UARTDBG_CFG_INIT 0xf0
|
||
|
+#define UARTDBG_CFG_OSHDL_TO_OS 0xf1
|
||
|
+#define UARTDBG_CFG_OSHDL_CPUSW 0xf3
|
||
|
+#define UARTDBG_CFG_OSHDL_DEBUG_ENABLE 0xf4
|
||
|
+#define UARTDBG_CFG_OSHDL_DEBUG_DISABLE 0xf5
|
||
|
+#define UARTDBG_CFG_PRINT_PORT 0xf7
|
||
|
+#define UARTDBG_CFG_FIQ_ENABEL 0xf8
|
||
|
+#define UARTDBG_CFG_FIQ_DISABEL 0xf9
|
||
|
+
|
||
|
+/* SIP_SUSPEND_MODE32 call types */
|
||
|
+#define SUSPEND_MODE_CONFIG 0x01
|
||
|
+#define WKUP_SOURCE_CONFIG 0x02
|
||
|
+#define PWM_REGULATOR_CONFIG 0x03
|
||
|
+#define GPIO_POWER_CONFIG 0x04
|
||
|
+#define SUSPEND_DEBUG_ENABLE 0x05
|
||
|
+#define APIOS_SUSPEND_CONFIG 0x06
|
||
|
+#define VIRTUAL_POWEROFF 0x07
|
||
|
+
|
||
|
+/* SIP_REMOTECTL_CFG call types */
|
||
|
+#define REMOTECTL_SET_IRQ 0xf0
|
||
|
+#define REMOTECTL_SET_PWM_CH 0xf1
|
||
|
+#define REMOTECTL_SET_PWRKEY 0xf2
|
||
|
+#define REMOTECTL_GET_WAKEUP_STATE 0xf3
|
||
|
+#define REMOTECTL_ENABLE 0xf4
|
||
|
+/* wakeup state */
|
||
|
+#define REMOTECTL_PWRKEY_WAKEUP 0xdeadbeaf
|
||
|
+
|
||
|
+/* Share mem page types */
|
||
|
+typedef enum {
|
||
|
+ SHARE_PAGE_TYPE_INVALID = 0,
|
||
|
+ SHARE_PAGE_TYPE_UARTDBG,
|
||
|
+ SHARE_PAGE_TYPE_MAX,
|
||
|
+} share_page_type_t;
|
||
|
+
|
||
|
+/*
|
||
|
+ * Rules: struct arm_smccc_res contains result and data, details:
|
||
|
+ *
|
||
|
+ * a0: error code(0: success, !0: error);
|
||
|
+ * a1~a3: data
|
||
|
+ */
|
||
|
+struct arm_smccc_res sip_smc_get_atf_version(void);
|
||
|
+struct arm_smccc_res sip_smc_get_sip_version(void);
|
||
|
+struct arm_smccc_res sip_smc_ddr_cfg(u32 arg0, u32 arg1, u32 arg2);
|
||
|
+struct arm_smccc_res sip_smc_request_share_mem(u32 page_num,
|
||
|
+ share_page_type_t page_type);
|
||
|
+struct arm_smccc_res sip_smc_mcu_el3fiq(u32 arg0, u32 arg1, u32 arg2);
|
||
|
+
|
||
|
+int sip_smc_set_suspend_mode(u32 ctrl, u32 config1, u32 config2);
|
||
|
+int sip_smc_virtual_poweroff(void);
|
||
|
+/***************************fiq debugger **************************************/
|
||
|
+void sip_fiq_debugger_enable_fiq(bool enable, uint32_t tgt_cpu);
|
||
|
+void sip_fiq_debugger_enable_debug(bool enable);
|
||
|
+int sip_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback_fn);
|
||
|
+int sip_fiq_debugger_set_print_port(u32 port_phyaddr, u32 baudrate);
|
||
|
+int sip_fiq_debugger_request_share_memory(void);
|
||
|
+int sip_fiq_debugger_get_target_cpu(void);
|
||
|
+int sip_fiq_debugger_switch_cpu(u32 cpu);
|
||
|
+int sip_fiq_debugger_is_enabled(void);
|
||
|
+
|
||
|
+/* optee cpu_context */
|
||
|
+struct sm_nsec_ctx {
|
||
|
+ u32 usr_sp;
|
||
|
+ u32 usr_lr;
|
||
|
+ u32 irq_spsr;
|
||
|
+ u32 irq_sp;
|
||
|
+ u32 irq_lr;
|
||
|
+ u32 svc_spsr;
|
||
|
+ u32 svc_sp;
|
||
|
+ u32 svc_lr;
|
||
|
+ u32 abt_spsr;
|
||
|
+ u32 abt_sp;
|
||
|
+ u32 abt_lr;
|
||
|
+ u32 und_spsr;
|
||
|
+ u32 und_sp;
|
||
|
+ u32 und_lr;
|
||
|
+ u32 mon_lr;
|
||
|
+ u32 mon_spsr;
|
||
|
+ u32 r4;
|
||
|
+ u32 r5;
|
||
|
+ u32 r6;
|
||
|
+ u32 r7;
|
||
|
+ u32 r8;
|
||
|
+ u32 r9;
|
||
|
+ u32 r10;
|
||
|
+ u32 r11;
|
||
|
+ u32 r12;
|
||
|
+ u32 r0;
|
||
|
+ u32 r1;
|
||
|
+ u32 r2;
|
||
|
+ u32 r3;
|
||
|
+};
|
||
|
+
|
||
|
+#endif
|
||
|
--
|
||
|
2.26.2
|