Linux chip driver firmware automatic upgrade II: melfas TP upgrade instance

Source: Internet
Author: User

The firmware upgrade instance of ms6000 chip with melfas describes the installation process of image files in the general array format. The chip requires a pin combination to complete a certain sequence and enable a set of command codes to enter the burning mode, in the burning mode, the I2C address is 0xfa (different from the address 0x40 when the chip works normally). After the burning, reset and start corresponding normal TP operations. The general chip burning process is as follows:

The implementation code is as follows:

(1) Basic macro definition

# Define fiamware_name "melfas_w105.h" // The Name Of The array-Format Image static unsigned char ms6000ctpm_fw [] = // divide the space by array to store the burned image {# include fiamware_name }; # define bytes // specifies the address of the specified byte in the burned image # define ms6000_transfer_length64 // The number of packet bytes in one burn/* ISP command */# define ms6000_isp_1__erase0x02 # define # define sequence # define ms6000_isp_1__reset0x07 # define sequence # define ms6000_8bit_download_addr (ms6000_7bit_download_addr <1) // The i2cclient of Linux requires an 8-bit address # define response // mcs6000's responses # define response # define ms6000_mds_ack_read_flash0x84 # define response # define ms6000_mds_ack_read_locked0xfe # define ms6000_mds_ack_fail0xfe # define sequence # define Sequence

(2) functions for writing and reading TP flash using I2C
Note: The Register address is not required for single-byte read and write operations on the chip in Burn-in mode. Only the chip address can be sent. The i2c_client-> address used in the address has been changed.

Static bool mfs_i2c_write_single_byte (unsigned char bufval) {int ret; unsigned char Buf; Buf = bufval; ret = i2c_master_send (i2c_client, & Buf, 1); If (Ret <= 0) {printk ("mfs_i2c_write_single_byte error line = % d, ret = % d \ n", _ line __, RET); Return false;} return true ;} static bool mfs_i2c_read_single_byte (unsigned char * BUF) {int ret; ret = i2c_master_recv (i2c_client, Buf, 1); If (Ret <= 0) {printk ("mfs_i2c _ Read_single_byte error line = % d, ret = % d \ n ", _ line __, RET); Return false;} return true;} static int mfs_i2c_read_flash (unsigned char * pbuffer, uint16 naddr_start, unsigned char clength) {// read the clength bytes starting with naddr_start into the space indicated by pbuffer: int nret = bytes, I; bool Bret; unsigned char cmd [4], uctemp; // send read flash Command [read code-address high-address low-size] cmd [0] = ms6000 _ Isp_cmd_read_flash; cmd [1] = (uint8) (naddr_start> 8) & 0xff); cmd [2] = (uint8) (naddr_start) & 0xff ); CMD [3] = clength; for (I = 0; I <4; I ++) {Bret = mfs_i2c_write_single_byte (CMD [I]); udelay (15 ); if (Bret = false) goto ms6000_i2c_read_flash_finish;} // read 'result of command 'bret = mfs_i2c_read_single_byte (& uctemp); If (! Bret | uctemp! = Ms6000_mds_ack_read_flash) {goto ms6000_i2c_read_flash_finish;} // read data [pcmd [3] = size] for (I = 0; I <(INT) cmd [3]; I ++) {udelay (100); Bret = mfs_i2c_read_single_byte (pbuffer ++); If (Bret = false & I! = (INT) (CMD [3]-1) goto ms6000_i2c_read_flash_finish;} nret = ms6000_ret_success; ms6000_i2c_read_flash_finish: Return nret ;}

(3) enter the download function

Static void ms6000_write_download_mode_signal (void) // send a set of joint levels through the reset foot and Eint foot {int I; unsigned char enter_code [14] = {0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1}; for (I = 0; I <14; I ++) {If (enter_code [I]) {response (response, gpio_out_one); mt_set_gpio_out (response, gpio_out_one);} else {mt_set_gpio_out (response, gpio_out_zero); Response (response, gpio_out_zero);} Mt _ Set_gpio_out (hour, gpio_out_one); udelay (15); hour (hour, gpio_out_zero); udelay (100 );} round (round, gpio_out_one); udelay (100); mt_set_gpio_out (round, gpio_out_one); mt_set_gpio_out (round, gpio_out_one);} static int ms6000_ent Er_download_mode (void) {bool Bret; int nret = forward; unsigned char CDATA = 0; hwpowerdown (forward, "TP"); // tkey_vdd_set_low (); mt_set_gpio_mode (forward, break); mt_set_gpio_dir (break, gpio_dir_out); mt_set_gpio_out (break, gpio_out_zero); mt_set_gpio_mode (Break, break); mt_set_gpi O_dir (outputs, gpio_dir_out); outputs (outputs, gpio_out_zero); // I2C changes gpio function outputs (outputs, outputs); outputs (outputs, gpio_dir_out); // tkey_intr_set_output (); mt_set_gpio_out (gpio_ctp_eint_pin, gpio_out_zero); // tkey_intr_set_low (); mt_set_gpio_mode (delimiter, delimiter); mt_set_gpio_dir (delimiter) In, gpio_dir_out); // tkey_resetb_set_output (); mt_set_gpio_out (idle, gpio_out_zero); // call mdelay (90) to reduce power supply ); // delay for stable vddhwpoweron (cost, vol_2800, "TP"); // round (); Round (cost, gpio_out_one); // tkey_ce_set_high (); mt_set_gpio_out (cost, gpio_out_one); // tkey_i2c_sda_set_high (); mdelay (25); ms6000_write_download_mode_s Ignal (); // write the command code mt_set_gpio_mode (gpio_i2c0_sca_pin, serial); mt_set_gpio_mode (serial, serial); // enable the I2C pin to restore the I2C function mdelay (2 ); bret = mfs_i2c_read_single_byte (& CDATA); If (Bret! = True | CDATA! = Ms6000_i2c_slave_ready_status) {goto ms6000_enter_download_mode_finish;} elseprintk ("respond from download mode commande is 0x55 \ r \ n"); // only the chip status returns 0x55, to enter the download mode nret = ms6000_ret_success; // entering mds isp mode finished. ms6000_enter_download_mode_finish: Return nret ;}

(4) chip reset and TP flash Erasure

Static void ms6000_reset_command (void) // whether the upgrade fails or succeeds, reset and enable the chip {unsigned char Buf; mdelay (1); Buf = ms6000_isp_assist_reset; if (bytes (BUF) = true) printk ("mfs6000_reset_command reset success \ r \ n"); mt_set_gpio_mode (delimiter, delimiter); mt_set_gpio_dir (delimiter, gpio_dir_in ); mt_set_gpio_pull_enable (gpio_ctp_eint_pin, gpio_pull_enable); mt_set_gpio_pul Rochelle select (gpio_ctp_eint_pin, gpio_pull_up); // restore the pin function of Eint mdelay (180);} static unsigned char ms6000_getlibver (void) // obtain the version number in the new firmware, to compare {unsigned int SZ; SZ = sizeof (ms6000ctpm_fw); If (SZ> 2) {return (ms6000ctpm_fw [157]-0x30 ); // version number byte data} else {return 0xff;} static int ms6000_i2c_prepare_erase_flash (void) {int nret = forward, I; bool Bret; uint8 i2c_buffer [4] = {ms6000_isp_cmd _ Erase_timing, lag, ms6000_isp_erase_timing_value_1, ms6000_isp_erase_timing_value_2}; uint8uctemp; // send erase setting CODEFOR (I = 0; I <4; I +) {Bret = mfs_i2c_write_single_byte (i2c_buffer [I]); If (! Bret) {goto streams;} udelay (15);} // read resultudelay (500); Bret = mfs_i2c_read_single_byte (& uctemp); If (Bret & uctemp = bytes) {nret = ms6000_ret_success;} response: Return nret;} static int forward (void) {int nret = forward, I; bool Bret; uint8 i2c_buffer [1] = {ms6000_isp_assist_era Se}; uint8 uctemp; // send erase CODEFOR (I = 0; I <1; I ++) {Bret = mfs_i2c_write_single_byte (i2c_buffer [I]); If (! Bret) goto dependencies; udelay (15);} // read resultmdelay (45); Bret = mfs_i2c_read_single_byte (& uctemp); If (Bret & uctemp = bytes) {nret = ms6000_ret_success;} ms6000_i2c_erase_flash_finish: Return nret ;}

(5) pre-programming and programming functions, as well as the main functions of the download Image

Static int ms6000_i2c_prepare_program (void) {int nret = forward, I; bool Bret; uint8 i2c_buffer [4] = {ms6000_isp_1__program_timing, distance }; // write program timing informationfor (I = 0; I <4; I ++) {Bret = mfs_i2c_write_single_byte (i2c_buffer [I]); If (Bret = false) goto ms6000_i2c_pre Pare_program_finish; udelay (15) ;}udelay (500); // READ command's resultbret = mfs_i2c_read_single_byte (& i2c_buffer [4]); if (Bret = false | i2c_buffer [4]! = Success) goto continue; mdelay (100); nret = ms6000_ret_success; success: Return nret;} static int ms6000_i2c_program_flash (uint8 * pdata, uint16 naddr_start, uint8 clength) // flash one packet programming main function {// The parameter is the data to be programmed, the write address, the length of the data to be programmed int nret = ms6000_ret_program_flash_failed; int I, j; bool Bret; uint8 CDATA; uint8 TMP; uint8 cmd [4]; // send Program Codecmd [0] = ms6000_isp_1__program_flash; cmd [1] = (uint8) (naddr_start> 8) & 0xff); cmd [2] = (uint8) (naddr_start) & 0xff); cmd [3] = clength; for (I = 0; I <4; I ++) {Bret = mfs_i2c_write_single_byte (CMD [I]); udelay (15); If (Bret = false) goto continue;} // check Command resultbret = mfs_i2c_read_single_byte (& CDATA); If (Bret = false | CDATA! = Ms6000_mds_ack_program_flash) {goto ms6000_i2c_program_flash_finish;} // program dataudelay (150); for (I = 0; I <(INT) cmd [3]; I + = 2) {// write two bytes at a time, first write high, then write low Bret = mfs_i2c_write_single_byte (pdata [I + 1]); If (Bret = false) goto ms6000_i2c_program_flash_finish; udelay (100); // delay about 150 usbret = forward (pdata [I]); udelay (150); // delay about 150 usif (Bret = false) goto ms6000_i2c_program _ Flash_finish;} nret = ms6000_ret_success; ms6000_i2c_program_flash_finish: Return nret;} static int ms6000_download (const uint8 * pdata, const uint16 nlength) // download main function, the parameter is the first address of the image memory and the image length {int I, nret; unsigned char clength, buffer [ms6000_transfer_length]; uint16_t nstart_address = 0; unsigned char * poriginal_data; // enter in download modenret = ms6000_enter_download_mode (); If (nret! = Ms6000_ret_success) goto ms6000_download_finish; mdelay (1); // erase flashnret = ms6000_i2c_prepare_erase_flash (); If (nret! = Ms6000_ret_success) {goto ms6000_download_finish;} mdelay (1); nret = ms6000_i2c_erase_flash (); If (nret! = Success) goto ms6000_download_finish; mdelay (1); // verify erasenret = mfs_i2c_read_flash (buffer, 0x00, 16); // must be '0xff' after eraseif (nret! = Ms6000_ret_success) goto ms6000_download_finish; for (I = 0; I <16; I ++) {If (buffer [I]! = 0xff) {nret = forward; goto ms6000_download_finish;} mdelay (1); // prepare for program flash. nret = ms6000_i2c_prepare_program (); If (nret! = Ms6000_ret_success) goto ms6000_download_finish; mdelay (1); // program flash # If 1poriginal_data = (uint8 *) pdata; // retain the original first address nstart_address = 0; // The start address of the burn-in process: clength = ms6000_transfer_length; // The length of each burn-in process: 64 BFOR (nstart_address = 0; nstart_address <nlength; nstart_address + = clength) {if) <ms6000_transfer_length) {clength = (uint8) (nlength-nstart_address); clength + = (clength % 2 );// For odd length. If it is less than 64b, add 1 byte to the end for even processing, because it is burned in Word} nret = ms6000_i2c_program_flash (poriginal_data, nstart_address, clength); If (nret! = Success) {goto ms6000_download_finish;} poriginal_data + = clength; udelay (500); printk ("#");} printk ("mfs6000 program finished \ r \ n "); # endif // verify flash # If 1poriginal_data = (uint8 *) pdata; // retain the original first address nstart_address = 0; clength = Hangzhou; For (nstart_address = 0; nstart_address <nlength; nstart_address + = clength) {If (nlength-nstart_address) <ms6000_transfer_length) {C Length = (uint8) (nlength-nstart_address); clength + = (clength % 2); // for odd length .} // read flashnret = mfs_i2c_read_flash (buffer, nstart_address, clength); // comparingfor (I = 0; I <(INT) clength; I ++) {If (buffer [I]! = Poriginal_data [I]) {// If the read address byte is different from the original address data, nret = bytes; goto ms6000_download_finish;} poriginal_data + = clength; udelay (500 ); printk ("*");} printk ("mfs6000 verify finished \ r \ n"); # endifnret = ms6000_ret_success; ms6000_download_finish: ms6000_reset_command (); Return nret ;}

(6) Upgrade the main function and process the TP probe function.

Static int ms6000_firmware_upgrade () {unsigned char newfwversion, oldfwversion; uint16_t nbinary_length = 0; int nread = 0; unsigned char * ptrbuff = NULL; int ret = bytes; if (mfs_i2c_read_single_reg (0x21, & oldfwversion) = true) {// prior to this, TP power supply and initialization must be available; otherwise, newfwversion = ms6000_getver lib() cannot be read (); printk ("mfs6000 oldfwversion is % d, and newfwversion is % d \ r \ n", oldfwversion, newfwversion);} I2C _ Client-> ADDR = ms6000_8bit_download_addr; // convert it to the TP upgrade I2C address if (newfwversion! = Oldfwversion) {// if the version number is different, upgrade ptrbuff = ms6000ctpm_fw; nbinary_length = sizeof (ms6000ctpm_fw); // download processprintk ("START Download \ r \ n "); mtk_wdt_disable (); ret = ms6000_download (ptrbuff, nbinary_length); mtk_wdt_get_en_setting (); // wdt and wdt enabling actions must be disabled before and after the upgrade, otherwise it is easy to restart // check process} else {// if the version number is the same, the printk ("because of the same Lib, update abort! \ R \ n ");} return ret;} // The changes in tpd_rrobe are as follows: {mt65xx_eint_mask (duration); // The Mask TP interrupt int upresult; upresult = ms6000_firmware_upgrade (); if (upresult = ms6000_ret_success) printk ("mfs6000 download success \ r \ n"); then (upresult); i2c_client-> ADDR = ms6000_8bit_i2caddr; // The I2C address mt_set_gpio_mode (gpio_i2c0_sca_pin, idle); mt_set_gpio_mode (idle, idle); // restores the I2C function foot mt65xx_eint_unmask (idle ); // unmask TP interrupt}

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.