[U-Boot] [PATCH 0/3] nand, gpmc: support 16nand prefetch mode

This patchset enables the gpmc prefetch mode for 16bit addressed nand and enables it for tam3517 derived boards.
Jeroen Hofstee (3): omap_gpmc: move prefetch out of CONFIG_NAND_OMAP_ELM mtd: OMAP: Enable GPMC prefetch mode for 16 bit access boards: tam3517-common: enable gpmc prefetch mode
drivers/mtd/nand/omap_gpmc.c | 236 ++++++++++++++++++++------------------- include/configs/tam3517-common.h | 1 + 2 files changed, 123 insertions(+), 114 deletions(-)

The prefech mode is a feature of the gpmc, not the ELM. An am3517 does not have an elm, but can do prefeches, so move the code out of the CONFIG_NAND_OMAP_ELM ifdef.
Cc: Scott Wood scottwood@freescale.com Cc: Tom Rini trini@konsulko.com Cc: Daniel Mack zonque@gmail.com
Signed-off-by: Jeroen Hofstee jeroen@myspectrum.nl --- drivers/mtd/nand/omap_gpmc.c | 218 +++++++++++++++++++++---------------------- 1 file changed, 109 insertions(+), 109 deletions(-)
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index 610f969..de90d55 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -340,6 +340,115 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat, return 0; }
+#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH + +#define PREFETCH_CONFIG1_CS_SHIFT 24 +#define PREFETCH_FIFOTHRESHOLD_MAX 0x40 +#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8) +#define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) +#define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F) +#define ENABLE_PREFETCH (1 << 7) + +/** + * omap_prefetch_enable - configures and starts prefetch transfer + * @fifo_th: fifo threshold to be used for read/ write + * @count: number of bytes to be transferred + * @is_write: prefetch read(0) or write post(1) mode + * @cs: chip select to use + */ +static int omap_prefetch_enable(int fifo_th, unsigned int count, int is_write, int cs) +{ + uint32_t val; + + if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) + return -EINVAL; + + if (readl(&gpmc_cfg->prefetch_control)) + return -EBUSY; + + /* Set the amount of bytes to be prefetched */ + writel(count, &gpmc_cfg->prefetch_config2); + + val = (cs << PREFETCH_CONFIG1_CS_SHIFT) | (is_write & 1) | + PREFETCH_FIFOTHRESHOLD(fifo_th) | ENABLE_PREFETCH; + writel(val, &gpmc_cfg->prefetch_config1); + + /* Start the prefetch engine */ + writel(1, &gpmc_cfg->prefetch_control); + + return 0; +} + +/** + * omap_prefetch_reset - disables and stops the prefetch engine + */ +static void omap_prefetch_reset(void) +{ + writel(0, &gpmc_cfg->prefetch_control); + writel(0, &gpmc_cfg->prefetch_config1); +} + +static int __read_prefetch_aligned(struct nand_chip *chip, uint32_t *buf, int len) +{ + int ret; + uint32_t cnt; + struct omap_nand_info *info = chip->priv; + + ret = omap_prefetch_enable(PREFETCH_FIFOTHRESHOLD_MAX, len, 0, info->cs); + if (ret < 0) + return ret; + + do { + int i; + + cnt = readl(&gpmc_cfg->prefetch_status); + cnt = PREFETCH_STATUS_FIFO_CNT(cnt); + + for (i = 0; i < cnt / 4; i++) { + *buf++ = readl(CONFIG_SYS_NAND_BASE); + len -= 4; + } + } while (len); + + omap_prefetch_reset(); + + return 0; +} + +static void omap_nand_read_prefetch8(struct mtd_info *mtd, uint8_t *buf, int len) +{ + int ret; + uint32_t head, tail; + struct nand_chip *chip = mtd->priv; + + /* + * If the destination buffer is unaligned, start with reading + * the overlap byte-wise. + */ + head = ((uint32_t) buf) % 4; + if (head) { + nand_read_buf(mtd, buf, head); + buf += head; + len -= head; + } + + /* + * Only transfer multiples of 4 bytes in a pre-fetched fashion. + * If there's a residue, care for it byte-wise afterwards. + */ + tail = len % 4; + + ret = __read_prefetch_aligned(chip, (uint32_t *) buf, len - tail); + if (ret < 0) { + /* fallback in case the prefetch engine is busy */ + nand_read_buf(mtd, buf, len); + } else if (tail) { + buf += len - tail; + nand_read_buf(mtd, buf, tail); + } +} +#endif /* CONFIG_NAND_OMAP_GPMC_PREFETCH */ + #ifdef CONFIG_NAND_OMAP_ELM /* * omap_reverse_list - re-orders list elements in reverse order [internal] @@ -452,115 +561,6 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat, return (err) ? err : error_count; }
-#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH - -#define PREFETCH_CONFIG1_CS_SHIFT 24 -#define PREFETCH_FIFOTHRESHOLD_MAX 0x40 -#define PREFETCH_FIFOTHRESHOLD(val) ((val) << 8) -#define PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) -#define PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F) -#define ENABLE_PREFETCH (1 << 7) - -/** - * omap_prefetch_enable - configures and starts prefetch transfer - * @fifo_th: fifo threshold to be used for read/ write - * @count: number of bytes to be transferred - * @is_write: prefetch read(0) or write post(1) mode - * @cs: chip select to use - */ -static int omap_prefetch_enable(int fifo_th, unsigned int count, int is_write, int cs) -{ - uint32_t val; - - if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) - return -EINVAL; - - if (readl(&gpmc_cfg->prefetch_control)) - return -EBUSY; - - /* Set the amount of bytes to be prefetched */ - writel(count, &gpmc_cfg->prefetch_config2); - - val = (cs << PREFETCH_CONFIG1_CS_SHIFT) | (is_write & 1) | - PREFETCH_FIFOTHRESHOLD(fifo_th) | ENABLE_PREFETCH; - writel(val, &gpmc_cfg->prefetch_config1); - - /* Start the prefetch engine */ - writel(1, &gpmc_cfg->prefetch_control); - - return 0; -} - -/** - * omap_prefetch_reset - disables and stops the prefetch engine - */ -static void omap_prefetch_reset(void) -{ - writel(0, &gpmc_cfg->prefetch_control); - writel(0, &gpmc_cfg->prefetch_config1); -} - -static int __read_prefetch_aligned(struct nand_chip *chip, uint32_t *buf, int len) -{ - int ret; - uint32_t cnt; - struct omap_nand_info *info = chip->priv; - - ret = omap_prefetch_enable(PREFETCH_FIFOTHRESHOLD_MAX, len, 0, info->cs); - if (ret < 0) - return ret; - - do { - int i; - - cnt = readl(&gpmc_cfg->prefetch_status); - cnt = PREFETCH_STATUS_FIFO_CNT(cnt); - - for (i = 0; i < cnt / 4; i++) { - *buf++ = readl(CONFIG_SYS_NAND_BASE); - len -= 4; - } - } while (len); - - omap_prefetch_reset(); - - return 0; -} - -static void omap_nand_read_prefetch8(struct mtd_info *mtd, uint8_t *buf, int len) -{ - int ret; - uint32_t head, tail; - struct nand_chip *chip = mtd->priv; - - /* - * If the destination buffer is unaligned, start with reading - * the overlap byte-wise. - */ - head = ((uint32_t) buf) % 4; - if (head) { - nand_read_buf(mtd, buf, head); - buf += head; - len -= head; - } - - /* - * Only transfer multiples of 4 bytes in a pre-fetched fashion. - * If there's a residue, care for it byte-wise afterwards. - */ - tail = len % 4; - - ret = __read_prefetch_aligned(chip, (uint32_t *) buf, len - tail); - if (ret < 0) { - /* fallback in case the prefetch engine is busy */ - nand_read_buf(mtd, buf, len); - } else if (tail) { - buf += len - tail; - nand_read_buf(mtd, buf, tail); - } -} -#endif /* CONFIG_NAND_OMAP_GPMC_PREFETCH */ - /** * omap_read_page_bch - hardware ecc based page read function * @mtd: mtd info structure

On Sat, May 30, 2015 at 10:11:23AM +0200, Jeroen Hofstee wrote:
The prefech mode is a feature of the gpmc, not the ELM. An am3517 does not have an elm, but can do prefeches, so move the code out of the CONFIG_NAND_OMAP_ELM ifdef.
Cc: Scott Wood scottwood@freescale.com Cc: Tom Rini trini@konsulko.com Cc: Daniel Mack zonque@gmail.com
Signed-off-by: Jeroen Hofstee jeroen@myspectrum.nl
Reviewed-by: Tom Rini trini@konsulko.com

On Sat, May 30, 2015 at 10:11:23AM +0200, Jeroen Hofstee wrote:
The prefech mode is a feature of the gpmc, not the ELM. An am3517 does not have an elm, but can do prefeches, so move the code out of the CONFIG_NAND_OMAP_ELM ifdef.
Cc: Scott Wood scottwood@freescale.com Cc: Tom Rini trini@konsulko.com Cc: Daniel Mack zonque@gmail.com
Signed-off-by: Jeroen Hofstee jeroen@myspectrum.nl Reviewed-by: Tom Rini trini@konsulko.com
Applied to u-boot/master, thanks!

commit c316f57 "mtd: OMAP: Enable GPMC prefetch mode" only enabled prefetch mode for 8 bit nand access, this adds 16 bit as well.
Cc: Scott Wood scottwood@freescale.com Cc: Tom Rini trini@konsulko.com Cc: Daniel Mack zonque@gmail.com
Signed-off-by: Jeroen Hofstee jeroen@myspectrum.nl --- drivers/mtd/nand/omap_gpmc.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index de90d55..4372988 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -415,7 +415,17 @@ static int __read_prefetch_aligned(struct nand_chip *chip, uint32_t *buf, int le return 0; }
-static void omap_nand_read_prefetch8(struct mtd_info *mtd, uint8_t *buf, int len) +static inline void omap_nand_read(struct mtd_info *mtd, uint8_t *buf, int len) +{ + struct nand_chip *chip = mtd->priv; + + if (chip->options & NAND_BUSWIDTH_16) + nand_read_buf16(mtd, buf, len); + else + nand_read_buf(mtd, buf, len); +} + +static void omap_nand_read_prefetch(struct mtd_info *mtd, uint8_t *buf, int len) { int ret; uint32_t head, tail; @@ -427,7 +437,7 @@ static void omap_nand_read_prefetch8(struct mtd_info *mtd, uint8_t *buf, int len */ head = ((uint32_t) buf) % 4; if (head) { - nand_read_buf(mtd, buf, head); + omap_nand_read(mtd, buf, head); buf += head; len -= head; } @@ -438,13 +448,13 @@ static void omap_nand_read_prefetch8(struct mtd_info *mtd, uint8_t *buf, int len */ tail = len % 4;
- ret = __read_prefetch_aligned(chip, (uint32_t *) buf, len - tail); + ret = __read_prefetch_aligned(chip, (uint32_t *)buf, len - tail); if (ret < 0) { /* fallback in case the prefetch engine is busy */ - nand_read_buf(mtd, buf, len); + omap_nand_read(mtd, buf, len); } else if (tail) { buf += len - tail; - nand_read_buf(mtd, buf, tail); + omap_nand_read(mtd, buf, tail); } } #endif /* CONFIG_NAND_OMAP_GPMC_PREFETCH */ @@ -1011,13 +1021,11 @@ int board_nand_init(struct nand_chip *nand) if (err) return err;
- /* TODO: Implement for 16-bit bus width */ - if (nand->options & NAND_BUSWIDTH_16) - nand->read_buf = nand_read_buf16; #ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH - else - nand->read_buf = omap_nand_read_prefetch8; + nand->read_buf = omap_nand_read_prefetch; #else + if (nand->options & NAND_BUSWIDTH_16) + nand->read_buf = nand_read_buf16; else nand->read_buf = nand_read_buf; #endif

On Sat, May 30, 2015 at 10:11:24AM +0200, Jeroen Hofstee wrote:
commit c316f57 "mtd: OMAP: Enable GPMC prefetch mode" only enabled prefetch mode for 8 bit nand access, this adds 16 bit as well.
Cc: Scott Wood scottwood@freescale.com Cc: Tom Rini trini@konsulko.com Cc: Daniel Mack zonque@gmail.com
Signed-off-by: Jeroen Hofstee jeroen@myspectrum.nl
Reviewed-by: Tom Rini trini@konsulko.com

On Sat, May 30, 2015 at 10:11:24AM +0200, Jeroen Hofstee wrote:
commit c316f57 "mtd: OMAP: Enable GPMC prefetch mode" only enabled prefetch mode for 8 bit nand access, this adds 16 bit as well.
Cc: Scott Wood scottwood@freescale.com Cc: Tom Rini trini@konsulko.com Cc: Daniel Mack zonque@gmail.com
Signed-off-by: Jeroen Hofstee jeroen@myspectrum.nl Reviewed-by: Tom Rini trini@konsulko.com
Applied to u-boot/master, thanks!

Since the tam3517 base board has a 16bit wide nand connected to the gpmc, enable the prefetch mode, since that is now supported.
Cc: Scott Wood scottwood@freescale.com Cc: Tom Rini trini@konsulko.com Cc: pekon gupta pekon@ti.com Cc: Nishanth Menon nm@ti.com Cc: Daniel Mack zonque@gmail.com Cc: Tapani Utriainen tapani@technexion.com
Signed-off-by: Jeroen Hofstee jeroen@myspectrum.nl --- include/configs/tam3517-common.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/include/configs/tam3517-common.h b/include/configs/tam3517-common.h index 2d12e86..169097f 100644 --- a/include/configs/tam3517-common.h +++ b/include/configs/tam3517-common.h @@ -261,6 +261,7 @@ #define CONFIG_SYS_NAND_ECCSIZE 256 #define CONFIG_SYS_NAND_ECCBYTES 3 #define CONFIG_NAND_OMAP_ECCSCHEME OMAP_ECC_HAM1_CODE_SW +#define CONFIG_NAND_OMAP_GPMC_PREFETCH
#define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE

On Sat, May 30, 2015 at 10:11:25AM +0200, Jeroen Hofstee wrote:
Since the tam3517 base board has a 16bit wide nand connected to the gpmc, enable the prefetch mode, since that is now supported.
Cc: Scott Wood scottwood@freescale.com Cc: Tom Rini trini@konsulko.com Cc: pekon gupta pekon@ti.com Cc: Nishanth Menon nm@ti.com Cc: Daniel Mack zonque@gmail.com Cc: Tapani Utriainen tapani@technexion.com
Signed-off-by: Jeroen Hofstee jeroen@myspectrum.nl
Reviewed-by: Tom Rini trini@konsulko.com

On Sat, May 30, 2015 at 10:11:25AM +0200, Jeroen Hofstee wrote:
Since the tam3517 base board has a 16bit wide nand connected to the gpmc, enable the prefetch mode, since that is now supported.
Cc: Scott Wood scottwood@freescale.com Cc: Tom Rini trini@konsulko.com Cc: pekon gupta pekon@ti.com Cc: Nishanth Menon nm@ti.com Cc: Daniel Mack zonque@gmail.com Cc: Tapani Utriainen tapani@technexion.com
Signed-off-by: Jeroen Hofstee jeroen@myspectrum.nl Reviewed-by: Tom Rini trini@konsulko.com
Applied to u-boot/master, thanks!
participants (2)
-
Jeroen Hofstee
-
Tom Rini