Commit | Line | Data |
---|---|---|
c5c77ba1 JK |
1 | #include <linux/module.h> |
2 | #include <linux/init.h> | |
3 | #include <linux/kernel.h> | |
4 | #include <linux/fs.h> | |
5 | #include <linux/slab.h> | |
6 | #include <linux/types.h> | |
7 | #include <linux/cdev.h> | |
8 | #include <asm/uaccess.h> | |
9 | #include <linux/device.h> | |
10 | #include <linux/spi/spi.h> | |
11 | ||
12 | #include "linux_wlan_common.h" | |
13 | ||
14 | #define USE_SPI_DMA 0 /* johnny add */ | |
15 | ||
16 | #ifdef WILC_ASIC_A0 | |
17 | #if defined(PLAT_PANDA_ES_OMAP4460) | |
18 | #define MIN_SPEED 12000000 | |
19 | #define MAX_SPEED 24000000 | |
20 | #elif defined(PLAT_WMS8304) | |
21 | #define MIN_SPEED 12000000 | |
22 | #define MAX_SPEED 24000000 /* 4000000 */ | |
23 | #elif defined(CUSTOMER_PLATFORM) | |
24 | /* | |
25 | TODO : define Clock speed under 48M. | |
26 | * | |
27 | * ex) | |
28 | * #define MIN_SPEED 24000000 | |
29 | * #define MAX_SPEED 48000000 | |
30 | */ | |
31 | #else | |
32 | #define MIN_SPEED 24000000 | |
33 | #define MAX_SPEED 48000000 | |
34 | #endif | |
35 | #else /* WILC_ASIC_A0 */ | |
36 | /* Limit clk to 6MHz on FPGA. */ | |
37 | #define MIN_SPEED 6000000 | |
38 | #define MAX_SPEED 6000000 | |
39 | #endif /* WILC_ASIC_A0 */ | |
40 | ||
41 | static uint32_t SPEED = MIN_SPEED; | |
42 | ||
43 | struct spi_device *wilc_spi_dev; | |
44 | void linux_spi_deinit(void *vp); | |
45 | ||
46 | static int __init wilc_bus_probe(struct spi_device *spi) | |
47 | { | |
48 | ||
49 | PRINT_D(BUS_DBG, "spiModalias: %s\n", spi->modalias); | |
50 | PRINT_D(BUS_DBG, "spiMax-Speed: %d\n", spi->max_speed_hz); | |
51 | wilc_spi_dev = spi; | |
52 | ||
53 | printk("Driver Initializing success\n"); | |
54 | return 0; | |
55 | } | |
56 | ||
57 | static int __exit wilc_bus_remove(struct spi_device *spi) | |
58 | { | |
59 | ||
c5c77ba1 JK |
60 | return 0; |
61 | } | |
62 | ||
63 | #ifdef CONFIG_OF | |
64 | static const struct of_device_id wilc1000_of_match[] = { | |
65 | { .compatible = "atmel,wilc_spi", }, | |
66 | {} | |
67 | }; | |
68 | MODULE_DEVICE_TABLE(of, wilc1000_of_match); | |
69 | #endif | |
70 | ||
71 | struct spi_driver wilc_bus __refdata = { | |
72 | .driver = { | |
73 | .name = MODALIAS, | |
74 | #ifdef CONFIG_OF | |
75 | .of_match_table = wilc1000_of_match, | |
76 | #endif | |
77 | }, | |
78 | .probe = wilc_bus_probe, | |
79 | .remove = __exit_p(wilc_bus_remove), | |
80 | }; | |
81 | ||
82 | ||
83 | void linux_spi_deinit(void *vp) | |
84 | { | |
85 | ||
86 | spi_unregister_driver(&wilc_bus); | |
87 | ||
88 | SPEED = MIN_SPEED; | |
89 | PRINT_ER("@@@@@@@@@@@@ restore SPI speed to %d @@@@@@@@@\n", SPEED); | |
90 | ||
91 | } | |
92 | ||
93 | ||
94 | ||
95 | int linux_spi_init(void *vp) | |
96 | { | |
97 | int ret = 1; | |
98 | static int called; | |
99 | ||
100 | ||
101 | if (called == 0) { | |
102 | called++; | |
c5c77ba1 JK |
103 | ret = spi_register_driver(&wilc_bus); |
104 | } | |
105 | ||
106 | /* change return value to match WILC interface */ | |
107 | (ret < 0) ? (ret = 0) : (ret = 1); | |
108 | ||
109 | return ret; | |
110 | } | |
111 | ||
112 | #if defined(PLAT_WMS8304) | |
113 | #define TXRX_PHASE_SIZE (4096) | |
114 | #endif | |
115 | ||
116 | #if defined (NM73131_0_BOARD) | |
117 | ||
118 | int linux_spi_write(uint8_t *b, uint32_t len) | |
119 | { | |
120 | ||
121 | int ret; | |
122 | ||
123 | if (len > 0 && b != NULL) { | |
124 | struct spi_message msg; | |
125 | PRINT_D(BUS_DBG, "Request writing %d bytes\n", len); | |
126 | struct spi_transfer tr = { | |
127 | .tx_buf = b, | |
128 | .len = len, | |
129 | .speed_hz = SPEED, | |
130 | .delay_usecs = 0, | |
131 | }; | |
132 | ||
133 | spi_message_init(&msg); | |
134 | spi_message_add_tail(&tr, &msg); | |
135 | ret = spi_sync(wilc_spi_dev, &msg); | |
136 | if (ret < 0) { | |
137 | PRINT_ER("SPI transaction failed\n"); | |
138 | } | |
139 | ||
140 | } else { | |
141 | PRINT_ER("can't write data with the following length: %d\n", len); | |
142 | PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len); | |
143 | ret = -1; | |
144 | } | |
145 | ||
146 | /* change return value to match WILC interface */ | |
147 | (ret < 0) ? (ret = 0) : (ret = 1); | |
148 | ||
149 | ||
150 | return ret; | |
151 | } | |
152 | ||
153 | #elif defined(TXRX_PHASE_SIZE) | |
154 | ||
155 | int linux_spi_write(uint8_t *b, uint32_t len) | |
156 | { | |
157 | int ret; | |
158 | if (len > 0 && b != NULL) { | |
159 | int i = 0; | |
160 | int blk = len / TXRX_PHASE_SIZE; | |
161 | int remainder = len % TXRX_PHASE_SIZE; | |
162 | ||
37bc15d8 | 163 | char *r_buffer = kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL); |
c5c77ba1 JK |
164 | if (!r_buffer) { |
165 | PRINT_ER("Failed to allocate memory for r_buffer\n"); | |
166 | } | |
167 | ||
168 | if (blk) { | |
169 | while (i < blk) { | |
170 | struct spi_message msg; | |
171 | struct spi_transfer tr = { | |
172 | .tx_buf = b + (i * TXRX_PHASE_SIZE), | |
c5c77ba1 JK |
173 | .len = TXRX_PHASE_SIZE, |
174 | .speed_hz = SPEED, | |
175 | .bits_per_word = 8, | |
176 | .delay_usecs = 0, | |
177 | }; | |
4d77c6cc | 178 | |
c5c77ba1 JK |
179 | tr.rx_buf = r_buffer; |
180 | ||
181 | memset(&msg, 0, sizeof(msg)); | |
182 | spi_message_init(&msg); | |
183 | msg.spi = wilc_spi_dev; | |
184 | msg.is_dma_mapped = USE_SPI_DMA; | |
185 | ||
186 | spi_message_add_tail(&tr, &msg); | |
187 | ret = spi_sync(wilc_spi_dev, &msg); | |
188 | if (ret < 0) { | |
189 | PRINT_ER("SPI transaction failed\n"); | |
190 | } | |
c5c77ba1 JK |
191 | i++; |
192 | ||
193 | } | |
194 | } | |
195 | if (remainder) { | |
196 | struct spi_message msg; | |
197 | struct spi_transfer tr = { | |
198 | .tx_buf = b + (blk * TXRX_PHASE_SIZE), | |
c5c77ba1 JK |
199 | .len = remainder, |
200 | .speed_hz = SPEED, | |
201 | .bits_per_word = 8, | |
202 | .delay_usecs = 0, | |
203 | }; | |
c5c77ba1 JK |
204 | tr.rx_buf = r_buffer; |
205 | ||
206 | memset(&msg, 0, sizeof(msg)); | |
207 | spi_message_init(&msg); | |
208 | msg.spi = wilc_spi_dev; | |
209 | msg.is_dma_mapped = USE_SPI_DMA; /* rachel */ | |
210 | ||
211 | spi_message_add_tail(&tr, &msg); | |
212 | ret = spi_sync(wilc_spi_dev, &msg); | |
213 | if (ret < 0) { | |
214 | PRINT_ER("SPI transaction failed\n"); | |
215 | } | |
216 | } | |
0256b540 | 217 | kfree(r_buffer); |
c5c77ba1 JK |
218 | } else { |
219 | PRINT_ER("can't write data with the following length: %d\n", len); | |
220 | PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len); | |
221 | ret = -1; | |
222 | } | |
223 | ||
224 | /* change return value to match WILC interface */ | |
225 | (ret < 0) ? (ret = 0) : (ret = 1); | |
226 | ||
227 | return ret; | |
228 | ||
229 | } | |
230 | ||
231 | #else | |
232 | int linux_spi_write(uint8_t *b, uint32_t len) | |
233 | { | |
234 | ||
235 | int ret; | |
236 | struct spi_message msg; | |
237 | ||
238 | if (len > 0 && b != NULL) { | |
239 | struct spi_transfer tr = { | |
240 | .tx_buf = b, | |
c5c77ba1 JK |
241 | .len = len, |
242 | .speed_hz = SPEED, | |
243 | .delay_usecs = 0, | |
244 | }; | |
37bc15d8 | 245 | char *r_buffer = kzalloc(len, GFP_KERNEL); |
c5c77ba1 JK |
246 | if (!r_buffer) { |
247 | PRINT_ER("Failed to allocate memory for r_buffer\n"); | |
248 | } | |
249 | tr.rx_buf = r_buffer; | |
250 | PRINT_D(BUS_DBG, "Request writing %d bytes\n", len); | |
251 | ||
252 | memset(&msg, 0, sizeof(msg)); | |
253 | spi_message_init(&msg); | |
254 | /* [[johnny add */ | |
255 | msg.spi = wilc_spi_dev; | |
256 | msg.is_dma_mapped = USE_SPI_DMA; | |
257 | /* ]] */ | |
258 | spi_message_add_tail(&tr, &msg); | |
259 | ||
260 | ret = spi_sync(wilc_spi_dev, &msg); | |
261 | if (ret < 0) { | |
262 | PRINT_ER("SPI transaction failed\n"); | |
263 | } | |
264 | ||
265 | kfree(r_buffer); | |
266 | } else { | |
267 | PRINT_ER("can't write data with the following length: %d\n", len); | |
268 | PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len); | |
269 | ret = -1; | |
270 | } | |
271 | ||
272 | /* change return value to match WILC interface */ | |
273 | (ret < 0) ? (ret = 0) : (ret = 1); | |
274 | ||
275 | ||
276 | return ret; | |
277 | } | |
278 | ||
279 | #endif | |
280 | ||
281 | #if defined (NM73131_0_BOARD) | |
282 | ||
283 | int linux_spi_read(unsigned char *rb, unsigned long rlen) | |
284 | { | |
285 | ||
286 | int ret; | |
287 | ||
288 | if (rlen > 0) { | |
289 | struct spi_message msg; | |
290 | struct spi_transfer tr = { | |
291 | .rx_buf = rb, | |
292 | .len = rlen, | |
293 | .speed_hz = SPEED, | |
294 | .delay_usecs = 0, | |
295 | ||
296 | }; | |
297 | ||
298 | spi_message_init(&msg); | |
299 | spi_message_add_tail(&tr, &msg); | |
300 | ret = spi_sync(wilc_spi_dev, &msg); | |
301 | if (ret < 0) { | |
302 | PRINT_ER("SPI transaction failed\n"); | |
303 | } | |
304 | } else { | |
305 | PRINT_ER("can't read data with the following length: %ld\n", rlen); | |
306 | ret = -1; | |
307 | } | |
308 | /* change return value to match WILC interface */ | |
309 | (ret < 0) ? (ret = 0) : (ret = 1); | |
310 | ||
311 | return ret; | |
312 | } | |
313 | ||
314 | #elif defined(TXRX_PHASE_SIZE) | |
315 | ||
316 | int linux_spi_read(unsigned char *rb, unsigned long rlen) | |
317 | { | |
318 | int ret; | |
319 | ||
320 | if (rlen > 0) { | |
321 | int i = 0; | |
322 | ||
323 | int blk = rlen / TXRX_PHASE_SIZE; | |
324 | int remainder = rlen % TXRX_PHASE_SIZE; | |
325 | ||
37bc15d8 | 326 | char *t_buffer = kzalloc(TXRX_PHASE_SIZE, GFP_KERNEL); |
c5c77ba1 JK |
327 | if (!t_buffer) { |
328 | PRINT_ER("Failed to allocate memory for t_buffer\n"); | |
329 | } | |
330 | ||
331 | if (blk) { | |
332 | while (i < blk) { | |
333 | struct spi_message msg; | |
334 | struct spi_transfer tr = { | |
c5c77ba1 JK |
335 | .rx_buf = rb + (i * TXRX_PHASE_SIZE), |
336 | .len = TXRX_PHASE_SIZE, | |
337 | .speed_hz = SPEED, | |
338 | .bits_per_word = 8, | |
339 | .delay_usecs = 0, | |
340 | }; | |
341 | tr.tx_buf = t_buffer; | |
342 | ||
343 | memset(&msg, 0, sizeof(msg)); | |
344 | spi_message_init(&msg); | |
345 | msg.spi = wilc_spi_dev; | |
346 | msg.is_dma_mapped = USE_SPI_DMA; | |
347 | ||
348 | spi_message_add_tail(&tr, &msg); | |
349 | ret = spi_sync(wilc_spi_dev, &msg); | |
350 | if (ret < 0) { | |
351 | PRINT_ER("SPI transaction failed\n"); | |
352 | } | |
353 | i++; | |
354 | } | |
355 | } | |
356 | if (remainder) { | |
357 | struct spi_message msg; | |
358 | struct spi_transfer tr = { | |
c5c77ba1 JK |
359 | .rx_buf = rb + (blk * TXRX_PHASE_SIZE), |
360 | .len = remainder, | |
361 | .speed_hz = SPEED, | |
362 | .bits_per_word = 8, | |
363 | .delay_usecs = 0, | |
364 | }; | |
c5c77ba1 JK |
365 | tr.tx_buf = t_buffer; |
366 | ||
367 | memset(&msg, 0, sizeof(msg)); | |
368 | spi_message_init(&msg); | |
369 | msg.spi = wilc_spi_dev; | |
370 | msg.is_dma_mapped = USE_SPI_DMA; /* rachel */ | |
371 | ||
372 | spi_message_add_tail(&tr, &msg); | |
373 | ret = spi_sync(wilc_spi_dev, &msg); | |
374 | if (ret < 0) { | |
375 | PRINT_ER("SPI transaction failed\n"); | |
376 | } | |
377 | } | |
378 | ||
0256b540 | 379 | kfree(t_buffer); |
c5c77ba1 JK |
380 | } else { |
381 | PRINT_ER("can't read data with the following length: %ld\n", rlen); | |
382 | ret = -1; | |
383 | } | |
384 | /* change return value to match WILC interface */ | |
385 | (ret < 0) ? (ret = 0) : (ret = 1); | |
386 | ||
387 | return ret; | |
388 | } | |
389 | ||
390 | #else | |
391 | int linux_spi_read(unsigned char *rb, unsigned long rlen) | |
392 | { | |
393 | ||
394 | int ret; | |
395 | ||
396 | if (rlen > 0) { | |
397 | struct spi_message msg; | |
398 | struct spi_transfer tr = { | |
c5c77ba1 JK |
399 | .rx_buf = rb, |
400 | .len = rlen, | |
401 | .speed_hz = SPEED, | |
402 | .delay_usecs = 0, | |
403 | ||
404 | }; | |
37bc15d8 | 405 | char *t_buffer = kzalloc(rlen, GFP_KERNEL); |
c5c77ba1 JK |
406 | if (!t_buffer) { |
407 | PRINT_ER("Failed to allocate memory for t_buffer\n"); | |
408 | } | |
409 | tr.tx_buf = t_buffer; | |
410 | ||
411 | memset(&msg, 0, sizeof(msg)); | |
412 | spi_message_init(&msg); | |
413 | /* [[ johnny add */ | |
414 | msg.spi = wilc_spi_dev; | |
415 | msg.is_dma_mapped = USE_SPI_DMA; | |
416 | /* ]] */ | |
417 | spi_message_add_tail(&tr, &msg); | |
418 | ||
419 | ret = spi_sync(wilc_spi_dev, &msg); | |
420 | if (ret < 0) { | |
421 | PRINT_ER("SPI transaction failed\n"); | |
422 | } | |
423 | kfree(t_buffer); | |
424 | } else { | |
425 | PRINT_ER("can't read data with the following length: %ld\n", rlen); | |
426 | ret = -1; | |
427 | } | |
428 | /* change return value to match WILC interface */ | |
429 | (ret < 0) ? (ret = 0) : (ret = 1); | |
430 | ||
431 | return ret; | |
432 | } | |
433 | ||
434 | #endif | |
435 | ||
436 | int linux_spi_write_read(unsigned char *wb, unsigned char *rb, unsigned int rlen) | |
437 | { | |
438 | ||
439 | int ret; | |
440 | ||
441 | if (rlen > 0) { | |
442 | struct spi_message msg; | |
443 | struct spi_transfer tr = { | |
444 | .rx_buf = rb, | |
445 | .tx_buf = wb, | |
446 | .len = rlen, | |
447 | .speed_hz = SPEED, | |
448 | .bits_per_word = 8, | |
449 | .delay_usecs = 0, | |
450 | ||
451 | }; | |
452 | ||
453 | memset(&msg, 0, sizeof(msg)); | |
454 | spi_message_init(&msg); | |
455 | msg.spi = wilc_spi_dev; | |
456 | msg.is_dma_mapped = USE_SPI_DMA; | |
457 | ||
458 | spi_message_add_tail(&tr, &msg); | |
459 | ret = spi_sync(wilc_spi_dev, &msg); | |
460 | if (ret < 0) { | |
461 | PRINT_ER("SPI transaction failed\n"); | |
462 | } | |
463 | } else { | |
464 | PRINT_ER("can't read data with the following length: %d\n", rlen); | |
465 | ret = -1; | |
466 | } | |
467 | /* change return value to match WILC interface */ | |
468 | (ret < 0) ? (ret = 0) : (ret = 1); | |
469 | ||
470 | return ret; | |
471 | } | |
472 | ||
473 | int linux_spi_set_max_speed(void) | |
474 | { | |
475 | SPEED = MAX_SPEED; | |
476 | ||
477 | PRINT_INFO(BUS_DBG, "@@@@@@@@@@@@ change SPI speed to %d @@@@@@@@@\n", SPEED); | |
478 | return 1; | |
479 | } |