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 (7058B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * SPI Link Layer for ST NCI based Driver
      4 * Copyright (C) 2014-2015 STMicroelectronics SAS. All rights reserved.
      5 */
      6
      7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      8
      9#include <linux/module.h>
     10#include <linux/spi/spi.h>
     11#include <linux/gpio/consumer.h>
     12#include <linux/acpi.h>
     13#include <linux/interrupt.h>
     14#include <linux/delay.h>
     15#include <linux/nfc.h>
     16#include <linux/of.h>
     17#include <net/nfc/nci.h>
     18
     19#include "st-nci.h"
     20
     21#define DRIVER_DESC "NCI NFC driver for ST_NCI"
     22
     23/* ndlc header */
     24#define ST_NCI_FRAME_HEADROOM	1
     25#define ST_NCI_FRAME_TAILROOM	0
     26
     27#define ST_NCI_SPI_MIN_SIZE 4   /* PCB(1) + NCI Packet header(3) */
     28#define ST_NCI_SPI_MAX_SIZE 250 /* req 4.2.1 */
     29
     30#define ST_NCI_DRIVER_NAME "st_nci"
     31#define ST_NCI_SPI_DRIVER_NAME "st_nci_spi"
     32
     33struct st_nci_spi_phy {
     34	struct spi_device *spi_dev;
     35	struct llt_ndlc *ndlc;
     36
     37	bool irq_active;
     38
     39	struct gpio_desc *gpiod_reset;
     40
     41	struct st_nci_se_status se_status;
     42};
     43
     44static int st_nci_spi_enable(void *phy_id)
     45{
     46	struct st_nci_spi_phy *phy = phy_id;
     47
     48	gpiod_set_value(phy->gpiod_reset, 0);
     49	usleep_range(10000, 15000);
     50	gpiod_set_value(phy->gpiod_reset, 1);
     51	usleep_range(80000, 85000);
     52
     53	if (phy->ndlc->powered == 0 && phy->irq_active == 0) {
     54		enable_irq(phy->spi_dev->irq);
     55		phy->irq_active = true;
     56	}
     57
     58	return 0;
     59}
     60
     61static void st_nci_spi_disable(void *phy_id)
     62{
     63	struct st_nci_spi_phy *phy = phy_id;
     64
     65	disable_irq_nosync(phy->spi_dev->irq);
     66	phy->irq_active = false;
     67}
     68
     69/*
     70 * Writing a frame must not return the number of written bytes.
     71 * It must return either zero for success, or <0 for error.
     72 * In addition, it must not alter the skb
     73 */
     74static int st_nci_spi_write(void *phy_id, struct sk_buff *skb)
     75{
     76	int r;
     77	struct st_nci_spi_phy *phy = phy_id;
     78	struct spi_device *dev = phy->spi_dev;
     79	struct sk_buff *skb_rx;
     80	u8 buf[ST_NCI_SPI_MAX_SIZE + NCI_DATA_HDR_SIZE +
     81	       ST_NCI_FRAME_HEADROOM + ST_NCI_FRAME_TAILROOM];
     82	struct spi_transfer spi_xfer = {
     83		.tx_buf = skb->data,
     84		.rx_buf = buf,
     85		.len = skb->len,
     86	};
     87
     88	if (phy->ndlc->hard_fault != 0)
     89		return phy->ndlc->hard_fault;
     90
     91	r = spi_sync_transfer(dev, &spi_xfer, 1);
     92	/*
     93	 * We may have received some valuable data on miso line.
     94	 * Send them back in the ndlc state machine.
     95	 */
     96	if (!r) {
     97		skb_rx = alloc_skb(skb->len, GFP_KERNEL);
     98		if (!skb_rx)
     99			return -ENOMEM;
    100
    101		skb_put(skb_rx, skb->len);
    102		memcpy(skb_rx->data, buf, skb->len);
    103		ndlc_recv(phy->ndlc, skb_rx);
    104	}
    105
    106	return r;
    107}
    108
    109/*
    110 * Reads an ndlc frame and returns it in a newly allocated sk_buff.
    111 * returns:
    112 * 0 : if received frame is complete
    113 * -EREMOTEIO : i2c read error (fatal)
    114 * -EBADMSG : frame was incorrect and discarded
    115 * -ENOMEM : cannot allocate skb, frame dropped
    116 */
    117static int st_nci_spi_read(struct st_nci_spi_phy *phy,
    118			struct sk_buff **skb)
    119{
    120	int r;
    121	u8 len;
    122	u8 buf[ST_NCI_SPI_MAX_SIZE];
    123	struct spi_device *dev = phy->spi_dev;
    124	struct spi_transfer spi_xfer = {
    125		.rx_buf = buf,
    126		.len = ST_NCI_SPI_MIN_SIZE,
    127	};
    128
    129	r = spi_sync_transfer(dev, &spi_xfer, 1);
    130	if (r < 0)
    131		return -EREMOTEIO;
    132
    133	len = be16_to_cpu(*(__be16 *) (buf + 2));
    134	if (len > ST_NCI_SPI_MAX_SIZE) {
    135		nfc_err(&dev->dev, "invalid frame len\n");
    136		phy->ndlc->hard_fault = 1;
    137		return -EBADMSG;
    138	}
    139
    140	*skb = alloc_skb(ST_NCI_SPI_MIN_SIZE + len, GFP_KERNEL);
    141	if (*skb == NULL)
    142		return -ENOMEM;
    143
    144	skb_reserve(*skb, ST_NCI_SPI_MIN_SIZE);
    145	skb_put(*skb, ST_NCI_SPI_MIN_SIZE);
    146	memcpy((*skb)->data, buf, ST_NCI_SPI_MIN_SIZE);
    147
    148	if (!len)
    149		return 0;
    150
    151	spi_xfer.len = len;
    152	r = spi_sync_transfer(dev, &spi_xfer, 1);
    153	if (r < 0) {
    154		kfree_skb(*skb);
    155		return -EREMOTEIO;
    156	}
    157
    158	skb_put(*skb, len);
    159	memcpy((*skb)->data + ST_NCI_SPI_MIN_SIZE, buf, len);
    160
    161	return 0;
    162}
    163
    164/*
    165 * Reads an ndlc frame from the chip.
    166 *
    167 * On ST21NFCB, IRQ goes in idle state when read starts.
    168 */
    169static irqreturn_t st_nci_irq_thread_fn(int irq, void *phy_id)
    170{
    171	struct st_nci_spi_phy *phy = phy_id;
    172	struct sk_buff *skb = NULL;
    173	int r;
    174
    175	if (!phy || !phy->ndlc || irq != phy->spi_dev->irq) {
    176		WARN_ON_ONCE(1);
    177		return IRQ_NONE;
    178	}
    179
    180	if (phy->ndlc->hard_fault)
    181		return IRQ_HANDLED;
    182
    183	if (!phy->ndlc->powered) {
    184		st_nci_spi_disable(phy);
    185		return IRQ_HANDLED;
    186	}
    187
    188	r = st_nci_spi_read(phy, &skb);
    189	if (r == -EREMOTEIO || r == -ENOMEM || r == -EBADMSG)
    190		return IRQ_HANDLED;
    191
    192	ndlc_recv(phy->ndlc, skb);
    193
    194	return IRQ_HANDLED;
    195}
    196
    197static const struct nfc_phy_ops spi_phy_ops = {
    198	.write = st_nci_spi_write,
    199	.enable = st_nci_spi_enable,
    200	.disable = st_nci_spi_disable,
    201};
    202
    203static const struct acpi_gpio_params reset_gpios = { 1, 0, false };
    204
    205static const struct acpi_gpio_mapping acpi_st_nci_gpios[] = {
    206	{ "reset-gpios", &reset_gpios, 1 },
    207	{},
    208};
    209
    210static int st_nci_spi_probe(struct spi_device *dev)
    211{
    212	struct st_nci_spi_phy *phy;
    213	int r;
    214
    215	/* Check SPI platform functionnalities */
    216	if (!dev) {
    217		pr_debug("%s: dev is NULL. Device is not accessible.\n",
    218			__func__);
    219		return -ENODEV;
    220	}
    221
    222	phy = devm_kzalloc(&dev->dev, sizeof(struct st_nci_spi_phy),
    223			   GFP_KERNEL);
    224	if (!phy)
    225		return -ENOMEM;
    226
    227	phy->spi_dev = dev;
    228
    229	spi_set_drvdata(dev, phy);
    230
    231	r = devm_acpi_dev_add_driver_gpios(&dev->dev, acpi_st_nci_gpios);
    232	if (r)
    233		dev_dbg(&dev->dev, "Unable to add GPIO mapping table\n");
    234
    235	/* Get RESET GPIO */
    236	phy->gpiod_reset = devm_gpiod_get(&dev->dev, "reset", GPIOD_OUT_HIGH);
    237	if (IS_ERR(phy->gpiod_reset)) {
    238		nfc_err(&dev->dev, "Unable to get RESET GPIO\n");
    239		return PTR_ERR(phy->gpiod_reset);
    240	}
    241
    242	phy->se_status.is_ese_present =
    243			device_property_read_bool(&dev->dev, "ese-present");
    244	phy->se_status.is_uicc_present =
    245			device_property_read_bool(&dev->dev, "uicc-present");
    246
    247	r = ndlc_probe(phy, &spi_phy_ops, &dev->dev,
    248			ST_NCI_FRAME_HEADROOM, ST_NCI_FRAME_TAILROOM,
    249			&phy->ndlc, &phy->se_status);
    250	if (r < 0) {
    251		nfc_err(&dev->dev, "Unable to register ndlc layer\n");
    252		return r;
    253	}
    254
    255	phy->irq_active = true;
    256	r = devm_request_threaded_irq(&dev->dev, dev->irq, NULL,
    257				st_nci_irq_thread_fn,
    258				IRQF_ONESHOT,
    259				ST_NCI_SPI_DRIVER_NAME, phy);
    260	if (r < 0)
    261		nfc_err(&dev->dev, "Unable to register IRQ handler\n");
    262
    263	return r;
    264}
    265
    266static void st_nci_spi_remove(struct spi_device *dev)
    267{
    268	struct st_nci_spi_phy *phy = spi_get_drvdata(dev);
    269
    270	ndlc_remove(phy->ndlc);
    271}
    272
    273static struct spi_device_id st_nci_spi_id_table[] = {
    274	{ST_NCI_SPI_DRIVER_NAME, 0},
    275	{"st21nfcb-spi", 0},
    276	{}
    277};
    278MODULE_DEVICE_TABLE(spi, st_nci_spi_id_table);
    279
    280static const struct acpi_device_id st_nci_spi_acpi_match[] __maybe_unused = {
    281	{"SMO2101", 0},
    282	{}
    283};
    284MODULE_DEVICE_TABLE(acpi, st_nci_spi_acpi_match);
    285
    286static const struct of_device_id of_st_nci_spi_match[] __maybe_unused = {
    287	{ .compatible = "st,st21nfcb-spi", },
    288	{}
    289};
    290MODULE_DEVICE_TABLE(of, of_st_nci_spi_match);
    291
    292static struct spi_driver st_nci_spi_driver = {
    293	.driver = {
    294		.name = ST_NCI_SPI_DRIVER_NAME,
    295		.of_match_table = of_match_ptr(of_st_nci_spi_match),
    296		.acpi_match_table = ACPI_PTR(st_nci_spi_acpi_match),
    297	},
    298	.probe = st_nci_spi_probe,
    299	.id_table = st_nci_spi_id_table,
    300	.remove = st_nci_spi_remove,
    301};
    302module_spi_driver(st_nci_spi_driver);
    303
    304MODULE_LICENSE("GPL");
    305MODULE_DESCRIPTION(DRIVER_DESC);