예제 #1
0
static ssize_t cbp_power_store(struct kobject *kobj, struct kobj_attribute *attr,
			   const char *buf, size_t n)
{
	unsigned long val;

	if (strict_strtoul(buf, 10, &val))
		return -EINVAL;

	if (val < 0)
		return -EINVAL;

	if (val){
		if(cbp_power_state == 0){
			//sys_power_on_cbp();
			hwlog_debug("AP power on CBP.\n");
		}
		else{
			hwlog_err("%s: CBP is already power on.\n", __func__);
		}
	}
	else{
		if(cbp_power_state == 1){
			//sys_power_off_cbp();
			hwlog_debug("AP power off CBP.\n");
			cbp_power_state = 0;
		}
		else{
			hwlog_err("%s: CBP is already power off.\n", __func__);
		}
	}

	return n;
}
static int hwlog_mmap(struct file *filp,
				  struct vm_area_struct *vma)
{
	size_t size = vma->vm_end - vma->vm_start;

	//hwlog_mem_debug();

	if(hwlog_memory_map_perm_check(vma)){
		pr_err("hwlog map out of memory range\n");
		return -EPERM;
	}

	hwlog_debug("hwlog start=0x%lx, size=%zx, vm_pgoff=0x%lx\n", 
			vma->vm_start, size, vma->vm_pgoff);

	vma->vm_ops = &hwlog_mmap_ops;

	/* Remap-pfn-range will mark the range VM_IO */
	if (remap_pfn_range(vma,
			    vma->vm_start,
			    vma->vm_pgoff,
			    size,
			    vma->vm_page_prot)) {
		pr_err("hwlog remap pfn range failed\n");
		return -EAGAIN;
	}

	hwlog_vma_open(vma);
	hwlog_debug("hwlog mmap sucess\n");
	return 0;
}
예제 #3
0
static int cbp_remove(struct platform_device *pdev)
{
	struct cbp_platform_data *plat = pdev->dev.platform_data;

	if(plat->data_ack_enable && (GPIO_OEM_VALID(plat->gpio_data_ack))){
		free_irq(oem_gpio_to_irq(plat->gpio_data_ack), cbp_data_ack);
		oem_gpio_free(plat->gpio_data_ack);
		kfree(cbp_data_ack);
	}

	if(plat->flow_ctrl_enable && (GPIO_OEM_VALID(plat->gpio_flow_ctrl))){
		free_irq(oem_gpio_to_irq(plat->gpio_flow_ctrl), cbp_flow_ctrl);
		oem_gpio_free(plat->gpio_flow_ctrl);
		kfree(cbp_flow_ctrl);
	}

	if(plat->rst_ind_enable && (GPIO_OEM_VALID(plat->gpio_rst_ind))){
		free_irq(oem_gpio_to_irq(plat->gpio_rst_ind), NULL);
		oem_gpio_free(plat->gpio_rst_ind);
	}
	plat->cbp_destroy();
	sysfs_remove_group(cbp_power_kobj, &g_power_attr_group);
	kobject_put(cbp_power_kobj);
	hwlog_debug(" cbp removed on host %s, bus is %s!\n", plat->host_id, plat->bus);
	return 0;
}
/* wait AP host controller to resumed */
int wait_ap_bus_resumed(void)
{
    unsigned long remain_time = 0;
    unsigned int timeout_cnt = 0;

    hwlog_debug("%s %d entered\n", __func__, __LINE__);

    do
    {
        remain_time = wait_event_timeout(g_ext_modem.m_ap_resume_waitq, (AP_BUS_RESUMED == atomic_read(&g_ext_modem.m_ap_resume_atom)) || \
                                         (0 == get_modem_bus_state()), msecs_to_jiffies(WAIT_APCP_BUS_RESUME_TIMEOUT));

        if (0 == get_modem_bus_state())
        {
            hwlog_err("%s %d: VIA modem reset happened\n", __func__, __LINE__);
            return -1;
        }
        else if (0 == remain_time)
        {
            hwlog_info("%s %d: wait ap host controller to resume timeout\n", __func__, __LINE__);
            timeout_cnt++;

            if (timeout_cnt >= MAX_WAIT_BUS_RESUME_TIMES)
            {
                hwlog_err("%s %d: FAIL to wait ap host to resume with MAX retries\n", __func__, __LINE__);
                return -2;
            }
        }
    }
    while (0 == remain_time);

    return 0;
}
예제 #5
0
static int modem_spi_rx_notifier(int event, void *data)
{
	struct asc_config *rx_config  = (struct asc_config *)data;
	int ret = 0;
	hwlog_debug("%s event=%d\n", __func__,event);
	switch(event){
		case ASC_NTF_RX_PREPARE:
#ifdef WAKE_HOST_BY_SYNC/*wake up spi host by four wire sync mechanis*/
			if(cbp_power_state){
				VIA_trigger_signal(1);
			}
			else
				hwlog_err("ignor asc event to resume spi host\n");
#endif
			asc_rx_confirm_ready(rx_config->name, 1);
			break;
		case ASC_NTF_RX_POST:
#ifdef WAKE_HOST_BY_SYNC/*wake up spi host by four wire sync mechanis*/
			if(cbp_power_state){
				VIA_trigger_signal(0);
			}
			else
				hwlog_err("ignor asc event to suspend spi host\n");
#endif
			break;
		default:
			hwlog_err("%s: ignor unknow evernt!!\n", __func__);
			break;
	}
	return ret;
}
/**********************************************************
*  Function:       charge_core_cbatt_handler
*  Discription:    update the charge dpm in different battery capaciy
*  Parameters:   cbat:battery capacity
*                      vdpm_data[]:the table for describe the dpm property
*                      data:charge parameters
*  return value:  NULL
**********************************************************/
static void charge_core_cbatt_handler(int cbat, struct charge_vdpm_data vdpm_data[], struct charge_core_data *data)
{
    int i;
    static int last_i = 0;
    static int last_vdpm = 0;
    static int last_cbat = 0;
    static int flag_running_first = 1;

    for (i = 0; i < VDPM_PARA_LEVEL; i++)
    {
        if ((cbat >= vdpm_data[i].cap_min) && (cbat < vdpm_data[i].cap_max))
        {
            if ((last_cbat - cbat <= 0) || (vdpm_data[i].cap_max - cbat > vdpm_data[i].cap_back)
                    || (abs(last_i - i) > 1) || (flag_running_first == 1))
            {
                data->vdpm = vdpm_data[i].vin_dpm;
            }
            else
            {
                data->vdpm = last_vdpm;
            }
            break;
        }
    }

    last_i = i;
    flag_running_first = 0;
    last_cbat = cbat;
    last_vdpm = data->vdpm;

    hwlog_debug("battery capacity is %%%d, vindpm set to %d mV\n", cbat, data->vdpm);
}
void hwlog_mem_debug(void){

	hwlog_debug("++++++hwlog debug tz mem:\n");
	hwlog_ddr_region[0].addr = ioremap(hwlog_ddr_region[0].phy_addr,
			hwlog_ddr_region[0].mem_size);

	hwlog_debug("%s addr after map: %p\n", hwlog_ddr_region[0].name,
			hwlog_ddr_region[0].addr);

	if(hwlog_ddr_region[0].addr){
		memcpy((char*)hwlog_ddr_region[0].addr, "tz_log_begin", 12);
		memcpy(((char*)hwlog_ddr_region[0].addr + 0x400000 -16), "11111 tz_log_end", 16);
		iounmap(hwlog_ddr_region[0].addr);
		hwlog_debug("unmap in init\n");
	}
	hwlog_debug("-------hwlog debug tz mem:\n");
}
static void charge_core_sbatt_handler(int vbat, struct charge_segment_data segment_data[], struct charge_core_data *data)
{
    /*not fcp do not use segment charging strategy */
    if(FCP_STAGE_SUCESS != fcp_get_stage_status())
    {
        return ;
    }

    switch (data->segment_type) {
    case SEGMENT_TYPE_BY_VBAT_ICHG:
        hwlog_debug("case = SEGMENT_TYPE_BY_VBAT_ICHG. \n");
        charge_core_sbatt_by_vbat_ichg_handler(vbat, segment_data, data);
        break;
    case SEGMENT_TYPE_BY_VBAT:
        hwlog_debug("case = SEGMENT_TYPE_BY_VBAT. \n");
        charge_core_sbatt_by_vbat_handler(vbat, segment_data, data);
        break;
    default:
        break;
    }
}
예제 #9
0
static irqreturn_t gpio_irq_via_rts(int irq, void *data)
{
    hwlog_debug("gpio_irq_via_rts entered, cbp_rst_ind_finished = %d\n", atomic_read(&cbp_rst_ind_finished));
	if(0 == atomic_read(&cbp_rst_ind_finished)) {
		hwlog_err("unexpected rts interrupt before cbp reset indication finished.\n");
		return IRQ_HANDLED;
	}

	respond_cflag80_packet_to_via_request_to_send();

	return IRQ_HANDLED;
}
static int __init hw_log_mem_init(void)
{
    int ret = 0;


	hwlog_debug("create hwlog devices sucess\n");

	if(misc_register(&hwlog_mem_miscdev)){
		pr_err("hwlog_mem: register misc device failed\n");
		return 0;
	}

	create_imem_node();
	create_ddr_mem_miscdev();

    return ret;
}
예제 #11
0
static irqreturn_t gpio_irq_via_spi_tx_rx_fifo_empty_ack(int irq, void *data)
{
	struct cbp_wait_event *cbp_data_ack = (struct cbp_wait_event *)data;
	int level;
	int ret = -1;

	ret = irq_set_irq_type(irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING);

	level = !!oem_gpio_get_value(cbp_data_ack->wait_gpio);
	hwlog_debug("%s enter, level = %d.\n", __func__, level);

	atomic_set(&cbp_data_ack->state, MODEM_ST_READY);
	wake_up(&cbp_data_ack->wait_q);

	oem_gpio_irq_unmask(cbp_data_ack->wait_gpio);

	return IRQ_HANDLED;
}
예제 #12
0
static ssize_t cbp_reset_store(struct kobject *kobj, struct kobj_attribute *attr,
			   const char *buf, size_t n)
{
	unsigned long val;

	if (strict_strtoul(buf, 10, &val))
		return -EINVAL;

	if (val < 0)
		return -EINVAL;

	if (val){
		//sys_reset_cbp();
		hwlog_debug("AP reset CBP.\n");
	}
	else{
		hwlog_err("%s: reset cbp use value 1.\n", __func__);
	}

	return n;
}
static void inputhub_mcu_send_complete(rproc_msg_t *ack_buffer,
				rproc_msg_len_t ack_buffer_len,
				int error,
				void *data)
{
    complete(&send_complete);
    	
    if ((-ETIMEOUT) == error) {
        hwlog_err("send failed timeout\n");
	        if(!dsm_client_ocuppy(shb_dclient)){
                    dsm_client_record(shb_dclient, "IOM3RSTSTAT: 0x%x\n", read_reg32(IOM3RSTSTAT_ADDR));
                    dsm_client_record(shb_dclient, "PERRSTSTAT4: 0x%x\n", read_reg32(PERRSTSTAT4_ADDR));
                    dsm_client_record(shb_dclient, "PERSTAT5: 0x%x\n", read_reg32(PERSTAT5_ADDR));
                    dsm_client_record(shb_dclient, "IOM3CLKEN: 0x%x\n", read_reg32(IOM3CLKEN_ADDR));
                    dsm_client_notify(shb_dclient, DSM_SHB_ERR_IPC_TIMEOUT);
            }
    }else{
    hwlog_debug("send success\n");
    }	
    return;
}
int inputhub_mcu_send(const char *buf, unsigned long length)
{
    struct hisi_mbox_task *tx_task = NULL;
    mbox_msg_t *tx_buffer = NULL;
    mbox_msg_len_t len=0;
    int i = 0;
    int ret = -1;

    if(NULL==mbox)
        inputhub_mcu_connect();
    if(NULL==mbox)
        return ret;

    len = (length + sizeof(mbox_msg_t) - 1) / (sizeof(mbox_msg_t));
    //todo:send 256 bytes max one time, and repeat until buf was sent.
    tx_buffer = (mbox_msg_t *)kmalloc(sizeof(mbox_msg_t)*len, GFP_KERNEL);
    if (!tx_buffer)
        return ret;

    memcpy(tx_buffer, buf, length);
    pr_debug("inputhub_mcu_send------------->length = %d, len = %d\n", (int)length, (int)len);
    for (i = 0; i < len; i++)
        pr_debug("tx_buffer[%d] = 0x%x\n", i, tx_buffer[i]);

    tx_task = hisi_mbox_task_alloc(mbox,
                HISI_MAILBOX_RP_IOM3,
                tx_buffer,
                len,
                0,
                inputhub_mcu_send_complete,
                NULL);

    if (!tx_task) {
        kfree((void *)tx_buffer);
        return ret;
    }

    INIT_COMPLETION(send_complete);
    ret=hisi_mbox_msg_send_async(mbox,tx_task);
    if(ret)
    {
        hwlog_err("hisi_mbox_msg_send_async return %d.\n", ret);
        if (tx_task->tx_buffer)
            kfree((void *)tx_task->tx_buffer);
        tx_task->tx_buffer = NULL;
        hisi_mbox_task_free(&tx_task);
        return -1;
    }

    wait_for_completion(&send_complete);
    if ((-ETIMEOUT) == tx_task->tx_error) {
        hwlog_err("send failed timeout\n");
        if(!dsm_client_ocuppy(shb_dclient)){
            dsm_client_record(shb_dclient, "IOM3RSTSTAT: 0x%x\n", read_reg32(IOM3RSTSTAT_ADDR));
            dsm_client_record(shb_dclient, "PERRSTSTAT4: 0x%x\n", read_reg32(PERRSTSTAT4_ADDR));
            dsm_client_record(shb_dclient, "PERSTAT5: 0x%x\n", read_reg32(PERSTAT5_ADDR));
            dsm_client_record(shb_dclient, "IOM3CLKEN: 0x%x\n", read_reg32(IOM3CLKEN_ADDR));
            dsm_client_notify(shb_dclient, DSM_SHB_ERR_IPC_TIMEOUT);
        }
        ret = -1;
    }else{
        hwlog_debug("send success\n");
        ret = 0;
    }

    kfree((void *)tx_task->tx_buffer);
    tx_task->tx_buffer = NULL;
    hisi_mbox_task_free(&tx_task);
    return ret;
}
/**
 * modem_read - read data from modem
 *
 * Returns:
 *   none
 */
int modem_read(char* pt_buf, int t_include_head, int t_head_size, int t_len)
{
    unsigned char* p_cur_buf = NULL; /* point to current available space for write in txrx common buf */
    int ret = 0;
    int status = 0;
    int err_flag = 0;
    unsigned int left_rx_pkt_len = 0; /* remain rx packet length */
    unsigned int cur_read_len = 0;
    char rst_buf[CBP_EXCEPT_STACK_LEN] = {0};
    modem_bus_t* p_cur_bus = NULL;
    unsigned int no_ack_times = 0;

    if ((NULL == pt_buf) || (t_len < 0))
    {
        hwlog_err("%s %d input parameter invalid, pt_buf=0x%lx, t_len=%d\n", __func__, __LINE__, (unsigned long)pt_buf, t_len);
        ret = -1;
        goto out;
    }

    /* first judge if the modem is power off */
    if (0 == get_modem_bus_state())
    {
        hwlog_err("%s %d: VIA modem reset happened\n", __func__, __LINE__);
        return -2;
    }

    if (NULL == g_ext_modem.pm_cur_bus)
    {
        hwlog_err("%s %d: current ext modem bus is NULL\n", __func__, __LINE__);
        return -3;
    }

    p_cur_bus = g_ext_modem.pm_cur_bus;

    /* get the read length */
    left_rx_pkt_len = t_len;

    if (t_include_head)   /* read include packet header */
    {
        if (left_rx_pkt_len <= g_ext_modem.pm_cur_bus->m_fifo_size)
        {
            cur_read_len = left_rx_pkt_len;
        }
        else
        {
            cur_read_len = g_ext_modem.pm_cur_bus->m_fifo_size;
        }
    }
    else     /* only read packet payload */
    {
        if (left_rx_pkt_len <= (g_ext_modem.pm_cur_bus->m_fifo_size - t_head_size))
        {
            cur_read_len = left_rx_pkt_len;
        }
        else
        {
            cur_read_len = g_ext_modem.pm_cur_bus->m_fifo_size - t_head_size;
        }
    }

    /* get the current available buffer address */
    p_cur_buf = pt_buf;
    hwlog_debug("%s %d: read subpacket buf addr=0x%lx, current read length is %d.\n", \
                __func__, __LINE__, (unsigned long)p_cur_buf, cur_read_len);

    do
    {
        /* reset DATA ACK state to inactvie just before bus read or write */
        reset_apcp_gpio_state(GPIO_APCP_DATA_ACK);

        /* read left packet payload */
        do
        {
            hwlog_debug("%s %d: read subpacket buf addr=0x%lx, current read length is %d.\n", \
                        __func__, __LINE__, (unsigned long)p_cur_buf, cur_read_len);
            /* do actual read */
            //if (t_len > t_head_size)
            {
                status = g_ext_modem.pm_cur_bus->pfm_bus_read(p_cur_buf, cur_read_len);
            }

            if (status)
            {
                hwlog_err("%s %d: sync error has reached MAX FAILed times.\n", __func__, __LINE__);
                apcp_current_subpacket_printk(p_cur_buf, cur_read_len, 1, 0);
                ret = -4;
                goto out;
            }

            /* refresh remain packet data length */
            left_rx_pkt_len -= cur_read_len;

            /* calculate how long to read for current bus read */
            cur_read_len = (left_rx_pkt_len > g_ext_modem.pm_cur_bus->m_fifo_size) ? g_ext_modem.pm_cur_bus->m_fifo_size : left_rx_pkt_len;
            /* get the current available buffer address */
            p_cur_buf += cur_read_len;
        }
        while (left_rx_pkt_len);

        ret = wait_apcp_gpio_state(GPIO_APCP_DATA_ACK);

        if (0 == ret) /* return success */
        {
            break;
        }
        else if (-1 == ret) /* wait data ack timeout */
        {
            /* increase no ack times */
            no_ack_times++;
            hwlog_err("%s %d: ext modem read wait data ack failed times=%d, ret=%d\n", __func__, __LINE__, no_ack_times, ret);
            apcp_current_subpacket_printk(pt_buf, t_len, 0, 0);
            modem_dsm_client_notify("ext modem read wait data ack fail ret=", ret, DSM_SPI_READ_ACK_ERROR_NO);
        }
        else
        {
            hwlog_err("%s %d: wait data ack fail, ret=%d\n", __func__, __LINE__, ret);
            ret = -5;
            break;
        }

        /* judge if no ack times reach MAX retry times */
        if (no_ack_times >= MAX_WAIT_DATA_ACK_RETRY)
        {
            err_flag = 1;
            hwlog_err("%s %d: had retry read reach MAX retry times\n", __func__, __LINE__);
            ret = -6;
            break;
        }
    }
    while (1);

out:

    if (err_flag != 0)
    {
        snprintf(rst_buf, CBP_EXCEPT_STACK_LEN - 1, "%s %d:read error notify VIA CBP to produce ramdump.\n", __func__, __LINE__);
        hwlog_err("%s %d: read error notify VIA CBP to produce ramdump.\n", __func__, __LINE__);
        modem_err_indication_usr_form_module(rst_buf, CBP_EXCEPT_REASON_SPI, CBP_EXCE_MID_SPI_READ_TIMEOUT);
    }

    return ret;
}
/**
 * modem_write - write a packet payload data through bus
 * @pt_pkt_buf: high-level buffer address of packet payload data
 * @pt_header: in pointer to packet header
 *
 * Returns:
 *   0 - success write whole packet
 *   minus - error occurred when write whole tx packet
 */
int modem_write(char* pt_pkt_buf, int t_len)
{
    unsigned char* p_tx_subpkt_buf = NULL; /* point to current available space for write in tx packet buf */
    unsigned int cur_write_len = 0; /* current write length to the bus */
    int ret_wait_hw_fc = 0; /* wait and check hardware flow control to disable*/
    unsigned int left_tx_pkt_len = 0; /* remain tx packet length */
    int ret = 0;
    int err_flag = 0;
    char rst_buf[CBP_EXCEPT_STACK_LEN] = {0};
    modem_bus_t* p_cur_bus = NULL;
    unsigned int no_ack_times = 0;

    if ((NULL == pt_pkt_buf) || (0 == t_len))
    {
        hwlog_err("%s %d: NULL pointer! pt_pkt_buf=0x%lx, len=%d\n", \
                  __func__, __LINE__, (unsigned long)pt_pkt_buf, t_len);
        return -1;
    }

    /* first judge if the modem is power off */
    if (0 == get_modem_bus_state())
    {
        hwlog_err("%s %d: VIA modem reset happened\n", __func__, __LINE__);
        return -2;
    }

    if (NULL == g_ext_modem.pm_cur_bus)
    {
        hwlog_err("%s %d: current ext modem bus is NULL\n", __func__, __LINE__);
        return -3;
    }

    p_cur_bus = g_ext_modem.pm_cur_bus;

    /* wait until hardware flow control disabled */
    ret_wait_hw_fc = wait_apcp_gpio_state(GPIO_APCP_FLOW_CTRL);

    if (ret_wait_hw_fc)
    {
        if (-1 == ret_wait_hw_fc)
        {
            ret = -2;
            err_flag = 1; //notify CBP to produce ramdump
            hwlog_err("%s %d: wait hardware flow ctrl disable timeout. current packet is:\n", __func__, __LINE__);
            apcp_current_subpacket_printk(p_tx_subpkt_buf, left_tx_pkt_len, 1, 0);
        }
        else if (-2 == ret_wait_hw_fc)
        {
            ret = -3;
            hwlog_err("%s %d: ext modem reset has happened, just return.\n", __func__, __LINE__);
        }

        goto down_out;
    }

    /* split the long packet to small subpackets according to actual bus fifo size */
    /* point to the start address of tx packet buf */
    p_tx_subpkt_buf = pt_pkt_buf;
    left_tx_pkt_len = t_len;
    hwlog_debug("%s %d: write subpacket addr=0x%lx, packet length is %d.\n", \
                __func__, __LINE__, (unsigned long)p_tx_subpkt_buf, left_tx_pkt_len);

    while (left_tx_pkt_len)
    {
        /* compare the left data length in buf and actual bus fifo size */
        if (left_tx_pkt_len > p_cur_bus->m_fifo_size)
        {
            cur_write_len = p_cur_bus->m_fifo_size;
        }
        else
        {
            cur_write_len = left_tx_pkt_len;
        }

        /* wakeup cp just before write */
        ret = ap_tx_wait_cp_ready();

        if (ret)
        {
            if (-2 == ret) /* wait cp ready timeout */
            {
                modem_dsm_client_notify("can NOT wake up CBP ret=", ret, DSM_SPI_AUTO_READY_ERROR_NO);
            }
            hwlog_err("%s %d: can NOT wake up CBP ret=%d! current packet is:\n", __func__, __LINE__, ret);
            apcp_current_subpacket_printk(p_tx_subpkt_buf, left_tx_pkt_len, 1, 0);
            ret = -1;
            goto down_out;
        }

        if (0 == get_modem_bus_state())
        {
            hwlog_err("%s %d: VIA modem reset happened\n", __func__, __LINE__);
            ret = -4;
            goto down_out;
        }

        /* make sure ap bus SPI/SDIO controller had resumed before write */
        ret = wait_ap_bus_resumed();

        if (ret)
        {
            hwlog_err("%s %d:wait Host controller to resume FAILED!", __func__, __LINE__);
            ret = -5;
            goto down_out;
        }

        if (p_cur_bus->pfm_bus_lock)
        {
            p_cur_bus->pfm_bus_lock(1);
        }

        if (0 == get_modem_bus_state())
        {
            hwlog_err("%s %d: VIA modem reset happened\n", __func__, __LINE__);
            if (p_cur_bus->pfm_bus_lock)
            {
                p_cur_bus->pfm_bus_lock(0);
            }
            ret = -4;
            goto down_out;
        }

        /* first disable bus irq */
        if (p_cur_bus->pfm_bus_irq_enable)
        {
            p_cur_bus->pfm_bus_irq_enable(0);
        }

        do
        {
            /* reset DATA ACK state to inactive just before bus write */
            reset_apcp_gpio_state(GPIO_APCP_DATA_ACK);

            /* do actual bus write current subpacket */
            ret = p_cur_bus->pfm_bus_write(p_tx_subpkt_buf, cur_write_len);

            ret = wait_apcp_gpio_state(GPIO_APCP_DATA_ACK);

            if (0 == ret) /* return success */
            {
                break;
            }
            else if (-1 == ret) /* wait data ack timeout */
            {
                no_ack_times++;
                hwlog_err("%s %d: via bus write wait data ack failed times=%d, ret=%d\n", __func__, __LINE__, no_ack_times, ret);
                apcp_current_subpacket_printk(p_tx_subpkt_buf, cur_write_len, 1, 0);
                modem_dsm_client_notify("via bus write wait data ack fail ret=", ret, DSM_APCP_SDIO_WRITE_ACK_ERROR_NO);
            }
            else
            {
                hwlog_err("%s %d: wait data ack fail, ret=%d\n", __func__, __LINE__, ret);
                ret = -6;
                break;
            }

            /* judge if no ack times reach MAX retry times */
            if (no_ack_times >= MAX_WAIT_DATA_ACK_RETRY)
            {
                err_flag = 1;
                hwlog_err("%s %d: had retry write reach MAX retry times\n", __func__, __LINE__);
                ret = -7;
                break;
            }
        }
        while (1);

        /* enable bus irq after write */
        if (p_cur_bus->pfm_bus_irq_enable)
        {
            p_cur_bus->pfm_bus_irq_enable(1);
        }

        if (p_cur_bus->pfm_bus_lock)
        {
            p_cur_bus->pfm_bus_lock(0);
        }

        if (ret)
        {
            hwlog_err("%s %d: write to ext modem FAILed ret=%d\n", __func__, __LINE__, ret);
            apcp_current_subpacket_printk(p_tx_subpkt_buf, cur_write_len, 1, 0);
            goto down_out;
        }

        /* recalculate remain data addr and length in txrx common buf */
        p_tx_subpkt_buf += cur_write_len;
        /* refresh left tx packet length */
        left_tx_pkt_len -= cur_write_len;
    }

down_out:

    if (err_flag != 0)
    {
        snprintf(rst_buf, CBP_EXCEPT_STACK_LEN - 1, "%s %d:write error notify VIA CBP to produce ramdump.\n", __func__, __LINE__);
        hwlog_err("%s %d: write error notify VIA CBP to produce ramdump.\n", __func__, __LINE__);
        modem_err_indication_usr_form_module(rst_buf, CBP_EXCEPT_REASON_SPI, CBP_EXCE_MID_SPI_WRITE_TIMEOUT);
    }

    /* return result of write */
    return ret;
}
예제 #17
0
static int cbp_probe(struct platform_device *pdev)
{
	struct cbp_platform_data *plat = NULL;
	int ret = -1;
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;

	ret = platform_device_add_data(pdev, &cbp_data, sizeof(struct cbp_platform_data));
	if (ret < 0) {
		hwlog_err("%s: add platform_data failed!\n", __func__);
		goto err_add_data_to_platform_device;
	}

	plat = pdev->dev.platform_data;
	/* must have platform data */
	if (!plat) {
		hwlog_err("%s: no platform data!\n", __func__);
		ret = -EINVAL;
		goto err_add_data_to_platform_device;
	}

	plat->gpio_data_ack = of_get_named_gpio(np, "via_data_ack", 0);
	hwlog_info(">>>> %s get via_data_ack gpio %d\n", __func__, plat->gpio_data_ack);
	if(GPIO_OEM_VALID(plat->gpio_data_ack)){
		cbp_data_ack = kzalloc(sizeof(struct cbp_wait_event), GFP_KERNEL);
		if (!cbp_data_ack){
			ret = -ENOMEM;
			hwlog_err("%s %d kzalloc cbp_data_ack failed \n",__func__, __LINE__);
			goto err_kzalloc_cbp_data_ack;
		}

		init_waitqueue_head(&cbp_data_ack->wait_q);
		atomic_set(&cbp_data_ack->state, MODEM_ST_UNKNOW);
		cbp_data_ack->wait_gpio = plat->gpio_data_ack;
		cbp_data_ack->wait_polar = plat->gpio_data_ack_polar;
		hwlog_info("cbp_data_ack->wait_gpio=%d\n",cbp_data_ack->wait_gpio);
		hwlog_info("cbp_data_ack->wait_polar=%d\n",cbp_data_ack->wait_polar);
		ret = oem_gpio_request(plat->gpio_data_ack, DRIVER_NAME "(data_ack)");
		if(ret < 0){
			hwlog_err("%s: %d fail to requset data_ack gpio %d ret =%d!!\n",
				__func__, __LINE__, plat->gpio_data_ack, ret);
			goto err_req_data_ack;
		}
		oem_gpio_irq_mask(plat->gpio_data_ack);
		oem_gpio_direction_input_for_irq(plat->gpio_data_ack);
		//on powerup, there is ack low level to high level jump.
		oem_gpio_set_irq_type(plat->gpio_data_ack, IRQF_TRIGGER_FALLING);
		ret = oem_gpio_request_irq(plat->gpio_data_ack, gpio_irq_via_spi_tx_rx_fifo_empty_ack,
				IRQF_SHARED | IRQF_TRIGGER_FALLING, DRIVER_NAME "(data_ack)", cbp_data_ack);
		oem_gpio_irq_unmask(plat->gpio_data_ack);
		if (ret < 0) {
			hwlog_err("%s: %d fail to request irq for data_ack!!\n", __func__, __LINE__);
			goto err_req_irq_data_ack;
		}
		plat->cbp_data_ack = cbp_data_ack;
		plat->data_ack_wait_event = data_ack_wait_event;
		plat->data_ack_enable =true;
	}

	plat->gpio_flow_ctrl = of_get_named_gpio(np, "via_flow_ctrl", 0);
	hwlog_info(">>>> %s get via_flow_ctrl gpio %d\n", __func__, plat->gpio_flow_ctrl);
	if(GPIO_OEM_VALID(plat->gpio_flow_ctrl)){
		cbp_flow_ctrl = kzalloc(sizeof(struct cbp_wait_event), GFP_KERNEL);
		if (!cbp_flow_ctrl){
			ret = -ENOMEM;
			hwlog_err("%s %d kzalloc cbp_flow_ctrl failed \n",__func__, __LINE__);
			goto err_kzalloc_cbp_flow_ctrl;
		}

		init_waitqueue_head(&cbp_flow_ctrl->wait_q);
		atomic_set(&cbp_flow_ctrl->state, FLOW_CTRL_DISABLE);
		cbp_flow_ctrl->wait_gpio = plat->gpio_flow_ctrl;
		cbp_flow_ctrl->wait_polar = plat->gpio_flow_ctrl_polar;
		hwlog_info("cbp_flow_ctrl->wait_gpio=%d\n",cbp_flow_ctrl->wait_gpio);
		hwlog_info("cbp_flow_ctrl->wait_polar=%d\n",cbp_flow_ctrl->wait_polar);
		ret = oem_gpio_request(plat->gpio_flow_ctrl, DRIVER_NAME "(flow_ctrl)");
		if(ret < 0){
			hwlog_err("%s: %d fail to requset flow_ctrl gpio %d ret =%d!!\n",
				__func__, __LINE__, plat->gpio_flow_ctrl, ret);
			goto err_req_flow_ctrl;
		}
		oem_gpio_irq_mask(plat->gpio_flow_ctrl);
		oem_gpio_direction_input_for_irq(plat->gpio_flow_ctrl);
		oem_gpio_set_irq_type(plat->gpio_flow_ctrl, IRQF_TRIGGER_FALLING);
		ret = oem_gpio_request_irq(plat->gpio_flow_ctrl, gpio_irq_flow_ctrl,
				IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				DRIVER_NAME "(flow_ctrl)", cbp_flow_ctrl);
		oem_gpio_irq_unmask(plat->gpio_flow_ctrl);
		if (ret < 0) {
			hwlog_err("%s: %d fail to request irq for flow_ctrl!!\n", __func__, __LINE__);
			goto err_req_irq_flow_ctrl;
		}

		plat->cbp_flow_ctrl= cbp_flow_ctrl;
		plat->flow_ctrl_wait_event = flow_ctrl_wait_event;
		plat->flow_ctrl_enable = true;
	}

	plat->gpio_via_requst_to_send = of_get_named_gpio(np, "via_requst_to_send", 0);
	hwlog_info(">>>> %s get via_requst_to_send gpio %d\n", __func__, plat->gpio_via_requst_to_send);
	if(GPIO_OEM_VALID(plat->gpio_via_requst_to_send)){
		ret = oem_gpio_request(plat->gpio_via_requst_to_send, DRIVER_NAME "(via_requst_to_send)");
		if(ret < 0){
			hwlog_err("%s: %d fail to requset flow_ctrl gpio %d ret =%d!!\n",
				__func__, __LINE__, plat->gpio_via_requst_to_send, ret);
			goto err_req_via_requst_to_send;
		}
		oem_gpio_irq_mask(plat->gpio_via_requst_to_send);
		oem_gpio_direction_input_for_irq(plat->gpio_via_requst_to_send);
		oem_gpio_set_irq_type(plat->gpio_via_requst_to_send, IRQF_TRIGGER_FALLING);
		ret = oem_gpio_request_irq(plat->gpio_via_requst_to_send, gpio_irq_via_rts,
				IRQF_SHARED | IRQF_TRIGGER_RISING,
				DRIVER_NAME "(via_requst_to_send)", &cbp_data); //api request the fifth argu NOT NULL.
		oem_gpio_irq_unmask(plat->gpio_via_requst_to_send);
		if (ret < 0) {
			hwlog_err("%s: %d fail to request irq for via_requst_to_send!!\n", __func__, __LINE__);
			goto err_req_irq_via_requst_to_send;
		}
	}

	plat->gpio_rst_ind = of_get_named_gpio(np, "via_reset_ind", 0);
	hwlog_info(">>>> %s get rst_ind gpio %d\n", __func__, plat->gpio_rst_ind);
	if(GPIO_OEM_VALID(plat->gpio_rst_ind)){
		cbp_data.gpio_rst_ind= plat->gpio_rst_ind;
		cbp_data.gpio_rst_ind_polar = plat->gpio_rst_ind_polar;

		atomic_set(&cbp_rst_ind_finished, 0);
		plat->rst_ind_enable = true;
	}
	plat->gpio_ap_wkup_cp= of_get_named_gpio(np, "via_ap_wkup_cp", 0);
	hwlog_info(">>>> %s get ap_wkup_cp gpio %d\n", __func__, plat->gpio_ap_wkup_cp);

	plat->gpio_cp_ready= of_get_named_gpio(np, "via_cp_ready", 0);
	hwlog_info(">>>> %s get cp_ready gpio %d\n", __func__, plat->gpio_cp_ready);

	plat->gpio_cp_wkup_ap= of_get_named_gpio(np, "via_cp_wkup_ap", 0);
	hwlog_info(">>>> %s get cp_wkup_ap gpio %d\n", __func__, plat->gpio_cp_wkup_ap);

	plat->gpio_ap_ready= of_get_named_gpio(np, "via_ap_ready", 0);
	hwlog_info(">>>> %s get ap_ready gpio %d\n", __func__, plat->gpio_ap_ready);
	if((GPIO_OEM_VALID(plat->gpio_ap_wkup_cp)) && (GPIO_OEM_VALID(plat->gpio_cp_ready)) &&
		(GPIO_OEM_VALID(plat->gpio_cp_wkup_ap))  && (GPIO_OEM_VALID(plat->gpio_ap_ready))){
		spi_tx_handle.gpio_wake = plat->gpio_ap_wkup_cp;
		spi_tx_handle.gpio_ready = plat->gpio_cp_ready;
		spi_tx_handle.polar = plat->gpio_sync_polar;
		ret = asc_tx_register_handle(&spi_tx_handle);
		if(ret){
			hwlog_err("%s %d asc_tx_register_handle failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}
		ret = asc_tx_add_user(spi_tx_handle.name, &spi_tx_user);
		if(ret){
			hwlog_err("%s %d asc_tx_add_user failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}

		spi_rx_handle.gpio_wake = plat->gpio_cp_wkup_ap;
		spi_rx_handle.gpio_ready = plat->gpio_ap_ready;
		spi_rx_handle.polar = plat->gpio_sync_polar;
		ret = asc_rx_register_handle(&spi_rx_handle);
		if(ret){
			hwlog_err("%s %d asc_rx_register_handle failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}
		ret = asc_rx_add_user(spi_rx_handle.name, &spi_rx_user);
		if(ret){
			hwlog_err("%s %d asc_rx_add_user failed.\n",__FUNCTION__,__LINE__);
			goto err_ipc;
		}
		plat->ipc_enable = true;
		plat->tx_handle = &spi_tx_handle;
	}

	ret = plat->cbp_setup(plat);
	if(ret){
		hwlog_err("%s: host %s setup failed!\n", __func__, plat->host_id);
		goto err_ipc;
	}

	cbp_power_kobj = viatel_kobject_add("power");
	if (!cbp_power_kobj){
		hwlog_err("error viatel_kobject_add!\n");
		ret = -ENOMEM;
		goto err_create_kobj;
	}

	hwlog_debug(" cbp initialized on host %s successfully, bus is %s !\n", plat->host_id, plat->bus);
	return sysfs_create_group(cbp_power_kobj, &g_power_attr_group);

err_create_kobj:
	plat->cbp_destroy();
err_ipc:
	if(GPIO_OEM_VALID(plat->gpio_via_requst_to_send)){
		free_irq(oem_gpio_to_irq(plat->gpio_via_requst_to_send), NULL);
	}
err_req_irq_via_requst_to_send:
	if(GPIO_OEM_VALID(plat->gpio_via_requst_to_send)){
		oem_gpio_free(plat->gpio_via_requst_to_send);
	}
err_req_via_requst_to_send:
	if(GPIO_OEM_VALID(plat->gpio_data_ack)){
		free_irq(oem_gpio_to_irq(plat->gpio_flow_ctrl), cbp_flow_ctrl);
	}
err_req_irq_flow_ctrl:
	if(GPIO_OEM_VALID(plat->gpio_flow_ctrl)){
		oem_gpio_free(plat->gpio_flow_ctrl);
	}
err_req_flow_ctrl:
	if(GPIO_OEM_VALID(plat->gpio_flow_ctrl)){
		kfree(cbp_flow_ctrl);
	}
err_kzalloc_cbp_flow_ctrl:
	if(GPIO_OEM_VALID(plat->gpio_data_ack)){
		free_irq(oem_gpio_to_irq(plat->gpio_data_ack), cbp_data_ack);
	}
err_req_irq_data_ack:
	if(GPIO_OEM_VALID(plat->gpio_data_ack)){
		oem_gpio_free(plat->gpio_data_ack);
	}
err_req_data_ack:
	if(GPIO_OEM_VALID(plat->gpio_data_ack)){
		kfree(cbp_data_ack);
	}
err_kzalloc_cbp_data_ack:
err_add_data_to_platform_device:
	return ret;
}
void hwlog_vma_close(struct vm_area_struct *vma)
{
	hwlog_debug("hwlog map close\n");
}
void hwlog_vma_open(struct vm_area_struct *vma)
{
	hwlog_debug("hwlog map open\n");
} 
static ssize_t hwlog_read(struct file *file, char __user *buf, size_t count,
			     loff_t *pos)
{
	hwlog_debug("%s enter\n", __func__);
	return 0;
}
static int hwlog_release(struct inode *inode, struct file *file)
{
	hwlog_debug("%s enter\n", __func__);
	return 0;
}
static int create_imem_node(void)
{
	hwlog_debug("create imem node\n");
	return 0;
}
/**********************************************************
*  Function:       charge_core_parse_dts
*  Discription:    parse the module dts config value
*  Parameters:   np:device_node
*                      di:charge_core_info
*  return value:  0-sucess or others-fail
**********************************************************/
static int charge_core_parse_dts(struct device_node* np, struct charge_core_info *di)
{
    int ret = 0;
    int i = 0;
    int array_len = 0;
    int idata = 0;
    const char *chrg_data_string = NULL;

    /*ac charge current*/
    ret = of_property_read_u32(np, "iin_ac", &(di->data.iin_ac));
    if(ret)
    {
        hwlog_err("get iin_ac failed\n");
        return -EINVAL;
    }
    hwlog_debug("iin_ac = %d\n",di->data.iin_ac);
    ret = of_property_read_u32(np, "ichg_ac", &(di->data.ichg_ac));
    if(ret)
    {
        hwlog_err("get ichg_ac failed\n");
        return -EINVAL;
    }
    hwlog_debug("ichg_ac = %d\n",di->data.ichg_ac);

    /*fcp charge current */
    ret = of_property_read_u32(np,"iin_fcp",&(di->data.iin_fcp));
    if(ret)
    {
        hwlog_info("get iin_fcp failed ,use iin_ac's value instead \n");
        di->data.iin_fcp = di->data.iin_ac;
    }
    hwlog_debug("iin_fcp = %d\n",di->data.iin_fcp);
    ret = of_property_read_u32(np,"ichg_fcp",&(di->data.ichg_fcp));
    if(ret)
    {
        hwlog_info("get ichg_fcp failed ,use ichg_ac's value instead \n");
        di->data.ichg_fcp = di->data.ichg_ac;
    }
    hwlog_debug("ichg_fcp = %d\n",di->data.ichg_fcp);

    /*usb charge current*/
    ret = of_property_read_u32(np, "iin_usb", &(di->data.iin_usb));
    if(ret)
    {
        hwlog_err("get iin_usb failed\n");
        return -EINVAL;
    }
    hwlog_debug("iin_usb = %d\n",di->data.iin_usb);
    ret = of_property_read_u32(np, "ichg_usb", &(di->data.ichg_usb));
    if(ret)
    {
        hwlog_err("get ichg_usb failed\n");
        return -EINVAL;
    }
    hwlog_debug("ichg_usb = %d\n",di->data.ichg_usb);
    /*nonstandard charge current*/
    ret = of_property_read_u32(np, "iin_nonstd", &(di->data.iin_nonstd));
    if(ret)
    {
        hwlog_err("get iin_nonstd failed\n");
        return -EINVAL;
    }
    hwlog_debug("iin_nonstd = %d\n",di->data.iin_nonstd);
    ret = of_property_read_u32(np, "ichg_nonstd", &(di->data.ichg_nonstd));
    if(ret)
    {
        hwlog_err("get ichg_nonstd failed\n");
        return -EINVAL;
    }
    hwlog_debug("ichg_nonstd = %d\n",di->data.ichg_nonstd);
    /*Charging Downstream Port*/
    ret = of_property_read_u32(np, "iin_bc_usb", &(di->data.iin_bc_usb));
    if(ret)
    {
        hwlog_err("get iin_bc_usb failed\n");
        return -EINVAL;
    }
    hwlog_debug("iin_bc_usb = %d\n",di->data.iin_bc_usb);
    ret = of_property_read_u32(np, "ichg_bc_usb", &(di->data.ichg_bc_usb));
    if(ret)
    {
        hwlog_err("get ichg_bc_usb failed\n");
        return -EINVAL;
    }
    hwlog_debug("ichg_bc_usb = %d\n",di->data.ichg_bc_usb);
    /*terminal current*/
    ret = of_property_read_u32(np, "iterm", &(di->data.iterm));
    if(ret)
    {
        hwlog_err("get iterm failed\n");
        return -EINVAL;
    }
    hwlog_debug("iterm = %d\n",di->data.iterm);
    /*otg current*/
    ret = of_property_read_u32(np, "otg_curr", &(di->data.otg_curr));
    if(ret)
    {
        hwlog_err("get otg_curr failed\n");
        return -EINVAL;
    }
    hwlog_debug("otg_curr = %d\n",di->data.otg_curr);

    //vdpm_para
    array_len = of_property_count_strings(np, "vdpm_para");
    if ((array_len <= 0) || (array_len % VDPM_PARA_TOTAL != 0))
    {
        hwlog_err("vdpm_para is invaild,please check vdpm_para number!!\n");
        return -EINVAL;
    }

    if (array_len > VDPM_PARA_LEVEL * VDPM_PARA_TOTAL)
    {
        array_len = VDPM_PARA_LEVEL * VDPM_PARA_TOTAL;
        hwlog_err("vdpm_para is too long,use only front %d paras!!\n", array_len);
        return -EINVAL;
    }

    memset(di->vdpm_para, 0, VDPM_PARA_LEVEL * sizeof(struct charge_vdpm_data)); // data reset to 0

    for (i = 0; i < array_len; i++)
    {
        ret = of_property_read_string_index(np, "vdpm_para", i, &chrg_data_string);
        if (ret)
        {
            hwlog_err("get vdpm_para failed\n");
            return -EINVAL;
        }

        idata = simple_strtol(chrg_data_string, NULL, 10);
        switch (i % VDPM_PARA_TOTAL)
        {
        case VDPM_PARA_CAP_MIN:
            if ((idata < VDPM_CBAT_MIN) || (idata > VDPM_CBAT_MAX))
            {
                hwlog_err("the vdpm_para cap_min is out of range!!\n");
                return -EINVAL;
            }
            di->vdpm_para[ i/ (VDPM_PARA_TOTAL)].cap_min = idata;
            break;
        case VDPM_PARA_CAP_MAX:
            if((idata < VDPM_CBAT_MIN) || (idata > VDPM_CBAT_MAX))
            {
                hwlog_err("the vdpm_para cap_max is out of range!!\n");
                return -EINVAL;
            }
            di->vdpm_para[i / (VDPM_PARA_TOTAL)].cap_max = idata;
            break;
        case VDPM_PARA_DPM:
            if((idata < VDPM_VOLT_MIN) || (idata > VDPM_VOLT_MAX))
            {
                hwlog_err("the vdpm_para vin_dpm is out of range!!\n");
                return -EINVAL;
            }
            di->vdpm_para[i / (VDPM_PARA_TOTAL)].vin_dpm = idata;
            break;
        case VDPM_PARA_CAP_BACK:
            if((idata < 0) || (idata > VDPM_CAP_DETA))
            {
                hwlog_err("the vdpm_para cap_back is out of range!!\n");
                return -EINVAL;
            }
            di->vdpm_para[i / (VDPM_PARA_TOTAL)].cap_back = idata;
            break;
        default:
            hwlog_err("get vdpm_para failed\n");
        }
        hwlog_debug("di->vdpm_para[%d][%d] = %d\n", i / (VDPM_PARA_TOTAL),
                    i % (VDPM_PARA_TOTAL), idata);
    }

    /* inductance_para */
    memset(di->inductance_para, 0, INDUCTANCE_PARA_LEVEL * sizeof(struct charge_inductance_data)); // data reset to 0

    array_len = of_property_count_strings(np, "inductance_para");
    if ((array_len <= 0) || (array_len % INDUCTANCE_PARA_TOTAL != 0))
    {
        hwlog_err("inductance_para is invaild,please check inductance_para number!!\n");
        return -EINVAL;
    }
    if (array_len > INDUCTANCE_PARA_LEVEL * INDUCTANCE_PARA_TOTAL)
    {
        array_len = INDUCTANCE_PARA_LEVEL * INDUCTANCE_PARA_TOTAL;
        hwlog_err("inductance_para is too long,use only front %d paras!!\n", array_len);
        return -EINVAL;
    }

    for(i = 0; i < array_len ; i++)
    {
        ret = of_property_read_string_index(np, "inductance_para", i, &chrg_data_string);
        if (ret)
        {
            hwlog_err("get inductance_para failed\n");
            return -EINVAL;
        }

        idata = simple_strtol(chrg_data_string, NULL, 10);
        switch (i % INDUCTANCE_PARA_TOTAL)
        {
        case INDUCTANCE_PARA_CAP_MIN:
            if ((idata < INDUCTANCE_CBAT_MIN) || (idata > INDUCTANCE_CBAT_MAX))
            {
                hwlog_err("the inductance_para cap_min is out of range!!\n");
                return -EINVAL;
            }
            di->inductance_para[ i/ (INDUCTANCE_PARA_TOTAL)].cap_min = idata;
            break;
        case INDUCTANCE_PARA_CAP_MAX:
            if ((idata < INDUCTANCE_CBAT_MIN) || (idata > INDUCTANCE_CBAT_MAX))
            {
                hwlog_err("the inductance_para cap_max is out of range!!\n");
                return -EINVAL;
            }
            di->inductance_para[i / (INDUCTANCE_PARA_TOTAL)].cap_max = idata;
            break;
        case INDUCTANCE_PARA_IIN:
            if ((idata < INDUCTANCE_IIN_MIN) || (idata > INDUCTANCE_IIN_MAX))
            {
                hwlog_err("the inductance_para iin is out of range!!\n");
                return -EINVAL;
            }
            di->inductance_para[i / (INDUCTANCE_PARA_TOTAL)].iin_inductance= idata;
            break;
        case INDUCTANCE_PARA_CAP_BACK:
            if ((idata < 0) || (idata > INDUCTANCE_CAP_DETA))
            {
                hwlog_err("the inductance_para cap_back is out of range!!\n");
                return -EINVAL;
            }
            di->inductance_para[i / (INDUCTANCE_PARA_TOTAL)].cap_back = idata;
            break;
        default:
            hwlog_err("get vdpm_para failed\n");
        }
        hwlog_info("di->inductance_para[%d][%d] = %d\n", i / (INDUCTANCE_PARA_TOTAL),
                   i % (INDUCTANCE_PARA_TOTAL), idata);
    }

    if(strstr(saved_command_line, "androidboot.swtype=factory") && (!is_hisi_battery_exist()))
    {
        di->data.iin_ac = CHARGE_CURRENT_2000_MA;
        di->data.ichg_ac = CHARGE_CURRENT_1900_MA;
        di->data.iin_bc_usb = CHARGE_CURRENT_2000_MA;
        di->data.ichg_bc_usb = CHARGE_CURRENT_1900_MA;
        hwlog_info("factory version,iin_ac = %d mA,ichg_ac %d mA,iin_bc_usb = %d mA,ichg_bc_usb = %d mA\n",
                   di->data.iin_ac,di->data.ichg_ac,di->data.iin_bc_usb,di->data.ichg_bc_usb);
    }
    di->data.iin_max = di->data.iin_ac < di->data.iin_fcp ? di->data.iin_fcp :di->data.iin_ac;
    di->data.ichg_max = di->data.ichg_ac < di->data.ichg_fcp ? di->data.ichg_fcp :di->data.ichg_ac;
    hwlog_info("iin_max = %d mA,ichg_max %d mA\n",di->data.iin_max,di->data.ichg_max);
    return 0;
}
/**********************************************************
*  Function:       charge_core_battery_data
*  Discription:    get the charge raw data from hisi_battery_data module
*  Parameters:   di:charge_core_info
*  return value:  0-sucess or others-fail
**********************************************************/
static int charge_core_battery_data(struct charge_core_info *di)
{
    int i;
    struct chrg_para_lut *p_batt_data = NULL;

    p_batt_data = hisi_battery_charge_params();
    if(NULL == p_batt_data)
    {
        hwlog_err("get battery params fail!\n");
        return -EINVAL;
    }

    for(i = 0; i < (p_batt_data->temp_len)/TEMP_PARA_TOTAL; i++)
    {
        di->temp_para[i].temp_min = p_batt_data->temp_data[i][TEMP_PARA_TEMP_MIN];
        di->temp_para[i].temp_max = p_batt_data->temp_data[i][TEMP_PARA_TEMP_MAX];
        di->temp_para[i].iin_temp = p_batt_data->temp_data[i][TEMP_PARA_IIN];
        di->temp_para[i].ichg_temp = p_batt_data->temp_data[i][TEMP_PARA_ICHG];
        di->temp_para[i].vterm_temp = p_batt_data->temp_data[i][TEMP_PARA_VTERM];
        di->temp_para[i].temp_back = p_batt_data->temp_data[i][TEMP_PARA_TEMP_BACK];
        if(di->temp_para[i].iin_temp == -1)
        {
            di->temp_para[i].iin_temp = di->data.iin_max;
        }
        if(di->temp_para[i].ichg_temp == -1)
        {
            di->temp_para[i].ichg_temp = di->data.ichg_max;
        }
        hwlog_debug("temp_min = %d,temp_max = %d,iin_temp = %d,ichg_temp = %d,vterm_temp = %d,temp_back = %d\n",
                    di->temp_para[i].temp_min,di->temp_para[i].temp_max,di->temp_para[i].iin_temp,
                    di->temp_para[i].ichg_temp,di->temp_para[i].vterm_temp,di->temp_para[i].temp_back);

        if((di->temp_para[i].temp_min < BATTERY_TEMPERATURE_MIN)||(di->temp_para[i].temp_min > BATTERY_TEMPERATURE_MAX)
                ||(di->temp_para[i].temp_max < BATTERY_TEMPERATURE_MIN)||(di->temp_para[i].temp_max > BATTERY_TEMPERATURE_MAX)
                ||(di->temp_para[i].iin_temp < CHARGE_CURRENT_0000_MA)||(di->temp_para[i].iin_temp > CHARGE_CURRENT_4000_MA)
                ||(di->temp_para[i].ichg_temp < CHARGE_CURRENT_0000_MA)||(di->temp_para[i].ichg_temp > CHARGE_CURRENT_4000_MA)
                ||(di->temp_para[i].vterm_temp < BATTERY_VOLTAGE_3200_MV)||(di->temp_para[i].vterm_temp > BATTERY_VOLTAGE_4500_MV)
                ||(di->temp_para[i].temp_back < BATTERY_TEMPERATURE_0_C)||(di->temp_para[i].temp_back > BATTERY_TEMPERATURE_5_C))
        {
            hwlog_err("the temp_para value is out of range!!\n");
            return -EINVAL;
        }
    }
    for(i = 0; i < (p_batt_data->volt_len)/VOLT_PARA_TOTAL; i++)
    {
        di->volt_para[i].vbat_min = p_batt_data->volt_data[i][VOLT_PARA_VOLT_MIN];
        di->volt_para[i].vbat_max = p_batt_data->volt_data[i][VOLT_PARA_VOLT_MAX];
        di->volt_para[i].iin_volt = p_batt_data->volt_data[i][VOLT_PARA_IIN];
        di->volt_para[i].ichg_volt = p_batt_data->volt_data[i][VOLT_PARA_ICHG];
        di->volt_para[i].volt_back = p_batt_data->volt_data[i][VOLT_PARA_VOLT_BACK];
        if(di->volt_para[i].iin_volt == -1)
        {
            di->volt_para[i].iin_volt = di->data.iin_max;
        }
        if(di->volt_para[i].ichg_volt == -1)
        {
            di->volt_para[i].ichg_volt = di->data.ichg_max;
        }
        hwlog_debug("vbat_min = %d,vbat_max = %d,iin_volt = %d,ichg_volt = %d,volt_back = %d\n",
                    di->volt_para[i].vbat_min,di->volt_para[i].vbat_max,di->volt_para[i].iin_volt,
                    di->volt_para[i].ichg_volt,di->volt_para[i].volt_back);

        if((di->volt_para[i].vbat_min < BATTERY_VOLTAGE_MIN_MV)||(di->volt_para[i].vbat_min > BATTERY_VOLTAGE_MAX_MV)
                ||(di->volt_para[i].vbat_max < BATTERY_VOLTAGE_MIN_MV)||(di->volt_para[i].vbat_max > BATTERY_VOLTAGE_MAX_MV)
                ||(di->volt_para[i].iin_volt < CHARGE_CURRENT_0000_MA)||(di->volt_para[i].iin_volt > CHARGE_CURRENT_4000_MA)
                ||(di->volt_para[i].ichg_volt < CHARGE_CURRENT_0000_MA)||(di->volt_para[i].ichg_volt > CHARGE_CURRENT_4000_MA)
                ||(di->volt_para[i].volt_back < BATTERY_VOLTAGE_0000_MV)||(di->volt_para[i].volt_back > BATTERY_VOLTAGE_0200_MV))
        {
            hwlog_err("the volt_para value is out of range!!\n");
            return -EINVAL;
        }
    }

    /*Initialize segment charging param */
    for(i = 0; i < (p_batt_data->segment_len)/SEGMENT_PARA_TOTAL; i++)
    {
        di->segment_para[i].vbat_min = p_batt_data->segment_data[i][SEGMENT_PARA_VOLT_MIN];
        di->segment_para[i].vbat_max = p_batt_data->segment_data[i][SEGMENT_PARA_VOLT_MAX];
        di->segment_para[i].ichg_segment= p_batt_data->segment_data[i][SEGMENT_PARA_ICHG];
        di->segment_para[i].vterm_segment= p_batt_data->segment_data[i][SEGMENT_PARA_VTERM];
        di->segment_para[i].volt_back = p_batt_data->segment_data[i][SEGMENT_PARA_VOLT_BACK];

        hwlog_info("segment param: vbat_min = %d,vbat_max = %d,ichg_segment = %d,vterm_segment = %d,volt_back = %d\n",
                   di->segment_para[i].vbat_min,di->segment_para[i].vbat_max,di->segment_para[i].ichg_segment,
                   di->segment_para[i].vterm_segment,di->segment_para[i].volt_back);

        if((di->segment_para[i].vbat_min < BATTERY_VOLTAGE_MIN_MV)||(di->segment_para[i].vbat_min > BATTERY_VOLTAGE_MAX_MV)
                ||(di->segment_para[i].vbat_max < BATTERY_VOLTAGE_MIN_MV)||(di->segment_para[i].vbat_max > BATTERY_VOLTAGE_MAX_MV)
                ||(di->segment_para[i].ichg_segment < CHARGE_CURRENT_0000_MA)||(di->segment_para[i].ichg_segment > CHARGE_CURRENT_MAX_MA)
                ||(di->segment_para[i].vterm_segment < BATTERY_VOLTAGE_3200_MV)||(di->segment_para[i].vterm_segment > BATTERY_VOLTAGE_4500_MV)
                ||(di->segment_para[i].volt_back < BATTERY_VOLTAGE_0000_MV)||(di->segment_para[i].volt_back > BATTERY_VOLTAGE_0200_MV))
        {
            hwlog_err("the segment_para value is out of range!!\n");
            return -EINVAL;
        }
    }

    return 0;
}