Commit 5af017c0 authored by David Woodhouse's avatar David Woodhouse

MTD and JFFS2 update.

 - JFFS2 bugfixes and performance improvements
 - Support for 64-bit flash arrangements
 - Optimise for linear mappings of flash, without out-of-line access functions
 - New map drivers
 - Updated NAND flash support, new board drivers
 - Support for DiskOnChip Millennium Plus and INFTL translation layer
 - Clean up all translation layers with a single blkdev helper library.
 - Fix races in MTD device registration/deregistration
 - Add support for new flash chips
 - Clean up partition parsing code

More detailed comments in per-file changelogs.
parent 015498d5
# $Id: Config.in,v 1.74 2002/04/23 13:52:14 mag Exp $ # $Id: Kconfig,v 1.3 2003/05/28 11:02:23 dwmw2 Exp $
menu "Memory Technology Devices (MTD)" menu "Memory Technology Devices (MTD)"
...@@ -199,13 +199,28 @@ config NFTL ...@@ -199,13 +199,28 @@ config NFTL
not use it. not use it.
config NFTL_RW config NFTL_RW
bool "Write support for NFTL (BETA)" bool "Write support for NFTL"
depends on NFTL depends on NFTL
help help
If you're lucky, this will actually work. Don't whinge if it Support for writing to the NAND Flash Translation Layer, as used
doesn't. Send mail to the MTD mailing list on the DiskOnChip.
<linux-mtd@lists.infradead.org> if you want to help to make it more
reliable. config INFTL
tristate "INFTL (Inverse NAND Flash Translation Layer) support"
depends on MTD
---help---
This provides support for the Inverse NAND Flash Translation
Layer which is used on M-Systems' newer DiskOnChip devices. It
uses a kind of pseudo-file system on a flash device to emulate
a block device with 512-byte sectors, on top of which you put
a 'normal' file system.
You may find that the algorithms used in this code are patented
unless you live in the Free World where software patents aren't
legal - in the USA you are only permitted to use this on DiskOnChip
hardware, although under the terms of the GPL you're obviously
permitted to copy, modify and distribute the code as you wish. Just
not use it.
source "drivers/mtd/chips/Kconfig" source "drivers/mtd/chips/Kconfig"
......
# #
# Makefile for the memory technology device drivers. # Makefile for the memory technology device drivers.
# #
# Based on: # $Id: Makefile.common,v 1.2 2003/05/23 11:38:29 dwmw2 Exp $
# $Id: Makefile,v 1.66 2002/04/23 13:52:14 mag Exp $
obj-y += chips/ maps/ devices/ nand/
# *** BIG UGLY NOTE *** # *** BIG UGLY NOTE ***
# #
...@@ -27,14 +24,18 @@ obj-$(CONFIG_MTD) += mtdcore.o ...@@ -27,14 +24,18 @@ obj-$(CONFIG_MTD) += mtdcore.o
obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o obj-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdline.o obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
# 'Users' - code which presents functionality to userspace. # 'Users' - code which presents functionality to userspace.
obj-$(CONFIG_MTD_CHAR) += mtdchar.o obj-$(CONFIG_MTD_CHAR) += mtdchar.o
obj-$(CONFIG_MTD_BLOCK) += mtdblock.o obj-$(CONFIG_MTD_BLOCK) += mtdblock.o mtd_blkdevs.o
obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o obj-$(CONFIG_MTD_BLOCK_RO) += mtdblock_ro.o mtd_blkdevs.o
obj-$(CONFIG_FTL) += ftl.o obj-$(CONFIG_FTL) += ftl.o mtd_blkdevs.o
obj-$(CONFIG_NFTL) += nftl.o obj-$(CONFIG_NFTL) += nftl.o mtd_blkdevs.o
obj-$(CONFIG_INFTL) += inftl.o mtd_blkdevs.o
nftl-objs := nftlcore.o nftlmount.o nftl-objs := nftlcore.o nftlmount.o
inftl-objs := inftlcore.o inftlmount.o
obj-y += chips/ maps/ devices/ nand/
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
This is access code for flashes using ARM's flash partitioning This is access code for flashes using ARM's flash partitioning
standards. standards.
$Id: afs.c,v 1.8 2002/05/04 08:49:09 rmk Exp $ $Id: afs.c,v 1.11 2003/05/16 17:08:24 dwmw2 Exp $
======================================================================*/ ======================================================================*/
...@@ -125,7 +125,9 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr) ...@@ -125,7 +125,9 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
return ret; return ret;
} }
int parse_afs_partitions(struct mtd_info *mtd, struct mtd_partition **pparts) static int parse_afs_partitions(struct mtd_info *mtd,
struct mtd_partition **pparts,
unsigned long origin)
{ {
struct mtd_partition *parts; struct mtd_partition *parts;
u_int mask, off, idx, sz; u_int mask, off, idx, sz;
...@@ -227,7 +229,25 @@ int parse_afs_partitions(struct mtd_info *mtd, struct mtd_partition **pparts) ...@@ -227,7 +229,25 @@ int parse_afs_partitions(struct mtd_info *mtd, struct mtd_partition **pparts)
return idx ? idx : ret; return idx ? idx : ret;
} }
EXPORT_SYMBOL(parse_afs_partitions); static struct mtd_part_parser afs_parser = {
.owner = THIS_MODULE,
.parse_fn = parse_afs_partitions,
.name = "afs",
};
static int __init afs_parser_init(void)
{
return register_mtd_parser(&afs_parser);
}
static void __exit afs_parser_exit(void)
{
deregister_mtd_parser(&afs_parser);
}
module_init(afs_parser_init);
module_exit(afs_parser_exit);
MODULE_AUTHOR("ARM Ltd"); MODULE_AUTHOR("ARM Ltd");
MODULE_DESCRIPTION("ARM Firmware Suite partition parser"); MODULE_DESCRIPTION("ARM Firmware Suite partition parser");
......
# drivers/mtd/chips/Config.in # drivers/mtd/chips/Kconfig
# $Id: Config.in,v 1.12 2001/09/23 15:35:21 dwmw2 Exp $ # $Id: Kconfig,v 1.2 2003/05/28 10:59:06 dwmw2 Exp $
menu "RAM/ROM/Flash chip drivers" menu "RAM/ROM/Flash chip drivers"
depends on MTD!=n depends on MTD!=n
...@@ -15,7 +15,6 @@ config MTD_CFI ...@@ -15,7 +15,6 @@ config MTD_CFI
option. Visit <http://www.amd.com/products/nvd/overview/cfi.html> option. Visit <http://www.amd.com/products/nvd/overview/cfi.html>
for more information on CFI. for more information on CFI.
#dep_tristate ' Detect non-CFI Intel-compatible flash chips' CONFIG_MTD_INTELPROBE $CONFIG_MTD
config MTD_JEDECPROBE config MTD_JEDECPROBE
tristate "Detect non-CFI AMD/JEDEC-compatible flash chips" tristate "Detect non-CFI AMD/JEDEC-compatible flash chips"
depends on MTD depends on MTD
...@@ -145,7 +144,15 @@ config MTD_CFI_AMDSTD ...@@ -145,7 +144,15 @@ config MTD_CFI_AMDSTD
The Common Flash Interface defines a number of different command The Common Flash Interface defines a number of different command
sets which a CFI-compliant chip may claim to implement. This code sets which a CFI-compliant chip may claim to implement. This code
provides support for one of those command sets, used on chips provides support for one of those command sets, used on chips
chips including the AMD Am29LV320. including the AMD Am29LV320.
config MTD_CFI_STAA
tristate "Support for ST (Advanced Architecture) flash chips"
depends on MTD_GEN_PROBE
help
The Common Flash Interface defines a number of different command
sets which a CFI-compliant chip may claim to implement. This code
provides support for one of those command sets.
config MTD_RAM config MTD_RAM
tristate "Support for RAM chips in bus mapping" tristate "Support for RAM chips in bus mapping"
...@@ -177,10 +184,10 @@ config MTD_OBSOLETE_CHIPS ...@@ -177,10 +184,10 @@ config MTD_OBSOLETE_CHIPS
help help
This option does not enable any code directly, but will allow you to This option does not enable any code directly, but will allow you to
select some other chip drivers which are now considered obsolete, select some other chip drivers which are now considered obsolete,
because the generic CONFIG_JEDEC_PROBE code above should now detect because the generic CONFIG_JEDECPROBE code above should now detect
the chips which are supported by these drivers, and allow the generic the chips which are supported by these drivers, and allow the generic
CFI-compatible drivers to drive the chips. Say 'N' here unless you have CFI-compatible drivers to drive the chips. Say 'N' here unless you have
already tried the CONFIG_JEDEC_PROBE method and reported its failure already tried the CONFIG_JEDECPROBE method and reported its failure
to the MTD mailing list at <linux-mtd@lists.infradead.org> to the MTD mailing list at <linux-mtd@lists.infradead.org>
config MTD_AMDSTD config MTD_AMDSTD
...@@ -209,8 +216,7 @@ config MTD_JEDEC ...@@ -209,8 +216,7 @@ config MTD_JEDEC
programming flash. It is commonly used in older AMD chips. It is programming flash. It is commonly used in older AMD chips. It is
only called JEDEC because the JEDEC association only called JEDEC because the JEDEC association
<http://www.jedec.org/> distributes the identification codes for the <http://www.jedec.org/> distributes the identification codes for the
chips. WARNING!!!! This code does not compile and is incomplete as chips.
are the specific JEDEC devices drivers.
endmenu endmenu
# #
# linux/drivers/chips/Makefile # linux/drivers/chips/Makefile
# #
# $Id: Makefile,v 1.7 2001/10/05 06:53:51 dwmw2 Exp $ # $Id: Makefile.common,v 1.1 2003/05/21 15:00:01 dwmw2 Exp $
# *** BIG UGLY NOTE *** # *** BIG UGLY NOTE ***
# #
...@@ -13,10 +13,10 @@ ...@@ -13,10 +13,10 @@
obj-$(CONFIG_MTD) += chipreg.o obj-$(CONFIG_MTD) += chipreg.o
obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o obj-$(CONFIG_MTD_AMDSTD) += amd_flash.o
obj-$(CONFIG_MTD_CFI) += cfi_probe.o obj-$(CONFIG_MTD_CFI) += cfi_probe.o
obj-$(CONFIG_MTD_CFI_STAA) += cfi_cmdset_0020.o
obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o obj-$(CONFIG_MTD_CFI_AMDSTD) += cfi_cmdset_0002.o
obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o obj-$(CONFIG_MTD_CFI_INTELEXT) += cfi_cmdset_0001.o
obj-$(CONFIG_MTD_GEN_PROBE) += gen_probe.o obj-$(CONFIG_MTD_GEN_PROBE) += gen_probe.o
obj-$(CONFIG_MTD_INTELPROBE) += intel_probe.o
obj-$(CONFIG_MTD_JEDEC) += jedec.o obj-$(CONFIG_MTD_JEDEC) += jedec.o
obj-$(CONFIG_MTD_JEDECPROBE) += jedec_probe.o obj-$(CONFIG_MTD_JEDECPROBE) += jedec_probe.o
obj-$(CONFIG_MTD_RAM) += map_ram.o obj-$(CONFIG_MTD_RAM) += map_ram.o
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Author: Jonas Holmberg <jonas.holmberg@axis.com> * Author: Jonas Holmberg <jonas.holmberg@axis.com>
* *
* $Id: amd_flash.c,v 1.15 2001/10/02 15:05:11 dwmw2 Exp $ * $Id: amd_flash.c,v 1.22 2003/05/28 13:47:19 dwmw2 Exp $
* *
* Copyright (c) 2001 Axis Communications AB * Copyright (c) 2001 Axis Communications AB
* *
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
/* Manufacturers */ /* Manufacturers */
#define MANUFACTURER_AMD 0x0001 #define MANUFACTURER_AMD 0x0001
#define MANUFACTURER_ATMEL 0x001F
#define MANUFACTURER_FUJITSU 0x0004 #define MANUFACTURER_FUJITSU 0x0004
#define MANUFACTURER_ST 0x0020 #define MANUFACTURER_ST 0x0020
#define MANUFACTURER_SST 0x00BF #define MANUFACTURER_SST 0x00BF
...@@ -67,10 +68,14 @@ ...@@ -67,10 +68,14 @@
#define AM29BDS323D 0x22D1 #define AM29BDS323D 0x22D1
#define AM29BDS643D 0x227E #define AM29BDS643D 0x227E
/* Atmel */
#define AT49xV16x 0x00C0
#define AT49xV16xT 0x00C2
/* Fujitsu */ /* Fujitsu */
#define MBM29LV160TE 0x22C4 #define MBM29LV160TE 0x22C4
#define MBM29LV160BE 0x2249 #define MBM29LV160BE 0x2249
#define MBM29LV800BB 0x225B
/* ST - www.st.com */ /* ST - www.st.com */
#define M29W800T 0x00D7 #define M29W800T 0x00D7
...@@ -135,11 +140,11 @@ static const char im_name[] = "amd_flash"; ...@@ -135,11 +140,11 @@ static const char im_name[] = "amd_flash";
static inline __u32 wide_read(struct map_info *map, __u32 addr) static inline __u32 wide_read(struct map_info *map, __u32 addr)
{ {
if (map->buswidth == 1) { if (map->buswidth == 1) {
return map->read8(map, addr); return map_read8(map, addr);
} else if (map->buswidth == 2) { } else if (map->buswidth == 2) {
return map->read16(map, addr); return map_read16(map, addr);
} else if (map->buswidth == 4) { } else if (map->buswidth == 4) {
return map->read32(map, addr); return map_read32(map, addr);
} }
return 0; return 0;
...@@ -148,11 +153,11 @@ static inline __u32 wide_read(struct map_info *map, __u32 addr) ...@@ -148,11 +153,11 @@ static inline __u32 wide_read(struct map_info *map, __u32 addr)
static inline void wide_write(struct map_info *map, __u32 val, __u32 addr) static inline void wide_write(struct map_info *map, __u32 val, __u32 addr)
{ {
if (map->buswidth == 1) { if (map->buswidth == 1) {
map->write8(map, val, addr); map_write8(map, val, addr);
} else if (map->buswidth == 2) { } else if (map->buswidth == 2) {
map->write16(map, val, addr); map_write16(map, val, addr);
} else if (map->buswidth == 4) { } else if (map->buswidth == 4) {
map->write32(map, val, addr); map_write32(map, val, addr);
} }
} }
...@@ -419,10 +424,7 @@ static int probe_new_chip(struct mtd_info *mtd, __u32 base, ...@@ -419,10 +424,7 @@ static int probe_new_chip(struct mtd_info *mtd, __u32 base,
static struct mtd_info *amd_flash_probe(struct map_info *map) static struct mtd_info *amd_flash_probe(struct map_info *map)
{ {
/* Keep this table on the stack so that it gets deallocated after the static const struct amd_flash_info table[] = {
* probe is done.
*/
const struct amd_flash_info table[] = {
{ {
.mfr_id = MANUFACTURER_AMD, .mfr_id = MANUFACTURER_AMD,
.dev_id = AM29LV160DT, .dev_id = AM29LV160DT,
...@@ -555,6 +557,18 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) ...@@ -555,6 +557,18 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 }, { .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 } { .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 }
} }
}, {
.mfr_id = MANUFACTURER_FUJITSU,
.dev_id = MBM29LV800BB,
.name = "Fujitsu MBM29LV800BB",
.size = 0x00100000,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 },
{ .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
}
}, { }, {
.mfr_id = MANUFACTURER_ST, .mfr_id = MANUFACTURER_ST,
.dev_id = M29W800T, .dev_id = M29W800T,
...@@ -613,6 +627,26 @@ static struct mtd_info *amd_flash_probe(struct map_info *map) ...@@ -613,6 +627,26 @@ static struct mtd_info *amd_flash_probe(struct map_info *map)
{ .offset = 0x600000, .erasesize = 0x10000, .numblocks = 31 }, { .offset = 0x600000, .erasesize = 0x10000, .numblocks = 31 },
{ .offset = 0x7f0000, .erasesize = 0x02000, .numblocks = 8 }, { .offset = 0x7f0000, .erasesize = 0x02000, .numblocks = 8 },
} }
}, {
.mfr_id = MANUFACTURER_ATMEL,
.dev_id = AT49xV16x,
.name = "Atmel AT49xV16x",
.size = 0x00200000,
.numeraseregions = 2,
.regions = {
{ .offset = 0x000000, .erasesize = 0x02000, .numblocks = 8 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
}
}, {
.mfr_id = MANUFACTURER_ATMEL,
.dev_id = AT49xV16xT,
.name = "Atmel AT49xV16xT",
.size = 0x00200000,
.numeraseregions = 2,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
{ .offset = 0x1F0000, .erasesize = 0x02000, .numblocks = 8 }
}
} }
}; };
...@@ -785,7 +819,7 @@ static inline int read_one_chip(struct map_info *map, struct flchip *chip, ...@@ -785,7 +819,7 @@ static inline int read_one_chip(struct map_info *map, struct flchip *chip,
chip->state = FL_READY; chip->state = FL_READY;
map->copy_from(map, buf, adr, len); map_copy_from(map, buf, adr, len);
wake_up(&chip->wq); wake_up(&chip->wq);
spin_unlock_bh(chip->mutex); spin_unlock_bh(chip->mutex);
...@@ -947,7 +981,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len, ...@@ -947,7 +981,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len,
u_char tmp_buf[4]; u_char tmp_buf[4];
__u32 datum; __u32 datum;
map->copy_from(map, tmp_buf, map_copy_from(map, tmp_buf,
bus_ofs + private->chips[chipnum].start, bus_ofs + private->chips[chipnum].start,
map->buswidth); map->buswidth);
while (len && i < map->buswidth) while (len && i < map->buswidth)
...@@ -1020,7 +1054,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len, ...@@ -1020,7 +1054,7 @@ static int amd_flash_write(struct mtd_info *mtd, loff_t to , size_t len,
u_char tmp_buf[2]; u_char tmp_buf[2];
__u32 datum; __u32 datum;
map->copy_from(map, tmp_buf, map_copy_from(map, tmp_buf,
ofs + private->chips[chipnum].start, ofs + private->chips[chipnum].start,
map->buswidth); map->buswidth);
while (len--) { while (len--) {
...@@ -1141,7 +1175,7 @@ static inline int erase_one_block(struct map_info *map, struct flchip *chip, ...@@ -1141,7 +1175,7 @@ static inline int erase_one_block(struct map_info *map, struct flchip *chip,
__u8 verify; __u8 verify;
for (address = adr; address < (adr + size); address++) { for (address = adr; address < (adr + size); address++) {
if ((verify = map->read8(map, address)) != 0xFF) { if ((verify = map_read8(map, address)) != 0xFF) {
error = 1; error = 1;
break; break;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* /*
Common Flash Interface probe code. Common Flash Interface probe code.
(C) 2000 Red Hat. GPL'd. (C) 2000 Red Hat. GPL'd.
$Id: cfi_probe.c,v 1.66 2001/10/02 15:05:12 dwmw2 Exp $ $Id: cfi_probe.c,v 1.71 2003/05/28 12:51:48 dwmw2 Exp $
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -24,16 +25,13 @@ ...@@ -24,16 +25,13 @@
static void print_cfi_ident(struct cfi_ident *); static void print_cfi_ident(struct cfi_ident *);
#endif #endif
int cfi_jedec_setup(struct cfi_private *p_cfi, int index);
int cfi_jedec_lookup(int index, int mfr_id, int dev_id);
static int cfi_probe_chip(struct map_info *map, __u32 base, static int cfi_probe_chip(struct map_info *map, __u32 base,
struct flchip *chips, struct cfi_private *cfi); struct flchip *chips, struct cfi_private *cfi);
static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi); static int cfi_chip_setup(struct map_info *map, struct cfi_private *cfi);
struct mtd_info *cfi_probe(struct map_info *map); struct mtd_info *cfi_probe(struct map_info *map);
/* check for QRY, or search for jedec id. /* check for QRY.
in: interleave,type,mode in: interleave,type,mode
ret: table index, <0 for error ret: table index, <0 for error
*/ */
...@@ -55,6 +53,18 @@ static int cfi_probe_chip(struct map_info *map, __u32 base, ...@@ -55,6 +53,18 @@ static int cfi_probe_chip(struct map_info *map, __u32 base,
{ {
int i; int i;
if ((base + 0) >= map->size) {
printk(KERN_NOTICE
"Probe at base[0x00](0x%08lx) past the end of the map(0x%08lx)\n",
(unsigned long)base, map->size -1);
return 0;
}
if ((base + 0xff) >= map->size) {
printk(KERN_NOTICE
"Probe at base[0x55](0x%08lx) past the end of the map(0x%08lx)\n",
(unsigned long)base + 0x55, map->size -1);
return 0;
}
cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
...@@ -139,7 +149,7 @@ static int cfi_chip_setup(struct map_info *map, ...@@ -139,7 +149,7 @@ static int cfi_chip_setup(struct map_info *map,
memset(cfi->cfiq,0,sizeof(struct cfi_ident)); memset(cfi->cfiq,0,sizeof(struct cfi_ident));
cfi->cfi_mode = 1; cfi->cfi_mode = CFI_MODE_CFI;
cfi->fast_prog=1; /* CFI supports fast programming */ cfi->fast_prog=1; /* CFI supports fast programming */
/* Read the CFI info structure */ /* Read the CFI info structure */
...@@ -250,11 +260,11 @@ static void print_cfi_ident(struct cfi_ident *cfip) ...@@ -250,11 +260,11 @@ static void print_cfi_ident(struct cfi_ident *cfip)
else else
printk("Full buffer write not supported\n"); printk("Full buffer write not supported\n");
printk("Typical block erase timeout: %d s\n", 1<<cfip->BlockEraseTimeoutTyp); printk("Typical block erase timeout: %d ms\n", 1<<cfip->BlockEraseTimeoutTyp);
printk("Maximum block erase timeout: %d s\n", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp)); printk("Maximum block erase timeout: %d ms\n", (1<<cfip->BlockEraseTimeoutMax) * (1<<cfip->BlockEraseTimeoutTyp));
if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) { if (cfip->ChipEraseTimeoutTyp || cfip->ChipEraseTimeoutMax) {
printk("Typical chip erase timeout: %d s\n", 1<<cfip->ChipEraseTimeoutTyp); printk("Typical chip erase timeout: %d ms\n", 1<<cfip->ChipEraseTimeoutTyp);
printk("Maximum chip erase timeout: %d s\n", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp)); printk("Maximum chip erase timeout: %d ms\n", (1<<cfip->ChipEraseTimeoutMax) * (1<<cfip->ChipEraseTimeoutTyp));
} }
else else
printk("Chip erase not supported\n"); printk("Chip erase not supported\n");
......
/* /*
* $Id: chipreg.c,v 1.12 2001/10/02 15:29:53 dwmw2 Exp $ * $Id: chipreg.c,v 1.15 2003/05/21 15:15:05 dwmw2 Exp $
* *
* Registration for chip drivers * Registration for chip drivers
* *
...@@ -7,10 +7,13 @@ ...@@ -7,10 +7,13 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/module.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/mtd/compatmac.h> #include <linux/slab.h>
#include <linux/mtd/map.h> #include <linux/mtd/map.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/compatmac.h>
spinlock_t chip_drvs_lock = SPIN_LOCK_UNLOCKED; spinlock_t chip_drvs_lock = SPIN_LOCK_UNLOCKED;
static LIST_HEAD(chip_drvs_list); static LIST_HEAD(chip_drvs_list);
...@@ -29,7 +32,7 @@ void unregister_mtd_chip_driver(struct mtd_chip_driver *drv) ...@@ -29,7 +32,7 @@ void unregister_mtd_chip_driver(struct mtd_chip_driver *drv)
spin_unlock(&chip_drvs_lock); spin_unlock(&chip_drvs_lock);
} }
static struct mtd_chip_driver *get_mtd_chip_driver (char *name) static struct mtd_chip_driver *get_mtd_chip_driver (const char *name)
{ {
struct list_head *pos; struct list_head *pos;
struct mtd_chip_driver *ret = NULL, *this; struct mtd_chip_driver *ret = NULL, *this;
...@@ -44,10 +47,8 @@ static struct mtd_chip_driver *get_mtd_chip_driver (char *name) ...@@ -44,10 +47,8 @@ static struct mtd_chip_driver *get_mtd_chip_driver (char *name)
break; break;
} }
} }
if (ret && !try_module_get(ret->module)) { if (ret && !try_module_get(ret->module))
/* Eep. Failed. */
ret = NULL; ret = NULL;
}
spin_unlock(&chip_drvs_lock); spin_unlock(&chip_drvs_lock);
...@@ -57,7 +58,7 @@ static struct mtd_chip_driver *get_mtd_chip_driver (char *name) ...@@ -57,7 +58,7 @@ static struct mtd_chip_driver *get_mtd_chip_driver (char *name)
/* Hide all the horrid details, like some silly person taking /* Hide all the horrid details, like some silly person taking
get_module_symbol() away from us, from the caller. */ get_module_symbol() away from us, from the caller. */
struct mtd_info *do_map_probe(char *name, struct map_info *map) struct mtd_info *do_map_probe(const char *name, struct map_info *map)
{ {
struct mtd_chip_driver *drv; struct mtd_chip_driver *drv;
struct mtd_info *ret; struct mtd_info *ret;
...@@ -84,10 +85,26 @@ struct mtd_info *do_map_probe(char *name, struct map_info *map) ...@@ -84,10 +85,26 @@ struct mtd_info *do_map_probe(char *name, struct map_info *map)
return NULL; return NULL;
} }
/*
* Destroy an MTD device which was created for a map device.
* Make sure the MTD device is already unregistered before calling this
*/
void map_destroy(struct mtd_info *mtd)
{
struct map_info *map = mtd->priv;
if (map->fldrv->destroy)
map->fldrv->destroy(mtd);
module_put(map->fldrv->module);
kfree(mtd);
}
EXPORT_SYMBOL(register_mtd_chip_driver); EXPORT_SYMBOL(register_mtd_chip_driver);
EXPORT_SYMBOL(unregister_mtd_chip_driver); EXPORT_SYMBOL(unregister_mtd_chip_driver);
EXPORT_SYMBOL(do_map_probe); EXPORT_SYMBOL(do_map_probe);
EXPORT_SYMBOL(map_destroy);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
......
...@@ -2,13 +2,16 @@ ...@@ -2,13 +2,16 @@
* Routines common to all CFI-type probes. * Routines common to all CFI-type probes.
* (C) 2001, 2001 Red Hat, Inc. * (C) 2001, 2001 Red Hat, Inc.
* GPL'd * GPL'd
* $Id: gen_probe.c,v 1.5 2001/10/02 15:05:12 dwmw2 Exp $ * $Id: gen_probe.c,v 1.11 2003/05/21 15:15:05 dwmw2 Exp $
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/mtd/map.h> #include <linux/mtd/map.h>
#include <linux/mtd/cfi.h> #include <linux/mtd/cfi.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/gen_probe.h> #include <linux/mtd/gen_probe.h>
static struct mtd_info *check_cmd_set(struct map_info *, int); static struct mtd_info *check_cmd_set(struct map_info *, int);
...@@ -38,7 +41,7 @@ struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp) ...@@ -38,7 +41,7 @@ struct mtd_info *mtd_do_chip_probe(struct map_info *map, struct chip_probe *cp)
if (mtd) if (mtd)
return mtd; return mtd;
printk(KERN_WARNING"cfi_probe: No supported Vendor Command Set found\n"); printk(KERN_WARNING"gen_probe: No supported Vendor Command Set found\n");
kfree(cfi->cfiq); kfree(cfi->cfiq);
kfree(cfi); kfree(cfi);
...@@ -57,6 +60,7 @@ struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe ...@@ -57,6 +60,7 @@ struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe
int i; int i;
memset(&cfi, 0, sizeof(cfi)); memset(&cfi, 0, sizeof(cfi));
memset(&chip[0], 0, sizeof(chip));
/* Call the probetype-specific code with all permutations of /* Call the probetype-specific code with all permutations of
interleave and device type, etc. */ interleave and device type, etc. */
...@@ -106,6 +110,12 @@ struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe ...@@ -106,6 +110,12 @@ struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chip_probe
* Now probe for other chips, checking sensibly for aliases while * Now probe for other chips, checking sensibly for aliases while
* we're at it. The new_chip probe above should have let the first * we're at it. The new_chip probe above should have let the first
* chip in read mode. * chip in read mode.
*
* NOTE: Here, we're checking if there is room for another chip
* the same size within the mapping. Therefore,
* base + chipsize <= map->size is the correct thing to do,
* because, base + chipsize would be the _first_ byte of the
* next chip, not the one we're currently pondering.
*/ */
for (base = (1<<cfi.chipshift); base + (1<<cfi.chipshift) <= map->size; for (base = (1<<cfi.chipshift); base + (1<<cfi.chipshift) <= map->size;
...@@ -224,6 +234,41 @@ static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp, ...@@ -224,6 +234,41 @@ static int genprobe_new_chip(struct map_info *map, struct chip_probe *cp,
break; break;
#endif /* CFIDEV_BUSWIDTH_4 */ #endif /* CFIDEV_BUSWIDTH_4 */
#ifdef CFIDEV_BUSWIDTH_8
case CFIDEV_BUSWIDTH_8:
#if defined(CFIDEV_INTERLEAVE_2) && defined(SOMEONE_ACTUALLY_MAKES_THESE)
cfi->interleave = CFIDEV_INTERLEAVE_2;
cfi->device_type = CFI_DEVICETYPE_X32;
if (cp->probe_chip(map, 0, NULL, cfi))
return 1;
#endif /* CFIDEV_INTERLEAVE_2 */
#ifdef CFIDEV_INTERLEAVE_4
cfi->interleave = CFIDEV_INTERLEAVE_4;
#ifdef SOMEONE_ACTUALLY_MAKES_THESE
cfi->device_type = CFI_DEVICETYPE_X32;
if (cp->probe_chip(map, 0, NULL, cfi))
return 1;
#endif
cfi->device_type = CFI_DEVICETYPE_X16;
if (cp->probe_chip(map, 0, NULL, cfi))
return 1;
#endif /* CFIDEV_INTERLEAVE_4 */
#ifdef CFIDEV_INTERLEAVE_8
cfi->interleave = CFIDEV_INTERLEAVE_8;
cfi->device_type = CFI_DEVICETYPE_X16;
if (cp->probe_chip(map, 0, NULL, cfi))
return 1;
cfi->device_type = CFI_DEVICETYPE_X8;
if (cp->probe_chip(map, 0, NULL, cfi))
return 1;
#endif /* CFIDEV_INTERLEAVE_8 */
break;
#endif /* CFIDEV_BUSWIDTH_8 */
default: default:
printk(KERN_WARNING "genprobe_new_chip called with unsupported buswidth %d\n", map->buswidth); printk(KERN_WARNING "genprobe_new_chip called with unsupported buswidth %d\n", map->buswidth);
return 0; return 0;
...@@ -288,6 +333,10 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) ...@@ -288,6 +333,10 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary)
#ifdef CONFIG_MTD_CFI_AMDSTD #ifdef CONFIG_MTD_CFI_AMDSTD
case 0x0002: case 0x0002:
return cfi_cmdset_0002(map, primary); return cfi_cmdset_0002(map, primary);
#endif
#ifdef CONFIG_MTD_CFI_STAA
case 0x0020:
return cfi_cmdset_0020(map, primary);
#endif #endif
} }
......
This diff is collapsed.
This diff is collapsed.
/* /*
* Common code to handle absent "placeholder" devices * Common code to handle absent "placeholder" devices
* Copyright 2001 Resilience Corporation <ebrower@resilience.com> * Copyright 2001 Resilience Corporation <ebrower@resilience.com>
* $Id: map_absent.c,v 1.2 2001/10/02 15:05:12 dwmw2 Exp $ * $Id: map_absent.c,v 1.4 2003/05/28 12:51:49 dwmw2 Exp $
* *
* This map driver is used to allocate "placeholder" MTD * This map driver is used to allocate "placeholder" MTD
* devices on systems that have socketed/removable media. * devices on systems that have socketed/removable media.
...@@ -23,9 +23,10 @@ ...@@ -23,9 +23,10 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h> #include <linux/mtd/map.h>
#include <linux/mtd/compatmac.h>
static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int map_absent_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int map_absent_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
...@@ -65,7 +66,7 @@ static struct mtd_info *map_absent_probe(struct map_info *map) ...@@ -65,7 +66,7 @@ static struct mtd_info *map_absent_probe(struct map_info *map)
mtd->flags = 0; mtd->flags = 0;
mtd->erasesize = PAGE_SIZE; mtd->erasesize = PAGE_SIZE;
MOD_INC_USE_COUNT; __module_get(THIS_MODULE);
return mtd; return mtd;
} }
......
This diff is collapsed.
/* /*
* Common code to handle map devices which are simple ROM * Common code to handle map devices which are simple ROM
* (C) 2000 Red Hat. GPL'd. * (C) 2000 Red Hat. GPL'd.
* $Id: map_rom.c,v 1.17 2001/10/02 15:05:12 dwmw2 Exp $ * $Id: map_rom.c,v 1.20 2003/05/28 12:51:49 dwmw2 Exp $
*/ */
#include <linux/version.h> #include <linux/version.h>
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h> #include <linux/mtd/map.h>
#include <linux/mtd/compatmac.h>
static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
...@@ -49,7 +51,7 @@ struct mtd_info *map_rom_probe(struct map_info *map) ...@@ -49,7 +51,7 @@ struct mtd_info *map_rom_probe(struct map_info *map)
while(mtd->size & (mtd->erasesize - 1)) while(mtd->size & (mtd->erasesize - 1))
mtd->erasesize >>= 1; mtd->erasesize >>= 1;
MOD_INC_USE_COUNT; __module_get(THIS_MODULE);
return mtd; return mtd;
} }
...@@ -58,7 +60,7 @@ static int maprom_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *r ...@@ -58,7 +60,7 @@ static int maprom_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *r
{ {
struct map_info *map = (struct map_info *)mtd->priv; struct map_info *map = (struct map_info *)mtd->priv;
map->copy_from(map, buf, from, len); map_copy_from(map, buf, from, len);
*retlen = len; *retlen = len;
return 0; return 0;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment