On Fri, Sep 27, 2024 at 12:22:17PM +0800, Michael Wu wrote: > In commit 35eba185fd1a ("i2c: designware: Calculate SCL timing parameter > for High Speed Mode") hs_hcnt and hs_lcnt are calculated based on fixed > tHIGH = 160 and tLOW = 120. However, the set of these fixed values only > applies to the combination of hardware parameters IC_CAP_LOADING = 400pF > and IC_CLK_FREQ_OPTIMIZATION = 1. Outside of this combination, if these > fixed tHIGH = 160 and tLOW = 120 are still used, the calculated hs_hcnt > and hs_lcnt may not be small enough, making it impossible for the SCL > frequency to reach 3.4 MHz. > > Section 3.15.4.5 in DesignWare DW_apb_i2b Databook v2.03 says that when > IC_CLK_FREQ_OPTIMIZATION = 0, > > MIN_SCL_HIGHtime = 60 ns for 3.4 Mbps, bus loading = 100pF > = 120 ns for 3.4 Mbps, bus loading = 400pF > MIN_SCL_LOWtime = 160 ns for 3.4 Mbps, bus loading = 100pF > = 320 ns for 3.4 Mbps, bus loading = 400pF > > and section 3.15.4.6 says that when IC_CLK_FREQ_OPTIMIZATION = 1, > > MIN_SCL_HIGHtime = 60 ns for 3.4 Mbps, bus loading = 100pF > = 160 ns for 3.4 Mbps, bus loading = 400pF > MIN_SCL_LOWtime = 120 ns for 3.4 Mbps, bus loading = 100pF > = 320 ns for 3.4 Mbps, bus loading = 400pF > > In order to calculate more accurate hs_hcnt amd hs_lcnt, two hardware > parameters IC_CAP_LOADING and IC_CLK_FREQ_OPTIMIZATION must be > considered together. > > Signed-off-by: Michael Wu <michael.wu@xxxxxxxxx> > --- > drivers/i2c/busses/i2c-designware-common.c | 16 ++++++++++++++++ > drivers/i2c/busses/i2c-designware-core.h | 6 ++++++ > drivers/i2c/busses/i2c-designware-master.c | 14 ++++++++++++-- > 3 files changed, 34 insertions(+), 2 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c > index 080204182bb5..907f049f09f8 100644 > --- a/drivers/i2c/busses/i2c-designware-common.c > +++ b/drivers/i2c/busses/i2c-designware-common.c > @@ -372,6 +372,20 @@ static void i2c_dw_adjust_bus_speed(struct dw_i2c_dev *dev) > t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ; > } > > +static void i2c_dw_fw_parse_hw_params(struct dw_i2c_dev *dev) > +{ > + struct device *device = dev->dev; > + int ret; > + > + ret = device_property_read_u32(device, "bus-capacitance-pf", &dev->bus_capacitance_pf); > + if (ret || dev->bus_capacitance_pf < 400) Your binding said nothing about some limits here. Something is not complete. You might be missing constraints in the binding. > + dev->bus_capacitance_pf = 100; > + else > + dev->bus_capacitance_pf = 400; > + > + dev->clk_freq_optimized = device_property_read_bool(device, "clk-freq-optimized"); Best regards, Krzysztof