mirror of
https://github.com/torvalds/linux.git
synced 2026-06-07 22:14:04 +02:00
firmware: rockchip: sip: add rockchip SIP runtime service
Change-Id: I996a90b3f6cb471f255566dfab0059a55da8866d Signed-off-by: Jianhong Chen <chenjh@rock-chips.com>
This commit is contained in:
parent
2c21d4842f
commit
a3bb010cad
|
|
@ -30,6 +30,10 @@
|
|||
#include <asm/smp_plat.h>
|
||||
#include <asm/suspend.h>
|
||||
|
||||
#ifdef CONFIG_FIQ_DEBUGGER_EL3_TO_EL1
|
||||
#include <linux/rockchip/rockchip_sip.h>
|
||||
#endif
|
||||
|
||||
static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
|
||||
|
||||
static int __maybe_unused cpu_psci_cpu_init_idle(unsigned int cpu)
|
||||
|
|
@ -202,6 +206,9 @@ static int __maybe_unused cpu_psci_cpu_suspend(unsigned long index)
|
|||
else
|
||||
ret = cpu_suspend(index, psci_suspend_finisher);
|
||||
|
||||
#ifdef CONFIG_FIQ_DEBUGGER_EL3_TO_EL1
|
||||
psci_enable_fiq();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -176,6 +176,13 @@ config QCOM_SCM_64
|
|||
config HAVE_ARM_SMCCC
|
||||
bool
|
||||
|
||||
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/broadcom/Kconfig"
|
||||
source "drivers/firmware/google/Kconfig"
|
||||
source "drivers/firmware/efi/Kconfig"
|
||||
|
|
|
|||
|
|
@ -23,3 +23,4 @@ obj-y += broadcom/
|
|||
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
|
||||
obj-$(CONFIG_EFI) += efi/
|
||||
obj-$(CONFIG_UEFI_CPER) += efi/
|
||||
obj-$(CONFIG_ROCKCHIP_SIP) += rockchip_sip.o
|
||||
|
|
|
|||
155
drivers/firmware/rockchip_sip.c
Normal file
155
drivers/firmware/rockchip_sip.c
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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>
|
||||
|
||||
#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(uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2)
|
||||
{
|
||||
return __invoke_sip_fn_smc(SIP_DDR_CFG32, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
struct arm_smccc_res sip_smc_get_atf_version(void)
|
||||
{
|
||||
return __invoke_sip_fn_smc(SIP_ATF_VERSION32, 0, 0, 0);
|
||||
}
|
||||
|
||||
struct arm_smccc_res sip_smc_get_sip_version(void)
|
||||
{
|
||||
return __invoke_sip_fn_smc(SIP_SIP_VERSION32, 0, 0, 0);
|
||||
}
|
||||
|
||||
int sip_smc_set_suspend_mode(uint32_t mode)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE32, mode, 0, 0);
|
||||
|
||||
return res.a0;
|
||||
}
|
||||
|
||||
static u64 ft_fiq_mem_phy;
|
||||
static void __iomem *ft_fiq_mem_base;
|
||||
static void (*psci_fiq_debugger_uart_irq_tf)(void *reg_base, u64 sp_el1);
|
||||
static u32 fig_init_flag;
|
||||
|
||||
u32 rockchip_psci_smc_get_tf_ver(void)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
arm_smccc_smc(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
|
||||
return 0x00010005;
|
||||
}
|
||||
|
||||
void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset)
|
||||
{
|
||||
psci_fiq_debugger_uart_irq_tf((char *)ft_fiq_mem_base + offset, sp_el1);
|
||||
__invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0, 0,
|
||||
UARTDBG_CFG_OSHDL_TO_OS);
|
||||
}
|
||||
|
||||
void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback)
|
||||
{
|
||||
struct arm_smccc_res sip_smmc;
|
||||
|
||||
psci_fiq_debugger_uart_irq_tf = callback;
|
||||
sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, irq_id,
|
||||
(u64)psci_fiq_debugger_uart_irq_tf_cb,
|
||||
UARTDBG_CFG_INIT);
|
||||
ft_fiq_mem_phy = sip_smmc.a0;
|
||||
ft_fiq_mem_base = ioremap(ft_fiq_mem_phy, 8 * 1024);
|
||||
fig_init_flag = 1;
|
||||
}
|
||||
|
||||
void psci_enable_fiq(void)
|
||||
{
|
||||
int irq_flag;
|
||||
int cpu_id;
|
||||
|
||||
if (fig_init_flag != 1)
|
||||
return;
|
||||
irq_flag = *((char *)(ft_fiq_mem_base) + 8 * 1024 - 0x04);
|
||||
|
||||
cpu_id = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
|
||||
if ((irq_flag == 0xAA) && (cpu_id == 0))
|
||||
__invoke_sip_fn_smc(RK_SIP_ENABLE_FIQ, 0, 0, 0);
|
||||
}
|
||||
|
||||
u32 psci_fiq_debugger_switch_cpu(u32 cpu)
|
||||
{
|
||||
struct arm_smccc_res sip_smmc;
|
||||
|
||||
sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64,
|
||||
cpu_logical_map(cpu),
|
||||
0, UARTDBG_CFG_OSHDL_CPUSW);
|
||||
return sip_smmc.a0;
|
||||
}
|
||||
|
||||
void psci_fiq_debugger_enable_debug(bool val)
|
||||
{
|
||||
if (val)
|
||||
__invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
|
||||
0, UARTDBG_CFG_OSHDL_DEBUG_ENABLE);
|
||||
else
|
||||
__invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
|
||||
0, UARTDBG_CFG_OSHDL_DEBUG_DISABLE);
|
||||
}
|
||||
|
||||
int psci_fiq_debugger_set_print_port(u32 port, u32 baudrate)
|
||||
{
|
||||
struct arm_smccc_res res;
|
||||
|
||||
res = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, port, baudrate,
|
||||
UARTDBG_CFG_PRINT_PORT);
|
||||
return res.a0;
|
||||
}
|
||||
|
||||
struct arm_smccc_res sip_smc_get_share_mem_page(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_MEM32, page_num, page_type, 0);
|
||||
if (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_get_call_count(void)
|
||||
{
|
||||
return __invoke_sip_fn_smc(SIP_SVC_CALL_COUNT, 0, 0, 0);
|
||||
}
|
||||
86
include/linux/rockchip/rockchip_sip.h
Normal file
86
include/linux/rockchip/rockchip_sip.h
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
/* 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 */
|
||||
#define SIP_SVC_CALL_COUNT 0x8200ff00
|
||||
#define SIP_SVC_UID 0x8200ff01
|
||||
#define SIP_SVC_VERSION 0x8200ff03
|
||||
|
||||
#define SIP_ATF_VERSION32 0x82000001
|
||||
#define SIP_SUSPEND_MODE32 0x82000003
|
||||
#define SIP_DDR_CFG32 0x82000008
|
||||
#define SIP_SHARE_MEM32 0x82000009
|
||||
#define SIP_SIP_VERSION32 0x8200000a
|
||||
|
||||
/* Share mem page types */
|
||||
typedef enum {
|
||||
SHARE_PAGE_TYPE_INVALID = 0,
|
||||
SHARE_PAGE_TYPE_UARTDBG,
|
||||
SHARE_PAGE_TYPE_MAX,
|
||||
} share_page_type_t;
|
||||
|
||||
/* Error return code */
|
||||
#define SIP_RET_SUCCESS 0
|
||||
#define SIP_RET_NOT_SUPPORTED -1
|
||||
#define SIP_RET_INVALID_PARAMS -2
|
||||
#define SIP_RET_INVALID_ADDRESS -3
|
||||
#define SIP_RET_DENIED -4
|
||||
#define SIP_RET_SMC_UNKNOWN 0xffffffff
|
||||
|
||||
/* Sip version */
|
||||
#define SIP_IMPLEMENT_V1 (1)
|
||||
#define SIP_IMPLEMENT_V2 (2)
|
||||
|
||||
#define RK_SIP_DISABLE_FIQ 0xc2000006
|
||||
#define RK_SIP_ENABLE_FIQ 0xc2000007
|
||||
#define PSCI_SIP_RKTF_VER 0x82000001
|
||||
#define PSCI_SIP_ACCESS_REG 0x82000002
|
||||
#define PSCI_SIP_ACCESS_REG64 0xc2000002
|
||||
#define PSCI_SIP_SUSPEND_WR_CTRBITS 0x82000003
|
||||
#define PSCI_SIP_PENDING_CPUS 0x82000004
|
||||
#define PSCI_SIP_UARTDBG_CFG 0x82000005
|
||||
#define PSCI_SIP_UARTDBG_CFG64 0xc2000005
|
||||
#define PSCI_SIP_EL3FIQ_CFG 0x82000006
|
||||
#define PSCI_SIP_SMEM_CONFIG 0x82000007
|
||||
|
||||
#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
|
||||
|
||||
/* struct arm_smccc_res: a0: error code; a1~a3: data */
|
||||
/* SMC32 Calls */
|
||||
int sip_smc_set_suspend_mode(uint32_t mode);
|
||||
struct arm_smccc_res sip_smc_get_call_count(void);
|
||||
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(uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2);
|
||||
struct arm_smccc_res sip_smc_get_share_mem_page(uint32_t page_num,
|
||||
share_page_type_t page_type);
|
||||
|
||||
void psci_enable_fiq(void);
|
||||
u32 rockchip_psci_smc_get_tf_ver(void);
|
||||
void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset);
|
||||
void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback);
|
||||
u32 psci_fiq_debugger_switch_cpu(u32 cpu);
|
||||
void psci_fiq_debugger_enable_debug(bool val);
|
||||
int psci_fiq_debugger_set_print_port(u32 port, u32 baudrate);
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user