bool fimc_is_ois_check_fw(struct fimc_is_core *core)
{
	u8 *buf = NULL;
	int ret = 0;

	ret = fimc_is_ois_fw_version(core);
	if (!ret) {
		err("Failed to read ois fw version.");
		return false;
	}
	fimc_is_ois_read_userdata(core);

	if (ois_minfo.header_ver[0] == '6') {
		if (ois_minfo.header_ver[2] == 'C' || ois_minfo.header_ver[2] == 'E'
			|| ois_minfo.header_ver[2] == 'G' || ois_minfo.header_ver[2] == 'I') {
			ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_DOM, &buf);
		} else if (ois_minfo.header_ver[2] == 'D' || ois_minfo.header_ver[2] == 'F'
			|| ois_minfo.header_ver[2] == 'H' || ois_minfo.header_ver[2] == 'J') {
			ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_SEC, &buf);
		}
	} else if (ois_minfo.header_ver[0] == '8') {
		if (ois_minfo.header_ver[2] == 'H' || ois_minfo.header_ver[2] == 'J') {
			ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_SEC_2, &buf);
		}
	} else {
		info("Module FW version does not matched with phone FW version.\n");
		strcpy(ois_pinfo.header_ver, "NULL");
		return true;
	}
	if (ret) {
		err("fimc_is_ois_open_fw failed(%d)\n", ret);
	}

	if (buf) {
		vfree(buf);
	}

	return true;
}
void fimc_is_ois_check_fw(struct fimc_is_core *core)
{
	u8 *buf = NULL;
	int ret = 0;

	fimc_is_ois_fw_version(core);
	fimc_is_ois_read_userdata(core);

	if (ois_minfo.header_ver[2] == 'A') {
		ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_DOM, &buf);
	} else if (ois_minfo.header_ver[2] == 'B') {
		ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_SEC, &buf);
	}
	if (ret) {
		err("fimc_is_ois_open_fw failed(%d)\n", ret);
	}

	if (buf) {
		vfree(buf);
	}

	return;
}
void fimc_is_ois_check_fw(struct fimc_is_core *core)
{
	u8 *buf = NULL;
	int ret = 0;

	ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME, &buf);
	if (ret) {
		err("fimc_is_ois_open_fw failed(%d)\n", ret);
	}

	if (buf) {
		vfree(buf);
	}

	return;
}
void fimc_is_ois_fw_update(struct fimc_is_core *core)
{
	u8 SendData[256], RcvData;
	u16 RcvDataShort = 0;
	u8 data[2] = {0, };
	int block, i, position = 0;
	u16 checkSum;
	u8 *buf = NULL;
	int ret = 0, sum_size = 0, retry_count = 3;
	int module_ver = 0, binary_ver = 0;
	u8 error_status = 0;
	bool forced_update = false, crc_result = false;
	bool need_reset = false;
	struct i2c_client *client = core->client1;
	struct exynos_platform_fimc_is *core_pdata = NULL;

	core_pdata = dev_get_platdata(fimc_is_dev);
	if (!core_pdata) {
		err("core->pdata is null");
		return;
	}

	/* OIS Status Check */
	error_status = fimc_is_ois_read_status(core);
	if (error_status == 0x01) {
		forced_update = true;
	}

	ret = fimc_is_ois_fw_version(core);
	if (!ret) {
		err("Failed to read ois fw version.");
		return;
	}
	fimc_is_ois_read_userdata(core);

	if (ois_minfo.header_ver[0] == '6') {
		if (ois_minfo.header_ver[2] == 'C' || ois_minfo.header_ver[2] == 'E'
			|| ois_minfo.header_ver[2] == 'G' || ois_minfo.header_ver[2] == 'I') {
			ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_DOM, &buf);
		} else if (ois_minfo.header_ver[2] == 'D' || ois_minfo.header_ver[2] == 'F'
			|| ois_minfo.header_ver[2] == 'H' || ois_minfo.header_ver[2] == 'J') {
			ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_SEC, &buf);
		}
	} else if (ois_minfo.header_ver[0] == '8') {
		if (ois_minfo.header_ver[2] == 'H' || ois_minfo.header_ver[2] == 'J') {
			ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME_SEC_2, &buf);
		}
	} else {
		info("Module FW version does not matched with phone FW version.\n");
		strcpy(ois_pinfo.header_ver, "NULL");
		return;
	}
	if (ret) {
		err("fimc_is_ois_open_fw failed(%d)", ret);
		goto p_err;
	}

	if (ois_minfo.header_ver[2] != CAMERA_OIS_DOM_UPDATE_VERSION
		&& ois_minfo.header_ver[2] != CAMERA_OIS_SEC_UPDATE_VERSION) {
		info("Do not update ois Firmware. FW version is low.\n");
		goto p_err;
	}

	if (buf == NULL) {
		err("buf is NULL. OIS FW Update failed.");
		return;
	}

	if (!forced_update) {
		if (ois_uinfo.header_ver[0] == 0xFF && ois_uinfo.header_ver[1] == 0xFF &&
			ois_uinfo.header_ver[2] == 0xFF) {
			err("OIS userdata is not valid.");
			goto p_err;
		}
	}

	/*Update OIS FW when Gyro sensor/Driver IC/ Core version is same*/
	if (!forced_update) {
		if (!fimc_is_ois_version_compare(ois_minfo.header_ver, ois_pinfo.header_ver,
			ois_uinfo.header_ver)) {
			err("Does not update ois fw. OIS module ver = %s, binary ver = %s, userdata ver = %s",
				ois_minfo.header_ver, ois_pinfo.header_ver, ois_uinfo.header_ver);
			goto p_err;
		}
	} else {
		if (!fimc_is_ois_version_compare_default(ois_minfo.header_ver, ois_pinfo.header_ver)) {
			err("Does not update ois fw. OIS module ver = %s, binary ver = %s",
				ois_minfo.header_ver, ois_pinfo.header_ver);
			goto p_err;
		}
	}

	crc_result = fimc_is_ois_crc_check(core, buf);
	if (crc_result == false) {
		err("OIS CRC32 error.\n");
		goto p_err;
	}

	if (!fw_sdcard && !forced_update) {
		module_ver = fimc_is_ois_fw_revision(ois_minfo.header_ver);
		binary_ver = fimc_is_ois_fw_revision(ois_pinfo.header_ver);
		if (binary_ver <= module_ver) {
			err("OIS module ver = %d, binary ver = %d", module_ver, binary_ver);
			goto p_err;
		}
	}
	info("OIS fw update started. module ver = %s, binary ver = %s, userdata ver = %s\n",
		ois_minfo.header_ver, ois_pinfo.header_ver, ois_uinfo.header_ver);

	if (core_pdata->use_ois_hsi2c) {
		fimc_is_ois_i2c_config(core->client1, true);
	}

retry:
	if (need_reset) {
		fimc_is_ois_gpio_off(core);
		msleep(30);
		fimc_is_ois_gpio_on(core);
		msleep(150);
	}

	fimc_is_ois_i2c_read(client, 0x01, &RcvData); /* OISSTS Read */

	if (RcvData != 0x01) {/* OISSTS != IDLE */
		err("RCV data return!!");
		goto p_err;
	}

	/* Update a Boot Program */
	/* SET FWUP_CTRL REG */
	fimc_is_ois_i2c_write(client ,0x000C, 0x0B);
	msleep(20);

	position = 0;
	/* Write Boot Data */
	for (block = 4; block < 8; block++) {       /* 0x1000 - 0x1FFF */
		for (i = 0; i < 4; i++) {
			memcpy(SendData, bootCode + position, FW_TRANS_SIZE);
			fimc_is_ois_i2c_write_multi(client, 0x0100, SendData, FW_TRANS_SIZE + 2);
			position += FW_TRANS_SIZE;
			if (i == 0 ) {
				msleep(20);
			} else if ((i == 1) || (i == 2)) {	 /* Wait Erase and Write process */
				 msleep(10);		/* Wait Write process */
			} else {
				msleep(15); /* Wait Write and Verify process */
			}
		}
	}

	/* CHECKSUM (Boot) */
	sum_size = OIS_BOOT_FW_SIZE;
	checkSum = fimc_is_ois_calc_checksum(&bootCode[0], sum_size);
	SendData[0] = (checkSum & 0x00FF);
	SendData[1] = (checkSum & 0xFF00) >> 8;
	SendData[2] = 0x00;
	SendData[3] = 0x00;
	fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);
	msleep(10);			 /* (RUMBA Self Reset) */

	fimc_is_ois_i2c_read_multi(client, 0x06, data, 2); /* Error Status read */
	info("%s: OISSTS Read = 0x%02x%02x\n", __func__, data[1], data[0]);

	if (data[1] == 0x00 && data[0] == 0x01) {					/* Boot F/W Update Error check */
		/* Update a User Program */
		/* SET FWUP_CTRL REG */
		position = 0;
		SendData[0] = 0x09;		/* FWUP_DSIZE=256Byte, FWUP_MODE=PROG, FWUPEN=Start */
		fimc_is_ois_i2c_write(client, 0x0C, SendData[0]);		/* FWUPCTRL REG(0x000C) 1Byte Send */

		/* Write UserProgram Data */
		for (block = 4; block <= 27; block++) {		/* 0x1000 -0x 6FFF (RUMBA-SA)*/
			for (i = 0; i < 4; i++) {
				memcpy(SendData, &progCode[position], (size_t)FW_TRANS_SIZE);
				fimc_is_ois_i2c_write_multi(client, 0x100, SendData, FW_TRANS_SIZE + 2); /* FLS_DATA REG(0x0100) 256Byte Send */
				position += FW_TRANS_SIZE;
				if (i ==0 ) {
					msleep(20);		/* Wait Erase and Write process */
				} else if ((i==1) || (i==2)) {
					msleep(10);		/* Wait Write process */
				} else {
					msleep(15);		/* Wait Write and Verify process */
				}
			}
		}

		/* CHECKSUM (Program) */
		sum_size = OIS_PROG_FW_SIZE;
		checkSum = fimc_is_ois_calc_checksum(&progCode[0], sum_size);
		SendData[0] = (checkSum & 0x00FF);
		SendData[1] = (checkSum & 0xFF00) >> 8;
		SendData[2] = 0;		/* Don't Care */
		SendData[3] = 0x80;		/* Self Reset Request */

		fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);  /* FWUP_CHKSUM REG(0x0008) 4Byte Send */
		msleep(60);		/* (Wait RUMBA Self Reset) */
		fimc_is_ois_i2c_read(client, 0x6, (u8*)&RcvDataShort); /* Error Status read */

		if (RcvDataShort == 0x0000) {
			/* F/W Update Success Process */
			info("%s: OISLOG OIS program update success\n", __func__);
		} else {
			/* Retry Process */
			if (retry_count > 0) {
				err("OISLOG OIS program update fail, retry update. count = %d", retry_count);
				retry_count--;
				need_reset = true;
				goto retry;
			}

			/* F/W Update Error Process */
			err("OISLOG OIS program update fail");
			goto p_err;
		}
	} else {
void fimc_is_ois_fw_update(struct fimc_is_core *core)
{
	u8 SendData[256], RcvData;
	u16 RcvDataShort = 0;
	int block, i, position = 0;
	u16 checkSum;
	u8 *buf = NULL;
	int ret = 0, sum_size = 0;
	int module_ver = 0, binary_ver = 0;
	struct i2c_client *client = core->client1;

	/* OIS Status Check */
	ret = fimc_is_ois_open_fw(core, FIMC_OIS_FW_NAME, &buf);
	if (ret) {
		err("fimc_is_ois_open_fw failed(%d)\n", ret);
		goto p_err;
	}

	fimc_is_ois_fw_version(core);

	/*Update OIS FW when Gyro sensor/Driver IC/ Core version is same*/
	if (!fimc_is_ois_version_compare(ois_minfo.header_ver, ois_pinfo.header_ver)) {
		err("Does not update ois fw. OIS module ver = %s, binary ver = %s\n", ois_minfo.header_ver, ois_pinfo.header_ver );
		goto p_err;
	}

	module_ver = fimc_is_ois_fw_revision(ois_minfo.header_ver);
	binary_ver = fimc_is_ois_fw_revision(ois_pinfo.header_ver);
	if (binary_ver <= module_ver) {
		err("OIS module ver = %d, binary ver = %d\n", module_ver, binary_ver);
		goto p_err;
	}

	fimc_is_ois_i2c_read(client, 0x01, &RcvData); /* OISSTS Read */

	if (RcvData != 0x01) {/* OISSTS != IDLE */
		err("RCV data return!!\n");
		goto p_err;
	}

	/* Update a Boot Program */
	/* SET FWUP_CTRL REG */
	fimc_is_ois_i2c_write(client ,0x000C, 0x0B);

	position = 0;
	/* Write Boot Data */
	for (block = 4; block < 8; block++) {       /* 0x1000 - 0x1FFF */
		for (i = 0; i < 4; i++) {
			memcpy(SendData, bootCode + position, FW_TRANS_SIZE);
			fimc_is_ois_i2c_write_multi(client, 0x0100, SendData, FW_TRANS_SIZE + 2);
			position += FW_TRANS_SIZE;
			if (i == 0 ) {
				msleep(20);
			} else if ((i == 1) || (i == 2)) {	 /* Wait Erase and Write process */
				 msleep(10);		/* Wait Write process */
			} else {
				msleep(15); /* Wait Write and Verify process */
			}
		}
	}

	/* CHECKSUM (Boot) */
	sum_size = OIS_BOOT_FW_SIZE;
	checkSum = fimc_is_ois_calc_checksum(&bootCode[0], sum_size);
	SendData[0] = (checkSum & 0x00FF);
	SendData[1] = (checkSum & 0xFF00) >> 8;
	SendData[2] = 0x00;
	SendData[3] = 0x00;
	fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);
	msleep(10);			 /* (RUMBA Self Reset) */

	fimc_is_ois_i2c_read_multi(client, 0x06, &RcvDataShort); /* Error Status read */
	pr_info("OISSTS Read = 0x%04x\n", RcvDataShort);

	if (RcvDataShort == 0x0001) {					/* Boot F/W Update Error check */
		/* Update a User Program */
		/* SET FWUP_CTRL REG */
		position = 0;
		SendData[0] = 0x09;		/* FWUP_DSIZE=256Byte, FWUP_MODE=PROG, FWUPEN=Start */
		fimc_is_ois_i2c_write(client, 0x0C, SendData[0]);		/* FWUPCTRL REG(0x000C) 1Byte Send */

		/* Write UserProgram Data */
		for (block = 4; block <= 27; block++) {		/* 0x1000 -0x 6FFF (RUMBA-SA)*/
			for (i = 0; i < 4; i++) {
				memcpy(SendData, &progCode[position], (size_t)FW_TRANS_SIZE);
				fimc_is_ois_i2c_write_multi(client, 0x100, SendData, FW_TRANS_SIZE + 2); /* FLS_DATA REG(0x0100) 256Byte Send */
				position += FW_TRANS_SIZE;
				if (i ==0 ) {
					msleep(20);		/* Wait Erase and Write process */
				} else if ((i==1) || (i==2)) {
					msleep(10);		/* Wait Write process */
				} else {
					 msleep(15);		/* Wait Write and Verify process */
				}
			}
		}

		/* CHECKSUM (Program) */
		sum_size = OIS_PROG_FW_SIZE;
		checkSum = fimc_is_ois_calc_checksum(&progCode[0], sum_size);
		SendData[0] = (checkSum & 0x00FF);
		SendData[1] = (checkSum & 0xFF00) >> 8;
		SendData[2] = 0;		/* Don't Care */
		SendData[3] = 0x80;		/* Self Reset Request */

		fimc_is_ois_i2c_write_multi(client, 0x08, SendData, 6);  /* FWUP_CHKSUM REG(0x0008) 4Byte Send */
		msleep(10);		/* (Wait RUMBA Self Reset) */
		fimc_is_ois_i2c_read(client, 0x6, (u8*)&RcvDataShort); /* Error Status read */

		if (RcvDataShort == 0x0000) {
			/* F/W Update Success Process */
			err("OISLOG OIS program update success\n");
		} else {
			/* F/W Update Error Process */
			err("OISLOG OIS program update fail\n");
		}
	} else {