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