mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-28 06:34:12 +08:00
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (226 commits) mtd: tests: annotate as DANGEROUS in Kconfig mtd: tests: don't use mtd0 as a default mtd: clean up usage of MTD_DOCPROBE_ADDRESS jffs2: add compr=lzo and compr=zlib options jffs2: implement mount option parsing and compression overriding mtd: nand: initialize ops.mode mtd: provide an alias for the redboot module name mtd: m25p80: don't probe device which has status of 'disabled' mtd: nand_h1900 never worked mtd: Add DiskOnChip G3 support mtd: m25p80: add EON flash EN25Q32B into spi flash id table mtd: mark block device queue as non-rotational mtd: r852: make r852_pm_ops static mtd: m25p80: add support for at25df321a spi data flash mtd: mxc_nand: preset_v1_v2: unlock all NAND flash blocks mtd: nand: switch `check_pattern()' to standard `memcmp()' mtd: nand: invalidate cache on unaligned reads mtd: nand: do not scan bad blocks with NAND_BBT_NO_OOB set mtd: nand: wait to set BBT version mtd: nand: scrub BBT on ECC errors ... Fix up trivial conflicts: - arch/arm/mach-at91/board-usb-a9260.c Merged into board-usb-a926x.c - drivers/mtd/maps/lantiq-flash.c add_mtd_partitions -> mtd_device_register vs changed to use mtd_device_parse_register.
This commit is contained in:
commit
e0d65113a7
@ -572,7 +572,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
|
||||
</para>
|
||||
<para>
|
||||
The simplest way to activate the FLASH based bad block table support
|
||||
is to set the option NAND_USE_FLASH_BBT in the option field of
|
||||
is to set the option NAND_BBT_USE_FLASH in the bbt_option field of
|
||||
the nand chip structure before calling nand_scan(). For AG-AND
|
||||
chips is this done by default.
|
||||
This activates the default FLASH based bad block table functionality
|
||||
@ -773,20 +773,6 @@ struct nand_oobinfo {
|
||||
done according to the default builtin scheme.
|
||||
</para>
|
||||
</sect2>
|
||||
<sect2 id="User_space_placement_selection">
|
||||
<title>User space placement selection</title>
|
||||
<para>
|
||||
All non ecc functions like mtd->read and mtd->write use an internal
|
||||
structure, which can be set by an ioctl. This structure is preset
|
||||
to the autoplacement default.
|
||||
<programlisting>
|
||||
ioctl (fd, MEMSETOOBSEL, oobsel);
|
||||
</programlisting>
|
||||
oobsel is a pointer to a user supplied structure of type
|
||||
nand_oobconfig. The contents of this structure must match the
|
||||
criteria of the filesystem, which will be used. See an example in utils/nandwrite.c.
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
<sect1 id="Spare_area_autoplacement_default">
|
||||
<title>Spare area autoplacement default schemes</title>
|
||||
@ -1158,9 +1144,6 @@ in this page</entry>
|
||||
These constants are defined in nand.h. They are ored together to describe
|
||||
the functionality.
|
||||
<programlisting>
|
||||
/* Use a flash based bad block table. This option is parsed by the
|
||||
* default bad block table function (nand_default_bbt). */
|
||||
#define NAND_USE_FLASH_BBT 0x00010000
|
||||
/* The hw ecc generator provides a syndrome instead a ecc value on read
|
||||
* This can only work if we have the ecc bytes directly behind the
|
||||
* data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */
|
||||
|
14
Documentation/devicetree/bindings/mtd/atmel-dataflash.txt
Normal file
14
Documentation/devicetree/bindings/mtd/atmel-dataflash.txt
Normal file
@ -0,0 +1,14 @@
|
||||
* Atmel Data Flash
|
||||
|
||||
Required properties:
|
||||
- compatible : "atmel,<model>", "atmel,<series>", "atmel,dataflash".
|
||||
|
||||
Example:
|
||||
|
||||
flash@1 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "atmel,at45db321d", "atmel,at45", "atmel,dataflash";
|
||||
spi-max-frequency = <25000000>;
|
||||
reg = <1>;
|
||||
};
|
@ -130,19 +130,14 @@ static struct mtd_partition __initdata afeb9260_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(afeb9260_nand_partition);
|
||||
return afeb9260_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata afeb9260_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
.rdy_pin = AT91_PIN_PC13,
|
||||
.enable_pin = AT91_PIN_PC14,
|
||||
.partition_info = nand_partitions,
|
||||
.bus_width_16 = 0,
|
||||
.parts = afeb9260_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(afeb9260_nand_partition),
|
||||
};
|
||||
|
||||
|
||||
|
@ -132,19 +132,14 @@ static struct mtd_partition __initdata cam60_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(cam60_nand_partition);
|
||||
return cam60_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata cam60_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
// .det_pin = ... not there
|
||||
.rdy_pin = AT91_PIN_PA9,
|
||||
.enable_pin = AT91_PIN_PA7,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = cam60_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(cam60_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata cam60_nand_smc_config = {
|
||||
|
@ -169,19 +169,14 @@ static struct mtd_partition __initdata cap9adk_nand_partitions[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(cap9adk_nand_partitions);
|
||||
return cap9adk_nand_partitions;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata cap9adk_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
// .det_pin = ... not connected
|
||||
// .rdy_pin = ... not connected
|
||||
.enable_pin = AT91_PIN_PD15,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = cap9adk_nand_partitions,
|
||||
.num_parts = ARRAY_SIZE(cap9adk_nand_partitions),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata cap9adk_nand_smc_config = {
|
||||
|
@ -97,19 +97,14 @@ static struct mtd_partition __initdata kb9202_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(kb9202_nand_partition);
|
||||
return kb9202_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata kb9202_nand_data = {
|
||||
.ale = 22,
|
||||
.cle = 21,
|
||||
// .det_pin = ... not there
|
||||
.rdy_pin = AT91_PIN_PC29,
|
||||
.enable_pin = AT91_PIN_PC28,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = kb9202_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(kb9202_nand_partition),
|
||||
};
|
||||
|
||||
static void __init kb9202_board_init(void)
|
||||
|
@ -182,19 +182,14 @@ static struct mtd_partition __initdata neocore926_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(neocore926_nand_partition);
|
||||
return neocore926_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata neocore926_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
.rdy_pin = AT91_PIN_PB19,
|
||||
.rdy_pin_active_low = 1,
|
||||
.enable_pin = AT91_PIN_PD15,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = neocore926_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(neocore926_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata neocore926_nand_smc_config = {
|
||||
|
@ -130,19 +130,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
// .det_pin = ... not connected
|
||||
.rdy_pin = AT91_PIN_PC13,
|
||||
.enable_pin = AT91_PIN_PC14,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = ek_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(ek_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
||||
|
@ -138,19 +138,14 @@ static struct mtd_partition __initdata dk_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(dk_nand_partition);
|
||||
return dk_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata dk_nand_data = {
|
||||
.ale = 22,
|
||||
.cle = 21,
|
||||
.det_pin = AT91_PIN_PB1,
|
||||
.rdy_pin = AT91_PIN_PC2,
|
||||
// .enable_pin = ... not there
|
||||
.partition_info = nand_partitions,
|
||||
.parts = dk_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(dk_nand_partition),
|
||||
};
|
||||
|
||||
#define DK_FLASH_BASE AT91_CHIPSELECT_0
|
||||
|
@ -131,19 +131,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
// .det_pin = ... not connected
|
||||
.rdy_pin = AT91_PIN_PC13,
|
||||
.enable_pin = AT91_PIN_PC14,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = ek_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(ek_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
||||
|
@ -173,19 +173,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
// .det_pin = ... not connected
|
||||
.rdy_pin = AT91_PIN_PC13,
|
||||
.enable_pin = AT91_PIN_PC14,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = ek_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(ek_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
||||
|
@ -179,19 +179,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
||||
.ale = 22,
|
||||
.cle = 21,
|
||||
// .det_pin = ... not connected
|
||||
.rdy_pin = AT91_PIN_PC15,
|
||||
.enable_pin = AT91_PIN_PC14,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = ek_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(ek_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
||||
|
@ -180,19 +180,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
// .det_pin = ... not connected
|
||||
.rdy_pin = AT91_PIN_PA22,
|
||||
.enable_pin = AT91_PIN_PD15,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = ek_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(ek_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
||||
|
@ -157,19 +157,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
}
|
||||
|
||||
/* det_pin is not connected */
|
||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
.rdy_pin = AT91_PIN_PC13,
|
||||
.enable_pin = AT91_PIN_PC14,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = ek_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(ek_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
||||
|
@ -137,19 +137,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
}
|
||||
|
||||
/* det_pin is not connected */
|
||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
.rdy_pin = AT91_PIN_PC8,
|
||||
.enable_pin = AT91_PIN_PC14,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = ek_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(ek_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
||||
|
@ -88,19 +88,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
// .det_pin = ... not connected
|
||||
.rdy_pin = AT91_PIN_PD17,
|
||||
.enable_pin = AT91_PIN_PB6,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = ek_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(ek_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
||||
|
@ -97,18 +97,12 @@ static struct mtd_partition __initdata snapper9260_nand_partitions[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init
|
||||
snapper9260_nand_partition_info(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(snapper9260_nand_partitions);
|
||||
return snapper9260_nand_partitions;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata snapper9260_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
.rdy_pin = AT91_PIN_PC13,
|
||||
.partition_info = snapper9260_nand_partition_info,
|
||||
.parts = snapper9260_nand_partitions,
|
||||
.num_parts = ARRAY_SIZE(snapper9260_nand_partitions),
|
||||
.bus_width_16 = 0,
|
||||
};
|
||||
|
||||
|
@ -190,19 +190,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(ek_nand_partition);
|
||||
return ek_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata ek_nand_data = {
|
||||
.ale = 21,
|
||||
.cle = 22,
|
||||
// .det_pin = ... not connected
|
||||
.rdy_pin = AT91_PIN_PA22,
|
||||
.enable_pin = AT91_PIN_PD15,
|
||||
.partition_info = nand_partitions,
|
||||
.parts = ek_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(ek_nand_partition),
|
||||
};
|
||||
|
||||
static struct sam9_smc_config __initdata usb_a9260_nand_smc_config = {
|
||||
|
@ -172,19 +172,14 @@ static struct mtd_partition __initdata yl9200_nand_partition[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(yl9200_nand_partition);
|
||||
return yl9200_nand_partition;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data __initdata yl9200_nand_data = {
|
||||
.ale = 6,
|
||||
.cle = 7,
|
||||
// .det_pin = ... not connected
|
||||
.rdy_pin = AT91_PIN_PC14, /* R/!B (Sheet10) */
|
||||
.enable_pin = AT91_PIN_PC15, /* !CE (Sheet10) */
|
||||
.partition_info = nand_partitions,
|
||||
.parts = yl9200_nand_partition,
|
||||
.num_parts = ARRAY_SIZE(yl9200_nand_partition),
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -117,7 +117,8 @@ struct atmel_nand_data {
|
||||
u8 ale; /* address line number connected to ALE */
|
||||
u8 cle; /* address line number connected to CLE */
|
||||
u8 bus_width_16; /* buswidth is 16 bit */
|
||||
struct mtd_partition* (*partition_info)(int, int*);
|
||||
struct mtd_partition *parts;
|
||||
unsigned int num_parts;
|
||||
};
|
||||
extern void __init at91_add_device_nand(struct atmel_nand_data *data);
|
||||
|
||||
|
@ -377,7 +377,7 @@ static struct davinci_nand_pdata da830_evm_nand_pdata = {
|
||||
.nr_parts = ARRAY_SIZE(da830_evm_nand_partitions),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.ecc_bits = 4,
|
||||
.options = NAND_USE_FLASH_BBT,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
.bbt_td = &da830_evm_nand_bbt_main_descr,
|
||||
.bbt_md = &da830_evm_nand_bbt_mirror_descr,
|
||||
.timing = &da830_evm_nandflash_timing,
|
||||
|
@ -256,7 +256,7 @@ static struct davinci_nand_pdata da850_evm_nandflash_data = {
|
||||
.nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.ecc_bits = 4,
|
||||
.options = NAND_USE_FLASH_BBT,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
.timing = &da850_evm_nandflash_timing,
|
||||
};
|
||||
|
||||
|
@ -77,7 +77,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
|
||||
.parts = davinci_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.options = NAND_USE_FLASH_BBT,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
.ecc_bits = 4,
|
||||
};
|
||||
|
||||
|
@ -74,7 +74,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
|
||||
.parts = davinci_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
|
||||
.ecc_mode = NAND_ECC_HW_SYNDROME,
|
||||
.options = NAND_USE_FLASH_BBT,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
};
|
||||
|
||||
static struct resource davinci_nand_resources[] = {
|
||||
|
@ -139,7 +139,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
|
||||
.parts = davinci_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.options = NAND_USE_FLASH_BBT,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
.ecc_bits = 4,
|
||||
};
|
||||
|
||||
|
@ -151,7 +151,7 @@ static struct davinci_nand_pdata davinci_evm_nandflash_data = {
|
||||
.parts = davinci_evm_nandflash_partition,
|
||||
.nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.options = NAND_USE_FLASH_BBT,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
.timing = &davinci_evm_nandflash_timing,
|
||||
};
|
||||
|
||||
|
@ -396,7 +396,8 @@ static struct davinci_nand_pdata mityomapl138_nandflash_data = {
|
||||
.parts = mityomapl138_nandflash_partition,
|
||||
.nr_parts = ARRAY_SIZE(mityomapl138_nandflash_partition),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.options = NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
.options = NAND_BUSWIDTH_16,
|
||||
.ecc_bits = 1, /* 4 bit mode is not supported with 16 bit NAND */
|
||||
};
|
||||
|
||||
|
@ -87,7 +87,7 @@ static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = {
|
||||
.parts = davinci_ntosd2_nandflash_partition,
|
||||
.nr_parts = ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.options = NAND_USE_FLASH_BBT,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
};
|
||||
|
||||
static struct resource davinci_ntosd2_nandflash_resource[] = {
|
||||
|
@ -144,7 +144,7 @@ static struct davinci_nand_pdata nand_config = {
|
||||
.parts = nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(nand_partitions),
|
||||
.ecc_mode = NAND_ECC_HW,
|
||||
.options = NAND_USE_FLASH_BBT,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
.ecc_bits = 1,
|
||||
};
|
||||
|
||||
|
@ -74,8 +74,10 @@ struct davinci_nand_pdata { /* platform_data */
|
||||
nand_ecc_modes_t ecc_mode;
|
||||
u8 ecc_bits;
|
||||
|
||||
/* e.g. NAND_BUSWIDTH_16 or NAND_USE_FLASH_BBT */
|
||||
/* e.g. NAND_BUSWIDTH_16 */
|
||||
unsigned options;
|
||||
/* e.g. NAND_BBT_USE_FLASH */
|
||||
unsigned bbt_options;
|
||||
|
||||
/* Main and mirror bbt descriptor overrides */
|
||||
struct nand_bbt_descr *bbt_td;
|
||||
|
@ -116,8 +116,9 @@ static struct mtd_partition ts72xx_nand_parts[] = {
|
||||
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
||||
}, {
|
||||
.name = "Linux",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = 0, /* filled in later */
|
||||
.offset = MTDPART_OFS_RETAIN,
|
||||
.size = TS72XX_REDBOOT_PART_SIZE,
|
||||
/* leave so much for last partition */
|
||||
}, {
|
||||
.name = "RedBoot",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
@ -126,28 +127,14 @@ static struct mtd_partition ts72xx_nand_parts[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static void ts72xx_nand_set_parts(uint64_t size,
|
||||
struct platform_nand_chip *chip)
|
||||
{
|
||||
/* Factory TS-72xx boards only come with 32MiB or 128MiB NAND options */
|
||||
if (size == SZ_32M || size == SZ_128M) {
|
||||
/* Set the "Linux" partition size */
|
||||
ts72xx_nand_parts[1].size = size - TS72XX_REDBOOT_PART_SIZE;
|
||||
|
||||
chip->partitions = ts72xx_nand_parts;
|
||||
chip->nr_partitions = ARRAY_SIZE(ts72xx_nand_parts);
|
||||
} else {
|
||||
pr_warning("Unknown nand disk size:%lluMiB\n", size >> 20);
|
||||
}
|
||||
}
|
||||
|
||||
static struct platform_nand_data ts72xx_nand_data = {
|
||||
.chip = {
|
||||
.nr_chips = 1,
|
||||
.chip_offset = 0,
|
||||
.chip_delay = 15,
|
||||
.part_probe_types = ts72xx_nand_part_probes,
|
||||
.set_parts = ts72xx_nand_set_parts,
|
||||
.partitions = ts72xx_nand_parts,
|
||||
.nr_partitions = ARRAY_SIZE(ts72xx_nand_parts),
|
||||
},
|
||||
.ctrl = {
|
||||
.cmd_ctrl = ts72xx_nand_hwcontrol,
|
||||
|
@ -167,8 +167,9 @@ static struct mtd_partition aspenite_nand_partitions[] = {
|
||||
|
||||
static struct pxa3xx_nand_platform_data aspenite_nand_info = {
|
||||
.enable_arbiter = 1,
|
||||
.parts = aspenite_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(aspenite_nand_partitions),
|
||||
.num_cs = 1,
|
||||
.parts[0] = aspenite_nand_partitions,
|
||||
.nr_parts[0] = ARRAY_SIZE(aspenite_nand_partitions),
|
||||
};
|
||||
|
||||
static struct i2c_board_info aspenite_i2c_info[] __initdata = {
|
||||
|
@ -275,7 +275,7 @@ static struct platform_nand_data ts78xx_ts_nand_data = {
|
||||
.partitions = ts78xx_ts_nand_parts,
|
||||
.nr_partitions = ARRAY_SIZE(ts78xx_ts_nand_parts),
|
||||
.chip_delay = 15,
|
||||
.options = NAND_USE_FLASH_BBT,
|
||||
.bbt_options = NAND_BBT_USE_FLASH,
|
||||
},
|
||||
.ctrl = {
|
||||
/*
|
||||
|
@ -424,8 +424,9 @@ static struct mtd_partition cm_x300_nand_partitions[] = {
|
||||
static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
|
||||
.enable_arbiter = 1,
|
||||
.keep_config = 1,
|
||||
.parts = cm_x300_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(cm_x300_nand_partitions),
|
||||
.num_cs = 1,
|
||||
.parts[0] = cm_x300_nand_partitions,
|
||||
.nr_parts[0] = ARRAY_SIZE(cm_x300_nand_partitions),
|
||||
};
|
||||
|
||||
static void __init cm_x300_init_nand(void)
|
||||
|
@ -139,8 +139,9 @@ static struct mtd_partition colibri_nand_partitions[] = {
|
||||
static struct pxa3xx_nand_platform_data colibri_nand_info = {
|
||||
.enable_arbiter = 1,
|
||||
.keep_config = 1,
|
||||
.parts = colibri_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(colibri_nand_partitions),
|
||||
.num_cs = 1,
|
||||
.parts[0] = colibri_nand_partitions,
|
||||
.nr_parts[0] = ARRAY_SIZE(colibri_nand_partitions),
|
||||
};
|
||||
|
||||
void __init colibri_pxa3xx_init_nand(void)
|
||||
|
@ -325,8 +325,9 @@ static struct mtd_partition littleton_nand_partitions[] = {
|
||||
|
||||
static struct pxa3xx_nand_platform_data littleton_nand_info = {
|
||||
.enable_arbiter = 1,
|
||||
.parts = littleton_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(littleton_nand_partitions),
|
||||
.num_cs = 1,
|
||||
.parts[0] = littleton_nand_partitions,
|
||||
.nr_parts[0] = ARRAY_SIZE(littleton_nand_partitions),
|
||||
};
|
||||
|
||||
static void __init littleton_init_nand(void)
|
||||
|
@ -389,10 +389,11 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = {
|
||||
};
|
||||
|
||||
static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
|
||||
.enable_arbiter = 1,
|
||||
.keep_config = 1,
|
||||
.parts = mxm_8x10_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(mxm_8x10_nand_partitions)
|
||||
.enable_arbiter = 1,
|
||||
.keep_config = 1,
|
||||
.num_cs = 1,
|
||||
.parts[0] = mxm_8x10_nand_partitions,
|
||||
.nr_parts[0] = ARRAY_SIZE(mxm_8x10_nand_partitions)
|
||||
};
|
||||
|
||||
static void __init mxm_8x10_nand_init(void)
|
||||
|
@ -346,8 +346,9 @@ static struct mtd_partition raumfeld_nand_partitions[] = {
|
||||
static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
|
||||
.enable_arbiter = 1,
|
||||
.keep_config = 1,
|
||||
.parts = raumfeld_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(raumfeld_nand_partitions),
|
||||
.num_cs = 1,
|
||||
.parts[0] = raumfeld_nand_partitions,
|
||||
.nr_parts[0] = ARRAY_SIZE(raumfeld_nand_partitions),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -366,8 +366,9 @@ static struct mtd_partition zylonite_nand_partitions[] = {
|
||||
|
||||
static struct pxa3xx_nand_platform_data zylonite_nand_info = {
|
||||
.enable_arbiter = 1,
|
||||
.parts = zylonite_nand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(zylonite_nand_partitions),
|
||||
.num_cs = 1,
|
||||
.parts[0] = zylonite_nand_partitions,
|
||||
.nr_parts[0] = ARRAY_SIZE(zylonite_nand_partitions),
|
||||
};
|
||||
|
||||
static void __init zylonite_init_nand(void)
|
||||
|
@ -41,6 +41,19 @@ struct pxa3xx_nand_flash {
|
||||
struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
|
||||
};
|
||||
|
||||
/*
|
||||
* Current pxa3xx_nand controller has two chip select which
|
||||
* both be workable.
|
||||
*
|
||||
* Notice should be taken that:
|
||||
* When you want to use this feature, you should not enable the
|
||||
* keep configuration feature, for two chip select could be
|
||||
* attached with different nand chip. The different page size
|
||||
* and timing requirement make the keep configuration impossible.
|
||||
*/
|
||||
|
||||
/* The max num of chip select current support */
|
||||
#define NUM_CHIP_SELECT (2)
|
||||
struct pxa3xx_nand_platform_data {
|
||||
|
||||
/* the data flash bus is shared between the Static Memory
|
||||
@ -52,8 +65,11 @@ struct pxa3xx_nand_platform_data {
|
||||
/* allow platform code to keep OBM/bootloader defined NFC config */
|
||||
int keep_config;
|
||||
|
||||
const struct mtd_partition *parts;
|
||||
unsigned int nr_parts;
|
||||
/* indicate how many chip selects will be used */
|
||||
int num_cs;
|
||||
|
||||
const struct mtd_partition *parts[NUM_CHIP_SELECT];
|
||||
unsigned int nr_parts[NUM_CHIP_SELECT];
|
||||
|
||||
const struct pxa3xx_nand_flash * flash;
|
||||
size_t num_flash;
|
||||
|
@ -90,11 +90,6 @@ static struct mtd_partition nand_partitions[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition *nand_part_info(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(nand_partitions);
|
||||
return nand_partitions;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
|
||||
.cle = 21,
|
||||
@ -102,7 +97,8 @@ static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
|
||||
.rdy_pin = GPIO_PIN_PB(28),
|
||||
.enable_pin = GPIO_PIN_PE(23),
|
||||
.bus_width_16 = true,
|
||||
.partition_info = nand_part_info,
|
||||
.parts = nand_partitions,
|
||||
.num_parts = ARRAY_SIZE(nand_partitions),
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -90,18 +90,13 @@ static struct mtd_partition nand_partitions[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static struct mtd_partition *nand_part_info(int size, int *num_partitions)
|
||||
{
|
||||
*num_partitions = ARRAY_SIZE(nand_partitions);
|
||||
return nand_partitions;
|
||||
}
|
||||
|
||||
static struct atmel_nand_data atstk1006_nand_data __initdata = {
|
||||
.cle = 21,
|
||||
.ale = 22,
|
||||
.rdy_pin = GPIO_PIN_PB(30),
|
||||
.enable_pin = GPIO_PIN_PB(29),
|
||||
.partition_info = nand_part_info,
|
||||
.parts = nand_partitions,
|
||||
.num_parts = ARRAY_SIZE(num_partitions),
|
||||
};
|
||||
#endif
|
||||
|
||||
|
@ -128,7 +128,8 @@ struct atmel_nand_data {
|
||||
u8 ale; /* address line number connected to ALE */
|
||||
u8 cle; /* address line number connected to CLE */
|
||||
u8 bus_width_16; /* buswidth is 16 bit */
|
||||
struct mtd_partition *(*partition_info)(int size, int *num_partitions);
|
||||
struct mtd_partition *parts;
|
||||
unsigned int num_parts;
|
||||
};
|
||||
struct platform_device *
|
||||
at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
|
||||
|
@ -163,7 +163,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
|
||||
this->ecc.mode = NAND_ECC_SOFT;
|
||||
|
||||
/* Enable the following for a flash based bad block table */
|
||||
/* this->options = NAND_USE_FLASH_BBT; */
|
||||
/* this->bbt_options = NAND_BBT_USE_FLASH; */
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
if (nand_scan(crisv32_mtd, 1)) {
|
||||
|
@ -154,7 +154,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
|
||||
this->ecc.mode = NAND_ECC_SOFT;
|
||||
|
||||
/* Enable the following for a flash based bad block table */
|
||||
/* this->options = NAND_USE_FLASH_BBT; */
|
||||
/* this->bbt_options = NAND_BBT_USE_FLASH; */
|
||||
|
||||
/* Scan to find existence of the device */
|
||||
if (nand_scan(crisv32_mtd, 1)) {
|
||||
|
@ -12,27 +12,17 @@ menuconfig MTD
|
||||
|
||||
if MTD
|
||||
|
||||
config MTD_DEBUG
|
||||
bool "Debugging"
|
||||
help
|
||||
This turns on low-level debugging for the entire MTD sub-system.
|
||||
Normally, you should say 'N'.
|
||||
|
||||
config MTD_DEBUG_VERBOSE
|
||||
int "Debugging verbosity (0 = quiet, 3 = noisy)"
|
||||
depends on MTD_DEBUG
|
||||
default "0"
|
||||
help
|
||||
Determines the verbosity level of the MTD debugging messages.
|
||||
|
||||
config MTD_TESTS
|
||||
tristate "MTD tests support"
|
||||
tristate "MTD tests support (DANGEROUS)"
|
||||
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.
|
||||
|
||||
WARNING: some of the tests will ERASE entire MTD device which they
|
||||
test. Do not use these tests unless you really know what you do.
|
||||
|
||||
config MTD_REDBOOT_PARTS
|
||||
tristate "RedBoot partition table parsing"
|
||||
---help---
|
||||
@ -137,7 +127,8 @@ config MTD_AFS_PARTS
|
||||
'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example.
|
||||
|
||||
config MTD_OF_PARTS
|
||||
def_bool y
|
||||
tristate "OpenFirmware partitioning information support"
|
||||
default Y
|
||||
depends on OF
|
||||
help
|
||||
This provides a partition parsing function which derives
|
||||
|
@ -5,8 +5,8 @@
|
||||
# Core functionality.
|
||||
obj-$(CONFIG_MTD) += mtd.o
|
||||
mtd-y := mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o
|
||||
mtd-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
|
||||
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
||||
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
||||
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
||||
|
@ -162,8 +162,8 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
|
||||
}
|
||||
|
||||
static int parse_afs_partitions(struct mtd_info *mtd,
|
||||
struct mtd_partition **pparts,
|
||||
unsigned long origin)
|
||||
struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
struct mtd_partition *parts;
|
||||
u_int mask, off, idx, sz;
|
||||
|
@ -47,7 +47,7 @@ struct ar7_bin_rec {
|
||||
|
||||
static int create_mtd_partitions(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
unsigned long origin)
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
struct ar7_bin_rec header;
|
||||
unsigned int offset;
|
||||
|
@ -145,8 +145,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
|
||||
if (((major << 8) | minor) < 0x3131) {
|
||||
/* CFI version 1.0 => don't trust bootloc */
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL1,
|
||||
"%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
|
||||
pr_debug("%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
|
||||
map->name, cfi->mfr, cfi->id);
|
||||
|
||||
/* AFAICS all 29LV400 with a bottom boot block have a device ID
|
||||
@ -166,8 +165,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
|
||||
* the 8-bit device ID.
|
||||
*/
|
||||
(cfi->mfr == CFI_MFR_MACRONIX)) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1,
|
||||
"%s: Macronix MX29LV400C with bottom boot block"
|
||||
pr_debug("%s: Macronix MX29LV400C with bottom boot block"
|
||||
" detected\n", map->name);
|
||||
extp->TopBottom = 2; /* bottom boot */
|
||||
} else
|
||||
@ -178,8 +176,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
|
||||
extp->TopBottom = 2; /* bottom boot */
|
||||
}
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL1,
|
||||
"%s: AMD CFI PRI V%c.%c has no boot block field;"
|
||||
pr_debug("%s: AMD CFI PRI V%c.%c has no boot block field;"
|
||||
" deduced %s from Device ID\n", map->name, major, minor,
|
||||
extp->TopBottom == 2 ? "bottom" : "top");
|
||||
}
|
||||
@ -191,7 +188,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd)
|
||||
struct map_info *map = mtd->priv;
|
||||
struct cfi_private *cfi = map->fldrv_priv;
|
||||
if (cfi->cfiq->BufWriteTimeoutTyp) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" );
|
||||
pr_debug("Using buffer write method\n" );
|
||||
mtd->write = cfi_amdstd_write_buffers;
|
||||
}
|
||||
}
|
||||
@ -443,8 +440,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary)
|
||||
mtd->writesize = 1;
|
||||
mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n",
|
||||
__func__, mtd->writebufsize);
|
||||
pr_debug("MTD %s(): write buffer size %d\n", __func__,
|
||||
mtd->writebufsize);
|
||||
|
||||
mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot;
|
||||
|
||||
@ -1163,7 +1160,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
|
||||
pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
|
||||
__func__, adr, datum.x[0] );
|
||||
|
||||
/*
|
||||
@ -1174,7 +1171,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
|
||||
*/
|
||||
oldd = map_read(map, adr);
|
||||
if (map_word_equal(map, oldd, datum)) {
|
||||
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n",
|
||||
pr_debug("MTD %s(): NOP\n",
|
||||
__func__);
|
||||
goto op_done;
|
||||
}
|
||||
@ -1400,7 +1397,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
|
||||
|
||||
datum = map_word_load(map, buf);
|
||||
|
||||
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
|
||||
pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n",
|
||||
__func__, adr, datum.x[0] );
|
||||
|
||||
XIP_INVAL_CACHED_RANGE(map, adr, len);
|
||||
@ -1587,7 +1584,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip)
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
|
||||
pr_debug("MTD %s(): ERASE 0x%.8lx\n",
|
||||
__func__, chip->start );
|
||||
|
||||
XIP_INVAL_CACHED_RANGE(map, adr, map->size);
|
||||
@ -1675,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
|
||||
return ret;
|
||||
}
|
||||
|
||||
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
|
||||
pr_debug("MTD %s(): ERASE 0x%.8lx\n",
|
||||
__func__, adr );
|
||||
|
||||
XIP_INVAL_CACHED_RANGE(map, adr, len);
|
||||
@ -1801,8 +1798,7 @@ static int do_atmel_lock(struct map_info *map, struct flchip *chip,
|
||||
goto out_unlock;
|
||||
chip->state = FL_LOCKING;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
|
||||
__func__, adr, len);
|
||||
pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len);
|
||||
|
||||
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
|
||||
cfi->device_type, NULL);
|
||||
@ -1837,8 +1833,7 @@ static int do_atmel_unlock(struct map_info *map, struct flchip *chip,
|
||||
goto out_unlock;
|
||||
chip->state = FL_UNLOCKING;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n",
|
||||
__func__, adr, len);
|
||||
pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len);
|
||||
|
||||
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
|
||||
cfi->device_type, NULL);
|
||||
|
@ -34,8 +34,7 @@ static int fwh_xxlock_oneblock(struct map_info *map, struct flchip *chip,
|
||||
|
||||
/* Refuse the operation if the we cannot look behind the chip */
|
||||
if (chip->start < 0x400000) {
|
||||
DEBUG( MTD_DEBUG_LEVEL3,
|
||||
"MTD %s(): chip->start: %lx wanted >= 0x400000\n",
|
||||
pr_debug( "MTD %s(): chip->start: %lx wanted >= 0x400000\n",
|
||||
__func__, chip->start );
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -1914,11 +1914,10 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi)
|
||||
* (oh and incidentaly the jedec spec - 3.5.3.3) the reset
|
||||
* sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
|
||||
* 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
|
||||
* as they will ignore the writes and dont care what address
|
||||
* as they will ignore the writes and don't care what address
|
||||
* the F0 is written to */
|
||||
if (cfi->addr_unlock1) {
|
||||
DEBUG( MTD_DEBUG_LEVEL3,
|
||||
"reset unlock called %x %x \n",
|
||||
pr_debug( "reset unlock called %x %x \n",
|
||||
cfi->addr_unlock1,cfi->addr_unlock2);
|
||||
cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
|
||||
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
|
||||
@ -1941,7 +1940,7 @@ static int cfi_jedec_setup(struct map_info *map, struct cfi_private *cfi, int in
|
||||
uint8_t uaddr;
|
||||
|
||||
if (!(jedec_table[index].devtypes & cfi->device_type)) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "Rejecting potential %s with incompatible %d-bit device type\n",
|
||||
pr_debug("Rejecting potential %s with incompatible %d-bit device type\n",
|
||||
jedec_table[index].name, 4 * (1<<cfi->device_type));
|
||||
return 0;
|
||||
}
|
||||
@ -2021,7 +2020,7 @@ static inline int jedec_match( uint32_t base,
|
||||
* there aren't.
|
||||
*/
|
||||
if (finfo->dev_id > 0xff) {
|
||||
DEBUG( MTD_DEBUG_LEVEL3, "%s(): ID is not 8bit\n",
|
||||
pr_debug("%s(): ID is not 8bit\n",
|
||||
__func__);
|
||||
goto match_done;
|
||||
}
|
||||
@ -2045,12 +2044,10 @@ static inline int jedec_match( uint32_t base,
|
||||
}
|
||||
|
||||
/* the part size must fit in the memory window */
|
||||
DEBUG( MTD_DEBUG_LEVEL3,
|
||||
"MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
|
||||
pr_debug("MTD %s(): Check fit 0x%.8x + 0x%.8x = 0x%.8x\n",
|
||||
__func__, base, 1 << finfo->dev_size, base + (1 << finfo->dev_size) );
|
||||
if ( base + cfi_interleave(cfi) * ( 1 << finfo->dev_size ) > map->size ) {
|
||||
DEBUG( MTD_DEBUG_LEVEL3,
|
||||
"MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
|
||||
pr_debug("MTD %s(): 0x%.4x 0x%.4x %dKiB doesn't fit\n",
|
||||
__func__, finfo->mfr_id, finfo->dev_id,
|
||||
1 << finfo->dev_size );
|
||||
goto match_done;
|
||||
@ -2061,13 +2058,12 @@ static inline int jedec_match( uint32_t base,
|
||||
|
||||
uaddr = finfo->uaddr;
|
||||
|
||||
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
|
||||
pr_debug("MTD %s(): check unlock addrs 0x%.4x 0x%.4x\n",
|
||||
__func__, cfi->addr_unlock1, cfi->addr_unlock2 );
|
||||
if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
|
||||
&& ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 ||
|
||||
unlock_addrs[uaddr].addr2 / cfi->device_type != cfi->addr_unlock2 ) ) {
|
||||
DEBUG( MTD_DEBUG_LEVEL3,
|
||||
"MTD %s(): 0x%.4x 0x%.4x did not match\n",
|
||||
pr_debug("MTD %s(): 0x%.4x 0x%.4x did not match\n",
|
||||
__func__,
|
||||
unlock_addrs[uaddr].addr1,
|
||||
unlock_addrs[uaddr].addr2);
|
||||
@ -2083,15 +2079,13 @@ static inline int jedec_match( uint32_t base,
|
||||
* FIXME - write a driver that takes all of the chip info as
|
||||
* module parameters, doesn't probe but forces a load.
|
||||
*/
|
||||
DEBUG( MTD_DEBUG_LEVEL3,
|
||||
"MTD %s(): check ID's disappear when not in ID mode\n",
|
||||
pr_debug("MTD %s(): check ID's disappear when not in ID mode\n",
|
||||
__func__ );
|
||||
jedec_reset( base, map, cfi );
|
||||
mfr = jedec_read_mfr( map, base, cfi );
|
||||
id = jedec_read_id( map, base, cfi );
|
||||
if ( mfr == cfi->mfr && id == cfi->id ) {
|
||||
DEBUG( MTD_DEBUG_LEVEL3,
|
||||
"MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n"
|
||||
pr_debug("MTD %s(): ID 0x%.2x:0x%.2x did not change after reset:\n"
|
||||
"You might need to manually specify JEDEC parameters.\n",
|
||||
__func__, cfi->mfr, cfi->id );
|
||||
goto match_done;
|
||||
@ -2104,7 +2098,7 @@ static inline int jedec_match( uint32_t base,
|
||||
* Put the device back in ID mode - only need to do this if we
|
||||
* were truly frobbing a real device.
|
||||
*/
|
||||
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): return to ID mode\n", __func__ );
|
||||
pr_debug("MTD %s(): return to ID mode\n", __func__ );
|
||||
if (cfi->addr_unlock1) {
|
||||
cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
|
||||
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, base, map, cfi, cfi->device_type, NULL);
|
||||
@ -2167,13 +2161,11 @@ static int jedec_probe_chip(struct map_info *map, __u32 base,
|
||||
|
||||
cfi->mfr = jedec_read_mfr(map, base, cfi);
|
||||
cfi->id = jedec_read_id(map, base, cfi);
|
||||
DEBUG(MTD_DEBUG_LEVEL3,
|
||||
"Search for id:(%02x %02x) interleave(%d) type(%d)\n",
|
||||
pr_debug("Search for id:(%02x %02x) interleave(%d) type(%d)\n",
|
||||
cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
|
||||
for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
|
||||
if ( jedec_match( base, map, cfi, &jedec_table[i] ) ) {
|
||||
DEBUG( MTD_DEBUG_LEVEL3,
|
||||
"MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
|
||||
pr_debug("MTD %s(): matched device 0x%x,0x%x unlock_addrs: 0x%.4x 0x%.4x\n",
|
||||
__func__, cfi->mfr, cfi->id,
|
||||
cfi->addr_unlock1, cfi->addr_unlock2 );
|
||||
if (!cfi_jedec_setup(map, cfi, i))
|
||||
|
@ -189,10 +189,7 @@ static struct mtd_partition * newpart(char *s,
|
||||
extra_mem_size;
|
||||
parts = kzalloc(alloc_size, GFP_KERNEL);
|
||||
if (!parts)
|
||||
{
|
||||
printk(KERN_ERR ERRP "out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
extra_mem = (unsigned char *)(parts + *num_parts);
|
||||
}
|
||||
/* enter this partition (offset will be calculated later if it is zero at this point) */
|
||||
@ -317,8 +314,8 @@ static int mtdpart_setup_real(char *s)
|
||||
* the first one in the chain if a NULL mtd_id is passed in.
|
||||
*/
|
||||
static int parse_cmdline_partitions(struct mtd_info *master,
|
||||
struct mtd_partition **pparts,
|
||||
unsigned long origin)
|
||||
struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
unsigned long offset;
|
||||
int i;
|
||||
|
@ -249,6 +249,16 @@ config MTD_DOC2001PLUS
|
||||
under "NAND Flash Device Drivers" (currently that driver does not
|
||||
support all Millennium Plus devices).
|
||||
|
||||
config MTD_DOCG3
|
||||
tristate "M-Systems Disk-On-Chip G3"
|
||||
---help---
|
||||
This provides an MTD device driver for the M-Systems DiskOnChip
|
||||
G3 devices.
|
||||
|
||||
The driver provides access to G3 DiskOnChip, distributed by
|
||||
M-Systems and now Sandisk. The support is very experimental,
|
||||
and doesn't give access to any write operations.
|
||||
|
||||
config MTD_DOCPROBE
|
||||
tristate
|
||||
select MTD_DOCECC
|
||||
@ -268,8 +278,7 @@ config MTD_DOCPROBE_ADVANCED
|
||||
config MTD_DOCPROBE_ADDRESS
|
||||
hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED
|
||||
depends on MTD_DOCPROBE
|
||||
default "0x0000" if MTD_DOCPROBE_ADVANCED
|
||||
default "0" if !MTD_DOCPROBE_ADVANCED
|
||||
default "0x0"
|
||||
---help---
|
||||
By default, the probe for DiskOnChip devices will look for a
|
||||
DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
|
||||
|
@ -5,6 +5,7 @@
|
||||
obj-$(CONFIG_MTD_DOC2000) += doc2000.o
|
||||
obj-$(CONFIG_MTD_DOC2001) += doc2001.o
|
||||
obj-$(CONFIG_MTD_DOC2001PLUS) += doc2001plus.o
|
||||
obj-$(CONFIG_MTD_DOCG3) += docg3.o
|
||||
obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o
|
||||
obj-$(CONFIG_MTD_DOCECC) += docecc.o
|
||||
obj-$(CONFIG_MTD_SLRAM) += slram.o
|
||||
@ -17,3 +18,5 @@ obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o
|
||||
obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o
|
||||
obj-$(CONFIG_MTD_M25P80) += m25p80.o
|
||||
obj-$(CONFIG_MTD_SST25L) += sst25l.o
|
||||
|
||||
CFLAGS_docg3.o += -I$(src)
|
@ -82,8 +82,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc)
|
||||
void __iomem *docptr = doc->virtadr;
|
||||
unsigned long timeo = jiffies + (HZ * 10);
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3,
|
||||
"_DoC_WaitReady called for out-of-line wait\n");
|
||||
pr_debug("_DoC_WaitReady called for out-of-line wait\n");
|
||||
|
||||
/* Out-of-line routine to wait for chip response */
|
||||
while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
|
||||
@ -92,7 +91,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc)
|
||||
DoC_Delay(doc, 2);
|
||||
|
||||
if (time_after(jiffies, timeo)) {
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
|
||||
pr_debug("_DoC_WaitReady timed out.\n");
|
||||
return -EIO;
|
||||
}
|
||||
udelay(1);
|
||||
@ -323,8 +322,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
|
||||
|
||||
/* Reset the chip */
|
||||
if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {
|
||||
DEBUG(MTD_DEBUG_LEVEL2,
|
||||
"DoC_Command (reset) for %d,%d returned true\n",
|
||||
pr_debug("DoC_Command (reset) for %d,%d returned true\n",
|
||||
floor, chip);
|
||||
return 0;
|
||||
}
|
||||
@ -332,8 +330,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
|
||||
|
||||
/* Read the NAND chip ID: 1. Send ReadID command */
|
||||
if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {
|
||||
DEBUG(MTD_DEBUG_LEVEL2,
|
||||
"DoC_Command (ReadID) for %d,%d returned true\n",
|
||||
pr_debug("DoC_Command (ReadID) for %d,%d returned true\n",
|
||||
floor, chip);
|
||||
return 0;
|
||||
}
|
||||
@ -699,7 +696,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
#ifdef ECC_DEBUG
|
||||
printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
|
||||
#endif
|
||||
/* Read the ECC syndrom through the DiskOnChip ECC
|
||||
/* Read the ECC syndrome through the DiskOnChip ECC
|
||||
logic. These syndrome will be all ZERO when there
|
||||
is no error */
|
||||
for (i = 0; i < 6; i++) {
|
||||
@ -930,7 +927,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
|
||||
uint8_t *buf = ops->oobbuf;
|
||||
size_t len = ops->len;
|
||||
|
||||
BUG_ON(ops->mode != MTD_OOB_PLACE);
|
||||
BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
|
||||
|
||||
ofs += ops->ooboffs;
|
||||
|
||||
@ -1094,7 +1091,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
|
||||
struct DiskOnChip *this = mtd->priv;
|
||||
int ret;
|
||||
|
||||
BUG_ON(ops->mode != MTD_OOB_PLACE);
|
||||
BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
|
||||
|
||||
mutex_lock(&this->lock);
|
||||
ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,
|
||||
|
@ -55,15 +55,14 @@ static int _DoC_WaitReady(void __iomem * docptr)
|
||||
{
|
||||
unsigned short c = 0xffff;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3,
|
||||
"_DoC_WaitReady called for out-of-line wait\n");
|
||||
pr_debug("_DoC_WaitReady called for out-of-line wait\n");
|
||||
|
||||
/* Out-of-line routine to wait for chip response */
|
||||
while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
|
||||
;
|
||||
|
||||
if (c == 0)
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
|
||||
pr_debug("_DoC_WaitReady timed out.\n");
|
||||
|
||||
return (c == 0);
|
||||
}
|
||||
@ -464,7 +463,7 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
|
||||
#ifdef ECC_DEBUG
|
||||
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
|
||||
#endif
|
||||
/* Read the ECC syndrom through the DiskOnChip ECC logic.
|
||||
/* Read the ECC syndrome through the DiskOnChip ECC logic.
|
||||
These syndrome will be all ZERO when there is no error */
|
||||
for (i = 0; i < 6; i++) {
|
||||
syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
|
||||
@ -632,7 +631,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
|
||||
uint8_t *buf = ops->oobbuf;
|
||||
size_t len = ops->len;
|
||||
|
||||
BUG_ON(ops->mode != MTD_OOB_PLACE);
|
||||
BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
|
||||
|
||||
ofs += ops->ooboffs;
|
||||
|
||||
@ -690,7 +689,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
|
||||
uint8_t *buf = ops->oobbuf;
|
||||
size_t len = ops->len;
|
||||
|
||||
BUG_ON(ops->mode != MTD_OOB_PLACE);
|
||||
BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
|
||||
|
||||
ofs += ops->ooboffs;
|
||||
|
||||
|
@ -61,15 +61,14 @@ static int _DoC_WaitReady(void __iomem * docptr)
|
||||
{
|
||||
unsigned int c = 0xffff;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3,
|
||||
"_DoC_WaitReady called for out-of-line wait\n");
|
||||
pr_debug("_DoC_WaitReady called for out-of-line wait\n");
|
||||
|
||||
/* Out-of-line routine to wait for chip response */
|
||||
while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
|
||||
;
|
||||
|
||||
if (c == 0)
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
|
||||
pr_debug("_DoC_WaitReady timed out.\n");
|
||||
|
||||
return (c == 0);
|
||||
}
|
||||
@ -655,7 +654,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
#ifdef ECC_DEBUG
|
||||
printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
|
||||
#endif
|
||||
/* Read the ECC syndrom through the DiskOnChip ECC logic.
|
||||
/* Read the ECC syndrome through the DiskOnChip ECC logic.
|
||||
These syndrome will be all ZERO when there is no error */
|
||||
for (i = 0; i < 6; i++)
|
||||
syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
|
||||
@ -835,7 +834,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
|
||||
uint8_t *buf = ops->oobbuf;
|
||||
size_t len = ops->len;
|
||||
|
||||
BUG_ON(ops->mode != MTD_OOB_PLACE);
|
||||
BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
|
||||
|
||||
ofs += ops->ooboffs;
|
||||
|
||||
@ -920,7 +919,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
|
||||
uint8_t *buf = ops->oobbuf;
|
||||
size_t len = ops->len;
|
||||
|
||||
BUG_ON(ops->mode != MTD_OOB_PLACE);
|
||||
BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
|
||||
|
||||
ofs += ops->ooboffs;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ECC algorithm for M-systems disk on chip. We use the excellent Reed
|
||||
* Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the
|
||||
* GNU GPL License. The rest is simply to convert the disk on chip
|
||||
* syndrom into a standard syndom.
|
||||
* syndrome into a standard syndome.
|
||||
*
|
||||
* Author: Fabrice Bellard (fabrice.bellard@netgem.com)
|
||||
* Copyright (C) 2000 Netgem S.A.
|
||||
|
1114
drivers/mtd/devices/docg3.c
Normal file
1114
drivers/mtd/devices/docg3.c
Normal file
File diff suppressed because it is too large
Load Diff
297
drivers/mtd/devices/docg3.h
Normal file
297
drivers/mtd/devices/docg3.h
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Handles the M-Systems DiskOnChip G3 chip
|
||||
*
|
||||
* Copyright (C) 2011 Robert Jarzmik
|
||||
*
|
||||
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _MTD_DOCG3_H
|
||||
#define _MTD_DOCG3_H
|
||||
|
||||
/*
|
||||
* Flash memory areas :
|
||||
* - 0x0000 .. 0x07ff : IPL
|
||||
* - 0x0800 .. 0x0fff : Data area
|
||||
* - 0x1000 .. 0x17ff : Registers
|
||||
* - 0x1800 .. 0x1fff : Unknown
|
||||
*/
|
||||
#define DOC_IOSPACE_IPL 0x0000
|
||||
#define DOC_IOSPACE_DATA 0x0800
|
||||
#define DOC_IOSPACE_SIZE 0x2000
|
||||
|
||||
/*
|
||||
* DOC G3 layout and adressing scheme
|
||||
* A page address for the block "b", plane "P" and page "p":
|
||||
* address = [bbbb bPpp pppp]
|
||||
*/
|
||||
|
||||
#define DOC_ADDR_PAGE_MASK 0x3f
|
||||
#define DOC_ADDR_BLOCK_SHIFT 6
|
||||
#define DOC_LAYOUT_NBPLANES 2
|
||||
#define DOC_LAYOUT_PAGES_PER_BLOCK 64
|
||||
#define DOC_LAYOUT_PAGE_SIZE 512
|
||||
#define DOC_LAYOUT_OOB_SIZE 16
|
||||
#define DOC_LAYOUT_WEAR_SIZE 8
|
||||
#define DOC_LAYOUT_PAGE_OOB_SIZE \
|
||||
(DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_SIZE)
|
||||
#define DOC_LAYOUT_WEAR_OFFSET (DOC_LAYOUT_PAGE_OOB_SIZE * 2)
|
||||
#define DOC_LAYOUT_BLOCK_SIZE \
|
||||
(DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE)
|
||||
#define DOC_ECC_BCH_SIZE 7
|
||||
#define DOC_ECC_BCH_COVERED_BYTES \
|
||||
(DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ + \
|
||||
DOC_LAYOUT_OOB_HAMMING_SZ + DOC_LAYOUT_OOB_BCH_SZ)
|
||||
|
||||
/*
|
||||
* Blocks distribution
|
||||
*/
|
||||
#define DOC_LAYOUT_BLOCK_BBT 0
|
||||
#define DOC_LAYOUT_BLOCK_OTP 0
|
||||
#define DOC_LAYOUT_BLOCK_FIRST_DATA 6
|
||||
|
||||
#define DOC_LAYOUT_PAGE_BBT 4
|
||||
|
||||
/*
|
||||
* Extra page OOB (16 bytes wide) layout
|
||||
*/
|
||||
#define DOC_LAYOUT_OOB_PAGEINFO_OFS 0
|
||||
#define DOC_LAYOUT_OOB_HAMMING_OFS 7
|
||||
#define DOC_LAYOUT_OOB_BCH_OFS 8
|
||||
#define DOC_LAYOUT_OOB_UNUSED_OFS 15
|
||||
#define DOC_LAYOUT_OOB_PAGEINFO_SZ 7
|
||||
#define DOC_LAYOUT_OOB_HAMMING_SZ 1
|
||||
#define DOC_LAYOUT_OOB_BCH_SZ 7
|
||||
#define DOC_LAYOUT_OOB_UNUSED_SZ 1
|
||||
|
||||
|
||||
#define DOC_CHIPID_G3 0x200
|
||||
#define DOC_ERASE_MARK 0xaa
|
||||
/*
|
||||
* Flash registers
|
||||
*/
|
||||
#define DOC_CHIPID 0x1000
|
||||
#define DOC_TEST 0x1004
|
||||
#define DOC_BUSLOCK 0x1006
|
||||
#define DOC_ENDIANCONTROL 0x1008
|
||||
#define DOC_DEVICESELECT 0x100a
|
||||
#define DOC_ASICMODE 0x100c
|
||||
#define DOC_CONFIGURATION 0x100e
|
||||
#define DOC_INTERRUPTCONTROL 0x1010
|
||||
#define DOC_READADDRESS 0x101a
|
||||
#define DOC_DATAEND 0x101e
|
||||
#define DOC_INTERRUPTSTATUS 0x1020
|
||||
|
||||
#define DOC_FLASHSEQUENCE 0x1032
|
||||
#define DOC_FLASHCOMMAND 0x1034
|
||||
#define DOC_FLASHADDRESS 0x1036
|
||||
#define DOC_FLASHCONTROL 0x1038
|
||||
#define DOC_NOP 0x103e
|
||||
|
||||
#define DOC_ECCCONF0 0x1040
|
||||
#define DOC_ECCCONF1 0x1042
|
||||
#define DOC_ECCPRESET 0x1044
|
||||
#define DOC_HAMMINGPARITY 0x1046
|
||||
#define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 1))
|
||||
|
||||
#define DOC_PROTECTION 0x1056
|
||||
#define DOC_DPS0_ADDRLOW 0x1060
|
||||
#define DOC_DPS0_ADDRHIGH 0x1062
|
||||
#define DOC_DPS1_ADDRLOW 0x1064
|
||||
#define DOC_DPS1_ADDRHIGH 0x1066
|
||||
#define DOC_DPS0_STATUS 0x106c
|
||||
#define DOC_DPS1_STATUS 0x106e
|
||||
|
||||
#define DOC_ASICMODECONFIRM 0x1072
|
||||
#define DOC_CHIPID_INV 0x1074
|
||||
|
||||
/*
|
||||
* Flash sequences
|
||||
* A sequence is preset before one or more commands are input to the chip.
|
||||
*/
|
||||
#define DOC_SEQ_RESET 0x00
|
||||
#define DOC_SEQ_PAGE_SIZE_532 0x03
|
||||
#define DOC_SEQ_SET_MODE 0x09
|
||||
#define DOC_SEQ_READ 0x12
|
||||
#define DOC_SEQ_SET_PLANE1 0x0e
|
||||
#define DOC_SEQ_SET_PLANE2 0x10
|
||||
#define DOC_SEQ_PAGE_SETUP 0x1d
|
||||
|
||||
/*
|
||||
* Flash commands
|
||||
*/
|
||||
#define DOC_CMD_READ_PLANE1 0x00
|
||||
#define DOC_CMD_SET_ADDR_READ 0x05
|
||||
#define DOC_CMD_READ_ALL_PLANES 0x30
|
||||
#define DOC_CMD_READ_PLANE2 0x50
|
||||
#define DOC_CMD_READ_FLASH 0xe0
|
||||
#define DOC_CMD_PAGE_SIZE_532 0x3c
|
||||
|
||||
#define DOC_CMD_PROG_BLOCK_ADDR 0x60
|
||||
#define DOC_CMD_PROG_CYCLE1 0x80
|
||||
#define DOC_CMD_PROG_CYCLE2 0x10
|
||||
#define DOC_CMD_ERASECYCLE2 0xd0
|
||||
|
||||
#define DOC_CMD_RELIABLE_MODE 0x22
|
||||
#define DOC_CMD_FAST_MODE 0xa2
|
||||
|
||||
#define DOC_CMD_RESET 0xff
|
||||
|
||||
/*
|
||||
* Flash register : DOC_FLASHCONTROL
|
||||
*/
|
||||
#define DOC_CTRL_VIOLATION 0x20
|
||||
#define DOC_CTRL_CE 0x10
|
||||
#define DOC_CTRL_UNKNOWN_BITS 0x08
|
||||
#define DOC_CTRL_PROTECTION_ERROR 0x04
|
||||
#define DOC_CTRL_SEQUENCE_ERROR 0x02
|
||||
#define DOC_CTRL_FLASHREADY 0x01
|
||||
|
||||
/*
|
||||
* Flash register : DOC_ASICMODE
|
||||
*/
|
||||
#define DOC_ASICMODE_RESET 0x00
|
||||
#define DOC_ASICMODE_NORMAL 0x01
|
||||
#define DOC_ASICMODE_POWERDOWN 0x02
|
||||
#define DOC_ASICMODE_MDWREN 0x04
|
||||
#define DOC_ASICMODE_BDETCT_RESET 0x08
|
||||
#define DOC_ASICMODE_RSTIN_RESET 0x10
|
||||
#define DOC_ASICMODE_RAM_WE 0x20
|
||||
|
||||
/*
|
||||
* Flash register : DOC_ECCCONF0
|
||||
*/
|
||||
#define DOC_ECCCONF0_READ_MODE 0x8000
|
||||
#define DOC_ECCCONF0_AUTO_ECC_ENABLE 0x4000
|
||||
#define DOC_ECCCONF0_HAMMING_ENABLE 0x1000
|
||||
#define DOC_ECCCONF0_BCH_ENABLE 0x0800
|
||||
#define DOC_ECCCONF0_DATA_BYTES_MASK 0x07ff
|
||||
|
||||
/*
|
||||
* Flash register : DOC_ECCCONF1
|
||||
*/
|
||||
#define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80
|
||||
#define DOC_ECCCONF1_UNKOWN1 0x40
|
||||
#define DOC_ECCCONF1_UNKOWN2 0x20
|
||||
#define DOC_ECCCONF1_UNKOWN3 0x10
|
||||
#define DOC_ECCCONF1_HAMMING_BITS_MASK 0x0f
|
||||
|
||||
/*
|
||||
* Flash register : DOC_PROTECTION
|
||||
*/
|
||||
#define DOC_PROTECT_FOUNDRY_OTP_LOCK 0x01
|
||||
#define DOC_PROTECT_CUSTOMER_OTP_LOCK 0x02
|
||||
#define DOC_PROTECT_LOCK_INPUT 0x04
|
||||
#define DOC_PROTECT_STICKY_LOCK 0x08
|
||||
#define DOC_PROTECT_PROTECTION_ENABLED 0x10
|
||||
#define DOC_PROTECT_IPL_DOWNLOAD_LOCK 0x20
|
||||
#define DOC_PROTECT_PROTECTION_ERROR 0x80
|
||||
|
||||
/*
|
||||
* Flash register : DOC_DPS0_STATUS and DOC_DPS1_STATUS
|
||||
*/
|
||||
#define DOC_DPS_OTP_PROTECTED 0x01
|
||||
#define DOC_DPS_READ_PROTECTED 0x02
|
||||
#define DOC_DPS_WRITE_PROTECTED 0x04
|
||||
#define DOC_DPS_HW_LOCK_ENABLED 0x08
|
||||
#define DOC_DPS_KEY_OK 0x80
|
||||
|
||||
/*
|
||||
* Flash register : DOC_CONFIGURATION
|
||||
*/
|
||||
#define DOC_CONF_IF_CFG 0x80
|
||||
#define DOC_CONF_MAX_ID_MASK 0x30
|
||||
#define DOC_CONF_VCCQ_3V 0x01
|
||||
|
||||
/*
|
||||
* Flash register : DOC_READADDRESS
|
||||
*/
|
||||
#define DOC_READADDR_INC 0x8000
|
||||
#define DOC_READADDR_ONE_BYTE 0x4000
|
||||
#define DOC_READADDR_ADDR_MASK 0x1fff
|
||||
|
||||
/**
|
||||
* struct docg3 - DiskOnChip driver private data
|
||||
* @dev: the device currently under control
|
||||
* @base: mapped IO space
|
||||
* @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3)
|
||||
* @if_cfg: if true, reads are on 16bits, else reads are on 8bits
|
||||
* @bbt: bad block table cache
|
||||
* @debugfs_root: debugfs root node
|
||||
*/
|
||||
struct docg3 {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
unsigned int device_id:4;
|
||||
unsigned int if_cfg:1;
|
||||
int max_block;
|
||||
u8 *bbt;
|
||||
struct dentry *debugfs_root;
|
||||
};
|
||||
|
||||
#define doc_err(fmt, arg...) dev_err(docg3->dev, (fmt), ## arg)
|
||||
#define doc_info(fmt, arg...) dev_info(docg3->dev, (fmt), ## arg)
|
||||
#define doc_dbg(fmt, arg...) dev_dbg(docg3->dev, (fmt), ## arg)
|
||||
#define doc_vdbg(fmt, arg...) dev_vdbg(docg3->dev, (fmt), ## arg)
|
||||
|
||||
#define DEBUGFS_RO_ATTR(name, show_fct) \
|
||||
static int name##_open(struct inode *inode, struct file *file) \
|
||||
{ return single_open(file, show_fct, inode->i_private); } \
|
||||
static const struct file_operations name##_fops = { \
|
||||
.owner = THIS_MODULE, \
|
||||
.open = name##_open, \
|
||||
.llseek = seq_lseek, \
|
||||
.read = seq_read, \
|
||||
.release = single_release \
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Trace events part
|
||||
*/
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM docg3
|
||||
|
||||
#if !defined(_MTD_DOCG3_TRACE) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _MTD_DOCG3_TRACE
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
TRACE_EVENT(docg3_io,
|
||||
TP_PROTO(int op, int width, u16 reg, int val),
|
||||
TP_ARGS(op, width, reg, val),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, op)
|
||||
__field(unsigned char, width)
|
||||
__field(u16, reg)
|
||||
__field(int, val)),
|
||||
TP_fast_assign(
|
||||
__entry->op = op;
|
||||
__entry->width = width;
|
||||
__entry->reg = reg;
|
||||
__entry->val = val;),
|
||||
TP_printk("docg3: %s%02d reg=%04x, val=%04x",
|
||||
__entry->op ? "write" : "read", __entry->width,
|
||||
__entry->reg, __entry->val)
|
||||
);
|
||||
#endif
|
||||
|
||||
/* This part must be outside protection */
|
||||
#undef TRACE_INCLUDE_PATH
|
||||
#undef TRACE_INCLUDE_FILE
|
||||
#define TRACE_INCLUDE_PATH .
|
||||
#define TRACE_INCLUDE_FILE docg3
|
||||
#include <trace/define_trace.h>
|
@ -50,11 +50,6 @@
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mtd/doc2000.h>
|
||||
|
||||
/* Where to look for the devices? */
|
||||
#ifndef CONFIG_MTD_DOCPROBE_ADDRESS
|
||||
#define CONFIG_MTD_DOCPROBE_ADDRESS 0
|
||||
#endif
|
||||
|
||||
|
||||
static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
|
||||
module_param(doc_config_location, ulong, 0);
|
||||
|
@ -34,9 +34,6 @@
|
||||
/* debugging */
|
||||
//#define LART_DEBUG
|
||||
|
||||
/* partition support */
|
||||
#define HAVE_PARTITIONS
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
@ -44,9 +41,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#ifdef HAVE_PARTITIONS
|
||||
#include <linux/mtd/partitions.h>
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SA1100_LART
|
||||
#error This is for LART architecture only
|
||||
@ -598,7 +593,6 @@ static struct mtd_erase_region_info erase_regions[] = {
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef HAVE_PARTITIONS
|
||||
static struct mtd_partition lart_partitions[] = {
|
||||
/* blob */
|
||||
{
|
||||
@ -619,7 +613,7 @@ static struct mtd_partition lart_partitions[] = {
|
||||
.size = INITRD_LEN, /* MTDPART_SIZ_FULL */
|
||||
}
|
||||
};
|
||||
#endif
|
||||
#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
|
||||
|
||||
static int __init lart_flash_init (void)
|
||||
{
|
||||
@ -668,7 +662,6 @@ static int __init lart_flash_init (void)
|
||||
result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024,
|
||||
result,mtd.eraseregions[result].numblocks);
|
||||
|
||||
#ifdef HAVE_PARTITIONS
|
||||
printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
|
||||
|
||||
for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
|
||||
@ -681,25 +674,16 @@ static int __init lart_flash_init (void)
|
||||
result,lart_partitions[result].offset,
|
||||
result,lart_partitions[result].size,lart_partitions[result].size / 1024);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PARTITIONS
|
||||
result = mtd_device_register(&mtd, NULL, 0);
|
||||
#else
|
||||
result = mtd_device_register(&mtd, lart_partitions,
|
||||
ARRAY_SIZE(lart_partitions));
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static void __exit lart_flash_exit (void)
|
||||
{
|
||||
#ifndef HAVE_PARTITIONS
|
||||
mtd_device_unregister(&mtd);
|
||||
#else
|
||||
mtd_device_unregister(&mtd);
|
||||
#endif
|
||||
}
|
||||
|
||||
module_init (lart_flash_init);
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <linux/mtd/cfi.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/of_platform.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/flash.h>
|
||||
@ -88,7 +89,6 @@ struct m25p {
|
||||
struct spi_device *spi;
|
||||
struct mutex lock;
|
||||
struct mtd_info mtd;
|
||||
unsigned partitioned:1;
|
||||
u16 page_size;
|
||||
u16 addr_width;
|
||||
u8 erase_opcode;
|
||||
@ -209,9 +209,8 @@ static int wait_till_ready(struct m25p *flash)
|
||||
*/
|
||||
static int erase_chip(struct m25p *flash)
|
||||
{
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n",
|
||||
dev_name(&flash->spi->dev), __func__,
|
||||
(long long)(flash->mtd.size >> 10));
|
||||
pr_debug("%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))
|
||||
@ -250,9 +249,8 @@ static int m25p_cmdsz(struct m25p *flash)
|
||||
*/
|
||||
static int erase_sector(struct m25p *flash, u32 offset)
|
||||
{
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
|
||||
dev_name(&flash->spi->dev), __func__,
|
||||
flash->mtd.erasesize / 1024, offset);
|
||||
pr_debug("%s: %s %dKiB at 0x%08x\n", dev_name(&flash->spi->dev),
|
||||
__func__, flash->mtd.erasesize / 1024, offset);
|
||||
|
||||
/* Wait until finished previous write command. */
|
||||
if (wait_till_ready(flash))
|
||||
@ -286,9 +284,9 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
u32 addr,len;
|
||||
uint32_t rem;
|
||||
|
||||
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);
|
||||
pr_debug("%s: %s at 0x%llx, len %lld\n", dev_name(&flash->spi->dev),
|
||||
__func__, (long long)instr->addr,
|
||||
(long long)instr->len);
|
||||
|
||||
/* sanity checks */
|
||||
if (instr->addr + instr->len > flash->mtd.size)
|
||||
@ -348,9 +346,8 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
struct spi_transfer t[2];
|
||||
struct spi_message m;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
|
||||
dev_name(&flash->spi->dev), __func__, "from",
|
||||
(u32)from, len);
|
||||
pr_debug("%s: %s from 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
|
||||
__func__, (u32)from, len);
|
||||
|
||||
/* sanity checks */
|
||||
if (!len)
|
||||
@ -417,9 +414,8 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
struct spi_transfer t[2];
|
||||
struct spi_message m;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
|
||||
dev_name(&flash->spi->dev), __func__, "to",
|
||||
(u32)to, len);
|
||||
pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
|
||||
__func__, (u32)to, len);
|
||||
|
||||
*retlen = 0;
|
||||
|
||||
@ -510,9 +506,8 @@ 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);
|
||||
pr_debug("%s: %s to 0x%08x, len %zd\n", dev_name(&flash->spi->dev),
|
||||
__func__, (u32)to, len);
|
||||
|
||||
*retlen = 0;
|
||||
|
||||
@ -661,6 +656,7 @@ static const struct spi_device_id m25p_ids[] = {
|
||||
{ "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) },
|
||||
|
||||
{ "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) },
|
||||
{ "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
|
||||
{ "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
|
||||
|
||||
{ "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) },
|
||||
@ -671,6 +667,7 @@ static const struct spi_device_id m25p_ids[] = {
|
||||
/* EON -- en25xxx */
|
||||
{ "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
|
||||
{ "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
|
||||
{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
|
||||
{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
|
||||
|
||||
/* Intel/Numonyx -- xxxs33b */
|
||||
@ -788,8 +785,8 @@ static const struct spi_device_id *__devinit jedec_probe(struct spi_device *spi)
|
||||
*/
|
||||
tmp = spi_write_then_read(spi, &code, 1, id, 5);
|
||||
if (tmp < 0) {
|
||||
DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
|
||||
dev_name(&spi->dev), tmp);
|
||||
pr_debug("%s: error %d reading JEDEC ID\n",
|
||||
dev_name(&spi->dev), tmp);
|
||||
return ERR_PTR(tmp);
|
||||
}
|
||||
jedec = id[0];
|
||||
@ -825,8 +822,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
|
||||
struct m25p *flash;
|
||||
struct flash_info *info;
|
||||
unsigned i;
|
||||
struct mtd_partition *parts = NULL;
|
||||
int nr_parts = 0;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
|
||||
#ifdef CONFIG_MTD_OF_PARTS
|
||||
if (!of_device_is_available(spi->dev.of_node))
|
||||
return -ENODEV;
|
||||
#endif
|
||||
|
||||
/* Platform data helps sort out which chip type we have, as
|
||||
* well as how this board partitions it. If we don't have
|
||||
@ -928,6 +929,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
|
||||
if (info->flags & M25P_NO_ERASE)
|
||||
flash->mtd.flags |= MTD_NO_ERASE;
|
||||
|
||||
ppdata.of_node = spi->dev.of_node;
|
||||
flash->mtd.dev.parent = &spi->dev;
|
||||
flash->page_size = info->page_size;
|
||||
|
||||
@ -945,8 +947,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
|
||||
dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
|
||||
(long long)flash->mtd.size >> 10);
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2,
|
||||
"mtd .name = %s, .size = 0x%llx (%lldMiB) "
|
||||
pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) "
|
||||
".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
|
||||
flash->mtd.name,
|
||||
(long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
|
||||
@ -955,8 +956,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
|
||||
|
||||
if (flash->mtd.numeraseregions)
|
||||
for (i = 0; i < flash->mtd.numeraseregions; i++)
|
||||
DEBUG(MTD_DEBUG_LEVEL2,
|
||||
"mtd.eraseregions[%d] = { .offset = 0x%llx, "
|
||||
pr_debug("mtd.eraseregions[%d] = { .offset = 0x%llx, "
|
||||
".erasesize = 0x%.8x (%uKiB), "
|
||||
".numblocks = %d }\n",
|
||||
i, (long long)flash->mtd.eraseregions[i].offset,
|
||||
@ -968,41 +968,9 @@ static int __devinit m25p_probe(struct spi_device *spi)
|
||||
/* partitions should match sector boundaries; and it may be good to
|
||||
* use readonly partitions for writeprotected sectors (BP2..BP0).
|
||||
*/
|
||||
if (mtd_has_cmdlinepart()) {
|
||||
static const char *part_probes[]
|
||||
= { "cmdlinepart", NULL, };
|
||||
|
||||
nr_parts = parse_mtd_partitions(&flash->mtd,
|
||||
part_probes, &parts, 0);
|
||||
}
|
||||
|
||||
if (nr_parts <= 0 && data && data->parts) {
|
||||
parts = data->parts;
|
||||
nr_parts = data->nr_parts;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_OF_PARTS
|
||||
if (nr_parts <= 0 && spi->dev.of_node) {
|
||||
nr_parts = of_mtd_parse_partitions(&spi->dev,
|
||||
spi->dev.of_node, &parts);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (nr_parts > 0) {
|
||||
for (i = 0; i < nr_parts; i++) {
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
|
||||
"{.name = %s, .offset = 0x%llx, "
|
||||
".size = 0x%llx (%lldKiB) }\n",
|
||||
i, parts[i].name,
|
||||
(long long)parts[i].offset,
|
||||
(long long)parts[i].size,
|
||||
(long long)(parts[i].size >> 10));
|
||||
}
|
||||
flash->partitioned = 1;
|
||||
}
|
||||
|
||||
return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ?
|
||||
-ENODEV : 0;
|
||||
return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
|
||||
data ? data->parts : NULL,
|
||||
data ? data->nr_parts : 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/flash.h>
|
||||
@ -24,7 +26,6 @@
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
|
||||
/*
|
||||
* DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in
|
||||
* each chip, which may be used for double buffered I/O; but this driver
|
||||
@ -98,6 +99,16 @@ struct dataflash {
|
||||
struct mtd_info mtd;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id dataflash_dt_ids[] = {
|
||||
{ .compatible = "atmel,at45", },
|
||||
{ .compatible = "atmel,dataflash", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
#else
|
||||
#define dataflash_dt_ids NULL
|
||||
#endif
|
||||
|
||||
/* ......................................................................... */
|
||||
|
||||
/*
|
||||
@ -122,7 +133,7 @@ static int dataflash_waitready(struct spi_device *spi)
|
||||
for (;;) {
|
||||
status = dataflash_status(spi);
|
||||
if (status < 0) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n",
|
||||
pr_debug("%s: status %d?\n",
|
||||
dev_name(&spi->dev), status);
|
||||
status = 0;
|
||||
}
|
||||
@ -149,7 +160,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
uint8_t *command;
|
||||
uint32_t rem;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%llx len 0x%llx\n",
|
||||
pr_debug("%s: erase addr=0x%llx len 0x%llx\n",
|
||||
dev_name(&spi->dev), (long long)instr->addr,
|
||||
(long long)instr->len);
|
||||
|
||||
@ -187,7 +198,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
|
||||
command[2] = (uint8_t)(pageaddr >> 8);
|
||||
command[3] = 0;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n",
|
||||
pr_debug("ERASE %s: (%x) %x %x %x [%i]\n",
|
||||
do_block ? "block" : "page",
|
||||
command[0], command[1], command[2], command[3],
|
||||
pageaddr);
|
||||
@ -238,8 +249,8 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
uint8_t *command;
|
||||
int status;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n",
|
||||
dev_name(&priv->spi->dev), (unsigned)from, (unsigned)(from + len));
|
||||
pr_debug("%s: read 0x%x..0x%x\n", dev_name(&priv->spi->dev),
|
||||
(unsigned)from, (unsigned)(from + len));
|
||||
|
||||
*retlen = 0;
|
||||
|
||||
@ -255,7 +266,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
|
||||
command = priv->command;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n",
|
||||
pr_debug("READ: (%x) %x %x %x\n",
|
||||
command[0], command[1], command[2], command[3]);
|
||||
|
||||
spi_message_init(&msg);
|
||||
@ -287,7 +298,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
*retlen = msg.actual_length - 8;
|
||||
status = 0;
|
||||
} else
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n",
|
||||
pr_debug("%s: read %x..%x --> %d\n",
|
||||
dev_name(&priv->spi->dev),
|
||||
(unsigned)from, (unsigned)(from + len),
|
||||
status);
|
||||
@ -314,7 +325,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
int status = -EINVAL;
|
||||
uint8_t *command;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n",
|
||||
pr_debug("%s: write 0x%x..0x%x\n",
|
||||
dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len));
|
||||
|
||||
*retlen = 0;
|
||||
@ -340,7 +351,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
while (remaining > 0) {
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
|
||||
pr_debug("write @ %i:%i len=%i\n",
|
||||
pageaddr, offset, writelen);
|
||||
|
||||
/* REVISIT:
|
||||
@ -368,12 +379,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
command[2] = (addr & 0x0000FF00) >> 8;
|
||||
command[3] = 0;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n",
|
||||
pr_debug("TRANSFER: (%x) %x %x %x\n",
|
||||
command[0], command[1], command[2], command[3]);
|
||||
|
||||
status = spi_sync(spi, &msg);
|
||||
if (status < 0)
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n",
|
||||
pr_debug("%s: xfer %u -> %d\n",
|
||||
dev_name(&spi->dev), addr, status);
|
||||
|
||||
(void) dataflash_waitready(priv->spi);
|
||||
@ -386,7 +397,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
command[2] = (addr & 0x0000FF00) >> 8;
|
||||
command[3] = (addr & 0x000000FF);
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n",
|
||||
pr_debug("PROGRAM: (%x) %x %x %x\n",
|
||||
command[0], command[1], command[2], command[3]);
|
||||
|
||||
x[1].tx_buf = writebuf;
|
||||
@ -395,7 +406,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
status = spi_sync(spi, &msg);
|
||||
spi_transfer_del(x + 1);
|
||||
if (status < 0)
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n",
|
||||
pr_debug("%s: pgm %u/%u -> %d\n",
|
||||
dev_name(&spi->dev), addr, writelen, status);
|
||||
|
||||
(void) dataflash_waitready(priv->spi);
|
||||
@ -410,12 +421,12 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
|
||||
command[2] = (addr & 0x0000FF00) >> 8;
|
||||
command[3] = 0;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n",
|
||||
pr_debug("COMPARE: (%x) %x %x %x\n",
|
||||
command[0], command[1], command[2], command[3]);
|
||||
|
||||
status = spi_sync(spi, &msg);
|
||||
if (status < 0)
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n",
|
||||
pr_debug("%s: compare %u -> %d\n",
|
||||
dev_name(&spi->dev), addr, status);
|
||||
|
||||
status = dataflash_waitready(priv->spi);
|
||||
@ -634,11 +645,10 @@ add_dataflash_otp(struct spi_device *spi, char *name,
|
||||
{
|
||||
struct dataflash *priv;
|
||||
struct mtd_info *device;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
struct flash_platform_data *pdata = spi->dev.platform_data;
|
||||
char *otp_tag = "";
|
||||
int err = 0;
|
||||
struct mtd_partition *parts;
|
||||
int nr_parts = 0;
|
||||
|
||||
priv = kzalloc(sizeof *priv, GFP_KERNEL);
|
||||
if (!priv)
|
||||
@ -677,28 +687,11 @@ add_dataflash_otp(struct spi_device *spi, char *name,
|
||||
pagesize, otp_tag);
|
||||
dev_set_drvdata(&spi->dev, priv);
|
||||
|
||||
if (mtd_has_cmdlinepart()) {
|
||||
static const char *part_probes[] = { "cmdlinepart", NULL, };
|
||||
ppdata.of_node = spi->dev.of_node;
|
||||
err = mtd_device_parse_register(device, NULL, &ppdata,
|
||||
pdata ? pdata->parts : NULL,
|
||||
pdata ? pdata->nr_parts : 0);
|
||||
|
||||
nr_parts = parse_mtd_partitions(device, part_probes, &parts,
|
||||
0);
|
||||
}
|
||||
|
||||
if (nr_parts <= 0 && pdata && pdata->parts) {
|
||||
parts = pdata->parts;
|
||||
nr_parts = pdata->nr_parts;
|
||||
}
|
||||
|
||||
if (nr_parts > 0) {
|
||||
priv->partitioned = 1;
|
||||
err = mtd_device_register(device, parts, nr_parts);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (mtd_device_register(device, NULL, 0) == 1)
|
||||
err = -ENODEV;
|
||||
|
||||
out:
|
||||
if (!err)
|
||||
return 0;
|
||||
|
||||
@ -787,7 +780,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
|
||||
*/
|
||||
tmp = spi_write_then_read(spi, &code, 1, id, 3);
|
||||
if (tmp < 0) {
|
||||
DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
|
||||
pr_debug("%s: error %d reading JEDEC ID\n",
|
||||
dev_name(&spi->dev), tmp);
|
||||
return ERR_PTR(tmp);
|
||||
}
|
||||
@ -804,7 +797,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
|
||||
tmp < ARRAY_SIZE(dataflash_data);
|
||||
tmp++, info++) {
|
||||
if (info->jedec_id == jedec) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: OTP, sector protect%s\n",
|
||||
pr_debug("%s: OTP, sector protect%s\n",
|
||||
dev_name(&spi->dev),
|
||||
(info->flags & SUP_POW2PS)
|
||||
? ", binary pagesize" : ""
|
||||
@ -812,8 +805,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
|
||||
if (info->flags & SUP_POW2PS) {
|
||||
status = dataflash_status(spi);
|
||||
if (status < 0) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1,
|
||||
"%s: status error %d\n",
|
||||
pr_debug("%s: status error %d\n",
|
||||
dev_name(&spi->dev), status);
|
||||
return ERR_PTR(status);
|
||||
}
|
||||
@ -878,7 +870,7 @@ static int __devinit dataflash_probe(struct spi_device *spi)
|
||||
*/
|
||||
status = dataflash_status(spi);
|
||||
if (status <= 0 || status == 0xff) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n",
|
||||
pr_debug("%s: status error %d\n",
|
||||
dev_name(&spi->dev), status);
|
||||
if (status == 0 || status == 0xff)
|
||||
status = -ENODEV;
|
||||
@ -914,14 +906,14 @@ static int __devinit dataflash_probe(struct spi_device *spi)
|
||||
break;
|
||||
/* obsolete AT45DB1282 not (yet?) supported */
|
||||
default:
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n",
|
||||
dev_name(&spi->dev), status & 0x3c);
|
||||
pr_debug("%s: unsupported device (%x)\n", dev_name(&spi->dev),
|
||||
status & 0x3c);
|
||||
status = -ENODEV;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n",
|
||||
dev_name(&spi->dev), status);
|
||||
pr_debug("%s: add_dataflash --> %d\n", dev_name(&spi->dev),
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
@ -931,7 +923,7 @@ static int __devexit dataflash_remove(struct spi_device *spi)
|
||||
struct dataflash *flash = dev_get_drvdata(&spi->dev);
|
||||
int status;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev));
|
||||
pr_debug("%s: remove\n", dev_name(&spi->dev));
|
||||
|
||||
status = mtd_device_unregister(&flash->mtd);
|
||||
if (status == 0) {
|
||||
@ -946,6 +938,7 @@ static struct spi_driver dataflash_driver = {
|
||||
.name = "mtd_dataflash",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = dataflash_dt_ids,
|
||||
},
|
||||
|
||||
.probe = dataflash_probe,
|
||||
|
@ -52,8 +52,6 @@ struct sst25l_flash {
|
||||
struct spi_device *spi;
|
||||
struct mutex lock;
|
||||
struct mtd_info mtd;
|
||||
|
||||
int partitioned;
|
||||
};
|
||||
|
||||
struct flash_info {
|
||||
@ -381,8 +379,6 @@ static int __devinit sst25l_probe(struct spi_device *spi)
|
||||
struct sst25l_flash *flash;
|
||||
struct flash_platform_data *data;
|
||||
int ret, i;
|
||||
struct mtd_partition *parts = NULL;
|
||||
int nr_parts = 0;
|
||||
|
||||
flash_info = sst25l_match_device(spi);
|
||||
if (!flash_info)
|
||||
@ -414,8 +410,7 @@ static int __devinit sst25l_probe(struct spi_device *spi)
|
||||
dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name,
|
||||
(long long)flash->mtd.size >> 10);
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2,
|
||||
"mtd .name = %s, .size = 0x%llx (%lldMiB) "
|
||||
pr_debug("mtd .name = %s, .size = 0x%llx (%lldMiB) "
|
||||
".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
|
||||
flash->mtd.name,
|
||||
(long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
|
||||
@ -423,37 +418,10 @@ static int __devinit sst25l_probe(struct spi_device *spi)
|
||||
flash->mtd.numeraseregions);
|
||||
|
||||
|
||||
if (mtd_has_cmdlinepart()) {
|
||||
static const char *part_probes[] = {"cmdlinepart", NULL};
|
||||
|
||||
nr_parts = parse_mtd_partitions(&flash->mtd,
|
||||
part_probes,
|
||||
&parts, 0);
|
||||
}
|
||||
|
||||
if (nr_parts <= 0 && data && data->parts) {
|
||||
parts = data->parts;
|
||||
nr_parts = data->nr_parts;
|
||||
}
|
||||
|
||||
if (nr_parts > 0) {
|
||||
for (i = 0; i < nr_parts; i++) {
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
|
||||
"{.name = %s, .offset = 0x%llx, "
|
||||
".size = 0x%llx (%lldKiB) }\n",
|
||||
i, parts[i].name,
|
||||
(long long)parts[i].offset,
|
||||
(long long)parts[i].size,
|
||||
(long long)(parts[i].size >> 10));
|
||||
}
|
||||
|
||||
flash->partitioned = 1;
|
||||
return mtd_device_register(&flash->mtd, parts,
|
||||
nr_parts);
|
||||
}
|
||||
|
||||
ret = mtd_device_register(&flash->mtd, NULL, 0);
|
||||
if (ret == 1) {
|
||||
ret = mtd_device_parse_register(&flash->mtd, NULL, 0,
|
||||
data ? data->parts : NULL,
|
||||
data ? data->nr_parts : 0);
|
||||
if (ret) {
|
||||
kfree(flash);
|
||||
dev_set_drvdata(&spi->dev, NULL);
|
||||
return -ENODEV;
|
||||
|
@ -339,7 +339,7 @@ static int erase_xfer(partition_t *part,
|
||||
struct erase_info *erase;
|
||||
|
||||
xfer = &part->XferInfo[xfernum];
|
||||
DEBUG(1, "ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset);
|
||||
pr_debug("ftl_cs: erasing xfer unit at 0x%x\n", xfer->Offset);
|
||||
xfer->state = XFER_ERASING;
|
||||
|
||||
/* Is there a free erase slot? Always in MTD. */
|
||||
@ -415,7 +415,7 @@ static int prepare_xfer(partition_t *part, int i)
|
||||
xfer = &part->XferInfo[i];
|
||||
xfer->state = XFER_FAILED;
|
||||
|
||||
DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
|
||||
pr_debug("ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
|
||||
|
||||
/* Write the transfer unit header */
|
||||
header = part->header;
|
||||
@ -476,7 +476,7 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
|
||||
|
||||
eun = &part->EUNInfo[srcunit];
|
||||
xfer = &part->XferInfo[xferunit];
|
||||
DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n",
|
||||
pr_debug("ftl_cs: copying block 0x%x to 0x%x\n",
|
||||
eun->Offset, xfer->Offset);
|
||||
|
||||
|
||||
@ -598,7 +598,7 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
|
||||
unit with the fewest erases, and usually pick the data unit with
|
||||
the most deleted blocks. But with a small probability, pick the
|
||||
oldest data unit instead. This means that we generally postpone
|
||||
the next reclaimation as long as possible, but shuffle static
|
||||
the next reclamation as long as possible, but shuffle static
|
||||
stuff around a bit for wear leveling.
|
||||
|
||||
======================================================================*/
|
||||
@ -609,8 +609,8 @@ static int reclaim_block(partition_t *part)
|
||||
uint32_t best;
|
||||
int queued, ret;
|
||||
|
||||
DEBUG(0, "ftl_cs: reclaiming space...\n");
|
||||
DEBUG(3, "NumTransferUnits == %x\n", part->header.NumTransferUnits);
|
||||
pr_debug("ftl_cs: reclaiming space...\n");
|
||||
pr_debug("NumTransferUnits == %x\n", part->header.NumTransferUnits);
|
||||
/* Pick the least erased transfer unit */
|
||||
best = 0xffffffff; xfer = 0xffff;
|
||||
do {
|
||||
@ -618,22 +618,22 @@ static int reclaim_block(partition_t *part)
|
||||
for (i = 0; i < part->header.NumTransferUnits; i++) {
|
||||
int n=0;
|
||||
if (part->XferInfo[i].state == XFER_UNKNOWN) {
|
||||
DEBUG(3,"XferInfo[%d].state == XFER_UNKNOWN\n",i);
|
||||
pr_debug("XferInfo[%d].state == XFER_UNKNOWN\n",i);
|
||||
n=1;
|
||||
erase_xfer(part, i);
|
||||
}
|
||||
if (part->XferInfo[i].state == XFER_ERASING) {
|
||||
DEBUG(3,"XferInfo[%d].state == XFER_ERASING\n",i);
|
||||
pr_debug("XferInfo[%d].state == XFER_ERASING\n",i);
|
||||
n=1;
|
||||
queued = 1;
|
||||
}
|
||||
else if (part->XferInfo[i].state == XFER_ERASED) {
|
||||
DEBUG(3,"XferInfo[%d].state == XFER_ERASED\n",i);
|
||||
pr_debug("XferInfo[%d].state == XFER_ERASED\n",i);
|
||||
n=1;
|
||||
prepare_xfer(part, i);
|
||||
}
|
||||
if (part->XferInfo[i].state == XFER_PREPARED) {
|
||||
DEBUG(3,"XferInfo[%d].state == XFER_PREPARED\n",i);
|
||||
pr_debug("XferInfo[%d].state == XFER_PREPARED\n",i);
|
||||
n=1;
|
||||
if (part->XferInfo[i].EraseCount <= best) {
|
||||
best = part->XferInfo[i].EraseCount;
|
||||
@ -641,12 +641,12 @@ static int reclaim_block(partition_t *part)
|
||||
}
|
||||
}
|
||||
if (!n)
|
||||
DEBUG(3,"XferInfo[%d].state == %x\n",i, part->XferInfo[i].state);
|
||||
pr_debug("XferInfo[%d].state == %x\n",i, part->XferInfo[i].state);
|
||||
|
||||
}
|
||||
if (xfer == 0xffff) {
|
||||
if (queued) {
|
||||
DEBUG(1, "ftl_cs: waiting for transfer "
|
||||
pr_debug("ftl_cs: waiting for transfer "
|
||||
"unit to be prepared...\n");
|
||||
if (part->mbd.mtd->sync)
|
||||
part->mbd.mtd->sync(part->mbd.mtd);
|
||||
@ -656,7 +656,7 @@ static int reclaim_block(partition_t *part)
|
||||
printk(KERN_NOTICE "ftl_cs: reclaim failed: no "
|
||||
"suitable transfer units!\n");
|
||||
else
|
||||
DEBUG(1, "ftl_cs: reclaim failed: no "
|
||||
pr_debug("ftl_cs: reclaim failed: no "
|
||||
"suitable transfer units!\n");
|
||||
|
||||
return -EIO;
|
||||
@ -666,7 +666,7 @@ static int reclaim_block(partition_t *part)
|
||||
|
||||
eun = 0;
|
||||
if ((jiffies % shuffle_freq) == 0) {
|
||||
DEBUG(1, "ftl_cs: recycling freshest block...\n");
|
||||
pr_debug("ftl_cs: recycling freshest block...\n");
|
||||
best = 0xffffffff;
|
||||
for (i = 0; i < part->DataUnits; i++)
|
||||
if (part->EUNInfo[i].EraseCount <= best) {
|
||||
@ -686,7 +686,7 @@ static int reclaim_block(partition_t *part)
|
||||
printk(KERN_NOTICE "ftl_cs: reclaim failed: "
|
||||
"no free blocks!\n");
|
||||
else
|
||||
DEBUG(1,"ftl_cs: reclaim failed: "
|
||||
pr_debug("ftl_cs: reclaim failed: "
|
||||
"no free blocks!\n");
|
||||
|
||||
return -EIO;
|
||||
@ -771,7 +771,7 @@ static uint32_t find_free(partition_t *part)
|
||||
printk(KERN_NOTICE "ftl_cs: bad free list!\n");
|
||||
return 0;
|
||||
}
|
||||
DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun);
|
||||
pr_debug("ftl_cs: found free block at %d in %d\n", blk, eun);
|
||||
return blk;
|
||||
|
||||
} /* find_free */
|
||||
@ -791,7 +791,7 @@ static int ftl_read(partition_t *part, caddr_t buffer,
|
||||
int ret;
|
||||
size_t offset, retlen;
|
||||
|
||||
DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
|
||||
pr_debug("ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
|
||||
part, sector, nblocks);
|
||||
if (!(part->state & FTL_FORMATTED)) {
|
||||
printk(KERN_NOTICE "ftl_cs: bad partition\n");
|
||||
@ -840,7 +840,7 @@ static int set_bam_entry(partition_t *part, uint32_t log_addr,
|
||||
int ret;
|
||||
size_t retlen, offset;
|
||||
|
||||
DEBUG(2, "ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n",
|
||||
pr_debug("ftl_cs: set_bam_entry(0x%p, 0x%x, 0x%x)\n",
|
||||
part, log_addr, virt_addr);
|
||||
bsize = 1 << part->header.EraseUnitSize;
|
||||
eun = log_addr / bsize;
|
||||
@ -905,7 +905,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
|
||||
int ret;
|
||||
size_t retlen, offset;
|
||||
|
||||
DEBUG(2, "ftl_cs: ftl_write(0x%p, %ld, %ld)\n",
|
||||
pr_debug("ftl_cs: ftl_write(0x%p, %ld, %ld)\n",
|
||||
part, sector, nblocks);
|
||||
if (!(part->state & FTL_FORMATTED)) {
|
||||
printk(KERN_NOTICE "ftl_cs: bad partition\n");
|
||||
@ -1011,7 +1011,7 @@ static int ftl_discardsect(struct mtd_blktrans_dev *dev,
|
||||
partition_t *part = (void *)dev;
|
||||
uint32_t bsize = 1 << part->header.EraseUnitSize;
|
||||
|
||||
DEBUG(1, "FTL erase sector %ld for %d sectors\n",
|
||||
pr_debug("FTL erase sector %ld for %d sectors\n",
|
||||
sector, nr_sects);
|
||||
|
||||
while (nr_sects) {
|
||||
|
@ -63,14 +63,12 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: add_mtd for %s\n", mtd->name);
|
||||
pr_debug("INFTL: add_mtd for %s\n", mtd->name);
|
||||
|
||||
inftl = kzalloc(sizeof(*inftl), GFP_KERNEL);
|
||||
|
||||
if (!inftl) {
|
||||
printk(KERN_WARNING "INFTL: Out of memory for data structures\n");
|
||||
if (!inftl)
|
||||
return;
|
||||
}
|
||||
|
||||
inftl->mbd.mtd = mtd;
|
||||
inftl->mbd.devnum = -1;
|
||||
@ -133,7 +131,7 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev)
|
||||
{
|
||||
struct INFTLrecord *inftl = (void *)dev;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: remove_dev (i=%d)\n", dev->devnum);
|
||||
pr_debug("INFTL: remove_dev (i=%d)\n", dev->devnum);
|
||||
|
||||
del_mtd_blktrans_dev(dev);
|
||||
|
||||
@ -154,7 +152,7 @@ int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len,
|
||||
struct mtd_oob_ops ops;
|
||||
int res;
|
||||
|
||||
ops.mode = MTD_OOB_PLACE;
|
||||
ops.mode = MTD_OPS_PLACE_OOB;
|
||||
ops.ooboffs = offs & (mtd->writesize - 1);
|
||||
ops.ooblen = len;
|
||||
ops.oobbuf = buf;
|
||||
@ -174,7 +172,7 @@ int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len,
|
||||
struct mtd_oob_ops ops;
|
||||
int res;
|
||||
|
||||
ops.mode = MTD_OOB_PLACE;
|
||||
ops.mode = MTD_OPS_PLACE_OOB;
|
||||
ops.ooboffs = offs & (mtd->writesize - 1);
|
||||
ops.ooblen = len;
|
||||
ops.oobbuf = buf;
|
||||
@ -194,7 +192,7 @@ static int inftl_write(struct mtd_info *mtd, loff_t offs, size_t len,
|
||||
struct mtd_oob_ops ops;
|
||||
int res;
|
||||
|
||||
ops.mode = MTD_OOB_PLACE;
|
||||
ops.mode = MTD_OPS_PLACE_OOB;
|
||||
ops.ooboffs = offs;
|
||||
ops.ooblen = mtd->oobsize;
|
||||
ops.oobbuf = oob;
|
||||
@ -215,16 +213,16 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate)
|
||||
u16 pot = inftl->LastFreeEUN;
|
||||
int silly = inftl->nb_blocks;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=%p,"
|
||||
"desperate=%d)\n", inftl, desperate);
|
||||
pr_debug("INFTL: INFTL_findfreeblock(inftl=%p,desperate=%d)\n",
|
||||
inftl, desperate);
|
||||
|
||||
/*
|
||||
* Normally, we force a fold to happen before we run out of free
|
||||
* blocks completely.
|
||||
*/
|
||||
if (!desperate && inftl->numfreeEUNs < 2) {
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "INFTL: there are too few free "
|
||||
"EUNs (%d)\n", inftl->numfreeEUNs);
|
||||
pr_debug("INFTL: there are too few free EUNs (%d)\n",
|
||||
inftl->numfreeEUNs);
|
||||
return BLOCK_NIL;
|
||||
}
|
||||
|
||||
@ -259,8 +257,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
|
||||
struct inftl_oob oob;
|
||||
size_t retlen;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,"
|
||||
"pending=%d)\n", inftl, thisVUC, pendingblock);
|
||||
pr_debug("INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,pending=%d)\n",
|
||||
inftl, thisVUC, pendingblock);
|
||||
|
||||
memset(BlockMap, 0xff, sizeof(BlockMap));
|
||||
memset(BlockDeleted, 0, sizeof(BlockDeleted));
|
||||
@ -323,8 +321,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
|
||||
* Chain, and the Erase Unit into which we are supposed to be copying.
|
||||
* Go for it.
|
||||
*/
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "INFTL: folding chain %d into unit %d\n",
|
||||
thisVUC, targetEUN);
|
||||
pr_debug("INFTL: folding chain %d into unit %d\n", thisVUC, targetEUN);
|
||||
|
||||
for (block = 0; block < inftl->EraseSize/SECTORSIZE ; block++) {
|
||||
unsigned char movebuf[SECTORSIZE];
|
||||
@ -349,14 +346,13 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
|
||||
ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) +
|
||||
(block * SECTORSIZE), SECTORSIZE, &retlen,
|
||||
movebuf);
|
||||
if (ret < 0 && ret != -EUCLEAN) {
|
||||
if (ret < 0 && !mtd_is_bitflip(ret)) {
|
||||
ret = mtd->read(mtd,
|
||||
(inftl->EraseSize * BlockMap[block]) +
|
||||
(block * SECTORSIZE), SECTORSIZE,
|
||||
&retlen, movebuf);
|
||||
if (ret != -EIO)
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "INFTL: error went "
|
||||
"away on retry?\n");
|
||||
pr_debug("INFTL: error went away on retry?\n");
|
||||
}
|
||||
memset(&oob, 0xff, sizeof(struct inftl_oob));
|
||||
oob.b.Status = oob.b.Status1 = SECTOR_USED;
|
||||
@ -372,8 +368,7 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
|
||||
* is important, by doing oldest first if we crash/reboot then it
|
||||
* it is relatively simple to clean up the mess).
|
||||
*/
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "INFTL: want to erase virtual chain %d\n",
|
||||
thisVUC);
|
||||
pr_debug("INFTL: want to erase virtual chain %d\n", thisVUC);
|
||||
|
||||
for (;;) {
|
||||
/* Find oldest unit in chain. */
|
||||
@ -421,7 +416,7 @@ static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)
|
||||
u16 ChainLength = 0, thislen;
|
||||
u16 chain, EUN;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=%p,"
|
||||
pr_debug("INFTL: INFTL_makefreeblock(inftl=%p,"
|
||||
"pending=%d)\n", inftl, pendingblock);
|
||||
|
||||
for (chain = 0; chain < inftl->nb_blocks; chain++) {
|
||||
@ -484,8 +479,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
size_t retlen;
|
||||
int silly, silly2 = 3;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=%p,"
|
||||
"block=%d)\n", inftl, block);
|
||||
pr_debug("INFTL: INFTL_findwriteunit(inftl=%p,block=%d)\n",
|
||||
inftl, block);
|
||||
|
||||
do {
|
||||
/*
|
||||
@ -501,8 +496,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
|
||||
blockofs, 8, &retlen, (char *)&bci);
|
||||
|
||||
status = bci.Status | bci.Status1;
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: status of block %d in "
|
||||
"EUN %d is %x\n", block , writeEUN, status);
|
||||
pr_debug("INFTL: status of block %d in EUN %d is %x\n",
|
||||
block , writeEUN, status);
|
||||
|
||||
switch(status) {
|
||||
case SECTOR_FREE:
|
||||
@ -555,9 +550,9 @@ hitused:
|
||||
* Hopefully we free something, lets try again.
|
||||
* This time we are desperate...
|
||||
*/
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "INFTL: using desperate==1 "
|
||||
"to find free EUN to accommodate write to "
|
||||
"VUC %d\n", thisVUC);
|
||||
pr_debug("INFTL: using desperate==1 to find free EUN "
|
||||
"to accommodate write to VUC %d\n",
|
||||
thisVUC);
|
||||
writeEUN = INFTL_findfreeblock(inftl, 1);
|
||||
if (writeEUN == BLOCK_NIL) {
|
||||
/*
|
||||
@ -647,7 +642,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
|
||||
struct inftl_bci bci;
|
||||
size_t retlen;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=%p,"
|
||||
pr_debug("INFTL: INFTL_trydeletechain(inftl=%p,"
|
||||
"thisVUC=%d)\n", inftl, thisVUC);
|
||||
|
||||
memset(BlockUsed, 0, sizeof(BlockUsed));
|
||||
@ -711,7 +706,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
|
||||
* For each block in the chain free it and make it available
|
||||
* for future use. Erase from the oldest unit first.
|
||||
*/
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "INFTL: deleting empty VUC %d\n", thisVUC);
|
||||
pr_debug("INFTL: deleting empty VUC %d\n", thisVUC);
|
||||
|
||||
for (;;) {
|
||||
u16 *prevEUN = &inftl->VUtable[thisVUC];
|
||||
@ -719,7 +714,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
|
||||
|
||||
/* If the chain is all gone already, we're done */
|
||||
if (thisEUN == BLOCK_NIL) {
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d for deletion was already absent\n", thisEUN);
|
||||
pr_debug("INFTL: Empty VUC %d for deletion was already absent\n", thisEUN);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -731,7 +726,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
|
||||
thisEUN = *prevEUN;
|
||||
}
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n",
|
||||
pr_debug("Deleting EUN %d from VUC %d\n",
|
||||
thisEUN, thisVUC);
|
||||
|
||||
if (INFTL_formatblock(inftl, thisEUN) < 0) {
|
||||
@ -767,7 +762,7 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
|
||||
size_t retlen;
|
||||
struct inftl_bci bci;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=%p,"
|
||||
pr_debug("INFTL: INFTL_deleteblock(inftl=%p,"
|
||||
"block=%d)\n", inftl, block);
|
||||
|
||||
while (thisEUN < inftl->nb_blocks) {
|
||||
@ -826,7 +821,7 @@ static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
|
||||
struct inftl_oob oob;
|
||||
char *p, *pend;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=%p,block=%ld,"
|
||||
pr_debug("INFTL: inftl_writeblock(inftl=%p,block=%ld,"
|
||||
"buffer=%p)\n", inftl, block, buffer);
|
||||
|
||||
/* Is block all zero? */
|
||||
@ -876,7 +871,7 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
|
||||
struct inftl_bci bci;
|
||||
size_t retlen;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld,"
|
||||
pr_debug("INFTL: inftl_readblock(inftl=%p,block=%ld,"
|
||||
"buffer=%p)\n", inftl, block, buffer);
|
||||
|
||||
while (thisEUN < inftl->nb_blocks) {
|
||||
@ -922,7 +917,7 @@ foundit:
|
||||
int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer);
|
||||
|
||||
/* Handle corrected bit flips gracefully */
|
||||
if (ret < 0 && ret != -EUCLEAN)
|
||||
if (ret < 0 && !mtd_is_bitflip(ret))
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
|
@ -53,7 +53,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
|
||||
struct INFTLPartition *ip;
|
||||
size_t retlen;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=%p)\n", inftl);
|
||||
pr_debug("INFTL: find_boot_record(inftl=%p)\n", inftl);
|
||||
|
||||
/*
|
||||
* Assume logical EraseSize == physical erasesize for starting the
|
||||
@ -139,24 +139,20 @@ static int find_boot_record(struct INFTLrecord *inftl)
|
||||
mh->FormatFlags = le32_to_cpu(mh->FormatFlags);
|
||||
mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
|
||||
|
||||
#ifdef CONFIG_MTD_DEBUG_VERBOSE
|
||||
if (CONFIG_MTD_DEBUG_VERBOSE >= 2) {
|
||||
printk("INFTL: Media Header ->\n"
|
||||
" bootRecordID = %s\n"
|
||||
" NoOfBootImageBlocks = %d\n"
|
||||
" NoOfBinaryPartitions = %d\n"
|
||||
" NoOfBDTLPartitions = %d\n"
|
||||
" BlockMultiplerBits = %d\n"
|
||||
" FormatFlgs = %d\n"
|
||||
" OsakVersion = 0x%x\n"
|
||||
" PercentUsed = %d\n",
|
||||
mh->bootRecordID, mh->NoOfBootImageBlocks,
|
||||
mh->NoOfBinaryPartitions,
|
||||
mh->NoOfBDTLPartitions,
|
||||
mh->BlockMultiplierBits, mh->FormatFlags,
|
||||
mh->OsakVersion, mh->PercentUsed);
|
||||
}
|
||||
#endif
|
||||
pr_debug("INFTL: Media Header ->\n"
|
||||
" bootRecordID = %s\n"
|
||||
" NoOfBootImageBlocks = %d\n"
|
||||
" NoOfBinaryPartitions = %d\n"
|
||||
" NoOfBDTLPartitions = %d\n"
|
||||
" BlockMultiplerBits = %d\n"
|
||||
" FormatFlgs = %d\n"
|
||||
" OsakVersion = 0x%x\n"
|
||||
" PercentUsed = %d\n",
|
||||
mh->bootRecordID, mh->NoOfBootImageBlocks,
|
||||
mh->NoOfBinaryPartitions,
|
||||
mh->NoOfBDTLPartitions,
|
||||
mh->BlockMultiplierBits, mh->FormatFlags,
|
||||
mh->OsakVersion, mh->PercentUsed);
|
||||
|
||||
if (mh->NoOfBDTLPartitions == 0) {
|
||||
printk(KERN_WARNING "INFTL: Media Header sanity check "
|
||||
@ -200,19 +196,15 @@ static int find_boot_record(struct INFTLrecord *inftl)
|
||||
ip->spareUnits = le32_to_cpu(ip->spareUnits);
|
||||
ip->Reserved0 = le32_to_cpu(ip->Reserved0);
|
||||
|
||||
#ifdef CONFIG_MTD_DEBUG_VERBOSE
|
||||
if (CONFIG_MTD_DEBUG_VERBOSE >= 2) {
|
||||
printk(" PARTITION[%d] ->\n"
|
||||
" virtualUnits = %d\n"
|
||||
" firstUnit = %d\n"
|
||||
" lastUnit = %d\n"
|
||||
" flags = 0x%x\n"
|
||||
" spareUnits = %d\n",
|
||||
i, ip->virtualUnits, ip->firstUnit,
|
||||
ip->lastUnit, ip->flags,
|
||||
ip->spareUnits);
|
||||
}
|
||||
#endif
|
||||
pr_debug(" PARTITION[%d] ->\n"
|
||||
" virtualUnits = %d\n"
|
||||
" firstUnit = %d\n"
|
||||
" lastUnit = %d\n"
|
||||
" flags = 0x%x\n"
|
||||
" spareUnits = %d\n",
|
||||
i, ip->virtualUnits, ip->firstUnit,
|
||||
ip->lastUnit, ip->flags,
|
||||
ip->spareUnits);
|
||||
|
||||
if (ip->Reserved0 != ip->firstUnit) {
|
||||
struct erase_info *instr = &inftl->instr;
|
||||
@ -375,7 +367,7 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
|
||||
*
|
||||
* Return: 0 when succeed, -1 on error.
|
||||
*
|
||||
* ToDo: 1. Is it neceressary to check_free_sector after erasing ??
|
||||
* ToDo: 1. Is it necessary to check_free_sector after erasing ??
|
||||
*/
|
||||
int INFTL_formatblock(struct INFTLrecord *inftl, int block)
|
||||
{
|
||||
@ -385,8 +377,7 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
|
||||
struct mtd_info *mtd = inftl->mbd.mtd;
|
||||
int physblock;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p,"
|
||||
"block=%d)\n", inftl, block);
|
||||
pr_debug("INFTL: INFTL_formatblock(inftl=%p,block=%d)\n", inftl, block);
|
||||
|
||||
memset(instr, 0, sizeof(struct erase_info));
|
||||
|
||||
@ -476,30 +467,30 @@ void INFTL_dumptables(struct INFTLrecord *s)
|
||||
{
|
||||
int i;
|
||||
|
||||
printk("-------------------------------------------"
|
||||
pr_debug("-------------------------------------------"
|
||||
"----------------------------------\n");
|
||||
|
||||
printk("VUtable[%d] ->", s->nb_blocks);
|
||||
pr_debug("VUtable[%d] ->", s->nb_blocks);
|
||||
for (i = 0; i < s->nb_blocks; i++) {
|
||||
if ((i % 8) == 0)
|
||||
printk("\n%04x: ", i);
|
||||
printk("%04x ", s->VUtable[i]);
|
||||
pr_debug("\n%04x: ", i);
|
||||
pr_debug("%04x ", s->VUtable[i]);
|
||||
}
|
||||
|
||||
printk("\n-------------------------------------------"
|
||||
pr_debug("\n-------------------------------------------"
|
||||
"----------------------------------\n");
|
||||
|
||||
printk("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
|
||||
pr_debug("PUtable[%d-%d=%d] ->", s->firstEUN, s->lastEUN, s->nb_blocks);
|
||||
for (i = 0; i <= s->lastEUN; i++) {
|
||||
if ((i % 8) == 0)
|
||||
printk("\n%04x: ", i);
|
||||
printk("%04x ", s->PUtable[i]);
|
||||
pr_debug("\n%04x: ", i);
|
||||
pr_debug("%04x ", s->PUtable[i]);
|
||||
}
|
||||
|
||||
printk("\n-------------------------------------------"
|
||||
pr_debug("\n-------------------------------------------"
|
||||
"----------------------------------\n");
|
||||
|
||||
printk("INFTL ->\n"
|
||||
pr_debug("INFTL ->\n"
|
||||
" EraseSize = %d\n"
|
||||
" h/s/c = %d/%d/%d\n"
|
||||
" numvunits = %d\n"
|
||||
@ -513,7 +504,7 @@ void INFTL_dumptables(struct INFTLrecord *s)
|
||||
s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,
|
||||
s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);
|
||||
|
||||
printk("\n-------------------------------------------"
|
||||
pr_debug("\n-------------------------------------------"
|
||||
"----------------------------------\n");
|
||||
}
|
||||
|
||||
@ -521,25 +512,25 @@ void INFTL_dumpVUchains(struct INFTLrecord *s)
|
||||
{
|
||||
int logical, block, i;
|
||||
|
||||
printk("-------------------------------------------"
|
||||
pr_debug("-------------------------------------------"
|
||||
"----------------------------------\n");
|
||||
|
||||
printk("INFTL Virtual Unit Chains:\n");
|
||||
pr_debug("INFTL Virtual Unit Chains:\n");
|
||||
for (logical = 0; logical < s->nb_blocks; logical++) {
|
||||
block = s->VUtable[logical];
|
||||
if (block > s->nb_blocks)
|
||||
continue;
|
||||
printk(" LOGICAL %d --> %d ", logical, block);
|
||||
pr_debug(" LOGICAL %d --> %d ", logical, block);
|
||||
for (i = 0; i < s->nb_blocks; i++) {
|
||||
if (s->PUtable[block] == BLOCK_NIL)
|
||||
break;
|
||||
block = s->PUtable[block];
|
||||
printk("%d ", block);
|
||||
pr_debug("%d ", block);
|
||||
}
|
||||
printk("\n");
|
||||
pr_debug("\n");
|
||||
}
|
||||
|
||||
printk("-------------------------------------------"
|
||||
pr_debug("-------------------------------------------"
|
||||
"----------------------------------\n");
|
||||
}
|
||||
|
||||
@ -555,7 +546,7 @@ int INFTL_mount(struct INFTLrecord *s)
|
||||
int i;
|
||||
u8 *ANACtable, ANAC;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=%p)\n", s);
|
||||
pr_debug("INFTL: INFTL_mount(inftl=%p)\n", s);
|
||||
|
||||
/* Search for INFTL MediaHeader and Spare INFTL Media Header */
|
||||
if (find_boot_record(s) < 0) {
|
||||
@ -585,7 +576,7 @@ int INFTL_mount(struct INFTLrecord *s)
|
||||
* NOTEXPLORED state. Then at the end we will try to format it and
|
||||
* mark it as free.
|
||||
*/
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 1, explore each unit\n");
|
||||
pr_debug("INFTL: pass 1, explore each unit\n");
|
||||
for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) {
|
||||
if (s->PUtable[first_block] != BLOCK_NOTEXPLORED)
|
||||
continue;
|
||||
@ -717,17 +708,14 @@ int INFTL_mount(struct INFTLrecord *s)
|
||||
logical_block = BLOCK_NIL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_DEBUG_VERBOSE
|
||||
if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
|
||||
INFTL_dumptables(s);
|
||||
#endif
|
||||
INFTL_dumptables(s);
|
||||
|
||||
/*
|
||||
* Second pass, check for infinite loops in chains. These are
|
||||
* possible because we don't update the previous pointers when
|
||||
* we fold chains. No big deal, just fix them up in PUtable.
|
||||
*/
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 2, validate virtual chains\n");
|
||||
pr_debug("INFTL: pass 2, validate virtual chains\n");
|
||||
for (logical_block = 0; logical_block < s->numvunits; logical_block++) {
|
||||
block = s->VUtable[logical_block];
|
||||
last_block = BLOCK_NIL;
|
||||
@ -772,12 +760,8 @@ int INFTL_mount(struct INFTLrecord *s)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_DEBUG_VERBOSE
|
||||
if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
|
||||
INFTL_dumptables(s);
|
||||
if (CONFIG_MTD_DEBUG_VERBOSE >= 2)
|
||||
INFTL_dumpVUchains(s);
|
||||
#endif
|
||||
INFTL_dumptables(s);
|
||||
INFTL_dumpVUchains(s);
|
||||
|
||||
/*
|
||||
* Third pass, format unreferenced blocks and init free block count.
|
||||
@ -785,7 +769,7 @@ int INFTL_mount(struct INFTLrecord *s)
|
||||
s->numfreeEUNs = 0;
|
||||
s->LastFreeEUN = BLOCK_NIL;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: pass 3, format unused blocks\n");
|
||||
pr_debug("INFTL: pass 3, format unused blocks\n");
|
||||
for (block = s->firstEUN; block <= s->lastEUN; block++) {
|
||||
if (s->PUtable[block] == BLOCK_NOTEXPLORED) {
|
||||
printk("INFTL: unreferenced block %d, formatting it\n",
|
||||
|
@ -41,8 +41,6 @@ config MTD_PHYSMAP_START
|
||||
are mapped on your particular target board. Refer to the
|
||||
memory map which should hopefully be in the documentation for
|
||||
your board.
|
||||
Ignore this option if you use run-time physmap configuration
|
||||
(i.e., run-time calling physmap_configure()).
|
||||
|
||||
config MTD_PHYSMAP_LEN
|
||||
hex "Physical length of flash mapping"
|
||||
@ -55,8 +53,6 @@ config MTD_PHYSMAP_LEN
|
||||
than the total amount of flash present. Refer to the memory
|
||||
map which should hopefully be in the documentation for your
|
||||
board.
|
||||
Ignore this option if you use run-time physmap configuration
|
||||
(i.e., run-time calling physmap_configure()).
|
||||
|
||||
config MTD_PHYSMAP_BANKWIDTH
|
||||
int "Bank width in octets"
|
||||
@ -67,8 +63,6 @@ config MTD_PHYSMAP_BANKWIDTH
|
||||
in octets. For example, if you have a data bus width of 32
|
||||
bits, you would set the bus width octet value to 4. This is
|
||||
used internally by the CFI drivers.
|
||||
Ignore this option if you use run-time physmap configuration
|
||||
(i.e., run-time calling physmap_configure()).
|
||||
|
||||
config MTD_PHYSMAP_OF
|
||||
tristate "Flash device in physical memory map based on OF description"
|
||||
@ -260,7 +254,6 @@ config MTD_BCM963XX
|
||||
config MTD_LANTIQ
|
||||
tristate "Lantiq SoC NOR support"
|
||||
depends on LANTIQ
|
||||
select MTD_PARTITIONS
|
||||
help
|
||||
Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
|
||||
|
||||
@ -339,10 +332,6 @@ config MTD_SOLUTIONENGINE
|
||||
This enables access to the flash chips on the Hitachi SolutionEngine and
|
||||
similar boards. Say 'Y' if you are building a kernel for such a board.
|
||||
|
||||
config MTD_ARM_INTEGRATOR
|
||||
tristate "CFI Flash device mapped on ARM Integrator/P720T"
|
||||
depends on ARM && MTD_CFI
|
||||
|
||||
config MTD_CDB89712
|
||||
tristate "Cirrus CDB89712 evaluation board mappings"
|
||||
depends on MTD_CFI && ARCH_CDB89712
|
||||
@ -398,13 +387,6 @@ config MTD_AUTCPU12
|
||||
This enables access to the NV-RAM on autronix autcpu12 board.
|
||||
If you have such a board, say 'Y'.
|
||||
|
||||
config MTD_EDB7312
|
||||
tristate "CFI Flash device mapped on EDB7312"
|
||||
depends on ARCH_EDB7312 && MTD_CFI
|
||||
help
|
||||
This enables access to the CFI Flash on the Cogent EDB7312 board.
|
||||
If you have such a board, say 'Y' here.
|
||||
|
||||
config MTD_IMPA7
|
||||
tristate "JEDEC Flash device mapped on impA7"
|
||||
depends on ARM && MTD_JEDECPROBE
|
||||
@ -412,14 +394,6 @@ config MTD_IMPA7
|
||||
This enables access to the NOR Flash on the impA7 board of
|
||||
implementa GmbH. If you have such a board, say 'Y' here.
|
||||
|
||||
config MTD_CEIVA
|
||||
tristate "JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame"
|
||||
depends on MTD_JEDECPROBE && ARCH_CEIVA
|
||||
help
|
||||
This enables access to the flash chips on the Ceiva/Polaroid
|
||||
PhotoMax Digital Picture Frame.
|
||||
If you have such a device, say 'Y'.
|
||||
|
||||
config MTD_H720X
|
||||
tristate "Hynix evaluation board mappings"
|
||||
depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
|
||||
|
@ -19,7 +19,6 @@ obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o
|
||||
obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
|
||||
obj-$(CONFIG_MTD_PXA2XX) += pxa2xx-flash.o
|
||||
obj-$(CONFIG_MTD_MBX860) += mbx860.o
|
||||
obj-$(CONFIG_MTD_CEIVA) += ceiva.o
|
||||
obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o
|
||||
obj-$(CONFIG_MTD_PHYSMAP) += physmap.o
|
||||
obj-$(CONFIG_MTD_PHYSMAP_OF) += physmap_of.o
|
||||
@ -40,7 +39,6 @@ obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.o
|
||||
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
|
||||
obj-$(CONFIG_MTD_PCI) += pci.o
|
||||
obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
|
||||
obj-$(CONFIG_MTD_EDB7312) += edb7312.o
|
||||
obj-$(CONFIG_MTD_IMPA7) += impa7.o
|
||||
obj-$(CONFIG_MTD_FORTUNET) += fortunet.o
|
||||
obj-$(CONFIG_MTD_UCLINUX) += uclinux.o
|
||||
|
@ -41,7 +41,6 @@ struct async_state {
|
||||
uint32_t flash_ambctl0, flash_ambctl1;
|
||||
uint32_t save_ambctl0, save_ambctl1;
|
||||
unsigned long irq_flags;
|
||||
struct mtd_partition *parts;
|
||||
};
|
||||
|
||||
static void switch_to_flash(struct async_state *state)
|
||||
@ -165,18 +164,8 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
|
||||
if (ret > 0) {
|
||||
pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
|
||||
mtd_device_register(state->mtd, pdata->parts, ret);
|
||||
state->parts = pdata->parts;
|
||||
} else if (pdata->nr_parts) {
|
||||
pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
|
||||
mtd_device_register(state->mtd, pdata->parts, pdata->nr_parts);
|
||||
} else {
|
||||
pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
|
||||
mtd_device_register(state->mtd, NULL, 0);
|
||||
}
|
||||
mtd_device_parse_register(state->mtd, part_probe_types, 0,
|
||||
pdata->parts, pdata->nr_parts);
|
||||
|
||||
platform_set_drvdata(pdev, state);
|
||||
|
||||
@ -188,7 +177,6 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev)
|
||||
struct async_state *state = platform_get_drvdata(pdev);
|
||||
gpio_free(state->enet_flash_pin);
|
||||
mtd_device_unregister(state->mtd);
|
||||
kfree(state->parts);
|
||||
map_destroy(state->mtd);
|
||||
kfree(state);
|
||||
return 0;
|
||||
|
@ -1,341 +0,0 @@
|
||||
/*
|
||||
* Ceiva flash memory driver.
|
||||
* Copyright (C) 2002 Rob Scott <rscott@mtrob.fdns.net>
|
||||
*
|
||||
* Note: this driver supports jedec compatible devices. Modification
|
||||
* for CFI compatible devices should be straight forward: change
|
||||
* jedec_probe to cfi_probe.
|
||||
*
|
||||
* Based on: sa1100-flash.c, which has the following copyright:
|
||||
* Flash memory access on SA11x0 based devices
|
||||
*
|
||||
* (C) 2000 Nicolas Pitre <nico@fluxnic.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/map.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/concat.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm/sizes.h>
|
||||
|
||||
/*
|
||||
* This isn't complete yet, so...
|
||||
*/
|
||||
#define CONFIG_MTD_CEIVA_STATICMAP
|
||||
|
||||
#ifdef CONFIG_MTD_CEIVA_STATICMAP
|
||||
/*
|
||||
* See include/linux/mtd/partitions.h for definition of the mtd_partition
|
||||
* structure.
|
||||
*
|
||||
* Please note:
|
||||
* 1. The flash size given should be the largest flash size that can
|
||||
* be accommodated.
|
||||
*
|
||||
* 2. The bus width must defined in clps_setup_flash.
|
||||
*
|
||||
* The MTD layer will detect flash chip aliasing and reduce the size of
|
||||
* the map accordingly.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ARCH_CEIVA
|
||||
/* Flash / Partition sizing */
|
||||
/* For the 28F8003, we use the block mapping to calcuate the sizes */
|
||||
#define MAX_SIZE_KiB (16 + 8 + 8 + 96 + (7*128))
|
||||
#define BOOT_PARTITION_SIZE_KiB (16)
|
||||
#define PARAMS_PARTITION_SIZE_KiB (8)
|
||||
#define KERNEL_PARTITION_SIZE_KiB (4*128)
|
||||
/* Use both remaining portion of first flash, and all of second flash */
|
||||
#define ROOT_PARTITION_SIZE_KiB (3*128) + (8*128)
|
||||
|
||||
static struct mtd_partition ceiva_partitions[] = {
|
||||
{
|
||||
.name = "Ceiva BOOT partition",
|
||||
.size = BOOT_PARTITION_SIZE_KiB*1024,
|
||||
.offset = 0,
|
||||
|
||||
},{
|
||||
.name = "Ceiva parameters partition",
|
||||
.size = PARAMS_PARTITION_SIZE_KiB*1024,
|
||||
.offset = (16 + 8) * 1024,
|
||||
},{
|
||||
.name = "Ceiva kernel partition",
|
||||
.size = (KERNEL_PARTITION_SIZE_KiB)*1024,
|
||||
.offset = 0x20000,
|
||||
|
||||
},{
|
||||
.name = "Ceiva root filesystem partition",
|
||||
.offset = MTDPART_OFS_APPEND,
|
||||
.size = (ROOT_PARTITION_SIZE_KiB)*1024,
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static int __init clps_static_partitions(struct mtd_partition **parts)
|
||||
{
|
||||
int nb_parts = 0;
|
||||
|
||||
#ifdef CONFIG_ARCH_CEIVA
|
||||
if (machine_is_ceiva()) {
|
||||
*parts = ceiva_partitions;
|
||||
nb_parts = ARRAY_SIZE(ceiva_partitions);
|
||||
}
|
||||
#endif
|
||||
return nb_parts;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct clps_info {
|
||||
unsigned long base;
|
||||
unsigned long size;
|
||||
int width;
|
||||
void *vbase;
|
||||
struct map_info *map;
|
||||
struct mtd_info *mtd;
|
||||
struct resource *res;
|
||||
};
|
||||
|
||||
#define NR_SUBMTD 4
|
||||
|
||||
static struct clps_info info[NR_SUBMTD];
|
||||
|
||||
static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info **rmtd)
|
||||
{
|
||||
struct mtd_info *subdev[nr];
|
||||
struct map_info *maps;
|
||||
int i, found = 0, ret = 0;
|
||||
|
||||
/*
|
||||
* Allocate the map_info structs in one go.
|
||||
*/
|
||||
maps = kzalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
|
||||
if (!maps)
|
||||
return -ENOMEM;
|
||||
/*
|
||||
* Claim and then map the memory regions.
|
||||
*/
|
||||
for (i = 0; i < nr; i++) {
|
||||
if (clps[i].base == (unsigned long)-1)
|
||||
break;
|
||||
|
||||
clps[i].res = request_mem_region(clps[i].base, clps[i].size, "clps flash");
|
||||
if (!clps[i].res) {
|
||||
ret = -EBUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
clps[i].map = maps + i;
|
||||
|
||||
clps[i].map->name = "clps flash";
|
||||
clps[i].map->phys = clps[i].base;
|
||||
|
||||
clps[i].vbase = ioremap(clps[i].base, clps[i].size);
|
||||
if (!clps[i].vbase) {
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
clps[i].map->virt = (void __iomem *)clps[i].vbase;
|
||||
clps[i].map->bankwidth = clps[i].width;
|
||||
clps[i].map->size = clps[i].size;
|
||||
|
||||
simple_map_init(&clps[i].map);
|
||||
|
||||
clps[i].mtd = do_map_probe("jedec_probe", clps[i].map);
|
||||
if (clps[i].mtd == NULL) {
|
||||
ret = -ENXIO;
|
||||
break;
|
||||
}
|
||||
clps[i].mtd->owner = THIS_MODULE;
|
||||
subdev[i] = clps[i].mtd;
|
||||
|
||||
printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, "
|
||||
"%d-bit\n", clps[i].base, clps[i].mtd->size >> 20,
|
||||
clps[i].width * 8);
|
||||
found += 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* ENXIO is special. It means we didn't find a chip when
|
||||
* we probed. We need to tear down the mapping, free the
|
||||
* resource and mark it as such.
|
||||
*/
|
||||
if (ret == -ENXIO) {
|
||||
iounmap(clps[i].vbase);
|
||||
clps[i].vbase = NULL;
|
||||
release_resource(clps[i].res);
|
||||
clps[i].res = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we found one device, don't bother with concat support.
|
||||
* If we found multiple devices, use concat if we have it
|
||||
* available, otherwise fail.
|
||||
*/
|
||||
if (ret == 0 || ret == -ENXIO) {
|
||||
if (found == 1) {
|
||||
*rmtd = subdev[0];
|
||||
ret = 0;
|
||||
} else if (found > 1) {
|
||||
/*
|
||||
* We detected multiple devices. Concatenate
|
||||
* them together.
|
||||
*/
|
||||
*rmtd = mtd_concat_create(subdev, found,
|
||||
"clps flash");
|
||||
if (*rmtd == NULL)
|
||||
ret = -ENXIO;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we failed, clean up.
|
||||
*/
|
||||
if (ret) {
|
||||
do {
|
||||
if (clps[i].mtd)
|
||||
map_destroy(clps[i].mtd);
|
||||
if (clps[i].vbase)
|
||||
iounmap(clps[i].vbase);
|
||||
if (clps[i].res)
|
||||
release_resource(clps[i].res);
|
||||
} while (i--);
|
||||
|
||||
kfree(maps);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd)
|
||||
{
|
||||
int i;
|
||||
|
||||
mtd_device_unregister(mtd);
|
||||
|
||||
if (mtd != clps[0].mtd)
|
||||
mtd_concat_destroy(mtd);
|
||||
|
||||
for (i = NR_SUBMTD; i >= 0; i--) {
|
||||
if (clps[i].mtd)
|
||||
map_destroy(clps[i].mtd);
|
||||
if (clps[i].vbase)
|
||||
iounmap(clps[i].vbase);
|
||||
if (clps[i].res)
|
||||
release_resource(clps[i].res);
|
||||
}
|
||||
kfree(clps[0].map);
|
||||
}
|
||||
|
||||
/*
|
||||
* We define the memory space, size, and width for the flash memory
|
||||
* space here.
|
||||
*/
|
||||
|
||||
static int __init clps_setup_flash(void)
|
||||
{
|
||||
int nr = 0;
|
||||
|
||||
#ifdef CONFIG_ARCH_CEIVA
|
||||
if (machine_is_ceiva()) {
|
||||
info[0].base = CS0_PHYS_BASE;
|
||||
info[0].size = SZ_32M;
|
||||
info[0].width = CEIVA_FLASH_WIDTH;
|
||||
info[1].base = CS1_PHYS_BASE;
|
||||
info[1].size = SZ_32M;
|
||||
info[1].width = CEIVA_FLASH_WIDTH;
|
||||
nr = 2;
|
||||
}
|
||||
#endif
|
||||
return nr;
|
||||
}
|
||||
|
||||
static struct mtd_partition *parsed_parts;
|
||||
static const char *probes[] = { "cmdlinepart", "RedBoot", NULL };
|
||||
|
||||
static void __init clps_locate_partitions(struct mtd_info *mtd)
|
||||
{
|
||||
const char *part_type = NULL;
|
||||
int nr_parts = 0;
|
||||
do {
|
||||
/*
|
||||
* Partition selection stuff.
|
||||
*/
|
||||
nr_parts = parse_mtd_partitions(mtd, probes, &parsed_parts, 0);
|
||||
if (nr_parts > 0) {
|
||||
part_type = "command line";
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_MTD_CEIVA_STATICMAP
|
||||
nr_parts = clps_static_partitions(&parsed_parts);
|
||||
if (nr_parts > 0) {
|
||||
part_type = "static";
|
||||
break;
|
||||
}
|
||||
printk("found: %d partitions\n", nr_parts);
|
||||
#endif
|
||||
} while (0);
|
||||
|
||||
if (nr_parts == 0) {
|
||||
printk(KERN_NOTICE "clps flash: no partition info "
|
||||
"available, registering whole flash\n");
|
||||
mtd_device_register(mtd, NULL, 0);
|
||||
} else {
|
||||
printk(KERN_NOTICE "clps flash: using %s partition "
|
||||
"definition\n", part_type);
|
||||
mtd_device_register(mtd, parsed_parts, nr_parts);
|
||||
}
|
||||
|
||||
/* Always succeeds. */
|
||||
}
|
||||
|
||||
static void __exit clps_destroy_partitions(void)
|
||||
{
|
||||
kfree(parsed_parts);
|
||||
}
|
||||
|
||||
static struct mtd_info *mymtd;
|
||||
|
||||
static int __init clps_mtd_init(void)
|
||||
{
|
||||
int ret;
|
||||
int nr;
|
||||
|
||||
nr = clps_setup_flash();
|
||||
if (nr < 0)
|
||||
return nr;
|
||||
|
||||
ret = clps_setup_mtd(info, nr, &mymtd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clps_locate_partitions(mymtd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit clps_mtd_cleanup(void)
|
||||
{
|
||||
clps_destroy_mtd(info, mymtd);
|
||||
clps_destroy_partitions();
|
||||
}
|
||||
|
||||
module_init(clps_mtd_init);
|
||||
module_exit(clps_mtd_cleanup);
|
||||
|
||||
MODULE_AUTHOR("Rob Scott");
|
||||
MODULE_DESCRIPTION("Cirrus Logic JEDEC map driver");
|
||||
MODULE_LICENSE("GPL");
|
@ -145,14 +145,10 @@ static struct map_info dc21285_map = {
|
||||
|
||||
|
||||
/* Partition stuff */
|
||||
static struct mtd_partition *dc21285_parts;
|
||||
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
|
||||
|
||||
static int __init init_dc21285(void)
|
||||
{
|
||||
|
||||
int nrparts;
|
||||
|
||||
/* Determine bankwidth */
|
||||
switch (*CSR_SA110_CNTL & (3<<14)) {
|
||||
case SA110_CNTL_ROMWIDTH_8:
|
||||
@ -200,8 +196,7 @@ static int __init init_dc21285(void)
|
||||
|
||||
dc21285_mtd->owner = THIS_MODULE;
|
||||
|
||||
nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0);
|
||||
mtd_device_register(dc21285_mtd, dc21285_parts, nrparts);
|
||||
mtd_device_parse_register(dc21285_mtd, probes, 0, NULL, 0);
|
||||
|
||||
if(machine_is_ebsa285()) {
|
||||
/*
|
||||
@ -224,8 +219,6 @@ static int __init init_dc21285(void)
|
||||
static void __exit cleanup_dc21285(void)
|
||||
{
|
||||
mtd_device_unregister(dc21285_mtd);
|
||||
if (dc21285_parts)
|
||||
kfree(dc21285_parts);
|
||||
map_destroy(dc21285_mtd);
|
||||
iounmap(dc21285_map.virt);
|
||||
}
|
||||
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
* Handle mapping of the NOR flash on Cogent EDB7312 boards
|
||||
*
|
||||
* Copyright 2002 SYSGO Real-Time Solutions GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/map.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
|
||||
#define WINDOW_ADDR 0x00000000 /* physical properties of flash */
|
||||
#define WINDOW_SIZE 0x01000000
|
||||
#define BUSWIDTH 2
|
||||
#define FLASH_BLOCKSIZE_MAIN 0x20000
|
||||
#define FLASH_NUMBLOCKS_MAIN 128
|
||||
/* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */
|
||||
#define PROBETYPES { "cfi_probe", NULL }
|
||||
|
||||
#define MSG_PREFIX "EDB7312-NOR:" /* prefix for our printk()'s */
|
||||
#define MTDID "edb7312-nor" /* for mtdparts= partitioning */
|
||||
|
||||
static struct mtd_info *mymtd;
|
||||
|
||||
struct map_info edb7312nor_map = {
|
||||
.name = "NOR flash on EDB7312",
|
||||
.size = WINDOW_SIZE,
|
||||
.bankwidth = BUSWIDTH,
|
||||
.phys = WINDOW_ADDR,
|
||||
};
|
||||
|
||||
/*
|
||||
* MTD partitioning stuff
|
||||
*/
|
||||
static struct mtd_partition static_partitions[3] =
|
||||
{
|
||||
{
|
||||
.name = "ARMboot",
|
||||
.size = 0x40000,
|
||||
.offset = 0
|
||||
},
|
||||
{
|
||||
.name = "Kernel",
|
||||
.size = 0x200000,
|
||||
.offset = 0x40000
|
||||
},
|
||||
{
|
||||
.name = "RootFS",
|
||||
.size = 0xDC0000,
|
||||
.offset = 0x240000
|
||||
},
|
||||
};
|
||||
|
||||
static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
|
||||
|
||||
static int mtd_parts_nb = 0;
|
||||
static struct mtd_partition *mtd_parts = 0;
|
||||
|
||||
static int __init init_edb7312nor(void)
|
||||
{
|
||||
static const char *rom_probe_types[] = PROBETYPES;
|
||||
const char **type;
|
||||
const char *part_type = 0;
|
||||
|
||||
printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n",
|
||||
WINDOW_SIZE, WINDOW_ADDR);
|
||||
edb7312nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
|
||||
|
||||
if (!edb7312nor_map.virt) {
|
||||
printk(MSG_PREFIX "failed to ioremap\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
simple_map_init(&edb7312nor_map);
|
||||
|
||||
mymtd = 0;
|
||||
type = rom_probe_types;
|
||||
for(; !mymtd && *type; type++) {
|
||||
mymtd = do_map_probe(*type, &edb7312nor_map);
|
||||
}
|
||||
if (mymtd) {
|
||||
mymtd->owner = THIS_MODULE;
|
||||
|
||||
mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID);
|
||||
if (mtd_parts_nb > 0)
|
||||
part_type = "detected";
|
||||
|
||||
if (mtd_parts_nb == 0) {
|
||||
mtd_parts = static_partitions;
|
||||
mtd_parts_nb = ARRAY_SIZE(static_partitions);
|
||||
part_type = "static";
|
||||
}
|
||||
|
||||
if (mtd_parts_nb == 0)
|
||||
printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
|
||||
else
|
||||
printk(KERN_NOTICE MSG_PREFIX
|
||||
"using %s partition definition\n", part_type);
|
||||
/* Register the whole device first. */
|
||||
mtd_device_register(mymtd, NULL, 0);
|
||||
mtd_device_register(mymtd, mtd_parts, mtd_parts_nb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iounmap((void *)edb7312nor_map.virt);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static void __exit cleanup_edb7312nor(void)
|
||||
{
|
||||
if (mymtd) {
|
||||
mtd_device_unregister(mymtd);
|
||||
map_destroy(mymtd);
|
||||
}
|
||||
if (edb7312nor_map.virt) {
|
||||
iounmap((void *)edb7312nor_map.virt);
|
||||
edb7312nor_map.virt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
module_init(init_edb7312nor);
|
||||
module_exit(cleanup_edb7312nor);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Marius Groeger <mag@sysgo.de>");
|
||||
MODULE_DESCRIPTION("Generic configurable MTD map driver");
|
@ -187,7 +187,6 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
|
||||
*/
|
||||
static int __devinit gpio_flash_probe(struct platform_device *pdev)
|
||||
{
|
||||
int nr_parts;
|
||||
size_t i, arr_size;
|
||||
struct physmap_flash_data *pdata;
|
||||
struct resource *memory;
|
||||
@ -252,20 +251,9 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
nr_parts = parse_mtd_partitions(state->mtd, part_probe_types,
|
||||
&pdata->parts, 0);
|
||||
if (nr_parts > 0) {
|
||||
pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n");
|
||||
kfree(pdata->parts);
|
||||
} else if (pdata->nr_parts) {
|
||||
pr_devinit(KERN_NOTICE PFX "Using board partition definition\n");
|
||||
nr_parts = pdata->nr_parts;
|
||||
} else {
|
||||
pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n");
|
||||
nr_parts = 0;
|
||||
}
|
||||
|
||||
mtd_device_register(state->mtd, pdata->parts, nr_parts);
|
||||
mtd_device_parse_register(state->mtd, part_probe_types, 0,
|
||||
pdata->parts, pdata->nr_parts);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -58,18 +58,11 @@ static struct mtd_partition h720x_partitions[] = {
|
||||
|
||||
#define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions)
|
||||
|
||||
static int nr_mtd_parts;
|
||||
static struct mtd_partition *mtd_parts;
|
||||
static const char *probes[] = { "cmdlinepart", NULL };
|
||||
|
||||
/*
|
||||
* Initialize FLASH support
|
||||
*/
|
||||
static int __init h720x_mtd_init(void)
|
||||
{
|
||||
|
||||
char *part_type = NULL;
|
||||
|
||||
h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
|
||||
|
||||
if (!h720x_map.virt) {
|
||||
@ -92,16 +85,8 @@ static int __init h720x_mtd_init(void)
|
||||
if (mymtd) {
|
||||
mymtd->owner = THIS_MODULE;
|
||||
|
||||
nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
|
||||
if (nr_mtd_parts > 0)
|
||||
part_type = "command line";
|
||||
if (nr_mtd_parts <= 0) {
|
||||
mtd_parts = h720x_partitions;
|
||||
nr_mtd_parts = NUM_PARTITIONS;
|
||||
part_type = "builtin";
|
||||
}
|
||||
printk(KERN_INFO "Using %s partition table\n", part_type);
|
||||
mtd_device_register(mymtd, mtd_parts, nr_mtd_parts);
|
||||
mtd_device_parse_register(mymtd, NULL, 0,
|
||||
h720x_partitions, NUM_PARTITIONS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -120,10 +105,6 @@ static void __exit h720x_mtd_cleanup(void)
|
||||
map_destroy(mymtd);
|
||||
}
|
||||
|
||||
/* Free partition info, if commandline partition was used */
|
||||
if (mtd_parts && (mtd_parts != h720x_partitions))
|
||||
kfree (mtd_parts);
|
||||
|
||||
if (h720x_map.virt) {
|
||||
iounmap((void *)h720x_map.virt);
|
||||
h720x_map.virt = 0;
|
||||
|
@ -49,7 +49,7 @@ static struct map_info impa7_map[NUM_FLASHBANKS] = {
|
||||
/*
|
||||
* MTD partitioning stuff
|
||||
*/
|
||||
static struct mtd_partition static_partitions[] =
|
||||
static struct mtd_partition partitions[] =
|
||||
{
|
||||
{
|
||||
.name = "FileSystem",
|
||||
@ -58,16 +58,10 @@ static struct mtd_partition static_partitions[] =
|
||||
},
|
||||
};
|
||||
|
||||
static int mtd_parts_nb[NUM_FLASHBANKS];
|
||||
static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
|
||||
|
||||
static const char *probes[] = { "cmdlinepart", NULL };
|
||||
|
||||
static int __init init_impa7(void)
|
||||
{
|
||||
static const char *rom_probe_types[] = PROBETYPES;
|
||||
const char **type;
|
||||
const char *part_type = 0;
|
||||
int i;
|
||||
static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
|
||||
{ WINDOW_ADDR0, WINDOW_SIZE0 },
|
||||
@ -97,23 +91,9 @@ static int __init init_impa7(void)
|
||||
if (impa7_mtd[i]) {
|
||||
impa7_mtd[i]->owner = THIS_MODULE;
|
||||
devicesfound++;
|
||||
mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i],
|
||||
probes,
|
||||
&mtd_parts[i],
|
||||
0);
|
||||
if (mtd_parts_nb[i] > 0) {
|
||||
part_type = "command line";
|
||||
} else {
|
||||
mtd_parts[i] = static_partitions;
|
||||
mtd_parts_nb[i] = ARRAY_SIZE(static_partitions);
|
||||
part_type = "static";
|
||||
}
|
||||
|
||||
printk(KERN_NOTICE MSG_PREFIX
|
||||
"using %s partition definition\n",
|
||||
part_type);
|
||||
mtd_device_register(impa7_mtd[i],
|
||||
mtd_parts[i], mtd_parts_nb[i]);
|
||||
mtd_device_parse_register(impa7_mtd[i], NULL, 0,
|
||||
partitions,
|
||||
ARRAY_SIZE(partitions));
|
||||
}
|
||||
else
|
||||
iounmap((void *)impa7_map[i].virt);
|
||||
|
@ -44,7 +44,6 @@ struct vr_nor_mtd {
|
||||
void __iomem *csr_base;
|
||||
struct map_info map;
|
||||
struct mtd_info *info;
|
||||
int nr_parts;
|
||||
struct pci_dev *dev;
|
||||
};
|
||||
|
||||
@ -71,13 +70,9 @@ static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
|
||||
|
||||
static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
|
||||
{
|
||||
struct mtd_partition *parts;
|
||||
static const char *part_probes[] = { "cmdlinepart", NULL };
|
||||
|
||||
/* register the flash bank */
|
||||
/* partition the flash bank */
|
||||
p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0);
|
||||
return mtd_device_register(p->info, parts, p->nr_parts);
|
||||
return mtd_device_parse_register(p->info, NULL, 0, NULL, 0);
|
||||
}
|
||||
|
||||
static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
|
||||
|
@ -38,7 +38,6 @@
|
||||
struct ixp2000_flash_info {
|
||||
struct mtd_info *mtd;
|
||||
struct map_info map;
|
||||
struct mtd_partition *partitions;
|
||||
struct resource *res;
|
||||
};
|
||||
|
||||
@ -125,8 +124,6 @@ static int ixp2000_flash_remove(struct platform_device *dev)
|
||||
if (info->map.map_priv_1)
|
||||
iounmap((void *) info->map.map_priv_1);
|
||||
|
||||
kfree(info->partitions);
|
||||
|
||||
if (info->res) {
|
||||
release_resource(info->res);
|
||||
kfree(info->res);
|
||||
@ -229,13 +226,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
|
||||
}
|
||||
info->mtd->owner = THIS_MODULE;
|
||||
|
||||
err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
|
||||
if (err > 0) {
|
||||
err = mtd_device_register(info->mtd, info->partitions, err);
|
||||
if(err)
|
||||
dev_err(&dev->dev, "Could not parse partitions\n");
|
||||
}
|
||||
|
||||
err = mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
|
||||
if (err)
|
||||
goto Error;
|
||||
|
||||
|
@ -145,7 +145,6 @@ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
|
||||
struct ixp4xx_flash_info {
|
||||
struct mtd_info *mtd;
|
||||
struct map_info map;
|
||||
struct mtd_partition *partitions;
|
||||
struct resource *res;
|
||||
};
|
||||
|
||||
@ -168,8 +167,6 @@ static int ixp4xx_flash_remove(struct platform_device *dev)
|
||||
if (info->map.virt)
|
||||
iounmap(info->map.virt);
|
||||
|
||||
kfree(info->partitions);
|
||||
|
||||
if (info->res) {
|
||||
release_resource(info->res);
|
||||
kfree(info->res);
|
||||
@ -185,8 +182,6 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
|
||||
{
|
||||
struct flash_platform_data *plat = dev->dev.platform_data;
|
||||
struct ixp4xx_flash_info *info;
|
||||
const char *part_type = NULL;
|
||||
int nr_parts = 0;
|
||||
int err = -1;
|
||||
|
||||
if (!plat)
|
||||
@ -252,28 +247,12 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
|
||||
/* Use the fast version */
|
||||
info->map.write = ixp4xx_write16;
|
||||
|
||||
nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions,
|
||||
dev->resource->start);
|
||||
if (nr_parts > 0) {
|
||||
part_type = "dynamic";
|
||||
} else {
|
||||
info->partitions = plat->parts;
|
||||
nr_parts = plat->nr_parts;
|
||||
part_type = "static";
|
||||
}
|
||||
if (nr_parts == 0)
|
||||
printk(KERN_NOTICE "IXP4xx flash: no partition info "
|
||||
"available, registering whole flash\n");
|
||||
else
|
||||
printk(KERN_NOTICE "IXP4xx flash: using %s partition "
|
||||
"definition\n", part_type);
|
||||
|
||||
err = mtd_device_register(info->mtd, info->partitions, nr_parts);
|
||||
if (err)
|
||||
err = mtd_device_parse_register(info->mtd, probes, dev->resource->start,
|
||||
plat->parts, plat->nr_parts);
|
||||
if (err) {
|
||||
printk(KERN_ERR "Could not parse partitions\n");
|
||||
|
||||
if (err)
|
||||
goto Error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -107,16 +107,12 @@ ltq_copy_to(struct map_info *map, unsigned long to,
|
||||
spin_unlock_irqrestore(&ebu_lock, flags);
|
||||
}
|
||||
|
||||
static const char const *part_probe_types[] = { "cmdlinepart", NULL };
|
||||
|
||||
static int __init
|
||||
ltq_mtd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
|
||||
struct ltq_mtd *ltq_mtd;
|
||||
struct mtd_partition *parts;
|
||||
struct resource *res;
|
||||
int nr_parts = 0;
|
||||
struct cfi_private *cfi;
|
||||
int err;
|
||||
|
||||
@ -172,17 +168,8 @@ ltq_mtd_probe(struct platform_device *pdev)
|
||||
cfi->addr_unlock1 ^= 1;
|
||||
cfi->addr_unlock2 ^= 1;
|
||||
|
||||
nr_parts = parse_mtd_partitions(ltq_mtd->mtd,
|
||||
part_probe_types, &parts, 0);
|
||||
if (nr_parts > 0) {
|
||||
dev_info(&pdev->dev,
|
||||
"using %d partitions from cmdline", nr_parts);
|
||||
} else {
|
||||
nr_parts = ltq_mtd_data->nr_parts;
|
||||
parts = ltq_mtd_data->parts;
|
||||
}
|
||||
|
||||
err = mtd_device_register(ltq_mtd->mtd, parts, nr_parts);
|
||||
err = mtd_device_parse_register(ltq_mtd->mtd, NULL, 0,
|
||||
ltq_mtd_data->parts, ltq_mtd_data->nr_parts);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "failed to add partitions\n");
|
||||
goto err_destroy;
|
||||
|
@ -33,9 +33,6 @@ struct latch_addr_flash_info {
|
||||
/* cache; could be found out of res */
|
||||
unsigned long win_mask;
|
||||
|
||||
int nr_parts;
|
||||
struct mtd_partition *parts;
|
||||
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
@ -97,8 +94,6 @@ static void lf_copy_from(struct map_info *map, void *to,
|
||||
|
||||
static char *rom_probe_types[] = { "cfi_probe", NULL };
|
||||
|
||||
static char *part_probe_types[] = { "cmdlinepart", NULL };
|
||||
|
||||
static int latch_addr_flash_remove(struct platform_device *dev)
|
||||
{
|
||||
struct latch_addr_flash_info *info;
|
||||
@ -112,8 +107,6 @@ static int latch_addr_flash_remove(struct platform_device *dev)
|
||||
latch_addr_data = dev->dev.platform_data;
|
||||
|
||||
if (info->mtd != NULL) {
|
||||
if (info->nr_parts)
|
||||
kfree(info->parts);
|
||||
mtd_device_unregister(info->mtd);
|
||||
map_destroy(info->mtd);
|
||||
}
|
||||
@ -206,21 +199,8 @@ static int __devinit latch_addr_flash_probe(struct platform_device *dev)
|
||||
}
|
||||
info->mtd->owner = THIS_MODULE;
|
||||
|
||||
err = parse_mtd_partitions(info->mtd, (const char **)part_probe_types,
|
||||
&info->parts, 0);
|
||||
if (err > 0) {
|
||||
mtd_device_register(info->mtd, info->parts, err);
|
||||
return 0;
|
||||
}
|
||||
if (latch_addr_data->nr_parts) {
|
||||
pr_notice("Using latch-addr-flash partition information\n");
|
||||
mtd_device_register(info->mtd,
|
||||
latch_addr_data->parts,
|
||||
latch_addr_data->nr_parts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mtd_device_register(info->mtd, NULL, 0);
|
||||
mtd_device_parse_register(info->mtd, NULL, 0,
|
||||
latch_addr_data->parts, latch_addr_data->nr_parts);
|
||||
return 0;
|
||||
|
||||
iounmap:
|
||||
|
@ -22,22 +22,6 @@
|
||||
#include <linux/mtd/map.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
|
||||
#ifdef CONFIG_MTD_DEBUG
|
||||
static int debug = CONFIG_MTD_DEBUG_VERBOSE;
|
||||
module_param(debug, int, 0);
|
||||
MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy");
|
||||
#undef DEBUG
|
||||
#define DEBUG(n, format, arg...) \
|
||||
if (n <= debug) { \
|
||||
printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \
|
||||
}
|
||||
|
||||
#else
|
||||
#undef DEBUG
|
||||
#define DEBUG(n, arg...)
|
||||
static const int debug = 0;
|
||||
#endif
|
||||
|
||||
#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
|
||||
|
||||
#define DRIVER_DESC "PCMCIA Flash memory card driver"
|
||||
@ -105,13 +89,13 @@ static caddr_t remap_window(struct map_info *map, unsigned long to)
|
||||
int ret;
|
||||
|
||||
if (!pcmcia_dev_present(dev->p_dev)) {
|
||||
DEBUG(1, "device removed");
|
||||
pr_debug("device removed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
offset = to & ~(dev->win_size-1);
|
||||
if (offset != dev->offset) {
|
||||
DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x",
|
||||
pr_debug("Remapping window from 0x%8.8x to 0x%8.8x\n",
|
||||
dev->offset, offset);
|
||||
ret = pcmcia_map_mem_page(dev->p_dev, win, offset);
|
||||
if (ret != 0)
|
||||
@ -132,7 +116,7 @@ static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
|
||||
return d;
|
||||
|
||||
d.x[0] = readb(addr);
|
||||
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", ofs, addr, d.x[0]);
|
||||
pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n", ofs, addr, d.x[0]);
|
||||
return d;
|
||||
}
|
||||
|
||||
@ -147,7 +131,7 @@ static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
|
||||
return d;
|
||||
|
||||
d.x[0] = readw(addr);
|
||||
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", ofs, addr, d.x[0]);
|
||||
pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n", ofs, addr, d.x[0]);
|
||||
return d;
|
||||
}
|
||||
|
||||
@ -157,7 +141,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long
|
||||
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
|
||||
unsigned long win_size = dev->win_size;
|
||||
|
||||
DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
|
||||
pr_debug("to = %p from = %lu len = %zd\n", to, from, len);
|
||||
while(len) {
|
||||
int toread = win_size - (from & (win_size-1));
|
||||
caddr_t addr;
|
||||
@ -169,7 +153,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long
|
||||
if(!addr)
|
||||
return;
|
||||
|
||||
DEBUG(4, "memcpy from %p to %p len = %d", addr, to, toread);
|
||||
pr_debug("memcpy from %p to %p len = %d\n", addr, to, toread);
|
||||
memcpy_fromio(to, addr, toread);
|
||||
len -= toread;
|
||||
to += toread;
|
||||
@ -185,7 +169,7 @@ static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long
|
||||
if(!addr)
|
||||
return;
|
||||
|
||||
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx", adr, addr, d.x[0]);
|
||||
pr_debug("adr = 0x%08lx (%p) data = 0x%02lx\n", adr, addr, d.x[0]);
|
||||
writeb(d.x[0], addr);
|
||||
}
|
||||
|
||||
@ -196,7 +180,7 @@ static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long
|
||||
if(!addr)
|
||||
return;
|
||||
|
||||
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx", adr, addr, d.x[0]);
|
||||
pr_debug("adr = 0x%08lx (%p) data = 0x%04lx\n", adr, addr, d.x[0]);
|
||||
writew(d.x[0], addr);
|
||||
}
|
||||
|
||||
@ -206,7 +190,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v
|
||||
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
|
||||
unsigned long win_size = dev->win_size;
|
||||
|
||||
DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
|
||||
pr_debug("to = %lu from = %p len = %zd\n", to, from, len);
|
||||
while(len) {
|
||||
int towrite = win_size - (to & (win_size-1));
|
||||
caddr_t addr;
|
||||
@ -218,7 +202,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v
|
||||
if(!addr)
|
||||
return;
|
||||
|
||||
DEBUG(4, "memcpy from %p to %p len = %d", from, addr, towrite);
|
||||
pr_debug("memcpy from %p to %p len = %d\n", from, addr, towrite);
|
||||
memcpy_toio(addr, from, towrite);
|
||||
len -= towrite;
|
||||
to += towrite;
|
||||
@ -240,7 +224,7 @@ static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
|
||||
return d;
|
||||
|
||||
d.x[0] = readb(win_base + ofs);
|
||||
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx",
|
||||
pr_debug("ofs = 0x%08lx (%p) data = 0x%02lx\n",
|
||||
ofs, win_base + ofs, d.x[0]);
|
||||
return d;
|
||||
}
|
||||
@ -255,7 +239,7 @@ static map_word pcmcia_read16(struct map_info *map, unsigned long ofs)
|
||||
return d;
|
||||
|
||||
d.x[0] = readw(win_base + ofs);
|
||||
DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx",
|
||||
pr_debug("ofs = 0x%08lx (%p) data = 0x%04lx\n",
|
||||
ofs, win_base + ofs, d.x[0]);
|
||||
return d;
|
||||
}
|
||||
@ -268,7 +252,7 @@ static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from,
|
||||
if(DEV_REMOVED(map))
|
||||
return;
|
||||
|
||||
DEBUG(3, "to = %p from = %lu len = %zd", to, from, len);
|
||||
pr_debug("to = %p from = %lu len = %zd\n", to, from, len);
|
||||
memcpy_fromio(to, win_base + from, len);
|
||||
}
|
||||
|
||||
@ -280,7 +264,7 @@ static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr)
|
||||
if(DEV_REMOVED(map))
|
||||
return;
|
||||
|
||||
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx",
|
||||
pr_debug("adr = 0x%08lx (%p) data = 0x%02lx\n",
|
||||
adr, win_base + adr, d.x[0]);
|
||||
writeb(d.x[0], win_base + adr);
|
||||
}
|
||||
@ -293,7 +277,7 @@ static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr)
|
||||
if(DEV_REMOVED(map))
|
||||
return;
|
||||
|
||||
DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx",
|
||||
pr_debug("adr = 0x%08lx (%p) data = 0x%04lx\n",
|
||||
adr, win_base + adr, d.x[0]);
|
||||
writew(d.x[0], win_base + adr);
|
||||
}
|
||||
@ -306,7 +290,7 @@ static void pcmcia_copy_to(struct map_info *map, unsigned long to, const void *f
|
||||
if(DEV_REMOVED(map))
|
||||
return;
|
||||
|
||||
DEBUG(3, "to = %lu from = %p len = %zd", to, from, len);
|
||||
pr_debug("to = %lu from = %p len = %zd\n", to, from, len);
|
||||
memcpy_toio(win_base + to, from, len);
|
||||
}
|
||||
|
||||
@ -316,7 +300,7 @@ static void pcmciamtd_set_vpp(struct map_info *map, int on)
|
||||
struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
|
||||
struct pcmcia_device *link = dev->p_dev;
|
||||
|
||||
DEBUG(2, "dev = %p on = %d vpp = %d\n", dev, on, dev->vpp);
|
||||
pr_debug("dev = %p on = %d vpp = %d\n\n", dev, on, dev->vpp);
|
||||
pcmcia_fixup_vpp(link, on ? dev->vpp : 0);
|
||||
}
|
||||
|
||||
@ -325,7 +309,7 @@ static void pcmciamtd_release(struct pcmcia_device *link)
|
||||
{
|
||||
struct pcmciamtd_dev *dev = link->priv;
|
||||
|
||||
DEBUG(3, "link = 0x%p", link);
|
||||
pr_debug("link = 0x%p\n", link);
|
||||
|
||||
if (link->resource[2]->end) {
|
||||
if(dev->win_base) {
|
||||
@ -337,7 +321,6 @@ static void pcmciamtd_release(struct pcmcia_device *link)
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_MTD_DEBUG
|
||||
static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev,
|
||||
tuple_t *tuple,
|
||||
void *priv_data)
|
||||
@ -347,7 +330,7 @@ static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev,
|
||||
if (!pcmcia_parse_tuple(tuple, &parse)) {
|
||||
cistpl_format_t *t = &parse.format;
|
||||
(void)t; /* Shut up, gcc */
|
||||
DEBUG(2, "Format type: %u, Error Detection: %u, offset = %u, length =%u",
|
||||
pr_debug("Format type: %u, Error Detection: %u, offset = %u, length =%u\n",
|
||||
t->type, t->edc, t->offset, t->length);
|
||||
}
|
||||
return -ENOSPC;
|
||||
@ -363,12 +346,11 @@ static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev,
|
||||
if (!pcmcia_parse_tuple(tuple, &parse)) {
|
||||
cistpl_jedec_t *t = &parse.jedec;
|
||||
for (i = 0; i < t->nid; i++)
|
||||
DEBUG(2, "JEDEC: 0x%02x 0x%02x",
|
||||
pr_debug("JEDEC: 0x%02x 0x%02x\n",
|
||||
t->id[i].mfr, t->id[i].info);
|
||||
}
|
||||
return -ENOSPC;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
|
||||
tuple_t *tuple,
|
||||
@ -382,14 +364,14 @@ static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
|
||||
if (pcmcia_parse_tuple(tuple, &parse))
|
||||
return -EINVAL;
|
||||
|
||||
DEBUG(2, "Common memory:");
|
||||
pr_debug("Common memory:\n");
|
||||
dev->pcmcia_map.size = t->dev[0].size;
|
||||
/* from here on: DEBUG only */
|
||||
for (i = 0; i < t->ndev; i++) {
|
||||
DEBUG(2, "Region %d, type = %u", i, t->dev[i].type);
|
||||
DEBUG(2, "Region %d, wp = %u", i, t->dev[i].wp);
|
||||
DEBUG(2, "Region %d, speed = %u ns", i, t->dev[i].speed);
|
||||
DEBUG(2, "Region %d, size = %u bytes", i, t->dev[i].size);
|
||||
pr_debug("Region %d, type = %u\n", i, t->dev[i].type);
|
||||
pr_debug("Region %d, wp = %u\n", i, t->dev[i].wp);
|
||||
pr_debug("Region %d, speed = %u ns\n", i, t->dev[i].speed);
|
||||
pr_debug("Region %d, size = %u bytes\n", i, t->dev[i].size);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -409,12 +391,12 @@ static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev,
|
||||
dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
|
||||
/* from here on: DEBUG only */
|
||||
for (i = 0; i < t->ngeo; i++) {
|
||||
DEBUG(2, "region: %d bankwidth = %u", i, t->geo[i].buswidth);
|
||||
DEBUG(2, "region: %d erase_block = %u", i, t->geo[i].erase_block);
|
||||
DEBUG(2, "region: %d read_block = %u", i, t->geo[i].read_block);
|
||||
DEBUG(2, "region: %d write_block = %u", i, t->geo[i].write_block);
|
||||
DEBUG(2, "region: %d partition = %u", i, t->geo[i].partition);
|
||||
DEBUG(2, "region: %d interleave = %u", i, t->geo[i].interleave);
|
||||
pr_debug("region: %d bankwidth = %u\n", i, t->geo[i].buswidth);
|
||||
pr_debug("region: %d erase_block = %u\n", i, t->geo[i].erase_block);
|
||||
pr_debug("region: %d read_block = %u\n", i, t->geo[i].read_block);
|
||||
pr_debug("region: %d write_block = %u\n", i, t->geo[i].write_block);
|
||||
pr_debug("region: %d partition = %u\n", i, t->geo[i].partition);
|
||||
pr_debug("region: %d interleave = %u\n", i, t->geo[i].interleave);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -432,13 +414,11 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev
|
||||
if (p_dev->prod_id[i])
|
||||
strcat(dev->mtd_name, p_dev->prod_id[i]);
|
||||
}
|
||||
DEBUG(2, "Found name: %s", dev->mtd_name);
|
||||
pr_debug("Found name: %s\n", dev->mtd_name);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MTD_DEBUG
|
||||
pcmcia_loop_tuple(p_dev, CISTPL_FORMAT, pcmciamtd_cistpl_format, NULL);
|
||||
pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, NULL);
|
||||
#endif
|
||||
pcmcia_loop_tuple(p_dev, CISTPL_DEVICE, pcmciamtd_cistpl_device, dev);
|
||||
pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, dev);
|
||||
|
||||
@ -450,12 +430,12 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev
|
||||
|
||||
if(force_size) {
|
||||
dev->pcmcia_map.size = force_size << 20;
|
||||
DEBUG(2, "size forced to %dM", force_size);
|
||||
pr_debug("size forced to %dM\n", force_size);
|
||||
}
|
||||
|
||||
if(bankwidth) {
|
||||
dev->pcmcia_map.bankwidth = bankwidth;
|
||||
DEBUG(2, "bankwidth forced to %d", bankwidth);
|
||||
pr_debug("bankwidth forced to %d\n", bankwidth);
|
||||
}
|
||||
|
||||
dev->pcmcia_map.name = dev->mtd_name;
|
||||
@ -464,7 +444,7 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev
|
||||
*new_name = 1;
|
||||
}
|
||||
|
||||
DEBUG(1, "Device: Size: %lu Width:%d Name: %s",
|
||||
pr_debug("Device: Size: %lu Width:%d Name: %s\n",
|
||||
dev->pcmcia_map.size,
|
||||
dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
|
||||
}
|
||||
@ -479,7 +459,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
|
||||
static char *probes[] = { "jedec_probe", "cfi_probe" };
|
||||
int new_name = 0;
|
||||
|
||||
DEBUG(3, "link=0x%p", link);
|
||||
pr_debug("link=0x%p\n", link);
|
||||
|
||||
card_settings(dev, link, &new_name);
|
||||
|
||||
@ -512,11 +492,11 @@ static int pcmciamtd_config(struct pcmcia_device *link)
|
||||
|
||||
do {
|
||||
int ret;
|
||||
DEBUG(2, "requesting window with size = %luKiB memspeed = %d",
|
||||
pr_debug("requesting window with size = %luKiB memspeed = %d\n",
|
||||
(unsigned long) resource_size(link->resource[2]) >> 10,
|
||||
mem_speed);
|
||||
ret = pcmcia_request_window(link, link->resource[2], mem_speed);
|
||||
DEBUG(2, "ret = %d dev->win_size = %d", ret, dev->win_size);
|
||||
pr_debug("ret = %d dev->win_size = %d\n", ret, dev->win_size);
|
||||
if(ret) {
|
||||
j++;
|
||||
link->resource[2]->start = 0;
|
||||
@ -524,21 +504,21 @@ static int pcmciamtd_config(struct pcmcia_device *link)
|
||||
force_size << 20 : MAX_PCMCIA_ADDR;
|
||||
link->resource[2]->end >>= j;
|
||||
} else {
|
||||
DEBUG(2, "Got window of size %luKiB", (unsigned long)
|
||||
pr_debug("Got window of size %luKiB\n", (unsigned long)
|
||||
resource_size(link->resource[2]) >> 10);
|
||||
dev->win_size = resource_size(link->resource[2]);
|
||||
break;
|
||||
}
|
||||
} while (link->resource[2]->end >= 0x1000);
|
||||
|
||||
DEBUG(2, "dev->win_size = %d", dev->win_size);
|
||||
pr_debug("dev->win_size = %d\n", dev->win_size);
|
||||
|
||||
if(!dev->win_size) {
|
||||
dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
|
||||
pcmciamtd_release(link);
|
||||
return -ENODEV;
|
||||
}
|
||||
DEBUG(1, "Allocated a window of %dKiB", dev->win_size >> 10);
|
||||
pr_debug("Allocated a window of %dKiB\n", dev->win_size >> 10);
|
||||
|
||||
/* Get write protect status */
|
||||
dev->win_base = ioremap(link->resource[2]->start,
|
||||
@ -549,7 +529,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
|
||||
pcmciamtd_release(link);
|
||||
return -ENODEV;
|
||||
}
|
||||
DEBUG(1, "mapped window dev = %p @ %pR, base = %p",
|
||||
pr_debug("mapped window dev = %p @ %pR, base = %p\n",
|
||||
dev, link->resource[2], dev->win_base);
|
||||
|
||||
dev->offset = 0;
|
||||
@ -564,7 +544,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
|
||||
}
|
||||
|
||||
link->config_index = 0;
|
||||
DEBUG(2, "Setting Configuration");
|
||||
pr_debug("Setting Configuration\n");
|
||||
ret = pcmcia_enable_device(link);
|
||||
if (ret != 0) {
|
||||
if (dev->win_base) {
|
||||
@ -580,17 +560,17 @@ static int pcmciamtd_config(struct pcmcia_device *link)
|
||||
mtd = do_map_probe("map_rom", &dev->pcmcia_map);
|
||||
} else {
|
||||
for(i = 0; i < ARRAY_SIZE(probes); i++) {
|
||||
DEBUG(1, "Trying %s", probes[i]);
|
||||
pr_debug("Trying %s\n", probes[i]);
|
||||
mtd = do_map_probe(probes[i], &dev->pcmcia_map);
|
||||
if(mtd)
|
||||
break;
|
||||
|
||||
DEBUG(1, "FAILED: %s", probes[i]);
|
||||
pr_debug("FAILED: %s\n", probes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if(!mtd) {
|
||||
DEBUG(1, "Can not find an MTD");
|
||||
pr_debug("Can not find an MTD\n");
|
||||
pcmciamtd_release(link);
|
||||
return -ENODEV;
|
||||
}
|
||||
@ -617,7 +597,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
|
||||
/* If the memory found is fits completely into the mapped PCMCIA window,
|
||||
use the faster non-remapping read/write functions */
|
||||
if(mtd->size <= dev->win_size) {
|
||||
DEBUG(1, "Using non remapping memory functions");
|
||||
pr_debug("Using non remapping memory functions\n");
|
||||
dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
|
||||
if (dev->pcmcia_map.bankwidth == 1) {
|
||||
dev->pcmcia_map.read = pcmcia_read8;
|
||||
@ -645,7 +625,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
|
||||
|
||||
static int pcmciamtd_suspend(struct pcmcia_device *dev)
|
||||
{
|
||||
DEBUG(2, "EVENT_PM_RESUME");
|
||||
pr_debug("EVENT_PM_RESUME\n");
|
||||
|
||||
/* get_lock(link); */
|
||||
|
||||
@ -654,7 +634,7 @@ static int pcmciamtd_suspend(struct pcmcia_device *dev)
|
||||
|
||||
static int pcmciamtd_resume(struct pcmcia_device *dev)
|
||||
{
|
||||
DEBUG(2, "EVENT_PM_SUSPEND");
|
||||
pr_debug("EVENT_PM_SUSPEND\n");
|
||||
|
||||
/* free_lock(link); */
|
||||
|
||||
@ -666,7 +646,7 @@ static void pcmciamtd_detach(struct pcmcia_device *link)
|
||||
{
|
||||
struct pcmciamtd_dev *dev = link->priv;
|
||||
|
||||
DEBUG(3, "link=0x%p", link);
|
||||
pr_debug("link=0x%p\n", link);
|
||||
|
||||
if(dev->mtd_info) {
|
||||
mtd_device_unregister(dev->mtd_info);
|
||||
@ -686,7 +666,7 @@ static int pcmciamtd_probe(struct pcmcia_device *link)
|
||||
/* Create new memory card device */
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev) return -ENOMEM;
|
||||
DEBUG(1, "dev=0x%p", dev);
|
||||
pr_debug("dev=0x%p\n", dev);
|
||||
|
||||
dev->p_dev = link;
|
||||
link->priv = dev;
|
||||
@ -755,7 +735,7 @@ static int __init init_pcmciamtd(void)
|
||||
|
||||
static void __exit exit_pcmciamtd(void)
|
||||
{
|
||||
DEBUG(1, DRIVER_DESC " unloading");
|
||||
pr_debug(DRIVER_DESC " unloading");
|
||||
pcmcia_unregister_driver(&pcmciamtd_driver);
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,6 @@ struct physmap_flash_info {
|
||||
struct mtd_info *mtd[MAX_RESOURCES];
|
||||
struct mtd_info *cmtd;
|
||||
struct map_info map[MAX_RESOURCES];
|
||||
int nr_parts;
|
||||
struct mtd_partition *parts;
|
||||
};
|
||||
|
||||
static int physmap_flash_remove(struct platform_device *dev)
|
||||
@ -46,8 +44,6 @@ static int physmap_flash_remove(struct platform_device *dev)
|
||||
|
||||
if (info->cmtd) {
|
||||
mtd_device_unregister(info->cmtd);
|
||||
if (info->nr_parts)
|
||||
kfree(info->parts);
|
||||
if (info->cmtd != info->mtd[0])
|
||||
mtd_concat_destroy(info->cmtd);
|
||||
}
|
||||
@ -175,23 +171,8 @@ static int physmap_flash_probe(struct platform_device *dev)
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
err = parse_mtd_partitions(info->cmtd, part_probe_types,
|
||||
&info->parts, 0);
|
||||
if (err > 0) {
|
||||
mtd_device_register(info->cmtd, info->parts, err);
|
||||
info->nr_parts = err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (physmap_data->nr_parts) {
|
||||
printk(KERN_NOTICE "Using physmap partition information\n");
|
||||
mtd_device_register(info->cmtd, physmap_data->parts,
|
||||
physmap_data->nr_parts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mtd_device_register(info->cmtd, NULL, 0);
|
||||
|
||||
mtd_device_parse_register(info->cmtd, part_probe_types, 0,
|
||||
physmap_data->parts, physmap_data->nr_parts);
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
@ -245,21 +226,6 @@ static struct platform_device physmap_flash = {
|
||||
.num_resources = 1,
|
||||
.resource = &physmap_flash_resource,
|
||||
};
|
||||
|
||||
void physmap_configure(unsigned long addr, unsigned long size,
|
||||
int bankwidth, void (*set_vpp)(struct map_info *, int))
|
||||
{
|
||||
physmap_flash_resource.start = addr;
|
||||
physmap_flash_resource.end = addr + size - 1;
|
||||
physmap_flash_data.width = bankwidth;
|
||||
physmap_flash_data.set_vpp = set_vpp;
|
||||
}
|
||||
|
||||
void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
|
||||
{
|
||||
physmap_flash_data.nr_parts = num_parts;
|
||||
physmap_flash_data.parts = parts;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int __init physmap_init(void)
|
||||
|
@ -34,58 +34,10 @@ struct of_flash_list {
|
||||
|
||||
struct of_flash {
|
||||
struct mtd_info *cmtd;
|
||||
struct mtd_partition *parts;
|
||||
int list_size; /* number of elements in of_flash_list */
|
||||
struct of_flash_list list[0];
|
||||
};
|
||||
|
||||
#define OF_FLASH_PARTS(info) ((info)->parts)
|
||||
static int parse_obsolete_partitions(struct platform_device *dev,
|
||||
struct of_flash *info,
|
||||
struct device_node *dp)
|
||||
{
|
||||
int i, plen, nr_parts;
|
||||
const struct {
|
||||
__be32 offset, len;
|
||||
} *part;
|
||||
const char *names;
|
||||
|
||||
part = of_get_property(dp, "partitions", &plen);
|
||||
if (!part)
|
||||
return 0; /* No partitions found */
|
||||
|
||||
dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
|
||||
|
||||
nr_parts = plen / sizeof(part[0]);
|
||||
|
||||
info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
|
||||
if (!info->parts)
|
||||
return -ENOMEM;
|
||||
|
||||
names = of_get_property(dp, "partition-names", &plen);
|
||||
|
||||
for (i = 0; i < nr_parts; i++) {
|
||||
info->parts[i].offset = be32_to_cpu(part->offset);
|
||||
info->parts[i].size = be32_to_cpu(part->len) & ~1;
|
||||
if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
|
||||
info->parts[i].mask_flags = MTD_WRITEABLE;
|
||||
|
||||
if (names && (plen > 0)) {
|
||||
int len = strlen(names) + 1;
|
||||
|
||||
info->parts[i].name = (char *)names;
|
||||
plen -= len;
|
||||
names += len;
|
||||
} else {
|
||||
info->parts[i].name = "unnamed";
|
||||
}
|
||||
|
||||
part++;
|
||||
}
|
||||
|
||||
return nr_parts;
|
||||
}
|
||||
|
||||
static int of_flash_remove(struct platform_device *dev)
|
||||
{
|
||||
struct of_flash *info;
|
||||
@ -101,11 +53,8 @@ static int of_flash_remove(struct platform_device *dev)
|
||||
mtd_concat_destroy(info->cmtd);
|
||||
}
|
||||
|
||||
if (info->cmtd) {
|
||||
if (OF_FLASH_PARTS(info))
|
||||
kfree(OF_FLASH_PARTS(info));
|
||||
if (info->cmtd)
|
||||
mtd_device_unregister(info->cmtd);
|
||||
}
|
||||
|
||||
for (i = 0; i < info->list_size; i++) {
|
||||
if (info->list[i].mtd)
|
||||
@ -165,7 +114,8 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
|
||||
specifies the list of partition probers to use. If none is given then the
|
||||
default is use. These take precedence over other device tree
|
||||
information. */
|
||||
static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL };
|
||||
static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
|
||||
"ofpart", "ofoldpart", NULL };
|
||||
static const char ** __devinit of_get_probes(struct device_node *dp)
|
||||
{
|
||||
const char *cp;
|
||||
@ -218,6 +168,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
|
||||
int reg_tuple_size;
|
||||
struct mtd_info **mtd_list = NULL;
|
||||
resource_size_t res_size;
|
||||
struct mtd_part_parser_data ppdata;
|
||||
|
||||
match = of_match_device(of_flash_match, &dev->dev);
|
||||
if (!match)
|
||||
@ -331,29 +282,12 @@ static int __devinit of_flash_probe(struct platform_device *dev)
|
||||
if (err)
|
||||
goto err_out;
|
||||
|
||||
ppdata.of_node = dp;
|
||||
part_probe_types = of_get_probes(dp);
|
||||
err = parse_mtd_partitions(info->cmtd, part_probe_types,
|
||||
&info->parts, 0);
|
||||
if (err < 0) {
|
||||
of_free_probes(part_probe_types);
|
||||
goto err_out;
|
||||
}
|
||||
mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
|
||||
NULL, 0);
|
||||
of_free_probes(part_probe_types);
|
||||
|
||||
if (err == 0) {
|
||||
err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
|
||||
if (err < 0)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if (err == 0) {
|
||||
err = parse_obsolete_partitions(dev, info, dp);
|
||||
if (err < 0)
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
mtd_device_register(info->cmtd, info->parts, err);
|
||||
|
||||
kfree(mtd_list);
|
||||
|
||||
return 0;
|
||||
|
@ -44,8 +44,6 @@ struct platram_info {
|
||||
struct device *dev;
|
||||
struct mtd_info *mtd;
|
||||
struct map_info map;
|
||||
struct mtd_partition *partitions;
|
||||
bool free_partitions;
|
||||
struct resource *area;
|
||||
struct platdata_mtd_ram *pdata;
|
||||
};
|
||||
@ -95,10 +93,6 @@ static int platram_remove(struct platform_device *pdev)
|
||||
|
||||
if (info->mtd) {
|
||||
mtd_device_unregister(info->mtd);
|
||||
if (info->partitions) {
|
||||
if (info->free_partitions)
|
||||
kfree(info->partitions);
|
||||
}
|
||||
map_destroy(info->mtd);
|
||||
}
|
||||
|
||||
@ -228,21 +222,8 @@ static int platram_probe(struct platform_device *pdev)
|
||||
/* check to see if there are any available partitions, or wether
|
||||
* to add this device whole */
|
||||
|
||||
if (!pdata->nr_partitions) {
|
||||
/* try to probe using the supplied probe type */
|
||||
if (pdata->probes) {
|
||||
err = parse_mtd_partitions(info->mtd, pdata->probes,
|
||||
&info->partitions, 0);
|
||||
info->free_partitions = 1;
|
||||
if (err > 0)
|
||||
err = mtd_device_register(info->mtd,
|
||||
info->partitions, err);
|
||||
}
|
||||
}
|
||||
/* use the static mapping */
|
||||
else
|
||||
err = mtd_device_register(info->mtd, pdata->partitions,
|
||||
pdata->nr_partitions);
|
||||
err = mtd_device_parse_register(info->mtd, pdata->probes, 0,
|
||||
pdata->partitions, pdata->nr_partitions);
|
||||
if (!err)
|
||||
dev_info(&pdev->dev, "registered mtd device\n");
|
||||
|
||||
|
@ -41,8 +41,6 @@ static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from,
|
||||
}
|
||||
|
||||
struct pxa2xx_flash_info {
|
||||
struct mtd_partition *parts;
|
||||
int nr_parts;
|
||||
struct mtd_info *mtd;
|
||||
struct map_info map;
|
||||
};
|
||||
@ -55,9 +53,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct flash_platform_data *flash = pdev->dev.platform_data;
|
||||
struct pxa2xx_flash_info *info;
|
||||
struct mtd_partition *parts;
|
||||
struct resource *res;
|
||||
int ret = 0;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
@ -71,8 +67,6 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
|
||||
info->map.bankwidth = flash->width;
|
||||
info->map.phys = res->start;
|
||||
info->map.size = resource_size(res);
|
||||
info->parts = flash->parts;
|
||||
info->nr_parts = flash->nr_parts;
|
||||
|
||||
info->map.virt = ioremap(info->map.phys, info->map.size);
|
||||
if (!info->map.virt) {
|
||||
@ -104,18 +98,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
|
||||
}
|
||||
info->mtd->owner = THIS_MODULE;
|
||||
|
||||
ret = parse_mtd_partitions(info->mtd, probes, &parts, 0);
|
||||
|
||||
if (ret > 0) {
|
||||
info->nr_parts = ret;
|
||||
info->parts = parts;
|
||||
}
|
||||
|
||||
if (!info->nr_parts)
|
||||
printk("Registering %s as whole device\n",
|
||||
info->map.name);
|
||||
|
||||
mtd_device_register(info->mtd, info->parts, info->nr_parts);
|
||||
mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
|
||||
|
||||
platform_set_drvdata(pdev, info);
|
||||
return 0;
|
||||
@ -133,7 +116,6 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
|
||||
iounmap(info->map.virt);
|
||||
if (info->map.cached)
|
||||
iounmap(info->map.cached);
|
||||
kfree(info->parts);
|
||||
kfree(info);
|
||||
return 0;
|
||||
}
|
||||
|
@ -25,8 +25,6 @@
|
||||
struct rbtx4939_flash_info {
|
||||
struct mtd_info *mtd;
|
||||
struct map_info map;
|
||||
int nr_parts;
|
||||
struct mtd_partition *parts;
|
||||
};
|
||||
|
||||
static int rbtx4939_flash_remove(struct platform_device *dev)
|
||||
@ -41,8 +39,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
|
||||
if (info->mtd) {
|
||||
struct rbtx4939_flash_data *pdata = dev->dev.platform_data;
|
||||
|
||||
if (info->nr_parts)
|
||||
kfree(info->parts);
|
||||
mtd_device_unregister(info->mtd);
|
||||
map_destroy(info->mtd);
|
||||
}
|
||||
@ -50,7 +46,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
|
||||
}
|
||||
|
||||
static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
|
||||
static const char *part_probe_types[] = { "cmdlinepart", NULL };
|
||||
|
||||
static int rbtx4939_flash_probe(struct platform_device *dev)
|
||||
{
|
||||
@ -107,22 +102,11 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
|
||||
info->mtd->owner = THIS_MODULE;
|
||||
if (err)
|
||||
goto err_out;
|
||||
err = mtd_device_parse_register(info->mtd, NULL, 0,
|
||||
pdata->parts, pdata->nr_parts);
|
||||
|
||||
err = parse_mtd_partitions(info->mtd, part_probe_types,
|
||||
&info->parts, 0);
|
||||
if (err > 0) {
|
||||
mtd_device_register(info->mtd, info->parts, err);
|
||||
info->nr_parts = err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pdata->nr_parts) {
|
||||
pr_notice("Using rbtx4939 partition information\n");
|
||||
mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mtd_device_register(info->mtd, NULL, 0);
|
||||
if (err)
|
||||
goto err_out;
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
|
@ -131,10 +131,8 @@ struct sa_subdev_info {
|
||||
};
|
||||
|
||||
struct sa_info {
|
||||
struct mtd_partition *parts;
|
||||
struct mtd_info *mtd;
|
||||
int num_subdev;
|
||||
unsigned int nr_parts;
|
||||
struct sa_subdev_info subdev[0];
|
||||
};
|
||||
|
||||
@ -231,8 +229,6 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla
|
||||
mtd_concat_destroy(info->mtd);
|
||||
}
|
||||
|
||||
kfree(info->parts);
|
||||
|
||||
for (i = info->num_subdev - 1; i >= 0; i--)
|
||||
sa1100_destroy_subdev(&info->subdev[i]);
|
||||
kfree(info);
|
||||
@ -341,10 +337,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
|
||||
static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct flash_platform_data *plat = pdev->dev.platform_data;
|
||||
struct mtd_partition *parts;
|
||||
const char *part_type = NULL;
|
||||
struct sa_info *info;
|
||||
int err, nr_parts = 0;
|
||||
int err;
|
||||
|
||||
if (!plat)
|
||||
return -ENODEV;
|
||||
@ -358,26 +352,8 @@ static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
|
||||
/*
|
||||
* Partition selection stuff.
|
||||
*/
|
||||
nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
|
||||
if (nr_parts > 0) {
|
||||
info->parts = parts;
|
||||
part_type = "dynamic";
|
||||
} else {
|
||||
parts = plat->parts;
|
||||
nr_parts = plat->nr_parts;
|
||||
part_type = "static";
|
||||
}
|
||||
|
||||
if (nr_parts == 0)
|
||||
printk(KERN_NOTICE "SA1100 flash: no partition info "
|
||||
"available, registering whole flash\n");
|
||||
else
|
||||
printk(KERN_NOTICE "SA1100 flash: using %s partition "
|
||||
"definition\n", part_type);
|
||||
|
||||
mtd_device_register(info->mtd, parts, nr_parts);
|
||||
|
||||
info->nr_parts = nr_parts;
|
||||
mtd_device_parse_register(info->mtd, part_probes, 0,
|
||||
plat->parts, plat->nr_parts);
|
||||
|
||||
platform_set_drvdata(pdev, info);
|
||||
err = 0;
|
||||
|
@ -19,8 +19,6 @@
|
||||
static struct mtd_info *flash_mtd;
|
||||
static struct mtd_info *eprom_mtd;
|
||||
|
||||
static struct mtd_partition *parsed_parts;
|
||||
|
||||
struct map_info soleng_eprom_map = {
|
||||
.name = "Solution Engine EPROM",
|
||||
.size = 0x400000,
|
||||
@ -51,12 +49,14 @@ static struct mtd_partition superh_se_partitions[] = {
|
||||
.size = MTDPART_SIZ_FULL,
|
||||
}
|
||||
};
|
||||
#define NUM_PARTITIONS ARRAY_SIZE(superh_se_partitions)
|
||||
#else
|
||||
#define superh_se_partitions NULL
|
||||
#define NUM_PARTITIONS 0
|
||||
#endif /* CONFIG_MTD_SUPERH_RESERVE */
|
||||
|
||||
static int __init init_soleng_maps(void)
|
||||
{
|
||||
int nr_parts = 0;
|
||||
|
||||
/* First probe at offset 0 */
|
||||
soleng_flash_map.phys = 0;
|
||||
soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0);
|
||||
@ -92,21 +92,8 @@ static int __init init_soleng_maps(void)
|
||||
mtd_device_register(eprom_mtd, NULL, 0);
|
||||
}
|
||||
|
||||
nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
|
||||
|
||||
#ifdef CONFIG_MTD_SUPERH_RESERVE
|
||||
if (nr_parts <= 0) {
|
||||
printk(KERN_NOTICE "Using configured partition at 0x%08x.\n",
|
||||
CONFIG_MTD_SUPERH_RESERVE);
|
||||
parsed_parts = superh_se_partitions;
|
||||
nr_parts = sizeof(superh_se_partitions)/sizeof(*parsed_parts);
|
||||
}
|
||||
#endif /* CONFIG_MTD_SUPERH_RESERVE */
|
||||
|
||||
if (nr_parts > 0)
|
||||
mtd_device_register(flash_mtd, parsed_parts, nr_parts);
|
||||
else
|
||||
mtd_device_register(flash_mtd, NULL, 0);
|
||||
mtd_device_parse_register(flash_mtd, probes, 0,
|
||||
superh_se_partitions, NUM_PARTITIONS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -118,10 +105,7 @@ static void __exit cleanup_soleng_maps(void)
|
||||
map_destroy(eprom_mtd);
|
||||
}
|
||||
|
||||
if (parsed_parts)
|
||||
mtd_device_unregister(flash_mtd);
|
||||
else
|
||||
mtd_device_unregister(flash_mtd);
|
||||
mtd_device_unregister(flash_mtd);
|
||||
map_destroy(flash_mtd);
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include <asm/immap_cpm2.h>
|
||||
|
||||
static struct mtd_info *sbcmtd[3];
|
||||
static struct mtd_partition *sbcmtd_parts[3];
|
||||
|
||||
struct map_info sbc82xx_flash_map[3] = {
|
||||
{.name = "Boot flash"},
|
||||
@ -101,6 +100,7 @@ static int __init init_sbc82xx_flash(void)
|
||||
for (i=0; i<3; i++) {
|
||||
int8_t flashcs[3] = { 0, 6, 1 };
|
||||
int nr_parts;
|
||||
struct mtd_partition *defparts;
|
||||
|
||||
printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
|
||||
sbc82xx_flash_map[i].name,
|
||||
@ -113,7 +113,8 @@ static int __init init_sbc82xx_flash(void)
|
||||
}
|
||||
printk(" at %08lx)\n", sbc82xx_flash_map[i].phys);
|
||||
|
||||
sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys, sbc82xx_flash_map[i].size);
|
||||
sbc82xx_flash_map[i].virt = ioremap(sbc82xx_flash_map[i].phys,
|
||||
sbc82xx_flash_map[i].size);
|
||||
|
||||
if (!sbc82xx_flash_map[i].virt) {
|
||||
printk("Failed to ioremap\n");
|
||||
@ -129,24 +130,20 @@ static int __init init_sbc82xx_flash(void)
|
||||
|
||||
sbcmtd[i]->owner = THIS_MODULE;
|
||||
|
||||
nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
|
||||
&sbcmtd_parts[i], 0);
|
||||
if (nr_parts > 0) {
|
||||
mtd_device_register(sbcmtd[i], sbcmtd_parts[i],
|
||||
nr_parts);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* No partitioning detected. Use default */
|
||||
if (i == 2) {
|
||||
mtd_device_register(sbcmtd[i], NULL, 0);
|
||||
defparts = NULL;
|
||||
nr_parts = 0;
|
||||
} else if (i == bigflash) {
|
||||
mtd_device_register(sbcmtd[i], bigflash_parts,
|
||||
ARRAY_SIZE(bigflash_parts));
|
||||
defparts = bigflash_parts;
|
||||
nr_parts = ARRAY_SIZE(bigflash_parts);
|
||||
} else {
|
||||
mtd_device_register(sbcmtd[i], smallflash_parts,
|
||||
ARRAY_SIZE(smallflash_parts));
|
||||
defparts = smallflash_parts;
|
||||
nr_parts = ARRAY_SIZE(smallflash_parts);
|
||||
}
|
||||
|
||||
mtd_device_parse_register(sbcmtd[i], part_probes, 0,
|
||||
defparts, nr_parts);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -159,12 +156,8 @@ static void __exit cleanup_sbc82xx_flash(void)
|
||||
if (!sbcmtd[i])
|
||||
continue;
|
||||
|
||||
if (i<2 || sbcmtd_parts[i])
|
||||
mtd_device_unregister(sbcmtd[i]);
|
||||
else
|
||||
mtd_device_unregister(sbcmtd[i]);
|
||||
mtd_device_unregister(sbcmtd[i]);
|
||||
|
||||
kfree(sbcmtd_parts[i]);
|
||||
map_destroy(sbcmtd[i]);
|
||||
|
||||
iounmap((void *)sbc82xx_flash_map[i].virt);
|
||||
|
@ -426,6 +426,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
|
||||
new->rq->queuedata = new;
|
||||
blk_queue_logical_block_size(new->rq, tr->blksize);
|
||||
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_NONROT, new->rq);
|
||||
|
||||
if (tr->discard) {
|
||||
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq);
|
||||
new->rq->limits.max_discard_sectors = UINT_MAX;
|
||||
|
@ -44,7 +44,7 @@ struct mtdblk_dev {
|
||||
enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
|
||||
};
|
||||
|
||||
static struct mutex mtdblks_lock;
|
||||
static DEFINE_MUTEX(mtdblks_lock);
|
||||
|
||||
/*
|
||||
* Cache stuff...
|
||||
@ -119,7 +119,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk)
|
||||
if (mtdblk->cache_state != STATE_DIRTY)
|
||||
return 0;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" "
|
||||
pr_debug("mtdblock: writing cached data for \"%s\" "
|
||||
"at 0x%lx, size 0x%x\n", mtd->name,
|
||||
mtdblk->cache_offset, mtdblk->cache_size);
|
||||
|
||||
@ -148,7 +148,7 @@ static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
size_t retlen;
|
||||
int ret;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",
|
||||
pr_debug("mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n",
|
||||
mtd->name, pos, len);
|
||||
|
||||
if (!sect_size)
|
||||
@ -218,7 +218,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
|
||||
size_t retlen;
|
||||
int ret;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
|
||||
pr_debug("mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n",
|
||||
mtd->name, pos, len);
|
||||
|
||||
if (!sect_size)
|
||||
@ -283,7 +283,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
|
||||
{
|
||||
struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd);
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n");
|
||||
pr_debug("mtdblock_open\n");
|
||||
|
||||
mutex_lock(&mtdblks_lock);
|
||||
if (mtdblk->count) {
|
||||
@ -303,7 +303,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
|
||||
|
||||
mutex_unlock(&mtdblks_lock);
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
|
||||
pr_debug("ok\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -312,7 +312,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
|
||||
{
|
||||
struct mtdblk_dev *mtdblk = container_of(mbd, struct mtdblk_dev, mbd);
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n");
|
||||
pr_debug("mtdblock_release\n");
|
||||
|
||||
mutex_lock(&mtdblks_lock);
|
||||
|
||||
@ -329,7 +329,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
|
||||
|
||||
mutex_unlock(&mtdblks_lock);
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
|
||||
pr_debug("ok\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -389,8 +389,6 @@ static struct mtd_blktrans_ops mtdblock_tr = {
|
||||
|
||||
static int __init init_mtdblock(void)
|
||||
{
|
||||
mutex_init(&mtdblks_lock);
|
||||
|
||||
return register_mtd_blktrans(&mtdblock_tr);
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ static struct vfsmount *mtd_inode_mnt __read_mostly;
|
||||
|
||||
/*
|
||||
* Data structure to hold the pointer to the mtd device as well
|
||||
* as mode information ofr various use cases.
|
||||
* as mode information of various use cases.
|
||||
*/
|
||||
struct mtd_file_info {
|
||||
struct mtd_info *mtd;
|
||||
@ -86,7 +86,7 @@ static int mtd_open(struct inode *inode, struct file *file)
|
||||
struct mtd_file_info *mfi;
|
||||
struct inode *mtd_ino;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
|
||||
pr_debug("MTD_open\n");
|
||||
|
||||
/* You can't open the RO devices RW */
|
||||
if ((file->f_mode & FMODE_WRITE) && (minor & 1))
|
||||
@ -151,7 +151,7 @@ static int mtd_close(struct inode *inode, struct file *file)
|
||||
struct mtd_file_info *mfi = file->private_data;
|
||||
struct mtd_info *mtd = mfi->mtd;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
|
||||
pr_debug("MTD_close\n");
|
||||
|
||||
/* Only sync if opened RW */
|
||||
if ((file->f_mode & FMODE_WRITE) && mtd->sync)
|
||||
@ -195,7 +195,7 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
|
||||
size_t size = count;
|
||||
char *kbuf;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
|
||||
pr_debug("MTD_read\n");
|
||||
|
||||
if (*ppos + count > mtd->size)
|
||||
count = mtd->size - *ppos;
|
||||
@ -211,17 +211,17 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
|
||||
len = min_t(size_t, count, size);
|
||||
|
||||
switch (mfi->mode) {
|
||||
case MTD_MODE_OTP_FACTORY:
|
||||
case MTD_FILE_MODE_OTP_FACTORY:
|
||||
ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf);
|
||||
break;
|
||||
case MTD_MODE_OTP_USER:
|
||||
case MTD_FILE_MODE_OTP_USER:
|
||||
ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
|
||||
break;
|
||||
case MTD_MODE_RAW:
|
||||
case MTD_FILE_MODE_RAW:
|
||||
{
|
||||
struct mtd_oob_ops ops;
|
||||
|
||||
ops.mode = MTD_OOB_RAW;
|
||||
ops.mode = MTD_OPS_RAW;
|
||||
ops.datbuf = kbuf;
|
||||
ops.oobbuf = NULL;
|
||||
ops.len = len;
|
||||
@ -233,16 +233,16 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
|
||||
default:
|
||||
ret = mtd->read(mtd, *ppos, len, &retlen, kbuf);
|
||||
}
|
||||
/* Nand returns -EBADMSG on ecc errors, but it returns
|
||||
/* Nand returns -EBADMSG on ECC errors, but it returns
|
||||
* the data. For our userspace tools it is important
|
||||
* to dump areas with ecc errors !
|
||||
* to dump areas with ECC errors!
|
||||
* For kernel internal usage it also might return -EUCLEAN
|
||||
* to signal the caller that a bitflip has occurred and has
|
||||
* been corrected by the ECC algorithm.
|
||||
* Userspace software which accesses NAND this way
|
||||
* must be aware of the fact that it deals with NAND
|
||||
*/
|
||||
if (!ret || (ret == -EUCLEAN) || (ret == -EBADMSG)) {
|
||||
if (!ret || mtd_is_bitflip_or_eccerr(ret)) {
|
||||
*ppos += retlen;
|
||||
if (copy_to_user(buf, kbuf, retlen)) {
|
||||
kfree(kbuf);
|
||||
@ -278,7 +278,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
|
||||
int ret=0;
|
||||
int len;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
|
||||
pr_debug("MTD_write\n");
|
||||
|
||||
if (*ppos == mtd->size)
|
||||
return -ENOSPC;
|
||||
@ -302,10 +302,10 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
|
||||
}
|
||||
|
||||
switch (mfi->mode) {
|
||||
case MTD_MODE_OTP_FACTORY:
|
||||
case MTD_FILE_MODE_OTP_FACTORY:
|
||||
ret = -EROFS;
|
||||
break;
|
||||
case MTD_MODE_OTP_USER:
|
||||
case MTD_FILE_MODE_OTP_USER:
|
||||
if (!mtd->write_user_prot_reg) {
|
||||
ret = -EOPNOTSUPP;
|
||||
break;
|
||||
@ -313,13 +313,14 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
|
||||
ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
|
||||
break;
|
||||
|
||||
case MTD_MODE_RAW:
|
||||
case MTD_FILE_MODE_RAW:
|
||||
{
|
||||
struct mtd_oob_ops ops;
|
||||
|
||||
ops.mode = MTD_OOB_RAW;
|
||||
ops.mode = MTD_OPS_RAW;
|
||||
ops.datbuf = kbuf;
|
||||
ops.oobbuf = NULL;
|
||||
ops.ooboffs = 0;
|
||||
ops.len = len;
|
||||
|
||||
ret = mtd->write_oob(mtd, *ppos, &ops);
|
||||
@ -367,13 +368,13 @@ static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
|
||||
if (!mtd->read_fact_prot_reg)
|
||||
ret = -EOPNOTSUPP;
|
||||
else
|
||||
mfi->mode = MTD_MODE_OTP_FACTORY;
|
||||
mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
|
||||
break;
|
||||
case MTD_OTP_USER:
|
||||
if (!mtd->read_fact_prot_reg)
|
||||
ret = -EOPNOTSUPP;
|
||||
else
|
||||
mfi->mode = MTD_MODE_OTP_USER;
|
||||
mfi->mode = MTD_FILE_MODE_OTP_USER;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@ -390,6 +391,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
|
||||
uint64_t start, uint32_t length, void __user *ptr,
|
||||
uint32_t __user *retp)
|
||||
{
|
||||
struct mtd_file_info *mfi = file->private_data;
|
||||
struct mtd_oob_ops ops;
|
||||
uint32_t retlen;
|
||||
int ret = 0;
|
||||
@ -409,9 +411,10 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
|
||||
return ret;
|
||||
|
||||
ops.ooblen = length;
|
||||
ops.ooboffs = start & (mtd->oobsize - 1);
|
||||
ops.ooboffs = start & (mtd->writesize - 1);
|
||||
ops.datbuf = NULL;
|
||||
ops.mode = MTD_OOB_PLACE;
|
||||
ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
|
||||
MTD_OPS_PLACE_OOB;
|
||||
|
||||
if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
|
||||
return -EINVAL;
|
||||
@ -420,7 +423,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
|
||||
if (IS_ERR(ops.oobbuf))
|
||||
return PTR_ERR(ops.oobbuf);
|
||||
|
||||
start &= ~((uint64_t)mtd->oobsize - 1);
|
||||
start &= ~((uint64_t)mtd->writesize - 1);
|
||||
ret = mtd->write_oob(mtd, start, &ops);
|
||||
|
||||
if (ops.oobretlen > 0xFFFFFFFFU)
|
||||
@ -433,9 +436,11 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
|
||||
uint32_t length, void __user *ptr, uint32_t __user *retp)
|
||||
static int mtd_do_readoob(struct file *file, struct mtd_info *mtd,
|
||||
uint64_t start, uint32_t length, void __user *ptr,
|
||||
uint32_t __user *retp)
|
||||
{
|
||||
struct mtd_file_info *mfi = file->private_data;
|
||||
struct mtd_oob_ops ops;
|
||||
int ret = 0;
|
||||
|
||||
@ -451,9 +456,10 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
|
||||
return ret;
|
||||
|
||||
ops.ooblen = length;
|
||||
ops.ooboffs = start & (mtd->oobsize - 1);
|
||||
ops.ooboffs = start & (mtd->writesize - 1);
|
||||
ops.datbuf = NULL;
|
||||
ops.mode = MTD_OOB_PLACE;
|
||||
ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW :
|
||||
MTD_OPS_PLACE_OOB;
|
||||
|
||||
if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
|
||||
return -EINVAL;
|
||||
@ -462,7 +468,7 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
|
||||
if (!ops.oobbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
start &= ~((uint64_t)mtd->oobsize - 1);
|
||||
start &= ~((uint64_t)mtd->writesize - 1);
|
||||
ret = mtd->read_oob(mtd, start, &ops);
|
||||
|
||||
if (put_user(ops.oobretlen, retp))
|
||||
@ -472,13 +478,29 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
|
||||
ret = -EFAULT;
|
||||
|
||||
kfree(ops.oobbuf);
|
||||
|
||||
/*
|
||||
* NAND returns -EBADMSG on ECC errors, but it returns the OOB
|
||||
* data. For our userspace tools it is important to dump areas
|
||||
* with ECC errors!
|
||||
* For kernel internal usage it also might return -EUCLEAN
|
||||
* to signal the caller that a bitflip has occured and has
|
||||
* been corrected by the ECC algorithm.
|
||||
*
|
||||
* Note: currently the standard NAND function, nand_read_oob_std,
|
||||
* does not calculate ECC for the OOB area, so do not rely on
|
||||
* this behavior unless you have replaced it with your own.
|
||||
*/
|
||||
if (mtd_is_bitflip_or_eccerr(ret))
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies (and truncates, if necessary) data from the larger struct,
|
||||
* nand_ecclayout, to the smaller, deprecated layout struct,
|
||||
* nand_ecclayout_user. This is necessary only to suppport the deprecated
|
||||
* nand_ecclayout_user. This is necessary only to support the deprecated
|
||||
* API ioctl ECCGETLAYOUT while allowing all new functionality to use
|
||||
* nand_ecclayout flexibly (i.e. the struct may change size in new
|
||||
* releases without requiring major rewrites).
|
||||
@ -544,6 +566,55 @@ static int mtd_blkpg_ioctl(struct mtd_info *mtd,
|
||||
}
|
||||
}
|
||||
|
||||
static int mtd_write_ioctl(struct mtd_info *mtd,
|
||||
struct mtd_write_req __user *argp)
|
||||
{
|
||||
struct mtd_write_req req;
|
||||
struct mtd_oob_ops ops;
|
||||
void __user *usr_data, *usr_oob;
|
||||
int ret;
|
||||
|
||||
if (copy_from_user(&req, argp, sizeof(req)) ||
|
||||
!access_ok(VERIFY_READ, req.usr_data, req.len) ||
|
||||
!access_ok(VERIFY_READ, req.usr_oob, req.ooblen))
|
||||
return -EFAULT;
|
||||
if (!mtd->write_oob)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
ops.mode = req.mode;
|
||||
ops.len = (size_t)req.len;
|
||||
ops.ooblen = (size_t)req.ooblen;
|
||||
ops.ooboffs = 0;
|
||||
|
||||
usr_data = (void __user *)(uintptr_t)req.usr_data;
|
||||
usr_oob = (void __user *)(uintptr_t)req.usr_oob;
|
||||
|
||||
if (req.usr_data) {
|
||||
ops.datbuf = memdup_user(usr_data, ops.len);
|
||||
if (IS_ERR(ops.datbuf))
|
||||
return PTR_ERR(ops.datbuf);
|
||||
} else {
|
||||
ops.datbuf = NULL;
|
||||
}
|
||||
|
||||
if (req.usr_oob) {
|
||||
ops.oobbuf = memdup_user(usr_oob, ops.ooblen);
|
||||
if (IS_ERR(ops.oobbuf)) {
|
||||
kfree(ops.datbuf);
|
||||
return PTR_ERR(ops.oobbuf);
|
||||
}
|
||||
} else {
|
||||
ops.oobbuf = NULL;
|
||||
}
|
||||
|
||||
ret = mtd->write_oob(mtd, (loff_t)req.start, &ops);
|
||||
|
||||
kfree(ops.datbuf);
|
||||
kfree(ops.oobbuf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
{
|
||||
struct mtd_file_info *mfi = file->private_data;
|
||||
@ -553,7 +624,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
u_long size;
|
||||
struct mtd_info_user info;
|
||||
|
||||
DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
|
||||
pr_debug("MTD_ioctl\n");
|
||||
|
||||
size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
|
||||
if (cmd & IOC_IN) {
|
||||
@ -601,8 +672,8 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
info.erasesize = mtd->erasesize;
|
||||
info.writesize = mtd->writesize;
|
||||
info.oobsize = mtd->oobsize;
|
||||
/* The below fields are obsolete */
|
||||
info.ecctype = -1;
|
||||
/* The below field is obsolete */
|
||||
info.padding = 0;
|
||||
if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
|
||||
return -EFAULT;
|
||||
break;
|
||||
@ -698,7 +769,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
if (copy_from_user(&buf, argp, sizeof(buf)))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = mtd_do_readoob(mtd, buf.start, buf.length,
|
||||
ret = mtd_do_readoob(file, mtd, buf.start, buf.length,
|
||||
buf.ptr, &buf_user->start);
|
||||
break;
|
||||
}
|
||||
@ -725,12 +796,19 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
if (copy_from_user(&buf, argp, sizeof(buf)))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = mtd_do_readoob(mtd, buf.start, buf.length,
|
||||
ret = mtd_do_readoob(file, mtd, buf.start, buf.length,
|
||||
(void __user *)(uintptr_t)buf.usr_ptr,
|
||||
&buf_user->length);
|
||||
break;
|
||||
}
|
||||
|
||||
case MEMWRITE:
|
||||
{
|
||||
ret = mtd_write_ioctl(mtd,
|
||||
(struct mtd_write_req __user *)arg);
|
||||
break;
|
||||
}
|
||||
|
||||
case MEMLOCK:
|
||||
{
|
||||
struct erase_info_user einfo;
|
||||
@ -827,7 +905,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
if (copy_from_user(&mode, argp, sizeof(int)))
|
||||
return -EFAULT;
|
||||
|
||||
mfi->mode = MTD_MODE_NORMAL;
|
||||
mfi->mode = MTD_FILE_MODE_NORMAL;
|
||||
|
||||
ret = otp_select_filemode(mfi, mode);
|
||||
|
||||
@ -843,11 +921,11 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
return -ENOMEM;
|
||||
ret = -EOPNOTSUPP;
|
||||
switch (mfi->mode) {
|
||||
case MTD_MODE_OTP_FACTORY:
|
||||
case MTD_FILE_MODE_OTP_FACTORY:
|
||||
if (mtd->get_fact_prot_info)
|
||||
ret = mtd->get_fact_prot_info(mtd, buf, 4096);
|
||||
break;
|
||||
case MTD_MODE_OTP_USER:
|
||||
case MTD_FILE_MODE_OTP_USER:
|
||||
if (mtd->get_user_prot_info)
|
||||
ret = mtd->get_user_prot_info(mtd, buf, 4096);
|
||||
break;
|
||||
@ -871,7 +949,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
{
|
||||
struct otp_info oinfo;
|
||||
|
||||
if (mfi->mode != MTD_MODE_OTP_USER)
|
||||
if (mfi->mode != MTD_FILE_MODE_OTP_USER)
|
||||
return -EINVAL;
|
||||
if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
|
||||
return -EFAULT;
|
||||
@ -882,7 +960,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This ioctl is being deprecated - it truncates the ecc layout */
|
||||
/* This ioctl is being deprecated - it truncates the ECC layout */
|
||||
case ECCGETLAYOUT:
|
||||
{
|
||||
struct nand_ecclayout_user *usrlay;
|
||||
@ -915,17 +993,17 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
|
||||
mfi->mode = 0;
|
||||
|
||||
switch(arg) {
|
||||
case MTD_MODE_OTP_FACTORY:
|
||||
case MTD_MODE_OTP_USER:
|
||||
case MTD_FILE_MODE_OTP_FACTORY:
|
||||
case MTD_FILE_MODE_OTP_USER:
|
||||
ret = otp_select_filemode(mfi, arg);
|
||||
break;
|
||||
|
||||
case MTD_MODE_RAW:
|
||||
case MTD_FILE_MODE_RAW:
|
||||
if (!mtd->read_oob || !mtd->write_oob)
|
||||
return -EOPNOTSUPP;
|
||||
mfi->mode = arg;
|
||||
|
||||
case MTD_MODE_NORMAL:
|
||||
case MTD_FILE_MODE_NORMAL:
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
@ -1011,7 +1089,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
if (copy_from_user(&buf, argp, sizeof(buf)))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = mtd_do_readoob(mtd, buf.start,
|
||||
ret = mtd_do_readoob(file, mtd, buf.start,
|
||||
buf.length, compat_ptr(buf.ptr),
|
||||
&buf_user->start);
|
||||
break;
|
||||
|
@ -95,10 +95,10 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
|
||||
/* Save information about bitflips! */
|
||||
if (unlikely(err)) {
|
||||
if (err == -EBADMSG) {
|
||||
if (mtd_is_eccerr(err)) {
|
||||
mtd->ecc_stats.failed++;
|
||||
ret = err;
|
||||
} else if (err == -EUCLEAN) {
|
||||
} else if (mtd_is_bitflip(err)) {
|
||||
mtd->ecc_stats.corrected++;
|
||||
/* Do not overwrite -EBADMSG !! */
|
||||
if (!ret)
|
||||
@ -279,10 +279,10 @@ concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
|
||||
|
||||
/* Save information about bitflips! */
|
||||
if (unlikely(err)) {
|
||||
if (err == -EBADMSG) {
|
||||
if (mtd_is_eccerr(err)) {
|
||||
mtd->ecc_stats.failed++;
|
||||
ret = err;
|
||||
} else if (err == -EUCLEAN) {
|
||||
} else if (mtd_is_bitflip(err)) {
|
||||
mtd->ecc_stats.corrected++;
|
||||
/* Do not overwrite -EBADMSG !! */
|
||||
if (!ret)
|
||||
@ -770,7 +770,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
|
||||
|
||||
/*
|
||||
* Set up the new "super" device's MTD object structure, check for
|
||||
* incompatibilites between the subdevices.
|
||||
* incompatibilities between the subdevices.
|
||||
*/
|
||||
concat->mtd.type = subdev[0]->type;
|
||||
concat->mtd.flags = subdev[0]->flags;
|
||||
|
@ -362,7 +362,7 @@ int add_mtd_device(struct mtd_info *mtd)
|
||||
MTD_DEVT(i) + 1,
|
||||
NULL, "mtd%dro", i);
|
||||
|
||||
DEBUG(0, "mtd: Giving out device %d to %s\n", i, mtd->name);
|
||||
pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name);
|
||||
/* No need to get a refcount on the module containing
|
||||
the notifier, since we hold the mtd_table_mutex */
|
||||
list_for_each_entry(not, &mtd_notifiers, list)
|
||||
@ -429,27 +429,63 @@ out_error:
|
||||
}
|
||||
|
||||
/**
|
||||
* mtd_device_register - register an MTD device.
|
||||
* mtd_device_parse_register - parse partitions and register an MTD device.
|
||||
*
|
||||
* @master: the MTD device to register
|
||||
* @parts: the partitions to register - only valid if nr_parts > 0
|
||||
* @nr_parts: the number of partitions in parts. If zero then the full MTD
|
||||
* device is registered
|
||||
* @mtd: the MTD device to register
|
||||
* @types: the list of MTD partition probes to try, see
|
||||
* 'parse_mtd_partitions()' for more information
|
||||
* @parser_data: MTD partition parser-specific data
|
||||
* @parts: fallback partition information to register, if parsing fails;
|
||||
* only valid if %nr_parts > %0
|
||||
* @nr_parts: the number of partitions in parts, if zero then the full
|
||||
* MTD device is registered if no partition info is found
|
||||
*
|
||||
* Register an MTD device with the system and optionally, a number of
|
||||
* partitions. If nr_parts is 0 then the whole device is registered, otherwise
|
||||
* only the partitions are registered. To register both the full device *and*
|
||||
* the partitions, call mtd_device_register() twice, once with nr_parts == 0
|
||||
* and once equal to the number of partitions.
|
||||
* This function aggregates MTD partitions parsing (done by
|
||||
* 'parse_mtd_partitions()') and MTD device and partitions registering. It
|
||||
* basically follows the most common pattern found in many MTD drivers:
|
||||
*
|
||||
* * It first tries to probe partitions on MTD device @mtd using parsers
|
||||
* specified in @types (if @types is %NULL, then the default list of parsers
|
||||
* is used, see 'parse_mtd_partitions()' for more information). If none are
|
||||
* found this functions tries to fallback to information specified in
|
||||
* @parts/@nr_parts.
|
||||
* * If any partitioning info was found, this function registers the found
|
||||
* partitions.
|
||||
* * If no partitions were found this function just registers the MTD device
|
||||
* @mtd and exits.
|
||||
*
|
||||
* Returns zero in case of success and a negative error code in case of failure.
|
||||
*/
|
||||
int mtd_device_register(struct mtd_info *master,
|
||||
const struct mtd_partition *parts,
|
||||
int nr_parts)
|
||||
int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
|
||||
struct mtd_part_parser_data *parser_data,
|
||||
const struct mtd_partition *parts,
|
||||
int nr_parts)
|
||||
{
|
||||
return parts ? add_mtd_partitions(master, parts, nr_parts) :
|
||||
add_mtd_device(master);
|
||||
int err;
|
||||
struct mtd_partition *real_parts;
|
||||
|
||||
err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
|
||||
if (err <= 0 && nr_parts && parts) {
|
||||
real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
|
||||
GFP_KERNEL);
|
||||
if (!real_parts)
|
||||
err = -ENOMEM;
|
||||
else
|
||||
err = nr_parts;
|
||||
}
|
||||
|
||||
if (err > 0) {
|
||||
err = add_mtd_partitions(mtd, real_parts, err);
|
||||
kfree(real_parts);
|
||||
} else if (err == 0) {
|
||||
err = add_mtd_device(mtd);
|
||||
if (err == 1)
|
||||
err = -ENODEV;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mtd_device_register);
|
||||
EXPORT_SYMBOL_GPL(mtd_device_parse_register);
|
||||
|
||||
/**
|
||||
* mtd_device_unregister - unregister an existing MTD device.
|
||||
|
@ -15,6 +15,9 @@ extern int del_mtd_device(struct mtd_info *mtd);
|
||||
extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *,
|
||||
int);
|
||||
extern int del_mtd_partitions(struct mtd_info *);
|
||||
extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
|
||||
struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data);
|
||||
|
||||
#define mtd_for_each_device(mtd) \
|
||||
for ((mtd) = __mtd_next_device(0); \
|
||||
|
@ -258,7 +258,7 @@ static void find_next_position(struct mtdoops_context *cxt)
|
||||
ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE,
|
||||
&retlen, (u_char *) &count[0]);
|
||||
if (retlen != MTDOOPS_HEADER_SIZE ||
|
||||
(ret < 0 && ret != -EUCLEAN)) {
|
||||
(ret < 0 && !mtd_is_bitflip(ret))) {
|
||||
printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n",
|
||||
page * record_size, retlen,
|
||||
MTDOOPS_HEADER_SIZE, ret);
|
||||
|
@ -73,9 +73,9 @@ static int part_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
res = part->master->read(part->master, from + part->offset,
|
||||
len, retlen, buf);
|
||||
if (unlikely(res)) {
|
||||
if (res == -EUCLEAN)
|
||||
if (mtd_is_bitflip(res))
|
||||
mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected;
|
||||
if (res == -EBADMSG)
|
||||
if (mtd_is_eccerr(res))
|
||||
mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed;
|
||||
}
|
||||
return res;
|
||||
@ -130,7 +130,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
|
||||
if (ops->oobbuf) {
|
||||
size_t len, pages;
|
||||
|
||||
if (ops->mode == MTD_OOB_AUTO)
|
||||
if (ops->mode == MTD_OPS_AUTO_OOB)
|
||||
len = mtd->oobavail;
|
||||
else
|
||||
len = mtd->oobsize;
|
||||
@ -142,9 +142,9 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
|
||||
|
||||
res = part->master->read_oob(part->master, from + part->offset, ops);
|
||||
if (unlikely(res)) {
|
||||
if (res == -EUCLEAN)
|
||||
if (mtd_is_bitflip(res))
|
||||
mtd->ecc_stats.corrected++;
|
||||
if (res == -EBADMSG)
|
||||
if (mtd_is_eccerr(res))
|
||||
mtd->ecc_stats.failed++;
|
||||
}
|
||||
return res;
|
||||
@ -479,6 +479,19 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
|
||||
(unsigned long long)cur_offset, (unsigned long long)slave->offset);
|
||||
}
|
||||
}
|
||||
if (slave->offset == MTDPART_OFS_RETAIN) {
|
||||
slave->offset = cur_offset;
|
||||
if (master->size - slave->offset >= slave->mtd.size) {
|
||||
slave->mtd.size = master->size - slave->offset
|
||||
- slave->mtd.size;
|
||||
} else {
|
||||
printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
|
||||
part->name, master->size - slave->offset,
|
||||
slave->mtd.size);
|
||||
/* register to preserve ordering */
|
||||
goto out_register;
|
||||
}
|
||||
}
|
||||
if (slave->mtd.size == MTDPART_SIZ_FULL)
|
||||
slave->mtd.size = master->size - slave->offset;
|
||||
|
||||
@ -693,6 +706,8 @@ static struct mtd_part_parser *get_partition_parser(const char *name)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define put_partition_parser(p) do { module_put((p)->owner); } while (0)
|
||||
|
||||
int register_mtd_parser(struct mtd_part_parser *p)
|
||||
{
|
||||
spin_lock(&part_parser_lock);
|
||||
@ -712,19 +727,51 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(deregister_mtd_parser);
|
||||
|
||||
/*
|
||||
* Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
|
||||
* are changing this array!
|
||||
*/
|
||||
static const char *default_mtd_part_types[] = {
|
||||
"cmdlinepart",
|
||||
"ofpart",
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
* parse_mtd_partitions - parse MTD partitions
|
||||
* @master: the master partition (describes whole MTD device)
|
||||
* @types: names of partition parsers to try or %NULL
|
||||
* @pparts: array of partitions found is returned here
|
||||
* @data: MTD partition parser-specific data
|
||||
*
|
||||
* This function tries to find partition on MTD device @master. It uses MTD
|
||||
* partition parsers, specified in @types. However, if @types is %NULL, then
|
||||
* the default list of parsers is used. The default list contains only the
|
||||
* "cmdlinepart" and "ofpart" parsers ATM.
|
||||
*
|
||||
* This function may return:
|
||||
* o a negative error code in case of failure
|
||||
* o zero if no partitions were found
|
||||
* o a positive number of found partitions, in which case on exit @pparts will
|
||||
* point to an array containing this number of &struct mtd_info objects.
|
||||
*/
|
||||
int parse_mtd_partitions(struct mtd_info *master, const char **types,
|
||||
struct mtd_partition **pparts, unsigned long origin)
|
||||
struct mtd_partition **pparts,
|
||||
struct mtd_part_parser_data *data)
|
||||
{
|
||||
struct mtd_part_parser *parser;
|
||||
int ret = 0;
|
||||
|
||||
if (!types)
|
||||
types = default_mtd_part_types;
|
||||
|
||||
for ( ; ret <= 0 && *types; types++) {
|
||||
parser = get_partition_parser(*types);
|
||||
if (!parser && !request_module("%s", *types))
|
||||
parser = get_partition_parser(*types);
|
||||
if (!parser)
|
||||
continue;
|
||||
ret = (*parser->parse_fn)(master, pparts, origin);
|
||||
ret = (*parser->parse_fn)(master, pparts, data);
|
||||
if (ret > 0) {
|
||||
printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
|
||||
ret, parser->name, master->name);
|
||||
@ -733,7 +780,6 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(parse_mtd_partitions);
|
||||
|
||||
int mtd_is_partition(struct mtd_info *mtd)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user