-#ifdef CONFIG_MTD_ONENAND_OTP
-
-/* Interal OTP operation */
-typedef int (*otp_op_t)(struct mtd_info *mtd, loff_t form, size_t len,
- size_t *retlen, u_char *buf);
-
-/**
- * do_otp_read - [DEFAULT] Read OTP block area
- * @param mtd MTD device structure
- * @param from The offset to read
- * @param len number of bytes to read
- * @param retlen pointer to variable to store the number of readbytes
- * @param buf the databuffer to put/get data
- *
- * Read OTP block area.
- */
-static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
-{
- struct onenand_chip *this = mtd->priv;
- int ret;
-
- /* Enter OTP access mode */
- this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
- this->wait(mtd, FL_OTPING);
-
- ret = mtd->read(mtd, from, len, retlen, buf);
-
- /* Exit OTP access mode */
- this->command(mtd, ONENAND_CMD_RESET, 0, 0);
- this->wait(mtd, FL_RESETING);
-
- return ret;
-}
-
-/**
- * do_otp_write - [DEFAULT] Write OTP block area
- * @param mtd MTD device structure
- * @param from The offset to write
- * @param len number of bytes to write
- * @param retlen pointer to variable to store the number of write bytes
- * @param buf the databuffer to put/get data
- *
- * Write OTP block area.
- */
-static int do_otp_write(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
-{
- struct onenand_chip *this = mtd->priv;
- unsigned char *pbuf = buf;
- int ret;
-
- /* Force buffer page aligned */
- if (len < mtd->writesize) {
- memcpy(this->page_buf, buf, len);
- memset(this->page_buf + len, 0xff, mtd->writesize - len);
- pbuf = this->page_buf;
- len = mtd->writesize;
- }
-
- /* Enter OTP access mode */
- this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
- this->wait(mtd, FL_OTPING);
-
- ret = mtd->write(mtd, from, len, retlen, pbuf);
-
- /* Exit OTP access mode */
- this->command(mtd, ONENAND_CMD_RESET, 0, 0);
- this->wait(mtd, FL_RESETING);
-
- return ret;
-}
-
-/**
- * do_otp_lock - [DEFAULT] Lock OTP block area
- * @param mtd MTD device structure
- * @param from The offset to lock
- * @param len number of bytes to lock
- * @param retlen pointer to variable to store the number of lock bytes
- * @param buf the databuffer to put/get data
- *
- * Lock OTP block area.
- */
-static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
-{
- struct onenand_chip *this = mtd->priv;
- int ret;
-
- /* Enter OTP access mode */
- this->command(mtd, ONENAND_CMD_OTP_ACCESS, 0, 0);
- this->wait(mtd, FL_OTPING);
-
- ret = onenand_do_write_oob(mtd, from, len, retlen, buf);
-
- /* Exit OTP access mode */
- this->command(mtd, ONENAND_CMD_RESET, 0, 0);
- this->wait(mtd, FL_RESETING);
-
- return ret;
-}
-
-/**
- * onenand_otp_walk - [DEFAULT] Handle OTP operation
- * @param mtd MTD device structure
- * @param from The offset to read/write
- * @param len number of bytes to read/write
- * @param retlen pointer to variable to store the number of read bytes
- * @param buf the databuffer to put/get data
- * @param action do given action
- * @param mode specify user and factory
- *
- * Handle OTP operation.
- */
-static int onenand_otp_walk(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf,
- otp_op_t action, int mode)
-{
- struct onenand_chip *this = mtd->priv;
- int otp_pages;
- int density;
- int ret = 0;
-
- *retlen = 0;
-
- density = this->device_id >> ONENAND_DEVICE_DENSITY_SHIFT;
- if (density < ONENAND_DEVICE_DENSITY_512Mb)
- otp_pages = 20;
- else
- otp_pages = 10;
-
- if (mode == MTD_OTP_FACTORY) {
- from += mtd->writesize * otp_pages;
- otp_pages = 64 - otp_pages;
- }
-
- /* Check User/Factory boundary */
- if (((mtd->writesize * otp_pages) - (from + len)) < 0)
- return 0;
-
- while (len > 0 && otp_pages > 0) {
- if (!action) { /* OTP Info functions */
- struct otp_info *otpinfo;
-
- len -= sizeof(struct otp_info);
- if (len <= 0)
- return -ENOSPC;
-
- otpinfo = (struct otp_info *) buf;
- otpinfo->start = from;
- otpinfo->length = mtd->writesize;
- otpinfo->locked = 0;
-
- from += mtd->writesize;
- buf += sizeof(struct otp_info);
- *retlen += sizeof(struct otp_info);
- } else {
- size_t tmp_retlen;
- int size = len;
-
- ret = action(mtd, from, len, &tmp_retlen, buf);
-
- buf += size;
- len -= size;
- *retlen += size;
-
- if (ret < 0)
- return ret;
- }
- otp_pages--;
- }
-
- return 0;
-}
-
-/**
- * onenand_get_fact_prot_info - [MTD Interface] Read factory OTP info
- * @param mtd MTD device structure
- * @param buf the databuffer to put/get data
- * @param len number of bytes to read
- *
- * Read factory OTP info.
- */
-static int onenand_get_fact_prot_info(struct mtd_info *mtd,
- struct otp_info *buf, size_t len)
-{
- size_t retlen;
- int ret;
-
- ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_FACTORY);
-
- return ret ? : retlen;
-}
-
-/**
- * onenand_read_fact_prot_reg - [MTD Interface] Read factory OTP area
- * @param mtd MTD device structure
- * @param from The offset to read
- * @param len number of bytes to read
- * @param retlen pointer to variable to store the number of read bytes
- * @param buf the databuffer to put/get data
- *
- * Read factory OTP area.
- */
-static int onenand_read_fact_prot_reg(struct mtd_info *mtd, loff_t from,
- size_t len, size_t *retlen, u_char *buf)
-{
- return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_FACTORY);
-}
-
-/**
- * onenand_get_user_prot_info - [MTD Interface] Read user OTP info
- * @param mtd MTD device structure
- * @param buf the databuffer to put/get data
- * @param len number of bytes to read
- *
- * Read user OTP info.
- */
-static int onenand_get_user_prot_info(struct mtd_info *mtd,
- struct otp_info *buf, size_t len)
-{
- size_t retlen;
- int ret;
-
- ret = onenand_otp_walk(mtd, 0, len, &retlen, (u_char *) buf, NULL, MTD_OTP_USER);
-
- return ret ? : retlen;
-}
-
-/**
- * onenand_read_user_prot_reg - [MTD Interface] Read user OTP area
- * @param mtd MTD device structure
- * @param from The offset to read
- * @param len number of bytes to read
- * @param retlen pointer to variable to store the number of read bytes
- * @param buf the databuffer to put/get data
- *
- * Read user OTP area.
- */
-static int onenand_read_user_prot_reg(struct mtd_info *mtd, loff_t from,
- size_t len, size_t *retlen, u_char *buf)
-{
- return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_read, MTD_OTP_USER);
-}
-
-/**
- * onenand_write_user_prot_reg - [MTD Interface] Write user OTP area
- * @param mtd MTD device structure
- * @param from The offset to write
- * @param len number of bytes to write
- * @param retlen pointer to variable to store the number of write bytes
- * @param buf the databuffer to put/get data
- *
- * Write user OTP area.
- */
-static int onenand_write_user_prot_reg(struct mtd_info *mtd, loff_t from,
- size_t len, size_t *retlen, u_char *buf)
-{
- return onenand_otp_walk(mtd, from, len, retlen, buf, do_otp_write, MTD_OTP_USER);
-}
-
-/**
- * onenand_lock_user_prot_reg - [MTD Interface] Lock user OTP area
- * @param mtd MTD device structure
- * @param from The offset to lock
- * @param len number of bytes to unlock
- *
- * Write lock mark on spare area in page 0 in OTP block
- */
-static int onenand_lock_user_prot_reg(struct mtd_info *mtd, loff_t from,
- size_t len)
-{
- unsigned char oob_buf[64];
- size_t retlen;
- int ret;
-
- memset(oob_buf, 0xff, mtd->oobsize);
- /*
- * Note: OTP lock operation
- * OTP block : 0xXXFC
- * 1st block : 0xXXF3 (If chip support)
- * Both : 0xXXF0 (If chip support)
- */
- oob_buf[ONENAND_OTP_LOCK_OFFSET] = 0xFC;
-
- /*
- * Write lock mark to 8th word of sector0 of page0 of the spare0.
- * We write 16 bytes spare area instead of 2 bytes.
- */
- from = 0;
- len = 16;
-
- ret = onenand_otp_walk(mtd, from, len, &retlen, oob_buf, do_otp_lock, MTD_OTP_USER);
-
- return ret ? : retlen;
-}
-#endif /* CONFIG_MTD_ONENAND_OTP */
-