109b0eb92SMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0 209b0eb92SMarc Kleine-Budde // 309b0eb92SMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver 409b0eb92SMarc Kleine-Budde // 509b0eb92SMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021 Pengutronix, 609b0eb92SMarc Kleine-Budde // Marc Kleine-Budde <kernel@pengutronix.de> 709b0eb92SMarc Kleine-Budde // 809b0eb92SMarc Kleine-Budde // Based on: 909b0eb92SMarc Kleine-Budde // 1009b0eb92SMarc Kleine-Budde // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface 1109b0eb92SMarc Kleine-Budde // 1209b0eb92SMarc Kleine-Budde // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org> 1309b0eb92SMarc Kleine-Budde // 1409b0eb92SMarc Kleine-Budde 1509b0eb92SMarc Kleine-Budde #include <asm/unaligned.h> 1609b0eb92SMarc Kleine-Budde #include <linux/bitfield.h> 1709b0eb92SMarc Kleine-Budde 1809b0eb92SMarc Kleine-Budde #include "mcp251xfd.h" 1909b0eb92SMarc Kleine-Budde 2009b0eb92SMarc Kleine-Budde static inline struct 2109b0eb92SMarc Kleine-Budde mcp251xfd_tx_obj *mcp251xfd_get_tx_obj_next(struct mcp251xfd_tx_ring *tx_ring) 2209b0eb92SMarc Kleine-Budde { 2309b0eb92SMarc Kleine-Budde u8 tx_head; 2409b0eb92SMarc Kleine-Budde 2509b0eb92SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 2609b0eb92SMarc Kleine-Budde 2709b0eb92SMarc Kleine-Budde return &tx_ring->obj[tx_head]; 2809b0eb92SMarc Kleine-Budde } 2909b0eb92SMarc Kleine-Budde 3009b0eb92SMarc Kleine-Budde static void 3109b0eb92SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv, 3209b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj, 3309b0eb92SMarc Kleine-Budde const struct sk_buff *skb, 3409b0eb92SMarc Kleine-Budde unsigned int seq) 3509b0eb92SMarc Kleine-Budde { 3609b0eb92SMarc Kleine-Budde const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 3709b0eb92SMarc Kleine-Budde struct mcp251xfd_hw_tx_obj_raw *hw_tx_obj; 3809b0eb92SMarc Kleine-Budde union mcp251xfd_tx_obj_load_buf *load_buf; 3909b0eb92SMarc Kleine-Budde u8 dlc; 4009b0eb92SMarc Kleine-Budde u32 id, flags; 4109b0eb92SMarc Kleine-Budde int len_sanitized = 0, len; 4209b0eb92SMarc Kleine-Budde 4309b0eb92SMarc Kleine-Budde if (cfd->can_id & CAN_EFF_FLAG) { 4409b0eb92SMarc Kleine-Budde u32 sid, eid; 4509b0eb92SMarc Kleine-Budde 4609b0eb92SMarc Kleine-Budde sid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_SID_MASK, cfd->can_id); 4709b0eb92SMarc Kleine-Budde eid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_EID_MASK, cfd->can_id); 4809b0eb92SMarc Kleine-Budde 4909b0eb92SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_EID_MASK, eid) | 5009b0eb92SMarc Kleine-Budde FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, sid); 5109b0eb92SMarc Kleine-Budde 5209b0eb92SMarc Kleine-Budde flags = MCP251XFD_OBJ_FLAGS_IDE; 5309b0eb92SMarc Kleine-Budde } else { 5409b0eb92SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, cfd->can_id); 5509b0eb92SMarc Kleine-Budde flags = 0; 5609b0eb92SMarc Kleine-Budde } 5709b0eb92SMarc Kleine-Budde 5809b0eb92SMarc Kleine-Budde /* Use the MCP2518FD mask even on the MCP2517FD. It doesn't 5909b0eb92SMarc Kleine-Budde * harm, only the lower 7 bits will be transferred into the 6009b0eb92SMarc Kleine-Budde * TEF object. 6109b0eb92SMarc Kleine-Budde */ 6209b0eb92SMarc Kleine-Budde flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq); 6309b0eb92SMarc Kleine-Budde 6409b0eb92SMarc Kleine-Budde if (cfd->can_id & CAN_RTR_FLAG) 6509b0eb92SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_RTR; 6609b0eb92SMarc Kleine-Budde else 6709b0eb92SMarc Kleine-Budde len_sanitized = canfd_sanitize_len(cfd->len); 6809b0eb92SMarc Kleine-Budde 6909b0eb92SMarc Kleine-Budde /* CANFD */ 7009b0eb92SMarc Kleine-Budde if (can_is_canfd_skb(skb)) { 7109b0eb92SMarc Kleine-Budde if (cfd->flags & CANFD_ESI) 7209b0eb92SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_ESI; 7309b0eb92SMarc Kleine-Budde 7409b0eb92SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_FDF; 7509b0eb92SMarc Kleine-Budde 7609b0eb92SMarc Kleine-Budde if (cfd->flags & CANFD_BRS) 7709b0eb92SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_BRS; 7809b0eb92SMarc Kleine-Budde 7909b0eb92SMarc Kleine-Budde dlc = can_fd_len2dlc(cfd->len); 8009b0eb92SMarc Kleine-Budde } else { 8109b0eb92SMarc Kleine-Budde dlc = can_get_cc_dlc((struct can_frame *)cfd, 8209b0eb92SMarc Kleine-Budde priv->can.ctrlmode); 8309b0eb92SMarc Kleine-Budde } 8409b0eb92SMarc Kleine-Budde 8509b0eb92SMarc Kleine-Budde flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC_MASK, dlc); 8609b0eb92SMarc Kleine-Budde 8709b0eb92SMarc Kleine-Budde load_buf = &tx_obj->buf; 8809b0eb92SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) 8909b0eb92SMarc Kleine-Budde hw_tx_obj = &load_buf->crc.hw_tx_obj; 9009b0eb92SMarc Kleine-Budde else 9109b0eb92SMarc Kleine-Budde hw_tx_obj = &load_buf->nocrc.hw_tx_obj; 9209b0eb92SMarc Kleine-Budde 9309b0eb92SMarc Kleine-Budde put_unaligned_le32(id, &hw_tx_obj->id); 9409b0eb92SMarc Kleine-Budde put_unaligned_le32(flags, &hw_tx_obj->flags); 9509b0eb92SMarc Kleine-Budde 9609b0eb92SMarc Kleine-Budde /* Copy data */ 9709b0eb92SMarc Kleine-Budde memcpy(hw_tx_obj->data, cfd->data, cfd->len); 9809b0eb92SMarc Kleine-Budde 9909b0eb92SMarc Kleine-Budde /* Clear unused data at end of CAN frame */ 10009b0eb92SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN && len_sanitized) { 10109b0eb92SMarc Kleine-Budde int pad_len; 10209b0eb92SMarc Kleine-Budde 10309b0eb92SMarc Kleine-Budde pad_len = len_sanitized - cfd->len; 10409b0eb92SMarc Kleine-Budde if (pad_len) 10509b0eb92SMarc Kleine-Budde memset(hw_tx_obj->data + cfd->len, 0x0, pad_len); 10609b0eb92SMarc Kleine-Budde } 10709b0eb92SMarc Kleine-Budde 10809b0eb92SMarc Kleine-Budde /* Number of bytes to be written into the RAM of the controller */ 10909b0eb92SMarc Kleine-Budde len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags); 11009b0eb92SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN) 11109b0eb92SMarc Kleine-Budde len += round_up(len_sanitized, sizeof(u32)); 11209b0eb92SMarc Kleine-Budde else 11309b0eb92SMarc Kleine-Budde len += round_up(cfd->len, sizeof(u32)); 11409b0eb92SMarc Kleine-Budde 11509b0eb92SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) { 11609b0eb92SMarc Kleine-Budde u16 crc; 11709b0eb92SMarc Kleine-Budde 11809b0eb92SMarc Kleine-Budde mcp251xfd_spi_cmd_crc_set_len_in_ram(&load_buf->crc.cmd, 11909b0eb92SMarc Kleine-Budde len); 12009b0eb92SMarc Kleine-Budde /* CRC */ 12109b0eb92SMarc Kleine-Budde len += sizeof(load_buf->crc.cmd); 12209b0eb92SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(&load_buf->crc, len); 12309b0eb92SMarc Kleine-Budde put_unaligned_be16(crc, (void *)load_buf + len); 12409b0eb92SMarc Kleine-Budde 12509b0eb92SMarc Kleine-Budde /* Total length */ 12609b0eb92SMarc Kleine-Budde len += sizeof(load_buf->crc.crc); 12709b0eb92SMarc Kleine-Budde } else { 12809b0eb92SMarc Kleine-Budde len += sizeof(load_buf->nocrc.cmd); 12909b0eb92SMarc Kleine-Budde } 13009b0eb92SMarc Kleine-Budde 13109b0eb92SMarc Kleine-Budde tx_obj->xfer[0].len = len; 13209b0eb92SMarc Kleine-Budde } 13309b0eb92SMarc Kleine-Budde 13409b0eb92SMarc Kleine-Budde static int mcp251xfd_tx_obj_write(const struct mcp251xfd_priv *priv, 13509b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj) 13609b0eb92SMarc Kleine-Budde { 13709b0eb92SMarc Kleine-Budde return spi_async(priv->spi, &tx_obj->msg); 13809b0eb92SMarc Kleine-Budde } 13909b0eb92SMarc Kleine-Budde 14009b0eb92SMarc Kleine-Budde static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv, 14109b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring) 14209b0eb92SMarc Kleine-Budde { 14309b0eb92SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) > 0) 14409b0eb92SMarc Kleine-Budde return false; 14509b0eb92SMarc Kleine-Budde 14609b0eb92SMarc Kleine-Budde netif_stop_queue(priv->ndev); 14709b0eb92SMarc Kleine-Budde 14809b0eb92SMarc Kleine-Budde /* Memory barrier before checking tx_free (head and tail) */ 14909b0eb92SMarc Kleine-Budde smp_mb(); 15009b0eb92SMarc Kleine-Budde 15109b0eb92SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) == 0) { 15209b0eb92SMarc Kleine-Budde netdev_dbg(priv->ndev, 15309b0eb92SMarc Kleine-Budde "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n", 15409b0eb92SMarc Kleine-Budde tx_ring->head, tx_ring->tail, 15509b0eb92SMarc Kleine-Budde tx_ring->head - tx_ring->tail); 15609b0eb92SMarc Kleine-Budde 15709b0eb92SMarc Kleine-Budde return true; 15809b0eb92SMarc Kleine-Budde } 15909b0eb92SMarc Kleine-Budde 16009b0eb92SMarc Kleine-Budde netif_start_queue(priv->ndev); 16109b0eb92SMarc Kleine-Budde 16209b0eb92SMarc Kleine-Budde return false; 16309b0eb92SMarc Kleine-Budde } 16409b0eb92SMarc Kleine-Budde 16509b0eb92SMarc Kleine-Budde netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb, 16609b0eb92SMarc Kleine-Budde struct net_device *ndev) 16709b0eb92SMarc Kleine-Budde { 16809b0eb92SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 16909b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 17009b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 17109b0eb92SMarc Kleine-Budde unsigned int frame_len; 17209b0eb92SMarc Kleine-Budde u8 tx_head; 17309b0eb92SMarc Kleine-Budde int err; 17409b0eb92SMarc Kleine-Budde 175*ae64438bSOliver Hartkopp if (can_dev_dropped_skb(ndev, skb)) 17609b0eb92SMarc Kleine-Budde return NETDEV_TX_OK; 17709b0eb92SMarc Kleine-Budde 17809b0eb92SMarc Kleine-Budde if (mcp251xfd_tx_busy(priv, tx_ring)) 17909b0eb92SMarc Kleine-Budde return NETDEV_TX_BUSY; 18009b0eb92SMarc Kleine-Budde 18109b0eb92SMarc Kleine-Budde tx_obj = mcp251xfd_get_tx_obj_next(tx_ring); 18209b0eb92SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(priv, tx_obj, skb, tx_ring->head); 18309b0eb92SMarc Kleine-Budde 18409b0eb92SMarc Kleine-Budde /* Stop queue if we occupy the complete TX FIFO */ 18509b0eb92SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 18609b0eb92SMarc Kleine-Budde tx_ring->head++; 18709b0eb92SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) == 0) 18809b0eb92SMarc Kleine-Budde netif_stop_queue(ndev); 18909b0eb92SMarc Kleine-Budde 19009b0eb92SMarc Kleine-Budde frame_len = can_skb_get_frame_len(skb); 19109b0eb92SMarc Kleine-Budde err = can_put_echo_skb(skb, ndev, tx_head, frame_len); 19209b0eb92SMarc Kleine-Budde if (!err) 19309b0eb92SMarc Kleine-Budde netdev_sent_queue(priv->ndev, frame_len); 19409b0eb92SMarc Kleine-Budde 19509b0eb92SMarc Kleine-Budde err = mcp251xfd_tx_obj_write(priv, tx_obj); 19609b0eb92SMarc Kleine-Budde if (err) 19709b0eb92SMarc Kleine-Budde goto out_err; 19809b0eb92SMarc Kleine-Budde 19909b0eb92SMarc Kleine-Budde return NETDEV_TX_OK; 20009b0eb92SMarc Kleine-Budde 20109b0eb92SMarc Kleine-Budde out_err: 20209b0eb92SMarc Kleine-Budde netdev_err(priv->ndev, "ERROR in %s: %d\n", __func__, err); 20309b0eb92SMarc Kleine-Budde 20409b0eb92SMarc Kleine-Budde return NETDEV_TX_OK; 20509b0eb92SMarc Kleine-Budde } 206