blob: bfd3cc39149468708f16057b91ce23310ff71261 [file] [log] [blame]
Johnny Kimc5c77ba2015-05-11 14:30:56 +09001#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>
Shraddha Barke7f9eb1f2015-09-10 09:03:01 +05308#include <linux/uaccess.h>
Johnny Kimc5c77ba2015-05-11 14:30:56 +09009#include <linux/device.h>
10#include <linux/spi/spi.h>
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010011#include <linux/of_gpio.h>
Johnny Kimc5c77ba2015-05-11 14:30:56 +090012
Arnd Bergmann67039922015-11-16 15:05:02 +010013#include "linux_wlan_spi.h"
Arnd Bergmannb03314e2015-11-16 15:05:01 +010014#include "wilc_wfi_netdevice.h"
Johnny Kimc5c77ba2015-05-11 14:30:56 +090015#include "linux_wlan_common.h"
Arnd Bergmannb03314e2015-11-16 15:05:01 +010016#include "wilc_wlan_if.h"
Johnny Kimc5c77ba2015-05-11 14:30:56 +090017
18#define USE_SPI_DMA 0 /* johnny add */
19
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010020static const struct wilc1000_ops wilc1000_spi_ops;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090021
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010022static int wilc_bus_probe(struct spi_device *spi)
Johnny Kimc5c77ba2015-05-11 14:30:56 +090023{
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010024 int ret, gpio;
25 struct wilc *wilc;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090026
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010027 gpio = of_get_gpio(spi->dev.of_node, 0);
28 if (gpio < 0)
29 gpio = GPIO_NUM;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090030
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010031 ret = wilc_netdev_init(&wilc, NULL, HIF_SPI, GPIO_NUM, &wilc_hif_spi);
32 if (ret)
33 return ret;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090034
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010035 spi_set_drvdata(spi, wilc);
36 wilc->dev = &spi->dev;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090037
Johnny Kimc5c77ba2015-05-11 14:30:56 +090038 return 0;
39}
40
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010041static int wilc_bus_remove(struct spi_device *spi)
42{
43 wilc_netdev_cleanup(spi_get_drvdata(spi));
44 return 0;
45}
46
Johnny Kimc5c77ba2015-05-11 14:30:56 +090047static const struct of_device_id wilc1000_of_match[] = {
48 { .compatible = "atmel,wilc_spi", },
49 {}
50};
51MODULE_DEVICE_TABLE(of, wilc1000_of_match);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090052
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010053struct spi_driver wilc1000_spi_driver = {
Johnny Kimc5c77ba2015-05-11 14:30:56 +090054 .driver = {
55 .name = MODALIAS,
Johnny Kimc5c77ba2015-05-11 14:30:56 +090056 .of_match_table = wilc1000_of_match,
Johnny Kimc5c77ba2015-05-11 14:30:56 +090057 },
58 .probe = wilc_bus_probe,
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010059 .remove = wilc_bus_remove,
Johnny Kimc5c77ba2015-05-11 14:30:56 +090060};
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010061module_spi_driver(wilc1000_spi_driver);
62MODULE_LICENSE("GPL");
Johnny Kimc5c77ba2015-05-11 14:30:56 +090063
Arnd Bergmann0e1af732015-11-16 15:04:54 +010064int wilc_spi_init(void)
Johnny Kimc5c77ba2015-05-11 14:30:56 +090065{
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010066 return 1;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090067}
68
Arnd Bergmann0e1af732015-11-16 15:04:54 +010069int wilc_spi_write(u8 *b, u32 len)
Johnny Kimc5c77ba2015-05-11 14:30:56 +090070{
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010071 struct spi_device *spi = to_spi_device(wilc_dev->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090072 int ret;
73 struct spi_message msg;
74
75 if (len > 0 && b != NULL) {
76 struct spi_transfer tr = {
77 .tx_buf = b,
Johnny Kimc5c77ba2015-05-11 14:30:56 +090078 .len = len,
Johnny Kimc5c77ba2015-05-11 14:30:56 +090079 .delay_usecs = 0,
80 };
Hari Prasath Gujulan Elango37bc15d2015-06-02 12:48:05 +000081 char *r_buffer = kzalloc(len, GFP_KERNEL);
Chaehyun Lima0e5fac2015-09-17 16:48:45 +090082 if (!r_buffer)
83 return -ENOMEM;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +090084
Johnny Kimc5c77ba2015-05-11 14:30:56 +090085 tr.rx_buf = r_buffer;
86 PRINT_D(BUS_DBG, "Request writing %d bytes\n", len);
87
88 memset(&msg, 0, sizeof(msg));
89 spi_message_init(&msg);
90/* [[johnny add */
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010091 msg.spi = spi;
Johnny Kimc5c77ba2015-05-11 14:30:56 +090092 msg.is_dma_mapped = USE_SPI_DMA;
93/* ]] */
94 spi_message_add_tail(&tr, &msg);
95
Arnd Bergmannc94f05e2015-11-16 15:05:09 +010096 ret = spi_sync(spi, &msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +090097 if (ret < 0) {
98 PRINT_ER("SPI transaction failed\n");
99 }
100
101 kfree(r_buffer);
102 } else {
103 PRINT_ER("can't write data with the following length: %d\n", len);
104 PRINT_ER("FAILED due to NULL buffer or ZERO length check the following length: %d\n", len);
105 ret = -1;
106 }
107
108 /* change return value to match WILC interface */
109 (ret < 0) ? (ret = 0) : (ret = 1);
110
111
112 return ret;
113}
114
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100115int wilc_spi_read(u8 *rb, u32 rlen)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900116{
Arnd Bergmannc94f05e2015-11-16 15:05:09 +0100117 struct spi_device *spi = to_spi_device(wilc_dev->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900118 int ret;
119
120 if (rlen > 0) {
121 struct spi_message msg;
122 struct spi_transfer tr = {
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900123 .rx_buf = rb,
124 .len = rlen,
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900125 .delay_usecs = 0,
126
127 };
Hari Prasath Gujulan Elango37bc15d2015-06-02 12:48:05 +0000128 char *t_buffer = kzalloc(rlen, GFP_KERNEL);
Chaehyun Lima0e5fac2015-09-17 16:48:45 +0900129 if (!t_buffer)
130 return -ENOMEM;
Chaehyun Lim8dfaafd2015-08-18 23:18:11 +0900131
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900132 tr.tx_buf = t_buffer;
133
134 memset(&msg, 0, sizeof(msg));
135 spi_message_init(&msg);
136/* [[ johnny add */
Arnd Bergmannc94f05e2015-11-16 15:05:09 +0100137 msg.spi = spi;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900138 msg.is_dma_mapped = USE_SPI_DMA;
139/* ]] */
140 spi_message_add_tail(&tr, &msg);
141
Arnd Bergmannc94f05e2015-11-16 15:05:09 +0100142 ret = spi_sync(spi, &msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900143 if (ret < 0) {
144 PRINT_ER("SPI transaction failed\n");
145 }
146 kfree(t_buffer);
147 } else {
Stanislav Kholmanskikh6b69b4f2015-10-08 21:23:13 +0300148 PRINT_ER("can't read data with the following length: %u\n", rlen);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900149 ret = -1;
150 }
151 /* change return value to match WILC interface */
152 (ret < 0) ? (ret = 0) : (ret = 1);
153
154 return ret;
155}
156
Arnd Bergmann0e1af732015-11-16 15:04:54 +0100157int wilc_spi_write_read(u8 *wb, u8 *rb, u32 rlen)
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900158{
Arnd Bergmannc94f05e2015-11-16 15:05:09 +0100159 struct spi_device *spi = to_spi_device(wilc_dev->dev);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900160 int ret;
161
162 if (rlen > 0) {
163 struct spi_message msg;
164 struct spi_transfer tr = {
165 .rx_buf = rb,
166 .tx_buf = wb,
167 .len = rlen,
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900168 .bits_per_word = 8,
169 .delay_usecs = 0,
170
171 };
172
173 memset(&msg, 0, sizeof(msg));
174 spi_message_init(&msg);
Arnd Bergmannc94f05e2015-11-16 15:05:09 +0100175 msg.spi = spi;
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900176 msg.is_dma_mapped = USE_SPI_DMA;
177
178 spi_message_add_tail(&tr, &msg);
Arnd Bergmannc94f05e2015-11-16 15:05:09 +0100179 ret = spi_sync(spi, &msg);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900180 if (ret < 0) {
181 PRINT_ER("SPI transaction failed\n");
182 }
183 } else {
Stanislav Kholmanskikh6b69b4f2015-10-08 21:23:13 +0300184 PRINT_ER("can't read data with the following length: %u\n", rlen);
Johnny Kimc5c77ba2015-05-11 14:30:56 +0900185 ret = -1;
186 }
187 /* change return value to match WILC interface */
188 (ret < 0) ? (ret = 0) : (ret = 1);
189
190 return ret;
191}