Skip to content

Commit 43bcfd2

Browse files
ezequielgarciacomputersforpeace
authored andcommitted
mtd: nand: pxa3xx: Add driver-specific ECC BCH support
This commit adds the BCH ECC support available in NFCv2 controller. Depending on the detected required strength the respective ECC layout is selected. This commit adds an empty ECC layout, since support to access large pages is first required. Once that support is added, a proper ECC layout will be added as well. Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> Tested-by: Daniel Mack <zonque@gmail.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
1 parent 776f265 commit 43bcfd2

File tree

1 file changed

+69
-17
lines changed

1 file changed

+69
-17
lines changed

drivers/mtd/nand/pxa3xx_nand.c

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#define NDPCR (0x18) /* Page Count Register */
5959
#define NDBDR0 (0x1C) /* Bad Block Register 0 */
6060
#define NDBDR1 (0x20) /* Bad Block Register 1 */
61+
#define NDECCCTRL (0x28) /* ECC control */
6162
#define NDDB (0x40) /* Data Buffer */
6263
#define NDCB0 (0x48) /* Command Buffer0 */
6364
#define NDCB1 (0x4C) /* Command Buffer1 */
@@ -198,13 +199,16 @@ struct pxa3xx_nand_info {
198199

199200
int cs;
200201
int use_ecc; /* use HW ECC ? */
202+
int ecc_bch; /* using BCH ECC? */
201203
int use_dma; /* use DMA ? */
202204
int use_spare; /* use spare ? */
203205
int need_wait;
204206

205207
unsigned int fifo_size; /* max. data size in the FIFO */
206208
unsigned int data_size; /* data to be read from FIFO */
207209
unsigned int oob_size;
210+
unsigned int spare_size;
211+
unsigned int ecc_size;
208212
int retcode;
209213

210214
/* cached register value */
@@ -335,19 +339,12 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
335339
int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
336340

337341
info->data_size = info->fifo_size;
338-
if (!oob_enable) {
339-
info->oob_size = 0;
342+
if (!oob_enable)
340343
return;
341-
}
342344

343-
switch (info->fifo_size) {
344-
case 2048:
345-
info->oob_size = (info->use_ecc) ? 40 : 64;
346-
break;
347-
case 512:
348-
info->oob_size = (info->use_ecc) ? 8 : 16;
349-
break;
350-
}
345+
info->oob_size = info->spare_size;
346+
if (!info->use_ecc)
347+
info->oob_size += info->ecc_size;
351348
}
352349

353350
/**
@@ -362,10 +359,15 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
362359

363360
ndcr = info->reg_ndcr;
364361

365-
if (info->use_ecc)
362+
if (info->use_ecc) {
366363
ndcr |= NDCR_ECC_EN;
367-
else
364+
if (info->ecc_bch)
365+
nand_writel(info, NDECCCTRL, 0x1);
366+
} else {
368367
ndcr &= ~NDCR_ECC_EN;
368+
if (info->ecc_bch)
369+
nand_writel(info, NDECCCTRL, 0x0);
370+
}
369371

370372
if (info->use_dma)
371373
ndcr |= NDCR_DMA_EN;
@@ -1067,6 +1069,41 @@ static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
10671069
return 0;
10681070
}
10691071

1072+
static int pxa_ecc_init(struct pxa3xx_nand_info *info,
1073+
struct nand_ecc_ctrl *ecc,
1074+
int strength, int page_size)
1075+
{
1076+
/*
1077+
* We don't use strength here as the PXA variant
1078+
* is used with non-ONFI compliant devices.
1079+
*/
1080+
if (page_size == 2048) {
1081+
info->spare_size = 40;
1082+
info->ecc_size = 24;
1083+
ecc->mode = NAND_ECC_HW;
1084+
ecc->size = 512;
1085+
ecc->strength = 1;
1086+
return 1;
1087+
1088+
} else if (page_size == 512) {
1089+
info->spare_size = 8;
1090+
info->ecc_size = 8;
1091+
ecc->mode = NAND_ECC_HW;
1092+
ecc->size = 512;
1093+
ecc->strength = 1;
1094+
return 1;
1095+
}
1096+
return 0;
1097+
}
1098+
1099+
static int armada370_ecc_init(struct pxa3xx_nand_info *info,
1100+
struct nand_ecc_ctrl *ecc,
1101+
int strength, int page_size)
1102+
{
1103+
/* Unimplemented yet */
1104+
return 0;
1105+
}
1106+
10701107
static int pxa3xx_nand_scan(struct mtd_info *mtd)
10711108
{
10721109
struct pxa3xx_nand_host *host = mtd->priv;
@@ -1137,13 +1174,13 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
11371174
pxa3xx_flash_ids[1].name = NULL;
11381175
def = pxa3xx_flash_ids;
11391176
KEEP_CONFIG:
1140-
chip->ecc.mode = NAND_ECC_HW;
1141-
chip->ecc.size = info->fifo_size;
1142-
chip->ecc.strength = 1;
1143-
11441177
if (info->reg_ndcr & NDCR_DWIDTH_M)
11451178
chip->options |= NAND_BUSWIDTH_16;
11461179

1180+
/* Device detection must be done with ECC disabled */
1181+
if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
1182+
nand_writel(info, NDECCCTRL, 0x0);
1183+
11471184
if (nand_scan_ident(mtd, 1, def))
11481185
return -ENODEV;
11491186

@@ -1158,6 +1195,21 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
11581195
chip->bbt_md = &bbt_mirror_descr;
11591196
}
11601197

1198+
if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370)
1199+
ret = armada370_ecc_init(info, &chip->ecc,
1200+
chip->ecc_strength_ds,
1201+
mtd->writesize);
1202+
else
1203+
ret = pxa_ecc_init(info, &chip->ecc,
1204+
chip->ecc_strength_ds,
1205+
mtd->writesize);
1206+
if (!ret) {
1207+
dev_err(&info->pdev->dev,
1208+
"ECC strength %d at page size %d is not supported\n",
1209+
chip->ecc_strength_ds, mtd->writesize);
1210+
return -ENODEV;
1211+
}
1212+
11611213
/* calculate addressing information */
11621214
if (mtd->writesize >= 2048)
11631215
host->col_addr_cycles = 2;

0 commit comments

Comments
 (0)