blob: a44c06cd838995812eab2ba24e246196f33e06ca [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;
Houston Hoffman17f2dc52014-01-29 08:15:06 -080033 unsigned int irq_gpio_clk_req;
34 unsigned int clk_req_irq_num;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070035 unsigned int dis_gpio;
Houston Hoffman17f2dc52014-01-29 08:15:06 -080036 unsigned int clkreq_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070037 unsigned int reg;
Houston Hoffmana0368172013-12-11 16:55:06 -080038 const char *clk_src_name;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +010039 unsigned int clk_src_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070040};
41
42static struct of_device_id msm_match_table[] = {
43 {.compatible = "qcom,nfc-nci"},
44 {}
45};
46
47MODULE_DEVICE_TABLE(of, msm_match_table);
48
Houston Hoffmana0368172013-12-11 16:55:06 -080049#define MAX_BUFFER_SIZE (780)
50#define PACKET_MAX_LENGTH (258)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070051/* Read data */
52#define PACKET_HEADER_SIZE_NCI (4)
Houston Hoffmana0368172013-12-11 16:55:06 -080053#define PACKET_TYPE_NCI (16)
54#define MAX_PACKET_SIZE (PACKET_HEADER_SIZE_NCI + 255)
55#define MAX_QCA_REG (116)
56/* will timeout in approx. 100ms as 10us steps */
Houston Hoffmanfa9a38b2014-01-24 02:09:53 -080057#define NFC_RF_CLK_FREQ (19200000)
Houston Hoffmana0368172013-12-11 16:55:06 -080058#define NTF_TIMEOUT (10000)
59#define CORE_RESET_RSP_GID (0x60)
60#define CORE_RESET_OID (0x00)
61#define CORE_RST_NTF_LENGTH (0x02)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070062
Houston Hoffman17f2dc52014-01-29 08:15:06 -080063static void clk_req_update(struct work_struct *work);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070064
65struct qca199x_dev {
66 wait_queue_head_t read_wq;
Houston Hoffman17f2dc52014-01-29 08:15:06 -080067 struct mutex read_mutex;
68 struct i2c_client *client;
69 struct miscdevice qca199x_device;
70 /* NFC_IRQ new NCI data available */
71 unsigned int irq_gpio;
72 /* CLK_REQ IRQ to signal the state has changed */
73 unsigned int irq_gpio_clk_req;
74 /* Actual IRQ no. assigned to CLK_REQ */
75 unsigned int clk_req_irq_num;
76 unsigned int dis_gpio;
77 unsigned int clkreq_gpio;
78 /* NFC_IRQ state */
79 bool irq_enabled;
80 bool sent_first_nci_write;
81 spinlock_t irq_enabled_lock;
82 unsigned int count_irq;
83 /* CLK_REQ IRQ state */
84 bool irq_enabled_clk_req;
85 spinlock_t irq_enabled_lock_clk_req;
86 unsigned int count_irq_clk_req;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -070087 enum nfcc_state state;
Houston Hoffman17f2dc52014-01-29 08:15:06 -080088 /* CLK control */
89 unsigned int clk_src_gpio;
90 const char *clk_src_name;
91 struct clk *s_clk;
92 bool clk_run;
93 struct work_struct msm_clock_controll_work;
94 struct workqueue_struct *my_wq;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070095};
96
Houston Hoffmana0368172013-12-11 16:55:06 -080097static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
Houston Hoffmanc108e8f2014-01-10 16:12:16 -080098static int nfcc_hw_check(struct i2c_client *client, unsigned short curr_addr);
Houston Hoffmana0368172013-12-11 16:55:06 -080099static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr);
100static int qca199x_clock_select(struct qca199x_dev *qca199x_dev);
101static int qca199x_clock_deselect(struct qca199x_dev *qca199x_dev);
102
103
104
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700105/*
106 * To allow filtering of nfc logging from user. This is set via
107 * IOCTL NFC_KERNEL_LOGGING_MODE.
108 */
109static int logging_level;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700110/*
111 * FTM-RAW-I2C RD/WR MODE
112 */
Houston Hoffman17f2dc52014-01-29 08:15:06 -0800113static struct devicemode device_mode;
114static int ftm_raw_write_mode;
115static int ftm_werr_code;
116
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700117
118static void qca199x_init_stat(struct qca199x_dev *qca199x_dev)
119{
120 qca199x_dev->count_irq = 0;
121}
122
123static void qca199x_disable_irq(struct qca199x_dev *qca199x_dev)
124{
125 unsigned long flags;
126
127 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
128 if (qca199x_dev->irq_enabled) {
129 disable_irq_nosync(qca199x_dev->client->irq);
130 qca199x_dev->irq_enabled = false;
131 }
132 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
133}
134
135static void qca199x_enable_irq(struct qca199x_dev *qca199x_dev)
136{
137 unsigned long flags;
138
139 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
140 if (!qca199x_dev->irq_enabled) {
141 qca199x_dev->irq_enabled = true;
142 enable_irq(qca199x_dev->client->irq);
143 }
144 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
145}
146
147static irqreturn_t qca199x_dev_irq_handler(int irq, void *dev_id)
148{
149 struct qca199x_dev *qca199x_dev = dev_id;
150 unsigned long flags;
151
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700152 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 return IRQ_HANDLED;
158}
159
160static unsigned int nfc_poll(struct file *filp, poll_table *wait)
161{
162 struct qca199x_dev *qca199x_dev = filp->private_data;
163 unsigned int mask = 0;
164 unsigned long flags;
165
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700166 poll_wait(filp, &qca199x_dev->read_wq, wait);
167
168 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
169 if (qca199x_dev->count_irq > 0) {
170 qca199x_dev->count_irq--;
171 mask |= POLLIN | POLLRDNORM;
172 }
173 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
174
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700175 return mask;
176}
177
Houston Hoffman17f2dc52014-01-29 08:15:06 -0800178/* Handlers for CLK_REQ */
179static void qca199x_disable_irq_clk_req(struct qca199x_dev *qca199x_dev)
180{
181 unsigned long flags;
182
183 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock_clk_req, flags);
184 if (qca199x_dev->irq_enabled_clk_req) {
185 disable_irq_nosync(qca199x_dev->clk_req_irq_num);
186 qca199x_dev->irq_enabled_clk_req = false;
187 }
188 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock_clk_req, flags);
189}
190
191
192static void qca199x_enable_irq_clk_req(struct qca199x_dev *qca199x_dev)
193{
194 unsigned long flags;
195
196 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock_clk_req, flags);
197 if (!qca199x_dev->irq_enabled_clk_req) {
198 qca199x_dev->irq_enabled_clk_req = true;
199 enable_irq(qca199x_dev->clk_req_irq_num);
200 }
201 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock_clk_req, flags);
202}
203
204
205static irqreturn_t qca199x_dev_irq_handler_clk_req(int irq, void *dev_id)
206{
207 struct qca199x_dev *qca199x_dev = dev_id;
208 unsigned long flags;
209
210 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock_clk_req, flags);
211 qca199x_dev->count_irq_clk_req++;
212 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock_clk_req, flags);
213
214 queue_work(qca199x_dev->my_wq, &qca199x_dev->msm_clock_controll_work);
215
216 return IRQ_HANDLED;
217}
218
219
220static struct gpiomux_setting nfc_clk_on = {
221 .func = GPIOMUX_FUNC_2,
222 .drv = GPIOMUX_DRV_2MA,
223 .pull = GPIOMUX_PULL_NONE,
224};
225static struct gpiomux_setting nfc_clk_on_suspend = {
226 .func = GPIOMUX_FUNC_2,
227 .drv = GPIOMUX_DRV_2MA,
228 .pull = GPIOMUX_PULL_DOWN,
229};
230static struct gpiomux_setting nfc_clk_off = {
231 .func = GPIOMUX_FUNC_GPIO,
232 .drv = GPIOMUX_DRV_2MA,
233 .pull = GPIOMUX_PULL_DOWN,
234};
235
236static void clk_req_update(struct work_struct *work)
237{
238 struct i2c_client *client;
239 struct qca199x_dev *qca199x_dev;
240 int gpio_clk_req_level = 0;
241
242 qca199x_dev = container_of(work, struct qca199x_dev,
243 msm_clock_controll_work);
244 client = qca199x_dev->client;
245
246 /* Read status level of CLK_REQ from NFC Controller, QCA199_x */
247 gpio_clk_req_level = gpio_get_value(qca199x_dev->irq_gpio_clk_req);
248 if (gpio_clk_req_level == 1) {
249 if (qca199x_dev->clk_run == false) {
250 msm_gpiomux_write(qca199x_dev->clk_src_gpio,
251 GPIOMUX_ACTIVE, &nfc_clk_on, NULL);
252 msm_gpiomux_write(qca199x_dev->clk_src_gpio,
253 GPIOMUX_SUSPENDED, &nfc_clk_on_suspend, NULL);
254 qca199x_dev->clk_run = true;
255 }
256 } else{
257 if (qca199x_dev->clk_run == true) {
258 msm_gpiomux_write(qca199x_dev->clk_src_gpio,
259 GPIOMUX_ACTIVE, &nfc_clk_off, NULL);
260 msm_gpiomux_write(qca199x_dev->clk_src_gpio,
261 GPIOMUX_SUSPENDED, &nfc_clk_off, NULL);
262 qca199x_dev->clk_run = false;
263 }
264 }
265}
266
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700267/*
268 * ONLY for FTM-RAW-I2C Mode
269 * Required to instigate a read, which comes from DT layer. This means we need
270 * to spoof an interrupt and send a wake up event.
271 */
272void ftm_raw_trigger_read(struct qca199x_dev *qca199x_dev)
273{
274 unsigned long flags;
275
276 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
277 qca199x_dev->count_irq++;
278 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
279 wake_up(&qca199x_dev->read_wq);
280}
281
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700282static ssize_t nfc_read(struct file *filp, char __user *buf,
283 size_t count, loff_t *offset)
284{
285 struct qca199x_dev *qca199x_dev = filp->private_data;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700286 unsigned char tmp[MAX_BUFFER_SIZE], rd_byte;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700287 unsigned char len[PAYLOAD_HEADER_LENGTH];
288 int total, length, ret;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700289 int ftm_rerr_code;
290 enum ehandler_mode dmode;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700291
292 total = 0;
293 length = 0;
294 if (count > MAX_BUFFER_SIZE)
295 count = MAX_BUFFER_SIZE;
296
297 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100298 memset(tmp, 0, sizeof(tmp));
299 memset(len, 0, sizeof(len));
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700300 dmode = device_mode.handle_flavour;
301 /* FTM-RAW-I2C RD/WR MODE - Special Case */
302 if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
303 (dmode == SOLICITED_FTM_RAW_MODE)) {
304 /* READ */
305 if ((ftm_raw_write_mode == 0) && (ftm_werr_code == 0)) {
306 ftm_rerr_code = i2c_master_recv(qca199x_dev->client,
307 &rd_byte, 1);
308 if (ftm_rerr_code == 0x1)
309 ftm_rerr_code = 0;
310 tmp[0] = (unsigned char)ftm_rerr_code;
311 tmp[1] = rd_byte;
312 total = 2;
313 ret = copy_to_user(buf, tmp, total);
314 }
315 /* WRITE */
316 else if ((ftm_raw_write_mode == 1) || (ftm_werr_code != 0)) {
317 tmp[0] = (unsigned char)ftm_werr_code;
318 total = 1;
319 ret = copy_to_user(buf, tmp, total);
320 } else {
321 /* Invalid case */
322 total = 0;
323 ret = copy_to_user(buf, tmp, total);
324 }
325 mutex_unlock(&qca199x_dev->read_mutex);
326 goto done;
327 }
328
329 /* NORMAL NCI Behaviour */
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700330 /* Read the header */
331 ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
Houston Hoffmana0368172013-12-11 16:55:06 -0800332 /*
333 We ignore all packets of length PAYLOAD_HEADER_LENGTH
334 or less (i.e <=3). In this case return a total length
335 of ZERO. So ALL PACKETS MUST HAVE A PAYLOAD.
336 If ret < 0 then this is an error code.
337 */
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100338 if (ret != PAYLOAD_HEADER_LENGTH) {
Houston Hoffmana0368172013-12-11 16:55:06 -0800339 if (ret < 0)
340 total = ret;
341 else
342 total = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700343 goto err;
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100344 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700345 length = len[PAYLOAD_HEADER_LENGTH - 1];
Houston Hoffmana0368172013-12-11 16:55:06 -0800346 if (length == 0) {
347 ret = 0;
348 total = ret;
349 goto err;
350 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700351 /** make sure full packet fits in the buffer **/
352 if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= count)) {
353 /* Read the packet */
354 ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
355 PAYLOAD_HEADER_LENGTH));
Houston Hoffmana0368172013-12-11 16:55:06 -0800356 total = ret;
357 if (ret < 0)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700358 goto err;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700359 }
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100360
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700361 if (total > 0) {
362 if ((total > count) || copy_to_user(buf, tmp, total)) {
363 dev_err(&qca199x_dev->client->dev,
364 "failed to copy to user space, total = %d\n",
365 total);
366 total = -EFAULT;
367 }
368 }
369err:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700370 mutex_unlock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700371done:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700372 return total;
373}
374
Houston Hoffmana0368172013-12-11 16:55:06 -0800375/*
376 Local routine to read from nfcc buffer. This is called to clear any
377 pending receive messages in the nfcc's read buffer, which may be there
378 following a POR. In this way, the upper layers (Device Transport) will
379 associate the next rsp/ntf nci message with the next nci command to the
380 nfcc. Otherwise, the DT may interpret a ntf from the nfcc as being from
381 the nci core reset command when in fact it was already present in the
382 nfcc read buffer following a POR.
383*/
384
385int nfcc_read_buff_svc(struct qca199x_dev *qca199x_dev)
386{
387 unsigned char tmp[PACKET_MAX_LENGTH];
388 unsigned char len[PAYLOAD_HEADER_LENGTH];
389 int total, length, ret;
390 total = 0;
391 length = 0;
392 mutex_lock(&qca199x_dev->read_mutex);
393 memset(tmp, 0, sizeof(tmp));
394 memset(len, 0, sizeof(len));
395
396 /* Read the header */
397 ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
398 if (ret < PAYLOAD_HEADER_LENGTH) {
399 total = ret;
400 goto leave;
401 }
402 length = len[PAYLOAD_HEADER_LENGTH - 1];
403 if (length == 0) {
404 ret = PAYLOAD_HEADER_LENGTH;
405 total = ret;
406 goto leave;
407 }
408 /** make sure full packet fits in the buffer **/
409 if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= PACKET_MAX_LENGTH)) {
410 /* Read the packet */
411 ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
412 PAYLOAD_HEADER_LENGTH));
413 total = ret;
414 }
415leave:
416 mutex_unlock(&qca199x_dev->read_mutex);
417 return total;
418}
419
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700420static ssize_t nfc_write(struct file *filp, const char __user *buf,
421 size_t count, loff_t *offset)
422{
423 struct qca199x_dev *qca199x_dev = filp->private_data;
424 char tmp[MAX_BUFFER_SIZE];
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700425 int ret = 0;
426 enum ehandler_mode dmode;
Houston Hoffmana0368172013-12-11 16:55:06 -0800427 int nfcc_buffer = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700428
429 if (count > MAX_BUFFER_SIZE) {
430 dev_err(&qca199x_dev->client->dev, "out of memory\n");
431 return -ENOMEM;
432 }
433 if (copy_from_user(tmp, buf, count)) {
434 dev_err(&qca199x_dev->client->dev,
435 "nfc-nci write: failed to copy from user space\n");
436 return -EFAULT;
437 }
Houston Hoffmana0368172013-12-11 16:55:06 -0800438 /*
439 A catch for when the DT is sending the initial NCI write
440 following a hardware POR. In this case we should clear any
441 pending messages in nfcc buffer and open the interrupt gate
442 for new messages coming from the nfcc.
443 */
444 if ((qca199x_dev->sent_first_nci_write == false) &&
445 (qca199x_dev->irq_enabled == false)) {
446 /* check rsp/ntf from nfcc read-side buffer */
447 nfcc_buffer = nfcc_read_buff_svc(qca199x_dev);
448 /* There has been an error while reading from nfcc */
449 if (nfcc_buffer < 0) {
450 dev_err(&qca199x_dev->client->dev,
451 "nfc-nci write: error while servicing nfcc read buffer\n");
452 }
453 qca199x_dev->sent_first_nci_write = true;
454 qca199x_enable_irq(qca199x_dev);
455 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700456 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700457 dmode = device_mode.handle_flavour;
458 /* FTM-DIRECT-I2C RD/WR MODE */
Houston Hoffmana0368172013-12-11 16:55:06 -0800459 /* This is a special FTM-i2c mode case, where tester is not using NCI */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700460 if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
461 (dmode == SOLICITED_FTM_RAW_MODE)) {
462 /* Read From Register */
463 if (count == 1) {
464 ftm_raw_write_mode = 0;
465 ret = i2c_master_send(qca199x_dev->client, tmp, count);
466 if (ret == 1)
467 ftm_werr_code = 0;
468 else
469 ftm_werr_code = ret;
470 ftm_raw_trigger_read(qca199x_dev);
471 }
472 /* Write to Register */
473 if (count == 2) {
474 ftm_raw_write_mode = 1;
475 ret = i2c_master_send(qca199x_dev->client, tmp, count);
476 if (ret == 2)
477 ftm_werr_code = 0;
478 else
479 ftm_werr_code = ret;
480 ftm_raw_trigger_read(qca199x_dev);
481 }
482 } else {
483 /* NORMAL NCI behaviour - NB :
484 We can be in FTM mode here also */
485 ret = i2c_master_send(qca199x_dev->client, tmp, count);
486 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700487 if (ret != count) {
488 dev_err(&qca199x_dev->client->dev,
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700489 "NFC: failed to write %d\n", ret);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700490 ret = -EIO;
491 }
492 mutex_unlock(&qca199x_dev->read_mutex);
493
494 return ret;
495}
496
497static int nfc_open(struct inode *inode, struct file *filp)
498{
499 int ret = 0;
500
501 struct qca199x_dev *qca199x_dev = container_of(filp->private_data,
502 struct qca199x_dev,
503 qca199x_device);
504
505 filp->private_data = qca199x_dev;
506 qca199x_init_stat(qca199x_dev);
Houston Hoffman17f2dc52014-01-29 08:15:06 -0800507 /* Enable interrupts from NFCC NFC_INT new NCI data available */
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700508 qca199x_enable_irq(qca199x_dev);
Houston Hoffman17f2dc52014-01-29 08:15:06 -0800509
510 if ((!strcmp(qca199x_dev->clk_src_name, "GPCLK")) ||
511 (!strcmp(qca199x_dev->clk_src_name, "GPCLK2"))) {
512 /* Enable interrupts from NFCC CLK_REQ */
513 qca199x_enable_irq_clk_req(qca199x_dev);
514 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700515 dev_dbg(&qca199x_dev->client->dev,
516 "%d,%d\n", imajor(inode), iminor(inode));
517 return ret;
518}
519
520/*
521 * Wake/Sleep Mode
522 */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700523int nfcc_wake(int level, struct file *filp)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700524{
525 int r = 0;
526 unsigned char raw_nci_sleep[] = {0x2F, 0x03, 0x00};
527 /* Change slave address to 0xE */
528 unsigned char raw_nci_wake[] = {0x10, 0x0F};
529 unsigned short slave_addr = 0xE;
530 unsigned short curr_addr;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700531 struct qca199x_dev *qca199x_dev = filp->private_data;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700532
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700533 dev_dbg(&qca199x_dev->client->dev, "nfcc_wake: %s: info: %p\n",
534 __func__, qca199x_dev);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700535
536 if (level == NFCC_SLEEP) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700537 r = i2c_master_send(qca199x_dev->client, &raw_nci_sleep[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700538 sizeof(raw_nci_sleep));
539
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700540 r = sizeof(raw_nci_sleep);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700541 if (r != sizeof(raw_nci_sleep))
542 return -EMSGSIZE;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700543 qca199x_dev->state = NFCC_STATE_NORMAL_SLEEP;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700544 } else {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700545 curr_addr = qca199x_dev->client->addr;
546 qca199x_dev->client->addr = slave_addr;
547 r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700548 sizeof(raw_nci_wake));
549 /* Restore original NFCC slave I2C address */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700550 qca199x_dev->client->addr = curr_addr;
551 r = sizeof(raw_nci_wake);
552 if (r != sizeof(raw_nci_wake))
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700553 return -EMSGSIZE;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700554 qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700555 }
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700556
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700557 return r;
558}
559
560/*
561 * Inside nfc_ioctl_power_states
562 *
563 * @brief ioctl functions
564 *
565 *
566 * Device control
567 * remove control via ioctl
568 * (arg = 0): NFC_DISABLE GPIO = 0
569 * (arg = 1): NFC_DISABLE GPIO = 1
570 * NOT USED (arg = 2): FW_DL GPIO = 0
571 * NOT USED (arg = 3): FW_DL GPIO = 1
572 * (arg = 4): NFCC_WAKE = 1
573 * (arg = 5): NFCC_WAKE = 0
574 *
575 *
576 */
577int nfc_ioctl_power_states(struct file *filp, unsigned int cmd,
578 unsigned long arg)
579{
580 int r = 0;
581 struct qca199x_dev *qca199x_dev = filp->private_data;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700582
583 if (arg == 0) {
Houston Hoffmana0368172013-12-11 16:55:06 -0800584 r = qca199x_clock_select(qca199x_dev);
585 if (r < 0)
586 goto err_req;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700587 gpio_set_value(qca199x_dev->dis_gpio, 0);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700588 r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
589 if (r) {
590 dev_err(&qca199x_dev->client->dev,
591 "unable to set direction for gpio [%d]\n",
592 qca199x_dev->dis_gpio);
593 goto err_req;
594 }
595 gpio_set_value(qca199x_dev->dis_gpio, 0);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100596 msleep(20);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700597 } else if (arg == 1) {
Houston Hoffmana0368172013-12-11 16:55:06 -0800598 /*
599 We are attempting a hardware reset so let us disable
600 interrupts to avoid spurious notifications to upper
601 layers.
602 */
603 qca199x_disable_irq(qca199x_dev);
604 /* Deselection of clock */
605 r = qca199x_clock_deselect(qca199x_dev);
606 if (r < 0)
607 goto err_req;
608 /*
609 Also, set flag for initial NCI write following resetas
610 may wish to do some house keeping. Ensure no pending
611 messages in NFCC buffers which may be wrongly
612 construed as response to initial message
613 */
614 qca199x_dev->sent_first_nci_write = false;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700615 gpio_set_value(qca199x_dev->dis_gpio, 0);
616 r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
617 if (r) {
618 dev_err(&qca199x_dev->client->dev,
619 "unable to set direction for gpio [%d]\n",
620 qca199x_dev->dis_gpio);
621 goto err_req;
622 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700623 gpio_set_value(qca199x_dev->dis_gpio, 1);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100624 usleep(1000);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700625 } else if (arg == 2) {
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100626 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100627 r = nfcc_initialise(qca199x_dev->client, 0xE);
Houston Hoffmana0368172013-12-11 16:55:06 -0800628 /* Also reset first NCI write */
629 qca199x_dev->sent_first_nci_write = false;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100630 mutex_unlock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100631 if (r) {
632 dev_err(&qca199x_dev->client->dev,
Houston Hoffmana0368172013-12-11 16:55:06 -0800633 "nfc_ioctl_power_states: request nfcc initialise failed\n");
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100634 goto err_req;
635 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700636 } else if (arg == 3) {
637 msleep(20);
638 } else if (arg == 4) {
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100639 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700640 nfcc_wake(NFCC_WAKE, filp);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100641 mutex_unlock(&qca199x_dev->read_mutex);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700642 } else if (arg == 5) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700643 nfcc_wake(NFCC_SLEEP, filp);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700644 } else {
645 r = -ENOIOCTLCMD;
646 }
647
648err_req:
649 return r;
650}
651
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700652/*
653 * Inside nfc_ioctl_nfcc_mode
654 *
655 * @brief nfc_ioctl_nfcc_mode
656 *
657 * (arg = 0) ; NORMAL_MODE - Standard mode, unsolicited read behaviour
658 * (arg = 1) ; SOLICITED_MODE - As above but reads are solicited from User Land
659 * (arg = 2) ; UNSOLICITED_FTM_RAW MODE - NORMAL_MODE but messages from FTM and
660 * not NCI Host.
661 * (arg = 2) ; SOLICITED_FTM_RAW_MODE - As SOLICITED_MODE but messages from FTM
662 * and not NCI Host.
663 *
664 *
665 *
666 */
667int nfc_ioctl_nfcc_mode(struct file *filp, unsigned int cmd, unsigned long arg)
668{
669 int retval = 0;
670
671 static unsigned short nci_addr;
672 struct qca199x_dev *qca199x_dev = filp->private_data;
673 struct qca199x_platform_data *platform_data;
674
675 platform_data = qca199x_dev->client->dev.platform_data;
676
677 if (arg == 0) {
678 device_mode.handle_flavour = UNSOLICITED_MODE;
679 qca199x_dev->client->addr = NCI_I2C_SLAVE;
680 /* enable interrupts again */
681 qca199x_enable_irq(qca199x_dev);
682 } else if (arg == 1) {
683 device_mode.handle_flavour = SOLICITED_MODE;
684 qca199x_dev->client->addr = qca199x_dev->client->addr;
685 /* enable interrupts again */
686 qca199x_enable_irq(qca199x_dev);
687 } else if (arg == 2) {
688 device_mode.handle_flavour = UNSOLICITED_FTM_RAW_MODE;
689 nci_addr = qca199x_dev->client->addr;
690 /* replace with new client slave address*/
691 qca199x_dev->client->addr = 0xE;
692 /* We also need to disable interrupts */
693 qca199x_disable_irq(qca199x_dev);
694 } else if (arg == 3) {
695 device_mode.handle_flavour = SOLICITED_FTM_RAW_MODE;
696 nci_addr = qca199x_dev->client->addr;
697 /* replace with new client slave address*/
698 qca199x_dev->client->addr = 0xE;
699 /* We also need to disable interrupts */
700 qca199x_disable_irq(qca199x_dev);
701 } else {
702 device_mode.handle_flavour = UNSOLICITED_MODE;
703 qca199x_dev->client->addr = NCI_I2C_SLAVE;
704 }
705 return retval;
706}
707
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700708/*
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100709 * Inside nfc_ioctl_nfcc_version
710 *
711 * @brief nfc_ioctl_nfcc_version
712 *
713 *
714 */
715int nfc_ioctl_nfcc_version(struct file *filp, unsigned int cmd,
716 unsigned long arg)
717{
718 int r = 0;
719 unsigned short slave_addr = 0xE;
720 unsigned short curr_addr;
721
722 unsigned char raw_chip_version_addr = 0x00;
723 unsigned char raw_chip_rev_id_addr = 0x9C;
724 unsigned char raw_chip_version = 0xFF;
725
726 struct qca199x_dev *qca199x_dev = filp->private_data;
727 struct qca199x_platform_data *platform_data;
728
729 platform_data = qca199x_dev->client->dev.platform_data;
730
731 if (arg == 0) {
732 curr_addr = qca199x_dev->client->addr;
733 qca199x_dev->client->addr = slave_addr;
734 r = nfc_i2c_write(qca199x_dev->client,
735 &raw_chip_version_addr, 1);
736 if (r < 0)
737 goto invalid_wr;
738 usleep(10);
739 r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
740 /* Restore original NFCC slave I2C address */
741 qca199x_dev->client->addr = curr_addr;
742 }
743 if (arg == 1) {
744 curr_addr = qca199x_dev->client->addr;
745 qca199x_dev->client->addr = slave_addr;
746 r = nfc_i2c_write(qca199x_dev->client,
747 &raw_chip_rev_id_addr, 1);
748 if (r < 0)
749 goto invalid_wr;
750 usleep(10);
751 r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
752 /* Restore original NFCC slave I2C address */
753 qca199x_dev->client->addr = curr_addr;
754 }
755
756 return raw_chip_version;
757invalid_wr:
758 raw_chip_version = 0xFF;
759 dev_err(&qca199x_dev->client->dev,
760 "\nNFCC_INVALID_CHIP_VERSION = %d\n", raw_chip_version);
761 return raw_chip_version;
762}
763
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100764/*
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700765 * Inside nfc_ioctl_kernel_logging
766 *
767 * @brief nfc_ioctl_kernel_logging
768 *
769 * (arg = 0) ; NO_LOGGING
770 * (arg = 1) ; COMMS_LOGGING - BASIC LOGGING - Mainly just comms over I2C
771 * (arg = 2) ; FULL_LOGGING - ENABLE ALL - DBG messages for handlers etc.
772 * ; ! Be aware as amount of logging could impact behaviour !
773 *
774 *
775 */
776int nfc_ioctl_kernel_logging(unsigned long arg, struct file *filp)
777{
778 int retval = 0;
779 struct qca199x_dev *qca199x_dev = container_of(filp->private_data,
780 struct qca199x_dev,
781 qca199x_device);
782 if (arg == 0) {
783 dev_dbg(&qca199x_dev->client->dev,
784 "nfc_ioctl_kernel_logging : level = NO_LOGGING\n");
785 logging_level = 0;
786 } else if (arg == 1) {
787 dev_dbg(&qca199x_dev->client->dev,
788 "nfc_ioctl_kernel_logging: level = COMMS_LOGGING only\n");
789 logging_level = 1;
790 } else if (arg == 2) {
791 dev_dbg(&qca199x_dev->client->dev,
792 "nfc_ioctl_kernel_logging: level = FULL_LOGGING\n");
793 logging_level = 2;
794 }
795 return retval;
796}
797
798static long nfc_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)
799{
800 int r = 0;
801
802 switch (cmd) {
803
804 case NFC_SET_PWR:
805 nfc_ioctl_power_states(pfile, cmd, arg);
806 break;
807 case NFCC_MODE:
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700808 nfc_ioctl_nfcc_mode(pfile, cmd, arg);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700809 break;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100810 case NFCC_VERSION:
811 r = nfc_ioctl_nfcc_version(pfile, cmd, arg);
812 break;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700813 case NFC_KERNEL_LOGGING_MODE:
814 nfc_ioctl_kernel_logging(arg, pfile);
815 break;
816 case SET_RX_BLOCK:
817 break;
818 case SET_EMULATOR_TEST_POINT:
819 break;
820 default:
821 r = -ENOIOCTLCMD;
822 }
823 return r;
824}
825
826static const struct file_operations nfc_dev_fops = {
827 .owner = THIS_MODULE,
828 .llseek = no_llseek,
829 .poll = nfc_poll,
830 .read = nfc_read,
831 .write = nfc_write,
832 .open = nfc_open,
833 .unlocked_ioctl = nfc_ioctl
834};
835
836void dumpqca1990(struct i2c_client *client)
837{
838 int r = 0;
839 int i = 0;
840 unsigned char raw_reg_rd = {0x0};
841 unsigned short temp_addr;
842
843 temp_addr = client->addr;
844 client->addr = 0x0E;
845
846 for (i = 0; i < MAX_QCA_REG; i++) {
847 raw_reg_rd = i;
848 if (((i >= 0x0) && (i < 0x4)) || ((i > 0x7) && (i < 0xA)) ||
849 ((i > 0xF) && (i < 0x12)) || ((i > 0x39) && (i < 0x4d)) ||
850 ((i > 0x69) && (i < 0x74)) || (i == 0x18) || (i == 0x30) ||
851 (i == 0x58)) {
852 r = nfc_i2c_write(client, &raw_reg_rd, 1);
853 msleep(20);
854 r = i2c_master_recv(client, &raw_reg_rd, 1);
855 }
856 }
857 client->addr = temp_addr;
858}
859
860static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len)
861{
862 int r;
863
864 r = i2c_master_send(client, buf, len);
865 dev_dbg(&client->dev, "send: %d\n", r);
866 if (r == -EREMOTEIO) { /* Retry, chip was in standby */
867 usleep_range(6000, 10000);
868 r = i2c_master_send(client, buf, len);
869 dev_dbg(&client->dev, "send2: %d\n", r);
870 }
871 if (r != len)
872 return -EREMOTEIO;
873
874 return r;
875}
876
Houston Hoffmanc108e8f2014-01-10 16:12:16 -0800877/* Check for availability of qca199x_ NFC controller hardware */
878static int nfcc_hw_check(struct i2c_client *client, unsigned short curr_addr)
879{
880 int r = 0;
881 unsigned char buf = 0;
882
883 client->addr = curr_addr;
884 /* Set-up Addr 0. No data written */
885 r = i2c_master_send(client, &buf, 1);
886 if (r < 0)
887 goto err_presence_check;
888 buf = 0;
889 /* Read back from Addr 0 */
890 r = i2c_master_recv(client, &buf, 1);
891 if (r < 0)
892 goto err_presence_check;
893
894 r = 0;
895 return r;
896
897err_presence_check:
898 r = -ENXIO;
899 dev_err(&client->dev,
900 "nfc-nci nfcc_presence check - no NFCC available\n");
901 return r;
902}
903/* Initialise qca199x_ NFC controller hardware */
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100904static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700905{
906 int r = 0;
907 unsigned char raw_1p8_CONTROL_011[] = {0x11, XTAL_CLOCK};
908 unsigned char raw_1P8_CONTROL_010[] = {0x10, PWR_EN};
909 unsigned char raw_1P8_X0_0B0[] = {0xB0, (FREQ_SEL)};
910 unsigned char raw_slave1[] = {0x09, NCI_I2C_SLAVE};
911 unsigned char raw_slave2[] = {0x8, 0x10};
912 unsigned char raw_s73[] = {0x73, 0x02};
913 unsigned char raw_slave1_rd = {0x0};
914 unsigned char raw_1P8_PAD_CFG_CLK_REQ[] = {0xA5, 0x1};
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700915 unsigned char raw_1P8_PAD_CFG_PWR_REQ[] = {0xA7, 0x1};
916 unsigned char buf = 0;
Houston Hoffmana0368172013-12-11 16:55:06 -0800917 bool core_reset_completed = false;
918 unsigned char rsp[6];
919 int time_taken = 0;
920 int ret = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700921
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700922 client->addr = curr_addr;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700923 r = i2c_master_send(client, &buf, 1);
Houston Hoffmana0368172013-12-11 16:55:06 -0800924 if (r < 0)
925 goto err_init;
926
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700927 buf = 0;
928 r = i2c_master_recv(client, &buf, 1);
Houston Hoffmana0368172013-12-11 16:55:06 -0800929 if (r < 0)
930 goto err_init;
931
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700932 if (0x10 != (0x10 & buf)) {
933 RAW(s73, 0x02);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700934
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700935 r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
Houston Hoffmana0368172013-12-11 16:55:06 -0800936 if (r < 0)
937 goto err_init;
938
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700939 usleep(1000);
940 RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700941
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700942 r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700943 sizeof(raw_1p8_CONTROL_011));
Houston Hoffmana0368172013-12-11 16:55:06 -0800944 if (r < 0)
945 goto err_init;
946
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700947 usleep(1000);
948 RAW(1P8_CONTROL_010, (0x8));
949 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700950 sizeof(raw_1P8_CONTROL_010));
Houston Hoffmana0368172013-12-11 16:55:06 -0800951 if (r < 0)
952 goto err_init;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700953
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700954 usleep(10000); /* 10ms wait */
955 RAW(1P8_CONTROL_010, (0xC));
956 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
957 sizeof(raw_1P8_CONTROL_010));
Houston Hoffmana0368172013-12-11 16:55:06 -0800958 if (r < 0)
959 goto err_init;
960
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700961 usleep(100); /* 100uS wait */
962 RAW(1P8_X0_0B0, (FREQ_SEL_19));
963 r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0],
964 sizeof(raw_1P8_X0_0B0));
Houston Hoffmana0368172013-12-11 16:55:06 -0800965 if (r < 0)
966 goto err_init;
967
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700968 usleep(1000);
969
970 /* PWR_EN = 1 */
971 RAW(1P8_CONTROL_010, (0xd));
972 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
973 sizeof(raw_1P8_CONTROL_010));
Houston Hoffmana0368172013-12-11 16:55:06 -0800974 if (r < 0)
975 goto err_init;
976
977
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700978 usleep(20000); /* 20ms wait */
979 /* LS_EN = 1 */
980 RAW(1P8_CONTROL_010, 0xF);
981 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
982 sizeof(raw_1P8_CONTROL_010));
Houston Hoffmana0368172013-12-11 16:55:06 -0800983 if (r < 0)
984 goto err_init;
985
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700986 usleep(20000); /* 20ms wait */
987
988 /* Enable the PMIC clock */
989 RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
990 r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700991 sizeof(raw_1P8_PAD_CFG_CLK_REQ));
Houston Hoffmana0368172013-12-11 16:55:06 -0800992 if (r < 0)
993 goto err_init;
994
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700995 usleep(1000);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700996
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700997 RAW(1P8_PAD_CFG_PWR_REQ, (0x1));
998 r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_PWR_REQ[0],
999 sizeof(raw_1P8_PAD_CFG_PWR_REQ));
Houston Hoffmana0368172013-12-11 16:55:06 -08001000 if (r < 0)
1001 goto err_init;
1002
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -07001003 usleep(1000);
1004
1005 RAW(slave2, 0x10);
1006 r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
Houston Hoffmana0368172013-12-11 16:55:06 -08001007 if (r < 0)
1008 goto err_init;
1009
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -07001010 usleep(1000);
1011
1012 RAW(slave1, NCI_I2C_SLAVE);
1013 r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
Houston Hoffmana0368172013-12-11 16:55:06 -08001014 if (r < 0)
1015 goto err_init;
1016
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -07001017 usleep(1000);
1018
1019 /* QCA199x NFCC CPU should now boot... */
1020 r = i2c_master_recv(client, &raw_slave1_rd, 1);
1021 /* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
1022 client->addr = NCI_I2C_SLAVE;
Houston Hoffmana0368172013-12-11 16:55:06 -08001023
1024 /*
1025 Start with small delay and then we will poll until we
1026 get a core reset notification - This is time for chip
1027 & NFCC controller to come-up.
1028 */
1029 usleep(1000); /* 1 ms */
1030
1031 do {
1032 ret = i2c_master_recv(client, rsp, 5);
1033 /* Found core reset notification */
1034 if (((rsp[0] == CORE_RESET_RSP_GID) &&
1035 (rsp[1] == CORE_RESET_OID) &&
1036 (rsp[2] == CORE_RST_NTF_LENGTH))
1037 || time_taken == NTF_TIMEOUT) {
1038 core_reset_completed = true;
1039 }
1040 usleep(10); /* 10us sleep before retry */
1041 time_taken++;
1042 } while (!core_reset_completed);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -07001043 r = 0;
1044 } else {
Houston Hoffmana0368172013-12-11 16:55:06 -08001045 goto err_init;
1046 }
1047 return r;
1048err_init:
1049 r = 1;
1050 dev_err(&client->dev,
1051 "nfc-nci nfcc_initialise: failed. Check Hardware\n");
1052 return r;
1053}
1054/*
1055 Routine to Select clocks
1056*/
1057static int qca199x_clock_select(struct qca199x_dev *qca199x_dev)
1058{
1059 int r = 0;
1060
1061 if (!strcmp(qca199x_dev->clk_src_name, "BBCLK2")) {
1062 qca199x_dev->s_clk =
1063 clk_get(&qca199x_dev->client->dev, "ref_clk");
1064 if (qca199x_dev->s_clk == NULL)
1065 goto err_invalid_dis_gpio;
1066 } else if (!strcmp(qca199x_dev->clk_src_name, "RFCLK3")) {
1067 qca199x_dev->s_clk =
1068 clk_get(&qca199x_dev->client->dev, "ref_clk_rf");
1069 if (qca199x_dev->s_clk == NULL)
1070 goto err_invalid_dis_gpio;
1071 } else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK")) {
1072 if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
1073 qca199x_dev->s_clk =
1074 clk_get(&qca199x_dev->client->dev, "core_clk");
1075 if (qca199x_dev->s_clk == NULL)
1076 goto err_invalid_dis_gpio;
1077 } else {
1078 goto err_invalid_dis_gpio;
1079 }
1080 } else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK2")) {
1081 if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
1082 qca199x_dev->s_clk =
1083 clk_get(&qca199x_dev->client->dev, "core_clk_pvt");
1084 if (qca199x_dev->s_clk == NULL)
1085 goto err_invalid_dis_gpio;
1086 } else {
1087 goto err_invalid_dis_gpio;
1088 }
1089 } else {
1090 qca199x_dev->s_clk = NULL;
1091 goto err_invalid_dis_gpio;
1092 }
1093 if (qca199x_dev->clk_run == false) {
Houston Hoffmanfa9a38b2014-01-24 02:09:53 -08001094 /* Set clock rate */
1095 if ((!strcmp(qca199x_dev->clk_src_name, "GPCLK")) ||
1096 (!strcmp(qca199x_dev->clk_src_name, "GPCLK2"))) {
1097 r = clk_set_rate(qca199x_dev->s_clk, NFC_RF_CLK_FREQ);
1098 if (r)
1099 goto err_invalid_clk;
1100 }
1101
Houston Hoffmana0368172013-12-11 16:55:06 -08001102 r = clk_prepare_enable(qca199x_dev->s_clk);
1103 if (r)
1104 goto err_invalid_clk;
1105 qca199x_dev->clk_run = true;
1106 }
1107 r = 0;
1108 return r;
1109
1110err_invalid_clk:
1111 r = -1;
1112 return r;
1113err_invalid_dis_gpio:
1114 r = -2;
1115 return r;
1116}
1117/*
1118 Routine to De-Select clocks
1119*/
1120
1121static int qca199x_clock_deselect(struct qca199x_dev *qca199x_dev)
1122{
1123 int r = -1;
1124 if (qca199x_dev->s_clk != NULL) {
1125 if (qca199x_dev->clk_run == true) {
1126 clk_disable_unprepare(qca199x_dev->s_clk);
1127 qca199x_dev->clk_run = false;
1128 }
1129 return 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001130 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001131 return r;
1132}
1133
1134static int nfc_parse_dt(struct device *dev, struct qca199x_platform_data *pdata)
1135{
1136 int r = 0;
1137 struct device_node *np = dev->of_node;
1138
1139 r = of_property_read_u32(np, "reg", &pdata->reg);
1140 if (r)
1141 return -EINVAL;
1142
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001143 pdata->dis_gpio = of_get_named_gpio(np, "qcom,dis-gpio", 0);
1144 if ((!gpio_is_valid(pdata->dis_gpio)))
1145 return -EINVAL;
1146
1147 pdata->irq_gpio = of_get_named_gpio(np, "qcom,irq-gpio", 0);
1148 if ((!gpio_is_valid(pdata->irq_gpio)))
1149 return -EINVAL;
1150
Houston Hoffmana0368172013-12-11 16:55:06 -08001151 r = of_property_read_string(np, "qcom,clk-src", &pdata->clk_src_name);
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001152
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001153 if (strcmp(pdata->clk_src_name, "GPCLK2")) {
1154 r = of_property_read_u32(np, "qcom,clk-gpio",
1155 &pdata->clkreq_gpio);
1156 if (r)
1157 return -EINVAL;
1158 }
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001159
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001160 if ((!strcmp(pdata->clk_src_name, "GPCLK")) ||
1161 (!strcmp(pdata->clk_src_name, "GPCLK2"))) {
1162 pdata->clk_src_gpio = of_get_named_gpio(np,
1163 "qcom,clk-src-gpio", 0);
1164 if ((!gpio_is_valid(pdata->clk_src_gpio)))
1165 return -EINVAL;
1166 pdata->irq_gpio_clk_req = of_get_named_gpio(np,
1167 "qcom,clk-req-gpio", 0);
1168 if ((!gpio_is_valid(pdata->irq_gpio_clk_req)))
1169 return -EINVAL;
1170 }
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001171 if (r)
1172 return -EINVAL;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001173 return r;
1174}
1175
1176static int qca199x_probe(struct i2c_client *client,
1177 const struct i2c_device_id *id)
1178{
1179 int r = 0;
1180 int irqn = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001181 struct device_node *node = client->dev.of_node;
1182 struct qca199x_platform_data *platform_data;
1183 struct qca199x_dev *qca199x_dev;
1184
1185 if (client->dev.of_node) {
1186 platform_data = devm_kzalloc(&client->dev,
1187 sizeof(struct qca199x_platform_data), GFP_KERNEL);
1188 if (!platform_data) {
1189 dev_err(&client->dev,
1190 "nfc-nci probe: Failed to allocate memory\n");
1191 return -ENOMEM;
1192 }
1193 r = nfc_parse_dt(&client->dev, platform_data);
1194 if (r)
1195 return r;
1196 } else {
1197 platform_data = client->dev.platform_data;
1198 }
1199 if (!platform_data)
1200 return -EINVAL;
1201 dev_dbg(&client->dev,
1202 "nfc-nci probe: %s, inside nfc-nci flags = %x\n",
1203 __func__, client->flags);
1204 if (platform_data == NULL) {
1205 dev_err(&client->dev, "nfc-nci probe: failed\n");
1206 return -ENODEV;
1207 }
1208 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1209 dev_err(&client->dev, "nfc-nci probe: need I2C_FUNC_I2C\n");
1210 return -ENODEV;
1211 }
1212 qca199x_dev = kzalloc(sizeof(*qca199x_dev), GFP_KERNEL);
1213 if (qca199x_dev == NULL) {
1214 dev_err(&client->dev,
1215 "nfc-nci probe: failed to allocate memory for module data\n");
1216 return -ENOMEM;
1217 }
Houston Hoffmana0368172013-12-11 16:55:06 -08001218 qca199x_dev->client = client;
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001219
1220 /*
1221 * To be efficient we need to test whether nfcc hardware is physically
1222 * present before attempting further hardware initialisation.
1223 * For this we need to be sure the device is in ULPM state by
1224 * setting disable line low early on.
1225 *
1226 */
1227
1228
1229 if (gpio_is_valid(platform_data->dis_gpio)) {
1230 r = gpio_request(platform_data->dis_gpio, "nfc_reset_gpio");
1231 if (r) {
1232 dev_err(&client->dev,
1233 "NFC: unable to request gpio [%d]\n",
1234 platform_data->dis_gpio);
1235 goto err_free_dev;
1236 }
1237 r = gpio_direction_output(platform_data->dis_gpio, 1);
1238 if (r) {
1239 dev_err(&client->dev,
1240 "NFC: unable to set direction for gpio [%d]\n",
1241 platform_data->dis_gpio);
1242 goto err_dis_gpio;
1243 }
1244 } else {
1245 dev_err(&client->dev, "dis gpio not provided\n");
1246 goto err_free_dev;
1247 }
1248
1249 /* Put device in ULPM */
1250 gpio_set_value(platform_data->dis_gpio, 0);
1251 r = nfcc_hw_check(client, platform_data->reg);
1252 if (r) {
1253 /* We don't think there is hardware but just in case HPD */
1254 gpio_set_value(platform_data->dis_gpio, 1);
1255 goto err_dis_gpio;
1256 }
1257
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001258 if (gpio_is_valid(platform_data->irq_gpio)) {
1259 r = gpio_request(platform_data->irq_gpio, "nfc_irq_gpio");
1260 if (r) {
1261 dev_err(&client->dev, "unable to request gpio [%d]\n",
1262 platform_data->irq_gpio);
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001263 goto err_dis_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001264 }
1265 r = gpio_direction_input(platform_data->irq_gpio);
1266 if (r) {
1267
1268 dev_err(&client->dev,
1269 "unable to set direction for gpio [%d]\n",
1270 platform_data->irq_gpio);
1271 goto err_irq;
1272 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001273 irqn = gpio_to_irq(platform_data->irq_gpio);
1274 if (irqn < 0) {
1275 r = irqn;
1276 goto err_irq;
1277 }
1278 client->irq = irqn;
1279
1280 } else {
1281 dev_err(&client->dev, "irq gpio not provided\n");
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001282 goto err_dis_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001283 }
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001284 /* Interrupt from NFCC CLK_REQ to handle REF_CLK
1285 o/p gating/selection */
1286 if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
1287 (!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
1288 if (gpio_is_valid(platform_data->irq_gpio_clk_req)) {
1289 r = gpio_request(platform_data->irq_gpio_clk_req,
1290 "nfc_irq_gpio_clk_en");
1291 if (r) {
1292 dev_err(&client->dev, "unable to request CLK_EN gpio [%d]\n",
1293 platform_data->irq_gpio_clk_req);
1294 goto err_irq;
1295 }
1296 r = gpio_direction_input(
1297 platform_data->irq_gpio_clk_req);
1298 if (r) {
1299 dev_err(&client->dev,
1300 "unable to set direction for CLK_EN gpio [%d]\n",
1301 platform_data->irq_gpio_clk_req);
1302 goto err_irq_clk;
1303 }
1304 gpio_to_irq(0);
1305 irqn = gpio_to_irq(platform_data->irq_gpio_clk_req);
1306 if (irqn < 0) {
1307 r = irqn;
1308 goto err_irq_clk;
1309 }
1310 platform_data->clk_req_irq_num = irqn;
1311 } else {
1312 dev_err(&client->dev, "irq CLK_EN gpio not provided\n");
1313 goto err_irq;
1314 }
1315 }
Houston Hoffmana0368172013-12-11 16:55:06 -08001316 /* Get the clock source name and gpio from from Device Tree */
1317 qca199x_dev->clk_src_name = platform_data->clk_src_name;
1318 qca199x_dev->clk_src_gpio = platform_data->clk_src_gpio;
1319 qca199x_dev->clk_run = false;
1320 r = qca199x_clock_select(qca199x_dev);
1321 if (r != 0) {
1322 if (r == -1)
1323 goto err_clk;
1324 else
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001325 goto err_irq_clk;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001326 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001327
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001328 if (strcmp(platform_data->clk_src_name, "GPCLK2")) {
1329 platform_data->clkreq_gpio =
1330 of_get_named_gpio(node, "qcom,clk-gpio", 0);
1331
1332 if (gpio_is_valid(platform_data->clkreq_gpio)) {
1333 r = gpio_request(platform_data->clkreq_gpio,
1334 "nfc_clkreq_gpio");
1335 if (r) {
1336 dev_err(&client->dev, "unable to request gpio [%d]\n",
1337 platform_data->clkreq_gpio);
1338 goto err_clkreq_gpio;
1339 }
1340 r = gpio_direction_input(platform_data->clkreq_gpio);
1341 if (r) {
1342 dev_err(&client->dev,
1343 "unable to set direction for gpio [%d]\n",
1344 platform_data->clkreq_gpio);
1345 goto err_clkreq_gpio;
1346 }
1347 } else {
1348 dev_err(&client->dev, "clkreq gpio not provided\n");
1349 goto err_clk;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001350 }
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001351 qca199x_dev->clkreq_gpio = platform_data->clkreq_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001352 }
1353 qca199x_dev->dis_gpio = platform_data->dis_gpio;
1354 qca199x_dev->irq_gpio = platform_data->irq_gpio;
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001355 if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
1356 (!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
1357 qca199x_dev->irq_gpio_clk_req =
1358 platform_data->irq_gpio_clk_req;
1359 qca199x_dev->clk_req_irq_num =
1360 platform_data->clk_req_irq_num;
1361 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001362
1363 /* init mutex and queues */
1364 init_waitqueue_head(&qca199x_dev->read_wq);
1365 mutex_init(&qca199x_dev->read_mutex);
1366 spin_lock_init(&qca199x_dev->irq_enabled_lock);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001367 spin_lock_init(&qca199x_dev->irq_enabled_lock_clk_req);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001368
1369 qca199x_dev->qca199x_device.minor = MISC_DYNAMIC_MINOR;
1370 qca199x_dev->qca199x_device.name = "nfc-nci";
1371 qca199x_dev->qca199x_device.fops = &nfc_dev_fops;
1372
1373 r = misc_register(&qca199x_dev->qca199x_device);
1374 if (r) {
1375 dev_err(&client->dev, "misc_register failed\n");
1376 goto err_misc_register;
1377 }
1378
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001379
1380 /*
1381 * Reboot the NFCC now that all resources are ready
1382 *
1383 * The NFCC takes time to transition between power states.
1384 * We wait 20uS for the NFCC to shutdown. (HPD)
1385 * We wait 100uS for the NFCC to boot into ULPM.
1386 */
1387 gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
1388 msleep(20);
1389 gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
1390 msleep(100);
1391
1392
1393 /* Here we perform a second presence check. */
1394 r = nfcc_hw_check(client, platform_data->reg);
1395 if (r) {
1396 /* We don't think there is hardware but just in case HPD */
1397 gpio_set_value(platform_data->dis_gpio, 1);
1398 goto err_nfcc_not_present;
1399 }
Bansidhar Gopalacharid093f1f2013-10-22 20:44:07 -07001400
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001401 logging_level = 0;
1402 /* request irq. The irq is set whenever the chip has data available
1403 * for reading. It is cleared when all data has been read.
1404 */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -07001405 device_mode.handle_flavour = UNSOLICITED_MODE;
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001406 /* NFC_INT IRQ */
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001407 qca199x_dev->irq_enabled = true;
1408 r = request_irq(client->irq, qca199x_dev_irq_handler,
1409 IRQF_TRIGGER_RISING, client->name, qca199x_dev);
1410 if (r) {
1411 dev_err(&client->dev, "nfc-nci probe: request_irq failed\n");
1412 goto err_request_irq_failed;
1413 }
1414 qca199x_disable_irq(qca199x_dev);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001415 /* CLK_REQ IRQ */
1416 if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
1417 (!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
1418 r = request_irq(qca199x_dev->clk_req_irq_num,
1419 qca199x_dev_irq_handler_clk_req,
1420 (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING),
1421 client->name, qca199x_dev);
1422 if (r) {
1423 dev_err(&client->dev,
1424 "nfc-nci probe: request_irq failed. irq no = %d\n, main irq = %d",
1425 qca199x_dev->clk_req_irq_num, client->irq);
1426 goto err_request_irq_failed;
1427 }
1428 qca199x_dev->irq_enabled_clk_req = true;
1429 qca199x_disable_irq_clk_req(qca199x_dev);
1430
1431
1432 qca199x_dev->my_wq =
1433 create_singlethread_workqueue("qca1990x_CLK_REQ_queue");
1434 if (!qca199x_dev->my_wq)
1435 goto err_create_workq;
1436
1437 INIT_WORK(&qca199x_dev->msm_clock_controll_work,
1438 clk_req_update);
1439 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001440 i2c_set_clientdata(client, qca199x_dev);
Houston Hoffmana0368172013-12-11 16:55:06 -08001441 gpio_set_value(platform_data->dis_gpio, 1);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001442 dev_dbg(&client->dev,
1443 "nfc-nci probe: %s, probing qca1990 exited successfully\n",
1444 __func__);
1445 return 0;
1446
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001447err_create_workq:
1448 dev_err(&client->dev,
1449 "nfc-nci probe: %s, work_queue creation failure\n",
1450 __func__);
1451 free_irq(client->irq, qca199x_dev);
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001452err_nfcc_not_present:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001453err_request_irq_failed:
1454 misc_deregister(&qca199x_dev->qca199x_device);
1455err_misc_register:
1456 mutex_destroy(&qca199x_dev->read_mutex);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001457err_clkreq_gpio:
1458 if (strcmp(platform_data->clk_src_name, "GPCLK2"))
1459 gpio_free(platform_data->clkreq_gpio);
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001460err_clk:
Houston Hoffmana0368172013-12-11 16:55:06 -08001461 qca199x_clock_deselect(qca199x_dev);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001462err_irq_clk:
1463 if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
1464 (!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
1465 r = gpio_direction_input(platform_data->irq_gpio_clk_req);
1466 if (r)
1467 dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
1468 gpio_free(platform_data->irq_gpio_clk_req);
1469 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001470err_irq:
1471 gpio_free(platform_data->irq_gpio);
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001472err_dis_gpio:
1473 gpio_free(platform_data->dis_gpio);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001474err_free_dev:
1475 kfree(qca199x_dev);
1476 return r;
1477}
1478
1479static int qca199x_remove(struct i2c_client *client)
1480{
1481 struct qca199x_dev *qca199x_dev;
1482
1483 qca199x_dev = i2c_get_clientdata(client);
1484 free_irq(client->irq, qca199x_dev);
1485 misc_deregister(&qca199x_dev->qca199x_device);
1486 mutex_destroy(&qca199x_dev->read_mutex);
1487 gpio_free(qca199x_dev->irq_gpio);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001488 if ((!strcmp(qca199x_dev->clk_src_name, "GPCLK")) ||
1489 (!strcmp(qca199x_dev->clk_src_name, "GPCLK2"))) {
1490 gpio_free(qca199x_dev->irq_gpio_clk_req);
1491 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001492 gpio_free(qca199x_dev->dis_gpio);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001493 if (strcmp(qca199x_dev->clk_src_name, "GPCLK2"))
1494 gpio_free(qca199x_dev->clkreq_gpio);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001495 kfree(qca199x_dev);
1496
1497 return 0;
1498}
1499
1500static const struct i2c_device_id qca199x_id[] = {
1501 {"qca199x-i2c", 0},
1502 {}
1503};
1504
1505static struct i2c_driver qca199x = {
1506 .id_table = qca199x_id,
1507 .probe = qca199x_probe,
1508 .remove = qca199x_remove,
1509 .driver = {
1510 .owner = THIS_MODULE,
1511 .name = "nfc-nci",
1512 .of_match_table = msm_match_table,
1513 },
1514};
1515
1516/*
1517 * module load/unload record keeping
1518 */
1519static int __init qca199x_dev_init(void)
1520{
1521 return i2c_add_driver(&qca199x);
1522}
1523module_init(qca199x_dev_init);
1524
1525static void __exit qca199x_dev_exit(void)
1526{
1527 i2c_del_driver(&qca199x);
1528}
1529module_exit(qca199x_dev_exit);
1530
1531MODULE_DESCRIPTION("NFC QCA199x");
1532MODULE_LICENSE("GPL v2");
1533