diff --git a/Android.mk b/Android.mk index f5eb11e2ed..3913c583d8 100644 --- a/Android.mk +++ b/Android.mk @@ -7,7 +7,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_MODULE := nfc_i2c.ko +LOCAL_MODULE := nxp-nci.ko LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT) LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/**/*) $(wildcard $(LOCAL_PATH)/*) diff --git a/Kbuild b/Kbuild index 14531aecd4..93012c8f01 100644 --- a/Kbuild +++ b/Kbuild @@ -6,10 +6,12 @@ LINUXINCLUDE += -I$(NFC_ROOT)/include/uapi/linux/nfc LINUXINCLUDE += -include $(NFC_ROOT)/config/gki_nfc_conf.h -obj-$(CONFIG_NFC_QTI_I2C) += nfc_i2c.o +obj-$(CONFIG_NXP_NFC_I2C) += nxp-nci.o #source files -nfc_i2c-objs += qti/ese_cold_reset.o \ - qti/nfc_common.o \ - qti/nfc_i2c_drv.o +nxp-nci-objs += nfc/ese_cold_reset.o \ + nfc/common.o \ + nfc/common_nxp.o \ + nfc/common_qcom.o \ + nfc/i2c_drv.o diff --git a/Kconfig b/Kconfig index 623e0ae0a0..facfd412a1 100644 --- a/Kconfig +++ b/Kconfig @@ -1,10 +1,13 @@ -menuconfig NFC_QTI_I2C - tristate "QTI NCI based NFC I2C Slave Driver for SNxxx" - depends on I2C - help - This enables the NFC driver for SNxxx based devices. - This is for I2C connected version. NCI protocol logic - resides in the usermode and it has no other NFC dependencies. +# +# near field communication driver configuration +# - If unsure, say N. +config NXP_NFC_I2C + tristate "NXP NCI based NFC I2C Slave Driver for SNxxx" + depends on I2C + help + This enables the NFC driver for SNxxx based devices. + This is for I2C connected version. NCI protocol logic + resides in the usermode and it has no other NFC dependencies. + If unsure, say N. diff --git a/config/gki_nfc.conf b/config/gki_nfc.conf index 2e606798ec..28cd8d20ed 100644 --- a/config/gki_nfc.conf +++ b/config/gki_nfc.conf @@ -1 +1 @@ -export CONFIG_NFC_QTI_I2C=m +export CONFIG_NXP_NFC_I2C=m diff --git a/config/gki_nfc_conf.h b/config/gki_nfc_conf.h index 745406be62..76869b9838 100644 --- a/config/gki_nfc_conf.h +++ b/config/gki_nfc_conf.h @@ -1,6 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. - */ + * + ***************************************************************************/ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + ***************************************************************************/ -#define CONFIG_NFC_QTI_I2C 1 +#define CONFIG_NXP_NFC_I2C 1 diff --git a/nfc/Kbuild b/nfc/Kbuild deleted file mode 100644 index 198d574a94..0000000000 --- a/nfc/Kbuild +++ /dev/null @@ -1,6 +0,0 @@ -obj-$(CONFIG_NXP_NFC_I2C) := pn553_i2c.o - -pn553_i2c-y := common.o \ - common_ese.o \ - i2c_drv.o - diff --git a/nfc/Kconfig b/nfc/Kconfig deleted file mode 100644 index facfd412a1..0000000000 --- a/nfc/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# -# near field communication driver configuration -# - -config NXP_NFC_I2C - tristate "NXP NCI based NFC I2C Slave Driver for SNxxx" - depends on I2C - help - This enables the NFC driver for SNxxx based devices. - This is for I2C connected version. NCI protocol logic - resides in the usermode and it has no other NFC dependencies. - - If unsure, say N. diff --git a/nfc/Makefile b/nfc/Makefile deleted file mode 100644 index 4191dea226..0000000000 --- a/nfc/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build - -all: - $(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS) - -modules_install: - $(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install - -clean: - $(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean diff --git a/nfc/common.c b/nfc/common.c index a4f8029fa1..c9b37cdcbb 100644 --- a/nfc/common.c +++ b/nfc/common.c @@ -17,17 +17,23 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ******************************************************************************/ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + *****************************************************************************/ #include #include #include -#include "common_ese.h" +#include "common.h" int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs, uint8_t interface) { + int ret; struct device_node *np = dev->of_node; struct platform_gpio *nfc_gpio = &nfc_configs->gpio; + struct platform_ldo *ldo = &nfc_configs->ldo; if (!np) { pr_err("%s: nfc of_node NULL\n", __func__); @@ -42,7 +48,7 @@ int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs, if (interface == PLATFORM_IF_I2C) { nfc_gpio->irq = of_get_named_gpio(np, DTS_IRQ_GPIO_STR, 0); if ((!gpio_is_valid(nfc_gpio->irq))) { - pr_err("%s: irq gpio invalid %d\n", __func__, + pr_err("%s: nfc irq gpio invalid %d\n", __func__, nfc_gpio->irq); return -EINVAL; } @@ -50,17 +56,38 @@ int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs, } nfc_gpio->ven = of_get_named_gpio(np, DTS_VEN_GPIO_STR, 0); if ((!gpio_is_valid(nfc_gpio->ven))) { - pr_err("%s: ven gpio invalid %d\n", __func__, nfc_gpio->ven); + pr_err("%s: nfc ven gpio invalid %d\n", __func__, nfc_gpio->ven); return -EINVAL; } /* some products like sn220 does not required fw dwl pin */ nfc_gpio->dwl_req = of_get_named_gpio(np, DTS_FWDN_GPIO_STR, 0); + /* not returning failure for dwl gpio as it is optional for sn220 */ if ((!gpio_is_valid(nfc_gpio->dwl_req))) - pr_warn("%s: dwl_req gpio invalid %d\n", __func__, + pr_warn("%s: nfc dwl_req gpio invalid %d\n", __func__, nfc_gpio->dwl_req); - pr_info("%s: %d, %d, %d\n", __func__, nfc_gpio->irq, nfc_gpio->ven, + pr_info("%s: irq %d, ven %d, dwl %d\n", __func__, nfc_gpio->irq, nfc_gpio->ven, nfc_gpio->dwl_req); + + /* optional property */ + ret = of_property_read_u32_array(np, NFC_LDO_VOL_DT_NAME, + (u32 *) ldo->vdd_levels, + ARRAY_SIZE(ldo->vdd_levels)); + if (ret) { + dev_err(dev, "error reading NFC VDDIO min and max value\n"); + // set default as per datasheet + ldo->vdd_levels[0] = NFC_VDDIO_MIN; + ldo->vdd_levels[1] = NFC_VDDIO_MAX; + } + + /* optional property */ + ret = of_property_read_u32(np, NFC_LDO_CUR_DT_NAME, &ldo->max_current); + if (ret) { + dev_err(dev, "error reading NFC current value\n"); + // set default as per datasheet + ldo->max_current = NFC_CURRENT_MAX; + } + return 0; } @@ -92,9 +119,6 @@ void gpio_set_ven(struct nfc_dev *nfc_dev, int value) if (gpio_get_value(nfc_gpio->ven) != value) { pr_debug("%s: value %d\n", __func__, value); - /* reset on change in level from high to low */ - if (value) - ese_cold_reset_release(nfc_dev); gpio_set_value(nfc_gpio->ven, value); /* hardware dependent delay */ @@ -168,10 +192,13 @@ void gpio_free_all(struct nfc_dev *nfc_dev) void nfc_misc_unregister(struct nfc_dev *nfc_dev, int count) { pr_debug("%s: entry\n", __func__); + kfree(nfc_dev->kbuf); device_destroy(nfc_dev->nfc_class, nfc_dev->devno); cdev_del(&nfc_dev->c_dev); class_destroy(nfc_dev->nfc_class); unregister_chrdev_region(nfc_dev->devno, count); + if (nfc_dev->ipcl) + ipc_log_context_destroy(nfc_dev->ipcl); } int nfc_misc_register(struct nfc_dev *nfc_dev, @@ -213,6 +240,23 @@ int nfc_misc_register(struct nfc_dev *nfc_dev, unregister_chrdev_region(nfc_dev->devno, count); return ret; } + nfc_dev->ipcl = ipc_log_context_create(NUM_OF_IPC_LOG_PAGES, + dev_name(nfc_dev->nfc_device), 0); + + nfc_dev->kbuflen = MAX_NCI_BUFFER_SIZE; + nfc_dev->kbuf = kzalloc(MAX_NCI_BUFFER_SIZE, GFP_KERNEL | GFP_DMA); + if (!nfc_dev->kbuf) { + nfc_misc_unregister(nfc_dev, count); + return -ENOMEM; + } + + nfc_dev->cold_reset.rsp_pending = false; + nfc_dev->cold_reset.is_nfc_enabled = false; + nfc_dev->cold_reset.is_crp_en = false; + nfc_dev->cold_reset.last_src_ese_prot = ESE_COLD_RESET_ORIGIN_NONE; + + init_waitqueue_head(&nfc_dev->cold_reset.read_wq); + return 0; } @@ -264,6 +308,7 @@ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg) * Setting firmware download gpio to HIGH * before FW download start */ + pr_debug("set fw gpio high\n"); set_valid_gpio(nfc_gpio->dwl_req, 1); nfc_dev->nfc_state = NFC_STATE_FW_DWL; @@ -272,15 +317,29 @@ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg) gpio_set_ven(nfc_dev, 0); gpio_set_ven(nfc_dev, 1); nfc_dev->nfc_enable_intr(nfc_dev); + pr_info("%s VEN forced reset done\n", __func__); + } else if (arg == NFC_FW_DWL_LOW) { /* * Setting firmware download gpio to LOW * FW download finished */ + pr_debug("set fw gpio LOW\n"); set_valid_gpio(nfc_gpio->dwl_req, 0); nfc_dev->nfc_state = NFC_STATE_NCI; - } else { - pr_err("%s: bad arg %lu\n", __func__, arg); + + } else if (arg == NFC_ENABLE) { + /* + * Setting flag true when NFC is enabled + */ + nfc_dev->cold_reset.is_nfc_enabled = true; + } else if (arg == NFC_DISABLE) { + /* + * Setting flag true when NFC is disabled + */ + nfc_dev->cold_reset.is_nfc_enabled = false; + } else { + pr_err("%s bad arg %lu\n", __func__, arg); ret = -ENOIOCTLCMD; } return ret; @@ -343,10 +402,17 @@ long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) case ESE_GET_PWR: ret = nfc_ese_pwr(nfc_dev, ESE_POWER_STATE); break; + case NFCC_GET_INFO: + ret = nfc_ioctl_nfcc_info(pfile, arg); + break; + case ESE_COLD_RESET: + pr_debug("nfc ese cold reset ioctl\n"); + ret = ese_cold_reset_ioctl(nfc_dev, arg); + break; default: pr_err("%s: bad cmd %lu\n", __func__, arg); ret = -ENOIOCTLCMD; - }; + } return ret; } @@ -413,14 +479,7 @@ int nfc_dev_close(struct inode *inode, struct file *filp) } if (nfc_dev->dev_ref_count > 0) nfc_dev->dev_ref_count = nfc_dev->dev_ref_count - 1; - else { - /* - * Use "ESE_RST_PROT_DIS" as argument - * if eSE calls flow is via NFC driver - * i.e. direct calls from SPI HAL to NFC driver - */ - nfc_ese_pwr(nfc_dev, ESE_RST_PROT_DIS_NFC); - } + filp->private_data = NULL; mutex_unlock(&nfc_dev->dev_ref_mutex); diff --git a/nfc/common.h b/nfc/common.h index bcdd26dd33..1c723bf79c 100644 --- a/nfc/common.h +++ b/nfc/common.h @@ -17,41 +17,68 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ******************************************************************************/ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + *****************************************************************************/ #ifndef _COMMON_H_ #define _COMMON_H_ #include - +#include +#include +#include +#include #include "i2c_drv.h" +#include "ese_cold_reset.h" /* Max device count for this driver */ #define DEV_COUNT 1 /* i2c device class */ -#define CLASS_NAME "nfc" +#define CLASS_NAME "qti-nfc" /* NFC character device name, this will be in /dev/ */ -#define NFC_CHAR_DEV_NAME "pn553" +#define NFC_CHAR_DEV_NAME "nq-nci" /* NCI packet details */ #define NCI_CMD (0x20) #define NCI_RSP (0x40) +#define NCI_NTF (0x60) #define NCI_HDR_LEN (3) #define NCI_HDR_IDX (0) +#define DL_CMD 0x00 +#define DL_PAYLOAD_BYTE_ZERO 0x00 #define NCI_HDR_OID_IDX (1) #define NCI_PAYLOAD_IDX (3) #define NCI_PAYLOAD_LEN_IDX (2) -/* FW DNLD packet details */ +/*Time to wait for first NCI rest response*/ +#define NCI_RESET_RESP_READ_DELAY (10000) // 10ms +#define NCI_RESET_RESP_TIMEOUT (500) // 500ms + +// FW DNLD packet details +#define FW_MSG_CMD_RSP 0x00 #define DL_HDR_LEN (2) +#define FW_PAYLOAD_LEN_IDX 1 #define DL_CRC_LEN (2) +#define NCI_RSP_PKT_TYPE (0x40) +#define FW_MIN_PAYLOAD_LEN 4 +#define MIN_NFC_DL_FRAME_SIZE 3 + +#define GET_VERSION_CMD_LEN 8 +#define GET_SESSION_STATE_CMD_LEN 8 #define MAX_NCI_PAYLOAD_LEN (255) #define MAX_NCI_BUFFER_SIZE (NCI_HDR_LEN + MAX_NCI_PAYLOAD_LEN) +/* + * From MW 11.04 buffer size increased to support + * frame size of 554 in FW download mode + * Frame len(2) + Frame Header(6) + DATA(512) + HASH(32) + CRC(2) + RFU(4) + */ #define MAX_DL_PAYLOAD_LEN (550) #define MAX_DL_BUFFER_SIZE (DL_HDR_LEN + DL_CRC_LEN + \ MAX_DL_PAYLOAD_LEN) - /* Retry count for normal write */ #define NO_RETRY (1) /* Maximum retry count for standby writes */ @@ -64,6 +91,8 @@ #define NCI_CMD_RSP_TIMEOUT_MS (2000) /* Time to wait for NFCC to be ready again after any change in the GPIO */ #define NFC_GPIO_SET_WAIT_TIME_US (10000) +/*Time to wait after soft reset via any NCI/DL cmd*/ +#define NFC_SOFT_RESET_WAIT_TIME_USEC (5000) /* Time to wait for IRQ low during write 5*3ms */ #define NFC_WRITE_IRQ_WAIT_TIME_US (3000) /* Time to wait before retrying i2c/I3C writes */ @@ -72,15 +101,51 @@ #define READ_RETRY_WAIT_TIME_US (3500) #define NFC_MAGIC (0xE9) -/* Ioctls */ -/* The type should be aligned with MW HAL definitions */ -#define NFC_SET_PWR _IOW(NFC_MAGIC, 0x01, uint32_t) -#define ESE_SET_PWR _IOW(NFC_MAGIC, 0x02, uint32_t) -#define ESE_GET_PWR _IOR(NFC_MAGIC, 0x03, uint32_t) +// Ioctls +// The type should be aligned with MW HAL definitions -#define DTS_IRQ_GPIO_STR "nxp,pn544-irq" -#define DTS_VEN_GPIO_STR "nxp,pn544-ven" -#define DTS_FWDN_GPIO_STR "nxp,pn544-fw-dwnld" +#define NFC_SET_PWR _IOW(NFC_MAGIC, 0x01, unsigned int) +#define ESE_SET_PWR _IOW(NFC_MAGIC, 0x02, unsigned int) +#define ESE_GET_PWR _IOR(NFC_MAGIC, 0x03, unsigned int) + +#define DTS_IRQ_GPIO_STR "qcom,sn-irq" +#define DTS_VEN_GPIO_STR "qcom,sn-ven" +#define DTS_FWDN_GPIO_STR "qcom,sn-firm" +#define NFC_LDO_SUPPLY_DT_NAME "qcom,sn-vdd-1p8" +#define NFC_LDO_SUPPLY_NAME "qcom,sn-vdd-1p8-supply" +#define NFC_LDO_VOL_DT_NAME "qcom,sn-vdd-1p8-voltage" +#define NFC_LDO_CUR_DT_NAME "qcom,sn-vdd-1p8-current" + +//as per SN1x0 datasheet +#define NFC_VDDIO_MIN 1650000 //in uV +#define NFC_VDDIO_MAX 1950000 //in uV +#define NFC_CURRENT_MAX 157000 //in uA + + +#define NUM_OF_IPC_LOG_PAGES (2) +#define PKT_MAX_LEN (4) // no of max bytes to print for cmd/resp + +#define GET_IPCLOG_MAX_PKT_LEN(c) ((c > PKT_MAX_LEN) ? PKT_MAX_LEN : c) + +#define NFCLOG_IPC(nfc_dev, log_to_dmesg, x...) \ +do { \ + ipc_log_string(nfc_dev->ipcl, x); \ + if (log_to_dmesg) { \ + if (nfc_dev->nfc_device) \ + dev_err((nfc_dev->nfc_device), x); \ + else \ + pr_err(x); \ + } \ +} while (0) + +enum ese_ioctl_request { + /* eSE POWER ON */ + ESE_POWER_ON = 0, + /* eSE POWER OFF */ + ESE_POWER_OFF, + /* eSE POWER STATE */ + ESE_POWER_STATE +}; enum nfcc_ioctl_request { /* NFC disable request with VEN LOW */ @@ -97,6 +162,10 @@ enum nfcc_ioctl_request { NFC_VEN_FORCED_HARD_RESET, /* request for firmware download gpio LOW */ NFC_FW_DWL_LOW, + /* NFC enable without VEN gpio modification */ + NFC_ENABLE, + /* NFC disable without VEN gpio modification */ + NFC_DISABLE, }; /* nfc platform interface type */ @@ -142,21 +211,18 @@ struct platform_gpio { unsigned int dwl_req; }; +// NFC LDO entries from DT +struct platform_ldo { + int vdd_levels[2]; + int max_current; +}; + /* NFC Struct to get all the required configs from DTS */ struct platform_configs { struct platform_gpio gpio; + struct platform_ldo ldo; }; -/* cold reset Features specific Parameters */ -struct cold_reset { - bool rsp_pending; /* cmd rsp pending status */ - bool in_progress; /* for cold reset when gurad timer in progress */ - bool reset_protection; /* reset protection enabled/disabled */ - uint8_t status; /* status from response buffer */ - uint8_t rst_prot_src; /* reset protection source (SPI, NFC) */ - struct timer_list timer; - wait_queue_head_t read_wq; -}; /* Device specific structure */ struct nfc_dev { @@ -177,12 +243,25 @@ struct nfc_dev { uint8_t nfc_state; /* NFC VEN pin state */ bool nfc_ven_enabled; + /* current firmware major version */ + uint8_t fw_major_version; + bool is_vreg_enabled; + bool is_ese_session_active; bool release_read; union { struct i2c_dev i2c_dev; }; struct platform_configs configs; struct cold_reset cold_reset; + struct regulator *reg; + + /* read buffer*/ + size_t kbuflen; + u8 *kbuf; + + union nqx_uinfo nqx_info; + + void *ipcl; /* function pointers for the common i2c functionality */ int (*nfc_read)(struct nfc_dev *dev, char *buf, size_t count, @@ -207,6 +286,14 @@ int nfc_misc_register(struct nfc_dev *nfc_dev, void nfc_misc_unregister(struct nfc_dev *nfc_dev, int count); int configure_gpio(unsigned int gpio, int flag); void gpio_set_ven(struct nfc_dev *nfc_dev, int value); +void set_valid_gpio(int gpio, int value); +int nfcc_hw_check(struct nfc_dev *nfc_dev); +unsigned int nfc_ioctl_nfcc_info(struct file *, unsigned long); void gpio_free_all(struct nfc_dev *nfc_dev); +int nfc_ldo_config(struct device *dev, struct nfc_dev *nfc_dev); +int nfc_ldo_vote(struct nfc_dev *nfc_dev); +int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg); +int nfc_ldo_unvote(struct nfc_dev *nfc_dev); +int is_nfc_data_available_for_read(struct nfc_dev *nfc_dev); int validate_nfc_state_nci(struct nfc_dev *nfc_dev); #endif /* _COMMON_H_ */ diff --git a/nfc/common_ese.c b/nfc/common_ese.c deleted file mode 100644 index 5c725a6845..0000000000 --- a/nfc/common_ese.c +++ /dev/null @@ -1,361 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2020-2021 NXP - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ******************************************************************************/ -#include -#include -#include - -#include "common_ese.h" - -static void cold_reset_gaurd_timer_callback(struct timer_list *t) -{ - struct cold_reset *cold_reset = from_timer(cold_reset, t, timer); - - pr_debug("%s: entry\n", __func__); - cold_reset->in_progress = false; -} - -static long start_cold_reset_guard_timer(struct cold_reset *cold_reset) -{ - long ret = -EINVAL; - - if (timer_pending(&cold_reset->timer) == 1) { - pr_debug("%s: delete pending timer\n", __func__); - /* delete timer if already pending */ - del_timer(&cold_reset->timer); - } - cold_reset->in_progress = true; - timer_setup(&cold_reset->timer, cold_reset_gaurd_timer_callback, 0); - ret = mod_timer(&cold_reset->timer, - jiffies + msecs_to_jiffies(ESE_CLD_RST_GUARD_TIME_MS)); - return ret; -} - -static int send_cold_reset_protection_cmd(struct nfc_dev *nfc_dev, - bool requestType) -{ - int ret = 0; - int cmd_length = 0; - uint8_t *cmd = nfc_dev->write_kbuf; - struct cold_reset *cold_reset = &nfc_dev->cold_reset; - - *cmd++ = NCI_PROP_MSG_CMD; - - if (requestType) { /* reset protection */ - *cmd++ = RST_PROT_OID; - *cmd++ = RST_PROT_PAYLOAD_SIZE; - *cmd++ = (!cold_reset->reset_protection) ? 1 : 0; - } else { /* cold reset */ - *cmd++ = CLD_RST_OID; - *cmd++ = CLD_RST_PAYLOAD_SIZE; - } - cmd_length = cmd - nfc_dev->write_kbuf; - - ret = nfc_dev->nfc_write(nfc_dev, nfc_dev->write_kbuf, cmd_length, - MAX_RETRY_COUNT); - if (ret != cmd_length) { - ret = -EIO; - pr_err("%s: nfc_write returned %d\n", __func__, ret); - goto exit; - } - cmd = nfc_dev->write_kbuf; - if (requestType) - pr_debug(" %s: NxpNciX: %d > 0x%02x%02x%02x%02x\n", __func__, - ret, cmd[NCI_HDR_IDX], cmd[NCI_HDR_OID_IDX], - cmd[NCI_PAYLOAD_LEN_IDX], cmd[NCI_PAYLOAD_IDX]); - else - pr_debug(" %s: NxpNciX: %d > 0x%02x%02x%02x\n", __func__, ret, - cmd[NCI_HDR_IDX], cmd[NCI_HDR_OID_IDX], - cmd[NCI_PAYLOAD_LEN_IDX]); -exit: - return ret; -} - -void wakeup_on_prop_rsp(struct nfc_dev *nfc_dev, uint8_t *buf) -{ - struct cold_reset *cold_reset = &nfc_dev->cold_reset; - - cold_reset->status = -EIO; - if ((NCI_HDR_LEN + buf[NCI_PAYLOAD_LEN_IDX]) != NCI_PROP_MSG_RSP_LEN) - pr_err("%s: invalid response for cold_reset/protection\n", - __func__); - else - cold_reset->status = buf[NCI_PAYLOAD_IDX]; - - pr_debug(" %s: NxpNciR 0x%02x%02x%02x%02x\n", __func__, - buf[NCI_HDR_IDX], buf[NCI_HDR_OID_IDX], - buf[NCI_PAYLOAD_LEN_IDX], buf[NCI_PAYLOAD_IDX]); - - cold_reset->rsp_pending = false; - wake_up_interruptible(&cold_reset->read_wq); -} - -static int validate_cold_reset_protection_request(struct cold_reset *cold_reset, - unsigned long arg) -{ - int ret = 0; - - if (!cold_reset->reset_protection) { - if (IS_RST_PROT_EN_REQ(arg) && IS_SRC_VALID_PROT(arg)) { - pr_debug("%s: reset protection enable\n", __func__); - } else if (IS_CLD_RST_REQ(arg) && IS_SRC_VALID(arg)) { - pr_debug("%s: cold reset\n", __func__); - } else if (IS_RST_PROT_DIS_REQ(arg) && IS_SRC_VALID_PROT(arg)) { - pr_debug("%s: reset protection already disable\n", - __func__); - ret = -EINVAL; - } else { - pr_err("%s: operation not permitted\n", __func__); - ret = -EPERM; - } - } else { - if (IS_RST_PROT_DIS_REQ(arg) && - IS_SRC(arg, cold_reset->rst_prot_src)) { - pr_debug("%s: disable reset protection from same src\n", - __func__); - } else if (IS_CLD_RST_REQ(arg) && - IS_SRC(arg, cold_reset->rst_prot_src)) { - pr_debug("%s: cold reset from same source\n", __func__); - } else if (IS_RST_PROT_EN_REQ(arg) && - IS_SRC(arg, cold_reset->rst_prot_src)) { - pr_debug("%s: enable reset protection from same src\n", - __func__); - } else { - pr_err("%s: operation not permitted\n", __func__); - ret = -EPERM; - } - } - return ret; -} - -static int perform_cold_reset_protection(struct nfc_dev *nfc_dev, - unsigned long arg) -{ - int ret = 0; - int timeout = 0; - char *rsp = nfc_dev->read_kbuf; - struct cold_reset *cold_reset = &nfc_dev->cold_reset; - - /* check if NFCC not in the FW download or hard reset state */ - ret = validate_nfc_state_nci(nfc_dev); - if (ret < 0) { - pr_err("%s: invalid cmd\n", __func__); - return ret; - } - - /* check if NFCC not in the FW download or hard reset state */ - ret = validate_cold_reset_protection_request(cold_reset, arg); - if (ret < 0) { - pr_err("%s: invalid cmd\n", __func__); - goto err; - } - - /* check if cold reset already in progress */ - if (IS_CLD_RST_REQ(arg) && cold_reset->in_progress) { - pr_err("%s: cold reset already in progress\n", __func__); - ret = -EBUSY; - goto err; - } - - /* enable interrupt if not enabled incase when devnode not opened by HAL */ - nfc_dev->nfc_enable_intr(nfc_dev); - - mutex_lock(&nfc_dev->write_mutex); - /* write api has 15ms maximum wait to clear any pending read before */ - cold_reset->status = -EIO; - cold_reset->rsp_pending = true; - ret = send_cold_reset_protection_cmd(nfc_dev, IS_RST_PROT_REQ(arg)); - if (ret < 0) { - mutex_unlock(&nfc_dev->write_mutex); - cold_reset->rsp_pending = false; - pr_err("%s: failed to send cold reset/protection cmd\n", - __func__); - goto err; - } - - ret = 0; - /* start the cold reset guard timer */ - if (IS_CLD_RST_REQ(arg)) { - /* Guard timer not needed when OSU over NFC */ - if (!(cold_reset->reset_protection && IS_SRC_NFC(arg))) { - ret = start_cold_reset_guard_timer(cold_reset); - if (ret) { - mutex_unlock(&nfc_dev->write_mutex); - pr_err("%s: error in mod_timer\n", __func__); - goto err; - } - } - } - - timeout = NCI_CMD_RSP_TIMEOUT_MS; - do { - /* call read api directly if reader thread is not blocked */ - if (mutex_trylock(&nfc_dev->read_mutex)) { - pr_debug("%s: reader thread not pending\n", __func__); - ret = nfc_dev->nfc_read(nfc_dev, rsp, 3, - timeout); - mutex_unlock(&nfc_dev->read_mutex); - if (!ret) - break; - usleep_range(READ_RETRY_WAIT_TIME_US, - READ_RETRY_WAIT_TIME_US + 500); - /* Read pending response form the HAL service */ - } else if (!wait_event_interruptible_timeout( - cold_reset->read_wq, - cold_reset->rsp_pending == false, - msecs_to_jiffies(timeout))) { - pr_err("%s: cold reset/prot response timeout\n", __func__); - ret = -EAGAIN; - } - } while (ret == -ERESTARTSYS || ret == -EFAULT); - mutex_unlock(&nfc_dev->write_mutex); - - timeout = ESE_CLD_RST_REBOOT_GUARD_TIME_MS; - if (ret == 0) { /* success case */ - ret = cold_reset->status; - if (IS_RST_PROT_REQ(arg)) { - cold_reset->reset_protection = IS_RST_PROT_EN_REQ(arg); - cold_reset->rst_prot_src = IS_RST_PROT_EN_REQ(arg) ? - GET_SRC(arg) : - SRC_NONE; - /* wait for reboot guard timer */ - } else if (wait_event_interruptible_timeout( - cold_reset->read_wq, true, - msecs_to_jiffies(timeout)) == 0) { - pr_info("%s: reboot guard timer timeout\n", __func__); - } - } -err: - mutex_unlock(&nfc_dev->dev_ref_mutex); - return ret; -} - -/** - * nfc_ese_pwr() - power control for ese - * @nfc_dev: nfc device data structure - * @arg: mode that we want to move to - * - * Device power control. Depending on the arg value, device moves to - * different states, refer common_ese.h for args - * - * Return: -ENOIOCTLCMD if arg is not supported - * 0 if Success(or no issue) - * 0 or 1 in case of arg is ESE_POWER_STATE - * and error ret code otherwise - */ -int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg) -{ - int ret = 0; - struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; - - if (arg == ESE_POWER_ON) { - /* - * Let's store the NFC VEN pin state - * will check stored value in case of eSE power off request, - * to find out if NFC MW also sent request to set VEN HIGH - * VEN state will remain HIGH if NFC is enabled otherwise - * it will be set as LOW - */ - nfc_dev->nfc_ven_enabled = gpio_get_value(nfc_gpio->ven); - if (!nfc_dev->nfc_ven_enabled) { - pr_debug("%s: ese hal service setting ven high\n", - __func__); - gpio_set_ven(nfc_dev, 1); - } else { - pr_debug("%s: ven already high\n", __func__); - } - } else if (arg == ESE_POWER_OFF) { - if (!nfc_dev->nfc_ven_enabled) { - pr_debug("%s: nfc not enabled, disabling ven\n", - __func__); - gpio_set_ven(nfc_dev, 0); - } else { - pr_debug("%s: keep ven high as nfc is enabled\n", - __func__); - } - } else if (arg == ESE_POWER_STATE) { - /* eSE get power state */ - ret = gpio_get_value(nfc_gpio->ven); - } else if (IS_CLD_RST_REQ(arg) || IS_RST_PROT_REQ(arg)) { - ret = perform_cold_reset_protection(nfc_dev, arg); - } else { - pr_err("%s: bad arg %lu\n", __func__, arg); - ret = -ENOIOCTLCMD; - } - return ret; -} -EXPORT_SYMBOL(nfc_ese_pwr); - -#define ESE_LEGACY_INTERFACE -#ifdef ESE_LEGACY_INTERFACE -static struct nfc_dev *nfc_dev_legacy; - -/****************************************************************************** - * perform_ese_cold_reset() - It shall be called by others driver(not nfc/ese) - * to perform cold reset only - * @arg: request of cold reset from other drivers should be ESE_CLD_RST_OTHER - * - * Returns:- 0 in case of success and negative values in case of failure - *****************************************************************************/ -int perform_ese_cold_reset(unsigned long arg) -{ - int ret = 0; - - if (nfc_dev_legacy) { - if (IS_CLD_RST_REQ(arg) && IS_SRC_OTHER(arg)) { - ret = nfc_ese_pwr(nfc_dev_legacy, arg); - } else { - pr_err("%s: operation not permitted\n", __func__); - return -EPERM; - } - } - pr_debug("%s: arg = %d ret = %lu\n", __func__, arg, ret); - return ret; -} -EXPORT_SYMBOL(perform_ese_cold_reset); -#endif /* ESE_LEGACY_INTERFACE */ - -void ese_cold_reset_release(struct nfc_dev *nfc_dev) -{ - struct cold_reset *cold_reset = &nfc_dev->cold_reset; - - cold_reset->rsp_pending = false; - cold_reset->in_progress = false; - if (timer_pending(&cold_reset->timer) == 1) - del_timer(&cold_reset->timer); -} - -void common_ese_init(struct nfc_dev *nfc_dev) -{ - struct cold_reset *cold_reset = &nfc_dev->cold_reset; - - cold_reset->reset_protection = false; - cold_reset->rst_prot_src = SRC_NONE; - init_waitqueue_head(&cold_reset->read_wq); - ese_cold_reset_release(nfc_dev); -#ifdef ESE_LEGACY_INTERFACE - nfc_dev_legacy = nfc_dev; -#endif /* ESE_LEGACY_INTERFACE */ -} - -void common_ese_exit(struct nfc_dev *nfc_dev) -{ -#ifdef ESE_LEGACY_INTERFACE - nfc_dev_legacy = NULL; -#endif /* ESE_LEGACY_INTERFACE */ -} diff --git a/nfc/common_ese.h b/nfc/common_ese.h deleted file mode 100644 index c8d563724b..0000000000 --- a/nfc/common_ese.h +++ /dev/null @@ -1,99 +0,0 @@ -/****************************************************************************** - * Copyright (C) 2020-2021 NXP - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ******************************************************************************/ -#ifndef _COMMON_ESE_H_ -#define _COMMON_ESE_H_ - -#include "common.h" - -/* nci prop msg 1st byte */ -#define NCI_PROP_MSG_GID 0x0F -#define NCI_PROP_MSG_CMD (NCI_CMD | NCI_PROP_MSG_GID) -#define NCI_PROP_MSG_RSP (NCI_RSP | NCI_PROP_MSG_GID) - -/* nci prop msg 2nd byte */ -#define CLD_RST_OID 0x1E -#define RST_PROT_OID 0x1F - -/* nci prop msg 3rd byte */ -#define CLD_RST_PAYLOAD_SIZE 0x00 -#define RST_PROT_PAYLOAD_SIZE 0x01 - -/* nci prop msg response length */ -#define NCI_PROP_MSG_RSP_LEN 0x04 - -/* cold reset guard time to allow back to back cold reset after some time */ -#define ESE_CLD_RST_GUARD_TIME_MS (3000) -/* guard time to reboot after reset */ -#define ESE_CLD_RST_REBOOT_GUARD_TIME_MS (50) -/* sources of reset protection and cold reset */ -enum reset_source { - SRC_SPI = 0, - SRC_NFC = 0x10, - SRC_OTHER = 0x20, - SRC_NONE = 0x80, -}; - -enum ese_ioctl_request { - ESE_POWER_ON = 0, /* eSE POWER ON */ - ESE_POWER_OFF, /* eSE POWER OFF */ - ESE_POWER_STATE, /* eSE GET POWER STATE */ - - /* ese reset requests from eSE service/hal/driver */ - ESE_CLD_RST, /* eSE COLD RESET */ - ESE_RST_PROT_EN, /* eSE RESET PROTECTION ENABLE */ - ESE_RST_PROT_DIS, /* eSE RESET PROTECTION DISABLE */ - - /* similar ese reset requests from nfc service/hal/driver */ - ESE_CLD_RST_NFC = ESE_CLD_RST | SRC_NFC, - ESE_RST_PROT_EN_NFC = ESE_RST_PROT_EN | SRC_NFC, - ESE_RST_PROT_DIS_NFC = ESE_RST_PROT_DIS | SRC_NFC, - - /* similar ese reset requests from other service/hal/driver */ - ESE_CLD_RST_OTHER = ESE_CLD_RST | SRC_OTHER, -}; - -#define GET_SRC(arg) (arg & 0xF0) -#define IS_SRC(arg, src) (GET_SRC(arg) == src) -#define IS_SRC_SPI(arg) IS_SRC(arg, SRC_SPI) -#define IS_SRC_NFC(arg) IS_SRC(arg, SRC_NFC) -#define IS_SRC_OTHER(arg) IS_SRC(arg, SRC_OTHER) -#define IS_SRC_VALID(arg) (IS_SRC_SPI(arg) || \ - IS_SRC_NFC(arg) || \ - IS_SRC_OTHER(arg)) -#define IS_SRC_VALID_PROT(arg) (IS_SRC_SPI(arg) || \ - IS_SRC_NFC(arg)) - -#define IS_RST(arg, type) ((arg & 0xF) == type) -#define IS_CLD_RST_REQ(arg) IS_RST(arg, ESE_CLD_RST) -#define IS_RST_PROT_EN_REQ(arg) IS_RST(arg, ESE_RST_PROT_EN) -#define IS_RST_PROT_DIS_REQ(arg) IS_RST(arg, ESE_RST_PROT_DIS) -#define IS_RST_PROT_REQ(arg) (IS_RST_PROT_EN_REQ(arg) || \ - IS_RST_PROT_DIS_REQ(arg)) -/* This macro evaluates to 1 if prop cmd response is received */ -#define IS_PROP_CMD_RSP(buf) ((buf[0] == NCI_PROP_MSG_RSP) && \ - ((buf[1] == CLD_RST_OID) || \ - (buf[1] == RST_PROT_OID))) - -void wakeup_on_prop_rsp(struct nfc_dev *nfc_dev, uint8_t *buf); -int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg); -void ese_cold_reset_release(struct nfc_dev *nfc_dev); -void common_ese_init(struct nfc_dev *nfc_dev); -void common_ese_exit(struct nfc_dev *nfc_dev); - -#endif /* _COMMON_ESE_H_ */ diff --git a/nfc/common_nxp.c b/nfc/common_nxp.c new file mode 100644 index 0000000000..8211a7cab6 --- /dev/null +++ b/nfc/common_nxp.c @@ -0,0 +1,332 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 NXP + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + ******************************************************************************/ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + ******************************************************************************/ +#include "common.h" +#include "common_nxp.h" + +/** + * get_nfcc_chip_type_dl() - get chip type in fw download command; + * @nfc_dev: nfc device data structure + * + * Perform get version command and determine chip + * type from response. + * + * @Return: enum chip_types value + * + */ +static enum chip_types get_nfcc_chip_type_dl(struct nfc_dev *nfc_dev) +{ + int ret = 0; + uint8_t *cmd = nfc_dev->write_kbuf; + uint8_t *rsp = nfc_dev->read_kbuf; + enum chip_types chip_type = CHIP_UNKNOWN; + + *cmd++ = DL_CMD; + *cmd++ = DL_GET_VERSION_CMD_PAYLOAD_LEN; + *cmd++ = DL_GET_VERSION_CMD_ID; + *cmd++ = DL_PAYLOAD_BYTE_ZERO; + *cmd++ = DL_PAYLOAD_BYTE_ZERO; + *cmd++ = DL_PAYLOAD_BYTE_ZERO; + *cmd++ = DL_GET_VERSION_CMD_CRC_1; + *cmd++ = DL_GET_VERSION_CMD_CRC_2; + + pr_debug("%s:Sending GET_VERSION cmd of size = %d\n", __func__, DL_GET_VERSION_CMD_LEN); + ret = nfc_dev->nfc_write(nfc_dev, nfc_dev->write_kbuf, DL_GET_VERSION_CMD_LEN, + MAX_RETRY_COUNT); + if (ret <= 0) { + pr_err("%s: - nfc get version cmd error ret %d\n", __func__, ret); + goto err; + } + memset(rsp, 0x00, DL_GET_VERSION_RSP_LEN_2); + pr_debug("%s:Reading response of GET_VERSION cmd\n", __func__); + ret = nfc_dev->nfc_read(nfc_dev, rsp, DL_GET_VERSION_RSP_LEN_2, NCI_CMD_RSP_TIMEOUT_MS); + if (ret <= 0) { + pr_err("%s: - nfc get version rsp error ret %d\n", __func__, ret); + goto err; + } + if (rsp[0] == FW_MSG_CMD_RSP && ret >= DL_GET_VERSION_RSP_LEN_2) { + + nfc_dev->fw_major_version = rsp[FW_MAJOR_VER_OFFSET]; + + if (rsp[FW_ROM_CODE_VER_OFFSET] == SN1XX_ROM_VER && + rsp[FW_MAJOR_VER_OFFSET] == SN1xx_MAJOR_VER) + chip_type = CHIP_SN1XX; + else if (rsp[FW_ROM_CODE_VER_OFFSET] == SN220_ROM_VER && + rsp[FW_MAJOR_VER_OFFSET] == SN220_MAJOR_VER) + chip_type = CHIP_SN220; + + pr_debug("%s:NFC Chip Type 0x%02x Rom Version 0x%02x FW Minor 0x%02x Major 0x%02x\n", + __func__, rsp[GET_VERSION_RSP_CHIP_TYPE_OFFSET], + rsp[FW_ROM_CODE_VER_OFFSET], + rsp[GET_VERSION_RSP_MINOR_VERSION_OFFSET], + rsp[FW_MAJOR_VER_OFFSET]); + + nfc_dev->nqx_info.info.chip_type = rsp[GET_VERSION_RSP_CHIP_TYPE_OFFSET]; + nfc_dev->nqx_info.info.rom_version = rsp[FW_ROM_CODE_VER_OFFSET]; + nfc_dev->nqx_info.info.fw_minor = rsp[GET_VERSION_RSP_MINOR_VERSION_OFFSET]; + nfc_dev->nqx_info.info.fw_major = rsp[FW_MAJOR_VER_OFFSET]; + } +err: + return chip_type; +} + +/** + * get_nfcc_session_state_dl() - gets the session state + * @nfc_dev: nfc device data structure + * + * Performs get session command and determine + * the nfcc state based on session status. + * + * @Return nfcc state based on session status. + * NFC_STATE_FW_TEARED if sessionis not closed + * NFC_STATE_FW_DWL if session closed + * NFC_STATE_UNKNOWN in error cases. + */ +enum nfc_state_flags get_nfcc_session_state_dl(struct nfc_dev *nfc_dev) +{ + int ret = 0; + uint8_t *cmd = nfc_dev->write_kbuf; + uint8_t *rsp = nfc_dev->read_kbuf; + enum nfc_state_flags nfc_state = NFC_STATE_UNKNOWN; + + *cmd++ = DL_CMD; + *cmd++ = DL_GET_SESSION_STATE_CMD_PAYLOAD_LEN; + *cmd++ = DL_GET_SESSION_CMD_ID; + *cmd++ = DL_PAYLOAD_BYTE_ZERO; + *cmd++ = DL_PAYLOAD_BYTE_ZERO; + *cmd++ = DL_PAYLOAD_BYTE_ZERO; + *cmd++ = DL_GET_SESSION_CMD_CRC_1; + *cmd++ = DL_GET_SESSION_CMD_CRC_2; + + pr_debug("%s:Sending GET_SESSION_STATE cmd of size = %d\n", __func__, + DL_GET_SESSION_STATE_CMD_LEN); + ret = nfc_dev->nfc_write(nfc_dev, nfc_dev->write_kbuf, DL_GET_SESSION_STATE_CMD_LEN, + MAX_RETRY_COUNT); + if (ret <= 0) { + pr_err("%s: - nfc get session cmd error ret %d\n", __func__, ret); + goto err; + } + memset(rsp, 0x00, DL_GET_SESSION_STATE_RSP_LEN); + pr_debug("%s:Reading response of GET_SESSION_STATE cmd\n", __func__); + ret = nfc_dev->nfc_read(nfc_dev, rsp, DL_GET_SESSION_STATE_RSP_LEN, NCI_CMD_RSP_TIMEOUT_MS); + if (ret <= 0) { + pr_err("%s: - nfc get session rsp error ret %d\n", __func__, ret); + goto err; + } + if (rsp[0] != FW_MSG_CMD_RSP) { + pr_err("%s: - nfc invalid get session state rsp\n", __func__); + goto err; + } + pr_debug("Response bytes are %02x%02x%02x%02x%02x%02x%02x%02x\n", + rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5], rsp[6], rsp[7]); + /*verify fw in non-teared state */ + if (rsp[GET_SESSION_STS_OFF] != NFCC_SESSION_STS_CLOSED) { + pr_err("%s NFCC booted in FW teared state\n", __func__); + nfc_state = NFC_STATE_FW_TEARED; + } else { + pr_info("%s NFCC booted in FW DN mode\n", __func__); + nfc_state = NFC_STATE_FW_DWL; + } +err: + return nfc_state; +} + +/** + * get_nfcc_chip_type() - get nfcc chip type in nci mode. + * @nfc_dev: nfc device data structure. + * + * Function to perform nci core reset and extract + * chip type from the response. + * + * @Return: enum chip_types value + * + */ +static enum chip_types get_nfcc_chip_type(struct nfc_dev *nfc_dev) +{ + int ret = 0; + uint8_t major_version = 0; + uint8_t rom_version = 0; + uint8_t *cmd = nfc_dev->write_kbuf; + uint8_t *rsp = nfc_dev->read_kbuf; + enum chip_types chip_type = CHIP_UNKNOWN; + + *cmd++ = NCI_CMD; + *cmd++ = NCI_CORE_RESET_CMD_OID; + *cmd++ = NCI_CORE_RESET_CMD_PAYLOAD_LEN; + *cmd++ = NCI_CORE_RESET_KEEP_CONFIG; + + pr_debug("%s:Sending NCI Core Reset cmd of size = %d\n", __func__, NCI_RESET_CMD_LEN); + ret = nfc_dev->nfc_write(nfc_dev, nfc_dev->write_kbuf, NCI_RESET_CMD_LEN, NO_RETRY); + if (ret <= 0) { + pr_err("%s: - nfc nci core reset cmd error ret %d\n", __func__, ret); + goto err; + } + + /* to flush out debug NTF this delay is required */ + usleep_range(NCI_RESET_RESP_READ_DELAY, NCI_RESET_RESP_READ_DELAY + 100); + nfc_dev->nfc_enable_intr(nfc_dev); + + memset(rsp, 0x00, NCI_RESET_RSP_LEN); + pr_debug("%s:Reading NCI Core Reset rsp\n", __func__); + ret = nfc_dev->nfc_read(nfc_dev, rsp, NCI_RESET_RSP_LEN, NCI_CMD_RSP_TIMEOUT_MS); + if (ret <= 0) { + pr_err("%s: - nfc nci core reset rsp error ret %d\n", __func__, ret); + goto err_disable_intr; + } + + pr_debug(" %s: nci core reset response 0x%02x%02x%02x%02x\n", + __func__, rsp[0], rsp[1], rsp[2], rsp[3]); + if (rsp[0] != NCI_RSP) { + /* reset response failed response*/ + pr_err("%s invalid nci core reset response\n", __func__); + goto err_disable_intr; + } + + memset(rsp, 0x00, NCI_RESET_NTF_LEN); + /* read nci rest response ntf */ + ret = nfc_dev->nfc_read(nfc_dev, rsp, NCI_RESET_NTF_LEN, NCI_CMD_RSP_TIMEOUT_MS); + if (ret <= 0) { + pr_err("%s - nfc nci rest rsp ntf error status %d\n", __func__, ret); + goto err_disable_intr; + } + + if (rsp[0] == NCI_NTF) { + /* read version info from NCI Reset Notification */ + rom_version = rsp[NCI_HDR_LEN + rsp[NCI_PAYLOAD_LEN_IDX] - 3]; + major_version = rsp[NCI_HDR_LEN + rsp[NCI_PAYLOAD_LEN_IDX] - 2]; + /* determine chip type based on version info */ + if (rom_version == SN1XX_ROM_VER && major_version == SN1xx_MAJOR_VER) + chip_type = CHIP_SN1XX; + else if (rom_version == SN220_ROM_VER && major_version == SN220_MAJOR_VER) + chip_type = CHIP_SN220; + pr_debug(" %s:NCI Core Reset ntf 0x%02x%02x%02x%02x\n", + __func__, rsp[0], rsp[1], rsp[2], rsp[3]); + + nfc_dev->nqx_info.info.chip_type = rsp[NCI_HDR_LEN + rsp[NCI_PAYLOAD_LEN_IDX] - + NFC_CHIP_TYPE_OFF]; + nfc_dev->nqx_info.info.rom_version = rom_version; + nfc_dev->nqx_info.info.fw_major = major_version; + nfc_dev->nqx_info.info.fw_minor = rsp[NCI_HDR_LEN + rsp[NCI_PAYLOAD_LEN_IDX] - + NFC_FW_MINOR_OFF]; + } +err_disable_intr: + nfc_dev->nfc_disable_intr(nfc_dev); +err: + return chip_type; +} + +/** + * validate_download_gpio() - validate download gpio. + * @nfc_dev: nfc_dev device data structure. + * @chip_type: chip type of the platform. + * + * Validates dwnld gpio should configured for supported and + * should not be configured for unsupported platform. + * + * @Return: true if gpio validation successful ortherwise + * false if validation fails. + */ +static bool validate_download_gpio(struct nfc_dev *nfc_dev, enum chip_types chip_type) +{ + bool status = false; + struct platform_gpio *nfc_gpio; + + if (nfc_dev == NULL) { + pr_err("%s nfc devices structure is null\n"); + return status; + } + nfc_gpio = &nfc_dev->configs.gpio; + if (chip_type == CHIP_SN1XX) { + /* gpio should be configured for SN1xx */ + status = gpio_is_valid(nfc_gpio->dwl_req); + } else if (chip_type == CHIP_SN220) { + /* gpio should not be configured for SN220 */ + set_valid_gpio(nfc_gpio->dwl_req, 0); + gpio_free(nfc_gpio->dwl_req); + nfc_gpio->dwl_req = -EINVAL; + status = true; + } + return status; +} + +/* Check for availability of NFC controller hardware */ +int nfcc_hw_check(struct nfc_dev *nfc_dev) +{ + int ret = 0; + enum nfc_state_flags nfc_state = NFC_STATE_UNKNOWN; + enum chip_types chip_type = CHIP_UNKNOWN; + struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; + + /*get fw version in nci mode*/ + gpio_set_ven(nfc_dev, 1); + gpio_set_ven(nfc_dev, 0); + gpio_set_ven(nfc_dev, 1); + chip_type = get_nfcc_chip_type(nfc_dev); + + /*get fw version in fw dwl mode*/ + if (chip_type == CHIP_UNKNOWN) { + nfc_dev->nfc_enable_intr(nfc_dev); + /*Chip is unknown, initially assume with fw dwl pin enabled*/ + set_valid_gpio(nfc_gpio->dwl_req, 1); + gpio_set_ven(nfc_dev, 0); + gpio_set_ven(nfc_dev, 1); + chip_type = get_nfcc_chip_type_dl(nfc_dev); + /*get the state of nfcc normal/teared in fw dwl mode*/ + } else { + nfc_state = NFC_STATE_NCI; + } + + /*validate gpio config required as per the chip*/ + if (!validate_download_gpio(nfc_dev, chip_type)) { + pr_info("%s gpio validation fail\n", __func__); + ret = -ENXIO; + goto err; + } + + /*check whether the NFCC is in FW DN or Teared state*/ + if (nfc_state != NFC_STATE_NCI) + nfc_state = get_nfcc_session_state_dl(nfc_dev); + + /*nfcc state specific operations */ + switch (nfc_state) { + case NFC_STATE_FW_TEARED: + pr_warn("%s: - NFCC FW Teared State\n", __func__); + case NFC_STATE_FW_DWL: + case NFC_STATE_NCI: + break; + case NFC_STATE_UNKNOWN: + default: + ret = -ENXIO; + pr_err("%s: - NFCC HW not available\n", __func__); + goto err; + } + nfc_dev->nfc_state = nfc_state; +err: + nfc_dev->nfc_disable_intr(nfc_dev); + set_valid_gpio(nfc_gpio->dwl_req, 0); + gpio_set_ven(nfc_dev, 0); + gpio_set_ven(nfc_dev, 1); + nfc_dev->nfc_ven_enabled = true; + return ret; +} diff --git a/nfc/common_nxp.h b/nfc/common_nxp.h new file mode 100644 index 0000000000..ad3e5aabfa --- /dev/null +++ b/nfc/common_nxp.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2019-2021 NXP + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + ******************************************************************************/ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + ******************************************************************************/ + +#ifndef _COMMON_QCOM_H_ +#define _COMMON_QCOM_H_ + +#define NCI_RESET_CMD_LEN (4) +#define NCI_RESET_RSP_LEN (4) +#define NCI_CORE_RESET_CMD_OID (0x0) +#define NCI_CORE_RESET_CMD_PAYLOAD_LEN (0x1) +#define NCI_CORE_RESET_KEEP_CONFIG (0x0) +#define NCI_RESET_NTF_LEN (13) + +/*command response timeout*/ +#define NCI_CMD_RSP_TIMEOUT_MS (2000) //2s + +#define SN1XX_ROM_VER 0x01 +#define SN1xx_MAJOR_VER 0x10 +#define SN220_ROM_VER 0x01 +#define SN220_MAJOR_VER 0x01 +#define FW_ROM_CODE_VER_OFFSET 4 +#define FW_MAJOR_VER_OFFSET 7 +#define GET_VERSION_RSP_CHIP_TYPE_OFFSET 3 +#define GET_VERSION_RSP_MINOR_VERSION_OFFSET 6 +#define DL_GET_VERSION_CMD_LEN (8) +#define DL_GET_VERSION_RSP_LEN_1 (12) /* SN110 */ +#define DL_GET_VERSION_RSP_LEN_2 (20) /* SN220 */ +#define DL_GET_VERSION_CMD_PAYLOAD_LEN (4) +#define DL_GET_VERSION_CMD_ID (0xF1) +#define DL_GET_VERSION_CMD_CRC_1 (0x6E) +#define DL_GET_VERSION_CMD_CRC_2 (0xEF) + +#define DL_RESET_CMD_LEN (8) +#define DL_GET_SESSION_STATE_CMD_LEN (8) +#define DL_GET_SESSION_STATE_RSP_LEN (8) +#define DL_GET_SESSION_STATE_CMD_PAYLOAD_LEN (4) +#define DL_GET_SESSION_CMD_ID (0xF2) +#define DL_GET_SESSION_CMD_CRC_1 (0xF5) +#define DL_GET_SESSION_CMD_CRC_2 (0x33) +#define GET_SESSION_STS_OFF (3) +#define NFCC_SESSION_STS_CLOSED (0x0) + +/* Below offsets should be subtracted from NCI header length + payload length */ + +#define NFC_CHIP_TYPE_OFF (4) +#define NFC_FW_MINOR_OFF (1) + + +enum chip_types { + CHIP_SN1XX = 0x01, + CHIP_SN220 = 0x02, + CHIP_UNKNOWN = 0xFF, +}; + +#endif //_COMMON_QCOM_H_ diff --git a/nfc/common_qcom.c b/nfc/common_qcom.c new file mode 100644 index 0000000000..ef05d01394 --- /dev/null +++ b/nfc/common_qcom.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. + * + ***************************************************************************/ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + ***************************************************************************/ + +#include "common.h" + +/* + * Inside nfc_ioctl_nfcc_info + * + * @brief nfc_ioctl_nfcc_info + * + * Check the NFC Chipset and firmware version details + */ +unsigned int nfc_ioctl_nfcc_info(struct file *filp, unsigned long arg) +{ + unsigned int r = 0; + struct nfc_dev *nfc_dev = filp->private_data; + + r = nfc_dev->nqx_info.i; + pr_debug("nfc : %s r = 0x%x\n", __func__, r); + + return r; +} + +/* + * Inside is_nfc_data_available_for_read + * + * @nfc_dev: nfc device data structure + * + * Checks if the data is available for reading + * on waiting queue. + * + * @Return: status value + * + */ +int is_nfc_data_available_for_read(struct nfc_dev *nfc_dev) +{ + int ret; + + nfc_dev->nfc_enable_intr(nfc_dev); + + ret = wait_event_interruptible_timeout(nfc_dev->read_wq, + !nfc_dev->i2c_dev.irq_enabled, + msecs_to_jiffies(MAX_IRQ_WAIT_TIME)); + return ret; +} + +/** + * nfc_ldo_vote() + * @nfc_dev: NFC device containing regulator handle + * + * LDO voting based on voltage and current entries in DT + * + * Return: 0 on success and -ve on failure + */ +int nfc_ldo_vote(struct nfc_dev *nfc_dev) +{ + int ret; + + ret = regulator_set_voltage(nfc_dev->reg, + nfc_dev->configs.ldo.vdd_levels[0], + nfc_dev->configs.ldo.vdd_levels[1]); + if (ret < 0) { + pr_err("%s: set voltage failed\n", __func__); + return ret; + } + + /* pass expected current from NFC in uA */ + ret = regulator_set_load(nfc_dev->reg, nfc_dev->configs.ldo.max_current); + if (ret < 0) { + pr_err("%s: set load failed\n", __func__); + return ret; + } + + ret = regulator_enable(nfc_dev->reg); + if (ret < 0) + pr_err("%s: regulator_enable failed\n", __func__); + else + nfc_dev->is_vreg_enabled = true; + return ret; +} + +/** + * nfc_ldo_config() + * @dev: device instance to read DT entry + * @nfc_dev: NFC device containing regulator handle + * + * Configure LDO if entry is present in DT file otherwise + * return with success as it's optional + * + * Return: 0 on success and -ve on failure + */ +int nfc_ldo_config(struct device *dev, struct nfc_dev *nfc_dev) +{ + int ret; + + if (of_get_property(dev->of_node, NFC_LDO_SUPPLY_NAME, NULL)) { + // Get the regulator handle + nfc_dev->reg = regulator_get(dev, NFC_LDO_SUPPLY_DT_NAME); + if (IS_ERR(nfc_dev->reg)) { + ret = PTR_ERR(nfc_dev->reg); + nfc_dev->reg = NULL; + pr_err("%s: regulator_get failed, ret = %d\n", + __func__, ret); + return ret; + } + } else { + nfc_dev->reg = NULL; + pr_err("%s: regulator entry not present\n", __func__); + // return success as it's optional to configure LDO + return 0; + } + + // LDO config supported by platform DT + ret = nfc_ldo_vote(nfc_dev); + if (ret < 0) { + pr_err("%s: LDO voting failed, ret = %d\n", __func__, ret); + regulator_put(nfc_dev->reg); + } + return ret; +} + +/** + * nfc_ldo_unvote() + * @nfc_dev: NFC device containing regulator handle + * + * set voltage and load to zero and disable regulator + * + * Return: 0 on success and -ve on failure + */ +int nfc_ldo_unvote(struct nfc_dev *nfc_dev) +{ + int ret; + + if (!nfc_dev->is_vreg_enabled) { + pr_err("%s: regulator already disabled\n", __func__); + return -EINVAL; + } + + ret = regulator_disable(nfc_dev->reg); + if (ret < 0) { + pr_err("%s: regulator_disable failed\n", __func__); + return ret; + } + nfc_dev->is_vreg_enabled = false; + + ret = regulator_set_voltage(nfc_dev->reg, 0, NFC_VDDIO_MAX); + if (ret < 0) { + pr_err("%s: set voltage failed\n", __func__); + return ret; + } + + ret = regulator_set_load(nfc_dev->reg, 0); + if (ret < 0) + pr_err("%s: set load failed\n", __func__); + return ret; +} diff --git a/qti/ese_cold_reset.c b/nfc/ese_cold_reset.c similarity index 83% rename from qti/ese_cold_reset.c rename to nfc/ese_cold_reset.c index 7d596ca27e..ad0aa2c6a3 100644 --- a/qti/ese_cold_reset.c +++ b/nfc/ese_cold_reset.c @@ -1,12 +1,61 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. - */ + * + ***************************************************************************/ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + ***************************************************************************/ #include #include #include -#include "nfc_common.h" +#include "common.h" + +/* + * Power management of the eSE + * eSE and NFCC both are powered using VEN gpio, + * VEN HIGH - eSE and NFCC both are powered on + * VEN LOW - eSE and NFCC both are power down + */ +int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg) +{ + int ret = 0; + + if (arg == ESE_POWER_ON) { + /* + * Let's store the NFC VEN pin state + * will check stored value in case of eSE power off request, + * to find out if NFC MW also sent request to set VEN HIGH + * VEN state will remain HIGH if NFC is enabled otherwise + * it will be set as LOW + */ + nfc_dev->nfc_ven_enabled = gpio_get_value(nfc_dev->configs.gpio.ven); + if (!nfc_dev->nfc_ven_enabled) { + pr_debug("eSE HAL service setting ven HIGH\n"); + gpio_set_ven(nfc_dev, 1); + } else { + pr_debug("ven already HIGH\n"); + } + nfc_dev->is_ese_session_active = true; + } else if (arg == ESE_POWER_OFF) { + if (!nfc_dev->nfc_ven_enabled) { + pr_debug("NFC not enabled, disabling ven\n"); + gpio_set_ven(nfc_dev, 0); + } else { + pr_debug("keep ven high as NFC is enabled\n"); + } + nfc_dev->is_ese_session_active = false; + } else if (arg == ESE_POWER_STATE) { + /* get VEN gpio state for eSE, as eSE also enabled through same GPIO */ + ret = gpio_get_value(nfc_dev->configs.gpio.ven); + } else { + pr_err("%s bad arg %lu\n", __func__, arg); + ret = -ENOIOCTLCMD; + } + return ret; +} /** * send_ese_cmd() - Send eSE command to NFC controller. @@ -106,7 +155,7 @@ int read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header) ret = nfc_dev->nfc_read(nfc_dev, &rsp_buf[NCI_PAYLOAD_IDX], rsp_buf[NCI_PAYLOAD_LEN_IDX], - NCI_CMD_RSP_TIMEOUT); + NCI_CMD_RSP_TIMEOUT_MS); if (ret <= 0) { dev_err(nfc_dev->nfc_device, diff --git a/qti/ese_cold_reset.h b/nfc/ese_cold_reset.h similarity index 100% rename from qti/ese_cold_reset.h rename to nfc/ese_cold_reset.h diff --git a/nfc/i2c_drv.c b/nfc/i2c_drv.c index 2792484263..d0e2d5a5f2 100644 --- a/nfc/i2c_drv.c +++ b/nfc/i2c_drv.c @@ -33,7 +33,11 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ + ****************************************************************************/ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + ****************************************************************************/ #include #include @@ -43,7 +47,7 @@ #ifdef CONFIG_COMPAT #include #endif -#include "common_ese.h" +#include "common.h" /** * i2c_disable_irq() @@ -108,6 +112,8 @@ int i2c_read(struct nfc_dev *nfc_dev, char *buf, size_t count, int timeout) int ret; struct i2c_dev *i2c_dev = &nfc_dev->i2c_dev; struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; + uint16_t i = 0; + uint16_t disp_len = GET_IPCLOG_MAX_PKT_LEN(count); pr_debug("%s: reading %zu bytes.\n", __func__, count); @@ -174,34 +180,34 @@ int i2c_read(struct nfc_dev *nfc_dev, char *buf, size_t count, int timeout) memset(buf, 0x00, count); /* Read data */ ret = i2c_master_recv(nfc_dev->i2c_dev.client, buf, count); + NFCLOG_IPC(nfc_dev, false, "%s of %d bytes, ret %d", __func__, count, + ret); if (ret <= 0) { pr_err("%s: returned %d\n", __func__, ret); goto err; } + + for (i = 0; i < disp_len; i++) + NFCLOG_IPC(nfc_dev, false, " %02x", buf[i]); + /* check if it's response of cold reset command * NFC HAL process shouldn't receive this data as - * command was sent by driver + * command was sent by esepowermanager */ - if (nfc_dev->cold_reset.rsp_pending) { - if (IS_PROP_CMD_RSP(buf)) { - /* Read data */ - ret = i2c_master_recv(nfc_dev->i2c_dev.client, - &buf[NCI_PAYLOAD_IDX], - buf[NCI_PAYLOAD_LEN_IDX]); - if (ret <= 0) { - pr_err("%s: error reading cold rst/prot rsp\n", - __func__); - goto err; - } - wakeup_on_prop_rsp(nfc_dev, buf); - /* - * NFC process doesn't know about cold reset command - * being sent as it was initiated by eSE process - * we shouldn't return any data to NFC process - */ - return 0; - } + if (nfc_dev->cold_reset.rsp_pending && nfc_dev->cold_reset.cmd_buf + && (buf[0] == PROP_NCI_RSP_GID) + && (buf[1] == nfc_dev->cold_reset.cmd_buf[1])) { + read_cold_reset_rsp(nfc_dev, buf); + nfc_dev->cold_reset.rsp_pending = false; + wake_up_interruptible(&nfc_dev->cold_reset.read_wq); + /* + * NFC process doesn't know about cold reset command + * being sent as it was initiated by eSE process + * we shouldn't return any data to NFC process + */ + return 0; } + err: return ret; } @@ -211,12 +217,18 @@ int i2c_write(struct nfc_dev *nfc_dev, const char *buf, size_t count, { int ret = -EINVAL; int retry_cnt; + uint16_t i = 0; + uint16_t disp_len = GET_IPCLOG_MAX_PKT_LEN(count); struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; if (count > MAX_DL_BUFFER_SIZE) count = MAX_DL_BUFFER_SIZE; pr_debug("%s: writing %zu bytes.\n", __func__, count); + NFCLOG_IPC(nfc_dev, false, "%s sending %d B", __func__, count); + + for (i = 0; i < disp_len; i++) + NFCLOG_IPC(nfc_dev, false, " %02x", buf[i]); /* * Wait for any pending read for max 15ms before write * This is to avoid any packet corruption during read, when @@ -238,6 +250,7 @@ int i2c_write(struct nfc_dev *nfc_dev, const char *buf, size_t count, for (retry_cnt = 1; retry_cnt <= max_retry_cnt; retry_cnt++) { ret = i2c_master_send(nfc_dev->i2c_dev.client, buf, count); + NFCLOG_IPC(nfc_dev, false, "%s ret %d", __func__, ret); if (ret <= 0) { pr_warn("%s: write failed ret(%d), maybe in standby\n", __func__, ret); @@ -391,7 +404,6 @@ int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id) mutex_init(&nfc_dev->write_mutex); mutex_init(&nfc_dev->dev_ref_mutex); spin_lock_init(&i2c_dev->irq_enabled_lock); - common_ese_init(nfc_dev); ret = nfc_misc_register(nfc_dev, &nfc_i2c_dev_fops, DEV_COUNT, NFC_CHAR_DEV_NAME, CLASS_NAME); if (ret) { @@ -408,15 +420,35 @@ int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id) goto err_nfc_misc_unregister; } i2c_disable_irq(nfc_dev); + + ret = nfc_ldo_config(&client->dev, nfc_dev); + if (ret) { + pr_err("LDO config failed\n"); + goto err_ldo_config_failed; + } + ret = nfcc_hw_check(nfc_dev); + if (ret || nfc_dev->nfc_state == NFC_STATE_UNKNOWN) { + pr_err("nfc hw check failed ret %d\n", ret); + goto err_nfcc_hw_check; + } gpio_set_ven(nfc_dev, 1); gpio_set_ven(nfc_dev, 0); gpio_set_ven(nfc_dev, 1); device_init_wakeup(&client->dev, true); i2c_set_clientdata(client, nfc_dev); i2c_dev->irq_wake_up = false; + nfc_dev->is_ese_session_active = false; pr_info("%s: probing nfc i2c successfully\n", __func__); return 0; + +err_nfcc_hw_check: + if (nfc_dev->reg) { + nfc_ldo_unvote(nfc_dev); + regulator_put(nfc_dev->reg); + } +err_ldo_config_failed: + free_irq(client->irq, nfc_dev); err_nfc_misc_unregister: nfc_misc_unregister(nfc_dev, DEV_COUNT); err_mutex_destroy: @@ -452,9 +484,19 @@ int nfc_i2c_dev_remove(struct i2c_client *client) pr_err("%s: device already in use\n", __func__); return -EBUSY; } + + gpio_set_value(nfc_dev->configs.gpio.ven, 0); + // HW dependent delay before LDO goes into LPM mode + usleep_range(10000, 10100); + if (nfc_dev->reg) { + nfc_ldo_unvote(nfc_dev); + regulator_put(nfc_dev->reg); + } + device_init_wakeup(&client->dev, false); free_irq(client->irq, nfc_dev); nfc_misc_unregister(nfc_dev, DEV_COUNT); + mutex_destroy(&nfc_dev->dev_ref_mutex); mutex_destroy(&nfc_dev->read_mutex); mutex_destroy(&nfc_dev->write_mutex); gpio_free_all(nfc_dev); @@ -475,6 +517,9 @@ int nfc_i2c_dev_suspend(struct device *device) } i2c_dev = &nfc_dev->i2c_dev; + NFCLOG_IPC(nfc_dev, false, "%s: irq_enabled = %d", __func__, + i2c_dev->irq_enabled); + if (device_may_wakeup(&client->dev) && i2c_dev->irq_enabled) { if (!enable_irq_wake(client->irq)) i2c_dev->irq_wake_up = true; @@ -494,6 +539,9 @@ int nfc_i2c_dev_resume(struct device *device) } i2c_dev = &nfc_dev->i2c_dev; + NFCLOG_IPC(nfc_dev, false, "%s: irq_wake_up = %d", __func__, + i2c_dev->irq_wake_up); + if (device_may_wakeup(&client->dev) && i2c_dev->irq_wake_up) { if (!disable_irq_wake(client->irq)) i2c_dev->irq_wake_up = false; diff --git a/nfc/i2c_drv.h b/nfc/i2c_drv.h index 1508fd4163..3abb56bd0f 100644 --- a/nfc/i2c_drv.h +++ b/nfc/i2c_drv.h @@ -17,14 +17,19 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ******************************************************************************/ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * + ******************************************************************************/ #ifndef _I2C_DRV_H_ #define _I2C_DRV_H_ #include -/* kept same as dts */ -#define NFC_I2C_DRV_STR "nxp,pn544" -#define NFC_I2C_DEV_ID "pn553" +#define NFC_I2C_DRV_STR "qcom,sn-nci" /*kept same as dts */ +#define NFC_I2C_DEV_ID "sn-i2c" + +struct nfc_dev; /* Interface specific parameters */ struct i2c_dev { @@ -43,4 +48,14 @@ int nfc_i2c_dev_remove(struct i2c_client *client); int nfc_i2c_dev_suspend(struct device *device); int nfc_i2c_dev_resume(struct device *device); -#endif /* _I2C_DRV_H_ */ +#if IS_ENABLED(CONFIG_NXP_NFC_I2C) + +int i2c_enable_irq(struct nfc_dev *dev); +int i2c_disable_irq(struct nfc_dev *dev); +int i2c_write(struct nfc_dev *dev, const char *buf, size_t count, + int max_retry_cnt); +int i2c_read(struct nfc_dev *dev, char *buf, size_t count, int timeout); + +#endif + +#endif //_I2C_DRV_H_ diff --git a/nfc_kernel_dlkm_vendor_board.mk b/nfc_kernel_dlkm_vendor_board.mk index 933ebdca5d..eb7a015643 100644 --- a/nfc_kernel_dlkm_vendor_board.mk +++ b/nfc_kernel_dlkm_vendor_board.mk @@ -1,4 +1,4 @@ # Build NFC kernel driver ifeq ($(call is-board-platform-in-list, kalama),true) -BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/nfc_i2c.ko +BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/nxp-nci.ko endif diff --git a/nfc_kernel_dlkm_vendor_product.mk b/nfc_kernel_dlkm_vendor_product.mk index d8150bf3da..fc1442a8e1 100644 --- a/nfc_kernel_dlkm_vendor_product.mk +++ b/nfc_kernel_dlkm_vendor_product.mk @@ -1 +1 @@ -PRODUCT_PACKAGES += nfc_i2c.ko +PRODUCT_PACKAGES += nxp-nci.ko diff --git a/qti/nfc_common.c b/qti/nfc_common.c deleted file mode 100644 index 6db09e212f..0000000000 --- a/qti/nfc_common.c +++ /dev/null @@ -1,951 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2019-2021 NXP - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ******************************************************************************/ - -#include -#include -#include -#include "nfc_common.h" - -int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs, - uint8_t interface) -{ - int ret; - struct device_node *np = dev->of_node; - struct platform_gpio *nfc_gpio = &nfc_configs->gpio; - struct platform_ldo *ldo = &nfc_configs->ldo; - - if (!np) { - pr_err("nfc of_node NULL\n"); - return -EINVAL; - } - - nfc_gpio->irq = -EINVAL; - nfc_gpio->dwl_req = -EINVAL; - nfc_gpio->ven = -EINVAL; - nfc_gpio->clkreq = -EINVAL; - - /* required for i2c based chips only */ - if (interface == PLATFORM_IF_I2C) { - nfc_gpio->irq = of_get_named_gpio(np, DTS_IRQ_GPIO_STR, 0); - if ((!gpio_is_valid(nfc_gpio->irq))) { - pr_err("nfc irq gpio invalid %d\n", nfc_gpio->irq); - return -EINVAL; - } - pr_info("%s: irq %d\n", __func__, nfc_gpio->irq); - } - nfc_gpio->ven = of_get_named_gpio(np, DTS_VEN_GPIO_STR, 0); - if ((!gpio_is_valid(nfc_gpio->ven))) { - pr_err("nfc ven gpio invalid %d\n", nfc_gpio->ven); - return -EINVAL; - } - - nfc_gpio->dwl_req = of_get_named_gpio(np, DTS_FWDN_GPIO_STR, 0); - - /* not returning failure for dwl gpio as it is optional for sn220 */ - if ((!gpio_is_valid(nfc_gpio->dwl_req))) - pr_warn("nfc dwl_req gpio invalid %d\n", nfc_gpio->dwl_req); - - nfc_gpio->clkreq = of_get_named_gpio(np, DTS_CLKREQ_GPIO_STR, 0); - if (!gpio_is_valid(nfc_gpio->clkreq)) { - dev_err(dev, "clkreq gpio invalid %d\n", nfc_gpio->dwl_req); - return -EINVAL; - } - - pr_info("%s: ven %d, dwl req %d, clkreq %d\n", __func__, - nfc_gpio->ven, nfc_gpio->dwl_req, nfc_gpio->clkreq); - - // optional property - ret = of_property_read_u32_array(np, NFC_LDO_VOL_DT_NAME, - (u32 *) ldo->vdd_levels, - ARRAY_SIZE(ldo->vdd_levels)); - if (ret) { - dev_err(dev, "error reading NFC VDDIO min and max value\n"); - // set default as per datasheet - ldo->vdd_levels[0] = NFC_VDDIO_MIN; - ldo->vdd_levels[1] = NFC_VDDIO_MAX; - } - - // optional property - ret = of_property_read_u32(np, NFC_LDO_CUR_DT_NAME, &ldo->max_current); - if (ret) { - dev_err(dev, "error reading NFC current value\n"); - // set default as per datasheet - ldo->max_current = NFC_CURRENT_MAX; - } - - return 0; -} - -/** - * nfc_ldo_vote() - * @nfc_dev: NFC device containing regulator handle - * - * LDO voting based on voltage and current entries in DT - * - * Return: 0 on success and -ve on failure - */ -int nfc_ldo_vote(struct nfc_dev *nfc_dev) -{ - int ret; - - ret = regulator_set_voltage(nfc_dev->reg, - nfc_dev->configs.ldo.vdd_levels[0], - nfc_dev->configs.ldo.vdd_levels[1]); - if (ret < 0) { - pr_err("%s: set voltage failed\n", __func__); - return ret; - } - - /* pass expected current from NFC in uA */ - ret = regulator_set_load(nfc_dev->reg, nfc_dev->configs.ldo.max_current); - if (ret < 0) { - pr_err("%s: set load failed\n", __func__); - return ret; - } - - ret = regulator_enable(nfc_dev->reg); - if (ret < 0) - pr_err("%s: regulator_enable failed\n", __func__); - else - nfc_dev->is_vreg_enabled = true; - return ret; -} - -/** - * nfc_ldo_config() - * @dev: device instance to read DT entry - * @nfc_dev: NFC device containing regulator handle - * - * Configure LDO if entry is present in DT file otherwise - * return with success as it's optional - * - * Return: 0 on success and -ve on failure - */ -int nfc_ldo_config(struct device *dev, struct nfc_dev *nfc_dev) -{ - int ret; - - if (of_get_property(dev->of_node, NFC_LDO_SUPPLY_NAME, NULL)) { - // Get the regulator handle - nfc_dev->reg = regulator_get(dev, NFC_LDO_SUPPLY_DT_NAME); - if (IS_ERR(nfc_dev->reg)) { - ret = PTR_ERR(nfc_dev->reg); - nfc_dev->reg = NULL; - pr_err("%s: regulator_get failed, ret = %d\n", - __func__, ret); - return ret; - } - } else { - nfc_dev->reg = NULL; - pr_err("%s: regulator entry not present\n", __func__); - // return success as it's optional to configure LDO - return 0; - } - - // LDO config supported by platform DT - ret = nfc_ldo_vote(nfc_dev); - if (ret < 0) { - pr_err("%s: LDO voting failed, ret = %d\n", __func__, ret); - regulator_put(nfc_dev->reg); - } - return ret; -} - -/** - * nfc_ldo_unvote() - * @nfc_dev: NFC device containing regulator handle - * - * set voltage and load to zero and disable regulator - * - * Return: 0 on success and -ve on failure - */ -int nfc_ldo_unvote(struct nfc_dev *nfc_dev) -{ - int ret; - - if (!nfc_dev->is_vreg_enabled) { - pr_err("%s: regulator already disabled\n", __func__); - return -EINVAL; - } - - ret = regulator_disable(nfc_dev->reg); - if (ret < 0) { - pr_err("%s: regulator_disable failed\n", __func__); - return ret; - } - nfc_dev->is_vreg_enabled = false; - - ret = regulator_set_voltage(nfc_dev->reg, 0, NFC_VDDIO_MAX); - if (ret < 0) { - pr_err("%s: set voltage failed\n", __func__); - return ret; - } - - ret = regulator_set_load(nfc_dev->reg, 0); - if (ret < 0) - pr_err("%s: set load failed\n", __func__); - return ret; -} - -void set_valid_gpio(int gpio, int value) -{ - if (gpio_is_valid(gpio)) { - pr_debug("%s gpio %d value %d\n", __func__, gpio, value); - gpio_set_value(gpio, value); - /* hardware dependent delay */ - usleep_range(NFC_GPIO_SET_WAIT_TIME_USEC, - NFC_GPIO_SET_WAIT_TIME_USEC + 100); - } -} - -int get_valid_gpio(int gpio) -{ - int value = -EINVAL; - - if (gpio_is_valid(gpio)) { - value = gpio_get_value(gpio); - pr_debug("%s gpio %d value %d\n", __func__, gpio, value); - } - return value; -} - -void gpio_set_ven(struct nfc_dev *nfc_dev, int value) -{ - struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; - - if (gpio_get_value(nfc_gpio->ven) != value) { - pr_debug("%s: value %d\n", __func__, value); - - gpio_set_value(nfc_gpio->ven, value); - /* hardware dependent delay */ - usleep_range(NFC_GPIO_SET_WAIT_TIME_USEC, - NFC_GPIO_SET_WAIT_TIME_USEC + 100); - } -} - -int configure_gpio(unsigned int gpio, int flag) -{ - int ret; - - pr_debug("%s: nfc gpio [%d] flag [%01x]\n", __func__, gpio, flag); - - if (gpio_is_valid(gpio)) { - ret = gpio_request(gpio, "nfc_gpio"); - if (ret) { - pr_err("%s: unable to request nfc gpio [%d]\n", - __func__, gpio); - return ret; - } - /* set direction and value for output pin */ - if (flag & GPIO_OUTPUT) { - ret = gpio_direction_output(gpio, (GPIO_HIGH & flag)); - pr_debug("nfc o/p gpio %d level %d\n", gpio, gpio_get_value(gpio)); - } else { - ret = gpio_direction_input(gpio); - pr_debug("nfc i/p gpio %d\n", gpio); - } - - if (ret) { - pr_err - ("%s: unable to set direction for nfc gpio [%d]\n", - __func__, gpio); - gpio_free(gpio); - return ret; - } - // Consider value as control for input IRQ pin - if (flag & GPIO_IRQ) { - ret = gpio_to_irq(gpio); - if (ret < 0) { - pr_err("%s: unable to set irq for nfc gpio [%d]\n", - __func__, gpio); - gpio_free(gpio); - return ret; - } - pr_debug - ("%s: gpio_to_irq successful [%d]\n", - __func__, gpio); - return ret; - } - } else { - pr_err("%s: invalid gpio\n", __func__); - ret = -EINVAL; - } - return ret; -} - -void nfc_misc_unregister(struct nfc_dev *nfc_dev, int count) -{ - pr_debug("%s: entry\n", __func__); - - kfree(nfc_dev->kbuf); - device_destroy(nfc_dev->nfc_class, nfc_dev->devno); - cdev_del(&nfc_dev->c_dev); - class_destroy(nfc_dev->nfc_class); - unregister_chrdev_region(nfc_dev->devno, count); - if (nfc_dev->ipcl) - ipc_log_context_destroy(nfc_dev->ipcl); -} - -int nfc_misc_register(struct nfc_dev *nfc_dev, - const struct file_operations *nfc_fops, int count, - char *devname, char *classname) -{ - int ret = 0; - - ret = alloc_chrdev_region(&nfc_dev->devno, 0, count, devname); - if (ret < 0) { - pr_err("%s: failed to alloc chrdev region ret %d\n", - __func__, ret); - return ret; - } - nfc_dev->nfc_class = class_create(THIS_MODULE, classname); - if (IS_ERR(nfc_dev->nfc_class)) { - ret = PTR_ERR(nfc_dev->nfc_class); - pr_err("%s: failed to register device class ret %d\n", - __func__, ret); - unregister_chrdev_region(nfc_dev->devno, count); - return ret; - } - cdev_init(&nfc_dev->c_dev, nfc_fops); - ret = cdev_add(&nfc_dev->c_dev, nfc_dev->devno, count); - if (ret < 0) { - pr_err("%s: failed to add cdev ret %d\n", __func__, ret); - class_destroy(nfc_dev->nfc_class); - unregister_chrdev_region(nfc_dev->devno, count); - return ret; - } - nfc_dev->nfc_device = device_create(nfc_dev->nfc_class, NULL, - nfc_dev->devno, nfc_dev, devname); - if (IS_ERR(nfc_dev->nfc_device)) { - ret = PTR_ERR(nfc_dev->nfc_device); - pr_err("%s: failed to create the device ret %d\n", - __func__, ret); - cdev_del(&nfc_dev->c_dev); - class_destroy(nfc_dev->nfc_class); - unregister_chrdev_region(nfc_dev->devno, count); - return ret; - } - - nfc_dev->ipcl = ipc_log_context_create(NUM_OF_IPC_LOG_PAGES, - dev_name(nfc_dev->nfc_device), 0); - - nfc_dev->kbuflen = MAX_BUFFER_SIZE; - nfc_dev->kbuf = kzalloc(MAX_BUFFER_SIZE, GFP_KERNEL | GFP_DMA); - if (!nfc_dev->kbuf) { - nfc_misc_unregister(nfc_dev, count); - return -ENOMEM; - } - - nfc_dev->cold_reset.rsp_pending = false; - nfc_dev->cold_reset.is_nfc_enabled = false; - nfc_dev->cold_reset.is_crp_en = false; - nfc_dev->cold_reset.last_src_ese_prot = ESE_COLD_RESET_ORIGIN_NONE; - - init_waitqueue_head(&nfc_dev->cold_reset.read_wq); - - return 0; -} - -/* - * Power management of the eSE - * eSE and NFCC both are powered using VEN gpio, - * VEN HIGH - eSE and NFCC both are powered on - * VEN LOW - eSE and NFCC both are power down - */ -int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg) -{ - int ret = 0; - - if (arg == ESE_POWER_ON) { - /* - * Let's store the NFC VEN pin state - * will check stored value in case of eSE power off request, - * to find out if NFC MW also sent request to set VEN HIGH - * VEN state will remain HIGH if NFC is enabled otherwise - * it will be set as LOW - */ - nfc_dev->nfc_ven_enabled = gpio_get_value(nfc_dev->configs.gpio.ven); - if (!nfc_dev->nfc_ven_enabled) { - pr_debug("eSE HAL service setting ven HIGH\n"); - gpio_set_ven(nfc_dev, 1); - } else { - pr_debug("ven already HIGH\n"); - } - nfc_dev->is_ese_session_active = true; - } else if (arg == ESE_POWER_OFF) { - if (!nfc_dev->nfc_ven_enabled) { - pr_debug("NFC not enabled, disabling ven\n"); - gpio_set_ven(nfc_dev, 0); - } else { - pr_debug("keep ven high as NFC is enabled\n"); - } - nfc_dev->is_ese_session_active = false; - } else if (arg == ESE_POWER_STATE) { - /* get VEN gpio state for eSE, as eSE also enabled through same GPIO */ - ret = gpio_get_value(nfc_dev->configs.gpio.ven); - } else { - pr_err("%s bad arg %lu\n", __func__, arg); - ret = -ENOIOCTLCMD; - } - return ret; -} - -/* - * nfc_ioctl_power_states() - power control - * @nfc_dev: nfc device data structure - * @arg: mode that we want to move to - * - * Device power control. Depending on the arg value, device moves to - * different states, refer nfcc_ioctl_request in nfc_common.h for args - * - * Return: -ENOIOCTLCMD if arg is not supported, 0 in any other case - */ -static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg) -{ - int ret = 0; - struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; - - if (arg == NFC_POWER_OFF) { - /* - * We are attempting a hardware reset so let us disable - * interrupts to avoid spurious notifications to upper - * layers. - */ - nfc_dev->nfc_disable_intr(nfc_dev); - set_valid_gpio(nfc_gpio->dwl_req, 0); - gpio_set_ven(nfc_dev, 0); - nfc_dev->nfc_ven_enabled = false; - - } else if (arg == NFC_POWER_ON) { - nfc_dev->nfc_enable_intr(nfc_dev); - set_valid_gpio(nfc_gpio->dwl_req, 0); - - gpio_set_ven(nfc_dev, 1); - nfc_dev->nfc_ven_enabled = true; - - } else if (arg == NFC_FW_DWL_VEN_TOGGLE) { - /* - * We are switching to download Mode, toggle the enable pin - * in order to set the NFCC in the new mode - */ - nfc_dev->nfc_disable_intr(nfc_dev); - set_valid_gpio(nfc_gpio->dwl_req, 1); - nfc_dev->nfc_state = NFC_STATE_FW_DWL; - gpio_set_ven(nfc_dev, 0); - gpio_set_ven(nfc_dev, 1); - nfc_dev->nfc_enable_intr(nfc_dev); - } else if (arg == NFC_FW_DWL_HIGH) { - /* - * Setting firmware download gpio to HIGH - * before FW download start - */ - pr_debug("set fw gpio high\n"); - set_valid_gpio(nfc_gpio->dwl_req, 1); - nfc_dev->nfc_state = NFC_STATE_FW_DWL; - - } else if (arg == NFC_VEN_FORCED_HARD_RESET) { - nfc_dev->nfc_disable_intr(nfc_dev); - gpio_set_ven(nfc_dev, 0); - gpio_set_ven(nfc_dev, 1); - nfc_dev->nfc_enable_intr(nfc_dev); - pr_info("%s VEN forced reset done\n", __func__); - - } else if (arg == NFC_FW_DWL_LOW) { - /* - * Setting firmware download gpio to LOW - * FW download finished - */ - pr_debug("set fw gpio LOW\n"); - set_valid_gpio(nfc_gpio->dwl_req, 0); - nfc_dev->nfc_state = NFC_STATE_NCI; - - } else if (arg == NFC_ENABLE) { - /* - * Setting flag true when NFC is enabled - */ - nfc_dev->cold_reset.is_nfc_enabled = true; - } else if (arg == NFC_DISABLE) { - /* - * Setting flag true when NFC is disabled - */ - nfc_dev->cold_reset.is_nfc_enabled = false; - } else { - pr_err("%s bad arg %lu\n", __func__, arg); - ret = -ENOIOCTLCMD; - } - return ret; -} - -/* - * Inside nfc_ioctl_nfcc_info - * - * @brief nfc_ioctl_nfcc_info - * - * Check the NFC Chipset and firmware version details - */ -unsigned int nfc_ioctl_nfcc_info(struct file *filp, unsigned long arg) -{ - unsigned int r = 0; - struct nfc_dev *nfc_dev = filp->private_data; - - r = nfc_dev->nqx_info.i; - pr_debug("nfc : %s r = 0x%x\n", __func__, r); - - return r; -} - -/** @brief IOCTL function to be used to set or get data from upper layer. - * - * @param pfile fil node for opened device. - * @cmd IOCTL type from upper layer. - * @arg IOCTL arg from upper layer. - * - * @return 0 on success, error code for failures. - */ -long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) -{ - int ret = 0; - struct nfc_dev *nfc_dev = pfile->private_data; - - if (!nfc_dev) - return -ENODEV; - - pr_debug("%s cmd = %x arg = %zx\n", __func__, cmd, arg); - - switch (cmd) { - case NFC_SET_PWR: - ret = nfc_ioctl_power_states(nfc_dev, arg); - break; - case ESE_SET_PWR: - ret = nfc_ese_pwr(nfc_dev, arg); - break; - case ESE_GET_PWR: - ret = nfc_ese_pwr(nfc_dev, ESE_POWER_STATE); - break; - case NFCC_GET_INFO: - ret = nfc_ioctl_nfcc_info(pfile, arg); - break; - case NFC_GET_PLATFORM_TYPE: - ret = nfc_dev->interface; - break; - case ESE_COLD_RESET: - pr_debug("nfc ese cold reset ioctl\n"); - ret = ese_cold_reset_ioctl(nfc_dev, arg); - break; - case NFC_GET_IRQ_STATE: - ret = gpio_get_value(nfc_dev->configs.gpio.irq); - break; - default: - pr_err("%s Unsupported ioctl cmd 0x%x, arg %lu\n", - __func__, cmd, arg); - ret = -ENOIOCTLCMD; - } - return ret; -} - -int nfc_dev_open(struct inode *inode, struct file *filp) -{ - struct nfc_dev *nfc_dev = container_of(inode->i_cdev, - struct nfc_dev, c_dev); - - if (!nfc_dev) - return -ENODEV; - - pr_debug("%s: %d, %d\n", __func__, imajor(inode), iminor(inode)); - - mutex_lock(&nfc_dev->dev_ref_mutex); - - filp->private_data = nfc_dev; - - if (nfc_dev->dev_ref_count == 0) { - set_valid_gpio(nfc_dev->configs.gpio.dwl_req, 0); - nfc_dev->nfc_enable_intr(nfc_dev); - } - nfc_dev->dev_ref_count = nfc_dev->dev_ref_count + 1; - - mutex_unlock(&nfc_dev->dev_ref_mutex); - - return 0; -} - -int nfc_dev_close(struct inode *inode, struct file *filp) -{ - struct nfc_dev *nfc_dev = container_of(inode->i_cdev, - struct nfc_dev, c_dev); - - if (!nfc_dev) - return -ENODEV; - - pr_debug("%s: %d, %d\n", __func__, imajor(inode), iminor(inode)); - - mutex_lock(&nfc_dev->dev_ref_mutex); - - if (nfc_dev->dev_ref_count == 1) { - nfc_dev->nfc_disable_intr(nfc_dev); - set_valid_gpio(nfc_dev->configs.gpio.dwl_req, 0); - } - - if (nfc_dev->dev_ref_count > 0) - nfc_dev->dev_ref_count = nfc_dev->dev_ref_count - 1; - - filp->private_data = NULL; - - mutex_unlock(&nfc_dev->dev_ref_mutex); - - return 0; -} - -int is_nfc_data_available_for_read(struct nfc_dev *nfc_dev) -{ - int ret; - - nfc_dev->nfc_enable_intr(nfc_dev); - - ret = wait_event_interruptible_timeout(nfc_dev->read_wq, - !nfc_dev->i2c_dev.irq_enabled, - msecs_to_jiffies(MAX_IRQ_WAIT_TIME)); - return ret; -} - -/** - * get_nfcc_chip_type_dl() - get chip type in fw download command; - * @nfc_dev: nfc device data structure - * - * Perform get version command and determine chip - * type from response. - * - * @Return: enum chip_types value - * - */ -static enum chip_types get_nfcc_chip_type_dl(struct nfc_dev *nfc_dev) -{ - int ret = 0; - uint8_t *cmd = nfc_dev->write_kbuf; - uint8_t *rsp = nfc_dev->read_kbuf; - enum chip_types chip_type = CHIP_UNKNOWN; - - *cmd++ = DL_CMD; - *cmd++ = DL_GET_VERSION_CMD_PAYLOAD_LEN; - *cmd++ = DL_GET_VERSION_CMD_ID; - *cmd++ = DL_PAYLOAD_BYTE_ZERO; - *cmd++ = DL_PAYLOAD_BYTE_ZERO; - *cmd++ = DL_PAYLOAD_BYTE_ZERO; - *cmd++ = DL_GET_VERSION_CMD_CRC_1; - *cmd++ = DL_GET_VERSION_CMD_CRC_2; - - pr_debug("%s:Sending GET_VERSION cmd of size = %d\n", __func__, DL_GET_VERSION_CMD_LEN); - ret = nfc_dev->nfc_write(nfc_dev, nfc_dev->write_kbuf, DL_GET_VERSION_CMD_LEN, - MAX_RETRY_COUNT); - if (ret <= 0) { - pr_err("%s: - nfc get version cmd error ret %d\n", __func__, ret); - goto err; - } - memset(rsp, 0x00, DL_GET_VERSION_RSP_LEN_2); - pr_debug("%s:Reading response of GET_VERSION cmd\n", __func__); - ret = nfc_dev->nfc_read(nfc_dev, rsp, DL_GET_VERSION_RSP_LEN_2, NCI_CMD_RSP_TIMEOUT); - if (ret <= 0) { - pr_err("%s: - nfc get version rsp error ret %d\n", __func__, ret); - goto err; - } - if (rsp[0] == FW_MSG_CMD_RSP && ret >= DL_GET_VERSION_RSP_LEN_2) { - - nfc_dev->fw_major_version = rsp[FW_MAJOR_VER_OFFSET]; - - if (rsp[FW_ROM_CODE_VER_OFFSET] == SN1XX_ROM_VER && - rsp[FW_MAJOR_VER_OFFSET] == SN1xx_MAJOR_VER) - chip_type = CHIP_SN1XX; - else if (rsp[FW_ROM_CODE_VER_OFFSET] == SN220_ROM_VER && - rsp[FW_MAJOR_VER_OFFSET] == SN220_MAJOR_VER) - chip_type = CHIP_SN220; - - pr_debug("%s:NFC Chip Type 0x%02x Rom Version 0x%02x FW Minor 0x%02x Major 0x%02x\n", - __func__, rsp[GET_VERSION_RSP_CHIP_TYPE_OFFSET], - rsp[FW_ROM_CODE_VER_OFFSET], - rsp[GET_VERSION_RSP_MINOR_VERSION_OFFSET], - rsp[FW_MAJOR_VER_OFFSET]); - - nfc_dev->nqx_info.info.chip_type = rsp[GET_VERSION_RSP_CHIP_TYPE_OFFSET]; - nfc_dev->nqx_info.info.rom_version = rsp[FW_ROM_CODE_VER_OFFSET]; - nfc_dev->nqx_info.info.fw_minor = rsp[GET_VERSION_RSP_MINOR_VERSION_OFFSET]; - nfc_dev->nqx_info.info.fw_major = rsp[FW_MAJOR_VER_OFFSET]; - } -err: - return chip_type; -} - -/** - * get_nfcc_session_state_dl() - gets the session state - * @nfc_dev: nfc device data structure - * - * Performs get session command and determine - * the nfcc state based on session status. - * - * @Return nfcc state based on session status. - * NFC_STATE_FW_TEARED if sessionis not closed - * NFC_STATE_FW_DWL if session closed - * NFC_STATE_UNKNOWN in error cases. - */ -enum nfc_state_flags get_nfcc_session_state_dl(struct nfc_dev *nfc_dev) -{ - int ret = 0; - uint8_t *cmd = nfc_dev->write_kbuf; - uint8_t *rsp = nfc_dev->read_kbuf; - enum nfc_state_flags nfc_state = NFC_STATE_UNKNOWN; - - *cmd++ = DL_CMD; - *cmd++ = DL_GET_SESSION_STATE_CMD_PAYLOAD_LEN; - *cmd++ = DL_GET_SESSION_CMD_ID; - *cmd++ = DL_PAYLOAD_BYTE_ZERO; - *cmd++ = DL_PAYLOAD_BYTE_ZERO; - *cmd++ = DL_PAYLOAD_BYTE_ZERO; - *cmd++ = DL_GET_SESSION_CMD_CRC_1; - *cmd++ = DL_GET_SESSION_CMD_CRC_2; - - pr_debug("%s:Sending GET_SESSION_STATE cmd of size = %d\n", __func__, - DL_GET_SESSION_STATE_CMD_LEN); - ret = nfc_dev->nfc_write(nfc_dev, nfc_dev->write_kbuf, DL_GET_SESSION_STATE_CMD_LEN, - MAX_RETRY_COUNT); - if (ret <= 0) { - pr_err("%s: - nfc get session cmd error ret %d\n", __func__, ret); - goto err; - } - memset(rsp, 0x00, DL_GET_SESSION_STATE_RSP_LEN); - pr_debug("%s:Reading response of GET_SESSION_STATE cmd\n", __func__); - ret = nfc_dev->nfc_read(nfc_dev, rsp, DL_GET_SESSION_STATE_RSP_LEN, NCI_CMD_RSP_TIMEOUT); - if (ret <= 0) { - pr_err("%s: - nfc get session rsp error ret %d\n", __func__, ret); - goto err; - } - if (rsp[0] != FW_MSG_CMD_RSP) { - pr_err("%s: - nfc invalid get session state rsp\n", __func__); - goto err; - } - pr_debug("Response bytes are %02x%02x%02x%02x%02x%02x%02x%02x\n", - rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5], rsp[6], rsp[7]); - /*verify fw in non-teared state */ - if (rsp[GET_SESSION_STS_OFF] != NFCC_SESSION_STS_CLOSED) { - pr_err("%s NFCC booted in FW teared state\n", __func__); - nfc_state = NFC_STATE_FW_TEARED; - } else { - pr_info("%s NFCC booted in FW DN mode\n", __func__); - nfc_state = NFC_STATE_FW_DWL; - } -err: - return nfc_state; -} - -/** - * get_nfcc_chip_type() - get nfcc chip type in nci mode. - * @nfc_dev: nfc device data structure. - * - * Function to perform nci core reset and extract - * chip type from the response. - * - * @Return: enum chip_types value - * - */ -static enum chip_types get_nfcc_chip_type(struct nfc_dev *nfc_dev) -{ - int ret = 0; - uint8_t major_version = 0; - uint8_t rom_version = 0; - uint8_t *cmd = nfc_dev->write_kbuf; - uint8_t *rsp = nfc_dev->read_kbuf; - enum chip_types chip_type = CHIP_UNKNOWN; - - *cmd++ = NCI_MSG_CMD; - *cmd++ = NCI_CORE_RESET_CMD_OID; - *cmd++ = NCI_CORE_RESET_CMD_PAYLOAD_LEN; - *cmd++ = NCI_CORE_RESET_KEEP_CONFIG; - - pr_debug("%s:Sending NCI Core Reset cmd of size = %d\n", __func__, NCI_RESET_CMD_LEN); - ret = nfc_dev->nfc_write(nfc_dev, nfc_dev->write_kbuf, NCI_RESET_CMD_LEN, NO_RETRY); - if (ret <= 0) { - pr_err("%s: - nfc nci core reset cmd error ret %d\n", __func__, ret); - goto err; - } - - /* to flush out debug NTF this delay is required */ - usleep_range(NCI_RESET_RESP_READ_DELAY, NCI_RESET_RESP_READ_DELAY + 100); - nfc_dev->nfc_enable_intr(nfc_dev); - - memset(rsp, 0x00, NCI_RESET_RSP_LEN); - pr_debug("%s:Reading NCI Core Reset rsp\n", __func__); - ret = nfc_dev->nfc_read(nfc_dev, rsp, NCI_RESET_RSP_LEN, NCI_CMD_RSP_TIMEOUT); - if (ret <= 0) { - pr_err("%s: - nfc nci core reset rsp error ret %d\n", __func__, ret); - goto err_disable_intr; - } - - pr_debug(" %s: nci core reset response 0x%02x%02x%02x%02x\n", - __func__, rsp[0], rsp[1], rsp[2], rsp[3]); - if (rsp[0] != NCI_MSG_RSP) { - /* reset response failed response*/ - pr_err("%s invalid nci core reset response\n", __func__); - goto err_disable_intr; - } - - memset(rsp, 0x00, NCI_RESET_NTF_LEN); - /* read nci rest response ntf */ - ret = nfc_dev->nfc_read(nfc_dev, rsp, NCI_RESET_NTF_LEN, NCI_CMD_RSP_TIMEOUT); - if (ret <= 0) { - pr_err("%s - nfc nci rest rsp ntf error status %d\n", __func__, ret); - goto err_disable_intr; - } - - if (rsp[0] == NCI_MSG_NTF) { - /* read version info from NCI Reset Notification */ - rom_version = rsp[NCI_HDR_LEN + rsp[NCI_PAYLOAD_LEN_IDX] - 3]; - major_version = rsp[NCI_HDR_LEN + rsp[NCI_PAYLOAD_LEN_IDX] - 2]; - /* determine chip type based on version info */ - if (rom_version == SN1XX_ROM_VER && major_version == SN1xx_MAJOR_VER) - chip_type = CHIP_SN1XX; - else if (rom_version == SN220_ROM_VER && major_version == SN220_MAJOR_VER) - chip_type = CHIP_SN220; - pr_debug(" %s:NCI Core Reset ntf 0x%02x%02x%02x%02x\n", - __func__, rsp[0], rsp[1], rsp[2], rsp[3]); - - nfc_dev->nqx_info.info.chip_type = rsp[NCI_HDR_LEN + rsp[NCI_PAYLOAD_LEN_IDX] - - NFC_CHIP_TYPE_OFF]; - nfc_dev->nqx_info.info.rom_version = rom_version; - nfc_dev->nqx_info.info.fw_major = major_version; - nfc_dev->nqx_info.info.fw_minor = rsp[NCI_HDR_LEN + rsp[NCI_PAYLOAD_LEN_IDX] - - NFC_FW_MINOR_OFF]; - } -err_disable_intr: - nfc_dev->nfc_disable_intr(nfc_dev); -err: - return chip_type; -} - -/** - * validate_download_gpio() - validate download gpio. - * @nfc_dev: nfc_dev device data structure. - * @chip_type: chip type of the platform. - * - * Validates dwnld gpio should configured for supported and - * should not be configured for unsupported platform. - * - * @Return: true if gpio validation successful ortherwise - * false if validation fails. - */ -static bool validate_download_gpio(struct nfc_dev *nfc_dev, enum chip_types chip_type) -{ - bool status = false; - struct platform_gpio *nfc_gpio; - - if (nfc_dev == NULL) { - pr_err("%s nfc devices structure is null\n"); - return status; - } - nfc_gpio = &nfc_dev->configs.gpio; - if (chip_type == CHIP_SN1XX) { - /* gpio should be configured for SN1xx */ - status = gpio_is_valid(nfc_gpio->dwl_req); - } else if (chip_type == CHIP_SN220) { - /* gpio should not be configured for SN220 */ - set_valid_gpio(nfc_gpio->dwl_req, 0); - gpio_free(nfc_gpio->dwl_req); - nfc_gpio->dwl_req = -EINVAL; - status = true; - } - return status; -} - -/* Check for availability of NFC controller hardware */ -int nfcc_hw_check(struct nfc_dev *nfc_dev) -{ - int ret = 0; - enum nfc_state_flags nfc_state = NFC_STATE_UNKNOWN; - enum chip_types chip_type = CHIP_UNKNOWN; - struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; - - /*get fw version in nci mode*/ - gpio_set_ven(nfc_dev, 1); - gpio_set_ven(nfc_dev, 0); - gpio_set_ven(nfc_dev, 1); - chip_type = get_nfcc_chip_type(nfc_dev); - - /*get fw version in fw dwl mode*/ - if (chip_type == CHIP_UNKNOWN) { - nfc_dev->nfc_enable_intr(nfc_dev); - /*Chip is unknown, initially assume with fw dwl pin enabled*/ - set_valid_gpio(nfc_gpio->dwl_req, 1); - gpio_set_ven(nfc_dev, 0); - gpio_set_ven(nfc_dev, 1); - chip_type = get_nfcc_chip_type_dl(nfc_dev); - /*get the state of nfcc normal/teared in fw dwl mode*/ - } else { - nfc_state = NFC_STATE_NCI; - } - - /*validate gpio config required as per the chip*/ - if (!validate_download_gpio(nfc_dev, chip_type)) { - pr_info("%s gpio validation fail\n", __func__); - ret = -ENXIO; - goto err; - } - - /*check whether the NFCC is in FW DN or Teared state*/ - if (nfc_state != NFC_STATE_NCI) - nfc_state = get_nfcc_session_state_dl(nfc_dev); - - /*nfcc state specific operations */ - switch (nfc_state) { - case NFC_STATE_FW_TEARED: - pr_warn("%s: - NFCC FW Teared State\n", __func__); - case NFC_STATE_FW_DWL: - case NFC_STATE_NCI: - break; - case NFC_STATE_UNKNOWN: - default: - ret = -ENXIO; - pr_err("%s: - NFCC HW not available\n", __func__); - goto err; - } - nfc_dev->nfc_state = nfc_state; -err: - nfc_dev->nfc_disable_intr(nfc_dev); - set_valid_gpio(nfc_gpio->dwl_req, 0); - gpio_set_ven(nfc_dev, 0); - gpio_set_ven(nfc_dev, 1); - nfc_dev->nfc_ven_enabled = true; - return ret; -} - -int validate_nfc_state_nci(struct nfc_dev *nfc_dev) -{ - struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; - - if (!gpio_get_value(nfc_gpio->ven)) { - pr_err("VEN LOW - NFCC powered off\n"); - return -ENODEV; - } - if (get_valid_gpio(nfc_gpio->dwl_req) == 1) { - pr_err("FW download in-progress\n"); - return -EBUSY; - } - if (nfc_dev->nfc_state != NFC_STATE_NCI) { - pr_err("FW download state\n"); - return -EBUSY; - } - return 0; -} diff --git a/qti/nfc_common.h b/qti/nfc_common.h deleted file mode 100644 index eac4663b58..0000000000 --- a/qti/nfc_common.h +++ /dev/null @@ -1,346 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2019-2021 NXP - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ******************************************************************************/ - -#ifndef _NFC_COMMON_H_ -#define _NFC_COMMON_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "nfc_i2c_drv.h" -#include "ese_cold_reset.h" - -// Max device count for this driver -#define DEV_COUNT 1 - -// NFC device class -#define CLASS_NAME "qti-nfc" - -// NFC character device name, this will be in /dev/ -#define NFC_CHAR_DEV_NAME "nq-nci" - -// NCI packet details -#define NCI_MSG_CMD 0x20 -#define NCI_MSG_RSP 0x40 -#define NCI_MSG_NTF 0x60 -#define DL_CMD 0x00 -#define DL_PAYLOAD_BYTE_ZERO 0x00 -#define NCI_HDR_LEN 3 -#define NCI_PAYLOAD_IDX 3 -#define NCI_PAYLOAD_LEN_IDX 2 - -/*Time to wait for first NCI rest response*/ -#define NCI_RESET_RESP_READ_DELAY (10000) // 10ms -#define NCI_RESET_RESP_TIMEOUT (500) // 500ms - -// FW DNLD packet details -#define FW_MSG_CMD_RSP 0x00 -#define FW_HDR_LEN 2 -#define FW_PAYLOAD_LEN_IDX 1 -#define FW_CRC_LEN 2 - -#define NCI_RSP_PKT_TYPE (0x40) -#define FW_MIN_PAYLOAD_LEN 4 -#define MIN_NFC_DL_FRAME_SIZE 3 - -#define NCI_RESET_CMD_LEN (4) -#define NCI_RESET_RSP_LEN (4) -#define NCI_CORE_RESET_CMD_OID (0x0) -#define NCI_CORE_RESET_CMD_PAYLOAD_LEN (0x1) -#define NCI_CORE_RESET_KEEP_CONFIG (0x0) -#define NCI_RESET_NTF_LEN (13) -#define SN1XX_ROM_VER 0x01 -#define SN1xx_MAJOR_VER 0x10 -#define SN220_ROM_VER 0x01 -#define SN220_MAJOR_VER 0x01 -#define FW_ROM_CODE_VER_OFFSET 4 -#define FW_MAJOR_VER_OFFSET 7 -#define GET_VERSION_RSP_CHIP_TYPE_OFFSET 3 -#define GET_VERSION_RSP_MINOR_VERSION_OFFSET 6 -#define DL_GET_VERSION_CMD_LEN (8) -#define DL_GET_VERSION_RSP_LEN_1 (12) /* SN110 */ -#define DL_GET_VERSION_RSP_LEN_2 (20) /* SN220 */ -#define DL_GET_VERSION_CMD_PAYLOAD_LEN (4) -#define DL_GET_VERSION_CMD_ID (0xF1) -#define DL_GET_VERSION_CMD_CRC_1 (0x6E) -#define DL_GET_VERSION_CMD_CRC_2 (0xEF) - -#define DL_RESET_CMD_LEN (8) -#define DL_GET_SESSION_STATE_CMD_LEN (8) -#define DL_GET_SESSION_STATE_RSP_LEN (8) -#define DL_GET_SESSION_STATE_CMD_PAYLOAD_LEN (4) -#define DL_GET_SESSION_CMD_ID (0xF2) -#define DL_GET_SESSION_CMD_CRC_1 (0xF5) -#define DL_GET_SESSION_CMD_CRC_2 (0x33) -#define GET_SESSION_STS_OFF (3) -#define NFCC_SESSION_STS_CLOSED (0x0) - -/* Below offsets should be subtracted from NCI header length + payload length */ - -#define NFC_CHIP_TYPE_OFF (4) -#define NFC_FW_MINOR_OFF (1) - -#define GET_VERSION_CMD_LEN 8 -#define GET_SESSION_STATE_CMD_LEN 8 -#define MAX_NCI_PAYLOAD_LEN (255) -#define MAX_BUFFER_SIZE (NCI_HDR_LEN + MAX_NCI_PAYLOAD_LEN) -/* - * From MW 11.04 buffer size increased to support - * frame size of 554 in FW download mode - * Frame len(2) + Frame Header(6) + DATA(512) + HASH(32) + CRC(2) + RFU(4) - */ -#define MAX_DL_PAYLOAD_LEN (550) -#define MAX_DL_BUFFER_SIZE (FW_HDR_LEN + FW_CRC_LEN + MAX_DL_PAYLOAD_LEN) -// Maximum retry count for standby writes -#define MAX_RETRY_COUNT (3) - -// Retry count for normal write -#define NO_RETRY (1) -#define MAX_IRQ_WAIT_TIME (90) -#define WAKEUP_SRC_TIMEOUT (2000) - -/*command response timeout*/ -#define NCI_CMD_RSP_TIMEOUT (2000) //2s -/*Time to wait for NFCC to be ready again after any change in the GPIO*/ -#define NFC_GPIO_SET_WAIT_TIME_USEC (10000) -/*Time to wait after soft reset via any NCI/DL cmd*/ -#define NFC_SOFT_RESET_WAIT_TIME_USEC (5000) -/*Time to wait before retrying i2c writes*/ -#define WRITE_RETRY_WAIT_TIME_USEC (1000) -/*Time to wait before retrying read for some specific usecases*/ -#define READ_RETRY_WAIT_TIME_USEC (3500) -#define NFC_MAGIC 0xE9 - -// Ioctls -// The type should be aligned with MW HAL definitions - -#define NFC_SET_PWR _IOW(NFC_MAGIC, 0x01, unsigned int) -#define ESE_SET_PWR _IOW(NFC_MAGIC, 0x02, unsigned int) -#define ESE_GET_PWR _IOR(NFC_MAGIC, 0x03, unsigned int) -#define NFC_GET_PLATFORM_TYPE _IO(NFC_MAGIC, 0x04) - -/* NFC HAL can call this ioctl to get the current IRQ state */ -#define NFC_GET_IRQ_STATE _IO(NFC_MAGIC, 0x06) - -#define DTS_IRQ_GPIO_STR "qcom,sn-irq" -#define DTS_VEN_GPIO_STR "qcom,sn-ven" -#define DTS_FWDN_GPIO_STR "qcom,sn-firm" -#define DTS_CLKREQ_GPIO_STR "qcom,sn-clkreq" -#define DTS_CLKSRC_GPIO_STR "qcom,clk-src" -#define NFC_LDO_SUPPLY_DT_NAME "qcom,sn-vdd-1p8" -#define NFC_LDO_SUPPLY_NAME "qcom,sn-vdd-1p8-supply" -#define NFC_LDO_VOL_DT_NAME "qcom,sn-vdd-1p8-voltage" -#define NFC_LDO_CUR_DT_NAME "qcom,sn-vdd-1p8-current" - -//as per SN1x0 datasheet -#define NFC_VDDIO_MIN 1650000 //in uV -#define NFC_VDDIO_MAX 1950000 //in uV -#define NFC_CURRENT_MAX 157000 //in uA - - -#define NUM_OF_IPC_LOG_PAGES (2) -#define PKT_MAX_LEN (4) // no of max bytes to print for cmd/resp - -#define GET_IPCLOG_MAX_PKT_LEN(c) ((c > PKT_MAX_LEN) ? PKT_MAX_LEN : c) - -#define NFCLOG_IPC(nfc_dev, log_to_dmesg, x...) \ -do { \ - ipc_log_string(nfc_dev->ipcl, x); \ - if (log_to_dmesg) { \ - if (nfc_dev->nfc_device) \ - dev_err((nfc_dev->nfc_device), x); \ - else \ - pr_err(x); \ - } \ -} while (0) - -enum ese_ioctl_request { - /* eSE POWER ON */ - ESE_POWER_ON = 0, - /* eSE POWER OFF */ - ESE_POWER_OFF, - /* eSE POWER STATE */ - ESE_POWER_STATE -}; - -enum nfcc_ioctl_request { - /* NFC disable request with VEN LOW */ - NFC_POWER_OFF = 0, - /* NFC enable request with VEN Toggle */ - NFC_POWER_ON, - /* firmware download request with VEN Toggle */ - NFC_FW_DWL_VEN_TOGGLE, - /* ISO reset request */ - NFC_ISO_RESET, - /* request for firmware download gpio HIGH */ - NFC_FW_DWL_HIGH, - /* VEN hard reset request */ - NFC_VEN_FORCED_HARD_RESET, - /* request for firmware download gpio LOW */ - NFC_FW_DWL_LOW, - /* NFC enable without VEN gpio modification */ - NFC_ENABLE, - /* NFC disable without VEN gpio modification */ - NFC_DISABLE, -}; - -/*nfc platform interface type*/ -enum interface_flags { - /*I2C physical IF for NFCC */ - PLATFORM_IF_I2C = 0, -}; - -/*nfc state flags*/ -enum nfc_state_flags { - /*nfc in unknown state */ - NFC_STATE_UNKNOWN = 0, - /*nfc in download mode */ - NFC_STATE_FW_DWL = 0x1, - /*nfc booted in NCI mode */ - NFC_STATE_NCI = 0x2, - /*nfc booted in Fw teared mode */ - NFC_STATE_FW_TEARED = 0x4, -}; -/* - * Power state for IBI handing, mainly needed to defer the IBI handling - * for the IBI received in suspend state to do it later in resume call - */ -enum pm_state_flags { - PM_STATE_NORMAL = 0, - PM_STATE_SUSPEND, - PM_STATE_IBI_BEFORE_RESUME, -}; - -/* Enum for GPIO values*/ -enum gpio_values { - GPIO_INPUT = 0x0, - GPIO_OUTPUT = 0x1, - GPIO_HIGH = 0x2, - GPIO_OUTPUT_HIGH = 0x3, - GPIO_IRQ = 0x4, -}; - -// NFC GPIO variables -struct platform_gpio { - unsigned int irq; - unsigned int ven; - unsigned int clkreq; - unsigned int dwl_req; -}; - -// NFC LDO entries from DT -struct platform_ldo { - int vdd_levels[2]; - int max_current; -}; - -// NFC Struct to get all the required configs from DTS -struct platform_configs { - struct platform_gpio gpio; - struct platform_ldo ldo; -}; - -enum chip_types { - CHIP_SN1XX = 0x01, - CHIP_SN220 = 0x02, - CHIP_UNKNOWN = 0xFF, -}; - -/* Device specific structure */ -struct nfc_dev { - wait_queue_head_t read_wq; - struct mutex read_mutex; - struct mutex write_mutex; - uint8_t *read_kbuf; - uint8_t *write_kbuf; - struct mutex dev_ref_mutex; - unsigned int dev_ref_count; - struct class *nfc_class; - struct device *nfc_device; - struct cdev c_dev; - dev_t devno; - /* Interface flag */ - uint8_t interface; - /* nfc state flags */ - uint8_t nfc_state; - /* NFC VEN pin state */ - bool nfc_ven_enabled; - /* current firmware major version */ - uint8_t fw_major_version; - bool is_vreg_enabled; - bool is_ese_session_active; - struct i2c_dev i2c_dev; - struct platform_configs configs; - struct cold_reset cold_reset; - struct regulator *reg; - - /* read buffer*/ - size_t kbuflen; - u8 *kbuf; - - union nqx_uinfo nqx_info; - - void *ipcl; - - int (*nfc_read)(struct nfc_dev *dev, char *buf, size_t count, int timeout); - int (*nfc_write)(struct nfc_dev *dev, const char *buf, const size_t count, - int max_retry_cnt); - int (*nfc_enable_intr)(struct nfc_dev *dev); - int (*nfc_disable_intr)(struct nfc_dev *dev); -}; - -int nfc_dev_open(struct inode *inode, struct file *filp); -int nfc_dev_close(struct inode *inode, struct file *filp); -long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg); -int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs, - uint8_t interface); -int nfc_misc_register(struct nfc_dev *nfc_dev, - const struct file_operations *nfc_fops, int count, char *devname, - char *classname); -void nfc_misc_unregister(struct nfc_dev *nfc_dev, int count); -int configure_gpio(unsigned int gpio, int flag); -void gpio_set_ven(struct nfc_dev *nfc_dev, int value); -int nfcc_hw_check(struct nfc_dev *nfc_dev); -int nfc_ldo_config(struct device *dev, struct nfc_dev *nfc_dev); -int nfc_ldo_vote(struct nfc_dev *nfc_dev); -int nfc_ldo_unvote(struct nfc_dev *nfc_dev); -int is_nfc_data_available_for_read(struct nfc_dev *nfc_dev); -int validate_nfc_state_nci(struct nfc_dev *nfc_dev); -void set_nfcc_state_from_rsp(struct nfc_dev *dev, const char *buf, - const int count); -void enable_dwnld_mode(struct nfc_dev *nfc_dev, bool value); -#endif //_NFC_COMMON_H_ diff --git a/qti/nfc_i2c_drv.c b/qti/nfc_i2c_drv.c deleted file mode 100644 index 58d318dd21..0000000000 --- a/qti/nfc_i2c_drv.c +++ /dev/null @@ -1,577 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2013-2021 NXP - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ******************************************************************************/ -/* - * Copyright (C) 2010 Trusted Logic S.A. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "nfc_common.h" - -/** - * i2c_disable_irq() - * - * Check if interrupt is disabled or not - * and disable interrupt - * - * Return: int - */ -int i2c_disable_irq(struct nfc_dev *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->i2c_dev.irq_enabled_lock, flags); - if (dev->i2c_dev.irq_enabled) { - disable_irq_nosync(dev->i2c_dev.client->irq); - dev->i2c_dev.irq_enabled = false; - } - spin_unlock_irqrestore(&dev->i2c_dev.irq_enabled_lock, flags); - - return 0; -} - -/** - * i2c_enable_irq() - * - * Check if interrupt is enabled or not - * and enable interrupt - * - * Return: int - */ -int i2c_enable_irq(struct nfc_dev *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->i2c_dev.irq_enabled_lock, flags); - if (!dev->i2c_dev.irq_enabled) { - dev->i2c_dev.irq_enabled = true; - enable_irq(dev->i2c_dev.client->irq); - } - spin_unlock_irqrestore(&dev->i2c_dev.irq_enabled_lock, flags); - - return 0; -} - -static irqreturn_t i2c_irq_handler(int irq, void *dev_id) -{ - struct nfc_dev *nfc_dev = dev_id; - struct i2c_dev *i2c_dev = &nfc_dev->i2c_dev; - - if (device_may_wakeup(&i2c_dev->client->dev)) - pm_wakeup_event(&i2c_dev->client->dev, WAKEUP_SRC_TIMEOUT); - - i2c_disable_irq(nfc_dev); - wake_up(&nfc_dev->read_wq); - - return IRQ_HANDLED; -} - -int i2c_read(struct nfc_dev *nfc_dev, char *buf, size_t count, int timeout) -{ - int ret; - struct i2c_dev *i2c_dev = &nfc_dev->i2c_dev; - struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; - uint16_t i = 0; - uint16_t disp_len = GET_IPCLOG_MAX_PKT_LEN(count); - - pr_debug("%s : reading %zu bytes.\n", __func__, count); - - if (timeout > NCI_CMD_RSP_TIMEOUT) - timeout = NCI_CMD_RSP_TIMEOUT; - - if (count > MAX_BUFFER_SIZE) - count = MAX_BUFFER_SIZE; - - if (!gpio_get_value(nfc_gpio->irq)) { - while (1) { - ret = 0; - if (!i2c_dev->irq_enabled) { - i2c_dev->irq_enabled = true; - enable_irq(i2c_dev->client->irq); - } - if (!gpio_get_value(nfc_gpio->irq)) { - if (timeout) { - ret = wait_event_interruptible_timeout(nfc_dev->read_wq, - !i2c_dev->irq_enabled, msecs_to_jiffies(timeout)); - - if (ret <= 0) { - pr_err("%s timeout/error in read\n", __func__); - goto err; - } - } else { - ret = wait_event_interruptible(nfc_dev->read_wq, - !i2c_dev->irq_enabled); - if (ret) { - pr_err("%s error wakeup of read wq\n", __func__); - ret = -EINTR; - goto err; - } - } - } - i2c_disable_irq(nfc_dev); - - if (gpio_get_value(nfc_gpio->irq)) - break; - if (!gpio_get_value(nfc_gpio->ven)) { - pr_info("%s: releasing read\n", __func__); - ret = -EIO; - goto err; - } - pr_warn("%s: spurious interrupt detected\n", __func__); - } - } - - memset(buf, 0x00, count); - /* Read data */ - ret = i2c_master_recv(nfc_dev->i2c_dev.client, buf, count); - NFCLOG_IPC(nfc_dev, false, "%s of %d bytes, ret %d", __func__, count, - ret); - if (ret <= 0) { - pr_err("%s: returned %d\n", __func__, ret); - goto err; - } - - for (i = 0; i < disp_len; i++) - NFCLOG_IPC(nfc_dev, false, " %02x", buf[i]); - - /* check if it's response of cold reset command - * NFC HAL process shouldn't receive this data as - * command was esepowermanager - */ - if (nfc_dev->cold_reset.rsp_pending && nfc_dev->cold_reset.cmd_buf - && (buf[0] == PROP_NCI_RSP_GID) - && (buf[1] == nfc_dev->cold_reset.cmd_buf[1])) { - read_cold_reset_rsp(nfc_dev, buf); - nfc_dev->cold_reset.rsp_pending = false; - wake_up_interruptible(&nfc_dev->cold_reset.read_wq); - /* - * NFC process doesn't know about cold reset command - * being sent as it was initiated by eSE process - * we shouldn't return any data to NFC process - */ - return 0; - } - -err: - return ret; -} - -int i2c_write(struct nfc_dev *nfc_dev, const char *buf, size_t count, - int max_retry_cnt) -{ - int ret = -EINVAL; - int retry_cnt; - uint16_t i = 0; - uint16_t disp_len = GET_IPCLOG_MAX_PKT_LEN(count); - - if (count > MAX_DL_BUFFER_SIZE) - count = MAX_DL_BUFFER_SIZE; - - pr_debug("%s : writing %zu bytes.\n", __func__, count); - - NFCLOG_IPC(nfc_dev, false, "%s sending %d B", __func__, count); - - for (i = 0; i < disp_len; i++) - NFCLOG_IPC(nfc_dev, false, " %02x", buf[i]); - - for (retry_cnt = 1; retry_cnt <= max_retry_cnt; retry_cnt++) { - - ret = i2c_master_send(nfc_dev->i2c_dev.client, buf, count); - NFCLOG_IPC(nfc_dev, false, "%s ret %d", __func__, ret); - if (ret <= 0) { - pr_warn("%s: write failed ret %d, Maybe in Standby Mode - Retry(%d)\n", - __func__, ret, retry_cnt); - usleep_range(WRITE_RETRY_WAIT_TIME_USEC, - WRITE_RETRY_WAIT_TIME_USEC + 100); - } else if (ret != count) { - pr_err("%s: failed to write %d\n", __func__, ret); - ret = -EIO; - } else if (ret == count) - break; - } - return ret; -} - -ssize_t nfc_i2c_dev_read(struct file *filp, char __user *buf, - size_t count, loff_t *offset) -{ - int ret = 0; - struct nfc_dev *nfc_dev = (struct nfc_dev *)filp->private_data; - - if (filp->f_flags & O_NONBLOCK) { - pr_err(":f_flag has O_NONBLOCK. EAGAIN\n"); - return -EAGAIN; - } - mutex_lock(&nfc_dev->read_mutex); - ret = i2c_read(nfc_dev, nfc_dev->read_kbuf, count, 0); - if (ret > 0) { - if (copy_to_user(buf, nfc_dev->read_kbuf, ret)) { - pr_warn("%s : failed to copy to user space\n", __func__); - ret = -EFAULT; - } - } - mutex_unlock(&nfc_dev->read_mutex); - return ret; -} - -ssize_t nfc_i2c_dev_write(struct file *filp, const char __user *buf, - size_t count, loff_t *offset) -{ - int ret; - struct nfc_dev *nfc_dev = (struct nfc_dev *)filp->private_data; - - if (count > MAX_DL_BUFFER_SIZE) - count = MAX_DL_BUFFER_SIZE; - - if (!nfc_dev) - return -ENODEV; - - mutex_lock(&nfc_dev->write_mutex); - if (copy_from_user(nfc_dev->write_kbuf, buf, count)) { - pr_err("%s : failed to copy from user space\n", __func__); - mutex_unlock(&nfc_dev->write_mutex); - return -EFAULT; - } - ret = i2c_write(nfc_dev, nfc_dev->write_kbuf, count, NO_RETRY); - mutex_unlock(&nfc_dev->write_mutex); - return ret; -} - -static const struct file_operations nfc_i2c_dev_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = nfc_i2c_dev_read, - .write = nfc_i2c_dev_write, - .open = nfc_dev_open, - .release = nfc_dev_close, - .unlocked_ioctl = nfc_dev_ioctl, -}; - -int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - int ret = 0; - struct nfc_dev *nfc_dev = NULL; - struct i2c_dev *i2c_dev = NULL; - struct platform_configs nfc_configs; - struct platform_gpio *nfc_gpio = &nfc_configs.gpio; - - pr_debug("%s: enter\n", __func__); - - //retrieve details of gpios from dt - - ret = nfc_parse_dt(&client->dev, &nfc_configs, PLATFORM_IF_I2C); - if (ret) { - pr_err("%s : failed to parse dt\n", __func__); - goto err; - } - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - pr_err("%s : need I2C_FUNC_I2C\n", __func__); - ret = -ENODEV; - goto err; - } - nfc_dev = kzalloc(sizeof(struct nfc_dev), GFP_KERNEL); - if (nfc_dev == NULL) { - ret = -ENOMEM; - goto err; - } - nfc_dev->read_kbuf = kzalloc(MAX_BUFFER_SIZE, GFP_DMA | GFP_KERNEL); - if (!nfc_dev->read_kbuf) { - ret = -ENOMEM; - goto err_free_nfc_dev; - } - nfc_dev->write_kbuf = kzalloc(MAX_DL_BUFFER_SIZE, GFP_DMA | GFP_KERNEL); - if (!nfc_dev->write_kbuf) { - ret = -ENOMEM; - goto err_free_read_kbuf; - } - nfc_dev->interface = PLATFORM_IF_I2C; - nfc_dev->nfc_state = NFC_STATE_NCI; - nfc_dev->i2c_dev.client = client; - i2c_dev = &nfc_dev->i2c_dev; - nfc_dev->nfc_read = i2c_read; - nfc_dev->nfc_write = i2c_write; - nfc_dev->nfc_enable_intr = i2c_enable_irq; - nfc_dev->nfc_disable_intr = i2c_disable_irq; - nfc_dev->fw_major_version = 0; - ret = configure_gpio(nfc_gpio->ven, GPIO_OUTPUT); - if (ret) { - pr_err("%s: unable to request nfc reset gpio [%d]\n", - __func__, nfc_gpio->ven); - goto err_free_write_kbuf; - } - ret = configure_gpio(nfc_gpio->irq, GPIO_IRQ); - if (ret <= 0) { - pr_err("%s: unable to request nfc irq gpio [%d]\n", - __func__, nfc_gpio->irq); - goto err_free_ven; - } - client->irq = ret; - ret = configure_gpio(nfc_gpio->dwl_req, GPIO_OUTPUT); - if (ret) { - pr_err("%s: unable to request nfc firm downl gpio [%d]\n", - __func__, nfc_gpio->dwl_req); - //not returning failure here as dwl gpio is a optional gpio for sn220 - } - - ret = configure_gpio(nfc_gpio->clkreq, GPIO_INPUT); - if (ret) { - pr_err("%s: unable to request nfc clkreq gpio [%d]\n", - __func__, nfc_gpio->clkreq); - goto err_free_dwl_req; - } - - /*copy the retrieved gpio details from DT */ - memcpy(&nfc_dev->configs, &nfc_configs, sizeof(struct platform_configs)); - - /* init mutex and queues */ - init_waitqueue_head(&nfc_dev->read_wq); - mutex_init(&nfc_dev->read_mutex); - mutex_init(&nfc_dev->write_mutex); - mutex_init(&nfc_dev->dev_ref_mutex); - spin_lock_init(&i2c_dev->irq_enabled_lock); - ret = nfc_misc_register(nfc_dev, &nfc_i2c_dev_fops, DEV_COUNT, - NFC_CHAR_DEV_NAME, CLASS_NAME); - if (ret) { - pr_err("%s: nfc_misc_register failed\n", __func__); - goto err_mutex_destroy; - } - /* interrupt initializations */ - pr_info("%s : requesting IRQ %d\n", __func__, client->irq); - i2c_dev->irq_enabled = true; - ret = request_irq(client->irq, i2c_irq_handler, - IRQF_TRIGGER_HIGH, client->name, nfc_dev); - if (ret) { - pr_err("%s: request_irq failed\n", __func__); - goto err_nfc_misc_unregister; - } - i2c_disable_irq(nfc_dev); - i2c_set_clientdata(client, nfc_dev); - - ret = nfc_ldo_config(&client->dev, nfc_dev); - if (ret) { - pr_err("LDO config failed\n"); - goto err_ldo_config_failed; - } - - ret = nfcc_hw_check(nfc_dev); - if (ret || nfc_dev->nfc_state == NFC_STATE_UNKNOWN) { - pr_err("nfc hw check failed ret %d\n", ret); - goto err_nfcc_hw_check; - } - - device_init_wakeup(&client->dev, true); - i2c_dev->irq_wake_up = false; - nfc_dev->is_ese_session_active = false; - - pr_info("%s success\n", __func__); - return 0; - -err_nfcc_hw_check: - if (nfc_dev->reg) { - nfc_ldo_unvote(nfc_dev); - regulator_put(nfc_dev->reg); - } -err_ldo_config_failed: - free_irq(client->irq, nfc_dev); -err_nfc_misc_unregister: - nfc_misc_unregister(nfc_dev, DEV_COUNT); -err_mutex_destroy: - mutex_destroy(&nfc_dev->dev_ref_mutex); - mutex_destroy(&nfc_dev->read_mutex); - mutex_destroy(&nfc_dev->write_mutex); - gpio_free(nfc_gpio->clkreq); -err_free_dwl_req: - if (gpio_is_valid(nfc_gpio->dwl_req)) - gpio_free(nfc_gpio->dwl_req); - gpio_free(nfc_gpio->irq); -err_free_ven: - gpio_free(nfc_gpio->ven); -err_free_write_kbuf: - kfree(nfc_dev->write_kbuf); -err_free_read_kbuf: - kfree(nfc_dev->read_kbuf); -err_free_nfc_dev: - kfree(nfc_dev); -err: - pr_err("%s: failed\n", __func__); - return ret; -} - -int nfc_i2c_dev_remove(struct i2c_client *client) -{ - int ret = 0; - struct nfc_dev *nfc_dev = NULL; - - pr_info("%s: remove device\n", __func__); - nfc_dev = i2c_get_clientdata(client); - if (!nfc_dev) { - pr_err("%s: device doesn't exist anymore\n", __func__); - ret = -ENODEV; - return ret; - } - - if (nfc_dev->dev_ref_count > 0) { - pr_err("%s: device already in use\n", __func__); - return -EBUSY; - } - - gpio_set_value(nfc_dev->configs.gpio.ven, 0); - // HW dependent delay before LDO goes into LPM mode - usleep_range(10000, 10100); - if (nfc_dev->reg) { - nfc_ldo_unvote(nfc_dev); - regulator_put(nfc_dev->reg); - } - - device_init_wakeup(&client->dev, false); - free_irq(client->irq, nfc_dev); - nfc_misc_unregister(nfc_dev, DEV_COUNT); - mutex_destroy(&nfc_dev->dev_ref_mutex); - mutex_destroy(&nfc_dev->read_mutex); - mutex_destroy(&nfc_dev->write_mutex); - - if (gpio_is_valid(nfc_dev->configs.gpio.clkreq)) - gpio_free(nfc_dev->configs.gpio.clkreq); - - if (gpio_is_valid(nfc_dev->configs.gpio.dwl_req)) - gpio_free(nfc_dev->configs.gpio.dwl_req); - - if (gpio_is_valid(nfc_dev->configs.gpio.irq)) - gpio_free(nfc_dev->configs.gpio.irq); - - if (gpio_is_valid(nfc_dev->configs.gpio.ven)) - gpio_free(nfc_dev->configs.gpio.ven); - - kfree(nfc_dev->read_kbuf); - kfree(nfc_dev->write_kbuf); - kfree(nfc_dev); - return ret; -} - -int nfc_i2c_dev_suspend(struct device *device) -{ - struct i2c_client *client = to_i2c_client(device); - struct nfc_dev *nfc_dev = i2c_get_clientdata(client); - struct i2c_dev *i2c_dev = NULL; - - if (!nfc_dev) { - pr_err("%s: device doesn't exist anymore\n", __func__); - return -ENODEV; - } - - i2c_dev = &nfc_dev->i2c_dev; - - NFCLOG_IPC(nfc_dev, false, "%s: irq_enabled = %d", __func__, - i2c_dev->irq_enabled); - - if (device_may_wakeup(&client->dev) && i2c_dev->irq_enabled) { - if (!enable_irq_wake(client->irq)) - i2c_dev->irq_wake_up = true; - } - return 0; -} - -int nfc_i2c_dev_resume(struct device *device) -{ - struct i2c_client *client = to_i2c_client(device); - struct nfc_dev *nfc_dev = i2c_get_clientdata(client); - struct i2c_dev *i2c_dev = NULL; - - if (!nfc_dev) { - pr_err("%s: device doesn't exist anymore\n", __func__); - return -ENODEV; - } - - i2c_dev = &nfc_dev->i2c_dev; - - NFCLOG_IPC(nfc_dev, false, "%s: irq_wake_up = %d", __func__, - i2c_dev->irq_wake_up); - - if (device_may_wakeup(&client->dev) && i2c_dev->irq_wake_up) { - if (!disable_irq_wake(client->irq)) - i2c_dev->irq_wake_up = false; - } - return 0; -} - -static const struct i2c_device_id nfc_i2c_dev_id[] = { - {NFC_I2C_DEV_ID, 0}, - {} -}; - -static const struct of_device_id nfc_i2c_dev_match_table[] = { - {.compatible = NFC_I2C_DRV_STR,}, - {} -}; - -static const struct dev_pm_ops nfc_i2c_dev_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(nfc_i2c_dev_suspend, nfc_i2c_dev_resume) -}; - -static struct i2c_driver nfc_i2c_dev_driver = { - .id_table = nfc_i2c_dev_id, - .probe = nfc_i2c_dev_probe, - .remove = nfc_i2c_dev_remove, - .driver = { - .name = NFC_I2C_DRV_STR, - .pm = &nfc_i2c_dev_pm_ops, - .of_match_table = nfc_i2c_dev_match_table, - .probe_type = PROBE_PREFER_ASYNCHRONOUS, - }, -}; - -MODULE_DEVICE_TABLE(of, nfc_i2c_dev_match_table); - -static int __init nfc_i2c_dev_init(void) -{ - int ret = 0; - - ret = i2c_add_driver(&nfc_i2c_dev_driver); - if (ret != 0) - pr_err("NFC I2C add driver error ret %d\n", ret); - return ret; -} - -module_init(nfc_i2c_dev_init); - -static void __exit nfc_i2c_dev_exit(void) -{ - pr_debug("Unloading NFC I2C driver\n"); - i2c_del_driver(&nfc_i2c_dev_driver); -} - -module_exit(nfc_i2c_dev_exit); - -MODULE_DESCRIPTION("QTI NFC I2C driver"); -MODULE_LICENSE("GPL v2"); diff --git a/qti/nfc_i2c_drv.h b/qti/nfc_i2c_drv.h deleted file mode 100644 index 5ba871a1e4..0000000000 --- a/qti/nfc_i2c_drv.h +++ /dev/null @@ -1,81 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2019-2021 NXP - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - ******************************************************************************/ - -#ifndef _NFC_I2C_DRV_H_ -#define _NFC_I2C_DRV_H_ -#include - -#define NFC_I2C_DRV_STR "qcom,sn-nci" /*kept same as dts */ -#define NFC_I2C_DEV_ID "sn-i2c" - -struct nfc_dev; - -//Interface specific parameters -struct i2c_dev { - struct i2c_client *client; - /*IRQ parameters */ - bool irq_enabled; - spinlock_t irq_enabled_lock; - /* NFC_IRQ wake-up state */ - bool irq_wake_up; -}; - -long nfc_i2c_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg); -int nfc_i2c_dev_probe(struct i2c_client *client, - const struct i2c_device_id *id); -int nfc_i2c_dev_remove(struct i2c_client *client); -int nfc_i2c_dev_suspend(struct device *device); -int nfc_i2c_dev_resume(struct device *device); - -#if IS_ENABLED(CONFIG_NFC_QTI_I2C) - -int i2c_enable_irq(struct nfc_dev *dev); -int i2c_disable_irq(struct nfc_dev *dev); -int i2c_write(struct nfc_dev *dev, const char *buf, size_t count, - int max_retry_cnt); -int i2c_read(struct nfc_dev *dev, char *buf, size_t count, int timeout); - -#else - -static inline int i2c_enable_irq(struct nfc_dev *dev) -{ - return -ENXIO; -} - -static inline int i2c_disable_irq(struct nfc_dev *dev) -{ - return -ENXIO; -} - -static inline int i2c_write(struct nfc_dev *dev, const char *buf, - size_t count, int max_retry_cnt) -{ - return -ENXIO; -} - -static inline int i2c_read(struct nfc_dev *dev, char *buf, size_t count, int timeout) -{ - return -ENXIO; -} - -#endif - -#endif //_NFC_I2C_DRV_H_