Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (59 commits) mtd: mtdpart: disallow reading OOB past the end of the partition mtd: pxa3xx_nand: NULL dereference in pxa3xx_nand_probe UBI: use mtd->writebufsize to set minimal I/O unit size mtd: initialize writebufsize in the MTD object of a partition mtd: onenand: add mtd->writebufsize initialization mtd: nand: add mtd->writebufsize initialization mtd: cfi: add writebufsize initialization mtd: add writebufsize field to mtd_info struct mtd: OneNAND: OMAP2/3: prevent regulator sleeping while OneNAND is in use mtd: OneNAND: add enable / disable methods to onenand_chip mtd: m25p80: Fix JEDEC ID for AT26DF321 mtd: txx9ndfmc: limit transfer bytes to 512 (ECC provides 6 bytes max) mtd: cfi_cmdset_0002: add support for Samsung K8D3x16UxC NOR chips mtd: cfi_cmdset_0002: add support for Samsung K8D6x16UxM NOR chips mtd: nand: ams-delta: drop omap_read/write, use ioremap mtd: m25p80: add debugging trace in sst_write mtd: nand: ams-delta: select for built-in by default mtd: OneNAND: lighten scary initial bad block messages mtd: OneNAND: OMAP2/3: add support for command line partitioning mtd: nand: rearrange ONFI revision checking, add ONFI 2.3 ... Fix up trivial conflict in drivers/mtd/Kconfig as per DavidW.
This commit is contained in:
commit
ab2020f2f1
|
@ -179,6 +179,22 @@ static struct omap_board_config_kernel ams_delta_config[] = {
|
|||
{ OMAP_TAG_LCD, &ams_delta_lcd_config },
|
||||
};
|
||||
|
||||
static struct resource ams_delta_nand_resources[] = {
|
||||
[0] = {
|
||||
.start = OMAP1_MPUIO_BASE,
|
||||
.end = OMAP1_MPUIO_BASE +
|
||||
OMAP_MPUIO_IO_CNTL + sizeof(u32) - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device ams_delta_nand_device = {
|
||||
.name = "ams-delta-nand",
|
||||
.id = -1,
|
||||
.num_resources = ARRAY_SIZE(ams_delta_nand_resources),
|
||||
.resource = ams_delta_nand_resources,
|
||||
};
|
||||
|
||||
static struct resource ams_delta_kp_resources[] = {
|
||||
[0] = {
|
||||
.start = INT_KEYBOARD,
|
||||
|
@ -265,6 +281,7 @@ static struct omap1_cam_platform_data ams_delta_camera_platform_data = {
|
|||
};
|
||||
|
||||
static struct platform_device *ams_delta_devices[] __initdata = {
|
||||
&ams_delta_nand_device,
|
||||
&ams_delta_kp_device,
|
||||
&ams_delta_lcd_device,
|
||||
&ams_delta_led_device,
|
||||
|
|
|
@ -23,6 +23,7 @@ struct omap_onenand_platform_data {
|
|||
int (*onenand_setup)(void __iomem *, int freq);
|
||||
int dma_channel;
|
||||
u8 flags;
|
||||
u8 regulator_can_sleep;
|
||||
};
|
||||
|
||||
#define ONENAND_MAX_PARTITIONS 8
|
||||
|
|
|
@ -53,9 +53,10 @@ config MTD_PARTITIONS
|
|||
devices. Partitioning on NFTL 'devices' is a different - that's the
|
||||
'normal' form of partitioning used on a block device.
|
||||
|
||||
if MTD_PARTITIONS
|
||||
|
||||
config MTD_REDBOOT_PARTS
|
||||
tristate "RedBoot partition table parsing"
|
||||
depends on MTD_PARTITIONS
|
||||
---help---
|
||||
RedBoot is a ROM monitor and bootloader which deals with multiple
|
||||
'images' in flash devices by putting a table one of the erase
|
||||
|
@ -72,9 +73,10 @@ config MTD_REDBOOT_PARTS
|
|||
SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for
|
||||
example.
|
||||
|
||||
if MTD_REDBOOT_PARTS
|
||||
|
||||
config MTD_REDBOOT_DIRECTORY_BLOCK
|
||||
int "Location of RedBoot partition table"
|
||||
depends on MTD_REDBOOT_PARTS
|
||||
default "-1"
|
||||
---help---
|
||||
This option is the Linux counterpart to the
|
||||
|
@ -91,18 +93,18 @@ config MTD_REDBOOT_DIRECTORY_BLOCK
|
|||
|
||||
config MTD_REDBOOT_PARTS_UNALLOCATED
|
||||
bool "Include unallocated flash regions"
|
||||
depends on MTD_REDBOOT_PARTS
|
||||
help
|
||||
If you need to register each unallocated flash region as a MTD
|
||||
'partition', enable this option.
|
||||
|
||||
config MTD_REDBOOT_PARTS_READONLY
|
||||
bool "Force read-only for RedBoot system images"
|
||||
depends on MTD_REDBOOT_PARTS
|
||||
help
|
||||
If you need to force read-only for 'RedBoot', 'RedBoot Config' and
|
||||
'FIS directory' images, enable this option.
|
||||
|
||||
endif # MTD_REDBOOT_PARTS
|
||||
|
||||
config MTD_CMDLINE_PARTS
|
||||
bool "Command line partition table parsing"
|
||||
depends on MTD_PARTITIONS = "y" && MTD = "y"
|
||||
|
@ -142,7 +144,7 @@ config MTD_CMDLINE_PARTS
|
|||
|
||||
config MTD_AFS_PARTS
|
||||
tristate "ARM Firmware Suite partition parsing"
|
||||
depends on ARM && MTD_PARTITIONS
|
||||
depends on ARM
|
||||
---help---
|
||||
The ARM Firmware Suite allows the user to divide flash devices into
|
||||
multiple 'images'. Each such image has a header containing its name
|
||||
|
@ -158,8 +160,8 @@ config MTD_AFS_PARTS
|
|||
example.
|
||||
|
||||
config MTD_OF_PARTS
|
||||
tristate "Flash partition map based on OF description"
|
||||
depends on OF && MTD_PARTITIONS
|
||||
def_bool y
|
||||
depends on OF
|
||||
help
|
||||
This provides a partition parsing function which derives
|
||||
the partition map from the children of the flash node,
|
||||
|
@ -167,10 +169,11 @@ config MTD_OF_PARTS
|
|||
|
||||
config MTD_AR7_PARTS
|
||||
tristate "TI AR7 partitioning support"
|
||||
depends on MTD_PARTITIONS
|
||||
---help---
|
||||
TI AR7 partitioning support
|
||||
|
||||
endif # MTD_PARTITIONS
|
||||
|
||||
comment "User Modules And Translation Layers"
|
||||
|
||||
config MTD_CHAR
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
obj-$(CONFIG_MTD) += mtd.o
|
||||
mtd-y := mtdcore.o mtdsuper.o
|
||||
mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
|
||||
mtd-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
|
||||
obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
|
||||
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
||||
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
|
||||
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
|
||||
# 'Users' - code which presents functionality to userspace.
|
||||
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
|
||||
|
|
|
@ -162,7 +162,7 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp)
|
|||
#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)
|
||||
static void fixup_convert_atmel_pri(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -202,7 +202,7 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
|
|||
cfi->cfiq->BufWriteTimeoutMax = 0;
|
||||
}
|
||||
|
||||
static void fixup_at49bv640dx_lock(struct mtd_info *mtd, void *param)
|
||||
static void fixup_at49bv640dx_lock(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -214,7 +214,7 @@ static void fixup_at49bv640dx_lock(struct mtd_info *mtd, void *param)
|
|||
|
||||
#ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE
|
||||
/* 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)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -227,7 +227,7 @@ static void fixup_intel_strataflash(struct mtd_info *mtd, void* param)
|
|||
#endif
|
||||
|
||||
#ifdef CMDSET0001_DISABLE_WRITE_SUSPEND
|
||||
static void fixup_no_write_suspend(struct mtd_info *mtd, void* param)
|
||||
static void fixup_no_write_suspend(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -240,7 +240,7 @@ static void fixup_no_write_suspend(struct mtd_info *mtd, void* param)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param)
|
||||
static void fixup_st_m28w320ct(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -249,7 +249,7 @@ static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param)
|
|||
cfi->cfiq->BufWriteTimeoutMax = 0; /* Not supported */
|
||||
}
|
||||
|
||||
static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param)
|
||||
static void fixup_st_m28w320cb(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -259,7 +259,7 @@ static void fixup_st_m28w320cb(struct mtd_info *mtd, void* param)
|
|||
(cfi->cfiq->EraseRegionInfo[1] & 0xffff0000) | 0x3e;
|
||||
};
|
||||
|
||||
static void fixup_use_point(struct mtd_info *mtd, void *param)
|
||||
static void fixup_use_point(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
if (!mtd->point && map_is_linear(map)) {
|
||||
|
@ -268,7 +268,7 @@ static void fixup_use_point(struct mtd_info *mtd, void *param)
|
|||
}
|
||||
}
|
||||
|
||||
static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
|
||||
static void fixup_use_write_buffers(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -282,7 +282,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
|
|||
/*
|
||||
* Some chips power-up with all sectors locked by default.
|
||||
*/
|
||||
static void fixup_unlock_powerup_lock(struct mtd_info *mtd, void *param)
|
||||
static void fixup_unlock_powerup_lock(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -295,31 +295,31 @@ static void fixup_unlock_powerup_lock(struct mtd_info *mtd, void *param)
|
|||
}
|
||||
|
||||
static struct cfi_fixup cfi_fixup_table[] = {
|
||||
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
|
||||
{ CFI_MFR_ATMEL, AT49BV640D, fixup_at49bv640dx_lock, NULL },
|
||||
{ CFI_MFR_ATMEL, AT49BV640DT, fixup_at49bv640dx_lock, NULL },
|
||||
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri },
|
||||
{ CFI_MFR_ATMEL, AT49BV640D, fixup_at49bv640dx_lock },
|
||||
{ CFI_MFR_ATMEL, AT49BV640DT, fixup_at49bv640dx_lock },
|
||||
#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 },
|
||||
#endif
|
||||
#ifdef CMDSET0001_DISABLE_WRITE_SUSPEND
|
||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend, NULL },
|
||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend },
|
||||
#endif
|
||||
#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 },
|
||||
#endif
|
||||
{ CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct, NULL },
|
||||
{ CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb, NULL },
|
||||
{ CFI_MFR_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock, NULL, },
|
||||
{ 0, 0, NULL, NULL }
|
||||
{ CFI_MFR_ST, 0x00ba, /* M28W320CT */ fixup_st_m28w320ct },
|
||||
{ CFI_MFR_ST, 0x00bb, /* M28W320CB */ fixup_st_m28w320cb },
|
||||
{ CFI_MFR_INTEL, CFI_ID_ANY, fixup_unlock_powerup_lock },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static struct cfi_fixup jedec_fixup_table[] = {
|
||||
{ CFI_MFR_INTEL, I82802AB, fixup_use_fwh_lock, NULL, },
|
||||
{ CFI_MFR_INTEL, I82802AC, fixup_use_fwh_lock, NULL, },
|
||||
{ CFI_MFR_ST, M50LPW080, fixup_use_fwh_lock, NULL, },
|
||||
{ CFI_MFR_ST, M50FLW080A, fixup_use_fwh_lock, NULL, },
|
||||
{ CFI_MFR_ST, M50FLW080B, fixup_use_fwh_lock, NULL, },
|
||||
{ 0, 0, NULL, NULL }
|
||||
{ CFI_MFR_INTEL, I82802AB, fixup_use_fwh_lock },
|
||||
{ CFI_MFR_INTEL, I82802AC, fixup_use_fwh_lock },
|
||||
{ CFI_MFR_ST, M50LPW080, fixup_use_fwh_lock },
|
||||
{ CFI_MFR_ST, M50FLW080A, fixup_use_fwh_lock },
|
||||
{ CFI_MFR_ST, M50FLW080B, fixup_use_fwh_lock },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
static struct cfi_fixup fixup_table[] = {
|
||||
/* The CFI vendor ids and the JEDEC vendor IDs appear
|
||||
|
@ -327,8 +327,8 @@ static struct cfi_fixup fixup_table[] = {
|
|||
* well. This table is to pick all cases where
|
||||
* we know that is the case.
|
||||
*/
|
||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point, NULL },
|
||||
{ 0, 0, NULL, NULL }
|
||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_point },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static void cfi_fixup_major_minor(struct cfi_private *cfi,
|
||||
|
@ -455,6 +455,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
|
|||
mtd->flags = MTD_CAP_NORFLASH;
|
||||
mtd->name = map->name;
|
||||
mtd->writesize = 1;
|
||||
mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
|
||||
|
||||
mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ static void cfi_tell_features(struct cfi_pri_amdstd *extp)
|
|||
|
||||
#ifdef AMD_BOOTLOC_BUG
|
||||
/* Wheee. Bring me the head of someone at AMD. */
|
||||
static void fixup_amd_bootblock(struct mtd_info *mtd, void* param)
|
||||
static void fixup_amd_bootblock(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -186,7 +186,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd, void* param)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
|
||||
static void fixup_use_write_buffers(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -197,7 +197,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd, void *param)
|
|||
}
|
||||
|
||||
/* Atmel chips don't use the same PRI format as AMD chips */
|
||||
static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
|
||||
static void fixup_convert_atmel_pri(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -228,14 +228,14 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
|
|||
cfi->cfiq->BufWriteTimeoutMax = 0;
|
||||
}
|
||||
|
||||
static void fixup_use_secsi(struct mtd_info *mtd, void *param)
|
||||
static void fixup_use_secsi(struct mtd_info *mtd)
|
||||
{
|
||||
/* Setup for chips with a secsi area */
|
||||
mtd->read_user_prot_reg = cfi_amdstd_secsi_read;
|
||||
mtd->read_fact_prot_reg = cfi_amdstd_secsi_read;
|
||||
}
|
||||
|
||||
static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)
|
||||
static void fixup_use_erase_chip(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -250,7 +250,7 @@ static void fixup_use_erase_chip(struct mtd_info *mtd, void *param)
|
|||
* Some Atmel chips (e.g. the AT49BV6416) power-up with all sectors
|
||||
* locked by default.
|
||||
*/
|
||||
static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param)
|
||||
static void fixup_use_atmel_lock(struct mtd_info *mtd)
|
||||
{
|
||||
mtd->lock = cfi_atmel_lock;
|
||||
mtd->unlock = cfi_atmel_unlock;
|
||||
|
@ -271,7 +271,7 @@ static void fixup_old_sst_eraseregion(struct mtd_info *mtd)
|
|||
cfi->cfiq->NumEraseRegions = 1;
|
||||
}
|
||||
|
||||
static void fixup_sst39vf(struct mtd_info *mtd, void *param)
|
||||
static void fixup_sst39vf(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -282,7 +282,7 @@ static void fixup_sst39vf(struct mtd_info *mtd, void *param)
|
|||
cfi->addr_unlock2 = 0x2AAA;
|
||||
}
|
||||
|
||||
static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
|
||||
static void fixup_sst39vf_rev_b(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -295,12 +295,12 @@ static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
|
|||
cfi->sector_erase_cmd = CMD(0x50);
|
||||
}
|
||||
|
||||
static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
|
||||
static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
||||
fixup_sst39vf_rev_b(mtd, param);
|
||||
fixup_sst39vf_rev_b(mtd);
|
||||
|
||||
/*
|
||||
* CFI reports 1024 sectors (0x03ff+1) of 64KBytes (0x0100*256) where
|
||||
|
@ -310,7 +310,7 @@ static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd, void *param)
|
|||
pr_warning("%s: Bad 38VF640x CFI data; adjusting sector size from 64 to 8KiB\n", mtd->name);
|
||||
}
|
||||
|
||||
static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
|
||||
static void fixup_s29gl064n_sectors(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -321,7 +321,7 @@ static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param)
|
|||
}
|
||||
}
|
||||
|
||||
static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
|
||||
static void fixup_s29gl032n_sectors(struct mtd_info *mtd)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
@ -334,47 +334,47 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param)
|
|||
|
||||
/* Used to fix CFI-Tables of chips without Extended Query Tables */
|
||||
static struct cfi_fixup cfi_nopri_fixup_table[] = {
|
||||
{ CFI_MFR_SST, 0x234A, fixup_sst39vf, NULL, }, /* SST39VF1602 */
|
||||
{ CFI_MFR_SST, 0x234B, fixup_sst39vf, NULL, }, /* SST39VF1601 */
|
||||
{ CFI_MFR_SST, 0x235A, fixup_sst39vf, NULL, }, /* SST39VF3202 */
|
||||
{ CFI_MFR_SST, 0x235B, fixup_sst39vf, NULL, }, /* SST39VF3201 */
|
||||
{ CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3202B */
|
||||
{ CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF3201B */
|
||||
{ CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6402B */
|
||||
{ CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, /* SST39VF6401B */
|
||||
{ 0, 0, NULL, NULL }
|
||||
{ CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */
|
||||
{ CFI_MFR_SST, 0x234b, fixup_sst39vf }, /* SST39VF1601 */
|
||||
{ CFI_MFR_SST, 0x235a, fixup_sst39vf }, /* SST39VF3202 */
|
||||
{ CFI_MFR_SST, 0x235b, fixup_sst39vf }, /* SST39VF3201 */
|
||||
{ CFI_MFR_SST, 0x235c, fixup_sst39vf_rev_b }, /* SST39VF3202B */
|
||||
{ CFI_MFR_SST, 0x235d, fixup_sst39vf_rev_b }, /* SST39VF3201B */
|
||||
{ CFI_MFR_SST, 0x236c, fixup_sst39vf_rev_b }, /* SST39VF6402B */
|
||||
{ CFI_MFR_SST, 0x236d, fixup_sst39vf_rev_b }, /* SST39VF6401B */
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static struct cfi_fixup cfi_fixup_table[] = {
|
||||
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
|
||||
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri },
|
||||
#ifdef AMD_BOOTLOC_BUG
|
||||
{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
|
||||
{ CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock, NULL },
|
||||
{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock },
|
||||
{ CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock },
|
||||
#endif
|
||||
{ CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, },
|
||||
{ CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, },
|
||||
{ CFI_MFR_AMD, 0x0055, fixup_use_secsi, NULL, },
|
||||
{ CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, },
|
||||
{ CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, },
|
||||
{ CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, },
|
||||
{ CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors, NULL, },
|
||||
{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, },
|
||||
{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, },
|
||||
{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, },
|
||||
{ CFI_MFR_SST, 0x536A, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6402 */
|
||||
{ CFI_MFR_SST, 0x536B, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6401 */
|
||||
{ CFI_MFR_SST, 0x536C, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6404 */
|
||||
{ CFI_MFR_SST, 0x536D, fixup_sst38vf640x_sectorsize, NULL, }, /* SST38VF6403 */
|
||||
{ CFI_MFR_AMD, 0x0050, fixup_use_secsi },
|
||||
{ CFI_MFR_AMD, 0x0053, fixup_use_secsi },
|
||||
{ CFI_MFR_AMD, 0x0055, fixup_use_secsi },
|
||||
{ CFI_MFR_AMD, 0x0056, fixup_use_secsi },
|
||||
{ CFI_MFR_AMD, 0x005C, fixup_use_secsi },
|
||||
{ CFI_MFR_AMD, 0x005F, fixup_use_secsi },
|
||||
{ CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors },
|
||||
{ CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors },
|
||||
{ CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors },
|
||||
{ CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors },
|
||||
{ CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */
|
||||
{ CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */
|
||||
{ CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */
|
||||
{ CFI_MFR_SST, 0x536d, fixup_sst38vf640x_sectorsize }, /* SST38VF6403 */
|
||||
#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 },
|
||||
#endif
|
||||
{ 0, 0, NULL, NULL }
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
static struct cfi_fixup jedec_fixup_table[] = {
|
||||
{ CFI_MFR_SST, SST49LF004B, fixup_use_fwh_lock, NULL, },
|
||||
{ CFI_MFR_SST, SST49LF040B, fixup_use_fwh_lock, NULL, },
|
||||
{ CFI_MFR_SST, SST49LF008A, fixup_use_fwh_lock, NULL, },
|
||||
{ 0, 0, NULL, NULL }
|
||||
{ CFI_MFR_SST, SST49LF004B, fixup_use_fwh_lock },
|
||||
{ CFI_MFR_SST, SST49LF040B, fixup_use_fwh_lock },
|
||||
{ CFI_MFR_SST, SST49LF008A, fixup_use_fwh_lock },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
static struct cfi_fixup fixup_table[] = {
|
||||
|
@ -383,18 +383,30 @@ static struct cfi_fixup fixup_table[] = {
|
|||
* well. This table is to pick all cases where
|
||||
* we know that is the case.
|
||||
*/
|
||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
|
||||
{ CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL },
|
||||
{ 0, 0, NULL, NULL }
|
||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip },
|
||||
{ CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock },
|
||||
{ 0, 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
static void cfi_fixup_major_minor(struct cfi_private *cfi,
|
||||
struct cfi_pri_amdstd *extp)
|
||||
{
|
||||
if (cfi->mfr == CFI_MFR_SAMSUNG && cfi->id == 0x257e &&
|
||||
extp->MajorVersion == '0')
|
||||
extp->MajorVersion = '1';
|
||||
if (cfi->mfr == CFI_MFR_SAMSUNG) {
|
||||
if ((extp->MajorVersion == '0' && extp->MinorVersion == '0') ||
|
||||
(extp->MajorVersion == '3' && extp->MinorVersion == '3')) {
|
||||
/*
|
||||
* Samsung K8P2815UQB and K8D6x16UxM chips
|
||||
* report major=0 / minor=0.
|
||||
* K8D3x16UxC chips report major=3 / minor=3.
|
||||
*/
|
||||
printk(KERN_NOTICE " Fixing Samsung's Amd/Fujitsu"
|
||||
" Extended Query version to 1.%c\n",
|
||||
extp->MinorVersion);
|
||||
extp->MajorVersion = '1';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SST 38VF640x chips report major=0xFF / minor=0xFF.
|
||||
*/
|
||||
|
@ -428,6 +440,10 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
|||
mtd->flags = MTD_CAP_NORFLASH;
|
||||
mtd->name = map->name;
|
||||
mtd->writesize = 1;
|
||||
mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n",
|
||||
__func__, mtd->writebufsize);
|
||||
|
||||
mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
|
||||
|
||||
|
|
|
@ -238,6 +238,7 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
|
|||
mtd->resume = cfi_staa_resume;
|
||||
mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE;
|
||||
mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
|
||||
mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
|
||||
map->fldrv = &cfi_staa_chipdrv;
|
||||
__module_get(THIS_MODULE);
|
||||
mtd->name = map->name;
|
||||
|
|
|
@ -156,7 +156,7 @@ void cfi_fixup(struct mtd_info *mtd, struct cfi_fixup *fixups)
|
|||
for (f=fixups; f->fixup; f++) {
|
||||
if (((f->mfr == CFI_MFR_ANY) || (f->mfr == cfi->mfr)) &&
|
||||
((f->id == CFI_ID_ANY) || (f->id == cfi->id))) {
|
||||
f->fixup(mtd, f->param);
|
||||
f->fixup(mtd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void fixup_use_fwh_lock(struct mtd_info *mtd, void *param)
|
||||
static void fixup_use_fwh_lock(struct mtd_info *mtd)
|
||||
{
|
||||
printk(KERN_NOTICE "using fwh lock/unlock method\n");
|
||||
/* Setup for the chips with the fwh lock method */
|
||||
|
|
|
@ -51,6 +51,10 @@
|
|||
#define OPCODE_WRDI 0x04 /* Write disable */
|
||||
#define OPCODE_AAI_WP 0xad /* Auto address increment word program */
|
||||
|
||||
/* Used for Macronix flashes only. */
|
||||
#define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */
|
||||
#define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */
|
||||
|
||||
/* Status Register bits. */
|
||||
#define SR_WIP 1 /* Write in progress */
|
||||
#define SR_WEL 2 /* Write enable latch */
|
||||
|
@ -62,7 +66,7 @@
|
|||
|
||||
/* Define max times to check status register before we give up. */
|
||||
#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */
|
||||
#define MAX_CMD_SIZE 4
|
||||
#define MAX_CMD_SIZE 5
|
||||
|
||||
#ifdef CONFIG_M25PXX_USE_FAST_READ
|
||||
#define OPCODE_READ OPCODE_FAST_READ
|
||||
|
@ -151,6 +155,16 @@ static inline int write_disable(struct m25p *flash)
|
|||
return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable/disable 4-byte addressing mode.
|
||||
*/
|
||||
static inline int set_4byte(struct m25p *flash, int enable)
|
||||
{
|
||||
u8 code = enable ? OPCODE_EN4B : OPCODE_EX4B;
|
||||
|
||||
return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Service routine to read status register until ready, or timeout occurs.
|
||||
* Returns non-zero if error.
|
||||
|
@ -207,6 +221,7 @@ static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
|
|||
cmd[1] = addr >> (flash->addr_width * 8 - 8);
|
||||
cmd[2] = addr >> (flash->addr_width * 8 - 16);
|
||||
cmd[3] = addr >> (flash->addr_width * 8 - 24);
|
||||
cmd[4] = addr >> (flash->addr_width * 8 - 32);
|
||||
}
|
||||
|
||||
static int m25p_cmdsz(struct m25p *flash)
|
||||
|
@ -482,6 +497,10 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|||
size_t actual;
|
||||
int cmd_sz, ret;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
|
||||
dev_name(&flash->spi->dev), __func__, "to",
|
||||
(u32)to, len);
|
||||
|
||||
*retlen = 0;
|
||||
|
||||
/* sanity checks */
|
||||
|
@ -607,7 +626,6 @@ struct flash_info {
|
|||
.sector_size = (_sector_size), \
|
||||
.n_sectors = (_n_sectors), \
|
||||
.page_size = 256, \
|
||||
.addr_width = 3, \
|
||||
.flags = (_flags), \
|
||||
})
|
||||
|
||||
|
@ -635,7 +653,7 @@ static const struct spi_device_id m25p_ids[] = {
|
|||
{ "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) },
|
||||
{ "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
|
||||
{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
|
||||
{ "at26df321", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
|
||||
{ "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
|
||||
|
||||
/* EON -- en25pxx */
|
||||
{ "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
|
||||
|
@ -653,6 +671,8 @@ static const struct spi_device_id m25p_ids[] = {
|
|||
{ "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) },
|
||||
{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
|
||||
{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
|
||||
{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
|
||||
{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
|
||||
|
||||
/* Spansion -- single (large) sector size only, at least
|
||||
* for the chips listed here (without boot sectors).
|
||||
|
@ -764,6 +784,7 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
|
|||
return &m25p_ids[tmp];
|
||||
}
|
||||
}
|
||||
dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
|
||||
return ERR_PTR(-ENODEV);
|
||||
}
|
||||
|
||||
|
@ -883,7 +904,17 @@ static int __devinit m25p_probe(struct spi_device *spi)
|
|||
|
||||
flash->mtd.dev.parent = &spi->dev;
|
||||
flash->page_size = info->page_size;
|
||||
flash->addr_width = info->addr_width;
|
||||
|
||||
if (info->addr_width)
|
||||
flash->addr_width = info->addr_width;
|
||||
else {
|
||||
/* enable 4-byte addressing if the device exceeds 16MiB */
|
||||
if (flash->mtd.size > 0x1000000) {
|
||||
flash->addr_width = 4;
|
||||
set_4byte(flash, 1);
|
||||
} else
|
||||
flash->addr_width = 3;
|
||||
}
|
||||
|
||||
dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
|
||||
(long long)flash->mtd.size >> 10);
|
||||
|
|
|
@ -335,7 +335,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct flash_info *__init sst25l_match_device(struct spi_device *spi)
|
||||
static struct flash_info *__devinit sst25l_match_device(struct spi_device *spi)
|
||||
{
|
||||
struct flash_info *flash_info = NULL;
|
||||
struct spi_message m;
|
||||
|
@ -375,7 +375,7 @@ static struct flash_info *__init sst25l_match_device(struct spi_device *spi)
|
|||
return flash_info;
|
||||
}
|
||||
|
||||
static int __init sst25l_probe(struct spi_device *spi)
|
||||
static int __devinit sst25l_probe(struct spi_device *spi)
|
||||
{
|
||||
struct flash_info *flash_info;
|
||||
struct sst25l_flash *flash;
|
||||
|
|
|
@ -149,11 +149,8 @@ static int __devinit amd76xrom_init_one (struct pci_dev *pdev,
|
|||
if (request_resource(&iomem_resource, &window->rsrc)) {
|
||||
window->rsrc.parent = NULL;
|
||||
printk(KERN_ERR MOD_NAME
|
||||
" %s(): Unable to register resource"
|
||||
" 0x%.16llx-0x%.16llx - kernel bug?\n",
|
||||
__func__,
|
||||
(unsigned long long)window->rsrc.start,
|
||||
(unsigned long long)window->rsrc.end);
|
||||
" %s(): Unable to register resource %pR - kernel bug?\n",
|
||||
__func__, &window->rsrc);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -196,10 +196,15 @@ static int bcm963xx_probe(struct platform_device *pdev)
|
|||
bcm963xx_mtd_info = do_map_probe("cfi_probe", &bcm963xx_map);
|
||||
if (!bcm963xx_mtd_info) {
|
||||
dev_err(&pdev->dev, "failed to probe using CFI\n");
|
||||
bcm963xx_mtd_info = do_map_probe("jedec_probe", &bcm963xx_map);
|
||||
if (bcm963xx_mtd_info)
|
||||
goto probe_ok;
|
||||
dev_err(&pdev->dev, "failed to probe using JEDEC\n");
|
||||
err = -EIO;
|
||||
goto err_probe;
|
||||
}
|
||||
|
||||
probe_ok:
|
||||
bcm963xx_mtd_info->owner = THIS_MODULE;
|
||||
|
||||
/* This is mutually exclusive */
|
||||
|
|
|
@ -178,11 +178,8 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev,
|
|||
if (request_resource(&iomem_resource, &window->rsrc)) {
|
||||
window->rsrc.parent = NULL;
|
||||
printk(KERN_ERR MOD_NAME
|
||||
" %s(): Unable to register resource"
|
||||
" 0x%.016llx-0x%.016llx - kernel bug?\n",
|
||||
__func__,
|
||||
(unsigned long long)window->rsrc.start,
|
||||
(unsigned long long)window->rsrc.end);
|
||||
" %s(): Unable to register resource %pR - kernel bug?\n",
|
||||
__func__, &window->rsrc);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -242,12 +242,9 @@ static int __devinit esb2rom_init_one(struct pci_dev *pdev,
|
|||
window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
|
||||
if (request_resource(&iomem_resource, &window->rsrc)) {
|
||||
window->rsrc.parent = NULL;
|
||||
printk(KERN_DEBUG MOD_NAME
|
||||
": %s(): Unable to register resource"
|
||||
" 0x%.08llx-0x%.08llx - kernel bug?\n",
|
||||
__func__,
|
||||
(unsigned long long)window->rsrc.start,
|
||||
(unsigned long long)window->rsrc.end);
|
||||
printk(KERN_DEBUG MOD_NAME ": "
|
||||
"%s(): Unable to register resource %pR - kernel bug?\n",
|
||||
__func__, &window->rsrc);
|
||||
}
|
||||
|
||||
/* Map the firmware hub into my address space. */
|
||||
|
|
|
@ -175,12 +175,9 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev,
|
|||
window->rsrc.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
|
||||
if (request_resource(&iomem_resource, &window->rsrc)) {
|
||||
window->rsrc.parent = NULL;
|
||||
printk(KERN_DEBUG MOD_NAME
|
||||
": %s(): Unable to register resource"
|
||||
" 0x%.16llx-0x%.16llx - kernel bug?\n",
|
||||
__func__,
|
||||
(unsigned long long)window->rsrc.start,
|
||||
(unsigned long long)window->rsrc.end);
|
||||
printk(KERN_DEBUG MOD_NAME ": "
|
||||
"%s(): Unable to register resource %pR - kernel bug?\n",
|
||||
__func__, &window->rsrc);
|
||||
}
|
||||
|
||||
/* Map the firmware hub into my address space. */
|
||||
|
|
|
@ -274,9 +274,7 @@ static int __devinit of_flash_probe(struct platform_device *dev,
|
|||
continue;
|
||||
}
|
||||
|
||||
dev_dbg(&dev->dev, "of_flash device: %.8llx-%.8llx\n",
|
||||
(unsigned long long)res.start,
|
||||
(unsigned long long)res.end);
|
||||
dev_dbg(&dev->dev, "of_flash device: %pR\n", &res);
|
||||
|
||||
err = -EBUSY;
|
||||
res_size = resource_size(&res);
|
||||
|
|
|
@ -166,9 +166,8 @@ static int __init init_scx200_docflash(void)
|
|||
outl(pmr, scx200_cb_base + SCx200_PMR);
|
||||
}
|
||||
|
||||
printk(KERN_INFO NAME ": DOCCS mapped at 0x%llx-0x%llx, width %d\n",
|
||||
(unsigned long long)docmem.start,
|
||||
(unsigned long long)docmem.end, width);
|
||||
printk(KERN_INFO NAME ": DOCCS mapped at %pR, width %d\n",
|
||||
&docmem, width);
|
||||
|
||||
scx200_docflash_map.size = size;
|
||||
if (width == 8)
|
||||
|
|
|
@ -139,7 +139,7 @@ static int __init init_tqm_mtd(void)
|
|||
goto error_mem;
|
||||
}
|
||||
|
||||
map_banks[idx]->name = (char *)kmalloc(16, GFP_KERNEL);
|
||||
map_banks[idx]->name = kmalloc(16, GFP_KERNEL);
|
||||
|
||||
if (!map_banks[idx]->name) {
|
||||
ret = -ENOMEM;
|
||||
|
|
|
@ -522,10 +522,6 @@ static int mtd_blkpg_ioctl(struct mtd_info *mtd,
|
|||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
/* Only master mtd device must be used to control partitions */
|
||||
if (!mtd_is_master(mtd))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&a, arg, sizeof(struct blkpg_ioctl_arg)))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -535,6 +531,10 @@ static int mtd_blkpg_ioctl(struct mtd_info *mtd,
|
|||
switch (a.op) {
|
||||
case BLKPG_ADD_PARTITION:
|
||||
|
||||
/* Only master mtd device must be used to add partitions */
|
||||
if (mtd_is_partition(mtd))
|
||||
return -EINVAL;
|
||||
|
||||
return mtd_add_partition(mtd, p.devname, p.start, p.length);
|
||||
|
||||
case BLKPG_DEL_PARTITION:
|
||||
|
@ -601,6 +601,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
|||
}
|
||||
|
||||
case MEMGETINFO:
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.type = mtd->type;
|
||||
info.flags = mtd->flags;
|
||||
info.size = mtd->size;
|
||||
|
@ -609,7 +610,6 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
|||
info.oobsize = mtd->oobsize;
|
||||
/* The below fields are obsolete */
|
||||
info.ecctype = -1;
|
||||
info.eccsize = 0;
|
||||
if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
|
|
|
@ -776,6 +776,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
|
|||
concat->mtd.size = subdev[0]->size;
|
||||
concat->mtd.erasesize = subdev[0]->erasesize;
|
||||
concat->mtd.writesize = subdev[0]->writesize;
|
||||
concat->mtd.writebufsize = subdev[0]->writebufsize;
|
||||
concat->mtd.subpage_sft = subdev[0]->subpage_sft;
|
||||
concat->mtd.oobsize = subdev[0]->oobsize;
|
||||
concat->mtd.oobavail = subdev[0]->oobavail;
|
||||
|
|
|
@ -401,7 +401,8 @@ static void mtdoops_notify_remove(struct mtd_info *mtd)
|
|||
printk(KERN_WARNING "mtdoops: could not unregister kmsg_dumper\n");
|
||||
|
||||
cxt->mtd = NULL;
|
||||
flush_scheduled_work();
|
||||
flush_work_sync(&cxt->work_erase);
|
||||
flush_work_sync(&cxt->work_write);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -120,8 +120,25 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
|
|||
return -EINVAL;
|
||||
if (ops->datbuf && from + ops->len > mtd->size)
|
||||
return -EINVAL;
|
||||
res = part->master->read_oob(part->master, from + part->offset, ops);
|
||||
|
||||
/*
|
||||
* If OOB is also requested, make sure that we do not read past the end
|
||||
* of this partition.
|
||||
*/
|
||||
if (ops->oobbuf) {
|
||||
size_t len, pages;
|
||||
|
||||
if (ops->mode == MTD_OOB_AUTO)
|
||||
len = mtd->oobavail;
|
||||
else
|
||||
len = mtd->oobsize;
|
||||
pages = mtd_div_by_ws(mtd->size, mtd);
|
||||
pages -= mtd_div_by_ws(from, mtd);
|
||||
if (ops->ooboffs + ops->ooblen > pages * len)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = part->master->read_oob(part->master, from + part->offset, ops);
|
||||
if (unlikely(res)) {
|
||||
if (res == -EUCLEAN)
|
||||
mtd->ecc_stats.corrected++;
|
||||
|
@ -384,6 +401,7 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
|
|||
slave->mtd.flags = master->flags & ~part->mask_flags;
|
||||
slave->mtd.size = part->size;
|
||||
slave->mtd.writesize = master->writesize;
|
||||
slave->mtd.writebufsize = master->writebufsize;
|
||||
slave->mtd.oobsize = master->oobsize;
|
||||
slave->mtd.oobavail = master->oobavail;
|
||||
slave->mtd.subpage_sft = master->subpage_sft;
|
||||
|
@ -720,19 +738,19 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(parse_mtd_partitions);
|
||||
|
||||
int mtd_is_master(struct mtd_info *mtd)
|
||||
int mtd_is_partition(struct mtd_info *mtd)
|
||||
{
|
||||
struct mtd_part *part;
|
||||
int nopart = 0;
|
||||
int ispart = 0;
|
||||
|
||||
mutex_lock(&mtd_partitions_mutex);
|
||||
list_for_each_entry(part, &mtd_partitions, list)
|
||||
if (&part->mtd == mtd) {
|
||||
nopart = 1;
|
||||
ispart = 1;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&mtd_partitions_mutex);
|
||||
|
||||
return nopart;
|
||||
return ispart;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_is_master);
|
||||
EXPORT_SYMBOL_GPL(mtd_is_partition);
|
||||
|
|
|
@ -96,6 +96,7 @@ config MTD_NAND_SPIA
|
|||
config MTD_NAND_AMS_DELTA
|
||||
tristate "NAND Flash device on Amstrad E3"
|
||||
depends on MACH_AMS_DELTA
|
||||
default y
|
||||
help
|
||||
Support for NAND flash on Amstrad E3 (Delta).
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
|
||||
*
|
||||
* Derived from drivers/mtd/toto.c
|
||||
* Converted to platform driver by Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
|
||||
* Partially stolen from drivers/mtd/nand/plat_nand.c
|
||||
*
|
||||
* 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
|
||||
|
@ -62,9 +64,10 @@ static struct mtd_partition partition_info[] = {
|
|||
static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte)
|
||||
{
|
||||
struct nand_chip *this = mtd->priv;
|
||||
void __iomem *io_base = this->priv;
|
||||
|
||||
omap_writew(0, (OMAP1_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
|
||||
omap_writew(byte, this->IO_ADDR_W);
|
||||
writew(0, io_base + OMAP_MPUIO_IO_CNTL);
|
||||
writew(byte, this->IO_ADDR_W);
|
||||
ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0);
|
||||
ndelay(40);
|
||||
ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE,
|
||||
|
@ -75,11 +78,12 @@ static u_char ams_delta_read_byte(struct mtd_info *mtd)
|
|||
{
|
||||
u_char res;
|
||||
struct nand_chip *this = mtd->priv;
|
||||
void __iomem *io_base = this->priv;
|
||||
|
||||
ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0);
|
||||
ndelay(40);
|
||||
omap_writew(~0, (OMAP1_MPUIO_BASE + OMAP_MPUIO_IO_CNTL));
|
||||
res = omap_readw(this->IO_ADDR_R);
|
||||
writew(~0, io_base + OMAP_MPUIO_IO_CNTL);
|
||||
res = readw(this->IO_ADDR_R);
|
||||
ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE,
|
||||
AMS_DELTA_LATCH2_NAND_NRE);
|
||||
|
||||
|
@ -151,11 +155,16 @@ static int ams_delta_nand_ready(struct mtd_info *mtd)
|
|||
/*
|
||||
* Main initialization routine
|
||||
*/
|
||||
static int __init ams_delta_init(void)
|
||||
static int __devinit ams_delta_init(struct platform_device *pdev)
|
||||
{
|
||||
struct nand_chip *this;
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
void __iomem *io_base;
|
||||
int err = 0;
|
||||
|
||||
if (!res)
|
||||
return -ENXIO;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
ams_delta_mtd = kmalloc(sizeof(struct mtd_info) +
|
||||
sizeof(struct nand_chip), GFP_KERNEL);
|
||||
|
@ -177,9 +186,25 @@ static int __init ams_delta_init(void)
|
|||
/* Link the private data with the MTD structure */
|
||||
ams_delta_mtd->priv = this;
|
||||
|
||||
if (!request_mem_region(res->start, resource_size(res),
|
||||
dev_name(&pdev->dev))) {
|
||||
dev_err(&pdev->dev, "request_mem_region failed\n");
|
||||
err = -EBUSY;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
io_base = ioremap(res->start, resource_size(res));
|
||||
if (io_base == NULL) {
|
||||
dev_err(&pdev->dev, "ioremap failed\n");
|
||||
err = -EIO;
|
||||
goto out_release_io;
|
||||
}
|
||||
|
||||
this->priv = io_base;
|
||||
|
||||
/* Set address of NAND IO lines */
|
||||
this->IO_ADDR_R = (OMAP1_MPUIO_BASE + OMAP_MPUIO_INPUT_LATCH);
|
||||
this->IO_ADDR_W = (OMAP1_MPUIO_BASE + OMAP_MPUIO_OUTPUT);
|
||||
this->IO_ADDR_R = io_base + OMAP_MPUIO_INPUT_LATCH;
|
||||
this->IO_ADDR_W = io_base + OMAP_MPUIO_OUTPUT;
|
||||
this->read_byte = ams_delta_read_byte;
|
||||
this->write_buf = ams_delta_write_buf;
|
||||
this->read_buf = ams_delta_read_buf;
|
||||
|
@ -195,6 +220,8 @@ static int __init ams_delta_init(void)
|
|||
this->chip_delay = 30;
|
||||
this->ecc.mode = NAND_ECC_SOFT;
|
||||
|
||||
platform_set_drvdata(pdev, io_base);
|
||||
|
||||
/* Set chip enabled, but */
|
||||
ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE |
|
||||
AMS_DELTA_LATCH2_NAND_NWE |
|
||||
|
@ -214,25 +241,56 @@ static int __init ams_delta_init(void)
|
|||
goto out;
|
||||
|
||||
out_mtd:
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
iounmap(io_base);
|
||||
out_release_io:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
out_free:
|
||||
kfree(ams_delta_mtd);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
module_init(ams_delta_init);
|
||||
|
||||
/*
|
||||
* Clean up routine
|
||||
*/
|
||||
static void __exit ams_delta_cleanup(void)
|
||||
static int __devexit ams_delta_cleanup(struct platform_device *pdev)
|
||||
{
|
||||
void __iomem *io_base = platform_get_drvdata(pdev);
|
||||
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
||||
/* Release resources, unregister device */
|
||||
nand_release(ams_delta_mtd);
|
||||
|
||||
iounmap(io_base);
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
|
||||
/* Free the MTD device structure */
|
||||
kfree(ams_delta_mtd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_exit(ams_delta_cleanup);
|
||||
|
||||
static struct platform_driver ams_delta_nand_driver = {
|
||||
.probe = ams_delta_init,
|
||||
.remove = __devexit_p(ams_delta_cleanup),
|
||||
.driver = {
|
||||
.name = "ams-delta-nand",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ams_delta_nand_init(void)
|
||||
{
|
||||
return platform_driver_register(&ams_delta_nand_driver);
|
||||
}
|
||||
module_init(ams_delta_nand_init);
|
||||
|
||||
static void __exit ams_delta_nand_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ams_delta_nand_driver);
|
||||
}
|
||||
module_exit(ams_delta_nand_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
|
||||
|
|
|
@ -388,6 +388,8 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
|
|||
"page_addr: 0x%x, column: 0x%x.\n",
|
||||
page_addr, column);
|
||||
|
||||
elbc_fcm_ctrl->column = column;
|
||||
elbc_fcm_ctrl->oob = 0;
|
||||
elbc_fcm_ctrl->use_mdr = 1;
|
||||
|
||||
fcr = (NAND_CMD_STATUS << FCR_CMD1_SHIFT) |
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mtd/fsmc.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <mtd/mtd-abi.h>
|
||||
|
||||
static struct nand_ecclayout fsmc_ecc1_layout = {
|
||||
|
@ -119,21 +120,36 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
/*
|
||||
* Default partition tables to be used if the partition information not
|
||||
* provided through platform data
|
||||
*/
|
||||
#define PARTITION(n, off, sz) {.name = n, .offset = off, .size = sz}
|
||||
|
||||
/*
|
||||
* provided through platform data.
|
||||
*
|
||||
* Default partition layout for small page(= 512 bytes) devices
|
||||
* Size for "Root file system" is updated in driver based on actual device size
|
||||
*/
|
||||
static struct mtd_partition partition_info_16KB_blk[] = {
|
||||
PARTITION("X-loader", 0, 4 * 0x4000),
|
||||
PARTITION("U-Boot", 0x10000, 20 * 0x4000),
|
||||
PARTITION("Kernel", 0x60000, 256 * 0x4000),
|
||||
PARTITION("Root File System", 0x460000, 0),
|
||||
{
|
||||
.name = "X-loader",
|
||||
.offset = 0,
|
||||
.size = 4*0x4000,
|
||||
},
|
||||
{
|
||||
.name = "U-Boot",
|
||||
.offset = 0x10000,
|
||||
.size = 20*0x4000,
|
||||
},
|
||||
{
|
||||
.name = "Kernel",
|
||||
.offset = 0x60000,
|
||||
.size = 256*0x4000,
|
||||
},
|
||||
{
|
||||
.name = "Root File System",
|
||||
.offset = 0x460000,
|
||||
.size = 0,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -141,19 +157,37 @@ static struct mtd_partition partition_info_16KB_blk[] = {
|
|||
* Size for "Root file system" is updated in driver based on actual device size
|
||||
*/
|
||||
static struct mtd_partition partition_info_128KB_blk[] = {
|
||||
PARTITION("X-loader", 0, 4 * 0x20000),
|
||||
PARTITION("U-Boot", 0x80000, 12 * 0x20000),
|
||||
PARTITION("Kernel", 0x200000, 48 * 0x20000),
|
||||
PARTITION("Root File System", 0x800000, 0),
|
||||
{
|
||||
.name = "X-loader",
|
||||
.offset = 0,
|
||||
.size = 4*0x20000,
|
||||
},
|
||||
{
|
||||
.name = "U-Boot",
|
||||
.offset = 0x80000,
|
||||
.size = 12*0x20000,
|
||||
},
|
||||
{
|
||||
.name = "Kernel",
|
||||
.offset = 0x200000,
|
||||
.size = 48*0x20000,
|
||||
},
|
||||
{
|
||||
.name = "Root File System",
|
||||
.offset = 0x800000,
|
||||
.size = 0,
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MTD_CMDLINE_PARTS
|
||||
const char *part_probes[] = { "cmdlinepart", NULL };
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* struct fsmc_nand_data - atructure for FSMC NAND device state
|
||||
* struct fsmc_nand_data - structure for FSMC NAND device state
|
||||
*
|
||||
* @pid: Part ID on the AMBA PrimeCell format
|
||||
* @mtd: MTD info for a NAND flash.
|
||||
* @nand: Chip related info for a NAND flash.
|
||||
* @partitions: Partition info for a NAND Flash.
|
||||
|
@ -169,6 +203,7 @@ const char *part_probes[] = { "cmdlinepart", NULL };
|
|||
* @regs_va: FSMC regs base address.
|
||||
*/
|
||||
struct fsmc_nand_data {
|
||||
u32 pid;
|
||||
struct mtd_info mtd;
|
||||
struct nand_chip nand;
|
||||
struct mtd_partition *partitions;
|
||||
|
@ -508,7 +543,9 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
struct nand_chip *nand;
|
||||
struct fsmc_regs *regs;
|
||||
struct resource *res;
|
||||
int nr_parts, ret = 0;
|
||||
int ret = 0;
|
||||
u32 pid;
|
||||
int i;
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&pdev->dev, "platform data is NULL\n");
|
||||
|
@ -598,6 +635,18 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_probe1;
|
||||
|
||||
/*
|
||||
* This device ID is actually a common AMBA ID as used on the
|
||||
* AMBA PrimeCell bus. However it is not a PrimeCell.
|
||||
*/
|
||||
for (pid = 0, i = 0; i < 4; i++)
|
||||
pid |= (readl(host->regs_va + resource_size(res) - 0x20 + 4 * i) & 255) << (i * 8);
|
||||
host->pid = pid;
|
||||
dev_info(&pdev->dev, "FSMC device partno %03x, manufacturer %02x, "
|
||||
"revision %02x, config %02x\n",
|
||||
AMBA_PART_BITS(pid), AMBA_MANF_BITS(pid),
|
||||
AMBA_REV_BITS(pid), AMBA_CONFIG_BITS(pid));
|
||||
|
||||
host->bank = pdata->bank;
|
||||
host->select_chip = pdata->select_bank;
|
||||
regs = host->regs_va;
|
||||
|
@ -625,7 +674,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
|
||||
fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16);
|
||||
|
||||
if (get_fsmc_version(host->regs_va) == FSMC_VER8) {
|
||||
if (AMBA_REV_BITS(host->pid) >= 8) {
|
||||
nand->ecc.read_page = fsmc_read_page_hwecc;
|
||||
nand->ecc.calculate = fsmc_read_hwecc_ecc4;
|
||||
nand->ecc.correct = fsmc_correct_data;
|
||||
|
@ -645,7 +694,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
goto err_probe;
|
||||
}
|
||||
|
||||
if (get_fsmc_version(host->regs_va) == FSMC_VER8) {
|
||||
if (AMBA_REV_BITS(host->pid) >= 8) {
|
||||
if (host->mtd.writesize == 512) {
|
||||
nand->ecc.layout = &fsmc_ecc4_sp_layout;
|
||||
host->ecc_place = &fsmc_ecc4_sp_place;
|
||||
|
@ -676,11 +725,9 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
|
|||
* Check if partition info passed via command line
|
||||
*/
|
||||
host->mtd.name = "nand";
|
||||
nr_parts = parse_mtd_partitions(&host->mtd, part_probes,
|
||||
host->nr_partitions = parse_mtd_partitions(&host->mtd, part_probes,
|
||||
&host->partitions, 0);
|
||||
if (nr_parts > 0) {
|
||||
host->nr_partitions = nr_parts;
|
||||
} else {
|
||||
if (host->nr_partitions <= 0) {
|
||||
#endif
|
||||
/*
|
||||
* Check if partition info passed via command line
|
||||
|
|
|
@ -251,58 +251,6 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Copy paste of nand_read_page_hwecc_oob_first except for different eccpos
|
||||
* handling. The ecc area is for 4k chips 72 bytes long and thus does not fit
|
||||
* into the eccpos array. */
|
||||
static int jz_nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
|
||||
struct nand_chip *chip, uint8_t *buf, int page)
|
||||
{
|
||||
int i, eccsize = chip->ecc.size;
|
||||
int eccbytes = chip->ecc.bytes;
|
||||
int eccsteps = chip->ecc.steps;
|
||||
uint8_t *p = buf;
|
||||
unsigned int ecc_offset = chip->page_shift;
|
||||
|
||||
/* Read the OOB area first */
|
||||
chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
|
||||
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
|
||||
chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
|
||||
|
||||
for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
|
||||
int stat;
|
||||
|
||||
chip->ecc.hwctl(mtd, NAND_ECC_READ);
|
||||
chip->read_buf(mtd, p, eccsize);
|
||||
|
||||
stat = chip->ecc.correct(mtd, p, &chip->oob_poi[i], NULL);
|
||||
if (stat < 0)
|
||||
mtd->ecc_stats.failed++;
|
||||
else
|
||||
mtd->ecc_stats.corrected += stat;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy-and-paste of nand_write_page_hwecc with different eccpos handling. */
|
||||
static void jz_nand_write_page_hwecc(struct mtd_info *mtd,
|
||||
struct nand_chip *chip, const uint8_t *buf)
|
||||
{
|
||||
int i, eccsize = chip->ecc.size;
|
||||
int eccbytes = chip->ecc.bytes;
|
||||
int eccsteps = chip->ecc.steps;
|
||||
const uint8_t *p = buf;
|
||||
unsigned int ecc_offset = chip->page_shift;
|
||||
|
||||
for (i = ecc_offset; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
|
||||
chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
|
||||
chip->write_buf(mtd, p, eccsize);
|
||||
chip->ecc.calculate(mtd, p, &chip->oob_poi[i]);
|
||||
}
|
||||
|
||||
chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_CMDLINE_PARTS
|
||||
static const char *part_probes[] = {"cmdline", NULL};
|
||||
#endif
|
||||
|
@ -393,9 +341,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
|
|||
chip->ecc.size = 512;
|
||||
chip->ecc.bytes = 9;
|
||||
|
||||
chip->ecc.read_page = jz_nand_read_page_hwecc_oob_first;
|
||||
chip->ecc.write_page = jz_nand_write_page_hwecc;
|
||||
|
||||
if (pdata)
|
||||
chip->ecc.layout = pdata->ecc_layout;
|
||||
|
||||
|
@ -489,7 +434,7 @@ static int __devexit jz_nand_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct platform_driver jz_nand_driver = {
|
||||
static struct platform_driver jz_nand_driver = {
|
||||
.probe = jz_nand_probe,
|
||||
.remove = __devexit_p(jz_nand_remove),
|
||||
.driver = {
|
||||
|
|
|
@ -1009,7 +1009,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
|
|||
struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct mxc_nand_host *host;
|
||||
struct resource *res;
|
||||
int err = 0, nr_parts = 0;
|
||||
int err = 0, __maybe_unused nr_parts = 0;
|
||||
struct nand_ecclayout *oob_smallpage, *oob_largepage;
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
|
|
|
@ -2865,20 +2865,24 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
|
||||
/* check version */
|
||||
val = le16_to_cpu(p->revision);
|
||||
if (val == 1 || val > (1 << 4)) {
|
||||
printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
|
||||
__func__, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (val & (1 << 4))
|
||||
if (val & (1 << 5))
|
||||
chip->onfi_version = 23;
|
||||
else if (val & (1 << 4))
|
||||
chip->onfi_version = 22;
|
||||
else if (val & (1 << 3))
|
||||
chip->onfi_version = 21;
|
||||
else if (val & (1 << 2))
|
||||
chip->onfi_version = 20;
|
||||
else
|
||||
else if (val & (1 << 1))
|
||||
chip->onfi_version = 10;
|
||||
else
|
||||
chip->onfi_version = 0;
|
||||
|
||||
if (!chip->onfi_version) {
|
||||
printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
|
||||
__func__, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sanitize_string(p->manufacturer, sizeof(p->manufacturer));
|
||||
sanitize_string(p->model, sizeof(p->model));
|
||||
|
@ -2887,7 +2891,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
|
|||
mtd->writesize = le32_to_cpu(p->byte_per_page);
|
||||
mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
|
||||
mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
|
||||
chip->chipsize = le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
|
||||
chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
|
||||
busw = 0;
|
||||
if (le16_to_cpu(p->features) & 1)
|
||||
busw = NAND_BUSWIDTH_16;
|
||||
|
@ -3157,7 +3161,7 @@ ident_done:
|
|||
printk(KERN_INFO "NAND device: Manufacturer ID:"
|
||||
" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
|
||||
nand_manuf_ids[maf_idx].name,
|
||||
chip->onfi_version ? type->name : chip->onfi_params.model);
|
||||
chip->onfi_version ? chip->onfi_params.model : type->name);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
@ -3435,6 +3439,7 @@ int nand_scan_tail(struct mtd_info *mtd)
|
|||
mtd->resume = nand_resume;
|
||||
mtd->block_isbad = nand_block_isbad;
|
||||
mtd->block_markbad = nand_block_markbad;
|
||||
mtd->writebufsize = mtd->writesize;
|
||||
|
||||
/* propagate ecc.layout to mtd_info */
|
||||
mtd->ecclayout = chip->ecc.layout;
|
||||
|
|
|
@ -1092,7 +1092,8 @@ static void mark_bbt_region(struct mtd_info *mtd, struct nand_bbt_descr *td)
|
|||
|
||||
/**
|
||||
* verify_bbt_descr - verify the bad block description
|
||||
* @bd: the table to verify
|
||||
* @mtd: MTD device structure
|
||||
* @bd: the table to verify
|
||||
*
|
||||
* This functions performs a few sanity checks on the bad block description
|
||||
* table.
|
||||
|
|
|
@ -210,12 +210,12 @@ MODULE_PARM_DESC(bbt, "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in d
|
|||
#define STATE_CMD_READ0 0x00000001 /* read data from the beginning of page */
|
||||
#define STATE_CMD_READ1 0x00000002 /* read data from the second half of page */
|
||||
#define STATE_CMD_READSTART 0x00000003 /* read data second command (large page devices) */
|
||||
#define STATE_CMD_PAGEPROG 0x00000004 /* start page programm */
|
||||
#define STATE_CMD_PAGEPROG 0x00000004 /* start page program */
|
||||
#define STATE_CMD_READOOB 0x00000005 /* read OOB area */
|
||||
#define STATE_CMD_ERASE1 0x00000006 /* sector erase first command */
|
||||
#define STATE_CMD_STATUS 0x00000007 /* read status */
|
||||
#define STATE_CMD_STATUS_M 0x00000008 /* read multi-plane status (isn't implemented) */
|
||||
#define STATE_CMD_SEQIN 0x00000009 /* sequential data imput */
|
||||
#define STATE_CMD_SEQIN 0x00000009 /* sequential data input */
|
||||
#define STATE_CMD_READID 0x0000000A /* read ID */
|
||||
#define STATE_CMD_ERASE2 0x0000000B /* sector erase second command */
|
||||
#define STATE_CMD_RESET 0x0000000C /* reset */
|
||||
|
@ -230,7 +230,7 @@ MODULE_PARM_DESC(bbt, "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in d
|
|||
#define STATE_ADDR_ZERO 0x00000040 /* one byte zero address was accepted */
|
||||
#define STATE_ADDR_MASK 0x00000070 /* address states mask */
|
||||
|
||||
/* Durind data input/output the simulator is in these states */
|
||||
/* During data input/output the simulator is in these states */
|
||||
#define STATE_DATAIN 0x00000100 /* waiting for data input */
|
||||
#define STATE_DATAIN_MASK 0x00000100 /* data input states mask */
|
||||
|
||||
|
@ -248,7 +248,7 @@ MODULE_PARM_DESC(bbt, "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in d
|
|||
|
||||
/* Simulator's actions bit masks */
|
||||
#define ACTION_CPY 0x00100000 /* copy page/OOB to the internal buffer */
|
||||
#define ACTION_PRGPAGE 0x00200000 /* programm the internal buffer to flash */
|
||||
#define ACTION_PRGPAGE 0x00200000 /* program the internal buffer to flash */
|
||||
#define ACTION_SECERASE 0x00300000 /* erase sector */
|
||||
#define ACTION_ZEROOFF 0x00400000 /* don't add any offset to address */
|
||||
#define ACTION_HALFOFF 0x00500000 /* add to address half of page */
|
||||
|
@ -263,18 +263,18 @@ MODULE_PARM_DESC(bbt, "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in d
|
|||
#define OPT_PAGE512 0x00000002 /* 512-byte page chips */
|
||||
#define OPT_PAGE2048 0x00000008 /* 2048-byte page chips */
|
||||
#define OPT_SMARTMEDIA 0x00000010 /* SmartMedia technology chips */
|
||||
#define OPT_AUTOINCR 0x00000020 /* page number auto inctimentation is possible */
|
||||
#define OPT_AUTOINCR 0x00000020 /* page number auto incrementation is possible */
|
||||
#define OPT_PAGE512_8BIT 0x00000040 /* 512-byte page chips with 8-bit bus width */
|
||||
#define OPT_PAGE4096 0x00000080 /* 4096-byte page chips */
|
||||
#define OPT_LARGEPAGE (OPT_PAGE2048 | OPT_PAGE4096) /* 2048 & 4096-byte page chips */
|
||||
#define OPT_SMALLPAGE (OPT_PAGE256 | OPT_PAGE512) /* 256 and 512-byte page chips */
|
||||
|
||||
/* Remove action bits ftom state */
|
||||
/* Remove action bits from state */
|
||||
#define NS_STATE(x) ((x) & ~ACTION_MASK)
|
||||
|
||||
/*
|
||||
* Maximum previous states which need to be saved. Currently saving is
|
||||
* only needed for page programm operation with preceeded read command
|
||||
* only needed for page program operation with preceded read command
|
||||
* (which is only valid for 512-byte pages).
|
||||
*/
|
||||
#define NS_MAX_PREVSTATES 1
|
||||
|
@ -380,16 +380,16 @@ static struct nandsim_operations {
|
|||
/* Read OOB */
|
||||
{OPT_SMALLPAGE, {STATE_CMD_READOOB | ACTION_OOBOFF, STATE_ADDR_PAGE | ACTION_CPY,
|
||||
STATE_DATAOUT, STATE_READY}},
|
||||
/* Programm page starting from the beginning */
|
||||
/* Program page starting from the beginning */
|
||||
{OPT_ANY, {STATE_CMD_SEQIN, STATE_ADDR_PAGE, STATE_DATAIN,
|
||||
STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
|
||||
/* Programm page starting from the beginning */
|
||||
/* Program page starting from the beginning */
|
||||
{OPT_SMALLPAGE, {STATE_CMD_READ0, STATE_CMD_SEQIN | ACTION_ZEROOFF, STATE_ADDR_PAGE,
|
||||
STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
|
||||
/* Programm page starting from the second half */
|
||||
/* Program page starting from the second half */
|
||||
{OPT_PAGE512, {STATE_CMD_READ1, STATE_CMD_SEQIN | ACTION_HALFOFF, STATE_ADDR_PAGE,
|
||||
STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
|
||||
/* Programm OOB */
|
||||
/* Program OOB */
|
||||
{OPT_SMALLPAGE, {STATE_CMD_READOOB, STATE_CMD_SEQIN | ACTION_OOBOFF, STATE_ADDR_PAGE,
|
||||
STATE_DATAIN, STATE_CMD_PAGEPROG | ACTION_PRGPAGE, STATE_READY}},
|
||||
/* Erase sector */
|
||||
|
@ -470,7 +470,7 @@ static int alloc_device(struct nandsim *ns)
|
|||
err = -EINVAL;
|
||||
goto err_close;
|
||||
}
|
||||
ns->pages_written = vmalloc(ns->geom.pgnum);
|
||||
ns->pages_written = vzalloc(ns->geom.pgnum);
|
||||
if (!ns->pages_written) {
|
||||
NS_ERR("alloc_device: unable to allocate pages written array\n");
|
||||
err = -ENOMEM;
|
||||
|
@ -483,7 +483,6 @@ static int alloc_device(struct nandsim *ns)
|
|||
goto err_free;
|
||||
}
|
||||
ns->cfile = cfile;
|
||||
memset(ns->pages_written, 0, ns->geom.pgnum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1171,9 +1170,9 @@ static inline void switch_to_ready_state(struct nandsim *ns, u_char status)
|
|||
* of supported operations.
|
||||
*
|
||||
* Operation can be unknown because of the following.
|
||||
* 1. New command was accepted and this is the firs call to find the
|
||||
* 1. New command was accepted and this is the first call to find the
|
||||
* correspondent states chain. In this case ns->npstates = 0;
|
||||
* 2. There is several operations which begin with the same command(s)
|
||||
* 2. There are several operations which begin with the same command(s)
|
||||
* (for example program from the second half and read from the
|
||||
* second half operations both begin with the READ1 command). In this
|
||||
* case the ns->pstates[] array contains previous states.
|
||||
|
@ -1186,7 +1185,7 @@ static inline void switch_to_ready_state(struct nandsim *ns, u_char status)
|
|||
* ns->ops, ns->state, ns->nxstate are initialized, ns->npstate is
|
||||
* zeroed).
|
||||
*
|
||||
* If there are several maches, the current state is pushed to the
|
||||
* If there are several matches, the current state is pushed to the
|
||||
* ns->pstates.
|
||||
*
|
||||
* The operation can be unknown only while commands are input to the chip.
|
||||
|
@ -1195,10 +1194,10 @@ static inline void switch_to_ready_state(struct nandsim *ns, u_char status)
|
|||
* operation is searched using the following pattern:
|
||||
* ns->pstates[0], ... ns->pstates[ns->npstates], <address input>
|
||||
*
|
||||
* It is supposed that this pattern must either match one operation on
|
||||
* It is supposed that this pattern must either match one operation or
|
||||
* none. There can't be ambiguity in that case.
|
||||
*
|
||||
* If no matches found, the functions does the following:
|
||||
* If no matches found, the function does the following:
|
||||
* 1. if there are saved states present, try to ignore them and search
|
||||
* again only using the last command. If nothing was found, switch
|
||||
* to the STATE_READY state.
|
||||
|
@ -1668,7 +1667,7 @@ static int do_state_action(struct nandsim *ns, uint32_t action)
|
|||
|
||||
case ACTION_PRGPAGE:
|
||||
/*
|
||||
* Programm page - move internal buffer data to the page.
|
||||
* Program page - move internal buffer data to the page.
|
||||
*/
|
||||
|
||||
if (ns->lines.wp) {
|
||||
|
@ -1933,7 +1932,7 @@ static u_char ns_nand_read_byte(struct mtd_info *mtd)
|
|||
NS_DBG("read_byte: all bytes were read\n");
|
||||
|
||||
/*
|
||||
* The OPT_AUTOINCR allows to read next conseqitive pages without
|
||||
* The OPT_AUTOINCR allows to read next consecutive pages without
|
||||
* new read operation cycle.
|
||||
*/
|
||||
if ((ns->options & OPT_AUTOINCR) && NS_STATE(ns->state) == STATE_DATAOUT) {
|
||||
|
|
|
@ -107,7 +107,7 @@ static int __devinit pasemi_nand_probe(struct platform_device *ofdev,
|
|||
if (pasemi_nand_mtd)
|
||||
return -ENODEV;
|
||||
|
||||
pr_debug("pasemi_nand at %llx-%llx\n", res.start, res.end);
|
||||
pr_debug("pasemi_nand at %pR\n", &res);
|
||||
|
||||
/* Allocate memory for MTD device structure and private data */
|
||||
pasemi_nand_mtd = kzalloc(sizeof(struct mtd_info) +
|
||||
|
|
|
@ -885,6 +885,7 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
|
|||
/* set info fields needed to __readid */
|
||||
info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
|
||||
info->reg_ndcr = ndcr;
|
||||
info->cmdset = &default_cmdset;
|
||||
|
||||
if (__readid(info, &id))
|
||||
return -ENODEV;
|
||||
|
@ -915,7 +916,6 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
|
|||
|
||||
info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
|
||||
info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
|
||||
info->cmdset = &default_cmdset;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -277,8 +277,9 @@ static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
|
|||
ret = nand_scan_ident(mtd, 1, NULL);
|
||||
if (!ret) {
|
||||
if (mtd->writesize >= 512) {
|
||||
chip->ecc.size = mtd->writesize;
|
||||
chip->ecc.bytes = 3 * (mtd->writesize / 256);
|
||||
/* Hardware ECC 6 byte ECC per 512 Byte data */
|
||||
chip->ecc.size = 512;
|
||||
chip->ecc.bytes = 6;
|
||||
}
|
||||
ret = nand_scan_tail(mtd);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/dma-mapping.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <asm/mach/flash.h>
|
||||
#include <plat/gpmc.h>
|
||||
|
@ -63,8 +64,13 @@ struct omap2_onenand {
|
|||
int dma_channel;
|
||||
int freq;
|
||||
int (*setup)(void __iomem *base, int freq);
|
||||
struct regulator *regulator;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
static const char *part_probes[] = { "cmdlinepart", NULL, };
|
||||
#endif
|
||||
|
||||
static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
|
||||
{
|
||||
struct omap2_onenand *c = data;
|
||||
|
@ -108,8 +114,9 @@ static void wait_warn(char *msg, int state, unsigned int ctrl,
|
|||
static int omap2_onenand_wait(struct mtd_info *mtd, int state)
|
||||
{
|
||||
struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
|
||||
struct onenand_chip *this = mtd->priv;
|
||||
unsigned int intr = 0;
|
||||
unsigned int ctrl;
|
||||
unsigned int ctrl, ctrl_mask;
|
||||
unsigned long timeout;
|
||||
u32 syscfg;
|
||||
|
||||
|
@ -180,7 +187,8 @@ retry:
|
|||
if (result == 0) {
|
||||
/* Timeout after 20ms */
|
||||
ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
|
||||
if (ctrl & ONENAND_CTRL_ONGO) {
|
||||
if (ctrl & ONENAND_CTRL_ONGO &&
|
||||
!this->ongoing) {
|
||||
/*
|
||||
* The operation seems to be still going
|
||||
* so give it some more time.
|
||||
|
@ -269,7 +277,11 @@ retry:
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (ctrl & 0xFE9F)
|
||||
ctrl_mask = 0xFE9F;
|
||||
if (this->ongoing)
|
||||
ctrl_mask &= ~0x8000;
|
||||
|
||||
if (ctrl & ctrl_mask)
|
||||
wait_warn("unexpected controller status", state, ctrl, intr);
|
||||
|
||||
return 0;
|
||||
|
@ -591,6 +603,30 @@ static void omap2_onenand_shutdown(struct platform_device *pdev)
|
|||
memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
|
||||
}
|
||||
|
||||
static int omap2_onenand_enable(struct mtd_info *mtd)
|
||||
{
|
||||
int ret;
|
||||
struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
|
||||
|
||||
ret = regulator_enable(c->regulator);
|
||||
if (ret != 0)
|
||||
dev_err(&c->pdev->dev, "cant enable regulator\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int omap2_onenand_disable(struct mtd_info *mtd)
|
||||
{
|
||||
int ret;
|
||||
struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
|
||||
|
||||
ret = regulator_disable(c->regulator);
|
||||
if (ret != 0)
|
||||
dev_err(&c->pdev->dev, "cant disable regulator\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit omap2_onenand_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_onenand_platform_data *pdata;
|
||||
|
@ -705,8 +741,18 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
if (pdata->regulator_can_sleep) {
|
||||
c->regulator = regulator_get(&pdev->dev, "vonenand");
|
||||
if (IS_ERR(c->regulator)) {
|
||||
dev_err(&pdev->dev, "Failed to get regulator\n");
|
||||
goto err_release_dma;
|
||||
}
|
||||
c->onenand.enable = omap2_onenand_enable;
|
||||
c->onenand.disable = omap2_onenand_disable;
|
||||
}
|
||||
|
||||
if ((r = onenand_scan(&c->mtd, 1)) < 0)
|
||||
goto err_release_dma;
|
||||
goto err_release_regulator;
|
||||
|
||||
switch ((c->onenand.version_id >> 4) & 0xf) {
|
||||
case 0:
|
||||
|
@ -727,13 +773,15 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
if (pdata->parts != NULL)
|
||||
r = add_mtd_partitions(&c->mtd, pdata->parts,
|
||||
pdata->nr_parts);
|
||||
r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
|
||||
if (r > 0)
|
||||
r = add_mtd_partitions(&c->mtd, c->parts, r);
|
||||
else if (pdata->parts != NULL)
|
||||
r = add_mtd_partitions(&c->mtd, pdata->parts, pdata->nr_parts);
|
||||
else
|
||||
#endif
|
||||
r = add_mtd_device(&c->mtd);
|
||||
if (r < 0)
|
||||
if (r)
|
||||
goto err_release_onenand;
|
||||
|
||||
platform_set_drvdata(pdev, c);
|
||||
|
@ -742,6 +790,8 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
|
|||
|
||||
err_release_onenand:
|
||||
onenand_release(&c->mtd);
|
||||
err_release_regulator:
|
||||
regulator_put(c->regulator);
|
||||
err_release_dma:
|
||||
if (c->dma_channel != -1)
|
||||
omap_free_dma(c->dma_channel);
|
||||
|
@ -757,6 +807,7 @@ err_release_mem_region:
|
|||
err_free_cs:
|
||||
gpmc_cs_free(c->gpmc_cs);
|
||||
err_kfree:
|
||||
kfree(c->parts);
|
||||
kfree(c);
|
||||
|
||||
return r;
|
||||
|
@ -766,18 +817,8 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
|
|||
{
|
||||
struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
|
||||
|
||||
BUG_ON(c == NULL);
|
||||
|
||||
#ifdef CONFIG_MTD_PARTITIONS
|
||||
if (c->parts)
|
||||
del_mtd_partitions(&c->mtd);
|
||||
else
|
||||
del_mtd_device(&c->mtd);
|
||||
#else
|
||||
del_mtd_device(&c->mtd);
|
||||
#endif
|
||||
|
||||
onenand_release(&c->mtd);
|
||||
regulator_put(c->regulator);
|
||||
if (c->dma_channel != -1)
|
||||
omap_free_dma(c->dma_channel);
|
||||
omap2_onenand_shutdown(pdev);
|
||||
|
@ -789,6 +830,7 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
|
|||
iounmap(c->onenand.base);
|
||||
release_mem_region(c->phys_base, ONENAND_IO_SIZE);
|
||||
gpmc_cs_free(c->gpmc_cs);
|
||||
kfree(c->parts);
|
||||
kfree(c);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -400,8 +400,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
|
|||
value = onenand_bufferram_address(this, block);
|
||||
this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
|
||||
|
||||
if (ONENAND_IS_MLC(this) || ONENAND_IS_2PLANE(this) ||
|
||||
ONENAND_IS_4KB_PAGE(this))
|
||||
if (ONENAND_IS_2PLANE(this) || ONENAND_IS_4KB_PAGE(this))
|
||||
/* It is always BufferRAM0 */
|
||||
ONENAND_SET_BUFFERRAM0(this);
|
||||
else
|
||||
|
@ -430,7 +429,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le
|
|||
case FLEXONENAND_CMD_RECOVER_LSB:
|
||||
case ONENAND_CMD_READ:
|
||||
case ONENAND_CMD_READOOB:
|
||||
if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this))
|
||||
if (ONENAND_IS_4KB_PAGE(this))
|
||||
/* It is always BufferRAM0 */
|
||||
dataram = ONENAND_SET_BUFFERRAM0(this);
|
||||
else
|
||||
|
@ -949,6 +948,8 @@ static int onenand_get_device(struct mtd_info *mtd, int new_state)
|
|||
if (this->state == FL_READY) {
|
||||
this->state = new_state;
|
||||
spin_unlock(&this->chip_lock);
|
||||
if (new_state != FL_PM_SUSPENDED && this->enable)
|
||||
this->enable(mtd);
|
||||
break;
|
||||
}
|
||||
if (new_state == FL_PM_SUSPENDED) {
|
||||
|
@ -975,6 +976,8 @@ static void onenand_release_device(struct mtd_info *mtd)
|
|||
{
|
||||
struct onenand_chip *this = mtd->priv;
|
||||
|
||||
if (this->state != FL_PM_SUSPENDED && this->disable)
|
||||
this->disable(mtd);
|
||||
/* Release the chip */
|
||||
spin_lock(&this->chip_lock);
|
||||
this->state = FL_READY;
|
||||
|
@ -1353,7 +1356,7 @@ static int onenand_read_oob_nolock(struct mtd_info *mtd, loff_t from,
|
|||
|
||||
stats = mtd->ecc_stats;
|
||||
|
||||
readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
|
||||
readcmd = ONENAND_IS_4KB_PAGE(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
|
||||
|
||||
while (read < len) {
|
||||
cond_resched();
|
||||
|
@ -1429,7 +1432,7 @@ static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|||
int ret;
|
||||
|
||||
onenand_get_device(mtd, FL_READING);
|
||||
ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ?
|
||||
ret = ONENAND_IS_4KB_PAGE(this) ?
|
||||
onenand_mlc_read_ops_nolock(mtd, from, &ops) :
|
||||
onenand_read_ops_nolock(mtd, from, &ops);
|
||||
onenand_release_device(mtd);
|
||||
|
@ -1464,7 +1467,7 @@ static int onenand_read_oob(struct mtd_info *mtd, loff_t from,
|
|||
|
||||
onenand_get_device(mtd, FL_READING);
|
||||
if (ops->datbuf)
|
||||
ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ?
|
||||
ret = ONENAND_IS_4KB_PAGE(this) ?
|
||||
onenand_mlc_read_ops_nolock(mtd, from, ops) :
|
||||
onenand_read_ops_nolock(mtd, from, ops);
|
||||
else
|
||||
|
@ -1485,8 +1488,7 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state)
|
|||
{
|
||||
struct onenand_chip *this = mtd->priv;
|
||||
unsigned long timeout;
|
||||
unsigned int interrupt;
|
||||
unsigned int ctrl;
|
||||
unsigned int interrupt, ctrl, ecc, addr1, addr8;
|
||||
|
||||
/* The 20 msec is enough */
|
||||
timeout = jiffies + msecs_to_jiffies(20);
|
||||
|
@ -1498,25 +1500,28 @@ static int onenand_bbt_wait(struct mtd_info *mtd, int state)
|
|||
/* To get correct interrupt status in timeout case */
|
||||
interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);
|
||||
ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
|
||||
addr1 = this->read_word(this->base + ONENAND_REG_START_ADDRESS1);
|
||||
addr8 = this->read_word(this->base + ONENAND_REG_START_ADDRESS8);
|
||||
|
||||
if (interrupt & ONENAND_INT_READ) {
|
||||
int ecc = onenand_read_ecc(this);
|
||||
ecc = onenand_read_ecc(this);
|
||||
if (ecc & ONENAND_ECC_2BIT_ALL) {
|
||||
printk(KERN_WARNING "%s: ecc error = 0x%04x, "
|
||||
"controller error 0x%04x\n",
|
||||
__func__, ecc, ctrl);
|
||||
printk(KERN_DEBUG "%s: ecc 0x%04x ctrl 0x%04x "
|
||||
"intr 0x%04x addr1 %#x addr8 %#x\n",
|
||||
__func__, ecc, ctrl, interrupt, addr1, addr8);
|
||||
return ONENAND_BBT_READ_ECC_ERROR;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_ERR "%s: read timeout! ctrl=0x%04x intr=0x%04x\n",
|
||||
__func__, ctrl, interrupt);
|
||||
printk(KERN_ERR "%s: read timeout! ctrl 0x%04x "
|
||||
"intr 0x%04x addr1 %#x addr8 %#x\n",
|
||||
__func__, ctrl, interrupt, addr1, addr8);
|
||||
return ONENAND_BBT_READ_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* Initial bad block case: 0x2400 or 0x0400 */
|
||||
if (ctrl & ONENAND_CTRL_ERROR) {
|
||||
printk(KERN_DEBUG "%s: controller error = 0x%04x\n",
|
||||
__func__, ctrl);
|
||||
printk(KERN_DEBUG "%s: ctrl 0x%04x intr 0x%04x addr1 %#x "
|
||||
"addr8 %#x\n", __func__, ctrl, interrupt, addr1, addr8);
|
||||
return ONENAND_BBT_READ_ERROR;
|
||||
}
|
||||
|
||||
|
@ -1558,7 +1563,7 @@ int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from,
|
|||
|
||||
column = from & (mtd->oobsize - 1);
|
||||
|
||||
readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
|
||||
readcmd = ONENAND_IS_4KB_PAGE(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
|
||||
|
||||
while (read < len) {
|
||||
cond_resched();
|
||||
|
@ -1612,7 +1617,7 @@ static int onenand_verify_oob(struct mtd_info *mtd, const u_char *buf, loff_t to
|
|||
u_char *oob_buf = this->oob_buf;
|
||||
int status, i, readcmd;
|
||||
|
||||
readcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
|
||||
readcmd = ONENAND_IS_4KB_PAGE(this) ? ONENAND_CMD_READ : ONENAND_CMD_READOOB;
|
||||
|
||||
this->command(mtd, readcmd, to, mtd->oobsize);
|
||||
onenand_update_bufferram(mtd, to, 0);
|
||||
|
@ -1845,7 +1850,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
|
|||
const u_char *buf = ops->datbuf;
|
||||
const u_char *oob = ops->oobbuf;
|
||||
u_char *oobbuf;
|
||||
int ret = 0;
|
||||
int ret = 0, cmd;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
|
||||
__func__, (unsigned int) to, (int) len);
|
||||
|
@ -1954,7 +1959,19 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
|
|||
ONENAND_SET_NEXT_BUFFERRAM(this);
|
||||
}
|
||||
|
||||
this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);
|
||||
this->ongoing = 0;
|
||||
cmd = ONENAND_CMD_PROG;
|
||||
|
||||
/* Exclude 1st OTP and OTP blocks for cache program feature */
|
||||
if (ONENAND_IS_CACHE_PROGRAM(this) &&
|
||||
likely(onenand_block(this, to) != 0) &&
|
||||
ONENAND_IS_4KB_PAGE(this) &&
|
||||
((written + thislen) < len)) {
|
||||
cmd = ONENAND_CMD_2X_CACHE_PROG;
|
||||
this->ongoing = 1;
|
||||
}
|
||||
|
||||
this->command(mtd, cmd, to, mtd->writesize);
|
||||
|
||||
/*
|
||||
* 2 PLANE, MLC, and Flex-OneNAND wait here
|
||||
|
@ -2067,7 +2084,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
|
|||
|
||||
oobbuf = this->oob_buf;
|
||||
|
||||
oobcmd = ONENAND_IS_MLC(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
|
||||
oobcmd = ONENAND_IS_4KB_PAGE(this) ? ONENAND_CMD_PROG : ONENAND_CMD_PROGOOB;
|
||||
|
||||
/* Loop until all data write */
|
||||
while (written < len) {
|
||||
|
@ -2086,7 +2103,7 @@ static int onenand_write_oob_nolock(struct mtd_info *mtd, loff_t to,
|
|||
memcpy(oobbuf + column, buf, thislen);
|
||||
this->write_bufferram(mtd, ONENAND_SPARERAM, oobbuf, 0, mtd->oobsize);
|
||||
|
||||
if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this)) {
|
||||
if (ONENAND_IS_4KB_PAGE(this)) {
|
||||
/* Set main area of DataRAM to 0xff*/
|
||||
memset(this->page_buf, 0xff, mtd->writesize);
|
||||
this->write_bufferram(mtd, ONENAND_DATARAM,
|
||||
|
@ -2481,7 +2498,8 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
|
|||
/* Grab the lock and see if the device is available */
|
||||
onenand_get_device(mtd, FL_ERASING);
|
||||
|
||||
if (region || instr->len < MB_ERASE_MIN_BLK_COUNT * block_size) {
|
||||
if (ONENAND_IS_4KB_PAGE(this) || region ||
|
||||
instr->len < MB_ERASE_MIN_BLK_COUNT * block_size) {
|
||||
/* region is set for Flex-OneNAND (no mb erase) */
|
||||
ret = onenand_block_by_block_erase(mtd, instr,
|
||||
region, block_size);
|
||||
|
@ -3029,7 +3047,7 @@ static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
|
|||
this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
|
||||
this->wait(mtd, FL_OTPING);
|
||||
|
||||
ret = ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this) ?
|
||||
ret = ONENAND_IS_4KB_PAGE(this) ?
|
||||
onenand_mlc_read_ops_nolock(mtd, from, &ops) :
|
||||
onenand_read_ops_nolock(mtd, from, &ops);
|
||||
|
||||
|
@ -3377,8 +3395,10 @@ static void onenand_check_features(struct mtd_info *mtd)
|
|||
case ONENAND_DEVICE_DENSITY_4Gb:
|
||||
if (ONENAND_IS_DDP(this))
|
||||
this->options |= ONENAND_HAS_2PLANE;
|
||||
else if (numbufs == 1)
|
||||
else if (numbufs == 1) {
|
||||
this->options |= ONENAND_HAS_4KB_PAGE;
|
||||
this->options |= ONENAND_HAS_CACHE_PROGRAM;
|
||||
}
|
||||
|
||||
case ONENAND_DEVICE_DENSITY_2Gb:
|
||||
/* 2Gb DDP does not have 2 plane */
|
||||
|
@ -3399,7 +3419,11 @@ static void onenand_check_features(struct mtd_info *mtd)
|
|||
break;
|
||||
}
|
||||
|
||||
if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this))
|
||||
/* The MLC has 4KiB pagesize. */
|
||||
if (ONENAND_IS_MLC(this))
|
||||
this->options |= ONENAND_HAS_4KB_PAGE;
|
||||
|
||||
if (ONENAND_IS_4KB_PAGE(this))
|
||||
this->options &= ~ONENAND_HAS_2PLANE;
|
||||
|
||||
if (FLEXONENAND(this)) {
|
||||
|
@ -3415,6 +3439,8 @@ static void onenand_check_features(struct mtd_info *mtd)
|
|||
printk(KERN_DEBUG "Chip has 2 plane\n");
|
||||
if (this->options & ONENAND_HAS_4KB_PAGE)
|
||||
printk(KERN_DEBUG "Chip has 4KiB pagesize\n");
|
||||
if (this->options & ONENAND_HAS_CACHE_PROGRAM)
|
||||
printk(KERN_DEBUG "Chip has cache program feature\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3831,7 +3857,7 @@ static int onenand_probe(struct mtd_info *mtd)
|
|||
/* The data buffer size is equal to page size */
|
||||
mtd->writesize = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE);
|
||||
/* We use the full BufferRAM */
|
||||
if (ONENAND_IS_MLC(this) || ONENAND_IS_4KB_PAGE(this))
|
||||
if (ONENAND_IS_4KB_PAGE(this))
|
||||
mtd->writesize <<= 1;
|
||||
|
||||
mtd->oobsize = mtd->writesize >> 5;
|
||||
|
@ -4054,6 +4080,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
|
|||
mtd->block_isbad = onenand_block_isbad;
|
||||
mtd->block_markbad = onenand_block_markbad;
|
||||
mtd->owner = THIS_MODULE;
|
||||
mtd->writebufsize = mtd->writesize;
|
||||
|
||||
/* Unlock whole block */
|
||||
this->unlock_all(mtd);
|
||||
|
|
|
@ -91,16 +91,18 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
|
|||
for (j = 0; j < len; j++) {
|
||||
/* No need to read pages fully,
|
||||
* just read required OOB bytes */
|
||||
ret = onenand_bbt_read_oob(mtd, from + j * mtd->writesize + bd->offs, &ops);
|
||||
ret = onenand_bbt_read_oob(mtd,
|
||||
from + j * this->writesize + bd->offs, &ops);
|
||||
|
||||
/* If it is a initial bad block, just ignore it */
|
||||
if (ret == ONENAND_BBT_READ_FATAL_ERROR)
|
||||
return -EIO;
|
||||
|
||||
if (ret || check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
|
||||
if (ret || check_short_pattern(&buf[j * scanlen],
|
||||
scanlen, this->writesize, bd)) {
|
||||
bbm->bbt[i >> 3] |= 0x03 << (i & 0x6);
|
||||
printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n",
|
||||
i >> 1, (unsigned int) from);
|
||||
printk(KERN_INFO "OneNAND eraseblock %d is an "
|
||||
"initial bad block\n", i >> 1);
|
||||
mtd->ecc_stats.badblocks++;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -651,7 +651,7 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
|
|||
void __iomem *p;
|
||||
void *buf = (void *) buffer;
|
||||
dma_addr_t dma_src, dma_dst;
|
||||
int err, page_dma = 0;
|
||||
int err, ofs, page_dma = 0;
|
||||
struct device *dev = &onenand->pdev->dev;
|
||||
|
||||
p = this->base + area;
|
||||
|
@ -677,10 +677,13 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
|
|||
if (!page)
|
||||
goto normal;
|
||||
|
||||
/* Page offset */
|
||||
ofs = ((size_t) buf & ~PAGE_MASK);
|
||||
page_dma = 1;
|
||||
|
||||
/* DMA routine */
|
||||
dma_src = onenand->phys_base + (p - this->base);
|
||||
dma_dst = dma_map_page(dev, page, 0, count, DMA_FROM_DEVICE);
|
||||
dma_dst = dma_map_page(dev, page, ofs, count, DMA_FROM_DEVICE);
|
||||
} else {
|
||||
/* DMA routine */
|
||||
dma_src = onenand->phys_base + (p - this->base);
|
||||
|
|
|
@ -672,7 +672,33 @@ static int io_init(struct ubi_device *ubi)
|
|||
ubi->nor_flash = 1;
|
||||
}
|
||||
|
||||
ubi->min_io_size = ubi->mtd->writesize;
|
||||
/*
|
||||
* Set UBI min. I/O size (@ubi->min_io_size). We use @mtd->writebufsize
|
||||
* for these purposes, not @mtd->writesize. At the moment this does not
|
||||
* matter for NAND, because currently @mtd->writebufsize is equivalent to
|
||||
* @mtd->writesize for all NANDs. However, some CFI NOR flashes may
|
||||
* have @mtd->writebufsize which is multiple of @mtd->writesize.
|
||||
*
|
||||
* The reason we use @mtd->writebufsize for @ubi->min_io_size is that
|
||||
* UBI and UBIFS recovery algorithms rely on the fact that if there was
|
||||
* an unclean power cut, then we can find offset of the last corrupted
|
||||
* node, align the offset to @ubi->min_io_size, read the rest of the
|
||||
* eraseblock starting from this offset, and check whether there are
|
||||
* only 0xFF bytes. If yes, then we are probably dealing with a
|
||||
* corruption caused by a power cut, if not, then this is probably some
|
||||
* severe corruption.
|
||||
*
|
||||
* Thus, we have to use the maximum write unit size of the flash, which
|
||||
* is @mtd->writebufsize, because @mtd->writesize is the minimum write
|
||||
* size, not the maximum.
|
||||
*/
|
||||
if (ubi->mtd->type == MTD_NANDFLASH)
|
||||
ubi_assert(ubi->mtd->writebufsize == ubi->mtd->writesize);
|
||||
else if (ubi->mtd->type == MTD_NORFLASH)
|
||||
ubi_assert(ubi->mtd->writebufsize % ubi->mtd->writesize == 0);
|
||||
|
||||
ubi->min_io_size = ubi->mtd->writebufsize;
|
||||
|
||||
ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
|
||||
|
||||
/*
|
||||
|
|
|
@ -425,12 +425,11 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
|
|||
|
||||
/* Read both LEB 0 and LEB 1 into memory */
|
||||
ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) {
|
||||
leb[seb->lnum] = vmalloc(ubi->vtbl_size);
|
||||
leb[seb->lnum] = vzalloc(ubi->vtbl_size);
|
||||
if (!leb[seb->lnum]) {
|
||||
err = -ENOMEM;
|
||||
goto out_free;
|
||||
}
|
||||
memset(leb[seb->lnum], 0, ubi->vtbl_size);
|
||||
|
||||
err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0,
|
||||
ubi->vtbl_size);
|
||||
|
@ -516,10 +515,9 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
|
|||
int i;
|
||||
struct ubi_vtbl_record *vtbl;
|
||||
|
||||
vtbl = vmalloc(ubi->vtbl_size);
|
||||
vtbl = vzalloc(ubi->vtbl_size);
|
||||
if (!vtbl)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
memset(vtbl, 0, ubi->vtbl_size);
|
||||
|
||||
for (i = 0; i < ubi->vtbl_slots; i++)
|
||||
memcpy(&vtbl[i], &empty_vtbl_record, UBI_VTBL_RECORD_SIZE);
|
||||
|
|
|
@ -336,14 +336,13 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
|
|||
size = sizeof(struct jffs2_eraseblock) * c->nr_blocks;
|
||||
#ifndef __ECOS
|
||||
if (jffs2_blocks_use_vmalloc(c))
|
||||
c->blocks = vmalloc(size);
|
||||
c->blocks = vzalloc(size);
|
||||
else
|
||||
#endif
|
||||
c->blocks = kmalloc(size, GFP_KERNEL);
|
||||
c->blocks = kzalloc(size, GFP_KERNEL);
|
||||
if (!c->blocks)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(c->blocks, 0, size);
|
||||
for (i=0; i<c->nr_blocks; i++) {
|
||||
INIT_LIST_HEAD(&c->blocks[i].list);
|
||||
c->blocks[i].offset = i * c->sector_size;
|
||||
|
|
|
@ -144,4 +144,4 @@ struct jffs2_sb_info {
|
|||
void *os_priv;
|
||||
};
|
||||
|
||||
#endif /* _JFFS2_FB_SB */
|
||||
#endif /* _JFFS2_FS_SB */
|
||||
|
|
|
@ -151,7 +151,7 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
|
|||
JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
|
||||
offset, je32_to_cpu(rx.hdr_crc), crc);
|
||||
xd->flags |= JFFS2_XFLAGS_INVALID;
|
||||
return EIO;
|
||||
return -EIO;
|
||||
}
|
||||
totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len));
|
||||
if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK
|
||||
|
@ -167,7 +167,7 @@ static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_dat
|
|||
je32_to_cpu(rx.xid), xd->xid,
|
||||
je32_to_cpu(rx.version), xd->version);
|
||||
xd->flags |= JFFS2_XFLAGS_INVALID;
|
||||
return EIO;
|
||||
return -EIO;
|
||||
}
|
||||
xd->xprefix = rx.xprefix;
|
||||
xd->name_len = rx.name_len;
|
||||
|
@ -230,7 +230,7 @@ static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum
|
|||
ref_offset(xd->node), xd->data_crc, crc);
|
||||
kfree(data);
|
||||
xd->flags |= JFFS2_XFLAGS_INVALID;
|
||||
return EIO;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
xd->flags |= JFFS2_XFLAGS_HOT;
|
||||
|
@ -268,7 +268,7 @@ static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *x
|
|||
if (xd->xname)
|
||||
return 0;
|
||||
if (xd->flags & JFFS2_XFLAGS_INVALID)
|
||||
return EIO;
|
||||
return -EIO;
|
||||
if (unlikely(is_xattr_datum_unchecked(c, xd)))
|
||||
rc = do_verify_xattr_datum(c, xd);
|
||||
if (!rc)
|
||||
|
@ -460,7 +460,7 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
|
|||
if (crc != je32_to_cpu(rr.node_crc)) {
|
||||
JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n",
|
||||
offset, je32_to_cpu(rr.node_crc), crc);
|
||||
return EIO;
|
||||
return -EIO;
|
||||
}
|
||||
if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK
|
||||
|| je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF
|
||||
|
@ -470,7 +470,7 @@ static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref
|
|||
offset, je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK,
|
||||
je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF,
|
||||
je32_to_cpu(rr.totlen), PAD(sizeof(rr)));
|
||||
return EIO;
|
||||
return -EIO;
|
||||
}
|
||||
ref->ino = je32_to_cpu(rr.ino);
|
||||
ref->xid = je32_to_cpu(rr.xid);
|
||||
|
|
|
@ -527,8 +527,7 @@ struct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t s
|
|||
struct cfi_fixup {
|
||||
uint16_t mfr;
|
||||
uint16_t id;
|
||||
void (*fixup)(struct mtd_info *mtd, void* param);
|
||||
void* param;
|
||||
void (*fixup)(struct mtd_info *mtd);
|
||||
};
|
||||
|
||||
#define CFI_MFR_ANY 0xFFFF
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifndef __MTD_FSMC_H
|
||||
#define __MTD_FSMC_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -27,7 +28,7 @@
|
|||
|
||||
/*
|
||||
* The placement of the Command Latch Enable (CLE) and
|
||||
* Address Latch Enable (ALE) is twised around in the
|
||||
* Address Latch Enable (ALE) is twisted around in the
|
||||
* SPEAR310 implementation.
|
||||
*/
|
||||
#if defined(CONFIG_MACH_SPEAR310)
|
||||
|
@ -62,7 +63,7 @@ struct fsmc_nor_bank_regs {
|
|||
|
||||
/* ctrl_tim register definitions */
|
||||
|
||||
struct fsms_nand_bank_regs {
|
||||
struct fsmc_nand_bank_regs {
|
||||
uint32_t pc;
|
||||
uint32_t sts;
|
||||
uint32_t comm;
|
||||
|
@ -78,7 +79,7 @@ struct fsms_nand_bank_regs {
|
|||
struct fsmc_regs {
|
||||
struct fsmc_nor_bank_regs nor_bank_regs[FSMC_MAX_NOR_BANKS];
|
||||
uint8_t reserved_1[0x40 - 0x20];
|
||||
struct fsms_nand_bank_regs bank_regs[FSMC_MAX_NAND_BANKS];
|
||||
struct fsmc_nand_bank_regs bank_regs[FSMC_MAX_NAND_BANKS];
|
||||
uint8_t reserved_2[0xfe0 - 0xc0];
|
||||
uint32_t peripid0; /* 0xfe0 */
|
||||
uint32_t peripid1; /* 0xfe4 */
|
||||
|
@ -114,25 +115,6 @@ struct fsmc_regs {
|
|||
#define FSMC_THOLD_4 (4 << 16)
|
||||
#define FSMC_THIZ_1 (1 << 24)
|
||||
|
||||
/* peripid2 register definitions */
|
||||
#define FSMC_REVISION_MSK (0xf)
|
||||
#define FSMC_REVISION_SHFT (0x4)
|
||||
|
||||
#define FSMC_VER1 1
|
||||
#define FSMC_VER2 2
|
||||
#define FSMC_VER3 3
|
||||
#define FSMC_VER4 4
|
||||
#define FSMC_VER5 5
|
||||
#define FSMC_VER6 6
|
||||
#define FSMC_VER7 7
|
||||
#define FSMC_VER8 8
|
||||
|
||||
static inline uint32_t get_fsmc_version(struct fsmc_regs *regs)
|
||||
{
|
||||
return (readl(®s->peripid2) >> FSMC_REVISION_SHFT) &
|
||||
FSMC_REVISION_MSK;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are 13 bytes of ecc for every 512 byte block in FSMC version 8
|
||||
* and it has to be read consecutively and immediately after the 512
|
||||
|
|
|
@ -144,6 +144,17 @@ struct mtd_info {
|
|||
*/
|
||||
uint32_t writesize;
|
||||
|
||||
/*
|
||||
* Size of the write buffer used by the MTD. MTD devices having a write
|
||||
* buffer can write multiple writesize chunks at a time. E.g. while
|
||||
* writing 4 * writesize bytes to a device with 2 * writesize bytes
|
||||
* buffer the MTD driver can (but doesn't have to) do 2 writesize
|
||||
* operations, but not 4. Currently, all NANDs have writebufsize
|
||||
* equivalent to writesize (NAND page size). Some NOR flashes do have
|
||||
* writebufsize greater than writesize.
|
||||
*/
|
||||
uint32_t writebufsize;
|
||||
|
||||
uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
|
||||
uint32_t oobavail; // Available OOB bytes per block
|
||||
|
||||
|
|
|
@ -448,6 +448,8 @@ struct nand_buffers {
|
|||
* See the defines for further explanation.
|
||||
* @badblockpos: [INTERN] position of the bad block marker in the oob
|
||||
* area.
|
||||
* @badblockbits: [INTERN] number of bits to left-shift the bad block
|
||||
* number
|
||||
* @cellinfo: [INTERN] MLC/multichip data from chip ident
|
||||
* @numchips: [INTERN] number of physical chips
|
||||
* @chipsize: [INTERN] the size of one chip for multichip arrays
|
||||
|
|
|
@ -118,6 +118,8 @@ struct onenand_chip {
|
|||
int (*chip_probe)(struct mtd_info *mtd);
|
||||
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
|
||||
int (*scan_bbt)(struct mtd_info *mtd);
|
||||
int (*enable)(struct mtd_info *mtd);
|
||||
int (*disable)(struct mtd_info *mtd);
|
||||
|
||||
struct completion complete;
|
||||
int irq;
|
||||
|
@ -137,6 +139,14 @@ struct onenand_chip {
|
|||
void *bbm;
|
||||
|
||||
void *priv;
|
||||
|
||||
/*
|
||||
* Shows that the current operation is composed
|
||||
* of sequence of commands. For example, cache program.
|
||||
* Such command status OnGo bit is checked at the end of
|
||||
* sequence.
|
||||
*/
|
||||
unsigned int ongoing;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -171,6 +181,9 @@ struct onenand_chip {
|
|||
#define ONENAND_IS_2PLANE(this) (0)
|
||||
#endif
|
||||
|
||||
#define ONENAND_IS_CACHE_PROGRAM(this) \
|
||||
(this->options & ONENAND_HAS_CACHE_PROGRAM)
|
||||
|
||||
/* Check byte access in OneNAND */
|
||||
#define ONENAND_CHECK_BYTE_ACCESS(addr) (addr & 0x1)
|
||||
|
||||
|
@ -181,6 +194,7 @@ struct onenand_chip {
|
|||
#define ONENAND_HAS_UNLOCK_ALL (0x0002)
|
||||
#define ONENAND_HAS_2PLANE (0x0004)
|
||||
#define ONENAND_HAS_4KB_PAGE (0x0008)
|
||||
#define ONENAND_HAS_CACHE_PROGRAM (0x0010)
|
||||
#define ONENAND_SKIP_UNLOCK_CHECK (0x0100)
|
||||
#define ONENAND_PAGEBUF_ALLOC (0x1000)
|
||||
#define ONENAND_OOBBUF_ALLOC (0x2000)
|
||||
|
|
|
@ -89,7 +89,7 @@ static inline int mtd_has_cmdlinepart(void) { return 1; }
|
|||
static inline int mtd_has_cmdlinepart(void) { return 0; }
|
||||
#endif
|
||||
|
||||
int mtd_is_master(struct mtd_info *mtd);
|
||||
int mtd_is_partition(struct mtd_info *mtd);
|
||||
int mtd_add_partition(struct mtd_info *master, char *name,
|
||||
long long offset, long long length);
|
||||
int mtd_del_partition(struct mtd_info *master, int partno);
|
||||
|
|
Loading…
Reference in New Issue