14
14
#include <zephyr/drivers/pinctrl.h>
15
15
#include <zephyr/drivers/reset.h>
16
16
17
+ #ifdef CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
18
+ #include "i2c_bitbang.h"
19
+ #include <zephyr/drivers/gpio.h>
20
+ #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
21
+
17
22
#include <zephyr/logging/log.h>
18
23
#include <zephyr/irq.h>
19
24
LOG_MODULE_REGISTER (mcux_flexcomm );
@@ -34,6 +39,10 @@ struct mcux_flexcomm_config {
34
39
uint32_t bitrate ;
35
40
const struct pinctrl_dev_config * pincfg ;
36
41
const struct reset_dt_spec reset ;
42
+ #ifdef CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
43
+ struct gpio_dt_spec scl ;
44
+ struct gpio_dt_spec sda ;
45
+ #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
37
46
};
38
47
39
48
#ifdef CONFIG_I2C_TARGET
@@ -204,6 +213,89 @@ static int mcux_flexcomm_transfer(const struct device *dev,
204
213
return ret ;
205
214
}
206
215
216
+ #if CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
217
+ static void mcux_flexcomm_bitbang_set_scl (void * io_context , int state )
218
+ {
219
+ const struct mcux_flexcomm_config * config = io_context ;
220
+
221
+ gpio_pin_set_dt (& config -> scl , state );
222
+ }
223
+
224
+ static void mcux_flexcomm_bitbang_set_sda (void * io_context , int state )
225
+ {
226
+ const struct mcux_flexcomm_config * config = io_context ;
227
+
228
+ gpio_pin_set_dt (& config -> sda , state );
229
+ }
230
+
231
+ static int mcux_flexcomm_bitbang_get_sda (void * io_context )
232
+ {
233
+ const struct mcux_flexcomm_config * config = io_context ;
234
+
235
+ return gpio_pin_get_dt (& config -> sda ) == 0 ? 0 : 1 ;
236
+ }
237
+
238
+ static int mcux_flexcomm_recover_bus (const struct device * dev )
239
+ {
240
+ const struct mcux_flexcomm_config * config = dev -> config ;
241
+ struct mcux_flexcomm_data * data = dev -> data ;
242
+ struct i2c_bitbang bitbang_ctx ;
243
+ struct i2c_bitbang_io bitbang_io = {
244
+ .set_scl = mcux_flexcomm_bitbang_set_scl ,
245
+ .set_sda = mcux_flexcomm_bitbang_set_sda ,
246
+ .get_sda = mcux_flexcomm_bitbang_get_sda ,
247
+ };
248
+ uint32_t bitrate_cfg ;
249
+ int error = 0 ;
250
+
251
+ if (!gpio_is_ready_dt (& config -> scl )) {
252
+ LOG_ERR ("SCL GPIO device not ready" );
253
+ return - EIO ;
254
+ }
255
+
256
+ if (!gpio_is_ready_dt (& config -> sda )) {
257
+ LOG_ERR ("SDA GPIO device not ready" );
258
+ return - EIO ;
259
+ }
260
+
261
+ k_sem_take (& data -> lock , K_FOREVER );
262
+
263
+ error = gpio_pin_configure_dt (& config -> scl , GPIO_OUTPUT_HIGH );
264
+ if (error != 0 ) {
265
+ LOG_ERR ("failed to configure SCL GPIO (err %d)" , error );
266
+ goto restore ;
267
+ }
268
+
269
+ error = gpio_pin_configure_dt (& config -> sda , GPIO_OUTPUT_HIGH );
270
+ if (error != 0 ) {
271
+ LOG_ERR ("failed to configure SDA GPIO (err %d)" , error );
272
+ goto restore ;
273
+ }
274
+
275
+ i2c_bitbang_init (& bitbang_ctx , & bitbang_io , (void * )config );
276
+
277
+ bitrate_cfg = i2c_map_dt_bitrate (config -> bitrate ) | I2C_MODE_CONTROLLER ;
278
+ error = i2c_bitbang_configure (& bitbang_ctx , bitrate_cfg );
279
+ if (error != 0 ) {
280
+ LOG_ERR ("failed to configure I2C bitbang (err %d)" , error );
281
+ goto restore ;
282
+ }
283
+
284
+ error = i2c_bitbang_recover_bus (& bitbang_ctx );
285
+ if (error != 0 ) {
286
+ LOG_ERR ("failed to recover bus (err %d)" , error );
287
+ goto restore ;
288
+ }
289
+
290
+ restore :
291
+ (void )pinctrl_apply_state (config -> pincfg , PINCTRL_STATE_DEFAULT );
292
+
293
+ k_sem_give (& data -> lock );
294
+
295
+ return error ;
296
+ }
297
+ #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
298
+
207
299
#if defined(CONFIG_I2C_TARGET )
208
300
209
301
static struct mcux_flexcomm_target_data * mcux_flexcomm_find_free_target (
@@ -522,6 +614,9 @@ static int mcux_flexcomm_init(const struct device *dev)
522
614
static DEVICE_API (i2c , mcux_flexcomm_driver_api ) = {
523
615
.configure = mcux_flexcomm_configure ,
524
616
.transfer = mcux_flexcomm_transfer ,
617
+ #if CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
618
+ .recover_bus = mcux_flexcomm_recover_bus ,
619
+ #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
525
620
#if defined(CONFIG_I2C_TARGET )
526
621
.target_register = mcux_flexcomm_target_register ,
527
622
.target_unregister = mcux_flexcomm_target_unregister ,
@@ -531,6 +626,14 @@ static DEVICE_API(i2c, mcux_flexcomm_driver_api) = {
531
626
#endif
532
627
};
533
628
629
+ #if CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY
630
+ #define I2C_MCUX_FLEXCOMM_SCL_INIT (n ) .scl = GPIO_DT_SPEC_INST_GET_OR(n, scl_gpios, {0}),
631
+ #define I2C_MCUX_FLEXCOMM_SDA_INIT (n ) .sda = GPIO_DT_SPEC_INST_GET_OR(n, sda_gpios, {0}),
632
+ #else
633
+ #define I2C_MCUX_FLEXCOMM_SCL_INIT (n )
634
+ #define I2C_MCUX_FLEXCOMM_SDA_INIT (n )
635
+ #endif /* CONFIG_I2C_MCUX_FLEXCOMM_BUS_RECOVERY */
636
+
534
637
#define I2C_MCUX_FLEXCOMM_DEVICE (id ) \
535
638
PINCTRL_DT_INST_DEFINE(id); \
536
639
static void mcux_flexcomm_config_func_##id(const struct device *dev); \
@@ -542,6 +645,8 @@ static DEVICE_API(i2c, mcux_flexcomm_driver_api) = {
542
645
.irq_config_func = mcux_flexcomm_config_func_##id, \
543
646
.bitrate = DT_INST_PROP(id, clock_frequency), \
544
647
.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \
648
+ I2C_MCUX_FLEXCOMM_SCL_INIT(id) \
649
+ I2C_MCUX_FLEXCOMM_SDA_INIT(id) \
545
650
.reset = RESET_DT_SPEC_INST_GET(id), \
546
651
}; \
547
652
static struct mcux_flexcomm_data mcux_flexcomm_data_##id; \
0 commit comments