blob: f08cf6d9e1aff1a6d63c4db380141396ad1a61f6 [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));
Rehas Sachdevad37843d2016-09-20 13:18:40 +0530413 return N_FAIL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900414 }
415 /* zero spi write buffers. */
Roger H. Newelle0a30002016-02-16 09:25:42 -0330416 for (wix = len; wix < len2; wix++)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900417 wb[wix] = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900418 rix = len;
419
Glen Leed4312b62015-12-21 14:18:31 +0900420 if (wilc_spi_tx_rx(wilc, wb, rb, len2)) {
Glen Leeac1da162015-12-21 14:18:13 +0900421 dev_err(&spi->dev, "Failed cmd write, bus error...\n");
Namrata A Shettar8244d262016-09-30 19:14:54 +0530422 return N_FAIL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900423 }
424
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900425 /**
426 * Command/Control response
427 **/
428 if ((cmd == CMD_RESET) ||
429 (cmd == CMD_TERMINATE) ||
430 (cmd == CMD_REPEAT)) {
431 rix++; /* skip 1 byte */
432 }
433
434 /* do { */
435 rsp = rb[rix++];
436 /* if(rsp == cmd) break; */
437 /* } while(&rptr[1] <= &rb[len2]); */
438
439 if (rsp != cmd) {
Anchal Jain8779bf82016-02-21 22:19:05 +0530440 dev_err(&spi->dev,
441 "Failed cmd response, cmd (%02x), resp (%02x)\n",
442 cmd, rsp);
Namrata A Shettar8244d262016-09-30 19:14:54 +0530443 return N_FAIL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900444 }
445
446 /**
447 * State response
448 **/
449 rsp = rb[rix++];
450 if (rsp != 0x00) {
Glen Leeac1da162015-12-21 14:18:13 +0900451 dev_err(&spi->dev, "Failed cmd state response state (%02x)\n",
452 rsp);
Namrata A Shettar8244d262016-09-30 19:14:54 +0530453 return N_FAIL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900454 }
455
456 if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)
457 || (cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) {
458 int retry;
Chaehyun Limec53adf2015-09-15 14:06:15 +0900459 /* u16 crc1, crc2; */
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900460 u8 crc[2];
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900461 /**
462 * Data Respnose header
463 **/
464 retry = 100;
465 do {
466 /* ensure there is room in buffer later to read data and crc */
467 if (rix < len2) {
468 rsp = rb[rix++];
469 } else {
470 retry = 0;
471 break;
472 }
473 if (((rsp >> 4) & 0xf) == 0xf)
474 break;
475 } while (retry--);
476
477 if (retry <= 0) {
Glen Leeac1da162015-12-21 14:18:13 +0900478 dev_err(&spi->dev,
479 "Error, data read response (%02x)\n", rsp);
Namrata A Shettar8244d262016-09-30 19:14:54 +0530480 return N_RESET;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900481 }
482
483 if ((cmd == CMD_INTERNAL_READ) || (cmd == CMD_SINGLE_READ)) {
484 /**
485 * Read bytes
486 **/
487 if ((rix + 3) < len2) {
488 b[0] = rb[rix++];
489 b[1] = rb[rix++];
490 b[2] = rb[rix++];
491 b[3] = rb[rix++];
492 } else {
Glen Leeac1da162015-12-21 14:18:13 +0900493 dev_err(&spi->dev,
494 "buffer overrun when reading data.\n");
Namrata A Shettar8244d262016-09-30 19:14:54 +0530495 return N_FAIL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900496 }
497
498 if (!g_spi.crc_off) {
499 /**
500 * Read Crc
501 **/
502 if ((rix + 1) < len2) {
503 crc[0] = rb[rix++];
504 crc[1] = rb[rix++];
505 } else {
Roger H. Newell5142a142016-02-16 09:24:56 -0330506 dev_err(&spi->dev, "buffer overrun when reading crc.\n");
Namrata A Shettar8244d262016-09-30 19:14:54 +0530507 return N_FAIL;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900508 }
509 }
510 } else if ((cmd == CMD_DMA_READ) || (cmd == CMD_DMA_EXT_READ)) {
511 int ix;
512
513 /* some data may be read in response to dummy bytes. */
Roger H. Newelle0a30002016-02-16 09:25:42 -0330514 for (ix = 0; (rix < len2) && (ix < sz); )
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900515 b[ix++] = rb[rix++];
Chaehyun Lim61500fb2015-06-18 14:46:05 +0900516
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900517 sz -= ix;
518
519 if (sz > 0) {
520 int nbytes;
521
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530522 if (sz <= (DATA_PKT_SZ - ix))
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900523 nbytes = sz;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530524 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900525 nbytes = DATA_PKT_SZ - ix;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900526
527 /**
528 * Read bytes
529 **/
Glen Leed4312b62015-12-21 14:18:31 +0900530 if (wilc_spi_rx(wilc, &b[ix], nbytes)) {
Glen Leeac1da162015-12-21 14:18:13 +0900531 dev_err(&spi->dev, "Failed data block read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900532 result = N_FAIL;
533 goto _error_;
534 }
535
536 /**
537 * Read Crc
538 **/
539 if (!g_spi.crc_off) {
Glen Leed4312b62015-12-21 14:18:31 +0900540 if (wilc_spi_rx(wilc, crc, 2)) {
Glen Leeac1da162015-12-21 14:18:13 +0900541 dev_err(&spi->dev, "Failed data block crc read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900542 result = N_FAIL;
543 goto _error_;
544 }
545 }
546
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900547 ix += nbytes;
548 sz -= nbytes;
549 }
550
551 /* if any data in left unread, then read the rest using normal DMA code.*/
552 while (sz > 0) {
553 int nbytes;
554
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530555 if (sz <= DATA_PKT_SZ)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900556 nbytes = sz;
Chandra S Gorentla78174ad2015-08-08 17:41:36 +0530557 else
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900558 nbytes = DATA_PKT_SZ;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900559
560 /**
561 * read data response only on the next DMA cycles not
562 * the first DMA since data response header is already
563 * handled above for the first DMA.
564 **/
565 /**
566 * Data Respnose header
567 **/
568 retry = 10;
569 do {
Glen Leed4312b62015-12-21 14:18:31 +0900570 if (wilc_spi_rx(wilc, &rsp, 1)) {
Glen Leeac1da162015-12-21 14:18:13 +0900571 dev_err(&spi->dev, "Failed data response read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900572 result = N_FAIL;
573 break;
574 }
575 if (((rsp >> 4) & 0xf) == 0xf)
576 break;
577 } while (retry--);
578
579 if (result == N_FAIL)
580 break;
581
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900582 /**
583 * Read bytes
584 **/
Glen Leed4312b62015-12-21 14:18:31 +0900585 if (wilc_spi_rx(wilc, &b[ix], nbytes)) {
Glen Leeac1da162015-12-21 14:18:13 +0900586 dev_err(&spi->dev, "Failed data block read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900587 result = N_FAIL;
588 break;
589 }
590
591 /**
592 * Read Crc
593 **/
594 if (!g_spi.crc_off) {
Glen Leed4312b62015-12-21 14:18:31 +0900595 if (wilc_spi_rx(wilc, crc, 2)) {
Glen Leeac1da162015-12-21 14:18:13 +0900596 dev_err(&spi->dev, "Failed data block crc read, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900597 result = N_FAIL;
598 break;
599 }
600 }
601
602 ix += nbytes;
603 sz -= nbytes;
604 }
605 }
606 }
607_error_:
608 return result;
609}
610
Glen Lee49dcd0d2015-11-18 15:11:26 +0900611static int spi_data_write(struct wilc *wilc, u8 *b, u32 sz)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900612{
Glen Leeac1da162015-12-21 14:18:13 +0900613 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900614 int ix, nbytes;
615 int result = 1;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900616 u8 cmd, order, crc[2] = {0};
617 /* u8 rsp; */
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900618
619 /**
620 * Data
621 **/
622 ix = 0;
623 do {
624 if (sz <= DATA_PKT_SZ)
625 nbytes = sz;
626 else
627 nbytes = DATA_PKT_SZ;
628
629 /**
630 * Write command
631 **/
632 cmd = 0xf0;
633 if (ix == 0) {
634 if (sz <= DATA_PKT_SZ)
635
636 order = 0x3;
637 else
638 order = 0x1;
639 } else {
640 if (sz <= DATA_PKT_SZ)
641 order = 0x3;
642 else
643 order = 0x2;
644 }
645 cmd |= order;
Glen Leed4312b62015-12-21 14:18:31 +0900646 if (wilc_spi_tx(wilc, &cmd, 1)) {
Glen Leeac1da162015-12-21 14:18:13 +0900647 dev_err(&spi->dev,
648 "Failed data block cmd write, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900649 result = N_FAIL;
650 break;
651 }
652
653 /**
654 * Write data
655 **/
Glen Leed4312b62015-12-21 14:18:31 +0900656 if (wilc_spi_tx(wilc, &b[ix], nbytes)) {
Glen Leeac1da162015-12-21 14:18:13 +0900657 dev_err(&spi->dev,
658 "Failed data block write, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900659 result = N_FAIL;
660 break;
661 }
662
663 /**
664 * Write Crc
665 **/
666 if (!g_spi.crc_off) {
Glen Leed4312b62015-12-21 14:18:31 +0900667 if (wilc_spi_tx(wilc, crc, 2)) {
Roger H. Newell5142a142016-02-16 09:24:56 -0330668 dev_err(&spi->dev, "Failed data block crc write, bus error...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900669 result = N_FAIL;
670 break;
671 }
672 }
673
674 /**
675 * No need to wait for response
676 **/
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900677 ix += nbytes;
678 sz -= nbytes;
679 } while (sz);
680
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900681 return result;
682}
683
684/********************************************
685 *
686 * Spi Internal Read/Write Function
687 *
688 ********************************************/
689
Glen Lee49dcd0d2015-11-18 15:11:26 +0900690static int spi_internal_write(struct wilc *wilc, u32 adr, u32 dat)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900691{
Glen Leeac1da162015-12-21 14:18:13 +0900692 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900693 int result;
694
Glen Lee9e6627a2015-12-21 14:18:08 +0900695 dat = cpu_to_le32(dat);
Glen Lee49dcd0d2015-11-18 15:11:26 +0900696 result = spi_cmd_complete(wilc, CMD_INTERNAL_WRITE, adr, (u8 *)&dat, 4,
697 0);
Roger H. Newelle0a30002016-02-16 09:25:42 -0330698 if (result != N_OK)
Glen Leeac1da162015-12-21 14:18:13 +0900699 dev_err(&spi->dev, "Failed internal write cmd...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900700
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900701 return result;
702}
703
Glen Lee49dcd0d2015-11-18 15:11:26 +0900704static int spi_internal_read(struct wilc *wilc, u32 adr, u32 *data)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900705{
Glen Leeac1da162015-12-21 14:18:13 +0900706 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900707 int result;
708
Glen Lee49dcd0d2015-11-18 15:11:26 +0900709 result = spi_cmd_complete(wilc, CMD_INTERNAL_READ, adr, (u8 *)data, 4,
710 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900711 if (result != N_OK) {
Glen Leeac1da162015-12-21 14:18:13 +0900712 dev_err(&spi->dev, "Failed internal read cmd...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900713 return 0;
714 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900715
Glen Lee9e6627a2015-12-21 14:18:08 +0900716 *data = cpu_to_le32(*data);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900717
718 return 1;
719}
720
721/********************************************
722 *
723 * Spi interfaces
724 *
725 ********************************************/
726
Glen Lee49dcd0d2015-11-18 15:11:26 +0900727static int wilc_spi_write_reg(struct wilc *wilc, u32 addr, u32 data)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900728{
Glen Leeac1da162015-12-21 14:18:13 +0900729 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900730 int result = N_OK;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900731 u8 cmd = CMD_SINGLE_WRITE;
732 u8 clockless = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900733
Glen Lee9e6627a2015-12-21 14:18:08 +0900734 data = cpu_to_le32(data);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900735 if (addr < 0x30) {
736 /* Clockless register*/
737 cmd = CMD_INTERNAL_WRITE;
738 clockless = 1;
739 }
740
Glen Lee49dcd0d2015-11-18 15:11:26 +0900741 result = spi_cmd_complete(wilc, cmd, addr, (u8 *)&data, 4, clockless);
Roger H. Newelle0a30002016-02-16 09:25:42 -0330742 if (result != N_OK)
Glen Leeac1da162015-12-21 14:18:13 +0900743 dev_err(&spi->dev, "Failed cmd, write reg (%08x)...\n", addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900744
745 return result;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900746}
747
Glen Leed4312b62015-12-21 14:18:31 +0900748static int wilc_spi_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900749{
Glen Leeac1da162015-12-21 14:18:13 +0900750 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900751 int result;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900752 u8 cmd = CMD_DMA_EXT_WRITE;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900753
754 /**
755 * has to be greated than 4
756 **/
757 if (size <= 4)
758 return 0;
759
Glen Lee49dcd0d2015-11-18 15:11:26 +0900760 result = spi_cmd_complete(wilc, cmd, addr, NULL, size, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900761 if (result != N_OK) {
Glen Leeac1da162015-12-21 14:18:13 +0900762 dev_err(&spi->dev,
763 "Failed cmd, write block (%08x)...\n", addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900764 return 0;
765 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900766
767 /**
768 * Data
769 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +0900770 result = spi_data_write(wilc, buf, size);
Roger H. Newelle0a30002016-02-16 09:25:42 -0330771 if (result != N_OK)
Glen Leeac1da162015-12-21 14:18:13 +0900772 dev_err(&spi->dev, "Failed block data write...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900773
774 return 1;
775}
776
Glen Lee49dcd0d2015-11-18 15:11:26 +0900777static int wilc_spi_read_reg(struct wilc *wilc, u32 addr, u32 *data)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900778{
Glen Leeac1da162015-12-21 14:18:13 +0900779 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900780 int result = N_OK;
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900781 u8 cmd = CMD_SINGLE_READ;
782 u8 clockless = 0;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900783
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900784 if (addr < 0x30) {
Glen Leeac1da162015-12-21 14:18:13 +0900785 /* dev_err(&spi->dev, "***** read addr %d\n\n", addr); */
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900786 /* Clockless register*/
787 cmd = CMD_INTERNAL_READ;
788 clockless = 1;
789 }
790
Glen Lee49dcd0d2015-11-18 15:11:26 +0900791 result = spi_cmd_complete(wilc, cmd, addr, (u8 *)data, 4, clockless);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900792 if (result != N_OK) {
Glen Leeac1da162015-12-21 14:18:13 +0900793 dev_err(&spi->dev, "Failed cmd, read reg (%08x)...\n", addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900794 return 0;
795 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900796
Glen Lee9e6627a2015-12-21 14:18:08 +0900797 *data = cpu_to_le32(*data);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900798
799 return 1;
800}
801
Glen Leed4312b62015-12-21 14:18:31 +0900802static int wilc_spi_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900803{
Glen Leeac1da162015-12-21 14:18:13 +0900804 struct spi_device *spi = to_spi_device(wilc->dev);
Chaehyun Lim51e825f2015-09-15 14:06:14 +0900805 u8 cmd = CMD_DMA_EXT_READ;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900806 int result;
807
808 if (size <= 4)
809 return 0;
810
Glen Lee49dcd0d2015-11-18 15:11:26 +0900811 result = spi_cmd_complete(wilc, cmd, addr, buf, size, 0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900812 if (result != N_OK) {
Glen Leeac1da162015-12-21 14:18:13 +0900813 dev_err(&spi->dev, "Failed cmd, read block (%08x)...\n", addr);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900814 return 0;
815 }
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900816
817 return 1;
818}
819
820/********************************************
821 *
822 * Bus interfaces
823 *
824 ********************************************/
825
Glen Lee49dcd0d2015-11-18 15:11:26 +0900826static int _wilc_spi_deinit(struct wilc *wilc)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900827{
828 /**
829 * TODO:
830 **/
831 return 1;
832}
833
Glen Lee5397cbc2016-01-25 16:35:09 +0900834static int wilc_spi_init(struct wilc *wilc, bool resume)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900835{
Glen Leeac1da162015-12-21 14:18:13 +0900836 struct spi_device *spi = to_spi_device(wilc->dev);
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900837 u32 reg;
838 u32 chipid;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900839
840 static int isinit;
841
842 if (isinit) {
Glen Lee49dcd0d2015-11-18 15:11:26 +0900843 if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) {
Glen Leeac1da162015-12-21 14:18:13 +0900844 dev_err(&spi->dev, "Fail cmd read chip id...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900845 return 0;
846 }
847 return 1;
848 }
849
Bhumika Goyal6a707a92016-02-21 03:12:11 +0530850 memset(&g_spi, 0, sizeof(struct wilc_spi));
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900851
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900852 /**
853 * configure protocol
854 **/
855 g_spi.crc_off = 0;
856
857 /* TODO: We can remove the CRC trials if there is a definite way to reset */
858 /* the SPI to it's initial value. */
Glen Lee49dcd0d2015-11-18 15:11:26 +0900859 if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, &reg)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900860 /* Read failed. Try with CRC off. This might happen when module
861 * is removed but chip isn't reset*/
862 g_spi.crc_off = 1;
Colin Ian King2218b8f2016-08-28 12:28:41 +0100863 dev_err(&spi->dev, "Failed internal read protocol with CRC on, retrying with CRC off...\n");
Glen Lee49dcd0d2015-11-18 15:11:26 +0900864 if (!spi_internal_read(wilc, WILC_SPI_PROTOCOL_OFFSET, &reg)) {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900865 /* Reaad failed with both CRC on and off, something went bad */
Glen Leeac1da162015-12-21 14:18:13 +0900866 dev_err(&spi->dev,
867 "Failed internal read protocol...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900868 return 0;
869 }
870 }
871 if (g_spi.crc_off == 0) {
872 reg &= ~0xc; /* disable crc checking */
873 reg &= ~0x70;
874 reg |= (0x5 << 4);
Glen Lee49dcd0d2015-11-18 15:11:26 +0900875 if (!spi_internal_write(wilc, WILC_SPI_PROTOCOL_OFFSET, reg)) {
Glen Leeac1da162015-12-21 14:18:13 +0900876 dev_err(&spi->dev, "[wilc spi %d]: Failed internal write protocol reg...\n", __LINE__);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900877 return 0;
878 }
879 g_spi.crc_off = 1;
880 }
881
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900882 /**
883 * make sure can read back chip id correctly
884 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +0900885 if (!wilc_spi_read_reg(wilc, 0x1000, &chipid)) {
Glen Leeac1da162015-12-21 14:18:13 +0900886 dev_err(&spi->dev, "Fail cmd read chip id...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900887 return 0;
888 }
Glen Leeac1da162015-12-21 14:18:13 +0900889 /* dev_err(&spi->dev, "chipid (%08x)\n", chipid); */
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900890
891 g_spi.has_thrpt_enh = 1;
892
893 isinit = 1;
894
895 return 1;
896}
897
Glen Lee49dcd0d2015-11-18 15:11:26 +0900898static int wilc_spi_read_size(struct wilc *wilc, u32 *size)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900899{
Glen Leeac1da162015-12-21 14:18:13 +0900900 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900901 int ret;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900902
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900903 if (g_spi.has_thrpt_enh) {
Glen Lee49dcd0d2015-11-18 15:11:26 +0900904 ret = spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE,
905 size);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900906 *size = *size & IRQ_DMA_WD_CNT_MASK;
907 } else {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900908 u32 tmp;
909 u32 byte_cnt;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900910
Glen Lee49dcd0d2015-11-18 15:11:26 +0900911 ret = wilc_spi_read_reg(wilc, WILC_VMM_TO_HOST_SIZE,
912 &byte_cnt);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900913 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +0900914 dev_err(&spi->dev,
915 "Failed read WILC_VMM_TO_HOST_SIZE ...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900916 goto _fail_;
917 }
918 tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK;
919 *size = tmp;
920 }
921
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900922_fail_:
923 return ret;
924}
925
Glen Lee49dcd0d2015-11-18 15:11:26 +0900926static int wilc_spi_read_int(struct wilc *wilc, u32 *int_status)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900927{
Glen Leeac1da162015-12-21 14:18:13 +0900928 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900929 int ret;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900930
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900931 if (g_spi.has_thrpt_enh) {
Glen Lee49dcd0d2015-11-18 15:11:26 +0900932 ret = spi_internal_read(wilc, 0xe840 - WILC_SPI_REG_BASE,
933 int_status);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900934 } else {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900935 u32 tmp;
936 u32 byte_cnt;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900937
Glen Lee49dcd0d2015-11-18 15:11:26 +0900938 ret = wilc_spi_read_reg(wilc, WILC_VMM_TO_HOST_SIZE,
939 &byte_cnt);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900940 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +0900941 dev_err(&spi->dev,
942 "Failed read WILC_VMM_TO_HOST_SIZE ...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900943 goto _fail_;
944 }
945 tmp = (byte_cnt >> 2) & IRQ_DMA_WD_CNT_MASK;
946
947 {
948 int happended, j;
949
950 j = 0;
951 do {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900952 u32 irq_flags;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900953
954 happended = 0;
955
Glen Lee49dcd0d2015-11-18 15:11:26 +0900956 wilc_spi_read_reg(wilc, 0x1a90, &irq_flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900957 tmp |= ((irq_flags >> 27) << IRG_FLAGS_OFFSET);
958
959 if (g_spi.nint > 5) {
Glen Lee49dcd0d2015-11-18 15:11:26 +0900960 wilc_spi_read_reg(wilc, 0x1a94,
961 &irq_flags);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900962 tmp |= (((irq_flags >> 0) & 0x7) << (IRG_FLAGS_OFFSET + 5));
963 }
964
965 {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900966 u32 unkmown_mask;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900967
968 unkmown_mask = ~((1ul << g_spi.nint) - 1);
969
970 if ((tmp >> IRG_FLAGS_OFFSET) & unkmown_mask) {
Glen Leeac1da162015-12-21 14:18:13 +0900971 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 +0900972 happended = 1;
973 }
974 }
975 j++;
976 } while (happended);
977 }
978
979 *int_status = tmp;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900980 }
981
982_fail_:
983 return ret;
984}
985
Glen Lee49dcd0d2015-11-18 15:11:26 +0900986static int wilc_spi_clear_int_ext(struct wilc *wilc, u32 val)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900987{
Glen Leeac1da162015-12-21 14:18:13 +0900988 struct spi_device *spi = to_spi_device(wilc->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900989 int ret;
990
991 if (g_spi.has_thrpt_enh) {
Glen Lee49dcd0d2015-11-18 15:11:26 +0900992 ret = spi_internal_write(wilc, 0xe844 - WILC_SPI_REG_BASE,
993 val);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900994 } else {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +0900995 u32 flags;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900996
Anish Bhattffda2032015-09-29 12:15:49 -0700997 flags = val & (BIT(MAX_NUM_INT) - 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900998 if (flags) {
999 int i;
1000
1001 ret = 1;
1002 for (i = 0; i < g_spi.nint; i++) {
1003 /* No matter what you write 1 or 0, it will clear interrupt. */
1004 if (flags & 1)
Glen Lee49dcd0d2015-11-18 15:11:26 +09001005 ret = wilc_spi_write_reg(wilc, 0x10c8 + i * 4, 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001006 if (!ret)
1007 break;
1008 flags >>= 1;
1009 }
1010 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001011 dev_err(&spi->dev,
1012 "Failed wilc_spi_write_reg, set reg %x ...\n",
1013 0x10c8 + i * 4);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001014 goto _fail_;
1015 }
1016 for (i = g_spi.nint; i < MAX_NUM_INT; i++) {
1017 if (flags & 1)
Glen Leeac1da162015-12-21 14:18:13 +09001018 dev_err(&spi->dev,
1019 "Unexpected interrupt cleared %d...\n",
1020 i);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001021 flags >>= 1;
1022 }
1023 }
1024
1025 {
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001026 u32 tbl_ctl;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001027
1028 tbl_ctl = 0;
1029 /* select VMM table 0 */
1030 if ((val & SEL_VMM_TBL0) == SEL_VMM_TBL0)
Anish Bhattffda2032015-09-29 12:15:49 -07001031 tbl_ctl |= BIT(0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001032 /* select VMM table 1 */
1033 if ((val & SEL_VMM_TBL1) == SEL_VMM_TBL1)
Anish Bhattffda2032015-09-29 12:15:49 -07001034 tbl_ctl |= BIT(1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001035
Glen Lee49dcd0d2015-11-18 15:11:26 +09001036 ret = wilc_spi_write_reg(wilc, WILC_VMM_TBL_CTL,
1037 tbl_ctl);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001038 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001039 dev_err(&spi->dev,
1040 "fail write reg vmm_tbl_ctl...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001041 goto _fail_;
1042 }
1043
1044 if ((val & EN_VMM) == EN_VMM) {
1045 /**
1046 * enable vmm transfer.
1047 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +09001048 ret = wilc_spi_write_reg(wilc,
1049 WILC_VMM_CORE_CTL, 1);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001050 if (!ret) {
Roger H. Newell5142a142016-02-16 09:24:56 -03301051 dev_err(&spi->dev, "fail write reg vmm_core_ctl...\n");
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001052 goto _fail_;
1053 }
1054 }
1055 }
1056 }
1057_fail_:
1058 return ret;
1059}
1060
Glen Lee49dcd0d2015-11-18 15:11:26 +09001061static int wilc_spi_sync_ext(struct wilc *wilc, int nint)
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001062{
Glen Leeac1da162015-12-21 14:18:13 +09001063 struct spi_device *spi = to_spi_device(wilc->dev);
Chaehyun Limfbc2fe12015-09-15 14:06:16 +09001064 u32 reg;
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001065 int ret, i;
1066
1067 if (nint > MAX_NUM_INT) {
Colin Ian King95b8cb82016-06-23 14:14:07 +01001068 dev_err(&spi->dev, "Too many interrupts (%d)...\n", nint);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001069 return 0;
1070 }
1071
1072 g_spi.nint = nint;
1073
1074 /**
1075 * interrupt pin mux select
1076 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +09001077 ret = wilc_spi_read_reg(wilc, WILC_PIN_MUX_0, &reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001078 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001079 dev_err(&spi->dev, "Failed read reg (%08x)...\n",
1080 WILC_PIN_MUX_0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001081 return 0;
1082 }
Anish Bhattffda2032015-09-29 12:15:49 -07001083 reg |= BIT(8);
Glen Lee49dcd0d2015-11-18 15:11:26 +09001084 ret = wilc_spi_write_reg(wilc, WILC_PIN_MUX_0, reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001085 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001086 dev_err(&spi->dev, "Failed write reg (%08x)...\n",
1087 WILC_PIN_MUX_0);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001088 return 0;
1089 }
1090
1091 /**
1092 * interrupt enable
1093 **/
Glen Lee49dcd0d2015-11-18 15:11:26 +09001094 ret = wilc_spi_read_reg(wilc, WILC_INTR_ENABLE, &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_INTR_ENABLE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001098 return 0;
1099 }
1100
Roger H. Newelle0a30002016-02-16 09:25:42 -03301101 for (i = 0; (i < 5) && (nint > 0); i++, nint--)
Anish Bhattffda2032015-09-29 12:15:49 -07001102 reg |= (BIT((27 + i)));
Roger H. Newelle0a30002016-02-16 09:25:42 -03301103
Glen Lee49dcd0d2015-11-18 15:11:26 +09001104 ret = wilc_spi_write_reg(wilc, WILC_INTR_ENABLE, reg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001105 if (!ret) {
Glen Leeac1da162015-12-21 14:18:13 +09001106 dev_err(&spi->dev, "Failed write reg (%08x)...\n",
1107 WILC_INTR_ENABLE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001108 return 0;
1109 }
1110 if (nint) {
Glen Lee49dcd0d2015-11-18 15:11:26 +09001111 ret = wilc_spi_read_reg(wilc, WILC_INTR2_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_INTR2_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 < 3) && (nint > 0); i++, nint--)
Anish Bhattffda2032015-09-29 12:15:49 -07001119 reg |= BIT(i);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001120
Glen Lee49dcd0d2015-11-18 15:11:26 +09001121 ret = wilc_spi_read_reg(wilc, WILC_INTR2_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_INTR2_ENABLE);
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001125 return 0;
1126 }
1127 }
1128
1129 return 1;
1130}
1131/********************************************
1132 *
1133 * Global spi HIF function table
1134 *
1135 ********************************************/
Arnd Bergmann7d37a4a2015-11-16 15:05:05 +01001136const struct wilc_hif_func wilc_hif_spi = {
Glen Lee2769d942015-12-21 14:18:32 +09001137 .hif_init = wilc_spi_init,
Arnd Bergmann7d37a4a2015-11-16 15:05:05 +01001138 .hif_deinit = _wilc_spi_deinit,
1139 .hif_read_reg = wilc_spi_read_reg,
1140 .hif_write_reg = wilc_spi_write_reg,
Glen Leed4312b62015-12-21 14:18:31 +09001141 .hif_block_rx = wilc_spi_read,
1142 .hif_block_tx = wilc_spi_write,
Arnd Bergmann7d37a4a2015-11-16 15:05:05 +01001143 .hif_read_int = wilc_spi_read_int,
1144 .hif_clear_int_ext = wilc_spi_clear_int_ext,
1145 .hif_read_size = wilc_spi_read_size,
Glen Leed4312b62015-12-21 14:18:31 +09001146 .hif_block_tx_ext = wilc_spi_write,
1147 .hif_block_rx_ext = wilc_spi_read,
Arnd Bergmann7d37a4a2015-11-16 15:05:05 +01001148 .hif_sync_ext = wilc_spi_sync_ext,
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001149};