1*09b0eb92SMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0 2*09b0eb92SMarc Kleine-Budde // 3*09b0eb92SMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver 4*09b0eb92SMarc Kleine-Budde // 5*09b0eb92SMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021 Pengutronix, 6*09b0eb92SMarc Kleine-Budde // Marc Kleine-Budde <kernel@pengutronix.de> 7*09b0eb92SMarc Kleine-Budde // 8*09b0eb92SMarc Kleine-Budde // Based on: 9*09b0eb92SMarc Kleine-Budde // 10*09b0eb92SMarc Kleine-Budde // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface 11*09b0eb92SMarc Kleine-Budde // 12*09b0eb92SMarc Kleine-Budde // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org> 13*09b0eb92SMarc Kleine-Budde // 14*09b0eb92SMarc Kleine-Budde 15*09b0eb92SMarc Kleine-Budde #include <asm/unaligned.h> 16*09b0eb92SMarc Kleine-Budde #include <linux/bitfield.h> 17*09b0eb92SMarc Kleine-Budde 18*09b0eb92SMarc Kleine-Budde #include "mcp251xfd.h" 19*09b0eb92SMarc Kleine-Budde 20*09b0eb92SMarc Kleine-Budde static inline struct 21*09b0eb92SMarc Kleine-Budde mcp251xfd_tx_obj *mcp251xfd_get_tx_obj_next(struct mcp251xfd_tx_ring *tx_ring) 22*09b0eb92SMarc Kleine-Budde { 23*09b0eb92SMarc Kleine-Budde u8 tx_head; 24*09b0eb92SMarc Kleine-Budde 25*09b0eb92SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 26*09b0eb92SMarc Kleine-Budde 27*09b0eb92SMarc Kleine-Budde return &tx_ring->obj[tx_head]; 28*09b0eb92SMarc Kleine-Budde } 29*09b0eb92SMarc Kleine-Budde 30*09b0eb92SMarc Kleine-Budde static void 31*09b0eb92SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv, 32*09b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj, 33*09b0eb92SMarc Kleine-Budde const struct sk_buff *skb, 34*09b0eb92SMarc Kleine-Budde unsigned int seq) 35*09b0eb92SMarc Kleine-Budde { 36*09b0eb92SMarc Kleine-Budde const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 37*09b0eb92SMarc Kleine-Budde struct mcp251xfd_hw_tx_obj_raw *hw_tx_obj; 38*09b0eb92SMarc Kleine-Budde union mcp251xfd_tx_obj_load_buf *load_buf; 39*09b0eb92SMarc Kleine-Budde u8 dlc; 40*09b0eb92SMarc Kleine-Budde u32 id, flags; 41*09b0eb92SMarc Kleine-Budde int len_sanitized = 0, len; 42*09b0eb92SMarc Kleine-Budde 43*09b0eb92SMarc Kleine-Budde if (cfd->can_id & CAN_EFF_FLAG) { 44*09b0eb92SMarc Kleine-Budde u32 sid, eid; 45*09b0eb92SMarc Kleine-Budde 46*09b0eb92SMarc Kleine-Budde sid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_SID_MASK, cfd->can_id); 47*09b0eb92SMarc Kleine-Budde eid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_EID_MASK, cfd->can_id); 48*09b0eb92SMarc Kleine-Budde 49*09b0eb92SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_EID_MASK, eid) | 50*09b0eb92SMarc Kleine-Budde FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, sid); 51*09b0eb92SMarc Kleine-Budde 52*09b0eb92SMarc Kleine-Budde flags = MCP251XFD_OBJ_FLAGS_IDE; 53*09b0eb92SMarc Kleine-Budde } else { 54*09b0eb92SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, cfd->can_id); 55*09b0eb92SMarc Kleine-Budde flags = 0; 56*09b0eb92SMarc Kleine-Budde } 57*09b0eb92SMarc Kleine-Budde 58*09b0eb92SMarc Kleine-Budde /* Use the MCP2518FD mask even on the MCP2517FD. It doesn't 59*09b0eb92SMarc Kleine-Budde * harm, only the lower 7 bits will be transferred into the 60*09b0eb92SMarc Kleine-Budde * TEF object. 61*09b0eb92SMarc Kleine-Budde */ 62*09b0eb92SMarc Kleine-Budde flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq); 63*09b0eb92SMarc Kleine-Budde 64*09b0eb92SMarc Kleine-Budde if (cfd->can_id & CAN_RTR_FLAG) 65*09b0eb92SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_RTR; 66*09b0eb92SMarc Kleine-Budde else 67*09b0eb92SMarc Kleine-Budde len_sanitized = canfd_sanitize_len(cfd->len); 68*09b0eb92SMarc Kleine-Budde 69*09b0eb92SMarc Kleine-Budde /* CANFD */ 70*09b0eb92SMarc Kleine-Budde if (can_is_canfd_skb(skb)) { 71*09b0eb92SMarc Kleine-Budde if (cfd->flags & CANFD_ESI) 72*09b0eb92SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_ESI; 73*09b0eb92SMarc Kleine-Budde 74*09b0eb92SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_FDF; 75*09b0eb92SMarc Kleine-Budde 76*09b0eb92SMarc Kleine-Budde if (cfd->flags & CANFD_BRS) 77*09b0eb92SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_BRS; 78*09b0eb92SMarc Kleine-Budde 79*09b0eb92SMarc Kleine-Budde dlc = can_fd_len2dlc(cfd->len); 80*09b0eb92SMarc Kleine-Budde } else { 81*09b0eb92SMarc Kleine-Budde dlc = can_get_cc_dlc((struct can_frame *)cfd, 82*09b0eb92SMarc Kleine-Budde priv->can.ctrlmode); 83*09b0eb92SMarc Kleine-Budde } 84*09b0eb92SMarc Kleine-Budde 85*09b0eb92SMarc Kleine-Budde flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC_MASK, dlc); 86*09b0eb92SMarc Kleine-Budde 87*09b0eb92SMarc Kleine-Budde load_buf = &tx_obj->buf; 88*09b0eb92SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) 89*09b0eb92SMarc Kleine-Budde hw_tx_obj = &load_buf->crc.hw_tx_obj; 90*09b0eb92SMarc Kleine-Budde else 91*09b0eb92SMarc Kleine-Budde hw_tx_obj = &load_buf->nocrc.hw_tx_obj; 92*09b0eb92SMarc Kleine-Budde 93*09b0eb92SMarc Kleine-Budde put_unaligned_le32(id, &hw_tx_obj->id); 94*09b0eb92SMarc Kleine-Budde put_unaligned_le32(flags, &hw_tx_obj->flags); 95*09b0eb92SMarc Kleine-Budde 96*09b0eb92SMarc Kleine-Budde /* Copy data */ 97*09b0eb92SMarc Kleine-Budde memcpy(hw_tx_obj->data, cfd->data, cfd->len); 98*09b0eb92SMarc Kleine-Budde 99*09b0eb92SMarc Kleine-Budde /* Clear unused data at end of CAN frame */ 100*09b0eb92SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN && len_sanitized) { 101*09b0eb92SMarc Kleine-Budde int pad_len; 102*09b0eb92SMarc Kleine-Budde 103*09b0eb92SMarc Kleine-Budde pad_len = len_sanitized - cfd->len; 104*09b0eb92SMarc Kleine-Budde if (pad_len) 105*09b0eb92SMarc Kleine-Budde memset(hw_tx_obj->data + cfd->len, 0x0, pad_len); 106*09b0eb92SMarc Kleine-Budde } 107*09b0eb92SMarc Kleine-Budde 108*09b0eb92SMarc Kleine-Budde /* Number of bytes to be written into the RAM of the controller */ 109*09b0eb92SMarc Kleine-Budde len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags); 110*09b0eb92SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN) 111*09b0eb92SMarc Kleine-Budde len += round_up(len_sanitized, sizeof(u32)); 112*09b0eb92SMarc Kleine-Budde else 113*09b0eb92SMarc Kleine-Budde len += round_up(cfd->len, sizeof(u32)); 114*09b0eb92SMarc Kleine-Budde 115*09b0eb92SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) { 116*09b0eb92SMarc Kleine-Budde u16 crc; 117*09b0eb92SMarc Kleine-Budde 118*09b0eb92SMarc Kleine-Budde mcp251xfd_spi_cmd_crc_set_len_in_ram(&load_buf->crc.cmd, 119*09b0eb92SMarc Kleine-Budde len); 120*09b0eb92SMarc Kleine-Budde /* CRC */ 121*09b0eb92SMarc Kleine-Budde len += sizeof(load_buf->crc.cmd); 122*09b0eb92SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(&load_buf->crc, len); 123*09b0eb92SMarc Kleine-Budde put_unaligned_be16(crc, (void *)load_buf + len); 124*09b0eb92SMarc Kleine-Budde 125*09b0eb92SMarc Kleine-Budde /* Total length */ 126*09b0eb92SMarc Kleine-Budde len += sizeof(load_buf->crc.crc); 127*09b0eb92SMarc Kleine-Budde } else { 128*09b0eb92SMarc Kleine-Budde len += sizeof(load_buf->nocrc.cmd); 129*09b0eb92SMarc Kleine-Budde } 130*09b0eb92SMarc Kleine-Budde 131*09b0eb92SMarc Kleine-Budde tx_obj->xfer[0].len = len; 132*09b0eb92SMarc Kleine-Budde } 133*09b0eb92SMarc Kleine-Budde 134*09b0eb92SMarc Kleine-Budde static int mcp251xfd_tx_obj_write(const struct mcp251xfd_priv *priv, 135*09b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj) 136*09b0eb92SMarc Kleine-Budde { 137*09b0eb92SMarc Kleine-Budde return spi_async(priv->spi, &tx_obj->msg); 138*09b0eb92SMarc Kleine-Budde } 139*09b0eb92SMarc Kleine-Budde 140*09b0eb92SMarc Kleine-Budde static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv, 141*09b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring) 142*09b0eb92SMarc Kleine-Budde { 143*09b0eb92SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) > 0) 144*09b0eb92SMarc Kleine-Budde return false; 145*09b0eb92SMarc Kleine-Budde 146*09b0eb92SMarc Kleine-Budde netif_stop_queue(priv->ndev); 147*09b0eb92SMarc Kleine-Budde 148*09b0eb92SMarc Kleine-Budde /* Memory barrier before checking tx_free (head and tail) */ 149*09b0eb92SMarc Kleine-Budde smp_mb(); 150*09b0eb92SMarc Kleine-Budde 151*09b0eb92SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) == 0) { 152*09b0eb92SMarc Kleine-Budde netdev_dbg(priv->ndev, 153*09b0eb92SMarc Kleine-Budde "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n", 154*09b0eb92SMarc Kleine-Budde tx_ring->head, tx_ring->tail, 155*09b0eb92SMarc Kleine-Budde tx_ring->head - tx_ring->tail); 156*09b0eb92SMarc Kleine-Budde 157*09b0eb92SMarc Kleine-Budde return true; 158*09b0eb92SMarc Kleine-Budde } 159*09b0eb92SMarc Kleine-Budde 160*09b0eb92SMarc Kleine-Budde netif_start_queue(priv->ndev); 161*09b0eb92SMarc Kleine-Budde 162*09b0eb92SMarc Kleine-Budde return false; 163*09b0eb92SMarc Kleine-Budde } 164*09b0eb92SMarc Kleine-Budde 165*09b0eb92SMarc Kleine-Budde netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb, 166*09b0eb92SMarc Kleine-Budde struct net_device *ndev) 167*09b0eb92SMarc Kleine-Budde { 168*09b0eb92SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 169*09b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 170*09b0eb92SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 171*09b0eb92SMarc Kleine-Budde unsigned int frame_len; 172*09b0eb92SMarc Kleine-Budde u8 tx_head; 173*09b0eb92SMarc Kleine-Budde int err; 174*09b0eb92SMarc Kleine-Budde 175*09b0eb92SMarc Kleine-Budde if (can_dropped_invalid_skb(ndev, skb)) 176*09b0eb92SMarc Kleine-Budde return NETDEV_TX_OK; 177*09b0eb92SMarc Kleine-Budde 178*09b0eb92SMarc Kleine-Budde if (mcp251xfd_tx_busy(priv, tx_ring)) 179*09b0eb92SMarc Kleine-Budde return NETDEV_TX_BUSY; 180*09b0eb92SMarc Kleine-Budde 181*09b0eb92SMarc Kleine-Budde tx_obj = mcp251xfd_get_tx_obj_next(tx_ring); 182*09b0eb92SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(priv, tx_obj, skb, tx_ring->head); 183*09b0eb92SMarc Kleine-Budde 184*09b0eb92SMarc Kleine-Budde /* Stop queue if we occupy the complete TX FIFO */ 185*09b0eb92SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 186*09b0eb92SMarc Kleine-Budde tx_ring->head++; 187*09b0eb92SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) == 0) 188*09b0eb92SMarc Kleine-Budde netif_stop_queue(ndev); 189*09b0eb92SMarc Kleine-Budde 190*09b0eb92SMarc Kleine-Budde frame_len = can_skb_get_frame_len(skb); 191*09b0eb92SMarc Kleine-Budde err = can_put_echo_skb(skb, ndev, tx_head, frame_len); 192*09b0eb92SMarc Kleine-Budde if (!err) 193*09b0eb92SMarc Kleine-Budde netdev_sent_queue(priv->ndev, frame_len); 194*09b0eb92SMarc Kleine-Budde 195*09b0eb92SMarc Kleine-Budde err = mcp251xfd_tx_obj_write(priv, tx_obj); 196*09b0eb92SMarc Kleine-Budde if (err) 197*09b0eb92SMarc Kleine-Budde goto out_err; 198*09b0eb92SMarc Kleine-Budde 199*09b0eb92SMarc Kleine-Budde return NETDEV_TX_OK; 200*09b0eb92SMarc Kleine-Budde 201*09b0eb92SMarc Kleine-Budde out_err: 202*09b0eb92SMarc Kleine-Budde netdev_err(priv->ndev, "ERROR in %s: %d\n", __func__, err); 203*09b0eb92SMarc Kleine-Budde 204*09b0eb92SMarc Kleine-Budde return NETDEV_TX_OK; 205*09b0eb92SMarc Kleine-Budde } 206