drivers: i2c: nrfx_twim: disable and restore state for bus recovery
TWIM peripheral needs to be disabled for bus recovery, otherwise SCL/SDA lines will not be released. This patch makes sure to disable peripheral if active, and, restore its state afterwards (including pin configuration). It is worth to note that a better solution would be to: 1. Define scl/sda pins as `-gpios` in DT 2. Use GPIO API in the driver to perform recovery (as some other drivers do) 3. Potentially use a "gpio" pinctrl state for this case Unfortunately HAL is doing everything under the hood, so we have little options to improve this unless we don't use it for such case. GPIO based recovery should likely be generalized as many drivers seem to replicate such _algorithm_. Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
parent
2828578c25
commit
9974bb043f
|
@ -169,7 +169,6 @@ static int i2c_nrfx_twim_transfer(const struct device *dev,
|
||||||
* bus from this error.
|
* bus from this error.
|
||||||
*/
|
*/
|
||||||
LOG_ERR("Error on I2C line occurred for message %d", i);
|
LOG_ERR("Error on I2C line occurred for message %d", i);
|
||||||
nrfx_twim_disable(&dev_config->twim);
|
|
||||||
(void)i2c_nrfx_twim_recover_bus(dev);
|
(void)i2c_nrfx_twim_recover_bus(dev);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
break;
|
break;
|
||||||
|
@ -266,13 +265,13 @@ static int i2c_nrfx_twim_configure(const struct device *dev,
|
||||||
|
|
||||||
static int i2c_nrfx_twim_recover_bus(const struct device *dev)
|
static int i2c_nrfx_twim_recover_bus(const struct device *dev)
|
||||||
{
|
{
|
||||||
|
const struct i2c_nrfx_twim_config *dev_config = dev->config;
|
||||||
|
enum pm_device_state state;
|
||||||
uint32_t scl_pin;
|
uint32_t scl_pin;
|
||||||
uint32_t sda_pin;
|
uint32_t sda_pin;
|
||||||
nrfx_err_t err;
|
nrfx_err_t err;
|
||||||
|
|
||||||
#ifdef CONFIG_PINCTRL
|
#ifdef CONFIG_PINCTRL
|
||||||
const struct i2c_nrfx_twim_config *dev_config = dev->config;
|
|
||||||
|
|
||||||
scl_pin = nrf_twim_scl_pin_get(dev_config->twim.p_twim);
|
scl_pin = nrf_twim_scl_pin_get(dev_config->twim.p_twim);
|
||||||
sda_pin = nrf_twim_sda_pin_get(dev_config->twim.p_twim);
|
sda_pin = nrf_twim_sda_pin_get(dev_config->twim.p_twim);
|
||||||
#else
|
#else
|
||||||
|
@ -282,7 +281,21 @@ static int i2c_nrfx_twim_recover_bus(const struct device *dev)
|
||||||
sda_pin = dev_data->twim_config.sda;
|
sda_pin = dev_data->twim_config.sda;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* disable peripheral if active (required to release SCL/SDA lines) */
|
||||||
|
(void)pm_device_state_get(dev, &state);
|
||||||
|
if (state == PM_DEVICE_STATE_ACTIVE) {
|
||||||
|
nrfx_twim_disable(&dev_config->twim);
|
||||||
|
}
|
||||||
|
|
||||||
err = nrfx_twim_bus_recover(scl_pin, sda_pin);
|
err = nrfx_twim_bus_recover(scl_pin, sda_pin);
|
||||||
|
|
||||||
|
/* restore peripheral if it was active before */
|
||||||
|
if (state == PM_DEVICE_STATE_ACTIVE) {
|
||||||
|
(void)pinctrl_apply_state(dev_config->pcfg,
|
||||||
|
PINCTRL_STATE_DEFAULT);
|
||||||
|
nrfx_twim_enable(&dev_config->twim);
|
||||||
|
}
|
||||||
|
|
||||||
return (err == NRFX_SUCCESS ? 0 : -EBUSY);
|
return (err == NRFX_SUCCESS ? 0 : -EBUSY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue