blob: 9d8b78083fc6ec548fe77da482de96e2d890fd27 [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>
Houston Hoffmanb03f6652014-01-16 16:28:02 -080016#include <linux/reboot.h>
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070017#include <linux/slab.h>
18#include <linux/i2c.h>
19#include <linux/irq.h>
20#include <linux/delay.h>
21#include <linux/interrupt.h>
22#include <linux/gpio.h>
23#include <linux/spinlock.h>
24#include <linux/poll.h>
25#include <linux/of_gpio.h>
26#include <linux/clk.h>
27#include <linux/of_device.h>
28#include <linux/regulator/consumer.h>
29#include "nfc-nci.h"
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +010030#include <mach/gpiomux.h>
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070031
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070032struct qca199x_platform_data {
33 unsigned int irq_gpio;
Houston Hoffman17f2dc52014-01-29 08:15:06 -080034 unsigned int irq_gpio_clk_req;
35 unsigned int clk_req_irq_num;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070036 unsigned int dis_gpio;
Houston Hoffman17f2dc52014-01-29 08:15:06 -080037 unsigned int clkreq_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070038 unsigned int reg;
Houston Hoffmana0368172013-12-11 16:55:06 -080039 const char *clk_src_name;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +010040 unsigned int clk_src_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070041};
42
43static struct of_device_id msm_match_table[] = {
44 {.compatible = "qcom,nfc-nci"},
45 {}
46};
47
48MODULE_DEVICE_TABLE(of, msm_match_table);
49
Houston Hoffmana0368172013-12-11 16:55:06 -080050#define MAX_BUFFER_SIZE (780)
Houston Hoffmanb03f6652014-01-16 16:28:02 -080051#define PACKET_MAX_LENGTH (258)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070052/* Read data */
53#define PACKET_HEADER_SIZE_NCI (4)
Houston Hoffmana0368172013-12-11 16:55:06 -080054#define PACKET_TYPE_NCI (16)
55#define MAX_PACKET_SIZE (PACKET_HEADER_SIZE_NCI + 255)
56#define MAX_QCA_REG (116)
57/* will timeout in approx. 100ms as 10us steps */
Houston Hoffmanfa9a38b2014-01-24 02:09:53 -080058#define NFC_RF_CLK_FREQ (19200000)
Houston Hoffmana0368172013-12-11 16:55:06 -080059#define NTF_TIMEOUT (10000)
60#define CORE_RESET_RSP_GID (0x60)
61#define CORE_RESET_OID (0x00)
Houston Hoffmanb03f6652014-01-16 16:28:02 -080062#define CORE_RST_NTF_LENGTH (0x02)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070063
Houston Hoffman17f2dc52014-01-29 08:15:06 -080064static void clk_req_update(struct work_struct *work);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070065
66struct qca199x_dev {
67 wait_queue_head_t read_wq;
Houston Hoffman17f2dc52014-01-29 08:15:06 -080068 struct mutex read_mutex;
69 struct i2c_client *client;
70 struct miscdevice qca199x_device;
71 /* NFC_IRQ new NCI data available */
72 unsigned int irq_gpio;
73 /* CLK_REQ IRQ to signal the state has changed */
74 unsigned int irq_gpio_clk_req;
75 /* Actual IRQ no. assigned to CLK_REQ */
76 unsigned int clk_req_irq_num;
77 unsigned int dis_gpio;
78 unsigned int clkreq_gpio;
79 /* NFC_IRQ state */
80 bool irq_enabled;
81 bool sent_first_nci_write;
82 spinlock_t irq_enabled_lock;
83 unsigned int count_irq;
84 /* CLK_REQ IRQ state */
85 bool irq_enabled_clk_req;
86 spinlock_t irq_enabled_lock_clk_req;
87 unsigned int count_irq_clk_req;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -070088 enum nfcc_state state;
Houston Hoffman17f2dc52014-01-29 08:15:06 -080089 /* CLK control */
90 unsigned int clk_src_gpio;
91 const char *clk_src_name;
92 struct clk *s_clk;
93 bool clk_run;
94 struct work_struct msm_clock_controll_work;
95 struct workqueue_struct *my_wq;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -070096};
97
Houston Hoffmana0368172013-12-11 16:55:06 -080098static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len);
Houston Hoffmanc108e8f2014-01-10 16:12:16 -080099static int nfcc_hw_check(struct i2c_client *client, unsigned short curr_addr);
Houston Hoffmana0368172013-12-11 16:55:06 -0800100static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr);
101static int qca199x_clock_select(struct qca199x_dev *qca199x_dev);
102static int qca199x_clock_deselect(struct qca199x_dev *qca199x_dev);
103
104
105
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700106/*
107 * To allow filtering of nfc logging from user. This is set via
108 * IOCTL NFC_KERNEL_LOGGING_MODE.
109 */
110static int logging_level;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700111/*
112 * FTM-RAW-I2C RD/WR MODE
113 */
Houston Hoffman17f2dc52014-01-29 08:15:06 -0800114static struct devicemode device_mode;
115static int ftm_raw_write_mode;
116static int ftm_werr_code;
117
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700118
Houston Hoffmanb03f6652014-01-16 16:28:02 -0800119unsigned int disable_ctrl;
Houston Hoffman2ab8e4b2014-02-08 14:02:13 -0800120bool region2_sent;
Houston Hoffmanb03f6652014-01-16 16:28:02 -0800121
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700122static void qca199x_init_stat(struct qca199x_dev *qca199x_dev)
123{
124 qca199x_dev->count_irq = 0;
125}
126
127static void qca199x_disable_irq(struct qca199x_dev *qca199x_dev)
128{
129 unsigned long flags;
130
131 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
132 if (qca199x_dev->irq_enabled) {
133 disable_irq_nosync(qca199x_dev->client->irq);
134 qca199x_dev->irq_enabled = false;
135 }
136 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
137}
138
139static void qca199x_enable_irq(struct qca199x_dev *qca199x_dev)
140{
141 unsigned long flags;
142
143 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
144 if (!qca199x_dev->irq_enabled) {
145 qca199x_dev->irq_enabled = true;
146 enable_irq(qca199x_dev->client->irq);
147 }
148 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
149}
150
151static irqreturn_t qca199x_dev_irq_handler(int irq, void *dev_id)
152{
153 struct qca199x_dev *qca199x_dev = dev_id;
154 unsigned long flags;
155
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700156 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
157 qca199x_dev->count_irq++;
158 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
159 wake_up(&qca199x_dev->read_wq);
160
161 return IRQ_HANDLED;
162}
163
164static unsigned int nfc_poll(struct file *filp, poll_table *wait)
165{
166 struct qca199x_dev *qca199x_dev = filp->private_data;
167 unsigned int mask = 0;
168 unsigned long flags;
169
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700170 poll_wait(filp, &qca199x_dev->read_wq, wait);
171
172 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
173 if (qca199x_dev->count_irq > 0) {
174 qca199x_dev->count_irq--;
175 mask |= POLLIN | POLLRDNORM;
176 }
177 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
178
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700179 return mask;
180}
181
Houston Hoffman17f2dc52014-01-29 08:15:06 -0800182/* Handlers for CLK_REQ */
183static void qca199x_disable_irq_clk_req(struct qca199x_dev *qca199x_dev)
184{
185 unsigned long flags;
186
187 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock_clk_req, flags);
188 if (qca199x_dev->irq_enabled_clk_req) {
189 disable_irq_nosync(qca199x_dev->clk_req_irq_num);
190 qca199x_dev->irq_enabled_clk_req = false;
191 }
192 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock_clk_req, flags);
193}
194
195
196static void qca199x_enable_irq_clk_req(struct qca199x_dev *qca199x_dev)
197{
198 unsigned long flags;
199
200 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock_clk_req, flags);
201 if (!qca199x_dev->irq_enabled_clk_req) {
202 qca199x_dev->irq_enabled_clk_req = true;
203 enable_irq(qca199x_dev->clk_req_irq_num);
204 }
205 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock_clk_req, flags);
206}
207
208
209static irqreturn_t qca199x_dev_irq_handler_clk_req(int irq, void *dev_id)
210{
211 struct qca199x_dev *qca199x_dev = dev_id;
212 unsigned long flags;
213
214 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock_clk_req, flags);
215 qca199x_dev->count_irq_clk_req++;
216 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock_clk_req, flags);
217
218 queue_work(qca199x_dev->my_wq, &qca199x_dev->msm_clock_controll_work);
219
220 return IRQ_HANDLED;
221}
222
223
224static struct gpiomux_setting nfc_clk_on = {
225 .func = GPIOMUX_FUNC_2,
226 .drv = GPIOMUX_DRV_2MA,
227 .pull = GPIOMUX_PULL_NONE,
228};
229static struct gpiomux_setting nfc_clk_on_suspend = {
230 .func = GPIOMUX_FUNC_2,
231 .drv = GPIOMUX_DRV_2MA,
232 .pull = GPIOMUX_PULL_DOWN,
233};
234static struct gpiomux_setting nfc_clk_off = {
235 .func = GPIOMUX_FUNC_GPIO,
236 .drv = GPIOMUX_DRV_2MA,
237 .pull = GPIOMUX_PULL_DOWN,
238};
239
240static void clk_req_update(struct work_struct *work)
241{
242 struct i2c_client *client;
243 struct qca199x_dev *qca199x_dev;
244 int gpio_clk_req_level = 0;
245
246 qca199x_dev = container_of(work, struct qca199x_dev,
247 msm_clock_controll_work);
248 client = qca199x_dev->client;
249
250 /* Read status level of CLK_REQ from NFC Controller, QCA199_x */
251 gpio_clk_req_level = gpio_get_value(qca199x_dev->irq_gpio_clk_req);
252 if (gpio_clk_req_level == 1) {
253 if (qca199x_dev->clk_run == false) {
254 msm_gpiomux_write(qca199x_dev->clk_src_gpio,
255 GPIOMUX_ACTIVE, &nfc_clk_on, NULL);
256 msm_gpiomux_write(qca199x_dev->clk_src_gpio,
257 GPIOMUX_SUSPENDED, &nfc_clk_on_suspend, NULL);
258 qca199x_dev->clk_run = true;
259 }
260 } else{
261 if (qca199x_dev->clk_run == true) {
262 msm_gpiomux_write(qca199x_dev->clk_src_gpio,
263 GPIOMUX_ACTIVE, &nfc_clk_off, NULL);
264 msm_gpiomux_write(qca199x_dev->clk_src_gpio,
265 GPIOMUX_SUSPENDED, &nfc_clk_off, NULL);
266 qca199x_dev->clk_run = false;
267 }
268 }
269}
270
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700271/*
272 * ONLY for FTM-RAW-I2C Mode
273 * Required to instigate a read, which comes from DT layer. This means we need
274 * to spoof an interrupt and send a wake up event.
275 */
276void ftm_raw_trigger_read(struct qca199x_dev *qca199x_dev)
277{
278 unsigned long flags;
279
280 spin_lock_irqsave(&qca199x_dev->irq_enabled_lock, flags);
281 qca199x_dev->count_irq++;
282 spin_unlock_irqrestore(&qca199x_dev->irq_enabled_lock, flags);
283 wake_up(&qca199x_dev->read_wq);
284}
285
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700286static ssize_t nfc_read(struct file *filp, char __user *buf,
287 size_t count, loff_t *offset)
288{
289 struct qca199x_dev *qca199x_dev = filp->private_data;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700290 unsigned char tmp[MAX_BUFFER_SIZE], rd_byte;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700291 unsigned char len[PAYLOAD_HEADER_LENGTH];
292 int total, length, ret;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700293 int ftm_rerr_code;
294 enum ehandler_mode dmode;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700295
296 total = 0;
297 length = 0;
298 if (count > MAX_BUFFER_SIZE)
299 count = MAX_BUFFER_SIZE;
300
301 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100302 memset(tmp, 0, sizeof(tmp));
303 memset(len, 0, sizeof(len));
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700304 dmode = device_mode.handle_flavour;
305 /* FTM-RAW-I2C RD/WR MODE - Special Case */
306 if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
307 (dmode == SOLICITED_FTM_RAW_MODE)) {
308 /* READ */
309 if ((ftm_raw_write_mode == 0) && (ftm_werr_code == 0)) {
310 ftm_rerr_code = i2c_master_recv(qca199x_dev->client,
311 &rd_byte, 1);
312 if (ftm_rerr_code == 0x1)
313 ftm_rerr_code = 0;
314 tmp[0] = (unsigned char)ftm_rerr_code;
315 tmp[1] = rd_byte;
316 total = 2;
317 ret = copy_to_user(buf, tmp, total);
318 }
319 /* WRITE */
320 else if ((ftm_raw_write_mode == 1) || (ftm_werr_code != 0)) {
321 tmp[0] = (unsigned char)ftm_werr_code;
322 total = 1;
323 ret = copy_to_user(buf, tmp, total);
324 } else {
325 /* Invalid case */
326 total = 0;
327 ret = copy_to_user(buf, tmp, total);
328 }
329 mutex_unlock(&qca199x_dev->read_mutex);
330 goto done;
331 }
332
333 /* NORMAL NCI Behaviour */
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700334 /* Read the header */
335 ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
Houston Hoffmana0368172013-12-11 16:55:06 -0800336 /*
337 We ignore all packets of length PAYLOAD_HEADER_LENGTH
338 or less (i.e <=3). In this case return a total length
339 of ZERO. So ALL PACKETS MUST HAVE A PAYLOAD.
340 If ret < 0 then this is an error code.
341 */
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100342 if (ret != PAYLOAD_HEADER_LENGTH) {
Houston Hoffmana0368172013-12-11 16:55:06 -0800343 if (ret < 0)
344 total = ret;
345 else
346 total = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700347 goto err;
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100348 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700349 length = len[PAYLOAD_HEADER_LENGTH - 1];
Houston Hoffmana0368172013-12-11 16:55:06 -0800350 if (length == 0) {
351 ret = 0;
352 total = ret;
353 goto err;
354 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700355 /** make sure full packet fits in the buffer **/
356 if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= count)) {
357 /* Read the packet */
358 ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
359 PAYLOAD_HEADER_LENGTH));
Houston Hoffmana0368172013-12-11 16:55:06 -0800360 total = ret;
361 if (ret < 0)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700362 goto err;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700363 }
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100364
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700365 if (total > 0) {
366 if ((total > count) || copy_to_user(buf, tmp, total)) {
367 dev_err(&qca199x_dev->client->dev,
368 "failed to copy to user space, total = %d\n",
369 total);
370 total = -EFAULT;
371 }
372 }
373err:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700374 mutex_unlock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700375done:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700376 return total;
377}
378
Houston Hoffmana0368172013-12-11 16:55:06 -0800379/*
380 Local routine to read from nfcc buffer. This is called to clear any
381 pending receive messages in the nfcc's read buffer, which may be there
382 following a POR. In this way, the upper layers (Device Transport) will
383 associate the next rsp/ntf nci message with the next nci command to the
384 nfcc. Otherwise, the DT may interpret a ntf from the nfcc as being from
385 the nci core reset command when in fact it was already present in the
386 nfcc read buffer following a POR.
387*/
388
389int nfcc_read_buff_svc(struct qca199x_dev *qca199x_dev)
390{
391 unsigned char tmp[PACKET_MAX_LENGTH];
392 unsigned char len[PAYLOAD_HEADER_LENGTH];
393 int total, length, ret;
394 total = 0;
395 length = 0;
396 mutex_lock(&qca199x_dev->read_mutex);
397 memset(tmp, 0, sizeof(tmp));
398 memset(len, 0, sizeof(len));
399
400 /* Read the header */
401 ret = i2c_master_recv(qca199x_dev->client, len, PAYLOAD_HEADER_LENGTH);
402 if (ret < PAYLOAD_HEADER_LENGTH) {
403 total = ret;
404 goto leave;
405 }
406 length = len[PAYLOAD_HEADER_LENGTH - 1];
407 if (length == 0) {
408 ret = PAYLOAD_HEADER_LENGTH;
409 total = ret;
410 goto leave;
411 }
412 /** make sure full packet fits in the buffer **/
413 if ((length > 0) && ((length + PAYLOAD_HEADER_LENGTH) <= PACKET_MAX_LENGTH)) {
414 /* Read the packet */
415 ret = i2c_master_recv(qca199x_dev->client, tmp, (length +
416 PAYLOAD_HEADER_LENGTH));
417 total = ret;
418 }
419leave:
420 mutex_unlock(&qca199x_dev->read_mutex);
421 return total;
422}
423
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700424static ssize_t nfc_write(struct file *filp, const char __user *buf,
425 size_t count, loff_t *offset)
426{
427 struct qca199x_dev *qca199x_dev = filp->private_data;
428 char tmp[MAX_BUFFER_SIZE];
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700429 int ret = 0;
430 enum ehandler_mode dmode;
Houston Hoffmana0368172013-12-11 16:55:06 -0800431 int nfcc_buffer = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700432
433 if (count > MAX_BUFFER_SIZE) {
434 dev_err(&qca199x_dev->client->dev, "out of memory\n");
435 return -ENOMEM;
436 }
437 if (copy_from_user(tmp, buf, count)) {
438 dev_err(&qca199x_dev->client->dev,
439 "nfc-nci write: failed to copy from user space\n");
440 return -EFAULT;
441 }
Houston Hoffmana0368172013-12-11 16:55:06 -0800442 /*
443 A catch for when the DT is sending the initial NCI write
444 following a hardware POR. In this case we should clear any
445 pending messages in nfcc buffer and open the interrupt gate
446 for new messages coming from the nfcc.
447 */
448 if ((qca199x_dev->sent_first_nci_write == false) &&
449 (qca199x_dev->irq_enabled == false)) {
450 /* check rsp/ntf from nfcc read-side buffer */
451 nfcc_buffer = nfcc_read_buff_svc(qca199x_dev);
452 /* There has been an error while reading from nfcc */
453 if (nfcc_buffer < 0) {
454 dev_err(&qca199x_dev->client->dev,
455 "nfc-nci write: error while servicing nfcc read buffer\n");
456 }
457 qca199x_dev->sent_first_nci_write = true;
458 qca199x_enable_irq(qca199x_dev);
459 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700460 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700461 dmode = device_mode.handle_flavour;
462 /* FTM-DIRECT-I2C RD/WR MODE */
Houston Hoffmana0368172013-12-11 16:55:06 -0800463 /* This is a special FTM-i2c mode case, where tester is not using NCI */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700464 if ((dmode == UNSOLICITED_FTM_RAW_MODE) ||
465 (dmode == SOLICITED_FTM_RAW_MODE)) {
466 /* Read From Register */
467 if (count == 1) {
468 ftm_raw_write_mode = 0;
469 ret = i2c_master_send(qca199x_dev->client, tmp, count);
470 if (ret == 1)
471 ftm_werr_code = 0;
472 else
473 ftm_werr_code = ret;
474 ftm_raw_trigger_read(qca199x_dev);
475 }
476 /* Write to Register */
477 if (count == 2) {
478 ftm_raw_write_mode = 1;
479 ret = i2c_master_send(qca199x_dev->client, tmp, count);
480 if (ret == 2)
481 ftm_werr_code = 0;
482 else
483 ftm_werr_code = ret;
484 ftm_raw_trigger_read(qca199x_dev);
485 }
486 } else {
487 /* NORMAL NCI behaviour - NB :
488 We can be in FTM mode here also */
489 ret = i2c_master_send(qca199x_dev->client, tmp, count);
490 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700491 if (ret != count) {
492 dev_err(&qca199x_dev->client->dev,
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700493 "NFC: failed to write %d\n", ret);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700494 ret = -EIO;
495 }
496 mutex_unlock(&qca199x_dev->read_mutex);
497
Houston Hoffman2ab8e4b2014-02-08 14:02:13 -0800498 /* If we detect a Region2 command prior to power-down */
499 if ((tmp[0] == 0x2F) && (tmp[1] == 0x01) && (tmp[2] == 0x02) &&
500 (tmp[3] == 0x08) && (tmp[4] == 0x00)) {
501 region2_sent = true;
502 }
503
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700504 return ret;
505}
506
507static int nfc_open(struct inode *inode, struct file *filp)
508{
509 int ret = 0;
510
511 struct qca199x_dev *qca199x_dev = container_of(filp->private_data,
512 struct qca199x_dev,
513 qca199x_device);
514
515 filp->private_data = qca199x_dev;
516 qca199x_init_stat(qca199x_dev);
Houston Hoffman17f2dc52014-01-29 08:15:06 -0800517 /* Enable interrupts from NFCC NFC_INT new NCI data available */
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700518 qca199x_enable_irq(qca199x_dev);
Houston Hoffman17f2dc52014-01-29 08:15:06 -0800519
520 if ((!strcmp(qca199x_dev->clk_src_name, "GPCLK")) ||
521 (!strcmp(qca199x_dev->clk_src_name, "GPCLK2"))) {
522 /* Enable interrupts from NFCC CLK_REQ */
523 qca199x_enable_irq_clk_req(qca199x_dev);
524 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700525 dev_dbg(&qca199x_dev->client->dev,
526 "%d,%d\n", imajor(inode), iminor(inode));
527 return ret;
528}
529
530/*
531 * Wake/Sleep Mode
532 */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700533int nfcc_wake(int level, struct file *filp)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700534{
535 int r = 0;
536 unsigned char raw_nci_sleep[] = {0x2F, 0x03, 0x00};
537 /* Change slave address to 0xE */
538 unsigned char raw_nci_wake[] = {0x10, 0x0F};
539 unsigned short slave_addr = 0xE;
540 unsigned short curr_addr;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700541 struct qca199x_dev *qca199x_dev = filp->private_data;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700542
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700543 dev_dbg(&qca199x_dev->client->dev, "nfcc_wake: %s: info: %p\n",
544 __func__, qca199x_dev);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700545
546 if (level == NFCC_SLEEP) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700547 r = i2c_master_send(qca199x_dev->client, &raw_nci_sleep[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700548 sizeof(raw_nci_sleep));
549
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700550 r = sizeof(raw_nci_sleep);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700551 if (r != sizeof(raw_nci_sleep))
552 return -EMSGSIZE;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700553 qca199x_dev->state = NFCC_STATE_NORMAL_SLEEP;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700554 } else {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700555 curr_addr = qca199x_dev->client->addr;
556 qca199x_dev->client->addr = slave_addr;
557 r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700558 sizeof(raw_nci_wake));
559 /* Restore original NFCC slave I2C address */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700560 qca199x_dev->client->addr = curr_addr;
561 r = sizeof(raw_nci_wake);
562 if (r != sizeof(raw_nci_wake))
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700563 return -EMSGSIZE;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700564 qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700565 }
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700566
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700567 return r;
568}
569
570/*
571 * Inside nfc_ioctl_power_states
572 *
573 * @brief ioctl functions
574 *
575 *
576 * Device control
577 * remove control via ioctl
578 * (arg = 0): NFC_DISABLE GPIO = 0
579 * (arg = 1): NFC_DISABLE GPIO = 1
580 * NOT USED (arg = 2): FW_DL GPIO = 0
581 * NOT USED (arg = 3): FW_DL GPIO = 1
582 * (arg = 4): NFCC_WAKE = 1
583 * (arg = 5): NFCC_WAKE = 0
584 *
585 *
586 */
587int nfc_ioctl_power_states(struct file *filp, unsigned int cmd,
588 unsigned long arg)
589{
590 int r = 0;
591 struct qca199x_dev *qca199x_dev = filp->private_data;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700592
593 if (arg == 0) {
Houston Hoffmana0368172013-12-11 16:55:06 -0800594 r = qca199x_clock_select(qca199x_dev);
595 if (r < 0)
596 goto err_req;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700597 gpio_set_value(qca199x_dev->dis_gpio, 0);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700598 r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
599 if (r) {
600 dev_err(&qca199x_dev->client->dev,
601 "unable to set direction for gpio [%d]\n",
602 qca199x_dev->dis_gpio);
603 goto err_req;
604 }
605 gpio_set_value(qca199x_dev->dis_gpio, 0);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100606 msleep(20);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700607 } else if (arg == 1) {
Houston Hoffmana0368172013-12-11 16:55:06 -0800608 /*
609 We are attempting a hardware reset so let us disable
610 interrupts to avoid spurious notifications to upper
611 layers.
612 */
613 qca199x_disable_irq(qca199x_dev);
614 /* Deselection of clock */
615 r = qca199x_clock_deselect(qca199x_dev);
616 if (r < 0)
617 goto err_req;
618 /*
Houston Hoffmanb03f6652014-01-16 16:28:02 -0800619 Also, set flag for initial NCI write following reset as
Houston Hoffmana0368172013-12-11 16:55:06 -0800620 may wish to do some house keeping. Ensure no pending
621 messages in NFCC buffers which may be wrongly
622 construed as response to initial message
623 */
624 qca199x_dev->sent_first_nci_write = false;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700625 gpio_set_value(qca199x_dev->dis_gpio, 0);
626 r = gpio_direction_output(qca199x_dev->dis_gpio, 1);
627 if (r) {
628 dev_err(&qca199x_dev->client->dev,
629 "unable to set direction for gpio [%d]\n",
630 qca199x_dev->dis_gpio);
631 goto err_req;
632 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700633 gpio_set_value(qca199x_dev->dis_gpio, 1);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100634 usleep(1000);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700635 } else if (arg == 2) {
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100636 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100637 r = nfcc_initialise(qca199x_dev->client, 0xE);
Houston Hoffmana0368172013-12-11 16:55:06 -0800638 /* Also reset first NCI write */
639 qca199x_dev->sent_first_nci_write = false;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100640 mutex_unlock(&qca199x_dev->read_mutex);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100641 if (r) {
642 dev_err(&qca199x_dev->client->dev,
Houston Hoffmana0368172013-12-11 16:55:06 -0800643 "nfc_ioctl_power_states: request nfcc initialise failed\n");
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100644 goto err_req;
645 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700646 } else if (arg == 3) {
647 msleep(20);
648 } else if (arg == 4) {
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100649 mutex_lock(&qca199x_dev->read_mutex);
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700650 nfcc_wake(NFCC_WAKE, filp);
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100651 mutex_unlock(&qca199x_dev->read_mutex);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700652 } else if (arg == 5) {
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700653 nfcc_wake(NFCC_SLEEP, filp);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700654 } else {
655 r = -ENOIOCTLCMD;
656 }
657
658err_req:
659 return r;
660}
661
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700662/*
663 * Inside nfc_ioctl_nfcc_mode
664 *
665 * @brief nfc_ioctl_nfcc_mode
666 *
667 * (arg = 0) ; NORMAL_MODE - Standard mode, unsolicited read behaviour
668 * (arg = 1) ; SOLICITED_MODE - As above but reads are solicited from User Land
669 * (arg = 2) ; UNSOLICITED_FTM_RAW MODE - NORMAL_MODE but messages from FTM and
670 * not NCI Host.
671 * (arg = 2) ; SOLICITED_FTM_RAW_MODE - As SOLICITED_MODE but messages from FTM
672 * and not NCI Host.
673 *
674 *
675 *
676 */
677int nfc_ioctl_nfcc_mode(struct file *filp, unsigned int cmd, unsigned long arg)
678{
679 int retval = 0;
680
681 static unsigned short nci_addr;
682 struct qca199x_dev *qca199x_dev = filp->private_data;
683 struct qca199x_platform_data *platform_data;
684
685 platform_data = qca199x_dev->client->dev.platform_data;
686
687 if (arg == 0) {
688 device_mode.handle_flavour = UNSOLICITED_MODE;
689 qca199x_dev->client->addr = NCI_I2C_SLAVE;
690 /* enable interrupts again */
691 qca199x_enable_irq(qca199x_dev);
692 } else if (arg == 1) {
693 device_mode.handle_flavour = SOLICITED_MODE;
694 qca199x_dev->client->addr = qca199x_dev->client->addr;
695 /* enable interrupts again */
696 qca199x_enable_irq(qca199x_dev);
697 } else if (arg == 2) {
698 device_mode.handle_flavour = UNSOLICITED_FTM_RAW_MODE;
699 nci_addr = qca199x_dev->client->addr;
700 /* replace with new client slave address*/
701 qca199x_dev->client->addr = 0xE;
702 /* We also need to disable interrupts */
703 qca199x_disable_irq(qca199x_dev);
704 } else if (arg == 3) {
705 device_mode.handle_flavour = SOLICITED_FTM_RAW_MODE;
706 nci_addr = qca199x_dev->client->addr;
707 /* replace with new client slave address*/
708 qca199x_dev->client->addr = 0xE;
709 /* We also need to disable interrupts */
710 qca199x_disable_irq(qca199x_dev);
711 } else {
712 device_mode.handle_flavour = UNSOLICITED_MODE;
713 qca199x_dev->client->addr = NCI_I2C_SLAVE;
714 }
715 return retval;
716}
717
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700718/*
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100719 * Inside nfc_ioctl_nfcc_version
720 *
721 * @brief nfc_ioctl_nfcc_version
722 *
723 *
724 */
725int nfc_ioctl_nfcc_version(struct file *filp, unsigned int cmd,
726 unsigned long arg)
727{
728 int r = 0;
729 unsigned short slave_addr = 0xE;
730 unsigned short curr_addr;
Houston Hoffman3196e562014-01-15 18:22:10 -0800731 unsigned char raw_nci_wake[] = {0x10, 0x0F};
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100732 unsigned char raw_chip_version_addr = 0x00;
733 unsigned char raw_chip_rev_id_addr = 0x9C;
734 unsigned char raw_chip_version = 0xFF;
735
736 struct qca199x_dev *qca199x_dev = filp->private_data;
737 struct qca199x_platform_data *platform_data;
738
739 platform_data = qca199x_dev->client->dev.platform_data;
740
Houston Hoffman3196e562014-01-15 18:22:10 -0800741 /*
742 * Always wake up chip when reading 0x9C, otherwise this
743 * register is not updated
744 */
745 curr_addr = qca199x_dev->client->addr;
746 qca199x_dev->client->addr = slave_addr;
747 r = nfc_i2c_write(qca199x_dev->client, &raw_nci_wake[0],
748 sizeof(raw_nci_wake));
749 r = sizeof(raw_nci_wake);
750 if (r != sizeof(raw_nci_wake))
751 goto invalid_wake_up;
752 qca199x_dev->state = NFCC_STATE_NORMAL_WAKE;
753
754 /* sleep to ensure the NFCC has time to wake up */
755 usleep(100);
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100756 if (arg == 0) {
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100757 r = nfc_i2c_write(qca199x_dev->client,
758 &raw_chip_version_addr, 1);
759 if (r < 0)
760 goto invalid_wr;
761 usleep(10);
762 r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
763 /* Restore original NFCC slave I2C address */
764 qca199x_dev->client->addr = curr_addr;
Houston Hoffman3196e562014-01-15 18:22:10 -0800765 } else if (arg == 1) {
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100766 r = nfc_i2c_write(qca199x_dev->client,
767 &raw_chip_rev_id_addr, 1);
768 if (r < 0)
769 goto invalid_wr;
770 usleep(10);
771 r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
772 /* Restore original NFCC slave I2C address */
773 qca199x_dev->client->addr = curr_addr;
774 }
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100775 return raw_chip_version;
Houston Hoffman3196e562014-01-15 18:22:10 -0800776invalid_wake_up:
777 raw_chip_version = 0xFE;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100778invalid_wr:
779 raw_chip_version = 0xFF;
780 dev_err(&qca199x_dev->client->dev,
781 "\nNFCC_INVALID_CHIP_VERSION = %d\n", raw_chip_version);
782 return raw_chip_version;
783}
784
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100785/*
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700786 * Inside nfc_ioctl_kernel_logging
787 *
788 * @brief nfc_ioctl_kernel_logging
789 *
790 * (arg = 0) ; NO_LOGGING
791 * (arg = 1) ; COMMS_LOGGING - BASIC LOGGING - Mainly just comms over I2C
792 * (arg = 2) ; FULL_LOGGING - ENABLE ALL - DBG messages for handlers etc.
793 * ; ! Be aware as amount of logging could impact behaviour !
794 *
795 *
796 */
797int nfc_ioctl_kernel_logging(unsigned long arg, struct file *filp)
798{
799 int retval = 0;
800 struct qca199x_dev *qca199x_dev = container_of(filp->private_data,
801 struct qca199x_dev,
802 qca199x_device);
803 if (arg == 0) {
804 dev_dbg(&qca199x_dev->client->dev,
805 "nfc_ioctl_kernel_logging : level = NO_LOGGING\n");
806 logging_level = 0;
807 } else if (arg == 1) {
808 dev_dbg(&qca199x_dev->client->dev,
809 "nfc_ioctl_kernel_logging: level = COMMS_LOGGING only\n");
810 logging_level = 1;
811 } else if (arg == 2) {
812 dev_dbg(&qca199x_dev->client->dev,
813 "nfc_ioctl_kernel_logging: level = FULL_LOGGING\n");
814 logging_level = 2;
815 }
816 return retval;
817}
818
819static long nfc_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg)
820{
821 int r = 0;
822
823 switch (cmd) {
824
825 case NFC_SET_PWR:
826 nfc_ioctl_power_states(pfile, cmd, arg);
827 break;
828 case NFCC_MODE:
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700829 nfc_ioctl_nfcc_mode(pfile, cmd, arg);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700830 break;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +0100831 case NFCC_VERSION:
832 r = nfc_ioctl_nfcc_version(pfile, cmd, arg);
833 break;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700834 case NFC_KERNEL_LOGGING_MODE:
835 nfc_ioctl_kernel_logging(arg, pfile);
836 break;
837 case SET_RX_BLOCK:
838 break;
839 case SET_EMULATOR_TEST_POINT:
840 break;
841 default:
842 r = -ENOIOCTLCMD;
843 }
844 return r;
845}
846
847static const struct file_operations nfc_dev_fops = {
848 .owner = THIS_MODULE,
849 .llseek = no_llseek,
850 .poll = nfc_poll,
851 .read = nfc_read,
852 .write = nfc_write,
853 .open = nfc_open,
854 .unlocked_ioctl = nfc_ioctl
855};
856
857void dumpqca1990(struct i2c_client *client)
858{
859 int r = 0;
860 int i = 0;
861 unsigned char raw_reg_rd = {0x0};
862 unsigned short temp_addr;
863
864 temp_addr = client->addr;
865 client->addr = 0x0E;
866
867 for (i = 0; i < MAX_QCA_REG; i++) {
868 raw_reg_rd = i;
869 if (((i >= 0x0) && (i < 0x4)) || ((i > 0x7) && (i < 0xA)) ||
870 ((i > 0xF) && (i < 0x12)) || ((i > 0x39) && (i < 0x4d)) ||
871 ((i > 0x69) && (i < 0x74)) || (i == 0x18) || (i == 0x30) ||
872 (i == 0x58)) {
873 r = nfc_i2c_write(client, &raw_reg_rd, 1);
874 msleep(20);
875 r = i2c_master_recv(client, &raw_reg_rd, 1);
876 }
877 }
878 client->addr = temp_addr;
879}
880
881static int nfc_i2c_write(struct i2c_client *client, u8 *buf, int len)
882{
883 int r;
884
885 r = i2c_master_send(client, buf, len);
886 dev_dbg(&client->dev, "send: %d\n", r);
887 if (r == -EREMOTEIO) { /* Retry, chip was in standby */
888 usleep_range(6000, 10000);
889 r = i2c_master_send(client, buf, len);
890 dev_dbg(&client->dev, "send2: %d\n", r);
891 }
892 if (r != len)
893 return -EREMOTEIO;
894
895 return r;
896}
897
Houston Hoffmanc108e8f2014-01-10 16:12:16 -0800898/* Check for availability of qca199x_ NFC controller hardware */
899static int nfcc_hw_check(struct i2c_client *client, unsigned short curr_addr)
900{
901 int r = 0;
902 unsigned char buf = 0;
903
904 client->addr = curr_addr;
905 /* Set-up Addr 0. No data written */
906 r = i2c_master_send(client, &buf, 1);
907 if (r < 0)
908 goto err_presence_check;
909 buf = 0;
910 /* Read back from Addr 0 */
911 r = i2c_master_recv(client, &buf, 1);
912 if (r < 0)
913 goto err_presence_check;
914
915 r = 0;
916 return r;
917
918err_presence_check:
919 r = -ENXIO;
920 dev_err(&client->dev,
921 "nfc-nci nfcc_presence check - no NFCC available\n");
922 return r;
923}
924/* Initialise qca199x_ NFC controller hardware */
Bansidhar Gopalacharia0e50d12013-07-25 19:03:32 +0100925static int nfcc_initialise(struct i2c_client *client, unsigned short curr_addr)
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700926{
927 int r = 0;
928 unsigned char raw_1p8_CONTROL_011[] = {0x11, XTAL_CLOCK};
929 unsigned char raw_1P8_CONTROL_010[] = {0x10, PWR_EN};
930 unsigned char raw_1P8_X0_0B0[] = {0xB0, (FREQ_SEL)};
931 unsigned char raw_slave1[] = {0x09, NCI_I2C_SLAVE};
932 unsigned char raw_slave2[] = {0x8, 0x10};
933 unsigned char raw_s73[] = {0x73, 0x02};
934 unsigned char raw_slave1_rd = {0x0};
935 unsigned char raw_1P8_PAD_CFG_CLK_REQ[] = {0xA5, 0x1};
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700936 unsigned char raw_1P8_PAD_CFG_PWR_REQ[] = {0xA7, 0x1};
937 unsigned char buf = 0;
Houston Hoffmana0368172013-12-11 16:55:06 -0800938 bool core_reset_completed = false;
939 unsigned char rsp[6];
940 int time_taken = 0;
941 int ret = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700942
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700943 client->addr = curr_addr;
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700944 r = i2c_master_send(client, &buf, 1);
Houston Hoffmana0368172013-12-11 16:55:06 -0800945 if (r < 0)
946 goto err_init;
947
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -0700948 buf = 0;
949 r = i2c_master_recv(client, &buf, 1);
Houston Hoffmana0368172013-12-11 16:55:06 -0800950 if (r < 0)
951 goto err_init;
952
Satish Kumar Singhceb61952014-03-04 10:15:01 -0800953 RAW(s73, 0x02);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -0700954
Satish Kumar Singhceb61952014-03-04 10:15:01 -0800955 r = nfc_i2c_write(client, &raw_s73[0], sizeof(raw_s73));
956 if (r < 0)
Houston Hoffmana0368172013-12-11 16:55:06 -0800957 goto err_init;
Satish Kumar Singhceb61952014-03-04 10:15:01 -0800958
959 usleep(1000);
960 RAW(1p8_CONTROL_011, XTAL_CLOCK | 0x01);
961
962 r = nfc_i2c_write(client, &raw_1p8_CONTROL_011[0],
963 sizeof(raw_1p8_CONTROL_011));
964 if (r < 0)
965 goto err_init;
966
967 usleep(1000);
968 RAW(1P8_CONTROL_010, (0x8));
969 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
970 sizeof(raw_1P8_CONTROL_010));
971 if (r < 0)
972 goto err_init;
973
974 usleep(10000); /* 10ms wait */
975 RAW(1P8_CONTROL_010, (0xC));
976 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
977 sizeof(raw_1P8_CONTROL_010));
978 if (r < 0)
979 goto err_init;
980
981 usleep(100); /* 100uS wait */
982 RAW(1P8_X0_0B0, (FREQ_SEL_19));
983 r = nfc_i2c_write(client, &raw_1P8_X0_0B0[0],
984 sizeof(raw_1P8_X0_0B0));
985 if (r < 0)
986 goto err_init;
987
988 usleep(1000);
989
990 /* PWR_EN = 1 */
991 RAW(1P8_CONTROL_010, (0xd));
992 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
993 sizeof(raw_1P8_CONTROL_010));
994 if (r < 0)
995 goto err_init;
996
997
998 usleep(20000); /* 20ms wait */
999 /* LS_EN = 1 */
1000 RAW(1P8_CONTROL_010, 0xF);
1001 r = nfc_i2c_write(client, &raw_1P8_CONTROL_010[0],
1002 sizeof(raw_1P8_CONTROL_010));
1003 if (r < 0)
1004 goto err_init;
1005
1006 usleep(20000); /* 20ms wait */
1007
1008 /* Enable the PMIC clock */
1009 RAW(1P8_PAD_CFG_CLK_REQ, (0x1));
1010 r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_CLK_REQ[0],
1011 sizeof(raw_1P8_PAD_CFG_CLK_REQ));
1012 if (r < 0)
1013 goto err_init;
1014
1015 usleep(1000);
1016
1017 RAW(1P8_PAD_CFG_PWR_REQ, (0x1));
1018 r = nfc_i2c_write(client, &raw_1P8_PAD_CFG_PWR_REQ[0],
1019 sizeof(raw_1P8_PAD_CFG_PWR_REQ));
1020 if (r < 0)
1021 goto err_init;
1022
1023 usleep(1000);
1024
1025 RAW(slave2, 0x10);
1026 r = nfc_i2c_write(client, &raw_slave2[0], sizeof(raw_slave2));
1027 if (r < 0)
1028 goto err_init;
1029
1030 usleep(1000);
1031
1032 RAW(slave1, NCI_I2C_SLAVE);
1033 r = nfc_i2c_write(client, &raw_slave1[0], sizeof(raw_slave1));
1034 if (r < 0)
1035 goto err_init;
1036
1037 usleep(1000);
1038
1039 /* QCA199x NFCC CPU should now boot... */
1040 r = i2c_master_recv(client, &raw_slave1_rd, 1);
1041 /* Talk on NCI slave address NCI_I2C_SLAVE 0x2C*/
1042 client->addr = NCI_I2C_SLAVE;
1043
1044 /*
1045 Start with small delay and then we will poll until we
1046 get a core reset notification - This is time for chip
1047 & NFCC controller to come-up.
1048 */
1049 usleep(1000); /* 1 ms */
1050
1051 do {
1052 ret = i2c_master_recv(client, rsp, 5);
1053 /* Found core reset notification */
1054 if (((rsp[0] == CORE_RESET_RSP_GID) &&
1055 (rsp[1] == CORE_RESET_OID) &&
1056 (rsp[2] == CORE_RST_NTF_LENGTH))
1057 || time_taken == NTF_TIMEOUT) {
1058 core_reset_completed = true;
1059 }
1060 usleep(10); /* 10us sleep before retry */
1061 time_taken++;
1062 } while (!core_reset_completed);
1063 r = 0;
Houston Hoffmana0368172013-12-11 16:55:06 -08001064 return r;
1065err_init:
1066 r = 1;
1067 dev_err(&client->dev,
1068 "nfc-nci nfcc_initialise: failed. Check Hardware\n");
1069 return r;
1070}
1071/*
1072 Routine to Select clocks
1073*/
1074static int qca199x_clock_select(struct qca199x_dev *qca199x_dev)
1075{
1076 int r = 0;
1077
1078 if (!strcmp(qca199x_dev->clk_src_name, "BBCLK2")) {
1079 qca199x_dev->s_clk =
1080 clk_get(&qca199x_dev->client->dev, "ref_clk");
1081 if (qca199x_dev->s_clk == NULL)
1082 goto err_invalid_dis_gpio;
1083 } else if (!strcmp(qca199x_dev->clk_src_name, "RFCLK3")) {
1084 qca199x_dev->s_clk =
1085 clk_get(&qca199x_dev->client->dev, "ref_clk_rf");
1086 if (qca199x_dev->s_clk == NULL)
1087 goto err_invalid_dis_gpio;
1088 } else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK")) {
1089 if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
1090 qca199x_dev->s_clk =
1091 clk_get(&qca199x_dev->client->dev, "core_clk");
1092 if (qca199x_dev->s_clk == NULL)
1093 goto err_invalid_dis_gpio;
1094 } else {
1095 goto err_invalid_dis_gpio;
1096 }
1097 } else if (!strcmp(qca199x_dev->clk_src_name, "GPCLK2")) {
1098 if (gpio_is_valid(qca199x_dev->clk_src_gpio)) {
1099 qca199x_dev->s_clk =
1100 clk_get(&qca199x_dev->client->dev, "core_clk_pvt");
1101 if (qca199x_dev->s_clk == NULL)
1102 goto err_invalid_dis_gpio;
1103 } else {
1104 goto err_invalid_dis_gpio;
1105 }
1106 } else {
1107 qca199x_dev->s_clk = NULL;
1108 goto err_invalid_dis_gpio;
1109 }
1110 if (qca199x_dev->clk_run == false) {
Houston Hoffmanfa9a38b2014-01-24 02:09:53 -08001111 /* Set clock rate */
1112 if ((!strcmp(qca199x_dev->clk_src_name, "GPCLK")) ||
1113 (!strcmp(qca199x_dev->clk_src_name, "GPCLK2"))) {
1114 r = clk_set_rate(qca199x_dev->s_clk, NFC_RF_CLK_FREQ);
1115 if (r)
1116 goto err_invalid_clk;
1117 }
1118
Houston Hoffmana0368172013-12-11 16:55:06 -08001119 r = clk_prepare_enable(qca199x_dev->s_clk);
1120 if (r)
1121 goto err_invalid_clk;
1122 qca199x_dev->clk_run = true;
1123 }
1124 r = 0;
1125 return r;
1126
1127err_invalid_clk:
1128 r = -1;
1129 return r;
1130err_invalid_dis_gpio:
1131 r = -2;
1132 return r;
1133}
1134/*
1135 Routine to De-Select clocks
1136*/
1137
1138static int qca199x_clock_deselect(struct qca199x_dev *qca199x_dev)
1139{
1140 int r = -1;
1141 if (qca199x_dev->s_clk != NULL) {
1142 if (qca199x_dev->clk_run == true) {
1143 clk_disable_unprepare(qca199x_dev->s_clk);
1144 qca199x_dev->clk_run = false;
1145 }
1146 return 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001147 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001148 return r;
1149}
1150
1151static int nfc_parse_dt(struct device *dev, struct qca199x_platform_data *pdata)
1152{
1153 int r = 0;
1154 struct device_node *np = dev->of_node;
1155
1156 r = of_property_read_u32(np, "reg", &pdata->reg);
1157 if (r)
1158 return -EINVAL;
1159
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001160 pdata->dis_gpio = of_get_named_gpio(np, "qcom,dis-gpio", 0);
1161 if ((!gpio_is_valid(pdata->dis_gpio)))
1162 return -EINVAL;
Houston Hoffmanb03f6652014-01-16 16:28:02 -08001163 disable_ctrl = pdata->dis_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001164
1165 pdata->irq_gpio = of_get_named_gpio(np, "qcom,irq-gpio", 0);
1166 if ((!gpio_is_valid(pdata->irq_gpio)))
1167 return -EINVAL;
1168
Houston Hoffmana0368172013-12-11 16:55:06 -08001169 r = of_property_read_string(np, "qcom,clk-src", &pdata->clk_src_name);
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001170
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001171 if (strcmp(pdata->clk_src_name, "GPCLK2")) {
1172 r = of_property_read_u32(np, "qcom,clk-gpio",
1173 &pdata->clkreq_gpio);
1174 if (r)
1175 return -EINVAL;
1176 }
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001177
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001178 if ((!strcmp(pdata->clk_src_name, "GPCLK")) ||
1179 (!strcmp(pdata->clk_src_name, "GPCLK2"))) {
1180 pdata->clk_src_gpio = of_get_named_gpio(np,
1181 "qcom,clk-src-gpio", 0);
1182 if ((!gpio_is_valid(pdata->clk_src_gpio)))
1183 return -EINVAL;
1184 pdata->irq_gpio_clk_req = of_get_named_gpio(np,
1185 "qcom,clk-req-gpio", 0);
1186 if ((!gpio_is_valid(pdata->irq_gpio_clk_req)))
1187 return -EINVAL;
1188 }
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001189 if (r)
1190 return -EINVAL;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001191 return r;
1192}
1193
1194static int qca199x_probe(struct i2c_client *client,
1195 const struct i2c_device_id *id)
1196{
1197 int r = 0;
1198 int irqn = 0;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001199 struct device_node *node = client->dev.of_node;
1200 struct qca199x_platform_data *platform_data;
1201 struct qca199x_dev *qca199x_dev;
1202
1203 if (client->dev.of_node) {
1204 platform_data = devm_kzalloc(&client->dev,
1205 sizeof(struct qca199x_platform_data), GFP_KERNEL);
1206 if (!platform_data) {
1207 dev_err(&client->dev,
1208 "nfc-nci probe: Failed to allocate memory\n");
1209 return -ENOMEM;
1210 }
1211 r = nfc_parse_dt(&client->dev, platform_data);
1212 if (r)
1213 return r;
1214 } else {
1215 platform_data = client->dev.platform_data;
1216 }
1217 if (!platform_data)
1218 return -EINVAL;
1219 dev_dbg(&client->dev,
1220 "nfc-nci probe: %s, inside nfc-nci flags = %x\n",
1221 __func__, client->flags);
1222 if (platform_data == NULL) {
1223 dev_err(&client->dev, "nfc-nci probe: failed\n");
1224 return -ENODEV;
1225 }
1226 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
1227 dev_err(&client->dev, "nfc-nci probe: need I2C_FUNC_I2C\n");
1228 return -ENODEV;
1229 }
1230 qca199x_dev = kzalloc(sizeof(*qca199x_dev), GFP_KERNEL);
1231 if (qca199x_dev == NULL) {
1232 dev_err(&client->dev,
1233 "nfc-nci probe: failed to allocate memory for module data\n");
1234 return -ENOMEM;
1235 }
Houston Hoffmana0368172013-12-11 16:55:06 -08001236 qca199x_dev->client = client;
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001237
1238 /*
1239 * To be efficient we need to test whether nfcc hardware is physically
1240 * present before attempting further hardware initialisation.
1241 * For this we need to be sure the device is in ULPM state by
1242 * setting disable line low early on.
1243 *
1244 */
1245
1246
1247 if (gpio_is_valid(platform_data->dis_gpio)) {
1248 r = gpio_request(platform_data->dis_gpio, "nfc_reset_gpio");
1249 if (r) {
1250 dev_err(&client->dev,
1251 "NFC: unable to request gpio [%d]\n",
1252 platform_data->dis_gpio);
1253 goto err_free_dev;
1254 }
1255 r = gpio_direction_output(platform_data->dis_gpio, 1);
1256 if (r) {
1257 dev_err(&client->dev,
1258 "NFC: unable to set direction for gpio [%d]\n",
1259 platform_data->dis_gpio);
1260 goto err_dis_gpio;
1261 }
1262 } else {
1263 dev_err(&client->dev, "dis gpio not provided\n");
1264 goto err_free_dev;
1265 }
1266
Houston Hoffman814c4072014-03-13 17:50:22 -07001267 /* Guarantee that the NFCC starts in a clean state. */
1268 gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
1269 usleep(200);
1270 gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
1271 usleep(200);
1272
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001273 r = nfcc_hw_check(client, platform_data->reg);
1274 if (r) {
1275 /* We don't think there is hardware but just in case HPD */
1276 gpio_set_value(platform_data->dis_gpio, 1);
1277 goto err_dis_gpio;
1278 }
1279
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001280 if (gpio_is_valid(platform_data->irq_gpio)) {
1281 r = gpio_request(platform_data->irq_gpio, "nfc_irq_gpio");
1282 if (r) {
1283 dev_err(&client->dev, "unable to request gpio [%d]\n",
1284 platform_data->irq_gpio);
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001285 goto err_dis_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001286 }
1287 r = gpio_direction_input(platform_data->irq_gpio);
1288 if (r) {
1289
1290 dev_err(&client->dev,
1291 "unable to set direction for gpio [%d]\n",
1292 platform_data->irq_gpio);
1293 goto err_irq;
1294 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001295 irqn = gpio_to_irq(platform_data->irq_gpio);
1296 if (irqn < 0) {
1297 r = irqn;
1298 goto err_irq;
1299 }
1300 client->irq = irqn;
1301
1302 } else {
1303 dev_err(&client->dev, "irq gpio not provided\n");
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001304 goto err_dis_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001305 }
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001306 /* Interrupt from NFCC CLK_REQ to handle REF_CLK
1307 o/p gating/selection */
1308 if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
1309 (!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
1310 if (gpio_is_valid(platform_data->irq_gpio_clk_req)) {
1311 r = gpio_request(platform_data->irq_gpio_clk_req,
1312 "nfc_irq_gpio_clk_en");
1313 if (r) {
1314 dev_err(&client->dev, "unable to request CLK_EN gpio [%d]\n",
1315 platform_data->irq_gpio_clk_req);
1316 goto err_irq;
1317 }
1318 r = gpio_direction_input(
1319 platform_data->irq_gpio_clk_req);
1320 if (r) {
1321 dev_err(&client->dev,
1322 "unable to set direction for CLK_EN gpio [%d]\n",
1323 platform_data->irq_gpio_clk_req);
1324 goto err_irq_clk;
1325 }
1326 gpio_to_irq(0);
1327 irqn = gpio_to_irq(platform_data->irq_gpio_clk_req);
1328 if (irqn < 0) {
1329 r = irqn;
1330 goto err_irq_clk;
1331 }
1332 platform_data->clk_req_irq_num = irqn;
1333 } else {
1334 dev_err(&client->dev, "irq CLK_EN gpio not provided\n");
1335 goto err_irq;
1336 }
1337 }
Houston Hoffmana0368172013-12-11 16:55:06 -08001338 /* Get the clock source name and gpio from from Device Tree */
1339 qca199x_dev->clk_src_name = platform_data->clk_src_name;
1340 qca199x_dev->clk_src_gpio = platform_data->clk_src_gpio;
1341 qca199x_dev->clk_run = false;
1342 r = qca199x_clock_select(qca199x_dev);
1343 if (r != 0) {
1344 if (r == -1)
1345 goto err_clk;
1346 else
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001347 goto err_irq_clk;
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001348 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001349
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001350 if (strcmp(platform_data->clk_src_name, "GPCLK2")) {
1351 platform_data->clkreq_gpio =
1352 of_get_named_gpio(node, "qcom,clk-gpio", 0);
1353
1354 if (gpio_is_valid(platform_data->clkreq_gpio)) {
1355 r = gpio_request(platform_data->clkreq_gpio,
1356 "nfc_clkreq_gpio");
1357 if (r) {
1358 dev_err(&client->dev, "unable to request gpio [%d]\n",
1359 platform_data->clkreq_gpio);
1360 goto err_clkreq_gpio;
1361 }
1362 r = gpio_direction_input(platform_data->clkreq_gpio);
1363 if (r) {
1364 dev_err(&client->dev,
1365 "unable to set direction for gpio [%d]\n",
1366 platform_data->clkreq_gpio);
1367 goto err_clkreq_gpio;
1368 }
1369 } else {
1370 dev_err(&client->dev, "clkreq gpio not provided\n");
1371 goto err_clk;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001372 }
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001373 qca199x_dev->clkreq_gpio = platform_data->clkreq_gpio;
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001374 }
1375 qca199x_dev->dis_gpio = platform_data->dis_gpio;
1376 qca199x_dev->irq_gpio = platform_data->irq_gpio;
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001377 if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
1378 (!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
1379 qca199x_dev->irq_gpio_clk_req =
1380 platform_data->irq_gpio_clk_req;
1381 qca199x_dev->clk_req_irq_num =
1382 platform_data->clk_req_irq_num;
1383 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001384
1385 /* init mutex and queues */
1386 init_waitqueue_head(&qca199x_dev->read_wq);
1387 mutex_init(&qca199x_dev->read_mutex);
1388 spin_lock_init(&qca199x_dev->irq_enabled_lock);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001389 spin_lock_init(&qca199x_dev->irq_enabled_lock_clk_req);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001390
1391 qca199x_dev->qca199x_device.minor = MISC_DYNAMIC_MINOR;
1392 qca199x_dev->qca199x_device.name = "nfc-nci";
1393 qca199x_dev->qca199x_device.fops = &nfc_dev_fops;
1394
1395 r = misc_register(&qca199x_dev->qca199x_device);
1396 if (r) {
1397 dev_err(&client->dev, "misc_register failed\n");
1398 goto err_misc_register;
1399 }
1400
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001401
1402 /*
1403 * Reboot the NFCC now that all resources are ready
1404 *
1405 * The NFCC takes time to transition between power states.
1406 * We wait 20uS for the NFCC to shutdown. (HPD)
1407 * We wait 100uS for the NFCC to boot into ULPM.
1408 */
1409 gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
1410 msleep(20);
1411 gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
1412 msleep(100);
1413
1414
1415 /* Here we perform a second presence check. */
1416 r = nfcc_hw_check(client, platform_data->reg);
1417 if (r) {
1418 /* We don't think there is hardware but just in case HPD */
1419 gpio_set_value(platform_data->dis_gpio, 1);
1420 goto err_nfcc_not_present;
1421 }
Bansidhar Gopalacharid093f1f2013-10-22 20:44:07 -07001422
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001423 logging_level = 0;
1424 /* request irq. The irq is set whenever the chip has data available
1425 * for reading. It is cleared when all data has been read.
1426 */
Bansidhar Gopalachari25fc8742013-07-16 00:46:19 -07001427 device_mode.handle_flavour = UNSOLICITED_MODE;
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001428 /* NFC_INT IRQ */
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001429 qca199x_dev->irq_enabled = true;
1430 r = request_irq(client->irq, qca199x_dev_irq_handler,
1431 IRQF_TRIGGER_RISING, client->name, qca199x_dev);
1432 if (r) {
1433 dev_err(&client->dev, "nfc-nci probe: request_irq failed\n");
1434 goto err_request_irq_failed;
1435 }
1436 qca199x_disable_irq(qca199x_dev);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001437 /* CLK_REQ IRQ */
1438 if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
1439 (!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
1440 r = request_irq(qca199x_dev->clk_req_irq_num,
1441 qca199x_dev_irq_handler_clk_req,
1442 (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING),
1443 client->name, qca199x_dev);
1444 if (r) {
1445 dev_err(&client->dev,
1446 "nfc-nci probe: request_irq failed. irq no = %d\n, main irq = %d",
1447 qca199x_dev->clk_req_irq_num, client->irq);
1448 goto err_request_irq_failed;
1449 }
1450 qca199x_dev->irq_enabled_clk_req = true;
1451 qca199x_disable_irq_clk_req(qca199x_dev);
1452
1453
1454 qca199x_dev->my_wq =
1455 create_singlethread_workqueue("qca1990x_CLK_REQ_queue");
1456 if (!qca199x_dev->my_wq)
1457 goto err_create_workq;
1458
1459 INIT_WORK(&qca199x_dev->msm_clock_controll_work,
1460 clk_req_update);
1461 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001462 i2c_set_clientdata(client, qca199x_dev);
Houston Hoffmana0368172013-12-11 16:55:06 -08001463 gpio_set_value(platform_data->dis_gpio, 1);
Houston Hoffman2ab8e4b2014-02-08 14:02:13 -08001464
1465 /* To keep track if region2 command has been sent to controller */
1466 region2_sent = false;
1467
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001468 dev_dbg(&client->dev,
1469 "nfc-nci probe: %s, probing qca1990 exited successfully\n",
1470 __func__);
1471 return 0;
1472
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001473err_create_workq:
1474 dev_err(&client->dev,
1475 "nfc-nci probe: %s, work_queue creation failure\n",
1476 __func__);
1477 free_irq(client->irq, qca199x_dev);
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001478err_nfcc_not_present:
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001479err_request_irq_failed:
1480 misc_deregister(&qca199x_dev->qca199x_device);
1481err_misc_register:
1482 mutex_destroy(&qca199x_dev->read_mutex);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001483err_clkreq_gpio:
1484 if (strcmp(platform_data->clk_src_name, "GPCLK2"))
1485 gpio_free(platform_data->clkreq_gpio);
Bansidhar Gopalacharibe0e4d92013-09-19 19:30:36 +01001486err_clk:
Houston Hoffmana0368172013-12-11 16:55:06 -08001487 qca199x_clock_deselect(qca199x_dev);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001488err_irq_clk:
1489 if ((!strcmp(platform_data->clk_src_name, "GPCLK")) ||
1490 (!strcmp(platform_data->clk_src_name, "GPCLK2"))) {
1491 r = gpio_direction_input(platform_data->irq_gpio_clk_req);
1492 if (r)
1493 dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
1494 gpio_free(platform_data->irq_gpio_clk_req);
1495 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001496err_irq:
1497 gpio_free(platform_data->irq_gpio);
Houston Hoffmanc108e8f2014-01-10 16:12:16 -08001498err_dis_gpio:
1499 gpio_free(platform_data->dis_gpio);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001500err_free_dev:
1501 kfree(qca199x_dev);
1502 return r;
1503}
1504
1505static int qca199x_remove(struct i2c_client *client)
1506{
1507 struct qca199x_dev *qca199x_dev;
1508
1509 qca199x_dev = i2c_get_clientdata(client);
1510 free_irq(client->irq, qca199x_dev);
1511 misc_deregister(&qca199x_dev->qca199x_device);
1512 mutex_destroy(&qca199x_dev->read_mutex);
1513 gpio_free(qca199x_dev->irq_gpio);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001514 if ((!strcmp(qca199x_dev->clk_src_name, "GPCLK")) ||
1515 (!strcmp(qca199x_dev->clk_src_name, "GPCLK2"))) {
1516 gpio_free(qca199x_dev->irq_gpio_clk_req);
1517 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001518 gpio_free(qca199x_dev->dis_gpio);
Houston Hoffman17f2dc52014-01-29 08:15:06 -08001519 if (strcmp(qca199x_dev->clk_src_name, "GPCLK2"))
1520 gpio_free(qca199x_dev->clkreq_gpio);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001521 kfree(qca199x_dev);
1522
1523 return 0;
1524}
1525
1526static const struct i2c_device_id qca199x_id[] = {
1527 {"qca199x-i2c", 0},
1528 {}
1529};
1530
1531static struct i2c_driver qca199x = {
1532 .id_table = qca199x_id,
1533 .probe = qca199x_probe,
1534 .remove = qca199x_remove,
1535 .driver = {
1536 .owner = THIS_MODULE,
1537 .name = "nfc-nci",
1538 .of_match_table = msm_match_table,
1539 },
1540};
1541
Houston Hoffmanb03f6652014-01-16 16:28:02 -08001542
1543static int nfcc_reboot(struct notifier_block *notifier, unsigned long val,
1544 void *v)
1545{
Houston Hoffman2ab8e4b2014-02-08 14:02:13 -08001546 /*
1547 * Set DISABLE=1 *ONLY* if the NFC service has been disabled.
1548 * This will put NFCC into HPD(Hard Power Down) state for power
1549 * saving when powering down(Low Batt. or Power off handset)
1550 * If user requires NFC and CE mode when powered down(PD) the
1551 * middleware puts NFCC into region2 prior to PD. In this case
1552 * we DO NOT HPD chip as this will trash Region2 and CE support
1553 * when handset is PD.
1554 */
1555 if (region2_sent == false) {
1556 /* HPD the NFCC */
1557 gpio_set_value(disable_ctrl, 1);
1558 }
Houston Hoffmanb03f6652014-01-16 16:28:02 -08001559 return NOTIFY_OK;
1560}
1561
1562
1563static struct notifier_block nfcc_notifier = {
1564 .notifier_call = nfcc_reboot,
Houston Hoffman2ab8e4b2014-02-08 14:02:13 -08001565 .next = NULL,
1566 .priority = 0
Houston Hoffmanb03f6652014-01-16 16:28:02 -08001567};
1568
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001569/*
1570 * module load/unload record keeping
1571 */
1572static int __init qca199x_dev_init(void)
1573{
Houston Hoffmanb03f6652014-01-16 16:28:02 -08001574 int ret;
1575
1576 ret = register_reboot_notifier(&nfcc_notifier);
1577 if (ret) {
1578 pr_err("cannot register reboot notifier (err=%d)\n", ret);
1579 return ret;
1580 }
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001581 return i2c_add_driver(&qca199x);
1582}
1583module_init(qca199x_dev_init);
1584
1585static void __exit qca199x_dev_exit(void)
1586{
Houston Hoffmanb03f6652014-01-16 16:28:02 -08001587 unregister_reboot_notifier(&nfcc_notifier);
Madan Mohan Koyyalamudif2e7dcc2013-06-18 13:03:26 -07001588 i2c_del_driver(&qca199x);
1589}
1590module_exit(qca199x_dev_exit);
1591
1592MODULE_DESCRIPTION("NFC QCA199x");
1593MODULE_LICENSE("GPL v2");
1594