NFC: Made the QTI NFC drivers GKI compliant

Removed circular dependency of nfc_common.c on NFC I2C and I3C drivers,
by setting interface specific API for nfc read,write,enable and disable
interrupts, in the interface drivers.

Change-Id: I66587d39ad92556d6e8fda3281e7bbcf1980683d
Signed-off-by: Karthik Poosa <[email protected]>
This commit is contained in:
Karthik Poosa 2020-01-13 12:29:37 +05:30
commit 5e2a9b4b62
7 changed files with 119 additions and 140 deletions

View file

@ -3,8 +3,8 @@
# Makefile for qti nfc drivers
#
obj-$(CONFIG_NFC_QTI_I2C) += nfc_i2c_drv.o
nfc_i2c_drv-objs:= nfc_common.o nfc_i2c_drv.o
obj-$(CONFIG_NFC_QTI_I2C) += nfc_i2c.o
nfc_i2c-objs:= nfc_common.o nfc_i2c_drv.o
obj-$(CONFIG_NFC_QTI_I3C) += nfc_i3c_drv.o
nfc_i3c_drv-objs:= nfc_common.o nfc_i3c_drv.o
obj-$(CONFIG_NFC_QTI_I3C) += nfc_i3c.o
nfc_i3c-objs:= nfc_common.o nfc_i3c_drv.o

View file

@ -8,24 +8,6 @@
#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)
@ -69,7 +51,6 @@ int nfc_parse_dt(struct device *dev, struct platform_gpio *nfc_gpio,
return 0;
}
EXPORT_SYMBOL(nfc_parse_dt);
void gpio_set_ven(struct nfc_dev *nfc_dev, int value)
{
@ -126,7 +107,6 @@ int configure_gpio(unsigned int gpio, int flag)
}
return ret;
}
EXPORT_SYMBOL(configure_gpio);
void nfc_misc_remove(struct nfc_dev *nfc_dev, int count)
{
@ -138,7 +118,6 @@ void nfc_misc_remove(struct nfc_dev *nfc_dev, int count)
class_destroy(nfc_dev->nfc_class);
unregister_chrdev_region(nfc_dev->devno, count);
}
EXPORT_SYMBOL(nfc_misc_remove);
int nfc_misc_probe(struct nfc_dev *nfc_dev,
const struct file_operations *nfc_fops, int count,
@ -191,23 +170,7 @@ int nfc_misc_probe(struct nfc_dev *nfc_dev,
return 0;
}
EXPORT_SYMBOL(nfc_misc_probe);
static void enable_interrupt(struct nfc_dev *nfc_dev)
{
if (nfc_dev->interface == PLATFORM_IF_I2C)
i2c_enable_irq(&nfc_dev->i2c_dev);
else
i3c_enable_ibi(&nfc_dev->i3c_dev);
}
static void disable_interrupt(struct nfc_dev *nfc_dev)
{
if (nfc_dev->interface == PLATFORM_IF_I2C)
i2c_disable_irq(&nfc_dev->i2c_dev);
else
i3c_disable_ibi(&nfc_dev->i3c_dev);
}
static int send_cold_reset_cmd(struct nfc_dev *nfc_dev)
{
@ -233,7 +196,7 @@ 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;
ret = nfc_write(nfc_dev, cold_reset_cmd,
ret = nfc_dev->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",
@ -261,7 +224,7 @@ void read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header)
if ((!cold_reset->is_nfc_enabled) &&
(nfc_dev->interface == PLATFORM_IF_I2C)) {
ret = i2c_read(&nfc_dev->i2c_dev, cold_reset_rsp,
ret = nfc_dev->nfc_read(nfc_dev, cold_reset_rsp,
NCI_HDR_LEN);
if (ret <= 0) {
pr_err("%s: failure to read cold reset rsp header\n",
@ -288,11 +251,11 @@ void read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header)
}
if (nfc_dev->interface == PLATFORM_IF_I2C)
ret = i2c_read(&nfc_dev->i2c_dev,
ret = nfc_dev->nfc_read(nfc_dev,
&cold_reset_rsp[NCI_PAYLOAD_IDX],
cold_reset_rsp[2]);
else
ret = i3c_read(&nfc_dev->i3c_dev,
ret = nfc_dev->i3c_dev.nfc_read_direct(nfc_dev,
&cold_reset_rsp[NCI_PAYLOAD_IDX],
cold_reset_rsp[2]);
@ -306,7 +269,6 @@ void read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header)
error:
kfree(cold_reset_rsp);
}
EXPORT_SYMBOL(read_cold_reset_rsp);
/*
* Power management of the eSE
@ -367,7 +329,7 @@ int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg)
// Read data as NFC thread is not active
enable_interrupt(nfc_dev);
nfc_dev->nfc_enable_intr(nfc_dev);
if (nfc_dev->interface == PLATFORM_IF_I2C) {
ret = wait_event_interruptible_timeout(
@ -375,7 +337,7 @@ int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg)
!nfc_dev->i2c_dev.irq_enabled,
msecs_to_jiffies(MAX_IRQ_WAIT_TIME));
if (ret <= 0) {
disable_interrupt(nfc_dev);
nfc_dev->nfc_disable_intr(nfc_dev);
nfc_dev->cold_reset.rsp_pending = false;
return nfc_dev->cold_reset.status;
}
@ -385,7 +347,7 @@ int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg)
wait_event_interruptible(
nfc_dev->cold_reset.read_wq,
!nfc_dev->cold_reset.rsp_pending);
disable_interrupt(nfc_dev);
nfc_dev->nfc_disable_intr(nfc_dev);
}
}
@ -400,7 +362,6 @@ int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg)
}
return ret;
}
EXPORT_SYMBOL(nfc_ese_pwr);
/*
* nfc_ioctl_power_states() - power control
@ -422,7 +383,7 @@ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg)
* interrupts to avoid spurious notifications to upper
* layers.
*/
disable_interrupt(nfc_dev);
nfc_dev->nfc_disable_intr(nfc_dev);
pr_debug("gpio firm disable\n");
if (gpio_is_valid(nfc_dev->gpio.dwl_req)) {
gpio_set_value(nfc_dev->gpio.dwl_req, 0);
@ -435,7 +396,7 @@ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg)
nfc_dev->nfc_ven_enabled = false;
} else if (arg == NFC_POWER_ON) {
enable_interrupt(nfc_dev);
nfc_dev->nfc_enable_intr(nfc_dev);
pr_debug("gpio_set_value enable: %s:\n", __func__);
if (gpio_is_valid(nfc_dev->gpio.dwl_req)) {
gpio_set_value(nfc_dev->gpio.dwl_req, 0);
@ -575,7 +536,6 @@ long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)
}
return ret;
}
EXPORT_SYMBOL(nfc_dev_ioctl);
int nfc_dev_open(struct inode *inode, struct file *filp)
{
@ -596,7 +556,7 @@ int nfc_dev_open(struct inode *inode, struct file *filp)
gpio_set_value(nfc_dev->gpio.dwl_req, 0);
usleep_range(10000, 10100);
}
enable_interrupt(nfc_dev);
nfc_dev->nfc_enable_intr(nfc_dev);
}
nfc_dev->dev_ref_count = nfc_dev->dev_ref_count + 1;
@ -604,7 +564,6 @@ int nfc_dev_open(struct inode *inode, struct file *filp)
return 0;
}
EXPORT_SYMBOL(nfc_dev_open);
int nfc_dev_close(struct inode *inode, struct file *filp)
{
@ -620,7 +579,7 @@ int nfc_dev_close(struct inode *inode, struct file *filp)
if (nfc_dev->dev_ref_count == 1) {
disable_interrupt(nfc_dev);
nfc_dev->nfc_disable_intr(nfc_dev);
if (gpio_is_valid(nfc_dev->gpio.dwl_req)) {
gpio_set_value(nfc_dev->gpio.dwl_req, 0);
@ -637,13 +596,12 @@ 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);
nfc_dev->nfc_enable_intr(nfc_dev);
ret = wait_event_interruptible_timeout(nfc_dev->read_wq,
!nfc_dev->i2c_dev.irq_enabled,
@ -693,7 +651,7 @@ int nfcc_hw_check(struct nfc_dev *nfc_dev)
}
if (nfc_dev->interface == PLATFORM_IF_I3C)
enable_interrupt(nfc_dev);
nfc_dev->nfc_enable_intr(nfc_dev);
else {
/* making sure that the NFCC starts in a clean state. */
gpio_set_ven(nfc_dev, 1);/* HPD : Enable*/
@ -707,7 +665,7 @@ int nfcc_hw_check(struct nfc_dev *nfc_dev)
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,
ret = nfc_dev->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__);
@ -731,7 +689,7 @@ int nfcc_hw_check(struct nfc_dev *nfc_dev)
nci_get_version_cmd[6] = 0x6E;
nci_get_version_cmd[7] = 0xEF;
ret = nfc_write(nfc_dev, nci_get_version_cmd,
ret = nfc_dev->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",
@ -742,14 +700,14 @@ int nfcc_hw_check(struct nfc_dev *nfc_dev)
if (nfc_dev->interface == PLATFORM_IF_I2C) {
ret = is_data_available_for_read(nfc_dev);
if (ret <= 0) {
disable_interrupt(nfc_dev);
nfc_dev->nfc_disable_intr(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,
ret = nfc_dev->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",
@ -774,7 +732,7 @@ int nfcc_hw_check(struct nfc_dev *nfc_dev)
if (nfc_dev->interface == PLATFORM_IF_I2C) {
ret = is_data_available_for_read(nfc_dev);
if (ret <= 0) {
disable_interrupt(nfc_dev);
nfc_dev->nfc_disable_intr(nfc_dev);
pr_err("%s: - error waiting for core reset rsp ret %d\n",
__func__, ret);
@ -783,7 +741,7 @@ int nfcc_hw_check(struct nfc_dev *nfc_dev)
}
/* Read Response of RESET command */
ret = nfc_read(nfc_dev, nci_reset_rsp, NCI_RESET_RSP_LEN);
ret = nfc_dev->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);
@ -795,13 +753,13 @@ int nfcc_hw_check(struct nfc_dev *nfc_dev)
if (ret <= 0) {
pr_err("%s: - error waiting for core reset ntf ret %d\n",
__func__, ret);
disable_interrupt(nfc_dev);
nfc_dev->nfc_disable_intr(nfc_dev);
goto err_nfcc_hw_check;
}
}
/* Read Notification of RESET command */
ret = nfc_read(nfc_dev, nci_reset_ntf, NCI_RESET_NTF_LEN);
ret = nfc_dev->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;
@ -856,7 +814,7 @@ err_nfcc_hw_check:
disable_i3c_intr:
if (nfc_dev->interface == PLATFORM_IF_I3C)
disable_interrupt(nfc_dev);
nfc_dev->nfc_disable_intr(nfc_dev);
done:
kfree(nci_reset_rsp);
kfree(nci_reset_ntf);
@ -866,4 +824,3 @@ done:
return ret;
}
EXPORT_SYMBOL(nfcc_hw_check);

View file

@ -197,6 +197,13 @@ struct nfc_dev {
u8 *kbuf;
union nqx_uinfo nqx_info;
int (*nfc_read)(struct nfc_dev *dev,
char *buf, size_t count);
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);

View file

@ -11,18 +11,20 @@
* Check if interrupt is disabled or not
* and disable interrupt
*
* Return: void
* Return: int
*/
void i2c_disable_irq(struct i2c_dev *i2c_dev)
int i2c_disable_irq(struct nfc_dev *dev)
{
unsigned long flags;
spin_lock_irqsave(&i2c_dev->irq_enabled_lock, flags);
if (i2c_dev->irq_enabled) {
disable_irq_nosync(i2c_dev->client->irq);
i2c_dev->irq_enabled = false;
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(&i2c_dev->irq_enabled_lock, flags);
spin_unlock_irqrestore(&dev->i2c_dev.irq_enabled_lock, flags);
return 0;
}
/**
@ -31,18 +33,20 @@ void i2c_disable_irq(struct i2c_dev *i2c_dev)
* Check if interrupt is enabled or not
* and enable interrupt
*
* Return: void
* Return: int
*/
void i2c_enable_irq(struct i2c_dev *i2c_dev)
int i2c_enable_irq(struct nfc_dev *dev)
{
unsigned long flags;
spin_lock_irqsave(&i2c_dev->irq_enabled_lock, flags);
if (!i2c_dev->irq_enabled) {
i2c_dev->irq_enabled = true;
enable_irq(i2c_dev->client->irq);
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(&i2c_dev->irq_enabled_lock, flags);
spin_unlock_irqrestore(&dev->i2c_dev.irq_enabled_lock, flags);
return 0;
}
static irqreturn_t i2c_irq_handler(int irq, void *dev_id)
@ -53,19 +57,19 @@ static irqreturn_t i2c_irq_handler(int irq, void *dev_id)
if (device_may_wakeup(&i2c_dev->client->dev))
pm_wakeup_event(&i2c_dev->client->dev, WAKEUP_SRC_TIMEOUT);
i2c_disable_irq(i2c_dev);
i2c_disable_irq(nfc_dev);
wake_up(&nfc_dev->read_wq);
return IRQ_HANDLED;
}
int i2c_read(struct i2c_dev *i2c_dev, char *buf, size_t count)
int i2c_read(struct nfc_dev *dev, char *buf, size_t count)
{
int ret;
pr_debug("%s : reading %zu bytes.\n", __func__, count);
/* Read data */
ret = i2c_master_recv(i2c_dev->client, buf, count);
ret = i2c_master_recv(dev->i2c_dev.client, buf, count);
if (ret <= 0) {
pr_err("%s: i2c_master_recv returned %d\n", __func__, ret);
goto i2c_read_err;
@ -80,9 +84,8 @@ int i2c_read(struct i2c_dev *i2c_dev, char *buf, size_t count)
i2c_read_err:
return ret;
}
EXPORT_SYMBOL(i2c_read);
int i2c_write(struct i2c_dev *i2c_dev, char *buf, size_t count,
int i2c_write(struct nfc_dev *dev, const char *buf, size_t count,
int max_retry_cnt)
{
int ret = -EINVAL;
@ -91,7 +94,7 @@ int i2c_write(struct i2c_dev *i2c_dev, char *buf, size_t count,
pr_debug("%s : writing %zu bytes.\n", __func__, count);
for (retry_cnt = 1; retry_cnt <= max_retry_cnt; retry_cnt++) {
ret = i2c_master_send(i2c_dev->client, buf, count);
ret = i2c_master_send(dev->i2c_dev.client, buf, count);
if (ret <= 0) {
pr_warn("%s: write failed, Maybe in Standby Mode - Retry(%d)\n",
__func__, retry_cnt);
@ -101,7 +104,6 @@ int i2c_write(struct i2c_dev *i2c_dev, char *buf, size_t count,
}
return ret;
}
EXPORT_SYMBOL(i2c_write);
ssize_t nfc_i2c_dev_read(struct file *filp, char __user *buf,
size_t count, loff_t *offset)
@ -142,7 +144,7 @@ ssize_t nfc_i2c_dev_read(struct file *filp, char __user *buf,
goto err;
}
}
i2c_disable_irq(i2c_dev);
i2c_disable_irq(nfc_dev);
if (gpio_get_value(nfc_dev->gpio.irq))
break;
@ -166,7 +168,7 @@ ssize_t nfc_i2c_dev_read(struct file *filp, char __user *buf,
memset(tmp, 0x00, count);
/* Read data */
ret = i2c_read(i2c_dev, tmp, count);
ret = i2c_read(nfc_dev, tmp, count);
if (ret <= 0) {
pr_err("%s: i2c_master_recv returned %d\n", __func__, ret);
goto err;
@ -206,7 +208,6 @@ ssize_t nfc_i2c_dev_write(struct file *filp, const char __user *buf,
int ret;
char *tmp = NULL;
struct nfc_dev *nfc_dev = filp->private_data;
struct i2c_dev *i2c_dev = &nfc_dev->i2c_dev;
if (!nfc_dev) {
ret = -ENODEV;
@ -226,7 +227,7 @@ ssize_t nfc_i2c_dev_write(struct file *filp, const char __user *buf,
goto out;
}
ret = i2c_write(i2c_dev, tmp, count, NO_RETRY);
ret = i2c_write(nfc_dev, tmp, count, NO_RETRY);
if (ret != count) {
pr_err("%s: failed to write %d\n", __func__, ret);
ret = -EIO;
@ -279,6 +280,10 @@ int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id)
nfc_dev->interface = PLATFORM_IF_I2C;
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;
ret = configure_gpio(nfc_gpio.ven, GPIO_OUTPUT);
if (ret) {
@ -333,7 +338,7 @@ int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id)
pr_err("%s: request_irq failed\n", __func__);
goto err_nfc_misc_remove;
}
i2c_disable_irq(i2c_dev);
i2c_disable_irq(nfc_dev);
i2c_set_clientdata(client, nfc_dev);
ret = nfcc_hw_check(nfc_dev);

View file

@ -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_I2C_DRV_H_
@ -10,6 +10,8 @@
#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;
@ -26,31 +28,33 @@ 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);
#ifdef CONFIG_NFC_QTI_I2C
#if IS_ENABLED(CONFIG_NFC_QTI_I2C)
void i2c_enable_irq(struct i2c_dev *i2c_dev);
void i2c_disable_irq(struct i2c_dev *i2c_dev);
int i2c_write(struct i2c_dev *i2c_dev, char *buf, size_t count,
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 i2c_dev *i2c_dev, char *buf, size_t count);
int i2c_read(struct nfc_dev *dev, char *buf, size_t count);
#else
static inline void i2c_enable_irq(struct i2c_dev *i2c_dev)
{
}
static inline void i2c_disable_irq(struct i2c_dev *i2c_dev)
{
}
static inline int i2c_write(struct i2c_dev *i2c_dev, char *buf, size_t count,
int max_retry_cnt)
static inline int i2c_enable_irq(struct nfc_dev *dev)
{
return -ENXIO;
}
static inline int i2c_read(struct i2c_dev *i2c_dev, char *buf, size_t count)
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)
{
return -ENXIO;
}

View file

@ -14,7 +14,7 @@
*
* @return ret number of bytes written ,negative error core otherwise.
*/
ssize_t i3c_write(struct i3c_dev *i3c_dev, const char *buf, const size_t count,
int i3c_write(struct nfc_dev *dev, const char *buf, const size_t count,
int max_retry_cnt)
{
int ret = -EIO;
@ -26,7 +26,7 @@ ssize_t i3c_write(struct i3c_dev *i3c_dev, const char *buf, const size_t count,
};
do {
ret = i3c_device_do_priv_xfers(i3c_dev->device, &write_buf,
ret = i3c_device_do_priv_xfers(dev->i3c_dev.device, &write_buf,
(sizeof(write_buf) / sizeof(struct i3c_priv_xfer)));
pr_debug("%s exit ret = %x\n", __func__, ret);
@ -42,7 +42,6 @@ ssize_t i3c_write(struct i3c_dev *i3c_dev, const char *buf, const size_t count,
return ret;
}
EXPORT_SYMBOL(i3c_write);
/** @brief This API used to read data from I3C device.
*
@ -52,7 +51,7 @@ EXPORT_SYMBOL(i3c_write);
*
* @return number of bytes read ,negative error code otherwise.
*/
ssize_t i3c_read(struct i3c_dev *i3c_dev, char *buf, size_t count)
int i3c_read(struct nfc_dev *dev, char *buf, size_t count)
{
int ret = -EIO;
struct i3c_priv_xfer read_buf = {
@ -61,7 +60,7 @@ ssize_t i3c_read(struct i3c_dev *i3c_dev, char *buf, size_t count)
.data.in = buf
};
ret = i3c_device_do_priv_xfers(i3c_dev->device, &read_buf,
ret = i3c_device_do_priv_xfers(dev->i3c_dev.device, &read_buf,
(sizeof(read_buf) / sizeof(struct i3c_priv_xfer)));
pr_debug("%s exit ret = %x\n", __func__, ret);
if (!ret)
@ -71,7 +70,6 @@ ssize_t i3c_read(struct i3c_dev *i3c_dev, char *buf, size_t count)
return ret;
}
EXPORT_SYMBOL(i3c_read);
/** @brief This API can be used to write data to nci buf.
* The API will overwrite the existing memory if
@ -154,12 +152,13 @@ static ssize_t i3c_kbuf_store(struct i3c_dev *i3c_dev, const char *buf,
*
* @return number of bytes copied , error code for failures .
*/
ssize_t i3c_nci_kbuf_retrieve(struct i3c_dev *i3c_dev, char *buf,
int i3c_nci_kbuf_retrieve(struct nfc_dev *dev, char *buf,
size_t count)
{
size_t requested_size = count;
size_t available_size = 0;
size_t copied_size = 0;
struct i3c_dev *i3c_dev = &dev->i3c_dev;
int ret = 0;
if (i3c_dev == NULL)
@ -245,7 +244,6 @@ 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.
*
@ -264,7 +262,6 @@ ssize_t nfc_i3c_dev_read(struct file *filp, char __user *buf,
int ret;
char *tmp = NULL;
struct nfc_dev *nfc_dev = filp->private_data;
struct i3c_dev *i3c_dev = &nfc_dev->i3c_dev;
if (count > nfc_dev->kbuflen)
count = nfc_dev->kbuflen;
@ -274,7 +271,7 @@ ssize_t nfc_i3c_dev_read(struct file *filp, char __user *buf,
mutex_lock(&nfc_dev->read_mutex);
tmp = nfc_dev->kbuf;
ret = i3c_nci_kbuf_retrieve(i3c_dev, tmp, count);
ret = i3c_nci_kbuf_retrieve(nfc_dev, tmp, count);
if (ret != count) {
pr_err("%s: kbuf read err ret (%d)\n",
__func__, ret);
@ -303,7 +300,6 @@ ssize_t nfc_i3c_dev_write(struct file *filp, const char __user *buf,
int ret;
char *tmp = NULL;
struct nfc_dev *nfc_dev = filp->private_data;
struct i3c_dev *i3c_dev = &nfc_dev->i3c_dev;
if (!nfc_dev)
return -ENODEV;
@ -321,7 +317,7 @@ ssize_t nfc_i3c_dev_write(struct file *filp, const char __user *buf,
goto out;
}
ret = i3c_write(i3c_dev, tmp, count, NO_RETRY);
ret = i3c_write(nfc_dev, tmp, count, NO_RETRY);
if (ret != count) {
pr_err("%s: i3c_write err ret %d\n", __func__, ret);
ret = -EIO;
@ -368,7 +364,7 @@ static void i3c_workqueue_handler(struct work_struct *work)
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);
ret = i3c_read(nfc_dev, tmp, hdr_len);
if (ret < 0) {
pr_err("%s: i3c_read returned error %d\n", __func__, ret);
return;
@ -396,7 +392,7 @@ static void i3c_workqueue_handler(struct work_struct *work)
return;
}
ret = i3c_read(i3c_dev, tmp + hdr_len, length_byte);
ret = i3c_read(nfc_dev, tmp + hdr_len, length_byte);
if (ret < 0) {
pr_err("%s: i3c_read returned error %d\n", __func__, ret);
i3c_kbuf_store(i3c_dev, tmp, hdr_len);
@ -439,17 +435,17 @@ static void i3c_ibi_handler(struct i3c_device *device,
*
* @return 0 on success, error code for failures.
*/
int i3c_enable_ibi(struct i3c_dev *i3c_dev)
int i3c_enable_ibi(struct nfc_dev *dev)
{
int ret = 0;
int retry_count = 0;
if (!i3c_dev->ibi_enabled) {
if (!dev->i3c_dev.ibi_enabled) {
do {
ret = i3c_device_enable_ibi(i3c_dev->device);
ret = i3c_device_enable_ibi(dev->i3c_dev.device);
if (!ret) {
i3c_dev->ibi_enabled = true;
dev->i3c_dev.ibi_enabled = true;
break;
}
@ -470,17 +466,17 @@ int i3c_enable_ibi(struct i3c_dev *i3c_dev)
*
* @return 0 on success, error code for failures.
*/
int i3c_disable_ibi(struct i3c_dev *i3c_dev)
int i3c_disable_ibi(struct nfc_dev *dev)
{
int ret = 0;
int retry_count = 0;
if (i3c_dev->ibi_enabled) {
if (dev->i3c_dev.ibi_enabled) {
do {
ret = i3c_device_disable_ibi(i3c_dev->device);
ret = i3c_device_disable_ibi(dev->i3c_dev.device);
if (!ret) {
i3c_dev->ibi_enabled = false;
dev->i3c_dev.ibi_enabled = false;
break;
}
@ -615,6 +611,11 @@ int nfc_i3c_dev_probe(struct i3c_device *device)
nfc_dev->i3c_dev.buf.total_size = PAGE_SIZE;
i3c_reset_nci_buf(&nfc_dev->i3c_dev);
nfc_dev->interface = PLATFORM_IF_I3C;
nfc_dev->nfc_write = i3c_write;
nfc_dev->nfc_read = i3c_nci_kbuf_retrieve;
nfc_dev->i3c_dev.nfc_read_direct = i3c_read;
nfc_dev->nfc_enable_intr = i3c_enable_ibi;
nfc_dev->nfc_disable_intr = i3c_disable_ibi;
nfc_dev->i3c_dev.device = device;
ret = configure_gpio(nfc_gpio.ven, GPIO_OUTPUT_HIGH);

View file

@ -41,6 +41,8 @@
// I3C WorkQueue name
#define NFC_I3C_WORKQUEUE "nfc_i3c_workq"
struct nfc_dev;
/**
* struct nci_buf - NCI buffer used to store and retrieve read data from device.
* @read_offset: The offset pointing to data available to read in nci buf.
@ -69,6 +71,7 @@ struct nci_buf {
* @read_hdr Header size for reads.
* @ibi_enabled: IBI enabled or not.
* @pm_state: PM state of NFC I3C device.
* @nfc_read_direct Do NFC read bypassing the read buffer.
*/
struct i3c_dev {
struct i3c_device *device;
@ -82,6 +85,8 @@ struct i3c_dev {
unsigned char read_hdr;
bool ibi_enabled;
atomic_t pm_state;
int (*nfc_read_direct)(struct nfc_dev *dev,
char *buf, size_t count);
};
int nfc_i3c_dev_probe(struct i3c_device *device);
@ -89,42 +94,42 @@ int nfc_i3c_dev_remove(struct i3c_device *device);
int nfc_i3c_dev_suspend(struct device *device);
int nfc_i3c_dev_resume(struct device *device);
#ifdef CONFIG_NFC_QTI_I3C
#if IS_ENABLED(CONFIG_NFC_QTI_I3C)
int i3c_enable_ibi(struct i3c_dev *i3c_dev);
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 i3c_enable_ibi(struct nfc_dev *dev);
int i3c_disable_ibi(struct nfc_dev *dev);
int i3c_write(struct nfc_dev *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,
int i3c_read(struct nfc_dev *dev, char *buf, size_t count);
int i3c_nci_kbuf_retrieve(struct nfc_dev *dev, char *buf,
size_t count);
#else
static inline int i3c_enable_ibi(struct i3c_dev *i3c_dev)
static inline int i3c_enable_ibi(struct nfc_dev *dev)
{
return -ENXIO;
}
static inline int i3c_disable_ibi(struct i3c_dev *i3c_dev)
static inline int i3c_disable_ibi(struct nfc_dev *dev)
{
return -ENXIO;
}
static inline ssize_t i3c_write(struct i3c_dev *i3c_dev,
static inline int i3c_write(struct nfc_dev *dev,
const char *buf, const size_t count, int max_retry_cnt)
{
return -ENXIO;
}
static inline ssize_t i3c_read(struct i3c_dev *i3c_dev,
static inline int i3c_read(struct nfc_dev *dev,
char *buf, size_t count)
{
return -ENXIO;
}
ssize_t i3c_nci_kbuf_retrieve(struct i3c_dev *i3c_dev, char *buf,
size_t count)
static inline int i3c_nci_kbuf_retrieve(struct nfc_dev *dev,
char *buf, size_t count)
{
return -ENXIO;
}