blob: 7e02f3ae1d7806cf0a60661bcb9900735276450c [file] [log] [blame]
Haojian Zhuang3846f142017-05-24 08:49:26 +08001/*
Antonio Nino Diaz6bca8be2018-08-09 15:30:28 +01002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Haojian Zhuang3846f142017-05-24 08:49:26 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
Antonio Nino Diaz6bca8be2018-08-09 15:30:28 +01008#include <debug.h>
Haojian Zhuang3846f142017-05-24 08:49:26 +08009#include <hisi_ipc.h>
10#include <hisi_sram_map.h>
11#include <mmio.h>
12#include <platform_def.h>
13#include <stdarg.h>
Antonio Nino Diaz00086e32018-08-16 16:46:06 +010014#include <stdio.h>
Haojian Zhuang3846f142017-05-24 08:49:26 +080015#include <string.h>
16
17static int ipc_init;
18
19static unsigned int cpu_ipc_num[PLATFORM_CLUSTER_COUNT][PLATFORM_CORE_COUNT_PER_CLUSTER] = {
20 {
21 HISI_IPC_MCU_INT_SRC_ACPU0_PD,
22 HISI_IPC_MCU_INT_SRC_ACPU1_PD,
23 HISI_IPC_MCU_INT_SRC_ACPU2_PD,
24 HISI_IPC_MCU_INT_SRC_ACPU3_PD,
25 },
26 {
27 HISI_IPC_MCU_INT_SRC_ACPU4_PD,
28 HISI_IPC_MCU_INT_SRC_ACPU5_PD,
29 HISI_IPC_MCU_INT_SRC_ACPU6_PD,
30 HISI_IPC_MCU_INT_SRC_ACPU7_PD,
31 }
32};
33
34int hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu,
35 unsigned int cluster)
36{
37 unsigned int val = 0, cpu_val = 0;
38 int i;
39
40 val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
41 val = val >> (cluster * 16);
42
43 for (i = 0; i < PLATFORM_CORE_COUNT_PER_CLUSTER; i++) {
44
45 if (cpu == i)
46 continue;
47
48 cpu_val = (val >> (i * 4)) & 0xF;
49 if (cpu_val == 0x8)
50 return 0;
51 }
52
53 return 1;
54}
55
56int hisi_cpus_powered_off_besides_curr(unsigned int cpu)
57{
58 unsigned int val;
59
60 val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
61 return (val == (0x8 << (cpu * 4)));
62}
63
64static void hisi_ipc_send(unsigned int ipc_num)
65{
66 if (!ipc_init) {
Antonio Nino Diaz00086e32018-08-16 16:46:06 +010067 printf("error ipc base is null!!!\n");
Haojian Zhuang3846f142017-05-24 08:49:26 +080068 return;
69 }
70
71 mmio_write_32(HISI_IPC_CPU_RAW_INT_ADDR, 1 << ipc_num);
72}
73
74void hisi_ipc_spin_lock(unsigned int signal)
75{
76 unsigned int hs_ctrl;
77
78 if (signal >= HISI_IPC_INT_SRC_NUM)
79 return;
80
81 do {
82 hs_ctrl = mmio_read_32(HISI_IPC_ACPU_CTRL(signal));
83 } while (hs_ctrl);
84}
85
86void hisi_ipc_spin_unlock(unsigned int signal)
87{
88 if (signal >= HISI_IPC_INT_SRC_NUM)
89 return;
90
91 mmio_write_32(HISI_IPC_ACPU_CTRL(signal), 0);
92}
93
94void hisi_ipc_cpu_on_off(unsigned int cpu, unsigned int cluster,
95 unsigned int mode)
96{
97 unsigned int val = 0;
98 unsigned int offset;
99
100 if (mode == HISI_IPC_PM_ON)
101 offset = cluster * 16 + cpu * 4;
102 else
103 offset = cluster * 16 + cpu * 4 + 1;
104
105 hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
106 val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
107 val |= (0x01 << offset);
108 mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
109 isb();
110 dsb();
111 hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
112
113 hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
114}
115
116void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster)
117{
118 hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_ON);
119}
120
121void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster)
122{
123 hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_OFF);
124}
125
126void hisi_ipc_cluster_on_off(unsigned int cpu, unsigned int cluster,
127 unsigned int mode)
128{
129 unsigned int val = 0;
130 unsigned int offset;
131
132 if (mode == HISI_IPC_PM_ON)
133 offset = cluster * 4;
134 else
135 offset = cluster * 4 + 1;
136
137 hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
138 val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
139 val |= (0x01 << offset);
140 mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
141 isb();
142 dsb();
143 hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
144
145 hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
146}
147
148void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster)
149{
150 hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_ON);
151}
152
153void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster)
154{
155 hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_OFF);
156}
157
158void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster)
159{
160 unsigned int val = 0;
161 unsigned int offset;
162
163 offset = cluster * 16 + cpu * 4 + 2;
164
165 hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
166 val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
167 val |= (0x01 << offset);
168 mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
169 hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
170
171 hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
172}
173
174void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster)
175{
176 unsigned int val;
177 unsigned int offset;
178
179 offset = cluster * 4 + 1;
180
181 hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
182 if (hisi_cpus_pd_in_cluster_besides_curr(cpu, cluster)) {
183 val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
184 val |= (0x01 << offset);
185 mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
186 }
187 hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
188
189 hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
190}
191
192void hisi_ipc_psci_system_off(void)
193{
194 hisi_ipc_send(HISI_IPC_MCU_INT_SRC_ACPU_PD);
195}
196
197int hisi_ipc_init(void)
198{
199 ipc_init = 1;
200
201 mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, 0x8);
202 mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, 0x8);
203 return 0;
204}