项目场景:

 因为项目需要,需要在高通MSM8953平台的LK阶段使用I2C8设备。但是MSM8953平台LK阶段并没有配置好I2C8接口,因此调试I2C8成为当务之急。本文只介绍在LK阶段配置使用I2C5的方法。

调试需要:

1、文档:BAM Low-Speed Peripherals (BLSP) User Guide
查看文档,有I2C介绍如下:

I2c3对应的物理地址为0x78B7000 , 中断IRQ:97 ,时钟信号 clk :clk_gcc_blsp1_qup3_i2c_apps_clk ,
I2c3对应的物理地址为0x7AF8000 , 中断IRQ:302,时钟信号 clk :clk_gcc_blsp2_qup4_i2c_apps_clk
查看产品配置表有:
I2C3:gpio10&gpio11;i2c8:gpio98&gpio99;

I2C Description :1、 arg: BLSP ID can be BLSP_ID_1 or BLSP_ID_22、 arg: QUP ID can be QUP_ID_0:QUP_ID_53、 arg: I2C CLK. should be 100KHZ, or 400KHz4、 arg: Source clock, should be set @ 19.2MHz

解决方案:

1、Initialize the I2C bus.

//mipi_dsi_i2c.c
#define I2C_CLK_FREQ     100000
#define I2C_SRC_CLK_FREQ 19200000int mipi_dsi_i2c_device_init(uint8_t blsp_id, uint8_t qup_id)
{if(BLSP_ID_2 == blsp_id) {i2c8_dev = qup_blsp_i2c_init(blsp_id, qup_id,I2C_CLK_FREQ, I2C_SRC_CLK_FREQ);if(!i2c8_dev) {dprintf(CRITICAL, "mipi_dsi_i2c_device_init() failed\n");return ERR_NOT_VALID;}}else{i2c_dev = qup_blsp_i2c_init(blsp_id, qup_id,I2C_CLK_FREQ, I2C_SRC_CLK_FREQ);if(!i2c_dev) {dprintf(CRITICAL, "mipi_dsi_i2c_device_init() failed\n");return ERR_NOT_VALID;}}return NO_ERROR;
}
//i2c_qup.c
#include <blsp_qup.h>
#include <platform.h>static struct qup_i2c_dev *dev_addr = NULL;
static struct qup_i2c_dev *dev8_addr = NULL;struct qup_i2c_dev *qup_blsp_i2c_init(uint8_t blsp_id, uint8_t qup_id,uint32_t clk_freq, uint32_t src_clk_freq)
{struct qup_i2c_dev *dev;if(BLSP_ID_2 == blsp_id){if (dev8_addr != NULL) {return dev8_addr;}}else {if (dev_addr != NULL) {return dev_addr;}}dev = malloc(sizeof(struct qup_i2c_dev));if (!dev) {return NULL;}dev = memset(dev, 0, sizeof(struct qup_i2c_dev));/* Platform uses BLSP */dev->qup_irq = BLSP_QUP_IRQ(blsp_id, qup_id);dev->qup_base = BLSP_QUP_BASE(blsp_id, qup_id);/* This must be done for qup_i2c_interrupt to work. */if(BLSP_ID_2 == blsp_id)dev8_addr = dev;elsedev_addr = dev;/* Initialize the GPIO for BLSP i2c */gpio_config_blsp_i2c(blsp_id, qup_id);clock_config_blsp_i2c(blsp_id, qup_id);qup_i2c_sec_init(dev, clk_freq, src_clk_freq);return dev;
}

添加I2C8操作函数

// i2c_qup.c
int mipi_dsi_i2c8_read_bytes(uint8_t addr, uint8_t *reg, uint8_t *buf, uint8_t len)
{if (!buf)return ERR_INVALID_ARGS;if(!i2c8_dev)return ERR_NOT_VALID;struct i2c_msg rd_buf[] = {{addr, I2C_M_WR, 2, reg},{addr, I2C_M_RD, len, buf}};int err = qup_i2c_xfer(i2c8_dev, rd_buf, 2);if (err < 0) {dprintf(CRITICAL, "Read reg %x failed\n", (int)reg[0]);return err;}return NO_ERROR;
}int mipi_dsi_i2c8_write_bytes(uint8_t addr, uint8_t *reg, uint32_t len)
{if (!i2c8_dev)return ERR_NOT_VALID;struct i2c_msg msg_buf[] = {{addr, I2C_M_WR, len, reg},};int err = qup_i2c_xfer(i2c8_dev, msg_buf, 1);if (err < 0) {dprintf(CRITICAL, "Write reg %x failed\n", (int)reg[0]);return err;}return NO_ERROR;
}int mipi_dsi_i2c8_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
{if (!buf)return ERR_INVALID_ARGS;if(!i2c8_dev)return ERR_NOT_VALID;struct i2c_msg rd_buf[] = {{addr, I2C_M_WR, 1, &reg},{addr, I2C_M_RD, len, buf}};int err = qup_i2c_xfer(i2c8_dev, rd_buf, 2);if (err < 0) {dprintf(CRITICAL, "Read reg %x failed\n", reg);return err;}return NO_ERROR;
}int mipi_dsi_i2c8_read_byte(uint8_t addr, uint8_t reg, uint8_t *buf)
{if (!buf)return ERR_INVALID_ARGS;return mipi_dsi_i2c8_read(addr, reg, buf, 1);
}int mipi_dsi_i2c8_write_byte(uint8_t addr, uint8_t reg, uint8_t val)
{if (!i2c8_dev)return ERR_NOT_VALID;unsigned char buf[2] = {reg, val};struct i2c_msg msg_buf[] = {{addr, I2C_M_WR, 2, buf},};int err = qup_i2c_xfer(i2c8_dev, msg_buf, 1);if (err < 0) {dprintf(CRITICAL, "Write reg %x failed\n", reg);return err;}return NO_ERROR;
}

声明函数

// mipi_dsi_i2c.hint mipi_dsi_i2c8_read_bytes(uint8_t addr, uint8_t *reg, uint8_t *buf, uint8_t len);
int mipi_dsi_i2c8_write_bytes(uint8_t addr, uint8_t *reg, uint32_t len);
int mipi_dsi_i2c8_read_byte(uint8_t addr, uint8_t reg, uint8_t *buf);
int mipi_dsi_i2c8_write_byte(uint8_t addr, uint8_t reg, uint8_t val);
int mipi_dsi_i2c8_read(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len);

查看文档,可以得知IRQ计算公式为:

#define BLSP_QUP_IRQ(blsp_id, qup_id)          (GIC_SPI_START + 95 + (blsp_id-1)*204 + qup_id)

物理地址计算公式为:

#define BLSP_QUP_BASE(blsp_id, qup_id) (PERIPH_SS_BASE + ((blsp_id) - 1) * 0x240000 \+ 0xB5000 + 0x1000 * (qup_id))

2、 Configure the GPIO.

// bootloader/lk/platform/msm8953/gpio.c
#define GPIO_BLSP1_ACTIVE_1 10
#define GPIO_BLSP1_ACTIVE_2 11#define GPIO_BLSP2_ACTIVE_1 98
#define GPIO_BLSP2_ACTIVE_2 99void gpio_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id)
{if(blsp_id == BLSP_ID_1) {switch (qup_id) {case QUP_ID_2:/* configure I2C SDA gpio */gpio_tlmm_config(GPIO_BLSP1_ACTIVE_1, 2, GPIO_OUTPUT,GPIO_NO_PULL, GPIO_6MA, GPIO_ENABLE);/* configure I2C SCL gpio */gpio_tlmm_config(GPIO_BLSP1_ACTIVE_2, 2, GPIO_OUTPUT,GPIO_NO_PULL, GPIO_6MA, GPIO_ENABLE);break;default:dprintf(CRITICAL, "Incorrect QUP id %d\n", qup_id);ASSERT(0);};}else if(blsp_id == BLSP_ID_2) {switch (qup_id) {case QUP_ID_3:/* configure I2C SDA gpio */gpio_tlmm_config(GPIO_BLSP2_ACTIVE_1, 1, GPIO_OUTPUT,GPIO_PULL_UP, GPIO_6MA, GPIO_ENABLE);/* configure I2C SCL gpio */gpio_tlmm_config(GPIO_BLSP2_ACTIVE_2, 1, GPIO_OUTPUT,GPIO_PULL_UP, GPIO_6MA, GPIO_ENABLE);break;default:dprintf(CRITICAL, "Incorrect QUP id %d\n", qup_id);ASSERT(0);};}    else {dprintf(CRITICAL, "Incorrect BLSP id %d\n",blsp_id);ASSERT(0);}
}

3、Register a clock.

// bootable/bootloader/lk/platform/msm8953/acpuclock.c.
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 && blsp_id != BLSP_ID_2)) {dprintf(CRITICAL, "Incorrect BLSP-%d or QUP-%d configuration\n",blsp_id, qup_id);ASSERT(0);}if(blsp_id == BLSP_ID_1){if (qup_id == QUP_ID_2) {snprintf(clk_name, sizeof(clk_name), "blsp1_qup3_ahb_iface_clk");}else if (qup_id == QUP_ID_3) {snprintf(clk_name, sizeof(clk_name), "blsp1_qup4_ahb_iface_clk");}}if(blsp_id == BLSP_ID_2){if (qup_id == QUP_ID_3) {snprintf(clk_name, sizeof(clk_name), "blsp2_qup4_ahb_iface_clk");}}ret = clk_get_set_enable(clk_name, 0 , 1);if (ret) {dprintf(CRITICAL, "Failed to enable %s clock\n", clk_name);return;}if(blsp_id == BLSP_ID_1){if (qup_id == QUP_ID_2) {snprintf(clk_name, sizeof(clk_name), "gcc_blsp1_qup3_i2c_apps_clk");}else if (qup_id == QUP_ID_3) {snprintf(clk_name, sizeof(clk_name), "gcc_blsp1_qup4_i2c_apps_clk");}}if(blsp_id == BLSP_ID_2){if (qup_id == QUP_ID_3) {snprintf(clk_name, sizeof(clk_name), "gcc_blsp2_qup4_i2c_apps_clk");}}qup_clk = clk_get(clk_name);if (!qup_clk) {dprintf(CRITICAL, "Failed to get %s\n", clk_name);return;}ret = clk_enable(qup_clk);if (ret) {dprintf(CRITICAL, "Failed to enable %s\n", clk_name);return;}
}
// bootable/bootloader/lk/platform/msm8953/msm8953-clock.c.static struct vote_clk gcc_blsp2_ahb_clk = {.cbcr_reg     = (uint32_t *) BLSP2_AHB_CBCR,.vote_reg     = (uint32_t *) APCS_CLOCK_BRANCH_ENA_VOTE,.en_mask      = BIT(20),.c = {.dbg_name = "gcc_blsp2_ahb_clk",.ops      = &clk_ops_vote,},
};static struct clk_freq_tbl ftbl_gcc_blsp1_qup2_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,  gpll0,   1,   0,  0),F(   25000000,  gpll0,  16,   1,  2),F(   50000000,  gpll0,  16,   0,  0),F_END
};static struct rcg_clk gcc_blsp1_qup2_i2c_apps_clk_src = {.cmd_reg      = (uint32_t *) GCC_BLSP1_QUP2_CMD_RCGR,.cfg_reg      = (uint32_t *) GCC_BLSP1_QUP2_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_qup2_i2c_apps_clk_src",.ops      = &clk_ops_rcg,},
};static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = {.cbcr_reg = (uint32_t *) GCC_BLSP1_QUP2_APPS_CBCR,.parent   = &gcc_blsp1_qup2_i2c_apps_clk_src.c,.c = {.dbg_name = "gcc_blsp1_qup2_i2c_apps_clk",.ops      = &clk_ops_branch,},
};static struct clk_freq_tbl ftbl_gcc_blsp1_qup3_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,  gpll0,   1,   0,  0),F(   25000000,  gpll0,  16,   1,  2),F(   50000000,  gpll0,  16,   0,  0),F_END
};#if 0
static struct clk_freq_tbl ftbl_gcc_blsp2_qup4_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,  gpll0,   1,   0,  0),F(   25000000,  gpll0,  16,   1,  2),F(   50000000,  gpll0,  16,   0,  0),F_END
};
#endifstatic struct rcg_clk gcc_blsp1_qup3_i2c_apps_clk_src = {.cmd_reg      = (uint32_t *) GCC_BLSP1_QUP3_CMD_RCGR,.cfg_reg      = (uint32_t *) GCC_BLSP1_QUP3_CFG_RCGR,.set_rate     = clock_lib2_rcg_set_rate_hid,.freq_tbl     = ftbl_gcc_blsp1_qup3_i2c_apps_clk_src,.current_freq = &rcg_dummy_freq,.c = {.dbg_name = "gcc_blsp1_qup3_i2c_apps_clk_src",.ops      = &clk_ops_rcg,},
};static struct rcg_clk gcc_blsp2_qup4_i2c_apps_clk_src = {.cmd_reg      = (uint32_t *) GCC_BLSP2_QUP4_CMD_RCGR,.cfg_reg      = (uint32_t *) GCC_BLSP2_QUP4_CFG_RCGR,.set_rate     = clock_lib2_rcg_set_rate_hid,
//  .freq_tbl     = ftbl_gcc_blsp2_qup4_i2c_apps_clk_src,.freq_tbl   = ftbl_gcc_blsp1_qup3_i2c_apps_clk_src,.current_freq = &rcg_dummy_freq,.c = {.dbg_name = "gcc_blsp2_qup4_i2c_apps_clk_src",.ops      = &clk_ops_rcg,},
};static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = {.cbcr_reg = (uint32_t *) GCC_BLSP1_QUP3_APPS_CBCR,.parent   = &gcc_blsp1_qup3_i2c_apps_clk_src.c,.c = {.dbg_name = "gcc_blsp1_qup3_i2c_apps_clk",.ops      = &clk_ops_branch,},
};static struct branch_clk gcc_blsp2_qup4_i2c_apps_clk = {.cbcr_reg = (uint32_t *) GCC_BLSP2_QUP4_APPS_CBCR,.parent   = &gcc_blsp2_qup4_i2c_apps_clk_src.c,.c = {.dbg_name = "gcc_blsp2_qup4_i2c_apps_clk",.ops      = &clk_ops_branch,},
};static struct clk_freq_tbl ftbl_mdss_esc1_1_clk[] = {F_MM(19200000,    cxo,   1,   0,   0),F_END
};static struct rcg_clk dsi_esc1_clk_src = {.cmd_reg  = (uint32_t *) DSI_ESC1_CMD_RCGR,.cfg_reg  = (uint32_t *) DSI_ESC1_CFG_RCGR,.set_rate = clock_lib2_rcg_set_rate_hid,.freq_tbl = ftbl_mdss_esc1_1_clk,.c        = {.dbg_name = "dsi_esc1_clk_src",.ops      = &clk_ops_rcg,},
};static struct branch_clk mdss_esc1_clk = {.cbcr_reg    = (uint32_t *) DSI_ESC1_CBCR,.parent      = &dsi_esc1_clk_src.c,.has_sibling = 0,.c           = {.dbg_name = "mdss_esc1_clk",.ops      = &clk_ops_branch,},
};static struct clk_lookup msm_clocks_8953[] =
{...
/*add start by Yubel for blsp 20200730 *//* BLSP CLOCKS */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_qup3_ahb_iface_clk", gcc_blsp1_ahb_clk.c),CLK_LOOKUP("gcc_blsp1_qup3_i2c_apps_clk_src",gcc_blsp1_qup3_i2c_apps_clk_src.c),CLK_LOOKUP("gcc_blsp1_qup3_i2c_apps_clk",gcc_blsp1_qup3_i2c_apps_clk.c),CLK_LOOKUP("blsp2_qup4_ahb_iface_clk", gcc_blsp2_ahb_clk.c),CLK_LOOKUP("gcc_blsp2_qup4_i2c_apps_clk_src",gcc_blsp2_qup4_i2c_apps_clk_src.c),CLK_LOOKUP("gcc_blsp2_qup4_i2c_apps_clk",gcc_blsp2_qup4_i2c_apps_clk.c),/*add end by Yubel 20200730 */
...
};

通过kernel中配置I2C的代码可知

#define GCC_BLSP1_QUP3_APPS_CBCR    (CLK_CTL_BASE + 0x04020)
#define GCC_BLSP1_QUP3_CFG_RCGR     (CLK_CTL_BASE + 0x04004)
#define GCC_BLSP1_QUP3_CMD_RCGR     (CLK_CTL_BASE + 0x04000)#define GCC_BLSP1_QUP2_APPS_CBCR    (CLK_CTL_BASE + 0x03010)
#define GCC_BLSP1_QUP2_CFG_RCGR     (CLK_CTL_BASE + 0x03004)
#define GCC_BLSP1_QUP2_CMD_RCGR     (CLK_CTL_BASE + 0x03000)#define BLSP2_AHB_CBCR              (CLK_CTL_BASE + 0x0B008)#define GCC_BLSP2_QUP4_APPS_CBCR    (CLK_CTL_BASE + 0x18020)
#define GCC_BLSP2_QUP4_CFG_RCGR     (CLK_CTL_BASE + 0x18004)
#define GCC_BLSP2_QUP4_CMD_RCGR     (CLK_CTL_BASE + 0x18000)

测试用例

// bootable/bootloader/lk/app/tests/my_i2c_test.c.
#include <ctype.h>
#include <debug.h>
#include <stdlib.h>
#include <printf.h>
#include <list.h>
#include <string.h>
#include <arch/ops.h>
#include <platform.h>
#include <platform/debug.h>
#include <kernel/thread.h>
#include <kernel/timer.h>
#ifdef WITH_LIB_CONSOLE
#include <lib/console.h>
static int cmd_i2c_test(int argc, const cmd_args *argv);
STATIC_COMMAND_START{ "i2c_test", "i2c test cmd", &cmd_i2c_test },
STATIC_COMMAND_END(my_i2c_test);
static int cmd_i2c_test(int argc, const cmd_args *argv)
{printf("Entering i2c_test\n");return 0;
}
#endif

高通MSM8953 LK阶段配置使用I2C8相关推荐

  1. 高通平台lk阶段logo修改

    高通平台lk阶段logo修改: 1.通过logo图片得到要显示的数组: 运行"ffmpeg -i logo.png -f rawvideo -pix_fmt bgr24 logo.raw&q ...

  2. 高通平台android 环境配置编译及开发经验总结

    完全转自:http://blog.csdn.net/dongwuming/article/details/12784535 1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通 ...

  3. 高通平台android 环境配置编译及开发经验总结【转】

    1.高通平台android开发总结 1.1 搭建高通平台环境开发环境 在高通开发板上烧录文件系统 建立高通平台开发环境 高通平台,android和 modem 编译流程分析 高通平台 7620 启动流 ...

  4. 高通APQ8074 spi 接口配置

    高通APQ8074 spi 接口配置 8074 平台含有两个BLSP(BAM Low-Speed Peripheral) , 每一个BLSP含有两个QUP, 每一个QUP可以被配置为I2C, SPI, ...

  5. Qcom 平台 LK 阶段配置 I2C

    qcom平台LK 阶段配置IIC 版本号:V 1.0 作者:Leo 目录 目录... 1 前言... 4 1.      确定硬件... 4 2.      LK I2C 函数接口... 5 2.1 ...

  6. 高通ais cam.xml配置

    高通ais cam.xml配置 参数解析代码:         else if ((!xmlStrcmp(cur->name, (const xmlChar *)"display_se ...

  7. 高通7x27a平台UART配置

    高通7x27a平台使用uart1作为debug的配置 高通7x27a平台一共有5个UART PORT: Port 对应的GPIO 描述 UART1 122+123 Can used for debug ...

  8. 高通打开内核阶段串口log

    高通项目一般进行到一定阶段,系统组的同事为了优化开机时间,就会把内核阶段的串口log关闭. 这点如果出了问题就很不方便,说一下如何把内核的串口log打开 以K89441AA1项目为例 android/ ...

  9. 高通相机系统-usecase配置

    高通相机系统用usecase描述一个相机的使用场景.相机场景配置以序列化的形式保存在g_sm8350_usecase.xml.工程构建阶段配置转换脚本usecaseconverter.pl解析这些us ...

最新文章

  1. Python——cmd调用(os.system阻塞处理)(多条命令执行)
  2. 5.3.3 TCP可靠传输
  3. Evernote相关技术介绍——mysql+lucene+tomcat
  4. 可恶的.NET FRAME,将一切变得更简单,还是更复杂?
  5. Xcode 11 新建项目适配 iOS 13 以下设备
  6. Planes, Trains, but not Automobiles-求最小路径覆盖的起点终点
  7. React开发(215):React中的Fragments的动机
  8. mysql sum_MySQL中的SUM函数使用教程
  9. eviews 9.5新版本——平均预测、面板效应检验
  10. 【luogu2272】 [ZJOI2007]最大半连通子图 [tarjan 缩点][拓扑排序]
  11. 太阳高度角计算题_正午太阳高度变化及计算(模拟题组)
  12. 在线IDE的原理及设计思路 以Java为例
  13. REST风格详细介绍
  14. 组合数学 —— 母函数
  15. Hadoop 如何退出安全模式
  16. 小C实例也有大梦想——自定义strlen函数
  17. [P3975][TJOI2015]弦论(后缀数组)
  18. iphone一键转移_iPhone 12换机首选,QQ同步助手一键智能备份迁移
  19. Netty 之 TCP粘包拆包场景
  20. mysql MHA的工作原理

热门文章

  1. 解释机器学习中的熵、联合熵、条件熵、相对熵和交叉熵
  2. Origin Pro2017 不等间距图
  3. python好用的编程工具
  4. 电商平台-安全设计与架构
  5. torchtext field.build_vocab问题
  6. Python Pathlib 详解
  7. Java Web入门之JSTL标签的解析及使用(超详细必看)
  8. css样式的优先顺序
  9. norflash的基本操作
  10. 使用python实现固定效应模型