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