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