高通msm8916 LK阶段配置使用i2c5
来源:互联网 发布:知乎for mac下载 编辑:程序博客网 时间:2024/06/07 15:21
背景:
在调试SLM753某客户项目LCM时,客户使用LVDS的LCM,而msm8916只有一个mipi的接口,所以就是用到了mipi-2-lvds转换芯片:icn6202。这颗芯片需要使用I2C进行配置LVDS屏的时钟和分辨率等信息,以至于LVDS屏可以正常显示。Kernel阶段i2c比较容易使用,只需在dts中配置一个i2c设备即可以使用对应的i2c接口进行数据传输,但是LK阶段的代码就显得蹩脚了,默认只配置了i2c0接口!!其他的i2c都不能使用,所以在不能修改硬件的情况下,调试i2c5成了不能绕开的关口!
解决方法:
注意:本文只介绍LK阶段配置i2c5,并测试i2c5的方法,不介绍i2cn6202的使用方法,谢谢!
1、下图为i2c0和i2c5对应的GPIO口。
i2c0:gpio6&gpio7;i2c5:gpio18&gpio19;
I2c0对应的物理地址为0x78B6000
I2c5对应的物理地址为0x78B9000
2、LK qup_blsp_i2c_init函数剖析
在文件I2c_qup.c(platform\msm_shared)中定义了高通申请i2c的接口:qup_blsp_i2c_init。
申请I2C5:
staticstruct qup_i2c_dev *i2c_dev_6202; i2c_dev_6202= qup_blsp_i2c_init(BLSP_ID_1, QUP_ID_4, 100000, 19200000);
进入qup_blsp_i2c_init函数,修改下面两个函数:
/*Initialize the GPIO for BLSP i2c */ gpio_config_blsp_i2c(blsp_id, qup_id); clock_config_blsp_i2c(blsp_id, qup_id);
首先修改GPIO配置,进入gpio_config_blsp_i2c(blsp_id, qup_id);
加入一个case选项:
case QUP_ID_4: /*configure I2C SDA gpio */ gpio_tlmm_config(18,2, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA,GPIO_DISABLE); /*configure I2C SCL gpio */ gpio_tlmm_config(19,2, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA,GPIO_DISABLE); dprintf(CRITICAL,"eliot : gpio_config_blsp_i2c QUP_ID_4 %d\n",qup_id); break;
进入clock_config_blsp_i2c(blsp_id, qup_id);
屏蔽如下代码:
/* if((blsp_id!= BLSP_ID_1) || (qup_id != QUP_ID_1)) { dprintf(CRITICAL,"Incorrect BLSP-%d or QUP-%d configuration\n", blsp_id, qup_id); ASSERT(0); }*/
然后修改时钟的一些配置,这里比较关键,也比较复杂。
修改
snprintf(clk_name, sizeof(clk_name),"blsp1_qup2_ahb_iface_clk");tosnprintf(clk_name, sizeof(clk_name),"blsp1_qup4_ahb_iface_clk"); 修改snprintf(clk_name, sizeof(clk_name),"gcc_blsp1_qup2_i2c_apps_clk");tosnprintf(clk_name, sizeof(clk_name),"gcc_blsp1_qup4_i2c_apps_clk");
但是我们发现,"blsp1_qup4_ahb_iface_clk"和"gcc_blsp1_qup4_i2c_apps_clk"其实并没有定义!
找到定义的地方,在文件Msm8916-clock.c (platform\msm8916)
时钟列表中加入qup4_i2c这三个时钟:
static struct clk_lookup msm_clocks_8916[]= { CLK_LOOKUP("blsp1_qup2_ahb_iface_clk",gcc_blsp1_ahb_clk.c), CLK_LOOKUP("gcc_blsp1_qup2_i2c_apps_clk_src",gcc_blsp1_qup2_i2c_apps_clk_src.c), CLK_LOOKUP("gcc_blsp1_qup2_i2c_apps_clk",gcc_blsp1_qup2_i2c_apps_clk.c), CLK_LOOKUP("blsp1_qup4_ahb_iface_clk",gcc_blsp1_ahb_clk.c), CLK_LOOKUP("gcc_blsp1_qup4_i2c_apps_clk_src",gcc_blsp1_qup4_i2c_apps_clk_src.c), CLK_LOOKUP("gcc_blsp1_qup4_i2c_apps_clk",gcc_blsp1_qup4_i2c_apps_clk.c),};
注意到每一个时钟名字都和一个结构体相连,所以我们还要补充后面的结构体!
gcc_blsp1_ahb_clk.c同"blsp1_qup2_ahb_iface_clk"一致。
gcc_blsp1_qup4_i2c_apps_clk_src结构体如下:
static struct rcg_clkgcc_blsp1_qup4_i2c_apps_clk_src ={ .cmd_reg = (uint32_t *) GCC_BLSP1_QUP4_CMD_RCGR, .cfg_reg = (uint32_t *) GCC_BLSP1_QUP4_CFG_RCGR, .set_rate = clock_lib2_rcg_set_rate_hid, .freq_tbl = ftbl_gcc_blsp1_qup2_i2c_apps_clk_src, .current_freq= &rcg_dummy_freq, .c= { .dbg_name= "gcc_blsp1_qup4_i2c_apps_clk_src", .ops = &clk_ops_rcg, },};
gcc_blsp1_qup4_i2c_apps_clk结构体如下:
static struct branch_clkgcc_blsp1_qup4_i2c_apps_clk = { .cbcr_reg= GCC_BLSP1_QUP4_APPS_CBCR, .parent = &gcc_blsp1_qup4_i2c_apps_clk_src.c, .c= { .dbg_name= "gcc_blsp1_qup4_i2c_apps_clk", .ops = &clk_ops_branch, },};
此时需要重新定义
#define GCC_BLSP1_QUP4_APPS_CBCR (CLK_CTL_BASE + 0x6020)#define GCC_BLSP1_QUP4_CFG_RCGR (CLK_CTL_BASE + 0x6004)#define GCC_BLSP1_QUP4_CMD_RCGR (CLK_CTL_BASE + 0x6000)
结构体其它部分仿照blsp1_qup2时钟结构体即可。
到目前为止i2c5的申请工作完成,总结起来主要是对代码的跟踪,仿照i2c0(QUP2)对应的GPIO和时钟进行配置。但是寄存器的值就需要查找msm8916有关BLSP相关寄存器文档了!
3、下面介绍LK 如何使用i2c.
读写函数如下:
static int qrd_icn_i2c_read(uint8_taddr) { int ret = 0; intval = 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, &addr}, {Slave_addr, I2C_M_RD, 1, &val} }; ret = qup_i2c_xfer(i2c_dev_6202, msg_buf, 2); dprintf(CRITICAL,"eliot qrd_lcd_i2c_read addr = %d, val = 0x%x\n",addr,val); if(ret < 0) { dprintf(CRITICAL, "qup_i2c_xfer error %d\n", ret); return ret; } return val; } static int qrd_icn_i2c_write(uint8_t addr,uint8_t val){ intret = 0; uint8_tdata_buf[] = { addr, val }; /*Create a i2c_msg buffer, that is used to put the controller into write mode and then to write some data. */ structi2c_msg msg_buf[] = { {Slave_addr, I2C_M_WR, 2, data_buf} }; ret= qup_i2c_xfer(i2c_dev_6202, msg_buf, 1); if(ret< 0) { dprintf(CRITICAL,"eliot qup_i2c_xfer error %d\n", ret); returnret; } return0;}
- 高通msm8916 LK阶段配置使用i2c5
- 高通平台msm8916修改开机logo 高通平台修改LK(bootloader)开机logo
- 高通使用/system/bin/r读取msm8916的gpio配置
- 高通使用/system/bin/r读取msm8916的gpio配置
- 高通LK阶段使用模拟i2c--附i2c子协议smbus-protocol
- Android启动流程分析之一:Bootloader(基于高通芯片) 【mtk lk阶段有类似】
- Qcom LK阶段如何使用ADC介绍
- Qcom LK阶段如何使用I2C介绍
- Qcom LK阶段如何使用ADC介绍
- Qcom LK阶段如何使用ADC介绍
- 基于msm8916移植lcd流程--LK
- 高通msm8916 gpio笔记(基于设备树)
- mms8916 lk阶段ADC
- 高通 MSM8K bootloader 之三: LK
- 高通 MSM8K bootloader 之三: LK
- 高通平台lk下调屏小结
- 高通 MSM8K bootloader 之三: LK
- 高通LCD lk代码跟踪分析
- String,StringBuilder,StringBuffer
- LaTex常用特殊符号对应表
- 请求转发与重定向比较
- 寻呼
- OpenStack-M版(Mitaka)搭建- – -环境准备篇
- 高通msm8916 LK阶段配置使用i2c5
- 标题栏滚动变色
- MyBatis 为类型别名
- hdu1116欧拉道路
- 【1】Hibernate的入门
- UML--实现图(构件图、部署图)
- 解决QT中文5.6 QTextEdit QPlainTextEdit的右键菜单翻译不全
- Webview加载本地图片的方案对比
- 零假设和备择假设