Commit | Line | Data |
---|---|---|
cab47333 SS |
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); |