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