suspend: rockchip: set the suspend config to ATF
[firefly-linux-kernel-4.4.55.git] / drivers / firmware / rockchip_sip.c
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License version 2 as
4  * published by the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9  * GNU General Public License for more details.
10  *
11  * Copyright (C) 2016, Fuzhou Rockchip Electronics Co., Ltd
12  */
13
14 #include <linux/arm-smccc.h>
15 #include <linux/io.h>
16 #include <linux/rockchip/rockchip_sip.h>
17 #include <asm/cputype.h>
18 #include <asm/smp_plat.h>
19 #include <uapi/linux/psci.h>
20
21 #define SIZE_PAGE(n)    ((n) << 12)
22
23 static struct arm_smccc_res __invoke_sip_fn_smc(unsigned long function_id,
24                                                 unsigned long arg0,
25                                                 unsigned long arg1,
26                                                 unsigned long arg2)
27 {
28         struct arm_smccc_res res;
29
30         arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
31         return res;
32 }
33
34 struct arm_smccc_res sip_smc_ddr_cfg(u32 arg0, u32 arg1,
35                                      u32 arg2)
36 {
37         return __invoke_sip_fn_smc(SIP_DDR_CFG32, arg0, arg1, arg2);
38 }
39
40 struct arm_smccc_res sip_smc_get_atf_version(void)
41 {
42         return __invoke_sip_fn_smc(SIP_ATF_VERSION32, 0, 0, 0);
43 }
44
45 struct arm_smccc_res sip_smc_get_sip_version(void)
46 {
47         return __invoke_sip_fn_smc(SIP_SIP_VERSION32, 0, 0, 0);
48 }
49
50 int sip_smc_set_suspend_mode(u32 ctrl,
51                              u32 config1,
52                              u32 config2)
53 {
54         struct arm_smccc_res res;
55
56         res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE32, ctrl,
57                                   config1, config2);
58
59         return res.a0;
60 }
61
62 static u64 ft_fiq_mem_phy;
63 static void __iomem *ft_fiq_mem_base;
64 static void (*psci_fiq_debugger_uart_irq_tf)(void *reg_base, u64 sp_el1);
65 static u32 fig_init_flag;
66
67 u32 rockchip_psci_smc_get_tf_ver(void)
68 {
69         struct arm_smccc_res res;
70
71         arm_smccc_smc(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
72         return 0x00010005;
73 }
74
75 void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset)
76 {
77         psci_fiq_debugger_uart_irq_tf((char *)ft_fiq_mem_base + offset, sp_el1);
78         __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0, 0,
79                             UARTDBG_CFG_OSHDL_TO_OS);
80 }
81
82 void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback)
83 {
84         struct arm_smccc_res sip_smmc;
85
86         psci_fiq_debugger_uart_irq_tf = callback;
87         sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, irq_id,
88                                        (u64)psci_fiq_debugger_uart_irq_tf_cb,
89                                        UARTDBG_CFG_INIT);
90         ft_fiq_mem_phy = sip_smmc.a0;
91         ft_fiq_mem_base = ioremap(ft_fiq_mem_phy, 8 * 1024);
92         fig_init_flag = 1;
93 }
94
95 void psci_enable_fiq(void)
96 {
97         int irq_flag;
98         int cpu_id;
99
100         if (fig_init_flag != 1)
101                 return;
102         irq_flag = *((char *)(ft_fiq_mem_base) + 8 * 1024 - 0x04);
103
104         cpu_id = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
105         if ((irq_flag == 0xAA) && (cpu_id == 0))
106                 __invoke_sip_fn_smc(RK_SIP_ENABLE_FIQ, 0, 0, 0);
107 }
108
109 u32 psci_fiq_debugger_switch_cpu(u32 cpu)
110 {
111         struct arm_smccc_res sip_smmc;
112
113                 sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64,
114                                                cpu_logical_map(cpu),
115                                                0, UARTDBG_CFG_OSHDL_CPUSW);
116         return sip_smmc.a0;
117 }
118
119 void psci_fiq_debugger_enable_debug(bool val)
120 {
121         if (val)
122                 __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
123                                     0, UARTDBG_CFG_OSHDL_DEBUG_ENABLE);
124         else
125                 __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
126                                     0, UARTDBG_CFG_OSHDL_DEBUG_DISABLE);
127 }
128
129 int psci_fiq_debugger_set_print_port(u32 port, u32 baudrate)
130 {
131         struct arm_smccc_res res;
132
133         res = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, port, baudrate,
134                                   UARTDBG_CFG_PRINT_PORT);
135         return res.a0;
136 }
137
138 struct arm_smccc_res sip_smc_get_share_mem_page(u32 page_num,
139                                                 share_page_type_t page_type)
140 {
141         struct arm_smccc_res res;
142         unsigned long share_mem_phy;
143
144         res = __invoke_sip_fn_smc(SIP_SHARE_MEM32, page_num, page_type, 0);
145         if (res.a0)
146                 goto error;
147
148         share_mem_phy = res.a1;
149         res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
150
151 error:
152         return res;
153 }
154
155 struct arm_smccc_res sip_smc_get_call_count(void)
156 {
157         return __invoke_sip_fn_smc(SIP_SVC_CALL_COUNT, 0, 0, 0);
158 }