static int mcsdl_download(uint8_t *pgm_data,  uint16_t length )
{
	int i;
	int ret;
	uint8_t   cLength;
	uint16_t  nStart_address=0;
	uint8_t   buffer[MCSDL_TRANSFER_LENGTH];

	/* Enter Download mode */
	ret = mcsdl_enter_download_mode();
	if (0 != ret) {
		return -1;
	} 
	printk("mcsdl enter download mode success!\n");
	mdelay(1);

	/* erase flash */
	printk("Erasing...\n");
	ret = mcsdl_erase_flash();
	if (0 != ret) {
		return -1;
	}
	printk("Erase OK!\n");
	mdelay(1);

	/* Verify erase */
	printk("Verifying erase...\n");
	ret = mcsdl_read_flash(buffer, 0x00, 16);		/* Must be '0xFF' after erase */
	if (0 != ret) {
		return -1;
	}
	for(i=0; i<16; i++){
		if( buffer[i] != 0xFF ){
			printk("Verify flash error\n");
			return -1;
		}
	}
	mdelay(1);

	/* Prepare for Program flash */
	printk("Preparing Program...\n");
	ret = mcsdl_prepare_program();
	if (0 != ret) {
		return -1;
	}
	mdelay(1);

	/* Program flash */
	printk("Programing flash...");
	nStart_address = 0;
	cLength  = MCSDL_TRANSFER_LENGTH;
	for( nStart_address = 0; nStart_address < length; nStart_address+=cLength ){
		printk("#");
		if( ( length - nStart_address ) < MCSDL_TRANSFER_LENGTH ){
			cLength  = (uint8_t)(length - nStart_address);
			cLength += (cLength%2);									/* For odd length */
		}
		ret = mcsdl_program_flash(&pgm_data[nStart_address], nStart_address, cLength);
		if (0 != ret) {
			printk("\nProgram flash failed.\n");
			return -1;
		}
		ndelay(500);
	}

	/* Verify flash */
	printk("\nVerifying flash...");
	nStart_address = 0;
	cLength  = MCSDL_TRANSFER_LENGTH;
	for( nStart_address = 0; nStart_address < length; nStart_address+=cLength ){
		printk("#");
		if( ( length - nStart_address ) < MCSDL_TRANSFER_LENGTH ){
			cLength  = (uint8_t)(length - nStart_address);
			cLength += (cLength%2);									/* For odd length */
		}
		ret = mcsdl_read_flash(buffer, nStart_address, cLength);

		if (0 != ret) {
			printk("\nVerify flash read failed.\n");
			return -1;
		}
		for(i=0; i<(int)cLength; i++){
			if( buffer[i] != pgm_data[nStart_address+i] ){
				printk("\nVerify flash compare failed.\n");
				return -1;
			}
		}
		ndelay(500);
	}
	printk("\n");

	/* Reset command */
	mdelay(1);
	ret = i2c_smbus_write_byte(g_client, 0x07);						/* 0x07 is reset cmd */
	if( 0 != ret ){
		printk("reset error\n");
		return -1;
	}
	mdelay(180);

	return 0;
}
static int mcsdl_download(const UINT8 *pData, const UINT16 nLength )
{
    int        i;
    int        nRet;

    UINT8   cLength;
    UINT16  nStart_address=0;

    UINT8    buffer[MELFAS_TRANSFER_LENGTH];
    UINT8    *pOriginal_data;


    #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
    printk("Starting download...\n");
    #endif
    //--------------------------------------------------------------
    //
    // Enter Download mode
    //
    //--------------------------------------------------------------
    nRet = mcsdl_enter_download_mode();

    if( nRet != MCSDL_RET_SUCCESS )
        goto MCSDL_DOWNLOAD_FINISH;


    mcsdl_delay(MCSDL_DELAY_1MS);                    // Delay '1 msec'

    //--------------------------------------------------------------
    //
    // Check H/W Revision Option
    //
    // ( Don't download firmware, if Module H/W revision does not match. )
    //
    //--------------------------------------------------------------
    #if MELFAS_DISABLE_DOWNLOAD_IF_MODULE_VERSION_DOES_NOT_MATCH

        #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
        printk("Checking module revision...\n");
        #endif

        pOriginal_data  = (UINT8 *)pData;

        nRet = mcsdl_i2c_read_flash( buffer, MCSDL_ADDR_MODULE_REVISION, 4 );

        if( nRet != MCSDL_RET_SUCCESS )
            goto MCSDL_DOWNLOAD_FINISH;

        if(     (pOriginal_data[MCSDL_ADDR_MODULE_REVISION+1] != buffer[1])
            ||    (pOriginal_data[MCSDL_ADDR_MODULE_REVISION+2] != buffer[2]) ){

            nRet = MCSDL_RET_WRONG_MODULE_REVISION;
            goto MCSDL_DOWNLOAD_FINISH;
        }

        mcsdl_delay(MCSDL_DELAY_1MS);                    // Delay '1 msec'

    #endif


    //--------------------------------------------------------------
    //
    // Erase Flash
    //
    //--------------------------------------------------------------

    #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
    printk("Erasing...\n");
    #endif

    nRet = mcsdl_i2c_prepare_erase_flash();

    if( nRet != MCSDL_RET_SUCCESS ){
        goto MCSDL_DOWNLOAD_FINISH;
    }

    mcsdl_delay(MCSDL_DELAY_1MS);                    // Delay '1 msec'

    nRet = mcsdl_i2c_erase_flash();

    if( nRet != MCSDL_RET_SUCCESS ){
        goto MCSDL_DOWNLOAD_FINISH;
    }

    mcsdl_delay(MCSDL_DELAY_1MS);                    // Delay '1 msec'


    //--------------------------------------------------------------
    //
    // Verify erase
    //
    //--------------------------------------------------------------
    #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
    printk("Verify Erasing...\n");
    #endif

    nRet = mcsdl_i2c_read_flash( buffer, 0x00, 16 );        // Must be '0xFF' after erase

    if( nRet != MCSDL_RET_SUCCESS )
        goto MCSDL_DOWNLOAD_FINISH;

    for(i=0; i<16; i++){

        if( buffer[i] != 0xFF ){

            nRet = MCSDL_RET_ERASE_VERIFY_FAILED;
            goto MCSDL_DOWNLOAD_FINISH;
        }
    }

    mcsdl_delay(MCSDL_DELAY_1MS);                            // Delay '1 msec'


    //--------------------------------------------------------------
    //
    // Prepare for Program flash.
    //
    //--------------------------------------------------------------
    #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
    printk("Preparing Program...\n");
    #endif

    nRet = mcsdl_i2c_prepare_program();

    if( nRet != MCSDL_RET_SUCCESS )
        goto MCSDL_DOWNLOAD_FINISH;


    mcsdl_delay(MCSDL_DELAY_1MS);                    // Delay '1 msec'


    //--------------------------------------------------------------
   //
   // Program flash
   //
    //--------------------------------------------------------------

    #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
    printk("Program flash...  ");
    #endif

    pOriginal_data  = (UINT8 *)pData;

    nStart_address = 0;
    cLength  = MELFAS_TRANSFER_LENGTH;

    for( nStart_address = 0; nStart_address < nLength; nStart_address+=cLength ){

        #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
        printk("#");
        #endif

        if( ( nLength - nStart_address ) < MELFAS_TRANSFER_LENGTH ){
            cLength  = (UINT8)(nLength - nStart_address);

            cLength += (cLength%2);                                    // For odd length.
        }

        nRet = mcsdl_i2c_program_flash( pOriginal_data, nStart_address, cLength );

        if( nRet != MCSDL_RET_SUCCESS ){

            #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
            printk("\nProgram flash failed position : 0x%x / nRet : 0x%x ", nStart_address, nRet);
            #endif

            goto MCSDL_DOWNLOAD_FINISH;
        }

        pOriginal_data  += cLength;

        mcsdl_delay(MCSDL_DELAY_500US);                    // Delay '500 usec'

    }


    //--------------------------------------------------------------
    //
    // Verify flash
    //
    //--------------------------------------------------------------

    #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
    printk("\n");
    printk("Verify flash...   ");
    #endif

    pOriginal_data  = (UINT8 *) pData;

    nStart_address = 0;

    cLength  = MELFAS_TRANSFER_LENGTH;

    for( nStart_address = 0; nStart_address < nLength; nStart_address+=cLength ){

        #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
        printk("#");
        #endif

        if( ( nLength - nStart_address ) < MELFAS_TRANSFER_LENGTH ){
            cLength = (UINT8)(nLength - nStart_address);

            cLength += (cLength%2);                                    // For odd length.
        }

        //--------------------
        // Read flash
        //--------------------
        nRet = mcsdl_i2c_read_flash( buffer, nStart_address, cLength );

        //--------------------
        // Comparing
        //--------------------

        for(i=0; i<(int)cLength; i++){

            if( buffer[i] != pOriginal_data[i] ){

                #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
                printk("\n [Error] Address : 0x%04X : 0x%02X - 0x%02X\n", nStart_address, pOriginal_data[i], buffer[i] );
                #endif

                nRet = MCSDL_RET_PROGRAM_VERIFY_FAILED;
                goto MCSDL_DOWNLOAD_FINISH;

            }
        }

        pOriginal_data += cLength;

        mcsdl_delay(MCSDL_DELAY_500US);                    // Delay '500 usec'
    }

    #if MELFAS_ENABLE_DBG_PROGRESS_PRINT
    printk("\n");
    #endif

    nRet = MCSDL_RET_SUCCESS;


MCSDL_DOWNLOAD_FINISH :

    mcsdl_delay(MCSDL_DELAY_1MS);                            // Delay '1 msec'

    //---------------------------
    //    Reset command
    //---------------------------
    buffer[0] = MCSDL_ISP_CMD_RESET;

    _i2c_write_( MCSDL_I2C_SLAVE_ADDR_ORG, buffer, 1 );
//    TKEY_INTR_SET_INPUT();                                    // Rollback Interrupt port
    TKEY_INTR_SET_AF();                                    // Rollback Interrupt port

    mcsdl_delay(MCSDL_DELAY_45MS);                            // Delay about '200 msec'
    mcsdl_delay(MCSDL_DELAY_45MS);
    mcsdl_delay(MCSDL_DELAY_45MS);
    mcsdl_delay(MCSDL_DELAY_45MS);

    return nRet;
}