197f18414SEric Lapuyade /* 297f18414SEric Lapuyade * HCI based Driver for NXP PN544 NFC Chip 397f18414SEric Lapuyade * 497f18414SEric Lapuyade * Copyright (C) 2012 Intel Corporation. All rights reserved. 597f18414SEric Lapuyade * 697f18414SEric Lapuyade * This program is free software; you can redistribute it and/or modify it 797f18414SEric Lapuyade * under the terms and conditions of the GNU General Public License, 897f18414SEric Lapuyade * version 2, as published by the Free Software Foundation. 997f18414SEric Lapuyade * 1097f18414SEric Lapuyade * This program is distributed in the hope that it will be useful, 1197f18414SEric Lapuyade * but WITHOUT ANY WARRANTY; without even the implied warranty of 1297f18414SEric Lapuyade * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1397f18414SEric Lapuyade * GNU General Public License for more details. 1497f18414SEric Lapuyade * 1597f18414SEric Lapuyade * You should have received a copy of the GNU General Public License 1697f18414SEric Lapuyade * along with this program; if not, write to the 1797f18414SEric Lapuyade * Free Software Foundation, Inc., 1897f18414SEric Lapuyade * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1997f18414SEric Lapuyade */ 2097f18414SEric Lapuyade 2197f18414SEric Lapuyade #include <linux/delay.h> 2297f18414SEric Lapuyade #include <linux/slab.h> 2397f18414SEric Lapuyade 2497f18414SEric Lapuyade #include <linux/nfc.h> 2597f18414SEric Lapuyade #include <net/nfc/hci.h> 2697f18414SEric Lapuyade #include <net/nfc/llc.h> 2797f18414SEric Lapuyade 2897f18414SEric Lapuyade #include "pn544.h" 2997f18414SEric Lapuyade 3097f18414SEric Lapuyade /* Timing restrictions (ms) */ 3197f18414SEric Lapuyade #define PN544_HCI_RESETVEN_TIME 30 3297f18414SEric Lapuyade 3397f18414SEric Lapuyade #define HCI_MODE 0 3497f18414SEric Lapuyade #define FW_MODE 1 3597f18414SEric Lapuyade 3697f18414SEric Lapuyade enum pn544_state { 3797f18414SEric Lapuyade PN544_ST_COLD, 3897f18414SEric Lapuyade PN544_ST_FW_READY, 3997f18414SEric Lapuyade PN544_ST_READY, 4097f18414SEric Lapuyade }; 4197f18414SEric Lapuyade 4297f18414SEric Lapuyade #define FULL_VERSION_LEN 11 4397f18414SEric Lapuyade 4497f18414SEric Lapuyade /* Proprietary commands */ 4597f18414SEric Lapuyade #define PN544_WRITE 0x3f 4697f18414SEric Lapuyade 4797f18414SEric Lapuyade /* Proprietary gates, events, commands and registers */ 4897f18414SEric Lapuyade 4997f18414SEric Lapuyade /* NFC_HCI_RF_READER_A_GATE additional registers and commands */ 5097f18414SEric Lapuyade #define PN544_RF_READER_A_AUTO_ACTIVATION 0x10 5197f18414SEric Lapuyade #define PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION 0x12 5297f18414SEric Lapuyade #define PN544_MIFARE_CMD 0x21 5397f18414SEric Lapuyade 5497f18414SEric Lapuyade /* Commands that apply to all RF readers */ 5597f18414SEric Lapuyade #define PN544_RF_READER_CMD_PRESENCE_CHECK 0x30 5697f18414SEric Lapuyade #define PN544_RF_READER_CMD_ACTIVATE_NEXT 0x32 5797f18414SEric Lapuyade 5897f18414SEric Lapuyade /* NFC_HCI_ID_MGMT_GATE additional registers */ 5997f18414SEric Lapuyade #define PN544_ID_MGMT_FULL_VERSION_SW 0x10 6097f18414SEric Lapuyade 6197f18414SEric Lapuyade #define PN544_RF_READER_ISO15693_GATE 0x12 6297f18414SEric Lapuyade 6397f18414SEric Lapuyade #define PN544_RF_READER_F_GATE 0x14 6497f18414SEric Lapuyade #define PN544_FELICA_ID 0x04 6597f18414SEric Lapuyade #define PN544_FELICA_RAW 0x20 6697f18414SEric Lapuyade 6797f18414SEric Lapuyade #define PN544_RF_READER_JEWEL_GATE 0x15 6897f18414SEric Lapuyade #define PN544_JEWEL_RAW_CMD 0x23 6997f18414SEric Lapuyade 7097f18414SEric Lapuyade #define PN544_RF_READER_NFCIP1_INITIATOR_GATE 0x30 7197f18414SEric Lapuyade #define PN544_RF_READER_NFCIP1_TARGET_GATE 0x31 7297f18414SEric Lapuyade 7397f18414SEric Lapuyade #define PN544_SYS_MGMT_GATE 0x90 7497f18414SEric Lapuyade #define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02 7597f18414SEric Lapuyade 7697f18414SEric Lapuyade #define PN544_POLLING_LOOP_MGMT_GATE 0x94 7797f18414SEric Lapuyade #define PN544_DEP_MODE 0x01 7897f18414SEric Lapuyade #define PN544_DEP_ATR_REQ 0x02 7997f18414SEric Lapuyade #define PN544_DEP_ATR_RES 0x03 8097f18414SEric Lapuyade #define PN544_DEP_MERGE 0x0D 8197f18414SEric Lapuyade #define PN544_PL_RDPHASES 0x06 8297f18414SEric Lapuyade #define PN544_PL_EMULATION 0x07 8397f18414SEric Lapuyade #define PN544_PL_NFCT_DEACTIVATED 0x09 8497f18414SEric Lapuyade 8597f18414SEric Lapuyade #define PN544_SWP_MGMT_GATE 0xA0 8697f18414SEric Lapuyade 8797f18414SEric Lapuyade #define PN544_NFC_WI_MGMT_GATE 0xA1 8897f18414SEric Lapuyade 8997f18414SEric Lapuyade #define PN544_HCI_EVT_SND_DATA 0x01 9097f18414SEric Lapuyade #define PN544_HCI_EVT_ACTIVATED 0x02 9197f18414SEric Lapuyade #define PN544_HCI_EVT_DEACTIVATED 0x03 9297f18414SEric Lapuyade #define PN544_HCI_EVT_RCV_DATA 0x04 9397f18414SEric Lapuyade #define PN544_HCI_EVT_CONTINUE_MI 0x05 9497f18414SEric Lapuyade 9597f18414SEric Lapuyade #define PN544_HCI_CMD_ATTREQUEST 0x12 9697f18414SEric Lapuyade #define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13 9797f18414SEric Lapuyade 9897f18414SEric Lapuyade static struct nfc_hci_gate pn544_gates[] = { 9997f18414SEric Lapuyade {NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE}, 10097f18414SEric Lapuyade {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE}, 10197f18414SEric Lapuyade {NFC_HCI_ID_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10297f18414SEric Lapuyade {NFC_HCI_LINK_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10397f18414SEric Lapuyade {NFC_HCI_RF_READER_B_GATE, NFC_HCI_INVALID_PIPE}, 10497f18414SEric Lapuyade {NFC_HCI_RF_READER_A_GATE, NFC_HCI_INVALID_PIPE}, 10597f18414SEric Lapuyade {PN544_SYS_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10697f18414SEric Lapuyade {PN544_SWP_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10797f18414SEric Lapuyade {PN544_POLLING_LOOP_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10897f18414SEric Lapuyade {PN544_NFC_WI_MGMT_GATE, NFC_HCI_INVALID_PIPE}, 10997f18414SEric Lapuyade {PN544_RF_READER_F_GATE, NFC_HCI_INVALID_PIPE}, 11097f18414SEric Lapuyade {PN544_RF_READER_JEWEL_GATE, NFC_HCI_INVALID_PIPE}, 11197f18414SEric Lapuyade {PN544_RF_READER_ISO15693_GATE, NFC_HCI_INVALID_PIPE}, 11297f18414SEric Lapuyade {PN544_RF_READER_NFCIP1_INITIATOR_GATE, NFC_HCI_INVALID_PIPE}, 11397f18414SEric Lapuyade {PN544_RF_READER_NFCIP1_TARGET_GATE, NFC_HCI_INVALID_PIPE} 11497f18414SEric Lapuyade }; 11597f18414SEric Lapuyade 11697f18414SEric Lapuyade /* Largest headroom needed for outgoing custom commands */ 11797f18414SEric Lapuyade #define PN544_CMDS_HEADROOM 2 11897f18414SEric Lapuyade 11997f18414SEric Lapuyade struct pn544_hci_info { 12097f18414SEric Lapuyade struct nfc_phy_ops *phy_ops; 12197f18414SEric Lapuyade void *phy_id; 12297f18414SEric Lapuyade 12397f18414SEric Lapuyade struct nfc_hci_dev *hdev; 12497f18414SEric Lapuyade 12597f18414SEric Lapuyade enum pn544_state state; 12697f18414SEric Lapuyade 12797f18414SEric Lapuyade struct mutex info_lock; 12897f18414SEric Lapuyade 12997f18414SEric Lapuyade int async_cb_type; 13097f18414SEric Lapuyade data_exchange_cb_t async_cb; 13197f18414SEric Lapuyade void *async_cb_context; 13297f18414SEric Lapuyade }; 13397f18414SEric Lapuyade 13497f18414SEric Lapuyade static int pn544_hci_open(struct nfc_hci_dev *hdev) 13597f18414SEric Lapuyade { 13697f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 13797f18414SEric Lapuyade int r = 0; 13897f18414SEric Lapuyade 13997f18414SEric Lapuyade mutex_lock(&info->info_lock); 14097f18414SEric Lapuyade 14197f18414SEric Lapuyade if (info->state != PN544_ST_COLD) { 14297f18414SEric Lapuyade r = -EBUSY; 14397f18414SEric Lapuyade goto out; 14497f18414SEric Lapuyade } 14597f18414SEric Lapuyade 14697f18414SEric Lapuyade r = info->phy_ops->enable(info->phy_id); 14797f18414SEric Lapuyade 14897f18414SEric Lapuyade if (r == 0) 14997f18414SEric Lapuyade info->state = PN544_ST_READY; 15097f18414SEric Lapuyade 15197f18414SEric Lapuyade out: 15297f18414SEric Lapuyade mutex_unlock(&info->info_lock); 15397f18414SEric Lapuyade return r; 15497f18414SEric Lapuyade } 15597f18414SEric Lapuyade 15697f18414SEric Lapuyade static void pn544_hci_close(struct nfc_hci_dev *hdev) 15797f18414SEric Lapuyade { 15897f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 15997f18414SEric Lapuyade 16097f18414SEric Lapuyade mutex_lock(&info->info_lock); 16197f18414SEric Lapuyade 16297f18414SEric Lapuyade if (info->state == PN544_ST_COLD) 16397f18414SEric Lapuyade goto out; 16497f18414SEric Lapuyade 16597f18414SEric Lapuyade info->phy_ops->disable(info->phy_id); 16697f18414SEric Lapuyade 16797f18414SEric Lapuyade info->state = PN544_ST_COLD; 16897f18414SEric Lapuyade 16997f18414SEric Lapuyade out: 17097f18414SEric Lapuyade mutex_unlock(&info->info_lock); 17197f18414SEric Lapuyade } 17297f18414SEric Lapuyade 17397f18414SEric Lapuyade static int pn544_hci_ready(struct nfc_hci_dev *hdev) 17497f18414SEric Lapuyade { 17597f18414SEric Lapuyade struct sk_buff *skb; 17697f18414SEric Lapuyade static struct hw_config { 17797f18414SEric Lapuyade u8 adr[2]; 17897f18414SEric Lapuyade u8 value; 17997f18414SEric Lapuyade } hw_config[] = { 18097f18414SEric Lapuyade {{0x9f, 0x9a}, 0x00}, 18197f18414SEric Lapuyade 18297f18414SEric Lapuyade {{0x98, 0x10}, 0xbc}, 18397f18414SEric Lapuyade 18497f18414SEric Lapuyade {{0x9e, 0x71}, 0x00}, 18597f18414SEric Lapuyade 18697f18414SEric Lapuyade {{0x98, 0x09}, 0x00}, 18797f18414SEric Lapuyade 18897f18414SEric Lapuyade {{0x9e, 0xb4}, 0x00}, 18997f18414SEric Lapuyade 19097f18414SEric Lapuyade {{0x9e, 0xd9}, 0xff}, 19197f18414SEric Lapuyade {{0x9e, 0xda}, 0xff}, 19297f18414SEric Lapuyade {{0x9e, 0xdb}, 0x23}, 19397f18414SEric Lapuyade {{0x9e, 0xdc}, 0x21}, 19497f18414SEric Lapuyade {{0x9e, 0xdd}, 0x22}, 19597f18414SEric Lapuyade {{0x9e, 0xde}, 0x24}, 19697f18414SEric Lapuyade 19797f18414SEric Lapuyade {{0x9c, 0x01}, 0x08}, 19897f18414SEric Lapuyade 19997f18414SEric Lapuyade {{0x9e, 0xaa}, 0x01}, 20097f18414SEric Lapuyade 20197f18414SEric Lapuyade {{0x9b, 0xd1}, 0x0d}, 20297f18414SEric Lapuyade {{0x9b, 0xd2}, 0x24}, 20397f18414SEric Lapuyade {{0x9b, 0xd3}, 0x0a}, 20497f18414SEric Lapuyade {{0x9b, 0xd4}, 0x22}, 20597f18414SEric Lapuyade {{0x9b, 0xd5}, 0x08}, 20697f18414SEric Lapuyade {{0x9b, 0xd6}, 0x1e}, 20797f18414SEric Lapuyade {{0x9b, 0xdd}, 0x1c}, 20897f18414SEric Lapuyade 20997f18414SEric Lapuyade {{0x9b, 0x84}, 0x13}, 21097f18414SEric Lapuyade {{0x99, 0x81}, 0x7f}, 21197f18414SEric Lapuyade {{0x99, 0x31}, 0x70}, 21297f18414SEric Lapuyade 21397f18414SEric Lapuyade {{0x98, 0x00}, 0x3f}, 21497f18414SEric Lapuyade 21597f18414SEric Lapuyade {{0x9f, 0x09}, 0x00}, 21697f18414SEric Lapuyade 21797f18414SEric Lapuyade {{0x9f, 0x0a}, 0x05}, 21897f18414SEric Lapuyade 21997f18414SEric Lapuyade {{0x9e, 0xd1}, 0xa1}, 22097f18414SEric Lapuyade {{0x99, 0x23}, 0x00}, 22197f18414SEric Lapuyade 22297f18414SEric Lapuyade {{0x9e, 0x74}, 0x80}, 22397f18414SEric Lapuyade 22497f18414SEric Lapuyade {{0x9f, 0x28}, 0x10}, 22597f18414SEric Lapuyade 22697f18414SEric Lapuyade {{0x9f, 0x35}, 0x14}, 22797f18414SEric Lapuyade 22897f18414SEric Lapuyade {{0x9f, 0x36}, 0x60}, 22997f18414SEric Lapuyade 23097f18414SEric Lapuyade {{0x9c, 0x31}, 0x00}, 23197f18414SEric Lapuyade 23297f18414SEric Lapuyade {{0x9c, 0x32}, 0xc8}, 23397f18414SEric Lapuyade 23497f18414SEric Lapuyade {{0x9c, 0x19}, 0x40}, 23597f18414SEric Lapuyade 23697f18414SEric Lapuyade {{0x9c, 0x1a}, 0x40}, 23797f18414SEric Lapuyade 23897f18414SEric Lapuyade {{0x9c, 0x0c}, 0x00}, 23997f18414SEric Lapuyade 24097f18414SEric Lapuyade {{0x9c, 0x0d}, 0x00}, 24197f18414SEric Lapuyade 24297f18414SEric Lapuyade {{0x9c, 0x12}, 0x00}, 24397f18414SEric Lapuyade 24497f18414SEric Lapuyade {{0x9c, 0x13}, 0x00}, 24597f18414SEric Lapuyade 24697f18414SEric Lapuyade {{0x98, 0xa2}, 0x0e}, 24797f18414SEric Lapuyade 24897f18414SEric Lapuyade {{0x98, 0x93}, 0x40}, 24997f18414SEric Lapuyade 25097f18414SEric Lapuyade {{0x98, 0x7d}, 0x02}, 25197f18414SEric Lapuyade {{0x98, 0x7e}, 0x00}, 25297f18414SEric Lapuyade {{0x9f, 0xc8}, 0x01}, 25397f18414SEric Lapuyade }; 25497f18414SEric Lapuyade struct hw_config *p = hw_config; 25597f18414SEric Lapuyade int count = ARRAY_SIZE(hw_config); 25697f18414SEric Lapuyade struct sk_buff *res_skb; 25797f18414SEric Lapuyade u8 param[4]; 25897f18414SEric Lapuyade int r; 25997f18414SEric Lapuyade 26097f18414SEric Lapuyade param[0] = 0; 26197f18414SEric Lapuyade while (count--) { 26297f18414SEric Lapuyade param[1] = p->adr[0]; 26397f18414SEric Lapuyade param[2] = p->adr[1]; 26497f18414SEric Lapuyade param[3] = p->value; 26597f18414SEric Lapuyade 26697f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_WRITE, 26797f18414SEric Lapuyade param, 4, &res_skb); 26897f18414SEric Lapuyade if (r < 0) 26997f18414SEric Lapuyade return r; 27097f18414SEric Lapuyade 27197f18414SEric Lapuyade if (res_skb->len != 1) { 27297f18414SEric Lapuyade kfree_skb(res_skb); 27397f18414SEric Lapuyade return -EPROTO; 27497f18414SEric Lapuyade } 27597f18414SEric Lapuyade 27697f18414SEric Lapuyade if (res_skb->data[0] != p->value) { 27797f18414SEric Lapuyade kfree_skb(res_skb); 27897f18414SEric Lapuyade return -EIO; 27997f18414SEric Lapuyade } 28097f18414SEric Lapuyade 28197f18414SEric Lapuyade kfree_skb(res_skb); 28297f18414SEric Lapuyade 28397f18414SEric Lapuyade p++; 28497f18414SEric Lapuyade } 28597f18414SEric Lapuyade 28697f18414SEric Lapuyade param[0] = NFC_HCI_UICC_HOST_ID; 28797f18414SEric Lapuyade r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, 28897f18414SEric Lapuyade NFC_HCI_ADMIN_WHITELIST, param, 1); 28997f18414SEric Lapuyade if (r < 0) 29097f18414SEric Lapuyade return r; 29197f18414SEric Lapuyade 29297f18414SEric Lapuyade param[0] = 0x3d; 29397f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_SYS_MGMT_GATE, 29497f18414SEric Lapuyade PN544_SYS_MGMT_INFO_NOTIFICATION, param, 1); 29597f18414SEric Lapuyade if (r < 0) 29697f18414SEric Lapuyade return r; 29797f18414SEric Lapuyade 29897f18414SEric Lapuyade param[0] = 0x0; 29997f18414SEric Lapuyade r = nfc_hci_set_param(hdev, NFC_HCI_RF_READER_A_GATE, 30097f18414SEric Lapuyade PN544_RF_READER_A_AUTO_ACTIVATION, param, 1); 30197f18414SEric Lapuyade if (r < 0) 30297f18414SEric Lapuyade return r; 30397f18414SEric Lapuyade 30497f18414SEric Lapuyade r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 30597f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 30697f18414SEric Lapuyade if (r < 0) 30797f18414SEric Lapuyade return r; 30897f18414SEric Lapuyade 30997f18414SEric Lapuyade param[0] = 0x1; 31097f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 31197f18414SEric Lapuyade PN544_PL_NFCT_DEACTIVATED, param, 1); 31297f18414SEric Lapuyade if (r < 0) 31397f18414SEric Lapuyade return r; 31497f18414SEric Lapuyade 31597f18414SEric Lapuyade param[0] = 0x0; 31697f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 31797f18414SEric Lapuyade PN544_PL_RDPHASES, param, 1); 31897f18414SEric Lapuyade if (r < 0) 31997f18414SEric Lapuyade return r; 32097f18414SEric Lapuyade 32197f18414SEric Lapuyade r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, 32297f18414SEric Lapuyade PN544_ID_MGMT_FULL_VERSION_SW, &skb); 32397f18414SEric Lapuyade if (r < 0) 32497f18414SEric Lapuyade return r; 32597f18414SEric Lapuyade 32697f18414SEric Lapuyade if (skb->len != FULL_VERSION_LEN) { 32797f18414SEric Lapuyade kfree_skb(skb); 32897f18414SEric Lapuyade return -EINVAL; 32997f18414SEric Lapuyade } 33097f18414SEric Lapuyade 33197f18414SEric Lapuyade print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ", 33297f18414SEric Lapuyade DUMP_PREFIX_NONE, 16, 1, 33397f18414SEric Lapuyade skb->data, FULL_VERSION_LEN, false); 33497f18414SEric Lapuyade 33597f18414SEric Lapuyade kfree_skb(skb); 33697f18414SEric Lapuyade 33797f18414SEric Lapuyade return 0; 33897f18414SEric Lapuyade } 33997f18414SEric Lapuyade 34097f18414SEric Lapuyade static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) 34197f18414SEric Lapuyade { 34297f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 34397f18414SEric Lapuyade 34497f18414SEric Lapuyade return info->phy_ops->write(info->phy_id, skb); 34597f18414SEric Lapuyade } 34697f18414SEric Lapuyade 34797f18414SEric Lapuyade static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, 34897f18414SEric Lapuyade u32 im_protocols, u32 tm_protocols) 34997f18414SEric Lapuyade { 35097f18414SEric Lapuyade u8 phases = 0; 35197f18414SEric Lapuyade int r; 35297f18414SEric Lapuyade u8 duration[2]; 35397f18414SEric Lapuyade u8 activated; 35497f18414SEric Lapuyade u8 i_mode = 0x3f; /* Enable all supported modes */ 35597f18414SEric Lapuyade u8 t_mode = 0x0f; 35697f18414SEric Lapuyade u8 t_merge = 0x01; /* Enable merge by default */ 35797f18414SEric Lapuyade 35897f18414SEric Lapuyade pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", 35997f18414SEric Lapuyade __func__, im_protocols, tm_protocols); 36097f18414SEric Lapuyade 36197f18414SEric Lapuyade r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 36297f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 36397f18414SEric Lapuyade if (r < 0) 36497f18414SEric Lapuyade return r; 36597f18414SEric Lapuyade 36697f18414SEric Lapuyade duration[0] = 0x18; 36797f18414SEric Lapuyade duration[1] = 0x6a; 36897f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 36997f18414SEric Lapuyade PN544_PL_EMULATION, duration, 2); 37097f18414SEric Lapuyade if (r < 0) 37197f18414SEric Lapuyade return r; 37297f18414SEric Lapuyade 37397f18414SEric Lapuyade activated = 0; 37497f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 37597f18414SEric Lapuyade PN544_PL_NFCT_DEACTIVATED, &activated, 1); 37697f18414SEric Lapuyade if (r < 0) 37797f18414SEric Lapuyade return r; 37897f18414SEric Lapuyade 37997f18414SEric Lapuyade if (im_protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | 38097f18414SEric Lapuyade NFC_PROTO_JEWEL_MASK)) 38197f18414SEric Lapuyade phases |= 1; /* Type A */ 38297f18414SEric Lapuyade if (im_protocols & NFC_PROTO_FELICA_MASK) { 38397f18414SEric Lapuyade phases |= (1 << 2); /* Type F 212 */ 38497f18414SEric Lapuyade phases |= (1 << 3); /* Type F 424 */ 38597f18414SEric Lapuyade } 38697f18414SEric Lapuyade 38797f18414SEric Lapuyade phases |= (1 << 5); /* NFC active */ 38897f18414SEric Lapuyade 38997f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, 39097f18414SEric Lapuyade PN544_PL_RDPHASES, &phases, 1); 39197f18414SEric Lapuyade if (r < 0) 39297f18414SEric Lapuyade return r; 39397f18414SEric Lapuyade 39497f18414SEric Lapuyade if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { 39597f18414SEric Lapuyade hdev->gb = nfc_get_local_general_bytes(hdev->ndev, 39697f18414SEric Lapuyade &hdev->gb_len); 39797f18414SEric Lapuyade pr_debug("generate local bytes %p", hdev->gb); 39897f18414SEric Lapuyade if (hdev->gb == NULL || hdev->gb_len == 0) { 39997f18414SEric Lapuyade im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; 40097f18414SEric Lapuyade tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; 40197f18414SEric Lapuyade } 40297f18414SEric Lapuyade } 40397f18414SEric Lapuyade 40497f18414SEric Lapuyade if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { 40597f18414SEric Lapuyade r = nfc_hci_send_event(hdev, 40697f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 40797f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 40897f18414SEric Lapuyade if (r < 0) 40997f18414SEric Lapuyade return r; 41097f18414SEric Lapuyade 41197f18414SEric Lapuyade r = nfc_hci_set_param(hdev, 41297f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 41397f18414SEric Lapuyade PN544_DEP_MODE, &i_mode, 1); 41497f18414SEric Lapuyade if (r < 0) 41597f18414SEric Lapuyade return r; 41697f18414SEric Lapuyade 41797f18414SEric Lapuyade r = nfc_hci_set_param(hdev, 41897f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 41997f18414SEric Lapuyade PN544_DEP_ATR_REQ, hdev->gb, hdev->gb_len); 42097f18414SEric Lapuyade if (r < 0) 42197f18414SEric Lapuyade return r; 42297f18414SEric Lapuyade 42397f18414SEric Lapuyade r = nfc_hci_send_event(hdev, 42497f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 42597f18414SEric Lapuyade NFC_HCI_EVT_READER_REQUESTED, NULL, 0); 42697f18414SEric Lapuyade if (r < 0) 42797f18414SEric Lapuyade nfc_hci_send_event(hdev, 42897f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 42997f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 43097f18414SEric Lapuyade } 43197f18414SEric Lapuyade 43297f18414SEric Lapuyade if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { 43397f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, 43497f18414SEric Lapuyade PN544_DEP_MODE, &t_mode, 1); 43597f18414SEric Lapuyade if (r < 0) 43697f18414SEric Lapuyade return r; 43797f18414SEric Lapuyade 43897f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, 43997f18414SEric Lapuyade PN544_DEP_ATR_RES, hdev->gb, hdev->gb_len); 44097f18414SEric Lapuyade if (r < 0) 44197f18414SEric Lapuyade return r; 44297f18414SEric Lapuyade 44397f18414SEric Lapuyade r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, 44497f18414SEric Lapuyade PN544_DEP_MERGE, &t_merge, 1); 44597f18414SEric Lapuyade if (r < 0) 44697f18414SEric Lapuyade return r; 44797f18414SEric Lapuyade } 44897f18414SEric Lapuyade 44997f18414SEric Lapuyade r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 45097f18414SEric Lapuyade NFC_HCI_EVT_READER_REQUESTED, NULL, 0); 45197f18414SEric Lapuyade if (r < 0) 45297f18414SEric Lapuyade nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, 45397f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 45497f18414SEric Lapuyade 45597f18414SEric Lapuyade return r; 45697f18414SEric Lapuyade } 45797f18414SEric Lapuyade 45897f18414SEric Lapuyade static int pn544_hci_dep_link_up(struct nfc_hci_dev *hdev, 45997f18414SEric Lapuyade struct nfc_target *target, u8 comm_mode, 46097f18414SEric Lapuyade u8 *gb, size_t gb_len) 46197f18414SEric Lapuyade { 46297f18414SEric Lapuyade struct sk_buff *rgb_skb = NULL; 46397f18414SEric Lapuyade int r; 46497f18414SEric Lapuyade 46597f18414SEric Lapuyade r = nfc_hci_get_param(hdev, target->hci_reader_gate, 46697f18414SEric Lapuyade PN544_DEP_ATR_RES, &rgb_skb); 46797f18414SEric Lapuyade if (r < 0) 46897f18414SEric Lapuyade return r; 46997f18414SEric Lapuyade 47097f18414SEric Lapuyade if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) { 47197f18414SEric Lapuyade r = -EPROTO; 47297f18414SEric Lapuyade goto exit; 47397f18414SEric Lapuyade } 47497f18414SEric Lapuyade print_hex_dump(KERN_DEBUG, "remote gb: ", DUMP_PREFIX_OFFSET, 47597f18414SEric Lapuyade 16, 1, rgb_skb->data, rgb_skb->len, true); 47697f18414SEric Lapuyade 47797f18414SEric Lapuyade r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data, 47897f18414SEric Lapuyade rgb_skb->len); 47997f18414SEric Lapuyade 48097f18414SEric Lapuyade if (r == 0) 48197f18414SEric Lapuyade r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode, 48297f18414SEric Lapuyade NFC_RF_INITIATOR); 48397f18414SEric Lapuyade exit: 48497f18414SEric Lapuyade kfree_skb(rgb_skb); 48597f18414SEric Lapuyade return r; 48697f18414SEric Lapuyade } 48797f18414SEric Lapuyade 48897f18414SEric Lapuyade static int pn544_hci_dep_link_down(struct nfc_hci_dev *hdev) 48997f18414SEric Lapuyade { 49097f18414SEric Lapuyade 49197f18414SEric Lapuyade return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_INITIATOR_GATE, 49297f18414SEric Lapuyade NFC_HCI_EVT_END_OPERATION, NULL, 0); 49397f18414SEric Lapuyade } 49497f18414SEric Lapuyade 49597f18414SEric Lapuyade static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, 49697f18414SEric Lapuyade struct nfc_target *target) 49797f18414SEric Lapuyade { 49897f18414SEric Lapuyade switch (gate) { 49997f18414SEric Lapuyade case PN544_RF_READER_F_GATE: 50097f18414SEric Lapuyade target->supported_protocols = NFC_PROTO_FELICA_MASK; 50197f18414SEric Lapuyade break; 50297f18414SEric Lapuyade case PN544_RF_READER_JEWEL_GATE: 50397f18414SEric Lapuyade target->supported_protocols = NFC_PROTO_JEWEL_MASK; 50497f18414SEric Lapuyade target->sens_res = 0x0c00; 50597f18414SEric Lapuyade break; 50697f18414SEric Lapuyade case PN544_RF_READER_NFCIP1_INITIATOR_GATE: 50797f18414SEric Lapuyade target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; 50897f18414SEric Lapuyade break; 50997f18414SEric Lapuyade default: 51097f18414SEric Lapuyade return -EPROTO; 51197f18414SEric Lapuyade } 51297f18414SEric Lapuyade 51397f18414SEric Lapuyade return 0; 51497f18414SEric Lapuyade } 51597f18414SEric Lapuyade 51697f18414SEric Lapuyade static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, 51797f18414SEric Lapuyade u8 gate, 51897f18414SEric Lapuyade struct nfc_target *target) 51997f18414SEric Lapuyade { 52097f18414SEric Lapuyade struct sk_buff *uid_skb; 52197f18414SEric Lapuyade int r = 0; 52297f18414SEric Lapuyade 52397f18414SEric Lapuyade if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) 52497f18414SEric Lapuyade return r; 52597f18414SEric Lapuyade 52697f18414SEric Lapuyade if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { 52797f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, 52897f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 52997f18414SEric Lapuyade PN544_HCI_CMD_CONTINUE_ACTIVATION, NULL, 0, NULL); 53097f18414SEric Lapuyade if (r < 0) 53197f18414SEric Lapuyade return r; 53297f18414SEric Lapuyade 53397f18414SEric Lapuyade target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE; 53497f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { 53597f18414SEric Lapuyade if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && 53697f18414SEric Lapuyade target->nfcid1_len != 10) 53797f18414SEric Lapuyade return -EPROTO; 53897f18414SEric Lapuyade 53997f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, 54097f18414SEric Lapuyade PN544_RF_READER_CMD_ACTIVATE_NEXT, 54197f18414SEric Lapuyade target->nfcid1, target->nfcid1_len, NULL); 54297f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) { 54397f18414SEric Lapuyade r = nfc_hci_get_param(hdev, PN544_RF_READER_F_GATE, 54497f18414SEric Lapuyade PN544_FELICA_ID, &uid_skb); 54597f18414SEric Lapuyade if (r < 0) 54697f18414SEric Lapuyade return r; 54797f18414SEric Lapuyade 54897f18414SEric Lapuyade if (uid_skb->len != 8) { 54997f18414SEric Lapuyade kfree_skb(uid_skb); 55097f18414SEric Lapuyade return -EPROTO; 55197f18414SEric Lapuyade } 55297f18414SEric Lapuyade 55397f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, 55497f18414SEric Lapuyade PN544_RF_READER_CMD_ACTIVATE_NEXT, 55597f18414SEric Lapuyade uid_skb->data, uid_skb->len, NULL); 55697f18414SEric Lapuyade kfree_skb(uid_skb); 55797f18414SEric Lapuyade 55897f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, 55997f18414SEric Lapuyade PN544_RF_READER_NFCIP1_INITIATOR_GATE, 56097f18414SEric Lapuyade PN544_HCI_CMD_CONTINUE_ACTIVATION, 56197f18414SEric Lapuyade NULL, 0, NULL); 56297f18414SEric Lapuyade if (r < 0) 56397f18414SEric Lapuyade return r; 56497f18414SEric Lapuyade 56597f18414SEric Lapuyade target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE; 56697f18414SEric Lapuyade target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; 56797f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) { 56897f18414SEric Lapuyade /* 56997f18414SEric Lapuyade * TODO: maybe other ISO 14443 require some kind of continue 57097f18414SEric Lapuyade * activation, but for now we've seen only this one below. 57197f18414SEric Lapuyade */ 57297f18414SEric Lapuyade if (target->sens_res == 0x4403) /* Type 4 Mifare DESFire */ 57397f18414SEric Lapuyade r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, 57497f18414SEric Lapuyade PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION, 57597f18414SEric Lapuyade NULL, 0, NULL); 57697f18414SEric Lapuyade } 57797f18414SEric Lapuyade 57897f18414SEric Lapuyade return r; 57997f18414SEric Lapuyade } 58097f18414SEric Lapuyade 58197f18414SEric Lapuyade #define PN544_CB_TYPE_READER_F 1 58297f18414SEric Lapuyade 58397f18414SEric Lapuyade static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb, 58497f18414SEric Lapuyade int err) 58597f18414SEric Lapuyade { 58697f18414SEric Lapuyade struct pn544_hci_info *info = context; 58797f18414SEric Lapuyade 58897f18414SEric Lapuyade switch (info->async_cb_type) { 58997f18414SEric Lapuyade case PN544_CB_TYPE_READER_F: 59097f18414SEric Lapuyade if (err == 0) 59197f18414SEric Lapuyade skb_pull(skb, 1); 59297f18414SEric Lapuyade info->async_cb(info->async_cb_context, skb, err); 59397f18414SEric Lapuyade break; 59497f18414SEric Lapuyade default: 59597f18414SEric Lapuyade if (err == 0) 59697f18414SEric Lapuyade kfree_skb(skb); 59797f18414SEric Lapuyade break; 59897f18414SEric Lapuyade } 59997f18414SEric Lapuyade } 60097f18414SEric Lapuyade 60197f18414SEric Lapuyade #define MIFARE_CMD_AUTH_KEY_A 0x60 60297f18414SEric Lapuyade #define MIFARE_CMD_AUTH_KEY_B 0x61 60397f18414SEric Lapuyade #define MIFARE_CMD_HEADER 2 60497f18414SEric Lapuyade #define MIFARE_UID_LEN 4 60597f18414SEric Lapuyade #define MIFARE_KEY_LEN 6 60697f18414SEric Lapuyade #define MIFARE_CMD_LEN 12 60797f18414SEric Lapuyade /* 60897f18414SEric Lapuyade * Returns: 60997f18414SEric Lapuyade * <= 0: driver handled the data exchange 61097f18414SEric Lapuyade * 1: driver doesn't especially handle, please do standard processing 61197f18414SEric Lapuyade */ 61297f18414SEric Lapuyade static int pn544_hci_im_transceive(struct nfc_hci_dev *hdev, 61397f18414SEric Lapuyade struct nfc_target *target, 61497f18414SEric Lapuyade struct sk_buff *skb, data_exchange_cb_t cb, 61597f18414SEric Lapuyade void *cb_context) 61697f18414SEric Lapuyade { 61797f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 61897f18414SEric Lapuyade 61997f18414SEric Lapuyade pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__, 62097f18414SEric Lapuyade target->hci_reader_gate); 62197f18414SEric Lapuyade 62297f18414SEric Lapuyade switch (target->hci_reader_gate) { 62397f18414SEric Lapuyade case NFC_HCI_RF_READER_A_GATE: 62497f18414SEric Lapuyade if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { 62597f18414SEric Lapuyade /* 62697f18414SEric Lapuyade * It seems that pn544 is inverting key and UID for 62797f18414SEric Lapuyade * MIFARE authentication commands. 62897f18414SEric Lapuyade */ 62997f18414SEric Lapuyade if (skb->len == MIFARE_CMD_LEN && 63097f18414SEric Lapuyade (skb->data[0] == MIFARE_CMD_AUTH_KEY_A || 63197f18414SEric Lapuyade skb->data[0] == MIFARE_CMD_AUTH_KEY_B)) { 63297f18414SEric Lapuyade u8 uid[MIFARE_UID_LEN]; 63397f18414SEric Lapuyade u8 *data = skb->data + MIFARE_CMD_HEADER; 63497f18414SEric Lapuyade 63597f18414SEric Lapuyade memcpy(uid, data + MIFARE_KEY_LEN, 63697f18414SEric Lapuyade MIFARE_UID_LEN); 63797f18414SEric Lapuyade memmove(data + MIFARE_UID_LEN, data, 63897f18414SEric Lapuyade MIFARE_KEY_LEN); 63997f18414SEric Lapuyade memcpy(data, uid, MIFARE_UID_LEN); 64097f18414SEric Lapuyade } 64197f18414SEric Lapuyade 64297f18414SEric Lapuyade return nfc_hci_send_cmd_async(hdev, 64397f18414SEric Lapuyade target->hci_reader_gate, 64497f18414SEric Lapuyade PN544_MIFARE_CMD, 64597f18414SEric Lapuyade skb->data, skb->len, 64697f18414SEric Lapuyade cb, cb_context); 64797f18414SEric Lapuyade } else 64897f18414SEric Lapuyade return 1; 64997f18414SEric Lapuyade case PN544_RF_READER_F_GATE: 65097f18414SEric Lapuyade *skb_push(skb, 1) = 0; 65197f18414SEric Lapuyade *skb_push(skb, 1) = 0; 65297f18414SEric Lapuyade 65397f18414SEric Lapuyade info->async_cb_type = PN544_CB_TYPE_READER_F; 65497f18414SEric Lapuyade info->async_cb = cb; 65597f18414SEric Lapuyade info->async_cb_context = cb_context; 65697f18414SEric Lapuyade 65797f18414SEric Lapuyade return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, 65897f18414SEric Lapuyade PN544_FELICA_RAW, skb->data, 65997f18414SEric Lapuyade skb->len, 66097f18414SEric Lapuyade pn544_hci_data_exchange_cb, info); 66197f18414SEric Lapuyade case PN544_RF_READER_JEWEL_GATE: 66297f18414SEric Lapuyade return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, 66397f18414SEric Lapuyade PN544_JEWEL_RAW_CMD, skb->data, 66497f18414SEric Lapuyade skb->len, cb, cb_context); 66597f18414SEric Lapuyade case PN544_RF_READER_NFCIP1_INITIATOR_GATE: 66697f18414SEric Lapuyade *skb_push(skb, 1) = 0; 66797f18414SEric Lapuyade 66897f18414SEric Lapuyade return nfc_hci_send_event(hdev, target->hci_reader_gate, 66997f18414SEric Lapuyade PN544_HCI_EVT_SND_DATA, skb->data, 67097f18414SEric Lapuyade skb->len); 67197f18414SEric Lapuyade default: 67297f18414SEric Lapuyade return 1; 67397f18414SEric Lapuyade } 67497f18414SEric Lapuyade } 67597f18414SEric Lapuyade 67697f18414SEric Lapuyade static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) 67797f18414SEric Lapuyade { 67897f18414SEric Lapuyade /* Set default false for multiple information chaining */ 67997f18414SEric Lapuyade *skb_push(skb, 1) = 0; 68097f18414SEric Lapuyade 68197f18414SEric Lapuyade return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, 68297f18414SEric Lapuyade PN544_HCI_EVT_SND_DATA, skb->data, skb->len); 68397f18414SEric Lapuyade } 68497f18414SEric Lapuyade 68597f18414SEric Lapuyade static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, 68697f18414SEric Lapuyade struct nfc_target *target) 68797f18414SEric Lapuyade { 68897f18414SEric Lapuyade pr_debug("supported protocol %d", target->supported_protocols); 68997f18414SEric Lapuyade if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK | 69097f18414SEric Lapuyade NFC_PROTO_ISO14443_B_MASK)) { 69197f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, target->hci_reader_gate, 69297f18414SEric Lapuyade PN544_RF_READER_CMD_PRESENCE_CHECK, 69397f18414SEric Lapuyade NULL, 0, NULL); 69497f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { 69597f18414SEric Lapuyade if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && 69697f18414SEric Lapuyade target->nfcid1_len != 10) 69797f18414SEric Lapuyade return -EOPNOTSUPP; 69897f18414SEric Lapuyade 69997f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, 70097f18414SEric Lapuyade PN544_RF_READER_CMD_ACTIVATE_NEXT, 70197f18414SEric Lapuyade target->nfcid1, target->nfcid1_len, NULL); 70297f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_JEWEL_MASK) { 70397f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, target->hci_reader_gate, 70497f18414SEric Lapuyade PN544_JEWEL_RAW_CMD, NULL, 0, NULL); 70597f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) { 70697f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, 70797f18414SEric Lapuyade PN544_FELICA_RAW, NULL, 0, NULL); 70897f18414SEric Lapuyade } else if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { 70997f18414SEric Lapuyade return nfc_hci_send_cmd(hdev, target->hci_reader_gate, 71097f18414SEric Lapuyade PN544_HCI_CMD_ATTREQUEST, 71197f18414SEric Lapuyade NULL, 0, NULL); 71297f18414SEric Lapuyade } 71397f18414SEric Lapuyade 71497f18414SEric Lapuyade return 0; 71597f18414SEric Lapuyade } 71697f18414SEric Lapuyade 717*27c31191SEric Lapuyade static int pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, u8 event, 718*27c31191SEric Lapuyade struct sk_buff *skb) 71997f18414SEric Lapuyade { 72097f18414SEric Lapuyade struct sk_buff *rgb_skb = NULL; 72197f18414SEric Lapuyade int r = 0; 72297f18414SEric Lapuyade 72397f18414SEric Lapuyade pr_debug("hci event %d", event); 72497f18414SEric Lapuyade switch (event) { 72597f18414SEric Lapuyade case PN544_HCI_EVT_ACTIVATED: 72697f18414SEric Lapuyade if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) 727*27c31191SEric Lapuyade r = nfc_hci_target_discovered(hdev, gate); 72897f18414SEric Lapuyade else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { 72997f18414SEric Lapuyade r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, 73097f18414SEric Lapuyade &rgb_skb); 73197f18414SEric Lapuyade if (r < 0) 73297f18414SEric Lapuyade goto exit; 73397f18414SEric Lapuyade 734*27c31191SEric Lapuyade r = nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, 73597f18414SEric Lapuyade NFC_COMM_PASSIVE, rgb_skb->data, 73697f18414SEric Lapuyade rgb_skb->len); 73797f18414SEric Lapuyade 73897f18414SEric Lapuyade kfree_skb(rgb_skb); 73997f18414SEric Lapuyade } 74097f18414SEric Lapuyade break; 74197f18414SEric Lapuyade case PN544_HCI_EVT_DEACTIVATED: 742*27c31191SEric Lapuyade r = nfc_hci_send_event(hdev, gate, NFC_HCI_EVT_END_OPERATION, 743*27c31191SEric Lapuyade NULL, 0); 74497f18414SEric Lapuyade break; 74597f18414SEric Lapuyade case PN544_HCI_EVT_RCV_DATA: 74697f18414SEric Lapuyade if (skb->len < 2) { 74797f18414SEric Lapuyade r = -EPROTO; 74897f18414SEric Lapuyade goto exit; 74997f18414SEric Lapuyade } 75097f18414SEric Lapuyade 75197f18414SEric Lapuyade if (skb->data[0] != 0) { 75297f18414SEric Lapuyade pr_debug("data0 %d", skb->data[0]); 75397f18414SEric Lapuyade r = -EPROTO; 75497f18414SEric Lapuyade goto exit; 75597f18414SEric Lapuyade } 75697f18414SEric Lapuyade 75797f18414SEric Lapuyade skb_pull(skb, 2); 758*27c31191SEric Lapuyade return nfc_tm_data_received(hdev->ndev, skb); 75997f18414SEric Lapuyade default: 760*27c31191SEric Lapuyade pr_err("Discarded unknown event %x to gate %x\n", event, gate); 76197f18414SEric Lapuyade break; 76297f18414SEric Lapuyade } 76397f18414SEric Lapuyade 76497f18414SEric Lapuyade exit: 76597f18414SEric Lapuyade kfree_skb(skb); 766*27c31191SEric Lapuyade 767*27c31191SEric Lapuyade return r; 76897f18414SEric Lapuyade } 76997f18414SEric Lapuyade 77097f18414SEric Lapuyade static struct nfc_hci_ops pn544_hci_ops = { 77197f18414SEric Lapuyade .open = pn544_hci_open, 77297f18414SEric Lapuyade .close = pn544_hci_close, 77397f18414SEric Lapuyade .hci_ready = pn544_hci_ready, 77497f18414SEric Lapuyade .xmit = pn544_hci_xmit, 77597f18414SEric Lapuyade .start_poll = pn544_hci_start_poll, 77697f18414SEric Lapuyade .dep_link_up = pn544_hci_dep_link_up, 77797f18414SEric Lapuyade .dep_link_down = pn544_hci_dep_link_down, 77897f18414SEric Lapuyade .target_from_gate = pn544_hci_target_from_gate, 77997f18414SEric Lapuyade .complete_target_discovered = pn544_hci_complete_target_discovered, 78097f18414SEric Lapuyade .im_transceive = pn544_hci_im_transceive, 78197f18414SEric Lapuyade .tm_send = pn544_hci_tm_send, 78297f18414SEric Lapuyade .check_presence = pn544_hci_check_presence, 78397f18414SEric Lapuyade .event_received = pn544_hci_event_received, 78497f18414SEric Lapuyade }; 78597f18414SEric Lapuyade 78697f18414SEric Lapuyade int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, 78797f18414SEric Lapuyade int phy_headroom, int phy_tailroom, int phy_payload, 78897f18414SEric Lapuyade struct nfc_hci_dev **hdev) 78997f18414SEric Lapuyade { 79097f18414SEric Lapuyade struct pn544_hci_info *info; 79197f18414SEric Lapuyade u32 protocols; 79297f18414SEric Lapuyade struct nfc_hci_init_data init_data; 79397f18414SEric Lapuyade int r; 79497f18414SEric Lapuyade 79597f18414SEric Lapuyade info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); 79697f18414SEric Lapuyade if (!info) { 79797f18414SEric Lapuyade pr_err("Cannot allocate memory for pn544_hci_info.\n"); 79897f18414SEric Lapuyade r = -ENOMEM; 79997f18414SEric Lapuyade goto err_info_alloc; 80097f18414SEric Lapuyade } 80197f18414SEric Lapuyade 80297f18414SEric Lapuyade info->phy_ops = phy_ops; 80397f18414SEric Lapuyade info->phy_id = phy_id; 80497f18414SEric Lapuyade info->state = PN544_ST_COLD; 80597f18414SEric Lapuyade mutex_init(&info->info_lock); 80697f18414SEric Lapuyade 80797f18414SEric Lapuyade init_data.gate_count = ARRAY_SIZE(pn544_gates); 80897f18414SEric Lapuyade 80997f18414SEric Lapuyade memcpy(init_data.gates, pn544_gates, sizeof(pn544_gates)); 81097f18414SEric Lapuyade 81197f18414SEric Lapuyade /* 81297f18414SEric Lapuyade * TODO: Session id must include the driver name + some bus addr 81397f18414SEric Lapuyade * persistent info to discriminate 2 identical chips 81497f18414SEric Lapuyade */ 81597f18414SEric Lapuyade strcpy(init_data.session_id, "ID544HCI"); 81697f18414SEric Lapuyade 81797f18414SEric Lapuyade protocols = NFC_PROTO_JEWEL_MASK | 81897f18414SEric Lapuyade NFC_PROTO_MIFARE_MASK | 81997f18414SEric Lapuyade NFC_PROTO_FELICA_MASK | 82097f18414SEric Lapuyade NFC_PROTO_ISO14443_MASK | 82197f18414SEric Lapuyade NFC_PROTO_ISO14443_B_MASK | 82297f18414SEric Lapuyade NFC_PROTO_NFC_DEP_MASK; 82397f18414SEric Lapuyade 82497f18414SEric Lapuyade info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, 82597f18414SEric Lapuyade protocols, llc_name, 82697f18414SEric Lapuyade phy_headroom + PN544_CMDS_HEADROOM, 82797f18414SEric Lapuyade phy_tailroom, phy_payload); 82897f18414SEric Lapuyade if (!info->hdev) { 82997f18414SEric Lapuyade pr_err("Cannot allocate nfc hdev.\n"); 83097f18414SEric Lapuyade r = -ENOMEM; 83197f18414SEric Lapuyade goto err_alloc_hdev; 83297f18414SEric Lapuyade } 83397f18414SEric Lapuyade 83497f18414SEric Lapuyade nfc_hci_set_clientdata(info->hdev, info); 83597f18414SEric Lapuyade 83697f18414SEric Lapuyade r = nfc_hci_register_device(info->hdev); 83797f18414SEric Lapuyade if (r) 83897f18414SEric Lapuyade goto err_regdev; 83997f18414SEric Lapuyade 84097f18414SEric Lapuyade *hdev = info->hdev; 84197f18414SEric Lapuyade 84297f18414SEric Lapuyade return 0; 84397f18414SEric Lapuyade 84497f18414SEric Lapuyade err_regdev: 84597f18414SEric Lapuyade nfc_hci_free_device(info->hdev); 84697f18414SEric Lapuyade 84797f18414SEric Lapuyade err_alloc_hdev: 84897f18414SEric Lapuyade kfree(info); 84997f18414SEric Lapuyade 85097f18414SEric Lapuyade err_info_alloc: 85197f18414SEric Lapuyade return r; 85297f18414SEric Lapuyade } 85397f18414SEric Lapuyade 85497f18414SEric Lapuyade void pn544_hci_remove(struct nfc_hci_dev *hdev) 85597f18414SEric Lapuyade { 85697f18414SEric Lapuyade struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); 85797f18414SEric Lapuyade 85897f18414SEric Lapuyade nfc_hci_unregister_device(hdev); 85997f18414SEric Lapuyade nfc_hci_free_device(hdev); 86097f18414SEric Lapuyade kfree(info); 86197f18414SEric Lapuyade } 862