Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFC: Add basic NCI over SPI

The NFC Forum defines a transport interface based on
Serial Peripheral Interface (SPI) for the NFC Controller
Interface (NCI).

This module implements the SPI transport of NCI, calling SPI module
directly to read/write data to NFC controller (NFCC).

NFCC driver should provide functions performing device open and close.
It should also provide functions asserting/de-asserting interruption
to prevent TX/RX race conditions.
NFCC driver can also fix a delay between transactions if needed by
the hardware.

Signed-off-by: Frederic Danis <frederic.danis@linux.intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Frederic Danis and committed by
Samuel Ortiz
8a00a61b a395298c

+197
+49
include/net/nfc/nci_core.h
··· 3 3 * NFC Controller (NFCC) and a Device Host (DH). 4 4 * 5 5 * Copyright (C) 2011 Texas Instruments, Inc. 6 + * Copyright (C) 2013 Intel Corporation. All rights reserved. 6 7 * 7 8 * Written by Ilan Elias <ilane@ti.com> 8 9 * ··· 202 201 203 202 /* ----- NCI status code ----- */ 204 203 int nci_to_errno(__u8 code); 204 + 205 + /* ----- NCI over SPI acknowledge modes ----- */ 206 + #define NCI_SPI_CRC_DISABLED 0x00 207 + #define NCI_SPI_CRC_ENABLED 0x01 208 + 209 + /* ----- NCI SPI structures ----- */ 210 + struct nci_spi_dev; 211 + 212 + struct nci_spi_ops { 213 + int (*open)(struct nci_spi_dev *ndev); 214 + int (*close)(struct nci_spi_dev *ndev); 215 + void (*assert_int)(struct nci_spi_dev *ndev); 216 + void (*deassert_int)(struct nci_spi_dev *ndev); 217 + }; 218 + 219 + struct nci_spi_dev { 220 + struct nci_dev *nci_dev; 221 + struct spi_device *spi; 222 + struct nci_spi_ops *ops; 223 + 224 + unsigned int xfer_udelay; /* microseconds delay between 225 + transactions */ 226 + u8 acknowledge_mode; 227 + 228 + void *driver_data; 229 + }; 230 + 231 + /* ----- NCI SPI Devices ----- */ 232 + struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, 233 + struct nci_spi_ops *ops, 234 + u32 supported_protocols, 235 + u32 supported_se, 236 + u8 acknowledge_mode, 237 + unsigned int delay); 238 + void nci_spi_free_device(struct nci_spi_dev *ndev); 239 + int nci_spi_register_device(struct nci_spi_dev *ndev); 240 + void nci_spi_unregister_device(struct nci_spi_dev *ndev); 241 + 242 + static inline void nci_spi_set_drvdata(struct nci_spi_dev *ndev, 243 + void *data) 244 + { 245 + ndev->driver_data = data; 246 + } 247 + 248 + static inline void *nci_spi_get_drvdata(struct nci_spi_dev *ndev) 249 + { 250 + return ndev->driver_data; 251 + } 205 252 206 253 #endif /* __NCI_CORE_H */
+10
net/nfc/nci/Kconfig
··· 8 8 9 9 Say Y here to compile NCI support into the kernel or say M to 10 10 compile it as module (nci). 11 + 12 + config NFC_NCI_SPI 13 + depends on NFC_NCI && SPI 14 + bool "NCI over SPI protocol support" 15 + default n 16 + help 17 + NCI (NFC Controller Interface) is a communication protocol between 18 + an NFC Controller (NFCC) and a Device Host (DH). 19 + 20 + Say yes if you use an NCI driver that requires SPI link layer.
+2
net/nfc/nci/Makefile
··· 5 5 obj-$(CONFIG_NFC_NCI) += nci.o 6 6 7 7 nci-objs := core.o data.o lib.o ntf.o rsp.o 8 + 9 + nci-$(CONFIG_NFC_NCI_SPI) += spi.o
+136
net/nfc/nci/spi.c
··· 1 + /* 2 + * Copyright (C) 2013 Intel Corporation. All rights reserved. 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms and conditions of the GNU General Public License, 6 + * version 2, as published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope it will be useful, but WITHOUT 9 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 + * more details. 12 + * 13 + * You should have received a copy of the GNU General Public License along with 14 + * this program; if not, write to the Free Software Foundation, Inc., 15 + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 16 + * 17 + */ 18 + 19 + #define pr_fmt(fmt) "nci_spi: %s: " fmt, __func__ 20 + 21 + #include <linux/export.h> 22 + #include <linux/spi/spi.h> 23 + #include <linux/nfc.h> 24 + #include <net/nfc/nci_core.h> 25 + 26 + #define NCI_SPI_HDR_LEN 4 27 + #define NCI_SPI_CRC_LEN 2 28 + 29 + static int nci_spi_open(struct nci_dev *nci_dev) 30 + { 31 + struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); 32 + 33 + return ndev->ops->open(ndev); 34 + } 35 + 36 + static int nci_spi_close(struct nci_dev *nci_dev) 37 + { 38 + struct nci_spi_dev *ndev = nci_get_drvdata(nci_dev); 39 + 40 + return ndev->ops->close(ndev); 41 + } 42 + 43 + static int nci_spi_send(struct nci_dev *nci_dev, struct sk_buff *skb) 44 + { 45 + return 0; 46 + } 47 + 48 + static struct nci_ops nci_spi_ops = { 49 + .open = nci_spi_open, 50 + .close = nci_spi_close, 51 + .send = nci_spi_send, 52 + }; 53 + 54 + /* ---- Interface to NCI SPI drivers ---- */ 55 + 56 + /** 57 + * nci_spi_allocate_device - allocate a new nci spi device 58 + * 59 + * @spi: SPI device 60 + * @ops: device operations 61 + * @supported_protocols: NFC protocols supported by the device 62 + * @supported_se: NFC Secure Elements supported by the device 63 + * @acknowledge_mode: Acknowledge mode used by the device 64 + * @delay: delay between transactions in us 65 + */ 66 + struct nci_spi_dev *nci_spi_allocate_device(struct spi_device *spi, 67 + struct nci_spi_ops *ops, 68 + u32 supported_protocols, 69 + u32 supported_se, 70 + u8 acknowledge_mode, 71 + unsigned int delay) 72 + { 73 + struct nci_spi_dev *ndev; 74 + int tailroom = 0; 75 + 76 + if (!ops->open || !ops->close || !ops->assert_int || !ops->deassert_int) 77 + return NULL; 78 + 79 + if (!supported_protocols) 80 + return NULL; 81 + 82 + ndev = devm_kzalloc(&spi->dev, sizeof(struct nci_dev), GFP_KERNEL); 83 + if (!ndev) 84 + return NULL; 85 + 86 + ndev->ops = ops; 87 + ndev->acknowledge_mode = acknowledge_mode; 88 + ndev->xfer_udelay = delay; 89 + 90 + if (acknowledge_mode == NCI_SPI_CRC_ENABLED) 91 + tailroom += NCI_SPI_CRC_LEN; 92 + 93 + ndev->nci_dev = nci_allocate_device(&nci_spi_ops, supported_protocols, 94 + supported_se, NCI_SPI_HDR_LEN, 95 + tailroom); 96 + if (!ndev->nci_dev) 97 + return NULL; 98 + 99 + nci_set_drvdata(ndev->nci_dev, ndev); 100 + 101 + return ndev; 102 + } 103 + EXPORT_SYMBOL_GPL(nci_spi_allocate_device); 104 + 105 + /** 106 + * nci_spi_free_device - deallocate nci spi device 107 + * 108 + * @ndev: The nci spi device to deallocate 109 + */ 110 + void nci_spi_free_device(struct nci_spi_dev *ndev) 111 + { 112 + nci_free_device(ndev->nci_dev); 113 + } 114 + EXPORT_SYMBOL_GPL(nci_spi_free_device); 115 + 116 + /** 117 + * nci_spi_register_device - register a nci spi device in the nfc subsystem 118 + * 119 + * @pdev: The nci spi device to register 120 + */ 121 + int nci_spi_register_device(struct nci_spi_dev *ndev) 122 + { 123 + return nci_register_device(ndev->nci_dev); 124 + } 125 + EXPORT_SYMBOL_GPL(nci_spi_register_device); 126 + 127 + /** 128 + * nci_spi_unregister_device - unregister a nci spi device in the nfc subsystem 129 + * 130 + * @dev: The nci spi device to unregister 131 + */ 132 + void nci_spi_unregister_device(struct nci_spi_dev *ndev) 133 + { 134 + nci_unregister_device(ndev->nci_dev); 135 + } 136 + EXPORT_SYMBOL_GPL(nci_spi_unregister_device);