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