大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
项目中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 %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 \
$(LOCAL_DIR)/mipi_dsi.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)
{
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/180370.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...