/* SynaFlashFirmwareWrite writes the firmware section of the image block by block
 */
void SynaFlashFirmwareWrite(struct i2c_client *client)
{
	unsigned char *puFirmwareData = SynafirmwareImgData;
	unsigned char uData[2];
	unsigned short blockNum;
	enum FlashCommand cmd;

	TPD_LOG("%s\n", __func__);
	for (blockNum = 0; blockNum < SynaFirmwareBlockCount; ++blockNum) {
		if (blockNum == 0) {
			/* Block by blcok, write the block number and data to the corresponding F34 data registers */
			uData[0] = blockNum & 0xff;
			uData[1] = (blockNum & 0xff00) >> 8;
			writeRMI(client, SynaF34Reflash_BlockNum, &uData[0], 2);
		}

		writeRMI(client, SynaF34Reflash_BlockData, puFirmwareData, SynaFirmwareBlockSize);
		puFirmwareData += SynaFirmwareBlockSize;

		/* Issue the "Write Firmware Block" command */
		cmd = m_uF34ReflashCmd_FirmwareWrite;
		writeRMI(client, SynaF34_FlashControl, (unsigned char *)&cmd, 1);

		SynaWaitForATTN(1000, client);
		CheckFlashStatus(cmd, client);
/* #ifdef SHOW_PROGRESS */
#if 1				/* APK_TEST */
		if (blockNum % 100 == 0)
			TPD_LOG("blk %d / %d\n", blockNum, SynaFirmwareBlockCount);
#endif
	}
/* SynaEnableFlashing kicks off the reflash process
 */
void SynaEnableFlashing(struct i2c_client *client)
{
	unsigned char uStatus = 0;
	enum FlashCommand cmd;
	TPD_LOG("%s\n", __func__);
	TPD_LOG("Enable Reflash...\n");

	readRMI(client, SynaF01DataBase, &uStatus, 1);

/* APK_TEST */
	TPD_LOG("APK_TEST uStatus= 0x%02x\n", uStatus);

	if ((uStatus & 0x40) == 0 /*|| force */) {
		/* Reflash is enabled by first reading the bootloader ID from the firmware and write it back */
		SynaReadBootloadID(client);
		SynaWriteBootloadID(client);

		/* Write the "Enable Flash Programming command to F34 Control register */
		/* Wait for ATTN and then clear the ATTN. */
		cmd = m_uF34ReflashCmd_Enable;
		writeRMI(client, SynaF34_FlashControl, (unsigned char *)&cmd, 1);
		SynaWaitForATTN(1000, client);

		/* I2C addrss may change */
		/* ConfigCommunication();//APK_TEST */

		/* Scan the PDT again to ensure all register offsets are correct */
		SynaScanPDT(client);

		/* Read the "Program Enabled" bit of the F34 Control register, and proceed only if the */
		/* bit is set. */
		CheckFlashStatus(cmd, client);
	}
}
/* SynaEnableFlashing kicks off the reflash process
 */
static int SynaEnableFlashing(void)
{
    unsigned char uData;
    unsigned char uStatus;
    int retry = 3;

    printk("\nEnable Reflash...\n");

    // Reflash is enabled by first reading the bootloader ID from the firmware and write it back
    SynaReadBootloadID();
    SynaWriteBootloadID();

    // Make sure Reflash is not already enabled
    do {
        readRMI(SynaF34_FlashControl, &uData, 1);
        printk("----Read reflash enable ---uData=0x%x--\n",uData);
    } while (uData  ==  0x0f);//while (((uData & 0x0f) != 0x00));

    // Clear ATTN
    readRMI (SynaF01DataBase, &uStatus, 1);
    printk("----Read status ---uStatus=0x%x--\n",uStatus);
    if ((uStatus &0x40) == 0) {
        // Write the "Enable Flash Programming command to F34 Control register
        // Wait for ATTN and then clear the ATTN.
        //uData = 0x0f;    //lemon
        readRMI(SynaF34_FlashControl, &uData, 1);
        uData = uData | 0x0f;  
        writeRMI(SynaF34_FlashControl, &uData, 1);
        SynaWaitForATTN();
        readRMI((SynaF01DataBase + 1), &uStatus, 1);

        // Scan the PDT again to ensure all register offsets are correct
        SynaSetup();

        // Read the "Program Enabled" bit of the F34 Control register, and proceed only if the
        // bit is set.
        readRMI(SynaF34_FlashControl, &uData, 1);
        printk("----read--enable ---uData=0x%x--\n",uData);
        while (uData != 0x80) {
            // In practice, if uData!=0x80 happens for multiple counts, it indicates reflash
            // is failed to be enabled, and program should quit
            printk("%s Can NOT enable reflash !!!\n",__func__);

            if (!retry--)
                return -1;
            readRMI(SynaF34_FlashControl, &uData, 1);
            printk("----read--enable ---uData=0x%x--\n",uData);
        }
    }
    return 0;
}
/* EraseConfigBlock erases the config block
*/
void eraseAllBlock(struct i2c_client *client)
{
	enum FlashCommand cmd;

	TPD_LOG("%s\n", __func__);
	/* Erase of config block is done by first entering into bootloader mode */
	SynaReadBootloadID(client);
	SynaWriteBootloadID(client);

	/* Command 7 to erase config block */
	cmd = m_uF34ReflashCmd_EraseAll;
	writeRMI(client, SynaF34_FlashControl, (unsigned char *)&cmd, 1);

	SynaWaitForATTN(6000, client);
	CheckFlashStatus(cmd, client);
}
/* SynaFinalizeReflash finalizes the reflash process
 */
static void SynaFinalizeReflash(void)
{
    unsigned char uData;
    unsigned char uStatus;

    printk("\nFinalizing Reflash...\n");

    // Issue the "Reset" command to F01 command register to reset the chip
    // This command will also test the new firmware image and check if its is valid
    uData = 1;
    writeRMI(SynaF01CommandBase, &uData, 1);

    SynaWaitForATTN();
    readRMI(SynaF01DataBase, &uData, 1);
    printk("-----SynaFinalizeReflash-1-\n");
    // Sanity check that the reflash process is still enabled
    do {
        readRMI(SynaF34_FlashControl, &uStatus, 1);
        printk("-----SynaFinalizeReflash-2-\n");
    } while ((uStatus & 0x0f) != 0x00);
    printk("-----SynaFinalizeReflash-3-\n");
    readRMI((SynaF01DataBase + 1), &uStatus, 1);
    printk("-----SynaFinalizeReflash-4-\n");
    SynaSetup();
    printk("-----SynaFinalizeReflash-5-\n");
    uData = 0;

    // Check if the "Program Enabled" bit in F01 data register is cleared
    // Reflash is completed, and the image passes testing when the bit is cleared
    do {
        readRMI(SynaF01DataBase, &uData, 1);
        printk("-----SynaFinalizeReflash-6- data=%02x\n", uData);
    } while ((uData & 0x40) != 0);
    printk("-----SynaFinalizeReflash-7-\n");
    // Rescan PDT the update any changed register offsets
    SynaSetup();

    printk("\nReflash Completed. Please reboot.\n");
}
void SynaBootloaderLock(struct synaptics_ts_data *ts)//no ds4
{
	unsigned short lockBlockCount;
	unsigned char uData[2] = {0};
	unsigned short uBlockNum;
	enum FlashCommand cmd;

	if (my_image_bin[0x1E] == 0)
	{
		TOUCH_ERR_MSG( "Skip lockdown process with this .img\n");
		return;
	}
	// Check if device is in unlocked state
	readRMI(ts->client, (SynaF34QueryBase+ 1), &uData[0], 1);

	//Device is unlocked
	if (uData[0] & 0x02)
	{
		TOUCH_ERR_MSG("Device unlocked. Lock it first...\n");
		// Different bootloader version has different block count for the lockdown data
		// Need to check the bootloader version from the image file being reflashed
		switch (SynafirmwareImgVersion)
		{
			case 2:
				lockBlockCount = 3;
				break;
			case 3:
			case 4:
				lockBlockCount = 4;
				break;
			case 5:
			case 6:
				lockBlockCount = 5;
				break;
			default:
				lockBlockCount = 0;
				break;
		}

		// Write the lockdown info block by block
		// This reference code of lockdown process does not check for bootloader version
		// currently programmed on the ASIC against the bootloader version of the image to
		// be reflashed. Such case should not happen in practice. Reflashing cross different
		// bootloader versions is not supported.
		for (uBlockNum = 0; uBlockNum < lockBlockCount; ++uBlockNum)
		{
			uData[0] = uBlockNum & 0xff;
			uData[1] = (uBlockNum & 0xff00) >> 8;

			/* Write Block Number */
			writeRMI(ts->client, SynaF34Reflash_BlockNum, &uData[0], 2);

			/* Write Data Block */
			writeRMI(ts->client, SynaF34Reflash_BlockData, SynalockImgData, SynaFirmwareBlockSize);

			/* Move to next data block */
			SynalockImgData += SynaFirmwareBlockSize;

			/* Issue Write Lockdown Block command */
			cmd = m_uF34ReflashCmd_LockDown;
			writeRMI(ts->client, SynaF34_FlashControl, (unsigned char*)&cmd, 1);

			/* Wait ATTN until device is done writing the block and is ready for the next. */
			SynaWaitForATTN(1000,ts);
			CheckFlashStatus(ts,cmd);
		}

		// Enable reflash again to finish the lockdown process.
		// Since this lockdown process is part of the reflash process, we are enabling
		// reflash instead, rather than resetting the device to finish the unlock procedure.
		SynaEnableFlashing(ts);
	}