Skip to content
Snippets Groups Projects
Commit 22f98e12 authored by Wu Zhixian's avatar Wu Zhixian Committed by Kenneth Johansson
Browse files

support QSPI NAND FLASH, test pass at HAPS

parent fc51b1f4
No related branches found
No related tags found
No related merge requests found
/*
/*
* (C) Copyright 2016 Intel Corporation
* Author: William Widjaja <w.widjaja@intel.com>
......@@ -240,6 +241,9 @@ static int spi_nand_manufacture_init(struct mtd_info *mtd, struct nand_chip *chi
chip->ecc.size = mtd->writesize >> 2;
//chip->ecc.steps = 4; /* 4 regions within page */
chip->ecc.bytes = 8; /* !<TODO : ??? */
if (type->dev_id == 0x12) {
info->options |= QSPI_NAND_FLASH_TYPE;
}
break;
......@@ -627,15 +631,25 @@ static int spinand_write_enable(struct spi_device *spi)
*/
static int spinand_read_page_to_cache(struct spi_device *spi, int page_id)
{
struct mtd_info *mtd = (struct mtd_info *)dev_get_drvdata((const struct device *)&(spi->dev));
struct nand_chip *chip = mtd_to_nand(mtd);
struct spinand_info *info = (struct spinand_info *)chip->priv;
struct spinand_cmd cmd = {0};
u16 row;
row = page_id;
cmd.cmd = CMD_READ;
cmd.n_addr = 3;
cmd.addr[0] = (u8) ((page_id & 0xff0000) >> 16);
cmd.addr[1] = (u8)((page_id & 0xff00) >> 8);
cmd.addr[2] = (u8)(page_id & 0x00ff);
if (info->options & QSPI_NAND_FLASH_TYPE) {
cmd.addr[2] = (u8) ((page_id & 0xff0000) >> 16);
cmd.addr[1] = (u8)((page_id & 0xff00) >> 8);
cmd.addr[0] = (u8)(page_id & 0x00ff);
} else {
cmd.addr[0] = (u8) ((page_id & 0xff0000) >> 16);
cmd.addr[1] = (u8)((page_id & 0xff00) >> 8);
cmd.addr[2] = (u8)(page_id & 0x00ff);
}
return spinand_cmd(spi, &cmd);
}
......@@ -670,6 +684,10 @@ static int spinand_read_from_cache(struct spi_device *spi, int page_id,
cmd.addr[0] = 0;
cmd.addr[1] = (u8)(column >> 8);
cmd.addr[2] = (u8)column;
} else if (info->options & QSPI_NAND_FLASH_TYPE) {
cmd.addr[0] = 0;
cmd.addr[1] = (u8)(column >> 8);
cmd.addr[2] = (u8)column;
} else {
cmd.addr[0] = (u8)((column & 0xff00) >> 8);
cmd.addr[1] = (u8)(column & 0x00ff);
......@@ -824,14 +842,23 @@ static int spinand_program_data_to_cache(struct spi_device *spi,
*/
static int spinand_program_execute(struct spi_device *spi, int page_id)
{
struct mtd_info *mtd = (struct mtd_info *)dev_get_drvdata((const struct device *)&(spi->dev));
struct nand_chip *chip = mtd_to_nand(mtd);
struct spinand_info *info = (struct spinand_info *)chip->priv;
struct spinand_cmd cmd = {0};
/* NOTE: this is changed so you can write above 128 MB */
cmd.cmd = CMD_PROG_PAGE_EXC;
cmd.n_addr = 3;
cmd.addr[0] = (u8)((page_id & 0xff0000) >> 16);
cmd.addr[1] = (u8)((page_id & 0xff00) >> 8);
cmd.addr[2] = (u8)(page_id & 0x00ff);
if (info->options & QSPI_NAND_FLASH_TYPE) {
cmd.addr[2] = (u8)((page_id & 0xff0000) >> 16);
cmd.addr[1] = (u8)((page_id & 0xff00) >> 8);
cmd.addr[0] = (u8)(page_id & 0x00ff);
} else {
cmd.addr[0] = (u8)((page_id & 0xff0000) >> 16);
cmd.addr[1] = (u8)((page_id & 0xff00) >> 8);
cmd.addr[2] = (u8)(page_id & 0x00ff);
}
return spinand_cmd(spi, &cmd);
}
......@@ -869,14 +896,21 @@ static int spinand_program_page(struct spi_device *spi,
if (wait_till_ready(spi))
dev_err(&spi->dev, "wait timedout!!!\n");
/* PROGRAM LOAD (02h), 2 bytes address, 2048 bytes data + 64 bytes OOB, no response */
retval = spinand_program_data_to_cache(spi, page_id,
offset, len, wbuf);
if (retval < 0)
if (retval < 0) {
dev_err(&spi->dev, "[%s]spinand_program_data_to_cache fail retval=0x%x\n", __func__, retval);
return retval;
}
/* PROGRAM EXECUTE (10h), 3 bytes address,no data, no response */
retval = spinand_program_execute(spi, page_id);
if (retval < 0)
if (retval < 0) {
dev_err(&spi->dev, "[%s]spinand_program_execute fail retval=0x%x\n", __func__, retval);
return retval;
}
while (1) {
/* GET FEATUR from command to read status (0Fh), 1 byte address for Status register address (C0h), 1 byte status response */
retval = spinand_read_status(spi, &status);
if (retval < 0) {
dev_err(&spi->dev,
......@@ -911,15 +945,24 @@ static int spinand_program_page(struct spi_device *spi,
*/
static int spinand_erase_block_erase(struct spi_device *spi, u32 block_id)
{
struct mtd_info *mtd = (struct mtd_info *)dev_get_drvdata((const struct device *)&(spi->dev));
struct nand_chip *chip = mtd_to_nand(mtd);
struct spinand_info *info = (struct spinand_info *)chip->priv;
struct spinand_cmd cmd = {0};
u16 row;
row = block_id;
cmd.cmd = CMD_ERASE_BLK;
cmd.n_addr = 3;
cmd.addr[0] = (u8)((block_id & 0xff0000) >> 16);
cmd.addr[1] = (u8)((block_id & 0xff00) >> 8);
cmd.addr[2] = (u8)(block_id & 0x00ff);
if (info->options & QSPI_NAND_FLASH_TYPE) {
cmd.addr[2] = (u8)((block_id & 0xff0000) >> 16);
cmd.addr[1] = (u8)((block_id & 0xff00) >> 8);
cmd.addr[0] = (u8)(block_id & 0x00ff);
} else {
cmd.addr[0] = (u8)((block_id & 0xff0000) >> 16);
cmd.addr[1] = (u8)((block_id & 0xff00) >> 8);
cmd.addr[2] = (u8)(block_id & 0x00ff);
}
return spinand_cmd(spi, &cmd);
}
......
......@@ -137,6 +137,6 @@ struct nand_ecclayout {
* - CMD_READ_RDM : extra dummy byte before column address
*/
#define GIGADEVICE_DUMMY_TYPE 0x1
#define QSPI_NAND_FLASH_TYPE 0x02
#endif /* __LTQ_MTD_SPI_NAND_H__ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment