These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / mtd / nand / pxa3xx_nand.c
index a4615fc..e453ae9 100644 (file)
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
+#include <linux/dma/pxa-dma.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_mtd.h>
 
-#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
+#if defined(CONFIG_ARM) && (defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP))
 #define ARCH_HAS_DMA
 #endif
 
-#ifdef ARCH_HAS_DMA
-#include <mach/dma.h>
-#endif
-
 #include <linux/platform_data/mtd-nand-pxa3xx.h>
 
 #define        CHIP_DELAY_TIMEOUT      msecs_to_jiffies(200)
 
 /*
  * Define a buffer size for the initial command that detects the flash device:
- * STATUS, READID and PARAM. The largest of these is the PARAM command,
- * needing 256 bytes.
+ * STATUS, READID and PARAM.
+ * ONFI param page is 256 bytes, and there are three redundant copies
+ * to be read. JEDEC param page is 512 bytes, and there are also three
+ * redundant copies to be read.
+ * Hence this buffer should be at least 512 x 3. Let's pick 2048.
  */
-#define INIT_BUFFER_SIZE       256
+#define INIT_BUFFER_SIZE       2048
 
 /* registers and bit definitions */
 #define NDCR           (0x00) /* Control register */
@@ -74,7 +76,8 @@
 #define NDCR_ND_MODE           (0x3 << 21)
 #define NDCR_NAND_MODE         (0x0)
 #define NDCR_CLR_PG_CNT                (0x1 << 20)
-#define NDCR_STOP_ON_UNCOR     (0x1 << 19)
+#define NFCV1_NDCR_ARB_CNTL    (0x1 << 19)
+#define NFCV2_NDCR_STOP_ON_UNCOR       (0x1 << 19)
 #define NDCR_RD_ID_CNT_MASK    (0x7 << 16)
 #define NDCR_RD_ID_CNT(x)      (((x) << 16) & NDCR_RD_ID_CNT_MASK)
 
 #define EXT_CMD_TYPE_LAST_RW   1 /* Last naked read/write */
 #define EXT_CMD_TYPE_MONO      0 /* Monolithic read/write */
 
+/*
+ * This should be large enough to read 'ONFI' and 'JEDEC'.
+ * Let's use 7 bytes, which is the maximum ID count supported
+ * by the controller (see NDCR_RD_ID_CNT_MASK).
+ */
+#define READ_ID_BYTES          7
+
 /* macros for registers read/write */
 #define nand_writel(info, off, val)    \
        writel_relaxed((val), (info)->mmio_base + (off))
@@ -172,8 +182,6 @@ struct pxa3xx_nand_host {
        /* calculated from pxa3xx_nand_flash data */
        unsigned int            col_addr_cycles;
        unsigned int            row_addr_cycles;
-       size_t                  read_id_bytes;
-
 };
 
 struct pxa3xx_nand_info {
@@ -192,6 +200,10 @@ struct pxa3xx_nand_info {
        unsigned int            oob_buff_pos;
 
        /* DMA information */
+       struct scatterlist      sg;
+       enum dma_data_direction dma_dir;
+       struct dma_chan         *dma_chan;
+       dma_cookie_t            dma_cookie;
        int                     drcmr_dat;
        int                     drcmr_cmd;
 
@@ -199,8 +211,6 @@ struct pxa3xx_nand_info {
        unsigned char           *oob_buff;
        dma_addr_t              data_buff_phys;
        int                     data_dma_ch;
-       struct pxa_dma_desc     *data_desc;
-       dma_addr_t              data_desc_addr;
 
        struct pxa3xx_nand_host *host[NUM_CHIP_SELECT];
        unsigned int            state;
@@ -243,6 +253,25 @@ static bool use_dma = 1;
 module_param(use_dma, bool, 0444);
 MODULE_PARM_DESC(use_dma, "enable DMA for data transferring to/from NAND HW");
 
+struct pxa3xx_nand_timing {
+       unsigned int    tCH;  /* Enable signal hold time */
+       unsigned int    tCS;  /* Enable signal setup time */
+       unsigned int    tWH;  /* ND_nWE high duration */
+       unsigned int    tWP;  /* ND_nWE pulse time */
+       unsigned int    tRH;  /* ND_nRE high duration */
+       unsigned int    tRP;  /* ND_nRE pulse width */
+       unsigned int    tR;   /* ND_nWE high to ND_nRE low for read */
+       unsigned int    tWHR; /* ND_nWE high to ND_nRE low for status read */
+       unsigned int    tAR;  /* ND_ALE low to ND_nRE low delay */
+};
+
+struct pxa3xx_nand_flash {
+       uint32_t        chip_id;
+       unsigned int    flash_width;    /* Width of Flash memory (DWIDTH_M) */
+       unsigned int    dfc_width;      /* Width of flash controller(DWIDTH_C) */
+       struct pxa3xx_nand_timing *timing;      /* NAND Flash timing */
+};
+
 static struct pxa3xx_nand_timing timing[] = {
        { 40, 80, 60, 100, 80, 100, 90000, 400, 40, },
        { 10,  0, 20,  40, 30,  40, 11123, 110, 10, },
@@ -251,15 +280,14 @@ static struct pxa3xx_nand_timing timing[] = {
 };
 
 static struct pxa3xx_nand_flash builtin_flash_types[] = {
-{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
-{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
-{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
-{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
-{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
-{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
-{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
-{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
-{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
+       { 0x46ec, 16, 16, &timing[1] },
+       { 0xdaec,  8,  8, &timing[1] },
+       { 0xd7ec,  8,  8, &timing[1] },
+       { 0xa12c,  8,  8, &timing[2] },
+       { 0xb12c, 16, 16, &timing[2] },
+       { 0xdc2c,  8,  8, &timing[2] },
+       { 0xcc2c, 16, 16, &timing[2] },
+       { 0xba20, 16, 16, &timing[3] },
 };
 
 static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' };
@@ -320,9 +348,6 @@ static struct nand_ecclayout ecc_layout_4KB_bch8bit = {
        .oobfree = { }
 };
 
-/* Define a default flash type setting serve as flash detecting only */
-#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
-
 #define NDTR0_tCH(c)   (min((c), 7) << 19)
 #define NDTR0_tCS(c)   (min((c), 7) << 16)
 #define NDTR0_tWH(c)   (min((c), 7) << 11)
@@ -384,6 +409,128 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
        nand_writel(info, NDTR1CS0, ndtr1);
 }
 
+static void pxa3xx_nand_set_sdr_timing(struct pxa3xx_nand_host *host,
+                                      const struct nand_sdr_timings *t)
+{
+       struct pxa3xx_nand_info *info = host->info_data;
+       struct nand_chip *chip = &host->chip;
+       unsigned long nand_clk = clk_get_rate(info->clk);
+       uint32_t ndtr0, ndtr1;
+
+       u32 tCH_min = DIV_ROUND_UP(t->tCH_min, 1000);
+       u32 tCS_min = DIV_ROUND_UP(t->tCS_min, 1000);
+       u32 tWH_min = DIV_ROUND_UP(t->tWH_min, 1000);
+       u32 tWP_min = DIV_ROUND_UP(t->tWC_min - t->tWH_min, 1000);
+       u32 tREH_min = DIV_ROUND_UP(t->tREH_min, 1000);
+       u32 tRP_min = DIV_ROUND_UP(t->tRC_min - t->tREH_min, 1000);
+       u32 tR = chip->chip_delay * 1000;
+       u32 tWHR_min = DIV_ROUND_UP(t->tWHR_min, 1000);
+       u32 tAR_min = DIV_ROUND_UP(t->tAR_min, 1000);
+
+       /* fallback to a default value if tR = 0 */
+       if (!tR)
+               tR = 20000;
+
+       ndtr0 = NDTR0_tCH(ns2cycle(tCH_min, nand_clk)) |
+               NDTR0_tCS(ns2cycle(tCS_min, nand_clk)) |
+               NDTR0_tWH(ns2cycle(tWH_min, nand_clk)) |
+               NDTR0_tWP(ns2cycle(tWP_min, nand_clk)) |
+               NDTR0_tRH(ns2cycle(tREH_min, nand_clk)) |
+               NDTR0_tRP(ns2cycle(tRP_min, nand_clk));
+
+       ndtr1 = NDTR1_tR(ns2cycle(tR, nand_clk)) |
+               NDTR1_tWHR(ns2cycle(tWHR_min, nand_clk)) |
+               NDTR1_tAR(ns2cycle(tAR_min, nand_clk));
+
+       info->ndtr0cs0 = ndtr0;
+       info->ndtr1cs0 = ndtr1;
+       nand_writel(info, NDTR0CS0, ndtr0);
+       nand_writel(info, NDTR1CS0, ndtr1);
+}
+
+static int pxa3xx_nand_init_timings_compat(struct pxa3xx_nand_host *host,
+                                          unsigned int *flash_width,
+                                          unsigned int *dfc_width)
+{
+       struct nand_chip *chip = &host->chip;
+       struct pxa3xx_nand_info *info = host->info_data;
+       const struct pxa3xx_nand_flash *f = NULL;
+       int i, id, ntypes;
+
+       ntypes = ARRAY_SIZE(builtin_flash_types);
+
+       chip->cmdfunc(host->mtd, NAND_CMD_READID, 0x00, -1);
+
+       id = chip->read_byte(host->mtd);
+       id |= chip->read_byte(host->mtd) << 0x8;
+
+       for (i = 0; i < ntypes; i++) {
+               f = &builtin_flash_types[i];
+
+               if (f->chip_id == id)
+                       break;
+       }
+
+       if (i == ntypes) {
+               dev_err(&info->pdev->dev, "Error: timings not found\n");
+               return -EINVAL;
+       }
+
+       pxa3xx_nand_set_timing(host, f->timing);
+
+       *flash_width = f->flash_width;
+       *dfc_width = f->dfc_width;
+
+       return 0;
+}
+
+static int pxa3xx_nand_init_timings_onfi(struct pxa3xx_nand_host *host,
+                                        int mode)
+{
+       const struct nand_sdr_timings *timings;
+
+       mode = fls(mode) - 1;
+       if (mode < 0)
+               mode = 0;
+
+       timings = onfi_async_timing_mode_to_sdr_timings(mode);
+       if (IS_ERR(timings))
+               return PTR_ERR(timings);
+
+       pxa3xx_nand_set_sdr_timing(host, timings);
+
+       return 0;
+}
+
+static int pxa3xx_nand_init(struct pxa3xx_nand_host *host)
+{
+       struct nand_chip *chip = &host->chip;
+       struct pxa3xx_nand_info *info = host->info_data;
+       unsigned int flash_width = 0, dfc_width = 0;
+       int mode, err;
+
+       mode = onfi_get_async_timing_mode(chip);
+       if (mode == ONFI_TIMING_MODE_UNKNOWN) {
+               err = pxa3xx_nand_init_timings_compat(host, &flash_width,
+                                                     &dfc_width);
+               if (err)
+                       return err;
+
+               if (flash_width == 16) {
+                       info->reg_ndcr |= NDCR_DWIDTH_M;
+                       chip->options |= NAND_BUSWIDTH_16;
+               }
+
+               info->reg_ndcr |= (dfc_width == 16) ? NDCR_DWIDTH_C : 0;
+       } else {
+               err = pxa3xx_nand_init_timings_onfi(host, mode);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
 /*
  * Set the data and OOB size, depending on the selected
  * spare and ECC configuration.
@@ -438,8 +585,8 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
        ndcr |= NDCR_ND_RUN;
 
        /* clear status bits and run */
-       nand_writel(info, NDCR, 0);
        nand_writel(info, NDSR, NDSR_MASK);
+       nand_writel(info, NDCR, 0);
        nand_writel(info, NDCR, ndcr);
 }
 
@@ -459,6 +606,9 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
                ndcr &= ~NDCR_ND_RUN;
                nand_writel(info, NDCR, ndcr);
        }
+       if (info->dma_chan)
+               dmaengine_terminate_all(info->dma_chan);
+
        /* clear status bits */
        nand_writel(info, NDSR, NDSR_MASK);
 }
@@ -483,7 +633,8 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
 static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len)
 {
        if (info->ecc_bch) {
-               int timeout;
+               u32 val;
+               int ret;
 
                /*
                 * According to the datasheet, when reading from NDDB
@@ -494,18 +645,14 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len)
                 * the polling on the last read.
                 */
                while (len > 8) {
-                       __raw_readsl(info->mmio_base + NDDB, data, 8);
-
-                       for (timeout = 0;
-                            !(nand_readl(info, NDSR) & NDSR_RDDREQ);
-                            timeout++) {
-                               if (timeout >= 5) {
-                                       dev_err(&info->pdev->dev,
-                                               "Timeout on RDDREQ while draining the FIFO\n");
-                                       return;
-                               }
-
-                               mdelay(1);
+                       ioread32_rep(info->mmio_base + NDDB, data, 8);
+
+                       ret = readl_relaxed_poll_timeout(info->mmio_base + NDSR, val,
+                                                        val & NDSR_RDDREQ, 1000, 5000);
+                       if (ret) {
+                               dev_err(&info->pdev->dev,
+                                       "Timeout on RDDREQ while draining the FIFO\n");
+                               return;
                        }
 
                        data += 32;
@@ -513,7 +660,7 @@ static void drain_fifo(struct pxa3xx_nand_info *info, void *data, int len)
                }
        }
 
-       __raw_readsl(info->mmio_base + NDDB, data, len);
+       ioread32_rep(info->mmio_base + NDDB, data, len);
 }
 
 static void handle_data_pio(struct pxa3xx_nand_info *info)
@@ -522,14 +669,14 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
 
        switch (info->state) {
        case STATE_PIO_WRITING:
-               __raw_writesl(info->mmio_base + NDDB,
-                             info->data_buff + info->data_buff_pos,
-                             DIV_ROUND_UP(do_bytes, 4));
+               writesl(info->mmio_base + NDDB,
+                       info->data_buff + info->data_buff_pos,
+                       DIV_ROUND_UP(do_bytes, 4));
 
                if (info->oob_size > 0)
-                       __raw_writesl(info->mmio_base + NDDB,
-                                     info->oob_buff + info->oob_buff_pos,
-                                     DIV_ROUND_UP(info->oob_size, 4));
+                       writesl(info->mmio_base + NDDB,
+                               info->oob_buff + info->oob_buff_pos,
+                               DIV_ROUND_UP(info->oob_size, 4));
                break;
        case STATE_PIO_READING:
                drain_fifo(info,
@@ -553,57 +700,61 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
        info->data_size -= do_bytes;
 }
 
-#ifdef ARCH_HAS_DMA
-static void start_data_dma(struct pxa3xx_nand_info *info)
+static void pxa3xx_nand_data_dma_irq(void *data)
 {
-       struct pxa_dma_desc *desc = info->data_desc;
-       int dma_len = ALIGN(info->data_size + info->oob_size, 32);
+       struct pxa3xx_nand_info *info = data;
+       struct dma_tx_state state;
+       enum dma_status status;
 
-       desc->ddadr = DDADR_STOP;
-       desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
+       status = dmaengine_tx_status(info->dma_chan, info->dma_cookie, &state);
+       if (likely(status == DMA_COMPLETE)) {
+               info->state = STATE_DMA_DONE;
+       } else {
+               dev_err(&info->pdev->dev, "DMA error on data channel\n");
+               info->retcode = ERR_DMABUSERR;
+       }
+       dma_unmap_sg(info->dma_chan->device->dev, &info->sg, 1, info->dma_dir);
+
+       nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
+       enable_int(info, NDCR_INT_MASK);
+}
+
+static void start_data_dma(struct pxa3xx_nand_info *info)
+{
+       enum dma_transfer_direction direction;
+       struct dma_async_tx_descriptor *tx;
 
        switch (info->state) {
        case STATE_DMA_WRITING:
-               desc->dsadr = info->data_buff_phys;
-               desc->dtadr = info->mmio_phys + NDDB;
-               desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
+               info->dma_dir = DMA_TO_DEVICE;
+               direction = DMA_MEM_TO_DEV;
                break;
        case STATE_DMA_READING:
-               desc->dtadr = info->data_buff_phys;
-               desc->dsadr = info->mmio_phys + NDDB;
-               desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
+               info->dma_dir = DMA_FROM_DEVICE;
+               direction = DMA_DEV_TO_MEM;
                break;
        default:
                dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
                                info->state);
                BUG();
        }
-
-       DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
-       DDADR(info->data_dma_ch) = info->data_desc_addr;
-       DCSR(info->data_dma_ch) |= DCSR_RUN;
-}
-
-static void pxa3xx_nand_data_dma_irq(int channel, void *data)
-{
-       struct pxa3xx_nand_info *info = data;
-       uint32_t dcsr;
-
-       dcsr = DCSR(channel);
-       DCSR(channel) = dcsr;
-
-       if (dcsr & DCSR_BUSERR) {
-               info->retcode = ERR_DMABUSERR;
+       info->sg.length = info->data_size +
+               (info->oob_size ? info->spare_size + info->ecc_size : 0);
+       dma_map_sg(info->dma_chan->device->dev, &info->sg, 1, info->dma_dir);
+
+       tx = dmaengine_prep_slave_sg(info->dma_chan, &info->sg, 1, direction,
+                                    DMA_PREP_INTERRUPT);
+       if (!tx) {
+               dev_err(&info->pdev->dev, "prep_slave_sg() failed\n");
+               return;
        }
-
-       info->state = STATE_DMA_DONE;
-       enable_int(info, NDCR_INT_MASK);
-       nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
+       tx->callback = pxa3xx_nand_data_dma_irq;
+       tx->callback_param = info;
+       info->dma_cookie = dmaengine_submit(tx);
+       dma_async_issue_pending(info->dma_chan);
+       dev_dbg(&info->pdev->dev, "%s(dir=%d cookie=%x size=%u)\n",
+               __func__, direction, info->dma_cookie, info->sg.length);
 }
-#else
-static void start_data_dma(struct pxa3xx_nand_info *info)
-{}
-#endif
 
 static irqreturn_t pxa3xx_nand_irq_thread(int irq, void *data)
 {
@@ -677,8 +828,14 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
                is_ready = 1;
        }
 
+       /*
+        * Clear all status bit before issuing the next command, which
+        * can and will alter the status bits and will deserve a new
+        * interrupt on its own. This lets the controller exit the IRQ
+        */
+       nand_writel(info, NDSR, status);
+
        if (status & NDSR_WRCMDREQ) {
-               nand_writel(info, NDSR, NDSR_WRCMDREQ);
                status &= ~NDSR_WRCMDREQ;
                info->state = STATE_CMD_HANDLE;
 
@@ -699,8 +856,6 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
                        nand_writel(info, NDCB0, info->ndcb3);
        }
 
-       /* clear NDSR to let the controller exit the IRQ */
-       nand_writel(info, NDSR, status);
        if (is_completed)
                complete(&info->cmd_complete);
        if (is_ready)
@@ -901,18 +1056,18 @@ static int prepare_set_command(struct pxa3xx_nand_info *info, int command,
                break;
 
        case NAND_CMD_PARAM:
-               info->buf_count = 256;
+               info->buf_count = INIT_BUFFER_SIZE;
                info->ndcb0 |= NDCB0_CMD_TYPE(0)
                                | NDCB0_ADDR_CYC(1)
                                | NDCB0_LEN_OVRD
                                | command;
                info->ndcb1 = (column & 0xFF);
-               info->ndcb3 = 256;
-               info->data_size = 256;
+               info->ndcb3 = INIT_BUFFER_SIZE;
+               info->data_size = INIT_BUFFER_SIZE;
                break;
 
        case NAND_CMD_READID:
-               info->buf_count = host->read_id_bytes;
+               info->buf_count = READ_ID_BYTES;
                info->ndcb0 |= NDCB0_CMD_TYPE(3)
                                | NDCB0_ADDR_CYC(1)
                                | command;
@@ -1118,7 +1273,8 @@ static void nand_cmdfunc_extended(struct mtd_info *mtd,
 }
 
 static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
-               struct nand_chip *chip, const uint8_t *buf, int oob_required)
+               struct nand_chip *chip, const uint8_t *buf, int oob_required,
+               int page)
 {
        chip->write_buf(mtd, buf, mtd->writesize);
        chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -1231,106 +1387,83 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
        return NAND_STATUS_READY;
 }
 
-static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
-                                   const struct pxa3xx_nand_flash *f)
+static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info)
 {
        struct platform_device *pdev = info->pdev;
        struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct pxa3xx_nand_host *host = info->host[info->cs];
-       uint32_t ndcr = 0x0; /* enable all interrupts */
-
-       if (f->page_size != 2048 && f->page_size != 512) {
-               dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
-               return -EINVAL;
-       }
-
-       if (f->flash_width != 16 && f->flash_width != 8) {
-               dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
-               return -EINVAL;
-       }
-
-       /* calculate flash information */
-       host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
-
-       /* calculate addressing information */
-       host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
-
-       if (f->num_blocks * f->page_per_block > 65536)
-               host->row_addr_cycles = 3;
-       else
-               host->row_addr_cycles = 2;
-
-       ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
-       ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
-       ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
-       ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
-       ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
-       ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
-
-       ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
-       ndcr |= NDCR_SPARE_EN; /* enable spare by default */
+       struct mtd_info *mtd = host->mtd;
+       struct nand_chip *chip = mtd->priv;
 
-       info->reg_ndcr = ndcr;
+       /* configure default flash values */
+       info->reg_ndcr = 0x0; /* enable all interrupts */
+       info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
+       info->reg_ndcr |= NDCR_RD_ID_CNT(READ_ID_BYTES);
+       info->reg_ndcr |= NDCR_SPARE_EN; /* enable spare by default */
+       info->reg_ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+       info->reg_ndcr |= (chip->page_shift == 6) ? NDCR_PG_PER_BLK : 0;
+       info->reg_ndcr |= (mtd->writesize == 2048) ? NDCR_PAGE_SZ : 0;
 
-       pxa3xx_nand_set_timing(host, f->timing);
        return 0;
 }
 
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
-       /*
-        * We set 0 by hard coding here, for we don't support keep_config
-        * when there is more than one chip attached to the controller
-        */
-       struct pxa3xx_nand_host *host = info->host[0];
        uint32_t ndcr = nand_readl(info, NDCR);
 
-       if (ndcr & NDCR_PAGE_SZ) {
-               /* Controller's FIFO size */
-               info->chunk_size = 2048;
-               host->read_id_bytes = 4;
-       } else {
-               info->chunk_size = 512;
-               host->read_id_bytes = 2;
-       }
-
        /* Set an initial chunk size */
-       info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
+       info->chunk_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
+       info->reg_ndcr = ndcr &
+               ~(NDCR_INT_MASK | NDCR_ND_ARB_EN | NFCV1_NDCR_ARB_CNTL);
        info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
        info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
        return 0;
 }
 
-#ifdef ARCH_HAS_DMA
 static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
 {
        struct platform_device *pdev = info->pdev;
-       int data_desc_offset = info->buf_size - sizeof(struct pxa_dma_desc);
+       struct dma_slave_config config;
+       dma_cap_mask_t mask;
+       struct pxad_param param;
+       int ret;
 
-       if (use_dma == 0) {
-               info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
-               if (info->data_buff == NULL)
-                       return -ENOMEM;
+       info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
+       if (info->data_buff == NULL)
+               return -ENOMEM;
+       if (use_dma == 0)
                return 0;
-       }
 
-       info->data_buff = dma_alloc_coherent(&pdev->dev, info->buf_size,
-                               &info->data_buff_phys, GFP_KERNEL);
-       if (info->data_buff == NULL) {
-               dev_err(&pdev->dev, "failed to allocate dma buffer\n");
-               return -ENOMEM;
-       }
+       ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
 
-       info->data_desc = (void *)info->data_buff + data_desc_offset;
-       info->data_desc_addr = info->data_buff_phys + data_desc_offset;
+       sg_init_one(&info->sg, info->data_buff, info->buf_size);
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       param.prio = PXAD_PRIO_LOWEST;
+       param.drcmr = info->drcmr_dat;
+       info->dma_chan = dma_request_slave_channel_compat(mask, pxad_filter_fn,
+                                                         &param, &pdev->dev,
+                                                         "data");
+       if (!info->dma_chan) {
+               dev_err(&pdev->dev, "unable to request data dma channel\n");
+               return -ENODEV;
+       }
 
-       info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
-                               pxa3xx_nand_data_dma_irq, info);
-       if (info->data_dma_ch < 0) {
-               dev_err(&pdev->dev, "failed to request data dma\n");
-               dma_free_coherent(&pdev->dev, info->buf_size,
-                               info->data_buff, info->data_buff_phys);
-               return info->data_dma_ch;
+       memset(&config, 0, sizeof(config));
+       config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       config.src_addr = info->mmio_phys + NDDB;
+       config.dst_addr = info->mmio_phys + NDDB;
+       config.src_maxburst = 32;
+       config.dst_maxburst = 32;
+       ret = dmaengine_slave_config(info->dma_chan, &config);
+       if (ret < 0) {
+               dev_err(&info->pdev->dev,
+                       "dma channel configuration failed: %d\n",
+                       ret);
+               return ret;
        }
 
        /*
@@ -1343,43 +1476,30 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
 
 static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
 {
-       struct platform_device *pdev = info->pdev;
        if (info->use_dma) {
-               pxa_free_dma(info->data_dma_ch);
-               dma_free_coherent(&pdev->dev, info->buf_size,
-                                 info->data_buff, info->data_buff_phys);
-       } else {
-               kfree(info->data_buff);
+               dmaengine_terminate_all(info->dma_chan);
+               dma_release_channel(info->dma_chan);
        }
-}
-#else
-static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
-{
-       info->data_buff = kmalloc(info->buf_size, GFP_KERNEL);
-       if (info->data_buff == NULL)
-               return -ENOMEM;
-       return 0;
-}
-
-static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info)
-{
        kfree(info->data_buff);
 }
-#endif
 
-static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_sensing(struct pxa3xx_nand_host *host)
 {
+       struct pxa3xx_nand_info *info = host->info_data;
        struct mtd_info *mtd;
        struct nand_chip *chip;
+       const struct nand_sdr_timings *timings;
        int ret;
 
        mtd = info->host[info->cs]->mtd;
        chip = mtd->priv;
 
        /* use the common timing to make a try */
-       ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
-       if (ret)
-               return ret;
+       timings = onfi_async_timing_mode_to_sdr_timings(0);
+       if (IS_ERR(timings))
+               return PTR_ERR(timings);
+
+       pxa3xx_nand_set_sdr_timing(host, timings);
 
        chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
        ret = chip->waitfunc(mtd, chip);
@@ -1464,73 +1584,30 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
        struct pxa3xx_nand_info *info = host->info_data;
        struct platform_device *pdev = info->pdev;
        struct pxa3xx_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
-       struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
-       const struct pxa3xx_nand_flash *f = NULL;
        struct nand_chip *chip = mtd->priv;
-       uint32_t id = -1;
-       uint64_t chipsize;
-       int i, ret, num;
+       int ret;
        uint16_t ecc_strength, ecc_step;
 
        if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
                goto KEEP_CONFIG;
 
-       ret = pxa3xx_nand_sensing(info);
-       if (ret) {
-               dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
-                        info->cs);
+       /* Set a default chunk size */
+       info->chunk_size = 512;
 
+       ret = pxa3xx_nand_config_flash(info);
+       if (ret)
                return ret;
-       }
-
-       chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-       id = *((uint16_t *)(info->data_buff));
-       if (id != 0)
-               dev_info(&info->pdev->dev, "Detect a flash id %x\n", id);
-       else {
-               dev_warn(&info->pdev->dev,
-                        "Read out ID 0, potential timing set wrong!!\n");
-
-               return -EINVAL;
-       }
-
-       num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1;
-       for (i = 0; i < num; i++) {
-               if (i < pdata->num_flash)
-                       f = pdata->flash + i;
-               else
-                       f = &builtin_flash_types[i - pdata->num_flash + 1];
 
-               /* find the chip in default list */
-               if (f->chip_id == id)
-                       break;
-       }
-
-       if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-               dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
-
-               return -EINVAL;
-       }
-
-       ret = pxa3xx_nand_config_flash(info, f);
+       ret = pxa3xx_nand_sensing(host);
        if (ret) {
-               dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
+               dev_info(&info->pdev->dev, "There is no chip on cs %d!\n",
+                        info->cs);
+
                return ret;
        }
 
-       memset(pxa3xx_flash_ids, 0, sizeof(pxa3xx_flash_ids));
-
-       pxa3xx_flash_ids[0].name = f->name;
-       pxa3xx_flash_ids[0].dev_id = (f->chip_id >> 8) & 0xffff;
-       pxa3xx_flash_ids[0].pagesize = f->page_size;
-       chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
-       pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
-       pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
-       if (f->flash_width == 16)
-               pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
-       pxa3xx_flash_ids[1].name = NULL;
-       def = pxa3xx_flash_ids;
 KEEP_CONFIG:
+       info->reg_ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
        if (info->reg_ndcr & NDCR_DWIDTH_M)
                chip->options |= NAND_BUSWIDTH_16;
 
@@ -1538,9 +1615,18 @@ KEEP_CONFIG:
        if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
                nand_writel(info, NDECCCTRL, 0x0);
 
-       if (nand_scan_ident(mtd, 1, def))
+       if (nand_scan_ident(mtd, 1, NULL))
                return -ENODEV;
 
+       if (!pdata->keep_config) {
+               ret = pxa3xx_nand_init(host);
+               if (ret) {
+                       dev_err(&info->pdev->dev, "Failed to init nand: %d\n",
+                               ret);
+                       return ret;
+               }
+       }
+
        if (pdata->flash_bbt) {
                /*
                 * We'll use a bad block table stored in-flash and don't
@@ -1630,8 +1716,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
        info->pdev = pdev;
        info->variant = pxa3xx_nand_get_variant(pdev);
        for (cs = 0; cs < pdata->num_cs; cs++) {
-               mtd = (struct mtd_info *)((unsigned int)&info[1] +
-                     (sizeof(*mtd) + sizeof(*host)) * cs);
+               mtd = (void *)&info[1] + (sizeof(*mtd) + sizeof(*host)) * cs;
                chip = (struct nand_chip *)(&mtd[1]);
                host = (struct pxa3xx_nand_host *)chip;
                info->host[cs] = host;
@@ -1639,7 +1724,7 @@ static int alloc_nand_resource(struct platform_device *pdev)
                host->cs = cs;
                host->info_data = info;
                mtd->priv = host;
-               mtd->owner = THIS_MODULE;
+               mtd->dev.parent = &pdev->dev;
 
                chip->ecc.read_page     = pxa3xx_nand_read_page_hwecc;
                chip->ecc.write_page    = pxa3xx_nand_write_page_hwecc;
@@ -1666,34 +1751,23 @@ static int alloc_nand_resource(struct platform_device *pdev)
                return ret;
 
        if (use_dma) {
-               /*
-                * This is a dirty hack to make this driver work from
-                * devicetree bindings. It can be removed once we have
-                * a prober DMA controller framework for DT.
-                */
-               if (pdev->dev.of_node &&
-                   of_machine_is_compatible("marvell,pxa3xx")) {
-                       info->drcmr_dat = 97;
-                       info->drcmr_cmd = 99;
-               } else {
-                       r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-                       if (r == NULL) {
-                               dev_err(&pdev->dev,
-                                       "no resource defined for data DMA\n");
-                               ret = -ENXIO;
-                               goto fail_disable_clk;
-                       }
-                       info->drcmr_dat = r->start;
-
-                       r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-                       if (r == NULL) {
-                               dev_err(&pdev->dev,
-                                       "no resource defined for cmd DMA\n");
-                               ret = -ENXIO;
-                               goto fail_disable_clk;
-                       }
-                       info->drcmr_cmd = r->start;
+               r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+               if (r == NULL) {
+                       dev_err(&pdev->dev,
+                               "no resource defined for data DMA\n");
+                       ret = -ENXIO;
+                       goto fail_disable_clk;
+               }
+               info->drcmr_dat = r->start;
+
+               r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+               if (r == NULL) {
+                       dev_err(&pdev->dev,
+                               "no resource defined for cmd DMA\n");
+                       ret = -ENXIO;
+                       goto fail_disable_clk;
                }
+               info->drcmr_cmd = r->start;
        }
 
        irq = platform_get_irq(pdev, 0);
@@ -1758,6 +1832,16 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
                free_irq(irq, info);
        pxa3xx_nand_free_buff(info);
 
+       /*
+        * In the pxa3xx case, the DFI bus is shared between the SMC and NFC.
+        * In order to prevent a lockup of the system bus, the DFI bus
+        * arbitration is granted to SMC upon driver removal. This is done by
+        * setting the x_ARB_CNTL bit, which also prevents the NAND to have
+        * access to the bus anymore.
+        */
+       nand_writel(info, NDCR,
+                   (nand_readl(info, NDCR) & ~NDCR_ND_ARB_EN) |
+                   NFCV1_NDCR_ARB_CNTL);
        clk_disable_unprepare(info->clk);
 
        for (cs = 0; cs < pdata->num_cs; cs++)
@@ -1804,15 +1888,16 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
        struct pxa3xx_nand_platform_data *pdata;
        struct mtd_part_parser_data ppdata = {};
        struct pxa3xx_nand_info *info;
-       int ret, cs, probe_success;
+       int ret, cs, probe_success, dma_available;
 
-#ifndef ARCH_HAS_DMA
-       if (use_dma) {
+       dma_available = IS_ENABLED(CONFIG_ARM) &&
+               (IS_ENABLED(CONFIG_ARCH_PXA) || IS_ENABLED(CONFIG_ARCH_MMP));
+       if (use_dma && !dma_available) {
                use_dma = 0;
                dev_warn(&pdev->dev,
                         "This platform can't do DMA on this device\n");
        }
-#endif
+
        ret = pxa3xx_nand_probe_dt(pdev);
        if (ret)
                return ret;
@@ -1865,35 +1950,22 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 }
 
 #ifdef CONFIG_PM
-static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
+static int pxa3xx_nand_suspend(struct device *dev)
 {
-       struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-       struct pxa3xx_nand_platform_data *pdata;
-       struct mtd_info *mtd;
-       int cs;
+       struct pxa3xx_nand_info *info = dev_get_drvdata(dev);
 
-       pdata = dev_get_platdata(&pdev->dev);
        if (info->state) {
-               dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
+               dev_err(dev, "driver busy, state = %d\n", info->state);
                return -EAGAIN;
        }
 
-       for (cs = 0; cs < pdata->num_cs; cs++) {
-               mtd = info->host[cs]->mtd;
-               mtd_suspend(mtd);
-       }
-
        return 0;
 }
 
-static int pxa3xx_nand_resume(struct platform_device *pdev)
+static int pxa3xx_nand_resume(struct device *dev)
 {
-       struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
-       struct pxa3xx_nand_platform_data *pdata;
-       struct mtd_info *mtd;
-       int cs;
+       struct pxa3xx_nand_info *info = dev_get_drvdata(dev);
 
-       pdata = dev_get_platdata(&pdev->dev);
        /* We don't want to handle interrupt without calling mtd routine */
        disable_int(info, NDCR_INT_MASK);
 
@@ -1911,10 +1983,6 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
         * all status before resume
         */
        nand_writel(info, NDSR, NDSR_MASK);
-       for (cs = 0; cs < pdata->num_cs; cs++) {
-               mtd = info->host[cs]->mtd;
-               mtd_resume(mtd);
-       }
 
        return 0;
 }
@@ -1923,15 +1991,19 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
 #define pxa3xx_nand_resume     NULL
 #endif
 
+static const struct dev_pm_ops pxa3xx_nand_pm_ops = {
+       .suspend        = pxa3xx_nand_suspend,
+       .resume         = pxa3xx_nand_resume,
+};
+
 static struct platform_driver pxa3xx_nand_driver = {
        .driver = {
                .name   = "pxa3xx-nand",
                .of_match_table = pxa3xx_nand_dt_ids,
+               .pm     = &pxa3xx_nand_pm_ops,
        },
        .probe          = pxa3xx_nand_probe,
        .remove         = pxa3xx_nand_remove,
-       .suspend        = pxa3xx_nand_suspend,
-       .resume         = pxa3xx_nand_resume,
 };
 
 module_platform_driver(pxa3xx_nand_driver);