1127793daSHaojian Zhuang /*
26a23356cSAntonio Nino Diaz * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3127793daSHaojian Zhuang *
4127793daSHaojian Zhuang * SPDX-License-Identifier: BSD-3-Clause
5127793daSHaojian Zhuang */
6127793daSHaojian Zhuang
7127793daSHaojian Zhuang #include <stdarg.h>
839b6cc66SAntonio Nino Diaz #include <stdio.h>
9127793daSHaojian Zhuang #include <string.h>
10127793daSHaojian Zhuang
11*09d40e0eSAntonio Nino Diaz #include <platform_def.h>
12*09d40e0eSAntonio Nino Diaz
13*09d40e0eSAntonio Nino Diaz #include <arch_helpers.h>
14*09d40e0eSAntonio Nino Diaz #include <common/debug.h>
15*09d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
16*09d40e0eSAntonio Nino Diaz
17*09d40e0eSAntonio Nino Diaz #include <hisi_ipc.h>
18*09d40e0eSAntonio Nino Diaz #include <hisi_sram_map.h>
19*09d40e0eSAntonio Nino Diaz
20127793daSHaojian Zhuang static int ipc_init;
21127793daSHaojian Zhuang
22127793daSHaojian Zhuang static unsigned int cpu_ipc_num[PLATFORM_CLUSTER_COUNT][PLATFORM_CORE_COUNT_PER_CLUSTER] = {
23127793daSHaojian Zhuang {
24127793daSHaojian Zhuang HISI_IPC_MCU_INT_SRC_ACPU0_PD,
25127793daSHaojian Zhuang HISI_IPC_MCU_INT_SRC_ACPU1_PD,
26127793daSHaojian Zhuang HISI_IPC_MCU_INT_SRC_ACPU2_PD,
27127793daSHaojian Zhuang HISI_IPC_MCU_INT_SRC_ACPU3_PD,
28127793daSHaojian Zhuang },
29127793daSHaojian Zhuang {
30127793daSHaojian Zhuang HISI_IPC_MCU_INT_SRC_ACPU4_PD,
31127793daSHaojian Zhuang HISI_IPC_MCU_INT_SRC_ACPU5_PD,
32127793daSHaojian Zhuang HISI_IPC_MCU_INT_SRC_ACPU6_PD,
33127793daSHaojian Zhuang HISI_IPC_MCU_INT_SRC_ACPU7_PD,
34127793daSHaojian Zhuang }
35127793daSHaojian Zhuang };
36127793daSHaojian Zhuang
hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu,unsigned int cluster)37127793daSHaojian Zhuang int hisi_cpus_pd_in_cluster_besides_curr(unsigned int cpu,
38127793daSHaojian Zhuang unsigned int cluster)
39127793daSHaojian Zhuang {
40127793daSHaojian Zhuang unsigned int val = 0, cpu_val = 0;
41127793daSHaojian Zhuang int i;
42127793daSHaojian Zhuang
43127793daSHaojian Zhuang val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
44127793daSHaojian Zhuang val = val >> (cluster * 16);
45127793daSHaojian Zhuang
46127793daSHaojian Zhuang for (i = 0; i < PLATFORM_CORE_COUNT_PER_CLUSTER; i++) {
47127793daSHaojian Zhuang
48127793daSHaojian Zhuang if (cpu == i)
49127793daSHaojian Zhuang continue;
50127793daSHaojian Zhuang
51127793daSHaojian Zhuang cpu_val = (val >> (i * 4)) & 0xF;
52127793daSHaojian Zhuang if (cpu_val == 0x8)
53127793daSHaojian Zhuang return 0;
54127793daSHaojian Zhuang }
55127793daSHaojian Zhuang
56127793daSHaojian Zhuang return 1;
57127793daSHaojian Zhuang }
58127793daSHaojian Zhuang
hisi_cpus_powered_off_besides_curr(unsigned int cpu)59127793daSHaojian Zhuang int hisi_cpus_powered_off_besides_curr(unsigned int cpu)
60127793daSHaojian Zhuang {
61127793daSHaojian Zhuang unsigned int val;
62127793daSHaojian Zhuang
63127793daSHaojian Zhuang val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
64127793daSHaojian Zhuang return (val == (0x8 << (cpu * 4)));
65127793daSHaojian Zhuang }
66127793daSHaojian Zhuang
hisi_ipc_send(unsigned int ipc_num)67127793daSHaojian Zhuang static void hisi_ipc_send(unsigned int ipc_num)
68127793daSHaojian Zhuang {
69127793daSHaojian Zhuang if (!ipc_init) {
7039b6cc66SAntonio Nino Diaz printf("error ipc base is null!!!\n");
71127793daSHaojian Zhuang return;
72127793daSHaojian Zhuang }
73127793daSHaojian Zhuang
74127793daSHaojian Zhuang mmio_write_32(HISI_IPC_CPU_RAW_INT_ADDR, 1 << ipc_num);
75127793daSHaojian Zhuang }
76127793daSHaojian Zhuang
hisi_ipc_spin_lock(unsigned int signal)77127793daSHaojian Zhuang void hisi_ipc_spin_lock(unsigned int signal)
78127793daSHaojian Zhuang {
79127793daSHaojian Zhuang unsigned int hs_ctrl;
80127793daSHaojian Zhuang
81127793daSHaojian Zhuang if (signal >= HISI_IPC_INT_SRC_NUM)
82127793daSHaojian Zhuang return;
83127793daSHaojian Zhuang
84127793daSHaojian Zhuang do {
85127793daSHaojian Zhuang hs_ctrl = mmio_read_32(HISI_IPC_ACPU_CTRL(signal));
86127793daSHaojian Zhuang } while (hs_ctrl);
87127793daSHaojian Zhuang }
88127793daSHaojian Zhuang
hisi_ipc_spin_unlock(unsigned int signal)89127793daSHaojian Zhuang void hisi_ipc_spin_unlock(unsigned int signal)
90127793daSHaojian Zhuang {
91127793daSHaojian Zhuang if (signal >= HISI_IPC_INT_SRC_NUM)
92127793daSHaojian Zhuang return;
93127793daSHaojian Zhuang
94127793daSHaojian Zhuang mmio_write_32(HISI_IPC_ACPU_CTRL(signal), 0);
95127793daSHaojian Zhuang }
96127793daSHaojian Zhuang
hisi_ipc_cpu_on_off(unsigned int cpu,unsigned int cluster,unsigned int mode)97127793daSHaojian Zhuang void hisi_ipc_cpu_on_off(unsigned int cpu, unsigned int cluster,
98127793daSHaojian Zhuang unsigned int mode)
99127793daSHaojian Zhuang {
100127793daSHaojian Zhuang unsigned int val = 0;
101127793daSHaojian Zhuang unsigned int offset;
102127793daSHaojian Zhuang
103127793daSHaojian Zhuang if (mode == HISI_IPC_PM_ON)
104127793daSHaojian Zhuang offset = cluster * 16 + cpu * 4;
105127793daSHaojian Zhuang else
106127793daSHaojian Zhuang offset = cluster * 16 + cpu * 4 + 1;
107127793daSHaojian Zhuang
108127793daSHaojian Zhuang hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
109127793daSHaojian Zhuang val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
110127793daSHaojian Zhuang val |= (0x01 << offset);
111127793daSHaojian Zhuang mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
112127793daSHaojian Zhuang isb();
113127793daSHaojian Zhuang dsb();
114127793daSHaojian Zhuang hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
115127793daSHaojian Zhuang
116127793daSHaojian Zhuang hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
117127793daSHaojian Zhuang }
118127793daSHaojian Zhuang
hisi_ipc_cpu_on(unsigned int cpu,unsigned int cluster)119127793daSHaojian Zhuang void hisi_ipc_cpu_on(unsigned int cpu, unsigned int cluster)
120127793daSHaojian Zhuang {
121127793daSHaojian Zhuang hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_ON);
122127793daSHaojian Zhuang }
123127793daSHaojian Zhuang
hisi_ipc_cpu_off(unsigned int cpu,unsigned int cluster)124127793daSHaojian Zhuang void hisi_ipc_cpu_off(unsigned int cpu, unsigned int cluster)
125127793daSHaojian Zhuang {
126127793daSHaojian Zhuang hisi_ipc_cpu_on_off(cpu, cluster, HISI_IPC_PM_OFF);
127127793daSHaojian Zhuang }
128127793daSHaojian Zhuang
hisi_ipc_cluster_on_off(unsigned int cpu,unsigned int cluster,unsigned int mode)129127793daSHaojian Zhuang void hisi_ipc_cluster_on_off(unsigned int cpu, unsigned int cluster,
130127793daSHaojian Zhuang unsigned int mode)
131127793daSHaojian Zhuang {
132127793daSHaojian Zhuang unsigned int val = 0;
133127793daSHaojian Zhuang unsigned int offset;
134127793daSHaojian Zhuang
135127793daSHaojian Zhuang if (mode == HISI_IPC_PM_ON)
136127793daSHaojian Zhuang offset = cluster * 4;
137127793daSHaojian Zhuang else
138127793daSHaojian Zhuang offset = cluster * 4 + 1;
139127793daSHaojian Zhuang
140127793daSHaojian Zhuang hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
141127793daSHaojian Zhuang val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
142127793daSHaojian Zhuang val |= (0x01 << offset);
143127793daSHaojian Zhuang mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
144127793daSHaojian Zhuang isb();
145127793daSHaojian Zhuang dsb();
146127793daSHaojian Zhuang hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
147127793daSHaojian Zhuang
148127793daSHaojian Zhuang hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
149127793daSHaojian Zhuang }
150127793daSHaojian Zhuang
hisi_ipc_cluster_on(unsigned int cpu,unsigned int cluster)151127793daSHaojian Zhuang void hisi_ipc_cluster_on(unsigned int cpu, unsigned int cluster)
152127793daSHaojian Zhuang {
153127793daSHaojian Zhuang hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_ON);
154127793daSHaojian Zhuang }
155127793daSHaojian Zhuang
hisi_ipc_cluster_off(unsigned int cpu,unsigned int cluster)156127793daSHaojian Zhuang void hisi_ipc_cluster_off(unsigned int cpu, unsigned int cluster)
157127793daSHaojian Zhuang {
158127793daSHaojian Zhuang hisi_ipc_cluster_on_off(cpu, cluster, HISI_IPC_PM_OFF);
159127793daSHaojian Zhuang }
160127793daSHaojian Zhuang
hisi_ipc_cpu_suspend(unsigned int cpu,unsigned int cluster)161127793daSHaojian Zhuang void hisi_ipc_cpu_suspend(unsigned int cpu, unsigned int cluster)
162127793daSHaojian Zhuang {
163127793daSHaojian Zhuang unsigned int val = 0;
164127793daSHaojian Zhuang unsigned int offset;
165127793daSHaojian Zhuang
166127793daSHaojian Zhuang offset = cluster * 16 + cpu * 4 + 2;
167127793daSHaojian Zhuang
168127793daSHaojian Zhuang hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
169127793daSHaojian Zhuang val = mmio_read_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR);
170127793daSHaojian Zhuang val |= (0x01 << offset);
171127793daSHaojian Zhuang mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, val);
172127793daSHaojian Zhuang hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
173127793daSHaojian Zhuang
174127793daSHaojian Zhuang hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
175127793daSHaojian Zhuang }
176127793daSHaojian Zhuang
hisi_ipc_cluster_suspend(unsigned int cpu,unsigned int cluster)177127793daSHaojian Zhuang void hisi_ipc_cluster_suspend(unsigned int cpu, unsigned int cluster)
178127793daSHaojian Zhuang {
179127793daSHaojian Zhuang unsigned int val;
180127793daSHaojian Zhuang unsigned int offset;
181127793daSHaojian Zhuang
182127793daSHaojian Zhuang offset = cluster * 4 + 1;
183127793daSHaojian Zhuang
184127793daSHaojian Zhuang hisi_ipc_spin_lock(HISI_IPC_SEM_CPUIDLE);
185127793daSHaojian Zhuang if (hisi_cpus_pd_in_cluster_besides_curr(cpu, cluster)) {
186127793daSHaojian Zhuang val = mmio_read_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR);
187127793daSHaojian Zhuang val |= (0x01 << offset);
188127793daSHaojian Zhuang mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, val);
189127793daSHaojian Zhuang }
190127793daSHaojian Zhuang hisi_ipc_spin_unlock(HISI_IPC_SEM_CPUIDLE);
191127793daSHaojian Zhuang
192127793daSHaojian Zhuang hisi_ipc_send(cpu_ipc_num[cluster][cpu]);
193127793daSHaojian Zhuang }
194127793daSHaojian Zhuang
hisi_ipc_psci_system_off(void)195127793daSHaojian Zhuang void hisi_ipc_psci_system_off(void)
196127793daSHaojian Zhuang {
197127793daSHaojian Zhuang hisi_ipc_send(HISI_IPC_MCU_INT_SRC_ACPU_PD);
198127793daSHaojian Zhuang }
199127793daSHaojian Zhuang
hisi_ipc_init(void)200127793daSHaojian Zhuang int hisi_ipc_init(void)
201127793daSHaojian Zhuang {
202127793daSHaojian Zhuang ipc_init = 1;
203127793daSHaojian Zhuang
204127793daSHaojian Zhuang mmio_write_32(ACPU_CORE_POWERDOWN_FLAGS_ADDR, 0x8);
205127793daSHaojian Zhuang mmio_write_32(ACPU_CLUSTER_POWERDOWN_FLAGS_ADDR, 0x8);
206127793daSHaojian Zhuang return 0;
207127793daSHaojian Zhuang }
208