| /* drivers/mtd/mtdadapt.c |
| * |
| * Mtd api adapt driver for nand&nor. |
| * |
| * Copyright (c) 2018 ZTE Ltd. |
| * |
| * This software is licensed under the terms of the GNU General Public |
| * License version 2, as published by the Free Software Foundation, and |
| * may be copied, distributed, and modified under those terms. |
| * |
| * 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. |
| * |
| */ |
| |
| #include <linux/slab.h> |
| #include <linux/kernel.h> |
| #include <linux/mtd/mtd.h> |
| #include <linux/module.h> |
| #include <linux/soc/zte/otp/otp_zx.h> |
| |
| #define READ_ZLOADER_FLAG_SIZE 0x800 |
| #define WRITE_ZLOADER_FLAG_SIZE 0x3000 |
| |
| |
| extern struct mtd_info *mtd_fota; |
| extern int g_zload_read_only_flag; |
| extern char *nor_cmdline; |
| unsigned char nor_flag = 0; |
| |
| #ifndef USE_CPPS_KO |
| extern unsigned int zOss_NvItemRead(unsigned int NvItemID, unsigned char *NvItemData, unsigned int NvItemLen); |
| extern unsigned int zOss_NvItemWrite(unsigned int NvItemID, unsigned char *NvItemData, unsigned int NvItemLen); |
| #endif |
| |
| /*zdd need modify*/ |
| int zDrvNand_ChangeNvrAttr(unsigned int rw ) |
| { |
| int ret = 0; |
| // ret = nand_nv_mid_r_set_to_rw(rw); |
| return ret; |
| } |
| EXPORT_SYMBOL(zDrvNand_ChangeNvrAttr); |
| |
| /* |
| * nv read interface. |
| * dwstart: nv addr to read |
| * dwLen: length of nv to read |
| * to: memory addr |
| */ |
| int zDrvNand_Read(unsigned int dwStart, unsigned int dwLen, unsigned char* to) |
| { |
| int ret = 0; |
| |
| #ifdef USE_CPPS_KO |
| ret = cpps_callbacks.zOss_NvItemRead(dwStart, to, dwLen); |
| #else |
| ret = zOss_NvItemRead(dwStart, to, dwLen); |
| #endif |
| |
| return ret; |
| } |
| EXPORT_SYMBOL(zDrvNand_Read); |
| |
| /* |
| * nv write interface. |
| * dwstart: nv addr to program |
| * dwLen: length of nv to program |
| * from: memory addr |
| */ |
| int zDrvNand_Program(unsigned int dwStart, unsigned int dwLen, unsigned char* from) |
| { |
| int ret = 0; |
| |
| #ifdef USE_CPPS_KO |
| ret = cpps_callbacks.zOss_NvItemWrite(dwStart,from, dwLen); |
| #else |
| ret = zOss_NvItemWrite(dwStart,from, dwLen); |
| #endif |
| |
| return ret; |
| } |
| EXPORT_SYMBOL(zDrvNand_Program); |
| |
| /*zdd need modify*/ |
| int zDrvNand_SmsRead(unsigned int dwStart, unsigned int dwLen, unsigned char* to) |
| { |
| int ret = 0; |
| |
| //ret = zftl_wrapper_read((char *)"sms", dwStart, dwLen, to); |
| |
| return ret; |
| } |
| |
| /*zdd need modify*/ |
| int zDrvNand_SmsProgram(unsigned int dwStart, unsigned int dwLen, unsigned char* from) |
| { |
| int ret = 0; |
| |
| //ret = zftl_wrapper_write((unsigned char *)"sms", dwStart, dwLen, from); |
| |
| return ret; |
| } |
| |
| /*zdd need modify*/ |
| int zDrvNand_SimNvRead(unsigned int dwStart, unsigned int dwLen, unsigned char* to) |
| { |
| int ret = 0; |
| #if 0//fyi |
| NAND_LOCK |
| nand_clk_gate(SYSCLK_ENABLE); |
| ret = nand_simnv_read(dwStart, dwLen, to); |
| nand_clk_gate(SYSCLK_DISABLE); |
| NAND_UNLOCK |
| |
| if(ret == -1) |
| { |
| zftl_res = 1; |
| zDrvNand_SetSimNvFlag(dwStart);/*ECC REBOOT*/ |
| zftl_res = 0; |
| } |
| #endif |
| //ret = zftl_wrapper_read((unsigned char *)"simnv", dwStart, dwLen, to); |
| |
| return ret; |
| } |
| |
| /*zdd need modify*/ |
| int zDrvNand_SimNvProgram(unsigned int dwStart, unsigned int dwLen, unsigned char* from) |
| { |
| int ret = 0; |
| #if 0//fyi |
| NAND_LOCK |
| nand_clk_gate(SYSCLK_ENABLE); |
| ret = nand_simnv_program(dwStart, dwLen, from); |
| nand_clk_gate(SYSCLK_DISABLE); |
| NAND_UNLOCK |
| if(ret == -1) |
| { |
| zftl_res = 1; |
| zDrvNand_SetSimNvFlag(dwStart);/*ECC REBOOT*/ |
| zftl_res = 0; |
| } |
| #endif |
| //ret = zftl_wrapper_write((unsigned char *)"simnv", dwStart, dwLen, from); |
| |
| return ret; |
| } |
| |
| /*zdd need modify*/ |
| int zDrvNand_SimNvFacRead(unsigned int dwStart, unsigned int dwLen, unsigned char* to) |
| { |
| int ret = 0; |
| #if 0//fyi |
| NAND_LOCK |
| nand_clk_gate(SYSCLK_ENABLE); |
| ret = nand_simnvfac_read(dwStart, dwLen, to); |
| nand_clk_gate(SYSCLK_DISABLE); |
| NAND_UNLOCK |
| #endif |
| //ret = zftl_wrapper_read((unsigned char *)"simnvfac", dwStart, dwLen, to); |
| |
| return ret; |
| } |
| |
| /*zdd need modify*/ |
| int zDrvNand_SimNvFacProgram(unsigned int dwStart, unsigned int dwLen, unsigned char* from) |
| { |
| int ret = 0; |
| #if 0//fyi |
| NAND_LOCK |
| nand_clk_gate(SYSCLK_ENABLE); |
| ret = nand_simnvfac_program(dwStart, dwLen, from); |
| nand_clk_gate(SYSCLK_DISABLE); |
| NAND_UNLOCK |
| #endif |
| //ret = zftl_wrapper_write((unsigned char *)"simnvfac", dwStart, dwLen, from); |
| |
| return ret; |
| } |
| |
| /*zdd need modify*/ |
| int zDrvNand_NvRwEccMake(unsigned int dwStart, unsigned int dwLen) |
| { |
| char buffer[2048]; |
| |
| //if( dwStart >= NVRW_SIZE||dwStart < 0 || (dwStart +dwLen)> NVRW_SIZE|| dwLen > 2048) |
| // return -1; |
| //fyi nand_nvrw_mid_ecc_make(dwStart,dwLen,buffer); |
| return 0; |
| } |
| EXPORT_SYMBOL(zDrvNand_NvRwEccMake); |
| |
| /*zdd need modify*/ |
| int zDrvNand_EccMake(unsigned char* partName,unsigned int dwStart, unsigned int dwLen) |
| { |
| return 0; |
| } |
| EXPORT_SYMBOL(zDrvNand_EccMake); |
| |
| /* |
| * get the bootflag from flash. |
| * return: 0, dl off 1, dl on |
| */ |
| unsigned int zDrvNand_ReadBootflag( void ) |
| { |
| unsigned int bootflag = 0; |
| |
| char value = 0; |
| int retlen = 0; |
| |
| unsigned char *buffer = kzalloc(READ_ZLOADER_FLAG_SIZE,GFP_KERNEL); |
| if( buffer == NULL ) |
| return -1; |
| |
| if(nor_cmdline != NULL) |
| { |
| if (!strcmp(nor_cmdline, "1")) |
| { |
| nor_flag = 1; |
| printk("----------EnhancedSecurity---------\n"); |
| } |
| } |
| if(1 == nor_flag) |
| { |
| #ifndef CONFIG_SPI_ZXIC_NOR |
| |
| if(nor_read(0, 256, buffer)) |
| { |
| kfree(buffer); |
| return 1; |
| } |
| memcpy(&value, buffer+2, 1); |
| bootflag = value; |
| |
| if( bootflag == 0x5a) |
| { |
| bootflag = 1; |
| } |
| else |
| { |
| bootflag = 0; |
| } |
| kfree(buffer); |
| #endif |
| } |
| else |
| { |
| if(mtd_read(mtd_fota,0,READ_ZLOADER_FLAG_SIZE,&retlen,buffer))/* BOOTFLAGÔÚnandµÄµÚ20~27×Ö½Ú */ |
| { |
| kfree(buffer); |
| return 1; |
| } |
| memcpy(&value, buffer+2, 1); |
| bootflag = value; |
| |
| if( bootflag == 0x5a) |
| { |
| bootflag = 1; |
| } |
| else |
| { |
| bootflag = 0; |
| } |
| kfree(buffer); |
| |
| } |
| |
| |
| return bootflag; |
| } |
| EXPORT_SYMBOL(zDrvNand_ReadBootflag); |
| |
| /* |
| * write the bootflag to flash. |
| * flag: 0,dl off else dl on |
| */ |
| unsigned int zDrvNand_WriteBootflag(unsigned int flag) |
| { |
| |
| unsigned int ret = 0; |
| char value = 0; |
| int bootflag = 0; |
| int retlen = 0; |
| struct erase_info ei; |
| |
| if(nor_cmdline != NULL) |
| { |
| if (!strcmp(nor_cmdline, "1")) |
| { |
| nor_flag = 1; |
| printk("----------EnhancedSecurity---------\n"); |
| }else{ |
| printk("----------normal---------\n"); |
| } |
| }else{ |
| printk("----------nor cmdline is null!---------\n"); |
| } |
| |
| if(1 == nor_flag) |
| { |
| #ifndef CONFIG_SPI_ZXIC_NOR |
| |
| unsigned char *buffer = kmalloc(0x10000, GFP_KERNEL); |
| |
| if( buffer == NULL ) |
| return -1; |
| |
| if(nor_read(0,0x10000,buffer)) |
| { |
| kfree(buffer); |
| return -1; |
| } |
| if(flag == 0 ) |
| { |
| bootflag = 0x00; |
| memset(&value, bootflag, 1); |
| } |
| else |
| { |
| bootflag = 0x5a; |
| memset(&value, bootflag, 1); |
| } |
| |
| memcpy(buffer+2, &value, 1); |
| |
| ret = nor_erase(0); |
| ret = nor_write(0,0x10000,buffer); |
| kfree(buffer); |
| #endif |
| } |
| else |
| { |
| unsigned char *buffer = kzalloc(WRITE_ZLOADER_FLAG_SIZE,GFP_KERNEL); |
| |
| if( buffer == NULL ) |
| return -1; |
| |
| if(mtd_read(mtd_fota,0,WRITE_ZLOADER_FLAG_SIZE,&retlen,buffer))/* BOOTFLAGÔÚnandµÄµÚ20~27×Ö½Ú */ |
| { |
| kfree(buffer); |
| return -1; |
| } |
| if(flag == 0 ) |
| { |
| bootflag = 0x00; |
| memset(&value, bootflag, 1); |
| } |
| else |
| { |
| bootflag = 0x5a; |
| memset(&value, bootflag, 1); |
| } |
| |
| memcpy(buffer+2, &value, 1); |
| memset(&ei, 0, sizeof(struct erase_info)); |
| ei.mtd = mtd_fota; |
| ei.addr = 0; |
| ei.len = mtd_fota->erasesize; |
| g_zload_read_only_flag = 1; |
| ret = mtd_erase(mtd_fota, &ei); /*²Á³ýµÚÒ»¿é*/ |
| ret = mtd_write(mtd_fota,0,WRITE_ZLOADER_FLAG_SIZE,&retlen,buffer); |
| g_zload_read_only_flag = 0; |
| kfree(buffer); |
| |
| } |
| |
| return 0; |
| |
| } |
| EXPORT_SYMBOL(zDrvNand_WriteBootflag); |
| |
| /* |
| * get the usbtimeout flag from flash. |
| * return: should be 1~10 |
| */ |
| unsigned int zDrvNand_ReadUsbtimeout( void ) |
| { |
| |
| unsigned int usbtimeout = 0; |
| char value = 0; |
| int retlen = 0; |
| |
| unsigned char *buffer = kzalloc(READ_ZLOADER_FLAG_SIZE,GFP_KERNEL); |
| if( buffer == NULL ) |
| return -1; |
| |
| if(mtd_read(mtd_fota,0,READ_ZLOADER_FLAG_SIZE,&retlen,buffer))/* BOOTFLAGÔÚnandµÄµÚ20~27×Ö½Ú */ |
| { |
| kfree(buffer); |
| return -1; |
| } |
| memcpy(&value, buffer+3, 1); |
| usbtimeout = value; |
| |
| kfree(buffer); |
| return usbtimeout; |
| |
| } |
| EXPORT_SYMBOL(zDrvNand_ReadUsbtimeout); |
| |
| /* |
| * write the usbtimeout flag to flash. |
| * flag: should be 1~10 |
| */ |
| unsigned int zDrvNand_WriteUsbtimeout( unsigned int flag ) |
| { |
| |
| unsigned int ret = 0; |
| uint8_t oob[256]; |
| int i =0; |
| int times = 0; |
| int retlen = 0; |
| char value = 0; |
| struct erase_info ei; |
| |
| unsigned char *buffer = kzalloc(WRITE_ZLOADER_FLAG_SIZE,GFP_KERNEL); /* ZLOADERºÍ·ÖÇø±í¹²8192BYTES */ |
| |
| if( buffer == NULL ) |
| return -1; |
| |
| if(mtd_read(mtd_fota,0,WRITE_ZLOADER_FLAG_SIZE,&retlen,buffer))/* BOOTFLAGÔÚnandµÄµÚ20~27×Ö½Ú */ |
| { |
| kfree(buffer); |
| return -1; |
| } |
| |
| memset(&value, flag, 1); |
| memcpy(buffer+3, &value, 1); |
| |
| memset(&ei, 0, sizeof(struct erase_info)); |
| ei.mtd = mtd_fota; |
| ei.addr = 0; |
| ei.len = mtd_fota->erasesize; |
| g_zload_read_only_flag = 1; |
| ret = mtd_erase(mtd_fota, &ei); /*²Á³ýµÚÒ»¿é*/ |
| ret = mtd_write(mtd_fota,0,WRITE_ZLOADER_FLAG_SIZE,&retlen,buffer); |
| g_zload_read_only_flag = 0; |
| kfree(buffer); |
| |
| return ret; |
| } |
| EXPORT_SYMBOL(zDrvNand_WriteUsbtimeout); |
| |