155e5b97fSMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0 255e5b97fSMarc Kleine-Budde // 3eb79a267SMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver 455e5b97fSMarc Kleine-Budde // 5eb94b74cSMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021 Pengutronix, 655e5b97fSMarc Kleine-Budde // Marc Kleine-Budde <kernel@pengutronix.de> 755e5b97fSMarc Kleine-Budde // 855e5b97fSMarc Kleine-Budde // Based on: 955e5b97fSMarc Kleine-Budde // 1055e5b97fSMarc Kleine-Budde // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface 1155e5b97fSMarc Kleine-Budde // 1255e5b97fSMarc Kleine-Budde // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org> 1355e5b97fSMarc Kleine-Budde // 1455e5b97fSMarc Kleine-Budde 1555e5b97fSMarc Kleine-Budde #include <linux/bitfield.h> 1655e5b97fSMarc Kleine-Budde #include <linux/clk.h> 1755e5b97fSMarc Kleine-Budde #include <linux/device.h> 1871520f85SAndy Shevchenko #include <linux/mod_devicetable.h> 1955e5b97fSMarc Kleine-Budde #include <linux/module.h> 2055e5b97fSMarc Kleine-Budde #include <linux/pm_runtime.h> 2171520f85SAndy Shevchenko #include <linux/property.h> 2255e5b97fSMarc Kleine-Budde 231f0e21a0SMarc Kleine-Budde #include "mcp251xfd.h" 2455e5b97fSMarc Kleine-Budde 25f4f77366SMarc Kleine-Budde #define DEVICE_NAME "mcp251xfd" 2655e5b97fSMarc Kleine-Budde 27eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp2517fd = { 28eb79a267SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_MAB_NO_WARN | MCP251XFD_QUIRK_CRC_REG | 29eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_RX | MCP251XFD_QUIRK_CRC_TX | 30eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ECC, 31eb79a267SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP2517FD, 3255e5b97fSMarc Kleine-Budde }; 3355e5b97fSMarc Kleine-Budde 34eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp2518fd = { 35eb79a267SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_CRC_REG | MCP251XFD_QUIRK_CRC_RX | 36eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_TX | MCP251XFD_QUIRK_ECC, 37eb79a267SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP2518FD, 3855e5b97fSMarc Kleine-Budde }; 3955e5b97fSMarc Kleine-Budde 40c6f2a617SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp251863 = { 41c6f2a617SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_CRC_REG | MCP251XFD_QUIRK_CRC_RX | 42c6f2a617SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_TX | MCP251XFD_QUIRK_ECC, 43c6f2a617SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP251863, 44c6f2a617SMarc Kleine-Budde }; 45c6f2a617SMarc Kleine-Budde 4655e5b97fSMarc Kleine-Budde /* Autodetect model, start with CRC enabled. */ 47eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp251xfd = { 48eb79a267SMarc Kleine-Budde .quirks = MCP251XFD_QUIRK_CRC_REG | MCP251XFD_QUIRK_CRC_RX | 49eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_CRC_TX | MCP251XFD_QUIRK_ECC, 50eb79a267SMarc Kleine-Budde .model = MCP251XFD_MODEL_MCP251XFD, 5155e5b97fSMarc Kleine-Budde }; 5255e5b97fSMarc Kleine-Budde 53eb79a267SMarc Kleine-Budde static const struct can_bittiming_const mcp251xfd_bittiming_const = { 5455e5b97fSMarc Kleine-Budde .name = DEVICE_NAME, 5555e5b97fSMarc Kleine-Budde .tseg1_min = 2, 5655e5b97fSMarc Kleine-Budde .tseg1_max = 256, 5755e5b97fSMarc Kleine-Budde .tseg2_min = 1, 5855e5b97fSMarc Kleine-Budde .tseg2_max = 128, 5955e5b97fSMarc Kleine-Budde .sjw_max = 128, 6055e5b97fSMarc Kleine-Budde .brp_min = 1, 6155e5b97fSMarc Kleine-Budde .brp_max = 256, 6255e5b97fSMarc Kleine-Budde .brp_inc = 1, 6355e5b97fSMarc Kleine-Budde }; 6455e5b97fSMarc Kleine-Budde 65eb79a267SMarc Kleine-Budde static const struct can_bittiming_const mcp251xfd_data_bittiming_const = { 6655e5b97fSMarc Kleine-Budde .name = DEVICE_NAME, 6755e5b97fSMarc Kleine-Budde .tseg1_min = 1, 6855e5b97fSMarc Kleine-Budde .tseg1_max = 32, 6955e5b97fSMarc Kleine-Budde .tseg2_min = 1, 7055e5b97fSMarc Kleine-Budde .tseg2_max = 16, 7155e5b97fSMarc Kleine-Budde .sjw_max = 16, 7255e5b97fSMarc Kleine-Budde .brp_min = 1, 7355e5b97fSMarc Kleine-Budde .brp_max = 256, 7455e5b97fSMarc Kleine-Budde .brp_inc = 1, 7555e5b97fSMarc Kleine-Budde }; 7655e5b97fSMarc Kleine-Budde 77eb79a267SMarc Kleine-Budde static const char *__mcp251xfd_get_model_str(enum mcp251xfd_model model) 7855e5b97fSMarc Kleine-Budde { 7955e5b97fSMarc Kleine-Budde switch (model) { 80eb79a267SMarc Kleine-Budde case MCP251XFD_MODEL_MCP2517FD: 8178db1aa8STom Rix return "MCP2517FD"; 82eb79a267SMarc Kleine-Budde case MCP251XFD_MODEL_MCP2518FD: 8378db1aa8STom Rix return "MCP2518FD"; 84c6f2a617SMarc Kleine-Budde case MCP251XFD_MODEL_MCP251863: 85c6f2a617SMarc Kleine-Budde return "MCP251863"; 86eb79a267SMarc Kleine-Budde case MCP251XFD_MODEL_MCP251XFD: 8778db1aa8STom Rix return "MCP251xFD"; 8855e5b97fSMarc Kleine-Budde } 8955e5b97fSMarc Kleine-Budde 9055e5b97fSMarc Kleine-Budde return "<unknown>"; 9155e5b97fSMarc Kleine-Budde } 9255e5b97fSMarc Kleine-Budde 9355e5b97fSMarc Kleine-Budde static inline const char * 94eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(const struct mcp251xfd_priv *priv) 9555e5b97fSMarc Kleine-Budde { 96eb79a267SMarc Kleine-Budde return __mcp251xfd_get_model_str(priv->devtype_data.model); 9755e5b97fSMarc Kleine-Budde } 9855e5b97fSMarc Kleine-Budde 99eb79a267SMarc Kleine-Budde static const char *mcp251xfd_get_mode_str(const u8 mode) 10055e5b97fSMarc Kleine-Budde { 10155e5b97fSMarc Kleine-Budde switch (mode) { 102eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_MIXED: 10378db1aa8STom Rix return "Mixed (CAN FD/CAN 2.0)"; 104eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_SLEEP: 10578db1aa8STom Rix return "Sleep"; 106eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_INT_LOOPBACK: 10778db1aa8STom Rix return "Internal Loopback"; 108eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_LISTENONLY: 10978db1aa8STom Rix return "Listen Only"; 110eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_CONFIG: 11178db1aa8STom Rix return "Configuration"; 112eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_EXT_LOOPBACK: 11378db1aa8STom Rix return "External Loopback"; 114eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_CAN2_0: 11578db1aa8STom Rix return "CAN 2.0"; 116eb79a267SMarc Kleine-Budde case MCP251XFD_REG_CON_MODE_RESTRICTED: 11778db1aa8STom Rix return "Restricted Operation"; 11855e5b97fSMarc Kleine-Budde } 11955e5b97fSMarc Kleine-Budde 12055e5b97fSMarc Kleine-Budde return "<unknown>"; 12155e5b97fSMarc Kleine-Budde } 12255e5b97fSMarc Kleine-Budde 12306db5dbcSMarc Kleine-Budde static const char * 12406db5dbcSMarc Kleine-Budde mcp251xfd_get_osc_str(const u32 osc, const u32 osc_reference) 12506db5dbcSMarc Kleine-Budde { 12606db5dbcSMarc Kleine-Budde switch (~osc & osc_reference & 12706db5dbcSMarc Kleine-Budde (MCP251XFD_REG_OSC_OSCRDY | MCP251XFD_REG_OSC_PLLRDY)) { 12806db5dbcSMarc Kleine-Budde case MCP251XFD_REG_OSC_PLLRDY: 12906db5dbcSMarc Kleine-Budde return "PLL"; 13006db5dbcSMarc Kleine-Budde case MCP251XFD_REG_OSC_OSCRDY: 13106db5dbcSMarc Kleine-Budde return "Oscillator"; 13206db5dbcSMarc Kleine-Budde case MCP251XFD_REG_OSC_PLLRDY | MCP251XFD_REG_OSC_OSCRDY: 13306db5dbcSMarc Kleine-Budde return "Oscillator/PLL"; 13406db5dbcSMarc Kleine-Budde } 13506db5dbcSMarc Kleine-Budde 13606db5dbcSMarc Kleine-Budde return "<unknown>"; 13706db5dbcSMarc Kleine-Budde } 13806db5dbcSMarc Kleine-Budde 139eb79a267SMarc Kleine-Budde static inline int mcp251xfd_vdd_enable(const struct mcp251xfd_priv *priv) 14055e5b97fSMarc Kleine-Budde { 14155e5b97fSMarc Kleine-Budde if (!priv->reg_vdd) 14255e5b97fSMarc Kleine-Budde return 0; 14355e5b97fSMarc Kleine-Budde 14455e5b97fSMarc Kleine-Budde return regulator_enable(priv->reg_vdd); 14555e5b97fSMarc Kleine-Budde } 14655e5b97fSMarc Kleine-Budde 147eb79a267SMarc Kleine-Budde static inline int mcp251xfd_vdd_disable(const struct mcp251xfd_priv *priv) 14855e5b97fSMarc Kleine-Budde { 14955e5b97fSMarc Kleine-Budde if (!priv->reg_vdd) 15055e5b97fSMarc Kleine-Budde return 0; 15155e5b97fSMarc Kleine-Budde 15255e5b97fSMarc Kleine-Budde return regulator_disable(priv->reg_vdd); 15355e5b97fSMarc Kleine-Budde } 15455e5b97fSMarc Kleine-Budde 15555e5b97fSMarc Kleine-Budde static inline int 156eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_enable(const struct mcp251xfd_priv *priv) 15755e5b97fSMarc Kleine-Budde { 15855e5b97fSMarc Kleine-Budde if (!priv->reg_xceiver) 15955e5b97fSMarc Kleine-Budde return 0; 16055e5b97fSMarc Kleine-Budde 16155e5b97fSMarc Kleine-Budde return regulator_enable(priv->reg_xceiver); 16255e5b97fSMarc Kleine-Budde } 16355e5b97fSMarc Kleine-Budde 16455e5b97fSMarc Kleine-Budde static inline int 165eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(const struct mcp251xfd_priv *priv) 16655e5b97fSMarc Kleine-Budde { 16755e5b97fSMarc Kleine-Budde if (!priv->reg_xceiver) 16855e5b97fSMarc Kleine-Budde return 0; 16955e5b97fSMarc Kleine-Budde 17055e5b97fSMarc Kleine-Budde return regulator_disable(priv->reg_xceiver); 17155e5b97fSMarc Kleine-Budde } 17255e5b97fSMarc Kleine-Budde 173eb79a267SMarc Kleine-Budde static int mcp251xfd_clks_and_vdd_enable(const struct mcp251xfd_priv *priv) 17455e5b97fSMarc Kleine-Budde { 17555e5b97fSMarc Kleine-Budde int err; 17655e5b97fSMarc Kleine-Budde 17755e5b97fSMarc Kleine-Budde err = clk_prepare_enable(priv->clk); 17855e5b97fSMarc Kleine-Budde if (err) 17955e5b97fSMarc Kleine-Budde return err; 18055e5b97fSMarc Kleine-Budde 181eb79a267SMarc Kleine-Budde err = mcp251xfd_vdd_enable(priv); 18255e5b97fSMarc Kleine-Budde if (err) 18355e5b97fSMarc Kleine-Budde clk_disable_unprepare(priv->clk); 18455e5b97fSMarc Kleine-Budde 18555e5b97fSMarc Kleine-Budde /* Wait for oscillator stabilisation time after power up */ 186eb79a267SMarc Kleine-Budde usleep_range(MCP251XFD_OSC_STAB_SLEEP_US, 187eb79a267SMarc Kleine-Budde 2 * MCP251XFD_OSC_STAB_SLEEP_US); 18855e5b97fSMarc Kleine-Budde 18955e5b97fSMarc Kleine-Budde return err; 19055e5b97fSMarc Kleine-Budde } 19155e5b97fSMarc Kleine-Budde 192eb79a267SMarc Kleine-Budde static int mcp251xfd_clks_and_vdd_disable(const struct mcp251xfd_priv *priv) 19355e5b97fSMarc Kleine-Budde { 19455e5b97fSMarc Kleine-Budde int err; 19555e5b97fSMarc Kleine-Budde 196eb79a267SMarc Kleine-Budde err = mcp251xfd_vdd_disable(priv); 19755e5b97fSMarc Kleine-Budde if (err) 19855e5b97fSMarc Kleine-Budde return err; 19955e5b97fSMarc Kleine-Budde 20055e5b97fSMarc Kleine-Budde clk_disable_unprepare(priv->clk); 20155e5b97fSMarc Kleine-Budde 20255e5b97fSMarc Kleine-Budde return 0; 20355e5b97fSMarc Kleine-Budde } 20455e5b97fSMarc Kleine-Budde 2053f5c91b4SMarc Kleine-Budde static inline bool mcp251xfd_reg_invalid(u32 reg) 2063f5c91b4SMarc Kleine-Budde { 2073f5c91b4SMarc Kleine-Budde return reg == 0x0 || reg == 0xffffffff; 2083f5c91b4SMarc Kleine-Budde } 2093f5c91b4SMarc Kleine-Budde 21055e5b97fSMarc Kleine-Budde static inline int 211eb79a267SMarc Kleine-Budde mcp251xfd_chip_get_mode(const struct mcp251xfd_priv *priv, u8 *mode) 21255e5b97fSMarc Kleine-Budde { 21355e5b97fSMarc Kleine-Budde u32 val; 21455e5b97fSMarc Kleine-Budde int err; 21555e5b97fSMarc Kleine-Budde 216eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_CON, &val); 21755e5b97fSMarc Kleine-Budde if (err) 21855e5b97fSMarc Kleine-Budde return err; 21955e5b97fSMarc Kleine-Budde 220eb79a267SMarc Kleine-Budde *mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, val); 22155e5b97fSMarc Kleine-Budde 22255e5b97fSMarc Kleine-Budde return 0; 22355e5b97fSMarc Kleine-Budde } 22455e5b97fSMarc Kleine-Budde 22555e5b97fSMarc Kleine-Budde static int 226eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv, 22755e5b97fSMarc Kleine-Budde const u8 mode_req, bool nowait) 22855e5b97fSMarc Kleine-Budde { 229a10fd91eSMarc Kleine-Budde u32 con = 0, con_reqop, osc = 0; 230a10fd91eSMarc Kleine-Budde u8 mode; 23155e5b97fSMarc Kleine-Budde int err; 23255e5b97fSMarc Kleine-Budde 233eb79a267SMarc Kleine-Budde con_reqop = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, mode_req); 234eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CON, 235eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_REQOP_MASK, con_reqop); 236a10fd91eSMarc Kleine-Budde if (err == -EBADMSG) { 237a10fd91eSMarc Kleine-Budde netdev_err(priv->ndev, 238a10fd91eSMarc Kleine-Budde "Failed to set Requested Operation Mode.\n"); 239a10fd91eSMarc Kleine-Budde 240a10fd91eSMarc Kleine-Budde return -ENODEV; 241a10fd91eSMarc Kleine-Budde } else if (err) { 24255e5b97fSMarc Kleine-Budde return err; 243a10fd91eSMarc Kleine-Budde } 24455e5b97fSMarc Kleine-Budde 245eb79a267SMarc Kleine-Budde if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait) 24655e5b97fSMarc Kleine-Budde return 0; 24755e5b97fSMarc Kleine-Budde 248eb79a267SMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con, 249a10fd91eSMarc Kleine-Budde !mcp251xfd_reg_invalid(con) && 250eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, 25155e5b97fSMarc Kleine-Budde con) == mode_req, 252eb79a267SMarc Kleine-Budde MCP251XFD_POLL_SLEEP_US, 253eb79a267SMarc Kleine-Budde MCP251XFD_POLL_TIMEOUT_US); 254a10fd91eSMarc Kleine-Budde if (err != -ETIMEDOUT && err != -EBADMSG) 25555e5b97fSMarc Kleine-Budde return err; 256a10fd91eSMarc Kleine-Budde 257a10fd91eSMarc Kleine-Budde /* Ignore return value. 258a10fd91eSMarc Kleine-Budde * Print below error messages, even if this fails. 259a10fd91eSMarc Kleine-Budde */ 260a10fd91eSMarc Kleine-Budde regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc); 261a10fd91eSMarc Kleine-Budde 262a10fd91eSMarc Kleine-Budde if (mcp251xfd_reg_invalid(con)) { 263a10fd91eSMarc Kleine-Budde netdev_err(priv->ndev, 264a10fd91eSMarc Kleine-Budde "Failed to read CAN Control Register (con=0x%08x, osc=0x%08x).\n", 265a10fd91eSMarc Kleine-Budde con, osc); 266a10fd91eSMarc Kleine-Budde 267a10fd91eSMarc Kleine-Budde return -ENODEV; 26855e5b97fSMarc Kleine-Budde } 26955e5b97fSMarc Kleine-Budde 270a10fd91eSMarc Kleine-Budde mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, con); 271a10fd91eSMarc Kleine-Budde netdev_err(priv->ndev, 272a10fd91eSMarc Kleine-Budde "Controller failed to enter mode %s Mode (%u) and stays in %s Mode (%u) (con=0x%08x, osc=0x%08x).\n", 273a10fd91eSMarc Kleine-Budde mcp251xfd_get_mode_str(mode_req), mode_req, 274a10fd91eSMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode, 275a10fd91eSMarc Kleine-Budde con, osc); 276a10fd91eSMarc Kleine-Budde 277a10fd91eSMarc Kleine-Budde return -ETIMEDOUT; 27855e5b97fSMarc Kleine-Budde } 27955e5b97fSMarc Kleine-Budde 28055e5b97fSMarc Kleine-Budde static inline int 281eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv, 28255e5b97fSMarc Kleine-Budde const u8 mode_req) 28355e5b97fSMarc Kleine-Budde { 284eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode_req, false); 28555e5b97fSMarc Kleine-Budde } 28655e5b97fSMarc Kleine-Budde 287b558e200SMarc Kleine-Budde static inline int __maybe_unused 288eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode_nowait(const struct mcp251xfd_priv *priv, 28955e5b97fSMarc Kleine-Budde const u8 mode_req) 29055e5b97fSMarc Kleine-Budde { 291eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode_req, true); 29255e5b97fSMarc Kleine-Budde } 29355e5b97fSMarc Kleine-Budde 2940445e5ffSMarc Kleine-Budde static int 2950445e5ffSMarc Kleine-Budde mcp251xfd_chip_wait_for_osc_ready(const struct mcp251xfd_priv *priv, 2960445e5ffSMarc Kleine-Budde u32 osc_reference, u32 osc_mask) 2970445e5ffSMarc Kleine-Budde { 2980445e5ffSMarc Kleine-Budde u32 osc; 2990445e5ffSMarc Kleine-Budde int err; 3000445e5ffSMarc Kleine-Budde 3010445e5ffSMarc Kleine-Budde err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_OSC, osc, 302197656deSMarc Kleine-Budde !mcp251xfd_reg_invalid(osc) && 3030445e5ffSMarc Kleine-Budde (osc & osc_mask) == osc_reference, 3040445e5ffSMarc Kleine-Budde MCP251XFD_OSC_STAB_SLEEP_US, 3050445e5ffSMarc Kleine-Budde MCP251XFD_OSC_STAB_TIMEOUT_US); 306197656deSMarc Kleine-Budde if (err != -ETIMEDOUT) 307197656deSMarc Kleine-Budde return err; 308197656deSMarc Kleine-Budde 3090445e5ffSMarc Kleine-Budde if (mcp251xfd_reg_invalid(osc)) { 3100445e5ffSMarc Kleine-Budde netdev_err(priv->ndev, 311197656deSMarc Kleine-Budde "Failed to read Oscillator Configuration Register (osc=0x%08x).\n", 312197656deSMarc Kleine-Budde osc); 3130445e5ffSMarc Kleine-Budde return -ENODEV; 314197656deSMarc Kleine-Budde } 315197656deSMarc Kleine-Budde 3160445e5ffSMarc Kleine-Budde netdev_err(priv->ndev, 31706db5dbcSMarc Kleine-Budde "Timeout waiting for %s ready (osc=0x%08x, osc_reference=0x%08x, osc_mask=0x%08x).\n", 31806db5dbcSMarc Kleine-Budde mcp251xfd_get_osc_str(osc, osc_reference), 31906db5dbcSMarc Kleine-Budde osc, osc_reference, osc_mask); 3200445e5ffSMarc Kleine-Budde 321197656deSMarc Kleine-Budde return -ETIMEDOUT; 3220445e5ffSMarc Kleine-Budde } 3230445e5ffSMarc Kleine-Budde 3241a4abba6SMarc Kleine-Budde static int mcp251xfd_chip_wake(const struct mcp251xfd_priv *priv) 32555e5b97fSMarc Kleine-Budde { 32655e5b97fSMarc Kleine-Budde u32 osc, osc_reference, osc_mask; 32755e5b97fSMarc Kleine-Budde int err; 32855e5b97fSMarc Kleine-Budde 3291a4abba6SMarc Kleine-Budde /* For normal sleep on MCP2517FD and MCP2518FD, clearing 3301a4abba6SMarc Kleine-Budde * "Oscillator Disable" will wake the chip. For low power mode 3311a4abba6SMarc Kleine-Budde * on MCP2518FD, asserting the chip select will wake the 3321a4abba6SMarc Kleine-Budde * chip. Writing to the Oscillator register will wake it in 3331a4abba6SMarc Kleine-Budde * both cases. 33455e5b97fSMarc Kleine-Budde */ 335eb79a267SMarc Kleine-Budde osc = FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 336eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 3372a68dd86SMarc Kleine-Budde 3382a68dd86SMarc Kleine-Budde /* We cannot check for the PLL ready bit (either set or 3392a68dd86SMarc Kleine-Budde * unset), as the PLL might be enabled. This can happen if the 3402a68dd86SMarc Kleine-Budde * system reboots, while the mcp251xfd stays powered. 3412a68dd86SMarc Kleine-Budde */ 342eb79a267SMarc Kleine-Budde osc_reference = MCP251XFD_REG_OSC_OSCRDY; 3432a68dd86SMarc Kleine-Budde osc_mask = MCP251XFD_REG_OSC_OSCRDY; 34455e5b97fSMarc Kleine-Budde 3451a4abba6SMarc Kleine-Budde /* If the controller is in Sleep Mode the following write only 34655e5b97fSMarc Kleine-Budde * removes the "Oscillator Disable" bit and powers it up. All 34755e5b97fSMarc Kleine-Budde * other bits are unaffected. 34855e5b97fSMarc Kleine-Budde */ 349eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc); 35055e5b97fSMarc Kleine-Budde if (err) 35155e5b97fSMarc Kleine-Budde return err; 35255e5b97fSMarc Kleine-Budde 35306db5dbcSMarc Kleine-Budde /* Sometimes the PLL is stuck enabled, the controller never 35406db5dbcSMarc Kleine-Budde * sets the OSC Ready bit, and we get an -ETIMEDOUT. Our 35506db5dbcSMarc Kleine-Budde * caller takes care of retry. 35606db5dbcSMarc Kleine-Budde */ 3570445e5ffSMarc Kleine-Budde return mcp251xfd_chip_wait_for_osc_ready(priv, osc_reference, osc_mask); 35855e5b97fSMarc Kleine-Budde } 35955e5b97fSMarc Kleine-Budde 3601ba3690fSMarc Kleine-Budde static inline int mcp251xfd_chip_sleep(const struct mcp251xfd_priv *priv) 3611ba3690fSMarc Kleine-Budde { 3622a68dd86SMarc Kleine-Budde if (priv->pll_enable) { 3632a68dd86SMarc Kleine-Budde u32 osc; 3642a68dd86SMarc Kleine-Budde int err; 3652a68dd86SMarc Kleine-Budde 3662a68dd86SMarc Kleine-Budde /* Turn off PLL */ 3672a68dd86SMarc Kleine-Budde osc = FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 3682a68dd86SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 3692a68dd86SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc); 3702a68dd86SMarc Kleine-Budde if (err) 3712a68dd86SMarc Kleine-Budde netdev_err(priv->ndev, 3722a68dd86SMarc Kleine-Budde "Failed to disable PLL.\n"); 3732a68dd86SMarc Kleine-Budde 3742a68dd86SMarc Kleine-Budde priv->spi->max_speed_hz = priv->spi_max_speed_hz_slow; 3752a68dd86SMarc Kleine-Budde } 3762a68dd86SMarc Kleine-Budde 3771ba3690fSMarc Kleine-Budde return mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP); 3781ba3690fSMarc Kleine-Budde } 3791ba3690fSMarc Kleine-Budde 380eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_do(const struct mcp251xfd_priv *priv) 38155e5b97fSMarc Kleine-Budde { 382eb79a267SMarc Kleine-Budde const __be16 cmd = mcp251xfd_cmd_reset(); 38355e5b97fSMarc Kleine-Budde int err; 38455e5b97fSMarc Kleine-Budde 3851a4abba6SMarc Kleine-Budde /* The Set Mode and SPI Reset command only works if the 3861a4abba6SMarc Kleine-Budde * controller is not in Sleep Mode. 38755e5b97fSMarc Kleine-Budde */ 3881a4abba6SMarc Kleine-Budde err = mcp251xfd_chip_wake(priv); 38955e5b97fSMarc Kleine-Budde if (err) 39055e5b97fSMarc Kleine-Budde return err; 39155e5b97fSMarc Kleine-Budde 392eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_CONFIG); 39355e5b97fSMarc Kleine-Budde if (err) 39455e5b97fSMarc Kleine-Budde return err; 39555e5b97fSMarc Kleine-Budde 39655e5b97fSMarc Kleine-Budde /* spi_write_then_read() works with non DMA-safe buffers */ 39755e5b97fSMarc Kleine-Budde return spi_write_then_read(priv->spi, &cmd, sizeof(cmd), NULL, 0); 39855e5b97fSMarc Kleine-Budde } 39955e5b97fSMarc Kleine-Budde 400eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_check(const struct mcp251xfd_priv *priv) 40155e5b97fSMarc Kleine-Budde { 40201a80d68SMarc Kleine-Budde u32 osc_reference, osc_mask; 40355e5b97fSMarc Kleine-Budde u8 mode; 40455e5b97fSMarc Kleine-Budde int err; 40555e5b97fSMarc Kleine-Budde 40601a80d68SMarc Kleine-Budde /* Check for reset defaults of OSC reg. 40701a80d68SMarc Kleine-Budde * This will take care of stabilization period. 40801a80d68SMarc Kleine-Budde */ 40901a80d68SMarc Kleine-Budde osc_reference = MCP251XFD_REG_OSC_OSCRDY | 41001a80d68SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 41101a80d68SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 41201a80d68SMarc Kleine-Budde osc_mask = osc_reference | MCP251XFD_REG_OSC_PLLRDY; 41301a80d68SMarc Kleine-Budde err = mcp251xfd_chip_wait_for_osc_ready(priv, osc_reference, osc_mask); 41401a80d68SMarc Kleine-Budde if (err) 41501a80d68SMarc Kleine-Budde return err; 41601a80d68SMarc Kleine-Budde 417eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_get_mode(priv, &mode); 41855e5b97fSMarc Kleine-Budde if (err) 41955e5b97fSMarc Kleine-Budde return err; 42055e5b97fSMarc Kleine-Budde 421eb79a267SMarc Kleine-Budde if (mode != MCP251XFD_REG_CON_MODE_CONFIG) { 42255e5b97fSMarc Kleine-Budde netdev_info(priv->ndev, 42355e5b97fSMarc Kleine-Budde "Controller not in Config Mode after reset, but in %s Mode (%u).\n", 424eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 42555e5b97fSMarc Kleine-Budde return -ETIMEDOUT; 42655e5b97fSMarc Kleine-Budde } 42755e5b97fSMarc Kleine-Budde 42855e5b97fSMarc Kleine-Budde return 0; 42955e5b97fSMarc Kleine-Budde } 43055e5b97fSMarc Kleine-Budde 431eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset(const struct mcp251xfd_priv *priv) 43255e5b97fSMarc Kleine-Budde { 43355e5b97fSMarc Kleine-Budde int err, i; 43455e5b97fSMarc Kleine-Budde 435eb79a267SMarc Kleine-Budde for (i = 0; i < MCP251XFD_SOFTRESET_RETRIES_MAX; i++) { 43655e5b97fSMarc Kleine-Budde if (i) 43755e5b97fSMarc Kleine-Budde netdev_info(priv->ndev, 438f93486a7SMarc Kleine-Budde "Retrying to reset controller.\n"); 43955e5b97fSMarc Kleine-Budde 440eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset_do(priv); 44155e5b97fSMarc Kleine-Budde if (err == -ETIMEDOUT) 44255e5b97fSMarc Kleine-Budde continue; 44355e5b97fSMarc Kleine-Budde if (err) 44455e5b97fSMarc Kleine-Budde return err; 44555e5b97fSMarc Kleine-Budde 446eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset_check(priv); 44755e5b97fSMarc Kleine-Budde if (err == -ETIMEDOUT) 44855e5b97fSMarc Kleine-Budde continue; 44955e5b97fSMarc Kleine-Budde if (err) 45055e5b97fSMarc Kleine-Budde return err; 45155e5b97fSMarc Kleine-Budde 45255e5b97fSMarc Kleine-Budde return 0; 45355e5b97fSMarc Kleine-Budde } 45455e5b97fSMarc Kleine-Budde 45555e5b97fSMarc Kleine-Budde return err; 45655e5b97fSMarc Kleine-Budde } 45755e5b97fSMarc Kleine-Budde 458eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_clock_init(const struct mcp251xfd_priv *priv) 45955e5b97fSMarc Kleine-Budde { 460e39ea136SMarc Kleine-Budde u32 osc, osc_reference, osc_mask; 46155e5b97fSMarc Kleine-Budde int err; 46255e5b97fSMarc Kleine-Budde 46355e5b97fSMarc Kleine-Budde /* Activate Low Power Mode on Oscillator Disable. This only 46455e5b97fSMarc Kleine-Budde * works on the MCP2518FD. The MCP2517FD will go into normal 46555e5b97fSMarc Kleine-Budde * Sleep Mode instead. 46655e5b97fSMarc Kleine-Budde */ 467eb79a267SMarc Kleine-Budde osc = MCP251XFD_REG_OSC_LPMEN | 468eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK, 469eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_CLKODIV_10); 470e39ea136SMarc Kleine-Budde osc_reference = MCP251XFD_REG_OSC_OSCRDY; 471e39ea136SMarc Kleine-Budde osc_mask = MCP251XFD_REG_OSC_OSCRDY | MCP251XFD_REG_OSC_PLLRDY; 472e39ea136SMarc Kleine-Budde 4732a68dd86SMarc Kleine-Budde if (priv->pll_enable) { 4742a68dd86SMarc Kleine-Budde osc |= MCP251XFD_REG_OSC_PLLEN; 4752a68dd86SMarc Kleine-Budde osc_reference |= MCP251XFD_REG_OSC_PLLRDY; 4762a68dd86SMarc Kleine-Budde } 4772a68dd86SMarc Kleine-Budde 478eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc); 47955e5b97fSMarc Kleine-Budde if (err) 48055e5b97fSMarc Kleine-Budde return err; 48155e5b97fSMarc Kleine-Budde 482e39ea136SMarc Kleine-Budde err = mcp251xfd_chip_wait_for_osc_ready(priv, osc_reference, osc_mask); 483e39ea136SMarc Kleine-Budde if (err) 484e39ea136SMarc Kleine-Budde return err; 485e39ea136SMarc Kleine-Budde 4862a68dd86SMarc Kleine-Budde priv->spi->max_speed_hz = priv->spi_max_speed_hz_fast; 4872a68dd86SMarc Kleine-Budde 48814193ea2SMarc Kleine-Budde return 0; 48914193ea2SMarc Kleine-Budde } 49014193ea2SMarc Kleine-Budde 49114193ea2SMarc Kleine-Budde static int mcp251xfd_chip_timestamp_init(const struct mcp251xfd_priv *priv) 49214193ea2SMarc Kleine-Budde { 49355e5b97fSMarc Kleine-Budde /* Set Time Base Counter Prescaler to 1. 49455e5b97fSMarc Kleine-Budde * 49555e5b97fSMarc Kleine-Budde * This means an overflow of the 32 bit Time Base Counter 49655e5b97fSMarc Kleine-Budde * register at 40 MHz every 107 seconds. 49755e5b97fSMarc Kleine-Budde */ 498eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_TSCON, 499eb79a267SMarc Kleine-Budde MCP251XFD_REG_TSCON_TBCEN); 50055e5b97fSMarc Kleine-Budde } 50155e5b97fSMarc Kleine-Budde 502eb79a267SMarc Kleine-Budde static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv) 50355e5b97fSMarc Kleine-Budde { 50455e5b97fSMarc Kleine-Budde const struct can_bittiming *bt = &priv->can.bittiming; 50555e5b97fSMarc Kleine-Budde const struct can_bittiming *dbt = &priv->can.data_bittiming; 50655e5b97fSMarc Kleine-Budde u32 val = 0; 50755e5b97fSMarc Kleine-Budde s8 tdco; 50855e5b97fSMarc Kleine-Budde int err; 50955e5b97fSMarc Kleine-Budde 51055e5b97fSMarc Kleine-Budde /* CAN Control Register 51155e5b97fSMarc Kleine-Budde * 51255e5b97fSMarc Kleine-Budde * - no transmit bandwidth sharing 51355e5b97fSMarc Kleine-Budde * - config mode 51455e5b97fSMarc Kleine-Budde * - disable transmit queue 51555e5b97fSMarc Kleine-Budde * - store in transmit FIFO event 51655e5b97fSMarc Kleine-Budde * - transition to restricted operation mode on system error 51755e5b97fSMarc Kleine-Budde * - ESI is transmitted recessive when ESI of message is high or 51855e5b97fSMarc Kleine-Budde * CAN controller error passive 51955e5b97fSMarc Kleine-Budde * - restricted retransmission attempts, 52055e5b97fSMarc Kleine-Budde * use TQXCON_TXAT and FIFOCON_TXAT 52155e5b97fSMarc Kleine-Budde * - wake-up filter bits T11FILTER 52255e5b97fSMarc Kleine-Budde * - use CAN bus line filter for wakeup 52355e5b97fSMarc Kleine-Budde * - protocol exception is treated as a form error 52455e5b97fSMarc Kleine-Budde * - Do not compare data bytes 52555e5b97fSMarc Kleine-Budde */ 526eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, 527eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_MODE_CONFIG) | 528eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_STEF | 529eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_ESIGM | 530eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_RTXAT | 531eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_CON_WFT_MASK, 532eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_WFT_T11FILTER) | 533eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_WAKFIL | 534eb79a267SMarc Kleine-Budde MCP251XFD_REG_CON_PXEDIS; 53555e5b97fSMarc Kleine-Budde 53655e5b97fSMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)) 537eb79a267SMarc Kleine-Budde val |= MCP251XFD_REG_CON_ISOCRCEN; 53855e5b97fSMarc Kleine-Budde 539eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_CON, val); 54055e5b97fSMarc Kleine-Budde if (err) 54155e5b97fSMarc Kleine-Budde return err; 54255e5b97fSMarc Kleine-Budde 54355e5b97fSMarc Kleine-Budde /* Nominal Bit Time */ 544eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_NBTCFG_BRP_MASK, bt->brp - 1) | 545eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG1_MASK, 54655e5b97fSMarc Kleine-Budde bt->prop_seg + bt->phase_seg1 - 1) | 547eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG2_MASK, 54855e5b97fSMarc Kleine-Budde bt->phase_seg2 - 1) | 549eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_NBTCFG_SJW_MASK, bt->sjw - 1); 55055e5b97fSMarc Kleine-Budde 551eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_NBTCFG, val); 55255e5b97fSMarc Kleine-Budde if (err) 55355e5b97fSMarc Kleine-Budde return err; 55455e5b97fSMarc Kleine-Budde 55555e5b97fSMarc Kleine-Budde if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD)) 55655e5b97fSMarc Kleine-Budde return 0; 55755e5b97fSMarc Kleine-Budde 55855e5b97fSMarc Kleine-Budde /* Data Bit Time */ 559eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_DBTCFG_BRP_MASK, dbt->brp - 1) | 560eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG1_MASK, 56155e5b97fSMarc Kleine-Budde dbt->prop_seg + dbt->phase_seg1 - 1) | 562eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG2_MASK, 56355e5b97fSMarc Kleine-Budde dbt->phase_seg2 - 1) | 564eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_DBTCFG_SJW_MASK, dbt->sjw - 1); 56555e5b97fSMarc Kleine-Budde 566eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_DBTCFG, val); 56755e5b97fSMarc Kleine-Budde if (err) 56855e5b97fSMarc Kleine-Budde return err; 56955e5b97fSMarc Kleine-Budde 57055e5b97fSMarc Kleine-Budde /* Transmitter Delay Compensation */ 57155e5b97fSMarc Kleine-Budde tdco = clamp_t(int, dbt->brp * (dbt->prop_seg + dbt->phase_seg1), 57255e5b97fSMarc Kleine-Budde -64, 63); 573eb79a267SMarc Kleine-Budde val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK, 574eb79a267SMarc Kleine-Budde MCP251XFD_REG_TDC_TDCMOD_AUTO) | 575eb79a267SMarc Kleine-Budde FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, tdco); 57655e5b97fSMarc Kleine-Budde 577eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val); 57855e5b97fSMarc Kleine-Budde } 57955e5b97fSMarc Kleine-Budde 580eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_enable(const struct mcp251xfd_priv *priv) 58155e5b97fSMarc Kleine-Budde { 58255e5b97fSMarc Kleine-Budde u32 val; 58355e5b97fSMarc Kleine-Budde 58455e5b97fSMarc Kleine-Budde if (!priv->rx_int) 58555e5b97fSMarc Kleine-Budde return 0; 58655e5b97fSMarc Kleine-Budde 58755e5b97fSMarc Kleine-Budde /* Configure GPIOs: 58855e5b97fSMarc Kleine-Budde * - PIN0: GPIO Input 58955e5b97fSMarc Kleine-Budde * - PIN1: GPIO Input/RX Interrupt 59055e5b97fSMarc Kleine-Budde * 59155e5b97fSMarc Kleine-Budde * PIN1 must be Input, otherwise there is a glitch on the 59255e5b97fSMarc Kleine-Budde * rx-INT line. It happens between setting the PIN as output 59355e5b97fSMarc Kleine-Budde * (in the first byte of the SPI transfer) and configuring the 59455e5b97fSMarc Kleine-Budde * PIN as interrupt (in the last byte of the SPI transfer). 59555e5b97fSMarc Kleine-Budde */ 596eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_IOCON_PM0 | MCP251XFD_REG_IOCON_TRIS1 | 597eb79a267SMarc Kleine-Budde MCP251XFD_REG_IOCON_TRIS0; 598eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val); 59955e5b97fSMarc Kleine-Budde } 60055e5b97fSMarc Kleine-Budde 601eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_disable(const struct mcp251xfd_priv *priv) 60255e5b97fSMarc Kleine-Budde { 60355e5b97fSMarc Kleine-Budde u32 val; 60455e5b97fSMarc Kleine-Budde 60555e5b97fSMarc Kleine-Budde if (!priv->rx_int) 60655e5b97fSMarc Kleine-Budde return 0; 60755e5b97fSMarc Kleine-Budde 60855e5b97fSMarc Kleine-Budde /* Configure GPIOs: 60955e5b97fSMarc Kleine-Budde * - PIN0: GPIO Input 61055e5b97fSMarc Kleine-Budde * - PIN1: GPIO Input 61155e5b97fSMarc Kleine-Budde */ 612eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_IOCON_PM1 | MCP251XFD_REG_IOCON_PM0 | 613eb79a267SMarc Kleine-Budde MCP251XFD_REG_IOCON_TRIS1 | MCP251XFD_REG_IOCON_TRIS0; 614eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val); 61555e5b97fSMarc Kleine-Budde } 61655e5b97fSMarc Kleine-Budde 617eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_ecc_init(struct mcp251xfd_priv *priv) 61855e5b97fSMarc Kleine-Budde { 619eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 62055e5b97fSMarc Kleine-Budde void *ram; 62155e5b97fSMarc Kleine-Budde u32 val = 0; 62255e5b97fSMarc Kleine-Budde int err; 62355e5b97fSMarc Kleine-Budde 62455e5b97fSMarc Kleine-Budde ecc->ecc_stat = 0; 62555e5b97fSMarc Kleine-Budde 626eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_ECC) 627eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_ECCCON_ECCEN; 62855e5b97fSMarc Kleine-Budde 629eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, 630eb79a267SMarc Kleine-Budde MCP251XFD_REG_ECCCON_ECCEN, val); 63155e5b97fSMarc Kleine-Budde if (err) 63255e5b97fSMarc Kleine-Budde return err; 63355e5b97fSMarc Kleine-Budde 634eb79a267SMarc Kleine-Budde ram = kzalloc(MCP251XFD_RAM_SIZE, GFP_KERNEL); 63555e5b97fSMarc Kleine-Budde if (!ram) 63655e5b97fSMarc Kleine-Budde return -ENOMEM; 63755e5b97fSMarc Kleine-Budde 638eb79a267SMarc Kleine-Budde err = regmap_raw_write(priv->map_reg, MCP251XFD_RAM_START, ram, 639eb79a267SMarc Kleine-Budde MCP251XFD_RAM_SIZE); 64055e5b97fSMarc Kleine-Budde kfree(ram); 64155e5b97fSMarc Kleine-Budde 64255e5b97fSMarc Kleine-Budde return err; 64355e5b97fSMarc Kleine-Budde } 64455e5b97fSMarc Kleine-Budde 645eb79a267SMarc Kleine-Budde static u8 mcp251xfd_get_normal_mode(const struct mcp251xfd_priv *priv) 64655e5b97fSMarc Kleine-Budde { 64755e5b97fSMarc Kleine-Budde u8 mode; 64855e5b97fSMarc Kleine-Budde 649ee42bedcSManivannan Sadhasivam if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) 650ee42bedcSManivannan Sadhasivam mode = MCP251XFD_REG_CON_MODE_INT_LOOPBACK; 651ee42bedcSManivannan Sadhasivam else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) 652eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_LISTENONLY; 65333ea42f6SKurt Van Dijck else if (priv->can.ctrlmode & CAN_CTRLMODE_FD) 654eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_MIXED; 65555e5b97fSMarc Kleine-Budde else 656eb79a267SMarc Kleine-Budde mode = MCP251XFD_REG_CON_MODE_CAN2_0; 65755e5b97fSMarc Kleine-Budde 65855e5b97fSMarc Kleine-Budde return mode; 65955e5b97fSMarc Kleine-Budde } 66055e5b97fSMarc Kleine-Budde 66155e5b97fSMarc Kleine-Budde static int 662eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv, 66355e5b97fSMarc Kleine-Budde bool nowait) 66455e5b97fSMarc Kleine-Budde { 66555e5b97fSMarc Kleine-Budde u8 mode; 66655e5b97fSMarc Kleine-Budde 667eb79a267SMarc Kleine-Budde mode = mcp251xfd_get_normal_mode(priv); 66855e5b97fSMarc Kleine-Budde 669eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_mode(priv, mode, nowait); 67055e5b97fSMarc Kleine-Budde } 67155e5b97fSMarc Kleine-Budde 67255e5b97fSMarc Kleine-Budde static inline int 673eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv) 67455e5b97fSMarc Kleine-Budde { 675eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_normal_mode(priv, false); 67655e5b97fSMarc Kleine-Budde } 67755e5b97fSMarc Kleine-Budde 67855e5b97fSMarc Kleine-Budde static inline int 679eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode_nowait(const struct mcp251xfd_priv *priv) 68055e5b97fSMarc Kleine-Budde { 681eb79a267SMarc Kleine-Budde return __mcp251xfd_chip_set_normal_mode(priv, true); 68255e5b97fSMarc Kleine-Budde } 68355e5b97fSMarc Kleine-Budde 684eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_enable(const struct mcp251xfd_priv *priv) 68555e5b97fSMarc Kleine-Budde { 68655e5b97fSMarc Kleine-Budde u32 val; 68755e5b97fSMarc Kleine-Budde int err; 68855e5b97fSMarc Kleine-Budde 689eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_CRC_FERRIE | MCP251XFD_REG_CRC_CRCERRIE; 690eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_CRC, val); 69155e5b97fSMarc Kleine-Budde if (err) 69255e5b97fSMarc Kleine-Budde return err; 69355e5b97fSMarc Kleine-Budde 694eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE; 695eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, val, val); 69655e5b97fSMarc Kleine-Budde if (err) 69755e5b97fSMarc Kleine-Budde return err; 69855e5b97fSMarc Kleine-Budde 699eb79a267SMarc Kleine-Budde val = MCP251XFD_REG_INT_CERRIE | 700eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_SERRIE | 701eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_RXOVIE | 702eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_TXATIE | 703eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_SPICRCIE | 704eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_ECCIE | 705eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_TEFIE | 706eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_MODIE | 707eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_RXIE; 70855e5b97fSMarc Kleine-Budde 70955e5b97fSMarc Kleine-Budde if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) 710eb79a267SMarc Kleine-Budde val |= MCP251XFD_REG_INT_IVMIE; 71155e5b97fSMarc Kleine-Budde 712eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_INT, val); 71355e5b97fSMarc Kleine-Budde } 71455e5b97fSMarc Kleine-Budde 715eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_disable(const struct mcp251xfd_priv *priv) 71655e5b97fSMarc Kleine-Budde { 71755e5b97fSMarc Kleine-Budde int err; 71855e5b97fSMarc Kleine-Budde u32 mask; 71955e5b97fSMarc Kleine-Budde 720eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_INT, 0); 72155e5b97fSMarc Kleine-Budde if (err) 72255e5b97fSMarc Kleine-Budde return err; 72355e5b97fSMarc Kleine-Budde 724eb79a267SMarc Kleine-Budde mask = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE; 725eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, 72655e5b97fSMarc Kleine-Budde mask, 0x0); 72755e5b97fSMarc Kleine-Budde if (err) 72855e5b97fSMarc Kleine-Budde return err; 72955e5b97fSMarc Kleine-Budde 730eb79a267SMarc Kleine-Budde return regmap_write(priv->map_reg, MCP251XFD_REG_CRC, 0); 73155e5b97fSMarc Kleine-Budde } 73255e5b97fSMarc Kleine-Budde 73313c54a1eSMarc Kleine-Budde static void mcp251xfd_chip_stop(struct mcp251xfd_priv *priv, 73455e5b97fSMarc Kleine-Budde const enum can_state state) 73555e5b97fSMarc Kleine-Budde { 73655e5b97fSMarc Kleine-Budde priv->can.state = state; 73755e5b97fSMarc Kleine-Budde 738eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 739eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_int_disable(priv); 74013c54a1eSMarc Kleine-Budde mcp251xfd_chip_sleep(priv); 74155e5b97fSMarc Kleine-Budde } 74255e5b97fSMarc Kleine-Budde 743eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv) 74455e5b97fSMarc Kleine-Budde { 74555e5b97fSMarc Kleine-Budde int err; 74655e5b97fSMarc Kleine-Budde 747eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset(priv); 74855e5b97fSMarc Kleine-Budde if (err) 74955e5b97fSMarc Kleine-Budde goto out_chip_stop; 75055e5b97fSMarc Kleine-Budde 751eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_clock_init(priv); 75255e5b97fSMarc Kleine-Budde if (err) 75355e5b97fSMarc Kleine-Budde goto out_chip_stop; 75455e5b97fSMarc Kleine-Budde 75514193ea2SMarc Kleine-Budde err = mcp251xfd_chip_timestamp_init(priv); 75614193ea2SMarc Kleine-Budde if (err) 75714193ea2SMarc Kleine-Budde goto out_chip_stop; 75814193ea2SMarc Kleine-Budde 759eb79a267SMarc Kleine-Budde err = mcp251xfd_set_bittiming(priv); 76055e5b97fSMarc Kleine-Budde if (err) 76155e5b97fSMarc Kleine-Budde goto out_chip_stop; 76255e5b97fSMarc Kleine-Budde 763eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_enable(priv); 76455e5b97fSMarc Kleine-Budde if (err) 76569c55f6eSMarc Kleine-Budde goto out_chip_stop; 76655e5b97fSMarc Kleine-Budde 767eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_ecc_init(priv); 76855e5b97fSMarc Kleine-Budde if (err) 76955e5b97fSMarc Kleine-Budde goto out_chip_stop; 77055e5b97fSMarc Kleine-Budde 771fa0b68dfSMarc Kleine-Budde err = mcp251xfd_ring_init(priv); 772fa0b68dfSMarc Kleine-Budde if (err) 773fa0b68dfSMarc Kleine-Budde goto out_chip_stop; 77455e5b97fSMarc Kleine-Budde 775eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_fifo_init(priv); 77655e5b97fSMarc Kleine-Budde if (err) 77755e5b97fSMarc Kleine-Budde goto out_chip_stop; 77855e5b97fSMarc Kleine-Budde 77955e5b97fSMarc Kleine-Budde priv->can.state = CAN_STATE_ERROR_ACTIVE; 78055e5b97fSMarc Kleine-Budde 781eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_set_normal_mode(priv); 78255e5b97fSMarc Kleine-Budde if (err) 78355e5b97fSMarc Kleine-Budde goto out_chip_stop; 78455e5b97fSMarc Kleine-Budde 78555e5b97fSMarc Kleine-Budde return 0; 78655e5b97fSMarc Kleine-Budde 78755e5b97fSMarc Kleine-Budde out_chip_stop: 788e0ab3dd5SMarc Kleine-Budde mcp251xfd_dump(priv); 789eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 79055e5b97fSMarc Kleine-Budde 79155e5b97fSMarc Kleine-Budde return err; 79255e5b97fSMarc Kleine-Budde } 79355e5b97fSMarc Kleine-Budde 794eb79a267SMarc Kleine-Budde static int mcp251xfd_set_mode(struct net_device *ndev, enum can_mode mode) 79555e5b97fSMarc Kleine-Budde { 796eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 79755e5b97fSMarc Kleine-Budde int err; 79855e5b97fSMarc Kleine-Budde 79955e5b97fSMarc Kleine-Budde switch (mode) { 80055e5b97fSMarc Kleine-Budde case CAN_MODE_START: 801eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_start(priv); 80255e5b97fSMarc Kleine-Budde if (err) 80355e5b97fSMarc Kleine-Budde return err; 80455e5b97fSMarc Kleine-Budde 805eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_interrupts_enable(priv); 80655e5b97fSMarc Kleine-Budde if (err) { 807eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 80855e5b97fSMarc Kleine-Budde return err; 80955e5b97fSMarc Kleine-Budde } 81055e5b97fSMarc Kleine-Budde 81155e5b97fSMarc Kleine-Budde netif_wake_queue(ndev); 81255e5b97fSMarc Kleine-Budde break; 81355e5b97fSMarc Kleine-Budde 81455e5b97fSMarc Kleine-Budde default: 81555e5b97fSMarc Kleine-Budde return -EOPNOTSUPP; 81655e5b97fSMarc Kleine-Budde } 81755e5b97fSMarc Kleine-Budde 81855e5b97fSMarc Kleine-Budde return 0; 81955e5b97fSMarc Kleine-Budde } 82055e5b97fSMarc Kleine-Budde 821eb79a267SMarc Kleine-Budde static int __mcp251xfd_get_berr_counter(const struct net_device *ndev, 82255e5b97fSMarc Kleine-Budde struct can_berr_counter *bec) 82355e5b97fSMarc Kleine-Budde { 824eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = netdev_priv(ndev); 82555e5b97fSMarc Kleine-Budde u32 trec; 82655e5b97fSMarc Kleine-Budde int err; 82755e5b97fSMarc Kleine-Budde 828eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec); 82955e5b97fSMarc Kleine-Budde if (err) 83055e5b97fSMarc Kleine-Budde return err; 83155e5b97fSMarc Kleine-Budde 832eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_TXBO) 83355e5b97fSMarc Kleine-Budde bec->txerr = 256; 83455e5b97fSMarc Kleine-Budde else 835eb79a267SMarc Kleine-Budde bec->txerr = FIELD_GET(MCP251XFD_REG_TREC_TEC_MASK, trec); 836eb79a267SMarc Kleine-Budde bec->rxerr = FIELD_GET(MCP251XFD_REG_TREC_REC_MASK, trec); 83755e5b97fSMarc Kleine-Budde 83855e5b97fSMarc Kleine-Budde return 0; 83955e5b97fSMarc Kleine-Budde } 84055e5b97fSMarc Kleine-Budde 841eb79a267SMarc Kleine-Budde static int mcp251xfd_get_berr_counter(const struct net_device *ndev, 84255e5b97fSMarc Kleine-Budde struct can_berr_counter *bec) 84355e5b97fSMarc Kleine-Budde { 844eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = netdev_priv(ndev); 84555e5b97fSMarc Kleine-Budde 84655e5b97fSMarc Kleine-Budde /* Avoid waking up the controller if the interface is down */ 84755e5b97fSMarc Kleine-Budde if (!(ndev->flags & IFF_UP)) 84855e5b97fSMarc Kleine-Budde return 0; 84955e5b97fSMarc Kleine-Budde 85055e5b97fSMarc Kleine-Budde /* The controller is powered down during Bus Off, use saved 85155e5b97fSMarc Kleine-Budde * bec values. 85255e5b97fSMarc Kleine-Budde */ 85355e5b97fSMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) { 85455e5b97fSMarc Kleine-Budde *bec = priv->bec; 85555e5b97fSMarc Kleine-Budde return 0; 85655e5b97fSMarc Kleine-Budde } 85755e5b97fSMarc Kleine-Budde 858eb79a267SMarc Kleine-Budde return __mcp251xfd_get_berr_counter(ndev, bec); 85955e5b97fSMarc Kleine-Budde } 86055e5b97fSMarc Kleine-Budde 86155e5b97fSMarc Kleine-Budde static struct sk_buff * 8625f02a49cSMarc Kleine-Budde mcp251xfd_alloc_can_err_skb(struct mcp251xfd_priv *priv, 86355e5b97fSMarc Kleine-Budde struct can_frame **cf, u32 *timestamp) 86455e5b97fSMarc Kleine-Budde { 8655f02a49cSMarc Kleine-Budde struct sk_buff *skb; 86655e5b97fSMarc Kleine-Budde int err; 86755e5b97fSMarc Kleine-Budde 868eb79a267SMarc Kleine-Budde err = mcp251xfd_get_timestamp(priv, timestamp); 86955e5b97fSMarc Kleine-Budde if (err) 87055e5b97fSMarc Kleine-Budde return NULL; 87155e5b97fSMarc Kleine-Budde 8725f02a49cSMarc Kleine-Budde skb = alloc_can_err_skb(priv->ndev, cf); 8735f02a49cSMarc Kleine-Budde if (skb) 8745f02a49cSMarc Kleine-Budde mcp251xfd_skb_set_timestamp(priv, skb, *timestamp); 8755f02a49cSMarc Kleine-Budde 8765f02a49cSMarc Kleine-Budde return skb; 87755e5b97fSMarc Kleine-Budde } 87855e5b97fSMarc Kleine-Budde 879eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_rxovif(struct mcp251xfd_priv *priv) 88055e5b97fSMarc Kleine-Budde { 88155e5b97fSMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 882eb79a267SMarc Kleine-Budde struct mcp251xfd_rx_ring *ring; 88355e5b97fSMarc Kleine-Budde struct sk_buff *skb; 88455e5b97fSMarc Kleine-Budde struct can_frame *cf; 88555e5b97fSMarc Kleine-Budde u32 timestamp, rxovif; 88655e5b97fSMarc Kleine-Budde int err, i; 88755e5b97fSMarc Kleine-Budde 88855e5b97fSMarc Kleine-Budde stats->rx_over_errors++; 88955e5b97fSMarc Kleine-Budde stats->rx_errors++; 89055e5b97fSMarc Kleine-Budde 891eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_RXOVIF, &rxovif); 89255e5b97fSMarc Kleine-Budde if (err) 89355e5b97fSMarc Kleine-Budde return err; 89455e5b97fSMarc Kleine-Budde 895eb79a267SMarc Kleine-Budde mcp251xfd_for_each_rx_ring(priv, ring, i) { 89655e5b97fSMarc Kleine-Budde if (!(rxovif & BIT(ring->fifo_nr))) 89755e5b97fSMarc Kleine-Budde continue; 89855e5b97fSMarc Kleine-Budde 89955e5b97fSMarc Kleine-Budde /* If SERRIF is active, there was a RX MAB overflow. */ 900eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_SERRIF) { 90158d0b0a9SMarc Kleine-Budde if (net_ratelimit()) 90258d0b0a9SMarc Kleine-Budde netdev_dbg(priv->ndev, 90355e5b97fSMarc Kleine-Budde "RX-%d: MAB overflow detected.\n", 90455e5b97fSMarc Kleine-Budde ring->nr); 90555e5b97fSMarc Kleine-Budde } else { 90658d0b0a9SMarc Kleine-Budde if (net_ratelimit()) 90758d0b0a9SMarc Kleine-Budde netdev_dbg(priv->ndev, 90858d0b0a9SMarc Kleine-Budde "RX-%d: FIFO overflow.\n", 90958d0b0a9SMarc Kleine-Budde ring->nr); 91055e5b97fSMarc Kleine-Budde } 91155e5b97fSMarc Kleine-Budde 91255e5b97fSMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 913eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA(ring->fifo_nr), 914eb79a267SMarc Kleine-Budde MCP251XFD_REG_FIFOSTA_RXOVIF, 91555e5b97fSMarc Kleine-Budde 0x0); 91655e5b97fSMarc Kleine-Budde if (err) 91755e5b97fSMarc Kleine-Budde return err; 91855e5b97fSMarc Kleine-Budde } 91955e5b97fSMarc Kleine-Budde 920eb79a267SMarc Kleine-Budde skb = mcp251xfd_alloc_can_err_skb(priv, &cf, ×tamp); 92155e5b97fSMarc Kleine-Budde if (!skb) 92255e5b97fSMarc Kleine-Budde return 0; 92355e5b97fSMarc Kleine-Budde 92455e5b97fSMarc Kleine-Budde cf->can_id |= CAN_ERR_CRTL; 92555e5b97fSMarc Kleine-Budde cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; 92655e5b97fSMarc Kleine-Budde 927eb38c205SMarc Kleine-Budde err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); 92855e5b97fSMarc Kleine-Budde if (err) 92955e5b97fSMarc Kleine-Budde stats->rx_fifo_errors++; 93055e5b97fSMarc Kleine-Budde 93155e5b97fSMarc Kleine-Budde return 0; 93255e5b97fSMarc Kleine-Budde } 93355e5b97fSMarc Kleine-Budde 934eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_txatif(struct mcp251xfd_priv *priv) 93555e5b97fSMarc Kleine-Budde { 93655e5b97fSMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", __func__); 93755e5b97fSMarc Kleine-Budde 93855e5b97fSMarc Kleine-Budde return 0; 93955e5b97fSMarc Kleine-Budde } 94055e5b97fSMarc Kleine-Budde 941eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_ivmif(struct mcp251xfd_priv *priv) 94255e5b97fSMarc Kleine-Budde { 94355e5b97fSMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 94455e5b97fSMarc Kleine-Budde u32 bdiag1, timestamp; 94555e5b97fSMarc Kleine-Budde struct sk_buff *skb; 94655e5b97fSMarc Kleine-Budde struct can_frame *cf = NULL; 94755e5b97fSMarc Kleine-Budde int err; 94855e5b97fSMarc Kleine-Budde 949eb79a267SMarc Kleine-Budde err = mcp251xfd_get_timestamp(priv, ×tamp); 95055e5b97fSMarc Kleine-Budde if (err) 95155e5b97fSMarc Kleine-Budde return err; 95255e5b97fSMarc Kleine-Budde 953eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_BDIAG1, &bdiag1); 95455e5b97fSMarc Kleine-Budde if (err) 95555e5b97fSMarc Kleine-Budde return err; 95655e5b97fSMarc Kleine-Budde 95755e5b97fSMarc Kleine-Budde /* Write 0s to clear error bits, don't write 1s to non active 95855e5b97fSMarc Kleine-Budde * bits, as they will be set. 95955e5b97fSMarc Kleine-Budde */ 960eb79a267SMarc Kleine-Budde err = regmap_write(priv->map_reg, MCP251XFD_REG_BDIAG1, 0x0); 96155e5b97fSMarc Kleine-Budde if (err) 96255e5b97fSMarc Kleine-Budde return err; 96355e5b97fSMarc Kleine-Budde 96455e5b97fSMarc Kleine-Budde priv->can.can_stats.bus_error++; 96555e5b97fSMarc Kleine-Budde 96655e5b97fSMarc Kleine-Budde skb = alloc_can_err_skb(priv->ndev, &cf); 96755e5b97fSMarc Kleine-Budde if (cf) 96855e5b97fSMarc Kleine-Budde cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; 96955e5b97fSMarc Kleine-Budde 97055e5b97fSMarc Kleine-Budde /* Controller misconfiguration */ 971eb79a267SMarc Kleine-Budde if (WARN_ON(bdiag1 & MCP251XFD_REG_BDIAG1_DLCMM)) 97255e5b97fSMarc Kleine-Budde netdev_err(priv->ndev, 97355e5b97fSMarc Kleine-Budde "recv'd DLC is larger than PLSIZE of FIFO element."); 97455e5b97fSMarc Kleine-Budde 97555e5b97fSMarc Kleine-Budde /* RX errors */ 976eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DCRCERR | 977eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NCRCERR)) { 97855e5b97fSMarc Kleine-Budde netdev_dbg(priv->ndev, "CRC error\n"); 97955e5b97fSMarc Kleine-Budde 98055e5b97fSMarc Kleine-Budde stats->rx_errors++; 98155e5b97fSMarc Kleine-Budde if (cf) 98255e5b97fSMarc Kleine-Budde cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ; 98355e5b97fSMarc Kleine-Budde } 984eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DSTUFERR | 985eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NSTUFERR)) { 98655e5b97fSMarc Kleine-Budde netdev_dbg(priv->ndev, "Stuff error\n"); 98755e5b97fSMarc Kleine-Budde 98855e5b97fSMarc Kleine-Budde stats->rx_errors++; 98955e5b97fSMarc Kleine-Budde if (cf) 99055e5b97fSMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_STUFF; 99155e5b97fSMarc Kleine-Budde } 992eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DFORMERR | 993eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NFORMERR)) { 99455e5b97fSMarc Kleine-Budde netdev_dbg(priv->ndev, "Format error\n"); 99555e5b97fSMarc Kleine-Budde 99655e5b97fSMarc Kleine-Budde stats->rx_errors++; 99755e5b97fSMarc Kleine-Budde if (cf) 99855e5b97fSMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_FORM; 99955e5b97fSMarc Kleine-Budde } 100055e5b97fSMarc Kleine-Budde 100155e5b97fSMarc Kleine-Budde /* TX errors */ 1002eb79a267SMarc Kleine-Budde if (bdiag1 & MCP251XFD_REG_BDIAG1_NACKERR) { 100355e5b97fSMarc Kleine-Budde netdev_dbg(priv->ndev, "NACK error\n"); 100455e5b97fSMarc Kleine-Budde 100555e5b97fSMarc Kleine-Budde stats->tx_errors++; 100655e5b97fSMarc Kleine-Budde if (cf) { 100755e5b97fSMarc Kleine-Budde cf->can_id |= CAN_ERR_ACK; 100855e5b97fSMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX; 100955e5b97fSMarc Kleine-Budde } 101055e5b97fSMarc Kleine-Budde } 1011eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT1ERR | 1012eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NBIT1ERR)) { 101355e5b97fSMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit1 error\n"); 101455e5b97fSMarc Kleine-Budde 101555e5b97fSMarc Kleine-Budde stats->tx_errors++; 101655e5b97fSMarc Kleine-Budde if (cf) 101755e5b97fSMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT1; 101855e5b97fSMarc Kleine-Budde } 1019eb79a267SMarc Kleine-Budde if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT0ERR | 1020eb79a267SMarc Kleine-Budde MCP251XFD_REG_BDIAG1_NBIT0ERR)) { 102155e5b97fSMarc Kleine-Budde netdev_dbg(priv->ndev, "Bit0 error\n"); 102255e5b97fSMarc Kleine-Budde 102355e5b97fSMarc Kleine-Budde stats->tx_errors++; 102455e5b97fSMarc Kleine-Budde if (cf) 102555e5b97fSMarc Kleine-Budde cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT0; 102655e5b97fSMarc Kleine-Budde } 102755e5b97fSMarc Kleine-Budde 102855e5b97fSMarc Kleine-Budde if (!cf) 102955e5b97fSMarc Kleine-Budde return 0; 103055e5b97fSMarc Kleine-Budde 10315f02a49cSMarc Kleine-Budde mcp251xfd_skb_set_timestamp(priv, skb, timestamp); 1032eb38c205SMarc Kleine-Budde err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); 103355e5b97fSMarc Kleine-Budde if (err) 103455e5b97fSMarc Kleine-Budde stats->rx_fifo_errors++; 103555e5b97fSMarc Kleine-Budde 103655e5b97fSMarc Kleine-Budde return 0; 103755e5b97fSMarc Kleine-Budde } 103855e5b97fSMarc Kleine-Budde 1039eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv) 104055e5b97fSMarc Kleine-Budde { 104155e5b97fSMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 104255e5b97fSMarc Kleine-Budde struct sk_buff *skb; 104355e5b97fSMarc Kleine-Budde struct can_frame *cf = NULL; 104455e5b97fSMarc Kleine-Budde enum can_state new_state, rx_state, tx_state; 104555e5b97fSMarc Kleine-Budde u32 trec, timestamp; 104655e5b97fSMarc Kleine-Budde int err; 104755e5b97fSMarc Kleine-Budde 1048eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec); 104955e5b97fSMarc Kleine-Budde if (err) 105055e5b97fSMarc Kleine-Budde return err; 105155e5b97fSMarc Kleine-Budde 1052eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_TXBO) 105355e5b97fSMarc Kleine-Budde tx_state = CAN_STATE_BUS_OFF; 1054eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_TXBP) 105555e5b97fSMarc Kleine-Budde tx_state = CAN_STATE_ERROR_PASSIVE; 1056eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_TXWARN) 105755e5b97fSMarc Kleine-Budde tx_state = CAN_STATE_ERROR_WARNING; 105855e5b97fSMarc Kleine-Budde else 105955e5b97fSMarc Kleine-Budde tx_state = CAN_STATE_ERROR_ACTIVE; 106055e5b97fSMarc Kleine-Budde 1061eb79a267SMarc Kleine-Budde if (trec & MCP251XFD_REG_TREC_RXBP) 106255e5b97fSMarc Kleine-Budde rx_state = CAN_STATE_ERROR_PASSIVE; 1063eb79a267SMarc Kleine-Budde else if (trec & MCP251XFD_REG_TREC_RXWARN) 106455e5b97fSMarc Kleine-Budde rx_state = CAN_STATE_ERROR_WARNING; 106555e5b97fSMarc Kleine-Budde else 106655e5b97fSMarc Kleine-Budde rx_state = CAN_STATE_ERROR_ACTIVE; 106755e5b97fSMarc Kleine-Budde 106855e5b97fSMarc Kleine-Budde new_state = max(tx_state, rx_state); 106955e5b97fSMarc Kleine-Budde if (new_state == priv->can.state) 107055e5b97fSMarc Kleine-Budde return 0; 107155e5b97fSMarc Kleine-Budde 107255e5b97fSMarc Kleine-Budde /* The skb allocation might fail, but can_change_state() 107355e5b97fSMarc Kleine-Budde * handles cf == NULL. 107455e5b97fSMarc Kleine-Budde */ 1075eb79a267SMarc Kleine-Budde skb = mcp251xfd_alloc_can_err_skb(priv, &cf, ×tamp); 107655e5b97fSMarc Kleine-Budde can_change_state(priv->ndev, cf, tx_state, rx_state); 107755e5b97fSMarc Kleine-Budde 107855e5b97fSMarc Kleine-Budde if (new_state == CAN_STATE_BUS_OFF) { 107955e5b97fSMarc Kleine-Budde /* As we're going to switch off the chip now, let's 108055e5b97fSMarc Kleine-Budde * save the error counters and return them to 108155e5b97fSMarc Kleine-Budde * userspace, if do_get_berr_counter() is called while 108255e5b97fSMarc Kleine-Budde * the chip is in Bus Off. 108355e5b97fSMarc Kleine-Budde */ 1084eb79a267SMarc Kleine-Budde err = __mcp251xfd_get_berr_counter(priv->ndev, &priv->bec); 108555e5b97fSMarc Kleine-Budde if (err) 108655e5b97fSMarc Kleine-Budde return err; 108755e5b97fSMarc Kleine-Budde 1088eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_BUS_OFF); 108955e5b97fSMarc Kleine-Budde can_bus_off(priv->ndev); 109055e5b97fSMarc Kleine-Budde } 109155e5b97fSMarc Kleine-Budde 109255e5b97fSMarc Kleine-Budde if (!skb) 109355e5b97fSMarc Kleine-Budde return 0; 109455e5b97fSMarc Kleine-Budde 109555e5b97fSMarc Kleine-Budde if (new_state != CAN_STATE_BUS_OFF) { 109655e5b97fSMarc Kleine-Budde struct can_berr_counter bec; 109755e5b97fSMarc Kleine-Budde 1098eb79a267SMarc Kleine-Budde err = mcp251xfd_get_berr_counter(priv->ndev, &bec); 109955e5b97fSMarc Kleine-Budde if (err) 110055e5b97fSMarc Kleine-Budde return err; 110155e5b97fSMarc Kleine-Budde cf->data[6] = bec.txerr; 110255e5b97fSMarc Kleine-Budde cf->data[7] = bec.rxerr; 110355e5b97fSMarc Kleine-Budde } 110455e5b97fSMarc Kleine-Budde 1105eb38c205SMarc Kleine-Budde err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp); 110655e5b97fSMarc Kleine-Budde if (err) 110755e5b97fSMarc Kleine-Budde stats->rx_fifo_errors++; 110855e5b97fSMarc Kleine-Budde 110955e5b97fSMarc Kleine-Budde return 0; 111055e5b97fSMarc Kleine-Budde } 111155e5b97fSMarc Kleine-Budde 111255e5b97fSMarc Kleine-Budde static int 1113eb79a267SMarc Kleine-Budde mcp251xfd_handle_modif(const struct mcp251xfd_priv *priv, bool *set_normal_mode) 111455e5b97fSMarc Kleine-Budde { 1115eb79a267SMarc Kleine-Budde const u8 mode_reference = mcp251xfd_get_normal_mode(priv); 111655e5b97fSMarc Kleine-Budde u8 mode; 111755e5b97fSMarc Kleine-Budde int err; 111855e5b97fSMarc Kleine-Budde 1119eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_get_mode(priv, &mode); 112055e5b97fSMarc Kleine-Budde if (err) 112155e5b97fSMarc Kleine-Budde return err; 112255e5b97fSMarc Kleine-Budde 112355e5b97fSMarc Kleine-Budde if (mode == mode_reference) { 112455e5b97fSMarc Kleine-Budde netdev_dbg(priv->ndev, 112555e5b97fSMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1126eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 112755e5b97fSMarc Kleine-Budde return 0; 112855e5b97fSMarc Kleine-Budde } 112955e5b97fSMarc Kleine-Budde 113055e5b97fSMarc Kleine-Budde /* According to MCP2517FD errata DS80000792B 1., during a TX 113155e5b97fSMarc Kleine-Budde * MAB underflow, the controller will transition to Restricted 113255e5b97fSMarc Kleine-Budde * Operation Mode or Listen Only Mode (depending on SERR2LOM). 113355e5b97fSMarc Kleine-Budde * 113455e5b97fSMarc Kleine-Budde * However this is not always the case. If SERR2LOM is 113555e5b97fSMarc Kleine-Budde * configured for Restricted Operation Mode (SERR2LOM not set) 113655e5b97fSMarc Kleine-Budde * the MCP2517FD will sometimes transition to Listen Only Mode 113755e5b97fSMarc Kleine-Budde * first. When polling this bit we see that it will transition 113855e5b97fSMarc Kleine-Budde * to Restricted Operation Mode shortly after. 113955e5b97fSMarc Kleine-Budde */ 1140eb79a267SMarc Kleine-Budde if ((priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN) && 1141eb79a267SMarc Kleine-Budde (mode == MCP251XFD_REG_CON_MODE_RESTRICTED || 1142eb79a267SMarc Kleine-Budde mode == MCP251XFD_REG_CON_MODE_LISTENONLY)) 114355e5b97fSMarc Kleine-Budde netdev_dbg(priv->ndev, 114455e5b97fSMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1145eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 114655e5b97fSMarc Kleine-Budde else 114755e5b97fSMarc Kleine-Budde netdev_err(priv->ndev, 114855e5b97fSMarc Kleine-Budde "Controller changed into %s Mode (%u).\n", 1149eb79a267SMarc Kleine-Budde mcp251xfd_get_mode_str(mode), mode); 115055e5b97fSMarc Kleine-Budde 1151f93486a7SMarc Kleine-Budde /* After the application requests Normal mode, the controller 115255e5b97fSMarc Kleine-Budde * will automatically attempt to retransmit the message that 115355e5b97fSMarc Kleine-Budde * caused the TX MAB underflow. 115455e5b97fSMarc Kleine-Budde * 115555e5b97fSMarc Kleine-Budde * However, if there is an ECC error in the TX-RAM, we first 115655e5b97fSMarc Kleine-Budde * have to reload the tx-object before requesting Normal 1157eb79a267SMarc Kleine-Budde * mode. This is done later in mcp251xfd_handle_eccif(). 115855e5b97fSMarc Kleine-Budde */ 1159eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF) { 116055e5b97fSMarc Kleine-Budde *set_normal_mode = true; 116155e5b97fSMarc Kleine-Budde return 0; 116255e5b97fSMarc Kleine-Budde } 116355e5b97fSMarc Kleine-Budde 1164eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode_nowait(priv); 116555e5b97fSMarc Kleine-Budde } 116655e5b97fSMarc Kleine-Budde 1167eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_serrif(struct mcp251xfd_priv *priv) 116855e5b97fSMarc Kleine-Budde { 1169eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 117055e5b97fSMarc Kleine-Budde struct net_device_stats *stats = &priv->ndev->stats; 117155e5b97fSMarc Kleine-Budde bool handled = false; 117255e5b97fSMarc Kleine-Budde 117355e5b97fSMarc Kleine-Budde /* TX MAB underflow 117455e5b97fSMarc Kleine-Budde * 117555e5b97fSMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a TX MAB 117655e5b97fSMarc Kleine-Budde * underflow is indicated by SERRIF and MODIF. 117755e5b97fSMarc Kleine-Budde * 117855e5b97fSMarc Kleine-Budde * In addition to the effects mentioned in the Errata, there 117955e5b97fSMarc Kleine-Budde * are Bus Errors due to the aborted CAN frame, so a IVMIF 118055e5b97fSMarc Kleine-Budde * will be seen as well. 118155e5b97fSMarc Kleine-Budde * 118255e5b97fSMarc Kleine-Budde * Sometimes there is an ECC error in the TX-RAM, which leads 118355e5b97fSMarc Kleine-Budde * to a TX MAB underflow. 118455e5b97fSMarc Kleine-Budde * 118555e5b97fSMarc Kleine-Budde * However, probably due to a race condition, there is no 118655e5b97fSMarc Kleine-Budde * associated MODIF pending. 118755e5b97fSMarc Kleine-Budde * 118855e5b97fSMarc Kleine-Budde * Further, there are situations, where the SERRIF is caused 118955e5b97fSMarc Kleine-Budde * by an ECC error in the TX-RAM, but not even the ECCIF is 119055e5b97fSMarc Kleine-Budde * set. This only seems to happen _after_ the first occurrence 119155e5b97fSMarc Kleine-Budde * of a ECCIF (which is tracked in ecc->cnt). 119255e5b97fSMarc Kleine-Budde * 119355e5b97fSMarc Kleine-Budde * Treat all as a known system errors.. 119455e5b97fSMarc Kleine-Budde */ 1195eb79a267SMarc Kleine-Budde if ((priv->regs_status.intf & MCP251XFD_REG_INT_MODIF && 1196eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_IVMIF) || 1197eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF || 119855e5b97fSMarc Kleine-Budde ecc->cnt) { 119955e5b97fSMarc Kleine-Budde const char *msg; 120055e5b97fSMarc Kleine-Budde 1201eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF || 120255e5b97fSMarc Kleine-Budde ecc->cnt) 120355e5b97fSMarc Kleine-Budde msg = "TX MAB underflow due to ECC error detected."; 120455e5b97fSMarc Kleine-Budde else 120555e5b97fSMarc Kleine-Budde msg = "TX MAB underflow detected."; 120655e5b97fSMarc Kleine-Budde 1207eb79a267SMarc Kleine-Budde if (priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN) 120855e5b97fSMarc Kleine-Budde netdev_dbg(priv->ndev, "%s\n", msg); 120955e5b97fSMarc Kleine-Budde else 121055e5b97fSMarc Kleine-Budde netdev_info(priv->ndev, "%s\n", msg); 121155e5b97fSMarc Kleine-Budde 121255e5b97fSMarc Kleine-Budde stats->tx_aborted_errors++; 121355e5b97fSMarc Kleine-Budde stats->tx_errors++; 121455e5b97fSMarc Kleine-Budde handled = true; 121555e5b97fSMarc Kleine-Budde } 121655e5b97fSMarc Kleine-Budde 121755e5b97fSMarc Kleine-Budde /* RX MAB overflow 121855e5b97fSMarc Kleine-Budde * 121955e5b97fSMarc Kleine-Budde * According to MCP2517FD Errata DS80000792B 1. a RX MAB 122055e5b97fSMarc Kleine-Budde * overflow is indicated by SERRIF. 122155e5b97fSMarc Kleine-Budde * 122255e5b97fSMarc Kleine-Budde * In addition to the effects mentioned in the Errata, (most 122355e5b97fSMarc Kleine-Budde * of the times) a RXOVIF is raised, if the FIFO that is being 122455e5b97fSMarc Kleine-Budde * received into has the RXOVIE activated (and we have enabled 122555e5b97fSMarc Kleine-Budde * RXOVIE on all FIFOs). 122655e5b97fSMarc Kleine-Budde * 122755e5b97fSMarc Kleine-Budde * Sometimes there is no RXOVIF just a RXIF is pending. 122855e5b97fSMarc Kleine-Budde * 122955e5b97fSMarc Kleine-Budde * Treat all as a known system errors.. 123055e5b97fSMarc Kleine-Budde */ 1231eb79a267SMarc Kleine-Budde if (priv->regs_status.intf & MCP251XFD_REG_INT_RXOVIF || 1232eb79a267SMarc Kleine-Budde priv->regs_status.intf & MCP251XFD_REG_INT_RXIF) { 123355e5b97fSMarc Kleine-Budde stats->rx_dropped++; 123455e5b97fSMarc Kleine-Budde handled = true; 123555e5b97fSMarc Kleine-Budde } 123655e5b97fSMarc Kleine-Budde 123755e5b97fSMarc Kleine-Budde if (!handled) 123855e5b97fSMarc Kleine-Budde netdev_err(priv->ndev, 123955e5b97fSMarc Kleine-Budde "Unhandled System Error Interrupt (intf=0x%08x)!\n", 124055e5b97fSMarc Kleine-Budde priv->regs_status.intf); 124155e5b97fSMarc Kleine-Budde 124255e5b97fSMarc Kleine-Budde return 0; 124355e5b97fSMarc Kleine-Budde } 124455e5b97fSMarc Kleine-Budde 124555e5b97fSMarc Kleine-Budde static int 1246eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif_recover(struct mcp251xfd_priv *priv, u8 nr) 124755e5b97fSMarc Kleine-Budde { 1248eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_ring *tx_ring = priv->tx; 1249eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 1250eb79a267SMarc Kleine-Budde struct mcp251xfd_tx_obj *tx_obj; 125155e5b97fSMarc Kleine-Budde u8 chip_tx_tail, tx_tail, offset; 125255e5b97fSMarc Kleine-Budde u16 addr; 125355e5b97fSMarc Kleine-Budde int err; 125455e5b97fSMarc Kleine-Budde 1255eb79a267SMarc Kleine-Budde addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc->ecc_stat); 125655e5b97fSMarc Kleine-Budde 1257eb79a267SMarc Kleine-Budde err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail); 125855e5b97fSMarc Kleine-Budde if (err) 125955e5b97fSMarc Kleine-Budde return err; 126055e5b97fSMarc Kleine-Budde 1261eb79a267SMarc Kleine-Budde tx_tail = mcp251xfd_get_tx_tail(tx_ring); 126255e5b97fSMarc Kleine-Budde offset = (nr - chip_tx_tail) & (tx_ring->obj_num - 1); 126355e5b97fSMarc Kleine-Budde 126455e5b97fSMarc Kleine-Budde /* Bail out if one of the following is met: 126555e5b97fSMarc Kleine-Budde * - tx_tail information is inconsistent 126655e5b97fSMarc Kleine-Budde * - for mcp2517fd: offset not 0 126755e5b97fSMarc Kleine-Budde * - for mcp2518fd: offset not 0 or 1 126855e5b97fSMarc Kleine-Budde */ 126955e5b97fSMarc Kleine-Budde if (chip_tx_tail != tx_tail || 1270c6f2a617SMarc Kleine-Budde !(offset == 0 || (offset == 1 && (mcp251xfd_is_2518FD(priv) || 1271c6f2a617SMarc Kleine-Budde mcp251xfd_is_251863(priv))))) { 127255e5b97fSMarc Kleine-Budde netdev_err(priv->ndev, 127355e5b97fSMarc Kleine-Budde "ECC Error information inconsistent (addr=0x%04x, nr=%d, tx_tail=0x%08x(%d), chip_tx_tail=%d, offset=%d).\n", 127455e5b97fSMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, chip_tx_tail, 127555e5b97fSMarc Kleine-Budde offset); 127655e5b97fSMarc Kleine-Budde return -EINVAL; 127755e5b97fSMarc Kleine-Budde } 127855e5b97fSMarc Kleine-Budde 127955e5b97fSMarc Kleine-Budde netdev_info(priv->ndev, 128055e5b97fSMarc Kleine-Budde "Recovering %s ECC Error at address 0x%04x (in TX-RAM, tx_obj=%d, tx_tail=0x%08x(%d), offset=%d).\n", 1281eb79a267SMarc Kleine-Budde ecc->ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF ? 128255e5b97fSMarc Kleine-Budde "Single" : "Double", 128355e5b97fSMarc Kleine-Budde addr, nr, tx_ring->tail, tx_tail, offset); 128455e5b97fSMarc Kleine-Budde 128555e5b97fSMarc Kleine-Budde /* reload tx_obj into controller RAM ... */ 128655e5b97fSMarc Kleine-Budde tx_obj = &tx_ring->obj[nr]; 128755e5b97fSMarc Kleine-Budde err = spi_sync_transfer(priv->spi, tx_obj->xfer, 1); 128855e5b97fSMarc Kleine-Budde if (err) 128955e5b97fSMarc Kleine-Budde return err; 129055e5b97fSMarc Kleine-Budde 129155e5b97fSMarc Kleine-Budde /* ... and trigger retransmit */ 1292eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode(priv); 129355e5b97fSMarc Kleine-Budde } 129455e5b97fSMarc Kleine-Budde 129555e5b97fSMarc Kleine-Budde static int 1296eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif(struct mcp251xfd_priv *priv, bool set_normal_mode) 129755e5b97fSMarc Kleine-Budde { 1298eb79a267SMarc Kleine-Budde struct mcp251xfd_ecc *ecc = &priv->ecc; 129955e5b97fSMarc Kleine-Budde const char *msg; 130055e5b97fSMarc Kleine-Budde bool in_tx_ram; 130155e5b97fSMarc Kleine-Budde u32 ecc_stat; 130255e5b97fSMarc Kleine-Budde u16 addr; 130355e5b97fSMarc Kleine-Budde u8 nr; 130455e5b97fSMarc Kleine-Budde int err; 130555e5b97fSMarc Kleine-Budde 1306eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_ECCSTAT, &ecc_stat); 130755e5b97fSMarc Kleine-Budde if (err) 130855e5b97fSMarc Kleine-Budde return err; 130955e5b97fSMarc Kleine-Budde 1310eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCSTAT, 1311eb79a267SMarc Kleine-Budde MCP251XFD_REG_ECCSTAT_IF_MASK, ~ecc_stat); 131255e5b97fSMarc Kleine-Budde if (err) 131355e5b97fSMarc Kleine-Budde return err; 131455e5b97fSMarc Kleine-Budde 131555e5b97fSMarc Kleine-Budde /* Check if ECC error occurred in TX-RAM */ 1316eb79a267SMarc Kleine-Budde addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc_stat); 1317eb79a267SMarc Kleine-Budde err = mcp251xfd_get_tx_nr_by_addr(priv->tx, &nr, addr); 131855e5b97fSMarc Kleine-Budde if (!err) 131955e5b97fSMarc Kleine-Budde in_tx_ram = true; 132055e5b97fSMarc Kleine-Budde else if (err == -ENOENT) 132155e5b97fSMarc Kleine-Budde in_tx_ram = false; 132255e5b97fSMarc Kleine-Budde else 132355e5b97fSMarc Kleine-Budde return err; 132455e5b97fSMarc Kleine-Budde 1325788b83eaSThomas Kopp /* Errata Reference: 1326788b83eaSThomas Kopp * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 2. 1327788b83eaSThomas Kopp * 1328788b83eaSThomas Kopp * ECC single error correction does not work in all cases: 1329788b83eaSThomas Kopp * 1330788b83eaSThomas Kopp * Fix/Work Around: 1331788b83eaSThomas Kopp * Enable single error correction and double error detection 1332788b83eaSThomas Kopp * interrupts by setting SECIE and DEDIE. Handle SECIF as a 1333788b83eaSThomas Kopp * detection interrupt and do not rely on the error 1334788b83eaSThomas Kopp * correction. Instead, handle both interrupts as a 1335788b83eaSThomas Kopp * notification that the RAM word at ERRADDR was corrupted. 1336788b83eaSThomas Kopp */ 1337eb79a267SMarc Kleine-Budde if (ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF) 1338788b83eaSThomas Kopp msg = "Single ECC Error detected at address"; 1339eb79a267SMarc Kleine-Budde else if (ecc_stat & MCP251XFD_REG_ECCSTAT_DEDIF) 134055e5b97fSMarc Kleine-Budde msg = "Double ECC Error detected at address"; 134155e5b97fSMarc Kleine-Budde else 134255e5b97fSMarc Kleine-Budde return -EINVAL; 134355e5b97fSMarc Kleine-Budde 134455e5b97fSMarc Kleine-Budde if (!in_tx_ram) { 134555e5b97fSMarc Kleine-Budde ecc->ecc_stat = 0; 134655e5b97fSMarc Kleine-Budde 1347788b83eaSThomas Kopp netdev_notice(priv->ndev, "%s 0x%04x.\n", msg, addr); 134855e5b97fSMarc Kleine-Budde } else { 134955e5b97fSMarc Kleine-Budde /* Re-occurring error? */ 135055e5b97fSMarc Kleine-Budde if (ecc->ecc_stat == ecc_stat) { 135155e5b97fSMarc Kleine-Budde ecc->cnt++; 135255e5b97fSMarc Kleine-Budde } else { 135355e5b97fSMarc Kleine-Budde ecc->ecc_stat = ecc_stat; 135455e5b97fSMarc Kleine-Budde ecc->cnt = 1; 135555e5b97fSMarc Kleine-Budde } 135655e5b97fSMarc Kleine-Budde 135755e5b97fSMarc Kleine-Budde netdev_info(priv->ndev, 135855e5b97fSMarc Kleine-Budde "%s 0x%04x (in TX-RAM, tx_obj=%d), occurred %d time%s.\n", 135955e5b97fSMarc Kleine-Budde msg, addr, nr, ecc->cnt, ecc->cnt > 1 ? "s" : ""); 136055e5b97fSMarc Kleine-Budde 1361eb79a267SMarc Kleine-Budde if (ecc->cnt >= MCP251XFD_ECC_CNT_MAX) 1362eb79a267SMarc Kleine-Budde return mcp251xfd_handle_eccif_recover(priv, nr); 136355e5b97fSMarc Kleine-Budde } 136455e5b97fSMarc Kleine-Budde 136555e5b97fSMarc Kleine-Budde if (set_normal_mode) 1366eb79a267SMarc Kleine-Budde return mcp251xfd_chip_set_normal_mode_nowait(priv); 136755e5b97fSMarc Kleine-Budde 136855e5b97fSMarc Kleine-Budde return 0; 136955e5b97fSMarc Kleine-Budde } 137055e5b97fSMarc Kleine-Budde 1371eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_spicrcif(struct mcp251xfd_priv *priv) 137255e5b97fSMarc Kleine-Budde { 137355e5b97fSMarc Kleine-Budde int err; 137455e5b97fSMarc Kleine-Budde u32 crc; 137555e5b97fSMarc Kleine-Budde 1376eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_CRC, &crc); 137755e5b97fSMarc Kleine-Budde if (err) 137855e5b97fSMarc Kleine-Budde return err; 137955e5b97fSMarc Kleine-Budde 1380eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CRC, 1381eb79a267SMarc Kleine-Budde MCP251XFD_REG_CRC_IF_MASK, 138255e5b97fSMarc Kleine-Budde ~crc); 138355e5b97fSMarc Kleine-Budde if (err) 138455e5b97fSMarc Kleine-Budde return err; 138555e5b97fSMarc Kleine-Budde 1386eb79a267SMarc Kleine-Budde if (crc & MCP251XFD_REG_CRC_FERRIF) 138755e5b97fSMarc Kleine-Budde netdev_notice(priv->ndev, "CRC write command format error.\n"); 1388eb79a267SMarc Kleine-Budde else if (crc & MCP251XFD_REG_CRC_CRCERRIF) 138955e5b97fSMarc Kleine-Budde netdev_notice(priv->ndev, 139055e5b97fSMarc Kleine-Budde "CRC write error detected. CRC=0x%04lx.\n", 1391eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_CRC_MASK, crc)); 139255e5b97fSMarc Kleine-Budde 139355e5b97fSMarc Kleine-Budde return 0; 139455e5b97fSMarc Kleine-Budde } 139555e5b97fSMarc Kleine-Budde 1396887e359dSMarc Kleine-Budde static int mcp251xfd_read_regs_status(struct mcp251xfd_priv *priv) 1397887e359dSMarc Kleine-Budde { 1398887e359dSMarc Kleine-Budde const int val_bytes = regmap_get_val_bytes(priv->map_reg); 1399887e359dSMarc Kleine-Budde size_t len; 1400887e359dSMarc Kleine-Budde 1401887e359dSMarc Kleine-Budde if (priv->rx_ring_num == 1) 1402887e359dSMarc Kleine-Budde len = sizeof(priv->regs_status.intf); 1403887e359dSMarc Kleine-Budde else 1404887e359dSMarc Kleine-Budde len = sizeof(priv->regs_status); 1405887e359dSMarc Kleine-Budde 1406887e359dSMarc Kleine-Budde return regmap_bulk_read(priv->map_reg, MCP251XFD_REG_INT, 1407887e359dSMarc Kleine-Budde &priv->regs_status, len / val_bytes); 1408887e359dSMarc Kleine-Budde } 1409887e359dSMarc Kleine-Budde 1410eb79a267SMarc Kleine-Budde #define mcp251xfd_handle(priv, irq, ...) \ 141155e5b97fSMarc Kleine-Budde ({ \ 1412eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *_priv = (priv); \ 141355e5b97fSMarc Kleine-Budde int err; \ 141455e5b97fSMarc Kleine-Budde \ 1415eb79a267SMarc Kleine-Budde err = mcp251xfd_handle_##irq(_priv, ## __VA_ARGS__); \ 141655e5b97fSMarc Kleine-Budde if (err) \ 141755e5b97fSMarc Kleine-Budde netdev_err(_priv->ndev, \ 1418eb79a267SMarc Kleine-Budde "IRQ handler mcp251xfd_handle_%s() returned %d.\n", \ 141955e5b97fSMarc Kleine-Budde __stringify(irq), err); \ 142055e5b97fSMarc Kleine-Budde err; \ 142155e5b97fSMarc Kleine-Budde }) 142255e5b97fSMarc Kleine-Budde 1423eb79a267SMarc Kleine-Budde static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) 142455e5b97fSMarc Kleine-Budde { 1425eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = dev_id; 142655e5b97fSMarc Kleine-Budde irqreturn_t handled = IRQ_NONE; 142755e5b97fSMarc Kleine-Budde int err; 142855e5b97fSMarc Kleine-Budde 142955e5b97fSMarc Kleine-Budde if (priv->rx_int) 143055e5b97fSMarc Kleine-Budde do { 143155e5b97fSMarc Kleine-Budde int rx_pending; 143255e5b97fSMarc Kleine-Budde 143355e5b97fSMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 143455e5b97fSMarc Kleine-Budde if (!rx_pending) 143555e5b97fSMarc Kleine-Budde break; 143655e5b97fSMarc Kleine-Budde 1437887e359dSMarc Kleine-Budde /* Assume 1st RX-FIFO pending, if other FIFOs 1438887e359dSMarc Kleine-Budde * are pending the main IRQ handler will take 1439887e359dSMarc Kleine-Budde * care. 1440887e359dSMarc Kleine-Budde */ 1441887e359dSMarc Kleine-Budde priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr); 1442eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxif); 144355e5b97fSMarc Kleine-Budde if (err) 144455e5b97fSMarc Kleine-Budde goto out_fail; 144555e5b97fSMarc Kleine-Budde 144655e5b97fSMarc Kleine-Budde handled = IRQ_HANDLED; 1447887e359dSMarc Kleine-Budde 1448887e359dSMarc Kleine-Budde /* We don't know which RX-FIFO is pending, but only 1449887e359dSMarc Kleine-Budde * handle the 1st RX-FIFO. Leave loop here if we have 1450887e359dSMarc Kleine-Budde * more than 1 RX-FIFO to avoid starvation. 1451887e359dSMarc Kleine-Budde */ 1452887e359dSMarc Kleine-Budde } while (priv->rx_ring_num == 1); 145355e5b97fSMarc Kleine-Budde 145455e5b97fSMarc Kleine-Budde do { 145555e5b97fSMarc Kleine-Budde u32 intf_pending, intf_pending_clearable; 1456727fba74SMarc Kleine-Budde bool set_normal_mode = false; 145755e5b97fSMarc Kleine-Budde 1458887e359dSMarc Kleine-Budde err = mcp251xfd_read_regs_status(priv); 145955e5b97fSMarc Kleine-Budde if (err) 146055e5b97fSMarc Kleine-Budde goto out_fail; 146155e5b97fSMarc Kleine-Budde 1462eb79a267SMarc Kleine-Budde intf_pending = FIELD_GET(MCP251XFD_REG_INT_IF_MASK, 146355e5b97fSMarc Kleine-Budde priv->regs_status.intf) & 1464eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_INT_IE_MASK, 146555e5b97fSMarc Kleine-Budde priv->regs_status.intf); 146655e5b97fSMarc Kleine-Budde 1467c757096eSMarc Kleine-Budde if (!(intf_pending)) { 146830bfec4fSMarc Kleine-Budde can_rx_offload_threaded_irq_finish(&priv->offload); 146955e5b97fSMarc Kleine-Budde return handled; 1470c757096eSMarc Kleine-Budde } 147155e5b97fSMarc Kleine-Budde 147255e5b97fSMarc Kleine-Budde /* Some interrupts must be ACKed in the 1473eb79a267SMarc Kleine-Budde * MCP251XFD_REG_INT register. 147455e5b97fSMarc Kleine-Budde * - First ACK then handle, to avoid lost-IRQ race 147555e5b97fSMarc Kleine-Budde * condition on fast re-occurring interrupts. 147655e5b97fSMarc Kleine-Budde * - Write "0" to clear active IRQs, "1" to all other, 147755e5b97fSMarc Kleine-Budde * to avoid r/m/w race condition on the 1478eb79a267SMarc Kleine-Budde * MCP251XFD_REG_INT register. 147955e5b97fSMarc Kleine-Budde */ 148055e5b97fSMarc Kleine-Budde intf_pending_clearable = intf_pending & 1481eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_IF_CLEARABLE_MASK; 148255e5b97fSMarc Kleine-Budde if (intf_pending_clearable) { 148355e5b97fSMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, 1484eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT, 1485eb79a267SMarc Kleine-Budde MCP251XFD_REG_INT_IF_MASK, 148655e5b97fSMarc Kleine-Budde ~intf_pending_clearable); 148755e5b97fSMarc Kleine-Budde if (err) 148855e5b97fSMarc Kleine-Budde goto out_fail; 148955e5b97fSMarc Kleine-Budde } 149055e5b97fSMarc Kleine-Budde 1491eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_MODIF) { 1492eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, modif, &set_normal_mode); 149355e5b97fSMarc Kleine-Budde if (err) 149455e5b97fSMarc Kleine-Budde goto out_fail; 149555e5b97fSMarc Kleine-Budde } 149655e5b97fSMarc Kleine-Budde 1497eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_RXIF) { 1498eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxif); 149955e5b97fSMarc Kleine-Budde if (err) 150055e5b97fSMarc Kleine-Budde goto out_fail; 150155e5b97fSMarc Kleine-Budde } 150255e5b97fSMarc Kleine-Budde 1503eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_TEFIF) { 1504eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, tefif); 150555e5b97fSMarc Kleine-Budde if (err) 150655e5b97fSMarc Kleine-Budde goto out_fail; 150755e5b97fSMarc Kleine-Budde } 150855e5b97fSMarc Kleine-Budde 1509eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_RXOVIF) { 1510eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, rxovif); 151155e5b97fSMarc Kleine-Budde if (err) 151255e5b97fSMarc Kleine-Budde goto out_fail; 151355e5b97fSMarc Kleine-Budde } 151455e5b97fSMarc Kleine-Budde 1515eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_TXATIF) { 1516eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, txatif); 151755e5b97fSMarc Kleine-Budde if (err) 151855e5b97fSMarc Kleine-Budde goto out_fail; 151955e5b97fSMarc Kleine-Budde } 152055e5b97fSMarc Kleine-Budde 1521eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_IVMIF) { 1522eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, ivmif); 152355e5b97fSMarc Kleine-Budde if (err) 152455e5b97fSMarc Kleine-Budde goto out_fail; 152555e5b97fSMarc Kleine-Budde } 152655e5b97fSMarc Kleine-Budde 1527eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_SERRIF) { 1528eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, serrif); 152955e5b97fSMarc Kleine-Budde if (err) 153055e5b97fSMarc Kleine-Budde goto out_fail; 153155e5b97fSMarc Kleine-Budde } 153255e5b97fSMarc Kleine-Budde 1533eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_ECCIF) { 1534eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, eccif, set_normal_mode); 153555e5b97fSMarc Kleine-Budde if (err) 153655e5b97fSMarc Kleine-Budde goto out_fail; 153755e5b97fSMarc Kleine-Budde } 153855e5b97fSMarc Kleine-Budde 1539eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_SPICRCIF) { 1540eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, spicrcif); 154155e5b97fSMarc Kleine-Budde if (err) 154255e5b97fSMarc Kleine-Budde goto out_fail; 154355e5b97fSMarc Kleine-Budde } 154455e5b97fSMarc Kleine-Budde 154555e5b97fSMarc Kleine-Budde /* On the MCP2527FD and MCP2518FD, we don't get a 154655e5b97fSMarc Kleine-Budde * CERRIF IRQ on the transition TX ERROR_WARNING -> TX 154755e5b97fSMarc Kleine-Budde * ERROR_ACTIVE. 154855e5b97fSMarc Kleine-Budde */ 1549eb79a267SMarc Kleine-Budde if (intf_pending & MCP251XFD_REG_INT_CERRIF || 155055e5b97fSMarc Kleine-Budde priv->can.state > CAN_STATE_ERROR_ACTIVE) { 1551eb79a267SMarc Kleine-Budde err = mcp251xfd_handle(priv, cerrif); 155255e5b97fSMarc Kleine-Budde if (err) 155355e5b97fSMarc Kleine-Budde goto out_fail; 155455e5b97fSMarc Kleine-Budde 155555e5b97fSMarc Kleine-Budde /* In Bus Off we completely shut down the 155655e5b97fSMarc Kleine-Budde * controller. Every subsequent register read 155755e5b97fSMarc Kleine-Budde * will read bogus data, and if 1558eb79a267SMarc Kleine-Budde * MCP251XFD_QUIRK_CRC_REG is enabled the CRC 155955e5b97fSMarc Kleine-Budde * check will fail, too. So leave IRQ handler 156055e5b97fSMarc Kleine-Budde * directly. 156155e5b97fSMarc Kleine-Budde */ 1562691204bdSMarc Kleine-Budde if (priv->can.state == CAN_STATE_BUS_OFF) { 1563691204bdSMarc Kleine-Budde can_rx_offload_threaded_irq_finish(&priv->offload); 156455e5b97fSMarc Kleine-Budde return IRQ_HANDLED; 156555e5b97fSMarc Kleine-Budde } 1566691204bdSMarc Kleine-Budde } 156755e5b97fSMarc Kleine-Budde 156855e5b97fSMarc Kleine-Budde handled = IRQ_HANDLED; 156955e5b97fSMarc Kleine-Budde } while (1); 157055e5b97fSMarc Kleine-Budde 157155e5b97fSMarc Kleine-Budde out_fail: 157230bfec4fSMarc Kleine-Budde can_rx_offload_threaded_irq_finish(&priv->offload); 1573c757096eSMarc Kleine-Budde 157455e5b97fSMarc Kleine-Budde netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n", 157555e5b97fSMarc Kleine-Budde err, priv->regs_status.intf); 1576e0ab3dd5SMarc Kleine-Budde mcp251xfd_dump(priv); 1577eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 1578ef68a717SMarc Kleine-Budde mcp251xfd_timestamp_stop(priv); 157955e5b97fSMarc Kleine-Budde 158055e5b97fSMarc Kleine-Budde return handled; 158155e5b97fSMarc Kleine-Budde } 158255e5b97fSMarc Kleine-Budde 1583eb79a267SMarc Kleine-Budde static int mcp251xfd_open(struct net_device *ndev) 158455e5b97fSMarc Kleine-Budde { 1585eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 158655e5b97fSMarc Kleine-Budde const struct spi_device *spi = priv->spi; 158755e5b97fSMarc Kleine-Budde int err; 158855e5b97fSMarc Kleine-Budde 1589e91aae8eSMarc Kleine-Budde err = open_candev(ndev); 1590e91aae8eSMarc Kleine-Budde if (err) 1591e91aae8eSMarc Kleine-Budde return err; 1592e91aae8eSMarc Kleine-Budde 1593d84ca221SMarc Kleine-Budde err = pm_runtime_resume_and_get(ndev->dev.parent); 1594d84ca221SMarc Kleine-Budde if (err) 1595e91aae8eSMarc Kleine-Budde goto out_close_candev; 159655e5b97fSMarc Kleine-Budde 1597eb79a267SMarc Kleine-Budde err = mcp251xfd_ring_alloc(priv); 159855e5b97fSMarc Kleine-Budde if (err) 1599e91aae8eSMarc Kleine-Budde goto out_pm_runtime_put; 160055e5b97fSMarc Kleine-Budde 1601eb79a267SMarc Kleine-Budde err = mcp251xfd_transceiver_enable(priv); 160255e5b97fSMarc Kleine-Budde if (err) 1603eb79a267SMarc Kleine-Budde goto out_mcp251xfd_ring_free; 160455e5b97fSMarc Kleine-Budde 1605eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_start(priv); 160655e5b97fSMarc Kleine-Budde if (err) 160755e5b97fSMarc Kleine-Budde goto out_transceiver_disable; 160855e5b97fSMarc Kleine-Budde 1609efd8d98dSMarc Kleine-Budde mcp251xfd_timestamp_init(priv); 161060a848c5SMarc Kleine-Budde clear_bit(MCP251XFD_FLAGS_DOWN, priv->flags); 161155e5b97fSMarc Kleine-Budde can_rx_offload_enable(&priv->offload); 161255e5b97fSMarc Kleine-Budde 1613eb79a267SMarc Kleine-Budde err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq, 1614cb6adfe2SMarc Kleine-Budde IRQF_SHARED | IRQF_ONESHOT, 1615cb6adfe2SMarc Kleine-Budde dev_name(&spi->dev), priv); 161655e5b97fSMarc Kleine-Budde if (err) 161755e5b97fSMarc Kleine-Budde goto out_can_rx_offload_disable; 161855e5b97fSMarc Kleine-Budde 1619eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_interrupts_enable(priv); 162055e5b97fSMarc Kleine-Budde if (err) 162155e5b97fSMarc Kleine-Budde goto out_free_irq; 162255e5b97fSMarc Kleine-Budde 162355e5b97fSMarc Kleine-Budde netif_start_queue(ndev); 162455e5b97fSMarc Kleine-Budde 162555e5b97fSMarc Kleine-Budde return 0; 162655e5b97fSMarc Kleine-Budde 162755e5b97fSMarc Kleine-Budde out_free_irq: 162855e5b97fSMarc Kleine-Budde free_irq(spi->irq, priv); 162955e5b97fSMarc Kleine-Budde out_can_rx_offload_disable: 163055e5b97fSMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 163160a848c5SMarc Kleine-Budde set_bit(MCP251XFD_FLAGS_DOWN, priv->flags); 1632efd8d98dSMarc Kleine-Budde mcp251xfd_timestamp_stop(priv); 163355e5b97fSMarc Kleine-Budde out_transceiver_disable: 1634eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(priv); 1635eb79a267SMarc Kleine-Budde out_mcp251xfd_ring_free: 1636eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 163755e5b97fSMarc Kleine-Budde out_pm_runtime_put: 1638eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 163955e5b97fSMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 1640e91aae8eSMarc Kleine-Budde out_close_candev: 1641e91aae8eSMarc Kleine-Budde close_candev(ndev); 164255e5b97fSMarc Kleine-Budde 164355e5b97fSMarc Kleine-Budde return err; 164455e5b97fSMarc Kleine-Budde } 164555e5b97fSMarc Kleine-Budde 1646eb79a267SMarc Kleine-Budde static int mcp251xfd_stop(struct net_device *ndev) 164755e5b97fSMarc Kleine-Budde { 1648eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = netdev_priv(ndev); 164955e5b97fSMarc Kleine-Budde 165055e5b97fSMarc Kleine-Budde netif_stop_queue(ndev); 165160a848c5SMarc Kleine-Budde set_bit(MCP251XFD_FLAGS_DOWN, priv->flags); 165260a848c5SMarc Kleine-Budde hrtimer_cancel(&priv->rx_irq_timer); 1653eb79a267SMarc Kleine-Budde mcp251xfd_chip_interrupts_disable(priv); 165455e5b97fSMarc Kleine-Budde free_irq(ndev->irq, priv); 165555e5b97fSMarc Kleine-Budde can_rx_offload_disable(&priv->offload); 1656efd8d98dSMarc Kleine-Budde mcp251xfd_timestamp_stop(priv); 1657eb79a267SMarc Kleine-Budde mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED); 1658eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(priv); 1659eb79a267SMarc Kleine-Budde mcp251xfd_ring_free(priv); 166055e5b97fSMarc Kleine-Budde close_candev(ndev); 166155e5b97fSMarc Kleine-Budde 166255e5b97fSMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 166355e5b97fSMarc Kleine-Budde 166455e5b97fSMarc Kleine-Budde return 0; 166555e5b97fSMarc Kleine-Budde } 166655e5b97fSMarc Kleine-Budde 1667eb79a267SMarc Kleine-Budde static const struct net_device_ops mcp251xfd_netdev_ops = { 1668eb79a267SMarc Kleine-Budde .ndo_open = mcp251xfd_open, 1669eb79a267SMarc Kleine-Budde .ndo_stop = mcp251xfd_stop, 1670eb79a267SMarc Kleine-Budde .ndo_start_xmit = mcp251xfd_start_xmit, 167155e5b97fSMarc Kleine-Budde .ndo_change_mtu = can_change_mtu, 167255e5b97fSMarc Kleine-Budde }; 167355e5b97fSMarc Kleine-Budde 167455e5b97fSMarc Kleine-Budde static void 1675eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(struct mcp251xfd_priv *priv) 167655e5b97fSMarc Kleine-Budde { 167755e5b97fSMarc Kleine-Budde const struct spi_device *spi = priv->spi; 167855e5b97fSMarc Kleine-Budde const struct spi_controller *ctlr = spi->controller; 167955e5b97fSMarc Kleine-Budde 168055e5b97fSMarc Kleine-Budde if (ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX) 1681eb79a267SMarc Kleine-Budde priv->devtype_data.quirks |= MCP251XFD_QUIRK_HALF_DUPLEX; 168255e5b97fSMarc Kleine-Budde } 168355e5b97fSMarc Kleine-Budde 1684eb79a267SMarc Kleine-Budde static int mcp251xfd_register_chip_detect(struct mcp251xfd_priv *priv) 168555e5b97fSMarc Kleine-Budde { 168655e5b97fSMarc Kleine-Budde const struct net_device *ndev = priv->ndev; 1687eb79a267SMarc Kleine-Budde const struct mcp251xfd_devtype_data *devtype_data; 168855e5b97fSMarc Kleine-Budde u32 osc; 168955e5b97fSMarc Kleine-Budde int err; 169055e5b97fSMarc Kleine-Budde 169155e5b97fSMarc Kleine-Budde /* The OSC_LPMEN is only supported on MCP2518FD, so use it to 169255e5b97fSMarc Kleine-Budde * autodetect the model. 169355e5b97fSMarc Kleine-Budde */ 1694eb79a267SMarc Kleine-Budde err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_OSC, 1695eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_LPMEN, 1696eb79a267SMarc Kleine-Budde MCP251XFD_REG_OSC_LPMEN); 169755e5b97fSMarc Kleine-Budde if (err) 169855e5b97fSMarc Kleine-Budde return err; 169955e5b97fSMarc Kleine-Budde 1700eb79a267SMarc Kleine-Budde err = regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc); 170155e5b97fSMarc Kleine-Budde if (err) 170255e5b97fSMarc Kleine-Budde return err; 170355e5b97fSMarc Kleine-Budde 1704eb79a267SMarc Kleine-Budde if (osc & MCP251XFD_REG_OSC_LPMEN) 1705eb79a267SMarc Kleine-Budde devtype_data = &mcp251xfd_devtype_data_mcp2518fd; 170655e5b97fSMarc Kleine-Budde else 1707eb79a267SMarc Kleine-Budde devtype_data = &mcp251xfd_devtype_data_mcp2517fd; 170855e5b97fSMarc Kleine-Budde 1709c6f2a617SMarc Kleine-Budde if (!mcp251xfd_is_251XFD(priv) && 171055e5b97fSMarc Kleine-Budde priv->devtype_data.model != devtype_data->model) { 171155e5b97fSMarc Kleine-Budde netdev_info(ndev, 17123bd9d8ceSMarc Kleine-Budde "Detected %s, but firmware specifies a %s. Fixing up.\n", 1713eb79a267SMarc Kleine-Budde __mcp251xfd_get_model_str(devtype_data->model), 1714eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv)); 171555e5b97fSMarc Kleine-Budde } 171655e5b97fSMarc Kleine-Budde priv->devtype_data = *devtype_data; 171755e5b97fSMarc Kleine-Budde 171855e5b97fSMarc Kleine-Budde /* We need to preserve the Half Duplex Quirk. */ 1719eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(priv); 172055e5b97fSMarc Kleine-Budde 172155e5b97fSMarc Kleine-Budde /* Re-init regmap with quirks of detected model. */ 1722eb79a267SMarc Kleine-Budde return mcp251xfd_regmap_init(priv); 172355e5b97fSMarc Kleine-Budde } 172455e5b97fSMarc Kleine-Budde 1725eb79a267SMarc Kleine-Budde static int mcp251xfd_register_check_rx_int(struct mcp251xfd_priv *priv) 172655e5b97fSMarc Kleine-Budde { 172755e5b97fSMarc Kleine-Budde int err, rx_pending; 172855e5b97fSMarc Kleine-Budde 172955e5b97fSMarc Kleine-Budde if (!priv->rx_int) 173055e5b97fSMarc Kleine-Budde return 0; 173155e5b97fSMarc Kleine-Budde 1732eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_enable(priv); 173355e5b97fSMarc Kleine-Budde if (err) 173455e5b97fSMarc Kleine-Budde return err; 173555e5b97fSMarc Kleine-Budde 173655e5b97fSMarc Kleine-Budde /* Check if RX_INT is properly working. The RX_INT should not 173755e5b97fSMarc Kleine-Budde * be active after a softreset. 173855e5b97fSMarc Kleine-Budde */ 173955e5b97fSMarc Kleine-Budde rx_pending = gpiod_get_value_cansleep(priv->rx_int); 174055e5b97fSMarc Kleine-Budde 1741eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_rx_int_disable(priv); 174255e5b97fSMarc Kleine-Budde if (err) 174355e5b97fSMarc Kleine-Budde return err; 174455e5b97fSMarc Kleine-Budde 174555e5b97fSMarc Kleine-Budde if (!rx_pending) 174655e5b97fSMarc Kleine-Budde return 0; 174755e5b97fSMarc Kleine-Budde 174855e5b97fSMarc Kleine-Budde netdev_info(priv->ndev, 17493bd9d8ceSMarc Kleine-Budde "RX_INT active after softreset, disabling RX_INT support.\n"); 175055e5b97fSMarc Kleine-Budde devm_gpiod_put(&priv->spi->dev, priv->rx_int); 175155e5b97fSMarc Kleine-Budde priv->rx_int = NULL; 175255e5b97fSMarc Kleine-Budde 175355e5b97fSMarc Kleine-Budde return 0; 175455e5b97fSMarc Kleine-Budde } 175555e5b97fSMarc Kleine-Budde 175655e5b97fSMarc Kleine-Budde static int 17572a68dd86SMarc Kleine-Budde mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv, u32 *dev_id, 17582a68dd86SMarc Kleine-Budde u32 *effective_speed_hz_slow, 17592a68dd86SMarc Kleine-Budde u32 *effective_speed_hz_fast) 176055e5b97fSMarc Kleine-Budde { 1761eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_rx; 1762eb79a267SMarc Kleine-Budde struct mcp251xfd_map_buf_nocrc *buf_tx; 176355e5b97fSMarc Kleine-Budde struct spi_transfer xfer[2] = { }; 176455e5b97fSMarc Kleine-Budde int err; 176555e5b97fSMarc Kleine-Budde 176655e5b97fSMarc Kleine-Budde buf_rx = kzalloc(sizeof(*buf_rx), GFP_KERNEL); 176755e5b97fSMarc Kleine-Budde if (!buf_rx) 176855e5b97fSMarc Kleine-Budde return -ENOMEM; 176955e5b97fSMarc Kleine-Budde 177055e5b97fSMarc Kleine-Budde buf_tx = kzalloc(sizeof(*buf_tx), GFP_KERNEL); 177155e5b97fSMarc Kleine-Budde if (!buf_tx) { 177255e5b97fSMarc Kleine-Budde err = -ENOMEM; 177355e5b97fSMarc Kleine-Budde goto out_kfree_buf_rx; 177455e5b97fSMarc Kleine-Budde } 177555e5b97fSMarc Kleine-Budde 177655e5b97fSMarc Kleine-Budde xfer[0].tx_buf = buf_tx; 177755e5b97fSMarc Kleine-Budde xfer[0].len = sizeof(buf_tx->cmd); 17782a68dd86SMarc Kleine-Budde xfer[0].speed_hz = priv->spi_max_speed_hz_slow; 177955e5b97fSMarc Kleine-Budde xfer[1].rx_buf = buf_rx->data; 178055e5b97fSMarc Kleine-Budde xfer[1].len = sizeof(dev_id); 17812a68dd86SMarc Kleine-Budde xfer[1].speed_hz = priv->spi_max_speed_hz_fast; 178255e5b97fSMarc Kleine-Budde 1783eb79a267SMarc Kleine-Budde mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, MCP251XFD_REG_DEVID); 17842a68dd86SMarc Kleine-Budde 178555e5b97fSMarc Kleine-Budde err = spi_sync_transfer(priv->spi, xfer, ARRAY_SIZE(xfer)); 178655e5b97fSMarc Kleine-Budde if (err) 178755e5b97fSMarc Kleine-Budde goto out_kfree_buf_tx; 178855e5b97fSMarc Kleine-Budde 178955e5b97fSMarc Kleine-Budde *dev_id = be32_to_cpup((__be32 *)buf_rx->data); 17902a68dd86SMarc Kleine-Budde *effective_speed_hz_slow = xfer[0].effective_speed_hz; 17912a68dd86SMarc Kleine-Budde *effective_speed_hz_fast = xfer[1].effective_speed_hz; 179255e5b97fSMarc Kleine-Budde 179355e5b97fSMarc Kleine-Budde out_kfree_buf_tx: 179455e5b97fSMarc Kleine-Budde kfree(buf_tx); 179555e5b97fSMarc Kleine-Budde out_kfree_buf_rx: 179655e5b97fSMarc Kleine-Budde kfree(buf_rx); 179755e5b97fSMarc Kleine-Budde 1798fa7b514dSTom Rix return err; 179955e5b97fSMarc Kleine-Budde } 180055e5b97fSMarc Kleine-Budde 1801eb79a267SMarc Kleine-Budde #define MCP251XFD_QUIRK_ACTIVE(quirk) \ 1802eb79a267SMarc Kleine-Budde (priv->devtype_data.quirks & MCP251XFD_QUIRK_##quirk ? '+' : '-') 180355e5b97fSMarc Kleine-Budde 180455e5b97fSMarc Kleine-Budde static int 1805eb79a267SMarc Kleine-Budde mcp251xfd_register_done(const struct mcp251xfd_priv *priv) 180655e5b97fSMarc Kleine-Budde { 18072a68dd86SMarc Kleine-Budde u32 dev_id, effective_speed_hz_slow, effective_speed_hz_fast; 18082a68dd86SMarc Kleine-Budde unsigned long clk_rate; 180955e5b97fSMarc Kleine-Budde int err; 181055e5b97fSMarc Kleine-Budde 1811eb79a267SMarc Kleine-Budde err = mcp251xfd_register_get_dev_id(priv, &dev_id, 18122a68dd86SMarc Kleine-Budde &effective_speed_hz_slow, 18132a68dd86SMarc Kleine-Budde &effective_speed_hz_fast); 181455e5b97fSMarc Kleine-Budde if (err) 181555e5b97fSMarc Kleine-Budde return err; 181655e5b97fSMarc Kleine-Budde 18172a68dd86SMarc Kleine-Budde clk_rate = clk_get_rate(priv->clk); 18182a68dd86SMarc Kleine-Budde 181955e5b97fSMarc Kleine-Budde netdev_info(priv->ndev, 18202a68dd86SMarc Kleine-Budde "%s rev%lu.%lu (%cRX_INT %cPLL %cMAB_NO_WARN %cCRC_REG %cCRC_RX %cCRC_TX %cECC %cHD o:%lu.%02luMHz c:%u.%02uMHz m:%u.%02uMHz rs:%u.%02uMHz es:%u.%02uMHz rf:%u.%02uMHz ef:%u.%02uMHz) successfully initialized.\n", 1821eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(priv), 1822eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_DEVID_ID_MASK, dev_id), 1823eb79a267SMarc Kleine-Budde FIELD_GET(MCP251XFD_REG_DEVID_REV_MASK, dev_id), 182455e5b97fSMarc Kleine-Budde priv->rx_int ? '+' : '-', 18252a68dd86SMarc Kleine-Budde priv->pll_enable ? '+' : '-', 1826eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(MAB_NO_WARN), 1827eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_REG), 1828eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_RX), 1829eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(CRC_TX), 1830eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(ECC), 1831eb79a267SMarc Kleine-Budde MCP251XFD_QUIRK_ACTIVE(HALF_DUPLEX), 18322a68dd86SMarc Kleine-Budde clk_rate / 1000000, 18332a68dd86SMarc Kleine-Budde clk_rate % 1000000 / 1000 / 10, 183455e5b97fSMarc Kleine-Budde priv->can.clock.freq / 1000000, 183555e5b97fSMarc Kleine-Budde priv->can.clock.freq % 1000000 / 1000 / 10, 183655e5b97fSMarc Kleine-Budde priv->spi_max_speed_hz_orig / 1000000, 183755e5b97fSMarc Kleine-Budde priv->spi_max_speed_hz_orig % 1000000 / 1000 / 10, 18382a68dd86SMarc Kleine-Budde priv->spi_max_speed_hz_slow / 1000000, 18392a68dd86SMarc Kleine-Budde priv->spi_max_speed_hz_slow % 1000000 / 1000 / 10, 18402a68dd86SMarc Kleine-Budde effective_speed_hz_slow / 1000000, 18412a68dd86SMarc Kleine-Budde effective_speed_hz_slow % 1000000 / 1000 / 10, 18422a68dd86SMarc Kleine-Budde priv->spi_max_speed_hz_fast / 1000000, 18432a68dd86SMarc Kleine-Budde priv->spi_max_speed_hz_fast % 1000000 / 1000 / 10, 18442a68dd86SMarc Kleine-Budde effective_speed_hz_fast / 1000000, 18452a68dd86SMarc Kleine-Budde effective_speed_hz_fast % 1000000 / 1000 / 10); 184655e5b97fSMarc Kleine-Budde 184755e5b97fSMarc Kleine-Budde return 0; 184855e5b97fSMarc Kleine-Budde } 184955e5b97fSMarc Kleine-Budde 1850eb79a267SMarc Kleine-Budde static int mcp251xfd_register(struct mcp251xfd_priv *priv) 185155e5b97fSMarc Kleine-Budde { 185255e5b97fSMarc Kleine-Budde struct net_device *ndev = priv->ndev; 185355e5b97fSMarc Kleine-Budde int err; 185455e5b97fSMarc Kleine-Budde 1855eb79a267SMarc Kleine-Budde err = mcp251xfd_clks_and_vdd_enable(priv); 185655e5b97fSMarc Kleine-Budde if (err) 185755e5b97fSMarc Kleine-Budde return err; 185855e5b97fSMarc Kleine-Budde 185955e5b97fSMarc Kleine-Budde pm_runtime_get_noresume(ndev->dev.parent); 186055e5b97fSMarc Kleine-Budde err = pm_runtime_set_active(ndev->dev.parent); 186155e5b97fSMarc Kleine-Budde if (err) 186255e5b97fSMarc Kleine-Budde goto out_runtime_put_noidle; 186355e5b97fSMarc Kleine-Budde pm_runtime_enable(ndev->dev.parent); 186455e5b97fSMarc Kleine-Budde 1865eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(priv); 186655e5b97fSMarc Kleine-Budde 1867eb79a267SMarc Kleine-Budde err = mcp251xfd_chip_softreset(priv); 186855e5b97fSMarc Kleine-Budde if (err == -ENODEV) 186955e5b97fSMarc Kleine-Budde goto out_runtime_disable; 187055e5b97fSMarc Kleine-Budde if (err) 18711ba3690fSMarc Kleine-Budde goto out_chip_sleep; 187255e5b97fSMarc Kleine-Budde 1873445dd72aSMarc Kleine-Budde err = mcp251xfd_chip_clock_init(priv); 1874445dd72aSMarc Kleine-Budde if (err == -ENODEV) 1875445dd72aSMarc Kleine-Budde goto out_runtime_disable; 1876445dd72aSMarc Kleine-Budde if (err) 1877445dd72aSMarc Kleine-Budde goto out_chip_sleep; 1878445dd72aSMarc Kleine-Budde 1879eb79a267SMarc Kleine-Budde err = mcp251xfd_register_chip_detect(priv); 188055e5b97fSMarc Kleine-Budde if (err) 18811ba3690fSMarc Kleine-Budde goto out_chip_sleep; 188255e5b97fSMarc Kleine-Budde 1883eb79a267SMarc Kleine-Budde err = mcp251xfd_register_check_rx_int(priv); 188455e5b97fSMarc Kleine-Budde if (err) 18851ba3690fSMarc Kleine-Budde goto out_chip_sleep; 188655e5b97fSMarc Kleine-Budde 1887d86ba8dbSMarc Kleine-Budde mcp251xfd_ethtool_init(priv); 1888d86ba8dbSMarc Kleine-Budde 188955e5b97fSMarc Kleine-Budde err = register_candev(ndev); 189055e5b97fSMarc Kleine-Budde if (err) 18911ba3690fSMarc Kleine-Budde goto out_chip_sleep; 189255e5b97fSMarc Kleine-Budde 1893eb79a267SMarc Kleine-Budde err = mcp251xfd_register_done(priv); 189455e5b97fSMarc Kleine-Budde if (err) 189555e5b97fSMarc Kleine-Budde goto out_unregister_candev; 189655e5b97fSMarc Kleine-Budde 189755e5b97fSMarc Kleine-Budde /* Put controller into sleep mode and let pm_runtime_put() 189855e5b97fSMarc Kleine-Budde * disable the clocks and vdd. If CONFIG_PM is not enabled, 189955e5b97fSMarc Kleine-Budde * the clocks and vdd will stay powered. 190055e5b97fSMarc Kleine-Budde */ 19011ba3690fSMarc Kleine-Budde err = mcp251xfd_chip_sleep(priv); 190255e5b97fSMarc Kleine-Budde if (err) 190355e5b97fSMarc Kleine-Budde goto out_unregister_candev; 190455e5b97fSMarc Kleine-Budde 190555e5b97fSMarc Kleine-Budde pm_runtime_put(ndev->dev.parent); 190655e5b97fSMarc Kleine-Budde 190755e5b97fSMarc Kleine-Budde return 0; 190855e5b97fSMarc Kleine-Budde 190955e5b97fSMarc Kleine-Budde out_unregister_candev: 191055e5b97fSMarc Kleine-Budde unregister_candev(ndev); 19111ba3690fSMarc Kleine-Budde out_chip_sleep: 19121ba3690fSMarc Kleine-Budde mcp251xfd_chip_sleep(priv); 191355e5b97fSMarc Kleine-Budde out_runtime_disable: 191455e5b97fSMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 191555e5b97fSMarc Kleine-Budde out_runtime_put_noidle: 191655e5b97fSMarc Kleine-Budde pm_runtime_put_noidle(ndev->dev.parent); 1917eb79a267SMarc Kleine-Budde mcp251xfd_clks_and_vdd_disable(priv); 191855e5b97fSMarc Kleine-Budde 191955e5b97fSMarc Kleine-Budde return err; 192055e5b97fSMarc Kleine-Budde } 192155e5b97fSMarc Kleine-Budde 1922eb79a267SMarc Kleine-Budde static inline void mcp251xfd_unregister(struct mcp251xfd_priv *priv) 192355e5b97fSMarc Kleine-Budde { 192455e5b97fSMarc Kleine-Budde struct net_device *ndev = priv->ndev; 192555e5b97fSMarc Kleine-Budde 192655e5b97fSMarc Kleine-Budde unregister_candev(ndev); 192755e5b97fSMarc Kleine-Budde 192872362dcdSMarc Kleine-Budde if (pm_runtime_enabled(ndev->dev.parent)) 192955e5b97fSMarc Kleine-Budde pm_runtime_disable(ndev->dev.parent); 193072362dcdSMarc Kleine-Budde else 193172362dcdSMarc Kleine-Budde mcp251xfd_clks_and_vdd_disable(priv); 193255e5b97fSMarc Kleine-Budde } 193355e5b97fSMarc Kleine-Budde 1934eb79a267SMarc Kleine-Budde static const struct of_device_id mcp251xfd_of_match[] = { 193555e5b97fSMarc Kleine-Budde { 193655e5b97fSMarc Kleine-Budde .compatible = "microchip,mcp2517fd", 1937eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp2517fd, 193855e5b97fSMarc Kleine-Budde }, { 193955e5b97fSMarc Kleine-Budde .compatible = "microchip,mcp2518fd", 1940eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp2518fd, 194155e5b97fSMarc Kleine-Budde }, { 1942c6f2a617SMarc Kleine-Budde .compatible = "microchip,mcp251863", 1943c6f2a617SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp251863, 1944c6f2a617SMarc Kleine-Budde }, { 1945dba1572cSThomas Kopp .compatible = "microchip,mcp251xfd", 1946eb79a267SMarc Kleine-Budde .data = &mcp251xfd_devtype_data_mcp251xfd, 194755e5b97fSMarc Kleine-Budde }, { 194855e5b97fSMarc Kleine-Budde /* sentinel */ 194955e5b97fSMarc Kleine-Budde }, 195055e5b97fSMarc Kleine-Budde }; 1951eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(of, mcp251xfd_of_match); 195255e5b97fSMarc Kleine-Budde 1953eb79a267SMarc Kleine-Budde static const struct spi_device_id mcp251xfd_id_table[] = { 195455e5b97fSMarc Kleine-Budde { 195555e5b97fSMarc Kleine-Budde .name = "mcp2517fd", 1956eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2517fd, 195755e5b97fSMarc Kleine-Budde }, { 195855e5b97fSMarc Kleine-Budde .name = "mcp2518fd", 1959eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2518fd, 196055e5b97fSMarc Kleine-Budde }, { 1961c6f2a617SMarc Kleine-Budde .name = "mcp251863", 1962c6f2a617SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp251863, 1963c6f2a617SMarc Kleine-Budde }, { 1964dba1572cSThomas Kopp .name = "mcp251xfd", 1965eb79a267SMarc Kleine-Budde .driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp251xfd, 196655e5b97fSMarc Kleine-Budde }, { 196755e5b97fSMarc Kleine-Budde /* sentinel */ 196855e5b97fSMarc Kleine-Budde }, 196955e5b97fSMarc Kleine-Budde }; 1970eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(spi, mcp251xfd_id_table); 197155e5b97fSMarc Kleine-Budde 1972eb79a267SMarc Kleine-Budde static int mcp251xfd_probe(struct spi_device *spi) 197355e5b97fSMarc Kleine-Budde { 197455e5b97fSMarc Kleine-Budde const void *match; 197555e5b97fSMarc Kleine-Budde struct net_device *ndev; 1976eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv; 197755e5b97fSMarc Kleine-Budde struct gpio_desc *rx_int; 197855e5b97fSMarc Kleine-Budde struct regulator *reg_vdd, *reg_xceiver; 197955e5b97fSMarc Kleine-Budde struct clk *clk; 19802a68dd86SMarc Kleine-Budde bool pll_enable = false; 198174f89cf1SAndy Shevchenko u32 freq = 0; 198255e5b97fSMarc Kleine-Budde int err; 198355e5b97fSMarc Kleine-Budde 19841a1c436bSMarc Kleine-Budde if (!spi->irq) 19851a1c436bSMarc Kleine-Budde return dev_err_probe(&spi->dev, -ENXIO, 19861a1c436bSMarc Kleine-Budde "No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n"); 19871a1c436bSMarc Kleine-Budde 198855e5b97fSMarc Kleine-Budde rx_int = devm_gpiod_get_optional(&spi->dev, "microchip,rx-int", 198955e5b97fSMarc Kleine-Budde GPIOD_IN); 1990cf8ee6deSMarc Kleine-Budde if (IS_ERR(rx_int)) 1991cf8ee6deSMarc Kleine-Budde return dev_err_probe(&spi->dev, PTR_ERR(rx_int), 1992cf8ee6deSMarc Kleine-Budde "Failed to get RX-INT!\n"); 199355e5b97fSMarc Kleine-Budde 199455e5b97fSMarc Kleine-Budde reg_vdd = devm_regulator_get_optional(&spi->dev, "vdd"); 1995cf8ee6deSMarc Kleine-Budde if (PTR_ERR(reg_vdd) == -ENODEV) 199655e5b97fSMarc Kleine-Budde reg_vdd = NULL; 199755e5b97fSMarc Kleine-Budde else if (IS_ERR(reg_vdd)) 1998cf8ee6deSMarc Kleine-Budde return dev_err_probe(&spi->dev, PTR_ERR(reg_vdd), 1999cf8ee6deSMarc Kleine-Budde "Failed to get VDD regulator!\n"); 200055e5b97fSMarc Kleine-Budde 200155e5b97fSMarc Kleine-Budde reg_xceiver = devm_regulator_get_optional(&spi->dev, "xceiver"); 2002cf8ee6deSMarc Kleine-Budde if (PTR_ERR(reg_xceiver) == -ENODEV) 200355e5b97fSMarc Kleine-Budde reg_xceiver = NULL; 200455e5b97fSMarc Kleine-Budde else if (IS_ERR(reg_xceiver)) 2005cf8ee6deSMarc Kleine-Budde return dev_err_probe(&spi->dev, PTR_ERR(reg_xceiver), 2006cf8ee6deSMarc Kleine-Budde "Failed to get Transceiver regulator!\n"); 200755e5b97fSMarc Kleine-Budde 200874f89cf1SAndy Shevchenko clk = devm_clk_get_optional(&spi->dev, NULL); 2009cf8ee6deSMarc Kleine-Budde if (IS_ERR(clk)) 20104cc7faa4SDan Carpenter return dev_err_probe(&spi->dev, PTR_ERR(clk), 2011cf8ee6deSMarc Kleine-Budde "Failed to get Oscillator (clock)!\n"); 201274f89cf1SAndy Shevchenko if (clk) { 201355e5b97fSMarc Kleine-Budde freq = clk_get_rate(clk); 201474f89cf1SAndy Shevchenko } else { 201574f89cf1SAndy Shevchenko err = device_property_read_u32(&spi->dev, "clock-frequency", 201674f89cf1SAndy Shevchenko &freq); 201774f89cf1SAndy Shevchenko if (err) 201874f89cf1SAndy Shevchenko return dev_err_probe(&spi->dev, err, 201974f89cf1SAndy Shevchenko "Failed to get clock-frequency!\n"); 202074f89cf1SAndy Shevchenko } 202155e5b97fSMarc Kleine-Budde 202255e5b97fSMarc Kleine-Budde /* Sanity check */ 2023eb79a267SMarc Kleine-Budde if (freq < MCP251XFD_SYSCLOCK_HZ_MIN || 2024eb79a267SMarc Kleine-Budde freq > MCP251XFD_SYSCLOCK_HZ_MAX) { 202555e5b97fSMarc Kleine-Budde dev_err(&spi->dev, 202655e5b97fSMarc Kleine-Budde "Oscillator frequency (%u Hz) is too low or high.\n", 202755e5b97fSMarc Kleine-Budde freq); 202855e5b97fSMarc Kleine-Budde return -ERANGE; 202955e5b97fSMarc Kleine-Budde } 203055e5b97fSMarc Kleine-Budde 20312a68dd86SMarc Kleine-Budde if (freq <= MCP251XFD_SYSCLOCK_HZ_MAX / MCP251XFD_OSC_PLL_MULTIPLIER) 20322a68dd86SMarc Kleine-Budde pll_enable = true; 203355e5b97fSMarc Kleine-Budde 2034eb79a267SMarc Kleine-Budde ndev = alloc_candev(sizeof(struct mcp251xfd_priv), 2035eb79a267SMarc Kleine-Budde MCP251XFD_TX_OBJ_NUM_MAX); 203655e5b97fSMarc Kleine-Budde if (!ndev) 203755e5b97fSMarc Kleine-Budde return -ENOMEM; 203855e5b97fSMarc Kleine-Budde 203955e5b97fSMarc Kleine-Budde SET_NETDEV_DEV(ndev, &spi->dev); 204055e5b97fSMarc Kleine-Budde 2041eb79a267SMarc Kleine-Budde ndev->netdev_ops = &mcp251xfd_netdev_ops; 204255e5b97fSMarc Kleine-Budde ndev->irq = spi->irq; 204355e5b97fSMarc Kleine-Budde ndev->flags |= IFF_ECHO; 204455e5b97fSMarc Kleine-Budde 204555e5b97fSMarc Kleine-Budde priv = netdev_priv(ndev); 204655e5b97fSMarc Kleine-Budde spi_set_drvdata(spi, priv); 204755e5b97fSMarc Kleine-Budde priv->can.clock.freq = freq; 20482a68dd86SMarc Kleine-Budde if (pll_enable) 20492a68dd86SMarc Kleine-Budde priv->can.clock.freq *= MCP251XFD_OSC_PLL_MULTIPLIER; 2050eb79a267SMarc Kleine-Budde priv->can.do_set_mode = mcp251xfd_set_mode; 2051eb79a267SMarc Kleine-Budde priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter; 2052eb79a267SMarc Kleine-Budde priv->can.bittiming_const = &mcp251xfd_bittiming_const; 2053eb79a267SMarc Kleine-Budde priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const; 2054ee42bedcSManivannan Sadhasivam priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | 2055ee42bedcSManivannan Sadhasivam CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING | 205686f1e3b1SMarc Kleine-Budde CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO | 205786f1e3b1SMarc Kleine-Budde CAN_CTRLMODE_CC_LEN8_DLC; 205860a848c5SMarc Kleine-Budde set_bit(MCP251XFD_FLAGS_DOWN, priv->flags); 205955e5b97fSMarc Kleine-Budde priv->ndev = ndev; 206055e5b97fSMarc Kleine-Budde priv->spi = spi; 206155e5b97fSMarc Kleine-Budde priv->rx_int = rx_int; 206255e5b97fSMarc Kleine-Budde priv->clk = clk; 20632a68dd86SMarc Kleine-Budde priv->pll_enable = pll_enable; 206455e5b97fSMarc Kleine-Budde priv->reg_vdd = reg_vdd; 206555e5b97fSMarc Kleine-Budde priv->reg_xceiver = reg_xceiver; 206655e5b97fSMarc Kleine-Budde 206755e5b97fSMarc Kleine-Budde match = device_get_match_data(&spi->dev); 206855e5b97fSMarc Kleine-Budde if (match) 2069eb79a267SMarc Kleine-Budde priv->devtype_data = *(struct mcp251xfd_devtype_data *)match; 207055e5b97fSMarc Kleine-Budde else 2071eb79a267SMarc Kleine-Budde priv->devtype_data = *(struct mcp251xfd_devtype_data *) 207255e5b97fSMarc Kleine-Budde spi_get_device_id(spi)->driver_data; 207355e5b97fSMarc Kleine-Budde 2074f5b84dedSThomas Kopp /* Errata Reference: 207528eb119cSMarc Kleine-Budde * mcp2517fd: DS80000792C 5., mcp2518fd: DS80000789C 4. 207655e5b97fSMarc Kleine-Budde * 2077f5b84dedSThomas Kopp * The SPI can write corrupted data to the RAM at fast SPI 2078f5b84dedSThomas Kopp * speeds: 2079f5b84dedSThomas Kopp * 2080f5b84dedSThomas Kopp * Simultaneous activity on the CAN bus while writing data to 2081f5b84dedSThomas Kopp * RAM via the SPI interface, with high SCK frequency, can 2082f5b84dedSThomas Kopp * lead to corrupted data being written to RAM. 2083f5b84dedSThomas Kopp * 2084f5b84dedSThomas Kopp * Fix/Work Around: 2085f5b84dedSThomas Kopp * Ensure that FSCK is less than or equal to 0.85 * 2086f5b84dedSThomas Kopp * (FSYSCLK/2). 2087f5b84dedSThomas Kopp * 208801b2a0e5SMarc Kleine-Budde * Known good combinations are: 208955e5b97fSMarc Kleine-Budde * 209001b2a0e5SMarc Kleine-Budde * MCP ext-clk SoC SPI SPI-clk max-clk parent-clk config 209155e5b97fSMarc Kleine-Budde * 209201b2a0e5SMarc Kleine-Budde * 2518 20 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 8333333 Hz 83.33% 600000000 Hz assigned-clocks = <&ccu CLK_SPIx> 209301b2a0e5SMarc Kleine-Budde * 2518 40 MHz allwinner,sun8i-h3 allwinner,sun8i-h3-spi 16666667 Hz 83.33% 600000000 Hz assigned-clocks = <&ccu CLK_SPIx> 209401b2a0e5SMarc Kleine-Budde * 2517 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz default 209501b2a0e5SMarc Kleine-Budde * 2518 40 MHz atmel,sama5d27 atmel,at91rm9200-spi 16400000 Hz 82.00% 82000000 Hz default 20969f1fbc1cSMarc Kleine-Budde * 2518 40 MHz fsl,imx6dl fsl,imx51-ecspi 15000000 Hz 75.00% 30000000 Hz default 209701b2a0e5SMarc Kleine-Budde * 2517 20 MHz fsl,imx8mm fsl,imx51-ecspi 8333333 Hz 83.33% 16666667 Hz assigned-clocks = <&clk IMX8MM_CLK_ECSPIx_ROOT> 209855e5b97fSMarc Kleine-Budde * 209955e5b97fSMarc Kleine-Budde */ 210055e5b97fSMarc Kleine-Budde priv->spi_max_speed_hz_orig = spi->max_speed_hz; 21012a68dd86SMarc Kleine-Budde priv->spi_max_speed_hz_slow = min(spi->max_speed_hz, 21022a68dd86SMarc Kleine-Budde freq / 2 / 1000 * 850); 21032a68dd86SMarc Kleine-Budde if (priv->pll_enable) 21042a68dd86SMarc Kleine-Budde priv->spi_max_speed_hz_fast = min(spi->max_speed_hz, 21052a68dd86SMarc Kleine-Budde freq * 21062a68dd86SMarc Kleine-Budde MCP251XFD_OSC_PLL_MULTIPLIER / 21072a68dd86SMarc Kleine-Budde 2 / 1000 * 850); 21082a68dd86SMarc Kleine-Budde else 21092a68dd86SMarc Kleine-Budde priv->spi_max_speed_hz_fast = priv->spi_max_speed_hz_slow; 21102a68dd86SMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_slow; 211155e5b97fSMarc Kleine-Budde spi->bits_per_word = 8; 211255e5b97fSMarc Kleine-Budde spi->rt = true; 211355e5b97fSMarc Kleine-Budde err = spi_setup(spi); 211455e5b97fSMarc Kleine-Budde if (err) 211555e5b97fSMarc Kleine-Budde goto out_free_candev; 211655e5b97fSMarc Kleine-Budde 2117eb79a267SMarc Kleine-Budde err = mcp251xfd_regmap_init(priv); 211855e5b97fSMarc Kleine-Budde if (err) 211955e5b97fSMarc Kleine-Budde goto out_free_candev; 212055e5b97fSMarc Kleine-Budde 212155e5b97fSMarc Kleine-Budde err = can_rx_offload_add_manual(ndev, &priv->offload, 2122eb79a267SMarc Kleine-Budde MCP251XFD_NAPI_WEIGHT); 212355e5b97fSMarc Kleine-Budde if (err) 212455e5b97fSMarc Kleine-Budde goto out_free_candev; 212555e5b97fSMarc Kleine-Budde 2126eb79a267SMarc Kleine-Budde err = mcp251xfd_register(priv); 2127197656deSMarc Kleine-Budde if (err) { 2128197656deSMarc Kleine-Budde dev_err_probe(&spi->dev, err, "Failed to detect %s.\n", 2129197656deSMarc Kleine-Budde mcp251xfd_get_model_str(priv)); 21304376ea42SMarc Kleine-Budde goto out_can_rx_offload_del; 2131197656deSMarc Kleine-Budde } 213255e5b97fSMarc Kleine-Budde 213355e5b97fSMarc Kleine-Budde return 0; 213455e5b97fSMarc Kleine-Budde 21354376ea42SMarc Kleine-Budde out_can_rx_offload_del: 21364376ea42SMarc Kleine-Budde can_rx_offload_del(&priv->offload); 213755e5b97fSMarc Kleine-Budde out_free_candev: 213855e5b97fSMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 213955e5b97fSMarc Kleine-Budde 214055e5b97fSMarc Kleine-Budde free_candev(ndev); 214155e5b97fSMarc Kleine-Budde 214255e5b97fSMarc Kleine-Budde return err; 214355e5b97fSMarc Kleine-Budde } 214455e5b97fSMarc Kleine-Budde 2145a0386bbaSUwe Kleine-König static void mcp251xfd_remove(struct spi_device *spi) 214655e5b97fSMarc Kleine-Budde { 2147eb79a267SMarc Kleine-Budde struct mcp251xfd_priv *priv = spi_get_drvdata(spi); 214855e5b97fSMarc Kleine-Budde struct net_device *ndev = priv->ndev; 214955e5b97fSMarc Kleine-Budde 215055e5b97fSMarc Kleine-Budde can_rx_offload_del(&priv->offload); 2151eb79a267SMarc Kleine-Budde mcp251xfd_unregister(priv); 215255e5b97fSMarc Kleine-Budde spi->max_speed_hz = priv->spi_max_speed_hz_orig; 215355e5b97fSMarc Kleine-Budde free_candev(ndev); 215455e5b97fSMarc Kleine-Budde } 215555e5b97fSMarc Kleine-Budde 2156eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_suspend(struct device *device) 215755e5b97fSMarc Kleine-Budde { 2158eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = dev_get_drvdata(device); 215955e5b97fSMarc Kleine-Budde 2160eb79a267SMarc Kleine-Budde return mcp251xfd_clks_and_vdd_disable(priv); 216155e5b97fSMarc Kleine-Budde } 216255e5b97fSMarc Kleine-Budde 2163eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_resume(struct device *device) 216455e5b97fSMarc Kleine-Budde { 2165eb79a267SMarc Kleine-Budde const struct mcp251xfd_priv *priv = dev_get_drvdata(device); 216655e5b97fSMarc Kleine-Budde 2167eb79a267SMarc Kleine-Budde return mcp251xfd_clks_and_vdd_enable(priv); 216855e5b97fSMarc Kleine-Budde } 216955e5b97fSMarc Kleine-Budde 2170eb79a267SMarc Kleine-Budde static const struct dev_pm_ops mcp251xfd_pm_ops = { 2171eb79a267SMarc Kleine-Budde SET_RUNTIME_PM_OPS(mcp251xfd_runtime_suspend, 2172eb79a267SMarc Kleine-Budde mcp251xfd_runtime_resume, NULL) 217355e5b97fSMarc Kleine-Budde }; 217455e5b97fSMarc Kleine-Budde 2175eb79a267SMarc Kleine-Budde static struct spi_driver mcp251xfd_driver = { 217655e5b97fSMarc Kleine-Budde .driver = { 217755e5b97fSMarc Kleine-Budde .name = DEVICE_NAME, 2178eb79a267SMarc Kleine-Budde .pm = &mcp251xfd_pm_ops, 2179eb79a267SMarc Kleine-Budde .of_match_table = mcp251xfd_of_match, 218055e5b97fSMarc Kleine-Budde }, 2181eb79a267SMarc Kleine-Budde .probe = mcp251xfd_probe, 2182eb79a267SMarc Kleine-Budde .remove = mcp251xfd_remove, 2183eb79a267SMarc Kleine-Budde .id_table = mcp251xfd_id_table, 218455e5b97fSMarc Kleine-Budde }; 2185eb79a267SMarc Kleine-Budde module_spi_driver(mcp251xfd_driver); 218655e5b97fSMarc Kleine-Budde 218755e5b97fSMarc Kleine-Budde MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>"); 2188f4f77366SMarc Kleine-Budde MODULE_DESCRIPTION("Microchip MCP251xFD Family CAN controller driver"); 218955e5b97fSMarc Kleine-Budde MODULE_LICENSE("GPL v2"); 2190