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 <aidomar@sequans.com>
This commit is contained in:
parent
68a3cce5f4
commit
c3ac598c7f
6 changed files with 225 additions and 0 deletions
|
@ -79,3 +79,4 @@ add_subdirectory_ifdef(CONFIG_WATCHDOG watchdog)
|
|||
add_subdirectory_ifdef(CONFIG_WIFI wifi)
|
||||
add_subdirectory_ifdef(CONFIG_RTC rtc)
|
||||
add_subdirectory_ifdef(CONFIG_ARM_SIP_SVC_DRIVER sip_svc)
|
||||
add_subdirectory_ifdef(CONFIG_HWSPINLOCK hwspinlock)
|
||||
|
|
|
@ -82,5 +82,6 @@ source "drivers/watchdog/Kconfig"
|
|||
source "drivers/wifi/Kconfig"
|
||||
source "drivers/xen/Kconfig"
|
||||
source "drivers/sip_svc/Kconfig"
|
||||
source "drivers/hwspinlock/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
|
5
drivers/hwspinlock/CMakeLists.txt
Normal file
5
drivers/hwspinlock/CMakeLists.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE hwspinlock_handlers.c)
|
19
drivers/hwspinlock/Kconfig
Normal file
19
drivers/hwspinlock/Kconfig
Normal file
|
@ -0,0 +1,19 @@
|
|||
# HW spinlock configuration options
|
||||
|
||||
# Copyright (c) 2023 Sequans Communications.
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig HWSPINLOCK
|
||||
bool "HW spinlock Support"
|
||||
help
|
||||
Include support for HW spinlock.
|
||||
|
||||
if HWSPINLOCK
|
||||
|
||||
config HWSPINLOCK_INIT_PRIORITY
|
||||
int "HW spinlock init priority"
|
||||
default KERNEL_INIT_PRIORITY_DEVICE
|
||||
help
|
||||
HW spinlock driver device initialization priority.
|
||||
|
||||
endif
|
40
drivers/hwspinlock/hwspinlock_handlers.c
Normal file
40
drivers/hwspinlock/hwspinlock_handlers.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Sequans Communications
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/drivers/hwspinlock.h>
|
||||
#include <zephyr/syscall_handler.h>
|
||||
|
||||
static inline int z_vrfy_hwspinlock_trylock(const struct device *dev, uint32_t id)
|
||||
{
|
||||
Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, trylock));
|
||||
return z_impl_hwspinlock_trylock(dev, id);
|
||||
}
|
||||
|
||||
#include <syscalls/hwspinlock_trylock_mrsh.c>
|
||||
|
||||
static inline void z_vrfy_hwspinlock_lock(const struct device *dev, uint32_t id)
|
||||
{
|
||||
Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, lock));
|
||||
z_impl_hwspinlock_lock(dev, id);
|
||||
}
|
||||
|
||||
#include <syscalls/hwspinlock_lock_mrsh.c>
|
||||
|
||||
static inline void z_vrfy_hwspinlock_unlock(const struct device *dev, uint32_t id)
|
||||
{
|
||||
Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, unlock));
|
||||
z_impl_hwspinlock_unlock(dev, id);
|
||||
}
|
||||
|
||||
#include <syscalls/hwspinlock_unlock_mrsh.c>
|
||||
|
||||
static inline uint32_t z_vrfy_hwspinlock_get_max_id(const struct device *dev)
|
||||
{
|
||||
Z_OOPS(Z_SYSCALL_DRIVER_HWSPINLOCK(dev, get_max_id));
|
||||
return z_impl_hwspinlock_get_max_id(dev);
|
||||
}
|
||||
|
||||
#include <syscalls/hwspinlock_get_max_id_mrsh.c>
|
159
include/zephyr/drivers/hwspinlock.h
Normal file
159
include/zephyr/drivers/hwspinlock.h
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Sequans Communications
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_
|
||||
#define ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_
|
||||
|
||||
/**
|
||||
* @brief HW spinlock Interface
|
||||
* @defgroup hwspinlock_interface HW spinlock Interface
|
||||
* @ingroup io_interfaces
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/device.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond INTERNAL_HIDDEN */
|
||||
|
||||
/**
|
||||
* @brief Callback API for trying to lock HW spinlock
|
||||
* @see hwspinlock_trylock().
|
||||
*/
|
||||
typedef int (*hwspinlock_api_trylock)(const struct device *dev, uint32_t id);
|
||||
|
||||
/**
|
||||
* @brief Callback API to lock HW spinlock
|
||||
* @see hwspinlock_lock().
|
||||
*/
|
||||
typedef void (*hwspinlock_api_lock)(const struct device *dev, uint32_t id);
|
||||
|
||||
/**
|
||||
* @brief Callback API to unlock HW spinlock
|
||||
* @see hwspinlock_unlock().
|
||||
*/
|
||||
typedef void (*hwspinlock_api_unlock)(const struct device *dev, uint32_t id);
|
||||
|
||||
/**
|
||||
* @brief Callback API to get HW spinlock max ID
|
||||
* @see hwspinlock_get_max_id().
|
||||
*/
|
||||
typedef uint32_t (*hwspinlock_api_get_max_id)(const struct device *dev);
|
||||
|
||||
__subsystem struct hwspinlock_driver_api {
|
||||
hwspinlock_api_trylock trylock;
|
||||
hwspinlock_api_lock lock;
|
||||
hwspinlock_api_unlock unlock;
|
||||
hwspinlock_api_get_max_id get_max_id;
|
||||
};
|
||||
/**
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Try to lock HW spinlock
|
||||
*
|
||||
* This function is used for try to lock specific HW spinlock. It should
|
||||
* be called before a critical section that we want to protect.
|
||||
*
|
||||
* @param dev HW spinlock device instance.
|
||||
* @param id Spinlock identifier.
|
||||
*
|
||||
* @retval 0 If successful.
|
||||
* @retval -errno In case of any failure.
|
||||
*/
|
||||
__syscall int hwspinlock_trylock(const struct device *dev, uint32_t id);
|
||||
|
||||
static inline int z_impl_hwspinlock_trylock(const struct device *dev, uint32_t id)
|
||||
{
|
||||
const struct hwspinlock_driver_api *api =
|
||||
(const struct hwspinlock_driver_api *)dev->api;
|
||||
|
||||
if (api->trylock == NULL)
|
||||
return -ENOSYS;
|
||||
|
||||
return api->trylock(dev, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock HW spinlock
|
||||
*
|
||||
* This function is used to lock specific HW spinlock. It should be
|
||||
* called before a critical section that we want to protect.
|
||||
*
|
||||
* @param dev HW spinlock device instance.
|
||||
* @param id Spinlock identifier.
|
||||
*/
|
||||
__syscall void hwspinlock_lock(const struct device *dev, uint32_t id);
|
||||
|
||||
static inline void z_impl_hwspinlock_lock(const struct device *dev, uint32_t id)
|
||||
{
|
||||
const struct hwspinlock_driver_api *api =
|
||||
(const struct hwspinlock_driver_api *)dev->api;
|
||||
|
||||
if (api->lock != NULL)
|
||||
api->lock(dev, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to unlock HW spinlock
|
||||
*
|
||||
* This function is used for try to unlock specific HW spinlock. It should
|
||||
* be called after a critical section that we want to protect.
|
||||
*
|
||||
* @param dev HW spinlock device instance.
|
||||
* @param id Spinlock identifier.
|
||||
*/
|
||||
__syscall void hwspinlock_unlock(const struct device *dev, uint32_t id);
|
||||
|
||||
static inline void z_impl_hwspinlock_unlock(const struct device *dev, uint32_t id)
|
||||
{
|
||||
const struct hwspinlock_driver_api *api =
|
||||
(const struct hwspinlock_driver_api *)dev->api;
|
||||
|
||||
if (api->unlock != NULL)
|
||||
api->unlock(dev, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get HW spinlock max ID
|
||||
*
|
||||
* This function is used to get the HW spinlock maximum ID. It should
|
||||
* be called before attempting to lock/unlock a specific HW spinlock.
|
||||
*
|
||||
* @param dev HW spinlock device instance.
|
||||
*
|
||||
* @retval HW spinlock max ID.
|
||||
* @retval 0 if the function is not implemented by the driver.
|
||||
*/
|
||||
__syscall uint32_t hwspinlock_get_max_id(const struct device *dev);
|
||||
|
||||
static inline uint32_t z_impl_hwspinlock_get_max_id(const struct device *dev)
|
||||
{
|
||||
const struct hwspinlock_driver_api *api =
|
||||
(const struct hwspinlock_driver_api *)dev->api;
|
||||
|
||||
if (api->get_max_id == NULL)
|
||||
return 0;
|
||||
|
||||
return api->get_max_id(dev);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#include <syscalls/hwspinlock.h>
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_ */
|
Loading…
Add table
Add a link
Reference in a new issue