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

@ -25,6 +25,8 @@
#include "qm_gpio.h"
#include "qm_scss.h"
#include "gpio_utils.h"
#include "gpio_api_compat.h"
struct gpio_qmsi_config {
qm_gpio_t gpio;
@ -32,9 +34,8 @@ struct gpio_qmsi_config {
};
struct gpio_qmsi_runtime {
gpio_callback_t callback;
sys_slist_t callbacks;
uint32_t pin_callbacks;
uint8_t port_callback;
};
int gpio_qmsi_init(struct device *dev);
@ -50,6 +51,8 @@ static struct gpio_qmsi_runtime gpio_0_runtime;
DEVICE_INIT(gpio_0, CONFIG_GPIO_QMSI_0_NAME, &gpio_qmsi_init,
&gpio_0_runtime, &gpio_0_config,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
GPIO_SETUP_COMPAT_DEV(gpio_0);
#endif /* CONFIG_GPIO_QMSI_0 */
#ifdef CONFIG_GPIO_QMSI_AON
@ -63,6 +66,7 @@ static struct gpio_qmsi_runtime gpio_aon_runtime;
DEVICE_INIT(gpio_aon, CONFIG_GPIO_QMSI_AON_NAME, &gpio_qmsi_init,
&gpio_aon_runtime, &gpio_aon_config,
SECONDARY, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
GPIO_SETUP_COMPAT_DEV(gpio_aon);
#endif /* CONFIG_GPIO_QMSI_AON */
@ -74,28 +78,11 @@ DEVICE_INIT(gpio_aon, CONFIG_GPIO_QMSI_AON_NAME, &gpio_qmsi_init,
*/
static void gpio_qmsi_callback(struct device *port, uint32_t status)
{
struct gpio_qmsi_config *config = port->config->config_info;
struct gpio_qmsi_runtime *context = port->driver_data;
const uint32_t enabled_mask = context->pin_callbacks & status;
int bit;
if (!context->callback) {
return;
}
if (context->port_callback) {
context->callback(port, status);
return;
}
if (!enabled_mask) {
return;
}
for (bit = 0; bit < config->num_pins; bit++) {
if (enabled_mask & BIT(bit)) {
context->callback(port, bit);
}
if (enabled_mask) {
_gpio_fire_callbacks(&context->callbacks, port, enabled_mask);
}
}
@ -233,12 +220,13 @@ static inline int gpio_qmsi_read(struct device *port,
return 0;
}
static inline int gpio_qmsi_set_callback(struct device *port,
gpio_callback_t callback)
static inline int gpio_qmsi_manage_callback(struct device *port,
struct gpio_callback *callback,
bool set)
{
struct gpio_qmsi_runtime *context = port->driver_data;
context->callback = callback;
_gpio_manage_callback(&context->callbacks, callback, set);
return 0;
}
@ -249,9 +237,11 @@ static inline int gpio_qmsi_enable_callback(struct device *port,
struct gpio_qmsi_runtime *context = port->driver_data;
if (access_op == GPIO_ACCESS_BY_PIN) {
_gpio_enable_callback(port, BIT(pin));
context->pin_callbacks |= BIT(pin);
} else {
context->port_callback = 1;
_gpio_enable_callback(port, 0xffffffff);
context->pin_callbacks = 0xffffffff;
}
return 0;
@ -263,9 +253,11 @@ static inline int gpio_qmsi_disable_callback(struct device *port,
struct gpio_qmsi_runtime *context = port->driver_data;
if (access_op == GPIO_ACCESS_BY_PIN) {
_gpio_disable_callback(port, BIT(pin));
context->pin_callbacks &= ~BIT(pin);
} else {
context->port_callback = 0;
_gpio_disable_callback(port, 0xffffffff);
context->pin_callbacks = 0;
}
return 0;
@ -275,7 +267,7 @@ static struct gpio_driver_api api_funcs = {
.config = gpio_qmsi_config,
.write = gpio_qmsi_write,
.read = gpio_qmsi_read,
.set_callback = gpio_qmsi_set_callback,
.manage_callback = gpio_qmsi_manage_callback,
.enable_callback = gpio_qmsi_enable_callback,
.disable_callback = gpio_qmsi_disable_callback,
};