1*a2a3dfbcSJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2*a2a3dfbcSJens Wiklander /* 3*a2a3dfbcSJens Wiklander * Copyright (c) 2021-2023, Linaro Limited 4*a2a3dfbcSJens Wiklander */ 5*a2a3dfbcSJens Wiklander 6*a2a3dfbcSJens Wiklander #include <bitstring.h> 7*a2a3dfbcSJens Wiklander #include <drivers/gic.h> 8*a2a3dfbcSJens Wiklander #include <kernel/notif.h> 9*a2a3dfbcSJens Wiklander #include <kernel/spinlock.h> 10*a2a3dfbcSJens Wiklander #include <types_ext.h> 11*a2a3dfbcSJens Wiklander 12*a2a3dfbcSJens Wiklander static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1); 13*a2a3dfbcSJens Wiklander static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1); 14*a2a3dfbcSJens Wiklander static unsigned int notif_default_lock = SPINLOCK_UNLOCK; 15*a2a3dfbcSJens Wiklander 16*a2a3dfbcSJens Wiklander TEE_Result notif_alloc_async_value(uint32_t *val) 17*a2a3dfbcSJens Wiklander { 18*a2a3dfbcSJens Wiklander static bool alloc_values_inited; 19*a2a3dfbcSJens Wiklander uint32_t old_itr_status = 0; 20*a2a3dfbcSJens Wiklander int bit = 0; 21*a2a3dfbcSJens Wiklander 22*a2a3dfbcSJens Wiklander assert(interrupt_can_raise_pi(interrupt_get_main_chip())); 23*a2a3dfbcSJens Wiklander 24*a2a3dfbcSJens Wiklander old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); 25*a2a3dfbcSJens Wiklander 26*a2a3dfbcSJens Wiklander if (!alloc_values_inited) { 27*a2a3dfbcSJens Wiklander bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF); 28*a2a3dfbcSJens Wiklander alloc_values_inited = true; 29*a2a3dfbcSJens Wiklander } 30*a2a3dfbcSJens Wiklander 31*a2a3dfbcSJens Wiklander bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); 32*a2a3dfbcSJens Wiklander if (bit >= 0) { 33*a2a3dfbcSJens Wiklander *val = bit; 34*a2a3dfbcSJens Wiklander bit_set(notif_alloc_values, bit); 35*a2a3dfbcSJens Wiklander } 36*a2a3dfbcSJens Wiklander 37*a2a3dfbcSJens Wiklander cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); 38*a2a3dfbcSJens Wiklander 39*a2a3dfbcSJens Wiklander if (bit < 0) 40*a2a3dfbcSJens Wiklander return TEE_ERROR_OUT_OF_MEMORY; 41*a2a3dfbcSJens Wiklander 42*a2a3dfbcSJens Wiklander return TEE_SUCCESS; 43*a2a3dfbcSJens Wiklander } 44*a2a3dfbcSJens Wiklander 45*a2a3dfbcSJens Wiklander void notif_free_async_value(uint32_t val) 46*a2a3dfbcSJens Wiklander { 47*a2a3dfbcSJens Wiklander uint32_t old_itr_status = 0; 48*a2a3dfbcSJens Wiklander 49*a2a3dfbcSJens Wiklander old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); 50*a2a3dfbcSJens Wiklander 51*a2a3dfbcSJens Wiklander assert(val < NOTIF_ASYNC_VALUE_MAX); 52*a2a3dfbcSJens Wiklander assert(bit_test(notif_alloc_values, val)); 53*a2a3dfbcSJens Wiklander bit_clear(notif_alloc_values, val); 54*a2a3dfbcSJens Wiklander 55*a2a3dfbcSJens Wiklander cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); 56*a2a3dfbcSJens Wiklander } 57*a2a3dfbcSJens Wiklander 58*a2a3dfbcSJens Wiklander uint32_t notif_get_value(bool *value_valid, bool *value_pending) 59*a2a3dfbcSJens Wiklander { 60*a2a3dfbcSJens Wiklander uint32_t old_itr_status = 0; 61*a2a3dfbcSJens Wiklander uint32_t res = 0; 62*a2a3dfbcSJens Wiklander int bit = 0; 63*a2a3dfbcSJens Wiklander 64*a2a3dfbcSJens Wiklander old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); 65*a2a3dfbcSJens Wiklander 66*a2a3dfbcSJens Wiklander bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); 67*a2a3dfbcSJens Wiklander *value_valid = (bit >= 0); 68*a2a3dfbcSJens Wiklander if (!*value_valid) { 69*a2a3dfbcSJens Wiklander *value_pending = false; 70*a2a3dfbcSJens Wiklander goto out; 71*a2a3dfbcSJens Wiklander } 72*a2a3dfbcSJens Wiklander 73*a2a3dfbcSJens Wiklander res = bit; 74*a2a3dfbcSJens Wiklander bit_clear(notif_values, res); 75*a2a3dfbcSJens Wiklander bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit); 76*a2a3dfbcSJens Wiklander *value_pending = (bit >= 0); 77*a2a3dfbcSJens Wiklander out: 78*a2a3dfbcSJens Wiklander cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); 79*a2a3dfbcSJens Wiklander 80*a2a3dfbcSJens Wiklander return res; 81*a2a3dfbcSJens Wiklander } 82*a2a3dfbcSJens Wiklander 83*a2a3dfbcSJens Wiklander void notif_send_async(uint32_t value) 84*a2a3dfbcSJens Wiklander { 85*a2a3dfbcSJens Wiklander uint32_t old_itr_status = 0; 86*a2a3dfbcSJens Wiklander struct itr_chip *itr_chip = interrupt_get_main_chip(); 87*a2a3dfbcSJens Wiklander 88*a2a3dfbcSJens Wiklander static_assert(CFG_CORE_ASYNC_NOTIF_GIC_INTID >= GIC_PPI_BASE); 89*a2a3dfbcSJens Wiklander 90*a2a3dfbcSJens Wiklander assert(value <= NOTIF_ASYNC_VALUE_MAX); 91*a2a3dfbcSJens Wiklander old_itr_status = cpu_spin_lock_xsave(¬if_default_lock); 92*a2a3dfbcSJens Wiklander 93*a2a3dfbcSJens Wiklander DMSG("0x%"PRIx32, value); 94*a2a3dfbcSJens Wiklander bit_set(notif_values, value); 95*a2a3dfbcSJens Wiklander interrupt_raise_pi(itr_chip, CFG_CORE_ASYNC_NOTIF_GIC_INTID); 96*a2a3dfbcSJens Wiklander 97*a2a3dfbcSJens Wiklander cpu_spin_unlock_xrestore(¬if_default_lock, old_itr_status); 98*a2a3dfbcSJens Wiklander } 99