blob: cc90a36b1971354fbc1cb4602b92f958262890af [file] [log] [blame]
Tapas Deyb5e69602019-05-07 11:33:00 +05301/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
Gaurav Singhalc53bc292017-02-16 16:35:39 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/fs.h>
16#include <linux/reboot.h>
17#include <linux/slab.h>
18#include <linux/irq.h>
19#include <linux/delay.h>
20#include <linux/interrupt.h>
21#include <linux/gpio.h>
22#include <linux/spinlock.h>
23#include <linux/of_gpio.h>
24#include <linux/of_device.h>
25#include <linux/uaccess.h>
26#include "nq-nci.h"
27#include <linux/clk.h>
28#ifdef CONFIG_COMPAT
29#include <linux/compat.h>
30#endif
31
michaellin1d8583b2020-04-21 18:39:32 +080032#define PFX "[NFC][NQ]"
33// 20181116 Michael Lin - Introduce firmware download fail recovery mechanism
34/* To avoid from recovery fail and then NFC always in download mode */
35#define NFC_FW_DOWNLOAD_MODE
36
Gaurav Singhalc53bc292017-02-16 16:35:39 +053037struct nqx_platform_data {
38 unsigned int irq_gpio;
39 unsigned int en_gpio;
40 unsigned int clkreq_gpio;
41 unsigned int firm_gpio;
42 unsigned int ese_gpio;
43 const char *clk_src_name;
Gaurav Singhal71661102018-01-30 16:34:37 +053044 /* NFC_CLK pin voting state */
45 bool clk_pin_voting;
Gaurav Singhalc53bc292017-02-16 16:35:39 +053046};
47
48static const struct of_device_id msm_match_table[] = {
49 {.compatible = "qcom,nq-nci"},
50 {}
51};
52
53MODULE_DEVICE_TABLE(of, msm_match_table);
54
55#define MAX_BUFFER_SIZE (320)
56#define WAKEUP_SRC_TIMEOUT (2000)
57#define MAX_RETRY_COUNT 3
58
59struct nqx_dev {
60 wait_queue_head_t read_wq;
61 struct mutex read_mutex;
62 struct i2c_client *client;
63 struct miscdevice nqx_device;
64 union nqx_uinfo nqx_info;
65 /* NFC GPIO variables */
66 unsigned int irq_gpio;
67 unsigned int en_gpio;
68 unsigned int firm_gpio;
69 unsigned int clkreq_gpio;
70 unsigned int ese_gpio;
71 /* NFC VEN pin state powered by Nfc */
72 bool nfc_ven_enabled;
73 /* NFC_IRQ state */
74 bool irq_enabled;
75 /* NFC_IRQ wake-up state */
76 bool irq_wake_up;
77 spinlock_t irq_enabled_lock;
78 unsigned int count_irq;
79 /* Initial CORE RESET notification */
80 unsigned int core_reset_ntf;
81 /* CLK control */
82 bool clk_run;
83 struct clk *s_clk;
84 /* read buffer*/
85 size_t kbuflen;
86 u8 *kbuf;
87 struct nqx_platform_data *pdata;
88};
89
90static int nfcc_reboot(struct notifier_block *notifier, unsigned long val,
91 void *v);
92/*clock enable function*/
93static int nqx_clock_select(struct nqx_dev *nqx_dev);
94/*clock disable function*/
95static int nqx_clock_deselect(struct nqx_dev *nqx_dev);
96static struct notifier_block nfcc_notifier = {
97 .notifier_call = nfcc_reboot,
98 .next = NULL,
99 .priority = 0
100};
101
102unsigned int disable_ctrl;
103
104static void nqx_init_stat(struct nqx_dev *nqx_dev)
105{
106 nqx_dev->count_irq = 0;
107}
108
109static void nqx_disable_irq(struct nqx_dev *nqx_dev)
110{
111 unsigned long flags;
112
113 spin_lock_irqsave(&nqx_dev->irq_enabled_lock, flags);
114 if (nqx_dev->irq_enabled) {
115 disable_irq_nosync(nqx_dev->client->irq);
116 nqx_dev->irq_enabled = false;
117 }
118 spin_unlock_irqrestore(&nqx_dev->irq_enabled_lock, flags);
119}
120
121/**
122 * nqx_enable_irq()
123 *
124 * Check if interrupt is enabled or not
125 * and enable interrupt
126 *
127 * Return: void
128 */
129static void nqx_enable_irq(struct nqx_dev *nqx_dev)
130{
131 unsigned long flags;
132
133 spin_lock_irqsave(&nqx_dev->irq_enabled_lock, flags);
134 if (!nqx_dev->irq_enabled) {
135 nqx_dev->irq_enabled = true;
136 enable_irq(nqx_dev->client->irq);
137 }
138 spin_unlock_irqrestore(&nqx_dev->irq_enabled_lock, flags);
139}
140
141static irqreturn_t nqx_dev_irq_handler(int irq, void *dev_id)
142{
143 struct nqx_dev *nqx_dev = dev_id;
144 unsigned long flags;
145
146 if (device_may_wakeup(&nqx_dev->client->dev))
147 pm_wakeup_event(&nqx_dev->client->dev, WAKEUP_SRC_TIMEOUT);
148
149 nqx_disable_irq(nqx_dev);
150 spin_lock_irqsave(&nqx_dev->irq_enabled_lock, flags);
151 nqx_dev->count_irq++;
152 spin_unlock_irqrestore(&nqx_dev->irq_enabled_lock, flags);
153 wake_up(&nqx_dev->read_wq);
154
155 return IRQ_HANDLED;
156}
157
Bhuvan Varshney8e2ca882019-09-09 19:20:37 +0530158static int is_data_available_for_read(struct nqx_dev *nqx_dev)
159{
160 int ret;
161
162 nqx_enable_irq(nqx_dev);
163 ret = wait_event_interruptible(nqx_dev->read_wq, !nqx_dev->irq_enabled);
164 return ret;
165}
166
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530167static ssize_t nfc_read(struct file *filp, char __user *buf,
168 size_t count, loff_t *offset)
169{
170 struct nqx_dev *nqx_dev = filp->private_data;
171 unsigned char *tmp = NULL;
172 int ret;
173 int irq_gpio_val = 0;
174
175 if (!nqx_dev) {
176 ret = -ENODEV;
177 goto out;
178 }
179
180 if (count > nqx_dev->kbuflen)
181 count = nqx_dev->kbuflen;
182
183 dev_dbg(&nqx_dev->client->dev, "%s : reading %zu bytes.\n",
184 __func__, count);
185
186 mutex_lock(&nqx_dev->read_mutex);
187
188 irq_gpio_val = gpio_get_value(nqx_dev->irq_gpio);
189 if (irq_gpio_val == 0) {
190 if (filp->f_flags & O_NONBLOCK) {
191 dev_err(&nqx_dev->client->dev,
192 ":f_falg has O_NONBLOCK. EAGAIN\n");
193 ret = -EAGAIN;
194 goto err;
195 }
196 while (1) {
197 ret = 0;
198 if (!nqx_dev->irq_enabled) {
199 nqx_dev->irq_enabled = true;
200 enable_irq(nqx_dev->client->irq);
201 }
202 if (!gpio_get_value(nqx_dev->irq_gpio)) {
203 ret = wait_event_interruptible(nqx_dev->read_wq,
204 !nqx_dev->irq_enabled);
205 }
206 if (ret)
207 goto err;
208 nqx_disable_irq(nqx_dev);
209
210 if (gpio_get_value(nqx_dev->irq_gpio))
211 break;
212 dev_err_ratelimited(&nqx_dev->client->dev,
213 "gpio is low, no need to read data\n");
214 }
215 }
216
217 tmp = nqx_dev->kbuf;
218 if (!tmp) {
219 dev_err(&nqx_dev->client->dev,
220 "%s: device doesn't exist anymore\n", __func__);
221 ret = -ENODEV;
222 goto err;
223 }
224 memset(tmp, 0x00, count);
225
226 /* Read data */
227 ret = i2c_master_recv(nqx_dev->client, tmp, count);
228 if (ret < 0) {
229 dev_err(&nqx_dev->client->dev,
230 "%s: i2c_master_recv returned %d\n", __func__, ret);
231 goto err;
232 }
233 if (ret > count) {
234 dev_err(&nqx_dev->client->dev,
235 "%s: received too many bytes from i2c (%d)\n",
236 __func__, ret);
237 ret = -EIO;
238 goto err;
239 }
240#ifdef NFC_KERNEL_BU
241 dev_dbg(&nqx_dev->client->dev, "%s : NfcNciRx %x %x %x\n",
242 __func__, tmp[0], tmp[1], tmp[2]);
243#endif
244 if (copy_to_user(buf, tmp, ret)) {
245 dev_warn(&nqx_dev->client->dev,
246 "%s : failed to copy to user space\n", __func__);
247 ret = -EFAULT;
248 goto err;
249 }
250 mutex_unlock(&nqx_dev->read_mutex);
251 return ret;
252
253err:
254 mutex_unlock(&nqx_dev->read_mutex);
255out:
256 return ret;
257}
258
259static ssize_t nfc_write(struct file *filp, const char __user *buf,
260 size_t count, loff_t *offset)
261{
262 struct nqx_dev *nqx_dev = filp->private_data;
263 char *tmp = NULL;
264 int ret = 0;
265
266 if (!nqx_dev) {
267 ret = -ENODEV;
268 goto out;
269 }
270 if (count > nqx_dev->kbuflen) {
271 dev_err(&nqx_dev->client->dev, "%s: out of memory\n",
272 __func__);
273 ret = -ENOMEM;
274 goto out;
275 }
276
277 tmp = memdup_user(buf, count);
278 if (IS_ERR(tmp)) {
279 dev_err(&nqx_dev->client->dev, "%s: memdup_user failed\n",
280 __func__);
281 ret = PTR_ERR(tmp);
282 goto out;
283 }
284
285 ret = i2c_master_send(nqx_dev->client, tmp, count);
286 if (ret != count) {
287 dev_err(&nqx_dev->client->dev,
288 "%s: failed to write %d\n", __func__, ret);
289 ret = -EIO;
290 goto out_free;
291 }
292#ifdef NFC_KERNEL_BU
293 dev_dbg(&nqx_dev->client->dev,
294 "%s : i2c-%d: NfcNciTx %x %x %x\n",
295 __func__, iminor(file_inode(filp)),
296 tmp[0], tmp[1], tmp[2]);
297#endif
298 usleep_range(1000, 1100);
299out_free:
300 kfree(tmp);
301out:
302 return ret;
303}
304
305/**
306 * nqx_standby_write()
307 * @buf: pointer to data buffer
308 * @len: # of bytes need to transfer
309 *
310 * write data buffer over I2C and retry
311 * if NFCC is in stand by mode
312 *
313 * Return: # of bytes written or -ve value in case of error
314 */
315static int nqx_standby_write(struct nqx_dev *nqx_dev,
316 const unsigned char *buf, size_t len)
317{
318 int ret = -EINVAL;
319 int retry_cnt;
320
321 for (retry_cnt = 1; retry_cnt <= MAX_RETRY_COUNT; retry_cnt++) {
322 ret = i2c_master_send(nqx_dev->client, buf, len);
323 if (ret < 0) {
324 dev_err(&nqx_dev->client->dev,
325 "%s: write failed, Maybe in Standby Mode - Retry(%d)\n",
326 __func__, retry_cnt);
327 usleep_range(1000, 1100);
328 } else if (ret == len)
329 break;
330 }
331 return ret;
332}
333
334/*
335 * Power management of the eSE
336 * NFC & eSE ON : NFC_EN high and eSE_pwr_req high.
337 * NFC OFF & eSE ON : NFC_EN high and eSE_pwr_req high.
338 * NFC OFF & eSE OFF : NFC_EN low and eSE_pwr_req low.
339 */
340static int nqx_ese_pwr(struct nqx_dev *nqx_dev, unsigned long int arg)
341{
342 int r = -1;
343 const unsigned char svdd_off_cmd_warn[] = {0x2F, 0x31, 0x01, 0x01};
344 const unsigned char svdd_off_cmd_done[] = {0x2F, 0x31, 0x01, 0x00};
345
346 if (!gpio_is_valid(nqx_dev->ese_gpio)) {
347 dev_err(&nqx_dev->client->dev,
348 "%s: ese_gpio is not valid\n", __func__);
349 return -EINVAL;
350 }
351
352 if (arg == 0) {
353 /*
354 * We want to power on the eSE and to do so we need the
355 * eSE_pwr_req pin and the NFC_EN pin to be high
356 */
357 if (gpio_get_value(nqx_dev->ese_gpio)) {
358 dev_dbg(&nqx_dev->client->dev, "ese_gpio is already high\n");
359 r = 0;
360 } else {
361 /**
362 * Let's store the NFC_EN pin state
363 * only if the eSE is not yet on
364 */
365 nqx_dev->nfc_ven_enabled =
366 gpio_get_value(nqx_dev->en_gpio);
367 if (!nqx_dev->nfc_ven_enabled) {
368 gpio_set_value(nqx_dev->en_gpio, 1);
369 /* hardware dependent delay */
370 usleep_range(1000, 1100);
371 }
372 gpio_set_value(nqx_dev->ese_gpio, 1);
Gaurav Singhalcfb64802017-08-30 17:03:58 +0530373 usleep_range(1000, 1100);
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530374 if (gpio_get_value(nqx_dev->ese_gpio)) {
375 dev_dbg(&nqx_dev->client->dev, "ese_gpio is enabled\n");
376 r = 0;
377 }
378 }
379 } else if (arg == 1) {
380 if (nqx_dev->nfc_ven_enabled &&
381 ((nqx_dev->nqx_info.info.chip_type == NFCC_NQ_220) ||
382 (nqx_dev->nqx_info.info.chip_type == NFCC_PN66T))) {
383 /**
384 * Let's inform the CLF we're
385 * powering off the eSE
386 */
387 r = nqx_standby_write(nqx_dev, svdd_off_cmd_warn,
388 sizeof(svdd_off_cmd_warn));
389 if (r < 0) {
390 dev_err(&nqx_dev->client->dev,
391 "%s: write failed after max retry\n",
392 __func__);
393 return -ENXIO;
394 }
395 dev_dbg(&nqx_dev->client->dev,
396 "%s: svdd_off_cmd_warn sent\n", __func__);
397
398 /* let's power down the eSE */
399 gpio_set_value(nqx_dev->ese_gpio, 0);
400 dev_dbg(&nqx_dev->client->dev,
401 "%s: nqx_dev->ese_gpio set to 0\n", __func__);
402
403 /**
404 * Time needed for the SVDD capacitor
405 * to get discharged
406 */
407 usleep_range(8000, 8100);
408
409 /* Let's inform the CLF the eSE is now off */
410 r = nqx_standby_write(nqx_dev, svdd_off_cmd_done,
411 sizeof(svdd_off_cmd_done));
412 if (r < 0) {
413 dev_err(&nqx_dev->client->dev,
414 "%s: write failed after max retry\n",
415 __func__);
416 return -ENXIO;
417 }
418 dev_dbg(&nqx_dev->client->dev,
419 "%s: svdd_off_cmd_done sent\n", __func__);
420 } else {
421 /**
422 * In case the NFC is off,
423 * there's no need to send the i2c commands
424 */
425 gpio_set_value(nqx_dev->ese_gpio, 0);
Gaurav Singhalcfb64802017-08-30 17:03:58 +0530426 usleep_range(1000, 1100);
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530427 }
428
429 if (!gpio_get_value(nqx_dev->ese_gpio)) {
430 dev_dbg(&nqx_dev->client->dev, "ese_gpio is disabled\n");
431 r = 0;
432 }
433
434 if (!nqx_dev->nfc_ven_enabled) {
435 /* hardware dependent delay */
436 usleep_range(1000, 1100);
437 dev_dbg(&nqx_dev->client->dev, "disabling en_gpio\n");
438 gpio_set_value(nqx_dev->en_gpio, 0);
439 }
440 } else if (arg == 3) {
441 r = gpio_get_value(nqx_dev->ese_gpio);
442 }
443 return r;
444}
445
446static int nfc_open(struct inode *inode, struct file *filp)
447{
448 int ret = 0;
449 struct nqx_dev *nqx_dev = container_of(filp->private_data,
450 struct nqx_dev, nqx_device);
451
452 filp->private_data = nqx_dev;
453 nqx_init_stat(nqx_dev);
454
455 dev_dbg(&nqx_dev->client->dev,
456 "%s: %d,%d\n", __func__, imajor(inode), iminor(inode));
457 return ret;
458}
459
460/*
461 * nfc_ioctl_power_states() - power control
462 * @filp: pointer to the file descriptor
463 * @arg: mode that we want to move to
464 *
465 * Device power control. Depending on the arg value, device moves to
466 * different states
467 * (arg = 0): NFC_ENABLE GPIO = 0, FW_DL GPIO = 0
468 * (arg = 1): NFC_ENABLE GPIO = 1, FW_DL GPIO = 0
469 * (arg = 2): FW_DL GPIO = 1
470 *
471 * Return: -ENOIOCTLCMD if arg is not supported, 0 in any other case
472 */
473int nfc_ioctl_power_states(struct file *filp, unsigned long arg)
474{
475 int r = 0;
476 struct nqx_dev *nqx_dev = filp->private_data;
477
478 if (arg == 0) {
479 /*
480 * We are attempting a hardware reset so let us disable
481 * interrupts to avoid spurious notifications to upper
482 * layers.
483 */
michaellin1d8583b2020-04-21 18:39:32 +0800484 //< 20181116 Michael Lin - Mask where firmware download fail recovery is used
485 #if !defined( NFC_FW_DOWNLOAD_MODE )
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530486 nqx_disable_irq(nqx_dev);
michaellin1d8583b2020-04-21 18:39:32 +0800487 #endif
488 //> 20181116 Michael Lin - Mask where firmware download fail recovery is used
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530489 dev_dbg(&nqx_dev->client->dev,
490 "gpio_set_value disable: %s: info: %p\n",
491 __func__, nqx_dev);
Gaurav Singhal165add72017-10-13 17:17:58 +0530492 if (gpio_is_valid(nqx_dev->firm_gpio)) {
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530493 gpio_set_value(nqx_dev->firm_gpio, 0);
Gaurav Singhal165add72017-10-13 17:17:58 +0530494 usleep_range(10000, 10100);
495 }
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530496
497 if (gpio_is_valid(nqx_dev->ese_gpio)) {
498 if (!gpio_get_value(nqx_dev->ese_gpio)) {
499 dev_dbg(&nqx_dev->client->dev, "disabling en_gpio\n");
500 gpio_set_value(nqx_dev->en_gpio, 0);
Gaurav Singhal165add72017-10-13 17:17:58 +0530501 usleep_range(10000, 10100);
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530502 } else {
503 dev_dbg(&nqx_dev->client->dev, "keeping en_gpio high\n");
504 }
505 } else {
506 dev_dbg(&nqx_dev->client->dev, "ese_gpio invalid, set en_gpio to low\n");
507 gpio_set_value(nqx_dev->en_gpio, 0);
Gaurav Singhal165add72017-10-13 17:17:58 +0530508 usleep_range(10000, 10100);
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530509 }
Gaurav Singhal71661102018-01-30 16:34:37 +0530510 if (nqx_dev->pdata->clk_pin_voting) {
511 r = nqx_clock_deselect(nqx_dev);
512 if (r < 0)
513 dev_err(&nqx_dev->client->dev, "unable to disable clock\n");
514 }
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530515 nqx_dev->nfc_ven_enabled = false;
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530516 } else if (arg == 1) {
517 nqx_enable_irq(nqx_dev);
518 dev_dbg(&nqx_dev->client->dev,
519 "gpio_set_value enable: %s: info: %p\n",
520 __func__, nqx_dev);
Gaurav Singhal165add72017-10-13 17:17:58 +0530521 if (gpio_is_valid(nqx_dev->firm_gpio)) {
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530522 gpio_set_value(nqx_dev->firm_gpio, 0);
Gaurav Singhal165add72017-10-13 17:17:58 +0530523 usleep_range(10000, 10100);
524 }
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530525 gpio_set_value(nqx_dev->en_gpio, 1);
Gaurav Singhal165add72017-10-13 17:17:58 +0530526 usleep_range(10000, 10100);
Gaurav Singhal71661102018-01-30 16:34:37 +0530527 if (nqx_dev->pdata->clk_pin_voting) {
528 r = nqx_clock_select(nqx_dev);
529 if (r < 0)
530 dev_err(&nqx_dev->client->dev, "unable to enable clock\n");
531 }
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530532 nqx_dev->nfc_ven_enabled = true;
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530533 } else if (arg == 2) {
534 /*
535 * We are switching to Dowload Mode, toggle the enable pin
536 * in order to set the NFCC in the new mode
537 */
538 if (gpio_is_valid(nqx_dev->ese_gpio)) {
539 if (gpio_get_value(nqx_dev->ese_gpio)) {
540 dev_err(&nqx_dev->client->dev,
541 "FW download forbidden while ese is on\n");
542 return -EBUSY; /* Device or resource busy */
543 }
544 }
michaellin1d8583b2020-04-21 18:39:32 +0800545 //< 20181116 Michael Lin - Add where firmware download fail recovery is used
546 #if defined( NFC_FW_DOWNLOAD_MODE )
547 /* Enable IRQ while upgrade FW. To avoid from recovery fail and then NFC always in download mode */
548 nqx_enable_irq( nqx_dev );
549 #endif
550 //< 20181116 Michael Lin - Add where firmware download fail recovery is used
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530551 gpio_set_value(nqx_dev->en_gpio, 1);
Gaurav Singhal165add72017-10-13 17:17:58 +0530552 usleep_range(10000, 10100);
553 if (gpio_is_valid(nqx_dev->firm_gpio)) {
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530554 gpio_set_value(nqx_dev->firm_gpio, 1);
Gaurav Singhal165add72017-10-13 17:17:58 +0530555 usleep_range(10000, 10100);
556 }
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530557 gpio_set_value(nqx_dev->en_gpio, 0);
Gaurav Singhal165add72017-10-13 17:17:58 +0530558 usleep_range(10000, 10100);
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530559 gpio_set_value(nqx_dev->en_gpio, 1);
Gaurav Singhal165add72017-10-13 17:17:58 +0530560 usleep_range(10000, 10100);
Bhuvan Varshneyae67c4e2018-11-23 15:15:27 +0530561 } else if (arg == 4) {
562 /*
563 * Setting firmware download gpio to HIGH for SN100U
564 * before FW download start
565 */
566 dev_dbg(&nqx_dev->client->dev, "SN100 fw gpio HIGH\n");
567 if (gpio_is_valid(nqx_dev->firm_gpio)) {
568 gpio_set_value(nqx_dev->firm_gpio, 1);
569 usleep_range(10000, 10100);
570 } else {
571 dev_err(&nqx_dev->client->dev,
572 "firm_gpio is invalid\n");
573 }
574 } else if (arg == 6) {
575 /*
576 * Setting firmware download gpio to LOW for SN100U
577 * FW download finished
578 */
579 dev_dbg(&nqx_dev->client->dev, "SN100 fw gpio LOW\n");
580 if (gpio_is_valid(nqx_dev->firm_gpio)) {
581 gpio_set_value(nqx_dev->firm_gpio, 0);
582 usleep_range(10000, 10100);
583 } else {
584 dev_err(&nqx_dev->client->dev,
585 "firm_gpio is invalid\n");
586 }
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530587 } else {
588 r = -ENOIOCTLCMD;
589 }
590
591 return r;
592}
593
594#ifdef CONFIG_COMPAT
595static long nfc_compat_ioctl(struct file *pfile, unsigned int cmd,
596 unsigned long arg)
597{
598 long r = 0;
599
600 arg = (compat_u64)arg;
601 switch (cmd) {
602 case NFC_SET_PWR:
603 nfc_ioctl_power_states(pfile, arg);
604 break;
605 case ESE_SET_PWR:
606 nqx_ese_pwr(pfile->private_data, arg);
607 break;
608 case ESE_GET_PWR:
609 nqx_ese_pwr(pfile->private_data, 3);
610 break;
611 case SET_RX_BLOCK:
612 break;
613 case SET_EMULATOR_TEST_POINT:
614 break;
615 default:
616 r = -ENOTTY;
617 }
618 return r;
619}
620#endif
621
622/*
623 * nfc_ioctl_core_reset_ntf()
624 * @filp: pointer to the file descriptor
625 *
626 * Allows callers to determine if a CORE_RESET_NTF has arrived
627 *
628 * Return: the value of variable core_reset_ntf
629 */
630int nfc_ioctl_core_reset_ntf(struct file *filp)
631{
632 struct nqx_dev *nqx_dev = filp->private_data;
633
634 dev_dbg(&nqx_dev->client->dev, "%s: returning = %d\n", __func__,
635 nqx_dev->core_reset_ntf);
636 return nqx_dev->core_reset_ntf;
637}
638
639/*
640 * Inside nfc_ioctl_nfcc_info
641 *
642 * @brief nfc_ioctl_nfcc_info
643 *
644 * Check the NQ Chipset and firmware version details
645 */
646unsigned int nfc_ioctl_nfcc_info(struct file *filp, unsigned long arg)
647{
648 unsigned int r = 0;
649 struct nqx_dev *nqx_dev = filp->private_data;
650
651 r = nqx_dev->nqx_info.i;
652 dev_dbg(&nqx_dev->client->dev,
653 "nqx nfc : nfc_ioctl_nfcc_info r = %d\n", r);
654
655 return r;
656}
657
658static long nfc_ioctl(struct file *pfile, unsigned int cmd,
659 unsigned long arg)
660{
661 int r = 0;
662
663 switch (cmd) {
664 case NFC_SET_PWR:
665 r = nfc_ioctl_power_states(pfile, arg);
666 break;
667 case ESE_SET_PWR:
668 r = nqx_ese_pwr(pfile->private_data, arg);
669 break;
670 case ESE_GET_PWR:
671 r = nqx_ese_pwr(pfile->private_data, 3);
672 break;
673 case SET_RX_BLOCK:
674 break;
675 case SET_EMULATOR_TEST_POINT:
676 break;
677 case NFCC_INITIAL_CORE_RESET_NTF:
678 r = nfc_ioctl_core_reset_ntf(pfile);
679 break;
680 case NFCC_GET_INFO:
681 r = nfc_ioctl_nfcc_info(pfile, arg);
682 break;
683 default:
684 r = -ENOIOCTLCMD;
685 }
686 return r;
687}
688
689static const struct file_operations nfc_dev_fops = {
690 .owner = THIS_MODULE,
691 .llseek = no_llseek,
692 .read = nfc_read,
693 .write = nfc_write,
694 .open = nfc_open,
695 .unlocked_ioctl = nfc_ioctl,
696#ifdef CONFIG_COMPAT
697 .compat_ioctl = nfc_compat_ioctl
698#endif
699};
700
701/* Check for availability of NQ_ NFC controller hardware */
702static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
703{
704 int ret = 0;
705
706 unsigned char raw_nci_reset_cmd[] = {0x20, 0x00, 0x01, 0x00};
707 unsigned char raw_nci_init_cmd[] = {0x20, 0x01, 0x00};
Tapas Deyb5e69602019-05-07 11:33:00 +0530708 unsigned char nci_get_version_cmd[] = {0x00, 0x04, 0xF1,
709 0x00, 0x00, 0x00, 0x6E, 0xEF};
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530710 unsigned char nci_init_rsp[28];
711 unsigned char nci_reset_rsp[6];
Tapas Deyb5e69602019-05-07 11:33:00 +0530712 unsigned char nci_get_version_rsp[12];
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530713 unsigned char init_rsp_len = 0;
714 unsigned int enable_gpio = nqx_dev->en_gpio;
Gaurav Singhal165add72017-10-13 17:17:58 +0530715
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530716 /* making sure that the NFCC starts in a clean state. */
717 gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
718 /* hardware dependent delay */
Gaurav Singhal165add72017-10-13 17:17:58 +0530719 usleep_range(10000, 10100);
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530720 gpio_set_value(enable_gpio, 1);/* HPD : Enable*/
721 /* hardware dependent delay */
Gaurav Singhal165add72017-10-13 17:17:58 +0530722 usleep_range(10000, 10100);
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530723
724 /* send NCI CORE RESET CMD with Keep Config parameters */
725 ret = i2c_master_send(client, raw_nci_reset_cmd,
726 sizeof(raw_nci_reset_cmd));
727 if (ret < 0) {
728 dev_err(&client->dev,
Tapas Deyb5e69602019-05-07 11:33:00 +0530729 "%s: - i2c_master_send core reset Error\n", __func__);
730
731 if (gpio_is_valid(nqx_dev->firm_gpio)) {
732 gpio_set_value(nqx_dev->firm_gpio, 1);
733 usleep_range(10000, 10100);
734 }
735 gpio_set_value(nqx_dev->en_gpio, 0);
736 usleep_range(10000, 10100);
737 gpio_set_value(nqx_dev->en_gpio, 1);
738 usleep_range(10000, 10100);
739
740 ret = i2c_master_send(client, nci_get_version_cmd,
741 sizeof(nci_get_version_cmd));
742
743 if (ret < 0) {
744 dev_err(&client->dev,
745 "%s: - i2c_master_send get version cmd Error\n",
746 __func__);
747 goto err_nfcc_hw_check;
748 }
749 /* hardware dependent delay */
750 usleep_range(10000, 10100);
751
752 ret = i2c_master_recv(client, nci_get_version_rsp,
753 sizeof(nci_get_version_rsp));
754 if (ret < 0) {
755 dev_err(&client->dev,
756 "%s: - i2c_master_recv get version rsp Error\n",
757 __func__);
758 goto err_nfcc_hw_check;
759 } else {
760 nqx_dev->nqx_info.info.chip_type =
761 nci_get_version_rsp[3];
762 nqx_dev->nqx_info.info.rom_version =
763 nci_get_version_rsp[4];
Tapas Dey48613f82019-11-21 16:18:42 +0530764 if ((nci_get_version_rsp[3] == NFCC_SN100_A)
765 || (nci_get_version_rsp[3] == NFCC_SN100_B)) {
766 nqx_dev->nqx_info.info.fw_minor =
767 nci_get_version_rsp[6];
768 nqx_dev->nqx_info.info.fw_major =
769 nci_get_version_rsp[7];
770 } else {
771 nqx_dev->nqx_info.info.fw_minor =
772 nci_get_version_rsp[10];
773 nqx_dev->nqx_info.info.fw_major =
774 nci_get_version_rsp[11];
775 }
Tapas Deyb5e69602019-05-07 11:33:00 +0530776 }
777 goto err_nfcc_reset_failed;
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530778 }
Bhuvan Varshney8e2ca882019-09-09 19:20:37 +0530779 ret = is_data_available_for_read(nqx_dev);
780 if (ret < 0) {
781 nqx_disable_irq(nqx_dev);
782 goto err_nfcc_hw_check;
783 }
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530784
785 /* Read Response of RESET command */
786 ret = i2c_master_recv(client, nci_reset_rsp,
787 sizeof(nci_reset_rsp));
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530788 if (ret < 0) {
789 dev_err(&client->dev,
790 "%s: - i2c_master_recv Error\n", __func__);
791 goto err_nfcc_hw_check;
792 }
Bhuvan Varshney8e2ca882019-09-09 19:20:37 +0530793
794 /* send NCI CORE INIT CMD */
Gaurav Singhal165add72017-10-13 17:17:58 +0530795 ret = nqx_standby_write(nqx_dev, raw_nci_init_cmd,
796 sizeof(raw_nci_init_cmd));
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530797 if (ret < 0) {
798 dev_err(&client->dev,
Tapas Deyb5e69602019-05-07 11:33:00 +0530799 "%s: - i2c_master_send failed for Core INIT\n", __func__);
Gaurav Singhal165add72017-10-13 17:17:58 +0530800 goto err_nfcc_core_init_fail;
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530801 }
Bhuvan Varshney8e2ca882019-09-09 19:20:37 +0530802 ret = is_data_available_for_read(nqx_dev);
803 if (ret < 0) {
804 nqx_disable_irq(nqx_dev);
805 goto err_nfcc_hw_check;
806 }
807
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530808 /* Read Response of INIT command */
809 ret = i2c_master_recv(client, nci_init_rsp,
810 sizeof(nci_init_rsp));
811 if (ret < 0) {
812 dev_err(&client->dev,
813 "%s: - i2c_master_recv Error\n", __func__);
Gaurav Singhal165add72017-10-13 17:17:58 +0530814 goto err_nfcc_core_init_fail;
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530815 }
816 init_rsp_len = 2 + nci_init_rsp[2]; /*payload + len*/
817 if (init_rsp_len > PAYLOAD_HEADER_LENGTH) {
818 nqx_dev->nqx_info.info.chip_type =
819 nci_init_rsp[init_rsp_len - 3];
820 nqx_dev->nqx_info.info.rom_version =
821 nci_init_rsp[init_rsp_len - 2];
822 nqx_dev->nqx_info.info.fw_major =
823 nci_init_rsp[init_rsp_len - 1];
824 nqx_dev->nqx_info.info.fw_minor =
825 nci_init_rsp[init_rsp_len];
826 }
Gaurav Singhal165add72017-10-13 17:17:58 +0530827 dev_dbg(&client->dev,
828 "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
829 __func__, nci_reset_rsp[0],
830 nci_reset_rsp[1], nci_reset_rsp[2]);
831
Tapas Deyb5e69602019-05-07 11:33:00 +0530832err_nfcc_reset_failed:
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530833 dev_dbg(&nqx_dev->client->dev, "NQ NFCC chip_type = %x\n",
834 nqx_dev->nqx_info.info.chip_type);
835 dev_dbg(&nqx_dev->client->dev, "NQ fw version = %x.%x.%x\n",
836 nqx_dev->nqx_info.info.rom_version,
837 nqx_dev->nqx_info.info.fw_major,
838 nqx_dev->nqx_info.info.fw_minor);
839
840 switch (nqx_dev->nqx_info.info.chip_type) {
841 case NFCC_NQ_210:
842 dev_dbg(&client->dev,
843 "%s: ## NFCC == NQ210 ##\n", __func__);
844 break;
845 case NFCC_NQ_220:
846 dev_dbg(&client->dev,
847 "%s: ## NFCC == NQ220 ##\n", __func__);
848 break;
849 case NFCC_NQ_310:
850 dev_dbg(&client->dev,
851 "%s: ## NFCC == NQ310 ##\n", __func__);
852 break;
853 case NFCC_NQ_330:
854 dev_dbg(&client->dev,
855 "%s: ## NFCC == NQ330 ##\n", __func__);
856 break;
857 case NFCC_PN66T:
858 dev_dbg(&client->dev,
859 "%s: ## NFCC == PN66T ##\n", __func__);
860 break;
Bhuvan Varshney8e2ca882019-09-09 19:20:37 +0530861 case NFCC_SN100_A:
862 case NFCC_SN100_B:
863 dev_dbg(&client->dev,
864 "%s: ## NFCC == SN100x ##\n", __func__);
865 break;
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530866 default:
867 dev_err(&client->dev,
868 "%s: - NFCC HW not Supported\n", __func__);
869 break;
870 }
871
872 /*Disable NFC by default to save power on boot*/
873 gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
874 ret = 0;
875 goto done;
876
Gaurav Singhal165add72017-10-13 17:17:58 +0530877err_nfcc_core_init_fail:
878 dev_err(&client->dev,
879 "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
880 __func__, nci_reset_rsp[0],
881 nci_reset_rsp[1], nci_reset_rsp[2]);
882
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530883err_nfcc_hw_check:
884 ret = -ENXIO;
885 dev_err(&client->dev,
886 "%s: - NFCC HW not available\n", __func__);
887done:
888 return ret;
889}
890
891/*
892 * Routine to enable clock.
893 * this routine can be extended to select from multiple
894 * sources based on clk_src_name.
895 */
896static int nqx_clock_select(struct nqx_dev *nqx_dev)
897{
898 int r = 0;
899
900 nqx_dev->s_clk = clk_get(&nqx_dev->client->dev, "ref_clk");
901
902 if (nqx_dev->s_clk == NULL)
903 goto err_clk;
904
905 if (nqx_dev->clk_run == false)
906 r = clk_prepare_enable(nqx_dev->s_clk);
907
908 if (r)
909 goto err_clk;
910
911 nqx_dev->clk_run = true;
912
913 return r;
914
915err_clk:
916 r = -1;
917 return r;
918}
919
920/*
921 * Routine to disable clocks
922 */
923static int nqx_clock_deselect(struct nqx_dev *nqx_dev)
924{
925 int r = -1;
926
927 if (nqx_dev->s_clk != NULL) {
928 if (nqx_dev->clk_run == true) {
929 clk_disable_unprepare(nqx_dev->s_clk);
930 nqx_dev->clk_run = false;
931 }
932 return 0;
933 }
934 return r;
935}
936
937static int nfc_parse_dt(struct device *dev, struct nqx_platform_data *pdata)
938{
939 int r = 0;
940 struct device_node *np = dev->of_node;
941
942 pdata->en_gpio = of_get_named_gpio(np, "qcom,nq-ven", 0);
943 if ((!gpio_is_valid(pdata->en_gpio)))
944 return -EINVAL;
945 disable_ctrl = pdata->en_gpio;
946
947 pdata->irq_gpio = of_get_named_gpio(np, "qcom,nq-irq", 0);
948 if ((!gpio_is_valid(pdata->irq_gpio)))
949 return -EINVAL;
950
951 pdata->firm_gpio = of_get_named_gpio(np, "qcom,nq-firm", 0);
952 if (!gpio_is_valid(pdata->firm_gpio)) {
953 dev_warn(dev,
954 "FIRM GPIO <OPTIONAL> error getting from OF node\n");
955 pdata->firm_gpio = -EINVAL;
956 }
957
958 pdata->ese_gpio = of_get_named_gpio(np, "qcom,nq-esepwr", 0);
959 if (!gpio_is_valid(pdata->ese_gpio)) {
960 dev_warn(dev,
961 "ese GPIO <OPTIONAL> error getting from OF node\n");
962 pdata->ese_gpio = -EINVAL;
963 }
964
Gaurav Singhal71661102018-01-30 16:34:37 +0530965 if (of_property_read_string(np, "qcom,clk-src", &pdata->clk_src_name))
966 pdata->clk_pin_voting = false;
967 else
968 pdata->clk_pin_voting = true;
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530969
970 pdata->clkreq_gpio = of_get_named_gpio(np, "qcom,nq-clkreq", 0);
971
Gaurav Singhalc53bc292017-02-16 16:35:39 +0530972 return r;
973}
974
975static inline int gpio_input_init(const struct device * const dev,
976 const int gpio, const char * const gpio_name)
977{
978 int r = gpio_request(gpio, gpio_name);
979
980 if (r) {
981 dev_err(dev, "unable to request gpio [%d]\n", gpio);
982 return r;
983 }
984
985 r = gpio_direction_input(gpio);
986 if (r)
987 dev_err(dev, "unable to set direction for gpio [%d]\n", gpio);
988
989 return r;
990}
991
992static int nqx_probe(struct i2c_client *client,
993 const struct i2c_device_id *id)
994{
995 int r = 0;
996 int irqn = 0;
997 struct nqx_platform_data *platform_data;
998 struct nqx_dev *nqx_dev;
999
1000 dev_dbg(&client->dev, "%s: enter\n", __func__);
1001 if (client->dev.of_node) {
1002 platform_data = devm_kzalloc(&client->dev,
1003 sizeof(struct nqx_platform_data), GFP_KERNEL);
1004 if (!platform_data) {
1005 r = -ENOMEM;
1006 goto err_platform_data;
1007 }
1008 r = nfc_parse_dt(&client->dev, platform_data);
1009 if (r)
1010 goto err_free_data;
1011 } else
1012 platform_data = client->dev.platform_data;
1013
1014 dev_dbg(&client->dev,
1015 "%s, inside nfc-nci flags = %x\n",
1016 __func__, client->flags);
1017
1018 if (platform_data == NULL) {
1019 dev_err(&client->dev, "%s: failed\n", __func__);
1020 r = -ENODEV;
1021 goto err_platform_data;
1022 }
1023 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1024 dev_err(&client->dev, "%s: need I2C_FUNC_I2C\n", __func__);
1025 r = -ENODEV;
1026 goto err_free_data;
1027 }
1028 nqx_dev = kzalloc(sizeof(*nqx_dev), GFP_KERNEL);
1029 if (nqx_dev == NULL) {
1030 r = -ENOMEM;
1031 goto err_free_data;
1032 }
1033 nqx_dev->client = client;
1034 nqx_dev->kbuflen = MAX_BUFFER_SIZE;
1035 nqx_dev->kbuf = kzalloc(MAX_BUFFER_SIZE, GFP_KERNEL);
1036 if (!nqx_dev->kbuf) {
1037 dev_err(&client->dev,
1038 "failed to allocate memory for nqx_dev->kbuf\n");
1039 r = -ENOMEM;
1040 goto err_free_dev;
1041 }
1042
1043 if (gpio_is_valid(platform_data->en_gpio)) {
1044 r = gpio_request(platform_data->en_gpio, "nfc_reset_gpio");
1045 if (r) {
1046 dev_err(&client->dev,
1047 "%s: unable to request nfc reset gpio [%d]\n",
1048 __func__,
1049 platform_data->en_gpio);
1050 goto err_mem;
1051 }
1052 r = gpio_direction_output(platform_data->en_gpio, 0);
1053 if (r) {
1054 dev_err(&client->dev,
1055 "%s: unable to set direction for nfc reset gpio [%d]\n",
1056 __func__,
1057 platform_data->en_gpio);
1058 goto err_en_gpio;
1059 }
1060 } else {
1061 dev_err(&client->dev,
1062 "%s: nfc reset gpio not provided\n", __func__);
1063 goto err_mem;
1064 }
1065
1066 if (gpio_is_valid(platform_data->irq_gpio)) {
1067 r = gpio_request(platform_data->irq_gpio, "nfc_irq_gpio");
1068 if (r) {
1069 dev_err(&client->dev, "%s: unable to request nfc irq gpio [%d]\n",
1070 __func__, platform_data->irq_gpio);
1071 goto err_en_gpio;
1072 }
1073 r = gpio_direction_input(platform_data->irq_gpio);
1074 if (r) {
1075 dev_err(&client->dev,
1076 "%s: unable to set direction for nfc irq gpio [%d]\n",
1077 __func__,
1078 platform_data->irq_gpio);
1079 goto err_irq_gpio;
1080 }
1081 irqn = gpio_to_irq(platform_data->irq_gpio);
1082 if (irqn < 0) {
1083 r = irqn;
1084 goto err_irq_gpio;
1085 }
1086 client->irq = irqn;
1087 } else {
1088 dev_err(&client->dev, "%s: irq gpio not provided\n", __func__);
1089 goto err_en_gpio;
1090 }
1091 if (gpio_is_valid(platform_data->firm_gpio)) {
1092 r = gpio_request(platform_data->firm_gpio,
1093 "nfc_firm_gpio");
1094 if (r) {
1095 dev_err(&client->dev,
1096 "%s: unable to request nfc firmware gpio [%d]\n",
1097 __func__, platform_data->firm_gpio);
1098 goto err_irq_gpio;
1099 }
1100 r = gpio_direction_output(platform_data->firm_gpio, 0);
1101 if (r) {
1102 dev_err(&client->dev,
1103 "%s: cannot set direction for nfc firmware gpio [%d]\n",
1104 __func__, platform_data->firm_gpio);
1105 goto err_firm_gpio;
1106 }
1107 } else {
1108 dev_err(&client->dev,
1109 "%s: firm gpio not provided\n", __func__);
1110 goto err_irq_gpio;
1111 }
1112 if (gpio_is_valid(platform_data->ese_gpio)) {
1113 r = gpio_request(platform_data->ese_gpio,
1114 "nfc-ese_pwr");
1115 if (r) {
1116 nqx_dev->ese_gpio = -EINVAL;
1117 dev_err(&client->dev,
1118 "%s: unable to request nfc ese gpio [%d]\n",
1119 __func__, platform_data->ese_gpio);
1120 /* ese gpio optional so we should continue */
1121 } else {
1122 nqx_dev->ese_gpio = platform_data->ese_gpio;
1123 r = gpio_direction_output(platform_data->ese_gpio, 0);
1124 if (r) {
1125 /*
1126 * free ese gpio and set invalid
1127 * to avoid further use
1128 */
1129 gpio_free(platform_data->ese_gpio);
1130 nqx_dev->ese_gpio = -EINVAL;
1131 dev_err(&client->dev,
1132 "%s: cannot set direction for nfc ese gpio [%d]\n",
1133 __func__, platform_data->ese_gpio);
1134 /* ese gpio optional so we should continue */
1135 }
1136 }
1137 } else {
1138 nqx_dev->ese_gpio = -EINVAL;
1139 dev_err(&client->dev,
1140 "%s: ese gpio not provided\n", __func__);
1141 /* ese gpio optional so we should continue */
1142 }
1143 if (gpio_is_valid(platform_data->clkreq_gpio)) {
1144 r = gpio_request(platform_data->clkreq_gpio,
1145 "nfc_clkreq_gpio");
1146 if (r) {
1147 dev_err(&client->dev,
1148 "%s: unable to request nfc clkreq gpio [%d]\n",
1149 __func__, platform_data->clkreq_gpio);
1150 goto err_ese_gpio;
1151 }
1152 r = gpio_direction_input(platform_data->clkreq_gpio);
1153 if (r) {
1154 dev_err(&client->dev,
1155 "%s: cannot set direction for nfc clkreq gpio [%d]\n",
1156 __func__, platform_data->clkreq_gpio);
1157 goto err_clkreq_gpio;
1158 }
1159 } else {
1160 dev_err(&client->dev,
1161 "%s: clkreq gpio not provided\n", __func__);
1162 goto err_ese_gpio;
1163 }
1164
1165 nqx_dev->en_gpio = platform_data->en_gpio;
1166 nqx_dev->irq_gpio = platform_data->irq_gpio;
1167 nqx_dev->firm_gpio = platform_data->firm_gpio;
1168 nqx_dev->clkreq_gpio = platform_data->clkreq_gpio;
1169 nqx_dev->pdata = platform_data;
1170
1171 /* init mutex and queues */
1172 init_waitqueue_head(&nqx_dev->read_wq);
1173 mutex_init(&nqx_dev->read_mutex);
1174 spin_lock_init(&nqx_dev->irq_enabled_lock);
1175
1176 nqx_dev->nqx_device.minor = MISC_DYNAMIC_MINOR;
1177 nqx_dev->nqx_device.name = "nq-nci";
1178 nqx_dev->nqx_device.fops = &nfc_dev_fops;
1179
1180 r = misc_register(&nqx_dev->nqx_device);
1181 if (r) {
1182 dev_err(&client->dev, "%s: misc_register failed\n", __func__);
1183 goto err_misc_register;
1184 }
1185
1186 /* NFC_INT IRQ */
1187 nqx_dev->irq_enabled = true;
1188 r = request_irq(client->irq, nqx_dev_irq_handler,
1189 IRQF_TRIGGER_HIGH, client->name, nqx_dev);
1190 if (r) {
1191 dev_err(&client->dev, "%s: request_irq failed\n", __func__);
1192 goto err_request_irq_failed;
1193 }
1194 nqx_disable_irq(nqx_dev);
1195
1196 /*
1197 * To be efficient we need to test whether nfcc hardware is physically
1198 * present before attempting further hardware initialisation.
1199 *
1200 */
1201 r = nfcc_hw_check(client, nqx_dev);
1202 if (r) {
1203 /* make sure NFCC is not enabled */
1204 gpio_set_value(platform_data->en_gpio, 0);
michaellin1d8583b2020-04-21 18:39:32 +08001205 //< 20181116 Michael Lin - Mask where firmware download fail recovery is used
1206 #if !defined( NFC_FW_DOWNLOAD_MODE ) /* Qualcomm default */
Gaurav Singhalc53bc292017-02-16 16:35:39 +05301207 /* We don't think there is hardware switch NFC OFF */
1208 goto err_request_hw_check_failed;
michaellin1d8583b2020-04-21 18:39:32 +08001209 #else
1210 dev_err(&client->dev, "[%s]nfcc_hw_check() error !!\n", __func__ );
1211 #endif
1212 //> 20181116 Michael Lin - Mask where firmware download fail recovery is used
Gaurav Singhalc53bc292017-02-16 16:35:39 +05301213 }
1214
1215 /* Register reboot notifier here */
1216 r = register_reboot_notifier(&nfcc_notifier);
1217 if (r) {
1218 dev_err(&client->dev,
1219 "%s: cannot register reboot notifier(err = %d)\n",
1220 __func__, r);
1221 /*
1222 * nfcc_hw_check function not doing memory
1223 * allocation so using same goto target here
1224 */
1225 goto err_request_hw_check_failed;
1226 }
1227
1228#ifdef NFC_KERNEL_BU
1229 r = nqx_clock_select(nqx_dev);
1230 if (r < 0) {
1231 dev_err(&client->dev,
1232 "%s: nqx_clock_select failed\n", __func__);
1233 goto err_clock_en_failed;
1234 }
1235 gpio_set_value(platform_data->en_gpio, 1);
1236#endif
1237 device_init_wakeup(&client->dev, true);
1238 device_set_wakeup_capable(&client->dev, true);
1239 i2c_set_clientdata(client, nqx_dev);
1240 nqx_dev->irq_wake_up = false;
1241
1242 dev_err(&client->dev,
1243 "%s: probing NFCC NQxxx exited successfully\n",
1244 __func__);
1245 return 0;
1246
1247#ifdef NFC_KERNEL_BU
1248err_clock_en_failed:
1249 unregister_reboot_notifier(&nfcc_notifier);
1250#endif
1251err_request_hw_check_failed:
1252 free_irq(client->irq, nqx_dev);
1253err_request_irq_failed:
1254 misc_deregister(&nqx_dev->nqx_device);
1255err_misc_register:
1256 mutex_destroy(&nqx_dev->read_mutex);
1257err_clkreq_gpio:
1258 gpio_free(platform_data->clkreq_gpio);
1259err_ese_gpio:
1260 /* optional gpio, not sure was configured in probe */
Bhuvan Varshneybf32b4a2019-03-20 13:26:27 +05301261 if (gpio_is_valid(platform_data->ese_gpio))
Gaurav Singhalc53bc292017-02-16 16:35:39 +05301262 gpio_free(platform_data->ese_gpio);
1263err_firm_gpio:
1264 gpio_free(platform_data->firm_gpio);
1265err_irq_gpio:
1266 gpio_free(platform_data->irq_gpio);
1267err_en_gpio:
1268 gpio_free(platform_data->en_gpio);
1269err_mem:
1270 kfree(nqx_dev->kbuf);
1271err_free_dev:
1272 kfree(nqx_dev);
1273err_free_data:
1274 if (client->dev.of_node)
1275 devm_kfree(&client->dev, platform_data);
1276err_platform_data:
1277 dev_err(&client->dev,
1278 "%s: probing nqxx failed, check hardware\n",
1279 __func__);
1280 return r;
1281}
1282
1283static int nqx_remove(struct i2c_client *client)
1284{
1285 int ret = 0;
1286 struct nqx_dev *nqx_dev;
1287
1288 nqx_dev = i2c_get_clientdata(client);
1289 if (!nqx_dev) {
1290 dev_err(&client->dev,
1291 "%s: device doesn't exist anymore\n", __func__);
1292 ret = -ENODEV;
1293 goto err;
1294 }
1295
1296 unregister_reboot_notifier(&nfcc_notifier);
1297 free_irq(client->irq, nqx_dev);
1298 misc_deregister(&nqx_dev->nqx_device);
1299 mutex_destroy(&nqx_dev->read_mutex);
1300 gpio_free(nqx_dev->clkreq_gpio);
1301 /* optional gpio, not sure was configured in probe */
1302 if (nqx_dev->ese_gpio > 0)
1303 gpio_free(nqx_dev->ese_gpio);
1304 gpio_free(nqx_dev->firm_gpio);
1305 gpio_free(nqx_dev->irq_gpio);
1306 gpio_free(nqx_dev->en_gpio);
1307 kfree(nqx_dev->kbuf);
1308 if (client->dev.of_node)
1309 devm_kfree(&client->dev, nqx_dev->pdata);
1310
1311 kfree(nqx_dev);
1312err:
1313 return ret;
1314}
1315
1316static int nqx_suspend(struct device *device)
1317{
1318 struct i2c_client *client = to_i2c_client(device);
1319 struct nqx_dev *nqx_dev = i2c_get_clientdata(client);
1320
1321 if (device_may_wakeup(&client->dev) && nqx_dev->irq_enabled) {
1322 if (!enable_irq_wake(client->irq))
1323 nqx_dev->irq_wake_up = true;
1324 }
1325 return 0;
1326}
1327
1328static int nqx_resume(struct device *device)
1329{
1330 struct i2c_client *client = to_i2c_client(device);
1331 struct nqx_dev *nqx_dev = i2c_get_clientdata(client);
1332
1333 if (device_may_wakeup(&client->dev) && nqx_dev->irq_wake_up) {
1334 if (!disable_irq_wake(client->irq))
1335 nqx_dev->irq_wake_up = false;
1336 }
1337 return 0;
1338}
1339
1340static const struct i2c_device_id nqx_id[] = {
1341 {"nqx-i2c", 0},
1342 {}
1343};
1344
1345static const struct dev_pm_ops nfc_pm_ops = {
1346 SET_SYSTEM_SLEEP_PM_OPS(nqx_suspend, nqx_resume)
1347};
1348
1349static struct i2c_driver nqx = {
1350 .id_table = nqx_id,
1351 .probe = nqx_probe,
1352 .remove = nqx_remove,
1353 .driver = {
1354 .owner = THIS_MODULE,
1355 .name = "nq-nci",
1356 .of_match_table = msm_match_table,
Lingutla Chandrasekhar788cb1c2016-09-12 11:10:27 +05301357 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
Gaurav Singhalc53bc292017-02-16 16:35:39 +05301358 .pm = &nfc_pm_ops,
1359 },
1360};
1361
1362static int nfcc_reboot(struct notifier_block *notifier, unsigned long val,
1363 void *v)
1364{
1365 gpio_set_value(disable_ctrl, 1);
1366 return NOTIFY_OK;
1367}
1368
1369/*
1370 * module load/unload record keeping
1371 */
1372static int __init nqx_dev_init(void)
1373{
michaellin1d8583b2020-04-21 18:39:32 +08001374 pr_info( PFX "[%s]Enter...\n", __func__ );
Gaurav Singhalc53bc292017-02-16 16:35:39 +05301375 return i2c_add_driver(&nqx);
1376}
1377module_init(nqx_dev_init);
1378
1379static void __exit nqx_dev_exit(void)
1380{
1381 unregister_reboot_notifier(&nfcc_notifier);
1382 i2c_del_driver(&nqx);
1383}
1384module_exit(nqx_dev_exit);
1385
1386MODULE_DESCRIPTION("NFC nqx");
1387MODULE_LICENSE("GPL v2");