ITE: drivers/gpio: Add critical section to avoid race condition

This gpio data register and keyboard scan out register are shared
register. To prevent race condition caused by access from different
thread, add critical section.

Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
This commit is contained in:
Tim Lin 2023-08-21 16:30:23 +08:00 committed by Carles Cufí
parent b18f229fc8
commit 7a2e86f563

View file

@ -11,6 +11,7 @@
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/gpio/gpio_utils.h>
#include <zephyr/dt-bindings/gpio/ite-it8xxx2-gpio.h>
#include <zephyr/irq.h>
#include <zephyr/sys/util.h>
#include <zephyr/types.h>
@ -68,6 +69,8 @@ static int gpio_kscan_it8xxx2_configure(const struct device *dev,
*reg_ksi_kso_gpod &= ~mask;
}
unsigned int key = irq_lock();
/* Set level before change to output */
if (flags & GPIO_OUTPUT_INIT_HIGH) {
*reg_ksi_kso_gdat |= mask;
@ -75,6 +78,8 @@ static int gpio_kscan_it8xxx2_configure(const struct device *dev,
*reg_ksi_kso_gdat &= ~mask;
}
irq_unlock(key);
/* Set output mode */
*reg_ksi_kso_goen |= mask;
} else {
@ -156,11 +161,14 @@ static int gpio_kscan_it8xxx2_port_set_masked_raw(const struct device *dev,
{
const struct gpio_kscan_cfg *const config = dev->config;
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
unsigned int key = irq_lock();
uint8_t out = *reg_ksi_kso_gdat;
/* Set high/low level to mask pins of the port */
*reg_ksi_kso_gdat = ((out & ~mask) | (value & mask));
irq_unlock(key);
return 0;
}
@ -169,10 +177,13 @@ static int gpio_kscan_it8xxx2_port_set_bits_raw(const struct device *dev,
{
const struct gpio_kscan_cfg *const config = dev->config;
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
unsigned int key = irq_lock();
/* Set high level to pins of the port */
*reg_ksi_kso_gdat |= pins;
irq_unlock(key);
return 0;
}
@ -181,10 +192,13 @@ static int gpio_kscan_it8xxx2_port_clear_bits_raw(const struct device *dev,
{
const struct gpio_kscan_cfg *const config = dev->config;
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
unsigned int key = irq_lock();
/* Set low level to pins of the port */
*reg_ksi_kso_gdat &= ~pins;
irq_unlock(key);
return 0;
}
@ -193,10 +207,13 @@ static int gpio_kscan_it8xxx2_port_toggle_bits(const struct device *dev,
{
const struct gpio_kscan_cfg *const config = dev->config;
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
unsigned int key = irq_lock();
/* Toggle output level to pins of the port */
*reg_ksi_kso_gdat ^= pins;
irq_unlock(key);
return 0;
}