static int sflash_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; int bytes, ret = 0; /* Check address range */ if (!len) return 0; if ((to + len) > mtd->size) return -EINVAL; down(&sflash->lock); *retlen = 0; while (len) { if ((bytes = sflash_write(sflash->sbh, sflash->cc, (uint) to, len, buf)) < 0) { ret = bytes; break; } if ((ret = sflash_mtd_poll(sflash, (unsigned int) to, HZ / 10))) break; to += (loff_t) bytes; len -= bytes; buf += bytes; *retlen += bytes; } up(&sflash->lock); return ret; }
static int sflash_mtd_erase(struct mtd_info *mtd, struct erase_info *erase) { struct sflash_mtd *sflash = (struct sflash_mtd *) mtd->priv; int i, j, ret = 0; unsigned int addr, len; /* Check address range */ if (!erase->len) return 0; if ((erase->addr + erase->len) > mtd->size) return -EINVAL; addr = erase->addr; len = erase->len; down(&sflash->lock); /* Ensure that requested region is aligned */ for (i = 0; i < mtd->numeraseregions; i++) { for (j = 0; j < mtd->eraseregions[i].numblocks; j++) { if (addr == mtd->eraseregions[i].offset + mtd->eraseregions[i].erasesize * j && len >= mtd->eraseregions[i].erasesize) { if ((ret = sflash_erase(sflash->sbh, sflash->cc, addr)) < 0) break; if ((ret = sflash_mtd_poll(sflash, addr, 10 * HZ))) break; addr += mtd->eraseregions[i].erasesize; len -= mtd->eraseregions[i].erasesize; } } if (ret) break; } up(&sflash->lock); /* Set erase status */ if (ret) erase->state = MTD_ERASE_FAILED; else erase->state = MTD_ERASE_DONE; /* Call erase callback */ if (erase->callback) erase->callback(erase); return ret; }