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 // 51f0e21a0SMarc Kleine-Budde // Copyright (c) 2019, 2020 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/netdevice.h> 201f0e21a0SMarc Kleine-Budde #include <linux/of.h> 211f0e21a0SMarc Kleine-Budde #include <linux/of_device.h> 221f0e21a0SMarc Kleine-Budde #include <linux/pm_runtime.h> 231f0e21a0SMarc Kleine-Budde 241f0e21a0SMarc Kleine-Budde #include <asm/unaligned.h> 251f0e21a0SMarc Kleine-Budde 261f0e21a0SMarc Kleine-Budde #include "mcp251xfd.h" 271f0e21a0SMarc Kleine-Budde 28f4f77366SMarc Kleine-Budde #define DEVICE_NAME "mcp251xfd" 291f0e21a0SMarc Kleine-Budde 30eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp2517fd = { 31eb79a267SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_MAB_NO_WARN | MCP251XFD_QUIRK_CRC_REG | 32eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_RX | MCP251XFD_QUIRK_CRC_TX | 33eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ECC, 34eb79a267SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP2517FD, 351f0e21a0SMarc Kleine-Budde }; 361f0e21a0SMarc Kleine-Budde 37eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp2518fd = { 38eb79a267SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_CRC_REG | MCP251XFD_QUIRK_CRC_RX | 39eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_TX | MCP251XFD_QUIRK_ECC, 40eb79a267SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP2518FD, 411f0e21a0SMarc Kleine-Budde }; 421f0e21a0SMarc Kleine-Budde 431f0e21a0SMarc Kleine-Budde /* Autodetect model, start with CRC enabled. */ 44eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp251xfd = { 45eb79a267SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_CRC_REG | MCP251XFD_QUIRK_CRC_RX | 46eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_TX | MCP251XFD_QUIRK_ECC, 47eb79a267SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP251XFD, 481f0e21a0SMarc Kleine-Budde }; 491f0e21a0SMarc Kleine-Budde 50eb79a267SMarc Kleine-Budde static const struct can_bittiming_const mcp251xfd_bittiming_const = { 511f0e21a0SMarc Kleine-Budde .name = DEVICE_NAME, 521f0e21a0SMarc Kleine-Budde .tseg1_min = 2, 531f0e21a0SMarc Kleine-Budde .tseg1_max = 256, 541f0e21a0SMarc Kleine-Budde .tseg2_min = 1, 551f0e21a0SMarc Kleine-Budde .tseg2_max = 128, 561f0e21a0SMarc Kleine-Budde .sjw_max = 128, 571f0e21a0SMarc Kleine-Budde .brp_min = 1, 581f0e21a0SMarc Kleine-Budde .brp_max = 256, 591f0e21a0SMarc Kleine-Budde .brp_inc = 1, 601f0e21a0SMarc Kleine-Budde }; 611f0e21a0SMarc Kleine-Budde 62eb79a267SMarc Kleine-Budde static const struct can_bittiming_const mcp251xfd_data_bittiming_const = { 631f0e21a0SMarc Kleine-Budde .name = DEVICE_NAME, 641f0e21a0SMarc Kleine-Budde .tseg1_min = 1, 651f0e21a0SMarc Kleine-Budde .tseg1_max = 32, 661f0e21a0SMarc Kleine-Budde .tseg2_min = 1, 671f0e21a0SMarc Kleine-Budde .tseg2_max = 16, 681f0e21a0SMarc Kleine-Budde .sjw_max = 16, 691f0e21a0SMarc Kleine-Budde .brp_min = 1, 701f0e21a0SMarc Kleine-Budde .brp_max = 256, 711f0e21a0SMarc Kleine-Budde .brp_inc = 1, 721f0e21a0SMarc Kleine-Budde }; 731f0e21a0SMarc Kleine-Budde 74eb79a267SMarc Kleine-Budde static const char *__mcp251xfd_get_model_str(enum mcp251xfd_model model) 751f0e21a0SMarc Kleine-Budde { 761f0e21a0SMarc Kleine-Budde switch (model) { 77eb79a267SMarc Kleine-Budde case MCP251XFD_MODEL_MCP2517FD: 7878db1aa8STom Rix return "MCP2517FD"; 79eb79a267SMarc Kleine-Budde case MCP251XFD_MODEL_MCP2518FD: 8078db1aa8STom Rix return "MCP2518FD"; 81eb79a267SMarc Kleine-Budde case MCP251XFD_MODEL_MCP251XFD: 8278db1aa8STom Rix return "MCP251xFD"; 831f0e21a0SMarc Kleine-Budde } 841f0e21a0SMarc Kleine-Budde 851f0e21a0SMarc Kleine-Budde return "<unknown>"; 861f0e21a0SMarc Kleine-Budde } 871f0e21a0SMarc Kleine-Budde 881f0e21a0SMarc Kleine-Budde static inline const char * 89eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(const struct mcp251xfd_priv *priv) 901f0e21a0SMarc Kleine-Budde { 91eb79a267SMarc Kleine-Budde return __mcp251xfd_get_model_str(priv->devtype_data.model); 921f0e21a0SMarc Kleine-Budde } 931f0e21a0SMarc Kleine-Budde 94eb79a267SMarc Kleine-Budde static const char *mcp251xfd_get_mode_str(const u8 mode) 951f0e21a0SMarc Kleine-Budde { 961f0e21a0SMarc Kleine-Budde switch (mode) { 97eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_MIXED: 9878db1aa8STom Rix return "Mixed (CAN FD/CAN 2.0)"; 99eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_SLEEP: 10078db1aa8STom Rix return "Sleep"; 101eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_INT_LOOPBACK: 10278db1aa8STom Rix return "Internal Loopback"; 103eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_LISTENONLY: 10478db1aa8STom Rix return "Listen Only"; 105eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_CONFIG: 10678db1aa8STom Rix return "Configuration"; 107eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_EXT_LOOPBACK: 10878db1aa8STom Rix return "External Loopback"; 109eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_CAN2_0: 11078db1aa8STom Rix return "CAN 2.0"; 111eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_RESTRICTED: 11278db1aa8STom Rix return "Restricted Operation"; 1131f0e21a0SMarc Kleine-Budde } 1141f0e21a0SMarc Kleine-Budde 1151f0e21a0SMarc Kleine-Budde return "<unknown>"; 1161f0e21a0SMarc Kleine-Budde } 1171f0e21a0SMarc Kleine-Budde 118eb79a267SMarc Kleine-Budde static inline int mcp251xfd_vdd_enable(const struct mcp251xfd_priv *priv) 1191f0e21a0SMarc Kleine-Budde { 1201f0e21a0SMarc Kleine-Budde if (!priv->reg_vdd) 1211f0e21a0SMarc Kleine-Budde return 0; 1221f0e21a0SMarc Kleine-Budde 1231f0e21a0SMarc Kleine-Budde return regulator_enable(priv->reg_vdd); 1241f0e21a0SMarc Kleine-Budde } 1251f0e21a0SMarc Kleine-Budde 126eb79a267SMarc Kleine-Budde static inline int mcp251xfd_vdd_disable(const struct mcp251xfd_priv *priv) 1271f0e21a0SMarc Kleine-Budde { 1281f0e21a0SMarc Kleine-Budde if (!priv->reg_vdd) 1291f0e21a0SMarc Kleine-Budde return 0; 1301f0e21a0SMarc Kleine-Budde 1311f0e21a0SMarc Kleine-Budde return regulator_disable(priv->reg_vdd); 1321f0e21a0SMarc Kleine-Budde } 1331f0e21a0SMarc Kleine-Budde 1341f0e21a0SMarc Kleine-Budde static inline int 135eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_enable(const struct mcp251xfd_priv *priv) 1361f0e21a0SMarc Kleine-Budde { 1371f0e21a0SMarc Kleine-Budde if (!priv->reg_xceiver) 1381f0e21a0SMarc Kleine-Budde return 0; 1391f0e21a0SMarc Kleine-Budde 1401f0e21a0SMarc Kleine-Budde return regulator_enable(priv->reg_xceiver); 1411f0e21a0SMarc Kleine-Budde } 1421f0e21a0SMarc Kleine-Budde 1431f0e21a0SMarc Kleine-Budde static inline int 144eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(const struct mcp251xfd_priv *priv) 1451f0e21a0SMarc Kleine-Budde { 1461f0e21a0SMarc Kleine-Budde if (!priv->reg_xceiver) 1471f0e21a0SMarc Kleine-Budde return 0; 1481f0e21a0SMarc Kleine-Budde 1491f0e21a0SMarc Kleine-Budde return regulator_disable(priv->reg_xceiver); 1501f0e21a0SMarc Kleine-Budde } 1511f0e21a0SMarc Kleine-Budde 152eb79a267SMarc Kleine-Budde static int mcp251xfd_clks_and_vdd_enable(const struct mcp251xfd_priv *priv) 1531f0e21a0SMarc Kleine-Budde { 1541f0e21a0SMarc Kleine-Budde int err; 1551f0e21a0SMarc Kleine-Budde 1561f0e21a0SMarc Kleine-Budde err = clk_prepare_enable(priv->clk); 1571f0e21a0SMarc Kleine-Budde if (err) 1581f0e21a0SMarc Kleine-Budde return err; 1591f0e21a0SMarc Kleine-Budde 160eb79a267SMarc Kleine-Budde err = mcp251xfd_vdd_enable(priv); 1611f0e21a0SMarc Kleine-Budde if (err) 1621f0e21a0SMarc Kleine-Budde clk_disable_unprepare(priv->clk); 1631f0e21a0SMarc Kleine-Budde 1641f0e21a0SMarc Kleine-Budde /* Wait for oscillator stabilisation time after power up */ 165eb79a267SMarc Kleine-Budde usleep_range(MCP251XFD_OSC_STAB_SLEEP_US, 166eb79a267SMarc Kleine-Budde 2 * MCP251XFD_OSC_STAB_SLEEP_US); 1671f0e21a0SMarc Kleine-Budde 1681f0e21a0SMarc Kleine-Budde return err; 1691f0e21a0SMarc Kleine-Budde } 1701f0e21a0SMarc Kleine-Budde 171eb79a267SMarc Kleine-Budde static int mcp251xfd_clks_and_vdd_disable(const struct mcp251xfd_priv *priv) 1721f0e21a0SMarc Kleine-Budde { 1731f0e21a0SMarc Kleine-Budde int err; 1741f0e21a0SMarc Kleine-Budde 175eb79a267SMarc Kleine-Budde err = mcp251xfd_vdd_disable(priv); 1761f0e21a0SMarc Kleine-Budde if (err) 1771f0e21a0SMarc Kleine-Budde return err; 1781f0e21a0SMarc Kleine-Budde 1791f0e21a0SMarc Kleine-Budde clk_disable_unprepare(priv->clk); 1801f0e21a0SMarc Kleine-Budde 1811f0e21a0SMarc Kleine-Budde return 0; 1821f0e21a0SMarc Kleine-Budde } 1831f0e21a0SMarc Kleine-Budde 1841f0e21a0SMarc Kleine-Budde static inline u8 185eb79a267SMarc Kleine-Budde mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv, 186eb79a267SMarc Kleine-Budde union mcp251xfd_write_reg_buf *write_reg_buf, 1871f0e21a0SMarc Kleine-Budde const u16 reg, const u32 mask, const u32 val) 1881f0e21a0SMarc Kleine-Budde { 1891f0e21a0SMarc Kleine-Budde u8 first_byte, last_byte, len; 1901f0e21a0SMarc Kleine-Budde u8 *data; 1911f0e21a0SMarc Kleine-Budde __le32 val_le32; 1921f0e21a0SMarc Kleine-Budde 193eb79a267SMarc Kleine-Budde first_byte = mcp251xfd_first_byte_set(mask); 194eb79a267SMarc Kleine-Budde last_byte = mcp251xfd_last_byte_set(mask); 1951f0e21a0SMarc Kleine-Budde len = last_byte - first_byte + 1; 1961f0e21a0SMarc Kleine-Budde 197eb79a267SMarc Kleine-Budde data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte); 1981f0e21a0SMarc Kleine-Budde val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte); 1991f0e21a0SMarc Kleine-Budde memcpy(data, &val_le32, len); 2001f0e21a0SMarc Kleine-Budde 201eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) { 2021f0e21a0SMarc Kleine-Budde u16 crc; 2031f0e21a0SMarc Kleine-Budde 204eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd, 2051f0e21a0SMarc Kleine-Budde len); 2061f0e21a0SMarc Kleine-Budde /* CRC */ 2071f0e21a0SMarc Kleine-Budde len += sizeof(write_reg_buf->crc.cmd); 208eb79a267SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(&write_reg_buf->crc, len); 2091f0e21a0SMarc Kleine-Budde put_unaligned_be16(crc, (void *)write_reg_buf + len); 2101f0e21a0SMarc Kleine-Budde 2111f0e21a0SMarc Kleine-Budde /* Total length */ 2121f0e21a0SMarc Kleine-Budde len += sizeof(write_reg_buf->crc.crc); 2131f0e21a0SMarc Kleine-Budde } else { 2141f0e21a0SMarc Kleine-Budde len += sizeof(write_reg_buf->nocrc.cmd); 2151f0e21a0SMarc Kleine-Budde } 2161f0e21a0SMarc Kleine-Budde 2171f0e21a0SMarc Kleine-Budde return len; 2181f0e21a0SMarc Kleine-Budde } 2191f0e21a0SMarc Kleine-Budde 2201f0e21a0SMarc Kleine-Budde static inline int 221eb79a267SMarc Kleine-Budde mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv, 2221f0e21a0SMarc Kleine-Budde u8 *tef_tail) 2231f0e21a0SMarc Kleine-Budde { 2241f0e21a0SMarc Kleine-Budde u32 tef_ua; 2251f0e21a0SMarc Kleine-Budde int err; 2261f0e21a0SMarc Kleine-Budde 227eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFUA, &tef_ua); 2281f0e21a0SMarc Kleine-Budde if (err) 2291f0e21a0SMarc Kleine-Budde return err; 2301f0e21a0SMarc Kleine-Budde 231eb79a267SMarc Kleine-Budde *tef_tail = tef_ua / sizeof(struct mcp251xfd_hw_tef_obj); 2321f0e21a0SMarc Kleine-Budde 2331f0e21a0SMarc Kleine-Budde return 0; 2341f0e21a0SMarc Kleine-Budde } 2351f0e21a0SMarc Kleine-Budde 2361f0e21a0SMarc Kleine-Budde static inline int 237eb79a267SMarc Kleine-Budde mcp251xfd_tx_tail_get_from_chip(const struct mcp251xfd_priv *priv, 2381f0e21a0SMarc Kleine-Budde u8 *tx_tail) 2391f0e21a0SMarc Kleine-Budde { 2401f0e21a0SMarc Kleine-Budde u32 fifo_sta; 2411f0e21a0SMarc Kleine-Budde int err; 2421f0e21a0SMarc Kleine-Budde 2431f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, 244eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA(MCP251XFD_TX_FIFO), 2451f0e21a0SMarc Kleine-Budde &fifo_sta); 2461f0e21a0SMarc Kleine-Budde if (err) 2471f0e21a0SMarc Kleine-Budde return err; 2481f0e21a0SMarc Kleine-Budde 249eb79a267SMarc Kleine-Budde *tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta); 2501f0e21a0SMarc Kleine-Budde 2511f0e21a0SMarc Kleine-Budde return 0; 2521f0e21a0SMarc Kleine-Budde } 2531f0e21a0SMarc Kleine-Budde 2541f0e21a0SMarc Kleine-Budde static inline int 255eb79a267SMarc Kleine-Budde mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv, 256eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring, 2571f0e21a0SMarc Kleine-Budde u8 *rx_head) 2581f0e21a0SMarc Kleine-Budde { 2591f0e21a0SMarc Kleine-Budde u32 fifo_sta; 2601f0e21a0SMarc Kleine-Budde int err; 2611f0e21a0SMarc Kleine-Budde 262eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(ring->fifo_nr), 2631f0e21a0SMarc Kleine-Budde &fifo_sta); 2641f0e21a0SMarc Kleine-Budde if (err) 2651f0e21a0SMarc Kleine-Budde return err; 2661f0e21a0SMarc Kleine-Budde 267eb79a267SMarc Kleine-Budde *rx_head = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta); 2681f0e21a0SMarc Kleine-Budde 2691f0e21a0SMarc Kleine-Budde return 0; 2701f0e21a0SMarc Kleine-Budde } 2711f0e21a0SMarc Kleine-Budde 2721f0e21a0SMarc Kleine-Budde static inline int 273eb79a267SMarc Kleine-Budde mcp251xfd_rx_tail_get_from_chip(const struct mcp251xfd_priv *priv, 274eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring, 2751f0e21a0SMarc Kleine-Budde u8 *rx_tail) 2761f0e21a0SMarc Kleine-Budde { 2771f0e21a0SMarc Kleine-Budde u32 fifo_ua; 2781f0e21a0SMarc Kleine-Budde int err; 2791f0e21a0SMarc Kleine-Budde 280eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOUA(ring->fifo_nr), 2811f0e21a0SMarc Kleine-Budde &fifo_ua); 2821f0e21a0SMarc Kleine-Budde if (err) 2831f0e21a0SMarc Kleine-Budde return err; 2841f0e21a0SMarc Kleine-Budde 285eb79a267SMarc Kleine-Budde fifo_ua -= ring->base - MCP251XFD_RAM_START; 2861f0e21a0SMarc Kleine-Budde *rx_tail = fifo_ua / ring->obj_size; 2871f0e21a0SMarc Kleine-Budde 2881f0e21a0SMarc Kleine-Budde return 0; 2891f0e21a0SMarc Kleine-Budde } 2901f0e21a0SMarc Kleine-Budde 2911f0e21a0SMarc Kleine-Budde static void 292eb79a267SMarc Kleine-Budde mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv, 293eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *ring, 294eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj, 2951f0e21a0SMarc Kleine-Budde const u8 rts_buf_len, 2961f0e21a0SMarc Kleine-Budde const u8 n) 2971f0e21a0SMarc Kleine-Budde { 2981f0e21a0SMarc Kleine-Budde struct spi_transfer *xfer; 2991f0e21a0SMarc Kleine-Budde u16 addr; 3001f0e21a0SMarc Kleine-Budde 3011f0e21a0SMarc Kleine-Budde /* FIFO load */ 302eb79a267SMarc Kleine-Budde addr = mcp251xfd_get_tx_obj_addr(ring, n); 303eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) 304eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_write_crc_set_addr(&tx_obj->buf.crc.cmd, 3051f0e21a0SMarc Kleine-Budde addr); 3061f0e21a0SMarc Kleine-Budde else 307eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_write_nocrc(&tx_obj->buf.nocrc.cmd, 3081f0e21a0SMarc Kleine-Budde addr); 3091f0e21a0SMarc Kleine-Budde 3101f0e21a0SMarc Kleine-Budde xfer = &tx_obj->xfer[0]; 3111f0e21a0SMarc Kleine-Budde xfer->tx_buf = &tx_obj->buf; 3121f0e21a0SMarc Kleine-Budde xfer->len = 0; /* actual len is assigned on the fly */ 3131f0e21a0SMarc Kleine-Budde xfer->cs_change = 1; 3141f0e21a0SMarc Kleine-Budde xfer->cs_change_delay.value = 0; 3151f0e21a0SMarc Kleine-Budde xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 3161f0e21a0SMarc Kleine-Budde 3171f0e21a0SMarc Kleine-Budde /* FIFO request to send */ 3181f0e21a0SMarc Kleine-Budde xfer = &tx_obj->xfer[1]; 3191f0e21a0SMarc Kleine-Budde xfer->tx_buf = &ring->rts_buf; 3201f0e21a0SMarc Kleine-Budde xfer->len = rts_buf_len; 3211f0e21a0SMarc Kleine-Budde 3221f0e21a0SMarc Kleine-Budde /* SPI message */ 3231f0e21a0SMarc Kleine-Budde spi_message_init_with_transfers(&tx_obj->msg, tx_obj->xfer, 3241f0e21a0SMarc Kleine-Budde ARRAY_SIZE(tx_obj->xfer)); 3251f0e21a0SMarc Kleine-Budde } 3261f0e21a0SMarc Kleine-Budde 327eb79a267SMarc Kleine-Budde static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv) 3281f0e21a0SMarc Kleine-Budde { 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; 3321f0e21a0SMarc Kleine-Budde u32 val; 3331f0e21a0SMarc Kleine-Budde u16 addr; 3341f0e21a0SMarc Kleine-Budde u8 len; 3351f0e21a0SMarc Kleine-Budde int i; 3361f0e21a0SMarc Kleine-Budde 3371f0e21a0SMarc Kleine-Budde /* TEF */ 3381f0e21a0SMarc Kleine-Budde priv->tef.head = 0; 3391f0e21a0SMarc Kleine-Budde priv->tef.tail = 0; 3401f0e21a0SMarc Kleine-Budde 3411f0e21a0SMarc Kleine-Budde /* TX */ 3421f0e21a0SMarc Kleine-Budde tx_ring = priv->tx; 3431f0e21a0SMarc Kleine-Budde tx_ring->head = 0; 3441f0e21a0SMarc Kleine-Budde tx_ring->tail = 0; 345eb79a267SMarc Kleine-Budde tx_ring->base = mcp251xfd_get_tef_obj_addr(tx_ring->obj_num); 3461f0e21a0SMarc Kleine-Budde 3471f0e21a0SMarc Kleine-Budde /* FIFO request to send */ 348eb79a267SMarc Kleine-Budde addr = MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO); 349eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC; 350eb79a267SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf, 3511f0e21a0SMarc Kleine-Budde addr, val, val); 3521f0e21a0SMarc Kleine-Budde 353eb79a267SMarc Kleine-Budde mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i) 354eb79a267SMarc Kleine-Budde mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i); 3551f0e21a0SMarc Kleine-Budde 3561f0e21a0SMarc Kleine-Budde /* RX */ 357eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { 3581f0e21a0SMarc Kleine-Budde rx_ring->head = 0; 3591f0e21a0SMarc Kleine-Budde rx_ring->tail = 0; 3601f0e21a0SMarc Kleine-Budde rx_ring->nr = i; 361eb79a267SMarc Kleine-Budde rx_ring->fifo_nr = MCP251XFD_RX_FIFO(i); 3621f0e21a0SMarc Kleine-Budde 3631f0e21a0SMarc Kleine-Budde if (!prev_rx_ring) 3641f0e21a0SMarc Kleine-Budde rx_ring->base = 365eb79a267SMarc Kleine-Budde mcp251xfd_get_tx_obj_addr(tx_ring, 3661f0e21a0SMarc Kleine-Budde tx_ring->obj_num); 3671f0e21a0SMarc Kleine-Budde else 3681f0e21a0SMarc Kleine-Budde rx_ring->base = prev_rx_ring->base + 3691f0e21a0SMarc Kleine-Budde prev_rx_ring->obj_size * 3701f0e21a0SMarc Kleine-Budde prev_rx_ring->obj_num; 3711f0e21a0SMarc Kleine-Budde 3721f0e21a0SMarc Kleine-Budde prev_rx_ring = rx_ring; 3731f0e21a0SMarc Kleine-Budde } 3741f0e21a0SMarc Kleine-Budde } 3751f0e21a0SMarc Kleine-Budde 376eb79a267SMarc Kleine-Budde static void mcp251xfd_ring_free(struct mcp251xfd_priv *priv) 3771f0e21a0SMarc Kleine-Budde { 3781f0e21a0SMarc Kleine-Budde int i; 3791f0e21a0SMarc Kleine-Budde 3801f0e21a0SMarc Kleine-Budde for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) { 3811f0e21a0SMarc Kleine-Budde kfree(priv->rx[i]); 3821f0e21a0SMarc Kleine-Budde priv->rx[i] = NULL; 3831f0e21a0SMarc Kleine-Budde } 3841f0e21a0SMarc Kleine-Budde } 3851f0e21a0SMarc Kleine-Budde 386eb79a267SMarc Kleine-Budde static int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv) 3871f0e21a0SMarc Kleine-Budde { 388eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring; 389eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *rx_ring; 3901f0e21a0SMarc Kleine-Budde int tef_obj_size, tx_obj_size, rx_obj_size; 3911f0e21a0SMarc Kleine-Budde int tx_obj_num; 3921f0e21a0SMarc Kleine-Budde int ram_free, i; 3931f0e21a0SMarc Kleine-Budde 394eb79a267SMarc Kleine-Budde tef_obj_size = sizeof(struct mcp251xfd_hw_tef_obj); 3951f0e21a0SMarc Kleine-Budde /* listen-only mode works like FD mode */ 3961f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) { 397eb79a267SMarc Kleine-Budde tx_obj_num = MCP251XFD_TX_OBJ_NUM_CANFD; 398eb79a267SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd); 399eb79a267SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd); 4001f0e21a0SMarc Kleine-Budde } else { 401eb79a267SMarc Kleine-Budde tx_obj_num = MCP251XFD_TX_OBJ_NUM_CAN; 402eb79a267SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can); 403eb79a267SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can); 4041f0e21a0SMarc Kleine-Budde } 4051f0e21a0SMarc Kleine-Budde 4061f0e21a0SMarc Kleine-Budde tx_ring = priv->tx; 4071f0e21a0SMarc Kleine-Budde tx_ring->obj_num = tx_obj_num; 4081f0e21a0SMarc Kleine-Budde tx_ring->obj_size = tx_obj_size; 4091f0e21a0SMarc Kleine-Budde 410eb79a267SMarc Kleine-Budde ram_free = MCP251XFD_RAM_SIZE - tx_obj_num * 4111f0e21a0SMarc Kleine-Budde (tef_obj_size + tx_obj_size); 4121f0e21a0SMarc Kleine-Budde 4131f0e21a0SMarc Kleine-Budde for (i = 0; 4141f0e21a0SMarc Kleine-Budde i < ARRAY_SIZE(priv->rx) && ram_free >= rx_obj_size; 4151f0e21a0SMarc Kleine-Budde i++) { 4161f0e21a0SMarc Kleine-Budde int rx_obj_num; 4171f0e21a0SMarc Kleine-Budde 4181f0e21a0SMarc Kleine-Budde rx_obj_num = ram_free / rx_obj_size; 419*4843ad9bSMarc Kleine-Budde rx_obj_num = min(1 << (fls(rx_obj_num) - 1), 420*4843ad9bSMarc Kleine-Budde MCP251XFD_RX_OBJ_NUM_MAX); 4211f0e21a0SMarc Kleine-Budde 4221f0e21a0SMarc Kleine-Budde rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num, 4231f0e21a0SMarc Kleine-Budde GFP_KERNEL); 4241f0e21a0SMarc Kleine-Budde if (!rx_ring) { 425eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 4261f0e21a0SMarc Kleine-Budde return -ENOMEM; 4271f0e21a0SMarc Kleine-Budde } 4281f0e21a0SMarc Kleine-Budde rx_ring->obj_num = rx_obj_num; 4291f0e21a0SMarc Kleine-Budde rx_ring->obj_size = rx_obj_size; 4301f0e21a0SMarc Kleine-Budde priv->rx[i] = rx_ring; 4311f0e21a0SMarc Kleine-Budde 4321f0e21a0SMarc Kleine-Budde ram_free -= rx_ring->obj_num * rx_ring->obj_size; 4331f0e21a0SMarc Kleine-Budde } 4341f0e21a0SMarc Kleine-Budde priv->rx_ring_num = i; 4351f0e21a0SMarc Kleine-Budde 4361f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4371f0e21a0SMarc Kleine-Budde "FIFO setup: TEF: %d*%d bytes = %d bytes, TX: %d*%d bytes = %d bytes\n", 4381f0e21a0SMarc Kleine-Budde tx_obj_num, tef_obj_size, tef_obj_size * tx_obj_num, 4391f0e21a0SMarc Kleine-Budde tx_obj_num, tx_obj_size, tx_obj_size * tx_obj_num); 4401f0e21a0SMarc Kleine-Budde 441eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { 4421f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4431f0e21a0SMarc Kleine-Budde "FIFO setup: RX-%d: %d*%d bytes = %d bytes\n", 4441f0e21a0SMarc Kleine-Budde i, rx_ring->obj_num, rx_ring->obj_size, 4451f0e21a0SMarc Kleine-Budde rx_ring->obj_size * rx_ring->obj_num); 4461f0e21a0SMarc Kleine-Budde } 4471f0e21a0SMarc Kleine-Budde 4481f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4491f0e21a0SMarc Kleine-Budde "FIFO setup: free: %d bytes\n", 4501f0e21a0SMarc Kleine-Budde ram_free); 4511f0e21a0SMarc Kleine-Budde 4521f0e21a0SMarc Kleine-Budde return 0; 4531f0e21a0SMarc Kleine-Budde } 4541f0e21a0SMarc Kleine-Budde 4551f0e21a0SMarc Kleine-Budde static inline int 456eb79a267SMarc Kleine-Budde mcp251xfd_chip_get_mode(const struct mcp251xfd_priv *priv, u8 *mode) 4571f0e21a0SMarc Kleine-Budde { 4581f0e21a0SMarc Kleine-Budde u32 val; 4591f0e21a0SMarc Kleine-Budde int err; 4601f0e21a0SMarc Kleine-Budde 461eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_CON, &val); 4621f0e21a0SMarc Kleine-Budde if (err) 4631f0e21a0SMarc Kleine-Budde return err; 4641f0e21a0SMarc Kleine-Budde 465eb79a267SMarc Kleine-Budde *mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, val); 4661f0e21a0SMarc Kleine-Budde 4671f0e21a0SMarc Kleine-Budde return 0; 4681f0e21a0SMarc Kleine-Budde } 4691f0e21a0SMarc Kleine-Budde 4701f0e21a0SMarc Kleine-Budde static int 471eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv, 4721f0e21a0SMarc Kleine-Budde const u8 mode_req, bool nowait) 4731f0e21a0SMarc Kleine-Budde { 4741f0e21a0SMarc Kleine-Budde u32 con, con_reqop; 4751f0e21a0SMarc Kleine-Budde int err; 4761f0e21a0SMarc Kleine-Budde 477eb79a267SMarc Kleine-Budde con_reqop = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, mode_req); 478eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CON, 479eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_REQOP_MASK, con_reqop); 4801f0e21a0SMarc Kleine-Budde if (err) 4811f0e21a0SMarc Kleine-Budde return err; 4821f0e21a0SMarc Kleine-Budde 483eb79a267SMarc Kleine-Budde if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait) 4841f0e21a0SMarc Kleine-Budde return 0; 4851f0e21a0SMarc Kleine-Budde 486eb79a267SMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con, 487eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, 4881f0e21a0SMarc Kleine-Budde con) == mode_req, 489eb79a267SMarc Kleine-Budde MCP251XFD_POLL_SLEEP_US, 490eb79a267SMarc Kleine-Budde MCP251XFD_POLL_TIMEOUT_US); 4911f0e21a0SMarc Kleine-Budde if (err) { 492eb79a267SMarc Kleine-Budde u8 mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, con); 4931f0e21a0SMarc Kleine-Budde 4941f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 4951f0e21a0SMarc Kleine-Budde "Controller failed to enter mode %s Mode (%u) and stays in %s Mode (%u).\n", 496eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode_req), mode_req, 497eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 4981f0e21a0SMarc Kleine-Budde return err; 4991f0e21a0SMarc Kleine-Budde } 5001f0e21a0SMarc Kleine-Budde 5011f0e21a0SMarc Kleine-Budde return 0; 5021f0e21a0SMarc Kleine-Budde } 5031f0e21a0SMarc Kleine-Budde 5041f0e21a0SMarc Kleine-Budde static inline int 505eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv, 5061f0e21a0SMarc Kleine-Budde const u8 mode_req) 5071f0e21a0SMarc Kleine-Budde { 508eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode_req, false); 5091f0e21a0SMarc Kleine-Budde } 5101f0e21a0SMarc Kleine-Budde 5111f0e21a0SMarc Kleine-Budde static inline int 512eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode_nowait(const struct mcp251xfd_priv *priv, 5131f0e21a0SMarc Kleine-Budde const u8 mode_req) 5141f0e21a0SMarc Kleine-Budde { 515eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode_req, true); 5161f0e21a0SMarc Kleine-Budde } 5171f0e21a0SMarc Kleine-Budde 518eb79a267SMarc Kleine-Budde static inline bool mcp251xfd_osc_invalid(u32 reg) 5191f0e21a0SMarc Kleine-Budde { 5201f0e21a0SMarc Kleine-Budde return reg == 0x0 || reg == 0xffffffff; 5211f0e21a0SMarc Kleine-Budde } 5221f0e21a0SMarc Kleine-Budde 523eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_clock_enable(const struct mcp251xfd_priv *priv) 5241f0e21a0SMarc Kleine-Budde { 5251f0e21a0SMarc Kleine-Budde u32 osc, osc_reference, osc_mask; 5261f0e21a0SMarc Kleine-Budde int err; 5271f0e21a0SMarc Kleine-Budde 5281f0e21a0SMarc Kleine-Budde /* Set Power On Defaults for "Clock Output Divisor" and remove 5291f0e21a0SMarc Kleine-Budde * "Oscillator Disable" bit. 5301f0e21a0SMarc Kleine-Budde */ 531eb79a267SMarc Kleine-Budde osc = FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 532eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 533eb79a267SMarc Kleine-Budde osc_reference = MCP251XFD_REG_OSC_OSCRDY; 534eb79a267SMarc Kleine-Budde osc_mask = MCP251XFD_REG_OSC_OSCRDY | MCP251XFD_REG_OSC_PLLRDY; 5351f0e21a0SMarc Kleine-Budde 5361f0e21a0SMarc Kleine-Budde /* Note: 5371f0e21a0SMarc Kleine-Budde * 5381f0e21a0SMarc Kleine-Budde * If the controller is in Sleep Mode the following write only 5391f0e21a0SMarc Kleine-Budde * removes the "Oscillator Disable" bit and powers it up. All 5401f0e21a0SMarc Kleine-Budde * other bits are unaffected. 5411f0e21a0SMarc Kleine-Budde */ 542eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc); 5431f0e21a0SMarc Kleine-Budde if (err) 5441f0e21a0SMarc Kleine-Budde return err; 5451f0e21a0SMarc Kleine-Budde 5461f0e21a0SMarc Kleine-Budde /* Wait for "Oscillator Ready" bit */ 547eb79a267SMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_OSC, osc, 5481f0e21a0SMarc Kleine-Budde (osc & osc_mask) == osc_reference, 549eb79a267SMarc Kleine-Budde MCP251XFD_OSC_STAB_SLEEP_US, 550eb79a267SMarc Kleine-Budde MCP251XFD_OSC_STAB_TIMEOUT_US); 551eb79a267SMarc Kleine-Budde if (mcp251xfd_osc_invalid(osc)) { 5521f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 5531f0e21a0SMarc Kleine-Budde "Failed to detect %s (osc=0x%08x).\n", 554eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv), osc); 5551f0e21a0SMarc Kleine-Budde return -ENODEV; 5561f0e21a0SMarc Kleine-Budde } else if (err == -ETIMEDOUT) { 5571f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 5581f0e21a0SMarc Kleine-Budde "Timeout waiting for Oscillator Ready (osc=0x%08x, osc_reference=0x%08x)\n", 5591f0e21a0SMarc Kleine-Budde osc, osc_reference); 5601f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 5611f0e21a0SMarc Kleine-Budde } else if (err) { 5621f0e21a0SMarc Kleine-Budde return err; 5631f0e21a0SMarc Kleine-Budde } 5641f0e21a0SMarc Kleine-Budde 5651f0e21a0SMarc Kleine-Budde return 0; 5661f0e21a0SMarc Kleine-Budde } 5671f0e21a0SMarc Kleine-Budde 568eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_do(const struct mcp251xfd_priv *priv) 5691f0e21a0SMarc Kleine-Budde { 570eb79a267SMarc Kleine-Budde const __be16 cmd = mcp251xfd_cmd_reset(); 5711f0e21a0SMarc Kleine-Budde int err; 5721f0e21a0SMarc Kleine-Budde 5731f0e21a0SMarc Kleine-Budde /* The Set Mode and SPI Reset command only seems to works if 5741f0e21a0SMarc Kleine-Budde * the controller is not in Sleep Mode. 5751f0e21a0SMarc Kleine-Budde */ 576eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_clock_enable(priv); 5771f0e21a0SMarc Kleine-Budde if (err) 5781f0e21a0SMarc Kleine-Budde return err; 5791f0e21a0SMarc Kleine-Budde 580eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_CONFIG); 5811f0e21a0SMarc Kleine-Budde if (err) 5821f0e21a0SMarc Kleine-Budde return err; 5831f0e21a0SMarc Kleine-Budde 5841f0e21a0SMarc Kleine-Budde /* spi_write_then_read() works with non DMA-safe buffers */ 5851f0e21a0SMarc Kleine-Budde return spi_write_then_read(priv->spi, &cmd, sizeof(cmd), NULL, 0); 5861f0e21a0SMarc Kleine-Budde } 5871f0e21a0SMarc Kleine-Budde 588eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_check(const struct mcp251xfd_priv *priv) 5891f0e21a0SMarc Kleine-Budde { 5901f0e21a0SMarc Kleine-Budde u32 osc, osc_reference; 5911f0e21a0SMarc Kleine-Budde u8 mode; 5921f0e21a0SMarc Kleine-Budde int err; 5931f0e21a0SMarc Kleine-Budde 594eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_get_mode(priv, &mode); 5951f0e21a0SMarc Kleine-Budde if (err) 5961f0e21a0SMarc Kleine-Budde return err; 5971f0e21a0SMarc Kleine-Budde 598eb79a267SMarc Kleine-Budde if (mode != MCP251XFD_REG_CON_MODE_CONFIG) { 5991f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 6001f0e21a0SMarc Kleine-Budde "Controller not in Config Mode after reset, but in %s Mode (%u).\n", 601eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 6021f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6031f0e21a0SMarc Kleine-Budde } 6041f0e21a0SMarc Kleine-Budde 605eb79a267SMarc Kleine-Budde osc_reference = MCP251XFD_REG_OSC_OSCRDY | 606eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 607eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 6081f0e21a0SMarc Kleine-Budde 6091f0e21a0SMarc Kleine-Budde /* check reset defaults of OSC reg */ 610eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc); 6111f0e21a0SMarc Kleine-Budde if (err) 6121f0e21a0SMarc Kleine-Budde return err; 6131f0e21a0SMarc Kleine-Budde 6141f0e21a0SMarc Kleine-Budde if (osc != osc_reference) { 6151f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 6161f0e21a0SMarc Kleine-Budde "Controller failed to reset. osc=0x%08x, reference value=0x%08x\n", 6171f0e21a0SMarc Kleine-Budde osc, osc_reference); 6181f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6191f0e21a0SMarc Kleine-Budde } 6201f0e21a0SMarc Kleine-Budde 6211f0e21a0SMarc Kleine-Budde return 0; 6221f0e21a0SMarc Kleine-Budde } 6231f0e21a0SMarc Kleine-Budde 624eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset(const struct mcp251xfd_priv *priv) 6251f0e21a0SMarc Kleine-Budde { 6261f0e21a0SMarc Kleine-Budde int err, i; 6271f0e21a0SMarc Kleine-Budde 628eb79a267SMarc Kleine-Budde for (i = 0; i < MCP251XFD_SOFTRESET_RETRIES_MAX; i++) { 6291f0e21a0SMarc Kleine-Budde if (i) 6301f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 6311f0e21a0SMarc Kleine-Budde "Retrying to reset Controller.\n"); 6321f0e21a0SMarc Kleine-Budde 633eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset_do(priv); 6341f0e21a0SMarc Kleine-Budde if (err == -ETIMEDOUT) 6351f0e21a0SMarc Kleine-Budde continue; 6361f0e21a0SMarc Kleine-Budde if (err) 6371f0e21a0SMarc Kleine-Budde return err; 6381f0e21a0SMarc Kleine-Budde 639eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset_check(priv); 6401f0e21a0SMarc Kleine-Budde if (err == -ETIMEDOUT) 6411f0e21a0SMarc Kleine-Budde continue; 6421f0e21a0SMarc Kleine-Budde if (err) 6431f0e21a0SMarc Kleine-Budde return err; 6441f0e21a0SMarc Kleine-Budde 6451f0e21a0SMarc Kleine-Budde return 0; 6461f0e21a0SMarc Kleine-Budde } 6471f0e21a0SMarc Kleine-Budde 6481f0e21a0SMarc Kleine-Budde return err; 6491f0e21a0SMarc Kleine-Budde } 6501f0e21a0SMarc Kleine-Budde 651eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_clock_init(const struct mcp251xfd_priv *priv) 6521f0e21a0SMarc Kleine-Budde { 6531f0e21a0SMarc Kleine-Budde u32 osc; 6541f0e21a0SMarc Kleine-Budde int err; 6551f0e21a0SMarc Kleine-Budde 6561f0e21a0SMarc Kleine-Budde /* Activate Low Power Mode on Oscillator Disable. This only 6571f0e21a0SMarc Kleine-Budde * works on the MCP2518FD. The MCP2517FD will go into normal 6581f0e21a0SMarc Kleine-Budde * Sleep Mode instead. 6591f0e21a0SMarc Kleine-Budde */ 660eb79a267SMarc Kleine-Budde osc = MCP251XFD_REG_OSC_LPMEN | 661eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 662eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 663eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc); 6641f0e21a0SMarc Kleine-Budde if (err) 6651f0e21a0SMarc Kleine-Budde return err; 6661f0e21a0SMarc Kleine-Budde 6671f0e21a0SMarc Kleine-Budde /* Set Time Base Counter Prescaler to 1. 6681f0e21a0SMarc Kleine-Budde * 6691f0e21a0SMarc Kleine-Budde * This means an overflow of the 32 bit Time Base Counter 6701f0e21a0SMarc Kleine-Budde * register at 40 MHz every 107 seconds. 6711f0e21a0SMarc Kleine-Budde */ 672eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_TSCON, 673eb79a267SMarc Kleine-Budde MCP251XFD_REG_TSCON_TBCEN); 6741f0e21a0SMarc Kleine-Budde } 6751f0e21a0SMarc Kleine-Budde 676eb79a267SMarc Kleine-Budde static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv) 6771f0e21a0SMarc Kleine-Budde { 6781f0e21a0SMarc Kleine-Budde const struct can_bittiming *bt = &priv->can.bittiming; 6791f0e21a0SMarc Kleine-Budde const struct can_bittiming *dbt = &priv->can.data_bittiming; 6801f0e21a0SMarc Kleine-Budde u32 val = 0; 6811f0e21a0SMarc Kleine-Budde s8 tdco; 6821f0e21a0SMarc Kleine-Budde int err; 6831f0e21a0SMarc Kleine-Budde 6841f0e21a0SMarc Kleine-Budde /* CAN Control Register 6851f0e21a0SMarc Kleine-Budde * 6861f0e21a0SMarc Kleine-Budde * - no transmit bandwidth sharing 6871f0e21a0SMarc Kleine-Budde * - config mode 6881f0e21a0SMarc Kleine-Budde * - disable transmit queue 6891f0e21a0SMarc Kleine-Budde * - store in transmit FIFO event 6901f0e21a0SMarc Kleine-Budde * - transition to restricted operation mode on system error 6911f0e21a0SMarc Kleine-Budde * - ESI is transmitted recessive when ESI of message is high or 6921f0e21a0SMarc Kleine-Budde * CAN controller error passive 6931f0e21a0SMarc Kleine-Budde * - restricted retransmission attempts, 6941f0e21a0SMarc Kleine-Budde * use TQXCON_TXAT and FIFOCON_TXAT 6951f0e21a0SMarc Kleine-Budde * - wake-up filter bits T11FILTER 6961f0e21a0SMarc Kleine-Budde * - use CAN bus line filter for wakeup 6971f0e21a0SMarc Kleine-Budde * - protocol exception is treated as a form error 6981f0e21a0SMarc Kleine-Budde * - Do not compare data bytes 6991f0e21a0SMarc Kleine-Budde */ 700eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, 701eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_MODE_CONFIG) | 702eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_STEF | 703eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_ESIGM | 704eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_RTXAT | 705eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_CON_WFT_MASK, 706eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_WFT_T11FILTER) | 707eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_WAKFIL | 708eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_PXEDIS; 7091f0e21a0SMarc Kleine-Budde 7101f0e21a0SMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)) 711eb79a267SMarc Kleine-Budde val |= MCP251XFD_REG_CON_ISOCRCEN; 7121f0e21a0SMarc Kleine-Budde 713eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_CON, val); 7141f0e21a0SMarc Kleine-Budde if (err) 7151f0e21a0SMarc Kleine-Budde return err; 7161f0e21a0SMarc Kleine-Budde 7171f0e21a0SMarc Kleine-Budde /* Nominal Bit Time */ 718eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_NBTCFG_BRP_MASK, bt->brp - 1) | 719eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG1_MASK, 7201f0e21a0SMarc Kleine-Budde bt->prop_seg + bt->phase_seg1 - 1) | 721eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG2_MASK, 7221f0e21a0SMarc Kleine-Budde bt->phase_seg2 - 1) | 723eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_SJW_MASK, bt->sjw - 1); 7241f0e21a0SMarc Kleine-Budde 725eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_NBTCFG, val); 7261f0e21a0SMarc Kleine-Budde if (err) 7271f0e21a0SMarc Kleine-Budde return err; 7281f0e21a0SMarc Kleine-Budde 7291f0e21a0SMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD)) 7301f0e21a0SMarc Kleine-Budde return 0; 7311f0e21a0SMarc Kleine-Budde 7321f0e21a0SMarc Kleine-Budde /* Data Bit Time */ 733eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_DBTCFG_BRP_MASK, dbt->brp - 1) | 734eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG1_MASK, 7351f0e21a0SMarc Kleine-Budde dbt->prop_seg + dbt->phase_seg1 - 1) | 736eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG2_MASK, 7371f0e21a0SMarc Kleine-Budde dbt->phase_seg2 - 1) | 738eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_SJW_MASK, dbt->sjw - 1); 7391f0e21a0SMarc Kleine-Budde 740eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_DBTCFG, val); 7411f0e21a0SMarc Kleine-Budde if (err) 7421f0e21a0SMarc Kleine-Budde return err; 7431f0e21a0SMarc Kleine-Budde 7441f0e21a0SMarc Kleine-Budde /* Transmitter Delay Compensation */ 7451f0e21a0SMarc Kleine-Budde tdco = clamp_t(int, dbt->brp * (dbt->prop_seg + dbt->phase_seg1), 7461f0e21a0SMarc Kleine-Budde -64, 63); 747eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, 748eb79a267SMarc Kleine-Budde MCP251XFD_REG_TDC_TDCMOD_AUTO) | 749eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, tdco); 7501f0e21a0SMarc Kleine-Budde 751eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val); 7521f0e21a0SMarc Kleine-Budde } 7531f0e21a0SMarc Kleine-Budde 754eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_enable(const struct mcp251xfd_priv *priv) 7551f0e21a0SMarc Kleine-Budde { 7561f0e21a0SMarc Kleine-Budde u32 val; 7571f0e21a0SMarc Kleine-Budde 7581f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 7591f0e21a0SMarc Kleine-Budde return 0; 7601f0e21a0SMarc Kleine-Budde 7611f0e21a0SMarc Kleine-Budde /* Configure GPIOs: 7621f0e21a0SMarc Kleine-Budde * - PIN0: GPIO Input 7631f0e21a0SMarc Kleine-Budde * - PIN1: GPIO Input/RX Interrupt 7641f0e21a0SMarc Kleine-Budde * 7651f0e21a0SMarc Kleine-Budde * PIN1 must be Input, otherwise there is a glitch on the 7661f0e21a0SMarc Kleine-Budde * rx-INT line. It happens between setting the PIN as output 7671f0e21a0SMarc Kleine-Budde * (in the first byte of the SPI transfer) and configuring the 7681f0e21a0SMarc Kleine-Budde * PIN as interrupt (in the last byte of the SPI transfer). 7691f0e21a0SMarc Kleine-Budde */ 770eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_IOCON_PM0 | MCP251XFD_REG_IOCON_TRIS1 | 771eb79a267SMarc Kleine-Budde MCP251XFD_REG_IOCON_TRIS0; 772eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val); 7731f0e21a0SMarc Kleine-Budde } 7741f0e21a0SMarc Kleine-Budde 775eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_disable(const struct mcp251xfd_priv *priv) 7761f0e21a0SMarc Kleine-Budde { 7771f0e21a0SMarc Kleine-Budde u32 val; 7781f0e21a0SMarc Kleine-Budde 7791f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 7801f0e21a0SMarc Kleine-Budde return 0; 7811f0e21a0SMarc Kleine-Budde 7821f0e21a0SMarc Kleine-Budde /* Configure GPIOs: 7831f0e21a0SMarc Kleine-Budde * - PIN0: GPIO Input 7841f0e21a0SMarc Kleine-Budde * - PIN1: GPIO Input 7851f0e21a0SMarc Kleine-Budde */ 786eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_IOCON_PM1 | MCP251XFD_REG_IOCON_PM0 | 787eb79a267SMarc Kleine-Budde MCP251XFD_REG_IOCON_TRIS1 | MCP251XFD_REG_IOCON_TRIS0; 788eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val); 7891f0e21a0SMarc Kleine-Budde } 7901f0e21a0SMarc Kleine-Budde 7911f0e21a0SMarc Kleine-Budde static int 792eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_fifo_init_one(const struct mcp251xfd_priv *priv, 793eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring) 7941f0e21a0SMarc Kleine-Budde { 7951f0e21a0SMarc Kleine-Budde u32 fifo_con; 7961f0e21a0SMarc Kleine-Budde 7971f0e21a0SMarc Kleine-Budde /* Enable RXOVIE on _all_ RX FIFOs, not just the last one. 7981f0e21a0SMarc Kleine-Budde * 7991f0e21a0SMarc Kleine-Budde * FIFOs hit by a RX MAB overflow and RXOVIE enabled will 8001f0e21a0SMarc Kleine-Budde * generate a RXOVIF, use this to properly detect RX MAB 8011f0e21a0SMarc Kleine-Budde * overflows. 8021f0e21a0SMarc Kleine-Budde */ 803eb79a267SMarc Kleine-Budde fifo_con = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK, 8041f0e21a0SMarc Kleine-Budde ring->obj_num - 1) | 805eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_RXTSEN | 806eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_RXOVIE | 807eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TFNRFNIE; 8081f0e21a0SMarc Kleine-Budde 8091f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) 810eb79a267SMarc Kleine-Budde fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 811eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_64); 8121f0e21a0SMarc Kleine-Budde else 813eb79a267SMarc Kleine-Budde fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 814eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_8); 8151f0e21a0SMarc Kleine-Budde 8161f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, 817eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON(ring->fifo_nr), fifo_con); 8181f0e21a0SMarc Kleine-Budde } 8191f0e21a0SMarc Kleine-Budde 8201f0e21a0SMarc Kleine-Budde static int 821eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_filter_init_one(const struct mcp251xfd_priv *priv, 822eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring) 8231f0e21a0SMarc Kleine-Budde { 8241f0e21a0SMarc Kleine-Budde u32 fltcon; 8251f0e21a0SMarc Kleine-Budde 826eb79a267SMarc Kleine-Budde fltcon = MCP251XFD_REG_FLTCON_FLTEN(ring->nr) | 827eb79a267SMarc Kleine-Budde MCP251XFD_REG_FLTCON_FBP(ring->nr, ring->fifo_nr); 8281f0e21a0SMarc Kleine-Budde 8291f0e21a0SMarc Kleine-Budde return regmap_update_bits(priv->map_reg, 830eb79a267SMarc Kleine-Budde MCP251XFD_REG_FLTCON(ring->nr >> 2), 831eb79a267SMarc Kleine-Budde MCP251XFD_REG_FLTCON_FLT_MASK(ring->nr), 8321f0e21a0SMarc Kleine-Budde fltcon); 8331f0e21a0SMarc Kleine-Budde } 8341f0e21a0SMarc Kleine-Budde 835eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv) 8361f0e21a0SMarc Kleine-Budde { 837eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 838eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *rx_ring; 8391f0e21a0SMarc Kleine-Budde u32 val; 8401f0e21a0SMarc Kleine-Budde int err, n; 8411f0e21a0SMarc Kleine-Budde 8421f0e21a0SMarc Kleine-Budde /* TEF */ 843eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_TEFCON_FSIZE_MASK, 8441f0e21a0SMarc Kleine-Budde tx_ring->obj_num - 1) | 845eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFTSEN | 846eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFOVIE | 847eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFNEIE; 8481f0e21a0SMarc Kleine-Budde 849eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_TEFCON, val); 8501f0e21a0SMarc Kleine-Budde if (err) 8511f0e21a0SMarc Kleine-Budde return err; 8521f0e21a0SMarc Kleine-Budde 8531f0e21a0SMarc Kleine-Budde /* FIFO 1 - TX */ 854eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK, 8551f0e21a0SMarc Kleine-Budde tx_ring->obj_num - 1) | 856eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXEN | 857eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXATIE; 8581f0e21a0SMarc Kleine-Budde 8591f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) 860eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 861eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_64); 8621f0e21a0SMarc Kleine-Budde else 863eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 864eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_8); 8651f0e21a0SMarc Kleine-Budde 8661f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) 867eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK, 868eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXAT_ONE_SHOT); 8691f0e21a0SMarc Kleine-Budde else 870eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK, 871eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXAT_UNLIMITED); 8721f0e21a0SMarc Kleine-Budde 8731f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, 874eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO), 8751f0e21a0SMarc Kleine-Budde val); 8761f0e21a0SMarc Kleine-Budde if (err) 8771f0e21a0SMarc Kleine-Budde return err; 8781f0e21a0SMarc Kleine-Budde 8791f0e21a0SMarc Kleine-Budde /* RX FIFOs */ 880eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, n) { 881eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_fifo_init_one(priv, rx_ring); 8821f0e21a0SMarc Kleine-Budde if (err) 8831f0e21a0SMarc Kleine-Budde return err; 8841f0e21a0SMarc Kleine-Budde 885eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_filter_init_one(priv, rx_ring); 8861f0e21a0SMarc Kleine-Budde if (err) 8871f0e21a0SMarc Kleine-Budde return err; 8881f0e21a0SMarc Kleine-Budde } 8891f0e21a0SMarc Kleine-Budde 8901f0e21a0SMarc Kleine-Budde return 0; 8911f0e21a0SMarc Kleine-Budde } 8921f0e21a0SMarc Kleine-Budde 893eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_ecc_init(struct mcp251xfd_priv *priv) 8941f0e21a0SMarc Kleine-Budde { 895eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 8961f0e21a0SMarc Kleine-Budde void *ram; 8971f0e21a0SMarc Kleine-Budde u32 val = 0; 8981f0e21a0SMarc Kleine-Budde int err; 8991f0e21a0SMarc Kleine-Budde 9001f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 9011f0e21a0SMarc Kleine-Budde 902eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_ECC) 903eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_ECCCON_ECCEN; 9041f0e21a0SMarc Kleine-Budde 905eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, 906eb79a267SMarc Kleine-Budde MCP251XFD_REG_ECCCON_ECCEN, val); 9071f0e21a0SMarc Kleine-Budde if (err) 9081f0e21a0SMarc Kleine-Budde return err; 9091f0e21a0SMarc Kleine-Budde 910eb79a267SMarc Kleine-Budde ram = kzalloc(MCP251XFD_RAM_SIZE, GFP_KERNEL); 9111f0e21a0SMarc Kleine-Budde if (!ram) 9121f0e21a0SMarc Kleine-Budde return -ENOMEM; 9131f0e21a0SMarc Kleine-Budde 914eb79a267SMarc Kleine-Budde err = regmap_raw_write(priv->map_reg, MCP251XFD_RAM_START, ram, 915eb79a267SMarc Kleine-Budde MCP251XFD_RAM_SIZE); 9161f0e21a0SMarc Kleine-Budde kfree(ram); 9171f0e21a0SMarc Kleine-Budde 9181f0e21a0SMarc Kleine-Budde return err; 9191f0e21a0SMarc Kleine-Budde } 9201f0e21a0SMarc Kleine-Budde 921eb79a267SMarc Kleine-Budde static inline void mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv *priv) 9221f0e21a0SMarc Kleine-Budde { 923eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 9241f0e21a0SMarc Kleine-Budde 9251f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 9261f0e21a0SMarc Kleine-Budde } 9271f0e21a0SMarc Kleine-Budde 928eb79a267SMarc Kleine-Budde static u8 mcp251xfd_get_normal_mode(const struct mcp251xfd_priv *priv) 9291f0e21a0SMarc Kleine-Budde { 9301f0e21a0SMarc Kleine-Budde u8 mode; 9311f0e21a0SMarc Kleine-Budde 9321f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 933eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_LISTENONLY; 9341f0e21a0SMarc Kleine-Budde else if (priv->can.ctrlmode & CAN_CTRLMODE_FD) 935eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_MIXED; 9361f0e21a0SMarc Kleine-Budde else 937eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_CAN2_0; 9381f0e21a0SMarc Kleine-Budde 9391f0e21a0SMarc Kleine-Budde return mode; 9401f0e21a0SMarc Kleine-Budde } 9411f0e21a0SMarc Kleine-Budde 9421f0e21a0SMarc Kleine-Budde static int 943eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv, 9441f0e21a0SMarc Kleine-Budde bool nowait) 9451f0e21a0SMarc Kleine-Budde { 9461f0e21a0SMarc Kleine-Budde u8 mode; 9471f0e21a0SMarc Kleine-Budde 948eb79a267SMarc Kleine-Budde mode = mcp251xfd_get_normal_mode(priv); 9491f0e21a0SMarc Kleine-Budde 950eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode, nowait); 9511f0e21a0SMarc Kleine-Budde } 9521f0e21a0SMarc Kleine-Budde 9531f0e21a0SMarc Kleine-Budde static inline int 954eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv) 9551f0e21a0SMarc Kleine-Budde { 956eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_normal_mode(priv, false); 9571f0e21a0SMarc Kleine-Budde } 9581f0e21a0SMarc Kleine-Budde 9591f0e21a0SMarc Kleine-Budde static inline int 960eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode_nowait(const struct mcp251xfd_priv *priv) 9611f0e21a0SMarc Kleine-Budde { 962eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_normal_mode(priv, true); 9631f0e21a0SMarc Kleine-Budde } 9641f0e21a0SMarc Kleine-Budde 965eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_enable(const struct mcp251xfd_priv *priv) 9661f0e21a0SMarc Kleine-Budde { 9671f0e21a0SMarc Kleine-Budde u32 val; 9681f0e21a0SMarc Kleine-Budde int err; 9691f0e21a0SMarc Kleine-Budde 970eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_CRC_FERRIE | MCP251XFD_REG_CRC_CRCERRIE; 971eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_CRC, val); 9721f0e21a0SMarc Kleine-Budde if (err) 9731f0e21a0SMarc Kleine-Budde return err; 9741f0e21a0SMarc Kleine-Budde 975eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE; 976eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, val, val); 9771f0e21a0SMarc Kleine-Budde if (err) 9781f0e21a0SMarc Kleine-Budde return err; 9791f0e21a0SMarc Kleine-Budde 980eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_INT_CERRIE | 981eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_SERRIE | 982eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_RXOVIE | 983eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_TXATIE | 984eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_SPICRCIE | 985eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_ECCIE | 986eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_TEFIE | 987eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_MODIE | 988eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_RXIE; 9891f0e21a0SMarc Kleine-Budde 9901f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) 991eb79a267SMarc Kleine-Budde val |= MCP251XFD_REG_INT_IVMIE; 9921f0e21a0SMarc Kleine-Budde 993eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_INT, val); 9941f0e21a0SMarc Kleine-Budde } 9951f0e21a0SMarc Kleine-Budde 996eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_disable(const struct mcp251xfd_priv *priv) 9971f0e21a0SMarc Kleine-Budde { 9981f0e21a0SMarc Kleine-Budde int err; 9991f0e21a0SMarc Kleine-Budde u32 mask; 10001f0e21a0SMarc Kleine-Budde 1001eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_INT, 0); 10021f0e21a0SMarc Kleine-Budde if (err) 10031f0e21a0SMarc Kleine-Budde return err; 10041f0e21a0SMarc Kleine-Budde 1005eb79a267SMarc Kleine-Budde mask = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE; 1006eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, 10071f0e21a0SMarc Kleine-Budde mask, 0x0); 10081f0e21a0SMarc Kleine-Budde if (err) 10091f0e21a0SMarc Kleine-Budde return err; 10101f0e21a0SMarc Kleine-Budde 1011eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_CRC, 0); 10121f0e21a0SMarc Kleine-Budde } 10131f0e21a0SMarc Kleine-Budde 1014eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_stop(struct mcp251xfd_priv *priv, 10151f0e21a0SMarc Kleine-Budde const enum can_state state) 10161f0e21a0SMarc Kleine-Budde { 10171f0e21a0SMarc Kleine-Budde priv->can.state = state; 10181f0e21a0SMarc Kleine-Budde 1019eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 1020eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_int_disable(priv); 1021eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 10221f0e21a0SMarc Kleine-Budde } 10231f0e21a0SMarc Kleine-Budde 1024eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv) 10251f0e21a0SMarc Kleine-Budde { 10261f0e21a0SMarc Kleine-Budde int err; 10271f0e21a0SMarc Kleine-Budde 1028eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset(priv); 10291f0e21a0SMarc Kleine-Budde if (err) 10301f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10311f0e21a0SMarc Kleine-Budde 1032eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_clock_init(priv); 10331f0e21a0SMarc Kleine-Budde if (err) 10341f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10351f0e21a0SMarc Kleine-Budde 1036eb79a267SMarc Kleine-Budde err = mcp251xfd_set_bittiming(priv); 10371f0e21a0SMarc Kleine-Budde if (err) 10381f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10391f0e21a0SMarc Kleine-Budde 1040eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_enable(priv); 10411f0e21a0SMarc Kleine-Budde if (err) 10421f0e21a0SMarc Kleine-Budde return err; 10431f0e21a0SMarc Kleine-Budde 1044eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_ecc_init(priv); 10451f0e21a0SMarc Kleine-Budde if (err) 10461f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10471f0e21a0SMarc Kleine-Budde 1048eb79a267SMarc Kleine-Budde mcp251xfd_ring_init(priv); 10491f0e21a0SMarc Kleine-Budde 1050eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_fifo_init(priv); 10511f0e21a0SMarc Kleine-Budde if (err) 10521f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10531f0e21a0SMarc Kleine-Budde 10541f0e21a0SMarc Kleine-Budde priv->can.state = CAN_STATE_ERROR_ACTIVE; 10551f0e21a0SMarc Kleine-Budde 1056eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_normal_mode(priv); 10571f0e21a0SMarc Kleine-Budde if (err) 10581f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10591f0e21a0SMarc Kleine-Budde 10601f0e21a0SMarc Kleine-Budde return 0; 10611f0e21a0SMarc Kleine-Budde 10621f0e21a0SMarc Kleine-Budde out_chip_stop: 1063eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 10641f0e21a0SMarc Kleine-Budde 10651f0e21a0SMarc Kleine-Budde return err; 10661f0e21a0SMarc Kleine-Budde } 10671f0e21a0SMarc Kleine-Budde 1068eb79a267SMarc Kleine-Budde static int mcp251xfd_set_mode(struct net_device *ndev, enum can_mode mode) 10691f0e21a0SMarc Kleine-Budde { 1070eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 10711f0e21a0SMarc Kleine-Budde int err; 10721f0e21a0SMarc Kleine-Budde 10731f0e21a0SMarc Kleine-Budde switch (mode) { 10741f0e21a0SMarc Kleine-Budde case CAN_MODE_START: 1075eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_start(priv); 10761f0e21a0SMarc Kleine-Budde if (err) 10771f0e21a0SMarc Kleine-Budde return err; 10781f0e21a0SMarc Kleine-Budde 1079eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_interrupts_enable(priv); 10801f0e21a0SMarc Kleine-Budde if (err) { 1081eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 10821f0e21a0SMarc Kleine-Budde return err; 10831f0e21a0SMarc Kleine-Budde } 10841f0e21a0SMarc Kleine-Budde 10851f0e21a0SMarc Kleine-Budde netif_wake_queue(ndev); 10861f0e21a0SMarc Kleine-Budde break; 10871f0e21a0SMarc Kleine-Budde 10881f0e21a0SMarc Kleine-Budde default: 10891f0e21a0SMarc Kleine-Budde return -EOPNOTSUPP; 10901f0e21a0SMarc Kleine-Budde } 10911f0e21a0SMarc Kleine-Budde 10921f0e21a0SMarc Kleine-Budde return 0; 10931f0e21a0SMarc Kleine-Budde } 10941f0e21a0SMarc Kleine-Budde 1095eb79a267SMarc Kleine-Budde static int __mcp251xfd_get_berr_counter(const struct net_device *ndev, 10961f0e21a0SMarc Kleine-Budde struct can_berr_counter *bec) 10971f0e21a0SMarc Kleine-Budde { 1098eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = netdev_priv(ndev); 10991f0e21a0SMarc Kleine-Budde u32 trec; 11001f0e21a0SMarc Kleine-Budde int err; 11011f0e21a0SMarc Kleine-Budde 1102eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec); 11031f0e21a0SMarc Kleine-Budde if (err) 11041f0e21a0SMarc Kleine-Budde return err; 11051f0e21a0SMarc Kleine-Budde 1106eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_TXBO) 11071f0e21a0SMarc Kleine-Budde bec->txerr = 256; 11081f0e21a0SMarc Kleine-Budde else 1109eb79a267SMarc Kleine-Budde bec->txerr = FIELD_GET(MCP251XFD_REG_TREC_TEC_MASK, trec); 1110eb79a267SMarc Kleine-Budde bec->rxerr = FIELD_GET(MCP251XFD_REG_TREC_REC_MASK, trec); 11111f0e21a0SMarc Kleine-Budde 11121f0e21a0SMarc Kleine-Budde return 0; 11131f0e21a0SMarc Kleine-Budde } 11141f0e21a0SMarc Kleine-Budde 1115eb79a267SMarc Kleine-Budde static int mcp251xfd_get_berr_counter(const struct net_device *ndev, 11161f0e21a0SMarc Kleine-Budde struct can_berr_counter *bec) 11171f0e21a0SMarc Kleine-Budde { 1118eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = netdev_priv(ndev); 11191f0e21a0SMarc Kleine-Budde 11201f0e21a0SMarc Kleine-Budde /* Avoid waking up the controller if the interface is down */ 11211f0e21a0SMarc Kleine-Budde if (!(ndev->flags & IFF_UP)) 11221f0e21a0SMarc Kleine-Budde return 0; 11231f0e21a0SMarc Kleine-Budde 11241f0e21a0SMarc Kleine-Budde /* The controller is powered down during Bus Off, use saved 11251f0e21a0SMarc Kleine-Budde * bec values. 11261f0e21a0SMarc Kleine-Budde */ 11271f0e21a0SMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) { 11281f0e21a0SMarc Kleine-Budde *bec = priv->bec; 11291f0e21a0SMarc Kleine-Budde return 0; 11301f0e21a0SMarc Kleine-Budde } 11311f0e21a0SMarc Kleine-Budde 1132eb79a267SMarc Kleine-Budde return __mcp251xfd_get_berr_counter(ndev, bec); 11331f0e21a0SMarc Kleine-Budde } 11341f0e21a0SMarc Kleine-Budde 1135eb79a267SMarc Kleine-Budde static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv) 11361f0e21a0SMarc Kleine-Budde { 11371f0e21a0SMarc Kleine-Budde u8 tef_tail_chip, tef_tail; 11381f0e21a0SMarc Kleine-Budde int err; 11391f0e21a0SMarc Kleine-Budde 1140eb79a267SMarc Kleine-Budde if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY)) 11411f0e21a0SMarc Kleine-Budde return 0; 11421f0e21a0SMarc Kleine-Budde 1143eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_tail_get_from_chip(priv, &tef_tail_chip); 11441f0e21a0SMarc Kleine-Budde if (err) 11451f0e21a0SMarc Kleine-Budde return err; 11461f0e21a0SMarc Kleine-Budde 1147eb79a267SMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 11481f0e21a0SMarc Kleine-Budde if (tef_tail_chip != tef_tail) { 11491f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 11501f0e21a0SMarc Kleine-Budde "TEF tail of chip (0x%02x) and ours (0x%08x) inconsistent.\n", 11511f0e21a0SMarc Kleine-Budde tef_tail_chip, tef_tail); 11521f0e21a0SMarc Kleine-Budde return -EILSEQ; 11531f0e21a0SMarc Kleine-Budde } 11541f0e21a0SMarc Kleine-Budde 11551f0e21a0SMarc Kleine-Budde return 0; 11561f0e21a0SMarc Kleine-Budde } 11571f0e21a0SMarc Kleine-Budde 11581f0e21a0SMarc Kleine-Budde static int 1159eb79a267SMarc Kleine-Budde mcp251xfd_check_rx_tail(const struct mcp251xfd_priv *priv, 1160eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring) 11611f0e21a0SMarc Kleine-Budde { 11621f0e21a0SMarc Kleine-Budde u8 rx_tail_chip, rx_tail; 11631f0e21a0SMarc Kleine-Budde int err; 11641f0e21a0SMarc Kleine-Budde 1165eb79a267SMarc Kleine-Budde if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY)) 11661f0e21a0SMarc Kleine-Budde return 0; 11671f0e21a0SMarc Kleine-Budde 1168eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_tail_get_from_chip(priv, ring, &rx_tail_chip); 11691f0e21a0SMarc Kleine-Budde if (err) 11701f0e21a0SMarc Kleine-Budde return err; 11711f0e21a0SMarc Kleine-Budde 1172eb79a267SMarc Kleine-Budde rx_tail = mcp251xfd_get_rx_tail(ring); 11731f0e21a0SMarc Kleine-Budde if (rx_tail_chip != rx_tail) { 11741f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 11751f0e21a0SMarc Kleine-Budde "RX tail of chip (%d) and ours (%d) inconsistent.\n", 11761f0e21a0SMarc Kleine-Budde rx_tail_chip, rx_tail); 11771f0e21a0SMarc Kleine-Budde return -EILSEQ; 11781f0e21a0SMarc Kleine-Budde } 11791f0e21a0SMarc Kleine-Budde 11801f0e21a0SMarc Kleine-Budde return 0; 11811f0e21a0SMarc Kleine-Budde } 11821f0e21a0SMarc Kleine-Budde 11831f0e21a0SMarc Kleine-Budde static int 1184eb79a267SMarc Kleine-Budde mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq) 11851f0e21a0SMarc Kleine-Budde { 1186eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 11871f0e21a0SMarc Kleine-Budde u32 tef_sta; 11881f0e21a0SMarc Kleine-Budde int err; 11891f0e21a0SMarc Kleine-Budde 1190eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta); 11911f0e21a0SMarc Kleine-Budde if (err) 11921f0e21a0SMarc Kleine-Budde return err; 11931f0e21a0SMarc Kleine-Budde 1194eb79a267SMarc Kleine-Budde if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) { 11951f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 11961f0e21a0SMarc Kleine-Budde "Transmit Event FIFO buffer overflow.\n"); 11971f0e21a0SMarc Kleine-Budde return -ENOBUFS; 11981f0e21a0SMarc Kleine-Budde } 11991f0e21a0SMarc Kleine-Budde 12001f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 12011f0e21a0SMarc Kleine-Budde "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x)\n", 1202eb79a267SMarc Kleine-Budde tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ? 1203eb79a267SMarc Kleine-Budde "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ? 12041f0e21a0SMarc Kleine-Budde "not empty" : "empty", 12051f0e21a0SMarc Kleine-Budde seq, priv->tef.tail, priv->tef.head, tx_ring->head); 12061f0e21a0SMarc Kleine-Budde 12071f0e21a0SMarc Kleine-Budde /* The Sequence Number in the TEF doesn't match our tef_tail. */ 12081f0e21a0SMarc Kleine-Budde return -EAGAIN; 12091f0e21a0SMarc Kleine-Budde } 12101f0e21a0SMarc Kleine-Budde 12111f0e21a0SMarc Kleine-Budde static int 1212eb79a267SMarc Kleine-Budde mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, 1213eb79a267SMarc Kleine-Budde const struct mcp251xfd_hw_tef_obj *hw_tef_obj) 12141f0e21a0SMarc Kleine-Budde { 1215eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 12161f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 12171f0e21a0SMarc Kleine-Budde u32 seq, seq_masked, tef_tail_masked; 12181f0e21a0SMarc Kleine-Budde int err; 12191f0e21a0SMarc Kleine-Budde 1220eb79a267SMarc Kleine-Budde seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, 12211f0e21a0SMarc Kleine-Budde hw_tef_obj->flags); 12221f0e21a0SMarc Kleine-Budde 12231f0e21a0SMarc Kleine-Budde /* Use the MCP2517FD mask on the MCP2518FD, too. We only 12241f0e21a0SMarc Kleine-Budde * compare 7 bits, this should be enough to detect 12251f0e21a0SMarc Kleine-Budde * net-yet-completed, i.e. old TEF objects. 12261f0e21a0SMarc Kleine-Budde */ 12271f0e21a0SMarc Kleine-Budde seq_masked = seq & 1228eb79a267SMarc Kleine-Budde field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 12291f0e21a0SMarc Kleine-Budde tef_tail_masked = priv->tef.tail & 1230eb79a267SMarc Kleine-Budde field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 12311f0e21a0SMarc Kleine-Budde if (seq_masked != tef_tail_masked) 1232eb79a267SMarc Kleine-Budde return mcp251xfd_handle_tefif_recover(priv, seq); 12331f0e21a0SMarc Kleine-Budde 12341f0e21a0SMarc Kleine-Budde stats->tx_bytes += 12351f0e21a0SMarc Kleine-Budde can_rx_offload_get_echo_skb(&priv->offload, 1236eb79a267SMarc Kleine-Budde mcp251xfd_get_tef_tail(priv), 12371f0e21a0SMarc Kleine-Budde hw_tef_obj->ts); 12381f0e21a0SMarc Kleine-Budde stats->tx_packets++; 12391f0e21a0SMarc Kleine-Budde 12401f0e21a0SMarc Kleine-Budde /* finally increment the TEF pointer */ 1241eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_TEFCON, 12421f0e21a0SMarc Kleine-Budde GENMASK(15, 8), 1243eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_UINC); 12441f0e21a0SMarc Kleine-Budde if (err) 12451f0e21a0SMarc Kleine-Budde return err; 12461f0e21a0SMarc Kleine-Budde 12471f0e21a0SMarc Kleine-Budde priv->tef.tail++; 12481f0e21a0SMarc Kleine-Budde tx_ring->tail++; 12491f0e21a0SMarc Kleine-Budde 1250eb79a267SMarc Kleine-Budde return mcp251xfd_check_tef_tail(priv); 12511f0e21a0SMarc Kleine-Budde } 12521f0e21a0SMarc Kleine-Budde 1253eb79a267SMarc Kleine-Budde static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv) 12541f0e21a0SMarc Kleine-Budde { 1255eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 12561f0e21a0SMarc Kleine-Budde unsigned int new_head; 12571f0e21a0SMarc Kleine-Budde u8 chip_tx_tail; 12581f0e21a0SMarc Kleine-Budde int err; 12591f0e21a0SMarc Kleine-Budde 1260eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail); 12611f0e21a0SMarc Kleine-Budde if (err) 12621f0e21a0SMarc Kleine-Budde return err; 12631f0e21a0SMarc Kleine-Budde 12641f0e21a0SMarc Kleine-Budde /* chip_tx_tail, is the next TX-Object send by the HW. 12651f0e21a0SMarc Kleine-Budde * The new TEF head must be >= the old head, ... 12661f0e21a0SMarc Kleine-Budde */ 12671f0e21a0SMarc Kleine-Budde new_head = round_down(priv->tef.head, tx_ring->obj_num) + chip_tx_tail; 12681f0e21a0SMarc Kleine-Budde if (new_head <= priv->tef.head) 12691f0e21a0SMarc Kleine-Budde new_head += tx_ring->obj_num; 12701f0e21a0SMarc Kleine-Budde 12711f0e21a0SMarc Kleine-Budde /* ... but it cannot exceed the TX head. */ 12721f0e21a0SMarc Kleine-Budde priv->tef.head = min(new_head, tx_ring->head); 12731f0e21a0SMarc Kleine-Budde 1274eb79a267SMarc Kleine-Budde return mcp251xfd_check_tef_tail(priv); 12751f0e21a0SMarc Kleine-Budde } 12761f0e21a0SMarc Kleine-Budde 12771f0e21a0SMarc Kleine-Budde static inline int 1278eb79a267SMarc Kleine-Budde mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv, 1279eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_tef_obj *hw_tef_obj, 12801f0e21a0SMarc Kleine-Budde const u8 offset, const u8 len) 12811f0e21a0SMarc Kleine-Budde { 1282eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 12831f0e21a0SMarc Kleine-Budde 1284eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 12851f0e21a0SMarc Kleine-Budde (offset > tx_ring->obj_num || 12861f0e21a0SMarc Kleine-Budde len > tx_ring->obj_num || 12871f0e21a0SMarc Kleine-Budde offset + len > tx_ring->obj_num)) { 12881f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 12891f0e21a0SMarc Kleine-Budde "Trying to read to many TEF objects (max=%d, offset=%d, len=%d).\n", 12901f0e21a0SMarc Kleine-Budde tx_ring->obj_num, offset, len); 12911f0e21a0SMarc Kleine-Budde return -ERANGE; 12921f0e21a0SMarc Kleine-Budde } 12931f0e21a0SMarc Kleine-Budde 12941f0e21a0SMarc Kleine-Budde return regmap_bulk_read(priv->map_rx, 1295eb79a267SMarc Kleine-Budde mcp251xfd_get_tef_obj_addr(offset), 12961f0e21a0SMarc Kleine-Budde hw_tef_obj, 12971f0e21a0SMarc Kleine-Budde sizeof(*hw_tef_obj) / sizeof(u32) * len); 12981f0e21a0SMarc Kleine-Budde } 12991f0e21a0SMarc Kleine-Budde 1300eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) 13011f0e21a0SMarc Kleine-Budde { 1302eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX]; 13031f0e21a0SMarc Kleine-Budde u8 tef_tail, len, l; 13041f0e21a0SMarc Kleine-Budde int err, i; 13051f0e21a0SMarc Kleine-Budde 1306eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_ring_update(priv); 13071f0e21a0SMarc Kleine-Budde if (err) 13081f0e21a0SMarc Kleine-Budde return err; 13091f0e21a0SMarc Kleine-Budde 1310eb79a267SMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 1311eb79a267SMarc Kleine-Budde len = mcp251xfd_get_tef_len(priv); 1312eb79a267SMarc Kleine-Budde l = mcp251xfd_get_tef_linear_len(priv); 1313eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l); 13141f0e21a0SMarc Kleine-Budde if (err) 13151f0e21a0SMarc Kleine-Budde return err; 13161f0e21a0SMarc Kleine-Budde 13171f0e21a0SMarc Kleine-Budde if (l < len) { 1318eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l); 13191f0e21a0SMarc Kleine-Budde if (err) 13201f0e21a0SMarc Kleine-Budde return err; 13211f0e21a0SMarc Kleine-Budde } 13221f0e21a0SMarc Kleine-Budde 13231f0e21a0SMarc Kleine-Budde for (i = 0; i < len; i++) { 1324eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i]); 13251f0e21a0SMarc Kleine-Budde /* -EAGAIN means the Sequence Number in the TEF 13261f0e21a0SMarc Kleine-Budde * doesn't match our tef_tail. This can happen if we 13271f0e21a0SMarc Kleine-Budde * read the TEF objects too early. Leave loop let the 13281f0e21a0SMarc Kleine-Budde * interrupt handler call us again. 13291f0e21a0SMarc Kleine-Budde */ 13301f0e21a0SMarc Kleine-Budde if (err == -EAGAIN) 13311f0e21a0SMarc Kleine-Budde goto out_netif_wake_queue; 13321f0e21a0SMarc Kleine-Budde if (err) 13331f0e21a0SMarc Kleine-Budde return err; 13341f0e21a0SMarc Kleine-Budde } 13351f0e21a0SMarc Kleine-Budde 13361f0e21a0SMarc Kleine-Budde out_netif_wake_queue: 1337eb79a267SMarc Kleine-Budde mcp251xfd_ecc_tefif_successful(priv); 13381f0e21a0SMarc Kleine-Budde 1339eb79a267SMarc Kleine-Budde if (mcp251xfd_get_tx_free(priv->tx)) { 13401f0e21a0SMarc Kleine-Budde /* Make sure that anybody stopping the queue after 13411f0e21a0SMarc Kleine-Budde * this sees the new tx_ring->tail. 13421f0e21a0SMarc Kleine-Budde */ 13431f0e21a0SMarc Kleine-Budde smp_mb(); 13441f0e21a0SMarc Kleine-Budde netif_wake_queue(priv->ndev); 13451f0e21a0SMarc Kleine-Budde } 13461f0e21a0SMarc Kleine-Budde 13471f0e21a0SMarc Kleine-Budde return 0; 13481f0e21a0SMarc Kleine-Budde } 13491f0e21a0SMarc Kleine-Budde 13501f0e21a0SMarc Kleine-Budde static int 1351eb79a267SMarc Kleine-Budde mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv, 1352eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring) 13531f0e21a0SMarc Kleine-Budde { 13541f0e21a0SMarc Kleine-Budde u32 new_head; 13551f0e21a0SMarc Kleine-Budde u8 chip_rx_head; 13561f0e21a0SMarc Kleine-Budde int err; 13571f0e21a0SMarc Kleine-Budde 1358eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head); 13591f0e21a0SMarc Kleine-Budde if (err) 13601f0e21a0SMarc Kleine-Budde return err; 13611f0e21a0SMarc Kleine-Budde 13621f0e21a0SMarc Kleine-Budde /* chip_rx_head, is the next RX-Object filled by the HW. 13631f0e21a0SMarc Kleine-Budde * The new RX head must be >= the old head. 13641f0e21a0SMarc Kleine-Budde */ 13651f0e21a0SMarc Kleine-Budde new_head = round_down(ring->head, ring->obj_num) + chip_rx_head; 13661f0e21a0SMarc Kleine-Budde if (new_head <= ring->head) 13671f0e21a0SMarc Kleine-Budde new_head += ring->obj_num; 13681f0e21a0SMarc Kleine-Budde 13691f0e21a0SMarc Kleine-Budde ring->head = new_head; 13701f0e21a0SMarc Kleine-Budde 1371eb79a267SMarc Kleine-Budde return mcp251xfd_check_rx_tail(priv, ring); 13721f0e21a0SMarc Kleine-Budde } 13731f0e21a0SMarc Kleine-Budde 13741f0e21a0SMarc Kleine-Budde static void 1375eb79a267SMarc Kleine-Budde mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv, 1376eb79a267SMarc Kleine-Budde const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj, 13771f0e21a0SMarc Kleine-Budde struct sk_buff *skb) 13781f0e21a0SMarc Kleine-Budde { 13791f0e21a0SMarc Kleine-Budde struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 13801f0e21a0SMarc Kleine-Budde 1381eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_IDE) { 13821f0e21a0SMarc Kleine-Budde u32 sid, eid; 13831f0e21a0SMarc Kleine-Budde 1384eb79a267SMarc Kleine-Budde eid = FIELD_GET(MCP251XFD_OBJ_ID_EID_MASK, hw_rx_obj->id); 1385eb79a267SMarc Kleine-Budde sid = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, hw_rx_obj->id); 13861f0e21a0SMarc Kleine-Budde 13871f0e21a0SMarc Kleine-Budde cfd->can_id = CAN_EFF_FLAG | 1388eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_FRAME_EFF_EID_MASK, eid) | 1389eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_FRAME_EFF_SID_MASK, sid); 13901f0e21a0SMarc Kleine-Budde } else { 1391eb79a267SMarc Kleine-Budde cfd->can_id = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, 13921f0e21a0SMarc Kleine-Budde hw_rx_obj->id); 13931f0e21a0SMarc Kleine-Budde } 13941f0e21a0SMarc Kleine-Budde 13951f0e21a0SMarc Kleine-Budde /* CANFD */ 1396eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) { 13971f0e21a0SMarc Kleine-Budde u8 dlc; 13981f0e21a0SMarc Kleine-Budde 1399eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_ESI) 14001f0e21a0SMarc Kleine-Budde cfd->flags |= CANFD_ESI; 14011f0e21a0SMarc Kleine-Budde 1402eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_BRS) 14031f0e21a0SMarc Kleine-Budde cfd->flags |= CANFD_BRS; 14041f0e21a0SMarc Kleine-Budde 1405eb79a267SMarc Kleine-Budde dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC, hw_rx_obj->flags); 14063ab4ce0dSOliver Hartkopp cfd->len = can_fd_dlc2len(dlc); 14071f0e21a0SMarc Kleine-Budde } else { 1408eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR) 14091f0e21a0SMarc Kleine-Budde cfd->can_id |= CAN_RTR_FLAG; 14101f0e21a0SMarc Kleine-Budde 141169d98969SOliver Hartkopp cfd->len = can_cc_dlc2len(FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC, 14121f0e21a0SMarc Kleine-Budde hw_rx_obj->flags)); 14131f0e21a0SMarc Kleine-Budde } 14141f0e21a0SMarc Kleine-Budde 14151f0e21a0SMarc Kleine-Budde memcpy(cfd->data, hw_rx_obj->data, cfd->len); 14161f0e21a0SMarc Kleine-Budde } 14171f0e21a0SMarc Kleine-Budde 14181f0e21a0SMarc Kleine-Budde static int 1419eb79a267SMarc Kleine-Budde mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv, 1420eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring, 1421eb79a267SMarc Kleine-Budde const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj) 14221f0e21a0SMarc Kleine-Budde { 14231f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 14241f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 14251f0e21a0SMarc Kleine-Budde struct canfd_frame *cfd; 14261f0e21a0SMarc Kleine-Budde int err; 14271f0e21a0SMarc Kleine-Budde 1428eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) 14291f0e21a0SMarc Kleine-Budde skb = alloc_canfd_skb(priv->ndev, &cfd); 14301f0e21a0SMarc Kleine-Budde else 14311f0e21a0SMarc Kleine-Budde skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cfd); 14321f0e21a0SMarc Kleine-Budde 14331f0e21a0SMarc Kleine-Budde if (!cfd) { 14341f0e21a0SMarc Kleine-Budde stats->rx_dropped++; 14351f0e21a0SMarc Kleine-Budde return 0; 14361f0e21a0SMarc Kleine-Budde } 14371f0e21a0SMarc Kleine-Budde 1438eb79a267SMarc Kleine-Budde mcp251xfd_hw_rx_obj_to_skb(priv, hw_rx_obj, skb); 14391f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, hw_rx_obj->ts); 14401f0e21a0SMarc Kleine-Budde if (err) 14411f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 14421f0e21a0SMarc Kleine-Budde 14431f0e21a0SMarc Kleine-Budde ring->tail++; 14441f0e21a0SMarc Kleine-Budde 14451f0e21a0SMarc Kleine-Budde /* finally increment the RX pointer */ 14461f0e21a0SMarc Kleine-Budde return regmap_update_bits(priv->map_reg, 1447eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON(ring->fifo_nr), 14481f0e21a0SMarc Kleine-Budde GENMASK(15, 8), 1449eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_UINC); 14501f0e21a0SMarc Kleine-Budde } 14511f0e21a0SMarc Kleine-Budde 14521f0e21a0SMarc Kleine-Budde static inline int 1453eb79a267SMarc Kleine-Budde mcp251xfd_rx_obj_read(const struct mcp251xfd_priv *priv, 1454eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring, 1455eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj, 14561f0e21a0SMarc Kleine-Budde const u8 offset, const u8 len) 14571f0e21a0SMarc Kleine-Budde { 14581f0e21a0SMarc Kleine-Budde int err; 14591f0e21a0SMarc Kleine-Budde 14601f0e21a0SMarc Kleine-Budde err = regmap_bulk_read(priv->map_rx, 1461eb79a267SMarc Kleine-Budde mcp251xfd_get_rx_obj_addr(ring, offset), 14621f0e21a0SMarc Kleine-Budde hw_rx_obj, 14631f0e21a0SMarc Kleine-Budde len * ring->obj_size / sizeof(u32)); 14641f0e21a0SMarc Kleine-Budde 14651f0e21a0SMarc Kleine-Budde return err; 14661f0e21a0SMarc Kleine-Budde } 14671f0e21a0SMarc Kleine-Budde 14681f0e21a0SMarc Kleine-Budde static int 1469eb79a267SMarc Kleine-Budde mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv, 1470eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring) 14711f0e21a0SMarc Kleine-Budde { 1472eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj = ring->obj; 14731f0e21a0SMarc Kleine-Budde u8 rx_tail, len; 14741f0e21a0SMarc Kleine-Budde int err, i; 14751f0e21a0SMarc Kleine-Budde 1476eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_ring_update(priv, ring); 14771f0e21a0SMarc Kleine-Budde if (err) 14781f0e21a0SMarc Kleine-Budde return err; 14791f0e21a0SMarc Kleine-Budde 1480eb79a267SMarc Kleine-Budde while ((len = mcp251xfd_get_rx_linear_len(ring))) { 1481eb79a267SMarc Kleine-Budde rx_tail = mcp251xfd_get_rx_tail(ring); 14821f0e21a0SMarc Kleine-Budde 1483eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj, 14841f0e21a0SMarc Kleine-Budde rx_tail, len); 14851f0e21a0SMarc Kleine-Budde if (err) 14861f0e21a0SMarc Kleine-Budde return err; 14871f0e21a0SMarc Kleine-Budde 14881f0e21a0SMarc Kleine-Budde for (i = 0; i < len; i++) { 1489eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_rxif_one(priv, ring, 14901f0e21a0SMarc Kleine-Budde (void *)hw_rx_obj + 14911f0e21a0SMarc Kleine-Budde i * ring->obj_size); 14921f0e21a0SMarc Kleine-Budde if (err) 14931f0e21a0SMarc Kleine-Budde return err; 14941f0e21a0SMarc Kleine-Budde } 14951f0e21a0SMarc Kleine-Budde } 14961f0e21a0SMarc Kleine-Budde 14971f0e21a0SMarc Kleine-Budde return 0; 14981f0e21a0SMarc Kleine-Budde } 14991f0e21a0SMarc Kleine-Budde 1500eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv) 15011f0e21a0SMarc Kleine-Budde { 1502eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring; 15031f0e21a0SMarc Kleine-Budde int err, n; 15041f0e21a0SMarc Kleine-Budde 1505eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, ring, n) { 1506eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_rxif_ring(priv, ring); 15071f0e21a0SMarc Kleine-Budde if (err) 15081f0e21a0SMarc Kleine-Budde return err; 15091f0e21a0SMarc Kleine-Budde } 15101f0e21a0SMarc Kleine-Budde 15111f0e21a0SMarc Kleine-Budde return 0; 15121f0e21a0SMarc Kleine-Budde } 15131f0e21a0SMarc Kleine-Budde 1514eb79a267SMarc Kleine-Budde static inline int mcp251xfd_get_timestamp(const struct mcp251xfd_priv *priv, 15151f0e21a0SMarc Kleine-Budde u32 *timestamp) 15161f0e21a0SMarc Kleine-Budde { 1517eb79a267SMarc Kleine-Budde return regmap_read(priv->map_reg, MCP251XFD_REG_TBC, timestamp); 15181f0e21a0SMarc Kleine-Budde } 15191f0e21a0SMarc Kleine-Budde 15201f0e21a0SMarc Kleine-Budde static struct sk_buff * 1521eb79a267SMarc Kleine-Budde mcp251xfd_alloc_can_err_skb(const struct mcp251xfd_priv *priv, 15221f0e21a0SMarc Kleine-Budde struct can_frame **cf, u32 *timestamp) 15231f0e21a0SMarc Kleine-Budde { 15241f0e21a0SMarc Kleine-Budde int err; 15251f0e21a0SMarc Kleine-Budde 1526eb79a267SMarc Kleine-Budde err = mcp251xfd_get_timestamp(priv, timestamp); 15271f0e21a0SMarc Kleine-Budde if (err) 15281f0e21a0SMarc Kleine-Budde return NULL; 15291f0e21a0SMarc Kleine-Budde 15301f0e21a0SMarc Kleine-Budde return alloc_can_err_skb(priv->ndev, cf); 15311f0e21a0SMarc Kleine-Budde } 15321f0e21a0SMarc Kleine-Budde 1533eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_rxovif(struct mcp251xfd_priv *priv) 15341f0e21a0SMarc Kleine-Budde { 15351f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 1536eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring; 15371f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 15381f0e21a0SMarc Kleine-Budde struct can_frame *cf; 15391f0e21a0SMarc Kleine-Budde u32 timestamp, rxovif; 15401f0e21a0SMarc Kleine-Budde int err, i; 15411f0e21a0SMarc Kleine-Budde 15421f0e21a0SMarc Kleine-Budde stats->rx_over_errors++; 15431f0e21a0SMarc Kleine-Budde stats->rx_errors++; 15441f0e21a0SMarc Kleine-Budde 1545eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_RXOVIF, &rxovif); 15461f0e21a0SMarc Kleine-Budde if (err) 15471f0e21a0SMarc Kleine-Budde return err; 15481f0e21a0SMarc Kleine-Budde 1549eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, ring, i) { 15501f0e21a0SMarc Kleine-Budde if (!(rxovif & BIT(ring->fifo_nr))) 15511f0e21a0SMarc Kleine-Budde continue; 15521f0e21a0SMarc Kleine-Budde 15531f0e21a0SMarc Kleine-Budde /* If SERRIF is active, there was a RX MAB overflow. */ 1554eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_SERRIF) { 15551f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 15561f0e21a0SMarc Kleine-Budde "RX-%d: MAB overflow detected.\n", 15571f0e21a0SMarc Kleine-Budde ring->nr); 15581f0e21a0SMarc Kleine-Budde } else { 15591f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 15601f0e21a0SMarc Kleine-Budde "RX-%d: FIFO overflow.\n", ring->nr); 15611f0e21a0SMarc Kleine-Budde } 15621f0e21a0SMarc Kleine-Budde 15631f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 1564eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA(ring->fifo_nr), 1565eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA_RXOVIF, 15661f0e21a0SMarc Kleine-Budde 0x0); 15671f0e21a0SMarc Kleine-Budde if (err) 15681f0e21a0SMarc Kleine-Budde return err; 15691f0e21a0SMarc Kleine-Budde } 15701f0e21a0SMarc Kleine-Budde 1571eb79a267SMarc Kleine-Budde skb = mcp251xfd_alloc_can_err_skb(priv, &cf, ×tamp); 15721f0e21a0SMarc Kleine-Budde if (!skb) 15731f0e21a0SMarc Kleine-Budde return 0; 15741f0e21a0SMarc Kleine-Budde 15751f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_CRTL; 15761f0e21a0SMarc Kleine-Budde cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; 15771f0e21a0SMarc Kleine-Budde 15781f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 15791f0e21a0SMarc Kleine-Budde if (err) 15801f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 15811f0e21a0SMarc Kleine-Budde 15821f0e21a0SMarc Kleine-Budde return 0; 15831f0e21a0SMarc Kleine-Budde } 15841f0e21a0SMarc Kleine-Budde 1585eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_txatif(struct mcp251xfd_priv *priv) 15861f0e21a0SMarc Kleine-Budde { 15871f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", __func__); 15881f0e21a0SMarc Kleine-Budde 15891f0e21a0SMarc Kleine-Budde return 0; 15901f0e21a0SMarc Kleine-Budde } 15911f0e21a0SMarc Kleine-Budde 1592eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_ivmif(struct mcp251xfd_priv *priv) 15931f0e21a0SMarc Kleine-Budde { 15941f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 15951f0e21a0SMarc Kleine-Budde u32 bdiag1, timestamp; 15961f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 15971f0e21a0SMarc Kleine-Budde struct can_frame *cf = NULL; 15981f0e21a0SMarc Kleine-Budde int err; 15991f0e21a0SMarc Kleine-Budde 1600eb79a267SMarc Kleine-Budde err = mcp251xfd_get_timestamp(priv, ×tamp); 16011f0e21a0SMarc Kleine-Budde if (err) 16021f0e21a0SMarc Kleine-Budde return err; 16031f0e21a0SMarc Kleine-Budde 1604eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_BDIAG1, &bdiag1); 16051f0e21a0SMarc Kleine-Budde if (err) 16061f0e21a0SMarc Kleine-Budde return err; 16071f0e21a0SMarc Kleine-Budde 16081f0e21a0SMarc Kleine-Budde /* Write 0s to clear error bits, don't write 1s to non active 16091f0e21a0SMarc Kleine-Budde * bits, as they will be set. 16101f0e21a0SMarc Kleine-Budde */ 1611eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_BDIAG1, 0x0); 16121f0e21a0SMarc Kleine-Budde if (err) 16131f0e21a0SMarc Kleine-Budde return err; 16141f0e21a0SMarc Kleine-Budde 16151f0e21a0SMarc Kleine-Budde priv->can.can_stats.bus_error++; 16161f0e21a0SMarc Kleine-Budde 16171f0e21a0SMarc Kleine-Budde skb = alloc_can_err_skb(priv->ndev, &cf); 16181f0e21a0SMarc Kleine-Budde if (cf) 16191f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; 16201f0e21a0SMarc Kleine-Budde 16211f0e21a0SMarc Kleine-Budde /* Controller misconfiguration */ 1622eb79a267SMarc Kleine-Budde if (WARN_ON(bdiag1 & MCP251XFD_REG_BDIAG1_DLCMM)) 16231f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 16241f0e21a0SMarc Kleine-Budde "recv'd DLC is larger than PLSIZE of FIFO element."); 16251f0e21a0SMarc Kleine-Budde 16261f0e21a0SMarc Kleine-Budde /* RX errors */ 1627eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DCRCERR | 1628eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NCRCERR)) { 16291f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "CRC error\n"); 16301f0e21a0SMarc Kleine-Budde 16311f0e21a0SMarc Kleine-Budde stats->rx_errors++; 16321f0e21a0SMarc Kleine-Budde if (cf) 16331f0e21a0SMarc Kleine-Budde cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; 16341f0e21a0SMarc Kleine-Budde } 1635eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DSTUFERR | 1636eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NSTUFERR)) { 16371f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Stuff error\n"); 16381f0e21a0SMarc Kleine-Budde 16391f0e21a0SMarc Kleine-Budde stats->rx_errors++; 16401f0e21a0SMarc Kleine-Budde if (cf) 16411f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_STUFF; 16421f0e21a0SMarc Kleine-Budde } 1643eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DFORMERR | 1644eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NFORMERR)) { 16451f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Format error\n"); 16461f0e21a0SMarc Kleine-Budde 16471f0e21a0SMarc Kleine-Budde stats->rx_errors++; 16481f0e21a0SMarc Kleine-Budde if (cf) 16491f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_FORM; 16501f0e21a0SMarc Kleine-Budde } 16511f0e21a0SMarc Kleine-Budde 16521f0e21a0SMarc Kleine-Budde /* TX errors */ 1653eb79a267SMarc Kleine-Budde if (bdiag1 & MCP251XFD_REG_BDIAG1_NACKERR) { 16541f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "NACK error\n"); 16551f0e21a0SMarc Kleine-Budde 16561f0e21a0SMarc Kleine-Budde stats->tx_errors++; 16571f0e21a0SMarc Kleine-Budde if (cf) { 16581f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_ACK; 16591f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX; 16601f0e21a0SMarc Kleine-Budde } 16611f0e21a0SMarc Kleine-Budde } 1662eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT1ERR | 1663eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NBIT1ERR)) { 16641f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit1 error\n"); 16651f0e21a0SMarc Kleine-Budde 16661f0e21a0SMarc Kleine-Budde stats->tx_errors++; 16671f0e21a0SMarc Kleine-Budde if (cf) 16681f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT1; 16691f0e21a0SMarc Kleine-Budde } 1670eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT0ERR | 1671eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NBIT0ERR)) { 16721f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit0 error\n"); 16731f0e21a0SMarc Kleine-Budde 16741f0e21a0SMarc Kleine-Budde stats->tx_errors++; 16751f0e21a0SMarc Kleine-Budde if (cf) 16761f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT0; 16771f0e21a0SMarc Kleine-Budde } 16781f0e21a0SMarc Kleine-Budde 16791f0e21a0SMarc Kleine-Budde if (!cf) 16801f0e21a0SMarc Kleine-Budde return 0; 16811f0e21a0SMarc Kleine-Budde 16821f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 16831f0e21a0SMarc Kleine-Budde if (err) 16841f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 16851f0e21a0SMarc Kleine-Budde 16861f0e21a0SMarc Kleine-Budde return 0; 16871f0e21a0SMarc Kleine-Budde } 16881f0e21a0SMarc Kleine-Budde 1689eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv) 16901f0e21a0SMarc Kleine-Budde { 16911f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 16921f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 16931f0e21a0SMarc Kleine-Budde struct can_frame *cf = NULL; 16941f0e21a0SMarc Kleine-Budde enum can_state new_state, rx_state, tx_state; 16951f0e21a0SMarc Kleine-Budde u32 trec, timestamp; 16961f0e21a0SMarc Kleine-Budde int err; 16971f0e21a0SMarc Kleine-Budde 1698eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec); 16991f0e21a0SMarc Kleine-Budde if (err) 17001f0e21a0SMarc Kleine-Budde return err; 17011f0e21a0SMarc Kleine-Budde 1702eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_TXBO) 17031f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_BUS_OFF; 1704eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_TXBP) 17051f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_PASSIVE; 1706eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_TXWARN) 17071f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_WARNING; 17081f0e21a0SMarc Kleine-Budde else 17091f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_ACTIVE; 17101f0e21a0SMarc Kleine-Budde 1711eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_RXBP) 17121f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_PASSIVE; 1713eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_RXWARN) 17141f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_WARNING; 17151f0e21a0SMarc Kleine-Budde else 17161f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_ACTIVE; 17171f0e21a0SMarc Kleine-Budde 17181f0e21a0SMarc Kleine-Budde new_state = max(tx_state, rx_state); 17191f0e21a0SMarc Kleine-Budde if (new_state == priv->can.state) 17201f0e21a0SMarc Kleine-Budde return 0; 17211f0e21a0SMarc Kleine-Budde 17221f0e21a0SMarc Kleine-Budde /* The skb allocation might fail, but can_change_state() 17231f0e21a0SMarc Kleine-Budde * handles cf == NULL. 17241f0e21a0SMarc Kleine-Budde */ 1725eb79a267SMarc Kleine-Budde skb = mcp251xfd_alloc_can_err_skb(priv, &cf, ×tamp); 17261f0e21a0SMarc Kleine-Budde can_change_state(priv->ndev, cf, tx_state, rx_state); 17271f0e21a0SMarc Kleine-Budde 17281f0e21a0SMarc Kleine-Budde if (new_state == CAN_STATE_BUS_OFF) { 17291f0e21a0SMarc Kleine-Budde /* As we're going to switch off the chip now, let's 17301f0e21a0SMarc Kleine-Budde * save the error counters and return them to 17311f0e21a0SMarc Kleine-Budde * userspace, if do_get_berr_counter() is called while 17321f0e21a0SMarc Kleine-Budde * the chip is in Bus Off. 17331f0e21a0SMarc Kleine-Budde */ 1734eb79a267SMarc Kleine-Budde err = __mcp251xfd_get_berr_counter(priv->ndev, &priv->bec); 17351f0e21a0SMarc Kleine-Budde if (err) 17361f0e21a0SMarc Kleine-Budde return err; 17371f0e21a0SMarc Kleine-Budde 1738eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_BUS_OFF); 17391f0e21a0SMarc Kleine-Budde can_bus_off(priv->ndev); 17401f0e21a0SMarc Kleine-Budde } 17411f0e21a0SMarc Kleine-Budde 17421f0e21a0SMarc Kleine-Budde if (!skb) 17431f0e21a0SMarc Kleine-Budde return 0; 17441f0e21a0SMarc Kleine-Budde 17451f0e21a0SMarc Kleine-Budde if (new_state != CAN_STATE_BUS_OFF) { 17461f0e21a0SMarc Kleine-Budde struct can_berr_counter bec; 17471f0e21a0SMarc Kleine-Budde 1748eb79a267SMarc Kleine-Budde err = mcp251xfd_get_berr_counter(priv->ndev, &bec); 17491f0e21a0SMarc Kleine-Budde if (err) 17501f0e21a0SMarc Kleine-Budde return err; 17511f0e21a0SMarc Kleine-Budde cf->data[6] = bec.txerr; 17521f0e21a0SMarc Kleine-Budde cf->data[7] = bec.rxerr; 17531f0e21a0SMarc Kleine-Budde } 17541f0e21a0SMarc Kleine-Budde 17551f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 17561f0e21a0SMarc Kleine-Budde if (err) 17571f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 17581f0e21a0SMarc Kleine-Budde 17591f0e21a0SMarc Kleine-Budde return 0; 17601f0e21a0SMarc Kleine-Budde } 17611f0e21a0SMarc Kleine-Budde 17621f0e21a0SMarc Kleine-Budde static int 1763eb79a267SMarc Kleine-Budde mcp251xfd_handle_modif(const struct mcp251xfd_priv *priv, bool *set_normal_mode) 17641f0e21a0SMarc Kleine-Budde { 1765eb79a267SMarc Kleine-Budde const u8 mode_reference = mcp251xfd_get_normal_mode(priv); 17661f0e21a0SMarc Kleine-Budde u8 mode; 17671f0e21a0SMarc Kleine-Budde int err; 17681f0e21a0SMarc Kleine-Budde 1769eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_get_mode(priv, &mode); 17701f0e21a0SMarc Kleine-Budde if (err) 17711f0e21a0SMarc Kleine-Budde return err; 17721f0e21a0SMarc Kleine-Budde 17731f0e21a0SMarc Kleine-Budde if (mode == mode_reference) { 17741f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 17751f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1776eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 17771f0e21a0SMarc Kleine-Budde return 0; 17781f0e21a0SMarc Kleine-Budde } 17791f0e21a0SMarc Kleine-Budde 17801f0e21a0SMarc Kleine-Budde /* According to MCP2517FD errata DS80000792B 1., during a TX 17811f0e21a0SMarc Kleine-Budde * MAB underflow, the controller will transition to Restricted 17821f0e21a0SMarc Kleine-Budde * Operation Mode or Listen Only Mode (depending on SERR2LOM). 17831f0e21a0SMarc Kleine-Budde * 17841f0e21a0SMarc Kleine-Budde * However this is not always the case. If SERR2LOM is 17851f0e21a0SMarc Kleine-Budde * configured for Restricted Operation Mode (SERR2LOM not set) 17861f0e21a0SMarc Kleine-Budde * the MCP2517FD will sometimes transition to Listen Only Mode 17871f0e21a0SMarc Kleine-Budde * first. When polling this bit we see that it will transition 17881f0e21a0SMarc Kleine-Budde * to Restricted Operation Mode shortly after. 17891f0e21a0SMarc Kleine-Budde */ 1790eb79a267SMarc Kleine-Budde if ((priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN) && 1791eb79a267SMarc Kleine-Budde (mode == MCP251XFD_REG_CON_MODE_RESTRICTED || 1792eb79a267SMarc Kleine-Budde mode == MCP251XFD_REG_CON_MODE_LISTENONLY)) 17931f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 17941f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1795eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 17961f0e21a0SMarc Kleine-Budde else 17971f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 17981f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1799eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 18001f0e21a0SMarc Kleine-Budde 18011f0e21a0SMarc Kleine-Budde /* After the application requests Normal mode, the Controller 18021f0e21a0SMarc Kleine-Budde * will automatically attempt to retransmit the message that 18031f0e21a0SMarc Kleine-Budde * caused the TX MAB underflow. 18041f0e21a0SMarc Kleine-Budde * 18051f0e21a0SMarc Kleine-Budde * However, if there is an ECC error in the TX-RAM, we first 18061f0e21a0SMarc Kleine-Budde * have to reload the tx-object before requesting Normal 1807eb79a267SMarc Kleine-Budde * mode. This is done later in mcp251xfd_handle_eccif(). 18081f0e21a0SMarc Kleine-Budde */ 1809eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF) { 18101f0e21a0SMarc Kleine-Budde *set_normal_mode = true; 18111f0e21a0SMarc Kleine-Budde return 0; 18121f0e21a0SMarc Kleine-Budde } 18131f0e21a0SMarc Kleine-Budde 1814eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode_nowait(priv); 18151f0e21a0SMarc Kleine-Budde } 18161f0e21a0SMarc Kleine-Budde 1817eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_serrif(struct mcp251xfd_priv *priv) 18181f0e21a0SMarc Kleine-Budde { 1819eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 18201f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 18211f0e21a0SMarc Kleine-Budde bool handled = false; 18221f0e21a0SMarc Kleine-Budde 18231f0e21a0SMarc Kleine-Budde /* TX MAB underflow 18241f0e21a0SMarc Kleine-Budde * 18251f0e21a0SMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a TX MAB 18261f0e21a0SMarc Kleine-Budde * underflow is indicated by SERRIF and MODIF. 18271f0e21a0SMarc Kleine-Budde * 18281f0e21a0SMarc Kleine-Budde * In addition to the effects mentioned in the Errata, there 18291f0e21a0SMarc Kleine-Budde * are Bus Errors due to the aborted CAN frame, so a IVMIF 18301f0e21a0SMarc Kleine-Budde * will be seen as well. 18311f0e21a0SMarc Kleine-Budde * 18321f0e21a0SMarc Kleine-Budde * Sometimes there is an ECC error in the TX-RAM, which leads 18331f0e21a0SMarc Kleine-Budde * to a TX MAB underflow. 18341f0e21a0SMarc Kleine-Budde * 18351f0e21a0SMarc Kleine-Budde * However, probably due to a race condition, there is no 18361f0e21a0SMarc Kleine-Budde * associated MODIF pending. 18371f0e21a0SMarc Kleine-Budde * 18381f0e21a0SMarc Kleine-Budde * Further, there are situations, where the SERRIF is caused 18391f0e21a0SMarc Kleine-Budde * by an ECC error in the TX-RAM, but not even the ECCIF is 18401f0e21a0SMarc Kleine-Budde * set. This only seems to happen _after_ the first occurrence 18411f0e21a0SMarc Kleine-Budde * of a ECCIF (which is tracked in ecc->cnt). 18421f0e21a0SMarc Kleine-Budde * 18431f0e21a0SMarc Kleine-Budde * Treat all as a known system errors.. 18441f0e21a0SMarc Kleine-Budde */ 1845eb79a267SMarc Kleine-Budde if ((priv->regs_status.intf & MCP251XFD_REG_INT_MODIF && 1846eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_IVMIF) || 1847eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF || 18481f0e21a0SMarc Kleine-Budde ecc->cnt) { 18491f0e21a0SMarc Kleine-Budde const char *msg; 18501f0e21a0SMarc Kleine-Budde 1851eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF || 18521f0e21a0SMarc Kleine-Budde ecc->cnt) 18531f0e21a0SMarc Kleine-Budde msg = "TX MAB underflow due to ECC error detected."; 18541f0e21a0SMarc Kleine-Budde else 18551f0e21a0SMarc Kleine-Budde msg = "TX MAB underflow detected."; 18561f0e21a0SMarc Kleine-Budde 1857eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN) 18581f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "%s\n", msg); 18591f0e21a0SMarc Kleine-Budde else 18601f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", msg); 18611f0e21a0SMarc Kleine-Budde 18621f0e21a0SMarc Kleine-Budde stats->tx_aborted_errors++; 18631f0e21a0SMarc Kleine-Budde stats->tx_errors++; 18641f0e21a0SMarc Kleine-Budde handled = true; 18651f0e21a0SMarc Kleine-Budde } 18661f0e21a0SMarc Kleine-Budde 18671f0e21a0SMarc Kleine-Budde /* RX MAB overflow 18681f0e21a0SMarc Kleine-Budde * 18691f0e21a0SMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a RX MAB 18701f0e21a0SMarc Kleine-Budde * overflow is indicated by SERRIF. 18711f0e21a0SMarc Kleine-Budde * 18721f0e21a0SMarc Kleine-Budde * In addition to the effects mentioned in the Errata, (most 18731f0e21a0SMarc Kleine-Budde * of the times) a RXOVIF is raised, if the FIFO that is being 18741f0e21a0SMarc Kleine-Budde * received into has the RXOVIE activated (and we have enabled 18751f0e21a0SMarc Kleine-Budde * RXOVIE on all FIFOs). 18761f0e21a0SMarc Kleine-Budde * 18771f0e21a0SMarc Kleine-Budde * Sometimes there is no RXOVIF just a RXIF is pending. 18781f0e21a0SMarc Kleine-Budde * 18791f0e21a0SMarc Kleine-Budde * Treat all as a known system errors.. 18801f0e21a0SMarc Kleine-Budde */ 1881eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_RXOVIF || 1882eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_RXIF) { 18831f0e21a0SMarc Kleine-Budde stats->rx_dropped++; 18841f0e21a0SMarc Kleine-Budde handled = true; 18851f0e21a0SMarc Kleine-Budde } 18861f0e21a0SMarc Kleine-Budde 18871f0e21a0SMarc Kleine-Budde if (!handled) 18881f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 18891f0e21a0SMarc Kleine-Budde "Unhandled System Error Interrupt (intf=0x%08x)!\n", 18901f0e21a0SMarc Kleine-Budde priv->regs_status.intf); 18911f0e21a0SMarc Kleine-Budde 18921f0e21a0SMarc Kleine-Budde return 0; 18931f0e21a0SMarc Kleine-Budde } 18941f0e21a0SMarc Kleine-Budde 18951f0e21a0SMarc Kleine-Budde static int 1896eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif_recover(struct mcp251xfd_priv *priv, u8 nr) 18971f0e21a0SMarc Kleine-Budde { 1898eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 1899eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 1900eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 19011f0e21a0SMarc Kleine-Budde u8 chip_tx_tail, tx_tail, offset; 19021f0e21a0SMarc Kleine-Budde u16 addr; 19031f0e21a0SMarc Kleine-Budde int err; 19041f0e21a0SMarc Kleine-Budde 1905eb79a267SMarc Kleine-Budde addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc->ecc_stat); 19061f0e21a0SMarc Kleine-Budde 1907eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail); 19081f0e21a0SMarc Kleine-Budde if (err) 19091f0e21a0SMarc Kleine-Budde return err; 19101f0e21a0SMarc Kleine-Budde 1911eb79a267SMarc Kleine-Budde tx_tail = mcp251xfd_get_tx_tail(tx_ring); 19121f0e21a0SMarc Kleine-Budde offset = (nr - chip_tx_tail) & (tx_ring->obj_num - 1); 19131f0e21a0SMarc Kleine-Budde 19141f0e21a0SMarc Kleine-Budde /* Bail out if one of the following is met: 19151f0e21a0SMarc Kleine-Budde * - tx_tail information is inconsistent 19161f0e21a0SMarc Kleine-Budde * - for mcp2517fd: offset not 0 19171f0e21a0SMarc Kleine-Budde * - for mcp2518fd: offset not 0 or 1 19181f0e21a0SMarc Kleine-Budde */ 19191f0e21a0SMarc Kleine-Budde if (chip_tx_tail != tx_tail || 1920eb79a267SMarc Kleine-Budde !(offset == 0 || (offset == 1 && mcp251xfd_is_2518(priv)))) { 19211f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 19221f0e21a0SMarc Kleine-Budde "ECC Error information inconsistent (addr=0x%04x, nr=%d, tx_tail=0x%08x(%d), chip_tx_tail=%d, offset=%d).\n", 19231f0e21a0SMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, chip_tx_tail, 19241f0e21a0SMarc Kleine-Budde offset); 19251f0e21a0SMarc Kleine-Budde return -EINVAL; 19261f0e21a0SMarc Kleine-Budde } 19271f0e21a0SMarc Kleine-Budde 19281f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 19291f0e21a0SMarc Kleine-Budde "Recovering %s ECC Error at address 0x%04x (in TX-RAM, tx_obj=%d, tx_tail=0x%08x(%d), offset=%d).\n", 1930eb79a267SMarc Kleine-Budde ecc->ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF ? 19311f0e21a0SMarc Kleine-Budde "Single" : "Double", 19321f0e21a0SMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, offset); 19331f0e21a0SMarc Kleine-Budde 19341f0e21a0SMarc Kleine-Budde /* reload tx_obj into controller RAM ... */ 19351f0e21a0SMarc Kleine-Budde tx_obj = &tx_ring->obj[nr]; 19361f0e21a0SMarc Kleine-Budde err = spi_sync_transfer(priv->spi, tx_obj->xfer, 1); 19371f0e21a0SMarc Kleine-Budde if (err) 19381f0e21a0SMarc Kleine-Budde return err; 19391f0e21a0SMarc Kleine-Budde 19401f0e21a0SMarc Kleine-Budde /* ... and trigger retransmit */ 1941eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode(priv); 19421f0e21a0SMarc Kleine-Budde } 19431f0e21a0SMarc Kleine-Budde 19441f0e21a0SMarc Kleine-Budde static int 1945eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif(struct mcp251xfd_priv *priv, bool set_normal_mode) 19461f0e21a0SMarc Kleine-Budde { 1947eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 19481f0e21a0SMarc Kleine-Budde const char *msg; 19491f0e21a0SMarc Kleine-Budde bool in_tx_ram; 19501f0e21a0SMarc Kleine-Budde u32 ecc_stat; 19511f0e21a0SMarc Kleine-Budde u16 addr; 19521f0e21a0SMarc Kleine-Budde u8 nr; 19531f0e21a0SMarc Kleine-Budde int err; 19541f0e21a0SMarc Kleine-Budde 1955eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_ECCSTAT, &ecc_stat); 19561f0e21a0SMarc Kleine-Budde if (err) 19571f0e21a0SMarc Kleine-Budde return err; 19581f0e21a0SMarc Kleine-Budde 1959eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCSTAT, 1960eb79a267SMarc Kleine-Budde MCP251XFD_REG_ECCSTAT_IF_MASK, ~ecc_stat); 19611f0e21a0SMarc Kleine-Budde if (err) 19621f0e21a0SMarc Kleine-Budde return err; 19631f0e21a0SMarc Kleine-Budde 19641f0e21a0SMarc Kleine-Budde /* Check if ECC error occurred in TX-RAM */ 1965eb79a267SMarc Kleine-Budde addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc_stat); 1966eb79a267SMarc Kleine-Budde err = mcp251xfd_get_tx_nr_by_addr(priv->tx, &nr, addr); 19671f0e21a0SMarc Kleine-Budde if (!err) 19681f0e21a0SMarc Kleine-Budde in_tx_ram = true; 19691f0e21a0SMarc Kleine-Budde else if (err == -ENOENT) 19701f0e21a0SMarc Kleine-Budde in_tx_ram = false; 19711f0e21a0SMarc Kleine-Budde else 19721f0e21a0SMarc Kleine-Budde return err; 19731f0e21a0SMarc Kleine-Budde 19741f0e21a0SMarc Kleine-Budde /* Errata Reference: 19751f0e21a0SMarc Kleine-Budde * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 2. 19761f0e21a0SMarc Kleine-Budde * 19771f0e21a0SMarc Kleine-Budde * ECC single error correction does not work in all cases: 19781f0e21a0SMarc Kleine-Budde * 19791f0e21a0SMarc Kleine-Budde * Fix/Work Around: 19801f0e21a0SMarc Kleine-Budde * Enable single error correction and double error detection 19811f0e21a0SMarc Kleine-Budde * interrupts by setting SECIE and DEDIE. Handle SECIF as a 19821f0e21a0SMarc Kleine-Budde * detection interrupt and do not rely on the error 19831f0e21a0SMarc Kleine-Budde * correction. Instead, handle both interrupts as a 19841f0e21a0SMarc Kleine-Budde * notification that the RAM word at ERRADDR was corrupted. 19851f0e21a0SMarc Kleine-Budde */ 1986eb79a267SMarc Kleine-Budde if (ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF) 19871f0e21a0SMarc Kleine-Budde msg = "Single ECC Error detected at address"; 1988eb79a267SMarc Kleine-Budde else if (ecc_stat & MCP251XFD_REG_ECCSTAT_DEDIF) 19891f0e21a0SMarc Kleine-Budde msg = "Double ECC Error detected at address"; 19901f0e21a0SMarc Kleine-Budde else 19911f0e21a0SMarc Kleine-Budde return -EINVAL; 19921f0e21a0SMarc Kleine-Budde 19931f0e21a0SMarc Kleine-Budde if (!in_tx_ram) { 19941f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 19951f0e21a0SMarc Kleine-Budde 19961f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, "%s 0x%04x.\n", msg, addr); 19971f0e21a0SMarc Kleine-Budde } else { 19981f0e21a0SMarc Kleine-Budde /* Re-occurring error? */ 19991f0e21a0SMarc Kleine-Budde if (ecc->ecc_stat == ecc_stat) { 20001f0e21a0SMarc Kleine-Budde ecc->cnt++; 20011f0e21a0SMarc Kleine-Budde } else { 20021f0e21a0SMarc Kleine-Budde ecc->ecc_stat = ecc_stat; 20031f0e21a0SMarc Kleine-Budde ecc->cnt = 1; 20041f0e21a0SMarc Kleine-Budde } 20051f0e21a0SMarc Kleine-Budde 20061f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 20071f0e21a0SMarc Kleine-Budde "%s 0x%04x (in TX-RAM, tx_obj=%d), occurred %d time%s.\n", 20081f0e21a0SMarc Kleine-Budde msg, addr, nr, ecc->cnt, ecc->cnt > 1 ? "s" : ""); 20091f0e21a0SMarc Kleine-Budde 2010eb79a267SMarc Kleine-Budde if (ecc->cnt >= MCP251XFD_ECC_CNT_MAX) 2011eb79a267SMarc Kleine-Budde return mcp251xfd_handle_eccif_recover(priv, nr); 20121f0e21a0SMarc Kleine-Budde } 20131f0e21a0SMarc Kleine-Budde 20141f0e21a0SMarc Kleine-Budde if (set_normal_mode) 2015eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode_nowait(priv); 20161f0e21a0SMarc Kleine-Budde 20171f0e21a0SMarc Kleine-Budde return 0; 20181f0e21a0SMarc Kleine-Budde } 20191f0e21a0SMarc Kleine-Budde 2020eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_spicrcif(struct mcp251xfd_priv *priv) 20211f0e21a0SMarc Kleine-Budde { 20221f0e21a0SMarc Kleine-Budde int err; 20231f0e21a0SMarc Kleine-Budde u32 crc; 20241f0e21a0SMarc Kleine-Budde 2025eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_CRC, &crc); 20261f0e21a0SMarc Kleine-Budde if (err) 20271f0e21a0SMarc Kleine-Budde return err; 20281f0e21a0SMarc Kleine-Budde 2029eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CRC, 2030eb79a267SMarc Kleine-Budde MCP251XFD_REG_CRC_IF_MASK, 20311f0e21a0SMarc Kleine-Budde ~crc); 20321f0e21a0SMarc Kleine-Budde if (err) 20331f0e21a0SMarc Kleine-Budde return err; 20341f0e21a0SMarc Kleine-Budde 2035eb79a267SMarc Kleine-Budde if (crc & MCP251XFD_REG_CRC_FERRIF) 20361f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, "CRC write command format error.\n"); 2037eb79a267SMarc Kleine-Budde else if (crc & MCP251XFD_REG_CRC_CRCERRIF) 20381f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, 20391f0e21a0SMarc Kleine-Budde "CRC write error detected. CRC=0x%04lx.\n", 2040eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_CRC_MASK, crc)); 20411f0e21a0SMarc Kleine-Budde 20421f0e21a0SMarc Kleine-Budde return 0; 20431f0e21a0SMarc Kleine-Budde } 20441f0e21a0SMarc Kleine-Budde 2045eb79a267SMarc Kleine-Budde #define mcp251xfd_handle(priv, irq, ...) \ 20461f0e21a0SMarc Kleine-Budde ({ \ 2047eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *_priv = (priv); \ 20481f0e21a0SMarc Kleine-Budde int err; \ 20491f0e21a0SMarc Kleine-Budde \ 2050eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_##irq(_priv, ## __VA_ARGS__); \ 20511f0e21a0SMarc Kleine-Budde if (err) \ 20521f0e21a0SMarc Kleine-Budde netdev_err(_priv->ndev, \ 2053eb79a267SMarc Kleine-Budde "IRQ handler mcp251xfd_handle_%s() returned %d.\n", \ 20541f0e21a0SMarc Kleine-Budde __stringify(irq), err); \ 20551f0e21a0SMarc Kleine-Budde err; \ 20561f0e21a0SMarc Kleine-Budde }) 20571f0e21a0SMarc Kleine-Budde 2058eb79a267SMarc Kleine-Budde static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) 20591f0e21a0SMarc Kleine-Budde { 2060eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = dev_id; 20611f0e21a0SMarc Kleine-Budde irqreturn_t handled = IRQ_NONE; 20621f0e21a0SMarc Kleine-Budde int err; 20631f0e21a0SMarc Kleine-Budde 20641f0e21a0SMarc Kleine-Budde if (priv->rx_int) 20651f0e21a0SMarc Kleine-Budde do { 20661f0e21a0SMarc Kleine-Budde int rx_pending; 20671f0e21a0SMarc Kleine-Budde 20681f0e21a0SMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 20691f0e21a0SMarc Kleine-Budde if (!rx_pending) 20701f0e21a0SMarc Kleine-Budde break; 20711f0e21a0SMarc Kleine-Budde 2072eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxif); 20731f0e21a0SMarc Kleine-Budde if (err) 20741f0e21a0SMarc Kleine-Budde goto out_fail; 20751f0e21a0SMarc Kleine-Budde 20761f0e21a0SMarc Kleine-Budde handled = IRQ_HANDLED; 20771f0e21a0SMarc Kleine-Budde } while (1); 20781f0e21a0SMarc Kleine-Budde 20791f0e21a0SMarc Kleine-Budde do { 20801f0e21a0SMarc Kleine-Budde u32 intf_pending, intf_pending_clearable; 20811f0e21a0SMarc Kleine-Budde bool set_normal_mode = false; 20821f0e21a0SMarc Kleine-Budde 2083eb79a267SMarc Kleine-Budde err = regmap_bulk_read(priv->map_reg, MCP251XFD_REG_INT, 20841f0e21a0SMarc Kleine-Budde &priv->regs_status, 20851f0e21a0SMarc Kleine-Budde sizeof(priv->regs_status) / 20861f0e21a0SMarc Kleine-Budde sizeof(u32)); 20871f0e21a0SMarc Kleine-Budde if (err) 20881f0e21a0SMarc Kleine-Budde goto out_fail; 20891f0e21a0SMarc Kleine-Budde 2090eb79a267SMarc Kleine-Budde intf_pending = FIELD_GET(MCP251XFD_REG_INT_IF_MASK, 20911f0e21a0SMarc Kleine-Budde priv->regs_status.intf) & 2092eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_INT_IE_MASK, 20931f0e21a0SMarc Kleine-Budde priv->regs_status.intf); 20941f0e21a0SMarc Kleine-Budde 20951f0e21a0SMarc Kleine-Budde if (!(intf_pending)) 20961f0e21a0SMarc Kleine-Budde return handled; 20971f0e21a0SMarc Kleine-Budde 20981f0e21a0SMarc Kleine-Budde /* Some interrupts must be ACKed in the 2099eb79a267SMarc Kleine-Budde * MCP251XFD_REG_INT register. 21001f0e21a0SMarc Kleine-Budde * - First ACK then handle, to avoid lost-IRQ race 21011f0e21a0SMarc Kleine-Budde * condition on fast re-occurring interrupts. 21021f0e21a0SMarc Kleine-Budde * - Write "0" to clear active IRQs, "1" to all other, 21031f0e21a0SMarc Kleine-Budde * to avoid r/m/w race condition on the 2104eb79a267SMarc Kleine-Budde * MCP251XFD_REG_INT register. 21051f0e21a0SMarc Kleine-Budde */ 21061f0e21a0SMarc Kleine-Budde intf_pending_clearable = intf_pending & 2107eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_IF_CLEARABLE_MASK; 21081f0e21a0SMarc Kleine-Budde if (intf_pending_clearable) { 21091f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 2110eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT, 2111eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_IF_MASK, 21121f0e21a0SMarc Kleine-Budde ~intf_pending_clearable); 21131f0e21a0SMarc Kleine-Budde if (err) 21141f0e21a0SMarc Kleine-Budde goto out_fail; 21151f0e21a0SMarc Kleine-Budde } 21161f0e21a0SMarc Kleine-Budde 2117eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_MODIF) { 2118eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, modif, &set_normal_mode); 21191f0e21a0SMarc Kleine-Budde if (err) 21201f0e21a0SMarc Kleine-Budde goto out_fail; 21211f0e21a0SMarc Kleine-Budde } 21221f0e21a0SMarc Kleine-Budde 2123eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_RXIF) { 2124eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxif); 21251f0e21a0SMarc Kleine-Budde if (err) 21261f0e21a0SMarc Kleine-Budde goto out_fail; 21271f0e21a0SMarc Kleine-Budde } 21281f0e21a0SMarc Kleine-Budde 2129eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_TEFIF) { 2130eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, tefif); 21311f0e21a0SMarc Kleine-Budde if (err) 21321f0e21a0SMarc Kleine-Budde goto out_fail; 21331f0e21a0SMarc Kleine-Budde } 21341f0e21a0SMarc Kleine-Budde 2135eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_RXOVIF) { 2136eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxovif); 21371f0e21a0SMarc Kleine-Budde if (err) 21381f0e21a0SMarc Kleine-Budde goto out_fail; 21391f0e21a0SMarc Kleine-Budde } 21401f0e21a0SMarc Kleine-Budde 2141eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_TXATIF) { 2142eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, txatif); 21431f0e21a0SMarc Kleine-Budde if (err) 21441f0e21a0SMarc Kleine-Budde goto out_fail; 21451f0e21a0SMarc Kleine-Budde } 21461f0e21a0SMarc Kleine-Budde 2147eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_IVMIF) { 2148eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, ivmif); 21491f0e21a0SMarc Kleine-Budde if (err) 21501f0e21a0SMarc Kleine-Budde goto out_fail; 21511f0e21a0SMarc Kleine-Budde } 21521f0e21a0SMarc Kleine-Budde 2153eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_SERRIF) { 2154eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, serrif); 21551f0e21a0SMarc Kleine-Budde if (err) 21561f0e21a0SMarc Kleine-Budde goto out_fail; 21571f0e21a0SMarc Kleine-Budde } 21581f0e21a0SMarc Kleine-Budde 2159eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_ECCIF) { 2160eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, eccif, set_normal_mode); 21611f0e21a0SMarc Kleine-Budde if (err) 21621f0e21a0SMarc Kleine-Budde goto out_fail; 21631f0e21a0SMarc Kleine-Budde } 21641f0e21a0SMarc Kleine-Budde 2165eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_SPICRCIF) { 2166eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, spicrcif); 21671f0e21a0SMarc Kleine-Budde if (err) 21681f0e21a0SMarc Kleine-Budde goto out_fail; 21691f0e21a0SMarc Kleine-Budde } 21701f0e21a0SMarc Kleine-Budde 21711f0e21a0SMarc Kleine-Budde /* On the MCP2527FD and MCP2518FD, we don't get a 21721f0e21a0SMarc Kleine-Budde * CERRIF IRQ on the transition TX ERROR_WARNING -> TX 21731f0e21a0SMarc Kleine-Budde * ERROR_ACTIVE. 21741f0e21a0SMarc Kleine-Budde */ 2175eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_CERRIF || 21761f0e21a0SMarc Kleine-Budde priv->can.state > CAN_STATE_ERROR_ACTIVE) { 2177eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, cerrif); 21781f0e21a0SMarc Kleine-Budde if (err) 21791f0e21a0SMarc Kleine-Budde goto out_fail; 21801f0e21a0SMarc Kleine-Budde 21811f0e21a0SMarc Kleine-Budde /* In Bus Off we completely shut down the 21821f0e21a0SMarc Kleine-Budde * controller. Every subsequent register read 21831f0e21a0SMarc Kleine-Budde * will read bogus data, and if 2184eb79a267SMarc Kleine-Budde * MCP251XFD_QUIRK_CRC_REG is enabled the CRC 21851f0e21a0SMarc Kleine-Budde * check will fail, too. So leave IRQ handler 21861f0e21a0SMarc Kleine-Budde * directly. 21871f0e21a0SMarc Kleine-Budde */ 21881f0e21a0SMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) 21891f0e21a0SMarc Kleine-Budde return IRQ_HANDLED; 21901f0e21a0SMarc Kleine-Budde } 21911f0e21a0SMarc Kleine-Budde 21921f0e21a0SMarc Kleine-Budde handled = IRQ_HANDLED; 21931f0e21a0SMarc Kleine-Budde } while (1); 21941f0e21a0SMarc Kleine-Budde 21951f0e21a0SMarc Kleine-Budde out_fail: 21961f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n", 21971f0e21a0SMarc Kleine-Budde err, priv->regs_status.intf); 2198eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 21991f0e21a0SMarc Kleine-Budde 22001f0e21a0SMarc Kleine-Budde return handled; 22011f0e21a0SMarc Kleine-Budde } 22021f0e21a0SMarc Kleine-Budde 22031f0e21a0SMarc Kleine-Budde static inline struct 2204eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj *mcp251xfd_get_tx_obj_next(struct mcp251xfd_tx_ring *tx_ring) 22051f0e21a0SMarc Kleine-Budde { 22061f0e21a0SMarc Kleine-Budde u8 tx_head; 22071f0e21a0SMarc Kleine-Budde 2208eb79a267SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 22091f0e21a0SMarc Kleine-Budde 22101f0e21a0SMarc Kleine-Budde return &tx_ring->obj[tx_head]; 22111f0e21a0SMarc Kleine-Budde } 22121f0e21a0SMarc Kleine-Budde 22131f0e21a0SMarc Kleine-Budde static void 2214eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv, 2215eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj, 22161f0e21a0SMarc Kleine-Budde const struct sk_buff *skb, 22171f0e21a0SMarc Kleine-Budde unsigned int seq) 22181f0e21a0SMarc Kleine-Budde { 22191f0e21a0SMarc Kleine-Budde const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 2220eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_tx_obj_raw *hw_tx_obj; 2221eb79a267SMarc Kleine-Budde union mcp251xfd_tx_obj_load_buf *load_buf; 22221f0e21a0SMarc Kleine-Budde u8 dlc; 22231f0e21a0SMarc Kleine-Budde u32 id, flags; 22241f0e21a0SMarc Kleine-Budde int offset, len; 22251f0e21a0SMarc Kleine-Budde 22261f0e21a0SMarc Kleine-Budde if (cfd->can_id & CAN_EFF_FLAG) { 22271f0e21a0SMarc Kleine-Budde u32 sid, eid; 22281f0e21a0SMarc Kleine-Budde 2229eb79a267SMarc Kleine-Budde sid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_SID_MASK, cfd->can_id); 2230eb79a267SMarc Kleine-Budde eid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_EID_MASK, cfd->can_id); 22311f0e21a0SMarc Kleine-Budde 2232eb79a267SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_EID_MASK, eid) | 2233eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, sid); 22341f0e21a0SMarc Kleine-Budde 2235eb79a267SMarc Kleine-Budde flags = MCP251XFD_OBJ_FLAGS_IDE; 22361f0e21a0SMarc Kleine-Budde } else { 2237eb79a267SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, cfd->can_id); 22381f0e21a0SMarc Kleine-Budde flags = 0; 22391f0e21a0SMarc Kleine-Budde } 22401f0e21a0SMarc Kleine-Budde 22411f0e21a0SMarc Kleine-Budde /* Use the MCP2518FD mask even on the MCP2517FD. It doesn't 22421f0e21a0SMarc Kleine-Budde * harm, only the lower 7 bits will be transferred into the 22431f0e21a0SMarc Kleine-Budde * TEF object. 22441f0e21a0SMarc Kleine-Budde */ 22453ab4ce0dSOliver Hartkopp dlc = can_fd_len2dlc(cfd->len); 2246eb79a267SMarc Kleine-Budde flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq) | 2247eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC, dlc); 22481f0e21a0SMarc Kleine-Budde 22491f0e21a0SMarc Kleine-Budde if (cfd->can_id & CAN_RTR_FLAG) 2250eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_RTR; 22511f0e21a0SMarc Kleine-Budde 22521f0e21a0SMarc Kleine-Budde /* CANFD */ 22531f0e21a0SMarc Kleine-Budde if (can_is_canfd_skb(skb)) { 22541f0e21a0SMarc Kleine-Budde if (cfd->flags & CANFD_ESI) 2255eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_ESI; 22561f0e21a0SMarc Kleine-Budde 2257eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_FDF; 22581f0e21a0SMarc Kleine-Budde 22591f0e21a0SMarc Kleine-Budde if (cfd->flags & CANFD_BRS) 2260eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_BRS; 22611f0e21a0SMarc Kleine-Budde } 22621f0e21a0SMarc Kleine-Budde 22631f0e21a0SMarc Kleine-Budde load_buf = &tx_obj->buf; 2264eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) 22651f0e21a0SMarc Kleine-Budde hw_tx_obj = &load_buf->crc.hw_tx_obj; 22661f0e21a0SMarc Kleine-Budde else 22671f0e21a0SMarc Kleine-Budde hw_tx_obj = &load_buf->nocrc.hw_tx_obj; 22681f0e21a0SMarc Kleine-Budde 22691f0e21a0SMarc Kleine-Budde put_unaligned_le32(id, &hw_tx_obj->id); 22701f0e21a0SMarc Kleine-Budde put_unaligned_le32(flags, &hw_tx_obj->flags); 22711f0e21a0SMarc Kleine-Budde 22721f0e21a0SMarc Kleine-Budde /* Clear data at end of CAN frame */ 22731f0e21a0SMarc Kleine-Budde offset = round_down(cfd->len, sizeof(u32)); 22743ab4ce0dSOliver Hartkopp len = round_up(can_fd_dlc2len(dlc), sizeof(u32)) - offset; 2275eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN && len) 22761f0e21a0SMarc Kleine-Budde memset(hw_tx_obj->data + offset, 0x0, len); 22771f0e21a0SMarc Kleine-Budde memcpy(hw_tx_obj->data, cfd->data, cfd->len); 22781f0e21a0SMarc Kleine-Budde 22791f0e21a0SMarc Kleine-Budde /* Number of bytes to be written into the RAM of the controller */ 22801f0e21a0SMarc Kleine-Budde len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags); 2281eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN) 22823ab4ce0dSOliver Hartkopp len += round_up(can_fd_dlc2len(dlc), sizeof(u32)); 22831f0e21a0SMarc Kleine-Budde else 22841f0e21a0SMarc Kleine-Budde len += round_up(cfd->len, sizeof(u32)); 22851f0e21a0SMarc Kleine-Budde 2286eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) { 22871f0e21a0SMarc Kleine-Budde u16 crc; 22881f0e21a0SMarc Kleine-Budde 2289eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_crc_set_len_in_ram(&load_buf->crc.cmd, 22901f0e21a0SMarc Kleine-Budde len); 22911f0e21a0SMarc Kleine-Budde /* CRC */ 22921f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->crc.cmd); 2293eb79a267SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(&load_buf->crc, len); 22941f0e21a0SMarc Kleine-Budde put_unaligned_be16(crc, (void *)load_buf + len); 22951f0e21a0SMarc Kleine-Budde 22961f0e21a0SMarc Kleine-Budde /* Total length */ 22971f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->crc.crc); 22981f0e21a0SMarc Kleine-Budde } else { 22991f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->nocrc.cmd); 23001f0e21a0SMarc Kleine-Budde } 23011f0e21a0SMarc Kleine-Budde 23021f0e21a0SMarc Kleine-Budde tx_obj->xfer[0].len = len; 23031f0e21a0SMarc Kleine-Budde } 23041f0e21a0SMarc Kleine-Budde 2305eb79a267SMarc Kleine-Budde static int mcp251xfd_tx_obj_write(const struct mcp251xfd_priv *priv, 2306eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj) 23071f0e21a0SMarc Kleine-Budde { 23081f0e21a0SMarc Kleine-Budde return spi_async(priv->spi, &tx_obj->msg); 23091f0e21a0SMarc Kleine-Budde } 23101f0e21a0SMarc Kleine-Budde 2311eb79a267SMarc Kleine-Budde static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv, 2312eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring) 23131f0e21a0SMarc Kleine-Budde { 2314eb79a267SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) > 0) 23151f0e21a0SMarc Kleine-Budde return false; 23161f0e21a0SMarc Kleine-Budde 23171f0e21a0SMarc Kleine-Budde netif_stop_queue(priv->ndev); 23181f0e21a0SMarc Kleine-Budde 23191f0e21a0SMarc Kleine-Budde /* Memory barrier before checking tx_free (head and tail) */ 23201f0e21a0SMarc Kleine-Budde smp_mb(); 23211f0e21a0SMarc Kleine-Budde 2322eb79a267SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) == 0) { 23231f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 23241f0e21a0SMarc Kleine-Budde "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n", 23251f0e21a0SMarc Kleine-Budde tx_ring->head, tx_ring->tail, 23261f0e21a0SMarc Kleine-Budde tx_ring->head - tx_ring->tail); 23271f0e21a0SMarc Kleine-Budde 23281f0e21a0SMarc Kleine-Budde return true; 23291f0e21a0SMarc Kleine-Budde } 23301f0e21a0SMarc Kleine-Budde 23311f0e21a0SMarc Kleine-Budde netif_start_queue(priv->ndev); 23321f0e21a0SMarc Kleine-Budde 23331f0e21a0SMarc Kleine-Budde return false; 23341f0e21a0SMarc Kleine-Budde } 23351f0e21a0SMarc Kleine-Budde 2336eb79a267SMarc Kleine-Budde static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb, 23371f0e21a0SMarc Kleine-Budde struct net_device *ndev) 23381f0e21a0SMarc Kleine-Budde { 2339eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 2340eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 2341eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 23421f0e21a0SMarc Kleine-Budde u8 tx_head; 23431f0e21a0SMarc Kleine-Budde int err; 23441f0e21a0SMarc Kleine-Budde 23451f0e21a0SMarc Kleine-Budde if (can_dropped_invalid_skb(ndev, skb)) 23461f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 23471f0e21a0SMarc Kleine-Budde 2348eb79a267SMarc Kleine-Budde if (mcp251xfd_tx_busy(priv, tx_ring)) 23491f0e21a0SMarc Kleine-Budde return NETDEV_TX_BUSY; 23501f0e21a0SMarc Kleine-Budde 2351eb79a267SMarc Kleine-Budde tx_obj = mcp251xfd_get_tx_obj_next(tx_ring); 2352eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(priv, tx_obj, skb, tx_ring->head); 23531f0e21a0SMarc Kleine-Budde 23541f0e21a0SMarc Kleine-Budde /* Stop queue if we occupy the complete TX FIFO */ 2355eb79a267SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 23561f0e21a0SMarc Kleine-Budde tx_ring->head++; 23571f0e21a0SMarc Kleine-Budde if (tx_ring->head - tx_ring->tail >= tx_ring->obj_num) 23581f0e21a0SMarc Kleine-Budde netif_stop_queue(ndev); 23591f0e21a0SMarc Kleine-Budde 23601f0e21a0SMarc Kleine-Budde can_put_echo_skb(skb, ndev, tx_head); 23611f0e21a0SMarc Kleine-Budde 2362eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_obj_write(priv, tx_obj); 23631f0e21a0SMarc Kleine-Budde if (err) 23641f0e21a0SMarc Kleine-Budde goto out_err; 23651f0e21a0SMarc Kleine-Budde 23661f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 23671f0e21a0SMarc Kleine-Budde 23681f0e21a0SMarc Kleine-Budde out_err: 23691f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, "ERROR in %s: %d\n", __func__, err); 23701f0e21a0SMarc Kleine-Budde 23711f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 23721f0e21a0SMarc Kleine-Budde } 23731f0e21a0SMarc Kleine-Budde 2374eb79a267SMarc Kleine-Budde static int mcp251xfd_open(struct net_device *ndev) 23751f0e21a0SMarc Kleine-Budde { 2376eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 23771f0e21a0SMarc Kleine-Budde const struct spi_device *spi = priv->spi; 23781f0e21a0SMarc Kleine-Budde int err; 23791f0e21a0SMarc Kleine-Budde 23801f0e21a0SMarc Kleine-Budde err = pm_runtime_get_sync(ndev->dev.parent); 23811f0e21a0SMarc Kleine-Budde if (err < 0) { 23821f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 23831f0e21a0SMarc Kleine-Budde return err; 23841f0e21a0SMarc Kleine-Budde } 23851f0e21a0SMarc Kleine-Budde 23861f0e21a0SMarc Kleine-Budde err = open_candev(ndev); 23871f0e21a0SMarc Kleine-Budde if (err) 23881f0e21a0SMarc Kleine-Budde goto out_pm_runtime_put; 23891f0e21a0SMarc Kleine-Budde 2390eb79a267SMarc Kleine-Budde err = mcp251xfd_ring_alloc(priv); 23911f0e21a0SMarc Kleine-Budde if (err) 23921f0e21a0SMarc Kleine-Budde goto out_close_candev; 23931f0e21a0SMarc Kleine-Budde 2394eb79a267SMarc Kleine-Budde err = mcp251xfd_transceiver_enable(priv); 23951f0e21a0SMarc Kleine-Budde if (err) 2396eb79a267SMarc Kleine-Budde goto out_mcp251xfd_ring_free; 23971f0e21a0SMarc Kleine-Budde 2398eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_start(priv); 23991f0e21a0SMarc Kleine-Budde if (err) 24001f0e21a0SMarc Kleine-Budde goto out_transceiver_disable; 24011f0e21a0SMarc Kleine-Budde 24021f0e21a0SMarc Kleine-Budde can_rx_offload_enable(&priv->offload); 24031f0e21a0SMarc Kleine-Budde 2404eb79a267SMarc Kleine-Budde err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq, 24051f0e21a0SMarc Kleine-Budde IRQF_ONESHOT, dev_name(&spi->dev), 24061f0e21a0SMarc Kleine-Budde priv); 24071f0e21a0SMarc Kleine-Budde if (err) 24081f0e21a0SMarc Kleine-Budde goto out_can_rx_offload_disable; 24091f0e21a0SMarc Kleine-Budde 2410eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_interrupts_enable(priv); 24111f0e21a0SMarc Kleine-Budde if (err) 24121f0e21a0SMarc Kleine-Budde goto out_free_irq; 24131f0e21a0SMarc Kleine-Budde 24141f0e21a0SMarc Kleine-Budde netif_start_queue(ndev); 24151f0e21a0SMarc Kleine-Budde 24161f0e21a0SMarc Kleine-Budde return 0; 24171f0e21a0SMarc Kleine-Budde 24181f0e21a0SMarc Kleine-Budde out_free_irq: 24191f0e21a0SMarc Kleine-Budde free_irq(spi->irq, priv); 24201f0e21a0SMarc Kleine-Budde out_can_rx_offload_disable: 24211f0e21a0SMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 24221f0e21a0SMarc Kleine-Budde out_transceiver_disable: 2423eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(priv); 2424eb79a267SMarc Kleine-Budde out_mcp251xfd_ring_free: 2425eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 24261f0e21a0SMarc Kleine-Budde out_close_candev: 24271f0e21a0SMarc Kleine-Budde close_candev(ndev); 24281f0e21a0SMarc Kleine-Budde out_pm_runtime_put: 2429eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 24301f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 24311f0e21a0SMarc Kleine-Budde 24321f0e21a0SMarc Kleine-Budde return err; 24331f0e21a0SMarc Kleine-Budde } 24341f0e21a0SMarc Kleine-Budde 2435eb79a267SMarc Kleine-Budde static int mcp251xfd_stop(struct net_device *ndev) 24361f0e21a0SMarc Kleine-Budde { 2437eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 24381f0e21a0SMarc Kleine-Budde 24391f0e21a0SMarc Kleine-Budde netif_stop_queue(ndev); 2440eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 24411f0e21a0SMarc Kleine-Budde free_irq(ndev->irq, priv); 24421f0e21a0SMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 2443eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 2444eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(priv); 2445eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 24461f0e21a0SMarc Kleine-Budde close_candev(ndev); 24471f0e21a0SMarc Kleine-Budde 24481f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 24491f0e21a0SMarc Kleine-Budde 24501f0e21a0SMarc Kleine-Budde return 0; 24511f0e21a0SMarc Kleine-Budde } 24521f0e21a0SMarc Kleine-Budde 2453eb79a267SMarc Kleine-Budde static const struct net_device_ops mcp251xfd_netdev_ops = { 2454eb79a267SMarc Kleine-Budde .ndo_open = mcp251xfd_open, 2455eb79a267SMarc Kleine-Budde .ndo_stop = mcp251xfd_stop, 2456eb79a267SMarc Kleine-Budde .ndo_start_xmit = mcp251xfd_start_xmit, 24571f0e21a0SMarc Kleine-Budde .ndo_change_mtu = can_change_mtu, 24581f0e21a0SMarc Kleine-Budde }; 24591f0e21a0SMarc Kleine-Budde 24601f0e21a0SMarc Kleine-Budde static void 2461eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(struct mcp251xfd_priv *priv) 24621f0e21a0SMarc Kleine-Budde { 24631f0e21a0SMarc Kleine-Budde const struct spi_device *spi = priv->spi; 24641f0e21a0SMarc Kleine-Budde const struct spi_controller *ctlr = spi->controller; 24651f0e21a0SMarc Kleine-Budde 24661f0e21a0SMarc Kleine-Budde if (ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX) 2467eb79a267SMarc Kleine-Budde priv->devtype_data.quirks |= MCP251XFD_QUIRK_HALF_DUPLEX; 24681f0e21a0SMarc Kleine-Budde } 24691f0e21a0SMarc Kleine-Budde 2470eb79a267SMarc Kleine-Budde static int mcp251xfd_register_chip_detect(struct mcp251xfd_priv *priv) 24711f0e21a0SMarc Kleine-Budde { 24721f0e21a0SMarc Kleine-Budde const struct net_device *ndev = priv->ndev; 2473eb79a267SMarc Kleine-Budde const struct mcp251xfd_devtype_data *devtype_data; 24741f0e21a0SMarc Kleine-Budde u32 osc; 24751f0e21a0SMarc Kleine-Budde int err; 24761f0e21a0SMarc Kleine-Budde 24771f0e21a0SMarc Kleine-Budde /* The OSC_LPMEN is only supported on MCP2518FD, so use it to 24781f0e21a0SMarc Kleine-Budde * autodetect the model. 24791f0e21a0SMarc Kleine-Budde */ 2480eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_OSC, 2481eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_LPMEN, 2482eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_LPMEN); 24831f0e21a0SMarc Kleine-Budde if (err) 24841f0e21a0SMarc Kleine-Budde return err; 24851f0e21a0SMarc Kleine-Budde 2486eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc); 24871f0e21a0SMarc Kleine-Budde if (err) 24881f0e21a0SMarc Kleine-Budde return err; 24891f0e21a0SMarc Kleine-Budde 2490eb79a267SMarc Kleine-Budde if (osc & MCP251XFD_REG_OSC_LPMEN) 2491eb79a267SMarc Kleine-Budde devtype_data = &mcp251xfd_devtype_data_mcp2518fd; 24921f0e21a0SMarc Kleine-Budde else 2493eb79a267SMarc Kleine-Budde devtype_data = &mcp251xfd_devtype_data_mcp2517fd; 24941f0e21a0SMarc Kleine-Budde 2495eb79a267SMarc Kleine-Budde if (!mcp251xfd_is_251X(priv) && 24961f0e21a0SMarc Kleine-Budde priv->devtype_data.model != devtype_data->model) { 24971f0e21a0SMarc Kleine-Budde netdev_info(ndev, 24981f0e21a0SMarc Kleine-Budde "Detected %s, but firmware specifies a %s. Fixing up.", 2499eb79a267SMarc Kleine-Budde __mcp251xfd_get_model_str(devtype_data->model), 2500eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv)); 25011f0e21a0SMarc Kleine-Budde } 25021f0e21a0SMarc Kleine-Budde priv->devtype_data = *devtype_data; 25031f0e21a0SMarc Kleine-Budde 25041f0e21a0SMarc Kleine-Budde /* We need to preserve the Half Duplex Quirk. */ 2505eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(priv); 25061f0e21a0SMarc Kleine-Budde 25071f0e21a0SMarc Kleine-Budde /* Re-init regmap with quirks of detected model. */ 2508eb79a267SMarc Kleine-Budde return mcp251xfd_regmap_init(priv); 25091f0e21a0SMarc Kleine-Budde } 25101f0e21a0SMarc Kleine-Budde 2511eb79a267SMarc Kleine-Budde static int mcp251xfd_register_check_rx_int(struct mcp251xfd_priv *priv) 25121f0e21a0SMarc Kleine-Budde { 25131f0e21a0SMarc Kleine-Budde int err, rx_pending; 25141f0e21a0SMarc Kleine-Budde 25151f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 25161f0e21a0SMarc Kleine-Budde return 0; 25171f0e21a0SMarc Kleine-Budde 2518eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_enable(priv); 25191f0e21a0SMarc Kleine-Budde if (err) 25201f0e21a0SMarc Kleine-Budde return err; 25211f0e21a0SMarc Kleine-Budde 25221f0e21a0SMarc Kleine-Budde /* Check if RX_INT is properly working. The RX_INT should not 25231f0e21a0SMarc Kleine-Budde * be active after a softreset. 25241f0e21a0SMarc Kleine-Budde */ 25251f0e21a0SMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 25261f0e21a0SMarc Kleine-Budde 2527eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_disable(priv); 25281f0e21a0SMarc Kleine-Budde if (err) 25291f0e21a0SMarc Kleine-Budde return err; 25301f0e21a0SMarc Kleine-Budde 25311f0e21a0SMarc Kleine-Budde if (!rx_pending) 25321f0e21a0SMarc Kleine-Budde return 0; 25331f0e21a0SMarc Kleine-Budde 25341f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 25351f0e21a0SMarc Kleine-Budde "RX_INT active after softreset, disabling RX_INT support."); 25361f0e21a0SMarc Kleine-Budde devm_gpiod_put(&priv->spi->dev, priv->rx_int); 25371f0e21a0SMarc Kleine-Budde priv->rx_int = NULL; 25381f0e21a0SMarc Kleine-Budde 25391f0e21a0SMarc Kleine-Budde return 0; 25401f0e21a0SMarc Kleine-Budde } 25411f0e21a0SMarc Kleine-Budde 25421f0e21a0SMarc Kleine-Budde static int 2543eb79a267SMarc Kleine-Budde mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, 25441f0e21a0SMarc Kleine-Budde u32 *dev_id, u32 *effective_speed_hz) 25451f0e21a0SMarc Kleine-Budde { 2546eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_rx; 2547eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_tx; 25481f0e21a0SMarc Kleine-Budde struct spi_transfer xfer[2] = { }; 25491f0e21a0SMarc Kleine-Budde int err; 25501f0e21a0SMarc Kleine-Budde 25511f0e21a0SMarc Kleine-Budde buf_rx = kzalloc(sizeof(*buf_rx), GFP_KERNEL); 25521f0e21a0SMarc Kleine-Budde if (!buf_rx) 25531f0e21a0SMarc Kleine-Budde return -ENOMEM; 25541f0e21a0SMarc Kleine-Budde 25551f0e21a0SMarc Kleine-Budde buf_tx = kzalloc(sizeof(*buf_tx), GFP_KERNEL); 25561f0e21a0SMarc Kleine-Budde if (!buf_tx) { 25571f0e21a0SMarc Kleine-Budde err = -ENOMEM; 25581f0e21a0SMarc Kleine-Budde goto out_kfree_buf_rx; 25591f0e21a0SMarc Kleine-Budde } 25601f0e21a0SMarc Kleine-Budde 25611f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 25621f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd); 25631f0e21a0SMarc Kleine-Budde xfer[1].rx_buf = buf_rx->data; 25641f0e21a0SMarc Kleine-Budde xfer[1].len = sizeof(dev_id); 25651f0e21a0SMarc Kleine-Budde 2566eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, MCP251XFD_REG_DEVID); 25671f0e21a0SMarc Kleine-Budde err = spi_sync_transfer(priv->spi, xfer, ARRAY_SIZE(xfer)); 25681f0e21a0SMarc Kleine-Budde if (err) 25691f0e21a0SMarc Kleine-Budde goto out_kfree_buf_tx; 25701f0e21a0SMarc Kleine-Budde 25711f0e21a0SMarc Kleine-Budde *dev_id = be32_to_cpup((__be32 *)buf_rx->data); 25721f0e21a0SMarc Kleine-Budde *effective_speed_hz = xfer->effective_speed_hz; 25731f0e21a0SMarc Kleine-Budde 25741f0e21a0SMarc Kleine-Budde out_kfree_buf_tx: 25751f0e21a0SMarc Kleine-Budde kfree(buf_tx); 25761f0e21a0SMarc Kleine-Budde out_kfree_buf_rx: 25771f0e21a0SMarc Kleine-Budde kfree(buf_rx); 25781f0e21a0SMarc Kleine-Budde 25791f0e21a0SMarc Kleine-Budde return 0; 25801f0e21a0SMarc Kleine-Budde } 25811f0e21a0SMarc Kleine-Budde 2582eb79a267SMarc Kleine-Budde #define MCP251XFD_QUIRK_ACTIVE(quirk) \ 2583eb79a267SMarc Kleine-Budde (priv->devtype_data.quirks & MCP251XFD_QUIRK_##quirk ? '+' : '-') 25841f0e21a0SMarc Kleine-Budde 25851f0e21a0SMarc Kleine-Budde static int 2586eb79a267SMarc Kleine-Budde mcp251xfd_register_done(const struct mcp251xfd_priv *priv) 25871f0e21a0SMarc Kleine-Budde { 25881f0e21a0SMarc Kleine-Budde u32 dev_id, effective_speed_hz; 25891f0e21a0SMarc Kleine-Budde int err; 25901f0e21a0SMarc Kleine-Budde 2591eb79a267SMarc Kleine-Budde err = mcp251xfd_register_get_dev_id(priv, &dev_id, 25921f0e21a0SMarc Kleine-Budde &effective_speed_hz); 25931f0e21a0SMarc Kleine-Budde if (err) 25941f0e21a0SMarc Kleine-Budde return err; 25951f0e21a0SMarc Kleine-Budde 25961f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 25971f0e21a0SMarc 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", 2598eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv), 2599eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_DEVID_ID_MASK, dev_id), 2600eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_DEVID_REV_MASK, dev_id), 26011f0e21a0SMarc Kleine-Budde priv->rx_int ? '+' : '-', 2602eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(MAB_NO_WARN), 2603eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_REG), 2604eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_RX), 2605eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_TX), 2606eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(ECC), 2607eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(HALF_DUPLEX), 26081f0e21a0SMarc Kleine-Budde priv->can.clock.freq / 1000000, 26091f0e21a0SMarc Kleine-Budde priv->can.clock.freq % 1000000 / 1000 / 10, 26101f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig / 1000000, 26111f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig % 1000000 / 1000 / 10, 26121f0e21a0SMarc Kleine-Budde priv->spi->max_speed_hz / 1000000, 26131f0e21a0SMarc Kleine-Budde priv->spi->max_speed_hz % 1000000 / 1000 / 10, 26141f0e21a0SMarc Kleine-Budde effective_speed_hz / 1000000, 26151f0e21a0SMarc Kleine-Budde effective_speed_hz % 1000000 / 1000 / 10); 26161f0e21a0SMarc Kleine-Budde 26171f0e21a0SMarc Kleine-Budde return 0; 26181f0e21a0SMarc Kleine-Budde } 26191f0e21a0SMarc Kleine-Budde 2620eb79a267SMarc Kleine-Budde static int mcp251xfd_register(struct mcp251xfd_priv *priv) 26211f0e21a0SMarc Kleine-Budde { 26221f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 26231f0e21a0SMarc Kleine-Budde int err; 26241f0e21a0SMarc Kleine-Budde 2625eb79a267SMarc Kleine-Budde err = mcp251xfd_clks_and_vdd_enable(priv); 26261f0e21a0SMarc Kleine-Budde if (err) 26271f0e21a0SMarc Kleine-Budde return err; 26281f0e21a0SMarc Kleine-Budde 26291f0e21a0SMarc Kleine-Budde pm_runtime_get_noresume(ndev->dev.parent); 26301f0e21a0SMarc Kleine-Budde err = pm_runtime_set_active(ndev->dev.parent); 26311f0e21a0SMarc Kleine-Budde if (err) 26321f0e21a0SMarc Kleine-Budde goto out_runtime_put_noidle; 26331f0e21a0SMarc Kleine-Budde pm_runtime_enable(ndev->dev.parent); 26341f0e21a0SMarc Kleine-Budde 2635eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(priv); 26361f0e21a0SMarc Kleine-Budde 2637eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset(priv); 26381f0e21a0SMarc Kleine-Budde if (err == -ENODEV) 26391f0e21a0SMarc Kleine-Budde goto out_runtime_disable; 26401f0e21a0SMarc Kleine-Budde if (err) 26411f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 26421f0e21a0SMarc Kleine-Budde 2643eb79a267SMarc Kleine-Budde err = mcp251xfd_register_chip_detect(priv); 26441f0e21a0SMarc Kleine-Budde if (err) 26451f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 26461f0e21a0SMarc Kleine-Budde 2647eb79a267SMarc Kleine-Budde err = mcp251xfd_register_check_rx_int(priv); 26481f0e21a0SMarc Kleine-Budde if (err) 26491f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 26501f0e21a0SMarc Kleine-Budde 26511f0e21a0SMarc Kleine-Budde err = register_candev(ndev); 26521f0e21a0SMarc Kleine-Budde if (err) 26531f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 26541f0e21a0SMarc Kleine-Budde 2655eb79a267SMarc Kleine-Budde err = mcp251xfd_register_done(priv); 26561f0e21a0SMarc Kleine-Budde if (err) 26571f0e21a0SMarc Kleine-Budde goto out_unregister_candev; 26581f0e21a0SMarc Kleine-Budde 26591f0e21a0SMarc Kleine-Budde /* Put controller into sleep mode and let pm_runtime_put() 26601f0e21a0SMarc Kleine-Budde * disable the clocks and vdd. If CONFIG_PM is not enabled, 26611f0e21a0SMarc Kleine-Budde * the clocks and vdd will stay powered. 26621f0e21a0SMarc Kleine-Budde */ 2663eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 26641f0e21a0SMarc Kleine-Budde if (err) 26651f0e21a0SMarc Kleine-Budde goto out_unregister_candev; 26661f0e21a0SMarc Kleine-Budde 26671f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 26681f0e21a0SMarc Kleine-Budde 26691f0e21a0SMarc Kleine-Budde return 0; 26701f0e21a0SMarc Kleine-Budde 26711f0e21a0SMarc Kleine-Budde out_unregister_candev: 26721f0e21a0SMarc Kleine-Budde unregister_candev(ndev); 26731f0e21a0SMarc Kleine-Budde out_chip_set_mode_sleep: 2674eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 26751f0e21a0SMarc Kleine-Budde out_runtime_disable: 26761f0e21a0SMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 26771f0e21a0SMarc Kleine-Budde out_runtime_put_noidle: 26781f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 2679eb79a267SMarc Kleine-Budde mcp251xfd_clks_and_vdd_disable(priv); 26801f0e21a0SMarc Kleine-Budde 26811f0e21a0SMarc Kleine-Budde return err; 26821f0e21a0SMarc Kleine-Budde } 26831f0e21a0SMarc Kleine-Budde 2684eb79a267SMarc Kleine-Budde static inline void mcp251xfd_unregister(struct mcp251xfd_priv *priv) 26851f0e21a0SMarc Kleine-Budde { 26861f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 26871f0e21a0SMarc Kleine-Budde 26881f0e21a0SMarc Kleine-Budde unregister_candev(ndev); 26891f0e21a0SMarc Kleine-Budde 26901f0e21a0SMarc Kleine-Budde pm_runtime_get_sync(ndev->dev.parent); 26911f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 2692eb79a267SMarc Kleine-Budde mcp251xfd_clks_and_vdd_disable(priv); 26931f0e21a0SMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 26941f0e21a0SMarc Kleine-Budde } 26951f0e21a0SMarc Kleine-Budde 2696eb79a267SMarc Kleine-Budde static const struct of_device_id mcp251xfd_of_match[] = { 26971f0e21a0SMarc Kleine-Budde { 26981f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp2517fd", 2699eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp2517fd, 27001f0e21a0SMarc Kleine-Budde }, { 27011f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp2518fd", 2702eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp2518fd, 27031f0e21a0SMarc Kleine-Budde }, { 27041f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp251xfd", 2705eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp251xfd, 27061f0e21a0SMarc Kleine-Budde }, { 27071f0e21a0SMarc Kleine-Budde /* sentinel */ 27081f0e21a0SMarc Kleine-Budde }, 27091f0e21a0SMarc Kleine-Budde }; 2710eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(of, mcp251xfd_of_match); 27111f0e21a0SMarc Kleine-Budde 2712eb79a267SMarc Kleine-Budde static const struct spi_device_id mcp251xfd_id_table[] = { 27131f0e21a0SMarc Kleine-Budde { 27141f0e21a0SMarc Kleine-Budde .name = "mcp2517fd", 2715eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2517fd, 27161f0e21a0SMarc Kleine-Budde }, { 27171f0e21a0SMarc Kleine-Budde .name = "mcp2518fd", 2718eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2518fd, 27191f0e21a0SMarc Kleine-Budde }, { 27201f0e21a0SMarc Kleine-Budde .name = "mcp251xfd", 2721eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp251xfd, 27221f0e21a0SMarc Kleine-Budde }, { 27231f0e21a0SMarc Kleine-Budde /* sentinel */ 27241f0e21a0SMarc Kleine-Budde }, 27251f0e21a0SMarc Kleine-Budde }; 2726eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(spi, mcp251xfd_id_table); 27271f0e21a0SMarc Kleine-Budde 2728eb79a267SMarc Kleine-Budde static int mcp251xfd_probe(struct spi_device *spi) 27291f0e21a0SMarc Kleine-Budde { 27301f0e21a0SMarc Kleine-Budde const void *match; 27311f0e21a0SMarc Kleine-Budde struct net_device *ndev; 2732eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv; 27331f0e21a0SMarc Kleine-Budde struct gpio_desc *rx_int; 27341f0e21a0SMarc Kleine-Budde struct regulator *reg_vdd, *reg_xceiver; 27351f0e21a0SMarc Kleine-Budde struct clk *clk; 27361f0e21a0SMarc Kleine-Budde u32 freq; 27371f0e21a0SMarc Kleine-Budde int err; 27381f0e21a0SMarc Kleine-Budde 27391a1c436bSMarc Kleine-Budde if (!spi->irq) 27401a1c436bSMarc Kleine-Budde return dev_err_probe(&spi->dev, -ENXIO, 27411a1c436bSMarc Kleine-Budde "No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n"); 27421a1c436bSMarc Kleine-Budde 27431f0e21a0SMarc Kleine-Budde rx_int = devm_gpiod_get_optional(&spi->dev, "microchip,rx-int", 27441f0e21a0SMarc Kleine-Budde GPIOD_IN); 27451f0e21a0SMarc Kleine-Budde if (PTR_ERR(rx_int) == -EPROBE_DEFER) 27461f0e21a0SMarc Kleine-Budde return -EPROBE_DEFER; 27471f0e21a0SMarc Kleine-Budde else if (IS_ERR(rx_int)) 27481f0e21a0SMarc Kleine-Budde return PTR_ERR(rx_int); 27491f0e21a0SMarc Kleine-Budde 27501f0e21a0SMarc Kleine-Budde reg_vdd = devm_regulator_get_optional(&spi->dev, "vdd"); 27511f0e21a0SMarc Kleine-Budde if (PTR_ERR(reg_vdd) == -EPROBE_DEFER) 27521f0e21a0SMarc Kleine-Budde return -EPROBE_DEFER; 27531f0e21a0SMarc Kleine-Budde else if (PTR_ERR(reg_vdd) == -ENODEV) 27541f0e21a0SMarc Kleine-Budde reg_vdd = NULL; 27551f0e21a0SMarc Kleine-Budde else if (IS_ERR(reg_vdd)) 27561f0e21a0SMarc Kleine-Budde return PTR_ERR(reg_vdd); 27571f0e21a0SMarc Kleine-Budde 27581f0e21a0SMarc Kleine-Budde reg_xceiver = devm_regulator_get_optional(&spi->dev, "xceiver"); 27591f0e21a0SMarc Kleine-Budde if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER) 27601f0e21a0SMarc Kleine-Budde return -EPROBE_DEFER; 27611f0e21a0SMarc Kleine-Budde else if (PTR_ERR(reg_xceiver) == -ENODEV) 27621f0e21a0SMarc Kleine-Budde reg_xceiver = NULL; 27631f0e21a0SMarc Kleine-Budde else if (IS_ERR(reg_xceiver)) 27641f0e21a0SMarc Kleine-Budde return PTR_ERR(reg_xceiver); 27651f0e21a0SMarc Kleine-Budde 27661f0e21a0SMarc Kleine-Budde clk = devm_clk_get(&spi->dev, NULL); 27671f0e21a0SMarc Kleine-Budde if (IS_ERR(clk)) { 27681f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, "No Oscillator (clock) defined.\n"); 27691f0e21a0SMarc Kleine-Budde return PTR_ERR(clk); 27701f0e21a0SMarc Kleine-Budde } 27711f0e21a0SMarc Kleine-Budde freq = clk_get_rate(clk); 27721f0e21a0SMarc Kleine-Budde 27731f0e21a0SMarc Kleine-Budde /* Sanity check */ 2774eb79a267SMarc Kleine-Budde if (freq < MCP251XFD_SYSCLOCK_HZ_MIN || 2775eb79a267SMarc Kleine-Budde freq > MCP251XFD_SYSCLOCK_HZ_MAX) { 27761f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, 27771f0e21a0SMarc Kleine-Budde "Oscillator frequency (%u Hz) is too low or high.\n", 27781f0e21a0SMarc Kleine-Budde freq); 27791f0e21a0SMarc Kleine-Budde return -ERANGE; 27801f0e21a0SMarc Kleine-Budde } 27811f0e21a0SMarc Kleine-Budde 2782eb79a267SMarc Kleine-Budde if (freq <= MCP251XFD_SYSCLOCK_HZ_MAX / MCP251XFD_OSC_PLL_MULTIPLIER) { 27831f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, 27841f0e21a0SMarc Kleine-Budde "Oscillator frequency (%u Hz) is too low and PLL is not supported.\n", 27851f0e21a0SMarc Kleine-Budde freq); 27861f0e21a0SMarc Kleine-Budde return -ERANGE; 27871f0e21a0SMarc Kleine-Budde } 27881f0e21a0SMarc Kleine-Budde 2789eb79a267SMarc Kleine-Budde ndev = alloc_candev(sizeof(struct mcp251xfd_priv), 2790eb79a267SMarc Kleine-Budde MCP251XFD_TX_OBJ_NUM_MAX); 27911f0e21a0SMarc Kleine-Budde if (!ndev) 27921f0e21a0SMarc Kleine-Budde return -ENOMEM; 27931f0e21a0SMarc Kleine-Budde 27941f0e21a0SMarc Kleine-Budde SET_NETDEV_DEV(ndev, &spi->dev); 27951f0e21a0SMarc Kleine-Budde 2796eb79a267SMarc Kleine-Budde ndev->netdev_ops = &mcp251xfd_netdev_ops; 27971f0e21a0SMarc Kleine-Budde ndev->irq = spi->irq; 27981f0e21a0SMarc Kleine-Budde ndev->flags |= IFF_ECHO; 27991f0e21a0SMarc Kleine-Budde 28001f0e21a0SMarc Kleine-Budde priv = netdev_priv(ndev); 28011f0e21a0SMarc Kleine-Budde spi_set_drvdata(spi, priv); 28021f0e21a0SMarc Kleine-Budde priv->can.clock.freq = freq; 2803eb79a267SMarc Kleine-Budde priv->can.do_set_mode = mcp251xfd_set_mode; 2804eb79a267SMarc Kleine-Budde priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter; 2805eb79a267SMarc Kleine-Budde priv->can.bittiming_const = &mcp251xfd_bittiming_const; 2806eb79a267SMarc Kleine-Budde priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const; 28071f0e21a0SMarc Kleine-Budde priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | 28081f0e21a0SMarc Kleine-Budde CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_FD | 28091f0e21a0SMarc Kleine-Budde CAN_CTRLMODE_FD_NON_ISO; 28101f0e21a0SMarc Kleine-Budde priv->ndev = ndev; 28111f0e21a0SMarc Kleine-Budde priv->spi = spi; 28121f0e21a0SMarc Kleine-Budde priv->rx_int = rx_int; 28131f0e21a0SMarc Kleine-Budde priv->clk = clk; 28141f0e21a0SMarc Kleine-Budde priv->reg_vdd = reg_vdd; 28151f0e21a0SMarc Kleine-Budde priv->reg_xceiver = reg_xceiver; 28161f0e21a0SMarc Kleine-Budde 28171f0e21a0SMarc Kleine-Budde match = device_get_match_data(&spi->dev); 28181f0e21a0SMarc Kleine-Budde if (match) 2819eb79a267SMarc Kleine-Budde priv->devtype_data = *(struct mcp251xfd_devtype_data *)match; 28201f0e21a0SMarc Kleine-Budde else 2821eb79a267SMarc Kleine-Budde priv->devtype_data = *(struct mcp251xfd_devtype_data *) 28221f0e21a0SMarc Kleine-Budde spi_get_device_id(spi)->driver_data; 28231f0e21a0SMarc Kleine-Budde 28241f0e21a0SMarc Kleine-Budde /* Errata Reference: 28251f0e21a0SMarc Kleine-Budde * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 4. 28261f0e21a0SMarc Kleine-Budde * 28271f0e21a0SMarc Kleine-Budde * The SPI can write corrupted data to the RAM at fast SPI 28281f0e21a0SMarc Kleine-Budde * speeds: 28291f0e21a0SMarc Kleine-Budde * 28301f0e21a0SMarc Kleine-Budde * Simultaneous activity on the CAN bus while writing data to 28311f0e21a0SMarc Kleine-Budde * RAM via the SPI interface, with high SCK frequency, can 28321f0e21a0SMarc Kleine-Budde * lead to corrupted data being written to RAM. 28331f0e21a0SMarc Kleine-Budde * 28341f0e21a0SMarc Kleine-Budde * Fix/Work Around: 28351f0e21a0SMarc Kleine-Budde * Ensure that FSCK is less than or equal to 0.85 * 28361f0e21a0SMarc Kleine-Budde * (FSYSCLK/2). 28371f0e21a0SMarc Kleine-Budde * 28381f0e21a0SMarc Kleine-Budde * Known good and bad combinations are: 28391f0e21a0SMarc Kleine-Budde * 28401f0e21a0SMarc Kleine-Budde * MCP ext-clk SoC SPI SPI-clk max-clk parent-clk Status config 28411f0e21a0SMarc Kleine-Budde * 28421f0e21a0SMarc Kleine-Budde * 2518 20 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 8333333 Hz 83.33% 600000000 Hz good assigned-clocks = <&ccu CLK_SPIx> 28431f0e21a0SMarc Kleine-Budde * 2518 20 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 9375000 Hz 93.75% 600000000 Hz bad assigned-clocks = <&ccu CLK_SPIx> 28441f0e21a0SMarc Kleine-Budde * 2518 40 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 16666667 Hz 83.33% 600000000 Hz good assigned-clocks = <&ccu CLK_SPIx> 28451f0e21a0SMarc Kleine-Budde * 2518 40 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 18750000 Hz 93.75% 600000000 Hz bad assigned-clocks = <&ccu CLK_SPIx> 28461f0e21a0SMarc Kleine-Budde * 2517 20 MHz fsl,imx8mm fsl,imx51-ecspi 8333333 Hz 83.33% 16666667 Hz good assigned-clocks = <&clk IMX8MM_CLK_ECSPIx_ROOT> 28471f0e21a0SMarc Kleine-Budde * 2517 20 MHz fsl,imx8mm fsl,imx51-ecspi 9523809 Hz 95.34% 28571429 Hz bad assigned-clocks = <&clk IMX8MM_CLK_ECSPIx_ROOT> 28481f0e21a0SMarc Kleine-Budde * 2517 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz good default 28491f0e21a0SMarc Kleine-Budde * 2518 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz good default 28501f0e21a0SMarc Kleine-Budde * 28511f0e21a0SMarc Kleine-Budde */ 28521f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig = spi->max_speed_hz; 28531f0e21a0SMarc Kleine-Budde spi->max_speed_hz = min(spi->max_speed_hz, freq / 2 / 1000 * 850); 28541f0e21a0SMarc Kleine-Budde spi->bits_per_word = 8; 28551f0e21a0SMarc Kleine-Budde spi->rt = true; 28561f0e21a0SMarc Kleine-Budde err = spi_setup(spi); 28571f0e21a0SMarc Kleine-Budde if (err) 28581f0e21a0SMarc Kleine-Budde goto out_free_candev; 28591f0e21a0SMarc Kleine-Budde 2860eb79a267SMarc Kleine-Budde err = mcp251xfd_regmap_init(priv); 28611f0e21a0SMarc Kleine-Budde if (err) 28621f0e21a0SMarc Kleine-Budde goto out_free_candev; 28631f0e21a0SMarc Kleine-Budde 28641f0e21a0SMarc Kleine-Budde err = can_rx_offload_add_manual(ndev, &priv->offload, 2865eb79a267SMarc Kleine-Budde MCP251XFD_NAPI_WEIGHT); 28661f0e21a0SMarc Kleine-Budde if (err) 28671f0e21a0SMarc Kleine-Budde goto out_free_candev; 28681f0e21a0SMarc Kleine-Budde 2869eb79a267SMarc Kleine-Budde err = mcp251xfd_register(priv); 28701f0e21a0SMarc Kleine-Budde if (err) 28711f0e21a0SMarc Kleine-Budde goto out_free_candev; 28721f0e21a0SMarc Kleine-Budde 28731f0e21a0SMarc Kleine-Budde return 0; 28741f0e21a0SMarc Kleine-Budde 28751f0e21a0SMarc Kleine-Budde out_free_candev: 28761f0e21a0SMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 28771f0e21a0SMarc Kleine-Budde 28781f0e21a0SMarc Kleine-Budde free_candev(ndev); 28791f0e21a0SMarc Kleine-Budde 28801f0e21a0SMarc Kleine-Budde return err; 28811f0e21a0SMarc Kleine-Budde } 28821f0e21a0SMarc Kleine-Budde 2883eb79a267SMarc Kleine-Budde static int mcp251xfd_remove(struct spi_device *spi) 28841f0e21a0SMarc Kleine-Budde { 2885eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = spi_get_drvdata(spi); 28861f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 28871f0e21a0SMarc Kleine-Budde 28881f0e21a0SMarc Kleine-Budde can_rx_offload_del(&priv->offload); 2889eb79a267SMarc Kleine-Budde mcp251xfd_unregister(priv); 28901f0e21a0SMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 28911f0e21a0SMarc Kleine-Budde free_candev(ndev); 28921f0e21a0SMarc Kleine-Budde 28931f0e21a0SMarc Kleine-Budde return 0; 28941f0e21a0SMarc Kleine-Budde } 28951f0e21a0SMarc Kleine-Budde 2896eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_suspend(struct device *device) 28971f0e21a0SMarc Kleine-Budde { 2898eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = dev_get_drvdata(device); 28991f0e21a0SMarc Kleine-Budde 2900eb79a267SMarc Kleine-Budde return mcp251xfd_clks_and_vdd_disable(priv); 29011f0e21a0SMarc Kleine-Budde } 29021f0e21a0SMarc Kleine-Budde 2903eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_resume(struct device *device) 29041f0e21a0SMarc Kleine-Budde { 2905eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = dev_get_drvdata(device); 29061f0e21a0SMarc Kleine-Budde 2907eb79a267SMarc Kleine-Budde return mcp251xfd_clks_and_vdd_enable(priv); 29081f0e21a0SMarc Kleine-Budde } 29091f0e21a0SMarc Kleine-Budde 2910eb79a267SMarc Kleine-Budde static const struct dev_pm_ops mcp251xfd_pm_ops = { 2911eb79a267SMarc Kleine-Budde SET_RUNTIME_PM_OPS(mcp251xfd_runtime_suspend, 2912eb79a267SMarc Kleine-Budde mcp251xfd_runtime_resume, NULL) 29131f0e21a0SMarc Kleine-Budde }; 29141f0e21a0SMarc Kleine-Budde 2915eb79a267SMarc Kleine-Budde static struct spi_driver mcp251xfd_driver = { 29161f0e21a0SMarc Kleine-Budde .driver = { 29171f0e21a0SMarc Kleine-Budde .name = DEVICE_NAME, 2918eb79a267SMarc Kleine-Budde .pm = &mcp251xfd_pm_ops, 2919eb79a267SMarc Kleine-Budde .of_match_table = mcp251xfd_of_match, 29201f0e21a0SMarc Kleine-Budde }, 2921eb79a267SMarc Kleine-Budde .probe = mcp251xfd_probe, 2922eb79a267SMarc Kleine-Budde .remove = mcp251xfd_remove, 2923eb79a267SMarc Kleine-Budde .id_table = mcp251xfd_id_table, 29241f0e21a0SMarc Kleine-Budde }; 2925eb79a267SMarc Kleine-Budde module_spi_driver(mcp251xfd_driver); 29261f0e21a0SMarc Kleine-Budde 29271f0e21a0SMarc Kleine-Budde MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>"); 2928f4f77366SMarc Kleine-Budde MODULE_DESCRIPTION("Microchip MCP251xFD Family CAN controller driver"); 29291f0e21a0SMarc Kleine-Budde MODULE_LICENSE("GPL v2"); 2930