Commit ab2020f2 authored by Linus Torvalds's avatar Linus Torvalds

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.
parents 235646a4 154bf89f
......@@ -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 @@ static int sst25l_write(struct mtd_info *mtd, loff_t to, size_t len,
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;
}
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_cleanup);
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 = {
}
};
/*
* 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}
#ifdef CONFIG_MTD_PARTITIONS
/*
* Default partition tables to be used if the partition information not
* 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 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
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 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
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 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
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 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
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(&regs->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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment