Linux 6.9-rc1
[linux-2.6-microblaze.git] / drivers / nfc / st95hf / spi.c
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);