PageRenderTime 61ms CodeModel.GetById 22ms app.highlight 34ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/block/sun3i_nand/nandtest/nand_test.c

https://bitbucket.org/ndreys/linux-sunxi
C | 1292 lines | 937 code | 265 blank | 90 comment | 107 complexity | f931f3ab0b809dfc34b084e210e62260 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
   1/*
   2 * drivers/block/sun3i_nand/nandtest/nand_test.c
   3 *
   4 * (C) Copyright 2007-2012
   5 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
   6 *
   7 * This program is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU General Public License as
   9 * published by the Free Software Foundation; either version 2 of
  10 * the License, or (at your option) any later version.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20 * MA 02111-1307 USA
  21 */
  22
  23#include <linux/device.h>
  24#include <linux/module.h>
  25#include <linux/kernel.h>
  26#include <linux/init.h>
  27#include <linux/string.h>
  28#include <linux/sysfs.h>
  29#include <linux/stat.h>
  30#include <linux/module.h>
  31#include <linux/moduleparam.h>
  32#include <linux/ioport.h>
  33#include <linux/device.h>
  34#include <linux/interrupt.h>
  35#include <linux/delay.h>
  36#include <linux/err.h>
  37#include <linux/clk.h>
  38#include <linux/scatterlist.h>
  39#include <linux/platform_device.h>
  40#include <linux/dma-mapping.h>
  41#include <linux/cpufreq.h>
  42#include <linux/sched.h>
  43#include "../src/include/nand_type.h"
  44#include "../src/include/nand_drv_cfg.h"
  45#include "../src/include/nand_format.h"
  46#include "../src/include/nand_logic.h"
  47#include "../src/include/nand_oal.h"
  48#include "../src/include/nand_physic.h"
  49#include "../src/include/nand_scan.h"
  50#include "../src/include/nand_simple.h"
  51
  52#include "../nfd/nand_blk.h"
  53#include "../nfd/mbr.h"
  54
  55#include "nand_test.h"
  56
  57#ifdef CONFIG_SUN3I_NANDFLASH_TEST     //  open nand test module
  58
  59#define NAND_TEST  "[nand_test]:"
  60
  61#define RESULT_OK   (0)
  62#define RESULT_FAIL   (1)
  63
  64#define MAX_SECTORS       (100)         // max alloc buffer
  65#define BUFFER_SIZE       (512*MAX_SECTORS)
  66
  67static ssize_t nand_test_store(struct kobject *kobject,struct attribute *attr, const char *buf, size_t count);
  68static ssize_t nand_test_show(struct kobject *kobject,struct attribute *attr, char *buf);
  69
  70void obj_test_release(struct kobject *kobject);
  71
  72
  73
  74struct nand_test_card {
  75    u8    *buffer;
  76    u8    *scratch;
  77    unsigned int sector_cnt;
  78};
  79
  80struct nand_test_case {
  81    const char *name;
  82    int  sectors_cnt;
  83    int (*prepare)(struct nand_test_card *, int sectors_cnt);
  84    int (*run)(struct nand_test_card * );
  85    int (*cleanup)(struct nand_test_card *);
  86};
  87
  88struct attribute prompt_attr = {
  89    .name = "nand_test",
  90    .mode = S_IRWXUGO
  91};
  92
  93static struct attribute *def_attrs[] = {
  94    &prompt_attr,
  95    NULL
  96};
  97
  98
  99struct sysfs_ops obj_test_sysops =
 100{
 101    .show =  nand_test_show,
 102    .store = nand_test_store
 103};
 104
 105struct kobj_type ktype =
 106{
 107    .release = obj_test_release,
 108    .sysfs_ops=&obj_test_sysops,
 109    .default_attrs=def_attrs
 110};
 111
 112void obj_test_release(struct kobject *kobject)
 113{
 114    printk(NAND_TEST "release .\n");
 115}
 116
 117
 118
 119/* prepare buffer data for read and write*/
 120static int __nand_test_prepare(struct nand_test_card *test, int sector_cnt,int write)
 121{
 122    int i;
 123
 124    test->sector_cnt = sector_cnt;
 125
 126    if (write){
 127        memset(test->buffer, 0xDF, 512 * (sector_cnt) +4);
 128    }
 129    else {
 130        for (i = 0; i < 512 * (sector_cnt) + 4; i++){
 131            test->buffer[i] = i%256;
 132         }
 133    }
 134
 135    return 0;
 136}
 137
 138
 139static int nand_test_prepare_write(struct nand_test_card *test, int sector_cnt)
 140{
 141    return __nand_test_prepare(test, sector_cnt, 1);
 142}
 143
 144static int nand_test_prepare_read(struct nand_test_card *test, int sector_cnt)
 145{
 146    return __nand_test_prepare(test, sector_cnt, 0);
 147}
 148
 149
 150static int nand_test_prepare_pwm(struct nand_test_card *test, int sector_cnt)
 151{
 152    test->sector_cnt = sector_cnt;
 153    return 0;
 154}
 155
 156
 157/* read /write one sector with out verification*/
 158static int nand_test_simple_transfer(struct nand_test_card *test,
 159                                    unsigned dev_addr,unsigned start,
 160                                    unsigned nsector, int write)
 161{
 162    int ret;
 163    if (write){
 164
 165#ifndef NAND_CACHE_RW
 166        ret = LML_Write(start, nsector, test->buffer + dev_addr);
 167#else
 168        //printk("Ws %lu %lu \n",start, nsector);
 169        ret = NAND_CacheWrite(start, nsector, test->buffer + dev_addr);
 170#endif
 171        if(ret){
 172            return -EIO;
 173        }
 174        return 0;
 175        }
 176    else {
 177
 178#ifndef NAND_CACHE_RW
 179        LML_FlushPageCache();
 180        ret = LML_Read(start, nsector, test->buffer + dev_addr);
 181#else
 182        //printk("Rs %lu %lu \n",start, nsector);
 183        LML_FlushPageCache();
 184        ret = NAND_CacheRead(start, nsector, test->buffer + dev_addr);
 185#endif                                                  // read
 186
 187        if (ret){
 188            return -EIO;
 189        }
 190        return 0;
 191    }
 192}
 193
 194
 195/* read /write one or more sectors with verification*/
 196static int nand_test_transfer(struct nand_test_card *test,
 197                              unsigned dev_addr,unsigned start,
 198                              unsigned nsector, int write)
 199{
 200    int ret;
 201    int i;
 202
 203    if (!write){
 204        ret = nand_test_simple_transfer(test, 0, start, nsector, 1);  // write to sectors for read
 205        if (ret){
 206            return ret;
 207        }
 208        memset(test->buffer, 0, nsector * 512 +4);    // clean mem for read
 209    }
 210
 211    if ( ( ret = nand_test_simple_transfer(test, dev_addr, start, nsector, write ) ) ) {   // read or write
 212        return ret;
 213    }
 214    if(write){
 215        memset(test->buffer, 0, nsector * 512 + 4);    // clean mem for read
 216        ret = nand_test_simple_transfer(test, 0 , start, nsector, 0);   // read
 217        if (ret){
 218            return ret;
 219        }
 220        for(i  = 0; i < nsector * 512; i++){    // verify data
 221            if (test->buffer[i] != 0xDF){
 222                printk(KERN_INFO "[nand_test] Ttest->buffer[i] = %d, i = %d, dev_addr = %d, nsector = %d\n", test->buffer[i],  i, dev_addr,nsector);
 223                return RESULT_FAIL;
 224            }
 225        }
 226    }
 227    else {   //read
 228        for(i  = 0 + dev_addr; i < nsector * 512 + dev_addr ; i++){   // verify data
 229
 230            if (test->buffer[i] != (i-dev_addr)%256){
 231                printk(KERN_INFO "[nand_test] Ttest->buffer[i] = %d, i = %d, dev_addr = %d, nsector = %d\n", test->buffer[i],  i, dev_addr,nsector);
 232                return RESULT_FAIL;
 233            }
 234       }
 235    }
 236    return RESULT_OK;
 237}
 238
 239
 240
 241/* write one sector without verification*/
 242static int nand_test_single_write(struct nand_test_card *test)
 243{
 244    int ret;
 245
 246
 247    ret = nand_test_simple_transfer(test, 0, 0, test->sector_cnt,1);
 248
 249    if(ret){
 250        return ret;
 251    }
 252    return nand_test_simple_transfer(test, 0, DiskSize/2, test->sector_cnt, 1 );
 253
 254}
 255
 256/* read one sector without verification*/
 257static int nand_test_single_read(struct nand_test_card *test)
 258{
 259    int ret;
 260
 261    ret = nand_test_simple_transfer(test, 0, 0, test->sector_cnt,0);
 262    if(ret){
 263        return ret;
 264    }
 265    return nand_test_simple_transfer(test, 0, DiskSize/2, test->sector_cnt, 0);
 266}
 267
 268/* write one  sector with verification */
 269static int nand_test_verify_write(struct nand_test_card *test)
 270{
 271    return nand_test_transfer(test,  0, 1, test->sector_cnt, 1);
 272}
 273
 274/* read one  sector with verification */
 275static int nand_test_verify_read(struct nand_test_card *test)
 276{
 277    return nand_test_transfer(test,  0, 1, test->sector_cnt, 0);
 278}
 279
 280/* write multi sector with start sector num 5*/
 281static int nand_test_multi_write(struct nand_test_card *test)
 282{
 283    return nand_test_transfer(test,  0, 5, test->sector_cnt, 1);
 284}
 285
 286
 287/* write multi sector with start sector num 29*/
 288
 289static int nand_test_multi_read(struct nand_test_card *test)
 290{
 291    return nand_test_transfer(test,  0, 29, test->sector_cnt, 0);
 292}
 293
 294/* write from buffer+1, buffer+2, and buffer+3, where buffer is  4  bytes algin */
 295static int nand_test_align_write(struct nand_test_card *test)
 296{
 297    int ret;
 298    int i;
 299
 300    for (i = 1;i < 4;i++) {
 301        ret = nand_test_transfer(test,  i, 1, test->sector_cnt, 1);
 302    }
 303    return ret;
 304}
 305
 306
 307/* read to buffer+1, buffer+2, and buffer+3, where buffer is  4  bytes algin */
 308
 309static int nand_test_align_read(struct nand_test_card *test)
 310{
 311    int ret;
 312    int i;
 313
 314    for (i = 1;i < 4;i++) {
 315        ret = nand_test_transfer(test,  i, 1, test->sector_cnt, 0);
 316    }
 317    if (ret){
 318        return ret;
 319    }
 320
 321    return 0;
 322}
 323
 324/* write to incorrect sector num such as -1, DiskSize,  DiskSize +1 */
 325static int nand_test_negstart_write(struct nand_test_card *test)
 326{
 327    int ret;
 328
 329    /* start + sectnum > 0, start < 0*/
 330    ret = nand_test_simple_transfer(test,  0, -5 , 11, 1);
 331
 332    if (!ret){
 333        return RESULT_FAIL;
 334    }
 335    printk(NAND_TEST "start + sectnum > 0 pass\n");
 336
 337    /* start + sectnum < 0 , start < 0 */
 338    ret = nand_test_simple_transfer(test,  0, -62, 5, 1);
 339
 340    if (!ret){
 341        return RESULT_FAIL;
 342    }
 343    return RESULT_OK;
 344
 345}
 346
 347
 348/* read from negative sector num   start + sectnum > 0, and start + setnum < 0 */
 349static int nand_test_negstart_read(struct nand_test_card *test)
 350{
 351    int ret;
 352
 353    /* start + sectnum > 0, start < 0*/
 354    ret = nand_test_simple_transfer(test,  0, -1, 3, 0);
 355
 356    if (!ret){
 357        return RESULT_FAIL;
 358    }
 359    printk(NAND_TEST "start + sectnum > 0 pass\n");
 360
 361    /* start + sectnum < 0 , start < 0 */
 362    ret = nand_test_simple_transfer(test,  0, -90, 15, 0);
 363
 364    if (!ret){
 365        return RESULT_FAIL;
 366    }
 367    return RESULT_OK;
 368
 369}
 370
 371static int nand_test_beyond(struct nand_test_card *test, int write)
 372{
 373    int ret;
 374
 375
 376    ret = nand_test_simple_transfer(test,  0, DiskSize -3 , 5, write);
 377
 378    if (!ret){
 379
 380        return 1;
 381    }
 382    printk(NAND_TEST "DiskSize -3 , 5 pass\n");
 383    ret = nand_test_simple_transfer(test,  0, DiskSize -1 , 2, write);
 384
 385    if (!ret){
 386
 387        return 1;
 388    }
 389    printk(NAND_TEST "DiskSize -1 , 2 pass\n");
 390    ret = nand_test_simple_transfer(test,  0, DiskSize , 3, write);
 391
 392    if (!ret){
 393
 394        return 1;
 395    }
 396
 397    printk(NAND_TEST "DiskSize , 3 pass\n");
 398
 399    ret = nand_test_simple_transfer(test,  0, DiskSize + 3 , 0, write);
 400
 401    if (!ret){
 402
 403        return 1;
 404    }
 405
 406    printk(NAND_TEST "DiskSize + 3 , 0 pass\n");
 407
 408    ret = nand_test_simple_transfer(test,  0, DiskSize - 3 , -2, write);
 409
 410    if (!ret){
 411
 412        return 1;
 413    }
 414
 415    printk(NAND_TEST "DiskSize - 3 , -2 pass\n");
 416
 417    return RESULT_OK;
 418}
 419
 420
 421static int nand_test_beyond_write(struct nand_test_card *test)
 422{
 423    return (nand_test_beyond(test, 1));
 424}
 425
 426
 427/* read from incorrect sector num such as -1, DiskSize(max sector num + 1),  DiskSize +1 */
 428static int nand_test_beyond_read(struct nand_test_card *test)
 429{
 430
 431    return (nand_test_beyond(test, 0));
 432
 433}
 434
 435
 436
 437/* write all sectors from sector num 0 to DiskSize - 1(max sector num )*/
 438static int nand_test_write_all_ascending(struct nand_test_card *test)
 439{
 440    int ret;
 441    int i = 0;
 442    int j = 0;
 443
 444    printk(KERN_INFO "DiskSize = %x\n", DiskSize);
 445
 446
 447    for (i = 0; i < DiskSize; i++) {   // write all sectors
 448        ret = nand_test_simple_transfer(test, 0, i, test->sector_cnt,1);
 449        if(ret){
 450            printk(KERN_INFO "nand_test_write_all_ascending fail, sector num %d\n", i);
 451            return ret;
 452        }
 453    }
 454
 455    /* start check */
 456    printk(KERN_INFO "[nand test]:start check\n");
 457
 458    for (i = 0; i < DiskSize; i++){
 459        memset(test->buffer, 0, test->sector_cnt * 512);  // clear buffer
 460
 461        ret = nand_test_simple_transfer(test, 0 , i, test->sector_cnt, 0);   // read
 462        if(ret){
 463            return ret;
 464        }
 465
 466        for(j  = 0; j < test->sector_cnt * 512; j++)  {  // verify
 467            if (test->buffer[j] != 0xDF){
 468                printk(KERN_INFO "nand_test_write_all_ascending, Ttest->buffer[j] = %d, i = %d\n", test->buffer[j],  i);
 469                return RESULT_FAIL;
 470            }
 471        }
 472
 473    }
 474    return RESULT_OK;
 475}
 476
 477
 478/* read all sectors from sector num 0 to DiskSize - 1(max sector num )*/
 479static int nand_test_read_all_ascending(struct nand_test_card *test)
 480{
 481    int ret;
 482    int i = 0;
 483    int j = 0;
 484
 485    /*  before reading, write */
 486    for (i = 0; i < DiskSize; i++) {
 487
 488        ret = nand_test_simple_transfer(test, 0, i, test->sector_cnt,1);  // write all sectors
 489        if(ret){
 490            printk(KERN_INFO "nand_test_read_all_ascending fail, sector num %d\n", i);
 491            return ret;
 492        }
 493    }
 494
 495   /* finish write,  start to read and check */
 496    for (i = 0; i < DiskSize; i++)
 497    {
 498        if (i%100000 == 0){
 499            printk(KERN_INFO "[nand test]: sector num:%d\n", i);
 500        }
 501
 502        memset(test->buffer, 0, test->sector_cnt * 512);  // clear buffer
 503
 504        ret = nand_test_simple_transfer(test, 0 , i, test->sector_cnt, 0);   // read
 505        if(ret){
 506            return ret;
 507        }
 508        for(j  = 0 ; j < test->sector_cnt * 512  ; j++){
 509            if (test->buffer[j] != (j)%256){
 510                printk(KERN_INFO "nand_test_read_all_ascending fial! Ttest->buffer[j] = %d, i = %d\n", test->buffer[i],  j);
 511                return RESULT_FAIL;
 512            }
 513
 514       }
 515    }
 516    return RESULT_OK;
 517}
 518
 519
 520/* write all sectors from sector num  DiskSize - 1(max sector num ) to  0  */
 521static int nand_test_write_all_descending(struct nand_test_card *test)
 522{
 523    int ret;
 524    int i = 0;
 525    int j = 0;
 526
 527    printk(KERN_INFO "nand_test: DiskSize = %x\n", DiskSize);
 528
 529    for (i = DiskSize - 1; i >= 0; i--){
 530
 531        memset(test->buffer, i%256, 512);
 532
 533        if (i%100000 == 0){
 534            printk(KERN_INFO "[nand test]: sector num:%d\n", i);
 535        }
 536
 537        ret = nand_test_simple_transfer(test, 0, i, test->sector_cnt,1);  // write all sectors
 538        if(ret){
 539            printk(KERN_INFO "[nand_test]: nand_test_write_all_ascending fail, sector num %d\n", i);
 540            return ret;
 541        }
 542   }
 543
 544   printk(KERN_INFO "[nand test]: check start\n");
 545
 546   for (i = DiskSize - 1; i >= 0; i--){
 547
 548       if (i%100000 == 0){
 549           printk(KERN_INFO "[nand test]: sector num:%d\n", i);
 550       }
 551
 552       memset(test->buffer, 0, test->sector_cnt * 512);  // clear buffer
 553
 554       ret = nand_test_simple_transfer(test, 0 , i, test->sector_cnt, 0);   // read
 555       if(ret){
 556           return ret;
 557       }
 558       for(j  = 0; j < 512; j++){  // verify
 559            if (test->buffer[j] != i%256){
 560                printk(KERN_INFO "[nand_test]: nand_test_write_all_ascending, Ttest->buffer[j] = %d, i = %d\n", test->buffer[j],  i);
 561                return RESULT_FAIL;
 562            }
 563        }
 564    }
 565    return RESULT_OK;
 566}
 567
 568/* read all sectors from sector num  DiskSize - 1(max sector num ) to  0  */
 569static int nand_test_read_all_descending(struct nand_test_card *test)
 570{
 571    int ret;
 572    int i = 0;
 573    int j = 0;
 574
 575    for (i = DiskSize - 1; i >= 0; i--){
 576        memset(test->buffer, i%256, 512);
 577
 578        ret = nand_test_simple_transfer(test, 0, i, test->sector_cnt,1);  // write all sectors
 579        if(ret){
 580            printk(KERN_INFO "[nand_test]: nand_test_read_all_ascending fail, sector num %d\n", i);
 581            return ret;
 582        }
 583    }
 584
 585    printk(KERN_INFO "[nand test]: check start\n");
 586    for (i = DiskSize - 1; i >= 0; i--){
 587        if (i%100000 == 0){
 588            printk(KERN_INFO "[nand test]: sector num:%d\n", i);
 589        }
 590        memset(test->buffer, 0, test->sector_cnt * 512);  // clear buffer
 591        ret = nand_test_simple_transfer(test, 0 , i, test->sector_cnt, 0);   // read
 592        if(ret){
 593            return ret;
 594        }
 595        for(j = 0 ; j < test->sector_cnt * 512  ; j++){      // verify data
 596            if (test->buffer[j] != (i)%256){
 597                printk(KERN_INFO "[nand_test]:nand_test_read_all_ascending fial! Ttest->buffer[j] = %d, i = %d\n", test->buffer[j],  i);
 598                return RESULT_FAIL;
 599            }
 600        }
 601    }
 602    return RESULT_OK;
 603}
 604
 605/* write a sector for  n times  without verification to test stability */
 606static int nand_test_repeat_single_write(struct nand_test_card *test)
 607{
 608    int ret;
 609    int i = 0;
 610
 611    printk(NAND_TEST "DiskSize = %d\n", DiskSize);
 612
 613    for(i = 0; i < REPEAT_TIMES*1000; i++){
 614       ret = nand_test_simple_transfer(test, 0 , DiskSize/7, test->sector_cnt, 1);
 615       if(ret){
 616           return ret;
 617       }
 618    }
 619    return 0;
 620}
 621
 622
 623/* read a sector for  n times with verification to test stability*/
 624static int nand_test_repeat_single_read(struct nand_test_card *test)
 625{
 626    int ret;
 627    int i = 0;
 628    for(i = 0; i < REPEAT_TIMES*30; i++){
 629        ret = nand_test_simple_transfer(test, 0 , DiskSize/4 + 7, test->sector_cnt, 0);
 630        if(ret){
 631            return ret;
 632        }
 633   }
 634   return 0;
 635}
 636
 637/* write multi sectors for  n times without verification to test stability*/
 638static int nand_test_repeat_multi_write(struct nand_test_card *test)
 639{
 640    int ret;
 641    int i = 0;
 642
 643    for(i = 0; i < 1100000; i++){
 644        ret = nand_test_simple_transfer(test, 0 , DiskSize/2, test->sector_cnt, 1);
 645        if(ret) {
 646            return ret;
 647        }
 648    }
 649
 650    return 0;
 651}
 652
 653
 654/* read multi sectors for  n times without verification to test stability*/
 655static int nand_test_repeat_multi_read(struct nand_test_card *test)
 656{
 657    int ret;
 658    int i = 0;
 659    for(i = 0; i < 9200000; i++){
 660        ret = nand_test_simple_transfer(test, 0 , DiskSize/3, test->sector_cnt, 0);
 661        if(ret){
 662            return ret;
 663       }
 664    }
 665    return 0;
 666}
 667
 668/* random write one or more sectors*/
 669static int nand_test_random_write(struct nand_test_card *test)
 670{
 671    int ret;
 672
 673    ret = nand_test_simple_transfer(test, 0 , 0, test->sector_cnt, 1);
 674    if(ret){
 675        return ret;
 676    }
 677
 678    ret = nand_test_simple_transfer(test, 0 , DiskSize -1, test->sector_cnt, 1);
 679    if(ret) {
 680        return ret;
 681    }
 682
 683    ret = nand_test_simple_transfer(test, 0 , DiskSize/2, test->sector_cnt, 1);
 684    if(ret){
 685        return ret;
 686    }
 687    return 0;
 688}
 689
 690/* random read one or more sectors*/
 691static int nand_test_random_read(struct nand_test_card *test)
 692{
 693    int ret;
 694
 695    ret = nand_test_simple_transfer(test, 0 , 0, test->sector_cnt, 0);
 696    if(ret) {
 697        return ret;
 698    }
 699
 700    ret = nand_test_simple_transfer(test, 0 , DiskSize -1, test->sector_cnt, 0);
 701    if(ret){
 702        return ret;
 703    }
 704
 705    ret = nand_test_simple_transfer(test, 0 , DiskSize/2, test->sector_cnt, 0);
 706    if(ret){
 707        return ret;
 708    }
 709
 710    return 0;
 711}
 712
 713
 714/* clear r/w buffer to 0*/
 715static int nand_test_cleanup(struct nand_test_card *test)
 716{
 717    memset(test->buffer, 0, 512* (test->sector_cnt));
 718    return 0;
 719}
 720
 721
 722/* test cases */
 723
 724static const struct nand_test_case nand_test_cases[] = {
 725    {
 726	    .name = "single sector write (no data verification)",
 727	    .sectors_cnt = 1,
 728	    .prepare = nand_test_prepare_write,
 729	    .run = nand_test_single_write,
 730	    .cleanup = nand_test_cleanup
 731    },
 732
 733    {
 734	    .name = "single sector read (no data verification)",
 735	    .sectors_cnt = 1,
 736	    .prepare = nand_test_prepare_read,
 737	    .run = nand_test_single_read,
 738	    .cleanup = nand_test_cleanup
 739    },
 740
 741    {
 742	    .name = "single sector write(verify data)",
 743	    .sectors_cnt = 1,
 744	    .prepare = nand_test_prepare_write,
 745	    .run = nand_test_verify_write,
 746	    .cleanup = nand_test_cleanup
 747    },
 748
 749    {
 750	    .name = "single sector read(verify data)",
 751	    .sectors_cnt = 1,
 752	    .prepare = nand_test_prepare_read,
 753	    .run = nand_test_verify_read,
 754	    .cleanup = nand_test_cleanup
 755    },
 756
 757    /* multi read/write*/
 758    {
 759	    .name = "multi sector read(2 sectors, verify)",
 760	    .sectors_cnt = 2,
 761	    .prepare = nand_test_prepare_read,
 762	    .run = nand_test_multi_read,
 763	    .cleanup = nand_test_cleanup
 764    },
 765
 766    {
 767	    .name = "multi sector read(3 sectors, verify)",
 768	    .sectors_cnt = 3,
 769	    .prepare = nand_test_prepare_read,
 770	    .run = nand_test_multi_read,
 771	    .cleanup = nand_test_cleanup
 772    },
 773
 774    {
 775	    .name = "multi sector read(8 sectors, verify)",
 776	    .sectors_cnt = 8,
 777	    .prepare = nand_test_prepare_read,
 778	    .run = nand_test_multi_read,
 779	    .cleanup = nand_test_cleanup
 780    },
 781
 782    {
 783	    .name = "multi sector read(18 sectors, verify)",
 784	    .sectors_cnt = 18,
 785	    .prepare = nand_test_prepare_read,
 786	    .run = nand_test_multi_read,
 787	    .cleanup = nand_test_cleanup
 788    },
 789
 790    {
 791	    .name = "multi sector read(53 sectors, verify)",
 792	    .sectors_cnt = 53,
 793	    .prepare = nand_test_prepare_read,
 794	    .run = nand_test_multi_read,
 795	    .cleanup = nand_test_cleanup
 796    },
 797
 798    {
 799	    .name = "multi sector write(2 sectors ,verify)",
 800	    .sectors_cnt = 2,
 801	    .prepare = nand_test_prepare_write,
 802	    .run = nand_test_multi_write,
 803	    .cleanup = nand_test_cleanup
 804    },
 805
 806    {
 807	    .name = "multi sector write(5 sectors ,verify)",
 808	    .sectors_cnt = 5,
 809	    .prepare = nand_test_prepare_write,
 810	    .run = nand_test_multi_write,
 811	    .cleanup = nand_test_cleanup,
 812    },
 813
 814    {
 815	    .name = "multi sector write(12 sectors ,verify)",
 816	    .sectors_cnt = 12,
 817	    .prepare = nand_test_prepare_write,
 818	    .run = nand_test_multi_write,
 819	    .cleanup = nand_test_cleanup,
 820    },
 821
 822    {
 823	    .name = "multi sector write(15 sectors ,verify)",
 824	    .sectors_cnt = 15,
 825	    .prepare = nand_test_prepare_write,
 826	    .run = nand_test_multi_write,
 827	    .cleanup = nand_test_cleanup,
 828    },
 829
 830    {
 831	    .name = "multi sector write(26 sectors ,verify)",
 832	    .sectors_cnt = 26,
 833	    .prepare = nand_test_prepare_write,
 834	    .run = nand_test_multi_write,
 835	    .cleanup = nand_test_cleanup,
 836    },
 837
 838    {
 839	    .name = "multi sector write(93 sectors ,verify)",
 840	    .sectors_cnt = 93,
 841	    .prepare = nand_test_prepare_write,
 842	    .run = nand_test_multi_write,
 843	    .cleanup = nand_test_cleanup,
 844    },
 845
 846    /*align test*/
 847    {
 848	    .name = "align write(1 sector ,verify)",
 849	    .sectors_cnt = 1,
 850	    .prepare = nand_test_prepare_write,
 851	    .run = nand_test_align_write,
 852	    .cleanup = nand_test_cleanup,
 853    },
 854
 855    {
 856	    .name = "align read(1 sector ,verify)",
 857	    .sectors_cnt = 1,
 858	    .prepare = nand_test_prepare_read,
 859	    .run = nand_test_align_read,
 860	    .cleanup = nand_test_cleanup,
 861    },
 862
 863    /* stability test */
 864    {
 865	    .name = "weird write(negative start)",   // 18
 866	    .sectors_cnt = 10,
 867	    .prepare = nand_test_prepare_write,
 868	    .run = nand_test_negstart_write,
 869	    .cleanup = nand_test_cleanup,
 870    },
 871
 872    {
 873	    .name = "weid read(nagative satrt)",
 874	    .sectors_cnt = 10,
 875	    .prepare = nand_test_prepare_read,
 876	    .run = nand_test_negstart_read,
 877	    .cleanup = nand_test_cleanup,
 878    },
 879
 880    {
 881	    .name = "weird write(beyond start)",   // 20
 882	    .sectors_cnt = 10,
 883	    .prepare = nand_test_prepare_write,
 884	    .run = nand_test_beyond_write,
 885	    .cleanup = nand_test_cleanup,
 886    },
 887
 888    {
 889	    .name = "weid read(bayond start)",
 890	    .sectors_cnt = 10,
 891	    .prepare = nand_test_prepare_read,
 892	    .run = nand_test_beyond_read,
 893	    .cleanup = nand_test_cleanup,
 894    },
 895
 896    {                                            // 22
 897	    .name = "write all ascending",
 898	    .sectors_cnt = 1,
 899	    .prepare = nand_test_prepare_write,
 900	    .run = nand_test_write_all_ascending,
 901	    .cleanup = nand_test_cleanup,
 902    },
 903
 904    {
 905	    .name = "read all ascending",
 906	    .sectors_cnt = 1,
 907	    .prepare = nand_test_prepare_read,
 908	    .run = nand_test_read_all_ascending,
 909	    .cleanup = nand_test_cleanup,
 910    },
 911
 912    {
 913	    .name = "write all descending",
 914	    .sectors_cnt = 1,
 915	    .prepare = nand_test_prepare_write,
 916	    .run = nand_test_write_all_descending,
 917	     .cleanup = nand_test_cleanup,
 918    },
 919
 920
 921    {
 922	    .name = "read all descending",
 923	    .sectors_cnt = 1,
 924	    .prepare = nand_test_prepare_read,
 925	    .run = nand_test_read_all_descending,
 926	    .cleanup = nand_test_cleanup,
 927    },
 928
 929    {                                                     // 26
 930	    .name = " repeat  write (no data verification) ",
 931	    .sectors_cnt = 1,
 932	    .prepare = nand_test_prepare_write,
 933	    .run = nand_test_repeat_single_write,
 934	    .cleanup = nand_test_cleanup,
 935    },
 936
 937    {                                                    // 27
 938	    .name = " repeat  read (no data verification) ",
 939	    .sectors_cnt = 1,
 940	    .prepare = nand_test_prepare_read,
 941	    .run = nand_test_repeat_single_read,
 942	    .cleanup = nand_test_cleanup,
 943   },
 944
 945   {                                                     // 28
 946	    .name = " repeat multi write (no data verification)",
 947	    .sectors_cnt = 43,
 948	    .prepare = nand_test_prepare_write,
 949	    .run = nand_test_repeat_multi_write,
 950	    .cleanup = nand_test_cleanup,
 951   },
 952
 953   {                                                    // 29
 954	    .name = " repeat multi read (no data verification)",
 955	    .sectors_cnt = 81,
 956	    .prepare = nand_test_prepare_read,
 957	    .run = nand_test_repeat_multi_read,
 958	    .cleanup = nand_test_cleanup,
 959    },
 960
 961    {                                                    // 30
 962	    .name = " random  write (no data verification)",
 963	    .sectors_cnt = 1,
 964	    .prepare = nand_test_prepare_write,
 965	    .run = nand_test_random_write,
 966	    .cleanup = nand_test_cleanup,
 967    },
 968
 969    {                                                    // 31
 970	    .name = " random  read (no data verification)",
 971	    .sectors_cnt = 1,
 972	    .prepare = nand_test_prepare_read,
 973	    .run = nand_test_random_read,
 974	    .cleanup = nand_test_cleanup,
 975    },
 976
 977    {                                                    // 32
 978	    .name = " pwm  test (no data verification)",
 979	    .sectors_cnt = 1,
 980	    .prepare = nand_test_prepare_pwm,
 981	    //.run = nand_test_pwm,
 982	    .cleanup = nand_test_cleanup,
 983    },
 984};
 985
 986static DEFINE_MUTEX(nand_test_lock);
 987
 988
 989/* run test cases*/
 990static void nand_test_run(struct nand_test_card *test, int testcase)
 991{
 992    int i, ret;
 993
 994    printk(KERN_INFO "[nand_test]: Starting tests of nand\n");
 995
 996    for (i = 0;i < ARRAY_SIZE(nand_test_cases);i++) {
 997        if (testcase && ((i + 1) != testcase)){
 998            continue;
 999        }
1000
1001        printk(KERN_INFO "[nand_test]: Test case %d. %s...\n", i + 1, nand_test_cases[i].name);
1002
1003        if (nand_test_cases[i].prepare) {
1004              ret = nand_test_cases[i].prepare(test, nand_test_cases[i].sectors_cnt);
1005          if (ret) {
1006              printk(KERN_INFO "[nand_test]: Result: Prepare stage failed! (%d)\n", ret);
1007              continue;
1008          }
1009        }
1010
1011        ret = nand_test_cases[i].run(test);
1012
1013        switch (ret) {
1014            case RESULT_OK:
1015                printk(KERN_INFO "[nand_test]: Result: OK\n");
1016                break;
1017            case RESULT_FAIL:
1018                printk(KERN_INFO "[nand_test]:Result: FAILED\n");
1019                break;
1020                //    case RESULT_UNSUP_HOST:                //grace del
1021                //      printk(KERN_INFO "%s: Result: UNSUPPORTED "
1022                //        "(by host)\n",
1023                //        mmc_hostname(test->card->host));
1024                //      break;
1025                //    case RESULT_UNSUP_CARD:
1026                //      printk(KERN_INFO "%s: Result: UNSUPPORTED "
1027                //        "(by card)\n",
1028                //        mmc_hostname(test->card->host));
1029                //      break;
1030            default:
1031                printk(KERN_INFO "[nand_test]:Result: ERROR (%d)\n", ret);
1032        }
1033
1034        if (nand_test_cases[i].cleanup) {
1035            ret = nand_test_cases[i].cleanup(test);
1036            if (ret) {
1037                printk(KERN_INFO "[nand_test]:Warning: Cleanup"
1038                       "stage failed! (%d)\n", ret);
1039            }
1040        }
1041    }
1042
1043    //mmc_release_host(test->card->host);
1044
1045    printk(KERN_INFO "[nand_test]: Nand tests completed.\n");
1046}
1047
1048
1049/* do nothing */
1050static ssize_t nand_test_show(struct kobject *kobject,struct attribute *attr, char *buf)
1051{
1052    return 0;
1053}
1054
1055
1056/* receive testcase num from echo command */
1057static ssize_t nand_test_store(struct kobject *kobject,struct attribute *attr, const char *buf, size_t count)
1058{
1059
1060    struct nand_test_card *test;
1061    int testcase;
1062
1063    testcase = simple_strtol(buf, NULL, 10);  // get test case number     >> grace
1064
1065    test = kzalloc(sizeof(struct nand_test_card), GFP_KERNEL);
1066    if (!test){
1067        return -ENOMEM;
1068    }
1069
1070    test->buffer = kzalloc(BUFFER_SIZE, GFP_KERNEL);  // alloc buffer for r/w
1071    test->scratch = kzalloc(BUFFER_SIZE, GFP_KERNEL); // not used now
1072
1073    if (test->buffer && test->scratch) {
1074        mutex_lock(&nand_test_lock);
1075        nand_test_run(test, testcase);             // run test cases
1076        mutex_unlock(&nand_test_lock);
1077    }
1078
1079
1080    kfree(test->buffer);
1081    kfree(test->scratch);
1082    kfree(test);
1083
1084    return count;
1085}
1086
1087struct kobject kobj;
1088
1089
1090/* if nand driver is not inited ,  functions below will be used  */
1091#ifdef INIT_NAND_IN_TESTDRIVER
1092
1093static void set_nand_pio(void)
1094{
1095    __u32 cfg0;
1096    __u32 cfg1;
1097    __u32 cfg2;
1098    void* gpio_base;
1099
1100    //modify for f20
1101    gpio_base = (void *)SW_VA_PORTC_IO_BASE;
1102
1103    cfg0 = *(volatile __u32 *)(gpio_base + 0x48);
1104    cfg1 = *(volatile __u32 *)(gpio_base + 0x4c);
1105    cfg2 = *(volatile __u32 *)(gpio_base + 0x50);
1106
1107    /*set PIOC for nand*/
1108    cfg0 &= 0x0;
1109    cfg0 |= 0x22222222;
1110    cfg1 &= 0x0;
1111    cfg1 |= 0x22222222;
1112    cfg2 &= 0x0;
1113    cfg2 |= 0x22222222;
1114
1115    *(volatile __u32 *)(gpio_base + 0x48) = cfg0;
1116    *(volatile __u32 *)(gpio_base + 0x4c) = cfg1;
1117    *(volatile __u32 *)(gpio_base + 0x50) = cfg2;
1118
1119    //iounmap(gpio_base);
1120}
1121
1122static __u32 get_cmu_clk(void)
1123{
1124    __u32 cmu_clk;
1125    __u32 cfg;
1126    __u32 ccmu_base;
1127
1128    ccmu_base = 0xf1c20000;
1129
1130    /*get cmu clock*/
1131    cfg = *(volatile __u32 *)(ccmu_base + 0x0);
1132
1133    if (cfg & (0x1 << 26)){
1134      /*bypass enable*/
1135        cmu_clk = 24/((cfg >> 16) & 0x7f);
1136    }
1137    else{
1138        cmu_clk = 24 + 6 * (((cfg >> 16) & 0x7f) + 1);
1139    }
1140
1141    return cmu_clk;
1142}
1143
1144
1145static void set_nand_clock(__u32 nand_max_clock,__u32 cmu_clk)
1146{
1147    __u32 edo_clk;
1148    __u32 cfg;
1149    __u32 nand_clk_divid_ratio;
1150    __u32 ccmu_base;
1151
1152    ccmu_base = 0xf1c20000;
1153
1154    /*open ahb nand clk */
1155    cfg = *(volatile __u32 *)(ccmu_base + 0x0C);
1156    cfg |= (0x1<<12);
1157    *(volatile __u32 *)(ccmu_base + 0x0C) = cfg;
1158
1159    /*set nand clock*/
1160    edo_clk = nand_max_clock * 2;
1161
1162    nand_clk_divid_ratio = cmu_clk / edo_clk;
1163    if (cmu_clk % edo_clk)
1164        nand_clk_divid_ratio++;
1165    if (nand_clk_divid_ratio){
1166        if (nand_clk_divid_ratio > 16){
1167            nand_clk_divid_ratio = 15;
1168        }
1169        else{
1170            nand_clk_divid_ratio--;
1171        }
1172    }
1173    /*set nand clock gate on*/
1174    cfg = *(volatile __u32 *)(ccmu_base + 0x14);
1175
1176    /*gate on nand clock*/
1177    cfg |= (1 << 15);
1178    /*take cmu pll as nand src block*/
1179    cfg &= (~(0x3<<12));
1180    cfg |= (0x3 << 12);
1181
1182    /*set ratio*/
1183    cfg &= ((~(0xf << 8))&0xffffffff);
1184    cfg |= (nand_clk_divid_ratio & 0xf) << 8;
1185
1186    *(volatile __u32 *)(ccmu_base + 0x14) = cfg;
1187}
1188
1189#endif
1190
1191static int __init nand_test_init(void)
1192{
1193
1194   int ret;
1195#ifdef INIT_NAND_IN_TESTDRIVER
1196    __u32 cmu_clk;
1197#endif
1198
1199    printk("[nand_test]:nand_test_init test init.\n");
1200    if((ret = kobject_init_and_add(&kobj,&ktype,NULL,"nand")) != 0 ) {
1201        return ret;
1202    }
1203
1204
1205#ifdef INIT_NAND_IN_TESTDRIVER
1206
1207    /* init nand resource */
1208    printk("[nand_test]:init nand resource \n");
1209    //set nand clk
1210    cmu_clk = get_cmu_clk();
1211    set_nand_clock(20, cmu_clk);
1212
1213   //set nand pio
1214    set_nand_pio();
1215
1216    clear_NAND_ZI();
1217
1218    printk("/*********************************************************/ \n");
1219    printk("[nand_test]: init nand block layer start \n");
1220    printk("/*********************************************************/ \n");
1221
1222    ret = PHY_Init();
1223    if (ret) {
1224     PHY_Exit();
1225     return -1;
1226    }
1227
1228    ret = SCN_AnalyzeNandSystem();
1229    if (ret < 0){
1230        return ret;
1231    }
1232
1233    ret = PHY_ChangeMode(1);
1234    if (ret < 0){
1235        return ret;
1236    }
1237    ret = FMT_Init();
1238    if (ret < 0){
1239        return ret;
1240    }
1241    ret = FMT_FormatNand();
1242    if (ret < 0){
1243        return ret;
1244    }
1245    FMT_Exit();
1246
1247    /*init logic layer*/
1248    ret = LML_Init();
1249    if (ret < 0){
1250        return ret;
1251    }
1252#ifdef NAND_CACHE_RW
1253    NAND_CacheOpen();
1254#endif
1255
1256#endif
1257
1258   return 0;  // init success
1259
1260}
1261
1262
1263
1264static void __exit nand_test_exit(void)
1265{
1266    printk("[nand_test]:nand test exit.\n");
1267    kobject_del(&kobj);
1268
1269#ifdef INIT_NAND_IN_TESTDRIVER
1270    LML_FlushPageCache();
1271    BMM_WriteBackAllMapTbl();
1272    LML_Exit();
1273    FMT_Exit();
1274    PHY_Exit();
1275#ifdef NAND_CACHE_RW
1276    NAND_CacheOpen();
1277#endif
1278
1279#endif
1280
1281    return;
1282}
1283
1284
1285module_init(nand_test_init);
1286module_exit(nand_test_exit);
1287
1288
1289MODULE_LICENSE("GPL");
1290MODULE_DESCRIPTION("Nand test driver");
1291MODULE_AUTHOR("Grace Miao");
1292#endif