cregit-Linux how code gets into the kernel

Release 4.14 drivers/nfc/fdp/fdp.c

Directory: drivers/nfc/fdp
/* -------------------------------------------------------------------------
 * Copyright (C) 2014-2016, Intel Corporation
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * -------------------------------------------------------------------------
 */

#include <linux/module.h>
#include <linux/nfc.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/firmware.h>
#include <net/nfc/nci_core.h>

#include "fdp.h"


#define FDP_OTP_PATCH_NAME			"otp.bin"

#define FDP_RAM_PATCH_NAME			"ram.bin"

#define FDP_FW_HEADER_SIZE			576

#define FDP_FW_UPDATE_SLEEP			1000


#define NCI_GET_VERSION_TIMEOUT			8000

#define NCI_PATCH_REQUEST_TIMEOUT		8000

#define FDP_PATCH_CONN_DEST			0xC2

#define FDP_PATCH_CONN_PARAM_TYPE		0xA0


#define NCI_PATCH_TYPE_RAM			0x00

#define NCI_PATCH_TYPE_OTP			0x01

#define NCI_PATCH_TYPE_EOT			0xFF


#define NCI_PARAM_ID_FW_RAM_VERSION		0xA0

#define NCI_PARAM_ID_FW_OTP_VERSION		0xA1

#define NCI_PARAM_ID_OTP_LIMITED_VERSION	0xC5

#define NCI_PARAM_ID_KEY_INDEX_ID		0xC6


#define NCI_GID_PROP				0x0F

#define NCI_OP_PROP_PATCH_OID			0x08

#define NCI_OP_PROP_SET_PDATA_OID		0x23


struct fdp_nci_info {
	
struct nfc_phy_ops *phy_ops;
	
struct fdp_i2c_phy *phy;
	
struct nci_dev *ndev;

	
const struct firmware *otp_patch;
	
const struct firmware *ram_patch;
	
u32 otp_patch_version;
	
u32 ram_patch_version;

	
u32 otp_version;
	
u32 ram_version;
	
u32 limited_otp_version;
	
u8 key_index;

	
u8 *fw_vsc_cfg;
	
u8 clock_type;
	
u32 clock_freq;

	
atomic_t data_pkt_counter;
	
void (*data_pkt_counter_cb)(struct nci_dev *ndev);
	
u8 setup_patch_sent;
	
u8 setup_patch_ntf;
	
u8 setup_patch_status;
	
u8 setup_reset_ntf;
	
wait_queue_head_t setup_wq;
};


static u8 nci_core_get_config_otp_ram_version[5] = {
	0x04,
	NCI_PARAM_ID_FW_RAM_VERSION,
	NCI_PARAM_ID_FW_OTP_VERSION,
	NCI_PARAM_ID_OTP_LIMITED_VERSION,
	NCI_PARAM_ID_KEY_INDEX_ID
};


struct nci_core_get_config_rsp {
	
u8 status;
	
u8 count;
	
u8 data[0];
};


static int fdp_nci_create_conn(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct core_conn_create_dest_spec_params param; int r; /* proprietary destination specific paramerer without value */ param.type = FDP_PATCH_CONN_PARAM_TYPE; param.length = 0x00; r = nci_core_conn_create(info->ndev, FDP_PATCH_CONN_DEST, 1, sizeof(param), &param); if (r) return r; return nci_get_conn_info_by_dest_type_params(ndev, FDP_PATCH_CONN_DEST, NULL); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca7594.94%150.00%
Christophe Ricard45.06%150.00%
Total79100.00%2100.00%


static inline int fdp_nci_get_versions(struct nci_dev *ndev) { return nci_core_cmd(ndev, NCI_OP_CORE_GET_CONFIG_CMD, sizeof(nci_core_get_config_otp_ram_version), (__u8 *) &nci_core_get_config_otp_ram_version); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca32100.00%1100.00%
Total32100.00%1100.00%


static inline int fdp_nci_patch_cmd(struct nci_dev *ndev, u8 type) { return nci_prop_cmd(ndev, NCI_OP_PROP_PATCH_OID, sizeof(type), &type); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca31100.00%1100.00%
Total31100.00%1100.00%


static inline int fdp_nci_set_production_data(struct nci_dev *ndev, u8 len, char *data) { return nci_prop_cmd(ndev, NCI_OP_PROP_SET_PDATA_OID, len, data); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca31100.00%1100.00%
Total31100.00%1100.00%


static int fdp_nci_set_clock(struct nci_dev *ndev, u8 clock_type, u32 clock_freq) { u32 fc = 13560; u32 nd, num, delta; char data[9]; nd = (24 * fc) / clock_freq; delta = 24 * fc - nd * clock_freq; num = (32768 * delta) / clock_freq; data[0] = 0x00; data[1] = 0x00; data[2] = 0x00; data[3] = 0x10; data[4] = 0x04; data[5] = num & 0xFF; data[6] = (num >> 8) & 0xff; data[7] = nd; data[8] = clock_type; return fdp_nci_set_production_data(ndev, 9, data); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca146100.00%1100.00%
Total146100.00%1100.00%


static void fdp_nci_send_patch_cb(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); info->setup_patch_sent = 1; wake_up(&info->setup_wq); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca35100.00%1100.00%
Total35100.00%1100.00%

/** * Register a packet sent counter and a callback * * We have no other way of knowing when all firmware packets were sent out * on the i2c bus. We need to know that in order to close the connection and * send the patch end message. */
static void fdp_nci_set_data_pkt_counter(struct nci_dev *ndev, void (*cb)(struct nci_dev *ndev), int count) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; dev_dbg(dev, "NCI data pkt counter %d\n", count); atomic_set(&info->data_pkt_counter, count); info->data_pkt_counter_cb = cb; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca75100.00%1100.00%
Total75100.00%1100.00%

/** * The device is expecting a stream of packets. All packets need to * have the PBF flag set to 0x0 (last packet) even if the firmware * file is segmented and there are multiple packets. If we give the * whole firmware to nci_send_data it will segment it and it will set * the PBF flag to 0x01 so we need to do the segmentation here. * * The firmware will be analyzed and applied when we send NCI_OP_PROP_PATCH_CMD * command with NCI_PATCH_TYPE_EOT parameter. The device will send a * NFCC_PATCH_NTF packaet and a NCI_OP_CORE_RESET_NTF packet. */
static int fdp_nci_send_patch(struct nci_dev *ndev, u8 conn_id, u8 type) { struct fdp_nci_info *info = nci_get_drvdata(ndev); const struct firmware *fw; struct sk_buff *skb; unsigned long len; u8 max_size, payload_size; int rc = 0; if ((type == NCI_PATCH_TYPE_OTP && !info->otp_patch) || (type == NCI_PATCH_TYPE_RAM && !info->ram_patch)) return -EINVAL; if (type == NCI_PATCH_TYPE_OTP) fw = info->otp_patch; else fw = info->ram_patch; max_size = nci_conn_max_data_pkt_payload_size(ndev, conn_id); if (max_size <= 0) return -EINVAL; len = fw->size; fdp_nci_set_data_pkt_counter(ndev, fdp_nci_send_patch_cb, DIV_ROUND_UP(fw->size, max_size)); while (len) { payload_size = min_t(unsigned long, (unsigned long) max_size, len); skb = nci_skb_alloc(ndev, (NCI_CTRL_HDR_SIZE + payload_size), GFP_KERNEL); if (!skb) { fdp_nci_set_data_pkt_counter(ndev, NULL, 0); return -ENOMEM; } skb_reserve(skb, NCI_CTRL_HDR_SIZE); skb_put_data(skb, fw->data + (fw->size - len), payload_size); rc = nci_send_data(ndev, conn_id, skb); if (rc) { fdp_nci_set_data_pkt_counter(ndev, NULL, 0); return rc; } len -= payload_size; } return rc; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca25399.61%150.00%
Johannes Berg10.39%150.00%
Total254100.00%2100.00%


static int fdp_nci_open(struct nci_dev *ndev) { int r; struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; dev_dbg(dev, "%s\n", __func__); r = info->phy_ops->enable(info->phy); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca63100.00%1100.00%
Total63100.00%1100.00%


static int fdp_nci_close(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; dev_dbg(dev, "%s\n", __func__); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca47100.00%1100.00%
Total47100.00%1100.00%


static int fdp_nci_send(struct nci_dev *ndev, struct sk_buff *skb) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; dev_dbg(dev, "%s\n", __func__); if (atomic_dec_and_test(&info->data_pkt_counter)) info->data_pkt_counter_cb(ndev); return info->phy_ops->write(info->phy, skb); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca80100.00%1100.00%
Total80100.00%1100.00%


int fdp_nci_recv_frame(struct nci_dev *ndev, struct sk_buff *skb) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; dev_dbg(dev, "%s\n", __func__); return nci_recv_frame(ndev, skb); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca56100.00%1100.00%
Total56100.00%1100.00%

EXPORT_SYMBOL(fdp_nci_recv_frame);
static int fdp_nci_request_firmware(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; u8 *data; int r; r = request_firmware(&info->ram_patch, FDP_RAM_PATCH_NAME, dev); if (r < 0) { nfc_err(dev, "RAM patch request error\n"); goto error; } data = (u8 *) info->ram_patch->data; info->ram_patch_version = data[FDP_FW_HEADER_SIZE] | (data[FDP_FW_HEADER_SIZE + 1] << 8) | (data[FDP_FW_HEADER_SIZE + 2] << 16) | (data[FDP_FW_HEADER_SIZE + 3] << 24); dev_dbg(dev, "RAM patch version: %d, size: %d\n", info->ram_patch_version, (int) info->ram_patch->size); r = request_firmware(&info->otp_patch, FDP_OTP_PATCH_NAME, dev); if (r < 0) { nfc_err(dev, "OTP patch request error\n"); goto out; } data = (u8 *) info->otp_patch->data; info->otp_patch_version = data[FDP_FW_HEADER_SIZE] | (data[FDP_FW_HEADER_SIZE + 1] << 8) | (data[FDP_FW_HEADER_SIZE+2] << 16) | (data[FDP_FW_HEADER_SIZE+3] << 24); dev_dbg(dev, "OTP patch version: %d, size: %d\n", info->otp_patch_version, (int) info->otp_patch->size); out: return 0; error: return r; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca264100.00%1100.00%
Total264100.00%1100.00%


static void fdp_nci_release_firmware(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); if (info->otp_patch) { release_firmware(info->otp_patch); info->otp_patch = NULL; } if (info->ram_patch) { release_firmware(info->ram_patch); info->ram_patch = NULL; } }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca6298.41%150.00%
Colin Ian King11.59%150.00%
Total63100.00%2100.00%


static int fdp_nci_patch_otp(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; int conn_id; int r = 0; if (info->otp_version >= info->otp_patch_version) goto out; info->setup_patch_sent = 0; info->setup_reset_ntf = 0; info->setup_patch_ntf = 0; /* Patch init request */ r = fdp_nci_patch_cmd(ndev, NCI_PATCH_TYPE_OTP); if (r) goto out; /* Patch data connection creation */ conn_id = fdp_nci_create_conn(ndev); if (conn_id < 0) { r = conn_id; goto out; } /* Send the patch over the data connection */ r = fdp_nci_send_patch(ndev, conn_id, NCI_PATCH_TYPE_OTP); if (r) goto out; /* Wait for all the packets to be send over i2c */ wait_event_interruptible(info->setup_wq, info->setup_patch_sent == 1); /* make sure that the NFCC processed the last data packet */ msleep(FDP_FW_UPDATE_SLEEP); /* Close the data connection */ r = nci_core_conn_close(info->ndev, conn_id); if (r) goto out; /* Patch finish message */ if (fdp_nci_patch_cmd(ndev, NCI_PATCH_TYPE_EOT)) { nfc_err(dev, "OTP patch error 0x%x\n", r); r = -EINVAL; goto out; } /* If the patch notification didn't arrive yet, wait for it */ wait_event_interruptible(info->setup_wq, info->setup_patch_ntf); /* Check if the patching was successful */ r = info->setup_patch_status; if (r) { nfc_err(dev, "OTP patch error 0x%x\n", r); r = -EINVAL; goto out; } /* * We need to wait for the reset notification before we * can continue */ wait_event_interruptible(info->setup_wq, info->setup_reset_ntf); out: return r; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca25999.62%150.00%
Geert Uytterhoeven10.38%150.00%
Total260100.00%2100.00%


static int fdp_nci_patch_ram(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; int conn_id; int r = 0; if (info->ram_version >= info->ram_patch_version) goto out; info->setup_patch_sent = 0; info->setup_reset_ntf = 0; info->setup_patch_ntf = 0; /* Patch init request */ r = fdp_nci_patch_cmd(ndev, NCI_PATCH_TYPE_RAM); if (r) goto out; /* Patch data connection creation */ conn_id = fdp_nci_create_conn(ndev); if (conn_id < 0) { r = conn_id; goto out; } /* Send the patch over the data connection */ r = fdp_nci_send_patch(ndev, conn_id, NCI_PATCH_TYPE_RAM); if (r) goto out; /* Wait for all the packets to be send over i2c */ wait_event_interruptible(info->setup_wq, info->setup_patch_sent == 1); /* make sure that the NFCC processed the last data packet */ msleep(FDP_FW_UPDATE_SLEEP); /* Close the data connection */ r = nci_core_conn_close(info->ndev, conn_id); if (r) goto out; /* Patch finish message */ if (fdp_nci_patch_cmd(ndev, NCI_PATCH_TYPE_EOT)) { nfc_err(dev, "RAM patch error 0x%x\n", r); r = -EINVAL; goto out; } /* If the patch notification didn't arrive yet, wait for it */ wait_event_interruptible(info->setup_wq, info->setup_patch_ntf); /* Check if the patching was successful */ r = info->setup_patch_status; if (r) { nfc_err(dev, "RAM patch error 0x%x\n", r); r = -EINVAL; goto out; } /* * We need to wait for the reset notification before we * can continue */ wait_event_interruptible(info->setup_wq, info->setup_reset_ntf); out: return r; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca25999.62%150.00%
Geert Uytterhoeven10.38%150.00%
Total260100.00%2100.00%


static int fdp_nci_setup(struct nci_dev *ndev) { /* Format: total length followed by an NCI packet */ struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; int r; u8 patched = 0; dev_dbg(dev, "%s\n", __func__); r = nci_core_init(ndev); if (r) goto error; /* Get RAM and OTP version */ r = fdp_nci_get_versions(ndev); if (r) goto error; /* Load firmware from disk */ r = fdp_nci_request_firmware(ndev); if (r) goto error; /* Update OTP */ if (info->otp_version < info->otp_patch_version) { r = fdp_nci_patch_otp(ndev); if (r) goto error; patched = 1; } /* Update RAM */ if (info->ram_version < info->ram_patch_version) { r = fdp_nci_patch_ram(ndev); if (r) goto error; patched = 1; } /* Release the firmware buffers */ fdp_nci_release_firmware(ndev); /* If a patch was applied the new version is checked */ if (patched) { r = nci_core_init(ndev); if (r) goto error; r = fdp_nci_get_versions(ndev); if (r) goto error; if (info->otp_version != info->otp_patch_version || info->ram_version != info->ram_patch_version) { nfc_err(dev, "Firmware update failed"); r = -EINVAL; goto error; } } /* * We initialized the devices but the NFC subsystem expects * it to not be initialized. */ return nci_core_reset(ndev); error: fdp_nci_release_firmware(ndev); nfc_err(dev, "Setup error %d\n", r); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca261100.00%1100.00%
Total261100.00%1100.00%


static int fdp_nci_post_setup(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; int r; /* Check if the device has VSC */ if (info->fw_vsc_cfg && info->fw_vsc_cfg[0]) { /* Set the vendor specific configuration */ r = fdp_nci_set_production_data(ndev, info->fw_vsc_cfg[3], &info->fw_vsc_cfg[4]); if (r) { nfc_err(dev, "Vendor specific config set error %d\n", r); return r; } } /* Set clock type and frequency */ r = fdp_nci_set_clock(ndev, info->clock_type, info->clock_freq); if (r) { nfc_err(dev, "Clock set error %d\n", r); return r; } /* * In order to apply the VSC FDP needs a reset */ r = nci_core_reset(ndev); if (r) return r; /** * The nci core was initialized when post setup was called * so we leave it like that */ return nci_core_init(ndev); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca151100.00%1100.00%
Total151100.00%1100.00%


static int fdp_nci_core_reset_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; dev_dbg(dev, "%s\n", __func__); info->setup_reset_ntf = 1; wake_up(&info->setup_wq); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca66100.00%1100.00%
Total66100.00%1100.00%


static int fdp_nci_prop_patch_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; dev_dbg(dev, "%s\n", __func__); info->setup_patch_ntf = 1; info->setup_patch_status = skb->data[0]; wake_up(&info->setup_wq); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca77100.00%1100.00%
Total77100.00%1100.00%


static int fdp_nci_prop_patch_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; u8 status = skb->data[0]; dev_dbg(dev, "%s: status 0x%x\n", __func__, status); nci_req_complete(ndev, status); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca71100.00%1100.00%
Total71100.00%1100.00%


static int fdp_nci_prop_set_production_data_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; u8 status = skb->data[0]; dev_dbg(dev, "%s: status 0x%x\n", __func__, status); nci_req_complete(ndev, status); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca71100.00%1100.00%
Total71100.00%1100.00%


static int fdp_nci_core_get_config_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; struct nci_core_get_config_rsp *rsp = (void *) skb->data; u8 i, *p; if (rsp->status == NCI_STATUS_OK) { p = rsp->data; for (i = 0; i < 4; i++) { switch (*p++) { case NCI_PARAM_ID_FW_RAM_VERSION: p++; info->ram_version = le32_to_cpup((__le32 *) p); p += 4; break; case NCI_PARAM_ID_FW_OTP_VERSION: p++; info->otp_version = le32_to_cpup((__le32 *) p); p += 4; break; case NCI_PARAM_ID_OTP_LIMITED_VERSION: p++; info->otp_version = le32_to_cpup((__le32 *) p); p += 4; break; case NCI_PARAM_ID_KEY_INDEX_ID: p++; info->key_index = *p++; } } } dev_dbg(dev, "OTP version %d\n", info->otp_version); dev_dbg(dev, "RAM version %d\n", info->ram_version); dev_dbg(dev, "key index %d\n", info->key_index); dev_dbg(dev, "%s: status 0x%x\n", __func__, rsp->status); nci_req_complete(ndev, rsp->status); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca242100.00%1100.00%
Total242100.00%1100.00%

static struct nci_driver_ops fdp_core_ops[] = { { .opcode = NCI_OP_CORE_GET_CONFIG_RSP, .rsp = fdp_nci_core_get_config_rsp_packet, }, { .opcode = NCI_OP_CORE_RESET_NTF, .ntf = fdp_nci_core_reset_ntf_packet, }, }; static struct nci_driver_ops fdp_prop_ops[] = { { .opcode = nci_opcode_pack(NCI_GID_PROP, NCI_OP_PROP_PATCH_OID), .rsp = fdp_nci_prop_patch_rsp_packet, .ntf = fdp_nci_prop_patch_ntf_packet, }, { .opcode = nci_opcode_pack(NCI_GID_PROP, NCI_OP_PROP_SET_PDATA_OID), .rsp = fdp_nci_prop_set_production_data_rsp_packet, }, }; struct nci_ops nci_ops = { .open = fdp_nci_open, .close = fdp_nci_close, .send = fdp_nci_send, .setup = fdp_nci_setup, .post_setup = fdp_nci_post_setup, .prop_ops = fdp_prop_ops, .n_prop_ops = ARRAY_SIZE(fdp_prop_ops), .core_ops = fdp_core_ops, .n_core_ops = ARRAY_SIZE(fdp_core_ops), };
int fdp_nci_probe(struct fdp_i2c_phy *phy, struct nfc_phy_ops *phy_ops, struct nci_dev **ndevp, int tx_headroom, int tx_tailroom, u8 clock_type, u32 clock_freq, u8 *fw_vsc_cfg) { struct device *dev = &phy->i2c_dev->dev; struct fdp_nci_info *info; struct nci_dev *ndev; u32 protocols; int r; info = devm_kzalloc(dev, sizeof(struct fdp_nci_info), GFP_KERNEL); if (!info) return -ENOMEM; info->phy = phy; info->phy_ops = phy_ops; info->clock_type = clock_type; info->clock_freq = clock_freq; info->fw_vsc_cfg = fw_vsc_cfg; init_waitqueue_head(&info->setup_wq); protocols = NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK | NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK | NFC_PROTO_ISO14443_B_MASK | NFC_PROTO_NFC_DEP_MASK | NFC_PROTO_ISO15693_MASK; ndev = nci_allocate_device(&nci_ops, protocols, tx_headroom, tx_tailroom); if (!ndev) { nfc_err(dev, "Cannot allocate nfc ndev\n"); return -ENOMEM; } r = nci_register_device(ndev); if (r) goto err_regdev; *ndevp = ndev; info->ndev = ndev; nci_set_drvdata(ndev, info); return 0; err_regdev: nci_free_device(ndev); return r; }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca21396.82%150.00%
Andy Shevchenko73.18%150.00%
Total220100.00%2100.00%

EXPORT_SYMBOL(fdp_nci_probe);
void fdp_nci_remove(struct nci_dev *ndev) { struct fdp_nci_info *info = nci_get_drvdata(ndev); struct device *dev = &info->phy->i2c_dev->dev; dev_dbg(dev, "%s\n", __func__); nci_unregister_device(ndev); nci_free_device(ndev); }

Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca53100.00%1100.00%
Total53100.00%1100.00%

EXPORT_SYMBOL(fdp_nci_remove); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("NFC NCI driver for Intel Fields Peak NFC controller"); MODULE_AUTHOR("Robert Dolca <robert.dolca@intel.com>");

Overall Contributors

PersonTokensPropCommitsCommitProp
Robert Dolca336199.56%116.67%
Andy Shevchenko70.21%116.67%
Christophe Ricard40.12%116.67%
Geert Uytterhoeven20.06%116.67%
Colin Ian King10.03%116.67%
Johannes Berg10.03%116.67%
Total3376100.00%6100.00%
Directory: drivers/nfc/fdp
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.