diff options
Diffstat (limited to 'gnu/packages/patches/linux-libre-pinebook-pro-02-firmware-Add-Rockchip-SIP-driver.patch')
-rw-r--r-- | gnu/packages/patches/linux-libre-pinebook-pro-02-firmware-Add-Rockchip-SIP-driver.patch | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/gnu/packages/patches/linux-libre-pinebook-pro-02-firmware-Add-Rockchip-SIP-driver.patch b/gnu/packages/patches/linux-libre-pinebook-pro-02-firmware-Add-Rockchip-SIP-driver.patch new file mode 100644 index 0000000000..9190e0086b --- /dev/null +++ b/gnu/packages/patches/linux-libre-pinebook-pro-02-firmware-Add-Rockchip-SIP-driver.patch @@ -0,0 +1,474 @@ +From f96cdf076bcc4a12af7670c5cb3ff584d2adf988 Mon Sep 17 00:00:00 2001 +From: Tobias Schramm <t.schramm@manjaro.org> +Date: Thu, 28 May 2020 14:11:05 +0200 +Subject: [PATCH 02/22] firmware: Add Rockchip SIP driver + +Used exclusively for suspend signaling. Drop for mainline and +use PSCI + +Signed-off-by: Tobias Schramm <t.schramm@manjaro.org> +--- + drivers/firmware/Kconfig | 7 + + drivers/firmware/Makefile | 1 + + drivers/firmware/rockchip_sip.c | 262 ++++++++++++++++++++++++++ + include/linux/rockchip/rockchip_sip.h | 149 +++++++++++++++ + 4 files changed, 419 insertions(+) + create mode 100644 drivers/firmware/rockchip_sip.c + create mode 100644 include/linux/rockchip/rockchip_sip.h + +diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig +index 3315e3c21586..1dfa18dde097 100644 +--- a/drivers/firmware/Kconfig ++++ b/drivers/firmware/Kconfig +@@ -250,6 +250,13 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT + + Say Y here to enable "download mode" by default. + ++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. ++ + config TI_SCI_PROTOCOL + tristate "TI System Control Interface (TISCI) Message Protocol" + depends on TI_MESSAGE_MANAGER +diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile +index 5e013b6a3692..85c40483e5fa 100644 +--- a/drivers/firmware/Makefile ++++ b/drivers/firmware/Makefile +@@ -28,6 +28,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 += psci/ + obj-y += smccc/ +diff --git a/drivers/firmware/rockchip_sip.c b/drivers/firmware/rockchip_sip.c +new file mode 100644 +index 000000000000..6ed780c587e1 +--- /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 <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/include/linux/rockchip/rockchip_sip.h b/include/linux/rockchip/rockchip_sip.h +new file mode 100644 +index 000000000000..b19f64ede981 +--- /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.30.0 + |