Commit 44299179 authored by Barry Song's avatar Barry Song Committed by David Woodhouse

mtd: Blackfin NFC: fix handling of page sizes

Rather than forcing the platform resources to declare the desired page
size, simply use the existing information passed down to us by the higher
layers.  This way we work out of the box with all flash chips that the
kernel knows about.
Signed-off-by: default avatarBarry Song <barry.song@analog.com>
Signed-off-by: default avatarMike Frysinger <vapier@gentoo.org>
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent 752b957a
...@@ -15,8 +15,6 @@ ...@@ -15,8 +15,6 @@
* partitions = mtd partition list * partitions = mtd partition list
*/ */
#define NFC_PG_SIZE_256 0
#define NFC_PG_SIZE_512 1
#define NFC_PG_SIZE_OFFSET 9 #define NFC_PG_SIZE_OFFSET 9
#define NFC_NWIDTH_8 0 #define NFC_NWIDTH_8 0
...@@ -30,7 +28,6 @@ ...@@ -30,7 +28,6 @@
struct bf5xx_nand_platform { struct bf5xx_nand_platform {
/* NAND chip information */ /* NAND chip information */
unsigned short page_size;
unsigned short data_width; unsigned short data_width;
/* RD/WR strobe delay timing information, all times in SCLK cycles */ /* RD/WR strobe delay timing information, all times in SCLK cycles */
......
...@@ -314,18 +314,16 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat, ...@@ -314,18 +314,16 @@ static int bf5xx_nand_correct_data_256(struct mtd_info *mtd, u_char *dat,
static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat, static int bf5xx_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc) u_char *read_ecc, u_char *calc_ecc)
{ {
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); struct nand_chip *chip = mtd->priv;
struct bf5xx_nand_platform *plat = info->platform;
unsigned short page_size = (plat->page_size ? 512 : 256);
int ret; int ret;
ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); ret = bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
/* If page size is 512, correct second 256 bytes */ /* If ecc size is 512, correct second 256 bytes */
if (page_size == 512) { if (chip->ecc.size == 512) {
dat += 256; dat += 256;
read_ecc += 8; read_ecc += 3;
calc_ecc += 8; calc_ecc += 3;
ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc); ret |= bf5xx_nand_correct_data_256(mtd, dat, read_ecc, calc_ecc);
} }
...@@ -341,13 +339,12 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd, ...@@ -341,13 +339,12 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
const u_char *dat, u_char *ecc_code) const u_char *dat, u_char *ecc_code)
{ {
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
struct bf5xx_nand_platform *plat = info->platform; struct nand_chip *chip = mtd->priv;
u16 page_size = (plat->page_size ? 512 : 256);
u16 ecc0, ecc1; u16 ecc0, ecc1;
u32 code[2]; u32 code[2];
u8 *p; u8 *p;
/* first 4 bytes ECC code for 256 page size */ /* first 3 bytes ECC code for 256 page size */
ecc0 = bfin_read_NFC_ECC0(); ecc0 = bfin_read_NFC_ECC0();
ecc1 = bfin_read_NFC_ECC1(); ecc1 = bfin_read_NFC_ECC1();
...@@ -355,12 +352,11 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd, ...@@ -355,12 +352,11 @@ static int bf5xx_nand_calculate_ecc(struct mtd_info *mtd,
dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]); dev_dbg(info->device, "returning ecc 0x%08x\n", code[0]);
/* first 3 bytes in ecc_code for 256 page size */
p = (u8 *) code; p = (u8 *) code;
memcpy(ecc_code, p, 3); memcpy(ecc_code, p, 3);
/* second 4 bytes ECC code for 512 page size */ /* second 3 bytes ECC code for 512 ecc size */
if (page_size == 512) { if (chip->ecc.size == 512) {
ecc0 = bfin_read_NFC_ECC2(); ecc0 = bfin_read_NFC_ECC2();
ecc1 = bfin_read_NFC_ECC3(); ecc1 = bfin_read_NFC_ECC3();
code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11); code[1] = (ecc0 & 0x7ff) | ((ecc1 & 0x7ff) << 11);
...@@ -480,8 +476,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, ...@@ -480,8 +476,7 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
uint8_t *buf, int is_read) uint8_t *buf, int is_read)
{ {
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
struct bf5xx_nand_platform *plat = info->platform; struct nand_chip *chip = mtd->priv;
unsigned short page_size = (plat->page_size ? 512 : 256);
unsigned short val; unsigned short val;
dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n", dev_dbg(info->device, " mtd->%p, buf->%p, is_read %d\n",
...@@ -495,10 +490,10 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, ...@@ -495,10 +490,10 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
*/ */
if (is_read) if (is_read)
invalidate_dcache_range((unsigned int)buf, invalidate_dcache_range((unsigned int)buf,
(unsigned int)(buf + page_size)); (unsigned int)(buf + chip->ecc.size));
else else
flush_dcache_range((unsigned int)buf, flush_dcache_range((unsigned int)buf,
(unsigned int)(buf + page_size)); (unsigned int)(buf + chip->ecc.size));
/* /*
* This register must be written before each page is * This register must be written before each page is
...@@ -519,13 +514,13 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd, ...@@ -519,13 +514,13 @@ static void bf5xx_nand_dma_rw(struct mtd_info *mtd,
/* The DMAs have different size on BF52x and BF54x */ /* The DMAs have different size on BF52x and BF54x */
#ifdef CONFIG_BF52x #ifdef CONFIG_BF52x
set_dma_x_count(CH_NFC, (page_size >> 1)); set_dma_x_count(CH_NFC, (chip->ecc.size >> 1));
set_dma_x_modify(CH_NFC, 2); set_dma_x_modify(CH_NFC, 2);
val = DI_EN | WDSIZE_16; val = DI_EN | WDSIZE_16;
#endif #endif
#ifdef CONFIG_BF54x #ifdef CONFIG_BF54x
set_dma_x_count(CH_NFC, (page_size >> 2)); set_dma_x_count(CH_NFC, (chip->ecc.size >> 2));
set_dma_x_modify(CH_NFC, 4); set_dma_x_modify(CH_NFC, 4);
val = DI_EN | WDSIZE_32; val = DI_EN | WDSIZE_32;
#endif #endif
...@@ -547,12 +542,11 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd, ...@@ -547,12 +542,11 @@ static void bf5xx_nand_dma_read_buf(struct mtd_info *mtd,
uint8_t *buf, int len) uint8_t *buf, int len)
{ {
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
struct bf5xx_nand_platform *plat = info->platform; struct nand_chip *chip = mtd->priv;
unsigned short page_size = (plat->page_size ? 512 : 256);
dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len); dev_dbg(info->device, "mtd->%p, buf->%p, int %d\n", mtd, buf, len);
if (len == page_size) if (len == chip->ecc.size)
bf5xx_nand_dma_rw(mtd, buf, 1); bf5xx_nand_dma_rw(mtd, buf, 1);
else else
bf5xx_nand_read_buf(mtd, buf, len); bf5xx_nand_read_buf(mtd, buf, len);
...@@ -562,12 +556,11 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd, ...@@ -562,12 +556,11 @@ static void bf5xx_nand_dma_write_buf(struct mtd_info *mtd,
const uint8_t *buf, int len) const uint8_t *buf, int len)
{ {
struct bf5xx_nand_info *info = mtd_to_nand_info(mtd); struct bf5xx_nand_info *info = mtd_to_nand_info(mtd);
struct bf5xx_nand_platform *plat = info->platform; struct nand_chip *chip = mtd->priv;
unsigned short page_size = (plat->page_size ? 512 : 256);
dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len); dev_dbg(info->device, "mtd->%p, buf->%p, len %d\n", mtd, buf, len);
if (len == page_size) if (len == chip->ecc.size)
bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0); bf5xx_nand_dma_rw(mtd, (uint8_t *)buf, 0);
else else
bf5xx_nand_write_buf(mtd, buf, len); bf5xx_nand_write_buf(mtd, buf, len);
...@@ -642,12 +635,11 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info) ...@@ -642,12 +635,11 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info)
/* setup NFC_CTL register */ /* setup NFC_CTL register */
dev_info(info->device, dev_info(info->device,
"page_size=%d, data_width=%d, wr_dly=%d, rd_dly=%d\n", "data_width=%d, wr_dly=%d, rd_dly=%d\n",
(plat->page_size ? 512 : 256),
(plat->data_width ? 16 : 8), (plat->data_width ? 16 : 8),
plat->wr_dly, plat->rd_dly); plat->wr_dly, plat->rd_dly);
val = (plat->page_size << NFC_PG_SIZE_OFFSET) | val = (1 << NFC_PG_SIZE_OFFSET) |
(plat->data_width << NFC_NWIDTH_OFFSET) | (plat->data_width << NFC_NWIDTH_OFFSET) |
(plat->rd_dly << NFC_RDDLY_OFFSET) | (plat->rd_dly << NFC_RDDLY_OFFSET) |
(plat->wr_dly << NFC_WRDLY_OFFSET); (plat->wr_dly << NFC_WRDLY_OFFSET);
...@@ -713,6 +705,33 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev) ...@@ -713,6 +705,33 @@ static int __devexit bf5xx_nand_remove(struct platform_device *pdev)
return 0; return 0;
} }
static int bf5xx_nand_scan(struct mtd_info *mtd)
{
struct nand_chip *chip = mtd->priv;
int ret;
ret = nand_scan_ident(mtd, 1);
if (ret)
return ret;
if (hardware_ecc) {
/*
* for nand with page size > 512B, think it as several sections with 512B
*/
if (likely(mtd->writesize >= 512)) {
chip->ecc.size = 512;
chip->ecc.bytes = 6;
} else {
chip->ecc.size = 256;
chip->ecc.bytes = 3;
bfin_write_NFC_CTL(bfin_read_NFC_CTL() & ~(1 << NFC_PG_SIZE_OFFSET));
SSYNC();
}
}
return nand_scan_tail(mtd);
}
/* /*
* bf5xx_nand_probe * bf5xx_nand_probe
* *
...@@ -798,15 +817,6 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) ...@@ -798,15 +817,6 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
chip->badblock_pattern = &bootrom_bbt; chip->badblock_pattern = &bootrom_bbt;
chip->ecc.layout = &bootrom_ecclayout; chip->ecc.layout = &bootrom_ecclayout;
#endif #endif
if (plat->page_size == NFC_PG_SIZE_256) {
chip->ecc.bytes = 3;
chip->ecc.size = 256;
} else if (plat->page_size == NFC_PG_SIZE_512) {
chip->ecc.bytes = 6;
chip->ecc.size = 512;
}
chip->read_buf = bf5xx_nand_dma_read_buf; chip->read_buf = bf5xx_nand_dma_read_buf;
chip->write_buf = bf5xx_nand_dma_write_buf; chip->write_buf = bf5xx_nand_dma_write_buf;
chip->ecc.calculate = bf5xx_nand_calculate_ecc; chip->ecc.calculate = bf5xx_nand_calculate_ecc;
...@@ -820,7 +830,7 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev) ...@@ -820,7 +830,7 @@ static int __devinit bf5xx_nand_probe(struct platform_device *pdev)
} }
/* scan hardware nand chip and setup mtd info data struct */ /* scan hardware nand chip and setup mtd info data struct */
if (nand_scan(mtd, 1)) { if (bf5xx_nand_scan(mtd)) {
err = -ENXIO; err = -ENXIO;
goto out_err_nand_scan; goto out_err_nand_scan;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment