xref: /linux/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c (revision 1e846c7aeb067fefbd53f03db56e69d160781d9d)
1*1e846c7aSMarc Kleine-Budde // SPDX-License-Identifier: GPL-2.0
2*1e846c7aSMarc Kleine-Budde //
3*1e846c7aSMarc Kleine-Budde // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
4*1e846c7aSMarc Kleine-Budde //
5*1e846c7aSMarc Kleine-Budde // Copyright (c) 2019, 2020, 2021 Pengutronix,
6*1e846c7aSMarc Kleine-Budde //               Marc Kleine-Budde <kernel@pengutronix.de>
7*1e846c7aSMarc Kleine-Budde //
8*1e846c7aSMarc Kleine-Budde // Based on:
9*1e846c7aSMarc Kleine-Budde //
10*1e846c7aSMarc Kleine-Budde // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
11*1e846c7aSMarc Kleine-Budde //
12*1e846c7aSMarc Kleine-Budde // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
13*1e846c7aSMarc Kleine-Budde //
14*1e846c7aSMarc Kleine-Budde 
15*1e846c7aSMarc Kleine-Budde #include <linux/bitfield.h>
16*1e846c7aSMarc Kleine-Budde 
17*1e846c7aSMarc Kleine-Budde #include "mcp251xfd.h"
18*1e846c7aSMarc Kleine-Budde 
19*1e846c7aSMarc Kleine-Budde static inline int
20*1e846c7aSMarc Kleine-Budde mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
21*1e846c7aSMarc Kleine-Budde 				 u8 *tef_tail)
22*1e846c7aSMarc Kleine-Budde {
23*1e846c7aSMarc Kleine-Budde 	u32 tef_ua;
24*1e846c7aSMarc Kleine-Budde 	int err;
25*1e846c7aSMarc Kleine-Budde 
26*1e846c7aSMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFUA, &tef_ua);
27*1e846c7aSMarc Kleine-Budde 	if (err)
28*1e846c7aSMarc Kleine-Budde 		return err;
29*1e846c7aSMarc Kleine-Budde 
30*1e846c7aSMarc Kleine-Budde 	*tef_tail = tef_ua / sizeof(struct mcp251xfd_hw_tef_obj);
31*1e846c7aSMarc Kleine-Budde 
32*1e846c7aSMarc Kleine-Budde 	return 0;
33*1e846c7aSMarc Kleine-Budde }
34*1e846c7aSMarc Kleine-Budde 
35*1e846c7aSMarc Kleine-Budde static int mcp251xfd_check_tef_tail(const struct mcp251xfd_priv *priv)
36*1e846c7aSMarc Kleine-Budde {
37*1e846c7aSMarc Kleine-Budde 	u8 tef_tail_chip, tef_tail;
38*1e846c7aSMarc Kleine-Budde 	int err;
39*1e846c7aSMarc Kleine-Budde 
40*1e846c7aSMarc Kleine-Budde 	if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY))
41*1e846c7aSMarc Kleine-Budde 		return 0;
42*1e846c7aSMarc Kleine-Budde 
43*1e846c7aSMarc Kleine-Budde 	err = mcp251xfd_tef_tail_get_from_chip(priv, &tef_tail_chip);
44*1e846c7aSMarc Kleine-Budde 	if (err)
45*1e846c7aSMarc Kleine-Budde 		return err;
46*1e846c7aSMarc Kleine-Budde 
47*1e846c7aSMarc Kleine-Budde 	tef_tail = mcp251xfd_get_tef_tail(priv);
48*1e846c7aSMarc Kleine-Budde 	if (tef_tail_chip != tef_tail) {
49*1e846c7aSMarc Kleine-Budde 		netdev_err(priv->ndev,
50*1e846c7aSMarc Kleine-Budde 			   "TEF tail of chip (0x%02x) and ours (0x%08x) inconsistent.\n",
51*1e846c7aSMarc Kleine-Budde 			   tef_tail_chip, tef_tail);
52*1e846c7aSMarc Kleine-Budde 		return -EILSEQ;
53*1e846c7aSMarc Kleine-Budde 	}
54*1e846c7aSMarc Kleine-Budde 
55*1e846c7aSMarc Kleine-Budde 	return 0;
56*1e846c7aSMarc Kleine-Budde }
57*1e846c7aSMarc Kleine-Budde 
58*1e846c7aSMarc Kleine-Budde static int
59*1e846c7aSMarc Kleine-Budde mcp251xfd_handle_tefif_recover(const struct mcp251xfd_priv *priv, const u32 seq)
60*1e846c7aSMarc Kleine-Budde {
61*1e846c7aSMarc Kleine-Budde 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
62*1e846c7aSMarc Kleine-Budde 	u32 tef_sta;
63*1e846c7aSMarc Kleine-Budde 	int err;
64*1e846c7aSMarc Kleine-Budde 
65*1e846c7aSMarc Kleine-Budde 	err = regmap_read(priv->map_reg, MCP251XFD_REG_TEFSTA, &tef_sta);
66*1e846c7aSMarc Kleine-Budde 	if (err)
67*1e846c7aSMarc Kleine-Budde 		return err;
68*1e846c7aSMarc Kleine-Budde 
69*1e846c7aSMarc Kleine-Budde 	if (tef_sta & MCP251XFD_REG_TEFSTA_TEFOVIF) {
70*1e846c7aSMarc Kleine-Budde 		netdev_err(priv->ndev,
71*1e846c7aSMarc Kleine-Budde 			   "Transmit Event FIFO buffer overflow.\n");
72*1e846c7aSMarc Kleine-Budde 		return -ENOBUFS;
73*1e846c7aSMarc Kleine-Budde 	}
74*1e846c7aSMarc Kleine-Budde 
75*1e846c7aSMarc Kleine-Budde 	netdev_info(priv->ndev,
76*1e846c7aSMarc Kleine-Budde 		    "Transmit Event FIFO buffer %s. (seq=0x%08x, tef_tail=0x%08x, tef_head=0x%08x, tx_head=0x%08x).\n",
77*1e846c7aSMarc Kleine-Budde 		    tef_sta & MCP251XFD_REG_TEFSTA_TEFFIF ?
78*1e846c7aSMarc Kleine-Budde 		    "full" : tef_sta & MCP251XFD_REG_TEFSTA_TEFNEIF ?
79*1e846c7aSMarc Kleine-Budde 		    "not empty" : "empty",
80*1e846c7aSMarc Kleine-Budde 		    seq, priv->tef->tail, priv->tef->head, tx_ring->head);
81*1e846c7aSMarc Kleine-Budde 
82*1e846c7aSMarc Kleine-Budde 	/* The Sequence Number in the TEF doesn't match our tef_tail. */
83*1e846c7aSMarc Kleine-Budde 	return -EAGAIN;
84*1e846c7aSMarc Kleine-Budde }
85*1e846c7aSMarc Kleine-Budde 
86*1e846c7aSMarc Kleine-Budde static int
87*1e846c7aSMarc Kleine-Budde mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
88*1e846c7aSMarc Kleine-Budde 			   const struct mcp251xfd_hw_tef_obj *hw_tef_obj,
89*1e846c7aSMarc Kleine-Budde 			   unsigned int *frame_len_ptr)
90*1e846c7aSMarc Kleine-Budde {
91*1e846c7aSMarc Kleine-Budde 	struct net_device_stats *stats = &priv->ndev->stats;
92*1e846c7aSMarc Kleine-Budde 	struct sk_buff *skb;
93*1e846c7aSMarc Kleine-Budde 	u32 seq, seq_masked, tef_tail_masked, tef_tail;
94*1e846c7aSMarc Kleine-Budde 
95*1e846c7aSMarc Kleine-Budde 	seq = FIELD_GET(MCP251XFD_OBJ_FLAGS_SEQ_MCP2518FD_MASK,
96*1e846c7aSMarc Kleine-Budde 			hw_tef_obj->flags);
97*1e846c7aSMarc Kleine-Budde 
98*1e846c7aSMarc Kleine-Budde 	/* Use the MCP2517FD mask on the MCP2518FD, too. We only
99*1e846c7aSMarc Kleine-Budde 	 * compare 7 bits, this should be enough to detect
100*1e846c7aSMarc Kleine-Budde 	 * net-yet-completed, i.e. old TEF objects.
101*1e846c7aSMarc Kleine-Budde 	 */
102*1e846c7aSMarc Kleine-Budde 	seq_masked = seq &
103*1e846c7aSMarc Kleine-Budde 		field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
104*1e846c7aSMarc Kleine-Budde 	tef_tail_masked = priv->tef->tail &
105*1e846c7aSMarc Kleine-Budde 		field_mask(MCP251XFD_OBJ_FLAGS_SEQ_MCP2517FD_MASK);
106*1e846c7aSMarc Kleine-Budde 	if (seq_masked != tef_tail_masked)
107*1e846c7aSMarc Kleine-Budde 		return mcp251xfd_handle_tefif_recover(priv, seq);
108*1e846c7aSMarc Kleine-Budde 
109*1e846c7aSMarc Kleine-Budde 	tef_tail = mcp251xfd_get_tef_tail(priv);
110*1e846c7aSMarc Kleine-Budde 	skb = priv->can.echo_skb[tef_tail];
111*1e846c7aSMarc Kleine-Budde 	if (skb)
112*1e846c7aSMarc Kleine-Budde 		mcp251xfd_skb_set_timestamp(priv, skb, hw_tef_obj->ts);
113*1e846c7aSMarc Kleine-Budde 	stats->tx_bytes +=
114*1e846c7aSMarc Kleine-Budde 		can_rx_offload_get_echo_skb(&priv->offload,
115*1e846c7aSMarc Kleine-Budde 					    tef_tail, hw_tef_obj->ts,
116*1e846c7aSMarc Kleine-Budde 					    frame_len_ptr);
117*1e846c7aSMarc Kleine-Budde 	stats->tx_packets++;
118*1e846c7aSMarc Kleine-Budde 	priv->tef->tail++;
119*1e846c7aSMarc Kleine-Budde 
120*1e846c7aSMarc Kleine-Budde 	return 0;
121*1e846c7aSMarc Kleine-Budde }
122*1e846c7aSMarc Kleine-Budde 
123*1e846c7aSMarc Kleine-Budde static int mcp251xfd_tef_ring_update(struct mcp251xfd_priv *priv)
124*1e846c7aSMarc Kleine-Budde {
125*1e846c7aSMarc Kleine-Budde 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
126*1e846c7aSMarc Kleine-Budde 	unsigned int new_head;
127*1e846c7aSMarc Kleine-Budde 	u8 chip_tx_tail;
128*1e846c7aSMarc Kleine-Budde 	int err;
129*1e846c7aSMarc Kleine-Budde 
130*1e846c7aSMarc Kleine-Budde 	err = mcp251xfd_tx_tail_get_from_chip(priv, &chip_tx_tail);
131*1e846c7aSMarc Kleine-Budde 	if (err)
132*1e846c7aSMarc Kleine-Budde 		return err;
133*1e846c7aSMarc Kleine-Budde 
134*1e846c7aSMarc Kleine-Budde 	/* chip_tx_tail, is the next TX-Object send by the HW.
135*1e846c7aSMarc Kleine-Budde 	 * The new TEF head must be >= the old head, ...
136*1e846c7aSMarc Kleine-Budde 	 */
137*1e846c7aSMarc Kleine-Budde 	new_head = round_down(priv->tef->head, tx_ring->obj_num) + chip_tx_tail;
138*1e846c7aSMarc Kleine-Budde 	if (new_head <= priv->tef->head)
139*1e846c7aSMarc Kleine-Budde 		new_head += tx_ring->obj_num;
140*1e846c7aSMarc Kleine-Budde 
141*1e846c7aSMarc Kleine-Budde 	/* ... but it cannot exceed the TX head. */
142*1e846c7aSMarc Kleine-Budde 	priv->tef->head = min(new_head, tx_ring->head);
143*1e846c7aSMarc Kleine-Budde 
144*1e846c7aSMarc Kleine-Budde 	return mcp251xfd_check_tef_tail(priv);
145*1e846c7aSMarc Kleine-Budde }
146*1e846c7aSMarc Kleine-Budde 
147*1e846c7aSMarc Kleine-Budde static inline int
148*1e846c7aSMarc Kleine-Budde mcp251xfd_tef_obj_read(const struct mcp251xfd_priv *priv,
149*1e846c7aSMarc Kleine-Budde 		       struct mcp251xfd_hw_tef_obj *hw_tef_obj,
150*1e846c7aSMarc Kleine-Budde 		       const u8 offset, const u8 len)
151*1e846c7aSMarc Kleine-Budde {
152*1e846c7aSMarc Kleine-Budde 	const struct mcp251xfd_tx_ring *tx_ring = priv->tx;
153*1e846c7aSMarc Kleine-Budde 	const int val_bytes = regmap_get_val_bytes(priv->map_rx);
154*1e846c7aSMarc Kleine-Budde 
155*1e846c7aSMarc Kleine-Budde 	if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
156*1e846c7aSMarc Kleine-Budde 	    (offset > tx_ring->obj_num ||
157*1e846c7aSMarc Kleine-Budde 	     len > tx_ring->obj_num ||
158*1e846c7aSMarc Kleine-Budde 	     offset + len > tx_ring->obj_num)) {
159*1e846c7aSMarc Kleine-Budde 		netdev_err(priv->ndev,
160*1e846c7aSMarc Kleine-Budde 			   "Trying to read too many TEF objects (max=%d, offset=%d, len=%d).\n",
161*1e846c7aSMarc Kleine-Budde 			   tx_ring->obj_num, offset, len);
162*1e846c7aSMarc Kleine-Budde 		return -ERANGE;
163*1e846c7aSMarc Kleine-Budde 	}
164*1e846c7aSMarc Kleine-Budde 
165*1e846c7aSMarc Kleine-Budde 	return regmap_bulk_read(priv->map_rx,
166*1e846c7aSMarc Kleine-Budde 				mcp251xfd_get_tef_obj_addr(offset),
167*1e846c7aSMarc Kleine-Budde 				hw_tef_obj,
168*1e846c7aSMarc Kleine-Budde 				sizeof(*hw_tef_obj) / val_bytes * len);
169*1e846c7aSMarc Kleine-Budde }
170*1e846c7aSMarc Kleine-Budde 
171*1e846c7aSMarc Kleine-Budde static inline void mcp251xfd_ecc_tefif_successful(struct mcp251xfd_priv *priv)
172*1e846c7aSMarc Kleine-Budde {
173*1e846c7aSMarc Kleine-Budde 	struct mcp251xfd_ecc *ecc = &priv->ecc;
174*1e846c7aSMarc Kleine-Budde 
175*1e846c7aSMarc Kleine-Budde 	ecc->ecc_stat = 0;
176*1e846c7aSMarc Kleine-Budde }
177*1e846c7aSMarc Kleine-Budde 
178*1e846c7aSMarc Kleine-Budde int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
179*1e846c7aSMarc Kleine-Budde {
180*1e846c7aSMarc Kleine-Budde 	struct mcp251xfd_hw_tef_obj hw_tef_obj[MCP251XFD_TX_OBJ_NUM_MAX];
181*1e846c7aSMarc Kleine-Budde 	unsigned int total_frame_len = 0;
182*1e846c7aSMarc Kleine-Budde 	u8 tef_tail, len, l;
183*1e846c7aSMarc Kleine-Budde 	int err, i;
184*1e846c7aSMarc Kleine-Budde 
185*1e846c7aSMarc Kleine-Budde 	err = mcp251xfd_tef_ring_update(priv);
186*1e846c7aSMarc Kleine-Budde 	if (err)
187*1e846c7aSMarc Kleine-Budde 		return err;
188*1e846c7aSMarc Kleine-Budde 
189*1e846c7aSMarc Kleine-Budde 	tef_tail = mcp251xfd_get_tef_tail(priv);
190*1e846c7aSMarc Kleine-Budde 	len = mcp251xfd_get_tef_len(priv);
191*1e846c7aSMarc Kleine-Budde 	l = mcp251xfd_get_tef_linear_len(priv);
192*1e846c7aSMarc Kleine-Budde 	err = mcp251xfd_tef_obj_read(priv, hw_tef_obj, tef_tail, l);
193*1e846c7aSMarc Kleine-Budde 	if (err)
194*1e846c7aSMarc Kleine-Budde 		return err;
195*1e846c7aSMarc Kleine-Budde 
196*1e846c7aSMarc Kleine-Budde 	if (l < len) {
197*1e846c7aSMarc Kleine-Budde 		err = mcp251xfd_tef_obj_read(priv, &hw_tef_obj[l], 0, len - l);
198*1e846c7aSMarc Kleine-Budde 		if (err)
199*1e846c7aSMarc Kleine-Budde 			return err;
200*1e846c7aSMarc Kleine-Budde 	}
201*1e846c7aSMarc Kleine-Budde 
202*1e846c7aSMarc Kleine-Budde 	for (i = 0; i < len; i++) {
203*1e846c7aSMarc Kleine-Budde 		unsigned int frame_len = 0;
204*1e846c7aSMarc Kleine-Budde 
205*1e846c7aSMarc Kleine-Budde 		err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
206*1e846c7aSMarc Kleine-Budde 		/* -EAGAIN means the Sequence Number in the TEF
207*1e846c7aSMarc Kleine-Budde 		 * doesn't match our tef_tail. This can happen if we
208*1e846c7aSMarc Kleine-Budde 		 * read the TEF objects too early. Leave loop let the
209*1e846c7aSMarc Kleine-Budde 		 * interrupt handler call us again.
210*1e846c7aSMarc Kleine-Budde 		 */
211*1e846c7aSMarc Kleine-Budde 		if (err == -EAGAIN)
212*1e846c7aSMarc Kleine-Budde 			goto out_netif_wake_queue;
213*1e846c7aSMarc Kleine-Budde 		if (err)
214*1e846c7aSMarc Kleine-Budde 			return err;
215*1e846c7aSMarc Kleine-Budde 
216*1e846c7aSMarc Kleine-Budde 		total_frame_len += frame_len;
217*1e846c7aSMarc Kleine-Budde 	}
218*1e846c7aSMarc Kleine-Budde 
219*1e846c7aSMarc Kleine-Budde  out_netif_wake_queue:
220*1e846c7aSMarc Kleine-Budde 	len = i;	/* number of handled goods TEFs */
221*1e846c7aSMarc Kleine-Budde 	if (len) {
222*1e846c7aSMarc Kleine-Budde 		struct mcp251xfd_tef_ring *ring = priv->tef;
223*1e846c7aSMarc Kleine-Budde 		struct mcp251xfd_tx_ring *tx_ring = priv->tx;
224*1e846c7aSMarc Kleine-Budde 		int offset;
225*1e846c7aSMarc Kleine-Budde 
226*1e846c7aSMarc Kleine-Budde 		/* Increment the TEF FIFO tail pointer 'len' times in
227*1e846c7aSMarc Kleine-Budde 		 * a single SPI message.
228*1e846c7aSMarc Kleine-Budde 		 *
229*1e846c7aSMarc Kleine-Budde 		 * Note:
230*1e846c7aSMarc Kleine-Budde 		 * Calculate offset, so that the SPI transfer ends on
231*1e846c7aSMarc Kleine-Budde 		 * the last message of the uinc_xfer array, which has
232*1e846c7aSMarc Kleine-Budde 		 * "cs_change == 0", to properly deactivate the chip
233*1e846c7aSMarc Kleine-Budde 		 * select.
234*1e846c7aSMarc Kleine-Budde 		 */
235*1e846c7aSMarc Kleine-Budde 		offset = ARRAY_SIZE(ring->uinc_xfer) - len;
236*1e846c7aSMarc Kleine-Budde 		err = spi_sync_transfer(priv->spi,
237*1e846c7aSMarc Kleine-Budde 					ring->uinc_xfer + offset, len);
238*1e846c7aSMarc Kleine-Budde 		if (err)
239*1e846c7aSMarc Kleine-Budde 			return err;
240*1e846c7aSMarc Kleine-Budde 
241*1e846c7aSMarc Kleine-Budde 		tx_ring->tail += len;
242*1e846c7aSMarc Kleine-Budde 		netdev_completed_queue(priv->ndev, len, total_frame_len);
243*1e846c7aSMarc Kleine-Budde 
244*1e846c7aSMarc Kleine-Budde 		err = mcp251xfd_check_tef_tail(priv);
245*1e846c7aSMarc Kleine-Budde 		if (err)
246*1e846c7aSMarc Kleine-Budde 			return err;
247*1e846c7aSMarc Kleine-Budde 	}
248*1e846c7aSMarc Kleine-Budde 
249*1e846c7aSMarc Kleine-Budde 	mcp251xfd_ecc_tefif_successful(priv);
250*1e846c7aSMarc Kleine-Budde 
251*1e846c7aSMarc Kleine-Budde 	if (mcp251xfd_get_tx_free(priv->tx)) {
252*1e846c7aSMarc Kleine-Budde 		/* Make sure that anybody stopping the queue after
253*1e846c7aSMarc Kleine-Budde 		 * this sees the new tx_ring->tail.
254*1e846c7aSMarc Kleine-Budde 		 */
255*1e846c7aSMarc Kleine-Budde 		smp_mb();
256*1e846c7aSMarc Kleine-Budde 		netif_wake_queue(priv->ndev);
257*1e846c7aSMarc Kleine-Budde 	}
258*1e846c7aSMarc Kleine-Budde 
259*1e846c7aSMarc Kleine-Budde 	return 0;
260*1e846c7aSMarc Kleine-Budde }
261