You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (67 commits)
[MTD] [MAPS] Fix printk format warning in nettel.c
[MTD] [NAND] add cmdline parsing (mtdparts=) support to cafe_nand
[MTD] CFI: remove major/minor version check for command set 0x0002
[MTD] [NAND] ndfc driver
[MTD] [TESTS] Fix some size_t printk format warnings
[MTD] LPDDR Makefile and KConfig
[MTD] LPDDR extended physmap driver to support LPDDR flash
[MTD] LPDDR added new pfow_base parameter
[MTD] LPDDR Command set driver
[MTD] LPDDR PFOW definition
[MTD] LPDDR QINFO records definitions
[MTD] LPDDR qinfo probing.
[MTD] [NAND] pxa3xx: convert from ns to clock ticks more accurately
[MTD] [NAND] pxa3xx: fix non-page-aligned reads
[MTD] [NAND] fix nandsim sched.h references
[MTD] [NAND] alauda: use USB API functions rather than constants
[MTD] struct device - replace bus_id with dev_name(), dev_set_name()
[MTD] fix m25p80 64-bit divisions
[MTD] fix dataflash 64-bit divisions
[MTD] [NAND] Set the fsl elbc ECCM according the settings in bootloader.
...
Fixed up trivial debug conflicts in drivers/mtd/devices/{m25p80.c,mtd_dataflash.c}
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
AMCC NDFC (NanD Flash Controller)
|
||||
|
||||
Required properties:
|
||||
- compatible : "ibm,ndfc".
|
||||
- reg : should specify chip select and size used for the chip (0x2000).
|
||||
|
||||
Optional properties:
|
||||
- ccr : NDFC config and control register value (default 0).
|
||||
- bank-settings : NDFC bank configuration register value (default 0).
|
||||
|
||||
Notes:
|
||||
- partition(s) - follows the OF MTD standard for partitions
|
||||
|
||||
Example:
|
||||
|
||||
ndfc@1,0 {
|
||||
compatible = "ibm,ndfc";
|
||||
reg = <0x00000001 0x00000000 0x00002000>;
|
||||
ccr = <0x00001000>;
|
||||
bank-settings = <0x80002222>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
nand {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
partition@0 {
|
||||
label = "kernel";
|
||||
reg = <0x00000000 0x00200000>;
|
||||
};
|
||||
partition@200000 {
|
||||
label = "root";
|
||||
reg = <0x00200000 0x03E00000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
#include <linux/spi/corgi_lcd.h>
|
||||
#include <linux/mtd/sharpsl.h>
|
||||
#include <video/w100fb.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
@@ -542,6 +543,55 @@ err_free_1:
|
||||
static inline void corgi_init_spi(void) {}
|
||||
#endif
|
||||
|
||||
static struct mtd_partition sharpsl_nand_partitions[] = {
|
||||
{
|
||||
.name = "System Area",
|
||||
.offset = 0,
|
||||
.size = 7 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "Root Filesystem",
|
||||
.offset = 7 * 1024 * 1024,
|
||||
.size = 25 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "Home Filesystem",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
},
|
||||
};
|
||||
|
||||
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
|
||||
|
||||
static struct nand_bbt_descr sharpsl_bbt = {
|
||||
.options = 0,
|
||||
.offs = 4,
|
||||
.len = 2,
|
||||
.pattern = scan_ff_pattern
|
||||
};
|
||||
|
||||
static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = {
|
||||
.badblock_pattern = &sharpsl_bbt,
|
||||
.partitions = sharpsl_nand_partitions,
|
||||
.nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions),
|
||||
};
|
||||
|
||||
static struct resource sharpsl_nand_resources[] = {
|
||||
{
|
||||
.start = 0x0C000000,
|
||||
.end = 0x0C000FFF,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device sharpsl_nand_device = {
|
||||
.name = "sharpsl-nand",
|
||||
.id = -1,
|
||||
.resource = sharpsl_nand_resources,
|
||||
.num_resources = ARRAY_SIZE(sharpsl_nand_resources),
|
||||
.dev.platform_data = &sharpsl_nand_platform_data,
|
||||
};
|
||||
|
||||
static struct mtd_partition sharpsl_rom_parts[] = {
|
||||
{
|
||||
.name ="Boot PROM Filesystem",
|
||||
@@ -577,6 +627,7 @@ static struct platform_device *devices[] __initdata = {
|
||||
&corgifb_device,
|
||||
&corgikbd_device,
|
||||
&corgiled_device,
|
||||
&sharpsl_nand_device,
|
||||
&sharpsl_rom_device,
|
||||
};
|
||||
|
||||
@@ -617,6 +668,9 @@ static void __init corgi_init(void)
|
||||
|
||||
platform_scoop_config = &corgi_pcmcia_config;
|
||||
|
||||
if (machine_is_husky())
|
||||
sharpsl_nand_partitions[1].size = 53 * 1024 * 1024;
|
||||
|
||||
platform_add_devices(devices, ARRAY_SIZE(devices));
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
#include <linux/mtd/sharpsl.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
@@ -414,6 +415,55 @@ static struct pxafb_mach_info poodle_fb_info = {
|
||||
.lcd_conn = LCD_COLOR_TFT_16BPP,
|
||||
};
|
||||
|
||||
static struct mtd_partition sharpsl_nand_partitions[] = {
|
||||
{
|
||||
.name = "System Area",
|
||||
.offset = 0,
|
||||
.size = 7 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "Root Filesystem",
|
||||
.offset = 7 * 1024 * 1024,
|
||||
.size = 22 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "Home Filesystem",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
},
|
||||
};
|
||||
|
||||
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
|
||||
|
||||
static struct nand_bbt_descr sharpsl_bbt = {
|
||||
.options = 0,
|
||||
.offs = 4,
|
||||
.len = 2,
|
||||
.pattern = scan_ff_pattern
|
||||
};
|
||||
|
||||
static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = {
|
||||
.badblock_pattern = &sharpsl_bbt,
|
||||
.partitions = sharpsl_nand_partitions,
|
||||
.nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions),
|
||||
};
|
||||
|
||||
static struct resource sharpsl_nand_resources[] = {
|
||||
{
|
||||
.start = 0x0C000000,
|
||||
.end = 0x0C000FFF,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device sharpsl_nand_device = {
|
||||
.name = "sharpsl-nand",
|
||||
.id = -1,
|
||||
.resource = sharpsl_nand_resources,
|
||||
.num_resources = ARRAY_SIZE(sharpsl_nand_resources),
|
||||
.dev.platform_data = &sharpsl_nand_platform_data,
|
||||
};
|
||||
|
||||
static struct mtd_partition sharpsl_rom_parts[] = {
|
||||
{
|
||||
.name ="Boot PROM Filesystem",
|
||||
@@ -447,6 +497,7 @@ static struct platform_device sharpsl_rom_device = {
|
||||
static struct platform_device *devices[] __initdata = {
|
||||
&poodle_locomo_device,
|
||||
&poodle_scoop_device,
|
||||
&sharpsl_nand_device,
|
||||
&sharpsl_rom_device,
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/ads7846.h>
|
||||
#include <linux/spi/corgi_lcd.h>
|
||||
#include <linux/mtd/sharpsl.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/memory.h>
|
||||
@@ -613,6 +614,54 @@ static struct pxafb_mach_info spitz_pxafb_info = {
|
||||
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_ALTERNATE_MAPPING,
|
||||
};
|
||||
|
||||
static struct mtd_partition sharpsl_nand_partitions[] = {
|
||||
{
|
||||
.name = "System Area",
|
||||
.offset = 0,
|
||||
.size = 7 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "Root Filesystem",
|
||||
.offset = 7 * 1024 * 1024,
|
||||
},
|
||||
{
|
||||
.name = "Home Filesystem",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
},
|
||||
};
|
||||
|
||||
static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
|
||||
|
||||
static struct nand_bbt_descr sharpsl_bbt = {
|
||||
.options = 0,
|
||||
.offs = 4,
|
||||
.len = 2,
|
||||
.pattern = scan_ff_pattern
|
||||
};
|
||||
|
||||
static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = {
|
||||
.badblock_pattern = &sharpsl_bbt,
|
||||
.partitions = sharpsl_nand_partitions,
|
||||
.nr_partitions = ARRAY_SIZE(sharpsl_nand_partitions),
|
||||
};
|
||||
|
||||
static struct resource sharpsl_nand_resources[] = {
|
||||
{
|
||||
.start = 0x0C000000,
|
||||
.end = 0x0C000FFF,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device sharpsl_nand_device = {
|
||||
.name = "sharpsl-nand",
|
||||
.id = -1,
|
||||
.resource = sharpsl_nand_resources,
|
||||
.num_resources = ARRAY_SIZE(sharpsl_nand_resources),
|
||||
.dev.platform_data = &sharpsl_nand_platform_data,
|
||||
};
|
||||
|
||||
|
||||
static struct mtd_partition sharpsl_rom_parts[] = {
|
||||
{
|
||||
@@ -648,6 +697,7 @@ static struct platform_device *devices[] __initdata = {
|
||||
&spitzscoop_device,
|
||||
&spitzkbd_device,
|
||||
&spitzled_device,
|
||||
&sharpsl_nand_device,
|
||||
&sharpsl_rom_device,
|
||||
};
|
||||
|
||||
@@ -671,6 +721,14 @@ static void __init common_init(void)
|
||||
pm_power_off = spitz_poweroff;
|
||||
arm_pm_restart = spitz_restart;
|
||||
|
||||
if (machine_is_spitz()) {
|
||||
sharpsl_nand_partitions[1].size = 5 * 1024 * 1024;
|
||||
} else if (machine_is_akita()) {
|
||||
sharpsl_nand_partitions[1].size = 58 * 1024 * 1024;
|
||||
} else if (machine_is_borzoi()) {
|
||||
sharpsl_nand_partitions[1].size = 32 * 1024 * 1024;
|
||||
}
|
||||
|
||||
PMCR = 0x00;
|
||||
|
||||
/* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
|
||||
@@ -715,10 +773,29 @@ static struct i2c_board_info akita_i2c_board_info[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct nand_bbt_descr sharpsl_akita_bbt = {
|
||||
.options = 0,
|
||||
.offs = 4,
|
||||
.len = 1,
|
||||
.pattern = scan_ff_pattern
|
||||
};
|
||||
|
||||
static struct nand_ecclayout akita_oobinfo = {
|
||||
.eccbytes = 24,
|
||||
.eccpos = {
|
||||
0x5, 0x1, 0x2, 0x3, 0x6, 0x7, 0x15, 0x11,
|
||||
0x12, 0x13, 0x16, 0x17, 0x25, 0x21, 0x22, 0x23,
|
||||
0x26, 0x27, 0x35, 0x31, 0x32, 0x33, 0x36, 0x37},
|
||||
.oobfree = {{0x08, 0x09}}
|
||||
};
|
||||
|
||||
static void __init akita_init(void)
|
||||
{
|
||||
spitz_ficp_platform_data.transceiver_mode = akita_irda_transceiver_mode;
|
||||
|
||||
sharpsl_nand_platform_data.badblock_pattern = &sharpsl_akita_bbt;
|
||||
sharpsl_nand_platform_data.ecc_layout = &akita_oobinfo;
|
||||
|
||||
/* We just pretend the second element of the array doesn't exist */
|
||||
spitz_pcmcia_config.num_devs = 1;
|
||||
platform_scoop_config = &spitz_pcmcia_config;
|
||||
|
||||
@@ -45,6 +45,14 @@ config MTD_PARTITIONS
|
||||
devices. Partitioning on NFTL 'devices' is a different - that's the
|
||||
'normal' form of partitioning used on a block device.
|
||||
|
||||
config MTD_TESTS
|
||||
tristate "MTD tests support"
|
||||
depends on m
|
||||
help
|
||||
This option includes various MTD tests into compilation. The tests
|
||||
should normally be compiled as kernel modules. The modules perform
|
||||
various checks and verifications when loaded.
|
||||
|
||||
config MTD_REDBOOT_PARTS
|
||||
tristate "RedBoot partition table parsing"
|
||||
depends on MTD_PARTITIONS
|
||||
@@ -316,6 +324,8 @@ source "drivers/mtd/nand/Kconfig"
|
||||
|
||||
source "drivers/mtd/onenand/Kconfig"
|
||||
|
||||
source "drivers/mtd/lpddr/Kconfig"
|
||||
|
||||
source "drivers/mtd/ubi/Kconfig"
|
||||
|
||||
endif # MTD
|
||||
|
||||
@@ -29,6 +29,6 @@ obj-$(CONFIG_MTD_OOPS) += mtdoops.o
|
||||
nftl-objs := nftlcore.o nftlmount.o
|
||||
inftl-objs := inftlcore.o inftlmount.o
|
||||
|
||||
obj-y += chips/ maps/ devices/ nand/ onenand/
|
||||
obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/
|
||||
|
||||
obj-$(CONFIG_MTD_UBI) += ubi/
|
||||
|
||||
@@ -58,8 +58,8 @@ static int cfi_intelext_write_buffers(struct mtd_info *, loff_t, size_t, size_t
|
||||
static int cfi_intelext_writev(struct mtd_info *, const struct kvec *, unsigned long, loff_t, size_t *);
|
||||
static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *);
|
||||
static void cfi_intelext_sync (struct mtd_info *);
|
||||
static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
|
||||
static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
|
||||
static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
|
||||
static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
|
||||
#ifdef CONFIG_MTD_OTP
|
||||
static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
||||
static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
||||
@@ -558,8 +558,8 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
|
||||
}
|
||||
|
||||
for (i=0; i<mtd->numeraseregions;i++){
|
||||
printk(KERN_DEBUG "erase region %d: offset=0x%x,size=0x%x,blocks=%d\n",
|
||||
i,mtd->eraseregions[i].offset,
|
||||
printk(KERN_DEBUG "erase region %d: offset=0x%llx,size=0x%x,blocks=%d\n",
|
||||
i,(unsigned long long)mtd->eraseregions[i].offset,
|
||||
mtd->eraseregions[i].erasesize,
|
||||
mtd->eraseregions[i].numblocks);
|
||||
}
|
||||
@@ -2058,7 +2058,7 @@ out: put_chip(map, chip, adr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -2082,7 +2082,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -71,8 +71,8 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
|
||||
static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr);
|
||||
#include "fwh_lock.h"
|
||||
|
||||
static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
|
||||
static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
|
||||
static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
|
||||
static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
|
||||
|
||||
static struct mtd_chip_driver cfi_amdstd_chipdrv = {
|
||||
.probe = NULL, /* Not usable directly */
|
||||
@@ -322,6 +322,14 @@ static struct cfi_fixup fixup_table[] = {
|
||||
};
|
||||
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
||||
{
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
@@ -363,6 +371,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cfi_fixup_major_minor(cfi, extp);
|
||||
|
||||
if (extp->MajorVersion != '1' ||
|
||||
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
|
||||
printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
|
||||
@@ -1774,12 +1784,12 @@ out_unlock:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
static int cfi_atmel_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
return cfi_varsize_frob(mtd, do_atmel_lock, ofs, len, NULL);
|
||||
}
|
||||
|
||||
static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
static int cfi_atmel_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
return cfi_varsize_frob(mtd, do_atmel_unlock, ofs, len, NULL);
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ static int cfi_staa_writev(struct mtd_info *mtd, const struct kvec *vecs,
|
||||
unsigned long count, loff_t to, size_t *retlen);
|
||||
static int cfi_staa_erase_varsize(struct mtd_info *, struct erase_info *);
|
||||
static void cfi_staa_sync (struct mtd_info *);
|
||||
static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len);
|
||||
static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len);
|
||||
static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
|
||||
static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
|
||||
static int cfi_staa_suspend (struct mtd_info *);
|
||||
static void cfi_staa_resume (struct mtd_info *);
|
||||
|
||||
@@ -221,8 +221,8 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
|
||||
}
|
||||
|
||||
for (i=0; i<mtd->numeraseregions;i++){
|
||||
printk(KERN_DEBUG "%d: offset=0x%x,size=0x%x,blocks=%d\n",
|
||||
i,mtd->eraseregions[i].offset,
|
||||
printk(KERN_DEBUG "%d: offset=0x%llx,size=0x%x,blocks=%d\n",
|
||||
i, (unsigned long long)mtd->eraseregions[i].offset,
|
||||
mtd->eraseregions[i].erasesize,
|
||||
mtd->eraseregions[i].numblocks);
|
||||
}
|
||||
@@ -964,7 +964,7 @@ static int cfi_staa_erase_varsize(struct mtd_info *mtd,
|
||||
adr += regions[i].erasesize;
|
||||
len -= regions[i].erasesize;
|
||||
|
||||
if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
|
||||
if (adr % (1<< cfi->chipshift) == (((unsigned long)regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
|
||||
i++;
|
||||
|
||||
if (adr >> cfi->chipshift) {
|
||||
@@ -1135,7 +1135,7 @@ retry:
|
||||
spin_unlock_bh(chip->mutex);
|
||||
return 0;
|
||||
}
|
||||
static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
static int cfi_staa_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
@@ -1284,7 +1284,7 @@ retry:
|
||||
spin_unlock_bh(chip->mutex);
|
||||
return 0;
|
||||
}
|
||||
static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
static int cfi_staa_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
|
||||
@@ -77,7 +77,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
|
||||
}
|
||||
|
||||
|
||||
static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@@ -88,7 +88,7 @@ static int fwh_lock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
}
|
||||
|
||||
|
||||
static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, size_t len)
|
||||
static int fwh_unlock_varsize(struct mtd_info *mtd, loff_t ofs, uint64_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -619,7 +619,7 @@ static struct mtd_partition lart_partitions[] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
int __init lart_flash_init (void)
|
||||
static int __init lart_flash_init (void)
|
||||
{
|
||||
int result;
|
||||
memset (&mtd,0,sizeof (mtd));
|
||||
@@ -690,7 +690,7 @@ int __init lart_flash_init (void)
|
||||
return (result);
|
||||
}
|
||||
|
||||
void __exit lart_flash_exit (void)
|
||||
static void __exit lart_flash_exit (void)
|
||||
{
|
||||
#ifndef HAVE_PARTITIONS
|
||||
del_mtd_device (&mtd);
|
||||
@@ -705,5 +705,3 @@ module_exit (lart_flash_exit);
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Abraham vd Merwe <abraham@2d3d.co.za>");
|
||||
MODULE_DESCRIPTION("MTD driver for Intel 28F160F3 on LART board");
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/math64.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
@@ -169,9 +170,9 @@ static int wait_till_ready(struct m25p *flash)
|
||||
*/
|
||||
static int erase_chip(struct m25p *flash)
|
||||
{
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n",
|
||||
dev_name(&flash->spi->dev), __func__,
|
||||
flash->mtd.size / 1024);
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n",
|
||||
dev_name(&flash->spi->dev), __func__,
|
||||
(long long)(flash->mtd.size >> 10));
|
||||
|
||||
/* Wait until finished previous write command. */
|
||||
if (wait_till_ready(flash))
|
||||
@@ -232,18 +233,18 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
{
|
||||
struct m25p *flash = mtd_to_m25p(mtd);
|
||||
u32 addr,len;
|
||||
uint32_t rem;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n",
|
||||
dev_name(&flash->spi->dev), __func__, "at",
|
||||
(u32)instr->addr, instr->len);
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n",
|
||||
dev_name(&flash->spi->dev), __func__, "at",
|
||||
(long long)instr->addr, (long long)instr->len);
|
||||
|
||||
/* sanity checks */
|
||||
if (instr->addr + instr->len > flash->mtd.size)
|
||||
return -EINVAL;
|
||||
if ((instr->addr % mtd->erasesize) != 0
|
||||
|| (instr->len % mtd->erasesize) != 0) {
|
||||
div_u64_rem(instr->len, mtd->erasesize, &rem);
|
||||
if (rem)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addr = instr->addr;
|
||||
len = instr->len;
|
||||
@@ -677,24 +678,24 @@ static int __devinit m25p_probe(struct spi_device *spi)
|
||||
flash->mtd.erasesize = info->sector_size;
|
||||
}
|
||||
|
||||
dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name,
|
||||
flash->mtd.size / 1024);
|
||||
dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
|
||||
(long long)flash->mtd.size >> 10);
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2,
|
||||
"mtd .name = %s, .size = 0x%.8x (%uMiB) "
|
||||
"mtd .name = %s, .size = 0x%llx (%lldMiB) "
|
||||
".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
|
||||
flash->mtd.name,
|
||||
flash->mtd.size, flash->mtd.size / (1024*1024),
|
||||
(long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
|
||||
flash->mtd.erasesize, flash->mtd.erasesize / 1024,
|
||||
flash->mtd.numeraseregions);
|
||||
|
||||
if (flash->mtd.numeraseregions)
|
||||
for (i = 0; i < flash->mtd.numeraseregions; i++)
|
||||
DEBUG(MTD_DEBUG_LEVEL2,
|
||||
"mtd.eraseregions[%d] = { .offset = 0x%.8x, "
|
||||
"mtd.eraseregions[%d] = { .offset = 0x%llx, "
|
||||
".erasesize = 0x%.8x (%uKiB), "
|
||||
".numblocks = %d }\n",
|
||||
i, flash->mtd.eraseregions[i].offset,
|
||||
i, (long long)flash->mtd.eraseregions[i].offset,
|
||||
flash->mtd.eraseregions[i].erasesize,
|
||||
flash->mtd.eraseregions[i].erasesize / 1024,
|
||||
flash->mtd.eraseregions[i].numblocks);
|
||||
@@ -722,12 +723,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
|
||||
if (nr_parts > 0) {
|
||||
for (i = 0; i < nr_parts; i++) {
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
|
||||
"{.name = %s, .offset = 0x%.8x, "
|
||||
".size = 0x%.8x (%uKiB) }\n",
|
||||
"{.name = %s, .offset = 0x%llx, "
|
||||
".size = 0x%llx (%lldKiB) }\n",
|
||||
i, parts[i].name,
|
||||
parts[i].offset,
|
||||
parts[i].size,
|
||||
parts[i].size / 1024);
|
||||
(long long)parts[i].offset,
|
||||
(long long)parts[i].size,
|
||||
(long long)(parts[i].size >> 10));
|
||||
}
|
||||
flash->partitioned = 1;
|
||||
return add_mtd_partitions(&flash->mtd, parts, nr_parts);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/math64.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/flash.h>
|
||||
@@ -152,15 +153,20 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
struct spi_message msg;
|
||||
unsigned blocksize = priv->page_size << 3;
|
||||
uint8_t *command;
|
||||
uint32_t rem;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n",
|
||||
dev_name(&spi->dev),
|
||||
instr->addr, instr->len);
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n",
|
||||
dev_name(&spi->dev), (long long)instr->addr,
|
||||
(long long)instr->len);
|
||||
|
||||
/* Sanity checks */
|
||||
if ((instr->addr + instr->len) > mtd->size
|
||||
|| (instr->len % priv->page_size) != 0
|
||||
|| (instr->addr % priv->page_size) != 0)
|
||||
if (instr->addr + instr->len > mtd->size)
|
||||
return -EINVAL;
|
||||
div_u64_rem(instr->len, priv->page_size, &rem);
|
||||
if (rem)
|
||||
return -EINVAL;
|
||||
div_u64_rem(instr->addr, priv->page_size, &rem);
|
||||
if (rem)
|
||||
return -EINVAL;
|
||||
|
||||
spi_message_init(&msg);
|
||||
@@ -178,7 +184,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
/* Calculate flash page address; use block erase (for speed) if
|
||||
* we're at a block boundary and need to erase the whole block.
|
||||
*/
|
||||
pageaddr = instr->addr / priv->page_size;
|
||||
pageaddr = div_u64(instr->len, priv->page_size);
|
||||
do_block = (pageaddr & 0x7) == 0 && instr->len >= blocksize;
|
||||
pageaddr = pageaddr << priv->page_offset;
|
||||
|
||||
@@ -667,8 +673,8 @@ add_dataflash_otp(struct spi_device *spi, char *name,
|
||||
if (revision >= 'c')
|
||||
otp_tag = otp_setup(device, revision);
|
||||
|
||||
dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes%s\n",
|
||||
name, DIV_ROUND_UP(device->size, 1024),
|
||||
dev_info(&spi->dev, "%s (%lld KBytes) pagesize %d bytes%s\n",
|
||||
name, (long long)((device->size + 1023) >> 10),
|
||||
pagesize, otp_tag);
|
||||
dev_set_drvdata(&spi->dev, priv);
|
||||
|
||||
|
||||
+50
-50
@@ -109,25 +109,25 @@ module_param(shuffle_freq, int, 0);
|
||||
/* Each memory region corresponds to a minor device */
|
||||
typedef struct partition_t {
|
||||
struct mtd_blktrans_dev mbd;
|
||||
u_int32_t state;
|
||||
u_int32_t *VirtualBlockMap;
|
||||
u_int32_t *VirtualPageMap;
|
||||
u_int32_t FreeTotal;
|
||||
uint32_t state;
|
||||
uint32_t *VirtualBlockMap;
|
||||
uint32_t *VirtualPageMap;
|
||||
uint32_t FreeTotal;
|
||||
struct eun_info_t {
|
||||
u_int32_t Offset;
|
||||
u_int32_t EraseCount;
|
||||
u_int32_t Free;
|
||||
u_int32_t Deleted;
|
||||
uint32_t Offset;
|
||||
uint32_t EraseCount;
|
||||
uint32_t Free;
|
||||
uint32_t Deleted;
|
||||
} *EUNInfo;
|
||||
struct xfer_info_t {
|
||||
u_int32_t Offset;
|
||||
u_int32_t EraseCount;
|
||||
u_int16_t state;
|
||||
uint32_t Offset;
|
||||
uint32_t EraseCount;
|
||||
uint16_t state;
|
||||
} *XferInfo;
|
||||
u_int16_t bam_index;
|
||||
u_int32_t *bam_cache;
|
||||
u_int16_t DataUnits;
|
||||
u_int32_t BlocksPerUnit;
|
||||
uint16_t bam_index;
|
||||
uint32_t *bam_cache;
|
||||
uint16_t DataUnits;
|
||||
uint32_t BlocksPerUnit;
|
||||
erase_unit_header_t header;
|
||||
} partition_t;
|
||||
|
||||
@@ -199,8 +199,8 @@ static int scan_header(partition_t *part)
|
||||
static int build_maps(partition_t *part)
|
||||
{
|
||||
erase_unit_header_t header;
|
||||
u_int16_t xvalid, xtrans, i;
|
||||
u_int blocks, j;
|
||||
uint16_t xvalid, xtrans, i;
|
||||
unsigned blocks, j;
|
||||
int hdr_ok, ret = -1;
|
||||
ssize_t retval;
|
||||
loff_t offset;
|
||||
@@ -269,14 +269,14 @@ static int build_maps(partition_t *part)
|
||||
|
||||
/* Set up virtual page map */
|
||||
blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize;
|
||||
part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t));
|
||||
part->VirtualBlockMap = vmalloc(blocks * sizeof(uint32_t));
|
||||
if (!part->VirtualBlockMap)
|
||||
goto out_XferInfo;
|
||||
|
||||
memset(part->VirtualBlockMap, 0xff, blocks * sizeof(u_int32_t));
|
||||
memset(part->VirtualBlockMap, 0xff, blocks * sizeof(uint32_t));
|
||||
part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize;
|
||||
|
||||
part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(u_int32_t),
|
||||
part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(uint32_t),
|
||||
GFP_KERNEL);
|
||||
if (!part->bam_cache)
|
||||
goto out_VirtualBlockMap;
|
||||
@@ -290,7 +290,7 @@ static int build_maps(partition_t *part)
|
||||
offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset);
|
||||
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset,
|
||||
part->BlocksPerUnit * sizeof(u_int32_t), &retval,
|
||||
part->BlocksPerUnit * sizeof(uint32_t), &retval,
|
||||
(unsigned char *)part->bam_cache);
|
||||
|
||||
if (ret)
|
||||
@@ -332,7 +332,7 @@ out:
|
||||
======================================================================*/
|
||||
|
||||
static int erase_xfer(partition_t *part,
|
||||
u_int16_t xfernum)
|
||||
uint16_t xfernum)
|
||||
{
|
||||
int ret;
|
||||
struct xfer_info_t *xfer;
|
||||
@@ -408,7 +408,7 @@ static int prepare_xfer(partition_t *part, int i)
|
||||
erase_unit_header_t header;
|
||||
struct xfer_info_t *xfer;
|
||||
int nbam, ret;
|
||||
u_int32_t ctl;
|
||||
uint32_t ctl;
|
||||
ssize_t retlen;
|
||||
loff_t offset;
|
||||
|
||||
@@ -430,15 +430,15 @@ static int prepare_xfer(partition_t *part, int i)
|
||||
}
|
||||
|
||||
/* Write the BAM stub */
|
||||
nbam = (part->BlocksPerUnit * sizeof(u_int32_t) +
|
||||
nbam = (part->BlocksPerUnit * sizeof(uint32_t) +
|
||||
le32_to_cpu(part->header.BAMOffset) + SECTOR_SIZE - 1) / SECTOR_SIZE;
|
||||
|
||||
offset = xfer->Offset + le32_to_cpu(part->header.BAMOffset);
|
||||
ctl = cpu_to_le32(BLOCK_CONTROL);
|
||||
|
||||
for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) {
|
||||
for (i = 0; i < nbam; i++, offset += sizeof(uint32_t)) {
|
||||
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint32_t),
|
||||
&retlen, (u_char *)&ctl);
|
||||
|
||||
if (ret)
|
||||
@@ -461,18 +461,18 @@ static int prepare_xfer(partition_t *part, int i)
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
u_int16_t xferunit)
|
||||
static int copy_erase_unit(partition_t *part, uint16_t srcunit,
|
||||
uint16_t xferunit)
|
||||
{
|
||||
u_char buf[SECTOR_SIZE];
|
||||
struct eun_info_t *eun;
|
||||
struct xfer_info_t *xfer;
|
||||
u_int32_t src, dest, free, i;
|
||||
u_int16_t unit;
|
||||
uint32_t src, dest, free, i;
|
||||
uint16_t unit;
|
||||
int ret;
|
||||
ssize_t retlen;
|
||||
loff_t offset;
|
||||
u_int16_t srcunitswap = cpu_to_le16(srcunit);
|
||||
uint16_t srcunitswap = cpu_to_le16(srcunit);
|
||||
|
||||
eun = &part->EUNInfo[srcunit];
|
||||
xfer = &part->XferInfo[xferunit];
|
||||
@@ -486,7 +486,7 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
offset = eun->Offset + le32_to_cpu(part->header.BAMOffset);
|
||||
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset,
|
||||
part->BlocksPerUnit * sizeof(u_int32_t),
|
||||
part->BlocksPerUnit * sizeof(uint32_t),
|
||||
&retlen, (u_char *) (part->bam_cache));
|
||||
|
||||
/* mark the cache bad, in case we get an error later */
|
||||
@@ -503,7 +503,7 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
offset = xfer->Offset + 20; /* Bad! */
|
||||
unit = cpu_to_le16(0x7fff);
|
||||
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t),
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint16_t),
|
||||
&retlen, (u_char *) &unit);
|
||||
|
||||
if (ret) {
|
||||
@@ -560,7 +560,7 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
|
||||
|
||||
/* All clear? Then update the LogicalEUN again */
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t),
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(uint16_t),
|
||||
&retlen, (u_char *)&srcunitswap);
|
||||
|
||||
if (ret) {
|
||||
@@ -605,8 +605,8 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
|
||||
|
||||
static int reclaim_block(partition_t *part)
|
||||
{
|
||||
u_int16_t i, eun, xfer;
|
||||
u_int32_t best;
|
||||
uint16_t i, eun, xfer;
|
||||
uint32_t best;
|
||||
int queued, ret;
|
||||
|
||||
DEBUG(0, "ftl_cs: reclaiming space...\n");
|
||||
@@ -723,10 +723,10 @@ static void dump_lists(partition_t *part)
|
||||
}
|
||||
#endif
|
||||
|
||||
static u_int32_t find_free(partition_t *part)
|
||||
static uint32_t find_free(partition_t *part)
|
||||
{
|
||||
u_int16_t stop, eun;
|
||||
u_int32_t blk;
|
||||
uint16_t stop, eun;
|
||||
uint32_t blk;
|
||||
size_t retlen;
|
||||
int ret;
|
||||
|
||||
@@ -749,7 +749,7 @@ static u_int32_t find_free(partition_t *part)
|
||||
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd,
|
||||
part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset),
|
||||
part->BlocksPerUnit * sizeof(u_int32_t),
|
||||
part->BlocksPerUnit * sizeof(uint32_t),
|
||||
&retlen, (u_char *) (part->bam_cache));
|
||||
|
||||
if (ret) {
|
||||
@@ -786,7 +786,7 @@ static u_int32_t find_free(partition_t *part)
|
||||
static int ftl_read(partition_t *part, caddr_t buffer,
|
||||
u_long sector, u_long nblocks)
|
||||
{
|
||||
u_int32_t log_addr, bsize;
|
||||
uint32_t log_addr, bsize;
|
||||
u_long i;
|
||||
int ret;
|
||||
size_t offset, retlen;
|
||||
@@ -829,14 +829,14 @@ static int ftl_read(partition_t *part, caddr_t buffer,
|
||||
|
||||
======================================================================*/
|
||||
|
||||
static int set_bam_entry(partition_t *part, u_int32_t log_addr,
|
||||
u_int32_t virt_addr)
|
||||
static int set_bam_entry(partition_t *part, uint32_t log_addr,
|
||||
uint32_t virt_addr)
|
||||
{
|
||||
u_int32_t bsize, blk, le_virt_addr;
|
||||
uint32_t bsize, blk, le_virt_addr;
|
||||
#ifdef PSYCHO_DEBUG
|
||||
u_int32_t old_addr;
|
||||
uint32_t old_addr;
|
||||
#endif
|
||||
u_int16_t eun;
|
||||
uint16_t eun;
|
||||
int ret;
|
||||
size_t retlen, offset;
|
||||
|
||||
@@ -845,11 +845,11 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
|
||||
bsize = 1 << part->header.EraseUnitSize;
|
||||
eun = log_addr / bsize;
|
||||
blk = (log_addr % bsize) / SECTOR_SIZE;
|
||||
offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) +
|
||||
offset = (part->EUNInfo[eun].Offset + blk * sizeof(uint32_t) +
|
||||
le32_to_cpu(part->header.BAMOffset));
|
||||
|
||||
#ifdef PSYCHO_DEBUG
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t),
|
||||
ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(uint32_t),
|
||||
&retlen, (u_char *)&old_addr);
|
||||
if (ret) {
|
||||
printk(KERN_WARNING"ftl: Error reading old_addr in set_bam_entry: %d\n",ret);
|
||||
@@ -886,7 +886,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
|
||||
#endif
|
||||
part->bam_cache[blk] = le_virt_addr;
|
||||
}
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),
|
||||
ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(uint32_t),
|
||||
&retlen, (u_char *)&le_virt_addr);
|
||||
|
||||
if (ret) {
|
||||
@@ -900,7 +900,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
|
||||
static int ftl_write(partition_t *part, caddr_t buffer,
|
||||
u_long sector, u_long nblocks)
|
||||
{
|
||||
u_int32_t bsize, log_addr, virt_addr, old_addr, blk;
|
||||
uint32_t bsize, log_addr, virt_addr, old_addr, blk;
|
||||
u_long i;
|
||||
int ret;
|
||||
size_t retlen, offset;
|
||||
|
||||
@@ -50,7 +50,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
|
||||
struct INFTLrecord *inftl;
|
||||
unsigned long temp;
|
||||
|
||||
if (mtd->type != MTD_NANDFLASH)
|
||||
if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX)
|
||||
return;
|
||||
/* OK, this is moderately ugly. But probably safe. Alternatives? */
|
||||
if (memcmp(mtd->name, "DiskOnChip", 10))
|
||||
|
||||
@@ -63,7 +63,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
|
||||
* otherwise.
|
||||
*/
|
||||
inftl->EraseSize = inftl->mbd.mtd->erasesize;
|
||||
inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
|
||||
inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize;
|
||||
|
||||
inftl->MediaUnit = BLOCK_NIL;
|
||||
|
||||
@@ -187,7 +187,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
|
||||
mh->BlockMultiplierBits);
|
||||
inftl->EraseSize = inftl->mbd.mtd->erasesize <<
|
||||
mh->BlockMultiplierBits;
|
||||
inftl->nb_blocks = inftl->mbd.mtd->size / inftl->EraseSize;
|
||||
inftl->nb_blocks = (u32)inftl->mbd.mtd->size / inftl->EraseSize;
|
||||
block >>= mh->BlockMultiplierBits;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# drivers/mtd/chips/Kconfig
|
||||
|
||||
menu "LPDDR flash memory drivers"
|
||||
depends on MTD!=n
|
||||
|
||||
config MTD_LPDDR
|
||||
tristate "Support for LPDDR flash chips"
|
||||
select MTD_QINFO_PROBE
|
||||
help
|
||||
This option enables support of LPDDR (Low power double data rate)
|
||||
flash chips. Synonymous with Mobile-DDR. It is a new standard for
|
||||
DDR memories, intended for battery-operated systems.
|
||||
|
||||
config MTD_QINFO_PROBE
|
||||
tristate "Detect flash chips by QINFO probe"
|
||||
help
|
||||
Device Information for LPDDR chips is offered through the Overlay
|
||||
Window QINFO interface, permits software to be used for entire
|
||||
families of devices. This serves similar purpose of CFI on legacy
|
||||
Flash products
|
||||
endmenu
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#
|
||||
# linux/drivers/mtd/lpddr/Makefile
|
||||
#
|
||||
|
||||
obj-$(CONFIG_MTD_QINFO_PROBE) += qinfo_probe.o
|
||||
obj-$(CONFIG_MTD_LPDDR) += lpddr_cmds.o
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Probing flash chips with QINFO records.
|
||||
* (C) 2008 Korolev Alexey <akorolev@infradead.org>
|
||||
* (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/mtd/xip.h>
|
||||
#include <linux/mtd/map.h>
|
||||
#include <linux/mtd/pfow.h>
|
||||
#include <linux/mtd/qinfo.h>
|
||||
|
||||
static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr);
|
||||
struct mtd_info *lpddr_probe(struct map_info *map);
|
||||
static struct lpddr_private *lpddr_probe_chip(struct map_info *map);
|
||||
static int lpddr_pfow_present(struct map_info *map,
|
||||
struct lpddr_private *lpddr);
|
||||
|
||||
static struct qinfo_query_info qinfo_array[] = {
|
||||
/* General device info */
|
||||
{0, 0, "DevSizeShift", "Device size 2^n bytes"},
|
||||
{0, 3, "BufSizeShift", "Program buffer size 2^n bytes"},
|
||||
/* Erase block information */
|
||||
{1, 1, "TotalBlocksNum", "Total number of blocks"},
|
||||
{1, 2, "UniformBlockSizeShift", "Uniform block size 2^n bytes"},
|
||||
/* Partition information */
|
||||
{2, 1, "HWPartsNum", "Number of hardware partitions"},
|
||||
/* Optional features */
|
||||
{5, 1, "SuspEraseSupp", "Suspend erase supported"},
|
||||
/* Operation typical time */
|
||||
{10, 0, "SingleWordProgTime", "Single word program 2^n u-sec"},
|
||||
{10, 1, "ProgBufferTime", "Program buffer write 2^n u-sec"},
|
||||
{10, 2, "BlockEraseTime", "Block erase 2^n m-sec"},
|
||||
{10, 3, "FullChipEraseTime", "Full chip erase 2^n m-sec"},
|
||||
};
|
||||
|
||||
static long lpddr_get_qinforec_pos(struct map_info *map, char *id_str)
|
||||
{
|
||||
int qinfo_lines = sizeof(qinfo_array)/sizeof(struct qinfo_query_info);
|
||||
int i;
|
||||
int bankwidth = map_bankwidth(map) * 8;
|
||||
int major, minor;
|
||||
|
||||
for (i = 0; i < qinfo_lines; i++) {
|
||||
if (strcmp(id_str, qinfo_array[i].id_str) == 0) {
|
||||
major = qinfo_array[i].major & ((1 << bankwidth) - 1);
|
||||
minor = qinfo_array[i].minor & ((1 << bankwidth) - 1);
|
||||
return minor | (major << bankwidth);
|
||||
}
|
||||
}
|
||||
printk(KERN_ERR"%s qinfo id string is wrong! \n", map->name);
|
||||
BUG();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static uint16_t lpddr_info_query(struct map_info *map, char *id_str)
|
||||
{
|
||||
unsigned int dsr, val;
|
||||
int bits_per_chip = map_bankwidth(map) * 8;
|
||||
unsigned long adr = lpddr_get_qinforec_pos(map, id_str);
|
||||
int attempts = 20;
|
||||
|
||||
/* Write a request for the PFOW record */
|
||||
map_write(map, CMD(LPDDR_INFO_QUERY),
|
||||
map->pfow_base + PFOW_COMMAND_CODE);
|
||||
map_write(map, CMD(adr & ((1 << bits_per_chip) - 1)),
|
||||
map->pfow_base + PFOW_COMMAND_ADDRESS_L);
|
||||
map_write(map, CMD(adr >> bits_per_chip),
|
||||
map->pfow_base + PFOW_COMMAND_ADDRESS_H);
|
||||
map_write(map, CMD(LPDDR_START_EXECUTION),
|
||||
map->pfow_base + PFOW_COMMAND_EXECUTE);
|
||||
|
||||
while ((attempts--) > 0) {
|
||||
dsr = CMDVAL(map_read(map, map->pfow_base + PFOW_DSR));
|
||||
if (dsr & DSR_READY_STATUS)
|
||||
break;
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
val = CMDVAL(map_read(map, map->pfow_base + PFOW_COMMAND_DATA));
|
||||
return val;
|
||||
}
|
||||
|
||||
static int lpddr_pfow_present(struct map_info *map, struct lpddr_private *lpddr)
|
||||
{
|
||||
map_word pfow_val[4];
|
||||
|
||||
/* Check identification string */
|
||||
pfow_val[0] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_P);
|
||||
pfow_val[1] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_F);
|
||||
pfow_val[2] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_O);
|
||||
pfow_val[3] = map_read(map, map->pfow_base + PFOW_QUERY_STRING_W);
|
||||
|
||||
if (!map_word_equal(map, CMD('P'), pfow_val[0]))
|
||||
goto out;
|
||||
|
||||
if (!map_word_equal(map, CMD('F'), pfow_val[1]))
|
||||
goto out;
|
||||
|
||||
if (!map_word_equal(map, CMD('O'), pfow_val[2]))
|
||||
goto out;
|
||||
|
||||
if (!map_word_equal(map, CMD('W'), pfow_val[3]))
|
||||
goto out;
|
||||
|
||||
return 1; /* "PFOW" is found */
|
||||
out:
|
||||
printk(KERN_WARNING"%s: PFOW string at 0x%lx is not found \n",
|
||||
map->name, map->pfow_base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr)
|
||||
{
|
||||
|
||||
lpddr->qinfo = kmalloc(sizeof(struct qinfo_chip), GFP_KERNEL);
|
||||
if (!lpddr->qinfo) {
|
||||
printk(KERN_WARNING "%s: no memory for LPDDR qinfo structure\n",
|
||||
map->name);
|
||||
return 0;
|
||||
}
|
||||
memset(lpddr->qinfo, 0, sizeof(struct qinfo_chip));
|
||||
|
||||
/* Get the ManuID */
|
||||
lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID));
|
||||
/* Get the DeviceID */
|
||||
lpddr->DevId = CMDVAL(map_read(map, map->pfow_base + PFOW_DEVICE_ID));
|
||||
/* read parameters from chip qinfo table */
|
||||
lpddr->qinfo->DevSizeShift = lpddr_info_query(map, "DevSizeShift");
|
||||
lpddr->qinfo->TotalBlocksNum = lpddr_info_query(map, "TotalBlocksNum");
|
||||
lpddr->qinfo->BufSizeShift = lpddr_info_query(map, "BufSizeShift");
|
||||
lpddr->qinfo->HWPartsNum = lpddr_info_query(map, "HWPartsNum");
|
||||
lpddr->qinfo->UniformBlockSizeShift =
|
||||
lpddr_info_query(map, "UniformBlockSizeShift");
|
||||
lpddr->qinfo->SuspEraseSupp = lpddr_info_query(map, "SuspEraseSupp");
|
||||
lpddr->qinfo->SingleWordProgTime =
|
||||
lpddr_info_query(map, "SingleWordProgTime");
|
||||
lpddr->qinfo->ProgBufferTime = lpddr_info_query(map, "ProgBufferTime");
|
||||
lpddr->qinfo->BlockEraseTime = lpddr_info_query(map, "BlockEraseTime");
|
||||
return 1;
|
||||
}
|
||||
static struct lpddr_private *lpddr_probe_chip(struct map_info *map)
|
||||
{
|
||||
struct lpddr_private lpddr;
|
||||
struct lpddr_private *retlpddr;
|
||||
int numvirtchips;
|
||||
|
||||
|
||||
if ((map->pfow_base + 0x1000) >= map->size) {
|
||||
printk(KERN_NOTICE"%s Probe at base (0x%08lx) past the end of"
|
||||
"the map(0x%08lx)\n", map->name,
|
||||
(unsigned long)map->pfow_base, map->size - 1);
|
||||
return NULL;
|
||||
}
|
||||
memset(&lpddr, 0, sizeof(struct lpddr_private));
|
||||
if (!lpddr_pfow_present(map, &lpddr))
|
||||
return NULL;
|
||||
|
||||
if (!lpddr_chip_setup(map, &lpddr))
|
||||
return NULL;
|
||||
|
||||
/* Ok so we found a chip */
|
||||
lpddr.chipshift = lpddr.qinfo->DevSizeShift;
|
||||
lpddr.numchips = 1;
|
||||
|
||||
numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum;
|
||||
retlpddr = kmalloc(sizeof(struct lpddr_private) +
|
||||
numvirtchips * sizeof(struct flchip), GFP_KERNEL);
|
||||
if (!retlpddr)
|
||||
return NULL;
|
||||
|
||||
memset(retlpddr, 0, sizeof(struct lpddr_private) +
|
||||
numvirtchips * sizeof(struct flchip));
|
||||
memcpy(retlpddr, &lpddr, sizeof(struct lpddr_private));
|
||||
|
||||
retlpddr->numchips = numvirtchips;
|
||||
retlpddr->chipshift = retlpddr->qinfo->DevSizeShift -
|
||||
__ffs(retlpddr->qinfo->HWPartsNum);
|
||||
|
||||
return retlpddr;
|
||||
}
|
||||
|
||||
struct mtd_info *lpddr_probe(struct map_info *map)
|
||||
{
|
||||
struct mtd_info *mtd = NULL;
|
||||
struct lpddr_private *lpddr;
|
||||
|
||||
/* First probe the map to see if we havecan open PFOW here */
|
||||
lpddr = lpddr_probe_chip(map);
|
||||
if (!lpddr)
|
||||
return NULL;
|
||||
|
||||
map->fldrv_priv = lpddr;
|
||||
mtd = lpddr_cmdset(map);
|
||||
if (mtd) {
|
||||
if (mtd->size > map->size) {
|
||||
printk(KERN_WARNING "Reducing visibility of %ldKiB chip"
|
||||
"to %ldKiB\n", (unsigned long)mtd->size >> 10,
|
||||
(unsigned long)map->size >> 10);
|
||||
mtd->size = map->size;
|
||||
}
|
||||
return mtd;
|
||||
}
|
||||
|
||||
kfree(lpddr->qinfo);
|
||||
kfree(lpddr);
|
||||
map->fldrv_priv = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct mtd_chip_driver lpddr_chipdrv = {
|
||||
.probe = lpddr_probe,
|
||||
.name = "qinfo_probe",
|
||||
.module = THIS_MODULE
|
||||
};
|
||||
|
||||
static int __init lpddr_probe_init(void)
|
||||
{
|
||||
register_mtd_chip_driver(&lpddr_chipdrv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit lpddr_probe_exit(void)
|
||||
{
|
||||
unregister_mtd_chip_driver(&lpddr_chipdrv);
|
||||
}
|
||||
|
||||
module_init(lpddr_probe_init);
|
||||
module_exit(lpddr_probe_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Vasiliy Leonenko <vasiliy.leonenko@gmail.com>");
|
||||
MODULE_DESCRIPTION("Driver to probe qinfo flash chips");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user