qmsi: gpio: Use locking mechanism to guard critical regions.
This will guard the driver API to be safe for concurrent invocation from fibers or tasks. The machanism is by default disabled. To enable it, the following flag needs to be defined: CONFIG_GPIO_QMSI_API_REENTRANCY Jira: ZEP-441 Change-Id: Ia3ee738aff2f8e70e4f9a7ec76346138ff6f5031 Signed-off-by: Sergio Rodriguez <sergio.sf.rodriguez@intel.com> Signed-off-by: Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com> Signed-off-by: Kuo-Lang Tseng <kuo-lang.tseng@intel.com>
This commit is contained in:
parent
3c5af9ab5b
commit
b4d87a575a
|
@ -70,4 +70,12 @@ config GPIO_QMSI_AON_IRQ_PRI
|
|||
help
|
||||
IRQ priority
|
||||
|
||||
config GPIO_QMSI_API_REENTRANCY
|
||||
bool
|
||||
prompt "GPIO driver API reentrancy"
|
||||
depends on GPIO_QMSI
|
||||
default n
|
||||
help
|
||||
Enable support for QMSI GPIO driver API reentrancy.
|
||||
|
||||
endif # GPIO_QMSI
|
||||
|
|
|
@ -37,8 +37,47 @@ struct gpio_qmsi_config {
|
|||
struct gpio_qmsi_runtime {
|
||||
sys_slist_t callbacks;
|
||||
uint32_t pin_callbacks;
|
||||
#ifdef CONFIG_GPIO_QMSI_API_REENTRANCY
|
||||
struct nano_sem sem;
|
||||
#endif /* CONFIG_GPIO_QMSI_API_REENTRANCY */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_GPIO_QMSI_API_REENTRANCY
|
||||
#define RP_GET(dev) (&((struct gpio_qmsi_runtime *)(dev->driver_data))->sem)
|
||||
static const int reentrancy_protection = 1;
|
||||
#else
|
||||
#define RP_GET(context) (NULL)
|
||||
static const int reentrancy_protection;
|
||||
#endif /* CONFIG_GPIO_QMSI_API_REENTRANCY */
|
||||
|
||||
static void gpio_reentrancy_init(struct device *dev)
|
||||
{
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_init(RP_GET(dev));
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
static void gpio_critical_region_start(struct device *dev)
|
||||
{
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_take(RP_GET(dev), TICKS_UNLIMITED);
|
||||
}
|
||||
|
||||
static void gpio_critical_region_end(struct device *dev)
|
||||
{
|
||||
if (!reentrancy_protection) {
|
||||
return;
|
||||
}
|
||||
|
||||
nano_sem_give(RP_GET(dev));
|
||||
}
|
||||
|
||||
int gpio_qmsi_init(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_GPIO_QMSI_0
|
||||
|
@ -162,7 +201,9 @@ static inline void qmsi_pin_config(struct device *port, uint32_t pin, int flags)
|
|||
return;
|
||||
}
|
||||
|
||||
gpio_critical_region_start(port);
|
||||
qm_gpio_set_config(gpio, &cfg);
|
||||
gpio_critical_region_end(port);
|
||||
}
|
||||
|
||||
static inline void qmsi_port_config(struct device *port, int flags)
|
||||
|
@ -198,6 +239,8 @@ static inline int gpio_qmsi_write(struct device *port,
|
|||
struct gpio_qmsi_config *gpio_config = port->config->config_info;
|
||||
qm_gpio_t gpio = gpio_config->gpio;
|
||||
|
||||
gpio_critical_region_start(port);
|
||||
|
||||
if (access_op == GPIO_ACCESS_BY_PIN) {
|
||||
if (value) {
|
||||
qm_gpio_set_pin(gpio, pin);
|
||||
|
@ -208,6 +251,7 @@ static inline int gpio_qmsi_write(struct device *port,
|
|||
qm_gpio_write_port(gpio, value);
|
||||
}
|
||||
|
||||
gpio_critical_region_end(port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -244,6 +288,8 @@ static inline int gpio_qmsi_enable_callback(struct device *port,
|
|||
{
|
||||
struct gpio_qmsi_runtime *context = port->driver_data;
|
||||
|
||||
gpio_critical_region_start(port);
|
||||
|
||||
if (access_op == GPIO_ACCESS_BY_PIN) {
|
||||
_gpio_enable_callback(port, BIT(pin));
|
||||
context->pin_callbacks |= BIT(pin);
|
||||
|
@ -252,6 +298,7 @@ static inline int gpio_qmsi_enable_callback(struct device *port,
|
|||
context->pin_callbacks = 0xffffffff;
|
||||
}
|
||||
|
||||
gpio_critical_region_end(port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -260,6 +307,8 @@ static inline int gpio_qmsi_disable_callback(struct device *port,
|
|||
{
|
||||
struct gpio_qmsi_runtime *context = port->driver_data;
|
||||
|
||||
gpio_critical_region_start(port);
|
||||
|
||||
if (access_op == GPIO_ACCESS_BY_PIN) {
|
||||
_gpio_disable_callback(port, BIT(pin));
|
||||
context->pin_callbacks &= ~BIT(pin);
|
||||
|
@ -268,6 +317,7 @@ static inline int gpio_qmsi_disable_callback(struct device *port,
|
|||
context->pin_callbacks = 0;
|
||||
}
|
||||
|
||||
gpio_critical_region_end(port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -284,6 +334,8 @@ int gpio_qmsi_init(struct device *port)
|
|||
{
|
||||
struct gpio_qmsi_config *gpio_config = port->config->config_info;
|
||||
|
||||
gpio_reentrancy_init(port);
|
||||
|
||||
switch (gpio_config->gpio) {
|
||||
case QM_GPIO_0:
|
||||
clk_periph_enable(CLK_PERIPH_GPIO_REGISTER |
|
||||
|
|
Loading…
Reference in a new issue