diff options
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 45 | ||||
-rw-r--r-- | 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 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 |
67 | static int cfi_intelext_suspend (struct mtd_info *); | 68 | static int cfi_intelext_suspend (struct mtd_info *); |
68 | static void cfi_intelext_resume (struct mtd_info *); | 69 | static void cfi_intelext_resume (struct mtd_info *); |
70 | static int cfi_intelext_reboot (struct notifier_block *, unsigned long, void *); | ||
69 | 71 | ||
70 | static void cfi_intelext_destroy(struct mtd_info *); | 72 | static 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 | ||
2309 | static 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 | |||
2333 | static 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 | |||
2304 | static void cfi_intelext_destroy(struct mtd_info *mtd) | 2343 | static 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; |