项目中I2C6所对应的gpio口为22和23
由上表可以确定以下信息:
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
在初始化代码中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 %dn”,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 %dn”,qup_id); ASSERT(0); } } else { dprintf(CRITICAL, “Incorrect BLSP id %dn”,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 configurationn”, 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 clockn”, 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 %sn”, clk_name); return; } ret = clk_enable(qup_clk); if (ret) { dprintf(CRITICAL, “Failed to enable %sn”, 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 clockn”, 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 %sn”, clk_name); return; } ret = clk_enable(qup_clk); if (ret) { dprintf(CRITICAL, “Failed to enable %sn”, 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_xfern”); int err = qup_i2c_xfer(i2c_dev, rd_buf, 2); if (err < 0) { dprintf(CRITICAL, “Read reg %x failed err %dn”, *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 errorn”); return ret; } dprintf(CRITICAL, “#### read reg[0x8]=%xn”,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 bootn”,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 =%dn”,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 %dn”, 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 `chargern”); 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