/drivers/block/sun3i_nand/nandtest/nand_test.c
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