You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (120 commits) [MTD] Fix mtdoops.c compilation [MTD] [NOR] fix startup lock when using multiple nor flash chips [MTD] [DOC200x] eccbuf is statically defined and always evaluate to true [MTD] Fix maps/physmap.c compilation with CONFIG_PM [MTD] onenand: Add panic_write function to the onenand driver [MTD] mtdoops: Use the panic_write function when present [MTD] Add mtd panic_write function pointer [MTD] [NAND] Freescale enhanced Local Bus Controller FCM NAND support. [MTD] physmap.c: Add support for multiple resources [MTD] [NAND] Fix misparenthesization introduced by commit 78b65179... [MTD] [NAND] Fix Blackfin NFC ECC calculating bug with page size 512 bytes [MTD] [NAND] Remove wrong operation in PM function of the BF54x NFC driver [MTD] [NAND] Remove unused variable in plat_nand_remove [MTD] Unlocking all Intel flash that is locked on power up. [MTD] [NAND] at91_nand: Make mtdparts option can override board info [MTD] mtdoops: Various minor cleanups [MTD] mtdoops: Ensure sequential write to the buffer [MTD] mtdoops: Perform write operations in a workqueue [MTD] mtdoops: Add further error return code checking [MTD] [NOR] Test devtype, not definition in flash_probe(), drivers/mtd/devices/lart.c ...
This commit is contained in:
@@ -150,6 +150,14 @@ config MTD_AFS_PARTS
|
|||||||
for your particular device. It won't happen automatically. The
|
for your particular device. It won't happen automatically. The
|
||||||
'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
|
'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
|
||||||
|
|
||||||
|
config MTD_OF_PARTS
|
||||||
|
tristate "Flash partition map based on OF description"
|
||||||
|
depends on PPC_OF && MTD_PARTITIONS
|
||||||
|
help
|
||||||
|
This provides a partition parsing function which derives
|
||||||
|
the partition map from the children of the flash node,
|
||||||
|
as described in Documentation/powerpc/booting-without-of.txt.
|
||||||
|
|
||||||
comment "User Modules And Translation Layers"
|
comment "User Modules And Translation Layers"
|
||||||
|
|
||||||
config MTD_CHAR
|
config MTD_CHAR
|
||||||
@@ -286,6 +294,9 @@ config MTD_OOPS
|
|||||||
buffer in a flash partition where it can be read back at some
|
buffer in a flash partition where it can be read back at some
|
||||||
later point.
|
later point.
|
||||||
|
|
||||||
|
To use, add console=ttyMTDx to the kernel command line,
|
||||||
|
where x is the MTD device number to use.
|
||||||
|
|
||||||
source "drivers/mtd/chips/Kconfig"
|
source "drivers/mtd/chips/Kconfig"
|
||||||
|
|
||||||
source "drivers/mtd/maps/Kconfig"
|
source "drivers/mtd/maps/Kconfig"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
|
|||||||
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
||||||
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
||||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||||
|
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.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
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
#define I82802AC 0x00ac
|
#define I82802AC 0x00ac
|
||||||
#define MANUFACTURER_ST 0x0020
|
#define MANUFACTURER_ST 0x0020
|
||||||
#define M50LPW080 0x002F
|
#define M50LPW080 0x002F
|
||||||
|
#define AT49BV640D 0x02de
|
||||||
|
|
||||||
static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
static int cfi_intelext_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
||||||
static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
static int cfi_intelext_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
||||||
@@ -157,6 +158,47 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Atmel chips don't use the same PRI format as Intel chips */
|
||||||
|
static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
|
||||||
|
{
|
||||||
|
struct map_info *map = mtd->priv;
|
||||||
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
|
struct cfi_pri_intelext *extp = cfi->cmdset_priv;
|
||||||
|
struct cfi_pri_atmel atmel_pri;
|
||||||
|
uint32_t features = 0;
|
||||||
|
|
||||||
|
/* Reverse byteswapping */
|
||||||
|
extp->FeatureSupport = cpu_to_le32(extp->FeatureSupport);
|
||||||
|
extp->BlkStatusRegMask = cpu_to_le16(extp->BlkStatusRegMask);
|
||||||
|
extp->ProtRegAddr = cpu_to_le16(extp->ProtRegAddr);
|
||||||
|
|
||||||
|
memcpy(&atmel_pri, extp, sizeof(atmel_pri));
|
||||||
|
memset((char *)extp + 5, 0, sizeof(*extp) - 5);
|
||||||
|
|
||||||
|
printk(KERN_ERR "atmel Features: %02x\n", atmel_pri.Features);
|
||||||
|
|
||||||
|
if (atmel_pri.Features & 0x01) /* chip erase supported */
|
||||||
|
features |= (1<<0);
|
||||||
|
if (atmel_pri.Features & 0x02) /* erase suspend supported */
|
||||||
|
features |= (1<<1);
|
||||||
|
if (atmel_pri.Features & 0x04) /* program suspend supported */
|
||||||
|
features |= (1<<2);
|
||||||
|
if (atmel_pri.Features & 0x08) /* simultaneous operations supported */
|
||||||
|
features |= (1<<9);
|
||||||
|
if (atmel_pri.Features & 0x20) /* page mode read supported */
|
||||||
|
features |= (1<<7);
|
||||||
|
if (atmel_pri.Features & 0x40) /* queued erase supported */
|
||||||
|
features |= (1<<4);
|
||||||
|
if (atmel_pri.Features & 0x80) /* Protection bits supported */
|
||||||
|
features |= (1<<6);
|
||||||
|
|
||||||
|
extp->FeatureSupport = features;
|
||||||
|
|
||||||
|
/* burst write mode not supported */
|
||||||
|
cfi->cfiq->BufWriteTimeoutTyp = 0;
|
||||||
|
cfi->cfiq->BufWriteTimeoutMax = 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
|
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
|
||||||
/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
|
/* Some Intel Strata Flash prior to FPO revision C has bugs in this area */
|
||||||
static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
|
static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
|
||||||
@@ -227,13 +269,20 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
|
|||||||
/*
|
/*
|
||||||
* Some chips power-up with all sectors locked by default.
|
* Some chips power-up with all sectors locked by default.
|
||||||
*/
|
*/
|
||||||
static void fixup_use_powerup_lock(struct mtd_info *mtd, void *param)
|
static void fixup_unlock_powerup_lock(struct mtd_info *mtd, void *param)
|
||||||
{
|
{
|
||||||
|
struct map_info *map = mtd->priv;
|
||||||
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
|
struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
|
||||||
|
|
||||||
|
if (cfip->FeatureSupport&32) {
|
||||||
printk(KERN_INFO "Using auto-unlock on power-up/resume\n" );
|
printk(KERN_INFO "Using auto-unlock on power-up/resume\n" );
|
||||||
mtd->flags |= MTD_STUPID_LOCK;
|
mtd->flags |= MTD_POWERUP_LOCK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cfi_fixup cfi_fixup_table[] = {
|
static struct cfi_fixup cfi_fixup_table[] = {
|
||||||
|
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
|
||||||
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
|
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
|
||||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
|
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL },
|
||||||
#endif
|
#endif
|
||||||
@@ -245,7 +294,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
|
|||||||
#endif
|
#endif
|
||||||
{ CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
|
{ CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
|
||||||
{ CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
|
{ CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
|
||||||
{ MANUFACTURER_INTEL, 0x891c, fixup_use_powerup_lock, NULL, },
|
{ MANUFACTURER_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock, NULL, },
|
||||||
{ 0, 0, NULL, NULL }
|
{ 0, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -277,7 +326,7 @@ read_pri_intelext(struct map_info *map, __u16 adr)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (extp->MajorVersion != '1' ||
|
if (extp->MajorVersion != '1' ||
|
||||||
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
|
(extp->MinorVersion < '0' || extp->MinorVersion > '5')) {
|
||||||
printk(KERN_ERR " Unknown Intel/Sharp Extended Query "
|
printk(KERN_ERR " Unknown Intel/Sharp Extended Query "
|
||||||
"version %c.%c.\n", extp->MajorVersion,
|
"version %c.%c.\n", extp->MajorVersion,
|
||||||
extp->MinorVersion);
|
extp->MinorVersion);
|
||||||
@@ -752,6 +801,7 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
|
|||||||
static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
|
static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
DECLARE_WAITQUEUE(wait, current);
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING
|
if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING
|
||||||
@@ -808,6 +858,20 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
|
|||||||
spin_unlock(contender->mutex);
|
spin_unlock(contender->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check if we already have suspended erase
|
||||||
|
* on this chip. Sleep. */
|
||||||
|
if (mode == FL_ERASING && shared->erasing
|
||||||
|
&& shared->erasing->oldstate == FL_ERASING) {
|
||||||
|
spin_unlock(&shared->lock);
|
||||||
|
set_current_state(TASK_UNINTERRUPTIBLE);
|
||||||
|
add_wait_queue(&chip->wq, &wait);
|
||||||
|
spin_unlock(chip->mutex);
|
||||||
|
schedule();
|
||||||
|
remove_wait_queue(&chip->wq, &wait);
|
||||||
|
spin_lock(chip->mutex);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
/* We now own it */
|
/* We now own it */
|
||||||
shared->writing = chip;
|
shared->writing = chip;
|
||||||
if (mode == FL_ERASING)
|
if (mode == FL_ERASING)
|
||||||
@@ -2294,7 +2358,7 @@ static int cfi_intelext_suspend(struct mtd_info *mtd)
|
|||||||
struct flchip *chip;
|
struct flchip *chip;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if ((mtd->flags & MTD_STUPID_LOCK)
|
if ((mtd->flags & MTD_POWERUP_LOCK)
|
||||||
&& extp && (extp->FeatureSupport & (1 << 5)))
|
&& extp && (extp->FeatureSupport & (1 << 5)))
|
||||||
cfi_intelext_save_locks(mtd);
|
cfi_intelext_save_locks(mtd);
|
||||||
|
|
||||||
@@ -2405,7 +2469,7 @@ static void cfi_intelext_resume(struct mtd_info *mtd)
|
|||||||
spin_unlock(chip->mutex);
|
spin_unlock(chip->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mtd->flags & MTD_STUPID_LOCK)
|
if ((mtd->flags & MTD_POWERUP_LOCK)
|
||||||
&& extp && (extp->FeatureSupport & (1 << 5)))
|
&& extp && (extp->FeatureSupport & (1 << 5)))
|
||||||
cfi_intelext_restore_locks(mtd);
|
cfi_intelext_restore_locks(mtd);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,6 +185,10 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
|
|||||||
extp->TopBottom = 2;
|
extp->TopBottom = 2;
|
||||||
else
|
else
|
||||||
extp->TopBottom = 3;
|
extp->TopBottom = 3;
|
||||||
|
|
||||||
|
/* burst write mode not supported */
|
||||||
|
cfi->cfiq->BufWriteTimeoutTyp = 0;
|
||||||
|
cfi->cfiq->BufWriteTimeoutMax = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fixup_use_secsi(struct mtd_info *mtd, void *param)
|
static void fixup_use_secsi(struct mtd_info *mtd, void *param)
|
||||||
@@ -213,10 +217,11 @@ static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
|
|||||||
{
|
{
|
||||||
mtd->lock = cfi_atmel_lock;
|
mtd->lock = cfi_atmel_lock;
|
||||||
mtd->unlock = cfi_atmel_unlock;
|
mtd->unlock = cfi_atmel_unlock;
|
||||||
mtd->flags |= MTD_STUPID_LOCK;
|
mtd->flags |= MTD_POWERUP_LOCK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cfi_fixup cfi_fixup_table[] = {
|
static struct cfi_fixup cfi_fixup_table[] = {
|
||||||
|
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
|
||||||
#ifdef AMD_BOOTLOC_BUG
|
#ifdef AMD_BOOTLOC_BUG
|
||||||
{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
|
{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
|
||||||
#endif
|
#endif
|
||||||
@@ -229,7 +234,6 @@ static struct cfi_fixup cfi_fixup_table[] = {
|
|||||||
#if !FORCE_WORD_WRITE
|
#if !FORCE_WORD_WRITE
|
||||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
|
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, },
|
||||||
#endif
|
#endif
|
||||||
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
|
|
||||||
{ 0, 0, NULL, NULL }
|
{ 0, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
static struct cfi_fixup jedec_fixup_table[] = {
|
static struct cfi_fixup jedec_fixup_table[] = {
|
||||||
@@ -338,10 +342,12 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
|||||||
/* Modify the unlock address if we are in compatibility mode */
|
/* Modify the unlock address if we are in compatibility mode */
|
||||||
if ( /* x16 in x8 mode */
|
if ( /* x16 in x8 mode */
|
||||||
((cfi->device_type == CFI_DEVICETYPE_X8) &&
|
((cfi->device_type == CFI_DEVICETYPE_X8) &&
|
||||||
(cfi->cfiq->InterfaceDesc == 2)) ||
|
(cfi->cfiq->InterfaceDesc ==
|
||||||
|
CFI_INTERFACE_X8_BY_X16_ASYNC)) ||
|
||||||
/* x32 in x16 mode */
|
/* x32 in x16 mode */
|
||||||
((cfi->device_type == CFI_DEVICETYPE_X16) &&
|
((cfi->device_type == CFI_DEVICETYPE_X16) &&
|
||||||
(cfi->cfiq->InterfaceDesc == 4)))
|
(cfi->cfiq->InterfaceDesc ==
|
||||||
|
CFI_INTERFACE_X16_BY_X32_ASYNC)))
|
||||||
{
|
{
|
||||||
cfi->addr_unlock1 = 0xaaa;
|
cfi->addr_unlock1 = 0xaaa;
|
||||||
cfi->addr_unlock2 = 0x555;
|
cfi->addr_unlock2 = 0x555;
|
||||||
|
|||||||
@@ -370,27 +370,27 @@ static void print_cfi_ident(struct cfi_ident *cfip)
|
|||||||
printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
|
printk("Device size: 0x%X bytes (%d MiB)\n", 1 << cfip->DevSize, 1<< (cfip->DevSize - 20));
|
||||||
printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc);
|
printk("Flash Device Interface description: 0x%4.4X\n", cfip->InterfaceDesc);
|
||||||
switch(cfip->InterfaceDesc) {
|
switch(cfip->InterfaceDesc) {
|
||||||
case 0:
|
case CFI_INTERFACE_X8_ASYNC:
|
||||||
printk(" - x8-only asynchronous interface\n");
|
printk(" - x8-only asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case CFI_INTERFACE_X16_ASYNC:
|
||||||
printk(" - x16-only asynchronous interface\n");
|
printk(" - x16-only asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case CFI_INTERFACE_X8_BY_X16_ASYNC:
|
||||||
printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n");
|
printk(" - supports x8 and x16 via BYTE# with asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case CFI_INTERFACE_X32_ASYNC:
|
||||||
printk(" - x32-only asynchronous interface\n");
|
printk(" - x32-only asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case CFI_INTERFACE_X16_BY_X32_ASYNC:
|
||||||
printk(" - supports x16 and x32 via Word# with asynchronous interface\n");
|
printk(" - supports x16 and x32 via Word# with asynchronous interface\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 65535:
|
case CFI_INTERFACE_NOT_ALLOWED:
|
||||||
printk(" - Not Allowed / Reserved\n");
|
printk(" - Not Allowed / Reserved\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
|
|||||||
max_chips = 1;
|
max_chips = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapsize = (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG;
|
mapsize = sizeof(long) * ( (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG );
|
||||||
chip_map = kzalloc(mapsize, GFP_KERNEL);
|
chip_map = kzalloc(mapsize, GFP_KERNEL);
|
||||||
if (!chip_map) {
|
if (!chip_map) {
|
||||||
printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
|
printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
|
||||||
|
|||||||
+572
-756
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@
|
|||||||
*
|
*
|
||||||
* mtdparts=<mtddef>[;<mtddef]
|
* mtdparts=<mtddef>[;<mtddef]
|
||||||
* <mtddef> := <mtd-id>:<partdef>[,<partdef>]
|
* <mtddef> := <mtd-id>:<partdef>[,<partdef>]
|
||||||
* <partdef> := <size>[@offset][<name>][ro]
|
* <partdef> := <size>[@offset][<name>][ro][lk]
|
||||||
* <mtd-id> := unique name used in mapping driver/device (mtd->name)
|
* <mtd-id> := unique name used in mapping driver/device (mtd->name)
|
||||||
* <size> := standard linux memsize OR "-" to denote all remaining space
|
* <size> := standard linux memsize OR "-" to denote all remaining space
|
||||||
* <name> := '(' NAME ')'
|
* <name> := '(' NAME ')'
|
||||||
@@ -143,6 +143,13 @@ static struct mtd_partition * newpart(char *s,
|
|||||||
s += 2;
|
s += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* if lk is found do NOT unlock the MTD partition*/
|
||||||
|
if (strncmp(s, "lk", 2) == 0)
|
||||||
|
{
|
||||||
|
mask_flags |= MTD_POWERUP_LOCK;
|
||||||
|
s += 2;
|
||||||
|
}
|
||||||
|
|
||||||
/* test if more partitions are following */
|
/* test if more partitions are following */
|
||||||
if (*s == ',')
|
if (*s == ',')
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -632,7 +632,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|||||||
len = ((from | 0x1ff) + 1) - from;
|
len = ((from | 0x1ff) + 1) - from;
|
||||||
|
|
||||||
/* The ECC will not be calculated correctly if less than 512 is read */
|
/* The ECC will not be calculated correctly if less than 512 is read */
|
||||||
if (len != 0x200 && eccbuf)
|
if (len != 0x200)
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING
|
||||||
"ECC needs a full sector read (adr: %lx size %lx)\n",
|
"ECC needs a full sector read (adr: %lx size %lx)\n",
|
||||||
(long) from, (long) len);
|
(long) from, (long) len);
|
||||||
@@ -896,7 +896,7 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
/* Let the caller know we completed it */
|
/* Let the caller know we completed it */
|
||||||
*retlen += len;
|
*retlen += len;
|
||||||
|
|
||||||
if (eccbuf) {
|
{
|
||||||
unsigned char x[8];
|
unsigned char x[8];
|
||||||
size_t dummy;
|
size_t dummy;
|
||||||
int ret;
|
int ret;
|
||||||
|
|||||||
@@ -748,7 +748,7 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
WriteDOC(DoC_GetDataOffset(mtd, &fto), docptr, Mplus_FlashCmd);
|
WriteDOC(DoC_GetDataOffset(mtd, &fto), docptr, Mplus_FlashCmd);
|
||||||
|
|
||||||
/* On interleaved devices the flags for 2nd half 512 are before data */
|
/* On interleaved devices the flags for 2nd half 512 are before data */
|
||||||
if (eccbuf && before)
|
if (before)
|
||||||
fto -= 2;
|
fto -= 2;
|
||||||
|
|
||||||
/* issue the Serial Data In command to initial the Page Program process */
|
/* issue the Serial Data In command to initial the Page Program process */
|
||||||
|
|||||||
@@ -323,7 +323,7 @@ static int flash_probe (void)
|
|||||||
/* put the flash back into command mode */
|
/* put the flash back into command mode */
|
||||||
write32 (DATA_TO_FLASH (READ_ARRAY),0x00000000);
|
write32 (DATA_TO_FLASH (READ_ARRAY),0x00000000);
|
||||||
|
|
||||||
return (manufacturer == FLASH_MANUFACTURER && (devtype == FLASH_DEVICE_16mbit_TOP || FLASH_DEVICE_16mbit_BOTTOM));
|
return (manufacturer == FLASH_MANUFACTURER && (devtype == FLASH_DEVICE_16mbit_TOP || devtype == FLASH_DEVICE_16mbit_BOTTOM));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -420,7 +420,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||||||
status = dataflash_waitready(priv->spi);
|
status = dataflash_waitready(priv->spi);
|
||||||
|
|
||||||
/* Check result of the compare operation */
|
/* Check result of the compare operation */
|
||||||
if ((status & (1 << 6)) == 1) {
|
if (status & (1 << 6)) {
|
||||||
printk(KERN_ERR "%s: compare page %u, err %d\n",
|
printk(KERN_ERR "%s: compare page %u, err %d\n",
|
||||||
spi->dev.bus_id, pageaddr, status);
|
spi->dev.bus_id, pageaddr, status);
|
||||||
remaining = 0;
|
remaining = 0;
|
||||||
|
|||||||
@@ -110,13 +110,6 @@ config MTD_SUN_UFLASH
|
|||||||
Sun Microsystems boardsets. This driver will require CFI support
|
Sun Microsystems boardsets. This driver will require CFI support
|
||||||
in the kernel, so if you did not enable CFI previously, do that now.
|
in the kernel, so if you did not enable CFI previously, do that now.
|
||||||
|
|
||||||
config MTD_PNC2000
|
|
||||||
tristate "CFI Flash device mapped on Photron PNC-2000"
|
|
||||||
depends on X86 && MTD_CFI && MTD_PARTITIONS
|
|
||||||
help
|
|
||||||
PNC-2000 is the name of Network Camera product from PHOTRON
|
|
||||||
Ltd. in Japan. It uses CFI-compliant flash.
|
|
||||||
|
|
||||||
config MTD_SC520CDP
|
config MTD_SC520CDP
|
||||||
tristate "CFI Flash device mapped on AMD SC520 CDP"
|
tristate "CFI Flash device mapped on AMD SC520 CDP"
|
||||||
depends on X86 && MTD_CFI && MTD_CONCAT
|
depends on X86 && MTD_CFI && MTD_CONCAT
|
||||||
@@ -576,7 +569,7 @@ config MTD_BAST_MAXSIZE
|
|||||||
default "4"
|
default "4"
|
||||||
|
|
||||||
config MTD_SHARP_SL
|
config MTD_SHARP_SL
|
||||||
bool "ROM mapped on Sharp SL Series"
|
tristate "ROM mapped on Sharp SL Series"
|
||||||
depends on ARCH_PXA
|
depends on ARCH_PXA
|
||||||
help
|
help
|
||||||
This enables access to the flash chip on the Sharp SL Series of PDAs.
|
This enables access to the flash chip on the Sharp SL Series of PDAs.
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
|
|||||||
obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
|
obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
|
||||||
obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o
|
obj-$(CONFIG_MTD_PMC_MSP_EVM) += pmcmsp-flash.o
|
||||||
obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcmsp-ramroot.o
|
obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcmsp-ramroot.o
|
||||||
obj-$(CONFIG_MTD_PNC2000) += pnc2000.o
|
|
||||||
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
|
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
|
||||||
obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
|
obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
|
||||||
obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
|
obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
|
||||||
|
|||||||
+88
-40
@@ -20,11 +20,15 @@
|
|||||||
#include <linux/mtd/map.h>
|
#include <linux/mtd/map.h>
|
||||||
#include <linux/mtd/partitions.h>
|
#include <linux/mtd/partitions.h>
|
||||||
#include <linux/mtd/physmap.h>
|
#include <linux/mtd/physmap.h>
|
||||||
|
#include <linux/mtd/concat.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
#define MAX_RESOURCES 4
|
||||||
|
|
||||||
struct physmap_flash_info {
|
struct physmap_flash_info {
|
||||||
struct mtd_info *mtd;
|
struct mtd_info *mtd[MAX_RESOURCES];
|
||||||
struct map_info map;
|
struct mtd_info *cmtd;
|
||||||
|
struct map_info map[MAX_RESOURCES];
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
#ifdef CONFIG_MTD_PARTITIONS
|
#ifdef CONFIG_MTD_PARTITIONS
|
||||||
int nr_parts;
|
int nr_parts;
|
||||||
@@ -32,11 +36,11 @@ struct physmap_flash_info {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int physmap_flash_remove(struct platform_device *dev)
|
static int physmap_flash_remove(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
struct physmap_flash_info *info;
|
struct physmap_flash_info *info;
|
||||||
struct physmap_flash_data *physmap_data;
|
struct physmap_flash_data *physmap_data;
|
||||||
|
int i;
|
||||||
|
|
||||||
info = platform_get_drvdata(dev);
|
info = platform_get_drvdata(dev);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
@@ -45,24 +49,33 @@ static int physmap_flash_remove(struct platform_device *dev)
|
|||||||
|
|
||||||
physmap_data = dev->dev.platform_data;
|
physmap_data = dev->dev.platform_data;
|
||||||
|
|
||||||
if (info->mtd != NULL) {
|
#ifdef CONFIG_MTD_CONCAT
|
||||||
|
if (info->cmtd != info->mtd[0]) {
|
||||||
|
del_mtd_device(info->cmtd);
|
||||||
|
mtd_concat_destroy(info->cmtd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_RESOURCES; i++) {
|
||||||
|
if (info->mtd[i] != NULL) {
|
||||||
#ifdef CONFIG_MTD_PARTITIONS
|
#ifdef CONFIG_MTD_PARTITIONS
|
||||||
if (info->nr_parts) {
|
if (info->nr_parts) {
|
||||||
del_mtd_partitions(info->mtd);
|
del_mtd_partitions(info->mtd[i]);
|
||||||
kfree(info->parts);
|
kfree(info->parts);
|
||||||
} else if (physmap_data->nr_parts) {
|
} else if (physmap_data->nr_parts) {
|
||||||
del_mtd_partitions(info->mtd);
|
del_mtd_partitions(info->mtd[i]);
|
||||||
} else {
|
} else {
|
||||||
del_mtd_device(info->mtd);
|
del_mtd_device(info->mtd[i]);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
del_mtd_device(info->mtd);
|
del_mtd_device(info->mtd[i]);
|
||||||
#endif
|
#endif
|
||||||
map_destroy(info->mtd);
|
map_destroy(info->mtd[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->map.virt != NULL)
|
if (info->map[i].virt != NULL)
|
||||||
iounmap(info->map.virt);
|
iounmap(info->map[i].virt);
|
||||||
|
}
|
||||||
|
|
||||||
if (info->res != NULL) {
|
if (info->res != NULL) {
|
||||||
release_resource(info->res);
|
release_resource(info->res);
|
||||||
@@ -82,16 +95,14 @@ static int physmap_flash_probe(struct platform_device *dev)
|
|||||||
struct physmap_flash_data *physmap_data;
|
struct physmap_flash_data *physmap_data;
|
||||||
struct physmap_flash_info *info;
|
struct physmap_flash_info *info;
|
||||||
const char **probe_type;
|
const char **probe_type;
|
||||||
int err;
|
int err = 0;
|
||||||
|
int i;
|
||||||
|
int devices_found = 0;
|
||||||
|
|
||||||
physmap_data = dev->dev.platform_data;
|
physmap_data = dev->dev.platform_data;
|
||||||
if (physmap_data == NULL)
|
if (physmap_data == NULL)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
|
|
||||||
(unsigned long long)(dev->resource->end - dev->resource->start + 1),
|
|
||||||
(unsigned long long)dev->resource->start);
|
|
||||||
|
|
||||||
info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
|
info = kzalloc(sizeof(struct physmap_flash_info), GFP_KERNEL);
|
||||||
if (info == NULL) {
|
if (info == NULL) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
@@ -100,8 +111,13 @@ static int physmap_flash_probe(struct platform_device *dev)
|
|||||||
|
|
||||||
platform_set_drvdata(dev, info);
|
platform_set_drvdata(dev, info);
|
||||||
|
|
||||||
info->res = request_mem_region(dev->resource->start,
|
for (i = 0; i < dev->num_resources; i++) {
|
||||||
dev->resource->end - dev->resource->start + 1,
|
printk(KERN_NOTICE "physmap platform flash device: %.8llx at %.8llx\n",
|
||||||
|
(unsigned long long)(dev->resource[i].end - dev->resource[i].start + 1),
|
||||||
|
(unsigned long long)dev->resource[i].start);
|
||||||
|
|
||||||
|
info->res = request_mem_region(dev->resource[i].start,
|
||||||
|
dev->resource[i].end - dev->resource[i].start + 1,
|
||||||
dev->dev.bus_id);
|
dev->dev.bus_id);
|
||||||
if (info->res == NULL) {
|
if (info->res == NULL) {
|
||||||
dev_err(&dev->dev, "Could not reserve memory region\n");
|
dev_err(&dev->dev, "Could not reserve memory region\n");
|
||||||
@@ -109,47 +125,69 @@ static int physmap_flash_probe(struct platform_device *dev)
|
|||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->map.name = dev->dev.bus_id;
|
info->map[i].name = dev->dev.bus_id;
|
||||||
info->map.phys = dev->resource->start;
|
info->map[i].phys = dev->resource[i].start;
|
||||||
info->map.size = dev->resource->end - dev->resource->start + 1;
|
info->map[i].size = dev->resource[i].end - dev->resource[i].start + 1;
|
||||||
info->map.bankwidth = physmap_data->width;
|
info->map[i].bankwidth = physmap_data->width;
|
||||||
info->map.set_vpp = physmap_data->set_vpp;
|
info->map[i].set_vpp = physmap_data->set_vpp;
|
||||||
|
|
||||||
info->map.virt = ioremap(info->map.phys, info->map.size);
|
info->map[i].virt = ioremap(info->map[i].phys, info->map[i].size);
|
||||||
if (info->map.virt == NULL) {
|
if (info->map[i].virt == NULL) {
|
||||||
dev_err(&dev->dev, "Failed to ioremap flash region\n");
|
dev_err(&dev->dev, "Failed to ioremap flash region\n");
|
||||||
err = EIO;
|
err = EIO;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
simple_map_init(&info->map);
|
simple_map_init(&info->map[i]);
|
||||||
|
|
||||||
probe_type = rom_probe_types;
|
probe_type = rom_probe_types;
|
||||||
for (; info->mtd == NULL && *probe_type != NULL; probe_type++)
|
for (; info->mtd[i] == NULL && *probe_type != NULL; probe_type++)
|
||||||
info->mtd = do_map_probe(*probe_type, &info->map);
|
info->mtd[i] = do_map_probe(*probe_type, &info->map[i]);
|
||||||
if (info->mtd == NULL) {
|
if (info->mtd[i] == NULL) {
|
||||||
dev_err(&dev->dev, "map_probe failed\n");
|
dev_err(&dev->dev, "map_probe failed\n");
|
||||||
err = -ENXIO;
|
err = -ENXIO;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
} else {
|
||||||
|
devices_found++;
|
||||||
}
|
}
|
||||||
info->mtd->owner = THIS_MODULE;
|
info->mtd[i]->owner = THIS_MODULE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (devices_found == 1) {
|
||||||
|
info->cmtd = info->mtd[0];
|
||||||
|
} else if (devices_found > 1) {
|
||||||
|
/*
|
||||||
|
* We detected multiple devices. Concatenate them together.
|
||||||
|
*/
|
||||||
|
#ifdef CONFIG_MTD_CONCAT
|
||||||
|
info->cmtd = mtd_concat_create(info->mtd, devices_found, dev->dev.bus_id);
|
||||||
|
if (info->cmtd == NULL)
|
||||||
|
err = -ENXIO;
|
||||||
|
#else
|
||||||
|
printk(KERN_ERR "physmap-flash: multiple devices "
|
||||||
|
"found but MTD concat support disabled.\n");
|
||||||
|
err = -ENXIO;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_PARTITIONS
|
#ifdef CONFIG_MTD_PARTITIONS
|
||||||
err = parse_mtd_partitions(info->mtd, part_probe_types, &info->parts, 0);
|
err = parse_mtd_partitions(info->cmtd, part_probe_types, &info->parts, 0);
|
||||||
if (err > 0) {
|
if (err > 0) {
|
||||||
add_mtd_partitions(info->mtd, info->parts, err);
|
add_mtd_partitions(info->cmtd, info->parts, err);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (physmap_data->nr_parts) {
|
if (physmap_data->nr_parts) {
|
||||||
printk(KERN_NOTICE "Using physmap partition information\n");
|
printk(KERN_NOTICE "Using physmap partition information\n");
|
||||||
add_mtd_partitions(info->mtd, physmap_data->parts,
|
add_mtd_partitions(info->cmtd, physmap_data->parts,
|
||||||
physmap_data->nr_parts);
|
physmap_data->nr_parts);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
add_mtd_device(info->mtd);
|
add_mtd_device(info->cmtd);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out:
|
err_out:
|
||||||
@@ -162,9 +200,11 @@ static int physmap_flash_suspend(struct platform_device *dev, pm_message_t state
|
|||||||
{
|
{
|
||||||
struct physmap_flash_info *info = platform_get_drvdata(dev);
|
struct physmap_flash_info *info = platform_get_drvdata(dev);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
if (info)
|
if (info)
|
||||||
ret = info->mtd->suspend(info->mtd);
|
for (i = 0; i < MAX_RESOURCES; i++)
|
||||||
|
ret |= info->mtd[i]->suspend(info->mtd[i]);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -172,27 +212,35 @@ static int physmap_flash_suspend(struct platform_device *dev, pm_message_t state
|
|||||||
static int physmap_flash_resume(struct platform_device *dev)
|
static int physmap_flash_resume(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
struct physmap_flash_info *info = platform_get_drvdata(dev);
|
struct physmap_flash_info *info = platform_get_drvdata(dev);
|
||||||
|
int i;
|
||||||
|
|
||||||
if (info)
|
if (info)
|
||||||
info->mtd->resume(info->mtd);
|
for (i = 0; i < MAX_RESOURCES; i++)
|
||||||
|
info->mtd[i]->resume(info->mtd[i]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void physmap_flash_shutdown(struct platform_device *dev)
|
static void physmap_flash_shutdown(struct platform_device *dev)
|
||||||
{
|
{
|
||||||
struct physmap_flash_info *info = platform_get_drvdata(dev);
|
struct physmap_flash_info *info = platform_get_drvdata(dev);
|
||||||
if (info && info->mtd->suspend(info->mtd) == 0)
|
int i;
|
||||||
info->mtd->resume(info->mtd);
|
|
||||||
|
for (i = 0; i < MAX_RESOURCES; i++)
|
||||||
|
if (info && info->mtd[i]->suspend(info->mtd[i]) == 0)
|
||||||
|
info->mtd[i]->resume(info->mtd[i]);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#define physmap_flash_suspend NULL
|
||||||
|
#define physmap_flash_resume NULL
|
||||||
|
#define physmap_flash_shutdown NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct platform_driver physmap_flash_driver = {
|
static struct platform_driver physmap_flash_driver = {
|
||||||
.probe = physmap_flash_probe,
|
.probe = physmap_flash_probe,
|
||||||
.remove = physmap_flash_remove,
|
.remove = physmap_flash_remove,
|
||||||
#ifdef CONFIG_PM
|
|
||||||
.suspend = physmap_flash_suspend,
|
.suspend = physmap_flash_suspend,
|
||||||
.resume = physmap_flash_resume,
|
.resume = physmap_flash_resume,
|
||||||
.shutdown = physmap_flash_shutdown,
|
.shutdown = physmap_flash_shutdown,
|
||||||
#endif
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "physmap-flash",
|
.name = "physmap-flash",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -80,64 +80,6 @@ static int parse_obsolete_partitions(struct of_device *dev,
|
|||||||
|
|
||||||
return nr_parts;
|
return nr_parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __devinit parse_partitions(struct of_flash *info,
|
|
||||||
struct of_device *dev)
|
|
||||||
{
|
|
||||||
const char *partname;
|
|
||||||
static const char *part_probe_types[]
|
|
||||||
= { "cmdlinepart", "RedBoot", NULL };
|
|
||||||
struct device_node *dp = dev->node, *pp;
|
|
||||||
int nr_parts, i;
|
|
||||||
|
|
||||||
/* First look for RedBoot table or partitions on the command
|
|
||||||
* line, these take precedence over device tree information */
|
|
||||||
nr_parts = parse_mtd_partitions(info->mtd, part_probe_types,
|
|
||||||
&info->parts, 0);
|
|
||||||
if (nr_parts > 0) {
|
|
||||||
add_mtd_partitions(info->mtd, info->parts, nr_parts);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* First count the subnodes */
|
|
||||||
nr_parts = 0;
|
|
||||||
for (pp = dp->child; pp; pp = pp->sibling)
|
|
||||||
nr_parts++;
|
|
||||||
|
|
||||||
if (nr_parts == 0)
|
|
||||||
return parse_obsolete_partitions(dev, info, dp);
|
|
||||||
|
|
||||||
info->parts = kzalloc(nr_parts * sizeof(*info->parts),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!info->parts)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
for (pp = dp->child, i = 0; pp; pp = pp->sibling, i++) {
|
|
||||||
const u32 *reg;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
reg = of_get_property(pp, "reg", &len);
|
|
||||||
if (!reg || (len != 2*sizeof(u32))) {
|
|
||||||
dev_err(&dev->dev, "Invalid 'reg' on %s\n",
|
|
||||||
dp->full_name);
|
|
||||||
kfree(info->parts);
|
|
||||||
info->parts = NULL;
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
info->parts[i].offset = reg[0];
|
|
||||||
info->parts[i].size = reg[1];
|
|
||||||
|
|
||||||
partname = of_get_property(pp, "label", &len);
|
|
||||||
if (!partname)
|
|
||||||
partname = of_get_property(pp, "name", &len);
|
|
||||||
info->parts[i].name = (char *)partname;
|
|
||||||
|
|
||||||
if (of_get_property(pp, "read-only", &len))
|
|
||||||
info->parts[i].mask_flags = MTD_WRITEABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nr_parts;
|
|
||||||
}
|
|
||||||
#else /* MTD_PARTITIONS */
|
#else /* MTD_PARTITIONS */
|
||||||
#define OF_FLASH_PARTS(info) (0)
|
#define OF_FLASH_PARTS(info) (0)
|
||||||
#define parse_partitions(info, dev) (0)
|
#define parse_partitions(info, dev) (0)
|
||||||
@@ -212,6 +154,10 @@ static struct mtd_info * __devinit obsolete_probe(struct of_device *dev,
|
|||||||
static int __devinit of_flash_probe(struct of_device *dev,
|
static int __devinit of_flash_probe(struct of_device *dev,
|
||||||
const struct of_device_id *match)
|
const struct of_device_id *match)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_MTD_PARTITIONS
|
||||||
|
static const char *part_probe_types[]
|
||||||
|
= { "cmdlinepart", "RedBoot", NULL };
|
||||||
|
#endif
|
||||||
struct device_node *dp = dev->node;
|
struct device_node *dp = dev->node;
|
||||||
struct resource res;
|
struct resource res;
|
||||||
struct of_flash *info;
|
struct of_flash *info;
|
||||||
@@ -274,13 +220,33 @@ static int __devinit of_flash_probe(struct of_device *dev,
|
|||||||
}
|
}
|
||||||
info->mtd->owner = THIS_MODULE;
|
info->mtd->owner = THIS_MODULE;
|
||||||
|
|
||||||
err = parse_partitions(info, dev);
|
#ifdef CONFIG_MTD_PARTITIONS
|
||||||
|
/* First look for RedBoot table or partitions on the command
|
||||||
|
* line, these take precedence over device tree information */
|
||||||
|
err = parse_mtd_partitions(info->mtd, part_probe_types,
|
||||||
|
&info->parts, 0);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto err_out;
|
return err;
|
||||||
|
|
||||||
|
#ifdef CONFIG_MTD_OF_PARTS
|
||||||
|
if (err == 0) {
|
||||||
|
err = of_mtd_parse_partitions(&dev->dev, info->mtd,
|
||||||
|
dp, &info->parts);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (err == 0) {
|
||||||
|
err = parse_obsolete_partitions(dev, info, dp);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
if (err > 0)
|
if (err > 0)
|
||||||
add_mtd_partitions(info->mtd, OF_FLASH_PARTS(info), err);
|
add_mtd_partitions(info->mtd, info->parts, err);
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
add_mtd_device(info->mtd);
|
add_mtd_device(info->mtd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* pnc2000.c - mapper for Photron PNC-2000 board.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
|
|
||||||
*
|
|
||||||
* This code is GPL
|
|
||||||
*
|
|
||||||
* $Id: pnc2000.c,v 1.18 2005/11/07 11:14:28 gleixner Exp $
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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>
|
|
||||||
|
|
||||||
|
|
||||||
#define WINDOW_ADDR 0xbf000000
|
|
||||||
#define WINDOW_SIZE 0x00400000
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MAP DRIVER STUFF
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
static struct map_info pnc_map = {
|
|
||||||
.name = "PNC-2000",
|
|
||||||
.size = WINDOW_SIZE,
|
|
||||||
.bankwidth = 4,
|
|
||||||
.phys = 0xFFFFFFFF,
|
|
||||||
.virt = (void __iomem *)WINDOW_ADDR,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MTD 'PARTITIONING' STUFF
|
|
||||||
*/
|
|
||||||
static struct mtd_partition pnc_partitions[3] = {
|
|
||||||
{
|
|
||||||
.name = "PNC-2000 boot firmware",
|
|
||||||
.size = 0x20000,
|
|
||||||
.offset = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "PNC-2000 kernel",
|
|
||||||
.size = 0x1a0000,
|
|
||||||
.offset = 0x20000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = "PNC-2000 filesystem",
|
|
||||||
.size = 0x240000,
|
|
||||||
.offset = 0x1c0000
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is the master MTD device for which all the others are just
|
|
||||||
* auto-relocating aliases.
|
|
||||||
*/
|
|
||||||
static struct mtd_info *mymtd;
|
|
||||||
|
|
||||||
static int __init init_pnc2000(void)
|
|
||||||
{
|
|
||||||
printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR);
|
|
||||||
|
|
||||||
simple_map_init(&pnc_map);
|
|
||||||
|
|
||||||
mymtd = do_map_probe("cfi_probe", &pnc_map);
|
|
||||||
if (mymtd) {
|
|
||||||
mymtd->owner = THIS_MODULE;
|
|
||||||
return add_mtd_partitions(mymtd, pnc_partitions, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -ENXIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit cleanup_pnc2000(void)
|
|
||||||
{
|
|
||||||
if (mymtd) {
|
|
||||||
del_mtd_partitions(mymtd);
|
|
||||||
map_destroy(mymtd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(init_pnc2000);
|
|
||||||
module_exit(cleanup_pnc2000);
|
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
MODULE_AUTHOR("Crossnet Co. <info@crossnet.co.jp>");
|
|
||||||
MODULE_DESCRIPTION("MTD map driver for Photron PNC-2000 board");
|
|
||||||
@@ -79,7 +79,7 @@ scb2_fixup_mtd(struct mtd_info *mtd)
|
|||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
|
|
||||||
/* barf if this doesn't look right */
|
/* barf if this doesn't look right */
|
||||||
if (cfi->cfiq->InterfaceDesc != 1) {
|
if (cfi->cfiq->InterfaceDesc != CFI_INTERFACE_X16_ASYNC) {
|
||||||
printk(KERN_ERR MODNAME ": unsupported InterfaceDesc: %#x\n",
|
printk(KERN_ERR MODNAME ": unsupported InterfaceDesc: %#x\n",
|
||||||
cfi->cfiq->InterfaceDesc);
|
cfi->cfiq->InterfaceDesc);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -248,9 +248,9 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
|
|||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_init(&new->lock);
|
|
||||||
list_add_tail(&new->list, &tr->devs);
|
list_add_tail(&new->list, &tr->devs);
|
||||||
added:
|
added:
|
||||||
|
mutex_init(&new->lock);
|
||||||
if (!tr->writesect)
|
if (!tr->writesect)
|
||||||
new->readonly = 1;
|
new->readonly = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -481,6 +481,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
|||||||
{
|
{
|
||||||
struct mtd_oob_buf buf;
|
struct mtd_oob_buf buf;
|
||||||
struct mtd_oob_ops ops;
|
struct mtd_oob_ops ops;
|
||||||
|
uint32_t retlen;
|
||||||
|
|
||||||
if(!(file->f_mode & 2))
|
if(!(file->f_mode & 2))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
@@ -520,8 +521,11 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
|
|||||||
buf.start &= ~(mtd->oobsize - 1);
|
buf.start &= ~(mtd->oobsize - 1);
|
||||||
ret = mtd->write_oob(mtd, buf.start, &ops);
|
ret = mtd->write_oob(mtd, buf.start, &ops);
|
||||||
|
|
||||||
if (copy_to_user(argp + sizeof(uint32_t), &ops.oobretlen,
|
if (ops.oobretlen > 0xFFFFFFFFU)
|
||||||
sizeof(uint32_t)))
|
ret = -EOVERFLOW;
|
||||||
|
retlen = ops.oobretlen;
|
||||||
|
if (copy_to_user(&((struct mtd_oob_buf *)argp)->length,
|
||||||
|
&retlen, sizeof(buf.length)))
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
|
|
||||||
kfree(ops.oobbuf);
|
kfree(ops.oobbuf);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user