static int read_mip(u8 *data, int len, int offset, int issigned)
{
	int ret;
	u32 sptr, dptr, cmd, cmdid, data_off;

	if (!intel_mip_base)
		return -ENODEV;

	if (offset + len > IPC_MIP_MAX_ADDR)
		return -EINVAL;

	dptr = offset;
	sptr = (len + 3) / 4;

	cmdid = issigned ? IPC_CMD_SMIP_RD : IPC_CMD_UMIP_RD;
	cmd = 4 << 16 | cmdid << 12 | IPCMSG_MIP_ACCESS;

	do {
		ret = intel_scu_ipc_raw_cmd(cmd, 0, NULL, 0, &data_off, 1,
				dptr, sptr);
		if (ret == -EIO)
			msleep(20);
	} while (ret == -EIO);

	if (!ret)
		memcpy(data, intel_mip_base + data_off, len);

	return ret;
}
int intel_scu_ipc_write_umip(u8 *data, int len, int offset)
{
	int ret, offset_align;
	int len_align = 0;
	u32 dptr, sptr, cmd;
	u8 *buf = NULL;

	/* Cloverview don't need UMIP access through IPC */
	if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_CLOVERVIEW)
		return -EINVAL;

	if (!intel_mip_base)
		return -ENODEV;

	if (offset + len > IPC_MIP_MAX_ADDR)
		return -EINVAL;

	intel_scu_ipc_lock();

	offset_align = offset & (~0x3);
	len_align = (len + (offset - offset_align) + 3) & (~0x3);

	if (len != len_align) {
		buf = kzalloc(len_align, GFP_KERNEL);
		if (!buf) {
			pr_err("Alloc memory failed\n");
			ret = -ENOMEM;
			goto fail;
		}
		ret = read_mip(buf, len_align, offset_align, 0);
		if (ret)
			goto fail;
		memcpy(buf + offset - offset_align, data, len);
	} else {
		buf = data;
	}

	dptr = offset_align;
	sptr = len_align / 4;
	cmd = IPC_CMD_UMIP_WR << 12 | IPCMSG_MIP_ACCESS;

	memcpy(intel_mip_base, buf, len_align);

	do {
		ret = intel_scu_ipc_raw_cmd(cmd, 0, NULL, 0, NULL, 0,
				dptr, sptr);
		if (ret == -EIO)
			msleep(20);
	} while (ret == -EIO);

fail:
	if (buf && len_align != len)
		kfree(buf);

	intel_scu_ipc_unlock();

	return ret;
}
int intel_scu_ipc_write_osnib(u8 *data, int len, int offset)
{
	int i;
	int ret = 0;
	u32 posnibw, oshob_base;
	u8 osnib_data[OSNIB_SIZE];
	u8 chksum = 0;
	void __iomem *oshob_addr, *osnibw_addr, *osnibr_addr;

	ret = intel_scu_ipc_command(IPCMSG_GET_HOBADDR, 0, NULL, 0,
			&oshob_base, 1);
	if (ret < 0) {
		pr_err("ipc_get_hobaddr failed!!\n");
		goto exit;
	}

	pr_info("OSHOB addr values is %x\n", oshob_base);

	intel_scu_ipc_lock();

	oshob_addr = ioremap_nocache(oshob_base, OSHOB_SIZE);
	if (!oshob_addr) {
		pr_err("ioremap failed!\n");
		ret = -ENOMEM;
		goto exit;
	}

	/*Dump osnib data for generate chksum */
	osnibr_addr = oshob_addr + OSNIB_OFFSET;
	for (i = 0; i < OSNIB_SIZE; i++)
		osnib_data[i] = readb(osnibr_addr + i);

	memcpy(osnib_data + offset, data, len);

	/* generate chksum */
	for (i = 0; i < OSNIB_SIZE - 1; i++)
		chksum += osnib_data[i];
	osnib_data[OSNIB_SIZE - 1] = ~chksum + 1;

	posnibw = readl(oshob_addr + POSNIBW_OFFSET);
	if (posnibw == 0) { /* workaround here for BZ 2914 */
		posnibw = 0xFFFF3400;
		pr_err("ERR: posnibw from oshob is 0, manually set it here\n");
	}

	pr_info("POSNIB: %x\n", posnibw);

	osnibw_addr = ioremap_nocache(posnibw, OSNIB_SIZE);
	if (!osnibw_addr) {
		pr_err("ioremap failed!\n");
		ret = -ENOMEM;
		goto unmap_oshob_addr;
	}

	for (i = 0; i < OSNIB_SIZE; i++)
		writeb(*(osnib_data + i), (osnibw_addr + i));

	ret = intel_scu_ipc_raw_cmd(IPCMSG_WRITE_OSNIB, 0, NULL, 0, NULL,
			0, 0, 0xFFFFFFFF);
	if (ret < 0)
		pr_err("ipc_write_osnib failed!!\n");

	iounmap(osnibw_addr);

unmap_oshob_addr:
	iounmap(oshob_addr);
exit:
	intel_scu_ipc_unlock();

	return ret;
}