aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c45
1 files changed, 43 insertions, 2 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);