ia64/linux-2.6.18-xen.hg

annotate drivers/mtd/chips/cfi_cmdset_0020.c @ 0:831230e53067

Import 2.6.18 from kernel.org tarball.
author Ian Campbell <ian.campbell@xensource.com>
date Wed Apr 11 14:15:44 2007 +0100 (2007-04-11)
parents
children
rev   line source
ian@0 1 /*
ian@0 2 * Common Flash Interface support:
ian@0 3 * ST Advanced Architecture Command Set (ID 0x0020)
ian@0 4 *
ian@0 5 * (C) 2000 Red Hat. GPL'd
ian@0 6 *
ian@0 7 * $Id: cfi_cmdset_0020.c,v 1.22 2005/11/07 11:14:22 gleixner Exp $
ian@0 8 *
ian@0 9 * 10/10/2000 Nicolas Pitre <nico@cam.org>
ian@0 10 * - completely revamped method functions so they are aware and
ian@0 11 * independent of the flash geometry (buswidth, interleave, etc.)
ian@0 12 * - scalability vs code size is completely set at compile-time
ian@0 13 * (see include/linux/mtd/cfi.h for selection)
ian@0 14 * - optimized write buffer method
ian@0 15 * 06/21/2002 Joern Engel <joern@wh.fh-wedel.de> and others
ian@0 16 * - modified Intel Command Set 0x0001 to support ST Advanced Architecture
ian@0 17 * (command set 0x0020)
ian@0 18 * - added a writev function
ian@0 19 * 07/13/2005 Joern Engel <joern@wh.fh-wedel.de>
ian@0 20 * - Plugged memory leak in cfi_staa_writev().
ian@0 21 */
ian@0 22
ian@0 23 #include <linux/module.h>
ian@0 24 #include <linux/types.h>
ian@0 25 #include <linux/kernel.h>
ian@0 26 #include <linux/sched.h>
ian@0 27 #include <linux/init.h>
ian@0 28 #include <asm/io.h>
ian@0 29 #include <asm/byteorder.h>
ian@0 30
ian@0 31 #include <linux/errno.h>
ian@0 32 #include <linux/slab.h>
ian@0 33 #include <linux/delay.h>
ian@0 34 #include <linux/interrupt.h>
ian@0 35 #include <linux/mtd/map.h>
ian@0 36 #include <linux/mtd/cfi.h>
ian@0 37 #include <linux/mtd/mtd.h>
ian@0 38 #include <linux/mtd/compatmac.h>
ian@0 39
ian@0 40
ian@0 41 static int cfi_staa_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *);
ian@0 42 static int cfi_staa_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
ian@0 43 static int cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs,
ian@0 44 unsigned long count, loff_t to, size_t *retlen);
ian@0 45 static int cfi_staa_erase_varsize(struct mtd_info *, struct erase_info *);
ian@0 46 static void cfi_staa_sync (struct mtd_info *);
ian@0 47 static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
ian@0 48 static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
ian@0 49 static int cfi_staa_suspend (struct mtd_info *);
ian@0 50 static void cfi_staa_resume (struct mtd_info *);
ian@0 51
ian@0 52 static void cfi_staa_destroy(struct mtd_info *);
ian@0 53
ian@0 54 struct mtd_info *cfi_cmdset_0020(struct map_info *, int);
ian@0 55
ian@0 56 static struct mtd_info *cfi_staa_setup (struct map_info *);
ian@0 57
ian@0 58 static struct mtd_chip_driver cfi_staa_chipdrv = {
ian@0 59 .probe = NULL, /* Not usable directly */
ian@0 60 .destroy = cfi_staa_destroy,
ian@0 61 .name = "cfi_cmdset_0020",
ian@0 62 .module = THIS_MODULE
ian@0 63 };
ian@0 64
ian@0 65 /* #define DEBUG_LOCK_BITS */
ian@0 66 //#define DEBUG_CFI_FEATURES
ian@0 67
ian@0 68 #ifdef DEBUG_CFI_FEATURES
ian@0 69 static void cfi_tell_features(struct cfi_pri_intelext *extp)
ian@0 70 {
ian@0 71 int i;
ian@0 72 printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport);
ian@0 73 printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported");
ian@0 74 printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported");
ian@0 75 printk(" - Suspend Program: %s\n", extp->FeatureSupport&4?"supported":"unsupported");
ian@0 76 printk(" - Legacy Lock/Unlock: %s\n", extp->FeatureSupport&8?"supported":"unsupported");
ian@0 77 printk(" - Queued Erase: %s\n", extp->FeatureSupport&16?"supported":"unsupported");
ian@0 78 printk(" - Instant block lock: %s\n", extp->FeatureSupport&32?"supported":"unsupported");
ian@0 79 printk(" - Protection Bits: %s\n", extp->FeatureSupport&64?"supported":"unsupported");
ian@0 80 printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported");
ian@0 81 printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported");
ian@0 82 for (i=9; i<32; i++) {
ian@0 83 if (extp->FeatureSupport & (1<<i))
ian@0 84 printk(" - Unknown Bit %X: supported\n", i);
ian@0 85 }
ian@0 86
ian@0 87 printk(" Supported functions after Suspend: %2.2X\n", extp->SuspendCmdSupport);
ian@0 88 printk(" - Program after Erase Suspend: %s\n", extp->SuspendCmdSupport&1?"supported":"unsupported");
ian@0 89 for (i=1; i<8; i++) {
ian@0 90 if (extp->SuspendCmdSupport & (1<<i))
ian@0 91 printk(" - Unknown Bit %X: supported\n", i);
ian@0 92 }
ian@0 93
ian@0 94 printk(" Block Status Register Mask: %4.4X\n", extp->BlkStatusRegMask);
ian@0 95 printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no");
ian@0 96 printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no");
ian@0 97 for (i=2; i<16; i++) {
ian@0 98 if (extp->BlkStatusRegMask & (1<<i))
ian@0 99 printk(" - Unknown Bit %X Active: yes\n",i);
ian@0 100 }
ian@0 101
ian@0 102 printk(" Vcc Logic Supply Optimum Program/Erase Voltage: %d.%d V\n",
ian@0 103 extp->VccOptimal >> 8, extp->VccOptimal & 0xf);
ian@0 104 if (extp->VppOptimal)
ian@0 105 printk(" Vpp Programming Supply Optimum Program/Erase Voltage: %d.%d V\n",
ian@0 106 extp->VppOptimal >> 8, extp->VppOptimal & 0xf);
ian@0 107 }
ian@0 108 #endif
ian@0 109
ian@0 110 /* This routine is made available to other mtd code via
ian@0 111 * inter_module_register. It must only be accessed through
ian@0 112 * inter_module_get which will bump the use count of this module. The
ian@0 113 * addresses passed back in cfi are valid as long as the use count of
ian@0 114 * this module is non-zero, i.e. between inter_module_get and
ian@0 115 * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000.
ian@0 116 */
ian@0 117 struct mtd_info *cfi_cmdset_0020(struct map_info *map, int primary)
ian@0 118 {
ian@0 119 struct cfi_private *cfi = map->fldrv_priv;
ian@0 120 int i;
ian@0 121
ian@0 122 if (cfi->cfi_mode) {
ian@0 123 /*
ian@0 124 * It's a real CFI chip, not one for which the probe
ian@0 125 * routine faked a CFI structure. So we read the feature
ian@0 126 * table from it.
ian@0 127 */
ian@0 128 __u16 adr = primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
ian@0 129 struct cfi_pri_intelext *extp;
ian@0 130
ian@0 131 extp = (struct cfi_pri_intelext*)cfi_read_pri(map, adr, sizeof(*extp), "ST Microelectronics");
ian@0 132 if (!extp)
ian@0 133 return NULL;
ian@0 134
ian@0 135 if (extp->MajorVersion != '1' ||
ian@0 136 (extp->MinorVersion < '0' || extp->MinorVersion > '3')) {
ian@0 137 printk(KERN_ERR " Unknown ST Microelectronics"
ian@0 138 " Extended Query version %c.%c.\n",
ian@0 139 extp->MajorVersion, extp->MinorVersion);
ian@0 140 kfree(extp);
ian@0 141 return NULL;
ian@0 142 }
ian@0 143
ian@0 144 /* Do some byteswapping if necessary */
ian@0 145 extp->FeatureSupport = cfi32_to_cpu(extp->FeatureSupport);
ian@0 146 extp->BlkStatusRegMask = cfi32_to_cpu(extp->BlkStatusRegMask);
ian@0 147
ian@0 148 #ifdef DEBUG_CFI_FEATURES
ian@0 149 /* Tell the user about it in lots of lovely detail */
ian@0 150 cfi_tell_features(extp);
ian@0 151 #endif
ian@0 152
ian@0 153 /* Install our own private info structure */
ian@0 154 cfi->cmdset_priv = extp;
ian@0 155 }
ian@0 156
ian@0 157 for (i=0; i< cfi->numchips; i++) {
ian@0 158 cfi->chips[i].word_write_time = 128;
ian@0 159 cfi->chips[i].buffer_write_time = 128;
ian@0 160 cfi->chips[i].erase_time = 1024;
ian@0 161 }
ian@0 162
ian@0 163 return cfi_staa_setup(map);
ian@0 164 }
ian@0 165 EXPORT_SYMBOL_GPL(cfi_cmdset_0020);
ian@0 166
ian@0 167 static struct mtd_info *cfi_staa_setup(struct map_info *map)
ian@0 168 {
ian@0 169 struct cfi_private *cfi = map->fldrv_priv;
ian@0 170 struct mtd_info *mtd;
ian@0 171 unsigned long offset = 0;
ian@0 172 int i,j;
ian@0 173 unsigned long devsize = (1<<cfi->cfiq->DevSize) * cfi->interleave;
ian@0 174
ian@0 175 mtd = kmalloc(sizeof(*mtd), GFP_KERNEL);
ian@0 176 //printk(KERN_DEBUG "number of CFI chips: %d\n", cfi->numchips);
ian@0 177
ian@0 178 if (!mtd) {
ian@0 179 printk(KERN_ERR "Failed to allocate memory for MTD device\n");
ian@0 180 kfree(cfi->cmdset_priv);
ian@0 181 return NULL;
ian@0 182 }
ian@0 183
ian@0 184 memset(mtd, 0, sizeof(*mtd));
ian@0 185 mtd->priv = map;
ian@0 186 mtd->type = MTD_NORFLASH;
ian@0 187 mtd->size = devsize * cfi->numchips;
ian@0 188
ian@0 189 mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
ian@0 190 mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
ian@0 191 * mtd->numeraseregions, GFP_KERNEL);
ian@0 192 if (!mtd->eraseregions) {
ian@0 193 printk(KERN_ERR "Failed to allocate memory for MTD erase region info\n");
ian@0 194 kfree(cfi->cmdset_priv);
ian@0 195 kfree(mtd);
ian@0 196 return NULL;
ian@0 197 }
ian@0 198
ian@0 199 for (i=0; i<cfi->cfiq->NumEraseRegions; i++) {
ian@0 200 unsigned long ernum, ersize;
ian@0 201 ersize = ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interleave;
ian@0 202 ernum = (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
ian@0 203
ian@0 204 if (mtd->erasesize < ersize) {
ian@0 205 mtd->erasesize = ersize;
ian@0 206 }
ian@0 207 for (j=0; j<cfi->numchips; j++) {
ian@0 208 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset = (j*devsize)+offset;
ian@0 209 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize = ersize;
ian@0 210 mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks = ernum;
ian@0 211 }
ian@0 212 offset += (ersize * ernum);
ian@0 213 }
ian@0 214
ian@0 215 if (offset != devsize) {
ian@0 216 /* Argh */
ian@0 217 printk(KERN_WARNING "Sum of regions (%lx) != total size of set of interleaved chips (%lx)\n", offset, devsize);
ian@0 218 kfree(mtd->eraseregions);
ian@0 219 kfree(cfi->cmdset_priv);
ian@0 220 kfree(mtd);
ian@0 221 return NULL;
ian@0 222 }
ian@0 223
ian@0 224 for (i=0; i<mtd->numeraseregions;i++){
ian@0 225 printk(KERN_DEBUG "%d: offset=0x%x,size=0x%x,blocks=%d\n",
ian@0 226 i,mtd->eraseregions[i].offset,
ian@0 227 mtd->eraseregions[i].erasesize,
ian@0 228 mtd->eraseregions[i].numblocks);
ian@0 229 }
ian@0 230
ian@0 231 /* Also select the correct geometry setup too */
ian@0 232 mtd->erase = cfi_staa_erase_varsize;
ian@0 233 mtd->read = cfi_staa_read;
ian@0 234 mtd->write = cfi_staa_write_buffers;
ian@0 235 mtd->writev = cfi_staa_writev;
ian@0 236 mtd->sync = cfi_staa_sync;
ian@0 237 mtd->lock = cfi_staa_lock;
ian@0 238 mtd->unlock = cfi_staa_unlock;
ian@0 239 mtd->suspend = cfi_staa_suspend;
ian@0 240 mtd->resume = cfi_staa_resume;
ian@0 241 mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE;
ian@0 242 mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
ian@0 243 map->fldrv = &cfi_staa_chipdrv;
ian@0 244 __module_get(THIS_MODULE);
ian@0 245 mtd->name = map->name;
ian@0 246 return mtd;
ian@0 247 }
ian@0 248
ian@0 249
ian@0 250 static inline int do_read_onechip(struct map_info *map, struct flchip *chip, loff_t adr, size_t len, u_char *buf)
ian@0 251 {
ian@0 252 map_word status, status_OK;
ian@0 253 unsigned long timeo;
ian@0 254 DECLARE_WAITQUEUE(wait, current);
ian@0 255 int suspended = 0;
ian@0 256 unsigned long cmd_addr;
ian@0 257 struct cfi_private *cfi = map->fldrv_priv;
ian@0 258
ian@0 259 adr += chip->start;
ian@0 260
ian@0 261 /* Ensure cmd read/writes are aligned. */
ian@0 262 cmd_addr = adr & ~(map_bankwidth(map)-1);
ian@0 263
ian@0 264 /* Let's determine this according to the interleave only once */
ian@0 265 status_OK = CMD(0x80);
ian@0 266
ian@0 267 timeo = jiffies + HZ;
ian@0 268 retry:
ian@0 269 spin_lock_bh(chip->mutex);
ian@0 270
ian@0 271 /* Check that the chip's ready to talk to us.
ian@0 272 * If it's in FL_ERASING state, suspend it and make it talk now.
ian@0 273 */
ian@0 274 switch (chip->state) {
ian@0 275 case FL_ERASING:
ian@0 276 if (!(((struct cfi_pri_intelext *)cfi->cmdset_priv)->FeatureSupport & 2))
ian@0 277 goto sleep; /* We don't support erase suspend */
ian@0 278
ian@0 279 map_write (map, CMD(0xb0), cmd_addr);
ian@0 280 /* If the flash has finished erasing, then 'erase suspend'
ian@0 281 * appears to make some (28F320) flash devices switch to
ian@0 282 * 'read' mode. Make sure that we switch to 'read status'
ian@0 283 * mode so we get the right data. --rmk
ian@0 284 */
ian@0 285 map_write(map, CMD(0x70), cmd_addr);
ian@0 286 chip->oldstate = FL_ERASING;
ian@0 287 chip->state = FL_ERASE_SUSPENDING;
ian@0 288 // printk("Erase suspending at 0x%lx\n", cmd_addr);
ian@0 289 for (;;) {
ian@0 290 status = map_read(map, cmd_addr);
ian@0 291 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 292 break;
ian@0 293
ian@0 294 if (time_after(jiffies, timeo)) {
ian@0 295 /* Urgh */
ian@0 296 map_write(map, CMD(0xd0), cmd_addr);
ian@0 297 /* make sure we're in 'read status' mode */
ian@0 298 map_write(map, CMD(0x70), cmd_addr);
ian@0 299 chip->state = FL_ERASING;
ian@0 300 spin_unlock_bh(chip->mutex);
ian@0 301 printk(KERN_ERR "Chip not ready after erase "
ian@0 302 "suspended: status = 0x%lx\n", status.x[0]);
ian@0 303 return -EIO;
ian@0 304 }
ian@0 305
ian@0 306 spin_unlock_bh(chip->mutex);
ian@0 307 cfi_udelay(1);
ian@0 308 spin_lock_bh(chip->mutex);
ian@0 309 }
ian@0 310
ian@0 311 suspended = 1;
ian@0 312 map_write(map, CMD(0xff), cmd_addr);
ian@0 313 chip->state = FL_READY;
ian@0 314 break;
ian@0 315
ian@0 316 #if 0
ian@0 317 case FL_WRITING:
ian@0 318 /* Not quite yet */
ian@0 319 #endif
ian@0 320
ian@0 321 case FL_READY:
ian@0 322 break;
ian@0 323
ian@0 324 case FL_CFI_QUERY:
ian@0 325 case FL_JEDEC_QUERY:
ian@0 326 map_write(map, CMD(0x70), cmd_addr);
ian@0 327 chip->state = FL_STATUS;
ian@0 328
ian@0 329 case FL_STATUS:
ian@0 330 status = map_read(map, cmd_addr);
ian@0 331 if (map_word_andequal(map, status, status_OK, status_OK)) {
ian@0 332 map_write(map, CMD(0xff), cmd_addr);
ian@0 333 chip->state = FL_READY;
ian@0 334 break;
ian@0 335 }
ian@0 336
ian@0 337 /* Urgh. Chip not yet ready to talk to us. */
ian@0 338 if (time_after(jiffies, timeo)) {
ian@0 339 spin_unlock_bh(chip->mutex);
ian@0 340 printk(KERN_ERR "waiting for chip to be ready timed out in read. WSM status = %lx\n", status.x[0]);
ian@0 341 return -EIO;
ian@0 342 }
ian@0 343
ian@0 344 /* Latency issues. Drop the lock, wait a while and retry */
ian@0 345 spin_unlock_bh(chip->mutex);
ian@0 346 cfi_udelay(1);
ian@0 347 goto retry;
ian@0 348
ian@0 349 default:
ian@0 350 sleep:
ian@0 351 /* Stick ourselves on a wait queue to be woken when
ian@0 352 someone changes the status */
ian@0 353 set_current_state(TASK_UNINTERRUPTIBLE);
ian@0 354 add_wait_queue(&chip->wq, &wait);
ian@0 355 spin_unlock_bh(chip->mutex);
ian@0 356 schedule();
ian@0 357 remove_wait_queue(&chip->wq, &wait);
ian@0 358 timeo = jiffies + HZ;
ian@0 359 goto retry;
ian@0 360 }
ian@0 361
ian@0 362 map_copy_from(map, buf, adr, len);
ian@0 363
ian@0 364 if (suspended) {
ian@0 365 chip->state = chip->oldstate;
ian@0 366 /* What if one interleaved chip has finished and the
ian@0 367 other hasn't? The old code would leave the finished
ian@0 368 one in READY mode. That's bad, and caused -EROFS
ian@0 369 errors to be returned from do_erase_oneblock because
ian@0 370 that's the only bit it checked for at the time.
ian@0 371 As the state machine appears to explicitly allow
ian@0 372 sending the 0x70 (Read Status) command to an erasing
ian@0 373 chip and expecting it to be ignored, that's what we
ian@0 374 do. */
ian@0 375 map_write(map, CMD(0xd0), cmd_addr);
ian@0 376 map_write(map, CMD(0x70), cmd_addr);
ian@0 377 }
ian@0 378
ian@0 379 wake_up(&chip->wq);
ian@0 380 spin_unlock_bh(chip->mutex);
ian@0 381 return 0;
ian@0 382 }
ian@0 383
ian@0 384 static int cfi_staa_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf)
ian@0 385 {
ian@0 386 struct map_info *map = mtd->priv;
ian@0 387 struct cfi_private *cfi = map->fldrv_priv;
ian@0 388 unsigned long ofs;
ian@0 389 int chipnum;
ian@0 390 int ret = 0;
ian@0 391
ian@0 392 /* ofs: offset within the first chip that the first read should start */
ian@0 393 chipnum = (from >> cfi->chipshift);
ian@0 394 ofs = from - (chipnum << cfi->chipshift);
ian@0 395
ian@0 396 *retlen = 0;
ian@0 397
ian@0 398 while (len) {
ian@0 399 unsigned long thislen;
ian@0 400
ian@0 401 if (chipnum >= cfi->numchips)
ian@0 402 break;
ian@0 403
ian@0 404 if ((len + ofs -1) >> cfi->chipshift)
ian@0 405 thislen = (1<<cfi->chipshift) - ofs;
ian@0 406 else
ian@0 407 thislen = len;
ian@0 408
ian@0 409 ret = do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
ian@0 410 if (ret)
ian@0 411 break;
ian@0 412
ian@0 413 *retlen += thislen;
ian@0 414 len -= thislen;
ian@0 415 buf += thislen;
ian@0 416
ian@0 417 ofs = 0;
ian@0 418 chipnum++;
ian@0 419 }
ian@0 420 return ret;
ian@0 421 }
ian@0 422
ian@0 423 static inline int do_write_buffer(struct map_info *map, struct flchip *chip,
ian@0 424 unsigned long adr, const u_char *buf, int len)
ian@0 425 {
ian@0 426 struct cfi_private *cfi = map->fldrv_priv;
ian@0 427 map_word status, status_OK;
ian@0 428 unsigned long cmd_adr, timeo;
ian@0 429 DECLARE_WAITQUEUE(wait, current);
ian@0 430 int wbufsize, z;
ian@0 431
ian@0 432 /* M58LW064A requires bus alignment for buffer wriets -- saw */
ian@0 433 if (adr & (map_bankwidth(map)-1))
ian@0 434 return -EINVAL;
ian@0 435
ian@0 436 wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
ian@0 437 adr += chip->start;
ian@0 438 cmd_adr = adr & ~(wbufsize-1);
ian@0 439
ian@0 440 /* Let's determine this according to the interleave only once */
ian@0 441 status_OK = CMD(0x80);
ian@0 442
ian@0 443 timeo = jiffies + HZ;
ian@0 444 retry:
ian@0 445
ian@0 446 #ifdef DEBUG_CFI_FEATURES
ian@0 447 printk("%s: chip->state[%d]\n", __FUNCTION__, chip->state);
ian@0 448 #endif
ian@0 449 spin_lock_bh(chip->mutex);
ian@0 450
ian@0 451 /* Check that the chip's ready to talk to us.
ian@0 452 * Later, we can actually think about interrupting it
ian@0 453 * if it's in FL_ERASING state.
ian@0 454 * Not just yet, though.
ian@0 455 */
ian@0 456 switch (chip->state) {
ian@0 457 case FL_READY:
ian@0 458 break;
ian@0 459
ian@0 460 case FL_CFI_QUERY:
ian@0 461 case FL_JEDEC_QUERY:
ian@0 462 map_write(map, CMD(0x70), cmd_adr);
ian@0 463 chip->state = FL_STATUS;
ian@0 464 #ifdef DEBUG_CFI_FEATURES
ian@0 465 printk("%s: 1 status[%x]\n", __FUNCTION__, map_read(map, cmd_adr));
ian@0 466 #endif
ian@0 467
ian@0 468 case FL_STATUS:
ian@0 469 status = map_read(map, cmd_adr);
ian@0 470 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 471 break;
ian@0 472 /* Urgh. Chip not yet ready to talk to us. */
ian@0 473 if (time_after(jiffies, timeo)) {
ian@0 474 spin_unlock_bh(chip->mutex);
ian@0 475 printk(KERN_ERR "waiting for chip to be ready timed out in buffer write Xstatus = %lx, status = %lx\n",
ian@0 476 status.x[0], map_read(map, cmd_adr).x[0]);
ian@0 477 return -EIO;
ian@0 478 }
ian@0 479
ian@0 480 /* Latency issues. Drop the lock, wait a while and retry */
ian@0 481 spin_unlock_bh(chip->mutex);
ian@0 482 cfi_udelay(1);
ian@0 483 goto retry;
ian@0 484
ian@0 485 default:
ian@0 486 /* Stick ourselves on a wait queue to be woken when
ian@0 487 someone changes the status */
ian@0 488 set_current_state(TASK_UNINTERRUPTIBLE);
ian@0 489 add_wait_queue(&chip->wq, &wait);
ian@0 490 spin_unlock_bh(chip->mutex);
ian@0 491 schedule();
ian@0 492 remove_wait_queue(&chip->wq, &wait);
ian@0 493 timeo = jiffies + HZ;
ian@0 494 goto retry;
ian@0 495 }
ian@0 496
ian@0 497 ENABLE_VPP(map);
ian@0 498 map_write(map, CMD(0xe8), cmd_adr);
ian@0 499 chip->state = FL_WRITING_TO_BUFFER;
ian@0 500
ian@0 501 z = 0;
ian@0 502 for (;;) {
ian@0 503 status = map_read(map, cmd_adr);
ian@0 504 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 505 break;
ian@0 506
ian@0 507 spin_unlock_bh(chip->mutex);
ian@0 508 cfi_udelay(1);
ian@0 509 spin_lock_bh(chip->mutex);
ian@0 510
ian@0 511 if (++z > 100) {
ian@0 512 /* Argh. Not ready for write to buffer */
ian@0 513 DISABLE_VPP(map);
ian@0 514 map_write(map, CMD(0x70), cmd_adr);
ian@0 515 chip->state = FL_STATUS;
ian@0 516 spin_unlock_bh(chip->mutex);
ian@0 517 printk(KERN_ERR "Chip not ready for buffer write. Xstatus = %lx\n", status.x[0]);
ian@0 518 return -EIO;
ian@0 519 }
ian@0 520 }
ian@0 521
ian@0 522 /* Write length of data to come */
ian@0 523 map_write(map, CMD(len/map_bankwidth(map)-1), cmd_adr );
ian@0 524
ian@0 525 /* Write data */
ian@0 526 for (z = 0; z < len;
ian@0 527 z += map_bankwidth(map), buf += map_bankwidth(map)) {
ian@0 528 map_word d;
ian@0 529 d = map_word_load(map, buf);
ian@0 530 map_write(map, d, adr+z);
ian@0 531 }
ian@0 532 /* GO GO GO */
ian@0 533 map_write(map, CMD(0xd0), cmd_adr);
ian@0 534 chip->state = FL_WRITING;
ian@0 535
ian@0 536 spin_unlock_bh(chip->mutex);
ian@0 537 cfi_udelay(chip->buffer_write_time);
ian@0 538 spin_lock_bh(chip->mutex);
ian@0 539
ian@0 540 timeo = jiffies + (HZ/2);
ian@0 541 z = 0;
ian@0 542 for (;;) {
ian@0 543 if (chip->state != FL_WRITING) {
ian@0 544 /* Someone's suspended the write. Sleep */
ian@0 545 set_current_state(TASK_UNINTERRUPTIBLE);
ian@0 546 add_wait_queue(&chip->wq, &wait);
ian@0 547 spin_unlock_bh(chip->mutex);
ian@0 548 schedule();
ian@0 549 remove_wait_queue(&chip->wq, &wait);
ian@0 550 timeo = jiffies + (HZ / 2); /* FIXME */
ian@0 551 spin_lock_bh(chip->mutex);
ian@0 552 continue;
ian@0 553 }
ian@0 554
ian@0 555 status = map_read(map, cmd_adr);
ian@0 556 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 557 break;
ian@0 558
ian@0 559 /* OK Still waiting */
ian@0 560 if (time_after(jiffies, timeo)) {
ian@0 561 /* clear status */
ian@0 562 map_write(map, CMD(0x50), cmd_adr);
ian@0 563 /* put back into read status register mode */
ian@0 564 map_write(map, CMD(0x70), adr);
ian@0 565 chip->state = FL_STATUS;
ian@0 566 DISABLE_VPP(map);
ian@0 567 spin_unlock_bh(chip->mutex);
ian@0 568 printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n");
ian@0 569 return -EIO;
ian@0 570 }
ian@0 571
ian@0 572 /* Latency issues. Drop the lock, wait a while and retry */
ian@0 573 spin_unlock_bh(chip->mutex);
ian@0 574 cfi_udelay(1);
ian@0 575 z++;
ian@0 576 spin_lock_bh(chip->mutex);
ian@0 577 }
ian@0 578 if (!z) {
ian@0 579 chip->buffer_write_time--;
ian@0 580 if (!chip->buffer_write_time)
ian@0 581 chip->buffer_write_time++;
ian@0 582 }
ian@0 583 if (z > 1)
ian@0 584 chip->buffer_write_time++;
ian@0 585
ian@0 586 /* Done and happy. */
ian@0 587 DISABLE_VPP(map);
ian@0 588 chip->state = FL_STATUS;
ian@0 589
ian@0 590 /* check for errors: 'lock bit', 'VPP', 'dead cell'/'unerased cell' or 'incorrect cmd' -- saw */
ian@0 591 if (map_word_bitsset(map, status, CMD(0x3a))) {
ian@0 592 #ifdef DEBUG_CFI_FEATURES
ian@0 593 printk("%s: 2 status[%lx]\n", __FUNCTION__, status.x[0]);
ian@0 594 #endif
ian@0 595 /* clear status */
ian@0 596 map_write(map, CMD(0x50), cmd_adr);
ian@0 597 /* put back into read status register mode */
ian@0 598 map_write(map, CMD(0x70), adr);
ian@0 599 wake_up(&chip->wq);
ian@0 600 spin_unlock_bh(chip->mutex);
ian@0 601 return map_word_bitsset(map, status, CMD(0x02)) ? -EROFS : -EIO;
ian@0 602 }
ian@0 603 wake_up(&chip->wq);
ian@0 604 spin_unlock_bh(chip->mutex);
ian@0 605
ian@0 606 return 0;
ian@0 607 }
ian@0 608
ian@0 609 static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to,
ian@0 610 size_t len, size_t *retlen, const u_char *buf)
ian@0 611 {
ian@0 612 struct map_info *map = mtd->priv;
ian@0 613 struct cfi_private *cfi = map->fldrv_priv;
ian@0 614 int wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
ian@0 615 int ret = 0;
ian@0 616 int chipnum;
ian@0 617 unsigned long ofs;
ian@0 618
ian@0 619 *retlen = 0;
ian@0 620 if (!len)
ian@0 621 return 0;
ian@0 622
ian@0 623 chipnum = to >> cfi->chipshift;
ian@0 624 ofs = to - (chipnum << cfi->chipshift);
ian@0 625
ian@0 626 #ifdef DEBUG_CFI_FEATURES
ian@0 627 printk("%s: map_bankwidth(map)[%x]\n", __FUNCTION__, map_bankwidth(map));
ian@0 628 printk("%s: chipnum[%x] wbufsize[%x]\n", __FUNCTION__, chipnum, wbufsize);
ian@0 629 printk("%s: ofs[%x] len[%x]\n", __FUNCTION__, ofs, len);
ian@0 630 #endif
ian@0 631
ian@0 632 /* Write buffer is worth it only if more than one word to write... */
ian@0 633 while (len > 0) {
ian@0 634 /* We must not cross write block boundaries */
ian@0 635 int size = wbufsize - (ofs & (wbufsize-1));
ian@0 636
ian@0 637 if (size > len)
ian@0 638 size = len;
ian@0 639
ian@0 640 ret = do_write_buffer(map, &cfi->chips[chipnum],
ian@0 641 ofs, buf, size);
ian@0 642 if (ret)
ian@0 643 return ret;
ian@0 644
ian@0 645 ofs += size;
ian@0 646 buf += size;
ian@0 647 (*retlen) += size;
ian@0 648 len -= size;
ian@0 649
ian@0 650 if (ofs >> cfi->chipshift) {
ian@0 651 chipnum ++;
ian@0 652 ofs = 0;
ian@0 653 if (chipnum == cfi->numchips)
ian@0 654 return 0;
ian@0 655 }
ian@0 656 }
ian@0 657
ian@0 658 return 0;
ian@0 659 }
ian@0 660
ian@0 661 /*
ian@0 662 * Writev for ECC-Flashes is a little more complicated. We need to maintain
ian@0 663 * a small buffer for this.
ian@0 664 * XXX: If the buffer size is not a multiple of 2, this will break
ian@0 665 */
ian@0 666 #define ECCBUF_SIZE (mtd->eccsize)
ian@0 667 #define ECCBUF_DIV(x) ((x) & ~(ECCBUF_SIZE - 1))
ian@0 668 #define ECCBUF_MOD(x) ((x) & (ECCBUF_SIZE - 1))
ian@0 669 static int
ian@0 670 cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs,
ian@0 671 unsigned long count, loff_t to, size_t *retlen)
ian@0 672 {
ian@0 673 unsigned long i;
ian@0 674 size_t totlen = 0, thislen;
ian@0 675 int ret = 0;
ian@0 676 size_t buflen = 0;
ian@0 677 static char *buffer;
ian@0 678
ian@0 679 if (!ECCBUF_SIZE) {
ian@0 680 /* We should fall back to a general writev implementation.
ian@0 681 * Until that is written, just break.
ian@0 682 */
ian@0 683 return -EIO;
ian@0 684 }
ian@0 685 buffer = kmalloc(ECCBUF_SIZE, GFP_KERNEL);
ian@0 686 if (!buffer)
ian@0 687 return -ENOMEM;
ian@0 688
ian@0 689 for (i=0; i<count; i++) {
ian@0 690 size_t elem_len = vecs[i].iov_len;
ian@0 691 void *elem_base = vecs[i].iov_base;
ian@0 692 if (!elem_len) /* FIXME: Might be unnecessary. Check that */
ian@0 693 continue;
ian@0 694 if (buflen) { /* cut off head */
ian@0 695 if (buflen + elem_len < ECCBUF_SIZE) { /* just accumulate */
ian@0 696 memcpy(buffer+buflen, elem_base, elem_len);
ian@0 697 buflen += elem_len;
ian@0 698 continue;
ian@0 699 }
ian@0 700 memcpy(buffer+buflen, elem_base, ECCBUF_SIZE-buflen);
ian@0 701 ret = mtd->write(mtd, to, ECCBUF_SIZE, &thislen, buffer);
ian@0 702 totlen += thislen;
ian@0 703 if (ret || thislen != ECCBUF_SIZE)
ian@0 704 goto write_error;
ian@0 705 elem_len -= thislen-buflen;
ian@0 706 elem_base += thislen-buflen;
ian@0 707 to += ECCBUF_SIZE;
ian@0 708 }
ian@0 709 if (ECCBUF_DIV(elem_len)) { /* write clean aligned data */
ian@0 710 ret = mtd->write(mtd, to, ECCBUF_DIV(elem_len), &thislen, elem_base);
ian@0 711 totlen += thislen;
ian@0 712 if (ret || thislen != ECCBUF_DIV(elem_len))
ian@0 713 goto write_error;
ian@0 714 to += thislen;
ian@0 715 }
ian@0 716 buflen = ECCBUF_MOD(elem_len); /* cut off tail */
ian@0 717 if (buflen) {
ian@0 718 memset(buffer, 0xff, ECCBUF_SIZE);
ian@0 719 memcpy(buffer, elem_base + thislen, buflen);
ian@0 720 }
ian@0 721 }
ian@0 722 if (buflen) { /* flush last page, even if not full */
ian@0 723 /* This is sometimes intended behaviour, really */
ian@0 724 ret = mtd->write(mtd, to, buflen, &thislen, buffer);
ian@0 725 totlen += thislen;
ian@0 726 if (ret || thislen != ECCBUF_SIZE)
ian@0 727 goto write_error;
ian@0 728 }
ian@0 729 write_error:
ian@0 730 if (retlen)
ian@0 731 *retlen = totlen;
ian@0 732 kfree(buffer);
ian@0 733 return ret;
ian@0 734 }
ian@0 735
ian@0 736
ian@0 737 static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
ian@0 738 {
ian@0 739 struct cfi_private *cfi = map->fldrv_priv;
ian@0 740 map_word status, status_OK;
ian@0 741 unsigned long timeo;
ian@0 742 int retries = 3;
ian@0 743 DECLARE_WAITQUEUE(wait, current);
ian@0 744 int ret = 0;
ian@0 745
ian@0 746 adr += chip->start;
ian@0 747
ian@0 748 /* Let's determine this according to the interleave only once */
ian@0 749 status_OK = CMD(0x80);
ian@0 750
ian@0 751 timeo = jiffies + HZ;
ian@0 752 retry:
ian@0 753 spin_lock_bh(chip->mutex);
ian@0 754
ian@0 755 /* Check that the chip's ready to talk to us. */
ian@0 756 switch (chip->state) {
ian@0 757 case FL_CFI_QUERY:
ian@0 758 case FL_JEDEC_QUERY:
ian@0 759 case FL_READY:
ian@0 760 map_write(map, CMD(0x70), adr);
ian@0 761 chip->state = FL_STATUS;
ian@0 762
ian@0 763 case FL_STATUS:
ian@0 764 status = map_read(map, adr);
ian@0 765 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 766 break;
ian@0 767
ian@0 768 /* Urgh. Chip not yet ready to talk to us. */
ian@0 769 if (time_after(jiffies, timeo)) {
ian@0 770 spin_unlock_bh(chip->mutex);
ian@0 771 printk(KERN_ERR "waiting for chip to be ready timed out in erase\n");
ian@0 772 return -EIO;
ian@0 773 }
ian@0 774
ian@0 775 /* Latency issues. Drop the lock, wait a while and retry */
ian@0 776 spin_unlock_bh(chip->mutex);
ian@0 777 cfi_udelay(1);
ian@0 778 goto retry;
ian@0 779
ian@0 780 default:
ian@0 781 /* Stick ourselves on a wait queue to be woken when
ian@0 782 someone changes the status */
ian@0 783 set_current_state(TASK_UNINTERRUPTIBLE);
ian@0 784 add_wait_queue(&chip->wq, &wait);
ian@0 785 spin_unlock_bh(chip->mutex);
ian@0 786 schedule();
ian@0 787 remove_wait_queue(&chip->wq, &wait);
ian@0 788 timeo = jiffies + HZ;
ian@0 789 goto retry;
ian@0 790 }
ian@0 791
ian@0 792 ENABLE_VPP(map);
ian@0 793 /* Clear the status register first */
ian@0 794 map_write(map, CMD(0x50), adr);
ian@0 795
ian@0 796 /* Now erase */
ian@0 797 map_write(map, CMD(0x20), adr);
ian@0 798 map_write(map, CMD(0xD0), adr);
ian@0 799 chip->state = FL_ERASING;
ian@0 800
ian@0 801 spin_unlock_bh(chip->mutex);
ian@0 802 msleep(1000);
ian@0 803 spin_lock_bh(chip->mutex);
ian@0 804
ian@0 805 /* FIXME. Use a timer to check this, and return immediately. */
ian@0 806 /* Once the state machine's known to be working I'll do that */
ian@0 807
ian@0 808 timeo = jiffies + (HZ*20);
ian@0 809 for (;;) {
ian@0 810 if (chip->state != FL_ERASING) {
ian@0 811 /* Someone's suspended the erase. Sleep */
ian@0 812 set_current_state(TASK_UNINTERRUPTIBLE);
ian@0 813 add_wait_queue(&chip->wq, &wait);
ian@0 814 spin_unlock_bh(chip->mutex);
ian@0 815 schedule();
ian@0 816 remove_wait_queue(&chip->wq, &wait);
ian@0 817 timeo = jiffies + (HZ*20); /* FIXME */
ian@0 818 spin_lock_bh(chip->mutex);
ian@0 819 continue;
ian@0 820 }
ian@0 821
ian@0 822 status = map_read(map, adr);
ian@0 823 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 824 break;
ian@0 825
ian@0 826 /* OK Still waiting */
ian@0 827 if (time_after(jiffies, timeo)) {
ian@0 828 map_write(map, CMD(0x70), adr);
ian@0 829 chip->state = FL_STATUS;
ian@0 830 printk(KERN_ERR "waiting for erase to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]);
ian@0 831 DISABLE_VPP(map);
ian@0 832 spin_unlock_bh(chip->mutex);
ian@0 833 return -EIO;
ian@0 834 }
ian@0 835
ian@0 836 /* Latency issues. Drop the lock, wait a while and retry */
ian@0 837 spin_unlock_bh(chip->mutex);
ian@0 838 cfi_udelay(1);
ian@0 839 spin_lock_bh(chip->mutex);
ian@0 840 }
ian@0 841
ian@0 842 DISABLE_VPP(map);
ian@0 843 ret = 0;
ian@0 844
ian@0 845 /* We've broken this before. It doesn't hurt to be safe */
ian@0 846 map_write(map, CMD(0x70), adr);
ian@0 847 chip->state = FL_STATUS;
ian@0 848 status = map_read(map, adr);
ian@0 849
ian@0 850 /* check for lock bit */
ian@0 851 if (map_word_bitsset(map, status, CMD(0x3a))) {
ian@0 852 unsigned char chipstatus = status.x[0];
ian@0 853 if (!map_word_equal(map, status, CMD(chipstatus))) {
ian@0 854 int i, w;
ian@0 855 for (w=0; w<map_words(map); w++) {
ian@0 856 for (i = 0; i<cfi_interleave(cfi); i++) {
ian@0 857 chipstatus |= status.x[w] >> (cfi->device_type * 8);
ian@0 858 }
ian@0 859 }
ian@0 860 printk(KERN_WARNING "Status is not identical for all chips: 0x%lx. Merging to give 0x%02x\n",
ian@0 861 status.x[0], chipstatus);
ian@0 862 }
ian@0 863 /* Reset the error bits */
ian@0 864 map_write(map, CMD(0x50), adr);
ian@0 865 map_write(map, CMD(0x70), adr);
ian@0 866
ian@0 867 if ((chipstatus & 0x30) == 0x30) {
ian@0 868 printk(KERN_NOTICE "Chip reports improper command sequence: status 0x%x\n", chipstatus);
ian@0 869 ret = -EIO;
ian@0 870 } else if (chipstatus & 0x02) {
ian@0 871 /* Protection bit set */
ian@0 872 ret = -EROFS;
ian@0 873 } else if (chipstatus & 0x8) {
ian@0 874 /* Voltage */
ian@0 875 printk(KERN_WARNING "Chip reports voltage low on erase: status 0x%x\n", chipstatus);
ian@0 876 ret = -EIO;
ian@0 877 } else if (chipstatus & 0x20) {
ian@0 878 if (retries--) {
ian@0 879 printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x. Retrying...\n", adr, chipstatus);
ian@0 880 timeo = jiffies + HZ;
ian@0 881 chip->state = FL_STATUS;
ian@0 882 spin_unlock_bh(chip->mutex);
ian@0 883 goto retry;
ian@0 884 }
ian@0 885 printk(KERN_DEBUG "Chip erase failed at 0x%08lx: status 0x%x\n", adr, chipstatus);
ian@0 886 ret = -EIO;
ian@0 887 }
ian@0 888 }
ian@0 889
ian@0 890 wake_up(&chip->wq);
ian@0 891 spin_unlock_bh(chip->mutex);
ian@0 892 return ret;
ian@0 893 }
ian@0 894
ian@0 895 int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
ian@0 896 { struct map_info *map = mtd->priv;
ian@0 897 struct cfi_private *cfi = map->fldrv_priv;
ian@0 898 unsigned long adr, len;
ian@0 899 int chipnum, ret = 0;
ian@0 900 int i, first;
ian@0 901 struct mtd_erase_region_info *regions = mtd->eraseregions;
ian@0 902
ian@0 903 if (instr->addr > mtd->size)
ian@0 904 return -EINVAL;
ian@0 905
ian@0 906 if ((instr->len + instr->addr) > mtd->size)
ian@0 907 return -EINVAL;
ian@0 908
ian@0 909 /* Check that both start and end of the requested erase are
ian@0 910 * aligned with the erasesize at the appropriate addresses.
ian@0 911 */
ian@0 912
ian@0 913 i = 0;
ian@0 914
ian@0 915 /* Skip all erase regions which are ended before the start of
ian@0 916 the requested erase. Actually, to save on the calculations,
ian@0 917 we skip to the first erase region which starts after the
ian@0 918 start of the requested erase, and then go back one.
ian@0 919 */
ian@0 920
ian@0 921 while (i < mtd->numeraseregions && instr->addr >= regions[i].offset)
ian@0 922 i++;
ian@0 923 i--;
ian@0 924
ian@0 925 /* OK, now i is pointing at the erase region in which this
ian@0 926 erase request starts. Check the start of the requested
ian@0 927 erase range is aligned with the erase size which is in
ian@0 928 effect here.
ian@0 929 */
ian@0 930
ian@0 931 if (instr->addr & (regions[i].erasesize-1))
ian@0 932 return -EINVAL;
ian@0 933
ian@0 934 /* Remember the erase region we start on */
ian@0 935 first = i;
ian@0 936
ian@0 937 /* Next, check that the end of the requested erase is aligned
ian@0 938 * with the erase region at that address.
ian@0 939 */
ian@0 940
ian@0 941 while (i<mtd->numeraseregions && (instr->addr + instr->len) >= regions[i].offset)
ian@0 942 i++;
ian@0 943
ian@0 944 /* As before, drop back one to point at the region in which
ian@0 945 the address actually falls
ian@0 946 */
ian@0 947 i--;
ian@0 948
ian@0 949 if ((instr->addr + instr->len) & (regions[i].erasesize-1))
ian@0 950 return -EINVAL;
ian@0 951
ian@0 952 chipnum = instr->addr >> cfi->chipshift;
ian@0 953 adr = instr->addr - (chipnum << cfi->chipshift);
ian@0 954 len = instr->len;
ian@0 955
ian@0 956 i=first;
ian@0 957
ian@0 958 while(len) {
ian@0 959 ret = do_erase_oneblock(map, &cfi->chips[chipnum], adr);
ian@0 960
ian@0 961 if (ret)
ian@0 962 return ret;
ian@0 963
ian@0 964 adr += regions[i].erasesize;
ian@0 965 len -= regions[i].erasesize;
ian@0 966
ian@0 967 if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
ian@0 968 i++;
ian@0 969
ian@0 970 if (adr >> cfi->chipshift) {
ian@0 971 adr = 0;
ian@0 972 chipnum++;
ian@0 973
ian@0 974 if (chipnum >= cfi->numchips)
ian@0 975 break;
ian@0 976 }
ian@0 977 }
ian@0 978
ian@0 979 instr->state = MTD_ERASE_DONE;
ian@0 980 mtd_erase_callback(instr);
ian@0 981
ian@0 982 return 0;
ian@0 983 }
ian@0 984
ian@0 985 static void cfi_staa_sync (struct mtd_info *mtd)
ian@0 986 {
ian@0 987 struct map_info *map = mtd->priv;
ian@0 988 struct cfi_private *cfi = map->fldrv_priv;
ian@0 989 int i;
ian@0 990 struct flchip *chip;
ian@0 991 int ret = 0;
ian@0 992 DECLARE_WAITQUEUE(wait, current);
ian@0 993
ian@0 994 for (i=0; !ret && i<cfi->numchips; i++) {
ian@0 995 chip = &cfi->chips[i];
ian@0 996
ian@0 997 retry:
ian@0 998 spin_lock_bh(chip->mutex);
ian@0 999
ian@0 1000 switch(chip->state) {
ian@0 1001 case FL_READY:
ian@0 1002 case FL_STATUS:
ian@0 1003 case FL_CFI_QUERY:
ian@0 1004 case FL_JEDEC_QUERY:
ian@0 1005 chip->oldstate = chip->state;
ian@0 1006 chip->state = FL_SYNCING;
ian@0 1007 /* No need to wake_up() on this state change -
ian@0 1008 * as the whole point is that nobody can do anything
ian@0 1009 * with the chip now anyway.
ian@0 1010 */
ian@0 1011 case FL_SYNCING:
ian@0 1012 spin_unlock_bh(chip->mutex);
ian@0 1013 break;
ian@0 1014
ian@0 1015 default:
ian@0 1016 /* Not an idle state */
ian@0 1017 add_wait_queue(&chip->wq, &wait);
ian@0 1018
ian@0 1019 spin_unlock_bh(chip->mutex);
ian@0 1020 schedule();
ian@0 1021 remove_wait_queue(&chip->wq, &wait);
ian@0 1022
ian@0 1023 goto retry;
ian@0 1024 }
ian@0 1025 }
ian@0 1026
ian@0 1027 /* Unlock the chips again */
ian@0 1028
ian@0 1029 for (i--; i >=0; i--) {
ian@0 1030 chip = &cfi->chips[i];
ian@0 1031
ian@0 1032 spin_lock_bh(chip->mutex);
ian@0 1033
ian@0 1034 if (chip->state == FL_SYNCING) {
ian@0 1035 chip->state = chip->oldstate;
ian@0 1036 wake_up(&chip->wq);
ian@0 1037 }
ian@0 1038 spin_unlock_bh(chip->mutex);
ian@0 1039 }
ian@0 1040 }
ian@0 1041
ian@0 1042 static inline int do_lock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
ian@0 1043 {
ian@0 1044 struct cfi_private *cfi = map->fldrv_priv;
ian@0 1045 map_word status, status_OK;
ian@0 1046 unsigned long timeo = jiffies + HZ;
ian@0 1047 DECLARE_WAITQUEUE(wait, current);
ian@0 1048
ian@0 1049 adr += chip->start;
ian@0 1050
ian@0 1051 /* Let's determine this according to the interleave only once */
ian@0 1052 status_OK = CMD(0x80);
ian@0 1053
ian@0 1054 timeo = jiffies + HZ;
ian@0 1055 retry:
ian@0 1056 spin_lock_bh(chip->mutex);
ian@0 1057
ian@0 1058 /* Check that the chip's ready to talk to us. */
ian@0 1059 switch (chip->state) {
ian@0 1060 case FL_CFI_QUERY:
ian@0 1061 case FL_JEDEC_QUERY:
ian@0 1062 case FL_READY:
ian@0 1063 map_write(map, CMD(0x70), adr);
ian@0 1064 chip->state = FL_STATUS;
ian@0 1065
ian@0 1066 case FL_STATUS:
ian@0 1067 status = map_read(map, adr);
ian@0 1068 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 1069 break;
ian@0 1070
ian@0 1071 /* Urgh. Chip not yet ready to talk to us. */
ian@0 1072 if (time_after(jiffies, timeo)) {
ian@0 1073 spin_unlock_bh(chip->mutex);
ian@0 1074 printk(KERN_ERR "waiting for chip to be ready timed out in lock\n");
ian@0 1075 return -EIO;
ian@0 1076 }
ian@0 1077
ian@0 1078 /* Latency issues. Drop the lock, wait a while and retry */
ian@0 1079 spin_unlock_bh(chip->mutex);
ian@0 1080 cfi_udelay(1);
ian@0 1081 goto retry;
ian@0 1082
ian@0 1083 default:
ian@0 1084 /* Stick ourselves on a wait queue to be woken when
ian@0 1085 someone changes the status */
ian@0 1086 set_current_state(TASK_UNINTERRUPTIBLE);
ian@0 1087 add_wait_queue(&chip->wq, &wait);
ian@0 1088 spin_unlock_bh(chip->mutex);
ian@0 1089 schedule();
ian@0 1090 remove_wait_queue(&chip->wq, &wait);
ian@0 1091 timeo = jiffies + HZ;
ian@0 1092 goto retry;
ian@0 1093 }
ian@0 1094
ian@0 1095 ENABLE_VPP(map);
ian@0 1096 map_write(map, CMD(0x60), adr);
ian@0 1097 map_write(map, CMD(0x01), adr);
ian@0 1098 chip->state = FL_LOCKING;
ian@0 1099
ian@0 1100 spin_unlock_bh(chip->mutex);
ian@0 1101 msleep(1000);
ian@0 1102 spin_lock_bh(chip->mutex);
ian@0 1103
ian@0 1104 /* FIXME. Use a timer to check this, and return immediately. */
ian@0 1105 /* Once the state machine's known to be working I'll do that */
ian@0 1106
ian@0 1107 timeo = jiffies + (HZ*2);
ian@0 1108 for (;;) {
ian@0 1109
ian@0 1110 status = map_read(map, adr);
ian@0 1111 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 1112 break;
ian@0 1113
ian@0 1114 /* OK Still waiting */
ian@0 1115 if (time_after(jiffies, timeo)) {
ian@0 1116 map_write(map, CMD(0x70), adr);
ian@0 1117 chip->state = FL_STATUS;
ian@0 1118 printk(KERN_ERR "waiting for lock to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]);
ian@0 1119 DISABLE_VPP(map);
ian@0 1120 spin_unlock_bh(chip->mutex);
ian@0 1121 return -EIO;
ian@0 1122 }
ian@0 1123
ian@0 1124 /* Latency issues. Drop the lock, wait a while and retry */
ian@0 1125 spin_unlock_bh(chip->mutex);
ian@0 1126 cfi_udelay(1);
ian@0 1127 spin_lock_bh(chip->mutex);
ian@0 1128 }
ian@0 1129
ian@0 1130 /* Done and happy. */
ian@0 1131 chip->state = FL_STATUS;
ian@0 1132 DISABLE_VPP(map);
ian@0 1133 wake_up(&chip->wq);
ian@0 1134 spin_unlock_bh(chip->mutex);
ian@0 1135 return 0;
ian@0 1136 }
ian@0 1137 static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
ian@0 1138 {
ian@0 1139 struct map_info *map = mtd->priv;
ian@0 1140 struct cfi_private *cfi = map->fldrv_priv;
ian@0 1141 unsigned long adr;
ian@0 1142 int chipnum, ret = 0;
ian@0 1143 #ifdef DEBUG_LOCK_BITS
ian@0 1144 int ofs_factor = cfi->interleave * cfi->device_type;
ian@0 1145 #endif
ian@0 1146
ian@0 1147 if (ofs & (mtd->erasesize - 1))
ian@0 1148 return -EINVAL;
ian@0 1149
ian@0 1150 if (len & (mtd->erasesize -1))
ian@0 1151 return -EINVAL;
ian@0 1152
ian@0 1153 if ((len + ofs) > mtd->size)
ian@0 1154 return -EINVAL;
ian@0 1155
ian@0 1156 chipnum = ofs >> cfi->chipshift;
ian@0 1157 adr = ofs - (chipnum << cfi->chipshift);
ian@0 1158
ian@0 1159 while(len) {
ian@0 1160
ian@0 1161 #ifdef DEBUG_LOCK_BITS
ian@0 1162 cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
ian@0 1163 printk("before lock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor)));
ian@0 1164 cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
ian@0 1165 #endif
ian@0 1166
ian@0 1167 ret = do_lock_oneblock(map, &cfi->chips[chipnum], adr);
ian@0 1168
ian@0 1169 #ifdef DEBUG_LOCK_BITS
ian@0 1170 cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
ian@0 1171 printk("after lock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor)));
ian@0 1172 cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
ian@0 1173 #endif
ian@0 1174
ian@0 1175 if (ret)
ian@0 1176 return ret;
ian@0 1177
ian@0 1178 adr += mtd->erasesize;
ian@0 1179 len -= mtd->erasesize;
ian@0 1180
ian@0 1181 if (adr >> cfi->chipshift) {
ian@0 1182 adr = 0;
ian@0 1183 chipnum++;
ian@0 1184
ian@0 1185 if (chipnum >= cfi->numchips)
ian@0 1186 break;
ian@0 1187 }
ian@0 1188 }
ian@0 1189 return 0;
ian@0 1190 }
ian@0 1191 static inline int do_unlock_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
ian@0 1192 {
ian@0 1193 struct cfi_private *cfi = map->fldrv_priv;
ian@0 1194 map_word status, status_OK;
ian@0 1195 unsigned long timeo = jiffies + HZ;
ian@0 1196 DECLARE_WAITQUEUE(wait, current);
ian@0 1197
ian@0 1198 adr += chip->start;
ian@0 1199
ian@0 1200 /* Let's determine this according to the interleave only once */
ian@0 1201 status_OK = CMD(0x80);
ian@0 1202
ian@0 1203 timeo = jiffies + HZ;
ian@0 1204 retry:
ian@0 1205 spin_lock_bh(chip->mutex);
ian@0 1206
ian@0 1207 /* Check that the chip's ready to talk to us. */
ian@0 1208 switch (chip->state) {
ian@0 1209 case FL_CFI_QUERY:
ian@0 1210 case FL_JEDEC_QUERY:
ian@0 1211 case FL_READY:
ian@0 1212 map_write(map, CMD(0x70), adr);
ian@0 1213 chip->state = FL_STATUS;
ian@0 1214
ian@0 1215 case FL_STATUS:
ian@0 1216 status = map_read(map, adr);
ian@0 1217 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 1218 break;
ian@0 1219
ian@0 1220 /* Urgh. Chip not yet ready to talk to us. */
ian@0 1221 if (time_after(jiffies, timeo)) {
ian@0 1222 spin_unlock_bh(chip->mutex);
ian@0 1223 printk(KERN_ERR "waiting for chip to be ready timed out in unlock\n");
ian@0 1224 return -EIO;
ian@0 1225 }
ian@0 1226
ian@0 1227 /* Latency issues. Drop the lock, wait a while and retry */
ian@0 1228 spin_unlock_bh(chip->mutex);
ian@0 1229 cfi_udelay(1);
ian@0 1230 goto retry;
ian@0 1231
ian@0 1232 default:
ian@0 1233 /* Stick ourselves on a wait queue to be woken when
ian@0 1234 someone changes the status */
ian@0 1235 set_current_state(TASK_UNINTERRUPTIBLE);
ian@0 1236 add_wait_queue(&chip->wq, &wait);
ian@0 1237 spin_unlock_bh(chip->mutex);
ian@0 1238 schedule();
ian@0 1239 remove_wait_queue(&chip->wq, &wait);
ian@0 1240 timeo = jiffies + HZ;
ian@0 1241 goto retry;
ian@0 1242 }
ian@0 1243
ian@0 1244 ENABLE_VPP(map);
ian@0 1245 map_write(map, CMD(0x60), adr);
ian@0 1246 map_write(map, CMD(0xD0), adr);
ian@0 1247 chip->state = FL_UNLOCKING;
ian@0 1248
ian@0 1249 spin_unlock_bh(chip->mutex);
ian@0 1250 msleep(1000);
ian@0 1251 spin_lock_bh(chip->mutex);
ian@0 1252
ian@0 1253 /* FIXME. Use a timer to check this, and return immediately. */
ian@0 1254 /* Once the state machine's known to be working I'll do that */
ian@0 1255
ian@0 1256 timeo = jiffies + (HZ*2);
ian@0 1257 for (;;) {
ian@0 1258
ian@0 1259 status = map_read(map, adr);
ian@0 1260 if (map_word_andequal(map, status, status_OK, status_OK))
ian@0 1261 break;
ian@0 1262
ian@0 1263 /* OK Still waiting */
ian@0 1264 if (time_after(jiffies, timeo)) {
ian@0 1265 map_write(map, CMD(0x70), adr);
ian@0 1266 chip->state = FL_STATUS;
ian@0 1267 printk(KERN_ERR "waiting for unlock to complete timed out. Xstatus = %lx, status = %lx.\n", status.x[0], map_read(map, adr).x[0]);
ian@0 1268 DISABLE_VPP(map);
ian@0 1269 spin_unlock_bh(chip->mutex);
ian@0 1270 return -EIO;
ian@0 1271 }
ian@0 1272
ian@0 1273 /* Latency issues. Drop the unlock, wait a while and retry */
ian@0 1274 spin_unlock_bh(chip->mutex);
ian@0 1275 cfi_udelay(1);
ian@0 1276 spin_lock_bh(chip->mutex);
ian@0 1277 }
ian@0 1278
ian@0 1279 /* Done and happy. */
ian@0 1280 chip->state = FL_STATUS;
ian@0 1281 DISABLE_VPP(map);
ian@0 1282 wake_up(&chip->wq);
ian@0 1283 spin_unlock_bh(chip->mutex);
ian@0 1284 return 0;
ian@0 1285 }
ian@0 1286 static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
ian@0 1287 {
ian@0 1288 struct map_info *map = mtd->priv;
ian@0 1289 struct cfi_private *cfi = map->fldrv_priv;
ian@0 1290 unsigned long adr;
ian@0 1291 int chipnum, ret = 0;
ian@0 1292 #ifdef DEBUG_LOCK_BITS
ian@0 1293 int ofs_factor = cfi->interleave * cfi->device_type;
ian@0 1294 #endif
ian@0 1295
ian@0 1296 chipnum = ofs >> cfi->chipshift;
ian@0 1297 adr = ofs - (chipnum << cfi->chipshift);
ian@0 1298
ian@0 1299 #ifdef DEBUG_LOCK_BITS
ian@0 1300 {
ian@0 1301 unsigned long temp_adr = adr;
ian@0 1302 unsigned long temp_len = len;
ian@0 1303
ian@0 1304 cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
ian@0 1305 while (temp_len) {
ian@0 1306 printk("before unlock %x: block status register is %x\n",temp_adr,cfi_read_query(map, temp_adr+(2*ofs_factor)));
ian@0 1307 temp_adr += mtd->erasesize;
ian@0 1308 temp_len -= mtd->erasesize;
ian@0 1309 }
ian@0 1310 cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
ian@0 1311 }
ian@0 1312 #endif
ian@0 1313
ian@0 1314 ret = do_unlock_oneblock(map, &cfi->chips[chipnum], adr);
ian@0 1315
ian@0 1316 #ifdef DEBUG_LOCK_BITS
ian@0 1317 cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL);
ian@0 1318 printk("after unlock: block status register is %x\n",cfi_read_query(map, adr+(2*ofs_factor)));
ian@0 1319 cfi_send_gen_cmd(0xff, 0x55, 0, map, cfi, cfi->device_type, NULL);
ian@0 1320 #endif
ian@0 1321
ian@0 1322 return ret;
ian@0 1323 }
ian@0 1324
ian@0 1325 static int cfi_staa_suspend(struct mtd_info *mtd)
ian@0 1326 {
ian@0 1327 struct map_info *map = mtd->priv;
ian@0 1328 struct cfi_private *cfi = map->fldrv_priv;
ian@0 1329 int i;
ian@0 1330 struct flchip *chip;
ian@0 1331 int ret = 0;
ian@0 1332
ian@0 1333 for (i=0; !ret && i<cfi->numchips; i++) {
ian@0 1334 chip = &cfi->chips[i];
ian@0 1335
ian@0 1336 spin_lock_bh(chip->mutex);
ian@0 1337
ian@0 1338 switch(chip->state) {
ian@0 1339 case FL_READY:
ian@0 1340 case FL_STATUS:
ian@0 1341 case FL_CFI_QUERY:
ian@0 1342 case FL_JEDEC_QUERY:
ian@0 1343 chip->oldstate = chip->state;
ian@0 1344 chip->state = FL_PM_SUSPENDED;
ian@0 1345 /* No need to wake_up() on this state change -
ian@0 1346 * as the whole point is that nobody can do anything
ian@0 1347 * with the chip now anyway.
ian@0 1348 */
ian@0 1349 case FL_PM_SUSPENDED:
ian@0 1350 break;
ian@0 1351
ian@0 1352 default:
ian@0 1353 ret = -EAGAIN;
ian@0 1354 break;
ian@0 1355 }
ian@0 1356 spin_unlock_bh(chip->mutex);
ian@0 1357 }
ian@0 1358
ian@0 1359 /* Unlock the chips again */
ian@0 1360
ian@0 1361 if (ret) {
ian@0 1362 for (i--; i >=0; i--) {
ian@0 1363 chip = &cfi->chips[i];
ian@0 1364
ian@0 1365 spin_lock_bh(chip->mutex);
ian@0 1366
ian@0 1367 if (chip->state == FL_PM_SUSPENDED) {
ian@0 1368 /* No need to force it into a known state here,
ian@0 1369 because we're returning failure, and it didn't
ian@0 1370 get power cycled */
ian@0 1371 chip->state = chip->oldstate;
ian@0 1372 wake_up(&chip->wq);
ian@0 1373 }
ian@0 1374 spin_unlock_bh(chip->mutex);
ian@0 1375 }
ian@0 1376 }
ian@0 1377
ian@0 1378 return ret;
ian@0 1379 }
ian@0 1380
ian@0 1381 static void cfi_staa_resume(struct mtd_info *mtd)
ian@0 1382 {
ian@0 1383 struct map_info *map = mtd->priv;
ian@0 1384 struct cfi_private *cfi = map->fldrv_priv;
ian@0 1385 int i;
ian@0 1386 struct flchip *chip;
ian@0 1387
ian@0 1388 for (i=0; i<cfi->numchips; i++) {
ian@0 1389
ian@0 1390 chip = &cfi->chips[i];
ian@0 1391
ian@0 1392 spin_lock_bh(chip->mutex);
ian@0 1393
ian@0 1394 /* Go to known state. Chip may have been power cycled */
ian@0 1395 if (chip->state == FL_PM_SUSPENDED) {
ian@0 1396 map_write(map, CMD(0xFF), 0);
ian@0 1397 chip->state = FL_READY;
ian@0 1398 wake_up(&chip->wq);
ian@0 1399 }
ian@0 1400
ian@0 1401 spin_unlock_bh(chip->mutex);
ian@0 1402 }
ian@0 1403 }
ian@0 1404
ian@0 1405 static void cfi_staa_destroy(struct mtd_info *mtd)
ian@0 1406 {
ian@0 1407 struct map_info *map = mtd->priv;
ian@0 1408 struct cfi_private *cfi = map->fldrv_priv;
ian@0 1409 kfree(cfi->cmdset_priv);
ian@0 1410 kfree(cfi);
ian@0 1411 }
ian@0 1412
ian@0 1413 MODULE_LICENSE("GPL");