static int nand_erase_block(uffs_Device *dev, u32 block) { u8 val = 0; struct my_nand_chip *chip = (struct my_nand_chip *) dev->attr->_private; CHIP_CLR_NCS(chip); CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_ERASE1); CHIP_CLR_CLE(chip); CHIP_SET_ALE(chip); WRITE_ERASE_ADDR(chip, blcok); CHIP_CLR_ALE(chip); CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_ERASE2); WRITE_COMMAND(chip, NAND_CMD_STATUS); CHIP_CLR_CLE(chip); CHIP_READY(chip); READ_DATA(chip, &val, 1); CHIP_SET_NCS(chip); val = val; // just for eliminating warning return PARSE_STATUS(val); }
static int nand_read_page(uffs_Device *dev, u32 block, u32 page, u8 *data, int data_len, u8 *ecc, u8 *spare, int spare_len) { u8 val = 0; int ret = UFFS_FLASH_NO_ERR; struct my_nand_chip *chip = (struct my_nand_chip *) dev->attr->_private; CHIP_CLR_NCS(chip); if (data && data_len > 0) { CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_READ0); CHIP_CLR_CLE(chip); CHIP_SET_ALE(chip); WRITE_DATA_ADDR(chip, block, page, 0); CHIP_CLR_ALE(chip); READ_DATA(chip, data, data_len); // for now, we return all 0xFF to pass UFFS mount, you should remove this at your driver memset(data, 0xFF, data_len); } if (spare && spare_len > 0) { CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_READOOB); CHIP_CLR_CLE(chip); CHIP_SET_ALE(chip); WRITE_DATA_ADDR(chip, block, page, dev->attr->page_data_size); CHIP_CLR_ALE(chip); READ_DATA(chip, spare, spare_len); // for now, we return all 0xFF to pass UFFS mount, you should remove this at your driver memset(spare, 0xFF, spare_len); } if (data == NULL && spare == NULL) { // read bad block mark CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_READOOB); CHIP_CLR_CLE(chip); CHIP_SET_ALE(chip); WRITE_DATA_ADDR(chip, block, page, dev->attr->page_data_size + attr->block_status_offs); CHIP_CLR_ALE(chip); READ_DATA(chip, &val, 1); ret = (val == 0xFF ? UFFS_FLASH_NO_ERR : UFFS_FLASH_BAD_BLK); // for now, we return UFFS_FLASH_NO_ERR to pass UFFS mount, you should remove this at your driver ret = UFFS_FLASH_NO_ERR; } CHIP_SET_NCS(chip); return ret; }
static int nand_write_page(uffs_Device *dev, u32 block, u32 page, const u8 *data, int data_len, const u8 *spare, int spare_len) { u8 val = 0; int ret = UFFS_FLASH_NO_ERR; UBOOL fall_through = FALSE; struct my_nand_chip *chip = (struct my_nand_chip *) dev->attr->_private; CHIP_CLR_NCS(chip); if (data && data_len > 0) { CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_READ0); WRITE_COMMAND(chip, NAND_CMD_SEQIN); CHIP_CLR_CLE(chip); CHIP_SET_ALE(chip); WRITE_DATA_ADDR(chip, block, page, 0); CHIP_CLR_ALE(chip); CHIP_BUSY(chip); WRITE_DATA(chip, data, data_len); if (data_len == dev->attr->page_data_size) fall_through = U_TRUE; else { CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_PAGEPROG); WRITE_COMMAND(chip, NAND_CMD_STATUS); CHIP_CLR_CLE(chip); CHIP_READY(chip); READ_DATA(chip, &val, 1); ret = PARSE_STATUS(val); } } if (ret != UFFS_FLASH_NO_ERR) goto ext; if (spare && spare_len > 0) { if (!fall_through) { CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_READOOB); WRITE_COMMAND(chip, NAND_CMD_SEQIN); CHIP_CLR_CLE(chip); CHIP_SET_ALE(chip); WRITE_DATA_ADDR(chip, block, page, dev->attr->page_data_size); CHIP_CLR_ALE(chip); CHIP_BUSY(chip); } WRITE_DATA(chip, spare, spare_len); CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_PAGEPROG); WRITE_COMMAND(chip, NAND_CMD_STATUS); CHIP_CLR_CLE(chip); CHIP_READY(chip); READ_DATA(chip, &val, 1); ret = PARSE_STATUS(val); } if (data == NULL && spare == NULL) { // mark bad block CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_READOOB); WRITE_COMMAND(chip, NAND_CMD_SEQIN); CHIP_CLR_CLE(chip); CHIP_SET_ALE(chip); WRITE_DATA_ADDR(chip, block, page, dev->attr->page_data_size + attr->block_status_offs); CHIP_CLR_ALE(chip); CHIP_BUSY(chip); val = 0; WRITE_DATA(chip, &val, 1); CHIP_SET_CLE(chip); WRITE_COMMAND(chip, NAND_CMD_PAGEPROG); WRITE_COMMAND(chip, NAND_CMD_STATUS); CHIP_CLR_CLE(chip); CHIP_READY(chip); READ_DATA(chip, &val, 1); ret = PARSE_STATUS(val); } ext: CHIP_SET_NCS(chip); return ret; }