Commit c8c55bcb authored by Linus Torvalds's avatar Linus Torvalds

Merge git://git.infradead.org/mtd-2.6

* git://git.infradead.org/mtd-2.6: (91 commits)
  [MTD] [NAND] Blackfin on-chip NAND Flash Controller driver
  [MTD] [NOR] fix ctrl-alt-del can't reboot for intel flash bug
  [MTD] [NAND] Fix compiler warning in Alauda driver
  [JFFS2] Remove stray debugging printk
  [JFFS2] Handle dirents on the flash with embedded zero bytes in names.
  [JFFS2] Check for creation of dirents with embedded zero bytes in name.
  [JFFS2] Don't count all 'very dirty' blocks except in debug mode
  [JFFS2] Check whether garbage-collection actually obsoleted its victim.
  [JFFS2] Relax threshold for triggering GC due to dirty blocks.
  [MTD] [OneNAND] Fix typo related with recent commit
  [JFFS2] Trigger garbage collection when very_dirty_list size becomes excessive
  [MTD] [NAND] Avoid deadlock in erase callback; release chip lock first.
  [MTD] [NAND] Resume method for CAFÉ NAND controller
  [MTD] [NAND] Fix PCI ident table for CAFÉ NAND controller.
  [MTD] [NAND] s3c2410: fix arch moves
  [MTD] [OneNAND] fix numerous races
  [MTD] map driver for NOR flash on the Intel Vermilion Range chipset
  [JFFS2] Fix unpoint length
  [MTD] fix CFI point method for discontiguous maps
  [MTD] MAPS: Merge Lubbock and Mainstone drivers into common PXA2xx driver
  ...
parents 3749c66c ebf8889b
......@@ -275,16 +275,13 @@ int __init board_init (void)
int err = 0;
/* Allocate memory for MTD device structure and private data */
board_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL);
board_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
if (!board_mtd) {
printk ("Unable to allocate NAND MTD device structure.\n");
err = -ENOMEM;
goto out;
}
/* Initialize structures */
memset ((char *) board_mtd, 0, sizeof(struct mtd_info) + sizeof(struct nand_chip));
/* map physical adress */
baseaddr = (unsigned long)ioremap(CHIP_PHYSICAL_ADDRESS, 1024);
if(!baseaddr){
......
......@@ -278,6 +278,14 @@ config SSFDC
This enables read only access to SmartMedia formatted NAND
flash. You can mount it with FAT file system.
config MTD_OOPS
tristate "Log panic/oops to an MTD buffer"
depends on MTD
help
This enables panic and oops messages to be logged to a circular
buffer in a flash partition where it can be read back at some
later point.
source "drivers/mtd/chips/Kconfig"
source "drivers/mtd/maps/Kconfig"
......
......@@ -22,6 +22,7 @@ obj-$(CONFIG_NFTL) += nftl.o
obj-$(CONFIG_INFTL) += inftl.o
obj-$(CONFIG_RFD_FTL) += rfd_ftl.o
obj-$(CONFIG_SSFDC) += ssfdc.o
obj-$(CONFIG_MTD_OOPS) += mtdoops.o
nftl-objs := nftlcore.o nftlmount.o
inftl-objs := inftlcore.o inftlmount.o
......
......@@ -526,7 +526,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
struct cfi_pri_intelext *extp = cfi->cmdset_priv;
/*
* Probing of multi-partition flash ships.
* Probing of multi-partition flash chips.
*
* To support multiple partitions when available, we simply arrange
* for each of them to have their own flchip structure even if they
......@@ -653,7 +653,7 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
resettime:
timeo = jiffies + HZ;
retry:
if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE)) {
if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) {
/*
* OK. We have possibility for contension on the write/erase
* operations which are global to the real chip and not per
......@@ -798,6 +798,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
if (mode == FL_READY && chip->oldstate == FL_READY)
return 0;
case FL_SHUTDOWN:
/* The machine is rebooting now,so no one can get chip anymore */
return -EIO;
default:
sleep:
set_current_state(TASK_UNINTERRUPTIBLE);
......@@ -1166,28 +1169,34 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
{
struct map_info *map = mtd->priv;
struct cfi_private *cfi = map->fldrv_priv;
unsigned long ofs;
unsigned long ofs, last_end = 0;
int chipnum;
int ret = 0;
if (!map->virt || (from + len > mtd->size))
return -EINVAL;
*mtdbuf = (void *)map->virt + from;
*retlen = 0;
/* Now lock the chip(s) to POINT state */
/* ofs: offset within the first chip that the first read should start */
chipnum = (from >> cfi->chipshift);
ofs = from - (chipnum << cfi->chipshift);
*mtdbuf = (void *)map->virt + cfi->chips[chipnum].start + ofs;
*retlen = 0;
while (len) {
unsigned long thislen;
if (chipnum >= cfi->numchips)
break;
/* We cannot point across chips that are virtually disjoint */
if (!last_end)
last_end = cfi->chips[chipnum].start;
else if (cfi->chips[chipnum].start != last_end)
break;
if ((len + ofs -1) >> cfi->chipshift)
thislen = (1<<cfi->chipshift) - ofs;
else
......@@ -1201,6 +1210,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
len -= thislen;
ofs = 0;
last_end += 1 << cfi->chipshift;
chipnum++;
}
return 0;
......@@ -1780,7 +1790,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
return ret;
}
int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
static int cfi_intelext_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
{
unsigned long ofs, len;
int ret;
......@@ -1930,7 +1940,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
__FUNCTION__, ofs, len);
cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
ofs, len, 0);
ofs, len, NULL);
#endif
ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
......@@ -1940,7 +1950,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
__FUNCTION__, ret);
cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
ofs, len, 0);
ofs, len, NULL);
#endif
return ret;
......@@ -1954,7 +1964,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n",
__FUNCTION__, ofs, len);
cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
ofs, len, 0);
ofs, len, NULL);
#endif
ret = cfi_varsize_frob(mtd, do_xxlock_oneblock,
......@@ -1964,7 +1974,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
printk(KERN_DEBUG "%s: lock status after, ret=%d\n",
__FUNCTION__, ret);
cfi_varsize_frob(mtd, do_printlockstatus_oneblock,
ofs, len, 0);
ofs, len, NULL);
#endif
return ret;
......@@ -2255,7 +2265,7 @@ static void cfi_intelext_save_locks(struct mtd_info *mtd)
adr = region->offset + block * len;
status = cfi_varsize_frob(mtd,
do_getlockstatus_oneblock, adr, len, 0);
do_getlockstatus_oneblock, adr, len, NULL);
if (status)
set_bit(block, region->lockmap);
else
......@@ -2402,10 +2412,10 @@ static int cfi_intelext_reset(struct mtd_info *mtd)
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);
ret = get_chip(map, chip, chip->start, FL_SHUTDOWN);
if (!ret) {
map_write(map, CMD(0xff), chip->start);
chip->state = FL_READY;
chip->state = FL_SHUTDOWN;
}
spin_unlock(chip->mutex);
}
......
......@@ -1609,7 +1609,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
}
int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
static int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
{
unsigned long ofs, len;
int ret;
......
......@@ -17,7 +17,6 @@
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
......@@ -70,6 +69,7 @@
/* Fujitsu */
#define MBM29F040C 0x00A4
#define MBM29F800BA 0x2258
#define MBM29LV650UE 0x22D7
#define MBM29LV320TE 0x22F6
#define MBM29LV320BE 0x22F9
......@@ -129,6 +129,7 @@
#define LH28F640BF 0x00b0
/* ST - www.st.com */
#define M29F800AB 0x0058
#define M29W800DT 0x00D7
#define M29W800DB 0x005B
#define M29W160DT 0x22C4
......@@ -644,6 +645,23 @@ static const struct amd_flash_info jedec_table[] = {
.regions = {
ERASEINFO(0x10000,8)
}
}, {
.mfr_id = MANUFACTURER_FUJITSU,
.dev_id = MBM29F800BA,
.name = "Fujitsu MBM29F800BA",
.uaddr = {
[0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
[1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
},
.DevSize = SIZE_1MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 4,
.regions = {
ERASEINFO(0x04000,1),
ERASEINFO(0x02000,2),
ERASEINFO(0x08000,1),
ERASEINFO(0x10000,15),
}
}, {
.mfr_id = MANUFACTURER_FUJITSU,
.dev_id = MBM29LV650UE,
......@@ -1510,6 +1528,23 @@ static const struct amd_flash_info jedec_table[] = {
ERASEINFO(0x1000,256)
}
}, {
.mfr_id = MANUFACTURER_ST,
.dev_id = M29F800AB,
.name = "ST M29F800AB",
.uaddr = {
[0] = MTD_UADDR_0x0AAA_0x0555, /* x8 */
[1] = MTD_UADDR_0x0555_0x02AA, /* x16 */
},
.DevSize = SIZE_1MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 4,
.regions = {
ERASEINFO(0x04000,1),
ERASEINFO(0x02000,2),
ERASEINFO(0x08000,1),
ERASEINFO(0x10000,15),
}
}, {
.mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */
.dev_id = M29W800DT,
......
......@@ -60,21 +60,22 @@ config MTD_DATAFLASH
Sometimes DataFlash chips are packaged inside MMC-format
cards; at this writing, the MMC stack won't handle those.
config MTD_DATAFLASH26
tristate "AT91RM9200 DataFlash AT26xxx"
depends on MTD && ARCH_AT91RM9200 && AT91_SPI
help
This enables access to the DataFlash chip (AT26xxx) on an
AT91RM9200-based board.
If you have such a board and such a DataFlash, say 'Y'.
config MTD_M25P80
tristate "Support for M25 SPI Flash"
tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
depends on SPI_MASTER && EXPERIMENTAL
help
This enables access to ST M25P80 and similar SPI flash chips,
used for program and data storage. Set up your spi devices
with the right board-specific platform data.
This enables access to most modern SPI flash chips, used for
program and data storage. Series supported include Atmel AT26DF,
Spansion S25SL, SST 25VF, ST M25P, and Winbond W25X. Other chips
are supported as well. See the driver source for the current list,
or to add other chips.
Note that the original DataFlash chips (AT45 series, not AT26DF),
need an entirely different driver.
Set up your spi devices with the right board-specific platform data,
if you want to specify device partitioning or to use a device which
doesn't support the JEDEC ID instruction.
config MTD_SLRAM
tristate "Uncached system RAM"
......
......@@ -16,5 +16,4 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o
obj-$(CONFIG_MTD_LART) += lart.o
obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
obj-$(CONFIG_MTD_DATAFLASH26) += at91_dataflash26.o
obj-$(CONFIG_MTD_M25P80) += m25p80.o
This diff is collapsed.
......@@ -81,9 +81,7 @@ static unsigned long __initdata doc_locations[] = {
#endif /* CONFIG_MTD_DOCPROBE_HIGH */
#elif defined(__PPC__)
0xe4000000,
#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
##else
#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
#endif
0xffffffff };
......
This diff is collapsed.
......@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
......@@ -89,7 +90,7 @@ struct dataflash {
unsigned short page_offset; /* offset in flash address */
unsigned int page_size; /* of bytes per page */
struct semaphore lock;
struct mutex lock;
struct spi_device *spi;
struct mtd_info mtd;
......@@ -167,7 +168,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
x.len = 4;
spi_message_add_tail(&x, &msg);
down(&priv->lock);
mutex_lock(&priv->lock);
while (instr->len > 0) {
unsigned int pageaddr;
int status;
......@@ -210,7 +211,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
instr->len -= priv->page_size;
}
}
up(&priv->lock);
mutex_unlock(&priv->lock);
/* Inform MTD subsystem that erase is complete */
instr->state = MTD_ERASE_DONE;
......@@ -266,7 +267,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
x[1].len = len;
spi_message_add_tail(&x[1], &msg);
down(&priv->lock);
mutex_lock(&priv->lock);
/* Continuous read, max clock = f(car) which may be less than
* the peak rate available. Some chips support commands with
......@@ -279,7 +280,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
/* plus 4 "don't care" bytes */
status = spi_sync(priv->spi, &msg);
up(&priv->lock);
mutex_unlock(&priv->lock);
if (status >= 0) {
*retlen = msg.actual_length - 8;
......@@ -336,7 +337,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
else
writelen = len;
down(&priv->lock);
mutex_lock(&priv->lock);
while (remaining > 0) {
DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
pageaddr, offset, writelen);
......@@ -441,7 +442,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
else
writelen = remaining;
}
up(&priv->lock);
mutex_unlock(&priv->lock);
return status;
}
......@@ -463,7 +464,7 @@ add_dataflash(struct spi_device *spi, char *name,
if (!priv)
return -ENOMEM;
init_MUTEX(&priv->lock);
mutex_init(&priv->lock);
priv->spi = spi;
priv->page_size = pagesize;
priv->page_offset = pageoffset;
......
......@@ -30,8 +30,8 @@
*
* Notes:
* Due to what I assume is more buggy SROM, the 64M PMC551 I
* have available claims that all 4 of it's DRAM banks have 64M
* of ram configured (making a grand total of 256M onboard).
* have available claims that all 4 of its DRAM banks have 64MiB
* of ram configured (making a grand total of 256MiB onboard).
* This is slightly annoying since the BAR0 size reflects the
* aperture size, not the dram size, and the V370PDC supplies no
* other method for memory size discovery. This problem is
......@@ -70,7 +70,7 @@
* made the memory unusable, added a fix to code to touch up
* the DRAM some.
*
* Bugs/FIXME's:
* Bugs/FIXMEs:
* * MUST fix the init function to not spin on a register
* waiting for it to set .. this does not safely handle busted
* devices that never reset the register correctly which will
......@@ -562,10 +562,10 @@ static u32 fixup_pmc551(struct pci_dev *dev)
/*
* Some screen fun
*/
printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at "
printk(KERN_DEBUG "pmc551: %d%sB (0x%x) of %sprefetchable memory at "
"0x%llx\n", (size < 1024) ? size : (size < 1048576) ?
size >> 10 : size >> 20,
(size < 1024) ? 'B' : (size < 1048576) ? 'K' : 'M', size,
(size < 1024) ? "" : (size < 1048576) ? "Ki" : "Mi", size,
((dcmd & (0x1 << 3)) == 0) ? "non-" : "",
(unsigned long long)pci_resource_start(dev, 0));
......@@ -649,14 +649,10 @@ MODULE_DESCRIPTION(PMC551_VERSION);
* Stuff these outside the ifdef so as to not bust compiled in driver support
*/
static int msize = 0;
#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE)
static int asize = CONFIG_MTD_PMC551_APERTURE_SIZE;
#else
static int asize = 0;
#endif
module_param(msize, int, 0);
MODULE_PARM_DESC(msize, "memory size in Megabytes [1 - 1024]");
MODULE_PARM_DESC(msize, "memory size in MiB [1 - 1024]");
module_param(asize, int, 0);
MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1-1024]");
......@@ -799,8 +795,7 @@ static int __init init_pmc551(void)
mtd->owner = THIS_MODULE;
if (add_mtd_device(mtd)) {
printk(KERN_NOTICE "pmc551: Failed to register new "
"device\n");
printk(KERN_NOTICE "pmc551: Failed to register new device\n");
pci_iounmap(PCI_Device, priv->start);
kfree(mtd->priv);
kfree(mtd);
......@@ -811,13 +806,13 @@ static int __init init_pmc551(void)
pci_dev_get(PCI_Device);
printk(KERN_NOTICE "Registered pmc551 memory device.\n");
printk(KERN_NOTICE "Mapped %dM of memory from 0x%p to 0x%p\n",
printk(KERN_NOTICE "Mapped %dMiB of memory from 0x%p to 0x%p\n",
priv->asize >> 20,
priv->start, priv->start + priv->asize);
printk(KERN_NOTICE "Total memory is %d%c\n",
printk(KERN_NOTICE "Total memory is %d%sB\n",
(length < 1024) ? length :
(length < 1048576) ? length >> 10 : length >> 20,
(length < 1024) ? 'B' : (length < 1048576) ? 'K' : 'M');
(length < 1024) ? "" : (length < 1048576) ? "Ki" : "Mi");
priv->nextpmc551 = pmc551list;
pmc551list = mtd;
found++;
......@@ -850,7 +845,7 @@ static void __exit cleanup_pmc551(void)
pmc551list = priv->nextpmc551;
if (priv->start) {
printk(KERN_DEBUG "pmc551: unmapping %dM starting at "
printk(KERN_DEBUG "pmc551: unmapping %dMiB starting at "
"0x%p\n", priv->asize >> 20, priv->start);
pci_iounmap(priv->dev, priv->start);
}
......
......@@ -580,14 +580,13 @@ int INFTL_mount(struct INFTLrecord *s)
logical_block = block = BLOCK_NIL;
/* Temporary buffer to store ANAC numbers. */
ANACtable = kmalloc(s->nb_blocks * sizeof(u8), GFP_KERNEL);
ANACtable = kcalloc(s->nb_blocks, sizeof(u8), GFP_KERNEL);
if (!ANACtable) {
printk(KERN_WARNING "INFTL: allocation of ANACtable "
"failed (%zd bytes)\n",
s->nb_blocks * sizeof(u8));
return -ENOMEM;
}
memset(ANACtable, 0, s->nb_blocks);
/*
* First pass is to explore each physical unit, and construct the
......
......@@ -163,20 +163,12 @@ config MTD_SBC_GXX
More info at
<http://www.arcomcontrols.com/products/icp/pc104/processors/SBC_GX1.htm>.
config MTD_LUBBOCK
tristate "CFI Flash device mapped on Intel Lubbock XScale eval board"
depends on ARCH_LUBBOCK && MTD_CFI_INTELEXT && MTD_PARTITIONS
help
This provides a driver for the on-board flash of the Intel
'Lubbock' XScale evaluation board.
config MTD_MAINSTONE
tristate "CFI Flash device mapped on Intel Mainstone XScale eval board"
depends on MACH_MAINSTONE && MTD_CFI_INTELEXT
config MTD_PXA2XX
tristate "CFI Flash device mapped on Intel XScale PXA2xx based boards"
depends on (PXA25x || PXA27x) && MTD_CFI_INTELEXT
select MTD_PARTITIONS
help
This provides a driver for the on-board flash of the Intel
'Mainstone PXA27x evaluation board.
This provides a driver for the NOR flash attached to a PXA2xx chip.
config MTD_OCTAGON
tristate "JEDEC Flash device mapped on Octagon 5066 SBC"
......@@ -354,7 +346,7 @@ config MTD_CFI_FLAGADM
config MTD_WALNUT
tristate "Flash device mapped on IBM 405GP Walnut"
depends on MTD_JEDECPROBE && WALNUT
depends on MTD_JEDECPROBE && WALNUT && !PPC_MERGE
help
This enables access routines for the flash chips on the IBM 405GP
Walnut board. If you have one of these boards and would like to
......@@ -370,7 +362,7 @@ config MTD_EBONY
config MTD_OCOTEA
tristate "Flash devices mapped on IBM 440GX Ocotea"
depends on MTD_CFI && OCOTEA
depends on MTD_CFI && OCOTEA && !PPC_MERGE
help
This enables access routines for the flash chips on the IBM 440GX
Ocotea board. If you have one of these boards and would like to
......@@ -384,22 +376,6 @@ config MTD_REDWOOD
Redwood board. If you have one of these boards and would like to
use the flash chips on it, say 'Y'.
config MTD_TQM834x
tristate "Flash device mapped on TQ Components TQM834x Boards"
depends on MTD_CFI && TQM834x
help
This enables access routines for the flash chips on the
TQ Components TQM834x boards. If you have one of these boards
and would like to use the flash chips on it, say 'Y'.
config MTD_OCELOT
tristate "Momenco Ocelot boot flash device"
depends on MOMENCO_OCELOT
help
This enables access routines for the boot flash device and for the
NVRAM on the Momenco Ocelot board. If you have one of these boards
and would like access to either of these, say 'Y'.
config MTD_SOLUTIONENGINE
tristate "CFI Flash device mapped on Hitachi SolutionEngine"
depends on SUPERH && MTD_CFI && MTD_REDBOOT_PARTS
......@@ -605,6 +581,13 @@ config MTD_SHARP_SL
help
This enables access to the flash chip on the Sharp SL Series of PDAs.
config MTD_INTEL_VR_NOR
tristate "NOR flash on Intel Vermilion Range Expansion Bus CS0"
depends on PCI
help
Map driver for a NOR flash bank located on the Expansion Bus of the
Intel Vermilion Range chipset.
config MTD_PLATRAM
tristate "Map driver for platform device RAM (mtd-ram)"
select MTD_RAM
......
......@@ -20,8 +20,7 @@ obj-$(CONFIG_MTD_ESB2ROM) += esb2rom.o
obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o
obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o
obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o
obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o
obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o
obj-$(CONFIG_MTD_MBX860) += mbx860.o
obj-$(CONFIG_MTD_CEIVA) += ceiva.o
obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
......@@ -43,7 +42,6 @@ obj-$(CONFIG_MTD_SUN_UFLASH) += sun_uflash.o
obj-$(CONFIG_MTD_VMAX) += vmax301.o
obj-$(CONFIG_MTD_SCx200_DOCFLASH)+= scx200_docflash.o
obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o
obj-$(CONFIG_MTD_OCELOT) += ocelot.o
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
obj-$(CONFIG_MTD_PCI) += pci.o
obj-$(CONFIG_MTD_ALCHEMY) += alchemy-flash.o
......@@ -70,4 +68,4 @@ obj-$(CONFIG_MTD_SHARP_SL) += sharpsl-flash.o
obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o
obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o
obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o
obj-$(CONFIG_MTD_TQM834x) += tqm834x.o
obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o
......@@ -75,13 +75,6 @@
#define BOARD_FLASH_WIDTH 2 /* 16-bits */
#endif
#ifdef CONFIG_MIPS_HYDROGEN3
#define BOARD_MAP_NAME "Hydrogen3 Flash"
#define BOARD_FLASH_SIZE 0x02000000 /* 32MB */
#define BOARD_FLASH_WIDTH 4 /* 32-bits */
#define USE_LOCAL_ACCESSORS /* why? */
#endif
#ifdef CONFIG_MIPS_BOSPORUS
#define BOARD_MAP_NAME "Bosporus Flash"
#define BOARD_FLASH_SIZE 0x01000000 /* 16MB */
......@@ -130,13 +123,6 @@ int __init alchemy_mtd_init(void)
window_addr = 0x20000000 - BOARD_FLASH_SIZE;
window_size = BOARD_FLASH_SIZE;
#ifdef CONFIG_MIPS_MIRAGE_WHY
/* Boot ROM flash bank only; no user bank */
window_addr = 0x1C000000;
window_size = 0x04000000;
/* USERFS from 0x1C00 0000 to 0x1FC00000 */
alchemy_partitions[0].size = 0x03C00000;
#endif
/*
* Static partition definition selection
......
/*
* drivers/mtd/maps/intel_vr_nor.c
*
* An MTD map driver for a NOR flash bank on the Expansion Bus of the Intel
* Vermilion Range chipset.
*
* The Vermilion Range Expansion Bus supports four chip selects, each of which
* has 64MiB of address space. The 2nd BAR of the Expansion Bus PCI Device
* is a 256MiB memory region containing the address spaces for all four of the
* chip selects, with start addresses hardcoded on 64MiB boundaries.
*
* This map driver only supports NOR flash on chip select 0. The buswidth
* (either 8 bits or 16 bits) is determined by reading the Expansion Bus Timing
* and Control Register for Chip Select 0 (EXP_TIMING_CS0). This driver does
* not modify the value in the EXP_TIMING_CS0 register except to enable writing
* and disable boot acceleration. The timing parameters in the register are
* assumed to have been properly initialized by the BIOS. The reset default
* timing parameters are maximally conservative (slow), so access to the flash
* will be slower than it should be if the BIOS has not initialized the timing
* parameters.
*
* Author: Andy Lowe <alowe@mvista.com>
*
* 2006 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/cfi.h>
#include <linux/mtd/flashchip.h>
#define DRV_NAME "vr_nor"
struct vr_nor_mtd {
void __iomem *csr_base;
struct map_info map;
struct mtd_info *info;
int nr_parts;
struct pci_dev *dev;
};
/* Expansion Bus Configuration and Status Registers are in BAR 0 */
#define EXP_CSR_MBAR 0
/* Expansion Bus Memory Window is BAR 1 */
#define EXP_WIN_MBAR 1
/* Maximum address space for Chip Select 0 is 64MiB */
#define CS0_SIZE 0x04000000
/* Chip Select 0 is at offset 0 in the Memory Window */
#define CS0_START 0x0
/* Chip Select 0 Timing Register is at offset 0 in CSR */
#define EXP_TIMING_CS0 0x00
#define TIMING_CS_EN (1 << 31) /* Chip Select Enable */
#define TIMING_BOOT_ACCEL_DIS (1 << 8) /* Boot Acceleration Disable */
#define TIMING_WR_EN (1 << 1) /* Write Enable */
#define TIMING_BYTE_EN (1 << 0) /* 8-bit vs 16-bit bus */
#define TIMING_MASK 0x3FFF0000
static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
{
if (p->nr_parts > 0) {
#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
del_mtd_partitions(p->info);
#endif
} else
del_mtd_device(p->info);
}
static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
{
int err = 0;
#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
struct mtd_partition *parts;
static const char *part_probes[] = { "cmdlinepart", NULL };
#endif
/* register the flash bank */
#if defined(CONFIG_MTD_PARTITIONS) || defined(CONFIG_MTD_PARTITIONS_MODULE)
/* partition the flash bank */
p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0);
if (p->nr_parts > 0)
err = add_mtd_partitions(p->info, parts, p->nr_parts);
#endif
if (p->nr_parts <= 0)
err = add_mtd_device(p->info);
return err;
}
static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
{
map_destroy(p->info);
}
static int __devinit vr_nor_mtd_setup(struct vr_nor_mtd *p)
{
static const char *probe_types[] =
{ "cfi_probe", "jedec_probe", NULL };
const char **type;
for (type = probe_types; !p->info && *type; type++)
p->info = do_map_probe(*type, &p->map);
if (!p->info)
return -ENODEV;
p->info->owner = THIS_MODULE;
return 0;
}
static void __devexit vr_nor_destroy_maps(struct vr_nor_mtd *p)
{
unsigned int exp_timing_cs0;
/* write-protect the flash bank */
exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0);
exp_timing_cs0 &= ~TIMING_WR_EN;
writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0);
/* unmap the flash window */
iounmap(p->map.virt);
/* unmap the csr window */
iounmap(p->csr_base);
}
/*
* Initialize the map_info structure and map the flash.
* Returns 0 on success, nonzero otherwise.
*/
static int __devinit vr_nor_init_maps(struct vr_nor_mtd *p)
{
unsigned long csr_phys, csr_len;
unsigned long win_phys, win_len;
unsigned int exp_timing_cs0;
int err;
csr_phys = pci_resource_start(p->dev, EXP_CSR_MBAR);
csr_len = pci_resource_len(p->dev, EXP_CSR_MBAR);
win_phys = pci_resource_start(p->dev, EXP_WIN_MBAR);
win_len = pci_resource_len(p->dev, EXP_WIN_MBAR);
if (!csr_phys || !csr_len || !win_phys || !win_len)
return -ENODEV;
if (win_len < (CS0_START + CS0_SIZE))
return -ENXIO;
p->csr_base = ioremap_nocache(csr_phys, csr_len);
if (!p->csr_base)
return -ENOMEM;
exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0);
if (!(exp_timing_cs0 & TIMING_CS_EN)) {
dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 "
"is disabled.\n");
err = -ENODEV;
goto release;
}
if ((exp_timing_cs0 & TIMING_MASK) == TIMING_MASK) {
dev_warn(&p->dev->dev, "Expansion Bus Chip Select 0 "
"is configured for maximally slow access times.\n");
}
p->map.name = DRV_NAME;
p->map.bankwidth = (exp_timing_cs0 & TIMING_BYTE_EN) ? 1 : 2;
p->map.phys = win_phys + CS0_START;
p->map.size = CS0_SIZE;
p->map.virt = ioremap_nocache(p->map.phys, p->map.size);
if (!p->map.virt) {
err = -ENOMEM;
goto release;
}
simple_map_init(&p->map);
/* Enable writes to flash bank */
exp_timing_cs0 |= TIMING_BOOT_ACCEL_DIS | TIMING_WR_EN;
writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0);
return 0;
release:
iounmap(p->csr_base);
return err;
}
static struct pci_device_id vr_nor_pci_ids[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x500D)},
{0,}
};
static void __devexit vr_nor_pci_remove(struct pci_dev *dev)
{
struct vr_nor_mtd *p = pci_get_drvdata(dev);
pci_set_drvdata(dev, NULL);
vr_nor_destroy_partitions(p);
vr_nor_destroy_mtd_setup(p);
vr_nor_destroy_maps(p);
kfree(p);
pci_release_regions(dev);
pci_disable_device(dev);
}
static int __devinit
vr_nor_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct vr_nor_mtd *p = NULL;
unsigned int exp_timing_cs0;
int err;
err = pci_enable_device(dev);
if (err)
goto out;
err = pci_request_regions(dev, DRV_NAME);
if (err)
goto disable_dev;
p = kzalloc(sizeof(*p), GFP_KERNEL);
err = -ENOMEM;
if (!p)
goto release;
p->dev = dev;
err = vr_nor_init_maps(p);
if (err)
goto release;
err = vr_nor_mtd_setup(p);
if (err)
goto destroy_maps;
err = vr_nor_init_partitions(p);
if (err)
goto destroy_mtd_setup;
pci_set_drvdata(dev, p);
return 0;
destroy_mtd_setup:
map_destroy(p->info);
destroy_maps:
/* write-protect the flash bank */
exp_timing_cs0 = readl(p->csr_base + EXP_TIMING_CS0);
exp_timing_cs0 &= ~TIMING_WR_EN;
writel(exp_timing_cs0, p->csr_base + EXP_TIMING_CS0);
/* unmap the flash window */
iounmap(p->map.virt);
/* unmap the csr window */
iounmap(p->csr_base);
release:
kfree(p);
pci_release_regions(dev);
disable_dev:
pci_disable_device(dev);
out:
return err;
}
static struct pci_driver vr_nor_pci_driver = {
.name = DRV_NAME,
.probe = vr_nor_pci_probe,
.remove = __devexit_p(vr_nor_pci_remove),
.id_table = vr_nor_pci_ids,
};
static int __init vr_nor_mtd_init(void)
{
return pci_register_driver(&vr_nor_pci_driver);
}
static void __exit vr_nor_mtd_exit(void)
{
pci_unregister_driver(&vr_nor_pci_driver);
}
module_init(vr_nor_mtd_init);
module_exit(vr_nor_mtd_exit);
MODULE_AUTHOR("Andy Lowe");
MODULE_DESCRIPTION("MTD map driver for NOR flash on Intel Vermilion Range");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, vr_nor_pci_ids);
/*
* $Id: lubbock-flash.c,v 1.21 2005/11/07 11:14:27 gleixner Exp $
*
* Map driver for the Lubbock developer platform.
*
* Author: Nicolas Pitre
* Copyright: (C) 2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/lubbock.h>
#include <asm/cacheflush.h>
#define ROM_ADDR 0x00000000
#define FLASH_ADDR 0x04000000
#define WINDOW_SIZE 64*1024*1024
static void lubbock_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len)
{
flush_ioremap_region(map->phys, map->cached, from, len);
}
static struct map_info lubbock_maps[2] = { {
.size = WINDOW_SIZE,
.phys = 0x00000000,
.inval_cache = lubbock_map_inval_cache,
}, {
.size = WINDOW_SIZE,
.phys = 0x04000000,
.inval_cache = lubbock_map_inval_cache,
} };
static struct mtd_partition lubbock_partitions[] = {
{
.name = "Bootloader",
.size = 0x00040000,
.offset = 0,
.mask_flags = MTD_WRITEABLE /* force read-only */
},{
.name = "Kernel",
.size = 0x00100000,
.offset = 0x00040000,
},{
.name = "Filesystem",
.size = MTDPART_SIZ_FULL,
.offset = 0x00140000
}
};
static struct mtd_info *mymtds[2];
static struct mtd_partition *parsed_parts[2];
static int nr_parsed_parts[2];
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
static int __init init_lubbock(void)
{
int flashboot = (LUB_CONF_SWITCHES & 1);
int ret = 0, i;
lubbock_maps[0].bankwidth = lubbock_maps[1].bankwidth =
(BOOT_DEF & 1) ? 2 : 4;
/* Compensate for the nROMBT switch which swaps the flash banks */
printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n",
flashboot?"Flash":"ROM", flashboot);
lubbock_maps[flashboot^1].name = "Lubbock Application Flash";
lubbock_maps[flashboot].name = "Lubbock Boot ROM";
for (i = 0; i < 2; i++) {
lubbock_maps[i].virt = ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
if (!lubbock_maps[i].virt) {
printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name);
if (!ret)
ret = -ENOMEM;
continue;
}
lubbock_maps[i].cached = ioremap_cached(lubbock_maps[i].phys, WINDOW_SIZE);
if (!lubbock_maps[i].cached)
printk(KERN_WARNING "Failed to ioremap cached %s\n", lubbock_maps[i].name);
simple_map_init(&lubbock_maps[i]);
printk(KERN_NOTICE "Probing %s at physical address 0x%08lx (%d-bit bankwidth)\n",
lubbock_maps[i].name, lubbock_maps[i].phys,
lubbock_maps[i].bankwidth * 8);
mymtds[i] = do_map_probe("cfi_probe", &lubbock_maps[i]);
if (!mymtds[i]) {
iounmap((void *)lubbock_maps[i].virt);
if (lubbock_maps[i].cached)
iounmap(lubbock_maps[i].cached);
if (!ret)
ret = -EIO;
continue;
}
mymtds[i]->owner = THIS_MODULE;
ret = parse_mtd_partitions(mymtds[i], probes,
&parsed_parts[i], 0);
if (ret > 0)
nr_parsed_parts[i] = ret;
}
if (!mymtds[0] && !mymtds[1])
return ret;
for (i = 0; i < 2; i++) {
if (!mymtds[i]) {
printk(KERN_WARNING "%s is absent. Skipping\n", lubbock_maps[i].name);
} else if (nr_parsed_parts[i]) {
add_mtd_partitions(mymtds[i], parsed_parts[i], nr_parsed_parts[i]);
} else if (!i) {
printk("Using static partitions on %s\n", lubbock_maps[i].name);
add_mtd_partitions(mymtds[i], lubbock_partitions, ARRAY_SIZE(lubbock_partitions));
} else {
printk("Registering %s as whole device\n", lubbock_maps[i].name);
add_mtd_device(mymtds[i]);
}
}
return 0;
}
static void __exit cleanup_lubbock(void)
{
int i;
for (i = 0; i < 2; i++) {
if (!mymtds[i])
continue;
if (nr_parsed_parts[i] || !i)
del_mtd_partitions(mymtds[i]);
else
del_mtd_device(mymtds[i]);
map_destroy(mymtds[i]);
iounmap((void *)lubbock_maps[i].virt);
if (lubbock_maps[i].cached)
iounmap(lubbock_maps[i].cached);
kfree(parsed_parts[i]);
}
}
module_init(init_lubbock);
module_exit(cleanup_lubbock);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
MODULE_DESCRIPTION("MTD map driver for Intel Lubbock");
/*
* $Id: $
*
* Map driver for the Mainstone developer platform.
*
* Author: Nicolas Pitre
* Copyright: (C) 2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/mainstone.h>
#include <asm/cacheflush.h>
#define ROM_ADDR 0x00000000
#define FLASH_ADDR 0x04000000
#define WINDOW_SIZE 0x04000000
static void mainstone_map_inval_cache(struct map_info *map, unsigned long from,
ssize_t len)
{
flush_ioremap_region(map->phys, map->cached, from, len);
}
static struct map_info mainstone_maps[2] = { {
.size = WINDOW_SIZE,
.phys = PXA_CS0_PHYS,
.inval_cache = mainstone_map_inval_cache,
}, {
.size = WINDOW_SIZE,
.phys = PXA_CS1_PHYS,
.inval_cache = mainstone_map_inval_cache,
} };
static struct mtd_partition mainstone_partitions[] = {
{
.name = "Bootloader",
.size = 0x00040000,
.offset = 0,
.mask_flags = MTD_WRITEABLE /* force read-only */
},{
.name = "Kernel",
.size = 0x00400000,
.offset = 0x00040000,
},{
.name = "Filesystem",
.size = MTDPART_SIZ_FULL,
.offset = 0x00440000
}
};
static struct mtd_info *mymtds[2];
static struct mtd_partition *parsed_parts[2];
static int nr_parsed_parts[2];
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
static int __init init_mainstone(void)
{
int SW7 = 0; /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
int ret = 0, i;
mainstone_maps[0].bankwidth = (BOOT_DEF & 1) ? 2 : 4;
mainstone_maps[1].bankwidth = 4;
/* Compensate for SW7 which swaps the flash banks */
mainstone_maps[SW7].name = "processor flash";
mainstone_maps[SW7 ^ 1].name = "main board flash";
printk(KERN_NOTICE "Mainstone configured to boot from %s\n",
mainstone_maps[0].name);
for (i = 0; i < 2; i++) {
mainstone_maps[i].virt = ioremap(mainstone_maps[i].phys,
WINDOW_SIZE);
if (!mainstone_maps[i].virt) {
printk(KERN_WARNING "Failed to ioremap %s\n",
mainstone_maps[i].name);
if (!ret)
ret = -ENOMEM;
continue;
}
mainstone_maps[i].cached =
ioremap_cached(mainstone_maps[i].phys, WINDOW_SIZE);
if (!mainstone_maps[i].cached)
printk(KERN_WARNING "Failed to ioremap cached %s\n",
mainstone_maps[i].name);
simple_map_init(&mainstone_maps[i]);
printk(KERN_NOTICE
"Probing %s at physical address 0x%08lx"
" (%d-bit bankwidth)\n",
mainstone_maps[i].name, mainstone_maps[i].phys,
mainstone_maps[i].bankwidth * 8);
mymtds[i] = do_map_probe("cfi_probe", &mainstone_maps[i]);
if (!mymtds[i]) {
iounmap((void *)mainstone_maps[i].virt);
if (mainstone_maps[i].cached)
iounmap(mainstone_maps[i].cached);
if (!ret)
ret = -EIO;
continue;
}
mymtds[i]->owner = THIS_MODULE;
ret = parse_mtd_partitions(mymtds[i], probes,
&parsed_parts[i], 0);
if (ret > 0)
nr_parsed_parts[i] = ret;
}
if (!mymtds[0] && !mymtds[1])
return ret;
for (i = 0; i < 2; i++) {
if (!mymtds[i]) {
printk(KERN_WARNING "%s is absent. Skipping\n",
mainstone_maps[i].name);
} else if (nr_parsed_parts[i]) {
add_mtd_partitions(mymtds[i], parsed_parts[i],
nr_parsed_parts[i]);
} else if (!i) {
printk("Using static partitions on %s\n",
mainstone_maps[i].name);
add_mtd_partitions(mymtds[i], mainstone_partitions,
ARRAY_SIZE(mainstone_partitions));
} else {
printk("Registering %s as whole device\n",
mainstone_maps[i].name);
add_mtd_device(mymtds[i]);
}
}
return 0;
}
static void __exit cleanup_mainstone(void)
{
int i;
for (i = 0; i < 2; i++) {
if (!mymtds[i])
continue;
if (nr_parsed_parts[i] || !i)
del_mtd_partitions(mymtds[i]);
else
del_mtd_device(mymtds[i]);
map_destroy(mymtds[i]);
iounmap((void *)mainstone_maps[i].virt);
if (mainstone_maps[i].cached)
iounmap(mainstone_maps[i].cached);
kfree(parsed_parts[i]);
}
}
module_init(init_mainstone);
module_exit(cleanup_mainstone);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
MODULE_DESCRIPTION("MTD map driver for Intel Mainstone");
......@@ -158,68 +158,11 @@ static struct notifier_block nettel_notifier_block = {
nettel_reboot_notifier, NULL, 0
};
/*
* Erase the configuration file system.
* Used to support the software reset button.
*/
static void nettel_erasecallback(struct erase_info *done)
{
wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
wake_up(wait_q);
}
static struct erase_info nettel_erase;
int nettel_eraseconfig(void)
{
struct mtd_info *mtd;
DECLARE_WAITQUEUE(wait, current);
wait_queue_head_t wait_q;
int ret;
init_waitqueue_head(&wait_q);
mtd = get_mtd_device(NULL, 2);
if (!IS_ERR(mtd)) {
nettel_erase.mtd = mtd;
nettel_erase.callback = nettel_erasecallback;
nettel_erase.callback = NULL;
nettel_erase.addr = 0;
nettel_erase.len = mtd->size;
nettel_erase.priv = (u_long) &wait_q;
nettel_erase.priv = 0;
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&wait_q, &wait);
ret = mtd->erase(mtd, &nettel_erase);
if (ret) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&wait_q, &wait);
put_mtd_device(mtd);
return(ret);
}
schedule(); /* Wait for erase to finish. */
remove_wait_queue(&wait_q, &wait);
put_mtd_device(mtd);
}
return(0);
}
#else
int nettel_eraseconfig(void)
{
return(0);
}
#endif
/****************************************************************************/
int __init nettel_init(void)
static int __init nettel_init(void)
{
volatile unsigned long *amdpar;
unsigned long amdaddr, maxsize;
......@@ -421,10 +364,6 @@ int __init nettel_init(void)
intel_mtd->owner = THIS_MODULE;
#ifndef CONFIG_BLK_DEV_INITRD
ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, 1);
#endif
num_intel_partitions = sizeof(nettel_intel_partitions) /
sizeof(nettel_intel_partitions[0]);
......@@ -477,7 +416,7 @@ int __init nettel_init(void)
/****************************************************************************/
void __exit nettel_cleanup(void)
static void __exit nettel_cleanup(void)
{
#ifdef CONFIG_MTD_CFI_INTELEXT
unregister_reboot_notifier(&nettel_notifier_block);
......
/*
* $Id: ocelot.c,v 1.17 2005/11/07 11:14:27 gleixner Exp $
*
* Flash on Momenco Ocelot
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define OCELOT_PLD 0x2c000000
#define FLASH_WINDOW_ADDR 0x2fc00000
#define FLASH_WINDOW_SIZE 0x00080000
#define FLASH_BUSWIDTH 1
#define NVRAM_WINDOW_ADDR 0x2c800000
#define NVRAM_WINDOW_SIZE 0x00007FF0
#define NVRAM_BUSWIDTH 1
static unsigned int cacheflush = 0;
static struct mtd_info *flash_mtd;
static struct mtd_info *nvram_mtd;
static void ocelot_ram_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf)
{
struct map_info *map = mtd->priv;
size_t done = 0;
/* If we use memcpy, it does word-wide writes. Even though we told the
GT64120A that it's an 8-bit wide region, word-wide writes don't work.
We end up just writing the first byte of the four to all four bytes.
So we have this loop instead */
*retlen = len;
while(len) {
__raw_writeb(*(unsigned char *) from, map->virt + to);
from++;
to++;
len--;
}
}
static struct mtd_partition *parsed_parts;
struct map_info ocelot_flash_map = {
.name = "Ocelot boot flash",
.size = FLASH_WINDOW_SIZE,
.bankwidth = FLASH_BUSWIDTH,
.phys = FLASH_WINDOW_ADDR,
};
struct map_info ocelot_nvram_map = {
.name = "Ocelot NVRAM",
.size = NVRAM_WINDOW_SIZE,
.bankwidth = NVRAM_BUSWIDTH,
.phys = NVRAM_WINDOW_ADDR,
};
static const char *probes[] = { "RedBoot", NULL };
static int __init init_ocelot_maps(void)
{
void *pld;
int nr_parts;
unsigned char brd_status;
printk(KERN_INFO "Momenco Ocelot MTD mappings: Flash 0x%x at 0x%x, NVRAM 0x%x at 0x%x\n",
FLASH_WINDOW_SIZE, FLASH_WINDOW_ADDR, NVRAM_WINDOW_SIZE, NVRAM_WINDOW_ADDR);
/* First check whether the flash jumper is present */
pld = ioremap(OCELOT_PLD, 0x10);
if (!pld) {
printk(KERN_NOTICE "Failed to ioremap Ocelot PLD\n");
return -EIO;
}
brd_status = readb(pld+4);
iounmap(pld);
/* Now ioremap the NVRAM space */
ocelot_nvram_map.virt = ioremap_nocache(NVRAM_WINDOW_ADDR, NVRAM_WINDOW_SIZE);
if (!ocelot_nvram_map.virt) {
printk(KERN_NOTICE "Failed to ioremap Ocelot NVRAM space\n");
return -EIO;
}
simple_map_init(&ocelot_nvram_map);
/* And do the RAM probe on it to get an MTD device */
nvram_mtd = do_map_probe("map_ram", &ocelot_nvram_map);
if (!nvram_mtd) {
printk("NVRAM probe failed\n");
goto fail_1;
}
nvram_mtd->owner = THIS_MODULE;
nvram_mtd->erasesize = 16;
/* Override the write() method */
nvram_mtd->write = ocelot_ram_write;
/* Now map the flash space */
ocelot_flash_map.virt = ioremap_nocache(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE);
if (!ocelot_flash_map.virt) {
printk(KERN_NOTICE "Failed to ioremap Ocelot flash space\n");
goto fail_2;
}
/* Now the cached version */
ocelot_flash_map.cached = (unsigned long)__ioremap(FLASH_WINDOW_ADDR, FLASH_WINDOW_SIZE, 0);
simple_map_init(&ocelot_flash_map);
/* Only probe for flash if the write jumper is present */
if (brd_status & 0x40) {
flash_mtd = do_map_probe("jedec", &ocelot_flash_map);
} else {
printk(KERN_NOTICE "Ocelot flash write jumper not present. Treating as ROM\n");
}
/* If that failed or the jumper's absent, pretend it's ROM */
if (!flash_mtd) {
flash_mtd = do_map_probe("map_rom", &ocelot_flash_map);
/* If we're treating it as ROM, set the erase size */
if (flash_mtd)
flash_mtd->erasesize = 0x10000;
}
if (!flash_mtd)
goto fail3;
add_mtd_device(nvram_mtd);
flash_mtd->owner = THIS_MODULE;
nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
if (nr_parts > 0)
add_mtd_partitions(flash_mtd, parsed_parts, nr_parts);
else
add_mtd_device(flash_mtd);
return 0;
fail3:
iounmap((void *)ocelot_flash_map.virt);
if (ocelot_flash_map.cached)
iounmap((void *)ocelot_flash_map.cached);
fail_2:
map_destroy(nvram_mtd);
fail_1:
iounmap((void *)ocelot_nvram_map.virt);
return -ENXIO;
}
static void __exit cleanup_ocelot_maps(void)
{
del_mtd_device(nvram_mtd);
map_destroy(nvram_mtd);
iounmap((void *)ocelot_nvram_map.virt);
if (parsed_parts)
del_mtd_partitions(flash_mtd);
else
del_mtd_device(flash_mtd);
map_destroy(flash_mtd);
iounmap((void *)ocelot_flash_map.virt);
if (ocelot_flash_map.cached)
iounmap((void *)ocelot_flash_map.cached);
}
module_init(init_ocelot_maps);
module_exit(cleanup_ocelot_maps);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Red Hat, Inc. - David Woodhouse <dwmw2@cambridge.redhat.com>");
MODULE_DESCRIPTION("MTD map driver for Momenco Ocelot board");
......@@ -232,7 +232,6 @@ static int __devinit of_flash_probe(struct of_device *dev,
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
goto err_out;
memset(info, 0, sizeof(*info));
dev_set_drvdata(&dev->dev, info);
......
......@@ -73,13 +73,16 @@ int __init init_msp_flash(void)
return -ENXIO;
printk(KERN_NOTICE "Found %d PMC flash devices\n", fcnt);
msp_flash = (struct mtd_info **)kmalloc(
fcnt * sizeof(struct map_info *), GFP_KERNEL);
msp_parts = (struct mtd_partition **)kmalloc(
fcnt * sizeof(struct mtd_partition *), GFP_KERNEL);
msp_maps = (struct map_info *)kmalloc(
fcnt * sizeof(struct mtd_info), GFP_KERNEL);
memset(msp_maps, 0, fcnt * sizeof(struct mtd_info));
msp_flash = kmalloc(fcnt * sizeof(struct map_info *), GFP_KERNEL);
msp_parts = kmalloc(fcnt * sizeof(struct mtd_partition *), GFP_KERNEL);
msp_maps = kcalloc(fcnt, sizeof(struct mtd_info), GFP_KERNEL);
if (!msp_flash || !msp_parts || !msp_maps) {
kfree(msp_maps);
kfree(msp_parts);
kfree(msp_flash);
return -ENOMEM;
}
/* loop over the flash devices, initializing each */
for (i = 0; i < fcnt; i++) {
......@@ -95,9 +98,8 @@ int __init init_msp_flash(void)
continue;
}
msp_parts[i] = (struct mtd_partition *)kmalloc(
pcnt * sizeof(struct mtd_partition), GFP_KERNEL);
memset(msp_parts[i], 0, pcnt * sizeof(struct mtd_partition));
msp_parts[i] = kcalloc(pcnt, sizeof(struct mtd_partition),
GFP_KERNEL);
/* now initialize the devices proper */
flash_name[5] = '0' + i;
......
......@@ -79,7 +79,6 @@ static int __init init_rrmap(void)
rr_mtd->owner = THIS_MODULE;
add_mtd_device(rr_mtd);
ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, rr_mtd->index);
return 0;
}
......
/*
* drivers/mtd/maps/pq2fads.c
*
* Mapping for the flash SIMM on 8272ADS and PQ2FADS board
*
* Author: Vitaly Bordug <vbordug@ru.mvista.com>
*
* 2005 (c) MontaVista Software, Inc. This file is licensed under
* the terms of the GNU General Public License version 2. This program
* is licensed "as is" without any warranty of any kind, whether express
* or implied.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/ppcboot.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
/*
NOTE: bank width and interleave relative to the installed flash
should have been chosen within MTD_CFI_GEOMETRY options.
*/
#define PQ2FADS_BANK_WIDTH 4
static struct mtd_partition pq2fads_partitions[] = {
{
#ifdef CONFIG_ADS8272
.name = "HRCW",
.size = 0x40000,
.offset = 0,
.mask_flags = MTD_WRITEABLE, /* force read-only */
}, {
.name = "User FS",
.size = 0x5c0000,
.offset = 0x40000,
#else
.name = "User FS",
.size = 0x600000,
.offset = 0,
#endif
}, {
.name = "uImage",
.size = 0x100000,
.offset = 0x600000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
}, {
.name = "bootloader",
.size = 0x40000,
.offset = 0x700000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
}, {
.name = "bootloader env",
.size = 0x40000,
.offset = 0x740000,
.mask_flags = MTD_WRITEABLE, /* force read-only */
}
};
/* pointer to MPC885ADS board info data */
extern unsigned char __res[];
static int __init init_pq2fads_mtd(void)
{
bd_t *bd = (bd_t *)__res;
physmap_configure(bd->bi_flashstart, bd->bi_flashsize, PQ2FADS_BANK_WIDTH, NULL);
physmap_set_partitions(pq2fads_partitions,
sizeof (pq2fads_partitions) /
sizeof (pq2fads_partitions[0]));
return 0;
}
static void __exit cleanup_pq2fads_mtd(void)
{
}
module_init(init_pq2fads_mtd);
module_exit(cleanup_pq2fads_mtd);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MTD map and partitions for MPC8272ADS boards");
/*
* Map driver for Intel XScale PXA2xx platforms.
*
* Author: Nicolas Pitre
* Copyright: (C) 2001 MontaVista Software Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/mach/flash.h>
static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from,
ssize_t len)
{
consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
}
struct pxa2xx_flash_info {
struct mtd_partition *parts;
int nr_parts;
struct mtd_info *mtd;
struct map_info map;
};
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
static int __init pxa2xx_flash_probe(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct flash_platform_data *flash = pdev->dev.platform_data;
struct pxa2xx_flash_info *info;
struct mtd_partition *parts;
struct resource *res;
int ret = 0;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
info = kmalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL);
if (!info)
return -ENOMEM;
memset(info, 0, sizeof(struct pxa2xx_flash_info));
info->map.name = (char *) flash->name;
info->map.bankwidth = flash->width;
info->map.phys = res->start;
info->map.size = res->end - res->start + 1;
info->parts = flash->parts;
info->nr_parts = flash->nr_parts;
info->map.virt = ioremap(info->map.phys, info->map.size);
if (!info->map.virt) {
printk(KERN_WARNING "Failed to ioremap %s\n",
info->map.name);
return -ENOMEM;
}
info->map.cached =
ioremap_cached(info->map.phys, info->map.size);
if (!info->map.cached)
printk(KERN_WARNING "Failed to ioremap cached %s\n",
info->map.name);
info->map.inval_cache = pxa2xx_map_inval_cache;
simple_map_init(&info->map);
printk(KERN_NOTICE
"Probing %s at physical address 0x%08lx"
" (%d-bit bankwidth)\n",
info->map.name, (unsigned long)info->map.phys,
info->map.bankwidth * 8);
info->mtd = do_map_probe(flash->map_name, &info->map);
if (!info->mtd) {
iounmap((void *)info->map.virt);
if (info->map.cached)
iounmap(info->map.cached);
return -EIO;
}
info->mtd->owner = THIS_MODULE;
#ifdef CONFIG_MTD_PARTITIONS
ret = parse_mtd_partitions(info->mtd, probes, &parts, 0);
if (ret > 0) {
info->nr_parts = ret;
info->parts = parts;
}
#endif
if (info->nr_parts) {
add_mtd_partitions(info->mtd, info->parts,
info->nr_parts);
} else {
printk("Registering %s as whole device\n",
info->map.name);
add_mtd_device(info->mtd);
}
dev_set_drvdata(dev, info);
return 0;
}
static int __exit pxa2xx_flash_remove(struct device *dev)
{
struct pxa2xx_flash_info *info = dev_get_drvdata(dev);
dev_set_drvdata(dev, NULL);
#ifdef CONFIG_MTD_PARTITIONS
if (info->nr_parts)
del_mtd_partitions(info->mtd);
else
#endif
del_mtd_device(info->mtd);
map_destroy(info->mtd);
iounmap(info->map.virt);
if (info->map.cached)
iounmap(info->map.cached);
kfree(info->parts);
kfree(info);
return 0;
}
#ifdef CONFIG_PM
static int pxa2xx_flash_suspend(struct device *dev, pm_message_t state)
{
struct pxa2xx_flash_info *info = dev_get_drvdata(dev);
int ret = 0;
if (info->mtd && info->mtd->suspend)
ret = info->mtd->suspend(info->mtd);
return ret;
}
static int pxa2xx_flash_resume(struct device *dev)
{
struct pxa2xx_flash_info *info = dev_get_drvdata(dev);
if (info->mtd && info->mtd->resume)
info->mtd->resume(info->mtd);
return 0;
}
static void pxa2xx_flash_shutdown(struct device *dev)
{
struct pxa2xx_flash_info *info = dev_get_drvdata(dev);
if (info && info->mtd->suspend(info->mtd) == 0)
info->mtd->resume(info->mtd);
}
#else
#define pxa2xx_flash_suspend NULL
#define pxa2xx_flash_resume NULL
#define pxa2xx_flash_shutdown NULL
#endif
static struct device_driver pxa2xx_flash_driver = {
.name = "pxa2xx-flash",
.bus = &platform_bus_type,
.probe = pxa2xx_flash_probe,
.remove = __exit_p(pxa2xx_flash_remove),
.suspend = pxa2xx_flash_suspend,
.resume = pxa2xx_flash_resume,
.shutdown = pxa2xx_flash_shutdown,
};
static int __init init_pxa2xx_flash(void)
{
return driver_register(&pxa2xx_flash_driver);
}
static void __exit cleanup_pxa2xx_flash(void)
{
driver_unregister(&pxa2xx_flash_driver);
}
module_init(init_pxa2xx_flash);
module_exit(cleanup_pxa2xx_flash);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
MODULE_DESCRIPTION("MTD map driver for Intel XScale PXA2xx");
/*
* drivers/mtd/maps/tqm834x.c
*
* MTD mapping driver for TQM834x boards
*
* Copyright 2005 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/ppcboot.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#define FLASH_BANK_MAX 2
extern unsigned char __res[];
/* trivial struct to describe partition information */
struct mtd_part_def
{
int nums;
unsigned char *type;
struct mtd_partition* mtd_part;
};
static struct mtd_info* mtd_banks[FLASH_BANK_MAX];
static struct map_info* map_banks[FLASH_BANK_MAX];
static struct mtd_part_def part_banks[FLASH_BANK_MAX];
static unsigned long num_banks;
static unsigned long start_scan_addr;
#ifdef CONFIG_MTD_PARTITIONS
/*
* The following defines the partition layout of TQM834x boards.
*
* See include/linux/mtd/partitions.h for definition of the
* mtd_partition structure.
*
* Assume minimal initial size of 4 MiB per bank, will be updated
* later in init_tqm834x_mtd() routine.
*/
/* Partition definition for the first flash bank which is always present. */
static struct mtd_partition tqm834x_partitions_bank1[] = {
{
.name = "u-boot", /* u-boot firmware */
.offset = 0x00000000,
.size = 0x00040000, /* 256 KiB */
/*mask_flags: MTD_WRITEABLE, * force read-only */
},
{
.name = "env", /* u-boot environment */
.offset = 0x00040000,
.size = 0x00020000, /* 128 KiB */
/*mask_flags: MTD_WRITEABLE, * force read-only */
},
{
.name = "kernel", /* linux kernel image */
.offset = 0x00060000,
.size = 0x00100000, /* 1 MiB */
/*mask_flags: MTD_WRITEABLE, * force read-only */
},
{
.name = "initrd", /* ramdisk image */
.offset = 0x00160000,
.size = 0x00200000, /* 2 MiB */
},
{
.name = "user", /* user data */
.offset = 0x00360000,
.size = 0x000a0000, /* remaining space */
/* NOTE: this parttion size is re-calcated in */
/* init_tqm834x_mtd() to cover actual remaining space. */
},
};
/* Partition definition for the second flash bank which may be present on some
* TQM834x boards.
*/
static struct mtd_partition tqm834x_partitions_bank2[] = {
{
.name = "jffs2", /* jffs2 filesystem */
.offset = 0x00000000,
.size = 0x00400000, /* whole device */
/* NOTE: this parttion size is re-calcated in */
/* init_tqm834x_mtd() to cover actual device size. */
},
};
#endif /* CONFIG_MTD_PARTITIONS */
static int __init init_tqm834x_mtd(void)
{
int idx = 0, ret = 0;
unsigned long flash_addr, flash_size, mtd_size = 0;
/* pointer to TQM834x board info data */
bd_t *bd = (bd_t *)__res;
#ifdef CONFIG_MTD_CMDLINE_PARTS
int n;
char mtdid[4];
const char *part_probes[] = { "cmdlinepart", NULL };
#endif
flash_addr = bd->bi_flashstart;
flash_size = bd->bi_flashsize;
/* request maximum flash size address space */
start_scan_addr = (unsigned long)ioremap(flash_addr, flash_size);
if (!start_scan_addr) {
printk("%s: Failed to ioremap address: 0x%lx\n",
__FUNCTION__, flash_addr);
return -EIO;
}
for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
if (mtd_size >= flash_size)
break;
pr_debug("%s: chip probing count %d\n", __FUNCTION__, idx);
map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL);
if (map_banks[idx] == NULL) {
ret = -ENOMEM;
goto error_mem;
}
map_banks[idx]->name = kzalloc(16, GFP_KERNEL);
if (map_banks[idx]->name == NULL) {
ret = -ENOMEM;
goto error_mem;
}
sprintf(map_banks[idx]->name, "TQM834x-%d", idx);
map_banks[idx]->size = flash_size;
map_banks[idx]->bankwidth = 4;
simple_map_init(map_banks[idx]);
map_banks[idx]->virt = (void __iomem *)
(start_scan_addr + ((idx > 0) ?
(mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0));
map_banks[idx]->phys =
flash_addr + ((idx > 0) ?
(mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0) : 0);
/* start to probe flash chips */
mtd_banks[idx] = do_map_probe("cfi_probe", map_banks[idx]);
if (mtd_banks[idx]) {
mtd_banks[idx]->owner = THIS_MODULE;
mtd_size += mtd_banks[idx]->size;
num_banks++;
pr_debug("%s: bank %ld, name: %s, size: %d bytes \n",
__FUNCTION__, num_banks,
mtd_banks[idx]->name, mtd_banks[idx]->size);
}
}
/* no supported flash chips found */
if (!num_banks) {
printk("TQM834x: No supported flash chips found!\n");
ret = -ENXIO;
goto error_mem;
}
#ifdef CONFIG_MTD_PARTITIONS
/*
* Select static partition definitions
*/
n = ARRAY_SIZE(tqm834x_partitions_bank1);
part_banks[0].mtd_part = tqm834x_partitions_bank1;
part_banks[0].type = "static image bank1";
part_banks[0].nums = n;
/* update last partition size to cover actual remaining space */
tqm834x_partitions_bank1[n - 1].size =
mtd_banks[0]->size -
tqm834x_partitions_bank1[n - 1].offset;
/* check if we have second bank? */
if (num_banks == 2) {
n = ARRAY_SIZE(tqm834x_partitions_bank2);
part_banks[1].mtd_part = tqm834x_partitions_bank2;
part_banks[1].type = "static image bank2";
part_banks[1].nums = n;
/* update last partition size to cover actual remaining space */
tqm834x_partitions_bank2[n - 1].size =
mtd_banks[1]->size -
tqm834x_partitions_bank2[n - 1].offset;
}
for(idx = 0; idx < num_banks ; idx++) {
#ifdef CONFIG_MTD_CMDLINE_PARTS
sprintf(mtdid, "%d", idx);
n = parse_mtd_partitions(mtd_banks[idx],
part_probes,
&part_banks[idx].mtd_part,
0);
pr_debug("%s: %d command line partitions on bank %s\n",
__FUNCTION__, n, mtdid);
if (n > 0) {
part_banks[idx].type = "command line";
part_banks[idx].nums = n;
}
#endif /* CONFIG_MTD_CMDLINE_PARTS */
if (part_banks[idx].nums == 0) {
printk(KERN_NOTICE
"TQM834x flash bank %d: no partition info "
"available, registering whole device\n", idx);
add_mtd_device(mtd_banks[idx]);
} else {
printk(KERN_NOTICE
"TQM834x flash bank %d: Using %s partition "
"definition\n", idx, part_banks[idx].type);
add_mtd_partitions(mtd_banks[idx],
part_banks[idx].mtd_part,
part_banks[idx].nums);
}
}
#else /* ! CONFIG_MTD_PARTITIONS */
printk(KERN_NOTICE "TQM834x flash: registering %d flash banks "
"at once\n", num_banks);
for(idx = 0 ; idx < num_banks ; idx++)
add_mtd_device(mtd_banks[idx]);
#endif /* CONFIG_MTD_PARTITIONS */
return 0;
error_mem:
for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
if (map_banks[idx] != NULL) {
if (map_banks[idx]->name != NULL) {
kfree(map_banks[idx]->name);
map_banks[idx]->name = NULL;
}
kfree(map_banks[idx]);
map_banks[idx] = NULL;
}
}
iounmap((void *)start_scan_addr);
return ret;
}
static void __exit cleanup_tqm834x_mtd(void)
{
unsigned int idx = 0;
for(idx = 0 ; idx < num_banks ; idx++) {
/* destroy mtd_info previously allocated */
if (mtd_banks[idx]) {
del_mtd_partitions(mtd_banks[idx]);
map_destroy(mtd_banks[idx]);
}
/* release map_info not used anymore */
kfree(map_banks[idx]->name);
kfree(map_banks[idx]);
}
if (start_scan_addr) {
iounmap((void *)start_scan_addr);
start_scan_addr = 0;
}
}
module_init(init_tqm834x_mtd);
module_exit(cleanup_tqm834x_mtd);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Wolfgang Denk <wd@denx.de>");
MODULE_DESCRIPTION("MTD map driver for TQM834x boards");
......@@ -24,10 +24,9 @@
#include <linux/kthread.h>
#include <asm/uaccess.h>
static LIST_HEAD(blktrans_majors);
#include "mtdcore.h"
extern struct mutex mtd_table_mutex;
extern struct mtd_info *mtd_table[];
static LIST_HEAD(blktrans_majors);
struct mtd_blkcore_priv {
struct task_struct *thread;
......@@ -202,7 +201,7 @@ static int blktrans_ioctl(struct inode *inode, struct file *file,
}
}
struct block_device_operations mtd_blktrans_ops = {
static struct block_device_operations mtd_blktrans_ops = {
.owner = THIS_MODULE,
.open = blktrans_open,
.release = blktrans_release,
......
......@@ -136,7 +136,8 @@ static int mtd_close(struct inode *inode, struct file *file)
DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
if (mtd->sync)
/* Only sync if opened RW */
if ((file->f_mode & 2) && mtd->sync)
mtd->sync(mtd);
put_mtd_device(mtd);
......
......@@ -178,7 +178,7 @@ concat_writev(struct mtd_info *mtd, const struct kvec *vecs,
/* Check alignment */
if (mtd->writesize > 1) {
loff_t __to = to;
uint64_t __to = to;
if (do_div(__to, mtd->writesize) || (total_len % mtd->writesize))
return -EINVAL;
}
......
......@@ -22,6 +22,8 @@
#include <linux/mtd/mtd.h>
#include "mtdcore.h"
/* These are exported solely for the purpose of mtd_blkdevs.c. You
should not use them for _anything_ else */
DEFINE_MUTEX(mtd_table_mutex);
......
/* linux/drivers/mtd/mtdcore.h
*
* Header file for driver private mtdcore exports
*
*/
/* These are exported solely for the purpose of mtd_blkdevs.c. You
should not use them for _anything_ else */
extern struct mutex mtd_table_mutex;
extern struct mtd_info *mtd_table[MAX_MTD_DEVICES];
/*
* MTD Oops/Panic logger
*
* Copyright (C) 2007 Nokia Corporation. All rights reserved.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/console.h>
#include <linux/vmalloc.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/mtd/mtd.h>
#define OOPS_PAGE_SIZE 4096
static struct mtdoops_context {
int mtd_index;
struct work_struct work;
struct mtd_info *mtd;
int oops_pages;
int nextpage;
int nextcount;
void *oops_buf;
int ready;
int writecount;
} oops_cxt;
static void mtdoops_erase_callback(struct erase_info *done)
{
wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
wake_up(wait_q);
}
static int mtdoops_erase_block(struct mtd_info *mtd, int offset)
{
struct erase_info erase;
DECLARE_WAITQUEUE(wait, current);
wait_queue_head_t wait_q;
int ret;
init_waitqueue_head(&wait_q);
erase.mtd = mtd;
erase.callback = mtdoops_erase_callback;
erase.addr = offset;
if (mtd->erasesize < OOPS_PAGE_SIZE)
erase.len = OOPS_PAGE_SIZE;
else
erase.len = mtd->erasesize;
erase.priv = (u_long)&wait_q;
set_current_state(TASK_INTERRUPTIBLE);
add_wait_queue(&wait_q, &wait);
ret = mtd->erase(mtd, &erase);
if (ret) {
set_current_state(TASK_RUNNING);
remove_wait_queue(&wait_q, &wait);
printk (KERN_WARNING "mtdoops: erase of region [0x%x, 0x%x] "
"on \"%s\" failed\n",
erase.addr, erase.len, mtd->name);
return ret;
}
schedule(); /* Wait for erase to finish. */
remove_wait_queue(&wait_q, &wait);
return 0;
}
static int mtdoops_inc_counter(struct mtdoops_context *cxt)
{
struct mtd_info *mtd = cxt->mtd;
size_t retlen;
u32 count;
int ret;
cxt->nextpage++;
if (cxt->nextpage > cxt->oops_pages)
cxt->nextpage = 0;
cxt->nextcount++;
if (cxt->nextcount == 0xffffffff)
cxt->nextcount = 0;
ret = mtd->read(mtd, cxt->nextpage * OOPS_PAGE_SIZE, 4,
&retlen, (u_char *) &count);
if ((retlen != 4) || (ret < 0)) {
printk(KERN_ERR "mtdoops: Read failure at %d (%td of 4 read)"
", err %d.\n", cxt->nextpage * OOPS_PAGE_SIZE,
retlen, ret);
return 1;
}
/* See if we need to erase the next block */
if (count != 0xffffffff)
return 1;
printk(KERN_DEBUG "mtdoops: Ready %d, %d (no erase)\n",
cxt->nextpage, cxt->nextcount);
cxt->ready = 1;
return 0;
}
static void mtdoops_prepare(struct mtdoops_context *cxt)
{
struct mtd_info *mtd = cxt->mtd;
int i = 0, j, ret, mod;
/* We were unregistered */
if (!mtd)
return;
mod = (cxt->nextpage * OOPS_PAGE_SIZE) % mtd->erasesize;
if (mod != 0) {
cxt->nextpage = cxt->nextpage + ((mtd->erasesize - mod) / OOPS_PAGE_SIZE);
if (cxt->nextpage > cxt->oops_pages)
cxt->nextpage = 0;
}
while (mtd->block_isbad &&
mtd->block_isbad(mtd, cxt->nextpage * OOPS_PAGE_SIZE)) {
badblock:
printk(KERN_WARNING "mtdoops: Bad block at %08x\n",
cxt->nextpage * OOPS_PAGE_SIZE);
i++;
cxt->nextpage = cxt->nextpage + (mtd->erasesize / OOPS_PAGE_SIZE);
if (cxt->nextpage > cxt->oops_pages)
cxt->nextpage = 0;
if (i == (cxt->oops_pages / (mtd->erasesize / OOPS_PAGE_SIZE))) {
printk(KERN_ERR "mtdoops: All blocks bad!\n");
return;
}
}
for (j = 0, ret = -1; (j < 3) && (ret < 0); j++)
ret = mtdoops_erase_block(mtd, cxt->nextpage * OOPS_PAGE_SIZE);
if (ret < 0) {
if (mtd->block_markbad)
mtd->block_markbad(mtd, cxt->nextpage * OOPS_PAGE_SIZE);
goto badblock;
}
printk(KERN_DEBUG "mtdoops: Ready %d, %d \n", cxt->nextpage, cxt->nextcount);
cxt->ready = 1;
}
static void mtdoops_workfunc(struct work_struct *work)
{
struct mtdoops_context *cxt =
container_of(work, struct mtdoops_context, work);
mtdoops_prepare(cxt);
}
static int find_next_position(struct mtdoops_context *cxt)
{
struct mtd_info *mtd = cxt->mtd;
int page, maxpos = 0;
u32 count, maxcount = 0xffffffff;
size_t retlen;
for (page = 0; page < cxt->oops_pages; page++) {
mtd->read(mtd, page * OOPS_PAGE_SIZE, 4, &retlen, (u_char *) &count);
if (count == 0xffffffff)
continue;
if (maxcount == 0xffffffff) {
maxcount = count;
maxpos = page;
} else if ((count < 0x40000000) && (maxcount > 0xc0000000)) {
maxcount = count;
maxpos = page;
} else if ((count > maxcount) && (count < 0xc0000000)) {
maxcount = count;
maxpos = page;
} else if ((count > maxcount) && (count > 0xc0000000)
&& (maxcount > 0x80000000)) {
maxcount = count;
maxpos = page;
}
}
if (maxcount == 0xffffffff) {
cxt->nextpage = 0;
cxt->nextcount = 1;
cxt->ready = 1;
printk(KERN_DEBUG "mtdoops: Ready %d, %d (first init)\n",
cxt->nextpage, cxt->nextcount);
return 0;
}
cxt->nextpage = maxpos;
cxt->nextcount = maxcount;
return mtdoops_inc_counter(cxt);
}
static void mtdoops_notify_add(struct mtd_info *mtd)
{
struct mtdoops_context *cxt = &oops_cxt;
int ret;
if ((mtd->index != cxt->mtd_index) || cxt->mtd_index < 0)
return;
if (mtd->size < (mtd->erasesize * 2)) {
printk(KERN_ERR "MTD partition %d not big enough for mtdoops\n",
mtd->index);
return;
}
cxt->mtd = mtd;
cxt->oops_pages = mtd->size / OOPS_PAGE_SIZE;
ret = find_next_position(cxt);
if (ret == 1)
mtdoops_prepare(cxt);
printk(KERN_DEBUG "mtdoops: Attached to MTD device %d\n", mtd->index);
}
static void mtdoops_notify_remove(struct mtd_info *mtd)
{
struct mtdoops_context *cxt = &oops_cxt;
if ((mtd->index != cxt->mtd_index) || cxt->mtd_index < 0)
return;
cxt->mtd = NULL;
flush_scheduled_work();
}
static void mtdoops_console_sync(void)
{
struct mtdoops_context *cxt = &oops_cxt;
struct mtd_info *mtd = cxt->mtd;
size_t retlen;
int ret;
if (!cxt->ready || !mtd)
return;
if (cxt->writecount == 0)
return;
if (cxt->writecount < OOPS_PAGE_SIZE)
memset(cxt->oops_buf + cxt->writecount, 0xff,
OOPS_PAGE_SIZE - cxt->writecount);
ret = mtd->write(mtd, cxt->nextpage * OOPS_PAGE_SIZE,
OOPS_PAGE_SIZE, &retlen, cxt->oops_buf);
cxt->ready = 0;
cxt->writecount = 0;
if ((retlen != OOPS_PAGE_SIZE) || (ret < 0))
printk(KERN_ERR "mtdoops: Write failure at %d (%td of %d written), err %d.\n",
cxt->nextpage * OOPS_PAGE_SIZE, retlen, OOPS_PAGE_SIZE, ret);
ret = mtdoops_inc_counter(cxt);
if (ret == 1)
schedule_work(&cxt->work);
}
static void
mtdoops_console_write(struct console *co, const char *s, unsigned int count)
{
struct mtdoops_context *cxt = co->data;
struct mtd_info *mtd = cxt->mtd;
int i;
if (!oops_in_progress) {
mtdoops_console_sync();
return;
}
if (!cxt->ready || !mtd)
return;
if (cxt->writecount == 0) {
u32 *stamp = cxt->oops_buf;
*stamp = cxt->nextcount;
cxt->writecount = 4;
}
if ((count + cxt->writecount) > OOPS_PAGE_SIZE)
count = OOPS_PAGE_SIZE - cxt->writecount;
for (i = 0; i < count; i++, s++)
*((char *)(cxt->oops_buf) + cxt->writecount + i) = *s;
cxt->writecount = cxt->writecount + count;
}
static int __init mtdoops_console_setup(struct console *co, char *options)
{
struct mtdoops_context *cxt = co->data;
if (cxt->mtd_index != -1)
return -EBUSY;
if (co->index == -1)
return -EINVAL;
cxt->mtd_index = co->index;
return 0;
}
static struct mtd_notifier mtdoops_notifier = {
.add = mtdoops_notify_add,
.remove = mtdoops_notify_remove,
};
static struct console mtdoops_console = {
.name = "ttyMTD",
.write = mtdoops_console_write,
.setup = mtdoops_console_setup,
.unblank = mtdoops_console_sync,
.flags = CON_PRINTBUFFER,
.index = -1,
.data = &oops_cxt,
};
static int __init mtdoops_console_init(void)
{
struct mtdoops_context *cxt = &oops_cxt;
cxt->mtd_index = -1;
cxt->oops_buf = vmalloc(OOPS_PAGE_SIZE);
if (!cxt->oops_buf) {
printk(KERN_ERR "Failed to allocate oops buffer workspace\n");
return -ENOMEM;
}
INIT_WORK(&cxt->work, mtdoops_workfunc);
register_console(&mtdoops_console);
register_mtd_user(&mtdoops_notifier);
return 0;
}
static void __exit mtdoops_console_exit(void)
{
struct mtdoops_context *cxt = &oops_cxt;
unregister_mtd_user(&mtdoops_notifier);
unregister_console(&mtdoops_console);
vfree(cxt->oops_buf);
}
subsys_initcall(mtdoops_console_init);
module_exit(mtdoops_console_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
MODULE_DESCRIPTION("MTD Oops/Panic console logger/driver");
......@@ -91,6 +91,25 @@ config MTD_NAND_AU1550
This enables the driver for the NAND flash controller on the
AMD/Alchemy 1550 SOC.
config MTD_NAND_BF5XX
tristate "Blackfin on-chip NAND Flash Controller driver"
depends on BF54x && MTD_NAND
help
This enables the Blackfin on-chip NAND flash controller
No board specific support is done by this driver, each board
must advertise a platform_device for the driver to attach.
This driver can also be built as a module. If so, the module
will be called bf5xx-nand.
config MTD_NAND_BF5XX_HWECC
bool "BF5XX NAND Hardware ECC"
depends on MTD_NAND_BF5XX
help
Enable the use of the BF5XX's internal ECC generator when
using NAND.
config MTD_NAND_RTC_FROM4
tristate "Renesas Flash ROM 4-slot interface board (FROM_BOARD4)"
depends on SH_SOLUTION_ENGINE
......@@ -134,10 +153,10 @@ config MTD_NAND_S3C2410_HWECC
config MTD_NAND_NDFC
tristate "NDFC NanD Flash Controller"
depends on 44x
depends on 4xx && !PPC_MERGE
select MTD_NAND_ECC_SMC
help
NDFC Nand Flash Controllers are integrated in EP44x SoCs
NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
config MTD_NAND_S3C2410_CLKSTOP
bool "S3C2410 NAND IDLE clock stop"
......@@ -237,7 +256,7 @@ config MTD_NAND_CAFE
select REED_SOLOMON
select REED_SOLOMON_DEC16
help
Use NAND flash attached to the CAFÉ chip designed for the $100
Use NAND flash attached to the CAFÉ chip designed for the OLPC
laptop.
config MTD_NAND_CS553X
......@@ -280,5 +299,11 @@ config MTD_NAND_PLATFORM
devices. You will need to provide platform-specific functions
via platform_data.
config MTD_ALAUDA
tristate "MTD driver for Olympus MAUSB-10 and Fijufilm DPC-R1"
depends on MTD_NAND && USB
help
These two (and possibly other) Alauda-based cardreaders for
SmartMedia and xD allow raw flash access.
endif # MTD_NAND
......@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_NAND_TOTO) += toto.o
obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
obj-$(CONFIG_MTD_NAND_EDB7312) += edb7312.o
obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o
obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
obj-$(CONFIG_MTD_NAND_S3C2410) += s3c2410.o
obj-$(CONFIG_MTD_NAND_DISKONCHIP) += diskonchip.o
......@@ -27,5 +28,6 @@ obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o
obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o
obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o
obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o
obj-$(CONFIG_MTD_ALAUDA) += alauda.o
nand-objs := nand_base.o nand_bbt.o
This diff is collapsed.
This diff is collapsed.
......@@ -623,6 +623,11 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
uint32_t ctrl;
int err = 0;
/* Very old versions shared the same PCI ident for all three
functions on the chip. Verify the class too... */
if ((pdev->class >> 8) != PCI_CLASS_MEMORY_FLASH)
return -ENODEV;
err = pci_enable_device(pdev);
if (err)
return err;
......@@ -816,21 +821,57 @@ static void __devexit cafe_nand_remove(struct pci_dev *pdev)
}
static struct pci_device_id cafe_nand_tbl[] = {
{ 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MEMORY_FLASH << 8, 0xFFFF0 },
{ 0, }
{ 0x11ab, 0x4100, PCI_ANY_ID, PCI_ANY_ID },
{ }
};
MODULE_DEVICE_TABLE(pci, cafe_nand_tbl);
static int cafe_nand_resume(struct pci_dev *pdev)
{
uint32_t ctrl;
struct mtd_info *mtd = pci_get_drvdata(pdev);
struct cafe_priv *cafe = mtd->priv;
/* Start off by resetting the NAND controller completely */
cafe_writel(cafe, 1, NAND_RESET);
cafe_writel(cafe, 0, NAND_RESET);
cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK);
/* Restore timing configuration */
cafe_writel(cafe, timing[0], NAND_TIMING1);
cafe_writel(cafe, timing[1], NAND_TIMING2);
cafe_writel(cafe, timing[2], NAND_TIMING3);
/* Disable master reset, enable NAND clock */
ctrl = cafe_readl(cafe, GLOBAL_CTRL);
ctrl &= 0xffffeff0;
ctrl |= 0x00007000;
cafe_writel(cafe, ctrl | 0x05, GLOBAL_CTRL);
cafe_writel(cafe, ctrl | 0x0a, GLOBAL_CTRL);
cafe_writel(cafe, 0, NAND_DMA_CTRL);
cafe_writel(cafe, 0x7006, GLOBAL_CTRL);
cafe_writel(cafe, 0x700a, GLOBAL_CTRL);
/* Set up DMA address */
cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);
if (sizeof(cafe->dmaaddr) > 4)
/* Shift in two parts to shut the compiler up */
cafe_writel(cafe, (cafe->dmaaddr >> 16) >> 16, NAND_DMA_ADDR1);
else
cafe_writel(cafe, 0, NAND_DMA_ADDR1);
/* Enable NAND IRQ in global IRQ mask register */
cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK);
return 0;
}
static struct pci_driver cafe_nand_pci_driver = {
.name = "CAFÉ NAND",
.id_table = cafe_nand_tbl,
.probe = cafe_nand_probe,
.remove = __devexit_p(cafe_nand_remove),
#ifdef CONFIG_PMx
.suspend = cafe_nand_suspend,
.resume = cafe_nand_resume,
#endif
};
static int cafe_nand_init(void)
......
......@@ -56,8 +56,6 @@ static unsigned long __initdata doc_locations[] = {
#endif /* CONFIG_MTD_DOCPROBE_HIGH */
#elif defined(__PPC__)
0xe4000000,
#elif defined(CONFIG_MOMENCO_OCELOT_G)
0xff000000,
#else
#warning Unknown architecture for DiskOnChip. No default probe locations defined
#endif
......
......@@ -27,7 +27,6 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
......
......@@ -7,7 +7,7 @@
* Basic support for AG-AND chips is provided.
*
* Additional technical information is available on
* http://www.linux-mtd.infradead.org/tech/nand.html
* http://www.linux-mtd.infradead.org/doc/nand.html
*
* Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
* 2002-2006 Thomas Gleixner (tglx@linutronix.de)
......@@ -2069,13 +2069,14 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
erase_exit:
ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO;
/* Do call back function */
if (!ret)
mtd_erase_callback(instr);
/* Deselect and wake up anyone waiting on the device */
nand_release_device(mtd);
/* Do call back function */
if (!ret)
mtd_erase_callback(instr);
/*
* If BBT requires refresh and erase was successful, rewrite any
* selected bad block tables
......
......@@ -141,6 +141,7 @@ struct nand_manufacturers nand_manuf_ids[] = {
{NAND_MFR_STMICRO, "ST Micro"},
{NAND_MFR_HYNIX, "Hynix"},
{NAND_MFR_MICRON, "Micron"},
{NAND_MFR_AMD, "AMD"},
{0x0, "Unknown"}
};
......
......@@ -1272,7 +1272,13 @@ static int prog_page(struct nandsim *ns, int num)
mypage = NS_GET_PAGE(ns);
if (mypage->byte == NULL) {
NS_DBG("prog_page: allocating page %d\n", ns->regs.row);
mypage->byte = kmalloc(ns->geom.pgszoob, GFP_KERNEL);
/*
* We allocate memory with GFP_NOFS because a flash FS may
* utilize this. If it is holding an FS lock, then gets here,
* then kmalloc runs writeback which goes to the FS again
* and deadlocks. This was seen in practice.
*/
mypage->byte = kmalloc(ns->geom.pgszoob, GFP_NOFS);
if (mypage->byte == NULL) {
NS_ERR("prog_page: error allocating memory for page %d\n", ns->regs.row);
return -1;
......
......@@ -24,7 +24,11 @@
#include <linux/platform_device.h>
#include <asm/io.h>
#ifdef CONFIG_40x
#include <asm/ibm405.h>
#else
#include <asm/ibm44x.h>
#endif
struct ndfc_nand_mtd {
struct mtd_info mtd;
......@@ -230,7 +234,11 @@ static int ndfc_nand_probe(struct platform_device *pdev)
struct ndfc_controller *ndfc = &ndfc_ctrl;
unsigned long long phys = settings->ndfc_erpn | res->start;
#ifndef CONFIG_PHYS_64BIT
ndfc->ndfcbase = ioremap((phys_addr_t)phys, res->end - res->start + 1);
#else
ndfc->ndfcbase = ioremap64(phys, res->end - res->start + 1);
#endif
if (!ndfc->ndfcbase) {
printk(KERN_ERR "NDFC: ioremap failed\n");
return -EIO;
......
......@@ -60,8 +60,8 @@
#include <asm/io.h>
#include <asm/arch/regs-nand.h>
#include <asm/arch/nand.h>
#include <asm/plat-s3c/regs-nand.h>
#include <asm/plat-s3c/nand.h>
#ifdef CONFIG_MTD_NAND_S3C2410_HWECC
static int hardware_ecc = 1;
......
......@@ -40,4 +40,27 @@ config MTD_ONENAND_OTP
OTP block is fully-guaranteed to be a valid block.
config MTD_ONENAND_2X_PROGRAM
bool "OneNAND 2X program support"
help
The 2X Program is an extension of Program Operation.
Since the device is equipped with two DataRAMs, and two-plane NAND
Flash memory array, these two component enables simultaneous program
of 4KiB. Plane1 has only even blocks such as block0, block2, block4
while Plane2 has only odd blocks such as block1, block3, block5.
So MTD regards it as 4KiB page size and 256KiB block size
Now the following chips support it. (KFXXX16Q2M)
Demux: KFG2G16Q2M, KFH4G16Q2M, KFW8G16Q2M,
Mux: KFM2G16Q2M, KFN4G16Q2M,
And more recent chips
config MTD_ONENAND_SIM
tristate "OneNAND simulator support"
depends on MTD_PARTITIONS
help
The simulator may simulate various OneNAND flash chips for the
OneNAND MTD layer.
endif # MTD_ONENAND
......@@ -8,4 +8,7 @@ obj-$(CONFIG_MTD_ONENAND) += onenand.o
# Board specific.
obj-$(CONFIG_MTD_ONENAND_GENERIC) += generic.o
# Simulator
obj-$(CONFIG_MTD_ONENAND_SIM) += onenand_sim.o
onenand-objs = onenand_base.o onenand_bbt.o
This diff is collapsed.
This diff is collapsed.
......@@ -779,10 +779,8 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
else {
if (!mtd->erasesize) {
printk(KERN_WARNING PREFIX "please provide block_size");
kfree(part);
return;
}
else
goto out;
} else
part->block_size = mtd->erasesize;
}
......@@ -804,7 +802,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
if (!add_mtd_blktrans_dev((void*)part))
return;
}
out:
kfree(part);
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -17,4 +17,5 @@ jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL) += acl.o
jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o
jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o
jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o
jffs2-$(CONFIG_JFFS2_LZO) += compr_lzo.o
jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o
This diff is collapsed.
This diff is collapsed.
......@@ -23,8 +23,8 @@ static int jffs2_garbage_collect_thread(void *);
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
{
spin_lock(&c->erase_completion_lock);
if (c->gc_task && jffs2_thread_should_wake(c))
send_sig(SIGHUP, c->gc_task, 1);
if (c->gc_task && jffs2_thread_should_wake(c))
send_sig(SIGHUP, c->gc_task, 1);
spin_unlock(&c->erase_completion_lock);
}
......
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.
......@@ -55,6 +55,7 @@
#define CH_SPORT3_RX 20
#define CH_SPORT3_TX 21
#define CH_SDH 22
#define CH_NFC 22
#define CH_SPI2 23
#define CH_MEM_STREAM0_DEST 24
......
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