123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- /*
- * ----------------------------------------------------------------------------
- * drivers/nfc/st95hf/spi.c function definitions for SPI communication
- * ----------------------------------------------------------------------------
- * Copyright (C) 2015 STMicroelectronics Pvt. Ltd. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
- #include "spi.h"
- /* Function to send user provided buffer to ST95HF through SPI */
- int st95hf_spi_send(struct st95hf_spi_context *spicontext,
- unsigned char *buffertx,
- int datalen,
- enum req_type reqtype)
- {
- struct spi_message m;
- int result = 0;
- struct spi_device *spidev = spicontext->spidev;
- struct spi_transfer tx_transfer = {
- .tx_buf = buffertx,
- .len = datalen,
- };
- mutex_lock(&spicontext->spi_lock);
- if (reqtype == SYNC) {
- spicontext->req_issync = true;
- reinit_completion(&spicontext->done);
- } else {
- spicontext->req_issync = false;
- }
- spi_message_init(&m);
- spi_message_add_tail(&tx_transfer, &m);
- result = spi_sync(spidev, &m);
- if (result) {
- dev_err(&spidev->dev, "error: sending cmd to st95hf using SPI = %d\n",
- result);
- mutex_unlock(&spicontext->spi_lock);
- return result;
- }
- /* return for asynchronous or no-wait case */
- if (reqtype == ASYNC) {
- mutex_unlock(&spicontext->spi_lock);
- return 0;
- }
- result = wait_for_completion_timeout(&spicontext->done,
- msecs_to_jiffies(1000));
- /* check for timeout or success */
- if (!result) {
- dev_err(&spidev->dev, "error: response not ready timeout\n");
- result = -ETIMEDOUT;
- } else {
- result = 0;
- }
- mutex_unlock(&spicontext->spi_lock);
- return result;
- }
- EXPORT_SYMBOL_GPL(st95hf_spi_send);
- /* Function to Receive command Response */
- int st95hf_spi_recv_response(struct st95hf_spi_context *spicontext,
- unsigned char *receivebuff)
- {
- int len = 0;
- struct spi_transfer tx_takedata;
- struct spi_message m;
- struct spi_device *spidev = spicontext->spidev;
- unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
- struct spi_transfer t[2] = {
- {.tx_buf = &readdata_cmd, .len = 1,},
- {.rx_buf = receivebuff, .len = 2, .cs_change = 1,},
- };
- int ret = 0;
- memset(&tx_takedata, 0x0, sizeof(struct spi_transfer));
- mutex_lock(&spicontext->spi_lock);
- /* First spi transfer to know the length of valid data */
- spi_message_init(&m);
- spi_message_add_tail(&t[0], &m);
- spi_message_add_tail(&t[1], &m);
- ret = spi_sync(spidev, &m);
- if (ret) {
- dev_err(&spidev->dev, "spi_recv_resp, data length error = %d\n",
- ret);
- mutex_unlock(&spicontext->spi_lock);
- return ret;
- }
- /* As 2 bytes are already read */
- len = 2;
- /* Support of long frame */
- if (receivebuff[0] & 0x60)
- len += (((receivebuff[0] & 0x60) >> 5) << 8) | receivebuff[1];
- else
- len += receivebuff[1];
- /* Now make a transfer to read only relevant bytes */
- tx_takedata.rx_buf = &receivebuff[2];
- tx_takedata.len = len - 2;
- spi_message_init(&m);
- spi_message_add_tail(&tx_takedata, &m);
- ret = spi_sync(spidev, &m);
- mutex_unlock(&spicontext->spi_lock);
- if (ret) {
- dev_err(&spidev->dev, "spi_recv_resp, data read error = %d\n",
- ret);
- return ret;
- }
- return len;
- }
- EXPORT_SYMBOL_GPL(st95hf_spi_recv_response);
- int st95hf_spi_recv_echo_res(struct st95hf_spi_context *spicontext,
- unsigned char *receivebuff)
- {
- unsigned char readdata_cmd = ST95HF_COMMAND_RECEIVE;
- struct spi_transfer t[2] = {
- {.tx_buf = &readdata_cmd, .len = 1,},
- {.rx_buf = receivebuff, .len = 1,},
- };
- struct spi_message m;
- struct spi_device *spidev = spicontext->spidev;
- int ret = 0;
- mutex_lock(&spicontext->spi_lock);
- spi_message_init(&m);
- spi_message_add_tail(&t[0], &m);
- spi_message_add_tail(&t[1], &m);
- ret = spi_sync(spidev, &m);
- mutex_unlock(&spicontext->spi_lock);
- if (ret)
- dev_err(&spidev->dev, "recv_echo_res, data read error = %d\n",
- ret);
- return ret;
- }
- EXPORT_SYMBOL_GPL(st95hf_spi_recv_echo_res);
|