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