mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 1/5] mtd: nand: define struct nand_timings
@ 2016-08-18 14:17 Sascha Hauer
  2016-08-18 14:17 ` [PATCH 2/5] mtd: nand: add ONFI timing mode to nand_timings converter Sascha Hauer
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Sascha Hauer @ 2016-08-18 14:17 UTC (permalink / raw)
  To: Barebox List

Ported from Linux commit bb5fd0b6da:

|  Define a struct containing the standard NAND timings as described in NAND
|  datasheets.
|
|  Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
|  Signed-off-by: Brian Norris <computersforpeace@gmail.com>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 include/linux/mtd/nand.h | 49 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 76a6425..5c237f0 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -742,4 +742,53 @@ static inline bool nand_is_slc(struct nand_chip *chip)
 	return chip->bits_per_cell == 1;
 }
 
+/**
+ * struct nand_sdr_timings - SDR NAND chip timings
+ *
+ * This struct defines the timing requirements of a SDR NAND chip.
+ * These informations can be found in every NAND datasheets and the timings
+ * meaning are described in the ONFI specifications:
+ * www.onfi.org/~/media/ONFI/specs/onfi_3_1_spec.pdf (chapter 4.15 Timing
+ * Parameters)
+ *
+ * All these timings are expressed in picoseconds.
+ */
+
+struct nand_sdr_timings {
+	u32 tALH_min;
+	u32 tADL_min;
+	u32 tALS_min;
+	u32 tAR_min;
+	u32 tCEA_max;
+	u32 tCEH_min;
+	u32 tCH_min;
+	u32 tCHZ_max;
+	u32 tCLH_min;
+	u32 tCLR_min;
+	u32 tCLS_min;
+	u32 tCOH_min;
+	u32 tCS_min;
+	u32 tDH_min;
+	u32 tDS_min;
+	u32 tFEAT_max;
+	u32 tIR_min;
+	u32 tITC_max;
+	u32 tRC_min;
+	u32 tREA_max;
+	u32 tREH_min;
+	u32 tRHOH_min;
+	u32 tRHW_min;
+	u32 tRHZ_max;
+	u32 tRLOH_min;
+	u32 tRP_min;
+	u32 tRR_min;
+	u64 tRST_max;
+	u32 tWB_max;
+	u32 tWC_min;
+	u32 tWH_min;
+	u32 tWHR_min;
+	u32 tWP_min;
+	u32 tWW_min;
+};
+
 #endif /* __LINUX_MTD_NAND_H */
-- 
2.8.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 2/5] mtd: nand: add ONFI timing mode to nand_timings converter
  2016-08-18 14:17 [PATCH 1/5] mtd: nand: define struct nand_timings Sascha Hauer
@ 2016-08-18 14:17 ` Sascha Hauer
  2016-08-18 14:17 ` [PATCH 3/5] mtd: nand-imx: split preset_v1_v2 into two functions Sascha Hauer
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2016-08-18 14:17 UTC (permalink / raw)
  To: Barebox List

Ported from Linux commit 974647e:
| Add a converter to retrieve NAND timings from an ONFI NAND timing mode.
| At the moment, only SDR NAND timings are supported.
|
| Signed-off-by: Boris BREZILLON <boris.brezillon@free-electrons.com>
| Signed-off-by: Brian Norris <computersforpeace@gmail.com>

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/Makefile       |   2 +-
 drivers/mtd/nand/nand_timings.c | 251 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/nand.h        |   3 +
 3 files changed, 255 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mtd/nand/nand_timings.c

diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 8809238..6088512 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -3,7 +3,7 @@
 obj-$(CONFIG_NAND)			+= nand_ecc.o
 obj-$(CONFIG_NAND_ECC_BCH)		+= nand_bch.o
 obj-$(CONFIG_MTD_NAND_IDS)		+= nand_ids.o
-obj-$(CONFIG_NAND)			+= nand_base.o nand-bb.o
+obj-$(CONFIG_NAND)			+= nand_base.o nand-bb.o nand_timings.o
 obj-$(CONFIG_NAND_BBT)			+= nand_bbt.o
 
 obj-$(CONFIG_MTD_NAND_NOMADIK)		+= nomadik_nand.o
diff --git a/drivers/mtd/nand/nand_timings.c b/drivers/mtd/nand/nand_timings.c
new file mode 100644
index 0000000..7a93951
--- /dev/null
+++ b/drivers/mtd/nand/nand_timings.c
@@ -0,0 +1,251 @@
+/*
+ *  Copyright (C) 2014 Free Electrons
+ *
+ *  Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/mtd/nand.h>
+
+static const struct nand_sdr_timings onfi_sdr_timings[] = {
+	/* Mode 0 */
+	{
+		.tADL_min = 200000,
+		.tALH_min = 20000,
+		.tALS_min = 50000,
+		.tAR_min = 25000,
+		.tCEA_max = 100000,
+		.tCEH_min = 20000,
+		.tCH_min = 20000,
+		.tCHZ_max = 100000,
+		.tCLH_min = 20000,
+		.tCLR_min = 20000,
+		.tCLS_min = 50000,
+		.tCOH_min = 0,
+		.tCS_min = 70000,
+		.tDH_min = 20000,
+		.tDS_min = 40000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 10000,
+		.tITC_max = 1000000,
+		.tRC_min = 100000,
+		.tREA_max = 40000,
+		.tREH_min = 30000,
+		.tRHOH_min = 0,
+		.tRHW_min = 200000,
+		.tRHZ_max = 200000,
+		.tRLOH_min = 0,
+		.tRP_min = 50000,
+		.tRST_max = 250000000000,
+		.tWB_max = 200000,
+		.tRR_min = 40000,
+		.tWC_min = 100000,
+		.tWH_min = 30000,
+		.tWHR_min = 120000,
+		.tWP_min = 50000,
+		.tWW_min = 100000,
+	},
+	/* Mode 1 */
+	{
+		.tADL_min = 100000,
+		.tALH_min = 10000,
+		.tALS_min = 25000,
+		.tAR_min = 10000,
+		.tCEA_max = 45000,
+		.tCEH_min = 20000,
+		.tCH_min = 10000,
+		.tCHZ_max = 50000,
+		.tCLH_min = 10000,
+		.tCLR_min = 10000,
+		.tCLS_min = 25000,
+		.tCOH_min = 15000,
+		.tCS_min = 35000,
+		.tDH_min = 10000,
+		.tDS_min = 20000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 50000,
+		.tREA_max = 30000,
+		.tREH_min = 15000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 0,
+		.tRP_min = 25000,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tWC_min = 45000,
+		.tWH_min = 15000,
+		.tWHR_min = 80000,
+		.tWP_min = 25000,
+		.tWW_min = 100000,
+	},
+	/* Mode 2 */
+	{
+		.tADL_min = 100000,
+		.tALH_min = 10000,
+		.tALS_min = 15000,
+		.tAR_min = 10000,
+		.tCEA_max = 30000,
+		.tCEH_min = 20000,
+		.tCH_min = 10000,
+		.tCHZ_max = 50000,
+		.tCLH_min = 10000,
+		.tCLR_min = 10000,
+		.tCLS_min = 15000,
+		.tCOH_min = 15000,
+		.tCS_min = 25000,
+		.tDH_min = 5000,
+		.tDS_min = 15000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 35000,
+		.tREA_max = 25000,
+		.tREH_min = 15000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 0,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tRP_min = 17000,
+		.tWC_min = 35000,
+		.tWH_min = 15000,
+		.tWHR_min = 80000,
+		.tWP_min = 17000,
+		.tWW_min = 100000,
+	},
+	/* Mode 3 */
+	{
+		.tADL_min = 100000,
+		.tALH_min = 5000,
+		.tALS_min = 10000,
+		.tAR_min = 10000,
+		.tCEA_max = 25000,
+		.tCEH_min = 20000,
+		.tCH_min = 5000,
+		.tCHZ_max = 50000,
+		.tCLH_min = 5000,
+		.tCLR_min = 10000,
+		.tCLS_min = 10000,
+		.tCOH_min = 15000,
+		.tCS_min = 25000,
+		.tDH_min = 5000,
+		.tDS_min = 10000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 30000,
+		.tREA_max = 20000,
+		.tREH_min = 10000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 0,
+		.tRP_min = 15000,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tWC_min = 30000,
+		.tWH_min = 10000,
+		.tWHR_min = 80000,
+		.tWP_min = 15000,
+		.tWW_min = 100000,
+	},
+	/* Mode 4 */
+	{
+		.tADL_min = 70000,
+		.tALH_min = 5000,
+		.tALS_min = 10000,
+		.tAR_min = 10000,
+		.tCEA_max = 25000,
+		.tCEH_min = 20000,
+		.tCH_min = 5000,
+		.tCHZ_max = 30000,
+		.tCLH_min = 5000,
+		.tCLR_min = 10000,
+		.tCLS_min = 10000,
+		.tCOH_min = 15000,
+		.tCS_min = 20000,
+		.tDH_min = 5000,
+		.tDS_min = 10000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 25000,
+		.tREA_max = 20000,
+		.tREH_min = 10000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 5000,
+		.tRP_min = 12000,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tWC_min = 25000,
+		.tWH_min = 10000,
+		.tWHR_min = 80000,
+		.tWP_min = 12000,
+		.tWW_min = 100000,
+	},
+	/* Mode 5 */
+	{
+		.tADL_min = 70000,
+		.tALH_min = 5000,
+		.tALS_min = 10000,
+		.tAR_min = 10000,
+		.tCEA_max = 25000,
+		.tCEH_min = 20000,
+		.tCH_min = 5000,
+		.tCHZ_max = 30000,
+		.tCLH_min = 5000,
+		.tCLR_min = 10000,
+		.tCLS_min = 10000,
+		.tCOH_min = 15000,
+		.tCS_min = 15000,
+		.tDH_min = 5000,
+		.tDS_min = 7000,
+		.tFEAT_max = 1000000,
+		.tIR_min = 0,
+		.tITC_max = 1000000,
+		.tRC_min = 20000,
+		.tREA_max = 16000,
+		.tREH_min = 7000,
+		.tRHOH_min = 15000,
+		.tRHW_min = 100000,
+		.tRHZ_max = 100000,
+		.tRLOH_min = 5000,
+		.tRP_min = 10000,
+		.tRR_min = 20000,
+		.tRST_max = 500000000,
+		.tWB_max = 100000,
+		.tWC_min = 20000,
+		.tWH_min = 7000,
+		.tWHR_min = 80000,
+		.tWP_min = 10000,
+		.tWW_min = 100000,
+	},
+};
+
+/**
+ * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
+ * timings according to the given ONFI timing mode
+ * @mode: ONFI timing mode
+ */
+const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
+{
+	if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
+		return ERR_PTR(-EINVAL);
+
+	return &onfi_sdr_timings[mode];
+}
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 5c237f0..66c936e 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -791,4 +791,7 @@ struct nand_sdr_timings {
 	u32 tWW_min;
 };
 
+/* get timing characteristics from ONFI timing mode. */
+const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode);
+
 #endif /* __LINUX_MTD_NAND_H */
-- 
2.8.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 3/5] mtd: nand-imx: split preset_v1_v2 into two functions
  2016-08-18 14:17 [PATCH 1/5] mtd: nand: define struct nand_timings Sascha Hauer
  2016-08-18 14:17 ` [PATCH 2/5] mtd: nand: add ONFI timing mode to nand_timings converter Sascha Hauer
@ 2016-08-18 14:17 ` Sascha Hauer
  2016-08-18 14:17 ` [PATCH 4/5] ARM: i.MX25: Provide a clock for the nand controller Sascha Hauer
  2016-08-18 14:17 ` [PATCH 5/5] mtd: nand-imx: Optimize timing for i.MX25 Sascha Hauer
  3 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2016-08-18 14:17 UTC (permalink / raw)
  To: Barebox List

preset_v1_v2() still needs to distinguish between v1 and v2 and
the shared code is not very big. Since we need another v2 only
addtion in the next patch split the function into a v1 and a v2
specific function.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c | 42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index f54fe21..47d9d9a 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -784,16 +784,37 @@ static int get_eccsize(struct mtd_info *mtd)
 		return 8;
 }
 
-static void preset_v1_v2(struct mtd_info *mtd)
+static void preset_v1(struct mtd_info *mtd)
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct imx_nand_host *host = nand_chip->priv;
 	uint16_t config1 = 0;
 
-	if (nfc_is_v21())
-		config1 |= NFC_V2_CONFIG1_FP_INT;
+	host->eccsize = 1;
+
+	writew(config1, host->regs + NFC_V1_V2_CONFIG1);
+	/* preset operation */
+
+	/* Unlock the internal RAM Buffer */
+	writew(0x2, host->regs + NFC_V1_V2_CONFIG);
+
+	/* Blocks to be unlocked */
+	writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
+	writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
 
-	if (nfc_is_v21() && mtd->writesize) {
+	/* Unlock Block Command for given address range */
+	writew(0x4, host->regs + NFC_V1_V2_WRPROT);
+}
+
+static void preset_v2(struct mtd_info *mtd)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct imx_nand_host *host = nand_chip->priv;
+	uint16_t config1 = 0;
+
+	config1 |= NFC_V2_CONFIG1_FP_INT;
+
+	if (mtd->writesize) {
 		uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
 
 		host->eccsize = get_eccsize(mtd);
@@ -812,14 +833,8 @@ static void preset_v1_v2(struct mtd_info *mtd)
 	writew(0x2, host->regs + NFC_V1_V2_CONFIG);
 
 	/* Blocks to be unlocked */
-	if (nfc_is_v21()) {
-		writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
-		writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
-	} else if (nfc_is_v1()) {
-		writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
-		writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
-	} else
-		BUG();
+	writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
+	writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
 
 	/* Unlock Block Command for given address range */
 	writew(0x4, host->regs + NFC_V1_V2_WRPROT);
@@ -1167,7 +1182,6 @@ static int __init imxnd_probe(struct device_d *dev)
 	host->data_buf = (uint8_t *)(host + 1);
 
 	if (nfc_is_v1() || nfc_is_v21()) {
-		host->preset = preset_v1_v2;
 		host->send_cmd = send_cmd_v1_v2;
 		host->send_addr = send_addr_v1_v2;
 		host->send_page = send_page_v1_v2;
@@ -1189,6 +1203,7 @@ static int __init imxnd_probe(struct device_d *dev)
 		oob_smallpage = &nandv2_hw_eccoob_smallpage;
 		oob_largepage = &nandv2_hw_eccoob_largepage;
 		oob_4kpage = &nandv2_hw_eccoob_4k; /* FIXME : to check */
+		host->preset = preset_v2;
 	} else if (nfc_is_v1()) {
 		iores = dev_request_mem_resource(dev, 0);
 		if (IS_ERR(iores))
@@ -1201,6 +1216,7 @@ static int __init imxnd_probe(struct device_d *dev)
 		oob_smallpage = &nandv1_hw_eccoob_smallpage;
 		oob_largepage = &nandv1_hw_eccoob_largepage;
 		oob_4kpage = &nandv1_hw_eccoob_smallpage; /* FIXME : to check  */
+		host->preset = preset_v1;
 	} else if (nfc_is_v3_2()) {
 		iores = dev_request_mem_resource(dev, 0);
 		if (IS_ERR(iores))
-- 
2.8.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 4/5] ARM: i.MX25: Provide a clock for the nand controller
  2016-08-18 14:17 [PATCH 1/5] mtd: nand: define struct nand_timings Sascha Hauer
  2016-08-18 14:17 ` [PATCH 2/5] mtd: nand: add ONFI timing mode to nand_timings converter Sascha Hauer
  2016-08-18 14:17 ` [PATCH 3/5] mtd: nand-imx: split preset_v1_v2 into two functions Sascha Hauer
@ 2016-08-18 14:17 ` Sascha Hauer
  2016-08-18 14:17 ` [PATCH 5/5] mtd: nand-imx: Optimize timing for i.MX25 Sascha Hauer
  3 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2016-08-18 14:17 UTC (permalink / raw)
  To: Barebox List

The clock is needed to configure optimized timings, so provide
one.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 arch/arm/mach-imx/clk-imx25.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
index fccea7f..864d06e 100644
--- a/arch/arm/mach-imx/clk-imx25.c
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -171,6 +171,7 @@ static int imx25_ccm_probe(struct device_d *dev)
 	clkdev_add_physbase(clks[ipg], MX25_CSPI3_BASE_ADDR, NULL);
 	clkdev_add_physbase(clks[per3], MX25_ESDHC1_BASE_ADDR, NULL);
 	clkdev_add_physbase(clks[per4], MX25_ESDHC2_BASE_ADDR, NULL);
+	clkdev_add_physbase(clks[per8], MX25_NFC_BASE_ADDR, NULL);
 	clkdev_add_physbase(clks[lcdc_ipg_per], MX25_LCDC_BASE_ADDR, "per");
 	clkdev_add_physbase(clks[lcdc_ipg], MX25_LCDC_BASE_ADDR, "ipg");
 	clkdev_add_physbase(clks[lcdc_ahb], MX25_LCDC_BASE_ADDR, "ahb");
-- 
2.8.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 5/5] mtd: nand-imx: Optimize timing for i.MX25
  2016-08-18 14:17 [PATCH 1/5] mtd: nand: define struct nand_timings Sascha Hauer
                   ` (2 preceding siblings ...)
  2016-08-18 14:17 ` [PATCH 4/5] ARM: i.MX25: Provide a clock for the nand controller Sascha Hauer
@ 2016-08-18 14:17 ` Sascha Hauer
  3 siblings, 0 replies; 5+ messages in thread
From: Sascha Hauer @ 2016-08-18 14:17 UTC (permalink / raw)
  To: Barebox List

So far we relied on the clock rate as configured by reset default or
board code. Also we did not touch the symmetric mode bit. Use
the ONFI provided timing parameters to configure the clock rate for
the Nand controller. Also symmetric mode (EDO mode) when needed.
This is done for v2 controllers (i.MX25/35) only, other controllers
need other setup code.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/mtd/nand/nand_imx.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index 47d9d9a..6f31c28 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -24,6 +24,7 @@
 #include <init.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
+#include <linux/clk.h>
 #include <mach/generic.h>
 #include <mach/imx-nand.h>
 #include <io.h>
@@ -811,6 +812,32 @@ static void preset_v2(struct mtd_info *mtd)
 	struct nand_chip *nand_chip = mtd->priv;
 	struct imx_nand_host *host = nand_chip->priv;
 	uint16_t config1 = 0;
+	int mode;
+
+	mode = onfi_get_async_timing_mode(nand_chip);
+	if (mode != ONFI_TIMING_MODE_UNKNOWN && !IS_ERR(host->clk)) {
+		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)) {
+			unsigned long rate;
+			int tRC_min_ns = timings->tRC_min / 1000;
+
+			rate = 1000000000 / tRC_min_ns;
+			if (tRC_min_ns < 30)
+				/* If tRC is smaller than 30ns we have to use EDO timing */
+				config1 |= NFC_V1_V2_CONFIG1_ONE_CYCLE;
+			else
+				/* Otherwise we have two clock cycles per access */
+				rate *= 2;
+
+			clk_set_rate(host->clk, rate);
+		}
+	}
 
 	config1 |= NFC_V2_CONFIG1_FP_INT;
 
@@ -1181,6 +1208,9 @@ static int __init imxnd_probe(struct device_d *dev)
 
 	host->data_buf = (uint8_t *)(host + 1);
 
+	/* No error check, not all SoCs provide a clk yet */
+	host->clk = clk_get(dev, NULL);
+
 	if (nfc_is_v1() || nfc_is_v21()) {
 		host->send_cmd = send_cmd_v1_v2;
 		host->send_addr = send_addr_v1_v2;
-- 
2.8.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-08-18 14:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-18 14:17 [PATCH 1/5] mtd: nand: define struct nand_timings Sascha Hauer
2016-08-18 14:17 ` [PATCH 2/5] mtd: nand: add ONFI timing mode to nand_timings converter Sascha Hauer
2016-08-18 14:17 ` [PATCH 3/5] mtd: nand-imx: split preset_v1_v2 into two functions Sascha Hauer
2016-08-18 14:17 ` [PATCH 4/5] ARM: i.MX25: Provide a clock for the nand controller Sascha Hauer
2016-08-18 14:17 ` [PATCH 5/5] mtd: nand-imx: Optimize timing for i.MX25 Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox