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