11f0e21a0SMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0 21f0e21a0SMarc Kleine-Budde // 31f0e21a0SMarc Kleine-Budde // mcp25xxfd - Microchip MCP25xxFD 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 281f0e21a0SMarc Kleine-Budde #define DEVICE_NAME "mcp25xxfd" 291f0e21a0SMarc Kleine-Budde 301f0e21a0SMarc Kleine-Budde static const struct mcp25xxfd_devtype_data mcp25xxfd_devtype_data_mcp2517fd = { 311f0e21a0SMarc Kleine-Budde .quirks = MCP25XXFD_QUIRK_MAB_NO_WARN | MCP25XXFD_QUIRK_CRC_REG | 321f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_CRC_RX | MCP25XXFD_QUIRK_CRC_TX | 331f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_ECC, 341f0e21a0SMarc Kleine-Budde .model = MCP25XXFD_MODEL_MCP2517FD, 351f0e21a0SMarc Kleine-Budde }; 361f0e21a0SMarc Kleine-Budde 371f0e21a0SMarc Kleine-Budde static const struct mcp25xxfd_devtype_data mcp25xxfd_devtype_data_mcp2518fd = { 381f0e21a0SMarc Kleine-Budde .quirks = MCP25XXFD_QUIRK_CRC_REG | MCP25XXFD_QUIRK_CRC_RX | 391f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_CRC_TX | MCP25XXFD_QUIRK_ECC, 401f0e21a0SMarc Kleine-Budde .model = MCP25XXFD_MODEL_MCP2518FD, 411f0e21a0SMarc Kleine-Budde }; 421f0e21a0SMarc Kleine-Budde 431f0e21a0SMarc Kleine-Budde /* Autodetect model, start with CRC enabled. */ 441f0e21a0SMarc Kleine-Budde static const struct mcp25xxfd_devtype_data mcp25xxfd_devtype_data_mcp251xfd = { 451f0e21a0SMarc Kleine-Budde .quirks = MCP25XXFD_QUIRK_CRC_REG | MCP25XXFD_QUIRK_CRC_RX | 461f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_CRC_TX | MCP25XXFD_QUIRK_ECC, 471f0e21a0SMarc Kleine-Budde .model = MCP25XXFD_MODEL_MCP251XFD, 481f0e21a0SMarc Kleine-Budde }; 491f0e21a0SMarc Kleine-Budde 501f0e21a0SMarc Kleine-Budde static const struct can_bittiming_const mcp25xxfd_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 621f0e21a0SMarc Kleine-Budde static const struct can_bittiming_const mcp25xxfd_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 741f0e21a0SMarc Kleine-Budde static const char *__mcp25xxfd_get_model_str(enum mcp25xxfd_model model) 751f0e21a0SMarc Kleine-Budde { 761f0e21a0SMarc Kleine-Budde switch (model) { 771f0e21a0SMarc Kleine-Budde case MCP25XXFD_MODEL_MCP2517FD: 781f0e21a0SMarc Kleine-Budde return "MCP2517FD"; break; 791f0e21a0SMarc Kleine-Budde case MCP25XXFD_MODEL_MCP2518FD: 801f0e21a0SMarc Kleine-Budde return "MCP2518FD"; break; 811f0e21a0SMarc Kleine-Budde case MCP25XXFD_MODEL_MCP251XFD: 821f0e21a0SMarc Kleine-Budde return "MCP251xFD"; break; 831f0e21a0SMarc Kleine-Budde } 841f0e21a0SMarc Kleine-Budde 851f0e21a0SMarc Kleine-Budde return "<unknown>"; 861f0e21a0SMarc Kleine-Budde } 871f0e21a0SMarc Kleine-Budde 881f0e21a0SMarc Kleine-Budde static inline const char * 891f0e21a0SMarc Kleine-Budde mcp25xxfd_get_model_str(const struct mcp25xxfd_priv *priv) 901f0e21a0SMarc Kleine-Budde { 911f0e21a0SMarc Kleine-Budde return __mcp25xxfd_get_model_str(priv->devtype_data.model); 921f0e21a0SMarc Kleine-Budde } 931f0e21a0SMarc Kleine-Budde 941f0e21a0SMarc Kleine-Budde static const char *mcp25xxfd_get_mode_str(const u8 mode) 951f0e21a0SMarc Kleine-Budde { 961f0e21a0SMarc Kleine-Budde switch (mode) { 971f0e21a0SMarc Kleine-Budde case MCP25XXFD_REG_CON_MODE_MIXED: 981f0e21a0SMarc Kleine-Budde return "Mixed (CAN FD/CAN 2.0)"; break; 991f0e21a0SMarc Kleine-Budde case MCP25XXFD_REG_CON_MODE_SLEEP: 1001f0e21a0SMarc Kleine-Budde return "Sleep"; break; 1011f0e21a0SMarc Kleine-Budde case MCP25XXFD_REG_CON_MODE_INT_LOOPBACK: 1021f0e21a0SMarc Kleine-Budde return "Internal Loopback"; break; 1031f0e21a0SMarc Kleine-Budde case MCP25XXFD_REG_CON_MODE_LISTENONLY: 1041f0e21a0SMarc Kleine-Budde return "Listen Only"; break; 1051f0e21a0SMarc Kleine-Budde case MCP25XXFD_REG_CON_MODE_CONFIG: 1061f0e21a0SMarc Kleine-Budde return "Configuration"; break; 1071f0e21a0SMarc Kleine-Budde case MCP25XXFD_REG_CON_MODE_EXT_LOOPBACK: 1081f0e21a0SMarc Kleine-Budde return "External Loopback"; break; 1091f0e21a0SMarc Kleine-Budde case MCP25XXFD_REG_CON_MODE_CAN2_0: 1101f0e21a0SMarc Kleine-Budde return "CAN 2.0"; break; 1111f0e21a0SMarc Kleine-Budde case MCP25XXFD_REG_CON_MODE_RESTRICTED: 1121f0e21a0SMarc Kleine-Budde return "Restricted Operation"; break; 1131f0e21a0SMarc Kleine-Budde } 1141f0e21a0SMarc Kleine-Budde 1151f0e21a0SMarc Kleine-Budde return "<unknown>"; 1161f0e21a0SMarc Kleine-Budde } 1171f0e21a0SMarc Kleine-Budde 1181f0e21a0SMarc Kleine-Budde static inline int mcp25xxfd_vdd_enable(const struct mcp25xxfd_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 1261f0e21a0SMarc Kleine-Budde static inline int mcp25xxfd_vdd_disable(const struct mcp25xxfd_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 1351f0e21a0SMarc Kleine-Budde mcp25xxfd_transceiver_enable(const struct mcp25xxfd_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 1441f0e21a0SMarc Kleine-Budde mcp25xxfd_transceiver_disable(const struct mcp25xxfd_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 1521f0e21a0SMarc Kleine-Budde static int mcp25xxfd_clks_and_vdd_enable(const struct mcp25xxfd_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 1601f0e21a0SMarc Kleine-Budde err = mcp25xxfd_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 */ 1651f0e21a0SMarc Kleine-Budde usleep_range(MCP25XXFD_OSC_STAB_SLEEP_US, 1661f0e21a0SMarc Kleine-Budde 2 * MCP25XXFD_OSC_STAB_SLEEP_US); 1671f0e21a0SMarc Kleine-Budde 1681f0e21a0SMarc Kleine-Budde return err; 1691f0e21a0SMarc Kleine-Budde } 1701f0e21a0SMarc Kleine-Budde 1711f0e21a0SMarc Kleine-Budde static int mcp25xxfd_clks_and_vdd_disable(const struct mcp25xxfd_priv *priv) 1721f0e21a0SMarc Kleine-Budde { 1731f0e21a0SMarc Kleine-Budde int err; 1741f0e21a0SMarc Kleine-Budde 1751f0e21a0SMarc Kleine-Budde err = mcp25xxfd_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 1851f0e21a0SMarc Kleine-Budde mcp25xxfd_cmd_prepare_write_reg(const struct mcp25xxfd_priv *priv, 1861f0e21a0SMarc Kleine-Budde union mcp25xxfd_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 1931f0e21a0SMarc Kleine-Budde first_byte = mcp25xxfd_first_byte_set(mask); 1941f0e21a0SMarc Kleine-Budde last_byte = mcp25xxfd_last_byte_set(mask); 1951f0e21a0SMarc Kleine-Budde len = last_byte - first_byte + 1; 1961f0e21a0SMarc Kleine-Budde 1971f0e21a0SMarc Kleine-Budde data = mcp25xxfd_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 2011f0e21a0SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_REG) { 2021f0e21a0SMarc Kleine-Budde u16 crc; 2031f0e21a0SMarc Kleine-Budde 2041f0e21a0SMarc Kleine-Budde mcp25xxfd_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); 2081f0e21a0SMarc Kleine-Budde crc = mcp25xxfd_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 2211f0e21a0SMarc Kleine-Budde mcp25xxfd_tef_tail_get_from_chip(const struct mcp25xxfd_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 2271f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_TEFUA, &tef_ua); 2281f0e21a0SMarc Kleine-Budde if (err) 2291f0e21a0SMarc Kleine-Budde return err; 2301f0e21a0SMarc Kleine-Budde 2311f0e21a0SMarc Kleine-Budde *tef_tail = tef_ua / sizeof(struct mcp25xxfd_hw_tef_obj); 2321f0e21a0SMarc Kleine-Budde 2331f0e21a0SMarc Kleine-Budde return 0; 2341f0e21a0SMarc Kleine-Budde } 2351f0e21a0SMarc Kleine-Budde 2361f0e21a0SMarc Kleine-Budde static inline int 2371f0e21a0SMarc Kleine-Budde mcp25xxfd_tx_tail_get_from_chip(const struct mcp25xxfd_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, 2441f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOSTA(MCP25XXFD_TX_FIFO), 2451f0e21a0SMarc Kleine-Budde &fifo_sta); 2461f0e21a0SMarc Kleine-Budde if (err) 2471f0e21a0SMarc Kleine-Budde return err; 2481f0e21a0SMarc Kleine-Budde 2491f0e21a0SMarc Kleine-Budde *tx_tail = FIELD_GET(MCP25XXFD_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 2551f0e21a0SMarc Kleine-Budde mcp25xxfd_rx_head_get_from_chip(const struct mcp25xxfd_priv *priv, 2561f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_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 2621f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_FIFOSTA(ring->fifo_nr), 2631f0e21a0SMarc Kleine-Budde &fifo_sta); 2641f0e21a0SMarc Kleine-Budde if (err) 2651f0e21a0SMarc Kleine-Budde return err; 2661f0e21a0SMarc Kleine-Budde 2671f0e21a0SMarc Kleine-Budde *rx_head = FIELD_GET(MCP25XXFD_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 2731f0e21a0SMarc Kleine-Budde mcp25xxfd_rx_tail_get_from_chip(const struct mcp25xxfd_priv *priv, 2741f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_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 2801f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_FIFOUA(ring->fifo_nr), 2811f0e21a0SMarc Kleine-Budde &fifo_ua); 2821f0e21a0SMarc Kleine-Budde if (err) 2831f0e21a0SMarc Kleine-Budde return err; 2841f0e21a0SMarc Kleine-Budde 2851f0e21a0SMarc Kleine-Budde fifo_ua -= ring->base - MCP25XXFD_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 2921f0e21a0SMarc Kleine-Budde mcp25xxfd_tx_ring_init_tx_obj(const struct mcp25xxfd_priv *priv, 2931f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_tx_ring *ring, 2941f0e21a0SMarc Kleine-Budde struct mcp25xxfd_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 */ 3021f0e21a0SMarc Kleine-Budde addr = mcp25xxfd_get_tx_obj_addr(ring, n); 3031f0e21a0SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_TX) 3041f0e21a0SMarc Kleine-Budde mcp25xxfd_spi_cmd_write_crc_set_addr(&tx_obj->buf.crc.cmd, 3051f0e21a0SMarc Kleine-Budde addr); 3061f0e21a0SMarc Kleine-Budde else 3071f0e21a0SMarc Kleine-Budde mcp25xxfd_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 3271f0e21a0SMarc Kleine-Budde static void mcp25xxfd_ring_init(struct mcp25xxfd_priv *priv) 3281f0e21a0SMarc Kleine-Budde { 3291f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_ring *tx_ring; 3301f0e21a0SMarc Kleine-Budde struct mcp25xxfd_rx_ring *rx_ring, *prev_rx_ring = NULL; 3311f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_obj *tx_obj; 3321f0e21a0SMarc Kleine-Budde u32 val; 3331f0e21a0SMarc Kleine-Budde u16 addr; 3341f0e21a0SMarc Kleine-Budde u8 len; 3351f0e21a0SMarc Kleine-Budde int i; 3361f0e21a0SMarc Kleine-Budde 3371f0e21a0SMarc Kleine-Budde /* TEF */ 3381f0e21a0SMarc Kleine-Budde priv->tef.head = 0; 3391f0e21a0SMarc Kleine-Budde priv->tef.tail = 0; 3401f0e21a0SMarc Kleine-Budde 3411f0e21a0SMarc Kleine-Budde /* TX */ 3421f0e21a0SMarc Kleine-Budde tx_ring = priv->tx; 3431f0e21a0SMarc Kleine-Budde tx_ring->head = 0; 3441f0e21a0SMarc Kleine-Budde tx_ring->tail = 0; 3451f0e21a0SMarc Kleine-Budde tx_ring->base = mcp25xxfd_get_tef_obj_addr(tx_ring->obj_num); 3461f0e21a0SMarc Kleine-Budde 3471f0e21a0SMarc Kleine-Budde /* FIFO request to send */ 3481f0e21a0SMarc Kleine-Budde addr = MCP25XXFD_REG_FIFOCON(MCP25XXFD_TX_FIFO); 3491f0e21a0SMarc Kleine-Budde val = MCP25XXFD_REG_FIFOCON_TXREQ | MCP25XXFD_REG_FIFOCON_UINC; 3501f0e21a0SMarc Kleine-Budde len = mcp25xxfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf, 3511f0e21a0SMarc Kleine-Budde addr, val, val); 3521f0e21a0SMarc Kleine-Budde 3531f0e21a0SMarc Kleine-Budde mcp25xxfd_for_each_tx_obj(tx_ring, tx_obj, i) 3541f0e21a0SMarc Kleine-Budde mcp25xxfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i); 3551f0e21a0SMarc Kleine-Budde 3561f0e21a0SMarc Kleine-Budde /* RX */ 3571f0e21a0SMarc Kleine-Budde mcp25xxfd_for_each_rx_ring(priv, rx_ring, i) { 3581f0e21a0SMarc Kleine-Budde rx_ring->head = 0; 3591f0e21a0SMarc Kleine-Budde rx_ring->tail = 0; 3601f0e21a0SMarc Kleine-Budde rx_ring->nr = i; 3611f0e21a0SMarc Kleine-Budde rx_ring->fifo_nr = MCP25XXFD_RX_FIFO(i); 3621f0e21a0SMarc Kleine-Budde 3631f0e21a0SMarc Kleine-Budde if (!prev_rx_ring) 3641f0e21a0SMarc Kleine-Budde rx_ring->base = 3651f0e21a0SMarc Kleine-Budde mcp25xxfd_get_tx_obj_addr(tx_ring, 3661f0e21a0SMarc Kleine-Budde tx_ring->obj_num); 3671f0e21a0SMarc Kleine-Budde else 3681f0e21a0SMarc Kleine-Budde rx_ring->base = prev_rx_ring->base + 3691f0e21a0SMarc Kleine-Budde prev_rx_ring->obj_size * 3701f0e21a0SMarc Kleine-Budde prev_rx_ring->obj_num; 3711f0e21a0SMarc Kleine-Budde 3721f0e21a0SMarc Kleine-Budde prev_rx_ring = rx_ring; 3731f0e21a0SMarc Kleine-Budde } 3741f0e21a0SMarc Kleine-Budde } 3751f0e21a0SMarc Kleine-Budde 3761f0e21a0SMarc Kleine-Budde static void mcp25xxfd_ring_free(struct mcp25xxfd_priv *priv) 3771f0e21a0SMarc Kleine-Budde { 3781f0e21a0SMarc Kleine-Budde int i; 3791f0e21a0SMarc Kleine-Budde 3801f0e21a0SMarc Kleine-Budde for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) { 3811f0e21a0SMarc Kleine-Budde kfree(priv->rx[i]); 3821f0e21a0SMarc Kleine-Budde priv->rx[i] = NULL; 3831f0e21a0SMarc Kleine-Budde } 3841f0e21a0SMarc Kleine-Budde } 3851f0e21a0SMarc Kleine-Budde 3861f0e21a0SMarc Kleine-Budde static int mcp25xxfd_ring_alloc(struct mcp25xxfd_priv *priv) 3871f0e21a0SMarc Kleine-Budde { 3881f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_ring *tx_ring; 3891f0e21a0SMarc Kleine-Budde struct mcp25xxfd_rx_ring *rx_ring; 3901f0e21a0SMarc Kleine-Budde int tef_obj_size, tx_obj_size, rx_obj_size; 3911f0e21a0SMarc Kleine-Budde int tx_obj_num; 3921f0e21a0SMarc Kleine-Budde int ram_free, i; 3931f0e21a0SMarc Kleine-Budde 3941f0e21a0SMarc Kleine-Budde tef_obj_size = sizeof(struct mcp25xxfd_hw_tef_obj); 3951f0e21a0SMarc Kleine-Budde /* listen-only mode works like FD mode */ 3961f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) { 3971f0e21a0SMarc Kleine-Budde tx_obj_num = MCP25XXFD_TX_OBJ_NUM_CANFD; 3981f0e21a0SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp25xxfd_hw_tx_obj_canfd); 3991f0e21a0SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp25xxfd_hw_rx_obj_canfd); 4001f0e21a0SMarc Kleine-Budde } else { 4011f0e21a0SMarc Kleine-Budde tx_obj_num = MCP25XXFD_TX_OBJ_NUM_CAN; 4021f0e21a0SMarc Kleine-Budde tx_obj_size = sizeof(struct mcp25xxfd_hw_tx_obj_can); 4031f0e21a0SMarc Kleine-Budde rx_obj_size = sizeof(struct mcp25xxfd_hw_rx_obj_can); 4041f0e21a0SMarc Kleine-Budde } 4051f0e21a0SMarc Kleine-Budde 4061f0e21a0SMarc Kleine-Budde tx_ring = priv->tx; 4071f0e21a0SMarc Kleine-Budde tx_ring->obj_num = tx_obj_num; 4081f0e21a0SMarc Kleine-Budde tx_ring->obj_size = tx_obj_size; 4091f0e21a0SMarc Kleine-Budde 4101f0e21a0SMarc Kleine-Budde ram_free = MCP25XXFD_RAM_SIZE - tx_obj_num * 4111f0e21a0SMarc Kleine-Budde (tef_obj_size + tx_obj_size); 4121f0e21a0SMarc Kleine-Budde 4131f0e21a0SMarc Kleine-Budde for (i = 0; 4141f0e21a0SMarc Kleine-Budde i < ARRAY_SIZE(priv->rx) && ram_free >= rx_obj_size; 4151f0e21a0SMarc Kleine-Budde i++) { 4161f0e21a0SMarc Kleine-Budde int rx_obj_num; 4171f0e21a0SMarc Kleine-Budde 4181f0e21a0SMarc Kleine-Budde rx_obj_num = ram_free / rx_obj_size; 4191f0e21a0SMarc Kleine-Budde rx_obj_num = min(1 << (fls(rx_obj_num) - 1), 32); 4201f0e21a0SMarc Kleine-Budde 4211f0e21a0SMarc Kleine-Budde rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num, 4221f0e21a0SMarc Kleine-Budde GFP_KERNEL); 4231f0e21a0SMarc Kleine-Budde if (!rx_ring) { 4241f0e21a0SMarc Kleine-Budde mcp25xxfd_ring_free(priv); 4251f0e21a0SMarc Kleine-Budde return -ENOMEM; 4261f0e21a0SMarc Kleine-Budde } 4271f0e21a0SMarc Kleine-Budde rx_ring->obj_num = rx_obj_num; 4281f0e21a0SMarc Kleine-Budde rx_ring->obj_size = rx_obj_size; 4291f0e21a0SMarc Kleine-Budde priv->rx[i] = rx_ring; 4301f0e21a0SMarc Kleine-Budde 4311f0e21a0SMarc Kleine-Budde ram_free -= rx_ring->obj_num * rx_ring->obj_size; 4321f0e21a0SMarc Kleine-Budde } 4331f0e21a0SMarc Kleine-Budde priv->rx_ring_num = i; 4341f0e21a0SMarc Kleine-Budde 4351f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4361f0e21a0SMarc Kleine-Budde "FIFO setup: TEF: %d*%d bytes = %d bytes, TX: %d*%d bytes = %d bytes\n", 4371f0e21a0SMarc Kleine-Budde tx_obj_num, tef_obj_size, tef_obj_size * tx_obj_num, 4381f0e21a0SMarc Kleine-Budde tx_obj_num, tx_obj_size, tx_obj_size * tx_obj_num); 4391f0e21a0SMarc Kleine-Budde 4401f0e21a0SMarc Kleine-Budde mcp25xxfd_for_each_rx_ring(priv, rx_ring, i) { 4411f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4421f0e21a0SMarc Kleine-Budde "FIFO setup: RX-%d: %d*%d bytes = %d bytes\n", 4431f0e21a0SMarc Kleine-Budde i, rx_ring->obj_num, rx_ring->obj_size, 4441f0e21a0SMarc Kleine-Budde rx_ring->obj_size * rx_ring->obj_num); 4451f0e21a0SMarc Kleine-Budde } 4461f0e21a0SMarc Kleine-Budde 4471f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 4481f0e21a0SMarc Kleine-Budde "FIFO setup: free: %d bytes\n", 4491f0e21a0SMarc Kleine-Budde ram_free); 4501f0e21a0SMarc Kleine-Budde 4511f0e21a0SMarc Kleine-Budde return 0; 4521f0e21a0SMarc Kleine-Budde } 4531f0e21a0SMarc Kleine-Budde 4541f0e21a0SMarc Kleine-Budde static inline int 4551f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_get_mode(const struct mcp25xxfd_priv *priv, u8 *mode) 4561f0e21a0SMarc Kleine-Budde { 4571f0e21a0SMarc Kleine-Budde u32 val; 4581f0e21a0SMarc Kleine-Budde int err; 4591f0e21a0SMarc Kleine-Budde 4601f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_CON, &val); 4611f0e21a0SMarc Kleine-Budde if (err) 4621f0e21a0SMarc Kleine-Budde return err; 4631f0e21a0SMarc Kleine-Budde 4641f0e21a0SMarc Kleine-Budde *mode = FIELD_GET(MCP25XXFD_REG_CON_OPMOD_MASK, val); 4651f0e21a0SMarc Kleine-Budde 4661f0e21a0SMarc Kleine-Budde return 0; 4671f0e21a0SMarc Kleine-Budde } 4681f0e21a0SMarc Kleine-Budde 4691f0e21a0SMarc Kleine-Budde static int 4701f0e21a0SMarc Kleine-Budde __mcp25xxfd_chip_set_mode(const struct mcp25xxfd_priv *priv, 4711f0e21a0SMarc Kleine-Budde const u8 mode_req, bool nowait) 4721f0e21a0SMarc Kleine-Budde { 4731f0e21a0SMarc Kleine-Budde u32 con, con_reqop; 4741f0e21a0SMarc Kleine-Budde int err; 4751f0e21a0SMarc Kleine-Budde 4761f0e21a0SMarc Kleine-Budde con_reqop = FIELD_PREP(MCP25XXFD_REG_CON_REQOP_MASK, mode_req); 4771f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP25XXFD_REG_CON, 4781f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_CON_REQOP_MASK, con_reqop); 4791f0e21a0SMarc Kleine-Budde if (err) 4801f0e21a0SMarc Kleine-Budde return err; 4811f0e21a0SMarc Kleine-Budde 4821f0e21a0SMarc Kleine-Budde if (mode_req == MCP25XXFD_REG_CON_MODE_SLEEP || nowait) 4831f0e21a0SMarc Kleine-Budde return 0; 4841f0e21a0SMarc Kleine-Budde 4851f0e21a0SMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP25XXFD_REG_CON, con, 4861f0e21a0SMarc Kleine-Budde FIELD_GET(MCP25XXFD_REG_CON_OPMOD_MASK, 4871f0e21a0SMarc Kleine-Budde con) == mode_req, 4881f0e21a0SMarc Kleine-Budde MCP25XXFD_POLL_SLEEP_US, 4891f0e21a0SMarc Kleine-Budde MCP25XXFD_POLL_TIMEOUT_US); 4901f0e21a0SMarc Kleine-Budde if (err) { 4911f0e21a0SMarc Kleine-Budde u8 mode = FIELD_GET(MCP25XXFD_REG_CON_OPMOD_MASK, con); 4921f0e21a0SMarc Kleine-Budde 4931f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 4941f0e21a0SMarc Kleine-Budde "Controller failed to enter mode %s Mode (%u) and stays in %s Mode (%u).\n", 4951f0e21a0SMarc Kleine-Budde mcp25xxfd_get_mode_str(mode_req), mode_req, 4961f0e21a0SMarc Kleine-Budde mcp25xxfd_get_mode_str(mode), mode); 4971f0e21a0SMarc Kleine-Budde return err; 4981f0e21a0SMarc Kleine-Budde } 4991f0e21a0SMarc Kleine-Budde 5001f0e21a0SMarc Kleine-Budde return 0; 5011f0e21a0SMarc Kleine-Budde } 5021f0e21a0SMarc Kleine-Budde 5031f0e21a0SMarc Kleine-Budde static inline int 5041f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_set_mode(const struct mcp25xxfd_priv *priv, 5051f0e21a0SMarc Kleine-Budde const u8 mode_req) 5061f0e21a0SMarc Kleine-Budde { 5071f0e21a0SMarc Kleine-Budde return __mcp25xxfd_chip_set_mode(priv, mode_req, false); 5081f0e21a0SMarc Kleine-Budde } 5091f0e21a0SMarc Kleine-Budde 5101f0e21a0SMarc Kleine-Budde static inline int 5111f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_set_mode_nowait(const struct mcp25xxfd_priv *priv, 5121f0e21a0SMarc Kleine-Budde const u8 mode_req) 5131f0e21a0SMarc Kleine-Budde { 5141f0e21a0SMarc Kleine-Budde return __mcp25xxfd_chip_set_mode(priv, mode_req, true); 5151f0e21a0SMarc Kleine-Budde } 5161f0e21a0SMarc Kleine-Budde 5171f0e21a0SMarc Kleine-Budde static inline bool mcp25xxfd_osc_invalid(u32 reg) 5181f0e21a0SMarc Kleine-Budde { 5191f0e21a0SMarc Kleine-Budde return reg == 0x0 || reg == 0xffffffff; 5201f0e21a0SMarc Kleine-Budde } 5211f0e21a0SMarc Kleine-Budde 5221f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_clock_enable(const struct mcp25xxfd_priv *priv) 5231f0e21a0SMarc Kleine-Budde { 5241f0e21a0SMarc Kleine-Budde u32 osc, osc_reference, osc_mask; 5251f0e21a0SMarc Kleine-Budde int err; 5261f0e21a0SMarc Kleine-Budde 5271f0e21a0SMarc Kleine-Budde /* Set Power On Defaults for "Clock Output Divisor" and remove 5281f0e21a0SMarc Kleine-Budde * "Oscillator Disable" bit. 5291f0e21a0SMarc Kleine-Budde */ 5301f0e21a0SMarc Kleine-Budde osc = FIELD_PREP(MCP25XXFD_REG_OSC_CLKODIV_MASK, 5311f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_OSC_CLKODIV_10); 5321f0e21a0SMarc Kleine-Budde osc_reference = MCP25XXFD_REG_OSC_OSCRDY; 5331f0e21a0SMarc Kleine-Budde osc_mask = MCP25XXFD_REG_OSC_OSCRDY | MCP25XXFD_REG_OSC_PLLRDY; 5341f0e21a0SMarc Kleine-Budde 5351f0e21a0SMarc Kleine-Budde /* Note: 5361f0e21a0SMarc Kleine-Budde * 5371f0e21a0SMarc Kleine-Budde * If the controller is in Sleep Mode the following write only 5381f0e21a0SMarc Kleine-Budde * removes the "Oscillator Disable" bit and powers it up. All 5391f0e21a0SMarc Kleine-Budde * other bits are unaffected. 5401f0e21a0SMarc Kleine-Budde */ 5411f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP25XXFD_REG_OSC, osc); 5421f0e21a0SMarc Kleine-Budde if (err) 5431f0e21a0SMarc Kleine-Budde return err; 5441f0e21a0SMarc Kleine-Budde 5451f0e21a0SMarc Kleine-Budde /* Wait for "Oscillator Ready" bit */ 5461f0e21a0SMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP25XXFD_REG_OSC, osc, 5471f0e21a0SMarc Kleine-Budde (osc & osc_mask) == osc_reference, 5481f0e21a0SMarc Kleine-Budde MCP25XXFD_OSC_STAB_SLEEP_US, 5491f0e21a0SMarc Kleine-Budde MCP25XXFD_OSC_STAB_TIMEOUT_US); 5501f0e21a0SMarc Kleine-Budde if (mcp25xxfd_osc_invalid(osc)) { 5511f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 5521f0e21a0SMarc Kleine-Budde "Failed to detect %s (osc=0x%08x).\n", 5531f0e21a0SMarc Kleine-Budde mcp25xxfd_get_model_str(priv), osc); 5541f0e21a0SMarc Kleine-Budde return -ENODEV; 5551f0e21a0SMarc Kleine-Budde } else if (err == -ETIMEDOUT) { 5561f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 5571f0e21a0SMarc Kleine-Budde "Timeout waiting for Oscillator Ready (osc=0x%08x, osc_reference=0x%08x)\n", 5581f0e21a0SMarc Kleine-Budde osc, osc_reference); 5591f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 5601f0e21a0SMarc Kleine-Budde } else if (err) { 5611f0e21a0SMarc Kleine-Budde return err; 5621f0e21a0SMarc Kleine-Budde } 5631f0e21a0SMarc Kleine-Budde 5641f0e21a0SMarc Kleine-Budde return 0; 5651f0e21a0SMarc Kleine-Budde } 5661f0e21a0SMarc Kleine-Budde 5671f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_softreset_do(const struct mcp25xxfd_priv *priv) 5681f0e21a0SMarc Kleine-Budde { 5691f0e21a0SMarc Kleine-Budde const __be16 cmd = mcp25xxfd_cmd_reset(); 5701f0e21a0SMarc Kleine-Budde int err; 5711f0e21a0SMarc Kleine-Budde 5721f0e21a0SMarc Kleine-Budde /* The Set Mode and SPI Reset command only seems to works if 5731f0e21a0SMarc Kleine-Budde * the controller is not in Sleep Mode. 5741f0e21a0SMarc Kleine-Budde */ 5751f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_clock_enable(priv); 5761f0e21a0SMarc Kleine-Budde if (err) 5771f0e21a0SMarc Kleine-Budde return err; 5781f0e21a0SMarc Kleine-Budde 5791f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_set_mode(priv, MCP25XXFD_REG_CON_MODE_CONFIG); 5801f0e21a0SMarc Kleine-Budde if (err) 5811f0e21a0SMarc Kleine-Budde return err; 5821f0e21a0SMarc Kleine-Budde 5831f0e21a0SMarc Kleine-Budde /* spi_write_then_read() works with non DMA-safe buffers */ 5841f0e21a0SMarc Kleine-Budde return spi_write_then_read(priv->spi, &cmd, sizeof(cmd), NULL, 0); 5851f0e21a0SMarc Kleine-Budde } 5861f0e21a0SMarc Kleine-Budde 5871f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_softreset_check(const struct mcp25xxfd_priv *priv) 5881f0e21a0SMarc Kleine-Budde { 5891f0e21a0SMarc Kleine-Budde u32 osc, osc_reference; 5901f0e21a0SMarc Kleine-Budde u8 mode; 5911f0e21a0SMarc Kleine-Budde int err; 5921f0e21a0SMarc Kleine-Budde 5931f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_get_mode(priv, &mode); 5941f0e21a0SMarc Kleine-Budde if (err) 5951f0e21a0SMarc Kleine-Budde return err; 5961f0e21a0SMarc Kleine-Budde 5971f0e21a0SMarc Kleine-Budde if (mode != MCP25XXFD_REG_CON_MODE_CONFIG) { 5981f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 5991f0e21a0SMarc Kleine-Budde "Controller not in Config Mode after reset, but in %s Mode (%u).\n", 6001f0e21a0SMarc Kleine-Budde mcp25xxfd_get_mode_str(mode), mode); 6011f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6021f0e21a0SMarc Kleine-Budde } 6031f0e21a0SMarc Kleine-Budde 6041f0e21a0SMarc Kleine-Budde osc_reference = MCP25XXFD_REG_OSC_OSCRDY | 6051f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_OSC_CLKODIV_MASK, 6061f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_OSC_CLKODIV_10); 6071f0e21a0SMarc Kleine-Budde 6081f0e21a0SMarc Kleine-Budde /* check reset defaults of OSC reg */ 6091f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_OSC, &osc); 6101f0e21a0SMarc Kleine-Budde if (err) 6111f0e21a0SMarc Kleine-Budde return err; 6121f0e21a0SMarc Kleine-Budde 6131f0e21a0SMarc Kleine-Budde if (osc != osc_reference) { 6141f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 6151f0e21a0SMarc Kleine-Budde "Controller failed to reset. osc=0x%08x, reference value=0x%08x\n", 6161f0e21a0SMarc Kleine-Budde osc, osc_reference); 6171f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6181f0e21a0SMarc Kleine-Budde } 6191f0e21a0SMarc Kleine-Budde 6201f0e21a0SMarc Kleine-Budde return 0; 6211f0e21a0SMarc Kleine-Budde } 6221f0e21a0SMarc Kleine-Budde 6231f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_softreset(const struct mcp25xxfd_priv *priv) 6241f0e21a0SMarc Kleine-Budde { 6251f0e21a0SMarc Kleine-Budde int err, i; 6261f0e21a0SMarc Kleine-Budde 6271f0e21a0SMarc Kleine-Budde for (i = 0; i < MCP25XXFD_SOFTRESET_RETRIES_MAX; i++) { 6281f0e21a0SMarc Kleine-Budde if (i) 6291f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 6301f0e21a0SMarc Kleine-Budde "Retrying to reset Controller.\n"); 6311f0e21a0SMarc Kleine-Budde 6321f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_softreset_do(priv); 6331f0e21a0SMarc Kleine-Budde if (err == -ETIMEDOUT) 6341f0e21a0SMarc Kleine-Budde continue; 6351f0e21a0SMarc Kleine-Budde if (err) 6361f0e21a0SMarc Kleine-Budde return err; 6371f0e21a0SMarc Kleine-Budde 6381f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_softreset_check(priv); 6391f0e21a0SMarc Kleine-Budde if (err == -ETIMEDOUT) 6401f0e21a0SMarc Kleine-Budde continue; 6411f0e21a0SMarc Kleine-Budde if (err) 6421f0e21a0SMarc Kleine-Budde return err; 6431f0e21a0SMarc Kleine-Budde 6441f0e21a0SMarc Kleine-Budde return 0; 6451f0e21a0SMarc Kleine-Budde } 6461f0e21a0SMarc Kleine-Budde 6471f0e21a0SMarc Kleine-Budde if (err) 6481f0e21a0SMarc Kleine-Budde return err; 6491f0e21a0SMarc Kleine-Budde 6501f0e21a0SMarc Kleine-Budde return -ETIMEDOUT; 6511f0e21a0SMarc Kleine-Budde } 6521f0e21a0SMarc Kleine-Budde 6531f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_clock_init(const struct mcp25xxfd_priv *priv) 6541f0e21a0SMarc Kleine-Budde { 6551f0e21a0SMarc Kleine-Budde u32 osc; 6561f0e21a0SMarc Kleine-Budde int err; 6571f0e21a0SMarc Kleine-Budde 6581f0e21a0SMarc Kleine-Budde /* Activate Low Power Mode on Oscillator Disable. This only 6591f0e21a0SMarc Kleine-Budde * works on the MCP2518FD. The MCP2517FD will go into normal 6601f0e21a0SMarc Kleine-Budde * Sleep Mode instead. 6611f0e21a0SMarc Kleine-Budde */ 6621f0e21a0SMarc Kleine-Budde osc = MCP25XXFD_REG_OSC_LPMEN | 6631f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_OSC_CLKODIV_MASK, 6641f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_OSC_CLKODIV_10); 6651f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP25XXFD_REG_OSC, osc); 6661f0e21a0SMarc Kleine-Budde if (err) 6671f0e21a0SMarc Kleine-Budde return err; 6681f0e21a0SMarc Kleine-Budde 6691f0e21a0SMarc Kleine-Budde /* Set Time Base Counter Prescaler to 1. 6701f0e21a0SMarc Kleine-Budde * 6711f0e21a0SMarc Kleine-Budde * This means an overflow of the 32 bit Time Base Counter 6721f0e21a0SMarc Kleine-Budde * register at 40 MHz every 107 seconds. 6731f0e21a0SMarc Kleine-Budde */ 6741f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP25XXFD_REG_TSCON, 6751f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_TSCON_TBCEN); 6761f0e21a0SMarc Kleine-Budde } 6771f0e21a0SMarc Kleine-Budde 6781f0e21a0SMarc Kleine-Budde static int mcp25xxfd_set_bittiming(const struct mcp25xxfd_priv *priv) 6791f0e21a0SMarc Kleine-Budde { 6801f0e21a0SMarc Kleine-Budde const struct can_bittiming *bt = &priv->can.bittiming; 6811f0e21a0SMarc Kleine-Budde const struct can_bittiming *dbt = &priv->can.data_bittiming; 6821f0e21a0SMarc Kleine-Budde u32 val = 0; 6831f0e21a0SMarc Kleine-Budde s8 tdco; 6841f0e21a0SMarc Kleine-Budde int err; 6851f0e21a0SMarc Kleine-Budde 6861f0e21a0SMarc Kleine-Budde /* CAN Control Register 6871f0e21a0SMarc Kleine-Budde * 6881f0e21a0SMarc Kleine-Budde * - no transmit bandwidth sharing 6891f0e21a0SMarc Kleine-Budde * - config mode 6901f0e21a0SMarc Kleine-Budde * - disable transmit queue 6911f0e21a0SMarc Kleine-Budde * - store in transmit FIFO event 6921f0e21a0SMarc Kleine-Budde * - transition to restricted operation mode on system error 6931f0e21a0SMarc Kleine-Budde * - ESI is transmitted recessive when ESI of message is high or 6941f0e21a0SMarc Kleine-Budde * CAN controller error passive 6951f0e21a0SMarc Kleine-Budde * - restricted retransmission attempts, 6961f0e21a0SMarc Kleine-Budde * use TQXCON_TXAT and FIFOCON_TXAT 6971f0e21a0SMarc Kleine-Budde * - wake-up filter bits T11FILTER 6981f0e21a0SMarc Kleine-Budde * - use CAN bus line filter for wakeup 6991f0e21a0SMarc Kleine-Budde * - protocol exception is treated as a form error 7001f0e21a0SMarc Kleine-Budde * - Do not compare data bytes 7011f0e21a0SMarc Kleine-Budde */ 7021f0e21a0SMarc Kleine-Budde val = FIELD_PREP(MCP25XXFD_REG_CON_REQOP_MASK, 7031f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_CON_MODE_CONFIG) | 7041f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_CON_STEF | 7051f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_CON_ESIGM | 7061f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_CON_RTXAT | 7071f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_CON_WFT_MASK, 7081f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_CON_WFT_T11FILTER) | 7091f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_CON_WAKFIL | 7101f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_CON_PXEDIS; 7111f0e21a0SMarc Kleine-Budde 7121f0e21a0SMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)) 7131f0e21a0SMarc Kleine-Budde val |= MCP25XXFD_REG_CON_ISOCRCEN; 7141f0e21a0SMarc Kleine-Budde 7151f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP25XXFD_REG_CON, val); 7161f0e21a0SMarc Kleine-Budde if (err) 7171f0e21a0SMarc Kleine-Budde return err; 7181f0e21a0SMarc Kleine-Budde 7191f0e21a0SMarc Kleine-Budde /* Nominal Bit Time */ 7201f0e21a0SMarc Kleine-Budde val = FIELD_PREP(MCP25XXFD_REG_NBTCFG_BRP_MASK, bt->brp - 1) | 7211f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_NBTCFG_TSEG1_MASK, 7221f0e21a0SMarc Kleine-Budde bt->prop_seg + bt->phase_seg1 - 1) | 7231f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_NBTCFG_TSEG2_MASK, 7241f0e21a0SMarc Kleine-Budde bt->phase_seg2 - 1) | 7251f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_NBTCFG_SJW_MASK, bt->sjw - 1); 7261f0e21a0SMarc Kleine-Budde 7271f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP25XXFD_REG_NBTCFG, val); 7281f0e21a0SMarc Kleine-Budde if (err) 7291f0e21a0SMarc Kleine-Budde return err; 7301f0e21a0SMarc Kleine-Budde 7311f0e21a0SMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD)) 7321f0e21a0SMarc Kleine-Budde return 0; 7331f0e21a0SMarc Kleine-Budde 7341f0e21a0SMarc Kleine-Budde /* Data Bit Time */ 7351f0e21a0SMarc Kleine-Budde val = FIELD_PREP(MCP25XXFD_REG_DBTCFG_BRP_MASK, dbt->brp - 1) | 7361f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_DBTCFG_TSEG1_MASK, 7371f0e21a0SMarc Kleine-Budde dbt->prop_seg + dbt->phase_seg1 - 1) | 7381f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_DBTCFG_TSEG2_MASK, 7391f0e21a0SMarc Kleine-Budde dbt->phase_seg2 - 1) | 7401f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_DBTCFG_SJW_MASK, dbt->sjw - 1); 7411f0e21a0SMarc Kleine-Budde 7421f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP25XXFD_REG_DBTCFG, val); 7431f0e21a0SMarc Kleine-Budde if (err) 7441f0e21a0SMarc Kleine-Budde return err; 7451f0e21a0SMarc Kleine-Budde 7461f0e21a0SMarc Kleine-Budde /* Transmitter Delay Compensation */ 7471f0e21a0SMarc Kleine-Budde tdco = clamp_t(int, dbt->brp * (dbt->prop_seg + dbt->phase_seg1), 7481f0e21a0SMarc Kleine-Budde -64, 63); 7491f0e21a0SMarc Kleine-Budde val = FIELD_PREP(MCP25XXFD_REG_TDC_TDCMOD_MASK, 7501f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_TDC_TDCMOD_AUTO) | 7511f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_TDC_TDCO_MASK, tdco); 7521f0e21a0SMarc Kleine-Budde 7531f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP25XXFD_REG_TDC, val); 7541f0e21a0SMarc Kleine-Budde } 7551f0e21a0SMarc Kleine-Budde 7561f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_rx_int_enable(const struct mcp25xxfd_priv *priv) 7571f0e21a0SMarc Kleine-Budde { 7581f0e21a0SMarc Kleine-Budde u32 val; 7591f0e21a0SMarc Kleine-Budde 7601f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 7611f0e21a0SMarc Kleine-Budde return 0; 7621f0e21a0SMarc Kleine-Budde 7631f0e21a0SMarc Kleine-Budde /* Configure GPIOs: 7641f0e21a0SMarc Kleine-Budde * - PIN0: GPIO Input 7651f0e21a0SMarc Kleine-Budde * - PIN1: GPIO Input/RX Interrupt 7661f0e21a0SMarc Kleine-Budde * 7671f0e21a0SMarc Kleine-Budde * PIN1 must be Input, otherwise there is a glitch on the 7681f0e21a0SMarc Kleine-Budde * rx-INT line. It happens between setting the PIN as output 7691f0e21a0SMarc Kleine-Budde * (in the first byte of the SPI transfer) and configuring the 7701f0e21a0SMarc Kleine-Budde * PIN as interrupt (in the last byte of the SPI transfer). 7711f0e21a0SMarc Kleine-Budde */ 7721f0e21a0SMarc Kleine-Budde val = MCP25XXFD_REG_IOCON_PM0 | MCP25XXFD_REG_IOCON_TRIS1 | 7731f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_IOCON_TRIS0; 7741f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP25XXFD_REG_IOCON, val); 7751f0e21a0SMarc Kleine-Budde } 7761f0e21a0SMarc Kleine-Budde 7771f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_rx_int_disable(const struct mcp25xxfd_priv *priv) 7781f0e21a0SMarc Kleine-Budde { 7791f0e21a0SMarc Kleine-Budde u32 val; 7801f0e21a0SMarc Kleine-Budde 7811f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 7821f0e21a0SMarc Kleine-Budde return 0; 7831f0e21a0SMarc Kleine-Budde 7841f0e21a0SMarc Kleine-Budde /* Configure GPIOs: 7851f0e21a0SMarc Kleine-Budde * - PIN0: GPIO Input 7861f0e21a0SMarc Kleine-Budde * - PIN1: GPIO Input 7871f0e21a0SMarc Kleine-Budde */ 7881f0e21a0SMarc Kleine-Budde val = MCP25XXFD_REG_IOCON_PM1 | MCP25XXFD_REG_IOCON_PM0 | 7891f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_IOCON_TRIS1 | MCP25XXFD_REG_IOCON_TRIS0; 7901f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP25XXFD_REG_IOCON, val); 7911f0e21a0SMarc Kleine-Budde } 7921f0e21a0SMarc Kleine-Budde 7931f0e21a0SMarc Kleine-Budde static int 7941f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_rx_fifo_init_one(const struct mcp25xxfd_priv *priv, 7951f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_rx_ring *ring) 7961f0e21a0SMarc Kleine-Budde { 7971f0e21a0SMarc Kleine-Budde u32 fifo_con; 7981f0e21a0SMarc Kleine-Budde 7991f0e21a0SMarc Kleine-Budde /* Enable RXOVIE on _all_ RX FIFOs, not just the last one. 8001f0e21a0SMarc Kleine-Budde * 8011f0e21a0SMarc Kleine-Budde * FIFOs hit by a RX MAB overflow and RXOVIE enabled will 8021f0e21a0SMarc Kleine-Budde * generate a RXOVIF, use this to properly detect RX MAB 8031f0e21a0SMarc Kleine-Budde * overflows. 8041f0e21a0SMarc Kleine-Budde */ 8051f0e21a0SMarc Kleine-Budde fifo_con = FIELD_PREP(MCP25XXFD_REG_FIFOCON_FSIZE_MASK, 8061f0e21a0SMarc Kleine-Budde ring->obj_num - 1) | 8071f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_RXTSEN | 8081f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_RXOVIE | 8091f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_TFNRFNIE; 8101f0e21a0SMarc Kleine-Budde 8111f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) 8121f0e21a0SMarc Kleine-Budde fifo_con |= FIELD_PREP(MCP25XXFD_REG_FIFOCON_PLSIZE_MASK, 8131f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_PLSIZE_64); 8141f0e21a0SMarc Kleine-Budde else 8151f0e21a0SMarc Kleine-Budde fifo_con |= FIELD_PREP(MCP25XXFD_REG_FIFOCON_PLSIZE_MASK, 8161f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_PLSIZE_8); 8171f0e21a0SMarc Kleine-Budde 8181f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, 8191f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON(ring->fifo_nr), fifo_con); 8201f0e21a0SMarc Kleine-Budde } 8211f0e21a0SMarc Kleine-Budde 8221f0e21a0SMarc Kleine-Budde static int 8231f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_rx_filter_init_one(const struct mcp25xxfd_priv *priv, 8241f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_rx_ring *ring) 8251f0e21a0SMarc Kleine-Budde { 8261f0e21a0SMarc Kleine-Budde u32 fltcon; 8271f0e21a0SMarc Kleine-Budde 8281f0e21a0SMarc Kleine-Budde fltcon = MCP25XXFD_REG_FLTCON_FLTEN(ring->nr) | 8291f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FLTCON_FBP(ring->nr, ring->fifo_nr); 8301f0e21a0SMarc Kleine-Budde 8311f0e21a0SMarc Kleine-Budde return regmap_update_bits(priv->map_reg, 8321f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FLTCON(ring->nr >> 2), 8331f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FLTCON_FLT_MASK(ring->nr), 8341f0e21a0SMarc Kleine-Budde fltcon); 8351f0e21a0SMarc Kleine-Budde } 8361f0e21a0SMarc Kleine-Budde 8371f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_fifo_init(const struct mcp25xxfd_priv *priv) 8381f0e21a0SMarc Kleine-Budde { 8391f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_tx_ring *tx_ring = priv->tx; 8401f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_rx_ring *rx_ring; 8411f0e21a0SMarc Kleine-Budde u32 val; 8421f0e21a0SMarc Kleine-Budde int err, n; 8431f0e21a0SMarc Kleine-Budde 8441f0e21a0SMarc Kleine-Budde /* TEF */ 8451f0e21a0SMarc Kleine-Budde val = FIELD_PREP(MCP25XXFD_REG_TEFCON_FSIZE_MASK, 8461f0e21a0SMarc Kleine-Budde tx_ring->obj_num - 1) | 8471f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_TEFCON_TEFTSEN | 8481f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_TEFCON_TEFOVIE | 8491f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_TEFCON_TEFNEIE; 8501f0e21a0SMarc Kleine-Budde 8511f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP25XXFD_REG_TEFCON, val); 8521f0e21a0SMarc Kleine-Budde if (err) 8531f0e21a0SMarc Kleine-Budde return err; 8541f0e21a0SMarc Kleine-Budde 8551f0e21a0SMarc Kleine-Budde /* FIFO 1 - TX */ 8561f0e21a0SMarc Kleine-Budde val = FIELD_PREP(MCP25XXFD_REG_FIFOCON_FSIZE_MASK, 8571f0e21a0SMarc Kleine-Budde tx_ring->obj_num - 1) | 8581f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_TXEN | 8591f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_TXATIE; 8601f0e21a0SMarc Kleine-Budde 8611f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) 8621f0e21a0SMarc Kleine-Budde val |= FIELD_PREP(MCP25XXFD_REG_FIFOCON_PLSIZE_MASK, 8631f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_PLSIZE_64); 8641f0e21a0SMarc Kleine-Budde else 8651f0e21a0SMarc Kleine-Budde val |= FIELD_PREP(MCP25XXFD_REG_FIFOCON_PLSIZE_MASK, 8661f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_PLSIZE_8); 8671f0e21a0SMarc Kleine-Budde 8681f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) 8691f0e21a0SMarc Kleine-Budde val |= FIELD_PREP(MCP25XXFD_REG_FIFOCON_TXAT_MASK, 8701f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_TXAT_ONE_SHOT); 8711f0e21a0SMarc Kleine-Budde else 8721f0e21a0SMarc Kleine-Budde val |= FIELD_PREP(MCP25XXFD_REG_FIFOCON_TXAT_MASK, 8731f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_TXAT_UNLIMITED); 8741f0e21a0SMarc Kleine-Budde 8751f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, 8761f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON(MCP25XXFD_TX_FIFO), 8771f0e21a0SMarc Kleine-Budde val); 8781f0e21a0SMarc Kleine-Budde if (err) 8791f0e21a0SMarc Kleine-Budde return err; 8801f0e21a0SMarc Kleine-Budde 8811f0e21a0SMarc Kleine-Budde /* RX FIFOs */ 8821f0e21a0SMarc Kleine-Budde mcp25xxfd_for_each_rx_ring(priv, rx_ring, n) { 8831f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_rx_fifo_init_one(priv, rx_ring); 8841f0e21a0SMarc Kleine-Budde if (err) 8851f0e21a0SMarc Kleine-Budde return err; 8861f0e21a0SMarc Kleine-Budde 8871f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_rx_filter_init_one(priv, rx_ring); 8881f0e21a0SMarc Kleine-Budde if (err) 8891f0e21a0SMarc Kleine-Budde return err; 8901f0e21a0SMarc Kleine-Budde } 8911f0e21a0SMarc Kleine-Budde 8921f0e21a0SMarc Kleine-Budde return 0; 8931f0e21a0SMarc Kleine-Budde } 8941f0e21a0SMarc Kleine-Budde 8951f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_ecc_init(struct mcp25xxfd_priv *priv) 8961f0e21a0SMarc Kleine-Budde { 8971f0e21a0SMarc Kleine-Budde struct mcp25xxfd_ecc *ecc = &priv->ecc; 8981f0e21a0SMarc Kleine-Budde void *ram; 8991f0e21a0SMarc Kleine-Budde u32 val = 0; 9001f0e21a0SMarc Kleine-Budde int err; 9011f0e21a0SMarc Kleine-Budde 9021f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 9031f0e21a0SMarc Kleine-Budde 9041f0e21a0SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_ECC) 9051f0e21a0SMarc Kleine-Budde val = MCP25XXFD_REG_ECCCON_ECCEN; 9061f0e21a0SMarc Kleine-Budde 9071f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP25XXFD_REG_ECCCON, 9081f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_ECCCON_ECCEN, val); 9091f0e21a0SMarc Kleine-Budde if (err) 9101f0e21a0SMarc Kleine-Budde return err; 9111f0e21a0SMarc Kleine-Budde 9121f0e21a0SMarc Kleine-Budde ram = kzalloc(MCP25XXFD_RAM_SIZE, GFP_KERNEL); 9131f0e21a0SMarc Kleine-Budde if (!ram) 9141f0e21a0SMarc Kleine-Budde return -ENOMEM; 9151f0e21a0SMarc Kleine-Budde 9161f0e21a0SMarc Kleine-Budde err = regmap_raw_write(priv->map_reg, MCP25XXFD_RAM_START, ram, 9171f0e21a0SMarc Kleine-Budde MCP25XXFD_RAM_SIZE); 9181f0e21a0SMarc Kleine-Budde kfree(ram); 9191f0e21a0SMarc Kleine-Budde 9201f0e21a0SMarc Kleine-Budde return err; 9211f0e21a0SMarc Kleine-Budde } 9221f0e21a0SMarc Kleine-Budde 9231f0e21a0SMarc Kleine-Budde static inline void mcp25xxfd_ecc_tefif_successful(struct mcp25xxfd_priv *priv) 9241f0e21a0SMarc Kleine-Budde { 9251f0e21a0SMarc Kleine-Budde struct mcp25xxfd_ecc *ecc = &priv->ecc; 9261f0e21a0SMarc Kleine-Budde 9271f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 9281f0e21a0SMarc Kleine-Budde } 9291f0e21a0SMarc Kleine-Budde 9301f0e21a0SMarc Kleine-Budde static u8 mcp25xxfd_get_normal_mode(const struct mcp25xxfd_priv *priv) 9311f0e21a0SMarc Kleine-Budde { 9321f0e21a0SMarc Kleine-Budde u8 mode; 9331f0e21a0SMarc Kleine-Budde 9341f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 9351f0e21a0SMarc Kleine-Budde mode = MCP25XXFD_REG_CON_MODE_LISTENONLY; 9361f0e21a0SMarc Kleine-Budde else if (priv->can.ctrlmode & CAN_CTRLMODE_FD) 9371f0e21a0SMarc Kleine-Budde mode = MCP25XXFD_REG_CON_MODE_MIXED; 9381f0e21a0SMarc Kleine-Budde else 9391f0e21a0SMarc Kleine-Budde mode = MCP25XXFD_REG_CON_MODE_CAN2_0; 9401f0e21a0SMarc Kleine-Budde 9411f0e21a0SMarc Kleine-Budde return mode; 9421f0e21a0SMarc Kleine-Budde } 9431f0e21a0SMarc Kleine-Budde 9441f0e21a0SMarc Kleine-Budde static int 9451f0e21a0SMarc Kleine-Budde __mcp25xxfd_chip_set_normal_mode(const struct mcp25xxfd_priv *priv, 9461f0e21a0SMarc Kleine-Budde bool nowait) 9471f0e21a0SMarc Kleine-Budde { 9481f0e21a0SMarc Kleine-Budde u8 mode; 9491f0e21a0SMarc Kleine-Budde 9501f0e21a0SMarc Kleine-Budde mode = mcp25xxfd_get_normal_mode(priv); 9511f0e21a0SMarc Kleine-Budde 9521f0e21a0SMarc Kleine-Budde return __mcp25xxfd_chip_set_mode(priv, mode, nowait); 9531f0e21a0SMarc Kleine-Budde } 9541f0e21a0SMarc Kleine-Budde 9551f0e21a0SMarc Kleine-Budde static inline int 9561f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_set_normal_mode(const struct mcp25xxfd_priv *priv) 9571f0e21a0SMarc Kleine-Budde { 9581f0e21a0SMarc Kleine-Budde return __mcp25xxfd_chip_set_normal_mode(priv, false); 9591f0e21a0SMarc Kleine-Budde } 9601f0e21a0SMarc Kleine-Budde 9611f0e21a0SMarc Kleine-Budde static inline int 9621f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_set_normal_mode_nowait(const struct mcp25xxfd_priv *priv) 9631f0e21a0SMarc Kleine-Budde { 9641f0e21a0SMarc Kleine-Budde return __mcp25xxfd_chip_set_normal_mode(priv, true); 9651f0e21a0SMarc Kleine-Budde } 9661f0e21a0SMarc Kleine-Budde 9671f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_interrupts_enable(const struct mcp25xxfd_priv *priv) 9681f0e21a0SMarc Kleine-Budde { 9691f0e21a0SMarc Kleine-Budde u32 val; 9701f0e21a0SMarc Kleine-Budde int err; 9711f0e21a0SMarc Kleine-Budde 9721f0e21a0SMarc Kleine-Budde val = MCP25XXFD_REG_CRC_FERRIE | MCP25XXFD_REG_CRC_CRCERRIE; 9731f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP25XXFD_REG_CRC, val); 9741f0e21a0SMarc Kleine-Budde if (err) 9751f0e21a0SMarc Kleine-Budde return err; 9761f0e21a0SMarc Kleine-Budde 9771f0e21a0SMarc Kleine-Budde val = MCP25XXFD_REG_ECCCON_DEDIE | MCP25XXFD_REG_ECCCON_SECIE; 9781f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP25XXFD_REG_ECCCON, val, val); 9791f0e21a0SMarc Kleine-Budde if (err) 9801f0e21a0SMarc Kleine-Budde return err; 9811f0e21a0SMarc Kleine-Budde 9821f0e21a0SMarc Kleine-Budde val = MCP25XXFD_REG_INT_CERRIE | 9831f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_SERRIE | 9841f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_RXOVIE | 9851f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_TXATIE | 9861f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_SPICRCIE | 9871f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_ECCIE | 9881f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_TEFIE | 9891f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_MODIE | 9901f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_RXIE; 9911f0e21a0SMarc Kleine-Budde 9921f0e21a0SMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) 9931f0e21a0SMarc Kleine-Budde val |= MCP25XXFD_REG_INT_IVMIE; 9941f0e21a0SMarc Kleine-Budde 9951f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP25XXFD_REG_INT, val); 9961f0e21a0SMarc Kleine-Budde } 9971f0e21a0SMarc Kleine-Budde 9981f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_interrupts_disable(const struct mcp25xxfd_priv *priv) 9991f0e21a0SMarc Kleine-Budde { 10001f0e21a0SMarc Kleine-Budde int err; 10011f0e21a0SMarc Kleine-Budde u32 mask; 10021f0e21a0SMarc Kleine-Budde 10031f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP25XXFD_REG_INT, 0); 10041f0e21a0SMarc Kleine-Budde if (err) 10051f0e21a0SMarc Kleine-Budde return err; 10061f0e21a0SMarc Kleine-Budde 10071f0e21a0SMarc Kleine-Budde mask = MCP25XXFD_REG_ECCCON_DEDIE | MCP25XXFD_REG_ECCCON_SECIE; 10081f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP25XXFD_REG_ECCCON, 10091f0e21a0SMarc Kleine-Budde mask, 0x0); 10101f0e21a0SMarc Kleine-Budde if (err) 10111f0e21a0SMarc Kleine-Budde return err; 10121f0e21a0SMarc Kleine-Budde 10131f0e21a0SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP25XXFD_REG_CRC, 0); 10141f0e21a0SMarc Kleine-Budde } 10151f0e21a0SMarc Kleine-Budde 10161f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_stop(struct mcp25xxfd_priv *priv, 10171f0e21a0SMarc Kleine-Budde const enum can_state state) 10181f0e21a0SMarc Kleine-Budde { 10191f0e21a0SMarc Kleine-Budde priv->can.state = state; 10201f0e21a0SMarc Kleine-Budde 10211f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_interrupts_disable(priv); 10221f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_rx_int_disable(priv); 10231f0e21a0SMarc Kleine-Budde return mcp25xxfd_chip_set_mode(priv, MCP25XXFD_REG_CON_MODE_SLEEP); 10241f0e21a0SMarc Kleine-Budde } 10251f0e21a0SMarc Kleine-Budde 10261f0e21a0SMarc Kleine-Budde static int mcp25xxfd_chip_start(struct mcp25xxfd_priv *priv) 10271f0e21a0SMarc Kleine-Budde { 10281f0e21a0SMarc Kleine-Budde int err; 10291f0e21a0SMarc Kleine-Budde 10301f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_softreset(priv); 10311f0e21a0SMarc Kleine-Budde if (err) 10321f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10331f0e21a0SMarc Kleine-Budde 10341f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_clock_init(priv); 10351f0e21a0SMarc Kleine-Budde if (err) 10361f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10371f0e21a0SMarc Kleine-Budde 10381f0e21a0SMarc Kleine-Budde err = mcp25xxfd_set_bittiming(priv); 10391f0e21a0SMarc Kleine-Budde if (err) 10401f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10411f0e21a0SMarc Kleine-Budde 10421f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_rx_int_enable(priv); 10431f0e21a0SMarc Kleine-Budde if (err) 10441f0e21a0SMarc Kleine-Budde return err; 10451f0e21a0SMarc Kleine-Budde 10461f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_ecc_init(priv); 10471f0e21a0SMarc Kleine-Budde if (err) 10481f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10491f0e21a0SMarc Kleine-Budde 10501f0e21a0SMarc Kleine-Budde mcp25xxfd_ring_init(priv); 10511f0e21a0SMarc Kleine-Budde 10521f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_fifo_init(priv); 10531f0e21a0SMarc Kleine-Budde if (err) 10541f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10551f0e21a0SMarc Kleine-Budde 10561f0e21a0SMarc Kleine-Budde priv->can.state = CAN_STATE_ERROR_ACTIVE; 10571f0e21a0SMarc Kleine-Budde 10581f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_set_normal_mode(priv); 10591f0e21a0SMarc Kleine-Budde if (err) 10601f0e21a0SMarc Kleine-Budde goto out_chip_stop; 10611f0e21a0SMarc Kleine-Budde 10621f0e21a0SMarc Kleine-Budde return 0; 10631f0e21a0SMarc Kleine-Budde 10641f0e21a0SMarc Kleine-Budde out_chip_stop: 10651f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_stop(priv, CAN_STATE_STOPPED); 10661f0e21a0SMarc Kleine-Budde 10671f0e21a0SMarc Kleine-Budde return err; 10681f0e21a0SMarc Kleine-Budde } 10691f0e21a0SMarc Kleine-Budde 10701f0e21a0SMarc Kleine-Budde static int mcp25xxfd_set_mode(struct net_device *ndev, enum can_mode mode) 10711f0e21a0SMarc Kleine-Budde { 10721f0e21a0SMarc Kleine-Budde struct mcp25xxfd_priv *priv = netdev_priv(ndev); 10731f0e21a0SMarc Kleine-Budde int err; 10741f0e21a0SMarc Kleine-Budde 10751f0e21a0SMarc Kleine-Budde switch (mode) { 10761f0e21a0SMarc Kleine-Budde case CAN_MODE_START: 10771f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_start(priv); 10781f0e21a0SMarc Kleine-Budde if (err) 10791f0e21a0SMarc Kleine-Budde return err; 10801f0e21a0SMarc Kleine-Budde 10811f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_interrupts_enable(priv); 10821f0e21a0SMarc Kleine-Budde if (err) { 10831f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_stop(priv, CAN_STATE_STOPPED); 10841f0e21a0SMarc Kleine-Budde return err; 10851f0e21a0SMarc Kleine-Budde } 10861f0e21a0SMarc Kleine-Budde 10871f0e21a0SMarc Kleine-Budde netif_wake_queue(ndev); 10881f0e21a0SMarc Kleine-Budde break; 10891f0e21a0SMarc Kleine-Budde 10901f0e21a0SMarc Kleine-Budde default: 10911f0e21a0SMarc Kleine-Budde return -EOPNOTSUPP; 10921f0e21a0SMarc Kleine-Budde } 10931f0e21a0SMarc Kleine-Budde 10941f0e21a0SMarc Kleine-Budde return 0; 10951f0e21a0SMarc Kleine-Budde } 10961f0e21a0SMarc Kleine-Budde 10971f0e21a0SMarc Kleine-Budde static int __mcp25xxfd_get_berr_counter(const struct net_device *ndev, 10981f0e21a0SMarc Kleine-Budde struct can_berr_counter *bec) 10991f0e21a0SMarc Kleine-Budde { 11001f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_priv *priv = netdev_priv(ndev); 11011f0e21a0SMarc Kleine-Budde u32 trec; 11021f0e21a0SMarc Kleine-Budde int err; 11031f0e21a0SMarc Kleine-Budde 11041f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_TREC, &trec); 11051f0e21a0SMarc Kleine-Budde if (err) 11061f0e21a0SMarc Kleine-Budde return err; 11071f0e21a0SMarc Kleine-Budde 11081f0e21a0SMarc Kleine-Budde if (trec & MCP25XXFD_REG_TREC_TXBO) 11091f0e21a0SMarc Kleine-Budde bec->txerr = 256; 11101f0e21a0SMarc Kleine-Budde else 11111f0e21a0SMarc Kleine-Budde bec->txerr = FIELD_GET(MCP25XXFD_REG_TREC_TEC_MASK, trec); 11121f0e21a0SMarc Kleine-Budde bec->rxerr = FIELD_GET(MCP25XXFD_REG_TREC_REC_MASK, trec); 11131f0e21a0SMarc Kleine-Budde 11141f0e21a0SMarc Kleine-Budde return 0; 11151f0e21a0SMarc Kleine-Budde } 11161f0e21a0SMarc Kleine-Budde 11171f0e21a0SMarc Kleine-Budde static int mcp25xxfd_get_berr_counter(const struct net_device *ndev, 11181f0e21a0SMarc Kleine-Budde struct can_berr_counter *bec) 11191f0e21a0SMarc Kleine-Budde { 11201f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_priv *priv = netdev_priv(ndev); 11211f0e21a0SMarc Kleine-Budde 11221f0e21a0SMarc Kleine-Budde /* Avoid waking up the controller if the interface is down */ 11231f0e21a0SMarc Kleine-Budde if (!(ndev->flags & IFF_UP)) 11241f0e21a0SMarc Kleine-Budde return 0; 11251f0e21a0SMarc Kleine-Budde 11261f0e21a0SMarc Kleine-Budde /* The controller is powered down during Bus Off, use saved 11271f0e21a0SMarc Kleine-Budde * bec values. 11281f0e21a0SMarc Kleine-Budde */ 11291f0e21a0SMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) { 11301f0e21a0SMarc Kleine-Budde *bec = priv->bec; 11311f0e21a0SMarc Kleine-Budde return 0; 11321f0e21a0SMarc Kleine-Budde } 11331f0e21a0SMarc Kleine-Budde 11341f0e21a0SMarc Kleine-Budde return __mcp25xxfd_get_berr_counter(ndev, bec); 11351f0e21a0SMarc Kleine-Budde } 11361f0e21a0SMarc Kleine-Budde 11371f0e21a0SMarc Kleine-Budde static int mcp25xxfd_check_tef_tail(const struct mcp25xxfd_priv *priv) 11381f0e21a0SMarc Kleine-Budde { 11391f0e21a0SMarc Kleine-Budde u8 tef_tail_chip, tef_tail; 11401f0e21a0SMarc Kleine-Budde int err; 11411f0e21a0SMarc Kleine-Budde 11421f0e21a0SMarc Kleine-Budde if (!IS_ENABLED(CONFIG_CAN_MCP25XXFD_SANITY)) 11431f0e21a0SMarc Kleine-Budde return 0; 11441f0e21a0SMarc Kleine-Budde 11451f0e21a0SMarc Kleine-Budde err = mcp25xxfd_tef_tail_get_from_chip(priv, &tef_tail_chip); 11461f0e21a0SMarc Kleine-Budde if (err) 11471f0e21a0SMarc Kleine-Budde return err; 11481f0e21a0SMarc Kleine-Budde 11491f0e21a0SMarc Kleine-Budde tef_tail = mcp25xxfd_get_tef_tail(priv); 11501f0e21a0SMarc Kleine-Budde if (tef_tail_chip != tef_tail) { 11511f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 11521f0e21a0SMarc Kleine-Budde "TEF tail of chip (0x%02x) and ours (0x%08x) inconsistent.\n", 11531f0e21a0SMarc Kleine-Budde tef_tail_chip, tef_tail); 11541f0e21a0SMarc Kleine-Budde return -EILSEQ; 11551f0e21a0SMarc Kleine-Budde } 11561f0e21a0SMarc Kleine-Budde 11571f0e21a0SMarc Kleine-Budde return 0; 11581f0e21a0SMarc Kleine-Budde } 11591f0e21a0SMarc Kleine-Budde 11601f0e21a0SMarc Kleine-Budde static int 11611f0e21a0SMarc Kleine-Budde mcp25xxfd_check_rx_tail(const struct mcp25xxfd_priv *priv, 11621f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_rx_ring *ring) 11631f0e21a0SMarc Kleine-Budde { 11641f0e21a0SMarc Kleine-Budde u8 rx_tail_chip, rx_tail; 11651f0e21a0SMarc Kleine-Budde int err; 11661f0e21a0SMarc Kleine-Budde 11671f0e21a0SMarc Kleine-Budde if (!IS_ENABLED(CONFIG_CAN_MCP25XXFD_SANITY)) 11681f0e21a0SMarc Kleine-Budde return 0; 11691f0e21a0SMarc Kleine-Budde 11701f0e21a0SMarc Kleine-Budde err = mcp25xxfd_rx_tail_get_from_chip(priv, ring, &rx_tail_chip); 11711f0e21a0SMarc Kleine-Budde if (err) 11721f0e21a0SMarc Kleine-Budde return err; 11731f0e21a0SMarc Kleine-Budde 11741f0e21a0SMarc Kleine-Budde rx_tail = mcp25xxfd_get_rx_tail(ring); 11751f0e21a0SMarc Kleine-Budde if (rx_tail_chip != rx_tail) { 11761f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 11771f0e21a0SMarc Kleine-Budde "RX tail of chip (%d) and ours (%d) inconsistent.\n", 11781f0e21a0SMarc Kleine-Budde rx_tail_chip, rx_tail); 11791f0e21a0SMarc Kleine-Budde return -EILSEQ; 11801f0e21a0SMarc Kleine-Budde } 11811f0e21a0SMarc Kleine-Budde 11821f0e21a0SMarc Kleine-Budde return 0; 11831f0e21a0SMarc Kleine-Budde } 11841f0e21a0SMarc Kleine-Budde 11851f0e21a0SMarc Kleine-Budde static int 11861f0e21a0SMarc Kleine-Budde mcp25xxfd_handle_tefif_recover(const struct mcp25xxfd_priv *priv, const u32 seq) 11871f0e21a0SMarc Kleine-Budde { 11881f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_tx_ring *tx_ring = priv->tx; 11891f0e21a0SMarc Kleine-Budde u32 tef_sta; 11901f0e21a0SMarc Kleine-Budde int err; 11911f0e21a0SMarc Kleine-Budde 11921f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_TEFSTA, &tef_sta); 11931f0e21a0SMarc Kleine-Budde if (err) 11941f0e21a0SMarc Kleine-Budde return err; 11951f0e21a0SMarc Kleine-Budde 11961f0e21a0SMarc Kleine-Budde if (tef_sta & MCP25XXFD_REG_TEFSTA_TEFOVIF) { 11971f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 11981f0e21a0SMarc Kleine-Budde "Transmit Event FIFO buffer overflow.\n"); 11991f0e21a0SMarc Kleine-Budde return -ENOBUFS; 12001f0e21a0SMarc Kleine-Budde } 12011f0e21a0SMarc Kleine-Budde 12021f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 12031f0e21a0SMarc Kleine-Budde "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x)\n", 12041f0e21a0SMarc Kleine-Budde tef_sta & MCP25XXFD_REG_TEFSTA_TEFFIF ? 12051f0e21a0SMarc Kleine-Budde "full" : tef_sta & MCP25XXFD_REG_TEFSTA_TEFNEIF ? 12061f0e21a0SMarc Kleine-Budde "not empty" : "empty", 12071f0e21a0SMarc Kleine-Budde seq, priv->tef.tail, priv->tef.head, tx_ring->head); 12081f0e21a0SMarc Kleine-Budde 12091f0e21a0SMarc Kleine-Budde /* The Sequence Number in the TEF doesn't match our tef_tail. */ 12101f0e21a0SMarc Kleine-Budde return -EAGAIN; 12111f0e21a0SMarc Kleine-Budde } 12121f0e21a0SMarc Kleine-Budde 12131f0e21a0SMarc Kleine-Budde static int 12141f0e21a0SMarc Kleine-Budde mcp25xxfd_handle_tefif_one(struct mcp25xxfd_priv *priv, 12151f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_hw_tef_obj *hw_tef_obj) 12161f0e21a0SMarc Kleine-Budde { 12171f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_ring *tx_ring = priv->tx; 12181f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 12191f0e21a0SMarc Kleine-Budde u32 seq, seq_masked, tef_tail_masked; 12201f0e21a0SMarc Kleine-Budde int err; 12211f0e21a0SMarc Kleine-Budde 12221f0e21a0SMarc Kleine-Budde seq = FIELD_GET(MCP25XXFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, 12231f0e21a0SMarc Kleine-Budde hw_tef_obj->flags); 12241f0e21a0SMarc Kleine-Budde 12251f0e21a0SMarc Kleine-Budde /* Use the MCP2517FD mask on the MCP2518FD, too. We only 12261f0e21a0SMarc Kleine-Budde * compare 7 bits, this should be enough to detect 12271f0e21a0SMarc Kleine-Budde * net-yet-completed, i.e. old TEF objects. 12281f0e21a0SMarc Kleine-Budde */ 12291f0e21a0SMarc Kleine-Budde seq_masked = seq & 12301f0e21a0SMarc Kleine-Budde field_mask(MCP25XXFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 12311f0e21a0SMarc Kleine-Budde tef_tail_masked = priv->tef.tail & 12321f0e21a0SMarc Kleine-Budde field_mask(MCP25XXFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK); 12331f0e21a0SMarc Kleine-Budde if (seq_masked != tef_tail_masked) 12341f0e21a0SMarc Kleine-Budde return mcp25xxfd_handle_tefif_recover(priv, seq); 12351f0e21a0SMarc Kleine-Budde 12361f0e21a0SMarc Kleine-Budde stats->tx_bytes += 12371f0e21a0SMarc Kleine-Budde can_rx_offload_get_echo_skb(&priv->offload, 12381f0e21a0SMarc Kleine-Budde mcp25xxfd_get_tef_tail(priv), 12391f0e21a0SMarc Kleine-Budde hw_tef_obj->ts); 12401f0e21a0SMarc Kleine-Budde stats->tx_packets++; 12411f0e21a0SMarc Kleine-Budde 12421f0e21a0SMarc Kleine-Budde /* finally increment the TEF pointer */ 12431f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP25XXFD_REG_TEFCON, 12441f0e21a0SMarc Kleine-Budde GENMASK(15, 8), 12451f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_TEFCON_UINC); 12461f0e21a0SMarc Kleine-Budde if (err) 12471f0e21a0SMarc Kleine-Budde return err; 12481f0e21a0SMarc Kleine-Budde 12491f0e21a0SMarc Kleine-Budde priv->tef.tail++; 12501f0e21a0SMarc Kleine-Budde tx_ring->tail++; 12511f0e21a0SMarc Kleine-Budde 12521f0e21a0SMarc Kleine-Budde return mcp25xxfd_check_tef_tail(priv); 12531f0e21a0SMarc Kleine-Budde } 12541f0e21a0SMarc Kleine-Budde 12551f0e21a0SMarc Kleine-Budde static int mcp25xxfd_tef_ring_update(struct mcp25xxfd_priv *priv) 12561f0e21a0SMarc Kleine-Budde { 12571f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_tx_ring *tx_ring = priv->tx; 12581f0e21a0SMarc Kleine-Budde unsigned int new_head; 12591f0e21a0SMarc Kleine-Budde u8 chip_tx_tail; 12601f0e21a0SMarc Kleine-Budde int err; 12611f0e21a0SMarc Kleine-Budde 12621f0e21a0SMarc Kleine-Budde err = mcp25xxfd_tx_tail_get_from_chip(priv, &chip_tx_tail); 12631f0e21a0SMarc Kleine-Budde if (err) 12641f0e21a0SMarc Kleine-Budde return err; 12651f0e21a0SMarc Kleine-Budde 12661f0e21a0SMarc Kleine-Budde /* chip_tx_tail, is the next TX-Object send by the HW. 12671f0e21a0SMarc Kleine-Budde * The new TEF head must be >= the old head, ... 12681f0e21a0SMarc Kleine-Budde */ 12691f0e21a0SMarc Kleine-Budde new_head = round_down(priv->tef.head, tx_ring->obj_num) + chip_tx_tail; 12701f0e21a0SMarc Kleine-Budde if (new_head <= priv->tef.head) 12711f0e21a0SMarc Kleine-Budde new_head += tx_ring->obj_num; 12721f0e21a0SMarc Kleine-Budde 12731f0e21a0SMarc Kleine-Budde /* ... but it cannot exceed the TX head. */ 12741f0e21a0SMarc Kleine-Budde priv->tef.head = min(new_head, tx_ring->head); 12751f0e21a0SMarc Kleine-Budde 12761f0e21a0SMarc Kleine-Budde return mcp25xxfd_check_tef_tail(priv); 12771f0e21a0SMarc Kleine-Budde } 12781f0e21a0SMarc Kleine-Budde 12791f0e21a0SMarc Kleine-Budde static inline int 12801f0e21a0SMarc Kleine-Budde mcp25xxfd_tef_obj_read(const struct mcp25xxfd_priv *priv, 12811f0e21a0SMarc Kleine-Budde struct mcp25xxfd_hw_tef_obj *hw_tef_obj, 12821f0e21a0SMarc Kleine-Budde const u8 offset, const u8 len) 12831f0e21a0SMarc Kleine-Budde { 12841f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_tx_ring *tx_ring = priv->tx; 12851f0e21a0SMarc Kleine-Budde 12861f0e21a0SMarc Kleine-Budde if (IS_ENABLED(CONFIG_CAN_MCP25XXFD_SANITY) && 12871f0e21a0SMarc Kleine-Budde (offset > tx_ring->obj_num || 12881f0e21a0SMarc Kleine-Budde len > tx_ring->obj_num || 12891f0e21a0SMarc Kleine-Budde offset + len > tx_ring->obj_num)) { 12901f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 12911f0e21a0SMarc Kleine-Budde "Trying to read to many TEF objects (max=%d, offset=%d, len=%d).\n", 12921f0e21a0SMarc Kleine-Budde tx_ring->obj_num, offset, len); 12931f0e21a0SMarc Kleine-Budde return -ERANGE; 12941f0e21a0SMarc Kleine-Budde } 12951f0e21a0SMarc Kleine-Budde 12961f0e21a0SMarc Kleine-Budde return regmap_bulk_read(priv->map_rx, 12971f0e21a0SMarc Kleine-Budde mcp25xxfd_get_tef_obj_addr(offset), 12981f0e21a0SMarc Kleine-Budde hw_tef_obj, 12991f0e21a0SMarc Kleine-Budde sizeof(*hw_tef_obj) / sizeof(u32) * len); 13001f0e21a0SMarc Kleine-Budde } 13011f0e21a0SMarc Kleine-Budde 13021f0e21a0SMarc Kleine-Budde static int mcp25xxfd_handle_tefif(struct mcp25xxfd_priv *priv) 13031f0e21a0SMarc Kleine-Budde { 13041f0e21a0SMarc Kleine-Budde struct mcp25xxfd_hw_tef_obj hw_tef_obj[MCP25XXFD_TX_OBJ_NUM_MAX]; 13051f0e21a0SMarc Kleine-Budde u8 tef_tail, len, l; 13061f0e21a0SMarc Kleine-Budde int err, i; 13071f0e21a0SMarc Kleine-Budde 13081f0e21a0SMarc Kleine-Budde err = mcp25xxfd_tef_ring_update(priv); 13091f0e21a0SMarc Kleine-Budde if (err) 13101f0e21a0SMarc Kleine-Budde return err; 13111f0e21a0SMarc Kleine-Budde 13121f0e21a0SMarc Kleine-Budde tef_tail = mcp25xxfd_get_tef_tail(priv); 13131f0e21a0SMarc Kleine-Budde len = mcp25xxfd_get_tef_len(priv); 13141f0e21a0SMarc Kleine-Budde l = mcp25xxfd_get_tef_linear_len(priv); 13151f0e21a0SMarc Kleine-Budde err = mcp25xxfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l); 13161f0e21a0SMarc Kleine-Budde if (err) 13171f0e21a0SMarc Kleine-Budde return err; 13181f0e21a0SMarc Kleine-Budde 13191f0e21a0SMarc Kleine-Budde if (l < len) { 13201f0e21a0SMarc Kleine-Budde err = mcp25xxfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l); 13211f0e21a0SMarc Kleine-Budde if (err) 13221f0e21a0SMarc Kleine-Budde return err; 13231f0e21a0SMarc Kleine-Budde } 13241f0e21a0SMarc Kleine-Budde 13251f0e21a0SMarc Kleine-Budde for (i = 0; i < len; i++) { 13261f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle_tefif_one(priv, &hw_tef_obj[i]); 13271f0e21a0SMarc Kleine-Budde /* -EAGAIN means the Sequence Number in the TEF 13281f0e21a0SMarc Kleine-Budde * doesn't match our tef_tail. This can happen if we 13291f0e21a0SMarc Kleine-Budde * read the TEF objects too early. Leave loop let the 13301f0e21a0SMarc Kleine-Budde * interrupt handler call us again. 13311f0e21a0SMarc Kleine-Budde */ 13321f0e21a0SMarc Kleine-Budde if (err == -EAGAIN) 13331f0e21a0SMarc Kleine-Budde goto out_netif_wake_queue; 13341f0e21a0SMarc Kleine-Budde if (err) 13351f0e21a0SMarc Kleine-Budde return err; 13361f0e21a0SMarc Kleine-Budde } 13371f0e21a0SMarc Kleine-Budde 13381f0e21a0SMarc Kleine-Budde out_netif_wake_queue: 13391f0e21a0SMarc Kleine-Budde mcp25xxfd_ecc_tefif_successful(priv); 13401f0e21a0SMarc Kleine-Budde 13411f0e21a0SMarc Kleine-Budde if (mcp25xxfd_get_tx_free(priv->tx)) { 13421f0e21a0SMarc Kleine-Budde /* Make sure that anybody stopping the queue after 13431f0e21a0SMarc Kleine-Budde * this sees the new tx_ring->tail. 13441f0e21a0SMarc Kleine-Budde */ 13451f0e21a0SMarc Kleine-Budde smp_mb(); 13461f0e21a0SMarc Kleine-Budde netif_wake_queue(priv->ndev); 13471f0e21a0SMarc Kleine-Budde } 13481f0e21a0SMarc Kleine-Budde 13491f0e21a0SMarc Kleine-Budde return 0; 13501f0e21a0SMarc Kleine-Budde } 13511f0e21a0SMarc Kleine-Budde 13521f0e21a0SMarc Kleine-Budde static int 13531f0e21a0SMarc Kleine-Budde mcp25xxfd_rx_ring_update(const struct mcp25xxfd_priv *priv, 13541f0e21a0SMarc Kleine-Budde struct mcp25xxfd_rx_ring *ring) 13551f0e21a0SMarc Kleine-Budde { 13561f0e21a0SMarc Kleine-Budde u32 new_head; 13571f0e21a0SMarc Kleine-Budde u8 chip_rx_head; 13581f0e21a0SMarc Kleine-Budde int err; 13591f0e21a0SMarc Kleine-Budde 13601f0e21a0SMarc Kleine-Budde err = mcp25xxfd_rx_head_get_from_chip(priv, ring, &chip_rx_head); 13611f0e21a0SMarc Kleine-Budde if (err) 13621f0e21a0SMarc Kleine-Budde return err; 13631f0e21a0SMarc Kleine-Budde 13641f0e21a0SMarc Kleine-Budde /* chip_rx_head, is the next RX-Object filled by the HW. 13651f0e21a0SMarc Kleine-Budde * The new RX head must be >= the old head. 13661f0e21a0SMarc Kleine-Budde */ 13671f0e21a0SMarc Kleine-Budde new_head = round_down(ring->head, ring->obj_num) + chip_rx_head; 13681f0e21a0SMarc Kleine-Budde if (new_head <= ring->head) 13691f0e21a0SMarc Kleine-Budde new_head += ring->obj_num; 13701f0e21a0SMarc Kleine-Budde 13711f0e21a0SMarc Kleine-Budde ring->head = new_head; 13721f0e21a0SMarc Kleine-Budde 13731f0e21a0SMarc Kleine-Budde return mcp25xxfd_check_rx_tail(priv, ring); 13741f0e21a0SMarc Kleine-Budde } 13751f0e21a0SMarc Kleine-Budde 13761f0e21a0SMarc Kleine-Budde static void 13771f0e21a0SMarc Kleine-Budde mcp25xxfd_hw_rx_obj_to_skb(const struct mcp25xxfd_priv *priv, 13781f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_hw_rx_obj_canfd *hw_rx_obj, 13791f0e21a0SMarc Kleine-Budde struct sk_buff *skb) 13801f0e21a0SMarc Kleine-Budde { 13811f0e21a0SMarc Kleine-Budde struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 13821f0e21a0SMarc Kleine-Budde 13831f0e21a0SMarc Kleine-Budde if (hw_rx_obj->flags & MCP25XXFD_OBJ_FLAGS_IDE) { 13841f0e21a0SMarc Kleine-Budde u32 sid, eid; 13851f0e21a0SMarc Kleine-Budde 13861f0e21a0SMarc Kleine-Budde eid = FIELD_GET(MCP25XXFD_OBJ_ID_EID_MASK, hw_rx_obj->id); 13871f0e21a0SMarc Kleine-Budde sid = FIELD_GET(MCP25XXFD_OBJ_ID_SID_MASK, hw_rx_obj->id); 13881f0e21a0SMarc Kleine-Budde 13891f0e21a0SMarc Kleine-Budde cfd->can_id = CAN_EFF_FLAG | 13901f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_FRAME_EFF_EID_MASK, eid) | 13911f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_REG_FRAME_EFF_SID_MASK, sid); 13921f0e21a0SMarc Kleine-Budde } else { 13931f0e21a0SMarc Kleine-Budde cfd->can_id = FIELD_GET(MCP25XXFD_OBJ_ID_SID_MASK, 13941f0e21a0SMarc Kleine-Budde hw_rx_obj->id); 13951f0e21a0SMarc Kleine-Budde } 13961f0e21a0SMarc Kleine-Budde 13971f0e21a0SMarc Kleine-Budde /* CANFD */ 13981f0e21a0SMarc Kleine-Budde if (hw_rx_obj->flags & MCP25XXFD_OBJ_FLAGS_FDF) { 13991f0e21a0SMarc Kleine-Budde u8 dlc; 14001f0e21a0SMarc Kleine-Budde 14011f0e21a0SMarc Kleine-Budde if (hw_rx_obj->flags & MCP25XXFD_OBJ_FLAGS_ESI) 14021f0e21a0SMarc Kleine-Budde cfd->flags |= CANFD_ESI; 14031f0e21a0SMarc Kleine-Budde 14041f0e21a0SMarc Kleine-Budde if (hw_rx_obj->flags & MCP25XXFD_OBJ_FLAGS_BRS) 14051f0e21a0SMarc Kleine-Budde cfd->flags |= CANFD_BRS; 14061f0e21a0SMarc Kleine-Budde 14071f0e21a0SMarc Kleine-Budde dlc = FIELD_GET(MCP25XXFD_OBJ_FLAGS_DLC, hw_rx_obj->flags); 14081f0e21a0SMarc Kleine-Budde cfd->len = can_dlc2len(get_canfd_dlc(dlc)); 14091f0e21a0SMarc Kleine-Budde } else { 14101f0e21a0SMarc Kleine-Budde if (hw_rx_obj->flags & MCP25XXFD_OBJ_FLAGS_RTR) 14111f0e21a0SMarc Kleine-Budde cfd->can_id |= CAN_RTR_FLAG; 14121f0e21a0SMarc Kleine-Budde 14131f0e21a0SMarc Kleine-Budde cfd->len = get_can_dlc(FIELD_GET(MCP25XXFD_OBJ_FLAGS_DLC, 14141f0e21a0SMarc Kleine-Budde hw_rx_obj->flags)); 14151f0e21a0SMarc Kleine-Budde } 14161f0e21a0SMarc Kleine-Budde 14171f0e21a0SMarc Kleine-Budde memcpy(cfd->data, hw_rx_obj->data, cfd->len); 14181f0e21a0SMarc Kleine-Budde } 14191f0e21a0SMarc Kleine-Budde 14201f0e21a0SMarc Kleine-Budde static int 14211f0e21a0SMarc Kleine-Budde mcp25xxfd_handle_rxif_one(struct mcp25xxfd_priv *priv, 14221f0e21a0SMarc Kleine-Budde struct mcp25xxfd_rx_ring *ring, 14231f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_hw_rx_obj_canfd *hw_rx_obj) 14241f0e21a0SMarc Kleine-Budde { 14251f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 14261f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 14271f0e21a0SMarc Kleine-Budde struct canfd_frame *cfd; 14281f0e21a0SMarc Kleine-Budde int err; 14291f0e21a0SMarc Kleine-Budde 14301f0e21a0SMarc Kleine-Budde if (hw_rx_obj->flags & MCP25XXFD_OBJ_FLAGS_FDF) 14311f0e21a0SMarc Kleine-Budde skb = alloc_canfd_skb(priv->ndev, &cfd); 14321f0e21a0SMarc Kleine-Budde else 14331f0e21a0SMarc Kleine-Budde skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cfd); 14341f0e21a0SMarc Kleine-Budde 14351f0e21a0SMarc Kleine-Budde if (!cfd) { 14361f0e21a0SMarc Kleine-Budde stats->rx_dropped++; 14371f0e21a0SMarc Kleine-Budde return 0; 14381f0e21a0SMarc Kleine-Budde } 14391f0e21a0SMarc Kleine-Budde 14401f0e21a0SMarc Kleine-Budde mcp25xxfd_hw_rx_obj_to_skb(priv, hw_rx_obj, skb); 14411f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, hw_rx_obj->ts); 14421f0e21a0SMarc Kleine-Budde if (err) 14431f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 14441f0e21a0SMarc Kleine-Budde 14451f0e21a0SMarc Kleine-Budde ring->tail++; 14461f0e21a0SMarc Kleine-Budde 14471f0e21a0SMarc Kleine-Budde /* finally increment the RX pointer */ 14481f0e21a0SMarc Kleine-Budde return regmap_update_bits(priv->map_reg, 14491f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON(ring->fifo_nr), 14501f0e21a0SMarc Kleine-Budde GENMASK(15, 8), 14511f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOCON_UINC); 14521f0e21a0SMarc Kleine-Budde } 14531f0e21a0SMarc Kleine-Budde 14541f0e21a0SMarc Kleine-Budde static inline int 14551f0e21a0SMarc Kleine-Budde mcp25xxfd_rx_obj_read(const struct mcp25xxfd_priv *priv, 14561f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_rx_ring *ring, 14571f0e21a0SMarc Kleine-Budde struct mcp25xxfd_hw_rx_obj_canfd *hw_rx_obj, 14581f0e21a0SMarc Kleine-Budde const u8 offset, const u8 len) 14591f0e21a0SMarc Kleine-Budde { 14601f0e21a0SMarc Kleine-Budde int err; 14611f0e21a0SMarc Kleine-Budde 14621f0e21a0SMarc Kleine-Budde err = regmap_bulk_read(priv->map_rx, 14631f0e21a0SMarc Kleine-Budde mcp25xxfd_get_rx_obj_addr(ring, offset), 14641f0e21a0SMarc Kleine-Budde hw_rx_obj, 14651f0e21a0SMarc Kleine-Budde len * ring->obj_size / sizeof(u32)); 14661f0e21a0SMarc Kleine-Budde 14671f0e21a0SMarc Kleine-Budde return err; 14681f0e21a0SMarc Kleine-Budde } 14691f0e21a0SMarc Kleine-Budde 14701f0e21a0SMarc Kleine-Budde static int 14711f0e21a0SMarc Kleine-Budde mcp25xxfd_handle_rxif_ring(struct mcp25xxfd_priv *priv, 14721f0e21a0SMarc Kleine-Budde struct mcp25xxfd_rx_ring *ring) 14731f0e21a0SMarc Kleine-Budde { 14741f0e21a0SMarc Kleine-Budde struct mcp25xxfd_hw_rx_obj_canfd *hw_rx_obj = ring->obj; 14751f0e21a0SMarc Kleine-Budde u8 rx_tail, len; 14761f0e21a0SMarc Kleine-Budde int err, i; 14771f0e21a0SMarc Kleine-Budde 14781f0e21a0SMarc Kleine-Budde err = mcp25xxfd_rx_ring_update(priv, ring); 14791f0e21a0SMarc Kleine-Budde if (err) 14801f0e21a0SMarc Kleine-Budde return err; 14811f0e21a0SMarc Kleine-Budde 14821f0e21a0SMarc Kleine-Budde while ((len = mcp25xxfd_get_rx_linear_len(ring))) { 14831f0e21a0SMarc Kleine-Budde rx_tail = mcp25xxfd_get_rx_tail(ring); 14841f0e21a0SMarc Kleine-Budde 14851f0e21a0SMarc Kleine-Budde err = mcp25xxfd_rx_obj_read(priv, ring, hw_rx_obj, 14861f0e21a0SMarc Kleine-Budde rx_tail, len); 14871f0e21a0SMarc Kleine-Budde if (err) 14881f0e21a0SMarc Kleine-Budde return err; 14891f0e21a0SMarc Kleine-Budde 14901f0e21a0SMarc Kleine-Budde for (i = 0; i < len; i++) { 14911f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle_rxif_one(priv, ring, 14921f0e21a0SMarc Kleine-Budde (void *)hw_rx_obj + 14931f0e21a0SMarc Kleine-Budde i * ring->obj_size); 14941f0e21a0SMarc Kleine-Budde if (err) 14951f0e21a0SMarc Kleine-Budde return err; 14961f0e21a0SMarc Kleine-Budde } 14971f0e21a0SMarc Kleine-Budde } 14981f0e21a0SMarc Kleine-Budde 14991f0e21a0SMarc Kleine-Budde return 0; 15001f0e21a0SMarc Kleine-Budde } 15011f0e21a0SMarc Kleine-Budde 15021f0e21a0SMarc Kleine-Budde static int mcp25xxfd_handle_rxif(struct mcp25xxfd_priv *priv) 15031f0e21a0SMarc Kleine-Budde { 15041f0e21a0SMarc Kleine-Budde struct mcp25xxfd_rx_ring *ring; 15051f0e21a0SMarc Kleine-Budde int err, n; 15061f0e21a0SMarc Kleine-Budde 15071f0e21a0SMarc Kleine-Budde mcp25xxfd_for_each_rx_ring(priv, ring, n) { 15081f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle_rxif_ring(priv, ring); 15091f0e21a0SMarc Kleine-Budde if (err) 15101f0e21a0SMarc Kleine-Budde return err; 15111f0e21a0SMarc Kleine-Budde } 15121f0e21a0SMarc Kleine-Budde 15131f0e21a0SMarc Kleine-Budde return 0; 15141f0e21a0SMarc Kleine-Budde } 15151f0e21a0SMarc Kleine-Budde 15161f0e21a0SMarc Kleine-Budde static inline int mcp25xxfd_get_timestamp(const struct mcp25xxfd_priv *priv, 15171f0e21a0SMarc Kleine-Budde u32 *timestamp) 15181f0e21a0SMarc Kleine-Budde { 15191f0e21a0SMarc Kleine-Budde return regmap_read(priv->map_reg, MCP25XXFD_REG_TBC, timestamp); 15201f0e21a0SMarc Kleine-Budde } 15211f0e21a0SMarc Kleine-Budde 15221f0e21a0SMarc Kleine-Budde static struct sk_buff * 15231f0e21a0SMarc Kleine-Budde mcp25xxfd_alloc_can_err_skb(const struct mcp25xxfd_priv *priv, 15241f0e21a0SMarc Kleine-Budde struct can_frame **cf, u32 *timestamp) 15251f0e21a0SMarc Kleine-Budde { 15261f0e21a0SMarc Kleine-Budde int err; 15271f0e21a0SMarc Kleine-Budde 15281f0e21a0SMarc Kleine-Budde err = mcp25xxfd_get_timestamp(priv, timestamp); 15291f0e21a0SMarc Kleine-Budde if (err) 15301f0e21a0SMarc Kleine-Budde return NULL; 15311f0e21a0SMarc Kleine-Budde 15321f0e21a0SMarc Kleine-Budde return alloc_can_err_skb(priv->ndev, cf); 15331f0e21a0SMarc Kleine-Budde } 15341f0e21a0SMarc Kleine-Budde 15351f0e21a0SMarc Kleine-Budde static int mcp25xxfd_handle_rxovif(struct mcp25xxfd_priv *priv) 15361f0e21a0SMarc Kleine-Budde { 15371f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 15381f0e21a0SMarc Kleine-Budde struct mcp25xxfd_rx_ring *ring; 15391f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 15401f0e21a0SMarc Kleine-Budde struct can_frame *cf; 15411f0e21a0SMarc Kleine-Budde u32 timestamp, rxovif; 15421f0e21a0SMarc Kleine-Budde int err, i; 15431f0e21a0SMarc Kleine-Budde 15441f0e21a0SMarc Kleine-Budde stats->rx_over_errors++; 15451f0e21a0SMarc Kleine-Budde stats->rx_errors++; 15461f0e21a0SMarc Kleine-Budde 15471f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_RXOVIF, &rxovif); 15481f0e21a0SMarc Kleine-Budde if (err) 15491f0e21a0SMarc Kleine-Budde return err; 15501f0e21a0SMarc Kleine-Budde 15511f0e21a0SMarc Kleine-Budde mcp25xxfd_for_each_rx_ring(priv, ring, i) { 15521f0e21a0SMarc Kleine-Budde if (!(rxovif & BIT(ring->fifo_nr))) 15531f0e21a0SMarc Kleine-Budde continue; 15541f0e21a0SMarc Kleine-Budde 15551f0e21a0SMarc Kleine-Budde /* If SERRIF is active, there was a RX MAB overflow. */ 15561f0e21a0SMarc Kleine-Budde if (priv->regs_status.intf & MCP25XXFD_REG_INT_SERRIF) { 15571f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 15581f0e21a0SMarc Kleine-Budde "RX-%d: MAB overflow detected.\n", 15591f0e21a0SMarc Kleine-Budde ring->nr); 15601f0e21a0SMarc Kleine-Budde } else { 15611f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 15621f0e21a0SMarc Kleine-Budde "RX-%d: FIFO overflow.\n", ring->nr); 15631f0e21a0SMarc Kleine-Budde } 15641f0e21a0SMarc Kleine-Budde 15651f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 15661f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOSTA(ring->fifo_nr), 15671f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_FIFOSTA_RXOVIF, 15681f0e21a0SMarc Kleine-Budde 0x0); 15691f0e21a0SMarc Kleine-Budde if (err) 15701f0e21a0SMarc Kleine-Budde return err; 15711f0e21a0SMarc Kleine-Budde } 15721f0e21a0SMarc Kleine-Budde 15731f0e21a0SMarc Kleine-Budde skb = mcp25xxfd_alloc_can_err_skb(priv, &cf, ×tamp); 15741f0e21a0SMarc Kleine-Budde if (!skb) 15751f0e21a0SMarc Kleine-Budde return 0; 15761f0e21a0SMarc Kleine-Budde 15771f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_CRTL; 15781f0e21a0SMarc Kleine-Budde cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; 15791f0e21a0SMarc Kleine-Budde 15801f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 15811f0e21a0SMarc Kleine-Budde if (err) 15821f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 15831f0e21a0SMarc Kleine-Budde 15841f0e21a0SMarc Kleine-Budde return 0; 15851f0e21a0SMarc Kleine-Budde } 15861f0e21a0SMarc Kleine-Budde 15871f0e21a0SMarc Kleine-Budde static int mcp25xxfd_handle_txatif(struct mcp25xxfd_priv *priv) 15881f0e21a0SMarc Kleine-Budde { 15891f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", __func__); 15901f0e21a0SMarc Kleine-Budde 15911f0e21a0SMarc Kleine-Budde return 0; 15921f0e21a0SMarc Kleine-Budde } 15931f0e21a0SMarc Kleine-Budde 15941f0e21a0SMarc Kleine-Budde static int mcp25xxfd_handle_ivmif(struct mcp25xxfd_priv *priv) 15951f0e21a0SMarc Kleine-Budde { 15961f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 15971f0e21a0SMarc Kleine-Budde u32 bdiag1, timestamp; 15981f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 15991f0e21a0SMarc Kleine-Budde struct can_frame *cf = NULL; 16001f0e21a0SMarc Kleine-Budde int err; 16011f0e21a0SMarc Kleine-Budde 16021f0e21a0SMarc Kleine-Budde err = mcp25xxfd_get_timestamp(priv, ×tamp); 16031f0e21a0SMarc Kleine-Budde if (err) 16041f0e21a0SMarc Kleine-Budde return err; 16051f0e21a0SMarc Kleine-Budde 16061f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_BDIAG1, &bdiag1); 16071f0e21a0SMarc Kleine-Budde if (err) 16081f0e21a0SMarc Kleine-Budde return err; 16091f0e21a0SMarc Kleine-Budde 16101f0e21a0SMarc Kleine-Budde /* Write 0s to clear error bits, don't write 1s to non active 16111f0e21a0SMarc Kleine-Budde * bits, as they will be set. 16121f0e21a0SMarc Kleine-Budde */ 16131f0e21a0SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP25XXFD_REG_BDIAG1, 0x0); 16141f0e21a0SMarc Kleine-Budde if (err) 16151f0e21a0SMarc Kleine-Budde return err; 16161f0e21a0SMarc Kleine-Budde 16171f0e21a0SMarc Kleine-Budde priv->can.can_stats.bus_error++; 16181f0e21a0SMarc Kleine-Budde 16191f0e21a0SMarc Kleine-Budde skb = alloc_can_err_skb(priv->ndev, &cf); 16201f0e21a0SMarc Kleine-Budde if (cf) 16211f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; 16221f0e21a0SMarc Kleine-Budde 16231f0e21a0SMarc Kleine-Budde /* Controller misconfiguration */ 16241f0e21a0SMarc Kleine-Budde if (WARN_ON(bdiag1 & MCP25XXFD_REG_BDIAG1_DLCMM)) 16251f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 16261f0e21a0SMarc Kleine-Budde "recv'd DLC is larger than PLSIZE of FIFO element."); 16271f0e21a0SMarc Kleine-Budde 16281f0e21a0SMarc Kleine-Budde /* RX errors */ 16291f0e21a0SMarc Kleine-Budde if (bdiag1 & (MCP25XXFD_REG_BDIAG1_DCRCERR | 16301f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_BDIAG1_NCRCERR)) { 16311f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "CRC error\n"); 16321f0e21a0SMarc Kleine-Budde 16331f0e21a0SMarc Kleine-Budde stats->rx_errors++; 16341f0e21a0SMarc Kleine-Budde if (cf) 16351f0e21a0SMarc Kleine-Budde cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; 16361f0e21a0SMarc Kleine-Budde } 16371f0e21a0SMarc Kleine-Budde if (bdiag1 & (MCP25XXFD_REG_BDIAG1_DSTUFERR | 16381f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_BDIAG1_NSTUFERR)) { 16391f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Stuff error\n"); 16401f0e21a0SMarc Kleine-Budde 16411f0e21a0SMarc Kleine-Budde stats->rx_errors++; 16421f0e21a0SMarc Kleine-Budde if (cf) 16431f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_STUFF; 16441f0e21a0SMarc Kleine-Budde } 16451f0e21a0SMarc Kleine-Budde if (bdiag1 & (MCP25XXFD_REG_BDIAG1_DFORMERR | 16461f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_BDIAG1_NFORMERR)) { 16471f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Format error\n"); 16481f0e21a0SMarc Kleine-Budde 16491f0e21a0SMarc Kleine-Budde stats->rx_errors++; 16501f0e21a0SMarc Kleine-Budde if (cf) 16511f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_FORM; 16521f0e21a0SMarc Kleine-Budde } 16531f0e21a0SMarc Kleine-Budde 16541f0e21a0SMarc Kleine-Budde /* TX errors */ 16551f0e21a0SMarc Kleine-Budde if (bdiag1 & MCP25XXFD_REG_BDIAG1_NACKERR) { 16561f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "NACK error\n"); 16571f0e21a0SMarc Kleine-Budde 16581f0e21a0SMarc Kleine-Budde stats->tx_errors++; 16591f0e21a0SMarc Kleine-Budde if (cf) { 16601f0e21a0SMarc Kleine-Budde cf->can_id |= CAN_ERR_ACK; 16611f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX; 16621f0e21a0SMarc Kleine-Budde } 16631f0e21a0SMarc Kleine-Budde } 16641f0e21a0SMarc Kleine-Budde if (bdiag1 & (MCP25XXFD_REG_BDIAG1_DBIT1ERR | 16651f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_BDIAG1_NBIT1ERR)) { 16661f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit1 error\n"); 16671f0e21a0SMarc Kleine-Budde 16681f0e21a0SMarc Kleine-Budde stats->tx_errors++; 16691f0e21a0SMarc Kleine-Budde if (cf) 16701f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT1; 16711f0e21a0SMarc Kleine-Budde } 16721f0e21a0SMarc Kleine-Budde if (bdiag1 & (MCP25XXFD_REG_BDIAG1_DBIT0ERR | 16731f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_BDIAG1_NBIT0ERR)) { 16741f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit0 error\n"); 16751f0e21a0SMarc Kleine-Budde 16761f0e21a0SMarc Kleine-Budde stats->tx_errors++; 16771f0e21a0SMarc Kleine-Budde if (cf) 16781f0e21a0SMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT0; 16791f0e21a0SMarc Kleine-Budde } 16801f0e21a0SMarc Kleine-Budde 16811f0e21a0SMarc Kleine-Budde if (!cf) 16821f0e21a0SMarc Kleine-Budde return 0; 16831f0e21a0SMarc Kleine-Budde 16841f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 16851f0e21a0SMarc Kleine-Budde if (err) 16861f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 16871f0e21a0SMarc Kleine-Budde 16881f0e21a0SMarc Kleine-Budde return 0; 16891f0e21a0SMarc Kleine-Budde } 16901f0e21a0SMarc Kleine-Budde 16911f0e21a0SMarc Kleine-Budde static int mcp25xxfd_handle_cerrif(struct mcp25xxfd_priv *priv) 16921f0e21a0SMarc Kleine-Budde { 16931f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 16941f0e21a0SMarc Kleine-Budde struct sk_buff *skb; 16951f0e21a0SMarc Kleine-Budde struct can_frame *cf = NULL; 16961f0e21a0SMarc Kleine-Budde enum can_state new_state, rx_state, tx_state; 16971f0e21a0SMarc Kleine-Budde u32 trec, timestamp; 16981f0e21a0SMarc Kleine-Budde int err; 16991f0e21a0SMarc Kleine-Budde 17001f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_TREC, &trec); 17011f0e21a0SMarc Kleine-Budde if (err) 17021f0e21a0SMarc Kleine-Budde return err; 17031f0e21a0SMarc Kleine-Budde 17041f0e21a0SMarc Kleine-Budde if (trec & MCP25XXFD_REG_TREC_TXBO) 17051f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_BUS_OFF; 17061f0e21a0SMarc Kleine-Budde else if (trec & MCP25XXFD_REG_TREC_TXBP) 17071f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_PASSIVE; 17081f0e21a0SMarc Kleine-Budde else if (trec & MCP25XXFD_REG_TREC_TXWARN) 17091f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_WARNING; 17101f0e21a0SMarc Kleine-Budde else 17111f0e21a0SMarc Kleine-Budde tx_state = CAN_STATE_ERROR_ACTIVE; 17121f0e21a0SMarc Kleine-Budde 17131f0e21a0SMarc Kleine-Budde if (trec & MCP25XXFD_REG_TREC_RXBP) 17141f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_PASSIVE; 17151f0e21a0SMarc Kleine-Budde else if (trec & MCP25XXFD_REG_TREC_RXWARN) 17161f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_WARNING; 17171f0e21a0SMarc Kleine-Budde else 17181f0e21a0SMarc Kleine-Budde rx_state = CAN_STATE_ERROR_ACTIVE; 17191f0e21a0SMarc Kleine-Budde 17201f0e21a0SMarc Kleine-Budde new_state = max(tx_state, rx_state); 17211f0e21a0SMarc Kleine-Budde if (new_state == priv->can.state) 17221f0e21a0SMarc Kleine-Budde return 0; 17231f0e21a0SMarc Kleine-Budde 17241f0e21a0SMarc Kleine-Budde /* The skb allocation might fail, but can_change_state() 17251f0e21a0SMarc Kleine-Budde * handles cf == NULL. 17261f0e21a0SMarc Kleine-Budde */ 17271f0e21a0SMarc Kleine-Budde skb = mcp25xxfd_alloc_can_err_skb(priv, &cf, ×tamp); 17281f0e21a0SMarc Kleine-Budde can_change_state(priv->ndev, cf, tx_state, rx_state); 17291f0e21a0SMarc Kleine-Budde 17301f0e21a0SMarc Kleine-Budde if (new_state == CAN_STATE_BUS_OFF) { 17311f0e21a0SMarc Kleine-Budde /* As we're going to switch off the chip now, let's 17321f0e21a0SMarc Kleine-Budde * save the error counters and return them to 17331f0e21a0SMarc Kleine-Budde * userspace, if do_get_berr_counter() is called while 17341f0e21a0SMarc Kleine-Budde * the chip is in Bus Off. 17351f0e21a0SMarc Kleine-Budde */ 17361f0e21a0SMarc Kleine-Budde err = __mcp25xxfd_get_berr_counter(priv->ndev, &priv->bec); 17371f0e21a0SMarc Kleine-Budde if (err) 17381f0e21a0SMarc Kleine-Budde return err; 17391f0e21a0SMarc Kleine-Budde 17401f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_stop(priv, CAN_STATE_BUS_OFF); 17411f0e21a0SMarc Kleine-Budde can_bus_off(priv->ndev); 17421f0e21a0SMarc Kleine-Budde } 17431f0e21a0SMarc Kleine-Budde 17441f0e21a0SMarc Kleine-Budde if (!skb) 17451f0e21a0SMarc Kleine-Budde return 0; 17461f0e21a0SMarc Kleine-Budde 17471f0e21a0SMarc Kleine-Budde if (new_state != CAN_STATE_BUS_OFF) { 17481f0e21a0SMarc Kleine-Budde struct can_berr_counter bec; 17491f0e21a0SMarc Kleine-Budde 17501f0e21a0SMarc Kleine-Budde err = mcp25xxfd_get_berr_counter(priv->ndev, &bec); 17511f0e21a0SMarc Kleine-Budde if (err) 17521f0e21a0SMarc Kleine-Budde return err; 17531f0e21a0SMarc Kleine-Budde cf->data[6] = bec.txerr; 17541f0e21a0SMarc Kleine-Budde cf->data[7] = bec.rxerr; 17551f0e21a0SMarc Kleine-Budde } 17561f0e21a0SMarc Kleine-Budde 17571f0e21a0SMarc Kleine-Budde err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp); 17581f0e21a0SMarc Kleine-Budde if (err) 17591f0e21a0SMarc Kleine-Budde stats->rx_fifo_errors++; 17601f0e21a0SMarc Kleine-Budde 17611f0e21a0SMarc Kleine-Budde return 0; 17621f0e21a0SMarc Kleine-Budde } 17631f0e21a0SMarc Kleine-Budde 17641f0e21a0SMarc Kleine-Budde static int 17651f0e21a0SMarc Kleine-Budde mcp25xxfd_handle_modif(const struct mcp25xxfd_priv *priv, bool *set_normal_mode) 17661f0e21a0SMarc Kleine-Budde { 17671f0e21a0SMarc Kleine-Budde const u8 mode_reference = mcp25xxfd_get_normal_mode(priv); 17681f0e21a0SMarc Kleine-Budde u8 mode; 17691f0e21a0SMarc Kleine-Budde int err; 17701f0e21a0SMarc Kleine-Budde 17711f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_get_mode(priv, &mode); 17721f0e21a0SMarc Kleine-Budde if (err) 17731f0e21a0SMarc Kleine-Budde return err; 17741f0e21a0SMarc Kleine-Budde 17751f0e21a0SMarc Kleine-Budde if (mode == mode_reference) { 17761f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 17771f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 17781f0e21a0SMarc Kleine-Budde mcp25xxfd_get_mode_str(mode), mode); 17791f0e21a0SMarc Kleine-Budde return 0; 17801f0e21a0SMarc Kleine-Budde } 17811f0e21a0SMarc Kleine-Budde 17821f0e21a0SMarc Kleine-Budde /* According to MCP2517FD errata DS80000792B 1., during a TX 17831f0e21a0SMarc Kleine-Budde * MAB underflow, the controller will transition to Restricted 17841f0e21a0SMarc Kleine-Budde * Operation Mode or Listen Only Mode (depending on SERR2LOM). 17851f0e21a0SMarc Kleine-Budde * 17861f0e21a0SMarc Kleine-Budde * However this is not always the case. If SERR2LOM is 17871f0e21a0SMarc Kleine-Budde * configured for Restricted Operation Mode (SERR2LOM not set) 17881f0e21a0SMarc Kleine-Budde * the MCP2517FD will sometimes transition to Listen Only Mode 17891f0e21a0SMarc Kleine-Budde * first. When polling this bit we see that it will transition 17901f0e21a0SMarc Kleine-Budde * to Restricted Operation Mode shortly after. 17911f0e21a0SMarc Kleine-Budde */ 17921f0e21a0SMarc Kleine-Budde if ((priv->devtype_data.quirks & MCP25XXFD_QUIRK_MAB_NO_WARN) && 17931f0e21a0SMarc Kleine-Budde (mode == MCP25XXFD_REG_CON_MODE_RESTRICTED || 17941f0e21a0SMarc Kleine-Budde mode == MCP25XXFD_REG_CON_MODE_LISTENONLY)) 17951f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 17961f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 17971f0e21a0SMarc Kleine-Budde mcp25xxfd_get_mode_str(mode), mode); 17981f0e21a0SMarc Kleine-Budde else 17991f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 18001f0e21a0SMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 18011f0e21a0SMarc Kleine-Budde mcp25xxfd_get_mode_str(mode), mode); 18021f0e21a0SMarc Kleine-Budde 18031f0e21a0SMarc Kleine-Budde /* After the application requests Normal mode, the Controller 18041f0e21a0SMarc Kleine-Budde * will automatically attempt to retransmit the message that 18051f0e21a0SMarc Kleine-Budde * caused the TX MAB underflow. 18061f0e21a0SMarc Kleine-Budde * 18071f0e21a0SMarc Kleine-Budde * However, if there is an ECC error in the TX-RAM, we first 18081f0e21a0SMarc Kleine-Budde * have to reload the tx-object before requesting Normal 18091f0e21a0SMarc Kleine-Budde * mode. This is done later in mcp25xxfd_handle_eccif(). 18101f0e21a0SMarc Kleine-Budde */ 18111f0e21a0SMarc Kleine-Budde if (priv->regs_status.intf & MCP25XXFD_REG_INT_ECCIF) { 18121f0e21a0SMarc Kleine-Budde *set_normal_mode = true; 18131f0e21a0SMarc Kleine-Budde return 0; 18141f0e21a0SMarc Kleine-Budde } 18151f0e21a0SMarc Kleine-Budde 18161f0e21a0SMarc Kleine-Budde return mcp25xxfd_chip_set_normal_mode_nowait(priv); 18171f0e21a0SMarc Kleine-Budde } 18181f0e21a0SMarc Kleine-Budde 18191f0e21a0SMarc Kleine-Budde static int mcp25xxfd_handle_serrif(struct mcp25xxfd_priv *priv) 18201f0e21a0SMarc Kleine-Budde { 18211f0e21a0SMarc Kleine-Budde struct mcp25xxfd_ecc *ecc = &priv->ecc; 18221f0e21a0SMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 18231f0e21a0SMarc Kleine-Budde bool handled = false; 18241f0e21a0SMarc Kleine-Budde 18251f0e21a0SMarc Kleine-Budde /* TX MAB underflow 18261f0e21a0SMarc Kleine-Budde * 18271f0e21a0SMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a TX MAB 18281f0e21a0SMarc Kleine-Budde * underflow is indicated by SERRIF and MODIF. 18291f0e21a0SMarc Kleine-Budde * 18301f0e21a0SMarc Kleine-Budde * In addition to the effects mentioned in the Errata, there 18311f0e21a0SMarc Kleine-Budde * are Bus Errors due to the aborted CAN frame, so a IVMIF 18321f0e21a0SMarc Kleine-Budde * will be seen as well. 18331f0e21a0SMarc Kleine-Budde * 18341f0e21a0SMarc Kleine-Budde * Sometimes there is an ECC error in the TX-RAM, which leads 18351f0e21a0SMarc Kleine-Budde * to a TX MAB underflow. 18361f0e21a0SMarc Kleine-Budde * 18371f0e21a0SMarc Kleine-Budde * However, probably due to a race condition, there is no 18381f0e21a0SMarc Kleine-Budde * associated MODIF pending. 18391f0e21a0SMarc Kleine-Budde * 18401f0e21a0SMarc Kleine-Budde * Further, there are situations, where the SERRIF is caused 18411f0e21a0SMarc Kleine-Budde * by an ECC error in the TX-RAM, but not even the ECCIF is 18421f0e21a0SMarc Kleine-Budde * set. This only seems to happen _after_ the first occurrence 18431f0e21a0SMarc Kleine-Budde * of a ECCIF (which is tracked in ecc->cnt). 18441f0e21a0SMarc Kleine-Budde * 18451f0e21a0SMarc Kleine-Budde * Treat all as a known system errors.. 18461f0e21a0SMarc Kleine-Budde */ 18471f0e21a0SMarc Kleine-Budde if ((priv->regs_status.intf & MCP25XXFD_REG_INT_MODIF && 18481f0e21a0SMarc Kleine-Budde priv->regs_status.intf & MCP25XXFD_REG_INT_IVMIF) || 18491f0e21a0SMarc Kleine-Budde priv->regs_status.intf & MCP25XXFD_REG_INT_ECCIF || 18501f0e21a0SMarc Kleine-Budde ecc->cnt) { 18511f0e21a0SMarc Kleine-Budde const char *msg; 18521f0e21a0SMarc Kleine-Budde 18531f0e21a0SMarc Kleine-Budde if (priv->regs_status.intf & MCP25XXFD_REG_INT_ECCIF || 18541f0e21a0SMarc Kleine-Budde ecc->cnt) 18551f0e21a0SMarc Kleine-Budde msg = "TX MAB underflow due to ECC error detected."; 18561f0e21a0SMarc Kleine-Budde else 18571f0e21a0SMarc Kleine-Budde msg = "TX MAB underflow detected."; 18581f0e21a0SMarc Kleine-Budde 18591f0e21a0SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_MAB_NO_WARN) 18601f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, "%s\n", msg); 18611f0e21a0SMarc Kleine-Budde else 18621f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", msg); 18631f0e21a0SMarc Kleine-Budde 18641f0e21a0SMarc Kleine-Budde stats->tx_aborted_errors++; 18651f0e21a0SMarc Kleine-Budde stats->tx_errors++; 18661f0e21a0SMarc Kleine-Budde handled = true; 18671f0e21a0SMarc Kleine-Budde } 18681f0e21a0SMarc Kleine-Budde 18691f0e21a0SMarc Kleine-Budde /* RX MAB overflow 18701f0e21a0SMarc Kleine-Budde * 18711f0e21a0SMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a RX MAB 18721f0e21a0SMarc Kleine-Budde * overflow is indicated by SERRIF. 18731f0e21a0SMarc Kleine-Budde * 18741f0e21a0SMarc Kleine-Budde * In addition to the effects mentioned in the Errata, (most 18751f0e21a0SMarc Kleine-Budde * of the times) a RXOVIF is raised, if the FIFO that is being 18761f0e21a0SMarc Kleine-Budde * received into has the RXOVIE activated (and we have enabled 18771f0e21a0SMarc Kleine-Budde * RXOVIE on all FIFOs). 18781f0e21a0SMarc Kleine-Budde * 18791f0e21a0SMarc Kleine-Budde * Sometimes there is no RXOVIF just a RXIF is pending. 18801f0e21a0SMarc Kleine-Budde * 18811f0e21a0SMarc Kleine-Budde * Treat all as a known system errors.. 18821f0e21a0SMarc Kleine-Budde */ 18831f0e21a0SMarc Kleine-Budde if (priv->regs_status.intf & MCP25XXFD_REG_INT_RXOVIF || 18841f0e21a0SMarc Kleine-Budde priv->regs_status.intf & MCP25XXFD_REG_INT_RXIF) { 18851f0e21a0SMarc Kleine-Budde stats->rx_dropped++; 18861f0e21a0SMarc Kleine-Budde handled = true; 18871f0e21a0SMarc Kleine-Budde } 18881f0e21a0SMarc Kleine-Budde 18891f0e21a0SMarc Kleine-Budde if (!handled) 18901f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 18911f0e21a0SMarc Kleine-Budde "Unhandled System Error Interrupt (intf=0x%08x)!\n", 18921f0e21a0SMarc Kleine-Budde priv->regs_status.intf); 18931f0e21a0SMarc Kleine-Budde 18941f0e21a0SMarc Kleine-Budde return 0; 18951f0e21a0SMarc Kleine-Budde } 18961f0e21a0SMarc Kleine-Budde 18971f0e21a0SMarc Kleine-Budde static int 18981f0e21a0SMarc Kleine-Budde mcp25xxfd_handle_eccif_recover(struct mcp25xxfd_priv *priv, u8 nr) 18991f0e21a0SMarc Kleine-Budde { 19001f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_ring *tx_ring = priv->tx; 19011f0e21a0SMarc Kleine-Budde struct mcp25xxfd_ecc *ecc = &priv->ecc; 19021f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_obj *tx_obj; 19031f0e21a0SMarc Kleine-Budde u8 chip_tx_tail, tx_tail, offset; 19041f0e21a0SMarc Kleine-Budde u16 addr; 19051f0e21a0SMarc Kleine-Budde int err; 19061f0e21a0SMarc Kleine-Budde 19071f0e21a0SMarc Kleine-Budde addr = FIELD_GET(MCP25XXFD_REG_ECCSTAT_ERRADDR_MASK, ecc->ecc_stat); 19081f0e21a0SMarc Kleine-Budde 19091f0e21a0SMarc Kleine-Budde err = mcp25xxfd_tx_tail_get_from_chip(priv, &chip_tx_tail); 19101f0e21a0SMarc Kleine-Budde if (err) 19111f0e21a0SMarc Kleine-Budde return err; 19121f0e21a0SMarc Kleine-Budde 19131f0e21a0SMarc Kleine-Budde tx_tail = mcp25xxfd_get_tx_tail(tx_ring); 19141f0e21a0SMarc Kleine-Budde offset = (nr - chip_tx_tail) & (tx_ring->obj_num - 1); 19151f0e21a0SMarc Kleine-Budde 19161f0e21a0SMarc Kleine-Budde /* Bail out if one of the following is met: 19171f0e21a0SMarc Kleine-Budde * - tx_tail information is inconsistent 19181f0e21a0SMarc Kleine-Budde * - for mcp2517fd: offset not 0 19191f0e21a0SMarc Kleine-Budde * - for mcp2518fd: offset not 0 or 1 19201f0e21a0SMarc Kleine-Budde */ 19211f0e21a0SMarc Kleine-Budde if (chip_tx_tail != tx_tail || 19221f0e21a0SMarc Kleine-Budde !(offset == 0 || (offset == 1 && mcp25xxfd_is_2518(priv)))) { 19231f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, 19241f0e21a0SMarc Kleine-Budde "ECC Error information inconsistent (addr=0x%04x, nr=%d, tx_tail=0x%08x(%d), chip_tx_tail=%d, offset=%d).\n", 19251f0e21a0SMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, chip_tx_tail, 19261f0e21a0SMarc Kleine-Budde offset); 19271f0e21a0SMarc Kleine-Budde return -EINVAL; 19281f0e21a0SMarc Kleine-Budde } 19291f0e21a0SMarc Kleine-Budde 19301f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 19311f0e21a0SMarc Kleine-Budde "Recovering %s ECC Error at address 0x%04x (in TX-RAM, tx_obj=%d, tx_tail=0x%08x(%d), offset=%d).\n", 19321f0e21a0SMarc Kleine-Budde ecc->ecc_stat & MCP25XXFD_REG_ECCSTAT_SECIF ? 19331f0e21a0SMarc Kleine-Budde "Single" : "Double", 19341f0e21a0SMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, offset); 19351f0e21a0SMarc Kleine-Budde 19361f0e21a0SMarc Kleine-Budde /* reload tx_obj into controller RAM ... */ 19371f0e21a0SMarc Kleine-Budde tx_obj = &tx_ring->obj[nr]; 19381f0e21a0SMarc Kleine-Budde err = spi_sync_transfer(priv->spi, tx_obj->xfer, 1); 19391f0e21a0SMarc Kleine-Budde if (err) 19401f0e21a0SMarc Kleine-Budde return err; 19411f0e21a0SMarc Kleine-Budde 19421f0e21a0SMarc Kleine-Budde /* ... and trigger retransmit */ 19431f0e21a0SMarc Kleine-Budde return mcp25xxfd_chip_set_normal_mode(priv); 19441f0e21a0SMarc Kleine-Budde } 19451f0e21a0SMarc Kleine-Budde 19461f0e21a0SMarc Kleine-Budde static int 19471f0e21a0SMarc Kleine-Budde mcp25xxfd_handle_eccif(struct mcp25xxfd_priv *priv, bool set_normal_mode) 19481f0e21a0SMarc Kleine-Budde { 19491f0e21a0SMarc Kleine-Budde struct mcp25xxfd_ecc *ecc = &priv->ecc; 19501f0e21a0SMarc Kleine-Budde const char *msg; 19511f0e21a0SMarc Kleine-Budde bool in_tx_ram; 19521f0e21a0SMarc Kleine-Budde u32 ecc_stat; 19531f0e21a0SMarc Kleine-Budde u16 addr; 19541f0e21a0SMarc Kleine-Budde u8 nr; 19551f0e21a0SMarc Kleine-Budde int err; 19561f0e21a0SMarc Kleine-Budde 19571f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_ECCSTAT, &ecc_stat); 19581f0e21a0SMarc Kleine-Budde if (err) 19591f0e21a0SMarc Kleine-Budde return err; 19601f0e21a0SMarc Kleine-Budde 19611f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP25XXFD_REG_ECCSTAT, 19621f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_ECCSTAT_IF_MASK, ~ecc_stat); 19631f0e21a0SMarc Kleine-Budde if (err) 19641f0e21a0SMarc Kleine-Budde return err; 19651f0e21a0SMarc Kleine-Budde 19661f0e21a0SMarc Kleine-Budde /* Check if ECC error occurred in TX-RAM */ 19671f0e21a0SMarc Kleine-Budde addr = FIELD_GET(MCP25XXFD_REG_ECCSTAT_ERRADDR_MASK, ecc_stat); 19681f0e21a0SMarc Kleine-Budde err = mcp25xxfd_get_tx_nr_by_addr(priv->tx, &nr, addr); 19691f0e21a0SMarc Kleine-Budde if (!err) 19701f0e21a0SMarc Kleine-Budde in_tx_ram = true; 19711f0e21a0SMarc Kleine-Budde else if (err == -ENOENT) 19721f0e21a0SMarc Kleine-Budde in_tx_ram = false; 19731f0e21a0SMarc Kleine-Budde else 19741f0e21a0SMarc Kleine-Budde return err; 19751f0e21a0SMarc Kleine-Budde 19761f0e21a0SMarc Kleine-Budde /* Errata Reference: 19771f0e21a0SMarc Kleine-Budde * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 2. 19781f0e21a0SMarc Kleine-Budde * 19791f0e21a0SMarc Kleine-Budde * ECC single error correction does not work in all cases: 19801f0e21a0SMarc Kleine-Budde * 19811f0e21a0SMarc Kleine-Budde * Fix/Work Around: 19821f0e21a0SMarc Kleine-Budde * Enable single error correction and double error detection 19831f0e21a0SMarc Kleine-Budde * interrupts by setting SECIE and DEDIE. Handle SECIF as a 19841f0e21a0SMarc Kleine-Budde * detection interrupt and do not rely on the error 19851f0e21a0SMarc Kleine-Budde * correction. Instead, handle both interrupts as a 19861f0e21a0SMarc Kleine-Budde * notification that the RAM word at ERRADDR was corrupted. 19871f0e21a0SMarc Kleine-Budde */ 19881f0e21a0SMarc Kleine-Budde if (ecc_stat & MCP25XXFD_REG_ECCSTAT_SECIF) 19891f0e21a0SMarc Kleine-Budde msg = "Single ECC Error detected at address"; 19901f0e21a0SMarc Kleine-Budde else if (ecc_stat & MCP25XXFD_REG_ECCSTAT_DEDIF) 19911f0e21a0SMarc Kleine-Budde msg = "Double ECC Error detected at address"; 19921f0e21a0SMarc Kleine-Budde else 19931f0e21a0SMarc Kleine-Budde return -EINVAL; 19941f0e21a0SMarc Kleine-Budde 19951f0e21a0SMarc Kleine-Budde if (!in_tx_ram) { 19961f0e21a0SMarc Kleine-Budde ecc->ecc_stat = 0; 19971f0e21a0SMarc Kleine-Budde 19981f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, "%s 0x%04x.\n", msg, addr); 19991f0e21a0SMarc Kleine-Budde } else { 20001f0e21a0SMarc Kleine-Budde /* Re-occurring error? */ 20011f0e21a0SMarc Kleine-Budde if (ecc->ecc_stat == ecc_stat) { 20021f0e21a0SMarc Kleine-Budde ecc->cnt++; 20031f0e21a0SMarc Kleine-Budde } else { 20041f0e21a0SMarc Kleine-Budde ecc->ecc_stat = ecc_stat; 20051f0e21a0SMarc Kleine-Budde ecc->cnt = 1; 20061f0e21a0SMarc Kleine-Budde } 20071f0e21a0SMarc Kleine-Budde 20081f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 20091f0e21a0SMarc Kleine-Budde "%s 0x%04x (in TX-RAM, tx_obj=%d), occurred %d time%s.\n", 20101f0e21a0SMarc Kleine-Budde msg, addr, nr, ecc->cnt, ecc->cnt > 1 ? "s" : ""); 20111f0e21a0SMarc Kleine-Budde 20121f0e21a0SMarc Kleine-Budde if (ecc->cnt >= MCP25XXFD_ECC_CNT_MAX) 20131f0e21a0SMarc Kleine-Budde return mcp25xxfd_handle_eccif_recover(priv, nr); 20141f0e21a0SMarc Kleine-Budde } 20151f0e21a0SMarc Kleine-Budde 20161f0e21a0SMarc Kleine-Budde if (set_normal_mode) 20171f0e21a0SMarc Kleine-Budde return mcp25xxfd_chip_set_normal_mode_nowait(priv); 20181f0e21a0SMarc Kleine-Budde 20191f0e21a0SMarc Kleine-Budde return 0; 20201f0e21a0SMarc Kleine-Budde } 20211f0e21a0SMarc Kleine-Budde 20221f0e21a0SMarc Kleine-Budde static int mcp25xxfd_handle_spicrcif(struct mcp25xxfd_priv *priv) 20231f0e21a0SMarc Kleine-Budde { 20241f0e21a0SMarc Kleine-Budde int err; 20251f0e21a0SMarc Kleine-Budde u32 crc; 20261f0e21a0SMarc Kleine-Budde 20271f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_CRC, &crc); 20281f0e21a0SMarc Kleine-Budde if (err) 20291f0e21a0SMarc Kleine-Budde return err; 20301f0e21a0SMarc Kleine-Budde 20311f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP25XXFD_REG_CRC, 20321f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_CRC_IF_MASK, 20331f0e21a0SMarc Kleine-Budde ~crc); 20341f0e21a0SMarc Kleine-Budde if (err) 20351f0e21a0SMarc Kleine-Budde return err; 20361f0e21a0SMarc Kleine-Budde 20371f0e21a0SMarc Kleine-Budde if (crc & MCP25XXFD_REG_CRC_FERRIF) 20381f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, "CRC write command format error.\n"); 20391f0e21a0SMarc Kleine-Budde else if (crc & MCP25XXFD_REG_CRC_CRCERRIF) 20401f0e21a0SMarc Kleine-Budde netdev_notice(priv->ndev, 20411f0e21a0SMarc Kleine-Budde "CRC write error detected. CRC=0x%04lx.\n", 20421f0e21a0SMarc Kleine-Budde FIELD_GET(MCP25XXFD_REG_CRC_MASK, crc)); 20431f0e21a0SMarc Kleine-Budde 20441f0e21a0SMarc Kleine-Budde return 0; 20451f0e21a0SMarc Kleine-Budde } 20461f0e21a0SMarc Kleine-Budde 20471f0e21a0SMarc Kleine-Budde #define mcp25xxfd_handle(priv, irq, ...) \ 20481f0e21a0SMarc Kleine-Budde ({ \ 20491f0e21a0SMarc Kleine-Budde struct mcp25xxfd_priv *_priv = (priv); \ 20501f0e21a0SMarc Kleine-Budde int err; \ 20511f0e21a0SMarc Kleine-Budde \ 20521f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle_##irq(_priv, ## __VA_ARGS__); \ 20531f0e21a0SMarc Kleine-Budde if (err) \ 20541f0e21a0SMarc Kleine-Budde netdev_err(_priv->ndev, \ 20551f0e21a0SMarc Kleine-Budde "IRQ handler mcp25xxfd_handle_%s() returned %d.\n", \ 20561f0e21a0SMarc Kleine-Budde __stringify(irq), err); \ 20571f0e21a0SMarc Kleine-Budde err; \ 20581f0e21a0SMarc Kleine-Budde }) 20591f0e21a0SMarc Kleine-Budde 20601f0e21a0SMarc Kleine-Budde static irqreturn_t mcp25xxfd_irq(int irq, void *dev_id) 20611f0e21a0SMarc Kleine-Budde { 20621f0e21a0SMarc Kleine-Budde struct mcp25xxfd_priv *priv = dev_id; 20631f0e21a0SMarc Kleine-Budde irqreturn_t handled = IRQ_NONE; 20641f0e21a0SMarc Kleine-Budde int err; 20651f0e21a0SMarc Kleine-Budde 20661f0e21a0SMarc Kleine-Budde if (priv->rx_int) 20671f0e21a0SMarc Kleine-Budde do { 20681f0e21a0SMarc Kleine-Budde int rx_pending; 20691f0e21a0SMarc Kleine-Budde 20701f0e21a0SMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 20711f0e21a0SMarc Kleine-Budde if (!rx_pending) 20721f0e21a0SMarc Kleine-Budde break; 20731f0e21a0SMarc Kleine-Budde 20741f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, rxif); 20751f0e21a0SMarc Kleine-Budde if (err) 20761f0e21a0SMarc Kleine-Budde goto out_fail; 20771f0e21a0SMarc Kleine-Budde 20781f0e21a0SMarc Kleine-Budde handled = IRQ_HANDLED; 20791f0e21a0SMarc Kleine-Budde } while (1); 20801f0e21a0SMarc Kleine-Budde 20811f0e21a0SMarc Kleine-Budde do { 20821f0e21a0SMarc Kleine-Budde u32 intf_pending, intf_pending_clearable; 20831f0e21a0SMarc Kleine-Budde bool set_normal_mode = false; 20841f0e21a0SMarc Kleine-Budde 20851f0e21a0SMarc Kleine-Budde err = regmap_bulk_read(priv->map_reg, MCP25XXFD_REG_INT, 20861f0e21a0SMarc Kleine-Budde &priv->regs_status, 20871f0e21a0SMarc Kleine-Budde sizeof(priv->regs_status) / 20881f0e21a0SMarc Kleine-Budde sizeof(u32)); 20891f0e21a0SMarc Kleine-Budde if (err) 20901f0e21a0SMarc Kleine-Budde goto out_fail; 20911f0e21a0SMarc Kleine-Budde 20921f0e21a0SMarc Kleine-Budde intf_pending = FIELD_GET(MCP25XXFD_REG_INT_IF_MASK, 20931f0e21a0SMarc Kleine-Budde priv->regs_status.intf) & 20941f0e21a0SMarc Kleine-Budde FIELD_GET(MCP25XXFD_REG_INT_IE_MASK, 20951f0e21a0SMarc Kleine-Budde priv->regs_status.intf); 20961f0e21a0SMarc Kleine-Budde 20971f0e21a0SMarc Kleine-Budde if (!(intf_pending)) 20981f0e21a0SMarc Kleine-Budde return handled; 20991f0e21a0SMarc Kleine-Budde 21001f0e21a0SMarc Kleine-Budde /* Some interrupts must be ACKed in the 21011f0e21a0SMarc Kleine-Budde * MCP25XXFD_REG_INT register. 21021f0e21a0SMarc Kleine-Budde * - First ACK then handle, to avoid lost-IRQ race 21031f0e21a0SMarc Kleine-Budde * condition on fast re-occurring interrupts. 21041f0e21a0SMarc Kleine-Budde * - Write "0" to clear active IRQs, "1" to all other, 21051f0e21a0SMarc Kleine-Budde * to avoid r/m/w race condition on the 21061f0e21a0SMarc Kleine-Budde * MCP25XXFD_REG_INT register. 21071f0e21a0SMarc Kleine-Budde */ 21081f0e21a0SMarc Kleine-Budde intf_pending_clearable = intf_pending & 21091f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_IF_CLEARABLE_MASK; 21101f0e21a0SMarc Kleine-Budde if (intf_pending_clearable) { 21111f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 21121f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT, 21131f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_INT_IF_MASK, 21141f0e21a0SMarc Kleine-Budde ~intf_pending_clearable); 21151f0e21a0SMarc Kleine-Budde if (err) 21161f0e21a0SMarc Kleine-Budde goto out_fail; 21171f0e21a0SMarc Kleine-Budde } 21181f0e21a0SMarc Kleine-Budde 21191f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_MODIF) { 21201f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, modif, &set_normal_mode); 21211f0e21a0SMarc Kleine-Budde if (err) 21221f0e21a0SMarc Kleine-Budde goto out_fail; 21231f0e21a0SMarc Kleine-Budde } 21241f0e21a0SMarc Kleine-Budde 21251f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_RXIF) { 21261f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, rxif); 21271f0e21a0SMarc Kleine-Budde if (err) 21281f0e21a0SMarc Kleine-Budde goto out_fail; 21291f0e21a0SMarc Kleine-Budde } 21301f0e21a0SMarc Kleine-Budde 21311f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_TEFIF) { 21321f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, tefif); 21331f0e21a0SMarc Kleine-Budde if (err) 21341f0e21a0SMarc Kleine-Budde goto out_fail; 21351f0e21a0SMarc Kleine-Budde } 21361f0e21a0SMarc Kleine-Budde 21371f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_RXOVIF) { 21381f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, rxovif); 21391f0e21a0SMarc Kleine-Budde if (err) 21401f0e21a0SMarc Kleine-Budde goto out_fail; 21411f0e21a0SMarc Kleine-Budde } 21421f0e21a0SMarc Kleine-Budde 21431f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_TXATIF) { 21441f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, txatif); 21451f0e21a0SMarc Kleine-Budde if (err) 21461f0e21a0SMarc Kleine-Budde goto out_fail; 21471f0e21a0SMarc Kleine-Budde } 21481f0e21a0SMarc Kleine-Budde 21491f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_IVMIF) { 21501f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, ivmif); 21511f0e21a0SMarc Kleine-Budde if (err) 21521f0e21a0SMarc Kleine-Budde goto out_fail; 21531f0e21a0SMarc Kleine-Budde } 21541f0e21a0SMarc Kleine-Budde 21551f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_SERRIF) { 21561f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, serrif); 21571f0e21a0SMarc Kleine-Budde if (err) 21581f0e21a0SMarc Kleine-Budde goto out_fail; 21591f0e21a0SMarc Kleine-Budde } 21601f0e21a0SMarc Kleine-Budde 21611f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_ECCIF) { 21621f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, eccif, set_normal_mode); 21631f0e21a0SMarc Kleine-Budde if (err) 21641f0e21a0SMarc Kleine-Budde goto out_fail; 21651f0e21a0SMarc Kleine-Budde } 21661f0e21a0SMarc Kleine-Budde 21671f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_SPICRCIF) { 21681f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, spicrcif); 21691f0e21a0SMarc Kleine-Budde if (err) 21701f0e21a0SMarc Kleine-Budde goto out_fail; 21711f0e21a0SMarc Kleine-Budde } 21721f0e21a0SMarc Kleine-Budde 21731f0e21a0SMarc Kleine-Budde /* On the MCP2527FD and MCP2518FD, we don't get a 21741f0e21a0SMarc Kleine-Budde * CERRIF IRQ on the transition TX ERROR_WARNING -> TX 21751f0e21a0SMarc Kleine-Budde * ERROR_ACTIVE. 21761f0e21a0SMarc Kleine-Budde */ 21771f0e21a0SMarc Kleine-Budde if (intf_pending & MCP25XXFD_REG_INT_CERRIF || 21781f0e21a0SMarc Kleine-Budde priv->can.state > CAN_STATE_ERROR_ACTIVE) { 21791f0e21a0SMarc Kleine-Budde err = mcp25xxfd_handle(priv, cerrif); 21801f0e21a0SMarc Kleine-Budde if (err) 21811f0e21a0SMarc Kleine-Budde goto out_fail; 21821f0e21a0SMarc Kleine-Budde 21831f0e21a0SMarc Kleine-Budde /* In Bus Off we completely shut down the 21841f0e21a0SMarc Kleine-Budde * controller. Every subsequent register read 21851f0e21a0SMarc Kleine-Budde * will read bogus data, and if 21861f0e21a0SMarc Kleine-Budde * MCP25XXFD_QUIRK_CRC_REG is enabled the CRC 21871f0e21a0SMarc Kleine-Budde * check will fail, too. So leave IRQ handler 21881f0e21a0SMarc Kleine-Budde * directly. 21891f0e21a0SMarc Kleine-Budde */ 21901f0e21a0SMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) 21911f0e21a0SMarc Kleine-Budde return IRQ_HANDLED; 21921f0e21a0SMarc Kleine-Budde } 21931f0e21a0SMarc Kleine-Budde 21941f0e21a0SMarc Kleine-Budde handled = IRQ_HANDLED; 21951f0e21a0SMarc Kleine-Budde } while (1); 21961f0e21a0SMarc Kleine-Budde 21971f0e21a0SMarc Kleine-Budde out_fail: 21981f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n", 21991f0e21a0SMarc Kleine-Budde err, priv->regs_status.intf); 22001f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_interrupts_disable(priv); 22011f0e21a0SMarc Kleine-Budde 22021f0e21a0SMarc Kleine-Budde return handled; 22031f0e21a0SMarc Kleine-Budde } 22041f0e21a0SMarc Kleine-Budde 22051f0e21a0SMarc Kleine-Budde static inline struct 22061f0e21a0SMarc Kleine-Budde mcp25xxfd_tx_obj *mcp25xxfd_get_tx_obj_next(struct mcp25xxfd_tx_ring *tx_ring) 22071f0e21a0SMarc Kleine-Budde { 22081f0e21a0SMarc Kleine-Budde u8 tx_head; 22091f0e21a0SMarc Kleine-Budde 22101f0e21a0SMarc Kleine-Budde tx_head = mcp25xxfd_get_tx_head(tx_ring); 22111f0e21a0SMarc Kleine-Budde 22121f0e21a0SMarc Kleine-Budde return &tx_ring->obj[tx_head]; 22131f0e21a0SMarc Kleine-Budde } 22141f0e21a0SMarc Kleine-Budde 22151f0e21a0SMarc Kleine-Budde static void 22161f0e21a0SMarc Kleine-Budde mcp25xxfd_tx_obj_from_skb(const struct mcp25xxfd_priv *priv, 22171f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_obj *tx_obj, 22181f0e21a0SMarc Kleine-Budde const struct sk_buff *skb, 22191f0e21a0SMarc Kleine-Budde unsigned int seq) 22201f0e21a0SMarc Kleine-Budde { 22211f0e21a0SMarc Kleine-Budde const struct canfd_frame *cfd = (struct canfd_frame *)skb->data; 22221f0e21a0SMarc Kleine-Budde struct mcp25xxfd_hw_tx_obj_raw *hw_tx_obj; 22231f0e21a0SMarc Kleine-Budde union mcp25xxfd_tx_obj_load_buf *load_buf; 22241f0e21a0SMarc Kleine-Budde u8 dlc; 22251f0e21a0SMarc Kleine-Budde u32 id, flags; 22261f0e21a0SMarc Kleine-Budde int offset, len; 22271f0e21a0SMarc Kleine-Budde 22281f0e21a0SMarc Kleine-Budde if (cfd->can_id & CAN_EFF_FLAG) { 22291f0e21a0SMarc Kleine-Budde u32 sid, eid; 22301f0e21a0SMarc Kleine-Budde 22311f0e21a0SMarc Kleine-Budde sid = FIELD_GET(MCP25XXFD_REG_FRAME_EFF_SID_MASK, cfd->can_id); 22321f0e21a0SMarc Kleine-Budde eid = FIELD_GET(MCP25XXFD_REG_FRAME_EFF_EID_MASK, cfd->can_id); 22331f0e21a0SMarc Kleine-Budde 22341f0e21a0SMarc Kleine-Budde id = FIELD_PREP(MCP25XXFD_OBJ_ID_EID_MASK, eid) | 22351f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_OBJ_ID_SID_MASK, sid); 22361f0e21a0SMarc Kleine-Budde 22371f0e21a0SMarc Kleine-Budde flags = MCP25XXFD_OBJ_FLAGS_IDE; 22381f0e21a0SMarc Kleine-Budde } else { 22391f0e21a0SMarc Kleine-Budde id = FIELD_PREP(MCP25XXFD_OBJ_ID_SID_MASK, cfd->can_id); 22401f0e21a0SMarc Kleine-Budde flags = 0; 22411f0e21a0SMarc Kleine-Budde } 22421f0e21a0SMarc Kleine-Budde 22431f0e21a0SMarc Kleine-Budde /* Use the MCP2518FD mask even on the MCP2517FD. It doesn't 22441f0e21a0SMarc Kleine-Budde * harm, only the lower 7 bits will be transferred into the 22451f0e21a0SMarc Kleine-Budde * TEF object. 22461f0e21a0SMarc Kleine-Budde */ 22471f0e21a0SMarc Kleine-Budde dlc = can_len2dlc(cfd->len); 22481f0e21a0SMarc Kleine-Budde flags |= FIELD_PREP(MCP25XXFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq) | 22491f0e21a0SMarc Kleine-Budde FIELD_PREP(MCP25XXFD_OBJ_FLAGS_DLC, dlc); 22501f0e21a0SMarc Kleine-Budde 22511f0e21a0SMarc Kleine-Budde if (cfd->can_id & CAN_RTR_FLAG) 22521f0e21a0SMarc Kleine-Budde flags |= MCP25XXFD_OBJ_FLAGS_RTR; 22531f0e21a0SMarc Kleine-Budde 22541f0e21a0SMarc Kleine-Budde /* CANFD */ 22551f0e21a0SMarc Kleine-Budde if (can_is_canfd_skb(skb)) { 22561f0e21a0SMarc Kleine-Budde if (cfd->flags & CANFD_ESI) 22571f0e21a0SMarc Kleine-Budde flags |= MCP25XXFD_OBJ_FLAGS_ESI; 22581f0e21a0SMarc Kleine-Budde 22591f0e21a0SMarc Kleine-Budde flags |= MCP25XXFD_OBJ_FLAGS_FDF; 22601f0e21a0SMarc Kleine-Budde 22611f0e21a0SMarc Kleine-Budde if (cfd->flags & CANFD_BRS) 22621f0e21a0SMarc Kleine-Budde flags |= MCP25XXFD_OBJ_FLAGS_BRS; 22631f0e21a0SMarc Kleine-Budde } 22641f0e21a0SMarc Kleine-Budde 22651f0e21a0SMarc Kleine-Budde load_buf = &tx_obj->buf; 22661f0e21a0SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_TX) 22671f0e21a0SMarc Kleine-Budde hw_tx_obj = &load_buf->crc.hw_tx_obj; 22681f0e21a0SMarc Kleine-Budde else 22691f0e21a0SMarc Kleine-Budde hw_tx_obj = &load_buf->nocrc.hw_tx_obj; 22701f0e21a0SMarc Kleine-Budde 22711f0e21a0SMarc Kleine-Budde put_unaligned_le32(id, &hw_tx_obj->id); 22721f0e21a0SMarc Kleine-Budde put_unaligned_le32(flags, &hw_tx_obj->flags); 22731f0e21a0SMarc Kleine-Budde 22741f0e21a0SMarc Kleine-Budde /* Clear data at end of CAN frame */ 22751f0e21a0SMarc Kleine-Budde offset = round_down(cfd->len, sizeof(u32)); 22761f0e21a0SMarc Kleine-Budde len = round_up(can_dlc2len(dlc), sizeof(u32)) - offset; 22771f0e21a0SMarc Kleine-Budde if (MCP25XXFD_SANITIZE_CAN && len) 22781f0e21a0SMarc Kleine-Budde memset(hw_tx_obj->data + offset, 0x0, len); 22791f0e21a0SMarc Kleine-Budde memcpy(hw_tx_obj->data, cfd->data, cfd->len); 22801f0e21a0SMarc Kleine-Budde 22811f0e21a0SMarc Kleine-Budde /* Number of bytes to be written into the RAM of the controller */ 22821f0e21a0SMarc Kleine-Budde len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags); 22831f0e21a0SMarc Kleine-Budde if (MCP25XXFD_SANITIZE_CAN) 22841f0e21a0SMarc Kleine-Budde len += round_up(can_dlc2len(dlc), sizeof(u32)); 22851f0e21a0SMarc Kleine-Budde else 22861f0e21a0SMarc Kleine-Budde len += round_up(cfd->len, sizeof(u32)); 22871f0e21a0SMarc Kleine-Budde 22881f0e21a0SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_TX) { 22891f0e21a0SMarc Kleine-Budde u16 crc; 22901f0e21a0SMarc Kleine-Budde 22911f0e21a0SMarc Kleine-Budde mcp25xxfd_spi_cmd_crc_set_len_in_ram(&load_buf->crc.cmd, 22921f0e21a0SMarc Kleine-Budde len); 22931f0e21a0SMarc Kleine-Budde /* CRC */ 22941f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->crc.cmd); 22951f0e21a0SMarc Kleine-Budde crc = mcp25xxfd_crc16_compute(&load_buf->crc, len); 22961f0e21a0SMarc Kleine-Budde put_unaligned_be16(crc, (void *)load_buf + len); 22971f0e21a0SMarc Kleine-Budde 22981f0e21a0SMarc Kleine-Budde /* Total length */ 22991f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->crc.crc); 23001f0e21a0SMarc Kleine-Budde } else { 23011f0e21a0SMarc Kleine-Budde len += sizeof(load_buf->nocrc.cmd); 23021f0e21a0SMarc Kleine-Budde } 23031f0e21a0SMarc Kleine-Budde 23041f0e21a0SMarc Kleine-Budde tx_obj->xfer[0].len = len; 23051f0e21a0SMarc Kleine-Budde } 23061f0e21a0SMarc Kleine-Budde 23071f0e21a0SMarc Kleine-Budde static int mcp25xxfd_tx_obj_write(const struct mcp25xxfd_priv *priv, 23081f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_obj *tx_obj) 23091f0e21a0SMarc Kleine-Budde { 23101f0e21a0SMarc Kleine-Budde return spi_async(priv->spi, &tx_obj->msg); 23111f0e21a0SMarc Kleine-Budde } 23121f0e21a0SMarc Kleine-Budde 23131f0e21a0SMarc Kleine-Budde static bool mcp25xxfd_tx_busy(const struct mcp25xxfd_priv *priv, 23141f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_ring *tx_ring) 23151f0e21a0SMarc Kleine-Budde { 23161f0e21a0SMarc Kleine-Budde if (mcp25xxfd_get_tx_free(tx_ring) > 0) 23171f0e21a0SMarc Kleine-Budde return false; 23181f0e21a0SMarc Kleine-Budde 23191f0e21a0SMarc Kleine-Budde netif_stop_queue(priv->ndev); 23201f0e21a0SMarc Kleine-Budde 23211f0e21a0SMarc Kleine-Budde /* Memory barrier before checking tx_free (head and tail) */ 23221f0e21a0SMarc Kleine-Budde smp_mb(); 23231f0e21a0SMarc Kleine-Budde 23241f0e21a0SMarc Kleine-Budde if (mcp25xxfd_get_tx_free(tx_ring) == 0) { 23251f0e21a0SMarc Kleine-Budde netdev_dbg(priv->ndev, 23261f0e21a0SMarc Kleine-Budde "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n", 23271f0e21a0SMarc Kleine-Budde tx_ring->head, tx_ring->tail, 23281f0e21a0SMarc Kleine-Budde tx_ring->head - tx_ring->tail); 23291f0e21a0SMarc Kleine-Budde 23301f0e21a0SMarc Kleine-Budde return true; 23311f0e21a0SMarc Kleine-Budde } 23321f0e21a0SMarc Kleine-Budde 23331f0e21a0SMarc Kleine-Budde netif_start_queue(priv->ndev); 23341f0e21a0SMarc Kleine-Budde 23351f0e21a0SMarc Kleine-Budde return false; 23361f0e21a0SMarc Kleine-Budde } 23371f0e21a0SMarc Kleine-Budde 23381f0e21a0SMarc Kleine-Budde static netdev_tx_t mcp25xxfd_start_xmit(struct sk_buff *skb, 23391f0e21a0SMarc Kleine-Budde struct net_device *ndev) 23401f0e21a0SMarc Kleine-Budde { 23411f0e21a0SMarc Kleine-Budde struct mcp25xxfd_priv *priv = netdev_priv(ndev); 23421f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_ring *tx_ring = priv->tx; 23431f0e21a0SMarc Kleine-Budde struct mcp25xxfd_tx_obj *tx_obj; 23441f0e21a0SMarc Kleine-Budde u8 tx_head; 23451f0e21a0SMarc Kleine-Budde int err; 23461f0e21a0SMarc Kleine-Budde 23471f0e21a0SMarc Kleine-Budde if (can_dropped_invalid_skb(ndev, skb)) 23481f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 23491f0e21a0SMarc Kleine-Budde 23501f0e21a0SMarc Kleine-Budde if (mcp25xxfd_tx_busy(priv, tx_ring)) 23511f0e21a0SMarc Kleine-Budde return NETDEV_TX_BUSY; 23521f0e21a0SMarc Kleine-Budde 23531f0e21a0SMarc Kleine-Budde tx_obj = mcp25xxfd_get_tx_obj_next(tx_ring); 23541f0e21a0SMarc Kleine-Budde mcp25xxfd_tx_obj_from_skb(priv, tx_obj, skb, tx_ring->head); 23551f0e21a0SMarc Kleine-Budde 23561f0e21a0SMarc Kleine-Budde /* Stop queue if we occupy the complete TX FIFO */ 23571f0e21a0SMarc Kleine-Budde tx_head = mcp25xxfd_get_tx_head(tx_ring); 23581f0e21a0SMarc Kleine-Budde tx_ring->head++; 23591f0e21a0SMarc Kleine-Budde if (tx_ring->head - tx_ring->tail >= tx_ring->obj_num) 23601f0e21a0SMarc Kleine-Budde netif_stop_queue(ndev); 23611f0e21a0SMarc Kleine-Budde 23621f0e21a0SMarc Kleine-Budde can_put_echo_skb(skb, ndev, tx_head); 23631f0e21a0SMarc Kleine-Budde 23641f0e21a0SMarc Kleine-Budde err = mcp25xxfd_tx_obj_write(priv, tx_obj); 23651f0e21a0SMarc Kleine-Budde if (err) 23661f0e21a0SMarc Kleine-Budde goto out_err; 23671f0e21a0SMarc Kleine-Budde 23681f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 23691f0e21a0SMarc Kleine-Budde 23701f0e21a0SMarc Kleine-Budde out_err: 23711f0e21a0SMarc Kleine-Budde netdev_err(priv->ndev, "ERROR in %s: %d\n", __func__, err); 23721f0e21a0SMarc Kleine-Budde 23731f0e21a0SMarc Kleine-Budde return NETDEV_TX_OK; 23741f0e21a0SMarc Kleine-Budde } 23751f0e21a0SMarc Kleine-Budde 23761f0e21a0SMarc Kleine-Budde static int mcp25xxfd_open(struct net_device *ndev) 23771f0e21a0SMarc Kleine-Budde { 23781f0e21a0SMarc Kleine-Budde struct mcp25xxfd_priv *priv = netdev_priv(ndev); 23791f0e21a0SMarc Kleine-Budde const struct spi_device *spi = priv->spi; 23801f0e21a0SMarc Kleine-Budde int err; 23811f0e21a0SMarc Kleine-Budde 23821f0e21a0SMarc Kleine-Budde err = pm_runtime_get_sync(ndev->dev.parent); 23831f0e21a0SMarc Kleine-Budde if (err < 0) { 23841f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 23851f0e21a0SMarc Kleine-Budde return err; 23861f0e21a0SMarc Kleine-Budde } 23871f0e21a0SMarc Kleine-Budde 23881f0e21a0SMarc Kleine-Budde err = open_candev(ndev); 23891f0e21a0SMarc Kleine-Budde if (err) 23901f0e21a0SMarc Kleine-Budde goto out_pm_runtime_put; 23911f0e21a0SMarc Kleine-Budde 23921f0e21a0SMarc Kleine-Budde err = mcp25xxfd_ring_alloc(priv); 23931f0e21a0SMarc Kleine-Budde if (err) 23941f0e21a0SMarc Kleine-Budde goto out_close_candev; 23951f0e21a0SMarc Kleine-Budde 23961f0e21a0SMarc Kleine-Budde err = mcp25xxfd_transceiver_enable(priv); 23971f0e21a0SMarc Kleine-Budde if (err) 23981f0e21a0SMarc Kleine-Budde goto out_mcp25xxfd_ring_free; 23991f0e21a0SMarc Kleine-Budde 24001f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_start(priv); 24011f0e21a0SMarc Kleine-Budde if (err) 24021f0e21a0SMarc Kleine-Budde goto out_transceiver_disable; 24031f0e21a0SMarc Kleine-Budde 24041f0e21a0SMarc Kleine-Budde can_rx_offload_enable(&priv->offload); 24051f0e21a0SMarc Kleine-Budde 24061f0e21a0SMarc Kleine-Budde err = request_threaded_irq(spi->irq, NULL, mcp25xxfd_irq, 24071f0e21a0SMarc Kleine-Budde IRQF_ONESHOT, dev_name(&spi->dev), 24081f0e21a0SMarc Kleine-Budde priv); 24091f0e21a0SMarc Kleine-Budde if (err) 24101f0e21a0SMarc Kleine-Budde goto out_can_rx_offload_disable; 24111f0e21a0SMarc Kleine-Budde 24121f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_interrupts_enable(priv); 24131f0e21a0SMarc Kleine-Budde if (err) 24141f0e21a0SMarc Kleine-Budde goto out_free_irq; 24151f0e21a0SMarc Kleine-Budde 24161f0e21a0SMarc Kleine-Budde netif_start_queue(ndev); 24171f0e21a0SMarc Kleine-Budde 24181f0e21a0SMarc Kleine-Budde return 0; 24191f0e21a0SMarc Kleine-Budde 24201f0e21a0SMarc Kleine-Budde out_free_irq: 24211f0e21a0SMarc Kleine-Budde free_irq(spi->irq, priv); 24221f0e21a0SMarc Kleine-Budde out_can_rx_offload_disable: 24231f0e21a0SMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 24241f0e21a0SMarc Kleine-Budde out_transceiver_disable: 24251f0e21a0SMarc Kleine-Budde mcp25xxfd_transceiver_disable(priv); 24261f0e21a0SMarc Kleine-Budde out_mcp25xxfd_ring_free: 24271f0e21a0SMarc Kleine-Budde mcp25xxfd_ring_free(priv); 24281f0e21a0SMarc Kleine-Budde out_close_candev: 24291f0e21a0SMarc Kleine-Budde close_candev(ndev); 24301f0e21a0SMarc Kleine-Budde out_pm_runtime_put: 24311f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_stop(priv, CAN_STATE_STOPPED); 24321f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 24331f0e21a0SMarc Kleine-Budde 24341f0e21a0SMarc Kleine-Budde return err; 24351f0e21a0SMarc Kleine-Budde } 24361f0e21a0SMarc Kleine-Budde 24371f0e21a0SMarc Kleine-Budde static int mcp25xxfd_stop(struct net_device *ndev) 24381f0e21a0SMarc Kleine-Budde { 24391f0e21a0SMarc Kleine-Budde struct mcp25xxfd_priv *priv = netdev_priv(ndev); 24401f0e21a0SMarc Kleine-Budde 24411f0e21a0SMarc Kleine-Budde netif_stop_queue(ndev); 24421f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_interrupts_disable(priv); 24431f0e21a0SMarc Kleine-Budde free_irq(ndev->irq, priv); 24441f0e21a0SMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 24451f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_stop(priv, CAN_STATE_STOPPED); 24461f0e21a0SMarc Kleine-Budde mcp25xxfd_transceiver_disable(priv); 24471f0e21a0SMarc Kleine-Budde mcp25xxfd_ring_free(priv); 24481f0e21a0SMarc Kleine-Budde close_candev(ndev); 24491f0e21a0SMarc Kleine-Budde 24501f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 24511f0e21a0SMarc Kleine-Budde 24521f0e21a0SMarc Kleine-Budde return 0; 24531f0e21a0SMarc Kleine-Budde } 24541f0e21a0SMarc Kleine-Budde 24551f0e21a0SMarc Kleine-Budde static const struct net_device_ops mcp25xxfd_netdev_ops = { 24561f0e21a0SMarc Kleine-Budde .ndo_open = mcp25xxfd_open, 24571f0e21a0SMarc Kleine-Budde .ndo_stop = mcp25xxfd_stop, 24581f0e21a0SMarc Kleine-Budde .ndo_start_xmit = mcp25xxfd_start_xmit, 24591f0e21a0SMarc Kleine-Budde .ndo_change_mtu = can_change_mtu, 24601f0e21a0SMarc Kleine-Budde }; 24611f0e21a0SMarc Kleine-Budde 24621f0e21a0SMarc Kleine-Budde static void 24631f0e21a0SMarc Kleine-Budde mcp25xxfd_register_quirks(struct mcp25xxfd_priv *priv) 24641f0e21a0SMarc Kleine-Budde { 24651f0e21a0SMarc Kleine-Budde const struct spi_device *spi = priv->spi; 24661f0e21a0SMarc Kleine-Budde const struct spi_controller *ctlr = spi->controller; 24671f0e21a0SMarc Kleine-Budde 24681f0e21a0SMarc Kleine-Budde if (ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX) 24691f0e21a0SMarc Kleine-Budde priv->devtype_data.quirks |= MCP25XXFD_QUIRK_HALF_DUPLEX; 24701f0e21a0SMarc Kleine-Budde } 24711f0e21a0SMarc Kleine-Budde 24721f0e21a0SMarc Kleine-Budde static int mcp25xxfd_register_chip_detect(struct mcp25xxfd_priv *priv) 24731f0e21a0SMarc Kleine-Budde { 24741f0e21a0SMarc Kleine-Budde const struct net_device *ndev = priv->ndev; 24751f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_devtype_data *devtype_data; 24761f0e21a0SMarc Kleine-Budde u32 osc; 24771f0e21a0SMarc Kleine-Budde int err; 24781f0e21a0SMarc Kleine-Budde 24791f0e21a0SMarc Kleine-Budde /* The OSC_LPMEN is only supported on MCP2518FD, so use it to 24801f0e21a0SMarc Kleine-Budde * autodetect the model. 24811f0e21a0SMarc Kleine-Budde */ 24821f0e21a0SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP25XXFD_REG_OSC, 24831f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_OSC_LPMEN, 24841f0e21a0SMarc Kleine-Budde MCP25XXFD_REG_OSC_LPMEN); 24851f0e21a0SMarc Kleine-Budde if (err) 24861f0e21a0SMarc Kleine-Budde return err; 24871f0e21a0SMarc Kleine-Budde 24881f0e21a0SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP25XXFD_REG_OSC, &osc); 24891f0e21a0SMarc Kleine-Budde if (err) 24901f0e21a0SMarc Kleine-Budde return err; 24911f0e21a0SMarc Kleine-Budde 24921f0e21a0SMarc Kleine-Budde if (osc & MCP25XXFD_REG_OSC_LPMEN) 24931f0e21a0SMarc Kleine-Budde devtype_data = &mcp25xxfd_devtype_data_mcp2518fd; 24941f0e21a0SMarc Kleine-Budde else 24951f0e21a0SMarc Kleine-Budde devtype_data = &mcp25xxfd_devtype_data_mcp2517fd; 24961f0e21a0SMarc Kleine-Budde 24971f0e21a0SMarc Kleine-Budde if (!mcp25xxfd_is_251X(priv) && 24981f0e21a0SMarc Kleine-Budde priv->devtype_data.model != devtype_data->model) { 24991f0e21a0SMarc Kleine-Budde netdev_info(ndev, 25001f0e21a0SMarc Kleine-Budde "Detected %s, but firmware specifies a %s. Fixing up.", 25011f0e21a0SMarc Kleine-Budde __mcp25xxfd_get_model_str(devtype_data->model), 25021f0e21a0SMarc Kleine-Budde mcp25xxfd_get_model_str(priv)); 25031f0e21a0SMarc Kleine-Budde } 25041f0e21a0SMarc Kleine-Budde priv->devtype_data = *devtype_data; 25051f0e21a0SMarc Kleine-Budde 25061f0e21a0SMarc Kleine-Budde /* We need to preserve the Half Duplex Quirk. */ 25071f0e21a0SMarc Kleine-Budde mcp25xxfd_register_quirks(priv); 25081f0e21a0SMarc Kleine-Budde 25091f0e21a0SMarc Kleine-Budde /* Re-init regmap with quirks of detected model. */ 25101f0e21a0SMarc Kleine-Budde return mcp25xxfd_regmap_init(priv); 25111f0e21a0SMarc Kleine-Budde } 25121f0e21a0SMarc Kleine-Budde 25131f0e21a0SMarc Kleine-Budde static int mcp25xxfd_register_check_rx_int(struct mcp25xxfd_priv *priv) 25141f0e21a0SMarc Kleine-Budde { 25151f0e21a0SMarc Kleine-Budde int err, rx_pending; 25161f0e21a0SMarc Kleine-Budde 25171f0e21a0SMarc Kleine-Budde if (!priv->rx_int) 25181f0e21a0SMarc Kleine-Budde return 0; 25191f0e21a0SMarc Kleine-Budde 25201f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_rx_int_enable(priv); 25211f0e21a0SMarc Kleine-Budde if (err) 25221f0e21a0SMarc Kleine-Budde return err; 25231f0e21a0SMarc Kleine-Budde 25241f0e21a0SMarc Kleine-Budde /* Check if RX_INT is properly working. The RX_INT should not 25251f0e21a0SMarc Kleine-Budde * be active after a softreset. 25261f0e21a0SMarc Kleine-Budde */ 25271f0e21a0SMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 25281f0e21a0SMarc Kleine-Budde 25291f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_rx_int_disable(priv); 25301f0e21a0SMarc Kleine-Budde if (err) 25311f0e21a0SMarc Kleine-Budde return err; 25321f0e21a0SMarc Kleine-Budde 25331f0e21a0SMarc Kleine-Budde if (!rx_pending) 25341f0e21a0SMarc Kleine-Budde return 0; 25351f0e21a0SMarc Kleine-Budde 25361f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 25371f0e21a0SMarc Kleine-Budde "RX_INT active after softreset, disabling RX_INT support."); 25381f0e21a0SMarc Kleine-Budde devm_gpiod_put(&priv->spi->dev, priv->rx_int); 25391f0e21a0SMarc Kleine-Budde priv->rx_int = NULL; 25401f0e21a0SMarc Kleine-Budde 25411f0e21a0SMarc Kleine-Budde return 0; 25421f0e21a0SMarc Kleine-Budde } 25431f0e21a0SMarc Kleine-Budde 25441f0e21a0SMarc Kleine-Budde static int 25451f0e21a0SMarc Kleine-Budde mcp25xxfd_register_get_dev_id(const struct mcp25xxfd_priv *priv, 25461f0e21a0SMarc Kleine-Budde u32 *dev_id, u32 *effective_speed_hz) 25471f0e21a0SMarc Kleine-Budde { 25481f0e21a0SMarc Kleine-Budde struct mcp25xxfd_map_buf_nocrc *buf_rx; 25491f0e21a0SMarc Kleine-Budde struct mcp25xxfd_map_buf_nocrc *buf_tx; 25501f0e21a0SMarc Kleine-Budde struct spi_transfer xfer[2] = { }; 25511f0e21a0SMarc Kleine-Budde int err; 25521f0e21a0SMarc Kleine-Budde 25531f0e21a0SMarc Kleine-Budde buf_rx = kzalloc(sizeof(*buf_rx), GFP_KERNEL); 25541f0e21a0SMarc Kleine-Budde if (!buf_rx) 25551f0e21a0SMarc Kleine-Budde return -ENOMEM; 25561f0e21a0SMarc Kleine-Budde 25571f0e21a0SMarc Kleine-Budde buf_tx = kzalloc(sizeof(*buf_tx), GFP_KERNEL); 25581f0e21a0SMarc Kleine-Budde if (!buf_tx) { 25591f0e21a0SMarc Kleine-Budde err = -ENOMEM; 25601f0e21a0SMarc Kleine-Budde goto out_kfree_buf_rx; 25611f0e21a0SMarc Kleine-Budde } 25621f0e21a0SMarc Kleine-Budde 25631f0e21a0SMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 25641f0e21a0SMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd); 25651f0e21a0SMarc Kleine-Budde xfer[1].rx_buf = buf_rx->data; 25661f0e21a0SMarc Kleine-Budde xfer[1].len = sizeof(dev_id); 25671f0e21a0SMarc Kleine-Budde 25681f0e21a0SMarc Kleine-Budde mcp25xxfd_spi_cmd_read_nocrc(&buf_tx->cmd, MCP25XXFD_REG_DEVID); 25691f0e21a0SMarc Kleine-Budde err = spi_sync_transfer(priv->spi, xfer, ARRAY_SIZE(xfer)); 25701f0e21a0SMarc Kleine-Budde if (err) 25711f0e21a0SMarc Kleine-Budde goto out_kfree_buf_tx; 25721f0e21a0SMarc Kleine-Budde 25731f0e21a0SMarc Kleine-Budde *dev_id = be32_to_cpup((__be32 *)buf_rx->data); 25741f0e21a0SMarc Kleine-Budde *effective_speed_hz = xfer->effective_speed_hz; 25751f0e21a0SMarc Kleine-Budde 25761f0e21a0SMarc Kleine-Budde out_kfree_buf_tx: 25771f0e21a0SMarc Kleine-Budde kfree(buf_tx); 25781f0e21a0SMarc Kleine-Budde out_kfree_buf_rx: 25791f0e21a0SMarc Kleine-Budde kfree(buf_rx); 25801f0e21a0SMarc Kleine-Budde 25811f0e21a0SMarc Kleine-Budde return 0; 25821f0e21a0SMarc Kleine-Budde } 25831f0e21a0SMarc Kleine-Budde 25841f0e21a0SMarc Kleine-Budde #define MCP25XXFD_QUIRK_ACTIVE(quirk) \ 25851f0e21a0SMarc Kleine-Budde (priv->devtype_data.quirks & MCP25XXFD_QUIRK_##quirk ? '+' : '-') 25861f0e21a0SMarc Kleine-Budde 25871f0e21a0SMarc Kleine-Budde static int 25881f0e21a0SMarc Kleine-Budde mcp25xxfd_register_done(const struct mcp25xxfd_priv *priv) 25891f0e21a0SMarc Kleine-Budde { 25901f0e21a0SMarc Kleine-Budde u32 dev_id, effective_speed_hz; 25911f0e21a0SMarc Kleine-Budde int err; 25921f0e21a0SMarc Kleine-Budde 25931f0e21a0SMarc Kleine-Budde err = mcp25xxfd_register_get_dev_id(priv, &dev_id, 25941f0e21a0SMarc Kleine-Budde &effective_speed_hz); 25951f0e21a0SMarc Kleine-Budde if (err) 25961f0e21a0SMarc Kleine-Budde return err; 25971f0e21a0SMarc Kleine-Budde 25981f0e21a0SMarc Kleine-Budde netdev_info(priv->ndev, 25991f0e21a0SMarc 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", 26001f0e21a0SMarc Kleine-Budde mcp25xxfd_get_model_str(priv), 26011f0e21a0SMarc Kleine-Budde FIELD_GET(MCP25XXFD_REG_DEVID_ID_MASK, dev_id), 26021f0e21a0SMarc Kleine-Budde FIELD_GET(MCP25XXFD_REG_DEVID_REV_MASK, dev_id), 26031f0e21a0SMarc Kleine-Budde priv->rx_int ? '+' : '-', 26041f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_ACTIVE(MAB_NO_WARN), 26051f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_ACTIVE(CRC_REG), 26061f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_ACTIVE(CRC_RX), 26071f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_ACTIVE(CRC_TX), 26081f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_ACTIVE(ECC), 26091f0e21a0SMarc Kleine-Budde MCP25XXFD_QUIRK_ACTIVE(HALF_DUPLEX), 26101f0e21a0SMarc Kleine-Budde priv->can.clock.freq / 1000000, 26111f0e21a0SMarc Kleine-Budde priv->can.clock.freq % 1000000 / 1000 / 10, 26121f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig / 1000000, 26131f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig % 1000000 / 1000 / 10, 26141f0e21a0SMarc Kleine-Budde priv->spi->max_speed_hz / 1000000, 26151f0e21a0SMarc Kleine-Budde priv->spi->max_speed_hz % 1000000 / 1000 / 10, 26161f0e21a0SMarc Kleine-Budde effective_speed_hz / 1000000, 26171f0e21a0SMarc Kleine-Budde effective_speed_hz % 1000000 / 1000 / 10); 26181f0e21a0SMarc Kleine-Budde 26191f0e21a0SMarc Kleine-Budde return 0; 26201f0e21a0SMarc Kleine-Budde } 26211f0e21a0SMarc Kleine-Budde 26221f0e21a0SMarc Kleine-Budde static int mcp25xxfd_register(struct mcp25xxfd_priv *priv) 26231f0e21a0SMarc Kleine-Budde { 26241f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 26251f0e21a0SMarc Kleine-Budde int err; 26261f0e21a0SMarc Kleine-Budde 26271f0e21a0SMarc Kleine-Budde err = mcp25xxfd_clks_and_vdd_enable(priv); 26281f0e21a0SMarc Kleine-Budde if (err) 26291f0e21a0SMarc Kleine-Budde return err; 26301f0e21a0SMarc Kleine-Budde 26311f0e21a0SMarc Kleine-Budde pm_runtime_get_noresume(ndev->dev.parent); 26321f0e21a0SMarc Kleine-Budde err = pm_runtime_set_active(ndev->dev.parent); 26331f0e21a0SMarc Kleine-Budde if (err) 26341f0e21a0SMarc Kleine-Budde goto out_runtime_put_noidle; 26351f0e21a0SMarc Kleine-Budde pm_runtime_enable(ndev->dev.parent); 26361f0e21a0SMarc Kleine-Budde 26371f0e21a0SMarc Kleine-Budde mcp25xxfd_register_quirks(priv); 26381f0e21a0SMarc Kleine-Budde 26391f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_softreset(priv); 26401f0e21a0SMarc Kleine-Budde if (err == -ENODEV) 26411f0e21a0SMarc Kleine-Budde goto out_runtime_disable; 26421f0e21a0SMarc Kleine-Budde if (err) 26431f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 26441f0e21a0SMarc Kleine-Budde 26451f0e21a0SMarc Kleine-Budde err = mcp25xxfd_register_chip_detect(priv); 26461f0e21a0SMarc Kleine-Budde if (err) 26471f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 26481f0e21a0SMarc Kleine-Budde 26491f0e21a0SMarc Kleine-Budde err = mcp25xxfd_register_check_rx_int(priv); 26501f0e21a0SMarc Kleine-Budde if (err) 26511f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 26521f0e21a0SMarc Kleine-Budde 26531f0e21a0SMarc Kleine-Budde err = register_candev(ndev); 26541f0e21a0SMarc Kleine-Budde if (err) 26551f0e21a0SMarc Kleine-Budde goto out_chip_set_mode_sleep; 26561f0e21a0SMarc Kleine-Budde 26571f0e21a0SMarc Kleine-Budde err = mcp25xxfd_register_done(priv); 26581f0e21a0SMarc Kleine-Budde if (err) 26591f0e21a0SMarc Kleine-Budde goto out_unregister_candev; 26601f0e21a0SMarc Kleine-Budde 26611f0e21a0SMarc Kleine-Budde /* Put controller into sleep mode and let pm_runtime_put() 26621f0e21a0SMarc Kleine-Budde * disable the clocks and vdd. If CONFIG_PM is not enabled, 26631f0e21a0SMarc Kleine-Budde * the clocks and vdd will stay powered. 26641f0e21a0SMarc Kleine-Budde */ 26651f0e21a0SMarc Kleine-Budde err = mcp25xxfd_chip_set_mode(priv, MCP25XXFD_REG_CON_MODE_SLEEP); 26661f0e21a0SMarc Kleine-Budde if (err) 26671f0e21a0SMarc Kleine-Budde goto out_unregister_candev; 26681f0e21a0SMarc Kleine-Budde 26691f0e21a0SMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 26701f0e21a0SMarc Kleine-Budde 26711f0e21a0SMarc Kleine-Budde return 0; 26721f0e21a0SMarc Kleine-Budde 26731f0e21a0SMarc Kleine-Budde out_unregister_candev: 26741f0e21a0SMarc Kleine-Budde unregister_candev(ndev); 26751f0e21a0SMarc Kleine-Budde out_chip_set_mode_sleep: 26761f0e21a0SMarc Kleine-Budde mcp25xxfd_chip_set_mode(priv, MCP25XXFD_REG_CON_MODE_SLEEP); 26771f0e21a0SMarc Kleine-Budde out_runtime_disable: 26781f0e21a0SMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 26791f0e21a0SMarc Kleine-Budde out_runtime_put_noidle: 26801f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 26811f0e21a0SMarc Kleine-Budde mcp25xxfd_clks_and_vdd_disable(priv); 26821f0e21a0SMarc Kleine-Budde 26831f0e21a0SMarc Kleine-Budde return err; 26841f0e21a0SMarc Kleine-Budde } 26851f0e21a0SMarc Kleine-Budde 26861f0e21a0SMarc Kleine-Budde static inline void mcp25xxfd_unregister(struct mcp25xxfd_priv *priv) 26871f0e21a0SMarc Kleine-Budde { 26881f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 26891f0e21a0SMarc Kleine-Budde 26901f0e21a0SMarc Kleine-Budde unregister_candev(ndev); 26911f0e21a0SMarc Kleine-Budde 26921f0e21a0SMarc Kleine-Budde pm_runtime_get_sync(ndev->dev.parent); 26931f0e21a0SMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 26941f0e21a0SMarc Kleine-Budde mcp25xxfd_clks_and_vdd_disable(priv); 26951f0e21a0SMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 26961f0e21a0SMarc Kleine-Budde } 26971f0e21a0SMarc Kleine-Budde 26981f0e21a0SMarc Kleine-Budde static const struct of_device_id mcp25xxfd_of_match[] = { 26991f0e21a0SMarc Kleine-Budde { 27001f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp2517fd", 27011f0e21a0SMarc Kleine-Budde .data = &mcp25xxfd_devtype_data_mcp2517fd, 27021f0e21a0SMarc Kleine-Budde }, { 27031f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp2518fd", 27041f0e21a0SMarc Kleine-Budde .data = &mcp25xxfd_devtype_data_mcp2518fd, 27051f0e21a0SMarc Kleine-Budde }, { 27061f0e21a0SMarc Kleine-Budde .compatible = "microchip,mcp251xfd", 27071f0e21a0SMarc Kleine-Budde .data = &mcp25xxfd_devtype_data_mcp251xfd, 27081f0e21a0SMarc Kleine-Budde }, { 27091f0e21a0SMarc Kleine-Budde /* sentinel */ 27101f0e21a0SMarc Kleine-Budde }, 27111f0e21a0SMarc Kleine-Budde }; 27121f0e21a0SMarc Kleine-Budde MODULE_DEVICE_TABLE(of, mcp25xxfd_of_match); 27131f0e21a0SMarc Kleine-Budde 27141f0e21a0SMarc Kleine-Budde static const struct spi_device_id mcp25xxfd_id_table[] = { 27151f0e21a0SMarc Kleine-Budde { 27161f0e21a0SMarc Kleine-Budde .name = "mcp2517fd", 27171f0e21a0SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp25xxfd_devtype_data_mcp2517fd, 27181f0e21a0SMarc Kleine-Budde }, { 27191f0e21a0SMarc Kleine-Budde .name = "mcp2518fd", 27201f0e21a0SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp25xxfd_devtype_data_mcp2518fd, 27211f0e21a0SMarc Kleine-Budde }, { 27221f0e21a0SMarc Kleine-Budde .name = "mcp251xfd", 27231f0e21a0SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp25xxfd_devtype_data_mcp251xfd, 27241f0e21a0SMarc Kleine-Budde }, { 27251f0e21a0SMarc Kleine-Budde /* sentinel */ 27261f0e21a0SMarc Kleine-Budde }, 27271f0e21a0SMarc Kleine-Budde }; 27281f0e21a0SMarc Kleine-Budde MODULE_DEVICE_TABLE(spi, mcp25xxfd_id_table); 27291f0e21a0SMarc Kleine-Budde 27301f0e21a0SMarc Kleine-Budde static int mcp25xxfd_probe(struct spi_device *spi) 27311f0e21a0SMarc Kleine-Budde { 27321f0e21a0SMarc Kleine-Budde const void *match; 27331f0e21a0SMarc Kleine-Budde struct net_device *ndev; 27341f0e21a0SMarc Kleine-Budde struct mcp25xxfd_priv *priv; 27351f0e21a0SMarc Kleine-Budde struct gpio_desc *rx_int; 27361f0e21a0SMarc Kleine-Budde struct regulator *reg_vdd, *reg_xceiver; 27371f0e21a0SMarc Kleine-Budde struct clk *clk; 27381f0e21a0SMarc Kleine-Budde u32 freq; 27391f0e21a0SMarc Kleine-Budde int err; 27401f0e21a0SMarc Kleine-Budde 27411f0e21a0SMarc Kleine-Budde rx_int = devm_gpiod_get_optional(&spi->dev, "microchip,rx-int", 27421f0e21a0SMarc Kleine-Budde GPIOD_IN); 27431f0e21a0SMarc Kleine-Budde if (PTR_ERR(rx_int) == -EPROBE_DEFER) 27441f0e21a0SMarc Kleine-Budde return -EPROBE_DEFER; 27451f0e21a0SMarc Kleine-Budde else if (IS_ERR(rx_int)) 27461f0e21a0SMarc Kleine-Budde return PTR_ERR(rx_int); 27471f0e21a0SMarc Kleine-Budde 27481f0e21a0SMarc Kleine-Budde reg_vdd = devm_regulator_get_optional(&spi->dev, "vdd"); 27491f0e21a0SMarc Kleine-Budde if (PTR_ERR(reg_vdd) == -EPROBE_DEFER) 27501f0e21a0SMarc Kleine-Budde return -EPROBE_DEFER; 27511f0e21a0SMarc Kleine-Budde else if (PTR_ERR(reg_vdd) == -ENODEV) 27521f0e21a0SMarc Kleine-Budde reg_vdd = NULL; 27531f0e21a0SMarc Kleine-Budde else if (IS_ERR(reg_vdd)) 27541f0e21a0SMarc Kleine-Budde return PTR_ERR(reg_vdd); 27551f0e21a0SMarc Kleine-Budde 27561f0e21a0SMarc Kleine-Budde reg_xceiver = devm_regulator_get_optional(&spi->dev, "xceiver"); 27571f0e21a0SMarc Kleine-Budde if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER) 27581f0e21a0SMarc Kleine-Budde return -EPROBE_DEFER; 27591f0e21a0SMarc Kleine-Budde else if (PTR_ERR(reg_xceiver) == -ENODEV) 27601f0e21a0SMarc Kleine-Budde reg_xceiver = NULL; 27611f0e21a0SMarc Kleine-Budde else if (IS_ERR(reg_xceiver)) 27621f0e21a0SMarc Kleine-Budde return PTR_ERR(reg_xceiver); 27631f0e21a0SMarc Kleine-Budde 27641f0e21a0SMarc Kleine-Budde clk = devm_clk_get(&spi->dev, NULL); 27651f0e21a0SMarc Kleine-Budde if (IS_ERR(clk)) { 27661f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, "No Oscillator (clock) defined.\n"); 27671f0e21a0SMarc Kleine-Budde return PTR_ERR(clk); 27681f0e21a0SMarc Kleine-Budde } 27691f0e21a0SMarc Kleine-Budde freq = clk_get_rate(clk); 27701f0e21a0SMarc Kleine-Budde 27711f0e21a0SMarc Kleine-Budde /* Sanity check */ 27721f0e21a0SMarc Kleine-Budde if (freq < MCP25XXFD_SYSCLOCK_HZ_MIN || 27731f0e21a0SMarc Kleine-Budde freq > MCP25XXFD_SYSCLOCK_HZ_MAX) { 27741f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, 27751f0e21a0SMarc Kleine-Budde "Oscillator frequency (%u Hz) is too low or high.\n", 27761f0e21a0SMarc Kleine-Budde freq); 27771f0e21a0SMarc Kleine-Budde return -ERANGE; 27781f0e21a0SMarc Kleine-Budde } 27791f0e21a0SMarc Kleine-Budde 27801f0e21a0SMarc Kleine-Budde if (freq <= MCP25XXFD_SYSCLOCK_HZ_MAX / MCP25XXFD_OSC_PLL_MULTIPLIER) { 27811f0e21a0SMarc Kleine-Budde dev_err(&spi->dev, 27821f0e21a0SMarc Kleine-Budde "Oscillator frequency (%u Hz) is too low and PLL is not supported.\n", 27831f0e21a0SMarc Kleine-Budde freq); 27841f0e21a0SMarc Kleine-Budde return -ERANGE; 27851f0e21a0SMarc Kleine-Budde } 27861f0e21a0SMarc Kleine-Budde 27871f0e21a0SMarc Kleine-Budde ndev = alloc_candev(sizeof(struct mcp25xxfd_priv), 27881f0e21a0SMarc Kleine-Budde MCP25XXFD_TX_OBJ_NUM_MAX); 27891f0e21a0SMarc Kleine-Budde if (!ndev) 27901f0e21a0SMarc Kleine-Budde return -ENOMEM; 27911f0e21a0SMarc Kleine-Budde 27921f0e21a0SMarc Kleine-Budde SET_NETDEV_DEV(ndev, &spi->dev); 27931f0e21a0SMarc Kleine-Budde 27941f0e21a0SMarc Kleine-Budde ndev->netdev_ops = &mcp25xxfd_netdev_ops; 27951f0e21a0SMarc Kleine-Budde ndev->irq = spi->irq; 27961f0e21a0SMarc Kleine-Budde ndev->flags |= IFF_ECHO; 27971f0e21a0SMarc Kleine-Budde 27981f0e21a0SMarc Kleine-Budde priv = netdev_priv(ndev); 27991f0e21a0SMarc Kleine-Budde spi_set_drvdata(spi, priv); 28001f0e21a0SMarc Kleine-Budde priv->can.clock.freq = freq; 28011f0e21a0SMarc Kleine-Budde priv->can.do_set_mode = mcp25xxfd_set_mode; 28021f0e21a0SMarc Kleine-Budde priv->can.do_get_berr_counter = mcp25xxfd_get_berr_counter; 28031f0e21a0SMarc Kleine-Budde priv->can.bittiming_const = &mcp25xxfd_bittiming_const; 28041f0e21a0SMarc Kleine-Budde priv->can.data_bittiming_const = &mcp25xxfd_data_bittiming_const; 28051f0e21a0SMarc Kleine-Budde priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | 28061f0e21a0SMarc Kleine-Budde CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_FD | 28071f0e21a0SMarc Kleine-Budde CAN_CTRLMODE_FD_NON_ISO; 28081f0e21a0SMarc Kleine-Budde priv->ndev = ndev; 28091f0e21a0SMarc Kleine-Budde priv->spi = spi; 28101f0e21a0SMarc Kleine-Budde priv->rx_int = rx_int; 28111f0e21a0SMarc Kleine-Budde priv->clk = clk; 28121f0e21a0SMarc Kleine-Budde priv->reg_vdd = reg_vdd; 28131f0e21a0SMarc Kleine-Budde priv->reg_xceiver = reg_xceiver; 28141f0e21a0SMarc Kleine-Budde 28151f0e21a0SMarc Kleine-Budde match = device_get_match_data(&spi->dev); 28161f0e21a0SMarc Kleine-Budde if (match) 28171f0e21a0SMarc Kleine-Budde priv->devtype_data = *(struct mcp25xxfd_devtype_data *)match; 28181f0e21a0SMarc Kleine-Budde else 28191f0e21a0SMarc Kleine-Budde priv->devtype_data = *(struct mcp25xxfd_devtype_data *) 28201f0e21a0SMarc Kleine-Budde spi_get_device_id(spi)->driver_data; 28211f0e21a0SMarc Kleine-Budde 28221f0e21a0SMarc Kleine-Budde /* Errata Reference: 28231f0e21a0SMarc Kleine-Budde * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 4. 28241f0e21a0SMarc Kleine-Budde * 28251f0e21a0SMarc Kleine-Budde * The SPI can write corrupted data to the RAM at fast SPI 28261f0e21a0SMarc Kleine-Budde * speeds: 28271f0e21a0SMarc Kleine-Budde * 28281f0e21a0SMarc Kleine-Budde * Simultaneous activity on the CAN bus while writing data to 28291f0e21a0SMarc Kleine-Budde * RAM via the SPI interface, with high SCK frequency, can 28301f0e21a0SMarc Kleine-Budde * lead to corrupted data being written to RAM. 28311f0e21a0SMarc Kleine-Budde * 28321f0e21a0SMarc Kleine-Budde * Fix/Work Around: 28331f0e21a0SMarc Kleine-Budde * Ensure that FSCK is less than or equal to 0.85 * 28341f0e21a0SMarc Kleine-Budde * (FSYSCLK/2). 28351f0e21a0SMarc Kleine-Budde * 28361f0e21a0SMarc Kleine-Budde * Known good and bad combinations are: 28371f0e21a0SMarc Kleine-Budde * 28381f0e21a0SMarc Kleine-Budde * MCP ext-clk SoC SPI SPI-clk max-clk parent-clk Status config 28391f0e21a0SMarc Kleine-Budde * 28401f0e21a0SMarc Kleine-Budde * 2518 20 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 8333333 Hz 83.33% 600000000 Hz good assigned-clocks = <&ccu CLK_SPIx> 28411f0e21a0SMarc Kleine-Budde * 2518 20 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 9375000 Hz 93.75% 600000000 Hz bad assigned-clocks = <&ccu CLK_SPIx> 28421f0e21a0SMarc Kleine-Budde * 2518 40 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 16666667 Hz 83.33% 600000000 Hz good assigned-clocks = <&ccu CLK_SPIx> 28431f0e21a0SMarc Kleine-Budde * 2518 40 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 18750000 Hz 93.75% 600000000 Hz bad assigned-clocks = <&ccu CLK_SPIx> 28441f0e21a0SMarc Kleine-Budde * 2517 20 MHz fsl,imx8mm fsl,imx51-ecspi 8333333 Hz 83.33% 16666667 Hz good assigned-clocks = <&clk IMX8MM_CLK_ECSPIx_ROOT> 28451f0e21a0SMarc Kleine-Budde * 2517 20 MHz fsl,imx8mm fsl,imx51-ecspi 9523809 Hz 95.34% 28571429 Hz bad assigned-clocks = <&clk IMX8MM_CLK_ECSPIx_ROOT> 28461f0e21a0SMarc Kleine-Budde * 2517 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz good default 28471f0e21a0SMarc Kleine-Budde * 2518 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz good default 28481f0e21a0SMarc Kleine-Budde * 28491f0e21a0SMarc Kleine-Budde */ 28501f0e21a0SMarc Kleine-Budde priv->spi_max_speed_hz_orig = spi->max_speed_hz; 28511f0e21a0SMarc Kleine-Budde spi->max_speed_hz = min(spi->max_speed_hz, freq / 2 / 1000 * 850); 28521f0e21a0SMarc Kleine-Budde spi->bits_per_word = 8; 28531f0e21a0SMarc Kleine-Budde spi->rt = true; 28541f0e21a0SMarc Kleine-Budde err = spi_setup(spi); 28551f0e21a0SMarc Kleine-Budde if (err) 28561f0e21a0SMarc Kleine-Budde goto out_free_candev; 28571f0e21a0SMarc Kleine-Budde 28581f0e21a0SMarc Kleine-Budde err = mcp25xxfd_regmap_init(priv); 28591f0e21a0SMarc Kleine-Budde if (err) 28601f0e21a0SMarc Kleine-Budde goto out_free_candev; 28611f0e21a0SMarc Kleine-Budde 28621f0e21a0SMarc Kleine-Budde err = can_rx_offload_add_manual(ndev, &priv->offload, 28631f0e21a0SMarc Kleine-Budde MCP25XXFD_NAPI_WEIGHT); 28641f0e21a0SMarc Kleine-Budde if (err) 28651f0e21a0SMarc Kleine-Budde goto out_free_candev; 28661f0e21a0SMarc Kleine-Budde 28671f0e21a0SMarc Kleine-Budde err = mcp25xxfd_register(priv); 28681f0e21a0SMarc Kleine-Budde if (err) 28691f0e21a0SMarc Kleine-Budde goto out_free_candev; 28701f0e21a0SMarc Kleine-Budde 28711f0e21a0SMarc Kleine-Budde return 0; 28721f0e21a0SMarc Kleine-Budde 28731f0e21a0SMarc Kleine-Budde out_free_candev: 28741f0e21a0SMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 28751f0e21a0SMarc Kleine-Budde 28761f0e21a0SMarc Kleine-Budde free_candev(ndev); 28771f0e21a0SMarc Kleine-Budde 28781f0e21a0SMarc Kleine-Budde return err; 28791f0e21a0SMarc Kleine-Budde } 28801f0e21a0SMarc Kleine-Budde 28811f0e21a0SMarc Kleine-Budde static int mcp25xxfd_remove(struct spi_device *spi) 28821f0e21a0SMarc Kleine-Budde { 28831f0e21a0SMarc Kleine-Budde struct mcp25xxfd_priv *priv = spi_get_drvdata(spi); 28841f0e21a0SMarc Kleine-Budde struct net_device *ndev = priv->ndev; 28851f0e21a0SMarc Kleine-Budde 28861f0e21a0SMarc Kleine-Budde can_rx_offload_del(&priv->offload); 28871f0e21a0SMarc Kleine-Budde mcp25xxfd_unregister(priv); 28881f0e21a0SMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 28891f0e21a0SMarc Kleine-Budde free_candev(ndev); 28901f0e21a0SMarc Kleine-Budde 28911f0e21a0SMarc Kleine-Budde return 0; 28921f0e21a0SMarc Kleine-Budde } 28931f0e21a0SMarc Kleine-Budde 28941f0e21a0SMarc Kleine-Budde static int __maybe_unused mcp25xxfd_runtime_suspend(struct device *device) 28951f0e21a0SMarc Kleine-Budde { 28961f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_priv *priv = dev_get_drvdata(device); 28971f0e21a0SMarc Kleine-Budde 28981f0e21a0SMarc Kleine-Budde return mcp25xxfd_clks_and_vdd_disable(priv); 28991f0e21a0SMarc Kleine-Budde } 29001f0e21a0SMarc Kleine-Budde 29011f0e21a0SMarc Kleine-Budde static int __maybe_unused mcp25xxfd_runtime_resume(struct device *device) 29021f0e21a0SMarc Kleine-Budde { 29031f0e21a0SMarc Kleine-Budde const struct mcp25xxfd_priv *priv = dev_get_drvdata(device); 29041f0e21a0SMarc Kleine-Budde 29051f0e21a0SMarc Kleine-Budde return mcp25xxfd_clks_and_vdd_enable(priv); 29061f0e21a0SMarc Kleine-Budde } 29071f0e21a0SMarc Kleine-Budde 29081f0e21a0SMarc Kleine-Budde static const struct dev_pm_ops mcp25xxfd_pm_ops = { 29091f0e21a0SMarc Kleine-Budde SET_RUNTIME_PM_OPS(mcp25xxfd_runtime_suspend, 29101f0e21a0SMarc Kleine-Budde mcp25xxfd_runtime_resume, NULL) 29111f0e21a0SMarc Kleine-Budde }; 29121f0e21a0SMarc Kleine-Budde 29131f0e21a0SMarc Kleine-Budde static struct spi_driver mcp25xxfd_driver = { 29141f0e21a0SMarc Kleine-Budde .driver = { 29151f0e21a0SMarc Kleine-Budde .name = DEVICE_NAME, 29161f0e21a0SMarc Kleine-Budde .pm = &mcp25xxfd_pm_ops, 29171f0e21a0SMarc Kleine-Budde .of_match_table = mcp25xxfd_of_match, 29181f0e21a0SMarc Kleine-Budde }, 29191f0e21a0SMarc Kleine-Budde .probe = mcp25xxfd_probe, 29201f0e21a0SMarc Kleine-Budde .remove = mcp25xxfd_remove, 29211f0e21a0SMarc Kleine-Budde .id_table = mcp25xxfd_id_table, 29221f0e21a0SMarc Kleine-Budde }; 29231f0e21a0SMarc Kleine-Budde module_spi_driver(mcp25xxfd_driver); 29241f0e21a0SMarc Kleine-Budde 29251f0e21a0SMarc Kleine-Budde MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>"); 29261f0e21a0SMarc Kleine-Budde MODULE_DESCRIPTION("Microchip MCP25xxFD Family CAN controller driver"); 29271f0e21a0SMarc Kleine-Budde MODULE_LICENSE("GPL v2"); 2928