@@ -321,7 +321,9 @@ LOG_MODULE_REGISTER(i3c_dw, CONFIG_I3C_DW_LOG_LEVEL);
321321#define I3C_BUS_I2C_FM_TLOW_MIN_NS 1300
322322#define I3C_BUS_I2C_FMP_TLOW_MIN_NS 500
323323#define I3C_BUS_THIGH_MAX_NS 41
324+ #define I3C_BUS_TCAS_PS 38400
324325#define I3C_PERIOD_NS 1000000000ULL
326+ #define I3C_PERIOD_PS I3C_PERIOD_NS * 1000ULL
325327
326328#define I3C_BUS_MAX_I3C_SCL_RATE 12900000
327329#define I3C_BUS_TYP_I3C_SCL_RATE 12500000
@@ -1408,13 +1410,33 @@ static int i3c_dw_irq(const struct device *dev)
14081410 return 0 ;
14091411}
14101412
1413+ #ifdef CONFIG_I3C_CONTROLLER
1414+ /**
1415+ * @brief Return true if any i2c device only supports fast mode
1416+ *
1417+ * @param dev_list Pointer to device list
1418+ *
1419+ * @retval true if any i2c device only supports fast mode
1420+ * @retval false if all devices support fast mode plus
1421+ */
1422+ static bool i3c_any_i2c_fast_mode (const struct i3c_dev_list * dev_list )
1423+ {
1424+ for (int i = 0 ; i < dev_list -> num_i2c ; i ++ ) {
1425+ if (I3C_LVR_I2C_MODE (dev_list -> i2c [i ].lvr ) == I3C_LVR_I2C_FM_MODE ) {
1426+ return true;
1427+ }
1428+ }
1429+ return false;
1430+ }
1431+ #endif
1432+
14111433static int dw_i3c_init_scl_timing (const struct device * dev , struct i3c_config_controller * ctrl_cfg )
14121434{
14131435 const struct dw_i3c_config * config = dev -> config ;
14141436 uint32_t core_rate , scl_timing ;
14151437#ifdef CONFIG_I3C_CONTROLLER
14161438 struct dw_i3c_data * data = dev -> data ;
1417- uint32_t hcnt , lcnt ;
1439+ uint32_t hcnt , lcnt , fmlcnt , fmplcnt , free_cnt ;
14181440#endif /* CONFIG_I3C_CONTROLLER */
14191441
14201442 if (clock_control_get_rate (config -> clock , config -> clock_subsys , & core_rate ) != 0 ) {
@@ -1441,9 +1463,6 @@ static int dw_i3c_init_scl_timing(const struct device *dev, struct i3c_config_co
14411463 scl_timing = SCL_I3C_TIMING_HCNT (hcnt ) | SCL_I3C_TIMING_LCNT (lcnt );
14421464 sys_write32 (scl_timing , config -> regs + SCL_I3C_OD_TIMING );
14431465
1444- /* Set bus free timing to match tlow setting for OD clk config. */
1445- sys_write32 (BUS_I3C_MST_FREE (lcnt ), config -> regs + BUS_FREE_TIMING );
1446-
14471466 /* I3C_PP */
14481467 hcnt = DIV_ROUND_UP (I3C_BUS_THIGH_MAX_NS * (uint64_t )core_rate , I3C_PERIOD_NS ) - 1 ;
14491468 hcnt = CLAMP (hcnt , SCL_I3C_TIMING_CNT_MIN , SCL_I3C_TIMING_CNT_MAX );
@@ -1466,21 +1485,35 @@ static int dw_i3c_init_scl_timing(const struct device *dev, struct i3c_config_co
14661485 sys_write32 (scl_timing , config -> regs + SCL_EXT_LCNT_TIMING );
14671486
14681487 /* I2C FM+ */
1469- lcnt = DIV_ROUND_UP (I3C_BUS_I2C_FMP_TLOW_MIN_NS * (uint64_t )core_rate , I3C_PERIOD_NS );
1470- hcnt = DIV_ROUND_UP (core_rate , I3C_BUS_I2C_FM_PLUS_SCL_RATE ) - lcnt ;
1471- scl_timing = SCL_I2C_FMP_TIMING_HCNT (hcnt ) | SCL_I2C_FMP_TIMING_LCNT (lcnt );
1488+ fmplcnt = DIV_ROUND_UP (I3C_BUS_I2C_FMP_TLOW_MIN_NS * (uint64_t )core_rate , I3C_PERIOD_NS );
1489+ hcnt = DIV_ROUND_UP (core_rate , I3C_BUS_I2C_FM_PLUS_SCL_RATE ) - fmplcnt ;
1490+ scl_timing = SCL_I2C_FMP_TIMING_HCNT (hcnt ) | SCL_I2C_FMP_TIMING_LCNT (fmplcnt );
14721491 sys_write32 (scl_timing , config -> regs + SCL_I2C_FMP_TIMING );
14731492
14741493 /* I2C FM */
1475- lcnt = DIV_ROUND_UP (I3C_BUS_I2C_FM_TLOW_MIN_NS * (uint64_t )core_rate , I3C_PERIOD_NS );
1476- hcnt = DIV_ROUND_UP (core_rate , I3C_BUS_I2C_FM_SCL_RATE ) - lcnt ;
1477- scl_timing = SCL_I2C_FM_TIMING_HCNT (hcnt ) | SCL_I2C_FM_TIMING_LCNT (lcnt );
1494+ fmlcnt = DIV_ROUND_UP (I3C_BUS_I2C_FM_TLOW_MIN_NS * (uint64_t )core_rate , I3C_PERIOD_NS );
1495+ hcnt = DIV_ROUND_UP (core_rate , I3C_BUS_I2C_FM_SCL_RATE ) - fmlcnt ;
1496+ scl_timing = SCL_I2C_FM_TIMING_HCNT (hcnt ) | SCL_I2C_FM_TIMING_LCNT (fmlcnt );
14781497 sys_write32 (scl_timing , config -> regs + SCL_I2C_FM_TIMING );
14791498
14801499 if (data -> mode != I3C_BUS_MODE_PURE ) {
1481- sys_write32 (BUS_I3C_MST_FREE (lcnt ), config -> regs + BUS_FREE_TIMING );
1500+ /*
1501+ * Mixed bus: Set bus free timing to match tLOW of I2C timing. If any i2c devices
1502+ * only support fast mode, then it to the tLOW of that, otherwise set to the tLOW
1503+ * of fast mode plus.
1504+ */
1505+ sys_write32 (BUS_I3C_MST_FREE (i3c_any_i2c_fast_mode (& config -> common .dev_list )
1506+ ? fmlcnt
1507+ : fmplcnt ),
1508+ config -> regs + BUS_FREE_TIMING );
14821509 sys_write32 (sys_read32 (config -> regs + DEVICE_CTRL ) | DEV_CTRL_I2C_SLAVE_PRESENT ,
14831510 config -> regs + DEVICE_CTRL );
1511+ } else {
1512+ /* Pure bus: Set bus free timing to t_cas of 38.4ns */
1513+ free_cnt = DIV_ROUND_UP (I3C_BUS_TCAS_PS * (uint64_t )core_rate , I3C_PERIOD_PS );
1514+ sys_write32 (BUS_I3C_MST_FREE (free_cnt ), config -> regs + BUS_FREE_TIMING );
1515+ sys_write32 (sys_read32 (config -> regs + DEVICE_CTRL ) & ~DEV_CTRL_I2C_SLAVE_PRESENT ,
1516+ config -> regs + DEVICE_CTRL );
14841517 }
14851518#endif /* CONFIG_I3C_CONTROLLER */
14861519#ifdef CONFIG_I3C_TARGET
0 commit comments