NFC: Add support for ese cold reset, protection ioctl
Add new ioctl to do ese cold reset, cold reset protection and move the old ese cold reset functionality under the new ioctl. Change-Id: I77305e4748d8e3a073d811b62550232ee0822f94 Signed-off-by: Karthik Poosa <kpoosa2@codeaurora.org>
This commit is contained in:
parent
ee692e5440
commit
16fe800e66
@ -4,9 +4,9 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_NFC_QTI_I2C) += nfc_i2c.o
|
||||
nfc_i2c-objs:= nfc_common.o nfc_i2c_drv.o
|
||||
nfc_i2c-objs:= ese_cold_reset.o nfc_common.o nfc_i2c_drv.o
|
||||
|
||||
obj-$(CONFIG_NFC_QTI_I3C) += nfc_i3c.o
|
||||
nfc_i3c-objs:= nfc_common.o nfc_i3c_drv.o
|
||||
nfc_i3c-objs:= ese_cold_reset.o nfc_common.o nfc_i3c_drv.o
|
||||
|
||||
obj-$(CONFIG_NFC_QTI_I3C_GPIO) += nfc_i3c_gpio_cfg.o
|
||||
|
342
drivers/nfc/qti/ese_cold_reset.c
Normal file
342
drivers/nfc/qti/ese_cold_reset.c
Normal file
@ -0,0 +1,342 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include "nfc_common.h"
|
||||
|
||||
/**
|
||||
* send_ese_cmd() - Send eSE command to NFC controller.
|
||||
* @nfc_dev: NFC device handle.
|
||||
*
|
||||
* Return: 0 on pass and negative value on failure.
|
||||
*/
|
||||
static int send_ese_cmd(struct nfc_dev *nfc_dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (gpio_get_value(nfc_dev->gpio.dwl_req)) {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"cannot send ese cmd as FW download is in-progress\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (!gpio_get_value(nfc_dev->gpio.ven)) {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"cannot send ese cmd as NFCC powered off\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = nfc_dev->nfc_write(nfc_dev, nfc_dev->cold_reset.cmd_buf,
|
||||
nfc_dev->cold_reset.cmd_len,
|
||||
MAX_RETRY_COUNT);
|
||||
if (ret <= 0)
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"%s: write failed after max retry, ret %d\n",
|
||||
__func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* read_cold_reset_rsp() - Read response of the cold reset command.
|
||||
* @nfc_dev: NFC device handle.
|
||||
* @header: Pointer to NCI header if it is already read.
|
||||
*
|
||||
* Return: 0 on pass and negative value on failure.
|
||||
*/
|
||||
int read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header)
|
||||
{
|
||||
int ret;
|
||||
struct cold_reset *cold_rst = &nfc_dev->cold_reset;
|
||||
char *rsp_buf = NULL;
|
||||
|
||||
rsp_buf = kzalloc(cold_rst->rsp_len, GFP_DMA | GFP_KERNEL);
|
||||
if (!rsp_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* read header if NFC is disabled
|
||||
* for enable case, header is read by nfc read thread(for i2c)
|
||||
* or worker function(for i3c)
|
||||
*/
|
||||
if ((!cold_rst->is_nfc_enabled) &&
|
||||
(nfc_dev->interface == PLATFORM_IF_I2C)) {
|
||||
ret = nfc_dev->nfc_read(nfc_dev, rsp_buf, NCI_HDR_LEN);
|
||||
if (ret <= 0) {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"%s: failure to read cold reset rsp header\n",
|
||||
__func__);
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
}
|
||||
/*
|
||||
* return failure, if packet is not a response packet or
|
||||
* if response's OID doesn't match with the CMD's OID
|
||||
*/
|
||||
if (!(rsp_buf[0] & NCI_RSP_PKT_TYPE) ||
|
||||
(rsp_buf[1] != cold_rst->cmd_buf[1])) {
|
||||
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"%s: - invalid cold reset response 0x%x 0x%x\n",
|
||||
__func__, rsp_buf[0], rsp_buf[1]);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
} else if (header)
|
||||
memcpy(rsp_buf, header, NCI_HDR_LEN);
|
||||
else {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"%s: - invalid or NULL header\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((NCI_HDR_LEN + rsp_buf[NCI_PAYLOAD_LEN_IDX]) >
|
||||
cold_rst->rsp_len) {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"%s: - no space for cold_reset resp\n", __func__);
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C)
|
||||
ret = nfc_dev->nfc_read(nfc_dev,
|
||||
&rsp_buf[NCI_PAYLOAD_IDX],
|
||||
rsp_buf[NCI_PAYLOAD_LEN_IDX]);
|
||||
else
|
||||
ret = nfc_dev->i3c_dev.nfc_read_direct(nfc_dev,
|
||||
&rsp_buf[NCI_PAYLOAD_IDX],
|
||||
rsp_buf[NCI_PAYLOAD_LEN_IDX]);
|
||||
|
||||
if (ret <= 0) {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"%s: failure to read cold reset rsp payload\n",
|
||||
__func__);
|
||||
ret = -EIO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = cold_rst->status = rsp_buf[NCI_PAYLOAD_IDX];
|
||||
|
||||
pr_debug("nfc ese rsp hdr 0x%x 0x%x 0x%x, payload byte0 0x%x\n",
|
||||
rsp_buf[0], rsp_buf[1], rsp_buf[2], rsp_buf[3]);
|
||||
error:
|
||||
kfree(rsp_buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ese_cold_reset_ioctl() - This function handles the eSE cold reset ioctls.
|
||||
* @nfc_dev: NFC device handle.
|
||||
* @arg: ioctl argument.
|
||||
*
|
||||
* Return: 0 on pass and negative value on failure.
|
||||
*/
|
||||
|
||||
int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
struct ese_ioctl_arg ioctl_arg;
|
||||
|
||||
if (!arg) {
|
||||
dev_err(nfc_dev->nfc_device, "arg is invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = copy_from_user((void *)&ioctl_arg, (const void *)arg,
|
||||
sizeof(ioctl_arg));
|
||||
if (ret) {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"ese ioctl arg copy from user failed\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
nfc_dev->cold_reset.arg = kzalloc(ioctl_arg.buf_size,
|
||||
GFP_KERNEL);
|
||||
if (!nfc_dev->cold_reset.arg)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = copy_struct_from_user(nfc_dev->cold_reset.arg,
|
||||
sizeof(struct ese_cold_reset_arg),
|
||||
u64_to_user_ptr(ioctl_arg.buf),
|
||||
ioctl_arg.buf_size);
|
||||
if (ret) {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"ese ioctl arg buffer copy from user failed\n");
|
||||
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
switch (nfc_dev->cold_reset.arg->sub_cmd) {
|
||||
|
||||
case ESE_COLD_RESET_DO:
|
||||
|
||||
/*
|
||||
* cold reset allowed during protection enable, only if the
|
||||
* source is same as the one which enabled protection.
|
||||
*/
|
||||
if (nfc_dev->cold_reset.is_crp_en &&
|
||||
(nfc_dev->cold_reset.arg->src !=
|
||||
nfc_dev->cold_reset.last_src_ese_prot)) {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"cold reset from %d denied, protection is on\n",
|
||||
nfc_dev->cold_reset.arg->src);
|
||||
ret = -EACCES;
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfc_dev->cold_reset.cmd_buf = kzalloc(COLD_RESET_CMD_LEN,
|
||||
GFP_DMA | GFP_KERNEL);
|
||||
if (!nfc_dev->cold_reset.cmd_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfc_dev->cold_reset.cmd_buf[0] = PROP_NCI_CMD_GID;
|
||||
nfc_dev->cold_reset.cmd_buf[1] = COLD_RESET_OID;
|
||||
nfc_dev->cold_reset.cmd_buf[2] = COLD_RESET_CMD_PL_LEN;
|
||||
nfc_dev->cold_reset.cmd_len = NCI_HDR_LEN +
|
||||
COLD_RESET_CMD_PL_LEN;
|
||||
nfc_dev->cold_reset.rsp_len = COLD_RESET_RSP_LEN;
|
||||
break;
|
||||
|
||||
case ESE_COLD_RESET_PROTECT_EN:
|
||||
|
||||
if (nfc_dev->cold_reset.is_crp_en) {
|
||||
if (nfc_dev->cold_reset.arg->src !=
|
||||
nfc_dev->cold_reset.last_src_ese_prot) {
|
||||
dev_err(nfc_dev->nfc_device,
|
||||
"ese protection enable denied\n");
|
||||
ret = -EACCES;
|
||||
goto err;
|
||||
}
|
||||
pr_warn("ese protection already enabled\n");
|
||||
|
||||
ret = 0;
|
||||
/* free buffers and exit with pass */
|
||||
goto err;
|
||||
}
|
||||
|
||||
case ESE_COLD_RESET_PROTECT_DIS:
|
||||
|
||||
if (nfc_dev->cold_reset.is_crp_en &&
|
||||
nfc_dev->cold_reset.arg->src !=
|
||||
nfc_dev->cold_reset.last_src_ese_prot) {
|
||||
pr_err("ese cold reset protection disable denied\n");
|
||||
ret = -EACCES;
|
||||
goto err;
|
||||
}
|
||||
nfc_dev->cold_reset.cmd_buf = kzalloc(COLD_RESET_PROT_CMD_LEN,
|
||||
GFP_DMA | GFP_KERNEL);
|
||||
if (!nfc_dev->cold_reset.cmd_buf) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfc_dev->cold_reset.cmd_buf[0] = PROP_NCI_CMD_GID;
|
||||
nfc_dev->cold_reset.cmd_buf[1] = COLD_RESET_PROT_OID;
|
||||
nfc_dev->cold_reset.cmd_buf[2] = COLD_RESET_PROT_CMD_PL_LEN;
|
||||
nfc_dev->cold_reset.cmd_len = NCI_HDR_LEN +
|
||||
COLD_RESET_PROT_CMD_PL_LEN;
|
||||
nfc_dev->cold_reset.rsp_len = COLD_RESET_PROT_RSP_LEN;
|
||||
if (nfc_dev->cold_reset.arg->sub_cmd ==
|
||||
ESE_COLD_RESET_PROTECT_EN)
|
||||
nfc_dev->cold_reset.cmd_buf[3] = 0x1;
|
||||
else
|
||||
nfc_dev->cold_reset.cmd_buf[3] = 0x0;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
pr_err("%s invalid ese ioctl sub cmd %d\n", __func__,
|
||||
nfc_dev->cold_reset.arg->sub_cmd);
|
||||
ret = -ENOIOCTLCMD;
|
||||
goto err;
|
||||
}
|
||||
|
||||
pr_debug("nfc ese cmd hdr 0x%x 0x%x 0x%x , payload byte0 = 0x%x\n",
|
||||
nfc_dev->cold_reset.cmd_buf[0],
|
||||
nfc_dev->cold_reset.cmd_buf[1],
|
||||
nfc_dev->cold_reset.cmd_buf[2],
|
||||
nfc_dev->cold_reset.cmd_buf[3]);
|
||||
|
||||
ret = send_ese_cmd(nfc_dev);
|
||||
if (ret <= 0) {
|
||||
pr_err("failed to send ese command\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
nfc_dev->cold_reset.rsp_pending = true;
|
||||
|
||||
/* check if NFC is enabled */
|
||||
if (nfc_dev->cold_reset.is_nfc_enabled) {
|
||||
/*
|
||||
* nfc_read thread will initiate cold reset response
|
||||
* and it will signal for data available
|
||||
*/
|
||||
wait_event_interruptible(nfc_dev->cold_reset.read_wq,
|
||||
!nfc_dev->cold_reset.rsp_pending);
|
||||
} else {
|
||||
|
||||
/*
|
||||
* Read data as NFC read thread is not active
|
||||
* For I3C driver response is already read by worker
|
||||
* function
|
||||
*/
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C) {
|
||||
ret = is_nfc_data_available_for_read(nfc_dev);
|
||||
if (ret <= 0) {
|
||||
nfc_dev->nfc_disable_intr(nfc_dev);
|
||||
nfc_dev->cold_reset.rsp_pending = false;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = read_cold_reset_rsp(nfc_dev, NULL);
|
||||
nfc_dev->cold_reset.rsp_pending = false;
|
||||
if (ret < 0) {
|
||||
pr_err("%s rsp read err\n", __func__);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Enable intr as it is disabled when NFC is in disable
|
||||
* state
|
||||
*/
|
||||
nfc_dev->nfc_enable_intr(nfc_dev);
|
||||
|
||||
wait_event_interruptible(
|
||||
nfc_dev->cold_reset.read_wq,
|
||||
!nfc_dev->cold_reset.rsp_pending);
|
||||
}
|
||||
|
||||
nfc_dev->nfc_disable_intr(nfc_dev);
|
||||
}
|
||||
|
||||
if (nfc_dev->cold_reset.arg->sub_cmd == ESE_COLD_RESET_PROTECT_EN) {
|
||||
nfc_dev->cold_reset.is_crp_en = true;
|
||||
nfc_dev->cold_reset.last_src_ese_prot =
|
||||
nfc_dev->cold_reset.arg->src;
|
||||
} else if (nfc_dev->cold_reset.arg->sub_cmd ==
|
||||
ESE_COLD_RESET_PROTECT_DIS) {
|
||||
nfc_dev->cold_reset.is_crp_en = false;
|
||||
nfc_dev->cold_reset.last_src_ese_prot =
|
||||
ESE_COLD_RESET_ORIGIN_NONE;
|
||||
} else
|
||||
pr_debug("ese cmd is %d\n", nfc_dev->cold_reset.arg->sub_cmd);
|
||||
|
||||
ret = nfc_dev->cold_reset.status;
|
||||
err:
|
||||
kfree(nfc_dev->cold_reset.cmd_buf);
|
||||
kfree(nfc_dev->cold_reset.arg);
|
||||
nfc_dev->cold_reset.arg = NULL;
|
||||
nfc_dev->cold_reset.cmd_buf = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
80
drivers/nfc/qti/ese_cold_reset.h
Normal file
80
drivers/nfc/qti/ese_cold_reset.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __ESE_COLD_RESET_H
|
||||
#define __ESE_COLD_RESET_H
|
||||
|
||||
#include <linux/nfcinfo.h>
|
||||
|
||||
#define MAX_BUFF_SIZE 264
|
||||
|
||||
/* ESE_COLD_RESET MACROS */
|
||||
#define COLD_RESET_CMD_LEN 3
|
||||
#define COLD_RESET_RSP_LEN 4
|
||||
#define COLD_RESET_PROT_CMD_LEN 4
|
||||
#define COLD_RESET_PROT_RSP_LEN 4
|
||||
#define PROP_NCI_CMD_GID 0x2F
|
||||
#define COLD_RESET_CMD_PL_LEN 0x00
|
||||
#define COLD_RESET_PROT_CMD_PL_LEN 0x01
|
||||
#define PROP_NCI_RSP_GID 0x4F
|
||||
#define COLD_RESET_OID 0x1E
|
||||
#define COLD_RESET_PROT_OID 0x1F
|
||||
|
||||
#define ESE_COLD_RESET _IOWR(NFCC_MAGIC, 0x08, struct ese_ioctl_arg)
|
||||
|
||||
enum ese_ioctl_arg_type {
|
||||
ESE_ARG_TYPE_COLD_RESET = 0,
|
||||
};
|
||||
|
||||
/* ESE_COLD_RESET ioctl origin, max 4 are supported */
|
||||
enum ese_cold_reset_origin {
|
||||
ESE_COLD_RESET_ORIGIN_ESE = 0,
|
||||
ESE_COLD_RESET_ORIGIN_NFC,
|
||||
ESE_COLD_RESET_ORIGIN_NONE = 0xFF,
|
||||
};
|
||||
|
||||
/* ESE_COLD_RESET ioctl sub commands, max 8 are supported */
|
||||
enum ese_cold_reset_sub_cmd {
|
||||
ESE_COLD_RESET_DO = 0,
|
||||
ESE_COLD_RESET_PROTECT_EN,
|
||||
ESE_COLD_RESET_PROTECT_DIS,
|
||||
};
|
||||
|
||||
/* Data passed in buf of ese cold reset ioctl */
|
||||
struct ese_cold_reset_arg {
|
||||
__u8 src;
|
||||
__u8 sub_cmd;
|
||||
__u16 rfu;
|
||||
};
|
||||
|
||||
/* Argument buffer passed to ese ioctl */
|
||||
struct ese_ioctl_arg {
|
||||
__u64 buf;
|
||||
__u32 buf_size;
|
||||
__u8 type;
|
||||
};
|
||||
|
||||
/* Features specific Parameters */
|
||||
struct cold_reset {
|
||||
wait_queue_head_t read_wq;
|
||||
char *cmd_buf;
|
||||
struct ese_cold_reset_arg *arg;
|
||||
uint16_t cmd_len;
|
||||
uint16_t rsp_len;
|
||||
/* Source of last ese protection command */
|
||||
uint8_t last_src_ese_prot;
|
||||
uint8_t status;
|
||||
/* Is cold reset protection enabled */
|
||||
bool is_crp_en;
|
||||
bool rsp_pending;
|
||||
/* Is NFC enabled from UI */
|
||||
bool is_nfc_enabled;
|
||||
};
|
||||
|
||||
struct nfc_dev;
|
||||
int ese_cold_reset_ioctl(struct nfc_dev *nfc_dev, unsigned long arg);
|
||||
int read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header);
|
||||
|
||||
#endif
|
@ -8,7 +8,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include "nfc_common.h"
|
||||
|
||||
|
||||
int nfc_parse_dt(struct device *dev, struct platform_gpio *nfc_gpio,
|
||||
struct platform_ldo *ldo, uint8_t interface)
|
||||
{
|
||||
@ -304,109 +303,16 @@ int nfc_misc_probe(struct nfc_dev *nfc_dev,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static int send_cold_reset_cmd(struct nfc_dev *nfc_dev)
|
||||
{
|
||||
int ret = 0;
|
||||
char *cold_reset_cmd = NULL;
|
||||
|
||||
cold_reset_cmd = kzalloc(COLD_RESET_CMD_LEN, GFP_DMA | GFP_KERNEL);
|
||||
if (!cold_reset_cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
if (gpio_get_value(nfc_dev->gpio.dwl_req)) {
|
||||
pr_err("FW download in-progress\n");
|
||||
ret = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
if (!gpio_get_value(nfc_dev->gpio.ven)) {
|
||||
pr_err("VEN LOW - NFCC powered off\n");
|
||||
ret = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
cold_reset_cmd[0] = COLD_RESET_CMD_GID;
|
||||
cold_reset_cmd[1] = COLD_RESET_OID;
|
||||
cold_reset_cmd[2] = COLD_RESET_CMD_PAYLOAD_LEN;
|
||||
|
||||
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",
|
||||
__func__, ret);
|
||||
|
||||
error:
|
||||
kfree(cold_reset_cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void read_cold_reset_rsp(struct nfc_dev *nfc_dev, char *header)
|
||||
{
|
||||
int ret = -1;
|
||||
char *cold_reset_rsp = NULL;
|
||||
struct cold_reset *cold_reset = &nfc_dev->cold_reset;
|
||||
|
||||
cold_reset_rsp = kzalloc(COLD_RESET_RSP_LEN, GFP_DMA | GFP_KERNEL);
|
||||
if (!cold_reset_rsp)
|
||||
return;
|
||||
|
||||
/*
|
||||
* read header also if NFC is disabled
|
||||
* for enable case, will be taken care by nfc read thread
|
||||
*/
|
||||
if ((!cold_reset->is_nfc_enabled) &&
|
||||
(nfc_dev->interface == PLATFORM_IF_I2C)) {
|
||||
|
||||
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",
|
||||
__func__);
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
|
||||
/* 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",
|
||||
__func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if ((NCI_HDR_LEN + cold_reset_rsp[2]) > COLD_RESET_RSP_LEN) {
|
||||
pr_err("%s: - invalid response for cold_reset\n", __func__);
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C)
|
||||
ret = nfc_dev->nfc_read(nfc_dev,
|
||||
&cold_reset_rsp[NCI_PAYLOAD_IDX],
|
||||
cold_reset_rsp[2]);
|
||||
else
|
||||
ret = nfc_dev->i3c_dev.nfc_read_direct(nfc_dev,
|
||||
&cold_reset_rsp[NCI_PAYLOAD_IDX],
|
||||
cold_reset_rsp[2]);
|
||||
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: failure to read cold reset rsp payload\n",
|
||||
__func__);
|
||||
goto error;
|
||||
}
|
||||
cold_reset->status = cold_reset_rsp[NCI_PAYLOAD_IDX];
|
||||
|
||||
error:
|
||||
kfree(cold_reset_rsp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Power management of the eSE
|
||||
@ -442,57 +348,6 @@ int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg)
|
||||
pr_debug("keep ven high as NFC is enabled\n");
|
||||
}
|
||||
nfc_dev->is_ese_session_active = false;
|
||||
} else if (arg == ESE_COLD_RESET) {
|
||||
|
||||
// set default value for status as failure
|
||||
nfc_dev->cold_reset.status = -EIO;
|
||||
|
||||
ret = send_cold_reset_cmd(nfc_dev);
|
||||
if (ret <= 0) {
|
||||
pr_err("failed to send cold reset command\n");
|
||||
return nfc_dev->cold_reset.status;
|
||||
}
|
||||
|
||||
nfc_dev->cold_reset.rsp_pending = true;
|
||||
|
||||
// check if NFC is enabled
|
||||
if (nfc_dev->cold_reset.is_nfc_enabled) {
|
||||
|
||||
/*
|
||||
* nfc_read thread will initiate cold reset response
|
||||
* and it will signal for data available
|
||||
*/
|
||||
wait_event_interruptible(nfc_dev->cold_reset.read_wq,
|
||||
!nfc_dev->cold_reset.rsp_pending);
|
||||
|
||||
} else {
|
||||
|
||||
// Read data as NFC thread is not active
|
||||
|
||||
nfc_dev->nfc_enable_intr(nfc_dev);
|
||||
|
||||
if (nfc_dev->interface == PLATFORM_IF_I2C) {
|
||||
ret = wait_event_interruptible_timeout(
|
||||
nfc_dev->read_wq,
|
||||
!nfc_dev->i2c_dev.irq_enabled,
|
||||
msecs_to_jiffies(MAX_IRQ_WAIT_TIME));
|
||||
if (ret <= 0) {
|
||||
nfc_dev->nfc_disable_intr(nfc_dev);
|
||||
nfc_dev->cold_reset.rsp_pending = false;
|
||||
return nfc_dev->cold_reset.status;
|
||||
}
|
||||
read_cold_reset_rsp(nfc_dev, NULL);
|
||||
nfc_dev->cold_reset.rsp_pending = false;
|
||||
} else {
|
||||
wait_event_interruptible(
|
||||
nfc_dev->cold_reset.read_wq,
|
||||
!nfc_dev->cold_reset.rsp_pending);
|
||||
nfc_dev->nfc_disable_intr(nfc_dev);
|
||||
}
|
||||
}
|
||||
|
||||
ret = nfc_dev->cold_reset.status;
|
||||
|
||||
} else if (arg == ESE_POWER_STATE) {
|
||||
// eSE power state
|
||||
ret = gpio_get_value(nfc_dev->gpio.ven);
|
||||
@ -673,8 +528,13 @@ long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)
|
||||
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;
|
||||
default:
|
||||
pr_err("%s bad cmd %lu\n", __func__, arg);
|
||||
pr_err("%s Unsupported ioctl 0x%x, arg %lu\n",
|
||||
__func__, cmd, arg);
|
||||
ret = -ENOIOCTLCMD;
|
||||
}
|
||||
return ret;
|
||||
@ -740,7 +600,7 @@ int nfc_dev_close(struct inode *inode, struct file *filp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_data_available_for_read(struct nfc_dev *nfc_dev)
|
||||
int is_nfc_data_available_for_read(struct nfc_dev *nfc_dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -843,7 +703,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);
|
||||
ret = is_nfc_data_available_for_read(nfc_dev);
|
||||
if (ret <= 0) {
|
||||
nfc_dev->nfc_disable_intr(nfc_dev);
|
||||
pr_err("%s: - error waiting for get version rsp ret %d\n",
|
||||
@ -875,7 +735,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);
|
||||
ret = is_nfc_data_available_for_read(nfc_dev);
|
||||
if (ret <= 0) {
|
||||
nfc_dev->nfc_disable_intr(nfc_dev);
|
||||
pr_err("%s: - error waiting for core reset rsp ret %d\n",
|
||||
@ -894,7 +754,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);
|
||||
ret = is_nfc_data_available_for_read(nfc_dev);
|
||||
if (ret <= 0) {
|
||||
pr_err("%s: - error waiting for core reset ntf ret %d\n",
|
||||
__func__, ret);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/ipc_logging.h>
|
||||
#include "nfc_i2c_drv.h"
|
||||
#include "nfc_i3c_drv.h"
|
||||
#include "ese_cold_reset.h"
|
||||
|
||||
// Max device count for this driver
|
||||
#define DEV_COUNT 1
|
||||
@ -38,9 +39,10 @@
|
||||
#define NFC_CHAR_DEV_NAME "nq-nci"
|
||||
|
||||
// HDR length of NCI packet
|
||||
#define NCI_HDR_LEN 3
|
||||
#define NCI_HDR_LEN 3
|
||||
#define NCI_PAYLOAD_IDX 3
|
||||
#define NCI_PAYLOAD_LEN_IDX 2
|
||||
#define NCI_RSP_PKT_TYPE (0x40)
|
||||
|
||||
#define NCI_RESET_CMD_LEN (4)
|
||||
#define NCI_RESET_RSP_LEN (4)
|
||||
@ -54,13 +56,6 @@
|
||||
#define NFC_ROM_VERSION_OFF (2)
|
||||
#define NFC_FW_MAJOR_OFF (1)
|
||||
|
||||
#define COLD_RESET_CMD_LEN 3
|
||||
#define COLD_RESET_RSP_LEN 4
|
||||
#define COLD_RESET_CMD_GID 0x2F
|
||||
#define COLD_RESET_CMD_PAYLOAD_LEN 0x00
|
||||
#define COLD_RESET_RSP_GID 0x4F
|
||||
#define COLD_RESET_OID 0x1E
|
||||
|
||||
#define MAX_NCI_PAYLOAD_LEN (255)
|
||||
/*
|
||||
* From MW 11.04 buffer size increased to support
|
||||
@ -124,8 +119,6 @@ enum ese_ioctl_request {
|
||||
ESE_POWER_ON = 0,
|
||||
/* eSE POWER OFF */
|
||||
ESE_POWER_OFF,
|
||||
/* eSE COLD RESET */
|
||||
ESE_COLD_RESET,
|
||||
/* eSE POWER STATE */
|
||||
ESE_POWER_STATE
|
||||
};
|
||||
@ -201,14 +194,6 @@ struct platform_ldo {
|
||||
int max_current;
|
||||
};
|
||||
|
||||
//Features specific Parameters
|
||||
struct cold_reset {
|
||||
wait_queue_head_t read_wq;
|
||||
bool rsp_pending;
|
||||
uint8_t status;
|
||||
/* Is NFC enabled from UI */
|
||||
bool is_nfc_enabled;
|
||||
};
|
||||
|
||||
/* Device specific structure */
|
||||
struct nfc_dev {
|
||||
@ -261,11 +246,11 @@ int nfc_misc_probe(struct nfc_dev *nfc_dev,
|
||||
char *devname, char *classname);
|
||||
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);
|
||||
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);
|
||||
|
||||
#endif //_NFC_COMMON_H_
|
||||
|
@ -196,9 +196,9 @@ ssize_t nfc_i2c_dev_read(struct file *filp, char __user *buf,
|
||||
* NFC HAL process shouldn't receive this data as
|
||||
* command was sent by SPI driver
|
||||
*/
|
||||
if (nfc_dev->cold_reset.rsp_pending
|
||||
&& (tmp[0] == COLD_RESET_RSP_GID)
|
||||
&& (tmp[1] == COLD_RESET_OID)) {
|
||||
if (nfc_dev->cold_reset.rsp_pending && nfc_dev->cold_reset.cmd_buf
|
||||
&& (tmp[0] == PROP_NCI_RSP_GID)
|
||||
&& (tmp[1] == nfc_dev->cold_reset.cmd_buf[1])) {
|
||||
read_cold_reset_rsp(nfc_dev, tmp);
|
||||
nfc_dev->cold_reset.rsp_pending = false;
|
||||
wake_up_interruptible(&nfc_dev->cold_reset.read_wq);
|
||||
|
@ -395,9 +395,9 @@ static void i3c_workqueue_handler(struct work_struct *work)
|
||||
* NFC HAL process shouldn't receive this data as
|
||||
* command was sent by SPI driver
|
||||
*/
|
||||
if (nfc_dev->cold_reset.rsp_pending
|
||||
&& (tmp[0] == COLD_RESET_RSP_GID)
|
||||
&& (tmp[1] == COLD_RESET_OID)) {
|
||||
if (nfc_dev->cold_reset.rsp_pending && nfc_dev->cold_reset.cmd_buf
|
||||
&& (tmp[0] == PROP_NCI_RSP_GID)
|
||||
&& (tmp[1] == nfc_dev->cold_reset.cmd_buf[1])) {
|
||||
read_cold_reset_rsp(nfc_dev, tmp);
|
||||
nfc_dev->cold_reset.rsp_pending = false;
|
||||
wake_up_interruptible(&nfc_dev->cold_reset.read_wq);
|
||||
|
Loading…
Reference in New Issue
Block a user