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 <linux/bitfield.h>
0016 
0017 #include "mcp251xfd.h"
0018 
0019 static inline int
0020 mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv,
0021                 const struct mcp251xfd_rx_ring *ring,
0022                 u8 *rx_head, bool *fifo_empty)
0023 {
0024     u32 fifo_sta;
0025     int err;
0026 
0027     err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(ring->fifo_nr),
0028               &fifo_sta);
0029     if (err)
0030         return err;
0031 
0032     *rx_head = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
0033     *fifo_empty = !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF);
0034 
0035     return 0;
0036 }
0037 
0038 static inline int
0039 mcp251xfd_rx_tail_get_from_chip(const struct mcp251xfd_priv *priv,
0040                 const struct mcp251xfd_rx_ring *ring,
0041                 u8 *rx_tail)
0042 {
0043     u32 fifo_ua;
0044     int err;
0045 
0046     err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOUA(ring->fifo_nr),
0047               &fifo_ua);
0048     if (err)
0049         return err;
0050 
0051     fifo_ua -= ring->base - MCP251XFD_RAM_START;
0052     *rx_tail = fifo_ua / ring->obj_size;
0053 
0054     return 0;
0055 }
0056 
0057 static int
0058 mcp251xfd_check_rx_tail(const struct mcp251xfd_priv *priv,
0059             const struct mcp251xfd_rx_ring *ring)
0060 {
0061     u8 rx_tail_chip, rx_tail;
0062     int err;
0063 
0064     if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY))
0065         return 0;
0066 
0067     err = mcp251xfd_rx_tail_get_from_chip(priv, ring, &rx_tail_chip);
0068     if (err)
0069         return err;
0070 
0071     rx_tail = mcp251xfd_get_rx_tail(ring);
0072     if (rx_tail_chip != rx_tail) {
0073         netdev_err(priv->ndev,
0074                "RX tail of chip (%d) and ours (%d) inconsistent.\n",
0075                rx_tail_chip, rx_tail);
0076         return -EILSEQ;
0077     }
0078 
0079     return 0;
0080 }
0081 
0082 static int
0083 mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv,
0084              struct mcp251xfd_rx_ring *ring)
0085 {
0086     u32 new_head;
0087     u8 chip_rx_head;
0088     bool fifo_empty;
0089     int err;
0090 
0091     err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head,
0092                           &fifo_empty);
0093     if (err || fifo_empty)
0094         return err;
0095 
0096     /* chip_rx_head, is the next RX-Object filled by the HW.
0097      * The new RX head must be >= the old head.
0098      */
0099     new_head = round_down(ring->head, ring->obj_num) + chip_rx_head;
0100     if (new_head <= ring->head)
0101         new_head += ring->obj_num;
0102 
0103     ring->head = new_head;
0104 
0105     return mcp251xfd_check_rx_tail(priv, ring);
0106 }
0107 
0108 static void
0109 mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv,
0110                const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
0111                struct sk_buff *skb)
0112 {
0113     struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
0114     u8 dlc;
0115 
0116     if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_IDE) {
0117         u32 sid, eid;
0118 
0119         eid = FIELD_GET(MCP251XFD_OBJ_ID_EID_MASK, hw_rx_obj->id);
0120         sid = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, hw_rx_obj->id);
0121 
0122         cfd->can_id = CAN_EFF_FLAG |
0123             FIELD_PREP(MCP251XFD_REG_FRAME_EFF_EID_MASK, eid) |
0124             FIELD_PREP(MCP251XFD_REG_FRAME_EFF_SID_MASK, sid);
0125     } else {
0126         cfd->can_id = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK,
0127                     hw_rx_obj->id);
0128     }
0129 
0130     dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC_MASK, hw_rx_obj->flags);
0131 
0132     /* CANFD */
0133     if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) {
0134         if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_ESI)
0135             cfd->flags |= CANFD_ESI;
0136 
0137         if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_BRS)
0138             cfd->flags |= CANFD_BRS;
0139 
0140         cfd->len = can_fd_dlc2len(dlc);
0141     } else {
0142         if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR)
0143             cfd->can_id |= CAN_RTR_FLAG;
0144 
0145         can_frame_set_cc_len((struct can_frame *)cfd, dlc,
0146                      priv->can.ctrlmode);
0147     }
0148 
0149     if (!(hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR))
0150         memcpy(cfd->data, hw_rx_obj->data, cfd->len);
0151 
0152     mcp251xfd_skb_set_timestamp(priv, skb, hw_rx_obj->ts);
0153 }
0154 
0155 static int
0156 mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv,
0157               struct mcp251xfd_rx_ring *ring,
0158               const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj)
0159 {
0160     struct net_device_stats *stats = &priv->ndev->stats;
0161     struct sk_buff *skb;
0162     struct canfd_frame *cfd;
0163     int err;
0164 
0165     if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF)
0166         skb = alloc_canfd_skb(priv->ndev, &cfd);
0167     else
0168         skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cfd);
0169 
0170     if (!skb) {
0171         stats->rx_dropped++;
0172         return 0;
0173     }
0174 
0175     mcp251xfd_hw_rx_obj_to_skb(priv, hw_rx_obj, skb);
0176     err = can_rx_offload_queue_timestamp(&priv->offload, skb, hw_rx_obj->ts);
0177     if (err)
0178         stats->rx_fifo_errors++;
0179 
0180     return 0;
0181 }
0182 
0183 static inline int
0184 mcp251xfd_rx_obj_read(const struct mcp251xfd_priv *priv,
0185               const struct mcp251xfd_rx_ring *ring,
0186               struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
0187               const u8 offset, const u8 len)
0188 {
0189     const int val_bytes = regmap_get_val_bytes(priv->map_rx);
0190     int err;
0191 
0192     err = regmap_bulk_read(priv->map_rx,
0193                    mcp251xfd_get_rx_obj_addr(ring, offset),
0194                    hw_rx_obj,
0195                    len * ring->obj_size / val_bytes);
0196 
0197     return err;
0198 }
0199 
0200 static int
0201 mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
0202                struct mcp251xfd_rx_ring *ring)
0203 {
0204     struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj = ring->obj;
0205     u8 rx_tail, len;
0206     int err, i;
0207 
0208     err = mcp251xfd_rx_ring_update(priv, ring);
0209     if (err)
0210         return err;
0211 
0212     while ((len = mcp251xfd_get_rx_linear_len(ring))) {
0213         int offset;
0214 
0215         rx_tail = mcp251xfd_get_rx_tail(ring);
0216 
0217         err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj,
0218                         rx_tail, len);
0219         if (err)
0220             return err;
0221 
0222         for (i = 0; i < len; i++) {
0223             err = mcp251xfd_handle_rxif_one(priv, ring,
0224                             (void *)hw_rx_obj +
0225                             i * ring->obj_size);
0226             if (err)
0227                 return err;
0228         }
0229 
0230         /* Increment the RX FIFO tail pointer 'len' times in a
0231          * single SPI message.
0232          *
0233          * Note:
0234          * Calculate offset, so that the SPI transfer ends on
0235          * the last message of the uinc_xfer array, which has
0236          * "cs_change == 0", to properly deactivate the chip
0237          * select.
0238          */
0239         offset = ARRAY_SIZE(ring->uinc_xfer) - len;
0240         err = spi_sync_transfer(priv->spi,
0241                     ring->uinc_xfer + offset, len);
0242         if (err)
0243             return err;
0244 
0245         ring->tail += len;
0246     }
0247 
0248     return 0;
0249 }
0250 
0251 int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv)
0252 {
0253     struct mcp251xfd_rx_ring *ring;
0254     int err, n;
0255 
0256     mcp251xfd_for_each_rx_ring(priv, ring, n) {
0257         /* - if RX IRQ coalescing is active always handle ring 0
0258          * - only handle rings if RX IRQ is active
0259          */
0260         if ((ring->nr > 0 || !priv->rx_obj_num_coalesce_irq) &&
0261             !(priv->regs_status.rxif & BIT(ring->fifo_nr)))
0262             continue;
0263 
0264         err = mcp251xfd_handle_rxif_ring(priv, ring);
0265         if (err)
0266             return err;
0267     }
0268 
0269     if (priv->rx_coalesce_usecs_irq)
0270         hrtimer_start(&priv->rx_irq_timer,
0271                   ns_to_ktime(priv->rx_coalesce_usecs_irq *
0272                       NSEC_PER_USEC),
0273                   HRTIMER_MODE_REL);
0274 
0275     return 0;
0276 }