nvmem: sunxi_sid: Optimize register read-out method
authorChen-Yu Tsai <wens@csie.org>
Sat, 13 Apr 2019 10:32:50 +0000 (11:32 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Apr 2019 17:43:11 +0000 (19:43 +0200)
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>
drivers/nvmem/sunxi_sid.c

index 704c35edf796c31e824c72c009e2c816c866dbc4..15fbfab62595b652b69b19b7a4721cf4c2c4f27f 100644 (file)
@@ -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;
 }