blob: 22cf4b7857e5317b34a940d8b100591984ea246c [file] [log] [blame]
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001/* ////////////////////////////////////////////////////////////////////////// */
2/* */
3/* Copyright (c) Atmel Corporation. All rights reserved. */
4/* */
5/* Module Name: wilc_spi.c */
6/* */
7/* */
8/* //////////////////////////////////////////////////////////////////////////// */
Glen Lee43a76222015-12-21 14:18:33 +09009#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>
Johnny Kimc5c77ba2015-05-11 14:30:56 +090020
Chaehyun Lim0c9fc332015-09-30 17:52:14 +090021#include <linux/string.h>
Johnny Kimc5c77ba2015-05-11 14:30:56 +090022#include "wilc_wlan_if.h"
23#include "wilc_wlan.h"
Glen Lee9c800322015-11-06 18:40:22 +090024#include "wilc_wfi_netdevice.h"
Johnny Kimc5c77ba2015-05-11 14:30:56 +090025
Bhumika Goyal6a707a92016-02-21 03:12:11 +053026struct wilc_spi {
Johnny Kimc5c77ba2015-05-11 14:30:56 +090027 int crc_off;
28 int nint;
29 int has_thrpt_enh;
Bhumika Goyal6a707a92016-02-21 03:12:11 +053030};
Johnny Kimc5c77ba2015-05-11 14:30:56 +090031
Bhumika Goyal6a707a92016-02-21 03:12:11 +053032static struct wilc_spi g_spi;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090033
Glen Leed4312b62015-12-21 14:18:31 +090034static int wilc_spi_read(struct wilc *wilc, u32, u8 *, u32);
35static int wilc_spi_write(struct wilc *wilc, u32, u8 *, u32);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090036
37/********************************************
38 *
39 * Crc7
40 *
41 ********************************************/
42
Chaehyun Lim51e825f2015-09-15 14:06:14 +090043static const u8 crc7_syndrome_table[256] = {
Johnny Kimc5c77ba2015-05-11 14:30:56 +090044 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
Chaehyun Lim51e825f2015-09-15 14:06:14 +090078static u8 crc7_byte(u8 crc, u8 data)
Johnny Kimc5c77ba2015-05-11 14:30:56 +090079{
80 return crc7_syndrome_table[(crc << 1) ^ data];
81}
82
Chaehyun Limfbc2fe12015-09-15 14:06:16 +090083static u8 crc7(u8 crc, const u8 *buffer, u32 len)
Johnny Kimc5c77ba2015-05-11 14:30:56 +090084{
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
Glen Lee43a76222015-12-21 14:18:33 +0900120#define USE_SPI_DMA 0
121
Glen Lee43a76222015-12-21 14:18:33 +0900122static 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
141static int wilc_bus_remove(struct spi_device *spi)
142{
143 wilc_netdev_cleanup(spi_get_drvdata(spi));
144 return 0;
145}
146
147static const struct of_device_id wilc1000_of_match[] = {
148 { .compatible = "atmel,wilc_spi", },
149 {}
150};
151MODULE_DEVICE_TABLE(of, wilc1000_of_match);
152
Hugo Camboulived27afda2016-01-04 22:02:23 +0000153static struct spi_driver wilc1000_spi_driver = {
Glen Lee43a76222015-12-21 14:18:33 +0900154 .driver = {
155 .name = MODALIAS,
156 .of_match_table = wilc1000_of_match,
157 },
158 .probe = wilc_bus_probe,
159 .remove = wilc_bus_remove,
160};
161module_spi_driver(wilc1000_spi_driver);
162MODULE_LICENSE("GPL");
163
164static 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);
Glen Lee43a76222015-12-21 14:18:33 +0900199 ret = -EINVAL;
200 }
201
202 return ret;
203}
204
205static 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
245static 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
Glen Lee49dcd0d2015-11-18 15:11:26 +0900280static int spi_cmd_complete(struct wilc *wilc, u8 cmd, u32 adr, u8 *b, u32 sz,
281 u8 clockless)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900282{
Glen Leeac1da162015-12-21 14:18:13 +0900283 struct spi_device *spi = to_spi_device(wilc->dev);
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900284 u8 wb[32], rb[32];
285 u8 wix, rix;
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900286 u32 len2;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900287 u8 rsp;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900288 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 */
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900294 wb[1] = (u8)(adr >> 16);
295 wb[2] = (u8)(adr >> 8);
296 wb[3] = (u8)adr;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900297 len = 5;
298 break;
299
300 case CMD_INTERNAL_READ: /* internal register read */
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900301 wb[1] = (u8)(adr >> 8);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900302 if (clockless == 1)
Anish Bhattffda2032015-09-29 12:15:49 -0700303 wb[1] |= BIT(7);
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900304 wb[2] = (u8)adr;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900305 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 */
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900332 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);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900337 len = 7;
338 break;
339
340 case CMD_DMA_EXT_WRITE: /* dma extended write */
341 case CMD_DMA_EXT_READ: /* dma extended read */
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900342 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);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900348 len = 8;
349 break;
350
351 case CMD_INTERNAL_WRITE: /* internal register write */
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900352 wb[1] = (u8)(adr >> 8);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900353 if (clockless == 1)
Anish Bhattffda2032015-09-29 12:15:49 -0700354 wb[1] |= BIT(7);
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900355 wb[2] = (u8)(adr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900356 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 */
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900364 wb[1] = (u8)(adr >> 16);
365 wb[2] = (u8)(adr >> 8);
366 wb[3] = (u8)(adr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900367 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
Roger H. Newelle0a30002016-02-16 09:25:42 -0330379 if (result != N_OK)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900380 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900381
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530382 if (!g_spi.crc_off)
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900383 wb[len - 1] = (crc7(0x7f, (const u8 *)&wb[0], len - 1)) << 1;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530384 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900385 len -= 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900386
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
Chaehyun Lim5cc59d22015-10-02 16:41:16 +0900410 if (len2 > ARRAY_SIZE(wb)) {
Glen Leeac1da162015-12-21 14:18:13 +0900411 dev_err(&spi->dev, "spi buffer size too small (%d) (%zu)\n",
Chaehyun Lim5cc59d22015-10-02 16:41:16 +0900412 len2, ARRAY_SIZE(wb));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900413 result = N_FAIL;
414 return result;
415 }
416 /* zero spi write buffers. */
Roger H. Newelle0a30002016-02-16 09:25:42 -0330417 for (wix = len; wix < len2; wix++)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900418 wb[wix] = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900419 rix = len;
420
Glen Leed4312b62015-12-21 14:18:31 +0900421 if (wilc_spi_tx_rx(wilc, wb, rb, len2)) {
Glen Leeac1da162015-12-21 14:18:13 +0900422 dev_err(&spi->dev, "Failed cmd write, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900423 result = N_FAIL;
424 return result;
425 }
426
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900427 /**
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) {
Anchal Jain8779bf82016-02-21 22:19:05 +0530442 dev_err(&spi->dev,
443 "Failed cmd response, cmd (%02x), resp (%02x)\n",
444 cmd, rsp);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900445 result = N_FAIL;
446 return result;
447 }
448
449 /**
450 * State response
451 **/
452 rsp = rb[rix++];
453 if (rsp != 0x00) {
Glen Leeac1da162015-12-21 14:18:13 +0900454 dev_err(&spi->dev, "Failed cmd state response state (%02x)\n",
455 rsp);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900456 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;
Chaehyun Limec53adf2015-09-15 14:06:15 +0900463 /* u16 crc1, crc2; */
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900464 u8 crc[2];
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900465 /**
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) {
Glen Leeac1da162015-12-21 14:18:13 +0900482 dev_err(&spi->dev,
483 "Error, data read response (%02x)\n", rsp);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900484 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 {
Glen Leeac1da162015-12-21 14:18:13 +0900498 dev_err(&spi->dev,
499 "buffer overrun when reading data.\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900500 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 {
Roger H. Newell5142a142016-02-16 09:24:56 -0330512 dev_err(&spi->dev, "buffer overrun when reading crc.\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900513 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. */
Roger H. Newelle0a30002016-02-16 09:25:42 -0330521 for (ix = 0; (rix < len2) && (ix < sz); )
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900522 b[ix++] = rb[rix++];
Chaehyun Lim61500fb2015-06-18 14:46:05 +0900523
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900524 sz -= ix;
525
526 if (sz > 0) {
527 int nbytes;
528
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530529 if (sz <= (DATA_PKT_SZ - ix))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900530 nbytes = sz;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530531 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900532 nbytes = DATA_PKT_SZ - ix;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900533
534 /**
535 * Read bytes
536 **/
Glen Leed4312b62015-12-21 14:18:31 +0900537 if (wilc_spi_rx(wilc, &b[ix], nbytes)) {
Glen Leeac1da162015-12-21 14:18:13 +0900538 dev_err(&spi->dev, "Failed data block read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900539 result = N_FAIL;
540 goto _error_;
541 }
542
543 /**
544 * Read Crc
545 **/
546 if (!g_spi.crc_off) {
Glen Leed4312b62015-12-21 14:18:31 +0900547 if (wilc_spi_rx(wilc, crc, 2)) {
Glen Leeac1da162015-12-21 14:18:13 +0900548 dev_err(&spi->dev, "Failed data block crc read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900549 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
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530563 if (sz <= DATA_PKT_SZ)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900564 nbytes = sz;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530565 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900566 nbytes = DATA_PKT_SZ;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900567
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 {
Glen Leed4312b62015-12-21 14:18:31 +0900578 if (wilc_spi_rx(wilc, &rsp, 1)) {
Glen Leeac1da162015-12-21 14:18:13 +0900579 dev_err(&spi->dev, "Failed data response read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900580 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 **/
Glen Leed4312b62015-12-21 14:18:31 +0900594 if (wilc_spi_rx(wilc, &b[ix], nbytes)) {
Glen Leeac1da162015-12-21 14:18:13 +0900595 dev_err(&spi->dev, "Failed data block read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900596 result = N_FAIL;
597 break;
598 }
599
600 /**
601 * Read Crc
602 **/
603 if (!g_spi.crc_off) {
Glen Leed4312b62015-12-21 14:18:31 +0900604 if (wilc_spi_rx(wilc, crc, 2)) {
Glen Leeac1da162015-12-21 14:18:13 +0900605 dev_err(&spi->dev, "Failed data block crc read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900606 result = N_FAIL;
607 break;
608 }
609 }
610
611 ix += nbytes;
612 sz -= nbytes;
613 }
614 }
615 }
616_error_:
617 return result;
618}
619
Glen Lee49dcd0d2015-11-18 15:11:26 +0900620static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900621{
Glen Leeac1da162015-12-21 14:18:13 +0900622 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900623 int ix, nbytes;
624 int result = 1;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900625 u8 cmd, order, crc[2] = {0};
626 /* u8 rsp; */
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900627
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;
Glen Leed4312b62015-12-21 14:18:31 +0900655 if (wilc_spi_tx(wilc, &cmd, 1)) {
Glen Leeac1da162015-12-21 14:18:13 +0900656 dev_err(&spi->dev,
657 "Failed data block cmd write, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900658 result = N_FAIL;
659 break;
660 }
661
662 /**
663 * Write data
664 **/
Glen Leed4312b62015-12-21 14:18:31 +0900665 if (wilc_spi_tx(wilc, &b[ix], nbytes)) {
Glen Leeac1da162015-12-21 14:18:13 +0900666 dev_err(&spi->dev,
667 "Failed data block write, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900668 result = N_FAIL;
669 break;
670 }
671
672 /**
673 * Write Crc
674 **/
675 if (!g_spi.crc_off) {
Glen Leed4312b62015-12-21 14:18:31 +0900676 if (wilc_spi_tx(wilc, crc, 2)) {
Roger H. Newell5142a142016-02-16 09:24:56 -0330677 dev_err(&spi->dev, "Failed data block crc write, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900678 result = N_FAIL;
679 break;
680 }
681 }
682
683 /**
684 * No need to wait for response
685 **/
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900686 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
Glen Lee49dcd0d2015-11-18 15:11:26 +0900700static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900701{
Glen Leeac1da162015-12-21 14:18:13 +0900702 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900703 int result;
704
Glen Lee9e6627a2015-12-21 14:18:08 +0900705 dat = cpu_to_le32(dat);
Glen Lee49dcd0d2015-11-18 15:11:26 +0900706 result = spi_cmd_complete(wilc, CMD_INTERNAL_WRITE, adr, (u8 *)&dat, 4,
707 0);
Roger H. Newelle0a30002016-02-16 09:25:42 -0330708 if (result != N_OK)
Glen Leeac1da162015-12-21 14:18:13 +0900709 dev_err(&spi->dev, "Failed internal write cmd...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900710
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900711 return result;
712}
713
Glen Lee49dcd0d2015-11-18 15:11:26 +0900714static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900715{
Glen Leeac1da162015-12-21 14:18:13 +0900716 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900717 int result;
718
Glen Lee49dcd0d2015-11-18 15:11:26 +0900719 result = spi_cmd_complete(wilc, CMD_INTERNAL_READ, adr, (u8 *)data, 4,
720 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900721 if (result != N_OK) {
Glen Leeac1da162015-12-21 14:18:13 +0900722 dev_err(&spi->dev, "Failed internal read cmd...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900723 return 0;
724 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900725
Glen Lee9e6627a2015-12-21 14:18:08 +0900726 *data = cpu_to_le32(*data);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900727
728 return 1;
729}
730
731/********************************************
732 *
733 * Spi interfaces
734 *
735 ********************************************/
736
Glen Lee49dcd0d2015-11-18 15:11:26 +0900737static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900738{
Glen Leeac1da162015-12-21 14:18:13 +0900739 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900740 int result = N_OK;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900741 u8 cmd = CMD_SINGLE_WRITE;
742 u8 clockless = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900743
Glen Lee9e6627a2015-12-21 14:18:08 +0900744 data = cpu_to_le32(data);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900745 if (addr < 0x30) {
746 /* Clockless register*/
747 cmd = CMD_INTERNAL_WRITE;
748 clockless = 1;
749 }
750
Glen Lee49dcd0d2015-11-18 15:11:26 +0900751 result = spi_cmd_complete(wilc, cmd, addr, (u8 *)&data, 4, clockless);
Roger H. Newelle0a30002016-02-16 09:25:42 -0330752 if (result != N_OK)
Glen Leeac1da162015-12-21 14:18:13 +0900753 dev_err(&spi->dev, "Failed cmd, write reg (%08x)...\n", addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900754
755 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900756}
757
Glen Leed4312b62015-12-21 14:18:31 +0900758static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900759{
Glen Leeac1da162015-12-21 14:18:13 +0900760 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900761 int result;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900762 u8 cmd = CMD_DMA_EXT_WRITE;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900763
764 /**
765 * has to be greated than 4
766 **/
767 if (size <= 4)
768 return 0;
769
Glen Lee49dcd0d2015-11-18 15:11:26 +0900770 result = spi_cmd_complete(wilc, cmd, addr, NULL, size, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900771 if (result != N_OK) {
Glen Leeac1da162015-12-21 14:18:13 +0900772 dev_err(&spi->dev,
773 "Failed cmd, write block (%08x)...\n", addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900774 return 0;
775 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900776
777 /**
778 * Data
779 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +0900780 result = spi_data_write(wilc, buf, size);
Roger H. Newelle0a30002016-02-16 09:25:42 -0330781 if (result != N_OK)
Glen Leeac1da162015-12-21 14:18:13 +0900782 dev_err(&spi->dev, "Failed block data write...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900783
784 return 1;
785}
786
Glen Lee49dcd0d2015-11-18 15:11:26 +0900787static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900788{
Glen Leeac1da162015-12-21 14:18:13 +0900789 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900790 int result = N_OK;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900791 u8 cmd = CMD_SINGLE_READ;
792 u8 clockless = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900793
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900794 if (addr < 0x30) {
Glen Leeac1da162015-12-21 14:18:13 +0900795 /* dev_err(&spi->dev, "***** read addr %d\n\n", addr); */
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900796 /* Clockless register*/
797 cmd = CMD_INTERNAL_READ;
798 clockless = 1;
799 }
800
Glen Lee49dcd0d2015-11-18 15:11:26 +0900801 result = spi_cmd_complete(wilc, cmd, addr, (u8 *)data, 4, clockless);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900802 if (result != N_OK) {
Glen Leeac1da162015-12-21 14:18:13 +0900803 dev_err(&spi->dev, "Failed cmd, read reg (%08x)...\n", addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900804 return 0;
805 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900806
Glen Lee9e6627a2015-12-21 14:18:08 +0900807 *data = cpu_to_le32(*data);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900808
809 return 1;
810}
811
Glen Leed4312b62015-12-21 14:18:31 +0900812static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900813{
Glen Leeac1da162015-12-21 14:18:13 +0900814 struct spi_device *spi = to_spi_device(wilc->dev);
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900815 u8 cmd = CMD_DMA_EXT_READ;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900816 int result;
817
818 if (size <= 4)
819 return 0;
820
Glen Lee49dcd0d2015-11-18 15:11:26 +0900821 result = spi_cmd_complete(wilc, cmd, addr, buf, size, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900822 if (result != N_OK) {
Glen Leeac1da162015-12-21 14:18:13 +0900823 dev_err(&spi->dev, "Failed cmd, read block (%08x)...\n", addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900824 return 0;
825 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900826
827 return 1;
828}
829
830/********************************************
831 *
832 * Bus interfaces
833 *
834 ********************************************/
835
Glen Lee49dcd0d2015-11-18 15:11:26 +0900836static int _wilc_spi_deinit(struct wilc *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900837{
838 /**
839 * TODO:
840 **/
841 return 1;
842}
843
Glen Lee5397cbc2016-01-25 16:35:09 +0900844static int wilc_spi_init(struct wilc *wilc, bool resume)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900845{
Glen Leeac1da162015-12-21 14:18:13 +0900846 struct spi_device *spi = to_spi_device(wilc->dev);
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900847 u32 reg;
848 u32 chipid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900849
850 static int isinit;
851
852 if (isinit) {
853
Glen Lee49dcd0d2015-11-18 15:11:26 +0900854 if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) {
Glen Leeac1da162015-12-21 14:18:13 +0900855 dev_err(&spi->dev, "Fail cmd read chip id...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900856 return 0;
857 }
858 return 1;
859 }
860
Bhumika Goyal6a707a92016-02-21 03:12:11 +0530861 memset(&g_spi, 0, sizeof(struct wilc_spi));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900862
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900863 /**
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. */
Glen Lee49dcd0d2015-11-18 15:11:26 +0900870 if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, &reg)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900871 /* 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;
Glen Leeac1da162015-12-21 14:18:13 +0900874 dev_err(&spi->dev, "Failed internal read protocol with CRC on, retyring with CRC off...\n");
Glen Lee49dcd0d2015-11-18 15:11:26 +0900875 if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, &reg)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900876 /* Reaad failed with both CRC on and off, something went bad */
Glen Leeac1da162015-12-21 14:18:13 +0900877 dev_err(&spi->dev,
878 "Failed internal read protocol...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900879 return 0;
880 }
881 }
882 if (g_spi.crc_off == 0) {
883 reg &= ~0xc; /* disable crc checking */
884 reg &= ~0x70;
885 reg |= (0x5 << 4);
Glen Lee49dcd0d2015-11-18 15:11:26 +0900886 if (!spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg)) {
Glen Leeac1da162015-12-21 14:18:13 +0900887 dev_err(&spi->dev, "[wilc spi %d]: Failed internal write protocol reg...\n", __LINE__);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900888 return 0;
889 }
890 g_spi.crc_off = 1;
891 }
892
893
894 /**
895 * make sure can read back chip id correctly
896 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +0900897 if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) {
Glen Leeac1da162015-12-21 14:18:13 +0900898 dev_err(&spi->dev, "Fail cmd read chip id...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900899 return 0;
900 }
Glen Leeac1da162015-12-21 14:18:13 +0900901 /* dev_err(&spi->dev, "chipid (%08x)\n", chipid); */
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900902
903 g_spi.has_thrpt_enh = 1;
904
905 isinit = 1;
906
907 return 1;
908}
909
Glen Lee49dcd0d2015-11-18 15:11:26 +0900910static int wilc_spi_read_size(struct wilc *wilc, u32 *size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900911{
Glen Leeac1da162015-12-21 14:18:13 +0900912 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900913 int ret;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900914
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900915 if (g_spi.has_thrpt_enh) {
Glen Lee49dcd0d2015-11-18 15:11:26 +0900916 ret = spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE,
917 size);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900918 *size = *size & IRQ_DMA_WD_CNT_MASK;
919 } else {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900920 u32 tmp;
921 u32 byte_cnt;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900922
Glen Lee49dcd0d2015-11-18 15:11:26 +0900923 ret = wilc_spi_read_reg(wilc, WILC_VMM_TO_HOST_SIZE,
924 &byte_cnt);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900925 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +0900926 dev_err(&spi->dev,
927 "Failed read WILC_VMM_TO_HOST_SIZE ...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900928 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
Glen Lee49dcd0d2015-11-18 15:11:26 +0900942static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900943{
Glen Leeac1da162015-12-21 14:18:13 +0900944 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900945 int ret;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900946
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900947 if (g_spi.has_thrpt_enh) {
Glen Lee49dcd0d2015-11-18 15:11:26 +0900948 ret = spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE,
949 int_status);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900950 } else {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900951 u32 tmp;
952 u32 byte_cnt;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900953
Glen Lee49dcd0d2015-11-18 15:11:26 +0900954 ret = wilc_spi_read_reg(wilc, WILC_VMM_TO_HOST_SIZE,
955 &byte_cnt);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900956 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +0900957 dev_err(&spi->dev,
958 "Failed read WILC_VMM_TO_HOST_SIZE ...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900959 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 {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900968 u32 irq_flags;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900969
970 happended = 0;
971
Glen Lee49dcd0d2015-11-18 15:11:26 +0900972 wilc_spi_read_reg(wilc, 0x1a90, &irq_flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900973 tmp |= ((irq_flags >> 27) << IRG_FLAGS_OFFSET);
974
975 if (g_spi.nint > 5) {
Glen Lee49dcd0d2015-11-18 15:11:26 +0900976 wilc_spi_read_reg(wilc, 0x1a94,
977 &irq_flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900978 tmp |= (((irq_flags >> 0) & 0x7) << (IRG_FLAGS_OFFSET + 5));
979 }
980
981 {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900982 u32 unkmown_mask;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900983
984 unkmown_mask = ~((1ul << g_spi.nint) - 1);
985
986 if ((tmp >> IRG_FLAGS_OFFSET) & unkmown_mask) {
Glen Leeac1da162015-12-21 14:18:13 +0900987 dev_err(&spi->dev, "Unexpected interrupt (2): j=%d, tmp=%x, mask=%x\n", j, tmp, unkmown_mask);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900988 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
Glen Lee49dcd0d2015-11-18 15:11:26 +09001003static int wilc_spi_clear_int_ext(struct wilc *wilc, u32 val)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001004{
Glen Leeac1da162015-12-21 14:18:13 +09001005 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001006 int ret;
1007
1008 if (g_spi.has_thrpt_enh) {
Glen Lee49dcd0d2015-11-18 15:11:26 +09001009 ret = spi_internal_write(wilc, 0xe844 - WILC_SPI_REG_BASE,
1010 val);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001011 } else {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001012 u32 flags;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +09001013
Anish Bhattffda2032015-09-29 12:15:49 -07001014 flags = val & (BIT(MAX_NUM_INT) - 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001015 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)
Glen Lee49dcd0d2015-11-18 15:11:26 +09001022 ret = wilc_spi_write_reg(wilc, 0x10c8 + i * 4, 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001023 if (!ret)
1024 break;
1025 flags >>= 1;
1026 }
1027 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001028 dev_err(&spi->dev,
1029 "Failed wilc_spi_write_reg, set reg %x ...\n",
1030 0x10c8 + i * 4);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001031 goto _fail_;
1032 }
1033 for (i = g_spi.nint; i < MAX_NUM_INT; i++) {
1034 if (flags & 1)
Glen Leeac1da162015-12-21 14:18:13 +09001035 dev_err(&spi->dev,
1036 "Unexpected interrupt cleared %d...\n",
1037 i);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001038 flags >>= 1;
1039 }
1040 }
1041
1042 {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001043 u32 tbl_ctl;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001044
1045 tbl_ctl = 0;
1046 /* select VMM table 0 */
1047 if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0)
Anish Bhattffda2032015-09-29 12:15:49 -07001048 tbl_ctl |= BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001049 /* select VMM table 1 */
1050 if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1)
Anish Bhattffda2032015-09-29 12:15:49 -07001051 tbl_ctl |= BIT(1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001052
Glen Lee49dcd0d2015-11-18 15:11:26 +09001053 ret = wilc_spi_write_reg(wilc, WILC_VMM_TBL_CTL,
1054 tbl_ctl);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001055 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001056 dev_err(&spi->dev,
1057 "fail write reg vmm_tbl_ctl...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001058 goto _fail_;
1059 }
1060
1061 if ((val & EN_VMM) == EN_VMM) {
1062 /**
1063 * enable vmm transfer.
1064 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +09001065 ret = wilc_spi_write_reg(wilc,
1066 WILC_VMM_CORE_CTL, 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001067 if (!ret) {
Roger H. Newell5142a142016-02-16 09:24:56 -03301068 dev_err(&spi->dev, "fail write reg vmm_core_ctl...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001069 goto _fail_;
1070 }
1071 }
1072 }
1073 }
1074_fail_:
1075 return ret;
1076}
1077
Glen Lee49dcd0d2015-11-18 15:11:26 +09001078static int wilc_spi_sync_ext(struct wilc *wilc, int nint)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001079{
Glen Leeac1da162015-12-21 14:18:13 +09001080 struct spi_device *spi = to_spi_device(wilc->dev);
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001081 u32 reg;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001082 int ret, i;
1083
1084 if (nint > MAX_NUM_INT) {
Colin Ian King95b8cb82016-06-23 14:14:07 +01001085 dev_err(&spi->dev, "Too many interrupts (%d)...\n", nint);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001086 return 0;
1087 }
1088
1089 g_spi.nint = nint;
1090
1091 /**
1092 * interrupt pin mux select
1093 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +09001094 ret = wilc_spi_read_reg(wilc, WILC_PIN_MUX_0, &reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001095 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001096 dev_err(&spi->dev, "Failed read reg (%08x)...\n",
1097 WILC_PIN_MUX_0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001098 return 0;
1099 }
Anish Bhattffda2032015-09-29 12:15:49 -07001100 reg |= BIT(8);
Glen Lee49dcd0d2015-11-18 15:11:26 +09001101 ret = wilc_spi_write_reg(wilc, WILC_PIN_MUX_0, reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001102 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001103 dev_err(&spi->dev, "Failed write reg (%08x)...\n",
1104 WILC_PIN_MUX_0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001105 return 0;
1106 }
1107
1108 /**
1109 * interrupt enable
1110 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +09001111 ret = wilc_spi_read_reg(wilc, WILC_INTR_ENABLE, &reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001112 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001113 dev_err(&spi->dev, "Failed read reg (%08x)...\n",
1114 WILC_INTR_ENABLE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001115 return 0;
1116 }
1117
Roger H. Newelle0a30002016-02-16 09:25:42 -03301118 for (i = 0; (i < 5) && (nint > 0); i++, nint--)
Anish Bhattffda2032015-09-29 12:15:49 -07001119 reg |= (BIT((27 + i)));
Roger H. Newelle0a30002016-02-16 09:25:42 -03301120
Glen Lee49dcd0d2015-11-18 15:11:26 +09001121 ret = wilc_spi_write_reg(wilc, WILC_INTR_ENABLE, reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001122 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001123 dev_err(&spi->dev, "Failed write reg (%08x)...\n",
1124 WILC_INTR_ENABLE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001125 return 0;
1126 }
1127 if (nint) {
Glen Lee49dcd0d2015-11-18 15:11:26 +09001128 ret = wilc_spi_read_reg(wilc, WILC_INTR2_ENABLE, &reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001129 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001130 dev_err(&spi->dev, "Failed read reg (%08x)...\n",
1131 WILC_INTR2_ENABLE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001132 return 0;
1133 }
1134
Roger H. Newelle0a30002016-02-16 09:25:42 -03301135 for (i = 0; (i < 3) && (nint > 0); i++, nint--)
Anish Bhattffda2032015-09-29 12:15:49 -07001136 reg |= BIT(i);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001137
Glen Lee49dcd0d2015-11-18 15:11:26 +09001138 ret = wilc_spi_read_reg(wilc, WILC_INTR2_ENABLE, &reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001139 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001140 dev_err(&spi->dev, "Failed write reg (%08x)...\n",
1141 WILC_INTR2_ENABLE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001142 return 0;
1143 }
1144 }
1145
1146 return 1;
1147}
1148/********************************************
1149 *
1150 * Global spi HIF function table
1151 *
1152 ********************************************/
Arnd Bergmann7d37a4a2015-11-16 15:05:05 +01001153const struct wilc_hif_func wilc_hif_spi = {
Glen Lee2769d942015-12-21 14:18:32 +09001154 .hif_init = wilc_spi_init,
Arnd Bergmann7d37a4a2015-11-16 15:05:05 +01001155 .hif_deinit = _wilc_spi_deinit,
1156 .hif_read_reg = wilc_spi_read_reg,
1157 .hif_write_reg = wilc_spi_write_reg,
Glen Leed4312b62015-12-21 14:18:31 +09001158 .hif_block_rx = wilc_spi_read,
1159 .hif_block_tx = wilc_spi_write,
Arnd Bergmann7d37a4a2015-11-16 15:05:05 +01001160 .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,
Glen Leed4312b62015-12-21 14:18:31 +09001163 .hif_block_tx_ext = wilc_spi_write,
1164 .hif_block_rx_ext = wilc_spi_read,
Arnd Bergmann7d37a4a2015-11-16 15:05:05 +01001165 .hif_sync_ext = wilc_spi_sync_ext,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001166};