1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (C) 2010 - 2018 Novatek, Inc.
- *
- * $Revision: 47247 $
- * $Date: 2019-07-10 10:41:36 +0800 (Wed, 10 Jul 2019) $
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- */
- #if !defined(NVT_NT36XXX_SPI) /* NT36XXX I2C */
- #include <linux/firmware.h>
- #include "nt36xxx.h"
- #if BOOT_UPDATE_FIRMWARE
- #define SIZE_4KB 4096
- #define FLASH_SECTOR_SIZE SIZE_4KB
- #define SIZE_64KB 65536
- #define BLOCK_64KB_NUM 4
- #define FW_BIN_VER_OFFSET (fw_need_write_size - SIZE_4KB)
- #define FW_BIN_VER_BAR_OFFSET (FW_BIN_VER_OFFSET + 1)
- #define NVT_FLASH_END_FLAG_LEN 3
- #define NVT_FLASH_END_FLAG_ADDR (fw_need_write_size - NVT_FLASH_END_FLAG_LEN)
- const struct firmware *fw_entry = NULL;
- static size_t fw_need_write_size = 0;
- static int32_t nvt_get_fw_need_write_size(const struct firmware *fw_entry)
- {
- int32_t i = 0;
- int32_t total_sectors_to_check = 0;
- total_sectors_to_check = fw_entry->size / FLASH_SECTOR_SIZE;
- /* printk("total_sectors_to_check = %d\n", total_sectors_to_check); */
- for (i = total_sectors_to_check; i > 0; i--) {
- /* printk("current end flag address checked = 0x%X\n", i * FLASH_SECTOR_SIZE - NVT_FLASH_END_FLAG_LEN); */
- /* check if there is end flag "NVT" at the end of this sector */
- if ((memcmp((const char *)&fw_entry->data[i * FLASH_SECTOR_SIZE -
- NVT_FLASH_END_FLAG_LEN], "NVT", NVT_FLASH_END_FLAG_LEN) == 0) ||
- (memcmp((const char *)&fw_entry->data[i * FLASH_SECTOR_SIZE -
- NVT_FLASH_END_FLAG_LEN], "MOD", NVT_FLASH_END_FLAG_LEN) == 0)) {
- fw_need_write_size = i * FLASH_SECTOR_SIZE;
- NVT_LOG("fw_need_write_size = %zu(0x%zx)\n", fw_need_write_size, fw_need_write_size);
- return 0;
- }
- }
- NVT_ERR("end flag \"NVT\" not found!\n");
- return -1;
- }
- /*******************************************************
- Description:
- Novatek touchscreen request update firmware function.
- return:
- Executive outcomes. 0---succeed. -1,-22---failed.
- *******************************************************/
- int32_t update_firmware_request(char *filename)
- {
- int32_t ret = 0;
- if (NULL == filename) {
- return -1;
- }
- NVT_LOG("filename is %s\n", filename);
- ret = request_firmware(&fw_entry, filename, &ts->client->dev);
- if (ret) {
- NVT_ERR("firmware load failed, ret=%d\n", ret);
- return ret;
- }
- // check FW need to write size
- if (nvt_get_fw_need_write_size(fw_entry)) {
- NVT_ERR("get fw need to write size fail!\n");
- return -EINVAL;
- }
- // check if FW version add FW version bar equals 0xFF
- if (*(fw_entry->data + FW_BIN_VER_OFFSET) + *(fw_entry->data + FW_BIN_VER_BAR_OFFSET) != 0xFF) {
- NVT_ERR("bin file FW_VER + FW_VER_BAR should be 0xFF!\n");
- NVT_ERR("FW_VER=0x%02X, FW_VER_BAR=0x%02X\n", *(fw_entry->data+FW_BIN_VER_OFFSET), *(fw_entry->data+FW_BIN_VER_BAR_OFFSET));
- return -EINVAL;
- }
- return 0;
- }
- /*******************************************************
- Description:
- Novatek touchscreen release update firmware function.
- return:
- n.a.
- *******************************************************/
- void update_firmware_release(void)
- {
- if (fw_entry) {
- release_firmware(fw_entry);
- }
- fw_entry=NULL;
- }
- /*******************************************************
- Description:
- Novatek touchscreen check firmware version function.
- return:
- Executive outcomes. 0---need update. 1---need not
- update.
- *******************************************************/
- int32_t Check_FW_Ver(void)
- {
- uint8_t buf[16] = {0};
- int32_t ret = 0;
- //write i2c index to EVENT BUF ADDR
- ret = nvt_set_page(I2C_BLDR_Address, ts->mmap->EVENT_BUF_ADDR | EVENT_MAP_FWINFO);
- if (ret < 0) {
- NVT_ERR("i2c write error!(%d)\n", ret);
- return ret;
- }
- //read Firmware Version
- buf[0] = EVENT_MAP_FWINFO;
- buf[1] = 0x00;
- buf[2] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3);
- if (ret < 0) {
- NVT_ERR("i2c read error!(%d)\n", ret);
- return ret;
- }
- NVT_LOG("IC FW Ver = 0x%02X, FW Ver Bar = 0x%02X\n", buf[1], buf[2]);
- NVT_LOG("Bin FW Ver = 0x%02X, FW ver Bar = 0x%02X\n",
- fw_entry->data[FW_BIN_VER_OFFSET], fw_entry->data[FW_BIN_VER_BAR_OFFSET]);
- // check IC FW_VER + FW_VER_BAR equals 0xFF or not, need to update if not
- if ((buf[1] + buf[2]) != 0xFF) {
- NVT_ERR("IC FW_VER + FW_VER_BAR not equals to 0xFF!\n");
- return 0;
- }
- // compare IC and binary FW version
- if (buf[1] > fw_entry->data[FW_BIN_VER_OFFSET])
- return 1;
- else
- return 0;
- }
- /*******************************************************
- Description:
- Novatek touchscreen resume from deep power down function.
- return:
- Executive outcomes. 0---succeed. negative---failed.
- *******************************************************/
- int32_t Resume_PD(void)
- {
- uint8_t buf[8] = {0};
- int32_t ret = 0;
- int32_t retry = 0;
- // Resume Command
- buf[0] = 0x00;
- buf[1] = 0xAB;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Write Enable error!!(%d)\n", ret);
- return ret;
- }
- // Check 0xAA (Resume Command)
- retry = 0;
- while(1) {
- msleep(1);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Resume Command) error!!(%d)\n", ret);
- return ret;
- }
- if (buf[1] == 0xAA) {
- break;
- }
- retry++;
- if (unlikely(retry > 20)) {
- NVT_ERR("Check 0xAA (Resume Command) error!! status=0x%02X\n", buf[1]);
- return -1;
- }
- }
- msleep(10);
- NVT_LOG("Resume PD OK\n");
- return 0;
- }
- /*******************************************************
- Description:
- Novatek touchscreen check firmware checksum function.
- return:
- Executive outcomes. 0---checksum not match.
- 1---checksum match. -1--- checksum read failed.
- *******************************************************/
- int32_t Check_CheckSum(void)
- {
- uint8_t buf[64] = {0};
- uint32_t XDATA_Addr = ts->mmap->READ_FLASH_CHECKSUM_ADDR;
- int32_t ret = 0;
- int32_t i = 0;
- int32_t k = 0;
- uint16_t WR_Filechksum[BLOCK_64KB_NUM] = {0};
- uint16_t RD_Filechksum[BLOCK_64KB_NUM] = {0};
- size_t len_in_blk = 0;
- int32_t retry = 0;
- if (Resume_PD()) {
- NVT_ERR("Resume PD error!!\n");
- return -1;
- }
- for (i = 0; i < BLOCK_64KB_NUM; i++) {
- if (fw_need_write_size > (i * SIZE_64KB)) {
- // Calculate WR_Filechksum of each 64KB block
- len_in_blk = min(fw_need_write_size - i * SIZE_64KB, (size_t)SIZE_64KB);
- WR_Filechksum[i] = i + 0x00 + 0x00 + (((len_in_blk - 1) >> 8) & 0xFF) + ((len_in_blk - 1) & 0xFF);
- for (k = 0; k < len_in_blk; k++) {
- WR_Filechksum[i] += fw_entry->data[k + i * SIZE_64KB];
- }
- WR_Filechksum[i] = 65535 - WR_Filechksum[i] + 1;
- // Fast Read Command
- buf[0] = 0x00;
- buf[1] = 0x07;
- buf[2] = i;
- buf[3] = 0x00;
- buf[4] = 0x00;
- buf[5] = ((len_in_blk - 1) >> 8) & 0xFF;
- buf[6] = (len_in_blk - 1) & 0xFF;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7);
- if (ret < 0) {
- NVT_ERR("Fast Read Command error!!(%d)\n", ret);
- return ret;
- }
- // Check 0xAA (Fast Read Command)
- retry = 0;
- while (1) {
- msleep(80);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Fast Read Command) error!!(%d)\n", ret);
- return ret;
- }
- if (buf[1] == 0xAA) {
- break;
- }
- retry++;
- if (unlikely(retry > 5)) {
- NVT_ERR("Check 0xAA (Fast Read Command) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
- return -1;
- }
- }
- // Read Checksum (write addr high byte & middle byte)
- ret = nvt_set_page(I2C_BLDR_Address, XDATA_Addr);
- if (ret < 0) {
- NVT_ERR("Read Checksum (write addr high byte & middle byte) error!!(%d)\n", ret);
- return ret;
- }
- // Read Checksum
- buf[0] = (XDATA_Addr) & 0xFF;
- buf[1] = 0x00;
- buf[2] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3);
- if (ret < 0) {
- NVT_ERR("Read Checksum error!!(%d)\n", ret);
- return ret;
- }
- RD_Filechksum[i] = (uint16_t)((buf[2] << 8) | buf[1]);
- if (WR_Filechksum[i] != RD_Filechksum[i]) {
- NVT_ERR("RD_Filechksum[%d]=0x%04X, WR_Filechksum[%d]=0x%04X\n", i, RD_Filechksum[i], i, WR_Filechksum[i]);
- NVT_ERR("firmware checksum not match!!\n");
- return 0;
- }
- }
- }
- NVT_LOG("firmware checksum match\n");
- return 1;
- }
- /*******************************************************
- Description:
- Novatek touchscreen initial bootloader and flash
- block function.
- return:
- Executive outcomes. 0---succeed. negative---failed.
- *******************************************************/
- int32_t Init_BootLoader(void)
- {
- uint8_t buf[64] = {0};
- int32_t ret = 0;
- int32_t retry = 0;
- // SW Reset & Idle
- nvt_sw_reset_idle();
- // Initiate Flash Block
- buf[0] = 0x00;
- buf[1] = 0x00;
- buf[2] = I2C_FW_Address;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 3);
- if (ret < 0) {
- NVT_ERR("Inittial Flash Block error!!(%d)\n", ret);
- return ret;
- }
- // Check 0xAA (Initiate Flash Block)
- retry = 0;
- while(1) {
- msleep(1);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Inittial Flash Block) error!!(%d)\n", ret);
- return ret;
- }
- if (buf[1] == 0xAA) {
- break;
- }
- retry++;
- if (unlikely(retry > 20)) {
- NVT_ERR("Check 0xAA (Inittial Flash Block) error!! status=0x%02X\n", buf[1]);
- return -1;
- }
- }
- NVT_LOG("Init OK \n");
- msleep(20);
- return 0;
- }
- /*******************************************************
- Description:
- Novatek touchscreen erase flash sectors function.
- return:
- Executive outcomes. 0---succeed. negative---failed.
- *******************************************************/
- int32_t Erase_Flash(void)
- {
- uint8_t buf[64] = {0};
- int32_t ret = 0;
- int32_t count = 0;
- int32_t i = 0;
- int32_t Flash_Address = 0;
- int32_t retry = 0;
- // Write Enable
- buf[0] = 0x00;
- buf[1] = 0x06;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Write Enable (for Write Status Register) error!!(%d)\n", ret);
- return ret;
- }
- // Check 0xAA (Write Enable)
- retry = 0;
- while (1) {
- msleep(1);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Write Enable for Write Status Register) error!!(%d)\n", ret);
- return ret;
- }
- if (buf[1] == 0xAA) {
- break;
- }
- retry++;
- if (unlikely(retry > 20)) {
- NVT_ERR("Check 0xAA (Write Enable for Write Status Register) error!! status=0x%02X\n", buf[1]);
- return -1;
- }
- }
- // Write Status Register
- buf[0] = 0x00;
- buf[1] = 0x01;
- buf[2] = 0x00;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 3);
- if (ret < 0) {
- NVT_ERR("Write Status Register error!!(%d)\n", ret);
- return ret;
- }
- // Check 0xAA (Write Status Register)
- retry = 0;
- while (1) {
- msleep(1);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Write Status Register) error!!(%d)\n", ret);
- return ret;
- }
- if (buf[1] == 0xAA) {
- break;
- }
- retry++;
- if (unlikely(retry > 20)) {
- NVT_ERR("Check 0xAA (Write Status Register) error!! status=0x%02X\n", buf[1]);
- return -1;
- }
- }
- // Read Status
- retry = 0;
- while (1) {
- msleep(5);
- buf[0] = 0x00;
- buf[1] = 0x05;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Read Status (for Write Status Register) error!!(%d)\n", ret);
- return ret;
- }
- // Check 0xAA (Read Status)
- buf[0] = 0x00;
- buf[1] = 0x00;
- buf[2] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Read Status for Write Status Register) error!!(%d)\n", ret);
- return ret;
- }
- if ((buf[1] == 0xAA) && (buf[2] == 0x00)) {
- break;
- }
- retry++;
- if (unlikely(retry > 100)) {
- NVT_ERR("Check 0xAA (Read Status for Write Status Register) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry);
- return -1;
- }
- }
- if (fw_need_write_size % FLASH_SECTOR_SIZE)
- count = fw_need_write_size / FLASH_SECTOR_SIZE + 1;
- else
- count = fw_need_write_size / FLASH_SECTOR_SIZE;
- for(i = 0; i < count; i++) {
- // Write Enable
- buf[0] = 0x00;
- buf[1] = 0x06;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Write Enable error!!(%d,%d)\n", ret, i);
- return ret;
- }
- // Check 0xAA (Write Enable)
- retry = 0;
- while (1) {
- msleep(1);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Write Enable) error!!(%d,%d)\n", ret, i);
- return ret;
- }
- if (buf[1] == 0xAA) {
- break;
- }
- retry++;
- if (unlikely(retry > 20)) {
- NVT_ERR("Check 0xAA (Write Enable) error!! status=0x%02X\n", buf[1]);
- return -1;
- }
- }
- Flash_Address = i * FLASH_SECTOR_SIZE;
- // Sector Erase
- buf[0] = 0x00;
- buf[1] = 0x20; // Command : Sector Erase
- buf[2] = ((Flash_Address >> 16) & 0xFF);
- buf[3] = ((Flash_Address >> 8) & 0xFF);
- buf[4] = (Flash_Address & 0xFF);
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 5);
- if (ret < 0) {
- NVT_ERR("Sector Erase error!!(%d,%d)\n", ret, i);
- return ret;
- }
- // Check 0xAA (Sector Erase)
- retry = 0;
- while (1) {
- msleep(1);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Sector Erase) error!!(%d,%d)\n", ret, i);
- return ret;
- }
- if (buf[1] == 0xAA) {
- break;
- }
- retry++;
- if (unlikely(retry > 20)) {
- NVT_ERR("Check 0xAA (Sector Erase) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
- return -1;
- }
- }
- // Read Status
- retry = 0;
- while (1) {
- msleep(5);
- buf[0] = 0x00;
- buf[1] = 0x05;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Read Status error!!(%d,%d)\n", ret, i);
- return ret;
- }
- // Check 0xAA (Read Status)
- buf[0] = 0x00;
- buf[1] = 0x00;
- buf[2] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Read Status) error!!(%d,%d)\n", ret, i);
- return ret;
- }
- if ((buf[1] == 0xAA) && (buf[2] == 0x00)) {
- break;
- }
- retry++;
- if (unlikely(retry > 100)) {
- NVT_ERR("Check 0xAA (Read Status) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry);
- return -1;
- }
- }
- }
- NVT_LOG("Erase OK \n");
- return 0;
- }
- /*******************************************************
- Description:
- Novatek touchscreen write flash sectors function.
- return:
- Executive outcomes. 0---succeed. negative---failed.
- *******************************************************/
- int32_t Write_Flash(void)
- {
- uint8_t buf[64] = {0};
- uint32_t XDATA_Addr = ts->mmap->RW_FLASH_DATA_ADDR;
- uint32_t Flash_Address = 0;
- int32_t i = 0, j = 0, k = 0;
- uint8_t tmpvalue = 0;
- int32_t count = 0;
- int32_t ret = 0;
- int32_t retry = 0;
- int32_t percent = 0;
- int32_t previous_percent = -1;
- // change I2C buffer index
- ret = nvt_set_page(I2C_BLDR_Address, XDATA_Addr);
- if (ret < 0) {
- NVT_ERR("change I2C buffer index error!!(%d)\n", ret);
- return ret;
- }
- if (fw_need_write_size % 256)
- count = fw_need_write_size / 256 + 1;
- else
- count = fw_need_write_size / 256;
- for (i = 0; i < count; i++) {
- Flash_Address = i * 256;
- // Write Enable
- buf[0] = 0x00;
- buf[1] = 0x06;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Write Enable error!!(%d)\n", ret);
- return ret;
- }
- // Check 0xAA (Write Enable)
- retry = 0;
- while (1) {
- udelay(100);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Write Enable) error!!(%d,%d)\n", ret, i);
- return ret;
- }
- if (buf[1] == 0xAA) {
- break;
- }
- retry++;
- if (unlikely(retry > 20)) {
- NVT_ERR("Check 0xAA (Write Enable) error!! status=0x%02X\n", buf[1]);
- return -1;
- }
- }
- // Write Page : 256 bytes
- for (j = 0; j < min(fw_need_write_size - i * 256, (size_t)256); j += 32) {
- buf[0] = (XDATA_Addr + j) & 0xFF;
- for (k = 0; k < 32; k++) {
- buf[1 + k] = fw_entry->data[Flash_Address + j + k];
- }
- ret = CTP_I2C_WRITE(ts->client, I2C_BLDR_Address, buf, 33);
- if (ret < 0) {
- NVT_ERR("Write Page error!!(%d), j=%d\n", ret, j);
- return ret;
- }
- }
- if (fw_need_write_size - Flash_Address >= 256)
- tmpvalue=(Flash_Address >> 16) + ((Flash_Address >> 8) & 0xFF) + (Flash_Address & 0xFF) + 0x00 + (255);
- else
- tmpvalue=(Flash_Address >> 16) + ((Flash_Address >> 8) & 0xFF) + (Flash_Address & 0xFF) + 0x00 + (fw_need_write_size - Flash_Address - 1);
- for (k = 0; k < min(fw_need_write_size - Flash_Address, (size_t)256); k++)
- tmpvalue += fw_entry->data[Flash_Address + k];
- tmpvalue = 255 - tmpvalue + 1;
- // Page Program
- buf[0] = 0x00;
- buf[1] = 0x02;
- buf[2] = ((Flash_Address >> 16) & 0xFF);
- buf[3] = ((Flash_Address >> 8) & 0xFF);
- buf[4] = (Flash_Address & 0xFF);
- buf[5] = 0x00;
- buf[6] = min(fw_need_write_size - Flash_Address, (size_t)256) - 1;
- buf[7] = tmpvalue;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 8);
- if (ret < 0) {
- NVT_ERR("Page Program error!!(%d), i=%d\n", ret, i);
- return ret;
- }
- // Check 0xAA (Page Program)
- retry = 0;
- while (1) {
- msleep(1);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Page Program error!!(%d)\n", ret);
- return ret;
- }
- if (buf[1] == 0xAA || buf[1] == 0xEA) {
- break;
- }
- retry++;
- if (unlikely(retry > 20)) {
- NVT_ERR("Check 0xAA (Page Program) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
- return -1;
- }
- }
- if (buf[1] == 0xEA) {
- NVT_ERR("Page Program error!! i=%d\n", i);
- return -3;
- }
- // Read Status
- retry = 0;
- while (1) {
- msleep(5);
- buf[0] = 0x00;
- buf[1] = 0x05;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Read Status error!!(%d)\n", ret);
- return ret;
- }
- // Check 0xAA (Read Status)
- buf[0] = 0x00;
- buf[1] = 0x00;
- buf[2] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 3);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Read Status) error!!(%d)\n", ret);
- return ret;
- }
- if (((buf[1] == 0xAA) && (buf[2] == 0x00)) || (buf[1] == 0xEA)) {
- break;
- }
- retry++;
- if (unlikely(retry > 100)) {
- NVT_ERR("Check 0xAA (Read Status) failed, buf[1]=0x%02X, buf[2]=0x%02X, retry=%d\n", buf[1], buf[2], retry);
- return -1;
- }
- }
- if (buf[1] == 0xEA) {
- NVT_ERR("Page Program error!! i=%d\n", i);
- return -4;
- }
- percent = ((i + 1) * 100) / count;
- if (((percent % 10) == 0) && (percent != previous_percent)) {
- NVT_LOG("Programming...%2d%%\n", percent);
- previous_percent = percent;
- }
- }
- NVT_LOG("Program OK \n");
- return 0;
- }
- /*******************************************************
- Description:
- Novatek touchscreen verify checksum of written
- flash function.
- return:
- Executive outcomes. 0---succeed. negative---failed.
- *******************************************************/
- int32_t Verify_Flash(void)
- {
- uint8_t buf[64] = {0};
- uint32_t XDATA_Addr = ts->mmap->READ_FLASH_CHECKSUM_ADDR;
- int32_t ret = 0;
- int32_t i = 0;
- int32_t k = 0;
- uint16_t WR_Filechksum[BLOCK_64KB_NUM] = {0};
- uint16_t RD_Filechksum[BLOCK_64KB_NUM] = {0};
- size_t len_in_blk = 0;
- int32_t retry = 0;
- for (i = 0; i < BLOCK_64KB_NUM; i++) {
- if (fw_need_write_size > (i * SIZE_64KB)) {
- // Calculate WR_Filechksum of each 64KB block
- len_in_blk = min(fw_need_write_size - i * SIZE_64KB, (size_t)SIZE_64KB);
- WR_Filechksum[i] = i + 0x00 + 0x00 + (((len_in_blk - 1) >> 8) & 0xFF) + ((len_in_blk - 1) & 0xFF);
- for (k = 0; k < len_in_blk; k++) {
- WR_Filechksum[i] += fw_entry->data[k + i * SIZE_64KB];
- }
- WR_Filechksum[i] = 65535 - WR_Filechksum[i] + 1;
- // Fast Read Command
- buf[0] = 0x00;
- buf[1] = 0x07;
- buf[2] = i;
- buf[3] = 0x00;
- buf[4] = 0x00;
- buf[5] = ((len_in_blk - 1) >> 8) & 0xFF;
- buf[6] = (len_in_blk - 1) & 0xFF;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7);
- if (ret < 0) {
- NVT_ERR("Fast Read Command error!!(%d)\n", ret);
- return ret;
- }
- // Check 0xAA (Fast Read Command)
- retry = 0;
- while (1) {
- msleep(80);
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Fast Read Command) error!!(%d)\n", ret);
- return ret;
- }
- if (buf[1] == 0xAA) {
- break;
- }
- retry++;
- if (unlikely(retry > 5)) {
- NVT_ERR("Check 0xAA (Fast Read Command) failed, buf[1]=0x%02X, retry=%d\n", buf[1], retry);
- return -1;
- }
- }
- // Read Checksum (write addr high byte & middle byte)
- ret = nvt_set_page(I2C_BLDR_Address, XDATA_Addr);
- if (ret < 0) {
- NVT_ERR("Read Checksum (write addr high byte & middle byte) error!!(%d)\n", ret);
- return ret;
- }
- // Read Checksum
- buf[0] = (XDATA_Addr) & 0xFF;
- buf[1] = 0x00;
- buf[2] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 3);
- if (ret < 0) {
- NVT_ERR("Read Checksum error!!(%d)\n", ret);
- return ret;
- }
- RD_Filechksum[i] = (uint16_t)((buf[2] << 8) | buf[1]);
- if (WR_Filechksum[i] != RD_Filechksum[i]) {
- NVT_ERR("Verify Fail%d!!\n", i);
- NVT_ERR("RD_Filechksum[%d]=0x%04X, WR_Filechksum[%d]=0x%04X\n", i, RD_Filechksum[i], i, WR_Filechksum[i]);
- return -1;
- }
- }
- }
- NVT_LOG("Verify OK \n");
- return 0;
- }
- /*******************************************************
- Description:
- Novatek touchscreen update firmware function.
- return:
- Executive outcomes. 0---succeed. negative---failed.
- *******************************************************/
- int32_t Update_Firmware(void)
- {
- int32_t ret = 0;
- //---Stop CRC check to prevent IC auto reboot---
- nvt_stop_crc_reboot();
- // Step 1 : initial bootloader
- ret = Init_BootLoader();
- if (ret) {
- return ret;
- }
- // Step 2 : Resume PD
- ret = Resume_PD();
- if (ret) {
- return ret;
- }
- // Step 3 : Erase
- ret = Erase_Flash();
- if (ret) {
- return ret;
- }
- // Step 4 : Program
- ret = Write_Flash();
- if (ret) {
- return ret;
- }
- // Step 5 : Verify
- ret = Verify_Flash();
- if (ret) {
- return ret;
- }
- //Step 6 : Bootloader Reset
- nvt_bootloader_reset();
- nvt_check_fw_reset_state(RESET_STATE_INIT);
- nvt_get_fw_info();
- return ret;
- }
- /*******************************************************
- Description:
- Novatek touchscreen check flash end flag function.
- return:
- Executive outcomes. 0---succeed. 1,negative---failed.
- *******************************************************/
- int32_t nvt_check_flash_end_flag(void)
- {
- uint8_t buf[8] = {0};
- uint8_t nvt_end_flag[NVT_FLASH_END_FLAG_LEN + 1] = {0};
- int32_t ret = 0;
- // Step 1 : initial bootloader
- ret = Init_BootLoader();
- if (ret) {
- return ret;
- }
- // Step 2 : Resume PD
- ret = Resume_PD();
- if (ret) {
- return ret;
- }
- // Step 3 : unlock
- buf[0] = 0x00;
- buf[1] = 0x35;
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("write unlock error!!(%d)\n", ret);
- return ret;
- }
- msleep(10);
- //Step 4 : Flash Read Command
- buf[0] = 0x00;
- buf[1] = 0x03;
- buf[2] = (NVT_FLASH_END_FLAG_ADDR >> 16) & 0xFF; //Addr_H
- buf[3] = (NVT_FLASH_END_FLAG_ADDR >> 8) & 0xFF; //Addr_M
- buf[4] = NVT_FLASH_END_FLAG_ADDR & 0xFF; //Addr_L
- buf[5] = (NVT_FLASH_END_FLAG_LEN >> 8) & 0xFF; //Len_H
- buf[6] = NVT_FLASH_END_FLAG_LEN & 0xFF; //Len_L
- ret = CTP_I2C_WRITE(ts->client, I2C_HW_Address, buf, 7);
- if (ret < 0) {
- NVT_ERR("write Read Command error!!(%d)\n", ret);
- return ret;
- }
- msleep(10);
- // Check 0xAA (Read Command)
- buf[0] = 0x00;
- buf[1] = 0x00;
- ret = CTP_I2C_READ(ts->client, I2C_HW_Address, buf, 2);
- if (ret < 0) {
- NVT_ERR("Check 0xAA (Read Command) error!!(%d)\n", ret);
- return ret;
- }
- if (buf[1] != 0xAA) {
- NVT_ERR("Check 0xAA (Read Command) error!! status=0x%02X\n", buf[1]);
- return -1;
- }
- msleep(10);
- //Step 5 : Read Flash Data
- ret = nvt_set_page(I2C_BLDR_Address, ts->mmap->READ_FLASH_CHECKSUM_ADDR);
- if (ret < 0) {
- NVT_ERR("change index error!! (%d)\n", ret);
- return ret;
- }
- msleep(10);
- // Read Back
- buf[0] = ts->mmap->READ_FLASH_CHECKSUM_ADDR & 0xFF;
- ret = CTP_I2C_READ(ts->client, I2C_BLDR_Address, buf, 6);
- if (ret < 0) {
- NVT_ERR("Read Back error!! (%d)\n", ret);
- return ret;
- }
- //buf[3:5] => NVT End Flag
- strlcpy(nvt_end_flag, &buf[3], sizeof(nvt_end_flag));
- NVT_LOG("nvt_end_flag=%s (%02X %02X %02X)\n", nvt_end_flag, buf[3], buf[4], buf[5]);
- if ((memcmp(nvt_end_flag, "NVT", NVT_FLASH_END_FLAG_LEN) == 0) ||
- (memcmp(nvt_end_flag, "MOD", NVT_FLASH_END_FLAG_LEN) == 0)) {
- return 0;
- } else {
- NVT_ERR("\"NVT\" end flag not found!\n");
- return 1;
- }
- }
- /*******************************************************
- Description:
- Novatek touchscreen update firmware when booting
- function.
- return:
- n.a.
- *******************************************************/
- void Boot_Update_Firmware(struct work_struct *work)
- {
- int32_t ret = 0;
- char firmware_name[256] = "";
- snprintf(firmware_name, sizeof(firmware_name),
- BOOT_UPDATE_FIRMWARE_NAME);
- // request bin file in "/etc/firmware"
- ret = update_firmware_request(firmware_name);
- if (ret) {
- NVT_ERR("update_firmware_request failed. (%d)\n", ret);
- return;
- }
- mutex_lock(&ts->lock);
- #if NVT_TOUCH_ESD_PROTECT
- nvt_esd_check_enable(false);
- #endif /* #if NVT_TOUCH_ESD_PROTECT */
- nvt_sw_reset_idle();
- ret = Check_CheckSum();
- if (ret < 0) { // read firmware checksum failed
- NVT_ERR("read firmware checksum failed\n");
- Update_Firmware();
- } else if ((ret == 0) && (Check_FW_Ver() == 0)) { // (fw checksum not match) && (bin fw version >= ic fw version)
- NVT_LOG("firmware version not match\n");
- Update_Firmware();
- } else if (nvt_check_flash_end_flag()) {
- NVT_LOG("check flash end flag failed\n");
- Update_Firmware();
- } else {
- // Bootloader Reset
- nvt_bootloader_reset();
- ret = nvt_check_fw_reset_state(RESET_STATE_INIT);
- if (ret) {
- NVT_LOG("check fw reset state failed\n");
- Update_Firmware();
- }
- }
- mutex_unlock(&ts->lock);
- update_firmware_release();
- }
- #endif /* BOOT_UPDATE_FIRMWARE */
- #else /* NT36XXX_SPI */
- #include <linux/firmware.h>
- #include <linux/gpio.h>
- #include "nt36xxx.h"
- #if NVT_SPI_BOOT_UPDATE_FIRMWARE
- #define SIZE_4KB 4096
- #define FLASH_SECTOR_SIZE SIZE_4KB
- #define FW_BIN_VER_OFFSET (nvt_spi_fw_need_write_size - SIZE_4KB)
- #define FW_BIN_VER_BAR_OFFSET (FW_BIN_VER_OFFSET + 1)
- #define NVT_FLASH_END_FLAG_LEN 3
- #define NVT_FLASH_END_FLAG_ADDR (nvt_spi_fw_need_write_size - NVT_FLASH_END_FLAG_LEN)
- #define NVT_DUMP_PARTITION (0)
- #define NVT_DUMP_PARTITION_LEN (1024)
- #define NVT_DUMP_PARTITION_PATH "/data/local/tmp"
- static ktime_t nvt_spi_start, nvt_spi_end;
- static const struct firmware *nvt_spi_fw_entry;
- static size_t nvt_spi_fw_need_write_size;
- static uint8_t *nvt_spi_fwbuf;
- struct nvt_spi_bin_map_t {
- char name[12];
- uint32_t BIN_addr;
- uint32_t SRAM_addr;
- uint32_t size;
- uint32_t crc;
- };
- static struct nvt_spi_bin_map_t *nvt_spi_bin_map;
- static int32_t nvt_spi_get_fw_need_write_size(const struct firmware *fw_entry)
- {
- int32_t i = 0;
- int32_t total_sectors_to_check = 0;
- total_sectors_to_check = fw_entry->size / FLASH_SECTOR_SIZE;
- /* printk("total_sectors_to_check = %d\n", total_sectors_to_check); */
- for (i = total_sectors_to_check; i > 0; i--) {
- // printk("current end flag address checked = 0x%X\n",
- // i * FLASH_SECTOR_SIZE - NVT_FLASH_END_FLAG_LEN);
- /* check if there is end flag "NVT" at the end of this sector */
- if (memcmp(&fw_entry->data[i * FLASH_SECTOR_SIZE - NVT_FLASH_END_FLAG_LEN],
- "NVT", NVT_FLASH_END_FLAG_LEN) == 0) {
- nvt_spi_fw_need_write_size = i * FLASH_SECTOR_SIZE;
- NVT_LOG("fw_need_write_size = %zu(0x%zx), NVT end flag\n",
- nvt_spi_fw_need_write_size, nvt_spi_fw_need_write_size);
- return 0;
- }
- /* check if there is end flag "MOD" at the end of this sector */
- if (memcmp(&fw_entry->data[i * FLASH_SECTOR_SIZE - NVT_FLASH_END_FLAG_LEN],
- "MOD", NVT_FLASH_END_FLAG_LEN) == 0) {
- nvt_spi_fw_need_write_size = i * FLASH_SECTOR_SIZE;
- NVT_LOG("fw_need_write_size = %zu(0x%zx), MOD end flag\n",
- nvt_spi_fw_need_write_size, nvt_spi_fw_need_write_size);
- return 0;
- }
- }
- NVT_ERR("end flag \"NVT\" \"MOD\" not found!\n");
- return -EINVAL;
- }
- /*
- *******************************************************
- * Description:
- * Novatek touchscreen init variable and allocate buffer
- * for download firmware function.
- *
- * return:
- * n.a.
- ******************************************************
- */
- static int32_t nvt_spi_download_init(void)
- {
- uint8_t *buf;
- /* allocate buffer for transfer firmware */
- //NVT_LOG("NVT_TRANSFER_LEN = 0x%06X\n", NVT_SPI_TRANSFER_LEN);
- if (nvt_spi_fwbuf == NULL) {
- buf = kzalloc((NVT_SPI_TRANSFER_LEN + 1 + NVT_SPI_DUMMY_BYTES), GFP_KERNEL);
- if (buf == NULL) {
- NVT_ERR("kzalloc for fwbuf failed!\n");
- return -ENOMEM;
- }
- nvt_spi_fwbuf = buf;
- }
- return 0;
- }
- /*
- ******************************************************
- * Description:
- * Novatek touchscreen checksum function. Calculate bin
- * file checksum for comparison.
- *
- * return:
- * n.a.
- ******************************************************
- */
- static uint32_t CheckSum(const u8 *data, size_t len)
- {
- uint32_t i = 0;
- uint32_t checksum = 0;
- for (i = 0 ; i < len + 1; i++)
- checksum += data[i];
- checksum += len;
- checksum = ~checksum + 1;
- return checksum;
- }
- static uint32_t byte_to_word(const uint8_t *data)
- {
- return data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24);
- }
- /*
- ******************************************************
- * Description:
- * Novatek touchscreen parsing bin header function.
- *
- * return:
- * n.a.
- ******************************************************
- */
- static uint32_t nvt_spi_partition;
- static uint8_t nvt_spi_ilm_dlm_num = 2;
- static uint8_t nvt_spi_cascade_2nd_header_info;
- static int32_t nvt_spi_bin_header_parser(const u8 *fwdata, size_t fwsize)
- {
- uint32_t list = 0;
- uint32_t pos = 0x00;
- uint32_t end = 0x00;
- uint8_t info_sec_num = 0;
- uint8_t ovly_sec_num = 0;
- uint8_t ovly_info = 0;
- uint8_t find_bin_header = 0;
- struct nvt_spi_bin_map_t *bin_map = NULL;
- struct nvt_spi_data_t *ts = nvt_spi_data;
- /* Find the header size */
- end = fwdata[0] + (fwdata[1] << 8) + (fwdata[2] << 16) + (fwdata[3] << 24);
- /* check cascade next header */
- nvt_spi_cascade_2nd_header_info = (fwdata[0x20] & 0x02) >> 1;
- NVT_LOG("cascade_2nd_header_info = %d\n", nvt_spi_cascade_2nd_header_info);
- if (nvt_spi_cascade_2nd_header_info) {
- pos = 0x30; // info section start at 0x30 offset
- while (pos < (end / 2)) {
- info_sec_num++;
- pos += 0x10; /* each header info is 16 bytes */
- }
- info_sec_num = info_sec_num + 1; //next header section
- } else {
- pos = 0x30; // info section start at 0x30 offset
- while (pos < end) {
- info_sec_num++;
- pos += 0x10; /* each header info is 16 bytes */
- }
- }
- /*
- * Find the DLM OVLY section
- * [0:3] Overlay Section Number
- * [4] Overlay Info
- */
- ovly_info = (fwdata[0x28] & 0x10) >> 4;
- ovly_sec_num = (ovly_info) ? (fwdata[0x28] & 0x0F) : 0;
- /*
- * calculate all partition number
- * ilm_dlm_num (ILM & DLM) + ovly_sec_num + info_sec_num
- */
- nvt_spi_partition = nvt_spi_ilm_dlm_num + ovly_sec_num + info_sec_num;
- NVT_LOG("ovly_info=%d, ilm_dlm_num=%d, ovly_sec_num=%d, info_sec_num=%d, partition=%d\n",
- ovly_info, nvt_spi_ilm_dlm_num, ovly_sec_num, info_sec_num, nvt_spi_partition);
- /* allocated memory for header info */
- bin_map = kzalloc((nvt_spi_partition+1) * sizeof(struct nvt_spi_bin_map_t), GFP_KERNEL);
- if (bin_map == NULL) {
- NVT_ERR("kzalloc for bin_map failed!\n");
- return -ENOMEM;
- }
- nvt_spi_bin_map = bin_map;
- for (list = 0; list < nvt_spi_partition; list++) {
- /*
- * [1] parsing ILM & DLM header info
- * BIN_addr : SRAM_addr : size (12-bytes)
- * crc located at 0x18 & 0x1C
- */
- if (list < nvt_spi_ilm_dlm_num) {
- bin_map[list].BIN_addr = byte_to_word(&fwdata[0 + list * 12]);
- bin_map[list].SRAM_addr = byte_to_word(&fwdata[4 + list * 12]);
- bin_map[list].size = byte_to_word(&fwdata[8 + list * 12]);
- if (ts->hw_crc)
- bin_map[list].crc = byte_to_word(&fwdata[0x18 + list * 4]);
- else { //ts->hw_crc
- if ((bin_map[list].BIN_addr + bin_map[list].size) < fwsize)
- bin_map[list].crc = CheckSum(
- &fwdata[bin_map[list].BIN_addr],
- bin_map[list].size);
- else {
- NVT_ERR("access range (0x%08X to 0x%08X) is too large!\n",
- bin_map[list].BIN_addr,
- bin_map[list].BIN_addr + bin_map[list].size);
- return -EINVAL;
- }
- } //ts->hw_crc
- if (list == 0)
- snprintf(bin_map[list].name, sizeof(bin_map[list].name), "ILM");
- else if (list == 1)
- snprintf(bin_map[list].name, sizeof(bin_map[list].name), "DLM");
- }
- /*
- * [2] parsing others header info
- * SRAM_addr : size : BIN_addr : crc (16-bytes)
- */
- if ((list >= nvt_spi_ilm_dlm_num)
- && (list < (nvt_spi_ilm_dlm_num + info_sec_num))) {
- if (find_bin_header == 0) {
- /* others partition located at 0x30 offset */
- pos = 0x30 + (0x10 * (list - nvt_spi_ilm_dlm_num));
- } else if (find_bin_header && nvt_spi_cascade_2nd_header_info) {
- /* cascade 2nd header info */
- pos = end - 0x10;
- }
- bin_map[list].SRAM_addr = byte_to_word(&fwdata[pos]);
- bin_map[list].size = byte_to_word(&fwdata[pos + 4]);
- bin_map[list].BIN_addr = byte_to_word(&fwdata[pos + 8]);
- if (ts->hw_crc)
- bin_map[list].crc = byte_to_word(&fwdata[pos + 12]);
- else { //ts->hw_crc
- if ((bin_map[list].BIN_addr + bin_map[list].size) < fwsize)
- bin_map[list].crc = CheckSum(
- &fwdata[bin_map[list].BIN_addr],
- bin_map[list].size);
- else {
- NVT_ERR("access range (0x%08X to 0x%08X) is too large!\n",
- bin_map[list].BIN_addr,
- bin_map[list].BIN_addr + bin_map[list].size);
- return -EINVAL;
- }
- } //ts->hw_crc
- /* detect header end to protect parser function */
- if ((bin_map[list].BIN_addr < end) && (bin_map[list].size != 0)) {
- snprintf(bin_map[list].name, sizeof(bin_map[list].name),
- "Header");
- find_bin_header = 1;
- } else
- snprintf(bin_map[list].name, sizeof(bin_map[list].name),
- "Info-%d", (list - nvt_spi_ilm_dlm_num));
- }
- /*
- * [3] parsing overlay section header info
- * SRAM_addr : size : BIN_addr : crc (16-bytes)
- */
- if (list >= (nvt_spi_ilm_dlm_num + info_sec_num)) {
- /* overlay info located at DLM (list = 1) start addr */
- pos = bin_map[1].BIN_addr;
- pos += (0x10 * (list - nvt_spi_ilm_dlm_num - info_sec_num));
- bin_map[list].SRAM_addr = byte_to_word(&fwdata[pos]);
- bin_map[list].size = byte_to_word(&fwdata[pos + 4]);
- bin_map[list].BIN_addr = byte_to_word(&fwdata[pos + 8]);
- if (ts->hw_crc)
- bin_map[list].crc = byte_to_word(&fwdata[pos + 12]);
- else { //ts->hw_crc
- if ((bin_map[list].BIN_addr + bin_map[list].size) < fwsize)
- bin_map[list].crc = CheckSum(
- &fwdata[bin_map[list].BIN_addr],
- bin_map[list].size);
- else {
- NVT_ERR("access range (0x%08X to 0x%08X) is too large!\n",
- bin_map[list].BIN_addr,
- bin_map[list].BIN_addr + bin_map[list].size);
- return -EINVAL;
- }
- } //ts->hw_crc
- snprintf(bin_map[list].name, sizeof(bin_map[list].name),
- "Overlay-%d",
- (list - nvt_spi_ilm_dlm_num - info_sec_num));
- }
- /* BIN size error detect */
- if ((bin_map[list].BIN_addr + bin_map[list].size) > fwsize) {
- NVT_ERR("access range (0x%08X to 0x%08X) is larger than bin size!\n",
- bin_map[list].BIN_addr,
- bin_map[list].BIN_addr + bin_map[list].size);
- return -EINVAL;
- }
- // NVT_LOG("[%d][%s] SRAM (0x%08X), SIZE (0x%08X), BIN (0x%08X), CRC (0x%08X)\n",
- // list, bin_map[list].name,
- // bin_map[list].SRAM_addr, bin_map[list].size,
- // bin_map[list].BIN_addr, bin_map[list].crc);
- }
- return 0;
- }
- /*
- *******************************************************
- * Description:
- * Novatek touchscreen release update firmware function.
- *
- * return:
- * n.a.
- ******************************************************
- */
- static void nvt_spi_update_firmware_release(void)
- {
- if (nvt_spi_fw_entry)
- release_firmware(nvt_spi_fw_entry);
- nvt_spi_fw_entry = NULL;
- }
- /*
- ******************************************************
- * Description:
- * Novatek touchscreen request update firmware function.
- *
- * return:
- * Executive outcomes. 0---succeed. -1,-22---failed.
- ******************************************************
- */
- static int32_t nvt_spi_update_firmware_request(char *filename)
- {
- uint8_t retry = 0;
- int32_t ret = 0;
- struct nvt_spi_data_t *ts = nvt_spi_data;
- uint8_t ver;
- if (filename == NULL)
- return -ENOENT;
- while (1) {
- NVT_LOG("filename is %s\n", filename);
- ret = request_firmware(&nvt_spi_fw_entry, filename, &ts->client->dev);
- if (ret) {
- NVT_ERR("firmware load failed, ret=%d\n", ret);
- goto request_fail;
- }
- // check FW need to write size
- if (nvt_spi_get_fw_need_write_size(nvt_spi_fw_entry)) {
- NVT_ERR("get fw need to write size fail!\n");
- ret = -EINVAL;
- goto invalid;
- }
- // check if FW version add FW version bar equals 0xFF
- ver = *(nvt_spi_fw_entry->data + FW_BIN_VER_OFFSET);
- if (ver + *(nvt_spi_fw_entry->data + FW_BIN_VER_BAR_OFFSET) != 0xFF) {
- NVT_ERR("bin file FW_VER + FW_VER_BAR should be 0xFF!\n");
- NVT_ERR("FW_VER=0x%02X, FW_VER_BAR=0x%02X\n",
- *(nvt_spi_fw_entry->data+FW_BIN_VER_OFFSET),
- *(nvt_spi_fw_entry->data+FW_BIN_VER_BAR_OFFSET));
- ret = -ENOEXEC;
- goto invalid;
- }
- /* BIN Header Parser */
- ret = nvt_spi_bin_header_parser(nvt_spi_fw_entry->data, nvt_spi_fw_entry->size);
- if (ret) {
- NVT_ERR("bin header parser failed\n");
- goto invalid;
- } else
- break;
- invalid:
- nvt_spi_update_firmware_release();
- if (!IS_ERR_OR_NULL(nvt_spi_bin_map)) {
- kfree(nvt_spi_bin_map);
- nvt_spi_bin_map = NULL;
- }
- request_fail:
- retry++;
- if (unlikely(retry > 2)) {
- NVT_ERR("error, retry=%d\n", retry);
- break;
- }
- }
- return ret;
- }
- /*
- *******************************************************
- * Description:
- * Novatek touchscreen write data to sram function.
- *
- * - fwdata : The buffer is written
- * - SRAM_addr: The sram destination address
- * - size : Number of data bytes in @fwdata being written
- * - BIN_addr : The transferred data offset of @fwdata
- *
- * return:
- * Executive outcomes. 0---succeed. else---fail.
- *******************************************************
- */
- static int32_t nvt_spi_write_sram(const u8 *fwdata,
- uint32_t SRAM_addr, uint32_t size, uint32_t BIN_addr)
- {
- int32_t ret = 0;
- uint32_t i = 0;
- uint16_t len = 0;
- int32_t count = 0;
- if (size % NVT_SPI_TRANSFER_LEN)
- count = (size / NVT_SPI_TRANSFER_LEN) + 1;
- else
- count = (size / NVT_SPI_TRANSFER_LEN);
- for (i = 0 ; i < count ; i++) {
- len = (size < NVT_SPI_TRANSFER_LEN) ? size : NVT_SPI_TRANSFER_LEN;
- //---set xdata index to start address of SRAM---
- ret = nvt_spi_set_page(SRAM_addr);
- if (ret) {
- NVT_ERR("set page failed, ret = %d\n", ret);
- return ret;
- }
- //---write data into SRAM---
- nvt_spi_fwbuf[0] = SRAM_addr & 0x7F; //offset
- memcpy(nvt_spi_fwbuf+1, &fwdata[BIN_addr], len); //payload
- ret = nvt_spi_write(nvt_spi_fwbuf, len+1);
- if (ret) {
- NVT_ERR("write to sram failed, ret = %d\n", ret);
- return ret;
- }
- SRAM_addr += NVT_SPI_TRANSFER_LEN;
- BIN_addr += NVT_SPI_TRANSFER_LEN;
- size -= NVT_SPI_TRANSFER_LEN;
- }
- return ret;
- }
- /*
- *******************************************************
- * Description:
- * Novatek touchscreen nvt_spi_write_firmware function to write
- * firmware into each partition.
- *
- * return:
- * n.a.
- ******************************************************
- */
- static int32_t nvt_spi_write_firmware(const u8 *fwdata, size_t fwsize)
- {
- uint32_t list = 0;
- char *name;
- uint32_t BIN_addr, SRAM_addr, size;
- int32_t ret = 0;
- memset(nvt_spi_fwbuf, 0, (NVT_SPI_TRANSFER_LEN+1));
- for (list = 0; list < nvt_spi_partition; list++) {
- /* initialize variable */
- SRAM_addr = nvt_spi_bin_map[list].SRAM_addr;
- size = nvt_spi_bin_map[list].size;
- BIN_addr = nvt_spi_bin_map[list].BIN_addr;
- name = nvt_spi_bin_map[list].name;
- // NVT_LOG("[%d][%s] SRAM (0x%08X), SIZE (0x%08X), BIN (0x%08X)\n",
- // list, name, SRAM_addr, size, BIN_addr);
- /* Check data size */
- if ((BIN_addr + size) > fwsize) {
- NVT_ERR("access range (0x%08X to 0x%08X) is larger than bin size!\n",
- BIN_addr, BIN_addr + size);
- ret = -EINVAL;
- goto out;
- }
- /* ignore reserved partition (Reserved Partition size is zero) */
- if (!size)
- continue;
- else
- size = size + 1;
- /* write data to SRAM */
- ret = nvt_spi_write_sram(fwdata, SRAM_addr, size, BIN_addr);
- if (ret) {
- NVT_ERR("sram program failed, ret = %d\n", ret);
- goto out;
- }
- }
- out:
- return ret;
- }
- /*
- *******************************************************
- * Description:
- * Novatek touchscreen check checksum function.
- * This function will compare file checksum and fw checksum.
- *
- * return:
- * n.a.
- *******************************************************
- */
- static int32_t nvt_spi_check_fw_checksum(void)
- {
- uint32_t fw_checksum = 0;
- uint32_t len = nvt_spi_partition * 4;
- uint32_t list = 0;
- int32_t ret = 0;
- struct nvt_spi_data_t *ts = nvt_spi_data;
- memset(nvt_spi_fwbuf, 0, (len+1));
- //---set xdata index to checksum---
- nvt_spi_set_page(ts->mmap->R_ILM_CHECKSUM_ADDR);
- /* read checksum */
- nvt_spi_fwbuf[0] = (ts->mmap->R_ILM_CHECKSUM_ADDR) & 0x7F;
- ret = nvt_spi_read(nvt_spi_fwbuf, len+1);
- if (ret) {
- NVT_ERR("Read fw checksum failed\n");
- return ret;
- }
- /*
- * Compare each checksum from fw
- * ILM + DLM + Overlay + Info
- * nvt_spi_ilm_dlm_num (ILM & DLM) + ovly_sec_num + info_sec_num
- */
- for (list = 0; list < nvt_spi_partition; list++) {
- fw_checksum = byte_to_word(&nvt_spi_fwbuf[1+list*4]);
- /* ignore reserved partition (Reserved Partition size is zero) */
- if (!nvt_spi_bin_map[list].size)
- continue;
- if (nvt_spi_bin_map[list].crc != fw_checksum) {
- NVT_ERR("[%d] BIN_checksum=0x%08X, FW_checksum=0x%08X\n",
- list, nvt_spi_bin_map[list].crc, fw_checksum);
- ret = -EIO;
- }
- }
- return ret;
- }
- /*
- *******************************************************
- * Description:
- * Novatek touchscreen set bootload crc reg bank function.
- * This function will set hw crc reg before enable crc function.
- *
- * return:
- * n.a.
- ******************************************************
- */
- static void nvt_spi_set_bld_crc_bank(uint32_t DES_ADDR, uint32_t SRAM_ADDR,
- uint32_t LENGTH_ADDR, uint32_t size,
- uint32_t G_CHECKSUM_ADDR, uint32_t crc)
- {
- struct nvt_spi_data_t *ts = nvt_spi_data;
- /* write destination address */
- nvt_spi_set_page(DES_ADDR);
- nvt_spi_fwbuf[0] = DES_ADDR & 0x7F;
- nvt_spi_fwbuf[1] = (SRAM_ADDR) & 0xFF;
- nvt_spi_fwbuf[2] = (SRAM_ADDR >> 8) & 0xFF;
- nvt_spi_fwbuf[3] = (SRAM_ADDR >> 16) & 0xFF;
- nvt_spi_write(nvt_spi_fwbuf, 4);
- /* write length */
- //nvt_spi_set_page(LENGTH_ADDR);
- nvt_spi_fwbuf[0] = LENGTH_ADDR & 0x7F;
- nvt_spi_fwbuf[1] = (size) & 0xFF;
- nvt_spi_fwbuf[2] = (size >> 8) & 0xFF;
- nvt_spi_fwbuf[3] = (size >> 16) & 0x01;
- if (ts->hw_crc == 1)
- nvt_spi_write(nvt_spi_fwbuf, 3);
- else if (ts->hw_crc > 1)
- nvt_spi_write(nvt_spi_fwbuf, 4);
- /* write golden dlm checksum */
- //nvt_spi_set_page(G_CHECKSUM_ADDR);
- nvt_spi_fwbuf[0] = G_CHECKSUM_ADDR & 0x7F;
- nvt_spi_fwbuf[1] = (crc) & 0xFF;
- nvt_spi_fwbuf[2] = (crc >> 8) & 0xFF;
- nvt_spi_fwbuf[3] = (crc >> 16) & 0xFF;
- nvt_spi_fwbuf[4] = (crc >> 24) & 0xFF;
- nvt_spi_write(nvt_spi_fwbuf, 5);
- }
- /*
- *********************************************************
- * Description:
- * Novatek touchscreen set BLD hw crc function.
- * This function will set ILM and DLM crc information to register.
- *
- * return:
- * n.a.
- *********************************************************
- */
- static void nvt_spi_set_bld_hw_crc(void)
- {
- struct nvt_spi_data_t *ts = nvt_spi_data;
- /* [0] ILM */
- /* write register bank */
- nvt_spi_set_bld_crc_bank(ts->mmap->ILM_DES_ADDR, nvt_spi_bin_map[0].SRAM_addr,
- ts->mmap->ILM_LENGTH_ADDR, nvt_spi_bin_map[0].size,
- ts->mmap->G_ILM_CHECKSUM_ADDR, nvt_spi_bin_map[0].crc);
- /* [1] DLM */
- /* write register bank */
- nvt_spi_set_bld_crc_bank(ts->mmap->DLM_DES_ADDR, nvt_spi_bin_map[1].SRAM_addr,
- ts->mmap->DLM_LENGTH_ADDR, nvt_spi_bin_map[1].size,
- ts->mmap->G_DLM_CHECKSUM_ADDR, nvt_spi_bin_map[1].crc);
- }
- /*
- *******************************************************
- * Description:
- * Novatek touchscreen read BLD hw crc info function.
- * This function will check crc results from register.
- *
- * return:
- * n.a.
- ******************************************************
- */
- static void nvt_spi_read_bld_hw_crc(void)
- {
- uint8_t buf[8] = {0};
- uint32_t g_crc = 0, r_crc = 0;
- struct nvt_spi_data_t *ts = nvt_spi_data;
- /* CRC Flag */
- nvt_spi_set_page(ts->mmap->BLD_ILM_DLM_CRC_ADDR);
- buf[0] = ts->mmap->BLD_ILM_DLM_CRC_ADDR & 0x7F;
- buf[1] = 0x00;
- nvt_spi_read(buf, 2);
- NVT_ERR("crc_done = %d, ilm_crc_flag = %d, dlm_crc_flag = %d\n",
- (buf[1] >> 2) & 0x01, (buf[1] >> 0) & 0x01, (buf[1] >> 1) & 0x01);
- /* ILM CRC */
- nvt_spi_set_page(ts->mmap->G_ILM_CHECKSUM_ADDR);
- buf[0] = ts->mmap->G_ILM_CHECKSUM_ADDR & 0x7F;
- buf[1] = 0x00;
- buf[2] = 0x00;
- buf[3] = 0x00;
- buf[4] = 0x00;
- nvt_spi_read(buf, 5);
- g_crc = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24);
- nvt_spi_set_page(ts->mmap->R_ILM_CHECKSUM_ADDR);
- buf[0] = ts->mmap->R_ILM_CHECKSUM_ADDR & 0x7F;
- buf[1] = 0x00;
- buf[2] = 0x00;
- buf[3] = 0x00;
- buf[4] = 0x00;
- nvt_spi_read(buf, 5);
- r_crc = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24);
- NVT_ERR("ilm: bin crc = 0x%08X, golden = 0x%08X, result = 0x%08X\n",
- nvt_spi_bin_map[0].crc, g_crc, r_crc);
- /* DLM CRC */
- nvt_spi_set_page(ts->mmap->G_DLM_CHECKSUM_ADDR);
- buf[0] = ts->mmap->G_DLM_CHECKSUM_ADDR & 0x7F;
- buf[1] = 0x00;
- buf[2] = 0x00;
- buf[3] = 0x00;
- buf[4] = 0x00;
- nvt_spi_read(buf, 5);
- g_crc = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24);
- nvt_spi_set_page(ts->mmap->R_DLM_CHECKSUM_ADDR);
- buf[0] = ts->mmap->R_DLM_CHECKSUM_ADDR & 0x7F;
- buf[1] = 0x00;
- buf[2] = 0x00;
- buf[3] = 0x00;
- buf[4] = 0x00;
- nvt_spi_read(buf, 5);
- r_crc = buf[1] | (buf[2] << 8) | (buf[3] << 16) | (buf[4] << 24);
- NVT_ERR("dlm: bin crc = 0x%08X, golden = 0x%08X, result = 0x%08X\n",
- nvt_spi_bin_map[1].crc, g_crc, r_crc);
- }
- /*
- ******************************************************
- * Description:
- * Novatek touchscreen Download_Firmware with HW CRC
- * function. It's complete download firmware flow.
- *
- * return:
- * Executive outcomes. 0---succeed. else---fail.
- ******************************************************
- */
- static int32_t nvt_spi_download_firmware_hw_crc(void)
- {
- uint8_t retry = 0;
- int32_t ret = 0;
- const struct firmware *fw = nvt_spi_fw_entry;
- nvt_spi_start = ktime_get();
- while (1) {
- /* bootloader reset to reset MCU */
- nvt_spi_bootloader_reset();
- /* set ilm & dlm reg bank */
- nvt_spi_set_bld_hw_crc();
- /* Start to write firmware process */
- if (nvt_spi_cascade_2nd_header_info) {
- /* for cascade */
- nvt_spi_tx_auto_copy_mode();
- ret = nvt_spi_write_firmware(fw->data, fw->size);
- if (ret) {
- NVT_ERR("Write_Firmware failed. (%d)\n", ret);
- goto fail;
- }
- ret = nvt_spi_check_spi_dma_tx_info();
- if (ret) {
- NVT_ERR("spi dma tx info failed. (%d)\n", ret);
- goto fail;
- }
- } else {
- ret = nvt_spi_write_firmware(fw->data, fw->size);
- if (ret) {
- NVT_ERR("Write_Firmware failed. (%d)\n", ret);
- goto fail;
- }
- }
- #if NVT_DUMP_PARTITION
- ret = nvt_dump_partition();
- if (ret)
- NVT_ERR("nvt_dump_partition failed, ret = %d\n", ret);
- #endif
- /* enable hw bld crc function */
- nvt_spi_bld_crc_enable();
- /* clear fw reset status & enable fw crc check */
- nvt_spi_fw_crc_enable();
- /* Set Boot Ready Bit */
- nvt_spi_boot_ready();
- ret = nvt_spi_check_fw_reset_state(NVT_SPI_RESET_STATE_INIT);
- if (ret) {
- NVT_ERR("nvt_check_fw_reset_state failed. (%d)\n", ret);
- goto fail;
- } else {
- break;
- }
- fail:
- retry++;
- if (unlikely(retry > 2)) {
- NVT_ERR("error, retry=%d\n", retry);
- nvt_spi_read_bld_hw_crc();
- break;
- }
- }
- nvt_spi_end = ktime_get();
- return ret;
- }
- /*
- ********************************************************
- * Description:
- * Novatek touchscreen Download_Firmware function. It's
- * complete download firmware flow.
- *
- * return:
- * n.a.
- ******************************************************
- */
- static int32_t nvt_spi_download_firmware(void)
- {
- uint32_t addr;
- uint8_t retry = 0;
- int32_t ret = 0;
- struct nvt_spi_data_t *ts = nvt_spi_data;
- nvt_spi_start = ktime_get();
- while (1) {
- /*
- * Send eng reset cmd before download FW
- * Keep TP_RESX low when send eng reset cmd
- */
- #if NVT_SPI_TOUCH_SUPPORT_HW_RST
- gpio_set_value(ts->reset_gpio, 0);
- mdelay(1); //wait 1ms
- #endif
- nvt_spi_eng_reset();
- #if NVT_SPI_TOUCH_SUPPORT_HW_RST
- gpio_set_value(ts->reset_gpio, 1);
- mdelay(10); //wait tRT2BRST after TP_RST
- #endif
- nvt_spi_bootloader_reset();
- addr = ts->mmap->EVENT_BUF_ADDR;
- /* clear fw reset status */
- nvt_spi_write_addr(addr | NVT_SPI_EVENT_MAP_RESET_COMPLETE, 0x00);
- /* Start to write firmware process */
- ret = nvt_spi_write_firmware(nvt_spi_fw_entry->data, nvt_spi_fw_entry->size);
- if (ret) {
- NVT_ERR("Write_Firmware failed. (%d)\n", ret);
- goto fail;
- }
- #if NVT_DUMP_PARTITION
- ret = nvt_dump_partition();
- if (ret)
- NVT_ERR("nvt_dump_partition failed, ret = %d\n", ret);
- #endif
- /* Set Boot Ready Bit */
- nvt_spi_boot_ready();
- ret = nvt_spi_check_fw_reset_state(NVT_SPI_RESET_STATE_INIT);
- if (ret) {
- NVT_ERR("nvt_check_fw_reset_state failed. (%d)\n", ret);
- goto fail;
- }
- /* check fw checksum result */
- ret = nvt_spi_check_fw_checksum();
- if (ret) {
- NVT_ERR("firmware checksum not match, retry=%d\n", retry);
- goto fail;
- } else
- break;
- fail:
- retry++;
- if (unlikely(retry > 2)) {
- NVT_ERR("error, retry=%d\n", retry);
- break;
- }
- }
- nvt_spi_end = ktime_get();
- return ret;
- }
- /*
- ******************************************************
- * Description:
- * Novatek touchscreen update firmware main function.
- *
- * return:
- * n.a.
- ******************************************************
- */
- int32_t nvt_spi_update_firmware(char *firmware_name)
- {
- int32_t ret = 0;
- struct nvt_spi_data_t *ts = nvt_spi_data;
- // request bin file in "/etc/firmware"
- ret = nvt_spi_update_firmware_request(firmware_name);
- if (ret) {
- NVT_ERR("update_firmware_request failed. (%d)\n", ret);
- goto request_firmware_fail;
- }
- /* initial buffer and variable */
- ret = nvt_spi_download_init();
- if (ret) {
- NVT_ERR("Download Init failed. (%d)\n", ret);
- goto download_fail;
- }
- /* download firmware process */
- if (ts->hw_crc)
- ret = nvt_spi_download_firmware_hw_crc();
- else
- ret = nvt_spi_download_firmware();
- if (ret) {
- NVT_ERR("Download Firmware failed. (%d)\n", ret);
- goto download_fail;
- }
- NVT_LOG("Update firmware success! <%ld us>\n",
- (long) ktime_us_delta(nvt_spi_end, nvt_spi_start));
- /* Get FW Info */
- ret = nvt_spi_get_fw_info();
- if (ret)
- NVT_ERR("nvt_get_fw_info failed. (%d)\n", ret);
- download_fail:
- if (!IS_ERR_OR_NULL(nvt_spi_bin_map)) {
- kfree(nvt_spi_bin_map);
- nvt_spi_bin_map = NULL;
- }
- nvt_spi_update_firmware_release();
- request_firmware_fail:
- return ret;
- }
- /*
- *******************************************************
- * Description:
- * Novatek touchscreen update firmware when booting
- * function.
- *
- * return:
- * n.a.
- ******************************************************
- */
- void nvt_spi_update_firmware_work(struct work_struct *work)
- {
- struct nvt_spi_data_t *ts = nvt_spi_data;
- mutex_lock(&ts->lock);
- nvt_spi_update_firmware(NVT_SPI_BOOT_UPDATE_FIRMWARE_NAME);
- mutex_unlock(&ts->lock);
- }
- #endif
- #endif
|