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