xref: /linux/drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c (revision 876f7a438e4247a948268ad77b67c494f709cc30)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // mcp251xfd - Microchip MCP251xFD Family CAN controller driver
4 //
5 // Copyright (c) 2019, 2020, 2021 Pengutronix,
6 //               Marc Kleine-Budde <kernel@pengutronix.de>
7 //
8 // Based on:
9 //
10 // CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
11 //
12 // Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
13 //
14 
15 #include <linux/bitfield.h>
16 
17 #include "mcp251xfd.h"
18 
19 static inline int
20 mcp251xfd_rx_head_get_from_chip(const struct mcp251xfd_priv *priv,
21 				const struct mcp251xfd_rx_ring *ring,
22 				u8 *rx_head)
23 {
24 	u32 fifo_sta;
25 	int err;
26 
27 	err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOSTA(ring->fifo_nr),
28 			  &fifo_sta);
29 	if (err)
30 		return err;
31 
32 	*rx_head = FIELD_GET(MCP251XFD_REG_FIFOSTA_FIFOCI_MASK, fifo_sta);
33 
34 	return 0;
35 }
36 
37 static inline int
38 mcp251xfd_rx_tail_get_from_chip(const struct mcp251xfd_priv *priv,
39 				const struct mcp251xfd_rx_ring *ring,
40 				u8 *rx_tail)
41 {
42 	u32 fifo_ua;
43 	int err;
44 
45 	err = regmap_read(priv->map_reg, MCP251XFD_REG_FIFOUA(ring->fifo_nr),
46 			  &fifo_ua);
47 	if (err)
48 		return err;
49 
50 	fifo_ua -= ring->base - MCP251XFD_RAM_START;
51 	*rx_tail = fifo_ua / ring->obj_size;
52 
53 	return 0;
54 }
55 
56 static int
57 mcp251xfd_check_rx_tail(const struct mcp251xfd_priv *priv,
58 			const struct mcp251xfd_rx_ring *ring)
59 {
60 	u8 rx_tail_chip, rx_tail;
61 	int err;
62 
63 	if (!IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY))
64 		return 0;
65 
66 	err = mcp251xfd_rx_tail_get_from_chip(priv, ring, &rx_tail_chip);
67 	if (err)
68 		return err;
69 
70 	rx_tail = mcp251xfd_get_rx_tail(ring);
71 	if (rx_tail_chip != rx_tail) {
72 		netdev_err(priv->ndev,
73 			   "RX tail of chip (%d) and ours (%d) inconsistent.\n",
74 			   rx_tail_chip, rx_tail);
75 		return -EILSEQ;
76 	}
77 
78 	return 0;
79 }
80 
81 static int
82 mcp251xfd_rx_ring_update(const struct mcp251xfd_priv *priv,
83 			 struct mcp251xfd_rx_ring *ring)
84 {
85 	u32 new_head;
86 	u8 chip_rx_head;
87 	int err;
88 
89 	err = mcp251xfd_rx_head_get_from_chip(priv, ring, &chip_rx_head);
90 	if (err)
91 		return err;
92 
93 	/* chip_rx_head, is the next RX-Object filled by the HW.
94 	 * The new RX head must be >= the old head.
95 	 */
96 	new_head = round_down(ring->head, ring->obj_num) + chip_rx_head;
97 	if (new_head <= ring->head)
98 		new_head += ring->obj_num;
99 
100 	ring->head = new_head;
101 
102 	return mcp251xfd_check_rx_tail(priv, ring);
103 }
104 
105 static void
106 mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv,
107 			   const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
108 			   struct sk_buff *skb)
109 {
110 	struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
111 	u8 dlc;
112 
113 	if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_IDE) {
114 		u32 sid, eid;
115 
116 		eid = FIELD_GET(MCP251XFD_OBJ_ID_EID_MASK, hw_rx_obj->id);
117 		sid = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK, hw_rx_obj->id);
118 
119 		cfd->can_id = CAN_EFF_FLAG |
120 			FIELD_PREP(MCP251XFD_REG_FRAME_EFF_EID_MASK, eid) |
121 			FIELD_PREP(MCP251XFD_REG_FRAME_EFF_SID_MASK, sid);
122 	} else {
123 		cfd->can_id = FIELD_GET(MCP251XFD_OBJ_ID_SID_MASK,
124 					hw_rx_obj->id);
125 	}
126 
127 	dlc = FIELD_GET(MCP251XFD_OBJ_FLAGS_DLC_MASK, hw_rx_obj->flags);
128 
129 	/* CANFD */
130 	if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF) {
131 		if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_ESI)
132 			cfd->flags |= CANFD_ESI;
133 
134 		if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_BRS)
135 			cfd->flags |= CANFD_BRS;
136 
137 		cfd->len = can_fd_dlc2len(dlc);
138 	} else {
139 		if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR)
140 			cfd->can_id |= CAN_RTR_FLAG;
141 
142 		can_frame_set_cc_len((struct can_frame *)cfd, dlc,
143 				     priv->can.ctrlmode);
144 	}
145 
146 	if (!(hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR))
147 		memcpy(cfd->data, hw_rx_obj->data, cfd->len);
148 
149 	mcp251xfd_skb_set_timestamp(priv, skb, hw_rx_obj->ts);
150 }
151 
152 static int
153 mcp251xfd_handle_rxif_one(struct mcp251xfd_priv *priv,
154 			  struct mcp251xfd_rx_ring *ring,
155 			  const struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj)
156 {
157 	struct net_device_stats *stats = &priv->ndev->stats;
158 	struct sk_buff *skb;
159 	struct canfd_frame *cfd;
160 	int err;
161 
162 	if (hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_FDF)
163 		skb = alloc_canfd_skb(priv->ndev, &cfd);
164 	else
165 		skb = alloc_can_skb(priv->ndev, (struct can_frame **)&cfd);
166 
167 	if (!skb) {
168 		stats->rx_dropped++;
169 		return 0;
170 	}
171 
172 	mcp251xfd_hw_rx_obj_to_skb(priv, hw_rx_obj, skb);
173 	err = can_rx_offload_queue_sorted(&priv->offload, skb, hw_rx_obj->ts);
174 	if (err)
175 		stats->rx_fifo_errors++;
176 
177 	return 0;
178 }
179 
180 static inline int
181 mcp251xfd_rx_obj_read(const struct mcp251xfd_priv *priv,
182 		      const struct mcp251xfd_rx_ring *ring,
183 		      struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj,
184 		      const u8 offset, const u8 len)
185 {
186 	const int val_bytes = regmap_get_val_bytes(priv->map_rx);
187 	int err;
188 
189 	err = regmap_bulk_read(priv->map_rx,
190 			       mcp251xfd_get_rx_obj_addr(ring, offset),
191 			       hw_rx_obj,
192 			       len * ring->obj_size / val_bytes);
193 
194 	return err;
195 }
196 
197 static int
198 mcp251xfd_handle_rxif_ring(struct mcp251xfd_priv *priv,
199 			   struct mcp251xfd_rx_ring *ring)
200 {
201 	struct mcp251xfd_hw_rx_obj_canfd *hw_rx_obj = ring->obj;
202 	u8 rx_tail, len;
203 	int err, i;
204 
205 	err = mcp251xfd_rx_ring_update(priv, ring);
206 	if (err)
207 		return err;
208 
209 	while ((len = mcp251xfd_get_rx_linear_len(ring))) {
210 		int offset;
211 
212 		rx_tail = mcp251xfd_get_rx_tail(ring);
213 
214 		err = mcp251xfd_rx_obj_read(priv, ring, hw_rx_obj,
215 					    rx_tail, len);
216 		if (err)
217 			return err;
218 
219 		for (i = 0; i < len; i++) {
220 			err = mcp251xfd_handle_rxif_one(priv, ring,
221 							(void *)hw_rx_obj +
222 							i * ring->obj_size);
223 			if (err)
224 				return err;
225 		}
226 
227 		/* Increment the RX FIFO tail pointer 'len' times in a
228 		 * single SPI message.
229 		 *
230 		 * Note:
231 		 * Calculate offset, so that the SPI transfer ends on
232 		 * the last message of the uinc_xfer array, which has
233 		 * "cs_change == 0", to properly deactivate the chip
234 		 * select.
235 		 */
236 		offset = ARRAY_SIZE(ring->uinc_xfer) - len;
237 		err = spi_sync_transfer(priv->spi,
238 					ring->uinc_xfer + offset, len);
239 		if (err)
240 			return err;
241 
242 		ring->tail += len;
243 	}
244 
245 	return 0;
246 }
247 
248 int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv)
249 {
250 	struct mcp251xfd_rx_ring *ring;
251 	int err, n;
252 
253 	mcp251xfd_for_each_rx_ring(priv, ring, n) {
254 		err = mcp251xfd_handle_rxif_ring(priv, ring);
255 		if (err)
256 			return err;
257 	}
258 
259 	return 0;
260 }
261