linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/13] mtd/nand/fsmc related modifications
@ 2012-03-14  6:17 Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data Vipin Kumar
                   ` (13 more replies)
  0 siblings, 14 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

Hello Artem,

These are the patches 8-20 of the original patchset of which 1-7 have already
been applied by you. I have rebased these patches over
git://git.infradead.org/users/dedekind/l2-mtd.git to help you apply these easily

Modifications in v2
- Add support for partition information to be passed from platform data
- Default partition information removed from driver
- Remove sparse errors and warnings

Modifications in v1
- DMA support
- Word read/write support to improve performance
- Move platform related things(ALE/CLE) from driver to platfrom files
- Add default partition support for more devices with erase sizes (256KB, 512KB,
		1024KB, 2048KB)
- Bugfixes
	- Read only 512 + 13 bytes for 8bit NAND devices
	- Flip the bit only if the error index is < 4096
	- Fixed data abort inside change_bit()

Regards
Vipin

Armando Visconti (1):
  nand/fsmc: Remove default partition information from driver

Shiraz Hashim (1):
  mtd/fsmc_nand: add pm callbacks to support hibernation

Vipin Kumar (11):
  nand/fsmc: Pass partition information through platform data
  nand/fsmc: Correct the multiline comment format
  nand/fsmc: Read only 512 + 13 bytes for 8bit NAND devices
  nand/fsmc: Flip the bit only if the error index is < 4096
  nand/fsmc: Initialize the badblockbits to 7
  nand/fsmc: Modify fsmc driver to accept nand timing parameters via
    platform
  nand/fsmc: Use devm routines
  nand/fsmc: Use dev_err to report error scenario
  nand/fsmc: Access the NAND device word by word whenever possible
  nand/fsmc: Add DMA support
  nand/fsmc: Remove sparse warnings and errors

 drivers/mtd/nand/fsmc_nand.c |  572 ++++++++++++++++++++++++++----------------
 include/linux/mtd/fsmc.h     |  151 +++++++-----
 2 files changed, 443 insertions(+), 280 deletions(-)

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

* [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14 11:06   ` Linus Walleij
                     ` (2 more replies)
  2012-03-14  6:17 ` [PATCH v2 02/13] nand/fsmc: Remove default partition information from driver Vipin Kumar
                   ` (12 subsequent siblings)
  13 siblings, 3 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

This patch reimplements the passing of partition information through platform
data. This was unintentionally deleted in commit
0d04eda1430e9a796214bee644b7e05d99cfe613
"mtd: fsmc_nand.c: use mtd_device_parse_register"

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |   15 ++++++++-------
 1 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 588e373..2d7683b 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -333,6 +333,8 @@ static struct mtd_partition partition_info_128KB_blk[] = {
  * @pid:		Part ID on the AMBA PrimeCell format
  * @mtd:		MTD info for a NAND flash.
  * @nand:		Chip related info for a NAND flash.
+ * @partitions:		Partition info for a NAND Flash.
+ * @nr_partitions:	Total number of partition of a NAND flash.
  *
  * @ecc_place:		ECC placing locations in oobfree type format.
  * @bank:		Bank number for probed device.
@@ -347,6 +349,8 @@ struct fsmc_nand_data {
 	u32			pid;
 	struct mtd_info		mtd;
 	struct nand_chip	nand;
+	struct mtd_partition	*partitions;
+	unsigned int		nr_partitions;
 
 	struct fsmc_eccplace	*ecc_place;
 	unsigned int		bank;
@@ -833,6 +837,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 
 	host->bank = pdata->bank;
 	host->select_chip = pdata->select_bank;
+	host->partitions = pdata->partitions;
+	host->nr_partitions = pdata->nr_partitions;
 	regs = host->regs_va;
 
 	/* Link all private pointers */
@@ -942,13 +948,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	 * Check for partition info passed
 	 */
 	host->mtd.name = "nand";
-	ret = mtd_device_parse_register(&host->mtd, NULL, NULL,
-					host->mtd.size <= 0x04000000 ?
-					partition_info_16KB_blk :
-					partition_info_128KB_blk,
-					host->mtd.size <= 0x04000000 ?
-					ARRAY_SIZE(partition_info_16KB_blk) :
-					ARRAY_SIZE(partition_info_128KB_blk));
+	ret = mtd_device_parse_register(&host->mtd, NULL, 0, host->partitions,
+			host->nr_partitions);
 	if (ret)
 		goto err_probe;
 
-- 
1.7.0.4

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

* [PATCH v2 02/13] nand/fsmc: Remove default partition information from driver
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 03/13] nand/fsmc: Correct the multiline comment format Vipin Kumar
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1
  Cc: sr, Armando Visconti, linus.walleij, spear-devel, Vipin Kumar

From: Armando Visconti <armando.visconti@st.com>

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |   58 ------------------------------------------
 1 files changed, 0 insertions(+), 58 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 2d7683b..ac45b41 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -269,64 +269,6 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = {
 	}
 };
 
-/*
- * Default partition tables to be used if the partition information not
- * provided through platform data.
- *
- * Default partition layout for small page(= 512 bytes) devices
- * Size for "Root file system" is updated in driver based on actual device size
- */
-static struct mtd_partition partition_info_16KB_blk[] = {
-	{
-		.name = "X-loader",
-		.offset = 0,
-		.size = 4*0x4000,
-	},
-	{
-		.name = "U-Boot",
-		.offset = 0x10000,
-		.size = 20*0x4000,
-	},
-	{
-		.name = "Kernel",
-		.offset = 0x60000,
-		.size = 256*0x4000,
-	},
-	{
-		.name = "Root File System",
-		.offset = 0x460000,
-		.size = MTDPART_SIZ_FULL,
-	},
-};
-
-/*
- * Default partition layout for large page(> 512 bytes) devices
- * Size for "Root file system" is updated in driver based on actual device size
- */
-static struct mtd_partition partition_info_128KB_blk[] = {
-	{
-		.name = "X-loader",
-		.offset = 0,
-		.size = 4*0x20000,
-	},
-	{
-		.name = "U-Boot",
-		.offset = 0x80000,
-		.size = 12*0x20000,
-	},
-	{
-		.name = "Kernel",
-		.offset = 0x200000,
-		.size = 48*0x20000,
-	},
-	{
-		.name = "Root File System",
-		.offset = 0x800000,
-		.size = MTDPART_SIZ_FULL,
-	},
-};
-
-
 /**
  * struct fsmc_nand_data - structure for FSMC NAND device state
  *
-- 
1.7.0.4

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

* [PATCH v2 03/13] nand/fsmc: Correct the multiline comment format
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 02/13] nand/fsmc: Remove default partition information from driver Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 04/13] nand/fsmc: Read only 512 + 13 bytes for 8bit NAND devices Vipin Kumar
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index ac45b41..fb2cc8b 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -545,10 +545,10 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 			group++;
 
 			/*
-			* length is intentionally kept a higher multiple of 2
-			* to read at least 13 bytes even in case of 16 bit NAND
-			* devices
-			*/
+			 * length is intentionally kept a higher multiple of 2
+			 * to read at least 13 bytes even in case of 16 bit NAND
+			 * devices
+			 */
 			len = roundup(len, 2);
 			chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page);
 			chip->read_buf(mtd, oob + j, len);
-- 
1.7.0.4

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

* [PATCH v2 04/13] nand/fsmc: Read only 512 + 13 bytes for 8bit NAND devices
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (2 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 03/13] nand/fsmc: Correct the multiline comment format Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 05/13] nand/fsmc: Flip the bit only if the error index is < 4096 Vipin Kumar
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

The ECC logic of FSMC works on 512 bytes data + 13 bytes ECC to generate error
indices of upto 8 incorrect bits. The FSMC driver reads 14 instead of 13 oob
bytes to accommodate for 16 bit device as well.

Unfortunately, the internal ecc state machine gets corrupted for 8 bit devices
reading 512 + 14 bytes of data resulting in error indices not getting reported.

Fix this by reading 14 bytes only for 16 bit devices

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index fb2cc8b..3f33103 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -549,7 +549,9 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 			 * to read at least 13 bytes even in case of 16 bit NAND
 			 * devices
 			 */
-			len = roundup(len, 2);
+			if (chip->options & NAND_BUSWIDTH_16)
+				len = roundup(len, 2);
+
 			chip->cmdfunc(mtd, NAND_CMD_READOOB, off, page);
 			chip->read_buf(mtd, oob + j, len);
 			j += len;
-- 
1.7.0.4

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

* [PATCH v2 05/13] nand/fsmc: Flip the bit only if the error index is < 4096
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (3 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 04/13] nand/fsmc: Read only 512 + 13 bytes for 8bit NAND devices Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 06/13] nand/fsmc: Initialize the badblockbits to 7 Vipin Kumar
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

ECC can correct upto 8 bits in 512 bytes data + 13 bytes ecc. This means that
the algorithm can correct a max of 8 bits in 4200 bits ie the error indices can
be from 0 to 4199. Of these 0 to 4095 are for data and 4096 to 4199 for ecc.

The driver flips the bit only if the index is <= 4096. This is a bug since the
data bits are only from 0 to 4095.

This patch modifies the check as < 4096

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 3f33103..745db62 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -654,7 +654,7 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
 		change_bit(0, (unsigned long *)&err_idx[i]);
 		change_bit(1, (unsigned long *)&err_idx[i]);
 
-		if (err_idx[i] <= chip->ecc.size * 8) {
+		if (err_idx[i] < chip->ecc.size * 8) {
 			change_bit(err_idx[i], (unsigned long *)dat);
 			i++;
 		}
-- 
1.7.0.4

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

* [PATCH v2 06/13] nand/fsmc: Initialize the badblockbits to 7
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (4 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 05/13] nand/fsmc: Flip the bit only if the error index is < 4096 Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 07/13] mtd/fsmc_nand: add pm callbacks to support hibernation Vipin Kumar
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

Ideally, the block should have 0xff written on the bad block position. Any value
other than 0xff implies a bad block. In practical situations, there can be
bit flips in the oob area as well which means that a block with 0x7f being read
at bad block position may imply a bad block but it is infact only a bit flip in
the bad block byte.

To resolve this problem, the block is marked as good if number of high bits is
greater than or equal to badblockbits (initialized to 7)

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 745db62..bfc924f 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -802,6 +802,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	nand->ecc.size = 512;
 	nand->options = pdata->options;
 	nand->select_chip = fsmc_select_chip;
+	nand->badblockbits = 7;
 
 	if (pdata->width == FSMC_NAND_BW16)
 		nand->options |= NAND_BUSWIDTH_16;
-- 
1.7.0.4

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

* [PATCH v2 07/13] mtd/fsmc_nand: add pm callbacks to support hibernation
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (5 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 06/13] nand/fsmc: Initialize the badblockbits to 7 Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 08/13] nand/fsmc: Modify fsmc driver to accept nand timing parameters via platform Vipin Kumar
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Shiraz Hashim, linus.walleij, spear-devel

From: Shiraz Hashim <shiraz.hashim@st.com>

Signed-off-by: Shiraz Hashim <shiraz.hashim@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index bfc924f..5433856 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -382,7 +382,7 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
  * This routine initializes timing parameters related to NAND memory access in
  * FSMC registers
  */
-static void __init fsmc_nand_setup(struct fsmc_regs *regs, uint32_t bank,
+static void fsmc_nand_setup(struct fsmc_regs *regs, uint32_t bank,
 				   uint32_t busw)
 {
 	uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON;
@@ -976,15 +976,15 @@ static int fsmc_nand_suspend(struct device *dev)
 static int fsmc_nand_resume(struct device *dev)
 {
 	struct fsmc_nand_data *host = dev_get_drvdata(dev);
-	if (host)
+	if (host) {
 		clk_enable(host->clk);
+		fsmc_nand_setup(host->regs_va, host->bank,
+				host->nand.options & NAND_BUSWIDTH_16);
+	}
 	return 0;
 }
 
-static const struct dev_pm_ops fsmc_nand_pm_ops = {
-	.suspend = fsmc_nand_suspend,
-	.resume = fsmc_nand_resume,
-};
+static SIMPLE_DEV_PM_OPS(fsmc_nand_pm_ops, fsmc_nand_suspend, fsmc_nand_resume);
 #endif
 
 static struct platform_driver fsmc_nand_driver = {
-- 
1.7.0.4

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

* [PATCH v2 08/13] nand/fsmc: Modify fsmc driver to accept nand timing parameters via platform
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (6 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 07/13] mtd/fsmc_nand: add pm callbacks to support hibernation Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 09/13] nand/fsmc: Use devm routines Vipin Kumar
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

FSMC controllers provide registers to program the required timing values for
attached NAND device. The timing values used until now are relaxed and should
work for all devices.

Although, for read/write performance improvements, the fsmc nand driver should
accept nand timings as a platform data and program the timing parameters into
fsmc registers accordingly.

This patch implements this modification. Additionally, it programs the default
timing parameters if these are not passed via platform data.

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |   41 +++++++++++++++++++++++++++++++++--------
 include/linux/mtd/fsmc.h     |   34 ++++++++++++++++++++++++++++------
 2 files changed, 61 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 5433856..71fd9f6 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -303,6 +303,8 @@ struct fsmc_nand_data {
 	struct resource		*resaddr;
 	struct resource		*resdata;
 
+	struct fsmc_nand_timings *dev_timings;
+
 	void __iomem		*data_va;
 	void __iomem		*cmd_va;
 	void __iomem		*addr_va;
@@ -383,21 +385,41 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
  * FSMC registers
  */
 static void fsmc_nand_setup(struct fsmc_regs *regs, uint32_t bank,
-				   uint32_t busw)
+			   uint32_t busw, struct fsmc_nand_timings *timings)
 {
 	uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON;
+	uint32_t tclr, tar, thiz, thold, twait, tset;
+	struct fsmc_nand_timings *tims;
+	struct fsmc_nand_timings default_timings = {
+		.tclr	= FSMC_TCLR_1,
+		.tar	= FSMC_TAR_1,
+		.thiz	= FSMC_THIZ_1,
+		.thold	= FSMC_THOLD_4,
+		.twait	= FSMC_TWAIT_6,
+		.tset	= FSMC_TSET_0,
+	};
+
+	if (timings)
+		tims = timings;
+	else
+		tims = &default_timings;
+
+	tclr = (tims->tclr & FSMC_TCLR_MASK) << FSMC_TCLR_SHIFT;
+	tar = (tims->tar & FSMC_TAR_MASK) << FSMC_TAR_SHIFT;
+	thiz = (tims->thiz & FSMC_THIZ_MASK) << FSMC_THIZ_SHIFT;
+	thold = (tims->thold & FSMC_THOLD_MASK) << FSMC_THOLD_SHIFT;
+	twait = (tims->twait & FSMC_TWAIT_MASK) << FSMC_TWAIT_SHIFT;
+	tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
 
 	if (busw)
 		writel(value | FSMC_DEVWID_16, &regs->bank_regs[bank].pc);
 	else
 		writel(value | FSMC_DEVWID_8, &regs->bank_regs[bank].pc);
 
-	writel(readl(&regs->bank_regs[bank].pc) | FSMC_TCLR_1 | FSMC_TAR_1,
+	writel(readl(&regs->bank_regs[bank].pc) | tclr | tar,
 	       &regs->bank_regs[bank].pc);
-	writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
-	       &regs->bank_regs[bank].comm);
-	writel(FSMC_THIZ_1 | FSMC_THOLD_4 | FSMC_TWAIT_6 | FSMC_TSET_0,
-	       &regs->bank_regs[bank].attrib);
+	writel(thiz | thold | twait | tset, &regs->bank_regs[bank].comm);
+	writel(thiz | thold | twait | tset, &regs->bank_regs[bank].attrib);
 }
 
 /*
@@ -783,6 +805,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	host->select_chip = pdata->select_bank;
 	host->partitions = pdata->partitions;
 	host->nr_partitions = pdata->nr_partitions;
+	host->dev_timings = pdata->nand_timings;
 	regs = host->regs_va;
 
 	/* Link all private pointers */
@@ -807,7 +830,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	if (pdata->width == FSMC_NAND_BW16)
 		nand->options |= NAND_BUSWIDTH_16;
 
-	fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16);
+	fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16,
+			host->dev_timings);
 
 	if (AMBA_REV_BITS(host->pid) >= 8) {
 		nand->ecc.read_page = fsmc_read_page_hwecc;
@@ -979,7 +1003,8 @@ static int fsmc_nand_resume(struct device *dev)
 	if (host) {
 		clk_enable(host->clk);
 		fsmc_nand_setup(host->regs_va, host->bank,
-				host->nand.options & NAND_BUSWIDTH_16);
+				host->nand.options & NAND_BUSWIDTH_16,
+				host->dev_timings);
 	}
 	return 0;
 }
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index e877325..c4ac07a 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -90,17 +90,29 @@ struct fsmc_regs {
 #define FSMC_ECCEN		(1 << 6)
 #define FSMC_ECCPLEN_512	(0 << 7)
 #define FSMC_ECCPLEN_256	(1 << 7)
-#define FSMC_TCLR_1		(1 << 9)
-#define FSMC_TAR_1		(1 << 13)
+#define FSMC_TCLR_1		(1)
+#define FSMC_TCLR_SHIFT		(9)
+#define FSMC_TCLR_MASK		(0xF)
+#define FSMC_TAR_1		(1)
+#define FSMC_TAR_SHIFT		(13)
+#define FSMC_TAR_MASK		(0xF)
 
 /* sts register definitions */
 #define FSMC_CODE_RDY		(1 << 15)
 
 /* comm register definitions */
-#define FSMC_TSET_0		(0 << 0)
-#define FSMC_TWAIT_6		(6 << 8)
-#define FSMC_THOLD_4		(4 << 16)
-#define FSMC_THIZ_1		(1 << 24)
+#define FSMC_TSET_0		0
+#define FSMC_TSET_SHIFT		0
+#define FSMC_TSET_MASK		0xFF
+#define FSMC_TWAIT_6		6
+#define FSMC_TWAIT_SHIFT	8
+#define FSMC_TWAIT_MASK		0xFF
+#define FSMC_THOLD_4		4
+#define FSMC_THOLD_SHIFT	16
+#define FSMC_THOLD_MASK		0xFF
+#define FSMC_THIZ_1		1
+#define FSMC_THIZ_SHIFT		24
+#define FSMC_THIZ_MASK		0xFF
 
 /*
  * There are 13 bytes of ecc for every 512 byte block in FSMC version 8
@@ -120,6 +132,15 @@ struct fsmc_eccplace {
 	struct fsmc_nand_eccplace eccplace[MAX_ECCPLACE_ENTRIES];
 };
 
+struct fsmc_nand_timings {
+	uint8_t tclr;
+	uint8_t tar;
+	uint8_t thiz;
+	uint8_t thold;
+	uint8_t twait;
+	uint8_t tset;
+};
+
 /**
  * fsmc_nand_platform_data - platform specific NAND controller config
  * @partitions: partition table for the platform, use a default fallback
@@ -133,6 +154,7 @@ struct fsmc_eccplace {
  * this may be set to NULL
  */
 struct fsmc_nand_platform_data {
+	struct fsmc_nand_timings *nand_timings;
 	struct mtd_partition	*partitions;
 	unsigned int		nr_partitions;
 	unsigned int		options;
-- 
1.7.0.4

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

* [PATCH v2 09/13] nand/fsmc: Use devm routines
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (7 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 08/13] nand/fsmc: Modify fsmc driver to accept nand timing parameters via platform Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 10/13] nand/fsmc: Use dev_err to report error scenario Vipin Kumar
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

fsmc_nand driver currently uses normal kzalloc, request_mem etc routines. This
patch replaces these routines with devm_kzalloc and devm_request_mem_region etc.
Consequently, the error and driver removal scenarios are curtailed.

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Reviewed-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |  134 +++++++++++++----------------------------
 1 files changed, 43 insertions(+), 91 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 71fd9f6..f0168a3 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -298,11 +298,6 @@ struct fsmc_nand_data {
 	unsigned int		bank;
 	struct clk		*clk;
 
-	struct resource		*resregs;
-	struct resource		*rescmd;
-	struct resource		*resaddr;
-	struct resource		*resdata;
-
 	struct fsmc_nand_timings *dev_timings;
 
 	void __iomem		*data_va;
@@ -706,88 +701,81 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	}
 
 	/* Allocate memory for the device structure (and zero it) */
-	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
 	if (!host) {
 		dev_err(&pdev->dev, "failed to allocate device structure\n");
 		return -ENOMEM;
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
-	if (!res) {
-		ret = -EIO;
-		goto err_probe1;
-	}
+	if (!res)
+		return -EINVAL;
 
-	host->resdata = request_mem_region(res->start, resource_size(res),
-			pdev->name);
-	if (!host->resdata) {
-		ret = -EIO;
-		goto err_probe1;
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				pdev->name)) {
+		dev_err(&pdev->dev, "Failed to get memory data resourse\n");
+		return -ENOENT;
 	}
 
-	host->data_va = ioremap(res->start, resource_size(res));
+	host->data_va = devm_ioremap(&pdev->dev, res->start,
+			resource_size(res));
 	if (!host->data_va) {
-		ret = -EIO;
-		goto err_probe1;
+		dev_err(&pdev->dev, "data ioremap failed\n");
+		return -ENOMEM;
 	}
 
-	host->resaddr = request_mem_region(res->start + pdata->ale_off,
-			resource_size(res), pdev->name);
-	if (!host->resaddr) {
-		ret = -EIO;
-		goto err_probe1;
+	if (!devm_request_mem_region(&pdev->dev, res->start + pdata->ale_off,
+			resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "Failed to get memory ale resourse\n");
+		return -ENOENT;
 	}
 
-	host->addr_va = ioremap(res->start + pdata->ale_off,
+	host->addr_va = devm_ioremap(&pdev->dev, res->start + pdata->ale_off,
 			resource_size(res));
 	if (!host->addr_va) {
-		ret = -EIO;
-		goto err_probe1;
+		dev_err(&pdev->dev, "ale ioremap failed\n");
+		return -ENOMEM;
 	}
 
-	host->rescmd = request_mem_region(res->start + pdata->cle_off,
-			resource_size(res), pdev->name);
-	if (!host->rescmd) {
-		ret = -EIO;
-		goto err_probe1;
+	if (!devm_request_mem_region(&pdev->dev, res->start + pdata->cle_off,
+			resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev, "Failed to get memory cle resourse\n");
+		return -ENOENT;
 	}
 
-	host->cmd_va = ioremap(res->start + pdata->cle_off, resource_size(res));
+	host->cmd_va = devm_ioremap(&pdev->dev, res->start + pdata->cle_off,
+			resource_size(res));
 	if (!host->cmd_va) {
-		ret = -EIO;
-		goto err_probe1;
+		dev_err(&pdev->dev, "ale ioremap failed\n");
+		return -ENOMEM;
 	}
 
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fsmc_regs");
-	if (!res) {
-		ret = -EIO;
-		goto err_probe1;
-	}
+	if (!res)
+		return -EINVAL;
 
-	host->resregs = request_mem_region(res->start, resource_size(res),
-			pdev->name);
-	if (!host->resregs) {
-		ret = -EIO;
-		goto err_probe1;
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+			pdev->name)) {
+		dev_err(&pdev->dev, "Failed to get memory regs resourse\n");
+		return -ENOENT;
 	}
 
-	host->regs_va = ioremap(res->start, resource_size(res));
+	host->regs_va = devm_ioremap(&pdev->dev, res->start,
+			resource_size(res));
 	if (!host->regs_va) {
-		ret = -EIO;
-		goto err_probe1;
+		dev_err(&pdev->dev, "regs ioremap failed\n");
+		return -ENOMEM;
 	}
 
 	host->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(host->clk)) {
 		dev_err(&pdev->dev, "failed to fetch block clock\n");
-		ret = PTR_ERR(host->clk);
-		host->clk = NULL;
-		goto err_probe1;
+		return PTR_ERR(host->clk);
 	}
 
 	ret = clk_enable(host->clk);
 	if (ret)
-		goto err_probe1;
+		goto err_clk_enable;
 
 	/*
 	 * This device ID is actually a common AMBA ID as used on the
@@ -852,7 +840,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	if (nand_scan_ident(&host->mtd, 1, NULL)) {
 		ret = -ENXIO;
 		dev_err(&pdev->dev, "No NAND Device found!\n");
-		goto err_probe;
+		goto err_scan_ident;
 	}
 
 	if (AMBA_REV_BITS(host->pid) >= 8) {
@@ -927,32 +915,10 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	return 0;
 
 err_probe:
+err_scan_ident:
 	clk_disable(host->clk);
-err_probe1:
-	if (host->clk)
-		clk_put(host->clk);
-	if (host->regs_va)
-		iounmap(host->regs_va);
-	if (host->resregs)
-		release_mem_region(host->resregs->start,
-				resource_size(host->resregs));
-	if (host->cmd_va)
-		iounmap(host->cmd_va);
-	if (host->rescmd)
-		release_mem_region(host->rescmd->start,
-				resource_size(host->rescmd));
-	if (host->addr_va)
-		iounmap(host->addr_va);
-	if (host->resaddr)
-		release_mem_region(host->resaddr->start,
-				resource_size(host->resaddr));
-	if (host->data_va)
-		iounmap(host->data_va);
-	if (host->resdata)
-		release_mem_region(host->resdata->start,
-				resource_size(host->resdata));
-
-	kfree(host);
+err_clk_enable:
+	clk_put(host->clk);
 	return ret;
 }
 
@@ -969,22 +935,8 @@ static int fsmc_nand_remove(struct platform_device *pdev)
 		nand_release(&host->mtd);
 		clk_disable(host->clk);
 		clk_put(host->clk);
-
-		iounmap(host->regs_va);
-		release_mem_region(host->resregs->start,
-				resource_size(host->resregs));
-		iounmap(host->cmd_va);
-		release_mem_region(host->rescmd->start,
-				resource_size(host->rescmd));
-		iounmap(host->addr_va);
-		release_mem_region(host->resaddr->start,
-				resource_size(host->resaddr));
-		iounmap(host->data_va);
-		release_mem_region(host->resdata->start,
-				resource_size(host->resdata));
-
-		kfree(host);
 	}
+
 	return 0;
 }
 
-- 
1.7.0.4

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

* [PATCH v2 10/13] nand/fsmc: Use dev_err to report error scenario
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (8 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 09/13] nand/fsmc: Use devm routines Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 11/13] nand/fsmc: Access the NAND device word by word whenever possible Vipin Kumar
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

fsmc controller takes time to calculate the bch8 codes and the error offsets.
The calculate logic checks for completion upto a timeout. This patch adds a
error print when this timer expires and the ecc or error offsets are not yet
calculated.

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Reviewed-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index f0168a3..e093fd5 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -296,6 +296,7 @@ struct fsmc_nand_data {
 
 	struct fsmc_eccplace	*ecc_place;
 	unsigned int		bank;
+	struct device		*dev;
 	struct clk		*clk;
 
 	struct fsmc_nand_timings *dev_timings;
@@ -457,6 +458,11 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
 			cond_resched();
 	} while (!time_after_eq(jiffies, deadline));
 
+	if (time_after_eq(jiffies, deadline)) {
+		dev_err(host->dev, "calculate ecc timed out\n");
+		return -ETIMEDOUT;
+	}
+
 	ecc_tmp = readl(&regs->bank_regs[bank].ecc1);
 	ecc[0] = (uint8_t) (ecc_tmp >> 0);
 	ecc[1] = (uint8_t) (ecc_tmp >> 8);
@@ -793,6 +799,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	host->select_chip = pdata->select_bank;
 	host->partitions = pdata->partitions;
 	host->nr_partitions = pdata->nr_partitions;
+	host->dev = &pdev->dev;
 	host->dev_timings = pdata->nand_timings;
 	regs = host->regs_va;
 
-- 
1.7.0.4

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

* [PATCH v2 11/13] nand/fsmc: Access the NAND device word by word whenever possible
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (9 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 10/13] nand/fsmc: Use dev_err to report error scenario Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 12/13] nand/fsmc: Add DMA support Vipin Kumar
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

The default way of accessing nand device is using the nand width. This means
that 8bit devices are using u8 * and 16bit devices are accessed using u16 *.

This results in a non-optimal performance since the FSMC is designed to
translate the normal word accesses into device width based accesses. This patch
implements read_buf and write_buf callbacks using word by word accesses.

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Reviewed-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |   55 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/fsmc.h     |    6 ++++
 2 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index e093fd5..cc23bc1 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -524,6 +524,52 @@ static int count_written_bits(uint8_t *buff, int size, int max_bits)
 }
 
 /*
+ * fsmc_write_buf - write buffer to chip
+ * @mtd:	MTD device structure
+ * @buf:	data buffer
+ * @len:	number of bytes to write
+ */
+static void fsmc_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+	int i;
+	struct nand_chip *chip = mtd->priv;
+
+	if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
+			IS_ALIGNED(len, sizeof(uint32_t))) {
+		uint32_t *p = (uint32_t *)buf;
+		len = len >> 2;
+		for (i = 0; i < len; i++)
+			writel(p[i], chip->IO_ADDR_W);
+	} else {
+		for (i = 0; i < len; i++)
+			writeb(buf[i], chip->IO_ADDR_W);
+	}
+}
+
+/*
+ * fsmc_read_buf - read chip data into buffer
+ * @mtd:	MTD device structure
+ * @buf:	buffer to store date
+ * @len:	number of bytes to read
+ */
+static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	int i;
+	struct nand_chip *chip = mtd->priv;
+
+	if (IS_ALIGNED((uint32_t)buf, sizeof(uint32_t)) &&
+			IS_ALIGNED(len, sizeof(uint32_t))) {
+		uint32_t *p = (uint32_t *)buf;
+		len = len >> 2;
+		for (i = 0; i < len; i++)
+			p[i] = readl(chip->IO_ADDR_R);
+	} else {
+		for (i = 0; i < len; i++)
+			buf[i] = readb(chip->IO_ADDR_R);
+	}
+}
+
+/*
  * fsmc_read_page_hwecc
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
@@ -825,6 +871,15 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	if (pdata->width == FSMC_NAND_BW16)
 		nand->options |= NAND_BUSWIDTH_16;
 
+	/*
+	 * use customized (word by word) version of read_buf, write_buf if
+	 * access_with_dev_width is reset supported
+	 */
+	if (pdata->mode == USE_WORD_ACCESS) {
+		nand->read_buf = fsmc_read_buf;
+		nand->write_buf = fsmc_write_buf;
+	}
+
 	fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16,
 			host->dev_timings);
 
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index c4ac07a..1edd2b3 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -141,6 +141,11 @@ struct fsmc_nand_timings {
 	uint8_t tset;
 };
 
+enum access_mode {
+	USE_DMA_ACCESS = 1,
+	USE_WORD_ACCESS,
+};
+
 /**
  * fsmc_nand_platform_data - platform specific NAND controller config
  * @partitions: partition table for the platform, use a default fallback
@@ -164,6 +169,7 @@ struct fsmc_nand_platform_data {
 	/* CLE, ALE offsets */
 	unsigned long           cle_off;
 	unsigned long           ale_off;
+	enum access_mode	mode;
 
 	void			(*select_bank)(uint32_t bank, uint32_t busw);
 };
-- 
1.7.0.4

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

* [PATCH v2 12/13] nand/fsmc: Add DMA support
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (10 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 11/13] nand/fsmc: Access the NAND device word by word whenever possible Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14  6:17 ` [PATCH v2 13/13] nand/fsmc: Remove sparse warnings and errors Vipin Kumar
  2012-03-14 13:13 ` [PATCH v2 00/13] mtd/nand/fsmc related modifications Artem Bityutskiy
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1
  Cc: vinod.koul, linus.walleij, spear-devel, Vipin Kumar,
	dan.j.williams, sr

The fsmc_nand driver uses cpu to read/write onto the device. This is inefficient
because of two reasons
- the cpu gets locked on AHB bus while reading from NAND
- the cpu is unnecessarily used when dma can do the job

This patch adds the support for accessing the device through DMA

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
Reviewed-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |  168 ++++++++++++++++++++++++++++++++++++++++-
 include/linux/mtd/fsmc.h     |    4 +
 2 files changed, 167 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index cc23bc1..2e9adfc 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -17,6 +17,10 @@
  */
 
 #include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-direction.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -282,6 +286,11 @@ static struct fsmc_eccplace fsmc_ecc4_sp_place = {
  * @bank:		Bank number for probed device.
  * @clk:		Clock structure for FSMC.
  *
+ * @read_dma_chan:	DMA channel for read access
+ * @write_dma_chan:	DMA channel for write access to NAND
+ * @dma_access_complete: Completion structure
+ *
+ * @data_pa:		NAND Physical port for Data.
  * @data_va:		NAND port for Data.
  * @cmd_va:		NAND port for Command.
  * @addr_va:		NAND port for Address.
@@ -297,10 +306,17 @@ struct fsmc_nand_data {
 	struct fsmc_eccplace	*ecc_place;
 	unsigned int		bank;
 	struct device		*dev;
+	enum access_mode	mode;
 	struct clk		*clk;
 
+	/* DMA related objects */
+	struct dma_chan		*read_dma_chan;
+	struct dma_chan		*write_dma_chan;
+	struct completion	dma_access_complete;
+
 	struct fsmc_nand_timings *dev_timings;
 
+	dma_addr_t		data_pa;
 	void __iomem		*data_va;
 	void __iomem		*cmd_va;
 	void __iomem		*addr_va;
@@ -523,6 +539,77 @@ static int count_written_bits(uint8_t *buff, int size, int max_bits)
 	return written_bits;
 }
 
+static void dma_complete(void *param)
+{
+	struct fsmc_nand_data *host = param;
+
+	complete(&host->dma_access_complete);
+}
+
+static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len,
+		enum dma_data_direction direction)
+{
+	struct dma_chan *chan;
+	struct dma_device *dma_dev;
+	struct dma_async_tx_descriptor *tx;
+	dma_addr_t dma_dst, dma_src, dma_addr;
+	dma_cookie_t cookie;
+	unsigned long flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
+	int ret;
+
+	if (direction == DMA_TO_DEVICE)
+		chan = host->write_dma_chan;
+	else if (direction == DMA_FROM_DEVICE)
+		chan = host->read_dma_chan;
+	else
+		return -EINVAL;
+
+	dma_dev = chan->device;
+	dma_addr = dma_map_single(dma_dev->dev, buffer, len, direction);
+
+	if (direction == DMA_TO_DEVICE) {
+		dma_src = dma_addr;
+		dma_dst = host->data_pa;
+		flags |= DMA_COMPL_SRC_UNMAP_SINGLE | DMA_COMPL_SKIP_DEST_UNMAP;
+	} else {
+		dma_src = host->data_pa;
+		dma_dst = dma_addr;
+		flags |= DMA_COMPL_DEST_UNMAP_SINGLE | DMA_COMPL_SKIP_SRC_UNMAP;
+	}
+
+	tx = dma_dev->device_prep_dma_memcpy(chan, dma_dst, dma_src,
+			len, flags);
+
+	if (!tx) {
+		dev_err(host->dev, "device_prep_dma_memcpy error\n");
+		dma_unmap_single(dma_dev->dev, dma_addr, len, direction);
+		return -EIO;
+	}
+
+	tx->callback = dma_complete;
+	tx->callback_param = host;
+	cookie = tx->tx_submit(tx);
+
+	ret = dma_submit_error(cookie);
+	if (ret) {
+		dev_err(host->dev, "dma_submit_error %d\n", cookie);
+		return ret;
+	}
+
+	dma_async_issue_pending(chan);
+
+	ret =
+	wait_for_completion_interruptible_timeout(&host->dma_access_complete,
+				msecs_to_jiffies(3000));
+	if (ret <= 0) {
+		chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+		dev_err(host->dev, "wait_for_completion_timeout\n");
+		return ret ? ret : -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
 /*
  * fsmc_write_buf - write buffer to chip
  * @mtd:	MTD device structure
@@ -570,6 +657,35 @@ static void fsmc_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 }
 
 /*
+ * fsmc_read_buf_dma - read chip data into buffer
+ * @mtd:	MTD device structure
+ * @buf:	buffer to store date
+ * @len:	number of bytes to read
+ */
+static void fsmc_read_buf_dma(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct fsmc_nand_data *host;
+
+	host = container_of(mtd, struct fsmc_nand_data, mtd);
+	dma_xfer(host, buf, len, DMA_FROM_DEVICE);
+}
+
+/*
+ * fsmc_write_buf_dma - write buffer to chip
+ * @mtd:	MTD device structure
+ * @buf:	data buffer
+ * @len:	number of bytes to write
+ */
+static void fsmc_write_buf_dma(struct mtd_info *mtd, const uint8_t *buf,
+		int len)
+{
+	struct fsmc_nand_data *host;
+
+	host = container_of(mtd, struct fsmc_nand_data, mtd);
+	dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
+}
+
+/*
  * fsmc_read_page_hwecc
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
@@ -731,6 +847,12 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
 	return i;
 }
 
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	chan->private = slave;
+	return true;
+}
+
 /*
  * fsmc_nand_probe - Probe function
  * @pdev:       platform device structure
@@ -743,6 +865,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	struct nand_chip *nand;
 	struct fsmc_regs *regs;
 	struct resource *res;
+	dma_cap_mask_t mask;
 	int ret = 0;
 	u32 pid;
 	int i;
@@ -769,6 +892,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 		return -ENOENT;
 	}
 
+	host->data_pa = (dma_addr_t)res->start;
 	host->data_va = devm_ioremap(&pdev->dev, res->start,
 			resource_size(res));
 	if (!host->data_va) {
@@ -847,6 +971,11 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	host->nr_partitions = pdata->nr_partitions;
 	host->dev = &pdev->dev;
 	host->dev_timings = pdata->nand_timings;
+	host->mode = pdata->mode;
+
+	if (host->mode == USE_DMA_ACCESS)
+		init_completion(&host->dma_access_complete);
+
 	regs = host->regs_va;
 
 	/* Link all private pointers */
@@ -871,13 +1000,31 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	if (pdata->width == FSMC_NAND_BW16)
 		nand->options |= NAND_BUSWIDTH_16;
 
-	/*
-	 * use customized (word by word) version of read_buf, write_buf if
-	 * access_with_dev_width is reset supported
-	 */
-	if (pdata->mode == USE_WORD_ACCESS) {
+	switch (host->mode) {
+	case USE_DMA_ACCESS:
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_MEMCPY, mask);
+		host->read_dma_chan = dma_request_channel(mask, filter,
+				pdata->read_dma_priv);
+		if (!host->read_dma_chan) {
+			dev_err(&pdev->dev, "Unable to get read dma channel\n");
+			goto err_req_read_chnl;
+		}
+		host->write_dma_chan = dma_request_channel(mask, filter,
+				pdata->write_dma_priv);
+		if (!host->write_dma_chan) {
+			dev_err(&pdev->dev, "Unable to get write dma channel\n");
+			goto err_req_write_chnl;
+		}
+		nand->read_buf = fsmc_read_buf_dma;
+		nand->write_buf = fsmc_write_buf_dma;
+		break;
+
+	default:
+	case USE_WORD_ACCESS:
 		nand->read_buf = fsmc_read_buf;
 		nand->write_buf = fsmc_write_buf;
+		break;
 	}
 
 	fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16,
@@ -978,6 +1125,12 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 
 err_probe:
 err_scan_ident:
+	if (host->mode == USE_DMA_ACCESS)
+		dma_release_channel(host->write_dma_chan);
+err_req_write_chnl:
+	if (host->mode == USE_DMA_ACCESS)
+		dma_release_channel(host->read_dma_chan);
+err_req_read_chnl:
 	clk_disable(host->clk);
 err_clk_enable:
 	clk_put(host->clk);
@@ -995,6 +1148,11 @@ static int fsmc_nand_remove(struct platform_device *pdev)
 
 	if (host) {
 		nand_release(&host->mtd);
+
+		if (host->mode == USE_DMA_ACCESS) {
+			dma_release_channel(host->write_dma_chan);
+			dma_release_channel(host->read_dma_chan);
+		}
 		clk_disable(host->clk);
 		clk_put(host->clk);
 	}
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index 1edd2b3..18f9127 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -172,6 +172,10 @@ struct fsmc_nand_platform_data {
 	enum access_mode	mode;
 
 	void			(*select_bank)(uint32_t bank, uint32_t busw);
+
+	/* priv structures for dma accesses */
+	void			*read_dma_priv;
+	void			*write_dma_priv;
 };
 
 extern int __init fsmc_nor_init(struct platform_device *pdev,
-- 
1.7.0.4

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

* [PATCH v2 13/13] nand/fsmc: Remove sparse warnings and errors
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (11 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 12/13] nand/fsmc: Add DMA support Vipin Kumar
@ 2012-03-14  6:17 ` Vipin Kumar
  2012-03-14 13:13 ` [PATCH v2 00/13] mtd/nand/fsmc related modifications Artem Bityutskiy
  13 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-14  6:17 UTC (permalink / raw)
  To: linux-mtd, dedekind1; +Cc: sr, Vipin Kumar, linus.walleij, spear-devel

This patch removes the sparse below warnings and errors for nand/fsmc driver
/root/vipin/spear/kernel/3.3/linux-3.3/drivers/mtd/nand/fsmc_nand.c:363:31:
warning: incorrect type in initializer (different address spaces)
/root/vipin/spear/kernel/3.3/linux-3.3/drivers/mtd/nand/fsmc_nand.c:363:31:
expected struct fsmc_regs *regs
/root/vipin/spear/kernel/3.3/linux-3.3/drivers/mtd/nand/fsmc_nand.c:363:31:
got void [noderef] <asn:2>*regs_va

[...]

Signed-off-by: Vipin Kumar <vipin.kumar@st.com>
---
 drivers/mtd/nand/fsmc_nand.c |   91 +++++++++++++-------------
 include/linux/mtd/fsmc.h     |  143 +++++++++++++++++++----------------------
 2 files changed, 111 insertions(+), 123 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 2e9adfc..32f98c2 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -360,28 +360,29 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 	struct nand_chip *this = mtd->priv;
 	struct fsmc_nand_data *host = container_of(mtd,
 					struct fsmc_nand_data, mtd);
-	struct fsmc_regs *regs = host->regs_va;
+	void *__iomem *regs = host->regs_va;
 	unsigned int bank = host->bank;
 
 	if (ctrl & NAND_CTRL_CHANGE) {
+		u32 pc;
+
 		if (ctrl & NAND_CLE) {
-			this->IO_ADDR_R = (void __iomem *)host->cmd_va;
-			this->IO_ADDR_W = (void __iomem *)host->cmd_va;
+			this->IO_ADDR_R = host->cmd_va;
+			this->IO_ADDR_W = host->cmd_va;
 		} else if (ctrl & NAND_ALE) {
-			this->IO_ADDR_R = (void __iomem *)host->addr_va;
-			this->IO_ADDR_W = (void __iomem *)host->addr_va;
+			this->IO_ADDR_R = host->addr_va;
+			this->IO_ADDR_W = host->addr_va;
 		} else {
-			this->IO_ADDR_R = (void __iomem *)host->data_va;
-			this->IO_ADDR_W = (void __iomem *)host->data_va;
+			this->IO_ADDR_R = host->data_va;
+			this->IO_ADDR_W = host->data_va;
 		}
 
-		if (ctrl & NAND_NCE) {
-			writel(readl(&regs->bank_regs[bank].pc) | FSMC_ENABLE,
-					&regs->bank_regs[bank].pc);
-		} else {
-			writel(readl(&regs->bank_regs[bank].pc) & ~FSMC_ENABLE,
-				       &regs->bank_regs[bank].pc);
-		}
+		pc = readl(FSMC_NAND_REG(regs, bank, PC));
+		if (ctrl & NAND_NCE)
+			pc |= FSMC_ENABLE;
+		else
+			pc &= ~FSMC_ENABLE;
+		writel(pc, FSMC_NAND_REG(regs, bank, PC));
 	}
 
 	mb();
@@ -396,7 +397,7 @@ static void fsmc_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
  * This routine initializes timing parameters related to NAND memory access in
  * FSMC registers
  */
-static void fsmc_nand_setup(struct fsmc_regs *regs, uint32_t bank,
+static void fsmc_nand_setup(void __iomem *regs, uint32_t bank,
 			   uint32_t busw, struct fsmc_nand_timings *timings)
 {
 	uint32_t value = FSMC_DEVTYPE_NAND | FSMC_ENABLE | FSMC_WAITON;
@@ -424,14 +425,14 @@ static void fsmc_nand_setup(struct fsmc_regs *regs, uint32_t bank,
 	tset = (tims->tset & FSMC_TSET_MASK) << FSMC_TSET_SHIFT;
 
 	if (busw)
-		writel(value | FSMC_DEVWID_16, &regs->bank_regs[bank].pc);
+		writel(value | FSMC_DEVWID_16, FSMC_NAND_REG(regs, bank, PC));
 	else
-		writel(value | FSMC_DEVWID_8, &regs->bank_regs[bank].pc);
+		writel(value | FSMC_DEVWID_8, FSMC_NAND_REG(regs, bank, PC));
 
-	writel(readl(&regs->bank_regs[bank].pc) | tclr | tar,
-	       &regs->bank_regs[bank].pc);
-	writel(thiz | thold | twait | tset, &regs->bank_regs[bank].comm);
-	writel(thiz | thold | twait | tset, &regs->bank_regs[bank].attrib);
+	writel(readl(FSMC_NAND_REG(regs, bank, PC)) | tclr | tar,
+			FSMC_NAND_REG(regs, bank, PC));
+	writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, COMM));
+	writel(thiz | thold | twait | tset, FSMC_NAND_REG(regs, bank, ATTRIB));
 }
 
 /*
@@ -441,15 +442,15 @@ static void fsmc_enable_hwecc(struct mtd_info *mtd, int mode)
 {
 	struct fsmc_nand_data *host = container_of(mtd,
 					struct fsmc_nand_data, mtd);
-	struct fsmc_regs *regs = host->regs_va;
+	void __iomem *regs = host->regs_va;
 	uint32_t bank = host->bank;
 
-	writel(readl(&regs->bank_regs[bank].pc) & ~FSMC_ECCPLEN_256,
-		       &regs->bank_regs[bank].pc);
-	writel(readl(&regs->bank_regs[bank].pc) & ~FSMC_ECCEN,
-			&regs->bank_regs[bank].pc);
-	writel(readl(&regs->bank_regs[bank].pc) | FSMC_ECCEN,
-			&regs->bank_regs[bank].pc);
+	writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCPLEN_256,
+			FSMC_NAND_REG(regs, bank, PC));
+	writel(readl(FSMC_NAND_REG(regs, bank, PC)) & ~FSMC_ECCEN,
+			FSMC_NAND_REG(regs, bank, PC));
+	writel(readl(FSMC_NAND_REG(regs, bank, PC)) | FSMC_ECCEN,
+			FSMC_NAND_REG(regs, bank, PC));
 }
 
 /*
@@ -462,13 +463,13 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
 {
 	struct fsmc_nand_data *host = container_of(mtd,
 					struct fsmc_nand_data, mtd);
-	struct fsmc_regs *regs = host->regs_va;
+	void __iomem *regs = host->regs_va;
 	uint32_t bank = host->bank;
 	uint32_t ecc_tmp;
 	unsigned long deadline = jiffies + FSMC_BUSY_WAIT_TIMEOUT;
 
 	do {
-		if (readl(&regs->bank_regs[bank].sts) & FSMC_CODE_RDY)
+		if (readl(FSMC_NAND_REG(regs, bank, STS)) & FSMC_CODE_RDY)
 			break;
 		else
 			cond_resched();
@@ -479,25 +480,25 @@ static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
 		return -ETIMEDOUT;
 	}
 
-	ecc_tmp = readl(&regs->bank_regs[bank].ecc1);
+	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1));
 	ecc[0] = (uint8_t) (ecc_tmp >> 0);
 	ecc[1] = (uint8_t) (ecc_tmp >> 8);
 	ecc[2] = (uint8_t) (ecc_tmp >> 16);
 	ecc[3] = (uint8_t) (ecc_tmp >> 24);
 
-	ecc_tmp = readl(&regs->bank_regs[bank].ecc2);
+	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC2));
 	ecc[4] = (uint8_t) (ecc_tmp >> 0);
 	ecc[5] = (uint8_t) (ecc_tmp >> 8);
 	ecc[6] = (uint8_t) (ecc_tmp >> 16);
 	ecc[7] = (uint8_t) (ecc_tmp >> 24);
 
-	ecc_tmp = readl(&regs->bank_regs[bank].ecc3);
+	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC3));
 	ecc[8] = (uint8_t) (ecc_tmp >> 0);
 	ecc[9] = (uint8_t) (ecc_tmp >> 8);
 	ecc[10] = (uint8_t) (ecc_tmp >> 16);
 	ecc[11] = (uint8_t) (ecc_tmp >> 24);
 
-	ecc_tmp = readl(&regs->bank_regs[bank].sts);
+	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, STS));
 	ecc[12] = (uint8_t) (ecc_tmp >> 16);
 
 	return 0;
@@ -513,11 +514,11 @@ static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
 {
 	struct fsmc_nand_data *host = container_of(mtd,
 					struct fsmc_nand_data, mtd);
-	struct fsmc_regs *regs = host->regs_va;
+	void __iomem *regs = host->regs_va;
 	uint32_t bank = host->bank;
 	uint32_t ecc_tmp;
 
-	ecc_tmp = readl(&regs->bank_regs[bank].ecc1);
+	ecc_tmp = readl(FSMC_NAND_REG(regs, bank, ECC1));
 	ecc[0] = (uint8_t) (ecc_tmp >> 0);
 	ecc[1] = (uint8_t) (ecc_tmp >> 8);
 	ecc[2] = (uint8_t) (ecc_tmp >> 16);
@@ -771,13 +772,13 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
 	struct fsmc_nand_data *host = container_of(mtd,
 					struct fsmc_nand_data, mtd);
 	struct nand_chip *chip = mtd->priv;
-	struct fsmc_regs *regs = host->regs_va;
+	void __iomem *regs = host->regs_va;
 	unsigned int bank = host->bank;
 	uint32_t err_idx[8];
 	uint32_t num_err, i;
 	uint32_t ecc1, ecc2, ecc3, ecc4;
 
-	num_err = (readl(&regs->bank_regs[bank].sts) >> 10) & 0xF;
+	num_err = (readl(FSMC_NAND_REG(regs, bank, STS)) >> 10) & 0xF;
 
 	/* no bit flipping */
 	if (likely(num_err == 0))
@@ -820,10 +821,10 @@ static int fsmc_bch8_correct_data(struct mtd_info *mtd, uint8_t *dat,
 	 * uint64_t array and error offset indexes are populated in err_idx
 	 * array
 	 */
-	ecc1 = readl(&regs->bank_regs[bank].ecc1);
-	ecc2 = readl(&regs->bank_regs[bank].ecc2);
-	ecc3 = readl(&regs->bank_regs[bank].ecc3);
-	ecc4 = readl(&regs->bank_regs[bank].sts);
+	ecc1 = readl(FSMC_NAND_REG(regs, bank, ECC1));
+	ecc2 = readl(FSMC_NAND_REG(regs, bank, ECC2));
+	ecc3 = readl(FSMC_NAND_REG(regs, bank, ECC3));
+	ecc4 = readl(FSMC_NAND_REG(regs, bank, STS));
 
 	err_idx[0] = (ecc1 >> 0) & 0x1FFF;
 	err_idx[1] = (ecc1 >> 13) & 0x1FFF;
@@ -863,7 +864,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	struct fsmc_nand_data *host;
 	struct mtd_info *mtd;
 	struct nand_chip *nand;
-	struct fsmc_regs *regs;
 	struct resource *res;
 	dma_cap_mask_t mask;
 	int ret = 0;
@@ -976,8 +976,6 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	if (host->mode == USE_DMA_ACCESS)
 		init_completion(&host->dma_access_complete);
 
-	regs = host->regs_va;
-
 	/* Link all private pointers */
 	mtd = &host->mtd;
 	nand = &host->nand;
@@ -1027,7 +1025,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 		break;
 	}
 
-	fsmc_nand_setup(regs, host->bank, nand->options & NAND_BUSWIDTH_16,
+	fsmc_nand_setup(host->regs_va, host->bank,
+			nand->options & NAND_BUSWIDTH_16,
 			host->dev_timings);
 
 	if (AMBA_REV_BITS(host->pid) >= 8) {
diff --git a/include/linux/mtd/fsmc.h b/include/linux/mtd/fsmc.h
index 18f9127..823359c 100644
--- a/include/linux/mtd/fsmc.h
+++ b/include/linux/mtd/fsmc.h
@@ -32,88 +32,77 @@
 #define FSMC_FLASH_WIDTH8	1
 #define FSMC_FLASH_WIDTH16	2
 
-struct fsmc_nor_bank_regs {
-	uint32_t ctrl;
-	uint32_t ctrl_tim;
-};
-
-/* ctrl register definitions */
-#define BANK_ENABLE		(1 << 0)
-#define MUXED			(1 << 1)
-#define NOR_DEV			(2 << 2)
-#define WIDTH_8			(0 << 4)
-#define WIDTH_16		(1 << 4)
-#define RSTPWRDWN		(1 << 6)
-#define WPROT			(1 << 7)
-#define WRT_ENABLE		(1 << 12)
-#define WAIT_ENB		(1 << 13)
-
-/* ctrl_tim register definitions */
-
-struct fsmc_nand_bank_regs {
-	uint32_t pc;
-	uint32_t sts;
-	uint32_t comm;
-	uint32_t attrib;
-	uint32_t ioata;
-	uint32_t ecc1;
-	uint32_t ecc2;
-	uint32_t ecc3;
-};
-
+/* fsmc controller registers for NOR flash */
+#define CTRL			0x0
+	/* ctrl register definitions */
+	#define BANK_ENABLE		(1 << 0)
+	#define MUXED			(1 << 1)
+	#define NOR_DEV			(2 << 2)
+	#define WIDTH_8			(0 << 4)
+	#define WIDTH_16		(1 << 4)
+	#define RSTPWRDWN		(1 << 6)
+	#define WPROT			(1 << 7)
+	#define WRT_ENABLE		(1 << 12)
+	#define WAIT_ENB		(1 << 13)
+
+#define CTRL_TIM		0x4
+	/* ctrl_tim register definitions */
+
+#define FSMC_NOR_BANK_SZ	0x8
 #define FSMC_NOR_REG_SIZE	0x40
 
-struct fsmc_regs {
-	struct fsmc_nor_bank_regs nor_bank_regs[FSMC_MAX_NOR_BANKS];
-	uint8_t reserved_1[0x40 - 0x20];
-	struct fsmc_nand_bank_regs bank_regs[FSMC_MAX_NAND_BANKS];
-	uint8_t reserved_2[0xfe0 - 0xc0];
-	uint32_t peripid0;			/* 0xfe0 */
-	uint32_t peripid1;			/* 0xfe4 */
-	uint32_t peripid2;			/* 0xfe8 */
-	uint32_t peripid3;			/* 0xfec */
-	uint32_t pcellid0;			/* 0xff0 */
-	uint32_t pcellid1;			/* 0xff4 */
-	uint32_t pcellid2;			/* 0xff8 */
-	uint32_t pcellid3;			/* 0xffc */
-};
+#define FSMC_NOR_REG(base, bank, reg)		(base + \
+						FSMC_NOR_BANK_SZ * (bank) + \
+						reg)
+
+/* fsmc controller registers for NAND flash */
+#define PC			0x00
+	/* pc register definitions */
+	#define FSMC_RESET		(1 << 0)
+	#define FSMC_WAITON		(1 << 1)
+	#define FSMC_ENABLE		(1 << 2)
+	#define FSMC_DEVTYPE_NAND	(1 << 3)
+	#define FSMC_DEVWID_8		(0 << 4)
+	#define FSMC_DEVWID_16		(1 << 4)
+	#define FSMC_ECCEN		(1 << 6)
+	#define FSMC_ECCPLEN_512	(0 << 7)
+	#define FSMC_ECCPLEN_256	(1 << 7)
+	#define FSMC_TCLR_1		(1)
+	#define FSMC_TCLR_SHIFT		(9)
+	#define FSMC_TCLR_MASK		(0xF)
+	#define FSMC_TAR_1		(1)
+	#define FSMC_TAR_SHIFT		(13)
+	#define FSMC_TAR_MASK		(0xF)
+#define STS			0x04
+	/* sts register definitions */
+	#define FSMC_CODE_RDY		(1 << 15)
+#define COMM			0x08
+	/* comm register definitions */
+	#define FSMC_TSET_0		0
+	#define FSMC_TSET_SHIFT		0
+	#define FSMC_TSET_MASK		0xFF
+	#define FSMC_TWAIT_6		6
+	#define FSMC_TWAIT_SHIFT	8
+	#define FSMC_TWAIT_MASK		0xFF
+	#define FSMC_THOLD_4		4
+	#define FSMC_THOLD_SHIFT	16
+	#define FSMC_THOLD_MASK		0xFF
+	#define FSMC_THIZ_1		1
+	#define FSMC_THIZ_SHIFT		24
+	#define FSMC_THIZ_MASK		0xFF
+#define ATTRIB			0x0C
+#define IOATA			0x10
+#define ECC1			0x14
+#define ECC2			0x18
+#define ECC3			0x1C
+#define FSMC_NAND_BANK_SZ	0x20
+
+#define FSMC_NAND_REG(base, bank, reg)		(base + FSMC_NOR_REG_SIZE + \
+						(FSMC_NAND_BANK_SZ * (bank)) + \
+						reg)
 
 #define FSMC_BUSY_WAIT_TIMEOUT	(1 * HZ)
 
-/* pc register definitions */
-#define FSMC_RESET		(1 << 0)
-#define FSMC_WAITON		(1 << 1)
-#define FSMC_ENABLE		(1 << 2)
-#define FSMC_DEVTYPE_NAND	(1 << 3)
-#define FSMC_DEVWID_8		(0 << 4)
-#define FSMC_DEVWID_16		(1 << 4)
-#define FSMC_ECCEN		(1 << 6)
-#define FSMC_ECCPLEN_512	(0 << 7)
-#define FSMC_ECCPLEN_256	(1 << 7)
-#define FSMC_TCLR_1		(1)
-#define FSMC_TCLR_SHIFT		(9)
-#define FSMC_TCLR_MASK		(0xF)
-#define FSMC_TAR_1		(1)
-#define FSMC_TAR_SHIFT		(13)
-#define FSMC_TAR_MASK		(0xF)
-
-/* sts register definitions */
-#define FSMC_CODE_RDY		(1 << 15)
-
-/* comm register definitions */
-#define FSMC_TSET_0		0
-#define FSMC_TSET_SHIFT		0
-#define FSMC_TSET_MASK		0xFF
-#define FSMC_TWAIT_6		6
-#define FSMC_TWAIT_SHIFT	8
-#define FSMC_TWAIT_MASK		0xFF
-#define FSMC_THOLD_4		4
-#define FSMC_THOLD_SHIFT	16
-#define FSMC_THOLD_MASK		0xFF
-#define FSMC_THIZ_1		1
-#define FSMC_THIZ_SHIFT		24
-#define FSMC_THIZ_MASK		0xFF
-
 /*
  * There are 13 bytes of ecc for every 512 byte block in FSMC version 8
  * and it has to be read consecutively and immediately after the 512
-- 
1.7.0.4

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

* Re: [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data
  2012-03-14  6:17 ` [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data Vipin Kumar
@ 2012-03-14 11:06   ` Linus Walleij
  2012-03-14 12:13     ` Artem Bityutskiy
  2012-03-14 11:24   ` Stefan Roese
  2012-03-14 12:12   ` Artem Bityutskiy
  2 siblings, 1 reply; 20+ messages in thread
From: Linus Walleij @ 2012-03-14 11:06 UTC (permalink / raw)
  To: Vipin Kumar; +Cc: sr, spear-devel, linux-mtd, dedekind1

On Wed, Mar 14, 2012 at 7:17 AM, Vipin Kumar <vipin.kumar@st.com> wrote:

> This patch reimplements the passing of partition information through platform
> data. This was unintentionally deleted in commit
> 0d04eda1430e9a796214bee644b7e05d99cfe613
> "mtd: fsmc_nand.c: use mtd_device_parse_register"
>
> Signed-off-by: Vipin Kumar <vipin.kumar@st.com>

Acked/Reviewed/Signed -off-by: Linus Walleij <linus.walleij@linaro.org>

Also recommend adding Cc: stable@kernel.org on this then.

Thanks!
Linus Walleij

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

* Re: [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data
  2012-03-14  6:17 ` [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data Vipin Kumar
  2012-03-14 11:06   ` Linus Walleij
@ 2012-03-14 11:24   ` Stefan Roese
  2012-03-14 12:12   ` Artem Bityutskiy
  2 siblings, 0 replies; 20+ messages in thread
From: Stefan Roese @ 2012-03-14 11:24 UTC (permalink / raw)
  To: linux-mtd; +Cc: Vipin Kumar, linus.walleij, spear-devel, dedekind1

On Wednesday 14 March 2012 07:17:07 Vipin Kumar wrote:
> This patch reimplements the passing of partition information through
> platform data. This was unintentionally deleted in commit
> 0d04eda1430e9a796214bee644b7e05d99cfe613
> "mtd: fsmc_nand.c: use mtd_device_parse_register"
> 
> Signed-off-by: Vipin Kumar <vipin.kumar@st.com>

Acked-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

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

* Re: [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data
  2012-03-14  6:17 ` [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data Vipin Kumar
  2012-03-14 11:06   ` Linus Walleij
  2012-03-14 11:24   ` Stefan Roese
@ 2012-03-14 12:12   ` Artem Bityutskiy
  2012-03-15  3:34     ` Vipin Kumar
  2 siblings, 1 reply; 20+ messages in thread
From: Artem Bityutskiy @ 2012-03-14 12:12 UTC (permalink / raw)
  To: Vipin Kumar; +Cc: sr, linus.walleij, spear-devel, linux-mtd

[-- Attachment #1: Type: text/plain, Size: 307 bytes --]

On Wed, 2012-03-14 at 11:47 +0530, Vipin Kumar wrote:
> +	ret = mtd_device_parse_register(&host->mtd, NULL, 0, host->partitions,
> +			host->nr_partitions);

This causes a GCC warning about passing plain 0 as NULL. But I'll amend
the patch myself and fix this.

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data
  2012-03-14 11:06   ` Linus Walleij
@ 2012-03-14 12:13     ` Artem Bityutskiy
  0 siblings, 0 replies; 20+ messages in thread
From: Artem Bityutskiy @ 2012-03-14 12:13 UTC (permalink / raw)
  To: Linus Walleij; +Cc: Vipin Kumar, spear-devel, linux-mtd, sr

[-- Attachment #1: Type: text/plain, Size: 276 bytes --]

On Wed, 2012-03-14 at 12:06 +0100, Linus Walleij wrote:

> Acked/Reviewed/Signed -off-by: Linus Walleij <linus.walleij@linaro.org>
> 
> Also recommend adding Cc: stable@kernel.org on this then.

Thanks, I will add -stable to CC.

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v2 00/13] mtd/nand/fsmc related modifications
  2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
                   ` (12 preceding siblings ...)
  2012-03-14  6:17 ` [PATCH v2 13/13] nand/fsmc: Remove sparse warnings and errors Vipin Kumar
@ 2012-03-14 13:13 ` Artem Bityutskiy
  13 siblings, 0 replies; 20+ messages in thread
From: Artem Bityutskiy @ 2012-03-14 13:13 UTC (permalink / raw)
  To: Vipin Kumar; +Cc: sr, linus.walleij, spear-devel, linux-mtd

[-- Attachment #1: Type: text/plain, Size: 571 bytes --]

On Wed, 2012-03-14 at 11:47 +0530, Vipin Kumar wrote:
> Hello Artem,
> 
> These are the patches 8-20 of the original patchset of which 1-7 have already
> been applied by you. I have rebased these patches over
> git://git.infradead.org/users/dedekind/l2-mtd.git to help you apply these easily
> 
> Modifications in v2
> - Add support for partition information to be passed from platform data
> - Default partition information removed from driver
> - Remove sparse errors and warnings

Pushed all to l2-mtd.git, thanks!

-- 
Best Regards,
Artem Bityutskiy

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data
  2012-03-14 12:12   ` Artem Bityutskiy
@ 2012-03-15  3:34     ` Vipin Kumar
  0 siblings, 0 replies; 20+ messages in thread
From: Vipin Kumar @ 2012-03-15  3:34 UTC (permalink / raw)
  To: dedekind1@gmail.com
  Cc: sr@denx.de, linus.walleij@linaro.org, spear-devel,
	linux-mtd@lists.infradead.org

On 3/14/2012 5:42 PM, Artem Bityutskiy wrote:
> On Wed, 2012-03-14 at 11:47 +0530, Vipin Kumar wrote:
>> +	ret = mtd_device_parse_register(&host->mtd, NULL, 0, host->partitions,
>> +			host->nr_partitions);
>
> This causes a GCC warning about passing plain 0 as NULL. But I'll amend
> the patch myself and fix this.
>

Thanks Artem

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

end of thread, other threads:[~2012-03-15  3:35 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-14  6:17 [PATCH v2 00/13] mtd/nand/fsmc related modifications Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 01/13] nand/fsmc: Pass partition information through platform data Vipin Kumar
2012-03-14 11:06   ` Linus Walleij
2012-03-14 12:13     ` Artem Bityutskiy
2012-03-14 11:24   ` Stefan Roese
2012-03-14 12:12   ` Artem Bityutskiy
2012-03-15  3:34     ` Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 02/13] nand/fsmc: Remove default partition information from driver Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 03/13] nand/fsmc: Correct the multiline comment format Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 04/13] nand/fsmc: Read only 512 + 13 bytes for 8bit NAND devices Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 05/13] nand/fsmc: Flip the bit only if the error index is < 4096 Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 06/13] nand/fsmc: Initialize the badblockbits to 7 Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 07/13] mtd/fsmc_nand: add pm callbacks to support hibernation Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 08/13] nand/fsmc: Modify fsmc driver to accept nand timing parameters via platform Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 09/13] nand/fsmc: Use devm routines Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 10/13] nand/fsmc: Use dev_err to report error scenario Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 11/13] nand/fsmc: Access the NAND device word by word whenever possible Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 12/13] nand/fsmc: Add DMA support Vipin Kumar
2012-03-14  6:17 ` [PATCH v2 13/13] nand/fsmc: Remove sparse warnings and errors Vipin Kumar
2012-03-14 13:13 ` [PATCH v2 00/13] mtd/nand/fsmc related modifications Artem Bityutskiy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).