static int _cmc221_idpram_wait_resp(struct dpram_link_device *dpld, u32 resp)
{
	struct link_device *ld = &dpld->ld;
	int count = 50000;
	u32 rcvd = 0;

	if (resp == CMC22x_CP_REQ_NV_DATA) {
		while (1) {
			rcvd = ioread32(dpld->bt_map.resp);
			if (rcvd == resp)
				break;

			rcvd = cmc221_idpram_recv_msg(dpld);
			if (rcvd == 0x9999) {
				mif_info("%s: Invalid resp 0x%04X\n",
					ld->name, rcvd);
				panic("CP Crash ... BAD CRC in CP");
			}

			if (count-- < 0) {
				mif_info("%s: Invalid resp 0x%08X\n",
					ld->name, rcvd);
				return -EAGAIN;
			}

			udelay(100);
		}
	} else {
		while (1) {
			rcvd = cmc221_idpram_recv_msg(dpld);

			if (rcvd == resp)
				break;

			if (resp == CMC22x_CP_RECV_NV_END &&
			    rcvd == CMC22x_CP_CAL_BAD) {
				mif_info("%s: CMC22x_CP_CAL_BAD\n", ld->name);
				break;
			}

			if (count-- < 0) {
				mif_info("%s: Invalid resp 0x%04X\n",
					ld->name, rcvd);
				return -EAGAIN;
			}

			udelay(100);
		}
	}

	return rcvd;
}
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 void _cmc221_idpram_wait_dump(unsigned long arg)
{
	struct dpram_link_device *dpld = (struct dpram_link_device *)arg;
	u16 msg;

	msg = cmc221_idpram_recv_msg(dpld);
	if (msg == CMC22x_CP_DUMP_END) {
		complete_all(&dpld->dump_recv_done);
		return;
	}

	if (((dpld->dump_rcvd & 0x1) == 0) && (msg == CMC22x_1ST_BUFF_FULL)) {
		complete_all(&dpld->dump_recv_done);
		return;
	}

	if (((dpld->dump_rcvd & 0x1) == 1) && (msg == CMC22x_2ND_BUFF_FULL)) {
		complete_all(&dpld->dump_recv_done);
		return;
	}

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