blob: 043f9bc25f6255ae1274fad3eebad193729a4899 [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"
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +010029#include <mach/gpiomux.h>
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070030
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070031struct qca199x_platform_data {
32 unsigned int irq_gpio;
33 unsigned int dis_gpio;
34 unsigned int ven_gpio;
35 unsigned int reg;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +010036 const char *clk_src;
37 unsigned int clk_src_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070038};
39
40static struct of_device_id msm_match_table[] = {
41 {.compatible = "qcom,nfc-nci"},
42 {}
43};
44
45MODULE_DEVICE_TABLE(of, msm_match_table);
46
47#define MAX_BUFFER_SIZE (780)
48/* Read data */
49#define PACKET_HEADER_SIZE_NCI (4)
50#define PACKET_TYPE_NCI (16)
51#define MAX_PACKET_SIZE (PACKET_HEADER_SIZE_NCI + 255)
52#define MAX_QCA_REG (116)
53
54static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +010055static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070056
57struct qca199x_dev {
58 wait_queue_head_t read_wq;
59 struct mutex read_mutex;
60 struct i2c_client *client;
61 struct miscdevice qca199x_device;
62 unsigned int irq_gpio;
63 unsigned int dis_gpio;
64 unsigned int ven_gpio;
65 bool irq_enabled;
66 spinlock_t irq_enabled_lock;
67 unsigned int count_irq;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -070068 enum nfcc_state state;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070069};
70
71/*
72 * To allow filtering of nfc logging from user. This is set via
73 * IOCTL NFC_KERNEL_LOGGING_MODE.
74 */
75static int logging_level;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -070076/*
77 * FTM-RAW-I2C RD/WR MODE
78 */
79static struct devicemode device_mode;
80static int ftm_raw_write_mode;
81static int ftm_werr_code;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070082
83static void qca199x_init_stat(struct qca199x_dev *qca199x_dev)
84{
85 qca199x_dev->count_irq = 0;
86}
87
88static void qca199x_disable_irq(struct qca199x_dev *qca199x_dev)
89{
90 unsigned long flags;
91
92 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
93 if (qca199x_dev->irq_enabled) {
94 disable_irq_nosync(qca199x_dev->client->irq);
95 qca199x_dev->irq_enabled = false;
96 }
97 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
98}
99
100static void qca199x_enable_irq(struct qca199x_dev *qca199x_dev)
101{
102 unsigned long flags;
103
104 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
105 if (!qca199x_dev->irq_enabled) {
106 qca199x_dev->irq_enabled = true;
107 enable_irq(qca199x_dev->client->irq);
108 }
109 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
110}
111
112static irqreturn_t qca199x_dev_irq_handler(int irq, void *dev_id)
113{
114 struct qca199x_dev *qca199x_dev = dev_id;
115 unsigned long flags;
116
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700117 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
118 qca199x_dev->count_irq++;
119 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
120 wake_up(&qca199x_dev->read_wq);
121
122 return IRQ_HANDLED;
123}
124
125static unsigned int nfc_poll(struct file *filp, poll_table *wait)
126{
127 struct qca199x_dev *qca199x_dev = filp->private_data;
128 unsigned int mask = 0;
129 unsigned long flags;
130
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700131 poll_wait(filp, &qca199x_dev->read_wq, wait);
132
133 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
134 if (qca199x_dev->count_irq > 0) {
135 qca199x_dev->count_irq--;
136 mask |= POLLIN | POLLRDNORM;
137 }
138 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
139
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700140 return mask;
141}
142
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700143/*
144 * ONLY for FTM-RAW-I2C Mode
145 * Required to instigate a read, which comes from DT layer. This means we need
146 * to spoof an interrupt and send a wake up event.
147 */
148void ftm_raw_trigger_read(struct qca199x_dev *qca199x_dev)
149{
150 unsigned long flags;
151
152 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
153 qca199x_dev->count_irq++;
154 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
155 wake_up(&qca199x_dev->read_wq);
156}
157
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700158static ssize_t nfc_read(struct file *filp, char __user *buf,
159 size_t count, loff_t *offset)
160{
161 struct qca199x_dev *qca199x_dev = filp->private_data;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700162 unsigned char tmp[MAX_BUFFER_SIZE], rd_byte;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700163 unsigned char len[PAYLOAD_HEADER_LENGTH];
164 int total, length, ret;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700165 int ftm_rerr_code;
166 enum ehandler_mode dmode;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700167
168 total = 0;
169 length = 0;
170 if (count > MAX_BUFFER_SIZE)
171 count = MAX_BUFFER_SIZE;
172
173 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100174 memset(tmp, 0, sizeof(tmp));
175 memset(len, 0, sizeof(len));
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700176 dmode = device_mode.handle_flavour;
177 /* FTM-RAW-I2C RD/WR MODE - Special Case */
178 if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
179 (dmode == SOLICITED_FTM_RAW_MODE)) {
180 /* READ */
181 if ((ftm_raw_write_mode == 0) && (ftm_werr_code == 0)) {
182 ftm_rerr_code = i2c_master_recv(qca199x_dev->client,
183 &rd_byte, 1);
184 if (ftm_rerr_code == 0x1)
185 ftm_rerr_code = 0;
186 tmp[0] = (unsigned char)ftm_rerr_code;
187 tmp[1] = rd_byte;
188 total = 2;
189 ret = copy_to_user(buf, tmp, total);
190 }
191 /* WRITE */
192 else if ((ftm_raw_write_mode == 1) || (ftm_werr_code != 0)) {
193 tmp[0] = (unsigned char)ftm_werr_code;
194 total = 1;
195 ret = copy_to_user(buf, tmp, total);
196 } else {
197 /* Invalid case */
198 total = 0;
199 ret = copy_to_user(buf, tmp, total);
200 }
201 mutex_unlock(&qca199x_dev->read_mutex);
202 goto done;
203 }
204
205 /* NORMAL NCI Behaviour */
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700206 /* Read the header */
207 ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100208 if (ret != PAYLOAD_HEADER_LENGTH) {
209 total = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700210 goto err;
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100211 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700212 length = len[PAYLOAD_HEADER_LENGTH - 1];
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100213 if (length == 0)
214 total = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700215 /** make sure full packet fits in the buffer **/
216 if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= count)) {
217 /* Read the packet */
218 ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
219 PAYLOAD_HEADER_LENGTH));
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100220 if (ret < 0) {
221 total = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700222 goto err;
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100223 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700224 total = (length + PAYLOAD_HEADER_LENGTH);
225 }
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100226
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700227 if (total > 0) {
228 if ((total > count) || copy_to_user(buf, tmp, total)) {
229 dev_err(&qca199x_dev->client->dev,
230 "failed to copy to user space, total = %d\n",
231 total);
232 total = -EFAULT;
233 }
234 }
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100235 mutex_unlock(&qca199x_dev->read_mutex);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700236err:
237 if (ret < 0)
238 mutex_unlock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700239done:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700240 return total;
241}
242
243static ssize_t nfc_write(struct file *filp, const char __user *buf,
244 size_t count, loff_t *offset)
245{
246 struct qca199x_dev *qca199x_dev = filp->private_data;
247 char tmp[MAX_BUFFER_SIZE];
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700248 int ret = 0;
249 enum ehandler_mode dmode;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700250
251 if (count > MAX_BUFFER_SIZE) {
252 dev_err(&qca199x_dev->client->dev, "out of memory\n");
253 return -ENOMEM;
254 }
255 if (copy_from_user(tmp, buf, count)) {
256 dev_err(&qca199x_dev->client->dev,
257 "nfc-nci write: failed to copy from user space\n");
258 return -EFAULT;
259 }
260 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700261 dmode = device_mode.handle_flavour;
262 /* FTM-DIRECT-I2C RD/WR MODE */
263 /* This is a special FTM-i2c mode case,where tester is not using NCI */
264 if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
265 (dmode == SOLICITED_FTM_RAW_MODE)) {
266 /* Read From Register */
267 if (count == 1) {
268 ftm_raw_write_mode = 0;
269 ret = i2c_master_send(qca199x_dev->client, tmp, count);
270 if (ret == 1)
271 ftm_werr_code = 0;
272 else
273 ftm_werr_code = ret;
274 ftm_raw_trigger_read(qca199x_dev);
275 }
276 /* Write to Register */
277 if (count == 2) {
278 ftm_raw_write_mode = 1;
279 ret = i2c_master_send(qca199x_dev->client, tmp, count);
280 if (ret == 2)
281 ftm_werr_code = 0;
282 else
283 ftm_werr_code = ret;
284 ftm_raw_trigger_read(qca199x_dev);
285 }
286 } else {
287 /* NORMAL NCI behaviour - NB :
288 We can be in FTM mode here also */
289 ret = i2c_master_send(qca199x_dev->client, tmp, count);
290 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700291 if (ret != count) {
292 dev_err(&qca199x_dev->client->dev,
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700293 "NFC: failed to write %d\n", ret);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700294 ret = -EIO;
295 }
296 mutex_unlock(&qca199x_dev->read_mutex);
297
298 return ret;
299}
300
301static int nfc_open(struct inode *inode, struct file *filp)
302{
303 int ret = 0;
304
305 struct qca199x_dev *qca199x_dev = container_of(filp->private_data,
306 struct qca199x_dev,
307 qca199x_device);
308
309 filp->private_data = qca199x_dev;
310 qca199x_init_stat(qca199x_dev);
311 qca199x_enable_irq(qca199x_dev);
312 dev_dbg(&qca199x_dev->client->dev,
313 "%d,%d\n", imajor(inode), iminor(inode));
314 return ret;
315}
316
317/*
318 * Wake/Sleep Mode
319 */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700320int nfcc_wake(int level, struct file *filp)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700321{
322 int r = 0;
323 unsigned char raw_nci_sleep[] = {0x2F, 0x03, 0x00};
324 /* Change slave address to 0xE */
325 unsigned char raw_nci_wake[] = {0x10, 0x0F};
326 unsigned short slave_addr = 0xE;
327 unsigned short curr_addr;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700328 struct qca199x_dev *qca199x_dev = filp->private_data;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700329
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700330 dev_dbg(&qca199x_dev->client->dev, "nfcc_wake: %s: info: %p\n",
331 __func__, qca199x_dev);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700332
333 if (level == NFCC_SLEEP) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700334 r = i2c_master_send(qca199x_dev->client, &raw_nci_sleep[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700335 sizeof(raw_nci_sleep));
336
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700337 r = sizeof(raw_nci_sleep);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700338 if (r != sizeof(raw_nci_sleep))
339 return -EMSGSIZE;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700340 qca199x_dev->state = NFCC_STATE_NORMAL_SLEEP;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700341 } else {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700342 curr_addr = qca199x_dev->client->addr;
343 qca199x_dev->client->addr = slave_addr;
344 r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700345 sizeof(raw_nci_wake));
346 /* Restore original NFCC slave I2C address */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700347 qca199x_dev->client->addr = curr_addr;
348 r = sizeof(raw_nci_wake);
349 if (r != sizeof(raw_nci_wake))
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700350 return -EMSGSIZE;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700351 qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700352 }
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700353
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700354 return r;
355}
356
357/*
358 * Inside nfc_ioctl_power_states
359 *
360 * @brief ioctl functions
361 *
362 *
363 * Device control
364 * remove control via ioctl
365 * (arg = 0): NFC_DISABLE GPIO = 0
366 * (arg = 1): NFC_DISABLE GPIO = 1
367 * NOT USED (arg = 2): FW_DL GPIO = 0
368 * NOT USED (arg = 3): FW_DL GPIO = 1
369 * (arg = 4): NFCC_WAKE = 1
370 * (arg = 5): NFCC_WAKE = 0
371 *
372 *
373 */
374int nfc_ioctl_power_states(struct file *filp, unsigned int cmd,
375 unsigned long arg)
376{
377 int r = 0;
378 struct qca199x_dev *qca199x_dev = filp->private_data;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700379
380 if (arg == 0) {
381 gpio_set_value(qca199x_dev->dis_gpio, 0);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700382 r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
383 if (r) {
384 dev_err(&qca199x_dev->client->dev,
385 "unable to set direction for gpio [%d]\n",
386 qca199x_dev->dis_gpio);
387 goto err_req;
388 }
389 gpio_set_value(qca199x_dev->dis_gpio, 0);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100390 msleep(20);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700391 } else if (arg == 1) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700392 gpio_set_value(qca199x_dev->dis_gpio, 0);
393 r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
394 if (r) {
395 dev_err(&qca199x_dev->client->dev,
396 "unable to set direction for gpio [%d]\n",
397 qca199x_dev->dis_gpio);
398 goto err_req;
399 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700400 gpio_set_value(qca199x_dev->dis_gpio, 1);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100401 usleep(1000);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700402 } else if (arg == 2) {
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100403 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100404 r = nfcc_initialise(qca199x_dev->client, 0xE);
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100405 mutex_unlock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100406 if (r) {
407 dev_err(&qca199x_dev->client->dev,
408 "nfc-nci probe: request nfcc initialise failed\n");
409 goto err_req;
410 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700411 } else if (arg == 3) {
412 msleep(20);
413 } else if (arg == 4) {
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100414 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700415 nfcc_wake(NFCC_WAKE, filp);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100416 mutex_unlock(&qca199x_dev->read_mutex);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700417 } else if (arg == 5) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700418 nfcc_wake(NFCC_SLEEP, filp);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700419 } else {
420 r = -ENOIOCTLCMD;
421 }
422
423err_req:
424 return r;
425}
426
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700427/*
428 * Inside nfc_ioctl_nfcc_mode
429 *
430 * @brief nfc_ioctl_nfcc_mode
431 *
432 * (arg = 0) ; NORMAL_MODE - Standard mode, unsolicited read behaviour
433 * (arg = 1) ; SOLICITED_MODE - As above but reads are solicited from User Land
434 * (arg = 2) ; UNSOLICITED_FTM_RAW MODE - NORMAL_MODE but messages from FTM and
435 * not NCI Host.
436 * (arg = 2) ; SOLICITED_FTM_RAW_MODE - As SOLICITED_MODE but messages from FTM
437 * and not NCI Host.
438 *
439 *
440 *
441 */
442int nfc_ioctl_nfcc_mode(struct file *filp, unsigned int cmd, unsigned long arg)
443{
444 int retval = 0;
445
446 static unsigned short nci_addr;
447 struct qca199x_dev *qca199x_dev = filp->private_data;
448 struct qca199x_platform_data *platform_data;
449
450 platform_data = qca199x_dev->client->dev.platform_data;
451
452 if (arg == 0) {
453 device_mode.handle_flavour = UNSOLICITED_MODE;
454 qca199x_dev->client->addr = NCI_I2C_SLAVE;
455 /* enable interrupts again */
456 qca199x_enable_irq(qca199x_dev);
457 } else if (arg == 1) {
458 device_mode.handle_flavour = SOLICITED_MODE;
459 qca199x_dev->client->addr = qca199x_dev->client->addr;
460 /* enable interrupts again */
461 qca199x_enable_irq(qca199x_dev);
462 } else if (arg == 2) {
463 device_mode.handle_flavour = UNSOLICITED_FTM_RAW_MODE;
464 nci_addr = qca199x_dev->client->addr;
465 /* replace with new client slave address*/
466 qca199x_dev->client->addr = 0xE;
467 /* We also need to disable interrupts */
468 qca199x_disable_irq(qca199x_dev);
469 } else if (arg == 3) {
470 device_mode.handle_flavour = SOLICITED_FTM_RAW_MODE;
471 nci_addr = qca199x_dev->client->addr;
472 /* replace with new client slave address*/
473 qca199x_dev->client->addr = 0xE;
474 /* We also need to disable interrupts */
475 qca199x_disable_irq(qca199x_dev);
476 } else {
477 device_mode.handle_flavour = UNSOLICITED_MODE;
478 qca199x_dev->client->addr = NCI_I2C_SLAVE;
479 }
480 return retval;
481}
482
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700483/*
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100484 * Inside nfc_ioctl_nfcc_version
485 *
486 * @brief nfc_ioctl_nfcc_version
487 *
488 *
489 */
490int nfc_ioctl_nfcc_version(struct file *filp, unsigned int cmd,
491 unsigned long arg)
492{
493 int r = 0;
494 unsigned short slave_addr = 0xE;
495 unsigned short curr_addr;
496
497 unsigned char raw_chip_version_addr = 0x00;
498 unsigned char raw_chip_rev_id_addr = 0x9C;
499 unsigned char raw_chip_version = 0xFF;
500
501 struct qca199x_dev *qca199x_dev = filp->private_data;
502 struct qca199x_platform_data *platform_data;
503
504 platform_data = qca199x_dev->client->dev.platform_data;
505
506 if (arg == 0) {
507 curr_addr = qca199x_dev->client->addr;
508 qca199x_dev->client->addr = slave_addr;
509 r = nfc_i2c_write(qca199x_dev->client,
510 &raw_chip_version_addr, 1);
511 if (r < 0)
512 goto invalid_wr;
513 usleep(10);
514 r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
515 /* Restore original NFCC slave I2C address */
516 qca199x_dev->client->addr = curr_addr;
517 }
518 if (arg == 1) {
519 curr_addr = qca199x_dev->client->addr;
520 qca199x_dev->client->addr = slave_addr;
521 r = nfc_i2c_write(qca199x_dev->client,
522 &raw_chip_rev_id_addr, 1);
523 if (r < 0)
524 goto invalid_wr;
525 usleep(10);
526 r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
527 /* Restore original NFCC slave I2C address */
528 qca199x_dev->client->addr = curr_addr;
529 }
530
531 return raw_chip_version;
532invalid_wr:
533 raw_chip_version = 0xFF;
534 dev_err(&qca199x_dev->client->dev,
535 "\nNFCC_INVALID_CHIP_VERSION = %d\n", raw_chip_version);
536 return raw_chip_version;
537}
538
539
540
541/*
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700542 * Inside nfc_ioctl_kernel_logging
543 *
544 * @brief nfc_ioctl_kernel_logging
545 *
546 * (arg = 0) ; NO_LOGGING
547 * (arg = 1) ; COMMS_LOGGING - BASIC LOGGING - Mainly just comms over I2C
548 * (arg = 2) ; FULL_LOGGING - ENABLE ALL - DBG messages for handlers etc.
549 * ; ! Be aware as amount of logging could impact behaviour !
550 *
551 *
552 */
553int nfc_ioctl_kernel_logging(unsigned long arg, struct file *filp)
554{
555 int retval = 0;
556 struct qca199x_dev *qca199x_dev = container_of(filp->private_data,
557 struct qca199x_dev,
558 qca199x_device);
559 if (arg == 0) {
560 dev_dbg(&qca199x_dev->client->dev,
561 "nfc_ioctl_kernel_logging : level = NO_LOGGING\n");
562 logging_level = 0;
563 } else if (arg == 1) {
564 dev_dbg(&qca199x_dev->client->dev,
565 "nfc_ioctl_kernel_logging: level = COMMS_LOGGING only\n");
566 logging_level = 1;
567 } else if (arg == 2) {
568 dev_dbg(&qca199x_dev->client->dev,
569 "nfc_ioctl_kernel_logging: level = FULL_LOGGING\n");
570 logging_level = 2;
571 }
572 return retval;
573}
574
575static long nfc_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)
576{
577 int r = 0;
578
579 switch (cmd) {
580
581 case NFC_SET_PWR:
582 nfc_ioctl_power_states(pfile, cmd, arg);
583 break;
584 case NFCC_MODE:
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700585 nfc_ioctl_nfcc_mode(pfile, cmd, arg);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700586 break;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100587 case NFCC_VERSION:
588 r = nfc_ioctl_nfcc_version(pfile, cmd, arg);
589 break;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700590 case NFC_KERNEL_LOGGING_MODE:
591 nfc_ioctl_kernel_logging(arg, pfile);
592 break;
593 case SET_RX_BLOCK:
594 break;
595 case SET_EMULATOR_TEST_POINT:
596 break;
597 default:
598 r = -ENOIOCTLCMD;
599 }
600 return r;
601}
602
603static const struct file_operations nfc_dev_fops = {
604 .owner = THIS_MODULE,
605 .llseek = no_llseek,
606 .poll = nfc_poll,
607 .read = nfc_read,
608 .write = nfc_write,
609 .open = nfc_open,
610 .unlocked_ioctl = nfc_ioctl
611};
612
613void dumpqca1990(struct i2c_client *client)
614{
615 int r = 0;
616 int i = 0;
617 unsigned char raw_reg_rd = {0x0};
618 unsigned short temp_addr;
619
620 temp_addr = client->addr;
621 client->addr = 0x0E;
622
623 for (i = 0; i < MAX_QCA_REG; i++) {
624 raw_reg_rd = i;
625 if (((i >= 0x0) && (i < 0x4)) || ((i > 0x7) && (i < 0xA)) ||
626 ((i > 0xF) && (i < 0x12)) || ((i > 0x39) && (i < 0x4d)) ||
627 ((i > 0x69) && (i < 0x74)) || (i == 0x18) || (i == 0x30) ||
628 (i == 0x58)) {
629 r = nfc_i2c_write(client, &raw_reg_rd, 1);
630 msleep(20);
631 r = i2c_master_recv(client, &raw_reg_rd, 1);
632 }
633 }
634 client->addr = temp_addr;
635}
636
637static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len)
638{
639 int r;
640
641 r = i2c_master_send(client, buf, len);
642 dev_dbg(&client->dev, "send: %d\n", r);
643 if (r == -EREMOTEIO) { /* Retry, chip was in standby */
644 usleep_range(6000, 10000);
645 r = i2c_master_send(client, buf, len);
646 dev_dbg(&client->dev, "send2: %d\n", r);
647 }
648 if (r != len)
649 return -EREMOTEIO;
650
651 return r;
652}
653
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100654static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700655{
656 int r = 0;
657 unsigned char raw_1p8_CONTROL_011[] = {0x11, XTAL_CLOCK};
658 unsigned char raw_1P8_CONTROL_010[] = {0x10, PWR_EN};
659 unsigned char raw_1P8_X0_0B0[] = {0xB0, (FREQ_SEL)};
660 unsigned char raw_slave1[] = {0x09, NCI_I2C_SLAVE};
661 unsigned char raw_slave2[] = {0x8, 0x10};
662 unsigned char raw_s73[] = {0x73, 0x02};
663 unsigned char raw_slave1_rd = {0x0};
664 unsigned char raw_1P8_PAD_CFG_CLK_REQ[] = {0xA5, 0x1};
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700665 unsigned char raw_1P8_PAD_CFG_PWR_REQ[] = {0xA7, 0x1};
666 unsigned char buf = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700667
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700668 client->addr = curr_addr;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700669 r = i2c_master_send(client, &buf, 1);
670 buf = 0;
671 r = i2c_master_recv(client, &buf, 1);
672 if (0x10 != (0x10 & buf)) {
673 RAW(s73, 0x02);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700674
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700675 r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
676 usleep(1000);
677 RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700678
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700679 r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700680 sizeof(raw_1p8_CONTROL_011));
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700681 usleep(1000);
682 RAW(1P8_CONTROL_010, (0x8));
683 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700684 sizeof(raw_1P8_CONTROL_010));
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700685
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700686 usleep(10000); /* 10ms wait */
687 RAW(1P8_CONTROL_010, (0xC));
688 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
689 sizeof(raw_1P8_CONTROL_010));
690 usleep(100); /* 100uS wait */
691 RAW(1P8_X0_0B0, (FREQ_SEL_19));
692 r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0],
693 sizeof(raw_1P8_X0_0B0));
694 usleep(1000);
695
696 /* PWR_EN = 1 */
697 RAW(1P8_CONTROL_010, (0xd));
698 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
699 sizeof(raw_1P8_CONTROL_010));
700 usleep(20000); /* 20ms wait */
701 /* LS_EN = 1 */
702 RAW(1P8_CONTROL_010, 0xF);
703 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
704 sizeof(raw_1P8_CONTROL_010));
705 usleep(20000); /* 20ms wait */
706
707 /* Enable the PMIC clock */
708 RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
709 r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700710 sizeof(raw_1P8_PAD_CFG_CLK_REQ));
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700711 usleep(1000);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700712
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700713 RAW(1P8_PAD_CFG_PWR_REQ, (0x1));
714 r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_PWR_REQ[0],
715 sizeof(raw_1P8_PAD_CFG_PWR_REQ));
716 usleep(1000);
717
718 RAW(slave2, 0x10);
719 r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
720 usleep(1000);
721
722 RAW(slave1, NCI_I2C_SLAVE);
723 r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
724 usleep(1000);
725
726 /* QCA199x NFCC CPU should now boot... */
727 r = i2c_master_recv(client, &raw_slave1_rd, 1);
728 /* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
729 client->addr = NCI_I2C_SLAVE;
730 r = 0;
731 } else {
732 r = 1;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700733 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700734 return r;
735}
736
737static int nfc_parse_dt(struct device *dev, struct qca199x_platform_data *pdata)
738{
739 int r = 0;
740 struct device_node *np = dev->of_node;
741
742 r = of_property_read_u32(np, "reg", &pdata->reg);
743 if (r)
744 return -EINVAL;
745
746 r = of_property_read_u32(np, "qcom,clk-gpio", &pdata->ven_gpio);
747 if (r)
748 return -EINVAL;
749
750 pdata->dis_gpio = of_get_named_gpio(np, "qcom,dis-gpio", 0);
751 if ((!gpio_is_valid(pdata->dis_gpio)))
752 return -EINVAL;
753
754 pdata->irq_gpio = of_get_named_gpio(np, "qcom,irq-gpio", 0);
755 if ((!gpio_is_valid(pdata->irq_gpio)))
756 return -EINVAL;
757
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100758 r = of_property_read_string(np, "qcom,clk-src", &pdata->clk_src);
759
760 if (!strcmp(pdata->clk_src, "GPCLK"))
761 pdata->clk_src_gpio = of_get_named_gpio(np,
762 "qcom,clk-en-gpio", 0);
763
764 if (r)
765 return -EINVAL;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700766 return r;
767}
768
769static int qca199x_probe(struct i2c_client *client,
770 const struct i2c_device_id *id)
771{
772 int r = 0;
773 int irqn = 0;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100774 struct clk *nfc_clk = NULL;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700775 struct device_node *node = client->dev.of_node;
776 struct qca199x_platform_data *platform_data;
777 struct qca199x_dev *qca199x_dev;
778
779 if (client->dev.of_node) {
780 platform_data = devm_kzalloc(&client->dev,
781 sizeof(struct qca199x_platform_data), GFP_KERNEL);
782 if (!platform_data) {
783 dev_err(&client->dev,
784 "nfc-nci probe: Failed to allocate memory\n");
785 return -ENOMEM;
786 }
787 r = nfc_parse_dt(&client->dev, platform_data);
788 if (r)
789 return r;
790 } else {
791 platform_data = client->dev.platform_data;
792 }
793 if (!platform_data)
794 return -EINVAL;
795 dev_dbg(&client->dev,
796 "nfc-nci probe: %s, inside nfc-nci flags = %x\n",
797 __func__, client->flags);
798 if (platform_data == NULL) {
799 dev_err(&client->dev, "nfc-nci probe: failed\n");
800 return -ENODEV;
801 }
802 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
803 dev_err(&client->dev, "nfc-nci probe: need I2C_FUNC_I2C\n");
804 return -ENODEV;
805 }
806 qca199x_dev = kzalloc(sizeof(*qca199x_dev), GFP_KERNEL);
807 if (qca199x_dev == NULL) {
808 dev_err(&client->dev,
809 "nfc-nci probe: failed to allocate memory for module data\n");
810 return -ENOMEM;
811 }
812 if (gpio_is_valid(platform_data->irq_gpio)) {
813 r = gpio_request(platform_data->irq_gpio, "nfc_irq_gpio");
814 if (r) {
815 dev_err(&client->dev, "unable to request gpio [%d]\n",
816 platform_data->irq_gpio);
817 goto err_irq;
818 }
819 r = gpio_direction_input(platform_data->irq_gpio);
820 if (r) {
821
822 dev_err(&client->dev,
823 "unable to set direction for gpio [%d]\n",
824 platform_data->irq_gpio);
825 goto err_irq;
826 }
827 gpio_to_irq(0);
828 irqn = gpio_to_irq(platform_data->irq_gpio);
829 if (irqn < 0) {
830 r = irqn;
831 goto err_irq;
832 }
833 client->irq = irqn;
834
835 } else {
836 dev_err(&client->dev, "irq gpio not provided\n");
837 goto err_free_dev;
838 }
839 if (gpio_is_valid(platform_data->dis_gpio)) {
840 r = gpio_request(platform_data->dis_gpio, "nfc_reset_gpio");
841 if (r) {
842 dev_err(&client->dev,
843 "NFC: unable to request gpio [%d]\n",
844 platform_data->dis_gpio);
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100845 goto err_free_dev;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700846 }
847 r = gpio_direction_output(platform_data->dis_gpio, 1);
848 if (r) {
849 dev_err(&client->dev,
850 "NFC: unable to set direction for gpio [%d]\n",
851 platform_data->dis_gpio);
852 goto err_dis_gpio;
853 }
854 } else {
855 dev_err(&client->dev, "dis gpio not provided\n");
856 goto err_irq;
857 }
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100858 gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700859 msleep(20);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100860 gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100861 if (!strcmp(platform_data->clk_src, "BBCLK2")) {
862 nfc_clk = clk_get(&client->dev, "ref_clk");
863 if (nfc_clk == NULL)
864 goto err_dis_gpio;
865 } else if (!strcmp(platform_data->clk_src, "RFCLK3")) {
866 nfc_clk = clk_get(&client->dev, "ref_clk_rf");
867 if (nfc_clk == NULL)
868 goto err_dis_gpio;
869 } else if (!strcmp(platform_data->clk_src, "GPCLK")) {
870 if (gpio_is_valid(platform_data->clk_src_gpio)) {
871 nfc_clk = clk_get(&client->dev, "core_clk");
872 if (nfc_clk == NULL)
873 goto err_dis_gpio;
874 } else {
875 goto err_dis_gpio;
876 }
877 } else {
878 nfc_clk = NULL;
879 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700880 r = clk_prepare_enable(nfc_clk);
881 if (r)
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100882 goto err_clk;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700883
884 platform_data->ven_gpio = of_get_named_gpio(node,
885 "qcom,clk-gpio", 0);
886
887 if (gpio_is_valid(platform_data->ven_gpio)) {
888 r = gpio_request(platform_data->ven_gpio, "nfc_ven_gpio");
889 if (r) {
890 dev_err(&client->dev, "unable to request gpio [%d]\n",
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700891 platform_data->ven_gpio);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700892 goto err_ven_gpio;
893 }
894 r = gpio_direction_input(platform_data->ven_gpio);
895 if (r) {
896
897 dev_err(&client->dev,
898 "unable to set direction for gpio [%d]\n",
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700899 platform_data->ven_gpio);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700900 goto err_ven_gpio;
901 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700902 } else {
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700903 dev_err(&client->dev, "ven gpio not provided\n");
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100904 goto err_clk;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700905 }
906 qca199x_dev->dis_gpio = platform_data->dis_gpio;
907 qca199x_dev->irq_gpio = platform_data->irq_gpio;
908 qca199x_dev->ven_gpio = platform_data->ven_gpio;
909 qca199x_dev->client = client;
910
911 /* init mutex and queues */
912 init_waitqueue_head(&qca199x_dev->read_wq);
913 mutex_init(&qca199x_dev->read_mutex);
914 spin_lock_init(&qca199x_dev->irq_enabled_lock);
915
916 qca199x_dev->qca199x_device.minor = MISC_DYNAMIC_MINOR;
917 qca199x_dev->qca199x_device.name = "nfc-nci";
918 qca199x_dev->qca199x_device.fops = &nfc_dev_fops;
919
920 r = misc_register(&qca199x_dev->qca199x_device);
921 if (r) {
922 dev_err(&client->dev, "misc_register failed\n");
923 goto err_misc_register;
924 }
925
Bansidhar Gopalacharid093f1f2013-10-22 20:44:07 -0700926 regulators.regulator = regulator_get(&client->dev, regulators.name);
927 if (IS_ERR(regulators.regulator)) {
928 r = PTR_ERR(regulators.regulator);
929 pr_err("regulator get of %s failed (%d)\n", regulators.name, r);
930 } else {
931 /* Enable the regulator */
932 r = regulator_enable(regulators.regulator);
933 if (r) {
934 pr_err("vreg %s enable failed (%d)\n",
935 regulators.name, r);
936 }
937 }
938
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700939 logging_level = 0;
940 /* request irq. The irq is set whenever the chip has data available
941 * for reading. It is cleared when all data has been read.
942 */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700943 device_mode.handle_flavour = UNSOLICITED_MODE;
944 r = nfcc_initialise(client, platform_data->reg);
945 if (r) {
946 dev_err(&client->dev, "nfc-nci probe: request nfcc initialise failed\n");
947 goto err_nfcc_init_failed;
948 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700949
950 qca199x_dev->irq_enabled = true;
951 r = request_irq(client->irq, qca199x_dev_irq_handler,
952 IRQF_TRIGGER_RISING, client->name, qca199x_dev);
953 if (r) {
954 dev_err(&client->dev, "nfc-nci probe: request_irq failed\n");
955 goto err_request_irq_failed;
956 }
957 qca199x_disable_irq(qca199x_dev);
958 i2c_set_clientdata(client, qca199x_dev);
959 dev_dbg(&client->dev,
960 "nfc-nci probe: %s, probing qca1990 exited successfully\n",
961 __func__);
962 return 0;
963
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700964err_nfcc_init_failed:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700965err_request_irq_failed:
966 misc_deregister(&qca199x_dev->qca199x_device);
967err_misc_register:
968 mutex_destroy(&qca199x_dev->read_mutex);
969err_ven_gpio:
970 gpio_free(platform_data->ven_gpio);
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100971err_clk:
972 clk_disable_unprepare(nfc_clk);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700973err_dis_gpio:
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100974 r = gpio_direction_input(platform_data->dis_gpio);
975 if (r)
976 dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
977 if (!strcmp(platform_data->clk_src, "GPCLK")) {
978 r = gpio_direction_input(platform_data->clk_src_gpio);
979 if (r)
980 dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
981 gpio_free(platform_data->clk_src_gpio);
982 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700983 gpio_free(platform_data->dis_gpio);
984err_irq:
985 gpio_free(platform_data->irq_gpio);
986err_free_dev:
987 kfree(qca199x_dev);
988 return r;
989}
990
991static int qca199x_remove(struct i2c_client *client)
992{
993 struct qca199x_dev *qca199x_dev;
994
995 qca199x_dev = i2c_get_clientdata(client);
996 free_irq(client->irq, qca199x_dev);
997 misc_deregister(&qca199x_dev->qca199x_device);
998 mutex_destroy(&qca199x_dev->read_mutex);
999 gpio_free(qca199x_dev->irq_gpio);
1000 gpio_free(qca199x_dev->dis_gpio);
1001 gpio_free(qca199x_dev->ven_gpio);
1002 kfree(qca199x_dev);
1003
1004 return 0;
1005}
1006
1007static const struct i2c_device_id qca199x_id[] = {
1008 {"qca199x-i2c", 0},
1009 {}
1010};
1011
1012static struct i2c_driver qca199x = {
1013 .id_table = qca199x_id,
1014 .probe = qca199x_probe,
1015 .remove = qca199x_remove,
1016 .driver = {
1017 .owner = THIS_MODULE,
1018 .name = "nfc-nci",
1019 .of_match_table = msm_match_table,
1020 },
1021};
1022
1023/*
1024 * module load/unload record keeping
1025 */
1026static int __init qca199x_dev_init(void)
1027{
1028 return i2c_add_driver(&qca199x);
1029}
1030module_init(qca199x_dev_init);
1031
1032static void __exit qca199x_dev_exit(void)
1033{
1034 i2c_del_driver(&qca199x);
1035}
1036module_exit(qca199x_dev_exit);
1037
1038MODULE_DESCRIPTION("NFC QCA199x");
1039MODULE_LICENSE("GPL v2");
1040