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 //
5eb94b74cSMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021 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>
1871520f85SAndy Shevchenko #include <linux/mod_devicetable.h>
191f0e21a0SMarc Kleine-Budde #include <linux/module.h>
201f0e21a0SMarc Kleine-Budde #include <linux/pm_runtime.h>
2171520f85SAndy Shevchenko #include <linux/property.h>
221f0e21a0SMarc Kleine-Budde 
231f0e21a0SMarc Kleine-Budde #include <asm/unaligned.h>
241f0e21a0SMarc Kleine-Budde 
251f0e21a0SMarc Kleine-Budde #include "mcp251xfd.h"
261f0e21a0SMarc Kleine-Budde 
27f4f77366SMarc Kleine-Budde #define DEVICE_NAME "mcp251xfd"
281f0e21a0SMarc Kleine-Budde 
29eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp2517fd = {
30eb79a267SMarc Kleine-Budde 	.quirks = MCP251XFD_QUIRK_MAB_NO_WARN | MCP251XFD_QUIRK_CRC_REG |
31eb79a267SMarc Kleine-Budde 		MCP251XFD_QUIRK_CRC_RX | MCP251XFD_QUIRK_CRC_TX |
32eb79a267SMarc Kleine-Budde 		MCP251XFD_QUIRK_ECC,
33eb79a267SMarc Kleine-Budde 	.model = MCP251XFD_MODEL_MCP2517FD,
341f0e21a0SMarc Kleine-Budde };
351f0e21a0SMarc Kleine-Budde 
36eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp2518fd = {
37eb79a267SMarc Kleine-Budde 	.quirks = MCP251XFD_QUIRK_CRC_REG | MCP251XFD_QUIRK_CRC_RX |
38eb79a267SMarc Kleine-Budde 		MCP251XFD_QUIRK_CRC_TX | MCP251XFD_QUIRK_ECC,
39eb79a267SMarc Kleine-Budde 	.model = MCP251XFD_MODEL_MCP2518FD,
401f0e21a0SMarc Kleine-Budde };
411f0e21a0SMarc Kleine-Budde 
421f0e21a0SMarc Kleine-Budde /* Autodetect model, start with CRC enabled. */
43eb79a267SMarc Kleine-Budde static const struct mcp251xfd_devtype_data mcp251xfd_devtype_data_mcp251xfd = {
44eb79a267SMarc Kleine-Budde 	.quirks = MCP251XFD_QUIRK_CRC_REG | MCP251XFD_QUIRK_CRC_RX |
45eb79a267SMarc Kleine-Budde 		MCP251XFD_QUIRK_CRC_TX | MCP251XFD_QUIRK_ECC,
46eb79a267SMarc Kleine-Budde 	.model = MCP251XFD_MODEL_MCP251XFD,
471f0e21a0SMarc Kleine-Budde };
481f0e21a0SMarc Kleine-Budde 
49eb79a267SMarc Kleine-Budde static const struct can_bittiming_const mcp251xfd_bittiming_const = {
501f0e21a0SMarc Kleine-Budde 	.name = DEVICE_NAME,
511f0e21a0SMarc Kleine-Budde 	.tseg1_min = 2,
521f0e21a0SMarc Kleine-Budde 	.tseg1_max = 256,
531f0e21a0SMarc Kleine-Budde 	.tseg2_min = 1,
541f0e21a0SMarc Kleine-Budde 	.tseg2_max = 128,
551f0e21a0SMarc Kleine-Budde 	.sjw_max = 128,
561f0e21a0SMarc Kleine-Budde 	.brp_min = 1,
571f0e21a0SMarc Kleine-Budde 	.brp_max = 256,
581f0e21a0SMarc Kleine-Budde 	.brp_inc = 1,
591f0e21a0SMarc Kleine-Budde };
601f0e21a0SMarc Kleine-Budde 
61eb79a267SMarc Kleine-Budde static const struct can_bittiming_const mcp251xfd_data_bittiming_const = {
621f0e21a0SMarc Kleine-Budde 	.name = DEVICE_NAME,
631f0e21a0SMarc Kleine-Budde 	.tseg1_min = 1,
641f0e21a0SMarc Kleine-Budde 	.tseg1_max = 32,
651f0e21a0SMarc Kleine-Budde 	.tseg2_min = 1,
661f0e21a0SMarc Kleine-Budde 	.tseg2_max = 16,
671f0e21a0SMarc Kleine-Budde 	.sjw_max = 16,
681f0e21a0SMarc Kleine-Budde 	.brp_min = 1,
691f0e21a0SMarc Kleine-Budde 	.brp_max = 256,
701f0e21a0SMarc Kleine-Budde 	.brp_inc = 1,
711f0e21a0SMarc Kleine-Budde };
721f0e21a0SMarc Kleine-Budde 
73eb79a267SMarc Kleine-Budde static const char *__mcp251xfd_get_model_str(enum mcp251xfd_model model)
741f0e21a0SMarc Kleine-Budde {
751f0e21a0SMarc Kleine-Budde 	switch (model) {
76eb79a267SMarc Kleine-Budde 	case MCP251XFD_MODEL_MCP2517FD:
7778db1aa8STom Rix 		return "MCP2517FD";
78eb79a267SMarc Kleine-Budde 	case MCP251XFD_MODEL_MCP2518FD:
7978db1aa8STom Rix 		return "MCP2518FD";
80eb79a267SMarc Kleine-Budde 	case MCP251XFD_MODEL_MCP251XFD:
8178db1aa8STom Rix 		return "MCP251xFD";
821f0e21a0SMarc Kleine-Budde 	}
831f0e21a0SMarc Kleine-Budde 
841f0e21a0SMarc Kleine-Budde 	return "<unknown>";
851f0e21a0SMarc Kleine-Budde }
861f0e21a0SMarc Kleine-Budde 
871f0e21a0SMarc Kleine-Budde static inline const char *
88eb79a267SMarc Kleine-Budde mcp251xfd_get_model_str(const struct mcp251xfd_priv *priv)
891f0e21a0SMarc Kleine-Budde {
90eb79a267SMarc Kleine-Budde 	return __mcp251xfd_get_model_str(priv->devtype_data.model);
911f0e21a0SMarc Kleine-Budde }
921f0e21a0SMarc Kleine-Budde 
93eb79a267SMarc Kleine-Budde static const char *mcp251xfd_get_mode_str(const u8 mode)
941f0e21a0SMarc Kleine-Budde {
951f0e21a0SMarc Kleine-Budde 	switch (mode) {
96eb79a267SMarc Kleine-Budde 	case MCP251XFD_REG_CON_MODE_MIXED:
9778db1aa8STom Rix 		return "Mixed (CAN FD/CAN 2.0)";
98eb79a267SMarc Kleine-Budde 	case MCP251XFD_REG_CON_MODE_SLEEP:
9978db1aa8STom Rix 		return "Sleep";
100eb79a267SMarc Kleine-Budde 	case MCP251XFD_REG_CON_MODE_INT_LOOPBACK:
10178db1aa8STom Rix 		return "Internal Loopback";
102eb79a267SMarc Kleine-Budde 	case MCP251XFD_REG_CON_MODE_LISTENONLY:
10378db1aa8STom Rix 		return "Listen Only";
104eb79a267SMarc Kleine-Budde 	case MCP251XFD_REG_CON_MODE_CONFIG:
10578db1aa8STom Rix 		return "Configuration";
106eb79a267SMarc Kleine-Budde 	case MCP251XFD_REG_CON_MODE_EXT_LOOPBACK:
10778db1aa8STom Rix 		return "External Loopback";
108eb79a267SMarc Kleine-Budde 	case MCP251XFD_REG_CON_MODE_CAN2_0:
10978db1aa8STom Rix 		return "CAN 2.0";
110eb79a267SMarc Kleine-Budde 	case MCP251XFD_REG_CON_MODE_RESTRICTED:
11178db1aa8STom Rix 		return "Restricted Operation";
1121f0e21a0SMarc Kleine-Budde 	}
1131f0e21a0SMarc Kleine-Budde 
1141f0e21a0SMarc Kleine-Budde 	return "<unknown>";
1151f0e21a0SMarc Kleine-Budde }
1161f0e21a0SMarc Kleine-Budde 
117eb79a267SMarc Kleine-Budde static inline int mcp251xfd_vdd_enable(const struct mcp251xfd_priv *priv)
1181f0e21a0SMarc Kleine-Budde {
1191f0e21a0SMarc Kleine-Budde 	if (!priv->reg_vdd)
1201f0e21a0SMarc Kleine-Budde 		return 0;
1211f0e21a0SMarc Kleine-Budde 
1221f0e21a0SMarc Kleine-Budde 	return regulator_enable(priv->reg_vdd);
1231f0e21a0SMarc Kleine-Budde }
1241f0e21a0SMarc Kleine-Budde 
125eb79a267SMarc Kleine-Budde static inline int mcp251xfd_vdd_disable(const struct mcp251xfd_priv *priv)
1261f0e21a0SMarc Kleine-Budde {
1271f0e21a0SMarc Kleine-Budde 	if (!priv->reg_vdd)
1281f0e21a0SMarc Kleine-Budde 		return 0;
1291f0e21a0SMarc Kleine-Budde 
1301f0e21a0SMarc Kleine-Budde 	return regulator_disable(priv->reg_vdd);
1311f0e21a0SMarc Kleine-Budde }
1321f0e21a0SMarc Kleine-Budde 
1331f0e21a0SMarc Kleine-Budde static inline int
134eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_enable(const struct mcp251xfd_priv *priv)
1351f0e21a0SMarc Kleine-Budde {
1361f0e21a0SMarc Kleine-Budde 	if (!priv->reg_xceiver)
1371f0e21a0SMarc Kleine-Budde 		return 0;
1381f0e21a0SMarc Kleine-Budde 
1391f0e21a0SMarc Kleine-Budde 	return regulator_enable(priv->reg_xceiver);
1401f0e21a0SMarc Kleine-Budde }
1411f0e21a0SMarc Kleine-Budde 
1421f0e21a0SMarc Kleine-Budde static inline int
143eb79a267SMarc Kleine-Budde mcp251xfd_transceiver_disable(const struct mcp251xfd_priv *priv)
1441f0e21a0SMarc Kleine-Budde {
1451f0e21a0SMarc Kleine-Budde 	if (!priv->reg_xceiver)
1461f0e21a0SMarc Kleine-Budde 		return 0;
1471f0e21a0SMarc Kleine-Budde 
1481f0e21a0SMarc Kleine-Budde 	return regulator_disable(priv->reg_xceiver);
1491f0e21a0SMarc Kleine-Budde }
1501f0e21a0SMarc Kleine-Budde 
151eb79a267SMarc Kleine-Budde static int mcp251xfd_clks_and_vdd_enable(const struct mcp251xfd_priv *priv)
1521f0e21a0SMarc Kleine-Budde {
1531f0e21a0SMarc Kleine-Budde 	int err;
1541f0e21a0SMarc Kleine-Budde 
1551f0e21a0SMarc Kleine-Budde 	err = clk_prepare_enable(priv->clk);
1561f0e21a0SMarc Kleine-Budde 	if (err)
1571f0e21a0SMarc Kleine-Budde 		return err;
1581f0e21a0SMarc Kleine-Budde 
159eb79a267SMarc Kleine-Budde 	err = mcp251xfd_vdd_enable(priv);
1601f0e21a0SMarc Kleine-Budde 	if (err)
1611f0e21a0SMarc Kleine-Budde 		clk_disable_unprepare(priv->clk);
1621f0e21a0SMarc Kleine-Budde 
1631f0e21a0SMarc Kleine-Budde 	/* Wait for oscillator stabilisation time after power up */
164eb79a267SMarc Kleine-Budde 	usleep_range(MCP251XFD_OSC_STAB_SLEEP_US,
165eb79a267SMarc Kleine-Budde 		     2 * MCP251XFD_OSC_STAB_SLEEP_US);
1661f0e21a0SMarc Kleine-Budde 
1671f0e21a0SMarc Kleine-Budde 	return err;
1681f0e21a0SMarc Kleine-Budde }
1691f0e21a0SMarc Kleine-Budde 
170eb79a267SMarc Kleine-Budde static int mcp251xfd_clks_and_vdd_disable(const struct mcp251xfd_priv *priv)
1711f0e21a0SMarc Kleine-Budde {
1721f0e21a0SMarc Kleine-Budde 	int err;
1731f0e21a0SMarc Kleine-Budde 
174eb79a267SMarc Kleine-Budde 	err = mcp251xfd_vdd_disable(priv);
1751f0e21a0SMarc Kleine-Budde 	if (err)
1761f0e21a0SMarc Kleine-Budde 		return err;
1771f0e21a0SMarc Kleine-Budde 
1781f0e21a0SMarc Kleine-Budde 	clk_disable_unprepare(priv->clk);
1791f0e21a0SMarc Kleine-Budde 
1801f0e21a0SMarc Kleine-Budde 	return 0;
1811f0e21a0SMarc Kleine-Budde }
1821f0e21a0SMarc Kleine-Budde 
1831f0e21a0SMarc Kleine-Budde static inline u8
184eb79a267SMarc Kleine-Budde mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv,
185eb79a267SMarc Kleine-Budde 				union mcp251xfd_write_reg_buf *write_reg_buf,
1861f0e21a0SMarc Kleine-Budde 				const u16 reg, const u32 mask, const u32 val)
1871f0e21a0SMarc Kleine-Budde {
1881f0e21a0SMarc Kleine-Budde 	u8 first_byte, last_byte, len;
1891f0e21a0SMarc Kleine-Budde 	u8 *data;
1901f0e21a0SMarc Kleine-Budde 	__le32 val_le32;
1911f0e21a0SMarc Kleine-Budde 
192eb79a267SMarc Kleine-Budde 	first_byte = mcp251xfd_first_byte_set(mask);
193eb79a267SMarc Kleine-Budde 	last_byte = mcp251xfd_last_byte_set(mask);
1941f0e21a0SMarc Kleine-Budde 	len = last_byte - first_byte + 1;
1951f0e21a0SMarc Kleine-Budde 
196eb79a267SMarc Kleine-Budde 	data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte);
1971f0e21a0SMarc Kleine-Budde 	val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte);
1981f0e21a0SMarc Kleine-Budde 	memcpy(data, &val_le32, len);
1991f0e21a0SMarc Kleine-Budde 
200eb79a267SMarc Kleine-Budde 	if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) {
2011f0e21a0SMarc Kleine-Budde 		u16 crc;
2021f0e21a0SMarc Kleine-Budde 
203eb79a267SMarc Kleine-Budde 		mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd,
2041f0e21a0SMarc Kleine-Budde 						     len);
2051f0e21a0SMarc Kleine-Budde 		/* CRC */
2061f0e21a0SMarc Kleine-Budde 		len += sizeof(write_reg_buf->crc.cmd);
207eb79a267SMarc Kleine-Budde 		crc = mcp251xfd_crc16_compute(&write_reg_buf->crc, len);
2081f0e21a0SMarc Kleine-Budde 		put_unaligned_be16(crc, (void *)write_reg_buf + len);
2091f0e21a0SMarc Kleine-Budde 
2101f0e21a0SMarc Kleine-Budde 		/* Total length */
2111f0e21a0SMarc Kleine-Budde 		len += sizeof(write_reg_buf->crc.crc);
2121f0e21a0SMarc Kleine-Budde 	} else {
2131f0e21a0SMarc Kleine-Budde 		len += sizeof(write_reg_buf->nocrc.cmd);
2141f0e21a0SMarc Kleine-Budde 	}
2151f0e21a0SMarc Kleine-Budde 
2161f0e21a0SMarc Kleine-Budde 	return len;
2171f0e21a0SMarc Kleine-Budde }
2181f0e21a0SMarc Kleine-Budde 
2191f0e21a0SMarc Kleine-Budde static inline int
220eb79a267SMarc Kleine-Budde mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
2211f0e21a0SMarc Kleine-Budde 				 u8 *tef_tail)
2221f0e21a0SMarc Kleine-Budde {
2231f0e21a0SMarc Kleine-Budde 	u32 tef_ua;
2241f0e21a0SMarc Kleine-Budde 	int err;
2251f0e21a0SMarc Kleine-Budde 
226eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFUA, &tef_ua);
2271f0e21a0SMarc Kleine-Budde 	if (err)
2281f0e21a0SMarc Kleine-Budde 		return err;
2291f0e21a0SMarc Kleine-Budde 
230eb79a267SMarc Kleine-Budde 	*tef_tail = tef_ua / sizeof(struct mcp251xfd_hw_tef_obj);
2311f0e21a0SMarc Kleine-Budde 
2321f0e21a0SMarc Kleine-Budde 	return 0;
2331f0e21a0SMarc Kleine-Budde }
2341f0e21a0SMarc Kleine-Budde 
2351f0e21a0SMarc Kleine-Budde static inline int
236eb79a267SMarc Kleine-Budde mcp251xfd_tx_tail_get_from_chip(const struct mcp251xfd_priv *priv,
2371f0e21a0SMarc Kleine-Budde 				u8 *tx_tail)
2381f0e21a0SMarc Kleine-Budde {
2391f0e21a0SMarc Kleine-Budde 	u32 fifo_sta;
2401f0e21a0SMarc Kleine-Budde 	int err;
2411f0e21a0SMarc Kleine-Budde 
2421f0e21a0SMarc Kleine-Budde 	err = regmap_read(priv->map_reg,
243eb79a267SMarc Kleine-Budde 			  MCP251XFD_REG_FIFOSTA(MCP251XFD_TX_FIFO),
2441f0e21a0SMarc Kleine-Budde 			  &fifo_sta);
2451f0e21a0SMarc Kleine-Budde 	if (err)
2461f0e21a0SMarc Kleine-Budde 		return err;
2471f0e21a0SMarc Kleine-Budde 
248eb79a267SMarc Kleine-Budde 	*tx_tail = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
2491f0e21a0SMarc Kleine-Budde 
2501f0e21a0SMarc Kleine-Budde 	return 0;
2511f0e21a0SMarc Kleine-Budde }
2521f0e21a0SMarc Kleine-Budde 
2531f0e21a0SMarc Kleine-Budde static inline int
254eb79a267SMarc Kleine-Budde mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv,
255eb79a267SMarc Kleine-Budde 				const struct mcp251xfd_rx_ring *ring,
2561f0e21a0SMarc Kleine-Budde 				u8 *rx_head)
2571f0e21a0SMarc Kleine-Budde {
2581f0e21a0SMarc Kleine-Budde 	u32 fifo_sta;
2591f0e21a0SMarc Kleine-Budde 	int err;
2601f0e21a0SMarc Kleine-Budde 
261eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(ring->fifo_nr),
2621f0e21a0SMarc Kleine-Budde 			  &fifo_sta);
2631f0e21a0SMarc Kleine-Budde 	if (err)
2641f0e21a0SMarc Kleine-Budde 		return err;
2651f0e21a0SMarc Kleine-Budde 
266eb79a267SMarc Kleine-Budde 	*rx_head = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
2671f0e21a0SMarc Kleine-Budde 
2681f0e21a0SMarc Kleine-Budde 	return 0;
2691f0e21a0SMarc Kleine-Budde }
2701f0e21a0SMarc Kleine-Budde 
2711f0e21a0SMarc Kleine-Budde static inline int
272eb79a267SMarc Kleine-Budde mcp251xfd_rx_tail_get_from_chip(const struct mcp251xfd_priv *priv,
273eb79a267SMarc Kleine-Budde 				const struct mcp251xfd_rx_ring *ring,
2741f0e21a0SMarc Kleine-Budde 				u8 *rx_tail)
2751f0e21a0SMarc Kleine-Budde {
2761f0e21a0SMarc Kleine-Budde 	u32 fifo_ua;
2771f0e21a0SMarc Kleine-Budde 	int err;
2781f0e21a0SMarc Kleine-Budde 
279eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOUA(ring->fifo_nr),
2801f0e21a0SMarc Kleine-Budde 			  &fifo_ua);
2811f0e21a0SMarc Kleine-Budde 	if (err)
2821f0e21a0SMarc Kleine-Budde 		return err;
2831f0e21a0SMarc Kleine-Budde 
284eb79a267SMarc Kleine-Budde 	fifo_ua -= ring->base - MCP251XFD_RAM_START;
2851f0e21a0SMarc Kleine-Budde 	*rx_tail = fifo_ua / ring->obj_size;
2861f0e21a0SMarc Kleine-Budde 
2871f0e21a0SMarc Kleine-Budde 	return 0;
2881f0e21a0SMarc Kleine-Budde }
2891f0e21a0SMarc Kleine-Budde 
2901f0e21a0SMarc Kleine-Budde static void
291eb79a267SMarc Kleine-Budde mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv,
292eb79a267SMarc Kleine-Budde 			      const struct mcp251xfd_tx_ring *ring,
293eb79a267SMarc Kleine-Budde 			      struct mcp251xfd_tx_obj *tx_obj,
2941f0e21a0SMarc Kleine-Budde 			      const u8 rts_buf_len,
2951f0e21a0SMarc Kleine-Budde 			      const u8 n)
2961f0e21a0SMarc Kleine-Budde {
2971f0e21a0SMarc Kleine-Budde 	struct spi_transfer *xfer;
2981f0e21a0SMarc Kleine-Budde 	u16 addr;
2991f0e21a0SMarc Kleine-Budde 
3001f0e21a0SMarc Kleine-Budde 	/* FIFO load */
301eb79a267SMarc Kleine-Budde 	addr = mcp251xfd_get_tx_obj_addr(ring, n);
302eb79a267SMarc Kleine-Budde 	if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX)
303eb79a267SMarc Kleine-Budde 		mcp251xfd_spi_cmd_write_crc_set_addr(&tx_obj->buf.crc.cmd,
3041f0e21a0SMarc Kleine-Budde 						     addr);
3051f0e21a0SMarc Kleine-Budde 	else
306eb79a267SMarc Kleine-Budde 		mcp251xfd_spi_cmd_write_nocrc(&tx_obj->buf.nocrc.cmd,
3071f0e21a0SMarc Kleine-Budde 					      addr);
3081f0e21a0SMarc Kleine-Budde 
3091f0e21a0SMarc Kleine-Budde 	xfer = &tx_obj->xfer[0];
3101f0e21a0SMarc Kleine-Budde 	xfer->tx_buf = &tx_obj->buf;
3111f0e21a0SMarc Kleine-Budde 	xfer->len = 0;	/* actual len is assigned on the fly */
3121f0e21a0SMarc Kleine-Budde 	xfer->cs_change = 1;
3131f0e21a0SMarc Kleine-Budde 	xfer->cs_change_delay.value = 0;
3141f0e21a0SMarc Kleine-Budde 	xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
3151f0e21a0SMarc Kleine-Budde 
3161f0e21a0SMarc Kleine-Budde 	/* FIFO request to send */
3171f0e21a0SMarc Kleine-Budde 	xfer = &tx_obj->xfer[1];
3181f0e21a0SMarc Kleine-Budde 	xfer->tx_buf = &ring->rts_buf;
3191f0e21a0SMarc Kleine-Budde 	xfer->len = rts_buf_len;
3201f0e21a0SMarc Kleine-Budde 
3211f0e21a0SMarc Kleine-Budde 	/* SPI message */
3221f0e21a0SMarc Kleine-Budde 	spi_message_init_with_transfers(&tx_obj->msg, tx_obj->xfer,
3231f0e21a0SMarc Kleine-Budde 					ARRAY_SIZE(tx_obj->xfer));
3241f0e21a0SMarc Kleine-Budde }
3251f0e21a0SMarc Kleine-Budde 
326eb79a267SMarc Kleine-Budde static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
3271f0e21a0SMarc Kleine-Budde {
328dada6a6cSMarc Kleine-Budde 	struct mcp251xfd_tef_ring *tef_ring;
329eb79a267SMarc Kleine-Budde 	struct mcp251xfd_tx_ring *tx_ring;
330eb79a267SMarc Kleine-Budde 	struct mcp251xfd_rx_ring *rx_ring, *prev_rx_ring = NULL;
331eb79a267SMarc Kleine-Budde 	struct mcp251xfd_tx_obj *tx_obj;
332eb94b74cSMarc Kleine-Budde 	struct spi_transfer *xfer;
3331f0e21a0SMarc Kleine-Budde 	u32 val;
3341f0e21a0SMarc Kleine-Budde 	u16 addr;
3351f0e21a0SMarc Kleine-Budde 	u8 len;
3361f652bb6SUrsula Maplehurst 	int i, j;
3371f0e21a0SMarc Kleine-Budde 
3380084e298SMarc Kleine-Budde 	netdev_reset_queue(priv->ndev);
3390084e298SMarc Kleine-Budde 
3401f0e21a0SMarc Kleine-Budde 	/* TEF */
341dada6a6cSMarc Kleine-Budde 	tef_ring = priv->tef;
342dada6a6cSMarc Kleine-Budde 	tef_ring->head = 0;
343dada6a6cSMarc Kleine-Budde 	tef_ring->tail = 0;
3441f0e21a0SMarc Kleine-Budde 
34568c0c1c7SMarc Kleine-Budde 	/* FIFO increment TEF tail pointer */
34668c0c1c7SMarc Kleine-Budde 	addr = MCP251XFD_REG_TEFCON;
34768c0c1c7SMarc Kleine-Budde 	val = MCP251XFD_REG_TEFCON_UINC;
34868c0c1c7SMarc Kleine-Budde 	len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf,
34968c0c1c7SMarc Kleine-Budde 					      addr, val, val);
35068c0c1c7SMarc Kleine-Budde 
35168c0c1c7SMarc Kleine-Budde 	for (j = 0; j < ARRAY_SIZE(tef_ring->uinc_xfer); j++) {
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 
360eb94b74cSMarc Kleine-Budde 	/* "cs_change == 1" on the last transfer results in an active
361eb94b74cSMarc Kleine-Budde 	 * chip select after the complete SPI message. This causes the
362eb94b74cSMarc Kleine-Budde 	 * controller to interpret the next register access as
363eb94b74cSMarc Kleine-Budde 	 * data. Set "cs_change" of the last transfer to "0" to
364eb94b74cSMarc Kleine-Budde 	 * properly deactivate the chip select at the end of the
365eb94b74cSMarc Kleine-Budde 	 * message.
366eb94b74cSMarc Kleine-Budde 	 */
367eb94b74cSMarc Kleine-Budde 	xfer->cs_change = 0;
368eb94b74cSMarc Kleine-Budde 
3691f0e21a0SMarc Kleine-Budde 	/* TX */
3701f0e21a0SMarc Kleine-Budde 	tx_ring = priv->tx;
3711f0e21a0SMarc Kleine-Budde 	tx_ring->head = 0;
3721f0e21a0SMarc Kleine-Budde 	tx_ring->tail = 0;
373eb79a267SMarc Kleine-Budde 	tx_ring->base = mcp251xfd_get_tef_obj_addr(tx_ring->obj_num);
3741f0e21a0SMarc Kleine-Budde 
3751f0e21a0SMarc Kleine-Budde 	/* FIFO request to send */
376eb79a267SMarc Kleine-Budde 	addr = MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO);
377eb79a267SMarc Kleine-Budde 	val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC;
378eb79a267SMarc Kleine-Budde 	len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf,
3791f0e21a0SMarc Kleine-Budde 					      addr, val, val);
3801f0e21a0SMarc Kleine-Budde 
381eb79a267SMarc Kleine-Budde 	mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i)
382eb79a267SMarc Kleine-Budde 		mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i);
3831f0e21a0SMarc Kleine-Budde 
3841f0e21a0SMarc Kleine-Budde 	/* RX */
385eb79a267SMarc Kleine-Budde 	mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
3861f0e21a0SMarc Kleine-Budde 		rx_ring->head = 0;
3871f0e21a0SMarc Kleine-Budde 		rx_ring->tail = 0;
3881f0e21a0SMarc Kleine-Budde 		rx_ring->nr = i;
389eb79a267SMarc Kleine-Budde 		rx_ring->fifo_nr = MCP251XFD_RX_FIFO(i);
3901f0e21a0SMarc Kleine-Budde 
3911f0e21a0SMarc Kleine-Budde 		if (!prev_rx_ring)
3921f0e21a0SMarc Kleine-Budde 			rx_ring->base =
393eb79a267SMarc Kleine-Budde 				mcp251xfd_get_tx_obj_addr(tx_ring,
3941f0e21a0SMarc Kleine-Budde 							  tx_ring->obj_num);
3951f0e21a0SMarc Kleine-Budde 		else
3961f0e21a0SMarc Kleine-Budde 			rx_ring->base = prev_rx_ring->base +
3971f0e21a0SMarc Kleine-Budde 				prev_rx_ring->obj_size *
3981f0e21a0SMarc Kleine-Budde 				prev_rx_ring->obj_num;
3991f0e21a0SMarc Kleine-Budde 
4001f0e21a0SMarc Kleine-Budde 		prev_rx_ring = rx_ring;
4011f652bb6SUrsula Maplehurst 
4021f652bb6SUrsula Maplehurst 		/* FIFO increment RX tail pointer */
4031f652bb6SUrsula Maplehurst 		addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr);
4041f652bb6SUrsula Maplehurst 		val = MCP251XFD_REG_FIFOCON_UINC;
4051f652bb6SUrsula Maplehurst 		len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf,
4061f652bb6SUrsula Maplehurst 						      addr, val, val);
4071f652bb6SUrsula Maplehurst 
4081f652bb6SUrsula Maplehurst 		for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) {
4091f652bb6SUrsula Maplehurst 			xfer = &rx_ring->uinc_xfer[j];
4101f652bb6SUrsula Maplehurst 			xfer->tx_buf = &rx_ring->uinc_buf;
4111f652bb6SUrsula Maplehurst 			xfer->len = len;
4121f652bb6SUrsula Maplehurst 			xfer->cs_change = 1;
4131f652bb6SUrsula Maplehurst 			xfer->cs_change_delay.value = 0;
4141f652bb6SUrsula Maplehurst 			xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
4151f652bb6SUrsula Maplehurst 		}
416eb94b74cSMarc Kleine-Budde 
417eb94b74cSMarc Kleine-Budde 		/* "cs_change == 1" on the last transfer results in an
418eb94b74cSMarc Kleine-Budde 		 * active chip select after the complete SPI
419eb94b74cSMarc Kleine-Budde 		 * message. This causes the controller to interpret
420eb94b74cSMarc Kleine-Budde 		 * the next register access as data. Set "cs_change"
421eb94b74cSMarc Kleine-Budde 		 * of the last transfer to "0" to properly deactivate
422eb94b74cSMarc Kleine-Budde 		 * the chip select at the end of the message.
423eb94b74cSMarc Kleine-Budde 		 */
424eb94b74cSMarc Kleine-Budde 		xfer->cs_change = 0;
4251f0e21a0SMarc Kleine-Budde 	}
4261f0e21a0SMarc Kleine-Budde }
4271f0e21a0SMarc Kleine-Budde 
428eb79a267SMarc Kleine-Budde static void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
4291f0e21a0SMarc Kleine-Budde {
4301f0e21a0SMarc Kleine-Budde 	int i;
4311f0e21a0SMarc Kleine-Budde 
4321f0e21a0SMarc Kleine-Budde 	for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) {
4331f0e21a0SMarc Kleine-Budde 		kfree(priv->rx[i]);
4341f0e21a0SMarc Kleine-Budde 		priv->rx[i] = NULL;
4351f0e21a0SMarc Kleine-Budde 	}
4361f0e21a0SMarc Kleine-Budde }
4371f0e21a0SMarc Kleine-Budde 
438eb79a267SMarc Kleine-Budde static int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
4391f0e21a0SMarc Kleine-Budde {
440eb79a267SMarc Kleine-Budde 	struct mcp251xfd_tx_ring *tx_ring;
441eb79a267SMarc Kleine-Budde 	struct mcp251xfd_rx_ring *rx_ring;
4421f0e21a0SMarc Kleine-Budde 	int tef_obj_size, tx_obj_size, rx_obj_size;
4431f0e21a0SMarc Kleine-Budde 	int tx_obj_num;
4441f0e21a0SMarc Kleine-Budde 	int ram_free, i;
4451f0e21a0SMarc Kleine-Budde 
446eb79a267SMarc Kleine-Budde 	tef_obj_size = sizeof(struct mcp251xfd_hw_tef_obj);
4471f0e21a0SMarc Kleine-Budde 	/* listen-only mode works like FD mode */
4481f0e21a0SMarc Kleine-Budde 	if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD)) {
449eb79a267SMarc Kleine-Budde 		tx_obj_num = MCP251XFD_TX_OBJ_NUM_CANFD;
450eb79a267SMarc Kleine-Budde 		tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd);
451eb79a267SMarc Kleine-Budde 		rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd);
4521f0e21a0SMarc Kleine-Budde 	} else {
453eb79a267SMarc Kleine-Budde 		tx_obj_num = MCP251XFD_TX_OBJ_NUM_CAN;
454eb79a267SMarc Kleine-Budde 		tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can);
455eb79a267SMarc Kleine-Budde 		rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can);
4561f0e21a0SMarc Kleine-Budde 	}
4571f0e21a0SMarc Kleine-Budde 
4581f0e21a0SMarc Kleine-Budde 	tx_ring = priv->tx;
4591f0e21a0SMarc Kleine-Budde 	tx_ring->obj_num = tx_obj_num;
4601f0e21a0SMarc Kleine-Budde 	tx_ring->obj_size = tx_obj_size;
4611f0e21a0SMarc Kleine-Budde 
462eb79a267SMarc Kleine-Budde 	ram_free = MCP251XFD_RAM_SIZE - tx_obj_num *
4631f0e21a0SMarc Kleine-Budde 		(tef_obj_size + tx_obj_size);
4641f0e21a0SMarc Kleine-Budde 
4651f0e21a0SMarc Kleine-Budde 	for (i = 0;
4661f0e21a0SMarc Kleine-Budde 	     i < ARRAY_SIZE(priv->rx) && ram_free >= rx_obj_size;
4671f0e21a0SMarc Kleine-Budde 	     i++) {
4681f0e21a0SMarc Kleine-Budde 		int rx_obj_num;
4691f0e21a0SMarc Kleine-Budde 
4701f0e21a0SMarc Kleine-Budde 		rx_obj_num = ram_free / rx_obj_size;
4714843ad9bSMarc Kleine-Budde 		rx_obj_num = min(1 << (fls(rx_obj_num) - 1),
4724843ad9bSMarc Kleine-Budde 				 MCP251XFD_RX_OBJ_NUM_MAX);
4731f0e21a0SMarc Kleine-Budde 
4741f0e21a0SMarc Kleine-Budde 		rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
4751f0e21a0SMarc Kleine-Budde 				  GFP_KERNEL);
4761f0e21a0SMarc Kleine-Budde 		if (!rx_ring) {
477eb79a267SMarc Kleine-Budde 			mcp251xfd_ring_free(priv);
4781f0e21a0SMarc Kleine-Budde 			return -ENOMEM;
4791f0e21a0SMarc Kleine-Budde 		}
4801f0e21a0SMarc Kleine-Budde 		rx_ring->obj_num = rx_obj_num;
4811f0e21a0SMarc Kleine-Budde 		rx_ring->obj_size = rx_obj_size;
4821f0e21a0SMarc Kleine-Budde 		priv->rx[i] = rx_ring;
4831f0e21a0SMarc Kleine-Budde 
4841f0e21a0SMarc Kleine-Budde 		ram_free -= rx_ring->obj_num * rx_ring->obj_size;
4851f0e21a0SMarc Kleine-Budde 	}
4861f0e21a0SMarc Kleine-Budde 	priv->rx_ring_num = i;
4871f0e21a0SMarc Kleine-Budde 
4881f0e21a0SMarc Kleine-Budde 	netdev_dbg(priv->ndev,
4891f0e21a0SMarc Kleine-Budde 		   "FIFO setup: TEF: %d*%d bytes = %d bytes, TX: %d*%d bytes = %d bytes\n",
4901f0e21a0SMarc Kleine-Budde 		   tx_obj_num, tef_obj_size, tef_obj_size * tx_obj_num,
4911f0e21a0SMarc Kleine-Budde 		   tx_obj_num, tx_obj_size, tx_obj_size * tx_obj_num);
4921f0e21a0SMarc Kleine-Budde 
493eb79a267SMarc Kleine-Budde 	mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
4941f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev,
4951f0e21a0SMarc Kleine-Budde 			   "FIFO setup: RX-%d: %d*%d bytes = %d bytes\n",
4961f0e21a0SMarc Kleine-Budde 			   i, rx_ring->obj_num, rx_ring->obj_size,
4971f0e21a0SMarc Kleine-Budde 			   rx_ring->obj_size * rx_ring->obj_num);
4981f0e21a0SMarc Kleine-Budde 	}
4991f0e21a0SMarc Kleine-Budde 
5001f0e21a0SMarc Kleine-Budde 	netdev_dbg(priv->ndev,
5011f0e21a0SMarc Kleine-Budde 		   "FIFO setup: free: %d bytes\n",
5021f0e21a0SMarc Kleine-Budde 		   ram_free);
5031f0e21a0SMarc Kleine-Budde 
5041f0e21a0SMarc Kleine-Budde 	return 0;
5051f0e21a0SMarc Kleine-Budde }
5061f0e21a0SMarc Kleine-Budde 
5071f0e21a0SMarc Kleine-Budde static inline int
508eb79a267SMarc Kleine-Budde mcp251xfd_chip_get_mode(const struct mcp251xfd_priv *priv, u8 *mode)
5091f0e21a0SMarc Kleine-Budde {
5101f0e21a0SMarc Kleine-Budde 	u32 val;
5111f0e21a0SMarc Kleine-Budde 	int err;
5121f0e21a0SMarc Kleine-Budde 
513eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_CON, &val);
5141f0e21a0SMarc Kleine-Budde 	if (err)
5151f0e21a0SMarc Kleine-Budde 		return err;
5161f0e21a0SMarc Kleine-Budde 
517eb79a267SMarc Kleine-Budde 	*mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, val);
5181f0e21a0SMarc Kleine-Budde 
5191f0e21a0SMarc Kleine-Budde 	return 0;
5201f0e21a0SMarc Kleine-Budde }
5211f0e21a0SMarc Kleine-Budde 
5221f0e21a0SMarc Kleine-Budde static int
523eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
5241f0e21a0SMarc Kleine-Budde 			  const u8 mode_req, bool nowait)
5251f0e21a0SMarc Kleine-Budde {
5261f0e21a0SMarc Kleine-Budde 	u32 con, con_reqop;
5271f0e21a0SMarc Kleine-Budde 	int err;
5281f0e21a0SMarc Kleine-Budde 
529eb79a267SMarc Kleine-Budde 	con_reqop = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK, mode_req);
530eb79a267SMarc Kleine-Budde 	err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CON,
531eb79a267SMarc Kleine-Budde 				 MCP251XFD_REG_CON_REQOP_MASK, con_reqop);
5321f0e21a0SMarc Kleine-Budde 	if (err)
5331f0e21a0SMarc Kleine-Budde 		return err;
5341f0e21a0SMarc Kleine-Budde 
535eb79a267SMarc Kleine-Budde 	if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait)
5361f0e21a0SMarc Kleine-Budde 		return 0;
5371f0e21a0SMarc Kleine-Budde 
538eb79a267SMarc Kleine-Budde 	err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con,
539eb79a267SMarc Kleine-Budde 				       FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK,
5401f0e21a0SMarc Kleine-Budde 						 con) == mode_req,
541eb79a267SMarc Kleine-Budde 				       MCP251XFD_POLL_SLEEP_US,
542eb79a267SMarc Kleine-Budde 				       MCP251XFD_POLL_TIMEOUT_US);
5431f0e21a0SMarc Kleine-Budde 	if (err) {
544eb79a267SMarc Kleine-Budde 		u8 mode = FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK, con);
5451f0e21a0SMarc Kleine-Budde 
5461f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
5471f0e21a0SMarc Kleine-Budde 			   "Controller failed to enter mode %s Mode (%u) and stays in %s Mode (%u).\n",
548eb79a267SMarc Kleine-Budde 			   mcp251xfd_get_mode_str(mode_req), mode_req,
549eb79a267SMarc Kleine-Budde 			   mcp251xfd_get_mode_str(mode), mode);
5501f0e21a0SMarc Kleine-Budde 		return err;
5511f0e21a0SMarc Kleine-Budde 	}
5521f0e21a0SMarc Kleine-Budde 
5531f0e21a0SMarc Kleine-Budde 	return 0;
5541f0e21a0SMarc Kleine-Budde }
5551f0e21a0SMarc Kleine-Budde 
5561f0e21a0SMarc Kleine-Budde static inline int
557eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
5581f0e21a0SMarc Kleine-Budde 			const u8 mode_req)
5591f0e21a0SMarc Kleine-Budde {
560eb79a267SMarc Kleine-Budde 	return __mcp251xfd_chip_set_mode(priv, mode_req, false);
5611f0e21a0SMarc Kleine-Budde }
5621f0e21a0SMarc Kleine-Budde 
563b558e200SMarc Kleine-Budde static inline int __maybe_unused
564eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_mode_nowait(const struct mcp251xfd_priv *priv,
5651f0e21a0SMarc Kleine-Budde 			       const u8 mode_req)
5661f0e21a0SMarc Kleine-Budde {
567eb79a267SMarc Kleine-Budde 	return __mcp251xfd_chip_set_mode(priv, mode_req, true);
5681f0e21a0SMarc Kleine-Budde }
5691f0e21a0SMarc Kleine-Budde 
570eb79a267SMarc Kleine-Budde static inline bool mcp251xfd_osc_invalid(u32 reg)
5711f0e21a0SMarc Kleine-Budde {
5721f0e21a0SMarc Kleine-Budde 	return reg == 0x0 || reg == 0xffffffff;
5731f0e21a0SMarc Kleine-Budde }
5741f0e21a0SMarc Kleine-Budde 
575eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_clock_enable(const struct mcp251xfd_priv *priv)
5761f0e21a0SMarc Kleine-Budde {
5771f0e21a0SMarc Kleine-Budde 	u32 osc, osc_reference, osc_mask;
5781f0e21a0SMarc Kleine-Budde 	int err;
5791f0e21a0SMarc Kleine-Budde 
5801f0e21a0SMarc Kleine-Budde 	/* Set Power On Defaults for "Clock Output Divisor" and remove
5811f0e21a0SMarc Kleine-Budde 	 * "Oscillator Disable" bit.
5821f0e21a0SMarc Kleine-Budde 	 */
583eb79a267SMarc Kleine-Budde 	osc = FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK,
584eb79a267SMarc Kleine-Budde 			 MCP251XFD_REG_OSC_CLKODIV_10);
585eb79a267SMarc Kleine-Budde 	osc_reference = MCP251XFD_REG_OSC_OSCRDY;
586eb79a267SMarc Kleine-Budde 	osc_mask = MCP251XFD_REG_OSC_OSCRDY | MCP251XFD_REG_OSC_PLLRDY;
5871f0e21a0SMarc Kleine-Budde 
5881f0e21a0SMarc Kleine-Budde 	/* Note:
5891f0e21a0SMarc Kleine-Budde 	 *
5901f0e21a0SMarc Kleine-Budde 	 * If the controller is in Sleep Mode the following write only
5911f0e21a0SMarc Kleine-Budde 	 * removes the "Oscillator Disable" bit and powers it up. All
5921f0e21a0SMarc Kleine-Budde 	 * other bits are unaffected.
5931f0e21a0SMarc Kleine-Budde 	 */
594eb79a267SMarc Kleine-Budde 	err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc);
5951f0e21a0SMarc Kleine-Budde 	if (err)
5961f0e21a0SMarc Kleine-Budde 		return err;
5971f0e21a0SMarc Kleine-Budde 
5981f0e21a0SMarc Kleine-Budde 	/* Wait for "Oscillator Ready" bit */
599eb79a267SMarc Kleine-Budde 	err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_OSC, osc,
6001f0e21a0SMarc Kleine-Budde 				       (osc & osc_mask) == osc_reference,
601eb79a267SMarc Kleine-Budde 				       MCP251XFD_OSC_STAB_SLEEP_US,
602eb79a267SMarc Kleine-Budde 				       MCP251XFD_OSC_STAB_TIMEOUT_US);
603eb79a267SMarc Kleine-Budde 	if (mcp251xfd_osc_invalid(osc)) {
6041f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
6051f0e21a0SMarc Kleine-Budde 			   "Failed to detect %s (osc=0x%08x).\n",
606eb79a267SMarc Kleine-Budde 			   mcp251xfd_get_model_str(priv), osc);
6071f0e21a0SMarc Kleine-Budde 		return -ENODEV;
6081f0e21a0SMarc Kleine-Budde 	} else if (err == -ETIMEDOUT) {
6091f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
6101f0e21a0SMarc Kleine-Budde 			   "Timeout waiting for Oscillator Ready (osc=0x%08x, osc_reference=0x%08x)\n",
6111f0e21a0SMarc Kleine-Budde 			   osc, osc_reference);
6121f0e21a0SMarc Kleine-Budde 		return -ETIMEDOUT;
6131f0e21a0SMarc Kleine-Budde 	}
6141f0e21a0SMarc Kleine-Budde 
615dfe99ba2SMarc Kleine-Budde 	return err;
6161f0e21a0SMarc Kleine-Budde }
6171f0e21a0SMarc Kleine-Budde 
618eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_do(const struct mcp251xfd_priv *priv)
6191f0e21a0SMarc Kleine-Budde {
620eb79a267SMarc Kleine-Budde 	const __be16 cmd = mcp251xfd_cmd_reset();
6211f0e21a0SMarc Kleine-Budde 	int err;
6221f0e21a0SMarc Kleine-Budde 
6231f0e21a0SMarc Kleine-Budde 	/* The Set Mode and SPI Reset command only seems to works if
6241f0e21a0SMarc Kleine-Budde 	 * the controller is not in Sleep Mode.
6251f0e21a0SMarc Kleine-Budde 	 */
626eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_clock_enable(priv);
6271f0e21a0SMarc Kleine-Budde 	if (err)
6281f0e21a0SMarc Kleine-Budde 		return err;
6291f0e21a0SMarc Kleine-Budde 
630eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_CONFIG);
6311f0e21a0SMarc Kleine-Budde 	if (err)
6321f0e21a0SMarc Kleine-Budde 		return err;
6331f0e21a0SMarc Kleine-Budde 
6341f0e21a0SMarc Kleine-Budde 	/* spi_write_then_read() works with non DMA-safe buffers */
6351f0e21a0SMarc Kleine-Budde 	return spi_write_then_read(priv->spi, &cmd, sizeof(cmd), NULL, 0);
6361f0e21a0SMarc Kleine-Budde }
6371f0e21a0SMarc Kleine-Budde 
638eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset_check(const struct mcp251xfd_priv *priv)
6391f0e21a0SMarc Kleine-Budde {
6401f0e21a0SMarc Kleine-Budde 	u32 osc, osc_reference;
6411f0e21a0SMarc Kleine-Budde 	u8 mode;
6421f0e21a0SMarc Kleine-Budde 	int err;
6431f0e21a0SMarc Kleine-Budde 
644eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_get_mode(priv, &mode);
6451f0e21a0SMarc Kleine-Budde 	if (err)
6461f0e21a0SMarc Kleine-Budde 		return err;
6471f0e21a0SMarc Kleine-Budde 
648eb79a267SMarc Kleine-Budde 	if (mode != MCP251XFD_REG_CON_MODE_CONFIG) {
6491f0e21a0SMarc Kleine-Budde 		netdev_info(priv->ndev,
6501f0e21a0SMarc Kleine-Budde 			    "Controller not in Config Mode after reset, but in %s Mode (%u).\n",
651eb79a267SMarc Kleine-Budde 			    mcp251xfd_get_mode_str(mode), mode);
6521f0e21a0SMarc Kleine-Budde 		return -ETIMEDOUT;
6531f0e21a0SMarc Kleine-Budde 	}
6541f0e21a0SMarc Kleine-Budde 
655eb79a267SMarc Kleine-Budde 	osc_reference = MCP251XFD_REG_OSC_OSCRDY |
656eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK,
657eb79a267SMarc Kleine-Budde 			   MCP251XFD_REG_OSC_CLKODIV_10);
6581f0e21a0SMarc Kleine-Budde 
6591f0e21a0SMarc Kleine-Budde 	/* check reset defaults of OSC reg */
660eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc);
6611f0e21a0SMarc Kleine-Budde 	if (err)
6621f0e21a0SMarc Kleine-Budde 		return err;
6631f0e21a0SMarc Kleine-Budde 
6641f0e21a0SMarc Kleine-Budde 	if (osc != osc_reference) {
6651f0e21a0SMarc Kleine-Budde 		netdev_info(priv->ndev,
666f93486a7SMarc Kleine-Budde 			    "Controller failed to reset. osc=0x%08x, reference value=0x%08x.\n",
6671f0e21a0SMarc Kleine-Budde 			    osc, osc_reference);
6681f0e21a0SMarc Kleine-Budde 		return -ETIMEDOUT;
6691f0e21a0SMarc Kleine-Budde 	}
6701f0e21a0SMarc Kleine-Budde 
6711f0e21a0SMarc Kleine-Budde 	return 0;
6721f0e21a0SMarc Kleine-Budde }
6731f0e21a0SMarc Kleine-Budde 
674eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_softreset(const struct mcp251xfd_priv *priv)
6751f0e21a0SMarc Kleine-Budde {
6761f0e21a0SMarc Kleine-Budde 	int err, i;
6771f0e21a0SMarc Kleine-Budde 
678eb79a267SMarc Kleine-Budde 	for (i = 0; i < MCP251XFD_SOFTRESET_RETRIES_MAX; i++) {
6791f0e21a0SMarc Kleine-Budde 		if (i)
6801f0e21a0SMarc Kleine-Budde 			netdev_info(priv->ndev,
681f93486a7SMarc Kleine-Budde 				    "Retrying to reset controller.\n");
6821f0e21a0SMarc Kleine-Budde 
683eb79a267SMarc Kleine-Budde 		err = mcp251xfd_chip_softreset_do(priv);
6841f0e21a0SMarc Kleine-Budde 		if (err == -ETIMEDOUT)
6851f0e21a0SMarc Kleine-Budde 			continue;
6861f0e21a0SMarc Kleine-Budde 		if (err)
6871f0e21a0SMarc Kleine-Budde 			return err;
6881f0e21a0SMarc Kleine-Budde 
689eb79a267SMarc Kleine-Budde 		err = mcp251xfd_chip_softreset_check(priv);
6901f0e21a0SMarc Kleine-Budde 		if (err == -ETIMEDOUT)
6911f0e21a0SMarc Kleine-Budde 			continue;
6921f0e21a0SMarc Kleine-Budde 		if (err)
6931f0e21a0SMarc Kleine-Budde 			return err;
6941f0e21a0SMarc Kleine-Budde 
6951f0e21a0SMarc Kleine-Budde 		return 0;
6961f0e21a0SMarc Kleine-Budde 	}
6971f0e21a0SMarc Kleine-Budde 
6981f0e21a0SMarc Kleine-Budde 	return err;
6991f0e21a0SMarc Kleine-Budde }
7001f0e21a0SMarc Kleine-Budde 
701eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_clock_init(const struct mcp251xfd_priv *priv)
7021f0e21a0SMarc Kleine-Budde {
7031f0e21a0SMarc Kleine-Budde 	u32 osc;
7041f0e21a0SMarc Kleine-Budde 	int err;
7051f0e21a0SMarc Kleine-Budde 
7061f0e21a0SMarc Kleine-Budde 	/* Activate Low Power Mode on Oscillator Disable. This only
7071f0e21a0SMarc Kleine-Budde 	 * works on the MCP2518FD. The MCP2517FD will go into normal
7081f0e21a0SMarc Kleine-Budde 	 * Sleep Mode instead.
7091f0e21a0SMarc Kleine-Budde 	 */
710eb79a267SMarc Kleine-Budde 	osc = MCP251XFD_REG_OSC_LPMEN |
711eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_OSC_CLKODIV_MASK,
712eb79a267SMarc Kleine-Budde 			   MCP251XFD_REG_OSC_CLKODIV_10);
713eb79a267SMarc Kleine-Budde 	err = regmap_write(priv->map_reg, MCP251XFD_REG_OSC, osc);
7141f0e21a0SMarc Kleine-Budde 	if (err)
7151f0e21a0SMarc Kleine-Budde 		return err;
7161f0e21a0SMarc Kleine-Budde 
7171f0e21a0SMarc Kleine-Budde 	/* Set Time Base Counter Prescaler to 1.
7181f0e21a0SMarc Kleine-Budde 	 *
7191f0e21a0SMarc Kleine-Budde 	 * This means an overflow of the 32 bit Time Base Counter
7201f0e21a0SMarc Kleine-Budde 	 * register at 40 MHz every 107 seconds.
7211f0e21a0SMarc Kleine-Budde 	 */
722eb79a267SMarc Kleine-Budde 	return regmap_write(priv->map_reg, MCP251XFD_REG_TSCON,
723eb79a267SMarc Kleine-Budde 			    MCP251XFD_REG_TSCON_TBCEN);
7241f0e21a0SMarc Kleine-Budde }
7251f0e21a0SMarc Kleine-Budde 
726eb79a267SMarc Kleine-Budde static int mcp251xfd_set_bittiming(const struct mcp251xfd_priv *priv)
7271f0e21a0SMarc Kleine-Budde {
7281f0e21a0SMarc Kleine-Budde 	const struct can_bittiming *bt = &priv->can.bittiming;
7291f0e21a0SMarc Kleine-Budde 	const struct can_bittiming *dbt = &priv->can.data_bittiming;
7301f0e21a0SMarc Kleine-Budde 	u32 val = 0;
7311f0e21a0SMarc Kleine-Budde 	s8 tdco;
7321f0e21a0SMarc Kleine-Budde 	int err;
7331f0e21a0SMarc Kleine-Budde 
7341f0e21a0SMarc Kleine-Budde 	/* CAN Control Register
7351f0e21a0SMarc Kleine-Budde 	 *
7361f0e21a0SMarc Kleine-Budde 	 * - no transmit bandwidth sharing
7371f0e21a0SMarc Kleine-Budde 	 * - config mode
7381f0e21a0SMarc Kleine-Budde 	 * - disable transmit queue
7391f0e21a0SMarc Kleine-Budde 	 * - store in transmit FIFO event
7401f0e21a0SMarc Kleine-Budde 	 * - transition to restricted operation mode on system error
7411f0e21a0SMarc Kleine-Budde 	 * - ESI is transmitted recessive when ESI of message is high or
7421f0e21a0SMarc Kleine-Budde 	 *   CAN controller error passive
7431f0e21a0SMarc Kleine-Budde 	 * - restricted retransmission attempts,
7441f0e21a0SMarc Kleine-Budde 	 *   use TQXCON_TXAT and FIFOCON_TXAT
7451f0e21a0SMarc Kleine-Budde 	 * - wake-up filter bits T11FILTER
7461f0e21a0SMarc Kleine-Budde 	 * - use CAN bus line filter for wakeup
7471f0e21a0SMarc Kleine-Budde 	 * - protocol exception is treated as a form error
7481f0e21a0SMarc Kleine-Budde 	 * - Do not compare data bytes
7491f0e21a0SMarc Kleine-Budde 	 */
750eb79a267SMarc Kleine-Budde 	val = FIELD_PREP(MCP251XFD_REG_CON_REQOP_MASK,
751eb79a267SMarc Kleine-Budde 			 MCP251XFD_REG_CON_MODE_CONFIG) |
752eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_CON_STEF |
753eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_CON_ESIGM |
754eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_CON_RTXAT |
755eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_CON_WFT_MASK,
756eb79a267SMarc Kleine-Budde 			   MCP251XFD_REG_CON_WFT_T11FILTER) |
757eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_CON_WAKFIL |
758eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_CON_PXEDIS;
7591f0e21a0SMarc Kleine-Budde 
7601f0e21a0SMarc Kleine-Budde 	if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO))
761eb79a267SMarc Kleine-Budde 		val |= MCP251XFD_REG_CON_ISOCRCEN;
7621f0e21a0SMarc Kleine-Budde 
763eb79a267SMarc Kleine-Budde 	err = regmap_write(priv->map_reg, MCP251XFD_REG_CON, val);
7641f0e21a0SMarc Kleine-Budde 	if (err)
7651f0e21a0SMarc Kleine-Budde 		return err;
7661f0e21a0SMarc Kleine-Budde 
7671f0e21a0SMarc Kleine-Budde 	/* Nominal Bit Time */
768eb79a267SMarc Kleine-Budde 	val = FIELD_PREP(MCP251XFD_REG_NBTCFG_BRP_MASK, bt->brp - 1) |
769eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG1_MASK,
7701f0e21a0SMarc Kleine-Budde 			   bt->prop_seg + bt->phase_seg1 - 1) |
771eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_NBTCFG_TSEG2_MASK,
7721f0e21a0SMarc Kleine-Budde 			   bt->phase_seg2 - 1) |
773eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_NBTCFG_SJW_MASK, bt->sjw - 1);
7741f0e21a0SMarc Kleine-Budde 
775eb79a267SMarc Kleine-Budde 	err = regmap_write(priv->map_reg, MCP251XFD_REG_NBTCFG, val);
7761f0e21a0SMarc Kleine-Budde 	if (err)
7771f0e21a0SMarc Kleine-Budde 		return err;
7781f0e21a0SMarc Kleine-Budde 
7791f0e21a0SMarc Kleine-Budde 	if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD))
7801f0e21a0SMarc Kleine-Budde 		return 0;
7811f0e21a0SMarc Kleine-Budde 
7821f0e21a0SMarc Kleine-Budde 	/* Data Bit Time */
783eb79a267SMarc Kleine-Budde 	val = FIELD_PREP(MCP251XFD_REG_DBTCFG_BRP_MASK, dbt->brp - 1) |
784eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG1_MASK,
7851f0e21a0SMarc Kleine-Budde 			   dbt->prop_seg + dbt->phase_seg1 - 1) |
786eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_DBTCFG_TSEG2_MASK,
7871f0e21a0SMarc Kleine-Budde 			   dbt->phase_seg2 - 1) |
788eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_DBTCFG_SJW_MASK, dbt->sjw - 1);
7891f0e21a0SMarc Kleine-Budde 
790eb79a267SMarc Kleine-Budde 	err = regmap_write(priv->map_reg, MCP251XFD_REG_DBTCFG, val);
7911f0e21a0SMarc Kleine-Budde 	if (err)
7921f0e21a0SMarc Kleine-Budde 		return err;
7931f0e21a0SMarc Kleine-Budde 
7941f0e21a0SMarc Kleine-Budde 	/* Transmitter Delay Compensation */
7951f0e21a0SMarc Kleine-Budde 	tdco = clamp_t(int, dbt->brp * (dbt->prop_seg + dbt->phase_seg1),
7961f0e21a0SMarc Kleine-Budde 		       -64, 63);
797eb79a267SMarc Kleine-Budde 	val = FIELD_PREP(MCP251XFD_REG_TDC_TDCMOD_MASK,
798eb79a267SMarc Kleine-Budde 			 MCP251XFD_REG_TDC_TDCMOD_AUTO) |
799eb79a267SMarc Kleine-Budde 		FIELD_PREP(MCP251XFD_REG_TDC_TDCO_MASK, tdco);
8001f0e21a0SMarc Kleine-Budde 
801eb79a267SMarc Kleine-Budde 	return regmap_write(priv->map_reg, MCP251XFD_REG_TDC, val);
8021f0e21a0SMarc Kleine-Budde }
8031f0e21a0SMarc Kleine-Budde 
804eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_enable(const struct mcp251xfd_priv *priv)
8051f0e21a0SMarc Kleine-Budde {
8061f0e21a0SMarc Kleine-Budde 	u32 val;
8071f0e21a0SMarc Kleine-Budde 
8081f0e21a0SMarc Kleine-Budde 	if (!priv->rx_int)
8091f0e21a0SMarc Kleine-Budde 		return 0;
8101f0e21a0SMarc Kleine-Budde 
8111f0e21a0SMarc Kleine-Budde 	/* Configure GPIOs:
8121f0e21a0SMarc Kleine-Budde 	 * - PIN0: GPIO Input
8131f0e21a0SMarc Kleine-Budde 	 * - PIN1: GPIO Input/RX Interrupt
8141f0e21a0SMarc Kleine-Budde 	 *
8151f0e21a0SMarc Kleine-Budde 	 * PIN1 must be Input, otherwise there is a glitch on the
8161f0e21a0SMarc Kleine-Budde 	 * rx-INT line. It happens between setting the PIN as output
8171f0e21a0SMarc Kleine-Budde 	 * (in the first byte of the SPI transfer) and configuring the
8181f0e21a0SMarc Kleine-Budde 	 * PIN as interrupt (in the last byte of the SPI transfer).
8191f0e21a0SMarc Kleine-Budde 	 */
820eb79a267SMarc Kleine-Budde 	val = MCP251XFD_REG_IOCON_PM0 | MCP251XFD_REG_IOCON_TRIS1 |
821eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_IOCON_TRIS0;
822eb79a267SMarc Kleine-Budde 	return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val);
8231f0e21a0SMarc Kleine-Budde }
8241f0e21a0SMarc Kleine-Budde 
825eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_rx_int_disable(const struct mcp251xfd_priv *priv)
8261f0e21a0SMarc Kleine-Budde {
8271f0e21a0SMarc Kleine-Budde 	u32 val;
8281f0e21a0SMarc Kleine-Budde 
8291f0e21a0SMarc Kleine-Budde 	if (!priv->rx_int)
8301f0e21a0SMarc Kleine-Budde 		return 0;
8311f0e21a0SMarc Kleine-Budde 
8321f0e21a0SMarc Kleine-Budde 	/* Configure GPIOs:
8331f0e21a0SMarc Kleine-Budde 	 * - PIN0: GPIO Input
8341f0e21a0SMarc Kleine-Budde 	 * - PIN1: GPIO Input
8351f0e21a0SMarc Kleine-Budde 	 */
836eb79a267SMarc Kleine-Budde 	val = MCP251XFD_REG_IOCON_PM1 | MCP251XFD_REG_IOCON_PM0 |
837eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_IOCON_TRIS1 | MCP251XFD_REG_IOCON_TRIS0;
838eb79a267SMarc Kleine-Budde 	return regmap_write(priv->map_reg, MCP251XFD_REG_IOCON, val);
8391f0e21a0SMarc Kleine-Budde }
8401f0e21a0SMarc Kleine-Budde 
8411f0e21a0SMarc Kleine-Budde static int
842eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_fifo_init_one(const struct mcp251xfd_priv *priv,
843eb79a267SMarc Kleine-Budde 				const struct mcp251xfd_rx_ring *ring)
8441f0e21a0SMarc Kleine-Budde {
8451f0e21a0SMarc Kleine-Budde 	u32 fifo_con;
8461f0e21a0SMarc Kleine-Budde 
8471f0e21a0SMarc Kleine-Budde 	/* Enable RXOVIE on _all_ RX FIFOs, not just the last one.
8481f0e21a0SMarc Kleine-Budde 	 *
8491f0e21a0SMarc Kleine-Budde 	 * FIFOs hit by a RX MAB overflow and RXOVIE enabled will
8501f0e21a0SMarc Kleine-Budde 	 * generate a RXOVIF, use this to properly detect RX MAB
8511f0e21a0SMarc Kleine-Budde 	 * overflows.
8521f0e21a0SMarc Kleine-Budde 	 */
853eb79a267SMarc Kleine-Budde 	fifo_con = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK,
8541f0e21a0SMarc Kleine-Budde 			      ring->obj_num - 1) |
855eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_FIFOCON_RXTSEN |
856eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_FIFOCON_RXOVIE |
857eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_FIFOCON_TFNRFNIE;
8581f0e21a0SMarc Kleine-Budde 
8591f0e21a0SMarc Kleine-Budde 	if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD))
860eb79a267SMarc Kleine-Budde 		fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
861eb79a267SMarc Kleine-Budde 				       MCP251XFD_REG_FIFOCON_PLSIZE_64);
8621f0e21a0SMarc Kleine-Budde 	else
863eb79a267SMarc Kleine-Budde 		fifo_con |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
864eb79a267SMarc Kleine-Budde 				       MCP251XFD_REG_FIFOCON_PLSIZE_8);
8651f0e21a0SMarc Kleine-Budde 
8661f0e21a0SMarc Kleine-Budde 	return regmap_write(priv->map_reg,
867eb79a267SMarc Kleine-Budde 			    MCP251XFD_REG_FIFOCON(ring->fifo_nr), fifo_con);
8681f0e21a0SMarc Kleine-Budde }
8691f0e21a0SMarc Kleine-Budde 
8701f0e21a0SMarc Kleine-Budde static int
871eb79a267SMarc Kleine-Budde mcp251xfd_chip_rx_filter_init_one(const struct mcp251xfd_priv *priv,
872eb79a267SMarc Kleine-Budde 				  const struct mcp251xfd_rx_ring *ring)
8731f0e21a0SMarc Kleine-Budde {
8741f0e21a0SMarc Kleine-Budde 	u32 fltcon;
8751f0e21a0SMarc Kleine-Budde 
876eb79a267SMarc Kleine-Budde 	fltcon = MCP251XFD_REG_FLTCON_FLTEN(ring->nr) |
877eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_FLTCON_FBP(ring->nr, ring->fifo_nr);
8781f0e21a0SMarc Kleine-Budde 
8791f0e21a0SMarc Kleine-Budde 	return regmap_update_bits(priv->map_reg,
880eb79a267SMarc Kleine-Budde 				  MCP251XFD_REG_FLTCON(ring->nr >> 2),
881eb79a267SMarc Kleine-Budde 				  MCP251XFD_REG_FLTCON_FLT_MASK(ring->nr),
8821f0e21a0SMarc Kleine-Budde 				  fltcon);
8831f0e21a0SMarc Kleine-Budde }
8841f0e21a0SMarc Kleine-Budde 
885eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv)
8861f0e21a0SMarc Kleine-Budde {
887eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
888eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_rx_ring *rx_ring;
8891f0e21a0SMarc Kleine-Budde 	u32 val;
8901f0e21a0SMarc Kleine-Budde 	int err, n;
8911f0e21a0SMarc Kleine-Budde 
8921f0e21a0SMarc Kleine-Budde 	/* TEF */
893eb79a267SMarc Kleine-Budde 	val = FIELD_PREP(MCP251XFD_REG_TEFCON_FSIZE_MASK,
8941f0e21a0SMarc Kleine-Budde 			 tx_ring->obj_num - 1) |
895eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_TEFCON_TEFTSEN |
896eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_TEFCON_TEFOVIE |
897eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_TEFCON_TEFNEIE;
8981f0e21a0SMarc Kleine-Budde 
899eb79a267SMarc Kleine-Budde 	err = regmap_write(priv->map_reg, MCP251XFD_REG_TEFCON, val);
9001f0e21a0SMarc Kleine-Budde 	if (err)
9011f0e21a0SMarc Kleine-Budde 		return err;
9021f0e21a0SMarc Kleine-Budde 
9031f0e21a0SMarc Kleine-Budde 	/* FIFO 1 - TX */
904eb79a267SMarc Kleine-Budde 	val = FIELD_PREP(MCP251XFD_REG_FIFOCON_FSIZE_MASK,
9051f0e21a0SMarc Kleine-Budde 			 tx_ring->obj_num - 1) |
906eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_FIFOCON_TXEN |
907eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_FIFOCON_TXATIE;
9081f0e21a0SMarc Kleine-Budde 
9091f0e21a0SMarc Kleine-Budde 	if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD))
910eb79a267SMarc Kleine-Budde 		val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
911eb79a267SMarc Kleine-Budde 				  MCP251XFD_REG_FIFOCON_PLSIZE_64);
9121f0e21a0SMarc Kleine-Budde 	else
913eb79a267SMarc Kleine-Budde 		val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_PLSIZE_MASK,
914eb79a267SMarc Kleine-Budde 				  MCP251XFD_REG_FIFOCON_PLSIZE_8);
9151f0e21a0SMarc Kleine-Budde 
9161f0e21a0SMarc Kleine-Budde 	if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
917eb79a267SMarc Kleine-Budde 		val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK,
918eb79a267SMarc Kleine-Budde 				  MCP251XFD_REG_FIFOCON_TXAT_ONE_SHOT);
9191f0e21a0SMarc Kleine-Budde 	else
920eb79a267SMarc Kleine-Budde 		val |= FIELD_PREP(MCP251XFD_REG_FIFOCON_TXAT_MASK,
921eb79a267SMarc Kleine-Budde 				  MCP251XFD_REG_FIFOCON_TXAT_UNLIMITED);
9221f0e21a0SMarc Kleine-Budde 
9231f0e21a0SMarc Kleine-Budde 	err = regmap_write(priv->map_reg,
924eb79a267SMarc Kleine-Budde 			   MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO),
9251f0e21a0SMarc Kleine-Budde 			   val);
9261f0e21a0SMarc Kleine-Budde 	if (err)
9271f0e21a0SMarc Kleine-Budde 		return err;
9281f0e21a0SMarc Kleine-Budde 
9291f0e21a0SMarc Kleine-Budde 	/* RX FIFOs */
930eb79a267SMarc Kleine-Budde 	mcp251xfd_for_each_rx_ring(priv, rx_ring, n) {
931eb79a267SMarc Kleine-Budde 		err = mcp251xfd_chip_rx_fifo_init_one(priv, rx_ring);
9321f0e21a0SMarc Kleine-Budde 		if (err)
9331f0e21a0SMarc Kleine-Budde 			return err;
9341f0e21a0SMarc Kleine-Budde 
935eb79a267SMarc Kleine-Budde 		err = mcp251xfd_chip_rx_filter_init_one(priv, rx_ring);
9361f0e21a0SMarc Kleine-Budde 		if (err)
9371f0e21a0SMarc Kleine-Budde 			return err;
9381f0e21a0SMarc Kleine-Budde 	}
9391f0e21a0SMarc Kleine-Budde 
9401f0e21a0SMarc Kleine-Budde 	return 0;
9411f0e21a0SMarc Kleine-Budde }
9421f0e21a0SMarc Kleine-Budde 
943eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_ecc_init(struct mcp251xfd_priv *priv)
9441f0e21a0SMarc Kleine-Budde {
945eb79a267SMarc Kleine-Budde 	struct mcp251xfd_ecc *ecc = &priv->ecc;
9461f0e21a0SMarc Kleine-Budde 	void *ram;
9471f0e21a0SMarc Kleine-Budde 	u32 val = 0;
9481f0e21a0SMarc Kleine-Budde 	int err;
9491f0e21a0SMarc Kleine-Budde 
9501f0e21a0SMarc Kleine-Budde 	ecc->ecc_stat = 0;
9511f0e21a0SMarc Kleine-Budde 
952eb79a267SMarc Kleine-Budde 	if (priv->devtype_data.quirks & MCP251XFD_QUIRK_ECC)
953eb79a267SMarc Kleine-Budde 		val = MCP251XFD_REG_ECCCON_ECCEN;
9541f0e21a0SMarc Kleine-Budde 
955eb79a267SMarc Kleine-Budde 	err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON,
956eb79a267SMarc Kleine-Budde 				 MCP251XFD_REG_ECCCON_ECCEN, val);
9571f0e21a0SMarc Kleine-Budde 	if (err)
9581f0e21a0SMarc Kleine-Budde 		return err;
9591f0e21a0SMarc Kleine-Budde 
960eb79a267SMarc Kleine-Budde 	ram = kzalloc(MCP251XFD_RAM_SIZE, GFP_KERNEL);
9611f0e21a0SMarc Kleine-Budde 	if (!ram)
9621f0e21a0SMarc Kleine-Budde 		return -ENOMEM;
9631f0e21a0SMarc Kleine-Budde 
964eb79a267SMarc Kleine-Budde 	err = regmap_raw_write(priv->map_reg, MCP251XFD_RAM_START, ram,
965eb79a267SMarc Kleine-Budde 			       MCP251XFD_RAM_SIZE);
9661f0e21a0SMarc Kleine-Budde 	kfree(ram);
9671f0e21a0SMarc Kleine-Budde 
9681f0e21a0SMarc Kleine-Budde 	return err;
9691f0e21a0SMarc Kleine-Budde }
9701f0e21a0SMarc Kleine-Budde 
971eb79a267SMarc Kleine-Budde static inline void mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv *priv)
9721f0e21a0SMarc Kleine-Budde {
973eb79a267SMarc Kleine-Budde 	struct mcp251xfd_ecc *ecc = &priv->ecc;
9741f0e21a0SMarc Kleine-Budde 
9751f0e21a0SMarc Kleine-Budde 	ecc->ecc_stat = 0;
9761f0e21a0SMarc Kleine-Budde }
9771f0e21a0SMarc Kleine-Budde 
978eb79a267SMarc Kleine-Budde static u8 mcp251xfd_get_normal_mode(const struct mcp251xfd_priv *priv)
9791f0e21a0SMarc Kleine-Budde {
9801f0e21a0SMarc Kleine-Budde 	u8 mode;
9811f0e21a0SMarc Kleine-Budde 
982ee42bedcSManivannan Sadhasivam 
983ee42bedcSManivannan Sadhasivam 	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
984ee42bedcSManivannan Sadhasivam 		mode = MCP251XFD_REG_CON_MODE_INT_LOOPBACK;
985ee42bedcSManivannan Sadhasivam 	else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
986eb79a267SMarc Kleine-Budde 		mode = MCP251XFD_REG_CON_MODE_LISTENONLY;
9871f0e21a0SMarc Kleine-Budde 	else if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
988eb79a267SMarc Kleine-Budde 		mode = MCP251XFD_REG_CON_MODE_MIXED;
9891f0e21a0SMarc Kleine-Budde 	else
990eb79a267SMarc Kleine-Budde 		mode = MCP251XFD_REG_CON_MODE_CAN2_0;
9911f0e21a0SMarc Kleine-Budde 
9921f0e21a0SMarc Kleine-Budde 	return mode;
9931f0e21a0SMarc Kleine-Budde }
9941f0e21a0SMarc Kleine-Budde 
9951f0e21a0SMarc Kleine-Budde static int
996eb79a267SMarc Kleine-Budde __mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv,
9971f0e21a0SMarc Kleine-Budde 				 bool nowait)
9981f0e21a0SMarc Kleine-Budde {
9991f0e21a0SMarc Kleine-Budde 	u8 mode;
10001f0e21a0SMarc Kleine-Budde 
1001eb79a267SMarc Kleine-Budde 	mode = mcp251xfd_get_normal_mode(priv);
10021f0e21a0SMarc Kleine-Budde 
1003eb79a267SMarc Kleine-Budde 	return __mcp251xfd_chip_set_mode(priv, mode, nowait);
10041f0e21a0SMarc Kleine-Budde }
10051f0e21a0SMarc Kleine-Budde 
10061f0e21a0SMarc Kleine-Budde static inline int
1007eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode(const struct mcp251xfd_priv *priv)
10081f0e21a0SMarc Kleine-Budde {
1009eb79a267SMarc Kleine-Budde 	return __mcp251xfd_chip_set_normal_mode(priv, false);
10101f0e21a0SMarc Kleine-Budde }
10111f0e21a0SMarc Kleine-Budde 
10121f0e21a0SMarc Kleine-Budde static inline int
1013eb79a267SMarc Kleine-Budde mcp251xfd_chip_set_normal_mode_nowait(const struct mcp251xfd_priv *priv)
10141f0e21a0SMarc Kleine-Budde {
1015eb79a267SMarc Kleine-Budde 	return __mcp251xfd_chip_set_normal_mode(priv, true);
10161f0e21a0SMarc Kleine-Budde }
10171f0e21a0SMarc Kleine-Budde 
1018eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_enable(const struct mcp251xfd_priv *priv)
10191f0e21a0SMarc Kleine-Budde {
10201f0e21a0SMarc Kleine-Budde 	u32 val;
10211f0e21a0SMarc Kleine-Budde 	int err;
10221f0e21a0SMarc Kleine-Budde 
1023eb79a267SMarc Kleine-Budde 	val = MCP251XFD_REG_CRC_FERRIE | MCP251XFD_REG_CRC_CRCERRIE;
1024eb79a267SMarc Kleine-Budde 	err = regmap_write(priv->map_reg, MCP251XFD_REG_CRC, val);
10251f0e21a0SMarc Kleine-Budde 	if (err)
10261f0e21a0SMarc Kleine-Budde 		return err;
10271f0e21a0SMarc Kleine-Budde 
1028eb79a267SMarc Kleine-Budde 	val = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE;
1029eb79a267SMarc Kleine-Budde 	err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON, val, val);
10301f0e21a0SMarc Kleine-Budde 	if (err)
10311f0e21a0SMarc Kleine-Budde 		return err;
10321f0e21a0SMarc Kleine-Budde 
1033eb79a267SMarc Kleine-Budde 	val = MCP251XFD_REG_INT_CERRIE |
1034eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_INT_SERRIE |
1035eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_INT_RXOVIE |
1036eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_INT_TXATIE |
1037eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_INT_SPICRCIE |
1038eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_INT_ECCIE |
1039eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_INT_TEFIE |
1040eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_INT_MODIE |
1041eb79a267SMarc Kleine-Budde 		MCP251XFD_REG_INT_RXIE;
10421f0e21a0SMarc Kleine-Budde 
10431f0e21a0SMarc Kleine-Budde 	if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
1044eb79a267SMarc Kleine-Budde 		val |= MCP251XFD_REG_INT_IVMIE;
10451f0e21a0SMarc Kleine-Budde 
1046eb79a267SMarc Kleine-Budde 	return regmap_write(priv->map_reg, MCP251XFD_REG_INT, val);
10471f0e21a0SMarc Kleine-Budde }
10481f0e21a0SMarc Kleine-Budde 
1049eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_interrupts_disable(const struct mcp251xfd_priv *priv)
10501f0e21a0SMarc Kleine-Budde {
10511f0e21a0SMarc Kleine-Budde 	int err;
10521f0e21a0SMarc Kleine-Budde 	u32 mask;
10531f0e21a0SMarc Kleine-Budde 
1054eb79a267SMarc Kleine-Budde 	err = regmap_write(priv->map_reg, MCP251XFD_REG_INT, 0);
10551f0e21a0SMarc Kleine-Budde 	if (err)
10561f0e21a0SMarc Kleine-Budde 		return err;
10571f0e21a0SMarc Kleine-Budde 
1058eb79a267SMarc Kleine-Budde 	mask = MCP251XFD_REG_ECCCON_DEDIE | MCP251XFD_REG_ECCCON_SECIE;
1059eb79a267SMarc Kleine-Budde 	err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCCON,
10601f0e21a0SMarc Kleine-Budde 				 mask, 0x0);
10611f0e21a0SMarc Kleine-Budde 	if (err)
10621f0e21a0SMarc Kleine-Budde 		return err;
10631f0e21a0SMarc Kleine-Budde 
1064eb79a267SMarc Kleine-Budde 	return regmap_write(priv->map_reg, MCP251XFD_REG_CRC, 0);
10651f0e21a0SMarc Kleine-Budde }
10661f0e21a0SMarc Kleine-Budde 
1067eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_stop(struct mcp251xfd_priv *priv,
10681f0e21a0SMarc Kleine-Budde 			       const enum can_state state)
10691f0e21a0SMarc Kleine-Budde {
10701f0e21a0SMarc Kleine-Budde 	priv->can.state = state;
10711f0e21a0SMarc Kleine-Budde 
1072eb79a267SMarc Kleine-Budde 	mcp251xfd_chip_interrupts_disable(priv);
1073eb79a267SMarc Kleine-Budde 	mcp251xfd_chip_rx_int_disable(priv);
1074eb79a267SMarc Kleine-Budde 	return mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP);
10751f0e21a0SMarc Kleine-Budde }
10761f0e21a0SMarc Kleine-Budde 
1077eb79a267SMarc Kleine-Budde static int mcp251xfd_chip_start(struct mcp251xfd_priv *priv)
10781f0e21a0SMarc Kleine-Budde {
10791f0e21a0SMarc Kleine-Budde 	int err;
10801f0e21a0SMarc Kleine-Budde 
1081eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_softreset(priv);
10821f0e21a0SMarc Kleine-Budde 	if (err)
10831f0e21a0SMarc Kleine-Budde 		goto out_chip_stop;
10841f0e21a0SMarc Kleine-Budde 
1085eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_clock_init(priv);
10861f0e21a0SMarc Kleine-Budde 	if (err)
10871f0e21a0SMarc Kleine-Budde 		goto out_chip_stop;
10881f0e21a0SMarc Kleine-Budde 
1089eb79a267SMarc Kleine-Budde 	err = mcp251xfd_set_bittiming(priv);
10901f0e21a0SMarc Kleine-Budde 	if (err)
10911f0e21a0SMarc Kleine-Budde 		goto out_chip_stop;
10921f0e21a0SMarc Kleine-Budde 
1093eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_rx_int_enable(priv);
10941f0e21a0SMarc Kleine-Budde 	if (err)
10951f0e21a0SMarc Kleine-Budde 		return err;
10961f0e21a0SMarc Kleine-Budde 
1097eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_ecc_init(priv);
10981f0e21a0SMarc Kleine-Budde 	if (err)
10991f0e21a0SMarc Kleine-Budde 		goto out_chip_stop;
11001f0e21a0SMarc Kleine-Budde 
1101eb79a267SMarc Kleine-Budde 	mcp251xfd_ring_init(priv);
11021f0e21a0SMarc Kleine-Budde 
1103eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_fifo_init(priv);
11041f0e21a0SMarc Kleine-Budde 	if (err)
11051f0e21a0SMarc Kleine-Budde 		goto out_chip_stop;
11061f0e21a0SMarc Kleine-Budde 
11071f0e21a0SMarc Kleine-Budde 	priv->can.state = CAN_STATE_ERROR_ACTIVE;
11081f0e21a0SMarc Kleine-Budde 
1109eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_set_normal_mode(priv);
11101f0e21a0SMarc Kleine-Budde 	if (err)
11111f0e21a0SMarc Kleine-Budde 		goto out_chip_stop;
11121f0e21a0SMarc Kleine-Budde 
11131f0e21a0SMarc Kleine-Budde 	return 0;
11141f0e21a0SMarc Kleine-Budde 
11151f0e21a0SMarc Kleine-Budde  out_chip_stop:
1116e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump(priv);
1117eb79a267SMarc Kleine-Budde 	mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED);
11181f0e21a0SMarc Kleine-Budde 
11191f0e21a0SMarc Kleine-Budde 	return err;
11201f0e21a0SMarc Kleine-Budde }
11211f0e21a0SMarc Kleine-Budde 
1122eb79a267SMarc Kleine-Budde static int mcp251xfd_set_mode(struct net_device *ndev, enum can_mode mode)
11231f0e21a0SMarc Kleine-Budde {
1124eb79a267SMarc Kleine-Budde 	struct mcp251xfd_priv *priv = netdev_priv(ndev);
11251f0e21a0SMarc Kleine-Budde 	int err;
11261f0e21a0SMarc Kleine-Budde 
11271f0e21a0SMarc Kleine-Budde 	switch (mode) {
11281f0e21a0SMarc Kleine-Budde 	case CAN_MODE_START:
1129eb79a267SMarc Kleine-Budde 		err = mcp251xfd_chip_start(priv);
11301f0e21a0SMarc Kleine-Budde 		if (err)
11311f0e21a0SMarc Kleine-Budde 			return err;
11321f0e21a0SMarc Kleine-Budde 
1133eb79a267SMarc Kleine-Budde 		err = mcp251xfd_chip_interrupts_enable(priv);
11341f0e21a0SMarc Kleine-Budde 		if (err) {
1135eb79a267SMarc Kleine-Budde 			mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED);
11361f0e21a0SMarc Kleine-Budde 			return err;
11371f0e21a0SMarc Kleine-Budde 		}
11381f0e21a0SMarc Kleine-Budde 
11391f0e21a0SMarc Kleine-Budde 		netif_wake_queue(ndev);
11401f0e21a0SMarc Kleine-Budde 		break;
11411f0e21a0SMarc Kleine-Budde 
11421f0e21a0SMarc Kleine-Budde 	default:
11431f0e21a0SMarc Kleine-Budde 		return -EOPNOTSUPP;
11441f0e21a0SMarc Kleine-Budde 	}
11451f0e21a0SMarc Kleine-Budde 
11461f0e21a0SMarc Kleine-Budde 	return 0;
11471f0e21a0SMarc Kleine-Budde }
11481f0e21a0SMarc Kleine-Budde 
1149eb79a267SMarc Kleine-Budde static int __mcp251xfd_get_berr_counter(const struct net_device *ndev,
11501f0e21a0SMarc Kleine-Budde 					struct can_berr_counter *bec)
11511f0e21a0SMarc Kleine-Budde {
1152eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_priv *priv = netdev_priv(ndev);
11531f0e21a0SMarc Kleine-Budde 	u32 trec;
11541f0e21a0SMarc Kleine-Budde 	int err;
11551f0e21a0SMarc Kleine-Budde 
1156eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec);
11571f0e21a0SMarc Kleine-Budde 	if (err)
11581f0e21a0SMarc Kleine-Budde 		return err;
11591f0e21a0SMarc Kleine-Budde 
1160eb79a267SMarc Kleine-Budde 	if (trec & MCP251XFD_REG_TREC_TXBO)
11611f0e21a0SMarc Kleine-Budde 		bec->txerr = 256;
11621f0e21a0SMarc Kleine-Budde 	else
1163eb79a267SMarc Kleine-Budde 		bec->txerr = FIELD_GET(MCP251XFD_REG_TREC_TEC_MASK, trec);
1164eb79a267SMarc Kleine-Budde 	bec->rxerr = FIELD_GET(MCP251XFD_REG_TREC_REC_MASK, trec);
11651f0e21a0SMarc Kleine-Budde 
11661f0e21a0SMarc Kleine-Budde 	return 0;
11671f0e21a0SMarc Kleine-Budde }
11681f0e21a0SMarc Kleine-Budde 
1169eb79a267SMarc Kleine-Budde static int mcp251xfd_get_berr_counter(const struct net_device *ndev,
11701f0e21a0SMarc Kleine-Budde 				      struct can_berr_counter *bec)
11711f0e21a0SMarc Kleine-Budde {
1172eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_priv *priv = netdev_priv(ndev);
11731f0e21a0SMarc Kleine-Budde 
11741f0e21a0SMarc Kleine-Budde 	/* Avoid waking up the controller if the interface is down */
11751f0e21a0SMarc Kleine-Budde 	if (!(ndev->flags & IFF_UP))
11761f0e21a0SMarc Kleine-Budde 		return 0;
11771f0e21a0SMarc Kleine-Budde 
11781f0e21a0SMarc Kleine-Budde 	/* The controller is powered down during Bus Off, use saved
11791f0e21a0SMarc Kleine-Budde 	 * bec values.
11801f0e21a0SMarc Kleine-Budde 	 */
11811f0e21a0SMarc Kleine-Budde 	if (priv->can.state == CAN_STATE_BUS_OFF) {
11821f0e21a0SMarc Kleine-Budde 		*bec = priv->bec;
11831f0e21a0SMarc Kleine-Budde 		return 0;
11841f0e21a0SMarc Kleine-Budde 	}
11851f0e21a0SMarc Kleine-Budde 
1186eb79a267SMarc Kleine-Budde 	return __mcp251xfd_get_berr_counter(ndev, bec);
11871f0e21a0SMarc Kleine-Budde }
11881f0e21a0SMarc Kleine-Budde 
1189eb79a267SMarc Kleine-Budde static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv)
11901f0e21a0SMarc Kleine-Budde {
11911f0e21a0SMarc Kleine-Budde 	u8 tef_tail_chip, tef_tail;
11921f0e21a0SMarc Kleine-Budde 	int err;
11931f0e21a0SMarc Kleine-Budde 
1194eb79a267SMarc Kleine-Budde 	if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY))
11951f0e21a0SMarc Kleine-Budde 		return 0;
11961f0e21a0SMarc Kleine-Budde 
1197eb79a267SMarc Kleine-Budde 	err = mcp251xfd_tef_tail_get_from_chip(priv, &tef_tail_chip);
11981f0e21a0SMarc Kleine-Budde 	if (err)
11991f0e21a0SMarc Kleine-Budde 		return err;
12001f0e21a0SMarc Kleine-Budde 
1201eb79a267SMarc Kleine-Budde 	tef_tail = mcp251xfd_get_tef_tail(priv);
12021f0e21a0SMarc Kleine-Budde 	if (tef_tail_chip != tef_tail) {
12031f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
12041f0e21a0SMarc Kleine-Budde 			   "TEF tail of chip (0x%02x) and ours (0x%08x) inconsistent.\n",
12051f0e21a0SMarc Kleine-Budde 			   tef_tail_chip, tef_tail);
12061f0e21a0SMarc Kleine-Budde 		return -EILSEQ;
12071f0e21a0SMarc Kleine-Budde 	}
12081f0e21a0SMarc Kleine-Budde 
12091f0e21a0SMarc Kleine-Budde 	return 0;
12101f0e21a0SMarc Kleine-Budde }
12111f0e21a0SMarc Kleine-Budde 
12121f0e21a0SMarc Kleine-Budde static int
1213eb79a267SMarc Kleine-Budde mcp251xfd_check_rx_tail(const struct mcp251xfd_priv *priv,
1214eb79a267SMarc Kleine-Budde 			const struct mcp251xfd_rx_ring *ring)
12151f0e21a0SMarc Kleine-Budde {
12161f0e21a0SMarc Kleine-Budde 	u8 rx_tail_chip, rx_tail;
12171f0e21a0SMarc Kleine-Budde 	int err;
12181f0e21a0SMarc Kleine-Budde 
1219eb79a267SMarc Kleine-Budde 	if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY))
12201f0e21a0SMarc Kleine-Budde 		return 0;
12211f0e21a0SMarc Kleine-Budde 
1222eb79a267SMarc Kleine-Budde 	err = mcp251xfd_rx_tail_get_from_chip(priv, ring, &rx_tail_chip);
12231f0e21a0SMarc Kleine-Budde 	if (err)
12241f0e21a0SMarc Kleine-Budde 		return err;
12251f0e21a0SMarc Kleine-Budde 
1226eb79a267SMarc Kleine-Budde 	rx_tail = mcp251xfd_get_rx_tail(ring);
12271f0e21a0SMarc Kleine-Budde 	if (rx_tail_chip != rx_tail) {
12281f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
12291f0e21a0SMarc Kleine-Budde 			   "RX tail of chip (%d) and ours (%d) inconsistent.\n",
12301f0e21a0SMarc Kleine-Budde 			   rx_tail_chip, rx_tail);
12311f0e21a0SMarc Kleine-Budde 		return -EILSEQ;
12321f0e21a0SMarc Kleine-Budde 	}
12331f0e21a0SMarc Kleine-Budde 
12341f0e21a0SMarc Kleine-Budde 	return 0;
12351f0e21a0SMarc Kleine-Budde }
12361f0e21a0SMarc Kleine-Budde 
12371f0e21a0SMarc Kleine-Budde static int
1238eb79a267SMarc Kleine-Budde mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
12391f0e21a0SMarc Kleine-Budde {
1240eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
12411f0e21a0SMarc Kleine-Budde 	u32 tef_sta;
12421f0e21a0SMarc Kleine-Budde 	int err;
12431f0e21a0SMarc Kleine-Budde 
1244eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta);
12451f0e21a0SMarc Kleine-Budde 	if (err)
12461f0e21a0SMarc Kleine-Budde 		return err;
12471f0e21a0SMarc Kleine-Budde 
1248eb79a267SMarc Kleine-Budde 	if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) {
12491f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
12501f0e21a0SMarc Kleine-Budde 			   "Transmit Event FIFO buffer overflow.\n");
12511f0e21a0SMarc Kleine-Budde 		return -ENOBUFS;
12521f0e21a0SMarc Kleine-Budde 	}
12531f0e21a0SMarc Kleine-Budde 
12541f0e21a0SMarc Kleine-Budde 	netdev_info(priv->ndev,
1255f93486a7SMarc Kleine-Budde 		    "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x).\n",
1256eb79a267SMarc Kleine-Budde 		    tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ?
1257eb79a267SMarc Kleine-Budde 		    "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ?
12581f0e21a0SMarc Kleine-Budde 		    "not empty" : "empty",
1259dada6a6cSMarc Kleine-Budde 		    seq, priv->tef->tail, priv->tef->head, tx_ring->head);
12601f0e21a0SMarc Kleine-Budde 
12611f0e21a0SMarc Kleine-Budde 	/* The Sequence Number in the TEF doesn't match our tef_tail. */
12621f0e21a0SMarc Kleine-Budde 	return -EAGAIN;
12631f0e21a0SMarc Kleine-Budde }
12641f0e21a0SMarc Kleine-Budde 
12651f0e21a0SMarc Kleine-Budde static int
1266eb79a267SMarc Kleine-Budde mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
12670084e298SMarc Kleine-Budde 			   const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
12680084e298SMarc Kleine-Budde 			   unsigned int *frame_len_ptr)
12691f0e21a0SMarc Kleine-Budde {
12701f0e21a0SMarc Kleine-Budde 	struct net_device_stats *stats = &priv->ndev->stats;
12715f02a49cSMarc Kleine-Budde 	struct sk_buff *skb;
12725f02a49cSMarc Kleine-Budde 	u32 seq, seq_masked, tef_tail_masked, tef_tail;
12731f0e21a0SMarc Kleine-Budde 
1274eb79a267SMarc Kleine-Budde 	seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK,
12751f0e21a0SMarc Kleine-Budde 			hw_tef_obj->flags);
12761f0e21a0SMarc Kleine-Budde 
12771f0e21a0SMarc Kleine-Budde 	/* Use the MCP2517FD mask on the MCP2518FD, too. We only
12781f0e21a0SMarc Kleine-Budde 	 * compare 7 bits, this should be enough to detect
12791f0e21a0SMarc Kleine-Budde 	 * net-yet-completed, i.e. old TEF objects.
12801f0e21a0SMarc Kleine-Budde 	 */
12811f0e21a0SMarc Kleine-Budde 	seq_masked = seq &
1282eb79a267SMarc Kleine-Budde 		field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
1283dada6a6cSMarc Kleine-Budde 	tef_tail_masked = priv->tef->tail &
1284eb79a267SMarc Kleine-Budde 		field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
12851f0e21a0SMarc Kleine-Budde 	if (seq_masked != tef_tail_masked)
1286eb79a267SMarc Kleine-Budde 		return mcp251xfd_handle_tefif_recover(priv, seq);
12871f0e21a0SMarc Kleine-Budde 
12885f02a49cSMarc Kleine-Budde 	tef_tail = mcp251xfd_get_tef_tail(priv);
12895f02a49cSMarc Kleine-Budde 	skb = priv->can.echo_skb[tef_tail];
12905f02a49cSMarc Kleine-Budde 	if (skb)
12915f02a49cSMarc Kleine-Budde 		mcp251xfd_skb_set_timestamp(priv, skb, hw_tef_obj->ts);
12921f0e21a0SMarc Kleine-Budde 	stats->tx_bytes +=
12931f0e21a0SMarc Kleine-Budde 		can_rx_offload_get_echo_skb(&priv->offload,
12940084e298SMarc Kleine-Budde 					    tef_tail, hw_tef_obj->ts,
12950084e298SMarc Kleine-Budde 					    frame_len_ptr);
12961f0e21a0SMarc Kleine-Budde 	stats->tx_packets++;
1297dada6a6cSMarc Kleine-Budde 	priv->tef->tail++;
12981f0e21a0SMarc Kleine-Budde 
129968c0c1c7SMarc Kleine-Budde 	return 0;
13001f0e21a0SMarc Kleine-Budde }
13011f0e21a0SMarc Kleine-Budde 
1302eb79a267SMarc Kleine-Budde static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv)
13031f0e21a0SMarc Kleine-Budde {
1304eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
13051f0e21a0SMarc Kleine-Budde 	unsigned int new_head;
13061f0e21a0SMarc Kleine-Budde 	u8 chip_tx_tail;
13071f0e21a0SMarc Kleine-Budde 	int err;
13081f0e21a0SMarc Kleine-Budde 
1309eb79a267SMarc Kleine-Budde 	err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail);
13101f0e21a0SMarc Kleine-Budde 	if (err)
13111f0e21a0SMarc Kleine-Budde 		return err;
13121f0e21a0SMarc Kleine-Budde 
13131f0e21a0SMarc Kleine-Budde 	/* chip_tx_tail, is the next TX-Object send by the HW.
13141f0e21a0SMarc Kleine-Budde 	 * The new TEF head must be >= the old head, ...
13151f0e21a0SMarc Kleine-Budde 	 */
1316dada6a6cSMarc Kleine-Budde 	new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail;
1317dada6a6cSMarc Kleine-Budde 	if (new_head <= priv->tef->head)
13181f0e21a0SMarc Kleine-Budde 		new_head += tx_ring->obj_num;
13191f0e21a0SMarc Kleine-Budde 
13201f0e21a0SMarc Kleine-Budde 	/* ... but it cannot exceed the TX head. */
1321dada6a6cSMarc Kleine-Budde 	priv->tef->head = min(new_head, tx_ring->head);
13221f0e21a0SMarc Kleine-Budde 
1323eb79a267SMarc Kleine-Budde 	return mcp251xfd_check_tef_tail(priv);
13241f0e21a0SMarc Kleine-Budde }
13251f0e21a0SMarc Kleine-Budde 
13261f0e21a0SMarc Kleine-Budde static inline int
1327eb79a267SMarc Kleine-Budde mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv,
1328eb79a267SMarc Kleine-Budde 		       struct mcp251xfd_hw_tef_obj *hw_tef_obj,
13291f0e21a0SMarc Kleine-Budde 		       const u8 offset, const u8 len)
13301f0e21a0SMarc Kleine-Budde {
1331eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
1332cdc4c698SSu Yanjun 	const int val_bytes = regmap_get_val_bytes(priv->map_rx);
13331f0e21a0SMarc Kleine-Budde 
1334eb79a267SMarc Kleine-Budde 	if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
13351f0e21a0SMarc Kleine-Budde 	    (offset > tx_ring->obj_num ||
13361f0e21a0SMarc Kleine-Budde 	     len > tx_ring->obj_num ||
13371f0e21a0SMarc Kleine-Budde 	     offset + len > tx_ring->obj_num)) {
13381f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
13391f0e21a0SMarc Kleine-Budde 			   "Trying to read to many TEF objects (max=%d, offset=%d, len=%d).\n",
13401f0e21a0SMarc Kleine-Budde 			   tx_ring->obj_num, offset, len);
13411f0e21a0SMarc Kleine-Budde 		return -ERANGE;
13421f0e21a0SMarc Kleine-Budde 	}
13431f0e21a0SMarc Kleine-Budde 
13441f0e21a0SMarc Kleine-Budde 	return regmap_bulk_read(priv->map_rx,
1345eb79a267SMarc Kleine-Budde 				mcp251xfd_get_tef_obj_addr(offset),
13461f0e21a0SMarc Kleine-Budde 				hw_tef_obj,
1347cdc4c698SSu Yanjun 				sizeof(*hw_tef_obj) / val_bytes * len);
13481f0e21a0SMarc Kleine-Budde }
13491f0e21a0SMarc Kleine-Budde 
1350eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
13511f0e21a0SMarc Kleine-Budde {
1352eb79a267SMarc Kleine-Budde 	struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX];
13530084e298SMarc Kleine-Budde 	unsigned int total_frame_len = 0;
13541f0e21a0SMarc Kleine-Budde 	u8 tef_tail, len, l;
13551f0e21a0SMarc Kleine-Budde 	int err, i;
13561f0e21a0SMarc Kleine-Budde 
1357eb79a267SMarc Kleine-Budde 	err = mcp251xfd_tef_ring_update(priv);
13581f0e21a0SMarc Kleine-Budde 	if (err)
13591f0e21a0SMarc Kleine-Budde 		return err;
13601f0e21a0SMarc Kleine-Budde 
1361eb79a267SMarc Kleine-Budde 	tef_tail = mcp251xfd_get_tef_tail(priv);
1362eb79a267SMarc Kleine-Budde 	len = mcp251xfd_get_tef_len(priv);
1363eb79a267SMarc Kleine-Budde 	l = mcp251xfd_get_tef_linear_len(priv);
1364eb79a267SMarc Kleine-Budde 	err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l);
13651f0e21a0SMarc Kleine-Budde 	if (err)
13661f0e21a0SMarc Kleine-Budde 		return err;
13671f0e21a0SMarc Kleine-Budde 
13681f0e21a0SMarc Kleine-Budde 	if (l < len) {
1369eb79a267SMarc Kleine-Budde 		err = mcp251xfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l);
13701f0e21a0SMarc Kleine-Budde 		if (err)
13711f0e21a0SMarc Kleine-Budde 			return err;
13721f0e21a0SMarc Kleine-Budde 	}
13731f0e21a0SMarc Kleine-Budde 
13741f0e21a0SMarc Kleine-Budde 	for (i = 0; i < len; i++) {
13750084e298SMarc Kleine-Budde 		unsigned int frame_len = 0;
13760084e298SMarc Kleine-Budde 
13770084e298SMarc Kleine-Budde 		err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
13781f0e21a0SMarc Kleine-Budde 		/* -EAGAIN means the Sequence Number in the TEF
13791f0e21a0SMarc Kleine-Budde 		 * doesn't match our tef_tail. This can happen if we
13801f0e21a0SMarc Kleine-Budde 		 * read the TEF objects too early. Leave loop let the
13811f0e21a0SMarc Kleine-Budde 		 * interrupt handler call us again.
13821f0e21a0SMarc Kleine-Budde 		 */
13831f0e21a0SMarc Kleine-Budde 		if (err == -EAGAIN)
13841f0e21a0SMarc Kleine-Budde 			goto out_netif_wake_queue;
13851f0e21a0SMarc Kleine-Budde 		if (err)
13861f0e21a0SMarc Kleine-Budde 			return err;
13870084e298SMarc Kleine-Budde 
13880084e298SMarc Kleine-Budde 		total_frame_len += frame_len;
13891f0e21a0SMarc Kleine-Budde 	}
13901f0e21a0SMarc Kleine-Budde 
13911f0e21a0SMarc Kleine-Budde  out_netif_wake_queue:
139268c0c1c7SMarc Kleine-Budde 	len = i;	/* number of handled goods TEFs */
139368c0c1c7SMarc Kleine-Budde 	if (len) {
139468c0c1c7SMarc Kleine-Budde 		struct mcp251xfd_tef_ring *ring = priv->tef;
139568c0c1c7SMarc Kleine-Budde 		struct mcp251xfd_tx_ring *tx_ring = priv->tx;
1396eb94b74cSMarc Kleine-Budde 		int offset;
139768c0c1c7SMarc Kleine-Budde 
139868c0c1c7SMarc Kleine-Budde 		/* Increment the TEF FIFO tail pointer 'len' times in
139968c0c1c7SMarc Kleine-Budde 		 * a single SPI message.
14006086f02aSMarc Kleine-Budde 		 *
14016086f02aSMarc Kleine-Budde 		 * Note:
1402eb94b74cSMarc Kleine-Budde 		 * Calculate offset, so that the SPI transfer ends on
1403eb94b74cSMarc Kleine-Budde 		 * the last message of the uinc_xfer array, which has
1404eb94b74cSMarc Kleine-Budde 		 * "cs_change == 0", to properly deactivate the chip
1405eb94b74cSMarc Kleine-Budde 		 * select.
140668c0c1c7SMarc Kleine-Budde 		 */
1407eb94b74cSMarc Kleine-Budde 		offset = ARRAY_SIZE(ring->uinc_xfer) - len;
1408eb94b74cSMarc Kleine-Budde 		err = spi_sync_transfer(priv->spi,
1409eb94b74cSMarc Kleine-Budde 					ring->uinc_xfer + offset, len);
141068c0c1c7SMarc Kleine-Budde 		if (err)
141168c0c1c7SMarc Kleine-Budde 			return err;
141268c0c1c7SMarc Kleine-Budde 
14136086f02aSMarc Kleine-Budde 		tx_ring->tail += len;
14140084e298SMarc Kleine-Budde 		netdev_completed_queue(priv->ndev, len, total_frame_len);
14156086f02aSMarc Kleine-Budde 
141668c0c1c7SMarc Kleine-Budde 		err = mcp251xfd_check_tef_tail(priv);
141768c0c1c7SMarc Kleine-Budde 		if (err)
141868c0c1c7SMarc Kleine-Budde 			return err;
141968c0c1c7SMarc Kleine-Budde 	}
142068c0c1c7SMarc Kleine-Budde 
1421eb79a267SMarc Kleine-Budde 	mcp251xfd_ecc_tefif_successful(priv);
14221f0e21a0SMarc Kleine-Budde 
1423eb79a267SMarc Kleine-Budde 	if (mcp251xfd_get_tx_free(priv->tx)) {
14241f0e21a0SMarc Kleine-Budde 		/* Make sure that anybody stopping the queue after
14251f0e21a0SMarc Kleine-Budde 		 * this sees the new tx_ring->tail.
14261f0e21a0SMarc Kleine-Budde 		 */
14271f0e21a0SMarc Kleine-Budde 		smp_mb();
14281f0e21a0SMarc Kleine-Budde 		netif_wake_queue(priv->ndev);
14291f0e21a0SMarc Kleine-Budde 	}
14301f0e21a0SMarc Kleine-Budde 
14311f0e21a0SMarc Kleine-Budde 	return 0;
14321f0e21a0SMarc Kleine-Budde }
14331f0e21a0SMarc Kleine-Budde 
14341f0e21a0SMarc Kleine-Budde static int
1435eb79a267SMarc Kleine-Budde mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv,
1436eb79a267SMarc Kleine-Budde 			 struct mcp251xfd_rx_ring *ring)
14371f0e21a0SMarc Kleine-Budde {
14381f0e21a0SMarc Kleine-Budde 	u32 new_head;
14391f0e21a0SMarc Kleine-Budde 	u8 chip_rx_head;
14401f0e21a0SMarc Kleine-Budde 	int err;
14411f0e21a0SMarc Kleine-Budde 
1442eb79a267SMarc Kleine-Budde 	err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head);
14431f0e21a0SMarc Kleine-Budde 	if (err)
14441f0e21a0SMarc Kleine-Budde 		return err;
14451f0e21a0SMarc Kleine-Budde 
14461f0e21a0SMarc Kleine-Budde 	/* chip_rx_head, is the next RX-Object filled by the HW.
14471f0e21a0SMarc Kleine-Budde 	 * The new RX head must be >= the old head.
14481f0e21a0SMarc Kleine-Budde 	 */
14491f0e21a0SMarc Kleine-Budde 	new_head = round_down(ring->head, ring->obj_num) + chip_rx_head;
14501f0e21a0SMarc Kleine-Budde 	if (new_head <= ring->head)
14511f0e21a0SMarc Kleine-Budde 		new_head += ring->obj_num;
14521f0e21a0SMarc Kleine-Budde 
14531f0e21a0SMarc Kleine-Budde 	ring->head = new_head;
14541f0e21a0SMarc Kleine-Budde 
1455eb79a267SMarc Kleine-Budde 	return mcp251xfd_check_rx_tail(priv, ring);
14561f0e21a0SMarc Kleine-Budde }
14571f0e21a0SMarc Kleine-Budde 
14581f0e21a0SMarc Kleine-Budde static void
14595f02a49cSMarc Kleine-Budde mcp251xfd_hw_rx_obj_to_skb(struct mcp251xfd_priv *priv,
1460eb79a267SMarc Kleine-Budde 			   const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
14611f0e21a0SMarc Kleine-Budde 			   struct sk_buff *skb)
14621f0e21a0SMarc Kleine-Budde {
14631f0e21a0SMarc Kleine-Budde 	struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
146486f1e3b1SMarc Kleine-Budde 	u8 dlc;
14651f0e21a0SMarc Kleine-Budde 
1466eb79a267SMarc Kleine-Budde 	if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_IDE) {
14671f0e21a0SMarc Kleine-Budde 		u32 sid, eid;
14681f0e21a0SMarc Kleine-Budde 
1469eb79a267SMarc Kleine-Budde 		eid = FIELD_GET(MCP251XFD_OBJ_ID_EID_MASK, hw_rx_obj->id);
1470eb79a267SMarc Kleine-Budde 		sid = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, hw_rx_obj->id);
14711f0e21a0SMarc Kleine-Budde 
14721f0e21a0SMarc Kleine-Budde 		cfd->can_id = CAN_EFF_FLAG |
1473eb79a267SMarc Kleine-Budde 			FIELD_PREP(MCP251XFD_REG_FRAME_EFF_EID_MASK, eid) |
1474eb79a267SMarc Kleine-Budde 			FIELD_PREP(MCP251XFD_REG_FRAME_EFF_SID_MASK, sid);
14751f0e21a0SMarc Kleine-Budde 	} else {
1476eb79a267SMarc Kleine-Budde 		cfd->can_id = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK,
14771f0e21a0SMarc Kleine-Budde 					hw_rx_obj->id);
14781f0e21a0SMarc Kleine-Budde 	}
14791f0e21a0SMarc Kleine-Budde 
148049ffacbcSMarc Kleine-Budde 	dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC_MASK, hw_rx_obj->flags);
148186f1e3b1SMarc Kleine-Budde 
14821f0e21a0SMarc Kleine-Budde 	/* CANFD */
1483eb79a267SMarc Kleine-Budde 	if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) {
14841f0e21a0SMarc Kleine-Budde 
1485eb79a267SMarc Kleine-Budde 		if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_ESI)
14861f0e21a0SMarc Kleine-Budde 			cfd->flags |= CANFD_ESI;
14871f0e21a0SMarc Kleine-Budde 
1488eb79a267SMarc Kleine-Budde 		if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_BRS)
14891f0e21a0SMarc Kleine-Budde 			cfd->flags |= CANFD_BRS;
14901f0e21a0SMarc Kleine-Budde 
14913ab4ce0dSOliver Hartkopp 		cfd->len = can_fd_dlc2len(dlc);
14921f0e21a0SMarc Kleine-Budde 	} else {
1493eb79a267SMarc Kleine-Budde 		if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR)
14941f0e21a0SMarc Kleine-Budde 			cfd->can_id |= CAN_RTR_FLAG;
14951f0e21a0SMarc Kleine-Budde 
149686f1e3b1SMarc Kleine-Budde 		can_frame_set_cc_len((struct can_frame *)cfd, dlc,
149786f1e3b1SMarc Kleine-Budde 				     priv->can.ctrlmode);
14981f0e21a0SMarc Kleine-Budde 	}
14991f0e21a0SMarc Kleine-Budde 
1500e20b85c7SMarc Kleine-Budde 	if (!(hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR))
15011f0e21a0SMarc Kleine-Budde 		memcpy(cfd->data, hw_rx_obj->data, cfd->len);
15025f02a49cSMarc Kleine-Budde 
15035f02a49cSMarc Kleine-Budde 	mcp251xfd_skb_set_timestamp(priv, skb, hw_rx_obj->ts);
15041f0e21a0SMarc Kleine-Budde }
15051f0e21a0SMarc Kleine-Budde 
15061f0e21a0SMarc Kleine-Budde static int
1507eb79a267SMarc Kleine-Budde mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv,
1508eb79a267SMarc Kleine-Budde 			  struct mcp251xfd_rx_ring *ring,
1509eb79a267SMarc Kleine-Budde 			  const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj)
15101f0e21a0SMarc Kleine-Budde {
15111f0e21a0SMarc Kleine-Budde 	struct net_device_stats *stats = &priv->ndev->stats;
15121f0e21a0SMarc Kleine-Budde 	struct sk_buff *skb;
15131f0e21a0SMarc Kleine-Budde 	struct canfd_frame *cfd;
15141f0e21a0SMarc Kleine-Budde 	int err;
15151f0e21a0SMarc Kleine-Budde 
1516eb79a267SMarc Kleine-Budde 	if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF)
15171f0e21a0SMarc Kleine-Budde 		skb = alloc_canfd_skb(priv->ndev, &cfd);
15181f0e21a0SMarc Kleine-Budde 	else
15191f0e21a0SMarc Kleine-Budde 		skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cfd);
15201f0e21a0SMarc Kleine-Budde 
1521ca4c6ebeSQinglang Miao 	if (!skb) {
15221f0e21a0SMarc Kleine-Budde 		stats->rx_dropped++;
15231f0e21a0SMarc Kleine-Budde 		return 0;
15241f0e21a0SMarc Kleine-Budde 	}
15251f0e21a0SMarc Kleine-Budde 
1526eb79a267SMarc Kleine-Budde 	mcp251xfd_hw_rx_obj_to_skb(priv, hw_rx_obj, skb);
15271f0e21a0SMarc Kleine-Budde 	err = can_rx_offload_queue_sorted(&priv->offload, skb, hw_rx_obj->ts);
15281f0e21a0SMarc Kleine-Budde 	if (err)
15291f0e21a0SMarc Kleine-Budde 		stats->rx_fifo_errors++;
15301f0e21a0SMarc Kleine-Budde 
15311f652bb6SUrsula Maplehurst 	return 0;
15321f0e21a0SMarc Kleine-Budde }
15331f0e21a0SMarc Kleine-Budde 
15341f0e21a0SMarc Kleine-Budde static inline int
1535eb79a267SMarc Kleine-Budde mcp251xfd_rx_obj_read(const struct mcp251xfd_priv *priv,
1536eb79a267SMarc Kleine-Budde 		      const struct mcp251xfd_rx_ring *ring,
1537eb79a267SMarc Kleine-Budde 		      struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
15381f0e21a0SMarc Kleine-Budde 		      const u8 offset, const u8 len)
15391f0e21a0SMarc Kleine-Budde {
1540cdc4c698SSu Yanjun 	const int val_bytes = regmap_get_val_bytes(priv->map_rx);
15411f0e21a0SMarc Kleine-Budde 	int err;
15421f0e21a0SMarc Kleine-Budde 
15431f0e21a0SMarc Kleine-Budde 	err = regmap_bulk_read(priv->map_rx,
1544eb79a267SMarc Kleine-Budde 			       mcp251xfd_get_rx_obj_addr(ring, offset),
15451f0e21a0SMarc Kleine-Budde 			       hw_rx_obj,
1546cdc4c698SSu Yanjun 			       len * ring->obj_size / val_bytes);
15471f0e21a0SMarc Kleine-Budde 
15481f0e21a0SMarc Kleine-Budde 	return err;
15491f0e21a0SMarc Kleine-Budde }
15501f0e21a0SMarc Kleine-Budde 
15511f0e21a0SMarc Kleine-Budde static int
1552eb79a267SMarc Kleine-Budde mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
1553eb79a267SMarc Kleine-Budde 			   struct mcp251xfd_rx_ring *ring)
15541f0e21a0SMarc Kleine-Budde {
1555eb79a267SMarc Kleine-Budde 	struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj = ring->obj;
15561f0e21a0SMarc Kleine-Budde 	u8 rx_tail, len;
15571f0e21a0SMarc Kleine-Budde 	int err, i;
15581f0e21a0SMarc Kleine-Budde 
1559eb79a267SMarc Kleine-Budde 	err = mcp251xfd_rx_ring_update(priv, ring);
15601f0e21a0SMarc Kleine-Budde 	if (err)
15611f0e21a0SMarc Kleine-Budde 		return err;
15621f0e21a0SMarc Kleine-Budde 
1563eb79a267SMarc Kleine-Budde 	while ((len = mcp251xfd_get_rx_linear_len(ring))) {
1564eb94b74cSMarc Kleine-Budde 		int offset;
15651f652bb6SUrsula Maplehurst 
1566eb79a267SMarc Kleine-Budde 		rx_tail = mcp251xfd_get_rx_tail(ring);
15671f0e21a0SMarc Kleine-Budde 
1568eb79a267SMarc Kleine-Budde 		err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj,
15691f0e21a0SMarc Kleine-Budde 					    rx_tail, len);
15701f0e21a0SMarc Kleine-Budde 		if (err)
15711f0e21a0SMarc Kleine-Budde 			return err;
15721f0e21a0SMarc Kleine-Budde 
15731f0e21a0SMarc Kleine-Budde 		for (i = 0; i < len; i++) {
1574eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle_rxif_one(priv, ring,
15751f0e21a0SMarc Kleine-Budde 							(void *)hw_rx_obj +
15761f0e21a0SMarc Kleine-Budde 							i * ring->obj_size);
15771f0e21a0SMarc Kleine-Budde 			if (err)
15781f0e21a0SMarc Kleine-Budde 				return err;
15791f0e21a0SMarc Kleine-Budde 		}
15801f652bb6SUrsula Maplehurst 
15811f652bb6SUrsula Maplehurst 		/* Increment the RX FIFO tail pointer 'len' times in a
15821f652bb6SUrsula Maplehurst 		 * single SPI message.
15832fbb397fSMarc Kleine-Budde 		 *
15842fbb397fSMarc Kleine-Budde 		 * Note:
1585eb94b74cSMarc Kleine-Budde 		 * Calculate offset, so that the SPI transfer ends on
1586eb94b74cSMarc Kleine-Budde 		 * the last message of the uinc_xfer array, which has
1587eb94b74cSMarc Kleine-Budde 		 * "cs_change == 0", to properly deactivate the chip
1588eb94b74cSMarc Kleine-Budde 		 * select.
15891f652bb6SUrsula Maplehurst 		 */
1590eb94b74cSMarc Kleine-Budde 		offset = ARRAY_SIZE(ring->uinc_xfer) - len;
1591eb94b74cSMarc Kleine-Budde 		err = spi_sync_transfer(priv->spi,
1592eb94b74cSMarc Kleine-Budde 					ring->uinc_xfer + offset, len);
15931f652bb6SUrsula Maplehurst 		if (err)
15941f652bb6SUrsula Maplehurst 			return err;
15952fbb397fSMarc Kleine-Budde 
15962fbb397fSMarc Kleine-Budde 		ring->tail += len;
15971f0e21a0SMarc Kleine-Budde 	}
15981f0e21a0SMarc Kleine-Budde 
15991f0e21a0SMarc Kleine-Budde 	return 0;
16001f0e21a0SMarc Kleine-Budde }
16011f0e21a0SMarc Kleine-Budde 
1602eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv)
16031f0e21a0SMarc Kleine-Budde {
1604eb79a267SMarc Kleine-Budde 	struct mcp251xfd_rx_ring *ring;
16051f0e21a0SMarc Kleine-Budde 	int err, n;
16061f0e21a0SMarc Kleine-Budde 
1607eb79a267SMarc Kleine-Budde 	mcp251xfd_for_each_rx_ring(priv, ring, n) {
1608eb79a267SMarc Kleine-Budde 		err = mcp251xfd_handle_rxif_ring(priv, ring);
16091f0e21a0SMarc Kleine-Budde 		if (err)
16101f0e21a0SMarc Kleine-Budde 			return err;
16111f0e21a0SMarc Kleine-Budde 	}
16121f0e21a0SMarc Kleine-Budde 
16131f0e21a0SMarc Kleine-Budde 	return 0;
16141f0e21a0SMarc Kleine-Budde }
16151f0e21a0SMarc Kleine-Budde 
16161f0e21a0SMarc Kleine-Budde static struct sk_buff *
16175f02a49cSMarc Kleine-Budde mcp251xfd_alloc_can_err_skb(struct mcp251xfd_priv *priv,
16181f0e21a0SMarc Kleine-Budde 			    struct can_frame **cf, u32 *timestamp)
16191f0e21a0SMarc Kleine-Budde {
16205f02a49cSMarc Kleine-Budde 	struct sk_buff *skb;
16211f0e21a0SMarc Kleine-Budde 	int err;
16221f0e21a0SMarc Kleine-Budde 
1623eb79a267SMarc Kleine-Budde 	err = mcp251xfd_get_timestamp(priv, timestamp);
16241f0e21a0SMarc Kleine-Budde 	if (err)
16251f0e21a0SMarc Kleine-Budde 		return NULL;
16261f0e21a0SMarc Kleine-Budde 
16275f02a49cSMarc Kleine-Budde 	skb = alloc_can_err_skb(priv->ndev, cf);
16285f02a49cSMarc Kleine-Budde 	if (skb)
16295f02a49cSMarc Kleine-Budde 		mcp251xfd_skb_set_timestamp(priv, skb, *timestamp);
16305f02a49cSMarc Kleine-Budde 
16315f02a49cSMarc Kleine-Budde 	return skb;
16321f0e21a0SMarc Kleine-Budde }
16331f0e21a0SMarc Kleine-Budde 
1634eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_rxovif(struct mcp251xfd_priv *priv)
16351f0e21a0SMarc Kleine-Budde {
16361f0e21a0SMarc Kleine-Budde 	struct net_device_stats *stats = &priv->ndev->stats;
1637eb79a267SMarc Kleine-Budde 	struct mcp251xfd_rx_ring *ring;
16381f0e21a0SMarc Kleine-Budde 	struct sk_buff *skb;
16391f0e21a0SMarc Kleine-Budde 	struct can_frame *cf;
16401f0e21a0SMarc Kleine-Budde 	u32 timestamp, rxovif;
16411f0e21a0SMarc Kleine-Budde 	int err, i;
16421f0e21a0SMarc Kleine-Budde 
16431f0e21a0SMarc Kleine-Budde 	stats->rx_over_errors++;
16441f0e21a0SMarc Kleine-Budde 	stats->rx_errors++;
16451f0e21a0SMarc Kleine-Budde 
1646eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_RXOVIF, &rxovif);
16471f0e21a0SMarc Kleine-Budde 	if (err)
16481f0e21a0SMarc Kleine-Budde 		return err;
16491f0e21a0SMarc Kleine-Budde 
1650eb79a267SMarc Kleine-Budde 	mcp251xfd_for_each_rx_ring(priv, ring, i) {
16511f0e21a0SMarc Kleine-Budde 		if (!(rxovif & BIT(ring->fifo_nr)))
16521f0e21a0SMarc Kleine-Budde 			continue;
16531f0e21a0SMarc Kleine-Budde 
16541f0e21a0SMarc Kleine-Budde 		/* If SERRIF is active, there was a RX MAB overflow. */
1655eb79a267SMarc Kleine-Budde 		if (priv->regs_status.intf & MCP251XFD_REG_INT_SERRIF) {
16561f0e21a0SMarc Kleine-Budde 			netdev_info(priv->ndev,
16571f0e21a0SMarc Kleine-Budde 				    "RX-%d: MAB overflow detected.\n",
16581f0e21a0SMarc Kleine-Budde 				    ring->nr);
16591f0e21a0SMarc Kleine-Budde 		} else {
16601f0e21a0SMarc Kleine-Budde 			netdev_info(priv->ndev,
16611f0e21a0SMarc Kleine-Budde 				    "RX-%d: FIFO overflow.\n", ring->nr);
16621f0e21a0SMarc Kleine-Budde 		}
16631f0e21a0SMarc Kleine-Budde 
16641f0e21a0SMarc Kleine-Budde 		err = regmap_update_bits(priv->map_reg,
1665eb79a267SMarc Kleine-Budde 					 MCP251XFD_REG_FIFOSTA(ring->fifo_nr),
1666eb79a267SMarc Kleine-Budde 					 MCP251XFD_REG_FIFOSTA_RXOVIF,
16671f0e21a0SMarc Kleine-Budde 					 0x0);
16681f0e21a0SMarc Kleine-Budde 		if (err)
16691f0e21a0SMarc Kleine-Budde 			return err;
16701f0e21a0SMarc Kleine-Budde 	}
16711f0e21a0SMarc Kleine-Budde 
1672eb79a267SMarc Kleine-Budde 	skb = mcp251xfd_alloc_can_err_skb(priv, &cf, &timestamp);
16731f0e21a0SMarc Kleine-Budde 	if (!skb)
16741f0e21a0SMarc Kleine-Budde 		return 0;
16751f0e21a0SMarc Kleine-Budde 
16761f0e21a0SMarc Kleine-Budde 	cf->can_id |= CAN_ERR_CRTL;
16771f0e21a0SMarc Kleine-Budde 	cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
16781f0e21a0SMarc Kleine-Budde 
16791f0e21a0SMarc Kleine-Budde 	err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
16801f0e21a0SMarc Kleine-Budde 	if (err)
16811f0e21a0SMarc Kleine-Budde 		stats->rx_fifo_errors++;
16821f0e21a0SMarc Kleine-Budde 
16831f0e21a0SMarc Kleine-Budde 	return 0;
16841f0e21a0SMarc Kleine-Budde }
16851f0e21a0SMarc Kleine-Budde 
1686eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_txatif(struct mcp251xfd_priv *priv)
16871f0e21a0SMarc Kleine-Budde {
16881f0e21a0SMarc Kleine-Budde 	netdev_info(priv->ndev, "%s\n", __func__);
16891f0e21a0SMarc Kleine-Budde 
16901f0e21a0SMarc Kleine-Budde 	return 0;
16911f0e21a0SMarc Kleine-Budde }
16921f0e21a0SMarc Kleine-Budde 
1693eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_ivmif(struct mcp251xfd_priv *priv)
16941f0e21a0SMarc Kleine-Budde {
16951f0e21a0SMarc Kleine-Budde 	struct net_device_stats *stats = &priv->ndev->stats;
16961f0e21a0SMarc Kleine-Budde 	u32 bdiag1, timestamp;
16971f0e21a0SMarc Kleine-Budde 	struct sk_buff *skb;
16981f0e21a0SMarc Kleine-Budde 	struct can_frame *cf = NULL;
16991f0e21a0SMarc Kleine-Budde 	int err;
17001f0e21a0SMarc Kleine-Budde 
1701eb79a267SMarc Kleine-Budde 	err = mcp251xfd_get_timestamp(priv, &timestamp);
17021f0e21a0SMarc Kleine-Budde 	if (err)
17031f0e21a0SMarc Kleine-Budde 		return err;
17041f0e21a0SMarc Kleine-Budde 
1705eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_BDIAG1, &bdiag1);
17061f0e21a0SMarc Kleine-Budde 	if (err)
17071f0e21a0SMarc Kleine-Budde 		return err;
17081f0e21a0SMarc Kleine-Budde 
17091f0e21a0SMarc Kleine-Budde 	/* Write 0s to clear error bits, don't write 1s to non active
17101f0e21a0SMarc Kleine-Budde 	 * bits, as they will be set.
17111f0e21a0SMarc Kleine-Budde 	 */
1712eb79a267SMarc Kleine-Budde 	err = regmap_write(priv->map_reg, MCP251XFD_REG_BDIAG1, 0x0);
17131f0e21a0SMarc Kleine-Budde 	if (err)
17141f0e21a0SMarc Kleine-Budde 		return err;
17151f0e21a0SMarc Kleine-Budde 
17161f0e21a0SMarc Kleine-Budde 	priv->can.can_stats.bus_error++;
17171f0e21a0SMarc Kleine-Budde 
17181f0e21a0SMarc Kleine-Budde 	skb = alloc_can_err_skb(priv->ndev, &cf);
17191f0e21a0SMarc Kleine-Budde 	if (cf)
17201f0e21a0SMarc Kleine-Budde 		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
17211f0e21a0SMarc Kleine-Budde 
17221f0e21a0SMarc Kleine-Budde 	/* Controller misconfiguration */
1723eb79a267SMarc Kleine-Budde 	if (WARN_ON(bdiag1 & MCP251XFD_REG_BDIAG1_DLCMM))
17241f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
17251f0e21a0SMarc Kleine-Budde 			   "recv'd DLC is larger than PLSIZE of FIFO element.");
17261f0e21a0SMarc Kleine-Budde 
17271f0e21a0SMarc Kleine-Budde 	/* RX errors */
1728eb79a267SMarc Kleine-Budde 	if (bdiag1 & (MCP251XFD_REG_BDIAG1_DCRCERR |
1729eb79a267SMarc Kleine-Budde 		      MCP251XFD_REG_BDIAG1_NCRCERR)) {
17301f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev, "CRC error\n");
17311f0e21a0SMarc Kleine-Budde 
17321f0e21a0SMarc Kleine-Budde 		stats->rx_errors++;
17331f0e21a0SMarc Kleine-Budde 		if (cf)
17341f0e21a0SMarc Kleine-Budde 			cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
17351f0e21a0SMarc Kleine-Budde 	}
1736eb79a267SMarc Kleine-Budde 	if (bdiag1 & (MCP251XFD_REG_BDIAG1_DSTUFERR |
1737eb79a267SMarc Kleine-Budde 		      MCP251XFD_REG_BDIAG1_NSTUFERR)) {
17381f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev, "Stuff error\n");
17391f0e21a0SMarc Kleine-Budde 
17401f0e21a0SMarc Kleine-Budde 		stats->rx_errors++;
17411f0e21a0SMarc Kleine-Budde 		if (cf)
17421f0e21a0SMarc Kleine-Budde 			cf->data[2] |= CAN_ERR_PROT_STUFF;
17431f0e21a0SMarc Kleine-Budde 	}
1744eb79a267SMarc Kleine-Budde 	if (bdiag1 & (MCP251XFD_REG_BDIAG1_DFORMERR |
1745eb79a267SMarc Kleine-Budde 		      MCP251XFD_REG_BDIAG1_NFORMERR)) {
17461f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev, "Format error\n");
17471f0e21a0SMarc Kleine-Budde 
17481f0e21a0SMarc Kleine-Budde 		stats->rx_errors++;
17491f0e21a0SMarc Kleine-Budde 		if (cf)
17501f0e21a0SMarc Kleine-Budde 			cf->data[2] |= CAN_ERR_PROT_FORM;
17511f0e21a0SMarc Kleine-Budde 	}
17521f0e21a0SMarc Kleine-Budde 
17531f0e21a0SMarc Kleine-Budde 	/* TX errors */
1754eb79a267SMarc Kleine-Budde 	if (bdiag1 & MCP251XFD_REG_BDIAG1_NACKERR) {
17551f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev, "NACK error\n");
17561f0e21a0SMarc Kleine-Budde 
17571f0e21a0SMarc Kleine-Budde 		stats->tx_errors++;
17581f0e21a0SMarc Kleine-Budde 		if (cf) {
17591f0e21a0SMarc Kleine-Budde 			cf->can_id |= CAN_ERR_ACK;
17601f0e21a0SMarc Kleine-Budde 			cf->data[2] |= CAN_ERR_PROT_TX;
17611f0e21a0SMarc Kleine-Budde 		}
17621f0e21a0SMarc Kleine-Budde 	}
1763eb79a267SMarc Kleine-Budde 	if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT1ERR |
1764eb79a267SMarc Kleine-Budde 		      MCP251XFD_REG_BDIAG1_NBIT1ERR)) {
17651f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev, "Bit1 error\n");
17661f0e21a0SMarc Kleine-Budde 
17671f0e21a0SMarc Kleine-Budde 		stats->tx_errors++;
17681f0e21a0SMarc Kleine-Budde 		if (cf)
17691f0e21a0SMarc Kleine-Budde 			cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT1;
17701f0e21a0SMarc Kleine-Budde 	}
1771eb79a267SMarc Kleine-Budde 	if (bdiag1 & (MCP251XFD_REG_BDIAG1_DBIT0ERR |
1772eb79a267SMarc Kleine-Budde 		      MCP251XFD_REG_BDIAG1_NBIT0ERR)) {
17731f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev, "Bit0 error\n");
17741f0e21a0SMarc Kleine-Budde 
17751f0e21a0SMarc Kleine-Budde 		stats->tx_errors++;
17761f0e21a0SMarc Kleine-Budde 		if (cf)
17771f0e21a0SMarc Kleine-Budde 			cf->data[2] |= CAN_ERR_PROT_TX | CAN_ERR_PROT_BIT0;
17781f0e21a0SMarc Kleine-Budde 	}
17791f0e21a0SMarc Kleine-Budde 
17801f0e21a0SMarc Kleine-Budde 	if (!cf)
17811f0e21a0SMarc Kleine-Budde 		return 0;
17821f0e21a0SMarc Kleine-Budde 
17835f02a49cSMarc Kleine-Budde 	mcp251xfd_skb_set_timestamp(priv, skb, timestamp);
17841f0e21a0SMarc Kleine-Budde 	err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
17851f0e21a0SMarc Kleine-Budde 	if (err)
17861f0e21a0SMarc Kleine-Budde 		stats->rx_fifo_errors++;
17871f0e21a0SMarc Kleine-Budde 
17881f0e21a0SMarc Kleine-Budde 	return 0;
17891f0e21a0SMarc Kleine-Budde }
17901f0e21a0SMarc Kleine-Budde 
1791eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv)
17921f0e21a0SMarc Kleine-Budde {
17931f0e21a0SMarc Kleine-Budde 	struct net_device_stats *stats = &priv->ndev->stats;
17941f0e21a0SMarc Kleine-Budde 	struct sk_buff *skb;
17951f0e21a0SMarc Kleine-Budde 	struct can_frame *cf = NULL;
17961f0e21a0SMarc Kleine-Budde 	enum can_state new_state, rx_state, tx_state;
17971f0e21a0SMarc Kleine-Budde 	u32 trec, timestamp;
17981f0e21a0SMarc Kleine-Budde 	int err;
17991f0e21a0SMarc Kleine-Budde 
1800eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec);
18011f0e21a0SMarc Kleine-Budde 	if (err)
18021f0e21a0SMarc Kleine-Budde 		return err;
18031f0e21a0SMarc Kleine-Budde 
1804eb79a267SMarc Kleine-Budde 	if (trec & MCP251XFD_REG_TREC_TXBO)
18051f0e21a0SMarc Kleine-Budde 		tx_state = CAN_STATE_BUS_OFF;
1806eb79a267SMarc Kleine-Budde 	else if (trec & MCP251XFD_REG_TREC_TXBP)
18071f0e21a0SMarc Kleine-Budde 		tx_state = CAN_STATE_ERROR_PASSIVE;
1808eb79a267SMarc Kleine-Budde 	else if (trec & MCP251XFD_REG_TREC_TXWARN)
18091f0e21a0SMarc Kleine-Budde 		tx_state = CAN_STATE_ERROR_WARNING;
18101f0e21a0SMarc Kleine-Budde 	else
18111f0e21a0SMarc Kleine-Budde 		tx_state = CAN_STATE_ERROR_ACTIVE;
18121f0e21a0SMarc Kleine-Budde 
1813eb79a267SMarc Kleine-Budde 	if (trec & MCP251XFD_REG_TREC_RXBP)
18141f0e21a0SMarc Kleine-Budde 		rx_state = CAN_STATE_ERROR_PASSIVE;
1815eb79a267SMarc Kleine-Budde 	else if (trec & MCP251XFD_REG_TREC_RXWARN)
18161f0e21a0SMarc Kleine-Budde 		rx_state = CAN_STATE_ERROR_WARNING;
18171f0e21a0SMarc Kleine-Budde 	else
18181f0e21a0SMarc Kleine-Budde 		rx_state = CAN_STATE_ERROR_ACTIVE;
18191f0e21a0SMarc Kleine-Budde 
18201f0e21a0SMarc Kleine-Budde 	new_state = max(tx_state, rx_state);
18211f0e21a0SMarc Kleine-Budde 	if (new_state == priv->can.state)
18221f0e21a0SMarc Kleine-Budde 		return 0;
18231f0e21a0SMarc Kleine-Budde 
18241f0e21a0SMarc Kleine-Budde 	/* The skb allocation might fail, but can_change_state()
18251f0e21a0SMarc Kleine-Budde 	 * handles cf == NULL.
18261f0e21a0SMarc Kleine-Budde 	 */
1827eb79a267SMarc Kleine-Budde 	skb = mcp251xfd_alloc_can_err_skb(priv, &cf, &timestamp);
18281f0e21a0SMarc Kleine-Budde 	can_change_state(priv->ndev, cf, tx_state, rx_state);
18291f0e21a0SMarc Kleine-Budde 
18301f0e21a0SMarc Kleine-Budde 	if (new_state == CAN_STATE_BUS_OFF) {
18311f0e21a0SMarc Kleine-Budde 		/* As we're going to switch off the chip now, let's
18321f0e21a0SMarc Kleine-Budde 		 * save the error counters and return them to
18331f0e21a0SMarc Kleine-Budde 		 * userspace, if do_get_berr_counter() is called while
18341f0e21a0SMarc Kleine-Budde 		 * the chip is in Bus Off.
18351f0e21a0SMarc Kleine-Budde 		 */
1836eb79a267SMarc Kleine-Budde 		err = __mcp251xfd_get_berr_counter(priv->ndev, &priv->bec);
18371f0e21a0SMarc Kleine-Budde 		if (err)
18381f0e21a0SMarc Kleine-Budde 			return err;
18391f0e21a0SMarc Kleine-Budde 
1840eb79a267SMarc Kleine-Budde 		mcp251xfd_chip_stop(priv, CAN_STATE_BUS_OFF);
18411f0e21a0SMarc Kleine-Budde 		can_bus_off(priv->ndev);
18421f0e21a0SMarc Kleine-Budde 	}
18431f0e21a0SMarc Kleine-Budde 
18441f0e21a0SMarc Kleine-Budde 	if (!skb)
18451f0e21a0SMarc Kleine-Budde 		return 0;
18461f0e21a0SMarc Kleine-Budde 
18471f0e21a0SMarc Kleine-Budde 	if (new_state != CAN_STATE_BUS_OFF) {
18481f0e21a0SMarc Kleine-Budde 		struct can_berr_counter bec;
18491f0e21a0SMarc Kleine-Budde 
1850eb79a267SMarc Kleine-Budde 		err = mcp251xfd_get_berr_counter(priv->ndev, &bec);
18511f0e21a0SMarc Kleine-Budde 		if (err)
18521f0e21a0SMarc Kleine-Budde 			return err;
18531f0e21a0SMarc Kleine-Budde 		cf->data[6] = bec.txerr;
18541f0e21a0SMarc Kleine-Budde 		cf->data[7] = bec.rxerr;
18551f0e21a0SMarc Kleine-Budde 	}
18561f0e21a0SMarc Kleine-Budde 
18571f0e21a0SMarc Kleine-Budde 	err = can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);
18581f0e21a0SMarc Kleine-Budde 	if (err)
18591f0e21a0SMarc Kleine-Budde 		stats->rx_fifo_errors++;
18601f0e21a0SMarc Kleine-Budde 
18611f0e21a0SMarc Kleine-Budde 	return 0;
18621f0e21a0SMarc Kleine-Budde }
18631f0e21a0SMarc Kleine-Budde 
18641f0e21a0SMarc Kleine-Budde static int
1865eb79a267SMarc Kleine-Budde mcp251xfd_handle_modif(const struct mcp251xfd_priv *priv, bool *set_normal_mode)
18661f0e21a0SMarc Kleine-Budde {
1867eb79a267SMarc Kleine-Budde 	const u8 mode_reference = mcp251xfd_get_normal_mode(priv);
18681f0e21a0SMarc Kleine-Budde 	u8 mode;
18691f0e21a0SMarc Kleine-Budde 	int err;
18701f0e21a0SMarc Kleine-Budde 
1871eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_get_mode(priv, &mode);
18721f0e21a0SMarc Kleine-Budde 	if (err)
18731f0e21a0SMarc Kleine-Budde 		return err;
18741f0e21a0SMarc Kleine-Budde 
18751f0e21a0SMarc Kleine-Budde 	if (mode == mode_reference) {
18761f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev,
18771f0e21a0SMarc Kleine-Budde 			   "Controller changed into %s Mode (%u).\n",
1878eb79a267SMarc Kleine-Budde 			   mcp251xfd_get_mode_str(mode), mode);
18791f0e21a0SMarc Kleine-Budde 		return 0;
18801f0e21a0SMarc Kleine-Budde 	}
18811f0e21a0SMarc Kleine-Budde 
18821f0e21a0SMarc Kleine-Budde 	/* According to MCP2517FD errata DS80000792B 1., during a TX
18831f0e21a0SMarc Kleine-Budde 	 * MAB underflow, the controller will transition to Restricted
18841f0e21a0SMarc Kleine-Budde 	 * Operation Mode or Listen Only Mode (depending on SERR2LOM).
18851f0e21a0SMarc Kleine-Budde 	 *
18861f0e21a0SMarc Kleine-Budde 	 * However this is not always the case. If SERR2LOM is
18871f0e21a0SMarc Kleine-Budde 	 * configured for Restricted Operation Mode (SERR2LOM not set)
18881f0e21a0SMarc Kleine-Budde 	 * the MCP2517FD will sometimes transition to Listen Only Mode
18891f0e21a0SMarc Kleine-Budde 	 * first. When polling this bit we see that it will transition
18901f0e21a0SMarc Kleine-Budde 	 * to Restricted Operation Mode shortly after.
18911f0e21a0SMarc Kleine-Budde 	 */
1892eb79a267SMarc Kleine-Budde 	if ((priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN) &&
1893eb79a267SMarc Kleine-Budde 	    (mode == MCP251XFD_REG_CON_MODE_RESTRICTED ||
1894eb79a267SMarc Kleine-Budde 	     mode == MCP251XFD_REG_CON_MODE_LISTENONLY))
18951f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev,
18961f0e21a0SMarc Kleine-Budde 			   "Controller changed into %s Mode (%u).\n",
1897eb79a267SMarc Kleine-Budde 			   mcp251xfd_get_mode_str(mode), mode);
18981f0e21a0SMarc Kleine-Budde 	else
18991f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
19001f0e21a0SMarc Kleine-Budde 			   "Controller changed into %s Mode (%u).\n",
1901eb79a267SMarc Kleine-Budde 			   mcp251xfd_get_mode_str(mode), mode);
19021f0e21a0SMarc Kleine-Budde 
1903f93486a7SMarc Kleine-Budde 	/* After the application requests Normal mode, the controller
19041f0e21a0SMarc Kleine-Budde 	 * will automatically attempt to retransmit the message that
19051f0e21a0SMarc Kleine-Budde 	 * caused the TX MAB underflow.
19061f0e21a0SMarc Kleine-Budde 	 *
19071f0e21a0SMarc Kleine-Budde 	 * However, if there is an ECC error in the TX-RAM, we first
19081f0e21a0SMarc Kleine-Budde 	 * have to reload the tx-object before requesting Normal
1909eb79a267SMarc Kleine-Budde 	 * mode. This is done later in mcp251xfd_handle_eccif().
19101f0e21a0SMarc Kleine-Budde 	 */
1911eb79a267SMarc Kleine-Budde 	if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF) {
19121f0e21a0SMarc Kleine-Budde 		*set_normal_mode = true;
19131f0e21a0SMarc Kleine-Budde 		return 0;
19141f0e21a0SMarc Kleine-Budde 	}
19151f0e21a0SMarc Kleine-Budde 
1916eb79a267SMarc Kleine-Budde 	return mcp251xfd_chip_set_normal_mode_nowait(priv);
19171f0e21a0SMarc Kleine-Budde }
19181f0e21a0SMarc Kleine-Budde 
1919eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_serrif(struct mcp251xfd_priv *priv)
19201f0e21a0SMarc Kleine-Budde {
1921eb79a267SMarc Kleine-Budde 	struct mcp251xfd_ecc *ecc = &priv->ecc;
19221f0e21a0SMarc Kleine-Budde 	struct net_device_stats *stats = &priv->ndev->stats;
19231f0e21a0SMarc Kleine-Budde 	bool handled = false;
19241f0e21a0SMarc Kleine-Budde 
19251f0e21a0SMarc Kleine-Budde 	/* TX MAB underflow
19261f0e21a0SMarc Kleine-Budde 	 *
19271f0e21a0SMarc Kleine-Budde 	 * According to MCP2517FD Errata DS80000792B 1. a TX MAB
19281f0e21a0SMarc Kleine-Budde 	 * underflow is indicated by SERRIF and MODIF.
19291f0e21a0SMarc Kleine-Budde 	 *
19301f0e21a0SMarc Kleine-Budde 	 * In addition to the effects mentioned in the Errata, there
19311f0e21a0SMarc Kleine-Budde 	 * are Bus Errors due to the aborted CAN frame, so a IVMIF
19321f0e21a0SMarc Kleine-Budde 	 * will be seen as well.
19331f0e21a0SMarc Kleine-Budde 	 *
19341f0e21a0SMarc Kleine-Budde 	 * Sometimes there is an ECC error in the TX-RAM, which leads
19351f0e21a0SMarc Kleine-Budde 	 * to a TX MAB underflow.
19361f0e21a0SMarc Kleine-Budde 	 *
19371f0e21a0SMarc Kleine-Budde 	 * However, probably due to a race condition, there is no
19381f0e21a0SMarc Kleine-Budde 	 * associated MODIF pending.
19391f0e21a0SMarc Kleine-Budde 	 *
19401f0e21a0SMarc Kleine-Budde 	 * Further, there are situations, where the SERRIF is caused
19411f0e21a0SMarc Kleine-Budde 	 * by an ECC error in the TX-RAM, but not even the ECCIF is
19421f0e21a0SMarc Kleine-Budde 	 * set. This only seems to happen _after_ the first occurrence
19431f0e21a0SMarc Kleine-Budde 	 * of a ECCIF (which is tracked in ecc->cnt).
19441f0e21a0SMarc Kleine-Budde 	 *
19451f0e21a0SMarc Kleine-Budde 	 * Treat all as a known system errors..
19461f0e21a0SMarc Kleine-Budde 	 */
1947eb79a267SMarc Kleine-Budde 	if ((priv->regs_status.intf & MCP251XFD_REG_INT_MODIF &&
1948eb79a267SMarc Kleine-Budde 	     priv->regs_status.intf & MCP251XFD_REG_INT_IVMIF) ||
1949eb79a267SMarc Kleine-Budde 	    priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF ||
19501f0e21a0SMarc Kleine-Budde 	    ecc->cnt) {
19511f0e21a0SMarc Kleine-Budde 		const char *msg;
19521f0e21a0SMarc Kleine-Budde 
1953eb79a267SMarc Kleine-Budde 		if (priv->regs_status.intf & MCP251XFD_REG_INT_ECCIF ||
19541f0e21a0SMarc Kleine-Budde 		    ecc->cnt)
19551f0e21a0SMarc Kleine-Budde 			msg = "TX MAB underflow due to ECC error detected.";
19561f0e21a0SMarc Kleine-Budde 		else
19571f0e21a0SMarc Kleine-Budde 			msg = "TX MAB underflow detected.";
19581f0e21a0SMarc Kleine-Budde 
1959eb79a267SMarc Kleine-Budde 		if (priv->devtype_data.quirks & MCP251XFD_QUIRK_MAB_NO_WARN)
19601f0e21a0SMarc Kleine-Budde 			netdev_dbg(priv->ndev, "%s\n", msg);
19611f0e21a0SMarc Kleine-Budde 		else
19621f0e21a0SMarc Kleine-Budde 			netdev_info(priv->ndev, "%s\n", msg);
19631f0e21a0SMarc Kleine-Budde 
19641f0e21a0SMarc Kleine-Budde 		stats->tx_aborted_errors++;
19651f0e21a0SMarc Kleine-Budde 		stats->tx_errors++;
19661f0e21a0SMarc Kleine-Budde 		handled = true;
19671f0e21a0SMarc Kleine-Budde 	}
19681f0e21a0SMarc Kleine-Budde 
19691f0e21a0SMarc Kleine-Budde 	/* RX MAB overflow
19701f0e21a0SMarc Kleine-Budde 	 *
19711f0e21a0SMarc Kleine-Budde 	 * According to MCP2517FD Errata DS80000792B 1. a RX MAB
19721f0e21a0SMarc Kleine-Budde 	 * overflow is indicated by SERRIF.
19731f0e21a0SMarc Kleine-Budde 	 *
19741f0e21a0SMarc Kleine-Budde 	 * In addition to the effects mentioned in the Errata, (most
19751f0e21a0SMarc Kleine-Budde 	 * of the times) a RXOVIF is raised, if the FIFO that is being
19761f0e21a0SMarc Kleine-Budde 	 * received into has the RXOVIE activated (and we have enabled
19771f0e21a0SMarc Kleine-Budde 	 * RXOVIE on all FIFOs).
19781f0e21a0SMarc Kleine-Budde 	 *
19791f0e21a0SMarc Kleine-Budde 	 * Sometimes there is no RXOVIF just a RXIF is pending.
19801f0e21a0SMarc Kleine-Budde 	 *
19811f0e21a0SMarc Kleine-Budde 	 * Treat all as a known system errors..
19821f0e21a0SMarc Kleine-Budde 	 */
1983eb79a267SMarc Kleine-Budde 	if (priv->regs_status.intf & MCP251XFD_REG_INT_RXOVIF ||
1984eb79a267SMarc Kleine-Budde 	    priv->regs_status.intf & MCP251XFD_REG_INT_RXIF) {
19851f0e21a0SMarc Kleine-Budde 		stats->rx_dropped++;
19861f0e21a0SMarc Kleine-Budde 		handled = true;
19871f0e21a0SMarc Kleine-Budde 	}
19881f0e21a0SMarc Kleine-Budde 
19891f0e21a0SMarc Kleine-Budde 	if (!handled)
19901f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
19911f0e21a0SMarc Kleine-Budde 			   "Unhandled System Error Interrupt (intf=0x%08x)!\n",
19921f0e21a0SMarc Kleine-Budde 			   priv->regs_status.intf);
19931f0e21a0SMarc Kleine-Budde 
19941f0e21a0SMarc Kleine-Budde 	return 0;
19951f0e21a0SMarc Kleine-Budde }
19961f0e21a0SMarc Kleine-Budde 
19971f0e21a0SMarc Kleine-Budde static int
1998eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif_recover(struct mcp251xfd_priv *priv, u8 nr)
19991f0e21a0SMarc Kleine-Budde {
2000eb79a267SMarc Kleine-Budde 	struct mcp251xfd_tx_ring *tx_ring = priv->tx;
2001eb79a267SMarc Kleine-Budde 	struct mcp251xfd_ecc *ecc = &priv->ecc;
2002eb79a267SMarc Kleine-Budde 	struct mcp251xfd_tx_obj *tx_obj;
20031f0e21a0SMarc Kleine-Budde 	u8 chip_tx_tail, tx_tail, offset;
20041f0e21a0SMarc Kleine-Budde 	u16 addr;
20051f0e21a0SMarc Kleine-Budde 	int err;
20061f0e21a0SMarc Kleine-Budde 
2007eb79a267SMarc Kleine-Budde 	addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc->ecc_stat);
20081f0e21a0SMarc Kleine-Budde 
2009eb79a267SMarc Kleine-Budde 	err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail);
20101f0e21a0SMarc Kleine-Budde 	if (err)
20111f0e21a0SMarc Kleine-Budde 		return err;
20121f0e21a0SMarc Kleine-Budde 
2013eb79a267SMarc Kleine-Budde 	tx_tail = mcp251xfd_get_tx_tail(tx_ring);
20141f0e21a0SMarc Kleine-Budde 	offset = (nr - chip_tx_tail) & (tx_ring->obj_num - 1);
20151f0e21a0SMarc Kleine-Budde 
20161f0e21a0SMarc Kleine-Budde 	/* Bail out if one of the following is met:
20171f0e21a0SMarc Kleine-Budde 	 * - tx_tail information is inconsistent
20181f0e21a0SMarc Kleine-Budde 	 * - for mcp2517fd: offset not 0
20191f0e21a0SMarc Kleine-Budde 	 * - for mcp2518fd: offset not 0 or 1
20201f0e21a0SMarc Kleine-Budde 	 */
20211f0e21a0SMarc Kleine-Budde 	if (chip_tx_tail != tx_tail ||
2022eb79a267SMarc Kleine-Budde 	    !(offset == 0 || (offset == 1 && mcp251xfd_is_2518(priv)))) {
20231f0e21a0SMarc Kleine-Budde 		netdev_err(priv->ndev,
20241f0e21a0SMarc Kleine-Budde 			   "ECC Error information inconsistent (addr=0x%04x, nr=%d, tx_tail=0x%08x(%d), chip_tx_tail=%d, offset=%d).\n",
20251f0e21a0SMarc Kleine-Budde 			   addr, nr, tx_ring->tail, tx_tail, chip_tx_tail,
20261f0e21a0SMarc Kleine-Budde 			   offset);
20271f0e21a0SMarc Kleine-Budde 		return -EINVAL;
20281f0e21a0SMarc Kleine-Budde 	}
20291f0e21a0SMarc Kleine-Budde 
20301f0e21a0SMarc Kleine-Budde 	netdev_info(priv->ndev,
20311f0e21a0SMarc Kleine-Budde 		    "Recovering %s ECC Error at address 0x%04x (in TX-RAM, tx_obj=%d, tx_tail=0x%08x(%d), offset=%d).\n",
2032eb79a267SMarc Kleine-Budde 		    ecc->ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF ?
20331f0e21a0SMarc Kleine-Budde 		    "Single" : "Double",
20341f0e21a0SMarc Kleine-Budde 		    addr, nr, tx_ring->tail, tx_tail, offset);
20351f0e21a0SMarc Kleine-Budde 
20361f0e21a0SMarc Kleine-Budde 	/* reload tx_obj into controller RAM ... */
20371f0e21a0SMarc Kleine-Budde 	tx_obj = &tx_ring->obj[nr];
20381f0e21a0SMarc Kleine-Budde 	err = spi_sync_transfer(priv->spi, tx_obj->xfer, 1);
20391f0e21a0SMarc Kleine-Budde 	if (err)
20401f0e21a0SMarc Kleine-Budde 		return err;
20411f0e21a0SMarc Kleine-Budde 
20421f0e21a0SMarc Kleine-Budde 	/* ... and trigger retransmit */
2043eb79a267SMarc Kleine-Budde 	return mcp251xfd_chip_set_normal_mode(priv);
20441f0e21a0SMarc Kleine-Budde }
20451f0e21a0SMarc Kleine-Budde 
20461f0e21a0SMarc Kleine-Budde static int
2047eb79a267SMarc Kleine-Budde mcp251xfd_handle_eccif(struct mcp251xfd_priv *priv, bool set_normal_mode)
20481f0e21a0SMarc Kleine-Budde {
2049eb79a267SMarc Kleine-Budde 	struct mcp251xfd_ecc *ecc = &priv->ecc;
20501f0e21a0SMarc Kleine-Budde 	const char *msg;
20511f0e21a0SMarc Kleine-Budde 	bool in_tx_ram;
20521f0e21a0SMarc Kleine-Budde 	u32 ecc_stat;
20531f0e21a0SMarc Kleine-Budde 	u16 addr;
20541f0e21a0SMarc Kleine-Budde 	u8 nr;
20551f0e21a0SMarc Kleine-Budde 	int err;
20561f0e21a0SMarc Kleine-Budde 
2057eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_ECCSTAT, &ecc_stat);
20581f0e21a0SMarc Kleine-Budde 	if (err)
20591f0e21a0SMarc Kleine-Budde 		return err;
20601f0e21a0SMarc Kleine-Budde 
2061eb79a267SMarc Kleine-Budde 	err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_ECCSTAT,
2062eb79a267SMarc Kleine-Budde 				 MCP251XFD_REG_ECCSTAT_IF_MASK, ~ecc_stat);
20631f0e21a0SMarc Kleine-Budde 	if (err)
20641f0e21a0SMarc Kleine-Budde 		return err;
20651f0e21a0SMarc Kleine-Budde 
20661f0e21a0SMarc Kleine-Budde 	/* Check if ECC error occurred in TX-RAM */
2067eb79a267SMarc Kleine-Budde 	addr = FIELD_GET(MCP251XFD_REG_ECCSTAT_ERRADDR_MASK, ecc_stat);
2068eb79a267SMarc Kleine-Budde 	err = mcp251xfd_get_tx_nr_by_addr(priv->tx, &nr, addr);
20691f0e21a0SMarc Kleine-Budde 	if (!err)
20701f0e21a0SMarc Kleine-Budde 		in_tx_ram = true;
20711f0e21a0SMarc Kleine-Budde 	else if (err == -ENOENT)
20721f0e21a0SMarc Kleine-Budde 		in_tx_ram = false;
20731f0e21a0SMarc Kleine-Budde 	else
20741f0e21a0SMarc Kleine-Budde 		return err;
20751f0e21a0SMarc Kleine-Budde 
20761f0e21a0SMarc Kleine-Budde 	/* Errata Reference:
20771f0e21a0SMarc Kleine-Budde 	 * mcp2517fd: DS80000789B, mcp2518fd: DS80000792C 2.
20781f0e21a0SMarc Kleine-Budde 	 *
20791f0e21a0SMarc Kleine-Budde 	 * ECC single error correction does not work in all cases:
20801f0e21a0SMarc Kleine-Budde 	 *
20811f0e21a0SMarc Kleine-Budde 	 * Fix/Work Around:
20821f0e21a0SMarc Kleine-Budde 	 * Enable single error correction and double error detection
20831f0e21a0SMarc Kleine-Budde 	 * interrupts by setting SECIE and DEDIE. Handle SECIF as a
20841f0e21a0SMarc Kleine-Budde 	 * detection interrupt and do not rely on the error
20851f0e21a0SMarc Kleine-Budde 	 * correction. Instead, handle both interrupts as a
20861f0e21a0SMarc Kleine-Budde 	 * notification that the RAM word at ERRADDR was corrupted.
20871f0e21a0SMarc Kleine-Budde 	 */
2088eb79a267SMarc Kleine-Budde 	if (ecc_stat & MCP251XFD_REG_ECCSTAT_SECIF)
20891f0e21a0SMarc Kleine-Budde 		msg = "Single ECC Error detected at address";
2090eb79a267SMarc Kleine-Budde 	else if (ecc_stat & MCP251XFD_REG_ECCSTAT_DEDIF)
20911f0e21a0SMarc Kleine-Budde 		msg = "Double ECC Error detected at address";
20921f0e21a0SMarc Kleine-Budde 	else
20931f0e21a0SMarc Kleine-Budde 		return -EINVAL;
20941f0e21a0SMarc Kleine-Budde 
20951f0e21a0SMarc Kleine-Budde 	if (!in_tx_ram) {
20961f0e21a0SMarc Kleine-Budde 		ecc->ecc_stat = 0;
20971f0e21a0SMarc Kleine-Budde 
20981f0e21a0SMarc Kleine-Budde 		netdev_notice(priv->ndev, "%s 0x%04x.\n", msg, addr);
20991f0e21a0SMarc Kleine-Budde 	} else {
21001f0e21a0SMarc Kleine-Budde 		/* Re-occurring error? */
21011f0e21a0SMarc Kleine-Budde 		if (ecc->ecc_stat == ecc_stat) {
21021f0e21a0SMarc Kleine-Budde 			ecc->cnt++;
21031f0e21a0SMarc Kleine-Budde 		} else {
21041f0e21a0SMarc Kleine-Budde 			ecc->ecc_stat = ecc_stat;
21051f0e21a0SMarc Kleine-Budde 			ecc->cnt = 1;
21061f0e21a0SMarc Kleine-Budde 		}
21071f0e21a0SMarc Kleine-Budde 
21081f0e21a0SMarc Kleine-Budde 		netdev_info(priv->ndev,
21091f0e21a0SMarc Kleine-Budde 			    "%s 0x%04x (in TX-RAM, tx_obj=%d), occurred %d time%s.\n",
21101f0e21a0SMarc Kleine-Budde 			    msg, addr, nr, ecc->cnt, ecc->cnt > 1 ? "s" : "");
21111f0e21a0SMarc Kleine-Budde 
2112eb79a267SMarc Kleine-Budde 		if (ecc->cnt >= MCP251XFD_ECC_CNT_MAX)
2113eb79a267SMarc Kleine-Budde 			return mcp251xfd_handle_eccif_recover(priv, nr);
21141f0e21a0SMarc Kleine-Budde 	}
21151f0e21a0SMarc Kleine-Budde 
21161f0e21a0SMarc Kleine-Budde 	if (set_normal_mode)
2117eb79a267SMarc Kleine-Budde 		return mcp251xfd_chip_set_normal_mode_nowait(priv);
21181f0e21a0SMarc Kleine-Budde 
21191f0e21a0SMarc Kleine-Budde 	return 0;
21201f0e21a0SMarc Kleine-Budde }
21211f0e21a0SMarc Kleine-Budde 
2122eb79a267SMarc Kleine-Budde static int mcp251xfd_handle_spicrcif(struct mcp251xfd_priv *priv)
21231f0e21a0SMarc Kleine-Budde {
21241f0e21a0SMarc Kleine-Budde 	int err;
21251f0e21a0SMarc Kleine-Budde 	u32 crc;
21261f0e21a0SMarc Kleine-Budde 
2127eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_CRC, &crc);
21281f0e21a0SMarc Kleine-Budde 	if (err)
21291f0e21a0SMarc Kleine-Budde 		return err;
21301f0e21a0SMarc Kleine-Budde 
2131eb79a267SMarc Kleine-Budde 	err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_CRC,
2132eb79a267SMarc Kleine-Budde 				 MCP251XFD_REG_CRC_IF_MASK,
21331f0e21a0SMarc Kleine-Budde 				 ~crc);
21341f0e21a0SMarc Kleine-Budde 	if (err)
21351f0e21a0SMarc Kleine-Budde 		return err;
21361f0e21a0SMarc Kleine-Budde 
2137eb79a267SMarc Kleine-Budde 	if (crc & MCP251XFD_REG_CRC_FERRIF)
21381f0e21a0SMarc Kleine-Budde 		netdev_notice(priv->ndev, "CRC write command format error.\n");
2139eb79a267SMarc Kleine-Budde 	else if (crc & MCP251XFD_REG_CRC_CRCERRIF)
21401f0e21a0SMarc Kleine-Budde 		netdev_notice(priv->ndev,
21411f0e21a0SMarc Kleine-Budde 			      "CRC write error detected. CRC=0x%04lx.\n",
2142eb79a267SMarc Kleine-Budde 			      FIELD_GET(MCP251XFD_REG_CRC_MASK, crc));
21431f0e21a0SMarc Kleine-Budde 
21441f0e21a0SMarc Kleine-Budde 	return 0;
21451f0e21a0SMarc Kleine-Budde }
21461f0e21a0SMarc Kleine-Budde 
2147eb79a267SMarc Kleine-Budde #define mcp251xfd_handle(priv, irq, ...) \
21481f0e21a0SMarc Kleine-Budde ({ \
2149eb79a267SMarc Kleine-Budde 	struct mcp251xfd_priv *_priv = (priv); \
21501f0e21a0SMarc Kleine-Budde 	int err; \
21511f0e21a0SMarc Kleine-Budde \
2152eb79a267SMarc Kleine-Budde 	err = mcp251xfd_handle_##irq(_priv, ## __VA_ARGS__); \
21531f0e21a0SMarc Kleine-Budde 	if (err) \
21541f0e21a0SMarc Kleine-Budde 		netdev_err(_priv->ndev, \
2155eb79a267SMarc Kleine-Budde 			"IRQ handler mcp251xfd_handle_%s() returned %d.\n", \
21561f0e21a0SMarc Kleine-Budde 			__stringify(irq), err); \
21571f0e21a0SMarc Kleine-Budde 	err; \
21581f0e21a0SMarc Kleine-Budde })
21591f0e21a0SMarc Kleine-Budde 
2160eb79a267SMarc Kleine-Budde static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
21611f0e21a0SMarc Kleine-Budde {
2162eb79a267SMarc Kleine-Budde 	struct mcp251xfd_priv *priv = dev_id;
2163cdc4c698SSu Yanjun 	const int val_bytes = regmap_get_val_bytes(priv->map_reg);
21641f0e21a0SMarc Kleine-Budde 	irqreturn_t handled = IRQ_NONE;
21651f0e21a0SMarc Kleine-Budde 	int err;
21661f0e21a0SMarc Kleine-Budde 
21671f0e21a0SMarc Kleine-Budde 	if (priv->rx_int)
21681f0e21a0SMarc Kleine-Budde 		do {
21691f0e21a0SMarc Kleine-Budde 			int rx_pending;
21701f0e21a0SMarc Kleine-Budde 
21711f0e21a0SMarc Kleine-Budde 			rx_pending = gpiod_get_value_cansleep(priv->rx_int);
21721f0e21a0SMarc Kleine-Budde 			if (!rx_pending)
21731f0e21a0SMarc Kleine-Budde 				break;
21741f0e21a0SMarc Kleine-Budde 
2175eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, rxif);
21761f0e21a0SMarc Kleine-Budde 			if (err)
21771f0e21a0SMarc Kleine-Budde 				goto out_fail;
21781f0e21a0SMarc Kleine-Budde 
21791f0e21a0SMarc Kleine-Budde 			handled = IRQ_HANDLED;
21801f0e21a0SMarc Kleine-Budde 		} while (1);
21811f0e21a0SMarc Kleine-Budde 
21821f0e21a0SMarc Kleine-Budde 	do {
21831f0e21a0SMarc Kleine-Budde 		u32 intf_pending, intf_pending_clearable;
21841f0e21a0SMarc Kleine-Budde 		bool set_normal_mode = false;
21851f0e21a0SMarc Kleine-Budde 
2186eb79a267SMarc Kleine-Budde 		err = regmap_bulk_read(priv->map_reg, MCP251XFD_REG_INT,
21871f0e21a0SMarc Kleine-Budde 				       &priv->regs_status,
21881f0e21a0SMarc Kleine-Budde 				       sizeof(priv->regs_status) /
2189cdc4c698SSu Yanjun 				       val_bytes);
21901f0e21a0SMarc Kleine-Budde 		if (err)
21911f0e21a0SMarc Kleine-Budde 			goto out_fail;
21921f0e21a0SMarc Kleine-Budde 
2193eb79a267SMarc Kleine-Budde 		intf_pending = FIELD_GET(MCP251XFD_REG_INT_IF_MASK,
21941f0e21a0SMarc Kleine-Budde 					 priv->regs_status.intf) &
2195eb79a267SMarc Kleine-Budde 			FIELD_GET(MCP251XFD_REG_INT_IE_MASK,
21961f0e21a0SMarc Kleine-Budde 				  priv->regs_status.intf);
21971f0e21a0SMarc Kleine-Budde 
2198c757096eSMarc Kleine-Budde 		if (!(intf_pending)) {
219930bfec4fSMarc Kleine-Budde 			can_rx_offload_threaded_irq_finish(&priv->offload);
22001f0e21a0SMarc Kleine-Budde 			return handled;
2201c757096eSMarc Kleine-Budde 		}
22021f0e21a0SMarc Kleine-Budde 
22031f0e21a0SMarc Kleine-Budde 		/* Some interrupts must be ACKed in the
2204eb79a267SMarc Kleine-Budde 		 * MCP251XFD_REG_INT register.
22051f0e21a0SMarc Kleine-Budde 		 * - First ACK then handle, to avoid lost-IRQ race
22061f0e21a0SMarc Kleine-Budde 		 *   condition on fast re-occurring interrupts.
22071f0e21a0SMarc Kleine-Budde 		 * - Write "0" to clear active IRQs, "1" to all other,
22081f0e21a0SMarc Kleine-Budde 		 *   to avoid r/m/w race condition on the
2209eb79a267SMarc Kleine-Budde 		 *   MCP251XFD_REG_INT register.
22101f0e21a0SMarc Kleine-Budde 		 */
22111f0e21a0SMarc Kleine-Budde 		intf_pending_clearable = intf_pending &
2212eb79a267SMarc Kleine-Budde 			MCP251XFD_REG_INT_IF_CLEARABLE_MASK;
22131f0e21a0SMarc Kleine-Budde 		if (intf_pending_clearable) {
22141f0e21a0SMarc Kleine-Budde 			err = regmap_update_bits(priv->map_reg,
2215eb79a267SMarc Kleine-Budde 						 MCP251XFD_REG_INT,
2216eb79a267SMarc Kleine-Budde 						 MCP251XFD_REG_INT_IF_MASK,
22171f0e21a0SMarc Kleine-Budde 						 ~intf_pending_clearable);
22181f0e21a0SMarc Kleine-Budde 			if (err)
22191f0e21a0SMarc Kleine-Budde 				goto out_fail;
22201f0e21a0SMarc Kleine-Budde 		}
22211f0e21a0SMarc Kleine-Budde 
2222eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_MODIF) {
2223eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, modif, &set_normal_mode);
22241f0e21a0SMarc Kleine-Budde 			if (err)
22251f0e21a0SMarc Kleine-Budde 				goto out_fail;
22261f0e21a0SMarc Kleine-Budde 		}
22271f0e21a0SMarc Kleine-Budde 
2228eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_RXIF) {
2229eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, rxif);
22301f0e21a0SMarc Kleine-Budde 			if (err)
22311f0e21a0SMarc Kleine-Budde 				goto out_fail;
22321f0e21a0SMarc Kleine-Budde 		}
22331f0e21a0SMarc Kleine-Budde 
2234eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_TEFIF) {
2235eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, tefif);
22361f0e21a0SMarc Kleine-Budde 			if (err)
22371f0e21a0SMarc Kleine-Budde 				goto out_fail;
22381f0e21a0SMarc Kleine-Budde 		}
22391f0e21a0SMarc Kleine-Budde 
2240eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_RXOVIF) {
2241eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, rxovif);
22421f0e21a0SMarc Kleine-Budde 			if (err)
22431f0e21a0SMarc Kleine-Budde 				goto out_fail;
22441f0e21a0SMarc Kleine-Budde 		}
22451f0e21a0SMarc Kleine-Budde 
2246eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_TXATIF) {
2247eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, txatif);
22481f0e21a0SMarc Kleine-Budde 			if (err)
22491f0e21a0SMarc Kleine-Budde 				goto out_fail;
22501f0e21a0SMarc Kleine-Budde 		}
22511f0e21a0SMarc Kleine-Budde 
2252eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_IVMIF) {
2253eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, ivmif);
22541f0e21a0SMarc Kleine-Budde 			if (err)
22551f0e21a0SMarc Kleine-Budde 				goto out_fail;
22561f0e21a0SMarc Kleine-Budde 		}
22571f0e21a0SMarc Kleine-Budde 
2258eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_SERRIF) {
2259eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, serrif);
22601f0e21a0SMarc Kleine-Budde 			if (err)
22611f0e21a0SMarc Kleine-Budde 				goto out_fail;
22621f0e21a0SMarc Kleine-Budde 		}
22631f0e21a0SMarc Kleine-Budde 
2264eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_ECCIF) {
2265eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, eccif, set_normal_mode);
22661f0e21a0SMarc Kleine-Budde 			if (err)
22671f0e21a0SMarc Kleine-Budde 				goto out_fail;
22681f0e21a0SMarc Kleine-Budde 		}
22691f0e21a0SMarc Kleine-Budde 
2270eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_SPICRCIF) {
2271eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, spicrcif);
22721f0e21a0SMarc Kleine-Budde 			if (err)
22731f0e21a0SMarc Kleine-Budde 				goto out_fail;
22741f0e21a0SMarc Kleine-Budde 		}
22751f0e21a0SMarc Kleine-Budde 
22761f0e21a0SMarc Kleine-Budde 		/* On the MCP2527FD and MCP2518FD, we don't get a
22771f0e21a0SMarc Kleine-Budde 		 * CERRIF IRQ on the transition TX ERROR_WARNING -> TX
22781f0e21a0SMarc Kleine-Budde 		 * ERROR_ACTIVE.
22791f0e21a0SMarc Kleine-Budde 		 */
2280eb79a267SMarc Kleine-Budde 		if (intf_pending & MCP251XFD_REG_INT_CERRIF ||
22811f0e21a0SMarc Kleine-Budde 		    priv->can.state > CAN_STATE_ERROR_ACTIVE) {
2282eb79a267SMarc Kleine-Budde 			err = mcp251xfd_handle(priv, cerrif);
22831f0e21a0SMarc Kleine-Budde 			if (err)
22841f0e21a0SMarc Kleine-Budde 				goto out_fail;
22851f0e21a0SMarc Kleine-Budde 
22861f0e21a0SMarc Kleine-Budde 			/* In Bus Off we completely shut down the
22871f0e21a0SMarc Kleine-Budde 			 * controller. Every subsequent register read
22881f0e21a0SMarc Kleine-Budde 			 * will read bogus data, and if
2289eb79a267SMarc Kleine-Budde 			 * MCP251XFD_QUIRK_CRC_REG is enabled the CRC
22901f0e21a0SMarc Kleine-Budde 			 * check will fail, too. So leave IRQ handler
22911f0e21a0SMarc Kleine-Budde 			 * directly.
22921f0e21a0SMarc Kleine-Budde 			 */
22931f0e21a0SMarc Kleine-Budde 			if (priv->can.state == CAN_STATE_BUS_OFF)
22941f0e21a0SMarc Kleine-Budde 				return IRQ_HANDLED;
22951f0e21a0SMarc Kleine-Budde 		}
22961f0e21a0SMarc Kleine-Budde 
22971f0e21a0SMarc Kleine-Budde 		handled = IRQ_HANDLED;
22981f0e21a0SMarc Kleine-Budde 	} while (1);
22991f0e21a0SMarc Kleine-Budde 
23001f0e21a0SMarc Kleine-Budde  out_fail:
230130bfec4fSMarc Kleine-Budde 	can_rx_offload_threaded_irq_finish(&priv->offload);
2302c757096eSMarc Kleine-Budde 
23031f0e21a0SMarc Kleine-Budde 	netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n",
23041f0e21a0SMarc Kleine-Budde 		   err, priv->regs_status.intf);
2305e0ab3dd5SMarc Kleine-Budde 	mcp251xfd_dump(priv);
2306eb79a267SMarc Kleine-Budde 	mcp251xfd_chip_interrupts_disable(priv);
23071f0e21a0SMarc Kleine-Budde 
23081f0e21a0SMarc Kleine-Budde 	return handled;
23091f0e21a0SMarc Kleine-Budde }
23101f0e21a0SMarc Kleine-Budde 
23111f0e21a0SMarc Kleine-Budde static inline struct
2312eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj *mcp251xfd_get_tx_obj_next(struct mcp251xfd_tx_ring *tx_ring)
23131f0e21a0SMarc Kleine-Budde {
23141f0e21a0SMarc Kleine-Budde 	u8 tx_head;
23151f0e21a0SMarc Kleine-Budde 
2316eb79a267SMarc Kleine-Budde 	tx_head = mcp251xfd_get_tx_head(tx_ring);
23171f0e21a0SMarc Kleine-Budde 
23181f0e21a0SMarc Kleine-Budde 	return &tx_ring->obj[tx_head];
23191f0e21a0SMarc Kleine-Budde }
23201f0e21a0SMarc Kleine-Budde 
23211f0e21a0SMarc Kleine-Budde static void
2322eb79a267SMarc Kleine-Budde mcp251xfd_tx_obj_from_skb(const struct mcp251xfd_priv *priv,
2323eb79a267SMarc Kleine-Budde 			  struct mcp251xfd_tx_obj *tx_obj,
23241f0e21a0SMarc Kleine-Budde 			  const struct sk_buff *skb,
23251f0e21a0SMarc Kleine-Budde 			  unsigned int seq)
23261f0e21a0SMarc Kleine-Budde {
23271f0e21a0SMarc Kleine-Budde 	const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
2328eb79a267SMarc Kleine-Budde 	struct mcp251xfd_hw_tx_obj_raw *hw_tx_obj;
2329eb79a267SMarc Kleine-Budde 	union mcp251xfd_tx_obj_load_buf *load_buf;
23301f0e21a0SMarc Kleine-Budde 	u8 dlc;
23311f0e21a0SMarc Kleine-Budde 	u32 id, flags;
2332a68eda20SMarc Kleine-Budde 	int len_sanitized = 0, len;
23331f0e21a0SMarc Kleine-Budde 
23341f0e21a0SMarc Kleine-Budde 	if (cfd->can_id & CAN_EFF_FLAG) {
23351f0e21a0SMarc Kleine-Budde 		u32 sid, eid;
23361f0e21a0SMarc Kleine-Budde 
2337eb79a267SMarc Kleine-Budde 		sid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_SID_MASK, cfd->can_id);
2338eb79a267SMarc Kleine-Budde 		eid = FIELD_GET(MCP251XFD_REG_FRAME_EFF_EID_MASK, cfd->can_id);
23391f0e21a0SMarc Kleine-Budde 
2340eb79a267SMarc Kleine-Budde 		id = FIELD_PREP(MCP251XFD_OBJ_ID_EID_MASK, eid) |
2341eb79a267SMarc Kleine-Budde 			FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, sid);
23421f0e21a0SMarc Kleine-Budde 
2343eb79a267SMarc Kleine-Budde 		flags = MCP251XFD_OBJ_FLAGS_IDE;
23441f0e21a0SMarc Kleine-Budde 	} else {
2345eb79a267SMarc Kleine-Budde 		id = FIELD_PREP(MCP251XFD_OBJ_ID_SID_MASK, cfd->can_id);
23461f0e21a0SMarc Kleine-Budde 		flags = 0;
23471f0e21a0SMarc Kleine-Budde 	}
23481f0e21a0SMarc Kleine-Budde 
23491f0e21a0SMarc Kleine-Budde 	/* Use the MCP2518FD mask even on the MCP2517FD. It doesn't
23501f0e21a0SMarc Kleine-Budde 	 * harm, only the lower 7 bits will be transferred into the
23511f0e21a0SMarc Kleine-Budde 	 * TEF object.
23521f0e21a0SMarc Kleine-Budde 	 */
235386f1e3b1SMarc Kleine-Budde 	flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK, seq);
23541f0e21a0SMarc Kleine-Budde 
23551f0e21a0SMarc Kleine-Budde 	if (cfd->can_id & CAN_RTR_FLAG)
2356eb79a267SMarc Kleine-Budde 		flags |= MCP251XFD_OBJ_FLAGS_RTR;
2357a68eda20SMarc Kleine-Budde 	else
2358a68eda20SMarc Kleine-Budde 		len_sanitized = canfd_sanitize_len(cfd->len);
23591f0e21a0SMarc Kleine-Budde 
23601f0e21a0SMarc Kleine-Budde 	/* CANFD */
23611f0e21a0SMarc Kleine-Budde 	if (can_is_canfd_skb(skb)) {
23621f0e21a0SMarc Kleine-Budde 		if (cfd->flags & CANFD_ESI)
2363eb79a267SMarc Kleine-Budde 			flags |= MCP251XFD_OBJ_FLAGS_ESI;
23641f0e21a0SMarc Kleine-Budde 
2365eb79a267SMarc Kleine-Budde 		flags |= MCP251XFD_OBJ_FLAGS_FDF;
23661f0e21a0SMarc Kleine-Budde 
23671f0e21a0SMarc Kleine-Budde 		if (cfd->flags & CANFD_BRS)
2368eb79a267SMarc Kleine-Budde 			flags |= MCP251XFD_OBJ_FLAGS_BRS;
236986f1e3b1SMarc Kleine-Budde 
237086f1e3b1SMarc Kleine-Budde 		dlc = can_fd_len2dlc(cfd->len);
237186f1e3b1SMarc Kleine-Budde 	} else {
237286f1e3b1SMarc Kleine-Budde 		dlc = can_get_cc_dlc((struct can_frame *)cfd,
237386f1e3b1SMarc Kleine-Budde 				     priv->can.ctrlmode);
23741f0e21a0SMarc Kleine-Budde 	}
23751f0e21a0SMarc Kleine-Budde 
237649ffacbcSMarc Kleine-Budde 	flags |= FIELD_PREP(MCP251XFD_OBJ_FLAGS_DLC_MASK, dlc);
237786f1e3b1SMarc Kleine-Budde 
23781f0e21a0SMarc Kleine-Budde 	load_buf = &tx_obj->buf;
2379eb79a267SMarc Kleine-Budde 	if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX)
23801f0e21a0SMarc Kleine-Budde 		hw_tx_obj = &load_buf->crc.hw_tx_obj;
23811f0e21a0SMarc Kleine-Budde 	else
23821f0e21a0SMarc Kleine-Budde 		hw_tx_obj = &load_buf->nocrc.hw_tx_obj;
23831f0e21a0SMarc Kleine-Budde 
23841f0e21a0SMarc Kleine-Budde 	put_unaligned_le32(id, &hw_tx_obj->id);
23851f0e21a0SMarc Kleine-Budde 	put_unaligned_le32(flags, &hw_tx_obj->flags);
23861f0e21a0SMarc Kleine-Budde 
2387561aa5b4SMarc Kleine-Budde 	/* Copy data */
23881f0e21a0SMarc Kleine-Budde 	memcpy(hw_tx_obj->data, cfd->data, cfd->len);
23891f0e21a0SMarc Kleine-Budde 
2390561aa5b4SMarc Kleine-Budde 	/* Clear unused data at end of CAN frame */
2391a68eda20SMarc Kleine-Budde 	if (MCP251XFD_SANITIZE_CAN && len_sanitized) {
2392a68eda20SMarc Kleine-Budde 		int pad_len;
2393a68eda20SMarc Kleine-Budde 
2394a68eda20SMarc Kleine-Budde 		pad_len = len_sanitized - cfd->len;
2395a68eda20SMarc Kleine-Budde 		if (pad_len)
2396561aa5b4SMarc Kleine-Budde 			memset(hw_tx_obj->data + cfd->len, 0x0, pad_len);
2397a68eda20SMarc Kleine-Budde 	}
2398561aa5b4SMarc Kleine-Budde 
23991f0e21a0SMarc Kleine-Budde 	/* Number of bytes to be written into the RAM of the controller */
24001f0e21a0SMarc Kleine-Budde 	len = sizeof(hw_tx_obj->id) + sizeof(hw_tx_obj->flags);
2401eb79a267SMarc Kleine-Budde 	if (MCP251XFD_SANITIZE_CAN)
2402a68eda20SMarc Kleine-Budde 		len += round_up(len_sanitized, sizeof(u32));
24031f0e21a0SMarc Kleine-Budde 	else
24041f0e21a0SMarc Kleine-Budde 		len += round_up(cfd->len, sizeof(u32));
24051f0e21a0SMarc Kleine-Budde 
2406eb79a267SMarc Kleine-Budde 	if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX) {
24071f0e21a0SMarc Kleine-Budde 		u16 crc;
24081f0e21a0SMarc Kleine-Budde 
2409eb79a267SMarc Kleine-Budde 		mcp251xfd_spi_cmd_crc_set_len_in_ram(&load_buf->crc.cmd,
24101f0e21a0SMarc Kleine-Budde 						     len);
24111f0e21a0SMarc Kleine-Budde 		/* CRC */
24121f0e21a0SMarc Kleine-Budde 		len += sizeof(load_buf->crc.cmd);
2413eb79a267SMarc Kleine-Budde 		crc = mcp251xfd_crc16_compute(&load_buf->crc, len);
24141f0e21a0SMarc Kleine-Budde 		put_unaligned_be16(crc, (void *)load_buf + len);
24151f0e21a0SMarc Kleine-Budde 
24161f0e21a0SMarc Kleine-Budde 		/* Total length */
24171f0e21a0SMarc Kleine-Budde 		len += sizeof(load_buf->crc.crc);
24181f0e21a0SMarc Kleine-Budde 	} else {
24191f0e21a0SMarc Kleine-Budde 		len += sizeof(load_buf->nocrc.cmd);
24201f0e21a0SMarc Kleine-Budde 	}
24211f0e21a0SMarc Kleine-Budde 
24221f0e21a0SMarc Kleine-Budde 	tx_obj->xfer[0].len = len;
24231f0e21a0SMarc Kleine-Budde }
24241f0e21a0SMarc Kleine-Budde 
2425eb79a267SMarc Kleine-Budde static int mcp251xfd_tx_obj_write(const struct mcp251xfd_priv *priv,
2426eb79a267SMarc Kleine-Budde 				  struct mcp251xfd_tx_obj *tx_obj)
24271f0e21a0SMarc Kleine-Budde {
24281f0e21a0SMarc Kleine-Budde 	return spi_async(priv->spi, &tx_obj->msg);
24291f0e21a0SMarc Kleine-Budde }
24301f0e21a0SMarc Kleine-Budde 
2431eb79a267SMarc Kleine-Budde static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv,
2432eb79a267SMarc Kleine-Budde 			      struct mcp251xfd_tx_ring *tx_ring)
24331f0e21a0SMarc Kleine-Budde {
2434eb79a267SMarc Kleine-Budde 	if (mcp251xfd_get_tx_free(tx_ring) > 0)
24351f0e21a0SMarc Kleine-Budde 		return false;
24361f0e21a0SMarc Kleine-Budde 
24371f0e21a0SMarc Kleine-Budde 	netif_stop_queue(priv->ndev);
24381f0e21a0SMarc Kleine-Budde 
24391f0e21a0SMarc Kleine-Budde 	/* Memory barrier before checking tx_free (head and tail) */
24401f0e21a0SMarc Kleine-Budde 	smp_mb();
24411f0e21a0SMarc Kleine-Budde 
2442eb79a267SMarc Kleine-Budde 	if (mcp251xfd_get_tx_free(tx_ring) == 0) {
24431f0e21a0SMarc Kleine-Budde 		netdev_dbg(priv->ndev,
24441f0e21a0SMarc Kleine-Budde 			   "Stopping tx-queue (tx_head=0x%08x, tx_tail=0x%08x, len=%d).\n",
24451f0e21a0SMarc Kleine-Budde 			   tx_ring->head, tx_ring->tail,
24461f0e21a0SMarc Kleine-Budde 			   tx_ring->head - tx_ring->tail);
24471f0e21a0SMarc Kleine-Budde 
24481f0e21a0SMarc Kleine-Budde 		return true;
24491f0e21a0SMarc Kleine-Budde 	}
24501f0e21a0SMarc Kleine-Budde 
24511f0e21a0SMarc Kleine-Budde 	netif_start_queue(priv->ndev);
24521f0e21a0SMarc Kleine-Budde 
24531f0e21a0SMarc Kleine-Budde 	return false;
24541f0e21a0SMarc Kleine-Budde }
24551f0e21a0SMarc Kleine-Budde 
2456eb79a267SMarc Kleine-Budde static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
24571f0e21a0SMarc Kleine-Budde 					struct net_device *ndev)
24581f0e21a0SMarc Kleine-Budde {
2459eb79a267SMarc Kleine-Budde 	struct mcp251xfd_priv *priv = netdev_priv(ndev);
2460eb79a267SMarc Kleine-Budde 	struct mcp251xfd_tx_ring *tx_ring = priv->tx;
2461eb79a267SMarc Kleine-Budde 	struct mcp251xfd_tx_obj *tx_obj;
24620084e298SMarc Kleine-Budde 	unsigned int frame_len;
24631f0e21a0SMarc Kleine-Budde 	u8 tx_head;
24641f0e21a0SMarc Kleine-Budde 	int err;
24651f0e21a0SMarc Kleine-Budde 
24661f0e21a0SMarc Kleine-Budde 	if (can_dropped_invalid_skb(ndev, skb))
24671f0e21a0SMarc Kleine-Budde 		return NETDEV_TX_OK;
24681f0e21a0SMarc Kleine-Budde 
2469eb79a267SMarc Kleine-Budde 	if (mcp251xfd_tx_busy(priv, tx_ring))
24701f0e21a0SMarc Kleine-Budde 		return NETDEV_TX_BUSY;
24711f0e21a0SMarc Kleine-Budde 
2472eb79a267SMarc Kleine-Budde 	tx_obj = mcp251xfd_get_tx_obj_next(tx_ring);
2473eb79a267SMarc Kleine-Budde 	mcp251xfd_tx_obj_from_skb(priv, tx_obj, skb, tx_ring->head);
24741f0e21a0SMarc Kleine-Budde 
24751f0e21a0SMarc Kleine-Budde 	/* Stop queue if we occupy the complete TX FIFO */
2476eb79a267SMarc Kleine-Budde 	tx_head = mcp251xfd_get_tx_head(tx_ring);
24771f0e21a0SMarc Kleine-Budde 	tx_ring->head++;
24789845b8f5SMarc Kleine-Budde 	if (mcp251xfd_get_tx_free(tx_ring) == 0)
24791f0e21a0SMarc Kleine-Budde 		netif_stop_queue(ndev);
24801f0e21a0SMarc Kleine-Budde 
24810084e298SMarc Kleine-Budde 	frame_len = can_skb_get_frame_len(skb);
24820084e298SMarc Kleine-Budde 	err = can_put_echo_skb(skb, ndev, tx_head, frame_len);
24830084e298SMarc Kleine-Budde 	if (!err)
24840084e298SMarc Kleine-Budde 		netdev_sent_queue(priv->ndev, frame_len);
24851f0e21a0SMarc Kleine-Budde 
2486eb79a267SMarc Kleine-Budde 	err = mcp251xfd_tx_obj_write(priv, tx_obj);
24871f0e21a0SMarc Kleine-Budde 	if (err)
24881f0e21a0SMarc Kleine-Budde 		goto out_err;
24891f0e21a0SMarc Kleine-Budde 
24901f0e21a0SMarc Kleine-Budde 	return NETDEV_TX_OK;
24911f0e21a0SMarc Kleine-Budde 
24921f0e21a0SMarc Kleine-Budde  out_err:
24931f0e21a0SMarc Kleine-Budde 	netdev_err(priv->ndev, "ERROR in %s: %d\n", __func__, err);
24941f0e21a0SMarc Kleine-Budde 
24951f0e21a0SMarc Kleine-Budde 	return NETDEV_TX_OK;
24961f0e21a0SMarc Kleine-Budde }
24971f0e21a0SMarc Kleine-Budde 
2498eb79a267SMarc Kleine-Budde static int mcp251xfd_open(struct net_device *ndev)
24991f0e21a0SMarc Kleine-Budde {
2500eb79a267SMarc Kleine-Budde 	struct mcp251xfd_priv *priv = netdev_priv(ndev);
25011f0e21a0SMarc Kleine-Budde 	const struct spi_device *spi = priv->spi;
25021f0e21a0SMarc Kleine-Budde 	int err;
25031f0e21a0SMarc Kleine-Budde 
25041f0e21a0SMarc Kleine-Budde 	err = pm_runtime_get_sync(ndev->dev.parent);
25051f0e21a0SMarc Kleine-Budde 	if (err < 0) {
25061f0e21a0SMarc Kleine-Budde 		pm_runtime_put_noidle(ndev->dev.parent);
25071f0e21a0SMarc Kleine-Budde 		return err;
25081f0e21a0SMarc Kleine-Budde 	}
25091f0e21a0SMarc Kleine-Budde 
25101f0e21a0SMarc Kleine-Budde 	err = open_candev(ndev);
25111f0e21a0SMarc Kleine-Budde 	if (err)
25121f0e21a0SMarc Kleine-Budde 		goto out_pm_runtime_put;
25131f0e21a0SMarc Kleine-Budde 
2514eb79a267SMarc Kleine-Budde 	err = mcp251xfd_ring_alloc(priv);
25151f0e21a0SMarc Kleine-Budde 	if (err)
25161f0e21a0SMarc Kleine-Budde 		goto out_close_candev;
25171f0e21a0SMarc Kleine-Budde 
2518eb79a267SMarc Kleine-Budde 	err = mcp251xfd_transceiver_enable(priv);
25191f0e21a0SMarc Kleine-Budde 	if (err)
2520eb79a267SMarc Kleine-Budde 		goto out_mcp251xfd_ring_free;
25211f0e21a0SMarc Kleine-Budde 
2522eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_start(priv);
25231f0e21a0SMarc Kleine-Budde 	if (err)
25241f0e21a0SMarc Kleine-Budde 		goto out_transceiver_disable;
25251f0e21a0SMarc Kleine-Budde 
2526efd8d98dSMarc Kleine-Budde 	mcp251xfd_timestamp_init(priv);
25271f0e21a0SMarc Kleine-Budde 	can_rx_offload_enable(&priv->offload);
25281f0e21a0SMarc Kleine-Budde 
2529eb79a267SMarc Kleine-Budde 	err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq,
2530*cb6adfe2SMarc Kleine-Budde 				   IRQF_SHARED | IRQF_ONESHOT,
2531*cb6adfe2SMarc Kleine-Budde 				   dev_name(&spi->dev), priv);
25321f0e21a0SMarc Kleine-Budde 	if (err)
25331f0e21a0SMarc Kleine-Budde 		goto out_can_rx_offload_disable;
25341f0e21a0SMarc Kleine-Budde 
2535eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_interrupts_enable(priv);
25361f0e21a0SMarc Kleine-Budde 	if (err)
25371f0e21a0SMarc Kleine-Budde 		goto out_free_irq;
25381f0e21a0SMarc Kleine-Budde 
25391f0e21a0SMarc Kleine-Budde 	netif_start_queue(ndev);
25401f0e21a0SMarc Kleine-Budde 
25411f0e21a0SMarc Kleine-Budde 	return 0;
25421f0e21a0SMarc Kleine-Budde 
25431f0e21a0SMarc Kleine-Budde  out_free_irq:
25441f0e21a0SMarc Kleine-Budde 	free_irq(spi->irq, priv);
25451f0e21a0SMarc Kleine-Budde  out_can_rx_offload_disable:
25461f0e21a0SMarc Kleine-Budde 	can_rx_offload_disable(&priv->offload);
2547efd8d98dSMarc Kleine-Budde 	mcp251xfd_timestamp_stop(priv);
25481f0e21a0SMarc Kleine-Budde  out_transceiver_disable:
2549eb79a267SMarc Kleine-Budde 	mcp251xfd_transceiver_disable(priv);
2550eb79a267SMarc Kleine-Budde  out_mcp251xfd_ring_free:
2551eb79a267SMarc Kleine-Budde 	mcp251xfd_ring_free(priv);
25521f0e21a0SMarc Kleine-Budde  out_close_candev:
25531f0e21a0SMarc Kleine-Budde 	close_candev(ndev);
25541f0e21a0SMarc Kleine-Budde  out_pm_runtime_put:
2555eb79a267SMarc Kleine-Budde 	mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED);
25561f0e21a0SMarc Kleine-Budde 	pm_runtime_put(ndev->dev.parent);
25571f0e21a0SMarc Kleine-Budde 
25581f0e21a0SMarc Kleine-Budde 	return err;
25591f0e21a0SMarc Kleine-Budde }
25601f0e21a0SMarc Kleine-Budde 
2561eb79a267SMarc Kleine-Budde static int mcp251xfd_stop(struct net_device *ndev)
25621f0e21a0SMarc Kleine-Budde {
2563eb79a267SMarc Kleine-Budde 	struct mcp251xfd_priv *priv = netdev_priv(ndev);
25641f0e21a0SMarc Kleine-Budde 
25651f0e21a0SMarc Kleine-Budde 	netif_stop_queue(ndev);
2566eb79a267SMarc Kleine-Budde 	mcp251xfd_chip_interrupts_disable(priv);
25671f0e21a0SMarc Kleine-Budde 	free_irq(ndev->irq, priv);
25681f0e21a0SMarc Kleine-Budde 	can_rx_offload_disable(&priv->offload);
2569efd8d98dSMarc Kleine-Budde 	mcp251xfd_timestamp_stop(priv);
2570eb79a267SMarc Kleine-Budde 	mcp251xfd_chip_stop(priv, CAN_STATE_STOPPED);
2571eb79a267SMarc Kleine-Budde 	mcp251xfd_transceiver_disable(priv);
2572eb79a267SMarc Kleine-Budde 	mcp251xfd_ring_free(priv);
25731f0e21a0SMarc Kleine-Budde 	close_candev(ndev);
25741f0e21a0SMarc Kleine-Budde 
25751f0e21a0SMarc Kleine-Budde 	pm_runtime_put(ndev->dev.parent);
25761f0e21a0SMarc Kleine-Budde 
25771f0e21a0SMarc Kleine-Budde 	return 0;
25781f0e21a0SMarc Kleine-Budde }
25791f0e21a0SMarc Kleine-Budde 
2580eb79a267SMarc Kleine-Budde static const struct net_device_ops mcp251xfd_netdev_ops = {
2581eb79a267SMarc Kleine-Budde 	.ndo_open = mcp251xfd_open,
2582eb79a267SMarc Kleine-Budde 	.ndo_stop = mcp251xfd_stop,
2583eb79a267SMarc Kleine-Budde 	.ndo_start_xmit	= mcp251xfd_start_xmit,
25841f0e21a0SMarc Kleine-Budde 	.ndo_change_mtu = can_change_mtu,
25851f0e21a0SMarc Kleine-Budde };
25861f0e21a0SMarc Kleine-Budde 
25871f0e21a0SMarc Kleine-Budde static void
2588eb79a267SMarc Kleine-Budde mcp251xfd_register_quirks(struct mcp251xfd_priv *priv)
25891f0e21a0SMarc Kleine-Budde {
25901f0e21a0SMarc Kleine-Budde 	const struct spi_device *spi = priv->spi;
25911f0e21a0SMarc Kleine-Budde 	const struct spi_controller *ctlr = spi->controller;
25921f0e21a0SMarc Kleine-Budde 
25931f0e21a0SMarc Kleine-Budde 	if (ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX)
2594eb79a267SMarc Kleine-Budde 		priv->devtype_data.quirks |= MCP251XFD_QUIRK_HALF_DUPLEX;
25951f0e21a0SMarc Kleine-Budde }
25961f0e21a0SMarc Kleine-Budde 
2597eb79a267SMarc Kleine-Budde static int mcp251xfd_register_chip_detect(struct mcp251xfd_priv *priv)
25981f0e21a0SMarc Kleine-Budde {
25991f0e21a0SMarc Kleine-Budde 	const struct net_device *ndev = priv->ndev;
2600eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_devtype_data *devtype_data;
26011f0e21a0SMarc Kleine-Budde 	u32 osc;
26021f0e21a0SMarc Kleine-Budde 	int err;
26031f0e21a0SMarc Kleine-Budde 
26041f0e21a0SMarc Kleine-Budde 	/* The OSC_LPMEN is only supported on MCP2518FD, so use it to
26051f0e21a0SMarc Kleine-Budde 	 * autodetect the model.
26061f0e21a0SMarc Kleine-Budde 	 */
2607eb79a267SMarc Kleine-Budde 	err = regmap_update_bits(priv->map_reg, MCP251XFD_REG_OSC,
2608eb79a267SMarc Kleine-Budde 				 MCP251XFD_REG_OSC_LPMEN,
2609eb79a267SMarc Kleine-Budde 				 MCP251XFD_REG_OSC_LPMEN);
26101f0e21a0SMarc Kleine-Budde 	if (err)
26111f0e21a0SMarc Kleine-Budde 		return err;
26121f0e21a0SMarc Kleine-Budde 
2613eb79a267SMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_OSC, &osc);
26141f0e21a0SMarc Kleine-Budde 	if (err)
26151f0e21a0SMarc Kleine-Budde 		return err;
26161f0e21a0SMarc Kleine-Budde 
2617eb79a267SMarc Kleine-Budde 	if (osc & MCP251XFD_REG_OSC_LPMEN)
2618eb79a267SMarc Kleine-Budde 		devtype_data = &mcp251xfd_devtype_data_mcp2518fd;
26191f0e21a0SMarc Kleine-Budde 	else
2620eb79a267SMarc Kleine-Budde 		devtype_data = &mcp251xfd_devtype_data_mcp2517fd;
26211f0e21a0SMarc Kleine-Budde 
2622eb79a267SMarc Kleine-Budde 	if (!mcp251xfd_is_251X(priv) &&
26231f0e21a0SMarc Kleine-Budde 	    priv->devtype_data.model != devtype_data->model) {
26241f0e21a0SMarc Kleine-Budde 		netdev_info(ndev,
26251f0e21a0SMarc Kleine-Budde 			    "Detected %s, but firmware specifies a %s. Fixing up.",
2626eb79a267SMarc Kleine-Budde 			    __mcp251xfd_get_model_str(devtype_data->model),
2627eb79a267SMarc Kleine-Budde 			    mcp251xfd_get_model_str(priv));
26281f0e21a0SMarc Kleine-Budde 	}
26291f0e21a0SMarc Kleine-Budde 	priv->devtype_data = *devtype_data;
26301f0e21a0SMarc Kleine-Budde 
26311f0e21a0SMarc Kleine-Budde 	/* We need to preserve the Half Duplex Quirk. */
2632eb79a267SMarc Kleine-Budde 	mcp251xfd_register_quirks(priv);
26331f0e21a0SMarc Kleine-Budde 
26341f0e21a0SMarc Kleine-Budde 	/* Re-init regmap with quirks of detected model. */
2635eb79a267SMarc Kleine-Budde 	return mcp251xfd_regmap_init(priv);
26361f0e21a0SMarc Kleine-Budde }
26371f0e21a0SMarc Kleine-Budde 
2638eb79a267SMarc Kleine-Budde static int mcp251xfd_register_check_rx_int(struct mcp251xfd_priv *priv)
26391f0e21a0SMarc Kleine-Budde {
26401f0e21a0SMarc Kleine-Budde 	int err, rx_pending;
26411f0e21a0SMarc Kleine-Budde 
26421f0e21a0SMarc Kleine-Budde 	if (!priv->rx_int)
26431f0e21a0SMarc Kleine-Budde 		return 0;
26441f0e21a0SMarc Kleine-Budde 
2645eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_rx_int_enable(priv);
26461f0e21a0SMarc Kleine-Budde 	if (err)
26471f0e21a0SMarc Kleine-Budde 		return err;
26481f0e21a0SMarc Kleine-Budde 
26491f0e21a0SMarc Kleine-Budde 	/* Check if RX_INT is properly working. The RX_INT should not
26501f0e21a0SMarc Kleine-Budde 	 * be active after a softreset.
26511f0e21a0SMarc Kleine-Budde 	 */
26521f0e21a0SMarc Kleine-Budde 	rx_pending = gpiod_get_value_cansleep(priv->rx_int);
26531f0e21a0SMarc Kleine-Budde 
2654eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_rx_int_disable(priv);
26551f0e21a0SMarc Kleine-Budde 	if (err)
26561f0e21a0SMarc Kleine-Budde 		return err;
26571f0e21a0SMarc Kleine-Budde 
26581f0e21a0SMarc Kleine-Budde 	if (!rx_pending)
26591f0e21a0SMarc Kleine-Budde 		return 0;
26601f0e21a0SMarc Kleine-Budde 
26611f0e21a0SMarc Kleine-Budde 	netdev_info(priv->ndev,
26621f0e21a0SMarc Kleine-Budde 		    "RX_INT active after softreset, disabling RX_INT support.");
26631f0e21a0SMarc Kleine-Budde 	devm_gpiod_put(&priv->spi->dev, priv->rx_int);
26641f0e21a0SMarc Kleine-Budde 	priv->rx_int = NULL;
26651f0e21a0SMarc Kleine-Budde 
26661f0e21a0SMarc Kleine-Budde 	return 0;
26671f0e21a0SMarc Kleine-Budde }
26681f0e21a0SMarc Kleine-Budde 
26691f0e21a0SMarc Kleine-Budde static int
2670eb79a267SMarc Kleine-Budde mcp251xfd_register_get_dev_id(const struct mcp251xfd_priv *priv,
26711f0e21a0SMarc Kleine-Budde 			      u32 *dev_id, u32 *effective_speed_hz)
26721f0e21a0SMarc Kleine-Budde {
2673eb79a267SMarc Kleine-Budde 	struct mcp251xfd_map_buf_nocrc *buf_rx;
2674eb79a267SMarc Kleine-Budde 	struct mcp251xfd_map_buf_nocrc *buf_tx;
26751f0e21a0SMarc Kleine-Budde 	struct spi_transfer xfer[2] = { };
26761f0e21a0SMarc Kleine-Budde 	int err;
26771f0e21a0SMarc Kleine-Budde 
26781f0e21a0SMarc Kleine-Budde 	buf_rx = kzalloc(sizeof(*buf_rx), GFP_KERNEL);
26791f0e21a0SMarc Kleine-Budde 	if (!buf_rx)
26801f0e21a0SMarc Kleine-Budde 		return -ENOMEM;
26811f0e21a0SMarc Kleine-Budde 
26821f0e21a0SMarc Kleine-Budde 	buf_tx = kzalloc(sizeof(*buf_tx), GFP_KERNEL);
26831f0e21a0SMarc Kleine-Budde 	if (!buf_tx) {
26841f0e21a0SMarc Kleine-Budde 		err = -ENOMEM;
26851f0e21a0SMarc Kleine-Budde 		goto out_kfree_buf_rx;
26861f0e21a0SMarc Kleine-Budde 	}
26871f0e21a0SMarc Kleine-Budde 
26881f0e21a0SMarc Kleine-Budde 	xfer[0].tx_buf = buf_tx;
26891f0e21a0SMarc Kleine-Budde 	xfer[0].len = sizeof(buf_tx->cmd);
26901f0e21a0SMarc Kleine-Budde 	xfer[1].rx_buf = buf_rx->data;
26911f0e21a0SMarc Kleine-Budde 	xfer[1].len = sizeof(dev_id);
26921f0e21a0SMarc Kleine-Budde 
2693eb79a267SMarc Kleine-Budde 	mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, MCP251XFD_REG_DEVID);
26941f0e21a0SMarc Kleine-Budde 	err = spi_sync_transfer(priv->spi, xfer, ARRAY_SIZE(xfer));
26951f0e21a0SMarc Kleine-Budde 	if (err)
26961f0e21a0SMarc Kleine-Budde 		goto out_kfree_buf_tx;
26971f0e21a0SMarc Kleine-Budde 
26981f0e21a0SMarc Kleine-Budde 	*dev_id = be32_to_cpup((__be32 *)buf_rx->data);
26991f0e21a0SMarc Kleine-Budde 	*effective_speed_hz = xfer->effective_speed_hz;
27001f0e21a0SMarc Kleine-Budde 
27011f0e21a0SMarc Kleine-Budde  out_kfree_buf_tx:
27021f0e21a0SMarc Kleine-Budde 	kfree(buf_tx);
27031f0e21a0SMarc Kleine-Budde  out_kfree_buf_rx:
27041f0e21a0SMarc Kleine-Budde 	kfree(buf_rx);
27051f0e21a0SMarc Kleine-Budde 
27061f0e21a0SMarc Kleine-Budde 	return 0;
27071f0e21a0SMarc Kleine-Budde }
27081f0e21a0SMarc Kleine-Budde 
2709eb79a267SMarc Kleine-Budde #define MCP251XFD_QUIRK_ACTIVE(quirk) \
2710eb79a267SMarc Kleine-Budde 	(priv->devtype_data.quirks & MCP251XFD_QUIRK_##quirk ? '+' : '-')
27111f0e21a0SMarc Kleine-Budde 
27121f0e21a0SMarc Kleine-Budde static int
2713eb79a267SMarc Kleine-Budde mcp251xfd_register_done(const struct mcp251xfd_priv *priv)
27141f0e21a0SMarc Kleine-Budde {
27151f0e21a0SMarc Kleine-Budde 	u32 dev_id, effective_speed_hz;
27161f0e21a0SMarc Kleine-Budde 	int err;
27171f0e21a0SMarc Kleine-Budde 
2718eb79a267SMarc Kleine-Budde 	err = mcp251xfd_register_get_dev_id(priv, &dev_id,
27191f0e21a0SMarc Kleine-Budde 					    &effective_speed_hz);
27201f0e21a0SMarc Kleine-Budde 	if (err)
27211f0e21a0SMarc Kleine-Budde 		return err;
27221f0e21a0SMarc Kleine-Budde 
27231f0e21a0SMarc Kleine-Budde 	netdev_info(priv->ndev,
27241f0e21a0SMarc 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",
2725eb79a267SMarc Kleine-Budde 		    mcp251xfd_get_model_str(priv),
2726eb79a267SMarc Kleine-Budde 		    FIELD_GET(MCP251XFD_REG_DEVID_ID_MASK, dev_id),
2727eb79a267SMarc Kleine-Budde 		    FIELD_GET(MCP251XFD_REG_DEVID_REV_MASK, dev_id),
27281f0e21a0SMarc Kleine-Budde 		    priv->rx_int ? '+' : '-',
2729eb79a267SMarc Kleine-Budde 		    MCP251XFD_QUIRK_ACTIVE(MAB_NO_WARN),
2730eb79a267SMarc Kleine-Budde 		    MCP251XFD_QUIRK_ACTIVE(CRC_REG),
2731eb79a267SMarc Kleine-Budde 		    MCP251XFD_QUIRK_ACTIVE(CRC_RX),
2732eb79a267SMarc Kleine-Budde 		    MCP251XFD_QUIRK_ACTIVE(CRC_TX),
2733eb79a267SMarc Kleine-Budde 		    MCP251XFD_QUIRK_ACTIVE(ECC),
2734eb79a267SMarc Kleine-Budde 		    MCP251XFD_QUIRK_ACTIVE(HALF_DUPLEX),
27351f0e21a0SMarc Kleine-Budde 		    priv->can.clock.freq / 1000000,
27361f0e21a0SMarc Kleine-Budde 		    priv->can.clock.freq % 1000000 / 1000 / 10,
27371f0e21a0SMarc Kleine-Budde 		    priv->spi_max_speed_hz_orig / 1000000,
27381f0e21a0SMarc Kleine-Budde 		    priv->spi_max_speed_hz_orig % 1000000 / 1000 / 10,
27391f0e21a0SMarc Kleine-Budde 		    priv->spi->max_speed_hz / 1000000,
27401f0e21a0SMarc Kleine-Budde 		    priv->spi->max_speed_hz % 1000000 / 1000 / 10,
27411f0e21a0SMarc Kleine-Budde 		    effective_speed_hz / 1000000,
27421f0e21a0SMarc Kleine-Budde 		    effective_speed_hz % 1000000 / 1000 / 10);
27431f0e21a0SMarc Kleine-Budde 
27441f0e21a0SMarc Kleine-Budde 	return 0;
27451f0e21a0SMarc Kleine-Budde }
27461f0e21a0SMarc Kleine-Budde 
2747eb79a267SMarc Kleine-Budde static int mcp251xfd_register(struct mcp251xfd_priv *priv)
27481f0e21a0SMarc Kleine-Budde {
27491f0e21a0SMarc Kleine-Budde 	struct net_device *ndev = priv->ndev;
27501f0e21a0SMarc Kleine-Budde 	int err;
27511f0e21a0SMarc Kleine-Budde 
2752eb79a267SMarc Kleine-Budde 	err = mcp251xfd_clks_and_vdd_enable(priv);
27531f0e21a0SMarc Kleine-Budde 	if (err)
27541f0e21a0SMarc Kleine-Budde 		return err;
27551f0e21a0SMarc Kleine-Budde 
27561f0e21a0SMarc Kleine-Budde 	pm_runtime_get_noresume(ndev->dev.parent);
27571f0e21a0SMarc Kleine-Budde 	err = pm_runtime_set_active(ndev->dev.parent);
27581f0e21a0SMarc Kleine-Budde 	if (err)
27591f0e21a0SMarc Kleine-Budde 		goto out_runtime_put_noidle;
27601f0e21a0SMarc Kleine-Budde 	pm_runtime_enable(ndev->dev.parent);
27611f0e21a0SMarc Kleine-Budde 
2762eb79a267SMarc Kleine-Budde 	mcp251xfd_register_quirks(priv);
27631f0e21a0SMarc Kleine-Budde 
2764eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_softreset(priv);
27651f0e21a0SMarc Kleine-Budde 	if (err == -ENODEV)
27661f0e21a0SMarc Kleine-Budde 		goto out_runtime_disable;
27671f0e21a0SMarc Kleine-Budde 	if (err)
27681f0e21a0SMarc Kleine-Budde 		goto out_chip_set_mode_sleep;
27691f0e21a0SMarc Kleine-Budde 
2770eb79a267SMarc Kleine-Budde 	err = mcp251xfd_register_chip_detect(priv);
27711f0e21a0SMarc Kleine-Budde 	if (err)
27721f0e21a0SMarc Kleine-Budde 		goto out_chip_set_mode_sleep;
27731f0e21a0SMarc Kleine-Budde 
2774eb79a267SMarc Kleine-Budde 	err = mcp251xfd_register_check_rx_int(priv);
27751f0e21a0SMarc Kleine-Budde 	if (err)
27761f0e21a0SMarc Kleine-Budde 		goto out_chip_set_mode_sleep;
27771f0e21a0SMarc Kleine-Budde 
27781f0e21a0SMarc Kleine-Budde 	err = register_candev(ndev);
27791f0e21a0SMarc Kleine-Budde 	if (err)
27801f0e21a0SMarc Kleine-Budde 		goto out_chip_set_mode_sleep;
27811f0e21a0SMarc Kleine-Budde 
2782eb79a267SMarc Kleine-Budde 	err = mcp251xfd_register_done(priv);
27831f0e21a0SMarc Kleine-Budde 	if (err)
27841f0e21a0SMarc Kleine-Budde 		goto out_unregister_candev;
27851f0e21a0SMarc Kleine-Budde 
27861f0e21a0SMarc Kleine-Budde 	/* Put controller into sleep mode and let pm_runtime_put()
27871f0e21a0SMarc Kleine-Budde 	 * disable the clocks and vdd. If CONFIG_PM is not enabled,
27881f0e21a0SMarc Kleine-Budde 	 * the clocks and vdd will stay powered.
27891f0e21a0SMarc Kleine-Budde 	 */
2790eb79a267SMarc Kleine-Budde 	err = mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP);
27911f0e21a0SMarc Kleine-Budde 	if (err)
27921f0e21a0SMarc Kleine-Budde 		goto out_unregister_candev;
27931f0e21a0SMarc Kleine-Budde 
27941f0e21a0SMarc Kleine-Budde 	pm_runtime_put(ndev->dev.parent);
27951f0e21a0SMarc Kleine-Budde 
27961f0e21a0SMarc Kleine-Budde 	return 0;
27971f0e21a0SMarc Kleine-Budde 
27981f0e21a0SMarc Kleine-Budde  out_unregister_candev:
27991f0e21a0SMarc Kleine-Budde 	unregister_candev(ndev);
28001f0e21a0SMarc Kleine-Budde  out_chip_set_mode_sleep:
2801eb79a267SMarc Kleine-Budde 	mcp251xfd_chip_set_mode(priv, MCP251XFD_REG_CON_MODE_SLEEP);
28021f0e21a0SMarc Kleine-Budde  out_runtime_disable:
28031f0e21a0SMarc Kleine-Budde 	pm_runtime_disable(ndev->dev.parent);
28041f0e21a0SMarc Kleine-Budde  out_runtime_put_noidle:
28051f0e21a0SMarc Kleine-Budde 	pm_runtime_put_noidle(ndev->dev.parent);
2806eb79a267SMarc Kleine-Budde 	mcp251xfd_clks_and_vdd_disable(priv);
28071f0e21a0SMarc Kleine-Budde 
28081f0e21a0SMarc Kleine-Budde 	return err;
28091f0e21a0SMarc Kleine-Budde }
28101f0e21a0SMarc Kleine-Budde 
2811eb79a267SMarc Kleine-Budde static inline void mcp251xfd_unregister(struct mcp251xfd_priv *priv)
28121f0e21a0SMarc Kleine-Budde {
28131f0e21a0SMarc Kleine-Budde 	struct net_device *ndev	= priv->ndev;
28141f0e21a0SMarc Kleine-Budde 
28151f0e21a0SMarc Kleine-Budde 	unregister_candev(ndev);
28161f0e21a0SMarc Kleine-Budde 
28171f0e21a0SMarc Kleine-Budde 	pm_runtime_get_sync(ndev->dev.parent);
28181f0e21a0SMarc Kleine-Budde 	pm_runtime_put_noidle(ndev->dev.parent);
2819eb79a267SMarc Kleine-Budde 	mcp251xfd_clks_and_vdd_disable(priv);
28201f0e21a0SMarc Kleine-Budde 	pm_runtime_disable(ndev->dev.parent);
28211f0e21a0SMarc Kleine-Budde }
28221f0e21a0SMarc Kleine-Budde 
2823eb79a267SMarc Kleine-Budde static const struct of_device_id mcp251xfd_of_match[] = {
28241f0e21a0SMarc Kleine-Budde 	{
28251f0e21a0SMarc Kleine-Budde 		.compatible = "microchip,mcp2517fd",
2826eb79a267SMarc Kleine-Budde 		.data = &mcp251xfd_devtype_data_mcp2517fd,
28271f0e21a0SMarc Kleine-Budde 	}, {
28281f0e21a0SMarc Kleine-Budde 		.compatible = "microchip,mcp2518fd",
2829eb79a267SMarc Kleine-Budde 		.data = &mcp251xfd_devtype_data_mcp2518fd,
28301f0e21a0SMarc Kleine-Budde 	}, {
28311f0e21a0SMarc Kleine-Budde 		.compatible = "microchip,mcp251xfd",
2832eb79a267SMarc Kleine-Budde 		.data = &mcp251xfd_devtype_data_mcp251xfd,
28331f0e21a0SMarc Kleine-Budde 	}, {
28341f0e21a0SMarc Kleine-Budde 		/* sentinel */
28351f0e21a0SMarc Kleine-Budde 	},
28361f0e21a0SMarc Kleine-Budde };
2837eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(of, mcp251xfd_of_match);
28381f0e21a0SMarc Kleine-Budde 
2839eb79a267SMarc Kleine-Budde static const struct spi_device_id mcp251xfd_id_table[] = {
28401f0e21a0SMarc Kleine-Budde 	{
28411f0e21a0SMarc Kleine-Budde 		.name = "mcp2517fd",
2842eb79a267SMarc Kleine-Budde 		.driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2517fd,
28431f0e21a0SMarc Kleine-Budde 	}, {
28441f0e21a0SMarc Kleine-Budde 		.name = "mcp2518fd",
2845eb79a267SMarc Kleine-Budde 		.driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp2518fd,
28461f0e21a0SMarc Kleine-Budde 	}, {
28471f0e21a0SMarc Kleine-Budde 		.name = "mcp251xfd",
2848eb79a267SMarc Kleine-Budde 		.driver_data = (kernel_ulong_t)&mcp251xfd_devtype_data_mcp251xfd,
28491f0e21a0SMarc Kleine-Budde 	}, {
28501f0e21a0SMarc Kleine-Budde 		/* sentinel */
28511f0e21a0SMarc Kleine-Budde 	},
28521f0e21a0SMarc Kleine-Budde };
2853eb79a267SMarc Kleine-Budde MODULE_DEVICE_TABLE(spi, mcp251xfd_id_table);
28541f0e21a0SMarc Kleine-Budde 
2855eb79a267SMarc Kleine-Budde static int mcp251xfd_probe(struct spi_device *spi)
28561f0e21a0SMarc Kleine-Budde {
28571f0e21a0SMarc Kleine-Budde 	const void *match;
28581f0e21a0SMarc Kleine-Budde 	struct net_device *ndev;
2859eb79a267SMarc Kleine-Budde 	struct mcp251xfd_priv *priv;
28601f0e21a0SMarc Kleine-Budde 	struct gpio_desc *rx_int;
28611f0e21a0SMarc Kleine-Budde 	struct regulator *reg_vdd, *reg_xceiver;
28621f0e21a0SMarc Kleine-Budde 	struct clk *clk;
286374f89cf1SAndy Shevchenko 	u32 freq = 0;
28641f0e21a0SMarc Kleine-Budde 	int err;
28651f0e21a0SMarc Kleine-Budde 
28661a1c436bSMarc Kleine-Budde 	if (!spi->irq)
28671a1c436bSMarc Kleine-Budde 		return dev_err_probe(&spi->dev, -ENXIO,
28681a1c436bSMarc Kleine-Budde 				     "No IRQ specified (maybe node \"interrupts-extended\" in DT missing)!\n");
28691a1c436bSMarc Kleine-Budde 
28701f0e21a0SMarc Kleine-Budde 	rx_int = devm_gpiod_get_optional(&spi->dev, "microchip,rx-int",
28711f0e21a0SMarc Kleine-Budde 					 GPIOD_IN);
2872cf8ee6deSMarc Kleine-Budde 	if (IS_ERR(rx_int))
2873cf8ee6deSMarc Kleine-Budde 		return dev_err_probe(&spi->dev, PTR_ERR(rx_int),
2874cf8ee6deSMarc Kleine-Budde 				     "Failed to get RX-INT!\n");
28751f0e21a0SMarc Kleine-Budde 
28761f0e21a0SMarc Kleine-Budde 	reg_vdd = devm_regulator_get_optional(&spi->dev, "vdd");
2877cf8ee6deSMarc Kleine-Budde 	if (PTR_ERR(reg_vdd) == -ENODEV)
28781f0e21a0SMarc Kleine-Budde 		reg_vdd = NULL;
28791f0e21a0SMarc Kleine-Budde 	else if (IS_ERR(reg_vdd))
2880cf8ee6deSMarc Kleine-Budde 		return dev_err_probe(&spi->dev, PTR_ERR(reg_vdd),
2881cf8ee6deSMarc Kleine-Budde 				     "Failed to get VDD regulator!\n");
28821f0e21a0SMarc Kleine-Budde 
28831f0e21a0SMarc Kleine-Budde 	reg_xceiver = devm_regulator_get_optional(&spi->dev, "xceiver");
2884cf8ee6deSMarc Kleine-Budde 	if (PTR_ERR(reg_xceiver) == -ENODEV)
28851f0e21a0SMarc Kleine-Budde 		reg_xceiver = NULL;
28861f0e21a0SMarc Kleine-Budde 	else if (IS_ERR(reg_xceiver))
2887cf8ee6deSMarc Kleine-Budde 		return dev_err_probe(&spi->dev, PTR_ERR(reg_xceiver),
2888cf8ee6deSMarc Kleine-Budde 				     "Failed to get Transceiver regulator!\n");
28891f0e21a0SMarc Kleine-Budde 
289074f89cf1SAndy Shevchenko 	clk = devm_clk_get_optional(&spi->dev, NULL);
2891cf8ee6deSMarc Kleine-Budde 	if (IS_ERR(clk))
28924cc7faa4SDan Carpenter 		return dev_err_probe(&spi->dev, PTR_ERR(clk),
2893cf8ee6deSMarc Kleine-Budde 				     "Failed to get Oscillator (clock)!\n");
289474f89cf1SAndy Shevchenko 	if (clk) {
28951f0e21a0SMarc Kleine-Budde 		freq = clk_get_rate(clk);
289674f89cf1SAndy Shevchenko 	} else {
289774f89cf1SAndy Shevchenko 		err = device_property_read_u32(&spi->dev, "clock-frequency",
289874f89cf1SAndy Shevchenko 					       &freq);
289974f89cf1SAndy Shevchenko 		if (err)
290074f89cf1SAndy Shevchenko 			return dev_err_probe(&spi->dev, err,
290174f89cf1SAndy Shevchenko 					     "Failed to get clock-frequency!\n");
290274f89cf1SAndy Shevchenko 	}
29031f0e21a0SMarc Kleine-Budde 
29041f0e21a0SMarc Kleine-Budde 	/* Sanity check */
2905eb79a267SMarc Kleine-Budde 	if (freq < MCP251XFD_SYSCLOCK_HZ_MIN ||
2906eb79a267SMarc Kleine-Budde 	    freq > MCP251XFD_SYSCLOCK_HZ_MAX) {
29071f0e21a0SMarc Kleine-Budde 		dev_err(&spi->dev,
29081f0e21a0SMarc Kleine-Budde 			"Oscillator frequency (%u Hz) is too low or high.\n",
29091f0e21a0SMarc Kleine-Budde 			freq);
29101f0e21a0SMarc Kleine-Budde 		return -ERANGE;
29111f0e21a0SMarc Kleine-Budde 	}
29121f0e21a0SMarc Kleine-Budde 
2913eb79a267SMarc Kleine-Budde 	if (freq <= MCP251XFD_SYSCLOCK_HZ_MAX / MCP251XFD_OSC_PLL_MULTIPLIER) {
29141f0e21a0SMarc Kleine-Budde 		dev_err(&spi->dev,
29151f0e21a0SMarc Kleine-Budde 			"Oscillator frequency (%u Hz) is too low and PLL is not supported.\n",
29161f0e21a0SMarc Kleine-Budde 			freq);
29171f0e21a0SMarc Kleine-Budde 		return -ERANGE;
29181f0e21a0SMarc Kleine-Budde 	}
29191f0e21a0SMarc Kleine-Budde 
2920eb79a267SMarc Kleine-Budde 	ndev = alloc_candev(sizeof(struct mcp251xfd_priv),
2921eb79a267SMarc Kleine-Budde 			    MCP251XFD_TX_OBJ_NUM_MAX);
29221f0e21a0SMarc Kleine-Budde 	if (!ndev)
29231f0e21a0SMarc Kleine-Budde 		return -ENOMEM;
29241f0e21a0SMarc Kleine-Budde 
29251f0e21a0SMarc Kleine-Budde 	SET_NETDEV_DEV(ndev, &spi->dev);
29261f0e21a0SMarc Kleine-Budde 
2927eb79a267SMarc Kleine-Budde 	ndev->netdev_ops = &mcp251xfd_netdev_ops;
29281f0e21a0SMarc Kleine-Budde 	ndev->irq = spi->irq;
29291f0e21a0SMarc Kleine-Budde 	ndev->flags |= IFF_ECHO;
29301f0e21a0SMarc Kleine-Budde 
29311f0e21a0SMarc Kleine-Budde 	priv = netdev_priv(ndev);
29321f0e21a0SMarc Kleine-Budde 	spi_set_drvdata(spi, priv);
29331f0e21a0SMarc Kleine-Budde 	priv->can.clock.freq = freq;
2934eb79a267SMarc Kleine-Budde 	priv->can.do_set_mode = mcp251xfd_set_mode;
2935eb79a267SMarc Kleine-Budde 	priv->can.do_get_berr_counter = mcp251xfd_get_berr_counter;
2936eb79a267SMarc Kleine-Budde 	priv->can.bittiming_const = &mcp251xfd_bittiming_const;
2937eb79a267SMarc Kleine-Budde 	priv->can.data_bittiming_const = &mcp251xfd_data_bittiming_const;
2938ee42bedcSManivannan Sadhasivam 	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
2939ee42bedcSManivannan Sadhasivam 		CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING |
294086f1e3b1SMarc Kleine-Budde 		CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |
294186f1e3b1SMarc Kleine-Budde 		CAN_CTRLMODE_CC_LEN8_DLC;
29421f0e21a0SMarc Kleine-Budde 	priv->ndev = ndev;
29431f0e21a0SMarc Kleine-Budde 	priv->spi = spi;
29441f0e21a0SMarc Kleine-Budde 	priv->rx_int = rx_int;
29451f0e21a0SMarc Kleine-Budde 	priv->clk = clk;
29461f0e21a0SMarc Kleine-Budde 	priv->reg_vdd = reg_vdd;
29471f0e21a0SMarc Kleine-Budde 	priv->reg_xceiver = reg_xceiver;
29481f0e21a0SMarc Kleine-Budde 
29491f0e21a0SMarc Kleine-Budde 	match = device_get_match_data(&spi->dev);
29501f0e21a0SMarc Kleine-Budde 	if (match)
2951eb79a267SMarc Kleine-Budde 		priv->devtype_data = *(struct mcp251xfd_devtype_data *)match;
29521f0e21a0SMarc Kleine-Budde 	else
2953eb79a267SMarc Kleine-Budde 		priv->devtype_data = *(struct mcp251xfd_devtype_data *)
29541f0e21a0SMarc Kleine-Budde 			spi_get_device_id(spi)->driver_data;
29551f0e21a0SMarc Kleine-Budde 
29561f0e21a0SMarc Kleine-Budde 	/* Errata Reference:
295728eb119cSMarc Kleine-Budde 	 * mcp2517fd: DS80000792C 5., mcp2518fd: DS80000789C 4.
29581f0e21a0SMarc Kleine-Budde 	 *
29591f0e21a0SMarc Kleine-Budde 	 * The SPI can write corrupted data to the RAM at fast SPI
29601f0e21a0SMarc Kleine-Budde 	 * speeds:
29611f0e21a0SMarc Kleine-Budde 	 *
29621f0e21a0SMarc Kleine-Budde 	 * Simultaneous activity on the CAN bus while writing data to
29631f0e21a0SMarc Kleine-Budde 	 * RAM via the SPI interface, with high SCK frequency, can
29641f0e21a0SMarc Kleine-Budde 	 * lead to corrupted data being written to RAM.
29651f0e21a0SMarc Kleine-Budde 	 *
29661f0e21a0SMarc Kleine-Budde 	 * Fix/Work Around:
29671f0e21a0SMarc Kleine-Budde 	 * Ensure that FSCK is less than or equal to 0.85 *
29681f0e21a0SMarc Kleine-Budde 	 * (FSYSCLK/2).
29691f0e21a0SMarc Kleine-Budde 	 *
297001b2a0e5SMarc Kleine-Budde 	 * Known good combinations are:
29711f0e21a0SMarc Kleine-Budde 	 *
297201b2a0e5SMarc Kleine-Budde 	 * MCP	ext-clk	SoC			SPI			SPI-clk		max-clk	parent-clk	config
29731f0e21a0SMarc Kleine-Budde 	 *
297401b2a0e5SMarc Kleine-Budde 	 * 2518	20 MHz	allwinner,sun8i-h3	allwinner,sun8i-h3-spi	 8333333 Hz	 83.33%	600000000 Hz	assigned-clocks = <&ccu CLK_SPIx>
297501b2a0e5SMarc Kleine-Budde 	 * 2518	40 MHz	allwinner,sun8i-h3	allwinner,sun8i-h3-spi	16666667 Hz	 83.33%	600000000 Hz	assigned-clocks = <&ccu CLK_SPIx>
297601b2a0e5SMarc Kleine-Budde 	 * 2517	40 MHz	atmel,sama5d27		atmel,at91rm9200-spi	16400000 Hz	 82.00%	 82000000 Hz	default
297701b2a0e5SMarc Kleine-Budde 	 * 2518	40 MHz	atmel,sama5d27		atmel,at91rm9200-spi	16400000 Hz	 82.00%	 82000000 Hz	default
29789f1fbc1cSMarc Kleine-Budde 	 * 2518	40 MHz	fsl,imx6dl		fsl,imx51-ecspi		15000000 Hz	 75.00%	 30000000 Hz	default
297901b2a0e5SMarc Kleine-Budde 	 * 2517	20 MHz	fsl,imx8mm		fsl,imx51-ecspi		 8333333 Hz	 83.33%	 16666667 Hz	assigned-clocks = <&clk IMX8MM_CLK_ECSPIx_ROOT>
29801f0e21a0SMarc Kleine-Budde 	 *
29811f0e21a0SMarc Kleine-Budde 	 */
29821f0e21a0SMarc Kleine-Budde 	priv->spi_max_speed_hz_orig = spi->max_speed_hz;
29831f0e21a0SMarc Kleine-Budde 	spi->max_speed_hz = min(spi->max_speed_hz, freq / 2 / 1000 * 850);
29841f0e21a0SMarc Kleine-Budde 	spi->bits_per_word = 8;
29851f0e21a0SMarc Kleine-Budde 	spi->rt = true;
29861f0e21a0SMarc Kleine-Budde 	err = spi_setup(spi);
29871f0e21a0SMarc Kleine-Budde 	if (err)
29881f0e21a0SMarc Kleine-Budde 		goto out_free_candev;
29891f0e21a0SMarc Kleine-Budde 
2990eb79a267SMarc Kleine-Budde 	err = mcp251xfd_regmap_init(priv);
29911f0e21a0SMarc Kleine-Budde 	if (err)
29921f0e21a0SMarc Kleine-Budde 		goto out_free_candev;
29931f0e21a0SMarc Kleine-Budde 
29941f0e21a0SMarc Kleine-Budde 	err = can_rx_offload_add_manual(ndev, &priv->offload,
2995eb79a267SMarc Kleine-Budde 					MCP251XFD_NAPI_WEIGHT);
29961f0e21a0SMarc Kleine-Budde 	if (err)
29971f0e21a0SMarc Kleine-Budde 		goto out_free_candev;
29981f0e21a0SMarc Kleine-Budde 
2999eb79a267SMarc Kleine-Budde 	err = mcp251xfd_register(priv);
30001f0e21a0SMarc Kleine-Budde 	if (err)
30014376ea42SMarc Kleine-Budde 		goto out_can_rx_offload_del;
30021f0e21a0SMarc Kleine-Budde 
30031f0e21a0SMarc Kleine-Budde 	return 0;
30041f0e21a0SMarc Kleine-Budde 
30054376ea42SMarc Kleine-Budde  out_can_rx_offload_del:
30064376ea42SMarc Kleine-Budde 	can_rx_offload_del(&priv->offload);
30071f0e21a0SMarc Kleine-Budde  out_free_candev:
30081f0e21a0SMarc Kleine-Budde 	spi->max_speed_hz = priv->spi_max_speed_hz_orig;
30091f0e21a0SMarc Kleine-Budde 
30101f0e21a0SMarc Kleine-Budde 	free_candev(ndev);
30111f0e21a0SMarc Kleine-Budde 
30121f0e21a0SMarc Kleine-Budde 	return err;
30131f0e21a0SMarc Kleine-Budde }
30141f0e21a0SMarc Kleine-Budde 
3015eb79a267SMarc Kleine-Budde static int mcp251xfd_remove(struct spi_device *spi)
30161f0e21a0SMarc Kleine-Budde {
3017eb79a267SMarc Kleine-Budde 	struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
30181f0e21a0SMarc Kleine-Budde 	struct net_device *ndev = priv->ndev;
30191f0e21a0SMarc Kleine-Budde 
30201f0e21a0SMarc Kleine-Budde 	can_rx_offload_del(&priv->offload);
3021eb79a267SMarc Kleine-Budde 	mcp251xfd_unregister(priv);
30221f0e21a0SMarc Kleine-Budde 	spi->max_speed_hz = priv->spi_max_speed_hz_orig;
30231f0e21a0SMarc Kleine-Budde 	free_candev(ndev);
30241f0e21a0SMarc Kleine-Budde 
30251f0e21a0SMarc Kleine-Budde 	return 0;
30261f0e21a0SMarc Kleine-Budde }
30271f0e21a0SMarc Kleine-Budde 
3028eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_suspend(struct device *device)
30291f0e21a0SMarc Kleine-Budde {
3030eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_priv *priv = dev_get_drvdata(device);
30311f0e21a0SMarc Kleine-Budde 
3032eb79a267SMarc Kleine-Budde 	return mcp251xfd_clks_and_vdd_disable(priv);
30331f0e21a0SMarc Kleine-Budde }
30341f0e21a0SMarc Kleine-Budde 
3035eb79a267SMarc Kleine-Budde static int __maybe_unused mcp251xfd_runtime_resume(struct device *device)
30361f0e21a0SMarc Kleine-Budde {
3037eb79a267SMarc Kleine-Budde 	const struct mcp251xfd_priv *priv = dev_get_drvdata(device);
30381f0e21a0SMarc Kleine-Budde 
3039eb79a267SMarc Kleine-Budde 	return mcp251xfd_clks_and_vdd_enable(priv);
30401f0e21a0SMarc Kleine-Budde }
30411f0e21a0SMarc Kleine-Budde 
3042eb79a267SMarc Kleine-Budde static const struct dev_pm_ops mcp251xfd_pm_ops = {
3043eb79a267SMarc Kleine-Budde 	SET_RUNTIME_PM_OPS(mcp251xfd_runtime_suspend,
3044eb79a267SMarc Kleine-Budde 			   mcp251xfd_runtime_resume, NULL)
30451f0e21a0SMarc Kleine-Budde };
30461f0e21a0SMarc Kleine-Budde 
3047eb79a267SMarc Kleine-Budde static struct spi_driver mcp251xfd_driver = {
30481f0e21a0SMarc Kleine-Budde 	.driver = {
30491f0e21a0SMarc Kleine-Budde 		.name = DEVICE_NAME,
3050eb79a267SMarc Kleine-Budde 		.pm = &mcp251xfd_pm_ops,
3051eb79a267SMarc Kleine-Budde 		.of_match_table = mcp251xfd_of_match,
30521f0e21a0SMarc Kleine-Budde 	},
3053eb79a267SMarc Kleine-Budde 	.probe = mcp251xfd_probe,
3054eb79a267SMarc Kleine-Budde 	.remove = mcp251xfd_remove,
3055eb79a267SMarc Kleine-Budde 	.id_table = mcp251xfd_id_table,
30561f0e21a0SMarc Kleine-Budde };
3057eb79a267SMarc Kleine-Budde module_spi_driver(mcp251xfd_driver);
30581f0e21a0SMarc Kleine-Budde 
30591f0e21a0SMarc Kleine-Budde MODULE_AUTHOR("Marc Kleine-Budde <mkl@pengutronix.de>");
3060f4f77366SMarc Kleine-Budde MODULE_DESCRIPTION("Microchip MCP251xFD Family CAN controller driver");
30611f0e21a0SMarc Kleine-Budde MODULE_LICENSE("GPL v2");
3062