Skip to content

Commit

Permalink
drivers/tca64xx: Add support for PCAL6416
Browse files Browse the repository at this point in the history
New part support added to driver,
pullup/pulldown configuration support

Signed-off-by: Jouni Ukkonen <[email protected]>
  • Loading branch information
joukkone committed Nov 6, 2024
1 parent 2b85095 commit 452f0b0
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 6 deletions.
107 changes: 101 additions & 6 deletions drivers/ioexpander/tca64xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ static uint8_t tca64_input_reg(FAR struct tca64_dev_s *priv, uint8_t pin);
static uint8_t tca64_output_reg(FAR struct tca64_dev_s *priv, uint8_t pin);
static uint8_t tca64_polarity_reg(FAR struct tca64_dev_s *priv, uint8_t pin);
static uint8_t tca64_config_reg(FAR struct tca64_dev_s *priv, uint8_t pin);
static uint8_t tca64_pdenable_reg(FAR struct tca64_dev_s *priv, uint8_t pin);
static uint8_t tca64_pdselect_reg(FAR struct tca64_dev_s *priv, uint8_t pin);

static int tca64_getreg(FAR struct tca64_dev_s *priv, uint8_t regaddr,
FAR uint8_t *regval, unsigned int count);
static int tca64_putreg(struct tca64_dev_s *priv, uint8_t regaddr,
Expand Down Expand Up @@ -149,6 +152,16 @@ static const struct tca64_part_s g_tca64_parts[TCA64_NPARTS] =
TCA6424_POLARITY0_REG,
TCA6424_CONFIG0_REG,
},
{
PCAL6416A_PART,
MIN(PCAL6416A_NR_GPIOS, CONFIG_IOEXPANDER_NPINS),
PCAL6416A_INPUT0_REG,
PCAL6416A_OUTPUT0_REG,
PCAL6416A_POLARITY0_REG,
PCAL6416A_CONFIG0_REG,
PCAL6416A_PU_ENABLE0_REG,
PCAL6416A_PUPD_SELECT0_REG,
},
};

/****************************************************************************
Expand Down Expand Up @@ -254,6 +267,41 @@ static uint8_t tca64_config_reg(FAR struct tca64_dev_s *priv, uint8_t pin)
return reg + (pin >> 3);
}

/****************************************************************************
* Name: tca64_pdenable_reg
*
* Description:
* Return the address of the pu/pd enable register for the specified pin.
*
****************************************************************************/

static uint8_t tca64_pdenable_reg(FAR struct tca64_dev_s *priv, uint8_t pin)
{
FAR const struct tca64_part_s *part = tca64_getpart(priv);
uint8_t reg = part->tp_puenable;

DEBUGASSERT(pin <= part->tp_ngpios);
return reg + (pin >> 3);
}

/****************************************************************************
* Name: tca64_pdselect_reg
*
* Description:
* Return the address of the pu/pd selection register for the specified pin.
*
****************************************************************************/

static uint8_t tca64_pdselect_reg(FAR struct tca64_dev_s *priv, uint8_t pin)
{
FAR const struct tca64_part_s *part = tca64_getpart(priv);
uint8_t reg = part->tp_pu_select;

DEBUGASSERT(pin <= part->tp_ngpios);
return reg + (pin >> 3);
}


Check failure on line 304 in drivers/ioexpander/tca64xx.c

View workflow job for this annotation

GitHub Actions / check

Too many blank lines
/****************************************************************************
* Name: tca64_getreg
*
Expand Down Expand Up @@ -373,11 +421,6 @@ static int tca64_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin,
uint8_t regval;
int ret;

if (direction != IOEXPANDER_DIRECTION_IN &&
direction != IOEXPANDER_DIRECTION_OUT)
{
return -EINVAL;
}

Check failure on line 424 in drivers/ioexpander/tca64xx.c

View workflow job for this annotation

GitHub Actions / check

Too many blank lines
DEBUGASSERT(priv != NULL && priv->config != NULL &&
pin < CONFIG_IOEXPANDER_NPINS);
Expand Down Expand Up @@ -409,14 +452,17 @@ static int tca64_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin,

/* Set the pin direction in the I/O Expander */

if (direction == IOEXPANDER_DIRECTION_IN)
if ((direction == IOEXPANDER_DIRECTION_IN) ||
(direction == IOEXPANDER_DIRECTION_IN_PULLDOWN) ||
(direction == IOEXPANDER_DIRECTION_IN_PULLUP))
{
/* Configure pin as input. If a bit in the configuration register is
* set to 1, the corresponding port pin is enabled as an input with a
* high-impedance output driver.
*/

regval |= (1 << (pin & 7));

}

Check failure on line 466 in drivers/ioexpander/tca64xx.c

View workflow job for this annotation

GitHub Actions / check

Blank line precedes right brace at line
else /* if (direction == IOEXPANDER_DIRECTION_OUT) */
{
Expand All @@ -439,6 +485,55 @@ static int tca64_direction(FAR struct ioexpander_dev_s *dev, uint8_t pin,
regaddr, ret);
}

if ((direction == IOEXPANDER_DIRECTION_IN_PULLDOWN) ||
(direction == IOEXPANDER_DIRECTION_IN_PULLUP))
{
regaddr = tca64_pdenable_reg(priv, pin);
ret = tca64_getreg(priv, regaddr, &regval, 1);
if (ret < 0)
{
gpioerr("ERROR: Failed to read pu config register at %u: %d\n",
regaddr, ret);
goto errout_with_lock;
}

regval |= (1 << (pin & 7));

ret = tca64_putreg(priv, regaddr, &regval, 1);
if (ret < 0)
{
gpioerr("ERROR: Failed to write pu config register at %u: %d\n",
regaddr, ret);
goto errout_with_lock;
}

regaddr = tca64_pdselect_reg(priv, pin);
ret = tca64_getreg(priv, regaddr, &regval, 1);
if (ret < 0)
{
gpioerr("ERROR: Failed to read pu select register at %u: %d\n",
regaddr, ret);
goto errout_with_lock;
}

if (direction == IOEXPANDER_DIRECTION_IN_PULLUP)
{
regval |= (1 << (pin & 7));
}
else
{
regval &= ~(1 << (pin & 7));
}

ret = tca64_putreg(priv, regaddr, &regval, 1);
if (ret < 0)
{
gpioerr("ERROR: Failed to write pu select register at %u: %d\n",
regaddr, ret);
goto errout_with_lock;
}
}

errout_with_lock:
nxmutex_unlock(&priv->lock);
return ret;
Expand Down
21 changes: 21 additions & 0 deletions drivers/ioexpander/tca64xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,25 @@

#define TCA64XX_NR_GPIO_MAX TCA6424_NR_GPIOS


Check failure on line 135 in drivers/ioexpander/tca64xx.h

View workflow job for this annotation

GitHub Actions / check

Too many blank lines

Check failure on line 136 in drivers/ioexpander/tca64xx.h

View workflow job for this annotation

GitHub Actions / check

Too many blank lines
#define PCAL6416A_INPUT0_REG 0x00
#define PCAL6416A_INPUT1_REG 0x01
#define PCAL6416A_OUTPUT0_REG 0x02
#define PCAL6416A_OUTPUT1_REG 0x03
#define PCAL6416A_POLARITY0_REG 0x04
#define PCAL6416A_POLARITY1_REG 0x05
#define PCAL6416A_CONFIG0_REG 0x06
#define PCAL6416A_CONFIG1_REG 0x07
#define PCAL6416A_PU_ENABLE0_REG 0x46
#define PCAL6416A_PU_ENABLE1_REG 0x47
#define PCAL6416A_PUPD_SELECT0_REG 0x48
#define PCAL6416A_PUPD_SELECT1_REG 0x49
#define PCAL6416A_NR_GPIOS 16


Check failure on line 151 in drivers/ioexpander/tca64xx.h

View workflow job for this annotation

GitHub Actions / check

Too many blank lines

Check failure on line 152 in drivers/ioexpander/tca64xx.h

View workflow job for this annotation

GitHub Actions / check

Too many blank lines

Check failure on line 153 in drivers/ioexpander/tca64xx.h

View workflow job for this annotation

GitHub Actions / check

Too many blank lines
/* 1us (datasheet: reset pulse duration (Tw) is 4ns */

#define TCA64XX_TW 1
Expand Down Expand Up @@ -181,6 +200,8 @@ struct tca64_part_s
uint8_t tp_output; /* Address of first output register */
uint8_t tp_polarity; /* Address of first polarity register */
uint8_t tp_config; /* Address of first configuration register */
uint8_t tp_puenable;
uint8_t tp_pu_select;
};

#ifdef CONFIG_IOEXPANDER_INT_ENABLE
Expand Down
1 change: 1 addition & 0 deletions include/nuttx/ioexpander/tca64xx.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ enum tca64xx_part_e
TCA6408_PART = 0,
TCA6416_PART,
TCA6424_PART,
PCAL6416A_PART,
TCA64_NPARTS
};

Expand Down

0 comments on commit 452f0b0

Please sign in to comment.