drivers: gpio: implement parallel mode in TLE9104

Implement the parallel mode in the powertrain switch TLE9104.
This allows that OUT1 and OUT2 are controlled together, as well
as OUT3 and OUT4.

Signed-off-by: Benedikt Schmidt <benedikt.schmidt@embedded-solutions.at>
This commit is contained in:
Benedikt Schmidt 2024-08-29 18:09:25 +02:00 committed by Anas Nashif
parent fb86c453cc
commit acbc14e767
4 changed files with 63 additions and 1 deletions

View File

@ -212,6 +212,9 @@ Drivers and Sensors
* GPIO
* tle9104: Add support for the parallel output mode via setting the properties ``parallel-out12`` and
``parallel-out34``.
* Hardware info
* I2C

View File

@ -22,6 +22,8 @@ struct tle9104_gpio_config {
struct gpio_driver_config common;
/* parent MFD */
const struct device *parent;
bool parallel_mode_out12;
bool parallel_mode_out34;
};
struct tle9104_gpio_data {
@ -80,6 +82,16 @@ static int tle9104_gpio_pin_configure(const struct device *dev, gpio_pin_t pin,
return -ENOTSUP;
}
if (config->parallel_mode_out12 && pin == 1) {
LOG_ERR("cannot configure OUT2 if parallel mode is enabled for OUT1 and OUT2");
return -EINVAL;
}
if (config->parallel_mode_out34 && pin == 3) {
LOG_ERR("cannot configure OUT4 if parallel mode is enabled for OUT3 and OUT4");
return -EINVAL;
}
k_mutex_lock(&data->lock, K_FOREVER);
if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
@ -110,6 +122,16 @@ static int tle9104_gpio_port_set_masked_raw(const struct device *dev, uint32_t m
struct tle9104_gpio_data *data = dev->data;
int result;
if (config->parallel_mode_out12 && (BIT(1) & mask) != 0) {
LOG_ERR("cannot set OUT2 if parallel mode is enabled for OUT1 and OUT2");
return -EINVAL;
}
if (config->parallel_mode_out34 && (BIT(3) & mask) != 0) {
LOG_ERR("cannot set OUT4 if parallel mode is enabled for OUT3 and OUT4");
return -EINVAL;
}
/* cannot execute a bus operation in an ISR context */
if (k_is_in_isr()) {
return -EWOULDBLOCK;
@ -139,6 +161,16 @@ static int tle9104_gpio_port_toggle_bits(const struct device *dev, uint32_t mask
struct tle9104_gpio_data *data = dev->data;
int result;
if (config->parallel_mode_out12 && (BIT(1) & mask) != 0) {
LOG_ERR("cannot toggle OUT2 if parallel mode is enabled for OUT1 and OUT2");
return -EINVAL;
}
if (config->parallel_mode_out34 && (BIT(3) & mask) != 0) {
LOG_ERR("cannot toggle OUT4 if parallel mode is enabled for OUT3 and OUT4");
return -EINVAL;
}
/* cannot execute a bus operation in an ISR context */
if (k_is_in_isr()) {
return -EWOULDBLOCK;
@ -176,6 +208,7 @@ static int tle9104_gpio_init(const struct device *dev)
{
const struct tle9104_gpio_config *config = dev->config;
struct tle9104_gpio_data *data = dev->data;
int result;
LOG_DBG("initialize TLE9104 GPIO instance %s", dev->name);
@ -184,7 +217,7 @@ static int tle9104_gpio_init(const struct device *dev)
return -EINVAL;
}
int result = k_mutex_init(&data->lock);
result = k_mutex_init(&data->lock);
if (result != 0) {
LOG_ERR("unable to initialize mutex");
return result;
@ -199,6 +232,8 @@ static int tle9104_gpio_init(const struct device *dev)
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(inst), \
}, \
.parent = DEVICE_DT_GET(DT_PARENT(DT_DRV_INST(inst))), \
.parallel_mode_out12 = DT_PROP(DT_PARENT(DT_DRV_INST(inst)), parallel_out12), \
.parallel_mode_out34 = DT_PROP(DT_PARENT(DT_DRV_INST(inst)), parallel_out34), \
}; \
\
static struct tle9104_gpio_data tle9104_gpio_##inst##_drvdata; \

View File

@ -36,6 +36,8 @@
#define TLE9104_CFG_CWDTIME_LENGTH 2
#define TLE9104_CFG_CWDTIME_POS 6
#define TLE9104_CFG_OUT34PAR_POS 5
#define TLE9104_CFG_OUT12PAR_POS 4
#define TLE9104_OFFDIAGCFG_DIAGFILTCFG_LENGTH 2
#define TLE9104_OFFDIAGCFG_DIAGFILTCFG_POS 4
@ -101,6 +103,8 @@ struct tle9104_config {
uint16_t diagnostic_filter_time;
uint16_t overcurrent_shutdown_delay_time;
uint16_t overcurrent_shutdown_threshold;
bool parallel_mode_out12;
bool parallel_mode_out34;
};
struct tle9104_data {
@ -527,6 +531,16 @@ static int tle9104_init(const struct device *dev)
tle9104_set_register_bits(&register_cfg, TLE9104_CFG_CWDTIME_POS,
TLE9104_CFG_CWDTIME_LENGTH, 0);
if (config->parallel_mode_out12) {
LOG_DBG("use parallel mode for OUT1 and OUT2");
register_cfg |= BIT(TLE9104_CFG_OUT12PAR_POS);
}
if (config->parallel_mode_out34) {
LOG_DBG("use parallel mode for OUT3 and OUT4");
register_cfg |= BIT(TLE9104_CFG_OUT34PAR_POS);
}
result = tle9104_write_register(dev, TLE9104REGISTER_CFG, register_cfg);
if (result != 0) {
LOG_ERR("unable to write configuration");
@ -598,6 +612,8 @@ static int tle9104_init(const struct device *dev)
DT_INST_ENUM_IDX(inst, overcurrent_shutdown_delay_time), \
.overcurrent_shutdown_threshold = \
DT_INST_ENUM_IDX(inst, overcurrent_shutdown_threshold), \
.parallel_mode_out12 = DT_INST_PROP(inst, parallel_out12), \
.parallel_mode_out34 = DT_INST_PROP(inst, parallel_out34), \
}; \
\
static struct tle9104_data tle9104_##inst##_data; \

View File

@ -76,3 +76,11 @@ properties:
description:
overcurrent shutdown threshold in mA,
default matches power on reset value
parallel-out12:
type: boolean
description: Enables parallel mode for OUT1 and OUT2
parallel-out34:
type: boolean
description: Enables parallel mode for OUT3 and OUT4