blob: 87c7c304cb10003ecb370ade9b2a63f483325664 [file] [log] [blame]
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
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/slab.h>
17#include <linux/i2c.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/poll.h>
24#include <linux/of_gpio.h>
25#include <linux/clk.h>
26#include <linux/of_device.h>
27#include <linux/regulator/consumer.h>
28#include "nfc-nci.h"
29
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070030struct qca199x_platform_data {
31 unsigned int irq_gpio;
32 unsigned int dis_gpio;
33 unsigned int ven_gpio;
34 unsigned int reg;
35};
36
37static struct of_device_id msm_match_table[] = {
38 {.compatible = "qcom,nfc-nci"},
39 {}
40};
41
42MODULE_DEVICE_TABLE(of, msm_match_table);
43
44#define MAX_BUFFER_SIZE (780)
45/* Read data */
46#define PACKET_HEADER_SIZE_NCI (4)
47#define PACKET_TYPE_NCI (16)
48#define MAX_PACKET_SIZE (PACKET_HEADER_SIZE_NCI + 255)
49#define MAX_QCA_REG (116)
50
51static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +010052static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070053
54struct qca199x_dev {
55 wait_queue_head_t read_wq;
56 struct mutex read_mutex;
57 struct i2c_client *client;
58 struct miscdevice qca199x_device;
59 unsigned int irq_gpio;
60 unsigned int dis_gpio;
61 unsigned int ven_gpio;
62 bool irq_enabled;
63 spinlock_t irq_enabled_lock;
64 unsigned int count_irq;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -070065 enum nfcc_state state;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070066};
67
68/*
69 * To allow filtering of nfc logging from user. This is set via
70 * IOCTL NFC_KERNEL_LOGGING_MODE.
71 */
72static int logging_level;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -070073/*
74 * FTM-RAW-I2C RD/WR MODE
75 */
76static struct devicemode device_mode;
77static int ftm_raw_write_mode;
78static int ftm_werr_code;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070079
80static void qca199x_init_stat(struct qca199x_dev *qca199x_dev)
81{
82 qca199x_dev->count_irq = 0;
83}
84
85static void qca199x_disable_irq(struct qca199x_dev *qca199x_dev)
86{
87 unsigned long flags;
88
89 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
90 if (qca199x_dev->irq_enabled) {
91 disable_irq_nosync(qca199x_dev->client->irq);
92 qca199x_dev->irq_enabled = false;
93 }
94 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
95}
96
97static void qca199x_enable_irq(struct qca199x_dev *qca199x_dev)
98{
99 unsigned long flags;
100
101 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
102 if (!qca199x_dev->irq_enabled) {
103 qca199x_dev->irq_enabled = true;
104 enable_irq(qca199x_dev->client->irq);
105 }
106 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
107}
108
109static irqreturn_t qca199x_dev_irq_handler(int irq, void *dev_id)
110{
111 struct qca199x_dev *qca199x_dev = dev_id;
112 unsigned long flags;
113
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700114 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
115 qca199x_dev->count_irq++;
116 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
117 wake_up(&qca199x_dev->read_wq);
118
119 return IRQ_HANDLED;
120}
121
122static unsigned int nfc_poll(struct file *filp, poll_table *wait)
123{
124 struct qca199x_dev *qca199x_dev = filp->private_data;
125 unsigned int mask = 0;
126 unsigned long flags;
127
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700128 poll_wait(filp, &qca199x_dev->read_wq, wait);
129
130 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
131 if (qca199x_dev->count_irq > 0) {
132 qca199x_dev->count_irq--;
133 mask |= POLLIN | POLLRDNORM;
134 }
135 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
136
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700137 return mask;
138}
139
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700140/*
141 * ONLY for FTM-RAW-I2C Mode
142 * Required to instigate a read, which comes from DT layer. This means we need
143 * to spoof an interrupt and send a wake up event.
144 */
145void ftm_raw_trigger_read(struct qca199x_dev *qca199x_dev)
146{
147 unsigned long flags;
148
149 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
150 qca199x_dev->count_irq++;
151 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
152 wake_up(&qca199x_dev->read_wq);
153}
154
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700155static ssize_t nfc_read(struct file *filp, char __user *buf,
156 size_t count, loff_t *offset)
157{
158 struct qca199x_dev *qca199x_dev = filp->private_data;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700159 unsigned char tmp[MAX_BUFFER_SIZE], rd_byte;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700160 unsigned char len[PAYLOAD_HEADER_LENGTH];
161 int total, length, ret;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700162 int ftm_rerr_code;
163 enum ehandler_mode dmode;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700164
165 total = 0;
166 length = 0;
167 if (count > MAX_BUFFER_SIZE)
168 count = MAX_BUFFER_SIZE;
169
170 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100171 memset(tmp, 0, sizeof(tmp));
172 memset(len, 0, sizeof(len));
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700173 dmode = device_mode.handle_flavour;
174 /* FTM-RAW-I2C RD/WR MODE - Special Case */
175 if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
176 (dmode == SOLICITED_FTM_RAW_MODE)) {
177 /* READ */
178 if ((ftm_raw_write_mode == 0) && (ftm_werr_code == 0)) {
179 ftm_rerr_code = i2c_master_recv(qca199x_dev->client,
180 &rd_byte, 1);
181 if (ftm_rerr_code == 0x1)
182 ftm_rerr_code = 0;
183 tmp[0] = (unsigned char)ftm_rerr_code;
184 tmp[1] = rd_byte;
185 total = 2;
186 ret = copy_to_user(buf, tmp, total);
187 }
188 /* WRITE */
189 else if ((ftm_raw_write_mode == 1) || (ftm_werr_code != 0)) {
190 tmp[0] = (unsigned char)ftm_werr_code;
191 total = 1;
192 ret = copy_to_user(buf, tmp, total);
193 } else {
194 /* Invalid case */
195 total = 0;
196 ret = copy_to_user(buf, tmp, total);
197 }
198 mutex_unlock(&qca199x_dev->read_mutex);
199 goto done;
200 }
201
202 /* NORMAL NCI Behaviour */
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700203 /* Read the header */
204 ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100205 if (ret != PAYLOAD_HEADER_LENGTH) {
206 total = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700207 goto err;
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100208 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700209 length = len[PAYLOAD_HEADER_LENGTH - 1];
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100210 if (length == 0)
211 total = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700212 /** make sure full packet fits in the buffer **/
213 if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= count)) {
214 /* Read the packet */
215 ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
216 PAYLOAD_HEADER_LENGTH));
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100217 if (ret < 0) {
218 total = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700219 goto err;
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100220 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700221 total = (length + PAYLOAD_HEADER_LENGTH);
222 }
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100223
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700224 if (total > 0) {
225 if ((total > count) || copy_to_user(buf, tmp, total)) {
226 dev_err(&qca199x_dev->client->dev,
227 "failed to copy to user space, total = %d\n",
228 total);
229 total = -EFAULT;
230 }
231 }
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100232 mutex_unlock(&qca199x_dev->read_mutex);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700233err:
234 if (ret < 0)
235 mutex_unlock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700236done:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700237 return total;
238}
239
240static ssize_t nfc_write(struct file *filp, const char __user *buf,
241 size_t count, loff_t *offset)
242{
243 struct qca199x_dev *qca199x_dev = filp->private_data;
244 char tmp[MAX_BUFFER_SIZE];
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700245 int ret = 0;
246 enum ehandler_mode dmode;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700247
248 if (count > MAX_BUFFER_SIZE) {
249 dev_err(&qca199x_dev->client->dev, "out of memory\n");
250 return -ENOMEM;
251 }
252 if (copy_from_user(tmp, buf, count)) {
253 dev_err(&qca199x_dev->client->dev,
254 "nfc-nci write: failed to copy from user space\n");
255 return -EFAULT;
256 }
257 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700258 dmode = device_mode.handle_flavour;
259 /* FTM-DIRECT-I2C RD/WR MODE */
260 /* This is a special FTM-i2c mode case,where tester is not using NCI */
261 if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
262 (dmode == SOLICITED_FTM_RAW_MODE)) {
263 /* Read From Register */
264 if (count == 1) {
265 ftm_raw_write_mode = 0;
266 ret = i2c_master_send(qca199x_dev->client, tmp, count);
267 if (ret == 1)
268 ftm_werr_code = 0;
269 else
270 ftm_werr_code = ret;
271 ftm_raw_trigger_read(qca199x_dev);
272 }
273 /* Write to Register */
274 if (count == 2) {
275 ftm_raw_write_mode = 1;
276 ret = i2c_master_send(qca199x_dev->client, tmp, count);
277 if (ret == 2)
278 ftm_werr_code = 0;
279 else
280 ftm_werr_code = ret;
281 ftm_raw_trigger_read(qca199x_dev);
282 }
283 } else {
284 /* NORMAL NCI behaviour - NB :
285 We can be in FTM mode here also */
286 ret = i2c_master_send(qca199x_dev->client, tmp, count);
287 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700288 if (ret != count) {
289 dev_err(&qca199x_dev->client->dev,
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700290 "NFC: failed to write %d\n", ret);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700291 ret = -EIO;
292 }
293 mutex_unlock(&qca199x_dev->read_mutex);
294
295 return ret;
296}
297
298static int nfc_open(struct inode *inode, struct file *filp)
299{
300 int ret = 0;
301
302 struct qca199x_dev *qca199x_dev = container_of(filp->private_data,
303 struct qca199x_dev,
304 qca199x_device);
305
306 filp->private_data = qca199x_dev;
307 qca199x_init_stat(qca199x_dev);
308 qca199x_enable_irq(qca199x_dev);
309 dev_dbg(&qca199x_dev->client->dev,
310 "%d,%d\n", imajor(inode), iminor(inode));
311 return ret;
312}
313
314/*
315 * Wake/Sleep Mode
316 */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700317int nfcc_wake(int level, struct file *filp)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700318{
319 int r = 0;
320 unsigned char raw_nci_sleep[] = {0x2F, 0x03, 0x00};
321 /* Change slave address to 0xE */
322 unsigned char raw_nci_wake[] = {0x10, 0x0F};
323 unsigned short slave_addr = 0xE;
324 unsigned short curr_addr;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700325 struct qca199x_dev *qca199x_dev = filp->private_data;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700326
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700327 dev_dbg(&qca199x_dev->client->dev, "nfcc_wake: %s: info: %p\n",
328 __func__, qca199x_dev);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700329
330 if (level == NFCC_SLEEP) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700331 r = i2c_master_send(qca199x_dev->client, &raw_nci_sleep[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700332 sizeof(raw_nci_sleep));
333
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700334 r = sizeof(raw_nci_sleep);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700335 if (r != sizeof(raw_nci_sleep))
336 return -EMSGSIZE;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700337 qca199x_dev->state = NFCC_STATE_NORMAL_SLEEP;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700338 } else {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700339 curr_addr = qca199x_dev->client->addr;
340 qca199x_dev->client->addr = slave_addr;
341 r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700342 sizeof(raw_nci_wake));
343 /* Restore original NFCC slave I2C address */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700344 qca199x_dev->client->addr = curr_addr;
345 r = sizeof(raw_nci_wake);
346 if (r != sizeof(raw_nci_wake))
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700347 return -EMSGSIZE;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700348 qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700349 }
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700350
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700351 return r;
352}
353
354/*
355 * Inside nfc_ioctl_power_states
356 *
357 * @brief ioctl functions
358 *
359 *
360 * Device control
361 * remove control via ioctl
362 * (arg = 0): NFC_DISABLE GPIO = 0
363 * (arg = 1): NFC_DISABLE GPIO = 1
364 * NOT USED (arg = 2): FW_DL GPIO = 0
365 * NOT USED (arg = 3): FW_DL GPIO = 1
366 * (arg = 4): NFCC_WAKE = 1
367 * (arg = 5): NFCC_WAKE = 0
368 *
369 *
370 */
371int nfc_ioctl_power_states(struct file *filp, unsigned int cmd,
372 unsigned long arg)
373{
374 int r = 0;
375 struct qca199x_dev *qca199x_dev = filp->private_data;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700376
377 if (arg == 0) {
378 gpio_set_value(qca199x_dev->dis_gpio, 0);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700379 r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
380 if (r) {
381 dev_err(&qca199x_dev->client->dev,
382 "unable to set direction for gpio [%d]\n",
383 qca199x_dev->dis_gpio);
384 goto err_req;
385 }
386 gpio_set_value(qca199x_dev->dis_gpio, 0);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100387 msleep(20);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700388 } else if (arg == 1) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700389 gpio_set_value(qca199x_dev->dis_gpio, 0);
390 r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
391 if (r) {
392 dev_err(&qca199x_dev->client->dev,
393 "unable to set direction for gpio [%d]\n",
394 qca199x_dev->dis_gpio);
395 goto err_req;
396 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700397 gpio_set_value(qca199x_dev->dis_gpio, 1);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100398 usleep(1000);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700399 } else if (arg == 2) {
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100400 r = nfcc_initialise(qca199x_dev->client, 0xE);
401 if (r) {
402 dev_err(&qca199x_dev->client->dev,
403 "nfc-nci probe: request nfcc initialise failed\n");
404 goto err_req;
405 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700406 } else if (arg == 3) {
407 msleep(20);
408 } else if (arg == 4) {
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100409 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700410 nfcc_wake(NFCC_WAKE, filp);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100411 mutex_unlock(&qca199x_dev->read_mutex);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700412 } else if (arg == 5) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700413 nfcc_wake(NFCC_SLEEP, filp);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700414 } else {
415 r = -ENOIOCTLCMD;
416 }
417
418err_req:
419 return r;
420}
421
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700422
423/*
424 * Inside nfc_ioctl_nfcc_mode
425 *
426 * @brief nfc_ioctl_nfcc_mode
427 *
428 * (arg = 0) ; NORMAL_MODE - Standard mode, unsolicited read behaviour
429 * (arg = 1) ; SOLICITED_MODE - As above but reads are solicited from User Land
430 * (arg = 2) ; UNSOLICITED_FTM_RAW MODE - NORMAL_MODE but messages from FTM and
431 * not NCI Host.
432 * (arg = 2) ; SOLICITED_FTM_RAW_MODE - As SOLICITED_MODE but messages from FTM
433 * and not NCI Host.
434 *
435 *
436 *
437 */
438int nfc_ioctl_nfcc_mode(struct file *filp, unsigned int cmd, unsigned long arg)
439{
440 int retval = 0;
441
442 static unsigned short nci_addr;
443 struct qca199x_dev *qca199x_dev = filp->private_data;
444 struct qca199x_platform_data *platform_data;
445
446 platform_data = qca199x_dev->client->dev.platform_data;
447
448 if (arg == 0) {
449 device_mode.handle_flavour = UNSOLICITED_MODE;
450 qca199x_dev->client->addr = NCI_I2C_SLAVE;
451 /* enable interrupts again */
452 qca199x_enable_irq(qca199x_dev);
453 } else if (arg == 1) {
454 device_mode.handle_flavour = SOLICITED_MODE;
455 qca199x_dev->client->addr = qca199x_dev->client->addr;
456 /* enable interrupts again */
457 qca199x_enable_irq(qca199x_dev);
458 } else if (arg == 2) {
459 device_mode.handle_flavour = UNSOLICITED_FTM_RAW_MODE;
460 nci_addr = qca199x_dev->client->addr;
461 /* replace with new client slave address*/
462 qca199x_dev->client->addr = 0xE;
463 /* We also need to disable interrupts */
464 qca199x_disable_irq(qca199x_dev);
465 } else if (arg == 3) {
466 device_mode.handle_flavour = SOLICITED_FTM_RAW_MODE;
467 nci_addr = qca199x_dev->client->addr;
468 /* replace with new client slave address*/
469 qca199x_dev->client->addr = 0xE;
470 /* We also need to disable interrupts */
471 qca199x_disable_irq(qca199x_dev);
472 } else {
473 device_mode.handle_flavour = UNSOLICITED_MODE;
474 qca199x_dev->client->addr = NCI_I2C_SLAVE;
475 }
476 return retval;
477}
478
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700479/*
480 * Inside nfc_ioctl_kernel_logging
481 *
482 * @brief nfc_ioctl_kernel_logging
483 *
484 * (arg = 0) ; NO_LOGGING
485 * (arg = 1) ; COMMS_LOGGING - BASIC LOGGING - Mainly just comms over I2C
486 * (arg = 2) ; FULL_LOGGING - ENABLE ALL - DBG messages for handlers etc.
487 * ; ! Be aware as amount of logging could impact behaviour !
488 *
489 *
490 */
491int nfc_ioctl_kernel_logging(unsigned long arg, struct file *filp)
492{
493 int retval = 0;
494 struct qca199x_dev *qca199x_dev = container_of(filp->private_data,
495 struct qca199x_dev,
496 qca199x_device);
497 if (arg == 0) {
498 dev_dbg(&qca199x_dev->client->dev,
499 "nfc_ioctl_kernel_logging : level = NO_LOGGING\n");
500 logging_level = 0;
501 } else if (arg == 1) {
502 dev_dbg(&qca199x_dev->client->dev,
503 "nfc_ioctl_kernel_logging: level = COMMS_LOGGING only\n");
504 logging_level = 1;
505 } else if (arg == 2) {
506 dev_dbg(&qca199x_dev->client->dev,
507 "nfc_ioctl_kernel_logging: level = FULL_LOGGING\n");
508 logging_level = 2;
509 }
510 return retval;
511}
512
513static long nfc_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)
514{
515 int r = 0;
516
517 switch (cmd) {
518
519 case NFC_SET_PWR:
520 nfc_ioctl_power_states(pfile, cmd, arg);
521 break;
522 case NFCC_MODE:
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700523 nfc_ioctl_nfcc_mode(pfile, cmd, arg);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700524 break;
525 case NFC_KERNEL_LOGGING_MODE:
526 nfc_ioctl_kernel_logging(arg, pfile);
527 break;
528 case SET_RX_BLOCK:
529 break;
530 case SET_EMULATOR_TEST_POINT:
531 break;
532 default:
533 r = -ENOIOCTLCMD;
534 }
535 return r;
536}
537
538static const struct file_operations nfc_dev_fops = {
539 .owner = THIS_MODULE,
540 .llseek = no_llseek,
541 .poll = nfc_poll,
542 .read = nfc_read,
543 .write = nfc_write,
544 .open = nfc_open,
545 .unlocked_ioctl = nfc_ioctl
546};
547
548void dumpqca1990(struct i2c_client *client)
549{
550 int r = 0;
551 int i = 0;
552 unsigned char raw_reg_rd = {0x0};
553 unsigned short temp_addr;
554
555 temp_addr = client->addr;
556 client->addr = 0x0E;
557
558 for (i = 0; i < MAX_QCA_REG; i++) {
559 raw_reg_rd = i;
560 if (((i >= 0x0) && (i < 0x4)) || ((i > 0x7) && (i < 0xA)) ||
561 ((i > 0xF) && (i < 0x12)) || ((i > 0x39) && (i < 0x4d)) ||
562 ((i > 0x69) && (i < 0x74)) || (i == 0x18) || (i == 0x30) ||
563 (i == 0x58)) {
564 r = nfc_i2c_write(client, &raw_reg_rd, 1);
565 msleep(20);
566 r = i2c_master_recv(client, &raw_reg_rd, 1);
567 }
568 }
569 client->addr = temp_addr;
570}
571
572static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len)
573{
574 int r;
575
576 r = i2c_master_send(client, buf, len);
577 dev_dbg(&client->dev, "send: %d\n", r);
578 if (r == -EREMOTEIO) { /* Retry, chip was in standby */
579 usleep_range(6000, 10000);
580 r = i2c_master_send(client, buf, len);
581 dev_dbg(&client->dev, "send2: %d\n", r);
582 }
583 if (r != len)
584 return -EREMOTEIO;
585
586 return r;
587}
588
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100589static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700590{
591 int r = 0;
592 unsigned char raw_1p8_CONTROL_011[] = {0x11, XTAL_CLOCK};
593 unsigned char raw_1P8_CONTROL_010[] = {0x10, PWR_EN};
594 unsigned char raw_1P8_X0_0B0[] = {0xB0, (FREQ_SEL)};
595 unsigned char raw_slave1[] = {0x09, NCI_I2C_SLAVE};
596 unsigned char raw_slave2[] = {0x8, 0x10};
597 unsigned char raw_s73[] = {0x73, 0x02};
598 unsigned char raw_slave1_rd = {0x0};
599 unsigned char raw_1P8_PAD_CFG_CLK_REQ[] = {0xA5, 0x1};
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700600 unsigned char raw_1P8_PAD_CFG_PWR_REQ[] = {0xA7, 0x1};
601 unsigned char buf = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700602
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700603 client->addr = curr_addr;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700604 r = i2c_master_send(client, &buf, 1);
605 buf = 0;
606 r = i2c_master_recv(client, &buf, 1);
607 if (0x10 != (0x10 & buf)) {
608 RAW(s73, 0x02);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700609
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700610 r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
611 usleep(1000);
612 RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700613
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700614 r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700615 sizeof(raw_1p8_CONTROL_011));
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700616 usleep(1000);
617 RAW(1P8_CONTROL_010, (0x8));
618 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700619 sizeof(raw_1P8_CONTROL_010));
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700620
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700621 usleep(10000); /* 10ms wait */
622 RAW(1P8_CONTROL_010, (0xC));
623 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
624 sizeof(raw_1P8_CONTROL_010));
625 usleep(100); /* 100uS wait */
626 RAW(1P8_X0_0B0, (FREQ_SEL_19));
627 r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0],
628 sizeof(raw_1P8_X0_0B0));
629 usleep(1000);
630
631 /* PWR_EN = 1 */
632 RAW(1P8_CONTROL_010, (0xd));
633 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
634 sizeof(raw_1P8_CONTROL_010));
635 usleep(20000); /* 20ms wait */
636 /* LS_EN = 1 */
637 RAW(1P8_CONTROL_010, 0xF);
638 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
639 sizeof(raw_1P8_CONTROL_010));
640 usleep(20000); /* 20ms wait */
641
642 /* Enable the PMIC clock */
643 RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
644 r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700645 sizeof(raw_1P8_PAD_CFG_CLK_REQ));
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700646 usleep(1000);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700647
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700648 RAW(1P8_PAD_CFG_PWR_REQ, (0x1));
649 r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_PWR_REQ[0],
650 sizeof(raw_1P8_PAD_CFG_PWR_REQ));
651 usleep(1000);
652
653 RAW(slave2, 0x10);
654 r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
655 usleep(1000);
656
657 RAW(slave1, NCI_I2C_SLAVE);
658 r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
659 usleep(1000);
660
661 /* QCA199x NFCC CPU should now boot... */
662 r = i2c_master_recv(client, &raw_slave1_rd, 1);
663 /* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
664 client->addr = NCI_I2C_SLAVE;
665 r = 0;
666 } else {
667 r = 1;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700668 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700669 return r;
670}
671
672static int nfc_parse_dt(struct device *dev, struct qca199x_platform_data *pdata)
673{
674 int r = 0;
675 struct device_node *np = dev->of_node;
676
677 r = of_property_read_u32(np, "reg", &pdata->reg);
678 if (r)
679 return -EINVAL;
680
681 r = of_property_read_u32(np, "qcom,clk-gpio", &pdata->ven_gpio);
682 if (r)
683 return -EINVAL;
684
685 pdata->dis_gpio = of_get_named_gpio(np, "qcom,dis-gpio", 0);
686 if ((!gpio_is_valid(pdata->dis_gpio)))
687 return -EINVAL;
688
689 pdata->irq_gpio = of_get_named_gpio(np, "qcom,irq-gpio", 0);
690 if ((!gpio_is_valid(pdata->irq_gpio)))
691 return -EINVAL;
692
693 return r;
694}
695
696static int qca199x_probe(struct i2c_client *client,
697 const struct i2c_device_id *id)
698{
699 int r = 0;
700 int irqn = 0;
701 struct clk *nfc_clk;
702 struct device_node *node = client->dev.of_node;
703 struct qca199x_platform_data *platform_data;
704 struct qca199x_dev *qca199x_dev;
705
706 if (client->dev.of_node) {
707 platform_data = devm_kzalloc(&client->dev,
708 sizeof(struct qca199x_platform_data), GFP_KERNEL);
709 if (!platform_data) {
710 dev_err(&client->dev,
711 "nfc-nci probe: Failed to allocate memory\n");
712 return -ENOMEM;
713 }
714 r = nfc_parse_dt(&client->dev, platform_data);
715 if (r)
716 return r;
717 } else {
718 platform_data = client->dev.platform_data;
719 }
720 if (!platform_data)
721 return -EINVAL;
722 dev_dbg(&client->dev,
723 "nfc-nci probe: %s, inside nfc-nci flags = %x\n",
724 __func__, client->flags);
725 if (platform_data == NULL) {
726 dev_err(&client->dev, "nfc-nci probe: failed\n");
727 return -ENODEV;
728 }
729 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
730 dev_err(&client->dev, "nfc-nci probe: need I2C_FUNC_I2C\n");
731 return -ENODEV;
732 }
733 qca199x_dev = kzalloc(sizeof(*qca199x_dev), GFP_KERNEL);
734 if (qca199x_dev == NULL) {
735 dev_err(&client->dev,
736 "nfc-nci probe: failed to allocate memory for module data\n");
737 return -ENOMEM;
738 }
739 if (gpio_is_valid(platform_data->irq_gpio)) {
740 r = gpio_request(platform_data->irq_gpio, "nfc_irq_gpio");
741 if (r) {
742 dev_err(&client->dev, "unable to request gpio [%d]\n",
743 platform_data->irq_gpio);
744 goto err_irq;
745 }
746 r = gpio_direction_input(platform_data->irq_gpio);
747 if (r) {
748
749 dev_err(&client->dev,
750 "unable to set direction for gpio [%d]\n",
751 platform_data->irq_gpio);
752 goto err_irq;
753 }
754 gpio_to_irq(0);
755 irqn = gpio_to_irq(platform_data->irq_gpio);
756 if (irqn < 0) {
757 r = irqn;
758 goto err_irq;
759 }
760 client->irq = irqn;
761
762 } else {
763 dev_err(&client->dev, "irq gpio not provided\n");
764 goto err_free_dev;
765 }
766 if (gpio_is_valid(platform_data->dis_gpio)) {
767 r = gpio_request(platform_data->dis_gpio, "nfc_reset_gpio");
768 if (r) {
769 dev_err(&client->dev,
770 "NFC: unable to request gpio [%d]\n",
771 platform_data->dis_gpio);
772 goto err_dis_gpio;
773 }
774 r = gpio_direction_output(platform_data->dis_gpio, 1);
775 if (r) {
776 dev_err(&client->dev,
777 "NFC: unable to set direction for gpio [%d]\n",
778 platform_data->dis_gpio);
779 goto err_dis_gpio;
780 }
781 } else {
782 dev_err(&client->dev, "dis gpio not provided\n");
783 goto err_irq;
784 }
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100785 gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700786 msleep(20);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100787 gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700788
789 nfc_clk = clk_get(&client->dev, "ref_clk");
790
791 if (nfc_clk == NULL)
792 goto err_dis_gpio;
793
794 r = clk_prepare_enable(nfc_clk);
795 if (r)
796 goto err_dis_gpio;
797
798 platform_data->ven_gpio = of_get_named_gpio(node,
799 "qcom,clk-gpio", 0);
800
801 if (gpio_is_valid(platform_data->ven_gpio)) {
802 r = gpio_request(platform_data->ven_gpio, "nfc_ven_gpio");
803 if (r) {
804 dev_err(&client->dev, "unable to request gpio [%d]\n",
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700805 platform_data->ven_gpio);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700806 goto err_ven_gpio;
807 }
808 r = gpio_direction_input(platform_data->ven_gpio);
809 if (r) {
810
811 dev_err(&client->dev,
812 "unable to set direction for gpio [%d]\n",
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700813 platform_data->ven_gpio);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700814 goto err_ven_gpio;
815 }
816
817 } else {
818
819 dev_err(&client->dev, "ven gpio not provided\n");
820 goto err_dis_gpio;
821 }
822 qca199x_dev->dis_gpio = platform_data->dis_gpio;
823 qca199x_dev->irq_gpio = platform_data->irq_gpio;
824 qca199x_dev->ven_gpio = platform_data->ven_gpio;
825 qca199x_dev->client = client;
826
827 /* init mutex and queues */
828 init_waitqueue_head(&qca199x_dev->read_wq);
829 mutex_init(&qca199x_dev->read_mutex);
830 spin_lock_init(&qca199x_dev->irq_enabled_lock);
831
832 qca199x_dev->qca199x_device.minor = MISC_DYNAMIC_MINOR;
833 qca199x_dev->qca199x_device.name = "nfc-nci";
834 qca199x_dev->qca199x_device.fops = &nfc_dev_fops;
835
836 r = misc_register(&qca199x_dev->qca199x_device);
837 if (r) {
838 dev_err(&client->dev, "misc_register failed\n");
839 goto err_misc_register;
840 }
841
842 logging_level = 0;
843 /* request irq. The irq is set whenever the chip has data available
844 * for reading. It is cleared when all data has been read.
845 */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700846 device_mode.handle_flavour = UNSOLICITED_MODE;
847 r = nfcc_initialise(client, platform_data->reg);
848 if (r) {
849 dev_err(&client->dev, "nfc-nci probe: request nfcc initialise failed\n");
850 goto err_nfcc_init_failed;
851 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700852
853 qca199x_dev->irq_enabled = true;
854 r = request_irq(client->irq, qca199x_dev_irq_handler,
855 IRQF_TRIGGER_RISING, client->name, qca199x_dev);
856 if (r) {
857 dev_err(&client->dev, "nfc-nci probe: request_irq failed\n");
858 goto err_request_irq_failed;
859 }
860 qca199x_disable_irq(qca199x_dev);
861 i2c_set_clientdata(client, qca199x_dev);
862 dev_dbg(&client->dev,
863 "nfc-nci probe: %s, probing qca1990 exited successfully\n",
864 __func__);
865 return 0;
866
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700867err_nfcc_init_failed:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700868err_request_irq_failed:
869 misc_deregister(&qca199x_dev->qca199x_device);
870err_misc_register:
871 mutex_destroy(&qca199x_dev->read_mutex);
872err_ven_gpio:
873 gpio_free(platform_data->ven_gpio);
874err_dis_gpio:
875 gpio_free(platform_data->dis_gpio);
876err_irq:
877 gpio_free(platform_data->irq_gpio);
878err_free_dev:
879 kfree(qca199x_dev);
880 return r;
881}
882
883static int qca199x_remove(struct i2c_client *client)
884{
885 struct qca199x_dev *qca199x_dev;
886
887 qca199x_dev = i2c_get_clientdata(client);
888 free_irq(client->irq, qca199x_dev);
889 misc_deregister(&qca199x_dev->qca199x_device);
890 mutex_destroy(&qca199x_dev->read_mutex);
891 gpio_free(qca199x_dev->irq_gpio);
892 gpio_free(qca199x_dev->dis_gpio);
893 gpio_free(qca199x_dev->ven_gpio);
894 kfree(qca199x_dev);
895
896 return 0;
897}
898
899static const struct i2c_device_id qca199x_id[] = {
900 {"qca199x-i2c", 0},
901 {}
902};
903
904static struct i2c_driver qca199x = {
905 .id_table = qca199x_id,
906 .probe = qca199x_probe,
907 .remove = qca199x_remove,
908 .driver = {
909 .owner = THIS_MODULE,
910 .name = "nfc-nci",
911 .of_match_table = msm_match_table,
912 },
913};
914
915/*
916 * module load/unload record keeping
917 */
918static int __init qca199x_dev_init(void)
919{
920 return i2c_add_driver(&qca199x);
921}
922module_init(qca199x_dev_init);
923
924static void __exit qca199x_dev_exit(void)
925{
926 i2c_del_driver(&qca199x);
927}
928module_exit(qca199x_dev_exit);
929
930MODULE_DESCRIPTION("NFC QCA199x");
931MODULE_LICENSE("GPL v2");
932