···192192 struct onenand_chip *this = mtd->priv;193193 int value, readcmd = 0, block_cmd = 0;194194 int block, page;195195- /* Now we use page size operation */196196- int sectors = 4, count = 4;197195198196 /* Address translation */199197 switch (cmd) {···243245 }244246245247 if (page != -1) {248248+ /* Now we use page size operation */249249+ int sectors = 4, count = 4;246250 int dataram;247251248252 switch (cmd) {···298298 unsigned long timeout;299299 unsigned int flags = ONENAND_INT_MASTER;300300 unsigned int interrupt = 0;301301- unsigned int ctrl, ecc;301301+ unsigned int ctrl;302302303303 /* The 20 msec is enough */304304 timeout = jiffies + msecs_to_jiffies(20);···310310311311 if (state != FL_READING)312312 cond_resched();313313- touch_softlockup_watchdog();314313 }315314 /* To get correct interrupt status in timeout case */316315 interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT);···317318 ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);318319319320 if (ctrl & ONENAND_CTRL_ERROR) {320320- /* It maybe occur at initial bad block */321321 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl);322322- /* Clear other interrupt bits for preventing ECC error */323323- interrupt &= ONENAND_INT_MASTER;324324- }325325-326326- if (ctrl & ONENAND_CTRL_LOCK) {327327- DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl);328328- return -EACCES;322322+ if (ctrl & ONENAND_CTRL_LOCK)323323+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error.\n");324324+ return ctrl;329325 }330326331327 if (interrupt & ONENAND_INT_READ) {332332- ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);328328+ int ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS);333329 if (ecc) {334330 DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc);335335- if (ecc & ONENAND_ECC_2BIT_ALL)331331+ if (ecc & ONENAND_ECC_2BIT_ALL) {336332 mtd->ecc_stats.failed++;337337- else if (ecc & ONENAND_ECC_1BIT_ALL)333333+ return ecc;334334+ } else if (ecc & ONENAND_ECC_1BIT_ALL)338335 mtd->ecc_stats.corrected++;339336 }340337 }···367372{368373 struct onenand_chip *this = mtd->priv;369374370370- /* To prevent soft lockup */371371- touch_softlockup_watchdog();372372-373375 wait_for_completion(&this->complete);374376375377 return onenand_wait(mtd, state);···386394387395 /* We use interrupt wait first */388396 this->wait = onenand_interrupt_wait;389389-390390- /* To prevent soft lockup */391391- touch_softlockup_watchdog();392397393398 timeout = msecs_to_jiffies(100);394399 remain = wait_for_completion_timeout(&this->complete, timeout);···710721 struct mtd_ecc_stats stats;711722 int read = 0, column;712723 int thislen;713713- int ret = 0;724724+ int ret = 0, boundary = 0;714725715726 DEBUG(MTD_DEBUG_LEVEL3, "onenand_read: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len);716727···727738 /* TODO handling oob */728739729740 stats = mtd->ecc_stats;730730- while (read < len) {731731- thislen = min_t(int, mtd->writesize, len - read);732741733733- column = from & (mtd->writesize - 1);734734- if (column + thislen > mtd->writesize)735735- thislen = mtd->writesize - column;742742+ /* Read-while-load method */736743737737- if (!onenand_check_bufferram(mtd, from)) {738738- this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);744744+ /* Do first load to bufferRAM */745745+ if (read < len) {746746+ if (!onenand_check_bufferram(mtd, from)) {747747+ this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);748748+ ret = this->wait(mtd, FL_READING);749749+ onenand_update_bufferram(mtd, from, !ret);750750+ }751751+ }739752740740- ret = this->wait(mtd, FL_READING);741741- /* First copy data and check return value for ECC handling */742742- onenand_update_bufferram(mtd, from, 1);743743- }753753+ thislen = min_t(int, mtd->writesize, len - read);754754+ column = from & (mtd->writesize - 1);755755+ if (column + thislen > mtd->writesize)756756+ thislen = mtd->writesize - column;744757745745- this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);758758+ while (!ret) {759759+ /* If there is more to load then start next load */760760+ from += thislen;761761+ if (read + thislen < len) {762762+ this->command(mtd, ONENAND_CMD_READ, from, mtd->writesize);763763+ /*764764+ * Chip boundary handling in DDP765765+ * Now we issued chip 1 read and pointed chip 1766766+ * bufferam so we have to point chip 0 bufferam.767767+ */768768+ if (this->device_id & ONENAND_DEVICE_IS_DDP &&769769+ unlikely(from == (this->chipsize >> 1))) {770770+ this->write_word(0, this->base + ONENAND_REG_START_ADDRESS2);771771+ boundary = 1;772772+ } else773773+ boundary = 0;774774+ ONENAND_SET_PREV_BUFFERRAM(this);775775+ }776776+ /* While load is going, read from last bufferRAM */777777+ this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);778778+ /* See if we are done */779779+ read += thislen;780780+ if (read == len)781781+ break;782782+ /* Set up for next read from bufferRAM */783783+ if (unlikely(boundary))784784+ this->write_word(0x8000, this->base + ONENAND_REG_START_ADDRESS2);785785+ ONENAND_SET_NEXT_BUFFERRAM(this);786786+ buf += thislen;787787+ thislen = min_t(int, mtd->writesize, len - read);788788+ column = 0;789789+ cond_resched();790790+ /* Now wait for load */791791+ ret = this->wait(mtd, FL_READING);792792+ onenand_update_bufferram(mtd, from, !ret);793793+ }746794747747- read += thislen;748748-749749- if (read == len)750750- break;751751-752752- if (ret) {753753- DEBUG(MTD_DEBUG_LEVEL0, "onenand_read: read failed = %d\n", ret);754754- goto out;755755- }756756-757757- from += thislen;758758- buf += thislen;759759- }760760-761761-out:762795 /* Deselect and wake up anyone waiting on the device */763796 onenand_release_device(mtd);764797···793782794783 if (mtd->ecc_stats.failed - stats.failed)795784 return -EBADMSG;785785+786786+ if (ret)787787+ return ret;796788797789 return mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;798790}···834820 column = from & (mtd->oobsize - 1);835821836822 while (read < len) {823823+ cond_resched();824824+837825 thislen = mtd->oobsize - column;838826 thislen = min_t(int, thislen, len);839827···848832849833 this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen);850834835835+ if (ret) {836836+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = 0x%x\n", ret);837837+ goto out;838838+ }839839+851840 read += thislen;852841853842 if (read == len)854843 break;855855-856856- if (ret) {857857- DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret);858858- goto out;859859- }860844861845 buf += thislen;862846···935919 void __iomem *dataram0, *dataram1;936920 int ret = 0;937921922922+ /* In partial page write, just skip it */923923+ if ((addr & (mtd->writesize - 1)) != 0)924924+ return 0;925925+938926 this->command(mtd, ONENAND_CMD_READ, addr, mtd->writesize);939927940928 ret = this->wait(mtd, FL_READING);···961941#define onenand_verify_oob(...) (0)962942#endif963943964964-#define NOTALIGNED(x) ((x & (mtd->writesize - 1)) != 0)944944+#define NOTALIGNED(x) ((x & (this->subpagesize - 1)) != 0)965945966946/**967947 * onenand_write - [MTD Interface] write buffer to FLASH···979959 struct onenand_chip *this = mtd->priv;980960 int written = 0;981961 int ret = 0;962962+ int column, subpage;982963983964 DEBUG(MTD_DEBUG_LEVEL3, "onenand_write: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len);984965···998977 return -EINVAL;999978 }1000979980980+ column = to & (mtd->writesize - 1);981981+ subpage = column || (len & (mtd->writesize - 1));982982+1001983 /* Grab the lock and see if the device is available */1002984 onenand_get_device(mtd, FL_WRITING);10039851004986 /* Loop until all data write */1005987 while (written < len) {10061006- int thislen = min_t(int, mtd->writesize, len - written);988988+ int bytes = mtd->writesize;989989+ int thislen = min_t(int, bytes, len - written);990990+ u_char *wbuf = (u_char *) buf;100799110081008- this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->writesize);992992+ cond_resched();100999310101010- this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen);994994+ this->command(mtd, ONENAND_CMD_BUFFERRAM, to, bytes);995995+996996+ /* Partial page write */997997+ if (subpage) {998998+ bytes = min_t(int, bytes - column, (int) len);999999+ memset(this->page_buf, 0xff, mtd->writesize);10001000+ memcpy(this->page_buf + column, buf, bytes);10011001+ wbuf = this->page_buf;10021002+ /* Even though partial write, we need page size */10031003+ thislen = mtd->writesize;10041004+ }10051005+10061006+ this->write_bufferram(mtd, ONENAND_DATARAM, wbuf, 0, thislen);10111007 this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize);1012100810131009 this->command(mtd, ONENAND_CMD_PROG, to, mtd->writesize);1014101010151015- onenand_update_bufferram(mtd, to, 1);10111011+ /* In partial page write we don't update bufferram */10121012+ onenand_update_bufferram(mtd, to, !subpage);1016101310171014 ret = this->wait(mtd, FL_WRITING);10181015 if (ret) {10191016 DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: write filaed %d\n", ret);10201020- goto out;10171017+ break;10181018+ }10191019+10201020+ /* Only check verify write turn on */10211021+ ret = onenand_verify_page(mtd, (u_char *) wbuf, to);10221022+ if (ret) {10231023+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);10241024+ break;10211025 }1022102610231027 written += thislen;1024102810251025- /* Only check verify write turn on */10261026- ret = onenand_verify_page(mtd, (u_char *) buf, to);10271027- if (ret) {10281028- DEBUG(MTD_DEBUG_LEVEL0, "onenand_write: verify failed %d\n", ret);10291029- goto out;10301030- }10311031-10321029 if (written == len)10331030 break;1034103110321032+ column = 0;10351033 to += thislen;10361034 buf += thislen;10371035 }1038103610391039-out:10401037 /* Deselect and wake up anyone waiting on the device */10411038 onenand_release_device(mtd);10421039···10971058 /* Loop until all data write */10981059 while (written < len) {10991060 int thislen = min_t(int, mtd->oobsize, len - written);10611061+10621062+ cond_resched();1100106311011064 column = to & (mtd->oobsize - 1);11021065···12271186 instr->state = MTD_ERASING;1228118712291188 while (len) {11891189+ cond_resched();1230119012311191 /* Check if we have a bad block, we do not erase bad blocks */12321192 if (onenand_block_checkbad(mtd, addr, 0, 0)) {···12411199 ret = this->wait(mtd, FL_ERASING);12421200 /* Check, if it is write protected */12431201 if (ret) {12441244- if (ret == -EPERM)12451245- DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n");12461246- else12471247- DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));12021202+ DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift));12481203 instr->state = MTD_ERASE_FAILED;12491204 instr->fail_addr = addr;12501205 goto erase_exit;···20682029 init_waitqueue_head(&this->wq);20692030 spin_lock_init(&this->chip_lock);2070203120322032+ /*20332033+ * Allow subpage writes up to oobsize.20342034+ */20712035 switch (mtd->oobsize) {20722036 case 64:20732037 this->ecclayout = &onenand_oob_64;20382038+ mtd->subpage_sft = 2;20742039 break;2075204020762041 case 32:20772042 this->ecclayout = &onenand_oob_32;20432043+ mtd->subpage_sft = 1;20782044 break;2079204520802046 default:20812047 printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n",20822048 mtd->oobsize);20492049+ mtd->subpage_sft = 0;20832050 /* To prevent kernel oops */20842051 this->ecclayout = &onenand_oob_32;20852052 break;20862053 }2087205420552055+ this->subpagesize = mtd->writesize >> mtd->subpage_sft;20882056 mtd->ecclayout = this->ecclayout;2089205720902058 /* Fill in remaining MTD driver data */
+2-1
drivers/mtd/onenand/onenand_bbt.c
···9393 ret = onenand_do_read_oob(mtd, from + j * mtd->writesize + bd->offs,9494 readlen, &retlen, &buf[0]);95959696- if (ret)9696+ /* If it is a initial bad block, just ignore it */9797+ if (ret && !(ret & ONENAND_CTRL_LOAD))9798 return ret;989999100 if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->writesize, bd)) {
+3
include/linux/mtd/onenand.h
···8888 * operation is in progress8989 * @state: [INTERN] the current state of the OneNAND device9090 * @page_buf: data buffer9191+ * @subpagesize: [INTERN] holds the subpagesize9192 * @ecclayout: [REPLACEABLE] the default ecc placement scheme9293 * @bbm: [REPLACEABLE] pointer to Bad Block Management9394 * @priv: [OPTIONAL] pointer to private chip date···129128 onenand_state_t state;130129 unsigned char *page_buf;131130131131+ int subpagesize;132132 struct nand_ecclayout *ecclayout;133133134134 void *bbm;···143141#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index)144142#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1)145143#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1)144144+#define ONENAND_SET_PREV_BUFFERRAM(this) (this->bufferram_index ^= 1)146145147146#define ONENAND_GET_SYS_CFG1(this) \148147 (this->read_word(this->base + ONENAND_REG_SYS_CFG1))