gpio: Improve the public API to handle multi callbacks

Many sub-systems might require to set a callback on different pins.
Thus enabling it via changing the API.

It is also possible to retrieve private-data in the callback handler
using CONTAINER_OF() macro (include/misc/util.h).

Former API is still available, and is emulated through the new one.
Using both should not be a problem as it's using new API calls.
However, it's now better to start using the new API.

Change-Id: Id16594202905976cc524775d1cd3592b54a84514
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
This commit is contained in:
Tomasz Bursztyka 2016-03-23 12:01:06 +01:00 committed by Anas Nashif
commit fea1c49ba2
22 changed files with 537 additions and 224 deletions

View file

@ -30,7 +30,8 @@
#include <pinmux/frdm_k64f/pinmux_k64.h>
#include "gpio_k64.h"
#include "gpio_utils.h"
#include "gpio_api_compat.h"
static int gpio_k64_config(struct device *dev,
int access_op, uint32_t pin, int flags)
@ -182,11 +183,12 @@ static int gpio_k64_read(struct device *dev,
}
static int gpio_k64_set_callback(struct device *dev, gpio_callback_t callback)
static int gpio_k64_manage_callback(struct device *dev,
struct gpio_callback *callback, bool set)
{
struct gpio_k64_data *data = dev->driver_data;
data->callback_func = callback;
_gpio_manage_callback(&data->callbacks, callback, set);
return 0;
}
@ -198,9 +200,11 @@ static int gpio_k64_enable_callback(struct device *dev,
struct gpio_k64_data *data = dev->driver_data;
if (access_op == GPIO_ACCESS_BY_PIN) {
_gpio_enable_callback(dev, BIT(pin));
data->pin_callback_enables |= BIT(pin);
} else {
data->port_callback_enable = 1;
_gpio_enable_callback(dev, 0xFFFFFFFF);
data->pin_callback_enables = 0xFFFFFFFF;
}
return 0;
@ -213,9 +217,11 @@ static int gpio_k64_disable_callback(struct device *dev,
struct gpio_k64_data *data = dev->driver_data;
if (access_op == GPIO_ACCESS_BY_PIN) {
_gpio_disable_callback(dev, BIT(pin));
data->pin_callback_enables &= ~BIT(pin);
} else {
data->port_callback_enable = 0;
_gpio_disable_callback(dev, 0xFFFFFFFF);
data->pin_callback_enables = 0;
}
return 0;
@ -234,34 +240,15 @@ static void gpio_k64_port_isr(void *dev)
struct gpio_k64_data *data = port->driver_data;
struct gpio_k64_config *config = port->config->config_info;
mem_addr_t int_status_reg_addr;
uint32_t enabled_int, int_status, pin;
if (!data->callback_func) {
return;
}
uint32_t enabled_int, int_status;
int_status_reg_addr = config->port_base_addr +
CONFIG_PORT_K64_INT_STATUS_OFFSET;
int_status = sys_read32(int_status_reg_addr);
enabled_int = int_status & data->pin_callback_enables;
if (data->port_callback_enable) {
data->callback_func(port, int_status);
} else if (data->pin_callback_enables) {
/* perform callback for each callback-enabled pin with
* an interrupt
*/
enabled_int = int_status & data->pin_callback_enables;
while ((pin = find_lsb_set(enabled_int))) {
pin--; /* normalize the pin number */
data->callback_func(port, BIT(pin));
/* clear the interrupt status */
enabled_int &= ~BIT(pin);
}
}
_gpio_fire_callbacks(&data->callbacks, port, enabled_int);
/* clear the port interrupts */
sys_write32(0xFFFFFFFF, int_status_reg_addr);
@ -272,7 +259,7 @@ static struct gpio_driver_api gpio_k64_drv_api_funcs = {
.config = gpio_k64_config,
.write = gpio_k64_write,
.read = gpio_k64_read,
.set_callback = gpio_k64_set_callback,
.manage_callback = gpio_k64_manage_callback,
.enable_callback = gpio_k64_enable_callback,
.disable_callback = gpio_k64_disable_callback,
};
@ -293,6 +280,7 @@ DEVICE_AND_API_INIT(gpio_k64_A, CONFIG_GPIO_K64_A_DEV_NAME, gpio_k64_A_init,
&gpio_data_A, &gpio_k64_A_cfg,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_k64_drv_api_funcs);
GPIO_SETUP_COMPAT_DEV(gpio_k64_A);
static int gpio_k64_A_init(struct device *dev)
{
@ -322,6 +310,7 @@ DEVICE_AND_API_INIT(gpio_k64_B, CONFIG_GPIO_K64_B_DEV_NAME, gpio_k64_B_init,
&gpio_data_B, &gpio_k64_B_cfg,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_k64_drv_api_funcs);
GPIO_SETUP_COMPAT_DEV(gpio_k64_B);
static int gpio_k64_B_init(struct device *dev)
{
@ -351,6 +340,7 @@ DEVICE_AND_API_INIT(gpio_k64_C, CONFIG_GPIO_K64_C_DEV_NAME, gpio_k64_C_init,
&gpio_data_C, &gpio_k64_C_cfg,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_k64_drv_api_funcs);
GPIO_SETUP_COMPAT_DEV(gpio_k64_C);
static int gpio_k64_C_init(struct device *dev)
{
@ -380,6 +370,7 @@ DEVICE_AND_API_INIT(gpio_k64_D, CONFIG_GPIO_K64_D_DEV_NAME, gpio_k64_D_init,
&gpio_data_D, &gpio_k64_D_cfg,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_k64_drv_api_funcs);
GPIO_SETUP_COMPAT_DEV(gpio_k64_D);
static int gpio_k64_D_init(struct device *dev)
{
@ -409,6 +400,7 @@ DEVICE_AND_API_INIT(gpio_k64_E, CONFIG_GPIO_K64_E_DEV_NAME, gpio_k64_E_init,
&gpio_data_E, &gpio_k64_E_cfg,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
&gpio_k64_drv_api_funcs);
GPIO_SETUP_COMPAT_DEV(gpio_k64_E);
static int gpio_k64_E_init(struct device *dev)
{