1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <asm/unaligned.h>
16
17#include "mcp251xfd.h"
18
19static inline u8
20mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv,
21 union mcp251xfd_write_reg_buf *write_reg_buf,
22 const u16 reg, const u32 mask, const u32 val)
23{
24 u8 first_byte, last_byte, len;
25 u8 *data;
26 __le32 val_le32;
27
28 first_byte = mcp251xfd_first_byte_set(mask);
29 last_byte = mcp251xfd_last_byte_set(mask);
30 len = last_byte - first_byte + 1;
31
32 data = mcp251xfd_spi_cmd_write(priv, write_reg_buf, reg + first_byte);
33 val_le32 = cpu_to_le32(val >> BITS_PER_BYTE * first_byte);
34 memcpy(data, &val_le32, len);
35
36 if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) {
37 u16 crc;
38
39 mcp251xfd_spi_cmd_crc_set_len_in_reg(&write_reg_buf->crc.cmd,
40 len);
41
42 len += sizeof(write_reg_buf->crc.cmd);
43 crc = mcp251xfd_crc16_compute(&write_reg_buf->crc, len);
44 put_unaligned_be16(crc, (void *)write_reg_buf + len);
45
46
47 len += sizeof(write_reg_buf->crc.crc);
48 } else {
49 len += sizeof(write_reg_buf->nocrc.cmd);
50 }
51
52 return len;
53}
54
55static void
56mcp251xfd_tx_ring_init_tx_obj(const struct mcp251xfd_priv *priv,
57 const struct mcp251xfd_tx_ring *ring,
58 struct mcp251xfd_tx_obj *tx_obj,
59 const u8 rts_buf_len,
60 const u8 n)
61{
62 struct spi_transfer *xfer;
63 u16 addr;
64
65
66 addr = mcp251xfd_get_tx_obj_addr(ring, n);
67 if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_TX)
68 mcp251xfd_spi_cmd_write_crc_set_addr(&tx_obj->buf.crc.cmd,
69 addr);
70 else
71 mcp251xfd_spi_cmd_write_nocrc(&tx_obj->buf.nocrc.cmd,
72 addr);
73
74 xfer = &tx_obj->xfer[0];
75 xfer->tx_buf = &tx_obj->buf;
76 xfer->len = 0;
77 xfer->cs_change = 1;
78 xfer->cs_change_delay.value = 0;
79 xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
80
81
82 xfer = &tx_obj->xfer[1];
83 xfer->tx_buf = &ring->rts_buf;
84 xfer->len = rts_buf_len;
85
86
87 spi_message_init_with_transfers(&tx_obj->msg, tx_obj->xfer,
88 ARRAY_SIZE(tx_obj->xfer));
89}
90
91void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
92{
93 struct mcp251xfd_tef_ring *tef_ring;
94 struct mcp251xfd_tx_ring *tx_ring;
95 struct mcp251xfd_rx_ring *rx_ring, *prev_rx_ring = NULL;
96 struct mcp251xfd_tx_obj *tx_obj;
97 struct spi_transfer *xfer;
98 u32 val;
99 u16 addr;
100 u8 len;
101 int i, j;
102
103 netdev_reset_queue(priv->ndev);
104
105
106 tef_ring = priv->tef;
107 tef_ring->head = 0;
108 tef_ring->tail = 0;
109
110
111 addr = MCP251XFD_REG_TEFCON;
112 val = MCP251XFD_REG_TEFCON_UINC;
113 len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->uinc_buf,
114 addr, val, val);
115
116 for (j = 0; j < ARRAY_SIZE(tef_ring->uinc_xfer); j++) {
117 xfer = &tef_ring->uinc_xfer[j];
118 xfer->tx_buf = &tef_ring->uinc_buf;
119 xfer->len = len;
120 xfer->cs_change = 1;
121 xfer->cs_change_delay.value = 0;
122 xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
123 }
124
125
126
127
128
129
130
131
132 xfer->cs_change = 0;
133
134
135 tx_ring = priv->tx;
136 tx_ring->head = 0;
137 tx_ring->tail = 0;
138 tx_ring->base = mcp251xfd_get_tef_obj_addr(tx_ring->obj_num);
139
140
141 addr = MCP251XFD_REG_FIFOCON(MCP251XFD_TX_FIFO);
142 val = MCP251XFD_REG_FIFOCON_TXREQ | MCP251XFD_REG_FIFOCON_UINC;
143 len = mcp251xfd_cmd_prepare_write_reg(priv, &tx_ring->rts_buf,
144 addr, val, val);
145
146 mcp251xfd_for_each_tx_obj(tx_ring, tx_obj, i)
147 mcp251xfd_tx_ring_init_tx_obj(priv, tx_ring, tx_obj, len, i);
148
149
150 mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
151 rx_ring->head = 0;
152 rx_ring->tail = 0;
153 rx_ring->nr = i;
154 rx_ring->fifo_nr = MCP251XFD_RX_FIFO(i);
155
156 if (!prev_rx_ring)
157 rx_ring->base =
158 mcp251xfd_get_tx_obj_addr(tx_ring,
159 tx_ring->obj_num);
160 else
161 rx_ring->base = prev_rx_ring->base +
162 prev_rx_ring->obj_size *
163 prev_rx_ring->obj_num;
164
165 prev_rx_ring = rx_ring;
166
167
168 addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr);
169 val = MCP251XFD_REG_FIFOCON_UINC;
170 len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf,
171 addr, val, val);
172
173 for (j = 0; j < ARRAY_SIZE(rx_ring->uinc_xfer); j++) {
174 xfer = &rx_ring->uinc_xfer[j];
175 xfer->tx_buf = &rx_ring->uinc_buf;
176 xfer->len = len;
177 xfer->cs_change = 1;
178 xfer->cs_change_delay.value = 0;
179 xfer->cs_change_delay.unit = SPI_DELAY_UNIT_NSECS;
180 }
181
182
183
184
185
186
187
188
189 xfer->cs_change = 0;
190 }
191}
192
193void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
194{
195 int i;
196
197 for (i = ARRAY_SIZE(priv->rx) - 1; i >= 0; i--) {
198 kfree(priv->rx[i]);
199 priv->rx[i] = NULL;
200 }
201}
202
203int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
204{
205 struct mcp251xfd_tx_ring *tx_ring;
206 struct mcp251xfd_rx_ring *rx_ring;
207 int tef_obj_size, tx_obj_size, rx_obj_size;
208 int tx_obj_num;
209 int ram_free, i;
210
211 tef_obj_size = sizeof(struct mcp251xfd_hw_tef_obj);
212 if (mcp251xfd_is_fd_mode(priv)) {
213 tx_obj_num = MCP251XFD_TX_OBJ_NUM_CANFD;
214 tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd);
215 rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd);
216 } else {
217 tx_obj_num = MCP251XFD_TX_OBJ_NUM_CAN;
218 tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can);
219 rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can);
220 }
221
222 tx_ring = priv->tx;
223 tx_ring->obj_num = tx_obj_num;
224 tx_ring->obj_size = tx_obj_size;
225
226 ram_free = MCP251XFD_RAM_SIZE - tx_obj_num *
227 (tef_obj_size + tx_obj_size);
228
229 for (i = 0;
230 i < ARRAY_SIZE(priv->rx) && ram_free >= rx_obj_size;
231 i++) {
232 int rx_obj_num;
233
234 rx_obj_num = ram_free / rx_obj_size;
235 rx_obj_num = min(1 << (fls(rx_obj_num) - 1),
236 MCP251XFD_RX_OBJ_NUM_MAX);
237
238 rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
239 GFP_KERNEL);
240 if (!rx_ring) {
241 mcp251xfd_ring_free(priv);
242 return -ENOMEM;
243 }
244 rx_ring->obj_num = rx_obj_num;
245 rx_ring->obj_size = rx_obj_size;
246 priv->rx[i] = rx_ring;
247
248 ram_free -= rx_ring->obj_num * rx_ring->obj_size;
249 }
250 priv->rx_ring_num = i;
251
252 netdev_dbg(priv->ndev,
253 "FIFO setup: TEF: %d*%d bytes = %d bytes, TX: %d*%d bytes = %d bytes\n",
254 tx_obj_num, tef_obj_size, tef_obj_size * tx_obj_num,
255 tx_obj_num, tx_obj_size, tx_obj_size * tx_obj_num);
256
257 mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
258 netdev_dbg(priv->ndev,
259 "FIFO setup: RX-%d: %d*%d bytes = %d bytes\n",
260 i, rx_ring->obj_num, rx_ring->obj_size,
261 rx_ring->obj_size * rx_ring->obj_num);
262 }
263
264 netdev_dbg(priv->ndev,
265 "FIFO setup: free: %d bytes\n",
266 ram_free);
267
268 return 0;
269}
270