static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; size_t size = mtd->writesize + mtd->oobsize; uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP; if (page != denali->page) { dev_err(denali->dev, "IN %s: page %d is not equal to denali->page %d", __func__, page, denali->page); BUG(); } setup_ecc_for_xfer(denali, false, true); denali_enable_dma(denali, true); dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); clear_interrupts(denali); denali_setup_dma(denali, DENALI_READ); /* wait for operation to complete */ wait_for_irq(denali, irq_mask); dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE); denali_enable_dma(denali, false); memcpy(buf, denali->buf.buf, mtd->writesize); memcpy(chip->oob_poi, denali->buf.buf + mtd->writesize, mtd->oobsize); return 0; }
/* Common DMA function */ static uint32_t denali_dma_configuration(struct denali_nand_info *denali, uint32_t ops, bool raw_xfer, uint32_t irq_mask, int oob_required) { uint32_t irq_status = 0; /* setup_ecc_for_xfer(bool ecc_en, bool transfer_spare) */ setup_ecc_for_xfer(denali, !raw_xfer, oob_required); /* clear any previous interrupt flags */ clear_interrupts(denali); /* enable the DMA */ denali_enable_dma(denali, true); /* setup the DMA */ denali_setup_dma(denali, ops); /* wait for operation to complete */ irq_status = wait_for_irq(denali, irq_mask); /* if ECC fault happen, seems we need delay before turning off DMA. * If not, the controller will go into non responsive condition */ if (irq_status & INTR_STATUS__ECC_UNCOR_ERR) udelay(100); /* disable the DMA */ denali_enable_dma(denali, false); return irq_status; }
/* * sends a pipeline command operation to the controller. See the Denali NAND * controller's user guide for more information (section 4.2.3.6). */ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool ecc_en, bool transfer_spare, int access_type, int op) { uint32_t addr, cmd, irq_status; static uint32_t page_count = 1; setup_ecc_for_xfer(denali, ecc_en, transfer_spare); clear_interrupts(denali); addr = BANK(denali->flash_bank) | denali->page; /* setup the acccess type */ cmd = MODE_10 | addr; index_addr(denali, cmd, access_type); /* setup the pipeline command */ index_addr(denali, cmd, 0x2000 | op | page_count); cmd = MODE_01 | addr; writel(cmd, denali->flash_mem + INDEX_CTRL_REG); if (op == DENALI_READ) { /* wait for command to be accepted */ irq_status = wait_for_irq(denali, INTR_STATUS__LOAD_COMP); if (irq_status == 0) return -EIO; } return 0; }
void spi_dw_isr(void *arg) { struct device *dev = (struct device *)arg; const struct spi_dw_config *info = dev->config->config_info; u32_t error = 0; u32_t int_status; int_status = read_isr(info->regs); SYS_LOG_DBG("SPI int_status 0x%x - (tx: %d, rx: %d)", int_status, read_txflr(info->regs), read_rxflr(info->regs)); if (int_status & DW_SPI_ISR_ERRORS_MASK) { error = 1; goto out; } if (int_status & DW_SPI_ISR_RXFIS) { pull_data(dev); } if (int_status & DW_SPI_ISR_TXEIS) { push_data(dev); } out: clear_interrupts(info->regs); completed(dev, error); }
// Called when a process closes the device file. static int close_pwm(struct inode *inode, struct file *file) { // Decrement the usage count, or else once you opened the file, you'll never get get rid of the module. module_put(THIS_MODULE); Device_Open--; clear_interrupts(); //printk(KERN_INFO PWM_DRIVER_NAME ": Device release (close_pwm)\n"); return 0; }
/* writes a page. user specifies type, and this function handles the * configuration details. */ static int write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, bool raw_xfer) { struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; size_t size = denali->mtd.writesize + denali->mtd.oobsize; uint32_t irq_status = 0; uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP | INTR_STATUS__PROGRAM_FAIL; /* if it is a raw xfer, we want to disable ecc, and send * the spare area. * !raw_xfer - enable ecc * raw_xfer - transfer spare */ setup_ecc_for_xfer(denali, !raw_xfer, raw_xfer); /* copy buffer into DMA buffer */ memcpy(denali->buf.buf, buf, mtd->writesize); if (raw_xfer) { /* transfer the data to the spare area */ memcpy(denali->buf.buf + mtd->writesize, chip->oob_poi, mtd->oobsize); } dma_sync_single_for_device(denali->dev, addr, size, DMA_TO_DEVICE); clear_interrupts(denali); denali_enable_dma(denali, true); denali_setup_dma(denali, DENALI_WRITE); /* wait for operation to complete */ irq_status = wait_for_irq(denali, irq_mask); if (irq_status == 0) { dev_err(denali->dev, "timeout on write_page (type = %d)\n", raw_xfer); denali->status = (irq_status & INTR_STATUS__PROGRAM_FAIL) ? NAND_STATUS_FAIL : PASS; } denali_enable_dma(denali, false); dma_sync_single_for_cpu(denali->dev, addr, size, DMA_TO_DEVICE); return 0; }
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { unsigned int max_bitflips; struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; size_t size = denali->mtd.writesize + denali->mtd.oobsize; uint32_t irq_status = 0; uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE | INTR_STATUS__ECC_ERR; bool check_erased_page = false; if (page != denali->page) { dev_err(denali->dev, "IN %s: page %d is not" " equal to denali->page %d, investigate!!", __func__, page, denali->page); BUG(); } setup_ecc_for_xfer(denali, true, false); denali_enable_dma(denali, true); dma_sync_single_for_device(denali->dev, addr, size, DMA_FROM_DEVICE); clear_interrupts(denali); denali_setup_dma(denali, DENALI_READ); /* wait for operation to complete */ irq_status = wait_for_irq(denali, irq_mask); dma_sync_single_for_cpu(denali->dev, addr, size, DMA_FROM_DEVICE); memcpy(buf, denali->buf.buf, mtd->writesize); check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips); denali_enable_dma(denali, false); if (check_erased_page) { read_oob_data(&denali->mtd, chip->oob_poi, denali->page); /* check ECC failures that may have occurred on erased pages */ if (check_erased_page) { if (!is_erased(buf, denali->mtd.writesize)) denali->mtd.ecc_stats.failed++; if (!is_erased(buf, denali->mtd.oobsize)) denali->mtd.ecc_stats.failed++; } } return max_bitflips; }
/* resets a specific device connected to the core */ static void reset_bank(struct denali_nand_info *denali) { uint32_t irq_status; uint32_t irq_mask = INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT; clear_interrupts(denali); writel(1 << denali->flash_bank, denali->flash_reg + DEVICE_RESET); irq_status = wait_for_irq(denali, irq_mask); if (irq_status & INTR_STATUS__TIME_OUT) debug("reset bank failed.\n"); }
static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, uint32_t irq_status) { bool check_erased_page = false; if (irq_status & INTR_STATUS__ECC_ERR) { uint32_t err_address = 0, err_correction_info = 0; uint32_t err_byte = 0, err_sector = 0, err_device = 0; uint32_t err_correction_value = 0; denali_set_intr_modes(denali, false); do { err_address = ioread32(denali->flash_reg + ECC_ERROR_ADDRESS); err_sector = ECC_SECTOR(err_address); err_byte = ECC_BYTE(err_address); err_correction_info = ioread32(denali->flash_reg + ERR_CORRECTION_INFO); err_correction_value = ECC_CORRECTION_VALUE(err_correction_info); err_device = ECC_ERR_DEVICE(err_correction_info); if (ECC_ERROR_CORRECTABLE(err_correction_info)) { if (err_byte < ECC_SECTOR_SIZE) { int offset; offset = (err_sector * ECC_SECTOR_SIZE + err_byte) * denali->devnum + err_device; buf[offset] ^= err_correction_value; denali->mtd.ecc_stats.corrected++; } } else { check_erased_page = true; } } while (!ECC_LAST_ERR(err_correction_info)); while (!(read_interrupt_status(denali) & INTR_STATUS__ECC_TRANSACTION_DONE)) cpu_relax(); clear_interrupts(denali); denali_set_intr_modes(denali, true); } return check_erased_page; }
static void write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, bool raw_xfer) { struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = denali->buf.dma_buf; size_t size = denali->mtd.writesize + denali->mtd.oobsize; uint32_t irq_status = 0; uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP | INTR_STATUS__PROGRAM_FAIL; setup_ecc_for_xfer(denali, !raw_xfer, raw_xfer); memcpy(denali->buf.buf, buf, mtd->writesize); if (raw_xfer) { memcpy(denali->buf.buf + mtd->writesize, chip->oob_poi, mtd->oobsize); } dma_sync_single_for_device(denali->dev, addr, size, DMA_TO_DEVICE); clear_interrupts(denali); denali_enable_dma(denali, true); denali_setup_dma(denali, DENALI_WRITE); irq_status = wait_for_irq(denali, irq_mask); if (irq_status == 0) { dev_err(denali->dev, "timeout on write_page (type = %d)\n", raw_xfer); denali->status = (irq_status & INTR_STATUS__PROGRAM_FAIL) ? NAND_STATUS_FAIL : PASS; } denali_enable_dma(denali, false); dma_sync_single_for_cpu(denali->dev, addr, size, DMA_TO_DEVICE); }
static int denali_erase(struct mtd_info *mtd, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t cmd, irq_status; clear_interrupts(denali); /* setup page read request for access type */ cmd = MODE_10 | BANK(denali->flash_bank) | page; index_addr(denali, cmd, 0x1); /* wait for erase to complete or failure to occur */ irq_status = wait_for_irq(denali, INTR_STATUS__ERASE_COMP | INTR_STATUS__ERASE_FAIL); return irq_status & INTR_STATUS__ERASE_FAIL ? NAND_STATUS_FAIL : PASS; }
void end_process_data(void) { report_utilization("cpu-consumption", total_cpu_time()); report_utilization("cpu-wakeups", total_wakeups()); report_utilization("gpu-operations", total_gpu_ops()); report_utilization("disk-operations", total_disk_hits()); report_utilization("disk-operations-hard", total_hard_disk_hits()); report_utilization("xwakes", total_xwakes()); all_power.erase(all_power.begin(), all_power.end()); clear_processes(); clear_proc_devices(); clear_interrupts(); clear_timers(); clear_work(); clear_consumers(); perf_events->clear(); }
static void denali_erase(struct mtd_info *mtd, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t cmd = 0x0, irq_status = 0; clear_interrupts(denali); cmd = MODE_10 | BANK(denali->flash_bank) | page; index_addr(denali, (uint32_t)cmd, 0x1); irq_status = wait_for_irq(denali, INTR_STATUS__ERASE_COMP | INTR_STATUS__ERASE_FAIL); denali->status = (irq_status & INTR_STATUS__ERASE_FAIL) ? NAND_STATUS_FAIL : PASS; }
static void denali_erase(struct mtd_info *mtd, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); uint32_t cmd, irq_status; /* clear interrupts */ clear_interrupts(denali); /* setup page read request for access type */ cmd = MODE_10 | BANK(denali->flash_bank) | page; index_addr(denali, cmd, 0x1); /* wait for erase to complete or failure to occur */ irq_status = wait_for_irq(denali, INTR_STATUS__ERASE_COMP | INTR_STATUS__ERASE_FAIL); if (irq_status & INTR_STATUS__ERASE_FAIL || irq_status & INTR_STATUS__LOCKED_BLK) denali->status = NAND_STATUS_FAIL; else denali->status = 0; }
void process_process_data(void) { if (!perf_events) return; clear_processes(); clear_interrupts(); all_power.erase(all_power.begin(), all_power.end()); clear_consumers(); cpu_credit.resize(0, 0); cpu_credit.resize(get_max_cpu()+1, 0); cpu_level.resize(0, 0); cpu_level.resize(get_max_cpu()+1, 0); cpu_blame.resize(0, NULL); cpu_blame.resize(get_max_cpu()+1, NULL); /* process data */ perf_events->process(); perf_events->clear(); run_devpower_list(); merge_processes(); all_processes_to_all_power(); all_interrupts_to_all_power(); all_timers_to_all_power(); all_work_to_all_power(); all_devices_to_all_power(); sort(all_power.begin(), all_power.end(), power_cpu_sort); }
static Bool dothestop(ps_context_t *pscontext, Bool super) { execStackSizeNotChanged = FALSE ; while ( ! isEmpty( executionstack )) { register OBJECT *o1 = theTop(executionstack) ; int32 *tptr ; FILELIST *flptr ; switch ( oType(*o1) ) { case OMARK : /* Represents a stopped mark */ if ( ! super || theLen(*o1)) { mm_context_t *mmc = ps_core_context(pscontext)->mm_context; if ( theLen(*o1)) { allow_interrupt = FALSE; /* superstop disables interrupt */ clear_interrupts(); } /* Reset allocation cost after error handling. */ if ( mmc != NULL) /* this can run before MM init */ mm_set_allocation_cost(mmc, mm_cost_normal); pop( & executionstack ) ; return push( & tnewobj , & operandstack ) ; } pop( & executionstack ) ; break ; case ONULL : switch ( theLen(*o1)) { case ISINTERPRETEREXIT : /* indicate that we're in a stopped context by changing the object's value */ oInteger(*o1) = super ? NAME_superstop : NAME_stop ; return TRUE; case ISPATHFORALL : tptr = oOther(*o1) ; path_free_list(thePathOf(*(PATHFORALL *)tptr), mm_pool_temp) ; free_forallpath( tptr ) ; npop( 4 , & executionstack ) ; break ; } pop( & executionstack ) ; break ; case OFILE : /* Represents a run object - if length is special value */ currfileCache = NULL ; if ( IsRunFile ( o1 )) { flptr = oFile(*o1) ; if ( isIOpenFileFilter( o1 , flptr )) (void)(*theIMyCloseFile( flptr ))( flptr, CLOSE_EXPLICIT ) ; } pop( & executionstack ) ; break ; default: pop( & executionstack ) ; } } return quit_(pscontext) ; }
static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf, uint32_t irq_status, unsigned int *max_bitflips) { bool check_erased_page = false; unsigned int bitflips = 0; if (irq_status & INTR_STATUS__ECC_ERR) { /* read the ECC errors. we'll ignore them for now */ uint32_t err_address = 0, err_correction_info = 0; uint32_t err_byte = 0, err_sector = 0, err_device = 0; uint32_t err_correction_value = 0; denali_set_intr_modes(denali, false); do { err_address = ioread32(denali->flash_reg + ECC_ERROR_ADDRESS); err_sector = ECC_SECTOR(err_address); err_byte = ECC_BYTE(err_address); err_correction_info = ioread32(denali->flash_reg + ERR_CORRECTION_INFO); err_correction_value = ECC_CORRECTION_VALUE(err_correction_info); err_device = ECC_ERR_DEVICE(err_correction_info); if (ECC_ERROR_CORRECTABLE(err_correction_info)) { /* If err_byte is larger than ECC_SECTOR_SIZE, * means error happened in OOB, so we ignore * it. It's no need for us to correct it * err_device is represented the NAND error * bits are happened in if there are more * than one NAND connected. * */ if (err_byte < ECC_SECTOR_SIZE) { int offset; offset = (err_sector * ECC_SECTOR_SIZE + err_byte) * denali->devnum + err_device; /* correct the ECC error */ buf[offset] ^= err_correction_value; denali->mtd.ecc_stats.corrected++; bitflips++; } } else { /* if the error is not correctable, need to * look at the page to see if it is an erased * page. if so, then it's not a real ECC error * */ check_erased_page = true; } } while (!ECC_LAST_ERR(err_correction_info)); /* Once handle all ecc errors, controller will triger * a ECC_TRANSACTION_DONE interrupt, so here just wait * for a while for this interrupt * */ while (!(read_interrupt_status(denali) & INTR_STATUS__ECC_TRANSACTION_DONE)) cpu_relax(); clear_interrupts(denali); denali_set_intr_modes(denali, true); } *max_bitflips = bitflips; return check_erased_page; }
/* sends a pipeline command operation to the controller. See the Denali NAND * controller's user guide for more information (section 4.2.3.6). */ static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool ecc_en, bool transfer_spare, int access_type, int op) { int status = PASS; uint32_t addr = 0x0, cmd = 0x0, page_count = 1, irq_status = 0, irq_mask = 0; if (op == DENALI_READ) irq_mask = INTR_STATUS__LOAD_COMP; else if (op == DENALI_WRITE) irq_mask = 0; else BUG(); setup_ecc_for_xfer(denali, ecc_en, transfer_spare); /* clear interrupts */ clear_interrupts(denali); addr = BANK(denali->flash_bank) | denali->page; if (op == DENALI_WRITE && access_type != SPARE_ACCESS) { cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); } else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) { /* read spare area */ cmd = MODE_10 | addr; index_addr(denali, (uint32_t)cmd, access_type); cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); } else if (op == DENALI_READ) { /* setup page read request for access type */ cmd = MODE_10 | addr; index_addr(denali, (uint32_t)cmd, access_type); /* page 33 of the NAND controller spec indicates we should not use the pipeline commands in Spare area only mode. So we don't. */ if (access_type == SPARE_ACCESS) { cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); } else { index_addr(denali, (uint32_t)cmd, 0x2000 | op | page_count); /* wait for command to be accepted * can always use status0 bit as the * mask is identical for each * bank. */ irq_status = wait_for_irq(denali, irq_mask); if (irq_status == 0) { dev_err(denali->dev, "cmd, page, addr on timeout " "(0x%x, 0x%x, 0x%x)\n", cmd, denali->page, addr); status = FAIL; } else { cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); } } } return status; }
static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { unsigned int max_bitflips = 0; struct denali_nand_info *denali = mtd_to_denali(mtd); dma_addr_t addr = (unsigned long)denali->buf.buf; size_t size = denali->mtd.writesize + denali->mtd.oobsize; uint32_t irq_status; uint32_t irq_mask = denali->have_hw_ecc_fixup ? (INTR_STATUS__DMA_CMD_COMP) : (INTR_STATUS__ECC_TRANSACTION_DONE | INTR_STATUS__ECC_ERR); bool check_erased_page = false; if (page != denali->page) { dev_err(denali->dev, "IN %s: page %d is not equal to denali->page %d", __func__, page, denali->page); BUG(); } setup_ecc_for_xfer(denali, true, false); denali_enable_dma(denali, true); dma_sync_single_for_device(addr, size, DMA_FROM_DEVICE); clear_interrupts(denali); denali_setup_dma(denali, DENALI_READ); /* wait for operation to complete */ irq_status = wait_for_irq(denali, irq_mask); dma_sync_single_for_cpu(addr, size, DMA_FROM_DEVICE); memcpy(buf, denali->buf.buf, mtd->writesize); check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips); denali_enable_dma(denali, false); if (check_erased_page) { if (denali->have_hw_ecc_fixup) { /* When we have hw ecc fixup, don't check oob. * That code below looks jacked up anyway. I mean, * look at it, wtf? */ if (!is_erased(buf, denali->mtd.writesize)) denali->mtd.ecc_stats.failed++; } else { read_oob_data(&denali->mtd, chip->oob_poi, denali->page); /* check ECC failures that may have occurred on * erased pages */ if (check_erased_page) { if (!is_erased(buf, denali->mtd.writesize)) denali->mtd.ecc_stats.failed++; if (!is_erased(buf, denali->mtd.oobsize)) denali->mtd.ecc_stats.failed++; } } } return max_bitflips; }
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; } }
static int denali_send_pipeline_cmd(struct denali_nand_info *denali, bool ecc_en, bool transfer_spare, int access_type, int op) { int status = PASS; uint32_t addr = 0x0, cmd = 0x0, page_count = 1, irq_status = 0, irq_mask = 0; if (op == DENALI_READ) irq_mask = INTR_STATUS__LOAD_COMP; else if (op == DENALI_WRITE) irq_mask = 0; else BUG(); setup_ecc_for_xfer(denali, ecc_en, transfer_spare); clear_interrupts(denali); addr = BANK(denali->flash_bank) | denali->page; if (op == DENALI_WRITE && access_type != SPARE_ACCESS) { cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); } else if (op == DENALI_WRITE && access_type == SPARE_ACCESS) { cmd = MODE_10 | addr; index_addr(denali, (uint32_t)cmd, access_type); cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); } else if (op == DENALI_READ) { cmd = MODE_10 | addr; index_addr(denali, (uint32_t)cmd, access_type); if (access_type == SPARE_ACCESS) { cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); } else { index_addr(denali, (uint32_t)cmd, 0x2000 | op | page_count); irq_status = wait_for_irq(denali, irq_mask); if (irq_status == 0) { dev_err(denali->dev, "cmd, page, addr on timeout " "(0x%x, 0x%x, 0x%x)\n", cmd, denali->page, addr); status = FAIL; } else { cmd = MODE_01 | addr; iowrite32(cmd, denali->flash_mem); } } } return status; }