static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor) { unsigned long deadline; int sr; int fsr; deadline = jiffies + MAX_READY_WAIT_JIFFIES; do { cond_resched(); sr = read_sr(nor); if (sr < 0) { break; } else if (!(sr & SR_WIP)) { fsr = read_fsr(nor); if (fsr < 0) break; if (fsr & FSR_READY) return 0; } } while (!time_after_eq(jiffies, deadline)); return -ETIMEDOUT; }
static inline int spi_nor_sr_ready(struct spi_nor *nor) { int sr = read_sr(nor); if (sr < 0) return sr; else return !(sr & SR_WIP); }
static int macronix_quad_enable(struct spi_nor *nor) { int ret, val; val = read_sr(nor); write_enable(nor); nor->cmd_buf[0] = val | SR_QUAD_EN_MX; nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); if (wait_till_ready(nor)) return 1; ret = read_sr(nor); if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { dev_err(nor->dev, "Macronix Quad bit not set\n"); return -EINVAL; } return 0; }
static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { struct spi_nor *nor = mtd_to_spi_nor(mtd); uint32_t offset = ofs; uint8_t status_old, status_new; int ret = 0; ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); if (ret) return ret; /* Wait until finished previous command */ ret = wait_till_ready(nor); if (ret) goto err; status_old = read_sr(nor); if (offset+len > mtd->size - (mtd->size / 64)) status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0); else if (offset+len > mtd->size - (mtd->size / 32)) status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; else if (offset+len > mtd->size - (mtd->size / 16)) status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; else if (offset+len > mtd->size - (mtd->size / 8)) status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; else if (offset+len > mtd->size - (mtd->size / 4)) status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; else if (offset+len > mtd->size - (mtd->size / 2)) status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; else status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; /* Only modify protection if it will not lock other areas */ if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) < (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { write_enable(nor); ret = write_sr(nor, status_new); if (ret) goto err; } err: spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); return ret; }
/* * Service routine to read status register until ready, or timeout occurs. * Returns non-zero if error. */ static int wait_till_ready(struct m25p *flash) { int sr; uint64_t timer_start; timer_start = get_time_ns(); do { if ((sr = read_sr(flash)) < 0) break; else if (!(sr & SR_WIP)) return 0; } while (!(is_timeout(timer_start, MAX_READY_WAIT * SECOND))); return -ETIMEDOUT; }
/* * Service routine to read status register until ready, or timeout occurs. * Returns non-zero if error. */ static int wait_till_ready(struct m25p *flash) { int count; int sr; /* one chip guarantees max 5 msec wait here after page writes, * but potentially three seconds (!) after page erase. */ for (count = 0; count < MAX_READY_WAIT_COUNT; count++) { if ((sr = read_sr(flash)) < 0) break; else if (!(sr & SR_WIP)) return 0; /* REVISIT sometimes sleeping would be best */ } return 1; }
/* * Service routine to read status register until ready, or timeout occurs. * Returns non-zero if error. */ static int wait_till_ready(struct m25p *flash) { unsigned long deadline; int sr; deadline = jiffies + MAX_READY_WAIT_JIFFIES; do { if ((sr = read_sr(flash)) < 0) break; else if (!(sr & SR_WIP)) return 0; cond_resched(); } while (!time_after_eq(jiffies, deadline)); return 1; }