Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/sun-nontendocm-kernel.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormadmonkey <madfkingmonkey@gmail.com>2018-02-27 19:54:48 +0300
committermadmonkey <madfkingmonkey@gmail.com>2018-02-27 19:54:48 +0300
commite2d264afda6ba9ec1d37697db7b416dcb59e5bf6 (patch)
tree8339e29761e70d57eeafb97cef5bb5ac408edfb9
parent2aacafac50fc547a326a739f6828a91b37381dd2 (diff)
raw nand writing
-rw-r--r--drivers/block/nand/nfd/nand_blk.c283
-rw-r--r--drivers/block/nand/nfd/nand_dev.c8
-rw-r--r--drivers/block/nand/nfd/nand_osal_for_linux.c6
-rw-r--r--drivers/block/nand/nfd/nand_ota_burn.c2
4 files changed, 281 insertions, 18 deletions
diff --git a/drivers/block/nand/nfd/nand_blk.c b/drivers/block/nand/nfd/nand_blk.c
index 867a0fb9..31727710 100644
--- a/drivers/block/nand/nfd/nand_blk.c
+++ b/drivers/block/nand/nfd/nand_blk.c
@@ -19,7 +19,9 @@ static unsigned int dragonboard_test_flag = 0;
struct burn_param_t{
void* buffer;
- long length;
+ long length;
+ long offset;
+ long unused;
};
/*****************************************************************************/
@@ -128,7 +130,7 @@ int end_time(int data,int time,int par)
{
if(debug_data != data)
return -1;
-
+
do_gettimeofday(&tpend);
timeuse = 1000*(tpend.tv_sec-tpstart.tv_sec)*1000+(tpend.tv_usec-tpstart.tv_usec);
if(timeuse > time)
@@ -187,7 +189,7 @@ static int do_blktrans_request(struct nand_blk_ops *tr,struct nand_blk_dev *dev,
goto request_exit;
case WRITE:
-
+
rq_flush_dcache_pages(req);
@@ -203,7 +205,7 @@ static int do_blktrans_request(struct nand_blk_ops *tr,struct nand_blk_dev *dev,
}
request_exit:
-
+
return ret;
}
@@ -372,19 +374,250 @@ static int nand_release(struct gendisk *disk, fmode_t mode)
#define ENABLE_WRITE _IO('V',1)
#define DISABLE_READ _IO('V',2)
#define ENABLE_READ _IO('V',3)
-#define DRAGON_BOARD_TEST _IO('V',55)
-#define BLKBURNBOOT0 _IO('v',127)
-#define BLKBURNBOOT1 _IO('v',128)
+#define DRAGON_BOARD_TEST _IO('V',55)
+
+#define OOB_BUF_SIZE 64
+
+enum
+{
+ hakchi_test=_IO('v',121),
+ BLKBURNBOOT0=_IO('v',122),
+ BLKBURNBOOT1=_IO('v',123),
+ phy_read=_IO('v',124),
+ phy_write=_IO('v',125),
+ read_boot0=_IO('v',126),
+};
+
+extern int NAND_PhysicLock(void);
+extern int NAND_PhysicUnLock(void);
+
+extern __u32 NAND_GetPageSize(void);
+extern __u32 NAND_GetPageCntPerBlk(void);
+extern __u32 NAND_GetBlkCntPerChip(void);
+extern __u32 NAND_GetChipCnt(void);
+extern __s32 NAND_GetBlkCntOfDie(void);
+
+extern int NAND_ReadBoot0(unsigned int length,void*buf);
+
+static uint NAND_UbootSimpleRead(uint start, uint blocks, void* buffer)
+{
+ __u32 i, k, block;
+ __u32 page_size, pages_per_block, block_size, block_count;
+ unsigned char oob_buf[OOB_BUF_SIZE];
+ struct boot_physical_param para;
+
+ for (i = 0; i < 32; i++)
+ oob_buf[i] = 0xff;
+
+ page_size = NAND_GetPageSize();
+ pages_per_block = NAND_GetPageCntPerBlk();
+ block_count = NAND_GetBlkCntPerChip();
+ block_size = page_size * pages_per_block;
+
+ block = 0;
+ for (i = start; i < block_count && block < blocks; i++)
+ {
+ for (k = 0; k < pages_per_block; k++)
+ {
+ para.chip = 0;
+ para.block = i;
+ para.page = k;
+ para.mainbuf = (void *) ((__u32)buffer + block * block_size + k * page_size);
+ para.oobbuf = oob_buf;
+
+ if (PHY_SimpleRead(&para) < 0 || oob_buf[0] != 0xff)
+ {
+ nand_dbg_err("Warning. Fail in read page %d in block %d.\n", k, i);
+ // retry to read data block from next NAND block
+ block--;
+ break;
+ }
+ }
+
+ ++block;
+ }
+
+ if (block < blocks)
+ return 0;
+
+ return blocks;
+}
+
+static uint NAND_UbootSimpleWrite(uint start, uint blocks, void *buffer)
+{
+ __u32 i, k, block;
+ __u32 page_size, pages_per_block, block_size, block_count;
+ unsigned char oob_buf[OOB_BUF_SIZE];
+ struct boot_physical_param para;
+
+ for (i = 0; i < 32; i++)
+ oob_buf[i] = 0xff;
+
+ page_size = NAND_GetPageSize();
+ pages_per_block = NAND_GetPageCntPerBlk();
+ block_count = NAND_GetBlkCntPerChip();
+ block_size = page_size * pages_per_block;
+
+ block = 0;
+ for (i = start; i < block_count && block < blocks; i++)
+ {
+ para.chip = 0;
+ para.block = i;
+ if (PHY_SimpleErase(&para) < 0)
+ {
+ nand_dbg_err("Fail in erasing block %d.\n", i);
+ //mark_bad_block(para.chip, para.block);
+ continue;
+ }
+
+ for (k = 0; k < pages_per_block; k++)
+ {
+ para.chip = 0;
+ para.block = i;
+ para.page = k;
+ para.mainbuf = (void *) ((__u32)buffer + block * block_size + k * page_size);
+ para.oobbuf = oob_buf;
+
+ if (PHY_SimpleWrite(&para) < 0)
+ {
+ nand_dbg_err("Warning. Fail in write page %d in block %d.\n", k, i);
+ //mark_bad_block(para.chip, para.block);
+ // retry to write data block on next NAND block
+ block--;
+ break;
+ }
+ }
+
+ ++block;
+ }
+
+ if (block < blocks)
+ return 0;
+
+ return blocks;
+}
+
+struct hakchi_nandinfo
+{
+ char str[8];
+ __u32 size;
+ __u32 page_size;
+ __u32 pages_per_block;
+ __u32 block_count;
+};
+
+static int NAND_ioctlRW(unsigned int cmd,unsigned int offset,unsigned int length,void*buf)
+{
+ void*buffer;
+ struct hakchi_nandinfo htn;
+ __u32 block_size;
+
+ if(length==0)
+ {
+ buffer=0;
+ }
+ else
+ {
+ buffer=(void*)kmalloc(length,GFP_KERNEL);
+ if(buffer==NULL)
+ {
+ nand_dbg_err("no memory!\n");
+ return -1;
+ }
+ }
+
+ NAND_PhysicLock();
+ PHY_WaitAllRbReady();
+
+ htn.page_size=NAND_GetPageSize();
+ htn.pages_per_block=NAND_GetPageCntPerBlk();
+ block_size=htn.page_size*htn.pages_per_block;
+
+ switch(cmd)
+ {
+ case hakchi_test:
+ htn.block_count=NAND_GetBlkCntPerChip();
+ memcpy(htn.str,"hakchi",7);
+ htn.str[7]=0;
+ htn.size=sizeof(htn);
+ if(copy_to_user(buf,&htn,sizeof(htn)))
+ {
+ nand_dbg_err("copy_to_user error!\n");
+ goto error;
+ }
+ break;
+
+ case phy_read:
+ if((length%block_size)||(offset%block_size))
+ {
+ nand_dbg_err("phy_read: requested %x at %x, block_size %x\n",length,offset,block_size);
+ goto error;
+ }
+ memset(buffer,0,length);
+ if(NAND_UbootSimpleRead(offset/block_size,length/block_size,buffer)!=(length/block_size))
+ {
+ nand_dbg_err("phy_read: requested %x at %x, cannot read\n",length,offset);
+ goto error;
+ }
+ if(copy_to_user(buf,buffer,length))
+ {
+ nand_dbg_err("copy_to_user error!\n");
+ goto error;
+ }
+ break;
+
+ case phy_write:
+ if(copy_from_user(buffer,(const void*)buf,length))
+ {
+ nand_dbg_err("copy_from_user error!\n");
+ goto error;
+ }
+ if((length%block_size)||(offset%block_size))
+ {
+ nand_dbg_err("phy_write: requested %x at %x, block_size %x\n",length,offset,block_size);
+ goto error;
+ }
+ if(NAND_UbootSimpleWrite(offset/block_size,length/block_size,buffer)!=(length/block_size))
+ {
+ nand_dbg_err("phy_write: requested %x at %x, cannot write\n",length,offset);
+ goto error;
+ }
+ break;
+
+ case read_boot0:
+ memset(buffer,0,length);
+ if(NAND_ReadBoot0(length,buffer))
+ {
+ nand_dbg_err("NAND_ReadBoot0() error!\n");
+ goto error;
+ }
+ if(copy_to_user(buf,buffer,length))
+ {
+ nand_dbg_err("copy_to_user error!\n");
+ goto error;
+ }
+ break;
+ }
+
+ kfree(buffer);
+ PHY_WaitAllRbReady();
+ NAND_PhysicUnLock();
+ return 0;
+
+error:
+ kfree(buffer);
+ PHY_WaitAllRbReady();
+ NAND_PhysicUnLock();
+ return -1;
+}
static int nand_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
{
struct nand_blk_dev *dev = bdev->bd_disk->private_data;
struct nand_blk_ops *nandr = dev->nandr;
- struct burn_param_t *burn_param;
+ struct burn_param_t burn_param;
int ret=0;
- burn_param = (struct burn_param_t *)arg;
-
switch (cmd) {
case BLKFLSBUF:
nand_dbg_err("BLKFLSBUF called!\n");
@@ -435,29 +668,48 @@ static int nand_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
return 0;
case BLKBURNBOOT0:
+ if (copy_from_user(&burn_param, (const void*)arg, sizeof (struct burn_param_t)))
+ return -EFAULT;
if (0 == down_trylock(&(nandr->nand_ops_mutex)))
{
IS_IDLE = 0;
- ret = NAND_BurnBoot0(burn_param->length, burn_param->buffer);
+ ret = NAND_BurnBoot0(burn_param.length, burn_param.buffer);
up(&(nandr->nand_ops_mutex));
IS_IDLE = 1;
}
return ret;
case BLKBURNBOOT1:
+ if (copy_from_user(&burn_param, (const void*)arg, sizeof (struct burn_param_t)))
+ return -EFAULT;
if (0 == down_trylock(&(nandr->nand_ops_mutex)))
{
IS_IDLE = 0;
- ret = NAND_BurnBoot1(burn_param->length, burn_param->buffer);
+ ret = NAND_BurnBoot1(burn_param.length, burn_param.buffer);
+ up(&(nandr->nand_ops_mutex));
+ IS_IDLE = 1;
+ }
+ return ret;
+
+ case phy_read:
+ case phy_write:
+ case read_boot0:
+ if (copy_from_user(&burn_param, (const void*)arg, sizeof (struct burn_param_t)))
+ return -EFAULT;
+
+ if (0 == down_trylock(&(nandr->nand_ops_mutex)))
+ {
+ IS_IDLE = 0;
+ ret = NAND_ioctlRW(cmd, burn_param.offset, burn_param.length, burn_param.buffer);
up(&(nandr->nand_ops_mutex));
IS_IDLE = 1;
}
return ret;
case DRAGON_BOARD_TEST:
-
+
if (0 == down_trylock(&(nandr->nand_ops_mutex)))
{
IS_IDLE = 0;
@@ -694,7 +946,10 @@ added:
gd->first_minor = (dev->devnum) << tr->minorbits;
gd->fops = &nand_blktrans_ops;
- snprintf(gd->disk_name, sizeof(gd->disk_name),"%s%c", tr->name, (tr->minorbits?'a':'0') + dev->devnum);
+ if(dev->devnum>0)
+ snprintf(gd->disk_name, sizeof(gd->disk_name),"%s%c", tr->name, (tr->minorbits?'a':'0') + dev->devnum-1);
+ else
+ snprintf(gd->disk_name, sizeof(gd->disk_name),"%s", tr->name);
/* 2.5 has capacity in units of 512 bytes while still
having BLOCK_SIZE_BITS set to 10. Just to keep us amused. */
set_capacity(gd, dev->size);
diff --git a/drivers/block/nand/nfd/nand_dev.c b/drivers/block/nand/nfd/nand_dev.c
index 6abfd364..c45849b2 100644
--- a/drivers/block/nand/nfd/nand_dev.c
+++ b/drivers/block/nand/nfd/nand_dev.c
@@ -325,6 +325,10 @@ int add_nand(struct nand_blk_ops *tr, struct _nand_phy_partition* phy_partition)
//nand_dbg_err("disk->size %x\n",disk[i].size);
}
+ if(PartitionNO == 0)
+ {
+ dev_num = -1;
+ }
head_disk = get_disk_from_phy_partition(phy_partition);
for(i=0;i<MAX_PART_COUNT_PER_FTL;i++)
{
@@ -365,11 +369,13 @@ int add_nand(struct nand_blk_ops *tr, struct _nand_phy_partition* phy_partition)
memcpy(nand_dev->name,disk->name,strlen(disk->name)+1);
nand_dbg_err("nand_dev add %s\n",nand_dev->name);
+#if 0
if((PartitionNO == 0) && (i==0))
{
dev_num = -1;
}
else
+#endif
{
dev_num++;
nand_dev->nbd.devnum = dev_num;
@@ -402,7 +408,7 @@ int add_nand_for_dragonboard_test(struct nand_blk_ops *tr)
nand_dev->nbd.size = 1024*4096;
nand_dev->nbd.priv = (void*)nand_dev;
-
+
dev_num = 0;
nand_dev->nbd.devnum = dev_num;
printk("befor add nand blktrans dev\n");
diff --git a/drivers/block/nand/nfd/nand_osal_for_linux.c b/drivers/block/nand/nfd/nand_osal_for_linux.c
index c10fed90..60917449 100644
--- a/drivers/block/nand/nfd/nand_osal_for_linux.c
+++ b/drivers/block/nand/nfd/nand_osal_for_linux.c
@@ -1306,7 +1306,7 @@ void NAND_Print_Version(void)
int NAND_get_storagetype(void)
{
-#if 1
+#if 0
script_item_value_type_e script_ret;
script_item_u storage_type;
@@ -1320,7 +1320,7 @@ int NAND_get_storagetype(void)
return (int)storage_type.val;
#else
- return 1;
+ return -1;
#endif
}
@@ -1412,4 +1412,4 @@ int NAND_Get_Secure_Mode(void)
sys_mode = 0;
return sys_mode;
-} \ No newline at end of file
+}
diff --git a/drivers/block/nand/nfd/nand_ota_burn.c b/drivers/block/nand/nfd/nand_ota_burn.c
index d6cb4a66..d66632e1 100644
--- a/drivers/block/nand/nfd/nand_ota_burn.c
+++ b/drivers/block/nand/nfd/nand_ota_burn.c
@@ -521,12 +521,14 @@ int NAND_BurnBoot0(unsigned int length, void *buf)
goto error;
}
+#if 0
if ( get_dram_para(buffer) ) {
debug("get dram para error\n");
goto error;
} else {
debug("get dram para ok\n");
}
+#endif
get_nand_para(buffer);
debug("get nand para ok\n");
gen_check_sum(buffer);