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