aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Pitre <nico@cam.org>2005-03-31 20:59:56 -0500
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-05-23 07:06:28 -0400
commit963a6fb0a0d336d0513083b7e4b5c3ff9d6d2061 (patch)
treed7f6ccfbef2fe150d3073d17d333f90d1ce304a6
parent8048d2fc38c9559ce37b46c21fa734c5cb9bcdb2 (diff)
[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 <nico@cam.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c45
-rw-r--r--include/linux/mtd/mtd.h5
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
index b482a4e48e48..dc257eb6932f 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -4,7 +4,7 @@
4 * 4 *
5 * (C) 2000 Red Hat. GPL'd 5 * (C) 2000 Red Hat. GPL'd
6 * 6 *
7 * $Id: cfi_cmdset_0001.c,v 1.173 2005/03/30 23:57:30 tpoynor Exp $ 7 * $Id: cfi_cmdset_0001.c,v 1.174 2005/04/01 01:59:52 nico Exp $
8 * 8 *
9 * 9 *
10 * 10/10/2000 Nicolas Pitre <nico@cam.org> 10 * 10/10/2000 Nicolas Pitre <nico@cam.org>
@@ -29,6 +29,7 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/reboot.h>
32#include <linux/mtd/xip.h> 33#include <linux/mtd/xip.h>
33#include <linux/mtd/map.h> 34#include <linux/mtd/map.h>
34#include <linux/mtd/mtd.h> 35#include <linux/mtd/mtd.h>
@@ -66,6 +67,7 @@ static int cfi_intelext_get_user_prot_info (struct mtd_info *,
66#endif 67#endif
67static int cfi_intelext_suspend (struct mtd_info *); 68static int cfi_intelext_suspend (struct mtd_info *);
68static void cfi_intelext_resume (struct mtd_info *); 69static void cfi_intelext_resume (struct mtd_info *);
70static int cfi_intelext_reboot (struct notifier_block *, unsigned long, void *);
69 71
70static void cfi_intelext_destroy(struct mtd_info *); 72static void cfi_intelext_destroy(struct mtd_info *);
71 73
@@ -333,7 +335,9 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
333 mtd->resume = cfi_intelext_resume; 335 mtd->resume = cfi_intelext_resume;
334 mtd->flags = MTD_CAP_NORFLASH; 336 mtd->flags = MTD_CAP_NORFLASH;
335 mtd->name = map->name; 337 mtd->name = map->name;
336 338
339 mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
340
337 if (cfi->cfi_mode == CFI_MODE_CFI) { 341 if (cfi->cfi_mode == CFI_MODE_CFI) {
338 /* 342 /*
339 * It's a real CFI chip, not one for which the probe 343 * It's a real CFI chip, not one for which the probe
@@ -446,6 +450,7 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
446 goto setup_err; 450 goto setup_err;
447 451
448 __module_get(THIS_MODULE); 452 __module_get(THIS_MODULE);
453 register_reboot_notifier(&mtd->reboot_notifier);
449 return mtd; 454 return mtd;
450 455
451 setup_err: 456 setup_err:
@@ -2301,10 +2306,46 @@ static void cfi_intelext_resume(struct mtd_info *mtd)
2301 } 2306 }
2302} 2307}
2303 2308
2309static int cfi_intelext_reset(struct mtd_info *mtd)
2310{
2311 struct map_info *map = mtd->priv;
2312 struct cfi_private *cfi = map->fldrv_priv;
2313 int i, ret;
2314
2315 for (i=0; i < cfi->numchips; i++) {
2316 struct flchip *chip = &cfi->chips[i];
2317
2318 /* force the completion of any ongoing operation
2319 and switch to array mode so any bootloader in
2320 flash is accessible for soft reboot. */
2321 spin_lock(chip->mutex);
2322 ret = get_chip(map, chip, chip->start, FL_SYNCING);
2323 if (!ret) {
2324 map_write(map, CMD(0xff), chip->start);
2325 chip->state = FL_READY;
2326 }
2327 spin_unlock(chip->mutex);
2328 }
2329
2330 return 0;
2331}
2332
2333static int cfi_intelext_reboot(struct notifier_block *nb, unsigned long val,
2334 void *v)
2335{
2336 struct mtd_info *mtd;
2337
2338 mtd = container_of(nb, struct mtd_info, reboot_notifier);
2339 cfi_intelext_reset(mtd);
2340 return NOTIFY_DONE;
2341}
2342
2304static void cfi_intelext_destroy(struct mtd_info *mtd) 2343static void cfi_intelext_destroy(struct mtd_info *mtd)
2305{ 2344{
2306 struct map_info *map = mtd->priv; 2345 struct map_info *map = mtd->priv;
2307 struct cfi_private *cfi = map->fldrv_priv; 2346 struct cfi_private *cfi = map->fldrv_priv;
2347 cfi_intelext_reset(mtd);
2348 unregister_reboot_notifier(&mtd->reboot_notifier);
2308 kfree(cfi->cmdset_priv); 2349 kfree(cfi->cmdset_priv);
2309 kfree(cfi->cfiq); 2350 kfree(cfi->cfiq);
2310 kfree(cfi->chips[0].priv); 2351 kfree(cfi->chips[0].priv);
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 3aab1b8729e0..f574cd498816 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * $Id: mtd.h,v 1.57 2005/02/08 17:11:15 nico Exp $ 2 * $Id: mtd.h,v 1.58 2005/04/01 01:59:54 nico Exp $
3 * 3 *
4 * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al. 4 * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
5 * 5 *
@@ -18,6 +18,7 @@
18#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/uio.h> 20#include <linux/uio.h>
21#include <linux/notifier.h>
21 22
22#include <linux/mtd/compatmac.h> 23#include <linux/mtd/compatmac.h>
23#include <mtd/mtd-abi.h> 24#include <mtd/mtd-abi.h>
@@ -147,6 +148,8 @@ struct mtd_info {
147 int (*block_isbad) (struct mtd_info *mtd, loff_t ofs); 148 int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
148 int (*block_markbad) (struct mtd_info *mtd, loff_t ofs); 149 int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
149 150
151 struct notifier_block reboot_notifier; /* default mode before reboot */
152
150 void *priv; 153 void *priv;
151 154
152 struct module *owner; 155 struct module *owner;