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