From: Chen-Yu Tsai <wens@xxxxxxxx> SID cells are 32-bit aligned, and a multiple of 32 bits in length. The only outlier is the thermal sensor calibration data, which is 16 bits per sensor. However a whole 64 bits is allocated for this purpose, so we could consider it conforming to the rule above. Also, the register read-out method assumes native endian, unlike the direct MMIO method, which assumes big endian. Thus no endian conversion is involved. Under these assumptions, the register read-out method can be slightly optimized. Instead of reading one word then discarding 3 bytes, read the whole word directly into the buffer. However, for reads under 4 bytes or trailing bytes, we still use a scratch buffer to extract the requested bytes. We could go one step further if .word_size was 4, but changing that would affect the sysfs interface's behavior. Signed-off-by: Chen-Yu Tsai <wens@xxxxxxxx> --- drivers/nvmem/sunxi_sid.c | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 704c35edf796..15fbfab62595 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -115,36 +115,34 @@ static int sun8i_sid_register_readout(const struct sunxi_sid *sid, * to be not reliable at all. * Read by the registers instead. */ -static int sun8i_sid_read_byte_by_reg(const struct sunxi_sid *sid, - const unsigned int offset, - u8 *out) -{ - u32 word; - int ret; - - ret = sun8i_sid_register_readout(sid, offset & ~0x03, &word); - - if (ret) - return ret; - - *out = (word >> ((offset & 0x3) * 8)) & 0xff; - - return 0; -} - static int sun8i_sid_read_by_reg(void *context, unsigned int offset, void *val, size_t bytes) { struct sunxi_sid *sid = context; - u8 *buf = val; + u32 word; int ret; - while (bytes--) { - ret = sun8i_sid_read_byte_by_reg(sid, offset++, buf++); + /* .stride = 4 so offset is guaranteed to be aligned */ + while (bytes >= 4) { + ret = sun8i_sid_register_readout(sid, offset, val); if (ret) return ret; + + val += 4; + offset += 4; + bytes -= 4; } + if (!bytes) + return 0; + + /* Handle any trailing bytes */ + ret = sun8i_sid_register_readout(sid, offset, &word); + if (ret) + return ret; + + memcpy(val, &word, bytes); + return 0; } -- 2.20.1