高通MSM8953 LK阶段配置使用I2C8

编程入门 行业动态 更新时间:2024-10-27 08:32:53

<a href=https://www.elefans.com/category/jswz/34/1768455.html style=高通MSM8953 LK阶段配置使用I2C8"/>

高通MSM8953 LK阶段配置使用I2C8

项目场景:

	因为项目需要,需要在高通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

本文发布于:2023-06-13 05:21:52,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/674853.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:高通   阶段   LK

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!