- 论坛徽章:
- 0
|
static int do_write_buffer(struct map_info *map, struct flchip *chip,
unsigned long adr, const u_char *buf, int len)
{
struct cfi_private *cfi = map->fldrv_priv;
cfi_word status, status_OK;
unsigned long cmd_adr, timeo;
int wbufsize, z;
wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize;
adr += chip->start;
cmd_adr = adr & ~(wbufsize - 1);
/* Let's determinc this according to the interleave only once */
status_OK = CMD(0x80);
timeo = cfi->cfiq->BufWriteTimeoutMax * 1000;
ENABLE_VPP(map);
cfi_write(map, CMD(0xe , cmd_adr);
for (; {
status = cfi_read(map, cmd_adr);
if ((status & status_OK) == status_OK)
break;
if (timeo < 0) {
/* Argh. Not ready for write to buffer */
cfi_write(map, CMD(0x70), cmd_adr);
DISABLE_VPP(map);
printk("Chip not ready for buffer write. Xstatus = 0x%llx, status = %llx\n", (__u64)status, (__u64)cfi_read(map, cmd_adr));
/* Odd. Clear status bits */
cfi_write(map, CMD(0x50), cmd_adr);
cfi_write(map, CMD(0x70), cmd_adr);
cfi_write(map, CMD(0xff), adr);
return -EIO;
}
}
/* Write length of data to come */
cfi_write(map, CMD(len/CFIDEV_BUSWIDTH-1), cmd_adr);
/* Write data */
for (z = 0; z < len; z += CFIDEV_BUSWIDTH) {
if (cfi_buswidth_is_1()) {
map->write8(map, *((__u8*)buf)++, adr+z);
} else if (cfi_buswidth_is_2()) {
map->write16(map, *((__u16*)buf)++, adr+z);
} else if (cfi_buswidth_is_4()) {
map->write32(map, *((__u32*)buf)++, adr+z);
} else if (cfi_buswidth_is_8()) {
map->write64(map, *((__u64*)buf)++, adr+z);
} else {
DISABLE_VPP(map);
cfi_write(map, CMD(0xff), adr);
return -EINVAL;
}
}
/* GO GO GO */
cfi_write(map, CMD(0xd0), cmd_adr);
timeo = cfi->cfiq->BufWriteTimeoutMax * 1000;
for (; {
status = cfi_read(map, cmd_adr);
if ((status & status_OK) == status_OK)
break;
if (timeo-- < 0) {
printk("Waiting for chip to be ready timed out in bufwrite\n" ;
cfi_write(map, CMD(0xff), adr);
return -EIO;
}
}
/* Done and happy. */
DISABLE_VPP(map);
/* check for lock bit */
if (status & CMD(0x02)) {
/* clear status */
cfi_write(map, CMD(0x50), cmd_adr);
/* put back into read status register mode */
cfi_write(map, CMD(0x70), adr);
cfi_write(map, CMD(0xff), adr);
return -EROFS;
}
cfi_write(map, CMD(0xff), adr);
return 0;
} |
|