Example #1
0
/*****************************************************************************
 函 数 名  : 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, &reg_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, &reg_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, &reg_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, &reg_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;
}
/*****************************************************************************
 函 数 名  : bsp_pmu_sdio_resume
 功能描述  : SDIO唤醒
 输入参数  : 无
 输出参数  : 无
 返 回 值  : BSP_PMU_OK: 成功; else:失败
*****************************************************************************/
s32 bsp_pmu_sdio_resume(void)
{
    s32 iret = BSP_PMU_OK;
    PMIC_HI6559_VLTGS_TABLE *hi6559_volt_table = (PMIC_HI6559_VLTGS_TABLE *)SHM_PMU_VOLTTABLE_ADDR;
    PMIC_HI6559_VLTGS_ATTR *hi6559_volt;
    s32 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 = (signed)(sizeof(pmu_volt_sdio)/(sizeof((pmu_volt_sdio)[0])) - 1);i >= 0;i--)
    {
        volt_id = pmu_volt_sdio[i].volt_id;
        hi6559_volt = &hi6559_volt_table->hi6559_volt_attr[volt_id];

        if(pmu_volt_sdio[i].flag)
        {
            regval = (u8)((u32)0x1 << hi6559_volt->enable_bit_offset);
            bsp_hi6559_reg_write(hi6559_volt->enable_reg_addr, regval);
            pmu_volt_sdio[i].flag = 0;
        }
    }

    return  BSP_PMU_OK;
}
/*****************************************************************************
 函 数 名  : 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, &regval);
        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;
}
Example #4
0
/*****************************************************************************
 函 数 名  : hi6559_uvp_die_handle
 功能描述  : 欠压2.5V处理函数,电压低于PMU所能容忍的阈值时所要进行的处理(按道
             理本函数调用到,系统就会挂)
 输入参数  : @para 参数指针
 输出参数  : 无
 返 回 值  : 无
 调用函数  :
 被调函数  : bbstar中断处理任务
*****************************************************************************/
void hi6559_uvp_die_handle(void* para)
{
    para = para;

    pmu_hi6559_om_data[0] |= (0x01 << HI6559_VSYS_UNDER_2P5_OFFSET);
    /*记录om log */
    /* hi6559_om_log_save(PMU_OM_LOG_EXC); */
    print2file(PMU_OM_LOG, "pmu_hi6559:vsys under 2.5v !\n");

    /* 清除非下电reg */
    bsp_hi6559_reg_write(HI6559_NP_IRQ1_RECORD_OFFSET, (0x01 << HI6559_VSYS_UNDER_2P5_OFFSET));
    pmic_print_error("\n**********hi6559_uvp_2p5_isr**********\n");

    return;/*lint !e438*/
}
Example #5
0
/*****************************************************************************
 函 数 名  : hi6559_ovp_handle
 功能描述  : 过压处理函数
 输入参数  : @para 参数指针
 输出参数  : 无
 返 回 值  : 无
*****************************************************************************/
void hi6559_ovp_handle(void* para)
{
    para = para;

    pmu_hi6559_om_data[0] |= (0x01 << HI6559_VSYS_OVER_6P0_OFFSET);

    /* 记录om log */
    /* hi6559_om_log_save(PMU_OM_LOG_EXC); */
    print2file(PMU_OM_LOG,"pmu_hi6559:vsys over 6.0v last time!\n");

    /* 清除非下电reg */
    bsp_hi6559_reg_write(HI6559_NP_IRQ1_RECORD_OFFSET, (0x01 << HI6559_VSYS_OVER_6P0_OFFSET));
    pmic_print_error("\n**********hi6559_ovp_isr**********\n");

    return;/*lint !e438*/
}
Example #6
0
/*****************************************************************************
 函 数 名  : hi6559_otp_handle
 功能描述  : 过温处理函数
 输入参数  : @para 参数指针
 输出参数  : 无
 返 回 值  : 无
*****************************************************************************/
void hi6559_otp_handle(void* para)
{
    s32 i = 0;

    para = para;

    pmic_print_error("hi6559:temperature overflow (>125℃)!\n");

    /*由nv控制过温是否关闭*/
    pmu_hi6559_om_data[0] |= (0x01 << HI6559_OTMP_125_OFFSET);
    
    /*根据nv配置,决定是否关闭非核心电源,后续增加产品形态相关特殊处理*/
    if(pmu_exc_pro.ulOtpCurIsOff)
    {
        for(i = PMIC_HI6559_VOLT_MIN; i < PMIC_HI6559_VOLT_MAX; i++)
        {
            if(pmu_exc_pro.VoltProConfig[i].VoltOtpIsOff)
            {
                pmic_print_error("hi6559:volt id %d will be closed !\n",i);
                bsp_hi6559_volt_disable(i);
            }
        }
    }
    
    if(pmu_exc_pro.ulOtpIsRst)
    {
        pmic_print_error("hi6559:system will be restart!\n");
        system_error(DRV_ERRNO_PMU_OVER_TEMP, PMU_STATE_OVER_TEMP, 0, NULL, 0);
    }

    /* 记录om log */
    /* hi6559_om_log_save(PMU_OM_LOG_EXC); */
    print2file(PMU_OM_LOG, "pmu_hi6559:temperature overflow (>125℃)!\n");
    
    /*clear np int */
    bsp_hi6559_reg_write(HI6559_NP_SCP_RECORD1_OFFSET, (0x01 << HI6559_OTMP_125_OFFSET));
    pmic_print_error("\n**********hi6559_otp_isr**********\n");

    return;/*lint !e438*/
}
Example #7
0
/*****************************************************************************
 函 数 名  : hi6559_uvp_warning_handle
 功能描述  : 欠压处理函数2.85/3.0,电压低于设定的告警阈值,所要进行的处理
 输入参数  : void
 输出参数  : 无
 返 回 值  : void
 调用函数  :
 被调函数  : bbstar中断处理任务
*****************************************************************************/
void hi6559_uvp_warning_handle(void* para)
{
    para = para;
    pmu_hi6559_om_data[0] |= (0x01 << HI6559_VSYS_UNDER_2P85_OFFSET);

    /* 记录om log */
    /* hi6559_om_log_save(PMU_OM_LOG_EXC); */
    print2file(PMU_OM_LOG,"pmu_hi6559:vsys under 2.85/3.0v !\n");

    /* 根据nv配置确定是否重启 */
    if(pmu_exc_pro.ulUvpIsRst)
    {
        pmic_print_error("hi6559:system will be restart!\n");
        system_error(DRV_ERRNO_PMU_UNDEF_VOL, PMU_STATE_UNDER_VOL, 0, NULL, 0);
    }

    /*清除非下电reg,write 1 clear*/
    bsp_hi6559_reg_write(HI6559_NP_IRQ1_RECORD_OFFSET, (0x01 << HI6559_VSYS_UNDER_2P85_OFFSET));
    pmic_print_error("**********hi6559_uvp_2p85_isr**********\n");

    return;/*lint !e438*/
}
Example #8
0
/*****************************************************************************
 函 数 名  : 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), &reg_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;
}
Example #9
0
/*****************************************************************************
 函 数 名  : 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_reg_read
*
* 功能描述  : 对pmu芯片寄存器的读函数
*
* 输入参数  : u16 addr:待写入的寄存器地址
*             u8 u8Data:读出的数据
*
* 输出参数  : 无
*
* 返 回 值  : 无
*****************************************************************************/
void bsp_dr_reg_write( u16 addr, u8 value)
{
    bsp_hi6559_reg_write(addr,value);
}
Example #11
0
/*****************************************************************************
 函 数 名  : 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, &regvalue);
    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,&regvalue);
        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, &regvalue);
        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;

}
Example #12
0
/*****************************************************************************
 函 数 名  : 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, &reg1);
    bsp_hi6559_reg_read(HI6559_IRQ2_OFFSET, &reg2);
    bsp_hi6559_reg_read(HI6559_IRQ3_OFFSET, &reg3);
    bsp_hi6559_reg_read(HI6559_IRQ4_OFFSET, &reg4);
    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, &reg_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;
}