static int _cmc221_idpram_upload(struct dpram_link_device *dpld,
		struct dpram_dump_arg *dumparg)
{
	struct link_device *ld = &dpld->ld;
	int ret;
	u8 __iomem *src;
	int buff_size = CMC22x_DUMP_BUFF_SIZE;

	if ((dpld->dump_rcvd & 0x1) == 0)
		cmc221_idpram_send_msg(dpld, CMC22x_1ST_BUFF_READY);
	else
		cmc221_idpram_send_msg(dpld, CMC22x_2ND_BUFF_READY);

	init_completion(&dpld->dump_recv_done);

	mif_add_timer(&dpld->dump_timer, DUMP_WAIT_TIMEOUT,
		_cmc221_idpram_wait_dump, (unsigned long)dpld);

	ret = wait_for_completion_interruptible_timeout(
			&dpld->dump_recv_done, DUMP_TIMEOUT);
	if (!ret) {
		mif_info("%s: ERR! CP didn't send dump data!!!\n", ld->name);
		goto err_out;
	}

	if (cmc221_idpram_recv_msg(dpld) == CMC22x_CP_DUMP_END) {
		mif_info("%s: CMC22x_CP_DUMP_END\n", ld->name);
		return 0;
	}

	if ((dpld->dump_rcvd & 0x1) == 0)
		src = dpld->ul_map.buff;
	else
		src = dpld->ul_map.buff + CMC22x_DUMP_BUFF_SIZE;

	memcpy(dpld->buff, src, buff_size);

	ret = copy_to_user(dumparg->buff, dpld->buff, buff_size);
	if (ret < 0) {
		mif_info("%s: ERR! copy_to_user fail\n", ld->name);
		goto err_out;
	}

	dpld->dump_rcvd++;
	return buff_size;

err_out:
	return -EIO;
}
static int cmc221_idpram_upload(struct dpram_link_device *dpld,
			struct dpram_dump_arg *dumparg)
{
	int ret;
	u8 __iomem *src;
	int buff_size = CMC22x_DUMP_BUFF_SIZE;

	if ((dpld->crash_rcvd & 0x1) == 0)
		cmc221_idpram_send_msg(dpld, CMC22x_1ST_BUFF_READY);
	else
		cmc221_idpram_send_msg(dpld, CMC22x_2ND_BUFF_READY);

	init_completion(&dpld->crash_cmpl);

	mif_add_timer(&dpld->crash_timer, DUMP_WAIT_TIMEOUT,
		cmc221_idpram_wait_dump, (unsigned long)dpld);

	ret = wait_for_completion_timeout(&dpld->crash_cmpl, DUMP_TIMEOUT);
	if (!ret) {
		mif_info("ERR! no dump from CP!!!\n");
		goto err_out;
	}

	if (cmc221_idpram_recv_msg(dpld) == CMC22x_CP_DUMP_END) {
		mif_info("recv CMC22x_CP_DUMP_END\n");
		return 0;
	}

	if ((dpld->crash_rcvd & 0x1) == 0)
		src = dpld->ul_map.buff;
	else
		src = dpld->ul_map.buff + CMC22x_DUMP_BUFF_SIZE;

	memcpy(dpld->buff, src, buff_size);

	ret = copy_to_user(dumparg->buff, dpld->buff, buff_size);
	if (ret < 0) {
		mif_info("ERR! copy_to_user fail\n");
		goto err_out;
	}

	dpld->crash_rcvd++;
	return buff_size;

err_out:
	return -EIO;
}
static int _cmc221_idpram_download_bin(struct dpram_link_device *dpld,
			struct sk_buff *skb)
{
	int err = 0;
	int ret = 0;
	struct link_device *ld = &dpld->ld;
	struct dpram_boot_frame *bf = (struct dpram_boot_frame *)skb->data;
	u8 __iomem *buff = (dpld->bt_map.buff + bf->offset);

	if ((bf->offset + bf->len) > dpld->bt_map.size) {
		mif_info("%s: ERR! Out of DPRAM boundary\n", ld->name);
		err = -EINVAL;
		goto exit;
	}

	if (bf->len)
		memcpy(buff, bf->data, bf->len);

	if (bf->req)
		cmc221_idpram_send_msg(dpld, (u16)bf->req);

	if (bf->resp) {
		err = _cmc221_idpram_wait_resp(dpld, bf->resp);
		if (err < 0)
			mif_info("%s: ERR! wait_response fail (err %d)\n",
				ld->name, err);
	}

	if (bf->req == CMC22x_CAL_NV_DOWN_END)
		mif_info("%s: CMC22x_CAL_NV_DOWN_END\n", ld->name);

exit:
	if (err < 0)
		ret = err;
	else
		ret = skb->len;

	dev_kfree_skb_any(skb);

	return ret;
}