16a2968aaSIlan Elias /* 26a2968aaSIlan Elias * The NFC Controller Interface is the communication protocol between an 36a2968aaSIlan Elias * NFC Controller (NFCC) and a Device Host (DH). 46a2968aaSIlan Elias * 56a2968aaSIlan Elias * Copyright (C) 2011 Texas Instruments, Inc. 68a00a61bSFrederic Danis * Copyright (C) 2013 Intel Corporation. All rights reserved. 7a99903ecSJulien Lefrique * Copyright (C) 2014 Marvell International Ltd. 86a2968aaSIlan Elias * 96a2968aaSIlan Elias * Written by Ilan Elias <ilane@ti.com> 106a2968aaSIlan Elias * 116a2968aaSIlan Elias * Acknowledgements: 126a2968aaSIlan Elias * This file is based on hci_core.h, which was written 136a2968aaSIlan Elias * by Maxim Krasnyansky. 146a2968aaSIlan Elias * 156a2968aaSIlan Elias * This program is free software; you can redistribute it and/or modify 166a2968aaSIlan Elias * it under the terms of the GNU General Public License version 2 176a2968aaSIlan Elias * as published by the Free Software Foundation 186a2968aaSIlan Elias * 196a2968aaSIlan Elias * This program is distributed in the hope that it will be useful, 206a2968aaSIlan Elias * but WITHOUT ANY WARRANTY; without even the implied warranty of 216a2968aaSIlan Elias * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 226a2968aaSIlan Elias * GNU General Public License for more details. 236a2968aaSIlan Elias * 246a2968aaSIlan Elias * You should have received a copy of the GNU General Public License 25a6227e26SJeff Kirsher * along with this program; if not, see <http://www.gnu.org/licenses/>. 266a2968aaSIlan Elias * 276a2968aaSIlan Elias */ 286a2968aaSIlan Elias 296a2968aaSIlan Elias #ifndef __NCI_CORE_H 306a2968aaSIlan Elias #define __NCI_CORE_H 316a2968aaSIlan Elias 326a2968aaSIlan Elias #include <linux/interrupt.h> 336a2968aaSIlan Elias #include <linux/skbuff.h> 346a2968aaSIlan Elias 356a2968aaSIlan Elias #include <net/nfc/nfc.h> 366a2968aaSIlan Elias #include <net/nfc/nci.h> 376a2968aaSIlan Elias 388939e47fSIlan Elias /* NCI device flags */ 398939e47fSIlan Elias enum nci_flag { 406a2968aaSIlan Elias NCI_INIT, 416a2968aaSIlan Elias NCI_UP, 4238f04c6bSIlan Elias NCI_DATA_EXCHANGE, 43c4bf98b2SIlan Elias NCI_DATA_EXCHANGE_TO, 446a2968aaSIlan Elias }; 456a2968aaSIlan Elias 468939e47fSIlan Elias /* NCI device states */ 478939e47fSIlan Elias enum nci_state { 488939e47fSIlan Elias NCI_IDLE, 498939e47fSIlan Elias NCI_DISCOVERY, 50019c4fbaSIlan Elias NCI_W4_ALL_DISCOVERIES, 51019c4fbaSIlan Elias NCI_W4_HOST_SELECT, 528939e47fSIlan Elias NCI_POLL_ACTIVE, 53a99903ecSJulien Lefrique NCI_LISTEN_ACTIVE, 54a99903ecSJulien Lefrique NCI_LISTEN_SLEEP, 558939e47fSIlan Elias }; 568939e47fSIlan Elias 576a2968aaSIlan Elias /* NCI timeouts */ 586a2968aaSIlan Elias #define NCI_RESET_TIMEOUT 5000 596a2968aaSIlan Elias #define NCI_INIT_TIMEOUT 5000 607e035230SIlan Elias #define NCI_SET_CONFIG_TIMEOUT 5000 616a2968aaSIlan Elias #define NCI_RF_DISC_TIMEOUT 5000 62019c4fbaSIlan Elias #define NCI_RF_DISC_SELECT_TIMEOUT 5000 6311ee5158SIlan Elias #define NCI_RF_DEACTIVATE_TIMEOUT 30000 646a2968aaSIlan Elias #define NCI_CMD_TIMEOUT 5000 65c4bf98b2SIlan Elias #define NCI_DATA_TIMEOUT 700 666a2968aaSIlan Elias 676a2968aaSIlan Elias struct nci_dev; 686a2968aaSIlan Elias 696a2968aaSIlan Elias struct nci_ops { 706a2968aaSIlan Elias int (*open)(struct nci_dev *ndev); 716a2968aaSIlan Elias int (*close)(struct nci_dev *ndev); 721095e69fSFrederic Danis int (*send)(struct nci_dev *ndev, struct sk_buff *skb); 7386e8586eSAmitkumar Karwar int (*setup)(struct nci_dev *ndev); 749e87f9a9SChristophe Ricard __u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol); 75ba4db551SChristophe Ricard int (*discover_se)(struct nci_dev *ndev); 766a2968aaSIlan Elias }; 776a2968aaSIlan Elias 786a2968aaSIlan Elias #define NCI_MAX_SUPPORTED_RF_INTERFACES 4 79019c4fbaSIlan Elias #define NCI_MAX_DISCOVERED_TARGETS 10 806a2968aaSIlan Elias 816a2968aaSIlan Elias /* NCI Core structures */ 826a2968aaSIlan Elias struct nci_dev { 836a2968aaSIlan Elias struct nfc_dev *nfc_dev; 846a2968aaSIlan Elias struct nci_ops *ops; 856a2968aaSIlan Elias 866a2968aaSIlan Elias int tx_headroom; 876a2968aaSIlan Elias int tx_tailroom; 886a2968aaSIlan Elias 898939e47fSIlan Elias atomic_t state; 906a2968aaSIlan Elias unsigned long flags; 916a2968aaSIlan Elias 926a2968aaSIlan Elias atomic_t cmd_cnt; 936a2968aaSIlan Elias atomic_t credits_cnt; 946a2968aaSIlan Elias 956a2968aaSIlan Elias struct timer_list cmd_timer; 96c4bf98b2SIlan Elias struct timer_list data_timer; 976a2968aaSIlan Elias 986a2968aaSIlan Elias struct workqueue_struct *cmd_wq; 996a2968aaSIlan Elias struct work_struct cmd_work; 1006a2968aaSIlan Elias 1016a2968aaSIlan Elias struct workqueue_struct *rx_wq; 1026a2968aaSIlan Elias struct work_struct rx_work; 1036a2968aaSIlan Elias 1046a2968aaSIlan Elias struct workqueue_struct *tx_wq; 1056a2968aaSIlan Elias struct work_struct tx_work; 1066a2968aaSIlan Elias 1076a2968aaSIlan Elias struct sk_buff_head cmd_q; 1086a2968aaSIlan Elias struct sk_buff_head rx_q; 1096a2968aaSIlan Elias struct sk_buff_head tx_q; 1106a2968aaSIlan Elias 1116a2968aaSIlan Elias struct mutex req_lock; 1126a2968aaSIlan Elias struct completion req_completion; 1136a2968aaSIlan Elias __u32 req_status; 1146a2968aaSIlan Elias __u32 req_result; 1156a2968aaSIlan Elias 1166a2968aaSIlan Elias void *driver_data; 1176a2968aaSIlan Elias 1186a2968aaSIlan Elias __u32 poll_prots; 1196a2968aaSIlan Elias __u32 target_active_prot; 1206a2968aaSIlan Elias 121019c4fbaSIlan Elias struct nfc_target targets[NCI_MAX_DISCOVERED_TARGETS]; 122019c4fbaSIlan Elias int n_targets; 123019c4fbaSIlan Elias 1246a2968aaSIlan Elias /* received during NCI_OP_CORE_RESET_RSP */ 1256a2968aaSIlan Elias __u8 nci_ver; 1266a2968aaSIlan Elias 1276a2968aaSIlan Elias /* received during NCI_OP_CORE_INIT_RSP */ 1286a2968aaSIlan Elias __u32 nfcc_features; 1296a2968aaSIlan Elias __u8 num_supported_rf_interfaces; 1306a2968aaSIlan Elias __u8 supported_rf_interfaces 1316a2968aaSIlan Elias [NCI_MAX_SUPPORTED_RF_INTERFACES]; 1326a2968aaSIlan Elias __u8 max_logical_connections; 1336a2968aaSIlan Elias __u16 max_routing_table_size; 134e8c0dacdSIlan Elias __u8 max_ctrl_pkt_payload_len; 135e8c0dacdSIlan Elias __u16 max_size_for_large_params; 136e8c0dacdSIlan Elias __u8 manufact_id; 137e8c0dacdSIlan Elias __u32 manufact_specific_info; 1386a2968aaSIlan Elias 139637d85a7SIlan Elias /* received during NCI_OP_RF_INTF_ACTIVATED_NTF */ 140637d85a7SIlan Elias __u8 max_data_pkt_payload_size; 141637d85a7SIlan Elias __u8 initial_num_credits; 142637d85a7SIlan Elias 1436a2968aaSIlan Elias /* stored during nci_data_exchange */ 1446a2968aaSIlan Elias data_exchange_cb_t data_exchange_cb; 1456a2968aaSIlan Elias void *data_exchange_cb_context; 1466a2968aaSIlan Elias struct sk_buff *rx_data_reassembly; 147767f19aeSIlan Elias 148767f19aeSIlan Elias /* stored during intf_activated_ntf */ 149767f19aeSIlan Elias __u8 remote_gb[NFC_MAX_GT_LEN]; 150767f19aeSIlan Elias __u8 remote_gb_len; 1516a2968aaSIlan Elias }; 1526a2968aaSIlan Elias 1536a2968aaSIlan Elias /* ----- NCI Devices ----- */ 1546a2968aaSIlan Elias struct nci_dev *nci_allocate_device(struct nci_ops *ops, 1556a2968aaSIlan Elias __u32 supported_protocols, 1566a2968aaSIlan Elias int tx_headroom, 1576a2968aaSIlan Elias int tx_tailroom); 1586a2968aaSIlan Elias void nci_free_device(struct nci_dev *ndev); 1596a2968aaSIlan Elias int nci_register_device(struct nci_dev *ndev); 1606a2968aaSIlan Elias void nci_unregister_device(struct nci_dev *ndev); 1611095e69fSFrederic Danis int nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb); 16222c15bf3SAmitkumar Karwar int nci_set_config(struct nci_dev *ndev, __u8 id, size_t len, __u8 *val); 1636a2968aaSIlan Elias 1646a2968aaSIlan Elias static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev, 1656a2968aaSIlan Elias unsigned int len, 1666a2968aaSIlan Elias gfp_t how) 1676a2968aaSIlan Elias { 1686a2968aaSIlan Elias struct sk_buff *skb; 1696a2968aaSIlan Elias 1706a2968aaSIlan Elias skb = alloc_skb(len + ndev->tx_headroom + ndev->tx_tailroom, how); 1716a2968aaSIlan Elias if (skb) 1726a2968aaSIlan Elias skb_reserve(skb, ndev->tx_headroom); 1736a2968aaSIlan Elias 1746a2968aaSIlan Elias return skb; 1756a2968aaSIlan Elias } 1766a2968aaSIlan Elias 1776a2968aaSIlan Elias static inline void nci_set_parent_dev(struct nci_dev *ndev, struct device *dev) 1786a2968aaSIlan Elias { 1796a2968aaSIlan Elias nfc_set_parent_dev(ndev->nfc_dev, dev); 1806a2968aaSIlan Elias } 1816a2968aaSIlan Elias 1826a2968aaSIlan Elias static inline void nci_set_drvdata(struct nci_dev *ndev, void *data) 1836a2968aaSIlan Elias { 1846a2968aaSIlan Elias ndev->driver_data = data; 1856a2968aaSIlan Elias } 1866a2968aaSIlan Elias 1876a2968aaSIlan Elias static inline void *nci_get_drvdata(struct nci_dev *ndev) 1886a2968aaSIlan Elias { 1896a2968aaSIlan Elias return ndev->driver_data; 1906a2968aaSIlan Elias } 1916a2968aaSIlan Elias 1926a2968aaSIlan Elias void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb); 1936a2968aaSIlan Elias void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb); 1946a2968aaSIlan Elias void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb); 1956a2968aaSIlan Elias int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload); 1966a2968aaSIlan Elias int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb); 1976a2968aaSIlan Elias void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb, 1986a2968aaSIlan Elias int err); 199019c4fbaSIlan Elias void nci_clear_target_list(struct nci_dev *ndev); 2006a2968aaSIlan Elias 2016a2968aaSIlan Elias /* ----- NCI requests ----- */ 2026a2968aaSIlan Elias #define NCI_REQ_DONE 0 2036a2968aaSIlan Elias #define NCI_REQ_PEND 1 2046a2968aaSIlan Elias #define NCI_REQ_CANCELED 2 2056a2968aaSIlan Elias 2066a2968aaSIlan Elias void nci_req_complete(struct nci_dev *ndev, int result); 2076a2968aaSIlan Elias 2086a2968aaSIlan Elias /* ----- NCI status code ----- */ 2096a2968aaSIlan Elias int nci_to_errno(__u8 code); 2106a2968aaSIlan Elias 2118a00a61bSFrederic Danis /* ----- NCI over SPI acknowledge modes ----- */ 2128a00a61bSFrederic Danis #define NCI_SPI_CRC_DISABLED 0x00 2138a00a61bSFrederic Danis #define NCI_SPI_CRC_ENABLED 0x01 2148a00a61bSFrederic Danis 2158a00a61bSFrederic Danis /* ----- NCI SPI structures ----- */ 216fa544fffSEric Lapuyade struct nci_spi { 217d5937511SEric Lapuyade struct nci_dev *ndev; 2188a00a61bSFrederic Danis struct spi_device *spi; 2198a00a61bSFrederic Danis 2208a00a61bSFrederic Danis unsigned int xfer_udelay; /* microseconds delay between 2218a00a61bSFrederic Danis transactions */ 2228a00a61bSFrederic Danis u8 acknowledge_mode; 2238a00a61bSFrederic Danis 224ee9596d4SFrederic Danis struct completion req_completion; 225ee9596d4SFrederic Danis u8 req_result; 2268a00a61bSFrederic Danis }; 2278a00a61bSFrederic Danis 228fa544fffSEric Lapuyade /* ----- NCI SPI ----- */ 229fa544fffSEric Lapuyade struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, 230fa544fffSEric Lapuyade u8 acknowledge_mode, unsigned int delay, 231fa544fffSEric Lapuyade struct nci_dev *ndev); 2322bed2785SEric Lapuyade int nci_spi_send(struct nci_spi *nspi, 2332bed2785SEric Lapuyade struct completion *write_handshake_completion, 2342bed2785SEric Lapuyade struct sk_buff *skb); 23522d4aae5SEric Lapuyade struct sk_buff *nci_spi_read(struct nci_spi *nspi); 2368a00a61bSFrederic Danis 2376a2968aaSIlan Elias #endif /* __NCI_CORE_H */ 238