diff options
author | Michael Thalmeier <michael.thalmeier@hale.at> | 2016-03-25 10:46:54 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2016-04-09 17:53:20 -0400 |
commit | dd7bedcd2673e4c8957d15d7e6e649fc6fa40206 (patch) | |
tree | dbe51f2048ed438bf00b95e068ba8601bc05265f | |
parent | 9815c7cf22daceabfb919ddcd6f2c80e049c1fbc (diff) |
NFC: pn533: add I2C phy driver
This adds the I2C phy interface for the pn533 driver.
This way the driver can be used to interact with I2C
connected pn532 devices.
Signed-off-by: Michael Thalmeier <michael.thalmeier@hale.at>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | drivers/nfc/pn533/Kconfig | 11 | ||||
-rw-r--r-- | drivers/nfc/pn533/Makefile | 2 | ||||
-rw-r--r-- | drivers/nfc/pn533/i2c.c | 271 | ||||
-rw-r--r-- | drivers/nfc/pn533/pn533.c | 31 | ||||
-rw-r--r-- | drivers/nfc/pn533/pn533.h | 2 |
5 files changed, 317 insertions, 0 deletions
diff --git a/drivers/nfc/pn533/Kconfig b/drivers/nfc/pn533/Kconfig index b5a926e42f7b..d94122dd30e4 100644 --- a/drivers/nfc/pn533/Kconfig +++ b/drivers/nfc/pn533/Kconfig | |||
@@ -14,3 +14,14 @@ config NFC_PN533_USB | |||
14 | 14 | ||
15 | If you choose to build a module, it'll be called pn533_usb. | 15 | If you choose to build a module, it'll be called pn533_usb. |
16 | Say N if unsure. | 16 | Say N if unsure. |
17 | |||
18 | config NFC_PN533_I2C | ||
19 | tristate "NFC PN533 device support (I2C)" | ||
20 | depends on I2C | ||
21 | select NFC_PN533 | ||
22 | ---help--- | ||
23 | This module adds support for the NXP pn533 I2C interface. | ||
24 | Select this if your platform is using the I2C bus. | ||
25 | |||
26 | If you choose to build a module, it'll be called pn533_i2c. | ||
27 | Say N if unsure. | ||
diff --git a/drivers/nfc/pn533/Makefile b/drivers/nfc/pn533/Makefile index 12c6be481483..51d24c622fcb 100644 --- a/drivers/nfc/pn533/Makefile +++ b/drivers/nfc/pn533/Makefile | |||
@@ -2,6 +2,8 @@ | |||
2 | # Makefile for PN533 NFC driver | 2 | # Makefile for PN533 NFC driver |
3 | # | 3 | # |
4 | pn533_usb-objs = usb.o | 4 | pn533_usb-objs = usb.o |
5 | pn533_i2c-objs = i2c.o | ||
5 | 6 | ||
6 | obj-$(CONFIG_NFC_PN533) += pn533.o | 7 | obj-$(CONFIG_NFC_PN533) += pn533.o |
7 | obj-$(CONFIG_NFC_PN533_USB) += pn533_usb.o | 8 | obj-$(CONFIG_NFC_PN533_USB) += pn533_usb.o |
9 | obj-$(CONFIG_NFC_PN533_I2C) += pn533_i2c.o | ||
diff --git a/drivers/nfc/pn533/i2c.c b/drivers/nfc/pn533/i2c.c new file mode 100644 index 000000000000..9679aa52c381 --- /dev/null +++ b/drivers/nfc/pn533/i2c.c | |||
@@ -0,0 +1,271 @@ | |||
1 | /* | ||
2 | * Driver for NXP PN533 NFC Chip - I2C transport layer | ||
3 | * | ||
4 | * Copyright (C) 2011 Instituto Nokia de Tecnologia | ||
5 | * Copyright (C) 2012-2013 Tieto Poland | ||
6 | * Copyright (C) 2016 HALE electronic | ||
7 | * | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
21 | */ | ||
22 | |||
23 | #include <linux/device.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/nfc.h> | ||
29 | #include <linux/netdevice.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <net/nfc/nfc.h> | ||
32 | #include "pn533.h" | ||
33 | |||
34 | #define VERSION "0.1" | ||
35 | |||
36 | #define PN533_I2C_DRIVER_NAME "pn533_i2c" | ||
37 | |||
38 | struct pn533_i2c_phy { | ||
39 | struct i2c_client *i2c_dev; | ||
40 | struct pn533 *priv; | ||
41 | |||
42 | int hard_fault; /* | ||
43 | * < 0 if hardware error occurred (e.g. i2c err) | ||
44 | * and prevents normal operation. | ||
45 | */ | ||
46 | }; | ||
47 | |||
48 | static int pn533_i2c_send_ack(struct pn533 *dev, gfp_t flags) | ||
49 | { | ||
50 | struct pn533_i2c_phy *phy = dev->phy; | ||
51 | struct i2c_client *client = phy->i2c_dev; | ||
52 | u8 ack[6] = {0x00, 0x00, 0xff, 0x00, 0xff, 0x00}; | ||
53 | /* spec 6.2.1.3: Preamble, SoPC (2), ACK Code (2), Postamble */ | ||
54 | int rc; | ||
55 | |||
56 | rc = i2c_master_send(client, ack, 6); | ||
57 | |||
58 | return rc; | ||
59 | } | ||
60 | |||
61 | static int pn533_i2c_send_frame(struct pn533 *dev, | ||
62 | struct sk_buff *out) | ||
63 | { | ||
64 | struct pn533_i2c_phy *phy = dev->phy; | ||
65 | struct i2c_client *client = phy->i2c_dev; | ||
66 | int rc; | ||
67 | |||
68 | if (phy->hard_fault != 0) | ||
69 | return phy->hard_fault; | ||
70 | |||
71 | if (phy->priv == NULL) | ||
72 | phy->priv = dev; | ||
73 | |||
74 | print_hex_dump_debug("PN533_i2c TX: ", DUMP_PREFIX_NONE, 16, 1, | ||
75 | out->data, out->len, false); | ||
76 | |||
77 | rc = i2c_master_send(client, out->data, out->len); | ||
78 | |||
79 | if (rc == -EREMOTEIO) { /* Retry, chip was in power down */ | ||
80 | usleep_range(6000, 10000); | ||
81 | rc = i2c_master_send(client, out->data, out->len); | ||
82 | } | ||
83 | |||
84 | if (rc >= 0) { | ||
85 | if (rc != out->len) | ||
86 | rc = -EREMOTEIO; | ||
87 | else | ||
88 | rc = 0; | ||
89 | } | ||
90 | |||
91 | return rc; | ||
92 | } | ||
93 | |||
94 | static void pn533_i2c_abort_cmd(struct pn533 *dev, gfp_t flags) | ||
95 | { | ||
96 | /* An ack will cancel the last issued command */ | ||
97 | pn533_i2c_send_ack(dev, flags); | ||
98 | |||
99 | /* schedule cmd_complete_work to finish current command execution */ | ||
100 | if (dev->cmd != NULL) | ||
101 | dev->cmd->status = -ENOENT; | ||
102 | queue_work(dev->wq, &dev->cmd_complete_work); | ||
103 | } | ||
104 | |||
105 | static int pn533_i2c_read(struct pn533_i2c_phy *phy, struct sk_buff **skb) | ||
106 | { | ||
107 | struct i2c_client *client = phy->i2c_dev; | ||
108 | int len = PN533_EXT_FRAME_HEADER_LEN + | ||
109 | PN533_STD_FRAME_MAX_PAYLOAD_LEN + | ||
110 | PN533_STD_FRAME_TAIL_LEN + 1; | ||
111 | int r; | ||
112 | |||
113 | *skb = alloc_skb(len, GFP_KERNEL); | ||
114 | if (*skb == NULL) | ||
115 | return -ENOMEM; | ||
116 | |||
117 | r = i2c_master_recv(client, skb_put(*skb, len), len); | ||
118 | if (r != len) { | ||
119 | nfc_err(&client->dev, "cannot read. r=%d len=%d\n", r, len); | ||
120 | kfree_skb(*skb); | ||
121 | return -EREMOTEIO; | ||
122 | } | ||
123 | |||
124 | if (!((*skb)->data[0] & 0x01)) { | ||
125 | nfc_err(&client->dev, "READY flag not set"); | ||
126 | kfree_skb(*skb); | ||
127 | return -EBUSY; | ||
128 | } | ||
129 | |||
130 | /* remove READY byte */ | ||
131 | skb_pull(*skb, 1); | ||
132 | /* trim to frame size */ | ||
133 | skb_trim(*skb, phy->priv->ops->rx_frame_size((*skb)->data)); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static irqreturn_t pn533_i2c_irq_thread_fn(int irq, void *data) | ||
139 | { | ||
140 | struct pn533_i2c_phy *phy = data; | ||
141 | struct i2c_client *client; | ||
142 | struct sk_buff *skb = NULL; | ||
143 | int r; | ||
144 | |||
145 | if (!phy || irq != phy->i2c_dev->irq) { | ||
146 | WARN_ON_ONCE(1); | ||
147 | return IRQ_NONE; | ||
148 | } | ||
149 | |||
150 | client = phy->i2c_dev; | ||
151 | dev_dbg(&client->dev, "IRQ\n"); | ||
152 | |||
153 | if (phy->hard_fault != 0) | ||
154 | return IRQ_HANDLED; | ||
155 | |||
156 | r = pn533_i2c_read(phy, &skb); | ||
157 | if (r == -EREMOTEIO) { | ||
158 | phy->hard_fault = r; | ||
159 | |||
160 | pn533_recv_frame(phy->priv, NULL, -EREMOTEIO); | ||
161 | |||
162 | return IRQ_HANDLED; | ||
163 | } else if ((r == -ENOMEM) || (r == -EBADMSG) || (r == -EBUSY)) { | ||
164 | return IRQ_HANDLED; | ||
165 | } | ||
166 | |||
167 | pn533_recv_frame(phy->priv, skb, 0); | ||
168 | |||
169 | return IRQ_HANDLED; | ||
170 | } | ||
171 | |||
172 | static struct pn533_phy_ops i2c_phy_ops = { | ||
173 | .send_frame = pn533_i2c_send_frame, | ||
174 | .send_ack = pn533_i2c_send_ack, | ||
175 | .abort_cmd = pn533_i2c_abort_cmd, | ||
176 | }; | ||
177 | |||
178 | |||
179 | static int pn533_i2c_probe(struct i2c_client *client, | ||
180 | const struct i2c_device_id *id) | ||
181 | { | ||
182 | struct pn533_i2c_phy *phy; | ||
183 | struct pn533 *priv; | ||
184 | int r = 0; | ||
185 | |||
186 | dev_dbg(&client->dev, "%s\n", __func__); | ||
187 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | ||
188 | |||
189 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
190 | nfc_err(&client->dev, "Need I2C_FUNC_I2C\n"); | ||
191 | return -ENODEV; | ||
192 | } | ||
193 | |||
194 | phy = devm_kzalloc(&client->dev, sizeof(struct pn533_i2c_phy), | ||
195 | GFP_KERNEL); | ||
196 | if (!phy) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | phy->i2c_dev = client; | ||
200 | i2c_set_clientdata(client, phy); | ||
201 | |||
202 | r = request_threaded_irq(client->irq, NULL, pn533_i2c_irq_thread_fn, | ||
203 | IRQF_TRIGGER_FALLING | | ||
204 | IRQF_SHARED | IRQF_ONESHOT, | ||
205 | PN533_I2C_DRIVER_NAME, phy); | ||
206 | |||
207 | if (r < 0) | ||
208 | nfc_err(&client->dev, "Unable to register IRQ handler\n"); | ||
209 | |||
210 | priv = pn533_register_device(PN533_DEVICE_PN532, | ||
211 | PN533_NO_TYPE_B_PROTOCOLS, | ||
212 | PN533_PROTO_REQ_ACK_RESP, | ||
213 | phy, &i2c_phy_ops, NULL, | ||
214 | &phy->i2c_dev->dev); | ||
215 | |||
216 | if (IS_ERR(priv)) { | ||
217 | r = PTR_ERR(priv); | ||
218 | goto err_register; | ||
219 | } | ||
220 | |||
221 | phy->priv = priv; | ||
222 | |||
223 | return 0; | ||
224 | |||
225 | err_register: | ||
226 | free_irq(client->irq, phy); | ||
227 | |||
228 | return r; | ||
229 | } | ||
230 | |||
231 | static int pn533_i2c_remove(struct i2c_client *client) | ||
232 | { | ||
233 | struct pn533_i2c_phy *phy = i2c_get_clientdata(client); | ||
234 | |||
235 | dev_dbg(&client->dev, "%s\n", __func__); | ||
236 | |||
237 | pn533_unregister_device(phy->priv); | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static const struct of_device_id of_pn533_i2c_match[] = { | ||
243 | { .compatible = "nxp,pn533-i2c", }, | ||
244 | { .compatible = "nxp,pn532-i2c", }, | ||
245 | {}, | ||
246 | }; | ||
247 | MODULE_DEVICE_TABLE(of, of_pn533_i2c_match); | ||
248 | |||
249 | static struct i2c_device_id pn533_i2c_id_table[] = { | ||
250 | { PN533_I2C_DRIVER_NAME, 0 }, | ||
251 | {} | ||
252 | }; | ||
253 | MODULE_DEVICE_TABLE(i2c, pn533_i2c_id_table); | ||
254 | |||
255 | static struct i2c_driver pn533_i2c_driver = { | ||
256 | .driver = { | ||
257 | .name = PN533_I2C_DRIVER_NAME, | ||
258 | .owner = THIS_MODULE, | ||
259 | .of_match_table = of_match_ptr(of_pn533_i2c_match), | ||
260 | }, | ||
261 | .probe = pn533_i2c_probe, | ||
262 | .id_table = pn533_i2c_id_table, | ||
263 | .remove = pn533_i2c_remove, | ||
264 | }; | ||
265 | |||
266 | module_i2c_driver(pn533_i2c_driver); | ||
267 | |||
268 | MODULE_AUTHOR("Michael Thalmeier <michael.thalmeier@hale.at>"); | ||
269 | MODULE_DESCRIPTION("PN533 I2C driver ver " VERSION); | ||
270 | MODULE_VERSION(VERSION); | ||
271 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c index 52d83fec5add..ee9e8f1195fa 100644 --- a/drivers/nfc/pn533/pn533.c +++ b/drivers/nfc/pn533/pn533.c | |||
@@ -2427,8 +2427,37 @@ static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf) | |||
2427 | return rc; | 2427 | return rc; |
2428 | } | 2428 | } |
2429 | 2429 | ||
2430 | static int pn532_sam_configuration(struct nfc_dev *nfc_dev) | ||
2431 | { | ||
2432 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
2433 | struct sk_buff *skb; | ||
2434 | struct sk_buff *resp; | ||
2435 | |||
2436 | skb = pn533_alloc_skb(dev, 1); | ||
2437 | if (!skb) | ||
2438 | return -ENOMEM; | ||
2439 | |||
2440 | *skb_put(skb, 1) = 0x01; | ||
2441 | |||
2442 | resp = pn533_send_cmd_sync(dev, PN533_CMD_SAM_CONFIGURATION, skb); | ||
2443 | if (IS_ERR(resp)) | ||
2444 | return PTR_ERR(resp); | ||
2445 | |||
2446 | dev_kfree_skb(resp); | ||
2447 | return 0; | ||
2448 | } | ||
2449 | |||
2430 | static int pn533_dev_up(struct nfc_dev *nfc_dev) | 2450 | static int pn533_dev_up(struct nfc_dev *nfc_dev) |
2431 | { | 2451 | { |
2452 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | ||
2453 | |||
2454 | if (dev->device_type == PN533_DEVICE_PN532) { | ||
2455 | int rc = pn532_sam_configuration(nfc_dev); | ||
2456 | |||
2457 | if (rc) | ||
2458 | return rc; | ||
2459 | } | ||
2460 | |||
2432 | return pn533_rf_field(nfc_dev, 1); | 2461 | return pn533_rf_field(nfc_dev, 1); |
2433 | } | 2462 | } |
2434 | 2463 | ||
@@ -2461,6 +2490,7 @@ static int pn533_setup(struct pn533 *dev) | |||
2461 | case PN533_DEVICE_STD: | 2490 | case PN533_DEVICE_STD: |
2462 | case PN533_DEVICE_PASORI: | 2491 | case PN533_DEVICE_PASORI: |
2463 | case PN533_DEVICE_ACR122U: | 2492 | case PN533_DEVICE_ACR122U: |
2493 | case PN533_DEVICE_PN532: | ||
2464 | max_retries.mx_rty_atr = 0x2; | 2494 | max_retries.mx_rty_atr = 0x2; |
2465 | max_retries.mx_rty_psl = 0x1; | 2495 | max_retries.mx_rty_psl = 0x1; |
2466 | max_retries.mx_rty_passive_act = | 2496 | max_retries.mx_rty_passive_act = |
@@ -2496,6 +2526,7 @@ static int pn533_setup(struct pn533 *dev) | |||
2496 | 2526 | ||
2497 | switch (dev->device_type) { | 2527 | switch (dev->device_type) { |
2498 | case PN533_DEVICE_STD: | 2528 | case PN533_DEVICE_STD: |
2529 | case PN533_DEVICE_PN532: | ||
2499 | break; | 2530 | break; |
2500 | 2531 | ||
2501 | case PN533_DEVICE_PASORI: | 2532 | case PN533_DEVICE_PASORI: |
diff --git a/drivers/nfc/pn533/pn533.h b/drivers/nfc/pn533/pn533.h index 1d9f19eb2a99..ba604f6d93f9 100644 --- a/drivers/nfc/pn533/pn533.h +++ b/drivers/nfc/pn533/pn533.h | |||
@@ -21,6 +21,7 @@ | |||
21 | #define PN533_DEVICE_STD 0x1 | 21 | #define PN533_DEVICE_STD 0x1 |
22 | #define PN533_DEVICE_PASORI 0x2 | 22 | #define PN533_DEVICE_PASORI 0x2 |
23 | #define PN533_DEVICE_ACR122U 0x3 | 23 | #define PN533_DEVICE_ACR122U 0x3 |
24 | #define PN533_DEVICE_PN532 0x4 | ||
24 | 25 | ||
25 | #define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\ | 26 | #define PN533_ALL_PROTOCOLS (NFC_PROTO_JEWEL_MASK | NFC_PROTO_MIFARE_MASK |\ |
26 | NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\ | 27 | NFC_PROTO_FELICA_MASK | NFC_PROTO_ISO14443_MASK |\ |
@@ -73,6 +74,7 @@ | |||
73 | #define PN533_FRAME_CMD(f) (f->data[1]) | 74 | #define PN533_FRAME_CMD(f) (f->data[1]) |
74 | 75 | ||
75 | #define PN533_CMD_GET_FIRMWARE_VERSION 0x02 | 76 | #define PN533_CMD_GET_FIRMWARE_VERSION 0x02 |
77 | #define PN533_CMD_SAM_CONFIGURATION 0x14 | ||
76 | #define PN533_CMD_RF_CONFIGURATION 0x32 | 78 | #define PN533_CMD_RF_CONFIGURATION 0x32 |
77 | #define PN533_CMD_IN_DATA_EXCHANGE 0x40 | 79 | #define PN533_CMD_IN_DATA_EXCHANGE 0x40 |
78 | #define PN533_CMD_IN_COMM_THRU 0x42 | 80 | #define PN533_CMD_IN_COMM_THRU 0x42 |