Lines Matching +full:tx +full:- +full:rings +full:- +full:empty
1 // SPDX-License-Identifier: GPL-2.0
3 // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
6 // Marc Kleine-Budde <kernel@pengutronix.de>
18 #include "mcp251xfd-ram.h"
31 len = last_byte - first_byte + 1; in mcp251xfd_cmd_prepare_write_reg()
37 if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)) { in mcp251xfd_cmd_prepare_write_reg()
38 len += sizeof(write_reg_buf->nocrc.cmd); in mcp251xfd_cmd_prepare_write_reg()
43 len += sizeof(write_reg_buf->safe.cmd); in mcp251xfd_cmd_prepare_write_reg()
44 crc = mcp251xfd_crc16_compute(&write_reg_buf->safe, len); in mcp251xfd_cmd_prepare_write_reg()
48 len += sizeof(write_reg_buf->safe.crc); in mcp251xfd_cmd_prepare_write_reg()
52 mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd, in mcp251xfd_cmd_prepare_write_reg()
55 len += sizeof(write_reg_buf->crc.cmd); in mcp251xfd_cmd_prepare_write_reg()
56 crc = mcp251xfd_crc16_compute(&write_reg_buf->crc, len); in mcp251xfd_cmd_prepare_write_reg()
60 len += sizeof(write_reg_buf->crc.crc); in mcp251xfd_cmd_prepare_write_reg()
77 tef_ring = priv->tef; in mcp251xfd_ring_init_tef()
78 tef_ring->head = 0; in mcp251xfd_ring_init_tef()
79 tef_ring->tail = 0; in mcp251xfd_ring_init_tef()
81 /* TEF- and TX-FIFO have same number of objects */ in mcp251xfd_ring_init_tef()
82 *base = mcp251xfd_get_tef_obj_addr(priv->tx->obj_num); in mcp251xfd_ring_init_tef()
88 len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->irq_enable_buf, in mcp251xfd_ring_init_tef()
90 tef_ring->irq_enable_xfer.tx_buf = &tef_ring->irq_enable_buf; in mcp251xfd_ring_init_tef()
91 tef_ring->irq_enable_xfer.len = len; in mcp251xfd_ring_init_tef()
92 spi_message_init_with_transfers(&tef_ring->irq_enable_msg, in mcp251xfd_ring_init_tef()
93 &tef_ring->irq_enable_xfer, 1); in mcp251xfd_ring_init_tef()
98 len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf, in mcp251xfd_ring_init_tef()
101 for (i = 0; i < ARRAY_SIZE(tef_ring->uinc_xfer); i++) { in mcp251xfd_ring_init_tef()
102 xfer = &tef_ring->uinc_xfer[i]; in mcp251xfd_ring_init_tef()
103 xfer->tx_buf = &tef_ring->uinc_buf; in mcp251xfd_ring_init_tef()
104 xfer->len = len; in mcp251xfd_ring_init_tef()
105 xfer->cs_change = 1; in mcp251xfd_ring_init_tef()
106 xfer->cs_change_delay.value = 0; in mcp251xfd_ring_init_tef()
107 xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; in mcp251xfd_ring_init_tef()
117 xfer->cs_change = 0; in mcp251xfd_ring_init_tef()
119 if (priv->tx_coalesce_usecs_irq || priv->tx_obj_num_coalesce_irq) { in mcp251xfd_ring_init_tef()
125 &tef_ring->uinc_irq_disable_buf, in mcp251xfd_ring_init_tef()
127 xfer->tx_buf = &tef_ring->uinc_irq_disable_buf; in mcp251xfd_ring_init_tef()
128 xfer->len = len; in mcp251xfd_ring_init_tef()
144 if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) in mcp251xfd_tx_ring_init_tx_obj()
145 mcp251xfd_spi_cmd_write_crc_set_addr(&tx_obj->buf.crc.cmd, in mcp251xfd_tx_ring_init_tx_obj()
148 mcp251xfd_spi_cmd_write_nocrc(&tx_obj->buf.nocrc.cmd, in mcp251xfd_tx_ring_init_tx_obj()
151 xfer = &tx_obj->xfer[0]; in mcp251xfd_tx_ring_init_tx_obj()
152 xfer->tx_buf = &tx_obj->buf; in mcp251xfd_tx_ring_init_tx_obj()
153 xfer->len = 0; /* actual len is assigned on the fly */ in mcp251xfd_tx_ring_init_tx_obj()
154 xfer->cs_change = 1; in mcp251xfd_tx_ring_init_tx_obj()
155 xfer->cs_change_delay.value = 0; in mcp251xfd_tx_ring_init_tx_obj()
156 xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; in mcp251xfd_tx_ring_init_tx_obj()
159 xfer = &tx_obj->xfer[1]; in mcp251xfd_tx_ring_init_tx_obj()
160 xfer->tx_buf = &ring->rts_buf; in mcp251xfd_tx_ring_init_tx_obj()
161 xfer->len = rts_buf_len; in mcp251xfd_tx_ring_init_tx_obj()
164 spi_message_init_with_transfers(&tx_obj->msg, tx_obj->xfer, in mcp251xfd_tx_ring_init_tx_obj()
165 ARRAY_SIZE(tx_obj->xfer)); in mcp251xfd_tx_ring_init_tx_obj()
178 tx_ring = priv->tx; in mcp251xfd_ring_init_tx()
179 tx_ring->head = 0; in mcp251xfd_ring_init_tx()
180 tx_ring->tail = 0; in mcp251xfd_ring_init_tx()
181 tx_ring->base = *base; in mcp251xfd_ring_init_tx()
182 tx_ring->nr = 0; in mcp251xfd_ring_init_tx()
183 tx_ring->fifo_nr = *fifo_nr; in mcp251xfd_ring_init_tx()
185 *base = mcp251xfd_get_tx_obj_addr(tx_ring, tx_ring->obj_num); in mcp251xfd_ring_init_tx()
189 addr = MCP251XFD_REG_FIFOCON(tx_ring->fifo_nr); in mcp251xfd_ring_init_tx()
191 len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf, in mcp251xfd_ring_init_tx()
209 rx_ring->head = 0; in mcp251xfd_ring_init_rx()
210 rx_ring->tail = 0; in mcp251xfd_ring_init_rx()
211 rx_ring->base = *base; in mcp251xfd_ring_init_rx()
212 rx_ring->nr = i; in mcp251xfd_ring_init_rx()
213 rx_ring->fifo_nr = *fifo_nr; in mcp251xfd_ring_init_rx()
215 *base = mcp251xfd_get_rx_obj_addr(rx_ring, rx_ring->obj_num); in mcp251xfd_ring_init_rx()
219 addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr); in mcp251xfd_ring_init_rx()
222 len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->irq_enable_buf, in mcp251xfd_ring_init_rx()
224 rx_ring->irq_enable_xfer.tx_buf = &rx_ring->irq_enable_buf; in mcp251xfd_ring_init_rx()
225 rx_ring->irq_enable_xfer.len = len; in mcp251xfd_ring_init_rx()
226 spi_message_init_with_transfers(&rx_ring->irq_enable_msg, in mcp251xfd_ring_init_rx()
227 &rx_ring->irq_enable_xfer, 1); in mcp251xfd_ring_init_rx()
231 len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf, in mcp251xfd_ring_init_rx()
234 for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) { in mcp251xfd_ring_init_rx()
235 xfer = &rx_ring->uinc_xfer[j]; in mcp251xfd_ring_init_rx()
236 xfer->tx_buf = &rx_ring->uinc_buf; in mcp251xfd_ring_init_rx()
237 xfer->len = len; in mcp251xfd_ring_init_rx()
238 xfer->cs_change = 1; in mcp251xfd_ring_init_rx()
239 xfer->cs_change_delay.value = 0; in mcp251xfd_ring_init_rx()
240 xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; in mcp251xfd_ring_init_rx()
250 xfer->cs_change = 0; in mcp251xfd_ring_init_rx()
252 /* Use 1st RX-FIFO for IRQ coalescing. If enabled in mcp251xfd_ring_init_rx()
256 * - TFNRFNIE (Receive FIFO Not Empty Interrupt) in mcp251xfd_ring_init_rx()
260 * - TFHRFHIE (Receive FIFO Half Full Interrupt) in mcp251xfd_ring_init_rx()
261 * - or - in mcp251xfd_ring_init_rx()
262 * - TFERFFIE (Receive FIFO Full Interrupt) in mcp251xfd_ring_init_rx()
268 if (rx_ring->nr == 0 && (priv->rx_coalesce_usecs_irq || in mcp251xfd_ring_init_rx()
269 priv->rx_obj_num_coalesce_irq)) { in mcp251xfd_ring_init_rx()
273 if (priv->rx_obj_num_coalesce_irq == rx_ring->obj_num) in mcp251xfd_ring_init_rx()
275 else if (priv->rx_obj_num_coalesce_irq) in mcp251xfd_ring_init_rx()
279 &rx_ring->uinc_irq_disable_buf, in mcp251xfd_ring_init_rx()
281 xfer->tx_buf = &rx_ring->uinc_irq_disable_buf; in mcp251xfd_ring_init_rx()
282 xfer->len = len; in mcp251xfd_ring_init_rx()
294 netdev_reset_queue(priv->ndev); in mcp251xfd_ring_init()
300 /* mcp251xfd_handle_rxif() will iterate over all RX rings. in mcp251xfd_ring_init()
301 * Rings with their corresponding bit set in in mcp251xfd_ring_init()
302 * priv->regs_status.rxif are read out. in mcp251xfd_ring_init()
304 * If the chip is configured for only 1 RX-FIFO, and if there in mcp251xfd_ring_init()
306 * it must be the 1st RX-FIFO. in mcp251xfd_ring_init()
310 * mcp251xfd_read_regs_status() for the 1 RX-FIFO only case. in mcp251xfd_ring_init()
312 * If we use more than 1 RX-FIFO, this value gets overwritten in mcp251xfd_ring_init()
316 priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr); in mcp251xfd_ring_init()
318 if (priv->tx_obj_num_coalesce_irq) { in mcp251xfd_ring_init()
319 netdev_dbg(priv->ndev, in mcp251xfd_ring_init()
322 priv->tx_obj_num_coalesce_irq, in mcp251xfd_ring_init()
324 priv->tx_obj_num_coalesce_irq * in mcp251xfd_ring_init()
327 netdev_dbg(priv->ndev, in mcp251xfd_ring_init()
329 mcp251xfd_get_tef_obj_addr(priv->tx_obj_num_coalesce_irq), in mcp251xfd_ring_init()
330 priv->tx->obj_num - priv->tx_obj_num_coalesce_irq, in mcp251xfd_ring_init()
332 (priv->tx->obj_num - priv->tx_obj_num_coalesce_irq) * in mcp251xfd_ring_init()
335 netdev_dbg(priv->ndev, in mcp251xfd_ring_init()
338 priv->tx->obj_num, sizeof(struct mcp251xfd_hw_tef_obj), in mcp251xfd_ring_init()
339 priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj)); in mcp251xfd_ring_init()
343 if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) { in mcp251xfd_ring_init()
344 netdev_dbg(priv->ndev, in mcp251xfd_ring_init()
345 "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes (coalesce)\n", in mcp251xfd_ring_init()
346 rx_ring->nr, rx_ring->fifo_nr, in mcp251xfd_ring_init()
348 priv->rx_obj_num_coalesce_irq, rx_ring->obj_size, in mcp251xfd_ring_init()
349 priv->rx_obj_num_coalesce_irq * rx_ring->obj_size); in mcp251xfd_ring_init()
351 if (priv->rx_obj_num_coalesce_irq == MCP251XFD_FIFO_DEPTH) in mcp251xfd_ring_init()
354 netdev_dbg(priv->ndev, in mcp251xfd_ring_init()
357 priv->rx_obj_num_coalesce_irq), in mcp251xfd_ring_init()
358 rx_ring->obj_num - priv->rx_obj_num_coalesce_irq, in mcp251xfd_ring_init()
359 rx_ring->obj_size, in mcp251xfd_ring_init()
360 (rx_ring->obj_num - priv->rx_obj_num_coalesce_irq) * in mcp251xfd_ring_init()
361 rx_ring->obj_size); in mcp251xfd_ring_init()
363 netdev_dbg(priv->ndev, in mcp251xfd_ring_init()
364 "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n", in mcp251xfd_ring_init()
365 rx_ring->nr, rx_ring->fifo_nr, in mcp251xfd_ring_init()
367 rx_ring->obj_num, rx_ring->obj_size, in mcp251xfd_ring_init()
368 rx_ring->obj_num * rx_ring->obj_size); in mcp251xfd_ring_init()
372 netdev_dbg(priv->ndev, in mcp251xfd_ring_init()
373 "FIFO setup: TX: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n", in mcp251xfd_ring_init()
374 priv->tx->fifo_nr, in mcp251xfd_ring_init()
375 mcp251xfd_get_tx_obj_addr(priv->tx, 0), in mcp251xfd_ring_init()
376 priv->tx->obj_num, priv->tx->obj_size, in mcp251xfd_ring_init()
377 priv->tx->obj_num * priv->tx->obj_size); in mcp251xfd_ring_init()
379 netdev_dbg(priv->ndev, in mcp251xfd_ring_init()
381 MCP251XFD_RAM_SIZE - (base - MCP251XFD_RAM_START)); in mcp251xfd_ring_init()
383 ram_used = base - MCP251XFD_RAM_START; in mcp251xfd_ring_init()
385 netdev_err(priv->ndev, in mcp251xfd_ring_init()
388 return -ENOMEM; in mcp251xfd_ring_init()
398 for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) { in mcp251xfd_ring_free()
399 kfree(priv->rx[i]); in mcp251xfd_ring_free()
400 priv->rx[i] = NULL; in mcp251xfd_ring_free()
408 struct mcp251xfd_rx_ring *ring = priv->rx[0]; in mcp251xfd_rx_irq_timer()
410 if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags)) in mcp251xfd_rx_irq_timer()
413 spi_async(priv->spi, &ring->irq_enable_msg); in mcp251xfd_rx_irq_timer()
422 struct mcp251xfd_tef_ring *ring = priv->tef; in mcp251xfd_tx_irq_timer()
424 if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags)) in mcp251xfd_tx_irq_timer()
427 spi_async(priv->spi, &ring->irq_enable_msg); in mcp251xfd_tx_irq_timer()
444 .tx = {
464 struct mcp251xfd_tx_ring *tx_ring = priv->tx; in mcp251xfd_ring_alloc()
469 /* switching from CAN-2.0 to CAN-FD mode or vice versa */ in mcp251xfd_ring_alloc()
470 if (fd_mode != test_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags)) { in mcp251xfd_ring_alloc()
474 priv->rx_obj_num = layout.default_rx; in mcp251xfd_ring_alloc()
475 tx_ring->obj_num = layout.default_tx; in mcp251xfd_ring_alloc()
481 set_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags); in mcp251xfd_ring_alloc()
485 clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags); in mcp251xfd_ring_alloc()
488 tx_ring->obj_size = tx_obj_size; in mcp251xfd_ring_alloc()
490 rem = priv->rx_obj_num; in mcp251xfd_ring_alloc()
491 for (i = 0; i < ARRAY_SIZE(priv->rx) && rem; i++) { in mcp251xfd_ring_alloc()
494 if (i == 0 && priv->rx_obj_num_coalesce_irq) in mcp251xfd_ring_alloc()
495 rx_obj_num = min_t(u8, priv->rx_obj_num_coalesce_irq * 2, in mcp251xfd_ring_alloc()
500 rem -= rx_obj_num; in mcp251xfd_ring_alloc()
506 return -ENOMEM; in mcp251xfd_ring_alloc()
509 rx_ring->obj_num = rx_obj_num; in mcp251xfd_ring_alloc()
510 rx_ring->obj_size = rx_obj_size; in mcp251xfd_ring_alloc()
511 priv->rx[i] = rx_ring; in mcp251xfd_ring_alloc()
513 priv->rx_ring_num = i; in mcp251xfd_ring_alloc()
515 hrtimer_init(&priv->rx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); in mcp251xfd_ring_alloc()
516 priv->rx_irq_timer.function = mcp251xfd_rx_irq_timer; in mcp251xfd_ring_alloc()
518 hrtimer_init(&priv->tx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); in mcp251xfd_ring_alloc()
519 priv->tx_irq_timer.function = mcp251xfd_tx_irq_timer; in mcp251xfd_ring_alloc()