@@ -365,12 +365,6 @@ struct dw_i3c_config {
365
365
clock_control_subsys_t clock_subsys ;
366
366
uint32_t regs ;
367
367
368
- /* Initial clk configuration */
369
- /* Maximum OD high clk pulse length */
370
- uint32_t od_thigh_max_ns ;
371
- /* Minimum OD low clk pulse length */
372
- uint32_t od_tlow_min_ns ;
373
-
374
368
void (* irq_config_func )();
375
369
376
370
#if defined(CONFIG_PINCTRL )
@@ -1414,7 +1408,7 @@ static int i3c_dw_irq(const struct device *dev)
1414
1408
return 0 ;
1415
1409
}
1416
1410
1417
- static int init_scl_timing (const struct device * dev )
1411
+ static int dw_i3c_init_scl_timing (const struct device * dev , struct i3c_config_controller * ctrl_cfg )
1418
1412
{
1419
1413
const struct dw_i3c_config * config = dev -> config ;
1420
1414
uint32_t core_rate , scl_timing ;
@@ -1427,12 +1421,21 @@ static int init_scl_timing(const struct device *dev)
1427
1421
LOG_ERR ("%s: get clock rate failed" , dev -> name );
1428
1422
return - EINVAL ;
1429
1423
}
1424
+
1430
1425
#ifdef CONFIG_I3C_CONTROLLER
1426
+
1427
+ __ASSERT ((ctrl_cfg != NULL ), "Controller configuration should not be NULL" );
1428
+
1429
+ if (ctrl_cfg -> scl_od_min .low_ns < I3C_OD_TLOW_MIN_NS ) {
1430
+ LOG_ERR ("%s: Open Drain Low Period is out of range" , dev -> name );
1431
+ return - EINVAL ;
1432
+ }
1433
+
1431
1434
/* I3C_OD */
1432
- hcnt = DIV_ROUND_UP (config -> od_thigh_max_ns * (uint64_t )core_rate , I3C_PERIOD_NS ) - 1 ;
1435
+ hcnt = DIV_ROUND_UP (ctrl_cfg -> scl_od_min . high_ns * (uint64_t )core_rate , I3C_PERIOD_NS ) - 1 ;
1433
1436
hcnt = CLAMP (hcnt , SCL_I3C_TIMING_CNT_MIN , SCL_I3C_TIMING_CNT_MAX );
1434
1437
1435
- lcnt = DIV_ROUND_UP (config -> od_tlow_min_ns * (uint64_t )core_rate , I3C_PERIOD_NS );
1438
+ lcnt = DIV_ROUND_UP (ctrl_cfg -> scl_od_min . low_ns * (uint64_t )core_rate , I3C_PERIOD_NS );
1436
1439
lcnt = CLAMP (lcnt , SCL_I3C_TIMING_CNT_MIN , SCL_I3C_TIMING_CNT_MAX );
1437
1440
1438
1441
scl_timing = SCL_I3C_TIMING_HCNT (hcnt ) | SCL_I3C_TIMING_LCNT (lcnt );
@@ -1491,8 +1494,10 @@ static int init_scl_timing(const struct device *dev)
1491
1494
DIV_ROUND_UP (I3C_BUS_IDLE_TIME_NS * (uint64_t )core_rate , I3C_PERIOD_NS );
1492
1495
sys_write32 (BUS_I3C_IDLE_TIME (scl_timing ), config -> regs + BUS_IDLE_TIMING );
1493
1496
#endif /* CONFIG_I3C_TARGET */
1497
+
1494
1498
return 0 ;
1495
1499
}
1500
+
1496
1501
#ifdef CONFIG_I3C_CONTROLLER
1497
1502
/**
1498
1503
* Determine I3C bus mode from the i2c devices on the bus
@@ -1634,6 +1639,7 @@ static int set_controller_info(const struct device *dev)
1634
1639
return 0 ;
1635
1640
}
1636
1641
#endif /* CONFIG_I3C_CONTROLLER */
1642
+
1637
1643
static void enable_interrupts (const struct device * dev )
1638
1644
{
1639
1645
const struct dw_i3c_config * config = dev -> config ;
@@ -2072,17 +2078,28 @@ static int dw_i3c_config_get(const struct device *dev, enum i3c_config_type type
2072
2078
*/
2073
2079
static int dw_i3c_configure (const struct device * dev , enum i3c_config_type type , void * config )
2074
2080
{
2081
+ #ifdef CONFIG_I3C_CONTROLLER
2082
+ struct dw_i3c_data * data = dev -> data ;
2083
+ int ret ;
2084
+ #endif /* CONFIG_I3C_CONTROLLER */
2075
2085
#ifdef CONFIG_I3C_TARGET
2076
2086
const struct dw_i3c_config * dev_config = dev -> config ;
2077
2087
#endif /* CONFIG_I3C_TARGET */
2078
2088
2079
2089
if (type == I3C_CONFIG_CONTROLLER ) {
2080
- /* struct i3c_config_controller *ctrl_cfg = config; */
2081
- /* TODO: somehow determine i3c rate? snps is complicated */
2090
+ #ifdef CONFIG_I3C_CONTROLLER
2091
+ ret = dw_i3c_init_scl_timing (dev , config );
2092
+ if (ret != 0 ) {
2093
+ return ret ;
2094
+ }
2095
+ (void )memcpy (& data -> common .ctrl_config ,
2096
+ config , sizeof (data -> common .ctrl_config ));
2097
+ #else
2082
2098
return - ENOTSUP ;
2099
+ #endif /* CONFIG_I3C_CONTROLLER */
2083
2100
} else if (type == I3C_CONFIG_TARGET ) {
2084
2101
#ifdef CONFIG_I3C_TARGET
2085
- struct i3c_config_target * target_cfg = config ;
2102
+ struct i3c_config_target * target_cfg = ( struct i3c_config_target * ) config ;
2086
2103
uint32_t val ;
2087
2104
2088
2105
/* TODO: some how randomly generate pid */
@@ -2357,13 +2374,6 @@ static int dw_i3c_init(const struct device *dev)
2357
2374
__ASSERT_NO_MSG ((IS_ENABLED (CONFIG_I3C_TARGET ) && ctrl_config -> is_secondary ) ||
2358
2375
(IS_ENABLED (CONFIG_I3C_CONTROLLER ) && !ctrl_config -> is_secondary ));
2359
2376
2360
- ret = init_scl_timing (dev );
2361
- if (ret != 0 ) {
2362
- return ret ;
2363
- }
2364
-
2365
- enable_interrupts (dev );
2366
-
2367
2377
/* disable ibi */
2368
2378
sys_write32 (IBI_REQ_REJECT_ALL , config -> regs + IBI_SIR_REQ_REJECT );
2369
2379
sys_write32 (IBI_REQ_REJECT_ALL , config -> regs + IBI_MR_REQ_REJECT );
@@ -2385,6 +2395,15 @@ static int dw_i3c_init(const struct device *dev)
2385
2395
}
2386
2396
#endif /* CONFIG_I3C_CONTROLLER */
2387
2397
dw_i3c_enable_controller (config , true);
2398
+
2399
+ ret = dw_i3c_init_scl_timing (dev , ctrl_config );
2400
+ if (ret != 0 ) {
2401
+ LOG_ERR ("%s: Clock setting failed" , dev -> name );
2402
+ return ret ;
2403
+ }
2404
+
2405
+ enable_interrupts (dev );
2406
+
2388
2407
#ifdef CONFIG_I3C_CONTROLLER
2389
2408
if (!(ctrl_config -> is_secondary )) {
2390
2409
/* Perform bus initialization - skip if no I3C devices are known. */
@@ -2497,15 +2516,15 @@ static DEVICE_API(i3c, dw_i3c_api) = {
2497
2516
.common.ctrl_config.scl.i3c = \
2498
2517
DT_INST_PROP_OR(n, i3c_scl_hz, I3C_BUS_TYP_I3C_SCL_RATE), \
2499
2518
.common.ctrl_config.scl.i2c = DT_INST_PROP_OR(n, i2c_scl_hz, 0), \
2519
+ .common.ctrl_config.scl_od_min.high_ns = DT_INST_PROP(n, od_thigh_min_ns), \
2520
+ .common.ctrl_config.scl_od_min.low_ns = DT_INST_PROP(n, od_tlow_min_ns), \
2500
2521
}; \
2501
2522
static const struct dw_i3c_config dw_i3c_cfg_##n = { \
2502
2523
.regs = DT_INST_REG_ADDR(n), \
2503
2524
.clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
2504
2525
.clock_subsys = COND_CODE_1(DT_INST_PHA_HAS_CELL(n, clocks, clkid), \
2505
2526
((clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, clkid)), \
2506
2527
((clock_control_subsys_t)0)), \
2507
- .od_thigh_max_ns = DT_INST_PROP(n, od_thigh_max_ns), \
2508
- .od_tlow_min_ns = DT_INST_PROP(n, od_tlow_min_ns), \
2509
2528
.irq_config_func = &i3c_dw_irq_config_##n, \
2510
2529
IF_ENABLED(CONFIG_I3C_CONTROLLER, \
2511
2530
(.common.dev_list.i3c = dw_i3c_device_array_##n, \
0 commit comments