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