Skip to content

Commit

Permalink
nvmem: sunxi_sid: Optimize register read-out method
Browse files Browse the repository at this point in the history
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@csie.org>
Acked-by: Maxime Ripard <maxime.ripard@bootlin.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Chen-Yu Tsai authored and Greg Kroah-Hartman committed Apr 25, 2019
1 parent 9c4adfb commit de2a3ea
Showing 1 changed file with 18 additions and 20 deletions.
38 changes: 18 additions & 20 deletions drivers/nvmem/sunxi_sid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down

0 comments on commit de2a3ea

Please sign in to comment.