Browse Source

drivers: i2c: tca9544a

Extend tca954x (tca9546a, tca9548a) driver to support tca9544a i2c MUX.
(different bitmask and flag for enable bit in register)

Signed-off-by: Florian Weber <Florian.Weber@live.de>
pull/81805/head
Florian Weber 9 months ago committed by Fabio Baltieri
parent
commit
7adeac1b12
  1. 3
      drivers/i2c/Kconfig.tca954x
  2. 31
      drivers/i2c/i2c_tca954x.c
  3. 10
      dts/bindings/i2c/ti,tca9544a.yaml

3
drivers/i2c/Kconfig.tca954x

@ -4,7 +4,8 @@ @@ -4,7 +4,8 @@
menuconfig I2C_TCA954X
bool "I2C addressable switch"
default y
depends on DT_HAS_TI_TCA9546A_ENABLED || DT_HAS_TI_TCA9548A_ENABLED
depends on DT_HAS_TI_TCA9546A_ENABLED || DT_HAS_TI_TCA9548A_ENABLED \
|| DT_HAS_TI_TCA9544A_ENABLED
help
Enable TCA954x series I2C bus switch

31
drivers/i2c/i2c_tca954x.c

@ -28,6 +28,7 @@ struct tca954x_root_data { @@ -28,6 +28,7 @@ struct tca954x_root_data {
struct tca954x_channel_config {
const struct device *root;
uint8_t chan_mask;
bool has_enable;
};
static inline struct tca954x_root_data *
@ -143,7 +144,8 @@ static int tca954x_channel_init(const struct device *dev) @@ -143,7 +144,8 @@ static int tca954x_channel_init(const struct device *dev)
return -ENODEV;
}
if (chan_cfg->chan_mask >= BIT(root_cfg->nchans)) {
if ((chan_cfg->chan_mask >= BIT(root_cfg->nchans) && !chan_cfg->has_enable) ||
(chan_cfg->chan_mask > (BIT(2) | (root_cfg->nchans - 1)) && chan_cfg->has_enable)) {
LOG_ERR("Wrong DTS address provided for %s", dev->name);
return -EINVAL;
}
@ -162,11 +164,13 @@ static const struct i2c_driver_api tca954x_api_funcs = { @@ -162,11 +164,13 @@ static const struct i2c_driver_api tca954x_api_funcs = {
BUILD_ASSERT(CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO > CONFIG_I2C_TCA954X_ROOT_INIT_PRIO,
"I2C multiplexer channels must be initialized after their root");
#define TCA954x_CHILD_DEFINE(node_id, n) \
#define TCA954x_CHILD_DEFINE(node_id, n, has_enable_bit) \
static const struct tca954x_channel_config \
tca##n##a_down_config_##node_id = { \
.chan_mask = BIT(DT_REG_ADDR(node_id)), \
.chan_mask = has_enable_bit ? BIT(2) | DT_REG_ADDR(node_id) \
: BIT(DT_REG_ADDR(node_id)), \
.root = DEVICE_DT_GET(DT_PARENT(node_id)), \
.has_enable = has_enable_bit, \
}; \
DEVICE_DT_DEFINE(node_id, \
tca954x_channel_init, \
@ -176,7 +180,7 @@ BUILD_ASSERT(CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO > CONFIG_I2C_TCA954X_ROOT_INIT @@ -176,7 +180,7 @@ BUILD_ASSERT(CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO > CONFIG_I2C_TCA954X_ROOT_INIT
POST_KERNEL, CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO, \
&tca954x_api_funcs);
#define TCA954x_ROOT_DEFINE(n, inst, ch) \
#define TCA954x_ROOT_DEFINE(n, inst, ch, has_enable_bit) \
static const struct tca954x_root_config tca##n##a_cfg_##inst = { \
.i2c = I2C_DT_SPEC_INST_GET(inst), \
.nchans = ch, \
@ -191,20 +195,29 @@ BUILD_ASSERT(CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO > CONFIG_I2C_TCA954X_ROOT_INIT @@ -191,20 +195,29 @@ BUILD_ASSERT(CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO > CONFIG_I2C_TCA954X_ROOT_INIT
&tca##n##a_data_##inst, &tca##n##a_cfg_##inst, \
POST_KERNEL, CONFIG_I2C_TCA954X_ROOT_INIT_PRIO, \
NULL); \
DT_FOREACH_CHILD_VARGS(DT_INST(inst, ti_tca##n##a), TCA954x_CHILD_DEFINE, n);
DT_FOREACH_CHILD_VARGS(DT_INST(inst, ti_tca##n##a), TCA954x_CHILD_DEFINE, n, \
has_enable_bit);
/*
* TCA9546A: 4 channels
* TCA9544A: 4 channels mux
*/
#define TCA9546A_INIT(n) TCA954x_ROOT_DEFINE(9546, n, 4)
#define TCA9544A_INIT(n) TCA954x_ROOT_DEFINE(9544, n, 4, true)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT ti_tca9544a
DT_INST_FOREACH_STATUS_OKAY(TCA9544A_INIT)
/*
* TCA9546A: 4 channels switch
*/
#define TCA9546A_INIT(n) TCA954x_ROOT_DEFINE(9546, n, 4, false)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT ti_tca9546a
DT_INST_FOREACH_STATUS_OKAY(TCA9546A_INIT)
/*
* TCA9548A: 8 channels
* TCA9548A: 8 channels switch
*/
#define TCA9548A_INIT(n) TCA954x_ROOT_DEFINE(9548, n, 8)
#define TCA9548A_INIT(n) TCA954x_ROOT_DEFINE(9548, n, 8, false)
#undef DT_DRV_COMPAT
#define DT_DRV_COMPAT ti_tca9548a
DT_INST_FOREACH_STATUS_OKAY(TCA9548A_INIT)

10
dts/bindings/i2c/ti,tca9544a.yaml

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
# Binding for TI TCA9544A, compatible with NXP PCA9544A
description: Texas Instruments TCA9544A binding
compatible: "ti,tca9544a"
include: ti,tca954x-base.yaml
child-binding:
compatible: "ti,tca9544a-channel"
Loading…
Cancel
Save