前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >i2c接口可以接哪些器件_单片机i2c接口

i2c接口可以接哪些器件_单片机i2c接口

作者头像
全栈程序员站长
发布2022-11-02 15:42:58
7020
发布2022-11-02 15:42:58
举报

项目中I2C6所对应的gpio口为22和23

i2c接口可以接哪些器件_单片机i2c接口
i2c接口可以接哪些器件_单片机i2c接口

由上表可以确定以下信息:

a) QUP ID:BLSP6

b) QUP BASE Addr:7AF6000

c) IRQ:300

d) src clk:clk_gcc_blsp2_qup2_i2c_apps_clk

1、高通在lk阶段已经存在I2C的初始化代码

路径:bootable/bootloader/lk/platform/msm_shard/i2c_qup.c

i2c接口可以接哪些器件_单片机i2c接口
i2c接口可以接哪些器件_单片机i2c接口

在初始化代码中qup_blsp_i2c_init为i2c接口函数,其中调用了两个重要函数gpio_config_blsp_i2c和clock_config_blsp_i2c,分别用于i2c的gpio和时钟clock的设置,BLSP_QUP_IRQ这个宏用来给中断号赋值。

2、添加中断号定义代码:

diff –git a/platform/msm8952/include/platform/irqs.h b/platform/msm8952/include/platform/irqs.h index 59408bd87..388be802a 100644 — a/platform/msm8952/include/platform/irqs.h +++ b/platform/msm8952/include/platform/irqs.h @@ -60,6 +60,7 @@ #define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + \ NR_BOARD_IRQS) – +//#define BLSP_QUP_IRQ(blsp_id, qup_id) (GIC_SPI_START + 101 + qup_id) +#define BLSP_QUP_IRQ(blsp_id, qup_id) (GIC_SPI_START + 95 + (blsp_id-1)*204 + qup_id) #define SMD_IRQ (GIC_SPI_START + 168) #endif /* __IRQS_MSM8952_H */

其中GIC_SPI_START为一个偏移量,blsp_id为2,qup_id为1,即中断号为300

3、I2C初始化时调用gpio和时钟的配置函数添加如下

gpio设置文件添加函数代码:

diff –git a/platform/msm8952/gpio.c b/platform/msm8952/gpio.c old mode 100644 new mode 100755 index 05b4977ec..72a3f6919 — a/platform/msm8952/gpio.c +++ b/platform/msm8952/gpio.c @@ -70,3 +70,46 @@ void gpio_config_uart_dm(uint8_t id) gpio_tlmm_config(4, 2, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_8MA, GPIO_DISABLE); } +void gpio_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id) +{ + if(blsp_id == BLSP_ID_1) { + switch (qup_id) { + case QUP_ID_1: + /* configure I2C SDA gpio */ + gpio_tlmm_config(6, 3, GPIO_OUTPUT, GPIO_NO_PULL, + GPIO_8MA, GPIO_DISABLE); + + /* configure I2C SCL gpio */ + gpio_tlmm_config(7, 3, GPIO_OUTPUT, GPIO_NO_PULL, + GPIO_8MA, GPIO_DISABLE); + break; + case QUP_ID_3: + /* configure I2C SDA gpio */ + gpio_tlmm_config(14, 2, GPIO_OUTPUT, GPIO_NO_PULL, + GPIO_8MA, GPIO_DISABLE); + + /* configure I2C SCL gpio */ + gpio_tlmm_config(15, 2, GPIO_OUTPUT, GPIO_NO_PULL, + GPIO_8MA, GPIO_DISABLE); + 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_1: + gpio_tlmm_config(22, 3, GPIO_OUTPUT, GPIO_NO_PULL, + GPIO_8MA, GPIO_DISABLE); + gpio_tlmm_config(23, 3, GPIO_OUTPUT, GPIO_NO_PULL, + GPIO_8MA, GPIO_DISABLE); + 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); + } +} \ No newline at end of file

diff –git a/platform/msm8952/include/platform/gpio.h b/platform/msm8952/include/platform/gpio.h index b4d12e818..4d4dcd1cf 100644 — a/platform/msm8952/include/platform/gpio.h +++ b/platform/msm8952/include/platform/gpio.h @@ -69,4 +69,5 @@ void gpio_tlmm_config(uint32_t gpio, uint8_t pull, uint8_t drvstr, uint32_t enable); +void gpio_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id); #endif

时钟设置文件添加函数代码:

diff –git a/platform/msm8952/acpuclock.c b/platform/msm8952/acpuclock.c old mode 100644 new mode 100755 index 9efe09b4f..7c9315ba2 — a/platform/msm8952/acpuclock.c +++ b/platform/msm8952/acpuclock.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #define MAX_LOOPS 500 @@ -507,3 +508,86 @@ void clock_config_ce(uint8_t instance) clock_ce_enable(instance); } +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(((qup_id != QUP_ID_1) && (qup_id != QUP_ID_3))) { + 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_1) { + snprintf(clk_name, sizeof(clk_name), “blsp1_qup2_ahb_iface_clk”); + } + else if (qup_id == QUP_ID_3) { + snprintf(clk_name, sizeof(clk_name), “blsp1_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 (qup_id == QUP_ID_1) { + snprintf(clk_name, sizeof(clk_name), “gcc_blsp1_qup2_i2c_apps_clk”); + } + else if (qup_id == QUP_ID_3) { + snprintf(clk_name, sizeof(clk_name), “gcc_blsp1_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; + } + } else if (blsp_id == BLSP_ID_2){ + if (qup_id == QUP_ID_1) { + snprintf(clk_name, sizeof(clk_name), “blsp2_qup2_ahb_iface_clk”); + } + else 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 (qup_id == QUP_ID_1) { + snprintf(clk_name, sizeof(clk_name), “gcc_blsp2_qup2_i2c_apps_clk”); + } + else 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; + } + } +} diff –git a/platform/msm8952/include/platform/clock.h b/platform/msm8952/include/platform/clock.h index e6734cb27..cbd1ba46f 100644 — a/platform/msm8952/include/platform/clock.h +++ b/platform/msm8952/include/platform/clock.h @@ -99,4 +99,5 @@ void gcc_dsi_hs_clocks_enable(uint32_t flags, bool use_dsi1_pll, uint8_t pclk0_ uint8_t pclk0_n, uint8_t pclk0_d); void gcc_dsi_lp_clock_enable(uint32_t flags); void gcc_dsi_clocks_disable(uint32_t flags); +void clock_config_blsp_i2c(uint8_t blsp_id, uint8_t qup_id); #endif 添加时钟的配置及序列,主要添加三个与时钟相关结构体

diff –git a/platform/msm8952/msm8952-clock.c b/platform/msm8952/msm8952-clock.c old mode 100644 new mode 100755 index 85d506987..f9bebfe9f — a/platform/msm8952/msm8952-clock.c +++ b/platform/msm8952/msm8952-clock.c @@ -206,6 +206,19 @@ static struct rcg_clk sdcc1_apps_clk_src = }, }; +/* BLSP2_QUP2 Clocks */ +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 branch_clk gcc_sdcc1_apps_clk = { .cbcr_reg = (uint32_t *) SDCC1_APPS_CBCR, @@ -594,6 +607,37 @@ static struct vote_clk gcc_ce1_axi_clk = { }, }; +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 rcg_clk gcc_blsp2_qup2_i2c_apps_clk_src = +{ + .cmd_reg = (uint32_t *) GCC_BLSP2_QUP2_CMD_RCGR, + .cfg_reg = (uint32_t *) GCC_BLSP2_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_blsp2_qup2_i2c_apps_clk_src”, + .ops = &clk_ops_rcg, + }, +}; +static struct branch_clk gcc_blsp2_qup2_i2c_apps_clk = { + .cbcr_reg = (uint32_t *) GCC_BLSP2_QUP2_APPS_CBCR, + .parent = &gcc_blsp2_qup2_i2c_apps_clk_src.c, + .c = { + .dbg_name = “gcc_blsp2_qup2_i2c_apps_clk”, + .ops = &clk_ops_branch, + }, +}; +

在时钟查找列表中添加如下函数代码: /* Clock lookup table */ static struct clk_lookup msm_clocks_8952[] = { @@ -621,6 +665,9 @@ static struct clk_lookup msm_clocks_8952[] = CLK_LOOKUP(“ce1_axi_clk”, gcc_ce1_axi_clk.c), CLK_LOOKUP(“ce1_core_clk”, gcc_ce1_clk.c), CLK_LOOKUP(“ce1_src_clk”, ce1_clk_src.c), + CLK_LOOKUP(“blsp2_qup2_ahb_iface_clk”, gcc_blsp2_ahb_clk.c), + CLK_LOOKUP(“gcc_blsp2_qup2_i2c_apps_clk_src”, gcc_blsp2_qup2_i2c_apps_clk_src.c), + CLK_LOOKUP(“gcc_blsp2_qup2_i2c_apps_clk”, gcc_blsp2_qup2_i2c_apps_clk.c), }; void msm8956_clock_override() diff –git a/platform/msm_shared/rules.mk b/platform/msm_shared/rules.mk index c64acf027..57f833189 100755 — a/platform/msm_shared/rules.mk +++ b/platform/msm_shared/rules.mk @@ -634,6 +634,7 @@ DEFINES += DISPLAY_NONE_LK_MENU=1 (LOCAL_DIR)/crypto_hash.o \ (LOCAL_DIR)/crypto5_eng.o \ (LOCAL_DIR)/crypto5_wrapper.o \ + (LOCAL_DIR)/i2c_qup.o \ (LOCAL_DIR)/mdp5.o \ (LOCAL_DIR)/display.o \

配置I2C的时钟参数:

diff –git a/platform/msm8952/include/platform/iomap.h b/platform/msm8952/include/platform/iomap.h old mode 100644 new mode 100755 index 057d909f2..3e016fcff — a/platform/msm8952/include/platform/iomap.h +++ b/platform/msm8952/include/platform/iomap.h @@ -101,6 +101,15 @@ #define GCC_CRYPTO_CBCR (CLK_CTL_BASE + 0x1601C) #define GCC_CRYPTO_AXI_CBCR (CLK_CTL_BASE + 0x16020) #define GCC_CRYPTO_AHB_CBCR (CLK_CTL_BASE + 0x16024) +#define BLSP_QUP_BASE(blsp_id, qup_id) ((blsp_id == 1) ? (PERIPH_SS_BASE + 0xB5000 \ + + (qup_id * 0x1000)) :\ + (PERIPH_SS_BASE + 0x2f5000 + \ + (qup_id * 0x1000))) + +#define BLSP2_AHB_CBCR (CLK_CTL_BASE + 0xB008) //0x0B008 +#define GCC_BLSP2_QUP2_APPS_CBCR (CLK_CTL_BASE + 0xD010) +#define GCC_BLSP2_QUP2_CFG_RCGR (CLK_CTL_BASE + 0xD004) +#define GCC_BLSP2_QUP2_CMD_RCGR (CLK_CTL_BASE + 0xD000)

4、添加I2C测试程序

diff –git a/app/aboot/aboot.c b/app/aboot/aboot.c index 16717dee5..87375893e 100755 — a/app/aboot/aboot.c +++ b/app/aboot/aboot.c @@ -95,6 +95,12 @@ #include #include #include “fastboot_test.h” +#include +#include +#include +#include +#include +#include extern bool target_use_signed_kernel(void); extern void platform_uninit(void); @@ -326,6 +332,8 @@ struct getvar_partition_info { #define EXT_MAGIC_OFFSET_SB 0x38 #define F2FS_MAGIC 0xF2F52010 // F2FS Magic Number #define F2FS_MAGIC_OFFSET_SB 0x0 +#define EXTERNCHG_SLAVE_ADDR 0x3b +#define EXTERNCHG_I2C_VOLTAGE 0x08 typedef enum fs_signature_type { EXT_FS_SIGNATURE = 1, @@ -372,6 +380,79 @@ extern int emmc_recovery_init(void); extern int fastboot_trigger(void); #endif +static struct qup_i2c_dev *i2c_dev; +int externchg_lk_i2c_read(uint8_t addr, uint8_t *reg, uint8_t *buf, uint8_t len) +{ + if (!buf) + return ERR_INVALID_ARGS; + if(!i2c_dev) + return ERR_NOT_VALID; + struct i2c_msg rd_buf[] = { + {addr, I2C_M_WR, 1, reg}, + {addr, I2C_M_RD, len, buf} + }; + dprintf(CRITICAL, “#### qup_i2c_xfer\n”); + int err = qup_i2c_xfer(i2c_dev, rd_buf, 2); + + if (err < 0) { + dprintf(CRITICAL, “Read reg %x failed err %d\n”, *reg,err); + return err; + } + return NO_ERROR; +} + +int externchg_lk_adapter_present(void) +{ + unsigned char buf; + unsigned char register_addr = EXTERNCHG_I2C_VOLTAGE; + unsigned char slave_addr = EXTERNCHG_SLAVE_ADDR; + int ret=-1; + + if(!i2c_dev) { + return ERR_NOT_VALID; + } + ret = externchg_lk_i2c_read(slave_addr, ®ister_addr, &buf, 1); + if(ret < 0) { + dprintf(CRITICAL, “read externchg adapter_present error\n”); + return ret; + } + dprintf(CRITICAL, “#### read reg[0x8]=%x\n”,buf); + return (buf && 0x04) ? 0 : -1; +} +int externchg_lk_read_voltage(void) +{ + return target_get_battery_voltage(); +} + +void check_low_batt_start_system(void){ + uint32_t is_batt_volt = 0; + uint32_t cutoff_volt = 3600000; + + i2c_dev = qup_blsp_i2c_init(BLSP_ID_2, QUP_ID_1, 100000, 19200000); + is_batt_volt = externchg_lk_read_voltage(); + if(is_batt_volt < cutoff_volt) { + dprintf(CRITICAL,”low battery(%d),forbidy boot\n”,is_batt_volt); + mdelay(20); + //display_image_on_screen(); + /* 判断有无充电器插入,有则进行预充电,没有则关机 + * externchg_lk_adapter_present(); + */ + if(!externchg_lk_adapter_present()){ + //充电IC初始化 + while(is_batt_volt < cutoff_volt){ + dprintf(CRITICAL, “charging: batt_volt =%d\n”,is_batt_volt); + mdelay(1000); + is_batt_volt = externchg_lk_read_voltage(); + } + }else { + shutdown_device(); + } + + }else{ + dprintf(CRITICAL,”not low-volt battery(%d)\n”,is_batt_volt); + } +} + void target_get_pmic_info(char *pmic_info) { dprintf(INFO, “PMIC 0 is %d\n”, board_pmic_target(0)); @@ -632,8 +713,9 @@ unsigned char *update_cmdline(const char * cmdline) cmdline_len += strlen(loglevel); } else if (boot_reason_alarm) { cmdline_len += strlen(alarmboot_cmdline); – } else if ((target_build_variant_user() || device.charger_screen_enabled) – && target_pause_for_battery_charge() && !boot_into_recovery) { + } else if (!externchg_lk_adapter_present()){ + //} else if ((target_build_variant_user() || device.charger_screen_enabled) + // && target_pause_for_battery_charge() && !boot_into_recovery) { pause_at_bootup = 1; cmdline_len += strlen(battchg_pause); } @@ -964,6 +1046,7 @@ unsigned char *update_cmdline(const char * cmdline) if (have_cmdline) –dst; while ((*dst++ = *src++)); } else if (pause_at_bootup) { + dprintf(INFO, “#### enter poweroff `charger\n”); src = battchg_pause; if (have_cmdline) –dst; while ((*dst++ = *src++)); @@ -5427,6 +5510,7 @@ retry_boot: goto fastboot; } + check_low_batt_start_system(); boot_err_type = boot_linux_from_mmc(); switch (boot_err_type) {

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/180370.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年10月19日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档