blob: 1cc4218f4c8d82418546455913a747d3a48b64fc [file] [log] [blame]
/* 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);