omap_gpmc: move prefetch out of CONFIG_NAND_OMAP_ELM
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>
This commit is contained in:
parent
24e7412696
commit
c07361145f
drivers/mtd/nand
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue