diff options
Diffstat (limited to 'drivers/mtd/nand')
| -rw-r--r-- | drivers/mtd/nand/nand.c | 11 | ||||
| -rw-r--r-- | drivers/mtd/nand/nand_util.c | 3 | ||||
| -rw-r--r-- | drivers/mtd/nand/omap_gpmc.c | 54 |
3 files changed, 60 insertions, 8 deletions
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c index d987f4c85c8..8a623e84808 100644 --- a/drivers/mtd/nand/nand.c +++ b/drivers/mtd/nand/nand.c @@ -77,17 +77,22 @@ static void nand_init_chip(struct mtd_info *mtd, struct nand_chip *nand, } +unsigned int mtd_nand_size; +unsigned int nand_size(void) +{ + return mtd_nand_size; +} + void nand_init(void) { int i; - unsigned int size = 0; for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) { nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]); - size += nand_info[i].size / 1024; + mtd_nand_size += nand_info[i].size / 1024; if (nand_curr_device == -1) nand_curr_device = i; } - printf("%u MiB\n", size / 1024); + printf("%u MiB\n", mtd_nand_size / 1024); #ifdef CONFIG_SYS_NAND_SELECT_DEVICE /* diff --git a/drivers/mtd/nand/nand_util.c b/drivers/mtd/nand/nand_util.c index 82e661d39c9..c9f1283fa00 100644 --- a/drivers/mtd/nand/nand_util.c +++ b/drivers/mtd/nand/nand_util.c @@ -510,7 +510,8 @@ int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, return -EINVAL; } - if (!need_skip && !withoob) { + /* Write one page at a time since need to update percentage */ + if (0 && !need_skip && !withoob) { rval = nand_write (nand, offset, length, buffer); if (rval == 0) return 0; diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index d5ee9bc5836..1a636cad236 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -31,8 +31,49 @@ #include <linux/mtd/nand_ecc.h> #include <linux/mtd/nand_bch.h> #include <nand.h> +#include <asm/arch/dma.h> + static uint8_t cs; + +#ifdef CONFIG_OMAP_DMA +void omap_dma_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) +{ + int i; + struct nand_chip *chip = mtd->priv; + u16 *p = (u16 *) buf; + +// printf("%s: len %u\n", __FUNCTION__, len); + + + /* If request is too small, read it by hand */ + if (len <= 32) { + len >>= 1; + for (i = 0; i < len; i+=8) { + *p++ = readw(chip->IO_ADDR_R); + *p++ = readw(chip->IO_ADDR_R); + *p++ = readw(chip->IO_ADDR_R); + *p++ = readw(chip->IO_ADDR_R); + *p++ = readw(chip->IO_ADDR_R); + *p++ = readw(chip->IO_ADDR_R); + *p++ = readw(chip->IO_ADDR_R); + *p++ = readw(chip->IO_ADDR_R); + } + for (; i < len; ++i) + *p++ = readw(chip->IO_ADDR_R); + return; + } + + /* Invalidate the datacache for the buffer, program the DMA and wait + * for it to finish */ + invalidate_dcache_range((unsigned long)p, (unsigned long)(p + len)); + + + /* Transfer the data(and wait to complete) */ + omap3_dma_transfer(DMA_CHANNEL_NAND, chip->IO_ADDR_R, buf, len, FB_DMA_START | FB_DMA_WAIT); +} +#endif + static struct nand_ecclayout hw_nand_oob = GPMC_NAND_HW_ECC_LAYOUT; static struct nand_ecclayout chip_nand_oob = GPMC_NAND_CHIP_ECC_LAYOUT; @@ -282,7 +323,7 @@ int omap_nand_chip_has_ecc(void) if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[nand_curr_device].name) { - printf("Error: Can't switch ecc, no devices available\n"); + /* If no device, no in-chip ECC! */ return 0; } @@ -572,10 +613,8 @@ void omap_nand_switch_ecc(enum omap_nand_ecc_mode mode) if (nand_curr_device < 0 || nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE || - !nand_info[nand_curr_device].name) { - printf("Error: Can't switch ecc, no devices available\n"); + !nand_info[nand_curr_device].name) return; - } mtd = &nand_info[nand_curr_device]; nand = mtd->priv; @@ -664,6 +703,13 @@ void omap_nand_switch_ecc(enum omap_nand_ecc_mode mode) nand->ecc.hwctl = omap_enable_chip_hwecc; nand->ecc.correct = omap_correct_chip_hwecc; nand->ecc.read_oob = omap_read_oob_chipecc; +#ifdef CONFIG_OMAP_DMA + omap3_dma_channel_init(DMA_CHANNEL_NAND, -1, CSDP_DATA_TYPE_32BIT, CCR_SRC_AMODE_CONSTANT, CCR_DST_AMODE_POST_INC); + if (nand->options & NAND_BUSWIDTH_16) + nand->read_buf = omap_dma_read_buf16; + else + printf("%s: Huh? not 16-bit for DMA\n", __FUNCTION__); +#endif nand->ecc.mode = NAND_ECC_CHIP; /* internal to chip */ nand->ecc.layout = &chip_nand_oob; if (nand->options & NAND_BUSWIDTH_16) |
