tree d7f6ccfbef2fe150d3073d17d333f90d1ce304a6
parent 8048d2fc38c9559ce37b46c21fa734c5cb9bcdb2
author Nicolas Pitre <[EMAIL PROTECTED]> Fri, 01 Apr 2005 02:59:56 +0100
committer Thomas Gleixner <[EMAIL PROTECTED]> Mon, 23 May 2005 13:06:28 +0200

[MTD] Add reboot notifier to Intel NOR flash driver

to make sure the flash is in array mode whenever we're about to
reboot. This is especially useful to allow "soft" reboot to work
which consists of branching back into the bootloader.

Signed-off-by: Nicolas Pitre <[EMAIL PROTECTED]>
Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>

 drivers/mtd/chips/cfi_cmdset_0001.c |   45 ++++++++++++++++++++++++++++++++++--
 include/linux/mtd/mtd.h             |    5 +++-
 2 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c 
b/drivers/mtd/chips/cfi_cmdset_0001.c
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -4,7 +4,7 @@
  *
  * (C) 2000 Red Hat. GPL'd
  *
- * $Id: cfi_cmdset_0001.c,v 1.173 2005/03/30 23:57:30 tpoynor Exp $
+ * $Id: cfi_cmdset_0001.c,v 1.174 2005/04/01 01:59:52 nico Exp $
  *
  * 
  * 10/10/2000  Nicolas Pitre <[EMAIL PROTECTED]>
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
+#include <linux/reboot.h>
 #include <linux/mtd/xip.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
@@ -66,6 +67,7 @@ static int cfi_intelext_get_user_prot_in
 #endif
 static int cfi_intelext_suspend (struct mtd_info *);
 static void cfi_intelext_resume (struct mtd_info *);
+static int cfi_intelext_reboot (struct notifier_block *, unsigned long, void 
*);
 
 static void cfi_intelext_destroy(struct mtd_info *);
 
@@ -333,7 +335,9 @@ struct mtd_info *cfi_cmdset_0001(struct 
        mtd->resume  = cfi_intelext_resume;
        mtd->flags   = MTD_CAP_NORFLASH;
        mtd->name    = map->name;
-       
+
+       mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
+
        if (cfi->cfi_mode == CFI_MODE_CFI) {
                /* 
                 * It's a real CFI chip, not one for which the probe
@@ -446,6 +450,7 @@ static struct mtd_info *cfi_intelext_set
                goto setup_err;
 
        __module_get(THIS_MODULE);
+       register_reboot_notifier(&mtd->reboot_notifier);
        return mtd;
 
  setup_err:
@@ -2301,10 +2306,46 @@ static void cfi_intelext_resume(struct m
        }
 }
 
+static int cfi_intelext_reset(struct mtd_info *mtd)
+{
+       struct map_info *map = mtd->priv;
+       struct cfi_private *cfi = map->fldrv_priv;
+       int i, ret;
+
+       for (i=0; i < cfi->numchips; i++) {
+               struct flchip *chip = &cfi->chips[i];
+
+               /* force the completion of any ongoing operation
+                  and switch to array mode so any bootloader in 
+                  flash is accessible for soft reboot. */
+               spin_lock(chip->mutex);
+               ret = get_chip(map, chip, chip->start, FL_SYNCING);
+               if (!ret) {
+                       map_write(map, CMD(0xff), chip->start);
+                       chip->state = FL_READY;
+               }
+               spin_unlock(chip->mutex);
+       }
+
+       return 0;
+}
+
+static int cfi_intelext_reboot(struct notifier_block *nb, unsigned long val,
+                              void *v)
+{
+       struct mtd_info *mtd;
+
+       mtd = container_of(nb, struct mtd_info, reboot_notifier);
+       cfi_intelext_reset(mtd);
+       return NOTIFY_DONE;
+}
+
 static void cfi_intelext_destroy(struct mtd_info *mtd)
 {
        struct map_info *map = mtd->priv;
        struct cfi_private *cfi = map->fldrv_priv;
+       cfi_intelext_reset(mtd);
+       unregister_reboot_notifier(&mtd->reboot_notifier);
        kfree(cfi->cmdset_priv);
        kfree(cfi->cfiq);
        kfree(cfi->chips[0].priv);
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -1,5 +1,5 @@
 /* 
- * $Id: mtd.h,v 1.57 2005/02/08 17:11:15 nico Exp $
+ * $Id: mtd.h,v 1.58 2005/04/01 01:59:54 nico Exp $
  *
  * Copyright (C) 1999-2003 David Woodhouse <[EMAIL PROTECTED]> et al.
  *
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/uio.h>
+#include <linux/notifier.h>
 
 #include <linux/mtd/compatmac.h>
 #include <mtd/mtd-abi.h>
@@ -147,6 +148,8 @@ struct mtd_info {
        int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
        int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
 
+       struct notifier_block reboot_notifier;  /* default mode before reboot */
+
        void *priv;
 
        struct module *owner;
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to