Merge tag 'for-linus-20121219' of git://git.infradead.org/linux-mtd
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 19 Dec 2012 20:47:41 +0000 (12:47 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 19 Dec 2012 20:47:41 +0000 (12:47 -0800)
Pull MTD updates from David Woodhouse:
 - Various cleanups especially in NAND tests
 - Add support for NAND flash on BCMA bus
 - DT support for sh_flctl and denali NAND drivers
 - Kill obsolete/superceded drivers (fortunet, nomadik_nand)
 - Fix JFFS2 locking bug in ENOMEM failure path
 - New SPI flash chips, as usual
 - Support writing in 'reliable mode' for DiskOnChip G4
 - Debugfs support in nandsim

* tag 'for-linus-20121219' of git://git.infradead.org/linux-mtd: (96 commits)
  mtd: nand: typo in nand_id_has_period() comments
  mtd: nand/gpio: use io{read,write}*_rep accessors
  mtd: block2mtd: throttle writes by calling balance_dirty_pages_ratelimited.
  mtd: nand: gpmi: reset BCH earlier, too, to avoid NAND startup problems
  mtd: nand/docg4: fix and improve read of factory bbt
  mtd: nand/docg4: reserve bb marker area in ecclayout
  mtd: nand/docg4: add support for writing in reliable mode
  mtd: mxc_nand: reorder part_probes to let cmdline override other sources
  mtd: mxc_nand: fix unbalanced clk_disable() in error path
  mtd: nandsim: Introduce debugfs infrastructure
  mtd: physmap_of: error checking to prevent a NULL pointer dereference
  mtg: docg3: potential divide by zero in doc_write_oob()
  mtd: bcm47xxnflash: writing support
  mtd: tests/read: initialize buffer for whole next page
  mtd: at91: atmel_nand: return bit flips for the PMECC read_page()
  mtd: fix recovery after failed write-buffer operation in cfi_cmdset_0002.c
  mtd: nand: onfi need to be probed in 8 bits mode
  mtd: nand: add NAND_BUSWIDTH_AUTO to autodetect bus width
  mtd: nand: print flash size during detection
  mted: nand_wait_ready timeout fix
  ...

21 files changed:
1  2 
Documentation/devicetree/bindings/arm/davinci/nand.txt
arch/arm/boot/dts/spear13xx.dtsi
arch/arm/boot/dts/spear300.dtsi
arch/arm/boot/dts/spear310.dtsi
arch/arm/boot/dts/spear320.dtsi
arch/arm/boot/dts/spear600.dtsi
arch/arm/mach-nomadik/board-nhk8815.c
arch/arm/mach-u300/core.c
drivers/bcma/driver_chipcommon_pmu.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/mxc_nand.c
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/s3c2410.c
drivers/mtd/nand/sh_flctl.c
drivers/mtd/onenand/omap2.c
include/linux/bcma/bcma.h

@@@ -23,16 -23,37 +23,24 @@@ Recommended properties 
  - ti,davinci-nand-buswidth: buswidth 8 or 16
  - ti,davinci-nand-use-bbt: use flash based bad block table support.
  
 -Example (enbw_cmc board):
 -aemif@60000000 {
 -      compatible = "ti,davinci-aemif";
 -      #address-cells = <2>;
 -      #size-cells = <1>;
 -      reg = <0x68000000 0x80000>;
 -      ranges = <2 0 0x60000000 0x02000000
 -                3 0 0x62000000 0x02000000
 -                4 0 0x64000000 0x02000000
 -                5 0 0x66000000 0x02000000
 -                6 0 0x68000000 0x02000000>;
 -      nand@3,0 {
 -              compatible = "ti,davinci-nand";
 -              reg = <3 0x0 0x807ff
 -                      6 0x0 0x8000>;
 -              #address-cells = <1>;
 -              #size-cells = <1>;
 -              ti,davinci-chipselect = <1>;
 -              ti,davinci-mask-ale = <0>;
 -              ti,davinci-mask-cle = <0>;
 -              ti,davinci-mask-chipsel = <0>;
 -              ti,davinci-ecc-mode = "hw";
 -              ti,davinci-ecc-bits = <4>;
 -              ti,davinci-nand-use-bbt;
+ nand device bindings may contain additional sub-nodes describing
+ partitions of the address space. See partition.txt for more detail.
 -              partition@180000 {
 -                      label = "ubifs";
 -                      reg = <0x180000 0x7e80000>;
 -              };
 +Example(da850 EVM ):
 +nand_cs3@62000000 {
 +      compatible = "ti,davinci-nand";
 +      reg = <0x62000000 0x807ff
 +              0x68000000 0x8000>;
 +      ti,davinci-chipselect = <1>;
 +      ti,davinci-mask-ale = <0>;
 +      ti,davinci-mask-cle = <0>;
 +      ti,davinci-mask-chipsel = <0>;
 +      ti,davinci-ecc-mode = "hw";
 +      ti,davinci-ecc-bits = <4>;
 +      ti,davinci-nand-use-bbt;
++      partition@180000 {
++              label = "ubifs";
++              reg = <0x180000 0x7e80000>;
+       };
  };
                bootargs = "console=ttyAMA0,115200";
        };
  
-               status = "disable";
 +      cpufreq {
 +              compatible = "st,cpufreq-spear";
 +              cpufreq_tbl = < 166000
 +                              200000
 +                              250000
 +                              300000
 +                              400000
 +                              500000
 +                              600000 >;
++              status = "disabled";
 +      };
 +
        ahb {
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "simple-bus";
                ranges = <0x50000000 0x50000000 0x10000000
                          0xb0000000 0xb0000000 0x10000000
 +                        0xd0000000 0xd0000000 0x02000000
 +                        0xd8000000 0xd8000000 0x01000000
                          0xe0000000 0xe0000000 0x10000000>;
  
                sdhci@b3000000 {
@@@ -95,7 -81,7 +95,7 @@@
  
                cf@b2800000 {
                        compatible = "arasan,cf-spear1340";
 -                      reg = <0xb2800000 0x100>;
 +                      reg = <0xb2800000 0x1000>;
                        interrupts = <0 29 0x4>;
                        status = "disabled";
                };
                        compatible = "st,spear600-fsmc-nand";
                        #address-cells = <1>;
                        #size-cells = <1>;
-                       reg = <0xb0000000 0x1000        /* FSMC Register */
-                              0xb0800000 0x0010>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
+                       reg = <0xb0000000 0x1000        /* FSMC Register*/
+                              0xb0800000 0x0010        /* NAND Base DATA */
+                              0xb0820000 0x0010        /* NAND Base ADDR */
+                              0xb0810000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        interrupts = <0 20 0x4
                                      0 21 0x4
                                      0 22 0x4
                                      0 23 0x4>;
-                       st,ale-off = <0x20000>;
-                       st,cle-off = <0x10000>;
 +                      st,mode = <2>;
                        status = "disabled";
                };
  
                        status = "disabled";
                };
  
-                       status = "disable";
 +              pcm {
 +                      compatible = "st,pcm-audio";
 +                      #address-cells = <0>;
 +                      #size-cells = <0>;
++                      status = "disabled";
 +              };
 +
                smi: flash@ea000000 {
                        compatible = "st,spear600-smi";
                        #address-cells = <1>;
                        status = "disabled";
                };
  
 -              spi0: spi@e0100000 {
 -                      compatible = "arm,pl022", "arm,primecell";
 -                      reg = <0xe0100000 0x1000>;
 -                      interrupts = <0 31 0x4>;
 -                      status = "disabled";
 -              };
 -
                ehci@e4800000 {
                        compatible = "st,spear600-ehci", "usb-ehci";
                        reg = <0xe4800000 0x1000>;
                        interrupts = <0 64 0x4>;
 +                      usbh0_id = <0>;
                        status = "disabled";
                };
  
                        compatible = "st,spear600-ehci", "usb-ehci";
                        reg = <0xe5800000 0x1000>;
                        interrupts = <0 66 0x4>;
 +                      usbh1_id = <1>;
                        status = "disabled";
                };
  
                        compatible = "st,spear600-ohci", "usb-ohci";
                        reg = <0xe4000000 0x1000>;
                        interrupts = <0 65 0x4>;
 +                      usbh0_id = <0>;
                        status = "disabled";
                };
  
                        compatible = "st,spear600-ohci", "usb-ohci";
                        reg = <0xe5000000 0x1000>;
                        interrupts = <0 67 0x4>;
 +                      usbh1_id = <1>;
                        status = "disabled";
                };
  
                        compatible = "simple-bus";
                        ranges = <0x50000000 0x50000000 0x10000000
                                  0xb0000000 0xb0000000 0x10000000
 +                                0xd0000000 0xd0000000 0x02000000
 +                                0xd8000000 0xd8000000 0x01000000
                                  0xe0000000 0xe0000000 0x10000000>;
  
                        gpio0: gpio@e0600000 {
                                status = "disabled";
                        };
  
 +                      i2s@e0180000 {
 +                              compatible = "st,designware-i2s";
 +                              reg = <0xe0180000 0x1000>;
 +                              interrupt-names = "play_irq", "record_irq";
 +                              interrupts = <0 10 0x4
 +                                            0 11 0x4 >;
 +                              status = "disabled";
 +                      };
 +
 +                      i2s@e0200000 {
 +                              compatible = "st,designware-i2s";
 +                              reg = <0xe0200000 0x1000>;
 +                              interrupt-names = "play_irq", "record_irq";
 +                              interrupts = <0 26 0x4
 +                                            0 53 0x4>;
 +                              status = "disabled";
 +                      };
 +
 +                      spi0: spi@e0100000 {
 +                              compatible = "arm,pl022", "arm,primecell";
 +                              reg = <0xe0100000 0x1000>;
 +                              #address-cells = <1>;
 +                              #size-cells = <0>;
 +                              interrupts = <0 31 0x4>;
 +                              status = "disabled";
 +                      };
 +
                        rtc@e0580000 {
 -                              compatible = "st,spear-rtc";
 +                              compatible = "st,spear600-rtc";
                                reg = <0xe0580000 0x1000>;
                                interrupts = <0 36 0x4>;
                                status = "disabled";
                        adc@e0080000 {
                                compatible = "st,spear600-adc";
                                reg = <0xe0080000 0x1000>;
 -                              interrupts = <0 44 0x4>;
 +                              interrupts = <0 12 0x4>;
                                status = "disabled";
                        };
  
                        timer@ec800600 {
                                compatible = "arm,cortex-a9-twd-timer";
                                reg = <0xec800600 0x20>;
 -                              interrupts = <1 13 0x301>;
 +                              interrupts = <1 13 0x4>;
 +                              status = "disabled";
                        };
  
                        wdt@ec800620 {
                        thermal@e07008c4 {
                                compatible = "st,thermal-spear1340";
                                reg = <0xe07008c4 0x4>;
 +                              thermal_flags = <0x7000>;
                        };
                };
        };
@@@ -27,7 -27,7 +27,7 @@@
                };
  
                clcd@60000000 {
 -                      compatible = "arm,clcd-pl110", "arm,primecell";
 +                      compatible = "arm,pl110", "arm,primecell";
                        reg = <0x60000000 0x1000>;
                        interrupts = <30>;
                        status = "disabled";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0x94000000 0x1000        /* FSMC Register */
-                              0x80000000 0x0010>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
-                       st,ale-off = <0x20000>;
-                       st,cle-off = <0x10000>;
+                              0x80000000 0x0010        /* NAND Base DATA */
+                              0x80020000 0x0010        /* NAND Base ADDR */
+                              0x80010000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        status = "disabled";
                };
  
                        status = "disabled";
                };
  
 +              shirq: interrupt-controller@0x50000000 {
 +                      compatible = "st,spear300-shirq";
 +                      reg = <0x50000000 0x1000>;
 +                      interrupts = <28>;
 +                      #interrupt-cells = <1>;
 +                      interrupt-controller;
 +              };
 +
                apb {
                        #address-cells = <1>;
                        #size-cells = <1>;
                                compatible = "arm,pl061", "arm,primecell";
                                gpio-controller;
                                reg = <0xa9000000 0x1000>;
 +                              interrupts = <8>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
  
                        kbd@a0000000 {
                                compatible = "st,spear300-kbd";
                                reg = <0xa0000000 0x1000>;
 +                              interrupts = <7>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
                };
                          0xb0000000 0xb0000000 0x10000000
                          0xd0000000 0xd0000000 0x30000000>;
  
 -              pinmux@b4000000 {
 +              pinmux: pinmux@b4000000 {
                        compatible = "st,spear310-pinmux";
                        reg = <0xb4000000 0x1000>;
 +                      #gpio-range-cells = <2>;
                };
  
                fsmc: flash@44000000 {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0x44000000 0x1000        /* FSMC Register */
-                              0x40000000 0x0010>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
-                       st,ale-off = <0x10000>;
-                       st,cle-off = <0x20000>;
+                              0x40000000 0x0010        /* NAND Base DATA */
+                              0x40020000 0x0010        /* NAND Base ADDR */
+                              0x40010000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        status = "disabled";
                };
  
 +              shirq: interrupt-controller@0xb4000000 {
 +                      compatible = "st,spear310-shirq";
 +                      reg = <0xb4000000 0x1000>;
 +                      interrupts = <28 29 30 1>;
 +                      #interrupt-cells = <1>;
 +                      interrupt-controller;
 +              };
 +
                apb {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        serial@b2000000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2000000 0x1000>;
 +                              interrupts = <8>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
  
                        serial@b2080000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2080000 0x1000>;
 +                              interrupts = <9>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
  
                        serial@b2100000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2100000 0x1000>;
 +                              interrupts = <10>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
  
                        serial@b2180000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2180000 0x1000>;
 +                              interrupts = <11>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
  
                        serial@b2200000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xb2200000 0x1000>;
 +                              interrupts = <12>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 +
 +                      gpiopinctrl: gpio@b4000000 {
 +                              compatible = "st,spear-plgpio";
 +                              reg = <0xb4000000 0x1000>;
 +                              #interrupt-cells = <1>;
 +                              interrupt-controller;
 +                              gpio-controller;
 +                              #gpio-cells = <2>;
 +                              gpio-ranges = <&pinmux 0 102>;
 +                              status = "disabled";
 +
 +                              st-plgpio,ngpio = <102>;
 +                              st-plgpio,enb-reg = <0x10>;
 +                              st-plgpio,wdata-reg = <0x20>;
 +                              st-plgpio,dir-reg = <0x30>;
 +                              st-plgpio,ie-reg = <0x50>;
 +                              st-plgpio,rdata-reg = <0x40>;
 +                              st-plgpio,mis-reg = <0x60>;
 +                      };
                };
        };
  };
                ranges = <0x40000000 0x40000000 0x80000000
                          0xd0000000 0xd0000000 0x30000000>;
  
 -              pinmux@b3000000 {
 +              pinmux: pinmux@b3000000 {
                        compatible = "st,spear320-pinmux";
                        reg = <0xb3000000 0x1000>;
 +                      #gpio-range-cells = <2>;
                };
  
                clcd@90000000 {
 -                      compatible = "arm,clcd-pl110", "arm,primecell";
 +                      compatible = "arm,pl110", "arm,primecell";
                        reg = <0x90000000 0x1000>;
 -                      interrupts = <33>;
 +                      interrupts = <8>;
 +                      interrupt-parent = <&shirq>;
                        status = "disabled";
                };
  
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0x4c000000 0x1000        /* FSMC Register */
-                              0x50000000 0x0010>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
-                       st,ale-off = <0x20000>;
-                       st,cle-off = <0x10000>;
+                              0x50000000 0x0010        /* NAND Base DATA */
+                              0x50020000 0x0010        /* NAND Base ADDR */
+                              0x50010000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        status = "disabled";
                };
  
                sdhci@70000000 {
                        compatible = "st,sdhci-spear";
                        reg = <0x70000000 0x100>;
 -                      interrupts = <29>;
 +                      interrupts = <10>;
 +                      interrupt-parent = <&shirq>;
                        status = "disabled";
                };
  
 +              shirq: interrupt-controller@0xb3000000 {
 +                      compatible = "st,spear320-shirq";
 +                      reg = <0xb3000000 0x1000>;
 +                      interrupts = <30 28 29 1>;
 +                      #interrupt-cells = <1>;
 +                      interrupt-controller;
 +              };
 +
                spi1: spi@a5000000 {
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0xa5000000 0x1000>;
 +                      interrupts = <15>;
 +                      interrupt-parent = <&shirq>;
 +                      #address-cells = <1>;
 +                      #size-cells = <0>;
                        status = "disabled";
                };
  
                spi2: spi@a6000000 {
                        compatible = "arm,pl022", "arm,primecell";
                        reg = <0xa6000000 0x1000>;
 +                      interrupts = <16>;
 +                      interrupt-parent = <&shirq>;
 +                      #address-cells = <1>;
 +                      #size-cells = <0>;
                        status = "disabled";
                };
  
 +              pwm: pwm@a8000000 {
 +                      compatible ="st,spear-pwm";
 +                      reg = <0xa8000000 0x1000>;
 +                      #pwm-cells = <2>;
 +                      status = "disabled";
 +                };
 +
                apb {
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "simple-bus";
 -                      ranges = <0xa0000000 0xa0000000 0x10000000
 +                      ranges = <0xa0000000 0xa0000000 0x20000000
                                  0xd0000000 0xd0000000 0x30000000>;
  
                        i2c1: i2c@a7000000 {
                                #size-cells = <0>;
                                compatible = "snps,designware-i2c";
                                reg = <0xa7000000 0x1000>;
 +                              interrupts = <21>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
  
                        serial@a3000000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xa3000000 0x1000>;
 +                              interrupts = <13>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
  
                        serial@a4000000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xa4000000 0x1000>;
 +                              interrupts = <14>;
 +                              interrupt-parent = <&shirq>;
                                status = "disabled";
                        };
 +
 +                      gpiopinctrl: gpio@b3000000 {
 +                              compatible = "st,spear-plgpio";
 +                              reg = <0xb3000000 0x1000>;
 +                              #interrupt-cells = <1>;
 +                              interrupt-controller;
 +                              gpio-controller;
 +                              #gpio-cells = <2>;
 +                              gpio-ranges = <&pinmux 0 102>;
 +                              status = "disabled";
 +
 +                              st-plgpio,ngpio = <102>;
 +                              st-plgpio,enb-reg = <0x24>;
 +                              st-plgpio,wdata-reg = <0x34>;
 +                              st-plgpio,dir-reg = <0x44>;
 +                              st-plgpio,ie-reg = <0x64>;
 +                              st-plgpio,rdata-reg = <0x54>;
 +                              st-plgpio,mis-reg = <0x84>;
 +                              st-plgpio,eit-reg = <0x94>;
 +                      };
                };
        };
  };
                        #interrupt-cells = <1>;
                };
  
 +              clcd@fc200000 {
 +                      compatible = "arm,pl110", "arm,primecell";
 +                      reg = <0xfc200000 0x1000>;
 +                      interrupt-parent = <&vic1>;
 +                      interrupts = <12>;
 +                      status = "disabled";
 +              };
 +
                dma@fc400000 {
                        compatible = "arm,pl080", "arm,primecell";
                        reg = <0xfc400000 0x1000>;
@@@ -67,7 -59,6 +67,7 @@@
                        interrupt-parent = <&vic1>;
                        interrupts = <24 23>;
                        interrupt-names = "macirq", "eth_wake_irq";
 +                      phy-mode = "gmii";
                        status = "disabled";
                };
  
                        #address-cells = <1>;
                        #size-cells = <1>;
                        reg = <0xd1800000 0x1000        /* FSMC Register */
-                              0xd2000000 0x4000>;      /* NAND Base */
-                       reg-names = "fsmc_regs", "nand_data";
-                       st,ale-off = <0x20000>;
-                       st,cle-off = <0x10000>;
+                              0xd2000000 0x0010        /* NAND Base DATA */
+                              0xd2020000 0x0010        /* NAND Base ADDR */
+                              0xd2010000 0x0010>;      /* NAND Base CMD */
+                       reg-names = "fsmc_regs", "nand_data", "nand_addr", "nand_cmd";
                        status = "disabled";
                };
  
                                status = "disabled";
                        };
  
 +                      rtc@fc900000 {
 +                              compatible = "st,spear600-rtc";
 +                              reg = <0xfc900000 0x1000>;
 +                              interrupts = <10>;
 +                              status = "disabled";
 +                      };
 +
                        timer@f0000000 {
                                compatible = "st,spear-timer";
                                reg = <0xf0000000 0x400>;
  #include <linux/gpio.h>
  #include <linux/mtd/mtd.h>
  #include <linux/mtd/nand.h>
+ #include <linux/mtd/fsmc.h>
  #include <linux/mtd/onenand.h>
  #include <linux/mtd/partitions.h>
  #include <linux/i2c.h>
  #include <linux/io.h>
  #include <linux/pinctrl/machine.h>
 +#include <linux/platform_data/pinctrl-nomadik.h>
 +#include <linux/platform_data/clocksource-nomadik-mtu.h>
 +#include <linux/platform_data/mtd-nomadik-nand.h>
  #include <asm/hardware/vic.h>
  #include <asm/sizes.h>
  #include <asm/mach-types.h>
  #include <asm/mach/arch.h>
 -#include <asm/mach/irq.h>
  #include <asm/mach/flash.h>
  #include <asm/mach/time.h>
- #include <mach/fsmc.h>
 -
 -#include <plat/gpio-nomadik.h>
 -#include <plat/mtu.h>
 -#include <plat/pincfg.h>
 +#include <mach/irqs.h>
  
  #include "cpu-8815.h"
  
  #define SRC_CR_INIT_MASK      0x00007fff
  #define SRC_CR_INIT_VAL               0x2aaa8000
  
+ #define ALE_OFF 0x1000000
+ #define CLE_OFF 0x800000
  /* These addresses span 16MB, so use three individual pages */
  static struct resource nhk8815_nand_resources[] = {
        {
+               .name = "nand_data",
+               .start = 0x40000000,
+               .end = 0x40000000 + SZ_16K - 1,
+               .flags = IORESOURCE_MEM,
+       }, {
                .name = "nand_addr",
-               .start = NAND_IO_ADDR,
-               .end = NAND_IO_ADDR + 0xfff,
+               .start = 0x40000000 + ALE_OFF,
+               .end = 0x40000000 +ALE_OFF + SZ_16K - 1,
                .flags = IORESOURCE_MEM,
        }, {
                .name = "nand_cmd",
-               .start = NAND_IO_CMD,
-               .end = NAND_IO_CMD + 0xfff,
+               .start = 0x40000000 + CLE_OFF,
+               .end = 0x40000000 + CLE_OFF + SZ_16K - 1,
                .flags = IORESOURCE_MEM,
        }, {
-               .name = "nand_data",
-               .start = NAND_IO_DATA,
-               .end = NAND_IO_DATA + 0xfff,
+               .name  = "fsmc_regs",
+               .start = NOMADIK_FSMC_BASE,
+               .end   = NOMADIK_FSMC_BASE + SZ_4K - 1,
                .flags = IORESOURCE_MEM,
-       }
+       },
  };
  
- static int nhk8815_nand_init(void)
- {
-       /* FSMC setup for nand chip select (8-bit nand in 8815NHK) */
-       writel(0x0000000E, FSMC_PCR(0));
-       writel(0x000D0A00, FSMC_PMEM(0));
-       writel(0x00100A00, FSMC_PATT(0));
-       /* enable access to the chip select area */
-       writel(readl(FSMC_PCR(0)) | 0x04, FSMC_PCR(0));
-       return 0;
- }
  /*
   * These partitions are the same as those used in the 2.6.20 release
   * shipped by the vendor; the first two partitions are mandated
@@@ -108,20 -104,28 +103,28 @@@ static struct mtd_partition nhk8815_par
        }
  };
  
- static struct nomadik_nand_platform_data nhk8815_nand_data = {
-       .parts          = nhk8815_partitions,
-       .nparts         = ARRAY_SIZE(nhk8815_partitions),
-       .options        = NAND_COPYBACK | NAND_CACHEPRG | NAND_NO_PADDING,
-       .init           = nhk8815_nand_init,
+ static struct fsmc_nand_timings nhk8815_nand_timings = {
+       .thiz   = 0,
+       .thold  = 0x10,
+       .twait  = 0x0A,
+       .tset   = 0,
+ };
+ static struct fsmc_nand_platform_data nhk8815_nand_platform_data = {
+       .nand_timings = &nhk8815_nand_timings,
+       .partitions = nhk8815_partitions,
+       .nr_partitions = ARRAY_SIZE(nhk8815_partitions),
+       .width = FSMC_NAND_BW8,
  };
  
  static struct platform_device nhk8815_nand_device = {
-       .name           = "nomadik_nand",
-       .dev            = {
-               .platform_data = &nhk8815_nand_data,
+       .name = "fsmc-nand",
+       .id = -1,
+       .resource = nhk8815_nand_resources,
+       .num_resources = ARRAY_SIZE(nhk8815_nand_resources),
+       .dev = {
+               .platform_data = &nhk8815_nand_platform_data,
        },
-       .resource       = nhk8815_nand_resources,
-       .num_resources  = ARRAY_SIZE(nhk8815_nand_resources),
  };
  
  /* These are the partitions for the OneNand device, different from above */
@@@ -176,6 -180,10 +179,10 @@@ static struct platform_device nhk8815_o
        .num_resources  = ARRAY_SIZE(nhk8815_onenand_resource),
  };
  
+ /* bus control reg. and bus timing reg. for CS0..CS3 */
+ #define FSMC_BCR(x)   (NOMADIK_FSMC_VA + (x << 3))
+ #define FSMC_BTR(x)   (NOMADIK_FSMC_VA + (x << 3) + 0x04)
  static void __init nhk8815_onenand_init(void)
  {
  #ifdef CONFIG_MTD_ONENAND
@@@ -258,7 -266,7 +265,7 @@@ static void __init nomadik_timer_init(v
        src_cr |= SRC_CR_INIT_VAL;
        writel(src_cr, io_p2v(NOMADIK_SRC_BASE));
  
 -      nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE));
 +      nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE), IRQ_MTU0);
  }
  
  static struct sys_timer nomadik_timer = {
@@@ -82,6 -82,8 +82,6 @@@ static struct map_desc u300_io_desc[] _
  static void __init u300_map_io(void)
  {
        iotable_init(u300_io_desc, ARRAY_SIZE(u300_io_desc));
 -      /* We enable a real big DMA buffer if need be. */
 -      init_consistent_dma_size(SZ_4M);
  }
  
  /*
@@@ -250,6 -252,18 +250,18 @@@ static struct resource rtc_resources[] 
   */
  static struct resource fsmc_resources[] = {
        {
+               .name  = "nand_addr",
+               .start = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_ALE,
+               .end   = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_ALE + SZ_16K - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .name  = "nand_cmd",
+               .start = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_CLE,
+               .end   = U300_NAND_CS0_PHYS_BASE + PLAT_NAND_CLE + SZ_16K - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       {
                .name  = "nand_data",
                .start = U300_NAND_CS0_PHYS_BASE,
                .end   = U300_NAND_CS0_PHYS_BASE + SZ_16K - 1,
@@@ -1443,6 -1457,8 +1455,6 @@@ static struct platform_device pinctrl_d
  static struct u300_gpio_platform u300_gpio_plat = {
        .ports = 7,
        .gpio_base = 0,
 -      .gpio_irq_base = IRQ_U300_GPIO_BASE,
 -      .pinctrl_device = &pinctrl_device,
  };
  
  static struct platform_device gpio_device = {
@@@ -1492,8 -1508,6 +1504,6 @@@ static struct fsmc_nand_platform_data n
        .nr_partitions = ARRAY_SIZE(u300_partitions),
        .options = NAND_SKIP_BBTSCAN,
        .width = FSMC_NAND_BW8,
-       .ale_off = PLAT_NAND_ALE,
-       .cle_off = PLAT_NAND_CLE,
  };
  
  static struct platform_device nand_device = {
@@@ -1586,7 -1600,6 +1596,7 @@@ static struct platform_device *platform
        &i2c1_device,
        &keypad_device,
        &rtc_device,
 +      &pinctrl_device,
        &gpio_device,
        &nand_device,
        &wdog_device,
@@@ -1801,7 -1814,7 +1811,7 @@@ MACHINE_START(U300, "Ericsson AB U335 S
        /* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
        .atag_offset    = 0x100,
        .map_io         = u300_map_io,
 -      .nr_irqs        = NR_IRQS_U300,
 +      .nr_irqs        = 0,
        .init_irq       = u300_init_irq,
        .handle_irq     = vic_handle_irq,
        .timer          = &u300_timer,
  #include <linux/export.h>
  #include <linux/bcma/bcma.h>
  
static u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
+ u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset)
  {
        bcma_cc_write32(cc, BCMA_CC_PLLCTL_ADDR, offset);
        bcma_cc_read32(cc, BCMA_CC_PLLCTL_ADDR);
        return bcma_cc_read32(cc, BCMA_CC_PLLCTL_DATA);
  }
+ EXPORT_SYMBOL_GPL(bcma_chipco_pll_read);
  
  void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, u32 value)
  {
@@@ -144,7 -145,7 +145,7 @@@ static void bcma_pmu_workarounds(struc
        }
  }
  
 -void bcma_pmu_init(struct bcma_drv_cc *cc)
 +void bcma_pmu_early_init(struct bcma_drv_cc *cc)
  {
        u32 pmucap;
  
  
        bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
                   cc->pmu.rev, pmucap);
 +}
  
 +void bcma_pmu_init(struct bcma_drv_cc *cc)
 +{
        if (cc->pmu.rev == 1)
                bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
                              ~BCMA_CC_PMU_CTL_NOILPONW);
        bcma_pmu_workarounds(cc);
  }
  
 -u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc)
 +u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc)
  {
        struct bcma_bus *bus = cc->core->bus;
  
  /* Find the output of the "m" pll divider given pll controls that start with
   * pllreg "pll0" i.e. 12 for main 6 for phy, 0 for misc.
   */
 -static u32 bcma_pmu_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
 +static u32 bcma_pmu_pll_clock(struct bcma_drv_cc *cc, u32 pll0, u32 m)
  {
        u32 tmp, div, ndiv, p1, p2, fc;
        struct bcma_bus *bus = cc->core->bus;
        ndiv = (tmp & BCMA_CC_PPL_NDIV_MASK) >> BCMA_CC_PPL_NDIV_SHIFT;
  
        /* Do calculation in Mhz */
 -      fc = bcma_pmu_alp_clock(cc) / 1000000;
 +      fc = bcma_pmu_get_alp_clock(cc) / 1000000;
        fc = (p1 * ndiv * fc) / p2;
  
        /* Return clock in Hertz */
        return (fc / div) * 1000000;
  }
  
 -static u32 bcma_pmu_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
 +static u32 bcma_pmu_pll_clock_bcm4706(struct bcma_drv_cc *cc, u32 pll0, u32 m)
  {
        u32 tmp, ndiv, p1div, p2div;
        u32 clock;
  }
  
  /* query bus clock frequency for PMU-enabled chipcommon */
 -static u32 bcma_pmu_get_clockcontrol(struct bcma_drv_cc *cc)
 +static u32 bcma_pmu_get_bus_clock(struct bcma_drv_cc *cc)
  {
        struct bcma_bus *bus = cc->core->bus;
  
        case BCMA_CHIP_ID_BCM4716:
        case BCMA_CHIP_ID_BCM4748:
        case BCMA_CHIP_ID_BCM47162:
 -              return bcma_pmu_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
 -                                    BCMA_CC_PMU5_MAINPLL_SSB);
 +              return bcma_pmu_pll_clock(cc, BCMA_CC_PMU4716_MAINPLL_PLL0,
 +                                        BCMA_CC_PMU5_MAINPLL_SSB);
        case BCMA_CHIP_ID_BCM5356:
 -              return bcma_pmu_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
 -                                    BCMA_CC_PMU5_MAINPLL_SSB);
 +              return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5356_MAINPLL_PLL0,
 +                                        BCMA_CC_PMU5_MAINPLL_SSB);
        case BCMA_CHIP_ID_BCM5357:
        case BCMA_CHIP_ID_BCM4749:
 -              return bcma_pmu_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
 -                                    BCMA_CC_PMU5_MAINPLL_SSB);
 +              return bcma_pmu_pll_clock(cc, BCMA_CC_PMU5357_MAINPLL_PLL0,
 +                                        BCMA_CC_PMU5_MAINPLL_SSB);
        case BCMA_CHIP_ID_BCM4706:
 -              return bcma_pmu_clock_bcm4706(cc, BCMA_CC_PMU4706_MAINPLL_PLL0,
 -                                            BCMA_CC_PMU5_MAINPLL_SSB);
 +              return bcma_pmu_pll_clock_bcm4706(cc,
 +                                                BCMA_CC_PMU4706_MAINPLL_PLL0,
 +                                                BCMA_CC_PMU5_MAINPLL_SSB);
        case BCMA_CHIP_ID_BCM53572:
                return 75000000;
        default:
 -              bcma_warn(bus, "No backplane clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
 +              bcma_warn(bus, "No bus clock specified for %04X device, pmu rev. %d, using default %d Hz\n",
                          bus->chipinfo.id, cc->pmu.rev, BCMA_CC_PMU_HT_CLOCK);
        }
        return BCMA_CC_PMU_HT_CLOCK;
  }
  
  /* query cpu clock frequency for PMU-enabled chipcommon */
 -u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc)
 +u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc)
  {
        struct bcma_bus *bus = cc->core->bus;
  
        if (bus->chipinfo.id == BCMA_CHIP_ID_BCM53572)
                return 300000000;
  
 +      /* New PMUs can have different clock for bus and CPU */
        if (cc->pmu.rev >= 5) {
                u32 pll;
                switch (bus->chipinfo.id) {
                case BCMA_CHIP_ID_BCM4706:
 -                      return bcma_pmu_clock_bcm4706(cc,
 +                      return bcma_pmu_pll_clock_bcm4706(cc,
                                                BCMA_CC_PMU4706_MAINPLL_PLL0,
                                                BCMA_CC_PMU5_MAINPLL_CPU);
                case BCMA_CHIP_ID_BCM5356:
                        break;
                }
  
 -              return bcma_pmu_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
 +              return bcma_pmu_pll_clock(cc, pll, BCMA_CC_PMU5_MAINPLL_CPU);
        }
  
 -      return bcma_pmu_get_clockcontrol(cc);
 +      /* On old PMUs CPU has the same clock as the bus */
 +      return bcma_pmu_get_bus_clock(cc);
  }
  
  static void bcma_pmu_spuravoid_pll_write(struct bcma_drv_cc *cc, u32 offset,
diff --combined drivers/mtd/maps/Kconfig
@@@ -324,6 -324,13 +324,6 @@@ config MTD_SOLUTIONENGIN
          This enables access to the flash chips on the Hitachi SolutionEngine and
          similar boards. Say 'Y' if you are building a kernel for such a board.
  
 -config MTD_CDB89712
 -      tristate "Cirrus CDB89712 evaluation board mappings"
 -      depends on MTD_CFI && ARCH_CDB89712
 -      help
 -        This enables access to the flash or ROM chips on the CDB89712 board.
 -        If you have such a board, say 'Y'.
 -
  config MTD_SA1100
        tristate "CFI Flash device mapped on StrongARM SA11x0"
        depends on MTD_CFI && ARCH_SA1100
@@@ -358,13 -365,6 +358,6 @@@ config MTD_IXP200
          IXP2000 based board and would like to use the flash chips on it,
          say 'Y'.
  
- config MTD_FORTUNET
-       tristate "CFI Flash device mapped on the FortuNet board"
-       depends on MTD_CFI && SA1100_FORTUNET
-       help
-         This enables access to the Flash on the FortuNet board.  If you
-         have such a board, say 'Y'.
  config MTD_AUTCPU12
        bool "NV-RAM mapping AUTCPU12 board"
        depends on ARCH_AUTCPU12
@@@ -7,6 -7,7 +7,6 @@@ obj-$(CONFIG_MTD)                += map_funcs.
  endif
  
  # Chip mappings
 -obj-$(CONFIG_MTD_CDB89712)    += cdb89712.o
  obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
  obj-$(CONFIG_MTD_DC21285)     += dc21285.o
  obj-$(CONFIG_MTD_DILNETPC)    += dilnetpc.o
@@@ -39,7 -40,6 +39,6 @@@ obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solu
  obj-$(CONFIG_MTD_PCI)         += pci.o
  obj-$(CONFIG_MTD_AUTCPU12)    += autcpu12-nvram.o
  obj-$(CONFIG_MTD_IMPA7)               += impa7.o
- obj-$(CONFIG_MTD_FORTUNET)    += fortunet.o
  obj-$(CONFIG_MTD_UCLINUX)     += uclinux.o
  obj-$(CONFIG_MTD_NETtel)      += nettel.o
  obj-$(CONFIG_MTD_SCB2_FLASH)  += scb2_flash.o
diff --combined drivers/mtd/nand/Kconfig
@@@ -49,17 -49,38 +49,31 @@@ config MTD_NAND_MUSEUM_ID
          NAND chips (page size 256 byte, erase size 4-8KiB). The IDs
          of these chips were reused by later, larger chips.
  
 -config MTD_NAND_AUTCPU12
 -      tristate "SmartMediaCard on autronix autcpu12 board"
 -      depends on ARCH_AUTCPU12
 -      help
 -        This enables the driver for the autronix autcpu12 board to
 -        access the SmartMediaCard.
 -
  config MTD_NAND_DENALI
-        depends on PCI
+         tristate "Support Denali NAND controller"
+         help
+         Enable support for the Denali NAND controller.  This should be
+         combined with either the PCI or platform drivers to provide device
+         registration.
+ config MTD_NAND_DENALI_PCI
          tristate "Support Denali NAND controller on Intel Moorestown"
+       depends on PCI && MTD_NAND_DENALI
          help
            Enable the driver for NAND flash on Intel Moorestown, using the
            Denali NAND controller core.
-  
+ config MTD_NAND_DENALI_DT
+       tristate "Support Denali NAND controller as a DT device"
+       depends on HAVE_CLK && MTD_NAND_DENALI
+       help
+         Enable the driver for NAND flash on platforms using a Denali NAND
+         controller as a DT device.
  config MTD_NAND_DENALI_SCRATCH_REG_ADDR
          hex "Denali NAND size scratch register address"
          default "0xFF108018"
-         depends on MTD_NAND_DENALI
+         depends on MTD_NAND_DENALI_PCI
          help
            Some platforms place the NAND chip size in a scratch register
            because (some versions of) the driver aren't able to automatically
@@@ -79,6 -100,12 +93,6 @@@ config MTD_NAND_GPI
        help
          This enables a GPIO based NAND flash driver.
  
 -config MTD_NAND_SPIA
 -      tristate "NAND Flash device on SPIA board"
 -      depends on ARCH_P720T
 -      help
 -        If you had to ask, you don't have one. Say 'N'.
 -
  config MTD_NAND_AMS_DELTA
        tristate "NAND Flash device on Amstrad E3"
        depends on MACH_AMS_DELTA
@@@ -433,6 -460,14 +447,14 @@@ config MTD_NAND_GPMI_NAN
         block, such as SD card. So pay attention to it when you enable
         the GPMI.
  
+ config MTD_NAND_BCM47XXNFLASH
+       tristate "Support for NAND flash on BCM4706 BCMA bus"
+       depends on BCMA_NFLASH
+       help
+         BCMA bus can have various flash memories attached, they are
+         registered by bcma as platform devices. This enables driver for
+         NAND flash memories. For now only BCM4706 is supported.
  config MTD_NAND_PLATFORM
        tristate "Support for generic platform NAND driver"
        depends on HAS_IOMEM
@@@ -499,12 -534,6 +521,6 @@@ config MTD_NAND_MX
          This enables the driver for the NAND flash controller on the
          MXC processors.
  
- config MTD_NAND_NOMADIK
-       tristate "ST Nomadik 8815 NAND support"
-       depends on ARCH_NOMADIK
-       help
-         Driver for the NAND flash controller on the Nomadik, with ECC.
  config MTD_NAND_SH_FLCTL
        tristate "Support for NAND on Renesas SuperH FLCTL"
        depends on SUPERH || ARCH_SHMOBILE
@@@ -546,7 -575,7 +562,7 @@@ config MTD_NAND_JZ474
  
  config MTD_NAND_FSMC
        tristate "Support for NAND on ST Micros FSMC"
 -      depends on PLAT_SPEAR || PLAT_NOMADIK || MACH_U300
 +      depends on PLAT_SPEAR || ARCH_NOMADIK || ARCH_U8500 || MACH_U300
        help
          Enables support for NAND Flash chips on the ST Microelectronics
          Flexible Static Memory Controller (FSMC)
@@@ -9,8 -9,12 +9,10 @@@ obj-$(CONFIG_MTD_NAND_IDS)             += nand_ids
  obj-$(CONFIG_MTD_SM_COMMON)           += sm_common.o
  
  obj-$(CONFIG_MTD_NAND_CAFE)           += cafe_nand.o
 -obj-$(CONFIG_MTD_NAND_SPIA)           += spia.o
  obj-$(CONFIG_MTD_NAND_AMS_DELTA)      += ams-delta.o
 -obj-$(CONFIG_MTD_NAND_AUTCPU12)               += autcpu12.o
  obj-$(CONFIG_MTD_NAND_DENALI)         += denali.o
+ obj-$(CONFIG_MTD_NAND_DENALI_PCI)     += denali_pci.o
+ obj-$(CONFIG_MTD_NAND_DENALI_DT)      += denali_dt.o
  obj-$(CONFIG_MTD_NAND_AU1550)         += au1550nd.o
  obj-$(CONFIG_MTD_NAND_BF5XX)          += bf5xx_nand.o
  obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
@@@ -45,11 -49,11 +47,11 @@@ obj-$(CONFIG_MTD_NAND_MXC)         += mxc_nand
  obj-$(CONFIG_MTD_NAND_SOCRATES)               += socrates_nand.o
  obj-$(CONFIG_MTD_NAND_TXX9NDFMC)      += txx9ndfmc.o
  obj-$(CONFIG_MTD_NAND_NUC900)         += nuc900_nand.o
- obj-$(CONFIG_MTD_NAND_NOMADIK)                += nomadik_nand.o
  obj-$(CONFIG_MTD_NAND_MPC5121_NFC)    += mpc5121_nfc.o
  obj-$(CONFIG_MTD_NAND_RICOH)          += r852.o
  obj-$(CONFIG_MTD_NAND_JZ4740)         += jz4740_nand.o
  obj-$(CONFIG_MTD_NAND_GPMI_NAND)      += gpmi-nand/
  obj-$(CONFIG_MTD_NAND_XWAY)           += xway_nand.o
+ obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH)  += bcm47xxnflash/
  
  nand-objs := nand_base.o nand_bbt.o
@@@ -41,7 -41,6 +41,7 @@@
  #include <linux/gpio.h>
  #include <linux/io.h>
  #include <linux/platform_data/atmel.h>
 +#include <linux/pinctrl/consumer.h>
  
  #include <mach/cpu.h>
  
@@@ -331,13 -330,13 +331,13 @@@ static void atmel_write_buf(struct mtd_
   *               12-bits                20-bytes                 21-bytes
   *               24-bits                39-bytes                 42-bytes
   */
- static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size)
+ static int pmecc_get_ecc_bytes(int cap, int sector_size)
  {
        int m = 12 + sector_size / 512;
        return (m * cap + 7) / 8;
  }
  
- static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout,
+ static void pmecc_config_ecc_layout(struct nand_ecclayout *layout,
        int oobsize, int ecc_len)
  {
        int i;
                oobsize - ecc_len - layout->oobfree[0].offset;
  }
  
- static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
+ static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
  {
        int table_size;
  
@@@ -375,7 -374,7 +375,7 @@@ static void pmecc_data_free(struct atme
        kfree(host->pmecc_delta);
  }
  
- static int __devinit pmecc_data_alloc(struct atmel_nand_host *host)
+ static int pmecc_data_alloc(struct atmel_nand_host *host)
  {
        const int cap = host->pmecc_corr_cap;
  
@@@ -724,6 -723,7 +724,7 @@@ static int pmecc_correction(struct mtd_
        struct atmel_nand_host *host = nand_chip->priv;
        int i, err_nbr, eccbytes;
        uint8_t *buf_pos;
+       int total_err = 0;
  
        eccbytes = nand_chip->ecc.bytes;
        for (i = 0; i < eccbytes; i++)
@@@ -751,12 -751,13 +752,13 @@@ normal_check
                                pmecc_correct_data(mtd, buf_pos, ecc, i,
                                        host->pmecc_bytes_per_sector, err_nbr);
                                mtd->ecc_stats.corrected += err_nbr;
+                               total_err += err_nbr;
                        }
                }
                pmecc_stat >>= 1;
        }
  
-       return 0;
+       return total_err;
  }
  
  static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
        uint32_t *eccpos = chip->ecc.layout->eccpos;
        uint32_t stat;
        unsigned long end_time;
+       int bitflips = 0;
  
        pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
        pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
        }
  
        stat = pmecc_readl_relaxed(host->ecc, ISR);
-       if (stat != 0)
-               if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0)
-                       return -EIO;
+       if (stat != 0) {
+               bitflips = pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]);
+               if (bitflips < 0)
+                       /* uncorrectable errors */
+                       return 0;
+       }
  
-       return 0;
+       return bitflips;
  }
  
  static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
@@@ -1206,7 -1211,7 +1212,7 @@@ static void atmel_nand_hwctl(struct mtd
  }
  
  #if defined(CONFIG_OF)
- static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
+ static int atmel_of_init_port(struct atmel_nand_host *host,
                                         struct device_node *np)
  {
        u32 val, table_offset;
        return 0;
  }
  #else
- static int __devinit atmel_of_init_port(struct atmel_nand_host *host,
+ static int atmel_of_init_port(struct atmel_nand_host *host,
                                         struct device_node *np)
  {
        return -EINVAL;
@@@ -1371,7 -1376,6 +1377,7 @@@ static int __init atmel_nand_probe(stru
        struct resource *mem;
        struct mtd_part_parser_data ppdata = {};
        int res;
 +      struct pinctrl *pinctrl;
  
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
        nand_chip->IO_ADDR_W = host->io_base;
        nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
  
 +      pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
 +      if (IS_ERR(pinctrl)) {
 +              dev_err(host->dev, "Failed to request pinctrl\n");
 +              res = PTR_ERR(pinctrl);
 +              goto err_ecc_ioremap;
 +      }
 +
        if (gpio_is_valid(host->board.rdy_pin)) {
                res = gpio_request(host->board.rdy_pin, "nand_rdy");
                if (res < 0) {
  
  #include <asm/mach/flash.h>
  #include <linux/platform_data/mtd-mxc_nand.h>
 -#include <mach/hardware.h>
  
  #define DRIVER_NAME "mxc_nand"
  
 -#define nfc_is_v21()          (cpu_is_mx25() || cpu_is_mx35())
 -#define nfc_is_v1()           (cpu_is_mx31() || cpu_is_mx27() || cpu_is_mx21())
 -#define nfc_is_v3_2a()                cpu_is_mx51()
 -#define nfc_is_v3_2b()                cpu_is_mx53()
 -
  /* Addresses for NFC registers */
  #define NFC_V1_V2_BUF_SIZE            (host->regs + 0x00)
  #define NFC_V1_V2_BUF_ADDR            (host->regs + 0x04)
@@@ -266,7 -272,8 +266,8 @@@ static struct nand_ecclayout nandv2_hw_
        }
  };
  
- static const char *part_probes[] = { "RedBoot", "cmdlinepart", "ofpart", NULL };
+ static const char const *part_probes[] = {
+       "cmdlinepart", "RedBoot", "ofpart", NULL };
  
  static void memcpy32_fromio(void *trg, const void __iomem  *src, size_t size)
  {
@@@ -1277,53 -1284,6 +1278,53 @@@ static const struct mxc_nand_devtype_da
        .ppb_shift = 8,
  };
  
 +static inline int is_imx21_nfc(struct mxc_nand_host *host)
 +{
 +      return host->devtype_data == &imx21_nand_devtype_data;
 +}
 +
 +static inline int is_imx27_nfc(struct mxc_nand_host *host)
 +{
 +      return host->devtype_data == &imx27_nand_devtype_data;
 +}
 +
 +static inline int is_imx25_nfc(struct mxc_nand_host *host)
 +{
 +      return host->devtype_data == &imx25_nand_devtype_data;
 +}
 +
 +static inline int is_imx51_nfc(struct mxc_nand_host *host)
 +{
 +      return host->devtype_data == &imx51_nand_devtype_data;
 +}
 +
 +static inline int is_imx53_nfc(struct mxc_nand_host *host)
 +{
 +      return host->devtype_data == &imx53_nand_devtype_data;
 +}
 +
 +static struct platform_device_id mxcnd_devtype[] = {
 +      {
 +              .name = "imx21-nand",
 +              .driver_data = (kernel_ulong_t) &imx21_nand_devtype_data,
 +      }, {
 +              .name = "imx27-nand",
 +              .driver_data = (kernel_ulong_t) &imx27_nand_devtype_data,
 +      }, {
 +              .name = "imx25-nand",
 +              .driver_data = (kernel_ulong_t) &imx25_nand_devtype_data,
 +      }, {
 +              .name = "imx51-nand",
 +              .driver_data = (kernel_ulong_t) &imx51_nand_devtype_data,
 +      }, {
 +              .name = "imx53-nand",
 +              .driver_data = (kernel_ulong_t) &imx53_nand_devtype_data,
 +      }, {
 +              /* sentinel */
 +      }
 +};
 +MODULE_DEVICE_TABLE(platform, mxcnd_devtype);
 +
  #ifdef CONFIG_OF_MTD
  static const struct of_device_id mxcnd_dt_ids[] = {
        {
@@@ -1378,7 -1338,33 +1379,7 @@@ static int __init mxcnd_probe_dt(struc
  }
  #endif
  
- static int __devinit mxcnd_probe(struct platform_device *pdev)
 -static int __init mxcnd_probe_pdata(struct mxc_nand_host *host)
 -{
 -      struct mxc_nand_platform_data *pdata = host->dev->platform_data;
 -
 -      if (!pdata)
 -              return -ENODEV;
 -
 -      host->pdata = *pdata;
 -
 -      if (nfc_is_v1()) {
 -              if (cpu_is_mx21())
 -                      host->devtype_data = &imx21_nand_devtype_data;
 -              else
 -                      host->devtype_data = &imx27_nand_devtype_data;
 -      } else if (nfc_is_v21()) {
 -              host->devtype_data = &imx25_nand_devtype_data;
 -      } else if (nfc_is_v3_2a()) {
 -              host->devtype_data = &imx51_nand_devtype_data;
 -      } else if (nfc_is_v3_2b()) {
 -              host->devtype_data = &imx53_nand_devtype_data;
 -      } else
 -              BUG();
 -
 -      return 0;
 -}
 -
+ static int mxcnd_probe(struct platform_device *pdev)
  {
        struct nand_chip *this;
        struct mtd_info *mtd;
                return PTR_ERR(host->clk);
  
        err = mxcnd_probe_dt(host);
 -      if (err > 0)
 -              err = mxcnd_probe_pdata(host);
 +      if (err > 0) {
 +              struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
 +              if (pdata) {
 +                      host->pdata = *pdata;
 +                      host->devtype_data = (struct mxc_nand_devtype_data *)
 +                                              pdev->id_entry->driver_data;
 +              } else {
 +                      err = -ENODEV;
 +              }
 +      }
        if (err < 0)
                return err;
  
        }
  
        /* first scan to find the device and get the page size */
 -      if (nand_scan_ident(mtd, nfc_is_v21() ? 4 : 1, NULL)) {
 +      if (nand_scan_ident(mtd, is_imx25_nfc(host) ? 4 : 1, NULL)) {
                err = -ENXIO;
                goto escan;
        }
                this->ecc.layout = host->devtype_data->ecclayout_4k;
  
        if (this->ecc.mode == NAND_ECC_HW) {
 -              if (nfc_is_v1())
 +              if (is_imx21_nfc(host) || is_imx27_nfc(host))
                        this->ecc.strength = 1;
                else
                        this->ecc.strength = (host->eccsize == 4) ? 4 : 8;
        return 0;
  
  escan:
-       clk_disable_unprepare(host->clk);
+       if (host->clk_act)
+               clk_disable_unprepare(host->clk);
  
        return err;
  }
  
- static int __devexit mxcnd_remove(struct platform_device *pdev)
+ static int mxcnd_remove(struct platform_device *pdev)
  {
        struct mxc_nand_host *host = platform_get_drvdata(pdev);
  
@@@ -1578,9 -1557,8 +1580,9 @@@ static struct platform_driver mxcnd_dri
                   .owner = THIS_MODULE,
                   .of_match_table = of_match_ptr(mxcnd_dt_ids),
        },
 +      .id_table = mxcnd_devtype,
        .probe = mxcnd_probe,
-       .remove = __devexit_p(mxcnd_remove),
+       .remove = mxcnd_remove,
  };
  module_platform_driver(mxcnd_driver);
  
@@@ -42,6 -42,8 +42,8 @@@
  #include <linux/sched.h>
  #include <linux/fs.h>
  #include <linux/pagemap.h>
+ #include <linux/seq_file.h>
+ #include <linux/debugfs.h>
  
  /* Default simulator parameters values */
  #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE)  || \
@@@ -105,7 -107,6 +107,6 @@@ static char *weakblocks = NULL
  static char *weakpages = NULL;
  static unsigned int bitflips = 0;
  static char *gravepages = NULL;
- static unsigned int rptwear = 0;
  static unsigned int overridesize = 0;
  static char *cache_file = NULL;
  static unsigned int bbt;
@@@ -130,7 -131,6 +131,6 @@@ module_param(weakblocks,     charp, 040
  module_param(weakpages,      charp, 0400);
  module_param(bitflips,       uint, 0400);
  module_param(gravepages,     charp, 0400);
- module_param(rptwear,        uint, 0400);
  module_param(overridesize,   uint, 0400);
  module_param(cache_file,     charp, 0400);
  module_param(bbt,          uint, 0400);
@@@ -162,7 -162,6 +162,6 @@@ MODULE_PARM_DESC(bitflips,       "Maxim
  MODULE_PARM_DESC(gravepages,     "Pages that lose data [: maximum reads (defaults to 3)]"
                                 " separated by commas e.g. 1401:2 means page 1401"
                                 " can be read only twice before failing");
- MODULE_PARM_DESC(rptwear,        "Number of erases between reporting wear, if not zero");
  MODULE_PARM_DESC(overridesize,   "Specifies the NAND Flash size overriding the ID bytes. "
                                 "The size is specified in erase blocks and as the exponent of a power of two"
                                 " e.g. 5 means a size of 32 erase blocks");
@@@ -286,6 -285,11 +285,11 @@@ MODULE_PARM_DESC(bch,             "Enable BCH ec
  /* Maximum page cache pages needed to read or write a NAND page to the cache_file */
  #define NS_MAX_HELD_PAGES 16
  
+ struct nandsim_debug_info {
+       struct dentry *dfs_root;
+       struct dentry *dfs_wear_report;
+ };
  /*
   * A union to represent flash memory contents and flash buffer.
   */
@@@ -365,6 -369,8 +369,8 @@@ struct nandsim 
        void *file_buf;
        struct page *held_pages[NS_MAX_HELD_PAGES];
        int held_cnt;
+       struct nandsim_debug_info dbg;
  };
  
  /*
@@@ -442,11 -448,123 +448,123 @@@ static LIST_HEAD(grave_pages)
  static unsigned long *erase_block_wear = NULL;
  static unsigned int wear_eb_count = 0;
  static unsigned long total_wear = 0;
- static unsigned int rptwear_cnt = 0;
  
  /* MTD structure for NAND controller */
  static struct mtd_info *nsmtd;
  
+ static int nandsim_debugfs_show(struct seq_file *m, void *private)
+ {
+       unsigned long wmin = -1, wmax = 0, avg;
+       unsigned long deciles[10], decile_max[10], tot = 0;
+       unsigned int i;
+       /* Calc wear stats */
+       for (i = 0; i < wear_eb_count; ++i) {
+               unsigned long wear = erase_block_wear[i];
+               if (wear < wmin)
+                       wmin = wear;
+               if (wear > wmax)
+                       wmax = wear;
+               tot += wear;
+       }
+       for (i = 0; i < 9; ++i) {
+               deciles[i] = 0;
+               decile_max[i] = (wmax * (i + 1) + 5) / 10;
+       }
+       deciles[9] = 0;
+       decile_max[9] = wmax;
+       for (i = 0; i < wear_eb_count; ++i) {
+               int d;
+               unsigned long wear = erase_block_wear[i];
+               for (d = 0; d < 10; ++d)
+                       if (wear <= decile_max[d]) {
+                               deciles[d] += 1;
+                               break;
+                       }
+       }
+       avg = tot / wear_eb_count;
+       /* Output wear report */
+       seq_printf(m, "Total numbers of erases:  %lu\n", tot);
+       seq_printf(m, "Number of erase blocks:   %u\n", wear_eb_count);
+       seq_printf(m, "Average number of erases: %lu\n", avg);
+       seq_printf(m, "Maximum number of erases: %lu\n", wmax);
+       seq_printf(m, "Minimum number of erases: %lu\n", wmin);
+       for (i = 0; i < 10; ++i) {
+               unsigned long from = (i ? decile_max[i - 1] + 1 : 0);
+               if (from > decile_max[i])
+                       continue;
+               seq_printf(m, "Number of ebs with erase counts from %lu to %lu : %lu\n",
+                       from,
+                       decile_max[i],
+                       deciles[i]);
+       }
+       return 0;
+ }
+ static int nandsim_debugfs_open(struct inode *inode, struct file *file)
+ {
+       return single_open(file, nandsim_debugfs_show, inode->i_private);
+ }
+ static const struct file_operations dfs_fops = {
+       .open           = nandsim_debugfs_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+ };
+ /**
+  * nandsim_debugfs_create - initialize debugfs
+  * @dev: nandsim device description object
+  *
+  * This function creates all debugfs files for UBI device @ubi. Returns zero in
+  * case of success and a negative error code in case of failure.
+  */
+ static int nandsim_debugfs_create(struct nandsim *dev)
+ {
+       struct nandsim_debug_info *dbg = &dev->dbg;
+       struct dentry *dent;
+       int err;
+       if (!IS_ENABLED(CONFIG_DEBUG_FS))
+               return 0;
+       dent = debugfs_create_dir("nandsim", NULL);
+       if (IS_ERR_OR_NULL(dent)) {
+               int err = dent ? -ENODEV : PTR_ERR(dent);
+               NS_ERR("cannot create \"nandsim\" debugfs directory, err %d\n",
+                       err);
+               return err;
+       }
+       dbg->dfs_root = dent;
+       dent = debugfs_create_file("wear_report", S_IRUSR,
+                                  dbg->dfs_root, dev, &dfs_fops);
+       if (IS_ERR_OR_NULL(dent))
+               goto out_remove;
+       dbg->dfs_wear_report = dent;
+       return 0;
+ out_remove:
+       debugfs_remove_recursive(dbg->dfs_root);
+       err = dent ? PTR_ERR(dent) : -ENODEV;
+       return err;
+ }
+ /**
+  * nandsim_debugfs_remove - destroy all debugfs files
+  */
+ static void nandsim_debugfs_remove(struct nandsim *ns)
+ {
+       if (IS_ENABLED(CONFIG_DEBUG_FS))
+               debugfs_remove_recursive(ns->dbg.dfs_root);
+ }
  /*
   * Allocate array of page pointers, create slab allocation for an array
   * and initialize the array by NULL pointers.
@@@ -911,8 -1029,6 +1029,6 @@@ static int setup_wear_reporting(struct 
  {
        size_t mem;
  
-       if (!rptwear)
-               return 0;
        wear_eb_count = div_u64(mtd->size, mtd->erasesize);
        mem = wear_eb_count * sizeof(unsigned long);
        if (mem / sizeof(unsigned long) != wear_eb_count) {
  
  static void update_wear(unsigned int erase_block_no)
  {
-       unsigned long wmin = -1, wmax = 0, avg;
-       unsigned long deciles[10], decile_max[10], tot = 0;
-       unsigned int i;
        if (!erase_block_wear)
                return;
        total_wear += 1;
+       /*
+        * TODO: Notify this through a debugfs entry,
+        * instead of showing an error message.
+        */
        if (total_wear == 0)
                NS_ERR("Erase counter total overflow\n");
        erase_block_wear[erase_block_no] += 1;
        if (erase_block_wear[erase_block_no] == 0)
                NS_ERR("Erase counter overflow for erase block %u\n", erase_block_no);
-       rptwear_cnt += 1;
-       if (rptwear_cnt < rptwear)
-               return;
-       rptwear_cnt = 0;
-       /* Calc wear stats */
-       for (i = 0; i < wear_eb_count; ++i) {
-               unsigned long wear = erase_block_wear[i];
-               if (wear < wmin)
-                       wmin = wear;
-               if (wear > wmax)
-                       wmax = wear;
-               tot += wear;
-       }
-       for (i = 0; i < 9; ++i) {
-               deciles[i] = 0;
-               decile_max[i] = (wmax * (i + 1) + 5) / 10;
-       }
-       deciles[9] = 0;
-       decile_max[9] = wmax;
-       for (i = 0; i < wear_eb_count; ++i) {
-               int d;
-               unsigned long wear = erase_block_wear[i];
-               for (d = 0; d < 10; ++d)
-                       if (wear <= decile_max[d]) {
-                               deciles[d] += 1;
-                               break;
-                       }
-       }
-       avg = tot / wear_eb_count;
-       /* Output wear report */
-       NS_INFO("*** Wear Report ***\n");
-       NS_INFO("Total numbers of erases:  %lu\n", tot);
-       NS_INFO("Number of erase blocks:   %u\n", wear_eb_count);
-       NS_INFO("Average number of erases: %lu\n", avg);
-       NS_INFO("Maximum number of erases: %lu\n", wmax);
-       NS_INFO("Minimum number of erases: %lu\n", wmin);
-       for (i = 0; i < 10; ++i) {
-               unsigned long from = (i ? decile_max[i - 1] + 1 : 0);
-               if (from > decile_max[i])
-                       continue;
-               NS_INFO("Number of ebs with erase counts from %lu to %lu : %lu\n",
-                       from,
-                       decile_max[i],
-                       deciles[i]);
-       }
-       NS_INFO("*** End of Wear Report ***\n");
  }
  
  /*
@@@ -1397,7 -1467,10 +1467,7 @@@ int do_read_error(struct nandsim *ns, i
        unsigned int page_no = ns->regs.row;
  
        if (read_error(page_no)) {
 -              int i;
 -              memset(ns->buf.byte, 0xFF, num);
 -              for (i = 0; i < num; ++i)
 -                      ns->buf.byte[i] = random32();
 +              prandom_bytes(ns->buf.byte, num);
                NS_WARN("simulating read error in page %u\n", page_no);
                return 1;
        }
@@@ -2327,6 -2400,9 +2397,9 @@@ static int __init ns_init_module(void
        if ((retval = setup_wear_reporting(nsmtd)) != 0)
                goto err_exit;
  
+       if ((retval = nandsim_debugfs_create(nand)) != 0)
+               goto err_exit;
        if ((retval = init_nandsim(nsmtd)) != 0)
                goto err_exit;
  
@@@ -2366,6 -2442,7 +2439,7 @@@ static void __exit ns_cleanup_module(vo
        struct nandsim *ns = ((struct nand_chip *)nsmtd->priv)->priv;
        int i;
  
+       nandsim_debugfs_remove(ns);
        free_nandsim(ns);    /* Free nandsim private resources */
        nand_release(nsmtd); /* Unregister driver */
        for (i = 0;i < ARRAY_SIZE(ns->partitions); ++i)
diff --combined drivers/mtd/nand/omap2.c
@@@ -27,6 -27,8 +27,6 @@@
  #include <linux/bch.h>
  #endif
  
 -#include <plat/dma.h>
 -#include <plat/gpmc.h>
  #include <linux/platform_data/mtd-nand-omap2.h>
  
  #define       DRIVER_NAME     "omap2-nand"
  #define       CS_MASK                         0x7
  #define       ENABLE_PREFETCH                 (0x1 << 7)
  #define       DMA_MPU_MODE_SHIFT              2
 +#define       ECCSIZE0_SHIFT                  12
  #define       ECCSIZE1_SHIFT                  22
  #define       ECC1RESULTSIZE                  0x1
  #define       ECCCLEAR                        0x100
  #define       ECC1                            0x1
 +#define       PREFETCH_FIFOTHRESHOLD_MAX      0x40
 +#define       PREFETCH_FIFOTHRESHOLD(val)     ((val) << 8)
 +#define       PREFETCH_STATUS_COUNT(val)      (val & 0x00003fff)
 +#define       PREFETCH_STATUS_FIFO_CNT(val)   ((val >> 24) & 0x7F)
 +#define       STATUS_BUFF_EMPTY               0x00000001
 +
 +#define OMAP24XX_DMA_GPMC             4
  
  /* oob info generated runtime depending on ecc algorithm and layout selected */
  static struct nand_ecclayout omap_oobinfo;
@@@ -275,7 -269,7 +275,7 @@@ static void omap_write_buf8(struct mtd_
                /* wait until buffer is available for write */
                do {
                        status = readl(info->reg.gpmc_status) &
 -                                      GPMC_STATUS_BUFF_EMPTY;
 +                                      STATUS_BUFF_EMPTY;
                } while (!status);
        }
  }
@@@ -313,7 -307,7 +313,7 @@@ static void omap_write_buf16(struct mtd
                /* wait until buffer is available for write */
                do {
                        status = readl(info->reg.gpmc_status) &
 -                                      GPMC_STATUS_BUFF_EMPTY;
 +                                      STATUS_BUFF_EMPTY;
                } while (!status);
        }
  }
@@@ -354,7 -348,7 +354,7 @@@ static void omap_read_buf_pref(struct m
        } else {
                do {
                        r_count = readl(info->reg.gpmc_prefetch_status);
 -                      r_count = GPMC_PREFETCH_STATUS_FIFO_CNT(r_count);
 +                      r_count = PREFETCH_STATUS_FIFO_CNT(r_count);
                        r_count = r_count >> 2;
                        ioread32_rep(info->nand.IO_ADDR_R, p, r_count);
                        p += r_count;
@@@ -401,7 -395,7 +401,7 @@@ static void omap_write_buf_pref(struct 
        } else {
                while (len) {
                        w_count = readl(info->reg.gpmc_prefetch_status);
 -                      w_count = GPMC_PREFETCH_STATUS_FIFO_CNT(w_count);
 +                      w_count = PREFETCH_STATUS_FIFO_CNT(w_count);
                        w_count = w_count >> 1;
                        for (i = 0; (i < w_count) && len; i++, len -= 2)
                                iowrite16(*p++, info->nand.IO_ADDR_W);
                do {
                        cpu_relax();
                        val = readl(info->reg.gpmc_prefetch_status);
 -                      val = GPMC_PREFETCH_STATUS_COUNT(val);
 +                      val = PREFETCH_STATUS_COUNT(val);
                } while (val && (tim++ < limit));
  
                /* disable and stop the PFPW engine */
@@@ -499,7 -493,7 +499,7 @@@ static inline int omap_nand_dma_transfe
        do {
                cpu_relax();
                val = readl(info->reg.gpmc_prefetch_status);
 -              val = GPMC_PREFETCH_STATUS_COUNT(val);
 +              val = PREFETCH_STATUS_COUNT(val);
        } while (val && (tim++ < limit));
  
        /* disable and stop the PFPW engine */
@@@ -562,7 -556,7 +562,7 @@@ static irqreturn_t omap_nand_irq(int th
        u32 bytes;
  
        bytes = readl(info->reg.gpmc_prefetch_status);
 -      bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
 +      bytes = PREFETCH_STATUS_FIFO_CNT(bytes);
        bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
        if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
                if (this_irq == info->gpmc_irq_count)
@@@ -688,7 -682,7 +688,7 @@@ static void omap_write_buf_irq_pref(str
        limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
        do {
                val = readl(info->reg.gpmc_prefetch_status);
 -              val = GPMC_PREFETCH_STATUS_COUNT(val);
 +              val = PREFETCH_STATUS_COUNT(val);
                cpu_relax();
        } while (val && (tim++ < limit));
  
@@@ -1002,7 -996,7 +1002,7 @@@ static int omap_wait(struct mtd_info *m
                cond_resched();
        }
  
 -      status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
 +      status = readb(info->reg.gpmc_nand_data);
        return status;
  }
  
@@@ -1035,45 -1029,19 +1035,45 @@@ static int omap_dev_ready(struct mtd_in
  static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode)
  {
        int nerrors;
 -      unsigned int dev_width;
 +      unsigned int dev_width, nsectors;
        struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
                                                   mtd);
        struct nand_chip *chip = mtd->priv;
 +      u32 val;
  
        nerrors = (info->nand.ecc.bytes == 13) ? 8 : 4;
        dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
 +      nsectors = 1;
        /*
         * Program GPMC to perform correction on one 512-byte sector at a time.
         * Using 4 sectors at a time (i.e. ecc.size = 2048) is also possible and
         * gives a slight (5%) performance gain (but requires additional code).
         */
 -      (void)gpmc_enable_hwecc_bch(info->gpmc_cs, mode, dev_width, 1, nerrors);
 +
 +      writel(ECC1, info->reg.gpmc_ecc_control);
 +
 +      /*
 +       * When using BCH, sector size is hardcoded to 512 bytes.
 +       * Here we are using wrapping mode 6 both for reading and writing, with:
 +       *  size0 = 0  (no additional protected byte in spare area)
 +       *  size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
 +       */
 +      val = (32 << ECCSIZE1_SHIFT) | (0 << ECCSIZE0_SHIFT);
 +      writel(val, info->reg.gpmc_ecc_size_config);
 +
 +      /* BCH configuration */
 +      val = ((1                        << 16) | /* enable BCH */
 +             (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */
 +             (0x06                     <<  8) | /* wrap mode = 6 */
 +             (dev_width                <<  7) | /* bus width */
 +             (((nsectors-1) & 0x7)     <<  4) | /* number of sectors */
 +             (info->gpmc_cs            <<  1) | /* ECC CS */
 +             (0x1));                            /* enable ECC */
 +
 +      writel(val, info->reg.gpmc_ecc_config);
 +
 +      /* clear ecc and enable bits */
 +      writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control);
  }
  
  /**
@@@ -1087,32 -1055,7 +1087,32 @@@ static int omap3_calculate_ecc_bch4(str
  {
        struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
                                                   mtd);
 -      return gpmc_calculate_ecc_bch4(info->gpmc_cs, dat, ecc_code);
 +      unsigned long nsectors, val1, val2;
 +      int i;
 +
 +      nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
 +
 +      for (i = 0; i < nsectors; i++) {
 +
 +              /* Read hw-computed remainder */
 +              val1 = readl(info->reg.gpmc_bch_result0[i]);
 +              val2 = readl(info->reg.gpmc_bch_result1[i]);
 +
 +              /*
 +               * Add constant polynomial to remainder, in order to get an ecc
 +               * sequence of 0xFFs for a buffer filled with 0xFFs; and
 +               * left-justify the resulting polynomial.
 +               */
 +              *ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF);
 +              *ecc_code++ = 0x13 ^ ((val2 >>  4) & 0xFF);
 +              *ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF));
 +              *ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF);
 +              *ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF);
 +              *ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF);
 +              *ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4);
 +      }
 +
 +      return 0;
  }
  
  /**
@@@ -1126,39 -1069,7 +1126,39 @@@ static int omap3_calculate_ecc_bch8(str
  {
        struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
                                                   mtd);
 -      return gpmc_calculate_ecc_bch8(info->gpmc_cs, dat, ecc_code);
 +      unsigned long nsectors, val1, val2, val3, val4;
 +      int i;
 +
 +      nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
 +
 +      for (i = 0; i < nsectors; i++) {
 +
 +              /* Read hw-computed remainder */
 +              val1 = readl(info->reg.gpmc_bch_result0[i]);
 +              val2 = readl(info->reg.gpmc_bch_result1[i]);
 +              val3 = readl(info->reg.gpmc_bch_result2[i]);
 +              val4 = readl(info->reg.gpmc_bch_result3[i]);
 +
 +              /*
 +               * Add constant polynomial to remainder, in order to get an ecc
 +               * sequence of 0xFFs for a buffer filled with 0xFFs.
 +               */
 +              *ecc_code++ = 0xef ^ (val4 & 0xFF);
 +              *ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF);
 +              *ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF);
 +              *ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF);
 +              *ecc_code++ = 0xed ^ (val3 & 0xFF);
 +              *ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF);
 +              *ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF);
 +              *ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
 +              *ecc_code++ = 0x97 ^ (val2 & 0xFF);
 +              *ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF);
 +              *ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
 +              *ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF);
 +              *ecc_code++ = 0xb5 ^ (val1 & 0xFF);
 +      }
 +
 +      return 0;
  }
  
  /**
@@@ -1214,7 -1125,7 +1214,7 @@@ static void omap3_free_bch(struct mtd_i
   */
  static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt)
  {
 -      int ret, max_errors;
 +      int max_errors;
        struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
                                                   mtd);
  #ifdef CONFIG_MTD_NAND_OMAP_BCH8
                goto fail;
        }
  
 -      /* initialize GPMC BCH engine */
 -      ret = gpmc_init_hwecc_bch(info->gpmc_cs, 1, max_errors);
 -      if (ret)
 -              goto fail;
 -
        /* software bch library is only used to detect and locate errors */
        info->bch = init_bch(13, max_errors, 0x201b /* hw polynomial */);
        if (!info->bch)
@@@ -1323,7 -1239,7 +1323,7 @@@ static void omap3_free_bch(struct mtd_i
  }
  #endif /* CONFIG_MTD_NAND_OMAP_BCH */
  
- static int __devinit omap_nand_probe(struct platform_device *pdev)
+ static int omap_nand_probe(struct platform_device *pdev)
  {
        struct omap_nand_info           *info;
        struct omap_nand_platform_data  *pdata;
@@@ -1597,7 -1513,7 +1597,7 @@@ static int omap_nand_remove(struct plat
        /* Release NAND device, its internal structures and partitions */
        nand_release(&info->mtd);
        iounmap(info->nand.IO_ADDR_R);
 -      release_mem_region(info->phys_base, NAND_IO_SIZE);
 +      release_mem_region(info->phys_base, info->mem_size);
        kfree(info);
        return 0;
  }
@@@ -730,11 -730,14 +730,14 @@@ static int s3c2410_nand_add_partition(s
                                      struct s3c2410_nand_mtd *mtd,
                                      struct s3c2410_nand_set *set)
  {
-       if (set)
+       if (set) {
                mtd->mtd.name = set->name;
  
-       return mtd_device_parse_register(&mtd->mtd, NULL, NULL,
+               return mtd_device_parse_register(&mtd->mtd, NULL, NULL,
                                         set->partitions, set->nr_partitions);
+       }
+       return -ENODEV;
  }
  
  /**
@@@ -879,7 -882,7 +882,7 @@@ static void s3c2410_nand_update_chip(st
        if (chip->ecc.mode != NAND_ECC_HW)
                return;
  
 -              /* change the behaviour depending on wether we are using
 +              /* change the behaviour depending on whether we are using
                 * the large or small page nand device */
  
        if (chip->page_shift > 10) {
  
  #include <linux/module.h>
  #include <linux/kernel.h>
+ #include <linux/completion.h>
  #include <linux/delay.h>
+ #include <linux/dmaengine.h>
+ #include <linux/dma-mapping.h>
  #include <linux/interrupt.h>
  #include <linux/io.h>
+ #include <linux/of.h>
+ #include <linux/of_device.h>
+ #include <linux/of_mtd.h>
  #include <linux/platform_device.h>
  #include <linux/pm_runtime.h>
+ #include <linux/sh_dma.h>
  #include <linux/slab.h>
  #include <linux/string.h>
  
@@@ -106,6 -113,84 +113,84 @@@ static void wait_completion(struct sh_f
        writeb(0x0, FLTRCR(flctl));
  }
  
+ static void flctl_dma_complete(void *param)
+ {
+       struct sh_flctl *flctl = param;
+       complete(&flctl->dma_complete);
+ }
+ static void flctl_release_dma(struct sh_flctl *flctl)
+ {
+       if (flctl->chan_fifo0_rx) {
+               dma_release_channel(flctl->chan_fifo0_rx);
+               flctl->chan_fifo0_rx = NULL;
+       }
+       if (flctl->chan_fifo0_tx) {
+               dma_release_channel(flctl->chan_fifo0_tx);
+               flctl->chan_fifo0_tx = NULL;
+       }
+ }
+ static void flctl_setup_dma(struct sh_flctl *flctl)
+ {
+       dma_cap_mask_t mask;
+       struct dma_slave_config cfg;
+       struct platform_device *pdev = flctl->pdev;
+       struct sh_flctl_platform_data *pdata = pdev->dev.platform_data;
+       int ret;
+       if (!pdata)
+               return;
+       if (pdata->slave_id_fifo0_tx <= 0 || pdata->slave_id_fifo0_rx <= 0)
+               return;
+       /* We can only either use DMA for both Tx and Rx or not use it at all */
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       flctl->chan_fifo0_tx = dma_request_channel(mask, shdma_chan_filter,
+                                           (void *)pdata->slave_id_fifo0_tx);
+       dev_dbg(&pdev->dev, "%s: TX: got channel %p\n", __func__,
+               flctl->chan_fifo0_tx);
+       if (!flctl->chan_fifo0_tx)
+               return;
+       memset(&cfg, 0, sizeof(cfg));
+       cfg.slave_id = pdata->slave_id_fifo0_tx;
+       cfg.direction = DMA_MEM_TO_DEV;
+       cfg.dst_addr = (dma_addr_t)FLDTFIFO(flctl);
+       cfg.src_addr = 0;
+       ret = dmaengine_slave_config(flctl->chan_fifo0_tx, &cfg);
+       if (ret < 0)
+               goto err;
+       flctl->chan_fifo0_rx = dma_request_channel(mask, shdma_chan_filter,
+                                           (void *)pdata->slave_id_fifo0_rx);
+       dev_dbg(&pdev->dev, "%s: RX: got channel %p\n", __func__,
+               flctl->chan_fifo0_rx);
+       if (!flctl->chan_fifo0_rx)
+               goto err;
+       cfg.slave_id = pdata->slave_id_fifo0_rx;
+       cfg.direction = DMA_DEV_TO_MEM;
+       cfg.dst_addr = 0;
+       cfg.src_addr = (dma_addr_t)FLDTFIFO(flctl);
+       ret = dmaengine_slave_config(flctl->chan_fifo0_rx, &cfg);
+       if (ret < 0)
+               goto err;
+       init_completion(&flctl->dma_complete);
+       return;
+ err:
+       flctl_release_dma(flctl);
+ }
  static void set_addr(struct mtd_info *mtd, int column, int page_addr)
  {
        struct sh_flctl *flctl = mtd_to_flctl(mtd);
@@@ -225,7 -310,7 +310,7 @@@ static enum flctl_ecc_res_t wait_recfif
  
                for (i = 0; i < 3; i++) {
                        uint8_t org;
-                       int index;
+                       unsigned int index;
  
                        data = readl(ecc_reg[i]);
  
@@@ -261,6 -346,70 +346,70 @@@ static void wait_wecfifo_ready(struct s
        timeout_error(flctl, __func__);
  }
  
+ static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf,
+                                       int len, enum dma_data_direction dir)
+ {
+       struct dma_async_tx_descriptor *desc = NULL;
+       struct dma_chan *chan;
+       enum dma_transfer_direction tr_dir;
+       dma_addr_t dma_addr;
+       dma_cookie_t cookie = -EINVAL;
+       uint32_t reg;
+       int ret;
+       if (dir == DMA_FROM_DEVICE) {
+               chan = flctl->chan_fifo0_rx;
+               tr_dir = DMA_DEV_TO_MEM;
+       } else {
+               chan = flctl->chan_fifo0_tx;
+               tr_dir = DMA_MEM_TO_DEV;
+       }
+       dma_addr = dma_map_single(chan->device->dev, buf, len, dir);
+       if (dma_addr)
+               desc = dmaengine_prep_slave_single(chan, dma_addr, len,
+                       tr_dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (desc) {
+               reg = readl(FLINTDMACR(flctl));
+               reg |= DREQ0EN;
+               writel(reg, FLINTDMACR(flctl));
+               desc->callback = flctl_dma_complete;
+               desc->callback_param = flctl;
+               cookie = dmaengine_submit(desc);
+               dma_async_issue_pending(chan);
+       } else {
+               /* DMA failed, fall back to PIO */
+               flctl_release_dma(flctl);
+               dev_warn(&flctl->pdev->dev,
+                        "DMA failed, falling back to PIO\n");
+               ret = -EIO;
+               goto out;
+       }
+       ret =
+       wait_for_completion_timeout(&flctl->dma_complete,
+                               msecs_to_jiffies(3000));
+       if (ret <= 0) {
+               chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+               dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n");
+       }
+ out:
+       reg = readl(FLINTDMACR(flctl));
+       reg &= ~DREQ0EN;
+       writel(reg, FLINTDMACR(flctl));
+       dma_unmap_single(chan->device->dev, dma_addr, len, dir);
+       /* ret > 0 is success */
+       return ret;
+ }
  static void read_datareg(struct sh_flctl *flctl, int offset)
  {
        unsigned long data;
@@@ -279,11 -428,20 +428,20 @@@ static void read_fiforeg(struct sh_flct
  
        len_4align = (rlen + 3) / 4;
  
+       /* initiate DMA transfer */
+       if (flctl->chan_fifo0_rx && rlen >= 32 &&
+               flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_DEV_TO_MEM) > 0)
+                       goto convert;   /* DMA success */
+       /* do polling transfer */
        for (i = 0; i < len_4align; i++) {
                wait_rfifo_ready(flctl);
                buf[i] = readl(FLDTFIFO(flctl));
-               buf[i] = be32_to_cpu(buf[i]);
        }
+ convert:
+       for (i = 0; i < len_4align; i++)
+               buf[i] = be32_to_cpu(buf[i]);
  }
  
  static enum flctl_ecc_res_t read_ecfiforeg
        return res;
  }
  
- static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+ static void write_fiforeg(struct sh_flctl *flctl, int rlen,
+                                               unsigned int offset)
  {
        int i, len_4align;
-       unsigned long *data = (unsigned long *)&flctl->done_buff[offset];
-       void *fifo_addr = (void *)FLDTFIFO(flctl);
+       unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
  
        len_4align = (rlen + 3) / 4;
        for (i = 0; i < len_4align; i++) {
                wait_wfifo_ready(flctl);
-               writel(cpu_to_be32(data[i]), fifo_addr);
+               writel(cpu_to_be32(buf[i]), FLDTFIFO(flctl));
        }
  }
  
- static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+ static void write_ec_fiforeg(struct sh_flctl *flctl, int rlen,
+                                               unsigned int offset)
  {
        int i, len_4align;
-       unsigned long *data = (unsigned long *)&flctl->done_buff[offset];
+       unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
  
        len_4align = (rlen + 3) / 4;
+       for (i = 0; i < len_4align; i++)
+               buf[i] = cpu_to_be32(buf[i]);
+       /* initiate DMA transfer */
+       if (flctl->chan_fifo0_tx && rlen >= 32 &&
+               flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_MEM_TO_DEV) > 0)
+                       return; /* DMA success */
+       /* do polling transfer */
        for (i = 0; i < len_4align; i++) {
                wait_wecfifo_ready(flctl);
-               writel(cpu_to_be32(data[i]), FLECFIFO(flctl));
+               writel(buf[i], FLECFIFO(flctl));
        }
  }
  
@@@ -727,9 -896,7 +896,9 @@@ static void flctl_select_chip(struct mt
  
                if (!flctl->qos_request) {
                        ret = dev_pm_qos_add_request(&flctl->pdev->dev,
 -                                                      &flctl->pm_qos, 100);
 +                                                      &flctl->pm_qos,
 +                                                      DEV_PM_QOS_LATENCY,
 +                                                      100);
                        if (ret < 0)
                                dev_err(&flctl->pdev->dev,
                                        "PM QoS request failed: %d\n", ret);
  static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
  {
        struct sh_flctl *flctl = mtd_to_flctl(mtd);
-       int index = flctl->index;
  
-       memcpy(&flctl->done_buff[index], buf, len);
+       memcpy(&flctl->done_buff[flctl->index], buf, len);
        flctl->index += len;
  }
  
  static uint8_t flctl_read_byte(struct mtd_info *mtd)
  {
        struct sh_flctl *flctl = mtd_to_flctl(mtd);
-       int index = flctl->index;
        uint8_t data;
  
-       data = flctl->done_buff[index];
+       data = flctl->done_buff[flctl->index];
        flctl->index++;
        return data;
  }
  
  static uint16_t flctl_read_word(struct mtd_info *mtd)
  {
-        struct sh_flctl *flctl = mtd_to_flctl(mtd);
-        int index = flctl->index;
-        uint16_t data;
-        uint16_t *buf = (uint16_t *)&flctl->done_buff[index];
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       uint16_t *buf = (uint16_t *)&flctl->done_buff[flctl->index];
  
-        data = *buf;
-        flctl->index += 2;
-        return data;
+       flctl->index += 2;
+       return *buf;
  }
  
  static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
  {
        struct sh_flctl *flctl = mtd_to_flctl(mtd);
-       int index = flctl->index;
  
-       memcpy(buf, &flctl->done_buff[index], len);
+       memcpy(buf, &flctl->done_buff[flctl->index], len);
        flctl->index += len;
  }
  
@@@ -858,7 -1019,74 +1021,74 @@@ static irqreturn_t flctl_handle_flste(i
        return IRQ_HANDLED;
  }
  
- static int __devinit flctl_probe(struct platform_device *pdev)
+ #ifdef CONFIG_OF
+ struct flctl_soc_config {
+       unsigned long flcmncr_val;
+       unsigned has_hwecc:1;
+       unsigned use_holden:1;
+ };
+ static struct flctl_soc_config flctl_sh7372_config = {
+       .flcmncr_val = CLK_16B_12L_4H | TYPESEL_SET | SHBUSSEL,
+       .has_hwecc = 1,
+       .use_holden = 1,
+ };
+ static const struct of_device_id of_flctl_match[] = {
+       { .compatible = "renesas,shmobile-flctl-sh7372",
+                               .data = &flctl_sh7372_config },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, of_flctl_match);
+ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
+ {
+       const struct of_device_id *match;
+       struct flctl_soc_config *config;
+       struct sh_flctl_platform_data *pdata;
+       struct device_node *dn = dev->of_node;
+       int ret;
+       match = of_match_device(of_flctl_match, dev);
+       if (match)
+               config = (struct flctl_soc_config *)match->data;
+       else {
+               dev_err(dev, "%s: no OF configuration attached\n", __func__);
+               return NULL;
+       }
+       pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data),
+                                                               GFP_KERNEL);
+       if (!pdata) {
+               dev_err(dev, "%s: failed to allocate config data\n", __func__);
+               return NULL;
+       }
+       /* set SoC specific options */
+       pdata->flcmncr_val = config->flcmncr_val;
+       pdata->has_hwecc = config->has_hwecc;
+       pdata->use_holden = config->use_holden;
+       /* parse user defined options */
+       ret = of_get_nand_bus_width(dn);
+       if (ret == 16)
+               pdata->flcmncr_val |= SEL_16BIT;
+       else if (ret != 8) {
+               dev_err(dev, "%s: invalid bus width\n", __func__);
+               return NULL;
+       }
+       return pdata;
+ }
+ #else /* CONFIG_OF */
+ #define of_flctl_match NULL
+ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
+ {
+       return NULL;
+ }
+ #endif /* CONFIG_OF */
+ static int flctl_probe(struct platform_device *pdev)
  {
        struct resource *res;
        struct sh_flctl *flctl;
        struct sh_flctl_platform_data *pdata;
        int ret = -ENXIO;
        int irq;
-       pdata = pdev->dev.platform_data;
-       if (pdata == NULL) {
-               dev_err(&pdev->dev, "no platform data defined\n");
-               return -EINVAL;
-       }
+       struct mtd_part_parser_data ppdata = {};
  
        flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
        if (!flctl) {
                goto err_flste;
        }
  
+       if (pdev->dev.of_node)
+               pdata = flctl_parse_dt(&pdev->dev);
+       else
+               pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(&pdev->dev, "no setup data defined\n");
+               ret = -EINVAL;
+               goto err_pdata;
+       }
        platform_set_drvdata(pdev, flctl);
        flctl_mtd = &flctl->mtd;
        nand = &flctl->chip;
        pm_runtime_enable(&pdev->dev);
        pm_runtime_resume(&pdev->dev);
  
+       flctl_setup_dma(flctl);
        ret = nand_scan_ident(flctl_mtd, 1, NULL);
        if (ret)
                goto err_chip;
        if (ret)
                goto err_chip;
  
-       mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts);
+       ppdata.of_node = pdev->dev.of_node;
+       ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts,
+                       pdata->nr_parts);
  
        return 0;
  
  err_chip:
+       flctl_release_dma(flctl);
        pm_runtime_disable(&pdev->dev);
+ err_pdata:
        free_irq(irq, flctl);
  err_flste:
        iounmap(flctl->reg);
@@@ -958,10 -1198,11 +1200,11 @@@ err_iomap
        return ret;
  }
  
- static int __devexit flctl_remove(struct platform_device *pdev)
+ static int flctl_remove(struct platform_device *pdev)
  {
        struct sh_flctl *flctl = platform_get_drvdata(pdev);
  
+       flctl_release_dma(flctl);
        nand_release(&flctl->mtd);
        pm_runtime_disable(&pdev->dev);
        free_irq(platform_get_irq(pdev, 0), flctl);
@@@ -976,6 -1217,7 +1219,7 @@@ static struct platform_driver flctl_dri
        .driver = {
                .name   = "sh_flctl",
                .owner  = THIS_MODULE,
+               .of_match_table = of_flctl_match,
        },
  };
  
  #include <linux/regulator/consumer.h>
  
  #include <asm/mach/flash.h>
 -#include <plat/gpmc.h>
  #include <linux/platform_data/mtd-onenand-omap2.h>
  #include <asm/gpio.h>
  
 -#include <plat/dma.h>
 -#include <plat/cpu.h>
 +#include <linux/omap-dma.h>
  
  #define DRIVER_NAME "omap2-onenand"
  
@@@ -61,7 -63,6 +61,7 @@@ struct omap2_onenand 
        int freq;
        int (*setup)(void __iomem *base, int *freq_ptr);
        struct regulator *regulator;
 +      u8 flags;
  };
  
  static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
@@@ -154,7 -155,7 +154,7 @@@ static int omap2_onenand_wait(struct mt
                if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
                        syscfg |= ONENAND_SYS_CFG1_IOBE;
                        write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
 -                      if (cpu_is_omap34xx())
 +                      if (c->flags & ONENAND_IN_OMAP34XX)
                                /* Add a delay to let GPIO settle */
                                syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
                }
@@@ -445,19 -446,13 +445,19 @@@ out_copy
  
  #else
  
 -int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
 -                               unsigned char *buffer, int offset,
 -                               size_t count);
 +static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                                      unsigned char *buffer, int offset,
 +                                      size_t count)
 +{
 +      return -ENOSYS;
 +}
  
 -int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
 -                                const unsigned char *buffer,
 -                                int offset, size_t count);
 +static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                       const unsigned char *buffer,
 +                                       int offset, size_t count)
 +{
 +      return -ENOSYS;
 +}
  
  #endif
  
@@@ -555,19 -550,13 +555,19 @@@ static int omap2_onenand_write_bufferra
  
  #else
  
 -int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
 -                               unsigned char *buffer, int offset,
 -                               size_t count);
 +static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
 +                                      unsigned char *buffer, int offset,
 +                                      size_t count)
 +{
 +      return -ENOSYS;
 +}
  
 -int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
 -                                const unsigned char *buffer,
 -                                int offset, size_t count);
 +static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
 +                                       const unsigned char *buffer,
 +                                       int offset, size_t count)
 +{
 +      return -ENOSYS;
 +}
  
  #endif
  
@@@ -630,7 -619,7 +630,7 @@@ static int omap2_onenand_disable(struc
        return ret;
  }
  
- static int __devinit omap2_onenand_probe(struct platform_device *pdev)
+ static int omap2_onenand_probe(struct platform_device *pdev)
  {
        struct omap_onenand_platform_data *pdata;
        struct omap2_onenand *c;
  
        init_completion(&c->irq_done);
        init_completion(&c->dma_done);
 +      c->flags = pdata->flags;
        c->gpmc_cs = pdata->cs;
        c->gpio_irq = pdata->gpio_irq;
        c->dma_channel = pdata->dma_channel;
        this = &c->onenand;
        if (c->dma_channel >= 0) {
                this->wait = omap2_onenand_wait;
 -              if (cpu_is_omap34xx()) {
 +              if (c->flags & ONENAND_IN_OMAP34XX) {
                        this->read_bufferram = omap3_onenand_read_bufferram;
                        this->write_bufferram = omap3_onenand_write_bufferram;
                } else {
@@@ -799,7 -787,7 +799,7 @@@ err_kfree
        return r;
  }
  
- static int __devexit omap2_onenand_remove(struct platform_device *pdev)
+ static int omap2_onenand_remove(struct platform_device *pdev)
  {
        struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
  
        }
        iounmap(c->onenand.base);
        release_mem_region(c->phys_base, c->mem_size);
 -      gpmc_cs_free(c->gpmc_cs);
        kfree(c);
  
        return 0;
  
  static struct platform_driver omap2_onenand_driver = {
        .probe          = omap2_onenand_probe,
-       .remove         = __devexit_p(omap2_onenand_remove),
+       .remove         = omap2_onenand_remove,
        .shutdown       = omap2_onenand_shutdown,
        .driver         = {
                .name   = DRIVER_NAME,
@@@ -157,7 -157,6 +157,7 @@@ struct bcma_host_ops 
  
  /* Chip IDs of SoCs */
  #define BCMA_CHIP_ID_BCM4706  0x5300
 +#define  BCMA_PKG_ID_BCM4706L 1
  #define BCMA_CHIP_ID_BCM4716  0x4716
  #define  BCMA_PKG_ID_BCM4716  8
  #define  BCMA_PKG_ID_BCM4717  9
  #define BCMA_CHIP_ID_BCM4749  0x4749
  #define BCMA_CHIP_ID_BCM5356  0x5356
  #define BCMA_CHIP_ID_BCM5357  0x5357
 +#define  BCMA_PKG_ID_BCM5358  9
 +#define  BCMA_PKG_ID_BCM47186 10
 +#define  BCMA_PKG_ID_BCM5357  11
  #define BCMA_CHIP_ID_BCM53572 53572
 +#define  BCMA_PKG_ID_BCM47188 9
  
  struct bcma_device {
        struct bcma_bus *bus;
@@@ -256,7 -251,7 +256,7 @@@ struct bcma_bus 
        u8 num;
  
        struct bcma_drv_cc drv_cc;
 -      struct bcma_drv_pci drv_pci;
 +      struct bcma_drv_pci drv_pci[2];
        struct bcma_drv_mips drv_mips;
        struct bcma_drv_gmac_cmn drv_gmac_cmn;
  
@@@ -350,6 -345,7 +350,7 @@@ extern void bcma_core_set_clockmode(str
                                    enum bcma_clkmode clkmode);
  extern void bcma_core_pll_ctl(struct bcma_device *core, u32 req, u32 status,
                              bool on);
+ extern u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset);
  #define BCMA_DMA_TRANSLATION_MASK     0xC0000000
  #define  BCMA_DMA_TRANSLATION_NONE    0x00000000
  #define  BCMA_DMA_TRANSLATION_DMA32_CMT       0x40000000 /* Client Mode Translation for 32-bit DMA */