/***************************************************************************** 函 数 名 : hi6559_irq_is_masked 功能描述 : 检查某个中断是否被屏蔽 输入参数 : 无 输出参数 : 无 返 回 值 : 无 *****************************************************************************/ s32 hi6559_irq_is_masked(u32 irq) { u32 offset = 0; u8 reg_temp = 0; /* 参数合法性检查 */ if (irq > IRQ_HI6559_NR_BASE+HI6559_IRQ_NR) { pmic_print_error("hi6559 irq is error,please check irq=%d\n", (s32)irq); return HI6559_IRQ_ERROR; } offset = irq - IRQ_HI6559_NR_BASE; if (offset < HI6559_IRQM2_BASE_OFFSET) { bsp_hi6559_reg_read(HI6559_IRQ1_MASK_OFFSET, ®_temp); } else if(offset < HI6559_IRQM3_BASE_OFFSET) { offset -= HI6559_IRQM2_BASE_OFFSET; bsp_hi6559_reg_read(HI6559_IRQ2_MASK_OFFSET, ®_temp); } else if(offset < HI6559_IRQM4_BASE_OFFSET) { offset = HI6559_IRQM3_BASE_OFFSET; bsp_hi6559_reg_read(HI6559_IRQ3_MASK_OFFSET, ®_temp); } else { offset = HI6559_IRQM4_BASE_OFFSET; bsp_hi6559_reg_read(HI6559_IRQ4_MASK_OFFSET, ®_temp); } return (reg_temp & ((u32)1 << offset)) ; }
/***************************************************************************** 函 数 名 : hi6559_irq_mask 功能描述 : 屏蔽中断 输入参数 : 无 输出参数 : 无 返 回 值 : 无 *****************************************************************************/ void hi6559_irq_mask(u32 irq) { hi6559_irqflags_t irq_flags = 0; u32 offset = 0; u8 reg_temp = 0; /* 参数合法性检查 */ if (irq > IRQ_HI6559_NR_BASE + HI6559_IRQ_NR) { pmic_print_error("hi6559 irq is error,please check irq=%d\n", (s32)irq); return; } /*lint --e{746,718}*/ spin_lock_irqsave(&hi6559_irq_data_st->irq_lock, irq_flags); offset = irq - IRQ_HI6559_NR_BASE; if (offset < HI6559_IRQM2_BASE_OFFSET) { bsp_hi6559_reg_read(HI6559_IRQ1_MASK_OFFSET, ®_temp); reg_temp |= (u8)((u32)1 << offset); bsp_hi6559_reg_write(HI6559_IRQ1_MASK_OFFSET, reg_temp); } else if(offset < HI6559_IRQM3_BASE_OFFSET) { offset -= HI6559_IRQM2_BASE_OFFSET; bsp_hi6559_reg_read(HI6559_IRQ2_MASK_OFFSET, ®_temp); reg_temp |= (u8)((u32)1 << offset); bsp_hi6559_reg_write(HI6559_IRQ2_MASK_OFFSET, reg_temp); } else if(offset < HI6559_IRQM4_BASE_OFFSET) { offset -= HI6559_IRQM3_BASE_OFFSET; bsp_hi6559_reg_read(HI6559_IRQ3_MASK_OFFSET, ®_temp); reg_temp |= (u8)((u32)1 << offset); bsp_hi6559_reg_write(HI6559_IRQ3_MASK_OFFSET, reg_temp); } else { offset -= HI6559_IRQM4_BASE_OFFSET; bsp_hi6559_reg_read(HI6559_IRQ4_MASK_OFFSET, ®_temp); reg_temp |= (u8)((u32)1 << offset); bsp_hi6559_reg_write(HI6559_IRQ4_MASK_OFFSET, reg_temp); } spin_unlock_irqrestore(&hi6559_irq_data_st->irq_lock, irq_flags); return; }
/***************************************************************************** 函 数 名 : hi6559_boot_om_log_save 功能描述 : 将非下电状态记录寄存器保存到全局变量 输入参数 : 无 输出参数 : 无 返 回 值 : 无 备注说明 : 无 *****************************************************************************/ void hi6559_boot_om_log_save(void) { u32 timeout = 0; u16 j = 0; if(true != (s32)pmu_om_flag) { for(j = 0; j < HI6559_NP_RECORD_REG_NUM; j++) { bsp_hi6559_reg_read((HI6559_NP_IRQ1_RECORD_OFFSET + j), &pmu_hi6559_om_boot[j]); } pmu_om_flag = true; } /* 记录重启后,pmu的最初状态,分析重启原因,记录日志时间长,采用工作队列完成 */ g_hi6559_exc_st.hi6559_om_wq = create_singlethread_workqueue("bsp_hi6559_om"); if (!g_hi6559_exc_st.hi6559_om_wq) { pmic_print_error("%s: create_singlethread_workqueue fail\n", __FUNCTION__); return; } INIT_DELAYED_WORK(&g_hi6559_exc_st.hi6559_om_wk, (void *)hi6559_om_wk_handler); queue_delayed_work(g_hi6559_exc_st.hi6559_om_wq, &g_hi6559_exc_st.hi6559_om_wk, timeout); return; }
s32 bsp_hi6559_dr_get_current(s32 dr_id) { u8 regval = 0; s32 iret = BSP_PMU_OK; PMIC_HI6559_DRS_ATTR *hi6559_dr; u32 cur = 0; /*参数有效性检查*/ iret = hi6559_dr_para_check(dr_id); if(BSP_PMU_OK != iret) return BSP_PMU_PARA_ERROR; hi6559_dr = &hi6559_dr_attr[dr_id]; bsp_hi6559_reg_read(hi6559_dr->current_reg_addr, ®val); /* 获取电压档位值 */ cur = (regval & hi6559_dr->current_bit_mask) >> hi6559_dr->current_bit_offset; cur = hi6559_dr->current_list[cur]; pmic_print_info("dr_id %d's current is %d uA!\n", dr_id,cur); return cur; }
/***************************************************************************** 函 数 名 : bsp_pmu_version_get 功能描述 : 获取版本号 输入参数 : 无 输出参数 : 无 返 回 值 : BSP_PMU_OK: 成功; else:失败 *****************************************************************************/ u8 bsp_pmu_version_get(void) { u8 regval = 0; bsp_hi6559_reg_read(HI6559_VERSION_OFFSET, ®val); return regval; }
/***************************************************************************** 函 数 名 : bsp_pmu_sdio_suspend 功能描述 : SDIO深睡 输入参数 : 无 输出参数 : 无 返 回 值 : BSP_PMU_OK: 成功; else:失败 *****************************************************************************/ s32 bsp_pmu_sdio_suspend(void) { PMIC_HI6559_VLTGS_TABLE *hi6559_volt_table = (PMIC_HI6559_VLTGS_TABLE *)SHM_PMU_VOLTTABLE_ADDR; PMIC_HI6559_VLTGS_ATTR *hi6559_volt; s32 iret = BSP_PMU_OK; u32 i = 0 ; u8 volt_id = 0; u8 regval = 0; /* 电压属性表安全性检查 */ iret = hi6559_volt_table_check(hi6559_volt_table); if(BSP_PMU_OK != iret) { return BSP_PMU_VOLTTABLE_ERROR; } for(i = 0;i < sizeof(pmu_volt_sdio)/(sizeof((pmu_volt_sdio)[0]));i++) { volt_id = pmu_volt_sdio[i].volt_id; hi6559_volt = &hi6559_volt_table->hi6559_volt_attr[volt_id]; bsp_hi6559_reg_read(hi6559_volt->is_enabled_reg_addr, ®val); if(regval & ((u32)0x1 << hi6559_volt->is_enabled_bit_offset)) { regval = (u8)((u32)0x1 << hi6559_volt->disable_bit_offset); bsp_hi6559_reg_write(hi6559_volt->disable_reg_addr, regval); pmu_volt_sdio[i].flag = 1; } } return BSP_PMU_OK; }
/***************************************************************************** 函 数 名 : bsp_hi6559_optreg_test 功能描述 : hi6559 优化reg配置测试 输入参数 : 无 输出参数 : 无 返 回 值 : 无 *****************************************************************************/ void bsp_hi6559_optreg_test(void) { #if 0 u32 test_num = 0; u32 m; u8 value; if(BSP_PMU_V230 == bsp_pmu_version_get()) { test_num = sizeof(g_BBStar_CFG)/sizeof(BBStar_CFG_S); for(m = 0; m < test_num; m++) { bsp_hi6559_reg_read(g_BBStar_CFG[m].regAddr,&value); pmic_print_info("the value of addr %x is %x\n", g_BBStar_CFG[m].regAddr,value); if(g_BBStar_CFG_V03[m].regValue != value) { pmic_print_error("the value of addr %x is different\n", g_BBStar_CFG[m].regAddr); pmic_print_error("read value is %x,should be %x\n", value,g_BBStar_CFG[m].regValue); } } } else if((BSP_PMU_V210 == bsp_pmu_version_get())||(BSP_PMU_V220 == bsp_pmu_version_get())) { test_num = sizeof(g_BBStar_CFG_V03)/sizeof(BBStar_CFG_S); for(m = 0; m < test_num; m++) { bsp_hi6559_reg_read(g_BBStar_CFG_V03[m].regAddr,&value); pmic_print_info("the value of addr %x is %x\n", g_BBStar_CFG_V03[m].regAddr,value); if(g_BBStar_CFG_V03[m].regValue != value) { pmic_print_error("the value of addr %x is different\n", g_BBStar_CFG_V03[m].regAddr); pmic_print_error("read value is %x,should be %x\n", value,g_BBStar_CFG_V03[m].regValue); } } } #else pmic_print_error("strub now\n"); #endif pmic_print_error("test ok!\n"); return; }
/***************************************************************************** 函 数 名 : bsp_hi6559_exc_init 功能描述 : 异常处理模块初始化函数 输入参数 : 无 输出参数 : 无 返 回 值 : 无 *****************************************************************************/ s32 bsp_hi6559_exc_init(void) { hi6559_excflags_t exc_flags = 0; u32 *volt_need_off = (u32 *)SHM_PMU_OCP_INFO_ADDR; /*过流,需要关闭的过流源*/ s32 iret = 0; s32 ret = 0; u16 i = 0; u8 reg_temp = 0; /*init default nv config*/ memset((void*)&pmu_exc_pro, 0, sizeof(PMU_EXC_PRO_NV_STRU)); pmu_exc_pro.ulOcpIsOn = 1; /* 过流的电源可以重新打开 */ pmu_exc_pro.ulOcpIsOff = 1; /* 过流的电源需要关闭 */ pmu_exc_pro.ulOtpCurIsOff = 1; /* 发生过温后需要关闭非核心电源 */ pmu_exc_pro.ulOtpIsRst = 0; /* 发生过温后系统不重启 */ pmu_exc_pro.ulOtpIsOff = 1; /* 过温150度后PMU下电 */ pmu_exc_pro.ulOtpLimit = 125; /* 温度预警阈值125度 */ pmu_exc_pro.ulUvpIsRst = 1; /* 发生欠压后系统重启 */ #if (FEATURE_ON == MBB_COMMON) pmu_exc_pro.ulUvpLimit = 2700; /* 欠压预警阈值2700mV */ #else pmu_exc_pro.ulUvpLimit = 3000; /* 欠压预警阈值3000mV */ #endif spin_lock_init(&g_hi6559_exc_st.lock); /* 中断只在Acore实现,多core互斥锁 */ /* 读NV */ iret = (s32)bsp_nvm_read(NV_ID_DRV_NV_PMU_EXC_PRO,(u8 *)&pmu_exc_pro,sizeof(PMU_EXC_PRO_NV_STRU)); if(NV_OK != iret) { pmic_print_error("ERROR: read nv failed, ret %d!\n", iret); ret |= iret; } else { /* 设置过温预警阈值 */ bsp_hi6559_otp_threshold_set((int)pmu_exc_pro.ulOtpLimit); /* 设置欠压预警阈值 */ bsp_hi6559_uvp_threshold_set((int)pmu_exc_pro.ulUvpLimit); } /* 写start flag到log文件 */ hi6559_om_log_save(PMU_OM_LOG_START); /* 保存非下电寄存器 */ hi6559_boot_om_log_save(); /* 清除非下电寄存器 */ for(i = 0; i < HI6559_NP_RECORD_REG_NUM; i++) { spin_lock_irqsave(&g_hi6559_exc_st.lock,exc_flags); bsp_hi6559_reg_read((HI6559_NP_IRQ1_RECORD_OFFSET+i), ®_temp); bsp_hi6559_reg_write((HI6559_NP_IRQ1_RECORD_OFFSET+i), reg_temp); spin_unlock_irqrestore(&g_hi6559_exc_st.lock,exc_flags); } /* 初始化过流标志位 */ *volt_need_off = 0; /* 注册中断处理函数 */ iret = hi6559_irq_callback_register(IRQ_HI6559_OCP_SCP, hi6559_ocp_scp_handle, NULL); if (iret) { pmic_print_error("hi6559 irq register ocp interrupt failed!\n"); ret |= iret; } iret = hi6559_irq_callback_register(IRQ_HI6559_OTMP, hi6559_otp_handle, NULL); if (iret) { pmic_print_error("hi6559 irq register otmp interrupt failed!\n"); ret |= iret; } iret = hi6559_irq_callback_register(IRQ_HI6559_VSYS_UNDER_2P5, hi6559_uvp_die_handle, NULL); if (iret) { pmic_print_error("hi6559 irq register ocp interrupt failed!\n"); ret |= iret; } iret = hi6559_irq_callback_register(IRQ_HI6559_VSYS_UNDER_2P85, hi6559_uvp_warning_handle, NULL); if (iret) { pmic_print_error("hi6559 irq register otmp interrupt failed!\n"); ret |= iret; } iret = hi6559_irq_callback_register(IRQ_HI6559_VSYS_OVER_6P0, hi6559_ovp_handle, NULL); if (iret) { pmic_print_error("hi6559 irq register otmp interrupt failed!\n"); ret |= iret; } pmic_print_error("hi6559 exc init ok!\n"); return ret; }
/***************************************************************************** 函 数 名 : hi6559_ocp_scp_handle 功能描述 : 过流处理函数 输入参数 : @para 参数指针 输出参数 : 无 返 回 值 : 无 *****************************************************************************/ void hi6559_ocp_scp_handle(void* para) { u32 volt_need_off = 0; u32 *pmu_ocp_flag = (u32 *)SHM_PMU_OCP_INFO_ADDR; /* 过流,需要关闭的过流源 */ s32 ret = ERROR; u8 a_ucRecordReg[HI6559_NP_OCP_SCP_REG_NUM] = {0}; /* 过流寄存器读取值 */ u8 i = 0; u8 j = 0; /*lint --e{690,831}*/ para = para; pmic_print_error("******* hi6559_current_overflow! **********\n"); for(i = 0; i < HI6559_NP_OCP_SCP_REG_NUM; i++) { bsp_hi6559_reg_read((HI6559_NP_SCP_RECORD1_OFFSET + i), &a_ucRecordReg[i]); /* 在中断处理任务中,是否需要加锁? */ pmu_hi6559_om_data[i + 3] |= a_ucRecordReg[i]; } /* 检查所有SCP_RECORD和OCP_RECORD中的状态, 根据nv配置进行安全处理 */ /* BUCK短路检查,0x18寄存器 */ for (j = 0; j < HI6559_NP_SCP_RECORD1_CONT_NUM; j++) { if (a_ucRecordReg[0] & (u8)((u32)0x1 << reg_np_scp_record1_cont[j].bit_ofs)) /*lint !e690,!e831*/ { volt_need_off |= ((u32)0x1 << reg_np_scp_record1_cont[j].volt_id); *pmu_ocp_flag |= ((u32)0x1 << reg_np_scp_record1_cont[j].volt_id); print2file(PMU_OM_LOG,"pmu_hi6559:%s short !\n", reg_np_scp_record1_cont[j].cont); } } /* BUCK过流检查,0x19寄存器 */ for (j = 0; j < HI6559_NP_OCP_RECORD1_CONT_NUM; j++) { if (a_ucRecordReg[1] & (u8)((u32)0x1 << reg_np_ocp_record1_cont[j].bit_ofs)) /*lint !e690,!e831*/ { volt_need_off |= ((u32)0x1 << reg_np_ocp_record1_cont[j].volt_id); *pmu_ocp_flag |= ((u32)0x1 << reg_np_ocp_record1_cont[j].volt_id); print2file(PMU_OM_LOG,"pmu_hi6559:%s overflow !\n", reg_np_ocp_record1_cont[j].cont); } } /* LDO1~8过流检查,0x1A寄存器 */ for (j = 0; j < HI6559_NP_OCP_RECORD2_CONT_NUM; j++) { if (a_ucRecordReg[2] & (u8)((u32)0x1 << reg_np_ocp_record2_cont[j].bit_ofs)) /*lint !e690,!e831*/ { volt_need_off |= ((u32)0x1 << reg_np_ocp_record2_cont[j].volt_id); *pmu_ocp_flag |= ((u32)0x1 << reg_np_ocp_record2_cont[j].volt_id); print2file(PMU_OM_LOG,"pmu_hi6559:%s overflow !\n", reg_np_ocp_record2_cont[j].cont); } } /* ldo9~14过流,寄存器0x1B */ for (j = 0; j < HI6559_NP_OCP_RECORD3_CONT_NUM; j++) { if (a_ucRecordReg[3] & (u8)((u32)0x1 << j)) /*lint !e690,!e831*/ { volt_need_off |= ((u32)0x1 << (PMIC_HI6559_LDO09 + j)); *pmu_ocp_flag |= ((u32)0x1 << (PMIC_HI6559_LDO09 + j)); print2file(PMU_OM_LOG,"pmu_hi6559:LDO %d overflow !\n", PMIC_HI6559_LDO09 + j - 1); } } /* ldo22~24过流,寄存器0x1C */ for(j = 0; j < HI6559_NP_OCP_RECORD4_CONT_NUM; j++) { if (a_ucRecordReg[4] & (u8)((u32)0x1 << (j + 5))) /*lint !e690,!e831*/ { volt_need_off |= ((u32)0x1 << (PMIC_HI6559_LDO22 + j)); *pmu_ocp_flag |= ((u32)0x1 << (PMIC_HI6559_LDO22 + j)); print2file(PMU_OM_LOG,"pmu_hi6559:LDO %d overflow !\n", PMIC_HI6559_LDO22 + j + 6); } } /* lvs7过流,寄存器0x1D */ if(a_ucRecordReg[5] & (u8)((u32)0x1 << HI6559_LVS07_BIT_OFFSET)) { volt_need_off |= ((u32)0x1 << PMIC_HI6559_LVS07); *pmu_ocp_flag |= ((u32)0x1 << PMIC_HI6559_LVS07); print2file(PMU_OM_LOG,"pmu_hi6559:LVS7 overflow !\n"); } /* lvs9过流,寄存器0x1E */ if(a_ucRecordReg[6] & (u8)((u32)0x1 << HI6559_LVS09_BIT_OFFSET)) { volt_need_off |= ((u32)0x1 << PMIC_HI6559_LVS09); *pmu_ocp_flag |= ((u32)0x1 << PMIC_HI6559_LVS09); print2file(PMU_OM_LOG,"pmu_hi6559:LVS09 overflow !\n"); } /* 异常信息发给C核 */ if(volt_need_off) { ret = bsp_icc_send(ICC_CPU_MODEM, PA_RF_ICC_CHN_ID, (u8*)&volt_need_off, sizeof(u32)); if(sizeof(u32) != (u32)ret) { pmic_print_error("bsp_icc_send failed, ret = %d!\n", ret); } } /* 根据NV值确认是否需要关闭过流的电源 */ for(j = PMIC_HI6559_VOLT_MIN; j <= PMIC_HI6559_VOLT_MAX; j++) { if(pmu_exc_pro.ulOcpIsOff) { if(volt_need_off & ((u32)0x1 << j)) { pmic_print_error("hi6559:volt id %d overflow !\n", j); /* 需要关闭过流的电压源,则关闭 */ if(pmu_exc_pro.VoltProConfig[j].VoltOcpIsOff) { pmic_print_error("hi6559:volt id %d will be closed !\n", j); bsp_hi6559_volt_disable(j); } /* 过流需要重启,则重启 */ if(pmu_exc_pro.VoltProConfig[j].VoltOcpIsRst) { pmic_print_error("hi6559:system will be restart!\n"); system_error(DRV_ERRNO_PMU_OVER_CUR, PMU_STATE_OVER_CUR, j, (char *)&volt_need_off, (u32)sizeof(volt_need_off)); } } } else { if(volt_need_off & ((u32)0x1 << j)) { pmic_print_error("hi6559:volt id %d overflow !\n", j); } } } /*清除非下电中断状态寄存器*/ for(i = 0; i < HI6559_NP_OCP_SCP_REG_NUM; i++) { bsp_hi6559_reg_write((HI6559_NP_SCP_RECORD1_OFFSET + i), a_ucRecordReg[i]); /*lint !e661*/ } return;/*lint !e438*/ }
/***************************************************************************** 函 数 名 : hi6559_get_boot_state 功能描述 : 系统启动时检查pmu寄存器状态,确认是否是由pmu引起的重启 输入参数 : void 输出参数 : reset.log 返 回 值 : 0 - 非PMU引起的重启, else - PMU引起的重启原因 *****************************************************************************/ s32 hi6559_get_boot_state(void) { s32 iret = PMU_STATE_OK; u16 j = 0; if(true != (s32)pmu_om_flag) /* 如果没有读取过非下电寄存器,还没清除,则读取到全局变量里 */ { for(j = 0; j < HI6559_NP_RECORD_REG_NUM; j++) { bsp_hi6559_reg_read((HI6559_NP_IRQ1_RECORD_OFFSET + j), &pmu_hi6559_om_boot[j]); } pmu_om_flag = true; } /* 欠压 */ if((pmu_hi6559_om_boot[0] & (0x01 << HI6559_VSYS_UNDER_2P5_OFFSET ))|| (pmu_hi6559_om_boot[0] & (0x01 << HI6559_VSYS_UNDER_2P85_OFFSET ))) { iret|= PMU_STATE_UNDER_VOL; } /* 过压 */ if(pmu_hi6559_om_boot[0] & (0x01 << HI6559_VSYS_OVER_6P0_OFFSET )) { iret|= PMU_STATE_OVER_VOL; } /* 过温 */ if(pmu_hi6559_om_boot[1] & (0x01 << HI6559_OTMP_150_OFFSET ) ) { iret|= PMU_STATE_OVER_TEMP; } /* buck短路,寄存器0x18 */ for (j = 0; j < HI6559_NP_SCP_RECORD1_CONT_NUM; j++) { if (pmu_hi6559_om_boot[3] & (u8)((u32)0x1 << reg_np_scp_record1_cont[j].bit_ofs)) { iret |= PMU_STATE_OVER_CUR; } } /* buck过流,寄存器0x19 */ for (j = 0; j < HI6559_NP_OCP_RECORD1_CONT_NUM; j++) { if (pmu_hi6559_om_boot[4] & (u8)((u32)0x1 << reg_np_ocp_record1_cont[j].bit_ofs)) { iret |= PMU_STATE_OVER_CUR; } } /* ldo1~8过流,寄存器0x1A */ for (j = 0; j < HI6559_NP_OCP_RECORD2_CONT_NUM; j++) { if (pmu_hi6559_om_boot[5] & (u8)((u32)0x1 << reg_np_ocp_record2_cont[j].bit_ofs)) { iret |= PMU_STATE_OVER_CUR; } } /* ldo9~14过流,寄存器0x1B */ for (j = 0; j < HI6559_NP_OCP_RECORD3_CONT_NUM; j++) { if (pmu_hi6559_om_boot[6] & (u8)((u32)0x1 << j)) { iret |= PMU_STATE_OVER_CUR; } } /* ldo22~24过流,寄存器0x1C */ for(j = 0; j < HI6559_NP_OCP_RECORD4_CONT_NUM; j++) { if (pmu_hi6559_om_boot[7] & (u8)((u32)0x1 << (j + 5))) { iret |= PMU_STATE_OVER_CUR; } } /* lvs7过流,寄存器0x1D */ if (pmu_hi6559_om_boot[8] & (u8)((u32)0x1 << HI6559_LVS07_BIT_OFFSET)) { iret|= PMU_STATE_OVER_CUR; } /* lvs9过流,寄存器0x1E */ if (pmu_hi6559_om_boot[9] & (u8)((u32)0x1 << HI6559_LVS09_BIT_OFFSET)) { iret|= PMU_STATE_OVER_CUR; } return iret; }
/***************************************************************************** * 函 数 名 : hi6559_reg_read * * 功能描述 : 对pmu芯片寄存器的读函数 * * 输入参数 : u16 addr:待写入的寄存器地址 * u8 u8Data:读出的数据 * * 输出参数 : 无 * * 返 回 值 : 无 *****************************************************************************/ void bsp_dr_reg_read( u16 addr, u8 *pValue) { bsp_hi6559_reg_read(addr,pValue); }
/***************************************************************************** 函 数 名 : hi6559_irq_probe 功能描述 : 输入参数 : 无 输出参数 : 无 返 回 值 : 无 *****************************************************************************/ static s32 __init hi6559_irq_probe(struct platform_device *pdev) { s32 ret = BSP_PMU_OK; u16 i = 0; u8 regvalue = 0; hi6559_irq_data_st = kzalloc(sizeof(*hi6559_irq_data_st), GFP_KERNEL); if (hi6559_irq_data_st == NULL) { pmic_print_error("hi6559 irq kzalloc is failed,please check!\n"); return -ENOMEM; } hi6559_irq_data_st->irq = (unsigned)platform_get_irq(pdev, 0); spin_lock_init(&hi6559_irq_data_st->irq_lock);/*中断只在Acore实现,多core*/ /* 初始化工作队列 */ hi6559_irq_data_st->hi6559_irq_wq = create_singlethread_workqueue("bsp_hi6559_irq"); INIT_WORK(&hi6559_irq_data_st->hi6559_irq_wk, (void *)hi6559_irq_wk_handler); /* 处理usb拔出误报,若usb不在位,多报usb拔出无影响 */ bsp_hi6559_reg_read(HI6559_IRQ2_OFFSET, ®value); if((regvalue & (0x01 << 2)) && hi6559_usb_state_get()) { bsp_hi6559_reg_write(HI6559_IRQ2_OFFSET, 0x04); } /* 清除所有下电中断寄存器 */ for(i = 0;i < HI6559_IRQ_REG_NUM; i++) { bsp_hi6559_reg_read(HI6559_IRQ1_OFFSET + i,®value); bsp_hi6559_reg_write(HI6559_IRQ1_OFFSET + i, regvalue); } /* 清除短路过流中断寄存器,这样过流中断位才能消除 */ for(i = 0; i < HI6559_NP_OCP_SCP_REG_NUM; i++) { bsp_hi6559_reg_read(HI6559_SCP_RECORD1_OFFSET + i, ®value); bsp_hi6559_reg_write(HI6559_SCP_RECORD1_OFFSET + i, regvalue); } /* 屏蔽所有中断 */ for(i = 0;i < HI6559_IRQ_REG_NUM;i++) { bsp_hi6559_reg_write(HI6559_IRQ1_MASK_OFFSET + i, 0xff); } /* 中断注册 */ #ifdef CONFIG_MODULE_VIC ret = bsp_vic_connect(hi6559_irq_data_st->irq, hi6559_irq_handler,(s32)(hi6559_irq_data_st->irq)); if (ret < 0) { pmic_print_error("unable to connect PMIC HI6559 IRQ!\n"); goto out; } ret = bsp_vic_enable(hi6559_irq_data_st->irq); if (ret < 0) { pmic_print_error("enable PMIC HI6559 IRQ error!\n"); goto out; } #else ret = request_irq((hi6559_irq_data_st->irq), hi6559_irq_handler, IRQF_DISABLED, "hi6559_irq", hi6559_irq_data_st); if (ret < 0) { pmic_print_error("unable to request PMIC HI6559 IRQ!\n"); goto out; } #endif /* 打开所有中断 */ for(i = 0; i < HI6559_IRQ_REG_NUM; i++) { bsp_hi6559_reg_write(HI6559_IRQ1_MASK_OFFSET + i, 0x0); } platform_set_drvdata(pdev, hi6559_irq_data_st); pmic_print_error("hi6559_irq_probe ok !\n"); return ret; out: kfree(hi6559_irq_data_st); return ret; }
/***************************************************************************** 函 数 名 : hi6559_irq_wk_handler 功能描述 : 输入参数 : 无 输出参数 : 无 返 回 值 : 无 *****************************************************************************/ void hi6559_irq_wk_handler(void) { u32 reg = 0; u8 i = 0, reg1 = 0, reg2 = 0, reg3 = 0, reg4 = 0, reg_tmp = 0; u8 flag = 0; /*power 键按下和抬起中断同时过来的标志*/ /* 读所有中断 */ bsp_hi6559_reg_read(HI6559_IRQ1_OFFSET, ®1); bsp_hi6559_reg_read(HI6559_IRQ2_OFFSET, ®2); bsp_hi6559_reg_read(HI6559_IRQ3_OFFSET, ®3); bsp_hi6559_reg_read(HI6559_IRQ4_OFFSET, ®4); reg = ((u32)reg1 | ((u32)reg2 << HI6559_IRQM2_BASE_OFFSET) | ((u32)reg3 << HI6559_IRQM3_BASE_OFFSET) | ((u32)reg4 << HI6559_IRQM4_BASE_OFFSET)); /* 按键中断press和release中断同时发生,则flag置1 */ if (unlikely(0x60 == (0x60 & reg1))) { /*lint !e730*/ flag = 1; } /* 逐个寄存器清中断 */ if (reg1) { bsp_hi6559_reg_write(HI6559_IRQ1_OFFSET, reg1); } if (reg2) { if (reg2 & 0x01) /* 发生了过流/短路中断 */ { for(i = 0; i < HI6559_NP_OCP_SCP_REG_NUM; i++) { /* 清除短路/过流中断状态寄存器 */ bsp_hi6559_reg_read(HI6559_IRQ2_OFFSET, ®_tmp); if(reg_tmp) { bsp_hi6559_reg_write((HI6559_SCP_RECORD1_OFFSET + i), 0xFF); } } } bsp_hi6559_reg_write(HI6559_IRQ2_OFFSET, reg2); } if (reg3) { bsp_hi6559_reg_write(HI6559_IRQ3_OFFSET, reg3); } if (reg4) { /* sim拔出中断,使用拔出的下跳沿 */ if(reg4 & 0x04) { /* 先关闭电源再清中断,否则热插拔功能失效,修改为任务队列,故可以使用锁 */ /* 后续需分析是否会引起任务处理时间长,影响中断响应 */ bsp_hi6559_volt_disable(PMIC_HI6559_LDO09); } bsp_hi6559_reg_write(HI6559_IRQ4_OFFSET, reg4); } if (reg) { for (i = 0; i < HI6559_IRQ_NR; i++) { if ((1 == flag) && (5 == i)) { /* 按键中断press和release中断同时发生,先处理press中断,这样更符合逻辑 */ Hi6559IrqInfo[6].cnt++; if (NULL != Hi6559IrqInfo[6].routine) Hi6559IrqInfo[6].routine(Hi6559IrqInfo[6].data); Hi6559IrqInfo[5].cnt++; if (NULL != Hi6559IrqInfo[5].routine) Hi6559IrqInfo[5].routine(Hi6559IrqInfo[5].data); i = i + 2; } if (reg & ((u32)1 << i)) { Hi6559IrqInfo[i].cnt++; /* 中断处理 */ if (NULL != Hi6559IrqInfo[i].routine) { Hi6559IrqInfo[i].routine(Hi6559IrqInfo[i].data); } } } } pmic_print_info("**********hi6559_irq_wk_handler**********\n"); hi6559_irq_enable(); return; }