Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
0004 //
0005 // Copyright (c) 2019, 2020, 2021 Pengutronix,
0006 //               Marc Kleine-Budde <kernel@pengutronix.de>
0007 //
0008 // Based on:
0009 //
0010 // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
0011 //
0012 // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
0013 //
0014 
0015 #include <asm/unaligned.h>
0016 #include <linux/bitfield.h>
0017 
0018 #include "mcp251xfd.h"
0019 
0020 static inline struct
0021 mcp251xfd_tx_obj *mcp251xfd_get_tx_obj_next(struct mcp251xfd_tx_ring *tx_ring)
0022 {
0023     u8 tx_head;
0024 
0025     tx_head = mcp251xfd_get_tx_head(tx_ring);
0026 
0027     return &tx_ring->obj[tx_head];
0028 }
0029 
0030 static void
0031 mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv,
0032               struct mcp251xfd_tx_obj *tx_obj,
0033               const struct sk_buff *skb,
0034               unsigned int seq)
0035 {
0036     const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
0037     struct mcp251xfd_hw_tx_obj_raw *hw_tx_obj;
0038     union mcp251xfd_tx_obj_load_buf *load_buf;
0039     u8 dlc;
0040     u32 id, flags;
0041     int len_sanitized = 0, len;
0042 
0043     if (cfd->can_id & CAN_EFF_FLAG) {
0044         u32 sid, eid;
0045 
0046         sid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_SID_MASK, cfd->can_id);
0047         eid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_EID_MASK, cfd->can_id);
0048 
0049         id = FIELD_PREP(MCP251XFD_OBJ_ID_EID_MASK, eid) |
0050             FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, sid);
0051 
0052         flags = MCP251XFD_OBJ_FLAGS_IDE;
0053     } else {
0054         id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, cfd->can_id);
0055         flags = 0;
0056     }
0057 
0058     /* Use the MCP2518FD mask even on the MCP2517FD. It doesn't
0059      * harm, only the lower 7 bits will be transferred into the
0060      * TEF object.
0061      */
0062     flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq);
0063 
0064     if (cfd->can_id & CAN_RTR_FLAG)
0065         flags |= MCP251XFD_OBJ_FLAGS_RTR;
0066     else
0067         len_sanitized = canfd_sanitize_len(cfd->len);
0068 
0069     /* CANFD */
0070     if (can_is_canfd_skb(skb)) {
0071         if (cfd->flags & CANFD_ESI)
0072             flags |= MCP251XFD_OBJ_FLAGS_ESI;
0073 
0074         flags |= MCP251XFD_OBJ_FLAGS_FDF;
0075 
0076         if (cfd->flags & CANFD_BRS)
0077             flags |= MCP251XFD_OBJ_FLAGS_BRS;
0078 
0079         dlc = can_fd_len2dlc(cfd->len);
0080     } else {
0081         dlc = can_get_cc_dlc((struct can_frame *)cfd,
0082                      priv->can.ctrlmode);
0083     }
0084 
0085     flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC_MASK, dlc);
0086 
0087     load_buf = &tx_obj->buf;
0088     if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX)
0089         hw_tx_obj = &load_buf->crc.hw_tx_obj;
0090     else
0091         hw_tx_obj = &load_buf->nocrc.hw_tx_obj;
0092 
0093     put_unaligned_le32(id, &hw_tx_obj->id);
0094     put_unaligned_le32(flags, &hw_tx_obj->flags);
0095 
0096     /* Copy data */
0097     memcpy(hw_tx_obj->data, cfd->data, cfd->len);
0098 
0099     /* Clear unused data at end of CAN frame */
0100     if (MCP251XFD_SANITIZE_CAN && len_sanitized) {
0101         int pad_len;
0102 
0103         pad_len = len_sanitized - cfd->len;
0104         if (pad_len)
0105             memset(hw_tx_obj->data + cfd->len, 0x0, pad_len);
0106     }
0107 
0108     /* Number of bytes to be written into the RAM of the controller */
0109     len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags);
0110     if (MCP251XFD_SANITIZE_CAN)
0111         len += round_up(len_sanitized, sizeof(u32));
0112     else
0113         len += round_up(cfd->len, sizeof(u32));
0114 
0115     if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) {
0116         u16 crc;
0117 
0118         mcp251xfd_spi_cmd_crc_set_len_in_ram(&load_buf->crc.cmd,
0119                              len);
0120         /* CRC */
0121         len += sizeof(load_buf->crc.cmd);
0122         crc = mcp251xfd_crc16_compute(&load_buf->crc, len);
0123         put_unaligned_be16(crc, (void *)load_buf + len);
0124 
0125         /* Total length */
0126         len += sizeof(load_buf->crc.crc);
0127     } else {
0128         len += sizeof(load_buf->nocrc.cmd);
0129     }
0130 
0131     tx_obj->xfer[0].len = len;
0132 }
0133 
0134 static int mcp251xfd_tx_obj_write(const struct mcp251xfd_priv *priv,
0135                   struct mcp251xfd_tx_obj *tx_obj)
0136 {
0137     return spi_async(priv->spi, &tx_obj->msg);
0138 }
0139 
0140 static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv,
0141                   struct mcp251xfd_tx_ring *tx_ring)
0142 {
0143     if (mcp251xfd_get_tx_free(tx_ring) > 0)
0144         return false;
0145 
0146     netif_stop_queue(priv->ndev);
0147 
0148     /* Memory barrier before checking tx_free (head and tail) */
0149     smp_mb();
0150 
0151     if (mcp251xfd_get_tx_free(tx_ring) == 0) {
0152         netdev_dbg(priv->ndev,
0153                "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n",
0154                tx_ring->head, tx_ring->tail,
0155                tx_ring->head - tx_ring->tail);
0156 
0157         return true;
0158     }
0159 
0160     netif_start_queue(priv->ndev);
0161 
0162     return false;
0163 }
0164 
0165 netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
0166                  struct net_device *ndev)
0167 {
0168     struct mcp251xfd_priv *priv = netdev_priv(ndev);
0169     struct mcp251xfd_tx_ring *tx_ring = priv->tx;
0170     struct mcp251xfd_tx_obj *tx_obj;
0171     unsigned int frame_len;
0172     u8 tx_head;
0173     int err;
0174 
0175     if (can_dropped_invalid_skb(ndev, skb))
0176         return NETDEV_TX_OK;
0177 
0178     if (mcp251xfd_tx_busy(priv, tx_ring))
0179         return NETDEV_TX_BUSY;
0180 
0181     tx_obj = mcp251xfd_get_tx_obj_next(tx_ring);
0182     mcp251xfd_tx_obj_from_skb(priv, tx_obj, skb, tx_ring->head);
0183 
0184     /* Stop queue if we occupy the complete TX FIFO */
0185     tx_head = mcp251xfd_get_tx_head(tx_ring);
0186     tx_ring->head++;
0187     if (mcp251xfd_get_tx_free(tx_ring) == 0)
0188         netif_stop_queue(ndev);
0189 
0190     frame_len = can_skb_get_frame_len(skb);
0191     err = can_put_echo_skb(skb, ndev, tx_head, frame_len);
0192     if (!err)
0193         netdev_sent_queue(priv->ndev, frame_len);
0194 
0195     err = mcp251xfd_tx_obj_write(priv, tx_obj);
0196     if (err)
0197         goto out_err;
0198 
0199     return NETDEV_TX_OK;
0200 
0201  out_err:
0202     netdev_err(priv->ndev, "ERROR in %s: %d\n", __func__, err);
0203 
0204     return NETDEV_TX_OK;
0205 }