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