diff options
author | Cong Wang <xiyou.wangcong@gmail.com> | 2012-09-18 13:31:58 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-09-24 18:17:27 -0400 |
commit | 7b55279f6a454771d06e8ddf4a7114d17ae9a741 (patch) | |
tree | 5818ccd616d3c3bc0ff4dd9651665d6258c6886c | |
parent | 80faa59847108d48928fac41b4817ef21ca108a9 (diff) |
NFC: Remove the pn544 raw driver
This was scheduled for 3.6, we're late.
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | Documentation/feature-removal-schedule.txt | 12 | ||||
-rw-r--r-- | drivers/nfc/Kconfig | 12 | ||||
-rw-r--r-- | drivers/nfc/Makefile | 1 | ||||
-rw-r--r-- | drivers/nfc/pn544.c | 893 |
4 files changed, 0 insertions, 918 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index afaff312bf41..2cbbac8019c8 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -516,18 +516,6 @@ Who: Kees Cook <keescook@chromium.org> | |||
516 | 516 | ||
517 | ---------------------------- | 517 | ---------------------------- |
518 | 518 | ||
519 | What: Removing the pn544 raw driver. | ||
520 | When: 3.6 | ||
521 | Why: With the introduction of the NFC HCI and SHDL kernel layers, pn544.c | ||
522 | is being replaced by pn544_hci.c which is accessible through the netlink | ||
523 | and socket NFC APIs. Moreover, pn544.c is outdated and does not seem to | ||
524 | work properly with the latest Android stacks. | ||
525 | Having 2 drivers for the same hardware is confusing and as such we | ||
526 | should only keep the one following the kernel NFC APIs. | ||
527 | Who: Samuel Ortiz <sameo@linux.intel.com> | ||
528 | |||
529 | ---------------------------- | ||
530 | |||
531 | What: setitimer accepts user NULL pointer (value) | 519 | What: setitimer accepts user NULL pointer (value) |
532 | When: 3.6 | 520 | When: 3.6 |
533 | Why: setitimer is not returning -EFAULT if user pointer is NULL. This | 521 | Why: setitimer is not returning -EFAULT if user pointer is NULL. This |
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 89c57d1a7cad..ec857676c39f 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig | |||
@@ -5,18 +5,6 @@ | |||
5 | menu "Near Field Communication (NFC) devices" | 5 | menu "Near Field Communication (NFC) devices" |
6 | depends on NFC | 6 | depends on NFC |
7 | 7 | ||
8 | config PN544_NFC | ||
9 | tristate "PN544 NFC driver" | ||
10 | depends on I2C | ||
11 | select CRC_CCITT | ||
12 | default n | ||
13 | ---help--- | ||
14 | Say yes if you want PN544 Near Field Communication driver. | ||
15 | This is for i2c connected version. If unsure, say N here. | ||
16 | |||
17 | To compile this driver as a module, choose m here. The module will | ||
18 | be called pn544. | ||
19 | |||
20 | config PN544_HCI_NFC | 8 | config PN544_HCI_NFC |
21 | tristate "HCI PN544 NFC driver" | 9 | tristate "HCI PN544 NFC driver" |
22 | depends on I2C && NFC_HCI && NFC_SHDLC | 10 | depends on I2C && NFC_HCI && NFC_SHDLC |
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index 473e44cef612..bf05831fdf09 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile | |||
@@ -2,7 +2,6 @@ | |||
2 | # Makefile for nfc devices | 2 | # Makefile for nfc devices |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PN544_NFC) += pn544.o | ||
6 | obj-$(CONFIG_PN544_HCI_NFC) += pn544_hci.o | 5 | obj-$(CONFIG_PN544_HCI_NFC) += pn544_hci.o |
7 | obj-$(CONFIG_NFC_PN533) += pn533.o | 6 | obj-$(CONFIG_NFC_PN533) += pn533.o |
8 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o | 7 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o |
diff --git a/drivers/nfc/pn544.c b/drivers/nfc/pn544.c deleted file mode 100644 index 724f65d8f9e4..000000000000 --- a/drivers/nfc/pn544.c +++ /dev/null | |||
@@ -1,893 +0,0 @@ | |||
1 | /* | ||
2 | * Driver for the PN544 NFC chip. | ||
3 | * | ||
4 | * Copyright (C) Nokia Corporation | ||
5 | * | ||
6 | * Author: Jari Vanhala <ext-jari.vanhala@nokia.com> | ||
7 | * Contact: Matti Aaltonen <matti.j.aaltonen@nokia.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
21 | */ | ||
22 | |||
23 | #include <linux/completion.h> | ||
24 | #include <linux/crc-ccitt.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/miscdevice.h> | ||
29 | #include <linux/module.h> | ||
30 | #include <linux/mutex.h> | ||
31 | #include <linux/nfc/pn544.h> | ||
32 | #include <linux/poll.h> | ||
33 | #include <linux/regulator/consumer.h> | ||
34 | #include <linux/serial_core.h> /* for TCGETS */ | ||
35 | #include <linux/slab.h> | ||
36 | |||
37 | #define DRIVER_CARD "PN544 NFC" | ||
38 | #define DRIVER_DESC "NFC driver for PN544" | ||
39 | |||
40 | static struct i2c_device_id pn544_id_table[] = { | ||
41 | { PN544_DRIVER_NAME, 0 }, | ||
42 | { } | ||
43 | }; | ||
44 | MODULE_DEVICE_TABLE(i2c, pn544_id_table); | ||
45 | |||
46 | #define HCI_MODE 0 | ||
47 | #define FW_MODE 1 | ||
48 | |||
49 | enum pn544_state { | ||
50 | PN544_ST_COLD, | ||
51 | PN544_ST_FW_READY, | ||
52 | PN544_ST_READY, | ||
53 | }; | ||
54 | |||
55 | enum pn544_irq { | ||
56 | PN544_NONE, | ||
57 | PN544_INT, | ||
58 | }; | ||
59 | |||
60 | struct pn544_info { | ||
61 | struct miscdevice miscdev; | ||
62 | struct i2c_client *i2c_dev; | ||
63 | struct regulator_bulk_data regs[3]; | ||
64 | |||
65 | enum pn544_state state; | ||
66 | wait_queue_head_t read_wait; | ||
67 | loff_t read_offset; | ||
68 | enum pn544_irq read_irq; | ||
69 | struct mutex read_mutex; /* Serialize read_irq access */ | ||
70 | struct mutex mutex; /* Serialize info struct access */ | ||
71 | u8 *buf; | ||
72 | size_t buflen; | ||
73 | }; | ||
74 | |||
75 | static const char reg_vdd_io[] = "Vdd_IO"; | ||
76 | static const char reg_vbat[] = "VBat"; | ||
77 | static const char reg_vsim[] = "VSim"; | ||
78 | |||
79 | /* sysfs interface */ | ||
80 | static ssize_t pn544_test(struct device *dev, | ||
81 | struct device_attribute *attr, char *buf) | ||
82 | { | ||
83 | struct pn544_info *info = dev_get_drvdata(dev); | ||
84 | struct i2c_client *client = info->i2c_dev; | ||
85 | struct pn544_nfc_platform_data *pdata = client->dev.platform_data; | ||
86 | |||
87 | return snprintf(buf, PAGE_SIZE, "%d\n", pdata->test()); | ||
88 | } | ||
89 | |||
90 | static int pn544_enable(struct pn544_info *info, int mode) | ||
91 | { | ||
92 | struct pn544_nfc_platform_data *pdata; | ||
93 | struct i2c_client *client = info->i2c_dev; | ||
94 | |||
95 | int r; | ||
96 | |||
97 | r = regulator_bulk_enable(ARRAY_SIZE(info->regs), info->regs); | ||
98 | if (r < 0) | ||
99 | return r; | ||
100 | |||
101 | pdata = client->dev.platform_data; | ||
102 | info->read_irq = PN544_NONE; | ||
103 | if (pdata->enable) | ||
104 | pdata->enable(mode); | ||
105 | |||
106 | if (mode) { | ||
107 | info->state = PN544_ST_FW_READY; | ||
108 | dev_dbg(&client->dev, "now in FW-mode\n"); | ||
109 | } else { | ||
110 | info->state = PN544_ST_READY; | ||
111 | dev_dbg(&client->dev, "now in HCI-mode\n"); | ||
112 | } | ||
113 | |||
114 | usleep_range(10000, 15000); | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static void pn544_disable(struct pn544_info *info) | ||
120 | { | ||
121 | struct pn544_nfc_platform_data *pdata; | ||
122 | struct i2c_client *client = info->i2c_dev; | ||
123 | |||
124 | pdata = client->dev.platform_data; | ||
125 | if (pdata->disable) | ||
126 | pdata->disable(); | ||
127 | |||
128 | info->state = PN544_ST_COLD; | ||
129 | |||
130 | dev_dbg(&client->dev, "Now in OFF-mode\n"); | ||
131 | |||
132 | msleep(PN544_RESETVEN_TIME); | ||
133 | |||
134 | info->read_irq = PN544_NONE; | ||
135 | regulator_bulk_disable(ARRAY_SIZE(info->regs), info->regs); | ||
136 | } | ||
137 | |||
138 | static int check_crc(u8 *buf, int buflen) | ||
139 | { | ||
140 | u8 len; | ||
141 | u16 crc; | ||
142 | |||
143 | len = buf[0] + 1; | ||
144 | if (len < 4 || len != buflen || len > PN544_MSG_MAX_SIZE) { | ||
145 | pr_err(PN544_DRIVER_NAME | ||
146 | ": CRC; corrupt packet len %u (%d)\n", len, buflen); | ||
147 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | ||
148 | 16, 2, buf, buflen, false); | ||
149 | return -EPERM; | ||
150 | } | ||
151 | crc = crc_ccitt(0xffff, buf, len - 2); | ||
152 | crc = ~crc; | ||
153 | |||
154 | if (buf[len-2] != (crc & 0xff) || buf[len-1] != (crc >> 8)) { | ||
155 | pr_err(PN544_DRIVER_NAME ": CRC error 0x%x != 0x%x 0x%x\n", | ||
156 | crc, buf[len-1], buf[len-2]); | ||
157 | |||
158 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | ||
159 | 16, 2, buf, buflen, false); | ||
160 | return -EPERM; | ||
161 | } | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int pn544_i2c_write(struct i2c_client *client, u8 *buf, int len) | ||
166 | { | ||
167 | int r; | ||
168 | |||
169 | if (len < 4 || len != (buf[0] + 1)) { | ||
170 | dev_err(&client->dev, "%s: Illegal message length: %d\n", | ||
171 | __func__, len); | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | |||
175 | if (check_crc(buf, len)) | ||
176 | return -EINVAL; | ||
177 | |||
178 | usleep_range(3000, 6000); | ||
179 | |||
180 | r = i2c_master_send(client, buf, len); | ||
181 | dev_dbg(&client->dev, "send: %d\n", r); | ||
182 | |||
183 | if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | ||
184 | usleep_range(6000, 10000); | ||
185 | r = i2c_master_send(client, buf, len); | ||
186 | dev_dbg(&client->dev, "send2: %d\n", r); | ||
187 | } | ||
188 | |||
189 | if (r != len) | ||
190 | return -EREMOTEIO; | ||
191 | |||
192 | return r; | ||
193 | } | ||
194 | |||
195 | static int pn544_i2c_read(struct i2c_client *client, u8 *buf, int buflen) | ||
196 | { | ||
197 | int r; | ||
198 | u8 len; | ||
199 | |||
200 | /* | ||
201 | * You could read a packet in one go, but then you'd need to read | ||
202 | * max size and rest would be 0xff fill, so we do split reads. | ||
203 | */ | ||
204 | r = i2c_master_recv(client, &len, 1); | ||
205 | dev_dbg(&client->dev, "recv1: %d\n", r); | ||
206 | |||
207 | if (r != 1) | ||
208 | return -EREMOTEIO; | ||
209 | |||
210 | if (len < PN544_LLC_HCI_OVERHEAD) | ||
211 | len = PN544_LLC_HCI_OVERHEAD; | ||
212 | else if (len > (PN544_MSG_MAX_SIZE - 1)) | ||
213 | len = PN544_MSG_MAX_SIZE - 1; | ||
214 | |||
215 | if (1 + len > buflen) /* len+(data+crc16) */ | ||
216 | return -EMSGSIZE; | ||
217 | |||
218 | buf[0] = len; | ||
219 | |||
220 | r = i2c_master_recv(client, buf + 1, len); | ||
221 | dev_dbg(&client->dev, "recv2: %d\n", r); | ||
222 | |||
223 | if (r != len) | ||
224 | return -EREMOTEIO; | ||
225 | |||
226 | usleep_range(3000, 6000); | ||
227 | |||
228 | return r + 1; | ||
229 | } | ||
230 | |||
231 | static int pn544_fw_write(struct i2c_client *client, u8 *buf, int len) | ||
232 | { | ||
233 | int r; | ||
234 | |||
235 | dev_dbg(&client->dev, "%s\n", __func__); | ||
236 | |||
237 | if (len < PN544_FW_HEADER_SIZE || | ||
238 | (PN544_FW_HEADER_SIZE + (buf[1] << 8) + buf[2]) != len) | ||
239 | return -EINVAL; | ||
240 | |||
241 | r = i2c_master_send(client, buf, len); | ||
242 | dev_dbg(&client->dev, "fw send: %d\n", r); | ||
243 | |||
244 | if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | ||
245 | usleep_range(6000, 10000); | ||
246 | r = i2c_master_send(client, buf, len); | ||
247 | dev_dbg(&client->dev, "fw send2: %d\n", r); | ||
248 | } | ||
249 | |||
250 | if (r != len) | ||
251 | return -EREMOTEIO; | ||
252 | |||
253 | return r; | ||
254 | } | ||
255 | |||
256 | static int pn544_fw_read(struct i2c_client *client, u8 *buf, int buflen) | ||
257 | { | ||
258 | int r, len; | ||
259 | |||
260 | if (buflen < PN544_FW_HEADER_SIZE) | ||
261 | return -EINVAL; | ||
262 | |||
263 | r = i2c_master_recv(client, buf, PN544_FW_HEADER_SIZE); | ||
264 | dev_dbg(&client->dev, "FW recv1: %d\n", r); | ||
265 | |||
266 | if (r < 0) | ||
267 | return r; | ||
268 | |||
269 | if (r < PN544_FW_HEADER_SIZE) | ||
270 | return -EINVAL; | ||
271 | |||
272 | len = (buf[1] << 8) + buf[2]; | ||
273 | if (len == 0) /* just header, no additional data */ | ||
274 | return r; | ||
275 | |||
276 | if (len > buflen - PN544_FW_HEADER_SIZE) | ||
277 | return -EMSGSIZE; | ||
278 | |||
279 | r = i2c_master_recv(client, buf + PN544_FW_HEADER_SIZE, len); | ||
280 | dev_dbg(&client->dev, "fw recv2: %d\n", r); | ||
281 | |||
282 | if (r != len) | ||
283 | return -EINVAL; | ||
284 | |||
285 | return r + PN544_FW_HEADER_SIZE; | ||
286 | } | ||
287 | |||
288 | static irqreturn_t pn544_irq_thread_fn(int irq, void *dev_id) | ||
289 | { | ||
290 | struct pn544_info *info = dev_id; | ||
291 | struct i2c_client *client = info->i2c_dev; | ||
292 | |||
293 | BUG_ON(!info); | ||
294 | BUG_ON(irq != info->i2c_dev->irq); | ||
295 | |||
296 | dev_dbg(&client->dev, "IRQ\n"); | ||
297 | |||
298 | mutex_lock(&info->read_mutex); | ||
299 | info->read_irq = PN544_INT; | ||
300 | mutex_unlock(&info->read_mutex); | ||
301 | |||
302 | wake_up_interruptible(&info->read_wait); | ||
303 | |||
304 | return IRQ_HANDLED; | ||
305 | } | ||
306 | |||
307 | static enum pn544_irq pn544_irq_state(struct pn544_info *info) | ||
308 | { | ||
309 | enum pn544_irq irq; | ||
310 | |||
311 | mutex_lock(&info->read_mutex); | ||
312 | irq = info->read_irq; | ||
313 | mutex_unlock(&info->read_mutex); | ||
314 | /* | ||
315 | * XXX: should we check GPIO-line status directly? | ||
316 | * return pdata->irq_status() ? PN544_INT : PN544_NONE; | ||
317 | */ | ||
318 | |||
319 | return irq; | ||
320 | } | ||
321 | |||
322 | static ssize_t pn544_read(struct file *file, char __user *buf, | ||
323 | size_t count, loff_t *offset) | ||
324 | { | ||
325 | struct pn544_info *info = container_of(file->private_data, | ||
326 | struct pn544_info, miscdev); | ||
327 | struct i2c_client *client = info->i2c_dev; | ||
328 | enum pn544_irq irq; | ||
329 | size_t len; | ||
330 | int r = 0; | ||
331 | |||
332 | dev_dbg(&client->dev, "%s: info: %p, count: %zu\n", __func__, | ||
333 | info, count); | ||
334 | |||
335 | mutex_lock(&info->mutex); | ||
336 | |||
337 | if (info->state == PN544_ST_COLD) { | ||
338 | r = -ENODEV; | ||
339 | goto out; | ||
340 | } | ||
341 | |||
342 | irq = pn544_irq_state(info); | ||
343 | if (irq == PN544_NONE) { | ||
344 | if (file->f_flags & O_NONBLOCK) { | ||
345 | r = -EAGAIN; | ||
346 | goto out; | ||
347 | } | ||
348 | |||
349 | if (wait_event_interruptible(info->read_wait, | ||
350 | (info->read_irq == PN544_INT))) { | ||
351 | r = -ERESTARTSYS; | ||
352 | goto out; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | if (info->state == PN544_ST_FW_READY) { | ||
357 | len = min(count, info->buflen); | ||
358 | |||
359 | mutex_lock(&info->read_mutex); | ||
360 | r = pn544_fw_read(info->i2c_dev, info->buf, len); | ||
361 | info->read_irq = PN544_NONE; | ||
362 | mutex_unlock(&info->read_mutex); | ||
363 | |||
364 | if (r < 0) { | ||
365 | dev_err(&info->i2c_dev->dev, "FW read failed: %d\n", r); | ||
366 | goto out; | ||
367 | } | ||
368 | |||
369 | print_hex_dump(KERN_DEBUG, "FW read: ", DUMP_PREFIX_NONE, | ||
370 | 16, 2, info->buf, r, false); | ||
371 | |||
372 | *offset += r; | ||
373 | if (copy_to_user(buf, info->buf, r)) { | ||
374 | r = -EFAULT; | ||
375 | goto out; | ||
376 | } | ||
377 | } else { | ||
378 | len = min(count, info->buflen); | ||
379 | |||
380 | mutex_lock(&info->read_mutex); | ||
381 | r = pn544_i2c_read(info->i2c_dev, info->buf, len); | ||
382 | info->read_irq = PN544_NONE; | ||
383 | mutex_unlock(&info->read_mutex); | ||
384 | |||
385 | if (r < 0) { | ||
386 | dev_err(&info->i2c_dev->dev, "read failed (%d)\n", r); | ||
387 | goto out; | ||
388 | } | ||
389 | print_hex_dump(KERN_DEBUG, "read: ", DUMP_PREFIX_NONE, | ||
390 | 16, 2, info->buf, r, false); | ||
391 | |||
392 | *offset += r; | ||
393 | if (copy_to_user(buf, info->buf, r)) { | ||
394 | r = -EFAULT; | ||
395 | goto out; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | out: | ||
400 | mutex_unlock(&info->mutex); | ||
401 | |||
402 | return r; | ||
403 | } | ||
404 | |||
405 | static unsigned int pn544_poll(struct file *file, poll_table *wait) | ||
406 | { | ||
407 | struct pn544_info *info = container_of(file->private_data, | ||
408 | struct pn544_info, miscdev); | ||
409 | struct i2c_client *client = info->i2c_dev; | ||
410 | int r = 0; | ||
411 | |||
412 | dev_dbg(&client->dev, "%s: info: %p\n", __func__, info); | ||
413 | |||
414 | mutex_lock(&info->mutex); | ||
415 | |||
416 | if (info->state == PN544_ST_COLD) { | ||
417 | r = -ENODEV; | ||
418 | goto out; | ||
419 | } | ||
420 | |||
421 | poll_wait(file, &info->read_wait, wait); | ||
422 | |||
423 | if (pn544_irq_state(info) == PN544_INT) { | ||
424 | r = POLLIN | POLLRDNORM; | ||
425 | goto out; | ||
426 | } | ||
427 | out: | ||
428 | mutex_unlock(&info->mutex); | ||
429 | |||
430 | return r; | ||
431 | } | ||
432 | |||
433 | static ssize_t pn544_write(struct file *file, const char __user *buf, | ||
434 | size_t count, loff_t *ppos) | ||
435 | { | ||
436 | struct pn544_info *info = container_of(file->private_data, | ||
437 | struct pn544_info, miscdev); | ||
438 | struct i2c_client *client = info->i2c_dev; | ||
439 | ssize_t len; | ||
440 | int r; | ||
441 | |||
442 | dev_dbg(&client->dev, "%s: info: %p, count %zu\n", __func__, | ||
443 | info, count); | ||
444 | |||
445 | mutex_lock(&info->mutex); | ||
446 | |||
447 | if (info->state == PN544_ST_COLD) { | ||
448 | r = -ENODEV; | ||
449 | goto out; | ||
450 | } | ||
451 | |||
452 | /* | ||
453 | * XXX: should we detect rset-writes and clean possible | ||
454 | * read_irq state | ||
455 | */ | ||
456 | if (info->state == PN544_ST_FW_READY) { | ||
457 | size_t fw_len; | ||
458 | |||
459 | if (count < PN544_FW_HEADER_SIZE) { | ||
460 | r = -EINVAL; | ||
461 | goto out; | ||
462 | } | ||
463 | |||
464 | len = min(count, info->buflen); | ||
465 | if (copy_from_user(info->buf, buf, len)) { | ||
466 | r = -EFAULT; | ||
467 | goto out; | ||
468 | } | ||
469 | |||
470 | print_hex_dump(KERN_DEBUG, "FW write: ", DUMP_PREFIX_NONE, | ||
471 | 16, 2, info->buf, len, false); | ||
472 | |||
473 | fw_len = PN544_FW_HEADER_SIZE + (info->buf[1] << 8) + | ||
474 | info->buf[2]; | ||
475 | |||
476 | if (len > fw_len) /* 1 msg at a time */ | ||
477 | len = fw_len; | ||
478 | |||
479 | r = pn544_fw_write(info->i2c_dev, info->buf, len); | ||
480 | } else { | ||
481 | if (count < PN544_LLC_MIN_SIZE) { | ||
482 | r = -EINVAL; | ||
483 | goto out; | ||
484 | } | ||
485 | |||
486 | len = min(count, info->buflen); | ||
487 | if (copy_from_user(info->buf, buf, len)) { | ||
488 | r = -EFAULT; | ||
489 | goto out; | ||
490 | } | ||
491 | |||
492 | print_hex_dump(KERN_DEBUG, "write: ", DUMP_PREFIX_NONE, | ||
493 | 16, 2, info->buf, len, false); | ||
494 | |||
495 | if (len > (info->buf[0] + 1)) /* 1 msg at a time */ | ||
496 | len = info->buf[0] + 1; | ||
497 | |||
498 | r = pn544_i2c_write(info->i2c_dev, info->buf, len); | ||
499 | } | ||
500 | out: | ||
501 | mutex_unlock(&info->mutex); | ||
502 | |||
503 | return r; | ||
504 | |||
505 | } | ||
506 | |||
507 | static long pn544_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
508 | { | ||
509 | struct pn544_info *info = container_of(file->private_data, | ||
510 | struct pn544_info, miscdev); | ||
511 | struct i2c_client *client = info->i2c_dev; | ||
512 | struct pn544_nfc_platform_data *pdata; | ||
513 | unsigned int val; | ||
514 | int r = 0; | ||
515 | |||
516 | dev_dbg(&client->dev, "%s: info: %p, cmd: 0x%x\n", __func__, info, cmd); | ||
517 | |||
518 | mutex_lock(&info->mutex); | ||
519 | |||
520 | if (info->state == PN544_ST_COLD) { | ||
521 | r = -ENODEV; | ||
522 | goto out; | ||
523 | } | ||
524 | |||
525 | pdata = info->i2c_dev->dev.platform_data; | ||
526 | switch (cmd) { | ||
527 | case PN544_GET_FW_MODE: | ||
528 | dev_dbg(&client->dev, "%s: PN544_GET_FW_MODE\n", __func__); | ||
529 | |||
530 | val = (info->state == PN544_ST_FW_READY); | ||
531 | if (copy_to_user((void __user *)arg, &val, sizeof(val))) { | ||
532 | r = -EFAULT; | ||
533 | goto out; | ||
534 | } | ||
535 | |||
536 | break; | ||
537 | |||
538 | case PN544_SET_FW_MODE: | ||
539 | dev_dbg(&client->dev, "%s: PN544_SET_FW_MODE\n", __func__); | ||
540 | |||
541 | if (copy_from_user(&val, (void __user *)arg, sizeof(val))) { | ||
542 | r = -EFAULT; | ||
543 | goto out; | ||
544 | } | ||
545 | |||
546 | if (val) { | ||
547 | if (info->state == PN544_ST_FW_READY) | ||
548 | break; | ||
549 | |||
550 | pn544_disable(info); | ||
551 | r = pn544_enable(info, FW_MODE); | ||
552 | if (r < 0) | ||
553 | goto out; | ||
554 | } else { | ||
555 | if (info->state == PN544_ST_READY) | ||
556 | break; | ||
557 | pn544_disable(info); | ||
558 | r = pn544_enable(info, HCI_MODE); | ||
559 | if (r < 0) | ||
560 | goto out; | ||
561 | } | ||
562 | file->f_pos = info->read_offset; | ||
563 | break; | ||
564 | |||
565 | case TCGETS: | ||
566 | dev_dbg(&client->dev, "%s: TCGETS\n", __func__); | ||
567 | |||
568 | r = -ENOIOCTLCMD; | ||
569 | break; | ||
570 | |||
571 | default: | ||
572 | dev_err(&client->dev, "Unknown ioctl 0x%x\n", cmd); | ||
573 | r = -ENOIOCTLCMD; | ||
574 | break; | ||
575 | } | ||
576 | |||
577 | out: | ||
578 | mutex_unlock(&info->mutex); | ||
579 | |||
580 | return r; | ||
581 | } | ||
582 | |||
583 | static int pn544_open(struct inode *inode, struct file *file) | ||
584 | { | ||
585 | struct pn544_info *info = container_of(file->private_data, | ||
586 | struct pn544_info, miscdev); | ||
587 | struct i2c_client *client = info->i2c_dev; | ||
588 | int r = 0; | ||
589 | |||
590 | dev_dbg(&client->dev, "%s: info: %p, client %p\n", __func__, | ||
591 | info, info->i2c_dev); | ||
592 | |||
593 | mutex_lock(&info->mutex); | ||
594 | |||
595 | /* | ||
596 | * Only 1 at a time. | ||
597 | * XXX: maybe user (counter) would work better | ||
598 | */ | ||
599 | if (info->state != PN544_ST_COLD) { | ||
600 | r = -EBUSY; | ||
601 | goto out; | ||
602 | } | ||
603 | |||
604 | file->f_pos = info->read_offset; | ||
605 | r = pn544_enable(info, HCI_MODE); | ||
606 | |||
607 | out: | ||
608 | mutex_unlock(&info->mutex); | ||
609 | return r; | ||
610 | } | ||
611 | |||
612 | static int pn544_close(struct inode *inode, struct file *file) | ||
613 | { | ||
614 | struct pn544_info *info = container_of(file->private_data, | ||
615 | struct pn544_info, miscdev); | ||
616 | struct i2c_client *client = info->i2c_dev; | ||
617 | |||
618 | dev_dbg(&client->dev, "%s: info: %p, client %p\n", | ||
619 | __func__, info, info->i2c_dev); | ||
620 | |||
621 | mutex_lock(&info->mutex); | ||
622 | pn544_disable(info); | ||
623 | mutex_unlock(&info->mutex); | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static const struct file_operations pn544_fops = { | ||
629 | .owner = THIS_MODULE, | ||
630 | .llseek = no_llseek, | ||
631 | .read = pn544_read, | ||
632 | .write = pn544_write, | ||
633 | .poll = pn544_poll, | ||
634 | .open = pn544_open, | ||
635 | .release = pn544_close, | ||
636 | .unlocked_ioctl = pn544_ioctl, | ||
637 | }; | ||
638 | |||
639 | #ifdef CONFIG_PM | ||
640 | static int pn544_suspend(struct device *dev) | ||
641 | { | ||
642 | struct i2c_client *client = to_i2c_client(dev); | ||
643 | struct pn544_info *info; | ||
644 | int r = 0; | ||
645 | |||
646 | dev_info(&client->dev, "***\n%s: client %p\n***\n", __func__, client); | ||
647 | |||
648 | info = i2c_get_clientdata(client); | ||
649 | dev_info(&client->dev, "%s: info: %p, client %p\n", __func__, | ||
650 | info, client); | ||
651 | |||
652 | mutex_lock(&info->mutex); | ||
653 | |||
654 | switch (info->state) { | ||
655 | case PN544_ST_FW_READY: | ||
656 | /* Do not suspend while upgrading FW, please! */ | ||
657 | r = -EPERM; | ||
658 | break; | ||
659 | |||
660 | case PN544_ST_READY: | ||
661 | /* | ||
662 | * CHECK: Device should be in standby-mode. No way to check? | ||
663 | * Allowing low power mode for the regulator is potentially | ||
664 | * dangerous if pn544 does not go to suspension. | ||
665 | */ | ||
666 | break; | ||
667 | |||
668 | case PN544_ST_COLD: | ||
669 | break; | ||
670 | }; | ||
671 | |||
672 | mutex_unlock(&info->mutex); | ||
673 | return r; | ||
674 | } | ||
675 | |||
676 | static int pn544_resume(struct device *dev) | ||
677 | { | ||
678 | struct i2c_client *client = to_i2c_client(dev); | ||
679 | struct pn544_info *info = i2c_get_clientdata(client); | ||
680 | int r = 0; | ||
681 | |||
682 | dev_dbg(&client->dev, "%s: info: %p, client %p\n", __func__, | ||
683 | info, client); | ||
684 | |||
685 | mutex_lock(&info->mutex); | ||
686 | |||
687 | switch (info->state) { | ||
688 | case PN544_ST_READY: | ||
689 | /* | ||
690 | * CHECK: If regulator low power mode is allowed in | ||
691 | * pn544_suspend, we should go back to normal mode | ||
692 | * here. | ||
693 | */ | ||
694 | break; | ||
695 | |||
696 | case PN544_ST_COLD: | ||
697 | break; | ||
698 | |||
699 | case PN544_ST_FW_READY: | ||
700 | break; | ||
701 | }; | ||
702 | |||
703 | mutex_unlock(&info->mutex); | ||
704 | |||
705 | return r; | ||
706 | } | ||
707 | |||
708 | static SIMPLE_DEV_PM_OPS(pn544_pm_ops, pn544_suspend, pn544_resume); | ||
709 | #endif | ||
710 | |||
711 | static struct device_attribute pn544_attr = | ||
712 | __ATTR(nfc_test, S_IRUGO, pn544_test, NULL); | ||
713 | |||
714 | static int __devinit pn544_probe(struct i2c_client *client, | ||
715 | const struct i2c_device_id *id) | ||
716 | { | ||
717 | struct pn544_info *info; | ||
718 | struct pn544_nfc_platform_data *pdata; | ||
719 | int r = 0; | ||
720 | |||
721 | dev_dbg(&client->dev, "%s\n", __func__); | ||
722 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | ||
723 | |||
724 | /* private data allocation */ | ||
725 | info = kzalloc(sizeof(struct pn544_info), GFP_KERNEL); | ||
726 | if (!info) { | ||
727 | dev_err(&client->dev, | ||
728 | "Cannot allocate memory for pn544_info.\n"); | ||
729 | r = -ENOMEM; | ||
730 | goto err_info_alloc; | ||
731 | } | ||
732 | |||
733 | info->buflen = max(PN544_MSG_MAX_SIZE, PN544_MAX_I2C_TRANSFER); | ||
734 | info->buf = kzalloc(info->buflen, GFP_KERNEL); | ||
735 | if (!info->buf) { | ||
736 | dev_err(&client->dev, | ||
737 | "Cannot allocate memory for pn544_info->buf.\n"); | ||
738 | r = -ENOMEM; | ||
739 | goto err_buf_alloc; | ||
740 | } | ||
741 | |||
742 | info->regs[0].supply = reg_vdd_io; | ||
743 | info->regs[1].supply = reg_vbat; | ||
744 | info->regs[2].supply = reg_vsim; | ||
745 | r = regulator_bulk_get(&client->dev, ARRAY_SIZE(info->regs), | ||
746 | info->regs); | ||
747 | if (r < 0) | ||
748 | goto err_kmalloc; | ||
749 | |||
750 | info->i2c_dev = client; | ||
751 | info->state = PN544_ST_COLD; | ||
752 | info->read_irq = PN544_NONE; | ||
753 | mutex_init(&info->read_mutex); | ||
754 | mutex_init(&info->mutex); | ||
755 | init_waitqueue_head(&info->read_wait); | ||
756 | i2c_set_clientdata(client, info); | ||
757 | pdata = client->dev.platform_data; | ||
758 | if (!pdata) { | ||
759 | dev_err(&client->dev, "No platform data\n"); | ||
760 | r = -EINVAL; | ||
761 | goto err_reg; | ||
762 | } | ||
763 | |||
764 | if (!pdata->request_resources) { | ||
765 | dev_err(&client->dev, "request_resources() missing\n"); | ||
766 | r = -EINVAL; | ||
767 | goto err_reg; | ||
768 | } | ||
769 | |||
770 | r = pdata->request_resources(client); | ||
771 | if (r) { | ||
772 | dev_err(&client->dev, "Cannot get platform resources\n"); | ||
773 | goto err_reg; | ||
774 | } | ||
775 | |||
776 | r = request_threaded_irq(client->irq, NULL, pn544_irq_thread_fn, | ||
777 | IRQF_TRIGGER_RISING, PN544_DRIVER_NAME, | ||
778 | info); | ||
779 | if (r < 0) { | ||
780 | dev_err(&client->dev, "Unable to register IRQ handler\n"); | ||
781 | goto err_res; | ||
782 | } | ||
783 | |||
784 | /* If we don't have the test we don't need the sysfs file */ | ||
785 | if (pdata->test) { | ||
786 | r = device_create_file(&client->dev, &pn544_attr); | ||
787 | if (r) { | ||
788 | dev_err(&client->dev, | ||
789 | "sysfs registration failed, error %d\n", r); | ||
790 | goto err_irq; | ||
791 | } | ||
792 | } | ||
793 | |||
794 | info->miscdev.minor = MISC_DYNAMIC_MINOR; | ||
795 | info->miscdev.name = PN544_DRIVER_NAME; | ||
796 | info->miscdev.fops = &pn544_fops; | ||
797 | info->miscdev.parent = &client->dev; | ||
798 | r = misc_register(&info->miscdev); | ||
799 | if (r < 0) { | ||
800 | dev_err(&client->dev, "Device registration failed\n"); | ||
801 | goto err_sysfs; | ||
802 | } | ||
803 | |||
804 | dev_dbg(&client->dev, "%s: info: %p, pdata %p, client %p\n", | ||
805 | __func__, info, pdata, client); | ||
806 | |||
807 | return 0; | ||
808 | |||
809 | err_sysfs: | ||
810 | if (pdata->test) | ||
811 | device_remove_file(&client->dev, &pn544_attr); | ||
812 | err_irq: | ||
813 | free_irq(client->irq, info); | ||
814 | err_res: | ||
815 | if (pdata->free_resources) | ||
816 | pdata->free_resources(); | ||
817 | err_reg: | ||
818 | regulator_bulk_free(ARRAY_SIZE(info->regs), info->regs); | ||
819 | err_kmalloc: | ||
820 | kfree(info->buf); | ||
821 | err_buf_alloc: | ||
822 | kfree(info); | ||
823 | err_info_alloc: | ||
824 | return r; | ||
825 | } | ||
826 | |||
827 | static __devexit int pn544_remove(struct i2c_client *client) | ||
828 | { | ||
829 | struct pn544_info *info = i2c_get_clientdata(client); | ||
830 | struct pn544_nfc_platform_data *pdata = client->dev.platform_data; | ||
831 | |||
832 | dev_dbg(&client->dev, "%s\n", __func__); | ||
833 | |||
834 | misc_deregister(&info->miscdev); | ||
835 | if (pdata->test) | ||
836 | device_remove_file(&client->dev, &pn544_attr); | ||
837 | |||
838 | if (info->state != PN544_ST_COLD) { | ||
839 | if (pdata->disable) | ||
840 | pdata->disable(); | ||
841 | |||
842 | info->read_irq = PN544_NONE; | ||
843 | } | ||
844 | |||
845 | free_irq(client->irq, info); | ||
846 | if (pdata->free_resources) | ||
847 | pdata->free_resources(); | ||
848 | |||
849 | regulator_bulk_free(ARRAY_SIZE(info->regs), info->regs); | ||
850 | kfree(info->buf); | ||
851 | kfree(info); | ||
852 | |||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | static struct i2c_driver pn544_driver = { | ||
857 | .driver = { | ||
858 | .name = PN544_DRIVER_NAME, | ||
859 | #ifdef CONFIG_PM | ||
860 | .pm = &pn544_pm_ops, | ||
861 | #endif | ||
862 | }, | ||
863 | .probe = pn544_probe, | ||
864 | .id_table = pn544_id_table, | ||
865 | .remove = __devexit_p(pn544_remove), | ||
866 | }; | ||
867 | |||
868 | static int __init pn544_init(void) | ||
869 | { | ||
870 | int r; | ||
871 | |||
872 | pr_debug(DRIVER_DESC ": %s\n", __func__); | ||
873 | |||
874 | r = i2c_add_driver(&pn544_driver); | ||
875 | if (r) { | ||
876 | pr_err(PN544_DRIVER_NAME ": driver registration failed\n"); | ||
877 | return r; | ||
878 | } | ||
879 | |||
880 | return 0; | ||
881 | } | ||
882 | |||
883 | static void __exit pn544_exit(void) | ||
884 | { | ||
885 | i2c_del_driver(&pn544_driver); | ||
886 | pr_info(DRIVER_DESC ", Exiting.\n"); | ||
887 | } | ||
888 | |||
889 | module_init(pn544_init); | ||
890 | module_exit(pn544_exit); | ||
891 | |||
892 | MODULE_LICENSE("GPL"); | ||
893 | MODULE_DESCRIPTION(DRIVER_DESC); | ||