ia64/linux-2.6.18-xen.hg

annotate drivers/mtd/chips/sharp.c @ 912:dd42cdb0ab89

[IA64] Build blktap2 driver by default in x86 builds.

add CONFIG_XEN_BLKDEV_TAP2=y to buildconfigs/linux-defconfig_xen_ia64.

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