Loading...
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * ----------------------------------------------------------------------------
4 * drivers/nfc/st95hf/spi.c function definitions for SPI communication
5 * ----------------------------------------------------------------------------
6 * Copyright (C) 2015 STMicroelectronics Pvt. Ltd. All rights reserved.
7 */
8
9#include "spi.h"
10
11/* Function to send user provided buffer to ST95HF through SPI */
12int st95hf_spi_send(struct st95hf_spi_context *spicontext,
13 unsigned char *buffertx,
14 int datalen,
15 enum req_type reqtype)
16{
17 struct spi_message m;
18 int result = 0;
19 struct spi_device *spidev = spicontext->spidev;
20 struct spi_transfer tx_transfer = {
21 .tx_buf = buffertx,
22 .len = datalen,
23 };
24
25 mutex_lock(&spicontext->spi_lock);
26
27 if (reqtype == SYNC) {
28 spicontext->req_issync = true;
29 reinit_completion(&spicontext->done);
30 } else {
31 spicontext->req_issync = false;
32 }
33
34 spi_message_init(&m);
35 spi_message_add_tail(&tx_transfer, &m);
36
37 result = spi_sync(spidev, &m);
38 if (result) {
39 dev_err(&spidev->dev, "error: sending cmd to st95hf using SPI = %d\n",
40 result);
41 mutex_unlock(&spicontext->spi_lock);
42 return result;
43 }
44
45 /* return for asynchronous or no-wait case */
46 if (reqtype == ASYNC) {
47 mutex_unlock(&spicontext->spi_lock);
48 return 0;
49 }
50
51 result = wait_for_completion_timeout(&spicontext->done,
52 msecs_to_jiffies(1000));
53 /* check for timeout or success */
54 if (!result) {
55 dev_err(&spidev->dev, "error: response not ready timeout\n");
56 result = -ETIMEDOUT;
57 } else {
58 result = 0;
59 }
60
61 mutex_unlock(&spicontext->spi_lock);
62
63 return result;
64}
65EXPORT_SYMBOL_GPL(st95hf_spi_send);
66
67/* Function to Receive command Response */
68int st95hf_spi_recv_response(struct st95hf_spi_context *spicontext,
69 unsigned char *receivebuff)
70{
71 int len = 0;
72 struct spi_transfer tx_takedata;
73 struct spi_message m;
74 struct spi_device *spidev = spicontext->spidev;
75 unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
76 struct spi_transfer t[2] = {
77 {.tx_buf = &readdata_cmd, .len = 1,},
78 {.rx_buf = receivebuff, .len = 2, .cs_change = 1,},
79 };
80
81 int ret = 0;
82
83 memset(&tx_takedata, 0x0, sizeof(struct spi_transfer));
84
85 mutex_lock(&spicontext->spi_lock);
86
87 /* First spi transfer to know the length of valid data */
88 spi_message_init(&m);
89 spi_message_add_tail(&t[0], &m);
90 spi_message_add_tail(&t[1], &m);
91
92 ret = spi_sync(spidev, &m);
93 if (ret) {
94 dev_err(&spidev->dev, "spi_recv_resp, data length error = %d\n",
95 ret);
96 mutex_unlock(&spicontext->spi_lock);
97 return ret;
98 }
99
100 /* As 2 bytes are already read */
101 len = 2;
102
103 /* Support of long frame */
104 if (receivebuff[0] & 0x60)
105 len += (((receivebuff[0] & 0x60) >> 5) << 8) | receivebuff[1];
106 else
107 len += receivebuff[1];
108
109 /* Now make a transfer to read only relevant bytes */
110 tx_takedata.rx_buf = &receivebuff[2];
111 tx_takedata.len = len - 2;
112
113 spi_message_init(&m);
114 spi_message_add_tail(&tx_takedata, &m);
115
116 ret = spi_sync(spidev, &m);
117
118 mutex_unlock(&spicontext->spi_lock);
119 if (ret) {
120 dev_err(&spidev->dev, "spi_recv_resp, data read error = %d\n",
121 ret);
122 return ret;
123 }
124
125 return len;
126}
127EXPORT_SYMBOL_GPL(st95hf_spi_recv_response);
128
129int st95hf_spi_recv_echo_res(struct st95hf_spi_context *spicontext,
130 unsigned char *receivebuff)
131{
132 unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
133 struct spi_transfer t[2] = {
134 {.tx_buf = &readdata_cmd, .len = 1,},
135 {.rx_buf = receivebuff, .len = 1,},
136 };
137 struct spi_message m;
138 struct spi_device *spidev = spicontext->spidev;
139 int ret = 0;
140
141 mutex_lock(&spicontext->spi_lock);
142
143 spi_message_init(&m);
144 spi_message_add_tail(&t[0], &m);
145 spi_message_add_tail(&t[1], &m);
146 ret = spi_sync(spidev, &m);
147
148 mutex_unlock(&spicontext->spi_lock);
149
150 if (ret)
151 dev_err(&spidev->dev, "recv_echo_res, data read error = %d\n",
152 ret);
153
154 return ret;
155}
156EXPORT_SYMBOL_GPL(st95hf_spi_recv_echo_res);
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 */
23int 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}
76EXPORT_SYMBOL_GPL(st95hf_spi_send);
77
78/* Function to Receive command Response */
79int 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}
138EXPORT_SYMBOL_GPL(st95hf_spi_recv_response);
139
140int 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}
167EXPORT_SYMBOL_GPL(st95hf_spi_recv_echo_res);