drivers/tca64xx: Add support for PCAL6416
- Added new part support for PCAL6416 - Added pullup/pulldown configuration support Signed-off-by: Jouni Ukkonen <jouni.ukkonen@unikie.com> Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
This commit is contained in:
parent
710bd199e5
commit
9b8c8bdd7b
3 changed files with 160 additions and 7 deletions
|
|
@ -53,6 +53,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,
|
||||
|
|
@ -134,6 +137,8 @@ static const struct tca64_part_s g_tca64_parts[TCA64_NPARTS] =
|
|||
TCA6408_OUTPUT_REG,
|
||||
TCA6408_POLARITY_REG,
|
||||
TCA6408_CONFIG_REG,
|
||||
TCA64XX_INVALID_REG,
|
||||
TCA64XX_INVALID_REG,
|
||||
},
|
||||
{
|
||||
TCA6416_PART,
|
||||
|
|
@ -142,6 +147,8 @@ static const struct tca64_part_s g_tca64_parts[TCA64_NPARTS] =
|
|||
TCA6416_OUTPUT0_REG,
|
||||
TCA6416_POLARITY0_REG,
|
||||
TCA6416_CONFIG0_REG,
|
||||
TCA64XX_INVALID_REG,
|
||||
TCA64XX_INVALID_REG,
|
||||
},
|
||||
{
|
||||
TCA6424_PART,
|
||||
|
|
@ -150,6 +157,18 @@ static const struct tca64_part_s g_tca64_parts[TCA64_NPARTS] =
|
|||
TCA6424_OUTPUT0_REG,
|
||||
TCA6424_POLARITY0_REG,
|
||||
TCA6424_CONFIG0_REG,
|
||||
TCA64XX_INVALID_REG,
|
||||
TCA64XX_INVALID_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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -256,6 +275,50 @@ 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;
|
||||
|
||||
if (reg == TCA64XX_INVALID_REG)
|
||||
{
|
||||
return reg;
|
||||
}
|
||||
|
||||
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_puselect;
|
||||
|
||||
if (reg == TCA64XX_INVALID_REG)
|
||||
{
|
||||
return reg;
|
||||
}
|
||||
|
||||
DEBUGASSERT(pin <= part->tp_ngpios);
|
||||
return reg + (pin >> 3);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tca64_getreg
|
||||
*
|
||||
|
|
@ -375,12 +438,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;
|
||||
}
|
||||
|
||||
DEBUGASSERT(priv != NULL && priv->config != NULL &&
|
||||
pin < CONFIG_IOEXPANDER_NPINS);
|
||||
|
||||
|
|
@ -411,7 +468,9 @@ 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
|
||||
|
|
@ -441,6 +500,81 @@ 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);
|
||||
if (regaddr == TCA64XX_INVALID_REG)
|
||||
{
|
||||
gpioerr("ERROR: This part does not support PU/PD settings\n");
|
||||
ret = -EINVAL;
|
||||
goto errout_with_lock;
|
||||
}
|
||||
|
||||
ret = tca64_getreg(priv, regaddr, ®val, 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, ®val, 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, ®val, 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, ®val, 1);
|
||||
if (ret < 0)
|
||||
{
|
||||
gpioerr("ERROR: Failed to write pu select register at %u: %d\n",
|
||||
regaddr, ret);
|
||||
goto errout_with_lock;
|
||||
}
|
||||
}
|
||||
else if (direction == IOEXPANDER_DIRECTION_IN)
|
||||
{
|
||||
/* Disable pu/pd if that is available */
|
||||
|
||||
regaddr = tca64_pdenable_reg(priv, pin);
|
||||
if (regaddr != TCA64XX_INVALID_REG)
|
||||
{
|
||||
ret = tca64_getreg(priv, regaddr, ®val, 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, ®val, 1);
|
||||
}
|
||||
}
|
||||
|
||||
errout_with_lock:
|
||||
nxmutex_unlock(&priv->lock);
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -99,6 +99,8 @@
|
|||
|
||||
/* TCA64XX Parts ************************************************************/
|
||||
|
||||
#define TCA64XX_INVALID_REG 0xff
|
||||
|
||||
#define TCA6408_INPUT_REG 0x00
|
||||
#define TCA6408_OUTPUT_REG 0x01
|
||||
#define TCA6408_POLARITY_REG 0x02
|
||||
|
|
@ -134,6 +136,20 @@
|
|||
|
||||
#define TCA64XX_NR_GPIO_MAX TCA6424_NR_GPIOS
|
||||
|
||||
#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
|
||||
|
||||
/* 1us (datasheet: reset pulse duration (Tw) is 4ns */
|
||||
|
||||
#define TCA64XX_TW 1
|
||||
|
|
@ -183,6 +199,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_puselect;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_IOEXPANDER_INT_ENABLE
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ enum tca64xx_part_e
|
|||
TCA6408_PART = 0,
|
||||
TCA6416_PART,
|
||||
TCA6424_PART,
|
||||
PCAL6416A_PART,
|
||||
TCA64_NPARTS
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue