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