1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "hardware/sync.h"
8 #include "hardware/claim.h"
9 
10 static_assert(PICO_SPINLOCK_ID_STRIPED_LAST >= PICO_SPINLOCK_ID_STRIPED_FIRST, "");
11 static uint8_t striped_spin_lock_num = PICO_SPINLOCK_ID_STRIPED_FIRST;
12 static uint32_t claimed;
13 
check_lock_num(uint __unused lock_num)14 static void check_lock_num(uint __unused lock_num) {
15     invalid_params_if(SYNC, lock_num >= 32);
16 }
17 
spin_locks_reset(void)18 void spin_locks_reset(void) {
19     for (uint i = 0; i < NUM_SPIN_LOCKS; i++) {
20         spin_unlock_unsafe(spin_lock_instance(i));
21     }
22 }
23 
spin_lock_init(uint lock_num)24 spin_lock_t *spin_lock_init(uint lock_num) {
25     assert(lock_num < NUM_SPIN_LOCKS);
26     spin_lock_t *lock = spin_lock_instance(lock_num);
27     spin_unlock_unsafe(lock);
28     return lock;
29 }
30 
next_striped_spin_lock_num()31 uint next_striped_spin_lock_num() {
32     uint rc = striped_spin_lock_num++;
33     if (striped_spin_lock_num > PICO_SPINLOCK_ID_STRIPED_LAST) {
34         striped_spin_lock_num = PICO_SPINLOCK_ID_STRIPED_FIRST;
35     }
36     return rc;
37 }
38 
spin_lock_claim(uint lock_num)39 void spin_lock_claim(uint lock_num) {
40     check_lock_num(lock_num);
41     hw_claim_or_assert((uint8_t *) &claimed, lock_num, "Spinlock %d is already claimed");
42 }
43 
spin_lock_claim_mask(uint32_t mask)44 void spin_lock_claim_mask(uint32_t mask) {
45     for(uint i = 0; mask; i++, mask >>= 1u) {
46         if (mask & 1u) spin_lock_claim(i);
47     }
48 }
49 
spin_lock_unclaim(uint lock_num)50 void spin_lock_unclaim(uint lock_num) {
51     check_lock_num(lock_num);
52     spin_unlock_unsafe(spin_lock_instance(lock_num));
53     hw_claim_clear((uint8_t *) &claimed, lock_num);
54 }
55 
spin_lock_claim_unused(bool required)56 int spin_lock_claim_unused(bool required) {
57     return hw_claim_unused_from_range((uint8_t*)&claimed, required, PICO_SPINLOCK_ID_CLAIM_FREE_FIRST, PICO_SPINLOCK_ID_CLAIM_FREE_LAST, "No spinlocks are available");
58 }
59 
spin_lock_is_claimed(uint lock_num)60 bool spin_lock_is_claimed(uint lock_num) {
61     check_lock_num(lock_num);
62     return hw_is_claimed((uint8_t *) &claimed, lock_num);
63 }
64 
65