📄 nand_base.c
字号:
} if (getchip) { /* Deselect and wake up anyone waiting on the device */ nand_release_device(mtd); } return res;}/** * nand_default_block_markbad - [DEFAULT] mark a block bad * @mtd: MTD device structure * @ofs: offset from device start * * This is the default implementation, which can be overridden by * a hardware specific driver.*/static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs){ struct nand_chip *this = mtd->priv; u_char buf[2] = {0, 0}; size_t retlen; int block; /* Get block number */ block = ((int) ofs) >> this->bbt_erase_shift; if (this->bbt) this->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); /* Do we have a flash based bad block table ? */ if (this->options & NAND_USE_FLASH_BBT) return nand_update_bbt (mtd, ofs); /* We write two bytes, so we dont have to mess with 16 bit access */ ofs += mtd->oobsize + (this->badblockpos & ~0x01); return nand_write_oob (mtd, ofs , 2, &retlen, buf);}/** * nand_check_wp - [GENERIC] check if the chip is write protected * @mtd: MTD device structure * Check, if the device is write protected * * The function expects, that the device is already selected */static int nand_check_wp (struct mtd_info *mtd){ struct nand_chip *this = mtd->priv; /* Check the WP bit */ this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); return (this->read_byte(mtd) & NAND_STATUS_WP) ? 0 : 1; }/** * nand_block_checkbad - [GENERIC] Check if a block is marked bad * @mtd: MTD device structure * @ofs: offset from device start * @getchip: 0, if the chip is already selected * @allowbbt: 1, if its allowed to access the bbt area * * Check, if the block is bad. Either by reading the bad block table or * calling of the scan function. */static int nand_block_checkbad (struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt){ struct nand_chip *this = mtd->priv; if (!this->bbt) return this->block_bad(mtd, ofs, getchip); /* Return info from the table */ return nand_isbad_bbt (mtd, ofs, allowbbt);}/* * Wait for the ready pin, after a command * The timeout is catched later. */static void nand_wait_ready(struct mtd_info *mtd){ struct nand_chip *this = mtd->priv; unsigned long timeo = jiffies + 2; /* wait until command is processed or timeout occures */ do { if (this->dev_ready(mtd)) return; } while (time_before(jiffies, timeo)); }/** * nand_command - [DEFAULT] Send command to NAND device * @mtd: MTD device structure * @command: the command to be sent * @column: the column address for this command, -1 if none * @page_addr: the page address for this command, -1 if none * * Send command to NAND device. This function is used for small page * devices (256/512 Bytes per page) */static void nand_command (struct mtd_info *mtd, unsigned command, int column, int page_addr){ register struct nand_chip *this = mtd->priv; /* Begin command latch cycle */ this->hwcontrol(mtd, NAND_CTL_SETCLE); /* * Write out the command to the device. */ if (command == NAND_CMD_SEQIN) { int readcmd; if (column >= mtd->oobblock) { /* OOB area */ column -= mtd->oobblock; readcmd = NAND_CMD_READOOB; } else if (column < 256) { /* First 256 bytes --> READ0 */ readcmd = NAND_CMD_READ0; } else { column -= 256; readcmd = NAND_CMD_READ1; } this->write_byte(mtd, readcmd); } this->write_byte(mtd, command); /* Set ALE and clear CLE to start address cycle */ this->hwcontrol(mtd, NAND_CTL_CLRCLE); if (column != -1 || page_addr != -1) { this->hwcontrol(mtd, NAND_CTL_SETALE); /* Serially input address */ if (column != -1) { /* Adjust columns for 16 bit buswidth */ if (this->options & NAND_BUSWIDTH_16) column >>= 1; this->write_byte(mtd, column); } if (page_addr != -1) { this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); /* One more address cycle for devices > 32MiB */ if (this->chipsize > (32 << 20)) this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0x0f)); } /* Latch in address */ this->hwcontrol(mtd, NAND_CTL_CLRALE); } /* * program and erase have their own busy handlers * status and sequential in needs no delay */ switch (command) { case NAND_CMD_PAGEPROG: case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: case NAND_CMD_SEQIN: case NAND_CMD_STATUS: return; case NAND_CMD_RESET: if (this->dev_ready) break; udelay(this->chip_delay); this->hwcontrol(mtd, NAND_CTL_SETCLE); this->write_byte(mtd, NAND_CMD_STATUS); this->hwcontrol(mtd, NAND_CTL_CLRCLE); while ( !(this->read_byte(mtd) & NAND_STATUS_READY)); return; /* This applies to read commands */ default: /* * If we don't have access to the busy pin, we apply the given * command delay */ if (!this->dev_ready) { udelay (this->chip_delay); return; } } /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ ndelay (100); nand_wait_ready(mtd);}/** * nand_command_lp - [DEFAULT] Send command to NAND large page device * @mtd: MTD device structure * @command: the command to be sent * @column: the column address for this command, -1 if none * @page_addr: the page address for this command, -1 if none * * Send command to NAND device. This is the version for the new large page devices * We dont have the seperate regions as we have in the small page devices. * We must emulate NAND_CMD_READOOB to keep the code compatible. * */static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, int page_addr){ register struct nand_chip *this = mtd->priv; /* Emulate NAND_CMD_READOOB */ if (command == NAND_CMD_READOOB) { column += mtd->oobblock; command = NAND_CMD_READ0; } /* Begin command latch cycle */ this->hwcontrol(mtd, NAND_CTL_SETCLE); /* Write out the command to the device. */ this->write_byte(mtd, (command & 0xff)); /* End command latch cycle */ this->hwcontrol(mtd, NAND_CTL_CLRCLE); if (column != -1 || page_addr != -1) { this->hwcontrol(mtd, NAND_CTL_SETALE); /* Serially input address */ if (column != -1) { /* Adjust columns for 16 bit buswidth */ if (this->options & NAND_BUSWIDTH_16) column >>= 1; this->write_byte(mtd, column & 0xff); this->write_byte(mtd, column >> 8); } if (page_addr != -1) { this->write_byte(mtd, (unsigned char) (page_addr & 0xff)); this->write_byte(mtd, (unsigned char) ((page_addr >> 8) & 0xff)); /* One more address cycle for devices > 128MiB */ if (this->chipsize > (128 << 20)) this->write_byte(mtd, (unsigned char) ((page_addr >> 16) & 0xff)); } /* Latch in address */ this->hwcontrol(mtd, NAND_CTL_CLRALE); } /* * program and erase have their own busy handlers * status, sequential in, and deplete1 need no delay */ switch (command) { case NAND_CMD_CACHEDPROG: case NAND_CMD_PAGEPROG: case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: case NAND_CMD_SEQIN: case NAND_CMD_STATUS: case NAND_CMD_DEPLETE1: return; /* * read error status commands require only a short delay */ case NAND_CMD_STATUS_ERROR: case NAND_CMD_STATUS_ERROR0: case NAND_CMD_STATUS_ERROR1: case NAND_CMD_STATUS_ERROR2: case NAND_CMD_STATUS_ERROR3: udelay(this->chip_delay); return; case NAND_CMD_RESET: if (this->dev_ready) break; udelay(this->chip_delay); this->hwcontrol(mtd, NAND_CTL_SETCLE); this->write_byte(mtd, NAND_CMD_STATUS); this->hwcontrol(mtd, NAND_CTL_CLRCLE); while ( !(this->read_byte(mtd) & NAND_STATUS_READY)); return; case NAND_CMD_READ0: /* Begin command latch cycle */ this->hwcontrol(mtd, NAND_CTL_SETCLE); /* Write out the start read command */ this->write_byte(mtd, NAND_CMD_READSTART); /* End command latch cycle */ this->hwcontrol(mtd, NAND_CTL_CLRCLE); /* Fall through into ready check */ /* This applies to read commands */ default: /* * If we don't have access to the busy pin, we apply the given * command delay */ if (!this->dev_ready) { udelay (this->chip_delay); return; } } /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ ndelay (100); nand_wait_ready(mtd);}/** * nand_get_device - [GENERIC] Get chip for selected access * @this: the nand chip descriptor * @mtd: MTD device structure * @new_state: the state which is requested * * Get the device and lock it for exclusive access */static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state){ struct nand_chip *active; spinlock_t *lock; wait_queue_head_t *wq; DECLARE_WAITQUEUE (wait, current); lock = (this->controller) ? &this->controller->lock : &this->chip_lock; wq = (this->controller) ? &this->controller->wq : &this->wq;retry: active = this; spin_lock(lock); /* Hardware controller shared among independend devices */ if (this->controller) { if (this->controller->active) active = this->controller->active; else this->controller->active = this; } if (active == this && this->state == FL_READY) { this->state = new_state; spin_unlock(lock); return; } set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(wq, &wait); spin_unlock(lock); schedule(); remove_wait_queue(wq, &wait); goto retry;}/** * nand_wait - [DEFAULT] wait until the command is done * @mtd: MTD device structure * @this: NAND chip structure * @state: state to select the max. timeout value * * Wait for command done. This applies to erase and program only * Erase can take up to 400ms and program up to 20ms according to * general NAND and SmartMedia specs **/static int nand_wait(struct mtd_info *mtd, struct nand_chip *this, int state){ unsigned long timeo = jiffies; int status; if (state == FL_ERASING) timeo += (HZ * 400) / 1000; else timeo += (HZ * 20) / 1000; /* Apply this short delay always to ensure that we do wait tWB in * any case on any machine. */ ndelay (100); if ((state == FL_ERASING) && (this->options & NAND_IS_AND)) this->cmdfunc (mtd, NAND_CMD_STATUS_MULTI, -1, -1); else this->cmdfunc (mtd, NAND_CMD_STATUS, -1, -1); while (time_before(jiffies, timeo)) { /* Check, if we were interrupted */ if (this->state != state) return 0; if (this->dev_ready) { if (this->dev_ready(mtd)) break; } else { if (this->read_byte(mtd) & NAND_STATUS_READY) break; } cond_resched(); } status = (int) this->read_byte(mtd); return status;}/** * nand_write_page - [GENERIC] write one page * @mtd: MTD device structure * @this: NAND chip structure * @page: startpage inside the chip, must be called with (page & this->pagemask) * @oob_buf: out of band data buffer * @oobsel: out of band selecttion structre * @cached: 1 = enable cached programming if supported by chip * * Nand_page_program function is used for write and writev ! * This function will always program a full page of data * If you call it with a non page aligned buffer, you're lost :) * * Cached programming is not supported yet. */static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf, struct nand_oobinfo *oobsel, int cached){ int i, status; u_char ecc_code[32]; int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; int *oob_config = oobsel->eccpos; int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; int eccbytes = 0; /* FIXME: Enable cached programming */ cached = 0; /* Send command to begin auto page programming */ this->cmdfunc (mtd, NAND_CMD_SEQIN, 0x00, page); /* Write out complete page of data, take care of eccmode */ switch (eccmode) { /* No ecc, write all */ case NAND_ECC_NONE: printk (KERN_WARNING "Writing data without ECC to NAND-FLASH is not recommended\n"); this->write_buf(mtd, this->data_poi, mtd->oobblock); break; /* Software ecc 3/256, write all */ case NAND_ECC_SOFT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -