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