I2C TYPE_114 On U-boot

We analyzd the problem " The clock-frequency of i2c@7000c400 in u-boot dts is 400000,
But we actually measured is 490K" , and found the i2c bus type is TYPE_114 on u-boot, and the clk rate will used new calculation as the picture as follow:

So the actually is not 400K, we measured it with an oscilloscope is about 490K.
Why config i2c bus type to TYPE_114?

Hi: help to support!

just compared how the i2c clock rate is being calculated both in uboot and in kernel.

uboot:

*unsigned rate = CLK_MULT_STD_FAST_MODE **

(clk_div_stdfst_mode + 1) * i2c_bus->speed * 2;

i2c_init_clock(i2c_bus, rate);

kernel:

clk_multiplier = (i2c_dev->low_clock_count +

i2c_dev->high_clock_count + 2);

*clk_multiplier = (i2c_dev->clk_divisor_non_hs_mode + 1);

ret = clk_set_rate(i2c_dev->div_clk,

i2c_dev->bus_clk_rate * clk_multiplier);

Both are setting the i2c clk rate similarly except that in uboot we have an extra multiplication by 2 as highlighted above. Also this doesn’t seem to be fitting into the equation in the comments section:

** SCL = CLK_SOURCE.I2C /*

** (CLK_MULT_STD_FAST_MODE * (I2C_CLK_DIV_STD_FAST_MODE+1) **

* I2C FREQUENCY DIVISOR) as per the T114 TRM (sec 30.3.1).

I am not sure why this extra multiplication is needed in uboot, but I think this is something that can be looked into.

Hi, help to analyze the issue, if we just need i2c clk 400k in uboot, what should we do?

Below could be the change cause it. Could you try to revert it to try.

    i2c: tegra: add standardized clk/reset API support
    
    clk/reset API was tested on T186 platform and previous chip like
    T210/T124 will still use the old APIs.
    
    Bug 200211165

Here’s the bulk of Bryan’s change (mostly for T186, it would appear):
static void i2c_init_controller(struct i2c_bus *i2c_bus)
{
        if (!i2c_bus->speed)
@@ -78,8 +126,12 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
         * here, in section 23.3.1, but in fact we seem to need a factor of
         * 16 to get the right frequency.
         */
+#ifdef CONFIG_TEGRA186
+       i2c_init_clock(i2c_bus, i2c_bus->speed * 2 * 8);
+#else
        clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
                i2c_bus->speed * 2 * 8);
+#endif

        if (i2c_bus->type == TYPE_114) {
                /*
@@ -94,12 +146,17 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
                 * is running, we hang, and we need it for the new calc.
                 */
                int clk_div_stdfst_mode = readl(&i2c_bus->regs->clk_div) >> 16;
+               unsigned rate = CLK_MULT_STD_FAST_MODE *
+                               (clk_div_stdfst_mode + 1) * i2c_bus->speed * 2;
                debug("%s: CLK_DIV_STD_FAST_MODE setting = %d\n", __func__,
                        clk_div_stdfst_mode);

+#ifdef CONFIG_TEGRA186
+               i2c_init_clock(i2c_bus, rate);
+#else
                clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
-                       CLK_MULT_STD_FAST_MODE * (clk_div_stdfst_mode + 1) *
-                       i2c_bus->speed * 2);
+                                      rate);
+#endif
        }


we are used TEGRA210,our code is follow,we print clk_div_stdfst_mode is 25.

i2c_init_controller:

i2c_init_clock(i2c_bus, i2c_bus->speed * 2 * 8);

if (i2c_bus->type == TYPE_114) {
	int clk_div_stdfst_mode = readl(&i2c_bus->regs->clk_div) >> 16;
	unsigned rate = CLK_MULT_STD_FAST_MODE *
			(clk_div_stdfst_mode + 1) * i2c_bus->speed * 2;
	printf("%s: CLK_DIV_STD_FAST_MODE setting = %d\n", __func__,
		clk_div_stdfst_mode);
	printf("scala %s:rate=%d\n",__func__,rate);
	i2c_init_clock(i2c_bus, rate);
}

/* Reset I2C controller. */
i2c_reset_controller(i2c_bus);

/* Configure I2C controller. */
if (i2c_bus->type == TYPE_DVC) {	/* only for DVC I2C */
	struct dvc_ctlr *dvc = (struct dvc_ctlr *)i2c_bus->regs;
	setbits_le32(&dvc->ctrl3, DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK);
}
   funcmux_select(i2c_bus->clk.id, i2c_bus->pinmux_config);

The code is our used for test, the actually i2c clk is 490K.
And we change clk_div_stdfst_mode =1 for test, the actually i2c clk just about 31K.

Please analyze this problem in your R & D department,Thanks!

Please measure the I2C clock on a T210 board (Nano, TX1, etc.) with our Rel32 BSP and see what you get. Stop in U-Boot by pressing any key on the console so you can measure it w/U-Boot settings, then proceed to boot to kernel (via ‘boot’ in the console) and measure it again w/the kernel clock settings.

Hi , we add i2c device in U-boot, and test it is 490K , also we add the same i2c device in Kernel dts 400K, and it is about 392K , it is right in Kernel.

Hi,the issuse you can test yourself, we just used , not create new method.
And I don’t think how difficult it is, you should ask your R & D department, Why this configuration?
we just want to know how to get 400K i2c clk?

HI:
rd1,you could test pin28(ID_I2C_SCL),It could be 400k during uboot, i tested with nano devkit.

HI:
rd1,you could test pin28(ID_I2C_SCL) in 40pin header,It could be 400k during uboot, i tested with nano devkit

what is the ID_I2C_SCL config in uboot?


Tested it with jetpack4.6

what is your L4t version?

Hi, which dts file do you used? And what device does use the ID_I2C_SCL?

default from jetpack, nothing changed.

I didn’t find the device used ID_I2C_SCL in uboot, and ID_I2C_SCL is i2c@7000c000, it is disable in uboot.

Could you check the clock of i2c@7000c000 after boot if uboot disable it.

We had checked it ago, if uboot disbale i2c@7000c000, and kernel dts config 400K, the clk just is 400k from power on.
You also try to test.