/* * Check the file size bounds and adjusts count as needed. * This would not be needed if the file size didn't reset to 0 after a write.
*/ staticinline size_t w1_f0d_fix_count(loff_t off, size_t count, size_t size)
{ if (off > size) return 0;
if ((off + count) > size) return size - off;
return count;
}
/* * Read a block from W1 ROM two times and compares the results. * If they are equal they are returned, otherwise the read * is repeated W1_F0D_READ_RETRIES times. * * count must not exceed W1_F0D_READ_MAXLEN.
*/ staticint w1_f0d_readblock(struct w1_slave *sl, int off, int count, char *buf)
{
u8 wrbuf[3];
u8 cmp[W1_F0D_READ_MAXLEN]; int tries = W1_F0D_READ_RETRIES;
do {
wrbuf[0] = W1_F0D_READ_EEPROM;
wrbuf[1] = off & 0x7f;
wrbuf[2] = 0;
todo -= W1_F0D_READ_MAXLEN;
buf += W1_F0D_READ_MAXLEN;
off += W1_F0D_READ_MAXLEN;
}
mutex_unlock(&sl->master->mutex);
return count;
}
/* * Writes to the scratchpad and reads it back for verification. * Then copies the scratchpad to EEPROM. * The data must be aligned at W1_F0D_SCRATCH_SIZE bytes and * must be W1_F0D_SCRATCH_SIZE bytes long. * The master must be locked. * * @param sl The slave structure * @param addr Address for the write * @param len length must be <= (W1_F0D_PAGE_SIZE - (addr & W1_F0D_PAGE_MASK)) * @param data The data to write * @return 0=Success -1=failure
*/ staticint w1_f0d_write(struct w1_slave *sl, int addr, int len, const u8 *data)
{ int tries = W1_F0D_READ_RETRIES;
u8 wrbuf[3];
u8 rdbuf[W1_F0D_SCRATCH_SIZE];
u8 cs;
w1_read_block(sl->master, rdbuf, sizeof(rdbuf)); /* Compare what was read against the data written */ if ((rdbuf[0] != data[0]) || (rdbuf[1] != data[1])) {
if (--tries) goto retry;
dev_err(&sl->dev, "could not write to eeprom, scratchpad compare failed %d times\n",
W1_F0D_READ_RETRIES);
pr_info("%s: rdbuf = %#x %#x data = %#x %#x\n",
__func__, rdbuf[0], rdbuf[1], data[0], data[1]);
return -1;
}
/* Trigger write out to EEPROM */
w1_write_8(sl->master, W1_F0D_RELEASE);
/* Sleep for tprog ms to wait for the write to complete */
msleep(W1_F0D_TPROG_MS);
/* Can only write data in blocks of the size of the scratchpad */
addr = off;
len = count; while (len > 0) {
/* if len too short or addr not aligned */ if (len < W1_F0D_SCRATCH_SIZE || addr & W1_F0D_SCRATCH_MASK) { char tmp[W1_F0D_SCRATCH_SIZE];
/* read the block and update the parts to be written */ if (w1_f0d_readblock(sl, addr & ~W1_F0D_SCRATCH_MASK,
W1_F0D_SCRATCH_SIZE, tmp)) {
count = -EIO; goto out_up;
}
/* copy at most to the boundary of the PAGE or len */
copy = W1_F0D_SCRATCH_SIZE -
(addr & W1_F0D_SCRATCH_MASK);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.