zoukankan      html  css  js  c++  java
  • 高通lk:配置与使用i2c

    高通lk:配置与使用i2c

    以msm8909为例。

    背景

    在lk中要去驱动一个aw9523的ic来控制指示灯。

    但是现在对应的i2c没有打开。因此需要进行处理。

    步骤

    找到I2C对应的ID与句柄

    参考文档:80-nu767-1_l_bam_low-speed_peripherals_(blsp)_user_guide.pdf

    根据其他人的说法,i2c-1对应的是第一个BLSP1、QUP0、0x78B5000。

    添加有关的时钟

    路径:bootable/bootloader/lk/platform/msm8909/msm8909-clock.c

    +
    +// i2c-1
    +static struct clk_freq_tbl ftbl_gcc_blsp1_qup1_i2c_apps_clk_src[] =
    +{
    +	F(      96000,    cxo,  10,   1,  2),
    +	F(    4800000,    cxo,   4,   0,  0),
    +	F(    9600000,    cxo,   2,   0,  0),
    +	F(   16000000,  gpll0,  10,   1,  5),
    +	F(   19200000,  cxo,   1,   0,  0),
    +	F(   25000000,  gpll0,  16,   1,  2),
    +	F(   50000000,  gpll0,  16,   0,  0),
    +	F_END
    +};
    +
    +static struct rcg_clk gcc_blsp1_qup1_i2c_apps_clk_src =
    +{
    +	.cmd_reg      = (uint32_t *) GCC_BLSP1_QUP1_CMD_RCGR,
    +	.cfg_reg      = (uint32_t *) GCC_BLSP1_QUP1_CFG_RCGR,
    +	.set_rate     = clock_lib2_rcg_set_rate_hid,
    +	.freq_tbl     = ftbl_gcc_blsp1_qup1_i2c_apps_clk_src,
    +	.current_freq = &rcg_dummy_freq,
    +
    +	.c = {
    +		.dbg_name = "gcc_blsp1_qup1_i2c_apps_clk_src",
    +		.ops      = &clk_ops_rcg,
    +	},
    +};
    +
    +static struct branch_clk gcc_blsp1_qup1_i2c_apps_clk = {
    +	.cbcr_reg = GCC_BLSP1_QUP1_APPS_CBCR,
    +	.parent   = &gcc_blsp1_qup1_i2c_apps_clk_src.c,
    +
    +	.c = {
    +		.dbg_name = "gcc_blsp1_qup1_i2c_apps_clk",
    +		.ops      = &clk_ops_branch,
    +	},
    +};
    +
    
     static struct rcg_clk gcc_blsp1_qup2_i2c_apps_clk_src =
     {
    @@ -585,6 +623,11 @@ static struct clk_lookup msm_clocks_msm8909[] =
     	CLK_LOOKUP("gcc_blsp1_qup2_i2c_apps_clk", gcc_blsp1_qup2_i2c_apps_clk.c),
     
     
    +	// i2c-1
    +	CLK_LOOKUP("blsp1_qup1_ahb_iface_clk", gcc_blsp1_ahb_clk.c),
    +	CLK_LOOKUP("gcc_blsp1_qup1_i2c_apps_clk_src", gcc_blsp1_qup1_i2c_apps_clk_src.c),
    +	CLK_LOOKUP("gcc_blsp1_qup1_i2c_apps_clk", gcc_blsp1_qup1_i2c_apps_clk.c),
    +
     	CLK_LOOKUP("mdp_ahb_clk", mdp_ahb_clk.c),
     	CLK_LOOKUP("mdss_esc0_clk", mdss_esc0_clk.c),
     	CLK_LOOKUP("mdss_axi_clk", mdss_axi_clk.c),
    

    初始化

    +static void i2c1_init(void)
    +{
    +    static int flag = 1;
    +
    +    dprintf(CRITICAL, "%s : start
    ", __func__);
    +    if(flag != 1)
    +        goto end;
    +    flag = 0;
    +    // i2c-1
    +   /*
    +        1 arg: BLSP ID can be BLSP_ID_1 or BLSP_ID_2
    +        2 arg: QUP ID can be QUP_ID_0 ~ QUP_ID_5
    +        3 arg: I2C CLK. should be 100KHZ, or 400KHz
    +        4 arg: Source clock, should be set @ 19.2MHz
    +        */
    +    i2c_dev = qup_blsp_i2c_init(BLSP_ID_1, QUP_ID_0, 100000, 19200000);
    +    if(!i2c_dev)
    +        dprintf(CRITICAL, "qup_blsp_i2c_init failed 
    ");
    +end :
    +    dprintf(CRITICAL, "%s : end
    ", __func__);
    +
    +}
    

    确保底层的调用没问题:

    路径:bootable/bootloader/lk/platform/msm8909/acpuclock.c

    /* Configure i2c clock */
    void clock_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id)
    {
        uint8_t ret = 0;
        char clk_name[64];
    
        struct clk *qup_clk;
    
        if((blsp_id != BLSP_ID_1) || (qup_id > QUP_ID_5)) {
            dprintf(CRITICAL, "Incorrect BLSP-%d or QUP-%d configuration
    ", blsp_id, qup_id);
            ASSERT(0);
        }
    
        snprintf(clk_name, sizeof(clk_name), "blsp1_qup1_ahb_iface_clk");
    
        ret = clk_get_set_enable(clk_name, 0 , 1);
    
        if (ret) {
            dprintf(CRITICAL, "Failed to enable %s clock
    ", clk_name);
            return;
        }
    
        snprintf(clk_name, sizeof(clk_name), "gcc_blsp1_qup1_i2c_apps_clk");
    
        qup_clk = clk_get(clk_name);
    
        if (!qup_clk) {
            dprintf(CRITICAL, "Failed to get %s
    ", clk_name);
            return;
        }
    
        ret = clk_enable(qup_clk);
    
        if (ret) {
            dprintf(CRITICAL, "Failed to enable %s
    ", clk_name);
            return;
        }
    }
    

    如果匹配不上的话,会导致下面错误:

    Alert!! Requested clock "blsp1_qup1_ahb_iface_clk" is not supported![1140] [1140] Can't find clock with id: blsp1_qup1_ahb_iface_clk
    

    读/写

    +static int write_reg(uint8_t slave_addr, uint8_t reg, uint8_t val)
    +{
    +    int ret = 0;
    +    uint8_t data_buf[] = { reg, val };
    +
    +    /* Create a i2c_msg buffer, that is used to put the controller into write
    +       mode and then to write some data. */
    +    struct i2c_msg msg_buf[] = { {slave_addr, I2C_M_WR, 2, data_buf} };
    +
    +    ret = qup_i2c_xfer(i2c_dev, msg_buf, 1);
    +    if(ret < 0) {
    +        dprintf(CRITICAL, "qup_i2c_xfer error %d
    ", ret);
    +        return ret;
    +    }
    +    return 0;
    +}
    +
    +static int read_reg(uint8_t slave_addr, uint8_t reg, uint8_t *val)
    +{
    +    int ret = 0;
    +    /* Create a i2c_msg buffer, that is used to put the controller into read
    +       mode and then to read some data. */
    +    struct i2c_msg msg_buf[] = {
    +        {slave_addr, I2C_M_WR, 1, &reg},
    +        {slave_addr, I2C_M_RD, 1, val}
    +    };
    +
    +    ret = qup_i2c_xfer(i2c_dev, msg_buf, 2);
    +    if(ret < 0) {
    +        dprintf(CRITICAL, "qup_i2c_xfer error %d
    ", ret);
    +        return ret;
    +    }
    +    return 0;
    +}
    
    如果说我的文章对你有用,只不过是我站在巨人的肩膀上再继续努力罢了。
    若在页首无特别声明,本篇文章由 Schips 经过整理后发布。
    博客地址:https://www.cnblogs.com/schips/
  • 相关阅读:
    [中英对照]INTEL与AT&T汇编语法对比
    用gdb理解C宏(#和##)
    Unix/Linux文件类型及访问权限
    apt-get
    查看ip地址信息和配置临时ip
    修改文件所有者 chown
    修改文件权限 chmod
    tar命令
    PHP magic_quotes_gpc
    chmod命令详细用法
  • 原文地址:https://www.cnblogs.com/schips/p/using_i2c_in_lk_in_qualcomm.html
Copyright © 2011-2022 走看看