xref: /linux/drivers/nfc/st95hf/spi.c (revision 44f57d78)
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 */
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 */
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 
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