在驱动的dts中修改: qcom,clk-freq-out = <400000>;//速率
arch/arm64/boot/dts/qcom/msm8953.dtsi
i2c_2: i2c@78b6000 { /* BLSP1 QUP2 */
compatible = "qcom,i2c-msm-v2";
#address-cells = <1>;
#size-cells = <0>;
reg-names = "qup_phys_addr";
reg = <0x78b6000 0x600>;
interrupt-names = "qup_irq";
interrupts = <0 96 0>;
qcom,clk-freq-out = <400000>;//速率
qcom,clk-freq-in = <19200000>;
clock-names = "iface_clk", "core_clk";
clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
<&clock_gcc clk_gcc_blsp1_qup2_i2c_apps_clk>;
pinctrl-names = "i2c_active", "i2c_sleep";
pinctrl-0 = <&i2c_2_active>;
pinctrl-1 = <&i2c_2_sleep>;
qcom,noise-rjct-scl = <0>;
qcom,noise-rjct-sda = <0>;
qcom,master-id = <86>;
dmas = <&dma_blsp1 6 64 0x20000020 0x20>,
<&dma_blsp1 7 32 0x20000020 0x20>;
dma-names = "tx", "rx";
status = "disabled";
};
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 = <100000>;//速率
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,master-id = <86>;
dmas = <&dma_blsp1 8 64 0x20000020 0x20>,
<&dma_blsp1 9 32 0x20000020 0x20>;
dma-names = "tx", "rx";
status = "disabled";
};
i2c对应的gpio控制,不用修改
arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
i2c_2 {
i2c_2_active: i2c_2_active {
/* active state */
mux {
pins = "gpio6", "gpio7";
function = "blsp_i2c2";
};
config {
pins = "gpio6", "gpio7";
drive-strength = <2>;
bias-disable;
};
};
i2c_2_sleep: i2c_2_sleep {
/* suspended state */
mux {
pins = "gpio6", "gpio7";
function = "gpio";
};
config {
pins = "gpio6", "gpio7";
drive-strength = <2>;
bias-disable;
};
};
};
i2c_3 {
i2c_3_active: i2c_3_active {
/* active state */
mux {
pins = "gpio10", "gpio11";
function = "blsp_i2c3";
};
config {
pins = "gpio10", "gpio11";
drive-strength = <2>;
bias-disable;
};
};
i2c_3_sleep: i2c_3_sleep {
/* suspended state */
mux {
pins = "gpio10", "gpio11";
function = "gpio";
};
config {
pins = "gpio10", "gpio11";
drive-strength = <2>;
bias-disable;
};
};
};
不同从设备如何配置i2c速率:
方法一:在总线中根据从设备地址进行配置,比如将从设备地址为0x28的i2c速率改为1m
方法2:在从设备的驱动中进行配置,通过adapter找到i2c所在总线
1 、从设备结构体如下:
struct i2c_client {
unsigned short flags; /* div., see below */
#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
/* Must equal I2C_M_TEN below */
#define I2C_CLIENT_SLAVE 0x20 /* we are the slave */
#define I2C_CLIENT_HOST_NOTIFY 0x40 /* We want to use I2C host notify */
#define I2C_CLIENT_WAKE 0x80 /* for board_info; true iff can wake */
#define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */
/* Must match I2C_M_STOP|IGNORE_NAK */
unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */
/* _LOWER_ 7 bits */
char name[I2C_NAME_SIZE];
struct i2c_adapter *adapter; /* the adapter we sit on */-------//关键成员
struct device dev; /* the device structure */
int init_irq; /* irq set at initialization */
int irq; /* irq issued by device */
struct list_head detected;
#if IS_ENABLED(CONFIG_I2C_SLAVE)
i2c_slave_cb_t slave_cb; /* callback for slave mode */
#endif
};
2 、i2c总线驱动的device如下:
struct geni_i2c_dev {
struct geni_se se;
u32 tx_wm;
int irq;
int err;
struct i2c_adapter adap;---------------------------------------//关键成员
struct completion done;
struct i2c_msg *cur;
int cur_wr;
int cur_rd;
spinlock_t lock;
u32 clk_freq_out;
const struct geni_i2c_clk_fld *clk_fld;
int suspended;
void *dma_buf;
size_t xfer_len;
dma_addr_t dma_addr;
};
3 、配置接口 qcom_geni_i2c_conf
初始化的过程配置方式如下:
通过dts配置属性:qcom,clk-freq-out
然后,驱动根据属性值查找对应的速率(geni_i2c_clk_map_idx),然后配置寄存器(qcom_geni_i2c_conf):