Skip to content

Commit c3ac598

Browse files
Aziz Idomarcarlescufi
authored andcommitted
drivers: introduce hardware spinlock framework
The intention of hardware spinlock is to allow two processors, that have no alternative mechanism for accomplish synchronization and mutual exclusion operations, to share resources (such as memory and/or any other element). Here, we add the hwspinlock framework, that makes possible to use those hwspinlock devices and stay platform-independent. Each platform wishing to support hardware spinlock must describe a driver using this framework. Signed-off-by: Aziz Idomar <[email protected]>
1 parent 68a3cce commit c3ac598

File tree

6 files changed

+225
-0
lines changed

6 files changed

+225
-0
lines changed

drivers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,4 @@ add_subdirectory_ifdef(CONFIG_WATCHDOG watchdog)
7979
add_subdirectory_ifdef(CONFIG_WIFI wifi)
8080
add_subdirectory_ifdef(CONFIG_RTC rtc)
8181
add_subdirectory_ifdef(CONFIG_ARM_SIP_SVC_DRIVER sip_svc)
82+
add_subdirectory_ifdef(CONFIG_HWSPINLOCK hwspinlock)

drivers/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,6 @@ source "drivers/watchdog/Kconfig"
8282
source "drivers/wifi/Kconfig"
8383
source "drivers/xen/Kconfig"
8484
source "drivers/sip_svc/Kconfig"
85+
source "drivers/hwspinlock/Kconfig"
8586

8687
endmenu

drivers/hwspinlock/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
zephyr_library()
4+
5+
zephyr_library_sources_ifdef(CONFIG_USERSPACE hwspinlock_handlers.c)

drivers/hwspinlock/Kconfig

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# HW spinlock configuration options
2+
3+
# Copyright (c) 2023 Sequans Communications.
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
menuconfig HWSPINLOCK
7+
bool "HW spinlock Support"
8+
help
9+
Include support for HW spinlock.
10+
11+
if HWSPINLOCK
12+
13+
config HWSPINLOCK_INIT_PRIORITY
14+
int "HW spinlock init priority"
15+
default KERNEL_INIT_PRIORITY_DEVICE
16+
help
17+
HW spinlock driver device initialization priority.
18+
19+
endif
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2023 Sequans Communications
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/drivers/hwspinlock.h>
8+
#include <zephyr/syscall_handler.h>
9+
10+
static inline int z_vrfy_hwspinlock_trylock(const struct device *dev, uint32_t id)
11+
{
12+
Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, trylock));
13+
return z_impl_hwspinlock_trylock(dev, id);
14+
}
15+
16+
#include <syscalls/hwspinlock_trylock_mrsh.c>
17+
18+
static inline void z_vrfy_hwspinlock_lock(const struct device *dev, uint32_t id)
19+
{
20+
Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, lock));
21+
z_impl_hwspinlock_lock(dev, id);
22+
}
23+
24+
#include <syscalls/hwspinlock_lock_mrsh.c>
25+
26+
static inline void z_vrfy_hwspinlock_unlock(const struct device *dev, uint32_t id)
27+
{
28+
Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, unlock));
29+
z_impl_hwspinlock_unlock(dev, id);
30+
}
31+
32+
#include <syscalls/hwspinlock_unlock_mrsh.c>
33+
34+
static inline uint32_t z_vrfy_hwspinlock_get_max_id(const struct device *dev)
35+
{
36+
Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, get_max_id));
37+
return z_impl_hwspinlock_get_max_id(dev);
38+
}
39+
40+
#include <syscalls/hwspinlock_get_max_id_mrsh.c>

include/zephyr/drivers/hwspinlock.h

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
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+
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+
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+
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+
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_ */

0 commit comments

Comments
 (0)