linux/drivers/nfc/st95hf/spi.c
<<
>>
Prefs
   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 */
  23int 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}
  76EXPORT_SYMBOL_GPL(st95hf_spi_send);
  77
  78/* Function to Receive command Response */
  79int 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}
 138EXPORT_SYMBOL_GPL(st95hf_spi_recv_response);
 139
 140int 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}
 167EXPORT_SYMBOL_GPL(st95hf_spi_recv_echo_res);
 168