Commit | Line | Data |
---|---|---|
c5c77ba1 JK |
1 | /* ////////////////////////////////////////////////////////////////////////// */ |
2 | /* */ | |
3 | /* Copyright (c) Atmel Corporation. All rights reserved. */ | |
4 | /* */ | |
5 | /* Module Name: wilc_spi.c */ | |
6 | /* */ | |
7 | /* */ | |
8 | /* //////////////////////////////////////////////////////////////////////////// */ | |
43a76229 GL |
9 | #include <linux/module.h> |
10 | #include <linux/init.h> | |
11 | #include <linux/kernel.h> | |
12 | #include <linux/fs.h> | |
13 | #include <linux/slab.h> | |
14 | #include <linux/types.h> | |
15 | #include <linux/cdev.h> | |
16 | #include <linux/uaccess.h> | |
17 | #include <linux/device.h> | |
18 | #include <linux/spi/spi.h> | |
19 | #include <linux/of_gpio.h> | |
c5c77ba1 | 20 | |
0c9fc33c | 21 | #include <linux/string.h> |
c5c77ba1 JK |
22 | #include "wilc_wlan_if.h" |
23 | #include "wilc_wlan.h" | |
9c800322 | 24 | #include "wilc_wfi_netdevice.h" |
c5c77ba1 | 25 | |
6a707a9e | 26 | struct wilc_spi { |
c5c77ba1 JK |
27 | int crc_off; |
28 | int nint; | |
29 | int has_thrpt_enh; | |
6a707a9e | 30 | }; |
c5c77ba1 | 31 | |
6a707a9e | 32 | static struct wilc_spi g_spi; |
c5c77ba1 | 33 | |
d4312b6f GL |
34 | static int wilc_spi_read(struct wilc *wilc, u32, u8 *, u32); |
35 | static int wilc_spi_write(struct wilc *wilc, u32, u8 *, u32); | |
c5c77ba1 JK |
36 | |
37 | /******************************************** | |
38 | * | |
39 | * Crc7 | |
40 | * | |
41 | ********************************************/ | |
42 | ||
51e825f7 | 43 | static const u8 crc7_syndrome_table[256] = { |
c5c77ba1 JK |
44 | 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, |
45 | 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, | |
46 | 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, | |
47 | 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, | |
48 | 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d, | |
49 | 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, | |
50 | 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, | |
51 | 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c, | |
52 | 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, | |
53 | 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, | |
54 | 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42, | |
55 | 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, | |
56 | 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, | |
57 | 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21, | |
58 | 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, | |
59 | 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, | |
60 | 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e, | |
61 | 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, | |
62 | 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, | |
63 | 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f, | |
64 | 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, | |
65 | 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, | |
66 | 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55, | |
67 | 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, | |
68 | 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, | |
69 | 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52, | |
70 | 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, | |
71 | 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, | |
72 | 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28, | |
73 | 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, | |
74 | 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, | |
75 | 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79 | |
76 | }; | |
77 | ||
51e825f7 | 78 | static u8 crc7_byte(u8 crc, u8 data) |
c5c77ba1 JK |
79 | { |
80 | return crc7_syndrome_table[(crc << 1) ^ data]; | |
81 | } | |
82 | ||
fbc2fe16 | 83 | static u8 crc7(u8 crc, const u8 *buffer, u32 len) |
c5c77ba1 JK |
84 | { |
85 | while (len--) | |
86 | crc = crc7_byte(crc, *buffer++); | |
87 | return crc; | |
88 | } | |
89 | ||
90 | /******************************************** | |
91 | * | |
92 | * Spi protocol Function | |
93 | * | |
94 | ********************************************/ | |
95 | ||
96 | #define CMD_DMA_WRITE 0xc1 | |
97 | #define CMD_DMA_READ 0xc2 | |
98 | #define CMD_INTERNAL_WRITE 0xc3 | |
99 | #define CMD_INTERNAL_READ 0xc4 | |
100 | #define CMD_TERMINATE 0xc5 | |
101 | #define CMD_REPEAT 0xc6 | |
102 | #define CMD_DMA_EXT_WRITE 0xc7 | |
103 | #define CMD_DMA_EXT_READ 0xc8 | |
104 | #define CMD_SINGLE_WRITE 0xc9 | |
105 | #define CMD_SINGLE_READ 0xca | |
106 | #define CMD_RESET 0xcf | |
107 | ||
108 | #define N_OK 1 | |
109 | #define N_FAIL 0 | |
110 | #define N_RESET -1 | |
111 | #define N_RETRY -2 | |
112 | ||
113 | #define DATA_PKT_SZ_256 256 | |
114 | #define DATA_PKT_SZ_512 512 | |
115 | #define DATA_PKT_SZ_1K 1024 | |
116 | #define DATA_PKT_SZ_4K (4 * 1024) | |
117 | #define DATA_PKT_SZ_8K (8 * 1024) | |
118 | #define DATA_PKT_SZ DATA_PKT_SZ_8K | |
119 | ||
43a76229 GL |
120 | #define USE_SPI_DMA 0 |
121 | ||
43a76229 GL |
122 | static int wilc_bus_probe(struct spi_device *spi) |
123 | { | |
124 | int ret, gpio; | |
125 | struct wilc *wilc; | |
126 | ||
127 | gpio = of_get_gpio(spi->dev.of_node, 0); | |
128 | if (gpio < 0) | |
129 | gpio = GPIO_NUM; | |
130 | ||
131 | ret = wilc_netdev_init(&wilc, NULL, HIF_SPI, GPIO_NUM, &wilc_hif_spi); | |
132 | if (ret) | |
133 | return ret; | |
134 | ||
135 | spi_set_drvdata(spi, wilc); | |
136 | wilc->dev = &spi->dev; | |
137 | ||
138 | return 0; | |
139 | } | |
140 | ||
141 | static int wilc_bus_remove(struct spi_device *spi) | |
142 | { | |
143 | wilc_netdev_cleanup(spi_get_drvdata(spi)); | |
144 | return 0; | |
145 | } | |
146 | ||
147 | static const struct of_device_id wilc1000_of_match[] = { | |
148 | { .compatible = "atmel,wilc_spi", }, | |
149 | {} | |
150 | }; | |
151 | MODULE_DEVICE_TABLE(of, wilc1000_of_match); | |
152 | ||
d27afda3 | 153 | static struct spi_driver wilc1000_spi_driver = { |
43a76229 GL |
154 | .driver = { |
155 | .name = MODALIAS, | |
156 | .of_match_table = wilc1000_of_match, | |
157 | }, | |
158 | .probe = wilc_bus_probe, | |
159 | .remove = wilc_bus_remove, | |
160 | }; | |
161 | module_spi_driver(wilc1000_spi_driver); | |
162 | MODULE_LICENSE("GPL"); | |
163 | ||
164 | static int wilc_spi_tx(struct wilc *wilc, u8 *b, u32 len) | |
165 | { | |
166 | struct spi_device *spi = to_spi_device(wilc->dev); | |
167 | int ret; | |
168 | struct spi_message msg; | |
169 | ||
170 | if (len > 0 && b) { | |
171 | struct spi_transfer tr = { | |
172 | .tx_buf = b, | |
173 | .len = len, | |
174 | .delay_usecs = 0, | |
175 | }; | |
176 | char *r_buffer = kzalloc(len, GFP_KERNEL); | |
177 | ||
178 | if (!r_buffer) | |
179 | return -ENOMEM; | |
180 | ||
181 | tr.rx_buf = r_buffer; | |
182 | dev_dbg(&spi->dev, "Request writing %d bytes\n", len); | |
183 | ||
184 | memset(&msg, 0, sizeof(msg)); | |
185 | spi_message_init(&msg); | |
186 | msg.spi = spi; | |
187 | msg.is_dma_mapped = USE_SPI_DMA; | |
188 | spi_message_add_tail(&tr, &msg); | |
189 | ||
190 | ret = spi_sync(spi, &msg); | |
191 | if (ret < 0) | |
192 | dev_err(&spi->dev, "SPI transaction failed\n"); | |
193 | ||
194 | kfree(r_buffer); | |
195 | } else { | |
196 | dev_err(&spi->dev, | |
197 | "can't write data with the following length: %d\n", | |
198 | len); | |
43a76229 GL |
199 | ret = -EINVAL; |
200 | } | |
201 | ||
202 | return ret; | |
203 | } | |
204 | ||
205 | static int wilc_spi_rx(struct wilc *wilc, u8 *rb, u32 rlen) | |
206 | { | |
207 | struct spi_device *spi = to_spi_device(wilc->dev); | |
208 | int ret; | |
209 | ||
210 | if (rlen > 0) { | |
211 | struct spi_message msg; | |
212 | struct spi_transfer tr = { | |
213 | .rx_buf = rb, | |
214 | .len = rlen, | |
215 | .delay_usecs = 0, | |
216 | ||
217 | }; | |
218 | char *t_buffer = kzalloc(rlen, GFP_KERNEL); | |
219 | ||
220 | if (!t_buffer) | |
221 | return -ENOMEM; | |
222 | ||
223 | tr.tx_buf = t_buffer; | |
224 | ||
225 | memset(&msg, 0, sizeof(msg)); | |
226 | spi_message_init(&msg); | |
227 | msg.spi = spi; | |
228 | msg.is_dma_mapped = USE_SPI_DMA; | |
229 | spi_message_add_tail(&tr, &msg); | |
230 | ||
231 | ret = spi_sync(spi, &msg); | |
232 | if (ret < 0) | |
233 | dev_err(&spi->dev, "SPI transaction failed\n"); | |
234 | kfree(t_buffer); | |
235 | } else { | |
236 | dev_err(&spi->dev, | |
237 | "can't read data with the following length: %u\n", | |
238 | rlen); | |
239 | ret = -EINVAL; | |
240 | } | |
241 | ||
242 | return ret; | |
243 | } | |
244 | ||
245 | static int wilc_spi_tx_rx(struct wilc *wilc, u8 *wb, u8 *rb, u32 rlen) | |
246 | { | |
247 | struct spi_device *spi = to_spi_device(wilc->dev); | |
248 | int ret; | |
249 | ||
250 | if (rlen > 0) { | |
251 | struct spi_message msg; | |
252 | struct spi_transfer tr = { | |
253 | .rx_buf = rb, | |
254 | .tx_buf = wb, | |
255 | .len = rlen, | |
256 | .bits_per_word = 8, | |
257 | .delay_usecs = 0, | |
258 | ||
259 | }; | |
260 | ||
261 | memset(&msg, 0, sizeof(msg)); | |
262 | spi_message_init(&msg); | |
263 | msg.spi = spi; | |
264 | msg.is_dma_mapped = USE_SPI_DMA; | |
265 | ||
266 | spi_message_add_tail(&tr, &msg); | |
267 | ret = spi_sync(spi, &msg); | |
268 | if (ret < 0) | |
269 | dev_err(&spi->dev, "SPI transaction failed\n"); | |
270 | } else { | |
271 | dev_err(&spi->dev, | |
272 | "can't read data with the following length: %u\n", | |
273 | rlen); | |
274 | ret = -EINVAL; | |
275 | } | |
276 | ||
277 | return ret; | |
278 | } | |
279 | ||
49dcd0dd GL |
280 | static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz, |
281 | u8 clockless) | |
c5c77ba1 | 282 | { |
ac1da162 | 283 | struct spi_device *spi = to_spi_device(wilc->dev); |
51e825f7 CL |
284 | u8 wb[32], rb[32]; |
285 | u8 wix, rix; | |
fbc2fe16 | 286 | u32 len2; |
51e825f7 | 287 | u8 rsp; |
c5c77ba1 JK |
288 | int len = 0; |
289 | int result = N_OK; | |
290 | ||
291 | wb[0] = cmd; | |
292 | switch (cmd) { | |
293 | case CMD_SINGLE_READ: /* single word (4 bytes) read */ | |
51e825f7 CL |
294 | wb[1] = (u8)(adr >> 16); |
295 | wb[2] = (u8)(adr >> 8); | |
296 | wb[3] = (u8)adr; | |
c5c77ba1 JK |
297 | len = 5; |
298 | break; | |
299 | ||
300 | case CMD_INTERNAL_READ: /* internal register read */ | |
51e825f7 | 301 | wb[1] = (u8)(adr >> 8); |
c5c77ba1 | 302 | if (clockless == 1) |
ffda203c | 303 | wb[1] |= BIT(7); |
51e825f7 | 304 | wb[2] = (u8)adr; |
c5c77ba1 JK |
305 | wb[3] = 0x00; |
306 | len = 5; | |
307 | break; | |
308 | ||
309 | case CMD_TERMINATE: /* termination */ | |
310 | wb[1] = 0x00; | |
311 | wb[2] = 0x00; | |
312 | wb[3] = 0x00; | |
313 | len = 5; | |
314 | break; | |
315 | ||
316 | case CMD_REPEAT: /* repeat */ | |
317 | wb[1] = 0x00; | |
318 | wb[2] = 0x00; | |
319 | wb[3] = 0x00; | |
320 | len = 5; | |
321 | break; | |
322 | ||
323 | case CMD_RESET: /* reset */ | |
324 | wb[1] = 0xff; | |
325 | wb[2] = 0xff; | |
326 | wb[3] = 0xff; | |
327 | len = 5; | |
328 | break; | |
329 | ||
330 | case CMD_DMA_WRITE: /* dma write */ | |
331 | case CMD_DMA_READ: /* dma read */ | |
51e825f7 CL |
332 | wb[1] = (u8)(adr >> 16); |
333 | wb[2] = (u8)(adr >> 8); | |
334 | wb[3] = (u8)adr; | |
335 | wb[4] = (u8)(sz >> 8); | |
336 | wb[5] = (u8)(sz); | |
c5c77ba1 JK |
337 | len = 7; |
338 | break; | |
339 | ||
340 | case CMD_DMA_EXT_WRITE: /* dma extended write */ | |
341 | case CMD_DMA_EXT_READ: /* dma extended read */ | |
51e825f7 CL |
342 | wb[1] = (u8)(adr >> 16); |
343 | wb[2] = (u8)(adr >> 8); | |
344 | wb[3] = (u8)adr; | |
345 | wb[4] = (u8)(sz >> 16); | |
346 | wb[5] = (u8)(sz >> 8); | |
347 | wb[6] = (u8)(sz); | |
c5c77ba1 JK |
348 | len = 8; |
349 | break; | |
350 | ||
351 | case CMD_INTERNAL_WRITE: /* internal register write */ | |
51e825f7 | 352 | wb[1] = (u8)(adr >> 8); |
c5c77ba1 | 353 | if (clockless == 1) |
ffda203c | 354 | wb[1] |= BIT(7); |
51e825f7 | 355 | wb[2] = (u8)(adr); |
c5c77ba1 JK |
356 | wb[3] = b[3]; |
357 | wb[4] = b[2]; | |
358 | wb[5] = b[1]; | |
359 | wb[6] = b[0]; | |
360 | len = 8; | |
361 | break; | |
362 | ||
363 | case CMD_SINGLE_WRITE: /* single word write */ | |
51e825f7 CL |
364 | wb[1] = (u8)(adr >> 16); |
365 | wb[2] = (u8)(adr >> 8); | |
366 | wb[3] = (u8)(adr); | |
c5c77ba1 JK |
367 | wb[4] = b[3]; |
368 | wb[5] = b[2]; | |
369 | wb[6] = b[1]; | |
370 | wb[7] = b[0]; | |
371 | len = 9; | |
372 | break; | |
373 | ||
374 | default: | |
375 | result = N_FAIL; | |
376 | break; | |
377 | } | |
378 | ||
e0a30008 | 379 | if (result != N_OK) |
c5c77ba1 | 380 | return result; |
c5c77ba1 | 381 | |
78174ada | 382 | if (!g_spi.crc_off) |
51e825f7 | 383 | wb[len - 1] = (crc7(0x7f, (const u8 *)&wb[0], len - 1)) << 1; |
78174ada | 384 | else |
c5c77ba1 | 385 | len -= 1; |
c5c77ba1 JK |
386 | |
387 | #define NUM_SKIP_BYTES (1) | |
388 | #define NUM_RSP_BYTES (2) | |
389 | #define NUM_DATA_HDR_BYTES (1) | |
390 | #define NUM_DATA_BYTES (4) | |
391 | #define NUM_CRC_BYTES (2) | |
392 | #define NUM_DUMMY_BYTES (3) | |
393 | if ((cmd == CMD_RESET) || | |
394 | (cmd == CMD_TERMINATE) || | |
395 | (cmd == CMD_REPEAT)) { | |
396 | len2 = len + (NUM_SKIP_BYTES + NUM_RSP_BYTES + NUM_DUMMY_BYTES); | |
397 | } else if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) { | |
398 | if (!g_spi.crc_off) { | |
399 | len2 = len + (NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES | |
400 | + NUM_CRC_BYTES + NUM_DUMMY_BYTES); | |
401 | } else { | |
402 | len2 = len + (NUM_RSP_BYTES + NUM_DATA_HDR_BYTES + NUM_DATA_BYTES | |
403 | + NUM_DUMMY_BYTES); | |
404 | } | |
405 | } else { | |
406 | len2 = len + (NUM_RSP_BYTES + NUM_DUMMY_BYTES); | |
407 | } | |
408 | #undef NUM_DUMMY_BYTES | |
409 | ||
5cc59d29 | 410 | if (len2 > ARRAY_SIZE(wb)) { |
ac1da162 | 411 | dev_err(&spi->dev, "spi buffer size too small (%d) (%zu)\n", |
5cc59d29 | 412 | len2, ARRAY_SIZE(wb)); |
c5c77ba1 JK |
413 | result = N_FAIL; |
414 | return result; | |
415 | } | |
416 | /* zero spi write buffers. */ | |
e0a30008 | 417 | for (wix = len; wix < len2; wix++) |
c5c77ba1 | 418 | wb[wix] = 0; |
c5c77ba1 JK |
419 | rix = len; |
420 | ||
d4312b6f | 421 | if (wilc_spi_tx_rx(wilc, wb, rb, len2)) { |
ac1da162 | 422 | dev_err(&spi->dev, "Failed cmd write, bus error...\n"); |
c5c77ba1 JK |
423 | result = N_FAIL; |
424 | return result; | |
425 | } | |
426 | ||
c5c77ba1 JK |
427 | /** |
428 | * Command/Control response | |
429 | **/ | |
430 | if ((cmd == CMD_RESET) || | |
431 | (cmd == CMD_TERMINATE) || | |
432 | (cmd == CMD_REPEAT)) { | |
433 | rix++; /* skip 1 byte */ | |
434 | } | |
435 | ||
436 | /* do { */ | |
437 | rsp = rb[rix++]; | |
438 | /* if(rsp == cmd) break; */ | |
439 | /* } while(&rptr[1] <= &rb[len2]); */ | |
440 | ||
441 | if (rsp != cmd) { | |
8779bf84 AJ |
442 | dev_err(&spi->dev, |
443 | "Failed cmd response, cmd (%02x), resp (%02x)\n", | |
444 | cmd, rsp); | |
c5c77ba1 JK |
445 | result = N_FAIL; |
446 | return result; | |
447 | } | |
448 | ||
449 | /** | |
450 | * State response | |
451 | **/ | |
452 | rsp = rb[rix++]; | |
453 | if (rsp != 0x00) { | |
ac1da162 GL |
454 | dev_err(&spi->dev, "Failed cmd state response state (%02x)\n", |
455 | rsp); | |
c5c77ba1 JK |
456 | result = N_FAIL; |
457 | return result; | |
458 | } | |
459 | ||
460 | if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ) | |
461 | || (cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { | |
462 | int retry; | |
ec53adfe | 463 | /* u16 crc1, crc2; */ |
51e825f7 | 464 | u8 crc[2]; |
c5c77ba1 JK |
465 | /** |
466 | * Data Respnose header | |
467 | **/ | |
468 | retry = 100; | |
469 | do { | |
470 | /* ensure there is room in buffer later to read data and crc */ | |
471 | if (rix < len2) { | |
472 | rsp = rb[rix++]; | |
473 | } else { | |
474 | retry = 0; | |
475 | break; | |
476 | } | |
477 | if (((rsp >> 4) & 0xf) == 0xf) | |
478 | break; | |
479 | } while (retry--); | |
480 | ||
481 | if (retry <= 0) { | |
ac1da162 GL |
482 | dev_err(&spi->dev, |
483 | "Error, data read response (%02x)\n", rsp); | |
c5c77ba1 JK |
484 | result = N_RESET; |
485 | return result; | |
486 | } | |
487 | ||
488 | if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) { | |
489 | /** | |
490 | * Read bytes | |
491 | **/ | |
492 | if ((rix + 3) < len2) { | |
493 | b[0] = rb[rix++]; | |
494 | b[1] = rb[rix++]; | |
495 | b[2] = rb[rix++]; | |
496 | b[3] = rb[rix++]; | |
497 | } else { | |
ac1da162 GL |
498 | dev_err(&spi->dev, |
499 | "buffer overrun when reading data.\n"); | |
c5c77ba1 JK |
500 | result = N_FAIL; |
501 | return result; | |
502 | } | |
503 | ||
504 | if (!g_spi.crc_off) { | |
505 | /** | |
506 | * Read Crc | |
507 | **/ | |
508 | if ((rix + 1) < len2) { | |
509 | crc[0] = rb[rix++]; | |
510 | crc[1] = rb[rix++]; | |
511 | } else { | |
5142a14e | 512 | dev_err(&spi->dev, "buffer overrun when reading crc.\n"); |
c5c77ba1 JK |
513 | result = N_FAIL; |
514 | return result; | |
515 | } | |
516 | } | |
517 | } else if ((cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) { | |
518 | int ix; | |
519 | ||
520 | /* some data may be read in response to dummy bytes. */ | |
e0a30008 | 521 | for (ix = 0; (rix < len2) && (ix < sz); ) |
c5c77ba1 | 522 | b[ix++] = rb[rix++]; |
61500fbd | 523 | |
c5c77ba1 JK |
524 | sz -= ix; |
525 | ||
526 | if (sz > 0) { | |
527 | int nbytes; | |
528 | ||
78174ada | 529 | if (sz <= (DATA_PKT_SZ - ix)) |
c5c77ba1 | 530 | nbytes = sz; |
78174ada | 531 | else |
c5c77ba1 | 532 | nbytes = DATA_PKT_SZ - ix; |
c5c77ba1 JK |
533 | |
534 | /** | |
535 | * Read bytes | |
536 | **/ | |
d4312b6f | 537 | if (wilc_spi_rx(wilc, &b[ix], nbytes)) { |
ac1da162 | 538 | dev_err(&spi->dev, "Failed data block read, bus error...\n"); |
c5c77ba1 JK |
539 | result = N_FAIL; |
540 | goto _error_; | |
541 | } | |
542 | ||
543 | /** | |
544 | * Read Crc | |
545 | **/ | |
546 | if (!g_spi.crc_off) { | |
d4312b6f | 547 | if (wilc_spi_rx(wilc, crc, 2)) { |
ac1da162 | 548 | dev_err(&spi->dev, "Failed data block crc read, bus error...\n"); |
c5c77ba1 JK |
549 | result = N_FAIL; |
550 | goto _error_; | |
551 | } | |
552 | } | |
553 | ||
554 | ||
555 | ix += nbytes; | |
556 | sz -= nbytes; | |
557 | } | |
558 | ||
559 | /* if any data in left unread, then read the rest using normal DMA code.*/ | |
560 | while (sz > 0) { | |
561 | int nbytes; | |
562 | ||
78174ada | 563 | if (sz <= DATA_PKT_SZ) |
c5c77ba1 | 564 | nbytes = sz; |
78174ada | 565 | else |
c5c77ba1 | 566 | nbytes = DATA_PKT_SZ; |
c5c77ba1 JK |
567 | |
568 | /** | |
569 | * read data response only on the next DMA cycles not | |
570 | * the first DMA since data response header is already | |
571 | * handled above for the first DMA. | |
572 | **/ | |
573 | /** | |
574 | * Data Respnose header | |
575 | **/ | |
576 | retry = 10; | |
577 | do { | |
d4312b6f | 578 | if (wilc_spi_rx(wilc, &rsp, 1)) { |
ac1da162 | 579 | dev_err(&spi->dev, "Failed data response read, bus error...\n"); |
c5c77ba1 JK |
580 | result = N_FAIL; |
581 | break; | |
582 | } | |
583 | if (((rsp >> 4) & 0xf) == 0xf) | |
584 | break; | |
585 | } while (retry--); | |
586 | ||
587 | if (result == N_FAIL) | |
588 | break; | |
589 | ||
590 | ||
591 | /** | |
592 | * Read bytes | |
593 | **/ | |
d4312b6f | 594 | if (wilc_spi_rx(wilc, &b[ix], nbytes)) { |
ac1da162 | 595 | dev_err(&spi->dev, "Failed data block read, bus error...\n"); |
c5c77ba1 JK |
596 | result = N_FAIL; |
597 | break; | |
598 | } | |
599 | ||
600 | /** | |
601 | * Read Crc | |
602 | **/ | |
603 | if (!g_spi.crc_off) { | |
d4312b6f | 604 | if (wilc_spi_rx(wilc, crc, 2)) { |
ac1da162 | 605 | dev_err(&spi->dev, "Failed data block crc read, bus error...\n"); |
c5c77ba1 JK |
606 | result = N_FAIL; |
607 | break; | |
608 | } | |
609 | } | |
610 | ||
611 | ix += nbytes; | |
612 | sz -= nbytes; | |
613 | } | |
614 | } | |
615 | } | |
616 | _error_: | |
617 | return result; | |
618 | } | |
619 | ||
49dcd0dd | 620 | static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz) |
c5c77ba1 | 621 | { |
ac1da162 | 622 | struct spi_device *spi = to_spi_device(wilc->dev); |
c5c77ba1 JK |
623 | int ix, nbytes; |
624 | int result = 1; | |
51e825f7 CL |
625 | u8 cmd, order, crc[2] = {0}; |
626 | /* u8 rsp; */ | |
c5c77ba1 JK |
627 | |
628 | /** | |
629 | * Data | |
630 | **/ | |
631 | ix = 0; | |
632 | do { | |
633 | if (sz <= DATA_PKT_SZ) | |
634 | nbytes = sz; | |
635 | else | |
636 | nbytes = DATA_PKT_SZ; | |
637 | ||
638 | /** | |
639 | * Write command | |
640 | **/ | |
641 | cmd = 0xf0; | |
642 | if (ix == 0) { | |
643 | if (sz <= DATA_PKT_SZ) | |
644 | ||
645 | order = 0x3; | |
646 | else | |
647 | order = 0x1; | |
648 | } else { | |
649 | if (sz <= DATA_PKT_SZ) | |
650 | order = 0x3; | |
651 | else | |
652 | order = 0x2; | |
653 | } | |
654 | cmd |= order; | |
d4312b6f | 655 | if (wilc_spi_tx(wilc, &cmd, 1)) { |
ac1da162 GL |
656 | dev_err(&spi->dev, |
657 | "Failed data block cmd write, bus error...\n"); | |
c5c77ba1 JK |
658 | result = N_FAIL; |
659 | break; | |
660 | } | |
661 | ||
662 | /** | |
663 | * Write data | |
664 | **/ | |
d4312b6f | 665 | if (wilc_spi_tx(wilc, &b[ix], nbytes)) { |
ac1da162 GL |
666 | dev_err(&spi->dev, |
667 | "Failed data block write, bus error...\n"); | |
c5c77ba1 JK |
668 | result = N_FAIL; |
669 | break; | |
670 | } | |
671 | ||
672 | /** | |
673 | * Write Crc | |
674 | **/ | |
675 | if (!g_spi.crc_off) { | |
d4312b6f | 676 | if (wilc_spi_tx(wilc, crc, 2)) { |
5142a14e | 677 | dev_err(&spi->dev, "Failed data block crc write, bus error...\n"); |
c5c77ba1 JK |
678 | result = N_FAIL; |
679 | break; | |
680 | } | |
681 | } | |
682 | ||
683 | /** | |
684 | * No need to wait for response | |
685 | **/ | |
c5c77ba1 JK |
686 | ix += nbytes; |
687 | sz -= nbytes; | |
688 | } while (sz); | |
689 | ||
690 | ||
691 | return result; | |
692 | } | |
693 | ||
694 | /******************************************** | |
695 | * | |
696 | * Spi Internal Read/Write Function | |
697 | * | |
698 | ********************************************/ | |
699 | ||
49dcd0dd | 700 | static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat) |
c5c77ba1 | 701 | { |
ac1da162 | 702 | struct spi_device *spi = to_spi_device(wilc->dev); |
c5c77ba1 JK |
703 | int result; |
704 | ||
9e6627ac | 705 | dat = cpu_to_le32(dat); |
49dcd0dd GL |
706 | result = spi_cmd_complete(wilc, CMD_INTERNAL_WRITE, adr, (u8 *)&dat, 4, |
707 | 0); | |
e0a30008 | 708 | if (result != N_OK) |
ac1da162 | 709 | dev_err(&spi->dev, "Failed internal write cmd...\n"); |
c5c77ba1 | 710 | |
c5c77ba1 JK |
711 | return result; |
712 | } | |
713 | ||
49dcd0dd | 714 | static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data) |
c5c77ba1 | 715 | { |
ac1da162 | 716 | struct spi_device *spi = to_spi_device(wilc->dev); |
c5c77ba1 JK |
717 | int result; |
718 | ||
49dcd0dd GL |
719 | result = spi_cmd_complete(wilc, CMD_INTERNAL_READ, adr, (u8 *)data, 4, |
720 | 0); | |
c5c77ba1 | 721 | if (result != N_OK) { |
ac1da162 | 722 | dev_err(&spi->dev, "Failed internal read cmd...\n"); |
c5c77ba1 JK |
723 | return 0; |
724 | } | |
c5c77ba1 | 725 | |
9e6627ac | 726 | *data = cpu_to_le32(*data); |
c5c77ba1 JK |
727 | |
728 | return 1; | |
729 | } | |
730 | ||
731 | /******************************************** | |
732 | * | |
733 | * Spi interfaces | |
734 | * | |
735 | ********************************************/ | |
736 | ||
49dcd0dd | 737 | static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data) |
c5c77ba1 | 738 | { |
ac1da162 | 739 | struct spi_device *spi = to_spi_device(wilc->dev); |
c5c77ba1 | 740 | int result = N_OK; |
51e825f7 CL |
741 | u8 cmd = CMD_SINGLE_WRITE; |
742 | u8 clockless = 0; | |
c5c77ba1 | 743 | |
9e6627ac | 744 | data = cpu_to_le32(data); |
c5c77ba1 JK |
745 | if (addr < 0x30) { |
746 | /* Clockless register*/ | |
747 | cmd = CMD_INTERNAL_WRITE; | |
748 | clockless = 1; | |
749 | } | |
750 | ||
49dcd0dd | 751 | result = spi_cmd_complete(wilc, cmd, addr, (u8 *)&data, 4, clockless); |
e0a30008 | 752 | if (result != N_OK) |
ac1da162 | 753 | dev_err(&spi->dev, "Failed cmd, write reg (%08x)...\n", addr); |
c5c77ba1 JK |
754 | |
755 | return result; | |
c5c77ba1 JK |
756 | } |
757 | ||
d4312b6f | 758 | static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) |
c5c77ba1 | 759 | { |
ac1da162 | 760 | struct spi_device *spi = to_spi_device(wilc->dev); |
c5c77ba1 | 761 | int result; |
51e825f7 | 762 | u8 cmd = CMD_DMA_EXT_WRITE; |
c5c77ba1 JK |
763 | |
764 | /** | |
765 | * has to be greated than 4 | |
766 | **/ | |
767 | if (size <= 4) | |
768 | return 0; | |
769 | ||
49dcd0dd | 770 | result = spi_cmd_complete(wilc, cmd, addr, NULL, size, 0); |
c5c77ba1 | 771 | if (result != N_OK) { |
ac1da162 GL |
772 | dev_err(&spi->dev, |
773 | "Failed cmd, write block (%08x)...\n", addr); | |
c5c77ba1 JK |
774 | return 0; |
775 | } | |
c5c77ba1 JK |
776 | |
777 | /** | |
778 | * Data | |
779 | **/ | |
49dcd0dd | 780 | result = spi_data_write(wilc, buf, size); |
e0a30008 | 781 | if (result != N_OK) |
ac1da162 | 782 | dev_err(&spi->dev, "Failed block data write...\n"); |
c5c77ba1 JK |
783 | |
784 | return 1; | |
785 | } | |
786 | ||
49dcd0dd | 787 | static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data) |
c5c77ba1 | 788 | { |
ac1da162 | 789 | struct spi_device *spi = to_spi_device(wilc->dev); |
c5c77ba1 | 790 | int result = N_OK; |
51e825f7 CL |
791 | u8 cmd = CMD_SINGLE_READ; |
792 | u8 clockless = 0; | |
c5c77ba1 | 793 | |
c5c77ba1 | 794 | if (addr < 0x30) { |
ac1da162 | 795 | /* dev_err(&spi->dev, "***** read addr %d\n\n", addr); */ |
c5c77ba1 JK |
796 | /* Clockless register*/ |
797 | cmd = CMD_INTERNAL_READ; | |
798 | clockless = 1; | |
799 | } | |
800 | ||
49dcd0dd | 801 | result = spi_cmd_complete(wilc, cmd, addr, (u8 *)data, 4, clockless); |
c5c77ba1 | 802 | if (result != N_OK) { |
ac1da162 | 803 | dev_err(&spi->dev, "Failed cmd, read reg (%08x)...\n", addr); |
c5c77ba1 JK |
804 | return 0; |
805 | } | |
c5c77ba1 | 806 | |
9e6627ac | 807 | *data = cpu_to_le32(*data); |
c5c77ba1 JK |
808 | |
809 | return 1; | |
810 | } | |
811 | ||
d4312b6f | 812 | static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) |
c5c77ba1 | 813 | { |
ac1da162 | 814 | struct spi_device *spi = to_spi_device(wilc->dev); |
51e825f7 | 815 | u8 cmd = CMD_DMA_EXT_READ; |
c5c77ba1 JK |
816 | int result; |
817 | ||
818 | if (size <= 4) | |
819 | return 0; | |
820 | ||
49dcd0dd | 821 | result = spi_cmd_complete(wilc, cmd, addr, buf, size, 0); |
c5c77ba1 | 822 | if (result != N_OK) { |
ac1da162 | 823 | dev_err(&spi->dev, "Failed cmd, read block (%08x)...\n", addr); |
c5c77ba1 JK |
824 | return 0; |
825 | } | |
c5c77ba1 JK |
826 | |
827 | return 1; | |
828 | } | |
829 | ||
830 | /******************************************** | |
831 | * | |
832 | * Bus interfaces | |
833 | * | |
834 | ********************************************/ | |
835 | ||
49dcd0dd | 836 | static int _wilc_spi_deinit(struct wilc *wilc) |
c5c77ba1 JK |
837 | { |
838 | /** | |
839 | * TODO: | |
840 | **/ | |
841 | return 1; | |
842 | } | |
843 | ||
5397cbc2 | 844 | static int wilc_spi_init(struct wilc *wilc, bool resume) |
c5c77ba1 | 845 | { |
ac1da162 | 846 | struct spi_device *spi = to_spi_device(wilc->dev); |
fbc2fe16 CL |
847 | u32 reg; |
848 | u32 chipid; | |
c5c77ba1 JK |
849 | |
850 | static int isinit; | |
851 | ||
852 | if (isinit) { | |
853 | ||
49dcd0dd | 854 | if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) { |
ac1da162 | 855 | dev_err(&spi->dev, "Fail cmd read chip id...\n"); |
c5c77ba1 JK |
856 | return 0; |
857 | } | |
858 | return 1; | |
859 | } | |
860 | ||
6a707a9e | 861 | memset(&g_spi, 0, sizeof(struct wilc_spi)); |
c5c77ba1 | 862 | |
c5c77ba1 JK |
863 | /** |
864 | * configure protocol | |
865 | **/ | |
866 | g_spi.crc_off = 0; | |
867 | ||
868 | /* TODO: We can remove the CRC trials if there is a definite way to reset */ | |
869 | /* the SPI to it's initial value. */ | |
49dcd0dd | 870 | if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { |
c5c77ba1 JK |
871 | /* Read failed. Try with CRC off. This might happen when module |
872 | * is removed but chip isn't reset*/ | |
873 | g_spi.crc_off = 1; | |
2218b8fc | 874 | dev_err(&spi->dev, "Failed internal read protocol with CRC on, retrying with CRC off...\n"); |
49dcd0dd | 875 | if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, ®)) { |
c5c77ba1 | 876 | /* Reaad failed with both CRC on and off, something went bad */ |
ac1da162 GL |
877 | dev_err(&spi->dev, |
878 | "Failed internal read protocol...\n"); | |
c5c77ba1 JK |
879 | return 0; |
880 | } | |
881 | } | |
882 | if (g_spi.crc_off == 0) { | |
883 | reg &= ~0xc; /* disable crc checking */ | |
884 | reg &= ~0x70; | |
885 | reg |= (0x5 << 4); | |
49dcd0dd | 886 | if (!spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg)) { |
ac1da162 | 887 | dev_err(&spi->dev, "[wilc spi %d]: Failed internal write protocol reg...\n", __LINE__); |
c5c77ba1 JK |
888 | return 0; |
889 | } | |
890 | g_spi.crc_off = 1; | |
891 | } | |
892 | ||
893 | ||
894 | /** | |
895 | * make sure can read back chip id correctly | |
896 | **/ | |
49dcd0dd | 897 | if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) { |
ac1da162 | 898 | dev_err(&spi->dev, "Fail cmd read chip id...\n"); |
c5c77ba1 JK |
899 | return 0; |
900 | } | |
ac1da162 | 901 | /* dev_err(&spi->dev, "chipid (%08x)\n", chipid); */ |
c5c77ba1 JK |
902 | |
903 | g_spi.has_thrpt_enh = 1; | |
904 | ||
905 | isinit = 1; | |
906 | ||
907 | return 1; | |
908 | } | |
909 | ||
49dcd0dd | 910 | static int wilc_spi_read_size(struct wilc *wilc, u32 *size) |
c5c77ba1 | 911 | { |
ac1da162 | 912 | struct spi_device *spi = to_spi_device(wilc->dev); |
c5c77ba1 | 913 | int ret; |
8dfaafd6 | 914 | |
c5c77ba1 | 915 | if (g_spi.has_thrpt_enh) { |
49dcd0dd GL |
916 | ret = spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE, |
917 | size); | |
c5c77ba1 JK |
918 | *size = *size & IRQ_DMA_WD_CNT_MASK; |
919 | } else { | |
fbc2fe16 CL |
920 | u32 tmp; |
921 | u32 byte_cnt; | |
c5c77ba1 | 922 | |
49dcd0dd GL |
923 | ret = wilc_spi_read_reg(wilc, WILC_VMM_TO_HOST_SIZE, |
924 | &byte_cnt); | |
c5c77ba1 | 925 | if (!ret) { |
ac1da162 GL |
926 | dev_err(&spi->dev, |
927 | "Failed read WILC_VMM_TO_HOST_SIZE ...\n"); | |
c5c77ba1 JK |
928 | goto _fail_; |
929 | } | |
930 | tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK; | |
931 | *size = tmp; | |
932 | } | |
933 | ||
934 | ||
935 | ||
936 | _fail_: | |
937 | return ret; | |
938 | } | |
939 | ||
940 | ||
941 | ||
49dcd0dd | 942 | static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status) |
c5c77ba1 | 943 | { |
ac1da162 | 944 | struct spi_device *spi = to_spi_device(wilc->dev); |
c5c77ba1 | 945 | int ret; |
8dfaafd6 | 946 | |
c5c77ba1 | 947 | if (g_spi.has_thrpt_enh) { |
49dcd0dd GL |
948 | ret = spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE, |
949 | int_status); | |
c5c77ba1 | 950 | } else { |
fbc2fe16 CL |
951 | u32 tmp; |
952 | u32 byte_cnt; | |
c5c77ba1 | 953 | |
49dcd0dd GL |
954 | ret = wilc_spi_read_reg(wilc, WILC_VMM_TO_HOST_SIZE, |
955 | &byte_cnt); | |
c5c77ba1 | 956 | if (!ret) { |
ac1da162 GL |
957 | dev_err(&spi->dev, |
958 | "Failed read WILC_VMM_TO_HOST_SIZE ...\n"); | |
c5c77ba1 JK |
959 | goto _fail_; |
960 | } | |
961 | tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK; | |
962 | ||
963 | { | |
964 | int happended, j; | |
965 | ||
966 | j = 0; | |
967 | do { | |
fbc2fe16 | 968 | u32 irq_flags; |
c5c77ba1 JK |
969 | |
970 | happended = 0; | |
971 | ||
49dcd0dd | 972 | wilc_spi_read_reg(wilc, 0x1a90, &irq_flags); |
c5c77ba1 JK |
973 | tmp |= ((irq_flags >> 27) << IRG_FLAGS_OFFSET); |
974 | ||
975 | if (g_spi.nint > 5) { | |
49dcd0dd GL |
976 | wilc_spi_read_reg(wilc, 0x1a94, |
977 | &irq_flags); | |
c5c77ba1 JK |
978 | tmp |= (((irq_flags >> 0) & 0x7) << (IRG_FLAGS_OFFSET + 5)); |
979 | } | |
980 | ||
981 | { | |
fbc2fe16 | 982 | u32 unkmown_mask; |
c5c77ba1 JK |
983 | |
984 | unkmown_mask = ~((1ul << g_spi.nint) - 1); | |
985 | ||
986 | if ((tmp >> IRG_FLAGS_OFFSET) & unkmown_mask) { | |
ac1da162 | 987 | dev_err(&spi->dev, "Unexpected interrupt (2): j=%d, tmp=%x, mask=%x\n", j, tmp, unkmown_mask); |
c5c77ba1 JK |
988 | happended = 1; |
989 | } | |
990 | } | |
991 | j++; | |
992 | } while (happended); | |
993 | } | |
994 | ||
995 | *int_status = tmp; | |
996 | ||
997 | } | |
998 | ||
999 | _fail_: | |
1000 | return ret; | |
1001 | } | |
1002 | ||
49dcd0dd | 1003 | static int wilc_spi_clear_int_ext(struct wilc *wilc, u32 val) |
c5c77ba1 | 1004 | { |
ac1da162 | 1005 | struct spi_device *spi = to_spi_device(wilc->dev); |
c5c77ba1 JK |
1006 | int ret; |
1007 | ||
1008 | if (g_spi.has_thrpt_enh) { | |
49dcd0dd GL |
1009 | ret = spi_internal_write(wilc, 0xe844 - WILC_SPI_REG_BASE, |
1010 | val); | |
c5c77ba1 | 1011 | } else { |
fbc2fe16 | 1012 | u32 flags; |
8dfaafd6 | 1013 | |
ffda203c | 1014 | flags = val & (BIT(MAX_NUM_INT) - 1); |
c5c77ba1 JK |
1015 | if (flags) { |
1016 | int i; | |
1017 | ||
1018 | ret = 1; | |
1019 | for (i = 0; i < g_spi.nint; i++) { | |
1020 | /* No matter what you write 1 or 0, it will clear interrupt. */ | |
1021 | if (flags & 1) | |
49dcd0dd | 1022 | ret = wilc_spi_write_reg(wilc, 0x10c8 + i * 4, 1); |
c5c77ba1 JK |
1023 | if (!ret) |
1024 | break; | |
1025 | flags >>= 1; | |
1026 | } | |
1027 | if (!ret) { | |
ac1da162 GL |
1028 | dev_err(&spi->dev, |
1029 | "Failed wilc_spi_write_reg, set reg %x ...\n", | |
1030 | 0x10c8 + i * 4); | |
c5c77ba1 JK |
1031 | goto _fail_; |
1032 | } | |
1033 | for (i = g_spi.nint; i < MAX_NUM_INT; i++) { | |
1034 | if (flags & 1) | |
ac1da162 GL |
1035 | dev_err(&spi->dev, |
1036 | "Unexpected interrupt cleared %d...\n", | |
1037 | i); | |
c5c77ba1 JK |
1038 | flags >>= 1; |
1039 | } | |
1040 | } | |
1041 | ||
1042 | { | |
fbc2fe16 | 1043 | u32 tbl_ctl; |
c5c77ba1 JK |
1044 | |
1045 | tbl_ctl = 0; | |
1046 | /* select VMM table 0 */ | |
1047 | if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0) | |
ffda203c | 1048 | tbl_ctl |= BIT(0); |
c5c77ba1 JK |
1049 | /* select VMM table 1 */ |
1050 | if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1) | |
ffda203c | 1051 | tbl_ctl |= BIT(1); |
c5c77ba1 | 1052 | |
49dcd0dd GL |
1053 | ret = wilc_spi_write_reg(wilc, WILC_VMM_TBL_CTL, |
1054 | tbl_ctl); | |
c5c77ba1 | 1055 | if (!ret) { |
ac1da162 GL |
1056 | dev_err(&spi->dev, |
1057 | "fail write reg vmm_tbl_ctl...\n"); | |
c5c77ba1 JK |
1058 | goto _fail_; |
1059 | } | |
1060 | ||
1061 | if ((val & EN_VMM) == EN_VMM) { | |
1062 | /** | |
1063 | * enable vmm transfer. | |
1064 | **/ | |
49dcd0dd GL |
1065 | ret = wilc_spi_write_reg(wilc, |
1066 | WILC_VMM_CORE_CTL, 1); | |
c5c77ba1 | 1067 | if (!ret) { |
5142a14e | 1068 | dev_err(&spi->dev, "fail write reg vmm_core_ctl...\n"); |
c5c77ba1 JK |
1069 | goto _fail_; |
1070 | } | |
1071 | } | |
1072 | } | |
1073 | } | |
1074 | _fail_: | |
1075 | return ret; | |
1076 | } | |
1077 | ||
49dcd0dd | 1078 | static int wilc_spi_sync_ext(struct wilc *wilc, int nint) |
c5c77ba1 | 1079 | { |
ac1da162 | 1080 | struct spi_device *spi = to_spi_device(wilc->dev); |
fbc2fe16 | 1081 | u32 reg; |
c5c77ba1 JK |
1082 | int ret, i; |
1083 | ||
1084 | if (nint > MAX_NUM_INT) { | |
95b8cb89 | 1085 | dev_err(&spi->dev, "Too many interrupts (%d)...\n", nint); |
c5c77ba1 JK |
1086 | return 0; |
1087 | } | |
1088 | ||
1089 | g_spi.nint = nint; | |
1090 | ||
1091 | /** | |
1092 | * interrupt pin mux select | |
1093 | **/ | |
49dcd0dd | 1094 | ret = wilc_spi_read_reg(wilc, WILC_PIN_MUX_0, ®); |
c5c77ba1 | 1095 | if (!ret) { |
ac1da162 GL |
1096 | dev_err(&spi->dev, "Failed read reg (%08x)...\n", |
1097 | WILC_PIN_MUX_0); | |
c5c77ba1 JK |
1098 | return 0; |
1099 | } | |
ffda203c | 1100 | reg |= BIT(8); |
49dcd0dd | 1101 | ret = wilc_spi_write_reg(wilc, WILC_PIN_MUX_0, reg); |
c5c77ba1 | 1102 | if (!ret) { |
ac1da162 GL |
1103 | dev_err(&spi->dev, "Failed write reg (%08x)...\n", |
1104 | WILC_PIN_MUX_0); | |
c5c77ba1 JK |
1105 | return 0; |
1106 | } | |
1107 | ||
1108 | /** | |
1109 | * interrupt enable | |
1110 | **/ | |
49dcd0dd | 1111 | ret = wilc_spi_read_reg(wilc, WILC_INTR_ENABLE, ®); |
c5c77ba1 | 1112 | if (!ret) { |
ac1da162 GL |
1113 | dev_err(&spi->dev, "Failed read reg (%08x)...\n", |
1114 | WILC_INTR_ENABLE); | |
c5c77ba1 JK |
1115 | return 0; |
1116 | } | |
1117 | ||
e0a30008 | 1118 | for (i = 0; (i < 5) && (nint > 0); i++, nint--) |
ffda203c | 1119 | reg |= (BIT((27 + i))); |
e0a30008 | 1120 | |
49dcd0dd | 1121 | ret = wilc_spi_write_reg(wilc, WILC_INTR_ENABLE, reg); |
c5c77ba1 | 1122 | if (!ret) { |
ac1da162 GL |
1123 | dev_err(&spi->dev, "Failed write reg (%08x)...\n", |
1124 | WILC_INTR_ENABLE); | |
c5c77ba1 JK |
1125 | return 0; |
1126 | } | |
1127 | if (nint) { | |
49dcd0dd | 1128 | ret = wilc_spi_read_reg(wilc, WILC_INTR2_ENABLE, ®); |
c5c77ba1 | 1129 | if (!ret) { |
ac1da162 GL |
1130 | dev_err(&spi->dev, "Failed read reg (%08x)...\n", |
1131 | WILC_INTR2_ENABLE); | |
c5c77ba1 JK |
1132 | return 0; |
1133 | } | |
1134 | ||
e0a30008 | 1135 | for (i = 0; (i < 3) && (nint > 0); i++, nint--) |
ffda203c | 1136 | reg |= BIT(i); |
c5c77ba1 | 1137 | |
49dcd0dd | 1138 | ret = wilc_spi_read_reg(wilc, WILC_INTR2_ENABLE, ®); |
c5c77ba1 | 1139 | if (!ret) { |
ac1da162 GL |
1140 | dev_err(&spi->dev, "Failed write reg (%08x)...\n", |
1141 | WILC_INTR2_ENABLE); | |
c5c77ba1 JK |
1142 | return 0; |
1143 | } | |
1144 | } | |
1145 | ||
1146 | return 1; | |
1147 | } | |
1148 | /******************************************** | |
1149 | * | |
1150 | * Global spi HIF function table | |
1151 | * | |
1152 | ********************************************/ | |
7d37a4a1 | 1153 | const struct wilc_hif_func wilc_hif_spi = { |
2769d942 | 1154 | .hif_init = wilc_spi_init, |
7d37a4a1 AB |
1155 | .hif_deinit = _wilc_spi_deinit, |
1156 | .hif_read_reg = wilc_spi_read_reg, | |
1157 | .hif_write_reg = wilc_spi_write_reg, | |
d4312b6f GL |
1158 | .hif_block_rx = wilc_spi_read, |
1159 | .hif_block_tx = wilc_spi_write, | |
7d37a4a1 AB |
1160 | .hif_read_int = wilc_spi_read_int, |
1161 | .hif_clear_int_ext = wilc_spi_clear_int_ext, | |
1162 | .hif_read_size = wilc_spi_read_size, | |
d4312b6f GL |
1163 | .hif_block_tx_ext = wilc_spi_write, |
1164 | .hif_block_rx_ext = wilc_spi_read, | |
7d37a4a1 | 1165 | .hif_sync_ext = wilc_spi_sync_ext, |
c5c77ba1 | 1166 | }; |