8
8
#include <zephyr/logging/log.h>
9
9
#include <zephyr/drivers/i3c.h>
10
10
#include <zephyr/drivers/clock_control.h>
11
+ #include <zephyr/pm/device.h>
11
12
#include <zephyr/sys/util.h>
12
13
#include <assert.h>
13
14
15
+ #if defined(CONFIG_PINCTRL )
16
+ #include <zephyr/drivers/pinctrl.h>
17
+ #endif
18
+
14
19
#define NANO_SEC 1000000000ULL
15
20
#define BYTES_PER_DWORD 4
16
21
@@ -365,6 +370,10 @@ struct dw_i3c_config {
365
370
uint32_t od_tlow_min_ns ;
366
371
367
372
void (* irq_config_func )();
373
+
374
+ #if defined(CONFIG_PINCTRL )
375
+ const struct pinctrl_dev_config * pcfg ;
376
+ #endif
368
377
};
369
378
370
379
struct dw_i3c_data {
@@ -2204,6 +2213,27 @@ static int dw_i3c_target_unregister(const struct device *dev, struct i3c_target_
2204
2213
return 0 ;
2205
2214
}
2206
2215
2216
+ static int dw_i3c_pinctrl_enable (const struct device * dev , bool enable )
2217
+ {
2218
+ #ifdef CONFIG_PINCTRL
2219
+ const struct dw_i3c_config * config = dev -> config ;
2220
+ uint8_t state = enable ? PINCTRL_STATE_DEFAULT : PINCTRL_STATE_SLEEP ;
2221
+ int ret ;
2222
+
2223
+ ret = pinctrl_apply_state (config -> pcfg , state );
2224
+ if (ret == - ENOENT ) {
2225
+ /* State not defined; ignore and return success. */
2226
+ ret = 0 ;
2227
+ }
2228
+
2229
+ return ret ;
2230
+ #else
2231
+ ARG_UNUSED (dev );
2232
+ ARG_UNUSED (enable );
2233
+ return 0 ;
2234
+ #endif
2235
+ }
2236
+
2207
2237
static int dw_i3c_init (const struct device * dev )
2208
2238
{
2209
2239
const struct dw_i3c_config * config = dev -> config ;
@@ -2229,6 +2259,8 @@ static int dw_i3c_init(const struct device *dev)
2229
2259
k_sem_init (& data -> sem_xfer , 0 , 1 );
2230
2260
k_mutex_init (& data -> mt );
2231
2261
2262
+ dw_i3c_pinctrl_enable (dev , true);
2263
+
2232
2264
data -> mode = i3c_bus_mode (& config -> common .dev_list );
2233
2265
2234
2266
/* reset all */
@@ -2309,6 +2341,32 @@ static int dw_i3c_init(const struct device *dev)
2309
2341
return 0 ;
2310
2342
}
2311
2343
2344
+ #if defined(CONFIG_PM_DEVICE )
2345
+ static int dw_i3c_pm_ctrl (const struct device * dev , enum pm_device_action action )
2346
+ {
2347
+ const struct dw_i3c_config * config = dev -> config ;
2348
+
2349
+ LOG_DBG ("PM action: %d" , (int )action );
2350
+
2351
+ switch (action ) {
2352
+ case PM_DEVICE_ACTION_SUSPEND :
2353
+ dw_i3c_enable_controller (config , false);
2354
+ dw_i3c_pinctrl_enable (dev , false);
2355
+ break ;
2356
+
2357
+ case PM_DEVICE_ACTION_RESUME :
2358
+ dw_i3c_pinctrl_enable (dev , true);
2359
+ dw_i3c_enable_controller (config , true);
2360
+ break ;
2361
+
2362
+ default :
2363
+ return - ENOTSUP ;
2364
+ }
2365
+
2366
+ return 0 ;
2367
+ }
2368
+ #endif
2369
+
2312
2370
static DEVICE_API (i3c , dw_i3c_api ) = {
2313
2371
.i2c_api .transfer = dw_i3c_i2c_api_transfer ,
2314
2372
@@ -2348,8 +2406,17 @@ static DEVICE_API(i3c, dw_i3c_api) = {
2348
2406
irq_enable(DT_INST_IRQN(n)); \
2349
2407
}
2350
2408
2409
+ #if defined(CONFIG_PINCTRL )
2410
+ #define I3C_DW_PINCTRL_DEFINE (n ) PINCTRL_DT_INST_DEFINE(n)
2411
+ #define I3C_DW_PINCTRL_INIT (n ) .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),
2412
+ #else
2413
+ #define I3C_DW_PINCTRL_DEFINE (n )
2414
+ #define I3C_DW_PINCTRL_INIT (n )
2415
+ #endif
2416
+
2351
2417
#define DEFINE_DEVICE_FN (n ) \
2352
2418
I3C_DW_IRQ_HANDLER(n) \
2419
+ I3C_DW_PINCTRL_DEFINE(n); \
2353
2420
static struct i3c_device_desc dw_i3c_device_array_##n[] = I3C_DEVICE_ARRAY_DT_INST(n); \
2354
2421
static struct i3c_i2c_device_desc dw_i3c_i2c_device_array_##n[] = \
2355
2422
I3C_I2C_DEVICE_ARRAY_DT_INST(n); \
@@ -2368,9 +2435,11 @@ static DEVICE_API(i3c, dw_i3c_api) = {
2368
2435
.common.dev_list.num_i3c = ARRAY_SIZE(dw_i3c_device_array_##n), \
2369
2436
.common.dev_list.i2c = dw_i3c_i2c_device_array_##n, \
2370
2437
.common.dev_list.num_i2c = ARRAY_SIZE(dw_i3c_i2c_device_array_##n), \
2371
- }; \
2372
- DEVICE_DT_INST_DEFINE(n, dw_i3c_init, NULL, &dw_i3c_data_##n, &dw_i3c_cfg_##n, \
2373
- POST_KERNEL, CONFIG_I3C_CONTROLLER_INIT_PRIORITY, &dw_i3c_api);
2438
+ I3C_DW_PINCTRL_INIT(n)}; \
2439
+ PM_DEVICE_DT_INST_DEFINE(n, dw_i3c_pm_action); \
2440
+ DEVICE_DT_INST_DEFINE(n, dw_i3c_init, PM_DEVICE_DT_INST_GET(n), &dw_i3c_data_##n, \
2441
+ &dw_i3c_cfg_##n, POST_KERNEL, CONFIG_I3C_CONTROLLER_INIT_PRIORITY, \
2442
+ &dw_i3c_api);
2374
2443
2375
2444
#define DT_DRV_COMPAT snps_designware_i3c
2376
2445
DT_INST_FOREACH_STATUS_OKAY (DEFINE_DEVICE_FN );
0 commit comments