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