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 // 5b8e0ddd3SMarc 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 19b8e0ddd3SMarc Kleine-Budde static inline bool mcp251xfd_tx_fifo_sta_full(u32 fifo_sta) 20b8e0ddd3SMarc Kleine-Budde { 21b8e0ddd3SMarc Kleine-Budde return !(fifo_sta & MCP251XFD_REG_FIFOSTA_TFNRFNIF); 22b8e0ddd3SMarc Kleine-Budde } 23b8e0ddd3SMarc 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_one(struct mcp251xfd_priv *priv, 651e846c7aSMarc Kleine-Budde const struct mcp251xfd_hw_tef_obj *hw_tef_obj, 661e846c7aSMarc Kleine-Budde unsigned int *frame_len_ptr) 671e846c7aSMarc Kleine-Budde { 681e846c7aSMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 69*3a0a88fcSMarc Kleine-Budde u32 seq, tef_tail_masked, tef_tail; 701e846c7aSMarc Kleine-Budde struct sk_buff *skb; 711e846c7aSMarc Kleine-Budde 721e846c7aSMarc Kleine-Budde /* Use the MCP2517FD mask on the MCP2518FD, too. We only 73*3a0a88fcSMarc Kleine-Budde * compare 7 bits, this is enough to detect old TEF objects. 741e846c7aSMarc Kleine-Budde */ 75*3a0a88fcSMarc Kleine-Budde seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK, 76*3a0a88fcSMarc Kleine-Budde hw_tef_obj->flags); 771e846c7aSMarc Kleine-Budde tef_tail_masked = priv->tef->tail & 781e846c7aSMarc Kleine-Budde field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 79*3a0a88fcSMarc Kleine-Budde 80*3a0a88fcSMarc Kleine-Budde /* According to mcp2518fd erratum DS80000789E 6. the FIFOCI 81*3a0a88fcSMarc Kleine-Budde * bits of a FIFOSTA register, here the TX FIFO tail index 82*3a0a88fcSMarc Kleine-Budde * might be corrupted and we might process past the TEF FIFO's 83*3a0a88fcSMarc Kleine-Budde * head into old CAN frames. 84*3a0a88fcSMarc Kleine-Budde * 85*3a0a88fcSMarc Kleine-Budde * Compare the sequence number of the currently processed CAN 86*3a0a88fcSMarc Kleine-Budde * frame with the expected sequence number. Abort with 87*3a0a88fcSMarc Kleine-Budde * -EBADMSG if an old CAN frame is detected. 88*3a0a88fcSMarc Kleine-Budde */ 89*3a0a88fcSMarc Kleine-Budde if (seq != tef_tail_masked) { 90*3a0a88fcSMarc Kleine-Budde netdev_dbg(priv->ndev, "%s: chip=0x%02x ring=0x%02x\n", __func__, 91*3a0a88fcSMarc Kleine-Budde seq, tef_tail_masked); 92*3a0a88fcSMarc Kleine-Budde stats->tx_fifo_errors++; 93*3a0a88fcSMarc Kleine-Budde 94*3a0a88fcSMarc Kleine-Budde return -EBADMSG; 95*3a0a88fcSMarc Kleine-Budde } 961e846c7aSMarc Kleine-Budde 971e846c7aSMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 981e846c7aSMarc Kleine-Budde skb = priv->can.echo_skb[tef_tail]; 991e846c7aSMarc Kleine-Budde if (skb) 100e793c724SMarc Kleine-Budde mcp251xfd_skb_set_timestamp_raw(priv, skb, hw_tef_obj->ts); 1011e846c7aSMarc Kleine-Budde stats->tx_bytes += 1022e3df4a3SMarc Kleine-Budde can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload, 1031e846c7aSMarc Kleine-Budde tef_tail, hw_tef_obj->ts, 1041e846c7aSMarc Kleine-Budde frame_len_ptr); 1051e846c7aSMarc Kleine-Budde stats->tx_packets++; 1061e846c7aSMarc Kleine-Budde priv->tef->tail++; 1071e846c7aSMarc Kleine-Budde 1081e846c7aSMarc Kleine-Budde return 0; 1091e846c7aSMarc Kleine-Budde } 1101e846c7aSMarc Kleine-Budde 111b8e0ddd3SMarc Kleine-Budde static int 112b8e0ddd3SMarc Kleine-Budde mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p) 1131e846c7aSMarc Kleine-Budde { 1141e846c7aSMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 115b8e0ddd3SMarc Kleine-Budde const u8 shift = tx_ring->obj_num_shift_to_u8; 116b8e0ddd3SMarc Kleine-Budde u8 chip_tx_tail, tail, len; 117b8e0ddd3SMarc Kleine-Budde u32 fifo_sta; 1181e846c7aSMarc Kleine-Budde int err; 1191e846c7aSMarc Kleine-Budde 120b8e0ddd3SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(priv->tx->fifo_nr), 121b8e0ddd3SMarc Kleine-Budde &fifo_sta); 1221e846c7aSMarc Kleine-Budde if (err) 1231e846c7aSMarc Kleine-Budde return err; 1241e846c7aSMarc Kleine-Budde 125b8e0ddd3SMarc Kleine-Budde if (mcp251xfd_tx_fifo_sta_full(fifo_sta)) { 126b8e0ddd3SMarc Kleine-Budde *len_p = tx_ring->obj_num; 127b8e0ddd3SMarc Kleine-Budde return 0; 128b8e0ddd3SMarc Kleine-Budde } 129b8e0ddd3SMarc Kleine-Budde 130b8e0ddd3SMarc Kleine-Budde chip_tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta); 131b8e0ddd3SMarc Kleine-Budde 132b8e0ddd3SMarc Kleine-Budde err = mcp251xfd_check_tef_tail(priv); 133b8e0ddd3SMarc Kleine-Budde if (err) 134b8e0ddd3SMarc Kleine-Budde return err; 135b8e0ddd3SMarc Kleine-Budde tail = mcp251xfd_get_tef_tail(priv); 136b8e0ddd3SMarc Kleine-Budde 137b8e0ddd3SMarc Kleine-Budde /* First shift to full u8. The subtraction works on signed 138b8e0ddd3SMarc Kleine-Budde * values, that keeps the difference steady around the u8 139b8e0ddd3SMarc Kleine-Budde * overflow. The right shift acts on len, which is an u8. 1401e846c7aSMarc Kleine-Budde */ 141b8e0ddd3SMarc Kleine-Budde BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(chip_tx_tail)); 142b8e0ddd3SMarc Kleine-Budde BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(tail)); 143b8e0ddd3SMarc Kleine-Budde BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len)); 1441e846c7aSMarc Kleine-Budde 145b8e0ddd3SMarc Kleine-Budde len = (chip_tx_tail << shift) - (tail << shift); 146b8e0ddd3SMarc Kleine-Budde *len_p = len >> shift; 1471e846c7aSMarc Kleine-Budde 148b8e0ddd3SMarc Kleine-Budde return 0; 1491e846c7aSMarc Kleine-Budde } 1501e846c7aSMarc Kleine-Budde 1511e846c7aSMarc Kleine-Budde static inline int 1521e846c7aSMarc Kleine-Budde mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv, 1531e846c7aSMarc Kleine-Budde struct mcp251xfd_hw_tef_obj *hw_tef_obj, 1541e846c7aSMarc Kleine-Budde const u8 offset, const u8 len) 1551e846c7aSMarc Kleine-Budde { 1561e846c7aSMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 1571e846c7aSMarc Kleine-Budde const int val_bytes = regmap_get_val_bytes(priv->map_rx); 1581e846c7aSMarc Kleine-Budde 1591e846c7aSMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 1601e846c7aSMarc Kleine-Budde (offset > tx_ring->obj_num || 1611e846c7aSMarc Kleine-Budde len > tx_ring->obj_num || 1621e846c7aSMarc Kleine-Budde offset + len > tx_ring->obj_num)) { 1631e846c7aSMarc Kleine-Budde netdev_err(priv->ndev, 1641e846c7aSMarc Kleine-Budde "Trying to read too many TEF objects (max=%d, offset=%d, len=%d).\n", 1651e846c7aSMarc Kleine-Budde tx_ring->obj_num, offset, len); 1661e846c7aSMarc Kleine-Budde return -ERANGE; 1671e846c7aSMarc Kleine-Budde } 1681e846c7aSMarc Kleine-Budde 1691e846c7aSMarc Kleine-Budde return regmap_bulk_read(priv->map_rx, 1701e846c7aSMarc Kleine-Budde mcp251xfd_get_tef_obj_addr(offset), 1711e846c7aSMarc Kleine-Budde hw_tef_obj, 1721e846c7aSMarc Kleine-Budde sizeof(*hw_tef_obj) / val_bytes * len); 1731e846c7aSMarc Kleine-Budde } 1741e846c7aSMarc Kleine-Budde 1751e846c7aSMarc Kleine-Budde static inline void mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv *priv) 1761e846c7aSMarc Kleine-Budde { 1771e846c7aSMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 1781e846c7aSMarc Kleine-Budde 1791e846c7aSMarc Kleine-Budde ecc->ecc_stat = 0; 1801e846c7aSMarc Kleine-Budde } 1811e846c7aSMarc Kleine-Budde 1821e846c7aSMarc Kleine-Budde int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) 1831e846c7aSMarc Kleine-Budde { 1841e846c7aSMarc Kleine-Budde struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX]; 1851e846c7aSMarc Kleine-Budde unsigned int total_frame_len = 0; 1861e846c7aSMarc Kleine-Budde u8 tef_tail, len, l; 1871e846c7aSMarc Kleine-Budde int err, i; 1881e846c7aSMarc Kleine-Budde 189b8e0ddd3SMarc Kleine-Budde err = mcp251xfd_get_tef_len(priv, &len); 1901e846c7aSMarc Kleine-Budde if (err) 1911e846c7aSMarc Kleine-Budde return err; 1921e846c7aSMarc Kleine-Budde 1931e846c7aSMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 194b8e0ddd3SMarc Kleine-Budde l = mcp251xfd_get_tef_linear_len(priv, len); 1951e846c7aSMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l); 1961e846c7aSMarc Kleine-Budde if (err) 1971e846c7aSMarc Kleine-Budde return err; 1981e846c7aSMarc Kleine-Budde 1991e846c7aSMarc Kleine-Budde if (l < len) { 2001e846c7aSMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l); 2011e846c7aSMarc Kleine-Budde if (err) 2021e846c7aSMarc Kleine-Budde return err; 2031e846c7aSMarc Kleine-Budde } 2041e846c7aSMarc Kleine-Budde 2051e846c7aSMarc Kleine-Budde for (i = 0; i < len; i++) { 2061e846c7aSMarc Kleine-Budde unsigned int frame_len = 0; 2071e846c7aSMarc Kleine-Budde 2081e846c7aSMarc Kleine-Budde err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len); 209*3a0a88fcSMarc Kleine-Budde /* -EBADMSG means we're affected by mcp2518fd erratum 210*3a0a88fcSMarc Kleine-Budde * DS80000789E 6., i.e. the Sequence Number in the TEF 211*3a0a88fcSMarc Kleine-Budde * doesn't match our tef_tail. Don't process any 212*3a0a88fcSMarc Kleine-Budde * further and mark processed frames as good. 2131e846c7aSMarc Kleine-Budde */ 214*3a0a88fcSMarc Kleine-Budde if (err == -EBADMSG) 2151e846c7aSMarc Kleine-Budde goto out_netif_wake_queue; 2161e846c7aSMarc Kleine-Budde if (err) 2171e846c7aSMarc Kleine-Budde return err; 2181e846c7aSMarc Kleine-Budde 2191e846c7aSMarc Kleine-Budde total_frame_len += frame_len; 2201e846c7aSMarc Kleine-Budde } 2211e846c7aSMarc Kleine-Budde 2221e846c7aSMarc Kleine-Budde out_netif_wake_queue: 2231e846c7aSMarc Kleine-Budde len = i; /* number of handled goods TEFs */ 2241e846c7aSMarc Kleine-Budde if (len) { 2251e846c7aSMarc Kleine-Budde struct mcp251xfd_tef_ring *ring = priv->tef; 2261e846c7aSMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 2271e846c7aSMarc Kleine-Budde int offset; 2281e846c7aSMarc Kleine-Budde 229b8e0ddd3SMarc Kleine-Budde ring->head += len; 230b8e0ddd3SMarc Kleine-Budde 2311e846c7aSMarc Kleine-Budde /* Increment the TEF FIFO tail pointer 'len' times in 2321e846c7aSMarc Kleine-Budde * a single SPI message. 2331e846c7aSMarc Kleine-Budde * 2341e846c7aSMarc Kleine-Budde * Note: 2351e846c7aSMarc Kleine-Budde * Calculate offset, so that the SPI transfer ends on 2361e846c7aSMarc Kleine-Budde * the last message of the uinc_xfer array, which has 2371e846c7aSMarc Kleine-Budde * "cs_change == 0", to properly deactivate the chip 2381e846c7aSMarc Kleine-Budde * select. 2391e846c7aSMarc Kleine-Budde */ 2401e846c7aSMarc Kleine-Budde offset = ARRAY_SIZE(ring->uinc_xfer) - len; 2411e846c7aSMarc Kleine-Budde err = spi_sync_transfer(priv->spi, 2421e846c7aSMarc Kleine-Budde ring->uinc_xfer + offset, len); 2431e846c7aSMarc Kleine-Budde if (err) 2441e846c7aSMarc Kleine-Budde return err; 2451e846c7aSMarc Kleine-Budde 2461e846c7aSMarc Kleine-Budde tx_ring->tail += len; 2471e846c7aSMarc Kleine-Budde netdev_completed_queue(priv->ndev, len, total_frame_len); 2481e846c7aSMarc Kleine-Budde 2491e846c7aSMarc Kleine-Budde err = mcp251xfd_check_tef_tail(priv); 2501e846c7aSMarc Kleine-Budde if (err) 2511e846c7aSMarc Kleine-Budde return err; 2521e846c7aSMarc Kleine-Budde } 2531e846c7aSMarc Kleine-Budde 2541e846c7aSMarc Kleine-Budde mcp251xfd_ecc_tefif_successful(priv); 2551e846c7aSMarc Kleine-Budde 2561e846c7aSMarc Kleine-Budde if (mcp251xfd_get_tx_free(priv->tx)) { 2571e846c7aSMarc Kleine-Budde /* Make sure that anybody stopping the queue after 2581e846c7aSMarc Kleine-Budde * this sees the new tx_ring->tail. 2591e846c7aSMarc Kleine-Budde */ 2601e846c7aSMarc Kleine-Budde smp_mb(); 2611e846c7aSMarc Kleine-Budde netif_wake_queue(priv->ndev); 2621e846c7aSMarc Kleine-Budde } 2631e846c7aSMarc Kleine-Budde 264169d00a2SMarc Kleine-Budde if (priv->tx_coalesce_usecs_irq) 265169d00a2SMarc Kleine-Budde hrtimer_start(&priv->tx_irq_timer, 266169d00a2SMarc Kleine-Budde ns_to_ktime(priv->tx_coalesce_usecs_irq * 267169d00a2SMarc Kleine-Budde NSEC_PER_USEC), 268169d00a2SMarc Kleine-Budde HRTIMER_MODE_REL); 269169d00a2SMarc Kleine-Budde 2701e846c7aSMarc Kleine-Budde return 0; 2711e846c7aSMarc Kleine-Budde } 272