11f0e21a0SMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0 21f0e21a0SMarc Kleine-Budde // 3eb79a267SMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver 41f0e21a0SMarc Kleine-Budde // 5eb94b74cSMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021 Pengutronix, 61f0e21a0SMarc Kleine-Budde // Marc Kleine-Budde <kernel@pengutronix.de> 71f0e21a0SMarc Kleine-Budde // 81f0e21a0SMarc Kleine-Budde // Based on: 91f0e21a0SMarc Kleine-Budde // 101f0e21a0SMarc Kleine-Budde // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface 111f0e21a0SMarc Kleine-Budde // 121f0e21a0SMarc Kleine-Budde // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org> 131f0e21a0SMarc Kleine-Budde // 141f0e21a0SMarc Kleine-Budde 151f0e21a0SMarc Kleine-Budde #include <linux/bitfield.h> 161f0e21a0SMarc Kleine-Budde #include <linux/clk.h> 171f0e21a0SMarc Kleine-Budde #include <linux/device.h> 181f0e21a0SMarc Kleine-Budde #include <linux/module.h> 191f0e21a0SMarc Kleine-Budde #include <linux/of.h> 201f0e21a0SMarc Kleine-Budde #include <linux/of_device.h> 211f0e21a0SMarc Kleine-Budde #include <linux/pm_runtime.h> 221f0e21a0SMarc Kleine-Budde 231f0e21a0SMarc Kleine-Budde #include <asm/unaligned.h> 241f0e21a0SMarc Kleine-Budde 251f0e21a0SMarc Kleine-Budde #include "mcp251xfd.h" 261f0e21a0SMarc Kleine-Budde 27f4f77366SMarc Kleine-Budde #define DEVICE_NAME "mcp251xfd" 281f0e21a0SMarc Kleine-Budde 29eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp2517fd = { 30eb79a267SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_MAB_NO_WARN | MCP251XFD_QUIRK_CRC_REG | 31eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_RX | MCP251XFD_QUIRK_CRC_TX | 32eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ECC, 33eb79a267SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP2517FD, 341f0e21a0SMarc Kleine-Budde }; 351f0e21a0SMarc Kleine-Budde 36eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp2518fd = { 37eb79a267SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_CRC_REG | MCP251XFD_QUIRK_CRC_RX | 38eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_TX | MCP251XFD_QUIRK_ECC, 39eb79a267SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP2518FD, 401f0e21a0SMarc Kleine-Budde }; 411f0e21a0SMarc Kleine-Budde 421f0e21a0SMarc Kleine-Budde /* Autodetect model, start with CRC enabled. */ 43eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp251xfd = { 44eb79a267SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_CRC_REG | MCP251XFD_QUIRK_CRC_RX | 45eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_TX | MCP251XFD_QUIRK_ECC, 46eb79a267SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP251XFD, 471f0e21a0SMarc Kleine-Budde }; 481f0e21a0SMarc Kleine-Budde 49eb79a267SMarc Kleine-Budde static const struct can_bittiming_const mcp251xfd_bittiming_const = { 501f0e21a0SMarc Kleine-Budde .name = DEVICE_NAME, 511f0e21a0SMarc Kleine-Budde .tseg1_min = 2, 521f0e21a0SMarc Kleine-Budde .tseg1_max = 256, 531f0e21a0SMarc Kleine-Budde .tseg2_min = 1, 541f0e21a0SMarc Kleine-Budde .tseg2_max = 128, 551f0e21a0SMarc Kleine-Budde .sjw_max = 128, 561f0e21a0SMarc Kleine-Budde .brp_min = 1, 571f0e21a0SMarc Kleine-Budde .brp_max = 256, 581f0e21a0SMarc Kleine-Budde .brp_inc = 1, 591f0e21a0SMarc Kleine-Budde }; 601f0e21a0SMarc Kleine-Budde 61eb79a267SMarc Kleine-Budde static const struct can_bittiming_const mcp251xfd_data_bittiming_const = { 621f0e21a0SMarc Kleine-Budde .name = DEVICE_NAME, 631f0e21a0SMarc Kleine-Budde .tseg1_min = 1, 641f0e21a0SMarc Kleine-Budde .tseg1_max = 32, 651f0e21a0SMarc Kleine-Budde .tseg2_min = 1, 661f0e21a0SMarc Kleine-Budde .tseg2_max = 16, 671f0e21a0SMarc Kleine-Budde .sjw_max = 16, 681f0e21a0SMarc Kleine-Budde .brp_min = 1, 691f0e21a0SMarc Kleine-Budde .brp_max = 256, 701f0e21a0SMarc Kleine-Budde .brp_inc = 1, 711f0e21a0SMarc Kleine-Budde }; 721f0e21a0SMarc Kleine-Budde 73eb79a267SMarc Kleine-Budde static const char *__mcp251xfd_get_model_str(enum mcp251xfd_model model) 741f0e21a0SMarc Kleine-Budde { 751f0e21a0SMarc Kleine-Budde switch (model) { 76eb79a267SMarc Kleine-Budde case MCP251XFD_MODEL_MCP2517FD: 7778db1aa8STom Rix return "MCP2517FD"; 78eb79a267SMarc Kleine-Budde case MCP251XFD_MODEL_MCP2518FD: 7978db1aa8STom Rix return "MCP2518FD"; 80eb79a267SMarc Kleine-Budde case MCP251XFD_MODEL_MCP251XFD: 8178db1aa8STom Rix return "MCP251xFD"; 821f0e21a0SMarc Kleine-Budde } 831f0e21a0SMarc Kleine-Budde 841f0e21a0SMarc Kleine-Budde return "<unknown>"; 851f0e21a0SMarc Kleine-Budde } 861f0e21a0SMarc Kleine-Budde 871f0e21a0SMarc Kleine-Budde static inline const char * 88eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(const struct mcp251xfd_priv *priv) 891f0e21a0SMarc Kleine-Budde { 90eb79a267SMarc Kleine-Budde return __mcp251xfd_get_model_str(priv->devtype_data.model); 911f0e21a0SMarc Kleine-Budde } 921f0e21a0SMarc Kleine-Budde 93eb79a267SMarc Kleine-Budde static const char *mcp251xfd_get_mode_str(const u8 mode) 941f0e21a0SMarc Kleine-Budde { 951f0e21a0SMarc Kleine-Budde switch (mode) { 96eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_MIXED: 9778db1aa8STom Rix return "Mixed (CAN FD/CAN 2.0)"; 98eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_SLEEP: 9978db1aa8STom Rix return "Sleep"; 100eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_INT_LOOPBACK: 10178db1aa8STom Rix return "Internal Loopback"; 102eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_LISTENONLY: 10378db1aa8STom Rix return "Listen Only"; 104eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_CONFIG: 10578db1aa8STom Rix return "Configuration"; 106eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_EXT_LOOPBACK: 10778db1aa8STom Rix return "External Loopback"; 108eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_CAN2_0: 10978db1aa8STom Rix return "CAN 2.0"; 110eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_RESTRICTED: 11178db1aa8STom Rix return "Restricted Operation"; 1121f0e21a0SMarc Kleine-Budde } 1131f0e21a0SMarc Kleine-Budde 1141f0e21a0SMarc Kleine-Budde return "<unknown>"; 1151f0e21a0SMarc Kleine-Budde } 1161f0e21a0SMarc Kleine-Budde 117eb79a267SMarc Kleine-Budde static inline int mcp251xfd_vdd_enable(const struct mcp251xfd_priv *priv) 1181f0e21a0SMarc Kleine-Budde { 1191f0e21a0SMarc Kleine-Budde if (!priv->reg_vdd) 1201f0e21a0SMarc Kleine-Budde return 0; 1211f0e21a0SMarc Kleine-Budde 1221f0e21a0SMarc Kleine-Budde return regulator_enable(priv->reg_vdd); 1231f0e21a0SMarc Kleine-Budde } 1241f0e21a0SMarc Kleine-Budde 125eb79a267SMarc Kleine-Budde static inline int mcp251xfd_vdd_disable(const struct mcp251xfd_priv *priv) 1261f0e21a0SMarc Kleine-Budde { 1271f0e21a0SMarc Kleine-Budde if (!priv->reg_vdd) 1281f0e21a0SMarc Kleine-Budde return 0; 1291f0e21a0SMarc Kleine-Budde 1301f0e21a0SMarc Kleine-Budde return regulator_disable(priv->reg_vdd); 1311f0e21a0SMarc Kleine-Budde } 1321f0e21a0SMarc Kleine-Budde 1331f0e21a0SMarc Kleine-Budde static inline int 134eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_enable(const struct mcp251xfd_priv *priv) 1351f0e21a0SMarc Kleine-Budde { 1361f0e21a0SMarc Kleine-Budde if (!priv->reg_xceiver) 1371f0e21a0SMarc Kleine-Budde return 0; 1381f0e21a0SMarc Kleine-Budde 1391f0e21a0SMarc Kleine-Budde return regulator_enable(priv->reg_xceiver); 1401f0e21a0SMarc Kleine-Budde } 1411f0e21a0SMarc Kleine-Budde 1421f0e21a0SMarc Kleine-Budde static inline int 143eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(const struct mcp251xfd_priv *priv) 1441f0e21a0SMarc Kleine-Budde { 1451f0e21a0SMarc Kleine-Budde if (!priv->reg_xceiver) 1461f0e21a0SMarc Kleine-Budde return 0; 1471f0e21a0SMarc Kleine-Budde 1481f0e21a0SMarc Kleine-Budde return regulator_disable(priv->reg_xceiver); 1491f0e21a0SMarc Kleine-Budde } 1501f0e21a0SMarc Kleine-Budde 151eb79a267SMarc Kleine-Budde static int mcp251xfd_clks_and_vdd_enable(const struct mcp251xfd_priv *priv) 1521f0e21a0SMarc Kleine-Budde { 1531f0e21a0SMarc Kleine-Budde int err; 1541f0e21a0SMarc Kleine-Budde 1551f0e21a0SMarc Kleine-Budde err = clk_prepare_enable(priv->clk); 1561f0e21a0SMarc Kleine-Budde if (err) 1571f0e21a0SMarc Kleine-Budde return err; 1581f0e21a0SMarc Kleine-Budde 159eb79a267SMarc Kleine-Budde err = mcp251xfd_vdd_enable(priv); 1601f0e21a0SMarc Kleine-Budde if (err) 1611f0e21a0SMarc Kleine-Budde clk_disable_unprepare(priv->clk); 1621f0e21a0SMarc Kleine-Budde 1631f0e21a0SMarc Kleine-Budde /* Wait for oscillator stabilisation time after power up */ 164eb79a267SMarc Kleine-Budde usleep_range(MCP251XFD_OSC_STAB_SLEEP_US, 165eb79a267SMarc Kleine-Budde 2 * MCP251XFD_OSC_STAB_SLEEP_US); 1661f0e21a0SMarc Kleine-Budde 1671f0e21a0SMarc Kleine-Budde return err; 1681f0e21a0SMarc Kleine-Budde } 1691f0e21a0SMarc Kleine-Budde 170eb79a267SMarc Kleine-Budde static int mcp251xfd_clks_and_vdd_disable(const struct mcp251xfd_priv *priv) 1711f0e21a0SMarc Kleine-Budde { 1721f0e21a0SMarc Kleine-Budde int err; 1731f0e21a0SMarc Kleine-Budde 174eb79a267SMarc Kleine-Budde err = mcp251xfd_vdd_disable(priv); 1751f0e21a0SMarc Kleine-Budde if (err) 1761f0e21a0SMarc Kleine-Budde return err; 1771f0e21a0SMarc Kleine-Budde 1781f0e21a0SMarc Kleine-Budde clk_disable_unprepare(priv->clk); 1791f0e21a0SMarc Kleine-Budde 1801f0e21a0SMarc Kleine-Budde return 0; 1811f0e21a0SMarc Kleine-Budde } 1821f0e21a0SMarc Kleine-Budde 1831f0e21a0SMarc Kleine-Budde static inline u8 184eb79a267SMarc Kleine-Budde mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv, 185eb79a267SMarc Kleine-Budde union mcp251xfd_write_reg_buf *write_reg_buf, 1861f0e21a0SMarc Kleine-Budde const u16 reg, const u32 mask, const u32 val) 1871f0e21a0SMarc Kleine-Budde { 1881f0e21a0SMarc Kleine-Budde u8 first_byte, last_byte, len; 1891f0e21a0SMarc Kleine-Budde u8 *data; 1901f0e21a0SMarc Kleine-Budde __le32 val_le32; 1911f0e21a0SMarc Kleine-Budde 192eb79a267SMarc Kleine-Budde first_byte = mcp251xfd_first_byte_set(mask); 193eb79a267SMarc Kleine-Budde last_byte = mcp251xfd_last_byte_set(mask); 1941f0e21a0SMarc Kleine-Budde len = last_byte - first_byte + 1; 1951f0e21a0SMarc Kleine-Budde 196eb79a267SMarc Kleine-Budde data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte); 1971f0e21a0SMarc Kleine-Budde val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte); 1981f0e21a0SMarc Kleine-Budde memcpy(data, &val_le32, len); 1991f0e21a0SMarc Kleine-Budde 200eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) { 2011f0e21a0SMarc Kleine-Budde u16 crc; 2021f0e21a0SMarc Kleine-Budde 203eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd, 2041f0e21a0SMarc Kleine-Budde len); 2051f0e21a0SMarc Kleine-Budde /* CRC */ 2061f0e21a0SMarc Kleine-Budde len += sizeof(write_reg_buf->crc.cmd); 207eb79a267SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(&write_reg_buf->crc, len); 2081f0e21a0SMarc Kleine-Budde put_unaligned_be16(crc, (void *)write_reg_buf + len); 2091f0e21a0SMarc Kleine-Budde 2101f0e21a0SMarc Kleine-Budde /* Total length */ 2111f0e21a0SMarc Kleine-Budde len += sizeof(write_reg_buf->crc.crc); 2121f0e21a0SMarc Kleine-Budde } else { 2131f0e21a0SMarc Kleine-Budde len += sizeof(write_reg_buf->nocrc.cmd); 2141f0e21a0SMarc Kleine-Budde } 2151f0e21a0SMarc Kleine-Budde 2161f0e21a0SMarc Kleine-Budde return len; 2171f0e21a0SMarc Kleine-Budde } 2181f0e21a0SMarc Kleine-Budde 2191f0e21a0SMarc Kleine-Budde static inline int 220eb79a267SMarc Kleine-Budde mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv, 2211f0e21a0SMarc Kleine-Budde u8 *tef_tail) 2221f0e21a0SMarc Kleine-Budde { 2231f0e21a0SMarc Kleine-Budde u32 tef_ua; 2241f0e21a0SMarc Kleine-Budde int err; 2251f0e21a0SMarc Kleine-Budde 226eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFUA, &tef_ua); 2271f0e21a0SMarc Kleine-Budde if (err) 2281f0e21a0SMarc Kleine-Budde return err; 2291f0e21a0SMarc Kleine-Budde 230eb79a267SMarc Kleine-Budde *tef_tail = tef_ua / sizeof(struct mcp251xfd_hw_tef_obj); 2311f0e21a0SMarc Kleine-Budde 2321f0e21a0SMarc Kleine-Budde return 0; 2331f0e21a0SMarc Kleine-Budde } 2341f0e21a0SMarc Kleine-Budde 2351f0e21a0SMarc Kleine-Budde static inline int 236eb79a267SMarc Kleine-Budde mcp251xfd_tx_tail_get_from_chip(const struct mcp251xfd_priv *priv, 2371f0e21a0SMarc Kleine-Budde u8 *tx_tail) 2381f0e21a0SMarc Kleine-Budde { 2391f0e21a0SMarc Kleine-Budde u32 fifo_sta; 2401f0e21a0SMarc Kleine-Budde int err; 2411f0e21a0SMarc Kleine-Budde 2421f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, 243eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA(MCP251XFD_TX_FIFO), 2441f0e21a0SMarc Kleine-Budde &fifo_sta); 2451f0e21a0SMarc Kleine-Budde if (err) 2461f0e21a0SMarc Kleine-Budde return err; 2471f0e21a0SMarc Kleine-Budde 248eb79a267SMarc Kleine-Budde *tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta); 2491f0e21a0SMarc Kleine-Budde 2501f0e21a0SMarc Kleine-Budde return 0; 2511f0e21a0SMarc Kleine-Budde } 2521f0e21a0SMarc Kleine-Budde 2531f0e21a0SMarc Kleine-Budde static inline int 254eb79a267SMarc Kleine-Budde mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv, 255eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring, 2561f0e21a0SMarc Kleine-Budde u8 *rx_head) 2571f0e21a0SMarc Kleine-Budde { 2581f0e21a0SMarc Kleine-Budde u32 fifo_sta; 2591f0e21a0SMarc Kleine-Budde int err; 2601f0e21a0SMarc Kleine-Budde 261eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(ring->fifo_nr), 2621f0e21a0SMarc Kleine-Budde &fifo_sta); 2631f0e21a0SMarc Kleine-Budde if (err) 2641f0e21a0SMarc Kleine-Budde return err; 2651f0e21a0SMarc Kleine-Budde 266eb79a267SMarc Kleine-Budde *rx_head = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta); 2671f0e21a0SMarc Kleine-Budde 2681f0e21a0SMarc Kleine-Budde return 0; 2691f0e21a0SMarc Kleine-Budde } 2701f0e21a0SMarc Kleine-Budde 2711f0e21a0SMarc Kleine-Budde static inline int 272eb79a267SMarc Kleine-Budde mcp251xfd_rx_tail_get_from_chip(const struct mcp251xfd_priv *priv, 273eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring, 2741f0e21a0SMarc Kleine-Budde u8 *rx_tail) 2751f0e21a0SMarc Kleine-Budde { 2761f0e21a0SMarc Kleine-Budde u32 fifo_ua; 2771f0e21a0SMarc Kleine-Budde int err; 2781f0e21a0SMarc Kleine-Budde 279eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOUA(ring->fifo_nr), 2801f0e21a0SMarc Kleine-Budde &fifo_ua); 2811f0e21a0SMarc Kleine-Budde if (err) 2821f0e21a0SMarc Kleine-Budde return err; 2831f0e21a0SMarc Kleine-Budde 284eb79a267SMarc Kleine-Budde fifo_ua -= ring->base - MCP251XFD_RAM_START; 2851f0e21a0SMarc Kleine-Budde *rx_tail = fifo_ua / ring->obj_size; 2861f0e21a0SMarc Kleine-Budde 2871f0e21a0SMarc Kleine-Budde return 0; 2881f0e21a0SMarc Kleine-Budde } 2891f0e21a0SMarc Kleine-Budde 2901f0e21a0SMarc Kleine-Budde static void 291eb79a267SMarc Kleine-Budde mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv, 292eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *ring, 293eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj, 2941f0e21a0SMarc Kleine-Budde const u8 rts_buf_len, 2951f0e21a0SMarc Kleine-Budde const u8 n) 2961f0e21a0SMarc Kleine-Budde { 2971f0e21a0SMarc Kleine-Budde struct spi_transfer *xfer; 2981f0e21a0SMarc Kleine-Budde u16 addr; 2991f0e21a0SMarc Kleine-Budde 3001f0e21a0SMarc Kleine-Budde /* FIFO load */ 301eb79a267SMarc Kleine-Budde addr = mcp251xfd_get_tx_obj_addr(ring, n); 302eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) 303eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_write_crc_set_addr(&tx_obj->buf.crc.cmd, 3041f0e21a0SMarc Kleine-Budde addr); 3051f0e21a0SMarc Kleine-Budde else 306eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_write_nocrc(&tx_obj->buf.nocrc.cmd, 3071f0e21a0SMarc Kleine-Budde addr); 3081f0e21a0SMarc Kleine-Budde 3091f0e21a0SMarc Kleine-Budde xfer = &tx_obj->xfer[0]; 3101f0e21a0SMarc Kleine-Budde xfer->tx_buf = &tx_obj->buf; 3111f0e21a0SMarc Kleine-Budde xfer->len = 0; /* actual len is assigned on the fly */ 3121f0e21a0SMarc Kleine-Budde xfer->cs_change = 1; 3131f0e21a0SMarc Kleine-Budde xfer->cs_change_delay.value = 0; 3141f0e21a0SMarc Kleine-Budde xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 3151f0e21a0SMarc Kleine-Budde 3161f0e21a0SMarc Kleine-Budde /* FIFO request to send */ 3171f0e21a0SMarc Kleine-Budde xfer = &tx_obj->xfer[1]; 3181f0e21a0SMarc Kleine-Budde xfer->tx_buf = &ring->rts_buf; 3191f0e21a0SMarc Kleine-Budde xfer->len = rts_buf_len; 3201f0e21a0SMarc Kleine-Budde 3211f0e21a0SMarc Kleine-Budde /* SPI message */ 3221f0e21a0SMarc Kleine-Budde spi_message_init_with_transfers(&tx_obj->msg, tx_obj->xfer, 3231f0e21a0SMarc Kleine-Budde ARRAY_SIZE(tx_obj->xfer)); 3241f0e21a0SMarc Kleine-Budde } 3251f0e21a0SMarc Kleine-Budde 326eb79a267SMarc Kleine-Budde static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv) 3271f0e21a0SMarc Kleine-Budde { 328dada6a6cSMarc Kleine-Budde struct mcp251xfd_tef_ring *tef_ring; 329eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring; 330eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *rx_ring, *prev_rx_ring = NULL; 331eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 332eb94b74cSMarc Kleine-Budde struct spi_transfer *xfer; 3331f0e21a0SMarc Kleine-Budde u32 val; 3341f0e21a0SMarc Kleine-Budde u16 addr; 3351f0e21a0SMarc Kleine-Budde u8 len; 3361f652bb6SUrsula Maplehurst int i, j; 3371f0e21a0SMarc Kleine-Budde 3380084e298SMarc Kleine-Budde netdev_reset_queue(priv->ndev); 3390084e298SMarc Kleine-Budde 3401f0e21a0SMarc Kleine-Budde /* TEF */ 341dada6a6cSMarc Kleine-Budde tef_ring = priv->tef; 342dada6a6cSMarc Kleine-Budde tef_ring->head = 0; 343dada6a6cSMarc Kleine-Budde tef_ring->tail = 0; 3441f0e21a0SMarc Kleine-Budde 34568c0c1c7SMarc Kleine-Budde /* FIFO increment TEF tail pointer */ 34668c0c1c7SMarc Kleine-Budde addr = MCP251XFD_REG_TEFCON; 34768c0c1c7SMarc Kleine-Budde val = MCP251XFD_REG_TEFCON_UINC; 34868c0c1c7SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf, 34968c0c1c7SMarc Kleine-Budde addr, val, val); 35068c0c1c7SMarc Kleine-Budde 35168c0c1c7SMarc Kleine-Budde for (j = 0; j < ARRAY_SIZE(tef_ring->uinc_xfer); j++) { 35268c0c1c7SMarc Kleine-Budde xfer = &tef_ring->uinc_xfer[j]; 35368c0c1c7SMarc Kleine-Budde xfer->tx_buf = &tef_ring->uinc_buf; 35468c0c1c7SMarc Kleine-Budde xfer->len = len; 35568c0c1c7SMarc Kleine-Budde xfer->cs_change = 1; 35668c0c1c7SMarc Kleine-Budde xfer->cs_change_delay.value = 0; 35768c0c1c7SMarc Kleine-Budde xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 35868c0c1c7SMarc Kleine-Budde } 35968c0c1c7SMarc Kleine-Budde 360eb94b74cSMarc Kleine-Budde /* "cs_change == 1" on the last transfer results in an active 361eb94b74cSMarc Kleine-Budde * chip select after the complete SPI message. This causes the 362eb94b74cSMarc Kleine-Budde * controller to interpret the next register access as 363eb94b74cSMarc Kleine-Budde * data. Set "cs_change" of the last transfer to "0" to 364eb94b74cSMarc Kleine-Budde * properly deactivate the chip select at the end of the 365eb94b74cSMarc Kleine-Budde * message. 366eb94b74cSMarc Kleine-Budde */ 367eb94b74cSMarc Kleine-Budde xfer->cs_change = 0; 368eb94b74cSMarc Kleine-Budde 3691f0e21a0SMarc Kleine-Budde /* TX */ 3701f0e21a0SMarc Kleine-Budde tx_ring = priv->tx; 3711f0e21a0SMarc Kleine-Budde tx_ring->head = 0; 3721f0e21a0SMarc Kleine-Budde tx_ring->tail = 0; 373eb79a267SMarc Kleine-Budde tx_ring->base = mcp251xfd_get_tef_obj_addr(tx_ring->obj_num); 3741f0e21a0SMarc Kleine-Budde 3751f0e21a0SMarc Kleine-Budde /* FIFO request to send */ 376eb79a267SMarc Kleine-Budde addr = MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO); 377eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC; 378eb79a267SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf, 3791f0e21a0SMarc Kleine-Budde addr, val, val); 3801f0e21a0SMarc Kleine-Budde 381eb79a267SMarc Kleine-Budde mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i) 382eb79a267SMarc Kleine-Budde mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i); 3831f0e21a0SMarc Kleine-Budde 3841f0e21a0SMarc Kleine-Budde /* RX */ 385eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { 3861f0e21a0SMarc Kleine-Budde rx_ring->head = 0; 3871f0e21a0SMarc Kleine-Budde rx_ring->tail = 0; 3881f0e21a0SMarc Kleine-Budde rx_ring->nr = i; 389eb79a267SMarc Kleine-Budde rx_ring->fifo_nr = MCP251XFD_RX_FIFO(i); 3901f0e21a0SMarc Kleine-Budde 3911f0e21a0SMarc Kleine-Budde if (!prev_rx_ring) 3921f0e21a0SMarc Kleine-Budde rx_ring->base = 393eb79a267SMarc Kleine-Budde mcp251xfd_get_tx_obj_addr(tx_ring, 3941f0e21a0SMarc Kleine-Budde tx_ring->obj_num); 3951f0e21a0SMarc Kleine-Budde else 3961f0e21a0SMarc Kleine-Budde rx_ring->base = prev_rx_ring->base + 3971f0e21a0SMarc Kleine-Budde prev_rx_ring->obj_size * 3981f0e21a0SMarc Kleine-Budde prev_rx_ring->obj_num; 3991f0e21a0SMarc Kleine-Budde 4001f0e21a0SMarc Kleine-Budde prev_rx_ring = rx_ring; 4011f652bb6SUrsula Maplehurst 4021f652bb6SUrsula Maplehurst /* FIFO increment RX tail pointer */ 4031f652bb6SUrsula Maplehurst addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr); 4041f652bb6SUrsula Maplehurst val = MCP251XFD_REG_FIFOCON_UINC; 4051f652bb6SUrsula Maplehurst len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf, 4061f652bb6SUrsula Maplehurst addr, val, val); 4071f652bb6SUrsula Maplehurst 4081f652bb6SUrsula Maplehurst for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) { 4091f652bb6SUrsula Maplehurst xfer = &rx_ring->uinc_xfer[j]; 4101f652bb6SUrsula Maplehurst xfer->tx_buf = &rx_ring->uinc_buf; 4111f652bb6SUrsula Maplehurst xfer->len = len; 4121f652bb6SUrsula Maplehurst xfer->cs_change = 1; 4131f652bb6SUrsula Maplehurst xfer->cs_change_delay.value = 0; 4141f652bb6SUrsula Maplehurst xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 4151f652bb6SUrsula Maplehurst } 416eb94b74cSMarc Kleine-Budde 417eb94b74cSMarc Kleine-Budde /* "cs_change == 1" on the last transfer results in an 418eb94b74cSMarc Kleine-Budde * active chip select after the complete SPI 419eb94b74cSMarc Kleine-Budde * message. This causes the controller to interpret 420eb94b74cSMarc Kleine-Budde * the next register access as data. Set "cs_change" 421eb94b74cSMarc Kleine-Budde * of the last transfer to "0" to properly deactivate 422eb94b74cSMarc Kleine-Budde * the chip select at the end of the message. 423eb94b74cSMarc Kleine-Budde */ 424eb94b74cSMarc Kleine-Budde xfer->cs_change = 0; 4251f0e21a0SMarc Kleine-Budde } 4261f0e21a0SMarc Kleine-Budde } 4271f0e21a0SMarc Kleine-Budde 428eb79a267SMarc Kleine-Budde static void mcp251xfd_ring_free(struct mcp251xfd_priv *priv) 4291f0e21a0SMarc Kleine-Budde { 4301f0e21a0SMarc Kleine-Budde int i; 4311f0e21a0SMarc Kleine-Budde 4321f0e21a0SMarc Kleine-Budde for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) { 4331f0e21a0SMarc Kleine-Budde kfree(priv->rx[i]); 4341f0e21a0SMarc Kleine-Budde priv->rx[i] = NULL; 4351f0e21a0SMarc Kleine-Budde } 4361f0e21a0SMarc Kleine-Budde } 4371f0e21a0SMarc Kleine-Budde 438eb79a267SMarc Kleine-Budde static int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv) 4391f0e21a0SMarc Kleine-Budde { 440eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring; 441eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *rx_ring; 4421f0e21a0SMarc Kleine-Budde int tef_obj_size, tx_obj_size, rx_obj_size; 4431f0e21a0SMarc Kleine-Budde int tx_obj_num; 4441f0e21a0SMarc Kleine-Budde int ram_free, i; 4451f0e21a0SMarc Kleine-Budde 446eb79a267SMarc Kleine-Budde tef_obj_size = sizeof(struct mcp251xfd_hw_tef_obj); 4471f0e21a0SMarc Kleine-Budde /* listen-only mode works like FD mode */ 4481f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) { 449eb79a267SMarc Kleine-Budde tx_obj_num = MCP251XFD_TX_OBJ_NUM_CANFD; 450eb79a267SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd); 451eb79a267SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd); 4521f0e21a0SMarc Kleine-Budde } else { 453eb79a267SMarc Kleine-Budde tx_obj_num = MCP251XFD_TX_OBJ_NUM_CAN; 454eb79a267SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can); 455eb79a267SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can); 4561f0e21a0SMarc Kleine-Budde } 4571f0e21a0SMarc Kleine-Budde 4581f0e21a0SMarc Kleine-Budde tx_ring = priv->tx; 4591f0e21a0SMarc Kleine-Budde tx_ring->obj_num = tx_obj_num; 4601f0e21a0SMarc Kleine-Budde tx_ring->obj_size = tx_obj_size; 4611f0e21a0SMarc Kleine-Budde 462eb79a267SMarc Kleine-Budde ram_free = MCP251XFD_RAM_SIZE - tx_obj_num * 4631f0e21a0SMarc Kleine-Budde (tef_obj_size + tx_obj_size); 4641f0e21a0SMarc Kleine-Budde 4651f0e21a0SMarc Kleine-Budde for (i = 0; 4661f0e21a0SMarc Kleine-Budde i < ARRAY_SIZE(priv->rx) && ram_free >= rx_obj_size; 4671f0e21a0SMarc Kleine-Budde i++) { 4681f0e21a0SMarc Kleine-Budde int rx_obj_num; 4691f0e21a0SMarc Kleine-Budde 4701f0e21a0SMarc Kleine-Budde rx_obj_num = ram_free / rx_obj_size; 4714843ad9bSMarc Kleine-Budde rx_obj_num = min(1 << (fls(rx_obj_num) - 1), 4724843ad9bSMarc Kleine-Budde MCP251XFD_RX_OBJ_NUM_MAX); 4731f0e21a0SMarc Kleine-Budde 4741f0e21a0SMarc Kleine-Budde rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num, 4751f0e21a0SMarc Kleine-Budde GFP_KERNEL); 4761f0e21a0SMarc Kleine-Budde if (!rx_ring) { 477eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 4781f0e21a0SMarc Kleine-Budde return -ENOMEM; 4791f0e21a0SMarc Kleine-Budde } 4801f0e21a0SMarc Kleine-Budde rx_ring->obj_num = rx_obj_num; 4811f0e21a0SMarc Kleine-Budde rx_ring->obj_size = rx_obj_size; 4821f0e21a0SMarc Kleine-Budde priv->rx[i] = rx_ring; 4831f0e21a0SMarc Kleine-Budde 4841f0e21a0SMarc Kleine-Budde ram_free -= rx_ring->obj_num * rx_ring->obj_size; 4851f0e21a0SMarc Kleine-Budde } 4861f0e21a0SMarc Kleine-Budde priv->rx_ring_num = i; 4871f0e21a0SMarc Kleine-Budde 4881f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4891f0e21a0SMarc Kleine-Budde "FIFO setup: TEF: %d*%d bytes = %d bytes, TX: %d*%d bytes = %d bytes\n", 4901f0e21a0SMarc Kleine-Budde tx_obj_num, tef_obj_size, tef_obj_size * tx_obj_num, 4911f0e21a0SMarc Kleine-Budde tx_obj_num, tx_obj_size, tx_obj_size * tx_obj_num); 4921f0e21a0SMarc Kleine-Budde 493eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { 4941f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4951f0e21a0SMarc Kleine-Budde "FIFO setup: RX-%d: %d*%d bytes = %d bytes\n", 4961f0e21a0SMarc Kleine-Budde i, rx_ring->obj_num, rx_ring->obj_size, 4971f0e21a0SMarc Kleine-Budde rx_ring->obj_size * rx_ring->obj_num); 4981f0e21a0SMarc Kleine-Budde } 4991f0e21a0SMarc Kleine-Budde 5001f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 5011f0e21a0SMarc Kleine-Budde "FIFO setup: free: %d bytes\n", 5021f0e21a0SMarc Kleine-Budde ram_free); 5031f0e21a0SMarc Kleine-Budde 5041f0e21a0SMarc Kleine-Budde return 0; 5051f0e21a0SMarc Kleine-Budde } 5061f0e21a0SMarc Kleine-Budde 5071f0e21a0SMarc Kleine-Budde static inline int 508eb79a267SMarc Kleine-Budde mcp251xfd_chip_get_mode(const struct mcp251xfd_priv *priv, u8 *mode) 5091f0e21a0SMarc Kleine-Budde { 5101f0e21a0SMarc Kleine-Budde u32 val; 5111f0e21a0SMarc Kleine-Budde int err; 5121f0e21a0SMarc Kleine-Budde 513eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_CON, &val); 5141f0e21a0SMarc Kleine-Budde if (err) 5151f0e21a0SMarc Kleine-Budde return err; 5161f0e21a0SMarc Kleine-Budde 517eb79a267SMarc Kleine-Budde *mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, val); 5181f0e21a0SMarc Kleine-Budde 5191f0e21a0SMarc Kleine-Budde return 0; 5201f0e21a0SMarc Kleine-Budde } 5211f0e21a0SMarc Kleine-Budde 5221f0e21a0SMarc Kleine-Budde static int 523eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv, 5241f0e21a0SMarc Kleine-Budde const u8 mode_req, bool nowait) 5251f0e21a0SMarc Kleine-Budde { 5261f0e21a0SMarc Kleine-Budde u32 con, con_reqop; 5271f0e21a0SMarc Kleine-Budde int err; 5281f0e21a0SMarc Kleine-Budde 529eb79a267SMarc Kleine-Budde con_reqop = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, mode_req); 530eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CON, 531eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_REQOP_MASK, con_reqop); 5321f0e21a0SMarc Kleine-Budde if (err) 5331f0e21a0SMarc Kleine-Budde return err; 5341f0e21a0SMarc Kleine-Budde 535eb79a267SMarc Kleine-Budde if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait) 5361f0e21a0SMarc Kleine-Budde return 0; 5371f0e21a0SMarc Kleine-Budde 538eb79a267SMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con, 539eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, 5401f0e21a0SMarc Kleine-Budde con) == mode_req, 541eb79a267SMarc Kleine-Budde MCP251XFD_POLL_SLEEP_US, 542eb79a267SMarc Kleine-Budde MCP251XFD_POLL_TIMEOUT_US); 5431f0e21a0SMarc Kleine-Budde if (err) { 544eb79a267SMarc Kleine-Budde u8 mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, con); 5451f0e21a0SMarc Kleine-Budde 5461f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 5471f0e21a0SMarc Kleine-Budde "Controller failed to enter mode %s Mode (%u) and stays in %s Mode (%u).\n", 548eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode_req), mode_req, 549eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 5501f0e21a0SMarc Kleine-Budde return err; 5511f0e21a0SMarc Kleine-Budde } 5521f0e21a0SMarc Kleine-Budde 5531f0e21a0SMarc Kleine-Budde return 0; 5541f0e21a0SMarc Kleine-Budde } 5551f0e21a0SMarc Kleine-Budde 5561f0e21a0SMarc Kleine-Budde static inline int 557eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv, 5581f0e21a0SMarc Kleine-Budde const u8 mode_req) 5591f0e21a0SMarc Kleine-Budde { 560eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode_req, false); 5611f0e21a0SMarc Kleine-Budde } 5621f0e21a0SMarc Kleine-Budde 563*b558e200SMarc Kleine-Budde static inline int __maybe_unused 564eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode_nowait(const struct mcp251xfd_priv *priv, 5651f0e21a0SMarc Kleine-Budde const u8 mode_req) 5661f0e21a0SMarc Kleine-Budde { 567eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode_req, true); 5681f0e21a0SMarc Kleine-Budde } 5691f0e21a0SMarc Kleine-Budde 570eb79a267SMarc Kleine-Budde static inline bool mcp251xfd_osc_invalid(u32 reg) 5711f0e21a0SMarc Kleine-Budde { 5721f0e21a0SMarc Kleine-Budde return reg == 0x0 || reg == 0xffffffff; 5731f0e21a0SMarc Kleine-Budde } 5741f0e21a0SMarc Kleine-Budde 575eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_clock_enable(const struct mcp251xfd_priv *priv) 5761f0e21a0SMarc Kleine-Budde { 5771f0e21a0SMarc Kleine-Budde u32 osc, osc_reference, osc_mask; 5781f0e21a0SMarc Kleine-Budde int err; 5791f0e21a0SMarc Kleine-Budde 5801f0e21a0SMarc Kleine-Budde /* Set Power On Defaults for "Clock Output Divisor" and remove 5811f0e21a0SMarc Kleine-Budde * "Oscillator Disable" bit. 5821f0e21a0SMarc Kleine-Budde */ 583eb79a267SMarc Kleine-Budde osc = FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 584eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 585eb79a267SMarc Kleine-Budde osc_reference = MCP251XFD_REG_OSC_OSCRDY; 586eb79a267SMarc Kleine-Budde osc_mask = MCP251XFD_REG_OSC_OSCRDY | MCP251XFD_REG_OSC_PLLRDY; 5871f0e21a0SMarc Kleine-Budde 5881f0e21a0SMarc Kleine-Budde /* Note: 5891f0e21a0SMarc Kleine-Budde * 5901f0e21a0SMarc Kleine-Budde * If the controller is in Sleep Mode the following write only 5911f0e21a0SMarc Kleine-Budde * removes the "Oscillator Disable" bit and powers it up. All 5921f0e21a0SMarc Kleine-Budde * other bits are unaffected. 5931f0e21a0SMarc Kleine-Budde */ 594eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc); 5951f0e21a0SMarc Kleine-Budde if (err) 5961f0e21a0SMarc Kleine-Budde return err; 5971f0e21a0SMarc Kleine-Budde 5981f0e21a0SMarc Kleine-Budde /* Wait for "Oscillator Ready" bit */ 599eb79a267SMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_OSC, osc, 6001f0e21a0SMarc Kleine-Budde (osc & osc_mask) == osc_reference, 601eb79a267SMarc Kleine-Budde MCP251XFD_OSC_STAB_SLEEP_US, 602eb79a267SMarc Kleine-Budde MCP251XFD_OSC_STAB_TIMEOUT_US); 603eb79a267SMarc Kleine-Budde if (mcp251xfd_osc_invalid(osc)) { 6041f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 6051f0e21a0SMarc Kleine-Budde "Failed to detect %s (osc=0x%08x).\n", 606eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv), osc); 6071f0e21a0SMarc Kleine-Budde return -ENODEV; 6081f0e21a0SMarc Kleine-Budde } else if (err == -ETIMEDOUT) { 6091f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 6101f0e21a0SMarc Kleine-Budde "Timeout waiting for Oscillator Ready (osc=0x%08x, osc_reference=0x%08x)\n", 6111f0e21a0SMarc Kleine-Budde osc, osc_reference); 6121f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6131f0e21a0SMarc Kleine-Budde } 6141f0e21a0SMarc Kleine-Budde 615dfe99ba2SMarc Kleine-Budde return err; 6161f0e21a0SMarc Kleine-Budde } 6171f0e21a0SMarc Kleine-Budde 618eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_do(const struct mcp251xfd_priv *priv) 6191f0e21a0SMarc Kleine-Budde { 620eb79a267SMarc Kleine-Budde const __be16 cmd = mcp251xfd_cmd_reset(); 6211f0e21a0SMarc Kleine-Budde int err; 6221f0e21a0SMarc Kleine-Budde 6231f0e21a0SMarc Kleine-Budde /* The Set Mode and SPI Reset command only seems to works if 6241f0e21a0SMarc Kleine-Budde * the controller is not in Sleep Mode. 6251f0e21a0SMarc Kleine-Budde */ 626eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_clock_enable(priv); 6271f0e21a0SMarc Kleine-Budde if (err) 6281f0e21a0SMarc Kleine-Budde return err; 6291f0e21a0SMarc Kleine-Budde 630eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_CONFIG); 6311f0e21a0SMarc Kleine-Budde if (err) 6321f0e21a0SMarc Kleine-Budde return err; 6331f0e21a0SMarc Kleine-Budde 6341f0e21a0SMarc Kleine-Budde /* spi_write_then_read() works with non DMA-safe buffers */ 6351f0e21a0SMarc Kleine-Budde return spi_write_then_read(priv->spi, &cmd, sizeof(cmd), NULL, 0); 6361f0e21a0SMarc Kleine-Budde } 6371f0e21a0SMarc Kleine-Budde 638eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_check(const struct mcp251xfd_priv *priv) 6391f0e21a0SMarc Kleine-Budde { 6401f0e21a0SMarc Kleine-Budde u32 osc, osc_reference; 6411f0e21a0SMarc Kleine-Budde u8 mode; 6421f0e21a0SMarc Kleine-Budde int err; 6431f0e21a0SMarc Kleine-Budde 644eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_get_mode(priv, &mode); 6451f0e21a0SMarc Kleine-Budde if (err) 6461f0e21a0SMarc Kleine-Budde return err; 6471f0e21a0SMarc Kleine-Budde 648eb79a267SMarc Kleine-Budde if (mode != MCP251XFD_REG_CON_MODE_CONFIG) { 6491f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 6501f0e21a0SMarc Kleine-Budde "Controller not in Config Mode after reset, but in %s Mode (%u).\n", 651eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 6521f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6531f0e21a0SMarc Kleine-Budde } 6541f0e21a0SMarc Kleine-Budde 655eb79a267SMarc Kleine-Budde osc_reference = MCP251XFD_REG_OSC_OSCRDY | 656eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 657eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 6581f0e21a0SMarc Kleine-Budde 6591f0e21a0SMarc Kleine-Budde /* check reset defaults of OSC reg */ 660eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc); 6611f0e21a0SMarc Kleine-Budde if (err) 6621f0e21a0SMarc Kleine-Budde return err; 6631f0e21a0SMarc Kleine-Budde 6641f0e21a0SMarc Kleine-Budde if (osc != osc_reference) { 6651f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 666f93486a7SMarc Kleine-Budde "Controller failed to reset. osc=0x%08x, reference value=0x%08x.\n", 6671f0e21a0SMarc Kleine-Budde osc, osc_reference); 6681f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6691f0e21a0SMarc Kleine-Budde } 6701f0e21a0SMarc Kleine-Budde 6711f0e21a0SMarc Kleine-Budde return 0; 6721f0e21a0SMarc Kleine-Budde } 6731f0e21a0SMarc Kleine-Budde 674eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset(const struct mcp251xfd_priv *priv) 6751f0e21a0SMarc Kleine-Budde { 6761f0e21a0SMarc Kleine-Budde int err, i; 6771f0e21a0SMarc Kleine-Budde 678eb79a267SMarc Kleine-Budde for (i = 0; i < MCP251XFD_SOFTRESET_RETRIES_MAX; i++) { 6791f0e21a0SMarc Kleine-Budde if (i) 6801f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 681f93486a7SMarc Kleine-Budde "Retrying to reset controller.\n"); 6821f0e21a0SMarc Kleine-Budde 683eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset_do(priv); 6841f0e21a0SMarc Kleine-Budde if (err == -ETIMEDOUT) 6851f0e21a0SMarc Kleine-Budde continue; 6861f0e21a0SMarc Kleine-Budde if (err) 6871f0e21a0SMarc Kleine-Budde return err; 6881f0e21a0SMarc Kleine-Budde 689eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset_check(priv); 6901f0e21a0SMarc Kleine-Budde if (err == -ETIMEDOUT) 6911f0e21a0SMarc Kleine-Budde continue; 6921f0e21a0SMarc Kleine-Budde if (err) 6931f0e21a0SMarc Kleine-Budde return err; 6941f0e21a0SMarc Kleine-Budde 6951f0e21a0SMarc Kleine-Budde return 0; 6961f0e21a0SMarc Kleine-Budde } 6971f0e21a0SMarc Kleine-Budde 6981f0e21a0SMarc Kleine-Budde return err; 6991f0e21a0SMarc Kleine-Budde } 7001f0e21a0SMarc Kleine-Budde 701eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_clock_init(const struct mcp251xfd_priv *priv) 7021f0e21a0SMarc Kleine-Budde { 7031f0e21a0SMarc Kleine-Budde u32 osc; 7041f0e21a0SMarc Kleine-Budde int err; 7051f0e21a0SMarc Kleine-Budde 7061f0e21a0SMarc Kleine-Budde /* Activate Low Power Mode on Oscillator Disable. This only 7071f0e21a0SMarc Kleine-Budde * works on the MCP2518FD. The MCP2517FD will go into normal 7081f0e21a0SMarc Kleine-Budde * Sleep Mode instead. 7091f0e21a0SMarc Kleine-Budde */ 710eb79a267SMarc Kleine-Budde osc = MCP251XFD_REG_OSC_LPMEN | 711eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 712eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 713eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc); 7141f0e21a0SMarc Kleine-Budde if (err) 7151f0e21a0SMarc Kleine-Budde return err; 7161f0e21a0SMarc Kleine-Budde 7171f0e21a0SMarc Kleine-Budde /* Set Time Base Counter Prescaler to 1. 7181f0e21a0SMarc Kleine-Budde * 7191f0e21a0SMarc Kleine-Budde * This means an overflow of the 32 bit Time Base Counter 7201f0e21a0SMarc Kleine-Budde * register at 40 MHz every 107 seconds. 7211f0e21a0SMarc Kleine-Budde */ 722eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_TSCON, 723eb79a267SMarc Kleine-Budde MCP251XFD_REG_TSCON_TBCEN); 7241f0e21a0SMarc Kleine-Budde } 7251f0e21a0SMarc Kleine-Budde 726eb79a267SMarc Kleine-Budde static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv) 7271f0e21a0SMarc Kleine-Budde { 7281f0e21a0SMarc Kleine-Budde const struct can_bittiming *bt = &priv->can.bittiming; 7291f0e21a0SMarc Kleine-Budde const struct can_bittiming *dbt = &priv->can.data_bittiming; 7301f0e21a0SMarc Kleine-Budde u32 val = 0; 7311f0e21a0SMarc Kleine-Budde s8 tdco; 7321f0e21a0SMarc Kleine-Budde int err; 7331f0e21a0SMarc Kleine-Budde 7341f0e21a0SMarc Kleine-Budde /* CAN Control Register 7351f0e21a0SMarc Kleine-Budde * 7361f0e21a0SMarc Kleine-Budde * - no transmit bandwidth sharing 7371f0e21a0SMarc Kleine-Budde * - config mode 7381f0e21a0SMarc Kleine-Budde * - disable transmit queue 7391f0e21a0SMarc Kleine-Budde * - store in transmit FIFO event 7401f0e21a0SMarc Kleine-Budde * - transition to restricted operation mode on system error 7411f0e21a0SMarc Kleine-Budde * - ESI is transmitted recessive when ESI of message is high or 7421f0e21a0SMarc Kleine-Budde * CAN controller error passive 7431f0e21a0SMarc Kleine-Budde * - restricted retransmission attempts, 7441f0e21a0SMarc Kleine-Budde * use TQXCON_TXAT and FIFOCON_TXAT 7451f0e21a0SMarc Kleine-Budde * - wake-up filter bits T11FILTER 7461f0e21a0SMarc Kleine-Budde * - use CAN bus line filter for wakeup 7471f0e21a0SMarc Kleine-Budde * - protocol exception is treated as a form error 7481f0e21a0SMarc Kleine-Budde * - Do not compare data bytes 7491f0e21a0SMarc Kleine-Budde */ 750eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, 751eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_MODE_CONFIG) | 752eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_STEF | 753eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_ESIGM | 754eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_RTXAT | 755eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_CON_WFT_MASK, 756eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_WFT_T11FILTER) | 757eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_WAKFIL | 758eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_PXEDIS; 7591f0e21a0SMarc Kleine-Budde 7601f0e21a0SMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)) 761eb79a267SMarc Kleine-Budde val |= MCP251XFD_REG_CON_ISOCRCEN; 7621f0e21a0SMarc Kleine-Budde 763eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_CON, val); 7641f0e21a0SMarc Kleine-Budde if (err) 7651f0e21a0SMarc Kleine-Budde return err; 7661f0e21a0SMarc Kleine-Budde 7671f0e21a0SMarc Kleine-Budde /* Nominal Bit Time */ 768eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_NBTCFG_BRP_MASK, bt->brp - 1) | 769eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG1_MASK, 7701f0e21a0SMarc Kleine-Budde bt->prop_seg + bt->phase_seg1 - 1) | 771eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG2_MASK, 7721f0e21a0SMarc Kleine-Budde bt->phase_seg2 - 1) | 773eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_SJW_MASK, bt->sjw - 1); 7741f0e21a0SMarc Kleine-Budde 775eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_NBTCFG, val); 7761f0e21a0SMarc Kleine-Budde if (err) 7771f0e21a0SMarc Kleine-Budde return err; 7781f0e21a0SMarc Kleine-Budde 7791f0e21a0SMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD)) 7801f0e21a0SMarc Kleine-Budde return 0; 7811f0e21a0SMarc Kleine-Budde 7821f0e21a0SMarc Kleine-Budde /* Data Bit Time */ 783eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_DBTCFG_BRP_MASK, dbt->brp - 1) | 784eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG1_MASK, 7851f0e21a0SMarc Kleine-Budde dbt->prop_seg + dbt->phase_seg1 - 1) | 786eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG2_MASK, 7871f0e21a0SMarc Kleine-Budde dbt->phase_seg2 - 1) | 788eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_SJW_MASK, dbt->sjw - 1); 7891f0e21a0SMarc Kleine-Budde 790eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_DBTCFG, val); 7911f0e21a0SMarc Kleine-Budde if (err) 7921f0e21a0SMarc Kleine-Budde return err; 7931f0e21a0SMarc Kleine-Budde 7941f0e21a0SMarc Kleine-Budde /* Transmitter Delay Compensation */ 7951f0e21a0SMarc Kleine-Budde tdco = clamp_t(int, dbt->brp * (dbt->prop_seg + dbt->phase_seg1), 7961f0e21a0SMarc Kleine-Budde -64, 63); 797eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, 798eb79a267SMarc Kleine-Budde MCP251XFD_REG_TDC_TDCMOD_AUTO) | 799eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, tdco); 8001f0e21a0SMarc Kleine-Budde 801eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val); 8021f0e21a0SMarc Kleine-Budde } 8031f0e21a0SMarc Kleine-Budde 804eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_enable(const struct mcp251xfd_priv *priv) 8051f0e21a0SMarc Kleine-Budde { 8061f0e21a0SMarc Kleine-Budde u32 val; 8071f0e21a0SMarc Kleine-Budde 8081f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 8091f0e21a0SMarc Kleine-Budde return 0; 8101f0e21a0SMarc Kleine-Budde 8111f0e21a0SMarc Kleine-Budde /* Configure GPIOs: 8121f0e21a0SMarc Kleine-Budde * - PIN0: GPIO Input 8131f0e21a0SMarc Kleine-Budde * - PIN1: GPIO Input/RX Interrupt 8141f0e21a0SMarc Kleine-Budde * 8151f0e21a0SMarc Kleine-Budde * PIN1 must be Input, otherwise there is a glitch on the 8161f0e21a0SMarc Kleine-Budde * rx-INT line. It happens between setting the PIN as output 8171f0e21a0SMarc Kleine-Budde * (in the first byte of the SPI transfer) and configuring the 8181f0e21a0SMarc Kleine-Budde * PIN as interrupt (in the last byte of the SPI transfer). 8191f0e21a0SMarc Kleine-Budde */ 820eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_IOCON_PM0 | MCP251XFD_REG_IOCON_TRIS1 | 821eb79a267SMarc Kleine-Budde MCP251XFD_REG_IOCON_TRIS0; 822eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val); 8231f0e21a0SMarc Kleine-Budde } 8241f0e21a0SMarc Kleine-Budde 825eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_disable(const struct mcp251xfd_priv *priv) 8261f0e21a0SMarc Kleine-Budde { 8271f0e21a0SMarc Kleine-Budde u32 val; 8281f0e21a0SMarc Kleine-Budde 8291f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 8301f0e21a0SMarc Kleine-Budde return 0; 8311f0e21a0SMarc Kleine-Budde 8321f0e21a0SMarc Kleine-Budde /* Configure GPIOs: 8331f0e21a0SMarc Kleine-Budde * - PIN0: GPIO Input 8341f0e21a0SMarc Kleine-Budde * - PIN1: GPIO Input 8351f0e21a0SMarc Kleine-Budde */ 836eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_IOCON_PM1 | MCP251XFD_REG_IOCON_PM0 | 837eb79a267SMarc Kleine-Budde MCP251XFD_REG_IOCON_TRIS1 | MCP251XFD_REG_IOCON_TRIS0; 838eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val); 8391f0e21a0SMarc Kleine-Budde } 8401f0e21a0SMarc Kleine-Budde 8411f0e21a0SMarc Kleine-Budde static int 842eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_fifo_init_one(const struct mcp251xfd_priv *priv, 843eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring) 8441f0e21a0SMarc Kleine-Budde { 8451f0e21a0SMarc Kleine-Budde u32 fifo_con; 8461f0e21a0SMarc Kleine-Budde 8471f0e21a0SMarc Kleine-Budde /* Enable RXOVIE on _all_ RX FIFOs, not just the last one. 8481f0e21a0SMarc Kleine-Budde * 8491f0e21a0SMarc Kleine-Budde * FIFOs hit by a RX MAB overflow and RXOVIE enabled will 8501f0e21a0SMarc Kleine-Budde * generate a RXOVIF, use this to properly detect RX MAB 8511f0e21a0SMarc Kleine-Budde * overflows. 8521f0e21a0SMarc Kleine-Budde */ 853eb79a267SMarc Kleine-Budde fifo_con = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK, 8541f0e21a0SMarc Kleine-Budde ring->obj_num - 1) | 855eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_RXTSEN | 856eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_RXOVIE | 857eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TFNRFNIE; 8581f0e21a0SMarc Kleine-Budde 8591f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) 860eb79a267SMarc Kleine-Budde fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 861eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_64); 8621f0e21a0SMarc Kleine-Budde else 863eb79a267SMarc Kleine-Budde fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 864eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_8); 8651f0e21a0SMarc Kleine-Budde 8661f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, 867eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON(ring->fifo_nr), fifo_con); 8681f0e21a0SMarc Kleine-Budde } 8691f0e21a0SMarc Kleine-Budde 8701f0e21a0SMarc Kleine-Budde static int 871eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_filter_init_one(const struct mcp251xfd_priv *priv, 872eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring) 8731f0e21a0SMarc Kleine-Budde { 8741f0e21a0SMarc Kleine-Budde u32 fltcon; 8751f0e21a0SMarc Kleine-Budde 876eb79a267SMarc Kleine-Budde fltcon = MCP251XFD_REG_FLTCON_FLTEN(ring->nr) | 877eb79a267SMarc Kleine-Budde MCP251XFD_REG_FLTCON_FBP(ring->nr, ring->fifo_nr); 8781f0e21a0SMarc Kleine-Budde 8791f0e21a0SMarc Kleine-Budde return regmap_update_bits(priv->map_reg, 880eb79a267SMarc Kleine-Budde MCP251XFD_REG_FLTCON(ring->nr >> 2), 881eb79a267SMarc Kleine-Budde MCP251XFD_REG_FLTCON_FLT_MASK(ring->nr), 8821f0e21a0SMarc Kleine-Budde fltcon); 8831f0e21a0SMarc Kleine-Budde } 8841f0e21a0SMarc Kleine-Budde 885eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv) 8861f0e21a0SMarc Kleine-Budde { 887eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 888eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *rx_ring; 8891f0e21a0SMarc Kleine-Budde u32 val; 8901f0e21a0SMarc Kleine-Budde int err, n; 8911f0e21a0SMarc Kleine-Budde 8921f0e21a0SMarc Kleine-Budde /* TEF */ 893eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_TEFCON_FSIZE_MASK, 8941f0e21a0SMarc Kleine-Budde tx_ring->obj_num - 1) | 895eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFTSEN | 896eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFOVIE | 897eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFNEIE; 8981f0e21a0SMarc Kleine-Budde 899eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_TEFCON, val); 9001f0e21a0SMarc Kleine-Budde if (err) 9011f0e21a0SMarc Kleine-Budde return err; 9021f0e21a0SMarc Kleine-Budde 9031f0e21a0SMarc Kleine-Budde /* FIFO 1 - TX */ 904eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK, 9051f0e21a0SMarc Kleine-Budde tx_ring->obj_num - 1) | 906eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXEN | 907eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXATIE; 9081f0e21a0SMarc Kleine-Budde 9091f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) 910eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 911eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_64); 9121f0e21a0SMarc Kleine-Budde else 913eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 914eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_8); 9151f0e21a0SMarc Kleine-Budde 9161f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) 917eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK, 918eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXAT_ONE_SHOT); 9191f0e21a0SMarc Kleine-Budde else 920eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK, 921eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXAT_UNLIMITED); 9221f0e21a0SMarc Kleine-Budde 9231f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, 924eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO), 9251f0e21a0SMarc Kleine-Budde val); 9261f0e21a0SMarc Kleine-Budde if (err) 9271f0e21a0SMarc Kleine-Budde return err; 9281f0e21a0SMarc Kleine-Budde 9291f0e21a0SMarc Kleine-Budde /* RX FIFOs */ 930eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, n) { 931eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_fifo_init_one(priv, rx_ring); 9321f0e21a0SMarc Kleine-Budde if (err) 9331f0e21a0SMarc Kleine-Budde return err; 9341f0e21a0SMarc Kleine-Budde 935eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_filter_init_one(priv, rx_ring); 9361f0e21a0SMarc Kleine-Budde if (err) 9371f0e21a0SMarc Kleine-Budde return err; 9381f0e21a0SMarc Kleine-Budde } 9391f0e21a0SMarc Kleine-Budde 9401f0e21a0SMarc Kleine-Budde return 0; 9411f0e21a0SMarc Kleine-Budde } 9421f0e21a0SMarc Kleine-Budde 943eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_ecc_init(struct mcp251xfd_priv *priv) 9441f0e21a0SMarc Kleine-Budde { 945eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 9461f0e21a0SMarc Kleine-Budde void *ram; 9471f0e21a0SMarc Kleine-Budde u32 val = 0; 9481f0e21a0SMarc Kleine-Budde int err; 9491f0e21a0SMarc Kleine-Budde 9501f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 9511f0e21a0SMarc Kleine-Budde 952eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_ECC) 953eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_ECCCON_ECCEN; 9541f0e21a0SMarc Kleine-Budde 955eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, 956eb79a267SMarc Kleine-Budde MCP251XFD_REG_ECCCON_ECCEN, val); 9571f0e21a0SMarc Kleine-Budde if (err) 9581f0e21a0SMarc Kleine-Budde return err; 9591f0e21a0SMarc Kleine-Budde 960eb79a267SMarc Kleine-Budde ram = kzalloc(MCP251XFD_RAM_SIZE, GFP_KERNEL); 9611f0e21a0SMarc Kleine-Budde if (!ram) 9621f0e21a0SMarc Kleine-Budde return -ENOMEM; 9631f0e21a0SMarc Kleine-Budde 964eb79a267SMarc Kleine-Budde err = regmap_raw_write(priv->map_reg, MCP251XFD_RAM_START, ram, 965eb79a267SMarc Kleine-Budde MCP251XFD_RAM_SIZE); 9661f0e21a0SMarc Kleine-Budde kfree(ram); 9671f0e21a0SMarc Kleine-Budde 9681f0e21a0SMarc Kleine-Budde return err; 9691f0e21a0SMarc Kleine-Budde } 9701f0e21a0SMarc Kleine-Budde 971eb79a267SMarc Kleine-Budde static inline void mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv *priv) 9721f0e21a0SMarc Kleine-Budde { 973eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 9741f0e21a0SMarc Kleine-Budde 9751f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 9761f0e21a0SMarc Kleine-Budde } 9771f0e21a0SMarc Kleine-Budde 978eb79a267SMarc Kleine-Budde static u8 mcp251xfd_get_normal_mode(const struct mcp251xfd_priv *priv) 9791f0e21a0SMarc Kleine-Budde { 9801f0e21a0SMarc Kleine-Budde u8 mode; 9811f0e21a0SMarc Kleine-Budde 982ee42bedcSManivannan Sadhasivam 983ee42bedcSManivannan Sadhasivam if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) 984ee42bedcSManivannan Sadhasivam mode = MCP251XFD_REG_CON_MODE_INT_LOOPBACK; 985ee42bedcSManivannan Sadhasivam else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 986eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_LISTENONLY; 9871f0e21a0SMarc Kleine-Budde else if (priv->can.ctrlmode & CAN_CTRLMODE_FD) 988eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_MIXED; 9891f0e21a0SMarc Kleine-Budde else 990eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_CAN2_0; 9911f0e21a0SMarc Kleine-Budde 9921f0e21a0SMarc Kleine-Budde return mode; 9931f0e21a0SMarc Kleine-Budde } 9941f0e21a0SMarc Kleine-Budde 9951f0e21a0SMarc Kleine-Budde static int 996eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv, 9971f0e21a0SMarc Kleine-Budde bool nowait) 9981f0e21a0SMarc Kleine-Budde { 9991f0e21a0SMarc Kleine-Budde u8 mode; 10001f0e21a0SMarc Kleine-Budde 1001eb79a267SMarc Kleine-Budde mode = mcp251xfd_get_normal_mode(priv); 10021f0e21a0SMarc Kleine-Budde 1003eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode, nowait); 10041f0e21a0SMarc Kleine-Budde } 10051f0e21a0SMarc Kleine-Budde 10061f0e21a0SMarc Kleine-Budde static inline int 1007eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv) 10081f0e21a0SMarc Kleine-Budde { 1009eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_normal_mode(priv, false); 10101f0e21a0SMarc Kleine-Budde } 10111f0e21a0SMarc Kleine-Budde 10121f0e21a0SMarc Kleine-Budde static inline int 1013eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode_nowait(const struct mcp251xfd_priv *priv) 10141f0e21a0SMarc Kleine-Budde { 1015eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_normal_mode(priv, true); 10161f0e21a0SMarc Kleine-Budde } 10171f0e21a0SMarc Kleine-Budde 1018eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_enable(const struct mcp251xfd_priv *priv) 10191f0e21a0SMarc Kleine-Budde { 10201f0e21a0SMarc Kleine-Budde u32 val; 10211f0e21a0SMarc Kleine-Budde int err; 10221f0e21a0SMarc Kleine-Budde 1023eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_CRC_FERRIE | MCP251XFD_REG_CRC_CRCERRIE; 1024eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_CRC, val); 10251f0e21a0SMarc Kleine-Budde if (err) 10261f0e21a0SMarc Kleine-Budde return err; 10271f0e21a0SMarc Kleine-Budde 1028eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE; 1029eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, val, val); 10301f0e21a0SMarc Kleine-Budde if (err) 10311f0e21a0SMarc Kleine-Budde return err; 10321f0e21a0SMarc Kleine-Budde 1033eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_INT_CERRIE | 1034eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_SERRIE | 1035eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_RXOVIE | 1036eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_TXATIE | 1037eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_SPICRCIE | 1038eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_ECCIE | 1039eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_TEFIE | 1040eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_MODIE | 1041eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_RXIE; 10421f0e21a0SMarc Kleine-Budde 10431f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) 1044eb79a267SMarc Kleine-Budde val |= MCP251XFD_REG_INT_IVMIE; 10451f0e21a0SMarc Kleine-Budde 1046eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_INT, val); 10471f0e21a0SMarc Kleine-Budde } 10481f0e21a0SMarc Kleine-Budde 1049eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_disable(const struct mcp251xfd_priv *priv) 10501f0e21a0SMarc Kleine-Budde { 10511f0e21a0SMarc Kleine-Budde int err; 10521f0e21a0SMarc Kleine-Budde u32 mask; 10531f0e21a0SMarc Kleine-Budde 1054eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_INT, 0); 10551f0e21a0SMarc Kleine-Budde if (err) 10561f0e21a0SMarc Kleine-Budde return err; 10571f0e21a0SMarc Kleine-Budde 1058eb79a267SMarc Kleine-Budde mask = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE; 1059eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, 10601f0e21a0SMarc Kleine-Budde mask, 0x0); 10611f0e21a0SMarc Kleine-Budde if (err) 10621f0e21a0SMarc Kleine-Budde return err; 10631f0e21a0SMarc Kleine-Budde 1064eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_CRC, 0); 10651f0e21a0SMarc Kleine-Budde } 10661f0e21a0SMarc Kleine-Budde 1067eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_stop(struct mcp251xfd_priv *priv, 10681f0e21a0SMarc Kleine-Budde const enum can_state state) 10691f0e21a0SMarc Kleine-Budde { 10701f0e21a0SMarc Kleine-Budde priv->can.state = state; 10711f0e21a0SMarc Kleine-Budde 1072eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 1073eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_int_disable(priv); 1074eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 10751f0e21a0SMarc Kleine-Budde } 10761f0e21a0SMarc Kleine-Budde 1077eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv) 10781f0e21a0SMarc Kleine-Budde { 10791f0e21a0SMarc Kleine-Budde int err; 10801f0e21a0SMarc Kleine-Budde 1081eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset(priv); 10821f0e21a0SMarc Kleine-Budde if (err) 10831f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10841f0e21a0SMarc Kleine-Budde 1085eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_clock_init(priv); 10861f0e21a0SMarc Kleine-Budde if (err) 10871f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10881f0e21a0SMarc Kleine-Budde 1089eb79a267SMarc Kleine-Budde err = mcp251xfd_set_bittiming(priv); 10901f0e21a0SMarc Kleine-Budde if (err) 10911f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10921f0e21a0SMarc Kleine-Budde 1093eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_enable(priv); 10941f0e21a0SMarc Kleine-Budde if (err) 10951f0e21a0SMarc Kleine-Budde return err; 10961f0e21a0SMarc Kleine-Budde 1097eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_ecc_init(priv); 10981f0e21a0SMarc Kleine-Budde if (err) 10991f0e21a0SMarc Kleine-Budde goto out_chip_stop; 11001f0e21a0SMarc Kleine-Budde 1101eb79a267SMarc Kleine-Budde mcp251xfd_ring_init(priv); 11021f0e21a0SMarc Kleine-Budde 1103eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_fifo_init(priv); 11041f0e21a0SMarc Kleine-Budde if (err) 11051f0e21a0SMarc Kleine-Budde goto out_chip_stop; 11061f0e21a0SMarc Kleine-Budde 11071f0e21a0SMarc Kleine-Budde priv->can.state = CAN_STATE_ERROR_ACTIVE; 11081f0e21a0SMarc Kleine-Budde 1109eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_normal_mode(priv); 11101f0e21a0SMarc Kleine-Budde if (err) 11111f0e21a0SMarc Kleine-Budde goto out_chip_stop; 11121f0e21a0SMarc Kleine-Budde 11131f0e21a0SMarc Kleine-Budde return 0; 11141f0e21a0SMarc Kleine-Budde 11151f0e21a0SMarc Kleine-Budde out_chip_stop: 1116e0ab3dd5SMarc Kleine-Budde mcp251xfd_dump(priv); 1117eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 11181f0e21a0SMarc Kleine-Budde 11191f0e21a0SMarc Kleine-Budde return err; 11201f0e21a0SMarc Kleine-Budde } 11211f0e21a0SMarc Kleine-Budde 1122eb79a267SMarc Kleine-Budde static int mcp251xfd_set_mode(struct net_device *ndev, enum can_mode mode) 11231f0e21a0SMarc Kleine-Budde { 1124eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 11251f0e21a0SMarc Kleine-Budde int err; 11261f0e21a0SMarc Kleine-Budde 11271f0e21a0SMarc Kleine-Budde switch (mode) { 11281f0e21a0SMarc Kleine-Budde case CAN_MODE_START: 1129eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_start(priv); 11301f0e21a0SMarc Kleine-Budde if (err) 11311f0e21a0SMarc Kleine-Budde return err; 11321f0e21a0SMarc Kleine-Budde 1133eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_interrupts_enable(priv); 11341f0e21a0SMarc Kleine-Budde if (err) { 1135eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 11361f0e21a0SMarc Kleine-Budde return err; 11371f0e21a0SMarc Kleine-Budde } 11381f0e21a0SMarc Kleine-Budde 11391f0e21a0SMarc Kleine-Budde netif_wake_queue(ndev); 11401f0e21a0SMarc Kleine-Budde break; 11411f0e21a0SMarc Kleine-Budde 11421f0e21a0SMarc Kleine-Budde default: 11431f0e21a0SMarc Kleine-Budde return -EOPNOTSUPP; 11441f0e21a0SMarc Kleine-Budde } 11451f0e21a0SMarc Kleine-Budde 11461f0e21a0SMarc Kleine-Budde return 0; 11471f0e21a0SMarc Kleine-Budde } 11481f0e21a0SMarc Kleine-Budde 1149eb79a267SMarc Kleine-Budde static int __mcp251xfd_get_berr_counter(const struct net_device *ndev, 11501f0e21a0SMarc Kleine-Budde struct can_berr_counter *bec) 11511f0e21a0SMarc Kleine-Budde { 1152eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = netdev_priv(ndev); 11531f0e21a0SMarc Kleine-Budde u32 trec; 11541f0e21a0SMarc Kleine-Budde int err; 11551f0e21a0SMarc Kleine-Budde 1156eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec); 11571f0e21a0SMarc Kleine-Budde if (err) 11581f0e21a0SMarc Kleine-Budde return err; 11591f0e21a0SMarc Kleine-Budde 1160eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_TXBO) 11611f0e21a0SMarc Kleine-Budde bec->txerr = 256; 11621f0e21a0SMarc Kleine-Budde else 1163eb79a267SMarc Kleine-Budde bec->txerr = FIELD_GET(MCP251XFD_REG_TREC_TEC_MASK, trec); 1164eb79a267SMarc Kleine-Budde bec->rxerr = FIELD_GET(MCP251XFD_REG_TREC_REC_MASK, trec); 11651f0e21a0SMarc Kleine-Budde 11661f0e21a0SMarc Kleine-Budde return 0; 11671f0e21a0SMarc Kleine-Budde } 11681f0e21a0SMarc Kleine-Budde 1169eb79a267SMarc Kleine-Budde static int mcp251xfd_get_berr_counter(const struct net_device *ndev, 11701f0e21a0SMarc Kleine-Budde struct can_berr_counter *bec) 11711f0e21a0SMarc Kleine-Budde { 1172eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = netdev_priv(ndev); 11731f0e21a0SMarc Kleine-Budde 11741f0e21a0SMarc Kleine-Budde /* Avoid waking up the controller if the interface is down */ 11751f0e21a0SMarc Kleine-Budde if (!(ndev->flags & IFF_UP)) 11761f0e21a0SMarc Kleine-Budde return 0; 11771f0e21a0SMarc Kleine-Budde 11781f0e21a0SMarc Kleine-Budde /* The controller is powered down during Bus Off, use saved 11791f0e21a0SMarc Kleine-Budde * bec values. 11801f0e21a0SMarc Kleine-Budde */ 11811f0e21a0SMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) { 11821f0e21a0SMarc Kleine-Budde *bec = priv->bec; 11831f0e21a0SMarc Kleine-Budde return 0; 11841f0e21a0SMarc Kleine-Budde } 11851f0e21a0SMarc Kleine-Budde 1186eb79a267SMarc Kleine-Budde return __mcp251xfd_get_berr_counter(ndev, bec); 11871f0e21a0SMarc Kleine-Budde } 11881f0e21a0SMarc Kleine-Budde 1189eb79a267SMarc Kleine-Budde static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv) 11901f0e21a0SMarc Kleine-Budde { 11911f0e21a0SMarc Kleine-Budde u8 tef_tail_chip, tef_tail; 11921f0e21a0SMarc Kleine-Budde int err; 11931f0e21a0SMarc Kleine-Budde 1194eb79a267SMarc Kleine-Budde if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY)) 11951f0e21a0SMarc Kleine-Budde return 0; 11961f0e21a0SMarc Kleine-Budde 1197eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_tail_get_from_chip(priv, &tef_tail_chip); 11981f0e21a0SMarc Kleine-Budde if (err) 11991f0e21a0SMarc Kleine-Budde return err; 12001f0e21a0SMarc Kleine-Budde 1201eb79a267SMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 12021f0e21a0SMarc Kleine-Budde if (tef_tail_chip != tef_tail) { 12031f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 12041f0e21a0SMarc Kleine-Budde "TEF tail of chip (0x%02x) and ours (0x%08x) inconsistent.\n", 12051f0e21a0SMarc Kleine-Budde tef_tail_chip, tef_tail); 12061f0e21a0SMarc Kleine-Budde return -EILSEQ; 12071f0e21a0SMarc Kleine-Budde } 12081f0e21a0SMarc Kleine-Budde 12091f0e21a0SMarc Kleine-Budde return 0; 12101f0e21a0SMarc Kleine-Budde } 12111f0e21a0SMarc Kleine-Budde 12121f0e21a0SMarc Kleine-Budde static int 1213eb79a267SMarc Kleine-Budde mcp251xfd_check_rx_tail(const struct mcp251xfd_priv *priv, 1214eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring) 12151f0e21a0SMarc Kleine-Budde { 12161f0e21a0SMarc Kleine-Budde u8 rx_tail_chip, rx_tail; 12171f0e21a0SMarc Kleine-Budde int err; 12181f0e21a0SMarc Kleine-Budde 1219eb79a267SMarc Kleine-Budde if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY)) 12201f0e21a0SMarc Kleine-Budde return 0; 12211f0e21a0SMarc Kleine-Budde 1222eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_tail_get_from_chip(priv, ring, &rx_tail_chip); 12231f0e21a0SMarc Kleine-Budde if (err) 12241f0e21a0SMarc Kleine-Budde return err; 12251f0e21a0SMarc Kleine-Budde 1226eb79a267SMarc Kleine-Budde rx_tail = mcp251xfd_get_rx_tail(ring); 12271f0e21a0SMarc Kleine-Budde if (rx_tail_chip != rx_tail) { 12281f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 12291f0e21a0SMarc Kleine-Budde "RX tail of chip (%d) and ours (%d) inconsistent.\n", 12301f0e21a0SMarc Kleine-Budde rx_tail_chip, rx_tail); 12311f0e21a0SMarc Kleine-Budde return -EILSEQ; 12321f0e21a0SMarc Kleine-Budde } 12331f0e21a0SMarc Kleine-Budde 12341f0e21a0SMarc Kleine-Budde return 0; 12351f0e21a0SMarc Kleine-Budde } 12361f0e21a0SMarc Kleine-Budde 12371f0e21a0SMarc Kleine-Budde static int 1238eb79a267SMarc Kleine-Budde mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq) 12391f0e21a0SMarc Kleine-Budde { 1240eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 12411f0e21a0SMarc Kleine-Budde u32 tef_sta; 12421f0e21a0SMarc Kleine-Budde int err; 12431f0e21a0SMarc Kleine-Budde 1244eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta); 12451f0e21a0SMarc Kleine-Budde if (err) 12461f0e21a0SMarc Kleine-Budde return err; 12471f0e21a0SMarc Kleine-Budde 1248eb79a267SMarc Kleine-Budde if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) { 12491f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 12501f0e21a0SMarc Kleine-Budde "Transmit Event FIFO buffer overflow.\n"); 12511f0e21a0SMarc Kleine-Budde return -ENOBUFS; 12521f0e21a0SMarc Kleine-Budde } 12531f0e21a0SMarc Kleine-Budde 12541f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 1255f93486a7SMarc Kleine-Budde "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x).\n", 1256eb79a267SMarc Kleine-Budde tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ? 1257eb79a267SMarc Kleine-Budde "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ? 12581f0e21a0SMarc Kleine-Budde "not empty" : "empty", 1259dada6a6cSMarc Kleine-Budde seq, priv->tef->tail, priv->tef->head, tx_ring->head); 12601f0e21a0SMarc Kleine-Budde 12611f0e21a0SMarc Kleine-Budde /* The Sequence Number in the TEF doesn't match our tef_tail. */ 12621f0e21a0SMarc Kleine-Budde return -EAGAIN; 12631f0e21a0SMarc Kleine-Budde } 12641f0e21a0SMarc Kleine-Budde 12651f0e21a0SMarc Kleine-Budde static int 1266eb79a267SMarc Kleine-Budde mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, 12670084e298SMarc Kleine-Budde const struct mcp251xfd_hw_tef_obj *hw_tef_obj, 12680084e298SMarc Kleine-Budde unsigned int *frame_len_ptr) 12691f0e21a0SMarc Kleine-Budde { 12701f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 12715f02a49cSMarc Kleine-Budde struct sk_buff *skb; 12725f02a49cSMarc Kleine-Budde u32 seq, seq_masked, tef_tail_masked, tef_tail; 12731f0e21a0SMarc Kleine-Budde 1274eb79a267SMarc Kleine-Budde seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, 12751f0e21a0SMarc Kleine-Budde hw_tef_obj->flags); 12761f0e21a0SMarc Kleine-Budde 12771f0e21a0SMarc Kleine-Budde /* Use the MCP2517FD mask on the MCP2518FD, too. We only 12781f0e21a0SMarc Kleine-Budde * compare 7 bits, this should be enough to detect 12791f0e21a0SMarc Kleine-Budde * net-yet-completed, i.e. old TEF objects. 12801f0e21a0SMarc Kleine-Budde */ 12811f0e21a0SMarc Kleine-Budde seq_masked = seq & 1282eb79a267SMarc Kleine-Budde field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 1283dada6a6cSMarc Kleine-Budde tef_tail_masked = priv->tef->tail & 1284eb79a267SMarc Kleine-Budde field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 12851f0e21a0SMarc Kleine-Budde if (seq_masked != tef_tail_masked) 1286eb79a267SMarc Kleine-Budde return mcp251xfd_handle_tefif_recover(priv, seq); 12871f0e21a0SMarc Kleine-Budde 12885f02a49cSMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 12895f02a49cSMarc Kleine-Budde skb = priv->can.echo_skb[tef_tail]; 12905f02a49cSMarc Kleine-Budde if (skb) 12915f02a49cSMarc Kleine-Budde mcp251xfd_skb_set_timestamp(priv, skb, hw_tef_obj->ts); 12921f0e21a0SMarc Kleine-Budde stats->tx_bytes += 12931f0e21a0SMarc Kleine-Budde can_rx_offload_get_echo_skb(&priv->offload, 12940084e298SMarc Kleine-Budde tef_tail, hw_tef_obj->ts, 12950084e298SMarc Kleine-Budde frame_len_ptr); 12961f0e21a0SMarc Kleine-Budde stats->tx_packets++; 1297dada6a6cSMarc Kleine-Budde priv->tef->tail++; 12981f0e21a0SMarc Kleine-Budde 129968c0c1c7SMarc Kleine-Budde return 0; 13001f0e21a0SMarc Kleine-Budde } 13011f0e21a0SMarc Kleine-Budde 1302eb79a267SMarc Kleine-Budde static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv) 13031f0e21a0SMarc Kleine-Budde { 1304eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 13051f0e21a0SMarc Kleine-Budde unsigned int new_head; 13061f0e21a0SMarc Kleine-Budde u8 chip_tx_tail; 13071f0e21a0SMarc Kleine-Budde int err; 13081f0e21a0SMarc Kleine-Budde 1309eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail); 13101f0e21a0SMarc Kleine-Budde if (err) 13111f0e21a0SMarc Kleine-Budde return err; 13121f0e21a0SMarc Kleine-Budde 13131f0e21a0SMarc Kleine-Budde /* chip_tx_tail, is the next TX-Object send by the HW. 13141f0e21a0SMarc Kleine-Budde * The new TEF head must be >= the old head, ... 13151f0e21a0SMarc Kleine-Budde */ 1316dada6a6cSMarc Kleine-Budde new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail; 1317dada6a6cSMarc Kleine-Budde if (new_head <= priv->tef->head) 13181f0e21a0SMarc Kleine-Budde new_head += tx_ring->obj_num; 13191f0e21a0SMarc Kleine-Budde 13201f0e21a0SMarc Kleine-Budde /* ... but it cannot exceed the TX head. */ 1321dada6a6cSMarc Kleine-Budde priv->tef->head = min(new_head, tx_ring->head); 13221f0e21a0SMarc Kleine-Budde 1323eb79a267SMarc Kleine-Budde return mcp251xfd_check_tef_tail(priv); 13241f0e21a0SMarc Kleine-Budde } 13251f0e21a0SMarc Kleine-Budde 13261f0e21a0SMarc Kleine-Budde static inline int 1327eb79a267SMarc Kleine-Budde mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv, 1328eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_tef_obj *hw_tef_obj, 13291f0e21a0SMarc Kleine-Budde const u8 offset, const u8 len) 13301f0e21a0SMarc Kleine-Budde { 1331eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 1332cdc4c698SSu Yanjun const int val_bytes = regmap_get_val_bytes(priv->map_rx); 13331f0e21a0SMarc Kleine-Budde 1334eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 13351f0e21a0SMarc Kleine-Budde (offset > tx_ring->obj_num || 13361f0e21a0SMarc Kleine-Budde len > tx_ring->obj_num || 13371f0e21a0SMarc Kleine-Budde offset + len > tx_ring->obj_num)) { 13381f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 13391f0e21a0SMarc Kleine-Budde "Trying to read to many TEF objects (max=%d, offset=%d, len=%d).\n", 13401f0e21a0SMarc Kleine-Budde tx_ring->obj_num, offset, len); 13411f0e21a0SMarc Kleine-Budde return -ERANGE; 13421f0e21a0SMarc Kleine-Budde } 13431f0e21a0SMarc Kleine-Budde 13441f0e21a0SMarc Kleine-Budde return regmap_bulk_read(priv->map_rx, 1345eb79a267SMarc Kleine-Budde mcp251xfd_get_tef_obj_addr(offset), 13461f0e21a0SMarc Kleine-Budde hw_tef_obj, 1347cdc4c698SSu Yanjun sizeof(*hw_tef_obj) / val_bytes * len); 13481f0e21a0SMarc Kleine-Budde } 13491f0e21a0SMarc Kleine-Budde 1350eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) 13511f0e21a0SMarc Kleine-Budde { 1352eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX]; 13530084e298SMarc Kleine-Budde unsigned int total_frame_len = 0; 13541f0e21a0SMarc Kleine-Budde u8 tef_tail, len, l; 13551f0e21a0SMarc Kleine-Budde int err, i; 13561f0e21a0SMarc Kleine-Budde 1357eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_ring_update(priv); 13581f0e21a0SMarc Kleine-Budde if (err) 13591f0e21a0SMarc Kleine-Budde return err; 13601f0e21a0SMarc Kleine-Budde 1361eb79a267SMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 1362eb79a267SMarc Kleine-Budde len = mcp251xfd_get_tef_len(priv); 1363eb79a267SMarc Kleine-Budde l = mcp251xfd_get_tef_linear_len(priv); 1364eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l); 13651f0e21a0SMarc Kleine-Budde if (err) 13661f0e21a0SMarc Kleine-Budde return err; 13671f0e21a0SMarc Kleine-Budde 13681f0e21a0SMarc Kleine-Budde if (l < len) { 1369eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l); 13701f0e21a0SMarc Kleine-Budde if (err) 13711f0e21a0SMarc Kleine-Budde return err; 13721f0e21a0SMarc Kleine-Budde } 13731f0e21a0SMarc Kleine-Budde 13741f0e21a0SMarc Kleine-Budde for (i = 0; i < len; i++) { 13750084e298SMarc Kleine-Budde unsigned int frame_len = 0; 13760084e298SMarc Kleine-Budde 13770084e298SMarc Kleine-Budde err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len); 13781f0e21a0SMarc Kleine-Budde /* -EAGAIN means the Sequence Number in the TEF 13791f0e21a0SMarc Kleine-Budde * doesn't match our tef_tail. This can happen if we 13801f0e21a0SMarc Kleine-Budde * read the TEF objects too early. Leave loop let the 13811f0e21a0SMarc Kleine-Budde * interrupt handler call us again. 13821f0e21a0SMarc Kleine-Budde */ 13831f0e21a0SMarc Kleine-Budde if (err == -EAGAIN) 13841f0e21a0SMarc Kleine-Budde goto out_netif_wake_queue; 13851f0e21a0SMarc Kleine-Budde if (err) 13861f0e21a0SMarc Kleine-Budde return err; 13870084e298SMarc Kleine-Budde 13880084e298SMarc Kleine-Budde total_frame_len += frame_len; 13891f0e21a0SMarc Kleine-Budde } 13901f0e21a0SMarc Kleine-Budde 13911f0e21a0SMarc Kleine-Budde out_netif_wake_queue: 139268c0c1c7SMarc Kleine-Budde len = i; /* number of handled goods TEFs */ 139368c0c1c7SMarc Kleine-Budde if (len) { 139468c0c1c7SMarc Kleine-Budde struct mcp251xfd_tef_ring *ring = priv->tef; 139568c0c1c7SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 1396eb94b74cSMarc Kleine-Budde int offset; 139768c0c1c7SMarc Kleine-Budde 139868c0c1c7SMarc Kleine-Budde /* Increment the TEF FIFO tail pointer 'len' times in 139968c0c1c7SMarc Kleine-Budde * a single SPI message. 14006086f02aSMarc Kleine-Budde * 14016086f02aSMarc Kleine-Budde * Note: 1402eb94b74cSMarc Kleine-Budde * Calculate offset, so that the SPI transfer ends on 1403eb94b74cSMarc Kleine-Budde * the last message of the uinc_xfer array, which has 1404eb94b74cSMarc Kleine-Budde * "cs_change == 0", to properly deactivate the chip 1405eb94b74cSMarc Kleine-Budde * select. 140668c0c1c7SMarc Kleine-Budde */ 1407eb94b74cSMarc Kleine-Budde offset = ARRAY_SIZE(ring->uinc_xfer) - len; 1408eb94b74cSMarc Kleine-Budde err = spi_sync_transfer(priv->spi, 1409eb94b74cSMarc Kleine-Budde ring->uinc_xfer + offset, len); 141068c0c1c7SMarc Kleine-Budde if (err) 141168c0c1c7SMarc Kleine-Budde return err; 141268c0c1c7SMarc Kleine-Budde 14136086f02aSMarc Kleine-Budde tx_ring->tail += len; 14140084e298SMarc Kleine-Budde netdev_completed_queue(priv->ndev, len, total_frame_len); 14156086f02aSMarc Kleine-Budde 141668c0c1c7SMarc Kleine-Budde err = mcp251xfd_check_tef_tail(priv); 141768c0c1c7SMarc Kleine-Budde if (err) 141868c0c1c7SMarc Kleine-Budde return err; 141968c0c1c7SMarc Kleine-Budde } 142068c0c1c7SMarc Kleine-Budde 1421eb79a267SMarc Kleine-Budde mcp251xfd_ecc_tefif_successful(priv); 14221f0e21a0SMarc Kleine-Budde 1423eb79a267SMarc Kleine-Budde if (mcp251xfd_get_tx_free(priv->tx)) { 14241f0e21a0SMarc Kleine-Budde /* Make sure that anybody stopping the queue after 14251f0e21a0SMarc Kleine-Budde * this sees the new tx_ring->tail. 14261f0e21a0SMarc Kleine-Budde */ 14271f0e21a0SMarc Kleine-Budde smp_mb(); 14281f0e21a0SMarc Kleine-Budde netif_wake_queue(priv->ndev); 14291f0e21a0SMarc Kleine-Budde } 14301f0e21a0SMarc Kleine-Budde 14311f0e21a0SMarc Kleine-Budde return 0; 14321f0e21a0SMarc Kleine-Budde } 14331f0e21a0SMarc Kleine-Budde 14341f0e21a0SMarc Kleine-Budde static int 1435eb79a267SMarc Kleine-Budde mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv, 1436eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring) 14371f0e21a0SMarc Kleine-Budde { 14381f0e21a0SMarc Kleine-Budde u32 new_head; 14391f0e21a0SMarc Kleine-Budde u8 chip_rx_head; 14401f0e21a0SMarc Kleine-Budde int err; 14411f0e21a0SMarc Kleine-Budde 1442eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head); 14431f0e21a0SMarc Kleine-Budde if (err) 14441f0e21a0SMarc Kleine-Budde return err; 14451f0e21a0SMarc Kleine-Budde 14461f0e21a0SMarc Kleine-Budde /* chip_rx_head, is the next RX-Object filled by the HW. 14471f0e21a0SMarc Kleine-Budde * The new RX head must be >= the old head. 14481f0e21a0SMarc Kleine-Budde */ 14491f0e21a0SMarc Kleine-Budde new_head = round_down(ring->head, ring->obj_num) + chip_rx_head; 14501f0e21a0SMarc Kleine-Budde if (new_head <= ring->head) 14511f0e21a0SMarc Kleine-Budde new_head += ring->obj_num; 14521f0e21a0SMarc Kleine-Budde 14531f0e21a0SMarc Kleine-Budde ring->head = new_head; 14541f0e21a0SMarc Kleine-Budde 1455eb79a267SMarc Kleine-Budde return mcp251xfd_check_rx_tail(priv, ring); 14561f0e21a0SMarc Kleine-Budde } 14571f0e21a0SMarc Kleine-Budde 14581f0e21a0SMarc Kleine-Budde static void 14595f02a49cSMarc Kleine-Budde mcp251xfd_hw_rx_obj_to_skb(struct mcp251xfd_priv *priv, 1460eb79a267SMarc Kleine-Budde const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj, 14611f0e21a0SMarc Kleine-Budde struct sk_buff *skb) 14621f0e21a0SMarc Kleine-Budde { 14631f0e21a0SMarc Kleine-Budde struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 146486f1e3b1SMarc Kleine-Budde u8 dlc; 14651f0e21a0SMarc Kleine-Budde 1466eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_IDE) { 14671f0e21a0SMarc Kleine-Budde u32 sid, eid; 14681f0e21a0SMarc Kleine-Budde 1469eb79a267SMarc Kleine-Budde eid = FIELD_GET(MCP251XFD_OBJ_ID_EID_MASK, hw_rx_obj->id); 1470eb79a267SMarc Kleine-Budde sid = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, hw_rx_obj->id); 14711f0e21a0SMarc Kleine-Budde 14721f0e21a0SMarc Kleine-Budde cfd->can_id = CAN_EFF_FLAG | 1473eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_FRAME_EFF_EID_MASK, eid) | 1474eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_FRAME_EFF_SID_MASK, sid); 14751f0e21a0SMarc Kleine-Budde } else { 1476eb79a267SMarc Kleine-Budde cfd->can_id = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, 14771f0e21a0SMarc Kleine-Budde hw_rx_obj->id); 14781f0e21a0SMarc Kleine-Budde } 14791f0e21a0SMarc Kleine-Budde 148049ffacbcSMarc Kleine-Budde dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC_MASK, hw_rx_obj->flags); 148186f1e3b1SMarc Kleine-Budde 14821f0e21a0SMarc Kleine-Budde /* CANFD */ 1483eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) { 14841f0e21a0SMarc Kleine-Budde 1485eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_ESI) 14861f0e21a0SMarc Kleine-Budde cfd->flags |= CANFD_ESI; 14871f0e21a0SMarc Kleine-Budde 1488eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_BRS) 14891f0e21a0SMarc Kleine-Budde cfd->flags |= CANFD_BRS; 14901f0e21a0SMarc Kleine-Budde 14913ab4ce0dSOliver Hartkopp cfd->len = can_fd_dlc2len(dlc); 14921f0e21a0SMarc Kleine-Budde } else { 1493eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR) 14941f0e21a0SMarc Kleine-Budde cfd->can_id |= CAN_RTR_FLAG; 14951f0e21a0SMarc Kleine-Budde 149686f1e3b1SMarc Kleine-Budde can_frame_set_cc_len((struct can_frame *)cfd, dlc, 149786f1e3b1SMarc Kleine-Budde priv->can.ctrlmode); 14981f0e21a0SMarc Kleine-Budde } 14991f0e21a0SMarc Kleine-Budde 1500e20b85c7SMarc Kleine-Budde if (!(hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR)) 15011f0e21a0SMarc Kleine-Budde memcpy(cfd->data, hw_rx_obj->data, cfd->len); 15025f02a49cSMarc Kleine-Budde 15035f02a49cSMarc Kleine-Budde mcp251xfd_skb_set_timestamp(priv, skb, hw_rx_obj->ts); 15041f0e21a0SMarc Kleine-Budde } 15051f0e21a0SMarc Kleine-Budde 15061f0e21a0SMarc Kleine-Budde static int 1507eb79a267SMarc Kleine-Budde mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv, 1508eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring, 1509eb79a267SMarc Kleine-Budde const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj) 15101f0e21a0SMarc Kleine-Budde { 15111f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 15121f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 15131f0e21a0SMarc Kleine-Budde struct canfd_frame *cfd; 15141f0e21a0SMarc Kleine-Budde int err; 15151f0e21a0SMarc Kleine-Budde 1516eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) 15171f0e21a0SMarc Kleine-Budde skb = alloc_canfd_skb(priv->ndev, &cfd); 15181f0e21a0SMarc Kleine-Budde else 15191f0e21a0SMarc Kleine-Budde skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cfd); 15201f0e21a0SMarc Kleine-Budde 1521ca4c6ebeSQinglang Miao if (!skb) { 15221f0e21a0SMarc Kleine-Budde stats->rx_dropped++; 15231f0e21a0SMarc Kleine-Budde return 0; 15241f0e21a0SMarc Kleine-Budde } 15251f0e21a0SMarc Kleine-Budde 1526eb79a267SMarc Kleine-Budde mcp251xfd_hw_rx_obj_to_skb(priv, hw_rx_obj, skb); 15271f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, hw_rx_obj->ts); 15281f0e21a0SMarc Kleine-Budde if (err) 15291f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 15301f0e21a0SMarc Kleine-Budde 15311f652bb6SUrsula Maplehurst return 0; 15321f0e21a0SMarc Kleine-Budde } 15331f0e21a0SMarc Kleine-Budde 15341f0e21a0SMarc Kleine-Budde static inline int 1535eb79a267SMarc Kleine-Budde mcp251xfd_rx_obj_read(const struct mcp251xfd_priv *priv, 1536eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring, 1537eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj, 15381f0e21a0SMarc Kleine-Budde const u8 offset, const u8 len) 15391f0e21a0SMarc Kleine-Budde { 1540cdc4c698SSu Yanjun const int val_bytes = regmap_get_val_bytes(priv->map_rx); 15411f0e21a0SMarc Kleine-Budde int err; 15421f0e21a0SMarc Kleine-Budde 15431f0e21a0SMarc Kleine-Budde err = regmap_bulk_read(priv->map_rx, 1544eb79a267SMarc Kleine-Budde mcp251xfd_get_rx_obj_addr(ring, offset), 15451f0e21a0SMarc Kleine-Budde hw_rx_obj, 1546cdc4c698SSu Yanjun len * ring->obj_size / val_bytes); 15471f0e21a0SMarc Kleine-Budde 15481f0e21a0SMarc Kleine-Budde return err; 15491f0e21a0SMarc Kleine-Budde } 15501f0e21a0SMarc Kleine-Budde 15511f0e21a0SMarc Kleine-Budde static int 1552eb79a267SMarc Kleine-Budde mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv, 1553eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring) 15541f0e21a0SMarc Kleine-Budde { 1555eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj = ring->obj; 15561f0e21a0SMarc Kleine-Budde u8 rx_tail, len; 15571f0e21a0SMarc Kleine-Budde int err, i; 15581f0e21a0SMarc Kleine-Budde 1559eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_ring_update(priv, ring); 15601f0e21a0SMarc Kleine-Budde if (err) 15611f0e21a0SMarc Kleine-Budde return err; 15621f0e21a0SMarc Kleine-Budde 1563eb79a267SMarc Kleine-Budde while ((len = mcp251xfd_get_rx_linear_len(ring))) { 1564eb94b74cSMarc Kleine-Budde int offset; 15651f652bb6SUrsula Maplehurst 1566eb79a267SMarc Kleine-Budde rx_tail = mcp251xfd_get_rx_tail(ring); 15671f0e21a0SMarc Kleine-Budde 1568eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj, 15691f0e21a0SMarc Kleine-Budde rx_tail, len); 15701f0e21a0SMarc Kleine-Budde if (err) 15711f0e21a0SMarc Kleine-Budde return err; 15721f0e21a0SMarc Kleine-Budde 15731f0e21a0SMarc Kleine-Budde for (i = 0; i < len; i++) { 1574eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_rxif_one(priv, ring, 15751f0e21a0SMarc Kleine-Budde (void *)hw_rx_obj + 15761f0e21a0SMarc Kleine-Budde i * ring->obj_size); 15771f0e21a0SMarc Kleine-Budde if (err) 15781f0e21a0SMarc Kleine-Budde return err; 15791f0e21a0SMarc Kleine-Budde } 15801f652bb6SUrsula Maplehurst 15811f652bb6SUrsula Maplehurst /* Increment the RX FIFO tail pointer 'len' times in a 15821f652bb6SUrsula Maplehurst * single SPI message. 15832fbb397fSMarc Kleine-Budde * 15842fbb397fSMarc Kleine-Budde * Note: 1585eb94b74cSMarc Kleine-Budde * Calculate offset, so that the SPI transfer ends on 1586eb94b74cSMarc Kleine-Budde * the last message of the uinc_xfer array, which has 1587eb94b74cSMarc Kleine-Budde * "cs_change == 0", to properly deactivate the chip 1588eb94b74cSMarc Kleine-Budde * select. 15891f652bb6SUrsula Maplehurst */ 1590eb94b74cSMarc Kleine-Budde offset = ARRAY_SIZE(ring->uinc_xfer) - len; 1591eb94b74cSMarc Kleine-Budde err = spi_sync_transfer(priv->spi, 1592eb94b74cSMarc Kleine-Budde ring->uinc_xfer + offset, len); 15931f652bb6SUrsula Maplehurst if (err) 15941f652bb6SUrsula Maplehurst return err; 15952fbb397fSMarc Kleine-Budde 15962fbb397fSMarc Kleine-Budde ring->tail += len; 15971f0e21a0SMarc Kleine-Budde } 15981f0e21a0SMarc Kleine-Budde 15991f0e21a0SMarc Kleine-Budde return 0; 16001f0e21a0SMarc Kleine-Budde } 16011f0e21a0SMarc Kleine-Budde 1602eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv) 16031f0e21a0SMarc Kleine-Budde { 1604eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring; 16051f0e21a0SMarc Kleine-Budde int err, n; 16061f0e21a0SMarc Kleine-Budde 1607eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, ring, n) { 1608eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_rxif_ring(priv, ring); 16091f0e21a0SMarc Kleine-Budde if (err) 16101f0e21a0SMarc Kleine-Budde return err; 16111f0e21a0SMarc Kleine-Budde } 16121f0e21a0SMarc Kleine-Budde 16131f0e21a0SMarc Kleine-Budde return 0; 16141f0e21a0SMarc Kleine-Budde } 16151f0e21a0SMarc Kleine-Budde 16161f0e21a0SMarc Kleine-Budde static struct sk_buff * 16175f02a49cSMarc Kleine-Budde mcp251xfd_alloc_can_err_skb(struct mcp251xfd_priv *priv, 16181f0e21a0SMarc Kleine-Budde struct can_frame **cf, u32 *timestamp) 16191f0e21a0SMarc Kleine-Budde { 16205f02a49cSMarc Kleine-Budde struct sk_buff *skb; 16211f0e21a0SMarc Kleine-Budde int err; 16221f0e21a0SMarc Kleine-Budde 1623eb79a267SMarc Kleine-Budde err = mcp251xfd_get_timestamp(priv, timestamp); 16241f0e21a0SMarc Kleine-Budde if (err) 16251f0e21a0SMarc Kleine-Budde return NULL; 16261f0e21a0SMarc Kleine-Budde 16275f02a49cSMarc Kleine-Budde skb = alloc_can_err_skb(priv->ndev, cf); 16285f02a49cSMarc Kleine-Budde if (skb) 16295f02a49cSMarc Kleine-Budde mcp251xfd_skb_set_timestamp(priv, skb, *timestamp); 16305f02a49cSMarc Kleine-Budde 16315f02a49cSMarc Kleine-Budde return skb; 16321f0e21a0SMarc Kleine-Budde } 16331f0e21a0SMarc Kleine-Budde 1634eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_rxovif(struct mcp251xfd_priv *priv) 16351f0e21a0SMarc Kleine-Budde { 16361f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 1637eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring; 16381f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 16391f0e21a0SMarc Kleine-Budde struct can_frame *cf; 16401f0e21a0SMarc Kleine-Budde u32 timestamp, rxovif; 16411f0e21a0SMarc Kleine-Budde int err, i; 16421f0e21a0SMarc Kleine-Budde 16431f0e21a0SMarc Kleine-Budde stats->rx_over_errors++; 16441f0e21a0SMarc Kleine-Budde stats->rx_errors++; 16451f0e21a0SMarc Kleine-Budde 1646eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_RXOVIF, &rxovif); 16471f0e21a0SMarc Kleine-Budde if (err) 16481f0e21a0SMarc Kleine-Budde return err; 16491f0e21a0SMarc Kleine-Budde 1650eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, ring, i) { 16511f0e21a0SMarc Kleine-Budde if (!(rxovif & BIT(ring->fifo_nr))) 16521f0e21a0SMarc Kleine-Budde continue; 16531f0e21a0SMarc Kleine-Budde 16541f0e21a0SMarc Kleine-Budde /* If SERRIF is active, there was a RX MAB overflow. */ 1655eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_SERRIF) { 16561f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 16571f0e21a0SMarc Kleine-Budde "RX-%d: MAB overflow detected.\n", 16581f0e21a0SMarc Kleine-Budde ring->nr); 16591f0e21a0SMarc Kleine-Budde } else { 16601f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 16611f0e21a0SMarc Kleine-Budde "RX-%d: FIFO overflow.\n", ring->nr); 16621f0e21a0SMarc Kleine-Budde } 16631f0e21a0SMarc Kleine-Budde 16641f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 1665eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA(ring->fifo_nr), 1666eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA_RXOVIF, 16671f0e21a0SMarc Kleine-Budde 0x0); 16681f0e21a0SMarc Kleine-Budde if (err) 16691f0e21a0SMarc Kleine-Budde return err; 16701f0e21a0SMarc Kleine-Budde } 16711f0e21a0SMarc Kleine-Budde 1672eb79a267SMarc Kleine-Budde skb = mcp251xfd_alloc_can_err_skb(priv, &cf, ×tamp); 16731f0e21a0SMarc Kleine-Budde if (!skb) 16741f0e21a0SMarc Kleine-Budde return 0; 16751f0e21a0SMarc Kleine-Budde 16761f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_CRTL; 16771f0e21a0SMarc Kleine-Budde cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; 16781f0e21a0SMarc Kleine-Budde 16791f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 16801f0e21a0SMarc Kleine-Budde if (err) 16811f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 16821f0e21a0SMarc Kleine-Budde 16831f0e21a0SMarc Kleine-Budde return 0; 16841f0e21a0SMarc Kleine-Budde } 16851f0e21a0SMarc Kleine-Budde 1686eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_txatif(struct mcp251xfd_priv *priv) 16871f0e21a0SMarc Kleine-Budde { 16881f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", __func__); 16891f0e21a0SMarc Kleine-Budde 16901f0e21a0SMarc Kleine-Budde return 0; 16911f0e21a0SMarc Kleine-Budde } 16921f0e21a0SMarc Kleine-Budde 1693eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_ivmif(struct mcp251xfd_priv *priv) 16941f0e21a0SMarc Kleine-Budde { 16951f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 16961f0e21a0SMarc Kleine-Budde u32 bdiag1, timestamp; 16971f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 16981f0e21a0SMarc Kleine-Budde struct can_frame *cf = NULL; 16991f0e21a0SMarc Kleine-Budde int err; 17001f0e21a0SMarc Kleine-Budde 1701eb79a267SMarc Kleine-Budde err = mcp251xfd_get_timestamp(priv, ×tamp); 17021f0e21a0SMarc Kleine-Budde if (err) 17031f0e21a0SMarc Kleine-Budde return err; 17041f0e21a0SMarc Kleine-Budde 1705eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_BDIAG1, &bdiag1); 17061f0e21a0SMarc Kleine-Budde if (err) 17071f0e21a0SMarc Kleine-Budde return err; 17081f0e21a0SMarc Kleine-Budde 17091f0e21a0SMarc Kleine-Budde /* Write 0s to clear error bits, don't write 1s to non active 17101f0e21a0SMarc Kleine-Budde * bits, as they will be set. 17111f0e21a0SMarc Kleine-Budde */ 1712eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_BDIAG1, 0x0); 17131f0e21a0SMarc Kleine-Budde if (err) 17141f0e21a0SMarc Kleine-Budde return err; 17151f0e21a0SMarc Kleine-Budde 17161f0e21a0SMarc Kleine-Budde priv->can.can_stats.bus_error++; 17171f0e21a0SMarc Kleine-Budde 17181f0e21a0SMarc Kleine-Budde skb = alloc_can_err_skb(priv->ndev, &cf); 17191f0e21a0SMarc Kleine-Budde if (cf) 17201f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; 17211f0e21a0SMarc Kleine-Budde 17221f0e21a0SMarc Kleine-Budde /* Controller misconfiguration */ 1723eb79a267SMarc Kleine-Budde if (WARN_ON(bdiag1 & MCP251XFD_REG_BDIAG1_DLCMM)) 17241f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 17251f0e21a0SMarc Kleine-Budde "recv'd DLC is larger than PLSIZE of FIFO element."); 17261f0e21a0SMarc Kleine-Budde 17271f0e21a0SMarc Kleine-Budde /* RX errors */ 1728eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DCRCERR | 1729eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NCRCERR)) { 17301f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "CRC error\n"); 17311f0e21a0SMarc Kleine-Budde 17321f0e21a0SMarc Kleine-Budde stats->rx_errors++; 17331f0e21a0SMarc Kleine-Budde if (cf) 17341f0e21a0SMarc Kleine-Budde cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; 17351f0e21a0SMarc Kleine-Budde } 1736eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DSTUFERR | 1737eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NSTUFERR)) { 17381f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Stuff error\n"); 17391f0e21a0SMarc Kleine-Budde 17401f0e21a0SMarc Kleine-Budde stats->rx_errors++; 17411f0e21a0SMarc Kleine-Budde if (cf) 17421f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_STUFF; 17431f0e21a0SMarc Kleine-Budde } 1744eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DFORMERR | 1745eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NFORMERR)) { 17461f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Format error\n"); 17471f0e21a0SMarc Kleine-Budde 17481f0e21a0SMarc Kleine-Budde stats->rx_errors++; 17491f0e21a0SMarc Kleine-Budde if (cf) 17501f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_FORM; 17511f0e21a0SMarc Kleine-Budde } 17521f0e21a0SMarc Kleine-Budde 17531f0e21a0SMarc Kleine-Budde /* TX errors */ 1754eb79a267SMarc Kleine-Budde if (bdiag1 & MCP251XFD_REG_BDIAG1_NACKERR) { 17551f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "NACK error\n"); 17561f0e21a0SMarc Kleine-Budde 17571f0e21a0SMarc Kleine-Budde stats->tx_errors++; 17581f0e21a0SMarc Kleine-Budde if (cf) { 17591f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_ACK; 17601f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX; 17611f0e21a0SMarc Kleine-Budde } 17621f0e21a0SMarc Kleine-Budde } 1763eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT1ERR | 1764eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NBIT1ERR)) { 17651f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit1 error\n"); 17661f0e21a0SMarc Kleine-Budde 17671f0e21a0SMarc Kleine-Budde stats->tx_errors++; 17681f0e21a0SMarc Kleine-Budde if (cf) 17691f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT1; 17701f0e21a0SMarc Kleine-Budde } 1771eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT0ERR | 1772eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NBIT0ERR)) { 17731f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit0 error\n"); 17741f0e21a0SMarc Kleine-Budde 17751f0e21a0SMarc Kleine-Budde stats->tx_errors++; 17761f0e21a0SMarc Kleine-Budde if (cf) 17771f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT0; 17781f0e21a0SMarc Kleine-Budde } 17791f0e21a0SMarc Kleine-Budde 17801f0e21a0SMarc Kleine-Budde if (!cf) 17811f0e21a0SMarc Kleine-Budde return 0; 17821f0e21a0SMarc Kleine-Budde 17835f02a49cSMarc Kleine-Budde mcp251xfd_skb_set_timestamp(priv, skb, timestamp); 17841f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 17851f0e21a0SMarc Kleine-Budde if (err) 17861f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 17871f0e21a0SMarc Kleine-Budde 17881f0e21a0SMarc Kleine-Budde return 0; 17891f0e21a0SMarc Kleine-Budde } 17901f0e21a0SMarc Kleine-Budde 1791eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv) 17921f0e21a0SMarc Kleine-Budde { 17931f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 17941f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 17951f0e21a0SMarc Kleine-Budde struct can_frame *cf = NULL; 17961f0e21a0SMarc Kleine-Budde enum can_state new_state, rx_state, tx_state; 17971f0e21a0SMarc Kleine-Budde u32 trec, timestamp; 17981f0e21a0SMarc Kleine-Budde int err; 17991f0e21a0SMarc Kleine-Budde 1800eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec); 18011f0e21a0SMarc Kleine-Budde if (err) 18021f0e21a0SMarc Kleine-Budde return err; 18031f0e21a0SMarc Kleine-Budde 1804eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_TXBO) 18051f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_BUS_OFF; 1806eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_TXBP) 18071f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_PASSIVE; 1808eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_TXWARN) 18091f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_WARNING; 18101f0e21a0SMarc Kleine-Budde else 18111f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_ACTIVE; 18121f0e21a0SMarc Kleine-Budde 1813eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_RXBP) 18141f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_PASSIVE; 1815eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_RXWARN) 18161f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_WARNING; 18171f0e21a0SMarc Kleine-Budde else 18181f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_ACTIVE; 18191f0e21a0SMarc Kleine-Budde 18201f0e21a0SMarc Kleine-Budde new_state = max(tx_state, rx_state); 18211f0e21a0SMarc Kleine-Budde if (new_state == priv->can.state) 18221f0e21a0SMarc Kleine-Budde return 0; 18231f0e21a0SMarc Kleine-Budde 18241f0e21a0SMarc Kleine-Budde /* The skb allocation might fail, but can_change_state() 18251f0e21a0SMarc Kleine-Budde * handles cf == NULL. 18261f0e21a0SMarc Kleine-Budde */ 1827eb79a267SMarc Kleine-Budde skb = mcp251xfd_alloc_can_err_skb(priv, &cf, ×tamp); 18281f0e21a0SMarc Kleine-Budde can_change_state(priv->ndev, cf, tx_state, rx_state); 18291f0e21a0SMarc Kleine-Budde 18301f0e21a0SMarc Kleine-Budde if (new_state == CAN_STATE_BUS_OFF) { 18311f0e21a0SMarc Kleine-Budde /* As we're going to switch off the chip now, let's 18321f0e21a0SMarc Kleine-Budde * save the error counters and return them to 18331f0e21a0SMarc Kleine-Budde * userspace, if do_get_berr_counter() is called while 18341f0e21a0SMarc Kleine-Budde * the chip is in Bus Off. 18351f0e21a0SMarc Kleine-Budde */ 1836eb79a267SMarc Kleine-Budde err = __mcp251xfd_get_berr_counter(priv->ndev, &priv->bec); 18371f0e21a0SMarc Kleine-Budde if (err) 18381f0e21a0SMarc Kleine-Budde return err; 18391f0e21a0SMarc Kleine-Budde 1840eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_BUS_OFF); 18411f0e21a0SMarc Kleine-Budde can_bus_off(priv->ndev); 18421f0e21a0SMarc Kleine-Budde } 18431f0e21a0SMarc Kleine-Budde 18441f0e21a0SMarc Kleine-Budde if (!skb) 18451f0e21a0SMarc Kleine-Budde return 0; 18461f0e21a0SMarc Kleine-Budde 18471f0e21a0SMarc Kleine-Budde if (new_state != CAN_STATE_BUS_OFF) { 18481f0e21a0SMarc Kleine-Budde struct can_berr_counter bec; 18491f0e21a0SMarc Kleine-Budde 1850eb79a267SMarc Kleine-Budde err = mcp251xfd_get_berr_counter(priv->ndev, &bec); 18511f0e21a0SMarc Kleine-Budde if (err) 18521f0e21a0SMarc Kleine-Budde return err; 18531f0e21a0SMarc Kleine-Budde cf->data[6] = bec.txerr; 18541f0e21a0SMarc Kleine-Budde cf->data[7] = bec.rxerr; 18551f0e21a0SMarc Kleine-Budde } 18561f0e21a0SMarc Kleine-Budde 18571f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 18581f0e21a0SMarc Kleine-Budde if (err) 18591f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 18601f0e21a0SMarc Kleine-Budde 18611f0e21a0SMarc Kleine-Budde return 0; 18621f0e21a0SMarc Kleine-Budde } 18631f0e21a0SMarc Kleine-Budde 18641f0e21a0SMarc Kleine-Budde static int 1865eb79a267SMarc Kleine-Budde mcp251xfd_handle_modif(const struct mcp251xfd_priv *priv, bool *set_normal_mode) 18661f0e21a0SMarc Kleine-Budde { 1867eb79a267SMarc Kleine-Budde const u8 mode_reference = mcp251xfd_get_normal_mode(priv); 18681f0e21a0SMarc Kleine-Budde u8 mode; 18691f0e21a0SMarc Kleine-Budde int err; 18701f0e21a0SMarc Kleine-Budde 1871eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_get_mode(priv, &mode); 18721f0e21a0SMarc Kleine-Budde if (err) 18731f0e21a0SMarc Kleine-Budde return err; 18741f0e21a0SMarc Kleine-Budde 18751f0e21a0SMarc Kleine-Budde if (mode == mode_reference) { 18761f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 18771f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1878eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 18791f0e21a0SMarc Kleine-Budde return 0; 18801f0e21a0SMarc Kleine-Budde } 18811f0e21a0SMarc Kleine-Budde 18821f0e21a0SMarc Kleine-Budde /* According to MCP2517FD errata DS80000792B 1., during a TX 18831f0e21a0SMarc Kleine-Budde * MAB underflow, the controller will transition to Restricted 18841f0e21a0SMarc Kleine-Budde * Operation Mode or Listen Only Mode (depending on SERR2LOM). 18851f0e21a0SMarc Kleine-Budde * 18861f0e21a0SMarc Kleine-Budde * However this is not always the case. If SERR2LOM is 18871f0e21a0SMarc Kleine-Budde * configured for Restricted Operation Mode (SERR2LOM not set) 18881f0e21a0SMarc Kleine-Budde * the MCP2517FD will sometimes transition to Listen Only Mode 18891f0e21a0SMarc Kleine-Budde * first. When polling this bit we see that it will transition 18901f0e21a0SMarc Kleine-Budde * to Restricted Operation Mode shortly after. 18911f0e21a0SMarc Kleine-Budde */ 1892eb79a267SMarc Kleine-Budde if ((priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN) && 1893eb79a267SMarc Kleine-Budde (mode == MCP251XFD_REG_CON_MODE_RESTRICTED || 1894eb79a267SMarc Kleine-Budde mode == MCP251XFD_REG_CON_MODE_LISTENONLY)) 18951f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 18961f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1897eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 18981f0e21a0SMarc Kleine-Budde else 18991f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 19001f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1901eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 19021f0e21a0SMarc Kleine-Budde 1903f93486a7SMarc Kleine-Budde /* After the application requests Normal mode, the controller 19041f0e21a0SMarc Kleine-Budde * will automatically attempt to retransmit the message that 19051f0e21a0SMarc Kleine-Budde * caused the TX MAB underflow. 19061f0e21a0SMarc Kleine-Budde * 19071f0e21a0SMarc Kleine-Budde * However, if there is an ECC error in the TX-RAM, we first 19081f0e21a0SMarc Kleine-Budde * have to reload the tx-object before requesting Normal 1909eb79a267SMarc Kleine-Budde * mode. This is done later in mcp251xfd_handle_eccif(). 19101f0e21a0SMarc Kleine-Budde */ 1911eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF) { 19121f0e21a0SMarc Kleine-Budde *set_normal_mode = true; 19131f0e21a0SMarc Kleine-Budde return 0; 19141f0e21a0SMarc Kleine-Budde } 19151f0e21a0SMarc Kleine-Budde 1916eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode_nowait(priv); 19171f0e21a0SMarc Kleine-Budde } 19181f0e21a0SMarc Kleine-Budde 1919eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_serrif(struct mcp251xfd_priv *priv) 19201f0e21a0SMarc Kleine-Budde { 1921eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 19221f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 19231f0e21a0SMarc Kleine-Budde bool handled = false; 19241f0e21a0SMarc Kleine-Budde 19251f0e21a0SMarc Kleine-Budde /* TX MAB underflow 19261f0e21a0SMarc Kleine-Budde * 19271f0e21a0SMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a TX MAB 19281f0e21a0SMarc Kleine-Budde * underflow is indicated by SERRIF and MODIF. 19291f0e21a0SMarc Kleine-Budde * 19301f0e21a0SMarc Kleine-Budde * In addition to the effects mentioned in the Errata, there 19311f0e21a0SMarc Kleine-Budde * are Bus Errors due to the aborted CAN frame, so a IVMIF 19321f0e21a0SMarc Kleine-Budde * will be seen as well. 19331f0e21a0SMarc Kleine-Budde * 19341f0e21a0SMarc Kleine-Budde * Sometimes there is an ECC error in the TX-RAM, which leads 19351f0e21a0SMarc Kleine-Budde * to a TX MAB underflow. 19361f0e21a0SMarc Kleine-Budde * 19371f0e21a0SMarc Kleine-Budde * However, probably due to a race condition, there is no 19381f0e21a0SMarc Kleine-Budde * associated MODIF pending. 19391f0e21a0SMarc Kleine-Budde * 19401f0e21a0SMarc Kleine-Budde * Further, there are situations, where the SERRIF is caused 19411f0e21a0SMarc Kleine-Budde * by an ECC error in the TX-RAM, but not even the ECCIF is 19421f0e21a0SMarc Kleine-Budde * set. This only seems to happen _after_ the first occurrence 19431f0e21a0SMarc Kleine-Budde * of a ECCIF (which is tracked in ecc->cnt). 19441f0e21a0SMarc Kleine-Budde * 19451f0e21a0SMarc Kleine-Budde * Treat all as a known system errors.. 19461f0e21a0SMarc Kleine-Budde */ 1947eb79a267SMarc Kleine-Budde if ((priv->regs_status.intf & MCP251XFD_REG_INT_MODIF && 1948eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_IVMIF) || 1949eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF || 19501f0e21a0SMarc Kleine-Budde ecc->cnt) { 19511f0e21a0SMarc Kleine-Budde const char *msg; 19521f0e21a0SMarc Kleine-Budde 1953eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF || 19541f0e21a0SMarc Kleine-Budde ecc->cnt) 19551f0e21a0SMarc Kleine-Budde msg = "TX MAB underflow due to ECC error detected."; 19561f0e21a0SMarc Kleine-Budde else 19571f0e21a0SMarc Kleine-Budde msg = "TX MAB underflow detected."; 19581f0e21a0SMarc Kleine-Budde 1959eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN) 19601f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "%s\n", msg); 19611f0e21a0SMarc Kleine-Budde else 19621f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", msg); 19631f0e21a0SMarc Kleine-Budde 19641f0e21a0SMarc Kleine-Budde stats->tx_aborted_errors++; 19651f0e21a0SMarc Kleine-Budde stats->tx_errors++; 19661f0e21a0SMarc Kleine-Budde handled = true; 19671f0e21a0SMarc Kleine-Budde } 19681f0e21a0SMarc Kleine-Budde 19691f0e21a0SMarc Kleine-Budde /* RX MAB overflow 19701f0e21a0SMarc Kleine-Budde * 19711f0e21a0SMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a RX MAB 19721f0e21a0SMarc Kleine-Budde * overflow is indicated by SERRIF. 19731f0e21a0SMarc Kleine-Budde * 19741f0e21a0SMarc Kleine-Budde * In addition to the effects mentioned in the Errata, (most 19751f0e21a0SMarc Kleine-Budde * of the times) a RXOVIF is raised, if the FIFO that is being 19761f0e21a0SMarc Kleine-Budde * received into has the RXOVIE activated (and we have enabled 19771f0e21a0SMarc Kleine-Budde * RXOVIE on all FIFOs). 19781f0e21a0SMarc Kleine-Budde * 19791f0e21a0SMarc Kleine-Budde * Sometimes there is no RXOVIF just a RXIF is pending. 19801f0e21a0SMarc Kleine-Budde * 19811f0e21a0SMarc Kleine-Budde * Treat all as a known system errors.. 19821f0e21a0SMarc Kleine-Budde */ 1983eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_RXOVIF || 1984eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_RXIF) { 19851f0e21a0SMarc Kleine-Budde stats->rx_dropped++; 19861f0e21a0SMarc Kleine-Budde handled = true; 19871f0e21a0SMarc Kleine-Budde } 19881f0e21a0SMarc Kleine-Budde 19891f0e21a0SMarc Kleine-Budde if (!handled) 19901f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 19911f0e21a0SMarc Kleine-Budde "Unhandled System Error Interrupt (intf=0x%08x)!\n", 19921f0e21a0SMarc Kleine-Budde priv->regs_status.intf); 19931f0e21a0SMarc Kleine-Budde 19941f0e21a0SMarc Kleine-Budde return 0; 19951f0e21a0SMarc Kleine-Budde } 19961f0e21a0SMarc Kleine-Budde 19971f0e21a0SMarc Kleine-Budde static int 1998eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif_recover(struct mcp251xfd_priv *priv, u8 nr) 19991f0e21a0SMarc Kleine-Budde { 2000eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 2001eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 2002eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 20031f0e21a0SMarc Kleine-Budde u8 chip_tx_tail, tx_tail, offset; 20041f0e21a0SMarc Kleine-Budde u16 addr; 20051f0e21a0SMarc Kleine-Budde int err; 20061f0e21a0SMarc Kleine-Budde 2007eb79a267SMarc Kleine-Budde addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc->ecc_stat); 20081f0e21a0SMarc Kleine-Budde 2009eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail); 20101f0e21a0SMarc Kleine-Budde if (err) 20111f0e21a0SMarc Kleine-Budde return err; 20121f0e21a0SMarc Kleine-Budde 2013eb79a267SMarc Kleine-Budde tx_tail = mcp251xfd_get_tx_tail(tx_ring); 20141f0e21a0SMarc Kleine-Budde offset = (nr - chip_tx_tail) & (tx_ring->obj_num - 1); 20151f0e21a0SMarc Kleine-Budde 20161f0e21a0SMarc Kleine-Budde /* Bail out if one of the following is met: 20171f0e21a0SMarc Kleine-Budde * - tx_tail information is inconsistent 20181f0e21a0SMarc Kleine-Budde * - for mcp2517fd: offset not 0 20191f0e21a0SMarc Kleine-Budde * - for mcp2518fd: offset not 0 or 1 20201f0e21a0SMarc Kleine-Budde */ 20211f0e21a0SMarc Kleine-Budde if (chip_tx_tail != tx_tail || 2022eb79a267SMarc Kleine-Budde !(offset == 0 || (offset == 1 && mcp251xfd_is_2518(priv)))) { 20231f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 20241f0e21a0SMarc Kleine-Budde "ECC Error information inconsistent (addr=0x%04x, nr=%d, tx_tail=0x%08x(%d), chip_tx_tail=%d, offset=%d).\n", 20251f0e21a0SMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, chip_tx_tail, 20261f0e21a0SMarc Kleine-Budde offset); 20271f0e21a0SMarc Kleine-Budde return -EINVAL; 20281f0e21a0SMarc Kleine-Budde } 20291f0e21a0SMarc Kleine-Budde 20301f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 20311f0e21a0SMarc Kleine-Budde "Recovering %s ECC Error at address 0x%04x (in TX-RAM, tx_obj=%d, tx_tail=0x%08x(%d), offset=%d).\n", 2032eb79a267SMarc Kleine-Budde ecc->ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF ? 20331f0e21a0SMarc Kleine-Budde "Single" : "Double", 20341f0e21a0SMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, offset); 20351f0e21a0SMarc Kleine-Budde 20361f0e21a0SMarc Kleine-Budde /* reload tx_obj into controller RAM ... */ 20371f0e21a0SMarc Kleine-Budde tx_obj = &tx_ring->obj[nr]; 20381f0e21a0SMarc Kleine-Budde err = spi_sync_transfer(priv->spi, tx_obj->xfer, 1); 20391f0e21a0SMarc Kleine-Budde if (err) 20401f0e21a0SMarc Kleine-Budde return err; 20411f0e21a0SMarc Kleine-Budde 20421f0e21a0SMarc Kleine-Budde /* ... and trigger retransmit */ 2043eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode(priv); 20441f0e21a0SMarc Kleine-Budde } 20451f0e21a0SMarc Kleine-Budde 20461f0e21a0SMarc Kleine-Budde static int 2047eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif(struct mcp251xfd_priv *priv, bool set_normal_mode) 20481f0e21a0SMarc Kleine-Budde { 2049eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 20501f0e21a0SMarc Kleine-Budde const char *msg; 20511f0e21a0SMarc Kleine-Budde bool in_tx_ram; 20521f0e21a0SMarc Kleine-Budde u32 ecc_stat; 20531f0e21a0SMarc Kleine-Budde u16 addr; 20541f0e21a0SMarc Kleine-Budde u8 nr; 20551f0e21a0SMarc Kleine-Budde int err; 20561f0e21a0SMarc Kleine-Budde 2057eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_ECCSTAT, &ecc_stat); 20581f0e21a0SMarc Kleine-Budde if (err) 20591f0e21a0SMarc Kleine-Budde return err; 20601f0e21a0SMarc Kleine-Budde 2061eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCSTAT, 2062eb79a267SMarc Kleine-Budde MCP251XFD_REG_ECCSTAT_IF_MASK, ~ecc_stat); 20631f0e21a0SMarc Kleine-Budde if (err) 20641f0e21a0SMarc Kleine-Budde return err; 20651f0e21a0SMarc Kleine-Budde 20661f0e21a0SMarc Kleine-Budde /* Check if ECC error occurred in TX-RAM */ 2067eb79a267SMarc Kleine-Budde addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc_stat); 2068eb79a267SMarc Kleine-Budde err = mcp251xfd_get_tx_nr_by_addr(priv->tx, &nr, addr); 20691f0e21a0SMarc Kleine-Budde if (!err) 20701f0e21a0SMarc Kleine-Budde in_tx_ram = true; 20711f0e21a0SMarc Kleine-Budde else if (err == -ENOENT) 20721f0e21a0SMarc Kleine-Budde in_tx_ram = false; 20731f0e21a0SMarc Kleine-Budde else 20741f0e21a0SMarc Kleine-Budde return err; 20751f0e21a0SMarc Kleine-Budde 20761f0e21a0SMarc Kleine-Budde /* Errata Reference: 20771f0e21a0SMarc Kleine-Budde * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 2. 20781f0e21a0SMarc Kleine-Budde * 20791f0e21a0SMarc Kleine-Budde * ECC single error correction does not work in all cases: 20801f0e21a0SMarc Kleine-Budde * 20811f0e21a0SMarc Kleine-Budde * Fix/Work Around: 20821f0e21a0SMarc Kleine-Budde * Enable single error correction and double error detection 20831f0e21a0SMarc Kleine-Budde * interrupts by setting SECIE and DEDIE. Handle SECIF as a 20841f0e21a0SMarc Kleine-Budde * detection interrupt and do not rely on the error 20851f0e21a0SMarc Kleine-Budde * correction. Instead, handle both interrupts as a 20861f0e21a0SMarc Kleine-Budde * notification that the RAM word at ERRADDR was corrupted. 20871f0e21a0SMarc Kleine-Budde */ 2088eb79a267SMarc Kleine-Budde if (ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF) 20891f0e21a0SMarc Kleine-Budde msg = "Single ECC Error detected at address"; 2090eb79a267SMarc Kleine-Budde else if (ecc_stat & MCP251XFD_REG_ECCSTAT_DEDIF) 20911f0e21a0SMarc Kleine-Budde msg = "Double ECC Error detected at address"; 20921f0e21a0SMarc Kleine-Budde else 20931f0e21a0SMarc Kleine-Budde return -EINVAL; 20941f0e21a0SMarc Kleine-Budde 20951f0e21a0SMarc Kleine-Budde if (!in_tx_ram) { 20961f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 20971f0e21a0SMarc Kleine-Budde 20981f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, "%s 0x%04x.\n", msg, addr); 20991f0e21a0SMarc Kleine-Budde } else { 21001f0e21a0SMarc Kleine-Budde /* Re-occurring error? */ 21011f0e21a0SMarc Kleine-Budde if (ecc->ecc_stat == ecc_stat) { 21021f0e21a0SMarc Kleine-Budde ecc->cnt++; 21031f0e21a0SMarc Kleine-Budde } else { 21041f0e21a0SMarc Kleine-Budde ecc->ecc_stat = ecc_stat; 21051f0e21a0SMarc Kleine-Budde ecc->cnt = 1; 21061f0e21a0SMarc Kleine-Budde } 21071f0e21a0SMarc Kleine-Budde 21081f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 21091f0e21a0SMarc Kleine-Budde "%s 0x%04x (in TX-RAM, tx_obj=%d), occurred %d time%s.\n", 21101f0e21a0SMarc Kleine-Budde msg, addr, nr, ecc->cnt, ecc->cnt > 1 ? "s" : ""); 21111f0e21a0SMarc Kleine-Budde 2112eb79a267SMarc Kleine-Budde if (ecc->cnt >= MCP251XFD_ECC_CNT_MAX) 2113eb79a267SMarc Kleine-Budde return mcp251xfd_handle_eccif_recover(priv, nr); 21141f0e21a0SMarc Kleine-Budde } 21151f0e21a0SMarc Kleine-Budde 21161f0e21a0SMarc Kleine-Budde if (set_normal_mode) 2117eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode_nowait(priv); 21181f0e21a0SMarc Kleine-Budde 21191f0e21a0SMarc Kleine-Budde return 0; 21201f0e21a0SMarc Kleine-Budde } 21211f0e21a0SMarc Kleine-Budde 2122eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_spicrcif(struct mcp251xfd_priv *priv) 21231f0e21a0SMarc Kleine-Budde { 21241f0e21a0SMarc Kleine-Budde int err; 21251f0e21a0SMarc Kleine-Budde u32 crc; 21261f0e21a0SMarc Kleine-Budde 2127eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_CRC, &crc); 21281f0e21a0SMarc Kleine-Budde if (err) 21291f0e21a0SMarc Kleine-Budde return err; 21301f0e21a0SMarc Kleine-Budde 2131eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CRC, 2132eb79a267SMarc Kleine-Budde MCP251XFD_REG_CRC_IF_MASK, 21331f0e21a0SMarc Kleine-Budde ~crc); 21341f0e21a0SMarc Kleine-Budde if (err) 21351f0e21a0SMarc Kleine-Budde return err; 21361f0e21a0SMarc Kleine-Budde 2137eb79a267SMarc Kleine-Budde if (crc & MCP251XFD_REG_CRC_FERRIF) 21381f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, "CRC write command format error.\n"); 2139eb79a267SMarc Kleine-Budde else if (crc & MCP251XFD_REG_CRC_CRCERRIF) 21401f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, 21411f0e21a0SMarc Kleine-Budde "CRC write error detected. CRC=0x%04lx.\n", 2142eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_CRC_MASK, crc)); 21431f0e21a0SMarc Kleine-Budde 21441f0e21a0SMarc Kleine-Budde return 0; 21451f0e21a0SMarc Kleine-Budde } 21461f0e21a0SMarc Kleine-Budde 2147eb79a267SMarc Kleine-Budde #define mcp251xfd_handle(priv, irq, ...) \ 21481f0e21a0SMarc Kleine-Budde ({ \ 2149eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *_priv = (priv); \ 21501f0e21a0SMarc Kleine-Budde int err; \ 21511f0e21a0SMarc Kleine-Budde \ 2152eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_##irq(_priv, ## __VA_ARGS__); \ 21531f0e21a0SMarc Kleine-Budde if (err) \ 21541f0e21a0SMarc Kleine-Budde netdev_err(_priv->ndev, \ 2155eb79a267SMarc Kleine-Budde "IRQ handler mcp251xfd_handle_%s() returned %d.\n", \ 21561f0e21a0SMarc Kleine-Budde __stringify(irq), err); \ 21571f0e21a0SMarc Kleine-Budde err; \ 21581f0e21a0SMarc Kleine-Budde }) 21591f0e21a0SMarc Kleine-Budde 2160eb79a267SMarc Kleine-Budde static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) 21611f0e21a0SMarc Kleine-Budde { 2162eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = dev_id; 2163cdc4c698SSu Yanjun const int val_bytes = regmap_get_val_bytes(priv->map_reg); 21641f0e21a0SMarc Kleine-Budde irqreturn_t handled = IRQ_NONE; 21651f0e21a0SMarc Kleine-Budde int err; 21661f0e21a0SMarc Kleine-Budde 21671f0e21a0SMarc Kleine-Budde if (priv->rx_int) 21681f0e21a0SMarc Kleine-Budde do { 21691f0e21a0SMarc Kleine-Budde int rx_pending; 21701f0e21a0SMarc Kleine-Budde 21711f0e21a0SMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 21721f0e21a0SMarc Kleine-Budde if (!rx_pending) 21731f0e21a0SMarc Kleine-Budde break; 21741f0e21a0SMarc Kleine-Budde 2175eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxif); 21761f0e21a0SMarc Kleine-Budde if (err) 21771f0e21a0SMarc Kleine-Budde goto out_fail; 21781f0e21a0SMarc Kleine-Budde 21791f0e21a0SMarc Kleine-Budde handled = IRQ_HANDLED; 21801f0e21a0SMarc Kleine-Budde } while (1); 21811f0e21a0SMarc Kleine-Budde 21821f0e21a0SMarc Kleine-Budde do { 21831f0e21a0SMarc Kleine-Budde u32 intf_pending, intf_pending_clearable; 21841f0e21a0SMarc Kleine-Budde bool set_normal_mode = false; 21851f0e21a0SMarc Kleine-Budde 2186eb79a267SMarc Kleine-Budde err = regmap_bulk_read(priv->map_reg, MCP251XFD_REG_INT, 21871f0e21a0SMarc Kleine-Budde &priv->regs_status, 21881f0e21a0SMarc Kleine-Budde sizeof(priv->regs_status) / 2189cdc4c698SSu Yanjun val_bytes); 21901f0e21a0SMarc Kleine-Budde if (err) 21911f0e21a0SMarc Kleine-Budde goto out_fail; 21921f0e21a0SMarc Kleine-Budde 2193eb79a267SMarc Kleine-Budde intf_pending = FIELD_GET(MCP251XFD_REG_INT_IF_MASK, 21941f0e21a0SMarc Kleine-Budde priv->regs_status.intf) & 2195eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_INT_IE_MASK, 21961f0e21a0SMarc Kleine-Budde priv->regs_status.intf); 21971f0e21a0SMarc Kleine-Budde 21981f0e21a0SMarc Kleine-Budde if (!(intf_pending)) 21991f0e21a0SMarc Kleine-Budde return handled; 22001f0e21a0SMarc Kleine-Budde 22011f0e21a0SMarc Kleine-Budde /* Some interrupts must be ACKed in the 2202eb79a267SMarc Kleine-Budde * MCP251XFD_REG_INT register. 22031f0e21a0SMarc Kleine-Budde * - First ACK then handle, to avoid lost-IRQ race 22041f0e21a0SMarc Kleine-Budde * condition on fast re-occurring interrupts. 22051f0e21a0SMarc Kleine-Budde * - Write "0" to clear active IRQs, "1" to all other, 22061f0e21a0SMarc Kleine-Budde * to avoid r/m/w race condition on the 2207eb79a267SMarc Kleine-Budde * MCP251XFD_REG_INT register. 22081f0e21a0SMarc Kleine-Budde */ 22091f0e21a0SMarc Kleine-Budde intf_pending_clearable = intf_pending & 2210eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_IF_CLEARABLE_MASK; 22111f0e21a0SMarc Kleine-Budde if (intf_pending_clearable) { 22121f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 2213eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT, 2214eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_IF_MASK, 22151f0e21a0SMarc Kleine-Budde ~intf_pending_clearable); 22161f0e21a0SMarc Kleine-Budde if (err) 22171f0e21a0SMarc Kleine-Budde goto out_fail; 22181f0e21a0SMarc Kleine-Budde } 22191f0e21a0SMarc Kleine-Budde 2220eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_MODIF) { 2221eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, modif, &set_normal_mode); 22221f0e21a0SMarc Kleine-Budde if (err) 22231f0e21a0SMarc Kleine-Budde goto out_fail; 22241f0e21a0SMarc Kleine-Budde } 22251f0e21a0SMarc Kleine-Budde 2226eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_RXIF) { 2227eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxif); 22281f0e21a0SMarc Kleine-Budde if (err) 22291f0e21a0SMarc Kleine-Budde goto out_fail; 22301f0e21a0SMarc Kleine-Budde } 22311f0e21a0SMarc Kleine-Budde 2232eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_TEFIF) { 2233eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, tefif); 22341f0e21a0SMarc Kleine-Budde if (err) 22351f0e21a0SMarc Kleine-Budde goto out_fail; 22361f0e21a0SMarc Kleine-Budde } 22371f0e21a0SMarc Kleine-Budde 2238eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_RXOVIF) { 2239eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxovif); 22401f0e21a0SMarc Kleine-Budde if (err) 22411f0e21a0SMarc Kleine-Budde goto out_fail; 22421f0e21a0SMarc Kleine-Budde } 22431f0e21a0SMarc Kleine-Budde 2244eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_TXATIF) { 2245eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, txatif); 22461f0e21a0SMarc Kleine-Budde if (err) 22471f0e21a0SMarc Kleine-Budde goto out_fail; 22481f0e21a0SMarc Kleine-Budde } 22491f0e21a0SMarc Kleine-Budde 2250eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_IVMIF) { 2251eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, ivmif); 22521f0e21a0SMarc Kleine-Budde if (err) 22531f0e21a0SMarc Kleine-Budde goto out_fail; 22541f0e21a0SMarc Kleine-Budde } 22551f0e21a0SMarc Kleine-Budde 2256eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_SERRIF) { 2257eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, serrif); 22581f0e21a0SMarc Kleine-Budde if (err) 22591f0e21a0SMarc Kleine-Budde goto out_fail; 22601f0e21a0SMarc Kleine-Budde } 22611f0e21a0SMarc Kleine-Budde 2262eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_ECCIF) { 2263eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, eccif, set_normal_mode); 22641f0e21a0SMarc Kleine-Budde if (err) 22651f0e21a0SMarc Kleine-Budde goto out_fail; 22661f0e21a0SMarc Kleine-Budde } 22671f0e21a0SMarc Kleine-Budde 2268eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_SPICRCIF) { 2269eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, spicrcif); 22701f0e21a0SMarc Kleine-Budde if (err) 22711f0e21a0SMarc Kleine-Budde goto out_fail; 22721f0e21a0SMarc Kleine-Budde } 22731f0e21a0SMarc Kleine-Budde 22741f0e21a0SMarc Kleine-Budde /* On the MCP2527FD and MCP2518FD, we don't get a 22751f0e21a0SMarc Kleine-Budde * CERRIF IRQ on the transition TX ERROR_WARNING -> TX 22761f0e21a0SMarc Kleine-Budde * ERROR_ACTIVE. 22771f0e21a0SMarc Kleine-Budde */ 2278eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_CERRIF || 22791f0e21a0SMarc Kleine-Budde priv->can.state > CAN_STATE_ERROR_ACTIVE) { 2280eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, cerrif); 22811f0e21a0SMarc Kleine-Budde if (err) 22821f0e21a0SMarc Kleine-Budde goto out_fail; 22831f0e21a0SMarc Kleine-Budde 22841f0e21a0SMarc Kleine-Budde /* In Bus Off we completely shut down the 22851f0e21a0SMarc Kleine-Budde * controller. Every subsequent register read 22861f0e21a0SMarc Kleine-Budde * will read bogus data, and if 2287eb79a267SMarc Kleine-Budde * MCP251XFD_QUIRK_CRC_REG is enabled the CRC 22881f0e21a0SMarc Kleine-Budde * check will fail, too. So leave IRQ handler 22891f0e21a0SMarc Kleine-Budde * directly. 22901f0e21a0SMarc Kleine-Budde */ 22911f0e21a0SMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) 22921f0e21a0SMarc Kleine-Budde return IRQ_HANDLED; 22931f0e21a0SMarc Kleine-Budde } 22941f0e21a0SMarc Kleine-Budde 22951f0e21a0SMarc Kleine-Budde handled = IRQ_HANDLED; 22961f0e21a0SMarc Kleine-Budde } while (1); 22971f0e21a0SMarc Kleine-Budde 22981f0e21a0SMarc Kleine-Budde out_fail: 22991f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n", 23001f0e21a0SMarc Kleine-Budde err, priv->regs_status.intf); 2301e0ab3dd5SMarc Kleine-Budde mcp251xfd_dump(priv); 2302eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 23031f0e21a0SMarc Kleine-Budde 23041f0e21a0SMarc Kleine-Budde return handled; 23051f0e21a0SMarc Kleine-Budde } 23061f0e21a0SMarc Kleine-Budde 23071f0e21a0SMarc Kleine-Budde static inline struct 2308eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj *mcp251xfd_get_tx_obj_next(struct mcp251xfd_tx_ring *tx_ring) 23091f0e21a0SMarc Kleine-Budde { 23101f0e21a0SMarc Kleine-Budde u8 tx_head; 23111f0e21a0SMarc Kleine-Budde 2312eb79a267SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 23131f0e21a0SMarc Kleine-Budde 23141f0e21a0SMarc Kleine-Budde return &tx_ring->obj[tx_head]; 23151f0e21a0SMarc Kleine-Budde } 23161f0e21a0SMarc Kleine-Budde 23171f0e21a0SMarc Kleine-Budde static void 2318eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv, 2319eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj, 23201f0e21a0SMarc Kleine-Budde const struct sk_buff *skb, 23211f0e21a0SMarc Kleine-Budde unsigned int seq) 23221f0e21a0SMarc Kleine-Budde { 23231f0e21a0SMarc Kleine-Budde const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 2324eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_tx_obj_raw *hw_tx_obj; 2325eb79a267SMarc Kleine-Budde union mcp251xfd_tx_obj_load_buf *load_buf; 23261f0e21a0SMarc Kleine-Budde u8 dlc; 23271f0e21a0SMarc Kleine-Budde u32 id, flags; 2328a68eda20SMarc Kleine-Budde int len_sanitized = 0, len; 23291f0e21a0SMarc Kleine-Budde 23301f0e21a0SMarc Kleine-Budde if (cfd->can_id & CAN_EFF_FLAG) { 23311f0e21a0SMarc Kleine-Budde u32 sid, eid; 23321f0e21a0SMarc Kleine-Budde 2333eb79a267SMarc Kleine-Budde sid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_SID_MASK, cfd->can_id); 2334eb79a267SMarc Kleine-Budde eid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_EID_MASK, cfd->can_id); 23351f0e21a0SMarc Kleine-Budde 2336eb79a267SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_EID_MASK, eid) | 2337eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, sid); 23381f0e21a0SMarc Kleine-Budde 2339eb79a267SMarc Kleine-Budde flags = MCP251XFD_OBJ_FLAGS_IDE; 23401f0e21a0SMarc Kleine-Budde } else { 2341eb79a267SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, cfd->can_id); 23421f0e21a0SMarc Kleine-Budde flags = 0; 23431f0e21a0SMarc Kleine-Budde } 23441f0e21a0SMarc Kleine-Budde 23451f0e21a0SMarc Kleine-Budde /* Use the MCP2518FD mask even on the MCP2517FD. It doesn't 23461f0e21a0SMarc Kleine-Budde * harm, only the lower 7 bits will be transferred into the 23471f0e21a0SMarc Kleine-Budde * TEF object. 23481f0e21a0SMarc Kleine-Budde */ 234986f1e3b1SMarc Kleine-Budde flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq); 23501f0e21a0SMarc Kleine-Budde 23511f0e21a0SMarc Kleine-Budde if (cfd->can_id & CAN_RTR_FLAG) 2352eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_RTR; 2353a68eda20SMarc Kleine-Budde else 2354a68eda20SMarc Kleine-Budde len_sanitized = canfd_sanitize_len(cfd->len); 23551f0e21a0SMarc Kleine-Budde 23561f0e21a0SMarc Kleine-Budde /* CANFD */ 23571f0e21a0SMarc Kleine-Budde if (can_is_canfd_skb(skb)) { 23581f0e21a0SMarc Kleine-Budde if (cfd->flags & CANFD_ESI) 2359eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_ESI; 23601f0e21a0SMarc Kleine-Budde 2361eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_FDF; 23621f0e21a0SMarc Kleine-Budde 23631f0e21a0SMarc Kleine-Budde if (cfd->flags & CANFD_BRS) 2364eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_BRS; 236586f1e3b1SMarc Kleine-Budde 236686f1e3b1SMarc Kleine-Budde dlc = can_fd_len2dlc(cfd->len); 236786f1e3b1SMarc Kleine-Budde } else { 236886f1e3b1SMarc Kleine-Budde dlc = can_get_cc_dlc((struct can_frame *)cfd, 236986f1e3b1SMarc Kleine-Budde priv->can.ctrlmode); 23701f0e21a0SMarc Kleine-Budde } 23711f0e21a0SMarc Kleine-Budde 237249ffacbcSMarc Kleine-Budde flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC_MASK, dlc); 237386f1e3b1SMarc Kleine-Budde 23741f0e21a0SMarc Kleine-Budde load_buf = &tx_obj->buf; 2375eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) 23761f0e21a0SMarc Kleine-Budde hw_tx_obj = &load_buf->crc.hw_tx_obj; 23771f0e21a0SMarc Kleine-Budde else 23781f0e21a0SMarc Kleine-Budde hw_tx_obj = &load_buf->nocrc.hw_tx_obj; 23791f0e21a0SMarc Kleine-Budde 23801f0e21a0SMarc Kleine-Budde put_unaligned_le32(id, &hw_tx_obj->id); 23811f0e21a0SMarc Kleine-Budde put_unaligned_le32(flags, &hw_tx_obj->flags); 23821f0e21a0SMarc Kleine-Budde 2383561aa5b4SMarc Kleine-Budde /* Copy data */ 23841f0e21a0SMarc Kleine-Budde memcpy(hw_tx_obj->data, cfd->data, cfd->len); 23851f0e21a0SMarc Kleine-Budde 2386561aa5b4SMarc Kleine-Budde /* Clear unused data at end of CAN frame */ 2387a68eda20SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN && len_sanitized) { 2388a68eda20SMarc Kleine-Budde int pad_len; 2389a68eda20SMarc Kleine-Budde 2390a68eda20SMarc Kleine-Budde pad_len = len_sanitized - cfd->len; 2391a68eda20SMarc Kleine-Budde if (pad_len) 2392561aa5b4SMarc Kleine-Budde memset(hw_tx_obj->data + cfd->len, 0x0, pad_len); 2393a68eda20SMarc Kleine-Budde } 2394561aa5b4SMarc Kleine-Budde 23951f0e21a0SMarc Kleine-Budde /* Number of bytes to be written into the RAM of the controller */ 23961f0e21a0SMarc Kleine-Budde len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags); 2397eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN) 2398a68eda20SMarc Kleine-Budde len += round_up(len_sanitized, sizeof(u32)); 23991f0e21a0SMarc Kleine-Budde else 24001f0e21a0SMarc Kleine-Budde len += round_up(cfd->len, sizeof(u32)); 24011f0e21a0SMarc Kleine-Budde 2402eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) { 24031f0e21a0SMarc Kleine-Budde u16 crc; 24041f0e21a0SMarc Kleine-Budde 2405eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_crc_set_len_in_ram(&load_buf->crc.cmd, 24061f0e21a0SMarc Kleine-Budde len); 24071f0e21a0SMarc Kleine-Budde /* CRC */ 24081f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->crc.cmd); 2409eb79a267SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(&load_buf->crc, len); 24101f0e21a0SMarc Kleine-Budde put_unaligned_be16(crc, (void *)load_buf + len); 24111f0e21a0SMarc Kleine-Budde 24121f0e21a0SMarc Kleine-Budde /* Total length */ 24131f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->crc.crc); 24141f0e21a0SMarc Kleine-Budde } else { 24151f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->nocrc.cmd); 24161f0e21a0SMarc Kleine-Budde } 24171f0e21a0SMarc Kleine-Budde 24181f0e21a0SMarc Kleine-Budde tx_obj->xfer[0].len = len; 24191f0e21a0SMarc Kleine-Budde } 24201f0e21a0SMarc Kleine-Budde 2421eb79a267SMarc Kleine-Budde static int mcp251xfd_tx_obj_write(const struct mcp251xfd_priv *priv, 2422eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj) 24231f0e21a0SMarc Kleine-Budde { 24241f0e21a0SMarc Kleine-Budde return spi_async(priv->spi, &tx_obj->msg); 24251f0e21a0SMarc Kleine-Budde } 24261f0e21a0SMarc Kleine-Budde 2427eb79a267SMarc Kleine-Budde static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv, 2428eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring) 24291f0e21a0SMarc Kleine-Budde { 2430eb79a267SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) > 0) 24311f0e21a0SMarc Kleine-Budde return false; 24321f0e21a0SMarc Kleine-Budde 24331f0e21a0SMarc Kleine-Budde netif_stop_queue(priv->ndev); 24341f0e21a0SMarc Kleine-Budde 24351f0e21a0SMarc Kleine-Budde /* Memory barrier before checking tx_free (head and tail) */ 24361f0e21a0SMarc Kleine-Budde smp_mb(); 24371f0e21a0SMarc Kleine-Budde 2438eb79a267SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) == 0) { 24391f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 24401f0e21a0SMarc Kleine-Budde "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n", 24411f0e21a0SMarc Kleine-Budde tx_ring->head, tx_ring->tail, 24421f0e21a0SMarc Kleine-Budde tx_ring->head - tx_ring->tail); 24431f0e21a0SMarc Kleine-Budde 24441f0e21a0SMarc Kleine-Budde return true; 24451f0e21a0SMarc Kleine-Budde } 24461f0e21a0SMarc Kleine-Budde 24471f0e21a0SMarc Kleine-Budde netif_start_queue(priv->ndev); 24481f0e21a0SMarc Kleine-Budde 24491f0e21a0SMarc Kleine-Budde return false; 24501f0e21a0SMarc Kleine-Budde } 24511f0e21a0SMarc Kleine-Budde 2452eb79a267SMarc Kleine-Budde static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb, 24531f0e21a0SMarc Kleine-Budde struct net_device *ndev) 24541f0e21a0SMarc Kleine-Budde { 2455eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 2456eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 2457eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 24580084e298SMarc Kleine-Budde unsigned int frame_len; 24591f0e21a0SMarc Kleine-Budde u8 tx_head; 24601f0e21a0SMarc Kleine-Budde int err; 24611f0e21a0SMarc Kleine-Budde 24621f0e21a0SMarc Kleine-Budde if (can_dropped_invalid_skb(ndev, skb)) 24631f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 24641f0e21a0SMarc Kleine-Budde 2465eb79a267SMarc Kleine-Budde if (mcp251xfd_tx_busy(priv, tx_ring)) 24661f0e21a0SMarc Kleine-Budde return NETDEV_TX_BUSY; 24671f0e21a0SMarc Kleine-Budde 2468eb79a267SMarc Kleine-Budde tx_obj = mcp251xfd_get_tx_obj_next(tx_ring); 2469eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(priv, tx_obj, skb, tx_ring->head); 24701f0e21a0SMarc Kleine-Budde 24711f0e21a0SMarc Kleine-Budde /* Stop queue if we occupy the complete TX FIFO */ 2472eb79a267SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 24731f0e21a0SMarc Kleine-Budde tx_ring->head++; 24749845b8f5SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) == 0) 24751f0e21a0SMarc Kleine-Budde netif_stop_queue(ndev); 24761f0e21a0SMarc Kleine-Budde 24770084e298SMarc Kleine-Budde frame_len = can_skb_get_frame_len(skb); 24780084e298SMarc Kleine-Budde err = can_put_echo_skb(skb, ndev, tx_head, frame_len); 24790084e298SMarc Kleine-Budde if (!err) 24800084e298SMarc Kleine-Budde netdev_sent_queue(priv->ndev, frame_len); 24811f0e21a0SMarc Kleine-Budde 2482eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_obj_write(priv, tx_obj); 24831f0e21a0SMarc Kleine-Budde if (err) 24841f0e21a0SMarc Kleine-Budde goto out_err; 24851f0e21a0SMarc Kleine-Budde 24861f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 24871f0e21a0SMarc Kleine-Budde 24881f0e21a0SMarc Kleine-Budde out_err: 24891f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, "ERROR in %s: %d\n", __func__, err); 24901f0e21a0SMarc Kleine-Budde 24911f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 24921f0e21a0SMarc Kleine-Budde } 24931f0e21a0SMarc Kleine-Budde 2494eb79a267SMarc Kleine-Budde static int mcp251xfd_open(struct net_device *ndev) 24951f0e21a0SMarc Kleine-Budde { 2496eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 24971f0e21a0SMarc Kleine-Budde const struct spi_device *spi = priv->spi; 24981f0e21a0SMarc Kleine-Budde int err; 24991f0e21a0SMarc Kleine-Budde 25001f0e21a0SMarc Kleine-Budde err = pm_runtime_get_sync(ndev->dev.parent); 25011f0e21a0SMarc Kleine-Budde if (err < 0) { 25021f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 25031f0e21a0SMarc Kleine-Budde return err; 25041f0e21a0SMarc Kleine-Budde } 25051f0e21a0SMarc Kleine-Budde 25061f0e21a0SMarc Kleine-Budde err = open_candev(ndev); 25071f0e21a0SMarc Kleine-Budde if (err) 25081f0e21a0SMarc Kleine-Budde goto out_pm_runtime_put; 25091f0e21a0SMarc Kleine-Budde 2510eb79a267SMarc Kleine-Budde err = mcp251xfd_ring_alloc(priv); 25111f0e21a0SMarc Kleine-Budde if (err) 25121f0e21a0SMarc Kleine-Budde goto out_close_candev; 25131f0e21a0SMarc Kleine-Budde 2514eb79a267SMarc Kleine-Budde err = mcp251xfd_transceiver_enable(priv); 25151f0e21a0SMarc Kleine-Budde if (err) 2516eb79a267SMarc Kleine-Budde goto out_mcp251xfd_ring_free; 25171f0e21a0SMarc Kleine-Budde 2518eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_start(priv); 25191f0e21a0SMarc Kleine-Budde if (err) 25201f0e21a0SMarc Kleine-Budde goto out_transceiver_disable; 25211f0e21a0SMarc Kleine-Budde 2522efd8d98dSMarc Kleine-Budde mcp251xfd_timestamp_init(priv); 25231f0e21a0SMarc Kleine-Budde can_rx_offload_enable(&priv->offload); 25241f0e21a0SMarc Kleine-Budde 2525eb79a267SMarc Kleine-Budde err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq, 25261f0e21a0SMarc Kleine-Budde IRQF_ONESHOT, dev_name(&spi->dev), 25271f0e21a0SMarc Kleine-Budde priv); 25281f0e21a0SMarc Kleine-Budde if (err) 25291f0e21a0SMarc Kleine-Budde goto out_can_rx_offload_disable; 25301f0e21a0SMarc Kleine-Budde 2531eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_interrupts_enable(priv); 25321f0e21a0SMarc Kleine-Budde if (err) 25331f0e21a0SMarc Kleine-Budde goto out_free_irq; 25341f0e21a0SMarc Kleine-Budde 25351f0e21a0SMarc Kleine-Budde netif_start_queue(ndev); 25361f0e21a0SMarc Kleine-Budde 25371f0e21a0SMarc Kleine-Budde return 0; 25381f0e21a0SMarc Kleine-Budde 25391f0e21a0SMarc Kleine-Budde out_free_irq: 25401f0e21a0SMarc Kleine-Budde free_irq(spi->irq, priv); 25411f0e21a0SMarc Kleine-Budde out_can_rx_offload_disable: 25421f0e21a0SMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 2543efd8d98dSMarc Kleine-Budde mcp251xfd_timestamp_stop(priv); 25441f0e21a0SMarc Kleine-Budde out_transceiver_disable: 2545eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(priv); 2546eb79a267SMarc Kleine-Budde out_mcp251xfd_ring_free: 2547eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 25481f0e21a0SMarc Kleine-Budde out_close_candev: 25491f0e21a0SMarc Kleine-Budde close_candev(ndev); 25501f0e21a0SMarc Kleine-Budde out_pm_runtime_put: 2551eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 25521f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 25531f0e21a0SMarc Kleine-Budde 25541f0e21a0SMarc Kleine-Budde return err; 25551f0e21a0SMarc Kleine-Budde } 25561f0e21a0SMarc Kleine-Budde 2557eb79a267SMarc Kleine-Budde static int mcp251xfd_stop(struct net_device *ndev) 25581f0e21a0SMarc Kleine-Budde { 2559eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 25601f0e21a0SMarc Kleine-Budde 25611f0e21a0SMarc Kleine-Budde netif_stop_queue(ndev); 2562eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 25631f0e21a0SMarc Kleine-Budde free_irq(ndev->irq, priv); 25641f0e21a0SMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 2565efd8d98dSMarc Kleine-Budde mcp251xfd_timestamp_stop(priv); 2566eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 2567eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(priv); 2568eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 25691f0e21a0SMarc Kleine-Budde close_candev(ndev); 25701f0e21a0SMarc Kleine-Budde 25711f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 25721f0e21a0SMarc Kleine-Budde 25731f0e21a0SMarc Kleine-Budde return 0; 25741f0e21a0SMarc Kleine-Budde } 25751f0e21a0SMarc Kleine-Budde 2576eb79a267SMarc Kleine-Budde static const struct net_device_ops mcp251xfd_netdev_ops = { 2577eb79a267SMarc Kleine-Budde .ndo_open = mcp251xfd_open, 2578eb79a267SMarc Kleine-Budde .ndo_stop = mcp251xfd_stop, 2579eb79a267SMarc Kleine-Budde .ndo_start_xmit = mcp251xfd_start_xmit, 25801f0e21a0SMarc Kleine-Budde .ndo_change_mtu = can_change_mtu, 25811f0e21a0SMarc Kleine-Budde }; 25821f0e21a0SMarc Kleine-Budde 25831f0e21a0SMarc Kleine-Budde static void 2584eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(struct mcp251xfd_priv *priv) 25851f0e21a0SMarc Kleine-Budde { 25861f0e21a0SMarc Kleine-Budde const struct spi_device *spi = priv->spi; 25871f0e21a0SMarc Kleine-Budde const struct spi_controller *ctlr = spi->controller; 25881f0e21a0SMarc Kleine-Budde 25891f0e21a0SMarc Kleine-Budde if (ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX) 2590eb79a267SMarc Kleine-Budde priv->devtype_data.quirks |= MCP251XFD_QUIRK_HALF_DUPLEX; 25911f0e21a0SMarc Kleine-Budde } 25921f0e21a0SMarc Kleine-Budde 2593eb79a267SMarc Kleine-Budde static int mcp251xfd_register_chip_detect(struct mcp251xfd_priv *priv) 25941f0e21a0SMarc Kleine-Budde { 25951f0e21a0SMarc Kleine-Budde const struct net_device *ndev = priv->ndev; 2596eb79a267SMarc Kleine-Budde const struct mcp251xfd_devtype_data *devtype_data; 25971f0e21a0SMarc Kleine-Budde u32 osc; 25981f0e21a0SMarc Kleine-Budde int err; 25991f0e21a0SMarc Kleine-Budde 26001f0e21a0SMarc Kleine-Budde /* The OSC_LPMEN is only supported on MCP2518FD, so use it to 26011f0e21a0SMarc Kleine-Budde * autodetect the model. 26021f0e21a0SMarc Kleine-Budde */ 2603eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_OSC, 2604eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_LPMEN, 2605eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_LPMEN); 26061f0e21a0SMarc Kleine-Budde if (err) 26071f0e21a0SMarc Kleine-Budde return err; 26081f0e21a0SMarc Kleine-Budde 2609eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc); 26101f0e21a0SMarc Kleine-Budde if (err) 26111f0e21a0SMarc Kleine-Budde return err; 26121f0e21a0SMarc Kleine-Budde 2613eb79a267SMarc Kleine-Budde if (osc & MCP251XFD_REG_OSC_LPMEN) 2614eb79a267SMarc Kleine-Budde devtype_data = &mcp251xfd_devtype_data_mcp2518fd; 26151f0e21a0SMarc Kleine-Budde else 2616eb79a267SMarc Kleine-Budde devtype_data = &mcp251xfd_devtype_data_mcp2517fd; 26171f0e21a0SMarc Kleine-Budde 2618eb79a267SMarc Kleine-Budde if (!mcp251xfd_is_251X(priv) && 26191f0e21a0SMarc Kleine-Budde priv->devtype_data.model != devtype_data->model) { 26201f0e21a0SMarc Kleine-Budde netdev_info(ndev, 26211f0e21a0SMarc Kleine-Budde "Detected %s, but firmware specifies a %s. Fixing up.", 2622eb79a267SMarc Kleine-Budde __mcp251xfd_get_model_str(devtype_data->model), 2623eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv)); 26241f0e21a0SMarc Kleine-Budde } 26251f0e21a0SMarc Kleine-Budde priv->devtype_data = *devtype_data; 26261f0e21a0SMarc Kleine-Budde 26271f0e21a0SMarc Kleine-Budde /* We need to preserve the Half Duplex Quirk. */ 2628eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(priv); 26291f0e21a0SMarc Kleine-Budde 26301f0e21a0SMarc Kleine-Budde /* Re-init regmap with quirks of detected model. */ 2631eb79a267SMarc Kleine-Budde return mcp251xfd_regmap_init(priv); 26321f0e21a0SMarc Kleine-Budde } 26331f0e21a0SMarc Kleine-Budde 2634eb79a267SMarc Kleine-Budde static int mcp251xfd_register_check_rx_int(struct mcp251xfd_priv *priv) 26351f0e21a0SMarc Kleine-Budde { 26361f0e21a0SMarc Kleine-Budde int err, rx_pending; 26371f0e21a0SMarc Kleine-Budde 26381f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 26391f0e21a0SMarc Kleine-Budde return 0; 26401f0e21a0SMarc Kleine-Budde 2641eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_enable(priv); 26421f0e21a0SMarc Kleine-Budde if (err) 26431f0e21a0SMarc Kleine-Budde return err; 26441f0e21a0SMarc Kleine-Budde 26451f0e21a0SMarc Kleine-Budde /* Check if RX_INT is properly working. The RX_INT should not 26461f0e21a0SMarc Kleine-Budde * be active after a softreset. 26471f0e21a0SMarc Kleine-Budde */ 26481f0e21a0SMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 26491f0e21a0SMarc Kleine-Budde 2650eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_disable(priv); 26511f0e21a0SMarc Kleine-Budde if (err) 26521f0e21a0SMarc Kleine-Budde return err; 26531f0e21a0SMarc Kleine-Budde 26541f0e21a0SMarc Kleine-Budde if (!rx_pending) 26551f0e21a0SMarc Kleine-Budde return 0; 26561f0e21a0SMarc Kleine-Budde 26571f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 26581f0e21a0SMarc Kleine-Budde "RX_INT active after softreset, disabling RX_INT support."); 26591f0e21a0SMarc Kleine-Budde devm_gpiod_put(&priv->spi->dev, priv->rx_int); 26601f0e21a0SMarc Kleine-Budde priv->rx_int = NULL; 26611f0e21a0SMarc Kleine-Budde 26621f0e21a0SMarc Kleine-Budde return 0; 26631f0e21a0SMarc Kleine-Budde } 26641f0e21a0SMarc Kleine-Budde 26651f0e21a0SMarc Kleine-Budde static int 2666eb79a267SMarc Kleine-Budde mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, 26671f0e21a0SMarc Kleine-Budde u32 *dev_id, u32 *effective_speed_hz) 26681f0e21a0SMarc Kleine-Budde { 2669eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_rx; 2670eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_tx; 26711f0e21a0SMarc Kleine-Budde struct spi_transfer xfer[2] = { }; 26721f0e21a0SMarc Kleine-Budde int err; 26731f0e21a0SMarc Kleine-Budde 26741f0e21a0SMarc Kleine-Budde buf_rx = kzalloc(sizeof(*buf_rx), GFP_KERNEL); 26751f0e21a0SMarc Kleine-Budde if (!buf_rx) 26761f0e21a0SMarc Kleine-Budde return -ENOMEM; 26771f0e21a0SMarc Kleine-Budde 26781f0e21a0SMarc Kleine-Budde buf_tx = kzalloc(sizeof(*buf_tx), GFP_KERNEL); 26791f0e21a0SMarc Kleine-Budde if (!buf_tx) { 26801f0e21a0SMarc Kleine-Budde err = -ENOMEM; 26811f0e21a0SMarc Kleine-Budde goto out_kfree_buf_rx; 26821f0e21a0SMarc Kleine-Budde } 26831f0e21a0SMarc Kleine-Budde 26841f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 26851f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd); 26861f0e21a0SMarc Kleine-Budde xfer[1].rx_buf = buf_rx->data; 26871f0e21a0SMarc Kleine-Budde xfer[1].len = sizeof(dev_id); 26881f0e21a0SMarc Kleine-Budde 2689eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, MCP251XFD_REG_DEVID); 26901f0e21a0SMarc Kleine-Budde err = spi_sync_transfer(priv->spi, xfer, ARRAY_SIZE(xfer)); 26911f0e21a0SMarc Kleine-Budde if (err) 26921f0e21a0SMarc Kleine-Budde goto out_kfree_buf_tx; 26931f0e21a0SMarc Kleine-Budde 26941f0e21a0SMarc Kleine-Budde *dev_id = be32_to_cpup((__be32 *)buf_rx->data); 26951f0e21a0SMarc Kleine-Budde *effective_speed_hz = xfer->effective_speed_hz; 26961f0e21a0SMarc Kleine-Budde 26971f0e21a0SMarc Kleine-Budde out_kfree_buf_tx: 26981f0e21a0SMarc Kleine-Budde kfree(buf_tx); 26991f0e21a0SMarc Kleine-Budde out_kfree_buf_rx: 27001f0e21a0SMarc Kleine-Budde kfree(buf_rx); 27011f0e21a0SMarc Kleine-Budde 27021f0e21a0SMarc Kleine-Budde return 0; 27031f0e21a0SMarc Kleine-Budde } 27041f0e21a0SMarc Kleine-Budde 2705eb79a267SMarc Kleine-Budde #define MCP251XFD_QUIRK_ACTIVE(quirk) \ 2706eb79a267SMarc Kleine-Budde (priv->devtype_data.quirks & MCP251XFD_QUIRK_##quirk ? '+' : '-') 27071f0e21a0SMarc Kleine-Budde 27081f0e21a0SMarc Kleine-Budde static int 2709eb79a267SMarc Kleine-Budde mcp251xfd_register_done(const struct mcp251xfd_priv *priv) 27101f0e21a0SMarc Kleine-Budde { 27111f0e21a0SMarc Kleine-Budde u32 dev_id, effective_speed_hz; 27121f0e21a0SMarc Kleine-Budde int err; 27131f0e21a0SMarc Kleine-Budde 2714eb79a267SMarc Kleine-Budde err = mcp251xfd_register_get_dev_id(priv, &dev_id, 27151f0e21a0SMarc Kleine-Budde &effective_speed_hz); 27161f0e21a0SMarc Kleine-Budde if (err) 27171f0e21a0SMarc Kleine-Budde return err; 27181f0e21a0SMarc Kleine-Budde 27191f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 27201f0e21a0SMarc Kleine-Budde "%s rev%lu.%lu (%cRX_INT %cMAB_NO_WARN %cCRC_REG %cCRC_RX %cCRC_TX %cECC %cHD c:%u.%02uMHz m:%u.%02uMHz r:%u.%02uMHz e:%u.%02uMHz) successfully initialized.\n", 2721eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv), 2722eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_DEVID_ID_MASK, dev_id), 2723eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_DEVID_REV_MASK, dev_id), 27241f0e21a0SMarc Kleine-Budde priv->rx_int ? '+' : '-', 2725eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(MAB_NO_WARN), 2726eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_REG), 2727eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_RX), 2728eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_TX), 2729eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(ECC), 2730eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(HALF_DUPLEX), 27311f0e21a0SMarc Kleine-Budde priv->can.clock.freq / 1000000, 27321f0e21a0SMarc Kleine-Budde priv->can.clock.freq % 1000000 / 1000 / 10, 27331f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig / 1000000, 27341f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig % 1000000 / 1000 / 10, 27351f0e21a0SMarc Kleine-Budde priv->spi->max_speed_hz / 1000000, 27361f0e21a0SMarc Kleine-Budde priv->spi->max_speed_hz % 1000000 / 1000 / 10, 27371f0e21a0SMarc Kleine-Budde effective_speed_hz / 1000000, 27381f0e21a0SMarc Kleine-Budde effective_speed_hz % 1000000 / 1000 / 10); 27391f0e21a0SMarc Kleine-Budde 27401f0e21a0SMarc Kleine-Budde return 0; 27411f0e21a0SMarc Kleine-Budde } 27421f0e21a0SMarc Kleine-Budde 2743eb79a267SMarc Kleine-Budde static int mcp251xfd_register(struct mcp251xfd_priv *priv) 27441f0e21a0SMarc Kleine-Budde { 27451f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 27461f0e21a0SMarc Kleine-Budde int err; 27471f0e21a0SMarc Kleine-Budde 2748eb79a267SMarc Kleine-Budde err = mcp251xfd_clks_and_vdd_enable(priv); 27491f0e21a0SMarc Kleine-Budde if (err) 27501f0e21a0SMarc Kleine-Budde return err; 27511f0e21a0SMarc Kleine-Budde 27521f0e21a0SMarc Kleine-Budde pm_runtime_get_noresume(ndev->dev.parent); 27531f0e21a0SMarc Kleine-Budde err = pm_runtime_set_active(ndev->dev.parent); 27541f0e21a0SMarc Kleine-Budde if (err) 27551f0e21a0SMarc Kleine-Budde goto out_runtime_put_noidle; 27561f0e21a0SMarc Kleine-Budde pm_runtime_enable(ndev->dev.parent); 27571f0e21a0SMarc Kleine-Budde 2758eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(priv); 27591f0e21a0SMarc Kleine-Budde 2760eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset(priv); 27611f0e21a0SMarc Kleine-Budde if (err == -ENODEV) 27621f0e21a0SMarc Kleine-Budde goto out_runtime_disable; 27631f0e21a0SMarc Kleine-Budde if (err) 27641f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 27651f0e21a0SMarc Kleine-Budde 2766eb79a267SMarc Kleine-Budde err = mcp251xfd_register_chip_detect(priv); 27671f0e21a0SMarc Kleine-Budde if (err) 27681f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 27691f0e21a0SMarc Kleine-Budde 2770eb79a267SMarc Kleine-Budde err = mcp251xfd_register_check_rx_int(priv); 27711f0e21a0SMarc Kleine-Budde if (err) 27721f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 27731f0e21a0SMarc Kleine-Budde 27741f0e21a0SMarc Kleine-Budde err = register_candev(ndev); 27751f0e21a0SMarc Kleine-Budde if (err) 27761f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 27771f0e21a0SMarc Kleine-Budde 2778eb79a267SMarc Kleine-Budde err = mcp251xfd_register_done(priv); 27791f0e21a0SMarc Kleine-Budde if (err) 27801f0e21a0SMarc Kleine-Budde goto out_unregister_candev; 27811f0e21a0SMarc Kleine-Budde 27821f0e21a0SMarc Kleine-Budde /* Put controller into sleep mode and let pm_runtime_put() 27831f0e21a0SMarc Kleine-Budde * disable the clocks and vdd. If CONFIG_PM is not enabled, 27841f0e21a0SMarc Kleine-Budde * the clocks and vdd will stay powered. 27851f0e21a0SMarc Kleine-Budde */ 2786eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 27871f0e21a0SMarc Kleine-Budde if (err) 27881f0e21a0SMarc Kleine-Budde goto out_unregister_candev; 27891f0e21a0SMarc Kleine-Budde 27901f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 27911f0e21a0SMarc Kleine-Budde 27921f0e21a0SMarc Kleine-Budde return 0; 27931f0e21a0SMarc Kleine-Budde 27941f0e21a0SMarc Kleine-Budde out_unregister_candev: 27951f0e21a0SMarc Kleine-Budde unregister_candev(ndev); 27961f0e21a0SMarc Kleine-Budde out_chip_set_mode_sleep: 2797eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 27981f0e21a0SMarc Kleine-Budde out_runtime_disable: 27991f0e21a0SMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 28001f0e21a0SMarc Kleine-Budde out_runtime_put_noidle: 28011f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 2802eb79a267SMarc Kleine-Budde mcp251xfd_clks_and_vdd_disable(priv); 28031f0e21a0SMarc Kleine-Budde 28041f0e21a0SMarc Kleine-Budde return err; 28051f0e21a0SMarc Kleine-Budde } 28061f0e21a0SMarc Kleine-Budde 2807eb79a267SMarc Kleine-Budde static inline void mcp251xfd_unregister(struct mcp251xfd_priv *priv) 28081f0e21a0SMarc Kleine-Budde { 28091f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 28101f0e21a0SMarc Kleine-Budde 28111f0e21a0SMarc Kleine-Budde unregister_candev(ndev); 28121f0e21a0SMarc Kleine-Budde 28131f0e21a0SMarc Kleine-Budde pm_runtime_get_sync(ndev->dev.parent); 28141f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 2815eb79a267SMarc Kleine-Budde mcp251xfd_clks_and_vdd_disable(priv); 28161f0e21a0SMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 28171f0e21a0SMarc Kleine-Budde } 28181f0e21a0SMarc Kleine-Budde 2819eb79a267SMarc Kleine-Budde static const struct of_device_id mcp251xfd_of_match[] = { 28201f0e21a0SMarc Kleine-Budde { 28211f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp2517fd", 2822eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp2517fd, 28231f0e21a0SMarc Kleine-Budde }, { 28241f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp2518fd", 2825eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp2518fd, 28261f0e21a0SMarc Kleine-Budde }, { 28271f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp251xfd", 2828eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp251xfd, 28291f0e21a0SMarc Kleine-Budde }, { 28301f0e21a0SMarc Kleine-Budde /* sentinel */ 28311f0e21a0SMarc Kleine-Budde }, 28321f0e21a0SMarc Kleine-Budde }; 2833eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(of, mcp251xfd_of_match); 28341f0e21a0SMarc Kleine-Budde 2835eb79a267SMarc Kleine-Budde static const struct spi_device_id mcp251xfd_id_table[] = { 28361f0e21a0SMarc Kleine-Budde { 28371f0e21a0SMarc Kleine-Budde .name = "mcp2517fd", 2838eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2517fd, 28391f0e21a0SMarc Kleine-Budde }, { 28401f0e21a0SMarc Kleine-Budde .name = "mcp2518fd", 2841eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2518fd, 28421f0e21a0SMarc Kleine-Budde }, { 28431f0e21a0SMarc Kleine-Budde .name = "mcp251xfd", 2844eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp251xfd, 28451f0e21a0SMarc Kleine-Budde }, { 28461f0e21a0SMarc Kleine-Budde /* sentinel */ 28471f0e21a0SMarc Kleine-Budde }, 28481f0e21a0SMarc Kleine-Budde }; 2849eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(spi, mcp251xfd_id_table); 28501f0e21a0SMarc Kleine-Budde 2851eb79a267SMarc Kleine-Budde static int mcp251xfd_probe(struct spi_device *spi) 28521f0e21a0SMarc Kleine-Budde { 28531f0e21a0SMarc Kleine-Budde const void *match; 28541f0e21a0SMarc Kleine-Budde struct net_device *ndev; 2855eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv; 28561f0e21a0SMarc Kleine-Budde struct gpio_desc *rx_int; 28571f0e21a0SMarc Kleine-Budde struct regulator *reg_vdd, *reg_xceiver; 28581f0e21a0SMarc Kleine-Budde struct clk *clk; 28591f0e21a0SMarc Kleine-Budde u32 freq; 28601f0e21a0SMarc Kleine-Budde int err; 28611f0e21a0SMarc Kleine-Budde 28621a1c436bSMarc Kleine-Budde if (!spi->irq) 28631a1c436bSMarc Kleine-Budde return dev_err_probe(&spi->dev, -ENXIO, 28641a1c436bSMarc Kleine-Budde "No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n"); 28651a1c436bSMarc Kleine-Budde 28661f0e21a0SMarc Kleine-Budde rx_int = devm_gpiod_get_optional(&spi->dev, "microchip,rx-int", 28671f0e21a0SMarc Kleine-Budde GPIOD_IN); 2868cf8ee6deSMarc Kleine-Budde if (IS_ERR(rx_int)) 2869cf8ee6deSMarc Kleine-Budde return dev_err_probe(&spi->dev, PTR_ERR(rx_int), 2870cf8ee6deSMarc Kleine-Budde "Failed to get RX-INT!\n"); 28711f0e21a0SMarc Kleine-Budde 28721f0e21a0SMarc Kleine-Budde reg_vdd = devm_regulator_get_optional(&spi->dev, "vdd"); 2873cf8ee6deSMarc Kleine-Budde if (PTR_ERR(reg_vdd) == -ENODEV) 28741f0e21a0SMarc Kleine-Budde reg_vdd = NULL; 28751f0e21a0SMarc Kleine-Budde else if (IS_ERR(reg_vdd)) 2876cf8ee6deSMarc Kleine-Budde return dev_err_probe(&spi->dev, PTR_ERR(reg_vdd), 2877cf8ee6deSMarc Kleine-Budde "Failed to get VDD regulator!\n"); 28781f0e21a0SMarc Kleine-Budde 28791f0e21a0SMarc Kleine-Budde reg_xceiver = devm_regulator_get_optional(&spi->dev, "xceiver"); 2880cf8ee6deSMarc Kleine-Budde if (PTR_ERR(reg_xceiver) == -ENODEV) 28811f0e21a0SMarc Kleine-Budde reg_xceiver = NULL; 28821f0e21a0SMarc Kleine-Budde else if (IS_ERR(reg_xceiver)) 2883cf8ee6deSMarc Kleine-Budde return dev_err_probe(&spi->dev, PTR_ERR(reg_xceiver), 2884cf8ee6deSMarc Kleine-Budde "Failed to get Transceiver regulator!\n"); 28851f0e21a0SMarc Kleine-Budde 28861f0e21a0SMarc Kleine-Budde clk = devm_clk_get(&spi->dev, NULL); 2887cf8ee6deSMarc Kleine-Budde if (IS_ERR(clk)) 28884cc7faa4SDan Carpenter return dev_err_probe(&spi->dev, PTR_ERR(clk), 2889cf8ee6deSMarc Kleine-Budde "Failed to get Oscillator (clock)!\n"); 28901f0e21a0SMarc Kleine-Budde freq = clk_get_rate(clk); 28911f0e21a0SMarc Kleine-Budde 28921f0e21a0SMarc Kleine-Budde /* Sanity check */ 2893eb79a267SMarc Kleine-Budde if (freq < MCP251XFD_SYSCLOCK_HZ_MIN || 2894eb79a267SMarc Kleine-Budde freq > MCP251XFD_SYSCLOCK_HZ_MAX) { 28951f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, 28961f0e21a0SMarc Kleine-Budde "Oscillator frequency (%u Hz) is too low or high.\n", 28971f0e21a0SMarc Kleine-Budde freq); 28981f0e21a0SMarc Kleine-Budde return -ERANGE; 28991f0e21a0SMarc Kleine-Budde } 29001f0e21a0SMarc Kleine-Budde 2901eb79a267SMarc Kleine-Budde if (freq <= MCP251XFD_SYSCLOCK_HZ_MAX / MCP251XFD_OSC_PLL_MULTIPLIER) { 29021f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, 29031f0e21a0SMarc Kleine-Budde "Oscillator frequency (%u Hz) is too low and PLL is not supported.\n", 29041f0e21a0SMarc Kleine-Budde freq); 29051f0e21a0SMarc Kleine-Budde return -ERANGE; 29061f0e21a0SMarc Kleine-Budde } 29071f0e21a0SMarc Kleine-Budde 2908eb79a267SMarc Kleine-Budde ndev = alloc_candev(sizeof(struct mcp251xfd_priv), 2909eb79a267SMarc Kleine-Budde MCP251XFD_TX_OBJ_NUM_MAX); 29101f0e21a0SMarc Kleine-Budde if (!ndev) 29111f0e21a0SMarc Kleine-Budde return -ENOMEM; 29121f0e21a0SMarc Kleine-Budde 29131f0e21a0SMarc Kleine-Budde SET_NETDEV_DEV(ndev, &spi->dev); 29141f0e21a0SMarc Kleine-Budde 2915eb79a267SMarc Kleine-Budde ndev->netdev_ops = &mcp251xfd_netdev_ops; 29161f0e21a0SMarc Kleine-Budde ndev->irq = spi->irq; 29171f0e21a0SMarc Kleine-Budde ndev->flags |= IFF_ECHO; 29181f0e21a0SMarc Kleine-Budde 29191f0e21a0SMarc Kleine-Budde priv = netdev_priv(ndev); 29201f0e21a0SMarc Kleine-Budde spi_set_drvdata(spi, priv); 29211f0e21a0SMarc Kleine-Budde priv->can.clock.freq = freq; 2922eb79a267SMarc Kleine-Budde priv->can.do_set_mode = mcp251xfd_set_mode; 2923eb79a267SMarc Kleine-Budde priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter; 2924eb79a267SMarc Kleine-Budde priv->can.bittiming_const = &mcp251xfd_bittiming_const; 2925eb79a267SMarc Kleine-Budde priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const; 2926ee42bedcSManivannan Sadhasivam priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | 2927ee42bedcSManivannan Sadhasivam CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING | 292886f1e3b1SMarc Kleine-Budde CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO | 292986f1e3b1SMarc Kleine-Budde CAN_CTRLMODE_CC_LEN8_DLC; 29301f0e21a0SMarc Kleine-Budde priv->ndev = ndev; 29311f0e21a0SMarc Kleine-Budde priv->spi = spi; 29321f0e21a0SMarc Kleine-Budde priv->rx_int = rx_int; 29331f0e21a0SMarc Kleine-Budde priv->clk = clk; 29341f0e21a0SMarc Kleine-Budde priv->reg_vdd = reg_vdd; 29351f0e21a0SMarc Kleine-Budde priv->reg_xceiver = reg_xceiver; 29361f0e21a0SMarc Kleine-Budde 29371f0e21a0SMarc Kleine-Budde match = device_get_match_data(&spi->dev); 29381f0e21a0SMarc Kleine-Budde if (match) 2939eb79a267SMarc Kleine-Budde priv->devtype_data = *(struct mcp251xfd_devtype_data *)match; 29401f0e21a0SMarc Kleine-Budde else 2941eb79a267SMarc Kleine-Budde priv->devtype_data = *(struct mcp251xfd_devtype_data *) 29421f0e21a0SMarc Kleine-Budde spi_get_device_id(spi)->driver_data; 29431f0e21a0SMarc Kleine-Budde 29441f0e21a0SMarc Kleine-Budde /* Errata Reference: 294528eb119cSMarc Kleine-Budde * mcp2517fd: DS80000792C 5., mcp2518fd: DS80000789C 4. 29461f0e21a0SMarc Kleine-Budde * 29471f0e21a0SMarc Kleine-Budde * The SPI can write corrupted data to the RAM at fast SPI 29481f0e21a0SMarc Kleine-Budde * speeds: 29491f0e21a0SMarc Kleine-Budde * 29501f0e21a0SMarc Kleine-Budde * Simultaneous activity on the CAN bus while writing data to 29511f0e21a0SMarc Kleine-Budde * RAM via the SPI interface, with high SCK frequency, can 29521f0e21a0SMarc Kleine-Budde * lead to corrupted data being written to RAM. 29531f0e21a0SMarc Kleine-Budde * 29541f0e21a0SMarc Kleine-Budde * Fix/Work Around: 29551f0e21a0SMarc Kleine-Budde * Ensure that FSCK is less than or equal to 0.85 * 29561f0e21a0SMarc Kleine-Budde * (FSYSCLK/2). 29571f0e21a0SMarc Kleine-Budde * 295801b2a0e5SMarc Kleine-Budde * Known good combinations are: 29591f0e21a0SMarc Kleine-Budde * 296001b2a0e5SMarc Kleine-Budde * MCP ext-clk SoC SPI SPI-clk max-clk parent-clk config 29611f0e21a0SMarc Kleine-Budde * 296201b2a0e5SMarc Kleine-Budde * 2518 20 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 8333333 Hz 83.33% 600000000 Hz assigned-clocks = <&ccu CLK_SPIx> 296301b2a0e5SMarc Kleine-Budde * 2518 40 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 16666667 Hz 83.33% 600000000 Hz assigned-clocks = <&ccu CLK_SPIx> 296401b2a0e5SMarc Kleine-Budde * 2517 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz default 296501b2a0e5SMarc Kleine-Budde * 2518 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz default 29669f1fbc1cSMarc Kleine-Budde * 2518 40 MHz fsl,imx6dl fsl,imx51-ecspi 15000000 Hz 75.00% 30000000 Hz default 296701b2a0e5SMarc Kleine-Budde * 2517 20 MHz fsl,imx8mm fsl,imx51-ecspi 8333333 Hz 83.33% 16666667 Hz assigned-clocks = <&clk IMX8MM_CLK_ECSPIx_ROOT> 29681f0e21a0SMarc Kleine-Budde * 29691f0e21a0SMarc Kleine-Budde */ 29701f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig = spi->max_speed_hz; 29711f0e21a0SMarc Kleine-Budde spi->max_speed_hz = min(spi->max_speed_hz, freq / 2 / 1000 * 850); 29721f0e21a0SMarc Kleine-Budde spi->bits_per_word = 8; 29731f0e21a0SMarc Kleine-Budde spi->rt = true; 29741f0e21a0SMarc Kleine-Budde err = spi_setup(spi); 29751f0e21a0SMarc Kleine-Budde if (err) 29761f0e21a0SMarc Kleine-Budde goto out_free_candev; 29771f0e21a0SMarc Kleine-Budde 2978eb79a267SMarc Kleine-Budde err = mcp251xfd_regmap_init(priv); 29791f0e21a0SMarc Kleine-Budde if (err) 29801f0e21a0SMarc Kleine-Budde goto out_free_candev; 29811f0e21a0SMarc Kleine-Budde 29821f0e21a0SMarc Kleine-Budde err = can_rx_offload_add_manual(ndev, &priv->offload, 2983eb79a267SMarc Kleine-Budde MCP251XFD_NAPI_WEIGHT); 29841f0e21a0SMarc Kleine-Budde if (err) 29851f0e21a0SMarc Kleine-Budde goto out_free_candev; 29861f0e21a0SMarc Kleine-Budde 2987eb79a267SMarc Kleine-Budde err = mcp251xfd_register(priv); 29881f0e21a0SMarc Kleine-Budde if (err) 29894376ea42SMarc Kleine-Budde goto out_can_rx_offload_del; 29901f0e21a0SMarc Kleine-Budde 29911f0e21a0SMarc Kleine-Budde return 0; 29921f0e21a0SMarc Kleine-Budde 29934376ea42SMarc Kleine-Budde out_can_rx_offload_del: 29944376ea42SMarc Kleine-Budde can_rx_offload_del(&priv->offload); 29951f0e21a0SMarc Kleine-Budde out_free_candev: 29961f0e21a0SMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 29971f0e21a0SMarc Kleine-Budde 29981f0e21a0SMarc Kleine-Budde free_candev(ndev); 29991f0e21a0SMarc Kleine-Budde 30001f0e21a0SMarc Kleine-Budde return err; 30011f0e21a0SMarc Kleine-Budde } 30021f0e21a0SMarc Kleine-Budde 3003eb79a267SMarc Kleine-Budde static int mcp251xfd_remove(struct spi_device *spi) 30041f0e21a0SMarc Kleine-Budde { 3005eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = spi_get_drvdata(spi); 30061f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 30071f0e21a0SMarc Kleine-Budde 30081f0e21a0SMarc Kleine-Budde can_rx_offload_del(&priv->offload); 3009eb79a267SMarc Kleine-Budde mcp251xfd_unregister(priv); 30101f0e21a0SMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 30111f0e21a0SMarc Kleine-Budde free_candev(ndev); 30121f0e21a0SMarc Kleine-Budde 30131f0e21a0SMarc Kleine-Budde return 0; 30141f0e21a0SMarc Kleine-Budde } 30151f0e21a0SMarc Kleine-Budde 3016eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_suspend(struct device *device) 30171f0e21a0SMarc Kleine-Budde { 3018eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = dev_get_drvdata(device); 30191f0e21a0SMarc Kleine-Budde 3020eb79a267SMarc Kleine-Budde return mcp251xfd_clks_and_vdd_disable(priv); 30211f0e21a0SMarc Kleine-Budde } 30221f0e21a0SMarc Kleine-Budde 3023eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_resume(struct device *device) 30241f0e21a0SMarc Kleine-Budde { 3025eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = dev_get_drvdata(device); 30261f0e21a0SMarc Kleine-Budde 3027eb79a267SMarc Kleine-Budde return mcp251xfd_clks_and_vdd_enable(priv); 30281f0e21a0SMarc Kleine-Budde } 30291f0e21a0SMarc Kleine-Budde 3030eb79a267SMarc Kleine-Budde static const struct dev_pm_ops mcp251xfd_pm_ops = { 3031eb79a267SMarc Kleine-Budde SET_RUNTIME_PM_OPS(mcp251xfd_runtime_suspend, 3032eb79a267SMarc Kleine-Budde mcp251xfd_runtime_resume, NULL) 30331f0e21a0SMarc Kleine-Budde }; 30341f0e21a0SMarc Kleine-Budde 3035eb79a267SMarc Kleine-Budde static struct spi_driver mcp251xfd_driver = { 30361f0e21a0SMarc Kleine-Budde .driver = { 30371f0e21a0SMarc Kleine-Budde .name = DEVICE_NAME, 3038eb79a267SMarc Kleine-Budde .pm = &mcp251xfd_pm_ops, 3039eb79a267SMarc Kleine-Budde .of_match_table = mcp251xfd_of_match, 30401f0e21a0SMarc Kleine-Budde }, 3041eb79a267SMarc Kleine-Budde .probe = mcp251xfd_probe, 3042eb79a267SMarc Kleine-Budde .remove = mcp251xfd_remove, 3043eb79a267SMarc Kleine-Budde .id_table = mcp251xfd_id_table, 30441f0e21a0SMarc Kleine-Budde }; 3045eb79a267SMarc Kleine-Budde module_spi_driver(mcp251xfd_driver); 30461f0e21a0SMarc Kleine-Budde 30471f0e21a0SMarc Kleine-Budde MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>"); 3048f4f77366SMarc Kleine-Budde MODULE_DESCRIPTION("Microchip MCP251xFD Family CAN controller driver"); 30491f0e21a0SMarc Kleine-Budde MODULE_LICENSE("GPL v2"); 3050