This is an automated email from the ASF dual-hosted git repository. acassis pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push: new 22110b3b83 ioexpander: add support for iC-JX expander 22110b3b83 is described below commit 22110b3b83e51ee9a5858223a88d038b87ee2c05 Author: Michal Lenc <michall...@seznam.cz> AuthorDate: Tue Jan 23 14:46:08 2024 +0100 ioexpander: add support for iC-JX expander This commit adds basic support for iC-JX expander in SPI mode. The expander is functional and supports both input and output pins. Further expander functionalities (filtering, adc, interrupt support) are not yet implemented. Signed-off-by: Michal Lenc <michall...@seznam.cz> --- drivers/ioexpander/Kconfig | 18 + drivers/ioexpander/Make.defs | 4 + drivers/ioexpander/icjx.c | 750 ++++++++++++++++++++++++++++++++++++++++ drivers/ioexpander/icjx.h | 102 ++++++ include/nuttx/ioexpander/icjx.h | 96 +++++ 5 files changed, 970 insertions(+) diff --git a/drivers/ioexpander/Kconfig b/drivers/ioexpander/Kconfig index 77c9b2eb96..f1f6cb9b25 100644 --- a/drivers/ioexpander/Kconfig +++ b/drivers/ioexpander/Kconfig @@ -56,6 +56,24 @@ config IOEXPANDER_DUMMY_INT_POLLDELAY endif # IOEXPANDER_DUMMY +config IOEXPANDER_ICJX + bool "iC-JX SPI IO expander" + default n + depends on SPI + ---help--- + Enable support for the iC-JX expander from iC-Haus GmbH manufacturer. + SPI peripheral is used for the communication. + +if IOEXPANDER_ICJX + +config iC-JX_MULTIPLE + bool "Multiple iC-JX Devices" + default n + ---help--- + Can be defined to support multiple iC-JX devices on board. + +endif # IOEXPANDER_ICJX + config IOEXPANDER_ISO1H812G bool "ISO1H812G SPI IO expander" default n diff --git a/drivers/ioexpander/Make.defs b/drivers/ioexpander/Make.defs index 2777af4415..cdf0921ccd 100644 --- a/drivers/ioexpander/Make.defs +++ b/drivers/ioexpander/Make.defs @@ -32,6 +32,10 @@ ifeq ($(CONFIG_IOEXPANDER_DUMMY),y) CSRCS += ioe_dummy.c endif +ifeq ($(CONFIG_IOEXPANDER_ICJX),y) + CSRCS += icjx.c +endif + ifeq ($(CONFIG_IOEXPANDER_ISO1H812G),y) CSRCS += iso1h812g.c endif diff --git a/drivers/ioexpander/icjx.c b/drivers/ioexpander/icjx.c new file mode 100644 index 0000000000..bff1975d18 --- /dev/null +++ b/drivers/ioexpander/icjx.c @@ -0,0 +1,750 @@ +/**************************************************************************** + * drivers/ioexpander/icjx.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <assert.h> +#include <errno.h> +#include <debug.h> +#include <sys/param.h> + +#include <nuttx/kmalloc.h> +#include <nuttx/arch.h> +#include <nuttx/spi/spi.h> +#include <nuttx/ioexpander/ioexpander.h> +#include <nuttx/ioexpander/icjx.h> + +#include "icjx.h" + +#ifdef CONFIG_IOEXPANDER_ICJX + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ICJX_NOP 0x00 +#define ICJX_RNW 0x01 +#define ICJX_NOB 0x0f +#define ICJX_CONTROL 0x59 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct icjx_dev_s +{ + struct ioexpander_dev_s dev; /* Nested structure to allow casting + * as public gpio expander. */ + FAR struct icjx_config_s *config; /* Board configuration data */ + FAR struct spi_dev_s *spi; /* Saved SPI driver instance */ + uint16_t outpins; + uint16_t outstate; + mutex_t lock; +}; + +/**************************************************************************** + * Private Function Protototypes + ****************************************************************************/ + +/* SPI helpers */ + +static void icjx_select(FAR struct spi_dev_s *spi, + FAR struct icjx_config_s *config, int bits); +static void icjx_deselect(FAR struct spi_dev_s *spi, + FAR struct icjx_config_s *config); + +/* Read/Write helpers */ + +static int icjx_read(FAR struct icjx_dev_s *priv, uint8_t reg, + uint8_t *data); +static int icjx_write(FAR struct icjx_dev_s *priv, uint8_t reg, + uint8_t data); + +/* I/O Expander Methods */ + +static int icjx_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, + int dir); +static int icjx_option(FAR struct ioexpander_dev_s *dev, uint8_t pin, + int opt, void *regval); +static int icjx_writepin(FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool value); +static int icjx_readpin(FAR struct ioexpander_dev_s *dev, uint8_t pin, + FAR bool *value); +#ifdef CONFIG_IOEXPANDER_MULTIPIN +static int icjx_multiwritepin(FAR struct ioexpander_dev_s *dev, + FAR const uint8_t *pins, FAR bool *values, + int count); +static int icjx_multireadpin(FAR struct ioexpander_dev_s *dev, + FAR const uint8_t *pins, FAR bool *values, + int count); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifndef CONFIG_ICJX_MULTIPLE +/* If only a single device is supported, then the driver state structure may + * as well be pre-allocated. + */ + +static struct icjx_dev_s g_icjx; +#endif + +/* I/O expander vtable */ + +static const struct ioexpander_ops_s g_icjx_ops = +{ + icjx_direction, + icjx_option, + icjx_writepin, + icjx_readpin, + icjx_readpin +#ifdef CONFIG_IOEXPANDER_MULTIPIN + , icjx_multiwritepin + , icjx_multireadpin + , icjx_multireadpin +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: icjx_select + * + * Description: + * Select the SPI, locking and re-configuring if necessary + * + * Input Parameters: + * spi - Reference to the SPI driver structure + * config - Reference to iC-JX configuration structure + * bits - Number of SPI bits + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void icjx_select(FAR struct spi_dev_s *spi, + FAR struct icjx_config_s *config, int bits) +{ + /* Select iC-JX chip (locking the SPI bus in case there are multiple + * devices competing for the SPI bus + */ + + SPI_LOCK(spi, true); + SPI_SELECT(spi, SPIDEV_EXPANDER(config->id), true); + + /* Now make sure that the SPI bus is configured for the iC-JX (it + * might have gotten configured for a different device while unlocked) + */ + + SPI_SETMODE(spi, config->mode); + SPI_SETBITS(spi, bits); + SPI_SETFREQUENCY(spi, config->frequency); +} + +/**************************************************************************** + * Name: icjx_deselect + * + * Description: + * De-select the SPI + * + * Input Parameters: + * spi - Reference to the SPI driver structure + * config - Reference to iC-JX configuration structure + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void icjx_deselect(FAR struct spi_dev_s *spi, + FAR struct icjx_config_s *config) +{ + /* De-select iC-JX chip and relinquish the SPI bus. */ + + SPI_SELECT(spi, SPIDEV_EXPANDER(config->id), false); + SPI_LOCK(spi, false); +} + +/**************************************************************************** + * Name: icjx_read + * + * Description: + * Helper function for register read operation. + * + * Input Parameters: + * priv - Pointer to icjx_dev_s structure + * reg - Register offset (see icjx.h) + * data - Pointer to read data + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +static int icjx_read(FAR struct icjx_dev_s *priv, uint8_t reg, uint8_t *data) +{ + uint8_t startaddr; + uint8_t tx_buffer[5]; + uint8_t rx_buffer[5]; + + startaddr = (priv->config->addr << 6) | (reg << 1) | ICJX_RNW; + tx_buffer[0] = startaddr; + tx_buffer[1] = ICJX_NOP; + tx_buffer[2] = ICJX_NOB; + + icjx_select(priv->spi, priv->config, 8); + SPI_EXCHANGE(priv->spi, tx_buffer, rx_buffer, 3); + + *data = rx_buffer[2]; + + if (priv->config->verification) + { + tx_buffer[0] = rx_buffer[2]; + tx_buffer[1] = ICJX_CONTROL; + SPI_EXCHANGE(priv->spi, tx_buffer, rx_buffer, 2); + } + + icjx_deselect(priv->spi, priv->config); + + if (priv->config->verification) + { + if (rx_buffer[0] != startaddr) + { + gpioerr("ERROR: Data verification error for register 0x%x!\n", + reg); + return -EIO; + } + + if (rx_buffer[1] != ICJX_CONTROL) + { + gpioerr("ERROR: Control byte verification error for register" + "0x%x!\n", reg); + return -EIO; + } + } + + return OK; +} + +/**************************************************************************** + * Name: icjx_write + * + * Description: + * Helper function for register write operation. + * + * Input Parameters: + * priv - Pointer to icjx_dev_s structure + * reg - Register offset (see icjx.h) + * data - Data to be written + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +static int icjx_write(FAR struct icjx_dev_s *priv, uint8_t reg, uint8_t data) +{ + uint8_t startaddr; + uint8_t bytes_to_exchange; + uint8_t tx_buffer[5]; + uint8_t rx_buffer[5]; + + bytes_to_exchange = 3; + startaddr = (priv->config->addr << 6) | (reg << 1); + tx_buffer[0] = startaddr; + tx_buffer[1] = ICJX_NOB; + tx_buffer[2] = data; + + if (priv->config->verification) + { + tx_buffer[3] = startaddr; + tx_buffer[4] = ICJX_CONTROL; + bytes_to_exchange = 5; + } + + icjx_select(priv->spi, priv->config, 8); + SPI_EXCHANGE(priv->spi, tx_buffer, rx_buffer, bytes_to_exchange); + icjx_deselect(priv->spi, priv->config); + + if (priv->config->verification) + { + if (rx_buffer[2] != ICJX_NOB) + { + gpioerr("ERROR: Start address verification error for register" + "0x%x!\n", reg); + return -EIO; + } + + if (rx_buffer[3] != data) + { + gpioerr("ERROR: Data verification error for register 0x%x!\n", + reg); + return -EIO; + } + + if (rx_buffer[4] != ICJX_CONTROL) + { + gpioerr("ERROR: Data verification error for register 0x%x!\n", + reg); + return -EIO; + } + } + + return OK; +} + +/**************************************************************************** + * Name: icjx_direction + * + * Description: + * iC-JX is only input pin. However interface is provided in order + * to avoid system falls if called. + * + * Input Parameters: + * dev - Device-specific state data + * pin - The index of the pin to alter in this call + * dir - One of the IOEXPANDER_DIRECTION_ macros + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +static int icjx_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin, + int dir) +{ + FAR struct icjx_dev_s *priv = (FAR struct icjx_dev_s *)dev; + uint8_t outpins; + uint8_t out_set; + uint8_t regaddr; + int ret; + + if (dir != IOEXPANDER_DIRECTION_IN && + dir != IOEXPANDER_DIRECTION_OUT) + { + return -EINVAL; + } + + DEBUGASSERT(priv != NULL && priv->config != NULL && pin < 16); + + ret = nxmutex_lock(&priv->lock); + if (ret < 0) + { + return ret; + } + + if (dir == IOEXPANDER_DIRECTION_OUT) + { + priv->outpins |= (1 << pin); + } + else + { + priv->outpins &= ~(1 << pin); + } + + if (pin < 8) + { + regaddr = ICJX_CTRL_WORD_2_A; + outpins = priv->outpins & 0xff; + } + else + { + regaddr = ICJX_CTRL_WORD_2_B; + outpins = (priv->outpins >> 8) & 0xff; + } + + ret = icjx_read(priv, regaddr, &out_set); + if (ret < 0) + { + nxmutex_unlock(&priv->lock); + return ret; + } + + /* Enable output generation */ + + if ((outpins & 0xf) != 0) + { + out_set |= ICJX_CTRL_WORD_2_NIOL; + } + else + { + out_set &= ~ICJX_CTRL_WORD_2_NIOL; + } + + if ((outpins & 0xf0) != 0) + { + out_set |= ICJX_CTRL_WORD_2_NIOH; + } + else + { + out_set &= ~ICJX_CTRL_WORD_2_NIOH; + } + + ret = icjx_write(priv, regaddr, out_set); + nxmutex_unlock(&priv->lock); + + return ret; +} + +/**************************************************************************** + * Name: icjx_option + * + * Description: + * Set pin options. Required. + * Since all IO expanders have various pin options, this API allows setting + * pin options in a flexible way. + * + * Input Parameters: + * dev - Device-specific state data + * pin - The index of the pin to alter in this call + * opt - One of the IOEXPANDER_OPTION_ macros + * value - The option's value + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +static int icjx_option(FAR struct ioexpander_dev_s *dev, uint8_t pin, + int opt, FAR void *value) +{ + /* TODO: Implementation of iC-JX options should be here. This includes + * setup of filters, ADC, interrupts etc. The right way to implement + * this would probably be to introduce config structure to + * include/nuttx/ioexpanders/icjx.h that the user could use for the + * nibbles configuration. + */ + + gpiowarn("ERROR: iC-JX options are not yet implemted!\n"); + + return -ENOTSUP; +} + +/**************************************************************************** + * Name: icjx_writepin + * + * Description: + * Set the pin level. Required. + * + * Input Parameters: + * dev - Device-specific state data + * pin - The index of the pin to alter in this call + * value - The pin level. Usually TRUE will set the pin high, + * except if OPTION_INVERT has been set on this pin. + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +static int icjx_writepin(FAR struct ioexpander_dev_s *dev, uint8_t pin, + bool value) +{ + FAR struct icjx_dev_s *priv = (FAR struct icjx_dev_s *)dev; + uint8_t outstate; + uint8_t regaddr; + int ret; + + if (pin > 16) + { + return -ENXIO; + } + + DEBUGASSERT(priv != NULL && priv->config != NULL); + + gpioinfo("Expander id=%02x, pin=%u\n", priv->config->id, pin); + + /* Get exclusive access to the I/O Expander */ + + ret = nxmutex_lock(&priv->lock); + if (ret < 0) + { + return ret; + } + + if ((priv->outpins & (1 << pin)) == 0) + { + gpioerr("ERROR: pin%u is an input\n", pin); + nxmutex_unlock(&priv->lock); + return -EINVAL; + } + + /* Set/clear a bit in outstate. */ + + if (value) + { + priv->outstate |= (1 << pin); + } + else + { + priv->outstate &= ~(1 << pin); + } + + if (pin < 8) + { + regaddr = ICJX_OUTPUT_A; + outstate = priv->outstate & 0xff; + } + else + { + regaddr = ICJX_OUTPUT_B; + outstate = (priv->outstate >> 8) & 0xff; + } + + ret = icjx_write(priv, regaddr, outstate); + nxmutex_unlock(&priv->lock); + + return ret; +} + +/**************************************************************************** + * Name: icjx_readpin + * + * Description: + * Read the actual PIN level. This can be different from the last value + * written to this pin. Required. + * + * Input Parameters: + * dev - Device-specific state data + * pin - The index of the pin + * value - Pointer to a buffer where the pin level is stored. Usually + * TRUE if the pin is high, except if OPTION_INVERT has been + * set this pin. + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +static int icjx_readpin(FAR struct ioexpander_dev_s *dev, uint8_t pin, + FAR bool *value) +{ + FAR struct icjx_dev_s *priv = (FAR struct icjx_dev_s *)dev; + uint8_t regaddr; + uint8_t data; + int ret; + + if (pin > 16) + { + return -ENXIO; + } + + DEBUGASSERT(priv != NULL && priv->config != NULL && value != NULL); + + gpioinfo("Expander addr=%02x, pin=%u\n", priv->config->addr, pin); + + /* Get exclusive access to the I/O Expander */ + + ret = nxmutex_lock(&priv->lock); + if (ret < 0) + { + return ret; + } + + /* Make sure that this is an output pin */ + + if ((priv->outpins & (1 << pin)) != 0) + { + *value = ((priv->outstate & (1 << pin)) != 0); + nxmutex_unlock(&priv->lock); + return OK; + } + + regaddr = pin < 8 ? ICJX_INPUT_A : ICJX_INPUT_B; + + ret = icjx_read(priv, regaddr, &data); + nxmutex_unlock(&priv->lock); + if (ret != OK) + { + return ret; + } + + *value = (bool)((data >> (pin & 0xf)) & 1); + return OK; +} + +/**************************************************************************** + * Name: icjx_multiwritepin + * + * Description: + * Set the pin level for multiple pins. This routine may be faster than + * individual pin accesses. Optional. + * + * Input Parameters: + * dev - Device-specific state data + * pins - The list of pin indexes to alter in this call + * values - The list of pin levels. + * count - Number of pins to be written + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +#ifdef CONFIG_IOEXPANDER_MULTIPIN +static int icjx_multiwritepin(FAR struct ioexpander_dev_s *dev, + FAR const uint8_t *pins, + FAR bool *values, int count) +{ + gpiowarn("WARNING: iC-JX does not have implemented support for" + "multiple pin write operation!\n"); + + return -ENOTSUP; +} + +/**************************************************************************** + * Name: icjx_multireadpin + * + * Description: + * Read the actual level for multiple pins. This routine may be faster than + * individual pin accesses. Optional. + * + * Input Parameters: + * dev - Device-specific state data + * pin - The list of pin indexes to read + * values - Pointer to a buffer where the pin levels are stored. + * count - Number of pins to be read + * + * Returned Value: + * 0 on success, else a negative error code + * + ****************************************************************************/ + +static int icjx_multireadpin(FAR struct ioexpander_dev_s *dev, + FAR const uint8_t *pins, FAR bool *values, + int count) +{ + gpiowarn("WARNING: iC-JX does not have implemented support for" + "multiple pin read operation!\n"); + + return -ENOTSUP; +} +#endif /* CONFIG_IOEXPANDER_MULTIPIN */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: icjx_initialize + * + * Description: + * Instantiate and configure the ICJXxx device driver to use the + * provided SPI device instance. + * + * Input Parameters: + * spi - A SPI driver instance + * config - Persistent board configuration data + * + * Returned Value: + * an ioexpander_dev_s instance on success, NULL on failure. + * + ****************************************************************************/ + +FAR struct ioexpander_dev_s *icjx_initialize(FAR struct spi_dev_s *spi, + FAR struct icjx_config_s *config) +{ + FAR struct icjx_dev_s *priv; + uint8_t regval; + int ret; + +#ifdef CONFIG_ICJX_MULTIPLE + /* Allocate the device state structure */ + + priv = kmm_zalloc(sizeof(struct icjx_dev_s)); + if (!priv) + { + gpioerr("ERROR: Failed to allocate driver instance\n"); + return NULL; + } +#else + /* Use the one-and-only I/O Expander driver instance */ + + priv = &g_icjx; +#endif + + /* Initialize the device state structure */ + + priv->dev.ops = &g_icjx_ops; + priv->spi = spi; + priv->config = config; + priv->outpins = 0; + priv->outstate = 0; + + nxmutex_init(&priv->lock); + + /* Set pull up/down based on expander configuration. This is the first + * time we are accessing the expander therefore we do not have to worry + * about reading the register content first. + */ + + regval = (config->current_src << 4) | config->current_src; + + ret = icjx_write(priv, ICJX_CTRL_WORD_2_A, regval); + if (ret < 0) + { + gpioerr("ERROR: Could write to ICJX_CTRL_WORD_2_A: %d!\n", ret); + goto err; + } + + ret = icjx_write(priv, ICJX_CTRL_WORD_2_B, regval); + if (ret < 0) + { + gpioerr("ERROR: Could write to ICJX_CTRL_WORD_2_B: %d!\n", ret); + goto err; + } + + /* Bypass filters as those are not yet supported. */ + + regval = ICJX_CTRL_WORD_1_BYP0 | ICJX_CTRL_WORD_1_BYP1; + ret = icjx_write(priv, ICJX_CTRL_WORD_1_A, regval); + if (ret < 0) + { + gpioerr("ERROR: Could write to ICJX_CTRL_WORD_1_A: %d!\n", ret); + goto err; + } + + ret = icjx_write(priv, ICJX_CTRL_WORD_1_B, regval); + if (ret < 0) + { + gpioerr("ERROR: Could write to ICJX_CTRL_WORD_1_B: %d!\n", ret); + goto err; + } + + return &priv->dev; + +err: + nxmutex_destroy(&priv->lock); +#ifdef CONFIG_ICJX_MULTIPLE + kmm_free(priv); +#endif + return NULL; +} + +#endif /* CONFIG_IOEXPANDER_ICJX */ diff --git a/drivers/ioexpander/icjx.h b/drivers/ioexpander/icjx.h new file mode 100644 index 0000000000..f0a736ce0e --- /dev/null +++ b/drivers/ioexpander/icjx.h @@ -0,0 +1,102 @@ +/**************************************************************************** + * drivers/ioexpander/icjx.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __DRIVERS_IOEXPANDER_ICJX_H +#define __DRIVERS_IOEXPANDER_ICJX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/mutex.h> + +#if defined(CONFIG_IOEXPANDER) && defined(CONFIG_IOEXPANDER_ICJX) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Prerequisites: + * CONFIG_SPI + * SPI support is required + * CONFIG_IOEXPANDER + * Enables I/O expander support + * + * CONFIG_IOEXPANDER_ICJX + * Enables support for the ICJX driver (Needs CONFIG_INPUT) + * CONFIG_ICJX_MULTIPLE + * Can be defined to support multiple ICJX devices on board. + */ + +#ifndef CONFIG_SPI +# error "CONFIG_SPI is required by ICJX" +#endif + +/* iC-JX Registers **********************************************************/ + +#define ICJX_INPUT_A 0x00 +#define ICJX_INPUT_B 0x01 +#define ICJX_CHNG_MSG_A 0x02 +#define ICJX_CNNG_MSG_B 0x03 +#define ICJX_INT_STATUS_A 0x04 +#define ICJX_INT_STATUS_B 0x05 +#define ICJX_OVERCURR_MSG_A 0x06 +#define ICJX_OVERCURR_MSG_B 0x07 +#define ICJX_OVERCURR_STATUS_A 0x08 +#define ICJX_OVERCURR_STATUS_B 0x09 +#define ICJX_ADC_DATA_1 0x0A +#define ICJX_ADC_DATA_2 0x0B +#define ICJX_OUTPUT_A 0x0C +#define ICJX_OUTPUT_B 0x0D +#define ICJX_FLASH_PULSE_A 0x0E +#define ICJX_FLASH_PULSE_B 0x0F +#define ICJX_CHNG_INT_EN_A 0x10 +#define ICJX_CHNG_INT_EN_B 0x11 +#define ICJX_OVERCURR_INT_EN_A 0x12 +#define ICJX_OVERCURR_INT_EN_B 0x13 +#define ICJX_CTRL_WORD_1_A 0x14 +#define ICJX_CTRL_WORD_1_B 0x15 +#define ICJX_CTRL_WORD_2_A 0x16 +#define ICJX_CTRL_WORD_2_B 0x17 +#define ICJX_CTRL_WORD_3_A 0x18 +#define ICJX_CTRL_WORD_3_B 0x19 +#define ICJX_CTRL_WORD_4 0x1A +#define ICJX_CTRL_WORD_5 0x1B +#define ICJX_CTRL_WORD_6 0x1C +#define ICJX_DEV_ID 0x1D +#define ICJX_TEST_1 0x1E +#define ICJX_TEST_2 0x1F + +/* Control Word 1 */ + +#define ICJX_CTRL_WORD_1_BYP0 (1 << 3) +#define ICJX_CTRL_WORD_1_BYP1 (1 << 7) + +/* Control Word 2 */ + +#define ICJX_CTRL_WORD_2_NIOL (1 << 3) +#define ICJX_CTRL_WORD_2_NIOH (1 << 7) + +#endif /* CONFIG_IOEXPANDER && CONFIG_IOEXPANDER_ICJX */ +#endif /* __DRIVERS_IOEXPANDER_ICJX_H */ diff --git a/include/nuttx/ioexpander/icjx.h b/include/nuttx/ioexpander/icjx.h new file mode 100644 index 0000000000..629a048019 --- /dev/null +++ b/include/nuttx/ioexpander/icjx.h @@ -0,0 +1,96 @@ +/**************************************************************************** + * include/nuttx/ioexpander/icjx.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __INCLUDE_NUTTX_IOEXPANDER_ICJX_H +#define __INCLUDE_NUTTX_IOEXPANDER_ICJX_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> +#include <stdint.h> + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define ICJX_CTRL_WORD_CURR_SRC_DIS 0 /* Pin current source disabled */ +#define ICJX_CTRL_WORD_PULLDOWN_200U 1 /* 200 uA pull down */ +#define ICJX_CTRL_WORD_PULLDOWN_600U 2 /* 600 uA pull down */ +#define ICJX_CTRL_WORD_PULLDOWN_2M 3 /* 2 mA pull down */ +#define ICJX_CTRL_WORD_PULLUP_200U 5 /* 200 uA pull up */ +#define ICJX_CTRL_WORD_PULLUP_600U 6 /* 600 uA pull up */ +#define ICJX_CTRL_WORD_PULLUP_2M 7 /* 2 mA pull up*/ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* A reference to a structure of this type must be passed to the iC-JX + * driver when the driver is instantiated. This structure provides + * information about the configuration of the iC-JX and provides some + * board-specific hooks. + * + * Memory for this structure is provided by the caller. It is not copied by + * the driver and is presumed to persist while the driver is active. The + * memory must be writeable because, under certain circumstances, the driver + * may modify the frequency. + */ + +struct icjx_config_s +{ + /* Device characterization */ + + uint8_t id; /* Device ID (if more expanders are used) */ + uint8_t verification; /* True if data verification on MISO line is used */ + uint8_t current_src; /* Current sources for pin nibbles (pull up, + * pull down) - see Control Word 2 register + */ + uint8_t addr; /* Device address (set by A(1:0) pins) */ + uint8_t mode; /* SPI mode */ + uint32_t frequency; /* SPI frequency */ +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: icjx_initialize + * + * Description: + * Instantiate and configure the iC-JX device driver to use the + * provided SPI device instance. + * + * Input Parameters: + * spi - A SPI driver instance + * config - Persistent board configuration data + * + * Returned Value: + * an ioexpander_dev_s instance on success, NULL on failure. + * + ****************************************************************************/ + +struct spi_dev_s; +FAR struct ioexpander_dev_s *icjx_initialize(FAR struct spi_dev_s *spi, + FAR struct icjx_config_s *config); + +#endif /* __INCLUDE_NUTTX_IOEXPANDER_ICJX_H */