summary refs log tree commit diff
path: root/gnu/packages/patches/linux-libre-pinebook-pro-02-firmware-Add-Rockchip-SIP-driver.patch
diff options
context:
space:
mode:
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.patch474
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
+