1 /*
2  * Copyright (c) 2023 Sequans Communications
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_
8 #define ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_
9 
10 /**
11  * @brief HW spinlock Interface
12  * @defgroup hwspinlock_interface HW spinlock Interface
13  * @ingroup io_interfaces
14  * @{
15  */
16 
17 #include <errno.h>
18 #include <zephyr/types.h>
19 #include <zephyr/sys/util.h>
20 #include <zephyr/device.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 /** @cond INTERNAL_HIDDEN */
27 
28 /**
29  * @brief Callback API for trying to lock HW spinlock
30  * @see hwspinlock_trylock().
31  */
32 typedef int (*hwspinlock_api_trylock)(const struct device *dev, uint32_t id);
33 
34 /**
35  * @brief Callback API to lock HW spinlock
36  * @see hwspinlock_lock().
37  */
38 typedef void (*hwspinlock_api_lock)(const struct device *dev, uint32_t id);
39 
40 /**
41  * @brief Callback API to unlock HW spinlock
42  * @see hwspinlock_unlock().
43  */
44 typedef void (*hwspinlock_api_unlock)(const struct device *dev, uint32_t id);
45 
46 /**
47  * @brief Callback API to get HW spinlock max ID
48  * @see hwspinlock_get_max_id().
49  */
50 typedef uint32_t (*hwspinlock_api_get_max_id)(const struct device *dev);
51 
52 __subsystem struct hwspinlock_driver_api {
53 	hwspinlock_api_trylock trylock;
54 	hwspinlock_api_lock lock;
55 	hwspinlock_api_unlock unlock;
56 	hwspinlock_api_get_max_id get_max_id;
57 };
58 /**
59  * @endcond
60  */
61 
62 /**
63  * @brief Try to lock HW spinlock
64  *
65  * This function is used for try to lock specific HW spinlock. It should
66  * be called before a critical section that we want to protect.
67  *
68  * @param dev HW spinlock device instance.
69  * @param id  Spinlock identifier.
70  *
71  * @retval 0 If successful.
72  * @retval -errno In case of any failure.
73  */
74 __syscall int hwspinlock_trylock(const struct device *dev, uint32_t id);
75 
z_impl_hwspinlock_trylock(const struct device * dev,uint32_t id)76 static inline int z_impl_hwspinlock_trylock(const struct device *dev, uint32_t id)
77 {
78 	const struct hwspinlock_driver_api *api =
79 		(const struct hwspinlock_driver_api *)dev->api;
80 
81 	if (api->trylock == NULL) {
82 		return -ENOSYS;
83 	}
84 
85 	return api->trylock(dev, id);
86 }
87 
88 /**
89  * @brief Lock HW spinlock
90  *
91  * This function is used to lock specific HW spinlock. It should be
92  * called before a critical section that we want to protect.
93  *
94  * @param dev HW spinlock device instance.
95  * @param id  Spinlock identifier.
96  */
97 __syscall void hwspinlock_lock(const struct device *dev, uint32_t id);
98 
z_impl_hwspinlock_lock(const struct device * dev,uint32_t id)99 static inline void z_impl_hwspinlock_lock(const struct device *dev, uint32_t id)
100 {
101 	const struct hwspinlock_driver_api *api =
102 		(const struct hwspinlock_driver_api *)dev->api;
103 
104 	if (api->lock != NULL) {
105 		api->lock(dev, id);
106 	}
107 }
108 
109 /**
110  * @brief Try to unlock HW spinlock
111  *
112  * This function is used for try to unlock specific HW spinlock. It should
113  * be called after a critical section that we want to protect.
114  *
115  * @param dev HW spinlock device instance.
116  * @param id  Spinlock identifier.
117  */
118 __syscall void hwspinlock_unlock(const struct device *dev, uint32_t id);
119 
z_impl_hwspinlock_unlock(const struct device * dev,uint32_t id)120 static inline void z_impl_hwspinlock_unlock(const struct device *dev, uint32_t id)
121 {
122 	const struct hwspinlock_driver_api *api =
123 		(const struct hwspinlock_driver_api *)dev->api;
124 
125 	if (api->unlock != NULL) {
126 		api->unlock(dev, id);
127 	}
128 }
129 
130 /**
131  * @brief Get HW spinlock max ID
132  *
133  * This function is used to get the HW spinlock maximum ID. It should
134  * be called before attempting to lock/unlock a specific HW spinlock.
135  *
136  * @param dev HW spinlock device instance.
137  *
138  * @retval HW spinlock max ID.
139  * @retval 0 if the function is not implemented by the driver.
140  */
141 __syscall uint32_t hwspinlock_get_max_id(const struct device *dev);
142 
z_impl_hwspinlock_get_max_id(const struct device * dev)143 static inline uint32_t z_impl_hwspinlock_get_max_id(const struct device *dev)
144 {
145 	const struct hwspinlock_driver_api *api =
146 		(const struct hwspinlock_driver_api *)dev->api;
147 
148 	if (api->get_max_id == NULL) {
149 		return 0;
150 	}
151 
152 	return api->get_max_id(dev);
153 }
154 
155 #ifdef __cplusplus
156 }
157 #endif
158 
159 /** @} */
160 
161 #include <zephyr/syscalls/hwspinlock.h>
162 
163 #endif /* ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_ */
164