/* reads the status of the device */ static void read_status(struct denali_nand_info *denali) { uint32_t cmd = 0x0; /* initialize the data buffer to store status */ reset_buf(denali); cmd = ioread32(denali->flash_reg + WRITE_PROTECT); if (cmd) write_byte_to_buf(denali, NAND_STATUS_WP); else write_byte_to_buf(denali, 0); }
static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t addr, id; int i; switch (cmd) { case NAND_CMD_PAGEPROG: break; case NAND_CMD_STATUS: read_status(denali); break; case NAND_CMD_READID: case NAND_CMD_PARAM: reset_buf(denali); /*sometimes ManufactureId read from register is not right * e.g. some of Micron MT29F32G08QAA MLC NAND chips * So here we send READID cmd to NAND insteand * */ addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); index_addr(denali, (uint32_t)addr | 0, 0x90); index_addr(denali, (uint32_t)addr | 1, 0); for (i = 0; i < 5; i++) { index_addr_read_data(denali, (uint32_t)addr | 2, &id); write_byte_to_buf(denali, id); } break; case NAND_CMD_READ0: case NAND_CMD_SEQIN: denali->page = page; break; case NAND_CMD_RESET: reset_bank(denali); break; case NAND_CMD_READOOB: /* TODO: Read OOB data */ break; default: printk(KERN_ERR ": unsupported command" " received 0x%x\n", cmd); break; } }
static void denali_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t i, addr, result; /* delay for tR (data transfer from Flash array to data register) */ udelay(25); /* ensure device completed else additional delay and polling */ wait_for_irq(denali, INTR_STATUS__INT_ACT); addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); for (i = 0; i < len; i++) { index_addr_read_data(denali, (uint32_t)addr | 2, &result); write_byte_to_buf(denali, result); } memcpy(buf, denali->buf.buf, len); }
static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t addr, id; int i; switch (cmd) { case NAND_CMD_PAGEPROG: break; case NAND_CMD_STATUS: read_status(denali); break; case NAND_CMD_READID: case NAND_CMD_PARAM: reset_buf(denali); addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); index_addr(denali, (uint32_t)addr | 0, 0x90); index_addr(denali, (uint32_t)addr | 1, 0); for (i = 0; i < 5; i++) { index_addr_read_data(denali, (uint32_t)addr | 2, &id); write_byte_to_buf(denali, id); } break; case NAND_CMD_READ0: case NAND_CMD_SEQIN: denali->page = page; break; case NAND_CMD_RESET: reset_bank(denali); break; case NAND_CMD_READOOB: break; default: printk(KERN_ERR ": unsupported command" " received 0x%x\n", cmd); break; } }
static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t addr, id; uint32_t pages_per_block; uint32_t block; int i; switch (cmd) { case NAND_CMD_PAGEPROG: break; case NAND_CMD_STATUS: read_status(denali); break; case NAND_CMD_READID: reset_buf(denali); /* * sometimes ManufactureId read from register is not right * e.g. some of Micron MT29F32G08QAA MLC NAND chips * So here we send READID cmd to NAND insteand */ addr = MODE_11 | BANK(denali->flash_bank); index_addr(denali, addr | 0, 0x90); index_addr(denali, addr | 1, col); for (i = 0; i < 8; i++) { index_addr_read_data(denali, addr | 2, &id); write_byte_to_buf(denali, id); } break; case NAND_CMD_PARAM: reset_buf(denali); /* turn on R/B interrupt */ denali_set_intr_modes(denali, false); denali_irq_mask = DENALI_IRQ_ALL | INTR_STATUS__INT_ACT; clear_interrupts(denali); denali_irq_enable(denali, denali_irq_mask); denali_set_intr_modes(denali, true); addr = (uint32_t)MODE_11 | BANK(denali->flash_bank); index_addr(denali, (uint32_t)addr | 0, cmd); index_addr(denali, (uint32_t)addr | 1, col & 0xFF); /* Wait tR time... */ udelay(25); /* And then wait for R/B interrupt */ wait_for_irq(denali, INTR_STATUS__INT_ACT); /* turn off R/B interrupt now */ denali_irq_mask = DENALI_IRQ_ALL; denali_set_intr_modes(denali, false); denali_irq_enable(denali, denali_irq_mask); denali_set_intr_modes(denali, true); for (i = 0; i < 256; i++) { index_addr_read_data(denali, (uint32_t)addr | 2, &id); write_byte_to_buf(denali, id); } break; case NAND_CMD_READ0: case NAND_CMD_SEQIN: denali->page = page; break; case NAND_CMD_RESET: reset_bank(denali); break; case NAND_CMD_READOOB: /* TODO: Read OOB data */ break; case NAND_CMD_UNLOCK1: pages_per_block = mtd->erasesize / mtd->writesize; block = page / pages_per_block; addr = (uint32_t)MODE_10 | (block * pages_per_block); index_addr(denali, addr, 0x10); break; case NAND_CMD_UNLOCK2: pages_per_block = mtd->erasesize / mtd->writesize; block = (page+pages_per_block-1) / pages_per_block; addr = (uint32_t)MODE_10 | (block * pages_per_block); index_addr(denali, addr, 0x11); break; case NAND_CMD_ERASE1: case NAND_CMD_ERASE2: addr = MODE_10 | BANK(denali->flash_bank) | page; index_addr(denali, addr, 0x1); break; default: pr_err(": unsupported command received 0x%x\n", cmd); break; } }