diff options
author | Justin Waters <justin.waters@timesys.com> | 2013-04-24 17:38:39 -0400 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2013-04-24 17:38:39 -0400 |
commit | 75c641ece39c136001340df61f0ad57028ce4ffc (patch) | |
tree | e5f2c5f5764770a34d0e39b5eace575fd4751527 /drivers/mtd/nand/omap_gpmc.c | |
parent | 1341f103ac87882633b019a5a137056818234248 (diff) |
LogicPD Support for OMAP3/DM3/AM3 boards 2.1 Update
Diffstat (limited to 'drivers/mtd/nand/omap_gpmc.c')
-rw-r--r-- | drivers/mtd/nand/omap_gpmc.c | 54 |
1 files changed, 50 insertions, 4 deletions
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) |