forked from kofal.net/zmk
refactor: Move away from deprecated label usages.
* Move away from DT_LABEL. * Move to DEVICE_DT_GET for non-behavior device access. * Move various drivers to `gpio_spec_dt` and `DT` related macros. * Remove mcp23017 while at it, since better upstream driver is available.
This commit is contained in:
committed by
Pete Johanson
parent
062f94d014
commit
09ed79a867
@@ -24,23 +24,6 @@ LOG_MODULE_REGISTER(il0323, CONFIG_DISPLAY_LOG_LEVEL);
|
||||
*
|
||||
*/
|
||||
|
||||
#define IL0323_SPI_FREQ DT_INST_PROP(0, spi_max_frequency)
|
||||
#define IL0323_BUS_NAME DT_INST_BUS_LABEL(0)
|
||||
#define IL0323_DC_PIN DT_INST_GPIO_PIN(0, dc_gpios)
|
||||
#define IL0323_DC_FLAGS DT_INST_GPIO_FLAGS(0, dc_gpios)
|
||||
#define IL0323_DC_CNTRL DT_INST_GPIO_LABEL(0, dc_gpios)
|
||||
#define IL0323_CS_PIN DT_INST_SPI_DEV_CS_GPIOS_PIN(0)
|
||||
#define IL0323_CS_FLAGS DT_INST_SPI_DEV_CS_GPIOS_FLAGS(0)
|
||||
#if DT_INST_SPI_DEV_HAS_CS_GPIOS(0)
|
||||
#define IL0323_CS_CNTRL DT_INST_SPI_DEV_CS_GPIOS_LABEL(0)
|
||||
#endif
|
||||
#define IL0323_BUSY_PIN DT_INST_GPIO_PIN(0, busy_gpios)
|
||||
#define IL0323_BUSY_CNTRL DT_INST_GPIO_LABEL(0, busy_gpios)
|
||||
#define IL0323_BUSY_FLAGS DT_INST_GPIO_FLAGS(0, busy_gpios)
|
||||
#define IL0323_RESET_PIN DT_INST_GPIO_PIN(0, reset_gpios)
|
||||
#define IL0323_RESET_CNTRL DT_INST_GPIO_LABEL(0, reset_gpios)
|
||||
#define IL0323_RESET_FLAGS DT_INST_GPIO_FLAGS(0, reset_gpios)
|
||||
|
||||
#define EPD_PANEL_WIDTH DT_INST_PROP(0, width)
|
||||
#define EPD_PANEL_HEIGHT DT_INST_PROP(0, height)
|
||||
#define IL0323_PIXELS_PER_BYTE 8U
|
||||
@@ -53,15 +36,11 @@ LOG_MODULE_REGISTER(il0323, CONFIG_DISPLAY_LOG_LEVEL);
|
||||
#define IL0323_PANEL_LAST_PAGE (IL0323_NUMOF_PAGES - 1)
|
||||
#define IL0323_BUFFER_SIZE 1280
|
||||
|
||||
struct il0323_data {
|
||||
const struct device *reset;
|
||||
const struct device *dc;
|
||||
const struct device *busy;
|
||||
const struct device *spi_dev;
|
||||
struct spi_config spi_config;
|
||||
#if defined(IL0323_CS_CNTRL)
|
||||
struct spi_cs_control cs_ctrl;
|
||||
#endif
|
||||
struct il0323_cfg {
|
||||
struct gpio_dt_spec reset;
|
||||
struct gpio_dt_spec dc;
|
||||
struct gpio_dt_spec busy;
|
||||
struct spi_dt_spec spi;
|
||||
};
|
||||
|
||||
static uint8_t il0323_pwr[] = DT_INST_PROP(0, pwr);
|
||||
@@ -69,21 +48,21 @@ static uint8_t il0323_pwr[] = DT_INST_PROP(0, pwr);
|
||||
static uint8_t last_buffer[IL0323_BUFFER_SIZE];
|
||||
static bool blanking_on = true;
|
||||
|
||||
static inline int il0323_write_cmd(struct il0323_data *driver, uint8_t cmd, uint8_t *data,
|
||||
static inline int il0323_write_cmd(const struct il0323_cfg *cfg, uint8_t cmd, uint8_t *data,
|
||||
size_t len) {
|
||||
struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)};
|
||||
struct spi_buf_set buf_set = {.buffers = &buf, .count = 1};
|
||||
|
||||
gpio_pin_set(driver->dc, IL0323_DC_PIN, 1);
|
||||
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
|
||||
gpio_pin_set_dt(&cfg->dc, 1);
|
||||
if (spi_write_dt(&cfg->spi, &buf_set)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (data != NULL) {
|
||||
buf.buf = data;
|
||||
buf.len = len;
|
||||
gpio_pin_set(driver->dc, IL0323_DC_PIN, 0);
|
||||
if (spi_write(driver->spi_dev, &driver->spi_config, &buf_set)) {
|
||||
gpio_pin_set_dt(&cfg->dc, 0);
|
||||
if (spi_write_dt(&cfg->spi, &buf_set)) {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
@@ -91,22 +70,22 @@ static inline int il0323_write_cmd(struct il0323_data *driver, uint8_t cmd, uint
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void il0323_busy_wait(struct il0323_data *driver) {
|
||||
int pin = gpio_pin_get(driver->busy, IL0323_BUSY_PIN);
|
||||
static inline void il0323_busy_wait(const struct il0323_cfg *cfg) {
|
||||
int pin = gpio_pin_get_dt(&cfg->busy);
|
||||
|
||||
while (pin > 0) {
|
||||
__ASSERT(pin >= 0, "Failed to get pin level");
|
||||
// LOG_DBG("wait %u", pin);
|
||||
k_msleep(IL0323_BUSY_DELAY);
|
||||
pin = gpio_pin_get(driver->busy, IL0323_BUSY_PIN);
|
||||
pin = gpio_pin_get_dt(&cfg->busy);
|
||||
}
|
||||
}
|
||||
|
||||
static int il0323_update_display(const struct device *dev) {
|
||||
struct il0323_data *driver = dev->data;
|
||||
const struct il0323_cfg *cfg = dev->config;
|
||||
|
||||
LOG_DBG("Trigger update sequence");
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_DRF, NULL, 0)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_DRF, NULL, 0)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -117,7 +96,7 @@ static int il0323_update_display(const struct device *dev) {
|
||||
|
||||
static int il0323_write(const struct device *dev, const uint16_t x, const uint16_t y,
|
||||
const struct display_buffer_descriptor *desc, const void *buf) {
|
||||
struct il0323_data *driver = dev->data;
|
||||
const struct il0323_cfg *cfg = dev->config;
|
||||
uint16_t x_end_idx = x + desc->width - 1;
|
||||
uint16_t y_end_idx = y + desc->height - 1;
|
||||
uint8_t ptl[IL0323_PTL_REG_LENGTH] = {0};
|
||||
@@ -147,20 +126,20 @@ static int il0323_write(const struct device *dev, const uint16_t x, const uint16
|
||||
ptl[sizeof(ptl) - 1] = IL0323_PTL_PT_SCAN;
|
||||
LOG_HEXDUMP_DBG(ptl, sizeof(ptl), "ptl");
|
||||
|
||||
il0323_busy_wait(driver);
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_PIN, NULL, 0)) {
|
||||
il0323_busy_wait(cfg);
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_PIN, NULL, 0)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_PTL, ptl, sizeof(ptl))) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_PTL, ptl, sizeof(ptl))) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_DTM1, last_buffer, IL0323_BUFFER_SIZE)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_DTM1, last_buffer, IL0323_BUFFER_SIZE)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_DTM2, (uint8_t *)buf, buf_len)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_DTM2, (uint8_t *)buf, buf_len)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -173,7 +152,7 @@ static int il0323_write(const struct device *dev, const uint16_t x, const uint16
|
||||
}
|
||||
}
|
||||
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_POUT, NULL, 0)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_POUT, NULL, 0)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -217,11 +196,11 @@ static int il0323_clear_and_write_buffer(const struct device *dev, uint8_t patte
|
||||
}
|
||||
|
||||
static int il0323_blanking_off(const struct device *dev) {
|
||||
struct il0323_data *driver = dev->data;
|
||||
const struct il0323_cfg *cfg = dev->config;
|
||||
|
||||
if (blanking_on) {
|
||||
/* Update EPD pannel in normal mode */
|
||||
il0323_busy_wait(driver);
|
||||
/* Update EPD panel in normal mode */
|
||||
il0323_busy_wait(cfg);
|
||||
if (il0323_clear_and_write_buffer(dev, 0xff, true)) {
|
||||
return -EIO;
|
||||
}
|
||||
@@ -278,30 +257,30 @@ static int il0323_set_pixel_format(const struct device *dev, const enum display_
|
||||
}
|
||||
|
||||
static int il0323_controller_init(const struct device *dev) {
|
||||
struct il0323_data *driver = dev->data;
|
||||
const struct il0323_cfg *cfg = dev->config;
|
||||
uint8_t tmp[IL0323_TRES_REG_LENGTH];
|
||||
|
||||
LOG_DBG("");
|
||||
|
||||
gpio_pin_set(driver->reset, IL0323_RESET_PIN, 1);
|
||||
gpio_pin_set_dt(&cfg->reset, 1);
|
||||
k_msleep(IL0323_RESET_DELAY);
|
||||
gpio_pin_set(driver->reset, IL0323_RESET_PIN, 0);
|
||||
gpio_pin_set_dt(&cfg->reset, 0);
|
||||
k_msleep(IL0323_RESET_DELAY);
|
||||
il0323_busy_wait(driver);
|
||||
il0323_busy_wait(cfg);
|
||||
|
||||
LOG_DBG("Initialize IL0323 controller");
|
||||
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_PWR, il0323_pwr, sizeof(il0323_pwr))) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_PWR, il0323_pwr, sizeof(il0323_pwr))) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Turn on: booster, controller, regulators, and sensor. */
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_PON, NULL, 0)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_PON, NULL, 0)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
k_msleep(IL0323_PON_DELAY);
|
||||
il0323_busy_wait(driver);
|
||||
il0323_busy_wait(cfg);
|
||||
|
||||
/* Pannel settings, KW mode */
|
||||
tmp[0] = IL0323_PSR_UD | IL0323_PSR_SHL | IL0323_PSR_SHD | IL0323_PSR_RST;
|
||||
@@ -321,7 +300,7 @@ static int il0323_controller_init(const struct device *dev) {
|
||||
#endif /* panel width */
|
||||
|
||||
LOG_HEXDUMP_DBG(tmp, 1, "PSR");
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_PSR, tmp, 1)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_PSR, tmp, 1)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -329,24 +308,24 @@ static int il0323_controller_init(const struct device *dev) {
|
||||
tmp[IL0323_TRES_HRES_IDX] = EPD_PANEL_WIDTH;
|
||||
tmp[IL0323_TRES_VRES_IDX] = EPD_PANEL_HEIGHT;
|
||||
LOG_HEXDUMP_DBG(tmp, IL0323_TRES_REG_LENGTH, "TRES");
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_TRES, tmp, IL0323_TRES_REG_LENGTH)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_TRES, tmp, IL0323_TRES_REG_LENGTH)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
tmp[IL0323_CDI_CDI_IDX] = DT_INST_PROP(0, cdi);
|
||||
LOG_HEXDUMP_DBG(tmp, IL0323_CDI_REG_LENGTH, "CDI");
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_CDI, tmp, IL0323_CDI_REG_LENGTH)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_CDI, tmp, IL0323_CDI_REG_LENGTH)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
tmp[0] = DT_INST_PROP(0, tcon);
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_TCON, tmp, 1)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_TCON, tmp, 1)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Enable Auto Sequence */
|
||||
tmp[0] = IL0323_AUTO_PON_DRF_POF;
|
||||
if (il0323_write_cmd(driver, IL0323_CMD_AUTO, tmp, 1)) {
|
||||
if (il0323_write_cmd(cfg, IL0323_CMD_AUTO, tmp, 1)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -354,62 +333,43 @@ static int il0323_controller_init(const struct device *dev) {
|
||||
}
|
||||
|
||||
static int il0323_init(const struct device *dev) {
|
||||
struct il0323_data *driver = dev->data;
|
||||
const struct il0323_cfg *cfg = dev->config;
|
||||
|
||||
LOG_DBG("");
|
||||
|
||||
driver->spi_dev = device_get_binding(IL0323_BUS_NAME);
|
||||
if (driver->spi_dev == NULL) {
|
||||
LOG_ERR("Could not get SPI device for IL0323");
|
||||
if (!spi_is_ready(&cfg->spi)) {
|
||||
LOG_ERR("SPI device not ready for IL0323");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
driver->spi_config.frequency = IL0323_SPI_FREQ;
|
||||
driver->spi_config.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8);
|
||||
driver->spi_config.slave = DT_INST_REG_ADDR(0);
|
||||
driver->spi_config.cs = NULL;
|
||||
|
||||
driver->reset = device_get_binding(IL0323_RESET_CNTRL);
|
||||
if (driver->reset == NULL) {
|
||||
if (!device_is_ready(cfg->reset.port)) {
|
||||
LOG_ERR("Could not get GPIO port for IL0323 reset");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
gpio_pin_configure(driver->reset, IL0323_RESET_PIN, GPIO_OUTPUT_INACTIVE | IL0323_RESET_FLAGS);
|
||||
gpio_pin_configure_dt(&cfg->reset, GPIO_OUTPUT_INACTIVE);
|
||||
|
||||
driver->dc = device_get_binding(IL0323_DC_CNTRL);
|
||||
if (driver->dc == NULL) {
|
||||
if (!device_is_ready(cfg->dc.port)) {
|
||||
LOG_ERR("Could not get GPIO port for IL0323 DC signal");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
gpio_pin_configure(driver->dc, IL0323_DC_PIN, GPIO_OUTPUT_INACTIVE | IL0323_DC_FLAGS);
|
||||
gpio_pin_configure_dt(&cfg->dc, GPIO_OUTPUT_INACTIVE);
|
||||
|
||||
driver->busy = device_get_binding(IL0323_BUSY_CNTRL);
|
||||
if (driver->busy == NULL) {
|
||||
if (!device_is_ready(cfg->busy.port)) {
|
||||
LOG_ERR("Could not get GPIO port for IL0323 busy signal");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
gpio_pin_configure(driver->busy, IL0323_BUSY_PIN, GPIO_INPUT | IL0323_BUSY_FLAGS);
|
||||
|
||||
#if defined(IL0323_CS_CNTRL)
|
||||
driver->cs_ctrl.gpio_dev = device_get_binding(IL0323_CS_CNTRL);
|
||||
if (!driver->cs_ctrl.gpio_dev) {
|
||||
LOG_ERR("Unable to get SPI GPIO CS device");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
driver->cs_ctrl.gpio_pin = IL0323_CS_PIN;
|
||||
driver->cs_ctrl.gpio_dt_flags = IL0323_CS_FLAGS;
|
||||
driver->cs_ctrl.delay = 0U;
|
||||
driver->spi_config.cs = &driver->cs_ctrl;
|
||||
#endif
|
||||
gpio_pin_configure_dt(&cfg->busy, GPIO_INPUT);
|
||||
|
||||
return il0323_controller_init(dev);
|
||||
}
|
||||
|
||||
static struct il0323_data il0323_driver;
|
||||
static struct il0323_cfg il0323_config = {
|
||||
.spi = SPI_DT_SPEC_INST_GET(0, SPI_OP_MODE_MASTER | SPI_WORD_SET(8), 0),
|
||||
.reset = GPIO_DT_SPEC_INST_GET(0, reset_gpios),
|
||||
.busy = GPIO_DT_SPEC_INST_GET(0, busy_gpios),
|
||||
.dc = GPIO_DT_SPEC_INST_GET(0, dc_gpios),
|
||||
};
|
||||
|
||||
static struct display_driver_api il0323_driver_api = {
|
||||
.blanking_on = il0323_blanking_on,
|
||||
@@ -424,5 +384,5 @@ static struct display_driver_api il0323_driver_api = {
|
||||
.set_orientation = il0323_set_orientation,
|
||||
};
|
||||
|
||||
DEVICE_DT_INST_DEFINE(0, il0323_init, NULL, &il0323_driver, NULL, POST_KERNEL,
|
||||
DEVICE_DT_INST_DEFINE(0, il0323_init, NULL, NULL, &il0323_config, POST_KERNEL,
|
||||
CONFIG_APPLICATION_INIT_PRIORITY, &il0323_driver_api);
|
||||
|
||||
@@ -5,5 +5,4 @@ zephyr_library_named(zmk__drivers__gpio)
|
||||
zephyr_library_include_directories(${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_595 gpio_595.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_MCP23017 gpio_mcp23017.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_MAX7318 gpio_max7318.c)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
menuconfig ZMK_DRIVERS_GPIO
|
||||
bool "GPIO"
|
||||
|
||||
rsource "Kconfig.mcp23017"
|
||||
rsource "Kconfig.max7318"
|
||||
rsource "Kconfig.595"
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
# MCP23017 GPIO configuration options
|
||||
|
||||
# Copyright (c) 2021 Pete Johanson
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig GPIO_MCP23017
|
||||
bool "MCP23017 I2C-based GPIO chip"
|
||||
depends on I2C
|
||||
select HAS_DTS_GPIO
|
||||
select ZMK_DRIVERS_GPIO
|
||||
help
|
||||
Enable driver for MCP23017 I2C-based GPIO chip.
|
||||
|
||||
if GPIO_MCP23017
|
||||
|
||||
config GPIO_MCP23017_INIT_PRIORITY
|
||||
int "Init priority"
|
||||
default 75
|
||||
help
|
||||
Device driver initialization priority.
|
||||
|
||||
endif #GPIO_MCP23017
|
||||
@@ -1,332 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Geanix ApS
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT microchip_mcp23017
|
||||
|
||||
/**
|
||||
* @file Driver for MCP23017 SPI-based GPIO driver.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <sys/byteorder.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <drivers/i2c.h>
|
||||
|
||||
#include "gpio_mcp23017.h"
|
||||
|
||||
#define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(gpio_mcp23017);
|
||||
|
||||
/**
|
||||
* @brief Read both port 0 and port 1 registers of certain register function.
|
||||
*
|
||||
* Given the register in reg, read the pair of port 0 and port 1.
|
||||
*
|
||||
* @param dev Device struct of the MCP23017.
|
||||
* @param reg Register to read (the PORTA of the pair of registers).
|
||||
* @param buf Buffer to read data into.
|
||||
*
|
||||
* @return 0 if successful, failed otherwise.
|
||||
*/
|
||||
static int read_port_regs(const struct device *dev, uint8_t reg, uint16_t *buf) {
|
||||
const struct mcp23017_config *const config = dev->config;
|
||||
struct mcp23017_drv_data *const drv_data = (struct mcp23017_drv_data *const)dev->data;
|
||||
int ret;
|
||||
uint16_t port_data;
|
||||
|
||||
uint8_t addr = config->slave;
|
||||
|
||||
ret = i2c_burst_read(drv_data->i2c, addr, reg, (uint8_t *)&port_data, sizeof(port_data));
|
||||
if (ret) {
|
||||
LOG_DBG("i2c_write_read FAIL %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*buf = sys_le16_to_cpu(port_data);
|
||||
|
||||
LOG_DBG("MCP23017: Read: REG[0x%X] = 0x%X, REG[0x%X] = 0x%X", reg, (*buf & 0xFF), (reg + 1),
|
||||
(*buf >> 8));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write both port 0 and port 1 registers of certain register function.
|
||||
*
|
||||
* Given the register in reg, write the pair of port 0 and port 1.
|
||||
*
|
||||
* @param dev Device struct of the MCP23017.
|
||||
* @param reg Register to write into (the PORTA of the pair of registers).
|
||||
* @param buf Buffer to write data from.
|
||||
*
|
||||
* @return 0 if successful, failed otherwise.
|
||||
*/
|
||||
static int write_port_regs(const struct device *dev, uint8_t reg, uint16_t value) {
|
||||
const struct mcp23017_config *const config = dev->config;
|
||||
struct mcp23017_drv_data *const drv_data = (struct mcp23017_drv_data *const)dev->data;
|
||||
int ret;
|
||||
uint16_t port_data;
|
||||
|
||||
LOG_DBG("MCP23017: Write: REG[0x%X] = 0x%X, REG[0x%X] = 0x%X", reg, (value & 0xFF), (reg + 1),
|
||||
(value >> 8));
|
||||
|
||||
port_data = sys_cpu_to_le16(value);
|
||||
|
||||
ret = i2c_burst_write(drv_data->i2c, config->slave, reg, (uint8_t *)&port_data,
|
||||
sizeof(port_data));
|
||||
if (ret) {
|
||||
LOG_DBG("i2c_write FAIL %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup the pin direction (input or output)
|
||||
*
|
||||
* @param dev Device struct of the MCP23017
|
||||
* @param pin The pin number
|
||||
* @param flags Flags of pin or port
|
||||
*
|
||||
* @return 0 if successful, failed otherwise
|
||||
*/
|
||||
static int setup_pin_dir(const struct device *dev, uint32_t pin, int flags) {
|
||||
struct mcp23017_drv_data *const drv_data = (struct mcp23017_drv_data *const)dev->data;
|
||||
uint16_t *dir = &drv_data->reg_cache.iodir;
|
||||
uint16_t *output = &drv_data->reg_cache.gpio;
|
||||
int ret;
|
||||
|
||||
if ((flags & GPIO_OUTPUT) != 0U) {
|
||||
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
|
||||
*output |= BIT(pin);
|
||||
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
|
||||
*output &= ~BIT(pin);
|
||||
}
|
||||
*dir &= ~BIT(pin);
|
||||
} else {
|
||||
*dir |= BIT(pin);
|
||||
}
|
||||
|
||||
ret = write_port_regs(dev, REG_GPIO_PORTA, *output);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = write_port_regs(dev, REG_IODIR_PORTA, *dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Setup the pin pull up/pull down status
|
||||
*
|
||||
* @param dev Device struct of the MCP23017
|
||||
* @param pin The pin number
|
||||
* @param flags Flags of pin or port
|
||||
*
|
||||
* @return 0 if successful, failed otherwise
|
||||
*/
|
||||
static int setup_pin_pullupdown(const struct device *dev, uint32_t pin, int flags) {
|
||||
struct mcp23017_drv_data *const drv_data = (struct mcp23017_drv_data *const)dev->data;
|
||||
uint16_t port;
|
||||
int ret;
|
||||
|
||||
/* Setup pin pull up or pull down */
|
||||
port = drv_data->reg_cache.gppu;
|
||||
|
||||
/* pull down == 0, pull up == 1 */
|
||||
if ((flags & GPIO_PULL_DOWN) != 0U) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
WRITE_BIT(port, pin, (flags & GPIO_PULL_UP) != 0U);
|
||||
|
||||
ret = write_port_regs(dev, REG_GPPU_PORTA, port);
|
||||
if (ret == 0) {
|
||||
drv_data->reg_cache.gppu = port;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mcp23017_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) {
|
||||
struct mcp23017_drv_data *const drv_data = (struct mcp23017_drv_data *const)dev->data;
|
||||
int ret;
|
||||
|
||||
/* Can't do SPI bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
k_sem_take(&drv_data->lock, K_FOREVER);
|
||||
|
||||
if ((flags & GPIO_OPEN_DRAIN) != 0U) {
|
||||
ret = -ENOTSUP;
|
||||
goto done;
|
||||
};
|
||||
|
||||
ret = setup_pin_dir(dev, pin, flags);
|
||||
if (ret) {
|
||||
LOG_ERR("MCP23017: error setting pin direction (%d)", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = setup_pin_pullupdown(dev, pin, flags);
|
||||
if (ret) {
|
||||
LOG_ERR("MCP23017: error setting pin pull up/down (%d)", ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
k_sem_give(&drv_data->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mcp23017_port_get_raw(const struct device *dev, uint32_t *value) {
|
||||
struct mcp23017_drv_data *const drv_data = (struct mcp23017_drv_data *const)dev->data;
|
||||
uint16_t buf;
|
||||
int ret;
|
||||
|
||||
/* Can't do SPI bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
k_sem_take(&drv_data->lock, K_FOREVER);
|
||||
|
||||
ret = read_port_regs(dev, REG_GPIO_PORTA, &buf);
|
||||
if (ret != 0) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
*value = buf;
|
||||
|
||||
done:
|
||||
k_sem_give(&drv_data->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mcp23017_port_set_masked_raw(const struct device *dev, uint32_t mask, uint32_t value) {
|
||||
struct mcp23017_drv_data *const drv_data = (struct mcp23017_drv_data *const)dev->data;
|
||||
uint16_t buf;
|
||||
int ret;
|
||||
|
||||
/* Can't do SPI bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
k_sem_take(&drv_data->lock, K_FOREVER);
|
||||
|
||||
buf = drv_data->reg_cache.gpio;
|
||||
buf = (buf & ~mask) | (mask & value);
|
||||
|
||||
ret = write_port_regs(dev, REG_GPIO_PORTA, buf);
|
||||
if (ret == 0) {
|
||||
drv_data->reg_cache.gpio = buf;
|
||||
}
|
||||
|
||||
k_sem_give(&drv_data->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mcp23017_port_set_bits_raw(const struct device *dev, uint32_t mask) {
|
||||
return mcp23017_port_set_masked_raw(dev, mask, mask);
|
||||
}
|
||||
|
||||
static int mcp23017_port_clear_bits_raw(const struct device *dev, uint32_t mask) {
|
||||
return mcp23017_port_set_masked_raw(dev, mask, 0);
|
||||
}
|
||||
|
||||
static int mcp23017_port_toggle_bits(const struct device *dev, uint32_t mask) {
|
||||
struct mcp23017_drv_data *const drv_data = (struct mcp23017_drv_data *const)dev->data;
|
||||
uint16_t buf;
|
||||
int ret;
|
||||
|
||||
/* Can't do SPI bus operations from an ISR */
|
||||
if (k_is_in_isr()) {
|
||||
return -EWOULDBLOCK;
|
||||
}
|
||||
|
||||
k_sem_take(&drv_data->lock, K_FOREVER);
|
||||
|
||||
buf = drv_data->reg_cache.gpio;
|
||||
buf ^= mask;
|
||||
|
||||
ret = write_port_regs(dev, REG_GPIO_PORTA, buf);
|
||||
if (ret == 0) {
|
||||
drv_data->reg_cache.gpio = buf;
|
||||
}
|
||||
|
||||
k_sem_give(&drv_data->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mcp23017_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin,
|
||||
enum gpio_int_mode mode, enum gpio_int_trig trig) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static const struct gpio_driver_api api_table = {
|
||||
.pin_configure = mcp23017_config,
|
||||
.port_get_raw = mcp23017_port_get_raw,
|
||||
.port_set_masked_raw = mcp23017_port_set_masked_raw,
|
||||
.port_set_bits_raw = mcp23017_port_set_bits_raw,
|
||||
.port_clear_bits_raw = mcp23017_port_clear_bits_raw,
|
||||
.port_toggle_bits = mcp23017_port_toggle_bits,
|
||||
.pin_interrupt_configure = mcp23017_pin_interrupt_configure,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialization function of MCP23017
|
||||
*
|
||||
* @param dev Device struct
|
||||
* @return 0 if successful, failed otherwise.
|
||||
*/
|
||||
static int mcp23017_init(const struct device *dev) {
|
||||
const struct mcp23017_config *const config = dev->config;
|
||||
struct mcp23017_drv_data *const drv_data = (struct mcp23017_drv_data *const)dev->data;
|
||||
|
||||
drv_data->i2c = device_get_binding((char *)config->i2c_dev_name);
|
||||
if (!drv_data->i2c) {
|
||||
LOG_DBG("Unable to get i2c device");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
k_sem_init(&drv_data->lock, 1, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define MCP23017_INIT(inst) \
|
||||
static struct mcp23017_config mcp23017_##inst##_config = { \
|
||||
.i2c_dev_name = DT_INST_BUS_LABEL(inst), \
|
||||
.slave = DT_INST_REG_ADDR(inst), \
|
||||
\
|
||||
}; \
|
||||
\
|
||||
static struct mcp23017_drv_data mcp23017_##inst##_drvdata = { \
|
||||
/* Default for registers according to datasheet */ \
|
||||
.reg_cache.iodir = 0xFFFF, .reg_cache.ipol = 0x0, .reg_cache.gpinten = 0x0, \
|
||||
.reg_cache.defval = 0x0, .reg_cache.intcon = 0x0, .reg_cache.iocon = 0x0, \
|
||||
.reg_cache.gppu = 0x0, .reg_cache.intf = 0x0, .reg_cache.intcap = 0x0, \
|
||||
.reg_cache.gpio = 0x0, .reg_cache.olat = 0x0, \
|
||||
}; \
|
||||
\
|
||||
/* This has to init after SPI master */ \
|
||||
DEVICE_DT_INST_DEFINE(inst, mcp23017_init, NULL, &mcp23017_##inst##_drvdata, \
|
||||
&mcp23017_##inst##_config, POST_KERNEL, \
|
||||
CONFIG_GPIO_MCP23017_INIT_PRIORITY, &api_table);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(MCP23017_INIT)
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Geanix ApS, Pete Johanson
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file Header file for the MCP23017 driver.
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_GPIO_GPIO_MCP23017_H_
|
||||
#define ZEPHYR_DRIVERS_GPIO_GPIO_MCP23017_H_
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <drivers/gpio.h>
|
||||
#include <drivers/i2c.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Register definitions */
|
||||
#define REG_IODIR_PORTA 0x00
|
||||
#define REG_IODIR_PORTB 0x01
|
||||
#define REG_IPOL_PORTA 0x02
|
||||
#define REG_IPOL_PORTB 0x03
|
||||
#define REG_GPINTEN_PORTA 0x04
|
||||
#define REG_GPINTEN_PORTB 0x05
|
||||
#define REG_DEFVAL_PORTA 0x06
|
||||
#define REG_DEFVAL_PORTB 0x07
|
||||
#define REG_INTCON_PORTA 0x08
|
||||
#define REG_INTCON_PORTB 0x09
|
||||
#define REG_GPPU_PORTA 0x0C
|
||||
#define REG_GPPU_PORTB 0x0D
|
||||
#define REG_INTF_PORTA 0x0E
|
||||
#define REG_INTF_PORTB 0x0F
|
||||
#define REG_INTCAP_PORTA 0x10
|
||||
#define REG_INTCAP_PORTB 0x11
|
||||
#define REG_GPIO_PORTA 0x12
|
||||
#define REG_GPIO_PORTB 0x13
|
||||
#define REG_OLAT_PORTA 0x14
|
||||
#define REG_OLAT_PORTB 0x15
|
||||
|
||||
#define MCP23017_ADDR 0x40
|
||||
#define MCP23017_READBIT 0x01
|
||||
|
||||
/** Configuration data */
|
||||
struct mcp23017_config {
|
||||
/* gpio_driver_data needs to be first */
|
||||
struct gpio_driver_config common;
|
||||
|
||||
const char *const i2c_dev_name;
|
||||
const uint16_t slave;
|
||||
};
|
||||
|
||||
/** Runtime driver data */
|
||||
struct mcp23017_drv_data {
|
||||
/* gpio_driver_data needs to be first */
|
||||
struct gpio_driver_config data;
|
||||
|
||||
/** Master SPI device */
|
||||
const struct device *i2c;
|
||||
|
||||
struct k_sem lock;
|
||||
|
||||
struct {
|
||||
uint16_t iodir;
|
||||
uint16_t ipol;
|
||||
uint16_t gpinten;
|
||||
uint16_t defval;
|
||||
uint16_t intcon;
|
||||
uint16_t iocon;
|
||||
uint16_t gppu;
|
||||
uint16_t intf;
|
||||
uint16_t intcap;
|
||||
uint16_t gpio;
|
||||
uint16_t olat;
|
||||
} reg_cache;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_DRIVERS_GPIO_GPIO_MCP23017_H_ */
|
||||
@@ -7,7 +7,7 @@
|
||||
#define DT_DRV_COMPAT zmk_kscan_composite
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <drivers/kscan.h>
|
||||
#include <zephyr/drivers/kscan.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
@@ -16,13 +16,13 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
#define MATRIX_COLS DT_PROP(MATRIX_NODE_ID, columns)
|
||||
|
||||
struct kscan_composite_child_config {
|
||||
char *label;
|
||||
const struct device *child;
|
||||
uint8_t row_offset;
|
||||
uint8_t column_offset;
|
||||
};
|
||||
|
||||
#define CHILD_CONFIG(inst) \
|
||||
{.label = DT_LABEL(DT_PHANDLE(inst, kscan)), \
|
||||
{.child = DEVICE_DT_GET(DT_PHANDLE(inst, kscan)), \
|
||||
.row_offset = DT_PROP(inst, row_offset), \
|
||||
.column_offset = DT_PROP(inst, column_offset)},
|
||||
|
||||
@@ -41,12 +41,7 @@ static int kscan_composite_enable_callback(const struct device *dev) {
|
||||
for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) {
|
||||
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
|
||||
|
||||
const struct device *dev = device_get_binding(cfg->label);
|
||||
if (!dev) {
|
||||
LOG_WRN("Failed to load child kscan device %s", cfg->label);
|
||||
continue;
|
||||
}
|
||||
kscan_enable_callback(dev);
|
||||
kscan_enable_callback(cfg->child);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -55,12 +50,7 @@ static int kscan_composite_disable_callback(const struct device *dev) {
|
||||
for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) {
|
||||
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
|
||||
|
||||
const struct device *dev = device_get_binding(cfg->label);
|
||||
if (!dev) {
|
||||
LOG_WRN("Failed to load child kscan device %s", cfg->label);
|
||||
continue;
|
||||
}
|
||||
kscan_disable_callback(dev);
|
||||
kscan_disable_callback(cfg->child);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -68,13 +58,13 @@ static int kscan_composite_disable_callback(const struct device *dev) {
|
||||
static void kscan_composite_child_callback(const struct device *child_dev, uint32_t row,
|
||||
uint32_t column, bool pressed) {
|
||||
// TODO: Ideally we can get this passed into our callback!
|
||||
const struct device *dev = device_get_binding(DT_INST_LABEL(0));
|
||||
const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0));
|
||||
struct kscan_composite_data *data = dev->data;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) {
|
||||
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
|
||||
|
||||
if (device_get_binding(cfg->label) != child_dev) {
|
||||
if (cfg->child != child_dev) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -92,7 +82,7 @@ static int kscan_composite_configure(const struct device *dev, kscan_callback_t
|
||||
for (int i = 0; i < ARRAY_SIZE(kscan_composite_children); i++) {
|
||||
const struct kscan_composite_child_config *cfg = &kscan_composite_children[i];
|
||||
|
||||
kscan_config(device_get_binding(cfg->label), &kscan_composite_child_callback);
|
||||
kscan_config(cfg->child, &kscan_composite_child_callback);
|
||||
}
|
||||
|
||||
data->callback = callback;
|
||||
|
||||
@@ -13,26 +13,11 @@
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct kscan_gpio_item_config {
|
||||
char *label;
|
||||
gpio_pin_t pin;
|
||||
gpio_flags_t flags;
|
||||
};
|
||||
|
||||
// Helper macro
|
||||
#define PWR_TWO(x) (1 << (x))
|
||||
|
||||
// Define GPIO cfg
|
||||
#define _KSCAN_GPIO_ITEM_CFG_INIT(n, prop, idx) \
|
||||
{ \
|
||||
.label = DT_INST_GPIO_LABEL_BY_IDX(n, prop, idx), \
|
||||
.pin = DT_INST_GPIO_PIN_BY_IDX(n, prop, idx), \
|
||||
.flags = DT_INST_GPIO_FLAGS_BY_IDX(n, prop, idx), \
|
||||
}
|
||||
|
||||
// Define row and col cfg
|
||||
#define _KSCAN_GPIO_INPUT_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, input_gpios, idx)
|
||||
#define _KSCAN_GPIO_OUTPUT_CFG_INIT(idx, n) _KSCAN_GPIO_ITEM_CFG_INIT(n, output_gpios, idx)
|
||||
#define _KSCAN_GPIO_CFG_INIT(n, prop, idx) GPIO_DT_SPEC_GET_BY_IDX(n, prop, idx),
|
||||
|
||||
// Check debounce config
|
||||
#define CHECK_DEBOUNCE_CFG(n, a, b) COND_CODE_0(DT_INST_PROP(n, debounce_period), a, b)
|
||||
@@ -51,8 +36,8 @@ struct kscan_gpio_item_config {
|
||||
}; \
|
||||
\
|
||||
struct kscan_gpio_config_##n { \
|
||||
struct kscan_gpio_item_config rows[INST_MATRIX_INPUTS(n)]; \
|
||||
struct kscan_gpio_item_config cols[INST_DEMUX_GPIOS(n)]; \
|
||||
const struct gpio_dt_spec rows[INST_MATRIX_INPUTS(n)]; \
|
||||
const struct gpio_dt_spec cols[INST_DEMUX_GPIOS(n)]; \
|
||||
}; \
|
||||
\
|
||||
struct kscan_gpio_data_##n { \
|
||||
@@ -60,33 +45,16 @@ struct kscan_gpio_item_config {
|
||||
struct k_timer poll_timer; \
|
||||
struct CHECK_DEBOUNCE_CFG(n, (k_work), (k_work_delayable)) work; \
|
||||
bool matrix_state[INST_MATRIX_INPUTS(n)][INST_MATRIX_OUTPUTS(n)]; \
|
||||
const struct device *rows[INST_MATRIX_INPUTS(n)]; \
|
||||
const struct device *cols[INST_MATRIX_OUTPUTS(n)]; \
|
||||
const struct device *dev; \
|
||||
}; \
|
||||
/* IO/GPIO SETUP */ \
|
||||
/* gpio_input_devices are PHYSICAL IO devices */ \
|
||||
static const struct device **kscan_gpio_input_devices_##n(const struct device *dev) { \
|
||||
struct kscan_gpio_data_##n *data = dev->data; \
|
||||
return data->rows; \
|
||||
} \
|
||||
\
|
||||
static const struct kscan_gpio_item_config *kscan_gpio_input_configs_##n( \
|
||||
const struct device *dev) { \
|
||||
static const struct gpio_dt_spec *kscan_gpio_input_specs_##n(const struct device *dev) { \
|
||||
const struct kscan_gpio_config_##n *cfg = dev->config; \
|
||||
return cfg->rows; \
|
||||
} \
|
||||
\
|
||||
/* gpio_output_devices are PHYSICAL IO devices */ \
|
||||
static const struct device **kscan_gpio_output_devices_##n(const struct device *dev) { \
|
||||
struct kscan_gpio_data_##n *data = dev->data; \
|
||||
return data->cols; \
|
||||
} \
|
||||
\
|
||||
static const struct kscan_gpio_item_config *kscan_gpio_output_configs_##n( \
|
||||
const struct device *dev) { \
|
||||
static const struct gpio_dt_spec *kscan_gpio_output_specs_##n(const struct device *dev) { \
|
||||
const struct kscan_gpio_config_##n *cfg = dev->config; \
|
||||
/* If row2col, rows = outputs & cols = inputs */ \
|
||||
return cfg->cols; \
|
||||
} \
|
||||
/* POLLING SETUP */ \
|
||||
@@ -106,21 +74,16 @@ struct kscan_gpio_item_config {
|
||||
/* Iterate over bits and set GPIOs accordingly */ \
|
||||
for (uint8_t bit = 0; bit < INST_DEMUX_GPIOS(n); bit++) { \
|
||||
uint8_t state = (o & (0b1 << bit)) >> bit; \
|
||||
const struct device *out_dev = kscan_gpio_output_devices_##n(dev)[bit]; \
|
||||
const struct kscan_gpio_item_config *out_cfg = \
|
||||
&kscan_gpio_output_configs_##n(dev)[bit]; \
|
||||
gpio_pin_set(out_dev, out_cfg->pin, state); \
|
||||
const struct gpio_dt_spec *out_spec = &kscan_gpio_output_specs_##n(dev)[bit]; \
|
||||
gpio_pin_set_dt(out_spec, state); \
|
||||
} \
|
||||
/* Let the col settle before reading the rows */ \
|
||||
k_usleep(1); \
|
||||
\
|
||||
for (int i = 0; i < INST_MATRIX_INPUTS(n); i++) { \
|
||||
/* Get the input device (port) */ \
|
||||
const struct device *in_dev = kscan_gpio_input_devices_##n(dev)[i]; \
|
||||
/* Get the input device config (pin) */ \
|
||||
const struct kscan_gpio_item_config *in_cfg = \
|
||||
&kscan_gpio_input_configs_##n(dev)[i]; \
|
||||
read_state[i][o] = gpio_pin_get(in_dev, in_cfg->pin) > 0; \
|
||||
/* Get the input spec */ \
|
||||
const struct gpio_dt_spec *in_spec = &kscan_gpio_input_specs_##n(dev)[i]; \
|
||||
read_state[i][o] = gpio_pin_get_dt(in_spec) > 0; \
|
||||
} \
|
||||
} \
|
||||
for (int r = 0; r < INST_MATRIX_INPUTS(n); r++) { \
|
||||
@@ -146,8 +109,7 @@ struct kscan_gpio_item_config {
|
||||
kscan_gpio_read_##n(data->dev); \
|
||||
} \
|
||||
\
|
||||
static struct kscan_gpio_data_##n kscan_gpio_data_##n = { \
|
||||
.rows = {[INST_MATRIX_INPUTS(n) - 1] = NULL}, .cols = {[INST_DEMUX_GPIOS(n) - 1] = NULL}}; \
|
||||
static struct kscan_gpio_data_##n kscan_gpio_data_##n = {}; \
|
||||
\
|
||||
/* KSCAN API configure function */ \
|
||||
static int kscan_gpio_configure_##n(const struct device *dev, kscan_callback_t callback) { \
|
||||
@@ -185,20 +147,18 @@ struct kscan_gpio_item_config {
|
||||
struct kscan_gpio_data_##n *data = dev->data; \
|
||||
int err; \
|
||||
/* configure input devices*/ \
|
||||
const struct device **input_devices = kscan_gpio_input_devices_##n(dev); \
|
||||
for (int i = 0; i < INST_MATRIX_INPUTS(n); i++) { \
|
||||
const struct kscan_gpio_item_config *in_cfg = &kscan_gpio_input_configs_##n(dev)[i]; \
|
||||
input_devices[i] = device_get_binding(in_cfg->label); \
|
||||
if (!input_devices[i]) { \
|
||||
const struct gpio_dt_spec *in_spec = &kscan_gpio_input_specs_##n(dev)[i]; \
|
||||
if (!device_is_ready(in_spec->port)) { \
|
||||
LOG_ERR("Unable to find input GPIO device"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
err = gpio_pin_configure(input_devices[i], in_cfg->pin, GPIO_INPUT | in_cfg->flags); \
|
||||
err = gpio_pin_configure_dt(in_spec, GPIO_INPUT); \
|
||||
if (err) { \
|
||||
LOG_ERR("Unable to configure pin %d on %s for input", in_cfg->pin, in_cfg->label); \
|
||||
LOG_ERR("Unable to configure pin %d for input", in_spec->pin); \
|
||||
return err; \
|
||||
} else { \
|
||||
LOG_DBG("Configured pin %d on %s for input", in_cfg->pin, in_cfg->label); \
|
||||
LOG_DBG("Configured pin %d for input", in_spec->pin); \
|
||||
} \
|
||||
if (err) { \
|
||||
LOG_ERR("Error adding the callback to the column device"); \
|
||||
@@ -206,22 +166,18 @@ struct kscan_gpio_item_config {
|
||||
} \
|
||||
} \
|
||||
/* configure output devices*/ \
|
||||
const struct device **output_devices = kscan_gpio_output_devices_##n(dev); \
|
||||
for (int o = 0; o < INST_DEMUX_GPIOS(n); o++) { \
|
||||
const struct kscan_gpio_item_config *out_cfg = &kscan_gpio_output_configs_##n(dev)[o]; \
|
||||
output_devices[o] = device_get_binding(out_cfg->label); \
|
||||
if (!output_devices[o]) { \
|
||||
const struct gpio_dt_spec *out_spec = &kscan_gpio_output_specs_##n(dev)[o]; \
|
||||
if (!device_is_ready(out_spec->port)) { \
|
||||
LOG_ERR("Unable to find output GPIO device"); \
|
||||
return -EINVAL; \
|
||||
} \
|
||||
err = gpio_pin_configure(output_devices[o], out_cfg->pin, \
|
||||
GPIO_OUTPUT_ACTIVE | out_cfg->flags); \
|
||||
err = gpio_pin_configure_dt(out_spec, GPIO_OUTPUT_ACTIVE); \
|
||||
if (err) { \
|
||||
LOG_ERR("Unable to configure pin %d on %s for output", out_cfg->pin, \
|
||||
out_cfg->label); \
|
||||
LOG_ERR("Unable to configure pin %d for output", out_spec->pin); \
|
||||
return err; \
|
||||
} else { \
|
||||
LOG_DBG("Configured pin %d on %s for output", out_cfg->pin, out_cfg->label); \
|
||||
LOG_DBG("Configured pin %d for output", out_spec->pin); \
|
||||
} \
|
||||
} \
|
||||
data->dev = dev; \
|
||||
@@ -240,8 +196,8 @@ struct kscan_gpio_item_config {
|
||||
}; \
|
||||
\
|
||||
static const struct kscan_gpio_config_##n kscan_gpio_config_##n = { \
|
||||
.rows = {LISTIFY(INST_MATRIX_INPUTS(n), _KSCAN_GPIO_INPUT_CFG_INIT, (, ), n)}, \
|
||||
.cols = {LISTIFY(INST_DEMUX_GPIOS(n), _KSCAN_GPIO_OUTPUT_CFG_INIT, (, ), n)}, \
|
||||
.rows = {DT_FOREACH_PROP_ELEM(DT_DRV_INST(n), input_gpios, _KSCAN_GPIO_CFG_INIT)}, \
|
||||
.cols = {DT_FOREACH_PROP_ELEM(DT_DRV_INST(n), output_gpios, _KSCAN_GPIO_CFG_INIT)}, \
|
||||
}; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, kscan_gpio_init_##n, NULL, &kscan_gpio_data_##n, \
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <drivers/adc.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/adc.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "battery_common.h"
|
||||
@@ -21,22 +21,15 @@ struct io_channel_config {
|
||||
uint8_t channel;
|
||||
};
|
||||
|
||||
struct gpio_channel_config {
|
||||
const char *label;
|
||||
uint8_t pin;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
struct bvd_config {
|
||||
struct io_channel_config io_channel;
|
||||
struct gpio_channel_config power_gpios;
|
||||
struct gpio_dt_spec power;
|
||||
uint32_t output_ohm;
|
||||
uint32_t full_ohm;
|
||||
};
|
||||
|
||||
struct bvd_data {
|
||||
const struct device *adc;
|
||||
const struct device *gpio;
|
||||
struct adc_channel_cfg acc;
|
||||
struct adc_sequence as;
|
||||
struct battery_value value;
|
||||
@@ -56,19 +49,19 @@ static int bvd_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
|
||||
int rc = 0;
|
||||
|
||||
// Enable power GPIO if present
|
||||
if (drv_data->gpio) {
|
||||
rc = gpio_pin_set(drv_data->gpio, drv_cfg->power_gpios.pin, 1);
|
||||
#if DT_INST_NODE_HAS_PROP(0, power_gpios)
|
||||
// Enable power before sampling
|
||||
rc = gpio_pin_set_dt(&drv_cfg->power, 1);
|
||||
|
||||
if (rc != 0) {
|
||||
LOG_DBG("Failed to enable ADC power GPIO: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// wait for any capacitance to charge up
|
||||
k_sleep(K_MSEC(10));
|
||||
if (rc != 0) {
|
||||
LOG_DBG("Failed to enable ADC power GPIO: %d", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// wait for any capacitance to charge up
|
||||
k_sleep(K_MSEC(10));
|
||||
#endif // DT_INST_NODE_HAS_PROP(0, power_gpios)
|
||||
|
||||
// Read ADC
|
||||
rc = adc_read(drv_data->adc, as);
|
||||
as->calibrate = false;
|
||||
@@ -90,15 +83,15 @@ static int bvd_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
LOG_DBG("Failed to read ADC: %d", rc);
|
||||
}
|
||||
|
||||
#if DT_INST_NODE_HAS_PROP(0, power_gpios)
|
||||
// Disable power GPIO if present
|
||||
if (drv_data->gpio) {
|
||||
int rc2 = gpio_pin_set(drv_data->gpio, drv_cfg->power_gpios.pin, 0);
|
||||
int rc2 = gpio_pin_set_dt(&drv_cfg->power, 0);
|
||||
|
||||
if (rc2 != 0) {
|
||||
LOG_DBG("Failed to disable ADC power GPIO: %d", rc2);
|
||||
return rc2;
|
||||
}
|
||||
if (rc2 != 0) {
|
||||
LOG_DBG("Failed to disable ADC power GPIO: %d", rc2);
|
||||
return rc2;
|
||||
}
|
||||
#endif // DT_INST_NODE_HAS_PROP(0, power_gpios)
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -125,20 +118,17 @@ static int bvd_init(const struct device *dev) {
|
||||
|
||||
int rc = 0;
|
||||
|
||||
if (drv_cfg->power_gpios.label) {
|
||||
drv_data->gpio = device_get_binding(drv_cfg->power_gpios.label);
|
||||
if (drv_data->gpio == NULL) {
|
||||
LOG_ERR("Failed to get GPIO %s", drv_cfg->power_gpios.label);
|
||||
return -ENODEV;
|
||||
}
|
||||
rc = gpio_pin_configure(drv_data->gpio, drv_cfg->power_gpios.pin,
|
||||
GPIO_OUTPUT_INACTIVE | drv_cfg->power_gpios.flags);
|
||||
if (rc != 0) {
|
||||
LOG_ERR("Failed to control feed %s.%u: %d", drv_cfg->power_gpios.label,
|
||||
drv_cfg->power_gpios.pin, rc);
|
||||
return rc;
|
||||
}
|
||||
#if DT_INST_NODE_HAS_PROP(0, power_gpios)
|
||||
if (!device_is_ready(drv_cfg->power.port)) {
|
||||
LOG_ERR("GPIO port for power control is not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
rc = gpio_pin_configure_dt(&drv_cfg->power, GPIO_OUTPUT_INACTIVE);
|
||||
if (rc != 0) {
|
||||
LOG_ERR("Failed to control feed %u: %d", drv_cfg->power.pin, rc);
|
||||
return rc;
|
||||
}
|
||||
#endif // DT_INST_NODE_HAS_PROP(0, power_gpios)
|
||||
|
||||
drv_data->as = (struct adc_sequence){
|
||||
.channels = BIT(0),
|
||||
@@ -175,12 +165,7 @@ static const struct bvd_config bvd_cfg = {
|
||||
DT_IO_CHANNELS_INPUT(DT_DRV_INST(0)),
|
||||
},
|
||||
#if DT_INST_NODE_HAS_PROP(0, power_gpios)
|
||||
.power_gpios =
|
||||
{
|
||||
DT_INST_GPIO_LABEL(0, power_gpios),
|
||||
DT_INST_GPIO_PIN(0, power_gpios),
|
||||
DT_INST_GPIO_FLAGS(0, power_gpios),
|
||||
},
|
||||
.power = GPIO_DT_SPEC_INST_GET(0, power_gpios),
|
||||
#endif
|
||||
.output_ohm = DT_INST_PROP(0, output_ohms),
|
||||
.full_ohm = DT_INST_PROP(0, full_ohms),
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
LOG_MODULE_REGISTER(EC11, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int ec11_get_ab_state(const struct device *dev) {
|
||||
struct ec11_data *drv_data = dev->data;
|
||||
const struct ec11_config *drv_cfg = dev->config;
|
||||
|
||||
return (gpio_pin_get(drv_data->a, drv_cfg->a_pin) << 1) |
|
||||
gpio_pin_get(drv_data->b, drv_cfg->b_pin);
|
||||
return (gpio_pin_get_dt(&drv_cfg->a) << 1) | gpio_pin_get_dt(&drv_cfg->b);
|
||||
}
|
||||
|
||||
static int ec11_sample_fetch(const struct device *dev, enum sensor_channel chan) {
|
||||
@@ -94,27 +92,25 @@ int ec11_init(const struct device *dev) {
|
||||
struct ec11_data *drv_data = dev->data;
|
||||
const struct ec11_config *drv_cfg = dev->config;
|
||||
|
||||
LOG_DBG("A: %s %d B: %s %d resolution %d", drv_cfg->a_label, drv_cfg->a_pin, drv_cfg->b_label,
|
||||
drv_cfg->b_pin, drv_cfg->resolution);
|
||||
LOG_DBG("A: %s %d B: %s %d resolution %d", drv_cfg->a.port->name, drv_cfg->a.pin,
|
||||
drv_cfg->b.port->name, drv_cfg->b.pin, drv_cfg->resolution);
|
||||
|
||||
drv_data->a = device_get_binding(drv_cfg->a_label);
|
||||
if (drv_data->a == NULL) {
|
||||
LOG_ERR("Failed to get pointer to A GPIO device");
|
||||
if (!device_is_ready(drv_cfg->a.port)) {
|
||||
LOG_ERR("A GPIO device is not ready");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
drv_data->b = device_get_binding(drv_cfg->b_label);
|
||||
if (drv_data->b == NULL) {
|
||||
LOG_ERR("Failed to get pointer to B GPIO device");
|
||||
if (!device_is_ready(drv_cfg->b.port)) {
|
||||
LOG_ERR("B GPIO device is not ready");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (gpio_pin_configure(drv_data->a, drv_cfg->a_pin, drv_cfg->a_flags | GPIO_INPUT)) {
|
||||
if (gpio_pin_configure_dt(&drv_cfg->a, GPIO_INPUT)) {
|
||||
LOG_DBG("Failed to configure A pin");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (gpio_pin_configure(drv_data->b, drv_cfg->b_pin, drv_cfg->b_flags | GPIO_INPUT)) {
|
||||
if (gpio_pin_configure_dt(&drv_cfg->b, GPIO_INPUT)) {
|
||||
LOG_DBG("Failed to configure B pin");
|
||||
return -EIO;
|
||||
}
|
||||
@@ -134,12 +130,8 @@ int ec11_init(const struct device *dev) {
|
||||
#define EC11_INST(n) \
|
||||
struct ec11_data ec11_data_##n; \
|
||||
const struct ec11_config ec11_cfg_##n = { \
|
||||
.a_label = DT_INST_GPIO_LABEL(n, a_gpios), \
|
||||
.a_pin = DT_INST_GPIO_PIN(n, a_gpios), \
|
||||
.a_flags = DT_INST_GPIO_FLAGS(n, a_gpios), \
|
||||
.b_label = DT_INST_GPIO_LABEL(n, b_gpios), \
|
||||
.b_pin = DT_INST_GPIO_PIN(n, b_gpios), \
|
||||
.b_flags = DT_INST_GPIO_FLAGS(n, b_gpios), \
|
||||
.a = GPIO_DT_SPEC_INST_GET(n, a_gpios), \
|
||||
.b = GPIO_DT_SPEC_INST_GET(n, b_gpios), \
|
||||
COND_CODE_0(DT_INST_NODE_HAS_PROP(n, resolution), (1), (DT_INST_PROP(n, resolution))), \
|
||||
}; \
|
||||
DEVICE_DT_INST_DEFINE(n, ec11_init, NULL, &ec11_data_##n, &ec11_cfg_##n, POST_KERNEL, \
|
||||
|
||||
@@ -11,20 +11,13 @@
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
struct ec11_config {
|
||||
const char *a_label;
|
||||
const uint8_t a_pin;
|
||||
const uint8_t a_flags;
|
||||
|
||||
const char *b_label;
|
||||
const uint8_t b_pin;
|
||||
const uint8_t b_flags;
|
||||
const struct gpio_dt_spec a;
|
||||
const struct gpio_dt_spec b;
|
||||
|
||||
const uint8_t resolution;
|
||||
};
|
||||
|
||||
struct ec11_data {
|
||||
const struct device *a;
|
||||
const struct device *b;
|
||||
uint8_t ab_state;
|
||||
int8_t pulses;
|
||||
int8_t ticks;
|
||||
|
||||
@@ -20,18 +20,15 @@ extern struct ec11_data ec11_driver;
|
||||
LOG_MODULE_DECLARE(EC11, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static inline void setup_int(const struct device *dev, bool enable) {
|
||||
struct ec11_data *data = dev->data;
|
||||
const struct ec11_config *cfg = dev->config;
|
||||
|
||||
LOG_DBG("enabled %s", (enable ? "true" : "false"));
|
||||
|
||||
if (gpio_pin_interrupt_configure(data->a, cfg->a_pin,
|
||||
enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE)) {
|
||||
if (gpio_pin_interrupt_configure_dt(&cfg->a, enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE)) {
|
||||
LOG_WRN("Unable to set A pin GPIO interrupt");
|
||||
}
|
||||
|
||||
if (gpio_pin_interrupt_configure(data->b, cfg->b_pin,
|
||||
enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE)) {
|
||||
if (gpio_pin_interrupt_configure_dt(&cfg->b, enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE)) {
|
||||
LOG_WRN("Unable to set A pin GPIO interrupt");
|
||||
}
|
||||
}
|
||||
@@ -121,16 +118,16 @@ int ec11_init_interrupt(const struct device *dev) {
|
||||
drv_data->dev = dev;
|
||||
/* setup gpio interrupt */
|
||||
|
||||
gpio_init_callback(&drv_data->a_gpio_cb, ec11_a_gpio_callback, BIT(drv_cfg->a_pin));
|
||||
gpio_init_callback(&drv_data->a_gpio_cb, ec11_a_gpio_callback, BIT(drv_cfg->a.pin));
|
||||
|
||||
if (gpio_add_callback(drv_data->a, &drv_data->a_gpio_cb) < 0) {
|
||||
if (gpio_add_callback(drv_cfg->a.port, &drv_data->a_gpio_cb) < 0) {
|
||||
LOG_DBG("Failed to set A callback!");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
gpio_init_callback(&drv_data->b_gpio_cb, ec11_b_gpio_callback, BIT(drv_cfg->b_pin));
|
||||
gpio_init_callback(&drv_data->b_gpio_cb, ec11_b_gpio_callback, BIT(drv_cfg->b.pin));
|
||||
|
||||
if (gpio_add_callback(drv_data->b, &drv_data->b_gpio_cb) < 0) {
|
||||
if (gpio_add_callback(drv_cfg->b.port, &drv_data->b_gpio_cb) < 0) {
|
||||
LOG_DBG("Failed to set B callback!");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2020 Geanix ApS
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
description: >
|
||||
This is a representation of the Microchip MCP23017 I2C Gpio Expander.
|
||||
|
||||
compatible: "microchip,mcp23017"
|
||||
|
||||
include: [gpio-controller.yaml, i2c-device.yaml]
|
||||
|
||||
properties:
|
||||
label:
|
||||
required: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
ngpios:
|
||||
type: int
|
||||
required: true
|
||||
const: 16
|
||||
description: Number of gpios supported
|
||||
|
||||
gpio-cells:
|
||||
- pin
|
||||
- flags
|
||||
@@ -12,9 +12,6 @@ compatible: "zmk,gpio-595"
|
||||
include: [gpio-controller.yaml, spi-device.yaml]
|
||||
|
||||
properties:
|
||||
label:
|
||||
required: true
|
||||
|
||||
"#gpio-cells":
|
||||
const: 2
|
||||
|
||||
|
||||
@@ -4,8 +4,3 @@
|
||||
description: Battery SoC monitoring using nRF VDDH
|
||||
|
||||
compatible: "zmk,battery-nrf-vddh"
|
||||
|
||||
properties:
|
||||
label:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
@@ -6,8 +6,3 @@ description: Battery SoC monitoring using voltage divider
|
||||
compatible: "zmk,battery-voltage-divider"
|
||||
|
||||
include: voltage-divider.yaml
|
||||
|
||||
properties:
|
||||
label:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
Reference in New Issue
Block a user