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 */
st95hf_spi_send(struct st95hf_spi_context * spicontext,unsigned char * buffertx,int datalen,enum req_type reqtype)12 int 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 }
65 EXPORT_SYMBOL_GPL(st95hf_spi_send);
66
67 /* Function to Receive command Response */
st95hf_spi_recv_response(struct st95hf_spi_context * spicontext,unsigned char * receivebuff)68 int 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 }
127 EXPORT_SYMBOL_GPL(st95hf_spi_recv_response);
128
st95hf_spi_recv_echo_res(struct st95hf_spi_context * spicontext,unsigned char * receivebuff)129 int 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 }
156 EXPORT_SYMBOL_GPL(st95hf_spi_recv_echo_res);
157