xref: /linux/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c (revision bfc64d9b7e8cac82be6b8629865e137d962578f8)
155bc37c8SMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0
255bc37c8SMarc Kleine-Budde //
355bc37c8SMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
455bc37c8SMarc Kleine-Budde //
5*eb9a839bSMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021, 2024 Pengutronix,
655bc37c8SMarc Kleine-Budde //               Marc Kleine-Budde <kernel@pengutronix.de>
755bc37c8SMarc Kleine-Budde //
855bc37c8SMarc Kleine-Budde // Based on:
955bc37c8SMarc Kleine-Budde //
1055bc37c8SMarc Kleine-Budde // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
1155bc37c8SMarc Kleine-Budde //
1255bc37c8SMarc Kleine-Budde // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
1355bc37c8SMarc Kleine-Budde //
1455bc37c8SMarc Kleine-Budde 
155f60d5f6SAl Viro #include <linux/unaligned.h>
1655bc37c8SMarc Kleine-Budde 
1755bc37c8SMarc Kleine-Budde #include "mcp251xfd.h"
189263c2e9SMarc Kleine-Budde #include "mcp251xfd-ram.h"
1955bc37c8SMarc Kleine-Budde 
2055bc37c8SMarc Kleine-Budde static inline u8
mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv * priv,union mcp251xfd_write_reg_buf * write_reg_buf,const u16 reg,const u32 mask,const u32 val)2155bc37c8SMarc Kleine-Budde mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv,
2255bc37c8SMarc Kleine-Budde 				union mcp251xfd_write_reg_buf *write_reg_buf,
2355bc37c8SMarc Kleine-Budde 				const u16 reg, const u32 mask, const u32 val)
2455bc37c8SMarc Kleine-Budde {
2555bc37c8SMarc Kleine-Budde 	u8 first_byte, last_byte, len;
2655bc37c8SMarc Kleine-Budde 	u8 *data;
2755bc37c8SMarc Kleine-Budde 	__le32 val_le32;
2855bc37c8SMarc Kleine-Budde 
2955bc37c8SMarc Kleine-Budde 	first_byte = mcp251xfd_first_byte_set(mask);
3055bc37c8SMarc Kleine-Budde 	last_byte = mcp251xfd_last_byte_set(mask);
3155bc37c8SMarc Kleine-Budde 	len = last_byte - first_byte + 1;
3255bc37c8SMarc Kleine-Budde 
332e8ca20bSThomas Kopp 	data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte, len);
3455bc37c8SMarc Kleine-Budde 	val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte);
3555bc37c8SMarc Kleine-Budde 	memcpy(data, &val_le32, len);
3655bc37c8SMarc Kleine-Budde 
372e8ca20bSThomas Kopp 	if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)) {
382e8ca20bSThomas Kopp 		len += sizeof(write_reg_buf->nocrc.cmd);
392e8ca20bSThomas Kopp 	} else if (len == 1) {
402e8ca20bSThomas Kopp 		u16 crc;
412e8ca20bSThomas Kopp 
422e8ca20bSThomas Kopp 		/* CRC */
432e8ca20bSThomas Kopp 		len += sizeof(write_reg_buf->safe.cmd);
442e8ca20bSThomas Kopp 		crc = mcp251xfd_crc16_compute(&write_reg_buf->safe, len);
452e8ca20bSThomas Kopp 		put_unaligned_be16(crc, (void *)write_reg_buf + len);
462e8ca20bSThomas Kopp 
472e8ca20bSThomas Kopp 		/* Total length */
482e8ca20bSThomas Kopp 		len += sizeof(write_reg_buf->safe.crc);
492e8ca20bSThomas Kopp 	} else {
5055bc37c8SMarc Kleine-Budde 		u16 crc;
5155bc37c8SMarc Kleine-Budde 
5255bc37c8SMarc Kleine-Budde 		mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd,
5355bc37c8SMarc Kleine-Budde 						     len);
5455bc37c8SMarc Kleine-Budde 		/* CRC */
5555bc37c8SMarc Kleine-Budde 		len += sizeof(write_reg_buf->crc.cmd);
5655bc37c8SMarc Kleine-Budde 		crc = mcp251xfd_crc16_compute(&write_reg_buf->crc, len);
5755bc37c8SMarc Kleine-Budde 		put_unaligned_be16(crc, (void *)write_reg_buf + len);
5855bc37c8SMarc Kleine-Budde 
5955bc37c8SMarc Kleine-Budde 		/* Total length */
6055bc37c8SMarc Kleine-Budde 		len += sizeof(write_reg_buf->crc.crc);
6155bc37c8SMarc Kleine-Budde 	}
6255bc37c8SMarc Kleine-Budde 
6355bc37c8SMarc Kleine-Budde 	return len;
6455bc37c8SMarc Kleine-Budde }
6555bc37c8SMarc Kleine-Budde 
66617283b9SMarc Kleine-Budde static void
mcp251xfd_ring_init_tef(struct mcp251xfd_priv * priv,u16 * base)67617283b9SMarc Kleine-Budde mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base)
68d2d5397fSMarc Kleine-Budde {
69d2d5397fSMarc Kleine-Budde 	struct mcp251xfd_tef_ring *tef_ring;
70d2d5397fSMarc Kleine-Budde 	struct spi_transfer *xfer;
71d2d5397fSMarc Kleine-Budde 	u32 val;
72d2d5397fSMarc Kleine-Budde 	u16 addr;
73d2d5397fSMarc Kleine-Budde 	u8 len;
74d2d5397fSMarc Kleine-Budde 	int i;
75d2d5397fSMarc Kleine-Budde 
76d2d5397fSMarc Kleine-Budde 	/* TEF */
77d2d5397fSMarc Kleine-Budde 	tef_ring = priv->tef;
78d2d5397fSMarc Kleine-Budde 	tef_ring->head = 0;
79d2d5397fSMarc Kleine-Budde 	tef_ring->tail = 0;
80d2d5397fSMarc Kleine-Budde 
81617283b9SMarc Kleine-Budde 	/* TEF- and TX-FIFO have same number of objects */
82617283b9SMarc Kleine-Budde 	*base = mcp251xfd_get_tef_obj_addr(priv->tx->obj_num);
83617283b9SMarc Kleine-Budde 
84169d00a2SMarc Kleine-Budde 	/* FIFO IRQ enable */
85169d00a2SMarc Kleine-Budde 	addr = MCP251XFD_REG_TEFCON;
86169d00a2SMarc Kleine-Budde 	val = MCP251XFD_REG_TEFCON_TEFOVIE | MCP251XFD_REG_TEFCON_TEFNEIE;
87169d00a2SMarc Kleine-Budde 
88169d00a2SMarc Kleine-Budde 	len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->irq_enable_buf,
89169d00a2SMarc Kleine-Budde 					      addr, val, val);
90169d00a2SMarc Kleine-Budde 	tef_ring->irq_enable_xfer.tx_buf = &tef_ring->irq_enable_buf;
91169d00a2SMarc Kleine-Budde 	tef_ring->irq_enable_xfer.len = len;
92169d00a2SMarc Kleine-Budde 	spi_message_init_with_transfers(&tef_ring->irq_enable_msg,
93169d00a2SMarc Kleine-Budde 					&tef_ring->irq_enable_xfer, 1);
94169d00a2SMarc Kleine-Budde 
95d2d5397fSMarc Kleine-Budde 	/* FIFO increment TEF tail pointer */
96d2d5397fSMarc Kleine-Budde 	addr = MCP251XFD_REG_TEFCON;
97d2d5397fSMarc Kleine-Budde 	val = MCP251XFD_REG_TEFCON_UINC;
98d2d5397fSMarc Kleine-Budde 	len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf,
99d2d5397fSMarc Kleine-Budde 					      addr, val, val);
100d2d5397fSMarc Kleine-Budde 
101d2d5397fSMarc Kleine-Budde 	for (i = 0; i < ARRAY_SIZE(tef_ring->uinc_xfer); i++) {
102d2d5397fSMarc Kleine-Budde 		xfer = &tef_ring->uinc_xfer[i];
103d2d5397fSMarc Kleine-Budde 		xfer->tx_buf = &tef_ring->uinc_buf;
104d2d5397fSMarc Kleine-Budde 		xfer->len = len;
105d2d5397fSMarc Kleine-Budde 		xfer->cs_change = 1;
106d2d5397fSMarc Kleine-Budde 		xfer->cs_change_delay.value = 0;
107d2d5397fSMarc Kleine-Budde 		xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
108d2d5397fSMarc Kleine-Budde 	}
109d2d5397fSMarc Kleine-Budde 
110d2d5397fSMarc Kleine-Budde 	/* "cs_change == 1" on the last transfer results in an active
111d2d5397fSMarc Kleine-Budde 	 * chip select after the complete SPI message. This causes the
112d2d5397fSMarc Kleine-Budde 	 * controller to interpret the next register access as
113d2d5397fSMarc Kleine-Budde 	 * data. Set "cs_change" of the last transfer to "0" to
114d2d5397fSMarc Kleine-Budde 	 * properly deactivate the chip select at the end of the
115d2d5397fSMarc Kleine-Budde 	 * message.
116d2d5397fSMarc Kleine-Budde 	 */
117d2d5397fSMarc Kleine-Budde 	xfer->cs_change = 0;
118169d00a2SMarc Kleine-Budde 
119169d00a2SMarc Kleine-Budde 	if (priv->tx_coalesce_usecs_irq || priv->tx_obj_num_coalesce_irq) {
120169d00a2SMarc Kleine-Budde 		val = MCP251XFD_REG_TEFCON_UINC |
121169d00a2SMarc Kleine-Budde 			MCP251XFD_REG_TEFCON_TEFOVIE |
122169d00a2SMarc Kleine-Budde 			MCP251XFD_REG_TEFCON_TEFHIE;
123169d00a2SMarc Kleine-Budde 
124169d00a2SMarc Kleine-Budde 		len = mcp251xfd_cmd_prepare_write_reg(priv,
125169d00a2SMarc Kleine-Budde 						      &tef_ring->uinc_irq_disable_buf,
126169d00a2SMarc Kleine-Budde 						      addr, val, val);
127169d00a2SMarc Kleine-Budde 		xfer->tx_buf = &tef_ring->uinc_irq_disable_buf;
128169d00a2SMarc Kleine-Budde 		xfer->len = len;
129169d00a2SMarc Kleine-Budde 	}
130d2d5397fSMarc Kleine-Budde }
131d2d5397fSMarc Kleine-Budde 
13255bc37c8SMarc Kleine-Budde static void
mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv * priv,const struct mcp251xfd_tx_ring * ring,struct mcp251xfd_tx_obj * tx_obj,const u8 rts_buf_len,const u8 n)13355bc37c8SMarc Kleine-Budde mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv,
13455bc37c8SMarc Kleine-Budde 			      const struct mcp251xfd_tx_ring *ring,
13555bc37c8SMarc Kleine-Budde 			      struct mcp251xfd_tx_obj *tx_obj,
13655bc37c8SMarc Kleine-Budde 			      const u8 rts_buf_len,
13755bc37c8SMarc Kleine-Budde 			      const u8 n)
13855bc37c8SMarc Kleine-Budde {
13955bc37c8SMarc Kleine-Budde 	struct spi_transfer *xfer;
14055bc37c8SMarc Kleine-Budde 	u16 addr;
14155bc37c8SMarc Kleine-Budde 
14255bc37c8SMarc Kleine-Budde 	/* FIFO load */
14355bc37c8SMarc Kleine-Budde 	addr = mcp251xfd_get_tx_obj_addr(ring, n);
14455bc37c8SMarc Kleine-Budde 	if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX)
14555bc37c8SMarc Kleine-Budde 		mcp251xfd_spi_cmd_write_crc_set_addr(&tx_obj->buf.crc.cmd,
14655bc37c8SMarc Kleine-Budde 						     addr);
14755bc37c8SMarc Kleine-Budde 	else
14855bc37c8SMarc Kleine-Budde 		mcp251xfd_spi_cmd_write_nocrc(&tx_obj->buf.nocrc.cmd,
14955bc37c8SMarc Kleine-Budde 					      addr);
15055bc37c8SMarc Kleine-Budde 
15155bc37c8SMarc Kleine-Budde 	xfer = &tx_obj->xfer[0];
15255bc37c8SMarc Kleine-Budde 	xfer->tx_buf = &tx_obj->buf;
15355bc37c8SMarc Kleine-Budde 	xfer->len = 0;	/* actual len is assigned on the fly */
15455bc37c8SMarc Kleine-Budde 	xfer->cs_change = 1;
15555bc37c8SMarc Kleine-Budde 	xfer->cs_change_delay.value = 0;
15655bc37c8SMarc Kleine-Budde 	xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
15755bc37c8SMarc Kleine-Budde 
15855bc37c8SMarc Kleine-Budde 	/* FIFO request to send */
15955bc37c8SMarc Kleine-Budde 	xfer = &tx_obj->xfer[1];
16055bc37c8SMarc Kleine-Budde 	xfer->tx_buf = &ring->rts_buf;
16155bc37c8SMarc Kleine-Budde 	xfer->len = rts_buf_len;
16255bc37c8SMarc Kleine-Budde 
16355bc37c8SMarc Kleine-Budde 	/* SPI message */
16455bc37c8SMarc Kleine-Budde 	spi_message_init_with_transfers(&tx_obj->msg, tx_obj->xfer,
16555bc37c8SMarc Kleine-Budde 					ARRAY_SIZE(tx_obj->xfer));
16655bc37c8SMarc Kleine-Budde }
16755bc37c8SMarc Kleine-Budde 
168617283b9SMarc Kleine-Budde static void
mcp251xfd_ring_init_tx(struct mcp251xfd_priv * priv,u16 * base,u8 * fifo_nr)169617283b9SMarc Kleine-Budde mcp251xfd_ring_init_tx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr)
17055bc37c8SMarc Kleine-Budde {
17155bc37c8SMarc Kleine-Budde 	struct mcp251xfd_tx_ring *tx_ring;
17255bc37c8SMarc Kleine-Budde 	struct mcp251xfd_tx_obj *tx_obj;
17355bc37c8SMarc Kleine-Budde 	u32 val;
17455bc37c8SMarc Kleine-Budde 	u16 addr;
17555bc37c8SMarc Kleine-Budde 	u8 len;
176d2d5397fSMarc Kleine-Budde 	int i;
17755bc37c8SMarc Kleine-Budde 
17855bc37c8SMarc Kleine-Budde 	tx_ring = priv->tx;
17955bc37c8SMarc Kleine-Budde 	tx_ring->head = 0;
18055bc37c8SMarc Kleine-Budde 	tx_ring->tail = 0;
181617283b9SMarc Kleine-Budde 	tx_ring->base = *base;
182c912f19eSMarc Kleine-Budde 	tx_ring->nr = 0;
183617283b9SMarc Kleine-Budde 	tx_ring->fifo_nr = *fifo_nr;
184617283b9SMarc Kleine-Budde 
185617283b9SMarc Kleine-Budde 	*base = mcp251xfd_get_tx_obj_addr(tx_ring, tx_ring->obj_num);
186617283b9SMarc Kleine-Budde 	*fifo_nr += 1;
18755bc37c8SMarc Kleine-Budde 
18855bc37c8SMarc Kleine-Budde 	/* FIFO request to send */
189c912f19eSMarc Kleine-Budde 	addr = MCP251XFD_REG_FIFOCON(tx_ring->fifo_nr);
19055bc37c8SMarc Kleine-Budde 	val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC;
19155bc37c8SMarc Kleine-Budde 	len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf,
19255bc37c8SMarc Kleine-Budde 					      addr, val, val);
19355bc37c8SMarc Kleine-Budde 
19455bc37c8SMarc Kleine-Budde 	mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i)
19555bc37c8SMarc Kleine-Budde 		mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i);
196d2d5397fSMarc Kleine-Budde }
19755bc37c8SMarc Kleine-Budde 
198617283b9SMarc Kleine-Budde static void
mcp251xfd_ring_init_rx(struct mcp251xfd_priv * priv,u16 * base,u8 * fifo_nr)199617283b9SMarc Kleine-Budde mcp251xfd_ring_init_rx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr)
200d2d5397fSMarc Kleine-Budde {
201617283b9SMarc Kleine-Budde 	struct mcp251xfd_rx_ring *rx_ring;
202d2d5397fSMarc Kleine-Budde 	struct spi_transfer *xfer;
203d2d5397fSMarc Kleine-Budde 	u32 val;
204d2d5397fSMarc Kleine-Budde 	u16 addr;
205d2d5397fSMarc Kleine-Budde 	u8 len;
206d2d5397fSMarc Kleine-Budde 	int i, j;
207d2d5397fSMarc Kleine-Budde 
20855bc37c8SMarc Kleine-Budde 	mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
20924436be5SMarc Kleine-Budde 		rx_ring->last_valid = timecounter_read(&priv->tc);
21055bc37c8SMarc Kleine-Budde 		rx_ring->head = 0;
21155bc37c8SMarc Kleine-Budde 		rx_ring->tail = 0;
212617283b9SMarc Kleine-Budde 		rx_ring->base = *base;
21355bc37c8SMarc Kleine-Budde 		rx_ring->nr = i;
214617283b9SMarc Kleine-Budde 		rx_ring->fifo_nr = *fifo_nr;
21555bc37c8SMarc Kleine-Budde 
216617283b9SMarc Kleine-Budde 		*base = mcp251xfd_get_rx_obj_addr(rx_ring, rx_ring->obj_num);
217617283b9SMarc Kleine-Budde 		*fifo_nr += 1;
21855bc37c8SMarc Kleine-Budde 
21960a848c5SMarc Kleine-Budde 		/* FIFO IRQ enable */
22055bc37c8SMarc Kleine-Budde 		addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr);
22160a848c5SMarc Kleine-Budde 		val = MCP251XFD_REG_FIFOCON_RXOVIE |
22260a848c5SMarc Kleine-Budde 			MCP251XFD_REG_FIFOCON_TFNRFNIE;
22360a848c5SMarc Kleine-Budde 		len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->irq_enable_buf,
22460a848c5SMarc Kleine-Budde 						      addr, val, val);
22560a848c5SMarc Kleine-Budde 		rx_ring->irq_enable_xfer.tx_buf = &rx_ring->irq_enable_buf;
22660a848c5SMarc Kleine-Budde 		rx_ring->irq_enable_xfer.len = len;
22760a848c5SMarc Kleine-Budde 		spi_message_init_with_transfers(&rx_ring->irq_enable_msg,
22860a848c5SMarc Kleine-Budde 						&rx_ring->irq_enable_xfer, 1);
22960a848c5SMarc Kleine-Budde 
23060a848c5SMarc Kleine-Budde 		/* FIFO increment RX tail pointer */
23155bc37c8SMarc Kleine-Budde 		val = MCP251XFD_REG_FIFOCON_UINC;
23255bc37c8SMarc Kleine-Budde 		len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf,
23355bc37c8SMarc Kleine-Budde 						      addr, val, val);
23455bc37c8SMarc Kleine-Budde 
23555bc37c8SMarc Kleine-Budde 		for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) {
23655bc37c8SMarc Kleine-Budde 			xfer = &rx_ring->uinc_xfer[j];
23755bc37c8SMarc Kleine-Budde 			xfer->tx_buf = &rx_ring->uinc_buf;
23855bc37c8SMarc Kleine-Budde 			xfer->len = len;
23955bc37c8SMarc Kleine-Budde 			xfer->cs_change = 1;
24055bc37c8SMarc Kleine-Budde 			xfer->cs_change_delay.value = 0;
24155bc37c8SMarc Kleine-Budde 			xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
24255bc37c8SMarc Kleine-Budde 		}
24355bc37c8SMarc Kleine-Budde 
24455bc37c8SMarc Kleine-Budde 		/* "cs_change == 1" on the last transfer results in an
24555bc37c8SMarc Kleine-Budde 		 * active chip select after the complete SPI
24655bc37c8SMarc Kleine-Budde 		 * message. This causes the controller to interpret
24755bc37c8SMarc Kleine-Budde 		 * the next register access as data. Set "cs_change"
24855bc37c8SMarc Kleine-Budde 		 * of the last transfer to "0" to properly deactivate
24955bc37c8SMarc Kleine-Budde 		 * the chip select at the end of the message.
25055bc37c8SMarc Kleine-Budde 		 */
25155bc37c8SMarc Kleine-Budde 		xfer->cs_change = 0;
25260a848c5SMarc Kleine-Budde 
25360a848c5SMarc Kleine-Budde 		/* Use 1st RX-FIFO for IRQ coalescing. If enabled
25460a848c5SMarc Kleine-Budde 		 * (rx_coalesce_usecs_irq or rx_max_coalesce_frames_irq
25560a848c5SMarc Kleine-Budde 		 * is activated), use the last transfer to disable:
25660a848c5SMarc Kleine-Budde 		 *
25760a848c5SMarc Kleine-Budde 		 * - TFNRFNIE (Receive FIFO Not Empty Interrupt)
25860a848c5SMarc Kleine-Budde 		 *
25960a848c5SMarc Kleine-Budde 		 * and enable:
26060a848c5SMarc Kleine-Budde 		 *
26160a848c5SMarc Kleine-Budde 		 * - TFHRFHIE (Receive FIFO Half Full Interrupt)
26260a848c5SMarc Kleine-Budde 		 *   - or -
26360a848c5SMarc Kleine-Budde 		 * - TFERFFIE (Receive FIFO Full Interrupt)
26460a848c5SMarc Kleine-Budde 		 *
26560a848c5SMarc Kleine-Budde 		 * depending on rx_max_coalesce_frames_irq.
26660a848c5SMarc Kleine-Budde 		 *
26760a848c5SMarc Kleine-Budde 		 * The RXOVIE (Overflow Interrupt) is always enabled.
26860a848c5SMarc Kleine-Budde 		 */
26960a848c5SMarc Kleine-Budde 		if (rx_ring->nr == 0 && (priv->rx_coalesce_usecs_irq ||
27060a848c5SMarc Kleine-Budde 					 priv->rx_obj_num_coalesce_irq)) {
27160a848c5SMarc Kleine-Budde 			val = MCP251XFD_REG_FIFOCON_UINC |
27260a848c5SMarc Kleine-Budde 				MCP251XFD_REG_FIFOCON_RXOVIE;
27360a848c5SMarc Kleine-Budde 
27460a848c5SMarc Kleine-Budde 			if (priv->rx_obj_num_coalesce_irq == rx_ring->obj_num)
27560a848c5SMarc Kleine-Budde 				val |= MCP251XFD_REG_FIFOCON_TFERFFIE;
27660a848c5SMarc Kleine-Budde 			else if (priv->rx_obj_num_coalesce_irq)
27760a848c5SMarc Kleine-Budde 				val |= MCP251XFD_REG_FIFOCON_TFHRFHIE;
27860a848c5SMarc Kleine-Budde 
27960a848c5SMarc Kleine-Budde 			len = mcp251xfd_cmd_prepare_write_reg(priv,
28060a848c5SMarc Kleine-Budde 							      &rx_ring->uinc_irq_disable_buf,
28160a848c5SMarc Kleine-Budde 							      addr, val, val);
28260a848c5SMarc Kleine-Budde 			xfer->tx_buf = &rx_ring->uinc_irq_disable_buf;
28360a848c5SMarc Kleine-Budde 			xfer->len = len;
28460a848c5SMarc Kleine-Budde 		}
28555bc37c8SMarc Kleine-Budde 	}
28655bc37c8SMarc Kleine-Budde }
28755bc37c8SMarc Kleine-Budde 
mcp251xfd_ring_init(struct mcp251xfd_priv * priv)288fa0b68dfSMarc Kleine-Budde int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
289d2d5397fSMarc Kleine-Budde {
29083daa863SMarc Kleine-Budde 	const struct mcp251xfd_rx_ring *rx_ring;
291fa0b68dfSMarc Kleine-Budde 	u16 base = 0, ram_used;
292617283b9SMarc Kleine-Budde 	u8 fifo_nr = 1;
293ac2b81ebSMarc Kleine-Budde 	int err = 0, i;
294617283b9SMarc Kleine-Budde 
295d2d5397fSMarc Kleine-Budde 	netdev_reset_queue(priv->ndev);
296d2d5397fSMarc Kleine-Budde 
297617283b9SMarc Kleine-Budde 	mcp251xfd_ring_init_tef(priv, &base);
298617283b9SMarc Kleine-Budde 	mcp251xfd_ring_init_rx(priv, &base, &fifo_nr);
29962713f0dSMarc Kleine-Budde 	mcp251xfd_ring_init_tx(priv, &base, &fifo_nr);
300fa0b68dfSMarc Kleine-Budde 
301887e359dSMarc Kleine-Budde 	/* mcp251xfd_handle_rxif() will iterate over all RX rings.
302887e359dSMarc Kleine-Budde 	 * Rings with their corresponding bit set in
303887e359dSMarc Kleine-Budde 	 * priv->regs_status.rxif are read out.
304887e359dSMarc Kleine-Budde 	 *
305887e359dSMarc Kleine-Budde 	 * If the chip is configured for only 1 RX-FIFO, and if there
306887e359dSMarc Kleine-Budde 	 * is an RX interrupt pending (RXIF in INT register is set),
307887e359dSMarc Kleine-Budde 	 * it must be the 1st RX-FIFO.
308887e359dSMarc Kleine-Budde 	 *
309887e359dSMarc Kleine-Budde 	 * We mark the RXIF of the 1st FIFO as pending here, so that
310887e359dSMarc Kleine-Budde 	 * we can skip the read of the RXIF register in
311887e359dSMarc Kleine-Budde 	 * mcp251xfd_read_regs_status() for the 1 RX-FIFO only case.
312887e359dSMarc Kleine-Budde 	 *
313887e359dSMarc Kleine-Budde 	 * If we use more than 1 RX-FIFO, this value gets overwritten
314887e359dSMarc Kleine-Budde 	 * in mcp251xfd_read_regs_status(), so set it unconditionally
315887e359dSMarc Kleine-Budde 	 * here.
316887e359dSMarc Kleine-Budde 	 */
317887e359dSMarc Kleine-Budde 	priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr);
318887e359dSMarc Kleine-Budde 
319169d00a2SMarc Kleine-Budde 	if (priv->tx_obj_num_coalesce_irq) {
320169d00a2SMarc Kleine-Budde 		netdev_dbg(priv->ndev,
321169d00a2SMarc Kleine-Budde 			   "FIFO setup: TEF:         0x%03x: %2d*%zu bytes = %4zu bytes (coalesce)\n",
322169d00a2SMarc Kleine-Budde 			   mcp251xfd_get_tef_obj_addr(0),
323169d00a2SMarc Kleine-Budde 			   priv->tx_obj_num_coalesce_irq,
324169d00a2SMarc Kleine-Budde 			   sizeof(struct mcp251xfd_hw_tef_obj),
325169d00a2SMarc Kleine-Budde 			   priv->tx_obj_num_coalesce_irq *
326169d00a2SMarc Kleine-Budde 			   sizeof(struct mcp251xfd_hw_tef_obj));
327169d00a2SMarc Kleine-Budde 
328169d00a2SMarc Kleine-Budde 		netdev_dbg(priv->ndev,
329169d00a2SMarc Kleine-Budde 			   "                         0x%03x: %2d*%zu bytes = %4zu bytes\n",
330169d00a2SMarc Kleine-Budde 			   mcp251xfd_get_tef_obj_addr(priv->tx_obj_num_coalesce_irq),
331169d00a2SMarc Kleine-Budde 			   priv->tx->obj_num - priv->tx_obj_num_coalesce_irq,
332169d00a2SMarc Kleine-Budde 			   sizeof(struct mcp251xfd_hw_tef_obj),
333169d00a2SMarc Kleine-Budde 			   (priv->tx->obj_num - priv->tx_obj_num_coalesce_irq) *
334169d00a2SMarc Kleine-Budde 			   sizeof(struct mcp251xfd_hw_tef_obj));
335169d00a2SMarc Kleine-Budde 	} else {
33683daa863SMarc Kleine-Budde 		netdev_dbg(priv->ndev,
33783daa863SMarc Kleine-Budde 			   "FIFO setup: TEF:         0x%03x: %2d*%zu bytes = %4zu bytes\n",
33883daa863SMarc Kleine-Budde 			   mcp251xfd_get_tef_obj_addr(0),
33983daa863SMarc Kleine-Budde 			   priv->tx->obj_num, sizeof(struct mcp251xfd_hw_tef_obj),
34083daa863SMarc Kleine-Budde 			   priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj));
341169d00a2SMarc Kleine-Budde 	}
34283daa863SMarc Kleine-Budde 
34383daa863SMarc Kleine-Budde 	mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
34460a848c5SMarc Kleine-Budde 		if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) {
34560a848c5SMarc Kleine-Budde 			netdev_dbg(priv->ndev,
34660a848c5SMarc Kleine-Budde 				   "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes (coalesce)\n",
34760a848c5SMarc Kleine-Budde 				   rx_ring->nr, rx_ring->fifo_nr,
34860a848c5SMarc Kleine-Budde 				   mcp251xfd_get_rx_obj_addr(rx_ring, 0),
34960a848c5SMarc Kleine-Budde 				   priv->rx_obj_num_coalesce_irq, rx_ring->obj_size,
35060a848c5SMarc Kleine-Budde 				   priv->rx_obj_num_coalesce_irq * rx_ring->obj_size);
35160a848c5SMarc Kleine-Budde 
35260a848c5SMarc Kleine-Budde 			if (priv->rx_obj_num_coalesce_irq == MCP251XFD_FIFO_DEPTH)
35360a848c5SMarc Kleine-Budde 				continue;
35460a848c5SMarc Kleine-Budde 
35560a848c5SMarc Kleine-Budde 			netdev_dbg(priv->ndev,
35660a848c5SMarc Kleine-Budde 				   "                         0x%03x: %2u*%u bytes = %4u bytes\n",
35760a848c5SMarc Kleine-Budde 				   mcp251xfd_get_rx_obj_addr(rx_ring,
35860a848c5SMarc Kleine-Budde 							     priv->rx_obj_num_coalesce_irq),
35960a848c5SMarc Kleine-Budde 				   rx_ring->obj_num - priv->rx_obj_num_coalesce_irq,
36060a848c5SMarc Kleine-Budde 				   rx_ring->obj_size,
36160a848c5SMarc Kleine-Budde 				   (rx_ring->obj_num - priv->rx_obj_num_coalesce_irq) *
36260a848c5SMarc Kleine-Budde 				   rx_ring->obj_size);
36360a848c5SMarc Kleine-Budde 		} else {
36483daa863SMarc Kleine-Budde 			netdev_dbg(priv->ndev,
36583daa863SMarc Kleine-Budde 				   "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
36683daa863SMarc Kleine-Budde 				   rx_ring->nr, rx_ring->fifo_nr,
36783daa863SMarc Kleine-Budde 				   mcp251xfd_get_rx_obj_addr(rx_ring, 0),
36883daa863SMarc Kleine-Budde 				   rx_ring->obj_num, rx_ring->obj_size,
36983daa863SMarc Kleine-Budde 				   rx_ring->obj_num * rx_ring->obj_size);
37083daa863SMarc Kleine-Budde 		}
37160a848c5SMarc Kleine-Budde 	}
37283daa863SMarc Kleine-Budde 
37383daa863SMarc Kleine-Budde 	netdev_dbg(priv->ndev,
37483daa863SMarc Kleine-Budde 		   "FIFO setup: TX:   FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
37583daa863SMarc Kleine-Budde 		   priv->tx->fifo_nr,
37683daa863SMarc Kleine-Budde 		   mcp251xfd_get_tx_obj_addr(priv->tx, 0),
37783daa863SMarc Kleine-Budde 		   priv->tx->obj_num, priv->tx->obj_size,
37883daa863SMarc Kleine-Budde 		   priv->tx->obj_num * priv->tx->obj_size);
37983daa863SMarc Kleine-Budde 
38083daa863SMarc Kleine-Budde 	netdev_dbg(priv->ndev,
381c47675b1SMarc Kleine-Budde 		   "FIFO setup: free:                             %4d bytes\n",
38283daa863SMarc Kleine-Budde 		   MCP251XFD_RAM_SIZE - (base - MCP251XFD_RAM_START));
38383daa863SMarc Kleine-Budde 
384fa0b68dfSMarc Kleine-Budde 	ram_used = base - MCP251XFD_RAM_START;
385fa0b68dfSMarc Kleine-Budde 	if (ram_used > MCP251XFD_RAM_SIZE) {
386fa0b68dfSMarc Kleine-Budde 		netdev_err(priv->ndev,
387fa0b68dfSMarc Kleine-Budde 			   "Error during ring configuration, using more RAM (%u bytes) than available (%u bytes).\n",
388fa0b68dfSMarc Kleine-Budde 			   ram_used, MCP251XFD_RAM_SIZE);
389ac2b81ebSMarc Kleine-Budde 		err = -ENOMEM;
390fa0b68dfSMarc Kleine-Budde 	}
391fa0b68dfSMarc Kleine-Budde 
392ac2b81ebSMarc Kleine-Budde 	if (priv->tx_obj_num_coalesce_irq &&
393ac2b81ebSMarc Kleine-Budde 	    priv->tx_obj_num_coalesce_irq * 2 != priv->tx->obj_num) {
394ac2b81ebSMarc Kleine-Budde 		netdev_err(priv->ndev,
395ac2b81ebSMarc Kleine-Budde 			   "Error during ring configuration, number of TEF coalescing buffers (%u) must be half of TEF buffers (%u).\n",
396ac2b81ebSMarc Kleine-Budde 			   priv->tx_obj_num_coalesce_irq, priv->tx->obj_num);
397ac2b81ebSMarc Kleine-Budde 		err = -EINVAL;
398ac2b81ebSMarc Kleine-Budde 	}
399ac2b81ebSMarc Kleine-Budde 
400ac2b81ebSMarc Kleine-Budde 	return err;
401d2d5397fSMarc Kleine-Budde }
402d2d5397fSMarc Kleine-Budde 
mcp251xfd_ring_free(struct mcp251xfd_priv * priv)40355bc37c8SMarc Kleine-Budde void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
40455bc37c8SMarc Kleine-Budde {
40555bc37c8SMarc Kleine-Budde 	int i;
40655bc37c8SMarc Kleine-Budde 
40755bc37c8SMarc Kleine-Budde 	for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) {
40855bc37c8SMarc Kleine-Budde 		kfree(priv->rx[i]);
40955bc37c8SMarc Kleine-Budde 		priv->rx[i] = NULL;
41055bc37c8SMarc Kleine-Budde 	}
41155bc37c8SMarc Kleine-Budde }
41255bc37c8SMarc Kleine-Budde 
mcp251xfd_rx_irq_timer(struct hrtimer * t)41360a848c5SMarc Kleine-Budde static enum hrtimer_restart mcp251xfd_rx_irq_timer(struct hrtimer *t)
41460a848c5SMarc Kleine-Budde {
41560a848c5SMarc Kleine-Budde 	struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv,
41660a848c5SMarc Kleine-Budde 						   rx_irq_timer);
41760a848c5SMarc Kleine-Budde 	struct mcp251xfd_rx_ring *ring = priv->rx[0];
41860a848c5SMarc Kleine-Budde 
41960a848c5SMarc Kleine-Budde 	if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags))
42060a848c5SMarc Kleine-Budde 		return HRTIMER_NORESTART;
42160a848c5SMarc Kleine-Budde 
42260a848c5SMarc Kleine-Budde 	spi_async(priv->spi, &ring->irq_enable_msg);
42360a848c5SMarc Kleine-Budde 
42460a848c5SMarc Kleine-Budde 	return HRTIMER_NORESTART;
42560a848c5SMarc Kleine-Budde }
42660a848c5SMarc Kleine-Budde 
mcp251xfd_tx_irq_timer(struct hrtimer * t)427169d00a2SMarc Kleine-Budde static enum hrtimer_restart mcp251xfd_tx_irq_timer(struct hrtimer *t)
428169d00a2SMarc Kleine-Budde {
429169d00a2SMarc Kleine-Budde 	struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv,
430169d00a2SMarc Kleine-Budde 						   tx_irq_timer);
431169d00a2SMarc Kleine-Budde 	struct mcp251xfd_tef_ring *ring = priv->tef;
432169d00a2SMarc Kleine-Budde 
433169d00a2SMarc Kleine-Budde 	if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags))
434169d00a2SMarc Kleine-Budde 		return HRTIMER_NORESTART;
435169d00a2SMarc Kleine-Budde 
436169d00a2SMarc Kleine-Budde 	spi_async(priv->spi, &ring->irq_enable_msg);
437169d00a2SMarc Kleine-Budde 
438169d00a2SMarc Kleine-Budde 	return HRTIMER_NORESTART;
439169d00a2SMarc Kleine-Budde }
440169d00a2SMarc Kleine-Budde 
4419263c2e9SMarc Kleine-Budde const struct can_ram_config mcp251xfd_ram_config = {
4429263c2e9SMarc Kleine-Budde 	.rx = {
4439263c2e9SMarc Kleine-Budde 		.size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_rx_obj_can),
4449263c2e9SMarc Kleine-Budde 		.size[CAN_RAM_MODE_CANFD] = sizeof(struct mcp251xfd_hw_rx_obj_canfd),
4459263c2e9SMarc Kleine-Budde 		.min = MCP251XFD_RX_OBJ_NUM_MIN,
4469263c2e9SMarc Kleine-Budde 		.max = MCP251XFD_RX_OBJ_NUM_MAX,
4479263c2e9SMarc Kleine-Budde 		.def[CAN_RAM_MODE_CAN] = CAN_RAM_NUM_MAX,
4489263c2e9SMarc Kleine-Budde 		.def[CAN_RAM_MODE_CANFD] = CAN_RAM_NUM_MAX,
4499263c2e9SMarc Kleine-Budde 		.fifo_num = MCP251XFD_FIFO_RX_NUM,
4509263c2e9SMarc Kleine-Budde 		.fifo_depth_min = MCP251XFD_RX_FIFO_DEPTH_MIN,
451846990e0SMarc Kleine-Budde 		.fifo_depth_coalesce_min = MCP251XFD_RX_FIFO_DEPTH_COALESCE_MIN,
4529263c2e9SMarc Kleine-Budde 	},
4539263c2e9SMarc Kleine-Budde 	.tx = {
4549263c2e9SMarc Kleine-Budde 		.size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_tef_obj) +
4559263c2e9SMarc Kleine-Budde 			sizeof(struct mcp251xfd_hw_tx_obj_can),
4569263c2e9SMarc Kleine-Budde 		.size[CAN_RAM_MODE_CANFD] = sizeof(struct mcp251xfd_hw_tef_obj) +
4579263c2e9SMarc Kleine-Budde 			sizeof(struct mcp251xfd_hw_tx_obj_canfd),
4589263c2e9SMarc Kleine-Budde 		.min = MCP251XFD_TX_OBJ_NUM_MIN,
4599263c2e9SMarc Kleine-Budde 		.max = MCP251XFD_TX_OBJ_NUM_MAX,
4609263c2e9SMarc Kleine-Budde 		.def[CAN_RAM_MODE_CAN] = MCP251XFD_TX_OBJ_NUM_CAN_DEFAULT,
4619263c2e9SMarc Kleine-Budde 		.def[CAN_RAM_MODE_CANFD] = MCP251XFD_TX_OBJ_NUM_CANFD_DEFAULT,
4629263c2e9SMarc Kleine-Budde 		.fifo_num = MCP251XFD_FIFO_TX_NUM,
4639263c2e9SMarc Kleine-Budde 		.fifo_depth_min = MCP251XFD_TX_FIFO_DEPTH_MIN,
464656fc12dSMarc Kleine-Budde 		.fifo_depth_coalesce_min = MCP251XFD_TX_FIFO_DEPTH_COALESCE_MIN,
4659263c2e9SMarc Kleine-Budde 	},
4669263c2e9SMarc Kleine-Budde 	.size = MCP251XFD_RAM_SIZE,
4679263c2e9SMarc Kleine-Budde 	.fifo_depth = MCP251XFD_FIFO_DEPTH,
4689263c2e9SMarc Kleine-Budde };
4699263c2e9SMarc Kleine-Budde 
mcp251xfd_ring_alloc(struct mcp251xfd_priv * priv)47055bc37c8SMarc Kleine-Budde int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
47155bc37c8SMarc Kleine-Budde {
4729263c2e9SMarc Kleine-Budde 	const bool fd_mode = mcp251xfd_is_fd_mode(priv);
4739263c2e9SMarc Kleine-Budde 	struct mcp251xfd_tx_ring *tx_ring = priv->tx;
47455bc37c8SMarc Kleine-Budde 	struct mcp251xfd_rx_ring *rx_ring;
4759263c2e9SMarc Kleine-Budde 	u8 tx_obj_size, rx_obj_size;
4760a1f2e65SMarc Kleine-Budde 	u8 rem, i;
47755bc37c8SMarc Kleine-Budde 
4789263c2e9SMarc Kleine-Budde 	/* switching from CAN-2.0 to CAN-FD mode or vice versa */
4799263c2e9SMarc Kleine-Budde 	if (fd_mode != test_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags)) {
48050ea5449SMarc Kleine-Budde 		const struct ethtool_ringparam ring = {
48150ea5449SMarc Kleine-Budde 			.rx_pending = priv->rx_obj_num,
48250ea5449SMarc Kleine-Budde 			.tx_pending = priv->tx->obj_num,
48350ea5449SMarc Kleine-Budde 		};
48450ea5449SMarc Kleine-Budde 		const struct ethtool_coalesce ec = {
48550ea5449SMarc Kleine-Budde 			.rx_coalesce_usecs_irq = priv->rx_coalesce_usecs_irq,
486*eb9a839bSMarc Kleine-Budde 			.rx_max_coalesced_frames_irq = priv->rx_obj_num_coalesce_irq == 0 ?
487*eb9a839bSMarc Kleine-Budde 				1 : priv->rx_obj_num_coalesce_irq,
48850ea5449SMarc Kleine-Budde 			.tx_coalesce_usecs_irq = priv->tx_coalesce_usecs_irq,
489*eb9a839bSMarc Kleine-Budde 			.tx_max_coalesced_frames_irq = priv->tx_obj_num_coalesce_irq == 0 ?
490*eb9a839bSMarc Kleine-Budde 				1 : priv->tx_obj_num_coalesce_irq,
49150ea5449SMarc Kleine-Budde 		};
4929263c2e9SMarc Kleine-Budde 		struct can_ram_layout layout;
4939263c2e9SMarc Kleine-Budde 
49450ea5449SMarc Kleine-Budde 		can_ram_get_layout(&layout, &mcp251xfd_ram_config, &ring, &ec, fd_mode);
49550ea5449SMarc Kleine-Budde 
49650ea5449SMarc Kleine-Budde 		priv->rx_obj_num = layout.cur_rx;
49750ea5449SMarc Kleine-Budde 		priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;
49850ea5449SMarc Kleine-Budde 
49950ea5449SMarc Kleine-Budde 		tx_ring->obj_num = layout.cur_tx;
50050ea5449SMarc Kleine-Budde 		priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;
50155bc37c8SMarc Kleine-Budde 	}
50255bc37c8SMarc Kleine-Budde 
5039263c2e9SMarc Kleine-Budde 	if (fd_mode) {
5049263c2e9SMarc Kleine-Budde 		tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd);
5059263c2e9SMarc Kleine-Budde 		rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd);
5069263c2e9SMarc Kleine-Budde 		set_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
5079263c2e9SMarc Kleine-Budde 	} else {
5089263c2e9SMarc Kleine-Budde 		tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can);
5099263c2e9SMarc Kleine-Budde 		rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can);
5109263c2e9SMarc Kleine-Budde 		clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
5119263c2e9SMarc Kleine-Budde 	}
512d86ba8dbSMarc Kleine-Budde 
513b8e0ddd3SMarc Kleine-Budde 	tx_ring->obj_num_shift_to_u8 = BITS_PER_TYPE(tx_ring->obj_num) -
514b8e0ddd3SMarc Kleine-Budde 		ilog2(tx_ring->obj_num);
51555bc37c8SMarc Kleine-Budde 	tx_ring->obj_size = tx_obj_size;
51655bc37c8SMarc Kleine-Budde 
5179263c2e9SMarc Kleine-Budde 	rem = priv->rx_obj_num;
5180a1f2e65SMarc Kleine-Budde 	for (i = 0; i < ARRAY_SIZE(priv->rx) && rem; i++) {
5190a1f2e65SMarc Kleine-Budde 		u8 rx_obj_num;
52055bc37c8SMarc Kleine-Budde 
52160a848c5SMarc Kleine-Budde 		if (i == 0 && priv->rx_obj_num_coalesce_irq)
52260a848c5SMarc Kleine-Budde 			rx_obj_num = min_t(u8, priv->rx_obj_num_coalesce_irq * 2,
52360a848c5SMarc Kleine-Budde 					   MCP251XFD_FIFO_DEPTH);
52460a848c5SMarc Kleine-Budde 		else
5250a1f2e65SMarc Kleine-Budde 			rx_obj_num = min_t(u8, rounddown_pow_of_two(rem),
5260a1f2e65SMarc Kleine-Budde 					   MCP251XFD_FIFO_DEPTH);
5270a1f2e65SMarc Kleine-Budde 		rem -= rx_obj_num;
52855bc37c8SMarc Kleine-Budde 
52955bc37c8SMarc Kleine-Budde 		rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
53055bc37c8SMarc Kleine-Budde 				  GFP_KERNEL);
53155bc37c8SMarc Kleine-Budde 		if (!rx_ring) {
53255bc37c8SMarc Kleine-Budde 			mcp251xfd_ring_free(priv);
53355bc37c8SMarc Kleine-Budde 			return -ENOMEM;
53455bc37c8SMarc Kleine-Budde 		}
5350a1f2e65SMarc Kleine-Budde 
53655bc37c8SMarc Kleine-Budde 		rx_ring->obj_num = rx_obj_num;
53785505e58SMarc Kleine-Budde 		rx_ring->obj_num_shift_to_u8 = BITS_PER_TYPE(rx_ring->obj_num_shift_to_u8) -
53885505e58SMarc Kleine-Budde 			ilog2(rx_obj_num);
53955bc37c8SMarc Kleine-Budde 		rx_ring->obj_size = rx_obj_size;
54055bc37c8SMarc Kleine-Budde 		priv->rx[i] = rx_ring;
54155bc37c8SMarc Kleine-Budde 	}
54255bc37c8SMarc Kleine-Budde 	priv->rx_ring_num = i;
54355bc37c8SMarc Kleine-Budde 
54460a848c5SMarc Kleine-Budde 	hrtimer_init(&priv->rx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
54560a848c5SMarc Kleine-Budde 	priv->rx_irq_timer.function = mcp251xfd_rx_irq_timer;
54660a848c5SMarc Kleine-Budde 
547169d00a2SMarc Kleine-Budde 	hrtimer_init(&priv->tx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
548169d00a2SMarc Kleine-Budde 	priv->tx_irq_timer.function = mcp251xfd_tx_irq_timer;
549169d00a2SMarc Kleine-Budde 
55055bc37c8SMarc Kleine-Budde 	return 0;
55155bc37c8SMarc Kleine-Budde }
552