mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
Merge "NFC: Add NFC hardware check and get info ioctl"
This commit is contained in:
commit
1f37c7cca2
7 changed files with 393 additions and 45 deletions
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/of_gpio.h>
|
||||
|
|
@ -8,6 +8,25 @@
|
|||
#include <linux/delay.h>
|
||||
#include "nfc_common.h"
|
||||
|
||||
int nfc_read(struct nfc_dev *nfc_dev, char *buf, size_t count)
|
||||
{
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C)
|
||||
return i2c_read(&nfc_dev->i2c_dev, buf, count);
|
||||
else
|
||||
return i3c_nci_kbuf_retrieve(&nfc_dev->i3c_dev, buf, count);
|
||||
}
|
||||
EXPORT_SYMBOL(nfc_read);
|
||||
|
||||
int nfc_write(struct nfc_dev *nfc_dev, char *buf, size_t count,
|
||||
uint8_t retry_cnt)
|
||||
{
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C)
|
||||
return i2c_write(&nfc_dev->i2c_dev, buf, count, retry_cnt);
|
||||
else
|
||||
return i3c_write(&nfc_dev->i3c_dev, buf, count, retry_cnt);
|
||||
}
|
||||
EXPORT_SYMBOL(nfc_write);
|
||||
|
||||
int nfc_parse_dt(struct device *dev, struct platform_gpio *nfc_gpio,
|
||||
uint8_t interface)
|
||||
{
|
||||
|
|
@ -214,13 +233,8 @@ static int send_cold_reset_cmd(struct nfc_dev *nfc_dev)
|
|||
cold_reset_cmd[1] = COLD_RESET_OID;
|
||||
cold_reset_cmd[2] = COLD_RESET_CMD_PAYLOAD_LEN;
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C)
|
||||
ret = i2c_write(&nfc_dev->i2c_dev, cold_reset_cmd,
|
||||
COLD_RESET_CMD_LEN, MAX_RETRY_COUNT);
|
||||
else
|
||||
ret = i3c_write(&nfc_dev->i3c_dev, cold_reset_cmd,
|
||||
COLD_RESET_CMD_LEN, MAX_RETRY_COUNT);
|
||||
|
||||
ret = nfc_write(nfc_dev, cold_reset_cmd,
|
||||
COLD_RESET_CMD_LEN, MAX_RETRY_COUNT);
|
||||
if (ret <= 0)
|
||||
pr_err("%s: write failed after max retry, ret %d\n",
|
||||
__func__, ret);
|
||||
|
|
@ -248,7 +262,7 @@ void read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header)
|
|||
(nfc_dev->interface == PLATFORM_IF_I2C)) {
|
||||
|
||||
ret = i2c_read(&nfc_dev->i2c_dev, cold_reset_rsp,
|
||||
NCI_HDR_LEN);
|
||||
NCI_HDR_LEN);
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: failure to read cold reset rsp header\n",
|
||||
__func__);
|
||||
|
|
@ -259,6 +273,7 @@ void read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header)
|
|||
/* For I3C driver, header is read by the worker thread */
|
||||
memcpy(cold_reset_rsp, header, NCI_HDR_LEN);
|
||||
}
|
||||
|
||||
if ((cold_reset_rsp[0] != COLD_RESET_RSP_GID)
|
||||
|| (cold_reset_rsp[1] != COLD_RESET_OID)) {
|
||||
pr_err("%s: - invalid response GID or OID for cold_reset\n",
|
||||
|
|
@ -271,6 +286,7 @@ void read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header)
|
|||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C)
|
||||
ret = i2c_read(&nfc_dev->i2c_dev,
|
||||
&cold_reset_rsp[NCI_PAYLOAD_IDX],
|
||||
|
|
@ -438,6 +454,7 @@ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg)
|
|||
*/
|
||||
|
||||
gpio_set_ven(nfc_dev, 1);
|
||||
|
||||
if (gpio_is_valid(nfc_dev->gpio.dwl_req)) {
|
||||
gpio_set_value(nfc_dev->gpio.dwl_req, 1);
|
||||
usleep_range(10000, 10100);
|
||||
|
|
@ -503,6 +520,24 @@ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg)
|
|||
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 = %d\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.
|
||||
|
|
@ -531,6 +566,9 @@ 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;
|
||||
default:
|
||||
pr_err("%s bad cmd %lu\n", __func__, arg);
|
||||
ret = -ENOIOCTLCMD;
|
||||
|
|
@ -600,3 +638,232 @@ int nfc_dev_close(struct inode *inode, struct file *filp)
|
|||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(nfc_dev_close);
|
||||
|
||||
int is_data_available_for_read(struct nfc_dev *nfc_dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
enable_interrupt(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;
|
||||
}
|
||||
|
||||
/* Check for availability of NFC controller hardware */
|
||||
int nfcc_hw_check(struct nfc_dev *nfc_dev)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char reset_ntf_len = 0;
|
||||
char *nci_reset_cmd = NULL;
|
||||
char *nci_reset_rsp = NULL;
|
||||
char *nci_reset_ntf = NULL;
|
||||
char *nci_get_version_cmd = NULL;
|
||||
char *nci_get_version_rsp = NULL;
|
||||
|
||||
nci_reset_cmd = kzalloc(NCI_RESET_CMD_LEN + 1, GFP_DMA | GFP_KERNEL);
|
||||
if (!nci_reset_cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
nci_reset_rsp = kzalloc(NCI_RESET_RSP_LEN + 1, GFP_DMA | GFP_KERNEL);
|
||||
if (!nci_reset_rsp) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
nci_reset_ntf = kzalloc(NCI_RESET_NTF_LEN + 1, GFP_DMA | GFP_KERNEL);
|
||||
if (!nci_reset_ntf) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
nci_get_version_cmd = kzalloc(NCI_GET_VERSION_CMD_LEN + 1,
|
||||
GFP_DMA | GFP_KERNEL);
|
||||
if (!nci_get_version_cmd) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
nci_get_version_rsp = kzalloc(NCI_GET_VERSION_RSP_LEN + 1,
|
||||
GFP_DMA | GFP_KERNEL);
|
||||
if (!nci_get_version_rsp) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I3C)
|
||||
enable_interrupt(nfc_dev);
|
||||
else {
|
||||
/* making sure that the NFCC starts in a clean state. */
|
||||
gpio_set_ven(nfc_dev, 1);/* HPD : Enable*/
|
||||
gpio_set_ven(nfc_dev, 0);/* ULPM: Disable */
|
||||
gpio_set_ven(nfc_dev, 1);/* HPD : Enable*/
|
||||
}
|
||||
|
||||
nci_reset_cmd[0] = 0x20;
|
||||
nci_reset_cmd[1] = 0x00;
|
||||
nci_reset_cmd[2] = 0x01;
|
||||
nci_reset_cmd[3] = 0x00;
|
||||
|
||||
/* send NCI CORE RESET CMD with Keep Config parameters */
|
||||
ret = nfc_write(nfc_dev, nci_reset_cmd, NCI_RESET_CMD_LEN,
|
||||
MAX_RETRY_COUNT);
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: - nfc core reset error\n", __func__);
|
||||
|
||||
if (gpio_is_valid(nfc_dev->gpio.dwl_req)) {
|
||||
gpio_set_value(nfc_dev->gpio.dwl_req, 1);
|
||||
usleep_range(10000, 10100);
|
||||
}
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C) {
|
||||
gpio_set_ven(nfc_dev, 0);
|
||||
gpio_set_ven(nfc_dev, 1);
|
||||
}
|
||||
|
||||
nci_get_version_cmd[0] = 0x00;
|
||||
nci_get_version_cmd[1] = 0x04;
|
||||
nci_get_version_cmd[2] = 0xF1;
|
||||
nci_get_version_cmd[3] = 0x00;
|
||||
nci_get_version_cmd[4] = 0x00;
|
||||
nci_get_version_cmd[5] = 0x00;
|
||||
nci_get_version_cmd[6] = 0x6E;
|
||||
nci_get_version_cmd[7] = 0xEF;
|
||||
|
||||
ret = nfc_write(nfc_dev, nci_get_version_cmd,
|
||||
NCI_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_nfcc_hw_check;
|
||||
}
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C) {
|
||||
ret = is_data_available_for_read(nfc_dev);
|
||||
if (ret <= 0) {
|
||||
disable_interrupt(nfc_dev);
|
||||
pr_err("%s: - error waiting for get version rsp ret %d\n",
|
||||
__func__, ret);
|
||||
goto err_nfcc_hw_check;
|
||||
}
|
||||
}
|
||||
|
||||
ret = nfc_read(nfc_dev, nci_get_version_rsp,
|
||||
NCI_GET_VERSION_RSP_LEN);
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: - nfc get version rsp error ret %d\n",
|
||||
__func__, ret);
|
||||
goto err_nfcc_hw_check;
|
||||
} else {
|
||||
nfc_dev->nqx_info.info.chip_type =
|
||||
nci_get_version_rsp[3];
|
||||
nfc_dev->nqx_info.info.rom_version =
|
||||
nci_get_version_rsp[4];
|
||||
nfc_dev->nqx_info.info.fw_minor =
|
||||
nci_get_version_rsp[6];
|
||||
nfc_dev->nqx_info.info.fw_major =
|
||||
nci_get_version_rsp[7];
|
||||
}
|
||||
|
||||
gpio_set_value(nfc_dev->gpio.dwl_req, 0);
|
||||
|
||||
goto err_nfcc_reset_failed;
|
||||
}
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C) {
|
||||
ret = is_data_available_for_read(nfc_dev);
|
||||
if (ret <= 0) {
|
||||
disable_interrupt(nfc_dev);
|
||||
pr_err("%s: - error waiting for core reset rsp ret %d\n",
|
||||
__func__, ret);
|
||||
|
||||
goto err_nfcc_hw_check;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read Response of RESET command */
|
||||
ret = nfc_read(nfc_dev, nci_reset_rsp, NCI_RESET_RSP_LEN);
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: - nfc rst rsp read err %d\n", __func__,
|
||||
ret);
|
||||
goto err_nfcc_hw_check;
|
||||
}
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C) {
|
||||
ret = is_data_available_for_read(nfc_dev);
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: - error waiting for core reset ntf ret %d\n",
|
||||
__func__, ret);
|
||||
disable_interrupt(nfc_dev);
|
||||
goto err_nfcc_hw_check;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read Notification of RESET command */
|
||||
ret = nfc_read(nfc_dev, nci_reset_ntf, NCI_RESET_NTF_LEN);
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: nfc nfc read error %d\n", __func__, ret);
|
||||
goto err_nfcc_hw_check;
|
||||
}
|
||||
|
||||
reset_ntf_len = NCI_HDR_LEN + nci_reset_ntf[NCI_PAYLOAD_LEN_IDX] - 1;
|
||||
if (reset_ntf_len > NCI_HDR_LEN) {
|
||||
nfc_dev->nqx_info.info.chip_type =
|
||||
nci_reset_ntf[reset_ntf_len - NFC_CHIP_TYPE_OFF];
|
||||
nfc_dev->nqx_info.info.rom_version =
|
||||
nci_reset_ntf[reset_ntf_len - NFC_ROM_VERSION_OFF];
|
||||
nfc_dev->nqx_info.info.fw_major =
|
||||
nci_reset_ntf[reset_ntf_len - NFC_FW_MAJOR_OFF];
|
||||
nfc_dev->nqx_info.info.fw_minor =
|
||||
nci_reset_ntf[reset_ntf_len];
|
||||
}
|
||||
pr_debug("%s: - NFC reset rsp : NfcNciRx %x %x %x\n",
|
||||
__func__, nci_reset_rsp[0],
|
||||
nci_reset_rsp[1], nci_reset_rsp[2]);
|
||||
|
||||
err_nfcc_reset_failed:
|
||||
pr_info("NFC chip_type = %x\n",
|
||||
nfc_dev->nqx_info.info.chip_type);
|
||||
pr_info("NFC fw version = %x.%x.%x\n",
|
||||
nfc_dev->nqx_info.info.rom_version,
|
||||
nfc_dev->nqx_info.info.fw_major,
|
||||
nfc_dev->nqx_info.info.fw_minor);
|
||||
|
||||
switch (nfc_dev->nqx_info.info.chip_type) {
|
||||
case NFCC_SN100_A:
|
||||
case NFCC_SN100_B:
|
||||
pr_debug("%s: ## NFCC == SN100x ##\n", __func__);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: - NFCC HW not Supported\n", __func__);
|
||||
break;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
nfc_dev->nfc_ven_enabled = true;
|
||||
|
||||
goto disable_i3c_intr;
|
||||
|
||||
err_nfcc_hw_check:
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C)
|
||||
gpio_set_ven(nfc_dev, 0);
|
||||
|
||||
gpio_set_value(nfc_dev->gpio.dwl_req, 0);
|
||||
|
||||
ret = -ENXIO;
|
||||
pr_debug("%s: - NFCC HW not available\n", __func__);
|
||||
|
||||
disable_i3c_intr:
|
||||
if (nfc_dev->interface == PLATFORM_IF_I3C)
|
||||
disable_interrupt(nfc_dev);
|
||||
done:
|
||||
kfree(nci_reset_rsp);
|
||||
kfree(nci_reset_ntf);
|
||||
kfree(nci_get_version_cmd);
|
||||
kfree(nci_get_version_rsp);
|
||||
kfree(nci_reset_cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(nfcc_hw_check);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _NFC_COMMON_H_
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/nfcinfo.h>
|
||||
|
||||
#include "nfc_i2c_drv.h"
|
||||
#include "nfc_i3c_drv.h"
|
||||
|
|
@ -38,6 +39,19 @@
|
|||
// HDR length of NCI packet
|
||||
#define NCI_HDR_LEN 3
|
||||
#define NCI_PAYLOAD_IDX 3
|
||||
#define NCI_PAYLOAD_LEN_IDX 2
|
||||
|
||||
#define NCI_RESET_CMD_LEN (4)
|
||||
#define NCI_RESET_RSP_LEN (4)
|
||||
#define NCI_RESET_NTF_LEN (13)
|
||||
#define NCI_GET_VERSION_CMD_LEN (8)
|
||||
#define NCI_GET_VERSION_RSP_LEN (12)
|
||||
|
||||
// Below offsets should be subtracted from core reset ntf len
|
||||
|
||||
#define NFC_CHIP_TYPE_OFF (3)
|
||||
#define NFC_ROM_VERSION_OFF (2)
|
||||
#define NFC_FW_MAJOR_OFF (1)
|
||||
|
||||
#define COLD_RESET_CMD_LEN 3
|
||||
#define COLD_RESET_RSP_LEN 4
|
||||
|
|
@ -134,6 +148,12 @@ enum gpio_values {
|
|||
GPIO_IRQ = 0x4,
|
||||
};
|
||||
|
||||
enum nfcc_chip_variant {
|
||||
NFCC_SN100_A = 0xa3, /**< NFCC SN100_A */
|
||||
NFCC_SN100_B = 0xa4, /**< NFCC SN100_B */
|
||||
NFCC_NOT_SUPPORTED = 0xFF /**< NFCC is not supported */
|
||||
};
|
||||
|
||||
// NFC GPIO variables
|
||||
struct platform_gpio {
|
||||
unsigned int irq;
|
||||
|
|
@ -175,6 +195,8 @@ struct nfc_dev {
|
|||
/* read buffer*/
|
||||
size_t kbuflen;
|
||||
u8 *kbuf;
|
||||
|
||||
union nqx_uinfo nqx_info;
|
||||
};
|
||||
|
||||
int nfc_dev_open(struct inode *inode, struct file *filp);
|
||||
|
|
@ -189,5 +211,6 @@ void nfc_misc_remove(struct nfc_dev *nfc_dev, int count);
|
|||
int configure_gpio(unsigned int gpio, int flag);
|
||||
void read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header);
|
||||
void gpio_set_ven(struct nfc_dev *nfc_dev, int value);
|
||||
int nfcc_hw_check(struct nfc_dev *nfc_dev);
|
||||
|
||||
#endif //_NFC_COMMON_H_
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "nfc_common.h"
|
||||
|
|
@ -133,24 +133,26 @@ ssize_t nfc_i2c_dev_read(struct file *filp, char __user *buf,
|
|||
i2c_dev->irq_enabled = true;
|
||||
enable_irq(i2c_dev->client->irq);
|
||||
}
|
||||
ret = wait_event_interruptible(nfc_dev->read_wq,
|
||||
if (!gpio_get_value(nfc_dev->gpio.irq)) {
|
||||
ret = wait_event_interruptible(nfc_dev->read_wq,
|
||||
!i2c_dev->irq_enabled);
|
||||
if (ret) {
|
||||
pr_err("error wakeup of read wq\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
pr_err("error wakeup of read wq\n");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
i2c_disable_irq(i2c_dev);
|
||||
|
||||
if (!gpio_get_value(nfc_dev->gpio.ven)) {
|
||||
pr_info("%s: releasing read\n", __func__);
|
||||
ret = -EIO;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (gpio_get_value(nfc_dev->gpio.irq))
|
||||
break;
|
||||
|
||||
if (!gpio_get_value(nfc_dev->gpio.ven)) {
|
||||
pr_info("%s: ven low in read !\n", __func__);
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pr_warn("%s: spurious interrupt detected\n", __func__);
|
||||
}
|
||||
}
|
||||
|
|
@ -332,20 +334,22 @@ int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
|||
goto err_nfc_misc_remove;
|
||||
}
|
||||
i2c_disable_irq(i2c_dev);
|
||||
device_init_wakeup(&client->dev, true);
|
||||
device_set_wakeup_capable(&client->dev, true);
|
||||
i2c_set_clientdata(client, nfc_dev);
|
||||
|
||||
ret = nfcc_hw_check(nfc_dev);
|
||||
if (ret) {
|
||||
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;
|
||||
|
||||
//SET VEN GPIO LOW and HIGH
|
||||
gpio_set_value(nfc_dev->gpio.ven, 0);
|
||||
usleep_range(10000, 10100);
|
||||
gpio_set_value(nfc_dev->gpio.ven, 1);
|
||||
usleep_range(10000, 10100);
|
||||
nfc_dev->nfc_ven_enabled = true;
|
||||
pr_info("%s success\n", __func__);
|
||||
return 0;
|
||||
|
||||
err_nfcc_hw_check:
|
||||
free_irq(client->irq, nfc_dev);
|
||||
err_nfc_misc_remove:
|
||||
nfc_misc_remove(nfc_dev, DEV_COUNT);
|
||||
err_mutex_destroy:
|
||||
|
|
@ -377,6 +381,7 @@ int nfc_i2c_dev_remove(struct i2c_client *client)
|
|||
ret = -ENODEV;
|
||||
return ret;
|
||||
}
|
||||
device_init_wakeup(&client->dev, false);
|
||||
free_irq(client->irq, nfc_dev);
|
||||
nfc_misc_remove(nfc_dev, DEV_COUNT);
|
||||
mutex_destroy(&nfc_dev->dev_ref_mutex);
|
||||
|
|
@ -456,8 +461,9 @@ static int __init nfc_i2c_dev_init(void)
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
pr_info("Loading NFC I2C driver\n");
|
||||
ret = i2c_add_driver(&nfc_i2c_dev_driver);
|
||||
if (ret != 0)
|
||||
pr_err("NFC I2C add driver error ret %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -465,7 +471,7 @@ module_init(nfc_i2c_dev_init);
|
|||
|
||||
static void __exit nfc_i2c_dev_exit(void)
|
||||
{
|
||||
pr_info("Unloading NFC I2C driver\n");
|
||||
pr_debug("Unloading NFC I2C driver\n");
|
||||
i2c_del_driver(&nfc_i2c_dev_driver);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "nfc_common.h"
|
||||
|
|
@ -154,7 +154,7 @@ static ssize_t i3c_kbuf_store(struct i3c_dev *i3c_dev, const char *buf,
|
|||
*
|
||||
* @return number of bytes copied , error code for failures .
|
||||
*/
|
||||
static ssize_t i3c_nci_kbuf_retrieve(struct i3c_dev *i3c_dev, char *buf,
|
||||
ssize_t i3c_nci_kbuf_retrieve(struct i3c_dev *i3c_dev, char *buf,
|
||||
size_t count)
|
||||
{
|
||||
size_t requested_size = count;
|
||||
|
|
@ -204,7 +204,7 @@ static ssize_t i3c_nci_kbuf_retrieve(struct i3c_dev *i3c_dev, char *buf,
|
|||
if (ret != 0) {
|
||||
pr_err("didn't get completion, interrupted!! ret %d\n",
|
||||
ret);
|
||||
return -EINVAL;
|
||||
return ret;
|
||||
}
|
||||
} while (available_size < requested_size);
|
||||
|
||||
|
|
@ -245,6 +245,7 @@ static ssize_t i3c_nci_kbuf_retrieve(struct i3c_dev *i3c_dev, char *buf,
|
|||
pr_debug("%s , count = %zx exit\n", __func__, count);
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL(i3c_nci_kbuf_retrieve);
|
||||
|
||||
/** @brief This API can be used to read data from I3C device from HAL layer.
|
||||
*
|
||||
|
|
@ -275,7 +276,7 @@ ssize_t nfc_i3c_dev_read(struct file *filp, char __user *buf,
|
|||
tmp = nfc_dev->kbuf;
|
||||
ret = i3c_nci_kbuf_retrieve(i3c_dev, tmp, count);
|
||||
if (ret != count) {
|
||||
pr_err("%s: buf read from I3C device returned error (%d)\n",
|
||||
pr_err("%s: kbuf read err ret (%d)\n",
|
||||
__func__, ret);
|
||||
ret = -EIO;
|
||||
} else if (copy_to_user(buf, tmp, ret)) {
|
||||
|
|
@ -322,7 +323,7 @@ ssize_t nfc_i3c_dev_write(struct file *filp, const char __user *buf,
|
|||
|
||||
ret = i3c_write(i3c_dev, tmp, count, NO_RETRY);
|
||||
if (ret != count) {
|
||||
pr_err("%s: failed to write %d\n", __func__, ret);
|
||||
pr_err("%s: i3c_write err ret %d\n", __func__, ret);
|
||||
ret = -EIO;
|
||||
goto out_free;
|
||||
}
|
||||
|
|
@ -364,7 +365,7 @@ static void i3c_workqueue_handler(struct work_struct *work)
|
|||
pr_err("%s: No memory to copy read data\n", __func__);
|
||||
return;
|
||||
}
|
||||
pr_info("%s: hdr_len = %d\n", __func__, hdr_len);
|
||||
pr_debug("%s: hdr_len = %d\n", __func__, hdr_len);
|
||||
memset(tmp, 0x00, i3c_dev->read_kbuf_len);
|
||||
|
||||
ret = i3c_read(i3c_dev, tmp, hdr_len);
|
||||
|
|
@ -419,7 +420,7 @@ static void i3c_ibi_handler(struct i3c_device *device,
|
|||
struct nfc_dev *nfc_dev = i3cdev_get_drvdata(device);
|
||||
struct i3c_dev *i3c_dev = &nfc_dev->i3c_dev;
|
||||
|
||||
pr_debug("%s: Received read IBI request from slave\n", __func__);
|
||||
pr_debug("%s\n", __func__);
|
||||
if (device_may_wakeup(&device->dev))
|
||||
pm_wakeup_event(&device->dev, WAKEUP_SRC_TIMEOUT);
|
||||
|
||||
|
|
@ -665,15 +666,21 @@ int nfc_i3c_dev_probe(struct i3c_device *device)
|
|||
goto err_nfc_misc_remove;
|
||||
}
|
||||
|
||||
atomic_set(&nfc_dev->i3c_dev.pm_state, PM_STATE_NORMAL);
|
||||
ret = nfcc_hw_check(nfc_dev);
|
||||
if (ret) {
|
||||
pr_err("nfc hw check failed ret %d\n", ret);
|
||||
goto err_nfcc_hw_check;
|
||||
}
|
||||
|
||||
atomic_set(&nfc_dev->i3c_dev.pm_state, PM_STATE_NORMAL);
|
||||
device_init_wakeup(&device->dev, true);
|
||||
device_set_wakeup_capable(&device->dev, true);
|
||||
|
||||
pr_info("%s success\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
err_nfcc_hw_check:
|
||||
i3c_device_free_ibi(device);
|
||||
err_nfc_misc_remove:
|
||||
nfc_misc_remove(nfc_dev, DEV_COUNT);
|
||||
err_wq_destroy:
|
||||
|
|
@ -825,9 +832,9 @@ static int __init nfc_dev_i3c_init(void)
|
|||
{
|
||||
int ret = 0;
|
||||
|
||||
pr_info("Loading NFC I3C driver\n");
|
||||
ret = i3c_driver_register_with_owner(&nfc_i3c_dev_driver, THIS_MODULE);
|
||||
pr_debug("NFC i3c driver register ret = %d\n", ret);
|
||||
if (ret != 0)
|
||||
pr_err("NFC I3C driver register error ret = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -835,7 +842,7 @@ module_init(nfc_dev_i3c_init);
|
|||
|
||||
static void __exit nfc_i3c_dev_exit(void)
|
||||
{
|
||||
pr_info("Unloading NFC I3C driver\n");
|
||||
pr_debug("Unloading NFC I3C driver\n");
|
||||
i3c_driver_unregister(&nfc_i3c_dev_driver);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _NFC_I3C_DRV_H_
|
||||
|
|
@ -96,6 +96,8 @@ int i3c_disable_ibi(struct i3c_dev *i3c_dev);
|
|||
ssize_t i3c_write(struct i3c_dev *i3c_dev, const char *buf, const size_t count,
|
||||
int max_retry_cnt);
|
||||
ssize_t i3c_read(struct i3c_dev *i3c_dev, char *buf, size_t count);
|
||||
ssize_t i3c_nci_kbuf_retrieve(struct i3c_dev *i3c_dev, char *buf,
|
||||
size_t count);
|
||||
|
||||
#else
|
||||
|
||||
|
|
@ -116,7 +118,13 @@ static inline ssize_t i3c_write(struct i3c_dev *i3c_dev,
|
|||
}
|
||||
|
||||
static inline ssize_t i3c_read(struct i3c_dev *i3c_dev,
|
||||
char *buf, size_t count);
|
||||
char *buf, size_t count)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
ssize_t i3c_nci_kbuf_retrieve(struct i3c_dev *i3c_dev, char *buf,
|
||||
size_t count)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
|
|
|||
11
include/linux/nfcinfo.h
Normal file
11
include/linux/nfcinfo.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _NFCINFO_H
|
||||
#define _NFCINFO_H
|
||||
|
||||
#include <uapi/linux/nfc/nfcinfo.h>
|
||||
|
||||
#endif
|
||||
26
include/uapi/linux/nfc/nfcinfo.h
Normal file
26
include/uapi/linux/nfc/nfcinfo.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_NFCINFO_H_
|
||||
#define _UAPI_NFCINFO_H_
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#define NFCC_MAGIC 0xE9
|
||||
#define NFCC_GET_INFO _IOW(NFCC_MAGIC, 0x09, unsigned int)
|
||||
|
||||
struct nqx_devinfo {
|
||||
unsigned char chip_type;
|
||||
unsigned char rom_version;
|
||||
unsigned char fw_major;
|
||||
unsigned char fw_minor;
|
||||
};
|
||||
|
||||
union nqx_uinfo {
|
||||
unsigned int i;
|
||||
struct nqx_devinfo info;
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in a new issue