drivers: gpio: Add MAX14916 industrial output
Industrial 8 channel output with advanced diagnostics. Allowing giagnostic configuration both on per channel or global bases In SPI communication diagnostic status transmitted on every READ/WRITE which includes generic status of chip. Diagnostics includes : * Oveload * Open Wire * Over current * Short to VDD * Thermal Shutdown * VDD Warn * Watch Dog Error * Communication Error * VDD under voltage Add app.overlay for MAX14916 driver. Tested with adopted basic/blinky example. Signed-off-by: Stoyan Bogdanov <sbogdanov@baylibre.com>
This commit is contained in:
parent
fe8f5d3f6a
commit
3ca5cf50fe
6 changed files with 642 additions and 0 deletions
|
@ -41,6 +41,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_LITEX gpio_litex.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_GPIO_LMP90XXX gpio_lmp90xxx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_LPC11U6X gpio_lpc11u6x.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_MAX14906 gpio_max14906.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_MAX14916 gpio_max14916.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_MAX32 gpio_max32.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_MCHP_MSS gpio_mchp_mss.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_GPIO_MCP230XX gpio_mcp230xx.c)
|
||||
|
|
|
@ -132,6 +132,7 @@ source "drivers/gpio/Kconfig.litex"
|
|||
source "drivers/gpio/Kconfig.lmp90xxx"
|
||||
source "drivers/gpio/Kconfig.lpc11u6x"
|
||||
source "drivers/gpio/Kconfig.max14906"
|
||||
source "drivers/gpio/Kconfig.max14916"
|
||||
source "drivers/gpio/Kconfig.max32"
|
||||
source "drivers/gpio/Kconfig.mchp_mss"
|
||||
source "drivers/gpio/Kconfig.mcp23xxx"
|
||||
|
|
20
drivers/gpio/Kconfig.max14916
Normal file
20
drivers/gpio/Kconfig.max14916
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Copyright (c) 2024 Analog Devices Inc.
|
||||
# Copyright (c) 2024 BayLibre SAS
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# MAX14916 GPIO configuration options
|
||||
|
||||
menuconfig GPIO_MAX14916
|
||||
bool "MAX14916 GPIO driver"
|
||||
default y
|
||||
depends on DT_HAS_ADI_MAX14916_GPIO_ENABLED && SPI
|
||||
help
|
||||
Enabe MAX1416 octal industrial digital
|
||||
output with diagnostics
|
||||
|
||||
config GPIO_MAX14916_INIT_PRIORITY
|
||||
int "Driver init priority"
|
||||
default 99
|
||||
depends on GPIO_MAX14916
|
||||
help
|
||||
Device driver initialization priority.
|
400
drivers/gpio/gpio_max14916.c
Normal file
400
drivers/gpio/gpio_max14916.c
Normal file
|
@ -0,0 +1,400 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Analog Devices Inc.
|
||||
* Copyright (c) 2024 Baylibre SAS
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_REGISTER(gpio_max14916);
|
||||
|
||||
#include <zephyr/drivers/gpio/gpio_utils.h>
|
||||
|
||||
#include "gpio_max14916.h"
|
||||
#include "gpio_max149x6.h"
|
||||
|
||||
#define DT_DRV_COMPAT adi_max14916_gpio
|
||||
|
||||
static int gpio_max14916_diag_chan_get(const struct device *dev);
|
||||
|
||||
static int max14916_pars_spi_diag(const struct device *dev, uint8_t *rx_diag_buff, uint8_t rw)
|
||||
{
|
||||
struct max14916_data *data = dev->data;
|
||||
int ret = 0;
|
||||
|
||||
if (rx_diag_buff[0]) {
|
||||
LOG_ERR("[DIAG] MAX14916 in SPI diag - error detected");
|
||||
|
||||
data->glob.interrupt.reg_bits.SHT_VDD_FLT = MAX149X6_GET_BIT(rx_diag_buff[0], 5);
|
||||
data->glob.interrupt.reg_bits.OW_ON_FLT = MAX149X6_GET_BIT(rx_diag_buff[0], 4);
|
||||
data->glob.interrupt.reg_bits.OW_OFF_FLT = MAX149X6_GET_BIT(rx_diag_buff[0], 3);
|
||||
data->glob.interrupt.reg_bits.CURR_LIM = MAX149X6_GET_BIT(rx_diag_buff[0], 2);
|
||||
data->glob.interrupt.reg_bits.OVER_LD_FLT = MAX149X6_GET_BIT(rx_diag_buff[0], 1);
|
||||
|
||||
if (MAX149X6_GET_BIT(rx_diag_buff[0], 0)) {
|
||||
LOG_ERR("[DIAG] MAX14916 in SPI diag - GLOBAL FAULT detected");
|
||||
}
|
||||
|
||||
ret = -EIO;
|
||||
|
||||
PRINT_ERR(data->glob.interrupt.reg_bits.SHT_VDD_FLT);
|
||||
PRINT_ERR(data->glob.interrupt.reg_bits.OW_ON_FLT);
|
||||
PRINT_ERR(data->glob.interrupt.reg_bits.OW_OFF_FLT);
|
||||
PRINT_ERR(data->glob.interrupt.reg_bits.CURR_LIM);
|
||||
PRINT_ERR(data->glob.interrupt.reg_bits.OVER_LD_FLT);
|
||||
}
|
||||
|
||||
if (rw == MAX149x6_WRITE && (rx_diag_buff[1] & 0x0f)) {
|
||||
/* +-----------------------------------------------------------------------+
|
||||
* | LSB BYTE 2 MSB |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
* | Fault1 | Fault2 | Fault3 | Fault4 | Fault5 | Fault6 | Fault7 | Fault8 |
|
||||
* +--------+--------+--------+--------+--------+--------+--------+--------+
|
||||
*/
|
||||
|
||||
LOG_ERR("[DIAG] Flt1[%x] Flt2[%x] Flt3[%x]"
|
||||
"Flt4[%x] Flt5[%x] Flt6[%x] Flt7[%x] Flt8[%x]\n",
|
||||
MAX149X6_GET_BIT(rx_diag_buff[1], 0), MAX149X6_GET_BIT(rx_diag_buff[1], 1),
|
||||
MAX149X6_GET_BIT(rx_diag_buff[1], 2), MAX149X6_GET_BIT(rx_diag_buff[1], 3),
|
||||
MAX149X6_GET_BIT(rx_diag_buff[1], 4), MAX149X6_GET_BIT(rx_diag_buff[1], 5),
|
||||
MAX149X6_GET_BIT(rx_diag_buff[1], 6), MAX149X6_GET_BIT(rx_diag_buff[1], 7));
|
||||
|
||||
if (rx_diag_buff[1]) {
|
||||
LOG_ERR("[DIAG] gpio_max14916_diag_chan_get(%x)\n", rx_diag_buff[1] & 0x0f);
|
||||
ret = gpio_max14916_diag_chan_get(dev);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int max14916_reg_trans_spi_diag(const struct device *dev, uint8_t addr, uint8_t tx,
|
||||
uint8_t rw)
|
||||
{
|
||||
const struct max14916_config *config = dev->config;
|
||||
uint8_t rx_diag_buff[2];
|
||||
|
||||
if (!gpio_pin_get_dt(&config->fault_gpio)) {
|
||||
LOG_ERR(" >>> FLT PIN");
|
||||
}
|
||||
|
||||
uint8_t ret = max149x6_reg_transceive(dev, addr, tx, rx_diag_buff, rw);
|
||||
|
||||
if (max14916_pars_spi_diag(dev, rx_diag_buff, rw)) {
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define MAX14916_REG_READ(dev, addr) max14916_reg_trans_spi_diag(dev, addr, 0, MAX149x6_READ)
|
||||
#define MAX14916_REG_WRITE(dev, addr, val) \
|
||||
max14916_reg_trans_spi_diag(dev, addr, val, MAX149x6_WRITE)
|
||||
|
||||
static int gpio_max14916_diag_chan_get(const struct device *dev)
|
||||
{
|
||||
const struct max14916_config *config = dev->config;
|
||||
struct max14916_data *data = dev->data;
|
||||
int ret = 0;
|
||||
|
||||
if (!gpio_pin_get_dt(&config->fault_gpio)) {
|
||||
LOG_ERR("FLT flag is rised");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
data->glob.interrupt.reg_raw =
|
||||
max149x6_reg_transceive(dev, MAX14916_INT_REG, 0, NULL, MAX149x6_READ);
|
||||
|
||||
if (data->glob.interrupt.reg_raw) {
|
||||
if (data->glob.interrupt.reg_bits.OVER_LD_FLT) {
|
||||
data->chan.ovr_ld = max149x6_reg_transceive(dev, MAX14916_OVR_LD_REG, 0,
|
||||
NULL, MAX149x6_READ);
|
||||
}
|
||||
if (data->glob.interrupt.reg_bits.CURR_LIM) {
|
||||
data->chan.curr_lim = max149x6_reg_transceive(dev, MAX14916_CURR_LIM_REG, 0,
|
||||
NULL, MAX149x6_READ);
|
||||
}
|
||||
if (data->glob.interrupt.reg_bits.OW_OFF_FLT) {
|
||||
data->chan.ow_off = max149x6_reg_transceive(dev, MAX14916_OW_OFF_FLT_REG, 0,
|
||||
NULL, MAX149x6_READ);
|
||||
}
|
||||
if (data->glob.interrupt.reg_bits.OW_ON_FLT) {
|
||||
data->chan.ow_on = max149x6_reg_transceive(dev, MAX14916_OW_ON_FLT_REG, 0,
|
||||
NULL, MAX149x6_READ);
|
||||
}
|
||||
if (data->glob.interrupt.reg_bits.SHT_VDD_FLT) {
|
||||
data->chan.sht_vdd = max149x6_reg_transceive(dev, MAX14916_SHT_VDD_FLT_REG,
|
||||
0, NULL, MAX149x6_READ);
|
||||
}
|
||||
|
||||
if (data->glob.interrupt.reg_bits.SUPPLY_ERR) {
|
||||
data->glob.glob_err.reg_raw = max149x6_reg_transceive(
|
||||
dev, MAX14916_GLOB_ERR_REG, 0, NULL, MAX149x6_READ);
|
||||
PRINT_ERR(data->glob.glob_err.reg_bits.VINT_UV);
|
||||
PRINT_ERR(data->glob.glob_err.reg_bits.VA_UVLO);
|
||||
PRINT_ERR(data->glob.glob_err.reg_bits.VDD_BAD);
|
||||
PRINT_ERR(data->glob.glob_err.reg_bits.VDD_WARN);
|
||||
PRINT_ERR(data->glob.glob_err.reg_bits.VDD_UVLO);
|
||||
PRINT_ERR(data->glob.glob_err.reg_bits.THRMSHUTD);
|
||||
PRINT_ERR(data->glob.glob_err.reg_bits.SYNC_ERR);
|
||||
PRINT_ERR(data->glob.glob_err.reg_bits.WDOG_ERR);
|
||||
}
|
||||
|
||||
if (data->glob.interrupt.reg_bits.COM_ERR) {
|
||||
LOG_ERR("MAX14916 Communication Error");
|
||||
}
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gpio_max14916_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
|
||||
{
|
||||
int ret;
|
||||
uint32_t reg_val = 0;
|
||||
|
||||
ret = MAX14916_REG_READ(dev, MAX14916_SETOUT_REG);
|
||||
reg_val = ret | pins;
|
||||
|
||||
return MAX14916_REG_WRITE(dev, MAX14916_SETOUT_REG, reg_val);
|
||||
}
|
||||
|
||||
static int gpio_max14916_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
|
||||
{
|
||||
int ret;
|
||||
uint32_t reg_val = 0;
|
||||
|
||||
ret = MAX14916_REG_READ(dev, MAX14916_SETOUT_REG);
|
||||
reg_val = ret & ~pins;
|
||||
|
||||
return MAX14916_REG_WRITE(dev, MAX14916_SETOUT_REG, reg_val);
|
||||
}
|
||||
|
||||
static int gpio_max14916_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == GPIO_DISCONNECTED) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if ((flags & GPIO_SINGLE_ENDED) != 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
if (flags & GPIO_INT_ENABLE) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
switch (flags & GPIO_DIR_MASK) {
|
||||
case GPIO_OUTPUT:
|
||||
break;
|
||||
case GPIO_INPUT:
|
||||
default:
|
||||
LOG_ERR("NOT SUPPORTED OPTION!");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int gpio_max14916_port_get_raw(const struct device *dev, gpio_port_value_t *value)
|
||||
{
|
||||
*value = MAX14916_REG_READ(dev, MAX14916_SETOUT_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_max14916_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
|
||||
{
|
||||
int ret;
|
||||
uint32_t reg_val = 0;
|
||||
|
||||
ret = MAX14916_REG_READ(dev, MAX14916_SETOUT_REG);
|
||||
|
||||
reg_val = ret;
|
||||
reg_val ^= pins;
|
||||
|
||||
MAX14916_REG_WRITE(dev, MAX14916_SETOUT_REG, reg_val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_max14916_clean_on_power(const struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Clear the latched faults generated at power up */
|
||||
ret = MAX14916_REG_READ(dev, MAX14916_OW_OFF_FLT_REG);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Error reading MAX14916_OW_OFF_FLT_REG");
|
||||
goto err_clean_on_power_max14916;
|
||||
}
|
||||
|
||||
ret = MAX14916_REG_READ(dev, MAX14916_OVR_LD_REG);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Error reading MAX14916_OVR_LD_REG");
|
||||
goto err_clean_on_power_max14916;
|
||||
}
|
||||
|
||||
ret = MAX14916_REG_READ(dev, MAX14916_SHT_VDD_FLT_REG);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Error reading MAX14916_SHD_VDD_FLT_REG");
|
||||
goto err_clean_on_power_max14916;
|
||||
}
|
||||
|
||||
ret = MAX14916_REG_READ(dev, MAX14916_GLOB_ERR_REG);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Error reading MAX14916_GLOBAL_FLT_REG");
|
||||
goto err_clean_on_power_max14916;
|
||||
}
|
||||
|
||||
err_clean_on_power_max14916:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int gpio_max14916_config_diag(const struct device *dev)
|
||||
{
|
||||
const struct max14916_config *config = dev->config;
|
||||
struct max14916_data *data = dev->data;
|
||||
|
||||
MAX14916_REG_WRITE(dev, MAX14916_CONFIG1_REG, config->config1.reg_raw);
|
||||
MAX14916_REG_WRITE(dev, MAX14916_CONFIG2_REG, config->config2.reg_raw);
|
||||
MAX14916_REG_WRITE(dev, MAX14916_OW_OFF_EN_REG, data->chan_en.ow_on_en);
|
||||
MAX14916_REG_WRITE(dev, MAX14916_OW_OFF_EN_REG, data->chan_en.ow_off_en);
|
||||
MAX14916_REG_WRITE(dev, MAX14916_SHT_VDD_EN_REG, data->chan_en.sht_vdd_en);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_max14916_init(const struct device *dev)
|
||||
{
|
||||
const struct max14916_config *config = dev->config;
|
||||
int err = 0;
|
||||
|
||||
LOG_DBG(" --- GPIO MAX14916 init IN ---");
|
||||
|
||||
if (!spi_is_ready_dt(&config->spi)) {
|
||||
LOG_ERR("SPI bus is not ready\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* setup READY gpio - normal low */
|
||||
if (!gpio_is_ready_dt(&config->ready_gpio)) {
|
||||
LOG_ERR("READY GPIO device not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
err = gpio_pin_configure_dt(&config->ready_gpio, GPIO_INPUT);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to configure reset GPIO");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* setup FLT gpio - normal high */
|
||||
if (!gpio_is_ready_dt(&config->fault_gpio)) {
|
||||
LOG_ERR("FLT GPIO device not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
err = gpio_pin_configure_dt(&config->fault_gpio, GPIO_INPUT);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to configure DC GPIO");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* setup LATCH gpio - normal high */
|
||||
if (!gpio_is_ready_dt(&config->sync_gpio)) {
|
||||
LOG_ERR("SYNC GPIO device not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
err = gpio_pin_configure_dt(&config->sync_gpio, GPIO_OUTPUT_INACTIVE);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to configure busy GPIO");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* setup LATCH gpio - normal high */
|
||||
if (!gpio_is_ready_dt(&config->en_gpio)) {
|
||||
LOG_ERR("SYNC GPIO device not ready");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
err = gpio_pin_configure_dt(&config->en_gpio, GPIO_OUTPUT_INACTIVE);
|
||||
if (err < 0) {
|
||||
LOG_ERR("Failed to configure busy GPIO");
|
||||
return err;
|
||||
}
|
||||
|
||||
gpio_pin_set_dt(&config->en_gpio, 1);
|
||||
gpio_pin_set_dt(&config->sync_gpio, 1);
|
||||
|
||||
LOG_ERR("[GPIO] FALUT - %d\n", gpio_pin_get_dt(&config->fault_gpio));
|
||||
LOG_ERR("[GPIO] READY - %d\n", gpio_pin_get_dt(&config->ready_gpio));
|
||||
LOG_ERR("[GPIO] SYNC - %d\n", gpio_pin_get_dt(&config->sync_gpio));
|
||||
LOG_ERR("[GPIO] EN - %d\n", gpio_pin_get_dt(&config->en_gpio));
|
||||
|
||||
int ret = gpio_max14916_clean_on_power(dev);
|
||||
|
||||
MAX14916_REG_WRITE(dev, MAX14916_SETOUT_REG, 0);
|
||||
|
||||
gpio_max14916_config_diag(dev);
|
||||
|
||||
LOG_DBG(" --- GPIO MAX14916 init OUT ---");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct gpio_driver_api gpio_max14916_api = {
|
||||
.pin_configure = gpio_max14916_config,
|
||||
.port_get_raw = gpio_max14916_port_get_raw,
|
||||
.port_set_bits_raw = gpio_max14916_port_set_bits_raw,
|
||||
.port_clear_bits_raw = gpio_max14916_port_clear_bits_raw,
|
||||
.port_toggle_bits = gpio_max14916_port_toggle_bits,
|
||||
};
|
||||
|
||||
#define GPIO_MAX14906_DEVICE(id) \
|
||||
static const struct max14916_config max14916_##id##_cfg = { \
|
||||
.spi = SPI_DT_SPEC_INST_GET(id, SPI_OP_MODE_MASTER | SPI_WORD_SET(8U), 0U), \
|
||||
.ready_gpio = GPIO_DT_SPEC_INST_GET(id, drdy_gpios), \
|
||||
.fault_gpio = GPIO_DT_SPEC_INST_GET(id, fault_gpios), \
|
||||
.sync_gpio = GPIO_DT_SPEC_INST_GET(id, sync_gpios), \
|
||||
.en_gpio = GPIO_DT_SPEC_INST_GET(id, en_gpios), \
|
||||
.crc_en = DT_INST_PROP(id, crc_en), \
|
||||
.config1.reg_bits.FLED_SET = DT_INST_PROP(id, fled_set), \
|
||||
.config1.reg_bits.SLED_SET = DT_INST_PROP(id, sled_set), \
|
||||
.config1.reg_bits.FLED_STRETCH = DT_INST_PROP(id, fled_stretch), \
|
||||
.config1.reg_bits.FFILTER_EN = DT_INST_PROP(id, ffilter_en), \
|
||||
.config1.reg_bits.FILTER_LONG = DT_INST_PROP(id, filter_long), \
|
||||
.config1.reg_bits.FLATCH_EN = DT_INST_PROP(id, flatch_en), \
|
||||
.config1.reg_bits.LED_CURR_LIM = DT_INST_PROP(id, led_cur_lim), \
|
||||
.config2.reg_bits.VDD_ON_THR = DT_INST_PROP(id, vdd_on_thr), \
|
||||
.config2.reg_bits.SYNCH_WD_EN = DT_INST_PROP(id, synch_wd_en), \
|
||||
.config2.reg_bits.SHT_VDD_THR = DT_INST_PROP(id, sht_vdd_thr), \
|
||||
.config2.reg_bits.OW_OFF_CS = DT_INST_PROP(id, ow_off_cs), \
|
||||
.config2.reg_bits.WD_TO = DT_INST_PROP(id, wd_to), \
|
||||
.pkt_size = (DT_INST_PROP(id, crc_en) & 0x1) ? 3 : 2, \
|
||||
.spi_addr = DT_INST_PROP(id, spi_addr), \
|
||||
}; \
|
||||
\
|
||||
static struct max14916_data max14916_##id##_data; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(id, &gpio_max14916_init, NULL, &max14916_##id##_data, \
|
||||
&max14916_##id##_cfg, POST_KERNEL, \
|
||||
CONFIG_GPIO_MAX14916_INIT_PRIORITY, &gpio_max14916_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(GPIO_MAX14906_DEVICE)
|
200
drivers/gpio/gpio_max14916.h
Normal file
200
drivers/gpio/gpio_max14916.h
Normal file
|
@ -0,0 +1,200 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Analog Devices Inc.
|
||||
* Copyright (c) 2024 Baylibre SAS
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_GPIO_GPIO_MAX14916_H_
|
||||
#define ZEPHYR_DRIVERS_GPIO_GPIO_MAX14916_H_
|
||||
|
||||
#define MAX14906_ENABLE 1
|
||||
#define MAX14906_DISABLE 0
|
||||
|
||||
#define MAX149x6_MAX_PKT_SIZE 3
|
||||
|
||||
#define MAX14916_CHANNELS 8
|
||||
|
||||
#define MAX14916_SETOUT_REG 0x0
|
||||
#define MAX14916_SET_FLED_REG 0x1
|
||||
#define MAX14916_SET_SLED_REG 0x2
|
||||
#define MAX14916_INT_REG 0x3
|
||||
#define MAX14916_OVR_LD_REG 0x4
|
||||
#define MAX14916_CURR_LIM_REG 0x5
|
||||
#define MAX14916_OW_OFF_FLT_REG 0x6
|
||||
#define MAX14916_OW_ON_FLT_REG 0x7
|
||||
#define MAX14916_SHT_VDD_FLT_REG 0x8
|
||||
#define MAX14916_GLOB_ERR_REG 0x9
|
||||
#define MAX14916_OW_OFF_EN_REG 0xA
|
||||
#define MAX14916_OW_ON_EN_REG 0xB
|
||||
#define MAX14916_SHT_VDD_EN_REG 0xC
|
||||
#define MAX14916_CONFIG1_REG 0xD
|
||||
#define MAX14916_CONFIG2_REG 0xE
|
||||
#define MAX14916_CONFIG_MASK 0xF
|
||||
|
||||
#define MAX149x6_CHIP_ADDR_MASK GENMASK(7, 6)
|
||||
#define MAX149x6_ADDR_MASK GENMASK(4, 1)
|
||||
#define MAX149x6_RW_MASK BIT(0)
|
||||
|
||||
/* DoiLevel register */
|
||||
#define MAX149x6_DOI_LEVEL_MASK(x) BIT(x)
|
||||
|
||||
/* SetOUT register */
|
||||
#define MAX14906_HIGHO_MASK(x) BIT(x)
|
||||
|
||||
#define MAX14906_DO_MASK(x) (GENMASK(1, 0) << (2 * (x)))
|
||||
#define MAX14906_CH_DIR_MASK(x) BIT((x) + 4)
|
||||
#define MAX14906_CH(x) (x)
|
||||
#define MAX14906_IEC_TYPE_MASK BIT(7)
|
||||
#define MAX14906_CL_MASK(x) (GENMASK(1, 0) << (2 * (x)))
|
||||
|
||||
/* Config1 register */
|
||||
#define MAX14906_SLED_MASK BIT(1)
|
||||
#define MAX14906_FLED_MASK BIT(0)
|
||||
|
||||
#define MAX14906_CHAN_MASK_LSB(x) BIT(x)
|
||||
#define MAX14906_CHAN_MASK_MSB(x) BIT((x) + 4)
|
||||
|
||||
enum max149x6_spi_addr {
|
||||
MAX14906_ADDR_0, /* A0=0, A1=0 */
|
||||
MAX14906_ADDR_1, /* A0=1, A1=0 */
|
||||
MAX14906_ADDR_2, /* A0=0, A1=1 */
|
||||
MAX14906_ADDR_3, /* A0=1, A1=1 */
|
||||
};
|
||||
|
||||
enum max14916_fled_time {
|
||||
MAX14916_FLED_TIME_DISABLED,
|
||||
MAX14916_FLED_TIME_1S,
|
||||
MAX14916_FLED_TIME_2S,
|
||||
MAX14916_FLED_TIME_3S
|
||||
};
|
||||
|
||||
enum max14916_sled_state {
|
||||
MAX14916_SLED_OFF,
|
||||
MAX14916_SLED_ON
|
||||
};
|
||||
|
||||
enum max14916_wd {
|
||||
MAX14916_WD_DISABLED,
|
||||
MAX14916_WD_200MS,
|
||||
MAX14916_WD_600MS,
|
||||
MAX14916_WD_1200MS
|
||||
};
|
||||
|
||||
enum max14916_ow_off_cs {
|
||||
MAX14916_OW_OFF_CS_20UA,
|
||||
MAX14916_OW_OFF_CS_100UA,
|
||||
MAX14916_OW_OFF_CS_300UA,
|
||||
MAX14916_OW_OFF_CS_600UA
|
||||
};
|
||||
|
||||
enum max14916_sht_vdd_thr {
|
||||
MAX14916_SHT_VDD_THR_9V,
|
||||
MAX14916_SHT_VDD_THR_10V,
|
||||
MAX14916_SHT_VDD_THR_12V,
|
||||
MAX14916_SHT_VDD_THR_14V
|
||||
};
|
||||
|
||||
union max14916_interrupt {
|
||||
uint8_t reg_raw;
|
||||
struct {
|
||||
uint8_t OVER_LD_FLT: 1; /* BIT0 */
|
||||
uint8_t CURR_LIM: 1;
|
||||
uint8_t OW_OFF_FLT: 1;
|
||||
uint8_t OW_ON_FLT: 1;
|
||||
uint8_t SHT_VDD_FLT: 1;
|
||||
uint8_t DE_MAG_FLT: 1;
|
||||
uint8_t SUPPLY_ERR: 1;
|
||||
uint8_t COM_ERR: 1; /* BIT7 */
|
||||
} reg_bits;
|
||||
};
|
||||
|
||||
union max14916_config1 {
|
||||
uint8_t reg_raw;
|
||||
struct {
|
||||
uint8_t FLED_SET: 1; /* BIT0 */
|
||||
uint8_t SLED_SET: 1;
|
||||
uint8_t FLED_STRETCH: 2;
|
||||
uint8_t FFILTER_EN: 1;
|
||||
uint8_t FILTER_LONG: 1;
|
||||
uint8_t FLATCH_EN: 1;
|
||||
uint8_t LED_CURR_LIM: 1; /* BIT7 */
|
||||
} reg_bits;
|
||||
};
|
||||
|
||||
union max14916_config2 {
|
||||
uint8_t reg_raw;
|
||||
struct {
|
||||
uint8_t VDD_ON_THR: 1; /* BIT0 */
|
||||
uint8_t SYNCH_WD_EN: 1;
|
||||
uint8_t SHT_VDD_THR: 2;
|
||||
uint8_t OW_OFF_CS: 2;
|
||||
uint8_t WD_TO: 2; /* BIT7 */
|
||||
} reg_bits;
|
||||
};
|
||||
|
||||
union max14916_mask {
|
||||
uint8_t reg_raw;
|
||||
struct {
|
||||
uint8_t OVER_LD_M: 1; /* BIT0 */
|
||||
uint8_t CURR_LIM_M: 1;
|
||||
uint8_t OW_OFF_M: 1;
|
||||
uint8_t OW_ON_M: 1;
|
||||
uint8_t SHT_VDD_M: 1;
|
||||
uint8_t VDD_OK_M: 1;
|
||||
uint8_t SUPPLY_ERR_M: 1;
|
||||
uint8_t COM_ERR_M: 1; /* BIT7 */
|
||||
} reg_bits;
|
||||
};
|
||||
|
||||
union max14916_global_err {
|
||||
uint8_t reg_raw;
|
||||
struct {
|
||||
uint8_t VINT_UV: 1; /* BIT0 */
|
||||
uint8_t VA_UVLO: 1;
|
||||
uint8_t VDD_BAD: 1;
|
||||
uint8_t VDD_WARN: 1;
|
||||
uint8_t VDD_UVLO: 1;
|
||||
uint8_t THRMSHUTD: 1;
|
||||
uint8_t SYNC_ERR: 1;
|
||||
uint8_t WDOG_ERR: 1; /* BIT7 */
|
||||
} reg_bits;
|
||||
};
|
||||
|
||||
struct max149x6_config {
|
||||
struct spi_dt_spec spi;
|
||||
struct gpio_dt_spec fault_gpio;
|
||||
struct gpio_dt_spec ready_gpio;
|
||||
struct gpio_dt_spec sync_gpio;
|
||||
struct gpio_dt_spec en_gpio;
|
||||
bool crc_en;
|
||||
union max14916_config1 config1;
|
||||
union max14916_config2 config2;
|
||||
enum max149x6_spi_addr spi_addr;
|
||||
uint8_t pkt_size;
|
||||
};
|
||||
|
||||
#define max14916_config max149x6_config
|
||||
|
||||
struct max14916_data {
|
||||
struct gpio_driver_data common;
|
||||
struct {
|
||||
uint8_t ovr_ld;
|
||||
uint8_t curr_lim;
|
||||
uint8_t ow_off;
|
||||
uint8_t ow_on;
|
||||
uint8_t sht_vdd;
|
||||
} chan;
|
||||
struct {
|
||||
uint8_t ow_off_en;
|
||||
uint8_t ow_on_en;
|
||||
uint8_t sht_vdd_en;
|
||||
} chan_en;
|
||||
struct {
|
||||
union max14916_interrupt interrupt;
|
||||
union max14916_global_err glob_err;
|
||||
union max14916_mask mask;
|
||||
} glob;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -361,6 +361,7 @@
|
|||
&test_gpio 0 0
|
||||
&test_gpio 0 0
|
||||
&test_gpio 0 0
|
||||
&test_gpio 0 0
|
||||
&test_gpio 0 0>;
|
||||
|
||||
test_spi_mcp23s17: mcp23s17@0 {
|
||||
|
@ -461,6 +462,25 @@
|
|||
sync-gpios = <&test_gpio 0 0>;
|
||||
en-gpios = <&test_gpio 0 0>;
|
||||
};
|
||||
|
||||
test_spi_max14916: max14916@6 {
|
||||
compatible = "adi,max1916-gpio";
|
||||
status = "okay";
|
||||
reg = <0x07>;
|
||||
spi-max-frequency = <0>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
ngpios = <8>;
|
||||
crc-en;
|
||||
spi-addr = <0>;
|
||||
ow-on-en = <0 0 0 0>;
|
||||
ow-off-en = <0 0 0 0>;
|
||||
sh-vdd-en = <0 0 0 0>;
|
||||
drdy-gpios = <&test_gpio 0 0>;
|
||||
fault-gpios = <&test_gpio 0 0>;
|
||||
sync-gpios = <&test_gpio 0 0>;
|
||||
en-gpios = <&test_gpio 0 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue