瀏覽代碼

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.
Linus Torvalds 13 年之前
父節點
當前提交
e0d65113a7
共有 100 個文件被更改,包括 2139 次插入1641 次删除
  1. 1 18
      Documentation/DocBook/mtdnand.tmpl
  2. 14 0
      Documentation/devicetree/bindings/mtd/atmel-dataflash.txt
  3. 2 7
      arch/arm/mach-at91/board-afeb-9260v1.c
  4. 2 7
      arch/arm/mach-at91/board-cam60.c
  5. 2 7
      arch/arm/mach-at91/board-cap9adk.c
  6. 2 7
      arch/arm/mach-at91/board-kb9202.c
  7. 2 7
      arch/arm/mach-at91/board-neocore926.c
  8. 2 7
      arch/arm/mach-at91/board-qil-a9260.c
  9. 2 7
      arch/arm/mach-at91/board-rm9200dk.c
  10. 2 7
      arch/arm/mach-at91/board-sam9-l9260.c
  11. 2 7
      arch/arm/mach-at91/board-sam9260ek.c
  12. 2 7
      arch/arm/mach-at91/board-sam9261ek.c
  13. 2 7
      arch/arm/mach-at91/board-sam9263ek.c
  14. 2 7
      arch/arm/mach-at91/board-sam9g20ek.c
  15. 2 7
      arch/arm/mach-at91/board-sam9m10g45ek.c
  16. 2 7
      arch/arm/mach-at91/board-sam9rlek.c
  17. 2 8
      arch/arm/mach-at91/board-snapper9260.c
  18. 2 7
      arch/arm/mach-at91/board-usb-a926x.c
  19. 2 7
      arch/arm/mach-at91/board-yl-9200.c
  20. 2 1
      arch/arm/mach-at91/include/mach/board.h
  21. 1 1
      arch/arm/mach-davinci/board-da830-evm.c
  22. 1 1
      arch/arm/mach-davinci/board-da850-evm.c
  23. 1 1
      arch/arm/mach-davinci/board-dm355-evm.c
  24. 1 1
      arch/arm/mach-davinci/board-dm355-leopard.c
  25. 1 1
      arch/arm/mach-davinci/board-dm365-evm.c
  26. 1 1
      arch/arm/mach-davinci/board-dm644x-evm.c
  27. 2 1
      arch/arm/mach-davinci/board-mityomapl138.c
  28. 1 1
      arch/arm/mach-davinci/board-neuros-osd2.c
  29. 1 1
      arch/arm/mach-davinci/board-tnetv107x-evm.c
  30. 3 1
      arch/arm/mach-davinci/include/mach/nand.h
  31. 5 18
      arch/arm/mach-ep93xx/ts72xx.c
  32. 3 2
      arch/arm/mach-mmp/aspenite.c
  33. 1 1
      arch/arm/mach-orion5x/ts78xx-setup.c
  34. 3 2
      arch/arm/mach-pxa/cm-x300.c
  35. 3 2
      arch/arm/mach-pxa/colibri-pxa3xx.c
  36. 3 2
      arch/arm/mach-pxa/littleton.c
  37. 5 4
      arch/arm/mach-pxa/mxm8x10.c
  38. 3 2
      arch/arm/mach-pxa/raumfeld.c
  39. 3 2
      arch/arm/mach-pxa/zylonite.c
  40. 18 2
      arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
  41. 2 6
      arch/avr32/boards/atngw100/setup.c
  42. 2 7
      arch/avr32/boards/atstk1000/atstk1002.c
  43. 2 1
      arch/avr32/mach-at32ap/include/mach/board.h
  44. 1 1
      arch/cris/arch-v32/drivers/mach-a3/nandflash.c
  45. 1 1
      arch/cris/arch-v32/drivers/mach-fs/nandflash.c
  46. 6 15
      drivers/mtd/Kconfig
  47. 1 1
      drivers/mtd/Makefile
  48. 2 2
      drivers/mtd/afs.c
  49. 1 1
      drivers/mtd/ar7part.c
  50. 13 18
      drivers/mtd/chips/cfi_cmdset_0002.c
  51. 1 2
      drivers/mtd/chips/fwh_lock.h
  52. 13 21
      drivers/mtd/chips/jedec_probe.c
  53. 2 5
      drivers/mtd/cmdlinepart.c
  54. 11 2
      drivers/mtd/devices/Kconfig
  55. 3 0
      drivers/mtd/devices/Makefile
  56. 7 10
      drivers/mtd/devices/doc2000.c
  57. 5 6
      drivers/mtd/devices/doc2001.c
  58. 5 6
      drivers/mtd/devices/doc2001plus.c
  59. 1 1
      drivers/mtd/devices/docecc.c
  60. 1114 0
      drivers/mtd/devices/docg3.c
  61. 297 0
      drivers/mtd/devices/docg3.h
  62. 0 5
      drivers/mtd/devices/docprobe.c
  63. 1 17
      drivers/mtd/devices/lart.c
  64. 30 62
      drivers/mtd/devices/m25p80.c
  65. 42 49
      drivers/mtd/devices/mtd_dataflash.c
  66. 5 37
      drivers/mtd/devices/sst25l.c
  67. 20 20
      drivers/mtd/ftl.c
  68. 32 37
      drivers/mtd/inftlcore.c
  69. 50 66
      drivers/mtd/inftlmount.c
  70. 0 26
      drivers/mtd/maps/Kconfig
  71. 0 2
      drivers/mtd/maps/Makefile
  72. 2 14
      drivers/mtd/maps/bfin-async-flash.c
  73. 0 341
      drivers/mtd/maps/ceiva.c
  74. 1 8
      drivers/mtd/maps/dc21285.c
  75. 0 134
      drivers/mtd/maps/edb7312.c
  76. 2 14
      drivers/mtd/maps/gpio-addr-flash.c
  77. 2 21
      drivers/mtd/maps/h720x-flash.c
  78. 4 24
      drivers/mtd/maps/impa7.c
  79. 1 6
      drivers/mtd/maps/intel_vr_nor.c
  80. 1 10
      drivers/mtd/maps/ixp2000.c
  81. 4 25
      drivers/mtd/maps/ixp4xx.c
  82. 2 15
      drivers/mtd/maps/lantiq-flash.c
  83. 2 22
      drivers/mtd/maps/latch-addr-flash.c
  84. 52 72
      drivers/mtd/maps/pcmciamtd.c
  85. 2 36
      drivers/mtd/maps/physmap.c
  86. 7 73
      drivers/mtd/maps/physmap_of.c
  87. 2 21
      drivers/mtd/maps/plat-ram.c
  88. 1 19
      drivers/mtd/maps/pxa2xx-flash.c
  89. 4 20
      drivers/mtd/maps/rbtx4939-flash.c
  90. 3 27
      drivers/mtd/maps/sa1100-flash.c
  91. 7 23
      drivers/mtd/maps/solutionengine.c
  92. 13 20
      drivers/mtd/maps/wr_sbc82xx_flash.c
  93. 2 0
      drivers/mtd/mtd_blkdevs.c
  94. 8 10
      drivers/mtd/mtdblock.c
  95. 120 42
      drivers/mtd/mtdchar.c
  96. 5 5
      drivers/mtd/mtdconcat.c
  97. 53 17
      drivers/mtd/mtdcore.c
  98. 3 0
      drivers/mtd/mtdcore.h
  99. 1 1
      drivers/mtd/mtdoops.c
  100. 54 8
      drivers/mtd/mtdpart.c

+ 1 - 18
Documentation/DocBook/mtdnand.tmpl

@@ -572,7 +572,7 @@ static void board_select_chip (struct mtd_info *mtd, int chip)
 			</para>
 			</para>
 			<para>
 			<para>
 				The simplest way to activate the FLASH based bad block table support 
 				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
 				the nand chip structure before calling nand_scan(). For AG-AND
 				chips is this done by default.
 				chips is this done by default.
 				This activates the default FLASH based bad block table functionality 
 				This activates the default FLASH based bad block table functionality 
@@ -773,20 +773,6 @@ struct nand_oobinfo {
 				done according to the default builtin scheme.
 				done according to the default builtin scheme.
 			</para>
 			</para>
 		</sect2>
 		</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>	
 	<sect1 id="Spare_area_autoplacement_default">
 	<sect1 id="Spare_area_autoplacement_default">
 		<title>Spare area autoplacement default schemes</title>
 		<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
 		These constants are defined in nand.h. They are ored together to describe
 		the functionality.
 		the functionality.
      		<programlisting>
      		<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 
 /* 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 
  * 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 */
  * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */

+ 14 - 0
Documentation/devicetree/bindings/mtd/atmel-dataflash.txt

@@ -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>;
+};

+ 2 - 7
arch/arm/mach-at91/board-afeb-9260v1.c

@@ -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 = {
 static struct atmel_nand_data __initdata afeb9260_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC13,
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
 	.enable_pin	= AT91_PIN_PC14,
-	.partition_info	= nand_partitions,
 	.bus_width_16	= 0,
 	.bus_width_16	= 0,
+	.parts		= afeb9260_nand_partition,
+	.num_parts	= ARRAY_SIZE(afeb9260_nand_partition),
 };
 };
 
 
 
 

+ 2 - 7
arch/arm/mach-at91/board-cam60.c

@@ -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 = {
 static struct atmel_nand_data __initdata cam60_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 	// .det_pin	= ... not there
 	// .det_pin	= ... not there
 	.rdy_pin	= AT91_PIN_PA9,
 	.rdy_pin	= AT91_PIN_PA9,
 	.enable_pin	= AT91_PIN_PA7,
 	.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 = {
 static struct sam9_smc_config __initdata cam60_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-cap9adk.c

@@ -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 = {
 static struct atmel_nand_data __initdata cap9adk_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 //	.det_pin	= ... not connected
 //	.rdy_pin	= ... not connected
 //	.rdy_pin	= ... not connected
 	.enable_pin	= AT91_PIN_PD15,
 	.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 = {
 static struct sam9_smc_config __initdata cap9adk_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-kb9202.c

@@ -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 = {
 static struct atmel_nand_data __initdata kb9202_nand_data = {
 	.ale		= 22,
 	.ale		= 22,
 	.cle		= 21,
 	.cle		= 21,
 	// .det_pin	= ... not there
 	// .det_pin	= ... not there
 	.rdy_pin	= AT91_PIN_PC29,
 	.rdy_pin	= AT91_PIN_PC29,
 	.enable_pin	= AT91_PIN_PC28,
 	.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)
 static void __init kb9202_board_init(void)

+ 2 - 7
arch/arm/mach-at91/board-neocore926.c

@@ -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 = {
 static struct atmel_nand_data __initdata neocore926_nand_data = {
 	.ale			= 21,
 	.ale			= 21,
 	.cle			= 22,
 	.cle			= 22,
 	.rdy_pin		= AT91_PIN_PB19,
 	.rdy_pin		= AT91_PIN_PB19,
 	.rdy_pin_active_low	= 1,
 	.rdy_pin_active_low	= 1,
 	.enable_pin		= AT91_PIN_PD15,
 	.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 = {
 static struct sam9_smc_config __initdata neocore926_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-qil-a9260.c

@@ -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 = {
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC13,
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
 	.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 = {
 static struct sam9_smc_config __initdata ek_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-rm9200dk.c

@@ -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 = {
 static struct atmel_nand_data __initdata dk_nand_data = {
 	.ale		= 22,
 	.ale		= 22,
 	.cle		= 21,
 	.cle		= 21,
 	.det_pin	= AT91_PIN_PB1,
 	.det_pin	= AT91_PIN_PB1,
 	.rdy_pin	= AT91_PIN_PC2,
 	.rdy_pin	= AT91_PIN_PC2,
 	// .enable_pin	= ... not there
 	// .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
 #define DK_FLASH_BASE	AT91_CHIPSELECT_0

+ 2 - 7
arch/arm/mach-at91/board-sam9-l9260.c

@@ -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 = {
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC13,
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
 	.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 = {
 static struct sam9_smc_config __initdata ek_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-sam9260ek.c

@@ -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 = {
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC13,
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
 	.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 = {
 static struct sam9_smc_config __initdata ek_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-sam9261ek.c

@@ -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 = {
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 22,
 	.ale		= 22,
 	.cle		= 21,
 	.cle		= 21,
 //	.det_pin	= ... not connected
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC15,
 	.rdy_pin	= AT91_PIN_PC15,
 	.enable_pin	= AT91_PIN_PC14,
 	.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 = {
 static struct sam9_smc_config __initdata ek_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-sam9263ek.c

@@ -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 = {
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PA22,
 	.rdy_pin	= AT91_PIN_PA22,
 	.enable_pin	= AT91_PIN_PD15,
 	.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 = {
 static struct sam9_smc_config __initdata ek_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-sam9g20ek.c

@@ -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 */
 /* det_pin is not connected */
 static struct atmel_nand_data __initdata ek_nand_data = {
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC13,
 	.rdy_pin	= AT91_PIN_PC13,
 	.enable_pin	= AT91_PIN_PC14,
 	.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 = {
 static struct sam9_smc_config __initdata ek_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-sam9m10g45ek.c

@@ -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 */
 /* det_pin is not connected */
 static struct atmel_nand_data __initdata ek_nand_data = {
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC8,
 	.rdy_pin	= AT91_PIN_PC8,
 	.enable_pin	= AT91_PIN_PC14,
 	.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 = {
 static struct sam9_smc_config __initdata ek_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-sam9rlek.c

@@ -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 = {
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PD17,
 	.rdy_pin	= AT91_PIN_PD17,
 	.enable_pin	= AT91_PIN_PB6,
 	.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 = {
 static struct sam9_smc_config __initdata ek_nand_smc_config = {

+ 2 - 8
arch/arm/mach-at91/board-snapper9260.c

@@ -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 = {
 static struct atmel_nand_data __initdata snapper9260_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 	.rdy_pin	= AT91_PIN_PC13,
 	.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,
 	.bus_width_16	= 0,
 };
 };
 
 

+ 2 - 7
arch/arm/mach-at91/board-usb-a926x.c

@@ -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 = {
 static struct atmel_nand_data __initdata ek_nand_data = {
 	.ale		= 21,
 	.ale		= 21,
 	.cle		= 22,
 	.cle		= 22,
 //	.det_pin	= ... not connected
 //	.det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PA22,
 	.rdy_pin	= AT91_PIN_PA22,
 	.enable_pin	= AT91_PIN_PD15,
 	.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 = {
 static struct sam9_smc_config __initdata usb_a9260_nand_smc_config = {

+ 2 - 7
arch/arm/mach-at91/board-yl-9200.c

@@ -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 = {
 static struct atmel_nand_data __initdata yl9200_nand_data = {
 	.ale		= 6,
 	.ale		= 6,
 	.cle		= 7,
 	.cle		= 7,
 	// .det_pin	= ... not connected
 	// .det_pin	= ... not connected
 	.rdy_pin	= AT91_PIN_PC14,	/* R/!B (Sheet10) */
 	.rdy_pin	= AT91_PIN_PC14,	/* R/!B (Sheet10) */
 	.enable_pin	= AT91_PIN_PC15,	/* !CE  (Sheet10) */
 	.enable_pin	= AT91_PIN_PC15,	/* !CE  (Sheet10) */
-	.partition_info	= nand_partitions,
+	.parts		= yl9200_nand_partition,
+	.num_parts	= ARRAY_SIZE(yl9200_nand_partition),
 };
 };
 
 
 /*
 /*

+ 2 - 1
arch/arm/mach-at91/include/mach/board.h

@@ -117,7 +117,8 @@ struct atmel_nand_data {
 	u8		ale;		/* address line number connected to ALE */
 	u8		ale;		/* address line number connected to ALE */
 	u8		cle;		/* address line number connected to CLE */
 	u8		cle;		/* address line number connected to CLE */
 	u8		bus_width_16;	/* buswidth is 16 bit */
 	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);
 extern void __init at91_add_device_nand(struct atmel_nand_data *data);
 
 

+ 1 - 1
arch/arm/mach-davinci/board-da830-evm.c

@@ -377,7 +377,7 @@ static struct davinci_nand_pdata da830_evm_nand_pdata = {
 	.nr_parts	= ARRAY_SIZE(da830_evm_nand_partitions),
 	.nr_parts	= ARRAY_SIZE(da830_evm_nand_partitions),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_bits	= 4,
 	.ecc_bits	= 4,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.bbt_td		= &da830_evm_nand_bbt_main_descr,
 	.bbt_td		= &da830_evm_nand_bbt_main_descr,
 	.bbt_md		= &da830_evm_nand_bbt_mirror_descr,
 	.bbt_md		= &da830_evm_nand_bbt_mirror_descr,
 	.timing         = &da830_evm_nandflash_timing,
 	.timing         = &da830_evm_nandflash_timing,

+ 1 - 1
arch/arm/mach-davinci/board-da850-evm.c

@@ -256,7 +256,7 @@ static struct davinci_nand_pdata da850_evm_nandflash_data = {
 	.nr_parts	= ARRAY_SIZE(da850_evm_nandflash_partition),
 	.nr_parts	= ARRAY_SIZE(da850_evm_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_bits	= 4,
 	.ecc_bits	= 4,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.timing		= &da850_evm_nandflash_timing,
 	.timing		= &da850_evm_nandflash_timing,
 };
 };
 
 

+ 1 - 1
arch/arm/mach-davinci/board-dm355-evm.c

@@ -77,7 +77,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
 	.parts			= davinci_nand_partitions,
 	.parts			= davinci_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.ecc_mode		= NAND_ECC_HW,
 	.ecc_mode		= NAND_ECC_HW,
-	.options		= NAND_USE_FLASH_BBT,
+	.bbt_options		= NAND_BBT_USE_FLASH,
 	.ecc_bits		= 4,
 	.ecc_bits		= 4,
 };
 };
 
 

+ 1 - 1
arch/arm/mach-davinci/board-dm355-leopard.c

@@ -74,7 +74,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
 	.parts			= davinci_nand_partitions,
 	.parts			= davinci_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.ecc_mode		= NAND_ECC_HW_SYNDROME,
 	.ecc_mode		= NAND_ECC_HW_SYNDROME,
-	.options		= NAND_USE_FLASH_BBT,
+	.bbt_options		= NAND_BBT_USE_FLASH,
 };
 };
 
 
 static struct resource davinci_nand_resources[] = {
 static struct resource davinci_nand_resources[] = {

+ 1 - 1
arch/arm/mach-davinci/board-dm365-evm.c

@@ -139,7 +139,7 @@ static struct davinci_nand_pdata davinci_nand_data = {
 	.parts			= davinci_nand_partitions,
 	.parts			= davinci_nand_partitions,
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.nr_parts		= ARRAY_SIZE(davinci_nand_partitions),
 	.ecc_mode		= NAND_ECC_HW,
 	.ecc_mode		= NAND_ECC_HW,
-	.options		= NAND_USE_FLASH_BBT,
+	.bbt_options		= NAND_BBT_USE_FLASH,
 	.ecc_bits		= 4,
 	.ecc_bits		= 4,
 };
 };
 
 

+ 1 - 1
arch/arm/mach-davinci/board-dm644x-evm.c

@@ -151,7 +151,7 @@ static struct davinci_nand_pdata davinci_evm_nandflash_data = {
 	.parts		= davinci_evm_nandflash_partition,
 	.parts		= davinci_evm_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(davinci_evm_nandflash_partition),
 	.nr_parts	= ARRAY_SIZE(davinci_evm_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.timing		= &davinci_evm_nandflash_timing,
 	.timing		= &davinci_evm_nandflash_timing,
 };
 };
 
 

+ 2 - 1
arch/arm/mach-davinci/board-mityomapl138.c

@@ -396,7 +396,8 @@ static struct davinci_nand_pdata mityomapl138_nandflash_data = {
 	.parts		= mityomapl138_nandflash_partition,
 	.parts		= mityomapl138_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(mityomapl138_nandflash_partition),
 	.nr_parts	= ARRAY_SIZE(mityomapl138_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
 	.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 */
 	.ecc_bits	= 1, /* 4 bit mode is not supported with 16 bit NAND */
 };
 };
 
 

+ 1 - 1
arch/arm/mach-davinci/board-neuros-osd2.c

@@ -87,7 +87,7 @@ static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = {
 	.parts		= davinci_ntosd2_nandflash_partition,
 	.parts		= davinci_ntosd2_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
 	.nr_parts	= ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 };
 };
 
 
 static struct resource davinci_ntosd2_nandflash_resource[] = {
 static struct resource davinci_ntosd2_nandflash_resource[] = {

+ 1 - 1
arch/arm/mach-davinci/board-tnetv107x-evm.c

@@ -144,7 +144,7 @@ static struct davinci_nand_pdata nand_config = {
 	.parts		= nand_partitions,
 	.parts		= nand_partitions,
 	.nr_parts	= ARRAY_SIZE(nand_partitions),
 	.nr_parts	= ARRAY_SIZE(nand_partitions),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_mode	= NAND_ECC_HW,
-	.options	= NAND_USE_FLASH_BBT,
+	.bbt_options	= NAND_BBT_USE_FLASH,
 	.ecc_bits	= 1,
 	.ecc_bits	= 1,
 };
 };
 
 

+ 3 - 1
arch/arm/mach-davinci/include/mach/nand.h

@@ -74,8 +74,10 @@ struct davinci_nand_pdata {		/* platform_data */
 	nand_ecc_modes_t	ecc_mode;
 	nand_ecc_modes_t	ecc_mode;
 	u8			ecc_bits;
 	u8			ecc_bits;
 
 
-	/* e.g. NAND_BUSWIDTH_16 or NAND_USE_FLASH_BBT */
+	/* e.g. NAND_BUSWIDTH_16 */
 	unsigned		options;
 	unsigned		options;
+	/* e.g. NAND_BBT_USE_FLASH */
+	unsigned		bbt_options;
 
 
 	/* Main and mirror bbt descriptor overrides */
 	/* Main and mirror bbt descriptor overrides */
 	struct nand_bbt_descr	*bbt_td;
 	struct nand_bbt_descr	*bbt_td;

+ 5 - 18
arch/arm/mach-ep93xx/ts72xx.c

@@ -116,8 +116,9 @@ static struct mtd_partition ts72xx_nand_parts[] = {
 		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
 		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
 	}, {
 	}, {
 		.name		= "Linux",
 		.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",
 		.name		= "RedBoot",
 		.offset		= MTDPART_OFS_APPEND,
 		.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 = {
 static struct platform_nand_data ts72xx_nand_data = {
 	.chip = {
 	.chip = {
 		.nr_chips	= 1,
 		.nr_chips	= 1,
 		.chip_offset	= 0,
 		.chip_offset	= 0,
 		.chip_delay	= 15,
 		.chip_delay	= 15,
 		.part_probe_types = ts72xx_nand_part_probes,
 		.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 = {
 	.ctrl = {
 		.cmd_ctrl	= ts72xx_nand_hwcontrol,
 		.cmd_ctrl	= ts72xx_nand_hwcontrol,

+ 3 - 2
arch/arm/mach-mmp/aspenite.c

@@ -167,8 +167,9 @@ static struct mtd_partition aspenite_nand_partitions[] = {
 
 
 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
 static struct pxa3xx_nand_platform_data aspenite_nand_info = {
 	.enable_arbiter	= 1,
 	.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 = {
 static struct i2c_board_info aspenite_i2c_info[] __initdata = {

+ 1 - 1
arch/arm/mach-orion5x/ts78xx-setup.c

@@ -275,7 +275,7 @@ static struct platform_nand_data ts78xx_ts_nand_data = {
 		.partitions		= ts78xx_ts_nand_parts,
 		.partitions		= ts78xx_ts_nand_parts,
 		.nr_partitions		= ARRAY_SIZE(ts78xx_ts_nand_parts),
 		.nr_partitions		= ARRAY_SIZE(ts78xx_ts_nand_parts),
 		.chip_delay		= 15,
 		.chip_delay		= 15,
-		.options		= NAND_USE_FLASH_BBT,
+		.bbt_options		= NAND_BBT_USE_FLASH,
 	},
 	},
 	.ctrl	= {
 	.ctrl	= {
 		/*
 		/*

+ 3 - 2
arch/arm/mach-pxa/cm-x300.c

@@ -424,8 +424,9 @@ static struct mtd_partition cm_x300_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
 static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
 	.enable_arbiter	= 1,
 	.enable_arbiter	= 1,
 	.keep_config	= 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)
 static void __init cm_x300_init_nand(void)

+ 3 - 2
arch/arm/mach-pxa/colibri-pxa3xx.c

@@ -139,8 +139,9 @@ static struct mtd_partition colibri_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data colibri_nand_info = {
 static struct pxa3xx_nand_platform_data colibri_nand_info = {
 	.enable_arbiter	= 1,
 	.enable_arbiter	= 1,
 	.keep_config	= 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)
 void __init colibri_pxa3xx_init_nand(void)

+ 3 - 2
arch/arm/mach-pxa/littleton.c

@@ -325,8 +325,9 @@ static struct mtd_partition littleton_nand_partitions[] = {
 
 
 static struct pxa3xx_nand_platform_data littleton_nand_info = {
 static struct pxa3xx_nand_platform_data littleton_nand_info = {
 	.enable_arbiter	= 1,
 	.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)
 static void __init littleton_init_nand(void)

+ 5 - 4
arch/arm/mach-pxa/mxm8x10.c

@@ -389,10 +389,11 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = {
 };
 };
 
 
 static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = {
 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)
 static void __init mxm_8x10_nand_init(void)

+ 3 - 2
arch/arm/mach-pxa/raumfeld.c

@@ -346,8 +346,9 @@ static struct mtd_partition raumfeld_nand_partitions[] = {
 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
 static struct pxa3xx_nand_platform_data raumfeld_nand_info = {
 	.enable_arbiter	= 1,
 	.enable_arbiter	= 1,
 	.keep_config	= 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),
 };
 };
 
 
 /**
 /**

+ 3 - 2
arch/arm/mach-pxa/zylonite.c

@@ -366,8 +366,9 @@ static struct mtd_partition zylonite_nand_partitions[] = {
 
 
 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
 static struct pxa3xx_nand_platform_data zylonite_nand_info = {
 	.enable_arbiter	= 1,
 	.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)
 static void __init zylonite_init_nand(void)

+ 18 - 2
arch/arm/plat-pxa/include/plat/pxa3xx_nand.h

@@ -41,6 +41,19 @@ struct pxa3xx_nand_flash {
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 	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 {
 struct pxa3xx_nand_platform_data {
 
 
 	/* the data flash bus is shared between the Static Memory
 	/* 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 */
 	/* allow platform code to keep OBM/bootloader defined NFC config */
 	int	keep_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;
 	const struct pxa3xx_nand_flash * 	flash;
 	size_t					num_flash;
 	size_t					num_flash;

+ 2 - 6
arch/avr32/boards/atngw100/setup.c

@@ -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 = {
 static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
 	.cle		= 21,
 	.cle		= 21,
@@ -102,7 +97,8 @@ static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
 	.rdy_pin	= GPIO_PIN_PB(28),
 	.rdy_pin	= GPIO_PIN_PB(28),
 	.enable_pin	= GPIO_PIN_PE(23),
 	.enable_pin	= GPIO_PIN_PE(23),
 	.bus_width_16	= true,
 	.bus_width_16	= true,
-	.partition_info	= nand_part_info,
+	.parts		= nand_partitions,
+	.num_parts	= ARRAY_SIZE(nand_partitions),
 };
 };
 #endif
 #endif
 
 

+ 2 - 7
arch/avr32/boards/atstk1000/atstk1002.c

@@ -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 = {
 static struct atmel_nand_data atstk1006_nand_data __initdata = {
 	.cle		= 21,
 	.cle		= 21,
 	.ale		= 22,
 	.ale		= 22,
 	.rdy_pin	= GPIO_PIN_PB(30),
 	.rdy_pin	= GPIO_PIN_PB(30),
 	.enable_pin	= GPIO_PIN_PB(29),
 	.enable_pin	= GPIO_PIN_PB(29),
-	.partition_info	= nand_part_info,
+	.parts		= nand_partitions,
+	.num_parts	= ARRAY_SIZE(num_partitions),
 };
 };
 #endif
 #endif
 
 

+ 2 - 1
arch/avr32/mach-at32ap/include/mach/board.h

@@ -128,7 +128,8 @@ struct atmel_nand_data {
 	u8	ale;		/* address line number connected to ALE */
 	u8	ale;		/* address line number connected to ALE */
 	u8	cle;		/* address line number connected to CLE */
 	u8	cle;		/* address line number connected to CLE */
 	u8	bus_width_16;	/* buswidth is 16 bit */
 	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 *
 struct platform_device *
 at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
 at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);

+ 1 - 1
arch/cris/arch-v32/drivers/mach-a3/nandflash.c

@@ -163,7 +163,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
 	this->ecc.mode = NAND_ECC_SOFT;
 	this->ecc.mode = NAND_ECC_SOFT;
 
 
 	/* Enable the following for a flash based bad block table */
 	/* 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 */
 	/* Scan to find existence of the device */
 	if (nand_scan(crisv32_mtd, 1)) {
 	if (nand_scan(crisv32_mtd, 1)) {

+ 1 - 1
arch/cris/arch-v32/drivers/mach-fs/nandflash.c

@@ -154,7 +154,7 @@ struct mtd_info *__init crisv32_nand_flash_probe(void)
 	this->ecc.mode = NAND_ECC_SOFT;
 	this->ecc.mode = NAND_ECC_SOFT;
 
 
 	/* Enable the following for a flash based bad block table */
 	/* 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 */
 	/* Scan to find existence of the device */
 	if (nand_scan(crisv32_mtd, 1)) {
 	if (nand_scan(crisv32_mtd, 1)) {

+ 6 - 15
drivers/mtd/Kconfig

@@ -12,27 +12,17 @@ menuconfig MTD
 
 
 if 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
 config MTD_TESTS
-	tristate "MTD tests support"
+	tristate "MTD tests support (DANGEROUS)"
 	depends on m
 	depends on m
 	help
 	help
 	  This option includes various MTD tests into compilation. The tests
 	  This option includes various MTD tests into compilation. The tests
 	  should normally be compiled as kernel modules. The modules perform
 	  should normally be compiled as kernel modules. The modules perform
 	  various checks and verifications when loaded.
 	  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
 config MTD_REDBOOT_PARTS
 	tristate "RedBoot partition table parsing"
 	tristate "RedBoot partition table parsing"
 	---help---
 	---help---
@@ -137,7 +127,8 @@ config MTD_AFS_PARTS
 	  'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example.
 	  'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example.
 
 
 config MTD_OF_PARTS
 config MTD_OF_PARTS
-	def_bool y
+	tristate "OpenFirmware partitioning information support"
+	default Y
 	depends on OF
 	depends on OF
 	help
 	help
 	  This provides a partition parsing function which derives
 	  This provides a partition parsing function which derives

+ 1 - 1
drivers/mtd/Makefile

@@ -5,8 +5,8 @@
 # Core functionality.
 # Core functionality.
 obj-$(CONFIG_MTD)		+= mtd.o
 obj-$(CONFIG_MTD)		+= mtd.o
 mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o mtdpart.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_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o

+ 2 - 2
drivers/mtd/afs.c

@@ -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,
 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;
 	struct mtd_partition *parts;
 	u_int mask, off, idx, sz;
 	u_int mask, off, idx, sz;

+ 1 - 1
drivers/mtd/ar7part.c

@@ -47,7 +47,7 @@ struct ar7_bin_rec {
 
 
 static int create_mtd_partitions(struct mtd_info *master,
 static int create_mtd_partitions(struct mtd_info *master,
 				 struct mtd_partition **pparts,
 				 struct mtd_partition **pparts,
-				 unsigned long origin)
+				 struct mtd_part_parser_data *data)
 {
 {
 	struct ar7_bin_rec header;
 	struct ar7_bin_rec header;
 	unsigned int offset;
 	unsigned int offset;

+ 13 - 18
drivers/mtd/chips/cfi_cmdset_0002.c

@@ -145,8 +145,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
 	if (((major << 8) | minor) < 0x3131) {
 	if (((major << 8) | minor) < 0x3131) {
 		/* CFI version 1.0 => don't trust bootloc */
 		/* 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);
 			map->name, cfi->mfr, cfi->id);
 
 
 		/* AFAICS all 29LV400 with a bottom boot block have a device 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.
 			 * the 8-bit device ID.
 			 */
 			 */
 			(cfi->mfr == CFI_MFR_MACRONIX)) {
 			(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);
 				" detected\n", map->name);
 			extp->TopBottom = 2;	/* bottom boot */
 			extp->TopBottom = 2;	/* bottom boot */
 		} else
 		} else
@@ -178,8 +176,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd)
 			extp->TopBottom = 2;	/* bottom boot */
 			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,
 			" deduced %s from Device ID\n", map->name, major, minor,
 			extp->TopBottom == 2 ? "bottom" : "top");
 			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 map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 	struct cfi_private *cfi = map->fldrv_priv;
 	if (cfi->cfiq->BufWriteTimeoutTyp) {
 	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;
 		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->writesize = 1;
 	mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
 	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;
 	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;
 		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] );
 	       __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);
 	oldd = map_read(map, adr);
 	if (map_word_equal(map, oldd, datum)) {
 	if (map_word_equal(map, oldd, datum)) {
-		DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n",
+		pr_debug("MTD %s(): NOP\n",
 		       __func__);
 		       __func__);
 		goto op_done;
 		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);
 	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] );
 	       __func__, adr, datum.x[0] );
 
 
 	XIP_INVAL_CACHED_RANGE(map, adr, len);
 	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;
 		return ret;
 	}
 	}
 
 
-	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
+	pr_debug("MTD %s(): ERASE 0x%.8lx\n",
 	       __func__, chip->start );
 	       __func__, chip->start );
 
 
 	XIP_INVAL_CACHED_RANGE(map, adr, map->size);
 	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;
 		return ret;
 	}
 	}
 
 
-	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
+	pr_debug("MTD %s(): ERASE 0x%.8lx\n",
 	       __func__, adr );
 	       __func__, adr );
 
 
 	XIP_INVAL_CACHED_RANGE(map, adr, len);
 	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;
 		goto out_unlock;
 	chip->state = FL_LOCKING;
 	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_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
 			 cfi->device_type, NULL);
 			 cfi->device_type, NULL);
@@ -1837,8 +1833,7 @@ static int do_atmel_unlock(struct map_info *map, struct flchip *chip,
 		goto out_unlock;
 		goto out_unlock;
 	chip->state = FL_UNLOCKING;
 	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_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi,
 			 cfi->device_type, NULL);
 			 cfi->device_type, NULL);

+ 1 - 2
drivers/mtd/chips/fwh_lock.h

@@ -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 */
 	/* Refuse the operation if the we cannot look behind the chip */
 	if (chip->start < 0x400000) {
 	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 );
 			__func__, chip->start );
 		return -EIO;
 		return -EIO;
 	}
 	}

+ 13 - 21
drivers/mtd/chips/jedec_probe.c

@@ -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
 	 * (oh and incidentaly the jedec spec - 3.5.3.3) the reset
 	 * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
 	 * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
 	 * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
 	 * 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 */
 	 * the F0 is written to */
 	if (cfi->addr_unlock1) {
 	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->addr_unlock1,cfi->addr_unlock2);
 		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
 		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);
 		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;
 	uint8_t uaddr;
 
 
 	if (!(jedec_table[index].devtypes & cfi->device_type)) {
 	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));
 		      jedec_table[index].name, 4 * (1<<cfi->device_type));
 		return 0;
 		return 0;
 	}
 	}
@@ -2021,7 +2020,7 @@ static inline int jedec_match( uint32_t base,
 		 * there aren't.
 		 * there aren't.
 		 */
 		 */
 		if (finfo->dev_id > 0xff) {
 		if (finfo->dev_id > 0xff) {
-			DEBUG( MTD_DEBUG_LEVEL3, "%s(): ID is not 8bit\n",
+			pr_debug("%s(): ID is not 8bit\n",
 			       __func__);
 			       __func__);
 			goto match_done;
 			goto match_done;
 		}
 		}
@@ -2045,12 +2044,10 @@ static inline int jedec_match( uint32_t base,
 	}
 	}
 
 
 	/* the part size must fit in the memory window */
 	/* 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) );
 	       __func__, base, 1 << finfo->dev_size, base + (1 << finfo->dev_size) );
 	if ( base + cfi_interleave(cfi) * ( 1 << finfo->dev_size ) > map->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,
 		       __func__, finfo->mfr_id, finfo->dev_id,
 		       1 << finfo->dev_size );
 		       1 << finfo->dev_size );
 		goto match_done;
 		goto match_done;
@@ -2061,13 +2058,12 @@ static inline int jedec_match( uint32_t base,
 
 
 	uaddr = finfo->uaddr;
 	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 );
 	       __func__, cfi->addr_unlock1, cfi->addr_unlock2 );
 	if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
 	if ( MTD_UADDR_UNNECESSARY != uaddr && MTD_UADDR_DONT_CARE != uaddr
 	     && ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 ||
 	     && ( unlock_addrs[uaddr].addr1 / cfi->device_type != cfi->addr_unlock1 ||
 		  unlock_addrs[uaddr].addr2 / cfi->device_type != cfi->addr_unlock2 ) ) {
 		  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__,
 			__func__,
 			unlock_addrs[uaddr].addr1,
 			unlock_addrs[uaddr].addr1,
 			unlock_addrs[uaddr].addr2);
 			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
 	 * FIXME - write a driver that takes all of the chip info as
 	 * module parameters, doesn't probe but forces a load.
 	 * 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__ );
 	       __func__ );
 	jedec_reset( base, map, cfi );
 	jedec_reset( base, map, cfi );
 	mfr = jedec_read_mfr( map, base, cfi );
 	mfr = jedec_read_mfr( map, base, cfi );
 	id = jedec_read_id( map, base, cfi );
 	id = jedec_read_id( map, base, cfi );
 	if ( mfr == cfi->mfr && id == cfi->id ) {
 	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",
 		       "You might need to manually specify JEDEC parameters.\n",
 			__func__, cfi->mfr, cfi->id );
 			__func__, cfi->mfr, cfi->id );
 		goto match_done;
 		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
 	 * Put the device back in ID mode - only need to do this if we
 	 * were truly frobbing a real device.
 	 * 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) {
 	if (cfi->addr_unlock1) {
 		cfi_send_gen_cmd(0xaa, cfi->addr_unlock1, base, map, cfi, cfi->device_type, NULL);
 		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);
 		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->mfr = jedec_read_mfr(map, base, cfi);
 		cfi->id = jedec_read_id(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);
 			cfi->mfr, cfi->id, cfi_interleave(cfi), cfi->device_type);
 		for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
 		for (i = 0; i < ARRAY_SIZE(jedec_table); i++) {
 			if ( jedec_match( base, map, cfi, &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,
 				       __func__, cfi->mfr, cfi->id,
 				       cfi->addr_unlock1, cfi->addr_unlock2 );
 				       cfi->addr_unlock1, cfi->addr_unlock2 );
 				if (!cfi_jedec_setup(map, cfi, i))
 				if (!cfi_jedec_setup(map, cfi, i))

+ 2 - 5
drivers/mtd/cmdlinepart.c

@@ -189,10 +189,7 @@ static struct mtd_partition * newpart(char *s,
 			     extra_mem_size;
 			     extra_mem_size;
 		parts = kzalloc(alloc_size, GFP_KERNEL);
 		parts = kzalloc(alloc_size, GFP_KERNEL);
 		if (!parts)
 		if (!parts)
-		{
-			printk(KERN_ERR ERRP "out of memory\n");
 			return NULL;
 			return NULL;
-		}
 		extra_mem = (unsigned char *)(parts + *num_parts);
 		extra_mem = (unsigned char *)(parts + *num_parts);
 	}
 	}
 	/* enter this partition (offset will be calculated later if it is zero at this point) */
 	/* 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.
  * the first one in the chain if a NULL mtd_id is passed in.
  */
  */
 static int parse_cmdline_partitions(struct mtd_info *master,
 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;
 	unsigned long offset;
 	int i;
 	int i;

+ 11 - 2
drivers/mtd/devices/Kconfig

@@ -249,6 +249,16 @@ config MTD_DOC2001PLUS
 	  under "NAND Flash Device Drivers" (currently that driver does not
 	  under "NAND Flash Device Drivers" (currently that driver does not
 	  support all Millennium Plus devices).
 	  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
 config MTD_DOCPROBE
 	tristate
 	tristate
 	select MTD_DOCECC
 	select MTD_DOCECC
@@ -268,8 +278,7 @@ config MTD_DOCPROBE_ADVANCED
 config MTD_DOCPROBE_ADDRESS
 config MTD_DOCPROBE_ADDRESS
 	hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED
 	hex "Physical address of DiskOnChip" if MTD_DOCPROBE_ADVANCED
 	depends on MTD_DOCPROBE
 	depends on MTD_DOCPROBE
-	default "0x0000" if MTD_DOCPROBE_ADVANCED
-	default "0" if !MTD_DOCPROBE_ADVANCED
+	default "0x0"
 	---help---
 	---help---
 	  By default, the probe for DiskOnChip devices will look for a
 	  By default, the probe for DiskOnChip devices will look for a
 	  DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.
 	  DiskOnChip at every multiple of 0x2000 between 0xC8000 and 0xEE000.

+ 3 - 0
drivers/mtd/devices/Makefile

@@ -5,6 +5,7 @@
 obj-$(CONFIG_MTD_DOC2000)	+= doc2000.o
 obj-$(CONFIG_MTD_DOC2000)	+= doc2000.o
 obj-$(CONFIG_MTD_DOC2001)	+= doc2001.o
 obj-$(CONFIG_MTD_DOC2001)	+= doc2001.o
 obj-$(CONFIG_MTD_DOC2001PLUS)	+= doc2001plus.o
 obj-$(CONFIG_MTD_DOC2001PLUS)	+= doc2001plus.o
+obj-$(CONFIG_MTD_DOCG3)		+= docg3.o
 obj-$(CONFIG_MTD_DOCPROBE)	+= docprobe.o
 obj-$(CONFIG_MTD_DOCPROBE)	+= docprobe.o
 obj-$(CONFIG_MTD_DOCECC)	+= docecc.o
 obj-$(CONFIG_MTD_DOCECC)	+= docecc.o
 obj-$(CONFIG_MTD_SLRAM)		+= slram.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_DATAFLASH)	+= mtd_dataflash.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
 obj-$(CONFIG_MTD_M25P80)	+= m25p80.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
 obj-$(CONFIG_MTD_SST25L)	+= sst25l.o
+
+CFLAGS_docg3.o			+= -I$(src)

+ 7 - 10
drivers/mtd/devices/doc2000.c

@@ -82,8 +82,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc)
 	void __iomem *docptr = doc->virtadr;
 	void __iomem *docptr = doc->virtadr;
 	unsigned long timeo = jiffies + (HZ * 10);
 	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 */
 	/* Out-of-line routine to wait for chip response */
 	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
 	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) {
@@ -92,7 +91,7 @@ static int _DoC_WaitReady(struct DiskOnChip *doc)
 		DoC_Delay(doc, 2);
 		DoC_Delay(doc, 2);
 
 
 		if (time_after(jiffies, timeo)) {
 		if (time_after(jiffies, timeo)) {
-			DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+			pr_debug("_DoC_WaitReady timed out.\n");
 			return -EIO;
 			return -EIO;
 		}
 		}
 		udelay(1);
 		udelay(1);
@@ -323,8 +322,7 @@ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip)
 
 
 	/* Reset the chip */
 	/* Reset the chip */
 	if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) {
 	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);
 		      floor, chip);
 		return 0;
 		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 */
 	/* Read the NAND chip ID: 1. Send ReadID command */
 	if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) {
 	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);
 		      floor, chip);
 		return 0;
 		return 0;
 	}
 	}
@@ -699,7 +696,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
 #ifdef ECC_DEBUG
 			printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
 			printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
 #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
 			   logic.  These syndrome will be all ZERO when there
 			   is no error */
 			   is no error */
 			for (i = 0; i < 6; i++) {
 			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;
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 	size_t len = ops->len;
 
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 
 	ofs += ops->ooboffs;
 	ofs += ops->ooboffs;
 
 
@@ -1094,7 +1091,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
 	struct DiskOnChip *this = mtd->priv;
 	struct DiskOnChip *this = mtd->priv;
 	int ret;
 	int ret;
 
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 
 	mutex_lock(&this->lock);
 	mutex_lock(&this->lock);
 	ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,
 	ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len,

+ 5 - 6
drivers/mtd/devices/doc2001.c

@@ -55,15 +55,14 @@ static int _DoC_WaitReady(void __iomem * docptr)
 {
 {
 	unsigned short c = 0xffff;
 	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 */
 	/* Out-of-line routine to wait for chip response */
 	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
 	while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c)
 		;
 		;
 
 
 	if (c == 0)
 	if (c == 0)
-		DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+		pr_debug("_DoC_WaitReady timed out.\n");
 
 
 	return (c == 0);
 	return (c == 0);
 }
 }
@@ -464,7 +463,7 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
 #ifdef ECC_DEBUG
 		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
 #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 */
 		   These syndrome will be all ZERO when there is no error */
 		for (i = 0; i < 6; i++) {
 		for (i = 0; i < 6; i++) {
 			syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + 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;
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 	size_t len = ops->len;
 
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 
 	ofs += ops->ooboffs;
 	ofs += ops->ooboffs;
 
 
@@ -690,7 +689,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
 	uint8_t *buf = ops->oobbuf;
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 	size_t len = ops->len;
 
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 
 	ofs += ops->ooboffs;
 	ofs += ops->ooboffs;
 
 

+ 5 - 6
drivers/mtd/devices/doc2001plus.c

@@ -61,15 +61,14 @@ static int _DoC_WaitReady(void __iomem * docptr)
 {
 {
 	unsigned int c = 0xffff;
 	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 */
 	/* 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)
 	while (((ReadDOC(docptr, Mplus_FlashControl) & CDSN_CTRL_FR_B_MASK) != CDSN_CTRL_FR_B_MASK) && --c)
 		;
 		;
 
 
 	if (c == 0)
 	if (c == 0)
-		DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n");
+		pr_debug("_DoC_WaitReady timed out.\n");
 
 
 	return (c == 0);
 	return (c == 0);
 }
 }
@@ -655,7 +654,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
 #ifdef ECC_DEBUG
 		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
 #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 */
 		   These syndrome will be all ZERO when there is no error */
 		for (i = 0; i < 6; i++)
 		for (i = 0; i < 6; i++)
 			syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + 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;
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 	size_t len = ops->len;
 
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 
 	ofs += ops->ooboffs;
 	ofs += ops->ooboffs;
 
 
@@ -920,7 +919,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
 	uint8_t *buf = ops->oobbuf;
 	uint8_t *buf = ops->oobbuf;
 	size_t len = ops->len;
 	size_t len = ops->len;
 
 
-	BUG_ON(ops->mode != MTD_OOB_PLACE);
+	BUG_ON(ops->mode != MTD_OPS_PLACE_OOB);
 
 
 	ofs += ops->ooboffs;
 	ofs += ops->ooboffs;
 
 

+ 1 - 1
drivers/mtd/devices/docecc.c

@@ -2,7 +2,7 @@
  * ECC algorithm for M-systems disk on chip. We use the excellent Reed
  * 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
  * 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
  * 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)
  * Author: Fabrice Bellard (fabrice.bellard@netgem.com)
  * Copyright (C) 2000 Netgem S.A.
  * Copyright (C) 2000 Netgem S.A.

+ 1114 - 0
drivers/mtd/devices/docg3.c

@@ -0,0 +1,1114 @@
+/*
+ * 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
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#define CREATE_TRACE_POINTS
+#include "docg3.h"
+
+/*
+ * This driver handles the DiskOnChip G3 flash memory.
+ *
+ * As no specification is available from M-Systems/Sandisk, this drivers lacks
+ * several functions available on the chip, as :
+ *  - block erase
+ *  - page write
+ *  - IPL write
+ *  - ECC fixing (lack of BCH algorith understanding)
+ *  - powerdown / powerup
+ *
+ * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and
+ * the driver assumes a 16bits data bus.
+ *
+ * DocG3 relies on 2 ECC algorithms, which are handled in hardware :
+ *  - a 1 byte Hamming code stored in the OOB for each page
+ *  - a 7 bytes BCH code stored in the OOB for each page
+ * The BCH part is only used for check purpose, no correction is available as
+ * some information is missing. What is known is that :
+ *  - BCH is in GF(2^14)
+ *  - BCH is over data of 520 bytes (512 page + 7 page_info bytes
+ *                                   + 1 hamming byte)
+ *  - BCH can correct up to 4 bits (t = 4)
+ *  - BCH syndroms are calculated in hardware, and checked in hardware as well
+ *
+ */
+
+static inline u8 doc_readb(struct docg3 *docg3, u16 reg)
+{
+	u8 val = readb(docg3->base + reg);
+
+	trace_docg3_io(0, 8, reg, (int)val);
+	return val;
+}
+
+static inline u16 doc_readw(struct docg3 *docg3, u16 reg)
+{
+	u16 val = readw(docg3->base + reg);
+
+	trace_docg3_io(0, 16, reg, (int)val);
+	return val;
+}
+
+static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg)
+{
+	writeb(val, docg3->base + reg);
+	trace_docg3_io(1, 16, reg, val);
+}
+
+static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg)
+{
+	writew(val, docg3->base + reg);
+	trace_docg3_io(1, 16, reg, val);
+}
+
+static inline void doc_flash_command(struct docg3 *docg3, u8 cmd)
+{
+	doc_writeb(docg3, cmd, DOC_FLASHCOMMAND);
+}
+
+static inline void doc_flash_sequence(struct docg3 *docg3, u8 seq)
+{
+	doc_writeb(docg3, seq, DOC_FLASHSEQUENCE);
+}
+
+static inline void doc_flash_address(struct docg3 *docg3, u8 addr)
+{
+	doc_writeb(docg3, addr, DOC_FLASHADDRESS);
+}
+
+static char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL };
+
+static int doc_register_readb(struct docg3 *docg3, int reg)
+{
+	u8 val;
+
+	doc_writew(docg3, reg, DOC_READADDRESS);
+	val = doc_readb(docg3, reg);
+	doc_vdbg("Read register %04x : %02x\n", reg, val);
+	return val;
+}
+
+static int doc_register_readw(struct docg3 *docg3, int reg)
+{
+	u16 val;
+
+	doc_writew(docg3, reg, DOC_READADDRESS);
+	val = doc_readw(docg3, reg);
+	doc_vdbg("Read register %04x : %04x\n", reg, val);
+	return val;
+}
+
+/**
+ * doc_delay - delay docg3 operations
+ * @docg3: the device
+ * @nbNOPs: the number of NOPs to issue
+ *
+ * As no specification is available, the right timings between chip commands are
+ * unknown. The only available piece of information are the observed nops on a
+ * working docg3 chip.
+ * Therefore, doc_delay relies on a busy loop of NOPs, instead of scheduler
+ * friendlier msleep() functions or blocking mdelay().
+ */
+static void doc_delay(struct docg3 *docg3, int nbNOPs)
+{
+	int i;
+
+	doc_dbg("NOP x %d\n", nbNOPs);
+	for (i = 0; i < nbNOPs; i++)
+		doc_writeb(docg3, 0, DOC_NOP);
+}
+
+static int is_prot_seq_error(struct docg3 *docg3)
+{
+	int ctrl;
+
+	ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+	return ctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR);
+}
+
+static int doc_is_ready(struct docg3 *docg3)
+{
+	int ctrl;
+
+	ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+	return ctrl & DOC_CTRL_FLASHREADY;
+}
+
+static int doc_wait_ready(struct docg3 *docg3)
+{
+	int maxWaitCycles = 100;
+
+	do {
+		doc_delay(docg3, 4);
+		cpu_relax();
+	} while (!doc_is_ready(docg3) && maxWaitCycles--);
+	doc_delay(docg3, 2);
+	if (maxWaitCycles > 0)
+		return 0;
+	else
+		return -EIO;
+}
+
+static int doc_reset_seq(struct docg3 *docg3)
+{
+	int ret;
+
+	doc_writeb(docg3, 0x10, DOC_FLASHCONTROL);
+	doc_flash_sequence(docg3, DOC_SEQ_RESET);
+	doc_flash_command(docg3, DOC_CMD_RESET);
+	doc_delay(docg3, 2);
+	ret = doc_wait_ready(docg3);
+
+	doc_dbg("doc_reset_seq() -> isReady=%s\n", ret ? "false" : "true");
+	return ret;
+}
+
+/**
+ * doc_read_data_area - Read data from data area
+ * @docg3: the device
+ * @buf: the buffer to fill in
+ * @len: the lenght to read
+ * @first: first time read, DOC_READADDRESS should be set
+ *
+ * Reads bytes from flash data. Handles the single byte / even bytes reads.
+ */
+static void doc_read_data_area(struct docg3 *docg3, void *buf, int len,
+			       int first)
+{
+	int i, cdr, len4;
+	u16 data16, *dst16;
+	u8 data8, *dst8;
+
+	doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len);
+	cdr = len & 0x3;
+	len4 = len - cdr;
+
+	if (first)
+		doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS);
+	dst16 = buf;
+	for (i = 0; i < len4; i += 2) {
+		data16 = doc_readw(docg3, DOC_IOSPACE_DATA);
+		*dst16 = data16;
+		dst16++;
+	}
+
+	if (cdr) {
+		doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE,
+			   DOC_READADDRESS);
+		doc_delay(docg3, 1);
+		dst8 = (u8 *)dst16;
+		for (i = 0; i < cdr; i++) {
+			data8 = doc_readb(docg3, DOC_IOSPACE_DATA);
+			*dst8 = data8;
+			dst8++;
+		}
+	}
+}
+
+/**
+ * doc_set_data_mode - Sets the flash to reliable data mode
+ * @docg3: the device
+ *
+ * The reliable data mode is a bit slower than the fast mode, but less errors
+ * occur.  Entering the reliable mode cannot be done without entering the fast
+ * mode first.
+ */
+static void doc_set_reliable_mode(struct docg3 *docg3)
+{
+	doc_dbg("doc_set_reliable_mode()\n");
+	doc_flash_sequence(docg3, DOC_SEQ_SET_MODE);
+	doc_flash_command(docg3, DOC_CMD_FAST_MODE);
+	doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE);
+	doc_delay(docg3, 2);
+}
+
+/**
+ * doc_set_asic_mode - Set the ASIC mode
+ * @docg3: the device
+ * @mode: the mode
+ *
+ * The ASIC can work in 3 modes :
+ *  - RESET: all registers are zeroed
+ *  - NORMAL: receives and handles commands
+ *  - POWERDOWN: minimal poweruse, flash parts shut off
+ */
+static void doc_set_asic_mode(struct docg3 *docg3, u8 mode)
+{
+	int i;
+
+	for (i = 0; i < 12; i++)
+		doc_readb(docg3, DOC_IOSPACE_IPL);
+
+	mode |= DOC_ASICMODE_MDWREN;
+	doc_dbg("doc_set_asic_mode(%02x)\n", mode);
+	doc_writeb(docg3, mode, DOC_ASICMODE);
+	doc_writeb(docg3, ~mode, DOC_ASICMODECONFIRM);
+	doc_delay(docg3, 1);
+}
+
+/**
+ * doc_set_device_id - Sets the devices id for cascaded G3 chips
+ * @docg3: the device
+ * @id: the chip to select (amongst 0, 1, 2, 3)
+ *
+ * There can be 4 cascaded G3 chips. This function selects the one which will
+ * should be the active one.
+ */
+static void doc_set_device_id(struct docg3 *docg3, int id)
+{
+	u8 ctrl;
+
+	doc_dbg("doc_set_device_id(%d)\n", id);
+	doc_writeb(docg3, id, DOC_DEVICESELECT);
+	ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+
+	ctrl &= ~DOC_CTRL_VIOLATION;
+	ctrl |= DOC_CTRL_CE;
+	doc_writeb(docg3, ctrl, DOC_FLASHCONTROL);
+}
+
+/**
+ * doc_set_extra_page_mode - Change flash page layout
+ * @docg3: the device
+ *
+ * Normally, the flash page is split into the data (512 bytes) and the out of
+ * band data (16 bytes). For each, 4 more bytes can be accessed, where the wear
+ * leveling counters are stored.  To access this last area of 4 bytes, a special
+ * mode must be input to the flash ASIC.
+ *
+ * Returns 0 if no error occured, -EIO else.
+ */
+static int doc_set_extra_page_mode(struct docg3 *docg3)
+{
+	int fctrl;
+
+	doc_dbg("doc_set_extra_page_mode()\n");
+	doc_flash_sequence(docg3, DOC_SEQ_PAGE_SIZE_532);
+	doc_flash_command(docg3, DOC_CMD_PAGE_SIZE_532);
+	doc_delay(docg3, 2);
+
+	fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+	if (fctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR))
+		return -EIO;
+	else
+		return 0;
+}
+
+/**
+ * doc_seek - Set both flash planes to the specified block, page for reading
+ * @docg3: the device
+ * @block0: the first plane block index
+ * @block1: the second plane block index
+ * @page: the page index within the block
+ * @wear: if true, read will occur on the 4 extra bytes of the wear area
+ * @ofs: offset in page to read
+ *
+ * Programs the flash even and odd planes to the specific block and page.
+ * Alternatively, programs the flash to the wear area of the specified page.
+ */
+static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page,
+			 int wear, int ofs)
+{
+	int sector, ret = 0;
+
+	doc_dbg("doc_seek(blocks=(%d,%d), page=%d, ofs=%d, wear=%d)\n",
+		block0, block1, page, ofs, wear);
+
+	if (!wear && (ofs < 2 * DOC_LAYOUT_PAGE_SIZE)) {
+		doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1);
+		doc_flash_command(docg3, DOC_CMD_READ_PLANE1);
+		doc_delay(docg3, 2);
+	} else {
+		doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2);
+		doc_flash_command(docg3, DOC_CMD_READ_PLANE2);
+		doc_delay(docg3, 2);
+	}
+
+	doc_set_reliable_mode(docg3);
+	if (wear)
+		ret = doc_set_extra_page_mode(docg3);
+	if (ret)
+		goto out;
+
+	sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+	doc_flash_sequence(docg3, DOC_SEQ_READ);
+	doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+	doc_delay(docg3, 1);
+	doc_flash_address(docg3, sector & 0xff);
+	doc_flash_address(docg3, (sector >> 8) & 0xff);
+	doc_flash_address(docg3, (sector >> 16) & 0xff);
+	doc_delay(docg3, 1);
+
+	sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+	doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+	doc_delay(docg3, 1);
+	doc_flash_address(docg3, sector & 0xff);
+	doc_flash_address(docg3, (sector >> 8) & 0xff);
+	doc_flash_address(docg3, (sector >> 16) & 0xff);
+	doc_delay(docg3, 2);
+
+out:
+	return ret;
+}
+
+/**
+ * doc_read_page_ecc_init - Initialize hardware ECC engine
+ * @docg3: the device
+ * @len: the number of bytes covered by the ECC (BCH covered)
+ *
+ * The function does initialize the hardware ECC engine to compute the Hamming
+ * ECC (on 1 byte) and the BCH Syndroms (on 7 bytes).
+ *
+ * Return 0 if succeeded, -EIO on error
+ */
+static int doc_read_page_ecc_init(struct docg3 *docg3, int len)
+{
+	doc_writew(docg3, DOC_ECCCONF0_READ_MODE
+		   | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE
+		   | (len & DOC_ECCCONF0_DATA_BYTES_MASK),
+		   DOC_ECCCONF0);
+	doc_delay(docg3, 4);
+	doc_register_readb(docg3, DOC_FLASHCONTROL);
+	return doc_wait_ready(docg3);
+}
+
+/**
+ * doc_read_page_prepare - Prepares reading data from a flash page
+ * @docg3: the device
+ * @block0: the first plane block index on flash memory
+ * @block1: the second plane block index on flash memory
+ * @page: the page index in the block
+ * @offset: the offset in the page (must be a multiple of 4)
+ *
+ * Prepares the page to be read in the flash memory :
+ *   - tell ASIC to map the flash pages
+ *   - tell ASIC to be in read mode
+ *
+ * After a call to this method, a call to doc_read_page_finish is mandatory,
+ * to end the read cycle of the flash.
+ *
+ * Read data from a flash page. The length to be read must be between 0 and
+ * (page_size + oob_size + wear_size), ie. 532, and a multiple of 4 (because
+ * the extra bytes reading is not implemented).
+ *
+ * As pages are grouped by 2 (in 2 planes), reading from a page must be done
+ * in two steps:
+ *  - one read of 512 bytes at offset 0
+ *  - one read of 512 bytes at offset 512 + 16
+ *
+ * Returns 0 if successful, -EIO if a read error occured.
+ */
+static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1,
+				 int page, int offset)
+{
+	int wear_area = 0, ret = 0;
+
+	doc_dbg("doc_read_page_prepare(blocks=(%d,%d), page=%d, ofsInPage=%d)\n",
+		block0, block1, page, offset);
+	if (offset >= DOC_LAYOUT_WEAR_OFFSET)
+		wear_area = 1;
+	if (!wear_area && offset > (DOC_LAYOUT_PAGE_OOB_SIZE * 2))
+		return -EINVAL;
+
+	doc_set_device_id(docg3, docg3->device_id);
+	ret = doc_reset_seq(docg3);
+	if (ret)
+		goto err;
+
+	/* Program the flash address block and page */
+	ret = doc_read_seek(docg3, block0, block1, page, wear_area, offset);
+	if (ret)
+		goto err;
+
+	doc_flash_command(docg3, DOC_CMD_READ_ALL_PLANES);
+	doc_delay(docg3, 2);
+	doc_wait_ready(docg3);
+
+	doc_flash_command(docg3, DOC_CMD_SET_ADDR_READ);
+	doc_delay(docg3, 1);
+	if (offset >= DOC_LAYOUT_PAGE_SIZE * 2)
+		offset -= 2 * DOC_LAYOUT_PAGE_SIZE;
+	doc_flash_address(docg3, offset >> 2);
+	doc_delay(docg3, 1);
+	doc_wait_ready(docg3);
+
+	doc_flash_command(docg3, DOC_CMD_READ_FLASH);
+
+	return 0;
+err:
+	doc_writeb(docg3, 0, DOC_DATAEND);
+	doc_delay(docg3, 2);
+	return -EIO;
+}
+
+/**
+ * doc_read_page_getbytes - Reads bytes from a prepared page
+ * @docg3: the device
+ * @len: the number of bytes to be read (must be a multiple of 4)
+ * @buf: the buffer to be filled in
+ * @first: 1 if first time read, DOC_READADDRESS should be set
+ *
+ */
+static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf,
+				  int first)
+{
+	doc_read_data_area(docg3, buf, len, first);
+	doc_delay(docg3, 2);
+	return len;
+}
+
+/**
+ * doc_get_hw_bch_syndroms - Get hardware calculated BCH syndroms
+ * @docg3: the device
+ * @syns:  the array of 7 integers where the syndroms will be stored
+ */
+static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns)
+{
+	int i;
+
+	for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
+		syns[i] = doc_register_readb(docg3, DOC_BCH_SYNDROM(i));
+}
+
+/**
+ * doc_read_page_finish - Ends reading of a flash page
+ * @docg3: the device
+ *
+ * As a side effect, resets the chip selector to 0. This ensures that after each
+ * read operation, the floor 0 is selected. Therefore, if the systems halts, the
+ * reboot will boot on floor 0, where the IPL is.
+ */
+static void doc_read_page_finish(struct docg3 *docg3)
+{
+	doc_writeb(docg3, 0, DOC_DATAEND);
+	doc_delay(docg3, 2);
+	doc_set_device_id(docg3, 0);
+}
+
+/**
+ * calc_block_sector - Calculate blocks, pages and ofs.
+
+ * @from: offset in flash
+ * @block0: first plane block index calculated
+ * @block1: second plane block index calculated
+ * @page: page calculated
+ * @ofs: offset in page
+ */
+static void calc_block_sector(loff_t from, int *block0, int *block1, int *page,
+			      int *ofs)
+{
+	uint sector;
+
+	sector = from / DOC_LAYOUT_PAGE_SIZE;
+	*block0 = sector / (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES)
+		* DOC_LAYOUT_NBPLANES;
+	*block1 = *block0 + 1;
+	*page = sector % (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES);
+	*page /= DOC_LAYOUT_NBPLANES;
+	if (sector % 2)
+		*ofs = DOC_LAYOUT_PAGE_OOB_SIZE;
+	else
+		*ofs = 0;
+}
+
+/**
+ * doc_read - Read bytes from flash
+ * @mtd: the device
+ * @from: the offset from first block and first page, in bytes, aligned on page
+ *        size
+ * @len: the number of bytes to read (must be a multiple of 4)
+ * @retlen: the number of bytes actually read
+ * @buf: the filled in buffer
+ *
+ * Reads flash memory pages. This function does not read the OOB chunk, but only
+ * the page data.
+ *
+ * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ */
+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
+	     size_t *retlen, u_char *buf)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int block0, block1, page, readlen, ret, ofs = 0;
+	int syn[DOC_ECC_BCH_SIZE], eccconf1;
+	u8 oob[DOC_LAYOUT_OOB_SIZE];
+
+	ret = -EINVAL;
+	doc_dbg("doc_read(from=%lld, len=%zu, buf=%p)\n", from, len, buf);
+	if (from % DOC_LAYOUT_PAGE_SIZE)
+		goto err;
+	if (len % 4)
+		goto err;
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	if (block1 > docg3->max_block)
+		goto err;
+
+	*retlen = 0;
+	ret = 0;
+	readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE);
+	while (!ret && len > 0) {
+		readlen = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE);
+		ret = doc_read_page_prepare(docg3, block0, block1, page, ofs);
+		if (ret < 0)
+			goto err;
+		ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_COVERED_BYTES);
+		if (ret < 0)
+			goto err_in_read;
+		ret = doc_read_page_getbytes(docg3, readlen, buf, 1);
+		if (ret < readlen)
+			goto err_in_read;
+		ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE,
+					     oob, 0);
+		if (ret < DOC_LAYOUT_OOB_SIZE)
+			goto err_in_read;
+
+		*retlen += readlen;
+		buf += readlen;
+		len -= readlen;
+
+		ofs ^= DOC_LAYOUT_PAGE_OOB_SIZE;
+		if (ofs == 0)
+			page += 2;
+		if (page > DOC_ADDR_PAGE_MASK) {
+			page = 0;
+			block0 += 2;
+			block1 += 2;
+		}
+
+		/*
+		 * There should be a BCH bitstream fixing algorithm here ...
+		 * By now, a page read failure is triggered by BCH error
+		 */
+		doc_get_hw_bch_syndroms(docg3, syn);
+		eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1);
+
+		doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			 oob[0], oob[1], oob[2], oob[3], oob[4],
+			 oob[5], oob[6]);
+		doc_dbg("OOB - HAMMING: %02x\n", oob[7]);
+		doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			 oob[8], oob[9], oob[10], oob[11], oob[12],
+			 oob[13], oob[14]);
+		doc_dbg("OOB - UNUSED: %02x\n", oob[15]);
+		doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1);
+		doc_dbg("ECC BCH syndrom: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			syn[0], syn[1], syn[2], syn[3], syn[4], syn[5], syn[6]);
+
+		ret = -EBADMSG;
+		if (block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) {
+			if (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR)
+				goto err_in_read;
+			if (is_prot_seq_error(docg3))
+				goto err_in_read;
+		}
+		doc_read_page_finish(docg3);
+	}
+
+	return 0;
+err_in_read:
+	doc_read_page_finish(docg3);
+err:
+	return ret;
+}
+
+/**
+ * doc_read_oob - Read out of band bytes from flash
+ * @mtd: the device
+ * @from: the offset from first block and first page, in bytes, aligned on page
+ *        size
+ * @ops: the mtd oob structure
+ *
+ * Reads flash memory OOB area of pages.
+ *
+ * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ */
+static int doc_read_oob(struct mtd_info *mtd, loff_t from,
+			struct mtd_oob_ops *ops)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int block0, block1, page, ofs, ret;
+	u8 *buf = ops->oobbuf;
+	size_t len = ops->ooblen;
+
+	doc_dbg("doc_read_oob(from=%lld, buf=%p, len=%zu)\n", from, buf, len);
+	if (len != DOC_LAYOUT_OOB_SIZE)
+		return -EINVAL;
+
+	switch (ops->mode) {
+	case MTD_OPS_PLACE_OOB:
+		buf += ops->ooboffs;
+		break;
+	default:
+		break;
+	}
+
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	if (block1 > docg3->max_block)
+		return -EINVAL;
+
+	ret = doc_read_page_prepare(docg3, block0, block1, page,
+				    ofs + DOC_LAYOUT_PAGE_SIZE);
+	if (!ret)
+		ret = doc_read_page_ecc_init(docg3, DOC_LAYOUT_OOB_SIZE);
+	if (!ret)
+		ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE,
+					     buf, 1);
+	doc_read_page_finish(docg3);
+
+	if (ret > 0)
+		ops->oobretlen = ret;
+	else
+		ops->oobretlen = 0;
+	return (ret > 0) ? 0 : ret;
+}
+
+static int doc_reload_bbt(struct docg3 *docg3)
+{
+	int block = DOC_LAYOUT_BLOCK_BBT;
+	int ret = 0, nbpages, page;
+	u_char *buf = docg3->bbt;
+
+	nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE);
+	for (page = 0; !ret && (page < nbpages); page++) {
+		ret = doc_read_page_prepare(docg3, block, block + 1,
+					    page + DOC_LAYOUT_PAGE_BBT, 0);
+		if (!ret)
+			ret = doc_read_page_ecc_init(docg3,
+						     DOC_LAYOUT_PAGE_SIZE);
+		if (!ret)
+			doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE,
+					       buf, 1);
+		buf += DOC_LAYOUT_PAGE_SIZE;
+	}
+	doc_read_page_finish(docg3);
+	return ret;
+}
+
+/**
+ * doc_block_isbad - Checks whether a block is good or not
+ * @mtd: the device
+ * @from: the offset to find the correct block
+ *
+ * Returns 1 if block is bad, 0 if block is good
+ */
+static int doc_block_isbad(struct mtd_info *mtd, loff_t from)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int block0, block1, page, ofs, is_good;
+
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n",
+		from, block0, block1, page, ofs);
+
+	if (block0 < DOC_LAYOUT_BLOCK_FIRST_DATA)
+		return 0;
+	if (block1 > docg3->max_block)
+		return -EINVAL;
+
+	is_good = docg3->bbt[block0 >> 3] & (1 << (block0 & 0x7));
+	return !is_good;
+}
+
+/**
+ * doc_get_erase_count - Get block erase count
+ * @docg3: the device
+ * @from: the offset in which the block is.
+ *
+ * Get the number of times a block was erased. The number is the maximum of
+ * erase times between first and second plane (which should be equal normally).
+ *
+ * Returns The number of erases, or -EINVAL or -EIO on error.
+ */
+static int doc_get_erase_count(struct docg3 *docg3, loff_t from)
+{
+	u8 buf[DOC_LAYOUT_WEAR_SIZE];
+	int ret, plane1_erase_count, plane2_erase_count;
+	int block0, block1, page, ofs;
+
+	doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf);
+	if (from % DOC_LAYOUT_PAGE_SIZE)
+		return -EINVAL;
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	if (block1 > docg3->max_block)
+		return -EINVAL;
+
+	ret = doc_reset_seq(docg3);
+	if (!ret)
+		ret = doc_read_page_prepare(docg3, block0, block1, page,
+					    ofs + DOC_LAYOUT_WEAR_OFFSET);
+	if (!ret)
+		ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE,
+					     buf, 1);
+	doc_read_page_finish(docg3);
+
+	if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK))
+		return -EIO;
+	plane1_erase_count = (u8)(~buf[1]) | ((u8)(~buf[4]) << 8)
+		| ((u8)(~buf[5]) << 16);
+	plane2_erase_count = (u8)(~buf[3]) | ((u8)(~buf[6]) << 8)
+		| ((u8)(~buf[7]) << 16);
+
+	return max(plane1_erase_count, plane2_erase_count);
+}
+
+/*
+ * Debug sysfs entries
+ */
+static int dbg_flashctrl_show(struct seq_file *s, void *p)
+{
+	struct docg3 *docg3 = (struct docg3 *)s->private;
+
+	int pos = 0;
+	u8 fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+
+	pos += seq_printf(s,
+		 "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n",
+		 fctrl,
+		 fctrl & DOC_CTRL_VIOLATION ? "protocol violation" : "-",
+		 fctrl & DOC_CTRL_CE ? "active" : "inactive",
+		 fctrl & DOC_CTRL_PROTECTION_ERROR ? "protection error" : "-",
+		 fctrl & DOC_CTRL_SEQUENCE_ERROR ? "sequence error" : "-",
+		 fctrl & DOC_CTRL_FLASHREADY ? "ready" : "not ready");
+	return pos;
+}
+DEBUGFS_RO_ATTR(flashcontrol, dbg_flashctrl_show);
+
+static int dbg_asicmode_show(struct seq_file *s, void *p)
+{
+	struct docg3 *docg3 = (struct docg3 *)s->private;
+
+	int pos = 0;
+	int pctrl = doc_register_readb(docg3, DOC_ASICMODE);
+	int mode = pctrl & 0x03;
+
+	pos += seq_printf(s,
+			 "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (",
+			 pctrl,
+			 pctrl & DOC_ASICMODE_RAM_WE ? 1 : 0,
+			 pctrl & DOC_ASICMODE_RSTIN_RESET ? 1 : 0,
+			 pctrl & DOC_ASICMODE_BDETCT_RESET ? 1 : 0,
+			 pctrl & DOC_ASICMODE_MDWREN ? 1 : 0,
+			 pctrl & DOC_ASICMODE_POWERDOWN ? 1 : 0,
+			 mode >> 1, mode & 0x1);
+
+	switch (mode) {
+	case DOC_ASICMODE_RESET:
+		pos += seq_printf(s, "reset");
+		break;
+	case DOC_ASICMODE_NORMAL:
+		pos += seq_printf(s, "normal");
+		break;
+	case DOC_ASICMODE_POWERDOWN:
+		pos += seq_printf(s, "powerdown");
+		break;
+	}
+	pos += seq_printf(s, ")\n");
+	return pos;
+}
+DEBUGFS_RO_ATTR(asic_mode, dbg_asicmode_show);
+
+static int dbg_device_id_show(struct seq_file *s, void *p)
+{
+	struct docg3 *docg3 = (struct docg3 *)s->private;
+	int pos = 0;
+	int id = doc_register_readb(docg3, DOC_DEVICESELECT);
+
+	pos += seq_printf(s, "DeviceId = %d\n", id);
+	return pos;
+}
+DEBUGFS_RO_ATTR(device_id, dbg_device_id_show);
+
+static int dbg_protection_show(struct seq_file *s, void *p)
+{
+	struct docg3 *docg3 = (struct docg3 *)s->private;
+	int pos = 0;
+	int protect = doc_register_readb(docg3, DOC_PROTECTION);
+	int dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
+	int dps0_low = doc_register_readb(docg3, DOC_DPS0_ADDRLOW);
+	int dps0_high = doc_register_readb(docg3, DOC_DPS0_ADDRHIGH);
+	int dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
+	int dps1_low = doc_register_readb(docg3, DOC_DPS1_ADDRLOW);
+	int dps1_high = doc_register_readb(docg3, DOC_DPS1_ADDRHIGH);
+
+	pos += seq_printf(s, "Protection = 0x%02x (",
+			 protect);
+	if (protect & DOC_PROTECT_FOUNDRY_OTP_LOCK)
+		pos += seq_printf(s, "FOUNDRY_OTP_LOCK,");
+	if (protect & DOC_PROTECT_CUSTOMER_OTP_LOCK)
+		pos += seq_printf(s, "CUSTOMER_OTP_LOCK,");
+	if (protect & DOC_PROTECT_LOCK_INPUT)
+		pos += seq_printf(s, "LOCK_INPUT,");
+	if (protect & DOC_PROTECT_STICKY_LOCK)
+		pos += seq_printf(s, "STICKY_LOCK,");
+	if (protect & DOC_PROTECT_PROTECTION_ENABLED)
+		pos += seq_printf(s, "PROTECTION ON,");
+	if (protect & DOC_PROTECT_IPL_DOWNLOAD_LOCK)
+		pos += seq_printf(s, "IPL_DOWNLOAD_LOCK,");
+	if (protect & DOC_PROTECT_PROTECTION_ERROR)
+		pos += seq_printf(s, "PROTECT_ERR,");
+	else
+		pos += seq_printf(s, "NO_PROTECT_ERR");
+	pos += seq_printf(s, ")\n");
+
+	pos += seq_printf(s, "DPS0 = 0x%02x : "
+			 "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
+			 "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+			 dps0, dps0_low, dps0_high,
+			 !!(dps0 & DOC_DPS_OTP_PROTECTED),
+			 !!(dps0 & DOC_DPS_READ_PROTECTED),
+			 !!(dps0 & DOC_DPS_WRITE_PROTECTED),
+			 !!(dps0 & DOC_DPS_HW_LOCK_ENABLED),
+			 !!(dps0 & DOC_DPS_KEY_OK));
+	pos += seq_printf(s, "DPS1 = 0x%02x : "
+			 "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
+			 "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+			 dps1, dps1_low, dps1_high,
+			 !!(dps1 & DOC_DPS_OTP_PROTECTED),
+			 !!(dps1 & DOC_DPS_READ_PROTECTED),
+			 !!(dps1 & DOC_DPS_WRITE_PROTECTED),
+			 !!(dps1 & DOC_DPS_HW_LOCK_ENABLED),
+			 !!(dps1 & DOC_DPS_KEY_OK));
+	return pos;
+}
+DEBUGFS_RO_ATTR(protection, dbg_protection_show);
+
+static int __init doc_dbg_register(struct docg3 *docg3)
+{
+	struct dentry *root, *entry;
+
+	root = debugfs_create_dir("docg3", NULL);
+	if (!root)
+		return -ENOMEM;
+
+	entry = debugfs_create_file("flashcontrol", S_IRUSR, root, docg3,
+				  &flashcontrol_fops);
+	if (entry)
+		entry = debugfs_create_file("asic_mode", S_IRUSR, root,
+					    docg3, &asic_mode_fops);
+	if (entry)
+		entry = debugfs_create_file("device_id", S_IRUSR, root,
+					    docg3, &device_id_fops);
+	if (entry)
+		entry = debugfs_create_file("protection", S_IRUSR, root,
+					    docg3, &protection_fops);
+	if (entry) {
+		docg3->debugfs_root = root;
+		return 0;
+	} else {
+		debugfs_remove_recursive(root);
+		return -ENOMEM;
+	}
+}
+
+static void __exit doc_dbg_unregister(struct docg3 *docg3)
+{
+	debugfs_remove_recursive(docg3->debugfs_root);
+}
+
+/**
+ * doc_set_driver_info - Fill the mtd_info structure and docg3 structure
+ * @chip_id: The chip ID of the supported chip
+ * @mtd: The structure to fill
+ */
+static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int cfg;
+
+	cfg = doc_register_readb(docg3, DOC_CONFIGURATION);
+	docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0);
+
+	switch (chip_id) {
+	case DOC_CHIPID_G3:
+		mtd->name = "DiskOnChip G3";
+		docg3->max_block = 2047;
+		break;
+	}
+	mtd->type = MTD_NANDFLASH;
+	/*
+	 * Once write methods are added, the correct flags will be set.
+	 * mtd->flags = MTD_CAP_NANDFLASH;
+	 */
+	mtd->flags = MTD_CAP_ROM;
+	mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE;
+	mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES;
+	mtd->writesize = DOC_LAYOUT_PAGE_SIZE;
+	mtd->oobsize = DOC_LAYOUT_OOB_SIZE;
+	mtd->owner = THIS_MODULE;
+	mtd->erase = NULL;
+	mtd->point = NULL;
+	mtd->unpoint = NULL;
+	mtd->read = doc_read;
+	mtd->write = NULL;
+	mtd->read_oob = doc_read_oob;
+	mtd->write_oob = NULL;
+	mtd->sync = NULL;
+	mtd->block_isbad = doc_block_isbad;
+}
+
+/**
+ * doc_probe - Probe the IO space for a DiskOnChip G3 chip
+ * @pdev: platform device
+ *
+ * Probes for a G3 chip at the specified IO space in the platform data
+ * ressources.
+ *
+ * Returns 0 on success, -ENOMEM, -ENXIO on error
+ */
+static int __init docg3_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct docg3 *docg3;
+	struct mtd_info *mtd;
+	struct resource *ress;
+	int ret, bbt_nbpages;
+	u16 chip_id, chip_id_inv;
+
+	ret = -ENOMEM;
+	docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL);
+	if (!docg3)
+		goto nomem1;
+	mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
+	if (!mtd)
+		goto nomem2;
+	mtd->priv = docg3;
+
+	ret = -ENXIO;
+	ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!ress) {
+		dev_err(dev, "No I/O memory resource defined\n");
+		goto noress;
+	}
+	docg3->base = ioremap(ress->start, DOC_IOSPACE_SIZE);
+
+	docg3->dev = &pdev->dev;
+	docg3->device_id = 0;
+	doc_set_device_id(docg3, docg3->device_id);
+	doc_set_asic_mode(docg3, DOC_ASICMODE_RESET);
+	doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL);
+
+	chip_id = doc_register_readw(docg3, DOC_CHIPID);
+	chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV);
+
+	ret = -ENODEV;
+	if (chip_id != (u16)(~chip_id_inv)) {
+		doc_info("No device found at IO addr %p\n",
+			 (void *)ress->start);
+		goto nochipfound;
+	}
+
+	switch (chip_id) {
+	case DOC_CHIPID_G3:
+		doc_info("Found a G3 DiskOnChip at addr %p\n",
+			 (void *)ress->start);
+		break;
+	default:
+		doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id);
+		goto nochipfound;
+	}
+
+	doc_set_driver_info(chip_id, mtd);
+	platform_set_drvdata(pdev, mtd);
+
+	ret = -ENOMEM;
+	bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1,
+				   8 * DOC_LAYOUT_PAGE_SIZE);
+	docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL);
+	if (!docg3->bbt)
+		goto nochipfound;
+	doc_reload_bbt(docg3);
+
+	ret = mtd_device_parse_register(mtd, part_probes,
+					NULL, NULL, 0);
+	if (ret)
+		goto register_error;
+
+	doc_dbg_register(docg3);
+	return 0;
+
+register_error:
+	kfree(docg3->bbt);
+nochipfound:
+	iounmap(docg3->base);
+noress:
+	kfree(mtd);
+nomem2:
+	kfree(docg3);
+nomem1:
+	return ret;
+}
+
+/**
+ * docg3_release - Release the driver
+ * @pdev: the platform device
+ *
+ * Returns 0
+ */
+static int __exit docg3_release(struct platform_device *pdev)
+{
+	struct mtd_info *mtd = platform_get_drvdata(pdev);
+	struct docg3 *docg3 = mtd->priv;
+
+	doc_dbg_unregister(docg3);
+	mtd_device_unregister(mtd);
+	iounmap(docg3->base);
+	kfree(docg3->bbt);
+	kfree(docg3);
+	kfree(mtd);
+	return 0;
+}
+
+static struct platform_driver g3_driver = {
+	.driver		= {
+		.name	= "docg3",
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __exit_p(docg3_release),
+};
+
+static int __init docg3_init(void)
+{
+	return platform_driver_probe(&g3_driver, docg3_probe);
+}
+module_init(docg3_init);
+
+
+static void __exit docg3_exit(void)
+{
+	platform_driver_unregister(&g3_driver);
+}
+module_exit(docg3_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
+MODULE_DESCRIPTION("MTD driver for DiskOnChip G3");

+ 297 - 0
drivers/mtd/devices/docg3.h

@@ -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>

+ 0 - 5
drivers/mtd/devices/docprobe.c

@@ -50,11 +50,6 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/doc2000.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;
 static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS;
 module_param(doc_config_location, ulong, 0);
 module_param(doc_config_location, ulong, 0);

+ 1 - 17
drivers/mtd/devices/lart.c

@@ -34,9 +34,6 @@
 /* debugging */
 /* debugging */
 //#define LART_DEBUG
 //#define LART_DEBUG
 
 
-/* partition support */
-#define HAVE_PARTITIONS
-
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/types.h>
@@ -44,9 +41,7 @@
 #include <linux/errno.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
-#ifdef HAVE_PARTITIONS
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/partitions.h>
-#endif
 
 
 #ifndef CONFIG_SA1100_LART
 #ifndef CONFIG_SA1100_LART
 #error This is for LART architecture only
 #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[] = {
 static struct mtd_partition lart_partitions[] = {
 	/* blob */
 	/* blob */
 	{
 	{
@@ -619,7 +613,7 @@ static struct mtd_partition lart_partitions[] = {
 		.size	= INITRD_LEN,		/* MTDPART_SIZ_FULL */
 		.size	= INITRD_LEN,		/* MTDPART_SIZ_FULL */
 	}
 	}
 };
 };
-#endif
+#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
 
 
 static int __init lart_flash_init (void)
 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].erasesize,mtd.eraseregions[result].erasesize / 1024,
 			   result,mtd.eraseregions[result].numblocks);
 			   result,mtd.eraseregions[result].numblocks);
 
 
-#ifdef HAVE_PARTITIONS
    printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
    printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
 
 
    for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
    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].offset,
 			 result,lart_partitions[result].size,lart_partitions[result].size / 1024);
 			 result,lart_partitions[result].size,lart_partitions[result].size / 1024);
 #endif
 #endif
-#endif
 
 
-#ifndef HAVE_PARTITIONS
-   result = mtd_device_register(&mtd, NULL, 0);
-#else
    result = mtd_device_register(&mtd, lart_partitions,
    result = mtd_device_register(&mtd, lart_partitions,
                                 ARRAY_SIZE(lart_partitions));
                                 ARRAY_SIZE(lart_partitions));
-#endif
 
 
    return (result);
    return (result);
 }
 }
 
 
 static void __exit lart_flash_exit (void)
 static void __exit lart_flash_exit (void)
 {
 {
-#ifndef HAVE_PARTITIONS
-   mtd_device_unregister(&mtd);
-#else
    mtd_device_unregister(&mtd);
    mtd_device_unregister(&mtd);
-#endif
 }
 }
 
 
 module_init (lart_flash_init);
 module_init (lart_flash_init);

+ 30 - 62
drivers/mtd/devices/m25p80.c

@@ -30,6 +30,7 @@
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/partitions.h>
+#include <linux/of_platform.h>
 
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/spi/flash.h>
@@ -88,7 +89,6 @@ struct m25p {
 	struct spi_device	*spi;
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct mutex		lock;
 	struct mtd_info		mtd;
 	struct mtd_info		mtd;
-	unsigned		partitioned:1;
 	u16			page_size;
 	u16			page_size;
 	u16			addr_width;
 	u16			addr_width;
 	u8			erase_opcode;
 	u8			erase_opcode;
@@ -209,9 +209,8 @@ static int wait_till_ready(struct m25p *flash)
  */
  */
 static int erase_chip(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. */
 	/* Wait until finished previous write command. */
 	if (wait_till_ready(flash))
 	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)
 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. */
 	/* Wait until finished previous write command. */
 	if (wait_till_ready(flash))
 	if (wait_till_ready(flash))
@@ -286,9 +284,9 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
 	u32 addr,len;
 	u32 addr,len;
 	uint32_t rem;
 	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 */
 	/* sanity checks */
 	if (instr->addr + instr->len > flash->mtd.size)
 	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_transfer t[2];
 	struct spi_message m;
 	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 */
 	/* sanity checks */
 	if (!len)
 	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_transfer t[2];
 	struct spi_message m;
 	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;
 	*retlen = 0;
 
 
@@ -510,9 +506,8 @@ static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
 	size_t actual;
 	size_t actual;
 	int cmd_sz, ret;
 	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;
 	*retlen = 0;
 
 
@@ -661,6 +656,7 @@ static const struct spi_device_id m25p_ids[] = {
 	{ "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
 	{ "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
 
 
 	{ "at25df041a", INFO(0x1f4401, 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) },
 	{ "at25df641",  INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
 
 
 	{ "at26f004",   INFO(0x1f0400, 0, 64 * 1024,  8, 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 */
 	/* EON -- en25xxx */
 	{ "en25f32", INFO(0x1c3116, 0, 64 * 1024,  64, SECT_4K) },
 	{ "en25f32", INFO(0x1c3116, 0, 64 * 1024,  64, SECT_4K) },
 	{ "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
 	{ "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
+	{ "en25q32b", INFO(0x1c3016, 0, 64 * 1024,  64, 0) },
 	{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
 	{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
 
 
 	/* Intel/Numonyx -- xxxs33b */
 	/* 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);
 	tmp = spi_write_then_read(spi, &code, 1, id, 5);
 	if (tmp < 0) {
 	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);
 		return ERR_PTR(tmp);
 	}
 	}
 	jedec = id[0];
 	jedec = id[0];
@@ -825,8 +822,12 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	struct m25p			*flash;
 	struct m25p			*flash;
 	struct flash_info		*info;
 	struct flash_info		*info;
 	unsigned			i;
 	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
 	/* Platform data helps sort out which chip type we have, as
 	 * well as how this board partitions it.  If we don't have
 	 * 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)
 	if (info->flags & M25P_NO_ERASE)
 		flash->mtd.flags |= MTD_NO_ERASE;
 		flash->mtd.flags |= MTD_NO_ERASE;
 
 
+	ppdata.of_node = spi->dev.of_node;
 	flash->mtd.dev.parent = &spi->dev;
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
 	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,
 	dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
 			(long long)flash->mtd.size >> 10);
 			(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",
 			".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
 		flash->mtd.name,
 		flash->mtd.name,
 		(long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
 		(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)
 	if (flash->mtd.numeraseregions)
 		for (i = 0; i < flash->mtd.numeraseregions; i++)
 		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), "
 				".erasesize = 0x%.8x (%uKiB), "
 				".numblocks = %d }\n",
 				".numblocks = %d }\n",
 				i, (long long)flash->mtd.eraseregions[i].offset,
 				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
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 * 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);
 }
 }
 
 
 
 

+ 42 - 49
drivers/mtd/devices/mtd_dataflash.c

@@ -17,6 +17,8 @@
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/math64.h>
 #include <linux/math64.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/spi/flash.h>
@@ -24,7 +26,6 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/partitions.h>
 
 
-
 /*
 /*
  * DataFlash is a kind of SPI flash.  Most AT45 chips have two buffers in
  * 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
  * each chip, which may be used for double buffered I/O; but this driver
@@ -98,6 +99,16 @@ struct dataflash {
 	struct mtd_info		mtd;
 	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 (;;) {
 	for (;;) {
 		status = dataflash_status(spi);
 		status = dataflash_status(spi);
 		if (status < 0) {
 		if (status < 0) {
-			DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n",
+			pr_debug("%s: status %d?\n",
 					dev_name(&spi->dev), status);
 					dev_name(&spi->dev), status);
 			status = 0;
 			status = 0;
 		}
 		}
@@ -149,7 +160,7 @@ static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr)
 	uint8_t			*command;
 	uint8_t			*command;
 	uint32_t		rem;
 	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,
 	      dev_name(&spi->dev), (long long)instr->addr,
 	      (long long)instr->len);
 	      (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[2] = (uint8_t)(pageaddr >> 8);
 		command[3] = 0;
 		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",
 			do_block ? "block" : "page",
 			command[0], command[1], command[2], command[3],
 			command[0], command[1], command[2], command[3],
 			pageaddr);
 			pageaddr);
@@ -238,8 +249,8 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 	uint8_t			*command;
 	uint8_t			*command;
 	int			status;
 	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;
 	*retlen = 0;
 
 
@@ -255,7 +266,7 @@ static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len,
 
 
 	command = priv->command;
 	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]);
 		command[0], command[1], command[2], command[3]);
 
 
 	spi_message_init(&msg);
 	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;
 		*retlen = msg.actual_length - 8;
 		status = 0;
 		status = 0;
 	} else
 	} else
-		DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n",
+		pr_debug("%s: read %x..%x --> %d\n",
 			dev_name(&priv->spi->dev),
 			dev_name(&priv->spi->dev),
 			(unsigned)from, (unsigned)(from + len),
 			(unsigned)from, (unsigned)(from + len),
 			status);
 			status);
@@ -314,7 +325,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
 	int			status = -EINVAL;
 	int			status = -EINVAL;
 	uint8_t			*command;
 	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));
 		dev_name(&spi->dev), (unsigned)to, (unsigned)(to + len));
 
 
 	*retlen = 0;
 	*retlen = 0;
@@ -340,7 +351,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
 
 
 	mutex_lock(&priv->lock);
 	mutex_lock(&priv->lock);
 	while (remaining > 0) {
 	while (remaining > 0) {
-		DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n",
+		pr_debug("write @ %i:%i len=%i\n",
 			pageaddr, offset, writelen);
 			pageaddr, offset, writelen);
 
 
 		/* REVISIT:
 		/* 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[2] = (addr & 0x0000FF00) >> 8;
 			command[3] = 0;
 			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]);
 				command[0], command[1], command[2], command[3]);
 
 
 			status = spi_sync(spi, &msg);
 			status = spi_sync(spi, &msg);
 			if (status < 0)
 			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);
 					dev_name(&spi->dev), addr, status);
 
 
 			(void) dataflash_waitready(priv->spi);
 			(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[2] = (addr & 0x0000FF00) >> 8;
 		command[3] = (addr & 0x000000FF);
 		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]);
 			command[0], command[1], command[2], command[3]);
 
 
 		x[1].tx_buf = writebuf;
 		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);
 		status = spi_sync(spi, &msg);
 		spi_transfer_del(x + 1);
 		spi_transfer_del(x + 1);
 		if (status < 0)
 		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);
 				dev_name(&spi->dev), addr, writelen, status);
 
 
 		(void) dataflash_waitready(priv->spi);
 		(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[2] = (addr & 0x0000FF00) >> 8;
 		command[3] = 0;
 		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]);
 			command[0], command[1], command[2], command[3]);
 
 
 		status = spi_sync(spi, &msg);
 		status = spi_sync(spi, &msg);
 		if (status < 0)
 		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);
 				dev_name(&spi->dev), addr, status);
 
 
 		status = dataflash_waitready(priv->spi);
 		status = dataflash_waitready(priv->spi);
@@ -634,11 +645,10 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 {
 {
 	struct dataflash		*priv;
 	struct dataflash		*priv;
 	struct mtd_info			*device;
 	struct mtd_info			*device;
+	struct mtd_part_parser_data	ppdata;
 	struct flash_platform_data	*pdata = spi->dev.platform_data;
 	struct flash_platform_data	*pdata = spi->dev.platform_data;
 	char				*otp_tag = "";
 	char				*otp_tag = "";
 	int				err = 0;
 	int				err = 0;
-	struct mtd_partition		*parts;
-	int				nr_parts = 0;
 
 
 	priv = kzalloc(sizeof *priv, GFP_KERNEL);
 	priv = kzalloc(sizeof *priv, GFP_KERNEL);
 	if (!priv)
 	if (!priv)
@@ -677,28 +687,11 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 			pagesize, otp_tag);
 			pagesize, otp_tag);
 	dev_set_drvdata(&spi->dev, priv);
 	dev_set_drvdata(&spi->dev, priv);
 
 
-	if (mtd_has_cmdlinepart()) {
-		static const char *part_probes[] = { "cmdlinepart", NULL, };
-
-		nr_parts = parse_mtd_partitions(device, part_probes, &parts,
-						0);
-	}
+	ppdata.of_node = spi->dev.of_node;
+	err = mtd_device_parse_register(device, NULL, &ppdata,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_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)
 	if (!err)
 		return 0;
 		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);
 	tmp = spi_write_then_read(spi, &code, 1, id, 3);
 	if (tmp < 0) {
 	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);
 			dev_name(&spi->dev), tmp);
 		return ERR_PTR(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 < ARRAY_SIZE(dataflash_data);
 			tmp++, info++) {
 			tmp++, info++) {
 		if (info->jedec_id == jedec) {
 		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),
 				dev_name(&spi->dev),
 				(info->flags & SUP_POW2PS)
 				(info->flags & SUP_POW2PS)
 					? ", binary pagesize" : ""
 					? ", binary pagesize" : ""
@@ -812,8 +805,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
 			if (info->flags & SUP_POW2PS) {
 			if (info->flags & SUP_POW2PS) {
 				status = dataflash_status(spi);
 				status = dataflash_status(spi);
 				if (status < 0) {
 				if (status < 0) {
-					DEBUG(MTD_DEBUG_LEVEL1,
-						"%s: status error %d\n",
+					pr_debug("%s: status error %d\n",
 						dev_name(&spi->dev), status);
 						dev_name(&spi->dev), status);
 					return ERR_PTR(status);
 					return ERR_PTR(status);
 				}
 				}
@@ -878,7 +870,7 @@ static int __devinit dataflash_probe(struct spi_device *spi)
 	 */
 	 */
 	status = dataflash_status(spi);
 	status = dataflash_status(spi);
 	if (status <= 0 || status == 0xff) {
 	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);
 				dev_name(&spi->dev), status);
 		if (status == 0 || status == 0xff)
 		if (status == 0 || status == 0xff)
 			status = -ENODEV;
 			status = -ENODEV;
@@ -914,14 +906,14 @@ static int __devinit dataflash_probe(struct spi_device *spi)
 		break;
 		break;
 	/* obsolete AT45DB1282 not (yet?) supported */
 	/* obsolete AT45DB1282 not (yet?) supported */
 	default:
 	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;
 		status = -ENODEV;
 	}
 	}
 
 
 	if (status < 0)
 	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;
 	return status;
 }
 }
@@ -931,7 +923,7 @@ static int __devexit dataflash_remove(struct spi_device *spi)
 	struct dataflash	*flash = dev_get_drvdata(&spi->dev);
 	struct dataflash	*flash = dev_get_drvdata(&spi->dev);
 	int			status;
 	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);
 	status = mtd_device_unregister(&flash->mtd);
 	if (status == 0) {
 	if (status == 0) {
@@ -946,6 +938,7 @@ static struct spi_driver dataflash_driver = {
 		.name		= "mtd_dataflash",
 		.name		= "mtd_dataflash",
 		.bus		= &spi_bus_type,
 		.bus		= &spi_bus_type,
 		.owner		= THIS_MODULE,
 		.owner		= THIS_MODULE,
+		.of_match_table = dataflash_dt_ids,
 	},
 	},
 
 
 	.probe		= dataflash_probe,
 	.probe		= dataflash_probe,

+ 5 - 37
drivers/mtd/devices/sst25l.c

@@ -52,8 +52,6 @@ struct sst25l_flash {
 	struct spi_device	*spi;
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct mutex		lock;
 	struct mtd_info		mtd;
 	struct mtd_info		mtd;
-
-	int 			partitioned;
 };
 };
 
 
 struct flash_info {
 struct flash_info {
@@ -381,8 +379,6 @@ static int __devinit sst25l_probe(struct spi_device *spi)
 	struct sst25l_flash *flash;
 	struct sst25l_flash *flash;
 	struct flash_platform_data *data;
 	struct flash_platform_data *data;
 	int ret, i;
 	int ret, i;
-	struct mtd_partition *parts = NULL;
-	int nr_parts = 0;
 
 
 	flash_info = sst25l_match_device(spi);
 	flash_info = sst25l_match_device(spi);
 	if (!flash_info)
 	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,
 	dev_info(&spi->dev, "%s (%lld KiB)\n", flash_info->name,
 		 (long long)flash->mtd.size >> 10);
 		 (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",
 	      ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
 	      flash->mtd.name,
 	      flash->mtd.name,
 	      (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
 	      (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);
 	      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);
 		kfree(flash);
 		dev_set_drvdata(&spi->dev, NULL);
 		dev_set_drvdata(&spi->dev, NULL);
 		return -ENODEV;
 		return -ENODEV;

+ 20 - 20
drivers/mtd/ftl.c

@@ -339,7 +339,7 @@ static int erase_xfer(partition_t *part,
     struct erase_info *erase;
     struct erase_info *erase;
 
 
     xfer = &part->XferInfo[xfernum];
     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;
     xfer->state = XFER_ERASING;
 
 
     /* Is there a free erase slot? Always in MTD. */
     /* 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 = &part->XferInfo[i];
     xfer->state = XFER_FAILED;
     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 */
     /* Write the transfer unit header */
     header = part->header;
     header = part->header;
@@ -476,7 +476,7 @@ static int copy_erase_unit(partition_t *part, uint16_t srcunit,
 
 
     eun = &part->EUNInfo[srcunit];
     eun = &part->EUNInfo[srcunit];
     xfer = &part->XferInfo[xferunit];
     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);
 	  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
     unit with the fewest erases, and usually pick the data unit with
     the most deleted blocks.  But with a small probability, pick the
     the most deleted blocks.  But with a small probability, pick the
     oldest data unit instead.  This means that we generally postpone
     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.
     stuff around a bit for wear leveling.
 
 
 ======================================================================*/
 ======================================================================*/
@@ -609,8 +609,8 @@ static int reclaim_block(partition_t *part)
     uint32_t best;
     uint32_t best;
     int queued, ret;
     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 */
     /* Pick the least erased transfer unit */
     best = 0xffffffff; xfer = 0xffff;
     best = 0xffffffff; xfer = 0xffff;
     do {
     do {
@@ -618,22 +618,22 @@ static int reclaim_block(partition_t *part)
 	for (i = 0; i < part->header.NumTransferUnits; i++) {
 	for (i = 0; i < part->header.NumTransferUnits; i++) {
 	    int n=0;
 	    int n=0;
 	    if (part->XferInfo[i].state == XFER_UNKNOWN) {
 	    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;
 		n=1;
 		erase_xfer(part, i);
 		erase_xfer(part, i);
 	    }
 	    }
 	    if (part->XferInfo[i].state == XFER_ERASING) {
 	    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;
 		n=1;
 		queued = 1;
 		queued = 1;
 	    }
 	    }
 	    else if (part->XferInfo[i].state == XFER_ERASED) {
 	    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;
 		n=1;
 		prepare_xfer(part, i);
 		prepare_xfer(part, i);
 	    }
 	    }
 	    if (part->XferInfo[i].state == XFER_PREPARED) {
 	    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;
 		n=1;
 		if (part->XferInfo[i].EraseCount <= best) {
 		if (part->XferInfo[i].EraseCount <= best) {
 		    best = part->XferInfo[i].EraseCount;
 		    best = part->XferInfo[i].EraseCount;
@@ -641,12 +641,12 @@ static int reclaim_block(partition_t *part)
 		}
 		}
 	    }
 	    }
 		if (!n)
 		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 (xfer == 0xffff) {
 	    if (queued) {
 	    if (queued) {
-		DEBUG(1, "ftl_cs: waiting for transfer "
+		pr_debug("ftl_cs: waiting for transfer "
 		      "unit to be prepared...\n");
 		      "unit to be prepared...\n");
 		if (part->mbd.mtd->sync)
 		if (part->mbd.mtd->sync)
 			part->mbd.mtd->sync(part->mbd.mtd);
 			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 "
 		    printk(KERN_NOTICE "ftl_cs: reclaim failed: no "
 			   "suitable transfer units!\n");
 			   "suitable transfer units!\n");
 		else
 		else
-		    DEBUG(1, "ftl_cs: reclaim failed: no "
+		    pr_debug("ftl_cs: reclaim failed: no "
 			  "suitable transfer units!\n");
 			  "suitable transfer units!\n");
 
 
 		return -EIO;
 		return -EIO;
@@ -666,7 +666,7 @@ static int reclaim_block(partition_t *part)
 
 
     eun = 0;
     eun = 0;
     if ((jiffies % shuffle_freq) == 0) {
     if ((jiffies % shuffle_freq) == 0) {
-	DEBUG(1, "ftl_cs: recycling freshest block...\n");
+	pr_debug("ftl_cs: recycling freshest block...\n");
 	best = 0xffffffff;
 	best = 0xffffffff;
 	for (i = 0; i < part->DataUnits; i++)
 	for (i = 0; i < part->DataUnits; i++)
 	    if (part->EUNInfo[i].EraseCount <= best) {
 	    if (part->EUNInfo[i].EraseCount <= best) {
@@ -686,7 +686,7 @@ static int reclaim_block(partition_t *part)
 		printk(KERN_NOTICE "ftl_cs: reclaim failed: "
 		printk(KERN_NOTICE "ftl_cs: reclaim failed: "
 		       "no free blocks!\n");
 		       "no free blocks!\n");
 	    else
 	    else
-		DEBUG(1,"ftl_cs: reclaim failed: "
+		pr_debug("ftl_cs: reclaim failed: "
 		       "no free blocks!\n");
 		       "no free blocks!\n");
 
 
 	    return -EIO;
 	    return -EIO;
@@ -771,7 +771,7 @@ static uint32_t find_free(partition_t *part)
 	printk(KERN_NOTICE "ftl_cs: bad free list!\n");
 	printk(KERN_NOTICE "ftl_cs: bad free list!\n");
 	return 0;
 	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;
     return blk;
 
 
 } /* find_free */
 } /* find_free */
@@ -791,7 +791,7 @@ static int ftl_read(partition_t *part, caddr_t buffer,
     int ret;
     int ret;
     size_t offset, retlen;
     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);
 	  part, sector, nblocks);
     if (!(part->state & FTL_FORMATTED)) {
     if (!(part->state & FTL_FORMATTED)) {
 	printk(KERN_NOTICE "ftl_cs: bad partition\n");
 	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;
     int ret;
     size_t retlen, offset;
     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);
 	  part, log_addr, virt_addr);
     bsize = 1 << part->header.EraseUnitSize;
     bsize = 1 << part->header.EraseUnitSize;
     eun = log_addr / bsize;
     eun = log_addr / bsize;
@@ -905,7 +905,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
     int ret;
     int ret;
     size_t retlen, offset;
     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);
 	  part, sector, nblocks);
     if (!(part->state & FTL_FORMATTED)) {
     if (!(part->state & FTL_FORMATTED)) {
 	printk(KERN_NOTICE "ftl_cs: bad partition\n");
 	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;
 	partition_t *part = (void *)dev;
 	uint32_t bsize = 1 << part->header.EraseUnitSize;
 	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);
 	      sector, nr_sects);
 
 
 	while (nr_sects) {
 	while (nr_sects) {

+ 32 - 37
drivers/mtd/inftlcore.c

@@ -63,14 +63,12 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 		return;
 		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);
 	inftl = kzalloc(sizeof(*inftl), GFP_KERNEL);
 
 
-	if (!inftl) {
-		printk(KERN_WARNING "INFTL: Out of memory for data structures\n");
+	if (!inftl)
 		return;
 		return;
-	}
 
 
 	inftl->mbd.mtd = mtd;
 	inftl->mbd.mtd = mtd;
 	inftl->mbd.devnum = -1;
 	inftl->mbd.devnum = -1;
@@ -133,7 +131,7 @@ static void inftl_remove_dev(struct mtd_blktrans_dev *dev)
 {
 {
 	struct INFTLrecord *inftl = (void *)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);
 	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;
 	struct mtd_oob_ops ops;
 	int res;
 	int res;
 
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = offs & (mtd->writesize - 1);
 	ops.ooboffs = offs & (mtd->writesize - 1);
 	ops.ooblen = len;
 	ops.ooblen = len;
 	ops.oobbuf = buf;
 	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;
 	struct mtd_oob_ops ops;
 	int res;
 	int res;
 
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = offs & (mtd->writesize - 1);
 	ops.ooboffs = offs & (mtd->writesize - 1);
 	ops.ooblen = len;
 	ops.ooblen = len;
 	ops.oobbuf = buf;
 	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;
 	struct mtd_oob_ops ops;
 	int res;
 	int res;
 
 
-	ops.mode = MTD_OOB_PLACE;
+	ops.mode = MTD_OPS_PLACE_OOB;
 	ops.ooboffs = offs;
 	ops.ooboffs = offs;
 	ops.ooblen = mtd->oobsize;
 	ops.ooblen = mtd->oobsize;
 	ops.oobbuf = oob;
 	ops.oobbuf = oob;
@@ -215,16 +213,16 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate)
 	u16 pot = inftl->LastFreeEUN;
 	u16 pot = inftl->LastFreeEUN;
 	int silly = inftl->nb_blocks;
 	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
 	 * Normally, we force a fold to happen before we run out of free
 	 * blocks completely.
 	 * blocks completely.
 	 */
 	 */
 	if (!desperate && inftl->numfreeEUNs < 2) {
 	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;
 		return BLOCK_NIL;
 	}
 	}
 
 
@@ -259,8 +257,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
 	struct inftl_oob oob;
 	struct inftl_oob oob;
 	size_t retlen;
 	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(BlockMap, 0xff, sizeof(BlockMap));
 	memset(BlockDeleted, 0, sizeof(BlockDeleted));
 	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.
 	 * Chain, and the Erase Unit into which we are supposed to be copying.
 	 * Go for it.
 	 * 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++) {
 	for (block = 0; block < inftl->EraseSize/SECTORSIZE ; block++) {
 		unsigned char movebuf[SECTORSIZE];
 		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]) +
 		ret = mtd->read(mtd, (inftl->EraseSize * BlockMap[block]) +
 				(block * SECTORSIZE), SECTORSIZE, &retlen,
 				(block * SECTORSIZE), SECTORSIZE, &retlen,
 				movebuf);
 				movebuf);
-		if (ret < 0 && ret != -EUCLEAN) {
+		if (ret < 0 && !mtd_is_bitflip(ret)) {
 			ret = mtd->read(mtd,
 			ret = mtd->read(mtd,
 					(inftl->EraseSize * BlockMap[block]) +
 					(inftl->EraseSize * BlockMap[block]) +
 					(block * SECTORSIZE), SECTORSIZE,
 					(block * SECTORSIZE), SECTORSIZE,
 					&retlen, movebuf);
 					&retlen, movebuf);
 			if (ret != -EIO)
 			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));
 		memset(&oob, 0xff, sizeof(struct inftl_oob));
 		oob.b.Status = oob.b.Status1 = SECTOR_USED;
 		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
 	 * is important, by doing oldest first if we crash/reboot then it
 	 * it is relatively simple to clean up the mess).
 	 * 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 (;;) {
 	for (;;) {
 		/* Find oldest unit in chain. */
 		/* Find oldest unit in chain. */
@@ -421,7 +416,7 @@ static u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)
 	u16 ChainLength = 0, thislen;
 	u16 ChainLength = 0, thislen;
 	u16 chain, EUN;
 	u16 chain, EUN;
 
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=%p,"
+	pr_debug("INFTL: INFTL_makefreeblock(inftl=%p,"
 		"pending=%d)\n", inftl, pendingblock);
 		"pending=%d)\n", inftl, pendingblock);
 
 
 	for (chain = 0; chain < inftl->nb_blocks; chain++) {
 	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;
 	size_t retlen;
 	int silly, silly2 = 3;
 	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 {
 	do {
 		/*
 		/*
@@ -501,8 +496,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
 				       blockofs, 8, &retlen, (char *)&bci);
 				       blockofs, 8, &retlen, (char *)&bci);
 
 
 			status = bci.Status | bci.Status1;
 			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) {
 			switch(status) {
 			case SECTOR_FREE:
 			case SECTOR_FREE:
@@ -555,9 +550,9 @@ hitused:
 			 * Hopefully we free something, lets try again.
 			 * Hopefully we free something, lets try again.
 			 * This time we are desperate...
 			 * 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);
 			writeEUN = INFTL_findfreeblock(inftl, 1);
 			if (writeEUN == BLOCK_NIL) {
 			if (writeEUN == BLOCK_NIL) {
 				/*
 				/*
@@ -647,7 +642,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
 	struct inftl_bci bci;
 	struct inftl_bci bci;
 	size_t retlen;
 	size_t retlen;
 
 
-	DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=%p,"
+	pr_debug("INFTL: INFTL_trydeletechain(inftl=%p,"
 		"thisVUC=%d)\n", inftl, thisVUC);
 		"thisVUC=%d)\n", inftl, thisVUC);
 
 
 	memset(BlockUsed, 0, sizeof(BlockUsed));
 	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 each block in the chain free it and make it available
 	 * for future use. Erase from the oldest unit first.
 	 * 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 (;;) {
 	for (;;) {
 		u16 *prevEUN = &inftl->VUtable[thisVUC];
 		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 the chain is all gone already, we're done */
 		if (thisEUN == BLOCK_NIL) {
 		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;
 			return;
 		}
 		}
 
 
@@ -731,7 +726,7 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
 			thisEUN = *prevEUN;
 			thisEUN = *prevEUN;
 		}
 		}
 
 
-		DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n",
+		pr_debug("Deleting EUN %d from VUC %d\n",
 		      thisEUN, thisVUC);
 		      thisEUN, thisVUC);
 
 
 		if (INFTL_formatblock(inftl, thisEUN) < 0) {
 		if (INFTL_formatblock(inftl, thisEUN) < 0) {
@@ -767,7 +762,7 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
 	size_t retlen;
 	size_t retlen;
 	struct inftl_bci bci;
 	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);
 		"block=%d)\n", inftl, block);
 
 
 	while (thisEUN < inftl->nb_blocks) {
 	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;
 	struct inftl_oob oob;
 	char *p, *pend;
 	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);
 		"buffer=%p)\n", inftl, block, buffer);
 
 
 	/* Is block all zero? */
 	/* Is block all zero? */
@@ -876,7 +871,7 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
 	struct inftl_bci bci;
 	struct inftl_bci bci;
 	size_t retlen;
 	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);
 		"buffer=%p)\n", inftl, block, buffer);
 
 
 	while (thisEUN < inftl->nb_blocks) {
 	while (thisEUN < inftl->nb_blocks) {
@@ -922,7 +917,7 @@ foundit:
 		int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer);
 		int ret = mtd->read(mtd, ptr, SECTORSIZE, &retlen, buffer);
 
 
 		/* Handle corrected bit flips gracefully */
 		/* Handle corrected bit flips gracefully */
-		if (ret < 0 && ret != -EUCLEAN)
+		if (ret < 0 && !mtd_is_bitflip(ret))
 			return -EIO;
 			return -EIO;
 	}
 	}
 	return 0;
 	return 0;

+ 50 - 66
drivers/mtd/inftlmount.c

@@ -53,7 +53,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
 	struct INFTLPartition *ip;
 	struct INFTLPartition *ip;
 	size_t retlen;
 	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
 	 * 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->FormatFlags = le32_to_cpu(mh->FormatFlags);
 		mh->PercentUsed = le32_to_cpu(mh->PercentUsed);
 		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) {
 		if (mh->NoOfBDTLPartitions == 0) {
 			printk(KERN_WARNING "INFTL: Media Header sanity check "
 			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->spareUnits = le32_to_cpu(ip->spareUnits);
 			ip->Reserved0 = le32_to_cpu(ip->Reserved0);
 			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) {
 			if (ip->Reserved0 != ip->firstUnit) {
 				struct erase_info *instr = &inftl->instr;
 				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.
  * 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)
 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;
 	struct mtd_info *mtd = inftl->mbd.mtd;
 	int physblock;
 	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));
 	memset(instr, 0, sizeof(struct erase_info));
 
 
@@ -476,30 +467,30 @@ void INFTL_dumptables(struct INFTLrecord *s)
 {
 {
 	int i;
 	int i;
 
 
-	printk("-------------------------------------------"
+	pr_debug("-------------------------------------------"
 		"----------------------------------\n");
 		"----------------------------------\n");
 
 
-	printk("VUtable[%d] ->", s->nb_blocks);
+	pr_debug("VUtable[%d] ->", s->nb_blocks);
 	for (i = 0; i < s->nb_blocks; i++) {
 	for (i = 0; i < s->nb_blocks; i++) {
 		if ((i % 8) == 0)
 		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");
 		"----------------------------------\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++) {
 	for (i = 0; i <= s->lastEUN; i++) {
 		if ((i % 8) == 0)
 		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");
 		"----------------------------------\n");
 
 
-	printk("INFTL ->\n"
+	pr_debug("INFTL ->\n"
 		"  EraseSize       = %d\n"
 		"  EraseSize       = %d\n"
 		"  h/s/c           = %d/%d/%d\n"
 		"  h/s/c           = %d/%d/%d\n"
 		"  numvunits       = %d\n"
 		"  numvunits       = %d\n"
@@ -513,7 +504,7 @@ void INFTL_dumptables(struct INFTLrecord *s)
 		s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,
 		s->numvunits, s->firstEUN, s->lastEUN, s->numfreeEUNs,
 		s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);
 		s->LastFreeEUN, s->nb_blocks, s->nb_boot_blocks);
 
 
-	printk("\n-------------------------------------------"
+	pr_debug("\n-------------------------------------------"
 		"----------------------------------\n");
 		"----------------------------------\n");
 }
 }
 
 
@@ -521,25 +512,25 @@ void INFTL_dumpVUchains(struct INFTLrecord *s)
 {
 {
 	int logical, block, i;
 	int logical, block, i;
 
 
-	printk("-------------------------------------------"
+	pr_debug("-------------------------------------------"
 		"----------------------------------\n");
 		"----------------------------------\n");
 
 
-	printk("INFTL Virtual Unit Chains:\n");
+	pr_debug("INFTL Virtual Unit Chains:\n");
 	for (logical = 0; logical < s->nb_blocks; logical++) {
 	for (logical = 0; logical < s->nb_blocks; logical++) {
 		block = s->VUtable[logical];
 		block = s->VUtable[logical];
 		if (block > s->nb_blocks)
 		if (block > s->nb_blocks)
 			continue;
 			continue;
-		printk("  LOGICAL %d --> %d ", logical, block);
+		pr_debug("  LOGICAL %d --> %d ", logical, block);
 		for (i = 0; i < s->nb_blocks; i++) {
 		for (i = 0; i < s->nb_blocks; i++) {
 			if (s->PUtable[block] == BLOCK_NIL)
 			if (s->PUtable[block] == BLOCK_NIL)
 				break;
 				break;
 			block = s->PUtable[block];
 			block = s->PUtable[block];
-			printk("%d ", block);
+			pr_debug("%d ", block);
 		}
 		}
-		printk("\n");
+		pr_debug("\n");
 	}
 	}
 
 
-	printk("-------------------------------------------"
+	pr_debug("-------------------------------------------"
 		"----------------------------------\n");
 		"----------------------------------\n");
 }
 }
 
 
@@ -555,7 +546,7 @@ int INFTL_mount(struct INFTLrecord *s)
 	int i;
 	int i;
 	u8 *ANACtable, ANAC;
 	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 */
 	/* Search for INFTL MediaHeader and Spare INFTL Media Header */
 	if (find_boot_record(s) < 0) {
 	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
 	 * NOTEXPLORED state. Then at the end we will try to format it and
 	 * mark it as free.
 	 * 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++) {
 	for (first_block = s->firstEUN; first_block <= s->lastEUN; first_block++) {
 		if (s->PUtable[first_block] != BLOCK_NOTEXPLORED)
 		if (s->PUtable[first_block] != BLOCK_NOTEXPLORED)
 			continue;
 			continue;
@@ -717,17 +708,14 @@ int INFTL_mount(struct INFTLrecord *s)
 		logical_block = BLOCK_NIL;
 		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
 	 * Second pass, check for infinite loops in chains. These are
 	 * possible because we don't update the previous pointers when
 	 * possible because we don't update the previous pointers when
 	 * we fold chains. No big deal, just fix them up in PUtable.
 	 * 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++) {
 	for (logical_block = 0; logical_block < s->numvunits; logical_block++) {
 		block = s->VUtable[logical_block];
 		block = s->VUtable[logical_block];
 		last_block = BLOCK_NIL;
 		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.
 	 * Third pass, format unreferenced blocks and init free block count.
@@ -785,7 +769,7 @@ int INFTL_mount(struct INFTLrecord *s)
 	s->numfreeEUNs = 0;
 	s->numfreeEUNs = 0;
 	s->LastFreeEUN = BLOCK_NIL;
 	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++) {
 	for (block = s->firstEUN; block <= s->lastEUN; block++) {
 		if (s->PUtable[block] == BLOCK_NOTEXPLORED) {
 		if (s->PUtable[block] == BLOCK_NOTEXPLORED) {
 			printk("INFTL: unreferenced block %d, formatting it\n",
 			printk("INFTL: unreferenced block %d, formatting it\n",

+ 0 - 26
drivers/mtd/maps/Kconfig

@@ -41,8 +41,6 @@ config MTD_PHYSMAP_START
 	  are mapped on your particular target board. Refer to the
 	  are mapped on your particular target board. Refer to the
 	  memory map which should hopefully be in the documentation for
 	  memory map which should hopefully be in the documentation for
 	  your board.
 	  your board.
-	  Ignore this option if you use run-time physmap configuration
-	  (i.e., run-time calling physmap_configure()).
 
 
 config MTD_PHYSMAP_LEN
 config MTD_PHYSMAP_LEN
 	hex "Physical length of flash mapping"
 	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
 	  than the total amount of flash present. Refer to the memory
 	  map which should hopefully be in the documentation for your
 	  map which should hopefully be in the documentation for your
 	  board.
 	  board.
-	  Ignore this option if you use run-time physmap configuration
-	  (i.e., run-time calling physmap_configure()).
 
 
 config MTD_PHYSMAP_BANKWIDTH
 config MTD_PHYSMAP_BANKWIDTH
 	int "Bank width in octets"
 	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
 	  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
 	  bits, you would set the bus width octet value to 4. This is
 	  used internally by the CFI drivers.
 	  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
 config MTD_PHYSMAP_OF
 	tristate "Flash device in physical memory map based on OF description"
 	tristate "Flash device in physical memory map based on OF description"
@@ -260,7 +254,6 @@ config MTD_BCM963XX
 config MTD_LANTIQ
 config MTD_LANTIQ
 	tristate "Lantiq SoC NOR support"
 	tristate "Lantiq SoC NOR support"
 	depends on LANTIQ
 	depends on LANTIQ
-	select MTD_PARTITIONS
 	help
 	help
 	  Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
 	  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
 	  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.
 	  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
 config MTD_CDB89712
 	tristate "Cirrus CDB89712 evaluation board mappings"
 	tristate "Cirrus CDB89712 evaluation board mappings"
 	depends on MTD_CFI && ARCH_CDB89712
 	depends on MTD_CFI && ARCH_CDB89712
@@ -398,13 +387,6 @@ config MTD_AUTCPU12
 	  This enables access to the NV-RAM on autronix autcpu12 board.
 	  This enables access to the NV-RAM on autronix autcpu12 board.
 	  If you have such a board, say 'Y'.
 	  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
 config MTD_IMPA7
 	tristate "JEDEC Flash device mapped on impA7"
 	tristate "JEDEC Flash device mapped on impA7"
 	depends on ARM && MTD_JEDECPROBE
 	depends on ARM && MTD_JEDECPROBE
@@ -412,14 +394,6 @@ config MTD_IMPA7
 	  This enables access to the NOR Flash on the impA7 board of
 	  This enables access to the NOR Flash on the impA7 board of
 	  implementa GmbH. If you have such a board, say 'Y' here.
 	  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
 config MTD_H720X
 	tristate "Hynix evaluation board mappings"
 	tristate "Hynix evaluation board mappings"
 	depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
 	depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )

+ 0 - 2
drivers/mtd/maps/Makefile

@@ -19,7 +19,6 @@ obj-$(CONFIG_MTD_CK804XROM)	+= ck804xrom.o
 obj-$(CONFIG_MTD_TSUNAMI)	+= tsunami_flash.o
 obj-$(CONFIG_MTD_TSUNAMI)	+= tsunami_flash.o
 obj-$(CONFIG_MTD_PXA2XX)	+= pxa2xx-flash.o
 obj-$(CONFIG_MTD_PXA2XX)	+= pxa2xx-flash.o
 obj-$(CONFIG_MTD_MBX860)	+= mbx860.o
 obj-$(CONFIG_MTD_MBX860)	+= mbx860.o
-obj-$(CONFIG_MTD_CEIVA)		+= ceiva.o
 obj-$(CONFIG_MTD_OCTAGON)	+= octagon-5066.o
 obj-$(CONFIG_MTD_OCTAGON)	+= octagon-5066.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= physmap.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= physmap.o
 obj-$(CONFIG_MTD_PHYSMAP_OF)	+= physmap_of.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_SOLUTIONENGINE)+= solutionengine.o
 obj-$(CONFIG_MTD_PCI)		+= pci.o
 obj-$(CONFIG_MTD_PCI)		+= pci.o
 obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o
 obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o
-obj-$(CONFIG_MTD_EDB7312)	+= edb7312.o
 obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
 obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
 obj-$(CONFIG_MTD_FORTUNET)	+= fortunet.o
 obj-$(CONFIG_MTD_FORTUNET)	+= fortunet.o
 obj-$(CONFIG_MTD_UCLINUX)	+= uclinux.o
 obj-$(CONFIG_MTD_UCLINUX)	+= uclinux.o

+ 2 - 14
drivers/mtd/maps/bfin-async-flash.c

@@ -41,7 +41,6 @@ struct async_state {
 	uint32_t flash_ambctl0, flash_ambctl1;
 	uint32_t flash_ambctl0, flash_ambctl1;
 	uint32_t save_ambctl0, save_ambctl1;
 	uint32_t save_ambctl0, save_ambctl1;
 	unsigned long irq_flags;
 	unsigned long irq_flags;
-	struct mtd_partition *parts;
 };
 };
 
 
 static void switch_to_flash(struct async_state *state)
 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;
 		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);
 	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);
 	struct async_state *state = platform_get_drvdata(pdev);
 	gpio_free(state->enet_flash_pin);
 	gpio_free(state->enet_flash_pin);
 	mtd_device_unregister(state->mtd);
 	mtd_device_unregister(state->mtd);
-	kfree(state->parts);
 	map_destroy(state->mtd);
 	map_destroy(state->mtd);
 	kfree(state);
 	kfree(state);
 	return 0;
 	return 0;

+ 0 - 341
drivers/mtd/maps/ceiva.c

@@ -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");

+ 1 - 8
drivers/mtd/maps/dc21285.c

@@ -145,14 +145,10 @@ static struct map_info dc21285_map = {
 
 
 
 
 /* Partition stuff */
 /* Partition stuff */
-static struct mtd_partition *dc21285_parts;
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 
 static int __init init_dc21285(void)
 static int __init init_dc21285(void)
 {
 {
-
-	int nrparts;
-
 	/* Determine bankwidth */
 	/* Determine bankwidth */
 	switch (*CSR_SA110_CNTL & (3<<14)) {
 	switch (*CSR_SA110_CNTL & (3<<14)) {
 		case SA110_CNTL_ROMWIDTH_8:
 		case SA110_CNTL_ROMWIDTH_8:
@@ -200,8 +196,7 @@ static int __init init_dc21285(void)
 
 
 	dc21285_mtd->owner = THIS_MODULE;
 	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()) {
 	if(machine_is_ebsa285()) {
 		/*
 		/*
@@ -224,8 +219,6 @@ static int __init init_dc21285(void)
 static void __exit cleanup_dc21285(void)
 static void __exit cleanup_dc21285(void)
 {
 {
 	mtd_device_unregister(dc21285_mtd);
 	mtd_device_unregister(dc21285_mtd);
-	if (dc21285_parts)
-		kfree(dc21285_parts);
 	map_destroy(dc21285_mtd);
 	map_destroy(dc21285_mtd);
 	iounmap(dc21285_map.virt);
 	iounmap(dc21285_map.virt);
 }
 }

+ 0 - 134
drivers/mtd/maps/edb7312.c

@@ -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");

+ 2 - 14
drivers/mtd/maps/gpio-addr-flash.c

@@ -187,7 +187,6 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
  */
  */
 static int __devinit gpio_flash_probe(struct platform_device *pdev)
 static int __devinit gpio_flash_probe(struct platform_device *pdev)
 {
 {
-	int nr_parts;
 	size_t i, arr_size;
 	size_t i, arr_size;
 	struct physmap_flash_data *pdata;
 	struct physmap_flash_data *pdata;
 	struct resource *memory;
 	struct resource *memory;
@@ -252,20 +251,9 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
 		return -ENXIO;
 		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;
 	return 0;
 }
 }

+ 2 - 21
drivers/mtd/maps/h720x-flash.c

@@ -58,18 +58,11 @@ static struct mtd_partition h720x_partitions[] = {
 
 
 #define NUM_PARTITIONS ARRAY_SIZE(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
  * Initialize FLASH support
  */
  */
 static int __init h720x_mtd_init(void)
 static int __init h720x_mtd_init(void)
 {
 {
-
-	char	*part_type = NULL;
-
 	h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
 	h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
 
 
 	if (!h720x_map.virt) {
 	if (!h720x_map.virt) {
@@ -92,16 +85,8 @@ static int __init h720x_mtd_init(void)
 	if (mymtd) {
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
 		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;
 		return 0;
 	}
 	}
 
 
@@ -120,10 +105,6 @@ static void __exit h720x_mtd_cleanup(void)
 		map_destroy(mymtd);
 		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) {
 	if (h720x_map.virt) {
 		iounmap((void *)h720x_map.virt);
 		iounmap((void *)h720x_map.virt);
 		h720x_map.virt = 0;
 		h720x_map.virt = 0;

+ 4 - 24
drivers/mtd/maps/impa7.c

@@ -49,7 +49,7 @@ static struct map_info impa7_map[NUM_FLASHBANKS] = {
 /*
 /*
  * MTD partitioning stuff
  * MTD partitioning stuff
  */
  */
-static struct mtd_partition static_partitions[] =
+static struct mtd_partition partitions[] =
 {
 {
 	{
 	{
 		.name = "FileSystem",
 		.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 int __init init_impa7(void)
 {
 {
 	static const char *rom_probe_types[] = PROBETYPES;
 	static const char *rom_probe_types[] = PROBETYPES;
 	const char **type;
 	const char **type;
-	const char *part_type = 0;
 	int i;
 	int i;
 	static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
 	static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
 	  { WINDOW_ADDR0, WINDOW_SIZE0 },
 	  { WINDOW_ADDR0, WINDOW_SIZE0 },
@@ -97,23 +91,9 @@ static int __init init_impa7(void)
 		if (impa7_mtd[i]) {
 		if (impa7_mtd[i]) {
 			impa7_mtd[i]->owner = THIS_MODULE;
 			impa7_mtd[i]->owner = THIS_MODULE;
 			devicesfound++;
 			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
 		else
 			iounmap((void *)impa7_map[i].virt);
 			iounmap((void *)impa7_map[i].virt);

+ 1 - 6
drivers/mtd/maps/intel_vr_nor.c

@@ -44,7 +44,6 @@ struct vr_nor_mtd {
 	void __iomem *csr_base;
 	void __iomem *csr_base;
 	struct map_info map;
 	struct map_info map;
 	struct mtd_info *info;
 	struct mtd_info *info;
-	int nr_parts;
 	struct pci_dev *dev;
 	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)
 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 */
 	/* register the flash bank */
 	/* partition 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)
 static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)

+ 1 - 10
drivers/mtd/maps/ixp2000.c

@@ -38,7 +38,6 @@
 struct ixp2000_flash_info {
 struct ixp2000_flash_info {
 	struct		mtd_info *mtd;
 	struct		mtd_info *mtd;
 	struct		map_info map;
 	struct		map_info map;
-	struct		mtd_partition *partitions;
 	struct		resource *res;
 	struct		resource *res;
 };
 };
 
 
@@ -125,8 +124,6 @@ static int ixp2000_flash_remove(struct platform_device *dev)
 	if (info->map.map_priv_1)
 	if (info->map.map_priv_1)
 		iounmap((void *) info->map.map_priv_1);
 		iounmap((void *) info->map.map_priv_1);
 
 
-	kfree(info->partitions);
-
 	if (info->res) {
 	if (info->res) {
 		release_resource(info->res);
 		release_resource(info->res);
 		kfree(info->res);
 		kfree(info->res);
@@ -229,13 +226,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
 	}
 	}
 	info->mtd->owner = THIS_MODULE;
 	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)
 	if (err)
 		goto Error;
 		goto Error;
 
 

+ 4 - 25
drivers/mtd/maps/ixp4xx.c

@@ -145,7 +145,6 @@ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
 struct ixp4xx_flash_info {
 struct ixp4xx_flash_info {
 	struct mtd_info *mtd;
 	struct mtd_info *mtd;
 	struct map_info map;
 	struct map_info map;
-	struct mtd_partition *partitions;
 	struct resource *res;
 	struct resource *res;
 };
 };
 
 
@@ -168,8 +167,6 @@ static int ixp4xx_flash_remove(struct platform_device *dev)
 	if (info->map.virt)
 	if (info->map.virt)
 		iounmap(info->map.virt);
 		iounmap(info->map.virt);
 
 
-	kfree(info->partitions);
-
 	if (info->res) {
 	if (info->res) {
 		release_resource(info->res);
 		release_resource(info->res);
 		kfree(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 flash_platform_data *plat = dev->dev.platform_data;
 	struct ixp4xx_flash_info *info;
 	struct ixp4xx_flash_info *info;
-	const char *part_type = NULL;
-	int nr_parts = 0;
 	int err = -1;
 	int err = -1;
 
 
 	if (!plat)
 	if (!plat)
@@ -252,28 +247,12 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 	/* Use the fast version */
 	/* Use the fast version */
 	info->map.write = ixp4xx_write16;
 	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");
 		printk(KERN_ERR "Could not parse partitions\n");
-
-	if (err)
 		goto Error;
 		goto Error;
+	}
 
 
 	return 0;
 	return 0;
 
 

+ 2 - 15
drivers/mtd/maps/lantiq-flash.c

@@ -107,16 +107,12 @@ ltq_copy_to(struct map_info *map, unsigned long to,
 	spin_unlock_irqrestore(&ebu_lock, flags);
 	spin_unlock_irqrestore(&ebu_lock, flags);
 }
 }
 
 
-static const char const *part_probe_types[] = { "cmdlinepart", NULL };
-
 static int __init
 static int __init
 ltq_mtd_probe(struct platform_device *pdev)
 ltq_mtd_probe(struct platform_device *pdev)
 {
 {
 	struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
 	struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
 	struct ltq_mtd *ltq_mtd;
 	struct ltq_mtd *ltq_mtd;
-	struct mtd_partition *parts;
 	struct resource *res;
 	struct resource *res;
-	int nr_parts = 0;
 	struct cfi_private *cfi;
 	struct cfi_private *cfi;
 	int err;
 	int err;
 
 
@@ -172,17 +168,8 @@ ltq_mtd_probe(struct platform_device *pdev)
 	cfi->addr_unlock1 ^= 1;
 	cfi->addr_unlock1 ^= 1;
 	cfi->addr_unlock2 ^= 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) {
 	if (err) {
 		dev_err(&pdev->dev, "failed to add partitions\n");
 		dev_err(&pdev->dev, "failed to add partitions\n");
 		goto err_destroy;
 		goto err_destroy;

+ 2 - 22
drivers/mtd/maps/latch-addr-flash.c

@@ -33,9 +33,6 @@ struct latch_addr_flash_info {
 	/* cache; could be found out of res */
 	/* cache; could be found out of res */
 	unsigned long		win_mask;
 	unsigned long		win_mask;
 
 
-	int			nr_parts;
-	struct mtd_partition	*parts;
-
 	spinlock_t		lock;
 	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 *rom_probe_types[] = { "cfi_probe", NULL };
 
 
-static char *part_probe_types[] = { "cmdlinepart", NULL };
-
 static int latch_addr_flash_remove(struct platform_device *dev)
 static int latch_addr_flash_remove(struct platform_device *dev)
 {
 {
 	struct latch_addr_flash_info *info;
 	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;
 	latch_addr_data = dev->dev.platform_data;
 
 
 	if (info->mtd != NULL) {
 	if (info->mtd != NULL) {
-		if (info->nr_parts)
-			kfree(info->parts);
 		mtd_device_unregister(info->mtd);
 		mtd_device_unregister(info->mtd);
 		map_destroy(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;
 	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;
 	return 0;
 
 
 iounmap:
 iounmap:

+ 52 - 72
drivers/mtd/maps/pcmciamtd.c

@@ -22,22 +22,6 @@
 #include <linux/mtd/map.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.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 info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg)
 
 
 #define DRIVER_DESC	"PCMCIA Flash memory card driver"
 #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;
 	int ret;
 
 
 	if (!pcmcia_dev_present(dev->p_dev)) {
 	if (!pcmcia_dev_present(dev->p_dev)) {
-		DEBUG(1, "device removed");
+		pr_debug("device removed\n");
 		return 0;
 		return 0;
 	}
 	}
 
 
 	offset = to & ~(dev->win_size-1);
 	offset = to & ~(dev->win_size-1);
 	if (offset != dev->offset) {
 	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);
 		      dev->offset, offset);
 		ret = pcmcia_map_mem_page(dev->p_dev, win, offset);
 		ret = pcmcia_map_mem_page(dev->p_dev, win, offset);
 		if (ret != 0)
 		if (ret != 0)
@@ -132,7 +116,7 @@ static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs)
 		return d;
 		return d;
 
 
 	d.x[0] = readb(addr);
 	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;
 	return d;
 }
 }
 
 
@@ -147,7 +131,7 @@ static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs)
 		return d;
 		return d;
 
 
 	d.x[0] = readw(addr);
 	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;
 	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;
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 	unsigned long win_size = dev->win_size;
 	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) {
 	while(len) {
 		int toread = win_size - (from & (win_size-1));
 		int toread = win_size - (from & (win_size-1));
 		caddr_t addr;
 		caddr_t addr;
@@ -169,7 +153,7 @@ static void pcmcia_copy_from_remap(struct map_info *map, void *to, unsigned long
 		if(!addr)
 		if(!addr)
 			return;
 			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);
 		memcpy_fromio(to, addr, toread);
 		len -= toread;
 		len -= toread;
 		to += toread;
 		to += toread;
@@ -185,7 +169,7 @@ static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long
 	if(!addr)
 	if(!addr)
 		return;
 		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);
 	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)
 	if(!addr)
 		return;
 		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);
 	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;
 	struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 	unsigned long win_size = dev->win_size;
 	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) {
 	while(len) {
 		int towrite = win_size - (to & (win_size-1));
 		int towrite = win_size - (to & (win_size-1));
 		caddr_t addr;
 		caddr_t addr;
@@ -218,7 +202,7 @@ static void pcmcia_copy_to_remap(struct map_info *map, unsigned long to, const v
 		if(!addr)
 		if(!addr)
 			return;
 			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);
 		memcpy_toio(addr, from, towrite);
 		len -= towrite;
 		len -= towrite;
 		to += towrite;
 		to += towrite;
@@ -240,7 +224,7 @@ static map_word pcmcia_read8(struct map_info *map, unsigned long ofs)
 		return d;
 		return d;
 
 
 	d.x[0] = readb(win_base + ofs);
 	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]);
 	      ofs, win_base + ofs, d.x[0]);
 	return d;
 	return d;
 }
 }
@@ -255,7 +239,7 @@ static map_word pcmcia_read16(struct map_info *map, unsigned long ofs)
 		return d;
 		return d;
 
 
 	d.x[0] = readw(win_base + ofs);
 	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]);
 	      ofs, win_base + ofs, d.x[0]);
 	return d;
 	return d;
 }
 }
@@ -268,7 +252,7 @@ static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from,
 	if(DEV_REMOVED(map))
 	if(DEV_REMOVED(map))
 		return;
 		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);
 	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))
 	if(DEV_REMOVED(map))
 		return;
 		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]);
 	      adr, win_base + adr, d.x[0]);
 	writeb(d.x[0], win_base + adr);
 	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))
 	if(DEV_REMOVED(map))
 		return;
 		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]);
 	      adr, win_base + adr, d.x[0]);
 	writew(d.x[0], win_base + adr);
 	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))
 	if(DEV_REMOVED(map))
 		return;
 		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);
 	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 pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1;
 	struct pcmcia_device *link = dev->p_dev;
 	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);
 	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;
 	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 (link->resource[2]->end) {
 		if(dev->win_base) {
 		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,
 static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev,
 				tuple_t *tuple,
 				tuple_t *tuple,
 				void *priv_data)
 				void *priv_data)
@@ -347,7 +330,7 @@ static int pcmciamtd_cistpl_format(struct pcmcia_device *p_dev,
 	if (!pcmcia_parse_tuple(tuple, &parse)) {
 	if (!pcmcia_parse_tuple(tuple, &parse)) {
 		cistpl_format_t *t = &parse.format;
 		cistpl_format_t *t = &parse.format;
 		(void)t; /* Shut up, gcc */
 		(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);
 			t->type, t->edc, t->offset, t->length);
 	}
 	}
 	return -ENOSPC;
 	return -ENOSPC;
@@ -363,12 +346,11 @@ static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev,
 	if (!pcmcia_parse_tuple(tuple, &parse)) {
 	if (!pcmcia_parse_tuple(tuple, &parse)) {
 		cistpl_jedec_t *t = &parse.jedec;
 		cistpl_jedec_t *t = &parse.jedec;
 		for (i = 0; i < t->nid; i++)
 		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);
 			      t->id[i].mfr, t->id[i].info);
 	}
 	}
 	return -ENOSPC;
 	return -ENOSPC;
 }
 }
-#endif
 
 
 static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
 static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
 				tuple_t *tuple,
 				tuple_t *tuple,
@@ -382,14 +364,14 @@ static int pcmciamtd_cistpl_device(struct pcmcia_device *p_dev,
 	if (pcmcia_parse_tuple(tuple, &parse))
 	if (pcmcia_parse_tuple(tuple, &parse))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	DEBUG(2, "Common memory:");
+	pr_debug("Common memory:\n");
 	dev->pcmcia_map.size = t->dev[0].size;
 	dev->pcmcia_map.size = t->dev[0].size;
 	/* from here on: DEBUG only */
 	/* from here on: DEBUG only */
 	for (i = 0; i < t->ndev; i++) {
 	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;
 	return 0;
 }
 }
@@ -409,12 +391,12 @@ static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev,
 	dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
 	dev->pcmcia_map.bankwidth = t->geo[0].buswidth;
 	/* from here on: DEBUG only */
 	/* from here on: DEBUG only */
 	for (i = 0; i < t->ngeo; i++) {
 	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;
 	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])
 			if (p_dev->prod_id[i])
 				strcat(dev->mtd_name, 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_FORMAT, pcmciamtd_cistpl_format, NULL);
 	pcmcia_loop_tuple(p_dev, CISTPL_JEDEC_C, pcmciamtd_cistpl_jedec, 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, pcmciamtd_cistpl_device, dev);
 	pcmcia_loop_tuple(p_dev, CISTPL_DEVICE_GEO, pcmciamtd_cistpl_geo, 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) {
 	if(force_size) {
 		dev->pcmcia_map.size = force_size << 20;
 		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) {
 	if(bankwidth) {
 		dev->pcmcia_map.bankwidth = 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;
 	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;
 		*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.size,
 	      dev->pcmcia_map.bankwidth << 3, dev->mtd_name);
 	      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" };
 	static char *probes[] = { "jedec_probe", "cfi_probe" };
 	int new_name = 0;
 	int new_name = 0;
 
 
-	DEBUG(3, "link=0x%p", link);
+	pr_debug("link=0x%p\n", link);
 
 
 	card_settings(dev, link, &new_name);
 	card_settings(dev, link, &new_name);
 
 
@@ -512,11 +492,11 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 
 
 	do {
 	do {
 		int ret;
 		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,
 			(unsigned long) resource_size(link->resource[2]) >> 10,
 			mem_speed);
 			mem_speed);
 		ret = pcmcia_request_window(link, link->resource[2], 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) {
 		if(ret) {
 			j++;
 			j++;
 			link->resource[2]->start = 0;
 			link->resource[2]->start = 0;
@@ -524,21 +504,21 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 					force_size << 20 : MAX_PCMCIA_ADDR;
 					force_size << 20 : MAX_PCMCIA_ADDR;
 			link->resource[2]->end >>= j;
 			link->resource[2]->end >>= j;
 		} else {
 		} 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);
 				resource_size(link->resource[2]) >> 10);
 			dev->win_size = resource_size(link->resource[2]);
 			dev->win_size = resource_size(link->resource[2]);
 			break;
 			break;
 		}
 		}
 	} while (link->resource[2]->end >= 0x1000);
 	} 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) {
 	if(!dev->win_size) {
 		dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
 		dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n");
 		pcmciamtd_release(link);
 		pcmciamtd_release(link);
 		return -ENODEV;
 		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 */
 	/* Get write protect status */
 	dev->win_base = ioremap(link->resource[2]->start,
 	dev->win_base = ioremap(link->resource[2]->start,
@@ -549,7 +529,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 		pcmciamtd_release(link);
 		pcmciamtd_release(link);
 		return -ENODEV;
 		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, link->resource[2], dev->win_base);
 
 
 	dev->offset = 0;
 	dev->offset = 0;
@@ -564,7 +544,7 @@ static int pcmciamtd_config(struct pcmcia_device *link)
 	}
 	}
 
 
 	link->config_index = 0;
 	link->config_index = 0;
-	DEBUG(2, "Setting Configuration");
+	pr_debug("Setting Configuration\n");
 	ret = pcmcia_enable_device(link);
 	ret = pcmcia_enable_device(link);
 	if (ret != 0) {
 	if (ret != 0) {
 		if (dev->win_base) {
 		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);
 		mtd = do_map_probe("map_rom", &dev->pcmcia_map);
 	} else {
 	} else {
 		for(i = 0; i < ARRAY_SIZE(probes); i++) {
 		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);
 			mtd = do_map_probe(probes[i], &dev->pcmcia_map);
 			if(mtd)
 			if(mtd)
 				break;
 				break;
 
 
-			DEBUG(1, "FAILED: %s", probes[i]);
+			pr_debug("FAILED: %s\n", probes[i]);
 		}
 		}
 	}
 	}
 
 
 	if(!mtd) {
 	if(!mtd) {
-		DEBUG(1, "Can not find an MTD");
+		pr_debug("Can not find an MTD\n");
 		pcmciamtd_release(link);
 		pcmciamtd_release(link);
 		return -ENODEV;
 		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,
 	/* If the memory found is fits completely into the mapped PCMCIA window,
 	   use the faster non-remapping read/write functions */
 	   use the faster non-remapping read/write functions */
 	if(mtd->size <= dev->win_size) {
 	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;
 		dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base;
 		if (dev->pcmcia_map.bankwidth == 1) {
 		if (dev->pcmcia_map.bankwidth == 1) {
 			dev->pcmcia_map.read = pcmcia_read8;
 			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)
 static int pcmciamtd_suspend(struct pcmcia_device *dev)
 {
 {
-	DEBUG(2, "EVENT_PM_RESUME");
+	pr_debug("EVENT_PM_RESUME\n");
 
 
 	/* get_lock(link); */
 	/* get_lock(link); */
 
 
@@ -654,7 +634,7 @@ static int pcmciamtd_suspend(struct pcmcia_device *dev)
 
 
 static int pcmciamtd_resume(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); */
 	/* free_lock(link); */
 
 
@@ -666,7 +646,7 @@ static void pcmciamtd_detach(struct pcmcia_device *link)
 {
 {
 	struct pcmciamtd_dev *dev = link->priv;
 	struct pcmciamtd_dev *dev = link->priv;
 
 
-	DEBUG(3, "link=0x%p", link);
+	pr_debug("link=0x%p\n", link);
 
 
 	if(dev->mtd_info) {
 	if(dev->mtd_info) {
 		mtd_device_unregister(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 */
 	/* Create new memory card device */
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev) return -ENOMEM;
 	if (!dev) return -ENOMEM;
-	DEBUG(1, "dev=0x%p", dev);
+	pr_debug("dev=0x%p\n", dev);
 
 
 	dev->p_dev = link;
 	dev->p_dev = link;
 	link->priv = dev;
 	link->priv = dev;
@@ -755,7 +735,7 @@ static int __init init_pcmciamtd(void)
 
 
 static void __exit exit_pcmciamtd(void)
 static void __exit exit_pcmciamtd(void)
 {
 {
-	DEBUG(1, DRIVER_DESC " unloading");
+	pr_debug(DRIVER_DESC " unloading");
 	pcmcia_unregister_driver(&pcmciamtd_driver);
 	pcmcia_unregister_driver(&pcmciamtd_driver);
 }
 }
 
 

+ 2 - 36
drivers/mtd/maps/physmap.c

@@ -27,8 +27,6 @@ struct physmap_flash_info {
 	struct mtd_info		*mtd[MAX_RESOURCES];
 	struct mtd_info		*mtd[MAX_RESOURCES];
 	struct mtd_info		*cmtd;
 	struct mtd_info		*cmtd;
 	struct map_info		map[MAX_RESOURCES];
 	struct map_info		map[MAX_RESOURCES];
-	int			nr_parts;
-	struct mtd_partition	*parts;
 };
 };
 
 
 static int physmap_flash_remove(struct platform_device *dev)
 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) {
 	if (info->cmtd) {
 		mtd_device_unregister(info->cmtd);
 		mtd_device_unregister(info->cmtd);
-		if (info->nr_parts)
-			kfree(info->parts);
 		if (info->cmtd != info->mtd[0])
 		if (info->cmtd != info->mtd[0])
 			mtd_concat_destroy(info->cmtd);
 			mtd_concat_destroy(info->cmtd);
 	}
 	}
@@ -175,23 +171,8 @@ static int physmap_flash_probe(struct platform_device *dev)
 	if (err)
 	if (err)
 		goto err_out;
 		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;
 	return 0;
 
 
 err_out:
 err_out:
@@ -245,21 +226,6 @@ static struct platform_device physmap_flash = {
 	.num_resources	= 1,
 	.num_resources	= 1,
 	.resource	= &physmap_flash_resource,
 	.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
 #endif
 
 
 static int __init physmap_init(void)
 static int __init physmap_init(void)

+ 7 - 73
drivers/mtd/maps/physmap_of.c

@@ -34,58 +34,10 @@ struct of_flash_list {
 
 
 struct of_flash {
 struct of_flash {
 	struct mtd_info		*cmtd;
 	struct mtd_info		*cmtd;
-	struct mtd_partition	*parts;
 	int list_size; /* number of elements in of_flash_list */
 	int list_size; /* number of elements in of_flash_list */
 	struct of_flash_list	list[0];
 	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)
 static int of_flash_remove(struct platform_device *dev)
 {
 {
 	struct of_flash *info;
 	struct of_flash *info;
@@ -101,11 +53,8 @@ static int of_flash_remove(struct platform_device *dev)
 		mtd_concat_destroy(info->cmtd);
 		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);
 		mtd_device_unregister(info->cmtd);
-	}
 
 
 	for (i = 0; i < info->list_size; i++) {
 	for (i = 0; i < info->list_size; i++) {
 		if (info->list[i].mtd)
 		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
    specifies the list of partition probers to use. If none is given then the
    default is use. These take precedence over other device tree
    default is use. These take precedence over other device tree
    information. */
    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)
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 {
 	const char *cp;
 	const char *cp;
@@ -218,6 +168,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	int reg_tuple_size;
 	int reg_tuple_size;
 	struct mtd_info **mtd_list = NULL;
 	struct mtd_info **mtd_list = NULL;
 	resource_size_t res_size;
 	resource_size_t res_size;
+	struct mtd_part_parser_data ppdata;
 
 
 	match = of_match_device(of_flash_match, &dev->dev);
 	match = of_match_device(of_flash_match, &dev->dev);
 	if (!match)
 	if (!match)
@@ -331,29 +282,12 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	if (err)
 	if (err)
 		goto err_out;
 		goto err_out;
 
 
+	ppdata.of_node = dp;
 	part_probe_types = of_get_probes(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);
 	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);
 	kfree(mtd_list);
 
 
 	return 0;
 	return 0;

+ 2 - 21
drivers/mtd/maps/plat-ram.c

@@ -44,8 +44,6 @@ struct platram_info {
 	struct device		*dev;
 	struct device		*dev;
 	struct mtd_info		*mtd;
 	struct mtd_info		*mtd;
 	struct map_info		 map;
 	struct map_info		 map;
-	struct mtd_partition	*partitions;
-	bool			free_partitions;
 	struct resource		*area;
 	struct resource		*area;
 	struct platdata_mtd_ram	*pdata;
 	struct platdata_mtd_ram	*pdata;
 };
 };
@@ -95,10 +93,6 @@ static int platram_remove(struct platform_device *pdev)
 
 
 	if (info->mtd) {
 	if (info->mtd) {
 		mtd_device_unregister(info->mtd);
 		mtd_device_unregister(info->mtd);
-		if (info->partitions) {
-			if (info->free_partitions)
-				kfree(info->partitions);
-		}
 		map_destroy(info->mtd);
 		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
 	/* check to see if there are any available partitions, or wether
 	 * to add this device whole */
 	 * 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)
 	if (!err)
 		dev_info(&pdev->dev, "registered mtd device\n");
 		dev_info(&pdev->dev, "registered mtd device\n");
 
 

+ 1 - 19
drivers/mtd/maps/pxa2xx-flash.c

@@ -41,8 +41,6 @@ static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from,
 }
 }
 
 
 struct pxa2xx_flash_info {
 struct pxa2xx_flash_info {
-	struct mtd_partition	*parts;
-	int			nr_parts;
 	struct mtd_info		*mtd;
 	struct mtd_info		*mtd;
 	struct map_info		map;
 	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 flash_platform_data *flash = pdev->dev.platform_data;
 	struct pxa2xx_flash_info *info;
 	struct pxa2xx_flash_info *info;
-	struct mtd_partition *parts;
 	struct resource *res;
 	struct resource *res;
-	int ret = 0;
 
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
 	if (!res)
@@ -71,8 +67,6 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	info->map.bankwidth = flash->width;
 	info->map.bankwidth = flash->width;
 	info->map.phys = res->start;
 	info->map.phys = res->start;
 	info->map.size = resource_size(res);
 	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);
 	info->map.virt = ioremap(info->map.phys, info->map.size);
 	if (!info->map.virt) {
 	if (!info->map.virt) {
@@ -104,18 +98,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	}
 	}
 	info->mtd->owner = THIS_MODULE;
 	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);
 	platform_set_drvdata(pdev, info);
 	return 0;
 	return 0;
@@ -133,7 +116,6 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
 	iounmap(info->map.virt);
 	iounmap(info->map.virt);
 	if (info->map.cached)
 	if (info->map.cached)
 		iounmap(info->map.cached);
 		iounmap(info->map.cached);
-	kfree(info->parts);
 	kfree(info);
 	kfree(info);
 	return 0;
 	return 0;
 }
 }

+ 4 - 20
drivers/mtd/maps/rbtx4939-flash.c

@@ -25,8 +25,6 @@
 struct rbtx4939_flash_info {
 struct rbtx4939_flash_info {
 	struct mtd_info *mtd;
 	struct mtd_info *mtd;
 	struct map_info map;
 	struct map_info map;
-	int nr_parts;
-	struct mtd_partition *parts;
 };
 };
 
 
 static int rbtx4939_flash_remove(struct platform_device *dev)
 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) {
 	if (info->mtd) {
 		struct rbtx4939_flash_data *pdata = dev->dev.platform_data;
 		struct rbtx4939_flash_data *pdata = dev->dev.platform_data;
 
 
-		if (info->nr_parts)
-			kfree(info->parts);
 		mtd_device_unregister(info->mtd);
 		mtd_device_unregister(info->mtd);
 		map_destroy(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 *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)
 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;
 	info->mtd->owner = THIS_MODULE;
 	if (err)
 	if (err)
 		goto err_out;
 		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;
 	return 0;
 
 
 err_out:
 err_out:

+ 3 - 27
drivers/mtd/maps/sa1100-flash.c

@@ -131,10 +131,8 @@ struct sa_subdev_info {
 };
 };
 
 
 struct sa_info {
 struct sa_info {
-	struct mtd_partition	*parts;
 	struct mtd_info		*mtd;
 	struct mtd_info		*mtd;
 	int			num_subdev;
 	int			num_subdev;
-	unsigned int		nr_parts;
 	struct sa_subdev_info	subdev[0];
 	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);
 			mtd_concat_destroy(info->mtd);
 	}
 	}
 
 
-	kfree(info->parts);
-
 	for (i = info->num_subdev - 1; i >= 0; i--)
 	for (i = info->num_subdev - 1; i >= 0; i--)
 		sa1100_destroy_subdev(&info->subdev[i]);
 		sa1100_destroy_subdev(&info->subdev[i]);
 	kfree(info);
 	kfree(info);
@@ -341,10 +337,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
 static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
 {
 {
 	struct flash_platform_data *plat = pdev->dev.platform_data;
 	struct flash_platform_data *plat = pdev->dev.platform_data;
-	struct mtd_partition *parts;
-	const char *part_type = NULL;
 	struct sa_info *info;
 	struct sa_info *info;
-	int err, nr_parts = 0;
+	int err;
 
 
 	if (!plat)
 	if (!plat)
 		return -ENODEV;
 		return -ENODEV;
@@ -358,26 +352,8 @@ static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
 	/*
 	/*
 	 * Partition selection stuff.
 	 * 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);
 	platform_set_drvdata(pdev, info);
 	err = 0;
 	err = 0;

+ 7 - 23
drivers/mtd/maps/solutionengine.c

@@ -19,8 +19,6 @@
 static struct mtd_info *flash_mtd;
 static struct mtd_info *flash_mtd;
 static struct mtd_info *eprom_mtd;
 static struct mtd_info *eprom_mtd;
 
 
-static struct mtd_partition *parsed_parts;
-
 struct map_info soleng_eprom_map = {
 struct map_info soleng_eprom_map = {
 	.name = "Solution Engine EPROM",
 	.name = "Solution Engine EPROM",
 	.size = 0x400000,
 	.size = 0x400000,
@@ -51,12 +49,14 @@ static struct mtd_partition superh_se_partitions[] = {
 		.size = MTDPART_SIZ_FULL,
 		.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 */
 #endif /* CONFIG_MTD_SUPERH_RESERVE */
 
 
 static int __init init_soleng_maps(void)
 static int __init init_soleng_maps(void)
 {
 {
-	int nr_parts = 0;
-
 	/* First probe at offset 0 */
 	/* First probe at offset 0 */
 	soleng_flash_map.phys = 0;
 	soleng_flash_map.phys = 0;
 	soleng_flash_map.virt = (void __iomem *)P2SEGADDR(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);
 		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;
 	return 0;
 }
 }
@@ -118,10 +105,7 @@ static void __exit cleanup_soleng_maps(void)
 		map_destroy(eprom_mtd);
 		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);
 	map_destroy(flash_mtd);
 }
 }
 
 

+ 13 - 20
drivers/mtd/maps/wr_sbc82xx_flash.c

@@ -20,7 +20,6 @@
 #include <asm/immap_cpm2.h>
 #include <asm/immap_cpm2.h>
 
 
 static struct mtd_info *sbcmtd[3];
 static struct mtd_info *sbcmtd[3];
-static struct mtd_partition *sbcmtd_parts[3];
 
 
 struct map_info sbc82xx_flash_map[3] = {
 struct map_info sbc82xx_flash_map[3] = {
 	{.name = "Boot flash"},
 	{.name = "Boot flash"},
@@ -101,6 +100,7 @@ static int __init init_sbc82xx_flash(void)
 	for (i=0; i<3; i++) {
 	for (i=0; i<3; i++) {
 		int8_t flashcs[3] = { 0, 6, 1 };
 		int8_t flashcs[3] = { 0, 6, 1 };
 		int nr_parts;
 		int nr_parts;
+		struct mtd_partition *defparts;
 
 
 		printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
 		printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
 		       sbc82xx_flash_map[i].name,
 		       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);
 		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) {
 		if (!sbc82xx_flash_map[i].virt) {
 			printk("Failed to ioremap\n");
 			printk("Failed to ioremap\n");
@@ -129,24 +130,20 @@ static int __init init_sbc82xx_flash(void)
 
 
 		sbcmtd[i]->owner = THIS_MODULE;
 		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 */
 		/* No partitioning detected. Use default */
 		if (i == 2) {
 		if (i == 2) {
-			mtd_device_register(sbcmtd[i], NULL, 0);
+			defparts = NULL;
+			nr_parts = 0;
 		} else if (i == bigflash) {
 		} 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 {
 		} 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;
 	return 0;
 }
 }
@@ -159,12 +156,8 @@ static void __exit cleanup_sbc82xx_flash(void)
 		if (!sbcmtd[i])
 		if (!sbcmtd[i])
 			continue;
 			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]);
 		map_destroy(sbcmtd[i]);
 
 
 		iounmap((void *)sbc82xx_flash_map[i].virt);
 		iounmap((void *)sbc82xx_flash_map[i].virt);

+ 2 - 0
drivers/mtd/mtd_blkdevs.c

@@ -426,6 +426,8 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
 	new->rq->queuedata = new;
 	new->rq->queuedata = new;
 	blk_queue_logical_block_size(new->rq, tr->blksize);
 	blk_queue_logical_block_size(new->rq, tr->blksize);
 
 
+	queue_flag_set_unlocked(QUEUE_FLAG_NONROT, new->rq);
+
 	if (tr->discard) {
 	if (tr->discard) {
 		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq);
 		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq);
 		new->rq->limits.max_discard_sectors = UINT_MAX;
 		new->rq->limits.max_discard_sectors = UINT_MAX;

+ 8 - 10
drivers/mtd/mtdblock.c

@@ -44,7 +44,7 @@ struct mtdblk_dev {
 	enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
 	enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
 };
 };
 
 
-static struct mutex mtdblks_lock;
+static DEFINE_MUTEX(mtdblks_lock);
 
 
 /*
 /*
  * Cache stuff...
  * Cache stuff...
@@ -119,7 +119,7 @@ static int write_cached_data (struct mtdblk_dev *mtdblk)
 	if (mtdblk->cache_state != STATE_DIRTY)
 	if (mtdblk->cache_state != STATE_DIRTY)
 		return 0;
 		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,
 			"at 0x%lx, size 0x%x\n", mtd->name,
 			mtdblk->cache_offset, mtdblk->cache_size);
 			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;
 	size_t retlen;
 	int ret;
 	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);
 		mtd->name, pos, len);
 
 
 	if (!sect_size)
 	if (!sect_size)
@@ -218,7 +218,7 @@ static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos,
 	size_t retlen;
 	size_t retlen;
 	int ret;
 	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);
 			mtd->name, pos, len);
 
 
 	if (!sect_size)
 	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);
 	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);
 	mutex_lock(&mtdblks_lock);
 	if (mtdblk->count) {
 	if (mtdblk->count) {
@@ -303,7 +303,7 @@ static int mtdblock_open(struct mtd_blktrans_dev *mbd)
 
 
 	mutex_unlock(&mtdblks_lock);
 	mutex_unlock(&mtdblks_lock);
 
 
-	DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
+	pr_debug("ok\n");
 
 
 	return 0;
 	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);
 	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);
 	mutex_lock(&mtdblks_lock);
 
 
@@ -329,7 +329,7 @@ static int mtdblock_release(struct mtd_blktrans_dev *mbd)
 
 
 	mutex_unlock(&mtdblks_lock);
 	mutex_unlock(&mtdblks_lock);
 
 
-	DEBUG(MTD_DEBUG_LEVEL1, "ok\n");
+	pr_debug("ok\n");
 
 
 	return 0;
 	return 0;
 }
 }
@@ -389,8 +389,6 @@ static struct mtd_blktrans_ops mtdblock_tr = {
 
 
 static int __init init_mtdblock(void)
 static int __init init_mtdblock(void)
 {
 {
-	mutex_init(&mtdblks_lock);
-
 	return register_mtd_blktrans(&mtdblock_tr);
 	return register_mtd_blktrans(&mtdblock_tr);
 }
 }
 
 

+ 120 - 42
drivers/mtd/mtdchar.c

@@ -43,7 +43,7 @@ static struct vfsmount *mtd_inode_mnt __read_mostly;
 
 
 /*
 /*
  * Data structure to hold the pointer to the mtd device as well
  * 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_file_info {
 	struct mtd_info *mtd;
 	struct mtd_info *mtd;
@@ -86,7 +86,7 @@ static int mtd_open(struct inode *inode, struct file *file)
 	struct mtd_file_info *mfi;
 	struct mtd_file_info *mfi;
 	struct inode *mtd_ino;
 	struct inode *mtd_ino;
 
 
-	DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n");
+	pr_debug("MTD_open\n");
 
 
 	/* You can't open the RO devices RW */
 	/* You can't open the RO devices RW */
 	if ((file->f_mode & FMODE_WRITE) && (minor & 1))
 	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_file_info *mfi = file->private_data;
 	struct mtd_info *mtd = mfi->mtd;
 	struct mtd_info *mtd = mfi->mtd;
 
 
-	DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n");
+	pr_debug("MTD_close\n");
 
 
 	/* Only sync if opened RW */
 	/* Only sync if opened RW */
 	if ((file->f_mode & FMODE_WRITE) && mtd->sync)
 	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;
 	size_t size = count;
 	char *kbuf;
 	char *kbuf;
 
 
-	DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n");
+	pr_debug("MTD_read\n");
 
 
 	if (*ppos + count > mtd->size)
 	if (*ppos + count > mtd->size)
 		count = mtd->size - *ppos;
 		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);
 		len = min_t(size_t, count, size);
 
 
 		switch (mfi->mode) {
 		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);
 			ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			break;
 			break;
-		case MTD_MODE_OTP_USER:
+		case MTD_FILE_MODE_OTP_USER:
 			ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			break;
 			break;
-		case MTD_MODE_RAW:
+		case MTD_FILE_MODE_RAW:
 		{
 		{
 			struct mtd_oob_ops ops;
 			struct mtd_oob_ops ops;
 
 
-			ops.mode = MTD_OOB_RAW;
+			ops.mode = MTD_OPS_RAW;
 			ops.datbuf = kbuf;
 			ops.datbuf = kbuf;
 			ops.oobbuf = NULL;
 			ops.oobbuf = NULL;
 			ops.len = len;
 			ops.len = len;
@@ -233,16 +233,16 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
 		default:
 		default:
 			ret = mtd->read(mtd, *ppos, len, &retlen, kbuf);
 			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
 		 * 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
 		 * For kernel internal usage it also might return -EUCLEAN
 		 * to signal the caller that a bitflip has occurred and has
 		 * to signal the caller that a bitflip has occurred and has
 		 * been corrected by the ECC algorithm.
 		 * been corrected by the ECC algorithm.
 		 * Userspace software which accesses NAND this way
 		 * Userspace software which accesses NAND this way
 		 * must be aware of the fact that it deals with NAND
 		 * 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;
 			*ppos += retlen;
 			if (copy_to_user(buf, kbuf, retlen)) {
 			if (copy_to_user(buf, kbuf, retlen)) {
 				kfree(kbuf);
 				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 ret=0;
 	int len;
 	int len;
 
 
-	DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n");
+	pr_debug("MTD_write\n");
 
 
 	if (*ppos == mtd->size)
 	if (*ppos == mtd->size)
 		return -ENOSPC;
 		return -ENOSPC;
@@ -302,10 +302,10 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
 		}
 		}
 
 
 		switch (mfi->mode) {
 		switch (mfi->mode) {
-		case MTD_MODE_OTP_FACTORY:
+		case MTD_FILE_MODE_OTP_FACTORY:
 			ret = -EROFS;
 			ret = -EROFS;
 			break;
 			break;
-		case MTD_MODE_OTP_USER:
+		case MTD_FILE_MODE_OTP_USER:
 			if (!mtd->write_user_prot_reg) {
 			if (!mtd->write_user_prot_reg) {
 				ret = -EOPNOTSUPP;
 				ret = -EOPNOTSUPP;
 				break;
 				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);
 			ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf);
 			break;
 			break;
 
 
-		case MTD_MODE_RAW:
+		case MTD_FILE_MODE_RAW:
 		{
 		{
 			struct mtd_oob_ops ops;
 			struct mtd_oob_ops ops;
 
 
-			ops.mode = MTD_OOB_RAW;
+			ops.mode = MTD_OPS_RAW;
 			ops.datbuf = kbuf;
 			ops.datbuf = kbuf;
 			ops.oobbuf = NULL;
 			ops.oobbuf = NULL;
+			ops.ooboffs = 0;
 			ops.len = len;
 			ops.len = len;
 
 
 			ret = mtd->write_oob(mtd, *ppos, &ops);
 			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)
 		if (!mtd->read_fact_prot_reg)
 			ret = -EOPNOTSUPP;
 			ret = -EOPNOTSUPP;
 		else
 		else
-			mfi->mode = MTD_MODE_OTP_FACTORY;
+			mfi->mode = MTD_FILE_MODE_OTP_FACTORY;
 		break;
 		break;
 	case MTD_OTP_USER:
 	case MTD_OTP_USER:
 		if (!mtd->read_fact_prot_reg)
 		if (!mtd->read_fact_prot_reg)
 			ret = -EOPNOTSUPP;
 			ret = -EOPNOTSUPP;
 		else
 		else
-			mfi->mode = MTD_MODE_OTP_USER;
+			mfi->mode = MTD_FILE_MODE_OTP_USER;
 		break;
 		break;
 	default:
 	default:
 		ret = -EINVAL;
 		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,
 	uint64_t start, uint32_t length, void __user *ptr,
 	uint32_t __user *retp)
 	uint32_t __user *retp)
 {
 {
+	struct mtd_file_info *mfi = file->private_data;
 	struct mtd_oob_ops ops;
 	struct mtd_oob_ops ops;
 	uint32_t retlen;
 	uint32_t retlen;
 	int ret = 0;
 	int ret = 0;
@@ -409,9 +411,10 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
 		return ret;
 		return ret;
 
 
 	ops.ooblen = length;
 	ops.ooblen = length;
-	ops.ooboffs = start & (mtd->oobsize - 1);
+	ops.ooboffs = start & (mtd->writesize - 1);
 	ops.datbuf = NULL;
 	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))
 	if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
 		return -EINVAL;
 		return -EINVAL;
@@ -420,7 +423,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
 	if (IS_ERR(ops.oobbuf))
 	if (IS_ERR(ops.oobbuf))
 		return PTR_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);
 	ret = mtd->write_oob(mtd, start, &ops);
 
 
 	if (ops.oobretlen > 0xFFFFFFFFU)
 	if (ops.oobretlen > 0xFFFFFFFFU)
@@ -433,9 +436,11 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
 	return ret;
 	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;
 	struct mtd_oob_ops ops;
 	int ret = 0;
 	int ret = 0;
 
 
@@ -451,9 +456,10 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
 		return ret;
 		return ret;
 
 
 	ops.ooblen = length;
 	ops.ooblen = length;
-	ops.ooboffs = start & (mtd->oobsize - 1);
+	ops.ooboffs = start & (mtd->writesize - 1);
 	ops.datbuf = NULL;
 	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))
 	if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs))
 		return -EINVAL;
 		return -EINVAL;
@@ -462,7 +468,7 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
 	if (!ops.oobbuf)
 	if (!ops.oobbuf)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
-	start &= ~((uint64_t)mtd->oobsize - 1);
+	start &= ~((uint64_t)mtd->writesize - 1);
 	ret = mtd->read_oob(mtd, start, &ops);
 	ret = mtd->read_oob(mtd, start, &ops);
 
 
 	if (put_user(ops.oobretlen, retp))
 	if (put_user(ops.oobretlen, retp))
@@ -472,13 +478,29 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
 		ret = -EFAULT;
 		ret = -EFAULT;
 
 
 	kfree(ops.oobbuf);
 	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;
 	return ret;
 }
 }
 
 
 /*
 /*
  * Copies (and truncates, if necessary) data from the larger struct,
  * Copies (and truncates, if necessary) data from the larger struct,
  * nand_ecclayout, to the smaller, deprecated layout 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
  * API ioctl ECCGETLAYOUT while allowing all new functionality to use
  * nand_ecclayout flexibly (i.e. the struct may change size in new
  * nand_ecclayout flexibly (i.e. the struct may change size in new
  * releases without requiring major rewrites).
  * 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)
 static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 {
 {
 	struct mtd_file_info *mfi = file->private_data;
 	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;
 	u_long size;
 	struct mtd_info_user info;
 	struct mtd_info_user info;
 
 
-	DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n");
+	pr_debug("MTD_ioctl\n");
 
 
 	size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
 	size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
 	if (cmd & IOC_IN) {
 	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.erasesize	= mtd->erasesize;
 		info.writesize	= mtd->writesize;
 		info.writesize	= mtd->writesize;
 		info.oobsize	= mtd->oobsize;
 		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)))
 		if (copy_to_user(argp, &info, sizeof(struct mtd_info_user)))
 			return -EFAULT;
 			return -EFAULT;
 		break;
 		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)))
 		if (copy_from_user(&buf, argp, sizeof(buf)))
 			ret = -EFAULT;
 			ret = -EFAULT;
 		else
 		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);
 				buf.ptr, &buf_user->start);
 		break;
 		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)))
 		if (copy_from_user(&buf, argp, sizeof(buf)))
 			ret = -EFAULT;
 			ret = -EFAULT;
 		else
 		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,
 				(void __user *)(uintptr_t)buf.usr_ptr,
 				&buf_user->length);
 				&buf_user->length);
 		break;
 		break;
 	}
 	}
 
 
+	case MEMWRITE:
+	{
+		ret = mtd_write_ioctl(mtd,
+		      (struct mtd_write_req __user *)arg);
+		break;
+	}
+
 	case MEMLOCK:
 	case MEMLOCK:
 	{
 	{
 		struct erase_info_user einfo;
 		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)))
 		if (copy_from_user(&mode, argp, sizeof(int)))
 			return -EFAULT;
 			return -EFAULT;
 
 
-		mfi->mode = MTD_MODE_NORMAL;
+		mfi->mode = MTD_FILE_MODE_NORMAL;
 
 
 		ret = otp_select_filemode(mfi, mode);
 		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;
 			return -ENOMEM;
 		ret = -EOPNOTSUPP;
 		ret = -EOPNOTSUPP;
 		switch (mfi->mode) {
 		switch (mfi->mode) {
-		case MTD_MODE_OTP_FACTORY:
+		case MTD_FILE_MODE_OTP_FACTORY:
 			if (mtd->get_fact_prot_info)
 			if (mtd->get_fact_prot_info)
 				ret = mtd->get_fact_prot_info(mtd, buf, 4096);
 				ret = mtd->get_fact_prot_info(mtd, buf, 4096);
 			break;
 			break;
-		case MTD_MODE_OTP_USER:
+		case MTD_FILE_MODE_OTP_USER:
 			if (mtd->get_user_prot_info)
 			if (mtd->get_user_prot_info)
 				ret = mtd->get_user_prot_info(mtd, buf, 4096);
 				ret = mtd->get_user_prot_info(mtd, buf, 4096);
 			break;
 			break;
@@ -871,7 +949,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 	{
 	{
 		struct otp_info oinfo;
 		struct otp_info oinfo;
 
 
-		if (mfi->mode != MTD_MODE_OTP_USER)
+		if (mfi->mode != MTD_FILE_MODE_OTP_USER)
 			return -EINVAL;
 			return -EINVAL;
 		if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
 		if (copy_from_user(&oinfo, argp, sizeof(oinfo)))
 			return -EFAULT;
 			return -EFAULT;
@@ -882,7 +960,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 	}
 	}
 #endif
 #endif
 
 
-	/* This ioctl is being deprecated - it truncates the ecc layout */
+	/* This ioctl is being deprecated - it truncates the ECC layout */
 	case ECCGETLAYOUT:
 	case ECCGETLAYOUT:
 	{
 	{
 		struct nand_ecclayout_user *usrlay;
 		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;
 		mfi->mode = 0;
 
 
 		switch(arg) {
 		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);
 			ret = otp_select_filemode(mfi, arg);
 			break;
 			break;
 
 
-		case MTD_MODE_RAW:
+		case MTD_FILE_MODE_RAW:
 			if (!mtd->read_oob || !mtd->write_oob)
 			if (!mtd->read_oob || !mtd->write_oob)
 				return -EOPNOTSUPP;
 				return -EOPNOTSUPP;
 			mfi->mode = arg;
 			mfi->mode = arg;
 
 
-		case MTD_MODE_NORMAL:
+		case MTD_FILE_MODE_NORMAL:
 			break;
 			break;
 		default:
 		default:
 			ret = -EINVAL;
 			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)))
 		if (copy_from_user(&buf, argp, sizeof(buf)))
 			ret = -EFAULT;
 			ret = -EFAULT;
 		else
 		else
-			ret = mtd_do_readoob(mtd, buf.start,
+			ret = mtd_do_readoob(file, mtd, buf.start,
 				buf.length, compat_ptr(buf.ptr),
 				buf.length, compat_ptr(buf.ptr),
 				&buf_user->start);
 				&buf_user->start);
 		break;
 		break;

+ 5 - 5
drivers/mtd/mtdconcat.c

@@ -95,10 +95,10 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len,
 
 
 		/* Save information about bitflips! */
 		/* Save information about bitflips! */
 		if (unlikely(err)) {
 		if (unlikely(err)) {
-			if (err == -EBADMSG) {
+			if (mtd_is_eccerr(err)) {
 				mtd->ecc_stats.failed++;
 				mtd->ecc_stats.failed++;
 				ret = err;
 				ret = err;
-			} else if (err == -EUCLEAN) {
+			} else if (mtd_is_bitflip(err)) {
 				mtd->ecc_stats.corrected++;
 				mtd->ecc_stats.corrected++;
 				/* Do not overwrite -EBADMSG !! */
 				/* Do not overwrite -EBADMSG !! */
 				if (!ret)
 				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! */
 		/* Save information about bitflips! */
 		if (unlikely(err)) {
 		if (unlikely(err)) {
-			if (err == -EBADMSG) {
+			if (mtd_is_eccerr(err)) {
 				mtd->ecc_stats.failed++;
 				mtd->ecc_stats.failed++;
 				ret = err;
 				ret = err;
-			} else if (err == -EUCLEAN) {
+			} else if (mtd_is_bitflip(err)) {
 				mtd->ecc_stats.corrected++;
 				mtd->ecc_stats.corrected++;
 				/* Do not overwrite -EBADMSG !! */
 				/* Do not overwrite -EBADMSG !! */
 				if (!ret)
 				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
 	 * 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.type = subdev[0]->type;
 	concat->mtd.flags = subdev[0]->flags;
 	concat->mtd.flags = subdev[0]->flags;

+ 53 - 17
drivers/mtd/mtdcore.c

@@ -362,7 +362,7 @@ int add_mtd_device(struct mtd_info *mtd)
 			      MTD_DEVT(i) + 1,
 			      MTD_DEVT(i) + 1,
 			      NULL, "mtd%dro", i);
 			      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
 	/* No need to get a refcount on the module containing
 	   the notifier, since we hold the mtd_table_mutex */
 	   the notifier, since we hold the mtd_table_mutex */
 	list_for_each_entry(not, &mtd_notifiers, list)
 	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.
  * mtd_device_unregister - unregister an existing MTD device.

+ 3 - 0
drivers/mtd/mtdcore.h

@@ -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 *,
 extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *,
 			      int);
 			      int);
 extern int del_mtd_partitions(struct mtd_info *);
 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)			\
 #define mtd_for_each_device(mtd)			\
 	for ((mtd) = __mtd_next_device(0);		\
 	for ((mtd) = __mtd_next_device(0);		\

+ 1 - 1
drivers/mtd/mtdoops.c

@@ -258,7 +258,7 @@ static void find_next_position(struct mtdoops_context *cxt)
 		ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE,
 		ret = mtd->read(mtd, page * record_size, MTDOOPS_HEADER_SIZE,
 				&retlen, (u_char *) &count[0]);
 				&retlen, (u_char *) &count[0]);
 		if (retlen != MTDOOPS_HEADER_SIZE ||
 		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",
 			printk(KERN_ERR "mtdoops: read failure at %ld (%td of %d read), err %d\n",
 			       page * record_size, retlen,
 			       page * record_size, retlen,
 			       MTDOOPS_HEADER_SIZE, ret);
 			       MTDOOPS_HEADER_SIZE, ret);

+ 54 - 8
drivers/mtd/mtdpart.c

@@ -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,
 	res = part->master->read(part->master, from + part->offset,
 				   len, retlen, buf);
 				   len, retlen, buf);
 	if (unlikely(res)) {
 	if (unlikely(res)) {
-		if (res == -EUCLEAN)
+		if (mtd_is_bitflip(res))
 			mtd->ecc_stats.corrected += part->master->ecc_stats.corrected - stats.corrected;
 			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;
 			mtd->ecc_stats.failed += part->master->ecc_stats.failed - stats.failed;
 	}
 	}
 	return res;
 	return res;
@@ -130,7 +130,7 @@ static int part_read_oob(struct mtd_info *mtd, loff_t from,
 	if (ops->oobbuf) {
 	if (ops->oobbuf) {
 		size_t len, pages;
 		size_t len, pages;
 
 
-		if (ops->mode == MTD_OOB_AUTO)
+		if (ops->mode == MTD_OPS_AUTO_OOB)
 			len = mtd->oobavail;
 			len = mtd->oobavail;
 		else
 		else
 			len = mtd->oobsize;
 			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);
 	res = part->master->read_oob(part->master, from + part->offset, ops);
 	if (unlikely(res)) {
 	if (unlikely(res)) {
-		if (res == -EUCLEAN)
+		if (mtd_is_bitflip(res))
 			mtd->ecc_stats.corrected++;
 			mtd->ecc_stats.corrected++;
-		if (res == -EBADMSG)
+		if (mtd_is_eccerr(res))
 			mtd->ecc_stats.failed++;
 			mtd->ecc_stats.failed++;
 	}
 	}
 	return res;
 	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);
 			       (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)
 	if (slave->mtd.size == MTDPART_SIZ_FULL)
 		slave->mtd.size = master->size - slave->offset;
 		slave->mtd.size = master->size - slave->offset;
 
 
@@ -693,6 +706,8 @@ static struct mtd_part_parser *get_partition_parser(const char *name)
 	return ret;
 	return ret;
 }
 }
 
 
+#define put_partition_parser(p) do { module_put((p)->owner); } while (0)
+
 int register_mtd_parser(struct mtd_part_parser *p)
 int register_mtd_parser(struct mtd_part_parser *p)
 {
 {
 	spin_lock(&part_parser_lock);
 	spin_lock(&part_parser_lock);
@@ -712,19 +727,51 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
 }
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 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,
 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;
 	struct mtd_part_parser *parser;
 	int ret = 0;
 	int ret = 0;
 
 
+	if (!types)
+		types = default_mtd_part_types;
+
 	for ( ; ret <= 0 && *types; types++) {
 	for ( ; ret <= 0 && *types; types++) {
 		parser = get_partition_parser(*types);
 		parser = get_partition_parser(*types);
 		if (!parser && !request_module("%s", *types))
 		if (!parser && !request_module("%s", *types))
 				parser = get_partition_parser(*types);
 				parser = get_partition_parser(*types);
 		if (!parser)
 		if (!parser)
 			continue;
 			continue;
-		ret = (*parser->parse_fn)(master, pparts, origin);
+		ret = (*parser->parse_fn)(master, pparts, data);
 		if (ret > 0) {
 		if (ret > 0) {
 			printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
 			printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
 			       ret, parser->name, master->name);
 			       ret, parser->name, master->name);
@@ -733,7 +780,6 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
 	}
 	}
 	return ret;
 	return ret;
 }
 }
-EXPORT_SYMBOL_GPL(parse_mtd_partitions);
 
 
 int mtd_is_partition(struct mtd_info *mtd)
 int mtd_is_partition(struct mtd_info *mtd)
 {
 {

Some files were not shown because too many files changed in this diff