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