/** * spinand_enable_ecc- send command 0x1f to write the SPI Nand OTP register * Description: * There is one bit( bit 0x10 ) to set or to clear the internal ECC. * Enable chip internal ECC, set the bit to 1 * Disable chip internal ECC, clear the bit to 0 */ static int spinand_enable_ecc(struct spi_device *spi_nand) { int retval; u8 otp = 0; retval = spinand_get_otp(spi_nand, &otp); if (retval < 0) return retval; if ((otp & OTP_ECC_MASK) == OTP_ECC_MASK) return 0; otp |= OTP_ECC_MASK; retval = spinand_set_otp(spi_nand, &otp); if (retval < 0) return retval; return spinand_get_otp(spi_nand, &otp); }
/** * spinand_lock_block- send write register 0x1f command to the Nand device * * Description: * After power up, all the Nand blocks are locked. This function allows * one to unlock the blocks, and so it can be written or erased. */ static int spinand_lock_block(struct spi_device *spi_nand, u8 lock) { struct spinand_cmd cmd = {0}; int ret; u8 otp = 0; ret = spinand_get_otp(spi_nand, &otp); cmd.cmd = CMD_WRITE_REG; cmd.n_addr = 1; cmd.addr[0] = REG_BLOCK_LOCK; cmd.n_tx = 1; cmd.tx_buf = &lock; ret = spinand_cmd(spi_nand, &cmd); if (ret < 0) dev_err(&spi_nand->dev, "error %d lock block\n", ret); return ret; }
static void spinand_cmdfunc(struct mtd_info *mtd, unsigned int command, int column, int page) { struct nand_chip *chip = (struct nand_chip *)mtd->priv; struct spinand_info *info = (struct spinand_info *)chip->priv; struct spinand_state *state = (struct spinand_state *)info->priv; switch (command) { /* * READ0 - read in first 0x800 bytes */ case NAND_CMD_READ1: case NAND_CMD_READ0: state->buf_ptr = 0; spinand_read_page(info->spi, page, 0x0, 0x840, state->buf); break; /* READOOB reads only the OOB because no ECC is performed. */ case NAND_CMD_READOOB: state->buf_ptr = 0; spinand_read_page(info->spi, page, 0x800, 0x40, state->buf); break; case NAND_CMD_RNDOUT: state->buf_ptr = column; break; case NAND_CMD_READID: state->buf_ptr = 0; spinand_read_id(info->spi, (u8 *)state->buf); break; case NAND_CMD_PARAM: state->buf_ptr = 0; break; /* ERASE1 stores the block and page address */ case NAND_CMD_ERASE1: spinand_erase_block(info->spi, page); break; /* ERASE2 uses the block and page address from ERASE1 */ case NAND_CMD_ERASE2: break; /* SEQIN sets up the addr buffer and all registers except the length */ case NAND_CMD_SEQIN: state->col = column; state->row = page; state->buf_ptr = 0; break; /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ case NAND_CMD_PAGEPROG: spinand_program_page(info->spi, state->row, state->col, state->buf_ptr, state->buf); break; case NAND_CMD_STATUS: spinand_get_otp(info->spi, state->buf); if (!(state->buf[0] & 0x80)) state->buf[0] = 0x80; state->buf_ptr = 0; break; /* RESET command */ case NAND_CMD_RESET: if (wait_till_ready(info->spi)) dev_err(&info->spi->dev, "WAIT timedout!!!\n"); /* a minimum of 250us must elapse before issuing RESET cmd*/ udelay(250); spinand_reset(info->spi); break; default: dev_err(&mtd->dev, "Unknown CMD: 0x%x\n", command); } }