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