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 return api->trylock(dev, id);
85 }
86
87 /**
88 * @brief Lock HW spinlock
89 *
90 * This function is used to lock specific HW spinlock. It should be
91 * called before a critical section that we want to protect.
92 *
93 * @param dev HW spinlock device instance.
94 * @param id Spinlock identifier.
95 */
96 __syscall void hwspinlock_lock(const struct device *dev, uint32_t id);
97
z_impl_hwspinlock_lock(const struct device * dev,uint32_t id)98 static inline void z_impl_hwspinlock_lock(const struct device *dev, uint32_t id)
99 {
100 const struct hwspinlock_driver_api *api =
101 (const struct hwspinlock_driver_api *)dev->api;
102
103 if (api->lock != NULL)
104 api->lock(dev, id);
105 }
106
107 /**
108 * @brief Try to unlock HW spinlock
109 *
110 * This function is used for try to unlock specific HW spinlock. It should
111 * be called after a critical section that we want to protect.
112 *
113 * @param dev HW spinlock device instance.
114 * @param id Spinlock identifier.
115 */
116 __syscall void hwspinlock_unlock(const struct device *dev, uint32_t id);
117
z_impl_hwspinlock_unlock(const struct device * dev,uint32_t id)118 static inline void z_impl_hwspinlock_unlock(const struct device *dev, uint32_t id)
119 {
120 const struct hwspinlock_driver_api *api =
121 (const struct hwspinlock_driver_api *)dev->api;
122
123 if (api->unlock != NULL)
124 api->unlock(dev, id);
125 }
126
127 /**
128 * @brief Get HW spinlock max ID
129 *
130 * This function is used to get the HW spinlock maximum ID. It should
131 * be called before attempting to lock/unlock a specific HW spinlock.
132 *
133 * @param dev HW spinlock device instance.
134 *
135 * @retval HW spinlock max ID.
136 * @retval 0 if the function is not implemented by the driver.
137 */
138 __syscall uint32_t hwspinlock_get_max_id(const struct device *dev);
139
z_impl_hwspinlock_get_max_id(const struct device * dev)140 static inline uint32_t z_impl_hwspinlock_get_max_id(const struct device *dev)
141 {
142 const struct hwspinlock_driver_api *api =
143 (const struct hwspinlock_driver_api *)dev->api;
144
145 if (api->get_max_id == NULL)
146 return 0;
147
148 return api->get_max_id(dev);
149 }
150
151 #ifdef __cplusplus
152 }
153 #endif
154
155 /** @} */
156
157 #include <syscalls/hwspinlock.h>
158
159 #endif /* ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_ */
160