From patchwork Sat May 30 08:11:23 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeroen Hofstee X-Patchwork-Id: 478427 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 361CC140FD7 for ; Sat, 30 May 2015 18:20:43 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 583E54B68A; Sat, 30 May 2015 10:20:31 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 499fCrLleJXb; Sat, 30 May 2015 10:20:31 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0350C4B663; Sat, 30 May 2015 10:20:18 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B0CB74B62A for ; Sat, 30 May 2015 10:20:07 +0200 (CEST) Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id n6A098jVjbxk for ; Sat, 30 May 2015 10:20:07 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from orange.myspectrum.nl (orange.myspectrum.nl [149.210.134.247]) by theia.denx.de (Postfix) with ESMTP id 4A66C4B62B for ; Sat, 30 May 2015 10:20:03 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by orange.myspectrum.nl (Postfix) with ESMTP id D0859909CA; Sat, 30 May 2015 10:11:39 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at myspectrum.nl Received: from orange.myspectrum.nl ([127.0.0.1]) by localhost (orange.myspectrum.nl [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id RKhNJDWuc1d5; Sat, 30 May 2015 10:11:37 +0200 (CEST) Received: from router.myspectrum.nl (5ED6B7F1.cm-7-7c.dynamic.ziggo.nl [94.214.183.241]) (Authenticated sender: jeroen@myspectrum.nl) by orange.myspectrum.nl (Postfix) with ESMTPSA id 21060909C3; Sat, 30 May 2015 10:11:37 +0200 (CEST) Received: from black (unknown [10.0.0.117]) by router.myspectrum.nl (Postfix) with SMTP id 8F9011BE1D; Sat, 30 May 2015 10:11:35 +0200 (CEST) Received: (nullmailer pid 4076 invoked by uid 1000); Sat, 30 May 2015 08:11:35 -0000 From: Jeroen Hofstee To: u-boot@lists.denx.de Date: Sat, 30 May 2015 10:11:23 +0200 Message-Id: <1432973485-4030-2-git-send-email-jeroen@myspectrum.nl> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1432973485-4030-1-git-send-email-jeroen@myspectrum.nl> References: <1432973485-4030-1-git-send-email-jeroen@myspectrum.nl> Cc: Scott Wood , Tom Rini , Jeroen Hofstee , Daniel Mack Subject: [U-Boot] [PATCH 1/3] omap_gpmc: move prefetch out of CONFIG_NAND_OMAP_ELM X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" 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 Cc: Tom Rini Cc: Daniel Mack Signed-off-by: Jeroen Hofstee Reviewed-by: Tom Rini --- 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