12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * FTS Capacitive touch screen controller (FingerTipS)
- *
- * Copyright (C) 2016-2019, STMicroelectronics Limited.
- * Authors: AMG(Analog Mems Group) <[email protected]>
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /**
- *
- **************************************************************************
- ** STMicroelectronics **
- **************************************************************************
- ** [email protected] **
- **************************************************************************
- * *
- * FTS API for Flashing the IC *
- * *
- **************************************************************************
- **************************************************************************
- *
- */
- #include <linux/init.h>
- #include <linux/errno.h>
- #include <linux/platform_device.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/slab.h>
- #include <linux/string.h>
- #include <stdarg.h>
- #include <linux/input.h>
- #include <linux/interrupt.h>
- #include <linux/serio.h>
- #include <linux/time.h>
- #include <linux/pm.h>
- #include <linux/delay.h>
- #include <linux/ctype.h>
- #include <linux/gpio.h>
- #include <linux/i2c.h>
- #include <linux/i2c-dev.h>
- #include <linux/fs.h>
- #include <linux/uaccess.h>
- #include <linux/power_supply.h>
- #include <linux/firmware.h>
- #include <linux/regulator/consumer.h>
- #include <linux/of_gpio.h>
- #include "ftsCrossCompile.h"
- #include "ftsCompensation.h"
- #include "ftsError.h"
- #include "ftsFlash.h"
- #include "ftsFrame.h"
- #include "ftsIO.h"
- #include "ftsSoftware.h"
- #include "ftsTest.h"
- #include "ftsTime.h"
- #include "ftsTool.h"
- #include "../fts.h"//needed for including the define FW_H_FILE
- #ifdef FW_H_FILE
- #include <../fts_fw.h>
- #define LOAD_FW_FROM 1
- #else
- #define LOAD_FW_FROM 0
- #endif
- #define FTS_LATEST_VERSION 0x1101
- static char tag[8] = "[ FTS ]\0";
- int getFirmwareVersion(u16 *fw_vers, u16 *config_id)
- {
- u8 fwvers[DCHIP_FW_VER_BYTE];
- u8 confid[CONFIG_ID_BYTE];
- int res;
- res = readCmdU16(FTS_CMD_HW_REG_R, DCHIP_FW_VER_ADDR,
- fwvers, DCHIP_FW_VER_BYTE, DUMMY_HW_REG);
- if (res < OK) {
- logError(1,
- "%s %s:unable to read fw_version ERROR %02X\n",
- tag, __func__, ERROR_FW_VER_READ);
- return (res | ERROR_FW_VER_READ);
- }
- u8ToU16(fwvers, fw_vers); //fw version use big endian
- if (*fw_vers != 0) {
- // if fw_version is 00 00 means that there is
- //no firmware running in the chip therefore will be
- //impossible find the config_id
- res = readB2(CONFIG_ID_ADDR, confid, CONFIG_ID_BYTE);
- if (res < OK) {
- logError(1, "%s %s:unable to read config_id ",
- tag, __func__);
- logError(1, "ERROR %02X\n", ERROR_FW_VER_READ);
- return (res | ERROR_FW_VER_READ);
- }
- u8ToU16(confid, config_id); //config id use little endian
- } else {
- *config_id = 0x0000;
- }
- logError(0, "%s FW VERS = %04X\n", tag, *fw_vers);
- logError(0, "%s CONFIG ID = %04X\n", tag, *config_id);
- return OK;
- }
- int getFWdata_nocheck(const char *pathToFile, u8 **data, int *size, int from)
- {
- const struct firmware *fw = NULL;
- struct device *dev = getDev();
- int res;
- if (dev == NULL)
- return ERROR_OP_NOT_ALLOW;
- logError(0, "%s Read FW from BIN file!\n", tag);
- res = firmware_request_nowarn(&fw, pathToFile, dev);
- if (res) {
- logError(1, "%s %s:No File found! ERROR %08X\n",
- tag, __func__, ERROR_FILE_NOT_FOUND);
- return ERROR_FILE_NOT_FOUND;
- }
- *size = fw->size;
- *data = (u8 *)kmalloc_array((*size), sizeof(u8), GFP_KERNEL);
- if (*data == NULL) {
- logError(1, "%s %s:Impossible to allocate! %08X\n", __func__);
- release_firmware(fw);
- return ERROR_ALLOC;
- }
- memcpy(*data, (u8 *)fw->data, (*size));
- release_firmware(fw);
- logError(0, "%s %s:Finshed!\n", tag, __func__);
- return OK;
- }
- int getFWdata(const char *pathToFile, u8 **data, int *size, int from)
- {
- const struct firmware *fw = NULL;
- struct device *dev = NULL;
- int res;
- logError(0, "%s %s starting...\n", tag, __func__);
- switch (from) {
- #ifdef FW_H_FILE
- case 1:
- logError(1, "%s Read FW from .h file!\n", tag);
- *size = FW_SIZE_NAME;
- *data = (u8 *)kmalloc_array((*size), sizeof(u8), GFP_KERNEL);
- if (*data == NULL) {
- logError(1, "%s %s:Impossible to allocate memory! ",
- tag, __func__);
- logError(1, "ERROR %08X\n", ERROR_ALLOC);
- return ERROR_ALLOC;
- }
- memcpy(*data, (u8 *)FW_ARRAY_NAME, (*size));
- break;
- #endif
- default:
- logError(0, "%s Read FW from BIN file!\n", tag);
- if (ftsInfo.u16_fwVer >= FTS_LATEST_VERSION)
- return ERROR_FW_NO_UPDATE;
- dev = getDev();
- if (dev != NULL) {
- res = firmware_request_nowarn(&fw, pathToFile, dev);
- if (res == 0) {
- *size = fw->size;
- *data = (u8 *)kmalloc_array((*size), sizeof(u8),
- GFP_KERNEL);
- if (*data == NULL) {
- logError(1, "%s %s:Impossible to ",
- tag, __func__);
- logError(1, "%allocate! %08X\n",
- ERROR_ALLOC);
- release_firmware(fw);
- return ERROR_ALLOC;
- }
- memcpy(*data, (u8 *)fw->data, (*size));
- release_firmware(fw);
- } else {
- logError(0, "%s %s:No File found! ERROR %08X\n",
- tag, __func__, ERROR_FILE_NOT_FOUND);
- return ERROR_FILE_NOT_FOUND;
- }
- } else {
- logError(1, "%s %s:No device found! ERROR %08X\n",
- tag, __func__, ERROR_OP_NOT_ALLOW);
- return ERROR_OP_NOT_ALLOW;
- }
- /* break; */
- }
- logError(0, "%s %s:Finshed!\n", tag, __func__);
- return OK;
- }
- int readFwFile(const char *path, struct Firmware *fw, int keep_cx)
- {
- int res;
- int orig_size;
- u8 *orig_data = NULL;
- res = getFWdata(path, &orig_data, &orig_size, LOAD_FW_FROM);
- if (res < OK) {
- logError(0, "%s %s:impossible retrieve FW... ERROR %08X\n",
- tag, __func__, ERROR_MEMH_READ);
- return (res | ERROR_MEMH_READ);
- }
- res = parseBinFile(orig_data, orig_size, fw, keep_cx);
- if (res < OK) {
- logError(1, "%s %s:impossible parse ERROR %08X\n",
- tag, __func__, ERROR_MEMH_READ);
- return (res | ERROR_MEMH_READ);
- }
- return OK;
- }
- int flashProcedure(const char *path, int force, int keep_cx)
- {
- struct Firmware fw;
- int res;
- fw.data = NULL;
- logError(0, "%s Reading Fw file...\n", tag);
- res = readFwFile(path, &fw, keep_cx);
- if (res < OK) {
- logError(0, "%s %s: ERROR %02X\n",
- tag, __func__, (res | ERROR_FLASH_PROCEDURE));
- kfree(fw.data);
- return (res | ERROR_FLASH_PROCEDURE);
- }
- logError(0, "%s Fw file read COMPLETED!\n", tag);
- logError(0, "%s Starting flashing procedure...\n", tag);
- res = flash_burn(&fw, force, keep_cx);
- if (res < OK && res != (ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED)) {
- logError(1, "%s %s: ERROR %02X\n",
- tag, __func__, ERROR_FLASH_PROCEDURE);
- kfree(fw.data);
- return (res | ERROR_FLASH_PROCEDURE);
- }
- logError(0, "%s flashing procedure Finished!\n", tag);
- kfree(fw.data);
- return res;
- }
- #ifdef FTM3_CHIP
- int flash_status(void)
- {
- u8 cmd[2] = {FLASH_CMD_READSTATUS, 0x00};
- u8 readData = 0;
- logError(0, "%s %s:Reading ...\n", tag, __func__);
- if (fts_readCmd(cmd, 2, &readData, FLASH_STATUS_BYTES) < 0) {
- logError(1, "%s %s: ERROR % 02X\n", tag, __func__, ERROR_I2C_R);
- return ERROR_I2C_R;
- }
- readData &= 0x01;
- logError(0, "%s %s = %d\n", tag, __func__, readData);
- return (int) readData;
- }
- int flash_status_ready(void)
- {
- int status = flash_status();
- if (status == ERROR_I2C_R) {
- logError(1, "%s %s: ERROR % 02X\n", tag, __func__, ERROR_I2C_R);
- return ERROR_I2C_R;
- }
- if (status != FLASH_READY) {
- //logError(1,
- //"%s %s:flash busy or unknown STATUS = % 02X\n",
- //tag, status);
- return ERROR_FLASH_UNKNOWN;
- }
- return FLASH_READY;
- }
- int wait_for_flash_ready(void)
- {
- int status;
- int (*code)(void);
- code = flash_status_ready;
- logError(0, "%s Waiting for flash ready...\n", tag);
- status = attempt_function(code, FLASH_WAIT_BEFORE_RETRY,
- FLASH_RETRY_COUNT);
- if (status != FLASH_READY) {
- logError(1, "%s %s: ERROR % 02X\n",
- tag, __func__, ERROR_FLASH_NOT_READY);
- return (status | ERROR_FLASH_NOT_READY);
- }
- logError(0, "%s Flash ready!\n", tag);
- return OK;
- }
- int flash_unlock(void)
- {
- int status;
- //write the command to perform the unlock
- u8 cmd[3] = {FLASH_CMD_UNLOCK, FLASH_UNLOCK_CODE0,
- FLASH_UNLOCK_CODE1};
- logError(0, "%s Try to unlock flash...\n", tag);
- status = wait_for_flash_ready();
- if (status != OK) {
- logError(1, "%s %s: ERROR % 02X\n",
- tag, __func__, ERROR_FLASH_NOT_READY);
- //Flash not ready within the chosen time, better exit!
- return (status | ERROR_FLASH_NOT_READY);
- }
- logError(0, "%s Command unlock ...\n", tag);
- if (fts_writeCmd(cmd, sizeof(cmd)) < 0) {
- logError(1, "%s %s: ERROR % 02X\n",
- tag, __func__, ERROR_I2C_W);
- return ERROR_I2C_W;
- }
- status = wait_for_flash_ready();
- if (status != OK) {
- logError(1, "%s %s: ERROR % 02X\n",
- tag, __func__, ERROR_FLASH_NOT_READY);
- //Flash not ready within the chosen time,
- //better exit!
- return (status | ERROR_FLASH_NOT_READY);
- }
- logError(0, "%s Unlock flash DONE!\n", tag);
- return OK;
- }
- int parseBinFile(u8 *fw_data, int fw_size, Firmware *fwData, int keep_cx)
- {
- int dimension;
- if (keep_cx) {
- dimension = FW_SIZE - FW_CX_SIZE;
- logError(1, "%s %s: Selected 124k Configuration!\n",
- tag, __func__);
- } else {
- dimension = FW_SIZE;
- logError(1, "%s %s: Selected 128k Configuration!\n",
- tag, __func__);
- }
- if (fw_size - FW_HEADER_SIZE != FW_SIZE || fw_data == NULL) {
- logError(1, "%s %s:Read only %d instead of %d... ERROR %02X\n",
- tag, __func__,
- fw_size - FW_HEADER_SIZE,
- FW_SIZE, ERROR_FILE_PARSE);
- kfree(fw_data);
- return ERROR_FILE_PARSE;
- }
- fwData->data = (u8 *)kmalloc_array(dimension, sizeof(u8), GFP_KERNEL);
- if (fwData->data == NULL) {
- logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_ALLOC);
- kfree(fw_data);
- return ERROR_ALLOC;
- }
- memcpy(fwData->data, ((u8 *)(fw_data) + FW_HEADER_SIZE),
- dimension);
- fwData->data_size = dimension;
- fwData->fw_ver = (u16)(((fwData->data[FW_VER_MEMH_BYTE1] & 0x00FF) << 8)
- + (fwData->data[FW_VER_MEMH_BYTE0] & 0x00FF));
- fwData->config_id = (u16)(((fwData->data[(FW_CODE_SIZE)
- + FW_OFF_CONFID_MEMH_BYTE1] & 0x00FF) << 8)
- + (fwData->data[(FW_CODE_SIZE) +
- FW_OFF_CONFID_MEMH_BYTE0] & 0x00FF));
- logError(0, "%s %s: FW VERS File = %04X\n",
- tag, __func__, fwData->fw_ver);
- logError(0, "%s %s: CONFIG ID File = %04X\n",
- tag, __func__, fwData->config_id);
- logError(0, "%s READ FW DONE %d bytes!\n", tag, fwData->data_size);
- kfree(fw_data);
- return OK;
- }
- int fillMemory(u32 address, u8 *data, int size)
- {
- int remaining = size;
- int toWrite = 0;
- int delta;
- u8 *buff = (u8 *)kmalloc_array((MEMORY_CHUNK + 3), sizeof(u8),
- GFP_KERNEL);
- if (buff == NULL) {
- logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_ALLOC);
- return ERROR_ALLOC;
- }
- while (remaining > 0) {
- if (remaining >= MEMORY_CHUNK) {
- if ((address + MEMORY_CHUNK) < FLASH_ADDR_SWITCH_CMD) {
- buff[0] = FLASH_CMD_WRITE_LOWER_64;
- toWrite = MEMORY_CHUNK;
- remaining -= MEMORY_CHUNK;
- } else {
- if (address < FLASH_ADDR_SWITCH_CMD) {
- delta = FLASH_ADDR_SWITCH_CMD - address;
- buff[0] = FLASH_CMD_WRITE_LOWER_64;
- toWrite = delta;
- remaining -= delta;
- } else {
- buff[0] = FLASH_CMD_WRITE_UPPER_64;
- toWrite = MEMORY_CHUNK;
- remaining -= MEMORY_CHUNK;
- }
- }
- } else {
- if ((address + remaining) < FLASH_ADDR_SWITCH_CMD) {
- buff[0] = FLASH_CMD_WRITE_LOWER_64;
- toWrite = remaining;
- remaining = 0;
- } else {
- if (address < FLASH_ADDR_SWITCH_CMD) {
- delta = FLASH_ADDR_SWITCH_CMD - address;
- buff[0] = FLASH_CMD_WRITE_LOWER_64;
- toWrite = delta;
- remaining -= delta;
- } else {
- buff[0] = FLASH_CMD_WRITE_UPPER_64;
- toWrite = remaining;
- remaining = 0;
- }
- }
- }
- buff[1] = (u8) ((address & 0x0000FF00) >> 8);
- buff[2] = (u8) (address & 0x000000FF);
- memcpy(buff + 3, data, toWrite);
- //logError(0,
- //"%s Command = %02X , address = %02X %02X, bytes = %d\n",
- //tag, buff[0], buff[1], buff[2], toWrite);
- if (fts_writeCmd(buff, 3 + toWrite) < 0) {
- logError(1, "%s %s: ERROR %02X\n",
- tag, __func__, ERROR_I2C_W);
- kfree(buff);
- return ERROR_I2C_W;
- }
- address += toWrite;
- data += toWrite;
- }
- kfree(buff);
- return OK;
- }
- int flash_burn(Firmware *fw, int force_burn, int keep_cx)
- {
- u8 cmd;
- int res;
- if (!force_burn && (ftsInfo.u16_fwVer >= fw->fw_ver)
- && (ftsInfo.u16_cfgId >= fw->config_id)) {
- logError(0, "Firmware in the chip newer");
- logError(0, " or equal to the one to burn! ");
- logError(0, "%s %s:NO UPDATE ERROR %02X\n",
- tag, __func__, ERROR_FW_NO_UPDATE);
- return (ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED);
- }
- //programming procedure start
- logError(0, "%s Programming Procedure for flashing started:\n", tag);
- logError(0, "%s 1) SYSTEM RESET:\n", tag);
- res = fts_system_reset();
- if (res < 0) {
- logError(1, "%s system reset FAILED!\n", tag);
- //if there is no firmware i will not
- //get the controller ready event and
- //there will be a timeout but i can
- //keep going, but if there is
- //an I2C error i have to exit
- if (res != (ERROR_SYSTEM_RESET_FAIL | ERROR_TIMEOUT))
- return (res | ERROR_FLASH_BURN_FAILED);
- } else
- logError(0, "%s system reset COMPLETED!\n\n", tag);
- logError(0, "%s 2) FLASH UNLOCK:\n", tag);
- res = flash_unlock();
- if (res < 0) {
- logError(1, "%s flash unlock FAILED! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s flash unlock COMPLETED!\n\n", tag);
- //Write the lower part of the Program RAM
- logError(0, "%s 3) PREPARING DATA FOR FLASH BURN:\n", tag);
- res = fillMemory(FLASH_ADDR_CODE, fw->data, fw->data_size);
- if (res < 0) {
- logError(1, "%s Error During filling the memory!%02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s Data copy COMPLETED!\n\n", tag);
- logError(0, "%s 4) ERASE FLASH:\n", tag);
- res = wait_for_flash_ready();
- if (res < 0) {
- logError(1, "%s Flash not ready! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s Command erase ...\n", tag);
- cmd = FLASH_CMD_ERASE;
- if (fts_writeCmd(&cmd, 1) < 0) {
- logError(1, "%s Error during erasing flash! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (ERROR_I2C_W | ERROR_FLASH_BURN_FAILED);
- }
- res = wait_for_flash_ready();
- if (res < 0) {
- logError(1, "%s Flash not ready 2! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s Flash erase COMPLETED!\n\n", tag);
- logError(0, "%s 5) BURN FLASH:\n", tag);
- logError(0, "%s Command burn ...\n", tag);
- cmd = FLASH_CMD_BURN;
- if (fts_writeCmd(&cmd, 1) < 0) {
- logError(1, "%s Error during burning data! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (ERROR_I2C_W | ERROR_FLASH_BURN_FAILED);
- }
- res = wait_for_flash_ready();
- if (res < 0) {
- logError(1, "%s Flash not ready! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s Flash burn COMPLETED!\n\n", tag);
- logError(0, "%s 6) SYSTEM RESET:\n", tag);
- res = fts_system_reset();
- if (res < 0) {
- logError(1, "%s system reset FAILED! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s system reset COMPLETED!\n\n", tag);
- logError(0, "%s 7) FINAL CHECK:\n", tag);
- res = readChipInfo(0);
- if (res < 0) {
- logError(1, "%s %s:Unable to retrieve Chip INFO!%02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- if ((ftsInfo.u16_fwVer != fw->fw_ver)
- && (ftsInfo.u16_cfgId != fw->config_id)) {
- logError(1, "Firmware in the chip different");
- logError(1, " from the one that was burn!");
- logError(1, "%s fw: %x != %x , conf: %x != %x\n",
- tag, ftsInfo.u16_fwVer,
- fw->fw_ver,
- ftsInfo.u16_cfgId,
- fw->config_id);
- return ERROR_FLASH_BURN_FAILED;
- }
- logError(0, "%s Final check OK! fw: %02X, conf: %02X\n",
- tag, ftsInfo.u16_fwVer, ftsInfo.u16_cfgId);
- return OK;
- }
- #else
- int wait_for_flash_ready(u8 type)
- {
- u8 cmd[2] = {FLASH_CMD_READ_REGISTER, type};
- u8 readData = 0;
- int i, res = -1;
- logError(0, "%s Waiting for flash ready ...\n", tag);
- for (i = 0; i < FLASH_RETRY_COUNT && res != 0; i++) {
- if (fts_readCmd(cmd, sizeof(cmd), &readData, 1) < 0) {
- logError(1, "%s %s: ERROR % 02X\n",
- tag, __func__, ERROR_I2C_R);
- } else {
- res = readData & 0x80;
- //logError(0, "%s flash status = %d\n", tag, res);
- }
- msleep(FLASH_WAIT_BEFORE_RETRY);
- }
- if (i == FLASH_RETRY_COUNT && res != 0) {
- logError(1, "%s Wait for flash TIMEOUT! ERROR %02X\n",
- tag, ERROR_TIMEOUT);
- return ERROR_TIMEOUT;
- }
- logError(0, "%s Flash READY!\n", tag);
- return OK;
- }
- int fts_warm_boot(void)
- {
- //write the command to perform the warm boot
- u8 cmd[4] = {FTS_CMD_HW_REG_W, 0x00, 0x00, WARM_BOOT_VALUE};
- u16ToU8_be(ADDR_WARM_BOOT, &cmd[1]);
- logError(0, "%s Command warm boot ...\n", tag);
- if (fts_writeCmd(cmd, sizeof(cmd)) < 0) {
- logError(1, "%s flash_unlock: ERROR % 02X\n", tag, ERROR_I2C_W);
- return ERROR_I2C_W;
- }
- logError(0, "%s Warm boot DONE!\n", tag);
- return OK;
- }
- int parseBinFile(u8 *data, int fw_size,
- struct Firmware *fwData, int keep_cx)
- {
- int dimension, index = 0;
- u32 temp;
- int res, i;
- //the file should contain at least the header plus the content_crc
- if (fw_size < FW_HEADER_SIZE+FW_BYTES_ALIGN || data == NULL) {
- logError(1, "%s %s:Read only %d instead of %d...ERROR %02X\n",
- tag, __func__, fw_size,
- FW_HEADER_SIZE + FW_BYTES_ALIGN,
- ERROR_FILE_PARSE);
- res = ERROR_FILE_PARSE;
- goto END;
- } else {
- //start parsing of bytes
- u8ToU32(&data[index], &temp);
- if (temp != FW_HEADER_SIGNATURE) {
- logError(1, "%s %s:Wrong Signature %08X...ERROR %02X\n",
- tag, __func__, temp, ERROR_FILE_PARSE);
- res = ERROR_FILE_PARSE;
- goto END;
- }
- logError(0, "%s %s: Fw Signature OK!\n", tag, __func__);
- index += FW_BYTES_ALIGN;
- u8ToU32(&data[index], &temp);
- if (temp != FW_FTB_VER) {
- logError(1, "%s %s:Wrong ftb_version %08X.ERROR %02X\n",
- tag, __func__, temp, ERROR_FILE_PARSE);
- res = ERROR_FILE_PARSE;
- goto END;
- }
- logError(0, "%s %s:ftb_version OK!\n", __func__, tag);
- index += FW_BYTES_ALIGN;
- if (data[index] != DCHIP_ID_0 || data[index+1] != DCHIP_ID_1) {
- logError(1, "%s %s:Wrong target %02X != %02X ",
- tag, __func__, data[index]);
- logError(1, "%%02X != %02X:%08X\n",
- DCHIP_ID_0, data[index+1],
- DCHIP_ID_1, ERROR_FILE_PARSE);
- res = ERROR_FILE_PARSE;
- goto END;
- }
- index += FW_BYTES_ALIGN;
- u8ToU32(&data[index], &temp);
- logError(0, "%s %s: Fw ID = %08X\n", tag, __func__, temp);
- index += FW_BYTES_ALIGN;
- u8ToU32(&data[index], &temp);
- fwData->fw_ver = temp;
- logError(0, "%s %s:FILE Fw Version = %04X\n",
- tag, __func__, fwData->fw_ver);
- index += FW_BYTES_ALIGN;
- u8ToU32(&data[index], &temp);
- fwData->config_id = temp;
- logError(0, "%s %s:FILE Config ID = %04X\n",
- tag, __func__, fwData->config_id);
- index += FW_BYTES_ALIGN;
- u8ToU32(&data[index], &temp);
- logError(0, "%s %s:Config Version = %08X\n",
- tag, __func__, temp);
- //skip reserved data
- index += FW_BYTES_ALIGN * 2;
- index += FW_BYTES_ALIGN;
- logError(0, "%s %s:File External Release = ",
- tag, __func__);
- for (i = 0; i < EXTERNAL_RELEASE_INFO_SIZE; i++) {
- fwData->externalRelease[i] = data[index++];
- logError(0, "%02X", fwData->externalRelease[i]);
- }
- logError(0, "\n");
- //index += FW_BYTES_ALIGN;
- u8ToU32(&data[index], &temp);
- fwData->sec0_size = temp;
- logError(0, "%s %s:sec0_size = %08X (%d bytes)\n",
- tag, __func__, fwData->sec0_size, fwData->sec0_size);
- index += FW_BYTES_ALIGN;
- u8ToU32(&data[index], &temp);
- fwData->sec1_size = temp;
- logError(0, "%s %s:sec1_size = %08X (%d bytes)\n",
- tag, __func__, fwData->sec1_size, fwData->sec1_size);
- index += FW_BYTES_ALIGN;
- u8ToU32(&data[index], &temp);
- fwData->sec2_size = temp;
- logError(0, "%s %s:sec2_size = %08X (%d bytes)\n",
- tag, __func__, fwData->sec2_size, fwData->sec2_size);
- index += FW_BYTES_ALIGN;
- u8ToU32(&data[index], &temp);
- fwData->sec3_size = temp;
- logError(0, "%s %s:sec3_size = %08X (%d bytes)\n",
- tag, __func__, fwData->sec3_size, fwData->sec3_size);
- //skip header crc
- index += FW_BYTES_ALIGN;
- if (!keep_cx) {
- dimension = fwData->sec0_size + fwData->sec1_size
- + fwData->sec2_size + fwData->sec3_size;
- temp = fw_size;
- } else {
- //sec2 may contain cx data (future implementation)
- //sec3 atm not used
- dimension = fwData->sec0_size + fwData->sec1_size;
- temp = fw_size - fwData->sec2_size - fwData->sec3_size;
- fwData->sec2_size = 0;
- fwData->sec3_size = 0;
- }
- if (dimension + FW_HEADER_SIZE + FW_BYTES_ALIGN != temp) {
- logError(1, "%s %s:Read only %d instead of %d...",
- tag, __func__, fw_size,
- dimension + FW_HEADER_SIZE + FW_BYTES_ALIGN);
- logError(1, "ERROR %02X\n", ERROR_FILE_PARSE);
- res = ERROR_FILE_PARSE;
- goto END;
- }
- fwData->data = (u8 *)kmalloc_array(dimension, sizeof(u8),
- GFP_KERNEL);
- if (fwData->data == NULL) {
- logError(1, "%s %s: ERROR %02X\n",
- tag, __func__, ERROR_ALLOC);
- res = ERROR_ALLOC;
- goto END;
- }
- index += FW_BYTES_ALIGN;
- memcpy(fwData->data, &data[index], dimension);
- fwData->data_size = dimension;
- logError(0, "%s READ FW DONE %d bytes!\n",
- tag, fwData->data_size);
- res = OK;
- goto END;
- }
- END:
- kfree(data);
- return res;
- }
- int flash_unlock(void)
- {
- //write the command to perform the unlock
- u8 cmd[3] = {FLASH_CMD_UNLOCK,
- FLASH_UNLOCK_CODE0, FLASH_UNLOCK_CODE1};
- logError(0, "%s Command unlock ...\n", tag);
- if (fts_writeCmd(cmd, sizeof(cmd)) < 0) {
- logError(1, "%s %s: ERROR % 02X\n", tag, __func__, ERROR_I2C_W);
- return ERROR_I2C_W;
- }
- //mdelay(FLASH_WAIT_TIME);
- logError(0, "%s Unlock flash DONE!\n", tag);
- return OK;
- }
- int flash_erase_unlock(void)
- {
- //write the command to perform
- //the unlock for erasing the flash
- u8 cmd[3] = {FLASH_CMD_WRITE_REGISTER, FLASH_ERASE_UNLOCK_CODE0,
- FLASH_ERASE_UNLOCK_CODE1};
- logError(0, "%s Try to erase unlock flash...\n", tag);
- logError(0, "%s Command erase unlock ...\n", tag);
- if (fts_writeCmd(cmd, sizeof(cmd)) < 0) {
- logError(1, "%s %s:ERROR % 02X\n", tag, __func__, ERROR_I2C_W);
- return ERROR_I2C_W;
- }
- logError(0, "%s Erase Unlock flash DONE!\n", tag);
- return OK;
- }
- int flash_full_erase(void)
- {
- int status;
- //write the command to erase the flash
- u8 cmd[3] = {FLASH_CMD_WRITE_REGISTER, FLASH_ERASE_CODE0,
- FLASH_ERASE_CODE1};
- logError(0, "%s Command full erase sent...\n",
- tag);
- if (fts_writeCmd(cmd, sizeof(cmd)) < 0) {
- logError(1, "%s %s:ERROR % 02X\n", tag, __func__, ERROR_I2C_W);
- return ERROR_I2C_W;
- }
- status = wait_for_flash_ready(FLASH_ERASE_CODE0);
- if (status != OK) {
- logError(1, "%s %s:ERROR % 02X\n",
- tag, __func__, ERROR_FLASH_NOT_READY);
- //Flash not ready within the chosen time,
- //better exit!
- return (status | ERROR_FLASH_NOT_READY);
- }
- logError(0, "%s Full Erase flash DONE!\n", tag);
- return OK;
- }
- int flash_erase_page_by_page(int keep_cx)
- {
- u8 status, i = 0;
- //write the command to erase the flash
- u8 cmd[4] = {FLASH_CMD_WRITE_REGISTER, FLASH_ERASE_CODE0, 0x00, 0x00};
- for (i = 0; i < FLASH_NUM_PAGE; i++) {
- if (i >= FLASH_CX_PAGE_START && i <= FLASH_CX_PAGE_END
- && keep_cx == 1) {
- logError(0, "%s Skipping erase page %d!\n", tag, i);
- continue;
- }
- cmd[2] = (0x3F & i) | FLASH_ERASE_START;
- logError(0, "Command erase page %d sent", i);
- logError(0, "%s:%02X %02X %02X %02X\n",
- tag, i, cmd[0], cmd[1], cmd[2], cmd[3]);
- if (fts_writeCmd(cmd, sizeof(cmd)) < 0) {
- logError(1,
- "%s %s:ERROR % 08X\n",
- tag, __func__, ERROR_I2C_W);
- return ERROR_I2C_W;
- }
- status = wait_for_flash_ready(FLASH_ERASE_CODE0);
- if (status != OK) {
- logError(1, "%s %s:ERROR % 08X\n",
- tag, __func__, ERROR_FLASH_NOT_READY);
- //Flash not ready within the chosen time,
- //better exit!
- return (status | ERROR_FLASH_NOT_READY);
- }
- }
- logError(0, "%s Erase flash page by page DONE!\n", tag);
- return OK;
- }
- int start_flash_dma(void)
- {
- int status;
- //write the command to erase the flash
- u8 cmd[3] = {FLASH_CMD_WRITE_REGISTER, FLASH_DMA_CODE0,
- FLASH_DMA_CODE1};
- logError(0, "%s Command flash DMA ...\n", tag);
- if (fts_writeCmd(cmd, sizeof(cmd)) < 0) {
- logError(1, "%s %s: ERROR % 02X\n",
- tag, __func__, ERROR_I2C_W);
- return ERROR_I2C_W;
- }
- status = wait_for_flash_ready(FLASH_DMA_CODE0);
- if (status != OK) {
- logError(1, "%s %s: ERROR % 02X\n",
- tag, __func__, ERROR_FLASH_NOT_READY);
- //Flash not ready within the chosen time, better exit!
- return (status | ERROR_FLASH_NOT_READY);
- }
- logError(0, "%s flash DMA DONE!\n", tag);
- return OK;
- }
- int fillFlash(u32 address, u8 *data, int size)
- {
- int remaining = size;
- int toWrite = 0;
- int byteBlock = 0;
- int wheel = 0;
- u32 addr = 0;
- int res;
- int delta;
- u8 *buff = NULL;
- u8 buff2[9] = {0};
- buff = (u8 *)kmalloc_array((DMA_CHUNK + 3), sizeof(u8), GFP_KERNEL);
- if (buff == NULL) {
- logError(1, "%s %s: ERROR %02X\n", tag, __func__, ERROR_ALLOC);
- return ERROR_ALLOC;
- }
- while (remaining > 0) {
- byteBlock = 0;
- addr = 0;
- while (byteBlock < FLASH_CHUNK && remaining > 0) {
- buff[0] = FLASH_CMD_WRITE_64K;
- if (remaining >= DMA_CHUNK) {
- if ((byteBlock + DMA_CHUNK) <= FLASH_CHUNK) {
- //logError(1, "%s fillFlash:1\n", tag);
- toWrite = DMA_CHUNK;
- remaining -= DMA_CHUNK;
- byteBlock += DMA_CHUNK;
- } else {
- //logError(1, "%s fillFlash:2\n", tag);
- delta = FLASH_CHUNK - byteBlock;
- toWrite = delta;
- remaining -= delta;
- byteBlock += delta;
- }
- } else {
- if ((byteBlock + remaining) <= FLASH_CHUNK) {
- //logError(1, "%s fillFlash:3\n", tag);
- toWrite = remaining;
- byteBlock += remaining;
- remaining = 0;
- } else {
- //logError(1, "%s fillFlash:4\n", tag);
- delta = FLASH_CHUNK - byteBlock;
- toWrite = delta;
- remaining -= delta;
- byteBlock += delta;
- }
- }
- buff[1] = (u8) ((addr & 0x0000FF00) >> 8);
- buff[2] = (u8) (addr & 0x000000FF);
- memcpy(&buff[3], data, toWrite);
- //logError(0,
- //"%s Command = %02X, address = %02X %02X,
- //bytes = %d, data = %02X %02X, %02X %02X\n",
- //tag, buff[0], buff[1], buff[2], toWrite,
- //buff[3], buff[4], buff[3 + toWrite-2],
- //buff[3 + toWrite-1]);
- if (fts_writeCmd(buff, 3 + toWrite) < 0) {
- logError(1, "%s %s: ERROR %02X\n",
- tag, __func__, ERROR_I2C_W);
- kfree(buff);
- return ERROR_I2C_W;
- }
- addr += toWrite;
- data += toWrite;
- }
- //configuring the DMA
- byteBlock = byteBlock / 4 - 1;
- buff2[0] = FLASH_CMD_WRITE_REGISTER;
- buff2[1] = FLASH_DMA_CONFIG;
- buff2[2] = 0x00;
- buff2[3] = 0x00;
- addr = address + ((wheel * FLASH_CHUNK)/4);
- buff2[4] = (u8) ((addr & 0x000000FF));
- buff2[5] = (u8) ((addr & 0x0000FF00) >> 8);
- buff2[6] = (u8) (byteBlock & 0x000000FF);
- buff2[7] = (u8) ((byteBlock & 0x0000FF00) >> 8);
- buff2[8] = 0x00;
- logError(0, "%s:Command:%02X, address:%02X %02X, ",
- tag, buff2[0], buff2[5], buff2[4]);
- logError(0, "words:%02X %02X\n", buff2[7], buff2[6]);
- if (fts_writeCmd(buff2, 9) < OK) {
- logError(1, "%s Error during filling Flash!:%02X\n",
- tag, ERROR_I2C_W);
- kfree(buff);
- return ERROR_I2C_W;
- }
- //mdelay(FLASH_WAIT_TIME);
- res = start_flash_dma();
- if (res < OK) {
- logError(1, "%s Error during flashing DMA!:%02X\n",
- tag, res);
- kfree(buff);
- return res;
- }
- wheel++;
- }
- kfree(buff);
- return OK;
- }
- int flash_burn(struct Firmware *fw, int force_burn, int keep_cx)
- {
- int res;
- if (!force_burn && (ftsInfo.u16_fwVer >= fw->fw_ver)
- && (ftsInfo.u16_cfgId >= fw->config_id)) {
- for (res = EXTERNAL_RELEASE_INFO_SIZE-1; res >= 0; res--) {
- if (fw->externalRelease[res] >
- ftsInfo.u8_extReleaseInfo[res])
- goto start;
- }
- logError(0, "Firmware in the chip newer or ");
- logError(0, "equal to the one to burn!");
- logError(0, "%s %s:NO UPDATE ERROR %02X\n",
- tag, __func__, ERROR_FW_NO_UPDATE);
- return (ERROR_FW_NO_UPDATE | ERROR_FLASH_BURN_FAILED);
- }
- //programming procedure start
- start:
- logError(0, "%s Programming Procedure for flashing started:\n\n", tag);
- logError(0, "%s 1) SYSTEM RESET:\n", tag);
- logError(0, "%s 2) WARM BOOT:\n", tag);
- res = fts_warm_boot();
- if (res < OK) {
- logError(1, "%s warm boot FAILED!\n", tag);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s warm boot COMPLETED!\n\n", tag);
- //mdelay(FLASH_WAIT_TIME);
- logError(0, "%s 3) FLASH UNLOCK:\n", tag);
- res = flash_unlock();
- if (res < OK) {
- logError(1, "%s flash unlock FAILED! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s flash unlock COMPLETED!\n\n", tag);
- //mdelay(200);
- logError(0, "%s 4) FLASH ERASE UNLOCK:\n", tag);
- res = flash_erase_unlock();
- if (res < 0) {
- logError(1, "%s flash unlock FAILED! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s flash unlock COMPLETED!\n\n", tag);
- //mdelay(FLASH_WAIT_TIME);
- logError(0, "%s 5) FLASH ERASE:\n", tag);
- if (keep_cx == 1)
- res = flash_erase_page_by_page(keep_cx);
- else
- res = flash_full_erase();
- if (res < 0) {
- logError(1, "%s flash erase FAILED! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s flash erase COMPLETED!\n\n", tag);
- //mdelay(FLASH_WAIT_TIME);
- logError(0, "%s 6) LOAD PROGRAM:\n", tag);
- res = fillFlash(FLASH_ADDR_CODE, (u8 *)(&fw->data[0]),
- fw->sec0_size);
- if (res < OK) {
- logError(1, "%s load program ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s load program DONE!\n", tag);
- logError(0, "%s 7) LOAD CONFIG:\n", tag);
- res = fillFlash(FLASH_ADDR_CONFIG,
- &(fw->data[fw->sec0_size]), fw->sec1_size);
- if (res < OK) {
- logError(1, "%s load config ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s load config DONE!\n", tag);
- logError(0, "%s Flash burn COMPLETED!\n\n", tag);
- logError(0, "%s 8) SYSTEM RESET:\n", tag);
- res = fts_system_reset();
- if (res < 0) {
- logError(1, "%s system reset FAILED! ERROR %02X\n",
- tag, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- logError(0, "%s system reset COMPLETED!\n\n", tag);
- logError(0, "%s 9) FINAL CHECK:\n", tag);
- res = readChipInfo(0);
- if (res < 0) {
- logError(1, "%s %s:Unable to retrieve Chip INFO!:%02X\n",
- tag, __func__, ERROR_FLASH_BURN_FAILED);
- return (res | ERROR_FLASH_BURN_FAILED);
- }
- if ((ftsInfo.u16_fwVer != fw->fw_ver)
- && (ftsInfo.u16_cfgId != fw->config_id)) {
- pr_err("Firmware is different from the old!\n");
- logError(1, "%s fw: %x != %x, conf: %x != %x\n",
- tag, ftsInfo.u16_fwVer, fw->fw_ver,
- ftsInfo.u16_cfgId, fw->config_id);
- return ERROR_FLASH_BURN_FAILED;
- }
- logError(0, "%s Final check OK! fw: %02X , conf: %02X\n",
- tag, ftsInfo.u16_fwVer, ftsInfo.u16_cfgId);
- return OK;
- }
- #endif
|