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