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