--- /dev/null +++ b/Documentation/devicetree/bindings/soc/rockchip/rockchip-pm-config.txt @@ -0,0 +1,39 @@ +* 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 + ) + >; + }; --- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include / { @@ -2899,4 +2899,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 + ) + >; + }; }; --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -9,2 +9,9 @@ source "drivers/firmware/arm_scmi/Kconfig" +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. + --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o +obj-$(CONFIG_ROCKCHIP_SIP) += rockchip_sip.o obj-$(CONFIG_QCOM_SCM) += qcom-scm.o qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o obj-$(CONFIG_SYSFB) += sysfb.o obj-$(CONFIG_SYSFB_SIMPLEFB) += sysfb_simplefb.o --- /dev/null +++ b/drivers/firmware/rockchip_sip.c @@ -0,0 +1,262 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include + +#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); +} --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -5773,6 +5773,14 @@ void regulator_unregister(struct regulat 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() @@ -5792,6 +5800,28 @@ static int regulator_suspend(struct devi regulator_lock(rdev); ret = __suspend_set_state(rdev, rstate); + if (ret) { + goto out; + } + + rstate = regulator_get_suspend_state(rdev, state); + if (rstate == NULL) + goto out; + + 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); + } + } +out: regulator_unlock(rdev); return ret; @@ -5808,15 +5838,25 @@ static int regulator_resume(struct devic if (rstate == NULL) return 0; - /* Avoid grabbing the lock if we don't need to */ - if (!rdev->desc->ops->resume) - return 0; - regulator_lock(rdev); if (rstate->enabled == ENABLE_IN_SUSPEND || - rstate->enabled == DISABLE_IN_SUSPEND) - ret = rdev->desc->ops->resume(rdev); + rstate->enabled == DISABLE_IN_SUSPEND) { + if (rdev->desc->ops->resume) { + rdev_info(rdev, "resume with ops\n"); + 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); + } + } else { + rdev_info(rdev, "no resume option taken!\n"); + } + } regulator_unlock(rdev); --- a/drivers/soc/rockchip/Kconfig +++ b/drivers/soc/rockchip/Kconfig @@ -42,4 +42,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 --- a/drivers/soc/rockchip/Makefile +++ b/drivers/soc/rockchip/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_ROCKCHIP_IODOMAIN) += io-domain.o obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o obj-$(CONFIG_ROCKCHIP_DTPM) += dtpm.o +obj-$(CONFIG_ROCKCHIP_SUSPEND_MODE) += rockchip_pm_config.o --- /dev/null +++ b/drivers/soc/rockchip/rockchip_pm_config.c @@ -0,0 +1,44 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#define PM_INVALID_GPIO 0xffff + +static const struct of_device_id pm_match_table[] = { + { .compatible = "rockchip,pm-rk3399",}, + { }, +}; + +static int __init pm_config_init(struct platform_device *pdev) +{ + 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); --- /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 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -650,6 +650,9 @@ struct regulator_dev { int cached_err; bool use_cached_err; spinlock_t err_lock; + + /* state when resuming */ + int resume_state; }; struct regulator_dev * --- /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 +#include + +/* 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