11e846c7aSMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0 21e846c7aSMarc Kleine-Budde // 31e846c7aSMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver 41e846c7aSMarc Kleine-Budde // 5*b8e0ddd3SMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021, 2023 Pengutronix, 61e846c7aSMarc Kleine-Budde // Marc Kleine-Budde <kernel@pengutronix.de> 71e846c7aSMarc Kleine-Budde // 81e846c7aSMarc Kleine-Budde // Based on: 91e846c7aSMarc Kleine-Budde // 101e846c7aSMarc Kleine-Budde // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface 111e846c7aSMarc Kleine-Budde // 121e846c7aSMarc Kleine-Budde // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org> 131e846c7aSMarc Kleine-Budde // 141e846c7aSMarc Kleine-Budde 151e846c7aSMarc Kleine-Budde #include <linux/bitfield.h> 161e846c7aSMarc Kleine-Budde 171e846c7aSMarc Kleine-Budde #include "mcp251xfd.h" 181e846c7aSMarc Kleine-Budde 19*b8e0ddd3SMarc Kleine-Budde static inline bool mcp251xfd_tx_fifo_sta_full(u32 fifo_sta) 20*b8e0ddd3SMarc Kleine-Budde { 21*b8e0ddd3SMarc Kleine-Budde return !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF); 22*b8e0ddd3SMarc Kleine-Budde } 23*b8e0ddd3SMarc Kleine-Budde 241e846c7aSMarc Kleine-Budde static inline int 251e846c7aSMarc Kleine-Budde mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv, 261e846c7aSMarc Kleine-Budde u8 *tef_tail) 271e846c7aSMarc Kleine-Budde { 281e846c7aSMarc Kleine-Budde u32 tef_ua; 291e846c7aSMarc Kleine-Budde int err; 301e846c7aSMarc Kleine-Budde 311e846c7aSMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFUA, &tef_ua); 321e846c7aSMarc Kleine-Budde if (err) 331e846c7aSMarc Kleine-Budde return err; 341e846c7aSMarc Kleine-Budde 351e846c7aSMarc Kleine-Budde *tef_tail = tef_ua / sizeof(struct mcp251xfd_hw_tef_obj); 361e846c7aSMarc Kleine-Budde 371e846c7aSMarc Kleine-Budde return 0; 381e846c7aSMarc Kleine-Budde } 391e846c7aSMarc Kleine-Budde 401e846c7aSMarc Kleine-Budde static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv) 411e846c7aSMarc Kleine-Budde { 421e846c7aSMarc Kleine-Budde u8 tef_tail_chip, tef_tail; 431e846c7aSMarc Kleine-Budde int err; 441e846c7aSMarc Kleine-Budde 451e846c7aSMarc Kleine-Budde if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY)) 461e846c7aSMarc Kleine-Budde return 0; 471e846c7aSMarc Kleine-Budde 481e846c7aSMarc Kleine-Budde err = mcp251xfd_tef_tail_get_from_chip(priv, &tef_tail_chip); 491e846c7aSMarc Kleine-Budde if (err) 501e846c7aSMarc Kleine-Budde return err; 511e846c7aSMarc Kleine-Budde 521e846c7aSMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 531e846c7aSMarc Kleine-Budde if (tef_tail_chip != tef_tail) { 541e846c7aSMarc Kleine-Budde netdev_err(priv->ndev, 551e846c7aSMarc Kleine-Budde "TEF tail of chip (0x%02x) and ours (0x%08x) inconsistent.\n", 561e846c7aSMarc Kleine-Budde tef_tail_chip, tef_tail); 571e846c7aSMarc Kleine-Budde return -EILSEQ; 581e846c7aSMarc Kleine-Budde } 591e846c7aSMarc Kleine-Budde 601e846c7aSMarc Kleine-Budde return 0; 611e846c7aSMarc Kleine-Budde } 621e846c7aSMarc Kleine-Budde 631e846c7aSMarc Kleine-Budde static int 641e846c7aSMarc Kleine-Budde mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq) 651e846c7aSMarc Kleine-Budde { 661e846c7aSMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 671e846c7aSMarc Kleine-Budde u32 tef_sta; 681e846c7aSMarc Kleine-Budde int err; 691e846c7aSMarc Kleine-Budde 701e846c7aSMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta); 711e846c7aSMarc Kleine-Budde if (err) 721e846c7aSMarc Kleine-Budde return err; 731e846c7aSMarc Kleine-Budde 741e846c7aSMarc Kleine-Budde if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) { 751e846c7aSMarc Kleine-Budde netdev_err(priv->ndev, 761e846c7aSMarc Kleine-Budde "Transmit Event FIFO buffer overflow.\n"); 771e846c7aSMarc Kleine-Budde return -ENOBUFS; 781e846c7aSMarc Kleine-Budde } 791e846c7aSMarc Kleine-Budde 801e846c7aSMarc Kleine-Budde netdev_info(priv->ndev, 811e846c7aSMarc Kleine-Budde "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x).\n", 821e846c7aSMarc Kleine-Budde tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ? 831e846c7aSMarc Kleine-Budde "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ? 841e846c7aSMarc Kleine-Budde "not empty" : "empty", 851e846c7aSMarc Kleine-Budde seq, priv->tef->tail, priv->tef->head, tx_ring->head); 861e846c7aSMarc Kleine-Budde 871e846c7aSMarc Kleine-Budde /* The Sequence Number in the TEF doesn't match our tef_tail. */ 881e846c7aSMarc Kleine-Budde return -EAGAIN; 891e846c7aSMarc Kleine-Budde } 901e846c7aSMarc Kleine-Budde 911e846c7aSMarc Kleine-Budde static int 921e846c7aSMarc Kleine-Budde mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, 931e846c7aSMarc Kleine-Budde const struct mcp251xfd_hw_tef_obj *hw_tef_obj, 941e846c7aSMarc Kleine-Budde unsigned int *frame_len_ptr) 951e846c7aSMarc Kleine-Budde { 961e846c7aSMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 971e846c7aSMarc Kleine-Budde struct sk_buff *skb; 981e846c7aSMarc Kleine-Budde u32 seq, seq_masked, tef_tail_masked, tef_tail; 991e846c7aSMarc Kleine-Budde 1001e846c7aSMarc Kleine-Budde seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, 1011e846c7aSMarc Kleine-Budde hw_tef_obj->flags); 1021e846c7aSMarc Kleine-Budde 1031e846c7aSMarc Kleine-Budde /* Use the MCP2517FD mask on the MCP2518FD, too. We only 1041e846c7aSMarc Kleine-Budde * compare 7 bits, this should be enough to detect 1051e846c7aSMarc Kleine-Budde * net-yet-completed, i.e. old TEF objects. 1061e846c7aSMarc Kleine-Budde */ 1071e846c7aSMarc Kleine-Budde seq_masked = seq & 1081e846c7aSMarc Kleine-Budde field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 1091e846c7aSMarc Kleine-Budde tef_tail_masked = priv->tef->tail & 1101e846c7aSMarc Kleine-Budde field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 1111e846c7aSMarc Kleine-Budde if (seq_masked != tef_tail_masked) 1121e846c7aSMarc Kleine-Budde return mcp251xfd_handle_tefif_recover(priv, seq); 1131e846c7aSMarc Kleine-Budde 1141e846c7aSMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 1151e846c7aSMarc Kleine-Budde skb = priv->can.echo_skb[tef_tail]; 1161e846c7aSMarc Kleine-Budde if (skb) 117e793c724SMarc Kleine-Budde mcp251xfd_skb_set_timestamp_raw(priv, skb, hw_tef_obj->ts); 1181e846c7aSMarc Kleine-Budde stats->tx_bytes += 1192e3df4a3SMarc Kleine-Budde can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, 1201e846c7aSMarc Kleine-Budde tef_tail, hw_tef_obj->ts, 1211e846c7aSMarc Kleine-Budde frame_len_ptr); 1221e846c7aSMarc Kleine-Budde stats->tx_packets++; 1231e846c7aSMarc Kleine-Budde priv->tef->tail++; 1241e846c7aSMarc Kleine-Budde 1251e846c7aSMarc Kleine-Budde return 0; 1261e846c7aSMarc Kleine-Budde } 1271e846c7aSMarc Kleine-Budde 128*b8e0ddd3SMarc Kleine-Budde static int 129*b8e0ddd3SMarc Kleine-Budde mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p) 1301e846c7aSMarc Kleine-Budde { 1311e846c7aSMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 132*b8e0ddd3SMarc Kleine-Budde const u8 shift = tx_ring->obj_num_shift_to_u8; 133*b8e0ddd3SMarc Kleine-Budde u8 chip_tx_tail, tail, len; 134*b8e0ddd3SMarc Kleine-Budde u32 fifo_sta; 1351e846c7aSMarc Kleine-Budde int err; 1361e846c7aSMarc Kleine-Budde 137*b8e0ddd3SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(priv->tx->fifo_nr), 138*b8e0ddd3SMarc Kleine-Budde &fifo_sta); 1391e846c7aSMarc Kleine-Budde if (err) 1401e846c7aSMarc Kleine-Budde return err; 1411e846c7aSMarc Kleine-Budde 142*b8e0ddd3SMarc Kleine-Budde if (mcp251xfd_tx_fifo_sta_full(fifo_sta)) { 143*b8e0ddd3SMarc Kleine-Budde *len_p = tx_ring->obj_num; 144*b8e0ddd3SMarc Kleine-Budde return 0; 145*b8e0ddd3SMarc Kleine-Budde } 146*b8e0ddd3SMarc Kleine-Budde 147*b8e0ddd3SMarc Kleine-Budde chip_tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta); 148*b8e0ddd3SMarc Kleine-Budde 149*b8e0ddd3SMarc Kleine-Budde err = mcp251xfd_check_tef_tail(priv); 150*b8e0ddd3SMarc Kleine-Budde if (err) 151*b8e0ddd3SMarc Kleine-Budde return err; 152*b8e0ddd3SMarc Kleine-Budde tail = mcp251xfd_get_tef_tail(priv); 153*b8e0ddd3SMarc Kleine-Budde 154*b8e0ddd3SMarc Kleine-Budde /* First shift to full u8. The subtraction works on signed 155*b8e0ddd3SMarc Kleine-Budde * values, that keeps the difference steady around the u8 156*b8e0ddd3SMarc Kleine-Budde * overflow. The right shift acts on len, which is an u8. 1571e846c7aSMarc Kleine-Budde */ 158*b8e0ddd3SMarc Kleine-Budde BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(chip_tx_tail)); 159*b8e0ddd3SMarc Kleine-Budde BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(tail)); 160*b8e0ddd3SMarc Kleine-Budde BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len)); 1611e846c7aSMarc Kleine-Budde 162*b8e0ddd3SMarc Kleine-Budde len = (chip_tx_tail << shift) - (tail << shift); 163*b8e0ddd3SMarc Kleine-Budde *len_p = len >> shift; 1641e846c7aSMarc Kleine-Budde 165*b8e0ddd3SMarc Kleine-Budde return 0; 1661e846c7aSMarc Kleine-Budde } 1671e846c7aSMarc Kleine-Budde 1681e846c7aSMarc Kleine-Budde static inline int 1691e846c7aSMarc Kleine-Budde mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv, 1701e846c7aSMarc Kleine-Budde struct mcp251xfd_hw_tef_obj *hw_tef_obj, 1711e846c7aSMarc Kleine-Budde const u8 offset, const u8 len) 1721e846c7aSMarc Kleine-Budde { 1731e846c7aSMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 1741e846c7aSMarc Kleine-Budde const int val_bytes = regmap_get_val_bytes(priv->map_rx); 1751e846c7aSMarc Kleine-Budde 1761e846c7aSMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 1771e846c7aSMarc Kleine-Budde (offset > tx_ring->obj_num || 1781e846c7aSMarc Kleine-Budde len > tx_ring->obj_num || 1791e846c7aSMarc Kleine-Budde offset + len > tx_ring->obj_num)) { 1801e846c7aSMarc Kleine-Budde netdev_err(priv->ndev, 1811e846c7aSMarc Kleine-Budde "Trying to read too many TEF objects (max=%d, offset=%d, len=%d).\n", 1821e846c7aSMarc Kleine-Budde tx_ring->obj_num, offset, len); 1831e846c7aSMarc Kleine-Budde return -ERANGE; 1841e846c7aSMarc Kleine-Budde } 1851e846c7aSMarc Kleine-Budde 1861e846c7aSMarc Kleine-Budde return regmap_bulk_read(priv->map_rx, 1871e846c7aSMarc Kleine-Budde mcp251xfd_get_tef_obj_addr(offset), 1881e846c7aSMarc Kleine-Budde hw_tef_obj, 1891e846c7aSMarc Kleine-Budde sizeof(*hw_tef_obj) / val_bytes * len); 1901e846c7aSMarc Kleine-Budde } 1911e846c7aSMarc Kleine-Budde 1921e846c7aSMarc Kleine-Budde static inline void mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv *priv) 1931e846c7aSMarc Kleine-Budde { 1941e846c7aSMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 1951e846c7aSMarc Kleine-Budde 1961e846c7aSMarc Kleine-Budde ecc->ecc_stat = 0; 1971e846c7aSMarc Kleine-Budde } 1981e846c7aSMarc Kleine-Budde 1991e846c7aSMarc Kleine-Budde int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) 2001e846c7aSMarc Kleine-Budde { 2011e846c7aSMarc Kleine-Budde struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX]; 2021e846c7aSMarc Kleine-Budde unsigned int total_frame_len = 0; 2031e846c7aSMarc Kleine-Budde u8 tef_tail, len, l; 2041e846c7aSMarc Kleine-Budde int err, i; 2051e846c7aSMarc Kleine-Budde 206*b8e0ddd3SMarc Kleine-Budde err = mcp251xfd_get_tef_len(priv, &len); 2071e846c7aSMarc Kleine-Budde if (err) 2081e846c7aSMarc Kleine-Budde return err; 2091e846c7aSMarc Kleine-Budde 2101e846c7aSMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 211*b8e0ddd3SMarc Kleine-Budde l = mcp251xfd_get_tef_linear_len(priv, len); 2121e846c7aSMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l); 2131e846c7aSMarc Kleine-Budde if (err) 2141e846c7aSMarc Kleine-Budde return err; 2151e846c7aSMarc Kleine-Budde 2161e846c7aSMarc Kleine-Budde if (l < len) { 2171e846c7aSMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l); 2181e846c7aSMarc Kleine-Budde if (err) 2191e846c7aSMarc Kleine-Budde return err; 2201e846c7aSMarc Kleine-Budde } 2211e846c7aSMarc Kleine-Budde 2221e846c7aSMarc Kleine-Budde for (i = 0; i < len; i++) { 2231e846c7aSMarc Kleine-Budde unsigned int frame_len = 0; 2241e846c7aSMarc Kleine-Budde 2251e846c7aSMarc Kleine-Budde err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len); 2261e846c7aSMarc Kleine-Budde /* -EAGAIN means the Sequence Number in the TEF 2271e846c7aSMarc Kleine-Budde * doesn't match our tef_tail. This can happen if we 2281e846c7aSMarc Kleine-Budde * read the TEF objects too early. Leave loop let the 2291e846c7aSMarc Kleine-Budde * interrupt handler call us again. 2301e846c7aSMarc Kleine-Budde */ 2311e846c7aSMarc Kleine-Budde if (err == -EAGAIN) 2321e846c7aSMarc Kleine-Budde goto out_netif_wake_queue; 2331e846c7aSMarc Kleine-Budde if (err) 2341e846c7aSMarc Kleine-Budde return err; 2351e846c7aSMarc Kleine-Budde 2361e846c7aSMarc Kleine-Budde total_frame_len += frame_len; 2371e846c7aSMarc Kleine-Budde } 2381e846c7aSMarc Kleine-Budde 2391e846c7aSMarc Kleine-Budde out_netif_wake_queue: 2401e846c7aSMarc Kleine-Budde len = i; /* number of handled goods TEFs */ 2411e846c7aSMarc Kleine-Budde if (len) { 2421e846c7aSMarc Kleine-Budde struct mcp251xfd_tef_ring *ring = priv->tef; 2431e846c7aSMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 2441e846c7aSMarc Kleine-Budde int offset; 2451e846c7aSMarc Kleine-Budde 246*b8e0ddd3SMarc Kleine-Budde ring->head += len; 247*b8e0ddd3SMarc Kleine-Budde 2481e846c7aSMarc Kleine-Budde /* Increment the TEF FIFO tail pointer 'len' times in 2491e846c7aSMarc Kleine-Budde * a single SPI message. 2501e846c7aSMarc Kleine-Budde * 2511e846c7aSMarc Kleine-Budde * Note: 2521e846c7aSMarc Kleine-Budde * Calculate offset, so that the SPI transfer ends on 2531e846c7aSMarc Kleine-Budde * the last message of the uinc_xfer array, which has 2541e846c7aSMarc Kleine-Budde * "cs_change == 0", to properly deactivate the chip 2551e846c7aSMarc Kleine-Budde * select. 2561e846c7aSMarc Kleine-Budde */ 2571e846c7aSMarc Kleine-Budde offset = ARRAY_SIZE(ring->uinc_xfer) - len; 2581e846c7aSMarc Kleine-Budde err = spi_sync_transfer(priv->spi, 2591e846c7aSMarc Kleine-Budde ring->uinc_xfer + offset, len); 2601e846c7aSMarc Kleine-Budde if (err) 2611e846c7aSMarc Kleine-Budde return err; 2621e846c7aSMarc Kleine-Budde 2631e846c7aSMarc Kleine-Budde tx_ring->tail += len; 2641e846c7aSMarc Kleine-Budde netdev_completed_queue(priv->ndev, len, total_frame_len); 2651e846c7aSMarc Kleine-Budde 2661e846c7aSMarc Kleine-Budde err = mcp251xfd_check_tef_tail(priv); 2671e846c7aSMarc Kleine-Budde if (err) 2681e846c7aSMarc Kleine-Budde return err; 2691e846c7aSMarc Kleine-Budde } 2701e846c7aSMarc Kleine-Budde 2711e846c7aSMarc Kleine-Budde mcp251xfd_ecc_tefif_successful(priv); 2721e846c7aSMarc Kleine-Budde 2731e846c7aSMarc Kleine-Budde if (mcp251xfd_get_tx_free(priv->tx)) { 2741e846c7aSMarc Kleine-Budde /* Make sure that anybody stopping the queue after 2751e846c7aSMarc Kleine-Budde * this sees the new tx_ring->tail. 2761e846c7aSMarc Kleine-Budde */ 2771e846c7aSMarc Kleine-Budde smp_mb(); 2781e846c7aSMarc Kleine-Budde netif_wake_queue(priv->ndev); 2791e846c7aSMarc Kleine-Budde } 2801e846c7aSMarc Kleine-Budde 281169d00a2SMarc Kleine-Budde if (priv->tx_coalesce_usecs_irq) 282169d00a2SMarc Kleine-Budde hrtimer_start(&priv->tx_irq_timer, 283169d00a2SMarc Kleine-Budde ns_to_ktime(priv->tx_coalesce_usecs_irq * 284169d00a2SMarc Kleine-Budde NSEC_PER_USEC), 285169d00a2SMarc Kleine-Budde HRTIMER_MODE_REL); 286169d00a2SMarc Kleine-Budde 2871e846c7aSMarc Kleine-Budde return 0; 2881e846c7aSMarc Kleine-Budde } 289