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

NFC: mei: Add a common mei bus API for NFC drivers

This isolates the common code that is required to use an mei bus nfc
device from an NFC HCI drivers. This prepares for future drivers for
NFC chips connected behind an Intel Management Engine controller.
The microread_mei HCI driver is also modified to use that common code.

Signed-off-by: Eric Lapuyade <eric.lapuyade@intel.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Eric Lapuyade and committed by
Samuel Ortiz
4912e2fe be055b2f

+215 -131
+10
drivers/nfc/Kconfig
··· 26 26 Say Y here to compile support for Texas Instrument's NFC WiLink driver 27 27 into the kernel or say M to compile it as module. 28 28 29 + config NFC_MEI_PHY 30 + tristate "MEI bus NFC device support" 31 + depends on INTEL_MEI_BUS_NFC && NFC_HCI 32 + help 33 + This adds support to use an mei bus nfc device. Select this if you 34 + will use an HCI NFC driver for an NFC chip connected behind an 35 + Intel's Management Engine chip. 36 + 37 + If unsure, say N. 38 + 29 39 source "drivers/nfc/pn544/Kconfig" 30 40 source "drivers/nfc/microread/Kconfig" 31 41
+1
drivers/nfc/Makefile
··· 6 6 obj-$(CONFIG_NFC_MICROREAD) += microread/ 7 7 obj-$(CONFIG_NFC_PN533) += pn533.o 8 8 obj-$(CONFIG_NFC_WILINK) += nfcwilink.o 9 + obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o 9 10 10 11 ccflags-$(CONFIG_NFC_DEBUG) := -DDEBUG
+164
drivers/nfc/mei_phy.c
··· 1 + /* 2 + * MEI Library for mei bus nfc device access 3 + * 4 + * Copyright (C) 2013 Intel Corporation. All rights reserved. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope that it will be useful, 11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 + * GNU General Public License for more details. 14 + * 15 + * You should have received a copy of the GNU General Public License 16 + * along with this program; if not, write to the 17 + * Free Software Foundation, Inc., 18 + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 + */ 20 + 21 + #include <linux/module.h> 22 + #include <linux/slab.h> 23 + #include <linux/nfc.h> 24 + 25 + #include "mei_phy.h" 26 + 27 + struct mei_nfc_hdr { 28 + u8 cmd; 29 + u8 status; 30 + u16 req_id; 31 + u32 reserved; 32 + u16 data_size; 33 + } __attribute__((packed)); 34 + 35 + #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) 36 + 37 + #define MEI_DUMP_SKB_IN(info, skb) \ 38 + do { \ 39 + pr_debug("%s:\n", info); \ 40 + print_hex_dump_debug("mei in : ", DUMP_PREFIX_OFFSET, \ 41 + 16, 1, (skb)->data, (skb)->len, false); \ 42 + } while (0) 43 + 44 + #define MEI_DUMP_SKB_OUT(info, skb) \ 45 + do { \ 46 + pr_debug("%s:\n", info); \ 47 + print_hex_dump_debug("mei out: ", DUMP_PREFIX_OFFSET, \ 48 + 16, 1, (skb)->data, (skb)->len, false); \ 49 + } while (0) 50 + 51 + int nfc_mei_phy_enable(void *phy_id) 52 + { 53 + int r; 54 + struct nfc_mei_phy *phy = phy_id; 55 + 56 + pr_info("%s\n", __func__); 57 + 58 + if (phy->powered == 1) 59 + return 0; 60 + 61 + r = mei_cl_enable_device(phy->device); 62 + if (r < 0) { 63 + pr_err("MEI_PHY: Could not enable device\n"); 64 + return r; 65 + } 66 + 67 + phy->powered = 1; 68 + 69 + return 0; 70 + } 71 + EXPORT_SYMBOL_GPL(nfc_mei_phy_enable); 72 + 73 + void nfc_mei_phy_disable(void *phy_id) 74 + { 75 + struct nfc_mei_phy *phy = phy_id; 76 + 77 + pr_info("%s\n", __func__); 78 + 79 + mei_cl_disable_device(phy->device); 80 + 81 + phy->powered = 0; 82 + } 83 + EXPORT_SYMBOL_GPL(nfc_mei_phy_disable); 84 + 85 + /* 86 + * Writing a frame must not return the number of written bytes. 87 + * It must return either zero for success, or <0 for error. 88 + * In addition, it must not alter the skb 89 + */ 90 + static int nfc_mei_phy_write(void *phy_id, struct sk_buff *skb) 91 + { 92 + struct nfc_mei_phy *phy = phy_id; 93 + int r; 94 + 95 + MEI_DUMP_SKB_OUT("mei frame sent", skb); 96 + 97 + r = mei_cl_send(phy->device, skb->data, skb->len); 98 + if (r > 0) 99 + r = 0; 100 + 101 + return r; 102 + } 103 + 104 + void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context) 105 + { 106 + struct nfc_mei_phy *phy = context; 107 + 108 + if (phy->hard_fault != 0) 109 + return; 110 + 111 + if (events & BIT(MEI_CL_EVENT_RX)) { 112 + struct sk_buff *skb; 113 + int reply_size; 114 + 115 + skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL); 116 + if (!skb) 117 + return; 118 + 119 + reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ); 120 + if (reply_size < MEI_NFC_HEADER_SIZE) { 121 + kfree(skb); 122 + return; 123 + } 124 + 125 + skb_put(skb, reply_size); 126 + skb_pull(skb, MEI_NFC_HEADER_SIZE); 127 + 128 + MEI_DUMP_SKB_IN("mei frame read", skb); 129 + 130 + nfc_hci_recv_frame(phy->hdev, skb); 131 + } 132 + } 133 + EXPORT_SYMBOL_GPL(nfc_mei_event_cb); 134 + 135 + struct nfc_phy_ops mei_phy_ops = { 136 + .write = nfc_mei_phy_write, 137 + .enable = nfc_mei_phy_enable, 138 + .disable = nfc_mei_phy_disable, 139 + }; 140 + EXPORT_SYMBOL_GPL(mei_phy_ops); 141 + 142 + struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device) 143 + { 144 + struct nfc_mei_phy *phy; 145 + 146 + phy = kzalloc(sizeof(struct nfc_mei_phy), GFP_KERNEL); 147 + if (!phy) 148 + return NULL; 149 + 150 + phy->device = device; 151 + mei_cl_set_drvdata(device, phy); 152 + 153 + return phy; 154 + } 155 + EXPORT_SYMBOL_GPL(nfc_mei_phy_alloc); 156 + 157 + void nfc_mei_phy_free(struct nfc_mei_phy *phy) 158 + { 159 + kfree(phy); 160 + } 161 + EXPORT_SYMBOL_GPL(nfc_mei_phy_free); 162 + 163 + MODULE_LICENSE("GPL"); 164 + MODULE_DESCRIPTION("mei bus NFC device interface");
+30
drivers/nfc/mei_phy.h
··· 1 + #ifndef __LOCAL_MEI_PHY_H_ 2 + #define __LOCAL_MEI_PHY_H_ 3 + 4 + #include <linux/mei_cl_bus.h> 5 + #include <net/nfc/hci.h> 6 + 7 + #define MEI_NFC_HEADER_SIZE 10 8 + #define MEI_NFC_MAX_HCI_PAYLOAD 300 9 + 10 + struct nfc_mei_phy { 11 + struct mei_cl_device *device; 12 + struct nfc_hci_dev *hdev; 13 + 14 + int powered; 15 + 16 + int hard_fault; /* 17 + * < 0 if hardware error occured 18 + * and prevents normal operation. 19 + */ 20 + }; 21 + 22 + extern struct nfc_phy_ops mei_phy_ops; 23 + 24 + int nfc_mei_phy_enable(void *phy_id); 25 + void nfc_mei_phy_disable(void *phy_id); 26 + void nfc_mei_event_cb(struct mei_cl_device *device, u32 events, void *context); 27 + struct nfc_mei_phy *nfc_mei_phy_alloc(struct mei_cl_device *device); 28 + void nfc_mei_phy_free(struct nfc_mei_phy *phy); 29 + 30 + #endif /* __LOCAL_MEI_PHY_H_ */
+1 -1
drivers/nfc/microread/Kconfig
··· 25 25 26 26 config NFC_MICROREAD_MEI 27 27 tristate "NFC Microread MEI support" 28 - depends on NFC_MICROREAD && INTEL_MEI_BUS_NFC 28 + depends on NFC_MICROREAD && NFC_MEI_PHY 29 29 ---help--- 30 30 This module adds support for the mei interface of adapters using 31 31 Inside microread chipsets. Select this if your microread chipset
+9 -130
drivers/nfc/microread/mei.c
··· 19 19 */ 20 20 21 21 #include <linux/module.h> 22 - #include <linux/slab.h> 23 - #include <linux/interrupt.h> 24 - #include <linux/gpio.h> 25 - #include <linux/mei_cl_bus.h> 26 - 22 + #include <linux/mod_devicetable.h> 27 23 #include <linux/nfc.h> 28 24 #include <net/nfc/hci.h> 29 25 #include <net/nfc/llc.h> 30 26 27 + #include "../mei_phy.h" 31 28 #include "microread.h" 32 29 33 30 #define MICROREAD_DRIVER_NAME "microread" 34 31 35 - struct mei_nfc_hdr { 36 - u8 cmd; 37 - u8 status; 38 - u16 req_id; 39 - u32 reserved; 40 - u16 data_size; 41 - } __attribute__((packed)); 42 - 43 - #define MEI_NFC_HEADER_SIZE 10 44 - #define MEI_NFC_MAX_HCI_PAYLOAD 300 45 - #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD) 46 - 47 - struct microread_mei_phy { 48 - struct mei_cl_device *device; 49 - struct nfc_hci_dev *hdev; 50 - 51 - int powered; 52 - 53 - int hard_fault; /* 54 - * < 0 if hardware error occured (e.g. i2c err) 55 - * and prevents normal operation. 56 - */ 57 - }; 58 - 59 - #define MEI_DUMP_SKB_IN(info, skb) \ 60 - do { \ 61 - pr_debug("%s:\n", info); \ 62 - print_hex_dump(KERN_DEBUG, "mei in : ", DUMP_PREFIX_OFFSET, \ 63 - 16, 1, (skb)->data, (skb)->len, 0); \ 64 - } while (0) 65 - 66 - #define MEI_DUMP_SKB_OUT(info, skb) \ 67 - do { \ 68 - pr_debug("%s:\n", info); \ 69 - print_hex_dump(KERN_DEBUG, "mei out: ", DUMP_PREFIX_OFFSET, \ 70 - 16, 1, (skb)->data, (skb)->len, 0); \ 71 - } while (0) 72 - 73 - static int microread_mei_enable(void *phy_id) 74 - { 75 - struct microread_mei_phy *phy = phy_id; 76 - 77 - pr_info(DRIVER_DESC ": %s\n", __func__); 78 - 79 - phy->powered = 1; 80 - 81 - return 0; 82 - } 83 - 84 - static void microread_mei_disable(void *phy_id) 85 - { 86 - struct microread_mei_phy *phy = phy_id; 87 - 88 - pr_info(DRIVER_DESC ": %s\n", __func__); 89 - 90 - phy->powered = 0; 91 - } 92 - 93 - /* 94 - * Writing a frame must not return the number of written bytes. 95 - * It must return either zero for success, or <0 for error. 96 - * In addition, it must not alter the skb 97 - */ 98 - static int microread_mei_write(void *phy_id, struct sk_buff *skb) 99 - { 100 - struct microread_mei_phy *phy = phy_id; 101 - int r; 102 - 103 - MEI_DUMP_SKB_OUT("mei frame sent", skb); 104 - 105 - r = mei_cl_send(phy->device, skb->data, skb->len); 106 - if (r > 0) 107 - r = 0; 108 - 109 - return r; 110 - } 111 - 112 - static void microread_event_cb(struct mei_cl_device *device, u32 events, 113 - void *context) 114 - { 115 - struct microread_mei_phy *phy = context; 116 - 117 - if (phy->hard_fault != 0) 118 - return; 119 - 120 - if (events & BIT(MEI_CL_EVENT_RX)) { 121 - struct sk_buff *skb; 122 - int reply_size; 123 - 124 - skb = alloc_skb(MEI_NFC_MAX_READ, GFP_KERNEL); 125 - if (!skb) 126 - return; 127 - 128 - reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ); 129 - if (reply_size < MEI_NFC_HEADER_SIZE) { 130 - kfree(skb); 131 - return; 132 - } 133 - 134 - skb_put(skb, reply_size); 135 - skb_pull(skb, MEI_NFC_HEADER_SIZE); 136 - 137 - MEI_DUMP_SKB_IN("mei frame read", skb); 138 - 139 - nfc_hci_recv_frame(phy->hdev, skb); 140 - } 141 - } 142 - 143 - static struct nfc_phy_ops mei_phy_ops = { 144 - .write = microread_mei_write, 145 - .enable = microread_mei_enable, 146 - .disable = microread_mei_disable, 147 - }; 148 - 149 32 static int microread_mei_probe(struct mei_cl_device *device, 150 33 const struct mei_cl_device_id *id) 151 34 { 152 - struct microread_mei_phy *phy; 35 + struct nfc_mei_phy *phy; 153 36 int r; 154 37 155 38 pr_info("Probing NFC microread\n"); 156 39 157 - phy = kzalloc(sizeof(struct microread_mei_phy), GFP_KERNEL); 40 + phy = nfc_mei_phy_alloc(device); 158 41 if (!phy) { 159 42 pr_err("Cannot allocate memory for microread mei phy.\n"); 160 43 return -ENOMEM; 161 44 } 162 45 163 - phy->device = device; 164 - mei_cl_set_drvdata(device, phy); 165 - 166 - r = mei_cl_register_event_cb(device, microread_event_cb, phy); 46 + r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy); 167 47 if (r) { 168 48 pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n"); 169 49 goto err_out; ··· 58 178 return 0; 59 179 60 180 err_out: 61 - kfree(phy); 181 + nfc_mei_phy_free(phy); 62 182 63 183 return r; 64 184 } 65 185 66 186 static int microread_mei_remove(struct mei_cl_device *device) 67 187 { 68 - struct microread_mei_phy *phy = mei_cl_get_drvdata(device); 188 + struct nfc_mei_phy *phy = mei_cl_get_drvdata(device); 69 189 70 190 pr_info("Removing microread\n"); 71 191 72 192 microread_remove(phy->hdev); 73 193 74 - if (phy->powered) 75 - microread_mei_disable(phy); 194 + nfc_mei_phy_disable(phy); 76 195 77 - kfree(phy); 196 + nfc_mei_phy_free(phy); 78 197 79 198 return 0; 80 199 }