Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e66e8265 authored by Nakul Kadannavar's avatar Nakul Kadannavar
Browse files

NFC: Read core reset notification



After chip has cold booted wait maximum of 50ms to
receive core reset notification.
Implement kernel ioctl to read whether core reset
notification has recieved before timeout.
Cold boot implementation of NFCC had a bug,
GPIO disable needs to be held high for atleast
100ms before switching it to low for a clean cold
boot.

CRs-Fixed: 729456
Change-Id: I11a213d68ff1b44f433706e104bbaeac406bd5d6
Signed-off-by: default avatarNakul Kadannavar <nakulk@codeaurora.org>
parent fe65c3f4
Loading
Loading
Loading
Loading
+38 −5
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ MODULE_DEVICE_TABLE(of, msm_match_table);
#define MAX_QCA_REG				(116)
/* will timeout in approx. 100ms as 10us steps */
#define NFC_RF_CLK_FREQ			(19200000)
#define NTF_TIMEOUT				(10)
#define NTF_TIMEOUT				(25)
#define	CORE_RESET_RSP_GID		(0x60)
#define	CORE_RESET_OID			(0x00)
#define CORE_RST_NTF_LENGTH		(0x02)
@@ -95,6 +95,7 @@ struct qca199x_dev {
	unsigned int		clk_src_gpio;
	const	char		*clk_src_name;
	struct	clk		*s_clk;
	unsigned int		core_reset_ntf;
	bool			clk_run;
	struct work_struct	msm_clock_controll_work;
	struct workqueue_struct *my_wq;
@@ -113,7 +114,8 @@ static struct notifier_block nfcc_notifier = {
};
static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
static int nfcc_hw_check(struct i2c_client *client, unsigned short curr_addr);
static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr);
static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr,
				struct qca199x_dev *qca199x_dev);
static int qca199x_clock_select(struct qca199x_dev *qca199x_dev);
static int qca199x_clock_deselect(struct qca199x_dev *qca199x_dev);

@@ -617,12 +619,13 @@ int nfc_ioctl_power_states(struct file *filp, unsigned int cmd,
		dev_dbg(&qca199x_dev->client->dev, "gpio_set_value enable: %s: info: %p\n",
			__func__, qca199x_dev);
		gpio_set_value(qca199x_dev->dis_gpio, 1);
		usleep(1000);
		/*nfcc needs atleast 100ms for the chip to power cycle*/
		msleep(100);
	} else if (arg == 2) {
		mutex_lock(&qca199x_dev->read_mutex);
		dev_dbg(&qca199x_dev->client->dev, "before nfcc_initialise: %s: info: %p\n",
			__func__, qca199x_dev);
		r = nfcc_initialise(qca199x_dev->client, 0xE);
		r = nfcc_initialise(qca199x_dev->client, 0xE, qca199x_dev);
		dev_dbg(&qca199x_dev->client->dev, "after nfcc_initialise: %s: info: %p\n",
			__func__, qca199x_dev);
		/* Also reset first NCI write */
@@ -951,6 +954,26 @@ static long nfc_compat_ioctl(struct file *pfile, unsigned int cmd,
}
#endif

/*
 * Inside nfc_ioctl_core_reset_ntf
 *
 * @brief   nfc_ioctl_core_reset_ntf
 *
 * Allows callers to determine if a CORE_RESET_NTF has arrived
 *
 * Returns the value of variable core_reset_ntf
 *
 */
int nfc_ioctl_core_reset_ntf(struct file *filp, unsigned int cmd,
				unsigned long arg)
{
	struct qca199x_dev *qca199x_dev = filp->private_data;
	dev_dbg(&qca199x_dev->client->dev,
		"nfc_ioctl_core_reset_ntf: returning = %d\n",
		qca199x_dev->core_reset_ntf);
	return qca199x_dev->core_reset_ntf;
}

static long nfc_ioctl(struct file *pfile, unsigned int cmd,
			unsigned long arg)
{
@@ -981,6 +1004,9 @@ static long nfc_ioctl(struct file *pfile, unsigned int cmd,
			"nfc_ioctl : FAILED TO READ EFUSE TYPE\n");
		}
		break;
	case NFCC_INITIAL_CORE_RESET_NTF:
		r = nfc_ioctl_core_reset_ntf(pfile, cmd, arg);
		break;
	default:
		r = -ENOIOCTLCMD;
	}
@@ -1068,7 +1094,8 @@ err_presence_check:
	return r;
}
/* Initialise qca199x_ NFC controller hardware */
static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr)
static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr,
				struct qca199x_dev *qca199x_dev)
{
	int r = 0;
	unsigned char raw_1p8_CONTROL_011[]	= {0x11, XTAL_CLOCK};
@@ -1087,6 +1114,7 @@ static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr)
	int ret = 0;

	client->addr = curr_addr;
	qca199x_dev->core_reset_ntf = DEFAULT_INITIAL_CORE_RESET_NTF;
	r = i2c_master_send(client, &buf, 1);
	if (r < 0)
		goto err_init;
@@ -1210,6 +1238,11 @@ static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr)
		}
		time_taken++;
	} while (!core_reset_completed);
	if (time_taken == NTF_TIMEOUT)
		qca199x_dev->core_reset_ntf = TIMEDOUT_INITIAL_CORE_RESET_NTF;
	else
		qca199x_dev->core_reset_ntf = ARRIVED_INITIAL_CORE_RESET_NTF;

	r = 0;
	return r;
err_init:
+6 −0
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@ struct devicemode {
#define SET_EMULATOR_TEST_POINT		_IOW(0xE9, 0x05, unsigned int)
#define NFCC_VERSION				_IOW(0xE9, 0x08, unsigned int)
#define NFC_GET_EFUSE				_IOW(0xE9, 0x09, unsigned int)
#define NFCC_INITIAL_CORE_RESET_NTF		_IOW(0xE9, 0x10, unsigned int)

#define NFC_MAX_I2C_TRANSFER	(0x0400)
#define NFC_MSG_MAX_SIZE	(0x21)
@@ -196,6 +197,11 @@ enum nfcc_irq {
	NFCC_INT,
};

enum nfcc_initial_core_reset_ntf {
	TIMEDOUT_INITIAL_CORE_RESET_NTF = 0, /* 0*/
	ARRIVED_INITIAL_CORE_RESET_NTF, /* 1 */
	DEFAULT_INITIAL_CORE_RESET_NTF, /*2*/
};

struct nfc_info {
	struct	miscdevice			miscdev;