at v2.6.13 13 kB view raw
1/* 2 * MTD chip driver for pre-CFI Sharp flash chips 3 * 4 * Copyright 2000,2001 David A. Schleef <ds@schleef.org> 5 * 2000,2001 Lineo, Inc. 6 * 7 * $Id: sharp.c,v 1.14 2004/08/09 13:19:43 dwmw2 Exp $ 8 * 9 * Devices supported: 10 * LH28F016SCT Symmetrical block flash memory, 2Mx8 11 * LH28F008SCT Symmetrical block flash memory, 1Mx8 12 * 13 * Documentation: 14 * http://www.sharpmeg.com/datasheets/memic/flashcmp/ 15 * http://www.sharpmeg.com/datasheets/memic/flashcmp/01symf/16m/016sctl9.pdf 16 * 016sctl9.pdf 17 * 18 * Limitations: 19 * This driver only supports 4x1 arrangement of chips. 20 * Not tested on anything but PowerPC. 21 */ 22 23#include <linux/kernel.h> 24#include <linux/module.h> 25#include <linux/types.h> 26#include <linux/sched.h> 27#include <linux/errno.h> 28#include <linux/interrupt.h> 29#include <linux/mtd/map.h> 30#include <linux/mtd/mtd.h> 31#include <linux/mtd/cfi.h> 32#include <linux/delay.h> 33#include <linux/init.h> 34 35#define CMD_RESET 0xffffffff 36#define CMD_READ_ID 0x90909090 37#define CMD_READ_STATUS 0x70707070 38#define CMD_CLEAR_STATUS 0x50505050 39#define CMD_BLOCK_ERASE_1 0x20202020 40#define CMD_BLOCK_ERASE_2 0xd0d0d0d0 41#define CMD_BYTE_WRITE 0x40404040 42#define CMD_SUSPEND 0xb0b0b0b0 43#define CMD_RESUME 0xd0d0d0d0 44#define CMD_SET_BLOCK_LOCK_1 0x60606060 45#define CMD_SET_BLOCK_LOCK_2 0x01010101 46#define CMD_SET_MASTER_LOCK_1 0x60606060 47#define CMD_SET_MASTER_LOCK_2 0xf1f1f1f1 48#define CMD_CLEAR_BLOCK_LOCKS_1 0x60606060 49#define CMD_CLEAR_BLOCK_LOCKS_2 0xd0d0d0d0 50 51#define SR_READY 0x80808080 // 1 = ready 52#define SR_ERASE_SUSPEND 0x40404040 // 1 = block erase suspended 53#define SR_ERROR_ERASE 0x20202020 // 1 = error in block erase or clear lock bits 54#define SR_ERROR_WRITE 0x10101010 // 1 = error in byte write or set lock bit 55#define SR_VPP 0x08080808 // 1 = Vpp is low 56#define SR_WRITE_SUSPEND 0x04040404 // 1 = byte write suspended 57#define SR_PROTECT 0x02020202 // 1 = lock bit set 58#define SR_RESERVED 0x01010101 59 60#define SR_ERRORS (SR_ERROR_ERASE|SR_ERROR_WRITE|SR_VPP|SR_PROTECT) 61 62/* Configuration options */ 63 64#undef AUTOUNLOCK /* automatically unlocks blocks before erasing */ 65 66struct mtd_info *sharp_probe(struct map_info *); 67 68static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd); 69 70static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len, 71 size_t *retlen, u_char *buf); 72static int sharp_write(struct mtd_info *mtd, loff_t from, size_t len, 73 size_t *retlen, const u_char *buf); 74static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr); 75static void sharp_sync(struct mtd_info *mtd); 76static int sharp_suspend(struct mtd_info *mtd); 77static void sharp_resume(struct mtd_info *mtd); 78static void sharp_destroy(struct mtd_info *mtd); 79 80static int sharp_write_oneword(struct map_info *map, struct flchip *chip, 81 unsigned long adr, __u32 datum); 82static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, 83 unsigned long adr); 84#ifdef AUTOUNLOCK 85static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, 86 unsigned long adr); 87#endif 88 89 90struct sharp_info{ 91 struct flchip *chip; 92 int bogus; 93 int chipshift; 94 int numchips; 95 struct flchip chips[1]; 96}; 97 98struct mtd_info *sharp_probe(struct map_info *map); 99static void sharp_destroy(struct mtd_info *mtd); 100 101static struct mtd_chip_driver sharp_chipdrv = { 102 .probe = sharp_probe, 103 .destroy = sharp_destroy, 104 .name = "sharp", 105 .module = THIS_MODULE 106}; 107 108 109struct mtd_info *sharp_probe(struct map_info *map) 110{ 111 struct mtd_info *mtd = NULL; 112 struct sharp_info *sharp = NULL; 113 int width; 114 115 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL); 116 if(!mtd) 117 return NULL; 118 119 sharp = kmalloc(sizeof(*sharp), GFP_KERNEL); 120 if(!sharp) { 121 kfree(mtd); 122 return NULL; 123 } 124 125 memset(mtd, 0, sizeof(*mtd)); 126 127 width = sharp_probe_map(map,mtd); 128 if(!width){ 129 kfree(mtd); 130 kfree(sharp); 131 return NULL; 132 } 133 134 mtd->priv = map; 135 mtd->type = MTD_NORFLASH; 136 mtd->erase = sharp_erase; 137 mtd->read = sharp_read; 138 mtd->write = sharp_write; 139 mtd->sync = sharp_sync; 140 mtd->suspend = sharp_suspend; 141 mtd->resume = sharp_resume; 142 mtd->flags = MTD_CAP_NORFLASH; 143 mtd->name = map->name; 144 145 memset(sharp, 0, sizeof(*sharp)); 146 sharp->chipshift = 23; 147 sharp->numchips = 1; 148 sharp->chips[0].start = 0; 149 sharp->chips[0].state = FL_READY; 150 sharp->chips[0].mutex = &sharp->chips[0]._spinlock; 151 sharp->chips[0].word_write_time = 0; 152 init_waitqueue_head(&sharp->chips[0].wq); 153 spin_lock_init(&sharp->chips[0]._spinlock); 154 155 map->fldrv = &sharp_chipdrv; 156 map->fldrv_priv = sharp; 157 158 __module_get(THIS_MODULE); 159 return mtd; 160} 161 162static int sharp_probe_map(struct map_info *map,struct mtd_info *mtd) 163{ 164 unsigned long tmp; 165 unsigned long base = 0; 166 u32 read0, read4; 167 int width = 4; 168 169 tmp = map_read32(map, base+0); 170 171 map_write32(map, CMD_READ_ID, base+0); 172 173 read0=map_read32(map, base+0); 174 read4=map_read32(map, base+4); 175 if(read0 == 0x89898989){ 176 printk("Looks like sharp flash\n"); 177 switch(read4){ 178 case 0xaaaaaaaa: 179 case 0xa0a0a0a0: 180 /* aa - LH28F016SCT-L95 2Mx8, 32 64k blocks*/ 181 /* a0 - LH28F016SCT-Z4 2Mx8, 32 64k blocks*/ 182 mtd->erasesize = 0x10000 * width; 183 mtd->size = 0x200000 * width; 184 return width; 185 case 0xa6a6a6a6: 186 /* a6 - LH28F008SCT-L12 1Mx8, 16 64k blocks*/ 187 /* a6 - LH28F008SCR-L85 1Mx8, 16 64k blocks*/ 188 mtd->erasesize = 0x10000 * width; 189 mtd->size = 0x100000 * width; 190 return width; 191#if 0 192 case 0x00000000: /* unknown */ 193 /* XX - LH28F004SCT 512kx8, 8 64k blocks*/ 194 mtd->erasesize = 0x10000 * width; 195 mtd->size = 0x80000 * width; 196 return width; 197#endif 198 default: 199 printk("Sort-of looks like sharp flash, 0x%08x 0x%08x\n", 200 read0,read4); 201 } 202 }else if((map_read32(map, base+0) == CMD_READ_ID)){ 203 /* RAM, probably */ 204 printk("Looks like RAM\n"); 205 map_write32(map, tmp, base+0); 206 }else{ 207 printk("Doesn't look like sharp flash, 0x%08x 0x%08x\n", 208 read0,read4); 209 } 210 211 return 0; 212} 213 214/* This function returns with the chip->mutex lock held. */ 215static int sharp_wait(struct map_info *map, struct flchip *chip) 216{ 217 __u16 status; 218 unsigned long timeo = jiffies + HZ; 219 DECLARE_WAITQUEUE(wait, current); 220 int adr = 0; 221 222retry: 223 spin_lock_bh(chip->mutex); 224 225 switch(chip->state){ 226 case FL_READY: 227 map_write32(map,CMD_READ_STATUS,adr); 228 chip->state = FL_STATUS; 229 case FL_STATUS: 230 status = map_read32(map,adr); 231//printk("status=%08x\n",status); 232 233 udelay(100); 234 if((status & SR_READY)!=SR_READY){ 235//printk(".status=%08x\n",status); 236 udelay(100); 237 } 238 break; 239 default: 240 printk("Waiting for chip\n"); 241 242 set_current_state(TASK_INTERRUPTIBLE); 243 add_wait_queue(&chip->wq, &wait); 244 245 spin_unlock_bh(chip->mutex); 246 247 schedule(); 248 remove_wait_queue(&chip->wq, &wait); 249 250 if(signal_pending(current)) 251 return -EINTR; 252 253 timeo = jiffies + HZ; 254 255 goto retry; 256 } 257 258 map_write32(map,CMD_RESET, adr); 259 260 chip->state = FL_READY; 261 262 return 0; 263} 264 265static void sharp_release(struct flchip *chip) 266{ 267 wake_up(&chip->wq); 268 spin_unlock_bh(chip->mutex); 269} 270 271static int sharp_read(struct mtd_info *mtd, loff_t from, size_t len, 272 size_t *retlen, u_char *buf) 273{ 274 struct map_info *map = mtd->priv; 275 struct sharp_info *sharp = map->fldrv_priv; 276 int chipnum; 277 int ret = 0; 278 int ofs = 0; 279 280 chipnum = (from >> sharp->chipshift); 281 ofs = from & ((1 << sharp->chipshift)-1); 282 283 *retlen = 0; 284 285 while(len){ 286 unsigned long thislen; 287 288 if(chipnum>=sharp->numchips) 289 break; 290 291 thislen = len; 292 if(ofs+thislen >= (1<<sharp->chipshift)) 293 thislen = (1<<sharp->chipshift) - ofs; 294 295 ret = sharp_wait(map,&sharp->chips[chipnum]); 296 if(ret<0) 297 break; 298 299 map_copy_from(map,buf,ofs,thislen); 300 301 sharp_release(&sharp->chips[chipnum]); 302 303 *retlen += thislen; 304 len -= thislen; 305 buf += thislen; 306 307 ofs = 0; 308 chipnum++; 309 } 310 return ret; 311} 312 313static int sharp_write(struct mtd_info *mtd, loff_t to, size_t len, 314 size_t *retlen, const u_char *buf) 315{ 316 struct map_info *map = mtd->priv; 317 struct sharp_info *sharp = map->fldrv_priv; 318 int ret = 0; 319 int i,j; 320 int chipnum; 321 unsigned long ofs; 322 union { u32 l; unsigned char uc[4]; } tbuf; 323 324 *retlen = 0; 325 326 while(len){ 327 tbuf.l = 0xffffffff; 328 chipnum = to >> sharp->chipshift; 329 ofs = to & ((1<<sharp->chipshift)-1); 330 331 j=0; 332 for(i=ofs&3;i<4 && len;i++){ 333 tbuf.uc[i] = *buf; 334 buf++; 335 to++; 336 len--; 337 j++; 338 } 339 sharp_write_oneword(map, &sharp->chips[chipnum], ofs&~3, tbuf.l); 340 if(ret<0) 341 return ret; 342 (*retlen)+=j; 343 } 344 345 return 0; 346} 347 348static int sharp_write_oneword(struct map_info *map, struct flchip *chip, 349 unsigned long adr, __u32 datum) 350{ 351 int ret; 352 int timeo; 353 int try; 354 int i; 355 int status = 0; 356 357 ret = sharp_wait(map,chip); 358 359 for(try=0;try<10;try++){ 360 map_write32(map,CMD_BYTE_WRITE,adr); 361 /* cpu_to_le32 -> hack to fix the writel be->le conversion */ 362 map_write32(map,cpu_to_le32(datum),adr); 363 364 chip->state = FL_WRITING; 365 366 timeo = jiffies + (HZ/2); 367 368 map_write32(map,CMD_READ_STATUS,adr); 369 for(i=0;i<100;i++){ 370 status = map_read32(map,adr); 371 if((status & SR_READY)==SR_READY) 372 break; 373 } 374 if(i==100){ 375 printk("sharp: timed out writing\n"); 376 } 377 378 if(!(status&SR_ERRORS)) 379 break; 380 381 printk("sharp: error writing byte at addr=%08lx status=%08x\n",adr,status); 382 383 map_write32(map,CMD_CLEAR_STATUS,adr); 384 } 385 map_write32(map,CMD_RESET,adr); 386 chip->state = FL_READY; 387 388 wake_up(&chip->wq); 389 spin_unlock_bh(chip->mutex); 390 391 return 0; 392} 393 394static int sharp_erase(struct mtd_info *mtd, struct erase_info *instr) 395{ 396 struct map_info *map = mtd->priv; 397 struct sharp_info *sharp = map->fldrv_priv; 398 unsigned long adr,len; 399 int chipnum, ret=0; 400 401//printk("sharp_erase()\n"); 402 if(instr->addr & (mtd->erasesize - 1)) 403 return -EINVAL; 404 if(instr->len & (mtd->erasesize - 1)) 405 return -EINVAL; 406 if(instr->len + instr->addr > mtd->size) 407 return -EINVAL; 408 409 chipnum = instr->addr >> sharp->chipshift; 410 adr = instr->addr & ((1<<sharp->chipshift)-1); 411 len = instr->len; 412 413 while(len){ 414 ret = sharp_erase_oneblock(map, &sharp->chips[chipnum], adr); 415 if(ret)return ret; 416 417 adr += mtd->erasesize; 418 len -= mtd->erasesize; 419 if(adr >> sharp->chipshift){ 420 adr = 0; 421 chipnum++; 422 if(chipnum>=sharp->numchips) 423 break; 424 } 425 } 426 427 instr->state = MTD_ERASE_DONE; 428 mtd_erase_callback(instr); 429 430 return 0; 431} 432 433static int sharp_do_wait_for_ready(struct map_info *map, struct flchip *chip, 434 unsigned long adr) 435{ 436 int ret; 437 unsigned long timeo; 438 int status; 439 DECLARE_WAITQUEUE(wait, current); 440 441 map_write32(map,CMD_READ_STATUS,adr); 442 status = map_read32(map,adr); 443 444 timeo = jiffies + HZ; 445 446 while(time_before(jiffies, timeo)){ 447 map_write32(map,CMD_READ_STATUS,adr); 448 status = map_read32(map,adr); 449 if((status & SR_READY)==SR_READY){ 450 ret = 0; 451 goto out; 452 } 453 set_current_state(TASK_INTERRUPTIBLE); 454 add_wait_queue(&chip->wq, &wait); 455 456 //spin_unlock_bh(chip->mutex); 457 458 schedule_timeout(1); 459 schedule(); 460 remove_wait_queue(&chip->wq, &wait); 461 462 //spin_lock_bh(chip->mutex); 463 464 if (signal_pending(current)){ 465 ret = -EINTR; 466 goto out; 467 } 468 469 } 470 ret = -ETIME; 471out: 472 return ret; 473} 474 475static int sharp_erase_oneblock(struct map_info *map, struct flchip *chip, 476 unsigned long adr) 477{ 478 int ret; 479 //int timeo; 480 int status; 481 //int i; 482 483//printk("sharp_erase_oneblock()\n"); 484 485#ifdef AUTOUNLOCK 486 /* This seems like a good place to do an unlock */ 487 sharp_unlock_oneblock(map,chip,adr); 488#endif 489 490 map_write32(map,CMD_BLOCK_ERASE_1,adr); 491 map_write32(map,CMD_BLOCK_ERASE_2,adr); 492 493 chip->state = FL_ERASING; 494 495 ret = sharp_do_wait_for_ready(map,chip,adr); 496 if(ret<0)return ret; 497 498 map_write32(map,CMD_READ_STATUS,adr); 499 status = map_read32(map,adr); 500 501 if(!(status&SR_ERRORS)){ 502 map_write32(map,CMD_RESET,adr); 503 chip->state = FL_READY; 504 //spin_unlock_bh(chip->mutex); 505 return 0; 506 } 507 508 printk("sharp: error erasing block at addr=%08lx status=%08x\n",adr,status); 509 map_write32(map,CMD_CLEAR_STATUS,adr); 510 511 //spin_unlock_bh(chip->mutex); 512 513 return -EIO; 514} 515 516#ifdef AUTOUNLOCK 517static void sharp_unlock_oneblock(struct map_info *map, struct flchip *chip, 518 unsigned long adr) 519{ 520 int i; 521 int status; 522 523 map_write32(map,CMD_CLEAR_BLOCK_LOCKS_1,adr); 524 map_write32(map,CMD_CLEAR_BLOCK_LOCKS_2,adr); 525 526 udelay(100); 527 528 status = map_read32(map,adr); 529 printk("status=%08x\n",status); 530 531 for(i=0;i<1000;i++){ 532 //map_write32(map,CMD_READ_STATUS,adr); 533 status = map_read32(map,adr); 534 if((status & SR_READY)==SR_READY) 535 break; 536 udelay(100); 537 } 538 if(i==1000){ 539 printk("sharp: timed out unlocking block\n"); 540 } 541 542 if(!(status&SR_ERRORS)){ 543 map_write32(map,CMD_RESET,adr); 544 chip->state = FL_READY; 545 return; 546 } 547 548 printk("sharp: error unlocking block at addr=%08lx status=%08x\n",adr,status); 549 map_write32(map,CMD_CLEAR_STATUS,adr); 550} 551#endif 552 553static void sharp_sync(struct mtd_info *mtd) 554{ 555 //printk("sharp_sync()\n"); 556} 557 558static int sharp_suspend(struct mtd_info *mtd) 559{ 560 printk("sharp_suspend()\n"); 561 return -EINVAL; 562} 563 564static void sharp_resume(struct mtd_info *mtd) 565{ 566 printk("sharp_resume()\n"); 567 568} 569 570static void sharp_destroy(struct mtd_info *mtd) 571{ 572 printk("sharp_destroy()\n"); 573 574} 575 576int __init sharp_probe_init(void) 577{ 578 printk("MTD Sharp chip driver <ds@lineo.com>\n"); 579 580 register_mtd_chip_driver(&sharp_chipdrv); 581 582 return 0; 583} 584 585static void __exit sharp_probe_exit(void) 586{ 587 unregister_mtd_chip_driver(&sharp_chipdrv); 588} 589 590module_init(sharp_probe_init); 591module_exit(sharp_probe_exit); 592 593 594MODULE_LICENSE("GPL"); 595MODULE_AUTHOR("David Schleef <ds@schleef.org>"); 596MODULE_DESCRIPTION("Old MTD chip driver for pre-CFI Sharp flash chips");