ipq40xx: Add SPI NAND support

Change-Id: I74de22fcea6455f73f263672b72b30b796f6c820
Signed-off-by: Rajkumar Ayyasamy <arajkuma@codeaurora.org>
This commit is contained in:
Rajkumar Ayyasamy 2017-12-27 13:02:55 +05:30
parent adaaa17195
commit f44fe93184
4 changed files with 69 additions and 26 deletions

View file

@ -135,6 +135,11 @@ void board_nand_init(void)
qca_gpio_init(gpio_node);
ipq_spi_init(CONFIG_IPQ_SPI_NOR_INFO_IDX);
}
#ifdef CONFIG_SPI_NAND
if (fdtdec_get_uint(gd->fdt_blob, 0, "spi_nand_available", 0))
spi_nand_init();
#endif
}
static void ipq40xx_edma_common_init(void)

View file

@ -16,3 +16,4 @@ obj-$(CONFIG_SPI_FLASH) += sf_probe.o spi_flash.o sf_params.o sf.o
obj-$(CONFIG_SPI_FLASH_DATAFLASH) += sf_dataflash.o
obj-$(CONFIG_SPI_FLASH_MTD) += sf_mtd.o
obj-$(CONFIG_SPI_FLASH_SANDBOX) += sandbox.o
obj-$(CONFIG_SPI_NAND) += spi_nand.o

View file

@ -957,6 +957,14 @@ int spi_flash_scan(struct spi_flash *flash)
}
if (!params->name) {
#ifdef CONFIG_SPI_NAND
ret = spi_nand_flash_probe(spi, flash, idcode);
if (!ret) {
flash->addr_width = flash->size > 0x1000000 ? 4 : 3;
goto print_sf_info;
}
#endif
printf("SF: Unsupported flash IDs: ");
printf("manuf %02x, jedec %04x, ext_jedec %04x\n",
idcode[0], jedec, ext_jedec);
@ -1120,6 +1128,7 @@ int spi_flash_scan(struct spi_flash *flash)
}
#endif
print_sf_info:
#ifndef CONFIG_SPL_BUILD
printf("SF: Detected %s with page size ", flash->name);
print_size(flash->page_size, ", erase size ");

View file

@ -16,9 +16,10 @@
#include <linux/mtd/nand.h>
#include <spi_flash.h>
#include <asm/errno.h>
#include "spi_flash_internal.h"
#include "spi_nand_dev.h"
#include <malloc.h>
#include "spi.h"
#include <watchdog.h>
#define CONFIG_SF_DEFAULT_SPEED (48 * 1000 * 1000)
#define TIMEOUT 5000
@ -172,6 +173,41 @@ void winbond_norm_read_cmd(u8 *cmd, int column)
cmd[3] = 0;
}
int spi_nand_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
u8 cmd, u8 poll_bit, u8 *status)
{
struct spi_slave *spi = flash->spi;
unsigned long timebase;
u8 cmd_buf[2];
cmd_buf[0] = 0x0F;
cmd_buf[1] = cmd;
timebase = get_timer(0);
do {
WATCHDOG_RESET();
spi_flash_cmd_read(spi, cmd_buf, 2, status, 1);
if ((*status & poll_bit) == 0)
break;
} while (get_timer(timebase) < timeout);
if ((*status & poll_bit) == 0)
return 0;
/* Timed out */
debug("SF: time out!\n");
return -1;
}
int spi_nand_flash_cmd_wait_ready(struct spi_flash *flash, u8 status_bit, u8 *status,
unsigned long timeout)
{
return spi_nand_flash_cmd_poll_bit(flash, timeout,
0xC0, status_bit, status);
}
static int spinand_waitfunc(struct mtd_info *mtd, u8 val, u8 *status)
{
struct ipq40xx_spinand_info *info = mtd_to_ipq_info(mtd);
@ -644,7 +680,7 @@ static int spi_nand_read(struct mtd_info *mtd, loff_t from, size_t len,
struct mtd_oob_ops ops = {0};
u32 ret;
ops.mode = MTD_OOB_AUTO;
ops.mode = MTD_OPS_AUTO_OOB;
ops.len = len;
ops.datbuf = (uint8_t *)buf;
ret = spi_nand_read_std(mtd, from, &ops);
@ -748,6 +784,8 @@ static int spi_nand_write_std(struct mtd_info *mtd, loff_t to, struct mtd_oob_op
}
if (ops->ooblen)
ret = spi_nand_write_oob_data(mtd, to, ops);
ops->retlen += bytes;
write_len -= bytes;
if (!write_len)
break;
@ -771,6 +809,7 @@ static int spi_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
ops.len = len;
ops.datbuf = (uint8_t *)buf;
ret = spi_nand_write_std(mtd, to, &ops);
*retlen = ops.retlen;
return ret;
}
@ -789,10 +828,9 @@ static int spi_nand_write_oob(struct mtd_info *mtd, loff_t to,
return ret;
}
struct spi_flash *spi_nand_flash_probe(struct spi_slave *spi,
u8 *idcode)
int spi_nand_flash_probe(struct spi_slave *spi, struct spi_flash *flash,
u8 *idcode)
{
struct spi_flash *flash;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(spi_nand_flash_tbl); i++) {
@ -809,25 +847,16 @@ struct spi_flash *spi_nand_flash_probe(struct spi_slave *spi,
}
if (i == ARRAY_SIZE(spi_nand_flash_tbl)) {
printf("SF NAND unsupported id:%x:%x:%x:%x",
idcode[0], idcode[1], idcode[2], idcode[3]);
return NULL;
return -EINVAL;
}
flash = (struct spi_flash *)malloc(sizeof (*flash));
if (!flash) {
printf ("SF Failed to allocate memeory\n");
return NULL;
}
flash->spi = spi;
flash->name = params->name;
flash->page_size = params->page_size;
flash->sector_size = params->page_size;
flash->erase_size = params->erase_size;
flash->size = (params->page_size * params->nr_sectors * params->pages_per_sector);
return flash;
return 0;
}
static int spinand_unlock_protect(struct mtd_info *mtd)
@ -962,20 +991,19 @@ int spi_nand_init(void)
mtd->priv = chip;
mtd->writesize = flash->page_size;
mtd->writebufsize = mtd->writesize;
mtd->erasesize = params->erase_size;
mtd->oobsize = params->oob_size;
mtd->size = flash->size;
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->point = NULL;
mtd->unpoint = NULL;
mtd->read = spi_nand_read;
mtd->write = spi_nand_write;
mtd->erase = spi_nand_erase;
mtd->read_oob = spi_nand_read_oob;
mtd->write_oob = spi_nand_write_oob;
mtd->block_isbad = spi_nand_block_isbad;
mtd->block_markbad = spi_nand_block_markbad;
mtd->_read = spi_nand_read;
mtd->_write = spi_nand_write;
mtd->_erase = spi_nand_erase;
mtd->_read_oob = spi_nand_read_oob;
mtd->_write_oob = spi_nand_write_oob;
mtd->_block_isbad = spi_nand_block_isbad;
mtd->_block_markbad = spi_nand_block_markbad;
chip->page_shift = ffs(mtd->writesize) - 1;
chip->phys_erase_shift = ffs(mtd->erasesize) - 1;