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