Skip to content
Permalink
Browse files

drivers: gpio: ht16k33: add GPIO driver for Holtek HT16K33 LED driver

The HT16K33 is a memory mapping, multifunction LED controller
driver. The controller supports up to 128 LEDs (up to 16 rows and 8
commons) and matrix key scan circuit of up to 13x3 keys.

This commit adds support for the keyscan functionality of the HT16K33.

Signed-off-by: Henrik Brix Andersen <henrik@brixandersen.dk>
  • Loading branch information...
henrikbrixandersen authored and nashif committed Mar 4, 2019
1 parent f9dd536 commit 98cecb3681dc155ee3420da5f048c1d689d44744
@@ -110,6 +110,7 @@
/drivers/ethernet/ @jukkar @tbursztyka @pfalcon
/drivers/flash/ @nashif
/drivers/flash/*stm32* @superna9999
/drivers/gpio/*ht16k33* @henrikbrixandersen
/drivers/gpio/*stm32* @rsalveti @idlethread
/drivers/hwinfo/ @alexanderwachter
/drivers/i2s/i2s_ll_stm32* @avisconti
@@ -195,6 +196,7 @@
/include/display.h @vanwinkeljan
/include/display/ @vanwinkeljan
/include/drivers/bluetooth/ @joerchan @jhedberg @Vudentz
/include/drivers/led/ht16k33.h @henrikbrixandersen
/include/drivers/modem/ @mike-scott
/include/drivers/ioapic.h @andrewboie
/include/drivers/loapic.h @andrewboie
@@ -29,6 +29,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_SX1509B gpio_sx1509b.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_INTEL_APL gpio_intel_apl.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_STELLARIS gpio_stellaris.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_RV32M1 gpio_rv32m1.c)
zephyr_library_sources_ifdef(CONFIG_GPIO_HT16K33 gpio_ht16k33.c)

zephyr_library_sources_ifdef(CONFIG_GPIO_SHELL gpio_shell.c)

@@ -74,4 +74,6 @@ source "drivers/gpio/Kconfig.stellaris"

source "drivers/gpio/Kconfig.rv32m1"

source "drivers/gpio/Kconfig.ht16k33"

endif # GPIO
@@ -0,0 +1,30 @@
#
# Copyright (c) 2019 Henrik Brix Andersen <henrik@brixandersen.dk>
#
# SPDX-License-Identifier: Apache-2.0
#

menuconfig GPIO_HT16K33
bool "HT16K33 keyscan driver"
depends on HT16K33_KEYSCAN && GPIO
help
Enable keyscan driver for HT16K33.

The HT16K33 is a memory mapping, multifunction LED
controller driver. The controller supports matrix key scan
circuit of up to 13x3 keys.

The keyscan functionality is exposed as up to 3 GPIO
controller drivers, each supporting GPIO callbacks for
keyscan event notifications.

if GPIO_HT16K33

config GPIO_HT16K33_INIT_PRIORITY
int "Driver init priority"
default 99
help
Device driver initialization priority. This driver must be
initilized after the HT16K33 LED driver.

endif #GPIO_HT16K33
@@ -0,0 +1,263 @@
/*
* Copyright (c) 2019 Henrik Brix Andersen <henrik@brixandersen.dk>
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @file
* @brief GPIO driver for the HT16K33 I2C LED driver with keyscan
*/

#include <gpio.h>
#include <zephyr.h>

#define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(gpio_ht16k33);

#include <led/ht16k33.h>

#include "gpio_utils.h"

/* HT16K33 size definitions */
#define HT16K33_KEYSCAN_ROWS 3

struct gpio_ht16k33_cfg {
char *parent_dev_name;
u8_t keyscan_idx;
};

struct gpio_ht16k33_data {
struct device *parent;
sys_slist_t callbacks;
};

static int gpio_ht16k33_cfg(struct device *dev, int access_op,
u32_t pin, int flags)
{
ARG_UNUSED(dev);
ARG_UNUSED(access_op);
ARG_UNUSED(pin);

/* Keyscan is input-only */
if ((flags & GPIO_DIR_MASK) != GPIO_DIR_IN) {
return -EINVAL;
}

return 0;
}

static int gpio_ht16k33_write(struct device *dev, int access_op,
u32_t pin, u32_t value)
{
ARG_UNUSED(dev);
ARG_UNUSED(access_op);
ARG_UNUSED(pin);
ARG_UNUSED(value);

/* Keyscan is input-only */
return -ENOTSUP;
}

static int gpio_ht16k33_read(struct device *dev, int access_op,
u32_t pin, u32_t *value)
{
ARG_UNUSED(dev);
ARG_UNUSED(access_op);
ARG_UNUSED(pin);
ARG_UNUSED(value);

/* Keyscan only supports interrupt mode */
return -ENOTSUP;
}

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,
int access_op,
u32_t pin)
{
/* All callbacks are always enabled */
return 0;
}

static int gpio_ht16k33_disable_callback(struct device *dev,
int access_op,
u32_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->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 = {
.config = gpio_ht16k33_cfg,
.write = gpio_ht16k33_write,
.read = gpio_ht16k33_read,
.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 = {\
.parent_dev_name = \
DT_HOLTEK_HT16K33_KEYSCAN_##id##_BUS_NAME, \
.keyscan_idx = \
DT_HOLTEK_HT16K33_KEYSCAN_##id##_BASE_ADDRESS, \
}; \
\
static struct gpio_ht16k33_data gpio_ht16k33_##id##_data; \
\
DEVICE_AND_API_INIT(gpio_ht16k33_##id, \
DT_HOLTEK_HT16K33_KEYSCAN_##id##_LABEL, \
&gpio_ht16k33_init, \
&gpio_ht16k33_##id##_data, \
&gpio_ht16k33_##id##_cfg, POST_KERNEL, \
CONFIG_GPIO_HT16K33_INIT_PRIORITY, \
&gpio_ht16k33_api)

/* Support up to eight HT16K33 devices, each with three keyscan devices */

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_0
GPIO_HT16K33_DEVICE(0);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_1
GPIO_HT16K33_DEVICE(1);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_2
GPIO_HT16K33_DEVICE(2);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_3
GPIO_HT16K33_DEVICE(3);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_4
GPIO_HT16K33_DEVICE(4);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_5
GPIO_HT16K33_DEVICE(5);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_6
GPIO_HT16K33_DEVICE(6);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_7
GPIO_HT16K33_DEVICE(7);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_8
GPIO_HT16K33_DEVICE(8);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_9
GPIO_HT16K33_DEVICE(9);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_10
GPIO_HT16K33_DEVICE(10);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_11
GPIO_HT16K33_DEVICE(11);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_12
GPIO_HT16K33_DEVICE(12);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_13
GPIO_HT16K33_DEVICE(13);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_14
GPIO_HT16K33_DEVICE(14);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_15
GPIO_HT16K33_DEVICE(15);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_16
GPIO_HT16K33_DEVICE(16);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_17
GPIO_HT16K33_DEVICE(17);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_18
GPIO_HT16K33_DEVICE(18);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_19
GPIO_HT16K33_DEVICE(19);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_20
GPIO_HT16K33_DEVICE(20);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_21
GPIO_HT16K33_DEVICE(21);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_22
GPIO_HT16K33_DEVICE(22);
#endif

#ifdef DT_HOLTEK_HT16K33_KEYSCAN_23
GPIO_HT16K33_DEVICE(23);
#endif

@@ -13,3 +13,47 @@ menuconfig HT16K33
The HT16K33 is a memory mapping, multifunction LED
controller driver. The controller supports up to 128 LEDs
(up to 16 rows and 8 commons).

config HT16K33_KEYSCAN
bool "Enable keyscan support"
depends on (HT16K33 && GPIO)
select GPIO_HT16K33
help
Enable keyscan child device support in the HT16K33 LED
driver.

The keyscan functionality itself is handled by the
HT16K33 GPIO driver.

if HT16K33_KEYSCAN

config HT16K33_KEYSCAN_IRQ_THREAD_STACK_SIZE
int "Stack size for keyscan interrupt request handler thread"
default 400
help
Size of the stack used for internal thread for keyscan
interrupt processing.

config HT16K33_KEYSCAN_IRQ_THREAD_PRIO
int "Priority for keyscan interrupt request handler thread"
default 2
help
Priority level for internal thread for keyscan interrupt
processing.

config HT16K33_KEYSCAN_DEBOUNCE_MSEC
int "Keyscan debounce interval in milliseconds"
default 50
range 20 1000
help
Keyscan debounce interval in milliseconds.

config HT16K33_KEYSCAN_POLL_MSEC
int "Keyscan poll interval in milliseconds"
default 200
range 20 10000
help
Keyscan poll interval in milliseconds. Polling is only used
if no interrupt line is present.

endif #HT16K33_KEYSCAN

0 comments on commit 98cecb3

Please sign in to comment.
You can’t perform that action at this time.