aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Kagstrom <simon.kagstrom@netinsight.net>2009-10-05 09:55:52 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-11-30 04:46:39 -0500
commit2af7c653993199fb32dc6d9504064a0c9c57e5d6 (patch)
treee5a493617a93cacaa77016567df7281d720121b4
parentc9f7ec30848637989b85a9f0ac5d4aa33c49916e (diff)
mtd: Add panic_write for NAND flashes
This is a quick and dirty patch to add panic_write for NAND flashes. The patch seems to work OK on my CRIS board running a 2.6.26 kernel with a ID: 0x20, Chip ID: 0xf1 (ST Micro NAND 128MiB 3,3V 8-bit), and also on a OpenRD base (Marvell Kirkwood) board with a Toshiba NAND 512MiB 3,3V 8-bit flash with 2.6.32-pre1. Signed-off-by: Edgar E. Iglesias <edgar@axis.com> Signed-off-by: Simon Kagstrom <simon.kagstrom@netinsight.net> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r--drivers/mtd/nand/nand_base.c128
1 files changed, 120 insertions, 8 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 2957cc70da3d..ba06473326d1 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -428,6 +428,28 @@ static int nand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip,
428 return nand_isbad_bbt(mtd, ofs, allowbbt); 428 return nand_isbad_bbt(mtd, ofs, allowbbt);
429} 429}
430 430
431/**
432 * panic_nand_wait_ready - [GENERIC] Wait for the ready pin after commands.
433 * @mtd: MTD device structure
434 * @timeo: Timeout
435 *
436 * Helper function for nand_wait_ready used when needing to wait in interrupt
437 * context.
438 */
439static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
440{
441 struct nand_chip *chip = mtd->priv;
442 int i;
443
444 /* Wait for the device to get ready */
445 for (i = 0; i < timeo; i++) {
446 if (chip->dev_ready(mtd))
447 break;
448 touch_softlockup_watchdog();
449 mdelay(1);
450 }
451}
452
431/* 453/*
432 * Wait for the ready pin, after a command 454 * Wait for the ready pin, after a command
433 * The timeout is catched later. 455 * The timeout is catched later.
@@ -437,6 +459,10 @@ void nand_wait_ready(struct mtd_info *mtd)
437 struct nand_chip *chip = mtd->priv; 459 struct nand_chip *chip = mtd->priv;
438 unsigned long timeo = jiffies + 2; 460 unsigned long timeo = jiffies + 2;
439 461
462 /* 400ms timeout */
463 if (in_interrupt() || oops_in_progress)
464 return panic_nand_wait_ready(mtd, 400);
465
440 led_trigger_event(nand_led_trigger, LED_FULL); 466 led_trigger_event(nand_led_trigger, LED_FULL);
441 /* wait until command is processed or timeout occures */ 467 /* wait until command is processed or timeout occures */
442 do { 468 do {
@@ -672,6 +698,22 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
672} 698}
673 699
674/** 700/**
701 * panic_nand_get_device - [GENERIC] Get chip for selected access
702 * @chip: the nand chip descriptor
703 * @mtd: MTD device structure
704 * @new_state: the state which is requested
705 *
706 * Used when in panic, no locks are taken.
707 */
708static void panic_nand_get_device(struct nand_chip *chip,
709 struct mtd_info *mtd, int new_state)
710{
711 /* Hardware controller shared among independend devices */
712 chip->controller->active = chip;
713 chip->state = new_state;
714}
715
716/**
675 * nand_get_device - [GENERIC] Get chip for selected access 717 * nand_get_device - [GENERIC] Get chip for selected access
676 * @chip: the nand chip descriptor 718 * @chip: the nand chip descriptor
677 * @mtd: MTD device structure 719 * @mtd: MTD device structure
@@ -710,6 +752,32 @@ nand_get_device(struct nand_chip *chip, struct mtd_info *mtd, int new_state)
710} 752}
711 753
712/** 754/**
755 * panic_nand_wait - [GENERIC] wait until the command is done
756 * @mtd: MTD device structure
757 * @chip: NAND chip structure
758 * @timeo: Timeout
759 *
760 * Wait for command done. This is a helper function for nand_wait used when
761 * we are in interrupt context. May happen when in panic and trying to write
762 * an oops trough mtdoops.
763 */
764static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
765 unsigned long timeo)
766{
767 int i;
768 for (i = 0; i < timeo; i++) {
769 if (chip->dev_ready) {
770 if (chip->dev_ready(mtd))
771 break;
772 } else {
773 if (chip->read_byte(mtd) & NAND_STATUS_READY)
774 break;
775 }
776 mdelay(1);
777 }
778}
779
780/**
713 * nand_wait - [DEFAULT] wait until the command is done 781 * nand_wait - [DEFAULT] wait until the command is done
714 * @mtd: MTD device structure 782 * @mtd: MTD device structure
715 * @chip: NAND chip structure 783 * @chip: NAND chip structure
@@ -740,15 +808,19 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
740 else 808 else
741 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1); 809 chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
742 810
743 while (time_before(jiffies, timeo)) { 811 if (in_interrupt() || oops_in_progress)
744 if (chip->dev_ready) { 812 panic_nand_wait(mtd, chip, timeo);
745 if (chip->dev_ready(mtd)) 813 else {
746 break; 814 while (time_before(jiffies, timeo)) {
747 } else { 815 if (chip->dev_ready) {
748 if (chip->read_byte(mtd) & NAND_STATUS_READY) 816 if (chip->dev_ready(mtd))
749 break; 817 break;
818 } else {
819 if (chip->read_byte(mtd) & NAND_STATUS_READY)
820 break;
821 }
822 cond_resched();
750 } 823 }
751 cond_resched();
752 } 824 }
753 led_trigger_event(nand_led_trigger, LED_OFF); 825 led_trigger_event(nand_led_trigger, LED_OFF);
754 826
@@ -1949,6 +2021,45 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1949} 2021}
1950 2022
1951/** 2023/**
2024 * panic_nand_write - [MTD Interface] NAND write with ECC
2025 * @mtd: MTD device structure
2026 * @to: offset to write to
2027 * @len: number of bytes to write
2028 * @retlen: pointer to variable to store the number of written bytes
2029 * @buf: the data to write
2030 *
2031 * NAND write with ECC. Used when performing writes in interrupt context, this
2032 * may for example be called by mtdoops when writing an oops while in panic.
2033 */
2034static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
2035 size_t *retlen, const uint8_t *buf)
2036{
2037 struct nand_chip *chip = mtd->priv;
2038 int ret;
2039
2040 /* Do not allow reads past end of device */
2041 if ((to + len) > mtd->size)
2042 return -EINVAL;
2043 if (!len)
2044 return 0;
2045
2046 /* Wait for the device to get ready. */
2047 panic_nand_wait(mtd, chip, 400);
2048
2049 /* Grab the device. */
2050 panic_nand_get_device(chip, mtd, FL_WRITING);
2051
2052 chip->ops.len = len;
2053 chip->ops.datbuf = (uint8_t *)buf;
2054 chip->ops.oobbuf = NULL;
2055
2056 ret = nand_do_write_ops(mtd, to, &chip->ops);
2057
2058 *retlen = chip->ops.retlen;
2059 return ret;
2060}
2061
2062/**
1952 * nand_write - [MTD Interface] NAND write with ECC 2063 * nand_write - [MTD Interface] NAND write with ECC
1953 * @mtd: MTD device structure 2064 * @mtd: MTD device structure
1954 * @to: offset to write to 2065 * @to: offset to write to
@@ -2877,6 +2988,7 @@ int nand_scan_tail(struct mtd_info *mtd)
2877 mtd->unpoint = NULL; 2988 mtd->unpoint = NULL;
2878 mtd->read = nand_read; 2989 mtd->read = nand_read;
2879 mtd->write = nand_write; 2990 mtd->write = nand_write;
2991 mtd->panic_write = panic_nand_write;
2880 mtd->read_oob = nand_read_oob; 2992 mtd->read_oob = nand_read_oob;
2881 mtd->write_oob = nand_write_oob; 2993 mtd->write_oob = nand_write_oob;
2882 mtd->sync = nand_sync; 2994 mtd->sync = nand_sync;