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:
parent
fb86c453cc
commit
acbc14e767
|
@ -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
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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(®ister_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; \
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue