GNU Linux-libre 4.14.328-gnu1
[releases.git] / drivers / nfc / st95hf / spi.c
1 /*
2  * ----------------------------------------------------------------------------
3  * drivers/nfc/st95hf/spi.c function definitions for SPI communication
4  * ----------------------------------------------------------------------------
5  * Copyright (C) 2015 STMicroelectronics Pvt. Ltd. All rights reserved.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms and conditions of the GNU General Public License,
9  * version 2, as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "spi.h"
21
22 /* Function to send user provided buffer to ST95HF through SPI */
23 int st95hf_spi_send(struct st95hf_spi_context *spicontext,
24                     unsigned char *buffertx,
25                     int datalen,
26                     enum req_type reqtype)
27 {
28         struct spi_message m;
29         int result = 0;
30         struct spi_device *spidev = spicontext->spidev;
31         struct spi_transfer tx_transfer = {
32                 .tx_buf = buffertx,
33                 .len = datalen,
34         };
35
36         mutex_lock(&spicontext->spi_lock);
37
38         if (reqtype == SYNC) {
39                 spicontext->req_issync = true;
40                 reinit_completion(&spicontext->done);
41         } else {
42                 spicontext->req_issync = false;
43         }
44
45         spi_message_init(&m);
46         spi_message_add_tail(&tx_transfer, &m);
47
48         result = spi_sync(spidev, &m);
49         if (result) {
50                 dev_err(&spidev->dev, "error: sending cmd to st95hf using SPI = %d\n",
51                         result);
52                 mutex_unlock(&spicontext->spi_lock);
53                 return result;
54         }
55
56         /* return for asynchronous or no-wait case */
57         if (reqtype == ASYNC) {
58                 mutex_unlock(&spicontext->spi_lock);
59                 return 0;
60         }
61
62         result = wait_for_completion_timeout(&spicontext->done,
63                                              msecs_to_jiffies(1000));
64         /* check for timeout or success */
65         if (!result) {
66                 dev_err(&spidev->dev, "error: response not ready timeout\n");
67                 result = -ETIMEDOUT;
68         } else {
69                 result = 0;
70         }
71
72         mutex_unlock(&spicontext->spi_lock);
73
74         return result;
75 }
76 EXPORT_SYMBOL_GPL(st95hf_spi_send);
77
78 /* Function to Receive command Response */
79 int st95hf_spi_recv_response(struct st95hf_spi_context *spicontext,
80                              unsigned char *receivebuff)
81 {
82         int len = 0;
83         struct spi_transfer tx_takedata;
84         struct spi_message m;
85         struct spi_device *spidev = spicontext->spidev;
86         unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
87         struct spi_transfer t[2] = {
88                 {.tx_buf = &readdata_cmd, .len = 1,},
89                 {.rx_buf = receivebuff, .len = 2, .cs_change = 1,},
90         };
91
92         int ret = 0;
93
94         memset(&tx_takedata, 0x0, sizeof(struct spi_transfer));
95
96         mutex_lock(&spicontext->spi_lock);
97
98         /* First spi transfer to know the length of valid data */
99         spi_message_init(&m);
100         spi_message_add_tail(&t[0], &m);
101         spi_message_add_tail(&t[1], &m);
102
103         ret = spi_sync(spidev, &m);
104         if (ret) {
105                 dev_err(&spidev->dev, "spi_recv_resp, data length error = %d\n",
106                         ret);
107                 mutex_unlock(&spicontext->spi_lock);
108                 return ret;
109         }
110
111         /* As 2 bytes are already read */
112         len = 2;
113
114         /* Support of long frame */
115         if (receivebuff[0] & 0x60)
116                 len += (((receivebuff[0] & 0x60) >> 5) << 8) | receivebuff[1];
117         else
118                 len += receivebuff[1];
119
120         /* Now make a transfer to read only relevant bytes */
121         tx_takedata.rx_buf = &receivebuff[2];
122         tx_takedata.len = len - 2;
123
124         spi_message_init(&m);
125         spi_message_add_tail(&tx_takedata, &m);
126
127         ret = spi_sync(spidev, &m);
128
129         mutex_unlock(&spicontext->spi_lock);
130         if (ret) {
131                 dev_err(&spidev->dev, "spi_recv_resp, data read error = %d\n",
132                         ret);
133                 return ret;
134         }
135
136         return len;
137 }
138 EXPORT_SYMBOL_GPL(st95hf_spi_recv_response);
139
140 int st95hf_spi_recv_echo_res(struct st95hf_spi_context *spicontext,
141                              unsigned char *receivebuff)
142 {
143         unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
144         struct spi_transfer t[2] = {
145                 {.tx_buf = &readdata_cmd, .len = 1,},
146                 {.rx_buf = receivebuff, .len = 1,},
147         };
148         struct spi_message m;
149         struct spi_device *spidev = spicontext->spidev;
150         int ret = 0;
151
152         mutex_lock(&spicontext->spi_lock);
153
154         spi_message_init(&m);
155         spi_message_add_tail(&t[0], &m);
156         spi_message_add_tail(&t[1], &m);
157         ret = spi_sync(spidev, &m);
158
159         mutex_unlock(&spicontext->spi_lock);
160
161         if (ret)
162                 dev_err(&spidev->dev, "recv_echo_res, data read error = %d\n",
163                         ret);
164
165         return ret;
166 }
167 EXPORT_SYMBOL_GPL(st95hf_spi_recv_echo_res);