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 // 555bc37c8SMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021 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 1555bc37c8SMarc Kleine-Budde #include <asm/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 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 3355bc37c8SMarc Kleine-Budde data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte); 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 3755bc37c8SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) { 3855bc37c8SMarc Kleine-Budde u16 crc; 3955bc37c8SMarc Kleine-Budde 4055bc37c8SMarc Kleine-Budde mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd, 4155bc37c8SMarc Kleine-Budde len); 4255bc37c8SMarc Kleine-Budde /* CRC */ 4355bc37c8SMarc Kleine-Budde len += sizeof(write_reg_buf->crc.cmd); 4455bc37c8SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(&write_reg_buf->crc, len); 4555bc37c8SMarc Kleine-Budde put_unaligned_be16(crc, (void *)write_reg_buf + len); 4655bc37c8SMarc Kleine-Budde 4755bc37c8SMarc Kleine-Budde /* Total length */ 4855bc37c8SMarc Kleine-Budde len += sizeof(write_reg_buf->crc.crc); 4955bc37c8SMarc Kleine-Budde } else { 5055bc37c8SMarc Kleine-Budde len += sizeof(write_reg_buf->nocrc.cmd); 5155bc37c8SMarc Kleine-Budde } 5255bc37c8SMarc Kleine-Budde 5355bc37c8SMarc Kleine-Budde return len; 5455bc37c8SMarc Kleine-Budde } 5555bc37c8SMarc Kleine-Budde 56617283b9SMarc Kleine-Budde static void 57617283b9SMarc Kleine-Budde mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base) 58d2d5397fSMarc Kleine-Budde { 59d2d5397fSMarc Kleine-Budde struct mcp251xfd_tef_ring *tef_ring; 60d2d5397fSMarc Kleine-Budde struct spi_transfer *xfer; 61d2d5397fSMarc Kleine-Budde u32 val; 62d2d5397fSMarc Kleine-Budde u16 addr; 63d2d5397fSMarc Kleine-Budde u8 len; 64d2d5397fSMarc Kleine-Budde int i; 65d2d5397fSMarc Kleine-Budde 66d2d5397fSMarc Kleine-Budde /* TEF */ 67d2d5397fSMarc Kleine-Budde tef_ring = priv->tef; 68d2d5397fSMarc Kleine-Budde tef_ring->head = 0; 69d2d5397fSMarc Kleine-Budde tef_ring->tail = 0; 70d2d5397fSMarc Kleine-Budde 71617283b9SMarc Kleine-Budde /* TEF- and TX-FIFO have same number of objects */ 72617283b9SMarc Kleine-Budde *base = mcp251xfd_get_tef_obj_addr(priv->tx->obj_num); 73617283b9SMarc Kleine-Budde 74169d00a2SMarc Kleine-Budde /* FIFO IRQ enable */ 75169d00a2SMarc Kleine-Budde addr = MCP251XFD_REG_TEFCON; 76169d00a2SMarc Kleine-Budde val = MCP251XFD_REG_TEFCON_TEFOVIE | MCP251XFD_REG_TEFCON_TEFNEIE; 77169d00a2SMarc Kleine-Budde 78169d00a2SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->irq_enable_buf, 79169d00a2SMarc Kleine-Budde addr, val, val); 80169d00a2SMarc Kleine-Budde tef_ring->irq_enable_xfer.tx_buf = &tef_ring->irq_enable_buf; 81169d00a2SMarc Kleine-Budde tef_ring->irq_enable_xfer.len = len; 82169d00a2SMarc Kleine-Budde spi_message_init_with_transfers(&tef_ring->irq_enable_msg, 83169d00a2SMarc Kleine-Budde &tef_ring->irq_enable_xfer, 1); 84169d00a2SMarc Kleine-Budde 85d2d5397fSMarc Kleine-Budde /* FIFO increment TEF tail pointer */ 86d2d5397fSMarc Kleine-Budde addr = MCP251XFD_REG_TEFCON; 87d2d5397fSMarc Kleine-Budde val = MCP251XFD_REG_TEFCON_UINC; 88d2d5397fSMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf, 89d2d5397fSMarc Kleine-Budde addr, val, val); 90d2d5397fSMarc Kleine-Budde 91d2d5397fSMarc Kleine-Budde for (i = 0; i < ARRAY_SIZE(tef_ring->uinc_xfer); i++) { 92d2d5397fSMarc Kleine-Budde xfer = &tef_ring->uinc_xfer[i]; 93d2d5397fSMarc Kleine-Budde xfer->tx_buf = &tef_ring->uinc_buf; 94d2d5397fSMarc Kleine-Budde xfer->len = len; 95d2d5397fSMarc Kleine-Budde xfer->cs_change = 1; 96d2d5397fSMarc Kleine-Budde xfer->cs_change_delay.value = 0; 97d2d5397fSMarc Kleine-Budde xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 98d2d5397fSMarc Kleine-Budde } 99d2d5397fSMarc Kleine-Budde 100d2d5397fSMarc Kleine-Budde /* "cs_change == 1" on the last transfer results in an active 101d2d5397fSMarc Kleine-Budde * chip select after the complete SPI message. This causes the 102d2d5397fSMarc Kleine-Budde * controller to interpret the next register access as 103d2d5397fSMarc Kleine-Budde * data. Set "cs_change" of the last transfer to "0" to 104d2d5397fSMarc Kleine-Budde * properly deactivate the chip select at the end of the 105d2d5397fSMarc Kleine-Budde * message. 106d2d5397fSMarc Kleine-Budde */ 107d2d5397fSMarc Kleine-Budde xfer->cs_change = 0; 108169d00a2SMarc Kleine-Budde 109169d00a2SMarc Kleine-Budde if (priv->tx_coalesce_usecs_irq || priv->tx_obj_num_coalesce_irq) { 110169d00a2SMarc Kleine-Budde val = MCP251XFD_REG_TEFCON_UINC | 111169d00a2SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFOVIE | 112169d00a2SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFHIE; 113169d00a2SMarc Kleine-Budde 114169d00a2SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, 115169d00a2SMarc Kleine-Budde &tef_ring->uinc_irq_disable_buf, 116169d00a2SMarc Kleine-Budde addr, val, val); 117169d00a2SMarc Kleine-Budde xfer->tx_buf = &tef_ring->uinc_irq_disable_buf; 118169d00a2SMarc Kleine-Budde xfer->len = len; 119169d00a2SMarc Kleine-Budde } 120d2d5397fSMarc Kleine-Budde } 121d2d5397fSMarc Kleine-Budde 12255bc37c8SMarc Kleine-Budde static void 12355bc37c8SMarc Kleine-Budde mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv, 12455bc37c8SMarc Kleine-Budde const struct mcp251xfd_tx_ring *ring, 12555bc37c8SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj, 12655bc37c8SMarc Kleine-Budde const u8 rts_buf_len, 12755bc37c8SMarc Kleine-Budde const u8 n) 12855bc37c8SMarc Kleine-Budde { 12955bc37c8SMarc Kleine-Budde struct spi_transfer *xfer; 13055bc37c8SMarc Kleine-Budde u16 addr; 13155bc37c8SMarc Kleine-Budde 13255bc37c8SMarc Kleine-Budde /* FIFO load */ 13355bc37c8SMarc Kleine-Budde addr = mcp251xfd_get_tx_obj_addr(ring, n); 13455bc37c8SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) 13555bc37c8SMarc Kleine-Budde mcp251xfd_spi_cmd_write_crc_set_addr(&tx_obj->buf.crc.cmd, 13655bc37c8SMarc Kleine-Budde addr); 13755bc37c8SMarc Kleine-Budde else 13855bc37c8SMarc Kleine-Budde mcp251xfd_spi_cmd_write_nocrc(&tx_obj->buf.nocrc.cmd, 13955bc37c8SMarc Kleine-Budde addr); 14055bc37c8SMarc Kleine-Budde 14155bc37c8SMarc Kleine-Budde xfer = &tx_obj->xfer[0]; 14255bc37c8SMarc Kleine-Budde xfer->tx_buf = &tx_obj->buf; 14355bc37c8SMarc Kleine-Budde xfer->len = 0; /* actual len is assigned on the fly */ 14455bc37c8SMarc Kleine-Budde xfer->cs_change = 1; 14555bc37c8SMarc Kleine-Budde xfer->cs_change_delay.value = 0; 14655bc37c8SMarc Kleine-Budde xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 14755bc37c8SMarc Kleine-Budde 14855bc37c8SMarc Kleine-Budde /* FIFO request to send */ 14955bc37c8SMarc Kleine-Budde xfer = &tx_obj->xfer[1]; 15055bc37c8SMarc Kleine-Budde xfer->tx_buf = &ring->rts_buf; 15155bc37c8SMarc Kleine-Budde xfer->len = rts_buf_len; 15255bc37c8SMarc Kleine-Budde 15355bc37c8SMarc Kleine-Budde /* SPI message */ 15455bc37c8SMarc Kleine-Budde spi_message_init_with_transfers(&tx_obj->msg, tx_obj->xfer, 15555bc37c8SMarc Kleine-Budde ARRAY_SIZE(tx_obj->xfer)); 15655bc37c8SMarc Kleine-Budde } 15755bc37c8SMarc Kleine-Budde 158617283b9SMarc Kleine-Budde static void 159617283b9SMarc Kleine-Budde mcp251xfd_ring_init_tx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr) 16055bc37c8SMarc Kleine-Budde { 16155bc37c8SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring; 16255bc37c8SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 16355bc37c8SMarc Kleine-Budde u32 val; 16455bc37c8SMarc Kleine-Budde u16 addr; 16555bc37c8SMarc Kleine-Budde u8 len; 166d2d5397fSMarc Kleine-Budde int i; 16755bc37c8SMarc Kleine-Budde 16855bc37c8SMarc Kleine-Budde tx_ring = priv->tx; 16955bc37c8SMarc Kleine-Budde tx_ring->head = 0; 17055bc37c8SMarc Kleine-Budde tx_ring->tail = 0; 171617283b9SMarc Kleine-Budde tx_ring->base = *base; 172c912f19eSMarc Kleine-Budde tx_ring->nr = 0; 173617283b9SMarc Kleine-Budde tx_ring->fifo_nr = *fifo_nr; 174617283b9SMarc Kleine-Budde 175617283b9SMarc Kleine-Budde *base = mcp251xfd_get_tx_obj_addr(tx_ring, tx_ring->obj_num); 176617283b9SMarc Kleine-Budde *fifo_nr += 1; 17755bc37c8SMarc Kleine-Budde 17855bc37c8SMarc Kleine-Budde /* FIFO request to send */ 179c912f19eSMarc Kleine-Budde addr = MCP251XFD_REG_FIFOCON(tx_ring->fifo_nr); 18055bc37c8SMarc Kleine-Budde val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC; 18155bc37c8SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf, 18255bc37c8SMarc Kleine-Budde addr, val, val); 18355bc37c8SMarc Kleine-Budde 18455bc37c8SMarc Kleine-Budde mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i) 18555bc37c8SMarc Kleine-Budde mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i); 186d2d5397fSMarc Kleine-Budde } 18755bc37c8SMarc Kleine-Budde 188617283b9SMarc Kleine-Budde static void 189617283b9SMarc Kleine-Budde mcp251xfd_ring_init_rx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr) 190d2d5397fSMarc Kleine-Budde { 191617283b9SMarc Kleine-Budde struct mcp251xfd_rx_ring *rx_ring; 192d2d5397fSMarc Kleine-Budde struct spi_transfer *xfer; 193d2d5397fSMarc Kleine-Budde u32 val; 194d2d5397fSMarc Kleine-Budde u16 addr; 195d2d5397fSMarc Kleine-Budde u8 len; 196d2d5397fSMarc Kleine-Budde int i, j; 197d2d5397fSMarc Kleine-Budde 19855bc37c8SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { 19955bc37c8SMarc Kleine-Budde rx_ring->head = 0; 20055bc37c8SMarc Kleine-Budde rx_ring->tail = 0; 201617283b9SMarc Kleine-Budde rx_ring->base = *base; 20255bc37c8SMarc Kleine-Budde rx_ring->nr = i; 203617283b9SMarc Kleine-Budde rx_ring->fifo_nr = *fifo_nr; 20455bc37c8SMarc Kleine-Budde 205617283b9SMarc Kleine-Budde *base = mcp251xfd_get_rx_obj_addr(rx_ring, rx_ring->obj_num); 206617283b9SMarc Kleine-Budde *fifo_nr += 1; 20755bc37c8SMarc Kleine-Budde 20860a848c5SMarc Kleine-Budde /* FIFO IRQ enable */ 20955bc37c8SMarc Kleine-Budde addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr); 21060a848c5SMarc Kleine-Budde val = MCP251XFD_REG_FIFOCON_RXOVIE | 21160a848c5SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TFNRFNIE; 21260a848c5SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->irq_enable_buf, 21360a848c5SMarc Kleine-Budde addr, val, val); 21460a848c5SMarc Kleine-Budde rx_ring->irq_enable_xfer.tx_buf = &rx_ring->irq_enable_buf; 21560a848c5SMarc Kleine-Budde rx_ring->irq_enable_xfer.len = len; 21660a848c5SMarc Kleine-Budde spi_message_init_with_transfers(&rx_ring->irq_enable_msg, 21760a848c5SMarc Kleine-Budde &rx_ring->irq_enable_xfer, 1); 21860a848c5SMarc Kleine-Budde 21960a848c5SMarc Kleine-Budde /* FIFO increment RX tail pointer */ 22055bc37c8SMarc Kleine-Budde val = MCP251XFD_REG_FIFOCON_UINC; 22155bc37c8SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf, 22255bc37c8SMarc Kleine-Budde addr, val, val); 22355bc37c8SMarc Kleine-Budde 22455bc37c8SMarc Kleine-Budde for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) { 22555bc37c8SMarc Kleine-Budde xfer = &rx_ring->uinc_xfer[j]; 22655bc37c8SMarc Kleine-Budde xfer->tx_buf = &rx_ring->uinc_buf; 22755bc37c8SMarc Kleine-Budde xfer->len = len; 22855bc37c8SMarc Kleine-Budde xfer->cs_change = 1; 22955bc37c8SMarc Kleine-Budde xfer->cs_change_delay.value = 0; 23055bc37c8SMarc Kleine-Budde xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 23155bc37c8SMarc Kleine-Budde } 23255bc37c8SMarc Kleine-Budde 23355bc37c8SMarc Kleine-Budde /* "cs_change == 1" on the last transfer results in an 23455bc37c8SMarc Kleine-Budde * active chip select after the complete SPI 23555bc37c8SMarc Kleine-Budde * message. This causes the controller to interpret 23655bc37c8SMarc Kleine-Budde * the next register access as data. Set "cs_change" 23755bc37c8SMarc Kleine-Budde * of the last transfer to "0" to properly deactivate 23855bc37c8SMarc Kleine-Budde * the chip select at the end of the message. 23955bc37c8SMarc Kleine-Budde */ 24055bc37c8SMarc Kleine-Budde xfer->cs_change = 0; 24160a848c5SMarc Kleine-Budde 24260a848c5SMarc Kleine-Budde /* Use 1st RX-FIFO for IRQ coalescing. If enabled 24360a848c5SMarc Kleine-Budde * (rx_coalesce_usecs_irq or rx_max_coalesce_frames_irq 24460a848c5SMarc Kleine-Budde * is activated), use the last transfer to disable: 24560a848c5SMarc Kleine-Budde * 24660a848c5SMarc Kleine-Budde * - TFNRFNIE (Receive FIFO Not Empty Interrupt) 24760a848c5SMarc Kleine-Budde * 24860a848c5SMarc Kleine-Budde * and enable: 24960a848c5SMarc Kleine-Budde * 25060a848c5SMarc Kleine-Budde * - TFHRFHIE (Receive FIFO Half Full Interrupt) 25160a848c5SMarc Kleine-Budde * - or - 25260a848c5SMarc Kleine-Budde * - TFERFFIE (Receive FIFO Full Interrupt) 25360a848c5SMarc Kleine-Budde * 25460a848c5SMarc Kleine-Budde * depending on rx_max_coalesce_frames_irq. 25560a848c5SMarc Kleine-Budde * 25660a848c5SMarc Kleine-Budde * The RXOVIE (Overflow Interrupt) is always enabled. 25760a848c5SMarc Kleine-Budde */ 25860a848c5SMarc Kleine-Budde if (rx_ring->nr == 0 && (priv->rx_coalesce_usecs_irq || 25960a848c5SMarc Kleine-Budde priv->rx_obj_num_coalesce_irq)) { 26060a848c5SMarc Kleine-Budde val = MCP251XFD_REG_FIFOCON_UINC | 26160a848c5SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_RXOVIE; 26260a848c5SMarc Kleine-Budde 26360a848c5SMarc Kleine-Budde if (priv->rx_obj_num_coalesce_irq == rx_ring->obj_num) 26460a848c5SMarc Kleine-Budde val |= MCP251XFD_REG_FIFOCON_TFERFFIE; 26560a848c5SMarc Kleine-Budde else if (priv->rx_obj_num_coalesce_irq) 26660a848c5SMarc Kleine-Budde val |= MCP251XFD_REG_FIFOCON_TFHRFHIE; 26760a848c5SMarc Kleine-Budde 26860a848c5SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, 26960a848c5SMarc Kleine-Budde &rx_ring->uinc_irq_disable_buf, 27060a848c5SMarc Kleine-Budde addr, val, val); 27160a848c5SMarc Kleine-Budde xfer->tx_buf = &rx_ring->uinc_irq_disable_buf; 27260a848c5SMarc Kleine-Budde xfer->len = len; 27360a848c5SMarc Kleine-Budde } 27455bc37c8SMarc Kleine-Budde } 27555bc37c8SMarc Kleine-Budde } 27655bc37c8SMarc Kleine-Budde 277fa0b68dfSMarc Kleine-Budde int mcp251xfd_ring_init(struct mcp251xfd_priv *priv) 278d2d5397fSMarc Kleine-Budde { 27983daa863SMarc Kleine-Budde const struct mcp251xfd_rx_ring *rx_ring; 280fa0b68dfSMarc Kleine-Budde u16 base = 0, ram_used; 281617283b9SMarc Kleine-Budde u8 fifo_nr = 1; 28283daa863SMarc Kleine-Budde int i; 283617283b9SMarc Kleine-Budde 284d2d5397fSMarc Kleine-Budde netdev_reset_queue(priv->ndev); 285d2d5397fSMarc Kleine-Budde 286617283b9SMarc Kleine-Budde mcp251xfd_ring_init_tef(priv, &base); 287617283b9SMarc Kleine-Budde mcp251xfd_ring_init_rx(priv, &base, &fifo_nr); 28862713f0dSMarc Kleine-Budde mcp251xfd_ring_init_tx(priv, &base, &fifo_nr); 289fa0b68dfSMarc Kleine-Budde 290887e359dSMarc Kleine-Budde /* mcp251xfd_handle_rxif() will iterate over all RX rings. 291887e359dSMarc Kleine-Budde * Rings with their corresponding bit set in 292887e359dSMarc Kleine-Budde * priv->regs_status.rxif are read out. 293887e359dSMarc Kleine-Budde * 294887e359dSMarc Kleine-Budde * If the chip is configured for only 1 RX-FIFO, and if there 295887e359dSMarc Kleine-Budde * is an RX interrupt pending (RXIF in INT register is set), 296887e359dSMarc Kleine-Budde * it must be the 1st RX-FIFO. 297887e359dSMarc Kleine-Budde * 298887e359dSMarc Kleine-Budde * We mark the RXIF of the 1st FIFO as pending here, so that 299887e359dSMarc Kleine-Budde * we can skip the read of the RXIF register in 300887e359dSMarc Kleine-Budde * mcp251xfd_read_regs_status() for the 1 RX-FIFO only case. 301887e359dSMarc Kleine-Budde * 302887e359dSMarc Kleine-Budde * If we use more than 1 RX-FIFO, this value gets overwritten 303887e359dSMarc Kleine-Budde * in mcp251xfd_read_regs_status(), so set it unconditionally 304887e359dSMarc Kleine-Budde * here. 305887e359dSMarc Kleine-Budde */ 306887e359dSMarc Kleine-Budde priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr); 307887e359dSMarc Kleine-Budde 308169d00a2SMarc Kleine-Budde if (priv->tx_obj_num_coalesce_irq) { 309169d00a2SMarc Kleine-Budde netdev_dbg(priv->ndev, 310169d00a2SMarc Kleine-Budde "FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes (coalesce)\n", 311169d00a2SMarc Kleine-Budde mcp251xfd_get_tef_obj_addr(0), 312169d00a2SMarc Kleine-Budde priv->tx_obj_num_coalesce_irq, 313169d00a2SMarc Kleine-Budde sizeof(struct mcp251xfd_hw_tef_obj), 314169d00a2SMarc Kleine-Budde priv->tx_obj_num_coalesce_irq * 315169d00a2SMarc Kleine-Budde sizeof(struct mcp251xfd_hw_tef_obj)); 316169d00a2SMarc Kleine-Budde 317169d00a2SMarc Kleine-Budde netdev_dbg(priv->ndev, 318169d00a2SMarc Kleine-Budde " 0x%03x: %2d*%zu bytes = %4zu bytes\n", 319169d00a2SMarc Kleine-Budde mcp251xfd_get_tef_obj_addr(priv->tx_obj_num_coalesce_irq), 320169d00a2SMarc Kleine-Budde priv->tx->obj_num - priv->tx_obj_num_coalesce_irq, 321169d00a2SMarc Kleine-Budde sizeof(struct mcp251xfd_hw_tef_obj), 322169d00a2SMarc Kleine-Budde (priv->tx->obj_num - priv->tx_obj_num_coalesce_irq) * 323169d00a2SMarc Kleine-Budde sizeof(struct mcp251xfd_hw_tef_obj)); 324169d00a2SMarc Kleine-Budde } else { 32583daa863SMarc Kleine-Budde netdev_dbg(priv->ndev, 32683daa863SMarc Kleine-Budde "FIFO setup: TEF: 0x%03x: %2d*%zu bytes = %4zu bytes\n", 32783daa863SMarc Kleine-Budde mcp251xfd_get_tef_obj_addr(0), 32883daa863SMarc Kleine-Budde priv->tx->obj_num, sizeof(struct mcp251xfd_hw_tef_obj), 32983daa863SMarc Kleine-Budde priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj)); 330169d00a2SMarc Kleine-Budde } 33183daa863SMarc Kleine-Budde 33283daa863SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { 33360a848c5SMarc Kleine-Budde if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) { 33460a848c5SMarc Kleine-Budde netdev_dbg(priv->ndev, 33560a848c5SMarc Kleine-Budde "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes (coalesce)\n", 33660a848c5SMarc Kleine-Budde rx_ring->nr, rx_ring->fifo_nr, 33760a848c5SMarc Kleine-Budde mcp251xfd_get_rx_obj_addr(rx_ring, 0), 33860a848c5SMarc Kleine-Budde priv->rx_obj_num_coalesce_irq, rx_ring->obj_size, 33960a848c5SMarc Kleine-Budde priv->rx_obj_num_coalesce_irq * rx_ring->obj_size); 34060a848c5SMarc Kleine-Budde 34160a848c5SMarc Kleine-Budde if (priv->rx_obj_num_coalesce_irq == MCP251XFD_FIFO_DEPTH) 34260a848c5SMarc Kleine-Budde continue; 34360a848c5SMarc Kleine-Budde 34460a848c5SMarc Kleine-Budde netdev_dbg(priv->ndev, 34560a848c5SMarc Kleine-Budde " 0x%03x: %2u*%u bytes = %4u bytes\n", 34660a848c5SMarc Kleine-Budde mcp251xfd_get_rx_obj_addr(rx_ring, 34760a848c5SMarc Kleine-Budde priv->rx_obj_num_coalesce_irq), 34860a848c5SMarc Kleine-Budde rx_ring->obj_num - priv->rx_obj_num_coalesce_irq, 34960a848c5SMarc Kleine-Budde rx_ring->obj_size, 35060a848c5SMarc Kleine-Budde (rx_ring->obj_num - priv->rx_obj_num_coalesce_irq) * 35160a848c5SMarc Kleine-Budde rx_ring->obj_size); 35260a848c5SMarc Kleine-Budde } else { 35383daa863SMarc Kleine-Budde netdev_dbg(priv->ndev, 35483daa863SMarc Kleine-Budde "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n", 35583daa863SMarc Kleine-Budde rx_ring->nr, rx_ring->fifo_nr, 35683daa863SMarc Kleine-Budde mcp251xfd_get_rx_obj_addr(rx_ring, 0), 35783daa863SMarc Kleine-Budde rx_ring->obj_num, rx_ring->obj_size, 35883daa863SMarc Kleine-Budde rx_ring->obj_num * rx_ring->obj_size); 35983daa863SMarc Kleine-Budde } 36060a848c5SMarc Kleine-Budde } 36183daa863SMarc Kleine-Budde 36283daa863SMarc Kleine-Budde netdev_dbg(priv->ndev, 36383daa863SMarc Kleine-Budde "FIFO setup: TX: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n", 36483daa863SMarc Kleine-Budde priv->tx->fifo_nr, 36583daa863SMarc Kleine-Budde mcp251xfd_get_tx_obj_addr(priv->tx, 0), 36683daa863SMarc Kleine-Budde priv->tx->obj_num, priv->tx->obj_size, 36783daa863SMarc Kleine-Budde priv->tx->obj_num * priv->tx->obj_size); 36883daa863SMarc Kleine-Budde 36983daa863SMarc Kleine-Budde netdev_dbg(priv->ndev, 370c47675b1SMarc Kleine-Budde "FIFO setup: free: %4d bytes\n", 37183daa863SMarc Kleine-Budde MCP251XFD_RAM_SIZE - (base - MCP251XFD_RAM_START)); 37283daa863SMarc Kleine-Budde 373fa0b68dfSMarc Kleine-Budde ram_used = base - MCP251XFD_RAM_START; 374fa0b68dfSMarc Kleine-Budde if (ram_used > MCP251XFD_RAM_SIZE) { 375fa0b68dfSMarc Kleine-Budde netdev_err(priv->ndev, 376fa0b68dfSMarc Kleine-Budde "Error during ring configuration, using more RAM (%u bytes) than available (%u bytes).\n", 377fa0b68dfSMarc Kleine-Budde ram_used, MCP251XFD_RAM_SIZE); 378fa0b68dfSMarc Kleine-Budde return -ENOMEM; 379fa0b68dfSMarc Kleine-Budde } 380fa0b68dfSMarc Kleine-Budde 381fa0b68dfSMarc Kleine-Budde return 0; 382d2d5397fSMarc Kleine-Budde } 383d2d5397fSMarc Kleine-Budde 38455bc37c8SMarc Kleine-Budde void mcp251xfd_ring_free(struct mcp251xfd_priv *priv) 38555bc37c8SMarc Kleine-Budde { 38655bc37c8SMarc Kleine-Budde int i; 38755bc37c8SMarc Kleine-Budde 38855bc37c8SMarc Kleine-Budde for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) { 38955bc37c8SMarc Kleine-Budde kfree(priv->rx[i]); 39055bc37c8SMarc Kleine-Budde priv->rx[i] = NULL; 39155bc37c8SMarc Kleine-Budde } 39255bc37c8SMarc Kleine-Budde } 39355bc37c8SMarc Kleine-Budde 39460a848c5SMarc Kleine-Budde static enum hrtimer_restart mcp251xfd_rx_irq_timer(struct hrtimer *t) 39560a848c5SMarc Kleine-Budde { 39660a848c5SMarc Kleine-Budde struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv, 39760a848c5SMarc Kleine-Budde rx_irq_timer); 39860a848c5SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring = priv->rx[0]; 39960a848c5SMarc Kleine-Budde 40060a848c5SMarc Kleine-Budde if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags)) 40160a848c5SMarc Kleine-Budde return HRTIMER_NORESTART; 40260a848c5SMarc Kleine-Budde 40360a848c5SMarc Kleine-Budde spi_async(priv->spi, &ring->irq_enable_msg); 40460a848c5SMarc Kleine-Budde 40560a848c5SMarc Kleine-Budde return HRTIMER_NORESTART; 40660a848c5SMarc Kleine-Budde } 40760a848c5SMarc Kleine-Budde 408169d00a2SMarc Kleine-Budde static enum hrtimer_restart mcp251xfd_tx_irq_timer(struct hrtimer *t) 409169d00a2SMarc Kleine-Budde { 410169d00a2SMarc Kleine-Budde struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv, 411169d00a2SMarc Kleine-Budde tx_irq_timer); 412169d00a2SMarc Kleine-Budde struct mcp251xfd_tef_ring *ring = priv->tef; 413169d00a2SMarc Kleine-Budde 414169d00a2SMarc Kleine-Budde if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags)) 415169d00a2SMarc Kleine-Budde return HRTIMER_NORESTART; 416169d00a2SMarc Kleine-Budde 417169d00a2SMarc Kleine-Budde spi_async(priv->spi, &ring->irq_enable_msg); 418169d00a2SMarc Kleine-Budde 419169d00a2SMarc Kleine-Budde return HRTIMER_NORESTART; 420169d00a2SMarc Kleine-Budde } 421169d00a2SMarc Kleine-Budde 4229263c2e9SMarc Kleine-Budde const struct can_ram_config mcp251xfd_ram_config = { 4239263c2e9SMarc Kleine-Budde .rx = { 4249263c2e9SMarc Kleine-Budde .size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_rx_obj_can), 4259263c2e9SMarc Kleine-Budde .size[CAN_RAM_MODE_CANFD] = sizeof(struct mcp251xfd_hw_rx_obj_canfd), 4269263c2e9SMarc Kleine-Budde .min = MCP251XFD_RX_OBJ_NUM_MIN, 4279263c2e9SMarc Kleine-Budde .max = MCP251XFD_RX_OBJ_NUM_MAX, 4289263c2e9SMarc Kleine-Budde .def[CAN_RAM_MODE_CAN] = CAN_RAM_NUM_MAX, 4299263c2e9SMarc Kleine-Budde .def[CAN_RAM_MODE_CANFD] = CAN_RAM_NUM_MAX, 4309263c2e9SMarc Kleine-Budde .fifo_num = MCP251XFD_FIFO_RX_NUM, 4319263c2e9SMarc Kleine-Budde .fifo_depth_min = MCP251XFD_RX_FIFO_DEPTH_MIN, 432846990e0SMarc Kleine-Budde .fifo_depth_coalesce_min = MCP251XFD_RX_FIFO_DEPTH_COALESCE_MIN, 4339263c2e9SMarc Kleine-Budde }, 4349263c2e9SMarc Kleine-Budde .tx = { 4359263c2e9SMarc Kleine-Budde .size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_tef_obj) + 4369263c2e9SMarc Kleine-Budde sizeof(struct mcp251xfd_hw_tx_obj_can), 4379263c2e9SMarc Kleine-Budde .size[CAN_RAM_MODE_CANFD] = sizeof(struct mcp251xfd_hw_tef_obj) + 4389263c2e9SMarc Kleine-Budde sizeof(struct mcp251xfd_hw_tx_obj_canfd), 4399263c2e9SMarc Kleine-Budde .min = MCP251XFD_TX_OBJ_NUM_MIN, 4409263c2e9SMarc Kleine-Budde .max = MCP251XFD_TX_OBJ_NUM_MAX, 4419263c2e9SMarc Kleine-Budde .def[CAN_RAM_MODE_CAN] = MCP251XFD_TX_OBJ_NUM_CAN_DEFAULT, 4429263c2e9SMarc Kleine-Budde .def[CAN_RAM_MODE_CANFD] = MCP251XFD_TX_OBJ_NUM_CANFD_DEFAULT, 4439263c2e9SMarc Kleine-Budde .fifo_num = MCP251XFD_FIFO_TX_NUM, 4449263c2e9SMarc Kleine-Budde .fifo_depth_min = MCP251XFD_TX_FIFO_DEPTH_MIN, 445656fc12dSMarc Kleine-Budde .fifo_depth_coalesce_min = MCP251XFD_TX_FIFO_DEPTH_COALESCE_MIN, 4469263c2e9SMarc Kleine-Budde }, 4479263c2e9SMarc Kleine-Budde .size = MCP251XFD_RAM_SIZE, 4489263c2e9SMarc Kleine-Budde .fifo_depth = MCP251XFD_FIFO_DEPTH, 4499263c2e9SMarc Kleine-Budde }; 4509263c2e9SMarc Kleine-Budde 45155bc37c8SMarc Kleine-Budde int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv) 45255bc37c8SMarc Kleine-Budde { 4539263c2e9SMarc Kleine-Budde const bool fd_mode = mcp251xfd_is_fd_mode(priv); 4549263c2e9SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 45555bc37c8SMarc Kleine-Budde struct mcp251xfd_rx_ring *rx_ring; 4569263c2e9SMarc Kleine-Budde u8 tx_obj_size, rx_obj_size; 4570a1f2e65SMarc Kleine-Budde u8 rem, i; 45855bc37c8SMarc Kleine-Budde 4599263c2e9SMarc Kleine-Budde /* switching from CAN-2.0 to CAN-FD mode or vice versa */ 4609263c2e9SMarc Kleine-Budde if (fd_mode != test_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags)) { 4619263c2e9SMarc Kleine-Budde struct can_ram_layout layout; 4629263c2e9SMarc Kleine-Budde 4639263c2e9SMarc Kleine-Budde can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, fd_mode); 4649263c2e9SMarc Kleine-Budde priv->rx_obj_num = layout.default_rx; 4659263c2e9SMarc Kleine-Budde tx_ring->obj_num = layout.default_tx; 46655bc37c8SMarc Kleine-Budde } 46755bc37c8SMarc Kleine-Budde 4689263c2e9SMarc Kleine-Budde if (fd_mode) { 4699263c2e9SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd); 4709263c2e9SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd); 4719263c2e9SMarc Kleine-Budde set_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags); 4729263c2e9SMarc Kleine-Budde } else { 4739263c2e9SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can); 4749263c2e9SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can); 4759263c2e9SMarc Kleine-Budde clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags); 4769263c2e9SMarc Kleine-Budde } 477d86ba8dbSMarc Kleine-Budde 47855bc37c8SMarc Kleine-Budde tx_ring->obj_size = tx_obj_size; 47955bc37c8SMarc Kleine-Budde 4809263c2e9SMarc Kleine-Budde rem = priv->rx_obj_num; 4810a1f2e65SMarc Kleine-Budde for (i = 0; i < ARRAY_SIZE(priv->rx) && rem; i++) { 4820a1f2e65SMarc Kleine-Budde u8 rx_obj_num; 48355bc37c8SMarc Kleine-Budde 48460a848c5SMarc Kleine-Budde if (i == 0 && priv->rx_obj_num_coalesce_irq) 48560a848c5SMarc Kleine-Budde rx_obj_num = min_t(u8, priv->rx_obj_num_coalesce_irq * 2, 48660a848c5SMarc Kleine-Budde MCP251XFD_FIFO_DEPTH); 48760a848c5SMarc Kleine-Budde else 4880a1f2e65SMarc Kleine-Budde rx_obj_num = min_t(u8, rounddown_pow_of_two(rem), 4890a1f2e65SMarc Kleine-Budde MCP251XFD_FIFO_DEPTH); 4900a1f2e65SMarc Kleine-Budde rem -= rx_obj_num; 49155bc37c8SMarc Kleine-Budde 49255bc37c8SMarc Kleine-Budde rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num, 49355bc37c8SMarc Kleine-Budde GFP_KERNEL); 49455bc37c8SMarc Kleine-Budde if (!rx_ring) { 49555bc37c8SMarc Kleine-Budde mcp251xfd_ring_free(priv); 49655bc37c8SMarc Kleine-Budde return -ENOMEM; 49755bc37c8SMarc Kleine-Budde } 4980a1f2e65SMarc Kleine-Budde 49955bc37c8SMarc Kleine-Budde rx_ring->obj_num = rx_obj_num; 50055bc37c8SMarc Kleine-Budde rx_ring->obj_size = rx_obj_size; 50155bc37c8SMarc Kleine-Budde priv->rx[i] = rx_ring; 50255bc37c8SMarc Kleine-Budde } 50355bc37c8SMarc Kleine-Budde priv->rx_ring_num = i; 50455bc37c8SMarc Kleine-Budde 50560a848c5SMarc Kleine-Budde hrtimer_init(&priv->rx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 50660a848c5SMarc Kleine-Budde priv->rx_irq_timer.function = mcp251xfd_rx_irq_timer; 50760a848c5SMarc Kleine-Budde 508169d00a2SMarc Kleine-Budde hrtimer_init(&priv->tx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 509169d00a2SMarc Kleine-Budde priv->tx_irq_timer.function = mcp251xfd_tx_irq_timer; 510169d00a2SMarc Kleine-Budde 51155bc37c8SMarc Kleine-Budde return 0; 51255bc37c8SMarc Kleine-Budde } 513