Zephyr Project API 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
hwspinlock.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025 Sequans Communications
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
12
13#ifndef ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_
14#define ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_
15
24
25#include <zephyr/types.h>
26#include <zephyr/sys/util.h>
27#include <zephyr/sys/__assert.h>
28#include <zephyr/device.h>
29#include <zephyr/spinlock.h>
30#include <zephyr/devicetree.h>
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
41 const struct device *dev;
44};
45
72#define HWSPINLOCK_DT_SPEC_GET_BY_IDX(node_id, idx) \
73 { \
74 .dev = DEVICE_DT_GET(DT_HWSPINLOCK_CTRL_BY_IDX(node_id, idx)), \
75 .id = DT_HWSPINLOCK_ID_BY_IDX(node_id, idx), \
76 }
77
105#define HWSPINLOCK_DT_SPEC_GET_BY_NAME(node_id, name) \
106 { \
107 .dev = DEVICE_DT_GET(DT_HWSPINLOCK_CTRL_BY_NAME(node_id, name)), \
108 .id = DT_HWSPINLOCK_ID_BY_NAME(node_id, name), \
109 }
110
119#define HWSPINLOCK_DT_SPEC_GET(node_id) \
120 HWSPINLOCK_DT_SPEC_GET_BY_IDX(node_id, 0)
121
130#define HWSPINLOCK_DT_SPEC_INST_GET_BY_IDX(inst, idx) \
131 HWSPINLOCK_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)
132
141#define HWSPINLOCK_DT_SPEC_INST_GET_BY_NAME(inst, name) \
142 HWSPINLOCK_DT_SPEC_GET_BY_NAME(DT_DRV_INST(inst), name)
143
150#define HWSPINLOCK_DT_SPEC_INST_GET(inst) \
151 HWSPINLOCK_DT_SPEC_GET(DT_DRV_INST(inst))
152
158
159#define __HWSPINLOCK_NUM_LOCKS_FROM_DT_NODE(node_id) \
160 DT_PROP(node_id, num_locks)
161
162#define __HWSPINLOCK_SPINLOCK_ARRAY_NAME_FROM_DT_NODE(node_id) \
163 CONCAT(__hwspinlock_locks_, DT_DEP_ORD(node_id))
164
168
177#define HWSPINLOCK_COMMON_CONFIG_FROM_DT_NODE(node_id) \
178 { \
179 .num_locks = __HWSPINLOCK_NUM_LOCKS_FROM_DT_NODE(node_id), \
180 .locks = __HWSPINLOCK_SPINLOCK_ARRAY_NAME_FROM_DT_NODE(node_id), \
181 }
182
191#define HWSPINLOCK_COMMON_CONFIG_FROM_DT_INST(inst) \
192 HWSPINLOCK_COMMON_CONFIG_FROM_DT_NODE(DT_DRV_INST(inst))
193
204#define HWSPINLOCK_SPINLOCK_ARRAY_DT_DEFINE(node_id) \
205 static struct k_spinlock __HWSPINLOCK_SPINLOCK_ARRAY_NAME_FROM_DT_NODE( \
206 node_id)[__HWSPINLOCK_NUM_LOCKS_FROM_DT_NODE(node_id)]
207
218#define HWSPINLOCK_SPINLOCK_ARRAY_DT_INST_DEFINE(inst) \
219 HWSPINLOCK_SPINLOCK_ARRAY_DT_DEFINE(DT_DRV_INST(inst))
220
233
238
244typedef int (*hwspinlock_api_trylock)(const struct device *dev, uint32_t id);
245
251typedef void (*hwspinlock_api_lock)(const struct device *dev, uint32_t id);
252
258typedef void (*hwspinlock_api_unlock)(const struct device *dev, uint32_t id);
259
267typedef uint32_t (*hwspinlock_api_get_max_id)(const struct device *dev);
268
290
293
311static inline int hw_spin_trylock(const struct device *dev, uint32_t id, k_spinlock_key_t *key)
312{
313 const struct hwspinlock_driver_api *api = DEVICE_API_GET(hwspinlock, dev);
314 const struct hwspinlock_driver_config *const cfg = dev->config;
315 int ret;
316
317 if (api->trylock == NULL) {
318 return -ENOSYS;
319 }
320
321 ret = k_spin_trylock(&cfg->locks[id], key);
322 if (ret) {
323 return ret;
324 }
325
326 ret = api->trylock(dev, id);
327 if (ret) {
328 /* HW trylock failed: release local lock before returning. */
329 k_spin_unlock(&cfg->locks[id], *key);
330 }
331
332 return ret;
333}
334
358static inline k_spinlock_key_t hw_spin_lock(const struct device *dev, uint32_t id)
359{
360 const struct hwspinlock_driver_api *api = DEVICE_API_GET(hwspinlock, dev);
361 const struct hwspinlock_driver_config *const cfg = dev->config;
363
364 __ASSERT(api->lock != NULL, "hwspinlock lock callback must be implemented");
365
366 k = k_spin_lock(&cfg->locks[id]);
367 api->lock(dev, id);
368
369 return k;
370}
371
382static inline void hw_spin_unlock(const struct device *dev, uint32_t id, k_spinlock_key_t key)
383{
384 const struct hwspinlock_driver_api *api = DEVICE_API_GET(hwspinlock, dev);
385 const struct hwspinlock_driver_config *const cfg = dev->config;
386
387 __ASSERT(api->unlock != NULL, "hwspinlock unlock callback must be implemented");
388
389 api->unlock(dev, id);
390 k_spin_unlock(&cfg->locks[id], key);
391}
392
403static inline uint32_t hw_spinlock_get_max_id(const struct device *dev)
404{
405 const struct hwspinlock_driver_api *api = DEVICE_API_GET(hwspinlock, dev);
406 __unused const struct hwspinlock_driver_config *const cfg = dev->config;
407
408 if (!api->get_max_id) {
409 /* Lock ids range from 0 to n-1 */
410 return cfg->num_locks - 1;
411 }
412
413 return api->get_max_id(dev);
414}
415
427static inline int hw_spin_trylock_dt(struct hwspinlock_dt_spec *spec, k_spinlock_key_t *key)
428{
429 return hw_spin_trylock(spec->dev, spec->id, key);
430}
431
443{
444 return hw_spin_lock(spec->dev, spec->id);
445}
446
457static inline void hw_spin_unlock_dt(struct hwspinlock_dt_spec *spec, k_spinlock_key_t key)
458{
459 hw_spin_unlock(spec->dev, spec->id, key);
460}
461
473{
474 return hw_spinlock_get_max_id(spec->dev);
475}
476
477#ifdef __cplusplus
478}
479#endif
480
482
483#endif /* ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_ */
#define DEVICE_API_GET(_class, _dev)
Expands to the pointer of a device's API for a given class.
Definition device.h:1449
Devicetree main header.
void(* hwspinlock_api_lock)(const struct device *dev, uint32_t id)
Callback API to lock an HW spinlock.
Definition hwspinlock.h:251
static uint32_t hw_spinlock_get_max_id_dt(struct hwspinlock_dt_spec *spec)
Get HW spinlock max ID from a struct hwspinlock_dt_spec.
Definition hwspinlock.h:472
static int hw_spin_trylock(const struct device *dev, uint32_t id, k_spinlock_key_t *key)
Try to lock HW spinlock.
Definition hwspinlock.h:311
uint32_t(* hwspinlock_api_get_max_id)(const struct device *dev)
Callback API to get the maximum HW spinlock ID.
Definition hwspinlock.h:267
static void hw_spin_unlock_dt(struct hwspinlock_dt_spec *spec, k_spinlock_key_t key)
Unlock HW spinlock from a struct hwspinlock_dt_spec.
Definition hwspinlock.h:457
int(* hwspinlock_api_trylock)(const struct device *dev, uint32_t id)
@def_driverbackendgroup{Hardware Spinlock,hwspinlock_interface}
Definition hwspinlock.h:244
static k_spinlock_key_t hw_spin_lock_dt(struct hwspinlock_dt_spec *spec)
Lock HW spinlock from a struct hwspinlock_dt_spec.
Definition hwspinlock.h:442
static void hw_spin_unlock(const struct device *dev, uint32_t id, k_spinlock_key_t key)
Unlock HW spinlock.
Definition hwspinlock.h:382
static k_spinlock_key_t hw_spin_lock(const struct device *dev, uint32_t id)
Lock HW spinlock.
Definition hwspinlock.h:358
void(* hwspinlock_api_unlock)(const struct device *dev, uint32_t id)
Callback API to unlock an HW spinlock.
Definition hwspinlock.h:258
static uint32_t hw_spinlock_get_max_id(const struct device *dev)
Get HW spinlock max ID.
Definition hwspinlock.h:403
static int hw_spin_trylock_dt(struct hwspinlock_dt_spec *spec, k_spinlock_key_t *key)
Try to lock HW spinlock from a struct hwspinlock_dt_spec.
Definition hwspinlock.h:427
static ALWAYS_INLINE int k_spin_trylock(struct k_spinlock *l, k_spinlock_key_t *k)
Attempt to lock a spinlock.
Definition spinlock.h:242
static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l, k_spinlock_key_t key)
Unlock a spin lock.
Definition spinlock.h:312
static ALWAYS_INLINE k_spinlock_key_t k_spin_lock(struct k_spinlock *l)
Lock a spinlock.
Definition spinlock.h:192
struct z_spinlock_key k_spinlock_key_t
Spinlock key type.
Definition spinlock.h:137
#define ENOSYS
Function not implemented.
Definition errno.h:83
#define NULL
Definition iar_missing_defs.h:20
Public interface for spinlocks.
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__UINT8_TYPE__ uint8_t
Definition stdint.h:88
Runtime device structure (in ROM) per driver instance.
Definition device.h:513
const void * config
Address of device instance config information.
Definition device.h:517
@driver_ops{Hardware Spinlock}
Definition hwspinlock.h:272
hwspinlock_api_unlock unlock
@driver_ops_mandatory Unlock HW spinlock.
Definition hwspinlock.h:284
hwspinlock_api_lock lock
@driver_ops_mandatory Lock HW spinlock.
Definition hwspinlock.h:280
hwspinlock_api_get_max_id get_max_id
@driver_ops_optional Get HW spinlock max ID.
Definition hwspinlock.h:288
hwspinlock_api_trylock trylock
@driver_ops_optional Try to lock HW spinlock.
Definition hwspinlock.h:276
This structure is common to all hardware spinlock drivers and is expected to be the first element in ...
Definition hwspinlock.h:225
uint8_t num_locks
The number of hw spinlock supported by this driver.
Definition hwspinlock.h:227
struct k_spinlock * locks
Array of spinlocks that will be used to protect access to underlying hardware.
Definition hwspinlock.h:231
Complete hardware spinlock DT information.
Definition hwspinlock.h:39
const struct device * dev
HW spinlock device.
Definition hwspinlock.h:41
uint32_t id
HW spinlock id.
Definition hwspinlock.h:43
Kernel Spin Lock.
Definition spinlock.h:45
Misc utilities.