xref: /openbmc/linux/drivers/nfc/st95hf/spi.c (revision 6a551c11)
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);
168