Commit 1f652bb6 authored by Ursula Maplehurst's avatar Ursula Maplehurst Committed by Marc Kleine-Budde

can: mcp25xxfd: rx-path: reduce number of SPI core requests to set UINC bit

Reduce the number of separate SPI core requests when setting the UINC bit in
the RX FIFO, and instead batch them up into a single SPI core request.

Link: https://github.com/marckleinebudde/linux/issues/4
Link: https://lore.kernel.org/r/20201126132144.351154-3-mkl@pengutronix.deTested-by: default avatarThomas Kopp <thomas.kopp@microchip.com>
Signed-off-by: default avatarUrsula Maplehurst <ursula@kangatronix.co.uk>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 4843ad9b
...@@ -332,7 +332,7 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv) ...@@ -332,7 +332,7 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
u32 val; u32 val;
u16 addr; u16 addr;
u8 len; u8 len;
int i; int i, j;
/* TEF */ /* TEF */
priv->tef.head = 0; priv->tef.head = 0;
...@@ -370,6 +370,23 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv) ...@@ -370,6 +370,23 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
prev_rx_ring->obj_num; prev_rx_ring->obj_num;
prev_rx_ring = rx_ring; prev_rx_ring = rx_ring;
/* FIFO increment RX tail pointer */
addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr);
val = MCP251XFD_REG_FIFOCON_UINC;
len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf,
addr, val, val);
for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) {
struct spi_transfer *xfer;
xfer = &rx_ring->uinc_xfer[j];
xfer->tx_buf = &rx_ring->uinc_buf;
xfer->len = len;
xfer->cs_change = 1;
xfer->cs_change_delay.value = 0;
xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
}
} }
} }
...@@ -1440,13 +1457,7 @@ mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv, ...@@ -1440,13 +1457,7 @@ mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv,
if (err) if (err)
stats->rx_fifo_errors++; stats->rx_fifo_errors++;
ring->tail++; return 0;
/* finally increment the RX pointer */
return regmap_update_bits(priv->map_reg,
MCP251XFD_REG_FIFOCON(ring->fifo_nr),
GENMASK(15, 8),
MCP251XFD_REG_FIFOCON_UINC);
} }
static inline int static inline int
...@@ -1478,6 +1489,8 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv, ...@@ -1478,6 +1489,8 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
return err; return err;
while ((len = mcp251xfd_get_rx_linear_len(ring))) { while ((len = mcp251xfd_get_rx_linear_len(ring))) {
struct spi_transfer *last_xfer;
rx_tail = mcp251xfd_get_rx_tail(ring); rx_tail = mcp251xfd_get_rx_tail(ring);
err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj, err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj,
...@@ -1492,6 +1505,28 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv, ...@@ -1492,6 +1505,28 @@ mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
if (err) if (err)
return err; return err;
} }
/* Increment the RX FIFO tail pointer 'len' times in a
* single SPI message.
*/
ring->tail += len;
/* Note:
*
* "cs_change == 1" on the last transfer results in an
* active chip select after the complete SPI
* message. This causes the controller to interpret
* the next register access as data. Temporary set
* "cs_change" of the last transfer to "0" to properly
* deactivate the chip select at the end of the
* message.
*/
last_xfer = &ring->uinc_xfer[len - 1];
last_xfer->cs_change = 0;
err = spi_sync_transfer(priv->spi, ring->uinc_xfer, len);
last_xfer->cs_change = 1;
if (err)
return err;
} }
return 0; return 0;
......
...@@ -528,6 +528,8 @@ struct mcp251xfd_rx_ring { ...@@ -528,6 +528,8 @@ struct mcp251xfd_rx_ring {
u8 obj_num; u8 obj_num;
u8 obj_size; u8 obj_size;
union mcp251xfd_write_reg_buf uinc_buf;
struct spi_transfer uinc_xfer[MCP251XFD_RX_OBJ_NUM_MAX];
struct mcp251xfd_hw_rx_obj_canfd obj[]; struct mcp251xfd_hw_rx_obj_canfd obj[];
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment