foreword
This article records the records made when debugging an I2C device communication exception on the Qualcomm platform and trying to modify the I2C clock rate.
Platform: MSM8953.
System: Android 9.0
Category: I2C CLK
in conclusion
Let me talk about the conclusion first. After analysis and verification, the I2C features supported by the platform are as follows.
Default speed: 100K.
Support speed: 100K, 400K, 1M
Support range: 50K ~ 1M
Register description
The period and rate of CLK can be determined by configuring the register of the high and low level duration of I2C CLK.
The register description is as follows
It can be seen from here that since the high and low level configuration registers are all 8bit, the maximum value is 255.
According to the current clock source 19.2M, fs_div = 2hs_div, the minimum clock rate is:
clk-Min = 19.2 M / (255 + 255/2 + 6 ) = 49.42K, rounded to 50K
Calculation formula
I2C_FS_CLK = I2C_CLK/(fs_div+hs_div+6)
Here, I2C_CLK is 19200000,19.2M
100K CLK configuration example:
19.2M (CXO) /100K(transfer rate) = fs_div+hs_div+6
In general fs_div = 2hs_div
That's why the default 100K configuration is: 124/62, fs_div+hs_div+6 = 192.
code modification
dts node configuration
kernel\msm-4.9\arch\arm64\boot\dts\nwy\XXX_msm8953.dtsi
The I2C node is modified to 50K configuration as follows:
i2c_3: i2c@78b7000 { /* BLSP1 QUP3 */
compatible = "qcom,i2c-msm-v2";
#address-cells = <1>;
#size-cells = <0>;
reg-names = "qup_phys_addr";
reg = <0x78b7000 0x600>;
interrupt-names = "qup_irq";
interrupts = <0 97 0>;
- qcom,clk-freq-out = <400000>; // 默认400K
+ qcom,clk-freq-out = <50000>; // 修改为 50K 输出
qcom,clk-freq-in = <19200000>;
clock-names = "iface_clk", "core_clk";
clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
<&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>;
pinctrl-names = "i2c_active", "i2c_sleep";
pinctrl-0 = <&i2c_3_active>;
pinctrl-1 = <&i2c_3_sleep>;
qcom,noise-rjct-scl = <0>;
qcom,noise-rjct-sda = <0>;
qcom,fs-clk-div = <252>; // clk High 电平持续时间,非必须项
qcom,high-time-clk-div = <126>; // clk Low 电平持续时间,非必须项
qcom,master-id = <86>;
dmas = <&dma_blsp1 8 64 0x20000020 0x20>,
<&dma_blsp1 9 32 0x20000020 0x20>;
dma-names = "tx", "rx";
status = "disabled";
};
I2C driver files add clk table
8953_APP_P\kernel\msm-4.9\drivers\i2c\busses\i2c-msm-v2.c
This table is the currently supported I2C rate, and the corresponding high and low level duration parameters. [Refer to the previous chapter for parameter configuration]
If there is no required rate, add a new group, such as adding 50M rate.
/*
* divider values as per HW Designers
*/
static struct i2c_msm_clk_div_fld i2c_msm_clk_div_map[] = {
+ {KHz(50), 252, 126},
{KHz(100), 124, 62},
{KHz(400), 28, 14},
{KHz(1000), 8, 5},
};
references
80-NU767-1_LINUX BAM LOW-SPEED PERIPHERALS CONFIGURATION AND DEBUG GUIDE.pdf