Signed-off-by: Lee Jones <lee.jo...@linaro.org>
---
 drivers/mtd/nand/stm_nand_bch.c | 56 +++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/stm_nand.h    | 20 +++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/drivers/mtd/nand/stm_nand_bch.c b/drivers/mtd/nand/stm_nand_bch.c
index 76a0d02..1a93f8d 100644
--- a/drivers/mtd/nand/stm_nand_bch.c
+++ b/drivers/mtd/nand/stm_nand_bch.c
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/device.h>
@@ -102,6 +103,56 @@ static void nandi_disable_interrupts(struct 
nandi_controller *nandi,
        writel(val, nandi->base + NANDBCH_INT_EN);
 }
 
+static void nandi_init_bch(struct nandi_controller *nandi, int emi_bank)
+{
+       dev_dbg(nandi->dev, "%s\n", __func__);
+
+       /* Initialise BCH Controller */
+       emiss_nandi_select(STM_NANDI_BCH);
+
+       /* Reset and disable boot-mode controller */
+       writel(BOOT_CFG_RESET, nandi->base + NANDBCH_BOOTBANK_CFG);
+       udelay(1);
+       writel(0x00000000, nandi->base + NANDBCH_BOOTBANK_CFG);
+
+       /* Reset AFM controller */
+       writel(CFG_RESET, nandi->base + NANDBCH_CONTROLLER_CFG);
+       udelay(1);
+       writel(0x00000000, nandi->base + NANDBCH_CONTROLLER_CFG);
+
+       /* Set EMI Bank */
+       writel(0x1 << emi_bank, nandi->base + NANDBCH_FLEX_MUXCTRL);
+
+       /* Reset ECC stats */
+       writel(0x7f0, nandi->base + NANDBCH_CONTROLLER_CFG);
+       udelay(1);
+
+       /* Enable AFM */
+       writel(CFG_ENABLE_AFM, nandi->base + NANDBCH_CONTROLLER_CFG);
+
+       /* Configure Read DMA Plugs (values supplied by Validation) */
+       writel(0x00000005, nandi->dma + EMISS_NAND_RD_DMA_PAGE_SIZE);
+       writel(0x00000005, nandi->dma + EMISS_NAND_RD_DMA_MAX_OPCODE_SIZE);
+       writel(0x00000002, nandi->dma + EMISS_NAND_RD_DMA_MIN_OPCODE_SIZE);
+       writel(0x00000001, nandi->dma + EMISS_NAND_RD_DMA_MAX_CHUNK_SIZE);
+       writel(0x00000000, nandi->dma + EMISS_NAND_RD_DMA_MAX_MESSAGE_SIZE);
+
+       /* Configure Write DMA Plugs (values supplied by Validation) */
+       writel(0x00000005, nandi->dma + EMISS_NAND_WR_DMA_PAGE_SIZE);
+       writel(0x00000005, nandi->dma + EMISS_NAND_WR_DMA_MAX_OPCODE_SIZE);
+       writel(0x00000002, nandi->dma + EMISS_NAND_WR_DMA_MIN_OPCODE_SIZE);
+       writel(0x00000001, nandi->dma + EMISS_NAND_WR_DMA_MAX_CHUNK_SIZE);
+       writel(0x00000000, nandi->dma + EMISS_NAND_WR_DMA_MAX_MESSAGE_SIZE);
+
+       nandi_enable_interrupts(nandi, NAND_INT_ENABLE);
+}
+
+static void nandi_init_controller(struct nandi_controller *nandi,
+                                 int emi_bank)
+{
+       nandi_init_bch(nandi, emi_bank);
+}
+
 static int remap_named_resource(struct platform_device *pdev,
                                char *name,
                                void __iomem **io_ptr)
@@ -174,6 +225,7 @@ nandi_init_resources(struct platform_device *pdev)
 static int stm_nand_bch_probe(struct platform_device *pdev)
 {
        struct stm_plat_nand_bch_data *pdata = pdev->dev.platform_data;
+       struct stm_nand_bank_data *bank;
        struct nandi_controller *nandi;
 
        if (!pdata) {
@@ -190,6 +242,10 @@ static int stm_nand_bch_probe(struct platform_device *pdev)
        init_completion(&nandi->seq_completed);
        init_completion(&nandi->rbn_completed);
 
+       bank = pdata->bank;
+       if (bank)
+               nandi_init_controller(nandi, bank->csn);
+
        return 0;
 }
 
diff --git a/include/linux/mtd/stm_nand.h b/include/linux/mtd/stm_nand.h
index da2006c..99a69ca 100644
--- a/include/linux/mtd/stm_nand.h
+++ b/include/linux/mtd/stm_nand.h
@@ -17,6 +17,26 @@
 
 #include <linux/io.h>
 
+/*
+ * Board-level specification relating to a 'bank' of NAND Flash
+ */
+struct stm_nand_bank_data {
+       int                     csn;
+       int                     nr_partitions;
+       struct mtd_partition    *partitions;
+       unsigned int            options;
+       unsigned int            bbt_options;
+
+       struct nand_timing_spec *timing_spec;
+
+       /*
+        * No. of IP clk cycles by which to 'relax' the timing configuration.
+        * Required on some boards to to accommodate board-level limitations.
+        * Used in conjunction with 'nand_timing_spec' and ONFI configuration.
+        */
+       int                     timing_relax;
+};
+
 struct stm_plat_nand_bch_data {
        struct stm_nand_bank_data *bank;
        enum stm_nand_bch_ecc_config bch_ecc_cfg;
-- 
1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to