mirror of
https://github.com/zephyrproject-rtos/zephyr
synced 2025-08-16 14:16:32 +00:00
Usually, we want to operate only on "available" device nodes ("available" means "status is okay and a matching binding is found"), but that's not true in all cases. Sometimes we want to operate on special nodes without matching bindings, such as those describing memory. To handle the distinction, change various additional devicetree APIs making it clear that they operate only on available device nodes, adjusting gen_defines and devicetree.h implementation details accordingly: - emit macros for all existing nodes in gen_defines.py, regardless of status or matching binding - rename DT_NUM_INST to DT_NUM_INST_STATUS_OKAY - rename DT_NODE_HAS_COMPAT to DT_NODE_HAS_COMPAT_STATUS_OKAY - rename DT_INST_FOREACH to DT_INST_FOREACH_STATUS_OKAY - rename DT_ANY_INST_ON_BUS to DT_ANY_INST_ON_BUS_STATUS_OKAY - rewrite DT_HAS_NODE_STATUS_OKAY in terms of a new DT_NODE_HAS_STATUS - resurrect DT_HAS_NODE in the form of DT_NODE_EXISTS - remove DT_COMPAT_ON_BUS as a public API - use the new default_prop_types edtlib parameter Signed-off-by: Martí Bolívar <marti.bolivar@nordicsemi.no>
221 lines
5.2 KiB
C
221 lines
5.2 KiB
C
/*
|
|
* Copyright (c) 2019 Henrik Brix Andersen <henrik@brixandersen.dk>
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT holtek_ht16k33_keyscan
|
|
|
|
/**
|
|
* @file
|
|
* @brief GPIO driver for the HT16K33 I2C LED driver with keyscan
|
|
*/
|
|
|
|
#include <drivers/gpio.h>
|
|
#include <zephyr.h>
|
|
|
|
#define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
|
|
#include <logging/log.h>
|
|
LOG_MODULE_REGISTER(gpio_ht16k33);
|
|
|
|
#include <drivers/led/ht16k33.h>
|
|
|
|
#include "gpio_utils.h"
|
|
|
|
/* HT16K33 size definitions */
|
|
#define HT16K33_KEYSCAN_ROWS 3
|
|
|
|
struct gpio_ht16k33_cfg {
|
|
/* gpio_driver_config needs to be first */
|
|
struct gpio_driver_config common;
|
|
char *parent_dev_name;
|
|
u8_t keyscan_idx;
|
|
};
|
|
|
|
struct gpio_ht16k33_data {
|
|
/* gpio_driver_data needs to be first */
|
|
struct gpio_driver_data common;
|
|
struct device *parent;
|
|
sys_slist_t callbacks;
|
|
};
|
|
|
|
static int gpio_ht16k33_cfg(struct device *dev,
|
|
gpio_pin_t pin,
|
|
gpio_flags_t flags)
|
|
{
|
|
ARG_UNUSED(dev);
|
|
ARG_UNUSED(pin);
|
|
|
|
/* Keyscan is input-only */
|
|
if (((flags & (GPIO_INPUT | GPIO_OUTPUT)) == GPIO_DISCONNECTED)
|
|
|| ((flags & GPIO_OUTPUT) != 0)) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_ht16k33_port_get_raw(struct device *port,
|
|
gpio_port_value_t *value)
|
|
{
|
|
ARG_UNUSED(port);
|
|
ARG_UNUSED(value);
|
|
|
|
/* Keyscan only supports interrupt mode */
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
static int gpio_ht16k33_port_set_masked_raw(struct device *port,
|
|
gpio_port_pins_t mask,
|
|
gpio_port_value_t value)
|
|
{
|
|
ARG_UNUSED(port);
|
|
ARG_UNUSED(mask);
|
|
ARG_UNUSED(value);
|
|
|
|
/* Keyscan is input-only */
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
static int gpio_ht16k33_port_set_bits_raw(struct device *port,
|
|
gpio_port_pins_t pins)
|
|
{
|
|
ARG_UNUSED(port);
|
|
ARG_UNUSED(pins);
|
|
|
|
/* Keyscan is input-only */
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
static int gpio_ht16k33_port_clear_bits_raw(struct device *port,
|
|
gpio_port_pins_t pins)
|
|
{
|
|
ARG_UNUSED(port);
|
|
ARG_UNUSED(pins);
|
|
|
|
/* Keyscan is input-only */
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
static int gpio_ht16k33_port_toggle_bits(struct device *port,
|
|
gpio_port_pins_t pins)
|
|
{
|
|
ARG_UNUSED(port);
|
|
ARG_UNUSED(pins);
|
|
|
|
/* Keyscan is input-only */
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
static int gpio_ht16k33_pin_interrupt_configure(struct device *port,
|
|
gpio_pin_t pin,
|
|
enum gpio_int_mode int_mode,
|
|
enum gpio_int_trig int_trig)
|
|
{
|
|
ARG_UNUSED(port);
|
|
ARG_UNUSED(pin);
|
|
ARG_UNUSED(int_mode);
|
|
ARG_UNUSED(int_trig);
|
|
|
|
/* Interrupts are always enabled */
|
|
return 0;
|
|
}
|
|
|
|
void ht16k33_process_keyscan_row_data(struct device *dev,
|
|
u32_t keys)
|
|
{
|
|
struct gpio_ht16k33_data *data = dev->driver_data;
|
|
|
|
gpio_fire_callbacks(&data->callbacks, dev, keys);
|
|
}
|
|
|
|
static int gpio_ht16k33_manage_callback(struct device *dev,
|
|
struct gpio_callback *callback,
|
|
bool set)
|
|
{
|
|
struct gpio_ht16k33_data *data = dev->driver_data;
|
|
|
|
return gpio_manage_callback(&data->callbacks, callback, set);
|
|
}
|
|
|
|
static int gpio_ht16k33_enable_callback(struct device *dev,
|
|
gpio_pin_t pin)
|
|
{
|
|
/* All callbacks are always enabled */
|
|
return 0;
|
|
}
|
|
|
|
static int gpio_ht16k33_disable_callback(struct device *dev,
|
|
gpio_pin_t pin)
|
|
{
|
|
/* Individual callbacks can not be disabled */
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
static u32_t gpio_ht16k33_get_pending_int(struct device *dev)
|
|
{
|
|
struct gpio_ht16k33_data *data = dev->driver_data;
|
|
|
|
return ht16k33_get_pending_int(data->parent);
|
|
}
|
|
|
|
static int gpio_ht16k33_init(struct device *dev)
|
|
{
|
|
const struct gpio_ht16k33_cfg *config = dev->config_info;
|
|
struct gpio_ht16k33_data *data = dev->driver_data;
|
|
|
|
if (config->keyscan_idx >= HT16K33_KEYSCAN_ROWS) {
|
|
LOG_ERR("HT16K33 keyscan index out of bounds (%d)",
|
|
config->keyscan_idx);
|
|
return -EINVAL;
|
|
}
|
|
|
|
/* Establish reference to parent and vice versa */
|
|
data->parent = device_get_binding(config->parent_dev_name);
|
|
if (!data->parent) {
|
|
LOG_ERR("HT16K33 parent device '%s' not found",
|
|
config->parent_dev_name);
|
|
return -EINVAL;
|
|
}
|
|
|
|
return ht16k33_register_keyscan_device(data->parent, dev,
|
|
config->keyscan_idx);
|
|
}
|
|
|
|
static const struct gpio_driver_api gpio_ht16k33_api = {
|
|
.pin_configure = gpio_ht16k33_cfg,
|
|
.port_get_raw = gpio_ht16k33_port_get_raw,
|
|
.port_set_masked_raw = gpio_ht16k33_port_set_masked_raw,
|
|
.port_set_bits_raw = gpio_ht16k33_port_set_bits_raw,
|
|
.port_clear_bits_raw = gpio_ht16k33_port_clear_bits_raw,
|
|
.port_toggle_bits = gpio_ht16k33_port_toggle_bits,
|
|
.pin_interrupt_configure = gpio_ht16k33_pin_interrupt_configure,
|
|
.manage_callback = gpio_ht16k33_manage_callback,
|
|
.enable_callback = gpio_ht16k33_enable_callback,
|
|
.disable_callback = gpio_ht16k33_disable_callback,
|
|
.get_pending_int = gpio_ht16k33_get_pending_int,
|
|
};
|
|
|
|
#define GPIO_HT16K33_DEVICE(id) \
|
|
static const struct gpio_ht16k33_cfg gpio_ht16k33_##id##_cfg = {\
|
|
.common = { \
|
|
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_NGPIOS(13), \
|
|
}, \
|
|
.parent_dev_name = \
|
|
DT_INST_BUS_LABEL(id), \
|
|
.keyscan_idx = \
|
|
DT_INST_REG_ADDR(id), \
|
|
}; \
|
|
\
|
|
static struct gpio_ht16k33_data gpio_ht16k33_##id##_data; \
|
|
\
|
|
DEVICE_AND_API_INIT(gpio_ht16k33_##id, \
|
|
DT_INST_LABEL(id), \
|
|
&gpio_ht16k33_init, \
|
|
&gpio_ht16k33_##id##_data, \
|
|
&gpio_ht16k33_##id##_cfg, POST_KERNEL, \
|
|
CONFIG_GPIO_HT16K33_INIT_PRIORITY, \
|
|
&gpio_ht16k33_api);
|
|
|
|
DT_INST_FOREACH_STATUS_OKAY(GPIO_HT16K33_DEVICE)
|