static ssize_t qfprom_write_store(struct device *dev,
				  struct device_attribute *attr,
				  const char *buf, size_t count)
{
	int ret = 0;
	if (!enable) {
		printk("%s: qfprom write is not enabled\n", __func__);
		return -EINVAL;
	}
	if (!qfprom_address) {
		printk("%s: qfprom address is NULL\n", __func__);
		return -EINVAL;
	}
	ret = qfuse_write_single_row(qfprom_address, qfprom_lsb_value,
				   qfprom_msb_value);
	qfprom_address = 0;
	if (ret == 0)
		return count;
	else if (ret < 0)
		printk("%s: scm call fail error = %d\n", __func__, ret);
	else
		printk("%s: qfprom write status error = %d\n", __func__, ret);

	return -EINVAL;
}
static ssize_t qfprom_sdp_enum_store(struct device* dev, struct device_attribute* attr,
				const char* buf, size_t count)
{
	int cmd;
	int ret;
	struct qfprom_blow_data sdp_data = { QFPROM_DEBUG_DISABLE, 0x200, 0x0 };

	if (sscanf(buf, "%d", &cmd) != 1)
		return -EINVAL;

	if (cmd) {
		ret = qfuse_write_single_row(sdp_data.qfprom_addr,sdp_data.lsb_data,sdp_data.msb_data);
		if(ret!=0){
			printk("%s: qfuse addr %x blow write error!!!\n",__func__,sdp_data.qfprom_addr);
			return -EINVAL;
		}
	}

	return count;
}
int qfprom_blow_secondary_hwkey_region(void)
{
	int ret;
	u32 addr, lsb, msb;
	int i;
	u32 *p_buf = NULL;

	p_buf = kmalloc(sizeof(u32)*2, GFP_KERNEL);
	if(!p_buf){
		printk("%s : buffer memory alloc fail\n", __func__);
		return -ENOMEM;
	}

	/* we check read permission
	 * if read permission region is blown, we can see all hw secondary key is blown
	 * because permission fuse is follow to secondary hw key
	 */
	
	ret = qfuse_read_single_row(QFPROM_RD_WR_PERMISSION, 0, p_buf);
	if(ret != 0){
		printk("%s: qfuse addr %x read fail, ret=%d\n", __func__, QFPROM_RD_WR_PERMISSION, ret);
		ret = -EINVAL;
		goto err;
	}
	if((p_buf[0]&0x0C000000) == 0x0C000000) {
		printk("%s: All hw key was written already\n", __func__);
		ret = 0;
		goto err;
	}

	addr = QFPROM_SECONDARY_HW_KEY;
	for(i=0;i<7;i++){
		/* we can read hw secondary key region because before read permission is set */
		/*
		ret = qfuse_read_single_row(addr, 0, p_buf);
		if(ret != 0){
			printk("%s: qfuse addr %x read fail, ret=%d\n", __func__, addr,ret);
			ret = -EINVAL;
			goto err;
		}
		printk("%s:Currently, secondary key addr=0x%x, lsb=0x%x, msb=0x%x\n", __func__, addr,p_buf[0], p_buf[1]);
		*/
		msleep(10);

		/* if you have not written ever hw key before, value to read will be zero
		 * so create random using tzbsp
		 * LSB region */
		if(!p_buf[0]){
			lsb = qfprom_create_random();
			if(!lsb) {
				ret = -EINVAL;
				goto err;
			}
			msleep(5);
		} else {
			/* dont create random value and rewrite value to read */
			printk("hw lsb key was blow already in 0x%x addr\n", addr);
			lsb = p_buf[0];
		}
		/* if you have not written ever hw key before, value to read will be zero
		 * so create random using tzbsp
		 * MSB region */
		if(!p_buf[1]) {
			msb = qfprom_create_random();
			if(!msb) {
				ret = -EINVAL;
				goto err;
			}
			msleep(5);
		} else {

			printk("hw msb key was blow already in 0x%x addr\n", addr+4);
			msb = p_buf[1];
		}
		/* must mask FEC bit */
		lsb = lsb&HW_KEY_LSB_FEC_MASK;
		msb = msb&HW_KEY_MSB_FEC_MASK;
		printk("We start to writing secondary key !!!\n");
		printk("addr=0x%x, lsb=0x%x, msb=0x%x\n", addr, lsb, msb);
		msleep(10);
		ret = qfuse_write_single_row(addr, lsb, msb);
		if(ret != 0) {
			printk("%s:qfus addr 0x%x write error, ret=%d\n", __func__, addr, ret);
			ret = -EINVAL;
			goto err;
		} else {
			/* write double check routine */
			printk("hw secondary key write successful\n");
			msleep(10);
			/*
			ret = qfuse_read_single_row(addr, 0, p_buf);
			if(ret != 0) {
				printk("%s:read fail when double check routine, ret=%d\n", __func__, ret);
				goto err;
			}
			if((p_buf[0]==lsb)&&(p_buf[1]==msb))
				printk("%s: hw key write double check successful!!!!!!!\n",__func__);
			else {
				printk("%s: hw key double check error, read_lsb=0x%x,read_msb=0x%x\n",__func__,p_buf[0],p_buf[1]);
				ret = -EINVAL;
				goto err;
			}
			*/
		}
		addr = addr+8;
		msleep(10);
	}

err:
	kfree(p_buf);
	return ret;
}
/* this api handle diag command(fusing command) from ATD
 * this api fuse secure boot, jtag disable, oem config, secondary hw key, R/W permission
 * this api check secondary hw key status before fusing R/W permission
 */
static ssize_t qfusing_store(struct device *dev, struct device_attribute *attr,
				const char *buf, size_t count)
{
	int ret;
	int i = 0;
	u32 *p_buf = NULL;
	u32 fusing_flag=0;

	if(!sysfs_streq(buf, "fusing")){
		printk("%s:argument fault\n", __func__);
		ret = -EINVAL;
		goto err;
	}

	p_buf = kmalloc(sizeof(u32)*2, GFP_KERNEL);
	if(!p_buf) {
		printk("%s: memory alloc fail\n", __func__);
		ret = -EINVAL;
		goto err;;

	}

	for(i=0;i<ARRAY_SIZE(blow_data);i++){
		if(blow_data[i].qfprom_addr==QFPROM_CHECK_HW_KEY) {
			/* We dont check secondary hw key status
			 * But qfprom_blow secondary_hwkey_region api does not create random if qfprom block was written
			 * The api create random if was not written only
			 * So HW key region to be written is not written by new random key
			 * The reason to not check hw key status reg is to check 7 hw key block to be written
			 */
			ret = qfprom_blow_secondary_hwkey_region();
			if(ret < 0) {
				printk("%s: hw key region blow error\n", __func__);
				goto err_fuse;
			}
			fusing_flag |= (0x1<<i);
			printk("%s: HW secondary key region is blown successfully\n", __func__);
			continue;
		}

		msleep(10);
		ret = qfuse_read_single_row(blow_data[i].qfprom_addr, 0, p_buf);
		if(ret != 0) {
			printk("%s: qfprom addr %x read fail, ret=%d\n", __func__, blow_data[i].qfprom_addr, ret);
			goto err_fuse;
		}
		printk("%s:read addr 0x%x, lsb 0x%x, msb 0x%x\n", __func__, blow_data[i].qfprom_addr, p_buf[0], p_buf[1]);
		/* Don't rewrite if value to read is same value to write */
		if(((p_buf[0]&blow_data[i].lsb_data) == blow_data[i].lsb_data) &&
			((p_buf[1]&blow_data[i].msb_data) == blow_data[i].msb_data)) {
			printk("%s: 0x%x was blown already\n", __func__, blow_data[i].qfprom_addr);
		} else {
			msleep(10);
			ret = qfuse_write_single_row(blow_data[i].qfprom_addr, blow_data[i].lsb_data, blow_data[i].msb_data);
			if(ret != 0) {
				printk("%s: qfuse addr %x blow write error!!!\n", __func__, blow_data[i].qfprom_addr);
				ret = -EINVAL;
				goto err_fuse;
			} else {
				/* double check routine*/
				msleep(10);
				printk("%s: qfprom 0x%x addr write double check routine\n", __func__, blow_data[i].qfprom_addr);
				ret = qfuse_read_single_row(blow_data[i].qfprom_addr, 0, p_buf);
				if(ret != 0) {
					printk("%s: read fail when double check, ret=%d\n", __func__, ret);
					ret = -EINVAL;
					goto err_fuse;
				}
				if(((p_buf[0]&blow_data[i].lsb_data) == blow_data[i].lsb_data) &&
					((p_buf[1]&blow_data[i].msb_data) == blow_data[i].msb_data)) {
					printk("%s:write double check successfully", __func__);
				} else {
					printk("%s:qfprom write successful but error when double check\n", __func__);
					ret = -EINVAL;
					goto err_fuse;
				}

			}

		}
		fusing_flag |= (0x1<<i);
	}
	printk("%s: fusing flag = 0x%x\n", __func__, fusing_flag);
	printk("%s: fusing complete!!!!!!!!!!!!!!!!!!!!\n", __func__);
	kfree(p_buf);
	return count;

err_fuse:
	kfree(p_buf);
err:
	return ret;
}