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