Эх сурвалжийг харах

mtd: atmel_nand: Support 32-bit ECC strength

As the SAMA5D2 controller supports the 32-bit ECC strength, accept it
as a valid setting when required by the device tree or the NAND
parameter page.

Then configure the controller to use this new setting.

For the binding:
Acked-by: Rob Herring <robh@kernel.org>

Signed-off-by: Romain Izard <romain.izard.pro@gmail.com>
Tested-by: Wenyou Yang <wenyou.yang@atmel.com>
Reviewed-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Romain Izard 9 жил өмнө
parent
commit
94248462f0

+ 2 - 1
Documentation/devicetree/bindings/mtd/atmel-nand.txt

@@ -27,7 +27,8 @@ Optional properties:
 - atmel,has-pmecc : boolean to enable Programmable Multibit ECC hardware,
 - atmel,has-pmecc : boolean to enable Programmable Multibit ECC hardware,
   capable of BCH encoding and decoding, on devices where it is present.
   capable of BCH encoding and decoding, on devices where it is present.
 - atmel,pmecc-cap : error correct capability for Programmable Multibit ECC
 - atmel,pmecc-cap : error correct capability for Programmable Multibit ECC
-  Controller. Supported values are: 2, 4, 8, 12, 24.
+  Controller. Supported values are: 2, 4, 8, 12, 24. If the compatible string
+  is "atmel,sama5d2-nand", 32 is also valid.
 - atmel,pmecc-sector-size : sector size for ECC computation. Supported values
 - atmel,pmecc-sector-size : sector size for ECC computation. Supported values
   are: 512, 1024.
   are: 512, 1024.
 - atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM
 - atmel,pmecc-lookup-table-offset : includes two offsets of lookup table in ROM

+ 17 - 2
drivers/mtd/nand/atmel_nand.c

@@ -475,6 +475,7 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
  *                8-bits                13-bytes                 14-bytes
  *                8-bits                13-bytes                 14-bytes
  *               12-bits                20-bytes                 21-bytes
  *               12-bits                20-bytes                 21-bytes
  *               24-bits                39-bytes                 42-bytes
  *               24-bits                39-bytes                 42-bytes
+ *               32-bits                52-bytes                 56-bytes
  */
  */
 static int pmecc_get_ecc_bytes(int cap, int sector_size)
 static int pmecc_get_ecc_bytes(int cap, int sector_size)
 {
 {
@@ -1024,6 +1025,9 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd)
 	case 24:
 	case 24:
 		val = PMECC_CFG_BCH_ERR24;
 		val = PMECC_CFG_BCH_ERR24;
 		break;
 		break;
+	case 32:
+		val = PMECC_CFG_BCH_ERR32;
+		break;
 	}
 	}
 
 
 	if (host->pmecc_sector_size == 512)
 	if (host->pmecc_sector_size == 512)
@@ -1085,6 +1089,9 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
 
 
 	/* If device tree doesn't specify, use NAND's minimum ECC parameters */
 	/* If device tree doesn't specify, use NAND's minimum ECC parameters */
 	if (host->pmecc_corr_cap == 0) {
 	if (host->pmecc_corr_cap == 0) {
+		if (*cap > host->caps->pmecc_max_correction)
+			return -EINVAL;
+
 		/* use the most fitable ecc bits (the near bigger one ) */
 		/* use the most fitable ecc bits (the near bigger one ) */
 		if (*cap <= 2)
 		if (*cap <= 2)
 			host->pmecc_corr_cap = 2;
 			host->pmecc_corr_cap = 2;
@@ -1096,6 +1103,8 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host,
 			host->pmecc_corr_cap = 12;
 			host->pmecc_corr_cap = 12;
 		else if (*cap <= 24)
 		else if (*cap <= 24)
 			host->pmecc_corr_cap = 24;
 			host->pmecc_corr_cap = 24;
+		else if (*cap <= 32)
+			host->pmecc_corr_cap = 32;
 		else
 		else
 			return -EINVAL;
 			return -EINVAL;
 	}
 	}
@@ -1554,8 +1563,14 @@ static int atmel_of_init_port(struct atmel_nand_host *host,
 	 * them from NAND ONFI parameters.
 	 * them from NAND ONFI parameters.
 	 */
 	 */
 	if (of_property_read_u32(np, "atmel,pmecc-cap", &val) == 0) {
 	if (of_property_read_u32(np, "atmel,pmecc-cap", &val) == 0) {
-		if ((val != 2) && (val != 4) && (val != 8) && (val != 12) &&
-				(val != 24)) {
+		if (val > host->caps->pmecc_max_correction) {
+			dev_err(host->dev,
+				"Required ECC strength too high: %u max %u\n",
+				val, host->caps->pmecc_max_correction);
+			return -EINVAL;
+		}
+		if ((val != 2)  && (val != 4)  && (val != 8) &&
+		    (val != 12) && (val != 24) && (val != 32)) {
 			dev_err(host->dev,
 			dev_err(host->dev,
 				"Required ECC strength not supported: %u\n",
 				"Required ECC strength not supported: %u\n",
 				val);
 				val);

+ 1 - 0
drivers/mtd/nand/atmel_nand_ecc.h

@@ -43,6 +43,7 @@
 #define		PMECC_CFG_BCH_ERR8		(2 << 0)
 #define		PMECC_CFG_BCH_ERR8		(2 << 0)
 #define		PMECC_CFG_BCH_ERR12		(3 << 0)
 #define		PMECC_CFG_BCH_ERR12		(3 << 0)
 #define		PMECC_CFG_BCH_ERR24		(4 << 0)
 #define		PMECC_CFG_BCH_ERR24		(4 << 0)
+#define		PMECC_CFG_BCH_ERR32		(5 << 0)
 
 
 #define		PMECC_CFG_SECTOR512		(0 << 4)
 #define		PMECC_CFG_SECTOR512		(0 << 4)
 #define		PMECC_CFG_SECTOR1024		(1 << 4)
 #define		PMECC_CFG_SECTOR1024		(1 << 4)