static struct hisi_mbox_task *mbox_debugfs_get_task(struct hisi_mbox *mbox,
					mbox_msg_t *msg,
					mbox_msg_len_t len,
					char *rp_name,
					struct mbox_task *context)
{
	struct hisi_mbox_task *tx_task = NULL;
	mbox_msg_t *tx_buffer = NULL;

	tx_buffer = kmalloc(sizeof(mbox_msg_t) * len, GFP_KERNEL);
	if (!tx_buffer)
		return tx_task;
	memcpy(tx_buffer, msg, sizeof(mbox_msg_t) * len);
	context->tx_buffer = tx_buffer;

	tx_task = hisi_mbox_task_alloc(mbox,
				rp_name,
				tx_buffer,
				len,
				1,
				mbox_debugfs_complete,
				context);

	if (!tx_task)
		kfree(tx_buffer);

	return tx_task;
}
/* AP sends msgs to LPM3 for adc sampling&converting. */
static int adc_send_ipc_to_lpm3(int channel)
{
	struct hisi_mbox_task *adc_tx_task;
	int loop = ADC_IPC_MAX_CNT;
	int ret = 0;

	if (channel > ADC_CHN_MAX) {
		pr_err("%s: invalid channel!\n", MODULE_NAME);
		ret = -EINVAL;
		goto err_adc_channel;
	}

	if (!hisi_adc_dev) {
		pr_err("%s: adc dev is not initialized yet!\n", MODULE_NAME);
		ret = -ENODEV;
		goto err_adc_dev;
	}

	if (hisi_adc_dev->tx_msg[ADC_IPC_CMD_TYPE] != ADC_IPC_DATA)
		hisi_adc_dev->tx_msg[ADC_IPC_CMD_TYPE] = ADC_IPC_DATA;

	hisi_adc_dev->info.channel = channel;
	hisi_adc_dev->tx_msg[ADC_IPC_CMD_CHANNEL] = channel;

	adc_tx_task = hisi_mbox_task_alloc(hisi_adc_dev->mbox, HISI_MAILBOX_RP_LPM3, hisi_adc_dev->tx_msg,
							ADC_IPC_CMD_LEN, 1, adc_complete_func, NULL);
	if (!adc_tx_task) {
		pr_err("%s: fail to alloc mbox task!\n", MODULE_NAME);
		ret = -ENOMEM;
		goto err_alloc_task;
	}

	do {
		ret = hisi_mbox_msg_send_async(hisi_adc_dev->mbox, adc_tx_task);
		loop--;
	} while (ret == -ENOMEM && loop > 0);
	if (ret) {
		pr_err("%s: fail to send mbox msg, ret = %d!\n", MODULE_NAME, ret);
		goto err_msg_async;
	}

	return ret;

err_msg_async:
	hisi_mbox_task_free(&adc_tx_task);
err_alloc_task:
	hisi_adc_dev->info.channel = ADC_RESULT_ERR;
err_adc_dev:
err_adc_channel:
	return ret;
}
static int hisi_clkmbox_send_ipc(mbox_msg_t *msg, void *context, int autoack)
{
	struct hisi_mbox_task *tx_task;
	int loop = MAX_SEND_IPC_TRY;
	mbox_msg_t	*tx_msg;
	int ret, i;

	tx_msg = kzalloc(sizeof(mbox_msg_t) * LPM3_CMD_LEN, GFP_ATOMIC);
	if (!tx_msg) {
		pr_err("[%s] fail to alloc tx_msg!\n", __func__);
		ret = -ENOMEM;
		goto err;
	}

	/* construct cmd */
	for (i = 0; i < LPM3_CMD_LEN; i++) {
		tx_msg[i] = msg[i];
		pr_debug("[%s] tx_msg[i] = 0x%x\n",	__func__, tx_msg[i]);
	}


	tx_task = hisi_mbox_task_alloc(mbox_clk->mbox, HISI_MAILBOX_RP_LPM3,
							tx_msg, LPM3_CMD_LEN, autoack, hisi_clkmbox_default_complete, context);
	if (!tx_task) {
		pr_err("[%s] fail to alloc mbox task!\n", __func__);
		ret = -ENOMEM;
		goto err_task;
	}

	/* try again if failing to send */
	do {
		ret = hisi_mbox_msg_send_async(mbox_clk->mbox, tx_task);
		loop--;
	} while (ret == -ENOMEM && loop > 0);
	if (ret) {
		pr_err("[%s] fail to send mbox msg, ret = %d!\n",
				__func__, ret);
		goto err_snd_async;
	}

	return 0;

err_snd_async:
	hisi_mbox_task_free(&tx_task);
err_task:
	kfree(tx_msg);
	tx_msg = NULL;
err:
	return ret;
}
void boot_iom3(void)
{
    struct hisi_mbox_task *tx_task = NULL;
    if (!(lpm3_mbox = hisi_mbox_get(HISI_MAILBOX_RP_LPM3, NULL))) {
        hwlog_err("failed to get mailbox in %s\n", __func__);
        return;
    }
    tx_task = hisi_mbox_task_alloc(lpm3_mbox,
                HISI_MAILBOX_RP_LPM3,
                &g_boot_iom3,
                1,
                1,
                inputhub_power_on_complete,
                NULL);
    if(!tx_task) {
        hwlog_err("failed to alloc task %s\n", __func__);
        return;
    }
    if (hisi_mbox_msg_send_async(lpm3_mbox,tx_task) != 0) {
        hwlog_err("hisi_mbox_msg_send_async error in %s\n", __func__);
    }
}
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;
}