283 lines
8.2 KiB
C
283 lines
8.2 KiB
C
/*
|
|
* nand_class.c for SUNXI NAND .
|
|
*
|
|
* Copyright (C) 2016 Allwinner.
|
|
*
|
|
*
|
|
* This file is licensed under the terms of the GNU General Public
|
|
* License version 2. This program is licensed "as is" without any
|
|
* warranty of any kind, whether express or implied.
|
|
*/
|
|
|
|
#include "nand_class.h"
|
|
|
|
/*****************************************************************************
|
|
*Name :
|
|
*Description :
|
|
*Parameter :
|
|
*Return :
|
|
*Note :
|
|
*****************************************************************************/
|
|
void obj_test_release(struct kobject *kobject)
|
|
{
|
|
nand_dbg_err("release");
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*Name :
|
|
*Description :
|
|
*Parameter :
|
|
*Return :
|
|
*Note :
|
|
*****************************************************************************/
|
|
static ssize_t nand_test_show(struct kobject *kobject, struct attribute *attr,
|
|
char *buf)
|
|
{
|
|
ssize_t count = 0;
|
|
struct nand_kobject *nand_kobj;
|
|
|
|
nand_kobj = (struct nand_kobject *)kobject;
|
|
print_nftl_zone(nand_kobj->nftl_blk->nftl_zone);
|
|
count = sprintf(buf, "%i", g_iShowVar);
|
|
|
|
return count;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*Name :
|
|
*Description :receive testcase num from echo command
|
|
*Parameter :
|
|
*Return :
|
|
*Note :
|
|
*****************************************************************************/
|
|
static ssize_t nand_test_store(struct kobject *kobject, struct attribute *attr,
|
|
const char *buf, size_t count)
|
|
{
|
|
int ret, i;
|
|
int argnum = 0;
|
|
char cmd[32] = { 0 };
|
|
unsigned int param0 = 0;
|
|
unsigned int param1 = 0;
|
|
unsigned int param2 = 0;
|
|
char param3[16] = { 0 };
|
|
char *tempbuf;
|
|
struct nand_kobject *nand_kobj;
|
|
|
|
nand_kobj = (struct nand_kobject *) kobject;
|
|
|
|
g_iShowVar = -1;
|
|
|
|
argnum =
|
|
sscanf(buf, "%s %u %u %u %s", cmd, ¶m0, ¶m1, ¶m2,
|
|
param3);
|
|
nand_dbg_err("argnum=%i, cmd=%s, param0=%u, param1=%u, param2=%u\n",
|
|
argnum, cmd, param0, param1, param2);
|
|
|
|
if (-1 == argnum) {
|
|
nand_dbg_err("cmd format err!");
|
|
g_iShowVar = -3;
|
|
goto NAND_TEST_STORE_EXIT;
|
|
}
|
|
|
|
if (strcmp(cmd, "help") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err("2016-10-24 19:48\n");
|
|
} else if (strcmp(cmd, "flush") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err(" flush\n");
|
|
mutex_lock(nand_kobj->nftl_blk->blk_lock);
|
|
ret =
|
|
nand_kobj->nftl_blk->flush_write_cache(nand_kobj->nftl_blk,
|
|
param0);
|
|
mutex_unlock(nand_kobj->nftl_blk->blk_lock);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "gcall") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err(" gcall\n");
|
|
mutex_lock(nand_kobj->nftl_blk->blk_lock);
|
|
ret = gc_all(nand_kobj->nftl_blk->nftl_zone);
|
|
mutex_unlock(nand_kobj->nftl_blk->blk_lock);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "gcone") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err(" gcone\n");
|
|
mutex_lock(nand_kobj->nftl_blk->blk_lock);
|
|
ret = gc_one(nand_kobj->nftl_blk->nftl_zone);
|
|
mutex_unlock(nand_kobj->nftl_blk->blk_lock);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "priogc") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err(" priogc\n");
|
|
mutex_lock(nand_kobj->nftl_blk->blk_lock);
|
|
ret =
|
|
prio_gc_one(nand_kobj->nftl_blk->nftl_zone, param0, param1);
|
|
mutex_unlock(nand_kobj->nftl_blk->blk_lock);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "test") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err(" test\n");
|
|
mutex_lock(nand_kobj->nftl_blk->blk_lock);
|
|
ret =
|
|
nftl_set_zone_test((void *)nand_kobj->nftl_blk->nftl_zone,
|
|
param0);
|
|
mutex_unlock(nand_kobj->nftl_blk->blk_lock);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "showall") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err(" show all\n");
|
|
print_free_list(nand_kobj->nftl_blk->nftl_zone);
|
|
print_block_invalid_list(nand_kobj->nftl_blk->nftl_zone);
|
|
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "showinfo") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err(" show info\n");
|
|
print_nftl_zone(nand_kobj->nftl_blk->nftl_zone);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "blkdebug") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err(" blk debug\n");
|
|
debug_data = param0;
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "smart") == 0) {
|
|
nand_dbg_err("nand debug cmd:\n");
|
|
nand_dbg_err("smart info\n");
|
|
print_smart(nand_kobj->nftl_blk->nftl_zone);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "read1") == 0) {
|
|
nand_dbg_err("nand read1 cmd:\n");
|
|
nand_dbg_phy_read(param0, param1, param2);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "read2") == 0) {
|
|
nand_dbg_err("nand read2 cmd:\n");
|
|
nand_dbg_zone_phy_read(nand_kobj->nftl_blk->nftl_zone, param0,
|
|
param1);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "erase1") == 0) {
|
|
nand_dbg_err("nand erase1 cmd:\n");
|
|
nand_dbg_phy_erase(param0, param1);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "erase2") == 0) {
|
|
nand_dbg_err("nand erase2 cmd:\n");
|
|
nand_dbg_zone_erase(nand_kobj->nftl_blk->nftl_zone, param0,
|
|
param1);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "erase3") == 0) {
|
|
nand_dbg_err("nand erase3 cmd:\n");
|
|
nand_dbg_single_phy_erase(param0, param1);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "write1") == 0) {
|
|
nand_dbg_err("nand read1 cmd:\n");
|
|
nand_dbg_phy_write(param0, param1, param2);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "write2") == 0) {
|
|
nand_dbg_err("nand read2 cmd:\n");
|
|
nand_dbg_zone_phy_write(nand_kobj->nftl_blk->nftl_zone, param0,
|
|
param1);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "checktable") == 0) {
|
|
nand_dbg_err("nand read2 cmd:\n");
|
|
|
|
mutex_lock(nand_kobj->nftl_blk->blk_lock);
|
|
nand_check_table(nand_kobj->nftl_blk->nftl_zone);
|
|
mutex_unlock(nand_kobj->nftl_blk->blk_lock);
|
|
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "testspeed") == 0) {
|
|
nand_dbg_err("nand runtest cmd:\n");
|
|
udisk_test_speed(nand_kobj->nftl_blk);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "teststart") == 0) {
|
|
nand_dbg_err("nand runtest cmd:\n");
|
|
udisk_test_start(nand_kobj->nftl_blk);
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "teststop") == 0) {
|
|
nand_dbg_err("nand runtest cmd:\n");
|
|
udisk_test_stop();
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else if (strcmp(cmd, "readdev") == 0) {
|
|
nand_dbg_err("nand dev read\n");
|
|
if (param1 > 16) {
|
|
nand_dbg_err("max len is 16!\n");
|
|
goto NAND_TEST_STORE_EXIT;
|
|
}
|
|
mutex_lock(nand_kobj->nftl_blk->blk_lock);
|
|
|
|
tempbuf = kmalloc(8192, GFP_KERNEL);
|
|
_dev_nand_read2(param3, param0, param1, tempbuf);
|
|
for (i = 0; i < (param1 << 9); i += 4) {
|
|
nand_dbg_inf("%8x ", *((int *)&tempbuf[i]));
|
|
if (((i + 4) % 64) == 0)
|
|
nand_dbg_inf("\n");
|
|
|
|
}
|
|
kfree(tempbuf);
|
|
|
|
mutex_unlock(nand_kobj->nftl_blk->blk_lock);
|
|
|
|
goto NAND_TEST_STORE_EXIT;
|
|
} else {
|
|
nand_dbg_err("err, nand debug undefined cmd: %s\n", cmd);
|
|
}
|
|
|
|
NAND_TEST_STORE_EXIT:
|
|
return count;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*Name :
|
|
*Description :
|
|
*Parameter :
|
|
*Return :
|
|
*Note :
|
|
*****************************************************************************/
|
|
void udisk_test_speed(struct _nftl_blk *nftl_blk)
|
|
{
|
|
char *test_buf;
|
|
struct timeval tpstart, tpend;
|
|
unsigned int start_sector;
|
|
unsigned int len;
|
|
unsigned int i;
|
|
unsigned int sec;
|
|
int usec;
|
|
|
|
test_buf = kmalloc(0x100000, GFP_KERNEL);
|
|
|
|
do_gettimeofday(&tpstart);
|
|
|
|
start_sector = 0x32000;
|
|
len = 0x800;
|
|
for (i = 0; i < 500; i++) {
|
|
mutex_lock(nftl_blk->blk_lock);
|
|
_dev_nand_write2("UDISK", start_sector + i * len, len,
|
|
test_buf);
|
|
mutex_unlock(nftl_blk->blk_lock);
|
|
}
|
|
|
|
do_gettimeofday(&tpend);
|
|
|
|
sec = tpend.tv_sec - tpstart.tv_sec;
|
|
usec = tpend.tv_usec - tpstart.tv_usec;
|
|
|
|
nand_dbg_inf("write sec:%d usec:%d\n", sec, usec);
|
|
|
|
do_gettimeofday(&tpstart);
|
|
|
|
start_sector = 0x32000;
|
|
len = 0x800;
|
|
for (i = 0; i < 500; i++) {
|
|
mutex_lock(nftl_blk->blk_lock);
|
|
_dev_nand_read2("UDISK", start_sector + i * len, len, test_buf);
|
|
mutex_unlock(nftl_blk->blk_lock);
|
|
}
|
|
|
|
do_gettimeofday(&tpend);
|
|
|
|
sec = tpend.tv_sec - tpstart.tv_sec;
|
|
usec = tpend.tv_usec - tpstart.tv_usec;
|
|
|
|
nand_dbg_inf("read sec:%d usec:%d\n", sec, usec);
|
|
|
|
kfree(test_buf);
|
|
}
|