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 { 329dada6a6cSMarc Kleine-Budde struct mcp251xfd_tef_ring *tef_ring; 330eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring; 331eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *rx_ring, *prev_rx_ring = NULL; 332eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 3331f0e21a0SMarc Kleine-Budde u32 val; 3341f0e21a0SMarc Kleine-Budde u16 addr; 3351f0e21a0SMarc Kleine-Budde u8 len; 3361f652bb6SUrsula Maplehurst int i, j; 3371f0e21a0SMarc Kleine-Budde 3381f0e21a0SMarc Kleine-Budde /* TEF */ 339dada6a6cSMarc Kleine-Budde tef_ring = priv->tef; 340dada6a6cSMarc Kleine-Budde tef_ring->head = 0; 341dada6a6cSMarc Kleine-Budde tef_ring->tail = 0; 3421f0e21a0SMarc Kleine-Budde 34368c0c1c7SMarc Kleine-Budde /* FIFO increment TEF tail pointer */ 34468c0c1c7SMarc Kleine-Budde addr = MCP251XFD_REG_TEFCON; 34568c0c1c7SMarc Kleine-Budde val = MCP251XFD_REG_TEFCON_UINC; 34668c0c1c7SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf, 34768c0c1c7SMarc Kleine-Budde addr, val, val); 34868c0c1c7SMarc Kleine-Budde 34968c0c1c7SMarc Kleine-Budde for (j = 0; j < ARRAY_SIZE(tef_ring->uinc_xfer); j++) { 35068c0c1c7SMarc Kleine-Budde struct spi_transfer *xfer; 35168c0c1c7SMarc Kleine-Budde 35268c0c1c7SMarc Kleine-Budde xfer = &tef_ring->uinc_xfer[j]; 35368c0c1c7SMarc Kleine-Budde xfer->tx_buf = &tef_ring->uinc_buf; 35468c0c1c7SMarc Kleine-Budde xfer->len = len; 35568c0c1c7SMarc Kleine-Budde xfer->cs_change = 1; 35668c0c1c7SMarc Kleine-Budde xfer->cs_change_delay.value = 0; 35768c0c1c7SMarc Kleine-Budde xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 35868c0c1c7SMarc Kleine-Budde } 35968c0c1c7SMarc Kleine-Budde 3601f0e21a0SMarc Kleine-Budde /* TX */ 3611f0e21a0SMarc Kleine-Budde tx_ring = priv->tx; 3621f0e21a0SMarc Kleine-Budde tx_ring->head = 0; 3631f0e21a0SMarc Kleine-Budde tx_ring->tail = 0; 364eb79a267SMarc Kleine-Budde tx_ring->base = mcp251xfd_get_tef_obj_addr(tx_ring->obj_num); 3651f0e21a0SMarc Kleine-Budde 3661f0e21a0SMarc Kleine-Budde /* FIFO request to send */ 367eb79a267SMarc Kleine-Budde addr = MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO); 368eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC; 369eb79a267SMarc Kleine-Budde len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf, 3701f0e21a0SMarc Kleine-Budde addr, val, val); 3711f0e21a0SMarc Kleine-Budde 372eb79a267SMarc Kleine-Budde mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i) 373eb79a267SMarc Kleine-Budde mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i); 3741f0e21a0SMarc Kleine-Budde 3751f0e21a0SMarc Kleine-Budde /* RX */ 376eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { 3771f0e21a0SMarc Kleine-Budde rx_ring->head = 0; 3781f0e21a0SMarc Kleine-Budde rx_ring->tail = 0; 3791f0e21a0SMarc Kleine-Budde rx_ring->nr = i; 380eb79a267SMarc Kleine-Budde rx_ring->fifo_nr = MCP251XFD_RX_FIFO(i); 3811f0e21a0SMarc Kleine-Budde 3821f0e21a0SMarc Kleine-Budde if (!prev_rx_ring) 3831f0e21a0SMarc Kleine-Budde rx_ring->base = 384eb79a267SMarc Kleine-Budde mcp251xfd_get_tx_obj_addr(tx_ring, 3851f0e21a0SMarc Kleine-Budde tx_ring->obj_num); 3861f0e21a0SMarc Kleine-Budde else 3871f0e21a0SMarc Kleine-Budde rx_ring->base = prev_rx_ring->base + 3881f0e21a0SMarc Kleine-Budde prev_rx_ring->obj_size * 3891f0e21a0SMarc Kleine-Budde prev_rx_ring->obj_num; 3901f0e21a0SMarc Kleine-Budde 3911f0e21a0SMarc Kleine-Budde prev_rx_ring = rx_ring; 3921f652bb6SUrsula Maplehurst 3931f652bb6SUrsula Maplehurst /* FIFO increment RX tail pointer */ 3941f652bb6SUrsula Maplehurst addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr); 3951f652bb6SUrsula Maplehurst val = MCP251XFD_REG_FIFOCON_UINC; 3961f652bb6SUrsula Maplehurst len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf, 3971f652bb6SUrsula Maplehurst addr, val, val); 3981f652bb6SUrsula Maplehurst 3991f652bb6SUrsula Maplehurst for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) { 4001f652bb6SUrsula Maplehurst struct spi_transfer *xfer; 4011f652bb6SUrsula Maplehurst 4021f652bb6SUrsula Maplehurst xfer = &rx_ring->uinc_xfer[j]; 4031f652bb6SUrsula Maplehurst xfer->tx_buf = &rx_ring->uinc_buf; 4041f652bb6SUrsula Maplehurst xfer->len = len; 4051f652bb6SUrsula Maplehurst xfer->cs_change = 1; 4061f652bb6SUrsula Maplehurst xfer->cs_change_delay.value = 0; 4071f652bb6SUrsula Maplehurst xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS; 4081f652bb6SUrsula Maplehurst } 4091f0e21a0SMarc Kleine-Budde } 4101f0e21a0SMarc Kleine-Budde } 4111f0e21a0SMarc Kleine-Budde 412eb79a267SMarc Kleine-Budde static void mcp251xfd_ring_free(struct mcp251xfd_priv *priv) 4131f0e21a0SMarc Kleine-Budde { 4141f0e21a0SMarc Kleine-Budde int i; 4151f0e21a0SMarc Kleine-Budde 4161f0e21a0SMarc Kleine-Budde for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) { 4171f0e21a0SMarc Kleine-Budde kfree(priv->rx[i]); 4181f0e21a0SMarc Kleine-Budde priv->rx[i] = NULL; 4191f0e21a0SMarc Kleine-Budde } 4201f0e21a0SMarc Kleine-Budde } 4211f0e21a0SMarc Kleine-Budde 422eb79a267SMarc Kleine-Budde static int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv) 4231f0e21a0SMarc Kleine-Budde { 424eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring; 425eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *rx_ring; 4261f0e21a0SMarc Kleine-Budde int tef_obj_size, tx_obj_size, rx_obj_size; 4271f0e21a0SMarc Kleine-Budde int tx_obj_num; 4281f0e21a0SMarc Kleine-Budde int ram_free, i; 4291f0e21a0SMarc Kleine-Budde 430eb79a267SMarc Kleine-Budde tef_obj_size = sizeof(struct mcp251xfd_hw_tef_obj); 4311f0e21a0SMarc Kleine-Budde /* listen-only mode works like FD mode */ 4321f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) { 433eb79a267SMarc Kleine-Budde tx_obj_num = MCP251XFD_TX_OBJ_NUM_CANFD; 434eb79a267SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd); 435eb79a267SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd); 4361f0e21a0SMarc Kleine-Budde } else { 437eb79a267SMarc Kleine-Budde tx_obj_num = MCP251XFD_TX_OBJ_NUM_CAN; 438eb79a267SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can); 439eb79a267SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can); 4401f0e21a0SMarc Kleine-Budde } 4411f0e21a0SMarc Kleine-Budde 4421f0e21a0SMarc Kleine-Budde tx_ring = priv->tx; 4431f0e21a0SMarc Kleine-Budde tx_ring->obj_num = tx_obj_num; 4441f0e21a0SMarc Kleine-Budde tx_ring->obj_size = tx_obj_size; 4451f0e21a0SMarc Kleine-Budde 446eb79a267SMarc Kleine-Budde ram_free = MCP251XFD_RAM_SIZE - tx_obj_num * 4471f0e21a0SMarc Kleine-Budde (tef_obj_size + tx_obj_size); 4481f0e21a0SMarc Kleine-Budde 4491f0e21a0SMarc Kleine-Budde for (i = 0; 4501f0e21a0SMarc Kleine-Budde i < ARRAY_SIZE(priv->rx) && ram_free >= rx_obj_size; 4511f0e21a0SMarc Kleine-Budde i++) { 4521f0e21a0SMarc Kleine-Budde int rx_obj_num; 4531f0e21a0SMarc Kleine-Budde 4541f0e21a0SMarc Kleine-Budde rx_obj_num = ram_free / rx_obj_size; 4554843ad9bSMarc Kleine-Budde rx_obj_num = min(1 << (fls(rx_obj_num) - 1), 4564843ad9bSMarc Kleine-Budde MCP251XFD_RX_OBJ_NUM_MAX); 4571f0e21a0SMarc Kleine-Budde 4581f0e21a0SMarc Kleine-Budde rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num, 4591f0e21a0SMarc Kleine-Budde GFP_KERNEL); 4601f0e21a0SMarc Kleine-Budde if (!rx_ring) { 461eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 4621f0e21a0SMarc Kleine-Budde return -ENOMEM; 4631f0e21a0SMarc Kleine-Budde } 4641f0e21a0SMarc Kleine-Budde rx_ring->obj_num = rx_obj_num; 4651f0e21a0SMarc Kleine-Budde rx_ring->obj_size = rx_obj_size; 4661f0e21a0SMarc Kleine-Budde priv->rx[i] = rx_ring; 4671f0e21a0SMarc Kleine-Budde 4681f0e21a0SMarc Kleine-Budde ram_free -= rx_ring->obj_num * rx_ring->obj_size; 4691f0e21a0SMarc Kleine-Budde } 4701f0e21a0SMarc Kleine-Budde priv->rx_ring_num = i; 4711f0e21a0SMarc Kleine-Budde 4721f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4731f0e21a0SMarc Kleine-Budde "FIFO setup: TEF: %d*%d bytes = %d bytes, TX: %d*%d bytes = %d bytes\n", 4741f0e21a0SMarc Kleine-Budde tx_obj_num, tef_obj_size, tef_obj_size * tx_obj_num, 4751f0e21a0SMarc Kleine-Budde tx_obj_num, tx_obj_size, tx_obj_size * tx_obj_num); 4761f0e21a0SMarc Kleine-Budde 477eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, i) { 4781f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4791f0e21a0SMarc Kleine-Budde "FIFO setup: RX-%d: %d*%d bytes = %d bytes\n", 4801f0e21a0SMarc Kleine-Budde i, rx_ring->obj_num, rx_ring->obj_size, 4811f0e21a0SMarc Kleine-Budde rx_ring->obj_size * rx_ring->obj_num); 4821f0e21a0SMarc Kleine-Budde } 4831f0e21a0SMarc Kleine-Budde 4841f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4851f0e21a0SMarc Kleine-Budde "FIFO setup: free: %d bytes\n", 4861f0e21a0SMarc Kleine-Budde ram_free); 4871f0e21a0SMarc Kleine-Budde 4881f0e21a0SMarc Kleine-Budde return 0; 4891f0e21a0SMarc Kleine-Budde } 4901f0e21a0SMarc Kleine-Budde 4911f0e21a0SMarc Kleine-Budde static inline int 492eb79a267SMarc Kleine-Budde mcp251xfd_chip_get_mode(const struct mcp251xfd_priv *priv, u8 *mode) 4931f0e21a0SMarc Kleine-Budde { 4941f0e21a0SMarc Kleine-Budde u32 val; 4951f0e21a0SMarc Kleine-Budde int err; 4961f0e21a0SMarc Kleine-Budde 497eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_CON, &val); 4981f0e21a0SMarc Kleine-Budde if (err) 4991f0e21a0SMarc Kleine-Budde return err; 5001f0e21a0SMarc Kleine-Budde 501eb79a267SMarc Kleine-Budde *mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, val); 5021f0e21a0SMarc Kleine-Budde 5031f0e21a0SMarc Kleine-Budde return 0; 5041f0e21a0SMarc Kleine-Budde } 5051f0e21a0SMarc Kleine-Budde 5061f0e21a0SMarc Kleine-Budde static int 507eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv, 5081f0e21a0SMarc Kleine-Budde const u8 mode_req, bool nowait) 5091f0e21a0SMarc Kleine-Budde { 5101f0e21a0SMarc Kleine-Budde u32 con, con_reqop; 5111f0e21a0SMarc Kleine-Budde int err; 5121f0e21a0SMarc Kleine-Budde 513eb79a267SMarc Kleine-Budde con_reqop = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, mode_req); 514eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CON, 515eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_REQOP_MASK, con_reqop); 5161f0e21a0SMarc Kleine-Budde if (err) 5171f0e21a0SMarc Kleine-Budde return err; 5181f0e21a0SMarc Kleine-Budde 519eb79a267SMarc Kleine-Budde if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait) 5201f0e21a0SMarc Kleine-Budde return 0; 5211f0e21a0SMarc Kleine-Budde 522eb79a267SMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con, 523eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, 5241f0e21a0SMarc Kleine-Budde con) == mode_req, 525eb79a267SMarc Kleine-Budde MCP251XFD_POLL_SLEEP_US, 526eb79a267SMarc Kleine-Budde MCP251XFD_POLL_TIMEOUT_US); 5271f0e21a0SMarc Kleine-Budde if (err) { 528eb79a267SMarc Kleine-Budde u8 mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, con); 5291f0e21a0SMarc Kleine-Budde 5301f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 5311f0e21a0SMarc Kleine-Budde "Controller failed to enter mode %s Mode (%u) and stays in %s Mode (%u).\n", 532eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode_req), mode_req, 533eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 5341f0e21a0SMarc Kleine-Budde return err; 5351f0e21a0SMarc Kleine-Budde } 5361f0e21a0SMarc Kleine-Budde 5371f0e21a0SMarc Kleine-Budde return 0; 5381f0e21a0SMarc Kleine-Budde } 5391f0e21a0SMarc Kleine-Budde 5401f0e21a0SMarc Kleine-Budde static inline int 541eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv, 5421f0e21a0SMarc Kleine-Budde const u8 mode_req) 5431f0e21a0SMarc Kleine-Budde { 544eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode_req, false); 5451f0e21a0SMarc Kleine-Budde } 5461f0e21a0SMarc Kleine-Budde 5471f0e21a0SMarc Kleine-Budde static inline int 548eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode_nowait(const struct mcp251xfd_priv *priv, 5491f0e21a0SMarc Kleine-Budde const u8 mode_req) 5501f0e21a0SMarc Kleine-Budde { 551eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode_req, true); 5521f0e21a0SMarc Kleine-Budde } 5531f0e21a0SMarc Kleine-Budde 554eb79a267SMarc Kleine-Budde static inline bool mcp251xfd_osc_invalid(u32 reg) 5551f0e21a0SMarc Kleine-Budde { 5561f0e21a0SMarc Kleine-Budde return reg == 0x0 || reg == 0xffffffff; 5571f0e21a0SMarc Kleine-Budde } 5581f0e21a0SMarc Kleine-Budde 559eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_clock_enable(const struct mcp251xfd_priv *priv) 5601f0e21a0SMarc Kleine-Budde { 5611f0e21a0SMarc Kleine-Budde u32 osc, osc_reference, osc_mask; 5621f0e21a0SMarc Kleine-Budde int err; 5631f0e21a0SMarc Kleine-Budde 5641f0e21a0SMarc Kleine-Budde /* Set Power On Defaults for "Clock Output Divisor" and remove 5651f0e21a0SMarc Kleine-Budde * "Oscillator Disable" bit. 5661f0e21a0SMarc Kleine-Budde */ 567eb79a267SMarc Kleine-Budde osc = FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 568eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 569eb79a267SMarc Kleine-Budde osc_reference = MCP251XFD_REG_OSC_OSCRDY; 570eb79a267SMarc Kleine-Budde osc_mask = MCP251XFD_REG_OSC_OSCRDY | MCP251XFD_REG_OSC_PLLRDY; 5711f0e21a0SMarc Kleine-Budde 5721f0e21a0SMarc Kleine-Budde /* Note: 5731f0e21a0SMarc Kleine-Budde * 5741f0e21a0SMarc Kleine-Budde * If the controller is in Sleep Mode the following write only 5751f0e21a0SMarc Kleine-Budde * removes the "Oscillator Disable" bit and powers it up. All 5761f0e21a0SMarc Kleine-Budde * other bits are unaffected. 5771f0e21a0SMarc Kleine-Budde */ 578eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc); 5791f0e21a0SMarc Kleine-Budde if (err) 5801f0e21a0SMarc Kleine-Budde return err; 5811f0e21a0SMarc Kleine-Budde 5821f0e21a0SMarc Kleine-Budde /* Wait for "Oscillator Ready" bit */ 583eb79a267SMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_OSC, osc, 5841f0e21a0SMarc Kleine-Budde (osc & osc_mask) == osc_reference, 585eb79a267SMarc Kleine-Budde MCP251XFD_OSC_STAB_SLEEP_US, 586eb79a267SMarc Kleine-Budde MCP251XFD_OSC_STAB_TIMEOUT_US); 587eb79a267SMarc Kleine-Budde if (mcp251xfd_osc_invalid(osc)) { 5881f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 5891f0e21a0SMarc Kleine-Budde "Failed to detect %s (osc=0x%08x).\n", 590eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv), osc); 5911f0e21a0SMarc Kleine-Budde return -ENODEV; 5921f0e21a0SMarc Kleine-Budde } else if (err == -ETIMEDOUT) { 5931f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 5941f0e21a0SMarc Kleine-Budde "Timeout waiting for Oscillator Ready (osc=0x%08x, osc_reference=0x%08x)\n", 5951f0e21a0SMarc Kleine-Budde osc, osc_reference); 5961f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 5971f0e21a0SMarc Kleine-Budde } else if (err) { 5981f0e21a0SMarc Kleine-Budde return err; 5991f0e21a0SMarc Kleine-Budde } 6001f0e21a0SMarc Kleine-Budde 6011f0e21a0SMarc Kleine-Budde return 0; 6021f0e21a0SMarc Kleine-Budde } 6031f0e21a0SMarc Kleine-Budde 604eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_do(const struct mcp251xfd_priv *priv) 6051f0e21a0SMarc Kleine-Budde { 606eb79a267SMarc Kleine-Budde const __be16 cmd = mcp251xfd_cmd_reset(); 6071f0e21a0SMarc Kleine-Budde int err; 6081f0e21a0SMarc Kleine-Budde 6091f0e21a0SMarc Kleine-Budde /* The Set Mode and SPI Reset command only seems to works if 6101f0e21a0SMarc Kleine-Budde * the controller is not in Sleep Mode. 6111f0e21a0SMarc Kleine-Budde */ 612eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_clock_enable(priv); 6131f0e21a0SMarc Kleine-Budde if (err) 6141f0e21a0SMarc Kleine-Budde return err; 6151f0e21a0SMarc Kleine-Budde 616eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_CONFIG); 6171f0e21a0SMarc Kleine-Budde if (err) 6181f0e21a0SMarc Kleine-Budde return err; 6191f0e21a0SMarc Kleine-Budde 6201f0e21a0SMarc Kleine-Budde /* spi_write_then_read() works with non DMA-safe buffers */ 6211f0e21a0SMarc Kleine-Budde return spi_write_then_read(priv->spi, &cmd, sizeof(cmd), NULL, 0); 6221f0e21a0SMarc Kleine-Budde } 6231f0e21a0SMarc Kleine-Budde 624eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_check(const struct mcp251xfd_priv *priv) 6251f0e21a0SMarc Kleine-Budde { 6261f0e21a0SMarc Kleine-Budde u32 osc, osc_reference; 6271f0e21a0SMarc Kleine-Budde u8 mode; 6281f0e21a0SMarc Kleine-Budde int err; 6291f0e21a0SMarc Kleine-Budde 630eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_get_mode(priv, &mode); 6311f0e21a0SMarc Kleine-Budde if (err) 6321f0e21a0SMarc Kleine-Budde return err; 6331f0e21a0SMarc Kleine-Budde 634eb79a267SMarc Kleine-Budde if (mode != MCP251XFD_REG_CON_MODE_CONFIG) { 6351f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 6361f0e21a0SMarc Kleine-Budde "Controller not in Config Mode after reset, but in %s Mode (%u).\n", 637eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 6381f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6391f0e21a0SMarc Kleine-Budde } 6401f0e21a0SMarc Kleine-Budde 641eb79a267SMarc Kleine-Budde osc_reference = MCP251XFD_REG_OSC_OSCRDY | 642eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 643eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 6441f0e21a0SMarc Kleine-Budde 6451f0e21a0SMarc Kleine-Budde /* check reset defaults of OSC reg */ 646eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc); 6471f0e21a0SMarc Kleine-Budde if (err) 6481f0e21a0SMarc Kleine-Budde return err; 6491f0e21a0SMarc Kleine-Budde 6501f0e21a0SMarc Kleine-Budde if (osc != osc_reference) { 6511f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 6521f0e21a0SMarc Kleine-Budde "Controller failed to reset. osc=0x%08x, reference value=0x%08x\n", 6531f0e21a0SMarc Kleine-Budde osc, osc_reference); 6541f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6551f0e21a0SMarc Kleine-Budde } 6561f0e21a0SMarc Kleine-Budde 6571f0e21a0SMarc Kleine-Budde return 0; 6581f0e21a0SMarc Kleine-Budde } 6591f0e21a0SMarc Kleine-Budde 660eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset(const struct mcp251xfd_priv *priv) 6611f0e21a0SMarc Kleine-Budde { 6621f0e21a0SMarc Kleine-Budde int err, i; 6631f0e21a0SMarc Kleine-Budde 664eb79a267SMarc Kleine-Budde for (i = 0; i < MCP251XFD_SOFTRESET_RETRIES_MAX; i++) { 6651f0e21a0SMarc Kleine-Budde if (i) 6661f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 6671f0e21a0SMarc Kleine-Budde "Retrying to reset Controller.\n"); 6681f0e21a0SMarc Kleine-Budde 669eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset_do(priv); 6701f0e21a0SMarc Kleine-Budde if (err == -ETIMEDOUT) 6711f0e21a0SMarc Kleine-Budde continue; 6721f0e21a0SMarc Kleine-Budde if (err) 6731f0e21a0SMarc Kleine-Budde return err; 6741f0e21a0SMarc Kleine-Budde 675eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset_check(priv); 6761f0e21a0SMarc Kleine-Budde if (err == -ETIMEDOUT) 6771f0e21a0SMarc Kleine-Budde continue; 6781f0e21a0SMarc Kleine-Budde if (err) 6791f0e21a0SMarc Kleine-Budde return err; 6801f0e21a0SMarc Kleine-Budde 6811f0e21a0SMarc Kleine-Budde return 0; 6821f0e21a0SMarc Kleine-Budde } 6831f0e21a0SMarc Kleine-Budde 6841f0e21a0SMarc Kleine-Budde return err; 6851f0e21a0SMarc Kleine-Budde } 6861f0e21a0SMarc Kleine-Budde 687eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_clock_init(const struct mcp251xfd_priv *priv) 6881f0e21a0SMarc Kleine-Budde { 6891f0e21a0SMarc Kleine-Budde u32 osc; 6901f0e21a0SMarc Kleine-Budde int err; 6911f0e21a0SMarc Kleine-Budde 6921f0e21a0SMarc Kleine-Budde /* Activate Low Power Mode on Oscillator Disable. This only 6931f0e21a0SMarc Kleine-Budde * works on the MCP2518FD. The MCP2517FD will go into normal 6941f0e21a0SMarc Kleine-Budde * Sleep Mode instead. 6951f0e21a0SMarc Kleine-Budde */ 696eb79a267SMarc Kleine-Budde osc = MCP251XFD_REG_OSC_LPMEN | 697eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 698eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 699eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc); 7001f0e21a0SMarc Kleine-Budde if (err) 7011f0e21a0SMarc Kleine-Budde return err; 7021f0e21a0SMarc Kleine-Budde 7031f0e21a0SMarc Kleine-Budde /* Set Time Base Counter Prescaler to 1. 7041f0e21a0SMarc Kleine-Budde * 7051f0e21a0SMarc Kleine-Budde * This means an overflow of the 32 bit Time Base Counter 7061f0e21a0SMarc Kleine-Budde * register at 40 MHz every 107 seconds. 7071f0e21a0SMarc Kleine-Budde */ 708eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_TSCON, 709eb79a267SMarc Kleine-Budde MCP251XFD_REG_TSCON_TBCEN); 7101f0e21a0SMarc Kleine-Budde } 7111f0e21a0SMarc Kleine-Budde 712eb79a267SMarc Kleine-Budde static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv) 7131f0e21a0SMarc Kleine-Budde { 7141f0e21a0SMarc Kleine-Budde const struct can_bittiming *bt = &priv->can.bittiming; 7151f0e21a0SMarc Kleine-Budde const struct can_bittiming *dbt = &priv->can.data_bittiming; 7161f0e21a0SMarc Kleine-Budde u32 val = 0; 7171f0e21a0SMarc Kleine-Budde s8 tdco; 7181f0e21a0SMarc Kleine-Budde int err; 7191f0e21a0SMarc Kleine-Budde 7201f0e21a0SMarc Kleine-Budde /* CAN Control Register 7211f0e21a0SMarc Kleine-Budde * 7221f0e21a0SMarc Kleine-Budde * - no transmit bandwidth sharing 7231f0e21a0SMarc Kleine-Budde * - config mode 7241f0e21a0SMarc Kleine-Budde * - disable transmit queue 7251f0e21a0SMarc Kleine-Budde * - store in transmit FIFO event 7261f0e21a0SMarc Kleine-Budde * - transition to restricted operation mode on system error 7271f0e21a0SMarc Kleine-Budde * - ESI is transmitted recessive when ESI of message is high or 7281f0e21a0SMarc Kleine-Budde * CAN controller error passive 7291f0e21a0SMarc Kleine-Budde * - restricted retransmission attempts, 7301f0e21a0SMarc Kleine-Budde * use TQXCON_TXAT and FIFOCON_TXAT 7311f0e21a0SMarc Kleine-Budde * - wake-up filter bits T11FILTER 7321f0e21a0SMarc Kleine-Budde * - use CAN bus line filter for wakeup 7331f0e21a0SMarc Kleine-Budde * - protocol exception is treated as a form error 7341f0e21a0SMarc Kleine-Budde * - Do not compare data bytes 7351f0e21a0SMarc Kleine-Budde */ 736eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, 737eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_MODE_CONFIG) | 738eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_STEF | 739eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_ESIGM | 740eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_RTXAT | 741eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_CON_WFT_MASK, 742eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_WFT_T11FILTER) | 743eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_WAKFIL | 744eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_PXEDIS; 7451f0e21a0SMarc Kleine-Budde 7461f0e21a0SMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)) 747eb79a267SMarc Kleine-Budde val |= MCP251XFD_REG_CON_ISOCRCEN; 7481f0e21a0SMarc Kleine-Budde 749eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_CON, val); 7501f0e21a0SMarc Kleine-Budde if (err) 7511f0e21a0SMarc Kleine-Budde return err; 7521f0e21a0SMarc Kleine-Budde 7531f0e21a0SMarc Kleine-Budde /* Nominal Bit Time */ 754eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_NBTCFG_BRP_MASK, bt->brp - 1) | 755eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG1_MASK, 7561f0e21a0SMarc Kleine-Budde bt->prop_seg + bt->phase_seg1 - 1) | 757eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG2_MASK, 7581f0e21a0SMarc Kleine-Budde bt->phase_seg2 - 1) | 759eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_SJW_MASK, bt->sjw - 1); 7601f0e21a0SMarc Kleine-Budde 761eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_NBTCFG, val); 7621f0e21a0SMarc Kleine-Budde if (err) 7631f0e21a0SMarc Kleine-Budde return err; 7641f0e21a0SMarc Kleine-Budde 7651f0e21a0SMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD)) 7661f0e21a0SMarc Kleine-Budde return 0; 7671f0e21a0SMarc Kleine-Budde 7681f0e21a0SMarc Kleine-Budde /* Data Bit Time */ 769eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_DBTCFG_BRP_MASK, dbt->brp - 1) | 770eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG1_MASK, 7711f0e21a0SMarc Kleine-Budde dbt->prop_seg + dbt->phase_seg1 - 1) | 772eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG2_MASK, 7731f0e21a0SMarc Kleine-Budde dbt->phase_seg2 - 1) | 774eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_SJW_MASK, dbt->sjw - 1); 7751f0e21a0SMarc Kleine-Budde 776eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_DBTCFG, val); 7771f0e21a0SMarc Kleine-Budde if (err) 7781f0e21a0SMarc Kleine-Budde return err; 7791f0e21a0SMarc Kleine-Budde 7801f0e21a0SMarc Kleine-Budde /* Transmitter Delay Compensation */ 7811f0e21a0SMarc Kleine-Budde tdco = clamp_t(int, dbt->brp * (dbt->prop_seg + dbt->phase_seg1), 7821f0e21a0SMarc Kleine-Budde -64, 63); 783eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, 784eb79a267SMarc Kleine-Budde MCP251XFD_REG_TDC_TDCMOD_AUTO) | 785eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, tdco); 7861f0e21a0SMarc Kleine-Budde 787eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val); 7881f0e21a0SMarc Kleine-Budde } 7891f0e21a0SMarc Kleine-Budde 790eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_enable(const struct mcp251xfd_priv *priv) 7911f0e21a0SMarc Kleine-Budde { 7921f0e21a0SMarc Kleine-Budde u32 val; 7931f0e21a0SMarc Kleine-Budde 7941f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 7951f0e21a0SMarc Kleine-Budde return 0; 7961f0e21a0SMarc Kleine-Budde 7971f0e21a0SMarc Kleine-Budde /* Configure GPIOs: 7981f0e21a0SMarc Kleine-Budde * - PIN0: GPIO Input 7991f0e21a0SMarc Kleine-Budde * - PIN1: GPIO Input/RX Interrupt 8001f0e21a0SMarc Kleine-Budde * 8011f0e21a0SMarc Kleine-Budde * PIN1 must be Input, otherwise there is a glitch on the 8021f0e21a0SMarc Kleine-Budde * rx-INT line. It happens between setting the PIN as output 8031f0e21a0SMarc Kleine-Budde * (in the first byte of the SPI transfer) and configuring the 8041f0e21a0SMarc Kleine-Budde * PIN as interrupt (in the last byte of the SPI transfer). 8051f0e21a0SMarc Kleine-Budde */ 806eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_IOCON_PM0 | MCP251XFD_REG_IOCON_TRIS1 | 807eb79a267SMarc Kleine-Budde MCP251XFD_REG_IOCON_TRIS0; 808eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val); 8091f0e21a0SMarc Kleine-Budde } 8101f0e21a0SMarc Kleine-Budde 811eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_disable(const struct mcp251xfd_priv *priv) 8121f0e21a0SMarc Kleine-Budde { 8131f0e21a0SMarc Kleine-Budde u32 val; 8141f0e21a0SMarc Kleine-Budde 8151f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 8161f0e21a0SMarc Kleine-Budde return 0; 8171f0e21a0SMarc Kleine-Budde 8181f0e21a0SMarc Kleine-Budde /* Configure GPIOs: 8191f0e21a0SMarc Kleine-Budde * - PIN0: GPIO Input 8201f0e21a0SMarc Kleine-Budde * - PIN1: GPIO Input 8211f0e21a0SMarc Kleine-Budde */ 822eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_IOCON_PM1 | MCP251XFD_REG_IOCON_PM0 | 823eb79a267SMarc Kleine-Budde MCP251XFD_REG_IOCON_TRIS1 | MCP251XFD_REG_IOCON_TRIS0; 824eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val); 8251f0e21a0SMarc Kleine-Budde } 8261f0e21a0SMarc Kleine-Budde 8271f0e21a0SMarc Kleine-Budde static int 828eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_fifo_init_one(const struct mcp251xfd_priv *priv, 829eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring) 8301f0e21a0SMarc Kleine-Budde { 8311f0e21a0SMarc Kleine-Budde u32 fifo_con; 8321f0e21a0SMarc Kleine-Budde 8331f0e21a0SMarc Kleine-Budde /* Enable RXOVIE on _all_ RX FIFOs, not just the last one. 8341f0e21a0SMarc Kleine-Budde * 8351f0e21a0SMarc Kleine-Budde * FIFOs hit by a RX MAB overflow and RXOVIE enabled will 8361f0e21a0SMarc Kleine-Budde * generate a RXOVIF, use this to properly detect RX MAB 8371f0e21a0SMarc Kleine-Budde * overflows. 8381f0e21a0SMarc Kleine-Budde */ 839eb79a267SMarc Kleine-Budde fifo_con = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK, 8401f0e21a0SMarc Kleine-Budde ring->obj_num - 1) | 841eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_RXTSEN | 842eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_RXOVIE | 843eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TFNRFNIE; 8441f0e21a0SMarc Kleine-Budde 8451f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) 846eb79a267SMarc Kleine-Budde fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 847eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_64); 8481f0e21a0SMarc Kleine-Budde else 849eb79a267SMarc Kleine-Budde fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 850eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_8); 8511f0e21a0SMarc Kleine-Budde 8521f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, 853eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON(ring->fifo_nr), fifo_con); 8541f0e21a0SMarc Kleine-Budde } 8551f0e21a0SMarc Kleine-Budde 8561f0e21a0SMarc Kleine-Budde static int 857eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_filter_init_one(const struct mcp251xfd_priv *priv, 858eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring) 8591f0e21a0SMarc Kleine-Budde { 8601f0e21a0SMarc Kleine-Budde u32 fltcon; 8611f0e21a0SMarc Kleine-Budde 862eb79a267SMarc Kleine-Budde fltcon = MCP251XFD_REG_FLTCON_FLTEN(ring->nr) | 863eb79a267SMarc Kleine-Budde MCP251XFD_REG_FLTCON_FBP(ring->nr, ring->fifo_nr); 8641f0e21a0SMarc Kleine-Budde 8651f0e21a0SMarc Kleine-Budde return regmap_update_bits(priv->map_reg, 866eb79a267SMarc Kleine-Budde MCP251XFD_REG_FLTCON(ring->nr >> 2), 867eb79a267SMarc Kleine-Budde MCP251XFD_REG_FLTCON_FLT_MASK(ring->nr), 8681f0e21a0SMarc Kleine-Budde fltcon); 8691f0e21a0SMarc Kleine-Budde } 8701f0e21a0SMarc Kleine-Budde 871eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv) 8721f0e21a0SMarc Kleine-Budde { 873eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 874eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *rx_ring; 8751f0e21a0SMarc Kleine-Budde u32 val; 8761f0e21a0SMarc Kleine-Budde int err, n; 8771f0e21a0SMarc Kleine-Budde 8781f0e21a0SMarc Kleine-Budde /* TEF */ 879eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_TEFCON_FSIZE_MASK, 8801f0e21a0SMarc Kleine-Budde tx_ring->obj_num - 1) | 881eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFTSEN | 882eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFOVIE | 883eb79a267SMarc Kleine-Budde MCP251XFD_REG_TEFCON_TEFNEIE; 8841f0e21a0SMarc Kleine-Budde 885eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_TEFCON, val); 8861f0e21a0SMarc Kleine-Budde if (err) 8871f0e21a0SMarc Kleine-Budde return err; 8881f0e21a0SMarc Kleine-Budde 8891f0e21a0SMarc Kleine-Budde /* FIFO 1 - TX */ 890eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK, 8911f0e21a0SMarc Kleine-Budde tx_ring->obj_num - 1) | 892eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXEN | 893eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXATIE; 8941f0e21a0SMarc Kleine-Budde 8951f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) 896eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 897eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_64); 8981f0e21a0SMarc Kleine-Budde else 899eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK, 900eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_PLSIZE_8); 9011f0e21a0SMarc Kleine-Budde 9021f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) 903eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK, 904eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXAT_ONE_SHOT); 9051f0e21a0SMarc Kleine-Budde else 906eb79a267SMarc Kleine-Budde val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK, 907eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON_TXAT_UNLIMITED); 9081f0e21a0SMarc Kleine-Budde 9091f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, 910eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO), 9111f0e21a0SMarc Kleine-Budde val); 9121f0e21a0SMarc Kleine-Budde if (err) 9131f0e21a0SMarc Kleine-Budde return err; 9141f0e21a0SMarc Kleine-Budde 9151f0e21a0SMarc Kleine-Budde /* RX FIFOs */ 916eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, rx_ring, n) { 917eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_fifo_init_one(priv, rx_ring); 9181f0e21a0SMarc Kleine-Budde if (err) 9191f0e21a0SMarc Kleine-Budde return err; 9201f0e21a0SMarc Kleine-Budde 921eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_filter_init_one(priv, rx_ring); 9221f0e21a0SMarc Kleine-Budde if (err) 9231f0e21a0SMarc Kleine-Budde return err; 9241f0e21a0SMarc Kleine-Budde } 9251f0e21a0SMarc Kleine-Budde 9261f0e21a0SMarc Kleine-Budde return 0; 9271f0e21a0SMarc Kleine-Budde } 9281f0e21a0SMarc Kleine-Budde 929eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_ecc_init(struct mcp251xfd_priv *priv) 9301f0e21a0SMarc Kleine-Budde { 931eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 9321f0e21a0SMarc Kleine-Budde void *ram; 9331f0e21a0SMarc Kleine-Budde u32 val = 0; 9341f0e21a0SMarc Kleine-Budde int err; 9351f0e21a0SMarc Kleine-Budde 9361f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 9371f0e21a0SMarc Kleine-Budde 938eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_ECC) 939eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_ECCCON_ECCEN; 9401f0e21a0SMarc Kleine-Budde 941eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, 942eb79a267SMarc Kleine-Budde MCP251XFD_REG_ECCCON_ECCEN, val); 9431f0e21a0SMarc Kleine-Budde if (err) 9441f0e21a0SMarc Kleine-Budde return err; 9451f0e21a0SMarc Kleine-Budde 946eb79a267SMarc Kleine-Budde ram = kzalloc(MCP251XFD_RAM_SIZE, GFP_KERNEL); 9471f0e21a0SMarc Kleine-Budde if (!ram) 9481f0e21a0SMarc Kleine-Budde return -ENOMEM; 9491f0e21a0SMarc Kleine-Budde 950eb79a267SMarc Kleine-Budde err = regmap_raw_write(priv->map_reg, MCP251XFD_RAM_START, ram, 951eb79a267SMarc Kleine-Budde MCP251XFD_RAM_SIZE); 9521f0e21a0SMarc Kleine-Budde kfree(ram); 9531f0e21a0SMarc Kleine-Budde 9541f0e21a0SMarc Kleine-Budde return err; 9551f0e21a0SMarc Kleine-Budde } 9561f0e21a0SMarc Kleine-Budde 957eb79a267SMarc Kleine-Budde static inline void mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv *priv) 9581f0e21a0SMarc Kleine-Budde { 959eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 9601f0e21a0SMarc Kleine-Budde 9611f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 9621f0e21a0SMarc Kleine-Budde } 9631f0e21a0SMarc Kleine-Budde 964eb79a267SMarc Kleine-Budde static u8 mcp251xfd_get_normal_mode(const struct mcp251xfd_priv *priv) 9651f0e21a0SMarc Kleine-Budde { 9661f0e21a0SMarc Kleine-Budde u8 mode; 9671f0e21a0SMarc Kleine-Budde 968ee42bedcSManivannan Sadhasivam 969ee42bedcSManivannan Sadhasivam if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) 970ee42bedcSManivannan Sadhasivam mode = MCP251XFD_REG_CON_MODE_INT_LOOPBACK; 971ee42bedcSManivannan Sadhasivam else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 972eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_LISTENONLY; 9731f0e21a0SMarc Kleine-Budde else if (priv->can.ctrlmode & CAN_CTRLMODE_FD) 974eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_MIXED; 9751f0e21a0SMarc Kleine-Budde else 976eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_CAN2_0; 9771f0e21a0SMarc Kleine-Budde 9781f0e21a0SMarc Kleine-Budde return mode; 9791f0e21a0SMarc Kleine-Budde } 9801f0e21a0SMarc Kleine-Budde 9811f0e21a0SMarc Kleine-Budde static int 982eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv, 9831f0e21a0SMarc Kleine-Budde bool nowait) 9841f0e21a0SMarc Kleine-Budde { 9851f0e21a0SMarc Kleine-Budde u8 mode; 9861f0e21a0SMarc Kleine-Budde 987eb79a267SMarc Kleine-Budde mode = mcp251xfd_get_normal_mode(priv); 9881f0e21a0SMarc Kleine-Budde 989eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode, nowait); 9901f0e21a0SMarc Kleine-Budde } 9911f0e21a0SMarc Kleine-Budde 9921f0e21a0SMarc Kleine-Budde static inline int 993eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv) 9941f0e21a0SMarc Kleine-Budde { 995eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_normal_mode(priv, false); 9961f0e21a0SMarc Kleine-Budde } 9971f0e21a0SMarc Kleine-Budde 9981f0e21a0SMarc Kleine-Budde static inline int 999eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode_nowait(const struct mcp251xfd_priv *priv) 10001f0e21a0SMarc Kleine-Budde { 1001eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_normal_mode(priv, true); 10021f0e21a0SMarc Kleine-Budde } 10031f0e21a0SMarc Kleine-Budde 1004eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_enable(const struct mcp251xfd_priv *priv) 10051f0e21a0SMarc Kleine-Budde { 10061f0e21a0SMarc Kleine-Budde u32 val; 10071f0e21a0SMarc Kleine-Budde int err; 10081f0e21a0SMarc Kleine-Budde 1009eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_CRC_FERRIE | MCP251XFD_REG_CRC_CRCERRIE; 1010eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_CRC, val); 10111f0e21a0SMarc Kleine-Budde if (err) 10121f0e21a0SMarc Kleine-Budde return err; 10131f0e21a0SMarc Kleine-Budde 1014eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE; 1015eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, val, val); 10161f0e21a0SMarc Kleine-Budde if (err) 10171f0e21a0SMarc Kleine-Budde return err; 10181f0e21a0SMarc Kleine-Budde 1019eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_INT_CERRIE | 1020eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_SERRIE | 1021eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_RXOVIE | 1022eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_TXATIE | 1023eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_SPICRCIE | 1024eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_ECCIE | 1025eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_TEFIE | 1026eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_MODIE | 1027eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_RXIE; 10281f0e21a0SMarc Kleine-Budde 10291f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) 1030eb79a267SMarc Kleine-Budde val |= MCP251XFD_REG_INT_IVMIE; 10311f0e21a0SMarc Kleine-Budde 1032eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_INT, val); 10331f0e21a0SMarc Kleine-Budde } 10341f0e21a0SMarc Kleine-Budde 1035eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_disable(const struct mcp251xfd_priv *priv) 10361f0e21a0SMarc Kleine-Budde { 10371f0e21a0SMarc Kleine-Budde int err; 10381f0e21a0SMarc Kleine-Budde u32 mask; 10391f0e21a0SMarc Kleine-Budde 1040eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_INT, 0); 10411f0e21a0SMarc Kleine-Budde if (err) 10421f0e21a0SMarc Kleine-Budde return err; 10431f0e21a0SMarc Kleine-Budde 1044eb79a267SMarc Kleine-Budde mask = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE; 1045eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, 10461f0e21a0SMarc Kleine-Budde mask, 0x0); 10471f0e21a0SMarc Kleine-Budde if (err) 10481f0e21a0SMarc Kleine-Budde return err; 10491f0e21a0SMarc Kleine-Budde 1050eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_CRC, 0); 10511f0e21a0SMarc Kleine-Budde } 10521f0e21a0SMarc Kleine-Budde 1053eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_stop(struct mcp251xfd_priv *priv, 10541f0e21a0SMarc Kleine-Budde const enum can_state state) 10551f0e21a0SMarc Kleine-Budde { 10561f0e21a0SMarc Kleine-Budde priv->can.state = state; 10571f0e21a0SMarc Kleine-Budde 1058eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 1059eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_int_disable(priv); 1060eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 10611f0e21a0SMarc Kleine-Budde } 10621f0e21a0SMarc Kleine-Budde 1063eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv) 10641f0e21a0SMarc Kleine-Budde { 10651f0e21a0SMarc Kleine-Budde int err; 10661f0e21a0SMarc Kleine-Budde 1067eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset(priv); 10681f0e21a0SMarc Kleine-Budde if (err) 10691f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10701f0e21a0SMarc Kleine-Budde 1071eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_clock_init(priv); 10721f0e21a0SMarc Kleine-Budde if (err) 10731f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10741f0e21a0SMarc Kleine-Budde 1075eb79a267SMarc Kleine-Budde err = mcp251xfd_set_bittiming(priv); 10761f0e21a0SMarc Kleine-Budde if (err) 10771f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10781f0e21a0SMarc Kleine-Budde 1079eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_enable(priv); 10801f0e21a0SMarc Kleine-Budde if (err) 10811f0e21a0SMarc Kleine-Budde return err; 10821f0e21a0SMarc Kleine-Budde 1083eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_ecc_init(priv); 10841f0e21a0SMarc Kleine-Budde if (err) 10851f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10861f0e21a0SMarc Kleine-Budde 1087eb79a267SMarc Kleine-Budde mcp251xfd_ring_init(priv); 10881f0e21a0SMarc Kleine-Budde 1089eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_fifo_init(priv); 10901f0e21a0SMarc Kleine-Budde if (err) 10911f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10921f0e21a0SMarc Kleine-Budde 10931f0e21a0SMarc Kleine-Budde priv->can.state = CAN_STATE_ERROR_ACTIVE; 10941f0e21a0SMarc Kleine-Budde 1095eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_normal_mode(priv); 10961f0e21a0SMarc Kleine-Budde if (err) 10971f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10981f0e21a0SMarc Kleine-Budde 10991f0e21a0SMarc Kleine-Budde return 0; 11001f0e21a0SMarc Kleine-Budde 11011f0e21a0SMarc Kleine-Budde out_chip_stop: 1102eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 11031f0e21a0SMarc Kleine-Budde 11041f0e21a0SMarc Kleine-Budde return err; 11051f0e21a0SMarc Kleine-Budde } 11061f0e21a0SMarc Kleine-Budde 1107eb79a267SMarc Kleine-Budde static int mcp251xfd_set_mode(struct net_device *ndev, enum can_mode mode) 11081f0e21a0SMarc Kleine-Budde { 1109eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 11101f0e21a0SMarc Kleine-Budde int err; 11111f0e21a0SMarc Kleine-Budde 11121f0e21a0SMarc Kleine-Budde switch (mode) { 11131f0e21a0SMarc Kleine-Budde case CAN_MODE_START: 1114eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_start(priv); 11151f0e21a0SMarc Kleine-Budde if (err) 11161f0e21a0SMarc Kleine-Budde return err; 11171f0e21a0SMarc Kleine-Budde 1118eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_interrupts_enable(priv); 11191f0e21a0SMarc Kleine-Budde if (err) { 1120eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 11211f0e21a0SMarc Kleine-Budde return err; 11221f0e21a0SMarc Kleine-Budde } 11231f0e21a0SMarc Kleine-Budde 11241f0e21a0SMarc Kleine-Budde netif_wake_queue(ndev); 11251f0e21a0SMarc Kleine-Budde break; 11261f0e21a0SMarc Kleine-Budde 11271f0e21a0SMarc Kleine-Budde default: 11281f0e21a0SMarc Kleine-Budde return -EOPNOTSUPP; 11291f0e21a0SMarc Kleine-Budde } 11301f0e21a0SMarc Kleine-Budde 11311f0e21a0SMarc Kleine-Budde return 0; 11321f0e21a0SMarc Kleine-Budde } 11331f0e21a0SMarc Kleine-Budde 1134eb79a267SMarc Kleine-Budde static int __mcp251xfd_get_berr_counter(const struct net_device *ndev, 11351f0e21a0SMarc Kleine-Budde struct can_berr_counter *bec) 11361f0e21a0SMarc Kleine-Budde { 1137eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = netdev_priv(ndev); 11381f0e21a0SMarc Kleine-Budde u32 trec; 11391f0e21a0SMarc Kleine-Budde int err; 11401f0e21a0SMarc Kleine-Budde 1141eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec); 11421f0e21a0SMarc Kleine-Budde if (err) 11431f0e21a0SMarc Kleine-Budde return err; 11441f0e21a0SMarc Kleine-Budde 1145eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_TXBO) 11461f0e21a0SMarc Kleine-Budde bec->txerr = 256; 11471f0e21a0SMarc Kleine-Budde else 1148eb79a267SMarc Kleine-Budde bec->txerr = FIELD_GET(MCP251XFD_REG_TREC_TEC_MASK, trec); 1149eb79a267SMarc Kleine-Budde bec->rxerr = FIELD_GET(MCP251XFD_REG_TREC_REC_MASK, trec); 11501f0e21a0SMarc Kleine-Budde 11511f0e21a0SMarc Kleine-Budde return 0; 11521f0e21a0SMarc Kleine-Budde } 11531f0e21a0SMarc Kleine-Budde 1154eb79a267SMarc Kleine-Budde static int mcp251xfd_get_berr_counter(const struct net_device *ndev, 11551f0e21a0SMarc Kleine-Budde struct can_berr_counter *bec) 11561f0e21a0SMarc Kleine-Budde { 1157eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = netdev_priv(ndev); 11581f0e21a0SMarc Kleine-Budde 11591f0e21a0SMarc Kleine-Budde /* Avoid waking up the controller if the interface is down */ 11601f0e21a0SMarc Kleine-Budde if (!(ndev->flags & IFF_UP)) 11611f0e21a0SMarc Kleine-Budde return 0; 11621f0e21a0SMarc Kleine-Budde 11631f0e21a0SMarc Kleine-Budde /* The controller is powered down during Bus Off, use saved 11641f0e21a0SMarc Kleine-Budde * bec values. 11651f0e21a0SMarc Kleine-Budde */ 11661f0e21a0SMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) { 11671f0e21a0SMarc Kleine-Budde *bec = priv->bec; 11681f0e21a0SMarc Kleine-Budde return 0; 11691f0e21a0SMarc Kleine-Budde } 11701f0e21a0SMarc Kleine-Budde 1171eb79a267SMarc Kleine-Budde return __mcp251xfd_get_berr_counter(ndev, bec); 11721f0e21a0SMarc Kleine-Budde } 11731f0e21a0SMarc Kleine-Budde 1174eb79a267SMarc Kleine-Budde static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv) 11751f0e21a0SMarc Kleine-Budde { 11761f0e21a0SMarc Kleine-Budde u8 tef_tail_chip, tef_tail; 11771f0e21a0SMarc Kleine-Budde int err; 11781f0e21a0SMarc Kleine-Budde 1179eb79a267SMarc Kleine-Budde if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY)) 11801f0e21a0SMarc Kleine-Budde return 0; 11811f0e21a0SMarc Kleine-Budde 1182eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_tail_get_from_chip(priv, &tef_tail_chip); 11831f0e21a0SMarc Kleine-Budde if (err) 11841f0e21a0SMarc Kleine-Budde return err; 11851f0e21a0SMarc Kleine-Budde 1186eb79a267SMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 11871f0e21a0SMarc Kleine-Budde if (tef_tail_chip != tef_tail) { 11881f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 11891f0e21a0SMarc Kleine-Budde "TEF tail of chip (0x%02x) and ours (0x%08x) inconsistent.\n", 11901f0e21a0SMarc Kleine-Budde tef_tail_chip, tef_tail); 11911f0e21a0SMarc Kleine-Budde return -EILSEQ; 11921f0e21a0SMarc Kleine-Budde } 11931f0e21a0SMarc Kleine-Budde 11941f0e21a0SMarc Kleine-Budde return 0; 11951f0e21a0SMarc Kleine-Budde } 11961f0e21a0SMarc Kleine-Budde 11971f0e21a0SMarc Kleine-Budde static int 1198eb79a267SMarc Kleine-Budde mcp251xfd_check_rx_tail(const struct mcp251xfd_priv *priv, 1199eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring) 12001f0e21a0SMarc Kleine-Budde { 12011f0e21a0SMarc Kleine-Budde u8 rx_tail_chip, rx_tail; 12021f0e21a0SMarc Kleine-Budde int err; 12031f0e21a0SMarc Kleine-Budde 1204eb79a267SMarc Kleine-Budde if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY)) 12051f0e21a0SMarc Kleine-Budde return 0; 12061f0e21a0SMarc Kleine-Budde 1207eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_tail_get_from_chip(priv, ring, &rx_tail_chip); 12081f0e21a0SMarc Kleine-Budde if (err) 12091f0e21a0SMarc Kleine-Budde return err; 12101f0e21a0SMarc Kleine-Budde 1211eb79a267SMarc Kleine-Budde rx_tail = mcp251xfd_get_rx_tail(ring); 12121f0e21a0SMarc Kleine-Budde if (rx_tail_chip != rx_tail) { 12131f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 12141f0e21a0SMarc Kleine-Budde "RX tail of chip (%d) and ours (%d) inconsistent.\n", 12151f0e21a0SMarc Kleine-Budde rx_tail_chip, rx_tail); 12161f0e21a0SMarc Kleine-Budde return -EILSEQ; 12171f0e21a0SMarc Kleine-Budde } 12181f0e21a0SMarc Kleine-Budde 12191f0e21a0SMarc Kleine-Budde return 0; 12201f0e21a0SMarc Kleine-Budde } 12211f0e21a0SMarc Kleine-Budde 12221f0e21a0SMarc Kleine-Budde static int 1223eb79a267SMarc Kleine-Budde mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq) 12241f0e21a0SMarc Kleine-Budde { 1225eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 12261f0e21a0SMarc Kleine-Budde u32 tef_sta; 12271f0e21a0SMarc Kleine-Budde int err; 12281f0e21a0SMarc Kleine-Budde 1229eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta); 12301f0e21a0SMarc Kleine-Budde if (err) 12311f0e21a0SMarc Kleine-Budde return err; 12321f0e21a0SMarc Kleine-Budde 1233eb79a267SMarc Kleine-Budde if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) { 12341f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 12351f0e21a0SMarc Kleine-Budde "Transmit Event FIFO buffer overflow.\n"); 12361f0e21a0SMarc Kleine-Budde return -ENOBUFS; 12371f0e21a0SMarc Kleine-Budde } 12381f0e21a0SMarc Kleine-Budde 12391f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 12401f0e21a0SMarc Kleine-Budde "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x)\n", 1241eb79a267SMarc Kleine-Budde tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ? 1242eb79a267SMarc Kleine-Budde "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ? 12431f0e21a0SMarc Kleine-Budde "not empty" : "empty", 1244dada6a6cSMarc Kleine-Budde seq, priv->tef->tail, priv->tef->head, tx_ring->head); 12451f0e21a0SMarc Kleine-Budde 12461f0e21a0SMarc Kleine-Budde /* The Sequence Number in the TEF doesn't match our tef_tail. */ 12471f0e21a0SMarc Kleine-Budde return -EAGAIN; 12481f0e21a0SMarc Kleine-Budde } 12491f0e21a0SMarc Kleine-Budde 12501f0e21a0SMarc Kleine-Budde static int 1251eb79a267SMarc Kleine-Budde mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv, 1252eb79a267SMarc Kleine-Budde const struct mcp251xfd_hw_tef_obj *hw_tef_obj) 12531f0e21a0SMarc Kleine-Budde { 12541f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 12551f0e21a0SMarc Kleine-Budde u32 seq, seq_masked, tef_tail_masked; 12561f0e21a0SMarc Kleine-Budde 1257eb79a267SMarc Kleine-Budde seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, 12581f0e21a0SMarc Kleine-Budde hw_tef_obj->flags); 12591f0e21a0SMarc Kleine-Budde 12601f0e21a0SMarc Kleine-Budde /* Use the MCP2517FD mask on the MCP2518FD, too. We only 12611f0e21a0SMarc Kleine-Budde * compare 7 bits, this should be enough to detect 12621f0e21a0SMarc Kleine-Budde * net-yet-completed, i.e. old TEF objects. 12631f0e21a0SMarc Kleine-Budde */ 12641f0e21a0SMarc Kleine-Budde seq_masked = seq & 1265eb79a267SMarc Kleine-Budde field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 1266dada6a6cSMarc Kleine-Budde tef_tail_masked = priv->tef->tail & 1267eb79a267SMarc Kleine-Budde field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 12681f0e21a0SMarc Kleine-Budde if (seq_masked != tef_tail_masked) 1269eb79a267SMarc Kleine-Budde return mcp251xfd_handle_tefif_recover(priv, seq); 12701f0e21a0SMarc Kleine-Budde 12711f0e21a0SMarc Kleine-Budde stats->tx_bytes += 12721f0e21a0SMarc Kleine-Budde can_rx_offload_get_echo_skb(&priv->offload, 1273eb79a267SMarc Kleine-Budde mcp251xfd_get_tef_tail(priv), 127499842c96SMarc Kleine-Budde hw_tef_obj->ts, NULL); 12751f0e21a0SMarc Kleine-Budde stats->tx_packets++; 1276dada6a6cSMarc Kleine-Budde priv->tef->tail++; 12771f0e21a0SMarc Kleine-Budde 127868c0c1c7SMarc Kleine-Budde return 0; 12791f0e21a0SMarc Kleine-Budde } 12801f0e21a0SMarc Kleine-Budde 1281eb79a267SMarc Kleine-Budde static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv) 12821f0e21a0SMarc Kleine-Budde { 1283eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 12841f0e21a0SMarc Kleine-Budde unsigned int new_head; 12851f0e21a0SMarc Kleine-Budde u8 chip_tx_tail; 12861f0e21a0SMarc Kleine-Budde int err; 12871f0e21a0SMarc Kleine-Budde 1288eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail); 12891f0e21a0SMarc Kleine-Budde if (err) 12901f0e21a0SMarc Kleine-Budde return err; 12911f0e21a0SMarc Kleine-Budde 12921f0e21a0SMarc Kleine-Budde /* chip_tx_tail, is the next TX-Object send by the HW. 12931f0e21a0SMarc Kleine-Budde * The new TEF head must be >= the old head, ... 12941f0e21a0SMarc Kleine-Budde */ 1295dada6a6cSMarc Kleine-Budde new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail; 1296dada6a6cSMarc Kleine-Budde if (new_head <= priv->tef->head) 12971f0e21a0SMarc Kleine-Budde new_head += tx_ring->obj_num; 12981f0e21a0SMarc Kleine-Budde 12991f0e21a0SMarc Kleine-Budde /* ... but it cannot exceed the TX head. */ 1300dada6a6cSMarc Kleine-Budde priv->tef->head = min(new_head, tx_ring->head); 13011f0e21a0SMarc Kleine-Budde 1302eb79a267SMarc Kleine-Budde return mcp251xfd_check_tef_tail(priv); 13031f0e21a0SMarc Kleine-Budde } 13041f0e21a0SMarc Kleine-Budde 13051f0e21a0SMarc Kleine-Budde static inline int 1306eb79a267SMarc Kleine-Budde mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv, 1307eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_tef_obj *hw_tef_obj, 13081f0e21a0SMarc Kleine-Budde const u8 offset, const u8 len) 13091f0e21a0SMarc Kleine-Budde { 1310eb79a267SMarc Kleine-Budde const struct mcp251xfd_tx_ring *tx_ring = priv->tx; 1311cdc4c698SSu Yanjun const int val_bytes = regmap_get_val_bytes(priv->map_rx); 13121f0e21a0SMarc Kleine-Budde 1313eb79a267SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) && 13141f0e21a0SMarc Kleine-Budde (offset > tx_ring->obj_num || 13151f0e21a0SMarc Kleine-Budde len > tx_ring->obj_num || 13161f0e21a0SMarc Kleine-Budde offset + len > tx_ring->obj_num)) { 13171f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 13181f0e21a0SMarc Kleine-Budde "Trying to read to many TEF objects (max=%d, offset=%d, len=%d).\n", 13191f0e21a0SMarc Kleine-Budde tx_ring->obj_num, offset, len); 13201f0e21a0SMarc Kleine-Budde return -ERANGE; 13211f0e21a0SMarc Kleine-Budde } 13221f0e21a0SMarc Kleine-Budde 13231f0e21a0SMarc Kleine-Budde return regmap_bulk_read(priv->map_rx, 1324eb79a267SMarc Kleine-Budde mcp251xfd_get_tef_obj_addr(offset), 13251f0e21a0SMarc Kleine-Budde hw_tef_obj, 1326cdc4c698SSu Yanjun sizeof(*hw_tef_obj) / val_bytes * len); 13271f0e21a0SMarc Kleine-Budde } 13281f0e21a0SMarc Kleine-Budde 1329eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv) 13301f0e21a0SMarc Kleine-Budde { 1331eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX]; 13321f0e21a0SMarc Kleine-Budde u8 tef_tail, len, l; 13331f0e21a0SMarc Kleine-Budde int err, i; 13341f0e21a0SMarc Kleine-Budde 1335eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_ring_update(priv); 13361f0e21a0SMarc Kleine-Budde if (err) 13371f0e21a0SMarc Kleine-Budde return err; 13381f0e21a0SMarc Kleine-Budde 1339eb79a267SMarc Kleine-Budde tef_tail = mcp251xfd_get_tef_tail(priv); 1340eb79a267SMarc Kleine-Budde len = mcp251xfd_get_tef_len(priv); 1341eb79a267SMarc Kleine-Budde l = mcp251xfd_get_tef_linear_len(priv); 1342eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l); 13431f0e21a0SMarc Kleine-Budde if (err) 13441f0e21a0SMarc Kleine-Budde return err; 13451f0e21a0SMarc Kleine-Budde 13461f0e21a0SMarc Kleine-Budde if (l < len) { 1347eb79a267SMarc Kleine-Budde err = mcp251xfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l); 13481f0e21a0SMarc Kleine-Budde if (err) 13491f0e21a0SMarc Kleine-Budde return err; 13501f0e21a0SMarc Kleine-Budde } 13511f0e21a0SMarc Kleine-Budde 13521f0e21a0SMarc Kleine-Budde for (i = 0; i < len; i++) { 1353eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i]); 13541f0e21a0SMarc Kleine-Budde /* -EAGAIN means the Sequence Number in the TEF 13551f0e21a0SMarc Kleine-Budde * doesn't match our tef_tail. This can happen if we 13561f0e21a0SMarc Kleine-Budde * read the TEF objects too early. Leave loop let the 13571f0e21a0SMarc Kleine-Budde * interrupt handler call us again. 13581f0e21a0SMarc Kleine-Budde */ 13591f0e21a0SMarc Kleine-Budde if (err == -EAGAIN) 13601f0e21a0SMarc Kleine-Budde goto out_netif_wake_queue; 13611f0e21a0SMarc Kleine-Budde if (err) 13621f0e21a0SMarc Kleine-Budde return err; 13631f0e21a0SMarc Kleine-Budde } 13641f0e21a0SMarc Kleine-Budde 13651f0e21a0SMarc Kleine-Budde out_netif_wake_queue: 136668c0c1c7SMarc Kleine-Budde len = i; /* number of handled goods TEFs */ 136768c0c1c7SMarc Kleine-Budde if (len) { 136868c0c1c7SMarc Kleine-Budde struct mcp251xfd_tef_ring *ring = priv->tef; 136968c0c1c7SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 137068c0c1c7SMarc Kleine-Budde struct spi_transfer *last_xfer; 137168c0c1c7SMarc Kleine-Budde 137268c0c1c7SMarc Kleine-Budde /* Increment the TEF FIFO tail pointer 'len' times in 137368c0c1c7SMarc Kleine-Budde * a single SPI message. 13746086f02aSMarc Kleine-Budde * 13756086f02aSMarc Kleine-Budde * Note: 137668c0c1c7SMarc Kleine-Budde * 137768c0c1c7SMarc Kleine-Budde * "cs_change == 1" on the last transfer results in an 137868c0c1c7SMarc Kleine-Budde * active chip select after the complete SPI 137968c0c1c7SMarc Kleine-Budde * message. This causes the controller to interpret 138068c0c1c7SMarc Kleine-Budde * the next register access as data. Temporary set 138168c0c1c7SMarc Kleine-Budde * "cs_change" of the last transfer to "0" to properly 138268c0c1c7SMarc Kleine-Budde * deactivate the chip select at the end of the 138368c0c1c7SMarc Kleine-Budde * message. 138468c0c1c7SMarc Kleine-Budde */ 138568c0c1c7SMarc Kleine-Budde last_xfer = &ring->uinc_xfer[len - 1]; 138668c0c1c7SMarc Kleine-Budde last_xfer->cs_change = 0; 138768c0c1c7SMarc Kleine-Budde err = spi_sync_transfer(priv->spi, ring->uinc_xfer, len); 138868c0c1c7SMarc Kleine-Budde last_xfer->cs_change = 1; 138968c0c1c7SMarc Kleine-Budde if (err) 139068c0c1c7SMarc Kleine-Budde return err; 139168c0c1c7SMarc Kleine-Budde 13926086f02aSMarc Kleine-Budde tx_ring->tail += len; 13936086f02aSMarc Kleine-Budde 139468c0c1c7SMarc Kleine-Budde err = mcp251xfd_check_tef_tail(priv); 139568c0c1c7SMarc Kleine-Budde if (err) 139668c0c1c7SMarc Kleine-Budde return err; 139768c0c1c7SMarc Kleine-Budde } 139868c0c1c7SMarc Kleine-Budde 1399eb79a267SMarc Kleine-Budde mcp251xfd_ecc_tefif_successful(priv); 14001f0e21a0SMarc Kleine-Budde 1401eb79a267SMarc Kleine-Budde if (mcp251xfd_get_tx_free(priv->tx)) { 14021f0e21a0SMarc Kleine-Budde /* Make sure that anybody stopping the queue after 14031f0e21a0SMarc Kleine-Budde * this sees the new tx_ring->tail. 14041f0e21a0SMarc Kleine-Budde */ 14051f0e21a0SMarc Kleine-Budde smp_mb(); 14061f0e21a0SMarc Kleine-Budde netif_wake_queue(priv->ndev); 14071f0e21a0SMarc Kleine-Budde } 14081f0e21a0SMarc Kleine-Budde 14091f0e21a0SMarc Kleine-Budde return 0; 14101f0e21a0SMarc Kleine-Budde } 14111f0e21a0SMarc Kleine-Budde 14121f0e21a0SMarc Kleine-Budde static int 1413eb79a267SMarc Kleine-Budde mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv, 1414eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring) 14151f0e21a0SMarc Kleine-Budde { 14161f0e21a0SMarc Kleine-Budde u32 new_head; 14171f0e21a0SMarc Kleine-Budde u8 chip_rx_head; 14181f0e21a0SMarc Kleine-Budde int err; 14191f0e21a0SMarc Kleine-Budde 1420eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head); 14211f0e21a0SMarc Kleine-Budde if (err) 14221f0e21a0SMarc Kleine-Budde return err; 14231f0e21a0SMarc Kleine-Budde 14241f0e21a0SMarc Kleine-Budde /* chip_rx_head, is the next RX-Object filled by the HW. 14251f0e21a0SMarc Kleine-Budde * The new RX head must be >= the old head. 14261f0e21a0SMarc Kleine-Budde */ 14271f0e21a0SMarc Kleine-Budde new_head = round_down(ring->head, ring->obj_num) + chip_rx_head; 14281f0e21a0SMarc Kleine-Budde if (new_head <= ring->head) 14291f0e21a0SMarc Kleine-Budde new_head += ring->obj_num; 14301f0e21a0SMarc Kleine-Budde 14311f0e21a0SMarc Kleine-Budde ring->head = new_head; 14321f0e21a0SMarc Kleine-Budde 1433eb79a267SMarc Kleine-Budde return mcp251xfd_check_rx_tail(priv, ring); 14341f0e21a0SMarc Kleine-Budde } 14351f0e21a0SMarc Kleine-Budde 14361f0e21a0SMarc Kleine-Budde static void 1437eb79a267SMarc Kleine-Budde mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv, 1438eb79a267SMarc Kleine-Budde const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj, 14391f0e21a0SMarc Kleine-Budde struct sk_buff *skb) 14401f0e21a0SMarc Kleine-Budde { 14411f0e21a0SMarc Kleine-Budde struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 14421f0e21a0SMarc Kleine-Budde 1443eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_IDE) { 14441f0e21a0SMarc Kleine-Budde u32 sid, eid; 14451f0e21a0SMarc Kleine-Budde 1446eb79a267SMarc Kleine-Budde eid = FIELD_GET(MCP251XFD_OBJ_ID_EID_MASK, hw_rx_obj->id); 1447eb79a267SMarc Kleine-Budde sid = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, hw_rx_obj->id); 14481f0e21a0SMarc Kleine-Budde 14491f0e21a0SMarc Kleine-Budde cfd->can_id = CAN_EFF_FLAG | 1450eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_FRAME_EFF_EID_MASK, eid) | 1451eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_FRAME_EFF_SID_MASK, sid); 14521f0e21a0SMarc Kleine-Budde } else { 1453eb79a267SMarc Kleine-Budde cfd->can_id = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, 14541f0e21a0SMarc Kleine-Budde hw_rx_obj->id); 14551f0e21a0SMarc Kleine-Budde } 14561f0e21a0SMarc Kleine-Budde 14571f0e21a0SMarc Kleine-Budde /* CANFD */ 1458eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) { 14591f0e21a0SMarc Kleine-Budde u8 dlc; 14601f0e21a0SMarc Kleine-Budde 1461eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_ESI) 14621f0e21a0SMarc Kleine-Budde cfd->flags |= CANFD_ESI; 14631f0e21a0SMarc Kleine-Budde 1464eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_BRS) 14651f0e21a0SMarc Kleine-Budde cfd->flags |= CANFD_BRS; 14661f0e21a0SMarc Kleine-Budde 1467eb79a267SMarc Kleine-Budde dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC, hw_rx_obj->flags); 14683ab4ce0dSOliver Hartkopp cfd->len = can_fd_dlc2len(dlc); 14691f0e21a0SMarc Kleine-Budde } else { 1470eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR) 14711f0e21a0SMarc Kleine-Budde cfd->can_id |= CAN_RTR_FLAG; 14721f0e21a0SMarc Kleine-Budde 147369d98969SOliver Hartkopp cfd->len = can_cc_dlc2len(FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC, 14741f0e21a0SMarc Kleine-Budde hw_rx_obj->flags)); 14751f0e21a0SMarc Kleine-Budde } 14761f0e21a0SMarc Kleine-Budde 1477*e20b85c7SMarc Kleine-Budde if (!(hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR)) 14781f0e21a0SMarc Kleine-Budde memcpy(cfd->data, hw_rx_obj->data, cfd->len); 14791f0e21a0SMarc Kleine-Budde } 14801f0e21a0SMarc Kleine-Budde 14811f0e21a0SMarc Kleine-Budde static int 1482eb79a267SMarc Kleine-Budde mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv, 1483eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring, 1484eb79a267SMarc Kleine-Budde const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj) 14851f0e21a0SMarc Kleine-Budde { 14861f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 14871f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 14881f0e21a0SMarc Kleine-Budde struct canfd_frame *cfd; 14891f0e21a0SMarc Kleine-Budde int err; 14901f0e21a0SMarc Kleine-Budde 1491eb79a267SMarc Kleine-Budde if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) 14921f0e21a0SMarc Kleine-Budde skb = alloc_canfd_skb(priv->ndev, &cfd); 14931f0e21a0SMarc Kleine-Budde else 14941f0e21a0SMarc Kleine-Budde skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cfd); 14951f0e21a0SMarc Kleine-Budde 1496ca4c6ebeSQinglang Miao if (!skb) { 14971f0e21a0SMarc Kleine-Budde stats->rx_dropped++; 14981f0e21a0SMarc Kleine-Budde return 0; 14991f0e21a0SMarc Kleine-Budde } 15001f0e21a0SMarc Kleine-Budde 1501eb79a267SMarc Kleine-Budde mcp251xfd_hw_rx_obj_to_skb(priv, hw_rx_obj, skb); 15021f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, hw_rx_obj->ts); 15031f0e21a0SMarc Kleine-Budde if (err) 15041f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 15051f0e21a0SMarc Kleine-Budde 15061f652bb6SUrsula Maplehurst return 0; 15071f0e21a0SMarc Kleine-Budde } 15081f0e21a0SMarc Kleine-Budde 15091f0e21a0SMarc Kleine-Budde static inline int 1510eb79a267SMarc Kleine-Budde mcp251xfd_rx_obj_read(const struct mcp251xfd_priv *priv, 1511eb79a267SMarc Kleine-Budde const struct mcp251xfd_rx_ring *ring, 1512eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj, 15131f0e21a0SMarc Kleine-Budde const u8 offset, const u8 len) 15141f0e21a0SMarc Kleine-Budde { 1515cdc4c698SSu Yanjun const int val_bytes = regmap_get_val_bytes(priv->map_rx); 15161f0e21a0SMarc Kleine-Budde int err; 15171f0e21a0SMarc Kleine-Budde 15181f0e21a0SMarc Kleine-Budde err = regmap_bulk_read(priv->map_rx, 1519eb79a267SMarc Kleine-Budde mcp251xfd_get_rx_obj_addr(ring, offset), 15201f0e21a0SMarc Kleine-Budde hw_rx_obj, 1521cdc4c698SSu Yanjun len * ring->obj_size / val_bytes); 15221f0e21a0SMarc Kleine-Budde 15231f0e21a0SMarc Kleine-Budde return err; 15241f0e21a0SMarc Kleine-Budde } 15251f0e21a0SMarc Kleine-Budde 15261f0e21a0SMarc Kleine-Budde static int 1527eb79a267SMarc Kleine-Budde mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv, 1528eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring) 15291f0e21a0SMarc Kleine-Budde { 1530eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj = ring->obj; 15311f0e21a0SMarc Kleine-Budde u8 rx_tail, len; 15321f0e21a0SMarc Kleine-Budde int err, i; 15331f0e21a0SMarc Kleine-Budde 1534eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_ring_update(priv, ring); 15351f0e21a0SMarc Kleine-Budde if (err) 15361f0e21a0SMarc Kleine-Budde return err; 15371f0e21a0SMarc Kleine-Budde 1538eb79a267SMarc Kleine-Budde while ((len = mcp251xfd_get_rx_linear_len(ring))) { 15391f652bb6SUrsula Maplehurst struct spi_transfer *last_xfer; 15401f652bb6SUrsula Maplehurst 1541eb79a267SMarc Kleine-Budde rx_tail = mcp251xfd_get_rx_tail(ring); 15421f0e21a0SMarc Kleine-Budde 1543eb79a267SMarc Kleine-Budde err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj, 15441f0e21a0SMarc Kleine-Budde rx_tail, len); 15451f0e21a0SMarc Kleine-Budde if (err) 15461f0e21a0SMarc Kleine-Budde return err; 15471f0e21a0SMarc Kleine-Budde 15481f0e21a0SMarc Kleine-Budde for (i = 0; i < len; i++) { 1549eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_rxif_one(priv, ring, 15501f0e21a0SMarc Kleine-Budde (void *)hw_rx_obj + 15511f0e21a0SMarc Kleine-Budde i * ring->obj_size); 15521f0e21a0SMarc Kleine-Budde if (err) 15531f0e21a0SMarc Kleine-Budde return err; 15541f0e21a0SMarc Kleine-Budde } 15551f652bb6SUrsula Maplehurst 15561f652bb6SUrsula Maplehurst /* Increment the RX FIFO tail pointer 'len' times in a 15571f652bb6SUrsula Maplehurst * single SPI message. 15582fbb397fSMarc Kleine-Budde * 15592fbb397fSMarc Kleine-Budde * Note: 15601f652bb6SUrsula Maplehurst * 15611f652bb6SUrsula Maplehurst * "cs_change == 1" on the last transfer results in an 15621f652bb6SUrsula Maplehurst * active chip select after the complete SPI 15631f652bb6SUrsula Maplehurst * message. This causes the controller to interpret 15641f652bb6SUrsula Maplehurst * the next register access as data. Temporary set 15651f652bb6SUrsula Maplehurst * "cs_change" of the last transfer to "0" to properly 15661f652bb6SUrsula Maplehurst * deactivate the chip select at the end of the 15671f652bb6SUrsula Maplehurst * message. 15681f652bb6SUrsula Maplehurst */ 15691f652bb6SUrsula Maplehurst last_xfer = &ring->uinc_xfer[len - 1]; 15701f652bb6SUrsula Maplehurst last_xfer->cs_change = 0; 15711f652bb6SUrsula Maplehurst err = spi_sync_transfer(priv->spi, ring->uinc_xfer, len); 15721f652bb6SUrsula Maplehurst last_xfer->cs_change = 1; 15731f652bb6SUrsula Maplehurst if (err) 15741f652bb6SUrsula Maplehurst return err; 15752fbb397fSMarc Kleine-Budde 15762fbb397fSMarc Kleine-Budde ring->tail += len; 15771f0e21a0SMarc Kleine-Budde } 15781f0e21a0SMarc Kleine-Budde 15791f0e21a0SMarc Kleine-Budde return 0; 15801f0e21a0SMarc Kleine-Budde } 15811f0e21a0SMarc Kleine-Budde 1582eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv) 15831f0e21a0SMarc Kleine-Budde { 1584eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring; 15851f0e21a0SMarc Kleine-Budde int err, n; 15861f0e21a0SMarc Kleine-Budde 1587eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, ring, n) { 1588eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_rxif_ring(priv, ring); 15891f0e21a0SMarc Kleine-Budde if (err) 15901f0e21a0SMarc Kleine-Budde return err; 15911f0e21a0SMarc Kleine-Budde } 15921f0e21a0SMarc Kleine-Budde 15931f0e21a0SMarc Kleine-Budde return 0; 15941f0e21a0SMarc Kleine-Budde } 15951f0e21a0SMarc Kleine-Budde 1596eb79a267SMarc Kleine-Budde static inline int mcp251xfd_get_timestamp(const struct mcp251xfd_priv *priv, 15971f0e21a0SMarc Kleine-Budde u32 *timestamp) 15981f0e21a0SMarc Kleine-Budde { 1599eb79a267SMarc Kleine-Budde return regmap_read(priv->map_reg, MCP251XFD_REG_TBC, timestamp); 16001f0e21a0SMarc Kleine-Budde } 16011f0e21a0SMarc Kleine-Budde 16021f0e21a0SMarc Kleine-Budde static struct sk_buff * 1603eb79a267SMarc Kleine-Budde mcp251xfd_alloc_can_err_skb(const struct mcp251xfd_priv *priv, 16041f0e21a0SMarc Kleine-Budde struct can_frame **cf, u32 *timestamp) 16051f0e21a0SMarc Kleine-Budde { 16061f0e21a0SMarc Kleine-Budde int err; 16071f0e21a0SMarc Kleine-Budde 1608eb79a267SMarc Kleine-Budde err = mcp251xfd_get_timestamp(priv, timestamp); 16091f0e21a0SMarc Kleine-Budde if (err) 16101f0e21a0SMarc Kleine-Budde return NULL; 16111f0e21a0SMarc Kleine-Budde 16121f0e21a0SMarc Kleine-Budde return alloc_can_err_skb(priv->ndev, cf); 16131f0e21a0SMarc Kleine-Budde } 16141f0e21a0SMarc Kleine-Budde 1615eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_rxovif(struct mcp251xfd_priv *priv) 16161f0e21a0SMarc Kleine-Budde { 16171f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 1618eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring; 16191f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 16201f0e21a0SMarc Kleine-Budde struct can_frame *cf; 16211f0e21a0SMarc Kleine-Budde u32 timestamp, rxovif; 16221f0e21a0SMarc Kleine-Budde int err, i; 16231f0e21a0SMarc Kleine-Budde 16241f0e21a0SMarc Kleine-Budde stats->rx_over_errors++; 16251f0e21a0SMarc Kleine-Budde stats->rx_errors++; 16261f0e21a0SMarc Kleine-Budde 1627eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_RXOVIF, &rxovif); 16281f0e21a0SMarc Kleine-Budde if (err) 16291f0e21a0SMarc Kleine-Budde return err; 16301f0e21a0SMarc Kleine-Budde 1631eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, ring, i) { 16321f0e21a0SMarc Kleine-Budde if (!(rxovif & BIT(ring->fifo_nr))) 16331f0e21a0SMarc Kleine-Budde continue; 16341f0e21a0SMarc Kleine-Budde 16351f0e21a0SMarc Kleine-Budde /* If SERRIF is active, there was a RX MAB overflow. */ 1636eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_SERRIF) { 16371f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 16381f0e21a0SMarc Kleine-Budde "RX-%d: MAB overflow detected.\n", 16391f0e21a0SMarc Kleine-Budde ring->nr); 16401f0e21a0SMarc Kleine-Budde } else { 16411f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 16421f0e21a0SMarc Kleine-Budde "RX-%d: FIFO overflow.\n", ring->nr); 16431f0e21a0SMarc Kleine-Budde } 16441f0e21a0SMarc Kleine-Budde 16451f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 1646eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA(ring->fifo_nr), 1647eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA_RXOVIF, 16481f0e21a0SMarc Kleine-Budde 0x0); 16491f0e21a0SMarc Kleine-Budde if (err) 16501f0e21a0SMarc Kleine-Budde return err; 16511f0e21a0SMarc Kleine-Budde } 16521f0e21a0SMarc Kleine-Budde 1653eb79a267SMarc Kleine-Budde skb = mcp251xfd_alloc_can_err_skb(priv, &cf, ×tamp); 16541f0e21a0SMarc Kleine-Budde if (!skb) 16551f0e21a0SMarc Kleine-Budde return 0; 16561f0e21a0SMarc Kleine-Budde 16571f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_CRTL; 16581f0e21a0SMarc Kleine-Budde cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; 16591f0e21a0SMarc Kleine-Budde 16601f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 16611f0e21a0SMarc Kleine-Budde if (err) 16621f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 16631f0e21a0SMarc Kleine-Budde 16641f0e21a0SMarc Kleine-Budde return 0; 16651f0e21a0SMarc Kleine-Budde } 16661f0e21a0SMarc Kleine-Budde 1667eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_txatif(struct mcp251xfd_priv *priv) 16681f0e21a0SMarc Kleine-Budde { 16691f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", __func__); 16701f0e21a0SMarc Kleine-Budde 16711f0e21a0SMarc Kleine-Budde return 0; 16721f0e21a0SMarc Kleine-Budde } 16731f0e21a0SMarc Kleine-Budde 1674eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_ivmif(struct mcp251xfd_priv *priv) 16751f0e21a0SMarc Kleine-Budde { 16761f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 16771f0e21a0SMarc Kleine-Budde u32 bdiag1, timestamp; 16781f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 16791f0e21a0SMarc Kleine-Budde struct can_frame *cf = NULL; 16801f0e21a0SMarc Kleine-Budde int err; 16811f0e21a0SMarc Kleine-Budde 1682eb79a267SMarc Kleine-Budde err = mcp251xfd_get_timestamp(priv, ×tamp); 16831f0e21a0SMarc Kleine-Budde if (err) 16841f0e21a0SMarc Kleine-Budde return err; 16851f0e21a0SMarc Kleine-Budde 1686eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_BDIAG1, &bdiag1); 16871f0e21a0SMarc Kleine-Budde if (err) 16881f0e21a0SMarc Kleine-Budde return err; 16891f0e21a0SMarc Kleine-Budde 16901f0e21a0SMarc Kleine-Budde /* Write 0s to clear error bits, don't write 1s to non active 16911f0e21a0SMarc Kleine-Budde * bits, as they will be set. 16921f0e21a0SMarc Kleine-Budde */ 1693eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_BDIAG1, 0x0); 16941f0e21a0SMarc Kleine-Budde if (err) 16951f0e21a0SMarc Kleine-Budde return err; 16961f0e21a0SMarc Kleine-Budde 16971f0e21a0SMarc Kleine-Budde priv->can.can_stats.bus_error++; 16981f0e21a0SMarc Kleine-Budde 16991f0e21a0SMarc Kleine-Budde skb = alloc_can_err_skb(priv->ndev, &cf); 17001f0e21a0SMarc Kleine-Budde if (cf) 17011f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; 17021f0e21a0SMarc Kleine-Budde 17031f0e21a0SMarc Kleine-Budde /* Controller misconfiguration */ 1704eb79a267SMarc Kleine-Budde if (WARN_ON(bdiag1 & MCP251XFD_REG_BDIAG1_DLCMM)) 17051f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 17061f0e21a0SMarc Kleine-Budde "recv'd DLC is larger than PLSIZE of FIFO element."); 17071f0e21a0SMarc Kleine-Budde 17081f0e21a0SMarc Kleine-Budde /* RX errors */ 1709eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DCRCERR | 1710eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NCRCERR)) { 17111f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "CRC error\n"); 17121f0e21a0SMarc Kleine-Budde 17131f0e21a0SMarc Kleine-Budde stats->rx_errors++; 17141f0e21a0SMarc Kleine-Budde if (cf) 17151f0e21a0SMarc Kleine-Budde cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; 17161f0e21a0SMarc Kleine-Budde } 1717eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DSTUFERR | 1718eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NSTUFERR)) { 17191f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Stuff error\n"); 17201f0e21a0SMarc Kleine-Budde 17211f0e21a0SMarc Kleine-Budde stats->rx_errors++; 17221f0e21a0SMarc Kleine-Budde if (cf) 17231f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_STUFF; 17241f0e21a0SMarc Kleine-Budde } 1725eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DFORMERR | 1726eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NFORMERR)) { 17271f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Format error\n"); 17281f0e21a0SMarc Kleine-Budde 17291f0e21a0SMarc Kleine-Budde stats->rx_errors++; 17301f0e21a0SMarc Kleine-Budde if (cf) 17311f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_FORM; 17321f0e21a0SMarc Kleine-Budde } 17331f0e21a0SMarc Kleine-Budde 17341f0e21a0SMarc Kleine-Budde /* TX errors */ 1735eb79a267SMarc Kleine-Budde if (bdiag1 & MCP251XFD_REG_BDIAG1_NACKERR) { 17361f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "NACK error\n"); 17371f0e21a0SMarc Kleine-Budde 17381f0e21a0SMarc Kleine-Budde stats->tx_errors++; 17391f0e21a0SMarc Kleine-Budde if (cf) { 17401f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_ACK; 17411f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX; 17421f0e21a0SMarc Kleine-Budde } 17431f0e21a0SMarc Kleine-Budde } 1744eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT1ERR | 1745eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NBIT1ERR)) { 17461f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit1 error\n"); 17471f0e21a0SMarc Kleine-Budde 17481f0e21a0SMarc Kleine-Budde stats->tx_errors++; 17491f0e21a0SMarc Kleine-Budde if (cf) 17501f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT1; 17511f0e21a0SMarc Kleine-Budde } 1752eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT0ERR | 1753eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NBIT0ERR)) { 17541f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit0 error\n"); 17551f0e21a0SMarc Kleine-Budde 17561f0e21a0SMarc Kleine-Budde stats->tx_errors++; 17571f0e21a0SMarc Kleine-Budde if (cf) 17581f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT0; 17591f0e21a0SMarc Kleine-Budde } 17601f0e21a0SMarc Kleine-Budde 17611f0e21a0SMarc Kleine-Budde if (!cf) 17621f0e21a0SMarc Kleine-Budde return 0; 17631f0e21a0SMarc Kleine-Budde 17641f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 17651f0e21a0SMarc Kleine-Budde if (err) 17661f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 17671f0e21a0SMarc Kleine-Budde 17681f0e21a0SMarc Kleine-Budde return 0; 17691f0e21a0SMarc Kleine-Budde } 17701f0e21a0SMarc Kleine-Budde 1771eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv) 17721f0e21a0SMarc Kleine-Budde { 17731f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 17741f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 17751f0e21a0SMarc Kleine-Budde struct can_frame *cf = NULL; 17761f0e21a0SMarc Kleine-Budde enum can_state new_state, rx_state, tx_state; 17771f0e21a0SMarc Kleine-Budde u32 trec, timestamp; 17781f0e21a0SMarc Kleine-Budde int err; 17791f0e21a0SMarc Kleine-Budde 1780eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec); 17811f0e21a0SMarc Kleine-Budde if (err) 17821f0e21a0SMarc Kleine-Budde return err; 17831f0e21a0SMarc Kleine-Budde 1784eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_TXBO) 17851f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_BUS_OFF; 1786eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_TXBP) 17871f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_PASSIVE; 1788eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_TXWARN) 17891f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_WARNING; 17901f0e21a0SMarc Kleine-Budde else 17911f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_ACTIVE; 17921f0e21a0SMarc Kleine-Budde 1793eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_RXBP) 17941f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_PASSIVE; 1795eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_RXWARN) 17961f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_WARNING; 17971f0e21a0SMarc Kleine-Budde else 17981f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_ACTIVE; 17991f0e21a0SMarc Kleine-Budde 18001f0e21a0SMarc Kleine-Budde new_state = max(tx_state, rx_state); 18011f0e21a0SMarc Kleine-Budde if (new_state == priv->can.state) 18021f0e21a0SMarc Kleine-Budde return 0; 18031f0e21a0SMarc Kleine-Budde 18041f0e21a0SMarc Kleine-Budde /* The skb allocation might fail, but can_change_state() 18051f0e21a0SMarc Kleine-Budde * handles cf == NULL. 18061f0e21a0SMarc Kleine-Budde */ 1807eb79a267SMarc Kleine-Budde skb = mcp251xfd_alloc_can_err_skb(priv, &cf, ×tamp); 18081f0e21a0SMarc Kleine-Budde can_change_state(priv->ndev, cf, tx_state, rx_state); 18091f0e21a0SMarc Kleine-Budde 18101f0e21a0SMarc Kleine-Budde if (new_state == CAN_STATE_BUS_OFF) { 18111f0e21a0SMarc Kleine-Budde /* As we're going to switch off the chip now, let's 18121f0e21a0SMarc Kleine-Budde * save the error counters and return them to 18131f0e21a0SMarc Kleine-Budde * userspace, if do_get_berr_counter() is called while 18141f0e21a0SMarc Kleine-Budde * the chip is in Bus Off. 18151f0e21a0SMarc Kleine-Budde */ 1816eb79a267SMarc Kleine-Budde err = __mcp251xfd_get_berr_counter(priv->ndev, &priv->bec); 18171f0e21a0SMarc Kleine-Budde if (err) 18181f0e21a0SMarc Kleine-Budde return err; 18191f0e21a0SMarc Kleine-Budde 1820eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_BUS_OFF); 18211f0e21a0SMarc Kleine-Budde can_bus_off(priv->ndev); 18221f0e21a0SMarc Kleine-Budde } 18231f0e21a0SMarc Kleine-Budde 18241f0e21a0SMarc Kleine-Budde if (!skb) 18251f0e21a0SMarc Kleine-Budde return 0; 18261f0e21a0SMarc Kleine-Budde 18271f0e21a0SMarc Kleine-Budde if (new_state != CAN_STATE_BUS_OFF) { 18281f0e21a0SMarc Kleine-Budde struct can_berr_counter bec; 18291f0e21a0SMarc Kleine-Budde 1830eb79a267SMarc Kleine-Budde err = mcp251xfd_get_berr_counter(priv->ndev, &bec); 18311f0e21a0SMarc Kleine-Budde if (err) 18321f0e21a0SMarc Kleine-Budde return err; 18331f0e21a0SMarc Kleine-Budde cf->data[6] = bec.txerr; 18341f0e21a0SMarc Kleine-Budde cf->data[7] = bec.rxerr; 18351f0e21a0SMarc Kleine-Budde } 18361f0e21a0SMarc Kleine-Budde 18371f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 18381f0e21a0SMarc Kleine-Budde if (err) 18391f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 18401f0e21a0SMarc Kleine-Budde 18411f0e21a0SMarc Kleine-Budde return 0; 18421f0e21a0SMarc Kleine-Budde } 18431f0e21a0SMarc Kleine-Budde 18441f0e21a0SMarc Kleine-Budde static int 1845eb79a267SMarc Kleine-Budde mcp251xfd_handle_modif(const struct mcp251xfd_priv *priv, bool *set_normal_mode) 18461f0e21a0SMarc Kleine-Budde { 1847eb79a267SMarc Kleine-Budde const u8 mode_reference = mcp251xfd_get_normal_mode(priv); 18481f0e21a0SMarc Kleine-Budde u8 mode; 18491f0e21a0SMarc Kleine-Budde int err; 18501f0e21a0SMarc Kleine-Budde 1851eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_get_mode(priv, &mode); 18521f0e21a0SMarc Kleine-Budde if (err) 18531f0e21a0SMarc Kleine-Budde return err; 18541f0e21a0SMarc Kleine-Budde 18551f0e21a0SMarc Kleine-Budde if (mode == mode_reference) { 18561f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 18571f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1858eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 18591f0e21a0SMarc Kleine-Budde return 0; 18601f0e21a0SMarc Kleine-Budde } 18611f0e21a0SMarc Kleine-Budde 18621f0e21a0SMarc Kleine-Budde /* According to MCP2517FD errata DS80000792B 1., during a TX 18631f0e21a0SMarc Kleine-Budde * MAB underflow, the controller will transition to Restricted 18641f0e21a0SMarc Kleine-Budde * Operation Mode or Listen Only Mode (depending on SERR2LOM). 18651f0e21a0SMarc Kleine-Budde * 18661f0e21a0SMarc Kleine-Budde * However this is not always the case. If SERR2LOM is 18671f0e21a0SMarc Kleine-Budde * configured for Restricted Operation Mode (SERR2LOM not set) 18681f0e21a0SMarc Kleine-Budde * the MCP2517FD will sometimes transition to Listen Only Mode 18691f0e21a0SMarc Kleine-Budde * first. When polling this bit we see that it will transition 18701f0e21a0SMarc Kleine-Budde * to Restricted Operation Mode shortly after. 18711f0e21a0SMarc Kleine-Budde */ 1872eb79a267SMarc Kleine-Budde if ((priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN) && 1873eb79a267SMarc Kleine-Budde (mode == MCP251XFD_REG_CON_MODE_RESTRICTED || 1874eb79a267SMarc Kleine-Budde mode == MCP251XFD_REG_CON_MODE_LISTENONLY)) 18751f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 18761f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1877eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 18781f0e21a0SMarc Kleine-Budde else 18791f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 18801f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1881eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 18821f0e21a0SMarc Kleine-Budde 18831f0e21a0SMarc Kleine-Budde /* After the application requests Normal mode, the Controller 18841f0e21a0SMarc Kleine-Budde * will automatically attempt to retransmit the message that 18851f0e21a0SMarc Kleine-Budde * caused the TX MAB underflow. 18861f0e21a0SMarc Kleine-Budde * 18871f0e21a0SMarc Kleine-Budde * However, if there is an ECC error in the TX-RAM, we first 18881f0e21a0SMarc Kleine-Budde * have to reload the tx-object before requesting Normal 1889eb79a267SMarc Kleine-Budde * mode. This is done later in mcp251xfd_handle_eccif(). 18901f0e21a0SMarc Kleine-Budde */ 1891eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF) { 18921f0e21a0SMarc Kleine-Budde *set_normal_mode = true; 18931f0e21a0SMarc Kleine-Budde return 0; 18941f0e21a0SMarc Kleine-Budde } 18951f0e21a0SMarc Kleine-Budde 1896eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode_nowait(priv); 18971f0e21a0SMarc Kleine-Budde } 18981f0e21a0SMarc Kleine-Budde 1899eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_serrif(struct mcp251xfd_priv *priv) 19001f0e21a0SMarc Kleine-Budde { 1901eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 19021f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 19031f0e21a0SMarc Kleine-Budde bool handled = false; 19041f0e21a0SMarc Kleine-Budde 19051f0e21a0SMarc Kleine-Budde /* TX MAB underflow 19061f0e21a0SMarc Kleine-Budde * 19071f0e21a0SMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a TX MAB 19081f0e21a0SMarc Kleine-Budde * underflow is indicated by SERRIF and MODIF. 19091f0e21a0SMarc Kleine-Budde * 19101f0e21a0SMarc Kleine-Budde * In addition to the effects mentioned in the Errata, there 19111f0e21a0SMarc Kleine-Budde * are Bus Errors due to the aborted CAN frame, so a IVMIF 19121f0e21a0SMarc Kleine-Budde * will be seen as well. 19131f0e21a0SMarc Kleine-Budde * 19141f0e21a0SMarc Kleine-Budde * Sometimes there is an ECC error in the TX-RAM, which leads 19151f0e21a0SMarc Kleine-Budde * to a TX MAB underflow. 19161f0e21a0SMarc Kleine-Budde * 19171f0e21a0SMarc Kleine-Budde * However, probably due to a race condition, there is no 19181f0e21a0SMarc Kleine-Budde * associated MODIF pending. 19191f0e21a0SMarc Kleine-Budde * 19201f0e21a0SMarc Kleine-Budde * Further, there are situations, where the SERRIF is caused 19211f0e21a0SMarc Kleine-Budde * by an ECC error in the TX-RAM, but not even the ECCIF is 19221f0e21a0SMarc Kleine-Budde * set. This only seems to happen _after_ the first occurrence 19231f0e21a0SMarc Kleine-Budde * of a ECCIF (which is tracked in ecc->cnt). 19241f0e21a0SMarc Kleine-Budde * 19251f0e21a0SMarc Kleine-Budde * Treat all as a known system errors.. 19261f0e21a0SMarc Kleine-Budde */ 1927eb79a267SMarc Kleine-Budde if ((priv->regs_status.intf & MCP251XFD_REG_INT_MODIF && 1928eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_IVMIF) || 1929eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF || 19301f0e21a0SMarc Kleine-Budde ecc->cnt) { 19311f0e21a0SMarc Kleine-Budde const char *msg; 19321f0e21a0SMarc Kleine-Budde 1933eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF || 19341f0e21a0SMarc Kleine-Budde ecc->cnt) 19351f0e21a0SMarc Kleine-Budde msg = "TX MAB underflow due to ECC error detected."; 19361f0e21a0SMarc Kleine-Budde else 19371f0e21a0SMarc Kleine-Budde msg = "TX MAB underflow detected."; 19381f0e21a0SMarc Kleine-Budde 1939eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN) 19401f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "%s\n", msg); 19411f0e21a0SMarc Kleine-Budde else 19421f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", msg); 19431f0e21a0SMarc Kleine-Budde 19441f0e21a0SMarc Kleine-Budde stats->tx_aborted_errors++; 19451f0e21a0SMarc Kleine-Budde stats->tx_errors++; 19461f0e21a0SMarc Kleine-Budde handled = true; 19471f0e21a0SMarc Kleine-Budde } 19481f0e21a0SMarc Kleine-Budde 19491f0e21a0SMarc Kleine-Budde /* RX MAB overflow 19501f0e21a0SMarc Kleine-Budde * 19511f0e21a0SMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a RX MAB 19521f0e21a0SMarc Kleine-Budde * overflow is indicated by SERRIF. 19531f0e21a0SMarc Kleine-Budde * 19541f0e21a0SMarc Kleine-Budde * In addition to the effects mentioned in the Errata, (most 19551f0e21a0SMarc Kleine-Budde * of the times) a RXOVIF is raised, if the FIFO that is being 19561f0e21a0SMarc Kleine-Budde * received into has the RXOVIE activated (and we have enabled 19571f0e21a0SMarc Kleine-Budde * RXOVIE on all FIFOs). 19581f0e21a0SMarc Kleine-Budde * 19591f0e21a0SMarc Kleine-Budde * Sometimes there is no RXOVIF just a RXIF is pending. 19601f0e21a0SMarc Kleine-Budde * 19611f0e21a0SMarc Kleine-Budde * Treat all as a known system errors.. 19621f0e21a0SMarc Kleine-Budde */ 1963eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_RXOVIF || 1964eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_RXIF) { 19651f0e21a0SMarc Kleine-Budde stats->rx_dropped++; 19661f0e21a0SMarc Kleine-Budde handled = true; 19671f0e21a0SMarc Kleine-Budde } 19681f0e21a0SMarc Kleine-Budde 19691f0e21a0SMarc Kleine-Budde if (!handled) 19701f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 19711f0e21a0SMarc Kleine-Budde "Unhandled System Error Interrupt (intf=0x%08x)!\n", 19721f0e21a0SMarc Kleine-Budde priv->regs_status.intf); 19731f0e21a0SMarc Kleine-Budde 19741f0e21a0SMarc Kleine-Budde return 0; 19751f0e21a0SMarc Kleine-Budde } 19761f0e21a0SMarc Kleine-Budde 19771f0e21a0SMarc Kleine-Budde static int 1978eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif_recover(struct mcp251xfd_priv *priv, u8 nr) 19791f0e21a0SMarc Kleine-Budde { 1980eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 1981eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 1982eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 19831f0e21a0SMarc Kleine-Budde u8 chip_tx_tail, tx_tail, offset; 19841f0e21a0SMarc Kleine-Budde u16 addr; 19851f0e21a0SMarc Kleine-Budde int err; 19861f0e21a0SMarc Kleine-Budde 1987eb79a267SMarc Kleine-Budde addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc->ecc_stat); 19881f0e21a0SMarc Kleine-Budde 1989eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail); 19901f0e21a0SMarc Kleine-Budde if (err) 19911f0e21a0SMarc Kleine-Budde return err; 19921f0e21a0SMarc Kleine-Budde 1993eb79a267SMarc Kleine-Budde tx_tail = mcp251xfd_get_tx_tail(tx_ring); 19941f0e21a0SMarc Kleine-Budde offset = (nr - chip_tx_tail) & (tx_ring->obj_num - 1); 19951f0e21a0SMarc Kleine-Budde 19961f0e21a0SMarc Kleine-Budde /* Bail out if one of the following is met: 19971f0e21a0SMarc Kleine-Budde * - tx_tail information is inconsistent 19981f0e21a0SMarc Kleine-Budde * - for mcp2517fd: offset not 0 19991f0e21a0SMarc Kleine-Budde * - for mcp2518fd: offset not 0 or 1 20001f0e21a0SMarc Kleine-Budde */ 20011f0e21a0SMarc Kleine-Budde if (chip_tx_tail != tx_tail || 2002eb79a267SMarc Kleine-Budde !(offset == 0 || (offset == 1 && mcp251xfd_is_2518(priv)))) { 20031f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 20041f0e21a0SMarc Kleine-Budde "ECC Error information inconsistent (addr=0x%04x, nr=%d, tx_tail=0x%08x(%d), chip_tx_tail=%d, offset=%d).\n", 20051f0e21a0SMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, chip_tx_tail, 20061f0e21a0SMarc Kleine-Budde offset); 20071f0e21a0SMarc Kleine-Budde return -EINVAL; 20081f0e21a0SMarc Kleine-Budde } 20091f0e21a0SMarc Kleine-Budde 20101f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 20111f0e21a0SMarc Kleine-Budde "Recovering %s ECC Error at address 0x%04x (in TX-RAM, tx_obj=%d, tx_tail=0x%08x(%d), offset=%d).\n", 2012eb79a267SMarc Kleine-Budde ecc->ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF ? 20131f0e21a0SMarc Kleine-Budde "Single" : "Double", 20141f0e21a0SMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, offset); 20151f0e21a0SMarc Kleine-Budde 20161f0e21a0SMarc Kleine-Budde /* reload tx_obj into controller RAM ... */ 20171f0e21a0SMarc Kleine-Budde tx_obj = &tx_ring->obj[nr]; 20181f0e21a0SMarc Kleine-Budde err = spi_sync_transfer(priv->spi, tx_obj->xfer, 1); 20191f0e21a0SMarc Kleine-Budde if (err) 20201f0e21a0SMarc Kleine-Budde return err; 20211f0e21a0SMarc Kleine-Budde 20221f0e21a0SMarc Kleine-Budde /* ... and trigger retransmit */ 2023eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode(priv); 20241f0e21a0SMarc Kleine-Budde } 20251f0e21a0SMarc Kleine-Budde 20261f0e21a0SMarc Kleine-Budde static int 2027eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif(struct mcp251xfd_priv *priv, bool set_normal_mode) 20281f0e21a0SMarc Kleine-Budde { 2029eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 20301f0e21a0SMarc Kleine-Budde const char *msg; 20311f0e21a0SMarc Kleine-Budde bool in_tx_ram; 20321f0e21a0SMarc Kleine-Budde u32 ecc_stat; 20331f0e21a0SMarc Kleine-Budde u16 addr; 20341f0e21a0SMarc Kleine-Budde u8 nr; 20351f0e21a0SMarc Kleine-Budde int err; 20361f0e21a0SMarc Kleine-Budde 2037eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_ECCSTAT, &ecc_stat); 20381f0e21a0SMarc Kleine-Budde if (err) 20391f0e21a0SMarc Kleine-Budde return err; 20401f0e21a0SMarc Kleine-Budde 2041eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCSTAT, 2042eb79a267SMarc Kleine-Budde MCP251XFD_REG_ECCSTAT_IF_MASK, ~ecc_stat); 20431f0e21a0SMarc Kleine-Budde if (err) 20441f0e21a0SMarc Kleine-Budde return err; 20451f0e21a0SMarc Kleine-Budde 20461f0e21a0SMarc Kleine-Budde /* Check if ECC error occurred in TX-RAM */ 2047eb79a267SMarc Kleine-Budde addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc_stat); 2048eb79a267SMarc Kleine-Budde err = mcp251xfd_get_tx_nr_by_addr(priv->tx, &nr, addr); 20491f0e21a0SMarc Kleine-Budde if (!err) 20501f0e21a0SMarc Kleine-Budde in_tx_ram = true; 20511f0e21a0SMarc Kleine-Budde else if (err == -ENOENT) 20521f0e21a0SMarc Kleine-Budde in_tx_ram = false; 20531f0e21a0SMarc Kleine-Budde else 20541f0e21a0SMarc Kleine-Budde return err; 20551f0e21a0SMarc Kleine-Budde 20561f0e21a0SMarc Kleine-Budde /* Errata Reference: 20571f0e21a0SMarc Kleine-Budde * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 2. 20581f0e21a0SMarc Kleine-Budde * 20591f0e21a0SMarc Kleine-Budde * ECC single error correction does not work in all cases: 20601f0e21a0SMarc Kleine-Budde * 20611f0e21a0SMarc Kleine-Budde * Fix/Work Around: 20621f0e21a0SMarc Kleine-Budde * Enable single error correction and double error detection 20631f0e21a0SMarc Kleine-Budde * interrupts by setting SECIE and DEDIE. Handle SECIF as a 20641f0e21a0SMarc Kleine-Budde * detection interrupt and do not rely on the error 20651f0e21a0SMarc Kleine-Budde * correction. Instead, handle both interrupts as a 20661f0e21a0SMarc Kleine-Budde * notification that the RAM word at ERRADDR was corrupted. 20671f0e21a0SMarc Kleine-Budde */ 2068eb79a267SMarc Kleine-Budde if (ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF) 20691f0e21a0SMarc Kleine-Budde msg = "Single ECC Error detected at address"; 2070eb79a267SMarc Kleine-Budde else if (ecc_stat & MCP251XFD_REG_ECCSTAT_DEDIF) 20711f0e21a0SMarc Kleine-Budde msg = "Double ECC Error detected at address"; 20721f0e21a0SMarc Kleine-Budde else 20731f0e21a0SMarc Kleine-Budde return -EINVAL; 20741f0e21a0SMarc Kleine-Budde 20751f0e21a0SMarc Kleine-Budde if (!in_tx_ram) { 20761f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 20771f0e21a0SMarc Kleine-Budde 20781f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, "%s 0x%04x.\n", msg, addr); 20791f0e21a0SMarc Kleine-Budde } else { 20801f0e21a0SMarc Kleine-Budde /* Re-occurring error? */ 20811f0e21a0SMarc Kleine-Budde if (ecc->ecc_stat == ecc_stat) { 20821f0e21a0SMarc Kleine-Budde ecc->cnt++; 20831f0e21a0SMarc Kleine-Budde } else { 20841f0e21a0SMarc Kleine-Budde ecc->ecc_stat = ecc_stat; 20851f0e21a0SMarc Kleine-Budde ecc->cnt = 1; 20861f0e21a0SMarc Kleine-Budde } 20871f0e21a0SMarc Kleine-Budde 20881f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 20891f0e21a0SMarc Kleine-Budde "%s 0x%04x (in TX-RAM, tx_obj=%d), occurred %d time%s.\n", 20901f0e21a0SMarc Kleine-Budde msg, addr, nr, ecc->cnt, ecc->cnt > 1 ? "s" : ""); 20911f0e21a0SMarc Kleine-Budde 2092eb79a267SMarc Kleine-Budde if (ecc->cnt >= MCP251XFD_ECC_CNT_MAX) 2093eb79a267SMarc Kleine-Budde return mcp251xfd_handle_eccif_recover(priv, nr); 20941f0e21a0SMarc Kleine-Budde } 20951f0e21a0SMarc Kleine-Budde 20961f0e21a0SMarc Kleine-Budde if (set_normal_mode) 2097eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode_nowait(priv); 20981f0e21a0SMarc Kleine-Budde 20991f0e21a0SMarc Kleine-Budde return 0; 21001f0e21a0SMarc Kleine-Budde } 21011f0e21a0SMarc Kleine-Budde 2102eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_spicrcif(struct mcp251xfd_priv *priv) 21031f0e21a0SMarc Kleine-Budde { 21041f0e21a0SMarc Kleine-Budde int err; 21051f0e21a0SMarc Kleine-Budde u32 crc; 21061f0e21a0SMarc Kleine-Budde 2107eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_CRC, &crc); 21081f0e21a0SMarc Kleine-Budde if (err) 21091f0e21a0SMarc Kleine-Budde return err; 21101f0e21a0SMarc Kleine-Budde 2111eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CRC, 2112eb79a267SMarc Kleine-Budde MCP251XFD_REG_CRC_IF_MASK, 21131f0e21a0SMarc Kleine-Budde ~crc); 21141f0e21a0SMarc Kleine-Budde if (err) 21151f0e21a0SMarc Kleine-Budde return err; 21161f0e21a0SMarc Kleine-Budde 2117eb79a267SMarc Kleine-Budde if (crc & MCP251XFD_REG_CRC_FERRIF) 21181f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, "CRC write command format error.\n"); 2119eb79a267SMarc Kleine-Budde else if (crc & MCP251XFD_REG_CRC_CRCERRIF) 21201f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, 21211f0e21a0SMarc Kleine-Budde "CRC write error detected. CRC=0x%04lx.\n", 2122eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_CRC_MASK, crc)); 21231f0e21a0SMarc Kleine-Budde 21241f0e21a0SMarc Kleine-Budde return 0; 21251f0e21a0SMarc Kleine-Budde } 21261f0e21a0SMarc Kleine-Budde 2127eb79a267SMarc Kleine-Budde #define mcp251xfd_handle(priv, irq, ...) \ 21281f0e21a0SMarc Kleine-Budde ({ \ 2129eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *_priv = (priv); \ 21301f0e21a0SMarc Kleine-Budde int err; \ 21311f0e21a0SMarc Kleine-Budde \ 2132eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_##irq(_priv, ## __VA_ARGS__); \ 21331f0e21a0SMarc Kleine-Budde if (err) \ 21341f0e21a0SMarc Kleine-Budde netdev_err(_priv->ndev, \ 2135eb79a267SMarc Kleine-Budde "IRQ handler mcp251xfd_handle_%s() returned %d.\n", \ 21361f0e21a0SMarc Kleine-Budde __stringify(irq), err); \ 21371f0e21a0SMarc Kleine-Budde err; \ 21381f0e21a0SMarc Kleine-Budde }) 21391f0e21a0SMarc Kleine-Budde 2140eb79a267SMarc Kleine-Budde static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) 21411f0e21a0SMarc Kleine-Budde { 2142eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = dev_id; 2143cdc4c698SSu Yanjun const int val_bytes = regmap_get_val_bytes(priv->map_reg); 21441f0e21a0SMarc Kleine-Budde irqreturn_t handled = IRQ_NONE; 21451f0e21a0SMarc Kleine-Budde int err; 21461f0e21a0SMarc Kleine-Budde 21471f0e21a0SMarc Kleine-Budde if (priv->rx_int) 21481f0e21a0SMarc Kleine-Budde do { 21491f0e21a0SMarc Kleine-Budde int rx_pending; 21501f0e21a0SMarc Kleine-Budde 21511f0e21a0SMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 21521f0e21a0SMarc Kleine-Budde if (!rx_pending) 21531f0e21a0SMarc Kleine-Budde break; 21541f0e21a0SMarc Kleine-Budde 2155eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxif); 21561f0e21a0SMarc Kleine-Budde if (err) 21571f0e21a0SMarc Kleine-Budde goto out_fail; 21581f0e21a0SMarc Kleine-Budde 21591f0e21a0SMarc Kleine-Budde handled = IRQ_HANDLED; 21601f0e21a0SMarc Kleine-Budde } while (1); 21611f0e21a0SMarc Kleine-Budde 21621f0e21a0SMarc Kleine-Budde do { 21631f0e21a0SMarc Kleine-Budde u32 intf_pending, intf_pending_clearable; 21641f0e21a0SMarc Kleine-Budde bool set_normal_mode = false; 21651f0e21a0SMarc Kleine-Budde 2166eb79a267SMarc Kleine-Budde err = regmap_bulk_read(priv->map_reg, MCP251XFD_REG_INT, 21671f0e21a0SMarc Kleine-Budde &priv->regs_status, 21681f0e21a0SMarc Kleine-Budde sizeof(priv->regs_status) / 2169cdc4c698SSu Yanjun val_bytes); 21701f0e21a0SMarc Kleine-Budde if (err) 21711f0e21a0SMarc Kleine-Budde goto out_fail; 21721f0e21a0SMarc Kleine-Budde 2173eb79a267SMarc Kleine-Budde intf_pending = FIELD_GET(MCP251XFD_REG_INT_IF_MASK, 21741f0e21a0SMarc Kleine-Budde priv->regs_status.intf) & 2175eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_INT_IE_MASK, 21761f0e21a0SMarc Kleine-Budde priv->regs_status.intf); 21771f0e21a0SMarc Kleine-Budde 21781f0e21a0SMarc Kleine-Budde if (!(intf_pending)) 21791f0e21a0SMarc Kleine-Budde return handled; 21801f0e21a0SMarc Kleine-Budde 21811f0e21a0SMarc Kleine-Budde /* Some interrupts must be ACKed in the 2182eb79a267SMarc Kleine-Budde * MCP251XFD_REG_INT register. 21831f0e21a0SMarc Kleine-Budde * - First ACK then handle, to avoid lost-IRQ race 21841f0e21a0SMarc Kleine-Budde * condition on fast re-occurring interrupts. 21851f0e21a0SMarc Kleine-Budde * - Write "0" to clear active IRQs, "1" to all other, 21861f0e21a0SMarc Kleine-Budde * to avoid r/m/w race condition on the 2187eb79a267SMarc Kleine-Budde * MCP251XFD_REG_INT register. 21881f0e21a0SMarc Kleine-Budde */ 21891f0e21a0SMarc Kleine-Budde intf_pending_clearable = intf_pending & 2190eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_IF_CLEARABLE_MASK; 21911f0e21a0SMarc Kleine-Budde if (intf_pending_clearable) { 21921f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 2193eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT, 2194eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_IF_MASK, 21951f0e21a0SMarc Kleine-Budde ~intf_pending_clearable); 21961f0e21a0SMarc Kleine-Budde if (err) 21971f0e21a0SMarc Kleine-Budde goto out_fail; 21981f0e21a0SMarc Kleine-Budde } 21991f0e21a0SMarc Kleine-Budde 2200eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_MODIF) { 2201eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, modif, &set_normal_mode); 22021f0e21a0SMarc Kleine-Budde if (err) 22031f0e21a0SMarc Kleine-Budde goto out_fail; 22041f0e21a0SMarc Kleine-Budde } 22051f0e21a0SMarc Kleine-Budde 2206eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_RXIF) { 2207eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxif); 22081f0e21a0SMarc Kleine-Budde if (err) 22091f0e21a0SMarc Kleine-Budde goto out_fail; 22101f0e21a0SMarc Kleine-Budde } 22111f0e21a0SMarc Kleine-Budde 2212eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_TEFIF) { 2213eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, tefif); 22141f0e21a0SMarc Kleine-Budde if (err) 22151f0e21a0SMarc Kleine-Budde goto out_fail; 22161f0e21a0SMarc Kleine-Budde } 22171f0e21a0SMarc Kleine-Budde 2218eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_RXOVIF) { 2219eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxovif); 22201f0e21a0SMarc Kleine-Budde if (err) 22211f0e21a0SMarc Kleine-Budde goto out_fail; 22221f0e21a0SMarc Kleine-Budde } 22231f0e21a0SMarc Kleine-Budde 2224eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_TXATIF) { 2225eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, txatif); 22261f0e21a0SMarc Kleine-Budde if (err) 22271f0e21a0SMarc Kleine-Budde goto out_fail; 22281f0e21a0SMarc Kleine-Budde } 22291f0e21a0SMarc Kleine-Budde 2230eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_IVMIF) { 2231eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, ivmif); 22321f0e21a0SMarc Kleine-Budde if (err) 22331f0e21a0SMarc Kleine-Budde goto out_fail; 22341f0e21a0SMarc Kleine-Budde } 22351f0e21a0SMarc Kleine-Budde 2236eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_SERRIF) { 2237eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, serrif); 22381f0e21a0SMarc Kleine-Budde if (err) 22391f0e21a0SMarc Kleine-Budde goto out_fail; 22401f0e21a0SMarc Kleine-Budde } 22411f0e21a0SMarc Kleine-Budde 2242eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_ECCIF) { 2243eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, eccif, set_normal_mode); 22441f0e21a0SMarc Kleine-Budde if (err) 22451f0e21a0SMarc Kleine-Budde goto out_fail; 22461f0e21a0SMarc Kleine-Budde } 22471f0e21a0SMarc Kleine-Budde 2248eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_SPICRCIF) { 2249eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, spicrcif); 22501f0e21a0SMarc Kleine-Budde if (err) 22511f0e21a0SMarc Kleine-Budde goto out_fail; 22521f0e21a0SMarc Kleine-Budde } 22531f0e21a0SMarc Kleine-Budde 22541f0e21a0SMarc Kleine-Budde /* On the MCP2527FD and MCP2518FD, we don't get a 22551f0e21a0SMarc Kleine-Budde * CERRIF IRQ on the transition TX ERROR_WARNING -> TX 22561f0e21a0SMarc Kleine-Budde * ERROR_ACTIVE. 22571f0e21a0SMarc Kleine-Budde */ 2258eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_CERRIF || 22591f0e21a0SMarc Kleine-Budde priv->can.state > CAN_STATE_ERROR_ACTIVE) { 2260eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, cerrif); 22611f0e21a0SMarc Kleine-Budde if (err) 22621f0e21a0SMarc Kleine-Budde goto out_fail; 22631f0e21a0SMarc Kleine-Budde 22641f0e21a0SMarc Kleine-Budde /* In Bus Off we completely shut down the 22651f0e21a0SMarc Kleine-Budde * controller. Every subsequent register read 22661f0e21a0SMarc Kleine-Budde * will read bogus data, and if 2267eb79a267SMarc Kleine-Budde * MCP251XFD_QUIRK_CRC_REG is enabled the CRC 22681f0e21a0SMarc Kleine-Budde * check will fail, too. So leave IRQ handler 22691f0e21a0SMarc Kleine-Budde * directly. 22701f0e21a0SMarc Kleine-Budde */ 22711f0e21a0SMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) 22721f0e21a0SMarc Kleine-Budde return IRQ_HANDLED; 22731f0e21a0SMarc Kleine-Budde } 22741f0e21a0SMarc Kleine-Budde 22751f0e21a0SMarc Kleine-Budde handled = IRQ_HANDLED; 22761f0e21a0SMarc Kleine-Budde } while (1); 22771f0e21a0SMarc Kleine-Budde 22781f0e21a0SMarc Kleine-Budde out_fail: 22791f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n", 22801f0e21a0SMarc Kleine-Budde err, priv->regs_status.intf); 2281eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 22821f0e21a0SMarc Kleine-Budde 22831f0e21a0SMarc Kleine-Budde return handled; 22841f0e21a0SMarc Kleine-Budde } 22851f0e21a0SMarc Kleine-Budde 22861f0e21a0SMarc Kleine-Budde static inline struct 2287eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj *mcp251xfd_get_tx_obj_next(struct mcp251xfd_tx_ring *tx_ring) 22881f0e21a0SMarc Kleine-Budde { 22891f0e21a0SMarc Kleine-Budde u8 tx_head; 22901f0e21a0SMarc Kleine-Budde 2291eb79a267SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 22921f0e21a0SMarc Kleine-Budde 22931f0e21a0SMarc Kleine-Budde return &tx_ring->obj[tx_head]; 22941f0e21a0SMarc Kleine-Budde } 22951f0e21a0SMarc Kleine-Budde 22961f0e21a0SMarc Kleine-Budde static void 2297eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv, 2298eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj, 22991f0e21a0SMarc Kleine-Budde const struct sk_buff *skb, 23001f0e21a0SMarc Kleine-Budde unsigned int seq) 23011f0e21a0SMarc Kleine-Budde { 23021f0e21a0SMarc Kleine-Budde const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 2303eb79a267SMarc Kleine-Budde struct mcp251xfd_hw_tx_obj_raw *hw_tx_obj; 2304eb79a267SMarc Kleine-Budde union mcp251xfd_tx_obj_load_buf *load_buf; 23051f0e21a0SMarc Kleine-Budde u8 dlc; 23061f0e21a0SMarc Kleine-Budde u32 id, flags; 2307561aa5b4SMarc Kleine-Budde int pad_len, len; 23081f0e21a0SMarc Kleine-Budde 23091f0e21a0SMarc Kleine-Budde if (cfd->can_id & CAN_EFF_FLAG) { 23101f0e21a0SMarc Kleine-Budde u32 sid, eid; 23111f0e21a0SMarc Kleine-Budde 2312eb79a267SMarc Kleine-Budde sid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_SID_MASK, cfd->can_id); 2313eb79a267SMarc Kleine-Budde eid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_EID_MASK, cfd->can_id); 23141f0e21a0SMarc Kleine-Budde 2315eb79a267SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_EID_MASK, eid) | 2316eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, sid); 23171f0e21a0SMarc Kleine-Budde 2318eb79a267SMarc Kleine-Budde flags = MCP251XFD_OBJ_FLAGS_IDE; 23191f0e21a0SMarc Kleine-Budde } else { 2320eb79a267SMarc Kleine-Budde id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, cfd->can_id); 23211f0e21a0SMarc Kleine-Budde flags = 0; 23221f0e21a0SMarc Kleine-Budde } 23231f0e21a0SMarc Kleine-Budde 23241f0e21a0SMarc Kleine-Budde /* Use the MCP2518FD mask even on the MCP2517FD. It doesn't 23251f0e21a0SMarc Kleine-Budde * harm, only the lower 7 bits will be transferred into the 23261f0e21a0SMarc Kleine-Budde * TEF object. 23271f0e21a0SMarc Kleine-Budde */ 23283ab4ce0dSOliver Hartkopp dlc = can_fd_len2dlc(cfd->len); 2329eb79a267SMarc Kleine-Budde flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq) | 2330eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC, dlc); 23311f0e21a0SMarc Kleine-Budde 23321f0e21a0SMarc Kleine-Budde if (cfd->can_id & CAN_RTR_FLAG) 2333eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_RTR; 23341f0e21a0SMarc Kleine-Budde 23351f0e21a0SMarc Kleine-Budde /* CANFD */ 23361f0e21a0SMarc Kleine-Budde if (can_is_canfd_skb(skb)) { 23371f0e21a0SMarc Kleine-Budde if (cfd->flags & CANFD_ESI) 2338eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_ESI; 23391f0e21a0SMarc Kleine-Budde 2340eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_FDF; 23411f0e21a0SMarc Kleine-Budde 23421f0e21a0SMarc Kleine-Budde if (cfd->flags & CANFD_BRS) 2343eb79a267SMarc Kleine-Budde flags |= MCP251XFD_OBJ_FLAGS_BRS; 23441f0e21a0SMarc Kleine-Budde } 23451f0e21a0SMarc Kleine-Budde 23461f0e21a0SMarc Kleine-Budde load_buf = &tx_obj->buf; 2347eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) 23481f0e21a0SMarc Kleine-Budde hw_tx_obj = &load_buf->crc.hw_tx_obj; 23491f0e21a0SMarc Kleine-Budde else 23501f0e21a0SMarc Kleine-Budde hw_tx_obj = &load_buf->nocrc.hw_tx_obj; 23511f0e21a0SMarc Kleine-Budde 23521f0e21a0SMarc Kleine-Budde put_unaligned_le32(id, &hw_tx_obj->id); 23531f0e21a0SMarc Kleine-Budde put_unaligned_le32(flags, &hw_tx_obj->flags); 23541f0e21a0SMarc Kleine-Budde 2355561aa5b4SMarc Kleine-Budde /* Copy data */ 23561f0e21a0SMarc Kleine-Budde memcpy(hw_tx_obj->data, cfd->data, cfd->len); 23571f0e21a0SMarc Kleine-Budde 2358561aa5b4SMarc Kleine-Budde /* Clear unused data at end of CAN frame */ 2359561aa5b4SMarc Kleine-Budde pad_len = can_fd_dlc2len(dlc) - cfd->len; 2360561aa5b4SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN && pad_len) 2361561aa5b4SMarc Kleine-Budde memset(hw_tx_obj->data + cfd->len, 0x0, pad_len); 2362561aa5b4SMarc Kleine-Budde 23631f0e21a0SMarc Kleine-Budde /* Number of bytes to be written into the RAM of the controller */ 23641f0e21a0SMarc Kleine-Budde len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags); 2365eb79a267SMarc Kleine-Budde if (MCP251XFD_SANITIZE_CAN) 23663ab4ce0dSOliver Hartkopp len += round_up(can_fd_dlc2len(dlc), sizeof(u32)); 23671f0e21a0SMarc Kleine-Budde else 23681f0e21a0SMarc Kleine-Budde len += round_up(cfd->len, sizeof(u32)); 23691f0e21a0SMarc Kleine-Budde 2370eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) { 23711f0e21a0SMarc Kleine-Budde u16 crc; 23721f0e21a0SMarc Kleine-Budde 2373eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_crc_set_len_in_ram(&load_buf->crc.cmd, 23741f0e21a0SMarc Kleine-Budde len); 23751f0e21a0SMarc Kleine-Budde /* CRC */ 23761f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->crc.cmd); 2377eb79a267SMarc Kleine-Budde crc = mcp251xfd_crc16_compute(&load_buf->crc, len); 23781f0e21a0SMarc Kleine-Budde put_unaligned_be16(crc, (void *)load_buf + len); 23791f0e21a0SMarc Kleine-Budde 23801f0e21a0SMarc Kleine-Budde /* Total length */ 23811f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->crc.crc); 23821f0e21a0SMarc Kleine-Budde } else { 23831f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->nocrc.cmd); 23841f0e21a0SMarc Kleine-Budde } 23851f0e21a0SMarc Kleine-Budde 23861f0e21a0SMarc Kleine-Budde tx_obj->xfer[0].len = len; 23871f0e21a0SMarc Kleine-Budde } 23881f0e21a0SMarc Kleine-Budde 2389eb79a267SMarc Kleine-Budde static int mcp251xfd_tx_obj_write(const struct mcp251xfd_priv *priv, 2390eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj) 23911f0e21a0SMarc Kleine-Budde { 23921f0e21a0SMarc Kleine-Budde return spi_async(priv->spi, &tx_obj->msg); 23931f0e21a0SMarc Kleine-Budde } 23941f0e21a0SMarc Kleine-Budde 2395eb79a267SMarc Kleine-Budde static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv, 2396eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring) 23971f0e21a0SMarc Kleine-Budde { 2398eb79a267SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) > 0) 23991f0e21a0SMarc Kleine-Budde return false; 24001f0e21a0SMarc Kleine-Budde 24011f0e21a0SMarc Kleine-Budde netif_stop_queue(priv->ndev); 24021f0e21a0SMarc Kleine-Budde 24031f0e21a0SMarc Kleine-Budde /* Memory barrier before checking tx_free (head and tail) */ 24041f0e21a0SMarc Kleine-Budde smp_mb(); 24051f0e21a0SMarc Kleine-Budde 2406eb79a267SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) == 0) { 24071f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 24081f0e21a0SMarc Kleine-Budde "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n", 24091f0e21a0SMarc Kleine-Budde tx_ring->head, tx_ring->tail, 24101f0e21a0SMarc Kleine-Budde tx_ring->head - tx_ring->tail); 24111f0e21a0SMarc Kleine-Budde 24121f0e21a0SMarc Kleine-Budde return true; 24131f0e21a0SMarc Kleine-Budde } 24141f0e21a0SMarc Kleine-Budde 24151f0e21a0SMarc Kleine-Budde netif_start_queue(priv->ndev); 24161f0e21a0SMarc Kleine-Budde 24171f0e21a0SMarc Kleine-Budde return false; 24181f0e21a0SMarc Kleine-Budde } 24191f0e21a0SMarc Kleine-Budde 2420eb79a267SMarc Kleine-Budde static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb, 24211f0e21a0SMarc Kleine-Budde struct net_device *ndev) 24221f0e21a0SMarc Kleine-Budde { 2423eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 2424eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 2425eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 24261f0e21a0SMarc Kleine-Budde u8 tx_head; 24271f0e21a0SMarc Kleine-Budde int err; 24281f0e21a0SMarc Kleine-Budde 24291f0e21a0SMarc Kleine-Budde if (can_dropped_invalid_skb(ndev, skb)) 24301f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 24311f0e21a0SMarc Kleine-Budde 2432eb79a267SMarc Kleine-Budde if (mcp251xfd_tx_busy(priv, tx_ring)) 24331f0e21a0SMarc Kleine-Budde return NETDEV_TX_BUSY; 24341f0e21a0SMarc Kleine-Budde 2435eb79a267SMarc Kleine-Budde tx_obj = mcp251xfd_get_tx_obj_next(tx_ring); 2436eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(priv, tx_obj, skb, tx_ring->head); 24371f0e21a0SMarc Kleine-Budde 24381f0e21a0SMarc Kleine-Budde /* Stop queue if we occupy the complete TX FIFO */ 2439eb79a267SMarc Kleine-Budde tx_head = mcp251xfd_get_tx_head(tx_ring); 24401f0e21a0SMarc Kleine-Budde tx_ring->head++; 24419845b8f5SMarc Kleine-Budde if (mcp251xfd_get_tx_free(tx_ring) == 0) 24421f0e21a0SMarc Kleine-Budde netif_stop_queue(ndev); 24431f0e21a0SMarc Kleine-Budde 24441dcb6e57SVincent Mailhol can_put_echo_skb(skb, ndev, tx_head, 0); 24451f0e21a0SMarc Kleine-Budde 2446eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_obj_write(priv, tx_obj); 24471f0e21a0SMarc Kleine-Budde if (err) 24481f0e21a0SMarc Kleine-Budde goto out_err; 24491f0e21a0SMarc Kleine-Budde 24501f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 24511f0e21a0SMarc Kleine-Budde 24521f0e21a0SMarc Kleine-Budde out_err: 24531f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, "ERROR in %s: %d\n", __func__, err); 24541f0e21a0SMarc Kleine-Budde 24551f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 24561f0e21a0SMarc Kleine-Budde } 24571f0e21a0SMarc Kleine-Budde 2458eb79a267SMarc Kleine-Budde static int mcp251xfd_open(struct net_device *ndev) 24591f0e21a0SMarc Kleine-Budde { 2460eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 24611f0e21a0SMarc Kleine-Budde const struct spi_device *spi = priv->spi; 24621f0e21a0SMarc Kleine-Budde int err; 24631f0e21a0SMarc Kleine-Budde 24641f0e21a0SMarc Kleine-Budde err = pm_runtime_get_sync(ndev->dev.parent); 24651f0e21a0SMarc Kleine-Budde if (err < 0) { 24661f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 24671f0e21a0SMarc Kleine-Budde return err; 24681f0e21a0SMarc Kleine-Budde } 24691f0e21a0SMarc Kleine-Budde 24701f0e21a0SMarc Kleine-Budde err = open_candev(ndev); 24711f0e21a0SMarc Kleine-Budde if (err) 24721f0e21a0SMarc Kleine-Budde goto out_pm_runtime_put; 24731f0e21a0SMarc Kleine-Budde 2474eb79a267SMarc Kleine-Budde err = mcp251xfd_ring_alloc(priv); 24751f0e21a0SMarc Kleine-Budde if (err) 24761f0e21a0SMarc Kleine-Budde goto out_close_candev; 24771f0e21a0SMarc Kleine-Budde 2478eb79a267SMarc Kleine-Budde err = mcp251xfd_transceiver_enable(priv); 24791f0e21a0SMarc Kleine-Budde if (err) 2480eb79a267SMarc Kleine-Budde goto out_mcp251xfd_ring_free; 24811f0e21a0SMarc Kleine-Budde 2482eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_start(priv); 24831f0e21a0SMarc Kleine-Budde if (err) 24841f0e21a0SMarc Kleine-Budde goto out_transceiver_disable; 24851f0e21a0SMarc Kleine-Budde 24861f0e21a0SMarc Kleine-Budde can_rx_offload_enable(&priv->offload); 24871f0e21a0SMarc Kleine-Budde 2488eb79a267SMarc Kleine-Budde err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq, 24891f0e21a0SMarc Kleine-Budde IRQF_ONESHOT, dev_name(&spi->dev), 24901f0e21a0SMarc Kleine-Budde priv); 24911f0e21a0SMarc Kleine-Budde if (err) 24921f0e21a0SMarc Kleine-Budde goto out_can_rx_offload_disable; 24931f0e21a0SMarc Kleine-Budde 2494eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_interrupts_enable(priv); 24951f0e21a0SMarc Kleine-Budde if (err) 24961f0e21a0SMarc Kleine-Budde goto out_free_irq; 24971f0e21a0SMarc Kleine-Budde 24981f0e21a0SMarc Kleine-Budde netif_start_queue(ndev); 24991f0e21a0SMarc Kleine-Budde 25001f0e21a0SMarc Kleine-Budde return 0; 25011f0e21a0SMarc Kleine-Budde 25021f0e21a0SMarc Kleine-Budde out_free_irq: 25031f0e21a0SMarc Kleine-Budde free_irq(spi->irq, priv); 25041f0e21a0SMarc Kleine-Budde out_can_rx_offload_disable: 25051f0e21a0SMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 25061f0e21a0SMarc Kleine-Budde out_transceiver_disable: 2507eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(priv); 2508eb79a267SMarc Kleine-Budde out_mcp251xfd_ring_free: 2509eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 25101f0e21a0SMarc Kleine-Budde out_close_candev: 25111f0e21a0SMarc Kleine-Budde close_candev(ndev); 25121f0e21a0SMarc Kleine-Budde out_pm_runtime_put: 2513eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 25141f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 25151f0e21a0SMarc Kleine-Budde 25161f0e21a0SMarc Kleine-Budde return err; 25171f0e21a0SMarc Kleine-Budde } 25181f0e21a0SMarc Kleine-Budde 2519eb79a267SMarc Kleine-Budde static int mcp251xfd_stop(struct net_device *ndev) 25201f0e21a0SMarc Kleine-Budde { 2521eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 25221f0e21a0SMarc Kleine-Budde 25231f0e21a0SMarc Kleine-Budde netif_stop_queue(ndev); 2524eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 25251f0e21a0SMarc Kleine-Budde free_irq(ndev->irq, priv); 25261f0e21a0SMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 2527eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 2528eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(priv); 2529eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 25301f0e21a0SMarc Kleine-Budde close_candev(ndev); 25311f0e21a0SMarc Kleine-Budde 25321f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 25331f0e21a0SMarc Kleine-Budde 25341f0e21a0SMarc Kleine-Budde return 0; 25351f0e21a0SMarc Kleine-Budde } 25361f0e21a0SMarc Kleine-Budde 2537eb79a267SMarc Kleine-Budde static const struct net_device_ops mcp251xfd_netdev_ops = { 2538eb79a267SMarc Kleine-Budde .ndo_open = mcp251xfd_open, 2539eb79a267SMarc Kleine-Budde .ndo_stop = mcp251xfd_stop, 2540eb79a267SMarc Kleine-Budde .ndo_start_xmit = mcp251xfd_start_xmit, 25411f0e21a0SMarc Kleine-Budde .ndo_change_mtu = can_change_mtu, 25421f0e21a0SMarc Kleine-Budde }; 25431f0e21a0SMarc Kleine-Budde 25441f0e21a0SMarc Kleine-Budde static void 2545eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(struct mcp251xfd_priv *priv) 25461f0e21a0SMarc Kleine-Budde { 25471f0e21a0SMarc Kleine-Budde const struct spi_device *spi = priv->spi; 25481f0e21a0SMarc Kleine-Budde const struct spi_controller *ctlr = spi->controller; 25491f0e21a0SMarc Kleine-Budde 25501f0e21a0SMarc Kleine-Budde if (ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX) 2551eb79a267SMarc Kleine-Budde priv->devtype_data.quirks |= MCP251XFD_QUIRK_HALF_DUPLEX; 25521f0e21a0SMarc Kleine-Budde } 25531f0e21a0SMarc Kleine-Budde 2554eb79a267SMarc Kleine-Budde static int mcp251xfd_register_chip_detect(struct mcp251xfd_priv *priv) 25551f0e21a0SMarc Kleine-Budde { 25561f0e21a0SMarc Kleine-Budde const struct net_device *ndev = priv->ndev; 2557eb79a267SMarc Kleine-Budde const struct mcp251xfd_devtype_data *devtype_data; 25581f0e21a0SMarc Kleine-Budde u32 osc; 25591f0e21a0SMarc Kleine-Budde int err; 25601f0e21a0SMarc Kleine-Budde 25611f0e21a0SMarc Kleine-Budde /* The OSC_LPMEN is only supported on MCP2518FD, so use it to 25621f0e21a0SMarc Kleine-Budde * autodetect the model. 25631f0e21a0SMarc Kleine-Budde */ 2564eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_OSC, 2565eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_LPMEN, 2566eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_LPMEN); 25671f0e21a0SMarc Kleine-Budde if (err) 25681f0e21a0SMarc Kleine-Budde return err; 25691f0e21a0SMarc Kleine-Budde 2570eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc); 25711f0e21a0SMarc Kleine-Budde if (err) 25721f0e21a0SMarc Kleine-Budde return err; 25731f0e21a0SMarc Kleine-Budde 2574eb79a267SMarc Kleine-Budde if (osc & MCP251XFD_REG_OSC_LPMEN) 2575eb79a267SMarc Kleine-Budde devtype_data = &mcp251xfd_devtype_data_mcp2518fd; 25761f0e21a0SMarc Kleine-Budde else 2577eb79a267SMarc Kleine-Budde devtype_data = &mcp251xfd_devtype_data_mcp2517fd; 25781f0e21a0SMarc Kleine-Budde 2579eb79a267SMarc Kleine-Budde if (!mcp251xfd_is_251X(priv) && 25801f0e21a0SMarc Kleine-Budde priv->devtype_data.model != devtype_data->model) { 25811f0e21a0SMarc Kleine-Budde netdev_info(ndev, 25821f0e21a0SMarc Kleine-Budde "Detected %s, but firmware specifies a %s. Fixing up.", 2583eb79a267SMarc Kleine-Budde __mcp251xfd_get_model_str(devtype_data->model), 2584eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv)); 25851f0e21a0SMarc Kleine-Budde } 25861f0e21a0SMarc Kleine-Budde priv->devtype_data = *devtype_data; 25871f0e21a0SMarc Kleine-Budde 25881f0e21a0SMarc Kleine-Budde /* We need to preserve the Half Duplex Quirk. */ 2589eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(priv); 25901f0e21a0SMarc Kleine-Budde 25911f0e21a0SMarc Kleine-Budde /* Re-init regmap with quirks of detected model. */ 2592eb79a267SMarc Kleine-Budde return mcp251xfd_regmap_init(priv); 25931f0e21a0SMarc Kleine-Budde } 25941f0e21a0SMarc Kleine-Budde 2595eb79a267SMarc Kleine-Budde static int mcp251xfd_register_check_rx_int(struct mcp251xfd_priv *priv) 25961f0e21a0SMarc Kleine-Budde { 25971f0e21a0SMarc Kleine-Budde int err, rx_pending; 25981f0e21a0SMarc Kleine-Budde 25991f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 26001f0e21a0SMarc Kleine-Budde return 0; 26011f0e21a0SMarc Kleine-Budde 2602eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_enable(priv); 26031f0e21a0SMarc Kleine-Budde if (err) 26041f0e21a0SMarc Kleine-Budde return err; 26051f0e21a0SMarc Kleine-Budde 26061f0e21a0SMarc Kleine-Budde /* Check if RX_INT is properly working. The RX_INT should not 26071f0e21a0SMarc Kleine-Budde * be active after a softreset. 26081f0e21a0SMarc Kleine-Budde */ 26091f0e21a0SMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 26101f0e21a0SMarc Kleine-Budde 2611eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_disable(priv); 26121f0e21a0SMarc Kleine-Budde if (err) 26131f0e21a0SMarc Kleine-Budde return err; 26141f0e21a0SMarc Kleine-Budde 26151f0e21a0SMarc Kleine-Budde if (!rx_pending) 26161f0e21a0SMarc Kleine-Budde return 0; 26171f0e21a0SMarc Kleine-Budde 26181f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 26191f0e21a0SMarc Kleine-Budde "RX_INT active after softreset, disabling RX_INT support."); 26201f0e21a0SMarc Kleine-Budde devm_gpiod_put(&priv->spi->dev, priv->rx_int); 26211f0e21a0SMarc Kleine-Budde priv->rx_int = NULL; 26221f0e21a0SMarc Kleine-Budde 26231f0e21a0SMarc Kleine-Budde return 0; 26241f0e21a0SMarc Kleine-Budde } 26251f0e21a0SMarc Kleine-Budde 26261f0e21a0SMarc Kleine-Budde static int 2627eb79a267SMarc Kleine-Budde mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, 26281f0e21a0SMarc Kleine-Budde u32 *dev_id, u32 *effective_speed_hz) 26291f0e21a0SMarc Kleine-Budde { 2630eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_rx; 2631eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_tx; 26321f0e21a0SMarc Kleine-Budde struct spi_transfer xfer[2] = { }; 26331f0e21a0SMarc Kleine-Budde int err; 26341f0e21a0SMarc Kleine-Budde 26351f0e21a0SMarc Kleine-Budde buf_rx = kzalloc(sizeof(*buf_rx), GFP_KERNEL); 26361f0e21a0SMarc Kleine-Budde if (!buf_rx) 26371f0e21a0SMarc Kleine-Budde return -ENOMEM; 26381f0e21a0SMarc Kleine-Budde 26391f0e21a0SMarc Kleine-Budde buf_tx = kzalloc(sizeof(*buf_tx), GFP_KERNEL); 26401f0e21a0SMarc Kleine-Budde if (!buf_tx) { 26411f0e21a0SMarc Kleine-Budde err = -ENOMEM; 26421f0e21a0SMarc Kleine-Budde goto out_kfree_buf_rx; 26431f0e21a0SMarc Kleine-Budde } 26441f0e21a0SMarc Kleine-Budde 26451f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 26461f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd); 26471f0e21a0SMarc Kleine-Budde xfer[1].rx_buf = buf_rx->data; 26481f0e21a0SMarc Kleine-Budde xfer[1].len = sizeof(dev_id); 26491f0e21a0SMarc Kleine-Budde 2650eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, MCP251XFD_REG_DEVID); 26511f0e21a0SMarc Kleine-Budde err = spi_sync_transfer(priv->spi, xfer, ARRAY_SIZE(xfer)); 26521f0e21a0SMarc Kleine-Budde if (err) 26531f0e21a0SMarc Kleine-Budde goto out_kfree_buf_tx; 26541f0e21a0SMarc Kleine-Budde 26551f0e21a0SMarc Kleine-Budde *dev_id = be32_to_cpup((__be32 *)buf_rx->data); 26561f0e21a0SMarc Kleine-Budde *effective_speed_hz = xfer->effective_speed_hz; 26571f0e21a0SMarc Kleine-Budde 26581f0e21a0SMarc Kleine-Budde out_kfree_buf_tx: 26591f0e21a0SMarc Kleine-Budde kfree(buf_tx); 26601f0e21a0SMarc Kleine-Budde out_kfree_buf_rx: 26611f0e21a0SMarc Kleine-Budde kfree(buf_rx); 26621f0e21a0SMarc Kleine-Budde 26631f0e21a0SMarc Kleine-Budde return 0; 26641f0e21a0SMarc Kleine-Budde } 26651f0e21a0SMarc Kleine-Budde 2666eb79a267SMarc Kleine-Budde #define MCP251XFD_QUIRK_ACTIVE(quirk) \ 2667eb79a267SMarc Kleine-Budde (priv->devtype_data.quirks & MCP251XFD_QUIRK_##quirk ? '+' : '-') 26681f0e21a0SMarc Kleine-Budde 26691f0e21a0SMarc Kleine-Budde static int 2670eb79a267SMarc Kleine-Budde mcp251xfd_register_done(const struct mcp251xfd_priv *priv) 26711f0e21a0SMarc Kleine-Budde { 26721f0e21a0SMarc Kleine-Budde u32 dev_id, effective_speed_hz; 26731f0e21a0SMarc Kleine-Budde int err; 26741f0e21a0SMarc Kleine-Budde 2675eb79a267SMarc Kleine-Budde err = mcp251xfd_register_get_dev_id(priv, &dev_id, 26761f0e21a0SMarc Kleine-Budde &effective_speed_hz); 26771f0e21a0SMarc Kleine-Budde if (err) 26781f0e21a0SMarc Kleine-Budde return err; 26791f0e21a0SMarc Kleine-Budde 26801f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 26811f0e21a0SMarc 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", 2682eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv), 2683eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_DEVID_ID_MASK, dev_id), 2684eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_DEVID_REV_MASK, dev_id), 26851f0e21a0SMarc Kleine-Budde priv->rx_int ? '+' : '-', 2686eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(MAB_NO_WARN), 2687eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_REG), 2688eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_RX), 2689eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_TX), 2690eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(ECC), 2691eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(HALF_DUPLEX), 26921f0e21a0SMarc Kleine-Budde priv->can.clock.freq / 1000000, 26931f0e21a0SMarc Kleine-Budde priv->can.clock.freq % 1000000 / 1000 / 10, 26941f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig / 1000000, 26951f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig % 1000000 / 1000 / 10, 26961f0e21a0SMarc Kleine-Budde priv->spi->max_speed_hz / 1000000, 26971f0e21a0SMarc Kleine-Budde priv->spi->max_speed_hz % 1000000 / 1000 / 10, 26981f0e21a0SMarc Kleine-Budde effective_speed_hz / 1000000, 26991f0e21a0SMarc Kleine-Budde effective_speed_hz % 1000000 / 1000 / 10); 27001f0e21a0SMarc Kleine-Budde 27011f0e21a0SMarc Kleine-Budde return 0; 27021f0e21a0SMarc Kleine-Budde } 27031f0e21a0SMarc Kleine-Budde 2704eb79a267SMarc Kleine-Budde static int mcp251xfd_register(struct mcp251xfd_priv *priv) 27051f0e21a0SMarc Kleine-Budde { 27061f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 27071f0e21a0SMarc Kleine-Budde int err; 27081f0e21a0SMarc Kleine-Budde 2709eb79a267SMarc Kleine-Budde err = mcp251xfd_clks_and_vdd_enable(priv); 27101f0e21a0SMarc Kleine-Budde if (err) 27111f0e21a0SMarc Kleine-Budde return err; 27121f0e21a0SMarc Kleine-Budde 27131f0e21a0SMarc Kleine-Budde pm_runtime_get_noresume(ndev->dev.parent); 27141f0e21a0SMarc Kleine-Budde err = pm_runtime_set_active(ndev->dev.parent); 27151f0e21a0SMarc Kleine-Budde if (err) 27161f0e21a0SMarc Kleine-Budde goto out_runtime_put_noidle; 27171f0e21a0SMarc Kleine-Budde pm_runtime_enable(ndev->dev.parent); 27181f0e21a0SMarc Kleine-Budde 2719eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(priv); 27201f0e21a0SMarc Kleine-Budde 2721eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset(priv); 27221f0e21a0SMarc Kleine-Budde if (err == -ENODEV) 27231f0e21a0SMarc Kleine-Budde goto out_runtime_disable; 27241f0e21a0SMarc Kleine-Budde if (err) 27251f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 27261f0e21a0SMarc Kleine-Budde 2727eb79a267SMarc Kleine-Budde err = mcp251xfd_register_chip_detect(priv); 27281f0e21a0SMarc Kleine-Budde if (err) 27291f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 27301f0e21a0SMarc Kleine-Budde 2731eb79a267SMarc Kleine-Budde err = mcp251xfd_register_check_rx_int(priv); 27321f0e21a0SMarc Kleine-Budde if (err) 27331f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 27341f0e21a0SMarc Kleine-Budde 27351f0e21a0SMarc Kleine-Budde err = register_candev(ndev); 27361f0e21a0SMarc Kleine-Budde if (err) 27371f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 27381f0e21a0SMarc Kleine-Budde 2739eb79a267SMarc Kleine-Budde err = mcp251xfd_register_done(priv); 27401f0e21a0SMarc Kleine-Budde if (err) 27411f0e21a0SMarc Kleine-Budde goto out_unregister_candev; 27421f0e21a0SMarc Kleine-Budde 27431f0e21a0SMarc Kleine-Budde /* Put controller into sleep mode and let pm_runtime_put() 27441f0e21a0SMarc Kleine-Budde * disable the clocks and vdd. If CONFIG_PM is not enabled, 27451f0e21a0SMarc Kleine-Budde * the clocks and vdd will stay powered. 27461f0e21a0SMarc Kleine-Budde */ 2747eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 27481f0e21a0SMarc Kleine-Budde if (err) 27491f0e21a0SMarc Kleine-Budde goto out_unregister_candev; 27501f0e21a0SMarc Kleine-Budde 27511f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 27521f0e21a0SMarc Kleine-Budde 27531f0e21a0SMarc Kleine-Budde return 0; 27541f0e21a0SMarc Kleine-Budde 27551f0e21a0SMarc Kleine-Budde out_unregister_candev: 27561f0e21a0SMarc Kleine-Budde unregister_candev(ndev); 27571f0e21a0SMarc Kleine-Budde out_chip_set_mode_sleep: 2758eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 27591f0e21a0SMarc Kleine-Budde out_runtime_disable: 27601f0e21a0SMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 27611f0e21a0SMarc Kleine-Budde out_runtime_put_noidle: 27621f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 2763eb79a267SMarc Kleine-Budde mcp251xfd_clks_and_vdd_disable(priv); 27641f0e21a0SMarc Kleine-Budde 27651f0e21a0SMarc Kleine-Budde return err; 27661f0e21a0SMarc Kleine-Budde } 27671f0e21a0SMarc Kleine-Budde 2768eb79a267SMarc Kleine-Budde static inline void mcp251xfd_unregister(struct mcp251xfd_priv *priv) 27691f0e21a0SMarc Kleine-Budde { 27701f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 27711f0e21a0SMarc Kleine-Budde 27721f0e21a0SMarc Kleine-Budde unregister_candev(ndev); 27731f0e21a0SMarc Kleine-Budde 27741f0e21a0SMarc Kleine-Budde pm_runtime_get_sync(ndev->dev.parent); 27751f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 2776eb79a267SMarc Kleine-Budde mcp251xfd_clks_and_vdd_disable(priv); 27771f0e21a0SMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 27781f0e21a0SMarc Kleine-Budde } 27791f0e21a0SMarc Kleine-Budde 2780eb79a267SMarc Kleine-Budde static const struct of_device_id mcp251xfd_of_match[] = { 27811f0e21a0SMarc Kleine-Budde { 27821f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp2517fd", 2783eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp2517fd, 27841f0e21a0SMarc Kleine-Budde }, { 27851f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp2518fd", 2786eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp2518fd, 27871f0e21a0SMarc Kleine-Budde }, { 27881f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp251xfd", 2789eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp251xfd, 27901f0e21a0SMarc Kleine-Budde }, { 27911f0e21a0SMarc Kleine-Budde /* sentinel */ 27921f0e21a0SMarc Kleine-Budde }, 27931f0e21a0SMarc Kleine-Budde }; 2794eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(of, mcp251xfd_of_match); 27951f0e21a0SMarc Kleine-Budde 2796eb79a267SMarc Kleine-Budde static const struct spi_device_id mcp251xfd_id_table[] = { 27971f0e21a0SMarc Kleine-Budde { 27981f0e21a0SMarc Kleine-Budde .name = "mcp2517fd", 2799eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2517fd, 28001f0e21a0SMarc Kleine-Budde }, { 28011f0e21a0SMarc Kleine-Budde .name = "mcp2518fd", 2802eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2518fd, 28031f0e21a0SMarc Kleine-Budde }, { 28041f0e21a0SMarc Kleine-Budde .name = "mcp251xfd", 2805eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp251xfd, 28061f0e21a0SMarc Kleine-Budde }, { 28071f0e21a0SMarc Kleine-Budde /* sentinel */ 28081f0e21a0SMarc Kleine-Budde }, 28091f0e21a0SMarc Kleine-Budde }; 2810eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(spi, mcp251xfd_id_table); 28111f0e21a0SMarc Kleine-Budde 2812eb79a267SMarc Kleine-Budde static int mcp251xfd_probe(struct spi_device *spi) 28131f0e21a0SMarc Kleine-Budde { 28141f0e21a0SMarc Kleine-Budde const void *match; 28151f0e21a0SMarc Kleine-Budde struct net_device *ndev; 2816eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv; 28171f0e21a0SMarc Kleine-Budde struct gpio_desc *rx_int; 28181f0e21a0SMarc Kleine-Budde struct regulator *reg_vdd, *reg_xceiver; 28191f0e21a0SMarc Kleine-Budde struct clk *clk; 28201f0e21a0SMarc Kleine-Budde u32 freq; 28211f0e21a0SMarc Kleine-Budde int err; 28221f0e21a0SMarc Kleine-Budde 28231a1c436bSMarc Kleine-Budde if (!spi->irq) 28241a1c436bSMarc Kleine-Budde return dev_err_probe(&spi->dev, -ENXIO, 28251a1c436bSMarc Kleine-Budde "No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n"); 28261a1c436bSMarc Kleine-Budde 28271f0e21a0SMarc Kleine-Budde rx_int = devm_gpiod_get_optional(&spi->dev, "microchip,rx-int", 28281f0e21a0SMarc Kleine-Budde GPIOD_IN); 28291f0e21a0SMarc Kleine-Budde if (PTR_ERR(rx_int) == -EPROBE_DEFER) 28301f0e21a0SMarc Kleine-Budde return -EPROBE_DEFER; 28311f0e21a0SMarc Kleine-Budde else if (IS_ERR(rx_int)) 28321f0e21a0SMarc Kleine-Budde return PTR_ERR(rx_int); 28331f0e21a0SMarc Kleine-Budde 28341f0e21a0SMarc Kleine-Budde reg_vdd = devm_regulator_get_optional(&spi->dev, "vdd"); 28351f0e21a0SMarc Kleine-Budde if (PTR_ERR(reg_vdd) == -EPROBE_DEFER) 28361f0e21a0SMarc Kleine-Budde return -EPROBE_DEFER; 28371f0e21a0SMarc Kleine-Budde else if (PTR_ERR(reg_vdd) == -ENODEV) 28381f0e21a0SMarc Kleine-Budde reg_vdd = NULL; 28391f0e21a0SMarc Kleine-Budde else if (IS_ERR(reg_vdd)) 28401f0e21a0SMarc Kleine-Budde return PTR_ERR(reg_vdd); 28411f0e21a0SMarc Kleine-Budde 28421f0e21a0SMarc Kleine-Budde reg_xceiver = devm_regulator_get_optional(&spi->dev, "xceiver"); 28431f0e21a0SMarc Kleine-Budde if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER) 28441f0e21a0SMarc Kleine-Budde return -EPROBE_DEFER; 28451f0e21a0SMarc Kleine-Budde else if (PTR_ERR(reg_xceiver) == -ENODEV) 28461f0e21a0SMarc Kleine-Budde reg_xceiver = NULL; 28471f0e21a0SMarc Kleine-Budde else if (IS_ERR(reg_xceiver)) 28481f0e21a0SMarc Kleine-Budde return PTR_ERR(reg_xceiver); 28491f0e21a0SMarc Kleine-Budde 28501f0e21a0SMarc Kleine-Budde clk = devm_clk_get(&spi->dev, NULL); 28511f0e21a0SMarc Kleine-Budde if (IS_ERR(clk)) { 28521f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, "No Oscillator (clock) defined.\n"); 28531f0e21a0SMarc Kleine-Budde return PTR_ERR(clk); 28541f0e21a0SMarc Kleine-Budde } 28551f0e21a0SMarc Kleine-Budde freq = clk_get_rate(clk); 28561f0e21a0SMarc Kleine-Budde 28571f0e21a0SMarc Kleine-Budde /* Sanity check */ 2858eb79a267SMarc Kleine-Budde if (freq < MCP251XFD_SYSCLOCK_HZ_MIN || 2859eb79a267SMarc Kleine-Budde freq > MCP251XFD_SYSCLOCK_HZ_MAX) { 28601f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, 28611f0e21a0SMarc Kleine-Budde "Oscillator frequency (%u Hz) is too low or high.\n", 28621f0e21a0SMarc Kleine-Budde freq); 28631f0e21a0SMarc Kleine-Budde return -ERANGE; 28641f0e21a0SMarc Kleine-Budde } 28651f0e21a0SMarc Kleine-Budde 2866eb79a267SMarc Kleine-Budde if (freq <= MCP251XFD_SYSCLOCK_HZ_MAX / MCP251XFD_OSC_PLL_MULTIPLIER) { 28671f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, 28681f0e21a0SMarc Kleine-Budde "Oscillator frequency (%u Hz) is too low and PLL is not supported.\n", 28691f0e21a0SMarc Kleine-Budde freq); 28701f0e21a0SMarc Kleine-Budde return -ERANGE; 28711f0e21a0SMarc Kleine-Budde } 28721f0e21a0SMarc Kleine-Budde 2873eb79a267SMarc Kleine-Budde ndev = alloc_candev(sizeof(struct mcp251xfd_priv), 2874eb79a267SMarc Kleine-Budde MCP251XFD_TX_OBJ_NUM_MAX); 28751f0e21a0SMarc Kleine-Budde if (!ndev) 28761f0e21a0SMarc Kleine-Budde return -ENOMEM; 28771f0e21a0SMarc Kleine-Budde 28781f0e21a0SMarc Kleine-Budde SET_NETDEV_DEV(ndev, &spi->dev); 28791f0e21a0SMarc Kleine-Budde 2880eb79a267SMarc Kleine-Budde ndev->netdev_ops = &mcp251xfd_netdev_ops; 28811f0e21a0SMarc Kleine-Budde ndev->irq = spi->irq; 28821f0e21a0SMarc Kleine-Budde ndev->flags |= IFF_ECHO; 28831f0e21a0SMarc Kleine-Budde 28841f0e21a0SMarc Kleine-Budde priv = netdev_priv(ndev); 28851f0e21a0SMarc Kleine-Budde spi_set_drvdata(spi, priv); 28861f0e21a0SMarc Kleine-Budde priv->can.clock.freq = freq; 2887eb79a267SMarc Kleine-Budde priv->can.do_set_mode = mcp251xfd_set_mode; 2888eb79a267SMarc Kleine-Budde priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter; 2889eb79a267SMarc Kleine-Budde priv->can.bittiming_const = &mcp251xfd_bittiming_const; 2890eb79a267SMarc Kleine-Budde priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const; 2891ee42bedcSManivannan Sadhasivam priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | 2892ee42bedcSManivannan Sadhasivam CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING | 2893ee42bedcSManivannan Sadhasivam CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO; 28941f0e21a0SMarc Kleine-Budde priv->ndev = ndev; 28951f0e21a0SMarc Kleine-Budde priv->spi = spi; 28961f0e21a0SMarc Kleine-Budde priv->rx_int = rx_int; 28971f0e21a0SMarc Kleine-Budde priv->clk = clk; 28981f0e21a0SMarc Kleine-Budde priv->reg_vdd = reg_vdd; 28991f0e21a0SMarc Kleine-Budde priv->reg_xceiver = reg_xceiver; 29001f0e21a0SMarc Kleine-Budde 29011f0e21a0SMarc Kleine-Budde match = device_get_match_data(&spi->dev); 29021f0e21a0SMarc Kleine-Budde if (match) 2903eb79a267SMarc Kleine-Budde priv->devtype_data = *(struct mcp251xfd_devtype_data *)match; 29041f0e21a0SMarc Kleine-Budde else 2905eb79a267SMarc Kleine-Budde priv->devtype_data = *(struct mcp251xfd_devtype_data *) 29061f0e21a0SMarc Kleine-Budde spi_get_device_id(spi)->driver_data; 29071f0e21a0SMarc Kleine-Budde 29081f0e21a0SMarc Kleine-Budde /* Errata Reference: 29091f0e21a0SMarc Kleine-Budde * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 4. 29101f0e21a0SMarc Kleine-Budde * 29111f0e21a0SMarc Kleine-Budde * The SPI can write corrupted data to the RAM at fast SPI 29121f0e21a0SMarc Kleine-Budde * speeds: 29131f0e21a0SMarc Kleine-Budde * 29141f0e21a0SMarc Kleine-Budde * Simultaneous activity on the CAN bus while writing data to 29151f0e21a0SMarc Kleine-Budde * RAM via the SPI interface, with high SCK frequency, can 29161f0e21a0SMarc Kleine-Budde * lead to corrupted data being written to RAM. 29171f0e21a0SMarc Kleine-Budde * 29181f0e21a0SMarc Kleine-Budde * Fix/Work Around: 29191f0e21a0SMarc Kleine-Budde * Ensure that FSCK is less than or equal to 0.85 * 29201f0e21a0SMarc Kleine-Budde * (FSYSCLK/2). 29211f0e21a0SMarc Kleine-Budde * 29221f0e21a0SMarc Kleine-Budde * Known good and bad combinations are: 29231f0e21a0SMarc Kleine-Budde * 29241f0e21a0SMarc Kleine-Budde * MCP ext-clk SoC SPI SPI-clk max-clk parent-clk Status config 29251f0e21a0SMarc Kleine-Budde * 29261f0e21a0SMarc Kleine-Budde * 2518 20 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 8333333 Hz 83.33% 600000000 Hz good assigned-clocks = <&ccu CLK_SPIx> 29271f0e21a0SMarc Kleine-Budde * 2518 20 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 9375000 Hz 93.75% 600000000 Hz bad assigned-clocks = <&ccu CLK_SPIx> 29281f0e21a0SMarc Kleine-Budde * 2518 40 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 16666667 Hz 83.33% 600000000 Hz good assigned-clocks = <&ccu CLK_SPIx> 29291f0e21a0SMarc Kleine-Budde * 2518 40 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 18750000 Hz 93.75% 600000000 Hz bad assigned-clocks = <&ccu CLK_SPIx> 29301f0e21a0SMarc Kleine-Budde * 2517 20 MHz fsl,imx8mm fsl,imx51-ecspi 8333333 Hz 83.33% 16666667 Hz good assigned-clocks = <&clk IMX8MM_CLK_ECSPIx_ROOT> 29311f0e21a0SMarc Kleine-Budde * 2517 20 MHz fsl,imx8mm fsl,imx51-ecspi 9523809 Hz 95.34% 28571429 Hz bad assigned-clocks = <&clk IMX8MM_CLK_ECSPIx_ROOT> 29321f0e21a0SMarc Kleine-Budde * 2517 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz good default 29331f0e21a0SMarc Kleine-Budde * 2518 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz good default 29341f0e21a0SMarc Kleine-Budde * 29351f0e21a0SMarc Kleine-Budde */ 29361f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig = spi->max_speed_hz; 29371f0e21a0SMarc Kleine-Budde spi->max_speed_hz = min(spi->max_speed_hz, freq / 2 / 1000 * 850); 29381f0e21a0SMarc Kleine-Budde spi->bits_per_word = 8; 29391f0e21a0SMarc Kleine-Budde spi->rt = true; 29401f0e21a0SMarc Kleine-Budde err = spi_setup(spi); 29411f0e21a0SMarc Kleine-Budde if (err) 29421f0e21a0SMarc Kleine-Budde goto out_free_candev; 29431f0e21a0SMarc Kleine-Budde 2944eb79a267SMarc Kleine-Budde err = mcp251xfd_regmap_init(priv); 29451f0e21a0SMarc Kleine-Budde if (err) 29461f0e21a0SMarc Kleine-Budde goto out_free_candev; 29471f0e21a0SMarc Kleine-Budde 29481f0e21a0SMarc Kleine-Budde err = can_rx_offload_add_manual(ndev, &priv->offload, 2949eb79a267SMarc Kleine-Budde MCP251XFD_NAPI_WEIGHT); 29501f0e21a0SMarc Kleine-Budde if (err) 29511f0e21a0SMarc Kleine-Budde goto out_free_candev; 29521f0e21a0SMarc Kleine-Budde 2953eb79a267SMarc Kleine-Budde err = mcp251xfd_register(priv); 29541f0e21a0SMarc Kleine-Budde if (err) 29551f0e21a0SMarc Kleine-Budde goto out_free_candev; 29561f0e21a0SMarc Kleine-Budde 29571f0e21a0SMarc Kleine-Budde return 0; 29581f0e21a0SMarc Kleine-Budde 29591f0e21a0SMarc Kleine-Budde out_free_candev: 29601f0e21a0SMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 29611f0e21a0SMarc Kleine-Budde 29621f0e21a0SMarc Kleine-Budde free_candev(ndev); 29631f0e21a0SMarc Kleine-Budde 29641f0e21a0SMarc Kleine-Budde return err; 29651f0e21a0SMarc Kleine-Budde } 29661f0e21a0SMarc Kleine-Budde 2967eb79a267SMarc Kleine-Budde static int mcp251xfd_remove(struct spi_device *spi) 29681f0e21a0SMarc Kleine-Budde { 2969eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = spi_get_drvdata(spi); 29701f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 29711f0e21a0SMarc Kleine-Budde 29721f0e21a0SMarc Kleine-Budde can_rx_offload_del(&priv->offload); 2973eb79a267SMarc Kleine-Budde mcp251xfd_unregister(priv); 29741f0e21a0SMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 29751f0e21a0SMarc Kleine-Budde free_candev(ndev); 29761f0e21a0SMarc Kleine-Budde 29771f0e21a0SMarc Kleine-Budde return 0; 29781f0e21a0SMarc Kleine-Budde } 29791f0e21a0SMarc Kleine-Budde 2980eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_suspend(struct device *device) 29811f0e21a0SMarc Kleine-Budde { 2982eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = dev_get_drvdata(device); 29831f0e21a0SMarc Kleine-Budde 2984eb79a267SMarc Kleine-Budde return mcp251xfd_clks_and_vdd_disable(priv); 29851f0e21a0SMarc Kleine-Budde } 29861f0e21a0SMarc Kleine-Budde 2987eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_resume(struct device *device) 29881f0e21a0SMarc Kleine-Budde { 2989eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = dev_get_drvdata(device); 29901f0e21a0SMarc Kleine-Budde 2991eb79a267SMarc Kleine-Budde return mcp251xfd_clks_and_vdd_enable(priv); 29921f0e21a0SMarc Kleine-Budde } 29931f0e21a0SMarc Kleine-Budde 2994eb79a267SMarc Kleine-Budde static const struct dev_pm_ops mcp251xfd_pm_ops = { 2995eb79a267SMarc Kleine-Budde SET_RUNTIME_PM_OPS(mcp251xfd_runtime_suspend, 2996eb79a267SMarc Kleine-Budde mcp251xfd_runtime_resume, NULL) 29971f0e21a0SMarc Kleine-Budde }; 29981f0e21a0SMarc Kleine-Budde 2999eb79a267SMarc Kleine-Budde static struct spi_driver mcp251xfd_driver = { 30001f0e21a0SMarc Kleine-Budde .driver = { 30011f0e21a0SMarc Kleine-Budde .name = DEVICE_NAME, 3002eb79a267SMarc Kleine-Budde .pm = &mcp251xfd_pm_ops, 3003eb79a267SMarc Kleine-Budde .of_match_table = mcp251xfd_of_match, 30041f0e21a0SMarc Kleine-Budde }, 3005eb79a267SMarc Kleine-Budde .probe = mcp251xfd_probe, 3006eb79a267SMarc Kleine-Budde .remove = mcp251xfd_remove, 3007eb79a267SMarc Kleine-Budde .id_table = mcp251xfd_id_table, 30081f0e21a0SMarc Kleine-Budde }; 3009eb79a267SMarc Kleine-Budde module_spi_driver(mcp251xfd_driver); 30101f0e21a0SMarc Kleine-Budde 30111f0e21a0SMarc Kleine-Budde MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>"); 3012f4f77366SMarc Kleine-Budde MODULE_DESCRIPTION("Microchip MCP251xFD Family CAN controller driver"); 30131f0e21a0SMarc Kleine-Budde MODULE_LICENSE("GPL v2"); 3014