Merge branch 'linux-linaro-lsk-v4.4-android' of git://git.linaro.org/kernel/linux...
[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(uint32_t arg0, uint32_t arg1,
35                                      uint32_t 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(uint32_t mode)
51 {
52         struct arm_smccc_res res;
53
54         res = __invoke_sip_fn_smc(SIP_SUSPEND_MODE32, mode, 0, 0);
55
56         return res.a0;
57 }
58
59 static u64 ft_fiq_mem_phy;
60 static void __iomem *ft_fiq_mem_base;
61 static void (*psci_fiq_debugger_uart_irq_tf)(void *reg_base, u64 sp_el1);
62 static u32 fig_init_flag;
63
64 u32 rockchip_psci_smc_get_tf_ver(void)
65 {
66         struct arm_smccc_res res;
67
68         arm_smccc_smc(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res);
69         return 0x00010005;
70 }
71
72 void psci_fiq_debugger_uart_irq_tf_cb(u64 sp_el1, u64 offset)
73 {
74         psci_fiq_debugger_uart_irq_tf((char *)ft_fiq_mem_base + offset, sp_el1);
75         __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0, 0,
76                             UARTDBG_CFG_OSHDL_TO_OS);
77 }
78
79 void psci_fiq_debugger_uart_irq_tf_init(u32 irq_id, void *callback)
80 {
81         struct arm_smccc_res sip_smmc;
82
83         psci_fiq_debugger_uart_irq_tf = callback;
84         sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, irq_id,
85                                        (u64)psci_fiq_debugger_uart_irq_tf_cb,
86                                        UARTDBG_CFG_INIT);
87         ft_fiq_mem_phy = sip_smmc.a0;
88         ft_fiq_mem_base = ioremap(ft_fiq_mem_phy, 8 * 1024);
89         fig_init_flag = 1;
90 }
91
92 void psci_enable_fiq(void)
93 {
94         int irq_flag;
95         int cpu_id;
96
97         if (fig_init_flag != 1)
98                 return;
99         irq_flag = *((char *)(ft_fiq_mem_base) + 8 * 1024 - 0x04);
100
101         cpu_id = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
102         if ((irq_flag == 0xAA) && (cpu_id == 0))
103                 __invoke_sip_fn_smc(RK_SIP_ENABLE_FIQ, 0, 0, 0);
104 }
105
106 u32 psci_fiq_debugger_switch_cpu(u32 cpu)
107 {
108         struct arm_smccc_res sip_smmc;
109
110                 sip_smmc = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64,
111                                                cpu_logical_map(cpu),
112                                                0, UARTDBG_CFG_OSHDL_CPUSW);
113         return sip_smmc.a0;
114 }
115
116 void psci_fiq_debugger_enable_debug(bool val)
117 {
118         if (val)
119                 __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
120                                     0, UARTDBG_CFG_OSHDL_DEBUG_ENABLE);
121         else
122                 __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, 0,
123                                     0, UARTDBG_CFG_OSHDL_DEBUG_DISABLE);
124 }
125
126 int psci_fiq_debugger_set_print_port(u32 port, u32 baudrate)
127 {
128         struct arm_smccc_res res;
129
130         res = __invoke_sip_fn_smc(PSCI_SIP_UARTDBG_CFG64, port, baudrate,
131                            UARTDBG_CFG_PRINT_PORT);
132         return res.a0;
133 }
134
135 struct arm_smccc_res sip_smc_get_share_mem_page(u32 page_num,
136                                                 share_page_type_t page_type)
137 {
138         struct arm_smccc_res res;
139         unsigned long share_mem_phy;
140
141         res = __invoke_sip_fn_smc(SIP_SHARE_MEM32, page_num, page_type, 0);
142         if (res.a0)
143                 goto error;
144
145         share_mem_phy = res.a1;
146         res.a1 = (unsigned long)ioremap(share_mem_phy, SIZE_PAGE(page_num));
147
148 error:
149         return res;
150 }
151
152 struct arm_smccc_res sip_smc_get_call_count(void)
153 {
154         return __invoke_sip_fn_smc(SIP_SVC_CALL_COUNT, 0, 0, 0);
155 }