cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

spi.c (3875B)


      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 */
     12int 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}
     65EXPORT_SYMBOL_GPL(st95hf_spi_send);
     66
     67/* Function to Receive command Response */
     68int 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}
    127EXPORT_SYMBOL_GPL(st95hf_spi_recv_response);
    128
    129int 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}
    156EXPORT_SYMBOL_GPL(st95hf_spi_recv_echo_res);