can: mcp251xfd: regmap: optimizing transfer size for CRC transfers size 1
authorThomas Kopp <thomas.kopp@microchip.com>
Fri, 27 Jan 2023 12:42:58 +0000 (13:42 +0100)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Thu, 2 Feb 2023 14:42:10 +0000 (15:42 +0100)
For CRC transfers with size 1 it is more efficient to use the
write_safe command instead of the write_crc command. This saves the
length byte on the SPI transfer.

changes since v1: https://lore.kernel.org/all/20230127124258.2764-1-thomas.kopp@microchip.com
- change logic to remove 1 level of indention

Link: https://lore.kernel.org/all/20230202141811.2581795-1-mkl@pengutronix.de
Signed-off-by: Thomas Kopp <thomas.kopp@microchip.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
drivers/net/can/spi/mcp251xfd/mcp251xfd.h

index bf3f0f1..bfe4caa 100644 (file)
@@ -30,11 +30,23 @@ mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv,
        last_byte = mcp251xfd_last_byte_set(mask);
        len = last_byte - first_byte + 1;
 
-       data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte);
+       data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte, len);
        val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte);
        memcpy(data, &val_le32, len);
 
-       if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) {
+       if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)) {
+               len += sizeof(write_reg_buf->nocrc.cmd);
+       } else if (len == 1) {
+               u16 crc;
+
+               /* CRC */
+               len += sizeof(write_reg_buf->safe.cmd);
+               crc = mcp251xfd_crc16_compute(&write_reg_buf->safe, len);
+               put_unaligned_be16(crc, (void *)write_reg_buf + len);
+
+               /* Total length */
+               len += sizeof(write_reg_buf->safe.crc);
+       } else {
                u16 crc;
 
                mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd,
@@ -46,8 +58,6 @@ mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv,
 
                /* Total length */
                len += sizeof(write_reg_buf->crc.crc);
-       } else {
-               len += sizeof(write_reg_buf->nocrc.cmd);
        }
 
        return len;
index 2b0309f..7024ff0 100644 (file)
@@ -504,6 +504,11 @@ union mcp251xfd_write_reg_buf {
                u8 data[4];
                __be16 crc;
        } crc;
+       struct __packed {
+               struct mcp251xfd_buf_cmd cmd;
+               u8 data[1];
+               __be16 crc;
+       } safe;
 } ____cacheline_aligned;
 
 struct mcp251xfd_tx_obj {
@@ -759,6 +764,13 @@ mcp251xfd_spi_cmd_write_crc_set_addr(struct mcp251xfd_buf_cmd_crc *cmd,
 }
 
 static inline void
+mcp251xfd_spi_cmd_write_safe_set_addr(struct mcp251xfd_buf_cmd *cmd,
+                                    u16 addr)
+{
+       cmd->cmd = cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE_CRC_SAFE | addr);
+}
+
+static inline void
 mcp251xfd_spi_cmd_write_crc(struct mcp251xfd_buf_cmd_crc *cmd,
                            u16 addr, u16 len)
 {
@@ -769,14 +781,20 @@ mcp251xfd_spi_cmd_write_crc(struct mcp251xfd_buf_cmd_crc *cmd,
 static inline u8 *
 mcp251xfd_spi_cmd_write(const struct mcp251xfd_priv *priv,
                        union mcp251xfd_write_reg_buf *write_reg_buf,
-                       u16 addr)
+                       u16 addr, u8 len)
 {
        u8 *data;
 
        if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) {
-               mcp251xfd_spi_cmd_write_crc_set_addr(&write_reg_buf->crc.cmd,
-                                                    addr);
-               data = write_reg_buf->crc.data;
+               if (len == 1) {
+                       mcp251xfd_spi_cmd_write_safe_set_addr(&write_reg_buf->safe.cmd,
+                                                            addr);
+                       data = write_reg_buf->safe.data;
+               } else {
+                       mcp251xfd_spi_cmd_write_crc_set_addr(&write_reg_buf->crc.cmd,
+                                                            addr);
+                       data = write_reg_buf->crc.data;
+               }
        } else {
                mcp251xfd_spi_cmd_write_nocrc(&write_reg_buf->nocrc.cmd,
                                              addr);