Patchwork [MTD] MXC NAND support for 2k page size flashes

login
register
mail settings
Submitter Vladimir Barinov
Date May 25, 2009, 9:06 a.m.
Message ID <1243242377-4470-1-git-send-email-vbarinov@embeddedalley.com>
Download mbox | patch
Permalink /patch/27603/
State New
Headers show

Comments

Vladimir Barinov - May 25, 2009, 9:06 a.m.
- Add support for 2k page size flashes
- Fix page address access for large pages
- Detect oob layout at runtime
- handle pagesize_2k variable
- Fix oob16 layout: reserve location 5 of oob area since it's used for bbt
---
 drivers/mtd/nand/mxc_nand.c |   60 ++++++++++++++++++++++++++++++++++++------
 1 files changed, 51 insertions(+), 9 deletions(-)
Alberto Panizzo - May 25, 2009, 9:52 a.m.
On Mon, 25 May 2009 13:06:17 +0400
Vladimir Barinov <vova.barinov@gmail.com> wrote:

> - Add support for 2k page size flashes
> - Fix page address access for large pages
> - Detect oob layout at runtime
> - handle pagesize_2k variable
> - Fix oob16 layout: reserve location 5 of oob area since it's used for bbt
> ---
>  drivers/mtd/nand/mxc_nand.c |   60 ++++++++++++++++++++++++++++++++++++------
>  1 files changed, 51 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
> index f3548d0..5ab8985 100644
> --- a/drivers/mtd/nand/mxc_nand.c
> +++ b/drivers/mtd/nand/mxc_nand.c
> @@ -138,7 +138,14 @@ static struct nand_ecclayout nand_hw_eccoob_8 = {
>  static struct nand_ecclayout nand_hw_eccoob_16 = {
>  	.eccbytes = 5,
>  	.eccpos = {6, 7, 8, 9, 10},
> -	.oobfree = {{0, 6}, {12, 4}, }
> +	.oobfree = {{0, 5}, {11, 5}, }
> +};
> +
> +static struct nand_ecclayout nand_hw_eccoob_64 = {
> +	.eccbytes = 20,
> +	.eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
> +		   38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
> +	.oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
>  };
>  
>  #ifdef CONFIG_MTD_PARTITIONS
> @@ -795,9 +802,13 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
>  		send_addr(host, (page_addr & 0xff), false);
>  
>  		if (host->pagesize_2k) {
> -			send_addr(host, (page_addr >> 8) & 0xFF, false);
> -			if (mtd->size >= 0x40000000)
> +			if (mtd->size >= 0x10000000) {
> +				/* paddr_8 - paddr_15 */
> +				send_addr(host, (page_addr >> 8) & 0xff, false);
>  				send_addr(host, (page_addr >> 16) & 0xff, true);
> +			} else
> +				/* paddr_8 - paddr_15 */
> +				send_addr(host, (page_addr >> 8) & 0xff, true);
>  		} else {
>  			/* One more address cycle for higher density devices */
>  			if (mtd->size >= 0x4000000) {
> @@ -919,7 +930,6 @@ static int __init mxcnd_probe(struct platform_device *pdev)
>  		this->ecc.mode = NAND_ECC_HW;
>  		this->ecc.size = 512;
>  		this->ecc.bytes = 3;
> -		this->ecc.layout = &nand_hw_eccoob_8;
>  		tmp = readw(host->regs + NFC_CONFIG1);
>  		tmp |= NFC_ECC_EN;
>  		writew(tmp, host->regs + NFC_CONFIG1);
> @@ -953,12 +963,44 @@ static int __init mxcnd_probe(struct platform_device *pdev)
>  		this->ecc.layout = &nand_hw_eccoob_16;
>  	}
>  
> -	host->pagesize_2k = 0;
> +	/* first scan to find the device and get the page size */
> +	if (nand_scan_ident(mtd, 1)) {
> +		err = -ENXIO;
> +		goto escan;
> +	}
>  
> -	/* Scan to find existence of the device */
> -	if (nand_scan(mtd, 1)) {
> -		DEBUG(MTD_DEBUG_LEVEL0,
> -		      "MXC_ND: Unable to find any NAND device.\n");
> +	host->pagesize_2k = (mtd->writesize == 2048) ? 1 : 0;
> +
> +	if (this->ecc.mode == NAND_ECC_HW) {
> +		switch (mtd->oobsize) {
> +		case 8:
> +			this->ecc.layout = &nand_hw_eccoob_8;
> +			break;
> +		case 16:
> +			this->ecc.layout = &nand_hw_eccoob_16;
> +			break;
> +		case 64:
> +			this->ecc.layout = &nand_hw_eccoob_64;
> +			break;
> +		default:
> +			/* page size not handled by HW ECC */
> +			/* switching back to soft ECC */
> +			this->ecc.size = 512;
> +			this->ecc.bytes = 3;
> +			this->ecc.layout = &nand_hw_eccoob_8;
> +			this->ecc.mode = NAND_ECC_SOFT;
> +			this->ecc.calculate = NULL;
> +			this->ecc.correct = NULL;
> +			this->ecc.hwctl = NULL;
> +			tmp = readw(host->regs + NFC_CONFIG1);
> +			tmp &= ~NFC_ECC_EN;
> +			writew(tmp, host->regs + NFC_CONFIG1);
> +			break;
> +		}
> +	}
> +
> +	/* second phase scan */
> +	if (nand_scan_tail(mtd)) {
>  		err = -ENXIO;
>  		goto escan;
>  	}

Hi Vladimir! Very thanks for your patch! This and setting correct value of NFMS bit, solve the problem!

Alberto!
Artem Bityutskiy - May 25, 2009, 1:29 p.m.
On Mon, 2009-05-25 at 13:06 +0400, Vladimir Barinov wrote:
> - Add support for 2k page size flashes
> - Fix page address access for large pages
> - Detect oob layout at runtime
> - handle pagesize_2k variable
> - Fix oob16 layout: reserve location 5 of oob area since it's used for bbt
> ---
>  drivers/mtd/nand/mxc_nand.c |   60 ++++++++++++++++++++++++++++++++++++------
>  1 files changed, 51 insertions(+), 9 deletions(-)

I've added this to my git tree. You did not provide your signature,
but I assume you have just forgotten about this and have added it for
you:

Signed-off-by: Vladimir Barinov <vova.barinov@gmail.com>
Vladimir Barinov - May 25, 2009, 3:02 p.m.
Artem Bityutskiy wrote:
> On Mon, 2009-05-25 at 13:06 +0400, Vladimir Barinov wrote:
>   
>> - Add support for 2k page size flashes
>> - Fix page address access for large pages
>> - Detect oob layout at runtime
>> - handle pagesize_2k variable
>> - Fix oob16 layout: reserve location 5 of oob area since it's used for bbt
>> ---
>>  drivers/mtd/nand/mxc_nand.c |   60 ++++++++++++++++++++++++++++++++++++------
>>  1 files changed, 51 insertions(+), 9 deletions(-)
>>     
>
> I've added this to my git tree. You did not provide your signature,
> but I assume you have just forgotten about this and have added it for
> you:
>
> Signed-off-by: Vladimir Barinov <vova.barinov@gmail.com>
>   
Oops, sorry for that

Patch

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index f3548d0..5ab8985 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -138,7 +138,14 @@  static struct nand_ecclayout nand_hw_eccoob_8 = {
 static struct nand_ecclayout nand_hw_eccoob_16 = {
 	.eccbytes = 5,
 	.eccpos = {6, 7, 8, 9, 10},
-	.oobfree = {{0, 6}, {12, 4}, }
+	.oobfree = {{0, 5}, {11, 5}, }
+};
+
+static struct nand_ecclayout nand_hw_eccoob_64 = {
+	.eccbytes = 20,
+	.eccpos = {6, 7, 8, 9, 10, 22, 23, 24, 25, 26,
+		   38, 39, 40, 41, 42, 54, 55, 56, 57, 58},
+	.oobfree = {{2, 4}, {11, 10}, {27, 10}, {43, 10}, {59, 5}, }
 };
 
 #ifdef CONFIG_MTD_PARTITIONS
@@ -795,9 +802,13 @@  static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
 		send_addr(host, (page_addr & 0xff), false);
 
 		if (host->pagesize_2k) {
-			send_addr(host, (page_addr >> 8) & 0xFF, false);
-			if (mtd->size >= 0x40000000)
+			if (mtd->size >= 0x10000000) {
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff, false);
 				send_addr(host, (page_addr >> 16) & 0xff, true);
+			} else
+				/* paddr_8 - paddr_15 */
+				send_addr(host, (page_addr >> 8) & 0xff, true);
 		} else {
 			/* One more address cycle for higher density devices */
 			if (mtd->size >= 0x4000000) {
@@ -919,7 +930,6 @@  static int __init mxcnd_probe(struct platform_device *pdev)
 		this->ecc.mode = NAND_ECC_HW;
 		this->ecc.size = 512;
 		this->ecc.bytes = 3;
-		this->ecc.layout = &nand_hw_eccoob_8;
 		tmp = readw(host->regs + NFC_CONFIG1);
 		tmp |= NFC_ECC_EN;
 		writew(tmp, host->regs + NFC_CONFIG1);
@@ -953,12 +963,44 @@  static int __init mxcnd_probe(struct platform_device *pdev)
 		this->ecc.layout = &nand_hw_eccoob_16;
 	}
 
-	host->pagesize_2k = 0;
+	/* first scan to find the device and get the page size */
+	if (nand_scan_ident(mtd, 1)) {
+		err = -ENXIO;
+		goto escan;
+	}
 
-	/* Scan to find existence of the device */
-	if (nand_scan(mtd, 1)) {
-		DEBUG(MTD_DEBUG_LEVEL0,
-		      "MXC_ND: Unable to find any NAND device.\n");
+	host->pagesize_2k = (mtd->writesize == 2048) ? 1 : 0;
+
+	if (this->ecc.mode == NAND_ECC_HW) {
+		switch (mtd->oobsize) {
+		case 8:
+			this->ecc.layout = &nand_hw_eccoob_8;
+			break;
+		case 16:
+			this->ecc.layout = &nand_hw_eccoob_16;
+			break;
+		case 64:
+			this->ecc.layout = &nand_hw_eccoob_64;
+			break;
+		default:
+			/* page size not handled by HW ECC */
+			/* switching back to soft ECC */
+			this->ecc.size = 512;
+			this->ecc.bytes = 3;
+			this->ecc.layout = &nand_hw_eccoob_8;
+			this->ecc.mode = NAND_ECC_SOFT;
+			this->ecc.calculate = NULL;
+			this->ecc.correct = NULL;
+			this->ecc.hwctl = NULL;
+			tmp = readw(host->regs + NFC_CONFIG1);
+			tmp &= ~NFC_ECC_EN;
+			writew(tmp, host->regs + NFC_CONFIG1);
+			break;
+		}
+	}
+
+	/* second phase scan */
+	if (nand_scan_tail(mtd)) {
 		err = -ENXIO;
 		goto escan;
 	}